Initial implementation of C-source-level &&-idiom recovery
[valgrind.git] / VEX / priv / guest_mips_toIR.c
blob87f53e33472f014a8269d08cc5cad416221d774e
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, see <http://www.gnu.org/licenses/>.
26 The GNU General Public License is contained in the file COPYING.
29 /* Translates MIPS code to IR. */
31 #include "libvex_basictypes.h"
32 #include "libvex_ir.h"
33 #include "libvex.h"
34 #include "libvex_guest_mips32.h"
35 #include "libvex_guest_mips64.h"
37 #include "main_util.h"
38 #include "main_globals.h"
39 #include "guest_generic_bb_to_IR.h"
40 #include "guest_mips_defs.h"
41 #include "mips_defs.h"
43 /*------------------------------------------------------------*/
44 /*--- Globals ---*/
45 /*------------------------------------------------------------*/
47 /* These are set at the start of the translation of a instruction, so
48 that we don't have to pass them around endlessly. CONST means does
49 not change during translation of the instruction. */
51 /* CONST: what is the host's endianness? This has to do with float vs
52 double register accesses on VFP, but it's complex and not properly
53 thought out. */
54 static VexEndness host_endness;
56 /* Pointer to the guest code area. */
57 const UChar *guest_code;
59 /* CONST: The guest address for the instruction currently being
60 translated. */
61 #if defined(VGP_mips32_linux)
62 static Addr32 guest_PC_curr_instr;
63 #else
64 static Addr64 guest_PC_curr_instr;
65 #endif
67 /* MOD: The IRSB* into which we're generating code. */
68 IRSB *irsb;
70 /* Is our guest binary 32 or 64bit? Set at each call to
71 disInstr_MIPS below. */
72 Bool mode64 = False;
74 /* CPU has FPU and 32 dbl. prec. FP registers. */
75 static Bool fp_mode64 = False;
77 /* FPU works in FRE mode */
78 static Bool fp_mode64_fre = False;
80 /* CPU has MSA unit */
81 static Bool has_msa = False;
83 /* Define 1.0 in single and double precision. */
84 #define ONE_SINGLE 0x3F800000
85 #define ONE_DOUBLE 0x3FF0000000000000ULL
87 /*------------------------------------------------------------*/
88 /*--- Helper bits and pieces for deconstructing the ---*/
89 /*--- mips insn stream. ---*/
90 /*------------------------------------------------------------*/
92 /* ---------------- Integer registers ---------------- */
94 static UInt integerGuestRegOffset(UInt iregNo)
96 /* Do we care about endianness here? We do if sub-parts of integer
97 registers are accessed, but I don't think that ever happens on
98 MIPS. */
99 UInt ret;
101 if (!mode64)
102 switch (iregNo) {
103 case 0:
104 ret = offsetof(VexGuestMIPS32State, guest_r0);
105 break;
107 case 1:
108 ret = offsetof(VexGuestMIPS32State, guest_r1);
109 break;
111 case 2:
112 ret = offsetof(VexGuestMIPS32State, guest_r2);
113 break;
115 case 3:
116 ret = offsetof(VexGuestMIPS32State, guest_r3);
117 break;
119 case 4:
120 ret = offsetof(VexGuestMIPS32State, guest_r4);
121 break;
123 case 5:
124 ret = offsetof(VexGuestMIPS32State, guest_r5);
125 break;
127 case 6:
128 ret = offsetof(VexGuestMIPS32State, guest_r6);
129 break;
131 case 7:
132 ret = offsetof(VexGuestMIPS32State, guest_r7);
133 break;
135 case 8:
136 ret = offsetof(VexGuestMIPS32State, guest_r8);
137 break;
139 case 9:
140 ret = offsetof(VexGuestMIPS32State, guest_r9);
141 break;
143 case 10:
144 ret = offsetof(VexGuestMIPS32State, guest_r10);
145 break;
147 case 11:
148 ret = offsetof(VexGuestMIPS32State, guest_r11);
149 break;
151 case 12:
152 ret = offsetof(VexGuestMIPS32State, guest_r12);
153 break;
155 case 13:
156 ret = offsetof(VexGuestMIPS32State, guest_r13);
157 break;
159 case 14:
160 ret = offsetof(VexGuestMIPS32State, guest_r14);
161 break;
163 case 15:
164 ret = offsetof(VexGuestMIPS32State, guest_r15);
165 break;
167 case 16:
168 ret = offsetof(VexGuestMIPS32State, guest_r16);
169 break;
171 case 17:
172 ret = offsetof(VexGuestMIPS32State, guest_r17);
173 break;
175 case 18:
176 ret = offsetof(VexGuestMIPS32State, guest_r18);
177 break;
179 case 19:
180 ret = offsetof(VexGuestMIPS32State, guest_r19);
181 break;
183 case 20:
184 ret = offsetof(VexGuestMIPS32State, guest_r20);
185 break;
187 case 21:
188 ret = offsetof(VexGuestMIPS32State, guest_r21);
189 break;
191 case 22:
192 ret = offsetof(VexGuestMIPS32State, guest_r22);
193 break;
195 case 23:
196 ret = offsetof(VexGuestMIPS32State, guest_r23);
197 break;
199 case 24:
200 ret = offsetof(VexGuestMIPS32State, guest_r24);
201 break;
203 case 25:
204 ret = offsetof(VexGuestMIPS32State, guest_r25);
205 break;
207 case 26:
208 ret = offsetof(VexGuestMIPS32State, guest_r26);
209 break;
211 case 27:
212 ret = offsetof(VexGuestMIPS32State, guest_r27);
213 break;
215 case 28:
216 ret = offsetof(VexGuestMIPS32State, guest_r28);
217 break;
219 case 29:
220 ret = offsetof(VexGuestMIPS32State, guest_r29);
221 break;
223 case 30:
224 ret = offsetof(VexGuestMIPS32State, guest_r30);
225 break;
227 case 31:
228 ret = offsetof(VexGuestMIPS32State, guest_r31);
229 break;
231 default:
232 vassert(0);
233 break;
235 else
236 switch (iregNo) {
237 case 0:
238 ret = offsetof(VexGuestMIPS64State, guest_r0);
239 break;
241 case 1:
242 ret = offsetof(VexGuestMIPS64State, guest_r1);
243 break;
245 case 2:
246 ret = offsetof(VexGuestMIPS64State, guest_r2);
247 break;
249 case 3:
250 ret = offsetof(VexGuestMIPS64State, guest_r3);
251 break;
253 case 4:
254 ret = offsetof(VexGuestMIPS64State, guest_r4);
255 break;
257 case 5:
258 ret = offsetof(VexGuestMIPS64State, guest_r5);
259 break;
261 case 6:
262 ret = offsetof(VexGuestMIPS64State, guest_r6);
263 break;
265 case 7:
266 ret = offsetof(VexGuestMIPS64State, guest_r7);
267 break;
269 case 8:
270 ret = offsetof(VexGuestMIPS64State, guest_r8);
271 break;
273 case 9:
274 ret = offsetof(VexGuestMIPS64State, guest_r9);
275 break;
277 case 10:
278 ret = offsetof(VexGuestMIPS64State, guest_r10);
279 break;
281 case 11:
282 ret = offsetof(VexGuestMIPS64State, guest_r11);
283 break;
285 case 12:
286 ret = offsetof(VexGuestMIPS64State, guest_r12);
287 break;
289 case 13:
290 ret = offsetof(VexGuestMIPS64State, guest_r13);
291 break;
293 case 14:
294 ret = offsetof(VexGuestMIPS64State, guest_r14);
295 break;
297 case 15:
298 ret = offsetof(VexGuestMIPS64State, guest_r15);
299 break;
301 case 16:
302 ret = offsetof(VexGuestMIPS64State, guest_r16);
303 break;
305 case 17:
306 ret = offsetof(VexGuestMIPS64State, guest_r17);
307 break;
309 case 18:
310 ret = offsetof(VexGuestMIPS64State, guest_r18);
311 break;
313 case 19:
314 ret = offsetof(VexGuestMIPS64State, guest_r19);
315 break;
317 case 20:
318 ret = offsetof(VexGuestMIPS64State, guest_r20);
319 break;
321 case 21:
322 ret = offsetof(VexGuestMIPS64State, guest_r21);
323 break;
325 case 22:
326 ret = offsetof(VexGuestMIPS64State, guest_r22);
327 break;
329 case 23:
330 ret = offsetof(VexGuestMIPS64State, guest_r23);
331 break;
333 case 24:
334 ret = offsetof(VexGuestMIPS64State, guest_r24);
335 break;
337 case 25:
338 ret = offsetof(VexGuestMIPS64State, guest_r25);
339 break;
341 case 26:
342 ret = offsetof(VexGuestMIPS64State, guest_r26);
343 break;
345 case 27:
346 ret = offsetof(VexGuestMIPS64State, guest_r27);
347 break;
349 case 28:
350 ret = offsetof(VexGuestMIPS64State, guest_r28);
351 break;
353 case 29:
354 ret = offsetof(VexGuestMIPS64State, guest_r29);
355 break;
357 case 30:
358 ret = offsetof(VexGuestMIPS64State, guest_r30);
359 break;
361 case 31:
362 ret = offsetof(VexGuestMIPS64State, guest_r31);
363 break;
365 default:
366 vassert(0);
367 break;
370 return ret;
373 #if defined(VGP_mips32_linux)
374 #define OFFB_PC offsetof(VexGuestMIPS32State, guest_PC)
375 #else
376 #define OFFB_PC offsetof(VexGuestMIPS64State, guest_PC)
377 #endif
379 /* ---------------- Floating point registers ---------------- */
381 static UInt floatGuestRegOffset(UInt fregNo)
383 vassert(fregNo < 32);
384 UInt ret;
386 if (!mode64)
387 switch (fregNo) {
388 case 0:
389 ret = offsetof(VexGuestMIPS32State, guest_f0);
390 break;
392 case 1:
393 ret = offsetof(VexGuestMIPS32State, guest_f1);
394 break;
396 case 2:
397 ret = offsetof(VexGuestMIPS32State, guest_f2);
398 break;
400 case 3:
401 ret = offsetof(VexGuestMIPS32State, guest_f3);
402 break;
404 case 4:
405 ret = offsetof(VexGuestMIPS32State, guest_f4);
406 break;
408 case 5:
409 ret = offsetof(VexGuestMIPS32State, guest_f5);
410 break;
412 case 6:
413 ret = offsetof(VexGuestMIPS32State, guest_f6);
414 break;
416 case 7:
417 ret = offsetof(VexGuestMIPS32State, guest_f7);
418 break;
420 case 8:
421 ret = offsetof(VexGuestMIPS32State, guest_f8);
422 break;
424 case 9:
425 ret = offsetof(VexGuestMIPS32State, guest_f9);
426 break;
428 case 10:
429 ret = offsetof(VexGuestMIPS32State, guest_f10);
430 break;
432 case 11:
433 ret = offsetof(VexGuestMIPS32State, guest_f11);
434 break;
436 case 12:
437 ret = offsetof(VexGuestMIPS32State, guest_f12);
438 break;
440 case 13:
441 ret = offsetof(VexGuestMIPS32State, guest_f13);
442 break;
444 case 14:
445 ret = offsetof(VexGuestMIPS32State, guest_f14);
446 break;
448 case 15:
449 ret = offsetof(VexGuestMIPS32State, guest_f15);
450 break;
452 case 16:
453 ret = offsetof(VexGuestMIPS32State, guest_f16);
454 break;
456 case 17:
457 ret = offsetof(VexGuestMIPS32State, guest_f17);
458 break;
460 case 18:
461 ret = offsetof(VexGuestMIPS32State, guest_f18);
462 break;
464 case 19:
465 ret = offsetof(VexGuestMIPS32State, guest_f19);
466 break;
468 case 20:
469 ret = offsetof(VexGuestMIPS32State, guest_f20);
470 break;
472 case 21:
473 ret = offsetof(VexGuestMIPS32State, guest_f21);
474 break;
476 case 22:
477 ret = offsetof(VexGuestMIPS32State, guest_f22);
478 break;
480 case 23:
481 ret = offsetof(VexGuestMIPS32State, guest_f23);
482 break;
484 case 24:
485 ret = offsetof(VexGuestMIPS32State, guest_f24);
486 break;
488 case 25:
489 ret = offsetof(VexGuestMIPS32State, guest_f25);
490 break;
492 case 26:
493 ret = offsetof(VexGuestMIPS32State, guest_f26);
494 break;
496 case 27:
497 ret = offsetof(VexGuestMIPS32State, guest_f27);
498 break;
500 case 28:
501 ret = offsetof(VexGuestMIPS32State, guest_f28);
502 break;
504 case 29:
505 ret = offsetof(VexGuestMIPS32State, guest_f29);
506 break;
508 case 30:
509 ret = offsetof(VexGuestMIPS32State, guest_f30);
510 break;
512 case 31:
513 ret = offsetof(VexGuestMIPS32State, guest_f31);
514 break;
516 default:
517 vassert(0);
518 break;
520 else
521 switch (fregNo) {
522 case 0:
523 ret = offsetof(VexGuestMIPS64State, guest_f0);
524 break;
526 case 1:
527 ret = offsetof(VexGuestMIPS64State, guest_f1);
528 break;
530 case 2:
531 ret = offsetof(VexGuestMIPS64State, guest_f2);
532 break;
534 case 3:
535 ret = offsetof(VexGuestMIPS64State, guest_f3);
536 break;
538 case 4:
539 ret = offsetof(VexGuestMIPS64State, guest_f4);
540 break;
542 case 5:
543 ret = offsetof(VexGuestMIPS64State, guest_f5);
544 break;
546 case 6:
547 ret = offsetof(VexGuestMIPS64State, guest_f6);
548 break;
550 case 7:
551 ret = offsetof(VexGuestMIPS64State, guest_f7);
552 break;
554 case 8:
555 ret = offsetof(VexGuestMIPS64State, guest_f8);
556 break;
558 case 9:
559 ret = offsetof(VexGuestMIPS64State, guest_f9);
560 break;
562 case 10:
563 ret = offsetof(VexGuestMIPS64State, guest_f10);
564 break;
566 case 11:
567 ret = offsetof(VexGuestMIPS64State, guest_f11);
568 break;
570 case 12:
571 ret = offsetof(VexGuestMIPS64State, guest_f12);
572 break;
574 case 13:
575 ret = offsetof(VexGuestMIPS64State, guest_f13);
576 break;
578 case 14:
579 ret = offsetof(VexGuestMIPS64State, guest_f14);
580 break;
582 case 15:
583 ret = offsetof(VexGuestMIPS64State, guest_f15);
584 break;
586 case 16:
587 ret = offsetof(VexGuestMIPS64State, guest_f16);
588 break;
590 case 17:
591 ret = offsetof(VexGuestMIPS64State, guest_f17);
592 break;
594 case 18:
595 ret = offsetof(VexGuestMIPS64State, guest_f18);
596 break;
598 case 19:
599 ret = offsetof(VexGuestMIPS64State, guest_f19);
600 break;
602 case 20:
603 ret = offsetof(VexGuestMIPS64State, guest_f20);
604 break;
606 case 21:
607 ret = offsetof(VexGuestMIPS64State, guest_f21);
608 break;
610 case 22:
611 ret = offsetof(VexGuestMIPS64State, guest_f22);
612 break;
614 case 23:
615 ret = offsetof(VexGuestMIPS64State, guest_f23);
616 break;
618 case 24:
619 ret = offsetof(VexGuestMIPS64State, guest_f24);
620 break;
622 case 25:
623 ret = offsetof(VexGuestMIPS64State, guest_f25);
624 break;
626 case 26:
627 ret = offsetof(VexGuestMIPS64State, guest_f26);
628 break;
630 case 27:
631 ret = offsetof(VexGuestMIPS64State, guest_f27);
632 break;
634 case 28:
635 ret = offsetof(VexGuestMIPS64State, guest_f28);
636 break;
638 case 29:
639 ret = offsetof(VexGuestMIPS64State, guest_f29);
640 break;
642 case 30:
643 ret = offsetof(VexGuestMIPS64State, guest_f30);
644 break;
646 case 31:
647 ret = offsetof(VexGuestMIPS64State, guest_f31);
648 break;
650 default:
651 vassert(0);
652 break;
655 return ret;
658 /* ---------------- MIPS32 DSP ASE(r2) accumulators ---------------- */
660 UInt accumulatorGuestRegOffset(UInt acNo)
662 vassert(!mode64);
663 vassert(acNo <= 3);
664 UInt ret;
666 switch (acNo) {
667 case 0:
668 ret = offsetof(VexGuestMIPS32State, guest_ac0);
669 break;
671 case 1:
672 ret = offsetof(VexGuestMIPS32State, guest_ac1);
673 break;
675 case 2:
676 ret = offsetof(VexGuestMIPS32State, guest_ac2);
677 break;
679 case 3:
680 ret = offsetof(VexGuestMIPS32State, guest_ac3);
681 break;
683 default:
684 vassert(0);
685 break;
688 return ret;
691 /* ---------------- MIPS32 MSA registers ---------------- */
693 static UInt msaGuestRegOffset(UInt msaRegNo)
695 vassert(msaRegNo <= 31);
696 UInt ret;
698 if (mode64) {
699 switch (msaRegNo) {
700 case 0:
701 ret = offsetof(VexGuestMIPS64State, guest_w0);
702 break;
704 case 1:
705 ret = offsetof(VexGuestMIPS64State, guest_w1);
706 break;
708 case 2:
709 ret = offsetof(VexGuestMIPS64State, guest_w2);
710 break;
712 case 3:
713 ret = offsetof(VexGuestMIPS64State, guest_w3);
714 break;
716 case 4:
717 ret = offsetof(VexGuestMIPS64State, guest_w4);
718 break;
720 case 5:
721 ret = offsetof(VexGuestMIPS64State, guest_w5);
722 break;
724 case 6:
725 ret = offsetof(VexGuestMIPS64State, guest_w6);
726 break;
728 case 7:
729 ret = offsetof(VexGuestMIPS64State, guest_w7);
730 break;
732 case 8:
733 ret = offsetof(VexGuestMIPS64State, guest_w8);
734 break;
736 case 9:
737 ret = offsetof(VexGuestMIPS64State, guest_w9);
738 break;
740 case 10:
741 ret = offsetof(VexGuestMIPS64State, guest_w10);
742 break;
744 case 11:
745 ret = offsetof(VexGuestMIPS64State, guest_w11);
746 break;
748 case 12:
749 ret = offsetof(VexGuestMIPS64State, guest_w12);
750 break;
752 case 13:
753 ret = offsetof(VexGuestMIPS64State, guest_w13);
754 break;
756 case 14:
757 ret = offsetof(VexGuestMIPS64State, guest_w14);
758 break;
760 case 15:
761 ret = offsetof(VexGuestMIPS64State, guest_w15);
762 break;
764 case 16:
765 ret = offsetof(VexGuestMIPS64State, guest_w16);
766 break;
768 case 17:
769 ret = offsetof(VexGuestMIPS64State, guest_w17);
770 break;
772 case 18:
773 ret = offsetof(VexGuestMIPS64State, guest_w18);
774 break;
776 case 19:
777 ret = offsetof(VexGuestMIPS64State, guest_w19);
778 break;
780 case 20:
781 ret = offsetof(VexGuestMIPS64State, guest_w20);
782 break;
784 case 21:
785 ret = offsetof(VexGuestMIPS64State, guest_w21);
786 break;
788 case 22:
789 ret = offsetof(VexGuestMIPS64State, guest_w22);
790 break;
792 case 23:
793 ret = offsetof(VexGuestMIPS64State, guest_w23);
794 break;
796 case 24:
797 ret = offsetof(VexGuestMIPS64State, guest_w24);
798 break;
800 case 25:
801 ret = offsetof(VexGuestMIPS64State, guest_w25);
802 break;
804 case 26:
805 ret = offsetof(VexGuestMIPS64State, guest_w26);
806 break;
808 case 27:
809 ret = offsetof(VexGuestMIPS64State, guest_w27);
810 break;
812 case 28:
813 ret = offsetof(VexGuestMIPS64State, guest_w28);
814 break;
816 case 29:
817 ret = offsetof(VexGuestMIPS64State, guest_w29);
818 break;
820 case 30:
821 ret = offsetof(VexGuestMIPS64State, guest_w30);
822 break;
824 case 31:
825 ret = offsetof(VexGuestMIPS64State, guest_w31);
826 break;
828 default:
829 vassert(0);
830 break;
832 } else {
833 switch (msaRegNo) {
834 case 0:
835 ret = offsetof(VexGuestMIPS32State, guest_w0);
836 break;
838 case 1:
839 ret = offsetof(VexGuestMIPS32State, guest_w1);
840 break;
842 case 2:
843 ret = offsetof(VexGuestMIPS32State, guest_w2);
844 break;
846 case 3:
847 ret = offsetof(VexGuestMIPS32State, guest_w3);
848 break;
850 case 4:
851 ret = offsetof(VexGuestMIPS32State, guest_w4);
852 break;
854 case 5:
855 ret = offsetof(VexGuestMIPS32State, guest_w5);
856 break;
858 case 6:
859 ret = offsetof(VexGuestMIPS32State, guest_w6);
860 break;
862 case 7:
863 ret = offsetof(VexGuestMIPS32State, guest_w7);
864 break;
866 case 8:
867 ret = offsetof(VexGuestMIPS32State, guest_w8);
868 break;
870 case 9:
871 ret = offsetof(VexGuestMIPS32State, guest_w9);
872 break;
874 case 10:
875 ret = offsetof(VexGuestMIPS32State, guest_w10);
876 break;
878 case 11:
879 ret = offsetof(VexGuestMIPS32State, guest_w11);
880 break;
882 case 12:
883 ret = offsetof(VexGuestMIPS32State, guest_w12);
884 break;
886 case 13:
887 ret = offsetof(VexGuestMIPS32State, guest_w13);
888 break;
890 case 14:
891 ret = offsetof(VexGuestMIPS32State, guest_w14);
892 break;
894 case 15:
895 ret = offsetof(VexGuestMIPS32State, guest_w15);
896 break;
898 case 16:
899 ret = offsetof(VexGuestMIPS32State, guest_w16);
900 break;
902 case 17:
903 ret = offsetof(VexGuestMIPS32State, guest_w17);
904 break;
906 case 18:
907 ret = offsetof(VexGuestMIPS32State, guest_w18);
908 break;
910 case 19:
911 ret = offsetof(VexGuestMIPS32State, guest_w19);
912 break;
914 case 20:
915 ret = offsetof(VexGuestMIPS32State, guest_w20);
916 break;
918 case 21:
919 ret = offsetof(VexGuestMIPS32State, guest_w21);
920 break;
922 case 22:
923 ret = offsetof(VexGuestMIPS32State, guest_w22);
924 break;
926 case 23:
927 ret = offsetof(VexGuestMIPS32State, guest_w23);
928 break;
930 case 24:
931 ret = offsetof(VexGuestMIPS32State, guest_w24);
932 break;
934 case 25:
935 ret = offsetof(VexGuestMIPS32State, guest_w25);
936 break;
938 case 26:
939 ret = offsetof(VexGuestMIPS32State, guest_w26);
940 break;
942 case 27:
943 ret = offsetof(VexGuestMIPS32State, guest_w27);
944 break;
946 case 28:
947 ret = offsetof(VexGuestMIPS32State, guest_w28);
948 break;
950 case 29:
951 ret = offsetof(VexGuestMIPS32State, guest_w29);
952 break;
954 case 30:
955 ret = offsetof(VexGuestMIPS32State, guest_w30);
956 break;
958 case 31:
959 ret = offsetof(VexGuestMIPS32State, guest_w31);
960 break;
962 default:
963 vassert(0);
964 break;
968 return ret;
972 /* Do a endian load of a 32-bit word, regardless of the endianness of the
973 underlying host. */
974 static inline UInt getUInt(const UChar * p)
976 UInt w = 0;
977 #if defined (_MIPSEL)
978 w = (w << 8) | p[3];
979 w = (w << 8) | p[2];
980 w = (w << 8) | p[1];
981 w = (w << 8) | p[0];
982 #elif defined (_MIPSEB)
983 w = (w << 8) | p[0];
984 w = (w << 8) | p[1];
985 w = (w << 8) | p[2];
986 w = (w << 8) | p[3];
987 #endif
988 return w;
991 #define BITS2(_b1,_b0) \
992 (((_b1) << 1) | (_b0))
994 #define BITS3(_b2,_b1,_b0) \
995 (((_b2) << 2) | ((_b1) << 1) | (_b0))
997 #define BITS4(_b3,_b2,_b1,_b0) \
998 (((_b3) << 3) | ((_b2) << 2) | ((_b1) << 1) | (_b0))
1000 #define BITS5(_b4,_b3,_b2,_b1,_b0) \
1001 (((_b4) << 4) | BITS4((_b3),(_b2),(_b1),(_b0)))
1003 #define BITS6(_b5,_b4,_b3,_b2,_b1,_b0) \
1004 ((BITS2((_b5),(_b4)) << 4) \
1005 | BITS4((_b3),(_b2),(_b1),(_b0)))
1007 #define BITS8(_b7,_b6,_b5,_b4,_b3,_b2,_b1,_b0) \
1008 ((BITS4((_b7),(_b6),(_b5),(_b4)) << 4) \
1009 | BITS4((_b3),(_b2),(_b1),(_b0)))
1011 #define LOAD_STORE_PATTERN \
1012 t1 = newTemp(mode64 ? Ity_I64 : Ity_I32); \
1013 if(!mode64) \
1014 assign(t1, binop(Iop_Add32, getIReg(rs), \
1015 mkU32(extend_s_16to32(imm)))); \
1016 else \
1017 assign(t1, binop(Iop_Add64, getIReg(rs), \
1018 mkU64(extend_s_16to64(imm)))); \
1020 #define LOAD_STORE_PATTERN_MSA(imm) \
1021 t1 = newTemp(mode64 ? Ity_I64 : Ity_I32); \
1022 if (!mode64) \
1023 assign(t1, binop(Iop_Add32, getIReg(ws), \
1024 mkU32(extend_s_10to32(imm)))); \
1025 else \
1026 assign(t1, binop(Iop_Add64, getIReg(ws), \
1027 mkU64(extend_s_10to64(imm)))); \
1029 #define LOADX_STORE_PATTERN \
1030 t1 = newTemp(mode64 ? Ity_I64 : Ity_I32); \
1031 if(!mode64) \
1032 assign(t1, binop(Iop_Add32, getIReg(regRs), getIReg(regRt))); \
1033 else \
1034 assign(t1, binop(Iop_Add64, getIReg(regRs), getIReg(regRt)));
1036 #define LWX_SWX_PATTERN64 \
1037 t2 = newTemp(Ity_I64); \
1038 assign(t2, binop(Iop_And64, mkexpr(t1), mkU64(0xFFFFFFFFFFFFFFFCULL))); \
1039 t4 = newTemp(Ity_I32); \
1040 assign(t4, mkNarrowTo32( ty, binop(Iop_And64, \
1041 mkexpr(t1), mkU64(0x3))));
1043 #define LWX_SWX_PATTERN64_1 \
1044 t2 = newTemp(Ity_I64); \
1045 assign(t2, binop(Iop_And64, mkexpr(t1), mkU64(0xFFFFFFFFFFFFFFF8ULL))); \
1046 t4 = newTemp(Ity_I64); \
1047 assign(t4, binop(Iop_And64, mkexpr(t1), mkU64(0x7)));
1049 #define LWX_SWX_PATTERN \
1050 t2 = newTemp(Ity_I32); \
1051 assign(t2, binop(Iop_And32, mkexpr(t1), mkU32(0xFFFFFFFC))); \
1052 t4 = newTemp(Ity_I32); \
1053 assign(t4, binop(Iop_And32, mkexpr(t1), mkU32(0x00000003)))
1055 #define SXXV_PATTERN(op) \
1056 putIReg(rd, binop(op, \
1057 getIReg(rt), \
1058 unop(Iop_32to8, \
1059 binop(Iop_And32, \
1060 getIReg(rs), \
1061 mkU32(0x0000001F) \
1067 #define SXXV_PATTERN64(op) \
1068 putIReg(rd, mkWidenFrom32(ty, binop(op, \
1069 mkNarrowTo32(ty, getIReg(rt)), \
1070 unop(Iop_32to8, \
1071 binop(Iop_And32, \
1072 mkNarrowTo32(ty, getIReg(rs)), \
1073 mkU32(0x0000001F) \
1076 ), True \
1079 #define SXX_PATTERN(op) \
1080 putIReg(rd, binop(op, getIReg(rt), mkU8(sa)));
1082 #define ALU_PATTERN(op) \
1083 putIReg(rd, binop(op, getIReg(rs), getIReg(rt)));
1085 #define ALUI_PATTERN(op) \
1086 putIReg(rt, binop(op, getIReg(rs), mkU32(imm)));
1088 #define ALUI_PATTERN64(op) \
1089 putIReg(rt, binop(op, getIReg(rs), mkU64(imm)));
1091 #define ALU_PATTERN64(op) \
1092 putIReg(rd, mkWidenFrom32(ty, binop(op, \
1093 mkNarrowTo32(ty, getIReg(rs)), \
1094 mkNarrowTo32(ty, getIReg(rt))), True));
1096 #define FP_CONDITIONAL_CODE \
1097 t3 = newTemp(Ity_I32); \
1098 assign(t3, binop(Iop_And32, \
1099 IRExpr_ITE( binop(Iop_CmpEQ32, mkU32(cc), mkU32(0)), \
1100 binop(Iop_Shr32, getFCSR(), mkU8(23)), \
1101 binop(Iop_Shr32, getFCSR(), mkU8(24+cc))), \
1102 mkU32(0x1)));
1106 #define ILLEGAL_INSTRUCTON \
1107 putPC(mkU32(guest_PC_curr_instr + 4)); \
1108 dres->jk_StopHere = Ijk_SigILL; \
1109 dres->whatNext = Dis_StopHere;
1111 #define LLADDR_INVALID \
1112 (mode64 ? mkU64(0xFFFFFFFFFFFFFFFFULL) : mkU32(0xFFFFFFFF))
1114 /*------------------------------------------------------------*/
1115 /*--- Field helpers ---*/
1116 /*------------------------------------------------------------*/
1118 static Bool branch_or_jump(const UChar * addr)
1120 UInt fmt;
1121 UInt cins = getUInt(addr);
1123 UInt opcode = get_opcode(cins);
1124 UInt rt = get_rt(cins);
1125 UInt function = get_function(cins);
1127 /* bgtz, blez, bne, beq, jal */
1128 if (opcode == 0x07 || opcode == 0x06 || opcode == 0x05 || opcode == 0x04
1129 || opcode == 0x03 || opcode == 0x02) {
1130 return True;
1133 /* bgez */
1134 if (opcode == 0x01 && rt == 0x01) {
1135 return True;
1138 /* bgezal */
1139 if (opcode == 0x01 && rt == 0x11) {
1140 return True;
1143 /* bltzal */
1144 if (opcode == 0x01 && rt == 0x10) {
1145 return True;
1148 /* bltz */
1149 if (opcode == 0x01 && rt == 0x00) {
1150 return True;
1153 /* jalr */
1154 if (opcode == 0x00 && function == 0x09) {
1155 return True;
1158 /* jr */
1159 if (opcode == 0x00 && function == 0x08) {
1160 return True;
1163 if (opcode == 0x11) {
1164 /* bc1f & bc1t */
1165 fmt = get_fmt(cins);
1167 if (fmt == 0x08) {
1168 return True;
1171 /* MSA branches */
1172 /* bnz.df, bz.df */
1173 if (fmt >= 0x18) {
1174 return True;
1177 /* bnz.v */
1178 if (fmt == 0x0f) {
1179 return True;
1182 /* bz.v */
1183 if (fmt == 0x0b) {
1184 return True;
1187 /* R6 branches */
1188 /* bc1eqz */
1189 if (fmt == 0x09) {
1190 return True;
1193 /* bc1nez */
1194 if (fmt == 0x0D) {
1195 return True;
1199 /* bposge32 */
1200 if (opcode == 0x01 && rt == 0x1c) {
1201 return True;
1204 /* Cavium Specific instructions. */
1205 if (opcode == 0x32 || opcode == 0x3A || opcode == 0x36 || opcode == 0x3E) {
1206 /* BBIT0, BBIT1, BBIT032, BBIT132 */
1207 return True;
1210 return False;
1213 static Bool is_Branch_or_Jump_and_Link(const UChar * addr)
1215 UInt cins = getUInt(addr);
1217 UInt opcode = get_opcode(cins);
1218 UInt rt = get_rt(cins);
1219 UInt function = get_function(cins);
1221 /* jal */
1222 if (opcode == 0x02) {
1223 return True;
1226 /* bgezal or bal(r6) */
1227 if (opcode == 0x01 && rt == 0x11) {
1228 return True;
1231 /* bltzal */
1232 if (opcode == 0x01 && rt == 0x10) {
1233 return True;
1236 /* jalr */
1237 if (opcode == 0x00 && function == 0x09) {
1238 return True;
1241 return False;
1244 static Bool branch_or_link_likely(const UChar * addr)
1246 UInt cins = getUInt(addr);
1247 UInt opcode = get_opcode(cins);
1248 UInt rt = get_rt(cins);
1250 /* bgtzl, blezl, bnel, beql */
1251 if (opcode == 0x17 || opcode == 0x16 || opcode == 0x15 || opcode == 0x14)
1252 return True;
1254 /* bgezl */
1255 if (opcode == 0x01 && rt == 0x03)
1256 return True;
1258 /* bgezall */
1259 if (opcode == 0x01 && rt == 0x13)
1260 return True;
1262 /* bltzall */
1263 if (opcode == 0x01 && rt == 0x12)
1264 return True;
1266 /* bltzl */
1267 if (opcode == 0x01 && rt == 0x02)
1268 return True;
1270 return False;
1273 /*------------------------------------------------------------*/
1274 /*--- Helper bits and pieces for creating IR fragments. ---*/
1275 /*------------------------------------------------------------*/
1277 /* Generate an expression for SRC rotated right by ROT. */
1278 static IRExpr *genROR32(IRExpr * src, Int rot)
1280 vassert(rot >= 0 && rot < 32);
1282 if (rot == 0)
1283 return src;
1285 return binop(Iop_Or32, binop(Iop_Shl32, src, mkU8(32 - rot)),
1286 binop(Iop_Shr32, src, mkU8(rot)));
1289 static IRExpr *genRORV32(IRExpr * src, IRExpr * rs)
1291 IRTemp t0 = newTemp(Ity_I8);
1292 IRTemp t1 = newTemp(Ity_I8);
1294 assign(t0, unop(Iop_32to8, binop(Iop_And32, rs, mkU32(0x0000001F))));
1295 assign(t1, binop(Iop_Sub8, mkU8(32), mkexpr(t0)));
1296 return binop(Iop_Or32, binop(Iop_Shl32, src, mkexpr(t1)),
1297 binop(Iop_Shr32, src, mkexpr(t0)));
1300 static void jmp_lit32 ( /*MOD*/ DisResult* dres, IRJumpKind kind, Addr32 d32 )
1302 vassert(dres->whatNext == Dis_Continue);
1303 vassert(dres->len == 0);
1304 vassert(dres->jk_StopHere == Ijk_INVALID);
1305 dres->whatNext = Dis_StopHere;
1306 dres->jk_StopHere = kind;
1307 stmt( IRStmt_Put( OFFB_PC, mkU32(d32) ) );
1310 static void jmp_lit64 ( /*MOD*/ DisResult* dres, IRJumpKind kind, Addr64 d64 )
1312 vassert(dres->whatNext == Dis_Continue);
1313 vassert(dres->len == 0);
1314 vassert(dres->jk_StopHere == Ijk_INVALID);
1315 dres->whatNext = Dis_StopHere;
1316 dres->jk_StopHere = kind;
1317 stmt(IRStmt_Put(OFFB_PC, mkU64(d64)));
1320 /* Get value from accumulator (helper function for MIPS32 DSP ASE instructions).
1321 This function should be called before any other operation if widening
1322 multiplications are used. */
1323 IRExpr *getAcc(UInt acNo)
1325 vassert(!mode64);
1326 vassert(acNo <= 3);
1327 return IRExpr_Get(accumulatorGuestRegOffset(acNo), Ity_I64);
1330 /* Get value from DSPControl register (helper function for MIPS32 DSP ASE
1331 instructions). */
1332 IRExpr *getDSPControl(void)
1334 vassert(!mode64);
1335 return IRExpr_Get(offsetof(VexGuestMIPS32State, guest_DSPControl), Ity_I32);
1338 /* Fetch a byte from the guest insn stream. */
1339 static UChar getIByte(Int delta)
1341 return guest_code[delta];
1344 IRExpr *getIReg(UInt iregNo)
1346 if (0 == iregNo) {
1347 return mode64 ? mkU64(0x0) : mkU32(0x0);
1348 } else {
1349 IRType ty = mode64 ? Ity_I64 : Ity_I32;
1350 vassert(iregNo < 32);
1351 return IRExpr_Get(integerGuestRegOffset(iregNo), ty);
1355 static IRExpr *getWReg(UInt wregNo)
1357 vassert(wregNo <= 31);
1358 return IRExpr_Get(msaGuestRegOffset(wregNo), Ity_V128);
1361 static IRExpr *getHI(void)
1363 if (mode64)
1364 return IRExpr_Get(offsetof(VexGuestMIPS64State, guest_HI), Ity_I64);
1365 else
1366 return IRExpr_Get(offsetof(VexGuestMIPS32State, guest_HI), Ity_I32);
1369 static IRExpr *getLO(void)
1371 if (mode64)
1372 return IRExpr_Get(offsetof(VexGuestMIPS64State, guest_LO), Ity_I64);
1373 else
1374 return IRExpr_Get(offsetof(VexGuestMIPS32State, guest_LO), Ity_I32);
1377 static IRExpr *getFCSR(void)
1379 if (mode64)
1380 return IRExpr_Get(offsetof(VexGuestMIPS64State, guest_FCSR), Ity_I32);
1381 else
1382 return IRExpr_Get(offsetof(VexGuestMIPS32State, guest_FCSR), Ity_I32);
1385 static IRExpr *getLLaddr(void)
1387 if (mode64)
1388 return IRExpr_Get(offsetof(VexGuestMIPS64State, guest_LLaddr), Ity_I64);
1389 else
1390 return IRExpr_Get(offsetof(VexGuestMIPS32State, guest_LLaddr), Ity_I32);
1393 static IRExpr *getLLdata(void)
1395 if (mode64)
1396 return IRExpr_Get(offsetof(VexGuestMIPS64State, guest_LLdata), Ity_I64);
1397 else
1398 return IRExpr_Get(offsetof(VexGuestMIPS32State, guest_LLdata), Ity_I32);
1401 static IRExpr *getMSACSR(void)
1403 if (mode64)
1404 return IRExpr_Get(offsetof(VexGuestMIPS64State, guest_MSACSR), Ity_I32);
1405 else
1406 return IRExpr_Get(offsetof(VexGuestMIPS32State, guest_MSACSR), Ity_I32);
1409 /* Get byte from register reg, byte pos from 0 to 3 (or 7 for MIPS64) . */
1410 static IRExpr *getByteFromReg(UInt reg, UInt byte_pos)
1412 UInt pos = byte_pos * 8;
1414 if (mode64)
1415 return unop(Iop_64to8, binop(Iop_And64,
1416 binop(Iop_Shr64, getIReg(reg), mkU8(pos)),
1417 mkU64(0xFF)));
1418 else
1419 return unop(Iop_32to8, binop(Iop_And32,
1420 binop(Iop_Shr32, getIReg(reg), mkU8(pos)),
1421 mkU32(0xFF)));
1424 static void putFCSR(IRExpr * e)
1426 if (mode64)
1427 stmt(IRStmt_Put(offsetof(VexGuestMIPS64State, guest_FCSR), e));
1428 else
1429 stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_FCSR), e));
1432 static void putLLaddr(IRExpr * e)
1434 if (mode64)
1435 stmt(IRStmt_Put(offsetof(VexGuestMIPS64State, guest_LLaddr), e));
1436 else
1437 stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_LLaddr), e));
1440 static void putLLdata(IRExpr * e)
1442 if (mode64)
1443 stmt(IRStmt_Put(offsetof(VexGuestMIPS64State, guest_LLdata), e));
1444 else
1445 stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_LLdata), e));
1448 static void putMSACSR(IRExpr * e)
1450 if (mode64)
1451 stmt(IRStmt_Put(offsetof(VexGuestMIPS64State, guest_MSACSR), e));
1452 else
1453 stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_MSACSR), e));
1456 /* fs - fpu source register number.
1457 inst - fpu instruction that needs to be executed.
1458 sz32 - size of source register.
1459 opN - number of operads:
1460 1 - unary operation.
1461 2 - binary operation. */
1462 static void calculateFCSR(UInt fs, UInt ft, UInt inst, Bool sz32, UInt opN)
1464 IRDirty *d;
1465 IRTemp fcsr = newTemp(Ity_I32);
1467 /* IRExpr_GSPTR() => Need to pass pointer to guest state to helper. */
1468 if (fp_mode64)
1469 d = unsafeIRDirty_1_N(fcsr, 0,
1470 "mips_dirtyhelper_calculate_FCSR_fp64",
1471 &mips_dirtyhelper_calculate_FCSR_fp64,
1472 mkIRExprVec_4(IRExpr_GSPTR(),
1473 mkU32(fs),
1474 mkU32(ft),
1475 mkU32(inst)));
1476 else
1477 d = unsafeIRDirty_1_N(fcsr, 0,
1478 "mips_dirtyhelper_calculate_FCSR_fp32",
1479 &mips_dirtyhelper_calculate_FCSR_fp32,
1480 mkIRExprVec_4(IRExpr_GSPTR(),
1481 mkU32(fs),
1482 mkU32(ft),
1483 mkU32(inst)));
1485 if (opN == 1) { /* Unary operation. */
1486 /* Declare we're reading guest state. */
1487 if (sz32 || fp_mode64)
1488 d->nFxState = 2;
1489 else
1490 d->nFxState = 3;
1492 vex_bzero(&d->fxState, sizeof(d->fxState));
1494 d->fxState[0].fx = Ifx_Read; /* read */
1496 if (mode64)
1497 d->fxState[0].offset = offsetof(VexGuestMIPS64State, guest_FCSR);
1498 else
1499 d->fxState[0].offset = offsetof(VexGuestMIPS32State, guest_FCSR);
1501 d->fxState[0].size = sizeof(UInt);
1502 d->fxState[1].fx = Ifx_Read; /* read */
1503 d->fxState[1].offset = floatGuestRegOffset(fs);
1504 d->fxState[1].size = sizeof(ULong);
1506 if (!(sz32 || fp_mode64)) {
1507 d->fxState[2].fx = Ifx_Read; /* read */
1508 d->fxState[2].offset = floatGuestRegOffset(fs + 1);
1509 d->fxState[2].size = sizeof(ULong);
1511 } else if (opN == 2) { /* Binary operation. */
1512 /* Declare we're reading guest state. */
1513 if (sz32 || fp_mode64)
1514 d->nFxState = 3;
1515 else
1516 d->nFxState = 5;
1518 vex_bzero(&d->fxState, sizeof(d->fxState));
1520 d->fxState[0].fx = Ifx_Read; /* read */
1522 if (mode64)
1523 d->fxState[0].offset = offsetof(VexGuestMIPS64State, guest_FCSR);
1524 else
1525 d->fxState[0].offset = offsetof(VexGuestMIPS32State, guest_FCSR);
1527 d->fxState[0].size = sizeof(UInt);
1528 d->fxState[1].fx = Ifx_Read; /* read */
1529 d->fxState[1].offset = floatGuestRegOffset(fs);
1530 d->fxState[1].size = sizeof(ULong);
1531 d->fxState[2].fx = Ifx_Read; /* read */
1532 d->fxState[2].offset = floatGuestRegOffset(ft);
1533 d->fxState[2].size = sizeof(ULong);
1535 if (!(sz32 || fp_mode64)) {
1536 d->fxState[3].fx = Ifx_Read; /* read */
1537 d->fxState[3].offset = floatGuestRegOffset(fs + 1);
1538 d->fxState[3].size = sizeof(ULong);
1539 d->fxState[4].fx = Ifx_Read; /* read */
1540 d->fxState[4].offset = floatGuestRegOffset(ft + 1);
1541 d->fxState[4].size = sizeof(ULong);
1545 stmt(IRStmt_Dirty(d));
1547 putFCSR(mkexpr(fcsr));
1550 /* ws, wt - source MSA register numbers.
1551 inst - MSA fp instruction that needs to be executed.
1552 opN - number of operads:
1553 1 - unary operation.
1554 2 - binary operation. */
1555 static void calculateMSACSR(UInt ws, UInt wt, UInt inst, UInt opN)
1557 IRDirty *d;
1558 IRTemp msacsr = newTemp(Ity_I32);
1559 /* IRExpr_BBPTR() => Need to pass pointer to guest state to helper. */
1560 d = unsafeIRDirty_1_N(msacsr, 0,
1561 "mips_dirtyhelper_calculate_MSACSR",
1562 &mips_dirtyhelper_calculate_MSACSR,
1563 mkIRExprVec_4(IRExpr_GSPTR(),
1564 mkU32(ws),
1565 mkU32(wt),
1566 mkU32(inst)));
1568 if (opN == 1) { /* Unary operation. */
1569 /* Declare we're reading guest state. */
1570 d->nFxState = 2;
1571 vex_bzero(&d->fxState, sizeof(d->fxState));
1572 d->fxState[0].fx = Ifx_Read; /* read */
1574 if (mode64)
1575 d->fxState[0].offset = offsetof(VexGuestMIPS64State, guest_MSACSR);
1576 else
1577 d->fxState[0].offset = offsetof(VexGuestMIPS32State, guest_MSACSR);
1579 d->fxState[0].size = sizeof(UInt);
1580 d->fxState[1].fx = Ifx_Read; /* read */
1581 d->fxState[1].offset = msaGuestRegOffset(ws);
1582 d->fxState[1].size = sizeof(ULong);
1583 } else if (opN == 2) { /* Binary operation. */
1584 /* Declare we're reading guest state. */
1585 d->nFxState = 3;
1586 vex_bzero(&d->fxState, sizeof(d->fxState));
1587 d->fxState[0].fx = Ifx_Read; /* read */
1589 if (mode64)
1590 d->fxState[0].offset = offsetof(VexGuestMIPS64State, guest_MSACSR);
1591 else
1592 d->fxState[0].offset = offsetof(VexGuestMIPS32State, guest_MSACSR);
1594 d->fxState[0].size = sizeof(UInt);
1595 d->fxState[1].fx = Ifx_Read; /* read */
1596 d->fxState[1].offset = msaGuestRegOffset(ws);
1597 d->fxState[1].size = sizeof(ULong);
1598 d->fxState[2].fx = Ifx_Read; /* read */
1599 d->fxState[2].offset = msaGuestRegOffset(wt);
1600 d->fxState[2].size = sizeof(ULong);
1603 stmt(IRStmt_Dirty(d));
1604 putMSACSR(mkexpr(msacsr));
1607 static IRExpr *getULR(void)
1609 if (mode64)
1610 return IRExpr_Get(offsetof(VexGuestMIPS64State, guest_ULR), Ity_I64);
1611 else
1612 return IRExpr_Get(offsetof(VexGuestMIPS32State, guest_ULR), Ity_I32);
1615 void putIReg(UInt archreg, IRExpr * e)
1617 IRType ty = mode64 ? Ity_I64 : Ity_I32;
1618 vassert(archreg < 32);
1619 vassert(typeOfIRExpr(irsb->tyenv, e) == ty);
1621 if (archreg != 0)
1622 stmt(IRStmt_Put(integerGuestRegOffset(archreg), e));
1625 static void putWReg(UInt wregNo, IRExpr * e)
1627 vassert(wregNo <= 31);
1628 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_V128);
1629 stmt(IRStmt_Put(msaGuestRegOffset(wregNo), e));
1630 stmt(IRStmt_Put(floatGuestRegOffset(wregNo),
1631 unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, e))));
1634 IRExpr *mkNarrowTo32(IRType ty, IRExpr * src)
1636 vassert(ty == Ity_I32 || ty == Ity_I64);
1637 return ty == Ity_I64 ? unop(Iop_64to32, src) : src;
1640 void putLO(IRExpr * e)
1642 if (mode64) {
1643 stmt(IRStmt_Put(offsetof(VexGuestMIPS64State, guest_LO), e));
1644 } else {
1645 stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_LO), e));
1646 /* Add value to lower 32 bits of ac0 to maintain compatibility between
1647 regular MIPS32 instruction set and MIPS DSP ASE. Keep higher 32bits
1648 unchanged. */
1649 IRTemp t_lo = newTemp(Ity_I32);
1650 IRTemp t_hi = newTemp(Ity_I32);
1651 assign(t_lo, e);
1652 assign(t_hi, unop(Iop_64HIto32, getAcc(0)));
1653 stmt(IRStmt_Put(accumulatorGuestRegOffset(0),
1654 binop(Iop_32HLto64, mkexpr(t_hi), mkexpr(t_lo))));
1658 void putHI(IRExpr * e)
1660 if (mode64) {
1661 stmt(IRStmt_Put(offsetof(VexGuestMIPS64State, guest_HI), e));
1662 } else {
1663 stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_HI), e));
1664 /* Add value to higher 32 bits of ac0 to maintain compatibility between
1665 regular MIPS32 instruction set and MIPS DSP ASE. Keep lower 32bits
1666 unchanged. */
1667 IRTemp t_lo = newTemp(Ity_I32);
1668 IRTemp t_hi = newTemp(Ity_I32);
1669 assign(t_hi, e);
1670 assign(t_lo, unop(Iop_64to32, getAcc(0)));
1671 stmt(IRStmt_Put(accumulatorGuestRegOffset(0),
1672 binop(Iop_32HLto64, mkexpr(t_hi), mkexpr(t_lo))));
1676 static IRExpr *mkNarrowTo8 ( IRType ty, IRExpr * src )
1678 vassert(ty == Ity_I32 || ty == Ity_I64);
1679 return ty == Ity_I64 ? unop(Iop_64to8, src) : unop(Iop_32to8, src);
1682 static IRExpr *mkNarrowTo16 ( IRType ty, IRExpr * src )
1684 vassert(ty == Ity_I32 || ty == Ity_I64);
1685 return ty == Ity_I64 ? unop(Iop_64to16, src) : unop(Iop_32to16, src);
1688 static void putPC(IRExpr * e)
1690 stmt(IRStmt_Put(OFFB_PC, e));
1693 static IRExpr *mkWidenFrom32(IRType ty, IRExpr * src, Bool sined)
1695 vassert(ty == Ity_I32 || ty == Ity_I64);
1697 if (ty == Ity_I32)
1698 return src;
1700 return (sined) ? unop(Iop_32Sto64, src) : unop(Iop_32Uto64, src);
1703 /* Narrow 8/16/32 bit int expr to 8/16/32. Clearly only some
1704 of these combinations make sense. */
1705 static IRExpr *narrowTo(IRType dst_ty, IRExpr * e)
1707 IRType src_ty = typeOfIRExpr(irsb->tyenv, e);
1709 if (src_ty == dst_ty)
1710 return e;
1712 if (src_ty == Ity_I32 && dst_ty == Ity_I16)
1713 return unop(Iop_32to16, e);
1715 if (src_ty == Ity_I32 && dst_ty == Ity_I8)
1716 return unop(Iop_32to8, e);
1718 if (src_ty == Ity_I64 && dst_ty == Ity_I8) {
1719 vassert(mode64);
1720 return unop(Iop_64to8, e);
1723 if (src_ty == Ity_I64 && dst_ty == Ity_I16) {
1724 vassert(mode64);
1725 return unop(Iop_64to16, e);
1728 vpanic("narrowTo(mips)");
1729 return 0;
1732 static IRExpr *getLoFromF64(IRType ty, IRExpr * src)
1734 vassert(ty == Ity_F32 || ty == Ity_F64);
1736 if (ty == Ity_F64) {
1737 IRTemp t0, t1;
1738 t0 = newTemp(Ity_I64);
1739 t1 = newTemp(Ity_I32);
1740 assign(t0, unop(Iop_ReinterpF64asI64, src));
1741 assign(t1, unop(Iop_64to32, mkexpr(t0)));
1742 return unop(Iop_ReinterpI32asF32, mkexpr(t1));
1743 } else
1744 return src;
1747 static inline IRExpr *getHiFromF64(IRExpr * src)
1749 vassert(typeOfIRExpr(irsb->tyenv, src) == Ity_F64);
1750 return unop(Iop_ReinterpI32asF32, unop(Iop_64HIto32,
1751 unop(Iop_ReinterpF64asI64, src)));
1754 static IRExpr *mkWidenFromF32(IRType ty, IRExpr * src)
1756 vassert(ty == Ity_F32 || ty == Ity_F64);
1758 if (ty == Ity_F64) {
1759 IRTemp t0 = newTemp(Ity_I32);
1760 IRTemp t1 = newTemp(Ity_I64);
1761 assign(t0, unop(Iop_ReinterpF32asI32, src));
1762 assign(t1, binop(Iop_32HLto64, mkU32(0x0), mkexpr(t0)));
1763 return unop(Iop_ReinterpI64asF64, mkexpr(t1));
1764 } else
1765 return src;
1768 /* Convenience function to move to next instruction on condition. */
1769 static void mips_next_insn_if(IRExpr *condition)
1771 vassert(typeOfIRExpr(irsb->tyenv, condition) == Ity_I1);
1773 stmt(IRStmt_Exit(condition, Ijk_Boring,
1774 mode64 ? IRConst_U64(guest_PC_curr_instr + 4) :
1775 IRConst_U32(guest_PC_curr_instr + 4),
1776 OFFB_PC));
1779 static IRExpr *dis_branch_likely(IRExpr * guard, UInt imm)
1781 ULong branch_offset;
1782 IRTemp t0;
1784 /* PC = PC + (SignExtend(signed_immed_24) << 2)
1785 An 18-bit signed offset (the 16-bit offset field shifted left 2 bits)
1786 is added to the address of the instruction following
1787 the branch (not the branch itself), in the branch delay slot, to form
1788 a PC-relative effective target address. */
1789 if (mode64)
1790 branch_offset = extend_s_18to64(imm << 2);
1791 else
1792 branch_offset = extend_s_18to32(imm << 2);
1794 t0 = newTemp(Ity_I1);
1795 assign(t0, guard);
1797 if (mode64)
1798 stmt(IRStmt_Exit(mkexpr(t0), Ijk_Boring,
1799 IRConst_U64(guest_PC_curr_instr + 8), OFFB_PC));
1800 else
1801 stmt(IRStmt_Exit(mkexpr(t0), Ijk_Boring,
1802 IRConst_U32(guest_PC_curr_instr + 8), OFFB_PC));
1804 irsb->jumpkind = Ijk_Boring;
1806 if (mode64)
1807 return mkU64(guest_PC_curr_instr + 4 + branch_offset);
1808 else
1809 return mkU32(guest_PC_curr_instr + 4 + branch_offset);
1812 static void dis_branch(Bool link, IRExpr * guard, UInt imm, IRStmt ** set)
1814 ULong branch_offset;
1815 IRTemp t0;
1817 if (link) { /* LR (GPR31) = addr of the 2nd instr after branch instr */
1818 if (mode64)
1819 putIReg(31, mkU64(guest_PC_curr_instr + 8));
1820 else
1821 putIReg(31, mkU32(guest_PC_curr_instr + 8));
1824 /* PC = PC + (SignExtend(signed_immed_24) << 2)
1825 An 18-bit signed offset (the 16-bit offset field shifted left 2 bits)
1826 is added to the address of the instruction following
1827 the branch (not the branch itself), in the branch delay slot, to form
1828 a PC-relative effective target address. */
1830 if (mode64)
1831 branch_offset = extend_s_18to64(imm << 2);
1832 else
1833 branch_offset = extend_s_18to32(imm << 2);
1835 t0 = newTemp(Ity_I1);
1836 assign(t0, guard);
1838 if (mode64)
1839 *set = IRStmt_Exit(mkexpr(t0), link ? Ijk_Call : Ijk_Boring,
1840 IRConst_U64(guest_PC_curr_instr + 4 + branch_offset),
1841 OFFB_PC);
1842 else
1843 *set = IRStmt_Exit(mkexpr(t0), link ? Ijk_Call : Ijk_Boring,
1844 IRConst_U32(guest_PC_curr_instr + 4 +
1845 (UInt) branch_offset), OFFB_PC);
1848 static void dis_branch_compact(Bool link, IRExpr * guard, UInt imm,
1849 DisResult *dres)
1851 ULong branch_offset;
1852 IRTemp t0;
1854 if (link) { /* LR (GPR31) = addr of the instr after branch instr */
1855 if (mode64)
1856 putIReg(31, mkU64(guest_PC_curr_instr + 4));
1857 else
1858 putIReg(31, mkU32(guest_PC_curr_instr + 4));
1860 dres->jk_StopHere = Ijk_Call;
1861 } else {
1862 dres->jk_StopHere = Ijk_Boring;
1865 dres->whatNext = Dis_StopHere;
1867 /* PC = PC + (SignExtend(signed_immed_24) << 2)
1868 An 18-bit signed offset (the 16-bit offset field shifted left 2 bits)
1869 is added to the address of the instruction following
1870 the branch (not the branch itself), in the branch delay slot, to form
1871 a PC-relative effective target address. */
1873 if (mode64)
1874 branch_offset = extend_s_18to64(imm << 2);
1875 else
1876 branch_offset = extend_s_18to32(imm << 2);
1878 t0 = newTemp(Ity_I1);
1879 assign(t0, guard);
1881 if (mode64) {
1882 stmt(IRStmt_Exit(mkexpr(t0), link ? Ijk_Call : Ijk_Boring,
1883 IRConst_U64(guest_PC_curr_instr + 4 + branch_offset),
1884 OFFB_PC));
1885 putPC(mkU64(guest_PC_curr_instr + 4));
1886 } else {
1887 stmt(IRStmt_Exit(mkexpr(t0), link ? Ijk_Call : Ijk_Boring,
1888 IRConst_U32(guest_PC_curr_instr + 4 +
1889 (UInt) branch_offset), OFFB_PC));
1890 putPC(mkU32(guest_PC_curr_instr + 4));
1894 static IRExpr *getFReg(UInt fregNo)
1896 vassert(fregNo < 32);
1897 IRType ty = fp_mode64 ? Ity_F64 : Ity_F32;
1898 return IRExpr_Get(floatGuestRegOffset(fregNo), ty);
1901 static IRExpr *getDReg(UInt dregNo)
1903 vassert(dregNo < 32);
1905 if (fp_mode64) {
1906 return IRExpr_Get(floatGuestRegOffset(dregNo), Ity_F64);
1907 } else {
1908 /* Read a floating point register pair and combine their contents into a
1909 64-bit value */
1910 IRTemp t0 = newTemp(Ity_F32);
1911 IRTemp t1 = newTemp(Ity_F32);
1912 IRTemp t2 = newTemp(Ity_F64);
1913 IRTemp t3 = newTemp(Ity_I32);
1914 IRTemp t4 = newTemp(Ity_I32);
1915 IRTemp t5 = newTemp(Ity_I64);
1917 assign(t0, getFReg(dregNo & (~1)));
1918 assign(t1, getFReg(dregNo | 1));
1920 assign(t3, unop(Iop_ReinterpF32asI32, mkexpr(t0)));
1921 assign(t4, unop(Iop_ReinterpF32asI32, mkexpr(t1)));
1922 assign(t5, binop(Iop_32HLto64, mkexpr(t4), mkexpr(t3)));
1923 assign(t2, unop(Iop_ReinterpI64asF64, mkexpr(t5)));
1925 return mkexpr(t2);
1929 static void putFReg(UInt dregNo, IRExpr * e)
1931 vassert(dregNo < 32);
1932 IRType ty = fp_mode64 ? Ity_F64 : Ity_F32;
1933 vassert(typeOfIRExpr(irsb->tyenv, e) == ty);
1935 if (fp_mode64_fre) {
1936 IRTemp t0 = newTemp(Ity_F32);
1937 assign(t0, getLoFromF64(ty, e));
1938 #if defined (_MIPSEL)
1939 stmt(IRStmt_Put(floatGuestRegOffset(dregNo), mkexpr(t0)));
1941 if (dregNo & 1)
1942 stmt(IRStmt_Put(floatGuestRegOffset(dregNo) - 4, mkexpr(t0)));
1944 #else
1945 stmt(IRStmt_Put(floatGuestRegOffset(dregNo) + 4, mkexpr(t0)));
1947 if (dregNo & 1)
1948 stmt(IRStmt_Put(floatGuestRegOffset(dregNo & (~1)), mkexpr(t0)));
1950 #endif
1951 } else {
1952 stmt(IRStmt_Put(floatGuestRegOffset(dregNo), e));
1955 if (has_msa && fp_mode64) {
1956 stmt(IRStmt_Put(msaGuestRegOffset(dregNo),
1957 binop(Iop_64HLtoV128,
1958 unop(Iop_ReinterpF64asI64, e),
1959 unop(Iop_ReinterpF64asI64, e))));
1963 static void putDReg(UInt dregNo, IRExpr * e)
1965 if (fp_mode64) {
1966 vassert(dregNo < 32);
1967 IRType ty = Ity_F64;
1968 vassert(typeOfIRExpr(irsb->tyenv, e) == ty);
1969 stmt(IRStmt_Put(floatGuestRegOffset(dregNo), e));
1971 if (fp_mode64_fre) {
1972 IRTemp t0 = newTemp(Ity_F32);
1974 if (dregNo & 1) {
1975 assign(t0, getLoFromF64(ty, e));
1976 #if defined (_MIPSEL)
1977 stmt(IRStmt_Put(floatGuestRegOffset(dregNo) - 4, mkexpr(t0)));
1978 #else
1979 stmt(IRStmt_Put(floatGuestRegOffset(dregNo & (~1)), mkexpr(t0)));
1980 #endif
1981 } else {
1982 assign(t0, getHiFromF64(e));
1983 #if defined (_MIPSEL)
1984 stmt(IRStmt_Put(floatGuestRegOffset(dregNo | 1), mkexpr(t0)));
1985 #else
1986 stmt(IRStmt_Put(floatGuestRegOffset(dregNo | 1) + 4, mkexpr(t0)));
1987 #endif
1991 if (has_msa)
1992 stmt(IRStmt_Put(msaGuestRegOffset(dregNo),
1993 binop(Iop_64HLtoV128,
1994 unop(Iop_ReinterpF64asI64, e),
1995 unop(Iop_ReinterpF64asI64, e))));
1996 } else {
1997 vassert(dregNo < 32);
1998 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_F64);
1999 IRTemp t1 = newTemp(Ity_F64);
2000 IRTemp t4 = newTemp(Ity_I32);
2001 IRTemp t5 = newTemp(Ity_I32);
2002 IRTemp t6 = newTemp(Ity_I64);
2003 assign(t1, e);
2004 assign(t6, unop(Iop_ReinterpF64asI64, mkexpr(t1)));
2005 assign(t4, unop(Iop_64HIto32, mkexpr(t6))); /* hi */
2006 assign(t5, unop(Iop_64to32, mkexpr(t6))); /* lo */
2007 putFReg(dregNo & (~1), unop(Iop_ReinterpI32asF32, mkexpr(t5)));
2008 putFReg(dregNo | 1, unop(Iop_ReinterpI32asF32, mkexpr(t4)));
2012 static void setFPUCondCode(IRExpr * e, UInt cc)
2014 if (cc == 0) {
2015 putFCSR(binop(Iop_And32, getFCSR(), mkU32(0xFF7FFFFF)));
2016 putFCSR(binop(Iop_Or32, getFCSR(), binop(Iop_Shl32, e, mkU8(23))));
2017 } else {
2018 putFCSR(binop(Iop_And32, getFCSR(), unop(Iop_Not32,
2019 binop(Iop_Shl32, mkU32(0x01000000), mkU8(cc)))));
2020 putFCSR(binop(Iop_Or32, getFCSR(), binop(Iop_Shl32, e, mkU8(24 + cc))));
2024 static IRExpr* get_IR_roundingmode ( void )
2027 rounding mode | MIPS | IR
2028 ------------------------
2029 to nearest | 00 | 00
2030 to zero | 01 | 11
2031 to +infinity | 10 | 10
2032 to -infinity | 11 | 01
2034 IRTemp rm_MIPS = newTemp(Ity_I32);
2035 /* Last two bits in FCSR are rounding mode. */
2037 if (mode64)
2038 assign(rm_MIPS, binop(Iop_And32, IRExpr_Get(offsetof(VexGuestMIPS64State,
2039 guest_FCSR), Ity_I32), mkU32(3)));
2040 else
2041 assign(rm_MIPS, binop(Iop_And32, IRExpr_Get(offsetof(VexGuestMIPS32State,
2042 guest_FCSR), Ity_I32), mkU32(3)));
2044 /* rm_IR = XOR( rm_MIPS32, (rm_MIPS32 << 1) & 2) */
2046 return binop(Iop_Xor32, mkexpr(rm_MIPS), binop(Iop_And32,
2047 binop(Iop_Shl32, mkexpr(rm_MIPS), mkU8(1)), mkU32(2)));
2050 static IRExpr* get_IR_roundingmode_MSA ( void )
2053 rounding mode | MIPS | IR
2054 ------------------------
2055 to nearest | 00 | 00
2056 to zero | 01 | 11
2057 to +infinity | 10 | 10
2058 to -infinity | 11 | 01
2060 IRTemp rm_MIPS = newTemp(Ity_I32);
2061 /* Last two bits in MSACSR are rounding mode. */
2063 if (mode64)
2064 assign(rm_MIPS, binop(Iop_And32, IRExpr_Get(offsetof(VexGuestMIPS64State,
2065 guest_MSACSR), Ity_I32), mkU32(3)));
2066 else
2067 assign(rm_MIPS, binop(Iop_And32, IRExpr_Get(offsetof(VexGuestMIPS32State,
2068 guest_MSACSR), Ity_I32), mkU32(3)));
2070 /* rm_IR = XOR( rm_MIPS32, (rm_MIPS32 << 1) & 2) */
2071 return binop(Iop_Xor32, mkexpr(rm_MIPS), binop(Iop_And32,
2072 binop(Iop_Shl32, mkexpr(rm_MIPS), mkU8(1)), mkU32(2)));
2075 /* sz, ULong -> IRExpr */
2076 static IRExpr *mkSzImm ( IRType ty, ULong imm64 )
2078 vassert(ty == Ity_I32 || ty == Ity_I64);
2079 return ty == Ity_I64 ? mkU64(imm64) : mkU32((UInt) imm64);
2082 static IRConst *mkSzConst ( IRType ty, ULong imm64 )
2084 vassert(ty == Ity_I32 || ty == Ity_I64);
2085 return (ty == Ity_I64 ? IRConst_U64(imm64) : IRConst_U32((UInt) imm64));
2088 /* Make sure we get valid 32 and 64bit addresses */
2089 static Addr64 mkSzAddr ( IRType ty, Addr64 addr )
2091 vassert(ty == Ity_I32 || ty == Ity_I64);
2092 return (ty == Ity_I64 ? (Addr64) addr :
2093 (Addr64) extend_s_32to64(toUInt(addr)));
2096 /* Shift and Rotate instructions for MIPS64 */
2097 static Bool dis_instr_shrt ( UInt theInstr )
2099 UInt opc2 = get_function(theInstr);
2100 UChar regRs = get_rs(theInstr);
2101 UChar regRt = get_rt(theInstr);
2102 UChar regRd = get_rd(theInstr);
2103 UChar uImmsa = get_sa(theInstr);
2104 Long sImmsa = extend_s_16to64(uImmsa);
2105 IRType ty = mode64 ? Ity_I64 : Ity_I32;
2106 IRTemp tmp = newTemp(ty);
2107 IRTemp tmpOr = newTemp(ty);
2108 IRTemp tmpRt = newTemp(ty);
2109 IRTemp tmpRs = newTemp(ty);
2110 IRTemp tmpRd = newTemp(ty);
2112 assign(tmpRs, getIReg(regRs));
2113 assign(tmpRt, getIReg(regRt));
2115 switch (opc2) {
2116 case 0x3A:
2117 if ((regRs & 0x01) == 0) {
2118 /* Doubleword Shift Right Logical - DSRL; MIPS64 */
2119 DIP("dsrl r%u, r%u, %lld", regRd, regRt, sImmsa);
2120 assign(tmpRd, binop(Iop_Shr64, mkexpr(tmpRt), mkU8(uImmsa)));
2121 putIReg(regRd, mkexpr(tmpRd));
2122 } else if ((regRs & 0x01) == 1) {
2123 /* Doubleword Rotate Right - DROTR; MIPS64r2 */
2124 vassert(mode64);
2125 DIP("drotr r%u, r%u, %lld", regRd, regRt, sImmsa);
2126 IRTemp tmpL = newTemp(ty);
2127 IRTemp tmpR = newTemp(ty);
2128 assign(tmpR, binop(Iop_Shr64, mkexpr(tmpRt), mkU8(uImmsa)));
2129 assign(tmp, binop(Iop_Shl64, mkexpr(tmpRt), mkU8(63 - uImmsa)));
2130 assign(tmpL, binop(Iop_Shl64, mkexpr(tmp), mkU8(1)));
2131 assign(tmpRd, binop(Iop_Or64, mkexpr(tmpL), mkexpr(tmpR)));
2132 putIReg(regRd, mkexpr(tmpRd));
2133 } else
2134 return False;
2136 break;
2138 case 0x3E:
2139 if ((regRs & 0x01) == 0) {
2140 /* Doubleword Shift Right Logical Plus 32 - DSRL32; MIPS64 */
2141 DIP("dsrl32 r%u, r%u, %lld", regRd, regRt, sImmsa + 32);
2142 assign(tmpRd, binop(Iop_Shr64, mkexpr(tmpRt), mkU8(uImmsa + 32)));
2143 putIReg(regRd, mkexpr(tmpRd));
2144 } else if ((regRs & 0x01) == 1) {
2145 /* Doubleword Rotate Right Plus 32 - DROTR32; MIPS64r2 */
2146 DIP("drotr32 r%u, r%u, %lld", regRd, regRt, sImmsa);
2147 vassert(mode64);
2148 IRTemp tmpL = newTemp(ty);
2149 IRTemp tmpR = newTemp(ty);
2150 /* (tmpRt >> sa) | (tmpRt << (64 - sa)) */
2151 assign(tmpR, binop(Iop_Shr64, mkexpr(tmpRt), mkU8(uImmsa + 32)));
2152 assign(tmp, binop(Iop_Shl64, mkexpr(tmpRt),
2153 mkU8(63 - (uImmsa + 32))));
2154 assign(tmpL, binop(Iop_Shl64, mkexpr(tmp), mkU8(1)));
2155 assign(tmpRd, binop(Iop_Or64, mkexpr(tmpL), mkexpr(tmpR)));
2156 putIReg(regRd, mkexpr(tmpRd));
2157 } else
2158 return False;
2160 break;
2162 case 0x16:
2163 if ((uImmsa & 0x01) == 0) {
2164 /* Doubleword Shift Right Logical Variable - DSRLV; MIPS64 */
2165 DIP("dsrlv r%u, r%u, r%u", regRd, regRt, regRs);
2166 IRTemp tmpRs8 = newTemp(Ity_I8);
2167 /* s = tmpRs[5..0] */
2168 assign(tmp, binop(Iop_And64, mkexpr(tmpRs), mkU64(63)));
2169 assign(tmpRs8, mkNarrowTo8(ty, mkexpr(tmp)));
2170 assign(tmpRd, binop(Iop_Shr64, mkexpr(tmpRt), mkexpr(tmpRs8)));
2171 putIReg(regRd, mkexpr(tmpRd));
2172 } else if ((uImmsa & 0x01) == 1) {
2173 /* Doubleword Rotate Right Variable - DROTRV; MIPS64r2 */
2174 DIP("drotrv r%u, r%u, r%u", regRd, regRt, regRs);
2175 IRTemp tmpL = newTemp(ty);
2176 IRTemp tmpR = newTemp(ty);
2177 IRTemp tmpRs8 = newTemp(Ity_I8);
2178 IRTemp tmpLs8 = newTemp(Ity_I8);
2179 IRTemp tmp64 = newTemp(ty);
2180 /* s = tmpRs[5...0]
2181 m = 64 - s
2182 (tmpRt << s) | (tmpRt >> m) */
2184 assign(tmp64, binop(Iop_And64, mkexpr(tmpRs), mkSzImm(ty, 63)));
2185 assign(tmp, binop(Iop_Sub64, mkU64(63), mkexpr(tmp64)));
2187 assign(tmpLs8, mkNarrowTo8(ty, mkexpr(tmp)));
2188 assign(tmpRs8, mkNarrowTo8(ty, mkexpr(tmp64)));
2190 assign(tmpR, binop(Iop_Shr64, mkexpr(tmpRt), mkexpr(tmpRs8)));
2191 assign(tmpL, binop(Iop_Shl64, mkexpr(tmpRt), mkexpr(tmpLs8)));
2192 assign(tmpRd, binop(Iop_Shl64, mkexpr(tmpL), mkU8(1)));
2193 assign(tmpOr, binop(Iop_Or64, mkexpr(tmpRd), mkexpr(tmpR)));
2195 putIReg(regRd, mkexpr(tmpOr));
2196 } else
2197 return False;
2199 break;
2201 case 0x38: /* Doubleword Shift Left Logical - DSLL; MIPS64 */
2202 DIP("dsll r%u, r%u, %lld", regRd, regRt, sImmsa);
2203 vassert(mode64);
2204 assign(tmpRd, binop(Iop_Shl64, mkexpr(tmpRt), mkU8(uImmsa)));
2205 putIReg(regRd, mkexpr(tmpRd));
2206 break;
2208 case 0x3C: /* Doubleword Shift Left Logical Plus 32 - DSLL32; MIPS64 */
2209 DIP("dsll32 r%u, r%u, %lld", regRd, regRt, sImmsa);
2210 assign(tmpRd, binop(Iop_Shl64, mkexpr(tmpRt), mkU8(uImmsa + 32)));
2211 putIReg(regRd, mkexpr(tmpRd));
2212 break;
2214 case 0x14: { /* Doubleword Shift Left Logical Variable - DSLLV; MIPS64 */
2215 DIP("dsllv r%u, r%u, r%u", regRd, regRt, regRs);
2216 IRTemp tmpRs8 = newTemp(Ity_I8);
2218 assign(tmp, binop(Iop_And64, mkexpr(tmpRs), mkSzImm(ty, 63)));
2219 assign(tmpRs8, mkNarrowTo8(ty, mkexpr(tmp)));
2220 assign(tmpRd, binop(Iop_Shl64, mkexpr(tmpRt), mkexpr(tmpRs8)));
2221 putIReg(regRd, mkexpr(tmpRd));
2222 break;
2225 case 0x3B: /* Doubleword Shift Right Arithmetic - DSRA; MIPS64 */
2226 DIP("dsra r%u, r%u, %lld", regRd, regRt, sImmsa);
2227 assign(tmpRd, binop(Iop_Sar64, mkexpr(tmpRt), mkU8(uImmsa)));
2228 putIReg(regRd, mkexpr(tmpRd));
2229 break;
2231 case 0x3F: /* Doubleword Shift Right Arithmetic Plus 32 - DSRA32;
2232 MIPS64 */
2233 DIP("dsra32 r%u, r%u, %lld", regRd, regRt, sImmsa);
2234 assign(tmpRd, binop(Iop_Sar64, mkexpr(tmpRt), mkU8(uImmsa + 32)));
2235 putIReg(regRd, mkexpr(tmpRd));
2236 break;
2238 case 0x17: {
2239 /* Doubleword Shift Right Arithmetic Variable - DSRAV;
2240 MIPS64 */
2241 DIP("dsrav r%u, r%u, r%u", regRd, regRt, regRs);
2242 IRTemp tmpRs8 = newTemp(Ity_I8);
2243 assign(tmp, binop(Iop_And64, mkexpr(tmpRs), mkSzImm(ty, 63)));
2244 assign(tmpRs8, mkNarrowTo8(ty, mkexpr(tmp)));
2245 assign(tmpRd, binop(Iop_Sar64, mkexpr(tmpRt), mkexpr(tmpRs8)));
2246 putIReg(regRd, mkexpr(tmpRd));
2247 break;
2251 default:
2252 return False;
2256 return True;
2259 static IROp mkSzOp ( IRType ty, IROp op8 )
2261 Int adj;
2262 vassert(ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32 || ty == Ity_I64);
2263 vassert(op8 == Iop_Add8 || op8 == Iop_Sub8 || op8 == Iop_Mul8
2264 || op8 == Iop_Or8 || op8 == Iop_And8 || op8 == Iop_Xor8
2265 || op8 == Iop_Shl8 || op8 == Iop_Shr8 || op8 == Iop_Sar8
2266 || op8 == Iop_CmpEQ8 || op8 == Iop_CmpNE8 || op8 == Iop_Not8);
2267 adj = ty == Ity_I8 ? 0 : (ty == Ity_I16 ? 1 : (ty == Ity_I32 ? 2 : 3));
2268 return adj + op8;
2271 /*********************************************************/
2272 /*--- Floating Point Compare ---*/
2273 /*********************************************************/
2274 /* Function that returns a string that represent mips cond
2275 mnemonic for the input code. */
2276 static const HChar* showCondCode(UInt code)
2278 const HChar* ret;
2280 switch (code) {
2281 case 0:
2282 ret = "f";
2283 break;
2285 case 1:
2286 ret = "un";
2287 break;
2289 case 2:
2290 ret = "eq";
2291 break;
2293 case 3:
2294 ret = "ueq";
2295 break;
2297 case 4:
2298 ret = "olt";
2299 break;
2301 case 5:
2302 ret = "ult";
2303 break;
2305 case 6:
2306 ret = "ole";
2307 break;
2309 case 7:
2310 ret = "ule";
2311 break;
2313 case 8:
2314 ret = "sf";
2315 break;
2317 case 9:
2318 ret = "ngle";
2319 break;
2321 case 10:
2322 ret = "seq";
2323 break;
2325 case 11:
2326 ret = "ngl";
2327 break;
2329 case 12:
2330 ret = "lt";
2331 break;
2333 case 13:
2334 ret = "nge";
2335 break;
2337 case 14:
2338 ret = "le";
2339 break;
2341 case 15:
2342 ret = "ngt";
2343 break;
2345 default:
2346 vpanic("showCondCode");
2347 break;
2350 return ret;
2353 static Bool dis_instr_CCondFmt ( UInt cins )
2355 IRTemp t0, t1, t2, t3, tmp5, tmp6;
2356 IRTemp ccIR = newTemp(Ity_I32);
2357 IRTemp ccMIPS = newTemp(Ity_I32);
2358 UInt FC = get_FC(cins);
2359 UInt fmt = get_fmt(cins);
2360 UInt fs = get_fs(cins);
2361 UInt ft = get_ft(cins);
2362 UInt cond = get_cond(cins);
2364 if (FC == 0x3) { /* C.cond.fmt */
2365 UInt fpc_cc = get_fpc_cc(cins);
2367 switch (fmt) {
2368 case 0x10: { /* C.cond.S */
2369 DIP("c.%s.s %u, f%u, f%u", showCondCode(cond), fpc_cc, fs, ft);
2371 if (fp_mode64) {
2372 t0 = newTemp(Ity_I32);
2373 t1 = newTemp(Ity_I32);
2374 t2 = newTemp(Ity_I32);
2375 t3 = newTemp(Ity_I32);
2377 tmp5 = newTemp(Ity_F64);
2378 tmp6 = newTemp(Ity_F64);
2380 assign(tmp5, unop(Iop_F32toF64, getLoFromF64(Ity_F64,
2381 getFReg(fs))));
2382 assign(tmp6, unop(Iop_F32toF64, getLoFromF64(Ity_F64,
2383 getFReg(ft))));
2385 assign(ccIR, binop(Iop_CmpF64, mkexpr(tmp5), mkexpr(tmp6)));
2386 putHI(mkWidenFrom32(mode64 ? Ity_I64 : Ity_I32,
2387 mkexpr(ccIR), True));
2388 /* Map compare result from IR to MIPS
2389 FP cmp result | MIPS | IR
2390 --------------------------
2391 UN | 0x1 | 0x45
2392 EQ | 0x2 | 0x40
2393 GT | 0x4 | 0x00
2394 LT | 0x8 | 0x01
2397 /* ccMIPS = Shl(1, (~(ccIR>>5) & 2) | ((ccIR ^ (ccIR>>6)) & 1) */
2398 assign(ccMIPS, binop(Iop_Shl32, mkU32(1), unop(Iop_32to8,
2399 binop(Iop_Or32, binop(Iop_And32, unop(Iop_Not32,
2400 binop(Iop_Shr32, mkexpr(ccIR), mkU8(5))), mkU32(2)),
2401 binop(Iop_And32, binop(Iop_Xor32, mkexpr(ccIR),
2402 binop(Iop_Shr32, mkexpr(ccIR), mkU8(6))),
2403 mkU32(1))))));
2404 putLO(mkWidenFrom32(mode64 ? Ity_I64 : Ity_I32,
2405 mkexpr(ccMIPS), True));
2407 /* UN */
2408 assign(t0, binop(Iop_And32, mkexpr(ccMIPS), mkU32(0x1)));
2409 /* EQ */
2410 assign(t1, binop(Iop_And32, binop(Iop_Shr32, mkexpr(ccMIPS),
2411 mkU8(0x1)), mkU32(0x1)));
2412 /* NGT */
2413 assign(t2, binop(Iop_And32, unop(Iop_Not32, binop(Iop_Shr32,
2414 mkexpr(ccMIPS), mkU8(0x2))), mkU32(0x1)));
2415 /* LT */
2416 assign(t3, binop(Iop_And32, binop(Iop_Shr32, mkexpr(ccMIPS),
2417 mkU8(0x3)), mkU32(0x1)));
2419 switch (cond) {
2420 case 0x0:
2421 setFPUCondCode(mkU32(0), fpc_cc);
2422 break;
2424 case 0x1:
2425 setFPUCondCode(mkexpr(t0), fpc_cc);
2426 break;
2428 case 0x2:
2429 setFPUCondCode(mkexpr(t1), fpc_cc);
2430 break;
2432 case 0x3:
2433 setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t1)),
2434 fpc_cc);
2435 break;
2437 case 0x4:
2438 setFPUCondCode(mkexpr(t3), fpc_cc);
2439 break;
2441 case 0x5:
2442 setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t3)),
2443 fpc_cc);
2444 break;
2446 case 0x6:
2447 setFPUCondCode(binop(Iop_Or32, mkexpr(t3), mkexpr(t1)),
2448 fpc_cc);
2449 break;
2451 case 0x7:
2452 setFPUCondCode(mkexpr(t2), fpc_cc);
2453 break;
2455 case 0x8:
2456 setFPUCondCode(mkU32(0), fpc_cc);
2457 break;
2459 case 0x9:
2460 setFPUCondCode(mkexpr(t0), fpc_cc);
2461 break;
2463 case 0xA:
2464 setFPUCondCode(mkexpr(t1), fpc_cc);
2465 break;
2467 case 0xB:
2468 setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t1)),
2469 fpc_cc);
2470 break;
2472 case 0xC:
2473 setFPUCondCode(mkexpr(t3), fpc_cc);
2474 break;
2476 case 0xD:
2477 setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t3)),
2478 fpc_cc);
2479 break;
2481 case 0xE:
2482 setFPUCondCode(binop(Iop_Or32, mkexpr(t3), mkexpr(t1)),
2483 fpc_cc);
2484 break;
2486 case 0xF:
2487 setFPUCondCode(mkexpr(t2), fpc_cc);
2488 break;
2490 default:
2491 return False;
2494 } else {
2495 t0 = newTemp(Ity_I32);
2496 t1 = newTemp(Ity_I32);
2497 t2 = newTemp(Ity_I32);
2498 t3 = newTemp(Ity_I32);
2500 assign(ccIR, binop(Iop_CmpF64, unop(Iop_F32toF64, getFReg(fs)),
2501 unop(Iop_F32toF64, getFReg(ft))));
2502 /* Map compare result from IR to MIPS
2503 FP cmp result | MIPS | IR
2504 --------------------------
2505 UN | 0x1 | 0x45
2506 EQ | 0x2 | 0x40
2507 GT | 0x4 | 0x00
2508 LT | 0x8 | 0x01
2511 /* ccMIPS = Shl(1, (~(ccIR>>5) & 2) | ((ccIR ^ (ccIR>>6)) & 1) */
2512 assign(ccMIPS, binop(Iop_Shl32, mkU32(1), unop(Iop_32to8,
2513 binop(Iop_Or32, binop(Iop_And32, unop(Iop_Not32,
2514 binop(Iop_Shr32, mkexpr(ccIR), mkU8(5))),
2515 mkU32(2)), binop(Iop_And32,
2516 binop(Iop_Xor32, mkexpr(ccIR),
2517 binop(Iop_Shr32, mkexpr(ccIR), mkU8(6))),
2518 mkU32(1))))));
2519 /* UN */
2520 assign(t0, binop(Iop_And32, mkexpr(ccMIPS), mkU32(0x1)));
2521 /* EQ */
2522 assign(t1, binop(Iop_And32, binop(Iop_Shr32, mkexpr(ccMIPS),
2523 mkU8(0x1)), mkU32(0x1)));
2524 /* NGT */
2525 assign(t2, binop(Iop_And32, unop(Iop_Not32, binop(Iop_Shr32,
2526 mkexpr(ccMIPS), mkU8(0x2))), mkU32(0x1)));
2527 /* LT */
2528 assign(t3, binop(Iop_And32, binop(Iop_Shr32, mkexpr(ccMIPS),
2529 mkU8(0x3)), mkU32(0x1)));
2531 switch (cond) {
2532 case 0x0:
2533 setFPUCondCode(mkU32(0), fpc_cc);
2534 break;
2536 case 0x1:
2537 setFPUCondCode(mkexpr(t0), fpc_cc);
2538 break;
2540 case 0x2:
2541 setFPUCondCode(mkexpr(t1), fpc_cc);
2542 break;
2544 case 0x3:
2545 setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t1)),
2546 fpc_cc);
2547 break;
2549 case 0x4:
2550 setFPUCondCode(mkexpr(t3), fpc_cc);
2551 break;
2553 case 0x5:
2554 setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t3)),
2555 fpc_cc);
2556 break;
2558 case 0x6:
2559 setFPUCondCode(binop(Iop_Or32, mkexpr(t3), mkexpr(t1)),
2560 fpc_cc);
2561 break;
2563 case 0x7:
2564 setFPUCondCode(mkexpr(t2), fpc_cc);
2565 break;
2567 case 0x8:
2568 setFPUCondCode(mkU32(0), fpc_cc);
2569 break;
2571 case 0x9:
2572 setFPUCondCode(mkexpr(t0), fpc_cc);
2573 break;
2575 case 0xA:
2576 setFPUCondCode(mkexpr(t1), fpc_cc);
2577 break;
2579 case 0xB:
2580 setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t1)),
2581 fpc_cc);
2582 break;
2584 case 0xC:
2585 setFPUCondCode(mkexpr(t3), fpc_cc);
2586 break;
2588 case 0xD:
2589 setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t3)),
2590 fpc_cc);
2591 break;
2593 case 0xE:
2594 setFPUCondCode(binop(Iop_Or32, mkexpr(t3), mkexpr(t1)),
2595 fpc_cc);
2596 break;
2598 case 0xF:
2599 setFPUCondCode(mkexpr(t2), fpc_cc);
2600 break;
2602 default:
2603 return False;
2607 break;
2609 case 0x11: { /* C.cond.D */
2610 DIP("c.%s.d %u, f%u, f%u", showCondCode(cond), fpc_cc, fs, ft);
2611 t0 = newTemp(Ity_I32);
2612 t1 = newTemp(Ity_I32);
2613 t2 = newTemp(Ity_I32);
2614 t3 = newTemp(Ity_I32);
2615 assign(ccIR, binop(Iop_CmpF64, getDReg(fs), getDReg(ft)));
2616 /* Map compare result from IR to MIPS
2617 FP cmp result | MIPS | IR
2618 --------------------------
2619 UN | 0x1 | 0x45
2620 EQ | 0x2 | 0x40
2621 GT | 0x4 | 0x00
2622 LT | 0x8 | 0x01
2625 /* ccMIPS = Shl(1, (~(ccIR>>5) & 2) | ((ccIR ^ (ccIR>>6)) & 1) */
2626 assign(ccMIPS, binop(Iop_Shl32, mkU32(1), unop(Iop_32to8,
2627 binop(Iop_Or32, binop(Iop_And32, unop(Iop_Not32,
2628 binop(Iop_Shr32, mkexpr(ccIR), mkU8(5))), mkU32(2)),
2629 binop(Iop_And32, binop(Iop_Xor32, mkexpr(ccIR),
2630 binop(Iop_Shr32, mkexpr(ccIR), mkU8(6))),
2631 mkU32(1))))));
2633 /* UN */
2634 assign(t0, binop(Iop_And32, mkexpr(ccMIPS), mkU32(0x1)));
2635 /* EQ */
2636 assign(t1, binop(Iop_And32, binop(Iop_Shr32, mkexpr(ccMIPS),
2637 mkU8(0x1)), mkU32(0x1)));
2638 /* NGT */
2639 assign(t2, binop(Iop_And32, unop(Iop_Not32, binop(Iop_Shr32,
2640 mkexpr(ccMIPS), mkU8(0x2))), mkU32(0x1)));
2641 /* LT */
2642 assign(t3, binop(Iop_And32, binop(Iop_Shr32, mkexpr(ccMIPS),
2643 mkU8(0x3)), mkU32(0x1)));
2645 switch (cond) {
2646 case 0x0:
2647 setFPUCondCode(mkU32(0), fpc_cc);
2648 break;
2650 case 0x1:
2651 setFPUCondCode(mkexpr(t0), fpc_cc);
2652 break;
2654 case 0x2:
2655 setFPUCondCode(mkexpr(t1), fpc_cc);
2656 break;
2658 case 0x3:
2659 setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t1)),
2660 fpc_cc);
2661 break;
2663 case 0x4:
2664 setFPUCondCode(mkexpr(t3), fpc_cc);
2665 break;
2667 case 0x5:
2668 setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t3)),
2669 fpc_cc);
2670 break;
2672 case 0x6:
2673 setFPUCondCode(binop(Iop_Or32, mkexpr(t3), mkexpr(t1)),
2674 fpc_cc);
2675 break;
2677 case 0x7:
2678 setFPUCondCode(mkexpr(t2), fpc_cc);
2679 break;
2681 case 0x8:
2682 setFPUCondCode(mkU32(0), fpc_cc);
2683 break;
2685 case 0x9:
2686 setFPUCondCode(mkexpr(t0), fpc_cc);
2687 break;
2689 case 0xA:
2690 setFPUCondCode(mkexpr(t1), fpc_cc);
2691 break;
2693 case 0xB:
2694 setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t1)),
2695 fpc_cc);
2696 break;
2698 case 0xC:
2699 setFPUCondCode(mkexpr(t3), fpc_cc);
2700 break;
2702 case 0xD:
2703 setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t3)),
2704 fpc_cc);
2705 break;
2707 case 0xE:
2708 setFPUCondCode(binop(Iop_Or32, mkexpr(t3), mkexpr(t1)),
2709 fpc_cc);
2710 break;
2712 case 0xF:
2713 setFPUCondCode(mkexpr(t2), fpc_cc);
2714 break;
2716 default:
2717 return False;
2720 break;
2722 default:
2723 return False;
2725 } else {
2726 return False;
2729 return True;
2732 /*********************************************************/
2733 /*--- Branch Instructions for mips64 ---*/
2734 /*********************************************************/
2735 static Bool dis_instr_branch ( UInt theInstr, DisResult * dres, IRStmt ** set )
2737 UInt jmpKind = 0;
2738 UChar opc1 = get_opcode(theInstr);
2739 UChar regRs = get_rs(theInstr);
2740 UChar regRt = get_rt(theInstr);
2741 UInt offset = get_imm(theInstr);
2742 Long sOffset = extend_s_16to64(offset);
2743 IRType ty = mode64 ? Ity_I64 : Ity_I32;
2744 IROp opSlt = mode64 ? Iop_CmpLT64S : Iop_CmpLT32S;
2746 IRTemp tmp = newTemp(ty);
2747 IRTemp tmpRs = newTemp(ty);
2748 IRTemp tmpRt = newTemp(ty);
2749 IRTemp tmpLt = newTemp(ty);
2750 IRTemp tmpReg0 = newTemp(ty);
2752 UChar regLnk = 31; /* reg 31 is link reg in MIPS */
2753 Addr64 addrTgt = 0;
2754 Addr64 cia = guest_PC_curr_instr;
2756 IRExpr *eConst0 = mkSzImm(ty, (UInt) 0);
2757 IRExpr *eNia = mkSzImm(ty, cia + 8);
2758 IRExpr *eCond = NULL;
2760 assign(tmpRs, getIReg(regRs));
2761 assign(tmpRt, getIReg(regRt));
2762 assign(tmpReg0, getIReg(0));
2764 eCond = binop(mkSzOp(ty, Iop_CmpNE8), mkexpr(tmpReg0), mkexpr(tmpReg0));
2766 switch (opc1) {
2767 case 0x01:
2768 switch (regRt) {
2769 case 0x00: { /* BLTZ rs, offset */
2770 addrTgt = mkSzAddr(ty, cia + 4 + (sOffset << 2));
2771 IRTemp tmpLtRes = newTemp(Ity_I1);
2773 assign(tmp, eConst0);
2774 assign(tmpLtRes, binop(opSlt, mkexpr(tmpRs), mkexpr(tmp)));
2775 assign(tmpLt, mode64 ? unop(Iop_1Uto64, mkexpr(tmpLtRes)) :
2776 unop(Iop_1Uto32, mkexpr(tmpLtRes)));
2778 eCond = binop(mkSzOp(ty, Iop_CmpNE8), mkexpr(tmpLt),
2779 mkexpr(tmpReg0));
2781 jmpKind = Ijk_Boring;
2782 break;
2785 case 0x01: { /* BGEZ rs, offset */
2786 IRTemp tmpLtRes = newTemp(Ity_I1);
2787 addrTgt = mkSzAddr(ty, cia + 4 + (sOffset << 2));
2789 assign(tmp, eConst0);
2790 assign(tmpLtRes, binop(opSlt, mkexpr(tmpRs), mkexpr(tmp)));
2791 assign(tmpLt, mode64 ? unop(Iop_1Uto64, mkexpr(tmpLtRes)) :
2792 unop(Iop_1Uto32, mkexpr(tmpLtRes)));
2793 eCond = binop(mkSzOp(ty, Iop_CmpEQ8), mkexpr(tmpLt),
2794 mkexpr(tmpReg0));
2796 jmpKind = Ijk_Boring;
2797 break;
2800 case 0x11: { /* BGEZAL rs, offset */
2801 addrTgt = mkSzAddr(ty, cia + 4 + (sOffset << 2));
2802 putIReg(regLnk, eNia);
2803 IRTemp tmpLtRes = newTemp(Ity_I1);
2805 assign(tmpLtRes, binop(opSlt, mkexpr(tmpRs), eConst0));
2806 assign(tmpLt, mode64 ? unop(Iop_1Uto64, mkexpr(tmpLtRes)) :
2807 unop(Iop_1Uto32, mkexpr(tmpLtRes)));
2809 eCond = binop(mkSzOp(ty, Iop_CmpEQ8), mkexpr(tmpLt),
2810 mkexpr(tmpReg0));
2812 jmpKind = Ijk_Call;
2813 break;
2816 case 0x10: { /* BLTZAL rs, offset */
2817 IRTemp tmpLtRes = newTemp(Ity_I1);
2818 IRTemp tmpRes = newTemp(ty);
2820 addrTgt = mkSzAddr(ty, cia + 4 + (sOffset << 2));
2821 putIReg(regLnk, eNia);
2823 assign(tmp, eConst0);
2824 assign(tmpLtRes, binop(opSlt, mkexpr(tmpRs), mkexpr(tmp)));
2825 assign(tmpRes, mode64 ? unop(Iop_1Uto64,
2826 mkexpr(tmpLtRes)) : unop(Iop_1Uto32, mkexpr(tmpLtRes)));
2827 eCond = binop(mkSzOp(ty, Iop_CmpNE8), mkexpr(tmpRes),
2828 mkexpr(tmpReg0));
2830 jmpKind = Ijk_Call;
2831 break;
2836 break;
2838 default:
2839 return False;
2842 *set = IRStmt_Exit(eCond, jmpKind, mkSzConst(ty, addrTgt), OFFB_PC);
2843 return True;
2846 /*********************************************************/
2847 /*--- Cavium Specific Instructions ---*/
2848 /*********************************************************/
2850 /* Convenience function to yield to thread scheduler */
2851 static void jump_back(IRExpr *condition)
2853 stmt( IRStmt_Exit(condition,
2854 Ijk_Yield,
2855 IRConst_U64( guest_PC_curr_instr ),
2856 OFFB_PC) );
2859 /* Based on s390_irgen_load_and_add32. */
2860 static void mips_load_store32(IRTemp op1addr, IRTemp new_val,
2861 IRTemp expd, UChar rd, Bool putIntoRd)
2863 IRCAS *cas;
2864 IRTemp old_mem = newTemp(Ity_I32);
2865 IRType ty = mode64 ? Ity_I64 : Ity_I32;
2867 cas = mkIRCAS(IRTemp_INVALID, old_mem,
2868 #if defined (_MIPSEL)
2869 Iend_LE, mkexpr(op1addr),
2870 #else /* _MIPSEB */
2871 Iend_BE, mkexpr(op1addr),
2872 #endif
2873 NULL, mkexpr(expd), /* expected value */
2874 NULL, mkexpr(new_val) /* new value */);
2875 stmt(IRStmt_CAS(cas));
2877 /* If old_mem contains the expected value, then the CAS succeeded.
2878 Otherwise, it did not */
2879 jump_back(binop(Iop_CmpNE32, mkexpr(old_mem), mkexpr(expd)));
2881 if (putIntoRd)
2882 putIReg(rd, mkWidenFrom32(ty, mkexpr(old_mem), True));
2885 /* Based on s390_irgen_load_and_add64. */
2886 static void mips_load_store64(IRTemp op1addr, IRTemp new_val,
2887 IRTemp expd, UChar rd, Bool putIntoRd)
2889 IRCAS *cas;
2890 IRTemp old_mem = newTemp(Ity_I64);
2891 vassert(mode64);
2892 cas = mkIRCAS(IRTemp_INVALID, old_mem,
2893 #if defined (_MIPSEL)
2894 Iend_LE, mkexpr(op1addr),
2895 #else /* _MIPSEB */
2896 Iend_BE, mkexpr(op1addr),
2897 #endif
2898 NULL, mkexpr(expd), /* expected value */
2899 NULL, mkexpr(new_val) /* new value */);
2900 stmt(IRStmt_CAS(cas));
2902 /* If old_mem contains the expected value, then the CAS succeeded.
2903 Otherwise, it did not */
2904 jump_back(binop(Iop_CmpNE64, mkexpr(old_mem), mkexpr(expd)));
2906 if (putIntoRd)
2907 putIReg(rd, mkexpr(old_mem));
2910 static Bool dis_instr_CVM ( UInt theInstr )
2912 UChar opc2 = get_function(theInstr);
2913 UChar opc1 = get_opcode(theInstr);
2914 UChar regRs = get_rs(theInstr);
2915 UChar regRt = get_rt(theInstr);
2916 UChar regRd = get_rd(theInstr);
2917 /* MIPS trap instructions extract code from theInstr[15:6].
2918 Cavium OCTEON instructions SNEI, SEQI extract immediate operands
2919 from the same bit field [15:6]. */
2920 UInt imm = get_code(theInstr);
2921 UChar lenM1 = get_msb(theInstr);
2922 UChar p = get_lsb(theInstr);
2923 IRType ty = mode64 ? Ity_I64 : Ity_I32;
2924 IRTemp tmp = newTemp(ty);
2925 IRTemp tmpRs = newTemp(ty);
2926 IRTemp tmpRt = newTemp(ty);
2927 IRTemp t1 = newTemp(ty);
2928 UInt size;
2929 assign(tmpRs, getIReg(regRs));
2931 switch (opc1) {
2932 case 0x1C: {
2933 switch (opc2) {
2934 case 0x03: { /* DMUL rd, rs, rt */
2935 DIP("dmul r%u, r%u, r%u", regRd, regRs, regRt);
2936 IRTemp t0 = newTemp(Ity_I128);
2937 assign(t0, binop(Iop_MullU64, getIReg(regRs), getIReg(regRt)));
2938 putIReg(regRd, unop(Iop_128to64, mkexpr(t0)));
2939 break;
2942 case 0x18: { /* Store Atomic Add Word - SAA; Cavium OCTEON */
2943 DIP("saa r%u, (r%u)", regRt, regRs);
2944 IRTemp addr = newTemp(Ity_I64);
2945 IRTemp new_val = newTemp(Ity_I32);
2946 IRTemp old = newTemp(Ity_I32);
2947 assign(addr, getIReg(regRs));
2948 assign(old, load(Ity_I32, mkexpr(addr)));
2949 assign(new_val, binop(Iop_Add32,
2950 mkexpr(old),
2951 mkNarrowTo32(ty, getIReg(regRt))));
2952 mips_load_store32(addr, new_val, old, 0, False);
2953 break;
2956 /* Store Atomic Add Doubleword - SAAD; Cavium OCTEON */
2957 case 0x19: {
2958 DIP( "saad r%u, (r%u)", regRt, regRs);
2959 IRTemp addr = newTemp(Ity_I64);
2960 IRTemp new_val = newTemp(Ity_I64);
2961 IRTemp old = newTemp(Ity_I64);
2962 assign(addr, getIReg(regRs));
2963 assign(old, load(Ity_I64, mkexpr(addr)));
2964 assign(new_val, binop(Iop_Add64,
2965 mkexpr(old),
2966 getIReg(regRt)));
2967 mips_load_store64(addr, new_val, old, 0, False);
2968 break;
2971 /* LAI, LAID, LAD, LADD, LAS, LASD,
2972 LAC, LACD, LAA, LAAD, LAW, LAWD */
2973 case 0x1f: {
2974 UInt opc3 = get_sa(theInstr);
2975 IRTemp addr = newTemp(Ity_I64);
2977 switch (opc3) {
2978 /* Load Atomic Increment Word - LAI; Cavium OCTEON2 */
2979 case 0x02: {
2980 DIP("lai r%u,(r%u)\n", regRd, regRs);
2981 IRTemp new_val = newTemp(Ity_I32);
2982 IRTemp old = newTemp(Ity_I32);
2983 assign(addr, getIReg(regRs));
2984 assign(old, load(Ity_I32, mkexpr(addr)));
2985 assign(new_val, binop(Iop_Add32,
2986 mkexpr(old),
2987 mkU32(1)));
2988 mips_load_store32(addr, new_val, old, regRd, True);
2989 break;
2992 /* Load Atomic Increment Doubleword - LAID; Cavium OCTEON2 */
2993 case 0x03: {
2994 DIP("laid r%u,(r%u)\n", regRd, regRs);
2995 IRTemp new_val = newTemp(Ity_I64);
2996 IRTemp old = newTemp(Ity_I64);
2997 assign(addr, getIReg(regRs));
2998 assign(old, load(Ity_I64, mkexpr(addr)));
2999 assign(new_val, binop(Iop_Add64,
3000 mkexpr(old),
3001 mkU64(1)));
3002 mips_load_store64(addr, new_val, old, regRd, True);
3003 break;
3006 /* Load Atomic Decrement Word - LAD; Cavium OCTEON2 */
3007 case 0x06: {
3008 DIP("lad r%u,(r%u)\n", regRd, regRs);
3009 IRTemp new_val = newTemp(Ity_I32);
3010 IRTemp old = newTemp(Ity_I32);
3011 assign(addr, getIReg(regRs));
3012 assign(old, load(Ity_I32, mkexpr(addr)));
3013 assign(new_val, binop(Iop_Sub32,
3014 mkexpr(old),
3015 mkU32(1)));
3016 mips_load_store32(addr, new_val, old, regRd, True);
3017 break;
3020 /* Load Atomic Decrement Doubleword - LADD; Cavium OCTEON2 */
3021 case 0x07: {
3022 DIP("ladd r%u,(r%u)\n", regRd, regRs);
3023 IRTemp new_val = newTemp(Ity_I64);
3024 IRTemp old = newTemp(Ity_I64);
3025 assign(addr, getIReg(regRs));
3026 assign(old, load(Ity_I64, mkexpr(addr)));
3027 assign(new_val, binop(Iop_Sub64,
3028 mkexpr(old),
3029 mkU64(1)));
3030 mips_load_store64(addr, new_val, old, regRd, True);
3031 break;
3034 /* Load Atomic Set Word - LAS; Cavium OCTEON2 */
3035 case 0x0a: {
3036 DIP("las r%u,(r%u)\n", regRd, regRs);
3037 IRTemp new_val = newTemp(Ity_I32);
3038 IRTemp old = newTemp(Ity_I32);
3039 assign(addr, getIReg(regRs));
3040 assign(new_val, mkU32(0xffffffff));
3041 assign(old, load(Ity_I32, mkexpr(addr)));
3042 mips_load_store32(addr, new_val, old, regRd, True);
3043 break;
3046 /* Load Atomic Set Doubleword - LASD; Cavium OCTEON2 */
3047 case 0x0b: {
3048 DIP("lasd r%u,(r%u)\n", regRd, regRs);
3049 IRTemp new_val = newTemp(Ity_I64);
3050 IRTemp old = newTemp(Ity_I64);
3051 assign(addr, getIReg(regRs));
3052 assign(new_val, mkU64(0xffffffffffffffffULL));
3053 assign(old, load(Ity_I64, mkexpr(addr)));
3054 mips_load_store64(addr, new_val, old, regRd, True);
3055 break;
3058 /* Load Atomic Clear Word - LAC; Cavium OCTEON2 */
3059 case 0x0e: {
3060 DIP("lac r%u,(r%u)\n", regRd, regRs);
3061 IRTemp new_val = newTemp(Ity_I32);
3062 IRTemp old = newTemp(Ity_I32);
3063 assign(addr, getIReg(regRs));
3064 assign(new_val, mkU32(0));
3065 assign(old, load(Ity_I32, mkexpr(addr)));
3066 mips_load_store32(addr, new_val, old, regRd, True);
3067 break;
3070 /* Load Atomic Clear Doubleword - LACD; Cavium OCTEON2 */
3071 case 0x0f: {
3072 DIP("lacd r%u,(r%u)\n", regRd, regRs);
3073 IRTemp new_val = newTemp(Ity_I64);
3074 IRTemp old = newTemp(Ity_I64);
3075 assign(addr, getIReg(regRs));
3076 assign(new_val, mkU64(0));
3077 assign(old, load(Ity_I64, mkexpr(addr)));
3078 mips_load_store64(addr, new_val, old, regRd, True);
3079 break;
3082 /* Load Atomic Add Word - LAA; Cavium OCTEON2 */
3083 case 0x12: {
3084 DIP("laa r%u,(r%u),r%u\n", regRd, regRs, regRt);
3085 IRTemp new_val = newTemp(Ity_I32);
3086 IRTemp old = newTemp(Ity_I32);
3087 assign(addr, getIReg(regRs));
3088 assign(old, load(Ity_I32, mkexpr(addr)));
3089 assign(new_val, binop(Iop_Add32,
3090 mkexpr(old),
3091 mkNarrowTo32(ty, getIReg(regRt))));
3092 mips_load_store32(addr, new_val, old, regRd, True);
3093 break;
3096 /* Load Atomic Add Doubleword - LAAD; Cavium OCTEON2 */
3097 case 0x13: {
3098 DIP("laad r%u,(r%u),r%u\n", regRd, regRs, regRt);
3099 IRTemp new_val = newTemp(Ity_I64);
3100 IRTemp old = newTemp(Ity_I64);
3101 assign(addr, getIReg(regRs));
3102 assign(old, load(Ity_I64, mkexpr(addr)));
3103 assign(new_val, binop(Iop_Add64,
3104 load(Ity_I64, mkexpr(addr)),
3105 getIReg(regRt)));
3106 mips_load_store64(addr, new_val, old, regRd, True);
3107 break;
3110 /* Load Atomic Swap Word - LAW; Cavium OCTEON2 */
3111 case 0x16: {
3112 DIP("law r%u,(r%u)\n", regRd, regRs);
3113 IRTemp new_val = newTemp(Ity_I32);
3114 IRTemp old = newTemp(Ity_I32);
3115 assign(addr, getIReg(regRs));
3116 assign(new_val, mkNarrowTo32(ty, getIReg(regRt)));
3117 assign(old, load(Ity_I32, mkexpr(addr)));
3118 mips_load_store32(addr, new_val, old, regRd, True);
3119 break;
3122 /* Load Atomic Swap Doubleword - LAWD; Cavium OCTEON2 */
3123 case 0x17: {
3124 DIP("lawd r%u,(r%u)\n", regRd, regRs);
3125 IRTemp new_val = newTemp(Ity_I64);
3126 IRTemp old = newTemp(Ity_I64);
3127 assign(addr, getIReg(regRs));
3128 assign(new_val, getIReg(regRt));
3129 assign(old, load(Ity_I64, mkexpr(addr)));
3130 mips_load_store64(addr, new_val, old, regRd, True);
3131 break;
3134 default:
3135 vex_printf("Unknown laxx instruction, opc3=0x%x\n", opc3);
3136 vex_printf("Instruction=0x%08x\n", theInstr);
3137 return False;
3140 break;
3143 /* Unsigned Byte Add - BADDU rd, rs, rt; Cavium OCTEON */
3144 case 0x28: {
3145 DIP("BADDU r%u, r%u, r%u", regRs, regRt, regRd);
3146 IRTemp t0 = newTemp(Ity_I8);
3148 assign(t0, binop(Iop_Add8,
3149 mkNarrowTo8(ty, getIReg(regRs)),
3150 mkNarrowTo8(ty, getIReg(regRt))));
3152 if (mode64)
3153 putIReg(regRd, binop(mkSzOp(ty, Iop_And8),
3154 unop(Iop_8Uto64, mkexpr(t0)),
3155 mkSzImm(ty, 0xFF)));
3156 else
3157 putIReg(regRd, binop(mkSzOp(ty, Iop_And8),
3158 unop(Iop_8Uto32, mkexpr(t0)),
3159 mkSzImm(ty, 0xFF)));
3161 break;
3164 case 0x2c: { /* Count Ones in a Word - POP; Cavium OCTEON */
3165 int i, shift[5];
3166 IRTemp mask[5];
3167 IRTemp old = newTemp(ty);
3168 IRTemp nyu = IRTemp_INVALID;
3169 assign(old, getIReg(regRs));
3170 DIP("pop r%u, r%u", regRd, regRs);
3172 for (i = 0; i < 5; i++) {
3173 mask[i] = newTemp(ty);
3174 shift[i] = 1 << i;
3177 if (mode64) {
3178 assign(mask[0], mkU64(0x0000000055555555));
3179 assign(mask[1], mkU64(0x0000000033333333));
3180 assign(mask[2], mkU64(0x000000000F0F0F0F));
3181 assign(mask[3], mkU64(0x0000000000FF00FF));
3182 assign(mask[4], mkU64(0x000000000000FFFF));
3184 for (i = 0; i < 5; i++) {
3185 nyu = newTemp(ty);
3186 assign(nyu,
3187 binop(Iop_Add64,
3188 binop(Iop_And64,
3189 mkexpr(old), mkexpr(mask[i])),
3190 binop(Iop_And64,
3191 binop(Iop_Shr64,
3192 mkexpr(old), mkU8(shift[i])),
3193 mkexpr(mask[i]))));
3194 old = nyu;
3196 } else {
3197 assign(mask[0], mkU32(0x55555555));
3198 assign(mask[1], mkU32(0x33333333));
3199 assign(mask[2], mkU32(0x0F0F0F0F));
3200 assign(mask[3], mkU32(0x00FF00FF));
3201 assign(mask[4], mkU32(0x0000FFFF));
3202 assign(old, getIReg(regRs));
3204 for (i = 0; i < 5; i++) {
3205 nyu = newTemp(ty);
3206 assign(nyu,
3207 binop(Iop_Add32,
3208 binop(Iop_And32,
3209 mkexpr(old), mkexpr(mask[i])),
3210 binop(Iop_And32,
3211 binop(Iop_Shr32,
3212 mkexpr(old), mkU8(shift[i])),
3213 mkexpr(mask[i]))));
3214 old = nyu;
3218 putIReg(regRd, mkexpr(nyu));
3219 break;
3222 /* Count Ones in a Doubleword - DPOP; Cavium OCTEON */
3223 case 0x2d: {
3224 int i, shift[6];
3225 IRTemp mask[6];
3226 IRTemp old = newTemp(ty);
3227 IRTemp nyu = IRTemp_INVALID;
3228 DIP("dpop r%u, r%u", regRd, regRs);
3230 for (i = 0; i < 6; i++) {
3231 mask[i] = newTemp(ty);
3232 shift[i] = 1 << i;
3235 vassert(mode64); /*Caution! Only for Mode 64*/
3236 assign(mask[0], mkU64(0x5555555555555555ULL));
3237 assign(mask[1], mkU64(0x3333333333333333ULL));
3238 assign(mask[2], mkU64(0x0F0F0F0F0F0F0F0FULL));
3239 assign(mask[3], mkU64(0x00FF00FF00FF00FFULL));
3240 assign(mask[4], mkU64(0x0000FFFF0000FFFFULL));
3241 assign(mask[5], mkU64(0x00000000FFFFFFFFULL));
3242 assign(old, getIReg(regRs));
3244 for (i = 0; i < 6; i++) {
3245 nyu = newTemp(Ity_I64);
3246 assign(nyu,
3247 binop(Iop_Add64,
3248 binop(Iop_And64,
3249 mkexpr(old), mkexpr(mask[i])),
3250 binop(Iop_And64,
3251 binop(Iop_Shr64,
3252 mkexpr(old), mkU8(shift[i])),
3253 mkexpr(mask[i]))));
3254 old = nyu;
3257 putIReg(regRd, mkexpr(nyu));
3258 break;
3261 case 0x32: /* 5. CINS rd, rs, p, lenm1 */
3262 DIP("cins r%u, r%u, %u, %u\n", regRt, regRs, p, lenM1);
3263 assign ( tmp , binop(Iop_Shl64, mkexpr(tmpRs),
3264 mkU8(64 - ( lenM1 + 1 ))));
3265 assign ( tmpRt, binop(Iop_Shr64, mkexpr( tmp ),
3266 mkU8(64 - (p + lenM1 + 1))));
3267 putIReg( regRt, mkexpr(tmpRt));
3268 break;
3270 case 0x33: /* 6. CINS32 rd, rs, p+32, lenm1 */
3271 DIP("cins32 r%u, r%u, %d, %d\n", regRt, regRs, p + 32, lenM1);
3272 assign ( tmp , binop(Iop_Shl64, mkexpr(tmpRs),
3273 mkU8(64 - ( lenM1 + 1 ))));
3274 assign ( tmpRt, binop(Iop_Shr64, mkexpr( tmp ),
3275 mkU8(32 - (p + lenM1 + 1))));
3276 putIReg( regRt, mkexpr(tmpRt));
3277 break;
3279 case 0x3A: /* 3. EXTS rt, rs, p len */
3280 DIP("exts r%u, r%u, %d, %d\n", regRt, regRs, p, lenM1);
3281 size = lenM1 + 1; /* lenm1+1 */
3282 UChar lsAmt = 64 - (p + size); /* p+lenm1+1 */
3283 UChar rsAmt = 64 - size; /* lenm1+1 */
3284 tmp = newTemp(Ity_I64);
3285 assign(tmp, binop(Iop_Shl64, mkexpr(tmpRs), mkU8(lsAmt)));
3286 putIReg(regRt, binop(Iop_Sar64, mkexpr(tmp), mkU8(rsAmt)));
3287 break;
3289 case 0x3B: /* 4. EXTS32 rt, rs, p len */
3290 DIP("exts32 r%u, r%u, %d, %d\n", regRt, regRs, p, lenM1);
3291 assign ( tmp , binop(Iop_Shl64, mkexpr(tmpRs),
3292 mkU8(32 - (p + lenM1 + 1))));
3293 assign ( tmpRt, binop(Iop_Sar64, mkexpr(tmp),
3294 mkU8(64 - (lenM1 + 1))) );
3295 putIReg( regRt, mkexpr(tmpRt));
3296 break;
3298 case 0x2B: /* 20. SNE rd, rs, rt */
3299 DIP("sne r%u, r%u, r%u", regRd, regRs, regRt);
3301 if (mode64)
3302 putIReg(regRd, unop(Iop_1Uto64, binop(Iop_CmpNE64,
3303 getIReg(regRs),
3304 getIReg(regRt))));
3305 else
3306 putIReg(regRd, unop(Iop_1Uto32, binop(Iop_CmpNE32,
3307 getIReg(regRs),
3308 getIReg(regRt))));
3310 break;
3312 case 0x2A: /* Set Equals - SEQ; Cavium OCTEON */
3313 DIP("seq r%u, r%u, %d", regRd, regRs, regRt);
3315 if (mode64)
3316 putIReg(regRd, unop(Iop_1Uto64,
3317 binop(Iop_CmpEQ64, getIReg(regRs),
3318 getIReg(regRt))));
3319 else
3320 putIReg(regRd, unop(Iop_1Uto32,
3321 binop(Iop_CmpEQ32, getIReg(regRs),
3322 getIReg(regRt))));
3324 break;
3326 case 0x2E: /* Set Equals Immediate - SEQI; Cavium OCTEON */
3327 DIP("seqi r%u, r%u, %u", regRt, regRs, imm);
3329 if (mode64)
3330 putIReg(regRt, unop(Iop_1Uto64,
3331 binop(Iop_CmpEQ64, getIReg(regRs),
3332 mkU64(extend_s_10to64(imm)))));
3333 else
3334 putIReg(regRt, unop(Iop_1Uto32,
3335 binop(Iop_CmpEQ32, getIReg(regRs),
3336 mkU32(extend_s_10to32(imm)))));
3338 break;
3340 case 0x2F: /* Set Not Equals Immediate - SNEI; Cavium OCTEON */
3341 DIP("snei r%u, r%u, %u", regRt, regRs, imm);
3343 if (mode64)
3344 putIReg(regRt, unop(Iop_1Uto64,
3345 binop(Iop_CmpNE64,
3346 getIReg(regRs),
3347 mkU64(extend_s_10to64(imm)))));
3348 else
3349 putIReg(regRt, unop(Iop_1Uto32,
3350 binop(Iop_CmpNE32,
3351 getIReg(regRs),
3352 mkU32(extend_s_10to32(imm)))));
3354 break;
3356 default:
3357 return False;
3360 break;
3361 } /* opc1 0x1C ends here*/
3363 case 0x1F: {
3364 switch (opc2) {
3365 case 0x0A: { // lx - Load indexed instructions
3366 switch (get_sa(theInstr)) {
3367 case 0x00: { // LWX rd, index(base)
3368 DIP("lwx r%u, r%u(r%u)", regRd, regRt, regRs);
3369 LOADX_STORE_PATTERN;
3370 putIReg(regRd, mkWidenFrom32(ty, load(Ity_I32, mkexpr(t1)),
3371 True));
3372 break;
3375 case 0x04: // LHX rd, index(base)
3376 DIP("lhx r%u, r%u(r%u)", regRd, regRt, regRs);
3377 LOADX_STORE_PATTERN;
3379 if (mode64)
3380 putIReg(regRd, unop(Iop_16Sto64, load(Ity_I16,
3381 mkexpr(t1))));
3382 else
3383 putIReg(regRd, unop(Iop_16Sto32, load(Ity_I16,
3384 mkexpr(t1))));
3386 break;
3388 case 0x08: { // LDX rd, index(base)
3389 DIP("ldx r%u, r%u(r%u)", regRd, regRt, regRs);
3390 vassert(mode64); /* Currently Implemented only for n64 */
3391 LOADX_STORE_PATTERN;
3392 putIReg(regRd, load(Ity_I64, mkexpr(t1)));
3393 break;
3396 case 0x06: { // LBUX rd, index(base)
3397 DIP("lbux r%u, r%u(r%u)", regRd, regRt, regRs);
3398 LOADX_STORE_PATTERN;
3400 if (mode64)
3401 putIReg(regRd, unop(Iop_8Uto64, load(Ity_I8,
3402 mkexpr(t1))));
3403 else
3404 putIReg(regRd, unop(Iop_8Uto32, load(Ity_I8,
3405 mkexpr(t1))));
3407 break;
3410 case 0x10: { // LWUX rd, index(base) (Cavium OCTEON)
3411 DIP("lwux r%u, r%u(r%u)", regRd, regRt, regRs);
3412 LOADX_STORE_PATTERN; /* same for both 32 and 64 modes*/
3413 putIReg(regRd, mkWidenFrom32(ty, load(Ity_I32, mkexpr(t1)),
3414 False));
3415 break;
3418 case 0x14: { // LHUX rd, index(base) (Cavium OCTEON)
3419 DIP("lhux r%u, r%u(r%u)", regRd, regRt, regRs);
3420 LOADX_STORE_PATTERN;
3422 if (mode64)
3423 putIReg(regRd,
3424 unop(Iop_16Uto64, load(Ity_I16, mkexpr(t1))));
3425 else
3426 putIReg(regRd,
3427 unop(Iop_16Uto32, load(Ity_I16, mkexpr(t1))));
3429 break;
3432 case 0x16: { // LBX rd, index(base) (Cavium OCTEON)
3433 DIP("lbx r%u, r%u(r%u)", regRd, regRs, regRt);
3434 LOADX_STORE_PATTERN;
3436 if (mode64)
3437 putIReg(regRd,
3438 unop(Iop_8Sto64, load(Ity_I8, mkexpr(t1))));
3439 else
3440 putIReg(regRd,
3441 unop(Iop_8Sto32, load(Ity_I8, mkexpr(t1))));
3443 break;
3446 default:
3447 vex_printf("\nUnhandled LX instruction opc3 = %x\n",
3448 get_sa(theInstr));
3449 return False;
3452 break;
3454 } /* opc1 = 0x1F & opc2 = 0xA (LX) ends here*/
3456 break;
3457 } /* opc1 = 0x1F ends here*/
3459 default:
3460 return False;
3461 } /* main opc1 switch ends here */
3463 return True;
3466 static Int msa_I8_logical(UInt cins, UChar wd, UChar ws)
3468 IRTemp t1, t2;
3469 UShort operation;
3470 UChar i8;
3472 operation = (cins >> 24) & 3;
3473 i8 = (cins & 0x00FF0000) >> 16;
3475 switch (operation) {
3476 case 0x00: { /* ANDI.B */
3477 DIP("ANDI.B w%d, w%d, %d", wd, ws, i8);
3478 t1 = newTemp(Ity_V128);
3479 t2 = newTemp(Ity_V128);
3480 ULong tmp = i8;
3481 tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
3482 (tmp << 32) | (tmp << 24) | (tmp << 16) |
3483 (tmp << 8);
3484 assign(t1, getWReg(ws));
3485 assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
3486 putWReg(wd, binop(Iop_AndV128, mkexpr(t1), mkexpr(t2)));
3487 break;
3490 case 0x01: { /* ORI.B */
3491 DIP("ORI.B w%d, w%d, %d", wd, ws, i8);
3492 t1 = newTemp(Ity_V128);
3493 t2 = newTemp(Ity_V128);
3494 ULong tmp = i8;
3495 tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
3496 (tmp << 32) | (tmp << 24) | (tmp << 16) |
3497 (tmp << 8);
3498 assign(t1, getWReg(ws));
3499 assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
3500 putWReg(wd, binop(Iop_OrV128, mkexpr(t1), mkexpr(t2)));
3501 break;
3504 case 0x02: { /* NORI.B */
3505 DIP("NORI.B w%d, w%d, %d", wd, ws, i8);
3506 t1 = newTemp(Ity_V128);
3507 t2 = newTemp(Ity_V128);
3508 ULong tmp = i8;
3509 tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
3510 (tmp << 32) | (tmp << 24) | (tmp << 16) |
3511 (tmp << 8);
3512 assign(t1, getWReg(ws));
3513 assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
3514 putWReg(wd, unop(Iop_NotV128, binop(Iop_OrV128,
3515 mkexpr(t1), mkexpr(t2))));
3516 break;
3519 case 0x03: { /* XORI.B */
3520 DIP("XORI.B w%d, w%d, %d", wd, ws, i8);
3521 t1 = newTemp(Ity_V128);
3522 t2 = newTemp(Ity_V128);
3523 ULong tmp = i8;
3524 tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
3525 (tmp << 32) | (tmp << 24) | (tmp << 16) |
3526 (tmp << 8);
3527 assign(t1, getWReg(ws));
3528 assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
3529 putWReg(wd, binop(Iop_XorV128, mkexpr(t1), mkexpr(t2)));
3530 break;
3533 default:
3534 return -1;
3537 return 0;
3540 static Int msa_I8_branch(UInt cins, UChar wd, UChar ws)
3542 IRTemp t1, t2, t3, t4;
3543 UShort operation;
3544 UChar i8;
3546 operation = (cins >> 24) & 3;
3547 i8 = (cins & 0x00FF0000) >> 16;
3549 switch (operation) {
3550 case 0x00: { /* BMNZI.B */
3551 DIP("BMNZI.B w%d, w%d, %d", wd, ws, i8);
3552 t1 = newTemp(Ity_V128);
3553 t2 = newTemp(Ity_V128);
3554 t3 = newTemp(Ity_V128);
3555 t4 = newTemp(Ity_V128);
3556 ULong tmp = i8;
3557 tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
3558 (tmp << 32) | (tmp << 24) | (tmp << 16) |
3559 (tmp << 8);
3560 assign(t4, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
3561 assign(t1, binop(Iop_AndV128, getWReg(ws), mkexpr(t4)));
3562 assign(t2, binop(Iop_AndV128, getWReg(wd),
3563 unop(Iop_NotV128, mkexpr(t4))));
3564 assign(t3, binop(Iop_OrV128, mkexpr(t1), mkexpr(t2)));
3565 putWReg(wd, mkexpr(t3));
3566 break;
3569 case 0x01: { /* BMZI.B */
3570 DIP("BMZI.B w%d, w%d, %d", wd, ws, i8);
3571 t1 = newTemp(Ity_V128);
3572 t2 = newTemp(Ity_V128);
3573 t3 = newTemp(Ity_V128);
3574 t4 = newTemp(Ity_V128);
3575 ULong tmp = i8;
3576 tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
3577 (tmp << 32) | (tmp << 24) | (tmp << 16) |
3578 (tmp << 8);
3579 assign(t4, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
3580 assign(t1, binop(Iop_AndV128, getWReg(wd), mkexpr(t4)));
3581 assign(t2, binop(Iop_AndV128, getWReg(ws),
3582 unop(Iop_NotV128, mkexpr(t4))));
3583 assign(t3, binop(Iop_OrV128, mkexpr(t1), mkexpr(t2)));
3584 putWReg(wd, mkexpr(t3));
3585 break;
3588 case 0x02: { /* BSELI.B */
3589 DIP("BSELI.B w%d, w%d, %d", wd, ws, i8);
3590 t1 = newTemp(Ity_V128);
3591 t2 = newTemp(Ity_V128);
3592 t3 = newTemp(Ity_V128);
3593 t4 = newTemp(Ity_V128);
3594 ULong tmp = i8;
3595 tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
3596 (tmp << 32) | (tmp << 24) | (tmp << 16) |
3597 (tmp << 8);
3598 assign(t4, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
3599 assign(t1, binop(Iop_AndV128, getWReg(wd), mkexpr(t4)));
3600 assign(t2, binop(Iop_AndV128, getWReg(ws),
3601 unop(Iop_NotV128, getWReg(wd))));
3602 assign(t3, binop(Iop_OrV128, mkexpr(t1), mkexpr(t2)));
3603 putWReg(wd, mkexpr(t3));
3604 break;
3607 default:
3608 return -1;
3611 return 0;
3614 static Int msa_I8_shift(UInt cins, UChar wd, UChar ws)
3616 IRTemp t1, t2;
3617 UShort operation;
3618 UChar i8;
3620 operation = (cins >> 24) & 3;
3621 i8 = (cins & 0x00FF0000) >> 16;
3623 switch (operation) {
3624 case 0x00: { /* SHF.B */
3625 DIP("SHF.B w%d, w%d, %d", wd, ws, i8);
3626 t1 = newTemp(Ity_V128);
3627 t2 = newTemp(Ity_V128);
3628 assign(t1, getWReg(wd));
3629 assign(t2, getWReg(ws));
3630 Int i;
3631 IRTemp tmp[16];
3633 for (i = 0; i < 16; i++) {
3634 tmp[i] = newTemp(Ity_I8);
3635 assign(tmp[i],
3636 binop(Iop_GetElem8x16, mkexpr(t2),
3637 mkU8(i - (i % 4) +
3638 ((i8 >> (i % 4) * 2) & 0x03))));
3641 putWReg(wd, binop(Iop_64HLtoV128,
3642 binop(Iop_32HLto64,
3643 binop(Iop_16HLto32,
3644 binop(Iop_8HLto16,
3645 mkexpr(tmp[15]),
3646 mkexpr(tmp[14])),
3647 binop(Iop_8HLto16,
3648 mkexpr(tmp[13]),
3649 mkexpr(tmp[12]))),
3650 binop(Iop_16HLto32,
3651 binop(Iop_8HLto16,
3652 mkexpr(tmp[11]),
3653 mkexpr(tmp[10])),
3654 binop(Iop_8HLto16,
3655 mkexpr(tmp[9]),
3656 mkexpr(tmp[8])))),
3657 binop(Iop_32HLto64,
3658 binop(Iop_16HLto32,
3659 binop(Iop_8HLto16,
3660 mkexpr(tmp[7]),
3661 mkexpr(tmp[6])),
3662 binop(Iop_8HLto16,
3663 mkexpr(tmp[5]),
3664 mkexpr(tmp[4]))),
3665 binop(Iop_16HLto32,
3666 binop(Iop_8HLto16,
3667 mkexpr(tmp[3]),
3668 mkexpr(tmp[2])),
3669 binop(Iop_8HLto16,
3670 mkexpr(tmp[1]),
3671 mkexpr(tmp[0]))))));
3672 break;
3675 case 0x01: { /* SHF.H */
3676 DIP("SHF.H w%d, w%d, %d", wd, ws, i8);
3677 t1 = newTemp(Ity_V128);
3678 t2 = newTemp(Ity_V128);
3679 assign(t1, getWReg(wd));
3680 assign(t2, getWReg(ws));
3681 Int i;
3682 IRTemp tmp[8];
3684 for (i = 0; i < 8; i++) {
3685 tmp[i] = newTemp(Ity_I16);
3686 assign(tmp[i],
3687 binop(Iop_GetElem16x8, mkexpr(t2),
3688 mkU8(i - (i % 4) +
3689 ((i8 >> (i % 4) * 2) & 0x03))));
3692 putWReg(wd, binop(Iop_64HLtoV128,
3693 binop(Iop_32HLto64,
3694 binop(Iop_16HLto32,
3695 mkexpr(tmp[7]), mkexpr(tmp[6])),
3696 binop(Iop_16HLto32,
3697 mkexpr(tmp[5]), mkexpr(tmp[4]))),
3698 binop(Iop_32HLto64,
3699 binop(Iop_16HLto32,
3700 mkexpr(tmp[3]), mkexpr(tmp[2])),
3701 binop(Iop_16HLto32,
3702 mkexpr(tmp[1]), mkexpr(tmp[0])))));
3703 break;
3706 case 0x02: { /* SHF.W */
3707 DIP("SHF.W w%d, w%d, %d", wd, ws, i8);
3708 t1 = newTemp(Ity_V128);
3709 t2 = newTemp(Ity_V128);
3710 assign(t1, getWReg(wd));
3711 assign(t2, getWReg(ws));
3712 Int i;
3713 IRTemp tmp[4];
3715 for (i = 0; i < 4; i++) {
3716 tmp[i] = newTemp(Ity_I32);
3717 assign(tmp[i],
3718 binop(Iop_GetElem32x4, mkexpr(t2),
3719 mkU8(i - (i % 4) +
3720 ((i8 >> (i % 4) * 2) & 0x03))));
3723 putWReg(wd, binop(Iop_64HLtoV128,
3724 binop(Iop_32HLto64,
3725 mkexpr(tmp[3]), mkexpr(tmp[2])),
3726 binop(Iop_32HLto64,
3727 mkexpr(tmp[1]), mkexpr(tmp[0]))));
3728 break;
3731 default:
3732 return -1;
3735 return 0;
3738 static Int msa_I5_06(UInt cins, UChar wd, UChar ws) /* I5 (0x06) */
3740 IRTemp t1, t2, t3;
3741 UShort operation;
3742 UChar df, wt;
3744 operation = (cins & 0x03800000) >> 23;
3745 df = (cins & 0x00600000) >> 21;
3746 wt = (cins & 0x001F0000) >> 16;
3748 switch (operation) {
3749 case 0x00: { /* ADDVI */
3750 ULong tmp = wt;
3752 switch (df) {
3753 case 0x00: { /* ADDVI.B */
3754 DIP("ADDVI.B w%d, w%d, %d", wd, ws, wt);
3755 t1 = newTemp(Ity_V128);
3756 t2 = newTemp(Ity_V128);
3757 t3 = newTemp(Ity_V128);
3758 tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
3759 (tmp << 32) | (tmp << 24) | (tmp << 16) |
3760 (tmp << 8);
3761 assign(t1, getWReg(ws));
3762 assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
3763 assign(t3, binop(Iop_Add8x16, mkexpr(t1), mkexpr(t2)));
3764 putWReg(wd, mkexpr(t3));
3765 break;
3768 case 0x01: { /* ADDVI.H */
3769 DIP("ADDVI.H w%d, w%d, %d", wd, ws, wt);
3770 t1 = newTemp(Ity_V128);
3771 t2 = newTemp(Ity_V128);
3772 t3 = newTemp(Ity_V128);
3773 tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
3774 assign(t1, getWReg(ws));
3775 assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
3776 assign(t3, binop(Iop_Add16x8, mkexpr(t1), mkexpr(t2)));
3777 putWReg(wd, mkexpr(t3));
3778 break;
3781 case 0x02: { /* ADDVI.W */
3782 DIP("ADDVI.W w%d, w%d, %d", wd, ws, wt);
3783 t1 = newTemp(Ity_V128);
3784 t2 = newTemp(Ity_V128);
3785 t3 = newTemp(Ity_V128);
3786 tmp |= (tmp << 32);
3787 assign(t1, getWReg(ws));
3788 assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
3789 assign(t3, binop(Iop_Add32x4, mkexpr(t1), mkexpr(t2)));
3790 putWReg(wd, mkexpr(t3));
3791 break;
3794 case 0x03: { /* ADDVI.D */
3795 DIP("ADDVI.D w%d, w%d, %d", wd, ws, wt);
3796 t1 = newTemp(Ity_V128);
3797 t2 = newTemp(Ity_V128);
3798 t3 = newTemp(Ity_V128);
3799 assign(t1, getWReg(ws));
3800 assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
3801 assign(t3, binop(Iop_Add64x2, mkexpr(t1), mkexpr(t2)));
3802 putWReg(wd, mkexpr(t3));
3803 break;
3807 break;
3810 case 0x01: { /* SUBVI */
3811 ULong tmp = wt;
3813 switch (df) {
3814 case 0x00: { /* SUBVI.B */
3815 DIP("SUBVI.B w%d, w%d, %d", wd, ws, wt);
3816 t1 = newTemp(Ity_V128);
3817 t2 = newTemp(Ity_V128);
3818 t3 = newTemp(Ity_V128);
3819 tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
3820 (tmp << 32) | (tmp << 24) | (tmp << 16) |
3821 (tmp << 8);
3822 assign(t1, getWReg(ws));
3823 assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
3824 assign(t3, binop(Iop_Sub8x16, mkexpr(t1), mkexpr(t2)));
3825 putWReg(wd, mkexpr(t3));
3826 break;
3829 case 0x01: { /* SUBVI.H */
3830 DIP("SUBVI.H w%d, w%d, %d", wd, ws, wt);
3831 t1 = newTemp(Ity_V128);
3832 t2 = newTemp(Ity_V128);
3833 t3 = newTemp(Ity_V128);
3834 tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
3835 assign(t1, getWReg(ws));
3836 assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
3837 assign(t3, binop(Iop_Sub16x8, mkexpr(t1), mkexpr(t2)));
3838 putWReg(wd, mkexpr(t3));
3839 break;
3842 case 0x02: { /* SUBVI.W */
3843 DIP("SUBVI.W w%d, w%d, %d", wd, ws, wt);
3844 t1 = newTemp(Ity_V128);
3845 t2 = newTemp(Ity_V128);
3846 t3 = newTemp(Ity_V128);
3847 tmp |= (tmp << 32);
3848 assign(t1, getWReg(ws));
3849 assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
3850 assign(t3, binop(Iop_Sub32x4, mkexpr(t1), mkexpr(t2)));
3851 putWReg(wd, mkexpr(t3));
3852 break;
3855 case 0x03: { /* SUBVI.D */
3856 DIP("SUBVI.D w%d, w%d, %d", wd, ws, wt);
3857 t1 = newTemp(Ity_V128);
3858 t2 = newTemp(Ity_V128);
3859 t3 = newTemp(Ity_V128);
3860 assign(t1, getWReg(ws));
3861 assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
3862 assign(t3, binop(Iop_Sub64x2, mkexpr(t1), mkexpr(t2)));
3863 putWReg(wd, mkexpr(t3));
3864 break;
3868 break;
3871 case 0x02: { /* MAXI_S */
3872 ULong tmp = wt;
3874 switch (df) {
3875 case 0x00: { /* MAXI_S.B */
3876 DIP("MAXI_S.B w%d, w%d, %d", wd, ws, wt);
3877 t1 = newTemp(Ity_V128);
3878 t2 = newTemp(Ity_V128);
3879 t3 = newTemp(Ity_V128);
3880 char stemp = ((int)tmp << 27) >> 27;
3881 tmp = (UChar)stemp;
3882 tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
3883 (tmp << 32) | (tmp << 24) | (tmp << 16) |
3884 (tmp << 8);
3885 assign(t1, getWReg(ws));
3886 assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
3887 assign(t3, binop(Iop_Max8Sx16, mkexpr(t1), mkexpr(t2)));
3888 putWReg(wd, mkexpr(t3));
3889 break;
3892 case 0x01: { /* MAXI_S.H */
3893 DIP("MAXI_S.H w%d, w%d, %d", wd, ws, wt);
3894 t1 = newTemp(Ity_V128);
3895 t2 = newTemp(Ity_V128);
3896 t3 = newTemp(Ity_V128);
3897 short stemp = ((int)tmp << 27) >> 27;
3898 tmp = (UShort)stemp;
3899 tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
3900 assign(t1, getWReg(ws));
3901 assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
3902 assign(t3, binop(Iop_Max16Sx8, mkexpr(t1), mkexpr(t2)));
3903 putWReg(wd, mkexpr(t3));
3904 break;
3907 case 0x02: { /* MAXI_S.W */
3908 DIP("MAXI_S.W w%d, w%d, %d", wd, ws, wt);
3909 t1 = newTemp(Ity_V128);
3910 t2 = newTemp(Ity_V128);
3911 t3 = newTemp(Ity_V128);
3912 int stemp = ((int)tmp << 27) >> 27;
3913 tmp = (UInt)stemp;
3914 tmp |= (tmp << 32);
3915 assign(t1, getWReg(ws));
3916 assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
3917 assign(t3, binop(Iop_Max32Sx4, mkexpr(t1), mkexpr(t2)));
3918 putWReg(wd, mkexpr(t3));
3919 break;
3922 case 0x03: { /* MAXI_S.D */
3923 DIP("MAXI_S.D w%d, w%d, %d", wd, ws, wt);
3924 t1 = newTemp(Ity_V128);
3925 t2 = newTemp(Ity_V128);
3926 t3 = newTemp(Ity_V128);
3927 Long stemp = ((Long)tmp << 59) >> 59;
3928 tmp = stemp;
3929 assign(t1, getWReg(ws));
3930 assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
3931 assign(t3, binop(Iop_Max64Sx2, mkexpr(t1), mkexpr(t2)));
3932 putWReg(wd, mkexpr(t3));
3933 break;
3937 break;
3940 case 0x03: { /* MAXI_U */
3941 ULong tmp = wt;
3943 switch (df) {
3944 case 0x00: { /* MAXI_U.B */
3945 DIP("MAXI_U.B w%d, w%d, %d", wd, ws, wt);
3946 t1 = newTemp(Ity_V128);
3947 t2 = newTemp(Ity_V128);
3948 t3 = newTemp(Ity_V128);
3949 tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
3950 (tmp << 32) | (tmp << 24) | (tmp << 16) |
3951 (tmp << 8);
3952 assign(t1, getWReg(ws));
3953 assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
3954 assign(t3, binop(Iop_Max8Ux16, mkexpr(t1), mkexpr(t2)));
3955 putWReg(wd, mkexpr(t3));
3956 break;
3959 case 0x01: { /* MAXI_U.H */
3960 DIP("MAXI_U.H w%d, w%d, %d", wd, ws, wt);
3961 t1 = newTemp(Ity_V128);
3962 t2 = newTemp(Ity_V128);
3963 t3 = newTemp(Ity_V128);
3964 tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
3965 assign(t1, getWReg(ws));
3966 assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
3967 assign(t3, binop(Iop_Max16Ux8, mkexpr(t1), mkexpr(t2)));
3968 putWReg(wd, mkexpr(t3));
3969 break;
3972 case 0x02: { /* MAXI_U.W */
3973 DIP("MAXI_U.W w%d, w%d, %d", wd, ws, wt);
3974 t1 = newTemp(Ity_V128);
3975 t2 = newTemp(Ity_V128);
3976 t3 = newTemp(Ity_V128);
3977 tmp |= (tmp << 32);
3978 assign(t1, getWReg(ws));
3979 assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
3980 assign(t3, binop(Iop_Max32Ux4, mkexpr(t1), mkexpr(t2)));
3981 putWReg(wd, mkexpr(t3));
3982 break;
3985 case 0x03: { /* MAXI_U.D */
3986 DIP("MAXI_U.D w%d, w%d, %d", wd, ws, wt);
3987 t1 = newTemp(Ity_V128);
3988 t2 = newTemp(Ity_V128);
3989 t3 = newTemp(Ity_V128);
3990 assign(t1, getWReg(ws));
3991 assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
3992 assign(t3, binop(Iop_Max64Ux2, mkexpr(t1), mkexpr(t2)));
3993 putWReg(wd, mkexpr(t3));
3994 break;
3998 break;
4001 case 0x04: { /* MINI_S */
4002 ULong tmp = wt;
4004 switch (df) {
4005 case 0x00: { /* MINI_S.B */
4006 DIP("MINI_S.B w%d, w%d, %d", wd, ws, wt);
4007 t1 = newTemp(Ity_V128);
4008 t2 = newTemp(Ity_V128);
4009 t3 = newTemp(Ity_V128);
4010 char stemp = ((int)tmp << 27) >> 27;
4011 tmp = (UChar)stemp;
4012 tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
4013 (tmp << 32) | (tmp << 24) | (tmp << 16) |
4014 (tmp << 8);
4015 assign(t1, getWReg(ws));
4016 assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
4017 assign(t3, binop(Iop_Min8Sx16, mkexpr(t1), mkexpr(t2)));
4018 putWReg(wd, mkexpr(t3));
4019 break;
4022 case 0x01: { /* MINI_S.H */
4023 DIP("MINI_S.H w%d, w%d, %d", wd, ws, wt);
4024 t1 = newTemp(Ity_V128);
4025 t2 = newTemp(Ity_V128);
4026 t3 = newTemp(Ity_V128);
4027 short stemp = ((int)tmp << 27) >> 27;
4028 tmp = (UShort)stemp;
4029 tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
4030 assign(t1, getWReg(ws));
4031 assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
4032 assign(t3, binop(Iop_Min16Sx8, mkexpr(t1), mkexpr(t2)));
4033 putWReg(wd, mkexpr(t3));
4034 break;
4037 case 0x02: { /* MINI_S.W */
4038 DIP("MINI_S.W w%d, w%d, %d", wd, ws, wt);
4039 t1 = newTemp(Ity_V128);
4040 t2 = newTemp(Ity_V128);
4041 t3 = newTemp(Ity_V128);
4042 int stemp = ((int)tmp << 27) >> 27;
4043 tmp = (UInt)stemp;
4044 tmp |= (tmp << 32);
4045 assign(t1, getWReg(ws));
4046 assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
4047 assign(t3, binop(Iop_Min32Sx4, mkexpr(t1), mkexpr(t2)));
4048 putWReg(wd, mkexpr(t3));
4049 break;
4052 case 0x03: { /* MINI_S.D */
4053 DIP("MINI_S.D w%d, w%d, %d", wd, ws, wt);
4054 t1 = newTemp(Ity_V128);
4055 t2 = newTemp(Ity_V128);
4056 t3 = newTemp(Ity_V128);
4057 Long stemp = ((Long)tmp << 59) >> 59;
4058 tmp = stemp;
4059 assign(t1, getWReg(ws));
4060 assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
4061 assign(t3, binop(Iop_Min64Sx2, mkexpr(t1), mkexpr(t2)));
4062 putWReg(wd, mkexpr(t3));
4063 break;
4067 break;
4070 case 0x05: { /* MINI_U */
4071 ULong tmp = wt;
4073 switch (df) {
4074 case 0x00: { /* MINI_U.B */
4075 DIP("MINI_U.B w%d, w%d, %d", wd, ws, wt);
4076 t1 = newTemp(Ity_V128);
4077 t2 = newTemp(Ity_V128);
4078 t3 = newTemp(Ity_V128);
4079 tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
4080 (tmp << 32) | (tmp << 24) | (tmp << 16) |
4081 (tmp << 8);
4082 assign(t1, getWReg(ws));
4083 assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
4084 assign(t3, binop(Iop_Min8Ux16, mkexpr(t1), mkexpr(t2)));
4085 putWReg(wd, mkexpr(t3));
4086 break;
4089 case 0x01: { /* MINI_U.H */
4090 DIP("MINI_U.H w%d, w%d, %d", wd, ws, wt);
4091 t1 = newTemp(Ity_V128);
4092 t2 = newTemp(Ity_V128);
4093 t3 = newTemp(Ity_V128);
4094 tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
4095 assign(t1, getWReg(ws));
4096 assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
4097 assign(t3, binop(Iop_Min16Ux8, mkexpr(t1), mkexpr(t2)));
4098 putWReg(wd, mkexpr(t3));
4099 break;
4102 case 0x02: { /* MINI_U.W */
4103 DIP("MINI_U.W w%d, w%d, %d", wd, ws, wt);
4104 t1 = newTemp(Ity_V128);
4105 t2 = newTemp(Ity_V128);
4106 t3 = newTemp(Ity_V128);
4107 tmp |= (tmp << 32);
4108 assign(t1, getWReg(ws));
4109 assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
4110 assign(t3, binop(Iop_Min32Ux4, mkexpr(t1), mkexpr(t2)));
4111 putWReg(wd, mkexpr(t3));
4112 break;
4115 case 0x03: { /* MINI_U.D */
4116 DIP("MINI_U.D w%d, w%d, %d", wd, ws, wt);
4117 t1 = newTemp(Ity_V128);
4118 t2 = newTemp(Ity_V128);
4119 t3 = newTemp(Ity_V128);
4120 assign(t1, getWReg(ws));
4121 assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
4122 assign(t3, binop(Iop_Min64Ux2, mkexpr(t1), mkexpr(t2)));
4123 putWReg(wd, mkexpr(t3));
4124 break;
4128 break;
4131 default: {
4132 return -1;
4136 return 0;
4139 static Int msa_I5_07(UInt cins, UChar wd, UChar ws) /* I5 (0x07) / I10 */
4141 IRTemp t1, t2, t3;
4142 UShort operation;
4143 UChar df, i5;
4145 operation = (cins & 0x03800000) >> 23;
4146 df = (cins & 0x00600000) >> 21;
4147 i5 = (cins & 0x001F0000) >> 16;
4149 switch (operation) {
4150 case 0x00: {
4151 ULong tmp = i5;
4153 switch (df) {
4154 case 0x00: { /* CEQI.B */
4155 DIP("CEQI.B w%d, w%d, %d", wd, ws, i5);
4156 t1 = newTemp(Ity_V128);
4157 t2 = newTemp(Ity_V128);
4158 t3 = newTemp(Ity_V128);
4159 char stemp = ((int)tmp << 27) >> 27;
4160 tmp = (UChar)stemp;
4161 tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
4162 (tmp << 32) | (tmp << 24) | (tmp << 16) |
4163 (tmp << 8);
4164 assign(t1, getWReg(ws));
4165 assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
4166 assign(t3, binop(Iop_CmpEQ8x16, mkexpr(t1), mkexpr(t2)));
4167 putWReg(wd, mkexpr(t3));
4168 break;
4171 case 0x01: { /* CEQI.H */
4172 DIP("CEQI.H w%d, w%d, %d", wd, ws, i5);
4173 t1 = newTemp(Ity_V128);
4174 t2 = newTemp(Ity_V128);
4175 t3 = newTemp(Ity_V128);
4176 short stemp = ((int)tmp << 27) >> 27;
4177 tmp = (UShort)stemp;
4178 tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
4179 assign(t1, getWReg(ws));
4180 assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
4181 assign(t3, binop(Iop_CmpEQ16x8, mkexpr(t1), mkexpr(t2)));
4182 putWReg(wd, mkexpr(t3));
4183 break;
4186 case 0x02: { /* CEQI.W */
4187 DIP("CEQI.W w%d, w%d, %d", wd, ws, i5);
4188 t1 = newTemp(Ity_V128);
4189 t2 = newTemp(Ity_V128);
4190 t3 = newTemp(Ity_V128);
4191 int stemp = ((int)tmp << 27) >> 27;
4192 tmp = (UInt)stemp;
4193 tmp |= (tmp << 32);
4194 assign(t1, getWReg(ws));
4195 assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
4196 assign(t3, binop(Iop_CmpEQ32x4, mkexpr(t1), mkexpr(t2)));
4197 putWReg(wd, mkexpr(t3));
4198 break;
4201 case 0x03: { /* CEQI.D */
4202 DIP("CEQI.D w%d, w%d, %d", wd, ws, i5);
4203 t1 = newTemp(Ity_V128);
4204 t2 = newTemp(Ity_V128);
4205 t3 = newTemp(Ity_V128);
4206 Long stemp = ((Long)tmp << 59) >> 59;
4207 tmp = stemp;
4208 assign(t1, getWReg(ws));
4209 assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
4210 assign(t3, binop(Iop_CmpEQ64x2, mkexpr(t1), mkexpr(t2)));
4211 putWReg(wd, mkexpr(t3));
4212 break;
4216 break;
4219 case 0x02: { /* CLTI_S.df */
4220 ULong tmp = i5;
4222 switch (df) {
4223 case 0x00: { /* CLTI_S.B */
4224 DIP("CLTI_S.B w%d, w%d, %d", wd, ws, i5);
4225 t1 = newTemp(Ity_V128);
4226 t2 = newTemp(Ity_V128);
4227 t3 = newTemp(Ity_V128);
4228 char stemp = ((int)tmp << 27) >> 27;
4229 tmp = (UChar)stemp;
4230 tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
4231 (tmp << 32) | (tmp << 24) | (tmp << 16) |
4232 (tmp << 8);
4233 assign(t1, getWReg(ws));
4234 assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
4235 assign(t3, binop(Iop_CmpGT8Sx16, mkexpr(t2), mkexpr(t1)));
4236 putWReg(wd, mkexpr(t3));
4237 break;
4240 case 0x01: { /* CLTI_S.H */
4241 DIP("CLTI_S.H w%d, w%d, %d", wd, ws, i5);
4242 t1 = newTemp(Ity_V128);
4243 t2 = newTemp(Ity_V128);
4244 t3 = newTemp(Ity_V128);
4245 short stemp = ((int)tmp << 27) >> 27;
4246 tmp = (UShort)stemp;
4247 tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
4248 assign(t1, getWReg(ws));
4249 assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
4250 assign(t3, binop(Iop_CmpGT16Sx8, mkexpr(t2), mkexpr(t1)));
4251 putWReg(wd, mkexpr(t3));
4252 break;
4255 case 0x02: { /* CLTI_S.W */
4256 DIP("CLTI_S.W w%d, w%d, %d", wd, ws, i5);
4257 t1 = newTemp(Ity_V128);
4258 t2 = newTemp(Ity_V128);
4259 t3 = newTemp(Ity_V128);
4260 int stemp = ((int)tmp << 27) >> 27;
4261 tmp = (UInt)stemp;
4262 tmp |= (tmp << 32);
4263 assign(t1, getWReg(ws));
4264 assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
4265 assign(t3, binop(Iop_CmpGT32Sx4, mkexpr(t2), mkexpr(t1)));
4266 putWReg(wd, mkexpr(t3));
4267 break;
4270 case 0x03: { /* CLTI_S.D */
4271 DIP("CLTI_S.D w%d, w%d, %d", wd, ws, i5);
4272 t1 = newTemp(Ity_V128);
4273 t2 = newTemp(Ity_V128);
4274 t3 = newTemp(Ity_V128);
4275 Long stemp = ((Long)tmp << 59) >> 59;
4276 tmp = stemp;
4277 assign(t1, getWReg(ws));
4278 assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
4279 assign(t3, binop(Iop_CmpGT64Sx2, mkexpr(t2), mkexpr(t1)));
4280 putWReg(wd, mkexpr(t3));
4281 break;
4284 default:
4285 return -1;
4288 break;
4291 case 0x03: { /* CLTI_U.df */
4292 ULong tmp = i5;
4294 switch (df) {
4295 case 0x00: { /* CLTI_U.B */
4296 DIP("CLTI_U.B w%d, w%d, %d", wd, ws, i5);
4297 t1 = newTemp(Ity_V128);
4298 t2 = newTemp(Ity_V128);
4299 t3 = newTemp(Ity_V128);
4300 tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
4301 (tmp << 32) | (tmp << 24) | (tmp << 16) |
4302 (tmp << 8);
4303 assign(t1, getWReg(ws));
4304 assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
4305 assign(t3, binop(Iop_CmpGT8Ux16, mkexpr(t2), mkexpr(t1)));
4306 putWReg(wd, mkexpr(t3));
4307 break;
4310 case 0x01: { /* CLTI_U.H */
4311 DIP("CLTI_U.H w%d, w%d, %d", wd, ws, i5);
4312 t1 = newTemp(Ity_V128);
4313 t2 = newTemp(Ity_V128);
4314 t3 = newTemp(Ity_V128);
4315 tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
4316 assign(t1, getWReg(ws));
4317 assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
4318 assign(t3, binop(Iop_CmpGT16Ux8, mkexpr(t2), mkexpr(t1)));
4319 putWReg(wd, mkexpr(t3));
4320 break;
4323 case 0x02: { /* CLTI_U.W */
4324 DIP("CLTI_U.W w%d, w%d, %d", wd, ws, i5);
4325 t1 = newTemp(Ity_V128);
4326 t2 = newTemp(Ity_V128);
4327 t3 = newTemp(Ity_V128);
4328 tmp |= (tmp << 32);
4329 assign(t1, getWReg(ws));
4330 assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
4331 assign(t3, binop(Iop_CmpGT32Ux4, mkexpr(t2), mkexpr(t1)));
4332 putWReg(wd, mkexpr(t3));
4333 break;
4336 case 0x03: { /* CLTI_U.D */
4337 DIP("CLTI_U.D w%d, w%d, %d", wd, ws, i5);
4338 t1 = newTemp(Ity_V128);
4339 t2 = newTemp(Ity_V128);
4340 t3 = newTemp(Ity_V128);
4341 assign(t1, getWReg(ws));
4342 assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
4343 assign(t3, binop(Iop_CmpGT64Ux2, mkexpr(t2), mkexpr(t1)));
4344 putWReg(wd, mkexpr(t3));
4345 break;
4349 break;
4352 case 0x04: { /* CLEI_S.df */
4353 ULong tmp = i5;
4355 switch (df) {
4356 case 0x00: { /* CLEI_S.B */
4357 DIP("CLEI_S.B w%d, w%d, %d", wd, ws, i5);
4358 t1 = newTemp(Ity_V128);
4359 t2 = newTemp(Ity_V128);
4360 t3 = newTemp(Ity_V128);
4361 char stemp = ((int)tmp << 27) >> 27;
4362 tmp = (UChar)stemp;
4363 tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
4364 (tmp << 32) | (tmp << 24) | (tmp << 16) |
4365 (tmp << 8);
4366 assign(t1, getWReg(ws));
4367 assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
4368 assign(t3, binop(Iop_OrV128, binop(Iop_CmpGT8Sx16,
4369 mkexpr(t2), mkexpr(t1)),
4370 binop(Iop_CmpEQ8x16,
4371 mkexpr(t1), mkexpr(t2))));
4372 putWReg(wd, mkexpr(t3));
4373 break;
4376 case 0x01: { /* CLEI_S.H */
4377 DIP("CLEI_S.H w%d, w%d, %d", wd, ws, i5);
4378 t1 = newTemp(Ity_V128);
4379 t2 = newTemp(Ity_V128);
4380 t3 = newTemp(Ity_V128);
4381 short stemp = ((int)tmp << 27) >> 27;
4382 tmp = (UShort)stemp;
4383 tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
4384 assign(t1, getWReg(ws));
4385 assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
4386 assign(t3, binop(Iop_OrV128, binop(Iop_CmpGT16Sx8,
4387 mkexpr(t2), mkexpr(t1)),
4388 binop(Iop_CmpEQ16x8,
4389 mkexpr(t1), mkexpr(t2))));
4390 putWReg(wd, mkexpr(t3));
4391 break;
4394 case 0x02: { /* CLEI_S.W */
4395 DIP("CLEI_S.W w%d, w%d, %d", wd, ws, i5);
4396 t1 = newTemp(Ity_V128);
4397 t2 = newTemp(Ity_V128);
4398 t3 = newTemp(Ity_V128);
4399 int stemp = ((int)tmp << 27) >> 27;
4400 tmp = (UInt)stemp;
4401 tmp |= (tmp << 32);
4402 assign(t1, getWReg(ws));
4403 assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
4404 assign(t3, binop(Iop_OrV128,
4405 binop(Iop_CmpGT32Sx4,
4406 mkexpr(t2), mkexpr(t1)),
4407 binop(Iop_CmpEQ32x4,
4408 mkexpr(t1), mkexpr(t2))));
4409 putWReg(wd, mkexpr(t3));
4410 break;
4413 case 0x03: { /* CLEI_S.D */
4414 DIP("CLEI_S.D w%d, w%d, %d", wd, ws, i5);
4415 t1 = newTemp(Ity_V128);
4416 t2 = newTemp(Ity_V128);
4417 t3 = newTemp(Ity_V128);
4418 Long stemp = ((Long)tmp << 59) >> 59;
4419 tmp = stemp;
4420 assign(t1, getWReg(ws));
4421 assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
4422 assign(t3, binop(Iop_OrV128,
4423 binop(Iop_CmpGT64Sx2,
4424 mkexpr(t2), mkexpr(t1)),
4425 binop(Iop_CmpEQ64x2,
4426 mkexpr(t1), mkexpr(t2))));
4427 putWReg(wd, mkexpr(t3));
4428 break;
4431 default:
4432 return -1;
4435 break;
4438 case 0x05: { /* CLEI_U.df */
4439 ULong tmp = i5;
4441 switch (df) {
4442 case 0x00: { /* CLEI_U.B */
4443 DIP("CLEI_U.B w%d, w%d, %d", wd, ws, i5);
4444 t1 = newTemp(Ity_V128);
4445 t2 = newTemp(Ity_V128);
4446 t3 = newTemp(Ity_V128);
4447 tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
4448 (tmp << 32) | (tmp << 24) | (tmp << 16) |
4449 (tmp << 8);
4450 assign(t1, getWReg(ws));
4451 assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
4452 assign(t3, binop(Iop_OrV128,
4453 binop(Iop_CmpGT8Ux16,
4454 mkexpr(t2), mkexpr(t1)),
4455 binop(Iop_CmpEQ8x16,
4456 mkexpr(t1), mkexpr(t2))));
4457 putWReg(wd, mkexpr(t3));
4458 break;
4461 case 0x01: { /* CLEI_U.H */
4462 DIP("CLEI_U.H w%d, w%d, %d", wd, ws, i5);
4463 t1 = newTemp(Ity_V128);
4464 t2 = newTemp(Ity_V128);
4465 t3 = newTemp(Ity_V128);
4466 tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
4467 assign(t1, getWReg(ws));
4468 assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
4469 assign(t3, binop(Iop_OrV128,
4470 binop(Iop_CmpGT16Ux8,
4471 mkexpr(t2), mkexpr(t1)),
4472 binop(Iop_CmpEQ16x8,
4473 mkexpr(t1), mkexpr(t2))));
4474 putWReg(wd, mkexpr(t3));
4475 break;
4478 case 0x02: { /* CLEI_U.W */
4479 DIP("CLEI_U.W w%d, w%d, %d", wd, ws, i5);
4480 t1 = newTemp(Ity_V128);
4481 t2 = newTemp(Ity_V128);
4482 t3 = newTemp(Ity_V128);
4483 tmp |= (tmp << 32);
4484 assign(t1, getWReg(ws));
4485 assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
4486 assign(t3, binop(Iop_OrV128,
4487 binop(Iop_CmpGT32Ux4,
4488 mkexpr(t2), mkexpr(t1)),
4489 binop(Iop_CmpEQ32x4,
4490 mkexpr(t1), mkexpr(t2))));
4491 putWReg(wd, mkexpr(t3));
4492 break;
4495 case 0x03: { /* CLEI_U.D */
4496 DIP("CLEI_U.D w%d, w%d, %d", wd, ws, i5);
4497 t1 = newTemp(Ity_V128);
4498 t2 = newTemp(Ity_V128);
4499 t3 = newTemp(Ity_V128);
4500 assign(t1, getWReg(ws));
4501 assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
4502 assign(t3, binop(Iop_OrV128,
4503 binop(Iop_CmpGT64Ux2,
4504 mkexpr(t2), mkexpr(t1)),
4505 binop(Iop_CmpEQ64x2,
4506 mkexpr(t1), mkexpr(t2))));
4507 putWReg(wd, mkexpr(t3));
4508 break;
4512 break;
4515 case 0x06: { /* LDI.df */
4516 ULong tmp;
4517 UShort s10;
4518 s10 = (cins & 0x001FF800) >> 11;
4520 switch (df) {
4521 case 0x00: /* LDI.B */
4522 DIP("LDI.B w%d, %d", wd, s10);
4523 tmp = s10 & 0xFFl;
4524 tmp = tmp | (tmp << 8) | (tmp << 16) | (tmp << 24)
4525 | (tmp << 32) | (tmp << 40) | (tmp << 48) |
4526 (tmp << 56);
4527 break;
4529 case 0x01: /* LDI.H */
4530 DIP("LDI.H w%d, %d", wd, s10);
4531 tmp = extend_s_10to16(s10);
4532 tmp = tmp | (tmp << 16) | (tmp << 32) | (tmp << 48);
4533 break;
4535 case 0x02: /* LDI.W */
4536 DIP("LDI.W w%d, %d", wd, s10);
4537 tmp = extend_s_10to32(s10);
4538 tmp = tmp | (tmp << 32);
4539 break;
4541 case 0x03: /* LDI.D */
4542 DIP("LDI.D w%d, %d", wd, s10);
4543 tmp = extend_s_10to64(s10);
4544 break;
4546 default:
4547 return -1;
4550 putWReg(wd, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
4551 break;
4554 default:
4555 return -1;
4558 return 0;
4561 static Int msa_BIT_09(UInt cins, UChar wd, UChar ws) /* BIT (0x09) */
4563 IRTemp t1, t2, t3;
4564 UShort operation;
4565 UChar df, m;
4567 operation = (cins & 0x03800000) >> 23;
4568 df = (cins & 0x007F0000) >> 16;
4570 if ((df & 0x70) == 0x70) { // 111mmmm; b
4571 m = df & 0x07;
4572 df = 0;
4573 } else if ((df & 0x60) == 0x60) { // 110mmmm; h
4574 m = df & 0x0F;
4575 df = 1;
4576 } else if ((df & 0x40) == 0x40) { // 10mmmmm; w
4577 m = df & 0x1F;
4578 df = 2;
4579 } else if ((df & 0x00) == 0x00) { // 0mmmmmm; d
4580 m = df & 0x3F;
4581 df = 3;
4584 switch (operation) {
4585 case 0x00: { /* SLLI.df */
4586 switch (df) {
4587 case 0x00: { /* SLLI.B */
4588 DIP("SLLI.B w%d, w%d, %d", wd, ws, m);
4589 putWReg(wd, binop(Iop_ShlN8x16, getWReg(ws), mkU8(m)));
4590 break;
4593 case 0x01: { /* SLLI.H */
4594 DIP("SLLI.H w%d, w%d, %d", wd, ws, m);
4595 putWReg(wd, binop(Iop_ShlN16x8, getWReg(ws), mkU8(m)));
4596 break;
4599 case 0x02: { /* SLLI.W */
4600 DIP("SLLI.W w%d, w%d, %d", wd, ws, m);
4601 putWReg(wd, binop(Iop_ShlN32x4, getWReg(ws), mkU8(m)));
4602 break;
4605 case 0x03: { /* SLLI.D */
4606 DIP("SLLI.D w%d, w%d, %d", wd, ws, m);
4607 putWReg(wd, binop(Iop_ShlN64x2, getWReg(ws), mkU8(m)));
4608 break;
4612 break;
4615 case 0x01: { /* SRAI.df */
4616 switch (df) {
4617 case 0x00: { /* SRAI.B */
4618 DIP("SRAI.B w%d, w%d, %d", wd, ws, m);
4619 putWReg(wd, binop(Iop_SarN8x16, getWReg(ws), mkU8(m)));
4620 break;
4623 case 0x01: { /* SRAI.H */
4624 DIP("SRAI.H w%d, w%d, %d", wd, ws, m);
4625 putWReg(wd, binop(Iop_SarN16x8, getWReg(ws), mkU8(m)));
4626 break;
4629 case 0x02: { /* SRAI.W */
4630 DIP("SRAI.W w%d, w%d, %d", wd, ws, m);
4631 putWReg(wd, binop(Iop_SarN32x4, getWReg(ws), mkU8(m)));
4632 break;
4635 case 0x03: { /* SRAI.D */
4636 DIP("SRAI.D w%d, w%d, %d", wd, ws, m);
4637 putWReg(wd, binop(Iop_SarN64x2, getWReg(ws), mkU8(m)));
4638 break;
4642 break;
4645 case 0x02: { /* SRLI.df */
4646 switch (df) {
4647 case 0x00: { /* SRLI.B */
4648 DIP("SRLI.B w%d, w%d, %d", wd, ws, m);
4649 putWReg(wd, binop(Iop_ShrN8x16, getWReg(ws), mkU8(m)));
4650 break;
4653 case 0x01: { /* SRLI.H */
4654 DIP("SRLI.H w%d, w%d, %d", wd, ws, m);
4655 putWReg(wd, binop(Iop_ShrN16x8, getWReg(ws), mkU8(m)));
4656 break;
4659 case 0x02: { /* SRLI.W */
4660 DIP("SRLI.W w%d, w%d, %d", wd, ws, m);
4661 putWReg(wd, binop(Iop_ShrN32x4, getWReg(ws), mkU8(m)));
4662 break;
4665 case 0x03: { /* SRLI.D */
4666 DIP("SRLI.D w%d, w%d, %d", wd, ws, m);
4667 putWReg(wd, binop(Iop_ShrN64x2, getWReg(ws), mkU8(m)));
4668 break;
4672 break;
4675 case 0x03: { /* BCLRI.df */
4676 t1 = newTemp(Ity_V128);
4677 t2 = newTemp(Ity_V128);
4678 t3 = newTemp(Ity_V128);
4679 ULong tmp = 1;
4680 assign(t1, getWReg(ws));
4682 switch (df) {
4683 case 0x00: { /* BCLRI.B */
4684 DIP("BCLRI.B w%d, w%d, %d", wd, ws, m);
4685 tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
4686 (tmp << 32) | (tmp << 24) | (tmp << 16) |
4687 (tmp << 8);
4688 assign(t2, binop(Iop_ShlN8x16,
4689 binop(Iop_64HLtoV128,
4690 mkU64(tmp), mkU64(tmp)), mkU8(m)));
4691 break;
4694 case 0x01: { /* BCLRI.H */
4695 DIP("BCLRI.H w%d, w%d, %d", wd, ws, m);
4696 tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
4697 assign(t2, binop(Iop_ShlN16x8,
4698 binop(Iop_64HLtoV128,
4699 mkU64(tmp), mkU64(tmp)), mkU8(m)));
4700 break;
4703 case 0x02: { /* BCLRI.W */
4704 DIP("BCLRI.W w%d, w%d, %d", wd, ws, m);
4705 tmp |= (tmp << 32);
4706 assign(t2, binop(Iop_ShlN32x4,
4707 binop(Iop_64HLtoV128,
4708 mkU64(tmp), mkU64(tmp)), mkU8(m)));
4709 break;
4712 case 0x03: { /* BCLRI.D */
4713 DIP("BCLRI.D w%d, w%d, %d", wd, ws, m);
4714 assign(t2, binop(Iop_ShlN64x2,
4715 binop(Iop_64HLtoV128,
4716 mkU64(tmp), mkU64(tmp)), mkU8(m)));
4717 break;
4721 assign(t3, binop(Iop_AndV128,
4722 mkexpr(t1), unop(Iop_NotV128, mkexpr(t2))));
4723 putWReg(wd, mkexpr(t3));
4724 break;
4727 case 0x04: { /* BSETI */
4728 t1 = newTemp(Ity_V128);
4729 t2 = newTemp(Ity_V128);
4730 t3 = newTemp(Ity_V128);
4731 ULong tmp = 1;
4732 assign(t1, getWReg(ws));
4734 switch (df) {
4735 case 0x00: { /* BSETI.B */
4736 DIP("BSETI.B w%d, w%d, %d", wd, ws, m);
4737 tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
4738 (tmp << 32) | (tmp << 24) | (tmp << 16) |
4739 (tmp << 8);
4740 assign(t2, binop(Iop_ShlN8x16,
4741 binop(Iop_64HLtoV128,
4742 mkU64(tmp), mkU64(tmp)), mkU8(m)));
4743 break;
4746 case 0x01: { /* BSETI.H */
4747 DIP("BSETI.H w%d, w%d, %d", wd, ws, m);
4748 tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
4749 assign(t2, binop(Iop_ShlN16x8,
4750 binop(Iop_64HLtoV128,
4751 mkU64(tmp), mkU64(tmp)), mkU8(m)));
4752 break;
4755 case 0x02: { /* BSETI.W */
4756 DIP("BSETI.W w%d, w%d, %d", wd, ws, m);
4757 tmp |= (tmp << 32);
4758 assign(t2, binop(Iop_ShlN32x4,
4759 binop(Iop_64HLtoV128,
4760 mkU64(tmp), mkU64(tmp)), mkU8(m)));
4761 break;
4764 case 0x03: { /* BSETI.D */
4765 DIP("BSETI.D w%d, w%d, %d", wd, ws, m);
4766 assign(t2, binop(Iop_ShlN64x2,
4767 binop(Iop_64HLtoV128,
4768 mkU64(tmp), mkU64(tmp)), mkU8(m)));
4769 break;
4773 assign(t3, binop(Iop_OrV128, mkexpr(t1), mkexpr(t2)));
4774 putWReg(wd, mkexpr(t3));
4775 break;
4778 case 0x05: { /* BNEGI.df */
4779 t1 = newTemp(Ity_V128);
4780 t2 = newTemp(Ity_V128);
4781 t3 = newTemp(Ity_V128);
4782 ULong tmp = 1;
4783 assign(t1, getWReg(ws));
4785 switch (df) {
4786 case 0x00: { /* BNEGI.B */
4787 DIP("BNEGI.B w%d, w%d, %d", wd, ws, m);
4788 tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
4789 (tmp << 32) | (tmp << 24) | (tmp << 16) |
4790 (tmp << 8);
4791 assign(t2, binop(Iop_ShlN8x16,
4792 binop(Iop_64HLtoV128,
4793 mkU64(tmp), mkU64(tmp)), mkU8(m)));
4794 break;
4797 case 0x01: { /* BNEGI.H */
4798 DIP("BNEGI.H w%d, w%d, %d", wd, ws, m);
4799 tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
4800 assign(t2, binop(Iop_ShlN16x8,
4801 binop(Iop_64HLtoV128,
4802 mkU64(tmp), mkU64(tmp)), mkU8(m)));
4803 break;
4806 case 0x02: { /* BNEGI.W */
4807 DIP("BNEGI.W w%d, w%d, %d", wd, ws, m);
4808 tmp |= (tmp << 32);
4809 assign(t2, binop(Iop_ShlN32x4,
4810 binop(Iop_64HLtoV128,
4811 mkU64(tmp), mkU64(tmp)), mkU8(m)));
4812 break;
4815 case 0x03: { /* BNEGI.D */
4816 DIP("BNEGI.D w%d, w%d, %d", wd, ws, m);
4817 assign(t2, binop(Iop_ShlN64x2,
4818 binop(Iop_64HLtoV128,
4819 mkU64(tmp), mkU64(tmp)), mkU8(m)));
4820 break;
4824 assign(t3, binop(Iop_XorV128, mkexpr(t1), mkexpr(t2)));
4825 putWReg(wd, mkexpr(t3));
4826 break;
4829 case 0x06: { /* BINSLI.df */
4830 switch (df) {
4831 case 0x00: { /* BINSLI.B */
4832 DIP("BINSLI.B w%d, w%d, w%d", wd, ws, m);
4833 t1 = newTemp(Ity_V128);
4834 t2 = newTemp(Ity_V128);
4835 t3 = newTemp(Ity_V128);
4836 ULong tmp = 0x8080808080808080ULL;
4837 assign(t1, binop(Iop_SarN8x16,
4838 binop(Iop_64HLtoV128,
4839 mkU64(tmp), mkU64(tmp)), mkU8(m)));
4840 assign(t2,
4841 binop(Iop_AndV128,
4842 unop(Iop_NotV128, mkexpr(t1)), getWReg(wd)));
4843 assign(t3,
4844 binop(Iop_AndV128,
4845 mkexpr(t1), getWReg(ws)));
4846 putWReg(wd,
4847 binop(Iop_OrV128,
4848 mkexpr(t2), mkexpr(t3)));
4849 break;
4852 case 0x01: { /* BINSLI.H */
4853 DIP("BINSLI.H w%d, w%d, w%d", wd, ws, m);
4854 t1 = newTemp(Ity_V128);
4855 t2 = newTemp(Ity_V128);
4856 t3 = newTemp(Ity_V128);
4857 ULong tmp = 0x8000800080008000ULL;
4858 assign(t1,
4859 binop(Iop_SarN16x8,
4860 binop(Iop_64HLtoV128,
4861 mkU64(tmp), mkU64(tmp)), mkU8(m)));
4862 assign(t2,
4863 binop(Iop_AndV128,
4864 unop(Iop_NotV128, mkexpr(t1)), getWReg(wd)));
4865 assign(t3,
4866 binop(Iop_AndV128,
4867 mkexpr(t1), getWReg(ws)));
4868 putWReg(wd,
4869 binop(Iop_OrV128,
4870 mkexpr(t2), mkexpr(t3)));
4871 break;
4874 case 0x02: { /* BINSLI.W */
4875 DIP("BINSLI.W w%d, w%d, w%d", wd, ws, m);
4876 t1 = newTemp(Ity_V128);
4877 t2 = newTemp(Ity_V128);
4878 t3 = newTemp(Ity_V128);
4879 ULong tmp = 0x8000000080000000ULL;
4880 assign(t1,
4881 binop(Iop_SarN32x4,
4882 binop(Iop_64HLtoV128,
4883 mkU64(tmp), mkU64(tmp)), mkU8(m)));
4884 assign(t2,
4885 binop(Iop_AndV128,
4886 unop(Iop_NotV128, mkexpr(t1)), getWReg(wd)));
4887 assign(t3,
4888 binop(Iop_AndV128,
4889 mkexpr(t1), getWReg(ws)));
4890 putWReg(wd,
4891 binop(Iop_OrV128,
4892 mkexpr(t2), mkexpr(t3)));
4893 break;
4896 case 0x03: { /* BINSLI.D */
4897 DIP("BINSLI.D w%d, w%d, w%d", wd, ws, m);
4898 t1 = newTemp(Ity_V128);
4899 t2 = newTemp(Ity_V128);
4900 t3 = newTemp(Ity_V128);
4901 ULong tmp = 0x8000000000000000ULL;
4902 assign(t1,
4903 binop(Iop_SarN64x2,
4904 binop(Iop_64HLtoV128,
4905 mkU64(tmp), mkU64(tmp)), mkU8(m)));
4906 assign(t2,
4907 binop(Iop_AndV128,
4908 unop(Iop_NotV128, mkexpr(t1)), getWReg(wd)));
4909 assign(t3,
4910 binop(Iop_AndV128,
4911 mkexpr(t1), getWReg(ws)));
4912 putWReg(wd,
4913 binop(Iop_OrV128,
4914 mkexpr(t2), mkexpr(t3)));
4915 break;
4918 default:
4919 return -1;
4922 break;
4925 case 0x07: {
4926 switch (df) {
4927 case 0x00: { /* BINSRI.B */
4928 DIP("BINSRI.B w%d, w%d, w%d", wd, ws, m);
4929 t1 = newTemp(Ity_V128);
4930 t2 = newTemp(Ity_V128);
4931 t3 = newTemp(Ity_V128);
4932 ULong tmp = 0xFEFEFEFEFEFEFEFEULL;
4933 assign(t1,
4934 binop(Iop_ShlN8x16,
4935 binop(Iop_64HLtoV128,
4936 mkU64(tmp), mkU64(tmp)), mkU8(m)));
4937 assign(t2,
4938 binop(Iop_AndV128,
4939 unop(Iop_NotV128, mkexpr(t1)), getWReg(ws)));
4940 assign(t3,
4941 binop(Iop_AndV128,
4942 mkexpr(t1), getWReg(wd)));
4943 putWReg(wd,
4944 binop(Iop_OrV128,
4945 mkexpr(t2), mkexpr(t3)));
4946 break;
4949 case 0x01: { /* BINSRI.H */
4950 DIP("BINSRI.H w%d, w%d, w%d", wd, ws, m);
4951 t1 = newTemp(Ity_V128);
4952 t2 = newTemp(Ity_V128);
4953 t3 = newTemp(Ity_V128);
4954 ULong tmp = 0xFFFEFFFEFFFEFFFEULL;
4955 assign(t1,
4956 binop(Iop_ShlN16x8,
4957 binop(Iop_64HLtoV128,
4958 mkU64(tmp), mkU64(tmp)),
4959 mkU8(m)));
4960 assign(t2,
4961 binop(Iop_AndV128,
4962 unop(Iop_NotV128, mkexpr(t1)),
4963 getWReg(ws)));
4964 assign(t3,
4965 binop(Iop_AndV128,
4966 mkexpr(t1), getWReg(wd)));
4967 putWReg(wd,
4968 binop(Iop_OrV128,
4969 mkexpr(t2), mkexpr(t3)));
4970 break;
4973 case 0x02: { /* BINSRI.W */
4974 DIP("BINSRI.W w%d, w%d, w%d", wd, ws, m);
4975 t1 = newTemp(Ity_V128);
4976 t2 = newTemp(Ity_V128);
4977 t3 = newTemp(Ity_V128);
4978 ULong tmp = 0xFFFFFFFEFFFFFFFEULL;
4979 assign(t1,
4980 binop(Iop_ShlN32x4,
4981 binop(Iop_64HLtoV128,
4982 mkU64(tmp), mkU64(tmp)),
4983 mkU8(m)));
4984 assign(t2,
4985 binop(Iop_AndV128,
4986 unop(Iop_NotV128, mkexpr(t1)),
4987 getWReg(ws)));
4988 assign(t3,
4989 binop(Iop_AndV128,
4990 mkexpr(t1), getWReg(wd)));
4991 putWReg(wd,
4992 binop(Iop_OrV128,
4993 mkexpr(t2), mkexpr(t3)));
4994 break;
4997 case 0x03: { /* BINSRI.D */
4998 DIP("BINSRI.D w%d, w%d, w%d", wd, ws, m);
4999 t1 = newTemp(Ity_V128);
5000 t2 = newTemp(Ity_V128);
5001 t3 = newTemp(Ity_V128);
5002 ULong tmp = -2;
5003 assign(t1,
5004 binop(Iop_ShlN64x2,
5005 binop(Iop_64HLtoV128,
5006 mkU64(tmp), mkU64(tmp)),
5007 mkU8(m)));
5008 assign(t2,
5009 binop(Iop_AndV128,
5010 unop(Iop_NotV128, mkexpr(t1)),
5011 getWReg(ws)));
5012 assign(t3,
5013 binop(Iop_AndV128,
5014 mkexpr(t1), getWReg(wd)));
5015 putWReg(wd,
5016 binop(Iop_OrV128,
5017 mkexpr(t2), mkexpr(t3)));
5018 break;
5021 default:
5022 return -1;
5025 break;
5028 default:
5029 return -1;
5032 return 0;
5035 static Int msa_BIT_0A(UInt cins, UChar wd, UChar ws) /* BIT (0x0A) */
5037 IRTemp t1, t2;
5038 UShort operation;
5039 UChar df, m;
5041 operation = (cins & 0x03800000) >> 23;
5042 df = (cins & 0x007F0000) >> 16;
5044 if ((df & 0x70) == 0x70) { // 111mmmm; b
5045 m = df & 0x07;
5046 df = 0;
5047 } else if ((df & 0x60) == 0x60) { // 110mmmm; h
5048 m = df & 0x0F;
5049 df = 1;
5050 } else if ((df & 0x40) == 0x40) { // 10mmmmm; w
5051 m = df & 0x1F;
5052 df = 2;
5053 } else if ((df & 0x00) == 0x00) { // 0mmmmmm; d
5054 m = df & 0x3F;
5055 df = 3;
5058 switch (operation) {
5059 case 0x00: { /* SAT_S.df */
5060 switch (df) {
5061 case 0x00: { /* SAT_S.B */
5062 DIP("SAT_S.B w%d, w%d, %d", wd, ws, m);
5063 t1 = newTemp(Ity_V128);
5064 assign(t1, binop(Iop_SarN8x16, getWReg(ws), mkU8(7)));
5066 if (m == 0) {
5067 putWReg(wd, mkexpr(t1));
5068 } else {
5069 t2 = newTemp(Ity_V128);
5070 assign(t2,
5071 binop(Iop_SarN8x16, getWReg(ws), mkU8(m)));
5072 putWReg(wd,
5073 binop(Iop_OrV128,
5074 binop(Iop_OrV128,
5075 binop(Iop_AndV128,
5076 binop(Iop_CmpEQ8x16,
5077 mkexpr(t1),
5078 mkexpr(t2)),
5079 getWReg(ws)),
5080 binop(Iop_ShlN8x16,
5081 binop(Iop_CmpGT8Sx16,
5082 mkexpr(t1),
5083 mkexpr(t2)),
5084 mkU8(m))),
5085 binop(Iop_ShrN8x16,
5086 binop(Iop_CmpGT8Sx16,
5087 mkexpr(t2),
5088 mkexpr(t1)),
5089 mkU8(8 - m))));
5092 break;
5095 case 0x01: { /* SAT_S.H */
5096 DIP("SAT_S.H w%d, w%d, %d", wd, ws, m);
5097 t1 = newTemp(Ity_V128);
5098 assign(t1, binop(Iop_SarN16x8, getWReg(ws), mkU8(15)));
5100 if (m == 0) {
5101 putWReg(wd, mkexpr(t1));
5102 } else {
5103 t2 = newTemp(Ity_V128);
5104 assign(t2,
5105 binop(Iop_SarN16x8,
5106 getWReg(ws),
5107 mkU8(m)));
5108 putWReg(wd,
5109 binop(Iop_OrV128,
5110 binop(Iop_OrV128,
5111 binop(Iop_AndV128,
5112 binop(Iop_CmpEQ16x8,
5113 mkexpr(t1),
5114 mkexpr(t2)),
5115 getWReg(ws)),
5116 binop(Iop_ShlN16x8,
5117 binop(Iop_CmpGT16Sx8,
5118 mkexpr(t1),
5119 mkexpr(t2)),
5120 mkU8(m))),
5121 binop(Iop_ShrN16x8,
5122 binop(Iop_CmpGT16Sx8,
5123 mkexpr(t2),
5124 mkexpr(t1)),
5125 mkU8(16 - m))));
5128 break;
5131 case 0x02: { /* SAT_S.W */
5132 DIP("SAT_S.W w%d, w%d, %d", wd, ws, m);
5133 t1 = newTemp(Ity_V128);
5134 assign(t1, binop(Iop_SarN32x4, getWReg(ws), mkU8(31)));
5136 if (m == 0) {
5137 putWReg(wd, mkexpr(t1));
5138 } else {
5139 t2 = newTemp(Ity_V128);
5140 assign(t2,
5141 binop(Iop_SarN32x4,
5142 getWReg(ws),
5143 mkU8(m)));
5144 putWReg(wd,
5145 binop(Iop_OrV128,
5146 binop(Iop_OrV128,
5147 binop(Iop_AndV128,
5148 binop(Iop_CmpEQ32x4,
5149 mkexpr(t1),
5150 mkexpr(t2)),
5151 getWReg(ws)),
5152 binop(Iop_ShlN32x4,
5153 binop(Iop_CmpGT32Sx4,
5154 mkexpr(t1),
5155 mkexpr(t2)),
5156 mkU8(m))),
5157 binop(Iop_ShrN32x4,
5158 binop(Iop_CmpGT32Sx4,
5159 mkexpr(t2),
5160 mkexpr(t1)),
5161 mkU8(32 - m))));
5164 break;
5167 case 0x03: { /* SAT_S.D */
5168 DIP("SAT_S.D w%d, w%d, %d", wd, ws, m);
5169 t1 = newTemp(Ity_V128);
5170 assign(t1, binop(Iop_SarN64x2, getWReg(ws), mkU8(63)));
5172 if (m == 0) {
5173 putWReg(wd, mkexpr(t1));
5174 } else {
5175 t2 = newTemp(Ity_V128);
5176 assign(t2,
5177 binop(Iop_SarN64x2,
5178 getWReg(ws),
5179 mkU8(m)));
5180 putWReg(wd,
5181 binop(Iop_OrV128,
5182 binop(Iop_OrV128,
5183 binop(Iop_AndV128,
5184 binop(Iop_CmpEQ64x2,
5185 mkexpr(t1),
5186 mkexpr(t2)),
5187 getWReg(ws)),
5188 binop(Iop_ShlN64x2,
5189 binop(Iop_CmpGT64Sx2,
5190 mkexpr(t1),
5191 mkexpr(t2)),
5192 mkU8(m))),
5193 binop(Iop_ShrN64x2,
5194 binop(Iop_CmpGT64Sx2,
5195 mkexpr(t2),
5196 mkexpr(t1)),
5197 mkU8(64 - m))));
5200 break;
5204 break;
5207 case 0x01: { /* SAT_U.df */
5208 switch (df) {
5209 case 0x00: { /* SAT_U.B */
5210 DIP("SAT_U.B w%d, w%d, %d", wd, ws, m);
5212 if (m == 7) {
5213 putWReg(wd, getWReg(ws));
5214 } else {
5215 t1 = newTemp(Ity_V128);
5216 assign(t1,
5217 binop(Iop_CmpEQ8x16,
5218 binop(Iop_ShrN8x16,
5219 getWReg(ws),
5220 mkU8(m + 1)),
5221 binop(Iop_64HLtoV128,
5222 mkU64(0), mkU64(0))));
5223 putWReg(wd,
5224 binop(Iop_OrV128,
5225 binop(Iop_AndV128,
5226 mkexpr(t1),
5227 getWReg(ws)),
5228 binop(Iop_ShrN8x16,
5229 unop(Iop_NotV128,
5230 mkexpr(t1)),
5231 mkU8(7 - m))));
5234 break;
5237 case 0x01: { /* SAT_U.H */
5238 DIP("SAT_U.H w%d, w%d, %d", wd, ws, m);
5240 if (m == 15) {
5241 putWReg(wd, getWReg(ws));
5242 } else {
5243 t1 = newTemp(Ity_V128);
5244 assign(t1,
5245 binop(Iop_CmpEQ16x8,
5246 binop(Iop_ShrN16x8,
5247 getWReg(ws),
5248 mkU8(m + 1)),
5249 binop(Iop_64HLtoV128,
5250 mkU64(0), mkU64(0))));
5251 putWReg(wd,
5252 binop(Iop_OrV128,
5253 binop(Iop_AndV128,
5254 mkexpr(t1),
5255 getWReg(ws)),
5256 binop(Iop_ShrN16x8,
5257 unop(Iop_NotV128,
5258 mkexpr(t1)),
5259 mkU8(15 - m))));
5262 break;
5265 case 0x02: { /* SAT_U.W */
5266 DIP("SAT_U.W w%d, w%d, %d", wd, ws, m);
5268 if (m == 31) {
5269 putWReg(wd, getWReg(ws));
5270 } else {
5271 t1 = newTemp(Ity_V128);
5272 assign(t1,
5273 binop(Iop_CmpEQ32x4,
5274 binop(Iop_ShrN32x4,
5275 getWReg(ws),
5276 mkU8(m + 1)),
5277 binop(Iop_64HLtoV128,
5278 mkU64(0), mkU64(0))));
5279 putWReg(wd,
5280 binop(Iop_OrV128,
5281 binop(Iop_AndV128,
5282 mkexpr(t1), \
5283 getWReg(ws)),
5284 binop(Iop_ShrN32x4,
5285 unop(Iop_NotV128,
5286 mkexpr(t1)),
5287 mkU8(31 - m))));
5290 break;
5293 case 0x03: { /* SAT_U.D */
5294 DIP("SAT_U.D w%d, w%d, %d", wd, ws, m);
5296 if (m == 63) {
5297 putWReg(wd, getWReg(ws));
5298 } else {
5299 t1 = newTemp(Ity_V128);
5300 assign(t1,
5301 binop(Iop_CmpEQ64x2,
5302 binop(Iop_ShrN64x2,
5303 getWReg(ws),
5304 mkU8(m + 1)),
5305 binop(Iop_64HLtoV128,
5306 mkU64(0), mkU64(0))));
5307 putWReg(wd,
5308 binop(Iop_OrV128,
5309 binop(Iop_AndV128,
5310 mkexpr(t1),
5311 getWReg(ws)),
5312 binop(Iop_ShrN64x2,
5313 unop(Iop_NotV128,
5314 mkexpr(t1)),
5315 mkU8(63 - m))));
5318 break;
5322 break;
5325 case 0x02: { /* SRARI.df */
5326 switch (df) {
5327 case 0x00: { /* SRARI.B */
5328 DIP("SRARI.B w%d, w%d, %d", wd, ws, m);
5329 t1 = newTemp(Ity_V128);
5330 t2 = newTemp(Ity_V128);
5331 assign(t1,
5332 binop(Iop_SarN8x16,
5333 getWReg(ws),
5334 mkU8(m)));
5335 assign(t2,
5336 binop(Iop_ShrN8x16,
5337 binop(Iop_ShlN8x16,
5338 getWReg(ws),
5339 mkU8(8 - m)),
5340 mkU8(7)));
5342 if (m) putWReg(wd, binop(Iop_Add8x16,
5343 mkexpr(t1),
5344 mkexpr(t2)));
5345 else putWReg(wd, mkexpr(t1));
5347 break;
5350 case 0x01: { /* SRARI.H */
5351 DIP("SRARI.H w%d, w%d, %d", wd, ws, m);
5352 t1 = newTemp(Ity_V128);
5353 t2 = newTemp(Ity_V128);
5354 assign(t1,
5355 binop(Iop_SarN16x8,
5356 getWReg(ws),
5357 mkU8(m)));
5358 assign(t2,
5359 binop(Iop_ShrN16x8,
5360 binop(Iop_ShlN16x8,
5361 getWReg(ws),
5362 mkU8(16 - m)),
5363 mkU8(15)));
5365 if (m)
5366 putWReg(wd,
5367 binop(Iop_Add16x8,
5368 mkexpr(t1), mkexpr(t2)));
5369 else putWReg(wd, mkexpr(t1));
5371 break;
5374 case 0x02: { /* SRARI.W */
5375 DIP("SRARI.W w%d, w%d, %d", wd, ws, m);
5376 t1 = newTemp(Ity_V128);
5377 t2 = newTemp(Ity_V128);
5378 assign(t1,
5379 binop(Iop_SarN32x4,
5380 getWReg(ws),
5381 mkU8(m)));
5382 assign(t2,
5383 binop(Iop_ShrN32x4,
5384 binop(Iop_ShlN32x4,
5385 getWReg(ws),
5386 mkU8(32 - m)),
5387 mkU8(31)));
5389 if (m)
5390 putWReg(wd,
5391 binop(Iop_Add32x4,
5392 mkexpr(t1), mkexpr(t2)));
5393 else putWReg(wd, mkexpr(t1));
5395 break;
5398 case 0x03: { /* SRARI.D */
5399 DIP("SRARI.D w%d, w%d, %d", wd, ws, m);
5400 t1 = newTemp(Ity_V128);
5401 t2 = newTemp(Ity_V128);
5402 assign(t1,
5403 binop(Iop_SarN64x2,
5404 getWReg(ws),
5405 mkU8(m)));
5406 assign(t2,
5407 binop(Iop_ShrN64x2,
5408 binop(Iop_ShlN64x2,
5409 getWReg(ws),
5410 mkU8(64 - m)),
5411 mkU8(63)));
5413 if (m)
5414 putWReg(wd,
5415 binop(Iop_Add64x2,
5416 mkexpr(t1), mkexpr(t2)));
5417 else putWReg(wd, mkexpr(t1));
5419 break;
5423 break;
5426 case 0x03: { /* SRLRI.df */
5427 switch (df) {
5428 case 0x00: { /* SRLRI.B */
5429 DIP("SRLRI.B w%d, w%d, %d", wd, ws, m);
5430 t1 = newTemp(Ity_V128);
5431 t2 = newTemp(Ity_V128);
5432 assign(t1,
5433 binop(Iop_ShrN8x16,
5434 getWReg(ws),
5435 mkU8(m)));
5436 assign(t2,
5437 binop(Iop_ShrN8x16,
5438 binop(Iop_ShlN8x16,
5439 getWReg(ws),
5440 mkU8(8 - m)),
5441 mkU8(7)));
5443 if (m)
5444 putWReg(wd,
5445 binop(Iop_Add8x16,
5446 mkexpr(t1), mkexpr(t2)));
5447 else putWReg(wd, mkexpr(t1));
5449 break;
5452 case 0x01: { /* SRLRI.H */
5453 DIP("SRLRI.H w%d, w%d, %d", wd, ws, m);
5454 t1 = newTemp(Ity_V128);
5455 t2 = newTemp(Ity_V128);
5456 assign(t1,
5457 binop(Iop_ShrN16x8,
5458 getWReg(ws),
5459 mkU8(m)));
5460 assign(t2,
5461 binop(Iop_ShrN16x8,
5462 binop(Iop_ShlN16x8,
5463 getWReg(ws),
5464 mkU8(16 - m)),
5465 mkU8(15)));
5467 if (m)
5468 putWReg(wd,
5469 binop(Iop_Add16x8,
5470 mkexpr(t1), mkexpr(t2)));
5471 else putWReg(wd, mkexpr(t1));
5473 break;
5476 case 0x02: { /* SRLRI.W */
5477 DIP("SRLRI.W w%d, w%d, %d", wd, ws, m);
5478 t1 = newTemp(Ity_V128);
5479 t2 = newTemp(Ity_V128);
5480 assign(t1,
5481 binop(Iop_ShrN32x4,
5482 getWReg(ws),
5483 mkU8(m)));
5484 assign(t2,
5485 binop(Iop_ShrN32x4,
5486 binop(Iop_ShlN32x4,
5487 getWReg(ws),
5488 mkU8(32 - m)),
5489 mkU8(31)));
5491 if (m)
5492 putWReg(wd,
5493 binop(Iop_Add32x4,
5494 mkexpr(t1), mkexpr(t2)));
5495 else putWReg(wd, mkexpr(t1));
5497 break;
5500 case 0x03: { /* SRLRI.D */
5501 DIP("SRLRI.D w%d, w%d, %d", wd, ws, m);
5502 t1 = newTemp(Ity_V128);
5503 t2 = newTemp(Ity_V128);
5504 assign(t1,
5505 binop(Iop_ShrN64x2,
5506 getWReg(ws),
5507 mkU8(m)));
5508 assign(t2,
5509 binop(Iop_ShrN64x2,
5510 binop(Iop_ShlN64x2,
5511 getWReg(ws),
5512 mkU8(64 - m)),
5513 mkU8(63)));
5515 if (m)
5516 putWReg(wd,
5517 binop(Iop_Add64x2,
5518 mkexpr(t1), mkexpr(t2)));
5519 else putWReg(wd, mkexpr(t1));
5521 break;
5525 break;
5528 default:
5529 return -1;
5532 return 0;
5535 static Int msa_3R_0D(UInt cins, UChar wd, UChar ws) /* 3R (0x0D) */
5537 IRTemp t1, t2, t3;
5538 UShort operation;
5539 UChar df, wt;
5541 operation = (cins & 0x03800000) >> 23;
5542 df = (cins & 0x00600000) >> 21;
5543 wt = (cins & 0x001F0000) >> 16;
5545 switch (operation) {
5546 case 0x00: { /* SLL.df */
5547 switch (df) {
5548 case 0x00: { /* SLL.B */
5549 DIP("SLL.B w%d, w%d, w%d", wd, ws, wt);
5550 t1 = newTemp(Ity_V128);
5551 t2 = newTemp(Ity_V128);
5552 t3 = newTemp(Ity_V128);
5553 assign(t1, getWReg(ws));
5554 assign(t2, getWReg(wt));
5555 assign(t3, binop(Iop_Shl8x16, mkexpr(t1), mkexpr(t2)));
5556 putWReg(wd, mkexpr(t3));
5557 break;
5560 case 0x01: { /* SLL.H */
5561 DIP("SLL.H w%d, w%d, w%d", wd, ws, wt);
5562 t1 = newTemp(Ity_V128);
5563 t2 = newTemp(Ity_V128);
5564 t3 = newTemp(Ity_V128);
5565 assign(t1, getWReg(ws));
5566 assign(t2, getWReg(wt));
5567 assign(t3, binop(Iop_Shl16x8, mkexpr(t1), mkexpr(t2)));
5568 putWReg(wd, mkexpr(t3));
5569 break;
5572 case 0x02: { /* SLL.W */
5573 DIP("SLL.W w%d, w%d, w%d", wd, ws, wt);
5574 t1 = newTemp(Ity_V128);
5575 t2 = newTemp(Ity_V128);
5576 t3 = newTemp(Ity_V128);
5577 assign(t1, getWReg(ws));
5578 assign(t2, getWReg(wt));
5579 assign(t3, binop(Iop_Shl32x4, mkexpr(t1), mkexpr(t2)));
5580 putWReg(wd, mkexpr(t3));
5581 break;
5584 case 0x03: { /* SLL.D */
5585 DIP("SLL.D w%d, w%d, w%d", wd, ws, wt);
5586 t1 = newTemp(Ity_V128);
5587 t2 = newTemp(Ity_V128);
5588 t3 = newTemp(Ity_V128);
5589 assign(t1, getWReg(ws));
5590 assign(t2, getWReg(wt));
5591 assign(t3, binop(Iop_Shl64x2, mkexpr(t1), mkexpr(t2)));
5592 putWReg(wd, mkexpr(t3));
5593 break;
5596 default:
5597 return -1;
5600 break;
5603 case 0x01: { /* SRA.df */
5604 switch (df) {
5605 case 0x00: { /* SRA.B */
5606 DIP("SRA.B w%d, w%d, w%d", wd, ws, wt);
5607 t1 = newTemp(Ity_V128);
5608 t2 = newTemp(Ity_V128);
5609 t3 = newTemp(Ity_V128);
5610 assign(t1, getWReg(ws));
5611 assign(t2, getWReg(wt));
5612 assign(t3, binop(Iop_Sar8x16, mkexpr(t1), mkexpr(t2)));
5613 putWReg(wd, mkexpr(t3));
5614 break;
5617 case 0x01: { /* SRA.H */
5618 DIP("SRA.H w%d, w%d, w%d", wd, ws, wt);
5619 t1 = newTemp(Ity_V128);
5620 t2 = newTemp(Ity_V128);
5621 t3 = newTemp(Ity_V128);
5622 assign(t1, getWReg(ws));
5623 assign(t2, getWReg(wt));
5624 assign(t3, binop(Iop_Sar16x8, mkexpr(t1), mkexpr(t2)));
5625 putWReg(wd, mkexpr(t3));
5626 break;
5629 case 0x02: { /* SRA.W */
5630 DIP("SRA.W w%d, w%d, w%d", wd, ws, wt);
5631 t1 = newTemp(Ity_V128);
5632 t2 = newTemp(Ity_V128);
5633 t3 = newTemp(Ity_V128);
5634 assign(t1, getWReg(ws));
5635 assign(t2, getWReg(wt));
5636 assign(t3, binop(Iop_Sar32x4, mkexpr(t1), mkexpr(t2)));
5637 putWReg(wd, mkexpr(t3));
5638 break;
5641 case 0x03: { /* SRA.D */
5642 DIP("SRA.D w%d, w%d, w%d", wd, ws, wt);
5643 t1 = newTemp(Ity_V128);
5644 t2 = newTemp(Ity_V128);
5645 t3 = newTemp(Ity_V128);
5646 assign(t1, getWReg(ws));
5647 assign(t2, getWReg(wt));
5648 assign(t3, binop(Iop_Sar64x2, mkexpr(t1), mkexpr(t2)));
5649 putWReg(wd, mkexpr(t3));
5650 break;
5653 default:
5654 return -1;
5657 break;
5660 case 0x02: { /* SRL.df */
5661 switch (df) {
5662 case 0x00: { /* SRL.B */
5663 DIP("SRL.B w%d, w%d, w%d", wd, ws, wt);
5664 t1 = newTemp(Ity_V128);
5665 t2 = newTemp(Ity_V128);
5666 t3 = newTemp(Ity_V128);
5667 assign(t1, getWReg(ws));
5668 assign(t2, getWReg(wt));
5669 assign(t3, binop(Iop_Shr8x16, mkexpr(t1), mkexpr(t2)));
5670 putWReg(wd, mkexpr(t3));
5671 break;
5674 case 0x01: { /* SRL.H */
5675 DIP("SRL.H w%d, w%d, w%d", wd, ws, wt);
5676 t1 = newTemp(Ity_V128);
5677 t2 = newTemp(Ity_V128);
5678 t3 = newTemp(Ity_V128);
5679 assign(t1, getWReg(ws));
5680 assign(t2, getWReg(wt));
5681 assign(t3, binop(Iop_Shr16x8, mkexpr(t1), mkexpr(t2)));
5682 putWReg(wd, mkexpr(t3));
5683 break;
5686 case 0x02: { /* SRL.W */
5687 DIP("SRL.W w%d, w%d, w%d", wd, ws, wt);
5688 t1 = newTemp(Ity_V128);
5689 t2 = newTemp(Ity_V128);
5690 t3 = newTemp(Ity_V128);
5691 assign(t1, getWReg(ws));
5692 assign(t2, getWReg(wt));
5693 assign(t3, binop(Iop_Shr32x4, mkexpr(t1), mkexpr(t2)));
5694 putWReg(wd, mkexpr(t3));
5695 break;
5698 case 0x03: { /* SRL.D */
5699 DIP("SRL.D w%d, w%d, w%d", wd, ws, wt);
5700 t1 = newTemp(Ity_V128);
5701 t2 = newTemp(Ity_V128);
5702 t3 = newTemp(Ity_V128);
5703 assign(t1, getWReg(ws));
5704 assign(t2, getWReg(wt));
5705 assign(t3, binop(Iop_Shr64x2, mkexpr(t1), mkexpr(t2)));
5706 putWReg(wd, mkexpr(t3));
5707 break;
5710 default:
5711 return -1;
5714 break;
5717 case 0x03: { /* BCLR.df */
5718 t1 = newTemp(Ity_V128);
5719 t2 = newTemp(Ity_V128);
5720 t3 = newTemp(Ity_V128);
5721 ULong tmp = 1;
5722 assign(t1, getWReg(ws));
5724 switch (df) {
5725 case 0x00: { /* BCLR.B */
5726 DIP("BCLR.B w%d, w%d, w%d", wd, ws, wt);
5727 tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
5728 (tmp << 32) | (tmp << 24) | (tmp << 16) |
5729 (tmp << 8);
5730 assign(t2, binop(Iop_Shl8x16,
5731 binop(Iop_64HLtoV128,
5732 mkU64(tmp), mkU64(tmp)),
5733 getWReg(wt)));
5734 break;
5737 case 0x01: { /* BCLR.H */
5738 DIP("BCLR.H w%d, w%d, w%d", wd, ws, wt);
5739 tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
5740 assign(t2,
5741 binop(Iop_Shl16x8,
5742 binop(Iop_64HLtoV128,
5743 mkU64(tmp), mkU64(tmp)),
5744 getWReg(wt)));
5745 break;
5748 case 0x02: { /* BCLR.W */
5749 DIP("BCLR.W w%d, w%d, w%d", wd, ws, wt);
5750 tmp |= (tmp << 32);
5751 assign(t2,
5752 binop(Iop_Shl32x4,
5753 binop(Iop_64HLtoV128,
5754 mkU64(tmp), mkU64(tmp)),
5755 getWReg(wt)));
5756 break;
5759 case 0x03: { /* BCLR.D */
5760 DIP("BCLR.D w%d, w%d, w%d", wd, ws, wt);
5761 assign(t2,
5762 binop(Iop_Shl64x2,
5763 binop(Iop_64HLtoV128,
5764 mkU64(tmp), mkU64(tmp)),
5765 getWReg(wt)));
5766 break;
5770 assign(t3,
5771 binop(Iop_AndV128,
5772 mkexpr(t1), unop(Iop_NotV128, mkexpr(t2))));
5773 putWReg(wd, mkexpr(t3));
5774 break;
5777 case 0x04: { /* BSET.df */
5778 t1 = newTemp(Ity_V128);
5779 t2 = newTemp(Ity_V128);
5780 t3 = newTemp(Ity_V128);
5781 ULong tmp = 1;
5782 assign(t1, getWReg(ws));
5784 switch (df) {
5785 case 0x00: { /* BSET.B */
5786 DIP("BSET.B w%d, w%d, w%d", wd, ws, wt);
5787 tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
5788 (tmp << 32) | (tmp << 24) | (tmp << 16) |
5789 (tmp << 8);
5790 assign(t2,
5791 binop(Iop_Shl8x16,
5792 binop(Iop_64HLtoV128,
5793 mkU64(tmp), mkU64(tmp)),
5794 getWReg(wt)));
5795 break;
5798 case 0x01: { /* BSET.H */
5799 DIP("BSET.H w%d, w%d, w%d", wd, ws, wt);
5800 tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
5801 assign(t2,
5802 binop(Iop_Shl16x8,
5803 binop(Iop_64HLtoV128,
5804 mkU64(tmp), mkU64(tmp)),
5805 getWReg(wt)));
5806 break;
5809 case 0x02: { /* BSET.W */
5810 DIP("BSET.W w%d, w%d, w%d", wd, ws, wt);
5811 tmp |= (tmp << 32);
5812 assign(t2,
5813 binop(Iop_Shl32x4,
5814 binop(Iop_64HLtoV128,
5815 mkU64(tmp), mkU64(tmp)),
5816 getWReg(wt)));
5817 break;
5820 case 0x03: { /* BSET.D */
5821 DIP("BSET.D w%d, w%d, w%d", wd, ws, wt);
5822 assign(t2,
5823 binop(Iop_Shl64x2,
5824 binop(Iop_64HLtoV128,
5825 mkU64(tmp), mkU64(tmp)),
5826 getWReg(wt)));
5827 break;
5831 assign(t3, binop(Iop_OrV128, mkexpr(t1), mkexpr(t2)));
5832 putWReg(wd, mkexpr(t3));
5833 break;
5836 case 0x05: { /* BNEG.df */
5837 t1 = newTemp(Ity_V128);
5838 t2 = newTemp(Ity_V128);
5839 t3 = newTemp(Ity_V128);
5840 ULong tmp = 1;
5841 assign(t1, getWReg(ws));
5843 switch (df) {
5844 case 0x00: { /* BNEG.B */
5845 DIP("BNEG.B w%d, w%d, w%d", wd, ws, wt);
5846 tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
5847 (tmp << 32) | (tmp << 24) | (tmp << 16) |
5848 (tmp << 8);
5849 assign(t2,
5850 binop(Iop_Shl8x16,
5851 binop(Iop_64HLtoV128,
5852 mkU64(tmp), mkU64(tmp)),
5853 getWReg(wt)));
5854 break;
5857 case 0x01: { /* BNEG.H */
5858 DIP("BNEG.H w%d, w%d, w%d", wd, ws, wt);
5859 tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
5860 assign(t2,
5861 binop(Iop_Shl16x8,
5862 binop(Iop_64HLtoV128,
5863 mkU64(tmp), mkU64(tmp)),
5864 getWReg(wt)));
5865 break;
5868 case 0x02: { /* BNEG.W */
5869 DIP("BNEG.W w%d, w%d, w%d", wd, ws, wt);
5870 tmp |= (tmp << 32);
5871 assign(t2,
5872 binop(Iop_Shl32x4,
5873 binop(Iop_64HLtoV128,
5874 mkU64(tmp), mkU64(tmp)),
5875 getWReg(wt)));
5876 break;
5879 case 0x03: { /* BNEG.D */
5880 DIP("BNEG.D w%d, w%d, w%d", wd, ws, wt);
5881 assign(t2,
5882 binop(Iop_Shl64x2,
5883 binop(Iop_64HLtoV128,
5884 mkU64(tmp), mkU64(tmp)),
5885 getWReg(wt)));
5886 break;
5890 assign(t3, binop(Iop_XorV128, mkexpr(t1), mkexpr(t2)));
5891 putWReg(wd, mkexpr(t3));
5892 break;
5895 case 0x06: { /* BINSL.df */
5896 switch (df) {
5897 case 0x00: { /* BINSL.B */
5898 DIP("BINSL.B w%d, w%d, w%d", wd, ws, wt);
5899 t1 = newTemp(Ity_V128);
5900 t2 = newTemp(Ity_V128);
5901 t3 = newTemp(Ity_V128);
5902 ULong tmp = 0x8080808080808080ULL;
5903 assign(t1,
5904 binop(Iop_Sar8x16,
5905 binop(Iop_64HLtoV128,
5906 mkU64(tmp), mkU64(tmp)),
5907 getWReg(wt)));
5908 assign(t2,
5909 binop(Iop_AndV128,
5910 unop(Iop_NotV128, mkexpr(t1)),
5911 getWReg(wd)));
5912 assign(t3,
5913 binop(Iop_AndV128,
5914 mkexpr(t1), getWReg(ws)));
5915 putWReg(wd,
5916 binop(Iop_OrV128,
5917 mkexpr(t2), mkexpr(t3)));
5918 break;
5921 case 0x01: { /* BINSL.H */
5922 DIP("BINSL.H w%d, w%d, w%d", wd, ws, wt);
5923 t1 = newTemp(Ity_V128);
5924 t2 = newTemp(Ity_V128);
5925 t3 = newTemp(Ity_V128);
5926 ULong tmp = 0x8000800080008000ULL;
5927 assign(t1,
5928 binop(Iop_Sar16x8,
5929 binop(Iop_64HLtoV128,
5930 mkU64(tmp), mkU64(tmp)),
5931 getWReg(wt)));
5932 assign(t2,
5933 binop(Iop_AndV128,
5934 unop(Iop_NotV128, mkexpr(t1)),
5935 getWReg(wd)));
5936 assign(t3,
5937 binop(Iop_AndV128,
5938 mkexpr(t1), getWReg(ws)));
5939 putWReg(wd,
5940 binop(Iop_OrV128,
5941 mkexpr(t2), mkexpr(t3)));
5942 break;
5945 case 0x02: { /* BINSL.W */
5946 DIP("BINSL.W w%d, w%d, w%d", wd, ws, wt);
5947 t1 = newTemp(Ity_V128);
5948 t2 = newTemp(Ity_V128);
5949 t3 = newTemp(Ity_V128);
5950 ULong tmp = 0x8000000080000000ULL;
5951 assign(t1,
5952 binop(Iop_Sar32x4,
5953 binop(Iop_64HLtoV128,
5954 mkU64(tmp), mkU64(tmp)),
5955 getWReg(wt)));
5956 assign(t2,
5957 binop(Iop_AndV128,
5958 unop(Iop_NotV128, mkexpr(t1)),
5959 getWReg(wd)));
5960 assign(t3,
5961 binop(Iop_AndV128,
5962 mkexpr(t1), getWReg(ws)));
5963 putWReg(wd,
5964 binop(Iop_OrV128,
5965 mkexpr(t2), mkexpr(t3)));
5966 break;
5969 case 0x03: { /* BINSL.D */
5970 DIP("BINSL.D w%d, w%d, w%d", wd, ws, wt);
5971 t1 = newTemp(Ity_V128);
5972 t2 = newTemp(Ity_V128);
5973 t3 = newTemp(Ity_V128);
5974 ULong tmp = 0x8000000000000000ULL;
5975 assign(t1,
5976 binop(Iop_Sar64x2,
5977 binop(Iop_64HLtoV128,
5978 mkU64(tmp), mkU64(tmp)),
5979 getWReg(wt)));
5980 assign(t2,
5981 binop(Iop_AndV128,
5982 unop(Iop_NotV128, mkexpr(t1)),
5983 getWReg(wd)));
5984 assign(t3,
5985 binop(Iop_AndV128,
5986 mkexpr(t1), getWReg(ws)));
5987 putWReg(wd,
5988 binop(Iop_OrV128,
5989 mkexpr(t2), mkexpr(t3)));
5990 break;
5993 default:
5994 return -1;
5997 break;
6000 case 0x07: { /* BINSR.df */
6001 switch (df) {
6002 case 0x00: { /* BINSR.B */
6003 DIP("BINSR.B w%d, w%d, w%d", wd, ws, wt);
6004 t1 = newTemp(Ity_V128);
6005 t2 = newTemp(Ity_V128);
6006 t3 = newTemp(Ity_V128);
6007 ULong tmp = 0xFEFEFEFEFEFEFEFEULL;
6008 assign(t1,
6009 binop(Iop_Shl8x16,
6010 binop(Iop_64HLtoV128,
6011 mkU64(tmp), mkU64(tmp)),
6012 getWReg(wt)));
6013 assign(t2,
6014 binop(Iop_AndV128,
6015 unop(Iop_NotV128, mkexpr(t1)),
6016 getWReg(ws)));
6017 assign(t3,
6018 binop(Iop_AndV128,
6019 mkexpr(t1), getWReg(wd)));
6020 putWReg(wd,
6021 binop(Iop_OrV128,
6022 mkexpr(t2), mkexpr(t3)));
6023 break;
6026 case 0x01: { /* BINSR.H */
6027 DIP("BINSR.H w%d, w%d, w%d", wd, ws, wt);
6028 t1 = newTemp(Ity_V128);
6029 t2 = newTemp(Ity_V128);
6030 t3 = newTemp(Ity_V128);
6031 ULong tmp = 0xFFFEFFFEFFFEFFFEULL;
6032 assign(t1,
6033 binop(Iop_Shl16x8,
6034 binop(Iop_64HLtoV128,
6035 mkU64(tmp), mkU64(tmp)),
6036 getWReg(wt)));
6037 assign(t2,
6038 binop(Iop_AndV128,
6039 unop(Iop_NotV128, mkexpr(t1)),
6040 getWReg(ws)));
6041 assign(t3,
6042 binop(Iop_AndV128,
6043 mkexpr(t1), getWReg(wd)));
6044 putWReg(wd,
6045 binop(Iop_OrV128,
6046 mkexpr(t2), mkexpr(t3)));
6047 break;
6050 case 0x02: { /* BINSR.W */
6051 DIP("BINSR.W w%d, w%d, w%d", wd, ws, wt);
6052 t1 = newTemp(Ity_V128);
6053 t2 = newTemp(Ity_V128);
6054 t3 = newTemp(Ity_V128);
6055 ULong tmp = 0xFFFFFFFEFFFFFFFEULL;
6056 assign(t1,
6057 binop(Iop_Shl32x4,
6058 binop(Iop_64HLtoV128,
6059 mkU64(tmp), mkU64(tmp)),
6060 getWReg(wt)));
6061 assign(t2,
6062 binop(Iop_AndV128,
6063 unop(Iop_NotV128, mkexpr(t1)),
6064 getWReg(ws)));
6065 assign(t3,
6066 binop(Iop_AndV128,
6067 mkexpr(t1), getWReg(wd)));
6068 putWReg(wd,
6069 binop(Iop_OrV128,
6070 mkexpr(t2), mkexpr(t3)));
6071 break;
6074 case 0x03: { /* BINSR.D */
6075 DIP("BINSR.D w%d, w%d, w%d", wd, ws, wt);
6076 t1 = newTemp(Ity_V128);
6077 t2 = newTemp(Ity_V128);
6078 t3 = newTemp(Ity_V128);
6079 ULong tmp = -2;
6080 assign(t1,
6081 binop(Iop_Shl64x2,
6082 binop(Iop_64HLtoV128,
6083 mkU64(tmp), mkU64(tmp)),
6084 getWReg(wt)));
6085 assign(t2,
6086 binop(Iop_AndV128,
6087 unop(Iop_NotV128, mkexpr(t1)),
6088 getWReg(ws)));
6089 assign(t3,
6090 binop(Iop_AndV128,
6091 mkexpr(t1), getWReg(wd)));
6092 putWReg(wd,
6093 binop(Iop_OrV128,
6094 mkexpr(t2), mkexpr(t3)));
6095 break;
6098 default:
6099 return -1;
6102 break;
6105 default:
6106 return -1;
6109 return 0;
6112 static Int msa_3R_0E(UInt cins, UChar wd, UChar ws) /* 3R (0x0E) */
6114 IRTemp t1, t2, t3, t4;
6115 UShort operation;
6116 UChar df, wt;
6118 operation = (cins & 0x03800000) >> 23;
6119 df = (cins & 0x00600000) >> 21;
6120 wt = (cins & 0x001F0000) >> 16;
6122 switch (operation) {
6123 case 0x00: { /* ADDV.df */
6124 switch (df) {
6125 case 0x00: { /* ADDV.B */
6126 DIP("ADDV.B w%d, w%d, w%d", wd, ws, wt);
6127 t1 = newTemp(Ity_V128);
6128 t2 = newTemp(Ity_V128);
6129 t3 = newTemp(Ity_V128);
6130 assign(t1, getWReg(ws));
6131 assign(t2, getWReg(wt));
6132 assign(t3, binop(Iop_Add8x16, mkexpr(t1), mkexpr(t2)));
6133 putWReg(wd, mkexpr(t3));
6134 break;
6137 case 0x01: { /* ADDV.H */
6138 DIP("ADDV.H w%d, w%d, w%d", wd, ws, wt);
6139 t1 = newTemp(Ity_V128);
6140 t2 = newTemp(Ity_V128);
6141 t3 = newTemp(Ity_V128);
6142 assign(t1, getWReg(ws));
6143 assign(t2, getWReg(wt));
6144 assign(t3, binop(Iop_Add16x8, mkexpr(t1), mkexpr(t2)));
6145 putWReg(wd, mkexpr(t3));
6146 break;
6149 case 0x02: { /* ADDV.W */
6150 DIP("ADDV.W w%d, w%d, w%d", wd, ws, wt);
6151 t1 = newTemp(Ity_V128);
6152 t2 = newTemp(Ity_V128);
6153 t3 = newTemp(Ity_V128);
6154 assign(t1, getWReg(ws));
6155 assign(t2, getWReg(wt));
6156 assign(t3, binop(Iop_Add32x4, mkexpr(t1), mkexpr(t2)));
6157 putWReg(wd, mkexpr(t3));
6158 break;
6161 case 0x03: { /* ADDV.D */
6162 DIP("ADDV.D w%d, w%d, w%d", wd, ws, wt);
6163 t1 = newTemp(Ity_V128);
6164 t2 = newTemp(Ity_V128);
6165 t3 = newTemp(Ity_V128);
6166 assign(t1, getWReg(ws));
6167 assign(t2, getWReg(wt));
6168 assign(t3, binop(Iop_Add64x2, mkexpr(t1), mkexpr(t2)));
6169 putWReg(wd, mkexpr(t3));
6170 break;
6173 default:
6174 return -1;
6177 break;
6180 case 0x01: { /* SUBV.df */
6181 switch (df) {
6182 case 0x00: { /* SUBV.B */
6183 DIP("SUBV.B w%d, w%d, w%d", wd, ws, wt);
6184 t1 = newTemp(Ity_V128);
6185 t2 = newTemp(Ity_V128);
6186 t3 = newTemp(Ity_V128);
6187 assign(t1, getWReg(ws));
6188 assign(t2, getWReg(wt));
6189 assign(t3, binop(Iop_Sub8x16, mkexpr(t1), mkexpr(t2)));
6190 putWReg(wd, mkexpr(t3));
6191 break;
6194 case 0x01: { /* SUBV.H */
6195 DIP("SUBV.H w%d, w%d, w%d", wd, ws, wt);
6196 t1 = newTemp(Ity_V128);
6197 t2 = newTemp(Ity_V128);
6198 t3 = newTemp(Ity_V128);
6199 assign(t1, getWReg(ws));
6200 assign(t2, getWReg(wt));
6201 assign(t3, binop(Iop_Sub16x8, mkexpr(t1), mkexpr(t2)));
6202 putWReg(wd, mkexpr(t3));
6203 break;
6206 case 0x02: { /* SUBV.W */
6207 DIP("SUBV.W w%d, w%d, w%d", wd, ws, wt);
6208 t1 = newTemp(Ity_V128);
6209 t2 = newTemp(Ity_V128);
6210 t3 = newTemp(Ity_V128);
6211 assign(t1, getWReg(ws));
6212 assign(t2, getWReg(wt));
6213 assign(t3, binop(Iop_Sub32x4, mkexpr(t1), mkexpr(t2)));
6214 putWReg(wd, mkexpr(t3));
6215 break;
6218 case 0x03: { /* SUBV.D */
6219 DIP("SUBV.D w%d, w%d, w%d", wd, ws, wt);
6220 t1 = newTemp(Ity_V128);
6221 t2 = newTemp(Ity_V128);
6222 t3 = newTemp(Ity_V128);
6223 assign(t1, getWReg(ws));
6224 assign(t2, getWReg(wt));
6225 assign(t3, binop(Iop_Sub64x2, mkexpr(t1), mkexpr(t2)));
6226 putWReg(wd, mkexpr(t3));
6227 break;
6230 default:
6231 return -1;
6234 break;
6237 case 0x02: { /* MAX_S.df */
6238 switch (df) {
6239 case 0x00: { /* MAX_S.B */
6240 DIP("MAX_S.B w%d, w%d, w%d", wd, ws, wt);
6241 t1 = newTemp(Ity_V128);
6242 t2 = newTemp(Ity_V128);
6243 t3 = newTemp(Ity_V128);
6244 assign(t1, getWReg(ws));
6245 assign(t2, getWReg(wt));
6246 assign(t3, binop(Iop_Max8Sx16, mkexpr(t1), mkexpr(t2)));
6247 putWReg(wd, mkexpr(t3));
6248 break;
6251 case 0x01: { /* MAX_S.H */
6252 DIP("MAX_S.H w%d, w%d, w%d", wd, ws, wt);
6253 t1 = newTemp(Ity_V128);
6254 t2 = newTemp(Ity_V128);
6255 t3 = newTemp(Ity_V128);
6256 assign(t1, getWReg(ws));
6257 assign(t2, getWReg(wt));
6258 assign(t3, binop(Iop_Max16Sx8, mkexpr(t1), mkexpr(t2)));
6259 putWReg(wd, mkexpr(t3));
6260 break;
6263 case 0x02: { /* MAX_S.W */
6264 DIP("MAX_S.W w%d, w%d, w%d", wd, ws, wt);
6265 t1 = newTemp(Ity_V128);
6266 t2 = newTemp(Ity_V128);
6267 t3 = newTemp(Ity_V128);
6268 assign(t1, getWReg(ws));
6269 assign(t2, getWReg(wt));
6270 assign(t3, binop(Iop_Max32Sx4, mkexpr(t1), mkexpr(t2)));
6271 putWReg(wd, mkexpr(t3));
6272 break;
6275 case 0x03: { /* MAX_S.D */
6276 DIP("MAX_S.D w%d, w%d, w%d", wd, ws, wt);
6277 t1 = newTemp(Ity_V128);
6278 t2 = newTemp(Ity_V128);
6279 t3 = newTemp(Ity_V128);
6280 assign(t1, getWReg(ws));
6281 assign(t2, getWReg(wt));
6282 assign(t3, binop(Iop_Max64Sx2, mkexpr(t1), mkexpr(t2)));
6283 putWReg(wd, mkexpr(t3));
6284 break;
6287 default:
6288 return -1;
6291 break;
6294 case 0x03: { /* MAX_U.df */
6295 switch (df) {
6296 case 0x00: { /* MAX_U.B */
6297 DIP("MAX_U.B w%d, w%d, w%d", wd, ws, wt);
6298 t1 = newTemp(Ity_V128);
6299 t2 = newTemp(Ity_V128);
6300 t3 = newTemp(Ity_V128);
6301 assign(t1, getWReg(ws));
6302 assign(t2, getWReg(wt));
6303 assign(t3, binop(Iop_Max8Ux16, mkexpr(t1), mkexpr(t2)));
6304 putWReg(wd, mkexpr(t3));
6305 break;
6308 case 0x01: { /* MAX_U.H */
6309 DIP("MAX_U.H w%d, w%d, w%d", wd, ws, wt);
6310 t1 = newTemp(Ity_V128);
6311 t2 = newTemp(Ity_V128);
6312 t3 = newTemp(Ity_V128);
6313 assign(t1, getWReg(ws));
6314 assign(t2, getWReg(wt));
6315 assign(t3, binop(Iop_Max16Ux8, mkexpr(t1), mkexpr(t2)));
6316 putWReg(wd, mkexpr(t3));
6317 break;
6320 case 0x02: { /* MAX_U.W */
6321 DIP("MAX_U.W w%d, w%d, w%d", wd, ws, wt);
6322 t1 = newTemp(Ity_V128);
6323 t2 = newTemp(Ity_V128);
6324 t3 = newTemp(Ity_V128);
6325 assign(t1, getWReg(ws));
6326 assign(t2, getWReg(wt));
6327 assign(t3, binop(Iop_Max32Ux4, mkexpr(t1), mkexpr(t2)));
6328 putWReg(wd, mkexpr(t3));
6329 break;
6332 case 0x03: { /* MAX_U.D */
6333 DIP("MAX_U.D w%d, w%d, w%d", wd, ws, wt);
6334 t1 = newTemp(Ity_V128);
6335 t2 = newTemp(Ity_V128);
6336 t3 = newTemp(Ity_V128);
6337 assign(t1, getWReg(ws));
6338 assign(t2, getWReg(wt));
6339 assign(t3, binop(Iop_Max64Ux2, mkexpr(t1), mkexpr(t2)));
6340 putWReg(wd, mkexpr(t3));
6341 break;
6344 default:
6345 return -1;
6348 break;
6351 case 0x04: { /* MIN_S.df */
6352 switch (df) {
6353 case 0x00: { /* MIN_S.B */
6354 DIP("MIN_S.B w%d, w%d, w%d", wd, ws, wt);
6355 t1 = newTemp(Ity_V128);
6356 t2 = newTemp(Ity_V128);
6357 t3 = newTemp(Ity_V128);
6358 assign(t1, getWReg(ws));
6359 assign(t2, getWReg(wt));
6360 assign(t3, binop(Iop_Min8Sx16, mkexpr(t1), mkexpr(t2)));
6361 putWReg(wd, mkexpr(t3));
6362 break;
6365 case 0x01: { /* MIN_S.H */
6366 DIP("MIN_S.H w%d, w%d, w%d", wd, ws, wt);
6367 t1 = newTemp(Ity_V128);
6368 t2 = newTemp(Ity_V128);
6369 t3 = newTemp(Ity_V128);
6370 assign(t1, getWReg(ws));
6371 assign(t2, getWReg(wt));
6372 assign(t3, binop(Iop_Min16Sx8, mkexpr(t1), mkexpr(t2)));
6373 putWReg(wd, mkexpr(t3));
6374 break;
6377 case 0x02: { /* MIN_S.W */
6378 DIP("MIN_S.W w%d, w%d, w%d", wd, ws, wt);
6379 t1 = newTemp(Ity_V128);
6380 t2 = newTemp(Ity_V128);
6381 t3 = newTemp(Ity_V128);
6382 assign(t1, getWReg(ws));
6383 assign(t2, getWReg(wt));
6384 assign(t3, binop(Iop_Min32Sx4, mkexpr(t1), mkexpr(t2)));
6385 putWReg(wd, mkexpr(t3));
6386 break;
6389 case 0x03: { /* MIN_S.D */
6390 DIP("MIN_S.D w%d, w%d, w%d", wd, ws, wt);
6391 t1 = newTemp(Ity_V128);
6392 t2 = newTemp(Ity_V128);
6393 t3 = newTemp(Ity_V128);
6394 assign(t1, getWReg(ws));
6395 assign(t2, getWReg(wt));
6396 assign(t3, binop(Iop_Min64Sx2, mkexpr(t1), mkexpr(t2)));
6397 putWReg(wd, mkexpr(t3));
6398 break;
6401 default:
6402 return -1;
6405 break;
6408 case 0x05: { /* MIN_U.df */
6409 switch (df) {
6410 case 0x00: { /* MIN_U.B */
6411 DIP("MIN_U.B w%d, w%d, w%d", wd, ws, wt);
6412 t1 = newTemp(Ity_V128);
6413 t2 = newTemp(Ity_V128);
6414 t3 = newTemp(Ity_V128);
6415 assign(t1, getWReg(ws));
6416 assign(t2, getWReg(wt));
6417 assign(t3, binop(Iop_Min8Ux16, mkexpr(t1), mkexpr(t2)));
6418 putWReg(wd, mkexpr(t3));
6419 break;
6422 case 0x01: { /* MIN_U.H */
6423 DIP("MIN_U.H w%d, w%d, w%d", wd, ws, wt);
6424 t1 = newTemp(Ity_V128);
6425 t2 = newTemp(Ity_V128);
6426 t3 = newTemp(Ity_V128);
6427 assign(t1, getWReg(ws));
6428 assign(t2, getWReg(wt));
6429 assign(t3, binop(Iop_Min16Ux8, mkexpr(t1), mkexpr(t2)));
6430 putWReg(wd, mkexpr(t3));
6431 break;
6434 case 0x02: { /* MIN_U.W */
6435 DIP("MIN_U.W w%d, w%d, w%d", wd, ws, wt);
6436 t1 = newTemp(Ity_V128);
6437 t2 = newTemp(Ity_V128);
6438 t3 = newTemp(Ity_V128);
6439 assign(t1, getWReg(ws));
6440 assign(t2, getWReg(wt));
6441 assign(t3, binop(Iop_Min32Ux4, mkexpr(t1), mkexpr(t2)));
6442 putWReg(wd, mkexpr(t3));
6443 break;
6446 case 0x03: { /* MIN_U.D */
6447 DIP("MIN_U.D w%d, w%d, w%d", wd, ws, wt);
6448 t1 = newTemp(Ity_V128);
6449 t2 = newTemp(Ity_V128);
6450 t3 = newTemp(Ity_V128);
6451 assign(t1, getWReg(ws));
6452 assign(t2, getWReg(wt));
6453 assign(t3, binop(Iop_Min64Ux2, mkexpr(t1), mkexpr(t2)));
6454 putWReg(wd, mkexpr(t3));
6455 break;
6458 default:
6459 return -1;
6462 break;
6465 case 0x06: { /* MAX_A.df */
6466 switch (df) {
6467 case 0x00: { /* MAX_A.B */
6468 DIP("MAX_A.B w%d, w%d, w%d", wd, ws, wt);
6469 t1 = newTemp(Ity_V128);
6470 t2 = newTemp(Ity_V128);
6471 t3 = newTemp(Ity_V128);
6472 t4 = newTemp(Ity_V128);
6473 assign(t1, unop(Iop_Abs8x16, getWReg(ws)));
6474 assign(t2, unop(Iop_Abs8x16, getWReg(wt)));
6475 assign(t4, binop(Iop_CmpGT8Ux16, mkexpr(t1), mkexpr(t2)));
6476 assign(t3, binop(Iop_OrV128,
6477 binop(Iop_AndV128,
6478 mkexpr(t4),
6479 getWReg(ws)),
6480 binop(Iop_AndV128,
6481 unop(Iop_NotV128, mkexpr(t4)),
6482 getWReg(wt))));
6483 putWReg(wd, mkexpr(t3));
6484 break;
6487 case 0x01: { /* MAX_A.H */
6488 DIP("MAX_A.H w%d, w%d, w%d", wd, ws, wt);
6489 t1 = newTemp(Ity_V128);
6490 t2 = newTemp(Ity_V128);
6491 t3 = newTemp(Ity_V128);
6492 t4 = newTemp(Ity_V128);
6493 assign(t1, unop(Iop_Abs16x8, getWReg(ws)));
6494 assign(t2, unop(Iop_Abs16x8, getWReg(wt)));
6495 assign(t4, binop(Iop_CmpGT16Ux8, mkexpr(t1), mkexpr(t2)));
6496 assign(t3, binop(Iop_OrV128,
6497 binop(Iop_AndV128,
6498 mkexpr(t4),
6499 getWReg(ws)),
6500 binop(Iop_AndV128,
6501 unop(Iop_NotV128, mkexpr(t4)),
6502 getWReg(wt))));
6503 putWReg(wd, mkexpr(t3));
6504 break;
6507 case 0x02: { /* MAX_A.W */
6508 DIP("MAX_A.W w%d, w%d, w%d", wd, ws, wt);
6509 t1 = newTemp(Ity_V128);
6510 t2 = newTemp(Ity_V128);
6511 t3 = newTemp(Ity_V128);
6512 t4 = newTemp(Ity_V128);
6513 assign(t1, unop(Iop_Abs32x4, getWReg(ws)));
6514 assign(t2, unop(Iop_Abs32x4, getWReg(wt)));
6515 assign(t4, binop(Iop_CmpGT32Ux4, mkexpr(t1), mkexpr(t2)));
6516 assign(t3, binop(Iop_OrV128,
6517 binop(Iop_AndV128,
6518 mkexpr(t4),
6519 getWReg(ws)),
6520 binop(Iop_AndV128,
6521 unop(Iop_NotV128, mkexpr(t4)),
6522 getWReg(wt))));
6523 putWReg(wd, mkexpr(t3));
6524 break;
6527 case 0x03: { /* MAX_A.D */
6528 DIP("MAX_A.D w%d, w%d, w%d", wd, ws, wt);
6529 t1 = newTemp(Ity_V128);
6530 t2 = newTemp(Ity_V128);
6531 t3 = newTemp(Ity_V128);
6532 t4 = newTemp(Ity_V128);
6533 assign(t1, unop(Iop_Abs64x2, getWReg(ws)));
6534 assign(t2, unop(Iop_Abs64x2, getWReg(wt)));
6535 assign(t4, binop(Iop_CmpGT64Ux2, mkexpr(t1), mkexpr(t2)));
6536 assign(t3, binop(Iop_OrV128,
6537 binop(Iop_AndV128,
6538 mkexpr(t4),
6539 getWReg(ws)),
6540 binop(Iop_AndV128,
6541 unop(Iop_NotV128, mkexpr(t4)),
6542 getWReg(wt))));
6543 putWReg(wd, mkexpr(t3));
6544 break;
6547 default:
6548 return -1;
6551 break;
6554 case 0x07: { /* MIN_A.df */
6555 switch (df) {
6556 case 0x00: { /* MIN_A.B */
6557 DIP("MIN_A.B w%d, w%d, w%d", wd, ws, wt);
6558 t1 = newTemp(Ity_V128);
6559 t2 = newTemp(Ity_V128);
6560 t3 = newTemp(Ity_V128);
6561 t4 = newTemp(Ity_V128);
6562 assign(t1, unop(Iop_Abs8x16, getWReg(ws)));
6563 assign(t2, unop(Iop_Abs8x16, getWReg(wt)));
6564 assign(t4, binop(Iop_OrV128,
6565 binop(Iop_CmpGT8Ux16,
6566 mkexpr(t1), mkexpr(t2)),
6567 binop(Iop_CmpEQ8x16,
6568 mkexpr(t1), mkexpr(t2))));
6569 assign(t3, binop(Iop_OrV128,
6570 binop(Iop_AndV128,
6571 mkexpr(t4),
6572 getWReg(wt)),
6573 binop(Iop_AndV128,
6574 unop(Iop_NotV128, mkexpr(t4)),
6575 getWReg(ws))));
6576 putWReg(wd, mkexpr(t3));
6577 break;
6580 case 0x01: { /* MIN_A.H */
6581 DIP("MIN_A.H w%d, w%d, w%d", wd, ws, wt);
6582 t1 = newTemp(Ity_V128);
6583 t2 = newTemp(Ity_V128);
6584 t3 = newTemp(Ity_V128);
6585 t4 = newTemp(Ity_V128);
6586 assign(t1, unop(Iop_Abs16x8, getWReg(ws)));
6587 assign(t2, unop(Iop_Abs16x8, getWReg(wt)));
6588 assign(t4, binop(Iop_OrV128,
6589 binop(Iop_CmpGT16Ux8,
6590 mkexpr(t1), mkexpr(t2)),
6591 binop(Iop_CmpEQ16x8,
6592 mkexpr(t1), mkexpr(t2))));
6593 assign(t3, binop(Iop_OrV128,
6594 binop(Iop_AndV128,
6595 mkexpr(t4),
6596 getWReg(wt)),
6597 binop(Iop_AndV128,
6598 unop(Iop_NotV128, mkexpr(t4)),
6599 getWReg(ws))));
6600 putWReg(wd, mkexpr(t3));
6601 break;
6604 case 0x02: { /* MIN_A.W */
6605 DIP("MIN_A.W w%d, w%d, w%d", wd, ws, wt);
6606 t1 = newTemp(Ity_V128);
6607 t2 = newTemp(Ity_V128);
6608 t3 = newTemp(Ity_V128);
6609 t4 = newTemp(Ity_V128);
6610 assign(t1, unop(Iop_Abs32x4, getWReg(ws)));
6611 assign(t2, unop(Iop_Abs32x4, getWReg(wt)));
6612 assign(t4, binop(Iop_OrV128,
6613 binop(Iop_CmpGT32Ux4,
6614 mkexpr(t1), mkexpr(t2)),
6615 binop(Iop_CmpEQ32x4,
6616 mkexpr(t1), mkexpr(t2))));
6617 assign(t3, binop(Iop_OrV128,
6618 binop(Iop_AndV128,
6619 mkexpr(t4),
6620 getWReg(wt)),
6621 binop(Iop_AndV128,
6622 unop(Iop_NotV128, mkexpr(t4)),
6623 getWReg(ws))));
6624 putWReg(wd, mkexpr(t3));
6625 break;
6628 case 0x03: { /* MIN_A.D */
6629 DIP("MIN_A.D w%d, w%d, w%d", wd, ws, wt);
6630 t1 = newTemp(Ity_V128);
6631 t2 = newTemp(Ity_V128);
6632 t3 = newTemp(Ity_V128);
6633 t4 = newTemp(Ity_V128);
6634 assign(t1, unop(Iop_Abs64x2, getWReg(ws)));
6635 assign(t2, unop(Iop_Abs64x2, getWReg(wt)));
6636 assign(t4, binop(Iop_OrV128,
6637 binop(Iop_CmpGT64Ux2,
6638 mkexpr(t1), mkexpr(t2)),
6639 binop(Iop_CmpEQ64x2,
6640 mkexpr(t1), mkexpr(t2))));
6641 assign(t3, binop(Iop_OrV128,
6642 binop(Iop_AndV128,
6643 mkexpr(t4),
6644 getWReg(wt)),
6645 binop(Iop_AndV128,
6646 unop(Iop_NotV128, mkexpr(t4)),
6647 getWReg(ws))));
6648 putWReg(wd, mkexpr(t3));
6649 break;
6652 default:
6653 return -1;
6656 break;
6659 default:
6660 return -1;
6663 return 0;
6666 static Int msa_3R_0F(UInt cins, UChar wd, UChar ws) /* 3R (0x0F) */
6668 IRTemp t1, t2, t3;
6669 UShort operation;
6670 UChar df, wt;
6672 operation = (cins & 0x03800000) >> 23;
6673 df = (cins & 0x00600000) >> 21;
6674 wt = (cins & 0x001F0000) >> 16;
6676 switch (operation) {
6677 case 0x00: { /* CEQ.df */
6678 switch (df) {
6679 case 0x00: { /* CEQ.B */
6680 DIP("CEQ.B w%d, w%d, w%d", wd, ws, wt);
6681 t1 = newTemp(Ity_V128);
6682 t2 = newTemp(Ity_V128);
6683 t3 = newTemp(Ity_V128);
6684 assign(t1, getWReg(ws));
6685 assign(t2, getWReg(wt));
6686 assign(t3, binop(Iop_CmpEQ8x16, mkexpr(t1), mkexpr(t2)));
6687 putWReg(wd, mkexpr(t3));
6688 break;
6691 case 0x01: { /* CEQ.H */
6692 DIP("CEQ.H w%d, w%d, w%d", wd, ws, wt);
6693 t1 = newTemp(Ity_V128);
6694 t2 = newTemp(Ity_V128);
6695 t3 = newTemp(Ity_V128);
6696 assign(t1, getWReg(ws));
6697 assign(t2, getWReg(wt));
6698 assign(t3, binop(Iop_CmpEQ16x8, mkexpr(t1), mkexpr(t2)));
6699 putWReg(wd, mkexpr(t3));
6700 break;
6703 case 0x02: { /* CEQ.W */
6704 DIP("CEQ.W w%d, w%d, w%d", wd, ws, wt);
6705 t1 = newTemp(Ity_V128);
6706 t2 = newTemp(Ity_V128);
6707 t3 = newTemp(Ity_V128);
6708 assign(t1, getWReg(ws));
6709 assign(t2, getWReg(wt));
6710 assign(t3, binop(Iop_CmpEQ32x4, mkexpr(t1), mkexpr(t2)));
6711 putWReg(wd, mkexpr(t3));
6712 break;
6715 case 0x03: { /* CEQ.D */
6716 DIP("CEQ.D w%d, w%d, w%d", wd, ws, wt);
6717 t1 = newTemp(Ity_V128);
6718 t2 = newTemp(Ity_V128);
6719 t3 = newTemp(Ity_V128);
6720 assign(t1, getWReg(ws));
6721 assign(t2, getWReg(wt));
6722 assign(t3, binop(Iop_CmpEQ64x2, mkexpr(t1), mkexpr(t2)));
6723 putWReg(wd, mkexpr(t3));
6724 break;
6727 default:
6728 return -1;
6731 break;
6734 case 0x02: { /* CLT_S.df */
6735 switch (df) {
6736 case 0x00: { /* CLT_S.B */
6737 DIP("CLT_S.B w%d, w%d, w%d", wd, ws, wt);
6738 t1 = newTemp(Ity_V128);
6739 t2 = newTemp(Ity_V128);
6740 t3 = newTemp(Ity_V128);
6741 assign(t1, getWReg(ws));
6742 assign(t2, getWReg(wt));
6743 assign(t3, binop(Iop_CmpGT8Sx16, mkexpr(t2), mkexpr(t1)));
6744 putWReg(wd, mkexpr(t3));
6745 break;
6748 case 0x01: { /* CLT_S.H */
6749 DIP("CLT_S.H w%d, w%d, w%d", wd, ws, wt);
6750 t1 = newTemp(Ity_V128);
6751 t2 = newTemp(Ity_V128);
6752 t3 = newTemp(Ity_V128);
6753 assign(t1, getWReg(ws));
6754 assign(t2, getWReg(wt));
6755 assign(t3, binop(Iop_CmpGT16Sx8, mkexpr(t2), mkexpr(t1)));
6756 putWReg(wd, mkexpr(t3));
6757 break;
6760 case 0x02: { /* CLT_S.W */
6761 DIP("CLT_S.W w%d, w%d, w%d", wd, ws, wt);
6762 t1 = newTemp(Ity_V128);
6763 t2 = newTemp(Ity_V128);
6764 t3 = newTemp(Ity_V128);
6765 assign(t1, getWReg(ws));
6766 assign(t2, getWReg(wt));
6767 assign(t3, binop(Iop_CmpGT32Sx4, mkexpr(t2), mkexpr(t1)));
6768 putWReg(wd, mkexpr(t3));
6769 break;
6772 case 0x03: { /* CLT_S.D */
6773 DIP("CLT_S.D w%d, w%d, w%d", wd, ws, wt);
6774 t1 = newTemp(Ity_V128);
6775 t2 = newTemp(Ity_V128);
6776 t3 = newTemp(Ity_V128);
6777 assign(t1, getWReg(ws));
6778 assign(t2, getWReg(wt));
6779 assign(t3, binop(Iop_CmpGT64Sx2, mkexpr(t2), mkexpr(t1)));
6780 putWReg(wd, mkexpr(t3));
6781 break;
6784 default:
6785 return -1;
6788 break;
6791 case 0x03: { /* CLT_U.df */
6792 switch (df) {
6793 case 0x00: { /* CLT_U.B */
6794 DIP("CLT_U.B w%d, w%d, w%d", wd, ws, wt);
6795 t1 = newTemp(Ity_V128);
6796 t2 = newTemp(Ity_V128);
6797 t3 = newTemp(Ity_V128);
6798 assign(t1, getWReg(ws));
6799 assign(t2, getWReg(wt));
6800 assign(t3, binop(Iop_CmpGT8Ux16, mkexpr(t2), mkexpr(t1)));
6801 putWReg(wd, mkexpr(t3));
6802 break;
6805 case 0x01: { /* CLT_U.H */
6806 DIP("CLT_U.H w%d, w%d, w%d", wd, ws, wt);
6807 t1 = newTemp(Ity_V128);
6808 t2 = newTemp(Ity_V128);
6809 t3 = newTemp(Ity_V128);
6810 assign(t1, getWReg(ws));
6811 assign(t2, getWReg(wt));
6812 assign(t3, binop(Iop_CmpGT16Ux8, mkexpr(t2), mkexpr(t1)));
6813 putWReg(wd, mkexpr(t3));
6814 break;
6817 case 0x02: { /* CLT_U.W */
6818 DIP("CLT_U.W w%d, w%d, w%d", wd, ws, wt);
6819 t1 = newTemp(Ity_V128);
6820 t2 = newTemp(Ity_V128);
6821 t3 = newTemp(Ity_V128);
6822 assign(t1, getWReg(ws));
6823 assign(t2, getWReg(wt));
6824 assign(t3, binop(Iop_CmpGT32Ux4, mkexpr(t2), mkexpr(t1)));
6825 putWReg(wd, mkexpr(t3));
6826 break;
6829 case 0x03: { /* CLT_U.D */
6830 DIP("CLT_U.D w%d, w%d, w%d", wd, ws, wt);
6831 t1 = newTemp(Ity_V128);
6832 t2 = newTemp(Ity_V128);
6833 t3 = newTemp(Ity_V128);
6834 assign(t1, getWReg(ws));
6835 assign(t2, getWReg(wt));
6836 assign(t3, binop(Iop_CmpGT64Ux2, mkexpr(t2), mkexpr(t1)));
6837 putWReg(wd, mkexpr(t3));
6838 break;
6841 default:
6842 return -1;
6845 break;
6848 case 0x04: { /* CLE_S.df */
6849 switch (df) {
6850 case 0x00: { /* CLE_S.B */
6851 DIP("CLE_S.B w%d, w%d, w%d", wd, ws, wt);
6852 t1 = newTemp(Ity_V128);
6853 t2 = newTemp(Ity_V128);
6854 t3 = newTemp(Ity_V128);
6855 assign(t1, getWReg(ws));
6856 assign(t2, getWReg(wt));
6857 assign(t3, binop(Iop_OrV128,
6858 binop(Iop_CmpGT8Sx16,
6859 mkexpr(t2), mkexpr(t1)),
6860 binop(Iop_CmpEQ8x16,
6861 mkexpr(t1), mkexpr(t2))));
6862 putWReg(wd, mkexpr(t3));
6863 break;
6866 case 0x01: { /* CLE_S.H */
6867 DIP("CLE_S.H w%d, w%d, w%d", wd, ws, wt);
6868 t1 = newTemp(Ity_V128);
6869 t2 = newTemp(Ity_V128);
6870 t3 = newTemp(Ity_V128);
6871 assign(t1, getWReg(ws));
6872 assign(t2, getWReg(wt));
6873 assign(t3, binop(Iop_OrV128,
6874 binop(Iop_CmpGT16Sx8,
6875 mkexpr(t2), mkexpr(t1)),
6876 binop(Iop_CmpEQ16x8,
6877 mkexpr(t1), mkexpr(t2))));
6878 putWReg(wd, mkexpr(t3));
6879 break;
6882 case 0x02: { /* CLE_S.W */
6883 DIP("CLE_S.W w%d, w%d, w%d", wd, ws, wt);
6884 t1 = newTemp(Ity_V128);
6885 t2 = newTemp(Ity_V128);
6886 t3 = newTemp(Ity_V128);
6887 assign(t1, getWReg(ws));
6888 assign(t2, getWReg(wt));
6889 assign(t3, binop(Iop_OrV128,
6890 binop(Iop_CmpGT32Sx4,
6891 mkexpr(t2), mkexpr(t1)),
6892 binop(Iop_CmpEQ32x4,
6893 mkexpr(t1), mkexpr(t2))));
6894 putWReg(wd, mkexpr(t3));
6895 break;
6898 case 0x03: { /* CLE_S.D */
6899 DIP("CLE_S.D w%d, w%d, w%d", wd, ws, wt);
6900 t1 = newTemp(Ity_V128);
6901 t2 = newTemp(Ity_V128);
6902 t3 = newTemp(Ity_V128);
6903 assign(t1, getWReg(ws));
6904 assign(t2, getWReg(wt));
6905 assign(t3, binop(Iop_OrV128,
6906 binop(Iop_CmpGT64Sx2,
6907 mkexpr(t2), mkexpr(t1)),
6908 binop(Iop_CmpEQ64x2,
6909 mkexpr(t1), mkexpr(t2))));
6910 putWReg(wd, mkexpr(t3));
6911 break;
6914 default:
6915 return -1;
6918 break;
6921 case 0x05: { /* CLE_U.df */
6922 switch (df) {
6923 case 0x00: { /* CLE_U.B */
6924 DIP("CLE_U.B w%d, w%d, w%d", wd, ws, wt);
6925 t1 = newTemp(Ity_V128);
6926 t2 = newTemp(Ity_V128);
6927 t3 = newTemp(Ity_V128);
6928 assign(t1, getWReg(ws));
6929 assign(t2, getWReg(wt));
6930 assign(t3, binop(Iop_OrV128,
6931 binop(Iop_CmpGT8Ux16,
6932 mkexpr(t2), mkexpr(t1)),
6933 binop(Iop_CmpEQ8x16,
6934 mkexpr(t1), mkexpr(t2))));
6935 putWReg(wd, mkexpr(t3));
6936 break;
6939 case 0x01: { /* CLE_U.H */
6940 DIP("CLE_U.H w%d, w%d, w%d", wd, ws, wt);
6941 t1 = newTemp(Ity_V128);
6942 t2 = newTemp(Ity_V128);
6943 t3 = newTemp(Ity_V128);
6944 assign(t1, getWReg(ws));
6945 assign(t2, getWReg(wt));
6946 assign(t3, binop(Iop_OrV128,
6947 binop(Iop_CmpGT16Ux8,
6948 mkexpr(t2), mkexpr(t1)),
6949 binop(Iop_CmpEQ16x8,
6950 mkexpr(t1), mkexpr(t2))));
6951 putWReg(wd, mkexpr(t3));
6952 break;
6955 case 0x02: { /* CLE_U.W */
6956 DIP("CLE_U.W w%d, w%d, w%d", wd, ws, wt);
6957 t1 = newTemp(Ity_V128);
6958 t2 = newTemp(Ity_V128);
6959 t3 = newTemp(Ity_V128);
6960 assign(t1, getWReg(ws));
6961 assign(t2, getWReg(wt));
6962 assign(t3, binop(Iop_OrV128,
6963 binop(Iop_CmpGT32Ux4,
6964 mkexpr(t2), mkexpr(t1)),
6965 binop(Iop_CmpEQ32x4,
6966 mkexpr(t1), mkexpr(t2))));
6967 putWReg(wd, mkexpr(t3));
6968 break;
6971 case 0x03: { /* CLE_U.D */
6972 DIP("CLE_U.D w%d, w%d, w%d", wd, ws, wt);
6973 t1 = newTemp(Ity_V128);
6974 t2 = newTemp(Ity_V128);
6975 t3 = newTemp(Ity_V128);
6976 assign(t1, getWReg(ws));
6977 assign(t2, getWReg(wt));
6978 assign(t3,
6979 binop(Iop_OrV128,
6980 binop(Iop_CmpGT64Ux2,
6981 mkexpr(t2), mkexpr(t1)),
6982 binop(Iop_CmpEQ64x2,
6983 mkexpr(t1), mkexpr(t2))));
6984 putWReg(wd, mkexpr(t3));
6985 break;
6988 default:
6989 return -1;
6992 break;
6995 default:
6996 return -1;
6999 return 0;
7002 static Int msa_3R_10(UInt cins, UChar wd, UChar ws) /* 3R (0x10) */
7004 IRTemp t1, t2, t3, t4;
7005 UShort operation;
7006 UChar df, wt;
7008 operation = (cins & 0x03800000) >> 23;
7009 df = (cins & 0x00600000) >> 21;
7010 wt = (cins & 0x001F0000) >> 16;
7012 switch (operation) {
7013 case 0x00: { /* ADD_A.df */
7014 switch (df) {
7015 case 0x00: { /* ADD_A.B */
7016 DIP("ADD_A.B w%d, w%d, w%d", wd, ws, wt);
7017 t1 = newTemp(Ity_V128);
7018 t2 = newTemp(Ity_V128);
7019 t3 = newTemp(Ity_V128);
7020 assign(t1, unop(Iop_Abs8x16, getWReg(ws)));
7021 assign(t2, unop(Iop_Abs8x16, getWReg(wt)));
7022 assign(t3, binop(Iop_Add8x16, mkexpr(t1), mkexpr(t2)));
7023 putWReg(wd, mkexpr(t3));
7024 break;
7027 case 0x01: { /* ADD_A.H */
7028 DIP("ADD_A.H w%d, w%d, w%d", wd, ws, wt);
7029 t1 = newTemp(Ity_V128);
7030 t2 = newTemp(Ity_V128);
7031 t3 = newTemp(Ity_V128);
7032 assign(t1, unop(Iop_Abs16x8, getWReg(ws)));
7033 assign(t2, unop(Iop_Abs16x8, getWReg(wt)));
7034 assign(t3, binop(Iop_Add16x8, mkexpr(t1), mkexpr(t2)));
7035 putWReg(wd, mkexpr(t3));
7036 break;
7039 case 0x02: { /* ADD_A.W */
7040 DIP("ADD_A.W w%d, w%d, w%d", wd, ws, wt);
7041 t1 = newTemp(Ity_V128);
7042 t2 = newTemp(Ity_V128);
7043 t3 = newTemp(Ity_V128);
7044 assign(t1, unop(Iop_Abs32x4, getWReg(ws)));
7045 assign(t2, unop(Iop_Abs32x4, getWReg(wt)));
7046 assign(t3, binop(Iop_Add32x4, mkexpr(t1), mkexpr(t2)));
7047 putWReg(wd, mkexpr(t3));
7048 break;
7051 case 0x03: { /* ADD_A.D */
7052 DIP("ADD_A.D w%d, w%d, w%d", wd, ws, wt);
7053 t1 = newTemp(Ity_V128);
7054 t2 = newTemp(Ity_V128);
7055 t3 = newTemp(Ity_V128);
7056 assign(t1, unop(Iop_Abs64x2, getWReg(ws)));
7057 assign(t2, unop(Iop_Abs64x2, getWReg(wt)));
7058 assign(t3, binop(Iop_Add64x2, mkexpr(t1), mkexpr(t2)));
7059 putWReg(wd, mkexpr(t3));
7060 break;
7063 default:
7064 return -1;
7067 break;
7070 case 0x01: { /* ADDS_A.df */
7071 switch (df) {
7072 case 0x00: { /* ADDS_A.B */
7073 DIP("ADDS_A.B w%d, w%d, w%d", wd, ws, wt);
7074 t1 = newTemp(Ity_V128);
7075 t2 = newTemp(Ity_V128);
7076 t3 = newTemp(Ity_V128);
7077 t4 = newTemp(Ity_V128);
7078 assign(t1, unop(Iop_Abs8x16, getWReg(ws)));
7079 assign(t2, unop(Iop_Abs8x16, getWReg(wt)));
7080 assign(t3, binop(Iop_SarN8x16,
7081 binop(Iop_AndV128,
7082 mkexpr(t1),
7083 getWReg(ws)),
7084 mkU8(7)));
7085 assign(t4, binop(Iop_SarN8x16,
7086 binop(Iop_AndV128,
7087 mkexpr(t2),
7088 getWReg(wt)),
7089 mkU8(7)));
7090 putWReg(wd, binop(Iop_QAdd8Sx16,
7091 binop(Iop_OrV128,
7092 binop(Iop_AndV128,
7093 unop(Iop_NotV128,
7094 mkexpr(t3)),
7095 mkexpr(t1)),
7096 binop(Iop_AndV128,
7097 unop(Iop_NotV128,
7098 mkexpr(t1)),
7099 mkexpr(t3))),
7100 binop(Iop_OrV128,
7101 binop(Iop_AndV128,
7102 unop(Iop_NotV128,
7103 mkexpr(t4)),
7104 mkexpr(t2)),
7105 binop(Iop_AndV128,
7106 unop(Iop_NotV128,
7107 mkexpr(t2)),
7108 mkexpr(t4)))));
7109 break;
7112 case 0x01: { /* ADDS_A.H */
7113 DIP("ADDS_A.H w%d, w%d, w%d", wd, ws, wt);
7114 t1 = newTemp(Ity_V128);
7115 t2 = newTemp(Ity_V128);
7116 t3 = newTemp(Ity_V128);
7117 t4 = newTemp(Ity_V128);
7118 assign(t1, unop(Iop_Abs16x8, getWReg(ws)));
7119 assign(t2, unop(Iop_Abs16x8, getWReg(wt)));
7120 assign(t3, binop(Iop_SarN16x8,
7121 binop(Iop_AndV128,
7122 mkexpr(t1),
7123 getWReg(ws)),
7124 mkU8(15)));
7125 assign(t4, binop(Iop_SarN16x8,
7126 binop(Iop_AndV128,
7127 mkexpr(t2),
7128 getWReg(wt)),
7129 mkU8(15)));
7130 putWReg(wd, binop(Iop_QAdd16Sx8,
7131 binop(Iop_OrV128,
7132 binop(Iop_AndV128,
7133 unop(Iop_NotV128,
7134 mkexpr(t3)),
7135 mkexpr(t1)),
7136 binop(Iop_AndV128,
7137 unop(Iop_NotV128,
7138 mkexpr(t1)),
7139 mkexpr(t3))),
7140 binop(Iop_OrV128,
7141 binop(Iop_AndV128,
7142 unop(Iop_NotV128,
7143 mkexpr(t4)),
7144 mkexpr(t2)),
7145 binop(Iop_AndV128,
7146 unop(Iop_NotV128,
7147 mkexpr(t2)),
7148 mkexpr(t4)))));
7149 break;
7152 case 0x02: { /* ADDS_A.W */
7153 DIP("ADDS_A.W w%d, w%d, w%d", wd, ws, wt);
7154 t1 = newTemp(Ity_V128);
7155 t2 = newTemp(Ity_V128);
7156 t3 = newTemp(Ity_V128);
7157 t4 = newTemp(Ity_V128);
7158 assign(t1, unop(Iop_Abs32x4, getWReg(ws)));
7159 assign(t2, unop(Iop_Abs32x4, getWReg(wt)));
7160 assign(t3, binop(Iop_SarN32x4,
7161 binop(Iop_AndV128,
7162 mkexpr(t1),
7163 getWReg(ws)),
7164 mkU8(31)));
7165 assign(t4, binop(Iop_SarN32x4,
7166 binop(Iop_AndV128,
7167 mkexpr(t2),
7168 getWReg(wt)),
7169 mkU8(31)));
7170 putWReg(wd, binop(Iop_QAdd32Sx4,
7171 binop(Iop_OrV128,
7172 binop(Iop_AndV128,
7173 unop(Iop_NotV128,
7174 mkexpr(t3)),
7175 mkexpr(t1)),
7176 binop(Iop_AndV128,
7177 unop(Iop_NotV128,
7178 mkexpr(t1)),
7179 mkexpr(t3))),
7180 binop(Iop_OrV128,
7181 binop(Iop_AndV128,
7182 unop(Iop_NotV128,
7183 mkexpr(t4)),
7184 mkexpr(t2)),
7185 binop(Iop_AndV128,
7186 unop(Iop_NotV128,
7187 mkexpr(t2)),
7188 mkexpr(t4)))));
7189 break;
7192 case 0x03: { /* ADDS_A.D */
7193 DIP("ADDS_A.D w%d, w%d, w%d", wd, ws, wt);
7194 t1 = newTemp(Ity_V128);
7195 t2 = newTemp(Ity_V128);
7196 t3 = newTemp(Ity_V128);
7197 t4 = newTemp(Ity_V128);
7198 assign(t1, unop(Iop_Abs64x2, getWReg(ws)));
7199 assign(t2, unop(Iop_Abs64x2, getWReg(wt)));
7200 assign(t3, binop(Iop_SarN64x2,
7201 binop(Iop_AndV128,
7202 mkexpr(t1),
7203 getWReg(ws)),
7204 mkU8(63)));
7205 assign(t4, binop(Iop_SarN64x2,
7206 binop(Iop_AndV128,
7207 mkexpr(t2),
7208 getWReg(wt)),
7209 mkU8(63)));
7210 putWReg(wd,
7211 binop(Iop_QAdd64Sx2,
7212 binop(Iop_OrV128,
7213 binop(Iop_AndV128,
7214 unop(Iop_NotV128,
7215 mkexpr(t3)),
7216 mkexpr(t1)),
7217 binop(Iop_AndV128,
7218 unop(Iop_NotV128,
7219 mkexpr(t1)),
7220 mkexpr(t3))),
7221 binop(Iop_OrV128,
7222 binop(Iop_AndV128,
7223 unop(Iop_NotV128,
7224 mkexpr(t4)),
7225 mkexpr(t2)),
7226 binop(Iop_AndV128,
7227 unop(Iop_NotV128,
7228 mkexpr(t2)),
7229 mkexpr(t4)))));
7230 break;
7233 default:
7234 return -1;
7237 break;
7240 case 0x02: { /* ADDS_S.df */
7241 switch (df) {
7242 case 0x00: { /* ADDS_S.B */
7243 DIP("ADDS_S.B w%d, w%d, w%d", wd, ws, wt);
7244 t1 = newTemp(Ity_V128);
7245 t2 = newTemp(Ity_V128);
7246 t3 = newTemp(Ity_V128);
7247 assign(t1, getWReg(ws));
7248 assign(t2, getWReg(wt));
7249 assign(t3, binop(Iop_QAdd8Sx16, mkexpr(t1), mkexpr(t2)));
7250 putWReg(wd, mkexpr(t3));
7251 break;
7254 case 0x01: { /* ADDS_S.H */
7255 DIP("ADDS_S.H w%d, w%d, w%d", wd, ws, wt);
7256 t1 = newTemp(Ity_V128);
7257 t2 = newTemp(Ity_V128);
7258 t3 = newTemp(Ity_V128);
7259 assign(t1, getWReg(ws));
7260 assign(t2, getWReg(wt));
7261 assign(t3, binop(Iop_QAdd16Sx8, mkexpr(t1), mkexpr(t2)));
7262 putWReg(wd, mkexpr(t3));
7263 break;
7266 case 0x02: { /* ADDS_S.W */
7267 DIP("ADDS_S.W w%d, w%d, w%d", wd, ws, wt);
7268 t1 = newTemp(Ity_V128);
7269 t2 = newTemp(Ity_V128);
7270 t3 = newTemp(Ity_V128);
7271 assign(t1, getWReg(ws));
7272 assign(t2, getWReg(wt));
7273 assign(t3, binop(Iop_QAdd32Sx4, mkexpr(t1), mkexpr(t2)));
7274 putWReg(wd, mkexpr(t3));
7275 break;
7278 case 0x03: { /* ADDS_S.D */
7279 DIP("ADDS_S.D w%d, w%d, w%d", wd, ws, wt);
7280 t1 = newTemp(Ity_V128);
7281 t2 = newTemp(Ity_V128);
7282 t3 = newTemp(Ity_V128);
7283 assign(t1, getWReg(ws));
7284 assign(t2, getWReg(wt));
7285 assign(t3, binop(Iop_QAdd64Sx2, mkexpr(t1), mkexpr(t2)));
7286 putWReg(wd, mkexpr(t3));
7287 break;
7290 default:
7291 return -1;
7294 break;
7297 case 0x03: { /* ADDS_U.df */
7298 switch (df) {
7299 case 0x00: { /* ADDS_U.B */
7300 DIP("ADDS_U.B w%d, w%d, w%d", wd, ws, wt);
7301 t1 = newTemp(Ity_V128);
7302 t2 = newTemp(Ity_V128);
7303 t3 = newTemp(Ity_V128);
7304 assign(t1, getWReg(ws));
7305 assign(t2, getWReg(wt));
7306 assign(t3, binop(Iop_QAdd8Ux16, mkexpr(t1), mkexpr(t2)));
7307 putWReg(wd, mkexpr(t3));
7308 break;
7311 case 0x01: { /* ADDS_U.H */
7312 DIP("ADDS_U.H w%d, w%d, w%d", wd, ws, wt);
7313 t1 = newTemp(Ity_V128);
7314 t2 = newTemp(Ity_V128);
7315 t3 = newTemp(Ity_V128);
7316 assign(t1, getWReg(ws));
7317 assign(t2, getWReg(wt));
7318 assign(t3, binop(Iop_QAdd16Ux8, mkexpr(t1), mkexpr(t2)));
7319 putWReg(wd, mkexpr(t3));
7320 break;
7323 case 0x02: { /* ADDS_U.W */
7324 DIP("ADDS_U.W w%d, w%d, w%d", wd, ws, wt);
7325 t1 = newTemp(Ity_V128);
7326 t2 = newTemp(Ity_V128);
7327 t3 = newTemp(Ity_V128);
7328 assign(t1, getWReg(ws));
7329 assign(t2, getWReg(wt));
7330 assign(t3, binop(Iop_QAdd32Ux4, mkexpr(t1), mkexpr(t2)));
7331 putWReg(wd, mkexpr(t3));
7332 break;
7335 case 0x03: { /* ADDS_U.D */
7336 DIP("ADDS_U.D w%d, w%d, w%d", wd, ws, wt);
7337 t1 = newTemp(Ity_V128);
7338 t2 = newTemp(Ity_V128);
7339 t3 = newTemp(Ity_V128);
7340 assign(t1, getWReg(ws));
7341 assign(t2, getWReg(wt));
7342 assign(t3, binop(Iop_QAdd64Ux2, mkexpr(t1), mkexpr(t2)));
7343 putWReg(wd, mkexpr(t3));
7344 break;
7347 default:
7348 return -1;
7351 break;
7354 case 0x04: { /* AVE_S.df */
7355 switch (df) {
7356 case 0x00: { /* AVE_S.B */
7357 DIP("AVE_S.B w%d, w%d, w%d", wd, ws, wt);
7358 t1 = newTemp(Ity_V128);
7359 t2 = newTemp(Ity_V128);
7360 t3 = newTemp(Ity_V128);
7361 assign(t1, getWReg(ws));
7362 assign(t2, getWReg(wt));
7363 assign(t3, binop(Iop_Add8x16,
7364 binop(Iop_Add8x16,
7365 binop(Iop_SarN8x16,
7366 mkexpr(t1), mkU8(1)),
7367 binop(Iop_SarN8x16,
7368 mkexpr(t2), mkU8(1))),
7369 binop(Iop_ShrN8x16,
7370 binop(Iop_ShlN8x16,
7371 binop(Iop_AndV128,
7372 mkexpr(t1),
7373 mkexpr(t2)),
7374 mkU8(7)),
7375 mkU8(7))));
7376 putWReg(wd, mkexpr(t3));
7377 break;
7380 case 0x01: { /* AVE_S.H */
7381 DIP("AVE_S.H w%d, w%d, w%d", wd, ws, wt);
7382 t1 = newTemp(Ity_V128);
7383 t2 = newTemp(Ity_V128);
7384 t3 = newTemp(Ity_V128);
7385 assign(t1, getWReg(ws));
7386 assign(t2, getWReg(wt));
7387 assign(t3,
7388 binop(Iop_Add16x8,
7389 binop(Iop_Add16x8,
7390 binop(Iop_SarN16x8,
7391 mkexpr(t1), mkU8(1)),
7392 binop(Iop_SarN16x8,
7393 mkexpr(t2), mkU8(1))),
7394 binop(Iop_ShrN16x8,
7395 binop(Iop_ShlN16x8,
7396 binop(Iop_AndV128,
7397 mkexpr(t1),
7398 mkexpr(t2)),
7399 mkU8(15)),
7400 mkU8(15))));
7401 putWReg(wd, mkexpr(t3));
7402 break;
7405 case 0x02: { /* AVE_S.W */
7406 DIP("AVE_S.W w%d, w%d, w%d", wd, ws, wt);
7407 t1 = newTemp(Ity_V128);
7408 t2 = newTemp(Ity_V128);
7409 t3 = newTemp(Ity_V128);
7410 assign(t1, getWReg(ws));
7411 assign(t2, getWReg(wt));
7412 assign(t3, binop(Iop_Add32x4,
7413 binop(Iop_Add32x4,
7414 binop(Iop_SarN32x4,
7415 mkexpr(t1), mkU8(1)),
7416 binop(Iop_SarN32x4,
7417 mkexpr(t2), mkU8(1))),
7418 binop(Iop_ShrN32x4,
7419 binop(Iop_ShlN32x4,
7420 binop(Iop_AndV128,
7421 mkexpr(t1),
7422 mkexpr(t2)),
7423 mkU8(31)),
7424 mkU8(31))));
7425 putWReg(wd, mkexpr(t3));
7426 break;
7429 case 0x03: { /* AVE_S.D */
7430 DIP("AVE_S.D w%d, w%d, w%d", wd, ws, wt);
7431 t1 = newTemp(Ity_V128);
7432 t2 = newTemp(Ity_V128);
7433 t3 = newTemp(Ity_V128);
7434 assign(t1, getWReg(ws));
7435 assign(t2, getWReg(wt));
7436 assign(t3, binop(Iop_Add64x2,
7437 binop(Iop_Add64x2,
7438 binop(Iop_SarN64x2,
7439 mkexpr(t1), mkU8(1)),
7440 binop(Iop_SarN64x2,
7441 mkexpr(t2), mkU8(1))),
7442 binop(Iop_ShrN64x2,
7443 binop(Iop_ShlN64x2,
7444 binop(Iop_AndV128,
7445 mkexpr(t1),
7446 mkexpr(t2)),
7447 mkU8(63)),
7448 mkU8(63))));
7449 putWReg(wd, mkexpr(t3));
7450 break;
7453 default:
7454 return -1;
7457 break;
7460 case 0x05: { /* AVE_U.df */
7461 switch (df) {
7462 case 0x00: { /* AVE_U.B */
7463 DIP("AVE_U.B w%d, w%d, w%d", wd, ws, wt);
7464 t1 = newTemp(Ity_V128);
7465 t2 = newTemp(Ity_V128);
7466 t3 = newTemp(Ity_V128);
7467 assign(t1, getWReg(ws));
7468 assign(t2, getWReg(wt));
7469 assign(t3, binop(Iop_Add16x8,
7470 binop(Iop_Add8x16,
7471 binop(Iop_ShrN8x16,
7472 mkexpr(t1), mkU8(1)),
7473 binop(Iop_ShrN8x16,
7474 mkexpr(t2), mkU8(1))),
7475 binop(Iop_ShrN8x16,
7476 binop(Iop_ShlN8x16,
7477 binop(Iop_AndV128,
7478 mkexpr(t1),
7479 mkexpr(t2)),
7480 mkU8(7)),
7481 mkU8(7))));
7482 putWReg(wd, mkexpr(t3));
7483 break;
7486 case 0x01: { /* AVE_U.H */
7487 DIP("AVE_U.H w%d, w%d, w%d", wd, ws, wt);
7488 t1 = newTemp(Ity_V128);
7489 t2 = newTemp(Ity_V128);
7490 t3 = newTemp(Ity_V128);
7491 assign(t1, getWReg(ws));
7492 assign(t2, getWReg(wt));
7493 assign(t3, binop(Iop_Add16x8,
7494 binop(Iop_Add16x8,
7495 binop(Iop_ShrN16x8,
7496 mkexpr(t1), mkU8(1)),
7497 binop(Iop_ShrN16x8,
7498 mkexpr(t2), mkU8(1))),
7499 binop(Iop_ShrN16x8,
7500 binop(Iop_ShlN16x8,
7501 binop(Iop_AndV128,
7502 mkexpr(t1),
7503 mkexpr(t2)),
7504 mkU8(15)),
7505 mkU8(15))));
7506 putWReg(wd, mkexpr(t3));
7507 break;
7510 case 0x02: { /* AVE_U.W */
7511 DIP("AVE_U.W w%d, w%d, w%d", wd, ws, wt);
7512 t1 = newTemp(Ity_V128);
7513 t2 = newTemp(Ity_V128);
7514 t3 = newTemp(Ity_V128);
7515 assign(t1, getWReg(ws));
7516 assign(t2, getWReg(wt));
7517 assign(t3, binop(Iop_Add32x4,
7518 binop(Iop_Add32x4,
7519 binop(Iop_ShrN32x4,
7520 mkexpr(t1), mkU8(1)),
7521 binop(Iop_ShrN32x4,
7522 mkexpr(t2), mkU8(1))),
7523 binop(Iop_ShrN32x4,
7524 binop(Iop_ShlN32x4,
7525 binop(Iop_AndV128,
7526 mkexpr(t1),
7527 mkexpr(t2)),
7528 mkU8(31)),
7529 mkU8(31))));
7530 putWReg(wd, mkexpr(t3));
7531 break;
7534 case 0x03: { /* AVE_U.D */
7535 DIP("AVE_U.D w%d, w%d, w%d", wd, ws, wt);
7536 t1 = newTemp(Ity_V128);
7537 t2 = newTemp(Ity_V128);
7538 t3 = newTemp(Ity_V128);
7539 assign(t1, getWReg(ws));
7540 assign(t2, getWReg(wt));
7541 assign(t3, binop(Iop_Add64x2,
7542 binop(Iop_Add64x2,
7543 binop(Iop_ShrN64x2,
7544 mkexpr(t1), mkU8(1)),
7545 binop(Iop_ShrN64x2,
7546 mkexpr(t2), mkU8(1))),
7547 binop(Iop_ShrN64x2,
7548 binop(Iop_ShlN64x2,
7549 binop(Iop_AndV128,
7550 mkexpr(t1),
7551 mkexpr(t2)),
7552 mkU8(63)),
7553 mkU8(63))));
7554 putWReg(wd, mkexpr(t3));
7555 break;
7558 default:
7559 return -1;
7562 break;
7565 case 0x06: { /* AVER_S.df */
7566 switch (df) {
7567 case 0x00: { /* AVER_S.B */
7568 DIP("AVER_S.B w%d, w%d, w%d", wd, ws, wt);
7569 t1 = newTemp(Ity_V128);
7570 t2 = newTemp(Ity_V128);
7571 t3 = newTemp(Ity_V128);
7572 assign(t1, getWReg(ws));
7573 assign(t2, getWReg(wt));
7574 assign(t3, binop(Iop_Avg8Sx16, mkexpr(t1), mkexpr(t2)));
7575 putWReg(wd, mkexpr(t3));
7576 break;
7579 case 0x01: { /* AVER_S.H */
7580 DIP("AVER_S.H w%d, w%d, w%d", wd, ws, wt);
7581 t1 = newTemp(Ity_V128);
7582 t2 = newTemp(Ity_V128);
7583 t3 = newTemp(Ity_V128);
7584 assign(t1, getWReg(ws));
7585 assign(t2, getWReg(wt));
7586 assign(t3, binop(Iop_Avg16Sx8, mkexpr(t1), mkexpr(t2)));
7587 putWReg(wd, mkexpr(t3));
7588 break;
7591 case 0x02: { /* AVER_S.W */
7592 DIP("AVER_S.W w%d, w%d, w%d", wd, ws, wt);
7593 t1 = newTemp(Ity_V128);
7594 t2 = newTemp(Ity_V128);
7595 t3 = newTemp(Ity_V128);
7596 assign(t1, getWReg(ws));
7597 assign(t2, getWReg(wt));
7598 assign(t3, binop(Iop_Avg32Sx4, mkexpr(t1), mkexpr(t2)));
7599 putWReg(wd, mkexpr(t3));
7600 break;
7603 case 0x03: { /* AVER_S.D */
7604 DIP("AVER_S.D w%d, w%d, w%d", wd, ws, wt);
7605 t1 = newTemp(Ity_V128);
7606 t2 = newTemp(Ity_V128);
7607 t3 = newTemp(Ity_V128);
7608 assign(t1, getWReg(ws));
7609 assign(t2, getWReg(wt));
7610 assign(t3, binop(Iop_Add64x2,
7611 binop(Iop_Add64x2,
7612 binop(Iop_SarN64x2,
7613 mkexpr(t1), mkU8(1)),
7614 binop(Iop_SarN64x2,
7615 mkexpr(t2), mkU8(1))),
7616 binop(Iop_ShrN64x2,
7617 binop(Iop_ShlN64x2,
7618 binop(Iop_OrV128,
7619 mkexpr(t1),
7620 mkexpr(t2)),
7621 mkU8(63)),
7622 mkU8(63))));
7623 putWReg(wd, mkexpr(t3));
7624 break;
7627 default:
7628 return -1;
7631 break;
7634 case 0x07: { /* AVER_U.df */
7635 switch (df) {
7636 case 0x00: { /* AVER_U.B */
7637 DIP("AVER_U.B w%d, w%d, w%d", wd, ws, wt);
7638 t1 = newTemp(Ity_V128);
7639 t2 = newTemp(Ity_V128);
7640 t3 = newTemp(Ity_V128);
7641 assign(t1, getWReg(ws));
7642 assign(t2, getWReg(wt));
7643 assign(t3, binop(Iop_Avg8Ux16, mkexpr(t1), mkexpr(t2)));
7644 putWReg(wd, mkexpr(t3));
7645 break;
7648 case 0x01: { /* AVER_U.H */
7649 DIP("AVER_U.H w%d, w%d, w%d", wd, ws, wt);
7650 t1 = newTemp(Ity_V128);
7651 t2 = newTemp(Ity_V128);
7652 t3 = newTemp(Ity_V128);
7653 assign(t1, getWReg(ws));
7654 assign(t2, getWReg(wt));
7655 assign(t3, binop(Iop_Avg16Ux8, mkexpr(t1), mkexpr(t2)));
7656 putWReg(wd, mkexpr(t3));
7657 break;
7660 case 0x02: { /* AVER_U.W */
7661 DIP("AVER_U.W w%d, w%d, w%d", wd, ws, wt);
7662 t1 = newTemp(Ity_V128);
7663 t2 = newTemp(Ity_V128);
7664 t3 = newTemp(Ity_V128);
7665 assign(t1, getWReg(ws));
7666 assign(t2, getWReg(wt));
7667 assign(t3, binop(Iop_Avg32Ux4, mkexpr(t1), mkexpr(t2)));
7668 putWReg(wd, mkexpr(t3));
7669 break;
7672 case 0x03: { /* AVER_U.D */
7673 DIP("AVER_U.D w%d, w%d, w%d", wd, ws, wt);
7674 t1 = newTemp(Ity_V128);
7675 t2 = newTemp(Ity_V128);
7676 t3 = newTemp(Ity_V128);
7677 assign(t1, getWReg(ws));
7678 assign(t2, getWReg(wt));
7679 assign(t3, binop(Iop_Add64x2,
7680 binop(Iop_Add64x2,
7681 binop(Iop_ShrN64x2,
7682 mkexpr(t1), mkU8(1)),
7683 binop(Iop_ShrN64x2,
7684 mkexpr(t2), mkU8(1))),
7685 binop(Iop_ShrN64x2,
7686 binop(Iop_ShlN64x2,
7687 binop(Iop_OrV128,
7688 mkexpr(t1),
7689 mkexpr(t2)),
7690 mkU8(63)),
7691 mkU8(63))));
7692 putWReg(wd, mkexpr(t3));
7693 break;
7696 default:
7697 return -1;
7700 break;
7703 default:
7704 return -1;
7707 return 0;
7710 static Int msa_3R_11(UInt cins, UChar wd, UChar ws) /* 3R (0x11) */
7712 IRTemp t1, t2, t3;
7713 UShort operation;
7714 UChar df, wt;
7716 operation = (cins & 0x03800000) >> 23;
7717 df = (cins & 0x00600000) >> 21;
7718 wt = (cins & 0x001F0000) >> 16;
7720 switch (operation) {
7721 case 0x00: { /* SUBS_S.df */
7722 switch (df) {
7723 case 0x00: { /* SUBS_S.B */
7724 DIP("SUBS_S.B w%d, w%d, w%d", wd, ws, wt);
7725 t1 = newTemp(Ity_V128);
7726 t2 = newTemp(Ity_V128);
7727 t3 = newTemp(Ity_V128);
7728 assign(t1, getWReg(ws));
7729 assign(t2, getWReg(wt));
7730 assign(t3, binop(Iop_QSub8Sx16, mkexpr(t1), mkexpr(t2)));
7731 putWReg(wd, mkexpr(t3));
7732 break;
7735 case 0x01: { /* SUBS_S.H */
7736 DIP("SUBS_S.H w%d, w%d, w%d", wd, ws, wt);
7737 t1 = newTemp(Ity_V128);
7738 t2 = newTemp(Ity_V128);
7739 t3 = newTemp(Ity_V128);
7740 assign(t1, getWReg(ws));
7741 assign(t2, getWReg(wt));
7742 assign(t3, binop(Iop_QSub16Sx8, mkexpr(t1), mkexpr(t2)));
7743 putWReg(wd, mkexpr(t3));
7744 break;
7747 case 0x02: { /* SUBS_S.W */
7748 DIP("SUBS_S.W w%d, w%d, w%d", wd, ws, wt);
7749 t1 = newTemp(Ity_V128);
7750 t2 = newTemp(Ity_V128);
7751 t3 = newTemp(Ity_V128);
7752 assign(t1, getWReg(ws));
7753 assign(t2, getWReg(wt));
7754 assign(t3, binop(Iop_QSub32Sx4, mkexpr(t1), mkexpr(t2)));
7755 putWReg(wd, mkexpr(t3));
7756 break;
7759 case 0x03: { /* SUBS_S.D */
7760 DIP("SUBS_S.D w%d, w%d, w%d", wd, ws, wt);
7761 t1 = newTemp(Ity_V128);
7762 t2 = newTemp(Ity_V128);
7763 t3 = newTemp(Ity_V128);
7764 assign(t1, getWReg(ws));
7765 assign(t2, getWReg(wt));
7766 assign(t3, binop(Iop_QSub64Sx2, mkexpr(t1), mkexpr(t2)));
7767 putWReg(wd, mkexpr(t3));
7768 break;
7771 default:
7772 return -1;
7775 break;
7778 case 0x01: { /* SUBS_U.df */
7779 switch (df) {
7780 case 0x00: { /* SUBS_U.B */
7781 DIP("SUBS_U.B w%d, w%d, w%d", wd, ws, wt);
7782 t1 = newTemp(Ity_V128);
7783 t2 = newTemp(Ity_V128);
7784 t3 = newTemp(Ity_V128);
7785 assign(t1, getWReg(ws));
7786 assign(t2, getWReg(wt));
7787 assign(t3, binop(Iop_QSub8Ux16, mkexpr(t1), mkexpr(t2)));
7788 putWReg(wd, mkexpr(t3));
7789 break;
7792 case 0x01: { /* SUBS_U.H */
7793 DIP("SUBS_U.H w%d, w%d, w%d", wd, ws, wt);
7794 t1 = newTemp(Ity_V128);
7795 t2 = newTemp(Ity_V128);
7796 t3 = newTemp(Ity_V128);
7797 assign(t1, getWReg(ws));
7798 assign(t2, getWReg(wt));
7799 assign(t3, binop(Iop_QSub16Ux8, mkexpr(t1), mkexpr(t2)));
7800 putWReg(wd, mkexpr(t3));
7801 break;
7804 case 0x02: { /* SUBS_U.W */
7805 DIP("SUBS_U.W w%d, w%d, w%d", wd, ws, wt);
7806 t1 = newTemp(Ity_V128);
7807 t2 = newTemp(Ity_V128);
7808 t3 = newTemp(Ity_V128);
7809 assign(t1, getWReg(ws));
7810 assign(t2, getWReg(wt));
7811 assign(t3, binop(Iop_QSub32Ux4, mkexpr(t1), mkexpr(t2)));
7812 putWReg(wd, mkexpr(t3));
7813 break;
7816 case 0x03: { /* SUBS_U.D */
7817 DIP("SUBS_U.D w%d, w%d, w%d", wd, ws, wt);
7818 t1 = newTemp(Ity_V128);
7819 t2 = newTemp(Ity_V128);
7820 t3 = newTemp(Ity_V128);
7821 assign(t1, getWReg(ws));
7822 assign(t2, getWReg(wt));
7823 assign(t3, binop(Iop_QSub64Ux2, mkexpr(t1), mkexpr(t2)));
7824 putWReg(wd, mkexpr(t3));
7825 break;
7828 default:
7829 return -1;
7832 break;
7835 case 0x02: { /* SUBSUS_U.df */
7836 switch (df) {
7837 case 0x00: { /* SUBSUS_U.B */
7838 DIP("SUBSUS_U.B w%d, w%d, w%d", wd, ws, wt);
7839 t1 = newTemp(Ity_V128);
7840 t2 = newTemp(Ity_V128);
7841 t3 = newTemp(Ity_V128);
7842 assign(t1, binop(Iop_Sub8x16, getWReg(ws), getWReg(wt)));
7843 assign(t2, binop(Iop_SarN8x16, getWReg(wt), mkU8(7)));
7844 assign(t3, binop(Iop_OrV128,
7845 binop(Iop_CmpGT8Ux16,
7846 getWReg(ws),
7847 getWReg(wt)),
7848 binop(Iop_CmpEQ8x16,
7849 getWReg(ws),
7850 getWReg(wt))));
7851 putWReg(wd,
7852 binop(Iop_OrV128,
7853 binop(Iop_AndV128,
7854 mkexpr(t3), mkexpr(t2)),
7855 binop(Iop_AndV128,
7856 mkexpr(t1),
7857 binop(Iop_XorV128,
7858 mkexpr(t3),
7859 mkexpr(t2)))));
7860 break;
7863 case 0x01: { /* SUBSUS_U.H */
7864 DIP("SUBSUS_U.H w%d, w%d, w%d", wd, ws, wt);
7865 t1 = newTemp(Ity_V128);
7866 t2 = newTemp(Ity_V128);
7867 t3 = newTemp(Ity_V128);
7868 assign(t1, binop(Iop_Sub16x8, getWReg(ws), getWReg(wt)));
7869 assign(t2, binop(Iop_SarN16x8, getWReg(wt), mkU8(15)));
7870 assign(t3,
7871 binop(Iop_OrV128,
7872 binop(Iop_CmpGT16Ux8,
7873 getWReg(ws),
7874 getWReg(wt)),
7875 binop(Iop_CmpEQ16x8,
7876 getWReg(ws),
7877 getWReg(wt))));
7878 putWReg(wd,
7879 binop(Iop_OrV128,
7880 binop(Iop_AndV128,
7881 mkexpr(t3), mkexpr(t2)),
7882 binop(Iop_AndV128,
7883 mkexpr(t1),
7884 binop(Iop_XorV128,
7885 mkexpr(t3),
7886 mkexpr(t2)))));
7887 break;
7890 case 0x02: { /* SUBSUS_U.W */
7891 DIP("SUBSUS_U.W w%d, w%d, w%d", wd, ws, wt);
7892 t1 = newTemp(Ity_V128);
7893 t2 = newTemp(Ity_V128);
7894 t3 = newTemp(Ity_V128);
7895 assign(t1, binop(Iop_Sub32x4, getWReg(ws), getWReg(wt)));
7896 assign(t2, binop(Iop_SarN32x4, getWReg(wt), mkU8(31)));
7897 assign(t3,
7898 binop(Iop_OrV128,
7899 binop(Iop_CmpGT32Ux4,
7900 getWReg(ws),
7901 getWReg(wt)),
7902 binop(Iop_CmpEQ32x4,
7903 getWReg(ws),
7904 getWReg(wt))));
7905 putWReg(wd,
7906 binop(Iop_OrV128,
7907 binop(Iop_AndV128,
7908 mkexpr(t3), mkexpr(t2)),
7909 binop(Iop_AndV128,
7910 mkexpr(t1),
7911 binop(Iop_XorV128,
7912 mkexpr(t3),
7913 mkexpr(t2)))));
7914 break;
7917 case 0x03: { /* SUBSUS_U.D */
7918 DIP("SUBSUS_U.D w%d, w%d, w%d", wd, ws, wt);
7919 t1 = newTemp(Ity_V128);
7920 t2 = newTemp(Ity_V128);
7921 t3 = newTemp(Ity_V128);
7922 assign(t1, binop(Iop_Sub64x2, getWReg(ws), getWReg(wt)));
7923 assign(t2, binop(Iop_SarN64x2, getWReg(wt), mkU8(63)));
7924 assign(t3,
7925 binop(Iop_OrV128,
7926 binop(Iop_CmpGT64Ux2,
7927 getWReg(ws),
7928 getWReg(wt)),
7929 binop(Iop_CmpEQ64x2,
7930 getWReg(ws),
7931 getWReg(wt))));
7932 putWReg(wd,
7933 binop(Iop_OrV128,
7934 binop(Iop_AndV128,
7935 mkexpr(t3), mkexpr(t2)),
7936 binop(Iop_AndV128,
7937 mkexpr(t1),
7938 binop(Iop_XorV128,
7939 mkexpr(t3),
7940 mkexpr(t2)))));
7941 break;
7944 default:
7945 return -1;
7948 break;
7951 case 0x03: { /* SUBSUU_S.df */
7952 switch (df) {
7953 case 0x00: { /* SUBSUU_S.B */
7954 DIP("SUBSUU_S.B w%d, w%d, w%d", wd, ws, wt);
7955 t1 = newTemp(Ity_V128);
7956 t2 = newTemp(Ity_V128);
7957 t3 = newTemp(Ity_V128);
7958 assign(t1, binop(Iop_Sub8x16, getWReg(ws), getWReg(wt)));
7959 assign(t2,
7960 binop(Iop_SarN8x16,
7961 binop (Iop_AndV128,
7962 binop(Iop_XorV128,
7963 getWReg(ws),
7964 getWReg(wt)),
7965 binop(Iop_XorV128,
7966 mkexpr(t1),
7967 getWReg(wt))),
7968 mkU8(7)));
7969 assign(t3,
7970 binop(Iop_AndV128,
7971 binop(Iop_SarN8x16,
7972 getWReg(ws), mkU8(7)),
7973 mkexpr(t2)));
7974 putWReg(wd,
7975 binop(Iop_OrV128,
7976 binop(Iop_AndV128,
7977 mkexpr(t1),
7978 unop(Iop_NotV128,
7979 mkexpr(t2))),
7980 binop(Iop_XorV128,
7981 binop(Iop_ShlN8x16,
7982 mkexpr(t2), mkU8(7)),
7983 mkexpr(t3))));
7984 break;
7987 case 0x01: { /* SUBSUU_S.H */
7988 DIP("SUBSUU_S.H w%d, w%d, w%d", wd, ws, wt);
7989 t1 = newTemp(Ity_V128);
7990 t2 = newTemp(Ity_V128);
7991 t3 = newTemp(Ity_V128);
7992 assign(t1, binop(Iop_Sub16x8, getWReg(ws), getWReg(wt)));
7993 assign(t2,
7994 binop(Iop_SarN16x8,
7995 binop (Iop_AndV128,
7996 binop(Iop_XorV128,
7997 getWReg(ws),
7998 getWReg(wt)),
7999 binop(Iop_XorV128,
8000 mkexpr(t1),
8001 getWReg(wt))),
8002 mkU8(15)));
8003 assign(t3,
8004 binop(Iop_AndV128,
8005 binop(Iop_SarN16x8,
8006 getWReg(ws),
8007 mkU8(15)),
8008 mkexpr(t2)));
8009 putWReg(wd,
8010 binop(Iop_OrV128,
8011 binop(Iop_AndV128,
8012 mkexpr(t1),
8013 unop(Iop_NotV128,
8014 mkexpr(t2))),
8015 binop(Iop_XorV128,
8016 binop(Iop_ShlN16x8,
8017 mkexpr(t2), mkU8(15)),
8018 mkexpr(t3))));
8019 break;
8022 case 0x02: { /* SUBSUU_S.W */
8023 DIP("SUBSUU_S.W w%d, w%d, w%d", wd, ws, wt);
8024 t1 = newTemp(Ity_V128);
8025 t2 = newTemp(Ity_V128);
8026 t3 = newTemp(Ity_V128);
8027 assign(t1, binop(Iop_Sub32x4, getWReg(ws), getWReg(wt)));
8028 assign(t2,
8029 binop(Iop_SarN32x4,
8030 binop (Iop_AndV128,
8031 binop(Iop_XorV128,
8032 getWReg(ws),
8033 getWReg(wt)),
8034 binop(Iop_XorV128,
8035 mkexpr(t1),
8036 getWReg(wt))),
8037 mkU8(31)));
8038 assign(t3,
8039 binop(Iop_AndV128,
8040 binop(Iop_SarN32x4,
8041 getWReg(ws),
8042 mkU8(31)),
8043 mkexpr(t2)));
8044 putWReg(wd,
8045 binop(Iop_OrV128,
8046 binop(Iop_AndV128,
8047 mkexpr(t1),
8048 unop(Iop_NotV128,
8049 mkexpr(t2))),
8050 binop(Iop_XorV128,
8051 binop(Iop_ShlN32x4,
8052 mkexpr(t2),
8053 mkU8(31)),
8054 mkexpr(t3))));
8055 break;
8058 case 0x03: { /* SUBSUU_S.D */
8059 DIP("SUBSUU_S.D w%d, w%d, w%d", wd, ws, wt);
8060 t1 = newTemp(Ity_V128);
8061 t2 = newTemp(Ity_V128);
8062 t3 = newTemp(Ity_V128);
8063 assign(t1, binop(Iop_Sub64x2, getWReg(ws), getWReg(wt)));
8064 assign(t2,
8065 binop(Iop_SarN64x2,
8066 binop (Iop_AndV128,
8067 binop(Iop_XorV128,
8068 getWReg(ws),
8069 getWReg(wt)),
8070 binop(Iop_XorV128,
8071 mkexpr(t1),
8072 getWReg(wt))),
8073 mkU8(63)));
8074 assign(t3,
8075 binop(Iop_AndV128,
8076 binop(Iop_SarN64x2,
8077 getWReg(ws),
8078 mkU8(63)),
8079 mkexpr(t2)));
8080 putWReg(wd,
8081 binop(Iop_OrV128,
8082 binop(Iop_AndV128,
8083 mkexpr(t1),
8084 unop(Iop_NotV128,
8085 mkexpr(t2))),
8086 binop(Iop_XorV128,
8087 binop(Iop_ShlN64x2,
8088 mkexpr(t2), mkU8(63)),
8089 mkexpr(t3))));
8090 break;
8093 default:
8094 return -1;
8097 break;
8100 case 0x04: { /* ASUB_S.df */
8101 switch (df) {
8102 case 0x00: { /* ASUB_S.B */
8103 DIP("ASUB_S.B w%d, w%d, w%d", wd, ws, wt);
8104 t1 = newTemp(Ity_V128);
8105 t2 = newTemp(Ity_V128);
8106 t3 = newTemp(Ity_V128);
8107 assign(t1, binop(Iop_SarN8x16, getWReg(ws), mkU8(7)));
8108 assign(t2, binop(Iop_SarN8x16, getWReg(wt), mkU8(7)));
8109 assign(t3, binop(Iop_Sub8x16, getWReg(ws), getWReg(wt)));
8110 putWReg(wd,
8111 binop(Iop_OrV128,
8112 binop(Iop_OrV128,
8113 binop(Iop_AndV128,
8114 binop(Iop_AndV128,
8115 unop(Iop_NotV128,
8116 mkexpr(t1)),
8117 mkexpr(t2)),
8118 mkexpr(t3)),
8119 binop(Iop_AndV128,
8120 unop(Iop_NotV128,
8121 binop(Iop_XorV128,
8122 mkexpr(t1),
8123 mkexpr(t2))),
8124 unop(Iop_Abs8x16,
8125 mkexpr(t3)))),
8126 binop(Iop_AndV128,
8127 binop(Iop_AndV128,
8128 mkexpr(t1),
8129 unop(Iop_NotV128,
8130 mkexpr(t2))),
8131 binop(Iop_Sub8x16,
8132 getWReg(wt),
8133 getWReg(ws)))));
8134 break;
8137 case 0x01: { /* ASUB_S.H */
8138 DIP("ASUB_S.H w%d, w%d, w%d", wd, ws, wt);
8139 t1 = newTemp(Ity_V128);
8140 t2 = newTemp(Ity_V128);
8141 t3 = newTemp(Ity_V128);
8142 assign(t1, binop(Iop_SarN16x8, getWReg(ws), mkU8(15)));
8143 assign(t2, binop(Iop_SarN16x8, getWReg(wt), mkU8(15)));
8144 assign(t3, binop(Iop_Sub16x8, getWReg(ws), getWReg(wt)));
8145 putWReg(wd,
8146 binop(Iop_OrV128,
8147 binop(Iop_OrV128,
8148 binop(Iop_AndV128,
8149 binop(Iop_AndV128,
8150 unop(Iop_NotV128,
8151 mkexpr(t1)),
8152 mkexpr(t2)),
8153 mkexpr(t3)),
8154 binop(Iop_AndV128,
8155 unop(Iop_NotV128,
8156 binop(Iop_XorV128,
8157 mkexpr(t1),
8158 mkexpr(t2))),
8159 unop(Iop_Abs16x8,
8160 mkexpr(t3)))),
8161 binop(Iop_AndV128,
8162 binop(Iop_AndV128,
8163 mkexpr(t1),
8164 unop(Iop_NotV128,
8165 mkexpr(t2))),
8166 binop(Iop_Sub16x8,
8167 getWReg(wt),
8168 getWReg(ws)))));
8169 break;
8172 case 0x02: { /* ASUB_S.W */
8173 DIP("ASUB_S.W w%d, w%d, w%d", wd, ws, wt);
8174 t1 = newTemp(Ity_V128);
8175 t2 = newTemp(Ity_V128);
8176 t3 = newTemp(Ity_V128);
8177 assign(t1, binop(Iop_SarN32x4, getWReg(ws), mkU8(31)));
8178 assign(t2, binop(Iop_SarN32x4, getWReg(wt), mkU8(31)));
8179 assign(t3, binop(Iop_Sub32x4, getWReg(ws), getWReg(wt)));
8180 putWReg(wd,
8181 binop(Iop_OrV128,
8182 binop(Iop_OrV128,
8183 binop(Iop_AndV128,
8184 binop(Iop_AndV128,
8185 unop(Iop_NotV128,
8186 mkexpr(t1)),
8187 mkexpr(t2)),
8188 mkexpr(t3)),
8189 binop(Iop_AndV128,
8190 unop(Iop_NotV128,
8191 binop(Iop_XorV128,
8192 mkexpr(t1),
8193 mkexpr(t2))),
8194 unop(Iop_Abs32x4,
8195 mkexpr(t3)))),
8196 binop(Iop_AndV128,
8197 binop(Iop_AndV128,
8198 mkexpr(t1),
8199 unop(Iop_NotV128,
8200 mkexpr(t2))),
8201 binop(Iop_Sub32x4,
8202 getWReg(wt),
8203 getWReg(ws)))));
8204 break;
8207 case 0x03: { /* ASUB_S.D */
8208 DIP("ASUB_S.D w%d, w%d, w%d", wd, ws, wt);
8209 t1 = newTemp(Ity_V128);
8210 t2 = newTemp(Ity_V128);
8211 t3 = newTemp(Ity_V128);
8212 assign(t1, binop(Iop_SarN64x2, getWReg(ws), mkU8(63)));
8213 assign(t2, binop(Iop_SarN64x2, getWReg(wt), mkU8(63)));
8214 assign(t3, binop(Iop_Sub64x2, getWReg(ws), getWReg(wt)));
8215 putWReg(wd,
8216 binop(Iop_OrV128,
8217 binop(Iop_OrV128,
8218 binop(Iop_AndV128,
8219 binop(Iop_AndV128,
8220 unop(Iop_NotV128,
8221 mkexpr(t1)),
8222 mkexpr(t2)),
8223 mkexpr(t3)),
8224 binop(Iop_AndV128,
8225 unop(Iop_NotV128,
8226 binop(Iop_XorV128,
8227 mkexpr(t1),
8228 mkexpr(t2))),
8229 unop(Iop_Abs64x2,
8230 mkexpr(t3)))),
8231 binop(Iop_AndV128,
8232 binop(Iop_AndV128,
8233 mkexpr(t1),
8234 unop(Iop_NotV128,
8235 mkexpr(t2))),
8236 binop(Iop_Sub64x2,
8237 getWReg(wt),
8238 getWReg(ws)))));
8239 break;
8242 default:
8243 return -1;
8246 break;
8249 case 0x05: { /* ASUB_U.df */
8250 switch (df) {
8251 case 0x00: { /* ASUB_U.B */
8252 DIP("ASUB_U.B w%d, w%d, w%d", wd, ws, wt);
8253 t1 = newTemp(Ity_V128);
8254 t2 = newTemp(Ity_V128);
8255 t3 = newTemp(Ity_V128);
8256 assign(t1, getWReg(ws));
8257 assign(t2, getWReg(wt));
8258 assign(t3,
8259 binop(Iop_SarN8x16,
8260 binop(Iop_XorV128,
8261 mkexpr(t1), mkexpr(t2)),
8262 mkU8(7)));
8263 putWReg(wd,
8264 binop(Iop_OrV128,
8265 binop(Iop_AndV128,
8266 unop(Iop_NotV128, mkexpr(t3)),
8267 unop(Iop_Abs8x16,
8268 binop(Iop_Sub8x16,
8269 mkexpr(t1),
8270 mkexpr(t2)))),
8271 binop(Iop_AndV128, mkexpr(t3),
8272 binop(Iop_Sub8x16,
8273 binop(Iop_Max8Ux16,
8274 mkexpr(t1),
8275 mkexpr(t2)),
8276 binop(Iop_Min8Ux16,
8277 mkexpr(t1),
8278 mkexpr(t2))))));
8279 break;
8282 case 0x01: { /* ASUB_U.H */
8283 DIP("ASUB_U.H w%d, w%d, w%d", wd, ws, wt);
8284 t1 = newTemp(Ity_V128);
8285 t2 = newTemp(Ity_V128);
8286 t3 = newTemp(Ity_V128);
8287 assign(t1, getWReg(ws));
8288 assign(t2, getWReg(wt));
8289 assign(t3,
8290 binop(Iop_SarN16x8,
8291 binop(Iop_XorV128,
8292 mkexpr(t1), mkexpr(t2)),
8293 mkU8(15)));
8294 putWReg(wd,
8295 binop(Iop_OrV128,
8296 binop(Iop_AndV128,
8297 unop(Iop_NotV128,
8298 mkexpr(t3)),
8299 unop(Iop_Abs16x8,
8300 binop(Iop_Sub16x8,
8301 mkexpr(t1),
8302 mkexpr(t2)))),
8303 binop(Iop_AndV128,
8304 mkexpr(t3),
8305 binop(Iop_Sub16x8,
8306 binop(Iop_Max16Ux8,
8307 mkexpr(t1),
8308 mkexpr(t2)),
8309 binop(Iop_Min16Ux8,
8310 mkexpr(t1),
8311 mkexpr(t2))))));
8312 break;
8315 case 0x02: { /* ASUB_U.W */
8316 DIP("ASUB_U.W w%d, w%d, w%d", wd, ws, wt);
8317 t1 = newTemp(Ity_V128);
8318 t2 = newTemp(Ity_V128);
8319 t3 = newTemp(Ity_V128);
8320 assign(t1, getWReg(ws));
8321 assign(t2, getWReg(wt));
8322 assign(t3,
8323 binop(Iop_SarN32x4,
8324 binop(Iop_XorV128,
8325 mkexpr(t1), mkexpr(t2)),
8326 mkU8(31)));
8327 putWReg(wd,
8328 binop(Iop_OrV128,
8329 binop(Iop_AndV128,
8330 unop(Iop_NotV128, mkexpr(t3)),
8331 unop(Iop_Abs32x4,
8332 binop(Iop_Sub32x4,
8333 mkexpr(t1),
8334 mkexpr(t2)))),
8335 binop(Iop_AndV128,
8336 mkexpr(t3),
8337 binop(Iop_Sub32x4,
8338 binop(Iop_Max32Ux4,
8339 mkexpr(t1),
8340 mkexpr(t2)),
8341 binop(Iop_Min32Ux4,
8342 mkexpr(t1),
8343 mkexpr(t2))))));
8344 break;
8347 case 0x03: { /* ASUB_U.D */
8348 DIP("ASUB_U.D w%d, w%d, w%d", wd, ws, wt);
8349 t1 = newTemp(Ity_V128);
8350 t2 = newTemp(Ity_V128);
8351 t3 = newTemp(Ity_V128);
8352 assign(t1, getWReg(ws));
8353 assign(t2, getWReg(wt));
8354 assign(t3,
8355 binop(Iop_SarN64x2,
8356 binop(Iop_XorV128,
8357 mkexpr(t1), mkexpr(t2)),
8358 mkU8(63)));
8359 putWReg(wd,
8360 binop(Iop_OrV128,
8361 binop(Iop_AndV128,
8362 unop(Iop_NotV128, mkexpr(t3)),
8363 unop(Iop_Abs64x2,
8364 binop(Iop_Sub64x2,
8365 mkexpr(t1),
8366 mkexpr(t2)))),
8367 binop(Iop_AndV128,
8368 mkexpr(t3),
8369 binop(Iop_Sub64x2,
8370 binop(Iop_Max64Ux2,
8371 mkexpr(t1),
8372 mkexpr(t2)),
8373 binop(Iop_Min64Ux2,
8374 mkexpr(t1),
8375 mkexpr(t2))))));
8376 break;
8379 default:
8380 return -1;
8383 break;
8386 default:
8387 return -1;
8390 return 0;
8393 static Int msa_3R_12(UInt cins, UChar wd, UChar ws) /* 3R (0x12) */
8395 IRTemp t1, t2, t3, t4, t5, t6;
8396 UShort operation;
8397 UChar df, wt;
8399 operation = (cins & 0x03800000) >> 23;
8400 df = (cins & 0x00600000) >> 21;
8401 wt = (cins & 0x001F0000) >> 16;
8403 switch (operation) {
8404 case 0x00: { /* MULV.df */
8405 switch (df) {
8406 case 0x00: { /* MULV.B */
8407 DIP("MULV.B w%d, w%d, w%d", wd, ws, wt);
8408 putWReg(wd, binop(Iop_Mul8x16, getWReg(ws), getWReg(wt)));
8409 break;
8412 case 0x01: { /* MULV.H */
8413 DIP("MULV.H w%d, w%d, w%d", wd, ws, wt);
8414 putWReg(wd, binop(Iop_Mul16x8, getWReg(ws), getWReg(wt)));
8415 break;
8418 case 0x02: { /* MULV.W */
8419 DIP("MULV.W w%d, w%d, w%d", wd, ws, wt);
8420 putWReg(wd, binop(Iop_Mul32x4, getWReg(ws), getWReg(wt)));
8421 break;
8424 case 0x03: { /* MULV.D */
8425 DIP("MULV.D w%d, w%d, w%d", wd, ws, wt);
8426 t1 = newTemp(Ity_V128);
8427 t2 = newTemp(Ity_V128);
8428 assign(t1, getWReg(ws));
8429 assign(t2, getWReg(wt));
8430 putWReg(wd,
8431 binop(Iop_64HLtoV128,
8432 binop(Iop_Mul64,
8433 unop(Iop_V128HIto64,
8434 mkexpr(t1)),
8435 unop(Iop_V128HIto64,
8436 mkexpr(t2))),
8437 binop(Iop_Mul64,
8438 unop(Iop_V128to64,
8439 mkexpr(t1)),
8440 unop(Iop_V128to64,
8441 mkexpr(t2)))));
8442 break;
8445 default:
8446 return -1;
8449 break;
8452 case 0x01: { /* MADDV.df */
8453 switch (df) {
8454 case 0x00: { /* MADDV.B */
8455 DIP("MADDV.B w%d, w%d, w%d", wd, ws, wt);
8456 putWReg(wd,
8457 binop(Iop_Add8x16,
8458 getWReg(wd),
8459 binop(Iop_Mul8x16,
8460 getWReg(ws),
8461 getWReg(wt))));
8462 break;
8465 case 0x01: { /* MADDV.H */
8466 DIP("MADDV.H w%d, w%d, w%d", wd, ws, wt);
8467 putWReg(wd,
8468 binop(Iop_Add16x8,
8469 getWReg(wd),
8470 binop(Iop_Mul16x8,
8471 getWReg(ws),
8472 getWReg(wt))));
8473 break;
8476 case 0x02: { /* MADDV.W */
8477 DIP("MADDV.W w%d, w%d, w%d", wd, ws, wt);
8478 putWReg(wd,
8479 binop(Iop_Add32x4,
8480 getWReg(wd),
8481 binop(Iop_Mul32x4,
8482 getWReg(ws),
8483 getWReg(wt))));
8484 break;
8487 case 0x03: { /* MADDV.D */
8488 DIP("MADDV.D w%d, w%d, w%d", wd, ws, wt);
8489 t1 = newTemp(Ity_V128);
8490 t2 = newTemp(Ity_V128);
8491 assign(t1, getWReg(ws));
8492 assign(t2, getWReg(wt));
8493 putWReg(wd,
8494 binop(Iop_Add64x2,
8495 getWReg(wd),
8496 binop(Iop_64HLtoV128,
8497 binop(Iop_Mul64,
8498 unop(Iop_V128HIto64,
8499 mkexpr(t1)),
8500 unop(Iop_V128HIto64,
8501 mkexpr(t2))),
8502 binop(Iop_Mul64,
8503 unop(Iop_V128to64,
8504 mkexpr(t1)),
8505 unop(Iop_V128to64,
8506 mkexpr(t2))))));
8507 break;
8510 default:
8511 return -1;
8514 break;
8517 case 0x02: { /* MSUBV.df */
8518 switch (df) {
8519 case 0x00: { /* MSUBV.B */
8520 DIP("MSUBV.B w%d, w%d, w%d", wd, ws, wt);
8521 putWReg(wd,
8522 binop(Iop_Sub8x16,
8523 getWReg(wd),
8524 binop(Iop_Mul8x16,
8525 getWReg(ws),
8526 getWReg(wt))));
8527 break;
8530 case 0x01: { /* MSUBV.H */
8531 DIP("MSUBV.H w%d, w%d, w%d", wd, ws, wt);
8532 putWReg(wd,
8533 binop(Iop_Sub16x8,
8534 getWReg(wd),
8535 binop(Iop_Mul16x8,
8536 getWReg(ws),
8537 getWReg(wt))));
8538 break;
8541 case 0x02: { /* MSUBV.W */
8542 DIP("MSUBV.W w%d, w%d, w%d", wd, ws, wt);
8543 putWReg(wd,
8544 binop(Iop_Sub32x4,
8545 getWReg(wd),
8546 binop(Iop_Mul32x4,
8547 getWReg(ws),
8548 getWReg(wt))));
8549 break;
8552 case 0x03: { /* MSUBV.D */
8553 DIP("MSUBV.D w%d, w%d, w%d", wd, ws, wt);
8554 t1 = newTemp(Ity_V128);
8555 t2 = newTemp(Ity_V128);
8556 assign(t1, getWReg(ws));
8557 assign(t2, getWReg(wt));
8558 putWReg(wd,
8559 binop(Iop_Sub64x2,
8560 getWReg(wd),
8561 binop(Iop_64HLtoV128,
8562 binop(Iop_Mul64,
8563 unop(Iop_V128HIto64,
8564 mkexpr(t1)),
8565 unop(Iop_V128HIto64,
8566 mkexpr(t2))),
8567 binop(Iop_Mul64,
8568 unop(Iop_V128to64,
8569 mkexpr(t1)),
8570 unop(Iop_V128to64,
8571 mkexpr(t2))))));
8572 break;
8575 default:
8576 return -1;
8579 break;
8582 case 0x04: { /* DIV_S.df */
8583 t1 = newTemp(Ity_V128);
8584 t2 = newTemp(Ity_V128);
8585 assign(t1, getWReg(ws));
8586 assign(t2, getWReg(wt));
8588 switch (df) {
8589 case 0x00: { /* DIV_S.B */
8590 DIP("DIV_S.B w%d, w%d, w%d", wd, ws, wt);
8591 IRTemp tmp[16];
8592 Int i;
8594 for (i = 0; i < 16; i++) {
8595 tmp[i] = newTemp(Ity_I32);
8596 assign(tmp[i],
8597 binop(Iop_Shl32,
8598 binop(Iop_And32,
8599 mkU32(0xFF),
8600 binop(Iop_DivS32,
8601 unop(Iop_8Sto32,
8602 binop(Iop_GetElem8x16,
8603 mkexpr(t1),
8604 mkU8(i))),
8605 unop(Iop_8Sto32,
8606 binop(Iop_GetElem8x16,
8607 mkexpr(t2),
8608 mkU8(i))))),
8609 mkU8((i & 3) << 3)));
8612 putWReg(wd,
8613 binop(Iop_64HLtoV128,
8614 binop(Iop_32HLto64,
8615 binop(Iop_Or32,
8616 mkexpr(tmp[15]),
8617 binop(Iop_Or32,
8618 mkexpr(tmp[14]),
8619 binop(Iop_Or32,
8620 mkexpr(tmp[13]),
8621 mkexpr(tmp[12])))),
8622 binop(Iop_Or32,
8623 mkexpr(tmp[11]),
8624 binop(Iop_Or32,
8625 mkexpr(tmp[10]),
8626 binop(Iop_Or32,
8627 mkexpr(tmp[9]),
8628 mkexpr(tmp[8]))))),
8629 binop(Iop_32HLto64,
8630 binop(Iop_Or32,
8631 mkexpr(tmp[7]),
8632 binop(Iop_Or32,
8633 mkexpr(tmp[6]),
8634 binop(Iop_Or32,
8635 mkexpr(tmp[5]),
8636 mkexpr(tmp[4])))),
8637 binop(Iop_Or32,
8638 mkexpr(tmp[3]),
8639 binop(Iop_Or32,
8640 mkexpr(tmp[2]),
8641 binop(Iop_Or32,
8642 mkexpr(tmp[1]),
8643 mkexpr(tmp[0]))))))
8645 break;
8648 case 0x01: { /* DIV_S.H */
8649 DIP("DIV_S.H w%d, w%d, w%d", wd, ws, wt);
8650 IRTemp tmp[8];
8651 Int i;
8653 for (i = 0; i < 8; i++) {
8654 tmp[i] = newTemp(Ity_I32);
8655 assign(tmp[i],
8656 binop(Iop_Shl32,
8657 binop(Iop_And32,
8658 mkU32(0xFFFF),
8659 binop(Iop_DivS32,
8660 unop(Iop_16Sto32,
8661 binop(Iop_GetElem16x8,
8662 mkexpr(t1),
8663 mkU8(i))),
8664 unop(Iop_16Sto32,
8665 binop(Iop_GetElem16x8,
8666 mkexpr(t2),
8667 mkU8(i))))),
8668 mkU8((i & 1) << 4)));
8671 putWReg(wd,
8672 binop(Iop_64HLtoV128,
8673 binop(Iop_32HLto64,
8674 binop(Iop_Or32,
8675 mkexpr(tmp[7]),
8676 mkexpr(tmp[6])),
8677 binop(Iop_Or32,
8678 mkexpr(tmp[5]),
8679 mkexpr(tmp[4]))),
8680 binop(Iop_32HLto64,
8681 binop(Iop_Or32,
8682 mkexpr(tmp[3]),
8683 mkexpr(tmp[2])),
8684 binop(Iop_Or32,
8685 mkexpr(tmp[1]),
8686 mkexpr(tmp[0])))));
8687 break;
8690 case 0x02: { /* DIV_S.W */
8691 DIP("DIV_S.W w%d, w%d, w%d", wd, ws, wt);
8692 IRTemp tmp[4];
8693 Int i;
8695 for (i = 0; i < 4; i++) {
8696 tmp[i] = newTemp(Ity_I32);
8697 assign(tmp[i],
8698 binop(Iop_DivS32,
8699 binop(Iop_GetElem32x4,
8700 mkexpr(t1), mkU8(i)),
8701 binop(Iop_GetElem32x4,
8702 mkexpr(t2), mkU8(i))));
8705 putWReg(wd,
8706 binop(Iop_64HLtoV128, \
8707 binop(Iop_32HLto64,
8708 mkexpr(tmp[3]),
8709 mkexpr(tmp[2])),
8710 binop(Iop_32HLto64,
8711 mkexpr(tmp[1]),
8712 mkexpr(tmp[0]))));
8713 break;
8716 case 0x03: { /* DIV_S.D */
8717 DIP("DIV_S.D w%d, w%d, w%d", wd, ws, wt);
8718 putWReg(wd,
8719 binop(Iop_64HLtoV128,
8720 binop(Iop_DivS64,
8721 unop(Iop_V128HIto64,
8722 mkexpr(t1)),
8723 unop(Iop_V128HIto64,
8724 mkexpr(t2))),
8725 binop(Iop_DivS64,
8726 unop(Iop_V128to64,
8727 mkexpr(t1)),
8728 unop(Iop_V128to64,
8729 mkexpr(t2)))));
8730 break;
8733 default:
8734 return -1;
8737 break;
8740 case 0x05: { /* DIV_U.df */
8741 t1 = newTemp(Ity_V128);
8742 t2 = newTemp(Ity_V128);
8743 assign(t1, getWReg(ws));
8744 assign(t2, getWReg(wt));
8746 switch (df) {
8747 case 0x00: { /* DIV_U.B */
8748 DIP("DIV_U.B w%d, w%d, w%d", wd, ws, wt);
8749 IRTemp tmp[16];
8750 Int i;
8752 for (i = 0; i < 16; i++) {
8753 tmp[i] = newTemp(Ity_I32);
8754 assign(tmp[i],
8755 binop(Iop_Shl32,
8756 binop(Iop_And32,
8757 mkU32(0xFF),
8758 binop(Iop_DivU32,
8759 unop(Iop_8Uto32,
8760 binop(Iop_GetElem8x16,
8761 mkexpr(t1),
8762 mkU8(i))),
8763 unop(Iop_8Uto32,
8764 binop(Iop_GetElem8x16,
8765 mkexpr(t2),
8766 mkU8(i))))),
8767 mkU8((i & 3) << 3)));
8770 putWReg(wd,
8771 binop(Iop_64HLtoV128,
8772 binop(Iop_32HLto64,
8773 binop(Iop_Or32,
8774 mkexpr(tmp[15]),
8775 binop(Iop_Or32,
8776 mkexpr(tmp[14]),
8777 binop(Iop_Or32,
8778 mkexpr(tmp[13]),
8779 mkexpr(tmp[12])))),
8780 binop(Iop_Or32,
8781 mkexpr(tmp[11]),
8782 binop(Iop_Or32,
8783 mkexpr(tmp[10]),
8784 binop(Iop_Or32,
8785 mkexpr(tmp[9]),
8786 mkexpr(tmp[8]))))),
8787 binop(Iop_32HLto64,
8788 binop(Iop_Or32,
8789 mkexpr(tmp[7]),
8790 binop(Iop_Or32,
8791 mkexpr(tmp[6]),
8792 binop(Iop_Or32,
8793 mkexpr(tmp[5]),
8794 mkexpr(tmp[4])))),
8795 binop(Iop_Or32,
8796 mkexpr(tmp[3]),
8797 binop(Iop_Or32,
8798 mkexpr(tmp[2]),
8799 binop(Iop_Or32,
8800 mkexpr(tmp[1]),
8801 mkexpr(tmp[0]))))))
8803 break;
8806 case 0x01: { /* DIV_U.H */
8807 DIP("DIV_U.H w%d, w%d, w%d", wd, ws, wt);
8808 IRTemp tmp[8];
8809 Int i;
8811 for (i = 0; i < 8; i++) {
8812 tmp[i] = newTemp(Ity_I32);
8813 assign(tmp[i],
8814 binop(Iop_Shl32,
8815 binop(Iop_And32,
8816 mkU32(0xFFFF),
8817 binop(Iop_DivU32,
8818 unop(Iop_16Uto32,
8819 binop(Iop_GetElem16x8,
8820 mkexpr(t1),
8821 mkU8(i))),
8822 unop(Iop_16Uto32,
8823 binop(Iop_GetElem16x8,
8824 mkexpr(t2),
8825 mkU8(i))))),
8826 mkU8((i & 1) << 4)));
8829 putWReg(wd,
8830 binop(Iop_64HLtoV128,
8831 binop(Iop_32HLto64,
8832 binop(Iop_Or32,
8833 mkexpr(tmp[7]),
8834 mkexpr(tmp[6])),
8835 binop(Iop_Or32,
8836 mkexpr(tmp[5]),
8837 mkexpr(tmp[4]))),
8838 binop(Iop_32HLto64,
8839 binop(Iop_Or32,
8840 mkexpr(tmp[3]),
8841 mkexpr(tmp[2])),
8842 binop(Iop_Or32,
8843 mkexpr(tmp[1]),
8844 mkexpr(tmp[0])))));
8845 break;
8848 case 0x02: { /* DIV_U.W */
8849 DIP("DIV_U.W w%d, w%d, w%d", wd, ws, wt);
8850 IRTemp tmp[4];
8851 Int i;
8853 for (i = 0; i < 4; i++) {
8854 tmp[i] = newTemp(Ity_I32);
8855 assign(tmp[i],
8856 binop(Iop_DivU32,
8857 binop(Iop_GetElem32x4,
8858 mkexpr(t1), mkU8(i)),
8859 binop(Iop_GetElem32x4,
8860 mkexpr(t2), mkU8(i))));
8863 putWReg(wd,
8864 binop(Iop_64HLtoV128,
8865 binop(Iop_32HLto64,
8866 mkexpr(tmp[3]),
8867 mkexpr(tmp[2])),
8868 binop(Iop_32HLto64,
8869 mkexpr(tmp[1]),
8870 mkexpr(tmp[0]))));
8871 break;
8874 case 0x03: { /* DIV_U.D */
8875 DIP("DIV_U.D w%d, w%d, w%d", wd, ws, wt);
8876 putWReg(wd,
8877 binop(Iop_64HLtoV128,
8878 binop(Iop_DivU64,
8879 unop(Iop_V128HIto64,
8880 mkexpr(t1)),
8881 unop(Iop_V128HIto64,
8882 mkexpr(t2))),
8883 binop(Iop_DivU64,
8884 unop(Iop_V128to64,
8885 mkexpr(t1)),
8886 unop(Iop_V128to64,
8887 mkexpr(t2)))));
8888 break;
8891 default:
8892 return -1;
8895 break;
8898 case 0x06: { /* MOD_S.df */
8899 t1 = newTemp(Ity_V128);
8900 t2 = newTemp(Ity_V128);
8901 assign(t1, getWReg(ws));
8902 assign(t2, getWReg(wt));
8904 switch (df) {
8905 case 0x00: { /* MOD_S.B */
8906 DIP("MOD_S.B w%d, w%d, w%d", wd, ws, wt);
8907 IRTemp tmp[16];
8908 Int i;
8910 for (i = 0; i < 16; i++) {
8911 tmp[i] = newTemp(Ity_I32);
8912 assign(tmp[i],
8913 binop(Iop_Shl32,
8914 binop(Iop_And32,
8915 mkU32(0xFF),
8916 unop(Iop_64HIto32,
8917 binop(Iop_DivModS32to32,
8918 unop(Iop_8Sto32,
8919 binop(Iop_GetElem8x16,
8920 mkexpr(t1),
8921 mkU8(i))),
8922 unop(Iop_8Sto32,
8923 binop(Iop_GetElem8x16,
8924 mkexpr(t2),
8925 mkU8(i)))))),
8926 mkU8((i & 3) << 3)));
8929 putWReg(wd,
8930 binop(Iop_64HLtoV128,
8931 binop(Iop_32HLto64,
8932 binop(Iop_Or32,
8933 mkexpr(tmp[15]),
8934 binop(Iop_Or32,
8935 mkexpr(tmp[14]),
8936 binop(Iop_Or32,
8937 mkexpr(tmp[13]),
8938 mkexpr(tmp[12])))),
8939 binop(Iop_Or32,
8940 mkexpr(tmp[11]),
8941 binop(Iop_Or32,
8942 mkexpr(tmp[10]),
8943 binop(Iop_Or32,
8944 mkexpr(tmp[9]),
8945 mkexpr(tmp[8]))))),
8946 binop(Iop_32HLto64,
8947 binop(Iop_Or32,
8948 mkexpr(tmp[7]),
8949 binop(Iop_Or32,
8950 mkexpr(tmp[6]),
8951 binop(Iop_Or32,
8952 mkexpr(tmp[5]),
8953 mkexpr(tmp[4])))),
8954 binop(Iop_Or32,
8955 mkexpr(tmp[3]),
8956 binop(Iop_Or32,
8957 mkexpr(tmp[2]),
8958 binop(Iop_Or32,
8959 mkexpr(tmp[1]),
8960 mkexpr(tmp[0])))))));
8961 break;
8964 case 0x01: { /* MOD_S.H */
8965 DIP("MOD_S.H w%d, w%d, w%d", wd, ws, wt);
8966 IRTemp tmp[8];
8967 Int i;
8969 for (i = 0; i < 8; i++) {
8970 tmp[i] = newTemp(Ity_I32);
8971 assign(tmp[i],
8972 binop(Iop_Shl32,
8973 binop(Iop_And32,
8974 mkU32(0xFFFF),
8975 unop(Iop_64HIto32,
8976 binop(Iop_DivModS32to32,
8977 unop(Iop_16Sto32,
8978 binop(Iop_GetElem16x8,
8979 mkexpr(t1),
8980 mkU8(i))),
8981 unop(Iop_16Sto32,
8982 binop(Iop_GetElem16x8,
8983 mkexpr(t2),
8984 mkU8(i)))))),
8985 mkU8((i & 1) << 4)));
8988 putWReg(wd,
8989 binop(Iop_64HLtoV128,
8990 binop(Iop_32HLto64,
8991 binop(Iop_Or32,
8992 mkexpr(tmp[7]),
8993 mkexpr(tmp[6])),
8994 binop(Iop_Or32,
8995 mkexpr(tmp[5]),
8996 mkexpr(tmp[4]))),
8997 binop(Iop_32HLto64,
8998 binop(Iop_Or32,
8999 mkexpr(tmp[3]),
9000 mkexpr(tmp[2])),
9001 binop(Iop_Or32,
9002 mkexpr(tmp[1]),
9003 mkexpr(tmp[0])))));
9004 break;
9007 case 0x02: { /* MOD_S.W */
9008 DIP("MOD_S.W w%d, w%d, w%d", wd, ws, wt);
9009 IRTemp tmp[4];
9010 Int i;
9012 for (i = 0; i < 4; i++) {
9013 tmp[i] = newTemp(Ity_I32);
9014 assign(tmp[i],
9015 unop(Iop_64HIto32,
9016 binop(Iop_DivModS32to32,
9017 binop(Iop_GetElem32x4,
9018 mkexpr(t1),
9019 mkU8(i)),
9020 binop(Iop_GetElem32x4,
9021 mkexpr(t2),
9022 mkU8(i)))));
9025 putWReg(wd,
9026 binop(Iop_64HLtoV128,
9027 binop(Iop_32HLto64,
9028 mkexpr(tmp[3]),
9029 mkexpr(tmp[2])),
9030 binop(Iop_32HLto64,
9031 mkexpr(tmp[1]),
9032 mkexpr(tmp[0]))));
9033 break;
9036 case 0x03: { /* MOD_S.D */
9037 DIP("MOD_S.D w%d, w%d, w%d", wd, ws, wt);
9038 t3 = newTemp(Ity_I64);
9039 t4 = newTemp(Ity_I64);
9040 t5 = newTemp(Ity_I64);
9041 t6 = newTemp(Ity_I64);
9042 assign(t3, unop(Iop_V128HIto64, mkexpr(t1)));
9043 assign(t4, unop(Iop_V128HIto64, mkexpr(t2)));
9044 assign(t5, unop(Iop_V128to64, mkexpr(t1)));
9045 assign(t6, unop(Iop_V128to64, mkexpr(t2)));
9046 putWReg(wd,
9047 binop(Iop_64HLtoV128,
9048 binop(Iop_Sub64,
9049 mkexpr(t3),
9050 binop(Iop_Mul64,
9051 mkexpr(t4),
9052 binop(Iop_DivS64,
9053 mkexpr(t3),
9054 mkexpr(t4)))),
9055 binop(Iop_Sub64,
9056 mkexpr(t5),
9057 binop(Iop_Mul64,
9058 mkexpr(t6),
9059 binop(Iop_DivS64,
9060 mkexpr(t5),
9061 mkexpr(t6))))));
9062 break;
9065 default:
9066 return -1;
9069 break;
9072 case 0x07: { /* MOD_U.df */
9073 t1 = newTemp(Ity_V128);
9074 t2 = newTemp(Ity_V128);
9075 assign(t1, getWReg(ws));
9076 assign(t2, getWReg(wt));
9078 switch (df) {
9079 case 0x00: { /* MOD_U.B */
9080 DIP("MOD_U.B w%d, w%d, w%d", wd, ws, wt);
9081 IRTemp tmp[16];
9082 Int i;
9084 for (i = 0; i < 16; i++) {
9085 tmp[i] = newTemp(Ity_I32);
9086 assign(tmp[i],
9087 binop(Iop_Shl32,
9088 binop(Iop_And32,
9089 mkU32(0xFF),
9090 unop(Iop_64HIto32,
9091 binop(Iop_DivModU32to32,
9092 unop(Iop_8Uto32,
9093 binop(Iop_GetElem8x16,
9094 mkexpr(t1),
9095 mkU8(i))),
9096 unop(Iop_8Uto32,
9097 binop(Iop_GetElem8x16,
9098 mkexpr(t2),
9099 mkU8(i)))))),
9100 mkU8((i & 3) << 3)));
9103 putWReg(wd,
9104 binop(Iop_64HLtoV128,
9105 binop(Iop_32HLto64,
9106 binop(Iop_Or32,
9107 mkexpr(tmp[15]),
9108 binop(Iop_Or32,
9109 mkexpr(tmp[14]),
9110 binop(Iop_Or32,
9111 mkexpr(tmp[13]),
9112 mkexpr(tmp[12])))),
9113 binop(Iop_Or32,
9114 mkexpr(tmp[11]),
9115 binop(Iop_Or32,
9116 mkexpr(tmp[10]),
9117 binop(Iop_Or32,
9118 mkexpr(tmp[9]),
9119 mkexpr(tmp[8]))))),
9120 binop(Iop_32HLto64,
9121 binop(Iop_Or32,
9122 mkexpr(tmp[7]),
9123 binop(Iop_Or32,
9124 mkexpr(tmp[6]),
9125 binop(Iop_Or32,
9126 mkexpr(tmp[5]),
9127 mkexpr(tmp[4])))),
9128 binop(Iop_Or32,
9129 mkexpr(tmp[3]),
9130 binop(Iop_Or32,
9131 mkexpr(tmp[2]),
9132 binop(Iop_Or32,
9133 mkexpr(tmp[1]),
9134 mkexpr(tmp[0])))))));
9135 break;
9138 case 0x01: { /* MOD_U.H */
9139 DIP("MOD_U.H w%d, w%d, w%d", wd, ws, wt);
9140 IRTemp tmp[8];
9141 Int i;
9143 for (i = 0; i < 8; i++) {
9144 tmp[i] = newTemp(Ity_I32);
9145 assign(tmp[i],
9146 binop(Iop_Shl32,
9147 binop(Iop_And32,
9148 mkU32(0xFFFF),
9149 unop(Iop_64HIto32,
9150 binop(Iop_DivModU32to32,
9151 unop(Iop_16Uto32,
9152 binop(Iop_GetElem16x8,
9153 mkexpr(t1),
9154 mkU8(i))),
9155 unop(Iop_16Uto32,
9156 binop(Iop_GetElem16x8,
9157 mkexpr(t2),
9158 mkU8(i)))))),
9159 mkU8((i & 1) << 4)));
9162 putWReg(wd,
9163 binop(Iop_64HLtoV128,
9164 binop(Iop_32HLto64,
9165 binop(Iop_Or32,
9166 mkexpr(tmp[7]),
9167 mkexpr(tmp[6])),
9168 binop(Iop_Or32,
9169 mkexpr(tmp[5]),
9170 mkexpr(tmp[4]))),
9171 binop(Iop_32HLto64,
9172 binop(Iop_Or32,
9173 mkexpr(tmp[3]),
9174 mkexpr(tmp[2])),
9175 binop(Iop_Or32,
9176 mkexpr(tmp[1]),
9177 mkexpr(tmp[0])))));
9178 break;
9181 case 0x02: { /* MOD_U.W */
9182 DIP("MOD_U.W w%d, w%d, w%d", wd, ws, wt);
9183 IRTemp tmp[4];
9184 Int i;
9186 for (i = 0; i < 4; i++) {
9187 tmp[i] = newTemp(Ity_I32);
9188 assign(tmp[i],
9189 unop(Iop_64HIto32,
9190 binop(Iop_DivModU32to32,
9191 binop(Iop_GetElem32x4,
9192 mkexpr(t1),
9193 mkU8(i)),
9194 binop(Iop_GetElem32x4,
9195 mkexpr(t2),
9196 mkU8(i)))));
9199 putWReg(wd,
9200 binop(Iop_64HLtoV128,
9201 binop(Iop_32HLto64,
9202 mkexpr(tmp[3]),
9203 mkexpr(tmp[2])),
9204 binop(Iop_32HLto64,
9205 mkexpr(tmp[1]),
9206 mkexpr(tmp[0]))));
9207 break;
9210 case 0x03: { /* MOD_U.D */
9211 DIP("MOD_U.D w%d, w%d, w%d", wd, ws, wt);
9212 t3 = newTemp(Ity_I64);
9213 t4 = newTemp(Ity_I64);
9214 t5 = newTemp(Ity_I64);
9215 t6 = newTemp(Ity_I64);
9216 assign(t3, unop(Iop_V128HIto64, mkexpr(t1)));
9217 assign(t4, unop(Iop_V128HIto64, mkexpr(t2)));
9218 assign(t5, unop(Iop_V128to64, mkexpr(t1)));
9219 assign(t6, unop(Iop_V128to64, mkexpr(t2)));
9220 putWReg(wd,
9221 binop(Iop_64HLtoV128,
9222 binop(Iop_Sub64,
9223 mkexpr(t3),
9224 binop(Iop_Mul64,
9225 mkexpr(t4),
9226 binop(Iop_DivU64,
9227 mkexpr(t3),
9228 mkexpr(t4)))),
9229 binop(Iop_Sub64,
9230 mkexpr(t5),
9231 binop(Iop_Mul64,
9232 mkexpr(t6),
9233 binop(Iop_DivU64,
9234 mkexpr(t5),
9235 mkexpr(t6))))));
9236 break;
9239 default:
9240 return -1;
9243 break;
9246 default:
9247 return -1;
9250 return 0;
9253 static Int msa_3R_13(UInt cins, UChar wd, UChar ws) /* 3R (0x13) */
9255 IRTemp t1, t2;
9256 UShort operation;
9257 UChar df, wt;
9259 operation = (cins & 0x03800000) >> 23;
9260 df = (cins & 0x00600000) >> 21;
9261 wt = (cins & 0x001F0000) >> 16;
9263 switch (operation) {
9264 case 0x00: { /* DOTP_S.df */
9265 t1 = newTemp(Ity_V128);
9266 t2 = newTemp(Ity_V128);
9267 assign(t1, getWReg(ws));
9268 assign(t2, getWReg(wt));
9270 switch (df) {
9271 case 0x01: { /* DOTP_S.H */
9272 DIP("DOTP_S.H w%d, w%d, w%d", wd, ws, wt);
9273 IRTemp tmp[8];
9274 Int i;
9276 for (i = 0; i < 8; i++) {
9277 tmp[i] = newTemp(Ity_I16);
9278 assign(tmp[i],
9279 binop(Iop_Add16,
9280 binop(Iop_MullS8,
9281 binop(Iop_GetElem8x16,
9282 mkexpr(t1),
9283 mkU8(2 * i)),
9284 binop(Iop_GetElem8x16,
9285 mkexpr(t2),
9286 mkU8(2 * i))),
9287 binop(Iop_MullS8,
9288 binop(Iop_GetElem8x16,
9289 mkexpr(t1),
9290 mkU8(2 * i + 1)),
9291 binop(Iop_GetElem8x16,
9292 mkexpr(t2),
9293 mkU8(2 * i + 1)))));
9296 putWReg(wd,
9297 binop(Iop_64HLtoV128,
9298 binop(Iop_32HLto64,
9299 binop(Iop_16HLto32,
9300 mkexpr(tmp[7]),
9301 mkexpr(tmp[6])),
9302 binop(Iop_16HLto32,
9303 mkexpr(tmp[5]),
9304 mkexpr(tmp[4]))),
9305 binop(Iop_32HLto64,
9306 binop(Iop_16HLto32,
9307 mkexpr(tmp[3]),
9308 mkexpr(tmp[2])),
9309 binop(Iop_16HLto32,
9310 mkexpr(tmp[1]),
9311 mkexpr(tmp[0])))));
9312 break;
9315 case 0x02: { /* DOTP_S.W */
9316 DIP("DOTP_S.W w%d, w%d, w%d", wd, ws, wt);
9317 IRTemp tmp[4];
9318 Int i;
9320 for (i = 0; i < 4; i++) {
9321 tmp[i] = newTemp(Ity_I32);
9322 assign(tmp[i],
9323 binop(Iop_Add32,
9324 binop(Iop_MullS16,
9325 binop(Iop_GetElem16x8,
9326 mkexpr(t1),
9327 mkU8(2 * i)),
9328 binop(Iop_GetElem16x8,
9329 mkexpr(t2),
9330 mkU8(2 * i))),
9331 binop(Iop_MullS16,
9332 binop(Iop_GetElem16x8,
9333 mkexpr(t1),
9334 mkU8(2 * i + 1)),
9335 binop(Iop_GetElem16x8,
9336 mkexpr(t2),
9337 mkU8(2 * i + 1)))));
9340 putWReg(wd,
9341 binop(Iop_64HLtoV128,
9342 binop(Iop_32HLto64,
9343 mkexpr(tmp[3]),
9344 mkexpr(tmp[2])),
9345 binop(Iop_32HLto64,
9346 mkexpr(tmp[1]),
9347 mkexpr(tmp[0]))));
9348 break;
9351 case 0x03: { /* DOTP_S.D */
9352 DIP("DOTP_S.D w%d, w%d, w%d", wd, ws, wt);
9353 IRTemp tmp[2];
9354 Int i;
9356 for (i = 0; i < 2; i++) {
9357 tmp[i] = newTemp(Ity_I64);
9358 assign(tmp[i],
9359 binop(Iop_Add64,
9360 binop(Iop_MullS32,
9361 binop(Iop_GetElem32x4,
9362 mkexpr(t1),
9363 mkU8(2 * i)),
9364 binop(Iop_GetElem32x4,
9365 mkexpr(t2),
9366 mkU8(2 * i))),
9367 binop(Iop_MullS32,
9368 binop(Iop_GetElem32x4,
9369 mkexpr(t1),
9370 mkU8(2 * i + 1)),
9371 binop(Iop_GetElem32x4,
9372 mkexpr(t2),
9373 mkU8(2 * i + 1)))));
9376 putWReg(wd,
9377 binop(Iop_64HLtoV128,
9378 mkexpr(tmp[1]), mkexpr(tmp[0])));
9379 break;
9382 default:
9383 return -1;
9386 break;
9389 case 0x01: { /* DOTP_U.df */
9390 t1 = newTemp(Ity_V128);
9391 t2 = newTemp(Ity_V128);
9392 assign(t1, getWReg(ws));
9393 assign(t2, getWReg(wt));
9395 switch (df) {
9396 case 0x01: { /* DOTP_U.H */
9397 DIP("DOTP_U.H w%d, w%d, w%d", wd, ws, wt);
9398 IRTemp tmp[8];
9399 Int i;
9401 for (i = 0; i < 8; i++) {
9402 tmp[i] = newTemp(Ity_I16);
9403 assign(tmp[i],
9404 binop(Iop_Add16,
9405 binop(Iop_MullU8,
9406 binop(Iop_GetElem8x16,
9407 mkexpr(t1),
9408 mkU8(2 * i)),
9409 binop(Iop_GetElem8x16,
9410 mkexpr(t2),
9411 mkU8(2 * i))),
9412 binop(Iop_MullU8,
9413 binop(Iop_GetElem8x16,
9414 mkexpr(t1),
9415 mkU8(2 * i + 1)),
9416 binop(Iop_GetElem8x16,
9417 mkexpr(t2),
9418 mkU8(2 * i + 1)))));
9421 putWReg(wd,
9422 binop(Iop_64HLtoV128,
9423 binop(Iop_32HLto64,
9424 binop(Iop_16HLto32,
9425 mkexpr(tmp[7]),
9426 mkexpr(tmp[6])),
9427 binop(Iop_16HLto32,
9428 mkexpr(tmp[5]),
9429 mkexpr(tmp[4]))),
9430 binop(Iop_32HLto64,
9431 binop(Iop_16HLto32,
9432 mkexpr(tmp[3]),
9433 mkexpr(tmp[2])),
9434 binop(Iop_16HLto32,
9435 mkexpr(tmp[1]),
9436 mkexpr(tmp[0])))));
9437 break;
9440 case 0x02: { /* DOTP_U.W */
9441 DIP("DOTP_U.W w%d, w%d, w%d", wd, ws, wt);
9442 IRTemp tmp[4];
9443 Int i;
9445 for (i = 0; i < 4; i++) {
9446 tmp[i] = newTemp(Ity_I32);
9447 assign(tmp[i],
9448 binop(Iop_Add32,
9449 binop(Iop_MullU16,
9450 binop(Iop_GetElem16x8,
9451 mkexpr(t1),
9452 mkU8(2 * i)),
9453 binop(Iop_GetElem16x8,
9454 mkexpr(t2),
9455 mkU8(2 * i))),
9456 binop(Iop_MullU16,
9457 binop(Iop_GetElem16x8,
9458 mkexpr(t1),
9459 mkU8(2 * i + 1)),
9460 binop(Iop_GetElem16x8,
9461 mkexpr(t2),
9462 mkU8(2 * i + 1)))));
9465 putWReg(wd,
9466 binop(Iop_64HLtoV128,
9467 binop(Iop_32HLto64,
9468 mkexpr(tmp[3]),
9469 mkexpr(tmp[2])),
9470 binop(Iop_32HLto64,
9471 mkexpr(tmp[1]),
9472 mkexpr(tmp[0]))));
9473 break;
9476 case 0x03: { /* DOTP_U.D */
9477 DIP("DOTP_U.D w%d, w%d, w%d", wd, ws, wt);
9478 IRTemp tmp[2];
9479 Int i;
9481 for (i = 0; i < 2; i++) {
9482 tmp[i] = newTemp(Ity_I64);
9483 assign(tmp[i],
9484 binop(Iop_Add64,
9485 binop(Iop_MullU32,
9486 binop(Iop_GetElem32x4,
9487 mkexpr(t1),
9488 mkU8(2 * i)),
9489 binop(Iop_GetElem32x4,
9490 mkexpr(t2),
9491 mkU8(2 * i))),
9492 binop(Iop_MullU32,
9493 binop(Iop_GetElem32x4,
9494 mkexpr(t1),
9495 mkU8(2 * i + 1)),
9496 binop(Iop_GetElem32x4,
9497 mkexpr(t2),
9498 mkU8(2 * i + 1)))));
9501 putWReg(wd,
9502 binop(Iop_64HLtoV128,
9503 mkexpr(tmp[1]), mkexpr(tmp[0])));
9504 break;
9507 default:
9508 return -1;
9511 break;
9514 case 0x02: { /* DPADD_S.df */
9515 t1 = newTemp(Ity_V128);
9516 t2 = newTemp(Ity_V128);
9517 assign(t1, getWReg(ws));
9518 assign(t2, getWReg(wt));
9520 switch (df) {
9521 case 0x01: { /* DPADD_S.H */
9522 DIP("DPADD_S.H w%d, w%d, w%d", wd, ws, wt);
9523 IRTemp tmp[8];
9524 Int i;
9526 for (i = 0; i < 8; i++) {
9527 tmp[i] = newTemp(Ity_I16);
9528 assign(tmp[i],
9529 binop(Iop_Add16,
9530 binop(Iop_MullS8,
9531 binop(Iop_GetElem8x16,
9532 mkexpr(t1),
9533 mkU8(2 * i)),
9534 binop(Iop_GetElem8x16,
9535 mkexpr(t2),
9536 mkU8(2 * i))),
9537 binop(Iop_MullS8,
9538 binop(Iop_GetElem8x16,
9539 mkexpr(t1),
9540 mkU8(2 * i + 1)),
9541 binop(Iop_GetElem8x16,
9542 mkexpr(t2),
9543 mkU8(2 * i + 1)))));
9546 putWReg(wd,
9547 binop(Iop_Add16x8,
9548 getWReg(wd),
9549 binop(Iop_64HLtoV128,
9550 binop(Iop_32HLto64,
9551 binop(Iop_16HLto32,
9552 mkexpr(tmp[7]),
9553 mkexpr(tmp[6])),
9554 binop(Iop_16HLto32,
9555 mkexpr(tmp[5]),
9556 mkexpr(tmp[4]))),
9557 binop(Iop_32HLto64,
9558 binop(Iop_16HLto32,
9559 mkexpr(tmp[3]),
9560 mkexpr(tmp[2])),
9561 binop(Iop_16HLto32,
9562 mkexpr(tmp[1]),
9563 mkexpr(tmp[0]))))));
9564 break;
9567 case 0x02: { /* DPADD_S.W */
9568 DIP("DPADD_S.W w%d, w%d, w%d", wd, ws, wt);
9569 IRTemp tmp[4];
9570 Int i;
9572 for (i = 0; i < 4; i++) {
9573 tmp[i] = newTemp(Ity_I32);
9574 assign(tmp[i],
9575 binop(Iop_Add32,
9576 binop(Iop_MullS16,
9577 binop(Iop_GetElem16x8,
9578 mkexpr(t1),
9579 mkU8(2 * i)),
9580 binop(Iop_GetElem16x8,
9581 mkexpr(t2),
9582 mkU8(2 * i))),
9583 binop(Iop_MullS16,
9584 binop(Iop_GetElem16x8,
9585 mkexpr(t1),
9586 mkU8(2 * i + 1)),
9587 binop(Iop_GetElem16x8,
9588 mkexpr(t2),
9589 mkU8(2 * i + 1)))));
9592 putWReg(wd,
9593 binop(Iop_Add32x4,
9594 getWReg(wd),
9595 binop(Iop_64HLtoV128,
9596 binop(Iop_32HLto64,
9597 mkexpr(tmp[3]),
9598 mkexpr(tmp[2])),
9599 binop(Iop_32HLto64,
9600 mkexpr(tmp[1]),
9601 mkexpr(tmp[0])))));
9602 break;
9605 case 0x03: { /* DPADD_S.D */
9606 DIP("DPADD_S.D w%d, w%d, w%d", wd, ws, wt);
9607 IRTemp tmp[2];
9608 Int i;
9610 for (i = 0; i < 2; i++) {
9611 tmp[i] = newTemp(Ity_I64);
9612 assign(tmp[i],
9613 binop(Iop_Add64,
9614 binop(Iop_MullS32,
9615 binop(Iop_GetElem32x4,
9616 mkexpr(t1),
9617 mkU8(2 * i)),
9618 binop(Iop_GetElem32x4,
9619 mkexpr(t2),
9620 mkU8(2 * i))),
9621 binop(Iop_MullS32,
9622 binop(Iop_GetElem32x4,
9623 mkexpr(t1),
9624 mkU8(2 * i + 1)),
9625 binop(Iop_GetElem32x4,
9626 mkexpr(t2),
9627 mkU8(2 * i + 1)))));
9630 putWReg(wd,
9631 binop(Iop_Add64x2,
9632 getWReg(wd),
9633 binop(Iop_64HLtoV128,
9634 mkexpr(tmp[1]),
9635 mkexpr(tmp[0]))));
9636 break;
9639 default:
9640 return -1;
9643 break;
9646 case 0x03: { /* DPADD_U.df */
9647 t1 = newTemp(Ity_V128);
9648 t2 = newTemp(Ity_V128);
9649 assign(t1, getWReg(ws));
9650 assign(t2, getWReg(wt));
9652 switch (df) {
9653 case 0x01: { /* DPADD_U.H */
9654 DIP("DPADD_U.H w%d, w%d, w%d", wd, ws, wt);
9655 IRTemp tmp[8];
9656 Int i;
9658 for (i = 0; i < 8; i++) {
9659 tmp[i] = newTemp(Ity_I16);
9660 assign(tmp[i],
9661 binop(Iop_Add16,
9662 binop(Iop_MullU8,
9663 binop(Iop_GetElem8x16,
9664 mkexpr(t1),
9665 mkU8(2 * i)),
9666 binop(Iop_GetElem8x16,
9667 mkexpr(t2),
9668 mkU8(2 * i))),
9669 binop(Iop_MullU8,
9670 binop(Iop_GetElem8x16,
9671 mkexpr(t1),
9672 mkU8(2 * i + 1)),
9673 binop(Iop_GetElem8x16,
9674 mkexpr(t2),
9675 mkU8(2 * i + 1)))));
9678 putWReg(wd,
9679 binop(Iop_Add16x8,
9680 getWReg(wd),
9681 binop(Iop_64HLtoV128,
9682 binop(Iop_32HLto64,
9683 binop(Iop_16HLto32,
9684 mkexpr(tmp[7]),
9685 mkexpr(tmp[6])),
9686 binop(Iop_16HLto32,
9687 mkexpr(tmp[5]),
9688 mkexpr(tmp[4]))),
9689 binop(Iop_32HLto64,
9690 binop(Iop_16HLto32,
9691 mkexpr(tmp[3]),
9692 mkexpr(tmp[2])),
9693 binop(Iop_16HLto32,
9694 mkexpr(tmp[1]),
9695 mkexpr(tmp[0]))))));
9696 break;
9699 case 0x02: { /* DPADD_U.W */
9700 DIP("DPADD_U.W w%d, w%d, w%d", wd, ws, wt);
9701 IRTemp tmp[4];
9702 Int i;
9704 for (i = 0; i < 4; i++) {
9705 tmp[i] = newTemp(Ity_I32);
9706 assign(tmp[i],
9707 binop(Iop_Add32,
9708 binop(Iop_MullU16,
9709 binop(Iop_GetElem16x8,
9710 mkexpr(t1),
9711 mkU8(2 * i)),
9712 binop(Iop_GetElem16x8,
9713 mkexpr(t2),
9714 mkU8(2 * i))),
9715 binop(Iop_MullU16,
9716 binop(Iop_GetElem16x8,
9717 mkexpr(t1),
9718 mkU8(2 * i + 1)),
9719 binop(Iop_GetElem16x8,
9720 mkexpr(t2),
9721 mkU8(2 * i + 1)))));
9724 putWReg(wd,
9725 binop(Iop_Add32x4,
9726 getWReg(wd),
9727 binop(Iop_64HLtoV128,
9728 binop(Iop_32HLto64,
9729 mkexpr(tmp[3]),
9730 mkexpr(tmp[2])),
9731 binop(Iop_32HLto64,
9732 mkexpr(tmp[1]),
9733 mkexpr(tmp[0])))));
9734 break;
9737 case 0x03: { /* DPADD_U.D */
9738 DIP("DPADD_U.D w%d, w%d, w%d", wd, ws, wt);
9739 IRTemp tmp[2];
9740 Int i;
9742 for (i = 0; i < 2; i++) {
9743 tmp[i] = newTemp(Ity_I64);
9744 assign(tmp[i],
9745 binop(Iop_Add64,
9746 binop(Iop_MullU32,
9747 binop(Iop_GetElem32x4,
9748 mkexpr(t1),
9749 mkU8(2 * i)),
9750 binop(Iop_GetElem32x4,
9751 mkexpr(t2),
9752 mkU8(2 * i))),
9753 binop(Iop_MullU32,
9754 binop(Iop_GetElem32x4,
9755 mkexpr(t1),
9756 mkU8(2 * i + 1)),
9757 binop(Iop_GetElem32x4,
9758 mkexpr(t2),
9759 mkU8(2 * i + 1)))));
9762 putWReg(wd,
9763 binop(Iop_Add64x2,
9764 getWReg(wd),
9765 binop(Iop_64HLtoV128,
9766 mkexpr(tmp[1]),
9767 mkexpr(tmp[0]))));
9768 break;
9771 default:
9772 return -1;
9775 break;
9778 case 0x04: { /* DPSUB_S.df */
9779 t1 = newTemp(Ity_V128);
9780 t2 = newTemp(Ity_V128);
9781 assign(t1, getWReg(ws));
9782 assign(t2, getWReg(wt));
9784 switch (df) {
9785 case 0x01: { /* DPSUB_S.H */
9786 DIP("DPSUB_S.H w%d, w%d, w%d", wd, ws, wt);
9787 IRTemp tmp[8];
9788 Int i;
9790 for (i = 0; i < 8; i++) {
9791 tmp[i] = newTemp(Ity_I16);
9792 assign(tmp[i],
9793 binop(Iop_Add16,
9794 binop(Iop_MullS8,
9795 binop(Iop_GetElem8x16,
9796 mkexpr(t1),
9797 mkU8(2 * i)),
9798 binop(Iop_GetElem8x16,
9799 mkexpr(t2),
9800 mkU8(2 * i))),
9801 binop(Iop_MullS8,
9802 binop(Iop_GetElem8x16,
9803 mkexpr(t1),
9804 mkU8(2 * i + 1)),
9805 binop(Iop_GetElem8x16,
9806 mkexpr(t2),
9807 mkU8(2 * i + 1)))));
9810 putWReg(wd,
9811 binop(Iop_Sub16x8,
9812 getWReg(wd),
9813 binop(Iop_64HLtoV128,
9814 binop(Iop_32HLto64,
9815 binop(Iop_16HLto32,
9816 mkexpr(tmp[7]),
9817 mkexpr(tmp[6])),
9818 binop(Iop_16HLto32,
9819 mkexpr(tmp[5]),
9820 mkexpr(tmp[4]))),
9821 binop(Iop_32HLto64,
9822 binop(Iop_16HLto32,
9823 mkexpr(tmp[3]),
9824 mkexpr(tmp[2])),
9825 binop(Iop_16HLto32,
9826 mkexpr(tmp[1]),
9827 mkexpr(tmp[0]))))));
9828 break;
9831 case 0x02: { /* DPSUB_S.W */
9832 DIP("DPSUB_S.W w%d, w%d, w%d", wd, ws, wt);
9833 IRTemp tmp[4];
9834 Int i;
9836 for (i = 0; i < 4; i++) {
9837 tmp[i] = newTemp(Ity_I32);
9838 assign(tmp[i],
9839 binop(Iop_Add32,
9840 binop(Iop_MullS16,
9841 binop(Iop_GetElem16x8,
9842 mkexpr(t1),
9843 mkU8(2 * i)),
9844 binop(Iop_GetElem16x8,
9845 mkexpr(t2),
9846 mkU8(2 * i))),
9847 binop(Iop_MullS16,
9848 binop(Iop_GetElem16x8,
9849 mkexpr(t1),
9850 mkU8(2 * i + 1)),
9851 binop(Iop_GetElem16x8,
9852 mkexpr(t2),
9853 mkU8(2 * i + 1)))));
9856 putWReg(wd,
9857 binop(Iop_Sub32x4,
9858 getWReg(wd),
9859 binop(Iop_64HLtoV128,
9860 binop(Iop_32HLto64,
9861 mkexpr(tmp[3]),
9862 mkexpr(tmp[2])),
9863 binop(Iop_32HLto64,
9864 mkexpr(tmp[1]),
9865 mkexpr(tmp[0])))));
9866 break;
9869 case 0x03: { /* DPSUB_S.D */
9870 DIP("DPSUB_S.D w%d, w%d, w%d", wd, ws, wt);
9871 IRTemp tmp[2];
9872 Int i;
9874 for (i = 0; i < 2; i++) {
9875 tmp[i] = newTemp(Ity_I64);
9876 assign(tmp[i],
9877 binop(Iop_Add64,
9878 binop(Iop_MullS32,
9879 binop(Iop_GetElem32x4,
9880 mkexpr(t1),
9881 mkU8(2 * i)),
9882 binop(Iop_GetElem32x4,
9883 mkexpr(t2),
9884 mkU8(2 * i))),
9885 binop(Iop_MullS32,
9886 binop(Iop_GetElem32x4,
9887 mkexpr(t1),
9888 mkU8(2 * i + 1)),
9889 binop(Iop_GetElem32x4,
9890 mkexpr(t2),
9891 mkU8(2 * i + 1)))));
9894 putWReg(wd,
9895 binop(Iop_Sub64x2,
9896 getWReg(wd),
9897 binop(Iop_64HLtoV128,
9898 mkexpr(tmp[1]),
9899 mkexpr(tmp[0]))));
9900 break;
9903 default:
9904 return -1;
9907 break;
9910 case 0x05: { /* DPSUB_U.df */
9911 t1 = newTemp(Ity_V128);
9912 t2 = newTemp(Ity_V128);
9913 assign(t1, getWReg(ws));
9914 assign(t2, getWReg(wt));
9916 switch (df) {
9917 case 0x01: { /* DPSUB_U.H */
9918 DIP("DPSUB_U.H w%d, w%d, w%d", wd, ws, wt);
9919 IRTemp tmp[8];
9920 Int i;
9922 for (i = 0; i < 8; i++) {
9923 tmp[i] = newTemp(Ity_I16);
9924 assign(tmp[i],
9925 binop(Iop_Add16,
9926 binop(Iop_MullU8,
9927 binop(Iop_GetElem8x16,
9928 mkexpr(t1),
9929 mkU8(2 * i)),
9930 binop(Iop_GetElem8x16,
9931 mkexpr(t2),
9932 mkU8(2 * i))),
9933 binop(Iop_MullU8,
9934 binop(Iop_GetElem8x16,
9935 mkexpr(t1),
9936 mkU8(2 * i + 1)),
9937 binop(Iop_GetElem8x16,
9938 mkexpr(t2),
9939 mkU8(2 * i + 1)))));
9942 putWReg(wd,
9943 binop(Iop_Sub16x8,
9944 getWReg(wd),
9945 binop(Iop_64HLtoV128,
9946 binop(Iop_32HLto64,
9947 binop(Iop_16HLto32,
9948 mkexpr(tmp[7]),
9949 mkexpr(tmp[6])),
9950 binop(Iop_16HLto32,
9951 mkexpr(tmp[5]),
9952 mkexpr(tmp[4]))),
9953 binop(Iop_32HLto64,
9954 binop(Iop_16HLto32,
9955 mkexpr(tmp[3]),
9956 mkexpr(tmp[2])),
9957 binop(Iop_16HLto32,
9958 mkexpr(tmp[1]),
9959 mkexpr(tmp[0]))))));
9960 break;
9963 case 0x02: { /* DPSUB_U.W */
9964 DIP("DPSUB_U.W w%d, w%d, w%d", wd, ws, wt);
9965 IRTemp tmp[4];
9966 Int i;
9968 for (i = 0; i < 4; i++) {
9969 tmp[i] = newTemp(Ity_I32);
9970 assign(tmp[i],
9971 binop(Iop_Add32,
9972 binop(Iop_MullU16,
9973 binop(Iop_GetElem16x8,
9974 mkexpr(t1),
9975 mkU8(2 * i)),
9976 binop(Iop_GetElem16x8,
9977 mkexpr(t2),
9978 mkU8(2 * i))),
9979 binop(Iop_MullU16,
9980 binop(Iop_GetElem16x8,
9981 mkexpr(t1),
9982 mkU8(2 * i + 1)),
9983 binop(Iop_GetElem16x8,
9984 mkexpr(t2),
9985 mkU8(2 * i + 1)))));
9988 putWReg(wd,
9989 binop(Iop_Sub32x4,
9990 getWReg(wd),
9991 binop(Iop_64HLtoV128,
9992 binop(Iop_32HLto64,
9993 mkexpr(tmp[3]),
9994 mkexpr(tmp[2])),
9995 binop(Iop_32HLto64,
9996 mkexpr(tmp[1]),
9997 mkexpr(tmp[0])))));
9998 break;
10001 case 0x03: { /* DPSUB_U.D */
10002 DIP("DPSUB_U.D w%d, w%d, w%d", wd, ws, wt);
10003 IRTemp tmp[2];
10004 Int i;
10006 for (i = 0; i < 2; i++) {
10007 tmp[i] = newTemp(Ity_I64);
10008 assign(tmp[i],
10009 binop(Iop_Add64,
10010 binop(Iop_MullU32,
10011 binop(Iop_GetElem32x4,
10012 mkexpr(t1),
10013 mkU8(2 * i)),
10014 binop(Iop_GetElem32x4,
10015 mkexpr(t2),
10016 mkU8(2 * i))),
10017 binop(Iop_MullU32,
10018 binop(Iop_GetElem32x4,
10019 mkexpr(t1),
10020 mkU8(2 * i + 1)),
10021 binop(Iop_GetElem32x4,
10022 mkexpr(t2),
10023 mkU8(2 * i + 1)))));
10026 putWReg(wd,
10027 binop(Iop_Sub64x2,
10028 getWReg(wd),
10029 binop(Iop_64HLtoV128,
10030 mkexpr(tmp[1]),
10031 mkexpr(tmp[0]))));
10032 break;
10035 default:
10036 return -1;
10039 break;
10042 default:
10043 return -1;
10046 return 0;
10049 static Int msa_3R_14(UInt cins, UChar wd, UChar ws) /* 3R (0x14) */
10051 IRTemp t1, t2, t3, t4;
10052 IRType ty;
10053 UShort operation;
10054 UChar df, wt;
10056 operation = (cins & 0x03800000) >> 23;
10057 df = (cins & 0x00600000) >> 21;
10058 wt = (cins & 0x001F0000) >> 16;
10059 ty = mode64 ? Ity_I64 : Ity_I32;
10061 switch (operation) {
10062 case 0x00: { /* SLD.df */
10063 switch (df) {
10064 case 0x00: {
10065 DIP("SLD.B w%d, w%d[%d]", wd, ws, wt);
10066 t1 = newTemp(Ity_I32);
10067 t2 = newTemp(Ity_V128);
10068 t3 = newTemp(Ity_V128);
10069 assign(t1,
10070 binop(Iop_Shl32,
10071 binop(Iop_And32,
10072 mkNarrowTo32(ty,
10073 getIReg(wt)),
10074 mkU32(15)),
10075 mkU8(3)));
10076 assign(t2,
10077 binop(Iop_ShrV128,
10078 getWReg(ws),
10079 unop(Iop_32to8, mkexpr(t1))));
10080 assign(t3,
10081 binop(Iop_ShlV128,
10082 getWReg(wd),
10083 unop(Iop_32to8,
10084 binop(Iop_Sub32,
10085 mkU32(128),
10086 mkexpr(t1)))));
10087 putWReg(wd,
10088 binop(Iop_OrV128,
10089 mkexpr(t2), mkexpr(t3)));
10090 break;
10093 case 0x01: {/* SLD.H */
10094 DIP("SLD.H w%d, w%d[%d]", wd, ws, wt);
10095 t1 = newTemp(Ity_I32);
10096 t2 = newTemp(Ity_I64);
10097 t3 = newTemp(Ity_V128);
10098 t4 = newTemp(Ity_V128);
10099 assign(t1,
10100 binop(Iop_Shl32,
10101 binop(Iop_And32,
10102 mkNarrowTo32(ty,
10103 getIReg(wt)),
10104 mkU32(7)),
10105 mkU8(3)));
10106 assign(t2,
10107 binop(Iop_32HLto64, mkU32(0), mkexpr(t1)));
10108 assign(t3,
10109 binop(Iop_Shr64x2,
10110 getWReg(ws),
10111 binop(Iop_64HLtoV128,
10112 mkexpr(t2), mkexpr(t2))));
10113 assign(t4,
10114 binop(Iop_Shl64x2,
10115 getWReg(wd),
10116 binop(Iop_Sub64x2,
10117 binop(Iop_64HLtoV128,
10118 mkU64(0x40ul),
10119 mkU64(0x40ul)),
10120 binop(Iop_64HLtoV128,
10121 mkexpr(t2),
10122 mkexpr(t2)))));
10123 putWReg(wd,
10124 binop(Iop_OrV128,
10125 mkexpr(t3),
10126 IRExpr_ITE(
10127 binop(Iop_CmpNE32,
10128 mkexpr(t1), mkU32(0)),
10129 mkexpr(t4),
10130 binop(Iop_64HLtoV128,
10131 mkU64(0), mkU64(0)))));
10132 break;
10135 case 0x02: {/* SLD.W */
10136 DIP("SLD.W w%d, w%d[%d]", wd, ws, wt);
10137 t1 = newTemp(Ity_I32);
10138 t2 = newTemp(Ity_I64);
10139 t3 = newTemp(Ity_V128);
10140 t4 = newTemp(Ity_V128);
10141 assign(t1,
10142 binop(Iop_Shl32,
10143 binop(Iop_And32,
10144 mkNarrowTo32(ty,
10145 getIReg(wt)),
10146 mkU32(3)),
10147 mkU8(3)));
10148 assign(t2,
10149 binop(Iop_32HLto64,
10150 mkexpr(t1), mkexpr(t1)));
10151 assign(t3,
10152 binop(Iop_Shr32x4,
10153 getWReg(ws),
10154 binop(Iop_64HLtoV128,
10155 mkexpr(t2), mkexpr(t2))));
10156 assign(t4,
10157 binop(Iop_Shl32x4,
10158 getWReg(wd),
10159 binop(Iop_Sub32x4,
10160 binop(Iop_64HLtoV128,
10161 mkU64(0x2000000020ul),
10162 mkU64(0x2000000020ul)),
10163 binop(Iop_64HLtoV128,
10164 mkexpr(t2),
10165 mkexpr(t2)))));
10166 putWReg(wd,
10167 binop(Iop_OrV128,
10168 mkexpr(t3),
10169 IRExpr_ITE(
10170 binop(Iop_CmpNE32,
10171 mkexpr(t1), mkU32(0)),
10172 mkexpr(t4),
10173 binop(Iop_64HLtoV128,
10174 mkU64(0), mkU64(0)))));
10175 break;
10178 case 0x03: { /* SLD.D */
10179 DIP("SLD.D w%d, w%d[%d]", wd, ws, wt);
10180 t1 = newTemp(Ity_I32);
10181 t2 = newTemp(Ity_I64);
10182 t3 = newTemp(Ity_V128);
10183 t4 = newTemp(Ity_V128);
10184 assign(t1,
10185 binop(Iop_Shl32,
10186 binop(Iop_And32,
10187 mkNarrowTo32(ty,
10188 getIReg(wt)),
10189 mkU32(1)),
10190 mkU8(3)));
10191 assign(t2,
10192 binop(Iop_32HLto64,
10193 binop(Iop_Or32,
10194 mkexpr(t1),
10195 binop(Iop_Shl32,
10196 mkexpr(t1), mkU8(16))),
10197 binop(Iop_Or32,
10198 mkexpr(t1),
10199 binop(Iop_Shl32,
10200 mkexpr(t1), mkU8(16)))));
10201 assign(t3,
10202 binop(Iop_Shr16x8,
10203 getWReg(ws),
10204 binop(Iop_64HLtoV128,
10205 mkexpr(t2), mkexpr(t2))));
10206 assign(t4,
10207 binop(Iop_Shl16x8,
10208 getWReg(wd),
10209 binop(Iop_Sub16x8,
10210 binop(Iop_64HLtoV128,
10211 mkU64(0x10001000100010ul),
10212 mkU64(0x10001000100010ul)),
10213 binop(Iop_64HLtoV128,
10214 mkexpr(t2),
10215 mkexpr(t2)))));
10216 putWReg(wd,
10217 binop(Iop_OrV128,
10218 mkexpr(t3),
10219 IRExpr_ITE(
10220 binop(Iop_CmpNE32,
10221 mkexpr(t1), mkU32(0)),
10222 mkexpr(t4),
10223 binop(Iop_64HLtoV128,
10224 mkU64(0), mkU64(0)))));
10225 break;
10229 break;
10232 case 0x01: { /* SPLAT.df */
10233 switch (df) {
10234 Int i;
10236 case 0x00: { /* SPLAT.B */
10237 DIP("SPLAT.B w%d, w%d, w%d", wd, ws, wt);
10238 t1 = newTemp(Ity_V128);
10239 t2 = newTemp(Ity_I32);
10240 assign(t1, getWReg(ws));
10241 assign(t2,
10242 mkNarrowTo32(ty, getIReg(wt)));
10243 IRTemp tmp[16];
10245 for (i = 0; i < 16; i++) {
10246 tmp[i] = newTemp(Ity_I8);
10247 assign(tmp[i],
10248 binop(Iop_GetElem8x16,
10249 mkexpr(t1),
10250 unop(Iop_32to8, mkexpr(t2))));
10253 putWReg(wd,
10254 binop(Iop_64HLtoV128,
10255 binop(Iop_32HLto64,
10256 binop(Iop_16HLto32,
10257 binop(Iop_8HLto16,
10258 mkexpr(tmp[15]),
10259 mkexpr(tmp[14])),
10260 binop(Iop_8HLto16,
10261 mkexpr(tmp[13]),
10262 mkexpr(tmp[12]))),
10263 binop(Iop_16HLto32,
10264 binop(Iop_8HLto16,
10265 mkexpr(tmp[11]),
10266 mkexpr(tmp[10])),
10267 binop(Iop_8HLto16,
10268 mkexpr(tmp[9]),
10269 mkexpr(tmp[8])))),
10270 binop(Iop_32HLto64,
10271 binop(Iop_16HLto32,
10272 binop(Iop_8HLto16,
10273 mkexpr(tmp[7]),
10274 mkexpr(tmp[6])),
10275 binop(Iop_8HLto16,
10276 mkexpr(tmp[5]),
10277 mkexpr(tmp[4]))),
10278 binop(Iop_16HLto32,
10279 binop(Iop_8HLto16,
10280 mkexpr(tmp[3]),
10281 mkexpr(tmp[2])),
10282 binop(Iop_8HLto16,
10283 mkexpr(tmp[1]),
10284 mkexpr(tmp[0]))))));
10285 break;
10288 case 0x01: { /* SPLAT.H */
10289 DIP("SPLAT.H w%d, w%d, w%d", wd, ws, wt);
10290 t1 = newTemp(Ity_V128);
10291 t2 = newTemp(Ity_I32);
10292 assign(t1, getWReg(ws));
10293 assign(t2,
10294 mkNarrowTo32(ty, getIReg(wt)));
10295 IRTemp tmp[8];
10297 for (i = 0; i < 8; i++) {
10298 tmp[i] = newTemp(Ity_I16);
10299 assign(tmp[i],
10300 binop(Iop_GetElem16x8,
10301 mkexpr(t1),
10302 unop(Iop_32to8, mkexpr(t2))));
10305 putWReg(wd,
10306 binop(Iop_64HLtoV128,
10307 binop(Iop_32HLto64,
10308 binop(Iop_16HLto32,
10309 mkexpr(tmp[7]),
10310 mkexpr(tmp[6])),
10311 binop(Iop_16HLto32,
10312 mkexpr(tmp[5]),
10313 mkexpr(tmp[4]))),
10314 binop(Iop_32HLto64,
10315 binop(Iop_16HLto32,
10316 mkexpr(tmp[3]),
10317 mkexpr(tmp[2])),
10318 binop(Iop_16HLto32,
10319 mkexpr(tmp[1]),
10320 mkexpr(tmp[0])))));
10321 break;
10324 case 0x02: { /* SPLAT.W */
10325 DIP("SPLAT.W w%d, w%d, w%d", wd, ws, wt);
10326 t1 = newTemp(Ity_V128);
10327 t2 = newTemp(Ity_I32);
10328 assign(t1, getWReg(ws));
10329 assign(t2,
10330 mkNarrowTo32(ty, getIReg(wt)));
10331 IRTemp tmp[4];
10333 for (i = 0; i < 4; i++) {
10334 tmp[i] = newTemp(Ity_I32);
10335 assign(tmp[i],
10336 binop(Iop_GetElem32x4,
10337 mkexpr(t1),
10338 unop(Iop_32to8, mkexpr(t2))));
10341 putWReg(wd,
10342 binop(Iop_64HLtoV128,
10343 binop(Iop_32HLto64,
10344 mkexpr(tmp[3]),
10345 mkexpr(tmp[2])),
10346 binop(Iop_32HLto64,
10347 mkexpr(tmp[1]),
10348 mkexpr(tmp[0]))));
10349 break;
10352 case 0x03: { /* SPLAT.D */
10353 DIP("SPLAT.D w%d, w%d, w%d", wd, ws, wt);
10354 t1 = newTemp(Ity_V128);
10355 t2 = newTemp(Ity_I32);
10356 assign(t1, getWReg(ws));
10357 assign(t2,
10358 mkNarrowTo32(ty, getIReg(wt)));
10359 IRTemp tmp[2];
10361 for (i = 0; i < 2; i++) {
10362 tmp[i] = newTemp(Ity_I64);
10363 assign(tmp[i],
10364 binop(Iop_GetElem64x2,
10365 mkexpr(t1),
10366 unop(Iop_32to8, mkexpr(t2))));
10369 putWReg(wd,
10370 binop(Iop_64HLtoV128,
10371 mkexpr(tmp[1]), mkexpr(tmp[0])));
10372 break;
10376 break;
10379 case 0x02: { /* PCKEV.df */
10380 switch (df) {
10381 case 0x00: { /* PCKEV.B */
10382 DIP("PCKEV.B w%d, w%d, w%d", wd, ws, wt);
10383 t1 = newTemp(Ity_V128);
10384 t2 = newTemp(Ity_V128);
10385 t3 = newTemp(Ity_V128);
10386 assign(t1, getWReg(ws));
10387 assign(t2, getWReg(wt));
10388 assign(t3,
10389 binop(Iop_PackEvenLanes8x16,
10390 mkexpr(t1), mkexpr(t2)));
10391 putWReg(wd, mkexpr(t3));
10392 break;
10395 case 0x01: { /* PCKEV.H */
10396 DIP("PCKEV.H w%d, w%d, w%d", wd, ws, wt);
10397 t1 = newTemp(Ity_V128);
10398 t2 = newTemp(Ity_V128);
10399 t3 = newTemp(Ity_V128);
10400 assign(t1, getWReg(ws));
10401 assign(t2, getWReg(wt));
10402 assign(t3,
10403 binop(Iop_PackEvenLanes16x8,
10404 mkexpr(t1), mkexpr(t2)));
10405 putWReg(wd, mkexpr(t3));
10406 break;
10409 case 0x02: { /* PCKEV.W */
10410 DIP("PCKEV.W w%d, w%d, w%d", wd, ws, wt);
10411 t1 = newTemp(Ity_V128);
10412 t2 = newTemp(Ity_V128);
10413 t3 = newTemp(Ity_V128);
10414 assign(t1, getWReg(ws));
10415 assign(t2, getWReg(wt));
10416 assign(t3,
10417 binop(Iop_PackEvenLanes32x4,
10418 mkexpr(t1), mkexpr(t2)));
10419 putWReg(wd, mkexpr(t3));
10420 break;
10423 case 0x03: { /* PCKEV.D */
10424 DIP("PCKEV.D w%d, w%d, w%d", wd, ws, wt);
10425 t1 = newTemp(Ity_V128);
10426 t2 = newTemp(Ity_V128);
10427 t3 = newTemp(Ity_V128);
10428 assign(t1, getWReg(ws));
10429 assign(t2, getWReg(wt));
10430 assign(t3,
10431 binop(Iop_InterleaveLO64x2,
10432 mkexpr(t1), mkexpr(t2)));
10433 putWReg(wd, mkexpr(t3));
10434 break;
10437 default:
10438 return -1;
10441 break;
10444 case 0x03: { /* PCKOD.df */
10445 switch (df) {
10446 case 0x00: { /* PCKOD.B */
10447 DIP("PCKOD.B w%d, w%d, w%d", wd, ws, wt);
10448 t1 = newTemp(Ity_V128);
10449 t2 = newTemp(Ity_V128);
10450 t3 = newTemp(Ity_V128);
10451 assign(t1, getWReg(ws));
10452 assign(t2, getWReg(wt));
10453 assign(t3,
10454 binop(Iop_PackOddLanes8x16,
10455 mkexpr(t1), mkexpr(t2)));
10456 putWReg(wd, mkexpr(t3));
10457 break;
10460 case 0x01: { /* PCKOD.H */
10461 DIP("PCKOD.H w%d, w%d, w%d", wd, ws, wt);
10462 t1 = newTemp(Ity_V128);
10463 t2 = newTemp(Ity_V128);
10464 t3 = newTemp(Ity_V128);
10465 assign(t1, getWReg(ws));
10466 assign(t2, getWReg(wt));
10467 assign(t3,
10468 binop(Iop_PackOddLanes16x8,
10469 mkexpr(t1), mkexpr(t2)));
10470 putWReg(wd, mkexpr(t3));
10471 break;
10474 case 0x02: { /* PCKOD.W */
10475 DIP("PCKOD.W w%d, w%d, w%d", wd, ws, wt);
10476 t1 = newTemp(Ity_V128);
10477 t2 = newTemp(Ity_V128);
10478 t3 = newTemp(Ity_V128);
10479 assign(t1, getWReg(ws));
10480 assign(t2, getWReg(wt));
10481 assign(t3,
10482 binop(Iop_PackOddLanes32x4,
10483 mkexpr(t1), mkexpr(t2)));
10484 putWReg(wd, mkexpr(t3));
10485 break;
10488 case 0x03: { /* PCKOD.D */
10489 DIP("PCKOD.D w%d, w%d, w%d", wd, ws, wt);
10490 t1 = newTemp(Ity_V128);
10491 t2 = newTemp(Ity_V128);
10492 t3 = newTemp(Ity_V128);
10493 assign(t1, getWReg(ws));
10494 assign(t2, getWReg(wt));
10495 assign(t3,
10496 binop(Iop_InterleaveHI64x2,
10497 mkexpr(t1), mkexpr(t2)));
10498 putWReg(wd, mkexpr(t3));
10499 break;
10502 default:
10503 return -1;
10506 break;
10509 case 0x04: { /* ILVL.df */
10510 switch (df) {
10511 case 0x00: { /* ILVL.B */
10512 DIP("ILVL.B w%d, w%d, w%d", wd, ws, wt);
10513 t1 = newTemp(Ity_V128);
10514 t2 = newTemp(Ity_V128);
10515 t3 = newTemp(Ity_V128);
10516 assign(t1, getWReg(ws));
10517 assign(t2, getWReg(wt));
10518 assign(t3,
10519 binop(Iop_InterleaveHI8x16,
10520 mkexpr(t1), mkexpr(t2)));
10521 putWReg(wd, mkexpr(t3));
10522 break;
10525 case 0x01: { /* ILVL.H */
10526 DIP("ILVL.H w%d, w%d, w%d", wd, ws, wt);
10527 t1 = newTemp(Ity_V128);
10528 t2 = newTemp(Ity_V128);
10529 t3 = newTemp(Ity_V128);
10530 assign(t1, getWReg(ws));
10531 assign(t2, getWReg(wt));
10532 assign(t3,
10533 binop(Iop_InterleaveHI16x8,
10534 mkexpr(t1), mkexpr(t2)));
10535 putWReg(wd, mkexpr(t3));
10536 break;
10539 case 0x02: { /* ILVL.W */
10540 DIP("ILVL.W w%d, w%d, w%d", wd, ws, wt);
10541 t1 = newTemp(Ity_V128);
10542 t2 = newTemp(Ity_V128);
10543 t3 = newTemp(Ity_V128);
10544 assign(t1, getWReg(ws));
10545 assign(t2, getWReg(wt));
10546 assign(t3,
10547 binop(Iop_InterleaveHI32x4,
10548 mkexpr(t1), mkexpr(t2)));
10549 putWReg(wd, mkexpr(t3));
10550 break;
10553 case 0x03: { /* ILVL.D */
10554 DIP("ILVL.D w%d, w%d, w%d", wd, ws, wt);
10555 t1 = newTemp(Ity_V128);
10556 t2 = newTemp(Ity_V128);
10557 t3 = newTemp(Ity_V128);
10558 assign(t1, getWReg(ws));
10559 assign(t2, getWReg(wt));
10560 assign(t3,
10561 binop(Iop_InterleaveHI64x2,
10562 mkexpr(t1), mkexpr(t2)));
10563 putWReg(wd, mkexpr(t3));
10564 break;
10567 default:
10568 return -1;
10571 break;
10574 case 0x05: { /* ILVR.df */
10575 switch (df) {
10576 case 0x00: { /* ILVL.B */
10577 DIP("ILVL.B w%d, w%d, w%d", wd, ws, wt);
10578 t1 = newTemp(Ity_V128);
10579 t2 = newTemp(Ity_V128);
10580 t3 = newTemp(Ity_V128);
10581 assign(t1, getWReg(ws));
10582 assign(t2, getWReg(wt));
10583 assign(t3,
10584 binop(Iop_InterleaveLO8x16,
10585 mkexpr(t1), mkexpr(t2)));
10586 putWReg(wd, mkexpr(t3));
10587 break;
10590 case 0x01: { /* ILVL.H */
10591 DIP("ILVL.H w%d, w%d, w%d", wd, ws, wt);
10592 t1 = newTemp(Ity_V128);
10593 t2 = newTemp(Ity_V128);
10594 t3 = newTemp(Ity_V128);
10595 assign(t1, getWReg(ws));
10596 assign(t2, getWReg(wt));
10597 assign(t3,
10598 binop(Iop_InterleaveLO16x8,
10599 mkexpr(t1), mkexpr(t2)));
10600 putWReg(wd, mkexpr(t3));
10601 break;
10604 case 0x02: { /* ILVL.W */
10605 DIP("ILVL.W w%d, w%d, w%d", wd, ws, wt);
10606 t1 = newTemp(Ity_V128);
10607 t2 = newTemp(Ity_V128);
10608 t3 = newTemp(Ity_V128);
10609 assign(t1, getWReg(ws));
10610 assign(t2, getWReg(wt));
10611 assign(t3,
10612 binop(Iop_InterleaveLO32x4,
10613 mkexpr(t1), mkexpr(t2)));
10614 putWReg(wd, mkexpr(t3));
10615 break;
10618 case 0x03: { /* ILVL.D */
10619 DIP("ILVL.D w%d, w%d, w%d", wd, ws, wt);
10620 t1 = newTemp(Ity_V128);
10621 t2 = newTemp(Ity_V128);
10622 t3 = newTemp(Ity_V128);
10623 assign(t1, getWReg(ws));
10624 assign(t2, getWReg(wt));
10625 assign(t3,
10626 binop(Iop_InterleaveLO64x2,
10627 mkexpr(t1), mkexpr(t2)));
10628 putWReg(wd, mkexpr(t3));
10629 break;
10633 break;
10636 case 0x06: { /* ILVEV.df */
10637 switch (df) {
10638 case 0x00: { /* ILVEV.B */
10639 DIP("ILVEV.B w%d, w%d, w%d", wd, ws, wt);
10640 t1 = newTemp(Ity_V128);
10641 t2 = newTemp(Ity_V128);
10642 t3 = newTemp(Ity_V128);
10643 assign(t1, getWReg(ws));
10644 assign(t2, getWReg(wt));
10645 assign(t3,
10646 binop(Iop_InterleaveEvenLanes8x16,
10647 mkexpr(t1), mkexpr(t2)));
10648 putWReg(wd, mkexpr(t3));
10649 break;
10652 case 0x01: { /* ILVEV.H */
10653 DIP("ILVEV.H w%d, w%d, w%d", wd, ws, wt);
10654 t1 = newTemp(Ity_V128);
10655 t2 = newTemp(Ity_V128);
10656 t3 = newTemp(Ity_V128);
10657 assign(t1, getWReg(ws));
10658 assign(t2, getWReg(wt));
10659 assign(t3,
10660 binop(Iop_InterleaveEvenLanes16x8,
10661 mkexpr(t1), mkexpr(t2)));
10662 putWReg(wd, mkexpr(t3));
10663 break;
10666 case 0x02: { /* ILVEV.W */
10667 DIP("ILVEV.W w%d, w%d, w%d", wd, ws, wt);
10668 t1 = newTemp(Ity_V128);
10669 t2 = newTemp(Ity_V128);
10670 t3 = newTemp(Ity_V128);
10671 assign(t1, getWReg(ws));
10672 assign(t2, getWReg(wt));
10673 assign(t3,
10674 binop(Iop_InterleaveEvenLanes32x4,
10675 mkexpr(t1), mkexpr(t2)));
10676 putWReg(wd, mkexpr(t3));
10677 break;
10680 case 0x03: { /* ILVEV.D */
10681 DIP("ILVEV.D w%d, w%d, w%d", wd, ws, wt);
10682 t1 = newTemp(Ity_V128);
10683 t2 = newTemp(Ity_V128);
10684 t3 = newTemp(Ity_V128);
10685 assign(t1, getWReg(ws));
10686 assign(t2, getWReg(wt));
10687 assign(t3,
10688 binop(Iop_InterleaveLO64x2,
10689 mkexpr(t1), mkexpr(t2)));
10690 putWReg(wd, mkexpr(t3));
10691 break;
10694 default:
10695 return -1;
10698 break;
10701 case 0x07: { /* ILVOD.df */
10702 switch (df) {
10703 case 0x00: { /* ILVOD.B */
10704 DIP("ILVOD.B w%d, w%d, w%d", wd, ws, wt);
10705 t1 = newTemp(Ity_V128);
10706 t2 = newTemp(Ity_V128);
10707 t3 = newTemp(Ity_V128);
10708 assign(t1, getWReg(ws));
10709 assign(t2, getWReg(wt));
10710 assign(t3,
10711 binop(Iop_InterleaveOddLanes8x16,
10712 mkexpr(t1), mkexpr(t2)));
10713 putWReg(wd, mkexpr(t3));
10714 break;
10717 case 0x01: { /* ILVOD.H */
10718 DIP("ILVOD.H w%d, w%d, w%d", wd, ws, wt);
10719 t1 = newTemp(Ity_V128);
10720 t2 = newTemp(Ity_V128);
10721 t3 = newTemp(Ity_V128);
10722 assign(t1, getWReg(ws));
10723 assign(t2, getWReg(wt));
10724 assign(t3,
10725 binop(Iop_InterleaveOddLanes16x8,
10726 mkexpr(t1), mkexpr(t2)));
10727 putWReg(wd, mkexpr(t3));
10728 break;
10731 case 0x02: { /* ILVOD.W */
10732 DIP("ILVOD.W w%d, w%d, w%d", wd, ws, wt);
10733 t1 = newTemp(Ity_V128);
10734 t2 = newTemp(Ity_V128);
10735 t3 = newTemp(Ity_V128);
10736 assign(t1, getWReg(ws));
10737 assign(t2, getWReg(wt));
10738 assign(t3,
10739 binop(Iop_InterleaveOddLanes32x4,
10740 mkexpr(t1), mkexpr(t2)));
10741 putWReg(wd, mkexpr(t3));
10742 break;
10745 case 0x03: { /* ILVOD.D */
10746 DIP("ILVOD.D w%d, w%d, w%d", wd, ws, wt);
10747 t1 = newTemp(Ity_V128);
10748 t2 = newTemp(Ity_V128);
10749 t3 = newTemp(Ity_V128);
10750 assign(t1, getWReg(ws));
10751 assign(t2, getWReg(wt));
10752 assign(t3,
10753 binop(Iop_InterleaveHI64x2,
10754 mkexpr(t1), mkexpr(t2)));
10755 putWReg(wd, mkexpr(t3));
10756 break;
10759 default:
10760 return -1;
10763 break;
10766 default:
10767 return -1;
10770 return 0;
10773 static Int msa_3R_15(UInt cins, UChar wd, UChar ws) /* 3R (0x15) */
10775 IRTemp t1, t2, t3, t4;
10776 UShort operation;
10777 UChar df, wt;
10779 operation = (cins & 0x03800000) >> 23;
10780 df = (cins & 0x00600000) >> 21;
10781 wt = (cins & 0x001F0000) >> 16;
10783 switch (operation) {
10784 case 0x00: { /* VSHF.df */
10785 t1 = newTemp(Ity_V128);
10786 t2 = newTemp(Ity_V128);
10787 t3 = newTemp(Ity_V128);
10788 assign(t1, getWReg(wd));
10789 assign(t2, getWReg(ws));
10790 assign(t3, getWReg(wt));
10792 switch (df) {
10793 case 0x00: { /* VSHF.B */
10794 DIP("VSHF.B w%d, w%d, w%d", wd, ws, wt);
10795 IRTemp tmp[16];
10796 Int i;
10798 for (i = 0; i < 16; i++) {
10799 tmp[i] = newTemp(Ity_I8);
10800 assign(tmp[i],
10801 IRExpr_ITE(
10802 binop(Iop_CmpEQ8,
10803 binop(Iop_And8,
10804 binop(Iop_GetElem8x16,
10805 mkexpr(t1),
10806 mkU8(i)),
10807 mkU8(0xC0)),
10808 mkU8(0x0)),
10809 IRExpr_ITE(
10810 binop(Iop_CmpEQ8,
10811 binop(Iop_And8,
10812 binop(Iop_GetElem8x16,
10813 mkexpr(t1),
10814 mkU8(i)),
10815 mkU8(0x10)),
10816 mkU8(0x0)),
10817 binop(Iop_GetElem8x16,
10818 mkexpr(t3),
10819 binop(Iop_GetElem8x16,
10820 mkexpr(t1),
10821 mkU8(i))),
10822 binop(Iop_GetElem8x16,
10823 mkexpr(t2),
10824 binop(Iop_GetElem8x16,
10825 mkexpr(t1),
10826 mkU8(i)))),
10827 mkU8(0x0)));
10830 putWReg(wd,
10831 binop(Iop_64HLtoV128,
10832 binop(Iop_32HLto64,
10833 binop(Iop_16HLto32,
10834 binop(Iop_8HLto16,
10835 mkexpr(tmp[15]),
10836 mkexpr(tmp[14])),
10837 binop(Iop_8HLto16,
10838 mkexpr(tmp[13]),
10839 mkexpr(tmp[12]))),
10840 binop(Iop_16HLto32,
10841 binop(Iop_8HLto16,
10842 mkexpr(tmp[11]),
10843 mkexpr(tmp[10])),
10844 binop(Iop_8HLto16,
10845 mkexpr(tmp[9]),
10846 mkexpr(tmp[8])))),
10847 binop(Iop_32HLto64,
10848 binop(Iop_16HLto32,
10849 binop(Iop_8HLto16,
10850 mkexpr(tmp[7]),
10851 mkexpr(tmp[6])),
10852 binop(Iop_8HLto16,
10853 mkexpr(tmp[5]),
10854 mkexpr(tmp[4]))),
10855 binop(Iop_16HLto32,
10856 binop(Iop_8HLto16,
10857 mkexpr(tmp[3]),
10858 mkexpr(tmp[2])),
10859 binop(Iop_8HLto16,
10860 mkexpr(tmp[1]),
10861 mkexpr(tmp[0]))))));
10862 break;
10865 case 0x01: { /* VSHF.H */
10866 DIP("VSHF.H w%d, w%d, w%d", wd, ws, wt);
10867 IRTemp tmp[8];
10868 Int i;
10870 for (i = 0; i < 8; i++) {
10871 tmp[i] = newTemp(Ity_I16);
10872 assign(tmp[i],
10873 IRExpr_ITE(
10874 binop(Iop_CmpEQ16,
10875 binop(Iop_And16,
10876 binop(Iop_GetElem16x8,
10877 mkexpr(t1),
10878 mkU8(i)),
10879 mkU16(0xC0)),
10880 mkU16(0x0)),
10881 IRExpr_ITE(
10882 binop(Iop_CmpEQ16,
10883 binop(Iop_And16,
10884 binop(Iop_GetElem16x8,
10885 mkexpr(t1),
10886 mkU8(i)),
10887 mkU16(0x08)),
10888 mkU16(0x0)),
10889 binop(Iop_GetElem16x8,
10890 mkexpr(t3),
10891 unop(Iop_16to8,
10892 binop(Iop_GetElem16x8,
10893 mkexpr(t1),
10894 mkU8(i)))),
10895 binop(Iop_GetElem16x8,
10896 mkexpr(t2),
10897 unop(Iop_16to8,
10898 binop(Iop_GetElem16x8,
10899 mkexpr(t1),
10900 mkU8(i))))),
10901 mkU16(0x0)));
10904 putWReg(wd,
10905 binop(Iop_64HLtoV128,
10906 binop(Iop_32HLto64,
10907 binop(Iop_16HLto32,
10908 mkexpr(tmp[7]),
10909 mkexpr(tmp[6])),
10910 binop(Iop_16HLto32,
10911 mkexpr(tmp[5]),
10912 mkexpr(tmp[4]))),
10913 binop(Iop_32HLto64,
10914 binop(Iop_16HLto32,
10915 mkexpr(tmp[3]),
10916 mkexpr(tmp[2])),
10917 binop(Iop_16HLto32,
10918 mkexpr(tmp[1]),
10919 mkexpr(tmp[0])))));
10920 break;
10923 case 0x02: { /* VSHF.W */
10924 DIP("VSHF.W w%d, w%d, w%d", wd, ws, wt);
10925 IRTemp tmp[4];
10926 Int i;
10928 for (i = 0; i < 4; i++) {
10929 tmp[i] = newTemp(Ity_I32);
10930 assign(tmp[i],
10931 IRExpr_ITE(
10932 binop(Iop_CmpEQ32,
10933 binop(Iop_And32,
10934 binop(Iop_GetElem32x4,
10935 mkexpr(t1),
10936 mkU8(i)),
10937 mkU32(0xC0)),
10938 mkU32(0x0)),
10939 IRExpr_ITE(
10940 binop(Iop_CmpEQ32,
10941 binop(Iop_And32,
10942 binop(Iop_GetElem32x4,
10943 mkexpr(t1),
10944 mkU8(i)),
10945 mkU32(0x04)),
10946 mkU32(0x0)),
10947 binop(Iop_GetElem32x4,
10948 mkexpr(t3),
10949 unop(Iop_32to8,
10950 binop(Iop_GetElem32x4,
10951 mkexpr(t1),
10952 mkU8(i)))),
10953 binop(Iop_GetElem32x4,
10954 mkexpr(t2),
10955 unop(Iop_32to8,
10956 binop(Iop_GetElem32x4,
10957 mkexpr(t1),
10958 mkU8(i))))),
10959 mkU32(0x0)));
10962 putWReg(wd,
10963 binop(Iop_64HLtoV128,
10964 binop(Iop_32HLto64,
10965 mkexpr(tmp[3]),
10966 mkexpr(tmp[2])),
10967 binop(Iop_32HLto64,
10968 mkexpr(tmp[1]),
10969 mkexpr(tmp[0]))));
10970 break;
10973 case 0x03: { /* VSHF.D */
10974 DIP("VSHF.D w%d, w%d, w%d", wd, ws, wt);
10975 IRTemp tmp[2];
10976 Int i;
10978 for (i = 0; i < 2; i++) {
10979 tmp[i] = newTemp(Ity_I64);
10980 assign(tmp[i],
10981 IRExpr_ITE(
10982 binop(Iop_CmpEQ64,
10983 binop(Iop_And64,
10984 binop(Iop_GetElem64x2,
10985 mkexpr(t1),
10986 mkU8(i)),
10987 mkU64(0xC0)),
10988 mkU64(0x0)),
10989 IRExpr_ITE(
10990 binop(Iop_CmpEQ64,
10991 binop(Iop_And64,
10992 binop(Iop_GetElem64x2,
10993 mkexpr(t1),
10994 mkU8(i)),
10995 mkU64(0x02)),
10996 mkU64(0x0)),
10997 binop(Iop_GetElem64x2,
10998 mkexpr(t3),
10999 unop(Iop_64to8,
11000 binop(Iop_GetElem64x2,
11001 mkexpr(t1),
11002 mkU8(i)))),
11003 binop(Iop_GetElem64x2,
11004 mkexpr(t2),
11005 unop(Iop_64to8,
11006 binop(Iop_GetElem64x2,
11007 mkexpr(t1),
11008 mkU8(i))))),
11009 mkU64(0x0)));
11012 putWReg(wd,
11013 binop(Iop_64HLtoV128,
11014 mkexpr(tmp[1]), mkexpr(tmp[0])));
11015 break;
11018 default:
11019 return -1;
11022 break;
11025 case 0x01: { /* SRAR.df */
11026 switch (df) {
11027 case 0x00: { /* SRAR.B */
11028 DIP("SRAR.B w%d, w%d, w%d", wd, ws, wt);
11029 t1 = newTemp(Ity_V128);
11030 t2 = newTemp(Ity_V128);
11031 t3 = newTemp(Ity_V128);
11032 t4 = newTemp(Ity_V128);
11033 assign(t1,
11034 binop(Iop_Sar8x16,
11035 getWReg(ws),
11036 getWReg(wt)));
11037 assign(t2,
11038 binop(Iop_Sub8x16,
11039 binop(Iop_64HLtoV128,
11040 mkU64(0x808080808080808ull),
11041 mkU64(0x808080808080808ull)),
11042 getWReg(wt)));
11043 assign(t4,
11044 unop(Iop_NotV128,
11045 binop(Iop_CmpEQ8x16,
11046 binop(Iop_ShlN8x16,
11047 getWReg(wt),
11048 mkU8(5)),
11049 binop(Iop_64HLtoV128,
11050 mkU64(0), mkU64(0)))));
11051 assign(t3,
11052 binop(Iop_ShrN8x16,
11053 binop(Iop_AndV128,
11054 binop(Iop_Shl8x16,
11055 getWReg(ws),
11056 mkexpr(t2)),
11057 mkexpr(t4)),
11058 mkU8(7)));
11059 putWReg(wd,
11060 binop(Iop_Add8x16,
11061 mkexpr(t1), mkexpr(t3)));
11062 break;
11065 case 0x01: { /* SRAR.H */
11066 DIP("SRAR.H w%d, w%d, w%d", wd, ws, wt);
11067 t1 = newTemp(Ity_V128);
11068 t2 = newTemp(Ity_V128);
11069 t3 = newTemp(Ity_V128);
11070 t4 = newTemp(Ity_V128);
11071 assign(t1,
11072 binop(Iop_Sar16x8,
11073 getWReg(ws),
11074 getWReg(wt)));
11075 assign(t2,
11076 binop(Iop_Sub16x8,
11077 binop(Iop_64HLtoV128,
11078 mkU64(0x10001000100010ul),
11079 mkU64(0x10001000100010ul)),
11080 getWReg(wt)));
11081 assign(t4,
11082 unop(Iop_NotV128,
11083 binop(Iop_CmpEQ16x8,
11084 binop(Iop_ShlN16x8,
11085 getWReg(wt),
11086 mkU8(12)),
11087 binop(Iop_64HLtoV128,
11088 mkU64(0), mkU64(0)))));
11089 assign(t3,
11090 binop(Iop_ShrN16x8,
11091 binop(Iop_AndV128,
11092 binop(Iop_Shl16x8,
11093 getWReg(ws),
11094 mkexpr(t2)),
11095 mkexpr(t4)),
11096 mkU8(15)));
11097 putWReg(wd,
11098 binop(Iop_Add16x8,
11099 mkexpr(t1), mkexpr(t3)));
11100 break;
11103 case 0x02: { /* SRAR.W */
11104 DIP("SRAR.W w%d, w%d, w%d", wd, ws, wt);
11105 t1 = newTemp(Ity_V128); // shifted
11106 t2 = newTemp(Ity_V128); // 32 - wt
11107 t3 = newTemp(Ity_V128); // rv
11108 t4 = newTemp(Ity_V128); // wt % 32 == 0
11109 assign(t1,
11110 binop(Iop_Sar32x4,
11111 getWReg(ws),
11112 getWReg(wt)));
11113 assign(t2,
11114 binop(Iop_Sub32x4,
11115 binop(Iop_64HLtoV128,
11116 mkU64(0x2000000020ul),
11117 mkU64(0x2000000020ul)),
11118 getWReg(wt)));
11119 assign(t4,
11120 unop(Iop_NotV128,
11121 binop(Iop_CmpEQ32x4,
11122 binop(Iop_ShlN32x4,
11123 getWReg(wt),
11124 mkU8(27)),
11125 binop(Iop_64HLtoV128,
11126 mkU64(0), mkU64(0)))));
11127 assign(t3,
11128 binop(Iop_ShrN32x4,
11129 binop(Iop_AndV128,
11130 binop(Iop_Shl32x4,
11131 getWReg(ws),
11132 mkexpr(t2)),
11133 mkexpr(t4)),
11134 mkU8(31)));
11135 putWReg(wd,
11136 binop(Iop_Add32x4,
11137 mkexpr(t1), mkexpr(t3)));
11138 break;
11141 case 0x03: { /* SRAR.D */
11142 DIP("SRAR.D w%d, w%d, w%d", wd, ws, wt);
11143 t1 = newTemp(Ity_V128);
11144 t2 = newTemp(Ity_V128);
11145 t3 = newTemp(Ity_V128);
11146 t4 = newTemp(Ity_V128);
11147 assign(t1,
11148 binop(Iop_Sar64x2,
11149 getWReg(ws),
11150 getWReg(wt)));
11151 assign(t2,
11152 binop(Iop_Sub64x2,
11153 binop(Iop_64HLtoV128,
11154 mkU64(64ul), mkU64(64ul)),
11155 getWReg(wt)));
11156 assign(t4,
11157 unop(Iop_NotV128,
11158 binop(Iop_CmpEQ64x2,
11159 binop(Iop_ShlN64x2,
11160 getWReg(wt),
11161 mkU8(58)),
11162 binop(Iop_64HLtoV128,
11163 mkU64(0), mkU64(0)))));
11164 assign(t3,
11165 binop(Iop_ShrN64x2,
11166 binop(Iop_AndV128,
11167 binop(Iop_Shl64x2,
11168 getWReg(ws),
11169 mkexpr(t2)),
11170 mkexpr(t4)),
11171 mkU8(63)));
11172 putWReg(wd,
11173 binop(Iop_Add64x2,
11174 mkexpr(t1), mkexpr(t3)));
11175 break;
11178 default:
11179 return -1;
11182 break;
11185 case 0x02: { /* SRLR.df */
11186 switch (df) {
11187 case 0x00: { /* SRLR.B */
11188 DIP("SRLR.B w%d, w%d, w%d", wd, ws, wt);
11189 t1 = newTemp(Ity_V128);
11190 t2 = newTemp(Ity_V128);
11191 t3 = newTemp(Ity_V128);
11192 t4 = newTemp(Ity_V128);
11193 assign(t1,
11194 binop(Iop_Shr8x16,
11195 getWReg(ws),
11196 getWReg(wt)));
11197 assign(t2,
11198 binop(Iop_Sub8x16,
11199 binop(Iop_64HLtoV128,
11200 mkU64(0x808080808080808ull),
11201 mkU64(0x808080808080808ull)),
11202 getWReg(wt)));
11203 assign(t4,
11204 unop(Iop_NotV128,
11205 binop(Iop_CmpEQ8x16,
11206 binop(Iop_ShlN8x16,
11207 getWReg(wt),
11208 mkU8(5)),
11209 binop(Iop_64HLtoV128,
11210 mkU64(0), mkU64(0)))));
11211 assign(t3,
11212 binop(Iop_ShrN8x16,
11213 binop(Iop_AndV128,
11214 binop(Iop_Shl8x16,
11215 getWReg(ws),
11216 mkexpr(t2)),
11217 mkexpr(t4)),
11218 mkU8(7)));
11219 putWReg(wd,
11220 binop(Iop_Add8x16,
11221 mkexpr(t1), mkexpr(t3)));
11222 break;
11225 case 0x01: { /* SRLR.H */
11226 DIP("SRLR.H w%d, w%d, w%d", wd, ws, wt);
11227 t1 = newTemp(Ity_V128);
11228 t2 = newTemp(Ity_V128);
11229 t3 = newTemp(Ity_V128);
11230 t4 = newTemp(Ity_V128);
11231 assign(t1,
11232 binop(Iop_Shr16x8,
11233 getWReg(ws),
11234 getWReg(wt)));
11235 assign(t2,
11236 binop(Iop_Sub16x8,
11237 binop(Iop_64HLtoV128,
11238 mkU64(0x10001000100010ul),
11239 mkU64(0x10001000100010ul)),
11240 getWReg(wt)));
11241 assign(t4,
11242 unop(Iop_NotV128,
11243 binop(Iop_CmpEQ16x8,
11244 binop(Iop_ShlN16x8,
11245 getWReg(wt),
11246 mkU8(12)),
11247 binop(Iop_64HLtoV128,
11248 mkU64(0), mkU64(0)))));
11249 assign(t3,
11250 binop(Iop_ShrN16x8,
11251 binop(Iop_AndV128,
11252 binop(Iop_Shl16x8,
11253 getWReg(ws),
11254 mkexpr(t2)),
11255 mkexpr(t4)),
11256 mkU8(15)));
11257 putWReg(wd,
11258 binop(Iop_Add16x8,
11259 mkexpr(t1), mkexpr(t3)));
11260 break;
11263 case 0x02: { /* SRLR.W */
11264 DIP("SRLR.W w%d, w%d, w%d", wd, ws, wt);
11265 t1 = newTemp(Ity_V128);
11266 t2 = newTemp(Ity_V128);
11267 t3 = newTemp(Ity_V128);
11268 t4 = newTemp(Ity_V128);
11269 assign(t1,
11270 binop(Iop_Shr32x4,
11271 getWReg(ws),
11272 getWReg(wt)));
11273 assign(t2,
11274 binop(Iop_Sub32x4,
11275 binop(Iop_64HLtoV128,
11276 mkU64(0x2000000020ul),
11277 mkU64(0x2000000020ul)),
11278 getWReg(wt)));
11279 assign(t4,
11280 unop(Iop_NotV128,
11281 binop(Iop_CmpEQ32x4,
11282 binop(Iop_ShlN32x4,
11283 getWReg(wt),
11284 mkU8(27)),
11285 binop(Iop_64HLtoV128,
11286 mkU64(0), mkU64(0)))));
11287 assign(t3,
11288 binop(Iop_ShrN32x4,
11289 binop(Iop_AndV128,
11290 binop(Iop_Shl32x4,
11291 getWReg(ws),
11292 mkexpr(t2)),
11293 mkexpr(t4)),
11294 mkU8(31)));
11295 putWReg(wd,
11296 binop(Iop_Add32x4,
11297 mkexpr(t1), mkexpr(t3)));
11298 break;
11301 case 0x03: { /* SRLR.D */
11302 DIP("SRLR.D w%d, w%d, w%d", wd, ws, wt);
11303 t1 = newTemp(Ity_V128);
11304 t2 = newTemp(Ity_V128);
11305 t3 = newTemp(Ity_V128);
11306 t4 = newTemp(Ity_V128);
11307 assign(t1,
11308 binop(Iop_Shr64x2,
11309 getWReg(ws),
11310 getWReg(wt)));
11311 assign(t2,
11312 binop(Iop_Sub64x2,
11313 binop(Iop_64HLtoV128,
11314 mkU64(64ul), mkU64(64ul)),
11315 getWReg(wt)));
11316 assign(t4,
11317 unop(Iop_NotV128,
11318 binop(Iop_CmpEQ64x2,
11319 binop(Iop_ShlN64x2,
11320 getWReg(wt),
11321 mkU8(58)),
11322 binop(Iop_64HLtoV128,
11323 mkU64(0), mkU64(0)))));
11324 assign(t3,
11325 binop(Iop_ShrN64x2,
11326 binop(Iop_AndV128,
11327 binop(Iop_Shl64x2,
11328 getWReg(ws),
11329 mkexpr(t2)),
11330 mkexpr(t4)),
11331 mkU8(63)));
11332 putWReg(wd,
11333 binop(Iop_Add64x2,
11334 mkexpr(t1), mkexpr(t3)));
11335 break;
11338 default:
11339 return -1;
11342 break;
11345 case 0x04: { /* HADD_S.df */
11346 switch (df) {
11347 case 0x01: { /* HADD_S.H */
11348 DIP("HADD_S.H w%d, w%d, w%d", wd, ws, wt);
11349 t1 = newTemp(Ity_V128);
11350 t2 = newTemp(Ity_V128);
11351 t3 = newTemp(Ity_V128);
11352 assign(t1, getWReg(ws));
11353 assign(t2, getWReg(wt));
11354 assign(t3,
11355 binop(Iop_Add16x8,
11356 binop(Iop_SarN16x8,
11357 mkexpr(t1), mkU8(8)),
11358 binop(Iop_SarN16x8,
11359 binop(Iop_ShlN16x8,
11360 mkexpr(t2), mkU8(8)),
11361 mkU8(8))));
11362 putWReg(wd, mkexpr(t3));
11363 break;
11366 case 0x02: { /* HADD_S.W */
11367 DIP("HADD_S.W w%d, w%d, w%d", wd, ws, wt);
11368 t1 = newTemp(Ity_V128);
11369 t2 = newTemp(Ity_V128);
11370 t3 = newTemp(Ity_V128);
11371 assign(t1, getWReg(ws));
11372 assign(t2, getWReg(wt));
11373 assign(t3,
11374 binop(Iop_Add32x4,
11375 binop(Iop_SarN32x4,
11376 mkexpr(t1), mkU8(16)),
11377 binop(Iop_SarN32x4,
11378 binop(Iop_ShlN32x4,
11379 mkexpr(t2), mkU8(16)),
11380 mkU8(16))));
11381 putWReg(wd, mkexpr(t3));
11382 break;
11385 case 0x03: { /* HADD_S.D */
11386 DIP("HADD_S.D w%d, w%d, w%d", wd, ws, wt);
11387 t1 = newTemp(Ity_V128);
11388 t2 = newTemp(Ity_V128);
11389 t3 = newTemp(Ity_V128);
11390 assign(t1, getWReg(ws));
11391 assign(t2, getWReg(wt));
11392 assign(t3,
11393 binop(Iop_Add64x2,
11394 binop(Iop_SarN64x2,
11395 mkexpr(t1), mkU8(32)),
11396 binop(Iop_SarN64x2,
11397 binop(Iop_ShlN64x2,
11398 mkexpr(t2), mkU8(32)),
11399 mkU8(32))));
11400 putWReg(wd, mkexpr(t3));
11401 break;
11404 default:
11405 return -1;
11408 break;
11411 case 0x05: { /* HADD_U.df */
11412 switch (df) {
11413 case 0x01: { /* HADD_U.H */
11414 DIP("HADD_U.H w%d, w%d, w%d", wd, ws, wt);
11415 t1 = newTemp(Ity_V128);
11416 t2 = newTemp(Ity_V128);
11417 t3 = newTemp(Ity_V128);
11418 assign(t1, getWReg(ws));
11419 assign(t2, getWReg(wt));
11420 assign(t3,
11421 binop(Iop_Add16x8,
11422 binop(Iop_ShrN16x8,
11423 mkexpr(t1), mkU8(8)),
11424 binop(Iop_ShrN16x8,
11425 binop(Iop_ShlN16x8,
11426 mkexpr(t2), mkU8(8)),
11427 mkU8(8))));
11428 putWReg(wd, mkexpr(t3));
11429 break;
11432 case 0x02: { /* HADD_U.W */
11433 DIP("HADD_U.W w%d, w%d, w%d", wd, ws, wt);
11434 t1 = newTemp(Ity_V128);
11435 t2 = newTemp(Ity_V128);
11436 t3 = newTemp(Ity_V128);
11437 assign(t1, getWReg(ws));
11438 assign(t2, getWReg(wt));
11439 assign(t3,
11440 binop(Iop_Add32x4,
11441 binop(Iop_ShrN32x4,
11442 mkexpr(t1), mkU8(16)),
11443 binop(Iop_ShrN32x4,
11444 binop(Iop_ShlN32x4,
11445 mkexpr(t2), mkU8(16)),
11446 mkU8(16))));
11447 putWReg(wd, mkexpr(t3));
11448 break;
11451 case 0x03: { /* HADD_U.D */
11452 DIP("HADD_U.D w%d, w%d, w%d", wd, ws, wt);
11453 t1 = newTemp(Ity_V128);
11454 t2 = newTemp(Ity_V128);
11455 t3 = newTemp(Ity_V128);
11456 assign(t1, getWReg(ws));
11457 assign(t2, getWReg(wt));
11458 assign(t3,
11459 binop(Iop_Add64x2,
11460 binop(Iop_ShrN64x2,
11461 mkexpr(t1), mkU8(32)),
11462 binop(Iop_ShrN64x2,
11463 binop(Iop_ShlN64x2,
11464 mkexpr(t2), mkU8(32)),
11465 mkU8(32))));
11466 putWReg(wd, mkexpr(t3));
11467 break;
11470 default:
11471 return -1;
11474 break;
11477 case 0x06: { /* HSUB_S.df */
11478 switch (df) {
11479 case 0x01: { /* HSUB_S.H */
11480 DIP("HSUB_S.H w%d, w%d, w%d", wd, ws, wt);
11481 t1 = newTemp(Ity_V128);
11482 t2 = newTemp(Ity_V128);
11483 t3 = newTemp(Ity_V128);
11484 assign(t1, getWReg(ws));
11485 assign(t2, getWReg(wt));
11486 assign(t3,
11487 binop(Iop_Sub16x8,
11488 binop(Iop_SarN16x8,
11489 mkexpr(t1), mkU8(8)),
11490 binop(Iop_SarN16x8,
11491 binop(Iop_ShlN16x8,
11492 mkexpr(t2), mkU8(8)),
11493 mkU8(8))));
11494 putWReg(wd, mkexpr(t3));
11495 break;
11498 case 0x02: { /* HSUB_S.W */
11499 DIP("HSUB_S.W w%d, w%d, w%d", wd, ws, wt);
11500 t1 = newTemp(Ity_V128);
11501 t2 = newTemp(Ity_V128);
11502 t3 = newTemp(Ity_V128);
11503 assign(t1, getWReg(ws));
11504 assign(t2, getWReg(wt));
11505 assign(t3,
11506 binop(Iop_Sub32x4,
11507 binop(Iop_SarN32x4,
11508 mkexpr(t1), mkU8(16)),
11509 binop(Iop_SarN32x4,
11510 binop(Iop_ShlN32x4,
11511 mkexpr(t2), mkU8(16)),
11512 mkU8(16))));
11513 putWReg(wd, mkexpr(t3));
11514 break;
11517 case 0x03: { /* HSUB_S.D */
11518 DIP("HSUB_S.D w%d, w%d, w%d", wd, ws, wt);
11519 t1 = newTemp(Ity_V128);
11520 t2 = newTemp(Ity_V128);
11521 t3 = newTemp(Ity_V128);
11522 assign(t1, getWReg(ws));
11523 assign(t2, getWReg(wt));
11524 assign(t3,
11525 binop(Iop_Sub64x2,
11526 binop(Iop_SarN64x2,
11527 mkexpr(t1), mkU8(32)),
11528 binop(Iop_SarN64x2,
11529 binop(Iop_ShlN64x2,
11530 mkexpr(t2), mkU8(32)),
11531 mkU8(32))));
11532 putWReg(wd, mkexpr(t3));
11533 break;
11536 default:
11537 return -1;
11540 break;
11543 case 0x07: { /* HSUB_U.df */
11544 switch (df) {
11545 case 0x01: { /* HSUB_U.H */
11546 DIP("HSUB_U.H w%d, w%d, w%d", wd, ws, wt);
11547 t1 = newTemp(Ity_V128);
11548 t2 = newTemp(Ity_V128);
11549 t3 = newTemp(Ity_V128);
11550 assign(t1, getWReg(ws));
11551 assign(t2, getWReg(wt));
11552 assign(t3,
11553 binop(Iop_Sub16x8,
11554 binop(Iop_ShrN16x8,
11555 mkexpr(t1), mkU8(8)),
11556 binop(Iop_ShrN16x8,
11557 binop(Iop_ShlN16x8,
11558 mkexpr(t2), mkU8(8)),
11559 mkU8(8))));
11560 putWReg(wd, mkexpr(t3));
11561 break;
11564 case 0x02: { /* HSUB_U.W */
11565 DIP("HSUB_U.W w%d, w%d, w%d", wd, ws, wt);
11566 t1 = newTemp(Ity_V128);
11567 t2 = newTemp(Ity_V128);
11568 t3 = newTemp(Ity_V128);
11569 assign(t1, getWReg(ws));
11570 assign(t2, getWReg(wt));
11571 assign(t3,
11572 binop(Iop_Sub32x4,
11573 binop(Iop_ShrN32x4,
11574 mkexpr(t1), mkU8(16)),
11575 binop(Iop_ShrN32x4,
11576 binop(Iop_ShlN32x4,
11577 mkexpr(t2), mkU8(16)),
11578 mkU8(16))));
11579 putWReg(wd, mkexpr(t3));
11580 break;
11583 case 0x03: { /* HSUB_U.D */
11584 DIP("HSUB_U.D w%d, w%d, w%d", wd, ws, wt);
11585 t1 = newTemp(Ity_V128);
11586 t2 = newTemp(Ity_V128);
11587 t3 = newTemp(Ity_V128);
11588 assign(t1, getWReg(ws));
11589 assign(t2, getWReg(wt));
11590 assign(t3,
11591 binop(Iop_Sub64x2,
11592 binop(Iop_ShrN64x2,
11593 mkexpr(t1), mkU8(32)),
11594 binop(Iop_ShrN64x2,
11595 binop(Iop_ShlN64x2,
11596 mkexpr(t2), mkU8(32)),
11597 mkU8(32))));
11598 putWReg(wd, mkexpr(t3));
11599 break;
11602 default:
11603 return -1;
11606 break;
11609 default:
11610 return -1;
11613 return 0;
11616 static Int msa_3R_1A(UInt cins, UChar wd, UChar ws) /* 3R (0x1A) */
11618 UShort operation;
11619 UChar df, wt;
11621 operation = (cins & 0x03C00000) >> 22;
11622 df = (cins & 0x00200000) >> 21;
11623 wt = (cins & 0x001F0000) >> 16;
11625 switch (operation) {
11626 case 0x00: { /* FCAF.df */
11627 switch (df) {
11628 case 0x00: { /* FCAF.W */
11629 DIP("FCAF.W w%d, w%d, w%d", wd, ws, wt);
11630 calculateMSACSR(ws, wt, FCAFW, 2);
11631 putWReg(wd, binop(Iop_64HLtoV128, mkU64(0ul), mkU64(0ul)));
11632 break;
11635 case 0x01: { /* FCAF.D */
11636 DIP("FCAF.D w%d, w%d, w%d", wd, ws, wt);
11637 calculateMSACSR(ws, wt, FCAFD, 2);
11638 putWReg(wd, binop(Iop_64HLtoV128, mkU64(0ul), mkU64(0ul)));
11639 break;
11642 default:
11643 return -1;
11646 break;
11649 case 0x01: { /* FCUN.df */
11650 switch (df) {
11651 case 0x00: { /* FCUN.W */
11652 DIP("FCUN.W w%d, w%d, w%d", wd, ws, wt);
11653 calculateMSACSR(ws, wt, FCUNW, 2);
11654 putWReg(wd, binop(Iop_CmpUN32Fx4,
11655 getWReg(ws),
11656 getWReg(wt)));
11657 break;
11660 case 0x01: { /* FCUN.D */
11661 DIP("FCUN.D w%d, w%d, w%d", wd, ws, wt);
11662 calculateMSACSR(ws, wt, FCUND, 2);
11663 putWReg(wd, binop(Iop_CmpUN64Fx2,
11664 getWReg(ws),
11665 getWReg(wt)));
11666 break;
11669 default:
11670 return -1;
11673 break;
11676 case 0x02: { /* FCEQ.df */
11677 switch (df) {
11678 case 0x00: { /* FCEQ.W */
11679 DIP("FCEQ.W w%d, w%d, w%d", wd, ws, wt);
11680 calculateMSACSR(ws, wt, FCEQW, 2);
11681 putWReg(wd, binop(Iop_CmpEQ32Fx4,
11682 getWReg(ws),
11683 getWReg(wt)));
11684 break;
11687 case 0x01: { /* FCEQ.D */
11688 DIP("FCEQ.D w%d, w%d, w%d", wd, ws, wt);
11689 calculateMSACSR(ws, wt, FCEQD, 2);
11690 putWReg(wd, binop(Iop_CmpEQ64Fx2,
11691 getWReg(ws),
11692 getWReg(wt)));
11693 break;
11696 default:
11697 return -1;
11700 break;
11703 case 0x03: { /* FCUEQ.df */
11704 switch (df) {
11705 case 0x00: { /* FCUEQ.W */
11706 DIP("FCUEQ.W w%d, w%d, w%d", wd, ws, wt);
11707 calculateMSACSR(ws, wt, FCUEQW, 2);
11708 putWReg(wd,
11709 binop(Iop_OrV128,
11710 binop(Iop_CmpEQ32Fx4,
11711 getWReg(ws),
11712 getWReg(wt)),
11713 binop(Iop_CmpUN32Fx4,
11714 getWReg(ws),
11715 getWReg(wt))));
11716 break;
11719 case 0x01: { /* FCUEQ.D */
11720 DIP("FCUEQ.D w%d, w%d, w%d", wd, ws, wt);
11721 calculateMSACSR(ws, wt, FCUEQD, 2);
11722 putWReg(wd,
11723 binop(Iop_OrV128,
11724 binop(Iop_CmpEQ64Fx2,
11725 getWReg(ws),
11726 getWReg(wt)),
11727 binop(Iop_CmpUN64Fx2,
11728 getWReg(ws),
11729 getWReg(wt))));
11730 break;
11733 default:
11734 return -1;
11737 break;
11740 case 0x04: { /* FCLT.df */
11741 switch (df) {
11742 case 0x00: { /* FCLT.W */
11743 DIP("FCLT.W w%d, w%d, w%d", wd, ws, wt);
11744 calculateMSACSR(ws, wt, FCLTW, 2);
11745 putWReg(wd,
11746 binop(Iop_CmpLT32Fx4,
11747 getWReg(ws),
11748 getWReg(wt)));
11749 break;
11752 case 0x01: { /* FCLT.D */
11753 DIP("FCLT.D w%d, w%d, w%d", wd, ws, wt);
11754 calculateMSACSR(ws, wt, FCLTD, 2);
11755 putWReg(wd,
11756 binop(Iop_CmpLT64Fx2,
11757 getWReg(ws),
11758 getWReg(wt)));
11759 break;
11762 default:
11763 return -1;
11766 break;
11769 case 0x05: { /* FCULT.df */
11770 switch (df) {
11771 case 0x00: { /* FCULT.W */
11772 DIP("FCULT.W w%d, w%d, w%d", wd, ws, wt);
11773 calculateMSACSR(ws, wt, FCULTW, 2);
11774 putWReg(wd,
11775 binop(Iop_OrV128,
11776 binop(Iop_CmpLT32Fx4,
11777 getWReg(ws),
11778 getWReg(wt)),
11779 binop(Iop_CmpUN32Fx4,
11780 getWReg(ws),
11781 getWReg(wt))));
11782 break;
11785 case 0x01: { /* FCULT.D */
11786 DIP("FCULT.D w%d, w%d, w%d", wd, ws, wt);
11787 calculateMSACSR(ws, wt, FCULTD, 2);
11788 putWReg(wd,
11789 binop(Iop_OrV128,
11790 binop(Iop_CmpLT64Fx2,
11791 getWReg(ws),
11792 getWReg(wt)),
11793 binop(Iop_CmpUN64Fx2,
11794 getWReg(ws),
11795 getWReg(wt))));
11796 break;
11799 default:
11800 return -1;
11803 break;
11806 case 0x06: { /* FCLE.df */
11807 switch (df) {
11808 case 0x00: { /* FCLE.W */
11809 DIP("FCLE.W w%d, w%d, w%d", wd, ws, wt);
11810 calculateMSACSR(ws, wt, FCLEW, 2);
11811 putWReg(wd,
11812 binop(Iop_CmpLE32Fx4,
11813 getWReg(ws),
11814 getWReg(wt)));
11815 break;
11818 case 0x01: { /* FCLE.D */
11819 DIP("FCLE.D w%d, w%d, w%d", wd, ws, wt);
11820 calculateMSACSR(ws, wt, FCLED, 2);
11821 putWReg(wd,
11822 binop(Iop_CmpLE64Fx2,
11823 getWReg(ws),
11824 getWReg(wt)));
11825 break;
11828 default:
11829 return -1;
11832 break;
11835 case 0x07: { /* FCULE.df */
11836 switch (df) {
11837 case 0x00: { /* FCULE.W */
11838 DIP("FCULE.W w%d, w%d, w%d", wd, ws, wt);
11839 calculateMSACSR(ws, wt, FCULEW, 2);
11840 putWReg(wd,
11841 binop(Iop_OrV128,
11842 binop(Iop_CmpLE32Fx4,
11843 getWReg(ws),
11844 getWReg(wt)),
11845 binop(Iop_CmpUN32Fx4,
11846 getWReg(ws),
11847 getWReg(wt))));
11848 break;
11851 case 0x01: { /* FCULE.D */
11852 DIP("FCULE.D w%d, w%d, w%d", wd, ws, wt);
11853 calculateMSACSR(ws, wt, FCULED, 2);
11854 putWReg(wd,
11855 binop(Iop_OrV128,
11856 binop(Iop_CmpLE64Fx2,
11857 getWReg(ws),
11858 getWReg(wt)),
11859 binop(Iop_CmpUN64Fx2,
11860 getWReg(ws),
11861 getWReg(wt))));
11862 break;
11865 default:
11866 return -1;
11869 break;
11872 case 0x08: { /* FSAF.df */
11873 switch (df) {
11874 case 0x00: { /* FSAF.W */
11875 DIP("FSAF.W w%d, w%d, w%d", wd, ws, wt);
11876 calculateMSACSR(ws, wt, FSAFW, 2);
11877 putWReg(wd,
11878 binop(Iop_64HLtoV128,
11879 mkU64(0ul), mkU64(0ul)));
11880 break;
11883 case 0x01: { /* FSAF.D */
11884 DIP("FSAF.D w%d, w%d, w%d", wd, ws, wt);
11885 calculateMSACSR(ws, wt, FSAFD, 2);
11886 putWReg(wd,
11887 binop(Iop_64HLtoV128,
11888 mkU64(0ul), mkU64(0ul)));
11889 break;
11892 default:
11893 return -1;
11896 break;
11899 case 0x09: { /* FSUN.df */
11900 switch (df) {
11901 case 0x00: { /* FSUN.W */
11902 DIP("FSUN.W w%d, w%d, w%d", wd, ws, wt);
11903 calculateMSACSR(ws, wt, FSUNW, 2);
11904 putWReg(wd,
11905 binop(Iop_CmpUN32Fx4,
11906 getWReg(ws),
11907 getWReg(wt)));
11908 break;
11911 case 0x01: { /* FSUN.D */
11912 DIP("FSUN.D w%d, w%d, w%d", wd, ws, wt);
11913 calculateMSACSR(ws, wt, FSUND, 2);
11914 putWReg(wd,
11915 binop(Iop_CmpUN64Fx2,
11916 getWReg(ws),
11917 getWReg(wt)));
11918 break;
11921 default:
11922 return -1;
11925 break;
11928 case 0x0A: { /* FSEQ.df */
11929 switch (df) {
11930 case 0x00: { /* FSEQ.W */
11931 DIP("FSEQ.W w%d, w%d, w%d", wd, ws, wt);
11932 calculateMSACSR(ws, wt, FSEQW, 2);
11933 putWReg(wd,
11934 binop(Iop_CmpEQ32Fx4,
11935 getWReg(ws),
11936 getWReg(wt)));
11937 break;
11940 case 0x01: { /* FSEQ.D */
11941 DIP("FSEQ.D w%d, w%d, w%d", wd, ws, wt);
11942 calculateMSACSR(ws, wt, FSEQD, 2);
11943 putWReg(wd,
11944 binop(Iop_CmpEQ64Fx2,
11945 getWReg(ws),
11946 getWReg(wt)));
11947 break;
11950 default:
11951 return -1;
11954 break;
11957 case 0x0B: { /* FSUEQ.df */
11958 switch (df) {
11959 case 0x00: { /* FSUEQ.W */
11960 DIP("FSUEQ.W w%d, w%d, w%d", wd, ws, wt);
11961 calculateMSACSR(ws, wt, FSUEQW, 2);
11962 putWReg(wd,
11963 binop(Iop_OrV128,
11964 binop(Iop_CmpEQ32Fx4,
11965 getWReg(ws),
11966 getWReg(wt)),
11967 binop(Iop_CmpUN32Fx4,
11968 getWReg(ws),
11969 getWReg(wt))));
11970 break;
11973 case 0x01: { /* FSUEQ.D */
11974 DIP("FSUEQ.D w%d, w%d, w%d", wd, ws, wt);
11975 calculateMSACSR(ws, wt, FSUEQD, 2);
11976 putWReg(wd,
11977 binop(Iop_OrV128,
11978 binop(Iop_CmpEQ64Fx2,
11979 getWReg(ws),
11980 getWReg(wt)),
11981 binop(Iop_CmpUN64Fx2,
11982 getWReg(ws),
11983 getWReg(wt))));
11984 break;
11987 default:
11988 return -1;
11991 break;
11994 case 0x0C: { /* FSLT.df */
11995 switch (df) {
11996 case 0x00: { /* FSLT.W */
11997 DIP("FSLT.W w%d, w%d, w%d", wd, ws, wt);
11998 calculateMSACSR(ws, wt, FSLTW, 2);
11999 putWReg(wd,
12000 binop(Iop_CmpLT32Fx4,
12001 getWReg(ws),
12002 getWReg(wt)));
12003 break;
12006 case 0x01: { /* FSLT.D */
12007 DIP("FSLT.D w%d, w%d, w%d", wd, ws, wt);
12008 calculateMSACSR(ws, wt, FSLTD, 2);
12009 putWReg(wd,
12010 binop(Iop_CmpLT64Fx2,
12011 getWReg(ws),
12012 getWReg(wt)));
12013 break;
12016 default:
12017 return -1;
12020 break;
12023 case 0x0D: { /* FSULT.df */
12024 switch (df) {
12025 case 0x00: { /* FSULT.W */
12026 DIP("FSULT.W w%d, w%d, w%d", wd, ws, wt);
12027 calculateMSACSR(ws, wt, FSULTW, 2);
12028 putWReg(wd,
12029 binop(Iop_OrV128,
12030 binop(Iop_CmpLT32Fx4,
12031 getWReg(ws),
12032 getWReg(wt)),
12033 binop(Iop_CmpUN32Fx4,
12034 getWReg(ws),
12035 getWReg(wt))));
12036 break;
12039 case 0x01: { /* FSULT.D */
12040 DIP("FSULT.D w%d, w%d, w%d", wd, ws, wt);
12041 calculateMSACSR(ws, wt, FSULTD, 2);
12042 putWReg(wd,
12043 binop(Iop_OrV128,
12044 binop(Iop_CmpLT64Fx2,
12045 getWReg(ws),
12046 getWReg(wt)),
12047 binop(Iop_CmpUN64Fx2,
12048 getWReg(ws),
12049 getWReg(wt))));
12050 break;
12053 default:
12054 return -1;
12057 break;
12060 case 0x0E: { /* FSLE.df */
12061 switch (df) {
12062 case 0x00: { /* FSLE.W */
12063 DIP("FSLE.W w%d, w%d, w%d", wd, ws, wt);
12064 calculateMSACSR(ws, wt, FSLEW, 2);
12065 putWReg(wd,
12066 binop(Iop_CmpLE32Fx4,
12067 getWReg(ws),
12068 getWReg(wt)));
12069 break;
12072 case 0x01: { /* FSLE.D */
12073 DIP("FSLE.D w%d, w%d, w%d", wd, ws, wt);
12074 calculateMSACSR(ws, wt, FSLED, 2);
12075 putWReg(wd,
12076 binop(Iop_CmpLE64Fx2,
12077 getWReg(ws),
12078 getWReg(wt)));
12079 break;
12082 default:
12083 return -1;
12086 break;
12089 case 0x0F: { /* FSULE.df */
12090 switch (df) {
12091 case 0x00: { /* FSULE.W */
12092 DIP("FSULE.W w%d, w%d, w%d", wd, ws, wt);
12093 calculateMSACSR(ws, wt, FSULEW, 2);
12094 putWReg(wd,
12095 binop(Iop_OrV128,
12096 binop(Iop_CmpLE32Fx4,
12097 getWReg(ws),
12098 getWReg(wt)),
12099 binop(Iop_CmpUN32Fx4,
12100 getWReg(ws),
12101 getWReg(wt))));
12102 break;
12105 case 0x01: { /* FSULE.D */
12106 DIP("FSULE.D w%d, w%d, w%d", wd, ws, wt);
12107 calculateMSACSR(ws, wt, FSULED, 2);
12108 putWReg(wd,
12109 binop(Iop_OrV128,
12110 binop(Iop_CmpLE64Fx2,
12111 getWReg(ws),
12112 getWReg(wt)),
12113 binop(Iop_CmpUN64Fx2,
12114 getWReg(ws),
12115 getWReg(wt))));
12116 break;
12119 default:
12120 return -1;
12123 break;
12126 default:
12127 return -1;
12130 return 0;
12133 static Int msa_3R_1B(UInt cins, UChar wd, UChar ws) /* 3R (0x1B) */
12135 IRTemp t1, t2, t3, t4;
12136 UShort operation;
12137 UChar df, wt;
12139 operation = (cins & 0x03C00000) >> 22;
12140 df = (cins & 0x00200000) >> 21;
12141 wt = (cins & 0x001F0000) >> 16;
12143 switch (operation) {
12144 case 0x00: { /* FADD.df */
12145 switch (df) {
12146 case 0x00: { /* FADD.W */
12147 DIP("FADD.W w%d, w%d, w%d", wd, ws, wt);
12148 calculateMSACSR(ws, wt, FADDW, 2);
12149 IRExpr *rm = get_IR_roundingmode_MSA();
12150 putWReg(wd,
12151 triop(Iop_Add32Fx4, rm,
12152 getWReg(ws),
12153 getWReg(wt)));
12154 break;
12157 case 0x01: { /* FADD.D */
12158 DIP("FADD.D w%d, w%d, w%d", wd, ws, wt);
12159 calculateMSACSR(ws, wt, FADDD, 2);
12160 IRExpr *rm = get_IR_roundingmode_MSA();
12161 putWReg(wd,
12162 triop(Iop_Add64Fx2, rm,
12163 getWReg(ws),
12164 getWReg(wt)));
12165 break;
12168 default:
12169 return -1;
12172 break;
12175 case 0x01: { /* FSUB.df */
12176 switch (df) {
12177 case 0x00: { /* FSUB.W */
12178 DIP("FSUB.W w%d, w%d, w%d", wd, ws, wt);
12179 calculateMSACSR(ws, wt, FSUBW, 2);
12180 IRExpr *rm = get_IR_roundingmode_MSA();
12181 putWReg(wd,
12182 triop(Iop_Sub32Fx4, rm,
12183 getWReg(ws),
12184 getWReg(wt)));
12185 break;
12188 case 0x01: { /* FSUB.D */
12189 DIP("FSUB.D w%d, w%d, w%d", wd, ws, wt);
12190 calculateMSACSR(ws, wt, FSUBD, 2);
12191 IRExpr *rm = get_IR_roundingmode_MSA();
12192 putWReg(wd,
12193 triop(Iop_Sub64Fx2, rm,
12194 getWReg(ws),
12195 getWReg(wt)));
12196 break;
12199 default:
12200 return -1;
12203 break;
12206 case 0x02: { /* FMUL.df */
12207 switch (df) {
12208 case 0x00: { /* FMUL.W */
12209 DIP("FMUL.W w%d, w%d, w%d", wd, ws, wt);
12210 calculateMSACSR(ws, wt, FMULW, 2);
12211 IRExpr *rm = get_IR_roundingmode_MSA();
12212 putWReg(wd,
12213 triop(Iop_Mul32Fx4, rm,
12214 getWReg(ws),
12215 getWReg(wt)));
12216 break;
12219 case 0x01: { /* FMUL.D */
12220 DIP("FMUL.D w%d, w%d, w%d", wd, ws, wt);
12221 calculateMSACSR(ws, wt, FMULW, 2);
12222 IRExpr *rm = get_IR_roundingmode_MSA();
12223 putWReg(wd,
12224 triop(Iop_Mul64Fx2, rm,
12225 getWReg(ws),
12226 getWReg(wt)));
12227 break;
12230 default:
12231 return -1;
12234 break;
12237 case 0x03: { /* FDIV.df */
12238 switch (df) {
12239 case 0x00: { /* FDIV.W */
12240 DIP("FDIV.W w%d, w%d, w%d", wd, ws, wt);
12241 calculateMSACSR(ws, wt, FDIVW, 2);
12242 IRExpr *rm = get_IR_roundingmode_MSA();
12243 putWReg(wd,
12244 triop(Iop_Div32Fx4, rm,
12245 getWReg(ws),
12246 getWReg(wt)));
12247 break;
12250 case 0x01: { /* FDIV.D */
12251 DIP("FDIV.D w%d, w%d, w%d", wd, ws, wt);
12252 calculateMSACSR(ws, wt, FDIVD, 2);
12253 IRExpr *rm = get_IR_roundingmode_MSA();
12254 putWReg(wd,
12255 triop(Iop_Div64Fx2, rm,
12256 getWReg(ws),
12257 getWReg(wt)));
12258 break;
12261 default:
12262 return -1;
12265 break;
12268 case 0x04: { /* FMADD.df */
12269 switch (df) {
12270 case 0x00: { /* FMADD.W */
12271 DIP("FMADD.W w%d, w%d, w%d", wd, ws, wt);
12272 calculateMSACSR(ws, wt, FMADDW, 2);
12273 IRExpr *rm = get_IR_roundingmode_MSA();
12274 IRTemp tmp[4];
12275 Int i;
12277 for (i = 0; i < 4; i++) {
12278 tmp[i] = newTemp(Ity_F32);
12279 assign(tmp[i],
12280 qop(Iop_MAddF32, rm,
12281 unop(Iop_ReinterpI32asF32,
12282 binop(Iop_GetElem32x4,
12283 getWReg(ws),
12284 mkU8(i))),
12285 unop(Iop_ReinterpI32asF32,
12286 binop(Iop_GetElem32x4,
12287 getWReg(wt),
12288 mkU8(i))),
12289 unop(Iop_ReinterpI32asF32,
12290 binop(Iop_GetElem32x4,
12291 getWReg(wd),
12292 mkU8(i)))));
12295 putWReg(wd,
12296 binop(Iop_64HLtoV128,
12297 binop(Iop_32HLto64,
12298 unop(Iop_ReinterpF32asI32,
12299 mkexpr(tmp[3])),
12300 unop(Iop_ReinterpF32asI32,
12301 mkexpr(tmp[2]))),
12302 binop(Iop_32HLto64,
12303 unop(Iop_ReinterpF32asI32,
12304 mkexpr(tmp[1])),
12305 unop(Iop_ReinterpF32asI32,
12306 mkexpr(tmp[0])))));
12307 break;
12310 case 0x01: { /* FMADD.D */
12311 DIP("FMADD.D w%d, w%d, w%d", wd, ws, wt);
12312 calculateMSACSR(ws, wt, FMADDW, 2);
12313 IRExpr *rm = get_IR_roundingmode_MSA();
12314 IRTemp tmp[2];
12315 Int i;
12317 for (i = 0; i < 2; i++) {
12318 tmp[i] = newTemp(Ity_F64);
12319 assign(tmp[i],
12320 qop(Iop_MAddF64, rm,
12321 unop(Iop_ReinterpI64asF64,
12322 binop(Iop_GetElem64x2,
12323 getWReg(ws),
12324 mkU8(i))),
12325 unop(Iop_ReinterpI64asF64,
12326 binop(Iop_GetElem64x2,
12327 getWReg(wt),
12328 mkU8(i))),
12329 unop(Iop_ReinterpI64asF64,
12330 binop(Iop_GetElem64x2,
12331 getWReg(wd),
12332 mkU8(i)))));
12335 putWReg(wd,
12336 binop(Iop_64HLtoV128,
12337 unop(Iop_ReinterpF64asI64,
12338 mkexpr(tmp[1])),
12339 unop(Iop_ReinterpF64asI64,
12340 mkexpr(tmp[0]))));
12341 break;
12344 default:
12345 return -1;
12348 break;
12351 case 0x05: { /* FMSUB.df */
12352 switch (df) {
12353 case 0x00: { /* FMSUB.W */
12354 DIP("FMSUB.W w%d, w%d, w%d", wd, ws, wt);
12355 calculateMSACSR(ws, wt, FMADDW, 2);
12356 IRExpr *rm = get_IR_roundingmode_MSA();
12357 IRTemp tmp[4];
12358 Int i;
12360 for (i = 0; i < 4; i++) {
12361 tmp[i] = newTemp(Ity_F32);
12362 assign(tmp[i],
12363 qop(Iop_MSubF32, rm,
12364 unop(Iop_ReinterpI32asF32,
12365 binop(Iop_GetElem32x4,
12366 getWReg(ws),
12367 mkU8(i))),
12368 unop(Iop_ReinterpI32asF32,
12369 binop(Iop_GetElem32x4,
12370 getWReg(wt),
12371 mkU8(i))),
12372 unop(Iop_ReinterpI32asF32,
12373 binop(Iop_GetElem32x4,
12374 getWReg(wd),
12375 mkU8(i)))));
12378 putWReg(wd,
12379 binop(Iop_64HLtoV128,
12380 binop(Iop_32HLto64,
12381 unop(Iop_ReinterpF32asI32,
12382 mkexpr(tmp[3])),
12383 unop(Iop_ReinterpF32asI32,
12384 mkexpr(tmp[2]))),
12385 binop(Iop_32HLto64,
12386 unop(Iop_ReinterpF32asI32,
12387 mkexpr(tmp[1])),
12388 unop(Iop_ReinterpF32asI32,
12389 mkexpr(tmp[0])))));
12390 break;
12393 case 0x01: { /* FMSUB.D */
12394 DIP("FMSUB.D w%d, w%d, w%d", wd, ws, wt);
12395 calculateMSACSR(ws, wt, FMADDD, 2);
12396 IRExpr *rm = get_IR_roundingmode_MSA();
12397 IRTemp tmp[2];
12398 Int i;
12400 for (i = 0; i < 2; i++) {
12401 tmp[i] = newTemp(Ity_F64);
12402 assign(tmp[i],
12403 qop(Iop_MSubF64, rm,
12404 unop(Iop_ReinterpI64asF64,
12405 binop(Iop_GetElem64x2,
12406 getWReg(ws),
12407 mkU8(i))),
12408 unop(Iop_ReinterpI64asF64,
12409 binop(Iop_GetElem64x2,
12410 getWReg(wt),
12411 mkU8(i))),
12412 unop(Iop_ReinterpI64asF64,
12413 binop(Iop_GetElem64x2,
12414 getWReg(wd),
12415 mkU8(i)))));
12418 putWReg(wd,
12419 binop(Iop_64HLtoV128,
12420 unop(Iop_ReinterpF64asI64,
12421 mkexpr(tmp[1])),
12422 unop(Iop_ReinterpF64asI64,
12423 mkexpr(tmp[0]))));
12424 break;
12427 default:
12428 return -1;
12431 break;
12434 case 0x07: { /* FEXP2.df */
12435 switch (df) {
12436 case 0x00: { /* FEXP2.W */
12437 DIP("FEXP2.W w%d, w%d, w%d", wd, ws, wt);
12438 calculateMSACSR(ws, wt, FEXP2W, 2);
12439 IRExpr *rm = get_IR_roundingmode_MSA();
12440 putWReg(wd,
12441 triop(Iop_Scale2_32Fx4, rm,
12442 getWReg(ws),
12443 getWReg(wt)));
12444 break;
12447 case 0x01: { /* FEXP2.D */
12448 DIP("FEXP2.D w%d, w%d, w%d", wd, ws, wt);
12449 calculateMSACSR(ws, wt, FEXP2D, 2);
12450 IRExpr *rm = get_IR_roundingmode_MSA();
12451 putWReg(wd,
12452 triop(Iop_Scale2_64Fx2, rm,
12453 getWReg(ws),
12454 getWReg(wt)));
12455 break;
12458 default:
12459 return -1;
12462 break;
12465 case 0x08: { /* FEXDO.df */
12466 switch (df) {
12467 case 0x00: { /* FEXDO.H */
12468 DIP("FEXDO.H w%d, w%d, w%d", wd, ws, wt);
12469 calculateMSACSR(ws, wt, FEXDOH, 2);
12470 t1 = newTemp(Ity_I64);
12471 t2 = newTemp(Ity_I64);
12472 assign(t1,
12473 unop(Iop_F32toF16x4_DEP,
12474 getWReg(ws)));
12475 assign(t2,
12476 unop(Iop_F32toF16x4_DEP,
12477 getWReg(wt)));
12478 putWReg(wd,
12479 binop(Iop_64HLtoV128,
12480 mkexpr(t1), mkexpr(t2)));
12481 break;
12484 case 0x01: { /* FEXDO.W */
12485 DIP("FEXDO.W w%d, w%d, w%d", wd, ws, wt);
12486 calculateMSACSR(ws, wt, FEXDOW, 2);
12487 t1 = newTemp(Ity_I32);
12488 t2 = newTemp(Ity_I32);
12489 t3 = newTemp(Ity_I32);
12490 t4 = newTemp(Ity_I32);
12491 IRExpr *rm = get_IR_roundingmode_MSA();
12492 assign(t1,
12493 unop(Iop_ReinterpF32asI32,
12494 binop(Iop_F64toF32, rm,
12495 unop(Iop_ReinterpI64asF64,
12496 unop(Iop_V128to64,
12497 getWReg(ws))))));
12498 assign(t2,
12499 unop(Iop_ReinterpF32asI32,
12500 binop(Iop_F64toF32, rm,
12501 unop(Iop_ReinterpI64asF64,
12502 unop(Iop_V128HIto64,
12503 getWReg(ws))))));
12504 assign(t3,
12505 unop(Iop_ReinterpF32asI32,
12506 binop(Iop_F64toF32, rm,
12507 unop(Iop_ReinterpI64asF64,
12508 unop(Iop_V128to64,
12509 getWReg(wt))))));
12510 assign(t4,
12511 unop(Iop_ReinterpF32asI32,
12512 binop(Iop_F64toF32, rm,
12513 unop(Iop_ReinterpI64asF64,
12514 unop(Iop_V128HIto64,
12515 getWReg(wt))))));
12516 putWReg(wd,
12517 binop(Iop_64HLtoV128,
12518 binop(Iop_32HLto64,
12519 mkexpr(t2), mkexpr(t1)),
12520 binop(Iop_32HLto64,
12521 mkexpr(t4), mkexpr(t3))));
12522 break;
12525 default:
12526 return -1;
12529 break;
12532 case 0x0A: { /* FTQ.df */
12533 switch (df) {
12534 case 0x00: { /* FTQ.H */
12535 DIP("FTQ.H w%d, w%d, w%d", wd, ws, wt);
12536 calculateMSACSR(ws, wt, FTQH, 2);
12537 IRExpr *rm = get_IR_roundingmode_MSA();
12538 putWReg(wd,
12539 triop(Iop_F32x4_2toQ16x8, rm,
12540 getWReg(ws),
12541 getWReg(wt)));
12542 break;
12545 case 0x01: { /* FTQ.W */
12546 DIP("FTQ.W w%d, w%d, w%d", wd, ws, wt);
12547 calculateMSACSR(ws, wt, FTQW, 2);
12548 IRExpr *rm = get_IR_roundingmode_MSA();
12549 putWReg(wd,
12550 triop(Iop_F64x2_2toQ32x4, rm,
12551 getWReg(ws),
12552 getWReg(wt)));
12553 break;
12556 default:
12557 return -1;
12560 break;
12563 case 0x0C: { /* FMIN.df */
12564 switch (df) {
12565 case 0x00: { /* FMIN.W */
12566 DIP("FMIN.W w%d, w%d, w%d", wd, ws, wt);
12567 calculateMSACSR(ws, wt, FMINW, 2);
12568 putWReg(wd,
12569 binop(Iop_Min32Fx4,
12570 getWReg(ws),
12571 getWReg(wt)));
12572 break;
12575 case 0x01: { /* FMIN.D */
12576 DIP("FMIN.D w%d, w%d, w%d", wd, ws, wt);
12577 calculateMSACSR(ws, wt, FMINW, 2);
12578 putWReg(wd,
12579 binop(Iop_Min64Fx2,
12580 getWReg(ws),
12581 getWReg(wt)));
12582 break;
12585 default:
12586 return -1;
12589 break;
12592 case 0x0D: { /* FMIN_A.df */
12593 switch (df) {
12594 case 0x00: { /* FMIN_A.W */
12595 DIP("FMIN_A.W w%d, w%d, w%d", wd, ws, wt);
12596 calculateMSACSR(ws, wt, FMINAW, 2);
12597 t1 = newTemp(Ity_V128);
12598 t2 = newTemp(Ity_V128);
12599 t3 = newTemp(Ity_V128);
12600 t4 = newTemp(Ity_V128);
12601 assign(t1,
12602 binop(Iop_AndV128,
12603 getWReg(ws),
12604 binop(Iop_64HLtoV128,
12605 mkU64(0x7FFFFFFF7FFFFFFF),
12606 mkU64(0x7FFFFFFF7FFFFFFF))));
12607 assign(t2,
12608 binop(Iop_AndV128,
12609 getWReg(wt),
12610 binop(Iop_64HLtoV128,
12611 mkU64(0x7FFFFFFF7FFFFFFF),
12612 mkU64(0x7FFFFFFF7FFFFFFF))));
12613 assign(t3,
12614 binop(Iop_Min32Fx4,
12615 mkexpr(t2), mkexpr(t1)));
12616 assign(t4,
12617 binop(Iop_AndV128,
12618 binop(Iop_AndV128,
12619 unop(Iop_NotV128,
12620 binop(Iop_CmpUN32Fx4,
12621 mkexpr(t3),
12622 mkexpr(t3))),
12623 binop(Iop_OrV128,
12624 binop(Iop_AndV128,
12625 binop(Iop_CmpEQ32Fx4,
12626 mkexpr(t1),
12627 mkexpr(t2)),
12628 binop(Iop_OrV128,
12629 getWReg(ws),
12630 getWReg(wt))),
12631 binop(Iop_OrV128,
12632 binop(Iop_AndV128,
12633 binop(Iop_OrV128,
12634 binop(Iop_CmpUN32Fx4,
12635 mkexpr(t1),
12636 mkexpr(t1)),
12637 binop(Iop_CmpLT32Fx4,
12638 mkexpr(t3),
12639 mkexpr(t1))),
12640 getWReg(wt)),
12641 binop(Iop_AndV128,
12642 binop(Iop_OrV128,
12643 binop(Iop_CmpUN32Fx4,
12644 mkexpr(t2),
12645 mkexpr(t2)),
12646 binop(Iop_CmpLT32Fx4,
12647 mkexpr(t3),
12648 mkexpr(t2))),
12649 getWReg(ws))))),
12650 binop(Iop_64HLtoV128,
12651 mkU64(0x8000000080000000),
12652 mkU64(0x8000000080000000))));
12653 putWReg(wd,
12654 binop(Iop_OrV128,
12655 mkexpr(t3), mkexpr(t4)));
12656 break;
12659 case 0x01: { /* FMIN_A.D */
12660 DIP("FMIN_A.D w%d, w%d, w%d", wd, ws, wt);
12661 calculateMSACSR(ws, wt, FMINAD, 2);
12662 t1 = newTemp(Ity_V128);
12663 t2 = newTemp(Ity_V128);
12664 t3 = newTemp(Ity_V128);
12665 t4 = newTemp(Ity_V128);
12666 assign(t1,
12667 binop(Iop_AndV128,
12668 getWReg(ws),
12669 binop(Iop_64HLtoV128,
12670 mkU64(0x7FFFFFFFFFFFFFFF),
12671 mkU64(0x7FFFFFFFFFFFFFFF))));
12672 assign(t2,
12673 binop(Iop_AndV128,
12674 getWReg(wt),
12675 binop(Iop_64HLtoV128,
12676 mkU64(0x7FFFFFFFFFFFFFFF),
12677 mkU64(0x7FFFFFFFFFFFFFFF))));
12678 assign(t3,
12679 binop(Iop_Min64Fx2,
12680 mkexpr(t2), mkexpr(t1)));
12681 assign(t4,
12682 binop(Iop_AndV128,
12683 binop(Iop_AndV128,
12684 unop(Iop_NotV128,
12685 binop(Iop_CmpUN64Fx2,
12686 mkexpr(t3),
12687 mkexpr(t3))),
12688 binop(Iop_OrV128,
12689 binop(Iop_AndV128,
12690 binop(Iop_CmpEQ64Fx2,
12691 mkexpr(t1),
12692 mkexpr(t2)),
12693 binop(Iop_OrV128,
12694 getWReg(ws),
12695 getWReg(wt))),
12696 binop(Iop_OrV128,
12697 binop(Iop_AndV128,
12698 binop(Iop_OrV128,
12699 binop(Iop_CmpUN64Fx2,
12700 mkexpr(t1),
12701 mkexpr(t1)),
12702 binop(Iop_CmpLT64Fx2,
12703 mkexpr(t3),
12704 mkexpr(t1))),
12705 getWReg(wt)),
12706 binop(Iop_AndV128,
12707 binop(Iop_OrV128,
12708 binop(Iop_CmpUN64Fx2,
12709 mkexpr(t2),
12710 mkexpr(t2)),
12711 binop(Iop_CmpLT64Fx2,
12712 mkexpr(t3),
12713 mkexpr(t2))),
12714 getWReg(ws))))),
12715 binop(Iop_64HLtoV128,
12716 mkU64(0x8000000000000000),
12717 mkU64(0x8000000000000000))));
12718 putWReg(wd,
12719 binop(Iop_OrV128,
12720 mkexpr(t3), mkexpr(t4)));
12721 break;
12724 default:
12725 return -1;
12728 break;
12731 case 0x0E: { /* FMAX.df */
12732 switch (df) {
12733 case 0x00: { /* FMAX.W */
12734 DIP("FMAX.W w%d, w%d, w%d", wd, ws, wt);
12735 calculateMSACSR(ws, wt, FMAXW, 2);
12736 putWReg(wd,
12737 binop(Iop_Max32Fx4,
12738 getWReg(ws),
12739 getWReg(wt)));
12740 break;
12743 case 0x01: { /* FMAX.D */
12744 DIP("FMAX.D w%d, w%d, w%d", wd, ws, wt);
12745 calculateMSACSR(ws, wt, FMAXW, 2);
12746 putWReg(wd,
12747 binop(Iop_Max64Fx2,
12748 getWReg(ws),
12749 getWReg(wt)));
12750 break;
12753 default:
12754 return -1;
12757 break;
12760 case 0x0F: { /* FMAX_A.df */
12761 switch (df) {
12762 case 0x00: { /* FMAX_A.W */
12763 DIP("FMAX_A.W w%d, w%d, w%d", wd, ws, wt);
12764 calculateMSACSR(ws, wt, FMAXAW, 2);
12765 t1 = newTemp(Ity_V128);
12766 t2 = newTemp(Ity_V128);
12767 t3 = newTemp(Ity_V128);
12768 t4 = newTemp(Ity_V128);
12769 assign(t1,
12770 binop(Iop_AndV128,
12771 getWReg(ws),
12772 binop(Iop_64HLtoV128,
12773 mkU64(0x7FFFFFFF7FFFFFFF),
12774 mkU64(0x7FFFFFFF7FFFFFFF))));
12775 assign(t2,
12776 binop(Iop_AndV128,
12777 getWReg(wt),
12778 binop(Iop_64HLtoV128,
12779 mkU64(0x7FFFFFFF7FFFFFFF),
12780 mkU64(0x7FFFFFFF7FFFFFFF))));
12781 assign(t3,
12782 binop(Iop_Max32Fx4,
12783 mkexpr(t2), mkexpr(t1)));
12784 assign(t4,
12785 binop(Iop_AndV128,
12786 binop(Iop_AndV128,
12787 unop(Iop_NotV128,
12788 binop(Iop_CmpUN32Fx4,
12789 mkexpr(t3),
12790 mkexpr(t3))),
12791 binop(Iop_OrV128,
12792 binop(Iop_AndV128,
12793 binop(Iop_CmpEQ32Fx4,
12794 mkexpr(t1),
12795 mkexpr(t2)),
12796 binop(Iop_AndV128,
12797 getWReg(ws),
12798 getWReg(wt))),
12799 binop(Iop_OrV128,
12800 binop(Iop_AndV128,
12801 binop(Iop_OrV128,
12802 binop(Iop_CmpUN32Fx4,
12803 mkexpr(t1),
12804 mkexpr(t1)),
12805 binop(Iop_CmpLT32Fx4,
12806 mkexpr(t1),
12807 mkexpr(t3))),
12808 getWReg(wt)),
12809 binop(Iop_AndV128,
12810 binop(Iop_OrV128,
12811 binop(Iop_CmpUN32Fx4,
12812 mkexpr(t2),
12813 mkexpr(t2)),
12814 binop(Iop_CmpLT32Fx4,
12815 mkexpr(t2),
12816 mkexpr(t3))),
12817 getWReg(ws))))),
12818 binop(Iop_64HLtoV128,
12819 mkU64(0x8000000080000000),
12820 mkU64(0x8000000080000000))));
12821 putWReg(wd,
12822 binop(Iop_OrV128,
12823 mkexpr(t3), mkexpr(t4)));
12824 break;
12827 case 0x01: { /* FMAX_A.D */
12828 DIP("FMAX_A.D w%d, w%d, w%d", wd, ws, wt);
12829 calculateMSACSR(ws, wt, FMAXAD, 2);
12830 t1 = newTemp(Ity_V128);
12831 t2 = newTemp(Ity_V128);
12832 t3 = newTemp(Ity_V128);
12833 t4 = newTemp(Ity_V128);
12834 assign(t1,
12835 binop(Iop_AndV128,
12836 getWReg(ws),
12837 binop(Iop_64HLtoV128,
12838 mkU64(0x7FFFFFFFFFFFFFFF),
12839 mkU64(0x7FFFFFFFFFFFFFFF))));
12840 assign(t2,
12841 binop(Iop_AndV128,
12842 getWReg(wt),
12843 binop(Iop_64HLtoV128,
12844 mkU64(0x7FFFFFFFFFFFFFFF),
12845 mkU64(0x7FFFFFFFFFFFFFFF))));
12846 assign(t3,
12847 binop(Iop_Max64Fx2,
12848 mkexpr(t2), mkexpr(t1)));
12849 assign(t4,
12850 binop(Iop_AndV128,
12851 binop(Iop_AndV128,
12852 unop(Iop_NotV128,
12853 binop(Iop_CmpUN64Fx2,
12854 mkexpr(t3),
12855 mkexpr(t3))),
12856 binop(Iop_OrV128,
12857 binop(Iop_AndV128,
12858 binop(Iop_CmpEQ64Fx2,
12859 mkexpr(t1),
12860 mkexpr(t2)),
12861 binop(Iop_AndV128,
12862 getWReg(ws),
12863 getWReg(wt))),
12864 binop(Iop_OrV128,
12865 binop(Iop_AndV128,
12866 binop(Iop_OrV128,
12867 binop(Iop_CmpUN64Fx2,
12868 mkexpr(t1),
12869 mkexpr(t1)),
12870 binop(Iop_CmpLT64Fx2,
12871 mkexpr(t1),
12872 mkexpr(t3))),
12873 getWReg(wt)),
12874 binop(Iop_AndV128,
12875 binop(Iop_OrV128,
12876 binop(Iop_CmpUN64Fx2,
12877 mkexpr(t2),
12878 mkexpr(t2)),
12879 binop(Iop_CmpLT64Fx2,
12880 mkexpr(t2),
12881 mkexpr(t3))),
12882 getWReg(ws))))),
12883 binop(Iop_64HLtoV128,
12884 mkU64(0x8000000000000000),
12885 mkU64(0x8000000000000000))));
12886 putWReg(wd,
12887 binop(Iop_OrV128,
12888 mkexpr(t3), mkexpr(t4)));
12889 break;
12892 default:
12893 return -1;
12896 break;
12899 default:
12900 return -1;
12903 return 0;
12906 static Int msa_3R_1C(UInt cins, UChar wd, UChar ws) /* 3R (0x1C) */
12908 IRTemp t1, t2, t3, t4, t5, t6;
12909 UShort operation;
12910 UChar df, wt;
12912 operation = (cins & 0x03C00000) >> 22;
12913 df = (cins & 0x00200000) >> 21;
12914 wt = (cins & 0x001F0000) >> 16;
12916 switch (operation) {
12917 case 0x01: { /* FCOR.df */
12918 switch (df) {
12919 case 0x00: { /* FCOR.W */
12920 DIP("FCOR.W w%d, w%d, w%d", wd, ws, wt);
12921 calculateMSACSR(ws, wt, FCORW, 2);
12922 putWReg(wd,
12923 unop(Iop_NotV128,
12924 binop(Iop_CmpUN32Fx4,
12925 getWReg(ws),
12926 getWReg(wt))));
12927 break;
12930 case 0x01: { /* FCOR.D */
12931 DIP("FCOR.D w%d, w%d, w%d", wd, ws, wt);
12932 calculateMSACSR(ws, wt, FCORD, 2);
12933 putWReg(wd,
12934 unop(Iop_NotV128,
12935 binop(Iop_CmpUN64Fx2,
12936 getWReg(ws),
12937 getWReg(wt))));
12938 break;
12941 default:
12942 return -1;
12945 break;
12948 case 0x02: { /* FCUNE.df */
12949 switch (df) {
12950 case 0x00: { /* FCUNE.W */
12951 DIP("FCUNE.W w%d, w%d, w%d", wd, ws, wt);
12952 calculateMSACSR(ws, wt, FCUNEW, 2);
12953 putWReg(wd,
12954 unop(Iop_NotV128,
12955 binop(Iop_CmpEQ32Fx4,
12956 getWReg(ws),
12957 getWReg(wt))));
12958 break;
12961 case 0x01: { /* FCUNE.D */
12962 DIP("FCUNE.D w%d, w%d, w%d", wd, ws, wt);
12963 calculateMSACSR(ws, wt, FCUNED, 2);
12964 putWReg(wd,
12965 unop(Iop_NotV128,
12966 binop(Iop_CmpEQ64Fx2,
12967 getWReg(ws),
12968 getWReg(wt))));
12969 break;
12972 default:
12973 return -1;
12976 break;
12979 case 0x03: { /* FCNE.df */
12980 switch (df) {
12981 case 0x00: { /* FCNE.W */
12982 DIP("FCNE.W w%d, w%d, w%d", wd, ws, wt);
12983 calculateMSACSR(ws, wt, FCNEW, 2);
12984 putWReg(wd,
12985 binop(Iop_XorV128,
12986 unop(Iop_NotV128,
12987 binop(Iop_CmpEQ32Fx4,
12988 getWReg(ws),
12989 getWReg(wt))),
12990 binop(Iop_CmpUN32Fx4,
12991 getWReg(ws),
12992 getWReg(wt))));
12993 break;
12996 case 0x01: { /* FCNE.D */
12997 DIP("FCNE.D w%d, w%d, w%d", wd, ws, wt);
12998 calculateMSACSR(ws, wt, FCNED, 2);
12999 putWReg(wd,
13000 binop(Iop_XorV128,
13001 unop(Iop_NotV128,
13002 binop(Iop_CmpEQ64Fx2,
13003 getWReg(ws),
13004 getWReg(wt))),
13005 binop(Iop_CmpUN64Fx2,
13006 getWReg(ws),
13007 getWReg(wt))));
13008 break;
13011 default:
13012 return -1;
13015 break;
13018 case 0x04: { /* MUL_Q.df */
13019 switch (df) {
13020 case 0x00: { /* MUL_Q.H */
13021 DIP("MUL_Q.H w%d, w%d, w%d", wd, ws, wt);
13022 t1 = newTemp(Ity_V128);
13023 t2 = newTemp(Ity_V128);
13024 t3 = newTemp(Ity_V128);
13025 assign(t1, getWReg(ws));
13026 assign(t2, getWReg(wt));
13027 assign(t3,
13028 binop(Iop_QDMulHi16Sx8,
13029 mkexpr(t1), mkexpr(t2)));
13030 putWReg(wd, mkexpr(t3));
13031 break;
13034 case 0x01: { /* MUL_Q.W */
13035 DIP("MUL_Q.W w%d, w%d, w%d", wd, ws, wt);
13036 t1 = newTemp(Ity_V128);
13037 t2 = newTemp(Ity_V128);
13038 t3 = newTemp(Ity_V128);
13039 assign(t1, getWReg(ws));
13040 assign(t2, getWReg(wt));
13041 assign(t3,
13042 binop(Iop_QDMulHi32Sx4,
13043 mkexpr(t1), mkexpr(t2)));
13044 putWReg(wd, mkexpr(t3));
13045 break;
13048 default:
13049 return -1;
13052 break;
13055 case 0x05: { /* MADD_Q.df */
13056 switch (df) {
13057 case 0x00: { /* MADD_Q.W */
13058 DIP("MADD_Q.W w%d, w%d, w%d", wd, ws, wt);
13059 t1 = newTemp(Ity_V128);
13060 t2 = newTemp(Ity_V128);
13061 t3 = newTemp(Ity_V128);
13062 t4 = newTemp(Ity_V128);
13063 t5 = newTemp(Ity_V128);
13064 t6 = newTemp(Ity_V128);
13065 assign(t1, // even
13066 binop(Iop_SarN32x4,
13067 binop(Iop_InterleaveEvenLanes16x8,
13068 getWReg(ws),
13069 getWReg(ws)),
13070 mkU8(16)));
13071 assign(t2, // odd
13072 binop(Iop_SarN32x4,
13073 getWReg(ws), mkU8(16)));
13074 assign(t3, // even
13075 binop(Iop_SarN32x4,
13076 binop(Iop_InterleaveEvenLanes16x8,
13077 getWReg(wt),
13078 getWReg(wt)),
13079 mkU8(16)));
13080 assign(t4, // odd
13081 binop(Iop_SarN32x4,
13082 getWReg(wt), mkU8(16)));
13083 assign(t5,
13084 binop(Iop_Add32x4,
13085 binop(Iop_ShlN32x4,
13086 binop(Iop_SarN32x4,
13087 binop(Iop_InterleaveEvenLanes16x8,
13088 getWReg(wd),
13089 getWReg(wd)),
13090 mkU8(16)),
13091 mkU8(15)),
13092 binop(Iop_Mul32x4,
13093 mkexpr(t1), mkexpr(t3))));
13094 assign(t6,
13095 binop(Iop_Add32x4,
13096 binop(Iop_ShlN32x4,
13097 binop(Iop_SarN32x4,
13098 getWReg(wd),
13099 mkU8(16)),
13100 mkU8(15)),
13101 binop(Iop_Mul32x4,
13102 mkexpr(t2), mkexpr(t4))));
13103 putWReg(wd,
13104 binop(Iop_InterleaveEvenLanes16x8,
13105 binop(Iop_QandQSarNnarrow32Sto16Sx4,
13106 mkexpr(t6), mkU8(15)),
13107 binop(Iop_QandQSarNnarrow32Sto16Sx4,
13108 mkexpr(t5), mkU8(15))));
13109 break;
13112 case 0x01: { /* MADD_Q.W */
13113 DIP("MADD_Q.W w%d, w%d, w%d", wd, ws, wt);
13114 t1 = newTemp(Ity_V128);
13115 t2 = newTemp(Ity_V128);
13116 t3 = newTemp(Ity_V128);
13117 t4 = newTemp(Ity_V128);
13118 t5 = newTemp(Ity_V128);
13119 t6 = newTemp(Ity_V128);
13120 assign(t1, // even
13121 binop(Iop_SarN64x2,
13122 binop(Iop_InterleaveEvenLanes32x4,
13123 getWReg(ws),
13124 getWReg(ws)),
13125 mkU8(32)));
13126 assign(t2, // odd
13127 binop(Iop_SarN64x2,
13128 getWReg(ws), mkU8(32)));
13129 assign(t3, // even
13130 binop(Iop_SarN64x2,
13131 binop(Iop_InterleaveEvenLanes32x4,
13132 getWReg(wt),
13133 getWReg(wt)),
13134 mkU8(32)));
13135 assign(t4, // odd
13136 binop(Iop_SarN64x2,
13137 getWReg(wt), mkU8(32)));
13138 assign(t5,
13139 binop(Iop_Add64x2,
13140 binop(Iop_ShlN64x2,
13141 binop(Iop_SarN64x2,
13142 binop(Iop_InterleaveEvenLanes32x4,
13143 getWReg(wd),
13144 getWReg(wd)),
13145 mkU8(32)),
13146 mkU8(31)),
13147 binop(Iop_64HLtoV128,
13148 binop(Iop_Mul64,
13149 unop(Iop_V128HIto64,
13150 mkexpr(t1)),
13151 unop(Iop_V128HIto64,
13152 mkexpr(t3))),
13153 binop(Iop_Mul64,
13154 unop(Iop_V128to64,
13155 mkexpr(t1)),
13156 unop(Iop_V128to64,
13157 mkexpr(t3))))));
13158 assign(t6,
13159 binop(Iop_Add64x2,
13160 binop(Iop_ShlN64x2,
13161 binop(Iop_SarN64x2,
13162 getWReg(wd),
13163 mkU8(32)),
13164 mkU8(31)),
13165 binop(Iop_64HLtoV128,
13166 binop(Iop_Mul64,
13167 unop(Iop_V128HIto64,
13168 mkexpr(t2)),
13169 unop(Iop_V128HIto64,
13170 mkexpr(t4))),
13171 binop(Iop_Mul64,
13172 unop(Iop_V128to64,
13173 mkexpr(t2)),
13174 unop(Iop_V128to64,
13175 mkexpr(t4))))));
13176 putWReg(wd,
13177 binop(Iop_InterleaveEvenLanes32x4,
13178 binop(Iop_QandQSarNnarrow64Sto32Sx2,
13179 mkexpr(t6), mkU8(31)),
13180 binop(Iop_QandQSarNnarrow64Sto32Sx2,
13181 mkexpr(t5), mkU8(31))));
13182 break;
13185 default:
13186 return -1;
13189 break;
13192 case 0x06: { /* MSUB_Q.df */
13193 switch (df) {
13194 case 0x00: { /* MSUB_Q.H */
13195 DIP("MSUB_Q.H w%d, w%d, w%d", wd, ws, wt);
13196 t1 = newTemp(Ity_V128);
13197 t2 = newTemp(Ity_V128);
13198 t3 = newTemp(Ity_V128);
13199 t4 = newTemp(Ity_V128);
13200 t5 = newTemp(Ity_V128);
13201 t6 = newTemp(Ity_V128);
13202 assign(t1, // even
13203 binop(Iop_SarN32x4,
13204 binop(Iop_InterleaveEvenLanes16x8,
13205 getWReg(ws),
13206 getWReg(ws)),
13207 mkU8(16)));
13208 assign(t2, // odd
13209 binop(Iop_SarN32x4,
13210 getWReg(ws), mkU8(16)));
13211 assign(t3, // even
13212 binop(Iop_SarN32x4,
13213 binop(Iop_InterleaveEvenLanes16x8,
13214 getWReg(wt),
13215 getWReg(wt)),
13216 mkU8(16)));
13217 assign(t4, // odd
13218 binop(Iop_SarN32x4,
13219 getWReg(wt), mkU8(16)));
13220 assign(t5,
13221 binop(Iop_Sub32x4,
13222 binop(Iop_ShlN32x4,
13223 binop(Iop_SarN32x4,
13224 binop(Iop_InterleaveEvenLanes16x8,
13225 getWReg(wd),
13226 getWReg(wd)),
13227 mkU8(16)),
13228 mkU8(15)),
13229 binop(Iop_Mul32x4,
13230 mkexpr(t1), mkexpr(t3))));
13231 assign(t6,
13232 binop(Iop_Sub32x4,
13233 binop(Iop_ShlN32x4,
13234 binop(Iop_SarN32x4,
13235 getWReg(wd),
13236 mkU8(16)),
13237 mkU8(15)),
13238 binop(Iop_Mul32x4,
13239 mkexpr(t2), mkexpr(t4))));
13240 putWReg(wd,
13241 binop(Iop_InterleaveEvenLanes16x8,
13242 binop(Iop_QandQSarNnarrow32Sto16Sx4,
13243 mkexpr(t6), mkU8(15)),
13244 binop(Iop_QandQSarNnarrow32Sto16Sx4,
13245 mkexpr(t5), mkU8(15))));
13246 break;
13249 case 0x01: { /* MSUB_Q.W */
13250 DIP("MSUB_Q.W w%d, w%d, w%d", wd, ws, wt);
13251 t1 = newTemp(Ity_V128);
13252 t2 = newTemp(Ity_V128);
13253 t3 = newTemp(Ity_V128);
13254 t4 = newTemp(Ity_V128);
13255 t5 = newTemp(Ity_V128);
13256 t6 = newTemp(Ity_V128);
13257 assign(t1, // even
13258 binop(Iop_SarN64x2,
13259 binop(Iop_InterleaveEvenLanes32x4,
13260 getWReg(ws),
13261 getWReg(ws)),
13262 mkU8(32)));
13263 assign(t2, // odd
13264 binop(Iop_SarN64x2,
13265 getWReg(ws), mkU8(32)));
13266 assign(t3, // even
13267 binop(Iop_SarN64x2,
13268 binop(Iop_InterleaveEvenLanes32x4,
13269 getWReg(wt),
13270 getWReg(wt)),
13271 mkU8(32)));
13272 assign(t4, // odd
13273 binop(Iop_SarN64x2,
13274 getWReg(wt), mkU8(32)));
13275 assign(t5,
13276 binop(Iop_Sub64x2,
13277 binop(Iop_ShlN64x2,
13278 binop(Iop_SarN64x2,
13279 binop(Iop_InterleaveEvenLanes32x4,
13280 getWReg(wd),
13281 getWReg(wd)),
13282 mkU8(32)),
13283 mkU8(31)),
13284 binop(Iop_64HLtoV128,
13285 binop(Iop_Mul64,
13286 unop(Iop_V128HIto64,
13287 mkexpr(t1)),
13288 unop(Iop_V128HIto64,
13289 mkexpr(t3))),
13290 binop(Iop_Mul64,
13291 unop(Iop_V128to64,
13292 mkexpr(t1)),
13293 unop(Iop_V128to64,
13294 mkexpr(t3))))));
13295 assign(t6,
13296 binop(Iop_Sub64x2,
13297 binop(Iop_ShlN64x2,
13298 binop(Iop_SarN64x2,
13299 getWReg(wd),
13300 mkU8(32)),
13301 mkU8(31)),
13302 binop(Iop_64HLtoV128,
13303 binop(Iop_Mul64,
13304 unop(Iop_V128HIto64,
13305 mkexpr(t2)),
13306 unop(Iop_V128HIto64,
13307 mkexpr(t4))),
13308 binop(Iop_Mul64,
13309 unop(Iop_V128to64,
13310 mkexpr(t2)),
13311 unop(Iop_V128to64,
13312 mkexpr(t4))))));
13313 putWReg(wd,
13314 binop(Iop_InterleaveEvenLanes32x4,
13315 binop(Iop_QandQSarNnarrow64Sto32Sx2,
13316 mkexpr(t6), mkU8(31)),
13317 binop(Iop_QandQSarNnarrow64Sto32Sx2,
13318 mkexpr(t5), mkU8(31))));
13319 break;
13322 default:
13323 return -1;
13326 break;
13329 case 0x09: { /* FSOR.df */
13330 switch (df) {
13331 case 0x00: { /* FSOR.W */
13332 DIP("FSOR.W w%d, w%d, w%d", wd, ws, wt);
13333 calculateMSACSR(ws, wt, FSORW, 2);
13334 putWReg(wd,
13335 unop(Iop_NotV128,
13336 binop(Iop_CmpUN32Fx4,
13337 getWReg(ws),
13338 getWReg(wt))));
13339 break;
13342 case 0x01: { /* FSOR.D */
13343 DIP("FSOR.D w%d, w%d, w%d", wd, ws, wt);
13344 calculateMSACSR(ws, wt, FSORD, 2);
13345 putWReg(wd,
13346 unop(Iop_NotV128,
13347 binop(Iop_CmpUN64Fx2,
13348 getWReg(ws),
13349 getWReg(wt))));
13350 break;
13353 default:
13354 return -1;
13357 break;
13360 case 0x0A: { /* FSUNE.df */
13361 switch (df) {
13362 case 0x00: { /* FSUNE.W */
13363 DIP("FSUNE.W w%d, w%d, w%d", wd, ws, wt);
13364 calculateMSACSR(ws, wt, FSUNEW, 2);
13365 putWReg(wd,
13366 unop(Iop_NotV128,
13367 binop(Iop_CmpEQ32Fx4,
13368 getWReg(ws),
13369 getWReg(wt))));
13370 break;
13373 case 0x01: { /* FSUNE.D */
13374 DIP("FSUNE.D w%d, w%d, w%d", wd, ws, wt);
13375 calculateMSACSR(ws, wt, FSUNED, 2);
13376 putWReg(wd,
13377 unop(Iop_NotV128,
13378 binop(Iop_CmpEQ64Fx2,
13379 getWReg(ws),
13380 getWReg(wt))));
13381 break;
13384 default:
13385 return -1;
13388 break;
13391 case 0x0B: { /* FSNE.df */
13392 switch (df) {
13393 case 0x00: { /* FSNE.W */
13394 DIP("FSNE.W w%d, w%d, w%d", wd, ws, wt);
13395 calculateMSACSR(ws, wt, FSNEW, 2);
13396 putWReg(wd,
13397 binop(Iop_XorV128,
13398 unop(Iop_NotV128,
13399 binop(Iop_CmpEQ32Fx4,
13400 getWReg(ws),
13401 getWReg(wt))),
13402 binop(Iop_CmpUN32Fx4,
13403 getWReg(ws),
13404 getWReg(wt))));
13405 break;
13408 case 0x01: { /* FSNE.D */
13409 DIP("FSNE.D w%d, w%d, w%d", wd, ws, wt);
13410 calculateMSACSR(ws, wt, FSNED, 2);
13411 putWReg(wd,
13412 binop(Iop_XorV128,
13413 unop(Iop_NotV128,
13414 binop(Iop_CmpEQ64Fx2,
13415 getWReg(ws),
13416 getWReg(wt))),
13417 binop(Iop_CmpUN64Fx2,
13418 getWReg(ws),
13419 getWReg(wt))));
13420 break;
13423 default:
13424 return -1;
13427 break;
13430 case 0x0C: { /* MULR_Q.df */
13431 switch (df) {
13432 case 0x00: { /* MULR_Q.H */
13433 DIP("MULR_Q.H w%d, w%d, w%d", wd, ws, wt);
13434 t1 = newTemp(Ity_V128);
13435 t2 = newTemp(Ity_V128);
13436 t3 = newTemp(Ity_V128);
13437 assign(t1, getWReg(ws));
13438 assign(t2, getWReg(wt));
13439 assign(t3, binop(Iop_QRDMulHi16Sx8,
13440 mkexpr(t1), mkexpr(t2)));
13441 putWReg(wd, mkexpr(t3));
13442 break;
13445 case 0x01: { /* MULR_Q.W */
13446 DIP("MULR_Q.W w%d, w%d, w%d", wd, ws, wt);
13447 t1 = newTemp(Ity_V128);
13448 t2 = newTemp(Ity_V128);
13449 t3 = newTemp(Ity_V128);
13450 assign(t1, getWReg(ws));
13451 assign(t2, getWReg(wt));
13452 assign(t3, binop(Iop_QRDMulHi32Sx4,
13453 mkexpr(t1), mkexpr(t2)));
13454 putWReg(wd, mkexpr(t3));
13455 break;
13458 default:
13459 return -1;
13462 break;
13465 case 0x0D: { /* MADDR_Q.df */
13466 switch (df) {
13467 case 0x00: { /* MADDR_Q.W */
13468 DIP("MADDR_Q.W w%d, w%d, w%d", wd, ws, wt);
13469 t1 = newTemp(Ity_V128);
13470 t2 = newTemp(Ity_V128);
13471 t3 = newTemp(Ity_V128);
13472 t4 = newTemp(Ity_V128);
13473 t5 = newTemp(Ity_V128);
13474 t6 = newTemp(Ity_V128);
13475 assign(t1, // even
13476 binop(Iop_SarN32x4,
13477 binop(Iop_InterleaveEvenLanes16x8,
13478 getWReg(ws),
13479 getWReg(ws)),
13480 mkU8(16)));
13481 assign(t2, // odd
13482 binop(Iop_SarN32x4,
13483 getWReg(ws), mkU8(16)));
13484 assign(t3, // even
13485 binop(Iop_SarN32x4,
13486 binop(Iop_InterleaveEvenLanes16x8,
13487 getWReg(wt),
13488 getWReg(wt)),
13489 mkU8(16)));
13490 assign(t4, // odd
13491 binop(Iop_SarN32x4,
13492 getWReg(wt), mkU8(16)));
13493 assign(t5,
13494 binop(Iop_Add32x4,
13495 binop(Iop_ShlN32x4,
13496 binop(Iop_SarN32x4,
13497 binop(Iop_InterleaveEvenLanes16x8,
13498 getWReg(wd),
13499 getWReg(wd)),
13500 mkU8(16)),
13501 mkU8(15)),
13502 binop(Iop_Mul32x4,
13503 mkexpr(t1), mkexpr(t3))));
13504 assign(t6,
13505 binop(Iop_Add32x4,
13506 binop(Iop_ShlN32x4,
13507 binop(Iop_SarN32x4,
13508 getWReg(wd),
13509 mkU8(16)),
13510 mkU8(15)),
13511 binop(Iop_Mul32x4,
13512 mkexpr(t2), mkexpr(t4))));
13513 putWReg(wd,
13514 binop(Iop_InterleaveEvenLanes16x8,
13515 binop(Iop_QandQRSarNnarrow32Sto16Sx4,
13516 mkexpr(t6), mkU8(15)),
13517 binop(Iop_QandQRSarNnarrow32Sto16Sx4,
13518 mkexpr(t5), mkU8(15))));
13519 break;
13522 case 0x01: { /* MADDR_Q.D */
13523 DIP("MADDR_Q.D w%d, w%d, w%d", wd, ws, wt);
13524 t1 = newTemp(Ity_V128);
13525 t2 = newTemp(Ity_V128);
13526 t3 = newTemp(Ity_V128);
13527 t4 = newTemp(Ity_V128);
13528 t5 = newTemp(Ity_V128);
13529 t6 = newTemp(Ity_V128);
13530 assign(t1, // even
13531 binop(Iop_SarN64x2,
13532 binop(Iop_InterleaveEvenLanes32x4,
13533 getWReg(ws),
13534 getWReg(ws)),
13535 mkU8(32)));
13536 assign(t2, // odd
13537 binop(Iop_SarN64x2,
13538 getWReg(ws), mkU8(32)));
13539 assign(t3, // even
13540 binop(Iop_SarN64x2,
13541 binop(Iop_InterleaveEvenLanes32x4,
13542 getWReg(wt),
13543 getWReg(wt)),
13544 mkU8(32)));
13545 assign(t4, // odd
13546 binop(Iop_SarN64x2,
13547 getWReg(wt), mkU8(32)));
13548 assign(t5,
13549 binop(Iop_Add64x2,
13550 binop(Iop_ShlN64x2,
13551 binop(Iop_SarN64x2,
13552 binop(Iop_InterleaveEvenLanes32x4,
13553 getWReg(wd),
13554 getWReg(wd)),
13555 mkU8(32)),
13556 mkU8(31)),
13557 binop(Iop_64HLtoV128,
13558 binop(Iop_Mul64,
13559 unop(Iop_V128HIto64,
13560 mkexpr(t1)),
13561 unop(Iop_V128HIto64,
13562 mkexpr(t3))),
13563 binop(Iop_Mul64,
13564 unop(Iop_V128to64,
13565 mkexpr(t1)),
13566 unop(Iop_V128to64,
13567 mkexpr(t3))))));
13568 assign(t6,
13569 binop(Iop_Add64x2,
13570 binop(Iop_ShlN64x2,
13571 binop(Iop_SarN64x2,
13572 getWReg(wd),
13573 mkU8(32)),
13574 mkU8(31)),
13575 binop(Iop_64HLtoV128,
13576 binop(Iop_Mul64,
13577 unop(Iop_V128HIto64,
13578 mkexpr(t2)),
13579 unop(Iop_V128HIto64,
13580 mkexpr(t4))),
13581 binop(Iop_Mul64,
13582 unop(Iop_V128to64,
13583 mkexpr(t2)),
13584 unop(Iop_V128to64,
13585 mkexpr(t4))))));
13586 putWReg(wd,
13587 binop(Iop_InterleaveEvenLanes32x4,
13588 binop(Iop_QandQRSarNnarrow64Sto32Sx2,
13589 mkexpr(t6), mkU8(31)),
13590 binop(Iop_QandQRSarNnarrow64Sto32Sx2,
13591 mkexpr(t5), mkU8(31))));
13592 break;
13595 default:
13596 return -1;
13599 break;
13602 case 0x0E: { /* MSUBR_Q.df */
13603 switch (df) {
13604 case 0x00: { /* MSUBR_Q.W */
13605 DIP("MSUBR_Q.W w%d, w%d, w%d", wd, ws, wt);
13606 t1 = newTemp(Ity_V128);
13607 t2 = newTemp(Ity_V128);
13608 t3 = newTemp(Ity_V128);
13609 t4 = newTemp(Ity_V128);
13610 t5 = newTemp(Ity_V128);
13611 t6 = newTemp(Ity_V128);
13612 assign(t1, // even
13613 binop(Iop_SarN32x4,
13614 binop(Iop_InterleaveEvenLanes16x8,
13615 getWReg(ws),
13616 getWReg(ws)),
13617 mkU8(16)));
13618 assign(t2, // odd
13619 binop(Iop_SarN32x4,
13620 getWReg(ws), mkU8(16)));
13621 assign(t3, // even
13622 binop(Iop_SarN32x4,
13623 binop(Iop_InterleaveEvenLanes16x8,
13624 getWReg(wt),
13625 getWReg(wt)),
13626 mkU8(16)));
13627 assign(t4, // odd
13628 binop(Iop_SarN32x4,
13629 getWReg(wt), mkU8(16)));
13630 assign(t5,
13631 binop(Iop_Sub32x4,
13632 binop(Iop_ShlN32x4,
13633 binop(Iop_SarN32x4,
13634 binop(Iop_InterleaveEvenLanes16x8,
13635 getWReg(wd),
13636 getWReg(wd)),
13637 mkU8(16)),
13638 mkU8(15)),
13639 binop(Iop_Mul32x4,
13640 mkexpr(t1), mkexpr(t3))));
13641 assign(t6,
13642 binop(Iop_Sub32x4,
13643 binop(Iop_ShlN32x4,
13644 binop(Iop_SarN32x4,
13645 getWReg(wd),
13646 mkU8(16)),
13647 mkU8(15)),
13648 binop(Iop_Mul32x4,
13649 mkexpr(t2), mkexpr(t4))));
13650 putWReg(wd,
13651 binop(Iop_InterleaveEvenLanes16x8,
13652 binop(Iop_QandQRSarNnarrow32Sto16Sx4,
13653 mkexpr(t6), mkU8(15)),
13654 binop(Iop_QandQRSarNnarrow32Sto16Sx4,
13655 mkexpr(t5), mkU8(15))));
13656 break;
13659 case 0x01: { /* MSUBR_Q.D */
13660 DIP("MSUBR_Q.D w%d, w%d, w%d", wd, ws, wt);
13661 t1 = newTemp(Ity_V128);
13662 t2 = newTemp(Ity_V128);
13663 t3 = newTemp(Ity_V128);
13664 t4 = newTemp(Ity_V128);
13665 t5 = newTemp(Ity_V128);
13666 t6 = newTemp(Ity_V128);
13667 assign(t1, // even
13668 binop(Iop_SarN64x2,
13669 binop(Iop_InterleaveEvenLanes32x4,
13670 getWReg(ws),
13671 getWReg(ws)),
13672 mkU8(32)));
13673 assign(t2, // odd
13674 binop(Iop_SarN64x2,
13675 getWReg(ws), mkU8(32)));
13676 assign(t3, // even
13677 binop(Iop_SarN64x2,
13678 binop(Iop_InterleaveEvenLanes32x4,
13679 getWReg(wt),
13680 getWReg(wt)),
13681 mkU8(32)));
13682 assign(t4, // odd
13683 binop(Iop_SarN64x2,
13684 getWReg(wt), mkU8(32)));
13685 assign(t5,
13686 binop(Iop_Sub64x2,
13687 binop(Iop_ShlN64x2,
13688 binop(Iop_SarN64x2,
13689 binop(Iop_InterleaveEvenLanes32x4,
13690 getWReg(wd),
13691 getWReg(wd)),
13692 mkU8(32)),
13693 mkU8(31)),
13694 binop(Iop_64HLtoV128,
13695 binop(Iop_Mul64,
13696 unop(Iop_V128HIto64,
13697 mkexpr(t1)),
13698 unop(Iop_V128HIto64,
13699 mkexpr(t3))),
13700 binop(Iop_Mul64,
13701 unop(Iop_V128to64,
13702 mkexpr(t1)),
13703 unop(Iop_V128to64,
13704 mkexpr(t3))))));
13705 assign(t6,
13706 binop(Iop_Sub64x2,
13707 binop(Iop_ShlN64x2,
13708 binop(Iop_SarN64x2,
13709 getWReg(wd),
13710 mkU8(32)),
13711 mkU8(31)),
13712 binop(Iop_64HLtoV128,
13713 binop(Iop_Mul64,
13714 unop(Iop_V128HIto64,
13715 mkexpr(t2)),
13716 unop(Iop_V128HIto64,
13717 mkexpr(t4))),
13718 binop(Iop_Mul64,
13719 unop(Iop_V128to64,
13720 mkexpr(t2)),
13721 unop(Iop_V128to64,
13722 mkexpr(t4))))));
13723 putWReg(wd,
13724 binop(Iop_InterleaveEvenLanes32x4,
13725 binop(Iop_QandQRSarNnarrow64Sto32Sx2,
13726 mkexpr(t6), mkU8(31)),
13727 binop(Iop_QandQRSarNnarrow64Sto32Sx2,
13728 mkexpr(t5), mkU8(31))));
13729 break;
13732 default:
13733 return -1;
13736 break;
13739 default:
13740 return -1;
13743 return 0;
13746 static Int msa_ELM(UInt cins, UChar wd, UChar ws) /* ELM (0x19) */
13748 IRTemp t1, t2, t3, t4, t5;
13749 IRType ty;
13750 UShort operation;
13751 UChar df, n;
13753 operation = (cins & 0x03C00000) >> 22;
13754 ty = mode64 ? Ity_I64 : Ity_I32;
13756 switch ((cins & 0x03FF0000) >> 16) {
13757 case 0x07E: /* CFCMSA */
13758 DIP("CFCMSA r%d, c%d", wd, ws);
13760 switch (ws) {
13761 case 0: { /* MSAIR */
13762 IRDirty *d;
13763 t1 = newTemp(Ity_I32);
13764 /* IRExpr_BBPTR() =>
13765 Need to pass pointer to
13766 guest state to helper. */
13767 d = unsafeIRDirty_1_N(t1, 0,
13768 "mips_dirtyhelper_get_MSAIR",
13769 &mips_dirtyhelper_get_MSAIR,
13770 mkIRExprVec_0());
13771 /* d->nFxState = 0; */
13772 stmt(IRStmt_Dirty(d));
13773 putIReg(wd,
13774 mkWidenFrom32(ty, mkexpr(t1), True));
13775 break;
13778 case 1: /* MSACSR */
13779 putIReg(wd,
13780 mkWidenFrom32(ty, getMSACSR(), True));
13781 break;
13783 default:
13784 putIReg(wd,
13785 mkWidenFrom32(ty, mkU32(0), False));
13786 break;
13789 break;
13791 case 0x03E: /* CTCMSA */
13792 DIP("CTCMSA r%d, c%d", ws, wd);
13794 if (wd == 1) { /* MSACSR */
13795 putMSACSR(
13796 binop(Iop_And32, mkNarrowTo32(ty, getIReg(ws)),
13797 mkU32(0x1FFFFFF)));
13800 break;
13802 case 0x0BE: /* MOVE.V */
13803 DIP("MOVE.V w%d, w%d", ws, wd);
13804 putWReg(wd, getWReg(ws));
13805 break;
13807 default:
13808 df = (cins & 0x003F0000) >> 16;
13810 if ((df & 0x38) == 0x38) { // 11100n; dw
13811 n = df & 0x01;
13812 df = 0x38;
13813 } else if ((df & 0x30) == 0x30) { // 1100nn; w
13814 n = df & 0x03;
13815 df = 0x30;
13816 } else if ((df & 0x20) == 0x20) { // 100nnn; hw
13817 n = df & 0x07;
13818 df = 0x20;
13819 } else if ((df & 0x00) == 0x00) { // 00nnnn; b
13820 n = df & 0x0F;
13821 df = 0x00;
13824 switch (operation) {
13825 case 0x00: /* SLDI.df */
13826 switch (df) {
13827 case 0x00: /* SLDI.B */
13828 DIP("SLDI.B w%d, w%d[%d]", wd, ws, n);
13829 t1 = newTemp(Ity_V128);
13830 t2 = newTemp(Ity_V128);
13831 assign(t1,
13832 binop(Iop_ShrV128,
13833 getWReg(ws),
13834 mkU8(n << 3)));
13835 assign(t2,
13836 binop(Iop_ShlV128,
13837 getWReg(wd),
13838 mkU8(n ?
13839 (16 - n) << 3 : 0)));
13840 putWReg(wd,
13841 binop(Iop_OrV128, mkexpr(t1), mkexpr(t2)));
13842 break;
13844 case 0x20: /* SLDI.H */
13845 DIP("SLDI.H w%d, w%d[%d]", wd, ws, n);
13847 if (n == 0) {
13848 putWReg(wd, getWReg(ws));
13849 } else {
13850 t1 = newTemp(Ity_V128);
13851 t2 = newTemp(Ity_V128);
13852 assign(t1,
13853 binop(Iop_ShrN64x2,
13854 getWReg(ws),
13855 mkU8(n << 3)));
13856 assign(t2,
13857 binop(Iop_ShlN64x2,
13858 getWReg(wd),
13859 mkU8((8 - n) << 3)));
13860 putWReg(wd,
13861 binop(Iop_OrV128,
13862 mkexpr(t1),
13863 mkexpr(t2)));
13866 break;
13868 case 0x30: /* SLDI.W */
13869 DIP("SLDI.W w%d, w%d[%d]", wd, ws, n);
13871 if (n == 0) {
13872 putWReg(wd, getWReg(ws));
13873 } else {
13874 t1 = newTemp(Ity_V128);
13875 t2 = newTemp(Ity_V128);
13876 assign(t1,
13877 binop(Iop_ShrN32x4,
13878 getWReg(ws),
13879 mkU8(n << 3)));
13880 assign(t2,
13881 binop(Iop_ShlN32x4,
13882 getWReg(wd),
13883 mkU8((4 - n) << 3)));
13884 putWReg(wd,
13885 binop(Iop_OrV128,
13886 mkexpr(t1),
13887 mkexpr(t2)));
13890 break;
13892 case 0x38: /* SLDI.D */
13893 DIP("SLDI.D w%d, w%d[%d]", wd, ws, n);
13895 if (n == 0) {
13896 putWReg(wd, getWReg(ws));
13897 } else {
13898 t1 = newTemp(Ity_V128);
13899 t2 = newTemp(Ity_V128);
13900 assign(t1,
13901 binop(Iop_ShrN16x8,
13902 getWReg(ws),
13903 mkU8(n << 3)));
13904 assign(t2,
13905 binop(Iop_ShlN16x8,
13906 getWReg(wd),
13907 mkU8((2 - n) << 3)));
13908 putWReg(wd,
13909 binop(Iop_OrV128,
13910 mkexpr(t1),
13911 mkexpr(t2)));
13914 break;
13916 default:
13917 return -1;
13920 break;
13922 case 0x01: /* SPLATI.df */
13923 switch (df) {
13924 case 0x00: { /* SPLATI.B */
13925 DIP("SPLATI.B w%d, w%d[%d]", wd, ws, n);
13926 t1 = newTemp(Ity_V128);
13927 t2 = newTemp(Ity_V128);
13928 t3 = newTemp(Ity_V128);
13929 t4 = newTemp(Ity_V128);
13931 if (n & 1)
13932 assign(t1,
13933 binop(Iop_InterleaveOddLanes8x16,
13934 getWReg(ws),
13935 getWReg(ws)));
13936 else
13937 assign(t1,
13938 binop(Iop_InterleaveEvenLanes8x16,
13939 getWReg(ws),
13940 getWReg(ws)));
13942 n /= 2;
13944 if (n & 1)
13945 assign(t2,
13946 binop(Iop_InterleaveOddLanes16x8,
13947 mkexpr(t1), mkexpr(t1)));
13948 else
13949 assign(t2,
13950 binop(Iop_InterleaveEvenLanes16x8,
13951 mkexpr(t1), mkexpr(t1)));
13953 n /= 2;
13955 if (n & 1)
13956 assign(t3,
13957 binop(Iop_InterleaveOddLanes32x4,
13958 mkexpr(t2), mkexpr(t2)));
13959 else
13960 assign(t3,
13961 binop(Iop_InterleaveEvenLanes32x4,
13962 mkexpr(t2), mkexpr(t2)));
13964 n /= 2;
13966 if (n & 1)
13967 assign(t4,
13968 binop(Iop_InterleaveHI64x2,
13969 mkexpr(t3), mkexpr(t3)));
13970 else
13971 assign(t4,
13972 binop(Iop_InterleaveLO64x2,
13973 mkexpr(t3), mkexpr(t3)));
13975 putWReg(wd, mkexpr(t4));
13976 break;
13979 case 0x20: { /* SPLATI.H */
13980 DIP("SPLATI.H w%d, w%d[%d]", wd, ws, n);
13981 t1 = newTemp(Ity_V128);
13982 t2 = newTemp(Ity_V128);
13983 t3 = newTemp(Ity_V128);
13985 if (n & 1)
13986 assign(t1,
13987 binop(Iop_InterleaveOddLanes16x8,
13988 getWReg(ws),
13989 getWReg(ws)));
13990 else
13991 assign(t1,
13992 binop(Iop_InterleaveEvenLanes16x8,
13993 getWReg(ws),
13994 getWReg(ws)));
13996 n /= 2;
13998 if (n & 1)
13999 assign(t2,
14000 binop(Iop_InterleaveOddLanes32x4,
14001 mkexpr(t1), mkexpr(t1)));
14002 else
14003 assign(t2,
14004 binop(Iop_InterleaveEvenLanes32x4,
14005 mkexpr(t1), mkexpr(t1)));
14007 n /= 2;
14009 if (n & 1)
14010 assign(t3,
14011 binop(Iop_InterleaveHI64x2,
14012 mkexpr(t2), mkexpr(t2)));
14013 else
14014 assign(t3,
14015 binop(Iop_InterleaveLO64x2,
14016 mkexpr(t2), mkexpr(t2)));
14018 putWReg(wd, mkexpr(t3));
14019 break;
14022 case 0x30: { /* SPLATI.W */
14023 DIP("SPLATI.W w%d, w%d[%d]", wd, ws, n);
14024 t1 = newTemp(Ity_V128);
14025 t2 = newTemp(Ity_V128);
14026 t3 = newTemp(Ity_V128);
14027 assign(t1, getWReg(ws));
14029 if (n & 1)
14030 assign(t2,
14031 binop(Iop_InterleaveOddLanes32x4,
14032 mkexpr(t1), mkexpr(t1)));
14033 else
14034 assign(t2,
14035 binop(Iop_InterleaveEvenLanes32x4,
14036 mkexpr(t1), mkexpr(t1)));
14038 n /= 2;
14040 if (n & 1)
14041 assign(t3,
14042 binop(Iop_InterleaveHI64x2,
14043 mkexpr(t2), mkexpr(t2)));
14044 else
14045 assign(t3,
14046 binop(Iop_InterleaveLO64x2,
14047 mkexpr(t2), mkexpr(t2)));
14049 putWReg(wd, mkexpr(t3));
14050 break;
14053 case 0x38: /* SPLATI.D */
14054 DIP("SPLATI.D w%d, w%d[%d]", wd, ws, n);
14055 t1 = newTemp(Ity_V128);
14056 t3 = newTemp(Ity_V128);
14057 assign(t1, getWReg(ws));
14059 if (n)
14060 assign(t3,
14061 binop(Iop_InterleaveHI64x2,
14062 mkexpr(t1), mkexpr(t1)));
14063 else
14064 assign(t3,
14065 binop(Iop_InterleaveLO64x2,
14066 mkexpr(t1), mkexpr(t1)));
14068 putWReg(wd, mkexpr(t3));
14069 break;
14071 default:
14072 return -1;
14075 break;
14077 case 0x02: /* COPY_S.df */
14078 switch (df) {
14079 case 0x00: /* COPY_S.B */
14080 DIP("COPY_S.B r%d, w%d[%d]", wd, ws, n);
14081 t1 = newTemp(Ity_I8);
14083 switch (n) {
14084 case 0:
14085 assign(t1,
14086 unop(Iop_32to8,
14087 unop(Iop_V128to32,
14088 getWReg(ws))));
14089 break;
14091 case 1:
14092 assign(t1,
14093 unop(Iop_16HIto8,
14094 unop(Iop_32to16,
14095 unop(Iop_V128to32,
14096 getWReg(ws)))));
14097 break;
14099 case 2:
14100 assign(t1,
14101 unop(Iop_16to8,
14102 unop(Iop_32HIto16,
14103 unop(Iop_64to32,
14104 unop(Iop_V128to64,
14105 getWReg(ws))))));
14106 break;
14108 case 3:
14109 assign(t1,
14110 unop(Iop_16HIto8,
14111 unop(Iop_32HIto16,
14112 unop(Iop_64to32,
14113 unop(Iop_V128to64,
14114 getWReg(ws))))));
14115 break;
14117 case 4:
14118 assign(t1,
14119 unop(Iop_16to8,
14120 unop(Iop_32to16,
14121 unop(Iop_64HIto32,
14122 unop(Iop_V128to64,
14123 getWReg(ws))))));
14124 break;
14126 case 5:
14127 assign(t1,
14128 unop(Iop_16HIto8,
14129 unop(Iop_32to16,
14130 unop(Iop_64HIto32,
14131 unop(Iop_V128to64,
14132 getWReg(ws))))));
14133 break;
14135 case 6:
14136 assign(t1,
14137 unop(Iop_16to8,
14138 unop(Iop_32HIto16,
14139 unop(Iop_64HIto32,
14140 unop(Iop_V128to64,
14141 getWReg(ws))))));
14142 break;
14144 case 7:
14145 assign(t1,
14146 unop(Iop_16HIto8,
14147 unop(Iop_32HIto16,
14148 unop(Iop_64HIto32,
14149 unop(Iop_V128to64,
14150 getWReg(ws))))));
14151 break;
14153 case 8:
14154 assign(t1,
14155 unop(Iop_16to8,
14156 unop(Iop_32to16,
14157 unop(Iop_64to32,
14158 unop(Iop_V128HIto64,
14159 getWReg(ws))))));
14160 break;
14162 case 9:
14163 assign(t1,
14164 unop(Iop_16HIto8,
14165 unop(Iop_32to16,
14166 unop(Iop_64to32,
14167 unop(Iop_V128HIto64,
14168 getWReg(ws))))));
14169 break;
14171 case 10:
14172 assign(t1,
14173 unop(Iop_16to8,
14174 unop(Iop_32HIto16,
14175 unop(Iop_64to32,
14176 unop(Iop_V128HIto64,
14177 getWReg(ws))))));
14178 break;
14180 case 11:
14181 assign(t1,
14182 unop(Iop_16HIto8,
14183 unop(Iop_32HIto16,
14184 unop(Iop_64to32,
14185 unop(Iop_V128HIto64,
14186 getWReg(ws))))));
14187 break;
14189 case 12:
14190 assign(t1,
14191 unop(Iop_16to8,
14192 unop(Iop_32to16,
14193 unop(Iop_64HIto32,
14194 unop(Iop_V128HIto64,
14195 getWReg(ws))))));
14196 break;
14198 case 13:
14199 assign(t1,
14200 unop(Iop_16HIto8,
14201 unop(Iop_32to16,
14202 unop(Iop_64HIto32,
14203 unop(Iop_V128HIto64,
14204 getWReg(ws))))));
14205 break;
14207 case 14:
14208 assign(t1,
14209 unop(Iop_16to8,
14210 unop(Iop_32HIto16,
14211 unop(Iop_64HIto32,
14212 unop(Iop_V128HIto64,
14213 getWReg(ws))))));
14214 break;
14216 case 15:
14217 assign(t1,
14218 unop(Iop_16HIto8,
14219 unop(Iop_32HIto16,
14220 unop(Iop_64HIto32,
14221 unop(Iop_V128HIto64,
14222 getWReg(ws))))));
14223 break;
14226 putIReg(wd,
14227 unop(mode64 ? Iop_8Sto64 : Iop_8Sto32,
14228 mkexpr(t1)));
14229 break;
14231 case 0x20: /* COPY_S.H */
14232 DIP("COPY_S.H r%d, w%d[%d]", wd, ws, n);
14233 t1 = newTemp(Ity_I16);
14235 switch (n) {
14236 case 0:
14237 assign(t1,
14238 unop(Iop_32to16,
14239 unop(Iop_64to32,
14240 unop(Iop_V128to64,
14241 getWReg(ws)))));
14242 break;
14244 case 1:
14245 assign(t1,
14246 unop(Iop_32HIto16,
14247 unop(Iop_64to32,
14248 unop(Iop_V128to64,
14249 getWReg(ws)))));
14250 break;
14252 case 2:
14253 assign(t1,
14254 unop(Iop_32to16,
14255 unop(Iop_64HIto32,
14256 unop(Iop_V128to64,
14257 getWReg(ws)))));
14258 break;
14260 case 3:
14261 assign(t1,
14262 unop(Iop_32HIto16,
14263 unop(Iop_64HIto32,
14264 unop(Iop_V128to64,
14265 getWReg(ws)))));
14266 break;
14268 case 4:
14269 assign(t1,
14270 unop(Iop_32to16,
14271 unop(Iop_64to32,
14272 unop(Iop_V128HIto64,
14273 getWReg(ws)))));
14274 break;
14276 case 5:
14277 assign(t1,
14278 unop(Iop_32HIto16,
14279 unop(Iop_64to32,
14280 unop(Iop_V128HIto64,
14281 getWReg(ws)))));
14282 break;
14284 case 6:
14285 assign(t1,
14286 unop(Iop_32to16,
14287 unop(Iop_64HIto32,
14288 unop(Iop_V128HIto64,
14289 getWReg(ws)))));
14290 break;
14292 case 7:
14293 assign(t1,
14294 unop(Iop_32HIto16,
14295 unop(Iop_64HIto32,
14296 unop(Iop_V128HIto64,
14297 getWReg(ws)))));
14298 break;
14301 putIReg(wd,
14302 unop(mode64 ? Iop_16Sto64 : Iop_16Sto32,
14303 mkexpr(t1)));
14304 break;
14306 case 0x30: /* COPY_S.W */
14307 DIP("COPY_S.W r%d, w%d[%d]", wd, ws, n);
14309 switch (n) {
14310 case 0:
14311 putIReg(wd,
14312 mkWidenFrom32(ty,
14313 unop(Iop_V128to32,
14314 getWReg(ws)),
14315 True));
14316 break;
14318 case 1:
14319 t2 = newTemp(Ity_I64);
14320 assign(t2,
14321 unop(Iop_V128to64, getWReg(ws)));
14322 putIReg(wd,
14323 mkWidenFrom32(ty,
14324 unop(Iop_64HIto32,
14325 mkexpr(t2)),
14326 True));
14327 break;
14329 case 2:
14330 t2 = newTemp(Ity_I64);
14331 assign(t2,
14332 unop(Iop_V128HIto64,
14333 getWReg(ws)));
14334 putIReg(wd,
14335 mkWidenFrom32(ty,
14336 unop(Iop_64to32,
14337 mkexpr(t2)),
14338 True));
14339 break;
14341 case 3:
14342 t2 = newTemp(Ity_I64);
14343 assign(t2,
14344 unop(Iop_V128HIto64,
14345 getWReg(ws)));
14346 putIReg(wd,
14347 mkWidenFrom32(ty,
14348 unop(Iop_64HIto32,
14349 mkexpr(t2)),
14350 True));
14351 break;
14353 default:
14354 break;
14357 break;
14359 case 0x38: /* COPY_S.D */
14360 if (mode64) {
14361 DIP("COPY_S.D r%d, w%d[%d]", wd, ws, n);
14363 switch (n) {
14364 case 0:
14365 putIReg(wd,
14366 unop(Iop_V128to64,
14367 getWReg(ws)));
14368 break;
14370 case 1:
14371 putIReg(wd,
14372 unop(Iop_V128HIto64,
14373 getWReg(ws)));
14374 break;
14376 } else {
14377 return -2;
14380 break;
14382 default:
14383 return -1;
14386 break;
14388 case 0x03: { /* COPY_U.df */
14389 switch (df) {
14390 case 0x00: /* COPY_U.B */
14391 DIP("COPY_U.B r%d, w%d[%d]", wd, ws, n);
14392 t1 = newTemp(Ity_I8);
14394 switch (n) {
14395 case 0:
14396 assign(t1,
14397 unop(Iop_16to8,
14398 unop(Iop_32to16,
14399 unop(Iop_64to32,
14400 unop(Iop_V128to64,
14401 getWReg(ws))))));
14402 break;
14404 case 1:
14405 assign(t1,
14406 unop(Iop_16HIto8,
14407 unop(Iop_32to16,
14408 unop(Iop_64to32,
14409 unop(Iop_V128to64,
14410 getWReg(ws))))));
14411 break;
14413 case 2:
14414 assign(t1,
14415 unop(Iop_16to8,
14416 unop(Iop_32HIto16,
14417 unop(Iop_64to32,
14418 unop(Iop_V128to64,
14419 getWReg(ws))))));
14420 break;
14422 case 3:
14423 assign(t1,
14424 unop(Iop_16HIto8,
14425 unop(Iop_32HIto16,
14426 unop(Iop_64to32,
14427 unop(Iop_V128to64,
14428 getWReg(ws))))));
14429 break;
14431 case 4:
14432 assign(t1,
14433 unop(Iop_16to8,
14434 unop(Iop_32to16,
14435 unop(Iop_64HIto32,
14436 unop(Iop_V128to64,
14437 getWReg(ws))))));
14438 break;
14440 case 5:
14441 assign(t1,
14442 unop(Iop_16HIto8,
14443 unop(Iop_32to16,
14444 unop(Iop_64HIto32,
14445 unop(Iop_V128to64,
14446 getWReg(ws))))));
14447 break;
14449 case 6:
14450 assign(t1,
14451 unop(Iop_16to8,
14452 unop(Iop_32HIto16,
14453 unop(Iop_64HIto32,
14454 unop(Iop_V128to64,
14455 getWReg(ws))))));
14456 break;
14458 case 7:
14459 assign(t1,
14460 unop(Iop_16HIto8,
14461 unop(Iop_32HIto16,
14462 unop(Iop_64HIto32,
14463 unop(Iop_V128to64,
14464 getWReg(ws))))));
14465 break;
14467 case 8:
14468 assign(t1,
14469 unop(Iop_16to8,
14470 unop(Iop_32to16,
14471 unop(Iop_64to32,
14472 unop(Iop_V128HIto64,
14473 getWReg(ws))))));
14474 break;
14476 case 9:
14477 assign(t1,
14478 unop(Iop_16HIto8,
14479 unop(Iop_32to16,
14480 unop(Iop_64to32,
14481 unop(Iop_V128HIto64,
14482 getWReg(ws))))));
14483 break;
14485 case 10:
14486 assign(t1,
14487 unop(Iop_16to8,
14488 unop(Iop_32HIto16,
14489 unop(Iop_64to32,
14490 unop(Iop_V128HIto64,
14491 getWReg(ws))))));
14492 break;
14494 case 11:
14495 assign(t1,
14496 unop(Iop_16HIto8,
14497 unop(Iop_32HIto16,
14498 unop(Iop_64to32,
14499 unop(Iop_V128HIto64,
14500 getWReg(ws))))));
14501 break;
14503 case 12:
14504 assign(t1,
14505 unop(Iop_16to8,
14506 unop(Iop_32to16,
14507 unop(Iop_64HIto32,
14508 unop(Iop_V128HIto64,
14509 getWReg(ws))))));
14510 break;
14512 case 13:
14513 assign(t1,
14514 unop(Iop_16HIto8,
14515 unop(Iop_32to16,
14516 unop(Iop_64HIto32,
14517 unop(Iop_V128HIto64,
14518 getWReg(ws))))));
14519 break;
14521 case 14:
14522 assign(t1,
14523 unop(Iop_16to8,
14524 unop(Iop_32HIto16,
14525 unop(Iop_64HIto32,
14526 unop(Iop_V128HIto64,
14527 getWReg(ws))))));
14528 break;
14530 case 15:
14531 assign(t1,
14532 unop(Iop_16HIto8,
14533 unop(Iop_32HIto16,
14534 unop(Iop_64HIto32,
14535 unop(Iop_V128HIto64,
14536 getWReg(ws))))));
14537 break;
14540 putIReg(wd,
14541 unop(mode64 ? Iop_8Uto64 : Iop_8Uto32,
14542 mkexpr(t1)));
14543 break;
14545 case 0x20: /* COPY_U.H */
14546 DIP("COPY_U.H r%d, w%d[%d]", wd, ws, n);
14547 t1 = newTemp(Ity_I16);
14549 switch (n) {
14550 case 0:
14551 assign(t1,
14552 unop(Iop_32to16,
14553 unop(Iop_64to32,
14554 unop(Iop_V128to64,
14555 getWReg(ws)))));
14556 break;
14558 case 1:
14559 assign(t1,
14560 unop(Iop_32HIto16,
14561 unop(Iop_64to32,
14562 unop(Iop_V128to64,
14563 getWReg(ws)))));
14564 break;
14566 case 2:
14567 assign(t1,
14568 unop(Iop_32to16,
14569 unop(Iop_64HIto32,
14570 unop(Iop_V128to64,
14571 getWReg(ws)))));
14572 break;
14574 case 3:
14575 assign(t1,
14576 unop(Iop_32HIto16,
14577 unop(Iop_64HIto32,
14578 unop(Iop_V128to64,
14579 getWReg(ws)))));
14580 break;
14582 case 4:
14583 assign(t1,
14584 unop(Iop_32to16,
14585 unop(Iop_64to32,
14586 unop(Iop_V128HIto64,
14587 getWReg(ws)))));
14588 break;
14590 case 5:
14591 assign(t1,
14592 unop(Iop_32HIto16,
14593 unop(Iop_64to32,
14594 unop(Iop_V128HIto64,
14595 getWReg(ws)))));
14596 break;
14598 case 6:
14599 assign(t1,
14600 unop(Iop_32to16,
14601 unop(Iop_64HIto32,
14602 unop(Iop_V128HIto64,
14603 getWReg(ws)))));
14604 break;
14606 case 7:
14607 assign(t1,
14608 unop(Iop_32HIto16,
14609 unop(Iop_64HIto32,
14610 unop(Iop_V128HIto64,
14611 getWReg(ws)))));
14612 break;
14615 putIReg(wd,
14616 unop(mode64 ? Iop_16Uto64 : Iop_16Uto32,
14617 mkexpr(t1)));
14618 break;
14620 case 0x30: /* COPY_U.W */
14621 DIP("COPY_U.W r%d, w%d[%d]", wd, ws, n);
14623 switch (n) {
14624 case 0:
14625 putIReg(wd,
14626 mkWidenFrom32(ty,
14627 unop(Iop_V128to32,
14628 getWReg(ws)),
14629 False));
14630 break;
14632 case 1:
14633 t2 = newTemp(Ity_I64);
14634 assign(t2,
14635 unop(Iop_V128to64,
14636 getWReg(ws)));
14637 putIReg(wd,
14638 mkWidenFrom32(ty,
14639 unop(Iop_64HIto32,
14640 mkexpr(t2)),
14641 False));
14642 break;
14644 case 2:
14645 t2 = newTemp(Ity_I64);
14646 assign(t2,
14647 unop(Iop_V128HIto64,
14648 getWReg(ws)));
14649 putIReg(wd,
14650 mkWidenFrom32(ty,
14651 unop(Iop_64to32,
14652 mkexpr(t2)),
14653 False));
14654 break;
14656 case 3:
14657 t2 = newTemp(Ity_I64);
14658 assign(t2,
14659 unop(Iop_V128HIto64,
14660 getWReg(ws)));
14661 putIReg(wd,
14662 mkWidenFrom32(ty,
14663 unop(Iop_64HIto32,
14664 mkexpr(t2)),
14665 False));
14666 break;
14668 default:
14669 break;
14672 break;
14674 default:
14675 return -1;
14678 break;
14681 case 0x04: { /* INSERT.df */
14682 t5 = newTemp(Ity_I64);
14683 UInt hi = 1;
14684 ULong mask;
14685 IRTemp *src, *dst;
14686 assign(t5, mode64 ? getIReg(ws) :
14687 unop(Iop_32Uto64, getIReg(ws)));
14689 if (df == 0x38) { /* INSERT.D */
14690 if (mode64) {
14691 DIP("INSERT.D w%d[%d], r%d", wd, n, ws);
14693 if (n == 0) {
14694 putWReg(wd,
14695 binop(Iop_64HLtoV128,
14696 unop(Iop_V128HIto64,
14697 getWReg(wd)),
14698 mkexpr(t5)));
14699 } else {
14700 putWReg(wd,
14701 binop(Iop_64HLtoV128,
14702 mkexpr(t5),
14703 unop(Iop_V128to64,
14704 getWReg(wd))));
14707 break;
14708 } else {
14709 return -2;
14711 } else {
14712 t1 = newTemp(Ity_I64);
14713 t2 = newTemp(Ity_I64);
14714 assign(t1, unop(Iop_V128to64, getWReg(wd)));
14715 assign(t2, unop(Iop_V128HIto64, getWReg(wd)));
14718 switch (df) {
14719 case 0x00: /* INSERT.B */
14720 DIP("INSERT.B w%d[%d], r%d", wd, n, ws);
14722 if (n >= 8) {
14723 n -= 8;
14724 } else {
14725 hi = 0;
14728 n <<= 3;
14729 mask = 0xFFull;
14730 break;
14732 case 0x20: /* INSERT.H */
14733 DIP("INSERT.H w%d[%d], r%d", wd, n, ws);
14735 if (n >= 4) {
14736 n -= 4;
14737 } else {
14738 hi = 0;
14741 n <<= 4;
14742 mask = 0xFFFFull;
14743 break;
14745 case 0x30: /* INSERT.W */
14746 DIP("INSERT.W w%d[%d], r%d", wd, n, ws);
14748 if (n >= 2) {
14749 n -= 2;
14750 } else {
14751 hi = 0;
14754 n <<= 5;
14755 mask = 0xFFFFFFFFull;
14756 break;
14758 default:
14759 return -1;
14762 if (hi) {
14763 t4 = newTemp(Ity_I64);
14764 src = &t2;
14765 dst = &t4;
14766 t3 = t1;
14767 } else {
14768 t3 = newTemp(Ity_I64);
14769 src = &t1;
14770 dst = &t3;
14771 t4 = t2;
14774 mask <<= n;
14775 assign(*dst,
14776 binop(Iop_Or64,
14777 binop(Iop_And64, mkexpr(*src), mkU64(~mask)),
14778 binop(Iop_And64,
14779 binop(Iop_Shl64, mkexpr(t5), mkU8(n)),
14780 mkU64(mask))));
14781 putWReg(wd,
14782 binop(Iop_64HLtoV128, mkexpr(t4), mkexpr(t3)));
14783 break;
14786 case 0x05: { /* INSVE.df */
14787 switch (df) {
14788 case 0x00: { /* INSVE.B */
14789 DIP("INSVE.B w%d[%d], w%d[0]", wd, n, ws);
14790 t1 = newTemp(Ity_V128);
14791 t2 = newTemp(Ity_V128);
14792 assign(t1, getWReg(wd));
14793 assign(t2, getWReg(ws));
14794 Int i;
14795 IRTemp tmp[16];
14797 for (i = 0; i < 16; i++) {
14798 tmp[i] = newTemp(Ity_I8);
14800 if (n == i)
14801 assign(tmp[i],
14802 binop(Iop_GetElem8x16,
14803 mkexpr(t2), mkU8(0x0)));
14804 else
14805 assign(tmp[i],
14806 binop(Iop_GetElem8x16,
14807 mkexpr(t1), mkU8(i)));
14810 putWReg(wd,
14811 binop(Iop_64HLtoV128,
14812 binop(Iop_32HLto64,
14813 binop(Iop_16HLto32,
14814 binop(Iop_8HLto16,
14815 mkexpr(tmp[15]),
14816 mkexpr(tmp[14])),
14817 binop(Iop_8HLto16,
14818 mkexpr(tmp[13]),
14819 mkexpr(tmp[12]))),
14820 binop(Iop_16HLto32,
14821 binop(Iop_8HLto16,
14822 mkexpr(tmp[11]),
14823 mkexpr(tmp[10])),
14824 binop(Iop_8HLto16,
14825 mkexpr(tmp[9]),
14826 mkexpr(tmp[8])))),
14827 binop(Iop_32HLto64,
14828 binop(Iop_16HLto32,
14829 binop(Iop_8HLto16,
14830 mkexpr(tmp[7]),
14831 mkexpr(tmp[6])),
14832 binop(Iop_8HLto16,
14833 mkexpr(tmp[5]),
14834 mkexpr(tmp[4]))),
14835 binop(Iop_16HLto32,
14836 binop(Iop_8HLto16,
14837 mkexpr(tmp[3]),
14838 mkexpr(tmp[2])),
14839 binop(Iop_8HLto16,
14840 mkexpr(tmp[1]),
14841 mkexpr(tmp[0]))))));
14842 break;
14845 case 0x20: { /* INSVE.H */
14846 DIP("INSVE.H w%d[%d], r%d[0]", wd, n, ws);
14847 t1 = newTemp(Ity_V128);
14848 t2 = newTemp(Ity_V128);
14849 assign(t1, getWReg(wd));
14850 assign(t2, getWReg(ws));
14851 Int i;
14852 IRTemp tmp[8];
14854 for (i = 0; i < 8; i++) {
14855 tmp[i] = newTemp(Ity_I16);
14857 if (n == i)
14858 assign(tmp[i],
14859 binop(Iop_GetElem16x8,
14860 mkexpr(t2), mkU8(0x0)));
14861 else
14862 assign(tmp[i],
14863 binop(Iop_GetElem16x8,
14864 mkexpr(t1), mkU8(i)));
14867 putWReg(wd,
14868 binop(Iop_64HLtoV128,
14869 binop(Iop_32HLto64,
14870 binop(Iop_16HLto32,
14871 mkexpr(tmp[7]),
14872 mkexpr(tmp[6])),
14873 binop(Iop_16HLto32,
14874 mkexpr(tmp[5]),
14875 mkexpr(tmp[4]))),
14876 binop(Iop_32HLto64,
14877 binop(Iop_16HLto32,
14878 mkexpr(tmp[3]),
14879 mkexpr(tmp[2])),
14880 binop(Iop_16HLto32,
14881 mkexpr(tmp[1]),
14882 mkexpr(tmp[0])))));
14883 break;
14886 case 0x30: { /* INSVE.W */
14887 DIP("INSVE.W w%d[%d], r%d[0]", wd, n, ws);
14888 t1 = newTemp(Ity_V128);
14889 t2 = newTemp(Ity_V128);
14890 assign(t1, getWReg(wd));
14891 assign(t2, getWReg(ws));
14892 Int i;
14893 IRTemp tmp[4];
14895 for (i = 0; i < 4; i++) {
14896 tmp[i] = newTemp(Ity_I32);
14898 if (n == i)
14899 assign(tmp[i],
14900 binop(Iop_GetElem32x4,
14901 mkexpr(t2), mkU8(0x0)));
14902 else
14903 assign(tmp[i],
14904 binop(Iop_GetElem32x4,
14905 mkexpr(t1), mkU8(i)));
14908 putWReg(wd,
14909 binop(Iop_64HLtoV128,
14910 binop(Iop_32HLto64,
14911 mkexpr(tmp[3]),
14912 mkexpr(tmp[2])),
14913 binop(Iop_32HLto64,
14914 mkexpr(tmp[1]),
14915 mkexpr(tmp[0]))));
14916 break;
14919 case 0x38: { /* INSVE.D */
14920 DIP("INSVE.D w%d[%d], r%d[0]", wd, n, ws);
14921 t1 = newTemp(Ity_V128);
14922 t2 = newTemp(Ity_V128);
14923 assign(t1, getWReg(wd));
14924 assign(t2, getWReg(ws));
14925 Int i;
14926 IRTemp tmp[2];
14928 for (i = 0; i < 2; i++) {
14929 tmp[i] = newTemp(Ity_I64);
14931 if (n == i)
14932 assign(tmp[i],
14933 binop(Iop_GetElem64x2,
14934 mkexpr(t2), mkU8(0x0)));
14935 else
14936 assign(tmp[i],
14937 binop(Iop_GetElem64x2,
14938 mkexpr(t1), mkU8(i)));
14941 putWReg(wd,
14942 binop(Iop_64HLtoV128,
14943 mkexpr(tmp[1]), mkexpr(tmp[0])));
14944 break;
14948 break;
14951 default:
14952 return -1;
14956 return 0;
14959 static Int msa_VEC(UInt cins, UChar wd, UChar ws) /* VEC */
14961 IRTemp t1, t2, t3;
14962 UShort operation;
14963 UChar wt;
14965 vassert((cins & 0x03000000) == 0);
14967 operation = (cins & 0x03E00000) >> 21;
14968 wt = (cins & 0x001F0000) >> 16;
14970 switch (operation) {
14971 case 0x00: { /* AND.V */
14972 DIP("AND.V w%d, w%d, w%d", wd, ws, wt);
14973 t1 = newTemp(Ity_V128);
14974 t2 = newTemp(Ity_V128);
14975 t3 = newTemp(Ity_V128);
14976 assign(t1, getWReg(ws));
14977 assign(t2, getWReg(wt));
14978 assign(t3, binop(Iop_AndV128, mkexpr(t1), mkexpr(t2)));
14979 putWReg(wd, mkexpr(t3));
14980 break;
14983 case 0x01: { /* OR.V */
14984 DIP("OR.V w%d, w%d, w%d", wd, ws, wt);
14985 t1 = newTemp(Ity_V128);
14986 t2 = newTemp(Ity_V128);
14987 t3 = newTemp(Ity_V128);
14988 assign(t1, getWReg(ws));
14989 assign(t2, getWReg(wt));
14990 assign(t3, binop(Iop_OrV128, mkexpr(t1), mkexpr(t2)));
14991 putWReg(wd, mkexpr(t3));
14992 break;
14995 case 0x02: { /* NOR.V */
14996 DIP("NOR.V w%d, w%d, w%d", wd, ws, wt);
14997 t1 = newTemp(Ity_V128);
14998 t2 = newTemp(Ity_V128);
14999 t3 = newTemp(Ity_V128);
15000 assign(t1, getWReg(ws));
15001 assign(t2, getWReg(wt));
15002 assign(t3,
15003 unop(Iop_NotV128,
15004 binop(Iop_OrV128, mkexpr(t1), mkexpr(t2))));
15005 putWReg(wd, mkexpr(t3));
15006 break;
15009 case 0x03: { /* XOR.V */
15010 DIP("XOR.V w%d, w%d, w%d", wd, ws, wt);
15011 t1 = newTemp(Ity_V128);
15012 t2 = newTemp(Ity_V128);
15013 t3 = newTemp(Ity_V128);
15014 assign(t1, getWReg(ws));
15015 assign(t2, getWReg(wt));
15016 assign(t3, binop(Iop_XorV128, mkexpr(t1), mkexpr(t2)));
15017 putWReg(wd, mkexpr(t3));
15018 break;
15021 case 0x04: { /* BMNZ (ws AND wt) OR (wd AND NOT wt) */
15022 DIP("BMNZ.V w%d, w%d, w%d", wd, ws, wt);
15023 t1 = newTemp(Ity_V128);
15024 t2 = newTemp(Ity_V128);
15025 t3 = newTemp(Ity_V128);
15026 assign(t1,
15027 binop(Iop_AndV128,
15028 getWReg(ws), getWReg(wt)));
15029 assign(t2,
15030 binop(Iop_AndV128,
15031 getWReg(wd),
15032 unop(Iop_NotV128, getWReg(wt))));
15033 assign(t3, binop(Iop_OrV128, mkexpr(t1), mkexpr(t2)));
15034 putWReg(wd, mkexpr(t3));
15035 break;
15038 case 0x05: { /* BMZ.V (ws AND NOT wt) OR (wd AND wt) */
15039 DIP("BMZ.V w%d, w%d, w%d", wd, ws, wt);
15040 t1 = newTemp(Ity_V128);
15041 t2 = newTemp(Ity_V128);
15042 t3 = newTemp(Ity_V128);
15043 assign(t1,
15044 binop(Iop_AndV128,
15045 getWReg(wd), getWReg(wt)));
15046 assign(t2,
15047 binop(Iop_AndV128,
15048 getWReg(ws),
15049 unop(Iop_NotV128, getWReg(wt))));
15050 assign(t3, binop(Iop_OrV128, mkexpr(t1), mkexpr(t2)));
15051 putWReg(wd, mkexpr(t3));
15052 break;
15055 case 0x06: { /* BSEL (ws AND NOT wd) OR (wt AND wd) */
15056 DIP("BSEL.V w%d, w%d, w%d", wd, ws, wt);
15057 t1 = newTemp(Ity_V128);
15058 t2 = newTemp(Ity_V128);
15059 t3 = newTemp(Ity_V128);
15060 assign(t1,
15061 binop(Iop_AndV128,
15062 getWReg(wd), getWReg(wt)));
15063 assign(t2,
15064 binop(Iop_AndV128,
15065 getWReg(ws),
15066 unop(Iop_NotV128, getWReg(wd))));
15067 assign(t3, binop(Iop_OrV128, mkexpr(t1), mkexpr(t2)));
15068 putWReg(wd, mkexpr(t3));
15069 break;
15072 default:
15073 return -1;
15076 return 0;
15079 static Int msa_2R(UInt cins, UChar wd, UChar ws) /* 2R */
15081 IRTemp t1, t2, t3, t4;
15082 IRType ty;
15083 UShort operation;
15084 UChar df;
15086 vassert((cins & 0x00200000) == 0);
15088 operation = (cins & 0x03FC0000) >> 18;
15089 df = (cins & 0x00030000) >> 16;
15090 ty = mode64 ? Ity_I64 : Ity_I32;
15092 switch (operation) {
15093 case 0xC0: { /* FILL.df */
15094 t1 = newTemp(Ity_I64);
15096 switch (df) {
15097 case 0x00: /* FILL.B */
15098 DIP("FILL.B w%d, r%d", wd, ws);
15099 t2 = newTemp(Ity_I32);
15100 t3 = newTemp(Ity_I16);
15101 t4 = newTemp(Ity_I8);
15102 assign(t4, mkNarrowTo8(ty, getIReg(ws)));
15103 assign(t3,
15104 binop(Iop_8HLto16, mkexpr(t4), mkexpr(t4)));
15105 assign(t2,
15106 binop(Iop_16HLto32, mkexpr(t3), mkexpr(t3)));
15107 assign(t1,
15108 binop(Iop_32HLto64, mkexpr(t2), mkexpr(t2)));
15109 break;
15111 case 0x01: /* FILL.H */
15112 DIP("FILL.H w%d, r%d", wd, ws);
15113 t2 = newTemp(Ity_I32);
15114 t3 = newTemp(Ity_I16);
15115 assign(t3, mkNarrowTo16(ty, getIReg(ws)));
15116 assign(t2,
15117 binop(Iop_16HLto32, mkexpr(t3), mkexpr(t3)));
15118 assign(t1,
15119 binop(Iop_32HLto64, mkexpr(t2), mkexpr(t2)));
15120 break;
15122 case 0x02: /* FILL.W */
15123 DIP("FILL.W w%d, r%d", wd, ws);
15124 t2 = newTemp(Ity_I32);
15125 assign(t2, mkNarrowTo32(ty, getIReg(ws)));
15126 assign(t1,
15127 binop(Iop_32HLto64, mkexpr(t2), mkexpr(t2)));
15128 break;
15130 case 0x03: /* FILL.D */
15131 if (mode64) {
15132 DIP("FILL.W w%d, r%d", wd, ws);
15133 t2 = newTemp(Ity_I32);
15134 assign(t1, getIReg(ws));
15135 } else {
15136 return -2;
15139 break;
15141 default:
15142 return -1;
15145 putWReg(wd,
15146 binop(Iop_64HLtoV128, mkexpr(t1), mkexpr(t1)));
15147 break;
15150 case 0xC1: { /* PCNT.df */
15151 switch (df) {
15152 case 0x00: /* PCNT.B */
15153 DIP("PCNT.B w%d, r%d", wd, ws);
15154 putWReg(wd,
15155 unop(Iop_Cnt8x16, getWReg(ws)));
15156 break;
15158 case 0x01: /* PCNT.H */
15159 DIP("PCNT.H w%d, r%d", wd, ws);
15160 t1 = newTemp(Ity_V128);
15161 t2 = newTemp(Ity_V128);
15162 assign(t1, unop(Iop_Cnt8x16, getWReg(ws)));
15163 assign(t2,
15164 binop(Iop_Add16x8,
15165 binop(Iop_AndV128,
15166 mkexpr(t1),
15167 binop(Iop_64HLtoV128,
15168 mkU64(0x00FF00FF00FF00FFULL),
15169 mkU64(0x00FF00FF00FF00FFULL))),
15170 binop(Iop_AndV128,
15171 binop(Iop_ShrN16x8,
15172 mkexpr(t1), mkU8(8)),
15173 binop(Iop_64HLtoV128,
15174 mkU64(0x00FF00FF00FF00FFULL),
15175 mkU64(0x00FF00FF00FF00FFULL)))));
15176 putWReg(wd, mkexpr(t2));
15177 break;
15179 case 0x02: /* PCNT.W */
15180 DIP("PCNT.W w%d, r%d", wd, ws);
15181 t1 = newTemp(Ity_V128);
15182 t2 = newTemp(Ity_V128);
15183 t3 = newTemp(Ity_V128);
15184 assign(t1, unop(Iop_Cnt8x16, getWReg(ws)));
15185 assign(t2,
15186 binop(Iop_Add32x4,
15187 binop(Iop_AndV128,
15188 mkexpr(t1),
15189 binop(Iop_64HLtoV128,
15190 mkU64(0x00FF00FF00FF00FFULL),
15191 mkU64(0x00FF00FF00FF00FFULL))),
15192 binop(Iop_AndV128,
15193 binop(Iop_ShrN32x4,
15194 mkexpr(t1), mkU8(8)),
15195 binop(Iop_64HLtoV128,
15196 mkU64(0x00FF00FF00FF00FFULL),
15197 mkU64(0x00FF00FF00FF00FFULL)))));
15198 assign(t3,
15199 binop(Iop_Add32x4,
15200 binop(Iop_AndV128,
15201 mkexpr(t2),
15202 binop(Iop_64HLtoV128,
15203 mkU64(0x0000FFFF0000FFFFULL),
15204 mkU64(0x0000FFFF0000FFFFULL))),
15205 binop(Iop_AndV128,
15206 binop(Iop_ShrN32x4,
15207 mkexpr(t2), mkU8(16)),
15208 binop(Iop_64HLtoV128,
15209 mkU64(0x0000FFFF0000FFFFULL),
15210 mkU64(0x0000FFFF0000FFFFULL)))));
15211 putWReg(wd, mkexpr(t3));
15212 break;
15214 case 0x03: /* PCNT.D */
15215 DIP("PCNT.D w%d, r%d", wd, ws);
15216 t1 = newTemp(Ity_V128);
15217 t2 = newTemp(Ity_V128);
15218 t3 = newTemp(Ity_V128);
15219 t4 = newTemp(Ity_V128);;
15220 assign(t1, unop(Iop_Cnt8x16, getWReg(ws)));
15221 assign(t2,
15222 binop(Iop_Add64x2,
15223 binop(Iop_AndV128,
15224 mkexpr(t1),
15225 binop(Iop_64HLtoV128,
15226 mkU64(0x00FF00FF00FF00FFULL),
15227 mkU64(0x00FF00FF00FF00FFULL))),
15228 binop(Iop_AndV128,
15229 binop(Iop_ShrN64x2,
15230 mkexpr(t1), mkU8(8)),
15231 binop(Iop_64HLtoV128,
15232 mkU64(0x00FF00FF00FF00FFULL),
15233 mkU64(0x00FF00FF00FF00FFULL)))));
15234 assign(t3,
15235 binop(Iop_Add64x2,
15236 binop(Iop_AndV128,
15237 mkexpr(t2),
15238 binop(Iop_64HLtoV128,
15239 mkU64(0x0000FFFF0000FFFFULL),
15240 mkU64(0x0000FFFF0000FFFFULL))),
15241 binop(Iop_AndV128,
15242 binop(Iop_ShrN64x2,
15243 mkexpr(t2), mkU8(16)),
15244 binop(Iop_64HLtoV128,
15245 mkU64(0x0000FFFF0000FFFFULL),
15246 mkU64(0x0000FFFF0000FFFFULL)))));
15247 assign(t4,
15248 binop(Iop_Add64x2,
15249 binop(Iop_AndV128,
15250 mkexpr(t3),
15251 binop(Iop_64HLtoV128,
15252 mkU64(0x00000000FFFFFFFFULL),
15253 mkU64(0x00000000FFFFFFFFULL))),
15254 binop(Iop_AndV128,
15255 binop(Iop_ShrN64x2,
15256 mkexpr(t3), mkU8(32)),
15257 binop(Iop_64HLtoV128,
15258 mkU64(0x00000000FFFFFFFFULL),
15259 mkU64(0x00000000FFFFFFFFULL)))));
15260 putWReg(wd, mkexpr(t4));
15261 break;
15263 default:
15264 return -1;
15267 break;
15270 case 0xC2: { /* NLOC.df */
15271 switch (df) {
15272 case 0x00: /* NLOC.B */
15273 DIP("NLOC.B w%d, w%d", wd, ws);
15274 putWReg(wd,
15275 unop(Iop_Cls8x16, getWReg(ws)));
15276 break;
15278 case 0x01: /* NLOC.H */
15279 DIP("NLOC.H w%d, w%d", wd, ws);
15280 putWReg(wd,
15281 unop(Iop_Cls16x8, getWReg(ws)));
15282 break;
15284 case 0x02: /* NLOC.W */
15285 DIP("NLOC.W w%d, w%d", wd, ws);
15286 putWReg(wd,
15287 unop(Iop_Cls32x4, getWReg(ws)));
15288 break;
15290 case 0x03: /* NLOC.D */
15291 DIP("NLOC.D w%d, w%d", wd, ws);
15292 t1 = newTemp(Ity_V128);
15293 assign(t1, unop(Iop_NotV128, getWReg(ws)));
15294 putWReg(wd, unop(Iop_Clz64x2, mkexpr(t1)));
15295 break;
15297 default:
15298 return -1;
15301 break;
15304 case 0xC3: { /* NLZC.df */
15305 switch (df) {
15306 case 0x00: /* NLZC.B */
15307 DIP("NLZC.W w%d, w%d", wd, ws);
15308 putWReg(wd,
15309 unop(Iop_Clz8x16, getWReg(ws)));
15310 break;
15312 case 0x01: /* NLZC.H */
15313 DIP("NLZC.H w%d, w%d", wd, ws);
15314 putWReg(wd,
15315 unop(Iop_Clz16x8, getWReg(ws)));
15316 break;
15318 case 0x02: /* NLZC.W */
15319 DIP("NLZC.W w%d, w%d", wd, ws);
15320 putWReg(wd,
15321 unop(Iop_Clz32x4, getWReg(ws)));
15322 break;
15324 case 0x03: {/* NLZC.D */
15325 putWReg(wd,
15326 unop(Iop_Clz64x2, getWReg(ws)));
15327 break;
15330 default:
15331 return -1;
15334 break;
15337 default:
15338 return -1;
15341 return 0;
15344 static Int msa_2RF(UInt cins, UChar wd, UChar ws) /* 2RF */
15346 IRTemp t1, t2, t3, t4, t5;
15347 UShort operation;
15348 UChar df, wt;
15350 operation = (cins & 0x03FE0000) >> 17;
15351 df = (cins & 0x00010000) >> 16;
15352 wt = (cins & 0x001F0000) >> 16;
15354 switch (operation) {
15356 case 0x190: { /* FCLASS.df */
15357 IRTemp t0 = newTemp(Ity_V128);
15358 t1 = newTemp(Ity_V128);
15359 t2 = newTemp(Ity_V128);
15360 t3 = newTemp(Ity_V128);
15361 t4 = newTemp(Ity_V128);
15362 t5 = newTemp(Ity_V128);
15364 switch (df) {
15365 case 0x00: { /* FCLASS.W */
15366 DIP("FCLASS.W w%d, w%d", wd, ws);
15367 assign(t0,
15368 binop(Iop_CmpEQ32x4,
15369 binop(Iop_AndV128,
15370 getWReg(ws),
15371 binop(Iop_64HLtoV128,
15372 mkU64(0x7F8000007F800000ull),
15373 mkU64(0x7F8000007F800000ull))),
15374 binop(Iop_64HLtoV128,
15375 mkU64(0ull), mkU64(0ull))));
15376 assign(t1,
15377 binop(Iop_CmpEQ32x4,
15378 binop(Iop_AndV128,
15379 getWReg(ws),
15380 binop(Iop_64HLtoV128,
15381 mkU64(0x7F8000007F800000ull),
15382 mkU64(0x7F8000007F800000ull))),
15383 binop(Iop_64HLtoV128,
15384 mkU64(0x7F8000007F800000ull),
15385 mkU64(0x7F8000007F800000ull))));
15386 assign(t2,
15387 binop(Iop_SarN32x4,
15388 getWReg(ws), mkU8(31)));
15389 assign(t3,
15390 binop(Iop_CmpEQ32x4,
15391 binop(Iop_AndV128,
15392 getWReg(ws),
15393 binop(Iop_64HLtoV128,
15394 mkU64(0x0040000000400000ull),
15395 mkU64(0x0040000000400000ull))),
15396 binop(Iop_64HLtoV128,
15397 mkU64(0x0040000000400000ull),
15398 mkU64(0x0040000000400000ull))));
15399 assign(t4,
15400 binop(Iop_CmpEQ32x4,
15401 binop(Iop_AndV128,
15402 getWReg(ws),
15403 binop(Iop_64HLtoV128,
15404 mkU64(0x007FFFFF007FFFFFULL),
15405 mkU64(0x007FFFFF007FFFFFULL))),
15406 binop(Iop_64HLtoV128,
15407 mkU64(0ull), mkU64(0ull))));
15408 assign(t5,
15409 binop(Iop_Shl32x4,
15410 binop(Iop_OrV128,
15411 binop(Iop_AndV128,
15412 mkexpr(t1),
15413 binop(Iop_AndV128,
15414 mkexpr(t4),
15415 binop(Iop_64HLtoV128,
15416 mkU64(0x100000001ull),
15417 mkU64(0x100000001ull)))),
15418 binop(Iop_OrV128,
15419 binop(Iop_AndV128,
15420 mkexpr(t0),
15421 binop(Iop_OrV128,
15422 binop(Iop_AndV128,
15423 mkexpr(t4),
15424 binop(Iop_64HLtoV128,
15425 mkU64(0x800000008ull),
15426 mkU64(0x800000008ull))),
15427 binop(Iop_AndV128,
15428 unop(Iop_NotV128,
15429 mkexpr(t4)),
15430 binop(Iop_64HLtoV128,
15431 mkU64(0x400000004ull),
15432 mkU64(0x400000004ull))))),
15433 binop(Iop_AndV128,
15434 unop(Iop_NotV128,
15435 mkexpr(t1)),
15436 binop(Iop_AndV128,
15437 unop(Iop_NotV128,
15438 mkexpr(t0)),
15439 binop(Iop_64HLtoV128,
15440 mkU64(0x200000002ull),
15441 mkU64(0x200000002ull)))))),
15442 binop(Iop_OrV128,
15443 binop(Iop_AndV128,
15444 mkexpr(t2),
15445 binop(Iop_64HLtoV128,
15446 mkU64(0x200000002ull),
15447 mkU64(0x200000002ull))),
15448 binop(Iop_AndV128,
15449 unop(Iop_NotV128,
15450 mkexpr(t2)),
15451 binop(Iop_64HLtoV128,
15452 mkU64(0x600000006ull),
15453 mkU64(0x600000006ull))))));
15454 putWReg(wd,
15455 binop(Iop_OrV128,
15456 mkexpr(t5),
15457 binop(Iop_AndV128,
15458 binop(Iop_CmpEQ32x4,
15459 mkexpr(t5),
15460 binop(Iop_64HLtoV128,
15461 mkU64(0ull),
15462 mkU64(0ull))),
15463 binop(Iop_OrV128,
15464 binop(Iop_AndV128,
15465 mkexpr(t3),
15466 binop(Iop_64HLtoV128,
15467 mkU64(0x100000001ull),
15468 mkU64(0x100000001ull))),
15469 binop(Iop_AndV128,
15470 unop(Iop_NotV128, mkexpr(t3)),
15471 binop(Iop_64HLtoV128,
15472 mkU64(0x200000002ull),
15473 mkU64(0x200000002ull)))))));
15474 break;
15477 case 0x01: { /* FCLASS.D */
15478 DIP("FCLASS.D w%d, w%d", wd, ws);
15479 assign(t0,
15480 binop(Iop_CmpEQ64x2,
15481 binop(Iop_AndV128,
15482 getWReg(ws),
15483 binop(Iop_64HLtoV128,
15484 mkU64(0x7FF0000000000000ull),
15485 mkU64(0x7FF0000000000000ull))),
15486 binop(Iop_64HLtoV128,
15487 mkU64(0ull), mkU64(0ull))));
15488 assign(t1,
15489 binop(Iop_CmpEQ64x2,
15490 binop(Iop_AndV128,
15491 getWReg(ws),
15492 binop(Iop_64HLtoV128,
15493 mkU64(0x7FF0000000000000ull),
15494 mkU64(0x7FF0000000000000ull))),
15495 binop(Iop_64HLtoV128,
15496 mkU64(0x7FF0000000000000ull),
15497 mkU64(0x7FF0000000000000ull))));
15498 assign(t2,
15499 binop(Iop_SarN64x2,
15500 getWReg(ws), mkU8(63)));
15501 assign(t3,
15502 binop(Iop_CmpEQ64x2,
15503 binop(Iop_AndV128,
15504 getWReg(ws),
15505 binop(Iop_64HLtoV128,
15506 mkU64(0x0008000000000000ull),
15507 mkU64(0x0008000000000000ull))),
15508 binop(Iop_64HLtoV128,
15509 mkU64(0x0008000000000000ull),
15510 mkU64(0x0008000000000000ull))));
15511 assign(t4,
15512 binop(Iop_CmpEQ64x2,
15513 binop(Iop_AndV128,
15514 getWReg(ws),
15515 binop(Iop_64HLtoV128,
15516 mkU64(0x000FFFFFFFFFFFFFULL),
15517 mkU64(0x000FFFFFFFFFFFFFULL))),
15518 binop(Iop_64HLtoV128,
15519 mkU64(0ull), mkU64(0ull))));
15520 assign(t5,
15521 binop(Iop_Shl64x2,
15522 binop(Iop_OrV128,
15523 binop(Iop_AndV128,
15524 mkexpr(t1),
15525 binop(Iop_AndV128,
15526 mkexpr(t4),
15527 binop(Iop_64HLtoV128,
15528 mkU64(1ull),
15529 mkU64(1ull)))),
15530 binop(Iop_OrV128,
15531 binop(Iop_AndV128,
15532 mkexpr(t0),
15533 binop(Iop_OrV128,
15534 binop(Iop_AndV128,
15535 mkexpr(t4),
15536 binop(Iop_64HLtoV128,
15537 mkU64(8ull),
15538 mkU64(8ull))),
15539 binop(Iop_AndV128,
15540 unop(Iop_NotV128,
15541 mkexpr(t4)),
15542 binop(Iop_64HLtoV128,
15543 mkU64(4ull),
15544 mkU64(4ull))))),
15545 binop(Iop_AndV128,
15546 unop(Iop_NotV128,
15547 mkexpr(t1)),
15548 binop(Iop_AndV128,
15549 unop(Iop_NotV128,
15550 mkexpr(t0)),
15551 binop(Iop_64HLtoV128,
15552 mkU64(2ull),
15553 mkU64(2ull)))))),
15554 binop(Iop_OrV128,
15555 binop(Iop_AndV128,
15556 mkexpr(t2),
15557 binop(Iop_64HLtoV128,
15558 mkU64(2ull),
15559 mkU64(2ull))),
15560 binop(Iop_AndV128,
15561 unop(Iop_NotV128,
15562 mkexpr(t2)),
15563 binop(Iop_64HLtoV128,
15564 mkU64(6ull),
15565 mkU64(6ull))))));
15566 putWReg(wd,
15567 binop(Iop_OrV128,
15568 mkexpr(t5),
15569 binop(Iop_AndV128,
15570 binop(Iop_CmpEQ64x2,
15571 mkexpr(t5),
15572 binop(Iop_64HLtoV128,
15573 mkU64(0ull),
15574 mkU64(0ull))),
15575 binop(Iop_OrV128,
15576 binop(Iop_AndV128,
15577 mkexpr(t3),
15578 binop(Iop_64HLtoV128,
15579 mkU64(1ull),
15580 mkU64(1ull))),
15581 binop(Iop_AndV128,
15582 unop(Iop_NotV128,
15583 mkexpr(t3)),
15584 binop(Iop_64HLtoV128,
15585 mkU64(2ull),
15586 mkU64(2ull)))))));
15587 break;
15590 default:
15591 return -1;
15594 break;
15597 case 0x191: { /* FTRUNC_S.df */
15598 switch (df) {
15599 case 0x00: { /* FTRUNC_S.W */
15600 DIP("FTRUNC_S.W w%d, w%d", wd, ws);
15601 calculateMSACSR(ws, wd, FTRUNCSW, 1);
15602 putWReg(wd, unop(Iop_F32toI32Sx4_RZ, getWReg(ws)));
15603 break;
15606 case 0x01: { /* FTRUNC_S.D */
15607 DIP("FTRUNC_S.D w%d, w%d", wd, ws);
15608 calculateMSACSR(ws, wd, FTRUNCSD, 1);
15609 t1 = newTemp(Ity_I64);
15610 t2 = newTemp(Ity_I64);
15611 t3 = newTemp(Ity_V128);
15612 assign(t3,
15613 binop(Iop_AndV128,
15614 unop(Iop_NotV128,
15615 binop(Iop_CmpUN64Fx2,
15616 getWReg(ws),
15617 getWReg(ws))),
15618 binop(Iop_Max64Fx2,
15619 getWReg(ws),
15620 binop(Iop_64HLtoV128,
15621 mkU64(0xC3E0000000000000),
15622 mkU64(0xC3E0000000000000)))));
15623 assign(t1,
15624 binop(Iop_F64toI64S, mkU32(0x3),
15625 unop(Iop_ReinterpI64asF64,
15626 unop(Iop_V128to64, mkexpr(t3)))));
15627 assign(t2,
15628 binop(Iop_F64toI64S, mkU32(0x3),
15629 unop(Iop_ReinterpI64asF64,
15630 unop(Iop_V128HIto64, mkexpr(t3)))));
15631 putWReg(wd,
15632 binop(Iop_64HLtoV128,
15633 mkexpr(t2), mkexpr(t1)));
15634 break;
15637 default:
15638 return -1;
15641 break;
15644 case 0x192: { /* FTRUNC_U.df */
15645 switch (df) {
15646 case 0x00: { /* FTRUNC_U.W */
15647 DIP("FTRUNC_U.W w%d, w%d", wd, ws);
15648 calculateMSACSR(ws, wd, FTRUNCUW, 1);
15649 putWReg(wd, unop(Iop_F32toI32Ux4_RZ, getWReg(ws)));
15650 break;
15653 case 0x01: { /* FTRUNC_U.D */
15654 DIP("FTRUNC_U.D w%d, w%d", wd, ws);
15655 calculateMSACSR(ws, wd, FTRUNCUD, 1);
15656 t1 = newTemp(Ity_I64);
15657 t2 = newTemp(Ity_I64);
15658 assign(t1,
15659 binop(Iop_F64toI64U,
15660 mkU32(0x3),
15661 unop(Iop_ReinterpI64asF64,
15662 unop(Iop_V128to64,
15663 getWReg(ws)))));
15664 assign(t2,
15665 binop(Iop_F64toI64U,
15666 mkU32(0x3),
15667 unop(Iop_ReinterpI64asF64,
15668 unop(Iop_V128HIto64,
15669 getWReg(ws)))));
15670 putWReg(wd,
15671 binop(Iop_64HLtoV128,
15672 mkexpr(t2), mkexpr(t1)));
15673 break;
15676 default:
15677 return -1;
15680 break;
15683 case 0x193: { /* FSQRT.df */
15684 switch (df) {
15685 case 0x00: { /* FSQRT.W */
15686 DIP("FSQRT.W w%d, w%d", wd, ws);
15687 IRExpr *rm = get_IR_roundingmode_MSA();
15688 calculateMSACSR(ws, wd, FSQRTW, 1);
15689 putWReg(wd, binop(Iop_Sqrt32Fx4, rm, getWReg(ws)));
15690 break;
15693 case 0x01: { /* FSQRT.D */
15694 DIP("FSQRT.D w%d, w%d", wd, ws);
15695 IRExpr *rm = get_IR_roundingmode_MSA();
15696 calculateMSACSR(ws, wd, FSQRTD, 1);
15697 putWReg(wd, binop(Iop_Sqrt64Fx2, rm, getWReg(ws)));
15698 break;
15701 default:
15702 return -1;
15705 break;
15708 case 0x194: { /* FRSQRT.df */
15709 switch (df) {
15710 case 0x00: { /* FRSQRT.W */
15711 DIP("FRSQRT.W w%d, w%d", wd, ws);
15712 calculateMSACSR(ws, wd, FRSQRTW, 1);
15713 putWReg(wd, unop(Iop_RSqrtEst32Fx4, getWReg(ws)));
15714 break;
15717 case 0x01: { /* FRSQRT.D */
15718 DIP("FRSQRT.D w%d, w%d", wd, ws);
15719 calculateMSACSR(ws, wd, FRSQRTD, 1);
15720 putWReg(wd, unop(Iop_RSqrtEst64Fx2, getWReg(ws)));
15721 break;
15724 default:
15725 return -1;
15728 break;
15731 case 0x195: { /* FRCP.df */
15732 switch (df) { /* FRCP.W */
15733 case 0x00: {
15734 DIP("FRCP.W w%d, w%d", wd, ws);
15735 calculateMSACSR(ws, wd, FRCPW, 1);
15736 putWReg(wd, unop(Iop_RecipEst32Fx4, getWReg(ws)));
15737 break;
15740 case 0x01: { /* FRCP.D */
15741 DIP("FRCP.D w%d, w%d", wd, ws);
15742 calculateMSACSR(ws, wd, FRCPD, 1);
15743 putWReg(wd, unop(Iop_RecipEst64Fx2, getWReg(ws)));
15744 break;
15747 default:
15748 return -1;
15751 break;
15754 case 0x196: { /* FRINT.df */
15755 t1 = newTemp(Ity_V128);
15756 t2 = newTemp(Ity_V128);
15757 t3 = newTemp(Ity_V128);
15758 t4 = newTemp(Ity_V128);
15759 IRExpr *rm = get_IR_roundingmode_MSA();
15760 assign(t1, getWReg(ws));
15762 switch (df) {
15763 case 0x00: { /* FRINT.W */
15764 DIP("FRINT.W w%d, w%d", wd, ws);
15765 calculateMSACSR(ws, wt, FRINTW, 1);
15766 assign(t2,
15767 binop(Iop_OrV128,
15768 binop(Iop_CmpLT32Fx4,
15769 mkexpr(t1),
15770 binop(Iop_64HLtoV128,
15771 mkU64(0xCF000000CF000000ull),
15772 mkU64(0xCF000000CF000000ull))),
15773 binop(Iop_CmpLT32Fx4,
15774 binop(Iop_64HLtoV128,
15775 mkU64(0x4F0000004F000000ull),
15776 mkU64(0x4F0000004F000000ull)),
15777 mkexpr(t1))));
15778 assign(t3,
15779 binop(Iop_CmpEQ32x4,
15780 binop(Iop_AndV128,
15781 mkexpr(t1),
15782 binop(Iop_64HLtoV128,
15783 mkU64(0x0040000000400000ull),
15784 mkU64(0x0040000000400000ull))),
15785 binop(Iop_64HLtoV128,
15786 mkU64(0x0040000000400000ull),
15787 mkU64(0x0040000000400000ull))));
15788 assign(t4,
15789 binop(Iop_CmpUN32Fx4,
15790 mkexpr(t1), mkexpr(t1)));
15791 IRTemp tmp[4];
15792 Int i;
15794 for (i = 0; i < 4; i++) {
15795 tmp[i] = newTemp(Ity_I32);
15796 assign(tmp[i],
15797 unop(Iop_ReinterpF32asI32,
15798 binop(Iop_RoundF32toInt, rm,
15799 unop(Iop_ReinterpI32asF32,
15800 binop(Iop_GetElem32x4,
15801 mkexpr(t1), mkU8(i))))));
15804 putWReg(wd,
15805 binop(Iop_OrV128,
15806 binop(Iop_OrV128,
15807 binop(Iop_AndV128,
15808 binop(Iop_OrV128,
15809 mkexpr(t2),
15810 binop(Iop_AndV128,
15811 mkexpr(t4),
15812 unop(Iop_NotV128,
15813 mkexpr(t3)))),
15814 mkexpr(t1)),
15815 binop(Iop_AndV128,
15816 binop(Iop_AndV128,
15817 mkexpr(t4),
15818 mkexpr(t3)),
15819 binop(Iop_64HLtoV128,
15820 mkU64(0x7FBFFFFF7FBFFFFF),
15821 mkU64(0x7FBFFFFF7FBFFFFF)))),
15822 binop(Iop_AndV128,
15823 unop(Iop_NotV128,
15824 binop(Iop_OrV128,
15825 mkexpr(t2),
15826 mkexpr(t4))),
15827 binop(Iop_OrV128,
15828 binop(Iop_64HLtoV128,
15829 binop(Iop_32HLto64,
15830 mkexpr(tmp[3]),
15831 mkexpr(tmp[2])),
15832 binop(Iop_32HLto64,
15833 mkexpr(tmp[1]),
15834 mkexpr(tmp[0]))),
15835 binop(Iop_AndV128,
15836 mkexpr(t1),
15837 binop(Iop_64HLtoV128,
15838 mkU64(0x8000000080000000ull),
15839 mkU64(0x8000000080000000ull)))
15840 ))));
15841 break;
15844 case 0x01: { /* FRINT.D */
15845 DIP("FRINT.D w%d, w%d", wd, ws);
15846 calculateMSACSR(ws, wt, FRINTD, 1);
15847 assign(t2,
15848 binop(Iop_OrV128,
15849 binop(Iop_CmpLT64Fx2,
15850 mkexpr(t1),
15851 binop(Iop_64HLtoV128,
15852 mkU64(0xC3E0000000000000ull),
15853 mkU64(0xC3E0000000000000ull))),
15854 binop(Iop_CmpLT64Fx2,
15855 binop(Iop_64HLtoV128,
15856 mkU64(0x43E0000000000000ull),
15857 mkU64(0x43E0000000000000ull)),
15858 mkexpr(t1))));
15859 assign(t3,
15860 binop(Iop_CmpEQ64x2,
15861 binop(Iop_AndV128,
15862 getWReg(ws),
15863 binop(Iop_64HLtoV128,
15864 mkU64(0x0008000000000000ull),
15865 mkU64(0x0008000000000000ull))),
15866 binop(Iop_64HLtoV128,
15867 mkU64(0x0008000000000000ull),
15868 mkU64(0x0008000000000000ull))));
15869 assign(t4,
15870 binop(Iop_CmpUN64Fx2,
15871 mkexpr(t1), mkexpr(t1)));
15872 IRTemp tmp[2];
15873 Int i;
15875 for (i = 0; i < 2; i++) {
15876 tmp[i] = newTemp(Ity_I64);
15877 assign(tmp[i],
15878 unop(Iop_ReinterpF64asI64,
15879 binop(Iop_RoundF64toInt, rm,
15880 unop(Iop_ReinterpI64asF64,
15881 binop(Iop_GetElem64x2,
15882 mkexpr(t1), mkU8(i))))));
15885 putWReg(wd,
15886 binop(Iop_OrV128,
15887 binop(Iop_OrV128,
15888 binop(Iop_AndV128,
15889 binop(Iop_OrV128,
15890 mkexpr(t2),
15891 binop(Iop_AndV128,
15892 mkexpr(t4),
15893 unop(Iop_NotV128,
15894 mkexpr(t3)))),
15895 mkexpr(t1)),
15896 binop(Iop_AndV128,
15897 binop(Iop_AndV128,
15898 mkexpr(t4),
15899 mkexpr(t3)),
15900 binop(Iop_64HLtoV128,
15901 mkU64(0x7FF7FFFFFFFFFFFF),
15902 mkU64(0x7FF7FFFFFFFFFFFF)))),
15903 binop(Iop_AndV128,
15904 unop(Iop_NotV128,
15905 binop(Iop_OrV128,
15906 mkexpr(t2),
15907 mkexpr(t4))),
15908 binop(Iop_OrV128,
15909 binop(Iop_64HLtoV128,
15910 mkexpr(tmp[1]),
15911 mkexpr(tmp[0])),
15912 binop(Iop_AndV128,
15913 mkexpr(t1),
15914 binop(Iop_64HLtoV128,
15915 mkU64(0x8000000000000000ull),
15916 mkU64(0x8000000000000000ull))
15917 )))));
15918 break;
15921 default:
15922 return -1;
15925 break;
15928 case 0x197: { /* FLOG2.df */
15930 switch (df) {
15931 case 0x00: { /* FLOG2.W */
15932 DIP("FLOG2.W w%d, w%d", wd, ws);
15933 calculateMSACSR(ws, wt, FLOG2W, 1);
15934 putWReg(wd, unop(Iop_Log2_32Fx4, getWReg(ws)));
15935 break;
15938 case 0x01: { /* FLOG2.D */
15939 DIP("FLOG2.D w%d, w%d", wd, ws);
15940 calculateMSACSR(ws, wt, FLOG2D, 1);
15941 putWReg(wd, unop(Iop_Log2_64Fx2, getWReg(ws)));
15942 break;
15945 default:
15946 return -1;
15949 break;
15952 case 0x198: { /* FEXUPL.df */
15953 switch (df) {
15954 case 0x00: { /* FEXUPL.W */
15955 DIP("FEXUPL.W w%d, w%d", wd, ws);
15956 calculateMSACSR(ws, wt, FEXUPLW, 1);
15957 putWReg(wd,
15958 unop(Iop_F16toF32x4,
15959 unop(Iop_V128HIto64,
15960 getWReg(ws))));
15961 break;
15964 case 0x01: { /* FEXUPL.D */
15965 DIP("FEXUPL.D w%d, w%d", wd, ws);
15966 calculateMSACSR(ws, wt, FEXUPLD, 1);
15967 t1 = newTemp(Ity_I64);
15968 t2 = newTemp(Ity_I64);
15969 assign(t1,
15970 unop(Iop_ReinterpF64asI64,
15971 unop(Iop_F32toF64,
15972 unop(Iop_ReinterpI32asF32,
15973 unop(Iop_64to32,
15974 unop(Iop_V128HIto64,
15975 getWReg(ws)))))));
15976 assign(t2,
15977 unop(Iop_ReinterpF64asI64,
15978 unop(Iop_F32toF64,
15979 unop(Iop_ReinterpI32asF32,
15980 unop(Iop_64HIto32,
15981 unop(Iop_V128HIto64,
15982 getWReg(ws)))))));
15983 putWReg(wd,
15984 binop(Iop_64HLtoV128,
15985 mkexpr(t2), mkexpr(t1)));
15986 break;
15989 default:
15990 return -1;
15993 break;
15996 case 0x199: { /* FEXUPR.df */
15997 switch (df) {
15998 case 0x00: { /* FEXUPR.W */
15999 DIP("FEXUPR.W w%d, w%d", wd, ws);
16000 calculateMSACSR(ws, wt, FEXUPRW, 1);
16001 putWReg(wd,
16002 unop(Iop_F16toF32x4,
16003 unop(Iop_V128to64,
16004 getWReg(ws))));
16005 break;
16008 case 0x01: { /* FEXUPR.D */
16009 DIP("FEXUPR.D w%d, w%d", wd, ws);
16010 calculateMSACSR(ws, wt, FEXUPRD, 1);
16011 t1 = newTemp(Ity_I64);
16012 t2 = newTemp(Ity_I64);
16013 assign(t1,
16014 unop(Iop_ReinterpF64asI64,
16015 unop(Iop_F32toF64,
16016 unop(Iop_ReinterpI32asF32,
16017 unop(Iop_64to32,
16018 unop(Iop_V128to64,
16019 getWReg(ws)))))));
16020 assign(t2,
16021 unop(Iop_ReinterpF64asI64,
16022 unop(Iop_F32toF64,
16023 unop(Iop_ReinterpI32asF32,
16024 unop(Iop_64HIto32,
16025 unop(Iop_V128to64,
16026 getWReg(ws)))))));
16027 putWReg(wd,
16028 binop(Iop_64HLtoV128,
16029 mkexpr(t2), mkexpr(t1)));
16030 break;
16033 default:
16034 return -1;
16037 break;
16040 case 0x19A: { /* FFQL.df */
16041 switch (df) {
16042 case 0x00: { /* FFQL.W */
16043 DIP("FFQL.W w%d, w%d", wd, ws);
16044 calculateMSACSR(ws, wt, FFQLW, 1);
16045 t1 = newTemp(Ity_V128);
16046 t2 = newTemp(Ity_I64);
16047 t3 = newTemp(Ity_I64);
16048 IRExpr *rm = get_IR_roundingmode_MSA();
16049 assign(t1,
16050 binop(Iop_SarN32x4,
16051 binop(Iop_InterleaveHI16x8,
16052 getWReg(ws),
16053 getWReg(ws)),
16054 mkU8(16)));
16055 assign(t2,
16056 binop(Iop_32HLto64,
16057 unop(Iop_ReinterpF32asI32,
16058 binop(Iop_I32StoF32, rm,
16059 binop(Iop_GetElem32x4,
16060 mkexpr(t1),
16061 mkU8(1)))),
16062 unop(Iop_ReinterpF32asI32,
16063 binop(Iop_I32StoF32, rm,
16064 binop(Iop_GetElem32x4,
16065 mkexpr(t1),
16066 mkU8(0))))));
16067 assign(t3,
16068 binop(Iop_32HLto64,
16069 unop(Iop_ReinterpF32asI32,
16070 binop(Iop_I32StoF32, rm,
16071 binop(Iop_GetElem32x4,
16072 mkexpr(t1),
16073 mkU8(3)))),
16074 unop(Iop_ReinterpF32asI32,
16075 binop(Iop_I32StoF32, rm,
16076 binop(Iop_GetElem32x4,
16077 mkexpr(t1),
16078 mkU8(2))))));
16079 putWReg(wd,
16080 triop(Iop_Div32Fx4, rm,
16081 binop(Iop_64HLtoV128,
16082 mkexpr(t3), mkexpr(t2)),
16083 binop(Iop_64HLtoV128,
16084 mkU64(0x4700000047000000),
16085 mkU64(0x4700000047000000))));
16086 break;
16089 case 0x01: { /* FFQL.D */
16090 DIP("FFQL.D w%d, w%d", wd, ws);
16091 calculateMSACSR(ws, wt, FFQLD, 1);
16092 t1 = newTemp(Ity_V128);
16093 t2 = newTemp(Ity_I64);
16094 t3 = newTemp(Ity_I64);
16095 IRExpr *rm = get_IR_roundingmode_MSA();
16096 assign(t1,
16097 binop(Iop_SarN64x2,
16098 binop(Iop_InterleaveHI32x4,
16099 getWReg(ws),
16100 getWReg(ws)),
16101 mkU8(32)));
16102 assign(t2,
16103 unop(Iop_ReinterpF64asI64,
16104 binop(Iop_I64StoF64, rm,
16105 unop(Iop_V128to64,
16106 mkexpr(t1)))));
16107 assign(t3,
16108 unop(Iop_ReinterpF64asI64,
16109 binop(Iop_I64StoF64, rm,
16110 unop(Iop_V128HIto64,
16111 mkexpr(t1)))));
16112 putWReg(wd,
16113 triop(Iop_Div64Fx2, rm,
16114 binop(Iop_64HLtoV128,
16115 mkexpr(t3), mkexpr(t2)),
16116 binop(Iop_64HLtoV128,
16117 mkU64(0x41E0000000000000),
16118 mkU64(0x41E0000000000000))));
16119 break;
16122 default:
16123 return -1;
16126 break;
16129 case 0x19B: { /* FFQR.df */
16130 switch (df) {
16131 case 0x00: { /* FFQR.W */
16132 DIP("FFQR.W w%d, w%d", wd, ws);
16133 calculateMSACSR(ws, wt, FFQRW, 1);
16134 t1 = newTemp(Ity_V128);
16135 t2 = newTemp(Ity_I64);
16136 t3 = newTemp(Ity_I64);
16137 IRExpr *rm = get_IR_roundingmode_MSA();
16138 assign(t1,
16139 binop(Iop_SarN32x4,
16140 binop(Iop_InterleaveLO16x8,
16141 getWReg(ws),
16142 getWReg(ws)),
16143 mkU8(16)));
16144 assign(t2,
16145 binop(Iop_32HLto64,
16146 unop(Iop_ReinterpF32asI32,
16147 binop(Iop_I32StoF32, rm,
16148 binop(Iop_GetElem32x4,
16149 mkexpr(t1),
16150 mkU8(1)))),
16151 unop(Iop_ReinterpF32asI32,
16152 binop(Iop_I32StoF32, rm,
16153 binop(Iop_GetElem32x4,
16154 mkexpr(t1),
16155 mkU8(0))))));
16156 assign(t3,
16157 binop(Iop_32HLto64,
16158 unop(Iop_ReinterpF32asI32,
16159 binop(Iop_I32StoF32, rm,
16160 binop(Iop_GetElem32x4,
16161 mkexpr(t1),
16162 mkU8(3)))),
16163 unop(Iop_ReinterpF32asI32,
16164 binop(Iop_I32StoF32, rm,
16165 binop(Iop_GetElem32x4,
16166 mkexpr(t1),
16167 mkU8(2))))));
16168 putWReg(wd,
16169 triop(Iop_Div32Fx4, rm,
16170 binop(Iop_64HLtoV128,
16171 mkexpr(t3), mkexpr(t2)),
16172 binop(Iop_64HLtoV128,
16173 mkU64(0x4700000047000000),
16174 mkU64(0x4700000047000000))));
16175 break;
16178 case 0x01: { /* FFQR.D */
16179 DIP("FFQR.D w%d, w%d", wd, ws);
16180 calculateMSACSR(ws, wt, FFQRD, 1);
16181 t1 = newTemp(Ity_V128);
16182 t2 = newTemp(Ity_I64);
16183 t3 = newTemp(Ity_I64);
16184 IRExpr *rm = get_IR_roundingmode_MSA();
16185 assign(t1,
16186 binop(Iop_SarN64x2,
16187 binop(Iop_InterleaveLO32x4,
16188 getWReg(ws),
16189 getWReg(ws)),
16190 mkU8(32)));
16191 assign(t2,
16192 unop(Iop_ReinterpF64asI64,
16193 binop(Iop_I64StoF64, rm,
16194 unop(Iop_V128to64,
16195 mkexpr(t1)))));
16196 assign(t3,
16197 unop(Iop_ReinterpF64asI64,
16198 binop(Iop_I64StoF64, rm,
16199 unop(Iop_V128HIto64,
16200 mkexpr(t1)))));
16201 putWReg(wd,
16202 triop(Iop_Div64Fx2, rm,
16203 binop(Iop_64HLtoV128,
16204 mkexpr(t3), mkexpr(t2)),
16205 binop(Iop_64HLtoV128,
16206 mkU64(0x41E0000000000000),
16207 mkU64(0x41E0000000000000))));
16208 break;
16211 default:
16212 return -1;
16215 break;
16218 case 0x19C: { /* FTINT_S.df */
16219 switch (df) { /* FTINT_S.W */
16220 case 0x00: {
16221 DIP("FTINT_S.W w%d, w%d", wd, ws);
16222 calculateMSACSR(ws, wd, FTINT_SW, 1);
16223 t1 = newTemp(Ity_I64);
16224 t2 = newTemp(Ity_I64);
16225 t3 = newTemp(Ity_V128);
16226 t4 = newTemp(Ity_I32);
16227 assign(t3,
16228 binop(Iop_AndV128,
16229 unop(Iop_NotV128,
16230 binop(Iop_CmpUN32Fx4,
16231 getWReg(ws),
16232 getWReg(ws))),
16233 binop(Iop_Max32Fx4,
16234 getWReg(ws),
16235 binop(Iop_64HLtoV128,
16236 mkU64(0xCF000000CF000000),
16237 mkU64(0xCF000000CF000000)))));
16238 IRExpr *rm = get_IR_roundingmode_MSA();
16239 assign(t1,
16240 binop(Iop_32HLto64,
16241 binop(Iop_F32toI32S, rm,
16242 unop(Iop_ReinterpI32asF32,
16243 binop(Iop_GetElem32x4,
16244 mkexpr(t3), mkU8(1)))),
16245 binop(Iop_F32toI32S, rm,
16246 unop(Iop_ReinterpI32asF32,
16247 binop(Iop_GetElem32x4,
16248 mkexpr(t3), mkU8(0))))));
16249 assign(t2,
16250 binop(Iop_32HLto64,
16251 binop(Iop_F32toI32S, rm,
16252 unop(Iop_ReinterpI32asF32,
16253 binop(Iop_GetElem32x4,
16254 mkexpr(t3), mkU8(3)))),
16255 binop(Iop_F32toI32S, rm,
16256 unop(Iop_ReinterpI32asF32,
16257 binop(Iop_GetElem32x4,
16258 mkexpr(t3), mkU8(2))))));
16259 putWReg(wd,
16260 binop(Iop_64HLtoV128,
16261 mkexpr(t2), mkexpr(t1)));
16262 break;
16265 case 0x01: { /* FTINT_S.D */
16266 DIP("FTINT_S.D w%d, w%d", wd, ws);
16267 calculateMSACSR(ws, wd, FTINT_SD, 1);
16268 t1 = newTemp(Ity_I64);
16269 t2 = newTemp(Ity_I64);
16270 t3 = newTemp(Ity_V128);
16271 assign(t3,
16272 binop(Iop_AndV128,
16273 unop(Iop_NotV128,
16274 binop(Iop_CmpUN64Fx2,
16275 getWReg(ws),
16276 getWReg(ws))),
16277 binop(Iop_Max64Fx2,
16278 getWReg(ws),
16279 binop(Iop_64HLtoV128,
16280 mkU64(0xC3E0000000000000),
16281 mkU64(0xC3E0000000000000)))));
16282 IRExpr *rm = get_IR_roundingmode_MSA();
16283 assign(t1,
16284 binop(Iop_F64toI64S, rm,
16285 unop(Iop_ReinterpI64asF64,
16286 unop(Iop_V128to64, mkexpr(t3)))));
16287 assign(t2,
16288 binop(Iop_F64toI64S, rm,
16289 unop(Iop_ReinterpI64asF64,
16290 unop(Iop_V128HIto64, mkexpr(t3)))));
16291 putWReg(wd,
16292 binop(Iop_64HLtoV128,
16293 mkexpr(t2), mkexpr(t1)));
16294 break;
16297 default:
16298 return -1;
16301 break;
16304 case 0x19D: {/* FTINT_U.df */
16305 switch (df) { /* FTINT_U.W */
16306 case 0x00: {
16307 DIP("FTINT_U.W w%d, w%d", wd, ws);
16308 calculateMSACSR(ws, wd, FTINT_UW, 1);
16309 t1 = newTemp(Ity_I64);
16310 t2 = newTemp(Ity_I64);
16311 t3 = newTemp(Ity_V128);
16312 t4 = newTemp(Ity_V128);
16313 IRExpr *rm = get_IR_roundingmode_MSA();
16314 assign(t1,
16315 binop(Iop_32HLto64,
16316 binop(Iop_F32toI32U, rm,
16317 unop(Iop_ReinterpI32asF32,
16318 binop(Iop_GetElem32x4,
16319 getWReg(ws), mkU8(1)))),
16320 binop(Iop_F32toI32U, rm,
16321 unop(Iop_ReinterpI32asF32,
16322 binop(Iop_GetElem32x4,
16323 getWReg(ws), mkU8(0))))));
16324 assign(t2,
16325 binop(Iop_32HLto64,
16326 binop(Iop_F32toI32U, rm,
16327 unop(Iop_ReinterpI32asF32,
16328 binop(Iop_GetElem32x4,
16329 getWReg(ws), mkU8(3)))),
16330 binop(Iop_F32toI32U, rm,
16331 unop(Iop_ReinterpI32asF32,
16332 binop(Iop_GetElem32x4,
16333 getWReg(ws), mkU8(2))))));
16334 assign(t3,
16335 unop(Iop_NotV128,
16336 binop(Iop_SarN32x4,
16337 getWReg(ws),
16338 mkU8(31))));
16339 assign(t4,
16340 binop(Iop_CmpLT32Fx4,
16341 getWReg(ws),
16342 binop(Iop_64HLtoV128,
16343 mkU64(0x4EFFFFFF4EFFFFFF),
16344 mkU64(0x4EFFFFFF4EFFFFFF))));
16345 putWReg(wd,
16346 binop(Iop_OrV128,
16347 binop(Iop_AndV128,
16348 mkexpr(t4),
16349 binop(Iop_AndV128,
16350 binop(Iop_64HLtoV128,
16351 mkexpr(t2),
16352 mkexpr(t1)),
16353 mkexpr(t3))),
16354 binop(Iop_AndV128,
16355 unop(Iop_NotV128, mkexpr(t4)),
16356 unop(Iop_F32toI32Ux4_RZ,
16357 getWReg(ws)))));
16358 break;
16361 case 0x01: { /* FTINT_U.D */
16362 DIP("FTINT_U.D w%d, w%d", wd, ws);
16363 calculateMSACSR(ws, wd, FTINT_UD, 1);
16364 t1 = newTemp(Ity_I64);
16365 t2 = newTemp(Ity_I64);
16366 IRExpr *rm = get_IR_roundingmode_MSA();
16367 assign(t1,
16368 binop(Iop_F64toI64U, rm,
16369 unop(Iop_ReinterpI64asF64,
16370 unop(Iop_V128to64,
16371 getWReg(ws)))));
16372 assign(t2,
16373 binop(Iop_F64toI64U, rm,
16374 unop(Iop_ReinterpI64asF64,
16375 unop(Iop_V128HIto64,
16376 getWReg(ws)))));
16377 putWReg(wd,
16378 binop(Iop_64HLtoV128,
16379 mkexpr(t2), mkexpr(t1)));
16380 break;
16383 default:
16384 return -1;
16387 break;
16390 case 0x19E: { /* FFINT_S.df */
16391 t1 = newTemp(Ity_V128);
16392 assign(t1, getWReg(ws));
16393 IRExpr *rm = get_IR_roundingmode_MSA();
16395 switch (df) {
16396 case 0x00: { /* FFINT_S.W */
16397 DIP("FFINT_S.W w%d, w%d", wd, ws);
16398 calculateMSACSR(ws, wt, FFINTSW, 1);
16399 IRTemp tmp[4];
16400 Int i;
16402 for (i = 0; i < 4; i++) {
16403 tmp[i] = newTemp(Ity_F32);
16404 assign(tmp[i],
16405 binop(Iop_I32StoF32, rm,
16406 binop(Iop_GetElem32x4,
16407 mkexpr(t1), mkU8(i))));
16410 putWReg(wd,
16411 binop(Iop_64HLtoV128,
16412 binop(Iop_32HLto64,
16413 unop(Iop_ReinterpF32asI32,
16414 mkexpr(tmp[3])),
16415 unop(Iop_ReinterpF32asI32,
16416 mkexpr(tmp[2]))),
16417 binop(Iop_32HLto64,
16418 unop(Iop_ReinterpF32asI32,
16419 mkexpr(tmp[1])),
16420 unop(Iop_ReinterpF32asI32,
16421 mkexpr(tmp[0])))));
16422 break;
16425 case 0x01: { /* FFINT_S.D */
16426 DIP("FFINT_S.D w%d, w%d", wd, ws);
16427 calculateMSACSR(ws, wt, FFINTSD, 1);
16428 IRTemp tmp[2];
16429 Int i;
16431 for (i = 0; i < 2; i++) {
16432 tmp[i] = newTemp(Ity_F64);
16433 assign(tmp[i],
16434 binop(Iop_I64StoF64, rm,
16435 binop(Iop_GetElem64x2,
16436 mkexpr(t1), mkU8(i))));
16439 putWReg(wd,
16440 binop(Iop_64HLtoV128,
16441 unop(Iop_ReinterpF64asI64,
16442 mkexpr(tmp[1])),
16443 unop(Iop_ReinterpF64asI64,
16444 mkexpr(tmp[0]))));
16445 break;
16448 default:
16449 return -1;
16452 break;
16455 case 0x19F: { /* FFINT_U.df */
16456 IRExpr *rm = get_IR_roundingmode_MSA();
16458 switch (df) {
16459 case 0x00: { /* FFINT_U.W */
16460 DIP("FFINT_U.W w%d, w%d", wd, ws);
16461 calculateMSACSR(ws, wt, FFINT_UW, 1);
16462 putWReg(wd, unop(Iop_I32UtoF32x4_DEP, getWReg(ws)));
16463 break;
16466 case 0x01: { /* FFINT_U.D */
16467 DIP("FFINT_U.D w%d, w%d",
16468 wd, ws);
16469 calculateMSACSR(ws, wt,
16470 FFINT_UD, 1);
16471 t1 = newTemp(Ity_I64);
16472 t2 = newTemp(Ity_I64);
16473 assign(t1,
16474 unop(Iop_ReinterpF64asI64,
16475 binop(Iop_I64UtoF64, rm,
16476 unop(Iop_V128to64,
16477 getWReg(ws)))));
16478 assign(t2,
16479 unop(Iop_ReinterpF64asI64,
16480 binop(Iop_I64UtoF64, rm,
16481 unop(Iop_V128HIto64,
16482 getWReg(ws)))));
16483 putWReg(wd,
16484 binop(Iop_64HLtoV128,
16485 mkexpr(t2), mkexpr(t1)));
16486 break;
16489 default:
16490 return -1;
16493 break;
16496 default:
16497 return -1;
16500 return 0;
16503 static Int msa_MI10_load(UInt cins, UChar wd, UChar ws) /* MI10 (0x20) */
16505 IRTemp t1;
16506 UShort i10;
16507 UChar df;
16509 i10 = (cins & 0x03FF0000) >> 16;
16510 df = cins & 0x00000003;
16512 switch (df) {
16513 case 0x00: { /* LD.B */
16514 DIP("LD.B w%d, %d(r%d)", wd, ws, i10);
16515 LOAD_STORE_PATTERN_MSA(i10);
16516 putWReg(wd, load(Ity_V128, mkexpr(t1)));
16517 break;
16520 case 0x01: { /* LD.H */
16521 DIP("LD.H w%d, %d(r%d)", wd, ws, i10);
16522 LOAD_STORE_PATTERN_MSA(i10 << 1);
16523 #if defined (_MIPSEL)
16524 putWReg(wd, load(Ity_V128, mkexpr(t1)));
16525 #elif defined (_MIPSEB)
16526 putWReg(wd,
16527 unop(Iop_Reverse8sIn16_x8,
16528 load(Ity_V128, mkexpr(t1))));
16529 #endif
16530 break;
16533 case 0x02: { /* LD.W */
16534 DIP("LD.W w%d, %d(r%d)", wd, ws, i10);
16535 LOAD_STORE_PATTERN_MSA(i10 << 2);
16536 #if defined (_MIPSEL)
16537 putWReg(wd, load(Ity_V128, mkexpr(t1)));
16538 #elif defined (_MIPSEB)
16539 putWReg(wd,
16540 unop(Iop_Reverse8sIn32_x4,
16541 load(Ity_V128, mkexpr(t1))));
16542 #endif
16543 break;
16546 case 0x03: { /* LD.D */
16547 DIP("LD.D w%d, %d(r%d)", wd, ws, i10);
16548 LOAD_STORE_PATTERN_MSA(i10 << 3);
16549 #if defined (_MIPSEL)
16550 putWReg(wd, load(Ity_V128, mkexpr(t1)));
16551 #elif defined (_MIPSEB)
16552 putWReg(wd,
16553 unop(Iop_Reverse8sIn64_x2,
16554 load(Ity_V128, mkexpr(t1))));
16555 #endif
16556 break;
16559 default:
16560 return -1;
16563 return 0;
16566 static Int msa_MI10_store(UInt cins, UChar wd, UChar ws) /* MI10 (0x24) */
16568 IRTemp t1;
16569 UShort i10;
16570 UChar df;
16572 df = cins & 0x00000003;
16573 i10 = (cins & 0x03FF0000) >> 16;
16575 switch (df) {
16576 case 0x00: { /* ST.B */
16577 DIP("ST.B w%d, %d(r%d)", wd, ws, i10);
16578 LOAD_STORE_PATTERN_MSA(i10);
16579 store(mkexpr(t1), getWReg(wd));
16580 break;
16583 case 0x01: { /* ST.H */
16584 DIP("ST.H w%d, %d(r%d)", wd, ws, i10);
16585 LOAD_STORE_PATTERN_MSA(i10 << 1);
16586 #if defined (_MIPSEL)
16587 store(mkexpr(t1), getWReg(wd));
16588 #elif defined (_MIPSEB)
16589 store(mkexpr(t1),
16590 unop(Iop_Reverse8sIn16_x8, getWReg(wd)));
16591 #endif
16592 break;
16595 case 0x02: { /* ST.W */
16596 DIP("ST.W w%d, %d(r%d)", wd, ws, i10);
16597 LOAD_STORE_PATTERN_MSA(i10 << 2);
16598 #if defined (_MIPSEL)
16599 store(mkexpr(t1), getWReg(wd));
16600 #elif defined (_MIPSEB)
16601 store(mkexpr(t1),
16602 unop(Iop_Reverse8sIn32_x4, getWReg(wd)));
16603 #endif
16604 break;
16607 case 0x03: { /* ST.D */
16608 DIP("ST.D w%d, %d(r%d)", wd, ws, i10);
16609 LOAD_STORE_PATTERN_MSA(i10 << 3);
16610 #if defined (_MIPSEL)
16611 store(mkexpr(t1), getWReg(wd));
16612 #elif defined (_MIPSEB)
16613 store(mkexpr(t1),
16614 unop(Iop_Reverse8sIn64_x2, getWReg(wd)));
16615 #endif
16616 break;
16619 default:
16620 return -1;
16623 return 0;
16626 /*------------------------------------------------------------*/
16627 /*--- Disassemble a single MIPS MSA (SIMD) instruction ---*/
16628 /*--- Return values: ---*/
16629 /*--- 0: Success ---*/
16630 /*--- -1: Decode failure (unknown instruction) ---*/
16631 /*--- -2: Illegal instruction ---*/
16632 /*------------------------------------------------------------*/
16633 static Int disMSAInstr_MIPS_WRK ( UInt cins )
16635 UChar minor_opcode, wd, ws;
16637 vassert(has_msa);
16638 vassert((cins & 0xFC000000) == 0x78000000);
16640 minor_opcode = (cins & 0x20) > 0 ? (cins & 0x3C) : (cins & 0x3F);
16641 wd = (cins & 0x000007C0) >> 6;
16642 ws = (cins & 0x0000F800) >> 11;
16644 switch (minor_opcode) {
16645 case 0x0:
16646 return msa_I8_logical(cins, wd, ws);
16648 case 0x01:
16649 return msa_I8_branch(cins, wd, ws);
16651 case 0x02:
16652 return msa_I8_shift(cins, wd, ws);
16654 case 0x06:
16655 return msa_I5_06(cins, wd, ws);
16657 case 0x07:
16658 return msa_I5_07(cins, wd, ws);
16660 case 0x09:
16661 return msa_BIT_09(cins, wd, ws);
16663 case 0x0A:
16664 return msa_BIT_0A(cins, wd, ws);
16666 case 0x0D:
16667 return msa_3R_0D(cins, wd, ws);
16669 case 0x0E:
16670 return msa_3R_0E(cins, wd, ws);
16672 case 0x0F:
16673 return msa_3R_0F(cins, wd, ws);
16675 case 0x10:
16676 return msa_3R_10(cins, wd, ws);
16678 case 0x11:
16679 return msa_3R_11(cins, wd, ws);
16681 case 0x12:
16682 return msa_3R_12(cins, wd, ws);
16684 case 0x13:
16685 return msa_3R_13(cins, wd, ws);
16687 case 0x14:
16688 return msa_3R_14(cins, wd, ws);
16690 case 0x15:
16691 return msa_3R_15(cins, wd, ws);
16693 case 0x19:
16694 return msa_ELM(cins, wd, ws);
16696 case 0x1A:
16697 return msa_3R_1A(cins, wd, ws);
16699 case 0x1B:
16700 return msa_3R_1B(cins, wd, ws);
16702 case 0x1C:
16703 return msa_3R_1C(cins, wd, ws);
16705 case 0x1E:
16706 if ((cins & 0x03000000) == 0)
16707 return msa_VEC(cins, wd, ws);
16708 else if ((cins & 0x00200000) == 0)
16709 return msa_2R(cins, wd, ws);
16710 else
16711 return msa_2RF(cins, wd, ws);
16713 case 0x20:
16714 return msa_MI10_load(cins, wd, ws);
16716 case 0x24:
16717 return msa_MI10_store(cins, wd, ws);
16720 return -1;
16723 /*------------------------------------------------------------*/
16724 /*--- DSP to IR function ---*/
16725 /*------------------------------------------------------------*/
16727 extern UInt disDSPInstr_MIPS_WRK ( UInt );
16729 /*------------------------------------------------------------*/
16730 /*--- Disassemble a single instruction ---*/
16731 /*------------------------------------------------------------*/
16733 /* Disassemble a single instruction into IR. The instruction is
16734 located in host memory at guest_instr, and has guest IP of
16735 guest_PC_curr_instr, which will have been set before the call
16736 here. */
16739 static UInt disInstr_MIPS_WRK_Special(UInt cins, const VexArchInfo* archinfo,
16740 const VexAbiInfo* abiinfo, DisResult* dres,
16741 IRStmt** bstmt, IRExpr** lastn)
16743 IRTemp t0, t1 = 0, t2, t3, t4, t5;
16744 UInt rs, rt, rd, sa, tf, function, trap_code, imm, instr_index, rot, sel;
16745 /* Additional variables for instruction fields in DSP ASE insructions */
16746 UInt ac;
16748 imm = get_imm(cins);
16749 rs = get_rs(cins);
16750 rt = get_rt(cins);
16751 rd = get_rd(cins);
16752 sa = get_sa(cins);
16753 tf = get_tf(cins);
16754 sel = get_sel(cins);
16755 instr_index = get_instr_index(cins);
16756 trap_code = get_code(cins);
16757 function = get_function(cins);
16758 IRType ty = mode64 ? Ity_I64 : Ity_I32;
16760 ac = get_acNo(cins);
16762 switch (function) {
16763 case 0x00: { /* SLL */
16764 DIP("sll r%u, r%u, %u", rd, rt, sa);
16765 IRTemp tmpRt32 = newTemp(Ity_I32);
16766 IRTemp tmpSh32 = newTemp(Ity_I32);
16767 IRTemp tmpRd = newTemp(Ity_I64);
16769 if (mode64) {
16770 assign(tmpRt32, mkNarrowTo32(ty, getIReg(rt)));
16771 assign(tmpSh32, binop(Iop_Shl32, mkexpr(tmpRt32), mkU8(sa)));
16772 assign(tmpRd, mkWidenFrom32(ty, mkexpr(tmpSh32), True));
16773 putIReg(rd, mkexpr(tmpRd));
16774 } else
16775 SXX_PATTERN(Iop_Shl32);
16777 break;
16780 case 0x01: { /* MOVCI */
16781 UInt mov_cc = get_mov_cc(cins);
16783 if (tf == 0) { /* MOVF */
16784 DIP("movf r%u, r%u, %u", rd, rs, mov_cc);
16785 t1 = newTemp(Ity_I1);
16786 t2 = newTemp(Ity_I32);
16787 t3 = newTemp(Ity_I1);
16789 assign(t1, binop(Iop_CmpEQ32, mkU32(0), mkU32(mov_cc)));
16790 assign(t2, IRExpr_ITE(mkexpr(t1),
16791 binop(Iop_And32,
16792 binop(Iop_Shr32, getFCSR(),
16793 mkU8(23)),
16794 mkU32(0x1)),
16795 binop(Iop_And32,
16796 binop(Iop_Shr32, getFCSR(),
16797 mkU8(24 + mov_cc)),
16798 mkU32(0x1))
16800 assign(t3, binop(Iop_CmpEQ32, mkU32(0), mkexpr(t2)));
16801 putIReg(rd, IRExpr_ITE(mkexpr(t3), getIReg(rs), getIReg(rd)));
16802 } else if (tf == 1) { /* MOVT */
16803 DIP("movt r%u, r%u, %u", rd, rs, mov_cc);
16804 t1 = newTemp(Ity_I1);
16805 t2 = newTemp(Ity_I32);
16806 t3 = newTemp(Ity_I1);
16808 assign(t1, binop(Iop_CmpEQ32, mkU32(0), mkU32(mov_cc)));
16809 assign(t2, IRExpr_ITE(mkexpr(t1),
16810 binop(Iop_And32,
16811 binop(Iop_Shr32, getFCSR(),
16812 mkU8(23)),
16813 mkU32(0x1)),
16814 binop(Iop_And32,
16815 binop(Iop_Shr32, getFCSR(),
16816 mkU8(24 + mov_cc)),
16817 mkU32(0x1))
16819 assign(t3, binop(Iop_CmpEQ32, mkU32(1), mkexpr(t2)));
16820 putIReg(rd, IRExpr_ITE(mkexpr(t3), getIReg(rs), getIReg(rd)));
16823 break;
16826 case 0x02: { /* SRL */
16827 rot = get_rot(cins);
16829 if (rot) {
16830 DIP("rotr r%u, r%u, %u", rd, rt, sa);
16831 putIReg(rd, mkWidenFrom32(ty, genROR32(mkNarrowTo32(ty,
16832 getIReg(rt)), sa), True));
16833 } else {
16834 DIP("srl r%u, r%u, %u", rd, rt, sa);
16836 if (mode64) {
16837 IRTemp tmpSh32 = newTemp(Ity_I32);
16838 IRTemp tmpRt32 = newTemp(Ity_I32);
16840 assign(tmpRt32, mkNarrowTo32(ty, getIReg(rt)));
16841 assign(tmpSh32, binop(Iop_Shr32, mkexpr(tmpRt32), mkU8(sa)));
16842 putIReg(rd, mkWidenFrom32(ty, mkexpr(tmpSh32), True));
16843 } else {
16844 SXX_PATTERN(Iop_Shr32);
16848 break;
16851 case 0x03: /* SRA */
16852 DIP("sra r%u, r%u, %u", rd, rt, sa);
16854 if (mode64) {
16855 IRTemp tmpRt32 = newTemp(Ity_I32);
16856 IRTemp tmpSh32 = newTemp(Ity_I32);
16858 t1 = newTemp(Ity_I64);
16859 t2 = newTemp(Ity_I64);
16860 t3 = newTemp(Ity_I64);
16862 assign(t1, binop(Iop_And64, getIReg(rt), /* hi */
16863 mkU64(0xFFFFFFFF00000000ULL)));
16865 assign(t2, binop(Iop_Sar64, mkexpr(t1), mkU8(sa)));
16867 assign(tmpRt32, mkNarrowTo32(ty, getIReg(rt)));
16868 assign(tmpSh32, binop(Iop_Sar32, mkexpr(tmpRt32), mkU8(sa)));
16870 putIReg(rd, mkWidenFrom32(ty, mkexpr(tmpSh32), True));
16871 } else {
16872 SXX_PATTERN(Iop_Sar32);
16875 break;
16877 case 0x04: { /* SLLV */
16878 DIP("sllv r%u, r%u, r%u", rd, rt, rs);
16880 if (mode64) {
16881 IRTemp tmpRs8 = newTemp(Ity_I8);
16882 IRTemp tmpRt32 = newTemp(Ity_I32);
16883 IRTemp tmpSh32 = newTemp(Ity_I32);
16884 IRTemp tmp = newTemp(ty);
16885 assign(tmp, binop(mkSzOp(ty, Iop_And8), getIReg(rs),
16886 mkSzImm(ty, 31)));
16887 assign(tmpRs8, mkNarrowTo8(ty, mkexpr(tmp)));
16888 assign(tmpRt32, mkNarrowTo32(ty, getIReg(rt)));
16889 assign(tmpSh32, binop(Iop_Shl32, mkexpr(tmpRt32), mkexpr(tmpRs8)));
16890 putIReg(rd, mkWidenFrom32(ty, mkexpr(tmpSh32), True));
16891 } else {
16892 SXXV_PATTERN(Iop_Shl32);
16895 break;
16898 case 0x05: { /* LSA */
16899 UInt imm2 = (imm & 0xC0) >> 6;
16901 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps) || has_msa) {
16902 DIP("lsa r%u, r%u, r%u, imm: 0x%x", rd, rs, rt, imm2);
16904 if (mode64) {
16905 DIP("lsa r%u, r%u, r%u, imm: 0x%x", rd, rs, rt, imm2);
16906 putIReg(rd, unop(Iop_32Sto64,
16907 binop(Iop_Add32,
16908 binop(Iop_Shl32,
16909 unop(Iop_64to32, getIReg(rs)),
16910 mkU8(imm2 + 1)),
16911 unop(Iop_64to32, getIReg(rt)))));
16912 break;
16913 } else {
16914 DIP("lsa r%u, r%u, r%u, imm: 0x%x", rd, rs, rt, imm2);
16915 putIReg(rd, binop(Iop_Add32,
16916 binop(Iop_Shl32,
16917 getIReg(rs), mkU8(imm2 + 1)), getIReg(rt)));
16918 break;
16920 } else {
16921 ILLEGAL_INSTRUCTON;
16922 break;
16926 case 0x06: { /* SRLV */
16927 rot = get_rotv(cins);
16929 if (rot) {
16930 DIP("rotrv r%u, r%u, r%u", rd, rt, rs);
16931 putIReg(rd, mkWidenFrom32(ty, genRORV32(mkNarrowTo32(ty,
16932 getIReg(rt)), mkNarrowTo32(ty, getIReg(rs))), True));
16933 break;
16934 } else { /* SRLV */
16935 DIP("srlv r%u, r%u, r%u", rd, rt, rs);
16937 if (mode64) {
16938 SXXV_PATTERN64(Iop_Shr32);
16939 } else {
16940 SXXV_PATTERN(Iop_Shr32);
16943 break;
16947 case 0x07: /* SRAV */
16948 DIP("srav r%u, r%u, r%u", rd, rt, rs);
16950 if (mode64) {
16951 IRTemp tmpRt32 = newTemp(Ity_I32);
16952 IRTemp tmpSh32 = newTemp(Ity_I32);
16954 t1 = newTemp(Ity_I64);
16955 t2 = newTemp(Ity_I64);
16956 t3 = newTemp(Ity_I64);
16957 t4 = newTemp(Ity_I8);
16959 assign(t4, unop(Iop_32to8, binop(Iop_And32,
16960 mkNarrowTo32(ty, getIReg(rs)), mkU32(0x0000001F))));
16962 assign(t1, binop(Iop_And64, getIReg(rt), /* hi */
16963 mkU64(0xFFFFFFFF00000000ULL)));
16965 assign(t2, binop(Iop_Sar64, mkexpr(t1), mkexpr(t4)));
16967 assign(tmpRt32, mkNarrowTo32(ty, getIReg(rt)));
16968 assign(tmpSh32, binop(Iop_Sar32, mkexpr(tmpRt32), mkexpr(t4)));
16970 putIReg(rd, mkWidenFrom32(ty, mkexpr(tmpSh32), True));
16971 } else {
16972 SXXV_PATTERN(Iop_Sar32);
16975 break;
16977 case 0x08: /* JR */
16978 DIP("jr r%u", rs);
16979 t0 = newTemp(ty);
16980 assign(t0, getIReg(rs));
16981 *lastn = mkexpr(t0);
16982 break;
16984 case 0x09: /* JALR */
16985 DIP("jalr r%u r%u", rd, rs);
16987 if (mode64) {
16988 putIReg(rd, mkU64(guest_PC_curr_instr + 8));
16989 t0 = newTemp(Ity_I64);
16990 assign(t0, getIReg(rs));
16991 *lastn = mkexpr(t0);
16992 } else {
16993 putIReg(rd, mkU32(guest_PC_curr_instr + 8));
16994 t0 = newTemp(Ity_I32);
16995 assign(t0, getIReg(rs));
16996 *lastn = mkexpr(t0);
16999 break;
17001 case 0x0A: { /* MOVZ */
17002 DIP("movz r%u, r%u, r%u", rd, rs, rt);
17003 t1 = newTemp(ty);
17004 t2 = newTemp(ty);
17006 if (mode64) {
17007 assign(t1, unop(Iop_32Sto64, unop(Iop_1Sto32, binop(Iop_CmpEQ64,
17008 getIReg(rt), mkU64(0x0)))));
17009 assign(t2, unop(Iop_32Sto64, unop(Iop_1Sto32, binop(Iop_CmpNE64,
17010 getIReg(rt), mkU64(0x0)))));
17011 putIReg(rd, binop(Iop_Add64, binop(Iop_And64, getIReg(rs),
17012 mkexpr(t1)), binop(Iop_And64, getIReg(rd), mkexpr(t2))));
17013 } else {
17014 assign(t1, unop(Iop_1Sto32, binop(Iop_CmpEQ32, getIReg(rt),
17015 mkU32(0x0))));
17016 assign(t2, unop(Iop_1Sto32, binop(Iop_CmpNE32, getIReg(rt),
17017 mkU32(0x0))));
17018 putIReg(rd, binop(Iop_Add32, binop(Iop_And32, getIReg(rs),
17019 mkexpr(t1)), binop(Iop_And32, getIReg(rd),
17020 mkexpr(t2))));
17023 break;
17026 case 0x0B: { /* MOVN */
17027 DIP("movn r%u, r%u, r%u", rd, rs, rt);
17028 t1 = newTemp(ty);
17029 t2 = newTemp(ty);
17031 if (mode64) {
17032 assign(t1, unop(Iop_32Sto64, unop(Iop_1Sto32, binop(Iop_CmpEQ64,
17033 getIReg(rt), mkU64(0x0)))));
17034 assign(t2, unop(Iop_32Sto64, unop(Iop_1Sto32, binop(Iop_CmpNE64,
17035 getIReg(rt), mkU64(0x0)))));
17036 putIReg(rd, binop(Iop_Add64, binop(Iop_And64, getIReg(rs),
17037 mkexpr(t2)), binop(Iop_And64, getIReg(rd),
17038 mkexpr(t1))));
17039 } else {
17040 assign(t1, unop(Iop_1Sto32, binop(Iop_CmpEQ32, getIReg(rt),
17041 mkU32(0x0))));
17042 assign(t2, unop(Iop_1Sto32, binop(Iop_CmpNE32, getIReg(rt),
17043 mkU32(0x0))));
17044 putIReg(rd, binop(Iop_Add32, binop(Iop_And32, getIReg(rs),
17045 mkexpr(t2)), binop(Iop_And32, getIReg(rd),
17046 mkexpr(t1))));
17049 break;
17052 case 0x0C: /* SYSCALL */
17053 DIP("syscall");
17055 if (mode64)
17056 putPC(mkU64(guest_PC_curr_instr + 4));
17057 else
17058 putPC(mkU32(guest_PC_curr_instr + 4));
17060 dres->jk_StopHere = Ijk_Sys_syscall;
17061 dres->whatNext = Dis_StopHere;
17062 break;
17064 case 0x0D: /* BREAK */
17065 DIP("break 0x%x", trap_code);
17067 if (mode64)
17068 jmp_lit64(dres, Ijk_SigTRAP, (guest_PC_curr_instr + 4));
17069 else
17070 jmp_lit32(dres, Ijk_SigTRAP, (guest_PC_curr_instr + 4));
17072 vassert(dres->whatNext == Dis_StopHere);
17073 break;
17075 case 0x0F: /* SYNC */
17076 DIP("sync 0x%x", sel);
17077 /* Just ignore it. */
17078 break;
17080 case 0x10: { /* MFHI, CLZ R6 */
17081 if (((instr_index >> 6) & 0x1f) == 1) { /* CLZ */
17082 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
17083 DIP("clz r%u, r%u", rd, rs);
17085 if (mode64) {
17086 IRTemp tmpClz32 = newTemp(Ity_I32);
17087 IRTemp tmpRs32 = newTemp(Ity_I32);
17089 assign(tmpRs32, mkNarrowTo32(ty, getIReg(rs)));
17090 assign(tmpClz32, unop(Iop_Clz32, mkexpr(tmpRs32)));
17091 putIReg(rd, mkWidenFrom32(ty, mkexpr(tmpClz32), True));
17092 } else {
17093 t1 = newTemp(Ity_I1);
17094 assign(t1, binop(Iop_CmpEQ32, getIReg(rs), mkU32(0)));
17095 putIReg(rd, IRExpr_ITE(mkexpr(t1),
17096 mkU32(0x00000020),
17097 unop(Iop_Clz32, getIReg(rs))));
17099 } else {
17100 ILLEGAL_INSTRUCTON;
17103 break;
17104 } else if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
17105 /* If DSP is present -> DSP ASE MFHI */
17106 UInt retVal = disDSPInstr_MIPS_WRK ( cins );
17108 if (0 != retVal ) {
17109 return -1;
17112 break;
17113 } else {
17114 DIP("mfhi r%u", rd);
17115 putIReg(rd, getHI());
17116 break;
17120 case 0x11: { /* MTHI, CLO R6 */
17121 if (((instr_index >> 6) & 0x1f) == 1) { /* CLO */
17122 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
17123 DIP("clo r%u, r%u", rd, rs);
17125 if (mode64) {
17126 IRTemp tmpClo32 = newTemp(Ity_I32);
17127 IRTemp tmpRs32 = newTemp(Ity_I32);
17128 assign(tmpRs32, mkNarrowTo32(ty, getIReg(rs)));
17130 t1 = newTemp(Ity_I1);
17131 assign(t1, binop(Iop_CmpEQ32, mkexpr(tmpRs32), mkU32(0xffffffff)));
17132 assign(tmpClo32, IRExpr_ITE(mkexpr(t1),
17133 mkU32(0x00000020),
17134 unop(Iop_Clz32, unop(Iop_Not32, mkexpr(tmpRs32)))));
17136 putIReg(rd, mkWidenFrom32(ty, mkexpr(tmpClo32), True));
17137 break;
17138 } else {
17139 t1 = newTemp(Ity_I1);
17140 assign(t1, binop(Iop_CmpEQ32, getIReg(rs), mkU32(0xffffffff)));
17141 putIReg(rd, IRExpr_ITE(mkexpr(t1),
17142 mkU32(0x00000020),
17143 unop(Iop_Clz32,
17144 unop(Iop_Not32, getIReg(rs)))));
17146 } else {
17147 ILLEGAL_INSTRUCTON;
17150 break;
17151 } else if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
17152 /* If DSP is present -> DSP ASE MTHI */
17153 UInt retVal = disDSPInstr_MIPS_WRK ( cins );
17155 if (0 != retVal ) {
17156 return -1;
17159 break;
17160 } else {
17161 DIP("mthi r%u", rs);
17162 putHI(getIReg(rs));
17163 break;
17167 case 0x12: { /* MFLO */
17168 if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
17169 /* If DSP is present -> DSP ASE MFLO */
17170 UInt retVal = disDSPInstr_MIPS_WRK ( cins );
17172 if (0 != retVal ) {
17173 return -1;
17176 break;
17177 } else {
17178 switch (sa) {
17179 case 0:
17180 DIP("mflo r%u", rd);
17182 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps) &&
17183 !VEX_MIPS_CPU_HAS_MIPS32R2(archinfo->hwcaps)) {
17184 ILLEGAL_INSTRUCTON
17187 putIReg(rd, getLO());
17188 break;
17190 case 1:
17191 DIP("dclz r%u, r%u", rd, rs);
17192 t1 = newTemp(Ity_I1);
17193 assign(t1, binop(Iop_CmpEQ64, getIReg(rs), mkU64(0)));
17194 putIReg(rd, IRExpr_ITE(mkexpr(t1),
17195 mkU64(0x00000040),
17196 unop(Iop_Clz64, getIReg(rs))));
17197 break;
17200 break;
17204 case 0x13: { /* MTLO */
17205 if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
17206 /* If DSP is present -> DSP ASE MTLO */
17207 UInt retVal = disDSPInstr_MIPS_WRK ( cins );
17209 if (0 != retVal ) {
17210 return -1;
17213 break;
17214 } else {
17215 switch (sa) {
17216 case 0:
17217 DIP("mtlo r%u", rs);
17219 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps) &&
17220 !VEX_MIPS_CPU_HAS_MIPS32R2(archinfo->hwcaps)) {
17221 ILLEGAL_INSTRUCTON
17224 putLO(getIReg(rs));
17225 break;
17227 case 1:
17228 DIP("dclo r%u, r%u", rd, rs);
17229 t1 = newTemp(Ity_I1);
17230 assign(t1, binop(Iop_CmpEQ64, getIReg(rs),
17231 mkU64(0xffffffffffffffffULL)));
17232 putIReg(rd, IRExpr_ITE(mkexpr(t1),
17233 mkU64(0x40),
17234 unop(Iop_Clz64, unop(Iop_Not64,
17235 getIReg(rs)))));
17236 break;
17239 break;
17243 case 0x15: { /* DLSA */
17244 UInt imm2 = (imm & 0xC0) >> 6;
17246 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps) || has_msa) {
17247 DIP("dlsa r%u, r%u, r%u, imm: 0x%x", rd, rs, rt, imm2);
17248 putIReg(rd, binop(Iop_Add64,
17249 binop(Iop_Shl64, getIReg(rs), mkU8(imm2 + 1)),
17250 getIReg(rt)));
17251 } else {
17252 ILLEGAL_INSTRUCTON
17255 break;
17258 case 0x18: { /* MULT */
17259 switch (sa & 0x3) {
17260 case 0: {
17261 if ((1 <= ac) && ( 3 >= ac)) {
17262 if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
17263 /* If DSP is present -> DSP ASE MULT */
17264 UInt retVal = disDSPInstr_MIPS_WRK(cins);
17266 if (0 != retVal) {
17267 return -2;
17270 break;
17271 } else {
17272 return -2;
17274 } else {
17275 DIP("mult r%u, r%u", rs, rt);
17277 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps) &&
17278 !VEX_MIPS_CPU_HAS_MIPS32R2(archinfo->hwcaps)) {
17279 ILLEGAL_INSTRUCTON
17282 t2 = newTemp(Ity_I64);
17284 assign(t2, binop(Iop_MullS32, mkNarrowTo32(ty, getIReg(rs)),
17285 mkNarrowTo32(ty, getIReg(rt))));
17287 putHI(mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(t2)), True));
17288 putLO(mkWidenFrom32(ty, unop(Iop_64to32, mkexpr(t2)), True));
17289 break;
17293 case 2: { /* MUL R6 */
17294 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
17295 DIP("mul r%u, r%u, r%u", rs, rt, rd);
17297 if (mode64) {
17298 putIReg(rd, unop(Iop_32Sto64,
17299 unop(Iop_64to32,
17300 binop(Iop_MullS32,
17301 unop(Iop_64to32, getIReg(rs)),
17302 unop(Iop_64to32, getIReg(rt))))));
17303 } else {
17304 putIReg(rd, unop(Iop_64to32,
17305 binop(Iop_MullS32,
17306 getIReg(rs), getIReg(rt))));
17308 } else {
17309 ILLEGAL_INSTRUCTON;
17312 break;
17315 case 3: { /* MUH R6 */
17316 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
17317 DIP("muh r%u, r%u, r%u", rs, rt, rd);
17319 if (mode64) {
17320 putIReg(rd, unop(Iop_32Sto64,
17321 unop(Iop_64HIto32,
17322 binop(Iop_MullS32,
17323 unop(Iop_64to32, getIReg(rs)),
17324 unop(Iop_64to32, getIReg(rt))))));
17325 } else {
17326 putIReg(rd, unop(Iop_64HIto32,
17327 binop(Iop_MullS32,
17328 getIReg(rs), getIReg(rt))));
17330 } else {
17331 ILLEGAL_INSTRUCTON;
17334 break;
17338 break;
17341 case 0x19: { /* MULTU */
17342 switch (sa & 0x3) {
17343 case 0: {
17344 if ((1 <= ac) && ( 3 >= ac)) {
17345 if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
17346 /* If DSP is present -> DSP ASE MULTU */
17347 UInt retVal = disDSPInstr_MIPS_WRK ( cins );
17349 if (0 != retVal) {
17350 return -2;
17353 break;
17354 } else {
17355 return -2;
17357 } else {
17358 DIP("multu r%u, r%u", rs, rt);
17360 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps) &&
17361 !VEX_MIPS_CPU_HAS_MIPS32R2(archinfo->hwcaps)) {
17362 ILLEGAL_INSTRUCTON
17365 t2 = newTemp(Ity_I64);
17367 assign(t2, binop(Iop_MullU32, mkNarrowTo32(ty, getIReg(rs)),
17368 mkNarrowTo32(ty, getIReg(rt))));
17370 putHI(mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(t2)), True));
17371 putLO(mkWidenFrom32(ty, unop(Iop_64to32, mkexpr(t2)), True));
17372 break;
17376 case 2: { /* MULU R6 */
17377 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
17378 DIP("mulu r%u, r%u, r%u", rs, rt, rd);
17380 if (mode64) {
17381 putIReg(rd, unop(Iop_32Uto64,
17382 unop(Iop_64to32,
17383 binop(Iop_MullU32,
17384 unop(Iop_64to32, getIReg(rs)),
17385 unop(Iop_64to32, getIReg(rt))))));
17386 } else {
17387 putIReg(rd, unop(Iop_64to32,
17388 binop(Iop_MullU32,
17389 getIReg(rs), getIReg(rt))));
17391 } else {
17392 ILLEGAL_INSTRUCTON;
17395 break;
17398 case 3: { /* MUHU R6 */
17399 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
17400 DIP("muhu r%u, r%u, r%u", rs, rt, rd);
17402 if (mode64) {
17403 putIReg(rd, unop(Iop_32Uto64,
17404 unop(Iop_64HIto32,
17405 binop(Iop_MullU32,
17406 unop(Iop_64to32, getIReg(rs)),
17407 unop(Iop_64to32, getIReg(rt))))));
17408 } else {
17409 putIReg(rd, unop(Iop_64HIto32,
17410 binop(Iop_MullU32,
17411 getIReg(rs), getIReg(rt))));
17413 } else {
17414 ILLEGAL_INSTRUCTON;
17417 break;
17421 break;
17424 case 0x1A: /* DIV */
17425 switch (sa & 0x3) {
17426 case 0:
17427 DIP("div r%u, r%u", rs, rt);
17429 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps) &&
17430 !VEX_MIPS_CPU_HAS_MIPS32R2(archinfo->hwcaps)) {
17431 ILLEGAL_INSTRUCTON
17434 if (mode64) {
17435 t2 = newTemp(Ity_I64);
17437 assign(t2, binop(Iop_DivModS32to32,
17438 mkNarrowTo32(ty, getIReg(rs)),
17439 mkNarrowTo32(ty, getIReg(rt))));
17441 putHI(mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(t2)), True));
17442 putLO(mkWidenFrom32(ty, unop(Iop_64to32, mkexpr(t2)), True));
17443 } else {
17444 t1 = newTemp(Ity_I64);
17446 assign(t1, binop(Iop_DivModS32to32, getIReg(rs), getIReg(rt)));
17448 putHI(unop(Iop_64HIto32, mkexpr(t1)));
17449 putLO(unop(Iop_64to32, mkexpr(t1)));
17452 break;
17454 case 2:
17455 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
17456 DIP("div r%u, r%u, r%u", rs, rt, rd);
17458 if (mode64) {
17459 putIReg(rd, unop(Iop_32Sto64,
17460 binop(Iop_DivS32,
17461 unop(Iop_64to32, getIReg(rs)),
17462 unop(Iop_64to32, getIReg(rt)))));
17463 } else {
17464 putIReg(rd, binop(Iop_DivS32, getIReg(rs), getIReg(rt)));
17466 } else {
17467 ILLEGAL_INSTRUCTON
17470 break;
17472 case 3:
17473 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
17474 DIP("mod r%u, r%u, r%u", rs, rt, rd);
17476 if (mode64) {
17477 putIReg(rd, unop(Iop_32Sto64,
17478 unop(Iop_64HIto32,
17479 binop(Iop_DivModS32to32,
17480 unop(Iop_64to32, getIReg(rs)),
17481 unop(Iop_64to32, getIReg(rt))))));
17482 } else {
17483 t1 = newTemp(Ity_I64);
17485 assign(t1, binop(Iop_DivModS32to32, getIReg(rs), getIReg(rt)));
17486 putIReg(rd, unop(Iop_64HIto32, mkexpr(t1)));
17488 } else {
17489 ILLEGAL_INSTRUCTON
17492 break;
17495 break;
17497 case 0x1B: /* DIVU */
17498 switch (sa & 0x3) {
17499 case 0:
17500 DIP("divu r%u, r%u", rs, rt);
17502 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps) &&
17503 !VEX_MIPS_CPU_HAS_MIPS32R2(archinfo->hwcaps)) {
17504 ILLEGAL_INSTRUCTON
17507 if (mode64) {
17508 t1 = newTemp(Ity_I64);
17510 assign(t1, binop(Iop_DivModU32to32,
17511 mkNarrowTo32(ty, getIReg(rs)),
17512 mkNarrowTo32(ty, getIReg(rt))));
17514 putHI(mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(t1)), True));
17515 putLO(mkWidenFrom32(ty, unop(Iop_64to32, mkexpr(t1)), True));
17516 } else {
17517 t1 = newTemp(Ity_I64);
17519 assign(t1, binop(Iop_DivModU32to32, getIReg(rs), getIReg(rt)));
17520 putHI(unop(Iop_64HIto32, mkexpr(t1)));
17521 putLO(unop(Iop_64to32, mkexpr(t1)));
17524 break;
17526 case 2:
17527 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
17528 DIP("divu r%u, r%u, r%u", rs, rt, rd);
17530 if (mode64) {
17531 putIReg(rd, unop(Iop_32Sto64,
17532 binop(Iop_DivU32,
17533 unop(Iop_64to32, getIReg(rs)),
17534 unop(Iop_64to32, getIReg(rt)))));
17535 } else {
17536 putIReg(rd, binop(Iop_DivU32, getIReg(rs), getIReg(rt)));
17539 break;
17540 } else {
17541 ILLEGAL_INSTRUCTON
17544 break;
17546 case 3:
17547 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
17548 DIP("modu r%u, r%u, r%u", rs, rt, rd);
17550 if (mode64) {
17551 putIReg(rd, unop(Iop_32Uto64,
17552 unop(Iop_64HIto32,
17553 binop(Iop_DivModU32to32,
17554 unop(Iop_64to32, getIReg(rs)),
17555 unop(Iop_64to32, getIReg(rt))))));
17556 } else {
17557 t1 = newTemp(Ity_I64);
17559 assign(t1, binop(Iop_DivModU32to32, getIReg(rs), getIReg(rt)));
17560 putIReg(rd, unop(Iop_64HIto32, mkexpr(t1)));
17562 } else {
17563 ILLEGAL_INSTRUCTON
17566 break;
17569 break;
17571 case 0x1C: /* Doubleword Multiply - DMULT; MIPS64 */
17572 switch (sa) {
17573 case 0:
17574 DIP("dmult r%u, r%u", rs, rt);
17576 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps) &&
17577 !VEX_MIPS_CPU_HAS_MIPS32R2(archinfo->hwcaps)) {
17578 ILLEGAL_INSTRUCTON
17581 t0 = newTemp(Ity_I128);
17583 assign(t0, binop(Iop_MullS64, getIReg(rs), getIReg(rt)));
17585 putHI(unop(Iop_128HIto64, mkexpr(t0)));
17586 putLO(unop(Iop_128to64, mkexpr(t0)));
17587 break;
17589 case 2: /* DMUL */
17590 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
17591 DIP("dmul r%u, r%u, r%u", rd, rs, rt);
17592 putIReg(rd, unop(Iop_128to64,
17593 binop(Iop_MullS64, getIReg(rs), getIReg(rt))));
17594 } else {
17595 ILLEGAL_INSTRUCTON
17598 break;
17600 case 3: /* DMUH */
17601 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
17602 DIP("dmuh r%u, r%u, r%u", rd, rs, rt);
17603 putIReg(rd, unop(Iop_128HIto64,
17604 binop(Iop_MullS64, getIReg(rs), getIReg(rt))));
17605 } else {
17606 ILLEGAL_INSTRUCTON
17609 break;
17612 break;
17614 case 0x1D: /* Doubleword Multiply Unsigned - DMULTU; MIPS64 */
17615 switch (sa) {
17616 case 0:
17617 DIP("dmultu r%u, r%u", rs, rt);
17619 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps) &&
17620 !VEX_MIPS_CPU_HAS_MIPS32R2(archinfo->hwcaps)) {
17621 ILLEGAL_INSTRUCTON
17624 t0 = newTemp(Ity_I128);
17626 assign(t0, binop(Iop_MullU64, getIReg(rs), getIReg(rt)));
17628 putHI(unop(Iop_128HIto64, mkexpr(t0)));
17629 putLO(unop(Iop_128to64, mkexpr(t0)));
17630 break;
17632 case 2: /* DMULU */
17633 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
17634 DIP("dmulu r%u, r%u, r%u", rd, rs, rt);
17635 putIReg(rd, unop(Iop_128to64,
17636 binop(Iop_MullU64, getIReg(rs), getIReg(rt))));
17637 } else {
17638 ILLEGAL_INSTRUCTON
17641 break;
17643 case 3: /* DMUHU */
17644 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
17645 DIP("dmuhu r%u, r%u, r%u", rd, rs, rt);
17646 putIReg(rd, unop(Iop_128HIto64,
17647 binop(Iop_MullU64, getIReg(rs), getIReg(rt))));
17648 } else {
17649 ILLEGAL_INSTRUCTON
17652 break;
17655 break;
17657 case 0x1E: /* Doubleword Divide DDIV; MIPS64 */
17658 switch (sa) {
17659 case 0:
17660 DIP("ddiv r%u, r%u", rs, rt);
17662 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps) &&
17663 !VEX_MIPS_CPU_HAS_MIPS32R2(archinfo->hwcaps)) {
17664 ILLEGAL_INSTRUCTON
17667 t1 = newTemp(Ity_I128);
17669 assign(t1, binop(Iop_DivModS64to64, getIReg(rs), getIReg(rt)));
17671 putHI(unop(Iop_128HIto64, mkexpr(t1)));
17672 putLO(unop(Iop_128to64, mkexpr(t1)));
17673 break;
17675 case 2: /* DDIV r6 */
17676 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
17677 DIP("ddiv r%u, r%u, r%u", rs, rt, rd);
17678 putIReg(rd, unop(Iop_128to64,
17679 binop(Iop_DivModS64to64,
17680 getIReg(rs), getIReg(rt))));
17681 } else {
17682 ILLEGAL_INSTRUCTON
17685 break;
17687 case 3: /* DMOD r6 */
17688 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
17689 DIP("dmod r%u, r%u, r%u", rs, rt, rd);
17690 t2 = newTemp(Ity_I128);
17691 assign(t2, binop(Iop_DivModS64to64, getIReg(rs), getIReg(rt)));
17692 putIReg(rd, unop(Iop_128HIto64, mkexpr(t2)));
17693 } else {
17694 ILLEGAL_INSTRUCTON
17697 break;
17700 break;
17702 case 0x1F: /* Doubleword Divide Unsigned DDIVU; MIPS64 check this */
17703 switch (sa) {
17704 case 0:
17705 DIP("ddivu r%u, r%u", rs, rt);
17707 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps) &&
17708 !VEX_MIPS_CPU_HAS_MIPS32R2(archinfo->hwcaps)) {
17709 ILLEGAL_INSTRUCTON
17712 t1 = newTemp(Ity_I128);
17714 assign(t1, binop(Iop_DivModU64to64, getIReg(rs), getIReg(rt)));
17716 putHI(unop(Iop_128HIto64, mkexpr(t1)));
17717 putLO(unop(Iop_128to64, mkexpr(t1)));
17718 break;
17720 case 2:
17721 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
17722 DIP("ddivu r%u, r%u, r%u", rs, rt, rd);
17723 putIReg(rd, unop(Iop_128to64, binop(Iop_DivModU64to64,
17724 getIReg(rs), getIReg(rt))));
17725 } else {
17726 ILLEGAL_INSTRUCTON
17729 break;
17731 case 3:
17732 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
17733 DIP("dmodu r%u, r%u, r%u", rs, rt, rd);
17734 putIReg(rd, unop(Iop_128HIto64, binop(Iop_DivModU64to64,
17735 getIReg(rs), getIReg(rt))));
17736 } else {
17737 ILLEGAL_INSTRUCTON
17740 break;
17743 break;
17745 case 0x20: { /* ADD */
17746 DIP("add r%u, r%u, r%u", rd, rs, rt);
17747 IRTemp tmpRs32 = newTemp(Ity_I32);
17748 IRTemp tmpRt32 = newTemp(Ity_I32);
17750 assign(tmpRs32, mkNarrowTo32(ty, getIReg(rs)));
17751 assign(tmpRt32, mkNarrowTo32(ty, getIReg(rt)));
17753 t0 = newTemp(Ity_I32);
17754 t1 = newTemp(Ity_I32);
17755 t2 = newTemp(Ity_I32);
17756 t3 = newTemp(Ity_I32);
17757 t4 = newTemp(Ity_I32);
17758 /* dst = src0 + src1
17759 if (sign(src0 ) != sign(src1 ))
17760 goto no overflow;
17761 if (sign(dst) == sign(src0 ))
17762 goto no overflow;
17763 we have overflow! */
17765 assign(t0, binop(Iop_Add32, mkexpr(tmpRs32), mkexpr(tmpRt32)));
17766 assign(t1, binop(Iop_Xor32, mkexpr(tmpRs32), mkexpr(tmpRt32)));
17767 assign(t2, unop(Iop_1Uto32,
17768 binop(Iop_CmpEQ32,
17769 binop(Iop_And32, mkexpr(t1), mkU32(0x80000000)),
17770 mkU32(0x80000000))));
17772 assign(t3, binop(Iop_Xor32, mkexpr(t0), mkexpr(tmpRs32)));
17773 assign(t4, unop(Iop_1Uto32,
17774 binop(Iop_CmpNE32,
17775 binop(Iop_And32, mkexpr(t3), mkU32(0x80000000)),
17776 mkU32(0x80000000))));
17778 stmt(IRStmt_Exit(binop(Iop_CmpEQ32,
17779 binop(Iop_Or32, mkexpr(t2), mkexpr(t4)),
17780 mkU32(0)),
17781 Ijk_SigFPE_IntOvf,
17782 mode64 ? IRConst_U64(guest_PC_curr_instr + 4) :
17783 IRConst_U32(guest_PC_curr_instr + 4),
17784 OFFB_PC));
17786 putIReg(rd, mkWidenFrom32(ty, mkexpr(t0), True));
17787 break;
17790 case 0x21: /* ADDU */
17791 DIP("addu r%u, r%u, r%u", rd, rs, rt);
17793 if (mode64) {
17794 ALU_PATTERN64(Iop_Add32);
17795 } else {
17796 ALU_PATTERN(Iop_Add32);
17799 break;
17801 case 0x22: { /* SUB */
17802 DIP("sub r%u, r%u, r%u", rd, rs, rt);
17803 IRTemp tmpRs32 = newTemp(Ity_I32);
17804 IRTemp tmpRt32 = newTemp(Ity_I32);
17806 assign(tmpRs32, mkNarrowTo32(ty, getIReg(rs)));
17807 assign(tmpRt32, mkNarrowTo32(ty, getIReg(rt)));
17808 t0 = newTemp(Ity_I32);
17809 t1 = newTemp(Ity_I32);
17810 t2 = newTemp(Ity_I32);
17811 t3 = newTemp(Ity_I32);
17812 t4 = newTemp(Ity_I32);
17813 t5 = newTemp(Ity_I32);
17814 /* dst = src0 + (-1 * src1)
17815 if(sign(src0 ) != sign((-1 * src1) ))
17816 goto no overflow;
17817 if(sign(dst) == sign(src0 ))
17818 goto no overflow;
17819 we have overflow! */
17821 assign(t5, binop(Iop_Mul32, mkexpr(tmpRt32), mkU32(-1)));
17822 assign(t0, binop(Iop_Add32, mkexpr(tmpRs32), mkexpr(t5)));
17823 assign(t1, binop(Iop_Xor32, mkexpr(tmpRs32), mkexpr(t5)));
17824 assign(t2, unop(Iop_1Sto32, binop(Iop_CmpEQ32, binop(Iop_And32,
17825 mkexpr(t1), mkU32(0x80000000)), mkU32(0x80000000))));
17827 assign(t3, binop(Iop_Xor32, mkexpr(t0), mkexpr(tmpRs32)));
17828 assign(t4, unop(Iop_1Sto32, binop(Iop_CmpNE32, binop(Iop_And32,
17829 mkexpr(t3), mkU32(0x80000000)), mkU32(0x80000000))));
17831 stmt(IRStmt_Exit(binop(Iop_CmpEQ32, binop(Iop_Or32, mkexpr(t2),
17832 mkexpr(t4)), mkU32(0)), Ijk_SigFPE_IntOvf,
17833 mode64 ? IRConst_U64(guest_PC_curr_instr + 4) :
17834 IRConst_U32(guest_PC_curr_instr + 4),
17835 OFFB_PC));
17837 putIReg(rd, mkWidenFrom32(ty, mkexpr(t0), True));
17838 break;
17841 case 0x23: /* SUBU */
17842 DIP("subu r%u, r%u, r%u", rd, rs, rt);
17844 if (mode64) {
17845 ALU_PATTERN64(Iop_Sub32);
17846 } else {
17847 ALU_PATTERN(Iop_Sub32);
17850 break;
17852 case 0x24: /* AND */
17853 DIP("and r%u, r%u, r%u", rd, rs, rt);
17855 if (mode64) {
17856 ALU_PATTERN(Iop_And64);
17857 } else {
17858 ALU_PATTERN(Iop_And32);
17861 break;
17863 case 0x25: /* OR */
17864 DIP("or r%u, r%u, r%u", rd, rs, rt);
17866 if (mode64) {
17867 ALU_PATTERN(Iop_Or64);
17868 } else {
17869 ALU_PATTERN(Iop_Or32);
17872 break;
17874 case 0x26: /* XOR */
17875 DIP("xor r%u, r%u, r%u", rd, rs, rt);
17877 if (mode64) {
17878 ALU_PATTERN(Iop_Xor64);
17879 } else {
17880 ALU_PATTERN(Iop_Xor32);
17883 break;
17885 case 0x27: /* NOR */
17886 DIP("nor r%u, r%u, r%u", rd, rs, rt);
17888 if (mode64)
17889 putIReg(rd, unop(Iop_Not64, binop(Iop_Or64, getIReg(rs),
17890 getIReg(rt))));
17891 else
17892 putIReg(rd, unop(Iop_Not32, binop(Iop_Or32, getIReg(rs),
17893 getIReg(rt))));
17895 break;
17897 case 0x2A: /* SLT */
17898 DIP("slt r%u, r%u, r%u", rd, rs, rt);
17900 if (mode64)
17901 putIReg(rd, unop(Iop_1Uto64, binop(Iop_CmpLT64S, getIReg(rs),
17902 getIReg(rt))));
17903 else
17904 putIReg(rd, unop(Iop_1Uto32, binop(Iop_CmpLT32S, getIReg(rs),
17905 getIReg(rt))));
17907 break;
17909 case 0x2B: /* SLTU */
17910 DIP("sltu r%u, r%u, r%u", rd, rs, rt);
17912 if (mode64)
17913 putIReg(rd, unop(Iop_1Uto64, binop(Iop_CmpLT64U, getIReg(rs),
17914 getIReg(rt))));
17915 else
17916 putIReg(rd, unop(Iop_1Uto32, binop(Iop_CmpLT32U, getIReg(rs),
17917 getIReg(rt))));
17919 break;
17921 case 0x2C: { /* Doubleword Add - DADD; MIPS64 */
17922 DIP("dadd r%u, r%u, r%u", rd, rs, rt);
17923 IRTemp tmpRs64 = newTemp(Ity_I64);
17924 IRTemp tmpRt64 = newTemp(Ity_I64);
17926 assign(tmpRs64, getIReg(rs));
17927 assign(tmpRt64, getIReg(rt));
17929 t0 = newTemp(Ity_I64);
17930 t1 = newTemp(Ity_I64);
17931 t2 = newTemp(Ity_I64);
17932 t3 = newTemp(Ity_I64);
17933 t4 = newTemp(Ity_I64);
17934 /* dst = src0 + src1
17935 if(sign(src0 ) != sign(src1 ))
17936 goto no overflow;
17937 if(sign(dst) == sign(src0 ))
17938 goto no overflow;
17939 we have overflow! */
17941 assign(t0, binop(Iop_Add64, mkexpr(tmpRs64), mkexpr(tmpRt64)));
17942 assign(t1, binop(Iop_Xor64, mkexpr(tmpRs64), mkexpr(tmpRt64)));
17943 assign(t2, unop(Iop_1Uto64,
17944 binop(Iop_CmpEQ64,
17945 binop(Iop_And64, mkexpr(t1),
17946 mkU64(0x8000000000000000ULL)),
17947 mkU64(0x8000000000000000ULL))));
17949 assign(t3, binop(Iop_Xor64, mkexpr(t0), mkexpr(tmpRs64)));
17950 assign(t4, unop(Iop_1Uto64,
17951 binop(Iop_CmpNE64,
17952 binop(Iop_And64, mkexpr(t3),
17953 mkU64(0x8000000000000000ULL)),
17954 mkU64(0x8000000000000000ULL))));
17956 stmt(IRStmt_Exit(binop(Iop_CmpEQ64,
17957 binop(Iop_Or64, mkexpr(t2), mkexpr(t4)),
17958 mkU64(0)),
17959 Ijk_SigFPE_IntOvf,
17960 IRConst_U64(guest_PC_curr_instr + 4),
17961 OFFB_PC));
17963 putIReg(rd, mkexpr(t0));
17964 break;
17967 case 0x2D: /* Doubleword Add Unsigned - DADDU; MIPS64 */
17968 DIP("daddu r%u, r%u, r%u", rd, rs, rt);
17969 ALU_PATTERN(Iop_Add64);
17970 break;
17972 case 0x2E: { /* Doubleword Subtract - DSUB; MIPS64 */
17973 DIP("dsub r%u, r%u, r%u", rd, rs, rt);
17974 IRTemp tmpRs64 = newTemp(Ity_I64);
17975 IRTemp tmpRt64 = newTemp(Ity_I64);
17977 assign(tmpRs64, getIReg(rs));
17978 assign(tmpRt64, getIReg(rt));
17979 t0 = newTemp(Ity_I64);
17980 t1 = newTemp(Ity_I64);
17981 t2 = newTemp(Ity_I64);
17982 t3 = newTemp(Ity_I64);
17983 t4 = newTemp(Ity_I64);
17984 t5 = newTemp(Ity_I64);
17985 /* dst = src0 + (-1 * src1)
17986 if(sign(src0 ) != sign((-1 * src1) ))
17987 goto no overflow;
17988 if(sign(dst) == sign(src0 ))
17989 goto no overflow;
17990 we have overflow! */
17992 assign(t5, binop(Iop_Mul64,
17993 mkexpr(tmpRt64),
17994 mkU64(0xffffffffffffffffULL)));
17995 assign(t0, binop(Iop_Add64, mkexpr(tmpRs64), mkexpr(t5)));
17996 assign(t1, binop(Iop_Xor64, mkexpr(tmpRs64), mkexpr(t5)));
17997 assign(t2, unop(Iop_1Sto64,
17998 binop(Iop_CmpEQ64,
17999 binop(Iop_And64,
18000 mkexpr(t1),
18001 mkU64(0x8000000000000000ULL)),
18002 mkU64(0x8000000000000000ULL))));
18004 assign(t3, binop(Iop_Xor64, mkexpr(t0), mkexpr(tmpRs64)));
18005 assign(t4, unop(Iop_1Sto64,
18006 binop(Iop_CmpNE64,
18007 binop(Iop_And64,
18008 mkexpr(t3),
18009 mkU64(0x8000000000000000ULL)),
18010 mkU64(0x8000000000000000ULL))));
18012 stmt(IRStmt_Exit(binop(Iop_CmpEQ64, binop(Iop_Or64, mkexpr(t2),
18013 mkexpr(t4)), mkU64(0)), Ijk_SigFPE_IntOvf,
18014 IRConst_U64(guest_PC_curr_instr + 4),
18015 OFFB_PC));
18017 putIReg(rd, binop(Iop_Sub64, getIReg(rs), getIReg(rt)));
18018 break;
18021 case 0x2F: /* Doubleword Subtract Unsigned - DSUBU; MIPS64 */
18022 DIP("dsub r%u, r%u,r%u", rd, rt, rt);
18023 ALU_PATTERN(Iop_Sub64);
18024 break;
18026 case 0x30: { /* TGE */
18027 DIP("tge r%u, r%u %u", rs, rt, trap_code);
18029 if (mode64) {
18030 if (trap_code == 7)
18031 stmt (IRStmt_Exit (unop (Iop_Not1,
18032 binop (Iop_CmpLT64S,
18033 getIReg (rs),
18034 getIReg (rt))),
18035 Ijk_SigFPE_IntDiv,
18036 IRConst_U64(guest_PC_curr_instr + 4),
18037 OFFB_PC));
18038 else if (trap_code == 6)
18039 stmt (IRStmt_Exit (unop (Iop_Not1,
18040 binop (Iop_CmpLT64S,
18041 getIReg (rs),
18042 getIReg (rt))),
18043 Ijk_SigFPE_IntOvf,
18044 IRConst_U64(guest_PC_curr_instr + 4),
18045 OFFB_PC));
18046 else
18047 stmt (IRStmt_Exit (unop (Iop_Not1,
18048 binop (Iop_CmpLT64S,
18049 getIReg (rs),
18050 getIReg (rt))),
18051 Ijk_SigTRAP,
18052 IRConst_U64(guest_PC_curr_instr + 4),
18053 OFFB_PC));
18054 } else {
18055 if (trap_code == 7)
18056 stmt (IRStmt_Exit (unop (Iop_Not1,
18057 binop (Iop_CmpLT32S,
18058 getIReg (rs),
18059 getIReg (rt))),
18060 Ijk_SigFPE_IntDiv,
18061 IRConst_U32(guest_PC_curr_instr + 4),
18062 OFFB_PC));
18063 else if (trap_code == 6)
18064 stmt (IRStmt_Exit (unop (Iop_Not1,
18065 binop (Iop_CmpLT32S,
18066 getIReg (rs),
18067 getIReg (rt))),
18068 Ijk_SigFPE_IntOvf,
18069 IRConst_U32(guest_PC_curr_instr + 4),
18070 OFFB_PC));
18071 else
18072 stmt (IRStmt_Exit (unop (Iop_Not1,
18073 binop (Iop_CmpLT32S,
18074 getIReg (rs),
18075 getIReg (rt))),
18076 Ijk_SigTRAP,
18077 IRConst_U32(guest_PC_curr_instr + 4),
18078 OFFB_PC));
18081 break;
18084 case 0x31: { /* TGEU */
18085 DIP("tgeu r%u, r%u %u", rs, rt, trap_code);
18087 if (mode64) {
18088 if (trap_code == 7)
18089 stmt (IRStmt_Exit (unop (Iop_Not1,
18090 binop (Iop_CmpLT64U,
18091 getIReg (rs),
18092 getIReg (rt))),
18093 Ijk_SigFPE_IntDiv,
18094 IRConst_U64(guest_PC_curr_instr + 4),
18095 OFFB_PC));
18096 else if (trap_code == 6)
18097 stmt (IRStmt_Exit (unop (Iop_Not1,
18098 binop (Iop_CmpLT64U,
18099 getIReg (rs),
18100 getIReg (rt))),
18101 Ijk_SigFPE_IntOvf,
18102 IRConst_U64(guest_PC_curr_instr + 4),
18103 OFFB_PC));
18104 else
18105 stmt (IRStmt_Exit (unop (Iop_Not1,
18106 binop (Iop_CmpLT64U,
18107 getIReg (rs),
18108 getIReg (rt))),
18109 Ijk_SigTRAP,
18110 IRConst_U64(guest_PC_curr_instr + 4),
18111 OFFB_PC));
18112 } else {
18113 if (trap_code == 7)
18114 stmt (IRStmt_Exit (unop (Iop_Not1,
18115 binop (Iop_CmpLT32U,
18116 getIReg (rs),
18117 getIReg (rt))),
18118 Ijk_SigFPE_IntDiv,
18119 IRConst_U32(guest_PC_curr_instr + 4),
18120 OFFB_PC));
18121 else if (trap_code == 6)
18122 stmt (IRStmt_Exit (unop (Iop_Not1,
18123 binop (Iop_CmpLT32U,
18124 getIReg (rs),
18125 getIReg (rt))),
18126 Ijk_SigFPE_IntOvf,
18127 IRConst_U32(guest_PC_curr_instr + 4),
18128 OFFB_PC));
18129 else
18130 stmt (IRStmt_Exit (unop (Iop_Not1,
18131 binop (Iop_CmpLT32U,
18132 getIReg (rs),
18133 getIReg (rt))),
18134 Ijk_SigTRAP,
18135 IRConst_U32(guest_PC_curr_instr + 4),
18136 OFFB_PC));
18139 break;
18142 case 0x32: { /* TLT */
18143 DIP("tlt r%u, r%u %u", rs, rt, trap_code);
18145 if (mode64) {
18146 if (trap_code == 7)
18147 stmt(IRStmt_Exit(binop(Iop_CmpLT64S, getIReg(rs),
18148 getIReg(rt)), Ijk_SigFPE_IntDiv,
18149 IRConst_U64(guest_PC_curr_instr + 4),
18150 OFFB_PC));
18151 else if (trap_code == 6)
18152 stmt(IRStmt_Exit(binop(Iop_CmpLT64S, getIReg(rs),
18153 getIReg(rt)), Ijk_SigFPE_IntOvf,
18154 IRConst_U64(guest_PC_curr_instr + 4),
18155 OFFB_PC));
18156 else
18157 stmt(IRStmt_Exit(binop(Iop_CmpLT64S, getIReg(rs),
18158 getIReg(rt)), Ijk_SigTRAP,
18159 IRConst_U64(guest_PC_curr_instr + 4),
18160 OFFB_PC));
18161 } else {
18162 if (trap_code == 7)
18163 stmt(IRStmt_Exit(binop(Iop_CmpLT32S, getIReg(rs),
18164 getIReg(rt)), Ijk_SigFPE_IntDiv,
18165 IRConst_U32(guest_PC_curr_instr + 4),
18166 OFFB_PC));
18167 else if (trap_code == 6)
18168 stmt(IRStmt_Exit(binop(Iop_CmpLT32S, getIReg(rs),
18169 getIReg(rt)), Ijk_SigFPE_IntOvf,
18170 IRConst_U32(guest_PC_curr_instr + 4),
18171 OFFB_PC));
18172 else
18173 stmt(IRStmt_Exit(binop(Iop_CmpLT32S, getIReg(rs),
18174 getIReg(rt)), Ijk_SigTRAP,
18175 IRConst_U32(guest_PC_curr_instr + 4),
18176 OFFB_PC));
18179 break;
18182 case 0x33: { /* TLTU */
18183 DIP("tltu r%u, r%u %u", rs, rt, trap_code);
18185 if (mode64) {
18186 if (trap_code == 7)
18187 stmt(IRStmt_Exit(binop(Iop_CmpLT64U, getIReg(rs),
18188 getIReg(rt)), Ijk_SigFPE_IntDiv,
18189 IRConst_U64(guest_PC_curr_instr + 4),
18190 OFFB_PC));
18191 else if (trap_code == 6)
18192 stmt(IRStmt_Exit(binop(Iop_CmpLT64U, getIReg(rs),
18193 getIReg(rt)), Ijk_SigFPE_IntOvf,
18194 IRConst_U64(guest_PC_curr_instr + 4),
18195 OFFB_PC));
18196 else
18197 stmt(IRStmt_Exit(binop(Iop_CmpLT64U, getIReg(rs),
18198 getIReg(rt)), Ijk_SigTRAP,
18199 IRConst_U64(guest_PC_curr_instr + 4),
18200 OFFB_PC));
18201 } else {
18202 if (trap_code == 7)
18203 stmt(IRStmt_Exit(binop(Iop_CmpLT32U, getIReg(rs),
18204 getIReg(rt)), Ijk_SigFPE_IntDiv,
18205 IRConst_U32(guest_PC_curr_instr + 4),
18206 OFFB_PC));
18207 else if (trap_code == 6)
18208 stmt(IRStmt_Exit(binop(Iop_CmpLT32U, getIReg(rs),
18209 getIReg(rt)), Ijk_SigFPE_IntOvf,
18210 IRConst_U32(guest_PC_curr_instr + 4),
18211 OFFB_PC));
18212 else
18213 stmt(IRStmt_Exit(binop(Iop_CmpLT32U, getIReg(rs),
18214 getIReg (rt)), Ijk_SigTRAP,
18215 IRConst_U32(guest_PC_curr_instr + 4),
18216 OFFB_PC));
18219 break;
18222 case 0x34: { /* TEQ */
18223 DIP("teq r%u, r%u, %u", rs, rt, trap_code);
18225 if (mode64) {
18226 if (trap_code == 7)
18227 stmt(IRStmt_Exit(binop(Iop_CmpEQ64, getIReg(rs),
18228 getIReg(rt)), Ijk_SigFPE_IntDiv,
18229 IRConst_U64(guest_PC_curr_instr + 4),
18230 OFFB_PC));
18231 else if (trap_code == 6)
18232 stmt(IRStmt_Exit(binop(Iop_CmpEQ64, getIReg(rs),
18233 getIReg(rt)), Ijk_SigFPE_IntOvf,
18234 IRConst_U64(guest_PC_curr_instr + 4),
18235 OFFB_PC));
18236 else
18237 stmt(IRStmt_Exit(binop(Iop_CmpEQ64, getIReg(rs),
18238 getIReg(rt)), Ijk_SigTRAP,
18239 IRConst_U64(guest_PC_curr_instr + 4),
18240 OFFB_PC));
18241 } else {
18242 if (trap_code == 7)
18243 stmt(IRStmt_Exit(binop(Iop_CmpEQ32, getIReg(rs),
18244 getIReg(rt)), Ijk_SigFPE_IntDiv,
18245 IRConst_U32(guest_PC_curr_instr + 4),
18246 OFFB_PC));
18247 else if (trap_code == 6)
18248 stmt(IRStmt_Exit(binop(Iop_CmpEQ32, getIReg(rs),
18249 getIReg(rt)), Ijk_SigFPE_IntOvf,
18250 IRConst_U32(guest_PC_curr_instr + 4),
18251 OFFB_PC));
18252 else
18253 stmt(IRStmt_Exit(binop(Iop_CmpEQ32, getIReg(rs),
18254 getIReg(rt)), Ijk_SigTRAP,
18255 IRConst_U32(guest_PC_curr_instr + 4),
18256 OFFB_PC));
18259 break;
18262 case 0x35: { /* SELEQZ */
18263 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
18264 DIP("seleqz r%u, r%u, r%u", rd, rs, rt);
18266 if (mode64) {
18267 putIReg(rd, binop(Iop_And64,
18268 unop(Iop_Not64,
18269 unop(Iop_CmpwNEZ64, getIReg(rt))),
18270 getIReg(rs)));
18271 } else {
18272 putIReg(rd, binop(Iop_And32,
18273 unop(Iop_Not32,
18274 unop(Iop_CmpwNEZ32, getIReg(rt))),
18275 getIReg(rs)));
18277 } else {
18278 ILLEGAL_INSTRUCTON;
18281 break;
18284 case 0x36: { /* TNE */
18285 DIP("tne r%u, r%u %u", rs, rt, trap_code);
18287 if (mode64) {
18288 if (trap_code == 7)
18289 stmt(IRStmt_Exit(binop(Iop_CmpNE64, getIReg(rs),
18290 getIReg(rt)), Ijk_SigFPE_IntDiv,
18291 IRConst_U64(guest_PC_curr_instr + 4),
18292 OFFB_PC));
18293 else if (trap_code == 6)
18294 stmt(IRStmt_Exit(binop(Iop_CmpNE64, getIReg(rs),
18295 getIReg(rt)), Ijk_SigFPE_IntOvf,
18296 IRConst_U64(guest_PC_curr_instr + 4),
18297 OFFB_PC));
18298 else
18299 stmt(IRStmt_Exit(binop(Iop_CmpNE64, getIReg(rs),
18300 getIReg(rt)), Ijk_SigTRAP,
18301 IRConst_U64(guest_PC_curr_instr + 4),
18302 OFFB_PC));
18303 } else {
18304 if (trap_code == 7)
18305 stmt(IRStmt_Exit(binop(Iop_CmpNE32, getIReg(rs),
18306 getIReg(rt)), Ijk_SigFPE_IntDiv,
18307 IRConst_U32(guest_PC_curr_instr + 4),
18308 OFFB_PC));
18309 else if (trap_code == 6)
18310 stmt(IRStmt_Exit(binop(Iop_CmpNE32, getIReg(rs),
18311 getIReg(rt)), Ijk_SigFPE_IntOvf,
18312 IRConst_U32(guest_PC_curr_instr + 4),
18313 OFFB_PC));
18314 else
18315 stmt(IRStmt_Exit(binop(Iop_CmpNE32, getIReg(rs),
18316 getIReg(rt)), Ijk_SigTRAP,
18317 IRConst_U32(guest_PC_curr_instr + 4),
18318 OFFB_PC));
18321 break;
18324 case 0x37: { /* SELNEZ */
18325 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
18326 DIP("selnez r%u, r%u, r%u", rd, rs, rt);
18328 if (mode64) {
18329 putIReg(rd, binop(Iop_And64,
18330 unop(Iop_CmpwNEZ64, getIReg(rt)), getIReg(rs)));
18331 } else {
18332 putIReg(rd, binop(Iop_And32,
18333 unop(Iop_CmpwNEZ32, getIReg(rt)), getIReg(rs)));
18335 } else {
18336 ILLEGAL_INSTRUCTON;
18339 break;
18342 case 0x14:
18343 case 0x16:
18344 case 0x17: /* DSLLV, DROTRV:DSRLV, DSRAV */
18345 case 0x38:
18346 case 0x3A:
18347 case 0x3B: /* DSLL, DROTL:DSRL, DSRA */
18348 case 0x3C:
18349 case 0x3E:
18350 case 0x3F: /* DSLL32, DROTR32:DSRL32, DSRA32 */
18351 if (dis_instr_shrt(cins))
18352 break;
18354 return -1;
18356 default:
18357 return -1;
18360 return 0;
18363 static UInt disInstr_MIPS_WRK_Special2(UInt cins, const VexArchInfo* archinfo,
18364 const VexAbiInfo* abiinfo, DisResult* dres,
18365 IRStmt** bstmt, IRExpr** lastn)
18367 IRTemp t0, t1 = 0, t2, t3, t4, t5, t6;
18368 UInt rs, rt, rd, function;
18369 /* Additional variables for instruction fields in DSP ASE insructions */
18370 UInt ac;
18372 rs = get_rs(cins);
18373 rt = get_rt(cins);
18374 rd = get_rd(cins);
18375 function = get_function(cins);
18376 IRType ty = mode64 ? Ity_I64 : Ity_I32;
18378 ac = get_acNo(cins);
18380 switch (function) {
18381 /* Cavium Specific instructions */
18382 case 0x03:
18383 case 0x32:
18384 case 0x33: /* DMUL, CINS , CINS32 */
18385 case 0x3A:
18386 case 0x3B:
18387 case 0x2B: /* EXT, EXT32, SNE */
18389 /* CVM Compare Instructions */
18390 case 0x2A:
18391 case 0x2E:
18392 case 0x2F: /* SEQ, SEQI, SNEI */
18394 /* CPU Load, Store, Memory, and Control Instructions */
18395 case 0x18:
18396 case 0x19: /* SAA, SAAD */
18397 case 0x1F: /* LAA, LAAD, LAI, LAID */
18398 case 0x28:
18399 case 0x2C:
18400 case 0x2D: /* BADDU, POP, DPOP */
18401 if (VEX_MIPS_COMP_ID(archinfo->hwcaps) == VEX_PRID_COMP_CAVIUM) {
18402 if (dis_instr_CVM(cins))
18403 break;
18405 return -1;
18406 } else {
18407 return -1;
18410 break;
18412 case 0x02: { /* MUL */
18413 DIP("mul r%u, r%u, r%u", rd, rs, rt);
18415 if (mode64) {
18416 IRTemp tmpRs32 = newTemp(Ity_I32);
18417 IRTemp tmpRt32 = newTemp(Ity_I32);
18418 IRTemp tmpRes = newTemp(Ity_I32);
18420 assign(tmpRs32, mkNarrowTo32(ty, getIReg(rs)));
18421 assign(tmpRt32, mkNarrowTo32(ty, getIReg(rt)));
18422 assign(tmpRes, binop(Iop_Mul32,
18423 mkexpr(tmpRs32), mkexpr(tmpRt32)));
18424 putIReg(rd, mkWidenFrom32(ty, mkexpr(tmpRes), True));
18425 } else
18426 putIReg(rd, binop(Iop_Mul32, getIReg(rs), getIReg(rt)));
18428 break;
18431 case 0x00: { /* MADD */
18432 if (mode64) {
18433 DIP("madd r%u, r%u", rs, rt);
18434 t1 = newTemp(Ity_I32);
18435 t2 = newTemp(Ity_I32);
18436 t3 = newTemp(Ity_I64);
18437 t4 = newTemp(Ity_I64);
18438 t5 = newTemp(Ity_I64);
18439 t6 = newTemp(Ity_I32);
18441 assign(t1, mkNarrowTo32(ty, getHI()));
18442 assign(t2, mkNarrowTo32(ty, getLO()));
18444 assign(t3, binop(Iop_MullS32, mkNarrowTo32(ty, getIReg(rs)),
18445 mkNarrowTo32(ty, getIReg(rt))));
18447 assign(t4, binop(Iop_32HLto64, mkexpr(t1), mkexpr(t2)));
18448 assign(t5, binop(Iop_Add64, mkexpr(t3), mkexpr(t4)));
18450 putHI(mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(t5)), True));
18451 putLO(mkWidenFrom32(ty, unop(Iop_64to32, mkexpr(t5)), True));
18452 } else {
18453 if ( (1 <= ac) && ( 3 >= ac) ) {
18454 if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
18455 /* If DSP is present -> DSP ASE MADD */
18456 UInt retVal = disDSPInstr_MIPS_WRK ( cins );
18458 if (0 != retVal ) {
18459 return -2;
18462 break;
18463 } else {
18464 return -2;
18466 } else {
18467 DIP("madd r%u, r%u", rs, rt);
18468 t1 = newTemp(Ity_I32);
18469 t2 = newTemp(Ity_I32);
18470 t3 = newTemp(Ity_I64);
18471 t4 = newTemp(Ity_I32);
18472 t5 = newTemp(Ity_I32);
18473 t6 = newTemp(Ity_I32);
18475 assign(t1, getHI());
18476 assign(t2, getLO());
18478 assign(t3, binop(Iop_MullS32, getIReg(rs), getIReg(rt)));
18480 assign(t4, binop(Iop_Add32, mkexpr(t2), unop(Iop_64to32,
18481 mkexpr(t3))));
18483 assign(t5, unop(Iop_1Uto32, binop(Iop_CmpLT32U, mkexpr(t4),
18484 unop(Iop_64to32, mkexpr(t3)))));
18485 assign(t6, binop(Iop_Add32, mkexpr(t5), mkexpr(t1)));
18487 putHI(binop(Iop_Add32, mkexpr(t6), unop(Iop_64HIto32,
18488 mkexpr(t3))));
18489 putLO(mkexpr(t4));
18490 break;
18494 break;
18497 case 0x01: { /* MADDU */
18498 if (mode64) {
18499 DIP("maddu r%u, r%u", rs, rt);
18500 t1 = newTemp(Ity_I32);
18501 t2 = newTemp(Ity_I32);
18502 t3 = newTemp(Ity_I64);
18503 t4 = newTemp(Ity_I64);
18504 t5 = newTemp(Ity_I64);
18505 t6 = newTemp(Ity_I32);
18507 assign(t1, mkNarrowTo32(ty, getHI()));
18508 assign(t2, mkNarrowTo32(ty, getLO()));
18510 assign(t3, binop(Iop_MullU32, mkNarrowTo32(ty, getIReg(rs)),
18511 mkNarrowTo32(ty, getIReg(rt))));
18513 assign(t4, binop(Iop_32HLto64, mkexpr(t1), mkexpr(t2)));
18514 assign(t5, binop(Iop_Add64, mkexpr(t3), mkexpr(t4)));
18516 putHI(mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(t5)), True));
18517 putLO(mkWidenFrom32(ty, unop(Iop_64to32, mkexpr(t5)), True));
18518 } else {
18519 if ( (1 <= ac) && ( 3 >= ac) ) {
18520 if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
18521 /* If DSP is present -> DSP ASE MADDU */
18522 UInt retVal = disDSPInstr_MIPS_WRK ( cins );
18524 if (0 != retVal ) {
18525 return -2;
18528 break;
18529 } else {
18530 return -2;
18532 } else {
18533 DIP("maddu r%u, r%u", rs, rt);
18534 t1 = newTemp(Ity_I32);
18535 t2 = newTemp(Ity_I32);
18536 t3 = newTemp(Ity_I64);
18537 t4 = newTemp(Ity_I32);
18538 t5 = newTemp(Ity_I32);
18539 t6 = newTemp(Ity_I32);
18541 assign(t1, getHI());
18542 assign(t2, getLO());
18544 assign(t3, binop(Iop_MullU32, getIReg(rs), getIReg(rt)));
18546 assign(t4, binop(Iop_Add32, mkexpr(t2), unop(Iop_64to32,
18547 mkexpr(t3))));
18548 assign(t5, unop(Iop_1Uto32, binop(Iop_CmpLT32U, mkexpr(t4),
18549 unop(Iop_64to32, mkexpr(t3)))));
18550 assign(t6, binop(Iop_Add32, mkexpr(t5), mkexpr(t1)));
18552 putHI(binop(Iop_Add32, mkexpr(t6), unop(Iop_64HIto32,
18553 mkexpr(t3))));
18554 putLO(mkexpr(t4));
18555 break;
18559 break;
18562 case 0x04: { /* MSUB */
18563 if (mode64) {
18564 DIP("msub r%u, r%u", rs, rt);
18565 t1 = newTemp(Ity_I32);
18566 t2 = newTemp(Ity_I32);
18567 t3 = newTemp(Ity_I64);
18568 t4 = newTemp(Ity_I64);
18569 t5 = newTemp(Ity_I64);
18570 t6 = newTemp(Ity_I32);
18572 assign(t1, mkNarrowTo32(ty, getHI()));
18573 assign(t2, mkNarrowTo32(ty, getLO()));
18575 assign(t3, binop(Iop_MullS32, mkNarrowTo32(ty, getIReg(rs)),
18576 mkNarrowTo32(ty, getIReg(rt))));
18578 assign(t4, binop(Iop_32HLto64, mkexpr(t1), mkexpr(t2)));
18579 assign(t5, binop(Iop_Sub64, mkexpr(t4), mkexpr(t3)));
18581 putHI(mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(t5)), True));
18582 putLO(mkWidenFrom32(ty, unop(Iop_64to32, mkexpr(t5)), True));
18583 } else {
18584 if ( (1 <= ac) && ( 3 >= ac) ) {
18585 if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
18586 /* If DSP is present -> DSP ASE MSUB */
18587 UInt retVal = disDSPInstr_MIPS_WRK ( cins );
18589 if (0 != retVal ) {
18590 return -2;
18593 break;
18594 } else {
18595 return -2;
18597 } else {
18598 DIP("msub r%u, r%u", rs, rt);
18599 t1 = newTemp(Ity_I32);
18600 t2 = newTemp(Ity_I32);
18601 t3 = newTemp(Ity_I64);
18602 t4 = newTemp(Ity_I32);
18603 t5 = newTemp(Ity_I1);
18604 t6 = newTemp(Ity_I32);
18606 assign(t1, getHI());
18607 assign(t2, getLO());
18609 assign(t3, binop(Iop_MullS32, getIReg(rs), getIReg(rt)));
18610 assign(t4, unop(Iop_64to32, mkexpr(t3))); /* new lo */
18612 /* if lo<lo(mul) hi = hi - 1 */
18613 assign(t5, binop(Iop_CmpLT32U,
18614 mkexpr(t2),
18615 mkexpr(t4)));
18617 assign(t6, IRExpr_ITE(mkexpr(t5),
18618 binop(Iop_Sub32, mkexpr(t1), mkU32(0x1)),
18619 mkexpr(t1)));
18621 putHI(binop(Iop_Sub32, mkexpr(t6), unop(Iop_64HIto32,
18622 mkexpr(t3))));
18623 putLO(binop(Iop_Sub32, mkexpr(t2), mkexpr(t4)));
18624 break;
18628 break;
18631 case 0x05: { /* MSUBU */
18632 if (mode64) {
18633 DIP("msubu r%u, r%u", rs, rt);
18634 t1 = newTemp(Ity_I32);
18635 t2 = newTemp(Ity_I32);
18636 t3 = newTemp(Ity_I64);
18637 t4 = newTemp(Ity_I64);
18638 t5 = newTemp(Ity_I64);
18639 t6 = newTemp(Ity_I32);
18641 assign(t1, mkNarrowTo32(ty, getHI()));
18642 assign(t2, mkNarrowTo32(ty, getLO()));
18644 assign(t3, binop(Iop_MullU32, mkNarrowTo32(ty, getIReg(rs)),
18645 mkNarrowTo32(ty, getIReg(rt))));
18647 assign(t4, binop(Iop_32HLto64, mkexpr(t1), mkexpr(t2)));
18648 assign(t5, binop(Iop_Sub64, mkexpr(t4), mkexpr(t3)));
18650 putHI(mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(t5)), True));
18651 putLO(mkWidenFrom32(ty, unop(Iop_64to32, mkexpr(t5)), True));
18652 } else {
18653 if ( (1 <= ac) && ( 3 >= ac) ) {
18654 if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
18655 /* If DSP is present -> DSP ASE MSUBU */
18656 UInt retVal = disDSPInstr_MIPS_WRK ( cins );
18658 if (0 != retVal ) {
18659 return -2;
18662 break;
18663 } else {
18664 return -2;
18666 } else {
18667 DIP("msubu r%u, r%u", rs, rt);
18668 t1 = newTemp(Ity_I32);
18669 t2 = newTemp(Ity_I32);
18670 t3 = newTemp(Ity_I64);
18671 t4 = newTemp(Ity_I32);
18672 t5 = newTemp(Ity_I1);
18673 t6 = newTemp(Ity_I32);
18675 assign(t1, getHI());
18676 assign(t2, getLO());
18678 assign(t3, binop(Iop_MullU32, getIReg(rs), getIReg(rt)));
18679 assign(t4, unop(Iop_64to32, mkexpr(t3))); /* new lo */
18681 /* if lo<lo(mul) hi = hi - 1 */
18682 assign(t5, binop(Iop_CmpLT32U,
18683 mkexpr(t2),
18684 mkexpr(t4)));
18686 assign(t6, IRExpr_ITE(mkexpr(t5),
18687 binop(Iop_Sub32,
18688 mkexpr(t1),
18689 mkU32(0x1)),
18690 mkexpr(t1)));
18692 putHI(binop(Iop_Sub32, mkexpr(t6), unop(Iop_64HIto32,
18693 mkexpr(t3))));
18694 putLO(binop(Iop_Sub32, mkexpr(t2), mkexpr(t4)));
18695 break;
18699 break;
18702 case 0x6: /* dmul MIPS64 - Netlogic */
18703 DIP("dmul r%u, r%u, r%u", rd, rs, rt);
18704 t0 = newTemp(Ity_I128);
18706 assign(t0, binop(Iop_MullU64, getIReg(rs), getIReg(rt)));
18708 putIReg(rd, unop(Iop_128to64, mkexpr(t0)));
18709 break;
18711 case 0x10: /* LDADDW - Swap Word - Netlogic */
18712 DIP("ldaddw r%u, r%u", rt, rs);
18713 t0 = newTemp(Ity_I32);
18714 t1 = newTemp(Ity_I32);
18715 t2 = newTemp(Ity_I32);
18716 t3 = newTemp(Ity_I64);
18717 t4 = newTemp(Ity_I32);
18718 t5 = newTemp(Ity_I32);
18719 t6 = newTemp(Ity_I32);
18721 /* v = GPR[rt] */
18722 assign(t0, mkNarrowTo32(ty, getIReg(rt)));
18724 /* GPR[rt] = memory[base]; */
18725 assign(t1, load(Ity_I32, getIReg(rs)));
18726 putIReg(rt, mkWidenFrom32(ty, mkexpr(t1), True));
18728 /* memory[base] = memory[base] + v; */
18729 store(getIReg(rs), binop(Iop_Add32, mkexpr(t0), mkexpr(t1)));
18730 break;
18732 case 0x12: /* LDADDD - Swap Word - Netlogic */
18733 DIP("ldaddw r%u, r%u", rt, rs);
18734 t0 = newTemp(Ity_I64);
18735 t1 = newTemp(Ity_I64);
18737 /* v = GPR[rt] */
18738 assign(t0, getIReg(rt));
18740 /* GPR[rt] = memory[base]; */
18741 assign(t1, load(Ity_I64, getIReg(rs)));
18742 putIReg(rt, mkexpr(t1));
18744 /* memory[base] = memory[base] + v; */
18745 store(getIReg(rs), binop(Iop_Add64, mkexpr(t0), mkexpr(t1)));
18746 break;
18748 case 0x14: /* SWAPW - Swap Word - Netlogic */
18749 DIP("swapw r%u, r%u", rt, rs);
18750 t0 = newTemp(Ity_I32);
18751 t1 = newTemp(Ity_I32);
18752 assign(t0, mkNarrowTo32(ty, getIReg(rt)));
18753 assign(t1, load(Ity_I32, getIReg(rs)));
18754 putIReg(rt, mkWidenFrom32(ty, mkexpr(t1), True));
18755 store(getIReg(rs), mkexpr(t0));
18756 break;
18758 case 0x16: /* SWAPD - Swap Double - Netlogic */
18759 DIP("swapw r%u, r%u", rt, rs);
18760 t0 = newTemp(Ity_I64);
18761 t1 = newTemp(Ity_I64);
18762 assign(t0, getIReg(rt));
18763 assign(t1, load(Ity_I64, getIReg(rs)));
18764 putIReg(rt, mkexpr(t1));
18765 store(getIReg(rs), mkexpr(t0));
18766 break;
18768 case 0x20: { /* CLZ */
18769 DIP("clz r%u, r%u", rd, rs);
18771 if (mode64) {
18772 IRTemp tmpClz32 = newTemp(Ity_I32);
18773 IRTemp tmpRs32 = newTemp(Ity_I32);
18775 assign(tmpRs32, mkNarrowTo32(ty, getIReg(rs)));
18776 assign(tmpClz32, unop(Iop_Clz32, mkexpr(tmpRs32)));
18777 putIReg(rd, mkWidenFrom32(ty, mkexpr(tmpClz32), True));
18778 } else {
18779 t1 = newTemp(Ity_I1);
18780 assign(t1, binop(Iop_CmpEQ32, getIReg(rs), mkU32(0)));
18781 putIReg(rd, IRExpr_ITE(mkexpr(t1),
18782 mkU32(0x00000020),
18783 unop(Iop_Clz32, getIReg(rs))));
18786 break;
18789 case 0x21: { /* CLO */
18790 DIP("clo r%u, r%u", rd, rs);
18792 if (mode64) {
18793 IRTemp tmpClo32 = newTemp(Ity_I32);
18794 IRTemp tmpRs32 = newTemp(Ity_I32);
18795 assign(tmpRs32, mkNarrowTo32(ty, getIReg(rs)));
18797 t1 = newTemp(Ity_I1);
18798 assign(t1, binop(Iop_CmpEQ32, mkexpr(tmpRs32), mkU32(0xffffffff)));
18799 assign(tmpClo32, IRExpr_ITE(mkexpr(t1),
18800 mkU32(0x00000020),
18801 unop(Iop_Clz32, unop(Iop_Not32, mkexpr(tmpRs32)))));
18803 putIReg(rd, mkWidenFrom32(ty, mkexpr(tmpClo32), True));
18804 break;
18805 } else {
18806 t1 = newTemp(Ity_I1);
18807 assign(t1, binop(Iop_CmpEQ32, getIReg(rs), mkU32(0xffffffff)));
18808 putIReg(rd, IRExpr_ITE(mkexpr(t1),
18809 mkU32(0x00000020),
18810 unop(Iop_Clz32,
18811 unop(Iop_Not32, getIReg(rs)))));
18812 break;
18816 case 0x24: /* Count Leading Zeros in Doubleword - DCLZ; MIPS64 */
18817 DIP("dclz r%u, r%u", rd, rs);
18818 t1 = newTemp(Ity_I1);
18819 assign(t1, binop(Iop_CmpEQ64, getIReg(rs), mkU64(0)));
18820 putIReg(rd, IRExpr_ITE(mkexpr(t1),
18821 mkU64(0x00000040),
18822 unop(Iop_Clz64, getIReg(rs))));
18823 break;
18825 case 0x25: /* Count Leading Ones in Doubleword - DCLO; MIPS64 */
18826 DIP("dclo r%u, r%u", rd, rs);
18827 t1 = newTemp(Ity_I1);
18828 assign(t1, binop(Iop_CmpEQ64, getIReg(rs),
18829 mkU64(0xffffffffffffffffULL)));
18830 putIReg(rd, IRExpr_ITE(mkexpr(t1),
18831 mkU64(0x40),
18832 unop(Iop_Clz64, unop(Iop_Not64,
18833 getIReg(rs)))));
18834 break;
18836 default:
18837 return -1;
18840 return 0;
18843 static UInt disInstr_MIPS_WRK_Special3(UInt cins, const VexArchInfo* archinfo,
18844 const VexAbiInfo* abiinfo, DisResult* dres,
18845 IRStmt** bstmt, IRExpr** lastn)
18848 IRTemp t0, t1 = 0, t2, t3, t4, t5, t6;
18849 UInt rs, rt, rd, sa, function, imm, instr_index, msb, lsb, size;
18850 /* Additional variables for instruction fields in DSP ASE insructions */
18852 imm = get_imm(cins);
18853 rs = get_rs(cins);
18854 rt = get_rt(cins);
18855 rd = get_rd(cins);
18856 sa = get_sa(cins);
18857 instr_index = get_instr_index(cins);
18858 function = get_function(cins);
18859 IRType ty = mode64 ? Ity_I64 : Ity_I32;
18861 switch (function) {
18862 case 0x01: { /* Doubleword Extract Bit Field - DEXTM; MIPS64r2 */
18863 msb = get_msb(cins);
18864 lsb = get_lsb(cins);
18865 size = msb + 1;
18866 UInt srcPos = lsb;
18867 UInt dstSz = msb + 33;
18868 t1 = newTemp(Ity_I64);
18869 DIP("dextm r%u, r%u, %u, %u", rt, rs, lsb, msb + 1);
18871 UChar lsAmt = 64 - (srcPos + dstSz); /* left shift amount; */
18872 UChar rsAmt = 64 - dstSz; /* right shift amount; */
18874 assign(t1, binop(Iop_Shl64, getIReg(rs), mkU8(lsAmt)));
18875 putIReg(rt, binop(Iop_Shr64, mkexpr(t1), mkU8(rsAmt)));
18877 break;
18880 case 0x02: { /* Doubleword Extract Bit Field Upper - DEXTU; MIPS64r2 */
18881 msb = get_msb(cins);
18882 lsb = get_lsb(cins);
18883 size = msb + 1;
18884 UInt srcPos = lsb + 32;
18885 UInt dstSz = msb + 1;
18886 DIP("dextu r%u, r%u, %u, %u", rt, rs, srcPos, dstSz);
18887 t1 = newTemp(Ity_I64);
18889 vassert(srcPos >= 32 && srcPos < 64);
18890 vassert(dstSz > 0 && dstSz <= 32);
18891 vassert((srcPos + dstSz) > 32 && (srcPos + dstSz) <= 64);
18893 UChar lsAmt = 64 - (srcPos + dstSz); /* left shift amount; */
18894 UChar rsAmt = 64 - dstSz; /* right shift amount; */
18896 assign(t1, binop(Iop_Shl64, getIReg(rs), mkU8(lsAmt)));
18897 putIReg(rt, binop(Iop_Shr64, mkexpr(t1), mkU8(rsAmt)));
18898 break;
18901 case 0x05: { /* Doubleword Insert Bit Field Middle - DINSM; MIPS64r2 */
18902 msb = get_msb(cins);
18903 lsb = get_lsb(cins);
18904 size = msb + 1;
18905 UInt dstPos = lsb;
18906 UInt srcSz = msb - lsb + 33;
18907 t1 = newTemp(ty);
18908 t2 = newTemp(ty);
18909 t3 = newTemp(ty);
18910 t4 = newTemp(ty);
18911 IRTemp tmpT1 = newTemp(ty);
18912 IRTemp tmpT2 = newTemp(ty);
18913 IRTemp tmpT3 = newTemp(ty);
18914 IRTemp tmpT4 = newTemp(ty);
18915 IRTemp tmpT5 = newTemp(ty);
18916 IRTemp tmpT6 = newTemp(ty);
18917 IRTemp tmpT7 = newTemp(ty);
18918 IRTemp tmpRs = newTemp(ty);
18919 IRTemp tmpRt = newTemp(ty);
18920 IRTemp tmpRd = newTemp(ty);
18922 assign(tmpRs, getIReg(rs));
18923 assign(tmpRt, getIReg(rt));
18924 DIP("dinsm r%u, r%u, %u, %u", rt, rs, lsb, msb);
18926 UChar lsAmt = dstPos + srcSz - 1; /* left shift amount; */
18927 UChar rsAmt = dstPos + srcSz - 1; /* right shift amount; */
18929 assign(t1, binop(Iop_Shr64, mkexpr(tmpRt), mkU8(rsAmt)));
18930 assign(tmpT1, binop(Iop_Shr64, mkexpr(t1), mkU8(1)));
18931 assign(t2, binop(Iop_Shl64, mkexpr(tmpT1), mkU8(lsAmt)));
18932 assign(tmpT2, binop(Iop_Shl64, mkexpr(t2), mkU8(1)));
18934 lsAmt = 63 - dstPos; /* left shift amount; */
18935 rsAmt = 63 - dstPos; /* right shift amount; */
18937 assign(t3, binop(Iop_Shl64, mkexpr(tmpRt), mkU8(lsAmt)));
18938 assign(tmpT3, binop(Iop_Shl64, mkexpr(t3), mkU8(1)));
18939 assign(t4, binop(Iop_Shr64, mkexpr(tmpT3), mkU8(rsAmt)));
18940 assign(tmpT4, binop(Iop_Shr64, mkexpr(t4), mkU8(1)));
18942 /* extract size from src register */
18943 lsAmt = 64 - srcSz; /* left shift amount; */
18944 rsAmt = 64 - (lsb + srcSz); /* right shift amount; */
18946 assign(tmpT5, binop(Iop_Shl64, mkexpr(tmpRs), mkU8(lsAmt)));
18947 assign(tmpT6, binop(Iop_Shr64, mkexpr(tmpT5), mkU8(rsAmt)));
18949 assign(tmpT7, binop(Iop_Or64, mkexpr(tmpT2), mkexpr(tmpT4)));
18950 assign(tmpRd, binop(Iop_Or64, mkexpr(tmpT6), mkexpr(tmpT7)));
18951 putIReg(rt, mkexpr(tmpRd));
18952 break;
18955 case 0x06: { /* Doubleword Insert Bit Field Upper - DINSU; MIPS64r2 */
18956 msb = get_msb(cins);
18957 lsb = get_lsb(cins);
18958 size = msb + 1;
18959 UInt dstPos = lsb + 32;
18960 UInt srcSz = msb - lsb + 1;
18961 IRTemp tmpT1 = newTemp(ty);
18962 IRTemp tmpT2 = newTemp(ty);
18963 IRTemp tmpT3 = newTemp(ty);
18964 IRTemp tmpT4 = newTemp(ty);
18965 IRTemp tmpT5 = newTemp(ty);
18966 IRTemp tmpT6 = newTemp(ty);
18967 IRTemp tmpT7 = newTemp(ty);
18968 IRTemp tmpT8 = newTemp(ty);
18969 IRTemp tmpT9 = newTemp(ty);
18970 IRTemp tmpRs = newTemp(ty);
18971 IRTemp tmpRt = newTemp(ty);
18972 IRTemp tmpRd = newTemp(ty);
18974 assign(tmpRs, getIReg(rs));
18975 assign(tmpRt, getIReg(rt));
18976 DIP("dinsu r%u, r%u, %u, %u", rt, rs, lsb, msb);
18978 UChar lsAmt = 64 - srcSz; /* left shift amount; */
18979 UChar rsAmt = 64 - (dstPos + srcSz); /* right shift amount; */
18980 assign(tmpT1, binop(Iop_Shl64, mkexpr(tmpRs), mkU8(lsAmt)));
18981 assign(tmpT2, binop(Iop_Shr64, mkexpr(tmpT1), mkU8(rsAmt)));
18983 lsAmt = 64 - dstPos; /* left shift amount; */
18984 rsAmt = 64 - dstPos; /* right shift amount; */
18985 assign(tmpT3, binop(Iop_Shl64, mkexpr(tmpRt), mkU8(lsAmt)));
18986 assign(tmpT4, binop(Iop_Shr64, mkexpr(tmpT3), mkU8(rsAmt)));
18988 lsAmt = dstPos; /* left shift amount; */
18989 rsAmt = srcSz; /* right shift amount; */
18990 assign(tmpT5, binop(Iop_Shr64, mkexpr(tmpRt), mkU8(rsAmt)));
18991 assign(tmpT6, binop(Iop_Shr64, mkexpr(tmpT5), mkU8(lsAmt)));
18993 assign(tmpT7, binop(Iop_Shl64, mkexpr(tmpT6), mkU8(rsAmt)));
18994 assign(tmpT8, binop(Iop_Shl64, mkexpr(tmpT7), mkU8(lsAmt)));
18996 assign(tmpT9, binop(Iop_Or64, mkexpr(tmpT8), mkexpr(tmpT4)));
18997 assign(tmpRd, binop(Iop_Or64, mkexpr(tmpT2), mkexpr(tmpT9)));
18998 putIReg(rt, mkexpr(tmpRd));
18999 break;
19002 case 0x07: { /* Doubleword Insert Bit Field - DINS; MIPS64r2 */
19003 IRTemp tmp1 = newTemp(ty);
19004 IRTemp tmpT1 = newTemp(ty);
19005 IRTemp tmpT2 = newTemp(ty);
19006 IRTemp tmpT3 = newTemp(ty);
19007 IRTemp tmpT4 = newTemp(ty);
19008 IRTemp tmpT5 = newTemp(ty);
19009 IRTemp tmpT6 = newTemp(ty);
19010 IRTemp tmpT7 = newTemp(ty);
19011 IRTemp tmpT8 = newTemp(ty);
19012 IRTemp tmpT9 = newTemp(ty);
19013 IRTemp tmp = newTemp(ty);
19014 IRTemp tmpRs = newTemp(ty);
19015 IRTemp tmpRt = newTemp(ty);
19016 IRTemp tmpRd = newTemp(ty);
19018 assign(tmpRs, getIReg(rs));
19019 assign(tmpRt, getIReg(rt));
19021 msb = get_msb(cins);
19022 lsb = get_lsb(cins);
19023 size = msb + 1;
19024 DIP("dins r%u, r%u, %u, %u", rt, rs, lsb,
19025 msb - lsb + 1);
19026 UChar lsAmt = 63 - lsb; /* left shift amount; */
19027 UChar rsAmt = 63 - lsb; /* right shift amount; */
19028 assign(tmp, binop(Iop_Shl64, mkexpr(tmpRt), mkU8(lsAmt)));
19029 assign(tmpT1, binop(Iop_Shl64, mkexpr(tmp), mkU8(1)));
19030 assign(tmp1, binop(Iop_Shr64, mkexpr(tmpT1), mkU8(rsAmt)));
19031 assign(tmpT2, binop(Iop_Shr64, mkexpr(tmp1), mkU8(1)));
19033 lsAmt = msb; /* left shift amount; */
19034 rsAmt = 1; /*right shift amount; */
19035 assign(tmpT3, binop(Iop_Shr64, mkexpr(tmpRt), mkU8(rsAmt)));
19036 assign(tmpT4, binop(Iop_Shr64, mkexpr(tmpT3), mkU8(lsAmt)));
19037 assign(tmpT5, binop(Iop_Shl64, mkexpr(tmpT4), mkU8(rsAmt)));
19038 assign(tmpT6, binop(Iop_Shl64, mkexpr(tmpT5), mkU8(lsAmt)));
19040 lsAmt = 64 - (msb - lsb + 1); /* left shift amount; */
19041 rsAmt = 64 - (msb + 1); /* right shift amount; */
19042 assign(tmpT7, binop(Iop_Shl64, mkexpr(tmpRs), mkU8(lsAmt)));
19043 assign(tmpT8, binop(Iop_Shr64, mkexpr(tmpT7), mkU8(rsAmt)));
19045 assign(tmpT9, binop(Iop_Or64, mkexpr(tmpT2), mkexpr(tmpT8)));
19046 assign(tmpRd, binop(Iop_Or64, mkexpr(tmpT6), mkexpr(tmpT9)));
19047 putIReg(rt, mkexpr(tmpRd));
19048 break;
19051 case 0x24: /* DBSHFL */
19052 lsb = get_lsb(cins);
19053 IRTemp tmpRs = newTemp(ty);
19054 IRTemp tmpRt = newTemp(ty);
19055 IRTemp tmpRd = newTemp(ty);
19056 assign(tmpRs, getIReg(rs));
19057 assign(tmpRt, getIReg(rt));
19059 switch (lsb) {
19060 case 0x02: { /* DSBH */
19061 DIP("dsbh r%u, r%u", rd, rt);
19062 IRTemp tmpT1 = newTemp(ty);
19063 IRTemp tmpT2 = newTemp(ty);
19064 IRTemp tmpT3 = newTemp(ty);
19065 IRTemp tmpT4 = newTemp(ty);
19066 IRTemp tmpT5 = newTemp(Ity_I64);
19067 IRTemp tmpT6 = newTemp(ty);
19068 assign(tmpT5, mkU64(0xFF00FF00FF00FF00ULL));
19069 assign(tmpT6, mkU64(0x00FF00FF00FF00FFULL));
19070 assign(tmpT1, binop(Iop_And64, mkexpr(tmpRt), mkexpr(tmpT5)));
19071 assign(tmpT2, binop(Iop_Shr64, mkexpr(tmpT1), mkU8(8)));
19072 assign(tmpT3, binop(Iop_And64, mkexpr(tmpRt), mkexpr(tmpT6)));
19073 assign(tmpT4, binop(Iop_Shl64, mkexpr(tmpT3), mkU8(8)));
19074 assign(tmpRd, binop(Iop_Or64, mkexpr(tmpT4), mkexpr(tmpT2)));
19075 putIReg(rd, mkexpr(tmpRd));
19076 break;
19079 case 0x05: { /* DSHD */
19080 DIP("dshd r%u, r%u\n", rd, rt);
19081 IRTemp tmpT1 = newTemp(ty);
19082 IRTemp tmpT2 = newTemp(ty);
19083 IRTemp tmpT3 = newTemp(ty);
19084 IRTemp tmpT4 = newTemp(ty);
19085 IRTemp tmpT5 = newTemp(Ity_I64);
19086 IRTemp tmpT6 = newTemp(ty);
19087 IRTemp tmpT7 = newTemp(ty);
19088 IRTemp tmpT8 = newTemp(ty);
19089 IRTemp tmpT9 = newTemp(ty);
19090 assign(tmpT5, mkU64(0xFFFF0000FFFF0000ULL));
19091 assign(tmpT6, mkU64(0x0000FFFF0000FFFFULL));
19092 assign(tmpT1, binop(Iop_And64, mkexpr(tmpRt), mkexpr(tmpT5)));
19093 assign(tmpT2, binop(Iop_Shr64, mkexpr(tmpT1), mkU8(16)));
19094 assign(tmpT3, binop(Iop_And64, mkexpr(tmpRt), mkexpr(tmpT6)));
19095 assign(tmpT4, binop(Iop_Shl64, mkexpr(tmpT3), mkU8(16)));
19096 assign(tmpT7, binop(Iop_Or64, mkexpr(tmpT4), mkexpr(tmpT2)));
19097 assign(tmpT8, binop(Iop_Shl64, mkexpr(tmpT7), mkU8(32)));
19098 assign(tmpT9, binop(Iop_Shr64, mkexpr(tmpT7), mkU8(32)));
19099 assign(tmpRd, binop(Iop_Or64, mkexpr(tmpT8), mkexpr(tmpT9)));
19100 putIReg(rd, mkexpr(tmpRd));
19101 break;
19104 case 0x08 ... 0x0f: { /* DALIGN */
19105 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
19106 DIP("dalign r%u, r%u, r%u, %u", rd, rs, rt, lsb & 0x7);
19107 UInt bp = (lsb & 0x7) << 3;
19109 if (bp) {
19110 putIReg(rd, binop(Iop_Or64,
19111 binop(Iop_Shl64, getIReg(rt), mkU8(bp)),
19112 binop(Iop_Shr64,
19113 getIReg(rs), mkU8(64 - bp))));
19114 } else
19115 putIReg(rd, getIReg(rt));
19116 } else {
19117 ILLEGAL_INSTRUCTON
19120 break;
19123 case 0: /* DBITSWAP */
19124 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
19125 DIP("dbitswap r%u, r%u", rd, rt);
19126 putIReg(rd, qop(Iop_Rotx64, getIReg(rt), mkU8(7), mkU8(8), mkU8(1)));
19127 } else {
19128 ILLEGAL_INSTRUCTON
19131 break;
19133 default:
19134 return -1;;
19137 break;
19139 case 0x3B: /* RDHWR */
19140 DIP("rdhwr r%u, r%u", rt, rd);
19142 if (VEX_MIPS_CPU_HAS_MIPS32R2(archinfo->hwcaps) ||
19143 VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps) ||
19144 (VEX_MIPS_COMP_ID(archinfo->hwcaps) == VEX_PRID_COMP_BROADCOM)) {
19145 if (rd == 29) {
19146 putIReg(rt, getULR());
19147 } else if (rd <= 3
19148 || (rd == 31
19149 && VEX_MIPS_COMP_ID(archinfo->hwcaps)
19150 == VEX_PRID_COMP_CAVIUM)) {
19151 IRExpr** arg = mkIRExprVec_1(mkU32(rd));
19152 IRTemp val = newTemp(ty);
19153 IRDirty *d = unsafeIRDirty_1_N(val,
19155 "mips_dirtyhelper_rdhwr",
19156 &mips_dirtyhelper_rdhwr,
19157 arg);
19158 stmt(IRStmt_Dirty(d));
19159 putIReg(rt, mkexpr(val));
19160 } else
19161 return -1;
19162 } else {
19163 ILLEGAL_INSTRUCTON
19166 break;
19168 case 0x04: /* INS */
19169 msb = get_msb(cins);
19170 lsb = get_lsb(cins);
19171 size = msb - lsb + 1;
19172 DIP("ins size:%u msb:%u lsb:%u", size, msb, lsb);
19174 vassert(lsb + size <= 32);
19175 vassert(lsb + size > 0);
19177 /* put size bits from rs at the pos in temporary */
19178 t0 = newTemp(Ity_I32);
19179 t3 = newTemp(Ity_I32);
19180 /* shift left for 32 - size to clear leading bits and get zeros
19181 at the end */
19182 assign(t0, binop(Iop_Shl32, mkNarrowTo32(ty, getIReg(rs)),
19183 mkU8(32 - size)));
19184 /* now set it at pos */
19185 t1 = newTemp(Ity_I32);
19186 assign(t1, binop(Iop_Shr32, mkexpr(t0), mkU8(32 - size - lsb)));
19188 if (lsb > 0) {
19189 t2 = newTemp(Ity_I32);
19190 /* clear everything but lower pos bits from rt */
19191 assign(t2, binop(Iop_Shl32, mkNarrowTo32(ty, getIReg(rt)),
19192 mkU8(32 - lsb)));
19193 assign(t3, binop(Iop_Shr32, mkexpr(t2), mkU8(32 - lsb)));
19194 } else
19195 assign(t3, mkU32(0));
19197 if (msb < 31) {
19198 t4 = newTemp(Ity_I32);
19199 /* clear everything but upper msb + 1 bits from rt */
19200 assign(t4, binop(Iop_Shr32, mkNarrowTo32(ty, getIReg(rt)),
19201 mkU8(msb + 1)));
19202 t5 = newTemp(Ity_I32);
19203 assign(t5, binop(Iop_Shl32, mkexpr(t4), mkU8(msb + 1)));
19205 /* now combine these registers */
19206 if (lsb > 0) {
19207 t6 = newTemp(Ity_I32);
19208 assign(t6, binop(Iop_Or32, mkexpr(t5), mkexpr(t1)));
19209 putIReg(rt, mkWidenFrom32(ty, binop(Iop_Or32, mkexpr(t6),
19210 mkexpr(t3)), True));
19211 } else {
19212 putIReg(rt, mkWidenFrom32(ty, binop(Iop_Or32, mkexpr(t1),
19213 mkexpr(t5)), True));
19215 } else {
19216 putIReg(rt, mkWidenFrom32(ty, binop(Iop_Or32, mkexpr(t1),
19217 mkexpr(t3)), True));
19220 break;
19222 case 0x00: /* EXT */
19223 msb = get_msb(cins);
19224 lsb = get_lsb(cins);
19225 size = msb + 1;
19226 DIP("ext size:%u msb:%u lsb:%u", size, msb, lsb);
19227 vassert(lsb + size <= 32);
19228 vassert(lsb + size > 0);
19230 /* put size bits from rs at the top of in temporary */
19231 if (lsb + size < 32) {
19232 t0 = newTemp(Ity_I32);
19233 assign(t0, binop(Iop_Shl32, mkNarrowTo32(ty, getIReg(rs)),
19234 mkU8(32 - lsb - size)));
19236 putIReg(rt, mkWidenFrom32(ty, binop(Iop_Shr32, mkexpr(t0),
19237 mkU8(32 - size)), True));
19238 } else {
19239 putIReg(rt, mkWidenFrom32(ty, binop(Iop_Shr32,
19240 mkNarrowTo32(ty, getIReg(rs)),
19241 mkU8(32 - size)), True));
19244 break;
19246 case 0x03: /* Doubleword Extract Bit Field - DEXT; MIPS64r2 */
19247 msb = get_msb(cins);
19248 lsb = get_lsb(cins);
19249 size = msb + 1;
19250 DIP("dext r%u, r%u, %u, %u", rt, rs, lsb, msb + 1);
19251 t1 = newTemp(Ity_I64);
19252 vassert(lsb >= 0 && lsb < 32);
19253 vassert(size > 0 && size <= 32);
19254 vassert((lsb + size) > 0 && (lsb + size) <= 63);
19256 UChar lsAmt = 63 - (lsb + msb); /* left shift amount; */
19257 UChar rsAmt = 63 - msb; /* right shift amount; */
19259 assign(t1, binop(Iop_Shl64, getIReg(rs), mkU8(lsAmt)));
19260 putIReg(rt, binop(Iop_Shr64, mkexpr(t1), mkU8(rsAmt)));
19262 break;
19264 case 0x20: /* BSHFL */
19265 switch (sa) {
19266 case 0x0: /* BITSWAP */
19267 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
19268 DIP("bitswap r%u, r%u", rd, rt);
19270 if (mode64) {
19271 putIReg(rd, unop(Iop_32Uto64, qop(Iop_Rotx32, unop(Iop_64to32, getIReg(rt)),
19272 mkU8(7), mkU8(8), mkU8(1))));
19273 } else {
19274 putIReg(rd, qop(Iop_Rotx32, getIReg(rt), mkU8(7),
19275 mkU8(8), mkU8(1)));
19277 } else {
19278 ILLEGAL_INSTRUCTON;
19281 break;
19283 case 0x02: /* WSBH */
19284 DIP("wsbh r%u, r%u", rd, rt);
19285 t0 = newTemp(Ity_I32);
19286 t1 = newTemp(Ity_I32);
19287 t2 = newTemp(Ity_I32);
19288 t3 = newTemp(Ity_I32);
19289 assign(t0, binop(Iop_Shl32, binop(Iop_And32, mkNarrowTo32(ty,
19290 getIReg(rt)), mkU32(0x00FF0000)),
19291 mkU8(0x8)));
19292 assign(t1, binop(Iop_Shr32, binop(Iop_And32, mkNarrowTo32(ty,
19293 getIReg(rt)), mkU32(0xFF000000)), mkU8(0x8)));
19294 assign(t2, binop(Iop_Shl32, binop(Iop_And32, mkNarrowTo32(ty,
19295 getIReg(rt)), mkU32(0x000000FF)), mkU8(0x8)));
19296 assign(t3, binop(Iop_Shr32, binop(Iop_And32, mkNarrowTo32(ty,
19297 getIReg(rt)), mkU32(0x0000FF00)), mkU8(0x8)));
19298 putIReg(rd, mkWidenFrom32(ty, binop(Iop_Or32, binop(Iop_Or32,
19299 mkexpr(t0), mkexpr(t1)),
19300 binop(Iop_Or32, mkexpr(t2),
19301 mkexpr(t3))), True));
19302 break;
19304 case 0x10: /* SEB */
19305 DIP("seb r%u, r%u", rd, rt);
19307 if (mode64)
19308 putIReg(rd, unop(Iop_8Sto64, unop(Iop_64to8, getIReg(rt))));
19309 else
19310 putIReg(rd, unop(Iop_8Sto32, unop(Iop_32to8, getIReg(rt))));
19312 break;
19314 case 0x18: /* SEH */
19315 DIP("seh r%u, r%u", rd, rt);
19317 if (mode64)
19318 putIReg(rd, unop(Iop_16Sto64, unop(Iop_64to16, getIReg(rt))));
19319 else
19320 putIReg(rd, unop(Iop_16Sto32, unop(Iop_32to16, getIReg(rt))));
19322 break;
19324 case 0x08 ... 0x0b: /* ALIGN */
19325 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
19326 if (mode64) {
19327 UInt bp = (sa & 0x3) << 3;
19329 if (bp) {
19330 putIReg(rd, unop(Iop_32Sto64,
19331 binop(Iop_Or32,
19332 binop(Iop_Shl32,
19333 unop(Iop_64to32,
19334 getIReg(rt)),
19335 mkU8(bp)),
19336 binop(Iop_Shr32,
19337 unop(Iop_64to32,
19338 getIReg(rs)),
19339 mkU8(32 - bp)))));
19340 } else
19341 putIReg(rd, getIReg(rt));
19342 } else {
19343 UInt bp = (sa & 0x3) << 3;
19345 if (bp) {
19346 putIReg(rd, binop(Iop_Or32,
19347 binop(Iop_Shl32,
19348 getIReg(rt), mkU8(bp)),
19349 binop(Iop_Shr32,
19350 getIReg(rs), mkU8(32 - bp))));
19351 } else
19352 putIReg(rd, getIReg(rt));
19354 } else {
19355 ILLEGAL_INSTRUCTON;
19358 break;
19360 default:
19361 return -1;
19365 break; /* BSHFL */
19367 /* --- MIPS32(r2) DSP ASE(r2) / Cavium Specfic (LX) instructions --- */
19368 case 0xA: /* LX */
19369 if (VEX_MIPS_COMP_ID(archinfo->hwcaps) == VEX_PRID_COMP_CAVIUM) {
19370 if (dis_instr_CVM(cins))
19371 break;
19373 return -1;
19375 /* fallthrough */
19376 case 0xC: /* INSV */
19377 case 0x38: { /* EXTR.W */
19378 if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
19379 UInt retVal = disDSPInstr_MIPS_WRK ( cins );
19381 if (0 != retVal ) {
19382 return -2;
19385 break;
19386 } else {
19387 return -2;
19390 break;
19393 case 0x10: { /* ADDU.QB */
19394 switch (sa) {
19395 case 0xC: /* SUBU_S.PH */
19396 case 0xD: /* ADDU_S.PH */
19397 case 0x1E: { /* MULQ_S.PH */
19398 if (VEX_MIPS_PROC_DSP2(archinfo->hwcaps)) {
19399 UInt retVal = disDSPInstr_MIPS_WRK ( cins );
19401 if (0 != retVal ) {
19402 return -2;
19405 break;
19406 } else {
19407 return -2;
19410 break;
19413 default: {
19414 if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
19415 UInt retVal = disDSPInstr_MIPS_WRK ( cins );
19417 if (0 != retVal ) {
19418 return -2;
19421 break;
19422 } else {
19423 return -2;
19426 break;
19430 break;
19433 case 0x11: { /* CMPU.EQ.QB */
19434 switch (sa) {
19435 case 0x18: /* CMPGDU.EQ.QB */
19436 case 0x19: /* CMPGDU.LT.QB */
19437 case 0x1A: /* CMPGDU.LE.QB */
19438 case 0x0D: /* PRECR.QB.PH */
19439 case 0x1E: /* PRECR_SRA.PH.W */
19440 case 0x1F: { /* PRECR_SRA_R.PH.W */
19441 if (VEX_MIPS_PROC_DSP2(archinfo->hwcaps)) {
19442 UInt retVal = disDSPInstr_MIPS_WRK ( cins );
19444 if (0 != retVal ) {
19445 return -2;
19448 break;
19449 } else {
19450 return -2;
19453 break;
19456 default: {
19457 if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
19458 UInt retVal = disDSPInstr_MIPS_WRK ( cins );
19460 if (0 != retVal ) {
19461 return -2;
19464 break;
19465 } else {
19466 return -2;
19469 break;
19473 break;
19476 case 0x12: { /* ABSQ_S.PH */
19477 switch (sa) {
19478 case 0x1: { /* ABSQ_S.QB */
19479 if (VEX_MIPS_PROC_DSP2(archinfo->hwcaps)) {
19480 UInt retVal = disDSPInstr_MIPS_WRK ( cins );
19482 if (0 != retVal ) {
19483 return -2;
19486 break;
19487 } else {
19488 return -2;
19491 break;
19494 default: {
19495 if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
19496 UInt retVal = disDSPInstr_MIPS_WRK ( cins );
19498 if (0 != retVal ) {
19499 return -2;
19502 break;
19503 } else {
19504 return -2;
19507 break;
19511 break;
19514 case 0x13: { /* SHLL.QB */
19515 switch (sa) {
19516 case 0x04: /* SHRA.QB */
19517 case 0x05: /* SHRA_R.QB */
19518 case 0x06: /* SHRAV.QB */
19519 case 0x07: /* SHRAV_R.QB */
19520 case 0x19: /* SHLR.PH */
19521 case 0x1B: { /* SHLRV.PH */
19522 if (VEX_MIPS_PROC_DSP2(archinfo->hwcaps)) {
19523 UInt retVal = disDSPInstr_MIPS_WRK ( cins );
19525 if (0 != retVal ) {
19526 return -2;
19529 break;
19530 } else {
19531 return -2;
19534 break;
19537 default: {
19538 if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
19539 UInt retVal = disDSPInstr_MIPS_WRK ( cins );
19541 if (0 != retVal ) {
19542 return -2;
19545 break;
19546 } else {
19547 return -2;
19550 break;
19554 break;
19557 case 0x30: { /* DPAQ.W.PH */
19558 switch (sa) {
19559 case 0x0: /* DPA.W.PH */
19560 case 0x18: /* DPAQX_S.W.PH */
19561 case 0x1A: /* DPAQX_SA.W.PH */
19562 case 0x8: /* DPAX.W.PH */
19563 case 0x1: /* DPS.W.PH */
19564 case 0x19: /* DPSQX_S.W.PH */
19565 case 0x1B: /* DPSQX_SA.W.PH */
19566 case 0x9: /* DPSX.W.PH */
19567 case 0x2: { /* MULSA.W.PH */
19568 if (VEX_MIPS_PROC_DSP2(archinfo->hwcaps)) {
19569 UInt retVal = disDSPInstr_MIPS_WRK ( cins );
19571 if (0 != retVal ) {
19572 return -2;
19575 break;
19576 } else {
19577 return -2;
19580 break;
19583 default: {
19584 if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
19585 UInt retVal = disDSPInstr_MIPS_WRK ( cins );
19587 if (0 != retVal ) {
19588 return -2;
19591 break;
19592 } else {
19593 return -2;
19596 break;
19600 break;
19603 case 0x18: /* ADDUH.QB/MUL.PH */
19604 case 0x31: { /* APPEND */
19605 if (VEX_MIPS_PROC_DSP2(archinfo->hwcaps)) {
19606 UInt retVal = disDSPInstr_MIPS_WRK ( cins );
19608 if (0 != retVal ) {
19609 return -2;
19612 break;
19613 } else {
19614 return -2;
19618 case 0x35: { /* PREF r6*/
19619 DIP("pref");
19620 break;
19623 case 0x36: { /* LL */
19624 imm = extend_s_9to16((instr_index >> 7) & 0x1ff);
19625 DIP("ll r%u, %u(r%u)", rt, imm, rs);
19626 LOAD_STORE_PATTERN;
19627 t2 = newTemp(ty);
19628 assign(t2, mkWidenFrom32(ty, load(Ity_I32, mkexpr(t1)), True));
19629 putLLaddr(mkexpr(t1));
19630 putLLdata(mkexpr(t2));
19631 putIReg(rt, mkexpr(t2));
19632 break;
19635 case 0x26: { /* SC */
19636 imm = extend_s_9to16((instr_index >> 7) & 0x1ff);
19637 DIP("sc r%u, %u(r%u)", rt, imm, rs);
19638 LOAD_STORE_PATTERN;
19640 t2 = newTemp(Ity_I1);
19641 t3 = newTemp(Ity_I32);
19642 assign(t2, binop(mode64 ? Iop_CmpNE64 : Iop_CmpNE32,
19643 mkexpr(t1), getLLaddr()));
19644 assign(t3, mkNarrowTo32(ty, getIReg(rt)));
19645 putLLaddr(LLADDR_INVALID);
19646 putIReg(rt, getIReg(0));
19648 mips_next_insn_if(mkexpr(t2));
19650 t4 = newTemp(Ity_I32);
19651 t5 = newTemp(Ity_I32);
19653 assign(t5, mkNarrowTo32(ty, getLLdata()));
19655 stmt(IRStmt_CAS(mkIRCAS(IRTemp_INVALID, t4, /* old_mem */
19656 MIPS_IEND, mkexpr(t1), /* addr */
19657 NULL, mkexpr(t5), /* expected value */
19658 NULL, mkexpr(t3) /* new value */)));
19660 putIReg(rt, unop(mode64 ? Iop_1Uto64 : Iop_1Uto32,
19661 binop(Iop_CmpEQ32, mkexpr(t4), mkexpr(t5))));
19662 break;
19665 case 0x37: { /* LLD */
19666 imm = extend_s_9to16((instr_index >> 7) & 0x1ff);
19667 DIP("lld r%u, %u(r%u)", rt, imm, rs);
19668 LOAD_STORE_PATTERN;
19670 t2 = newTemp(Ity_I64);
19671 assign(t2, load(Ity_I64, mkexpr(t1)));
19672 putLLaddr(mkexpr(t1));
19673 putLLdata(mkexpr(t2));
19674 putIReg(rt, mkexpr(t2));
19675 break;
19678 case 0x27: { /* SCD */
19679 imm = extend_s_9to16((instr_index >> 7) & 0x1ff);
19680 DIP("sdc r%u, %u(r%u)", rt, imm, rs);
19681 LOAD_STORE_PATTERN;
19683 t2 = newTemp(Ity_I1);
19684 t3 = newTemp(Ity_I64);
19685 assign(t2, binop(Iop_CmpNE64, mkexpr(t1), getLLaddr()));
19686 assign(t3, getIReg(rt));
19687 putLLaddr(LLADDR_INVALID);
19688 putIReg(rt, getIReg(0));
19690 mips_next_insn_if(mkexpr(t2));
19692 t4 = newTemp(Ity_I64);
19693 t5 = newTemp(Ity_I64);
19695 assign(t5, getLLdata());
19697 stmt(IRStmt_CAS(mkIRCAS(IRTemp_INVALID, t4, /* old_mem */
19698 MIPS_IEND, mkexpr(t1), /* addr */
19699 NULL, mkexpr(t5), /* expected value */
19700 NULL, mkexpr(t3) /* new value */)));
19702 putIReg(rt, unop(Iop_1Uto64,
19703 binop(Iop_CmpEQ64, mkexpr(t4), mkexpr(t5))));
19704 break;
19707 default:
19708 return -1;
19711 return 0;
19714 static UInt disInstr_MIPS_WRK_00(UInt cins, const VexArchInfo* archinfo,
19715 const VexAbiInfo* abiinfo, DisResult* dres,
19716 IRStmt** bstmt, IRExpr** lastn)
19718 IRTemp t0;
19719 UInt opcode, rs, rt, trap_code, imm, instr_index, p;
19720 /* Additional variables for instruction fields in DSP ASE insructions */
19722 opcode = get_opcode(cins);
19723 imm = get_imm(cins);
19724 rs = get_rs(cins);
19725 rt = get_rt(cins);
19726 instr_index = get_instr_index(cins);
19727 trap_code = get_code(cins);
19728 IRType ty = mode64 ? Ity_I64 : Ity_I32;
19730 switch (opcode & 0x0F) {
19731 case 0x00: /* Special */
19732 return disInstr_MIPS_WRK_Special(cins, archinfo, abiinfo,
19733 dres, bstmt, lastn);
19735 case 0x01: /* Regimm */
19736 switch (rt) {
19737 case 0x00: /* BLTZ */
19738 DIP("bltz r%u, %u", rs, imm);
19740 if (mode64) {
19741 if (!dis_instr_branch(cins, dres, bstmt))
19742 return -1;
19743 } else
19744 dis_branch(False, binop(Iop_CmpEQ32, binop(Iop_And32, getIReg(rs),
19745 mkU32(0x80000000)), mkU32(0x80000000)), imm, bstmt);
19747 break;
19749 case 0x01: /* BGEZ */
19750 DIP("bgez r%u, %u", rs, imm);
19752 if (mode64) {
19753 if (!dis_instr_branch(cins, dres, bstmt))
19754 return -1;
19755 } else
19756 dis_branch(False, binop(Iop_CmpEQ32, binop(Iop_And32, getIReg(rs),
19757 mkU32(0x80000000)), mkU32(0x0)), imm, bstmt);
19759 break;
19761 case 0x02: /* BLTZL */
19762 DIP("bltzl r%u, %u", rs, imm);
19763 *lastn = dis_branch_likely(binop(mode64 ? Iop_CmpNE64 : Iop_CmpNE32,
19764 binop(mode64 ? Iop_And64 : Iop_And32, getIReg(rs),
19765 mode64 ? mkU64(0x8000000000000000ULL) : mkU32(0x80000000)),
19766 mode64 ? mkU64(0x8000000000000000ULL) : mkU32(0x80000000)),
19767 imm);
19768 break;
19770 case 0x03: /* BGEZL */
19771 DIP("bgezl r%u, %u", rs, imm);
19772 *lastn = dis_branch_likely(binop(mode64 ? Iop_CmpNE64 : Iop_CmpNE32,
19773 binop(mode64 ? Iop_And64 : Iop_And32, getIReg(rs),
19774 mode64 ? mkU64(0x8000000000000000ULL) : mkU32(0x80000000)),
19775 mode64 ? mkU64(0x0) : mkU32(0x0)), imm);
19776 break;
19778 case 0x06: { /* DAHI */
19779 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
19780 DIP("dahi r%u, %x", rs, imm);
19781 putIReg(rs, binop(Iop_Add64,
19782 getIReg(rs), mkU64(extend_s_16to64 (imm) << 32)));
19783 } else {
19784 ILLEGAL_INSTRUCTON
19787 break;
19790 case 0x08: /* TGEI */
19791 DIP("tgei r%u, %u %u", rs, imm, trap_code);
19793 if (mode64) {
19794 stmt (IRStmt_Exit (unop (Iop_Not1,
19795 binop (Iop_CmpLT64S,
19796 getIReg (rs),
19797 mkU64 (extend_s_16to64 (imm)))),
19798 Ijk_SigTRAP,
19799 IRConst_U64(guest_PC_curr_instr + 4),
19800 OFFB_PC));
19801 } else {
19802 stmt (IRStmt_Exit (unop (Iop_Not1,
19803 binop (Iop_CmpLT32S,
19804 getIReg (rs),
19805 mkU32 (extend_s_16to32 (imm)))),
19806 Ijk_SigTRAP,
19807 IRConst_U32(guest_PC_curr_instr + 4),
19808 OFFB_PC));
19811 break;
19813 case 0x09: { /* TGEIU */
19814 DIP("tgeiu r%u, %u %u", rs, imm, trap_code);
19816 if (mode64) {
19817 stmt (IRStmt_Exit (unop (Iop_Not1,
19818 binop (Iop_CmpLT64U,
19819 getIReg (rs),
19820 mkU64 (extend_s_16to64 (imm)))),
19821 Ijk_SigTRAP,
19822 IRConst_U64(guest_PC_curr_instr + 4),
19823 OFFB_PC));
19824 } else {
19825 stmt (IRStmt_Exit (unop (Iop_Not1,
19826 binop (Iop_CmpLT32U,
19827 getIReg (rs),
19828 mkU32 (extend_s_16to32 (imm)))),
19829 Ijk_SigTRAP,
19830 IRConst_U32(guest_PC_curr_instr + 4),
19831 OFFB_PC));
19834 break;
19837 case 0x0A: { /* TLTI */
19838 DIP("tlti r%u, %u %u", rs, imm, trap_code);
19840 if (mode64) {
19841 stmt (IRStmt_Exit (binop (Iop_CmpLT64S, getIReg (rs),
19842 mkU64 (extend_s_16to64 (imm))),
19843 Ijk_SigTRAP,
19844 IRConst_U64(guest_PC_curr_instr + 4),
19845 OFFB_PC));
19846 } else {
19847 stmt (IRStmt_Exit (binop (Iop_CmpLT32S, getIReg (rs),
19848 mkU32 (extend_s_16to32 (imm))),
19849 Ijk_SigTRAP,
19850 IRConst_U32(guest_PC_curr_instr + 4),
19851 OFFB_PC));
19854 break;
19857 case 0x0B: { /* TLTIU */
19858 DIP("tltiu r%u, %u %u", rs, imm, trap_code);
19860 if (mode64) {
19861 stmt (IRStmt_Exit (binop (Iop_CmpLT64U, getIReg (rs),
19862 mkU64 (extend_s_16to64 (imm))),
19863 Ijk_SigTRAP,
19864 IRConst_U64(guest_PC_curr_instr + 4),
19865 OFFB_PC));
19866 } else {
19867 stmt (IRStmt_Exit (binop (Iop_CmpLT32U, getIReg (rs),
19868 mkU32 (extend_s_16to32 (imm))),
19869 Ijk_SigTRAP,
19870 IRConst_U32(guest_PC_curr_instr + 4),
19871 OFFB_PC));
19874 break;
19877 case 0x0C: { /* TEQI */
19878 DIP("teqi r%u, %u %u", rs, imm, trap_code);
19880 if (mode64) {
19881 stmt (IRStmt_Exit (binop (Iop_CmpEQ64, getIReg (rs),
19882 mkU64 (extend_s_16to64 (imm))),
19883 Ijk_SigTRAP,
19884 IRConst_U64(guest_PC_curr_instr + 4),
19885 OFFB_PC));
19886 } else {
19887 stmt (IRStmt_Exit (binop (Iop_CmpEQ32, getIReg (rs),
19888 mkU32 (extend_s_16to32 (imm))),
19889 Ijk_SigTRAP,
19890 IRConst_U32(guest_PC_curr_instr + 4),
19891 OFFB_PC));
19894 break;
19897 case 0x0E: { /* TNEI */
19898 DIP("tnei r%u, %u %u", rs, imm, trap_code);
19900 if (mode64) {
19901 stmt (IRStmt_Exit (binop (Iop_CmpNE64, getIReg (rs),
19902 mkU64 (extend_s_16to64 (imm))),
19903 Ijk_SigTRAP,
19904 IRConst_U64(guest_PC_curr_instr + 4),
19905 OFFB_PC));
19906 } else {
19907 stmt (IRStmt_Exit (binop (Iop_CmpNE32, getIReg (rs),
19908 mkU32 (extend_s_16to32 (imm))),
19909 Ijk_SigTRAP,
19910 IRConst_U32(guest_PC_curr_instr + 4),
19911 OFFB_PC));
19914 break;
19917 case 0x10: /* BLTZAL */
19918 DIP("bltzal r%u, %u", rs, imm);
19920 if (mode64) {
19921 if (!dis_instr_branch(cins, dres, bstmt))
19922 return -1;
19923 } else
19924 dis_branch(True, binop(Iop_CmpEQ32, binop(Iop_And32, getIReg(rs),
19925 mkU32(0x80000000)), mkU32(0x80000000)), imm, bstmt);
19927 break;
19929 case 0x11: /* BGEZAL */
19930 DIP("bgezal r%u, %u", rs, imm);
19932 if (mode64) {
19933 if (!dis_instr_branch(cins, dres, bstmt))
19934 return -1;
19935 } else
19936 dis_branch(True, binop(Iop_CmpEQ32, binop(Iop_And32, getIReg(rs),
19937 mkU32(0x80000000)), mkU32(0x0)), imm, bstmt);
19939 break;
19941 case 0x12: /* BLTZALL */
19942 DIP("bltzall r%u, %u", rs, imm);
19943 putIReg(31, mode64 ? mkU64(guest_PC_curr_instr + 8) :
19944 mkU32(guest_PC_curr_instr + 8));
19945 *lastn = dis_branch_likely(binop(mode64 ? Iop_CmpNE64 : Iop_CmpNE32,
19946 binop(mode64 ? Iop_And64 : Iop_And32, getIReg(rs),
19947 mode64 ? mkU64(0x8000000000000000ULL) : mkU32(0x80000000)),
19948 mode64 ? mkU64(0x8000000000000000ULL) : mkU32(0x80000000)),
19949 imm);
19950 break;
19952 case 0x13: /* BGEZALL */
19953 DIP("bgezall r%u, %u", rs, imm);
19955 if (mode64) {
19956 putIReg(31, mkU64(guest_PC_curr_instr + 8));
19957 *lastn = dis_branch_likely(binop(Iop_CmpNE64,
19958 binop(Iop_And64,
19959 getIReg(rs),
19960 mkU64(0x8000000000000000ULL)),
19961 mkU64(0x0)),
19962 imm);
19963 } else {
19964 putIReg(31, mkU32(guest_PC_curr_instr + 8));
19965 *lastn = dis_branch_likely(binop(Iop_CmpNE32, binop(Iop_And32,
19966 getIReg(rs), mkU32(0x80000000)),
19967 mkU32(0x0)), imm);
19970 break;
19972 case 0x1C: { /* BPOSGE32 */
19973 DIP("bposge32 %u", imm);
19974 vassert(!mode64);
19975 t0 = newTemp(Ity_I32);
19976 /* Get pos field from DSPControl register. */
19977 assign(t0, binop(Iop_And32, getDSPControl(), mkU32(0x3f)));
19978 dis_branch(False, unop(Iop_Not1, binop(Iop_CmpLT32U, mkexpr(t0),
19979 mkU32(32))), imm, bstmt);
19980 break;
19983 case 0x1E: { /* DATI */
19984 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
19985 DIP("dati r%u, %x", rs, imm);
19986 putIReg(rs, binop(Iop_Add64,
19987 getIReg(rs), mkU64((long long)imm << 48)));
19988 } else {
19989 ILLEGAL_INSTRUCTON
19992 break;
19995 case 0x1F: /* SYNCI */
19996 /* Just ignore it */
19997 break;
19999 default:
20000 return -1;
20003 break;
20005 case 0x02: /* J */
20006 DIP("j 0x%x", instr_index);
20007 t0 = newTemp(ty);
20009 if (mode64)
20010 assign(t0, mkU64((guest_PC_curr_instr & 0xFFFFFFFFF0000000ULL) |
20011 (instr_index << 2)));
20012 else
20013 assign(t0, mkU32((guest_PC_curr_instr & 0xF0000000) |
20014 (instr_index << 2)));
20016 *lastn = mkexpr(t0);
20017 break;
20019 case 0x03: /* JAL */
20020 DIP("jal 0x%x", instr_index);
20022 if (mode64) {
20023 putIReg(31, mkU64(guest_PC_curr_instr + 8));
20024 t0 = newTemp(ty);
20025 assign(t0, mkU64((guest_PC_curr_instr & 0xFFFFFFFFF0000000ULL) |
20026 (instr_index << 2)));
20027 } else {
20028 putIReg(31, mkU32(guest_PC_curr_instr + 8));
20029 t0 = newTemp(ty);
20030 assign(t0, mkU32((guest_PC_curr_instr & 0xF0000000) |
20031 (instr_index << 2)));
20034 *lastn = mkexpr(t0);
20035 break;
20037 case 0x04: /* BEQ */
20038 DIP("beq r%u, r%u, %u", rs, rt, imm);
20040 if (mode64)
20041 dis_branch(False, binop(Iop_CmpEQ64, getIReg(rs), getIReg(rt)),
20042 imm, bstmt);
20043 else
20044 dis_branch(False, binop(Iop_CmpEQ32, getIReg(rs), getIReg(rt)),
20045 imm, bstmt);
20047 break;
20049 case 0x05: /* BNE */
20050 DIP("bne r%u, r%u, %u", rs, rt, imm);
20052 if (mode64)
20053 dis_branch(False, binop(Iop_CmpNE64, getIReg(rs), getIReg(rt)),
20054 imm, bstmt);
20055 else
20056 dis_branch(False, binop(Iop_CmpNE32, getIReg(rs), getIReg(rt)),
20057 imm, bstmt);
20059 break;
20061 case 0x06: /* BLEZ, BLEZALC, BGEZALC, BGEUC */
20062 if (rt == 0) { /* BLEZ */
20063 DIP("blez r%u, %u", rs, imm);
20065 if (mode64)
20066 dis_branch(False, binop(Iop_CmpLE64S, getIReg(rs), mkU64(0x0)),
20067 imm, bstmt);
20068 else
20069 dis_branch(False, binop(Iop_CmpLE32S, getIReg(rs), mkU32(0x0)), imm,
20070 bstmt);
20071 } else if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
20072 if (rs == 0) { /* BLEZALC */
20073 DIP("blezalc r%u, %u", rt, imm);
20075 if (mode64)
20076 dis_branch_compact(True,
20077 binop(Iop_CmpLE64S, getIReg(rt), mkU64(0x0)),
20078 imm, dres);
20079 else
20080 dis_branch_compact(True,
20081 binop(Iop_CmpLE32S, getIReg(rt), mkU32(0x0)),
20082 imm, dres);
20083 } else if (rt == rs) { /* BGEZALC */
20084 DIP("bgezalc r%u, %u", rt, imm);
20086 if (mode64)
20087 dis_branch_compact(True,
20088 binop(Iop_CmpLE64S, mkU64(0x0), getIReg(rt)),
20089 imm, dres);
20090 else
20091 dis_branch_compact(True,
20092 binop(Iop_CmpLE32S, mkU32(0x0), getIReg(rt)),
20093 imm, dres);
20094 } else { /* BGEUC */
20095 DIP("bgeuc r%u, r%u, %u", rt, rs, imm);
20097 if (mode64)
20098 dis_branch_compact(False,
20099 unop(Iop_Not1,
20100 binop(Iop_CmpLT64U,
20101 getIReg(rs), getIReg(rt))),
20102 imm, dres);
20103 else
20104 dis_branch_compact(False,
20105 unop(Iop_Not1,
20106 binop(Iop_CmpLT32U,
20107 getIReg(rs), getIReg(rt))),
20108 imm, dres);
20110 } else {
20111 ILLEGAL_INSTRUCTON
20114 break;
20116 case 0x07: /* BGTZ, BGTZALC, BLTZALC, BLTUC */
20117 if (rt == 0) { /* BGTZ */
20118 DIP("bgtz r%u, %u", rs, imm);
20120 if (mode64)
20121 dis_branch(False, unop(Iop_Not1, binop(Iop_CmpLE64S, getIReg(rs),
20122 mkU64(0x00))), imm, bstmt);
20123 else
20124 dis_branch(False, unop(Iop_Not1, binop(Iop_CmpLE32S, getIReg(rs),
20125 mkU32(0x00))), imm, bstmt);
20126 } else if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
20127 if (rs == 0) { /* BGTZALC */
20128 DIP("bgtzalc r%u, %u", rt, imm);
20130 if (mode64) {
20131 dis_branch_compact(True,
20132 unop(Iop_Not1,
20133 binop(Iop_CmpLE64S,
20134 getIReg(rt), mkU64(0x0))),
20135 imm, dres);
20136 } else {
20137 dis_branch_compact(True,
20138 unop(Iop_Not1,
20139 binop(Iop_CmpLE32S,
20140 getIReg(rt), mkU32(0x0))),
20141 imm, dres);
20143 } else if (rs == rt) { /* BLTZALC */
20144 DIP("bltzalc r%u, %u", rt, imm);
20146 if (mode64) {
20147 dis_branch_compact(True,
20148 unop(Iop_Not1,
20149 binop(Iop_CmpLE64S,
20150 mkU64(0x0), getIReg(rt))),
20151 imm, dres);
20152 } else {
20153 dis_branch_compact(True,
20154 unop(Iop_Not1,
20155 binop(Iop_CmpLE32S,
20156 mkU32(0x0), getIReg(rt))),
20157 imm, dres);
20159 } else { /* BLTUC */
20160 DIP("bltuc r%u, r%u, %u", rt, rs, imm);
20162 if (mode64) {
20163 dis_branch_compact(False,
20164 binop(Iop_CmpLT64U, getIReg(rs), getIReg(rt)),
20165 imm, dres);
20166 } else {
20167 dis_branch_compact(False,
20168 binop(Iop_CmpLT32U, getIReg(rs), getIReg(rt)),
20169 imm, dres);
20172 } else {
20173 ILLEGAL_INSTRUCTON
20176 break;
20178 #if defined(__mips__) && ((defined(__mips_isa_rev) && __mips_isa_rev < 6))
20180 case 0x08: { /* ADDI */
20181 DIP("addi r%u, r%u, %u", rt, rs, imm);
20182 IRTemp tmpRs32, t1, t2, t3, t4;
20183 tmpRs32 = newTemp(Ity_I32);
20184 assign(tmpRs32, mkNarrowTo32(ty, getIReg(rs)));
20186 t0 = newTemp(Ity_I32);
20187 t1 = newTemp(Ity_I32);
20188 t2 = newTemp(Ity_I32);
20189 t3 = newTemp(Ity_I32);
20190 t4 = newTemp(Ity_I32);
20191 /* dst = src0 + sign(imm)
20192 if(sign(src0 ) != sign(imm ))
20193 goto no overflow;
20194 if(sign(dst) == sign(src0 ))
20195 goto no overflow;
20196 we have overflow! */
20198 assign(t0, binop(Iop_Add32, mkexpr(tmpRs32),
20199 mkU32(extend_s_16to32(imm))));
20200 assign(t1, binop(Iop_Xor32, mkexpr(tmpRs32),
20201 mkU32(extend_s_16to32(imm))));
20202 assign(t2, unop(Iop_1Sto32, binop(Iop_CmpEQ32, binop(Iop_And32,
20203 mkexpr(t1), mkU32(0x80000000)), mkU32(0x80000000))));
20205 assign(t3, binop(Iop_Xor32, mkexpr(t0), mkexpr(tmpRs32)));
20206 assign(t4, unop(Iop_1Sto32, binop(Iop_CmpNE32, binop(Iop_And32,
20207 mkexpr(t3), mkU32(0x80000000)), mkU32(0x80000000))));
20209 stmt(IRStmt_Exit(binop(Iop_CmpEQ32, binop(Iop_Or32, mkexpr(t2),
20210 mkexpr(t4)), mkU32(0)), Ijk_SigFPE_IntOvf,
20211 mode64 ? IRConst_U64(guest_PC_curr_instr + 4) :
20212 IRConst_U32(guest_PC_curr_instr + 4),
20213 OFFB_PC));
20215 putIReg(rt, mkWidenFrom32(ty, mkexpr(t0), True));
20216 break;
20219 #elif defined(__mips__) && ((defined(__mips_isa_rev) && __mips_isa_rev >= 6))
20221 case 0x08: { /* BEQZALC, BEQC, BOVC */
20222 IRTemp t1, t2, t3, t4;
20223 if (rs == 0) { /* BEQZALC */
20224 DIP("beqzalc r%u, %u", rt, imm);
20226 if (mode64) {
20227 dis_branch_compact(True,
20228 binop(Iop_CmpEQ64, getIReg(rt), mkU64(0x0)),
20229 imm, dres);
20230 } else {
20231 dis_branch_compact(True,
20232 binop(Iop_CmpEQ32, getIReg(rt), mkU32(0x0)),
20233 imm, dres);
20235 } else if (rs < rt) { /* BEQC */
20236 DIP("beqc r%u, r%u, %u", rs, rt, imm);
20238 if (mode64) {
20239 dis_branch_compact(False,
20240 binop(Iop_CmpEQ64, getIReg(rt), getIReg(rs)),
20241 imm, dres);
20242 } else {
20243 dis_branch_compact(False,
20244 binop(Iop_CmpEQ32, getIReg(rt), getIReg(rs)),
20245 imm, dres);
20247 } else { /* BOVC */
20248 DIP("bovc r%u, r%u, %u", rs, rt, imm);
20250 if (mode64) {
20251 t0 = newTemp(Ity_I32);
20252 t1 = newTemp(Ity_I32);
20253 t2 = newTemp(Ity_I32);
20254 t3 = newTemp(Ity_I32);
20255 assign(t0, IRExpr_ITE(binop(Iop_CmpLT64S,
20256 getIReg(rt),
20257 mkU64(0xffffffff80000000ULL)),
20258 mkU32(1),
20259 IRExpr_ITE(binop(Iop_CmpLT64S,
20260 getIReg(rt),
20261 mkU64(0x7FFFFFFFULL)),
20262 mkU32(0), mkU32(1))));
20263 assign(t1, IRExpr_ITE(binop(Iop_CmpLT64S,
20264 getIReg(rs),
20265 mkU64(0xffffffff80000000ULL)),
20266 mkU32(1),
20267 IRExpr_ITE(binop(Iop_CmpLT64S,
20268 getIReg(rs),
20269 mkU64(0x7FFFFFFFULL)),
20270 mkU32(0), mkU32(1))));
20271 assign(t2, IRExpr_ITE(binop(Iop_CmpLT64S,
20272 binop(Iop_Add64,
20273 getIReg(rt), getIReg(rs)),
20274 mkU64(0xffffffff80000000ULL)),
20275 mkU32(1),
20276 IRExpr_ITE(binop(Iop_CmpLT64S,
20277 binop(Iop_Add64,
20278 getIReg(rt),
20279 getIReg(rs)),
20280 mkU64(0x7FFFFFFFULL)),
20281 mkU32(0), mkU32(1))));
20282 assign(t3, binop(Iop_Add32,
20283 mkexpr(t0),
20284 binop(Iop_Add32, mkexpr(t1), mkexpr(t2))));
20285 dis_branch_compact(False,
20286 binop(Iop_CmpNE32, mkexpr(t3), mkU32(0)),
20287 imm, dres);
20288 } else {
20289 IRTemp tmpRs32 = newTemp(Ity_I32);
20290 IRTemp tmpRt32 = newTemp(Ity_I32);
20291 assign(tmpRs32, getIReg(rs));
20292 assign(tmpRt32, getIReg(rt));
20294 t0 = newTemp(Ity_I32);
20295 t1 = newTemp(Ity_I32);
20296 t2 = newTemp(Ity_I32);
20297 t3 = newTemp(Ity_I32);
20298 t4 = newTemp(Ity_I32);
20299 /* dst = src0 + src1
20300 if (sign(src0 ) != sign(src1 ))
20301 goto no overflow;
20302 if (sign(dst) == sign(src0 ))
20303 goto no overflow;
20304 we have overflow! */
20306 assign(t0, binop(Iop_Add32, mkexpr(tmpRs32), mkexpr(tmpRt32)));
20307 assign(t1, binop(Iop_Xor32, mkexpr(tmpRs32), mkexpr(tmpRt32)));
20308 assign(t2, unop(Iop_1Uto32,
20309 binop(Iop_CmpEQ32,
20310 binop(Iop_And32, mkexpr(t1), mkU32(0x80000000)),
20311 mkU32(0x80000000))));
20313 assign(t3, binop(Iop_Xor32, mkexpr(t0), mkexpr(tmpRs32)));
20314 assign(t4, unop(Iop_1Uto32,
20315 binop(Iop_CmpNE32,
20316 binop(Iop_And32, mkexpr(t3), mkU32(0x80000000)),
20317 mkU32(0x80000000))));
20319 dis_branch_compact(False, binop(Iop_CmpEQ32,
20320 binop(Iop_Or32, mkexpr(t2), mkexpr(t4)),
20321 mkU32(0)), imm, dres);
20325 break;
20326 /* In documentation for BEQC stands rs > rt and for BOVC stands rs >= rt! */
20329 #endif
20331 case 0x09: /* ADDIU */
20332 DIP("addiu r%u, r%u, %u", rt, rs, imm);
20334 if (mode64) {
20335 putIReg(rt, mkWidenFrom32(ty, binop(Iop_Add32,
20336 mkNarrowTo32(ty, getIReg(rs)), mkU32(extend_s_16to32(imm))),
20337 True));
20338 } else
20339 putIReg(rt, binop(Iop_Add32, getIReg(rs), mkU32(extend_s_16to32(imm))));
20341 break;
20343 case 0x0A: /* SLTI */
20344 DIP("slti r%u, r%u, %u", rt, rs, imm);
20346 if (mode64)
20347 putIReg(rt, unop(Iop_1Uto64, binop(Iop_CmpLT64S, getIReg(rs),
20348 mkU64(extend_s_16to64(imm)))));
20349 else
20350 putIReg(rt, unop(Iop_1Uto32, binop(Iop_CmpLT32S, getIReg(rs),
20351 mkU32(extend_s_16to32(imm)))));
20353 break;
20355 case 0x0B: /* SLTIU */
20356 DIP("sltiu r%u, r%u, %u", rt, rs, imm);
20358 if (mode64)
20359 putIReg(rt, unop(Iop_1Uto64, binop(Iop_CmpLT64U, getIReg(rs),
20360 mkU64(extend_s_16to64(imm)))));
20361 else
20362 putIReg(rt, unop(Iop_1Uto32, binop(Iop_CmpLT32U, getIReg(rs),
20363 mkU32(extend_s_16to32(imm)))));
20365 break;
20367 case 0x0C: /* ANDI */
20368 DIP("andi r%u, r%u, %u", rt, rs, imm);
20370 if (mode64) {
20371 ALUI_PATTERN64(Iop_And64);
20372 } else {
20373 ALUI_PATTERN(Iop_And32);
20376 break;
20378 case 0x0D: /* ORI */
20379 DIP("ori r%u, r%u, %u", rt, rs, imm);
20381 if (mode64) {
20382 ALUI_PATTERN64(Iop_Or64);
20383 } else {
20384 ALUI_PATTERN(Iop_Or32);
20387 break;
20389 case 0x0E: /* XORI */
20390 DIP("xori r%u, r%u, %u", rt, rs, imm);
20392 if (mode64) {
20393 ALUI_PATTERN64(Iop_Xor64);
20394 } else {
20395 ALUI_PATTERN(Iop_Xor32);
20398 break;
20400 case 0x0F: /* LUI */
20401 if (rs == 0) {
20402 p = (imm << 16);
20403 DIP("lui r%u, imm: 0x%x", rt, imm);
20405 if (mode64)
20406 putIReg(rt, mkU64(extend_s_32to64(p)));
20407 else
20408 putIReg(rt, mkU32(p));
20410 break;
20411 } else if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) { /* AUI */
20412 DIP("aui r%u, imm: 0x%x", rt, imm);
20414 if (mode64) {
20415 putIReg(rt, unop(Iop_32Sto64,
20416 unop(Iop_64to32,
20417 binop(Iop_Add64,
20418 getIReg(rs),
20419 mkU64(extend_s_32to64(imm << 16))))));
20420 } else {
20421 putIReg(rt, binop(Iop_Add32, getIReg(rs), mkU32(imm << 16)));
20424 } else {
20425 ILLEGAL_INSTRUCTON
20428 break;
20430 default:
20431 return -1;
20434 return 0;
20437 static UInt disInstr_MIPS_WRK_10(UInt cins, const VexArchInfo* archinfo,
20438 const VexAbiInfo* abiinfo, DisResult* dres,
20439 IRStmt** bstmt, IRExpr** lastn)
20441 IRTemp t0, t1 = 0, t2, t3, t4, t5, t6, t7;
20442 UInt opcode, rs, rt, ft, fs, fd, fmt, tf, nd, function, imm;
20443 /* Additional variables for instruction fields in DSP ASE insructions */
20445 opcode = get_opcode(cins);
20446 imm = get_imm(cins);
20447 rs = get_rs(cins);
20448 rt = get_rt(cins);
20449 fs = get_fs(cins);
20450 fd = get_fd(cins);
20451 ft = get_ft(cins);
20452 tf = get_tf(cins);
20453 nd = get_nd(cins);
20454 fmt = get_fmt(cins);
20455 function = get_function(cins);
20456 IRType ty = mode64 ? Ity_I64 : Ity_I32;
20457 IRType tyF = fp_mode64 ? Ity_F64 : Ity_F32;
20459 switch (opcode & 0x0F) {
20460 case 0x01: { /* COP1 */
20461 if (fmt == 0x3 && fd == 0 && function == 0) { /* MFHC1 */
20462 DIP("mfhc1 r%u, f%u", rt, fs);
20464 if (VEX_MIPS_CPU_HAS_MIPS32R2(archinfo->hwcaps) ||
20465 VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
20466 if (fp_mode64) {
20467 t0 = newTemp(Ity_I64);
20468 t1 = newTemp(Ity_I32);
20469 assign(t0, unop(Iop_ReinterpF64asI64, getDReg(fs)));
20470 assign(t1, unop(Iop_64HIto32, mkexpr(t0)));
20471 putIReg(rt, mkWidenFrom32(ty, mkexpr(t1), True));
20472 } else {
20473 putIReg(rt, mkWidenFrom32(ty, unop(Iop_ReinterpF32asI32,
20474 getFReg(fs | 1)), True));
20476 } else {
20477 ILLEGAL_INSTRUCTON;
20480 break;
20481 } else if (fmt == 0x7 && fd == 0 && function == 0) { /* MTHC1 */
20482 DIP("mthc1 r%u, f%u", rt, fs);
20484 if (VEX_MIPS_CPU_HAS_MIPS32R2(archinfo->hwcaps) ||
20485 VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
20486 if (fp_mode64) {
20487 t0 = newTemp(Ity_I64);
20488 assign(t0, binop(Iop_32HLto64, mkNarrowTo32(ty, getIReg(rt)),
20489 unop(Iop_ReinterpF32asI32,
20490 getLoFromF64(Ity_F64, getDReg(fs)))));
20491 putDReg(fs, unop(Iop_ReinterpI64asF64, mkexpr(t0)));
20492 } else {
20493 putFReg(fs | 1, unop(Iop_ReinterpI32asF32,
20494 mkNarrowTo32(ty, getIReg(rt))));
20496 } else {
20497 ILLEGAL_INSTRUCTON;
20500 break;
20501 } else if (fmt == 0x8) { /* BC */
20502 /* FcConditionalCode(bc1_cc) */
20503 UInt bc1_cc = get_bc1_cc(cins);
20504 t1 = newTemp(Ity_I1);
20505 t2 = newTemp(Ity_I32);
20506 t3 = newTemp(Ity_I1);
20508 assign(t1, binop(Iop_CmpEQ32, mkU32(0), mkU32(bc1_cc)));
20509 assign(t2, IRExpr_ITE(mkexpr(t1),
20510 binop(Iop_And32,
20511 binop(Iop_Shr32, getFCSR(), mkU8(23)),
20512 mkU32(0x1)),
20513 binop(Iop_And32,
20514 binop(Iop_Shr32, getFCSR(),
20515 mkU8(24 + bc1_cc)),
20516 mkU32(0x1))));
20518 if (tf == 1 && nd == 0) {
20519 /* branch on true */
20520 DIP("bc1t %u, %u", bc1_cc, imm);
20521 assign(t3, binop(Iop_CmpEQ32, mkU32(1), mkexpr(t2)));
20522 dis_branch(False, mkexpr(t3), imm, bstmt);
20523 break;
20524 } else if (tf == 0 && nd == 0) {
20525 /* branch on false */
20526 DIP("bc1f %u, %u", bc1_cc, imm);
20527 assign(t3, binop(Iop_CmpEQ32, mkU32(0), mkexpr(t2)));
20528 dis_branch(False, mkexpr(t3), imm, bstmt);
20529 break;
20530 } else if (nd == 1 && tf == 0) {
20531 DIP("bc1fl %u, %u", bc1_cc, imm);
20532 *lastn = dis_branch_likely(binop(Iop_CmpNE32, mkexpr(t2),
20533 mkU32(0x0)), imm);
20534 break;
20535 } else if (nd == 1 && tf == 1) {
20536 DIP("bc1tl %u, %u", bc1_cc, imm);
20537 *lastn = dis_branch_likely(binop(Iop_CmpEQ32, mkexpr(t2),
20538 mkU32(0x0)), imm);
20539 break;
20540 } else
20541 return -1;
20542 } else if (fmt >= 0x1c && has_msa) { /* BNZ.df */
20543 Int df = fmt & 3;
20544 t0 = newTemp(Ity_I32);
20545 t1 = newTemp(Ity_V128);
20546 t2 = newTemp(Ity_V128);
20547 t3 = newTemp(Ity_V128);
20548 assign(t1, getWReg(ft));
20549 assign(t2, binop(Iop_64HLtoV128, mkU64(0), mkU64(0)));
20551 switch (df) {
20552 case 0x00: { /* BNZ.B */
20553 DIP("BNZ.B w%u, %u", ft, imm);
20554 assign(t3, binop(Iop_CmpEQ8x16, mkexpr(t1), mkexpr(t2)));
20555 break;
20558 case 0x01: { /* BNZ.H */
20559 DIP("BNZ.H w%u, %u", ft, imm);
20560 assign(t3, binop(Iop_CmpEQ16x8, mkexpr(t1), mkexpr(t2)));
20561 break;
20564 case 0x02: { /* BNZ.W */
20565 DIP("BNZ.W w%u, %u", ft, imm);
20566 assign(t3, binop(Iop_CmpEQ32x4, mkexpr(t1), mkexpr(t2)));
20567 break;
20570 case 0x03: { /* BNZ.D */
20571 DIP("BNZ.D w%u, %u", ft, imm);
20572 assign(t3, binop(Iop_CmpEQ64x2, mkexpr(t1), mkexpr(t2)));
20573 break;
20577 assign(t0,
20578 binop(Iop_Or32,
20579 binop(Iop_Or32,
20580 unop(Iop_V128to32, mkexpr(t3)),
20581 unop(Iop_64HIto32, unop(Iop_V128to64, mkexpr(t3)))),
20582 binop(Iop_Or32,
20583 unop(Iop_64to32,
20584 unop(Iop_V128HIto64, mkexpr(t3))),
20585 unop(Iop_64HIto32,
20586 unop(Iop_V128HIto64, mkexpr(t3))))));
20587 dis_branch(False,
20588 binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0)), imm, bstmt);
20589 } else if (fmt == 0x0F && has_msa) { /* BNZ.V */
20590 t0 = newTemp(Ity_I32);
20591 t1 = newTemp(Ity_V128);
20592 assign(t1, getWReg(ft));
20593 assign(t0,
20594 binop(Iop_Or32,
20595 binop(Iop_Or32,
20596 unop(Iop_V128to32, mkexpr(t1)),
20597 unop(Iop_64HIto32, unop(Iop_V128to64, mkexpr(t1)))),
20598 binop(Iop_Or32,
20599 unop(Iop_64to32, unop(Iop_V128HIto64, mkexpr(t1))),
20600 unop(Iop_64HIto32,
20601 unop(Iop_V128HIto64, mkexpr(t1))))));
20602 dis_branch(False,
20603 binop(Iop_CmpNE32, mkexpr(t0), mkU32(0)), imm, bstmt);
20604 } else if (fmt >= 0x18 && has_msa) { /* BZ.df */
20605 Int df = fmt & 3;
20606 t0 = newTemp(Ity_I32);
20607 t1 = newTemp(Ity_V128);
20608 t2 = newTemp(Ity_V128);
20609 t3 = newTemp(Ity_V128);
20610 assign(t1, getWReg(ft));
20611 assign(t2, binop(Iop_64HLtoV128, mkU64(0), mkU64(0)));
20613 switch (df) {
20614 case 0x00: { /* BZ.B */
20615 DIP("BZ.B w%u, %u", ft, imm);
20616 assign(t3, binop(Iop_CmpEQ8x16, mkexpr(t1), mkexpr(t2)));
20617 break;
20620 case 0x01: { /* BZ.H */
20621 DIP("BZ.H w%u, %u", ft, imm);
20622 assign(t3, binop(Iop_CmpEQ16x8, mkexpr(t1), mkexpr(t2)));
20623 break;
20626 case 0x02: { /* BZ.W */
20627 DIP("BZ.W w%u, %u", ft, imm);
20628 assign(t3, binop(Iop_CmpEQ32x4, mkexpr(t1), mkexpr(t2)));
20629 break;
20632 case 0x03: { /* BZ.D */
20633 DIP("BZ.D w%u, %u", ft, imm);
20634 assign(t3, binop(Iop_CmpEQ64x2, mkexpr(t1), mkexpr(t2)));
20635 break;
20639 assign(t0,
20640 binop(Iop_Or32,
20641 binop(Iop_Or32,
20642 unop(Iop_V128to32, mkexpr(t3)),
20643 unop(Iop_64HIto32, unop(Iop_V128to64, mkexpr(t3)))),
20644 binop(Iop_Or32,
20645 unop(Iop_64to32, unop(Iop_V128HIto64, mkexpr(t3))),
20646 unop(Iop_64HIto32,
20647 unop(Iop_V128HIto64, mkexpr(t3))))));
20648 dis_branch(False,
20649 binop(Iop_CmpNE32, mkexpr(t0), mkU32(0)), imm, bstmt);
20650 } else if (fmt == 0x0B && has_msa) { /* BZ.V */
20651 t0 = newTemp(Ity_I32);
20652 t1 = newTemp(Ity_V128);
20653 assign(t1, getWReg(ft));
20654 assign(t0,
20655 binop(Iop_Or32,
20656 binop(Iop_Or32,
20657 unop(Iop_V128to32, mkexpr(t1)),
20658 unop(Iop_64HIto32, unop(Iop_V128to64, mkexpr(t1)))),
20659 binop(Iop_Or32,
20660 unop(Iop_64to32, unop(Iop_V128HIto64, mkexpr(t1))),
20661 unop(Iop_64HIto32,
20662 unop(Iop_V128HIto64, mkexpr(t1))))));
20663 dis_branch(False,
20664 binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0)), imm, bstmt);
20665 } else if (fmt == 0x09) { /* BC1EQZ */
20666 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
20667 DIP("bc1eqz f%u, %u", ft, imm);
20668 t1 = newTemp(Ity_I1);
20670 if (mode64) {
20671 assign(t1, binop(Iop_CmpEQ64,
20672 binop(Iop_And64,
20673 unop(Iop_ReinterpF64asI64, getDReg(ft)),
20674 mkU64(1)),
20675 mkU64(0)));
20676 } else {
20677 assign(t1, binop(Iop_CmpEQ32,
20678 binop(Iop_And32,
20679 unop(Iop_64to32,
20680 unop(Iop_ReinterpF64asI64,
20681 getDReg(ft))),
20682 mkU32(1)),
20683 mkU32(0)));
20686 dis_branch(False, mkexpr(t1), imm, bstmt);
20687 } else {
20688 ILLEGAL_INSTRUCTON
20690 } else if (fmt == 0x0D) { /* BC1NEZ */
20691 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
20692 DIP("bc1nez f%u, %u", ft, imm);
20693 t1 = newTemp(Ity_I1);
20695 if (mode64) {
20696 assign(t1, binop(Iop_CmpNE64,
20697 binop(Iop_And64,
20698 unop(Iop_ReinterpF64asI64, getDReg(ft)),
20699 mkU64(1)),
20700 mkU64(0)));
20701 } else {
20702 assign(t1, binop(Iop_CmpNE32,
20703 binop(Iop_And32,
20704 unop(Iop_64to32,
20705 unop(Iop_ReinterpF64asI64, getDReg(ft))),
20706 mkU32(1)),
20707 mkU32(0)));
20710 dis_branch(False, mkexpr(t1), imm, bstmt);
20711 } else {
20712 ILLEGAL_INSTRUCTON;
20713 break;
20715 } else {
20716 if (fmt == 0x15) { /* CMP.cond.d */
20717 Bool comparison = True;
20718 UInt signaling = CMPAFD;
20719 DIP("cmp.cond.d f%u, f%u, f%u, cond %u", fd, fs, ft, function);
20720 t0 = newTemp(Ity_I32);
20722 /* Conditions starting with S should signal exception on QNaN inputs. */
20723 switch (function) {
20724 case 0x08: /* SAF */
20725 signaling = CMPSAFD; /* fallthrough */
20727 case 0x00: /* AF */
20728 assign(t0, binop(Iop_CmpF64, getDReg(fs), getDReg(ft)));
20729 calculateFCSR(fs, ft, signaling, False, 2);
20730 putDReg(fd,
20731 binop(Iop_I64StoF64,
20732 get_IR_roundingmode(), mkU64(0)));
20733 break;
20735 case 0x09: /* SUN */
20736 signaling = CMPSAFD; /* fallthrough */
20738 case 0x01: /* UN */
20739 assign(t0, binop(Iop_CmpF64, getDReg(fs), getDReg(ft)));
20740 calculateFCSR(fs, ft, signaling, False, 2);
20741 putDReg(fd,
20742 IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x45)),
20743 unop(Iop_ReinterpI64asF64,
20744 mkU64(0xFFFFFFFFFFFFFFFFULL)),
20745 binop(Iop_I64StoF64,
20746 get_IR_roundingmode(), mkU64(0))));
20747 break;
20749 case 0x19: /* SOR */
20750 signaling = CMPSAFD; /* fallthrough */
20752 case 0x11: /* OR */
20753 assign(t0, binop(Iop_CmpF64, getDReg(fs), getDReg(ft)));
20754 calculateFCSR(fs, ft, signaling, False, 2);
20755 putDReg(fd,
20756 IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x45)),
20757 binop(Iop_I64StoF64,
20758 get_IR_roundingmode(), mkU64(0)),
20759 unop(Iop_ReinterpI64asF64,
20760 mkU64(0xFFFFFFFFFFFFFFFFULL))));
20761 break;
20763 case 0x0A: /* SEQ */
20764 signaling = CMPSAFD; /* fallthrough */
20766 case 0x02: /* EQ */
20767 assign(t0, binop(Iop_CmpF64, getDReg(fs), getDReg(ft)));
20768 calculateFCSR(fs, ft, signaling, False, 2);
20769 putDReg(fd,
20770 IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x40)),
20771 unop(Iop_ReinterpI64asF64,
20772 mkU64(0xFFFFFFFFFFFFFFFFULL)),
20773 binop(Iop_I64StoF64,
20774 get_IR_roundingmode(), mkU64(0))));
20775 break;
20777 case 0x1A: /* SNEQ */
20778 signaling = CMPSAFD; /* fallthrough */
20780 case 0x12: /* NEQ */
20781 assign(t0, binop(Iop_CmpF64, getDReg(fs), getDReg(ft)));
20782 calculateFCSR(fs, ft, signaling, False, 2);
20783 putDReg(fd,
20784 IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x40)),
20785 binop(Iop_I64StoF64,
20786 get_IR_roundingmode(), mkU64(0)),
20787 unop(Iop_ReinterpI64asF64,
20788 mkU64(0xFFFFFFFFFFFFFFFFULL))));
20789 break;
20791 case 0x0B: /* SUEQ */
20792 signaling = CMPSAFD; /* fallthrough */
20794 case 0x03: /* UEQ */
20795 assign(t0, binop(Iop_CmpF64, getDReg(fs), getDReg(ft)));
20796 calculateFCSR(fs, ft, signaling, False, 2);
20797 putDReg(fd,
20798 IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x40)),
20799 unop(Iop_ReinterpI64asF64,
20800 mkU64(0xFFFFFFFFFFFFFFFFULL)),
20801 IRExpr_ITE(binop(Iop_CmpEQ32,
20802 mkexpr(t0), mkU32(0x45)),
20803 unop(Iop_ReinterpI64asF64,
20804 mkU64(0xFFFFFFFFFFFFFFFFULL)),
20805 binop(Iop_I64StoF64,
20806 get_IR_roundingmode(),
20807 mkU64(0)))));
20808 break;
20810 case 0x1B: /* SNEQ */
20811 signaling = CMPSAFD; /* fallthrough */
20813 case 0x13: /* NEQ */
20814 assign(t0, binop(Iop_CmpF64, getDReg(fs), getDReg(ft)));
20815 calculateFCSR(fs, ft, signaling, False, 2);
20816 putDReg(fd,
20817 IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x01)),
20818 unop(Iop_ReinterpI64asF64,
20819 mkU64(0xFFFFFFFFFFFFFFFFULL)),
20820 IRExpr_ITE(binop(Iop_CmpEQ32,
20821 mkexpr(t0), mkU32(0x00)),
20822 unop(Iop_ReinterpI64asF64,
20823 mkU64(0xFFFFFFFFFFFFFFFFULL)),
20824 binop(Iop_I64StoF64,
20825 get_IR_roundingmode(),
20826 mkU64(0)))));
20827 break;
20829 case 0x0C: /* SLT */
20830 signaling = CMPSAFD; /* fallthrough */
20832 case 0x04: /* LT */
20833 assign(t0, binop(Iop_CmpF64, getDReg(fs), getDReg(ft)));
20834 calculateFCSR(fs, ft, signaling, False, 2);
20835 putDReg(fd,
20836 IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x01)),
20837 unop(Iop_ReinterpI64asF64,
20838 mkU64(0xFFFFFFFFFFFFFFFFULL)),
20839 binop(Iop_I64StoF64,
20840 get_IR_roundingmode(), mkU64(0))));
20841 break;
20843 case 0x0D: /* SULT */
20844 signaling = CMPSAFD; /* fallthrough */
20846 case 0x05: /* ULT */
20847 assign(t0, binop(Iop_CmpF64, getDReg(fs), getDReg(ft)));
20848 calculateFCSR(fs, ft, signaling, False, 2);
20849 putDReg(fd,
20850 IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x01)),
20851 unop(Iop_ReinterpI64asF64,
20852 mkU64(0xFFFFFFFFFFFFFFFFULL)),
20853 IRExpr_ITE(binop(Iop_CmpEQ32,
20854 mkexpr(t0), mkU32(0x45)),
20855 unop(Iop_ReinterpI64asF64,
20856 mkU64(0xFFFFFFFFFFFFFFFFULL)),
20857 binop(Iop_I64StoF64,
20858 get_IR_roundingmode(),
20859 mkU64(0)))));
20860 break;
20862 case 0x0E: /* SLE */
20863 signaling = CMPSAFD; /* fallthrough */
20865 case 0x06: /* LE */
20866 assign(t0, binop(Iop_CmpF64, getDReg(fs), getDReg(ft)));
20867 calculateFCSR(fs, ft, signaling, False, 2);
20868 putDReg(fd,
20869 IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x01)),
20870 unop(Iop_ReinterpI64asF64,
20871 mkU64(0xFFFFFFFFFFFFFFFFULL)),
20872 IRExpr_ITE(binop(Iop_CmpEQ32,
20873 mkexpr(t0), mkU32(0x40)),
20874 unop(Iop_ReinterpI64asF64,
20875 mkU64(0xFFFFFFFFFFFFFFFFULL)),
20876 binop(Iop_I64StoF64,
20877 get_IR_roundingmode(),
20878 mkU64(0)))));
20879 break;
20881 case 0x0F: /* SULE */
20882 signaling = CMPSAFD; /* fallthrough */
20884 case 0x07: /* ULE */
20885 assign(t0, binop(Iop_CmpF64, getDReg(fs), getDReg(ft)));
20886 calculateFCSR(fs, ft, signaling, False, 2);
20887 putDReg(fd,
20888 IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x0)),
20889 binop(Iop_I64StoF64,
20890 get_IR_roundingmode(), mkU64(0)),
20891 unop(Iop_ReinterpI64asF64,
20892 mkU64(0xFFFFFFFFFFFFFFFFULL))));
20893 break;
20895 default:
20896 comparison = False;
20899 if (comparison) {
20900 if (!VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
20901 ILLEGAL_INSTRUCTON
20904 break;
20907 } else if (fmt == 0x14) {
20908 Bool comparison = True;
20909 UInt signaling = CMPAFS;
20910 DIP("cmp.cond.s f%u, f%u, f%u, cond %u", fd, fs, ft, function);
20911 t0 = newTemp(Ity_I32);
20913 /* Conditions starting with S should signal exception on QNaN inputs. */
20914 switch (function) {
20915 case 0x08: /* SAF */
20916 signaling = CMPSAFS; /* fallthrough */
20918 case 0x00: /* AF */
20919 assign(t0, binop(Iop_CmpF32,
20920 getLoFromF64(Ity_F64, getFReg(fs)),
20921 getLoFromF64(Ity_F64, getFReg(ft))));
20922 calculateFCSR(fs, ft, signaling, True, 2);
20923 putFReg(fd,
20924 mkWidenFromF32(tyF,
20925 binop(Iop_I32StoF32,
20926 get_IR_roundingmode(), mkU32(0))));
20927 break;
20929 case 0x09: /* SUN */
20930 signaling = CMPSAFS; /* fallthrough */
20932 case 0x01: /* UN */
20933 assign(t0, binop(Iop_CmpF32,
20934 getLoFromF64(Ity_F64, getFReg(fs)),
20935 getLoFromF64(Ity_F64, getFReg(ft))));
20936 calculateFCSR(fs, ft, signaling, True, 2);
20937 putFReg(fd,
20938 IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x45)),
20939 mkWidenFromF32(tyF,
20940 unop(Iop_ReinterpI32asF32,
20941 mkU32(0xFFFFFFFFU))),
20942 mkWidenFromF32(tyF,
20943 binop(Iop_I32StoF32,
20944 get_IR_roundingmode(),
20945 mkU32(0)))));
20946 break;
20948 case 0x19: /* SOR */
20949 signaling = CMPSAFS; /* fallthrough */
20951 case 0x11: /* OR */
20952 assign(t0, binop(Iop_CmpF32,
20953 getLoFromF64(Ity_F64, getFReg(fs)),
20954 getLoFromF64(Ity_F64, getFReg(ft))));
20955 calculateFCSR(fs, ft, signaling, True, 2);
20956 putFReg(fd,
20957 IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x45)),
20958 mkWidenFromF32(tyF,
20959 binop(Iop_I32StoF32,
20960 get_IR_roundingmode(),
20961 mkU32(0))),
20962 mkWidenFromF32(tyF,
20963 unop(Iop_ReinterpI32asF32,
20964 mkU32(0xFFFFFFFFU)))));
20965 break;
20967 case 0x0A: /* SEQ */
20968 signaling = CMPSAFS; /* fallthrough */
20970 case 0x02: /* EQ */
20971 assign(t0, binop(Iop_CmpF32,
20972 getLoFromF64(Ity_F64, getFReg(fs)),
20973 getLoFromF64(Ity_F64, getFReg(ft))));
20974 calculateFCSR(fs, ft, signaling, True, 2);
20975 putFReg(fd,
20976 IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x40)),
20977 mkWidenFromF32(tyF,
20978 unop(Iop_ReinterpI32asF32,
20979 mkU32(0xFFFFFFFFU))),
20980 mkWidenFromF32(tyF,
20981 binop(Iop_I32StoF32,
20982 get_IR_roundingmode(),
20983 mkU32(0)))));
20984 break;
20986 case 0x1A: /* SNEQ */
20987 signaling = CMPSAFS; /* fallthrough */
20989 case 0x12: /* NEQ */
20990 assign(t0, binop(Iop_CmpF32,
20991 getLoFromF64(Ity_F64, getFReg(fs)),
20992 getLoFromF64(Ity_F64, getFReg(ft))));
20993 calculateFCSR(fs, ft, signaling, True, 2);
20994 putFReg(fd,
20995 IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x40)),
20996 mkWidenFromF32(tyF,
20997 binop(Iop_I32StoF32,
20998 get_IR_roundingmode(),
20999 mkU32(0))),
21000 mkWidenFromF32(tyF,
21001 unop(Iop_ReinterpI32asF32,
21002 mkU32(0xFFFFFFFFU)))));
21003 break;
21005 case 0x0B: /* SUEQ */
21006 signaling = CMPSAFS; /* fallthrough */
21008 case 0x03: /* UEQ */
21009 assign(t0, binop(Iop_CmpF32,
21010 getLoFromF64(Ity_F64, getFReg(fs)),
21011 getLoFromF64(Ity_F64, getFReg(ft))));
21012 calculateFCSR(fs, ft, signaling, True, 2);
21013 putFReg(fd,
21014 IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x40)),
21015 mkWidenFromF32(tyF,
21016 unop(Iop_ReinterpI32asF32,
21017 mkU32(0xFFFFFFFFU))),
21018 IRExpr_ITE(binop(Iop_CmpEQ32,
21019 mkexpr(t0), mkU32(0x45)),
21020 mkWidenFromF32(tyF,
21021 unop(Iop_ReinterpI32asF32,
21022 mkU32(0xFFFFFFFFU))),
21023 mkWidenFromF32(tyF,
21024 binop(Iop_I32StoF32,
21025 get_IR_roundingmode(),
21026 mkU32(0))))));
21027 break;
21029 case 0x1B: /* SNEQ */
21030 signaling = CMPSAFS; /* fallthrough */
21032 case 0x13: /* NEQ */
21033 assign(t0, binop(Iop_CmpF32,
21034 getLoFromF64(Ity_F64, getFReg(fs)),
21035 getLoFromF64(Ity_F64, getFReg(ft))));
21036 calculateFCSR(fs, ft, signaling, True, 2);
21037 putFReg(fd,
21038 IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x01)),
21039 mkWidenFromF32(tyF,
21040 unop(Iop_ReinterpI32asF32,
21041 mkU32(0xFFFFFFFFU))),
21042 IRExpr_ITE(binop(Iop_CmpEQ32,
21043 mkexpr(t0), mkU32(0x00)),
21044 mkWidenFromF32(tyF,
21045 unop(Iop_ReinterpI32asF32,
21046 mkU32(0xFFFFFFFFU))),
21047 mkWidenFromF32(tyF,
21048 binop(Iop_I32StoF32,
21049 get_IR_roundingmode(),
21050 mkU32(0))))));
21051 break;
21053 case 0x0C: /* SLT */
21054 signaling = CMPSAFS; /* fallthrough */
21056 case 0x04: /* LT */
21057 assign(t0, binop(Iop_CmpF32,
21058 getLoFromF64(Ity_F64, getFReg(fs)),
21059 getLoFromF64(Ity_F64, getFReg(ft))));
21060 calculateFCSR(fs, ft, signaling, True, 2);
21061 putFReg(fd,
21062 IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x01)),
21063 mkWidenFromF32(tyF,
21064 unop(Iop_ReinterpI32asF32,
21065 mkU32(0xFFFFFFFFU))),
21066 mkWidenFromF32(tyF,
21067 binop(Iop_I32StoF32,
21068 get_IR_roundingmode(),
21069 mkU32(0)))));
21070 break;
21072 case 0x0D: /* SULT */
21073 signaling = CMPSAFS; /* fallthrough */
21075 case 0x05: /* ULT */
21076 assign(t0, binop(Iop_CmpF32,
21077 getLoFromF64(Ity_F64, getFReg(fs)),
21078 getLoFromF64(Ity_F64, getFReg(ft))));
21079 calculateFCSR(fs, ft, signaling, True, 2);
21080 putFReg(fd,
21081 IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x01)),
21082 mkWidenFromF32(tyF,
21083 unop(Iop_ReinterpI32asF32,
21084 mkU32(0xFFFFFFFFU))),
21085 IRExpr_ITE(binop(Iop_CmpEQ32,
21086 mkexpr(t0), mkU32(0x45)),
21087 mkWidenFromF32(tyF,
21088 unop(Iop_ReinterpI32asF32,
21089 mkU32(0xFFFFFFFFU))),
21090 mkWidenFromF32(tyF,
21091 binop(Iop_I32StoF32,
21092 get_IR_roundingmode(),
21093 mkU32(0))))));
21094 break;
21096 case 0x0E: /* SLE */
21097 signaling = CMPSAFS; /* fallthrough */
21099 case 0x06: /* LE */
21100 assign(t0, binop(Iop_CmpF32,
21101 getLoFromF64(Ity_F64, getFReg(fs)),
21102 getLoFromF64(Ity_F64, getFReg(ft))));
21103 calculateFCSR(fs, ft, signaling, True, 2);
21104 putFReg(fd,
21105 IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x01)),
21106 mkWidenFromF32(tyF,
21107 unop(Iop_ReinterpI32asF32,
21108 mkU32(0xFFFFFFFFU))),
21109 IRExpr_ITE(binop(Iop_CmpEQ32,
21110 mkexpr(t0), mkU32(0x40)),
21111 mkWidenFromF32(tyF,
21112 unop(Iop_ReinterpI32asF32,
21113 mkU32(0xFFFFFFFFU))),
21114 mkWidenFromF32(tyF,
21115 binop(Iop_I32StoF32,
21116 get_IR_roundingmode(),
21117 mkU32(0))))));
21118 break;
21120 case 0x0F: /* SULE */
21121 signaling = CMPSAFS; /* fallthrough */
21123 case 0x07: /* ULE */
21124 assign(t0, binop(Iop_CmpF32,
21125 getLoFromF64(Ity_F64, getFReg(fs)),
21126 getLoFromF64(Ity_F64, getFReg(ft))));
21127 calculateFCSR(fs, ft, signaling, True, 2);
21128 putFReg(fd,
21129 IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x0)),
21130 mkWidenFromF32(tyF,
21131 binop(Iop_I32StoF32,
21132 get_IR_roundingmode(),
21133 mkU32(0))),
21134 mkWidenFromF32(tyF,
21135 unop(Iop_ReinterpI32asF32,
21136 mkU32(0xFFFFFFFFU)))));
21137 break;
21139 default:
21140 comparison = False;
21143 if (comparison) {
21144 if (!VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
21145 ILLEGAL_INSTRUCTON
21148 break;
21152 switch (function) {
21153 case 0x04: { /* SQRT.fmt */
21154 switch (fmt) {
21155 case 0x10: { /* S */
21156 IRExpr *rm = get_IR_roundingmode();
21157 putFReg(fd, mkWidenFromF32(tyF, binop(Iop_SqrtF32, rm,
21158 getLoFromF64(tyF, getFReg(fs)))));
21159 break;
21162 case 0x11: { /* D */
21163 IRExpr *rm = get_IR_roundingmode();
21164 putDReg(fd, binop(Iop_SqrtF64, rm, getDReg(fs)));
21165 break;
21168 default:
21169 return -1;
21172 break; /* SQRT.fmt */
21174 case 0x05: /* ABS.fmt */
21175 switch (fmt) {
21176 case 0x10: /* S */
21177 DIP("abs.s f%u, f%u", fd, fs);
21178 putFReg(fd, mkWidenFromF32(tyF, unop(Iop_AbsF32,
21179 getLoFromF64(tyF, getFReg(fs)))));
21180 break;
21182 case 0x11: /* D */
21183 DIP("abs.d f%u, f%u", fd, fs);
21184 putDReg(fd, unop(Iop_AbsF64, getDReg(fs)));
21185 break;
21187 default:
21188 return -1;
21191 break; /* ABS.fmt */
21193 case 0x02: /* MUL.fmt */
21194 switch (fmt) {
21195 case 0x11: { /* D */
21196 DIP("mul.d f%u, f%u, f%u", fd, fs, ft);
21197 IRExpr *rm = get_IR_roundingmode();
21198 putDReg(fd, triop(Iop_MulF64, rm, getDReg(fs),
21199 getDReg(ft)));
21200 break;
21203 case 0x10: { /* S */
21204 DIP("mul.s f%u, f%u, f%u", fd, fs, ft);
21205 IRExpr *rm = get_IR_roundingmode();
21206 putFReg(fd, mkWidenFromF32(tyF, triop(Iop_MulF32, rm,
21207 getLoFromF64(tyF, getFReg(fs)),
21208 getLoFromF64(tyF, getFReg(ft)))));
21209 break;
21212 default:
21213 return -1;
21216 break; /* MUL.fmt */
21218 case 0x03: /* DIV.fmt */
21219 switch (fmt) {
21220 case 0x11: { /* D */
21221 DIP("div.d f%u, f%u, f%u", fd, fs, ft);
21222 IRExpr *rm = get_IR_roundingmode();
21223 putDReg(fd, triop(Iop_DivF64, rm, getDReg(fs),
21224 getDReg(ft)));
21225 break;
21228 case 0x10: { /* S */
21229 DIP("div.s f%u, f%u, f%u", fd, fs, ft);
21230 calculateFCSR(fs, ft, DIVS, False, 2);
21231 IRExpr *rm = get_IR_roundingmode();
21232 putFReg(fd, mkWidenFromF32(tyF, triop(Iop_DivF32, rm,
21233 getLoFromF64(tyF, getFReg(fs)),
21234 getLoFromF64(tyF, getFReg(ft)))));
21235 break;
21238 default:
21239 return -1;
21242 break; /* DIV.fmt */
21244 case 0x01: /* SUB.fmt */
21245 switch (fmt) {
21246 case 0x11: { /* D */
21247 DIP("sub.d f%u, f%u, f%u", fd, fs, ft);
21248 calculateFCSR(fs, ft, SUBD, False, 2);
21249 IRExpr *rm = get_IR_roundingmode();
21250 putDReg(fd, triop(Iop_SubF64, rm, getDReg(fs),
21251 getDReg(ft)));
21252 break;
21255 case 0x10: { /* S */
21256 DIP("sub.s f%u, f%u, f%u", fd, fs, ft);
21257 calculateFCSR(fs, ft, SUBS, True, 2);
21258 IRExpr *rm = get_IR_roundingmode();
21259 putFReg(fd, mkWidenFromF32(tyF, triop(Iop_SubF32, rm,
21260 getLoFromF64(tyF, getFReg(fs)),
21261 getLoFromF64(tyF, getFReg(ft)))));
21262 break;
21265 default:
21266 return -1;
21269 break; /* SUB.fmt */
21271 case 0x06: /* MOV.fmt */
21272 switch (fmt) {
21273 case 0x11: /* D */
21274 DIP("mov.d f%u, f%u", fd, fs);
21276 if (fp_mode64) {
21277 putDReg(fd, getDReg(fs));
21278 } else {
21279 putFReg(fd, getFReg(fs));
21280 putFReg(fd + 1, getFReg(fs + 1));
21283 break;
21285 case 0x10: /* S */
21286 DIP("mov.s f%u, f%u", fd, fs);
21287 putFReg(fd, getFReg(fs));
21288 break;
21290 default:
21291 return -1;
21294 break; /* MOV.fmt */
21296 case 0x07: /* NEG.fmt */
21297 switch (fmt) {
21298 case 0x10: /* S */
21299 DIP("neg.s f%u, f%u", fd, fs);
21300 putFReg(fd, mkWidenFromF32(tyF, unop(Iop_NegF32,
21301 getLoFromF64(tyF, getFReg(fs)))));
21302 break;
21304 case 0x11: /* D */
21305 DIP("neg.d f%u, f%u", fd, fs);
21306 putDReg(fd, unop(Iop_NegF64, getDReg(fs)));
21307 break;
21309 default:
21310 return -1;
21313 break; /* NEG.fmt */
21315 case 0x08: /* ROUND.L.fmt */
21316 switch (fmt) {
21317 case 0x10: /* S */
21318 DIP("round.l.s f%u, f%u", fd, fs);
21320 if (fp_mode64) {
21321 calculateFCSR(fs, 0, ROUNDLS, True, 1);
21322 t0 = newTemp(Ity_I64);
21324 assign(t0, binop(Iop_F32toI64S, mkU32(0x0),
21325 getLoFromF64(Ity_F64, getFReg(fs))));
21327 putDReg(fd, unop(Iop_ReinterpI64asF64, mkexpr(t0)));
21328 } else {
21329 ILLEGAL_INSTRUCTON
21332 break;
21334 case 0x11: /* D */
21335 DIP("round.l.d f%u, f%u", fd, fs);
21337 if (fp_mode64) {
21338 calculateFCSR(fs, 0, ROUNDLD, False, 1);
21339 putDReg(fd, unop(Iop_ReinterpI64asF64,
21340 binop(Iop_F64toI64S,
21341 mkU32(0x0),
21342 getDReg(fs))));
21343 } else {
21344 ILLEGAL_INSTRUCTON
21347 break;
21349 default:
21350 return -1;
21354 break; /* ROUND.L.fmt */
21356 case 0x09: /* TRUNC.L.fmt */
21357 switch (fmt) {
21358 case 0x10: /* S */
21359 DIP("trunc.l.s f%u, f%u", fd, fs);
21361 if (fp_mode64) {
21362 calculateFCSR(fs, 0, TRUNCLS, True, 1);
21363 t0 = newTemp(Ity_I64);
21364 assign(t0, binop(Iop_F32toI64S, mkU32(0x3),
21365 getLoFromF64(Ity_F64, getFReg(fs))));
21367 putDReg(fd, unop(Iop_ReinterpI64asF64, mkexpr(t0)));
21368 } else {
21369 ILLEGAL_INSTRUCTON
21372 break;
21374 case 0x11: /* D */
21375 DIP("trunc.l.d f%u, f%u", fd, fs);
21377 if (fp_mode64) {
21378 calculateFCSR(fs, 0, TRUNCLD, False, 1);
21379 putDReg(fd, unop(Iop_ReinterpI64asF64,
21380 binop(Iop_F64toI64S,
21381 mkU32(0x3),
21382 getDReg(fs))));
21383 } else {
21384 ILLEGAL_INSTRUCTON
21387 break;
21389 default:
21390 return -1;
21393 break; /* TRUNC.L.fmt */
21395 case 0x15: /* RECIP.fmt */
21396 switch (fmt) {
21397 case 0x10: { /* S */
21398 DIP("recip.s f%u, f%u", fd, fs);
21399 IRExpr *rm = get_IR_roundingmode();
21400 putFReg(fd, mkWidenFromF32(tyF, triop(Iop_DivF32,
21401 rm, unop(Iop_ReinterpI32asF32,
21402 mkU32(ONE_SINGLE)), getLoFromF64(tyF,
21403 getFReg(fs)))));
21404 break;
21407 case 0x11: { /* D */
21408 DIP("recip.d f%u, f%u", fd, fs);
21409 IRExpr *rm = get_IR_roundingmode();
21410 /* putDReg(fd, 1.0/getDreg(fs)); */
21411 putDReg(fd, triop(Iop_DivF64, rm,
21412 unop(Iop_ReinterpI64asF64,
21413 mkU64(ONE_DOUBLE)), getDReg(fs)));
21414 break;
21417 default:
21418 return -1;
21422 break; /* RECIP.fmt */
21424 case 0x13: /* MOVN.fmt */
21425 switch (fmt) {
21426 case 0x10: /* S */
21427 DIP("movn.s f%u, f%u, r%u", fd, fs, rt);
21428 t1 = newTemp(Ity_I1);
21430 if (mode64)
21431 assign(t1, binop(Iop_CmpNE64, mkU64(0), getIReg(rt)));
21432 else
21433 assign(t1, binop(Iop_CmpNE32, mkU32(0), getIReg(rt)));
21435 putFReg(fd, IRExpr_ITE(mkexpr(t1), getFReg(fs), getFReg(fd)));
21436 break;
21438 case 0x11: /* D */
21439 DIP("movn.d f%u, f%u, r%u", fd, fs, rt);
21440 t1 = newTemp(Ity_I1);
21442 if (mode64)
21443 assign(t1, binop(Iop_CmpNE64, mkU64(0), getIReg(rt)));
21444 else
21445 assign(t1, binop(Iop_CmpNE32, mkU32(0), getIReg(rt)));
21447 putDReg(fd, IRExpr_ITE(mkexpr(t1), getDReg(fs), getDReg(fd)));
21448 break;
21450 default:
21451 return -1;
21454 break; /* MOVN.fmt */
21456 case 0x12: /* MOVZ.fmt */
21457 switch (fmt) {
21458 case 0x10: /* S */
21459 DIP("movz.s f%u, f%u, r%u", fd, fs, rt);
21460 t1 = newTemp(Ity_I1);
21462 if (mode64)
21463 assign(t1, binop(Iop_CmpEQ64, mkU64(0), getIReg(rt)));
21464 else
21465 assign(t1, binop(Iop_CmpEQ32, mkU32(0), getIReg(rt)));
21467 putFReg(fd, IRExpr_ITE(mkexpr(t1), getFReg(fs), getFReg(fd)));
21468 break;
21470 case 0x11: /* D */
21471 DIP("movz.d f%u, f%u, r%u", fd, fs, rt);
21472 t1 = newTemp(Ity_I1);
21474 if (mode64)
21475 assign(t1, binop(Iop_CmpEQ64, mkU64(0), getIReg(rt)));
21476 else
21477 assign(t1, binop(Iop_CmpEQ32, mkU32(0), getIReg(rt)));
21479 putDReg(fd, IRExpr_ITE(mkexpr(t1), getDReg(fs), getDReg(fd)));
21480 break;
21482 default:
21483 return -1;
21486 break; /* MOVZ.fmt */
21488 case 0x11: /* MOVT.fmt */
21489 if (tf == 1) {
21490 UInt mov_cc = get_mov_cc(cins);
21492 switch (fmt) { /* MOVCF = 010001 */
21493 case 0x11: /* D */
21494 DIP("movt.d f%u, f%u, %u", fd, fs, mov_cc);
21495 t1 = newTemp(Ity_I1);
21496 t2 = newTemp(Ity_I32);
21497 t3 = newTemp(Ity_I1);
21498 t4 = newTemp(Ity_F64);
21500 assign(t1, binop(Iop_CmpEQ32, mkU32(0), mkU32(mov_cc)));
21501 assign(t2, IRExpr_ITE(mkexpr(t1),
21502 binop(Iop_And32,
21503 binop(Iop_Shr32, getFCSR(),
21504 mkU8(23)),
21505 mkU32(0x1)),
21506 binop(Iop_And32,
21507 binop(Iop_Shr32, getFCSR(),
21508 mkU8(24 + mov_cc)),
21509 mkU32(0x1))
21512 assign(t3, binop(Iop_CmpEQ32, mkU32(1), mkexpr(t2)));
21513 assign(t4, IRExpr_ITE(mkexpr(t3),
21514 getDReg(fs), getDReg(fd)));
21515 putDReg(fd, mkexpr(t4));
21516 break;
21518 case 0x10: /* S */
21519 DIP("movt.s f%u, f%u, %u", fd, fs, mov_cc);
21520 t1 = newTemp(Ity_I1);
21521 t2 = newTemp(Ity_I32);
21522 t3 = newTemp(Ity_I1);
21523 t4 = newTemp(Ity_F64);
21524 t5 = newTemp(Ity_F64);
21525 t6 = newTemp(Ity_F64);
21526 t7 = newTemp(Ity_I64);
21528 if (fp_mode64) {
21529 assign(t5, getFReg(fs));
21530 assign(t6, getFReg(fd));
21531 } else {
21532 assign(t5, unop(Iop_F32toF64, getFReg(fs)));
21533 assign(t6, unop(Iop_F32toF64, getFReg(fd)));
21536 assign(t1, binop(Iop_CmpEQ32, mkU32(0), mkU32(mov_cc)));
21537 assign(t2, IRExpr_ITE(mkexpr(t1),
21538 binop(Iop_And32,
21539 binop(Iop_Shr32, getFCSR(),
21540 mkU8(23)),
21541 mkU32(0x1)),
21542 binop(Iop_And32,
21543 binop(Iop_Shr32, getFCSR(),
21544 mkU8(24 + mov_cc)),
21545 mkU32(0x1))
21548 assign(t3, binop(Iop_CmpEQ32, mkU32(1), mkexpr(t2)));
21549 assign(t4, IRExpr_ITE(mkexpr(t3),
21550 mkexpr(t5), mkexpr(t6)));
21552 if (fp_mode64) {
21553 IRTemp f = newTemp(Ity_F64);
21554 IRTemp fd_hi = newTemp(Ity_I32);
21555 assign(f, getFReg(fd));
21556 assign(fd_hi, unop(Iop_64HIto32,
21557 unop(Iop_ReinterpF64asI64, mkexpr(f))));
21558 assign(t7, mkWidenFrom32(Ity_I64, unop(Iop_64to32,
21559 unop(Iop_ReinterpF64asI64, mkexpr(t4))),
21560 True));
21562 putFReg(fd, unop(Iop_ReinterpI64asF64, mkexpr(t7)));
21563 } else
21564 putFReg(fd, binop(Iop_F64toF32, get_IR_roundingmode(),
21565 mkexpr(t4)));
21567 break;
21569 default:
21570 return -1;
21572 } else if (tf == 0) { /* MOVF.fmt */
21573 UInt mov_cc = get_mov_cc(cins);
21575 switch (fmt) { /* MOVCF = 010001 */
21576 case 0x11: /* D */
21577 DIP("movf.d f%u, f%u, %u", fd, fs, mov_cc);
21578 t1 = newTemp(Ity_I1);
21579 t2 = newTemp(Ity_I32);
21580 t3 = newTemp(Ity_I1);
21581 t4 = newTemp(Ity_F64);
21583 assign(t1, binop(Iop_CmpEQ32, mkU32(0), mkU32(mov_cc)));
21584 assign(t2, IRExpr_ITE(mkexpr(t1),
21585 binop(Iop_And32,
21586 binop(Iop_Shr32, getFCSR(),
21587 mkU8(23)),
21588 mkU32(0x1)),
21589 binop(Iop_And32,
21590 binop(Iop_Shr32, getFCSR(),
21591 mkU8(24 + mov_cc)),
21592 mkU32(0x1))
21595 assign(t3, binop(Iop_CmpEQ32, mkU32(0), mkexpr(t2)));
21596 assign(t4, IRExpr_ITE(mkexpr(t3),
21597 getDReg(fs), getDReg(fd)));
21598 putDReg(fd, mkexpr(t4));
21599 break;
21601 case 0x10: /* S */
21602 DIP("movf.s f%u, f%u, %u", fd, fs, mov_cc);
21603 t1 = newTemp(Ity_I1);
21604 t2 = newTemp(Ity_I32);
21605 t3 = newTemp(Ity_I1);
21606 t4 = newTemp(Ity_F64);
21607 t5 = newTemp(Ity_F64);
21608 t6 = newTemp(Ity_F64);
21610 if (fp_mode64) {
21611 assign(t5, getFReg(fs));
21612 assign(t6, getFReg(fd));
21613 } else {
21614 assign(t5, unop(Iop_F32toF64, getFReg(fs)));
21615 assign(t6, unop(Iop_F32toF64, getFReg(fd)));
21618 assign(t1, binop(Iop_CmpEQ32, mkU32(0), mkU32(mov_cc)));
21619 assign(t2, IRExpr_ITE(mkexpr(t1),
21620 binop(Iop_And32,
21621 binop(Iop_Shr32, getFCSR(),
21622 mkU8(23)),
21623 mkU32(0x1)),
21624 binop(Iop_And32,
21625 binop(Iop_Shr32, getFCSR(),
21626 mkU8(24 + mov_cc)),
21627 mkU32(0x1))
21630 assign(t3, binop(Iop_CmpEQ32, mkU32(0), mkexpr(t2)));
21631 assign(t4, IRExpr_ITE(mkexpr(t3),
21632 mkexpr(t5), mkexpr(t6)));
21634 if (fp_mode64) {
21635 IRTemp f = newTemp(Ity_F64);
21636 IRTemp fd_hi = newTemp(Ity_I32);
21637 t7 = newTemp(Ity_I64);
21638 assign(f, getFReg(fd));
21639 assign(fd_hi, unop(Iop_64HIto32,
21640 unop(Iop_ReinterpF64asI64, mkexpr(f))));
21641 assign(t7, mkWidenFrom32(Ity_I64, unop(Iop_64to32,
21642 unop(Iop_ReinterpF64asI64, mkexpr(t4))),
21643 True));
21645 putFReg(fd, unop(Iop_ReinterpI64asF64, mkexpr(t7)));
21646 } else
21647 putFReg(fd, binop(Iop_F64toF32, get_IR_roundingmode(),
21648 mkexpr(t4)));
21650 break;
21652 default:
21653 return -1;
21657 break; /* MOVT.fmt */
21659 case 0x00: /* ADD.fmt */
21660 switch (fmt) {
21661 case 0x10: { /* S */
21662 DIP("add.s f%u, f%u, f%u", fd, fs, ft);
21663 calculateFCSR(fs, ft, ADDS, True, 2);
21664 IRExpr *rm = get_IR_roundingmode();
21665 putFReg(fd, mkWidenFromF32(tyF, triop(Iop_AddF32, rm,
21666 getLoFromF64(tyF, getFReg(fs)),
21667 getLoFromF64(tyF, getFReg(ft)))));
21668 break;
21671 case 0x11: { /* D */
21672 DIP("add.d f%u, f%u, f%u", fd, fs, ft);
21673 calculateFCSR(fs, ft, ADDD, False, 2);
21674 IRExpr *rm = get_IR_roundingmode();
21675 putDReg(fd, triop(Iop_AddF64, rm, getDReg(fs), getDReg(ft)));
21676 break;
21679 case 0x04: /* MTC1 (Move Word to Floating Point) */
21680 DIP("mtc1 r%u, f%u", rt, fs);
21682 if (fp_mode64) {
21683 t0 = newTemp(Ity_I32);
21684 t1 = newTemp(Ity_F32);
21685 assign(t0, mkNarrowTo32(ty, getIReg(rt)));
21686 assign(t1, unop(Iop_ReinterpI32asF32, mkexpr(t0)));
21688 putFReg(fs, mkWidenFromF32(tyF, mkexpr(t1)));
21689 } else
21690 putFReg(fs, unop(Iop_ReinterpI32asF32,
21691 mkNarrowTo32(ty, getIReg(rt))));
21693 break;
21695 case 0x05: /* Doubleword Move to Floating Point DMTC1; MIPS64 */
21696 DIP("dmtc1 r%u, f%u", rt, fs);
21697 vassert(mode64);
21698 putDReg(fs, unop(Iop_ReinterpI64asF64, getIReg(rt)));
21699 break;
21701 case 0x00: /* MFC1 */
21702 DIP("mfc1 r%u, f%u", rt, fs);
21704 if (fp_mode64) {
21705 t0 = newTemp(Ity_I64);
21706 t1 = newTemp(Ity_I32);
21707 assign(t0, unop(Iop_ReinterpF64asI64, getFReg(fs)));
21708 assign(t1, unop(Iop_64to32, mkexpr(t0)));
21709 putIReg(rt, mkWidenFrom32(ty, mkexpr(t1), True));
21710 } else
21711 putIReg(rt, mkWidenFrom32(ty,
21712 unop(Iop_ReinterpF32asI32, getFReg(fs)),
21713 True));
21715 break;
21717 case 0x01: /* Doubleword Move from Floating Point DMFC1;
21718 MIPS64 */
21719 DIP("dmfc1 r%u, f%u", rt, fs);
21720 putIReg(rt, unop(Iop_ReinterpF64asI64, getDReg(fs)));
21721 break;
21723 case 0x06: /* CTC1 */
21724 DIP("ctc1 r%u, f%u", rt, fs);
21725 t0 = newTemp(Ity_I32);
21726 t1 = newTemp(Ity_I32);
21727 t2 = newTemp(Ity_I32);
21728 t3 = newTemp(Ity_I32);
21729 t4 = newTemp(Ity_I32);
21730 t5 = newTemp(Ity_I32);
21731 t6 = newTemp(Ity_I32);
21732 assign(t0, mkNarrowTo32(ty, getIReg(rt)));
21734 if (fs == 25) { /* FCCR */
21735 assign(t1, binop(Iop_Shl32, binop(Iop_And32, mkexpr(t0),
21736 mkU32(0x000000FE)), mkU8(24)));
21737 assign(t2, binop(Iop_And32, mkexpr(t0),
21738 mkU32(0x01000000)));
21739 assign(t3, binop(Iop_Shl32, binop(Iop_And32, mkexpr(t0),
21740 mkU32(0x00000001)), mkU8(23)));
21741 assign(t4, binop(Iop_And32, mkexpr(t0),
21742 mkU32(0x007FFFFF)));
21743 putFCSR(binop(Iop_Or32, binop(Iop_Or32, mkexpr(t1),
21744 mkexpr(t2)), binop(Iop_Or32, mkexpr(t3),
21745 mkexpr(t4))));
21746 } else if (fs == 26) { /* FEXR */
21747 assign(t1, binop(Iop_And32, getFCSR(), mkU32(0xFFFC0000)));
21748 assign(t2, binop(Iop_And32, mkexpr(t0),
21749 mkU32(0x0003F000)));
21750 assign(t3, binop(Iop_And32, getFCSR(), mkU32(0x00000F80)));
21751 assign(t4, binop(Iop_And32, mkexpr(t0),
21752 mkU32(0x0000007C)));
21753 assign(t5, binop(Iop_And32, getFCSR(), mkU32(0x00000003)));
21754 putFCSR(binop(Iop_Or32, binop(Iop_Or32, binop(Iop_Or32,
21755 mkexpr(t1), mkexpr(t2)), binop(Iop_Or32,
21756 mkexpr(t3), mkexpr(t4))), mkexpr(t5)));
21757 } else if (fs == 28) {
21758 assign(t1, binop(Iop_And32, getFCSR(), mkU32(0xFE000000)));
21759 assign(t2, binop(Iop_Shl32, binop(Iop_And32, mkexpr(t0),
21760 mkU32(0x00000002)), mkU8(22)));
21761 assign(t3, binop(Iop_And32, getFCSR(), mkU32(0x00FFF000)));
21762 assign(t4, binop(Iop_And32, mkexpr(t0),
21763 mkU32(0x00000F80)));
21764 assign(t5, binop(Iop_And32, getFCSR(), mkU32(0x0000007C)));
21765 assign(t6, binop(Iop_And32, mkexpr(t0),
21766 mkU32(0x00000003)));
21767 putFCSR(binop(Iop_Or32, binop(Iop_Or32, binop(Iop_Or32,
21768 mkexpr(t1), mkexpr(t2)), binop(Iop_Or32,
21769 mkexpr(t3), mkexpr(t4))), binop(Iop_Or32,
21770 mkexpr(t5), mkexpr(t6))));
21771 } else if (fs == 31) {
21772 putFCSR(mkexpr(t0));
21775 break;
21777 case 0x02: /* CFC1 */
21778 DIP("cfc1 r%u, f%u", rt, fs);
21779 t0 = newTemp(Ity_I32);
21780 t1 = newTemp(Ity_I32);
21781 t2 = newTemp(Ity_I32);
21782 t3 = newTemp(Ity_I32);
21783 t4 = newTemp(Ity_I32);
21784 t5 = newTemp(Ity_I32);
21785 t6 = newTemp(Ity_I32);
21786 assign(t0, getFCSR());
21788 if (fs == 0) {
21789 putIReg(rt, mkWidenFrom32(ty,
21790 IRExpr_Get(offsetof(VexGuestMIPS32State,
21791 guest_FIR),
21792 Ity_I32),
21793 False));
21794 } else if (fs == 25) {
21795 assign(t1, mkU32(0x000000FF));
21796 assign(t2, binop(Iop_Shr32, binop(Iop_And32, mkexpr(t0),
21797 mkU32(0xFE000000)), mkU8(25)));
21798 assign(t3, binop(Iop_Shr32, binop(Iop_And32, mkexpr(t0),
21799 mkU32(0x00800000)), mkU8(23)));
21800 putIReg(rt, mkWidenFrom32(ty, binop(Iop_Or32,
21801 binop(Iop_Or32, mkexpr(t1), mkexpr(t2)),
21802 mkexpr(t3)), False));
21803 } else if (fs == 26) {
21804 assign(t1, mkU32(0xFFFFF07C));
21805 assign(t2, binop(Iop_And32, mkexpr(t0),
21806 mkU32(0x0003F000)));
21807 assign(t3, binop(Iop_And32, mkexpr(t0),
21808 mkU32(0x0000007C)));
21809 putIReg(rt, mkWidenFrom32(ty, binop(Iop_Or32,
21810 binop(Iop_Or32, mkexpr(t1), mkexpr(t2)),
21811 mkexpr(t3)), False));
21812 } else if (fs == 28) {
21813 assign(t1, mkU32(0x00000F87));
21814 assign(t2, binop(Iop_And32, mkexpr(t0),
21815 mkU32(0x00000F83)));
21816 assign(t3, binop(Iop_Shr32, binop(Iop_And32, mkexpr(t0),
21817 mkU32(0x01000000)), mkU8(22)));
21818 putIReg(rt, mkWidenFrom32(ty, binop(Iop_Or32,
21819 binop(Iop_Or32, mkexpr(t1), mkexpr(t2)),
21820 mkexpr(t3)), False));
21821 } else if (fs == 31) {
21822 putIReg(rt, mkWidenFrom32(ty, getFCSR(), False));
21825 break;
21827 default:
21828 return -1;
21831 break;
21833 case 0x21: /* CVT.D */
21834 switch (fmt) {
21835 case 0x10: /* S */
21836 DIP("cvt.d.s f%u, f%u", fd, fs);
21837 calculateFCSR(fs, 0, CVTDS, True, 1);
21839 if (fp_mode64) {
21840 t0 = newTemp(Ity_I64);
21841 t1 = newTemp(Ity_I32);
21842 t3 = newTemp(Ity_F32);
21843 t4 = newTemp(Ity_F32);
21844 /* get lo half of FPR */
21845 assign(t0, unop(Iop_ReinterpF64asI64, getFReg(fs)));
21847 assign(t1, unop(Iop_64to32, mkexpr(t0)));
21849 assign(t3, unop(Iop_ReinterpI32asF32, mkexpr(t1)));
21851 putFReg(fd, unop(Iop_F32toF64, mkexpr(t3)));
21852 } else
21853 putDReg(fd, unop(Iop_F32toF64, getFReg(fs)));
21855 break;
21857 case 0x14: /* W */
21858 DIP("cvt.d.w %u, %u", fd, fs);
21859 calculateFCSR(fs, 0, CVTDW, True, 1);
21861 if (fp_mode64) {
21862 t0 = newTemp(Ity_I64);
21863 t1 = newTemp(Ity_I32);
21864 t3 = newTemp(Ity_F32);
21865 t4 = newTemp(Ity_F32);
21866 /* get lo half of FPR */
21867 assign(t0, unop(Iop_ReinterpF64asI64, getFReg(fs)));
21869 assign(t1, unop(Iop_64to32, mkexpr(t0)));
21870 putDReg(fd, unop(Iop_I32StoF64, mkexpr(t1)));
21871 break;
21872 } else {
21873 t0 = newTemp(Ity_I32);
21874 assign(t0, unop(Iop_ReinterpF32asI32, getFReg(fs)));
21875 putDReg(fd, unop(Iop_I32StoF64, mkexpr(t0)));
21876 break;
21879 case 0x15: { /* L */
21880 if (fp_mode64) {
21881 DIP("cvt.d.l %u, %u", fd, fs);
21882 calculateFCSR(fs, 0, CVTDL, False, 1);
21883 t0 = newTemp(Ity_I64);
21884 assign(t0, unop(Iop_ReinterpF64asI64, getFReg(fs)));
21886 putFReg(fd, binop(Iop_I64StoF64,
21887 get_IR_roundingmode(), mkexpr(t0)));
21888 break;
21889 } else
21890 return -1;
21893 default:
21894 return -1;
21897 break; /* CVT.D */
21899 case 0x20: /* CVT.s */
21900 switch (fmt) {
21901 case 0x14: /* W */
21902 DIP("cvt.s.w %u, %u", fd, fs);
21903 calculateFCSR(fs, 0, CVTSW, True, 1);
21905 if (fp_mode64) {
21906 t0 = newTemp(Ity_I64);
21907 t1 = newTemp(Ity_I32);
21908 t3 = newTemp(Ity_F32);
21909 t4 = newTemp(Ity_F32);
21910 /* get lo half of FPR */
21911 assign(t0, unop(Iop_ReinterpF64asI64, getFReg(fs)));
21913 assign(t1, unop(Iop_64to32, mkexpr(t0)));
21914 putFReg(fd, mkWidenFromF32(tyF, binop(Iop_I32StoF32,
21915 get_IR_roundingmode(), mkexpr(t1))));
21916 } else {
21917 t0 = newTemp(Ity_I32);
21918 assign(t0, unop(Iop_ReinterpF32asI32, getFReg(fs)));
21919 putFReg(fd, binop(Iop_I32StoF32, get_IR_roundingmode(),
21920 mkexpr(t0)));
21923 break;
21925 case 0x11: /* D */
21926 DIP("cvt.s.d %u, %u", fd, fs);
21927 calculateFCSR(fs, 0, CVTSD, False, 1);
21928 t0 = newTemp(Ity_F32);
21929 assign(t0, binop(Iop_F64toF32, get_IR_roundingmode(),
21930 getDReg(fs)));
21931 putFReg(fd, mkWidenFromF32(tyF, mkexpr(t0)));
21932 break;
21934 case 0x15: /* L */
21935 DIP("cvt.s.l %u, %u", fd, fs);
21937 if (fp_mode64) {
21938 calculateFCSR(fs, 0, CVTSL, False, 1);
21939 t0 = newTemp(Ity_I64);
21940 assign(t0, unop(Iop_ReinterpF64asI64, getFReg(fs)));
21942 putFReg(fd, mkWidenFromF32(tyF, binop(Iop_I64StoF32,
21943 get_IR_roundingmode(), mkexpr(t0))));
21944 } else {
21945 ILLEGAL_INSTRUCTON
21948 break;
21950 default:
21951 return -1;
21954 break; /* CVT.s */
21956 case 0x24: /* CVT.w */
21957 switch (fmt) {
21958 case 0x10: /* S */
21959 DIP("cvt.w.s %u, %u", fd, fs);
21960 calculateFCSR(fs, 0, CVTWS, True, 1);
21961 putFReg(fd,
21962 mkWidenFromF32(tyF,
21963 unop(Iop_ReinterpI32asF32,
21964 binop(Iop_F32toI32S,
21965 get_IR_roundingmode(),
21966 getLoFromF64(tyF,
21967 getFReg(fs))))));
21968 break;
21970 case 0x11: /* D */
21971 DIP("cvt.w.d %u, %u", fd, fs);
21972 calculateFCSR(fs, 0, CVTWD, False, 1);
21973 t0 = newTemp(Ity_I32);
21974 t1 = newTemp(Ity_F32);
21975 assign(t0, binop(Iop_F64toI32S, get_IR_roundingmode(),
21976 getDReg(fs)));
21977 assign(t1, unop(Iop_ReinterpI32asF32, mkexpr(t0)));
21978 putFReg(fd, mkWidenFromF32(tyF, mkexpr(t1)));
21979 break;
21981 default:
21982 return -1;
21986 break;
21988 case 0x25: /* CVT.l */
21989 switch (fmt) {
21990 case 0x10: /* S */
21991 DIP("cvt.l.s %u, %u", fd, fs);
21993 if (fp_mode64) {
21994 calculateFCSR(fs, 0, CVTLS, True, 1);
21995 t0 = newTemp(Ity_I64);
21997 assign(t0, binop(Iop_F32toI64S, get_IR_roundingmode(),
21998 getLoFromF64(tyF, getFReg(fs))));
22000 putDReg(fd, unop(Iop_ReinterpI64asF64, mkexpr(t0)));
22001 } else {
22002 ILLEGAL_INSTRUCTON
22005 break;
22007 case 0x11: { /* D */
22008 DIP("cvt.l.d %u, %u", fd, fs);
22010 if (fp_mode64) {
22011 calculateFCSR(fs, 0, CVTLD, False, 1);
22012 putDReg(fd, unop(Iop_ReinterpI64asF64,
22013 binop(Iop_F64toI64S,
22014 get_IR_roundingmode(),
22015 getDReg(fs))));
22016 } else {
22017 ILLEGAL_INSTRUCTON
22020 break;
22023 default:
22024 return -1;
22027 break;
22029 case 0x0B: /* FLOOR.L.fmt */
22030 switch (fmt) {
22031 case 0x10: /* S */
22032 DIP("floor.l.s %u, %u", fd, fs);
22034 if (fp_mode64) {
22035 calculateFCSR(fs, 0, FLOORLS, True, 1);
22036 t0 = newTemp(Ity_I64);
22038 assign(t0, binop(Iop_F32toI64S, mkU32(0x1),
22039 getLoFromF64(tyF, getFReg(fs))));
22041 putDReg(fd, unop(Iop_ReinterpI64asF64, mkexpr(t0)));
22042 } else {
22043 ILLEGAL_INSTRUCTON
22046 break;
22048 case 0x11: /* D */
22049 DIP("floor.l.d %u, %u", fd, fs);
22051 if (fp_mode64) {
22052 calculateFCSR(fs, 0, FLOORLD, False, 1);
22053 putDReg(fd, unop(Iop_ReinterpI64asF64,
22054 binop(Iop_F64toI64S,
22055 mkU32(0x01),
22056 getDReg(fs))));
22057 } else {
22058 ILLEGAL_INSTRUCTON
22061 break;
22063 default:
22064 return -1;
22067 break;
22069 case 0x0C: /* ROUND.W.fmt */
22070 switch (fmt) {
22071 case 0x10: /* S */
22072 DIP("round.w.s f%u, f%u", fd, fs);
22073 calculateFCSR(fs, 0, ROUNDWS, True, 1);
22074 putFReg(fd,
22075 mkWidenFromF32(tyF,
22076 unop(Iop_ReinterpI32asF32,
22077 binop(Iop_F32toI32S,
22078 mkU32(0x0),
22079 getLoFromF64(tyF,
22080 getFReg(fs))))));
22081 break;
22083 case 0x11: /* D */
22084 DIP("round.w.d f%u, f%u", fd, fs);
22085 calculateFCSR(fs, 0, ROUNDWD, False, 1);
22087 if (fp_mode64) {
22088 t0 = newTemp(Ity_I32);
22089 assign(t0, binop(Iop_F64toI32S, mkU32(0x0),
22090 getDReg(fs)));
22091 putFReg(fd, mkWidenFromF32(tyF,
22092 unop(Iop_ReinterpI32asF32, mkexpr(t0))));
22093 } else {
22094 t0 = newTemp(Ity_I32);
22096 assign(t0, binop(Iop_F64toI32S, mkU32(0x0),
22097 getDReg(fs)));
22099 putFReg(fd, unop(Iop_ReinterpI32asF32, mkexpr(t0)));
22102 break;
22104 default:
22105 return -1;
22109 break; /* ROUND.W.fmt */
22111 case 0x0F: /* FLOOR.W.fmt */
22112 switch (fmt) {
22113 case 0x10: /* S */
22114 DIP("floor.w.s f%u, f%u", fd, fs);
22115 calculateFCSR(fs, 0, FLOORWS, True, 1);
22116 putFReg(fd,
22117 mkWidenFromF32(tyF,
22118 unop(Iop_ReinterpI32asF32,
22119 binop(Iop_F32toI32S,
22120 mkU32(0x1),
22121 getLoFromF64(tyF,
22122 getFReg(fs))))));
22123 break;
22125 case 0x11: /* D */
22126 DIP("floor.w.d f%u, f%u", fd, fs);
22127 calculateFCSR(fs, 0, FLOORWD, False, 1);
22129 if (fp_mode64) {
22130 t0 = newTemp(Ity_I32);
22131 assign(t0, binop(Iop_F64toI32S, mkU32(0x1),
22132 getDReg(fs)));
22133 putFReg(fd, mkWidenFromF32(tyF,
22134 unop(Iop_ReinterpI32asF32, mkexpr(t0))));
22135 break;
22136 } else {
22137 t0 = newTemp(Ity_I32);
22139 assign(t0, binop(Iop_F64toI32S, mkU32(0x1),
22140 getDReg(fs)));
22142 putFReg(fd, unop(Iop_ReinterpI32asF32, mkexpr(t0)));
22143 break;
22146 default:
22147 return -1;
22151 break; /* FLOOR.W.fmt */
22153 case 0x0D: /* TRUNC.W */
22154 switch (fmt) {
22155 case 0x10: /* S */
22156 DIP("trunc.w.s %u, %u", fd, fs);
22157 calculateFCSR(fs, 0, TRUNCWS, True, 1);
22158 putFReg(fd,
22159 mkWidenFromF32(tyF,
22160 unop(Iop_ReinterpI32asF32,
22161 binop(Iop_F32toI32S,
22162 mkU32(0x3),
22163 getLoFromF64(tyF,
22164 getFReg(fs))))));
22165 break;
22167 case 0x11: /* D */
22168 DIP("trunc.w.d %u, %u", fd, fs);
22169 calculateFCSR(fs, 0, TRUNCWD, False, 1);
22171 if (fp_mode64) {
22172 t0 = newTemp(Ity_I32);
22174 assign(t0, binop(Iop_F64toI32S, mkU32(0x3),
22175 getFReg(fs)));
22177 putFReg(fd, mkWidenFromF32(tyF,
22178 unop(Iop_ReinterpI32asF32, mkexpr(t0))));
22179 } else {
22180 t0 = newTemp(Ity_I32);
22182 assign(t0, binop(Iop_F64toI32S, mkU32(0x3),
22183 getDReg(fs)));
22185 putFReg(fd, unop(Iop_ReinterpI32asF32, mkexpr(t0)));
22188 break;
22190 default:
22191 return -1;
22195 break;
22197 case 0x0E: /* CEIL.W.fmt */
22198 switch (fmt) {
22199 case 0x10: /* S */
22200 DIP("ceil.w.s %u, %u", fd, fs);
22201 calculateFCSR(fs, 0, CEILWS, True, 1);
22202 putFReg(fd,
22203 mkWidenFromF32(tyF,
22204 unop(Iop_ReinterpI32asF32,
22205 binop(Iop_F32toI32S,
22206 mkU32(0x2),
22207 getLoFromF64(tyF,
22208 getFReg(fs))))));
22209 break;
22211 case 0x11: /* D */
22212 DIP("ceil.w.d %u, %u", fd, fs);
22213 calculateFCSR(fs, 0, CEILWD, False, 1);
22215 if (!fp_mode64) {
22216 t0 = newTemp(Ity_I32);
22217 assign(t0, binop(Iop_F64toI32S, mkU32(0x2),
22218 getDReg(fs)));
22219 putFReg(fd, unop(Iop_ReinterpI32asF32, mkexpr(t0)));
22220 } else {
22221 t0 = newTemp(Ity_I32);
22222 assign(t0, binop(Iop_F64toI32S, mkU32(0x2),
22223 getDReg(fs)));
22224 putFReg(fd, mkWidenFromF32(tyF,
22225 unop(Iop_ReinterpI32asF32, mkexpr(t0))));
22228 break;
22230 default:
22231 return -1;
22235 break;
22237 case 0x0A: /* CEIL.L.fmt */
22238 switch (fmt) {
22239 case 0x10: /* S */
22240 DIP("ceil.l.s %u, %u", fd, fs);
22242 if (fp_mode64) {
22243 calculateFCSR(fs, 0, CEILLS, True, 1);
22244 t0 = newTemp(Ity_I64);
22246 assign(t0, binop(Iop_F32toI64S, mkU32(0x2),
22247 getLoFromF64(tyF, getFReg(fs))));
22249 putFReg(fd, unop(Iop_ReinterpI64asF64, mkexpr(t0)));
22250 } else {
22251 ILLEGAL_INSTRUCTON
22254 break;
22256 case 0x11: /* D */
22257 DIP("ceil.l.d %u, %u", fd, fs);
22259 if (fp_mode64) {
22260 calculateFCSR(fs, 0, CEILLD, False, 1);
22261 putDReg(fd, unop(Iop_ReinterpI64asF64,
22262 binop(Iop_F64toI64S,
22263 mkU32(0x2),
22264 getDReg(fs))));
22265 } else {
22266 ILLEGAL_INSTRUCTON
22269 break;
22271 default:
22272 return -1;
22276 break;
22278 case 0x16: /* RSQRT.fmt */
22279 switch (fmt) {
22280 case 0x10: { /* S */
22281 DIP("rsqrt.s %u, %u", fd, fs);
22282 IRExpr *rm = get_IR_roundingmode();
22283 putFReg(fd, mkWidenFromF32(tyF, triop(Iop_DivF32, rm,
22284 unop(Iop_ReinterpI32asF32, mkU32(ONE_SINGLE)),
22285 binop(Iop_SqrtF32, rm, getLoFromF64(tyF,
22286 getFReg(fs))))));
22287 break;
22290 case 0x11: { /* D */
22291 DIP("rsqrt.d %u, %u", fd, fs);
22292 IRExpr *rm = get_IR_roundingmode();
22293 putDReg(fd, triop(Iop_DivF64, rm,
22294 unop(Iop_ReinterpI64asF64,
22295 mkU64(ONE_DOUBLE)),
22296 binop(Iop_SqrtF64, rm, getDReg(fs))));
22297 break;
22300 default:
22301 return -1;
22305 break;
22307 case 0x18: /* MADDF.fmt */
22308 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
22309 switch (fmt) {
22310 case 0x11: { /* D */
22311 DIP("maddf.d f%u, f%u, f%u", fd, fs, ft);
22312 IRExpr *rm = get_IR_roundingmode();
22313 putDReg(fd, qop(Iop_MAddF64, rm, getDReg(fs), getDReg(ft),
22314 getDReg(fd)));
22315 break;
22318 case 0x10: { /* S */
22319 DIP("maddf.s f%u, f%u, f%u", fd, fs, ft);
22320 IRExpr *rm = get_IR_roundingmode();
22321 t1 = newTemp(Ity_F32);
22322 assign(t1, qop(Iop_MAddF32, rm,
22323 getLoFromF64(tyF, getFReg(fs)),
22324 getLoFromF64(tyF, getFReg(ft)),
22325 getLoFromF64(tyF, getFReg(fd))));
22326 putFReg(fd, mkWidenFromF32(tyF, mkexpr(t1)));
22327 break;
22330 default:
22331 return -1;
22333 } else {
22334 ILLEGAL_INSTRUCTON;
22337 break;
22339 case 0x19: /* MSUBF.fmt */
22340 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
22341 switch (fmt) {
22342 case 0x11: { /* D */
22343 DIP("msubf.d f%u, f%u, f%u", fd, fs, ft);
22344 IRExpr *rm = get_IR_roundingmode();
22345 putDReg(fd, qop(Iop_MSubF64, rm, getDReg(fs),
22346 getDReg(ft), getDReg(fd)));
22347 break;
22350 case 0x10: { /* S */
22351 DIP("msubf.s f%u, f%u, f%u", fd, fs, ft);
22352 IRExpr *rm = get_IR_roundingmode();
22353 t1 = newTemp(Ity_F32);
22354 assign(t1, qop(Iop_MSubF32, rm,
22355 getLoFromF64(tyF, getFReg(fs)),
22356 getLoFromF64(tyF, getFReg(ft)),
22357 getLoFromF64(tyF, getFReg(fd))));
22358 putFReg(fd, mkWidenFromF32(tyF, mkexpr(t1)));
22359 break;
22362 default:
22363 return -1;
22365 } else {
22366 ILLEGAL_INSTRUCTON;
22369 break;
22371 case 0x1E: /* MAX.fmt */
22372 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
22373 switch (fmt) {
22374 case 0x11: { /* D */
22375 DIP("max.d f%u, f%u, f%u", fd, fs, ft);
22376 calculateFCSR(fs, ft, MAXD, False, 2);
22377 putDReg(fd, binop(Iop_MaxNumF64, getDReg(fs), getDReg(ft)));
22378 break;
22381 case 0x10: { /* S */
22382 DIP("max.s f%u, f%u, f%u", fd, fs, ft);
22383 calculateFCSR(fs, ft, MAXS, True, 2);
22384 putFReg(fd, mkWidenFromF32(tyF, binop(Iop_MaxNumF32,
22385 getLoFromF64(Ity_F64,
22386 getFReg(fs)),
22387 getLoFromF64(Ity_F64,
22388 getFReg(ft)))));
22389 break;
22392 default:
22393 return -1;
22395 } else {
22396 ILLEGAL_INSTRUCTON;
22399 break;
22401 case 0x1C: /* MIN.fmt */
22402 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
22403 switch (fmt) {
22404 case 0x11: { /* D */
22405 DIP("min.d f%u, f%u, f%u", fd, fs, ft);
22406 calculateFCSR(fs, ft, MIND, False, 2);
22407 putDReg(fd, binop(Iop_MinNumF64, getDReg(fs), getDReg(ft)));
22408 break;
22411 case 0x10: { /* S */
22412 DIP("min.s f%u, f%u, f%u", fd, fs, ft);
22413 calculateFCSR(fs, ft, MINS, True, 2);
22414 putFReg(fd, mkWidenFromF32(tyF, binop(Iop_MinNumF32,
22415 getLoFromF64(Ity_F64,
22416 getFReg(fs)),
22417 getLoFromF64(Ity_F64,
22418 getFReg(ft)))));
22419 break;
22422 default:
22423 return -1;
22425 } else {
22426 ILLEGAL_INSTRUCTON;
22429 break;
22431 case 0x1F: /* MAXA.fmt */
22432 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
22433 switch (fmt) {
22434 case 0x11: { /* D */
22435 DIP("maxa.d f%u, f%u, f%u", fd, fs, ft);
22436 calculateFCSR(fs, ft, MAXAD, False, 2);
22437 t1 = newTemp(Ity_F64);
22438 t2 = newTemp(Ity_F64);
22439 t3 = newTemp(Ity_F64);
22440 t4 = newTemp(Ity_I1);
22441 assign(t1, unop(Iop_AbsF64, getFReg(fs)));
22442 assign(t2, unop(Iop_AbsF64, getFReg(ft)));
22443 assign(t3, binop(Iop_MaxNumF64, mkexpr(t1), mkexpr(t2)));
22444 assign(t4, binop(Iop_CmpEQ32,
22445 binop(Iop_CmpF64, mkexpr(t3), mkexpr(t1)),
22446 mkU32(0x40)));
22447 putFReg(fd, IRExpr_ITE(mkexpr(t4),
22448 getFReg(fs), getFReg(ft)));
22449 break;
22452 case 0x10: { /* S */
22453 DIP("maxa.s f%u, f%u, f%u", fd, fs, ft);
22454 calculateFCSR(fs, ft, MAXAS, True, 2);
22455 t1 = newTemp(Ity_F32);
22456 t2 = newTemp(Ity_F32);
22457 t3 = newTemp(Ity_F32);
22458 t4 = newTemp(Ity_I1);
22459 assign(t1, unop(Iop_AbsF32, getLoFromF64(Ity_F64,
22460 getFReg(fs))));
22461 assign(t2, unop(Iop_AbsF32, getLoFromF64(Ity_F64,
22462 getFReg(ft))));
22463 assign(t3, binop(Iop_MaxNumF32, mkexpr(t1), mkexpr(t2)));
22464 assign(t4, binop(Iop_CmpEQ32,
22465 binop(Iop_CmpF32, mkexpr(t3), mkexpr(t1)),
22466 mkU32(0x40)));
22467 putFReg(fd, IRExpr_ITE(mkexpr(t4),
22468 getFReg(fs), getFReg(ft)));
22469 break;
22472 default:
22473 return -1;
22476 } else {
22477 ILLEGAL_INSTRUCTON;
22480 break;
22482 case 0x1D: /* MINA.fmt */
22483 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
22484 switch (fmt) {
22485 case 0x11: { /* D */
22486 DIP("mina.d f%u, f%u, f%u", fd, fs, ft);
22487 calculateFCSR(fs, ft, MINAD, False, 2);
22488 t1 = newTemp(Ity_F64);
22489 t2 = newTemp(Ity_F64);
22490 t3 = newTemp(Ity_F64);
22491 t4 = newTemp(Ity_I1);
22492 assign(t1, unop(Iop_AbsF64, getFReg(fs)));
22493 assign(t2, unop(Iop_AbsF64, getFReg(ft)));
22494 assign(t3, binop(Iop_MinNumF64, mkexpr(t1), mkexpr(t2)));
22495 assign(t4, binop(Iop_CmpEQ32,
22496 binop(Iop_CmpF64, mkexpr(t3), mkexpr(t1)),
22497 mkU32(0x40)));
22498 putFReg(fd, IRExpr_ITE(mkexpr(t4),
22499 getFReg(fs), getFReg(ft)));
22500 break;
22503 case 0x10: { /* S */
22504 DIP("mina.s f%u, f%u, f%u", fd, fs, ft);
22505 calculateFCSR(fs, ft, MINAS, True, 2);
22506 t1 = newTemp(Ity_F32);
22507 t2 = newTemp(Ity_F32);
22508 t3 = newTemp(Ity_F32);
22509 t4 = newTemp(Ity_I1);
22510 assign(t1, unop(Iop_AbsF32, getLoFromF64(Ity_F64,
22511 getFReg(fs))));
22512 assign(t2, unop(Iop_AbsF32, getLoFromF64(Ity_F64,
22513 getFReg(ft))));
22514 assign(t3, binop(Iop_MinNumF32, mkexpr(t1), mkexpr(t2)));
22515 assign(t4, binop(Iop_CmpEQ32,
22516 binop(Iop_CmpF32, mkexpr(t3), mkexpr(t1)),
22517 mkU32(0x40)));
22518 putFReg(fd, IRExpr_ITE(mkexpr(t4),
22519 getFReg(fs), getFReg(ft)));
22520 break;
22523 default:
22524 return -1;
22528 break;
22530 case 0x1A: /* RINT.fmt */
22531 if (ft == 0) {
22532 switch (fmt) {
22533 case 0x11: { /* D */
22534 DIP("rint.d f%u, f%u", fd, fs);
22535 calculateFCSR(fs, 0, RINTS, True, 1);
22536 IRExpr *rm = get_IR_roundingmode();
22537 putDReg(fd, binop(Iop_RoundF64toInt, rm, getDReg(fs)));
22538 break;
22541 case 0x10: { /* S */
22542 DIP("rint.s f%u, f%u", fd, fs);
22543 calculateFCSR(fs, 0, RINTD, True, 1);
22544 IRExpr *rm = get_IR_roundingmode();
22545 putFReg(fd,
22546 mkWidenFromF32(tyF,
22547 binop(Iop_RoundF32toInt, rm,
22548 getLoFromF64(tyF,
22549 getFReg(fs)))));
22550 break;
22553 default:
22554 return -1;
22559 break;
22561 case 0x10: /* SEL.fmt */
22562 switch (fmt) {
22563 case 0x11: { /* D */
22564 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
22565 DIP("sel.d f%u, f%u, f%u", fd, fs, ft);
22566 t1 = newTemp(Ity_I1);
22568 if (mode64) {
22569 assign(t1, binop(Iop_CmpNE64,
22570 binop(Iop_And64,
22571 unop(Iop_ReinterpF64asI64,
22572 getDReg(fd)),
22573 mkU64(1)),
22574 mkU64(0)));
22575 } else {
22576 assign(t1, binop(Iop_CmpNE32,
22577 binop(Iop_And32,
22578 unop(Iop_64to32,
22579 unop(Iop_ReinterpF64asI64,
22580 getDReg(fd))),
22581 mkU32(1)),
22582 mkU32(0)));
22585 putDReg(fd, IRExpr_ITE(mkexpr(t1),
22586 getDReg(ft), getDReg(fs)));
22587 break;
22588 } else {
22589 ILLEGAL_INSTRUCTON;
22590 break;
22595 case 0x10: { /* S */
22596 DIP("sel.s f%u, f%u, f%u", fd, fs, ft);
22597 t1 = newTemp(Ity_I1);
22598 assign(t1, binop(Iop_CmpNE32,
22599 binop(Iop_And32,
22600 unop(Iop_ReinterpF32asI32,
22601 getLoFromF64(tyF, getFReg(fd))),
22602 mkU32(1)),
22603 mkU32(0)));
22604 putFReg(fd, IRExpr_ITE( mkexpr(t1),
22605 getFReg(ft), getFReg(fs)));
22606 break;
22609 default:
22610 return -1;
22613 break;
22615 case 0x14: /* SELEQZ.fmt */
22616 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
22617 switch (fmt) { /* SELEQZ.df */
22618 case 0x11: { /* D */
22619 DIP("seleqz.d f%u, f%u, f%u", fd, fs, ft);
22620 t1 = newTemp(Ity_I1);
22622 if (mode64) {
22623 assign(t1, binop(Iop_CmpNE64,
22624 binop(Iop_And64,
22625 unop(Iop_ReinterpF64asI64,
22626 getDReg(ft)),
22627 mkU64(1)),
22628 mkU64(0)));
22629 } else {
22630 assign(t1, binop(Iop_CmpNE32,
22631 binop(Iop_And32,
22632 unop(Iop_64to32,
22633 unop(Iop_ReinterpF64asI64,
22634 getDReg(ft))),
22635 mkU32(1)),
22636 mkU32(0)));
22639 putDReg(fd, IRExpr_ITE( mkexpr(t1),
22640 binop(Iop_I64StoF64,
22641 get_IR_roundingmode(), mkU64(0)),
22642 getDReg(fs)));
22643 break;
22646 case 0x10: { /* S */
22647 DIP("seleqz.s f%u, f%u, f%u", fd, fs, ft);
22648 t1 = newTemp(Ity_I1);
22649 assign(t1, binop(Iop_CmpNE32,
22650 binop(Iop_And32,
22651 unop(Iop_ReinterpF32asI32,
22652 getLoFromF64(tyF, getFReg(ft))),
22653 mkU32(1)),
22654 mkU32(0)));
22655 putFReg(fd, IRExpr_ITE(mkexpr(t1),
22656 mkWidenFromF32(tyF,
22657 binop(Iop_I32StoF32,
22658 get_IR_roundingmode(),
22659 mkU32(0))),
22660 getFReg(fs)));
22661 break;
22664 default:
22665 return -1;
22667 } else {
22668 ILLEGAL_INSTRUCTON;
22671 break;
22673 case 0x17: /* SELNEZ.fmt */
22674 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
22675 switch (fmt) {
22676 case 0x11: { /* D */
22677 DIP("selnez.d f%u, f%u, f%u", fd, fs, ft);
22678 t1 = newTemp(Ity_I1);
22680 if (mode64) {
22681 assign(t1, binop(Iop_CmpNE64,
22682 binop(Iop_And64,
22683 unop(Iop_ReinterpF64asI64,
22684 getDReg(ft)),
22685 mkU64(1)),
22686 mkU64(0)));
22687 } else {
22688 assign(t1, binop(Iop_CmpNE32,
22689 binop(Iop_And32,
22690 unop(Iop_64to32,
22691 unop(Iop_ReinterpF64asI64,
22692 getDReg(ft))),
22693 mkU32(1)),
22694 mkU32(0)));
22697 putDReg(fd, IRExpr_ITE( mkexpr(t1),
22698 getDReg(fs),
22699 binop(Iop_I64StoF64,
22700 get_IR_roundingmode(),
22701 mkU64(0))));
22702 break;
22705 case 0x10: { /* S */
22706 DIP("selnez.s f%u, f%u, f%u", fd, fs, ft);
22707 t1 = newTemp(Ity_I1);
22708 assign(t1, binop(Iop_CmpNE32,
22709 binop(Iop_And32,
22710 unop(Iop_ReinterpF32asI32,
22711 getLoFromF64(tyF, getFReg(ft))),
22712 mkU32(1)),
22713 mkU32(0)));
22714 putFReg(fd, IRExpr_ITE(mkexpr(t1),
22715 getFReg(fs),
22716 mkWidenFromF32(tyF,
22717 binop(Iop_I32StoF32,
22718 get_IR_roundingmode(),
22719 mkU32(0)))));
22720 break;
22723 default:
22724 return -1;
22728 } else {
22729 ILLEGAL_INSTRUCTON;
22732 break;
22734 case 0x1B: /* CLASS.fmt */
22735 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
22736 t0 = newTemp(Ity_I1); // exp zero
22737 t1 = newTemp(Ity_I1); // exp max
22738 t2 = newTemp(Ity_I1); // sign
22739 t3 = newTemp(Ity_I1); // first
22740 t4 = newTemp(Ity_I1); // val not zero
22741 t5 = newTemp(Ity_I32);
22743 switch (fmt) {
22744 case 0x11: { /* D */
22745 DIP("class.d f%u, f%u", fd, fs);
22746 assign(t0, binop(Iop_CmpEQ32,
22747 binop(Iop_And32,
22748 unop(Iop_64HIto32,
22749 unop(Iop_ReinterpF64asI64,
22750 getDReg(fs))),
22751 mkU32(0x7ff00000)),
22752 mkU32(0)));
22753 assign(t1, binop(Iop_CmpEQ32,
22754 binop(Iop_And32,
22755 unop(Iop_64HIto32,
22756 unop(Iop_ReinterpF64asI64,
22757 getDReg(fs))),
22758 mkU32(0x7ff00000)),
22759 mkU32(0x7ff00000)));
22760 assign(t2, binop(Iop_CmpEQ32,
22761 binop(Iop_And32,
22762 unop(Iop_64HIto32,
22763 unop(Iop_ReinterpF64asI64,
22764 getDReg(fs))),
22765 mkU32(0x80000000)),
22766 mkU32(0x80000000)));
22767 assign(t3, binop(Iop_CmpEQ32,
22768 binop(Iop_And32,
22769 unop(Iop_64HIto32,
22770 unop(Iop_ReinterpF64asI64,
22771 getDReg(fs))),
22772 mkU32(0x00080000)),
22773 mkU32(0x00080000)));
22775 if (mode64) assign(t4, binop(Iop_CmpNE64,
22776 binop(Iop_And64,
22777 unop(Iop_ReinterpF64asI64,
22778 getDReg(fs)),
22779 mkU64(0x000fffffffffffffULL)),
22780 mkU64(0)));
22781 else assign(t4, binop(Iop_CmpNE32,
22782 binop(Iop_Or32,
22783 binop(Iop_And32,
22784 unop(Iop_64HIto32,
22785 unop(Iop_ReinterpF64asI64,
22786 getDReg(fs))),
22787 mkU32(0x000fffff)),
22788 unop(Iop_64to32,
22789 unop(Iop_ReinterpF64asI64,
22790 getDReg(fs)))),
22791 mkU32(0)));
22793 assign(t5, binop(Iop_Shl32,
22794 IRExpr_ITE(mkexpr(t1),
22795 IRExpr_ITE(mkexpr(t4),
22796 mkU32(0), mkU32(1)),
22797 IRExpr_ITE(mkexpr(t0),
22798 IRExpr_ITE(mkexpr(t4),
22799 mkU32(0x4),
22800 mkU32(0x8)),
22801 mkU32(2))),
22802 IRExpr_ITE(mkexpr(t2), mkU8(2), mkU8(6))));
22803 putDReg(fd, unop(Iop_ReinterpI64asF64,
22804 unop(Iop_32Uto64,
22805 IRExpr_ITE(binop(Iop_CmpNE32,
22806 mkexpr(t5), mkU32(0)),
22807 mkexpr(t5),
22808 IRExpr_ITE(mkexpr(t3),
22809 mkU32(2),
22810 mkU32(1))))));
22811 break;
22814 case 0x10: { /* S */
22815 DIP("class.s f%u, f%u", fd, fs);
22816 assign(t0, binop(Iop_CmpEQ32,
22817 binop(Iop_And32,
22818 unop(Iop_ReinterpF32asI32,
22819 getLoFromF64(tyF, getFReg(fs))),
22820 mkU32(0x7f800000)),
22821 mkU32(0)));
22822 assign(t1, binop(Iop_CmpEQ32,
22823 binop(Iop_And32,
22824 unop(Iop_ReinterpF32asI32,
22825 getLoFromF64(tyF, getFReg(fs))),
22826 mkU32(0x7f800000)),
22827 mkU32(0x7f800000)));
22828 assign(t2, binop(Iop_CmpEQ32,
22829 binop(Iop_And32,
22830 unop(Iop_ReinterpF32asI32,
22831 getLoFromF64(tyF, getFReg(fs))),
22832 mkU32(0x80000000)),
22833 mkU32(0x80000000)));
22834 assign(t3, binop(Iop_CmpEQ32,
22835 binop(Iop_And32,
22836 unop(Iop_ReinterpF32asI32,
22837 getLoFromF64(tyF, getFReg(fs))),
22838 mkU32(0x00400000)),
22839 mkU32(0x00400000)));
22840 assign(t4, binop(Iop_CmpNE32,
22841 binop(Iop_And32,
22842 unop(Iop_ReinterpF32asI32,
22843 getLoFromF64(tyF, getFReg(fs))),
22844 mkU32(0x007fffff)),
22845 mkU32(0)));
22846 assign(t5, binop(Iop_Shl32,
22847 IRExpr_ITE(mkexpr(t1),
22848 IRExpr_ITE(mkexpr(t4),
22849 mkU32(0), mkU32(1)),
22850 IRExpr_ITE(mkexpr(t0),
22851 IRExpr_ITE(mkexpr(t4),
22852 mkU32(0x4),
22853 mkU32(0x8)), //zero or subnorm
22854 mkU32(2))),
22855 IRExpr_ITE(mkexpr(t2), mkU8(2), mkU8(6))));
22856 putDReg(fd, unop(Iop_ReinterpI64asF64,
22857 unop(Iop_32Uto64,
22858 IRExpr_ITE(binop(Iop_CmpNE32,
22859 mkexpr(t5), mkU32(0)),
22860 mkexpr(t5),
22861 IRExpr_ITE(mkexpr(t3),
22862 mkU32(2),
22863 mkU32(1))))));
22864 break;
22867 default:
22868 return -1;
22870 } else {
22871 ILLEGAL_INSTRUCTON;
22874 break;
22876 default:
22877 if (dis_instr_CCondFmt(cins))
22878 break;
22880 return -1;
22886 break; /* COP1 */
22888 case 0x03: /* COP1X */
22889 switch (function) {
22890 case 0x0: { /* LWXC1 */
22891 /* Load Word Indexed to Floating Point - LWXC1 (MIPS32r2) */
22892 DIP("lwxc1 f%u, r%u(r%u)", fd, rt, rs);
22893 t2 = newTemp(ty);
22894 assign(t2, binop(mode64 ? Iop_Add64 : Iop_Add32, getIReg(rs),
22895 getIReg(rt)));
22897 if (fp_mode64) {
22898 t0 = newTemp(Ity_I64);
22899 t1 = newTemp(Ity_I32);
22900 t3 = newTemp(Ity_F32);
22901 t4 = newTemp(Ity_I64);
22902 assign(t3, load(Ity_F32, mkexpr(t2)));
22904 assign(t4, mkWidenFrom32(Ity_I64, unop(Iop_ReinterpF32asI32,
22905 mkexpr(t3)), True));
22907 putFReg(fd, unop(Iop_ReinterpI64asF64, mkexpr(t4)));
22908 } else {
22909 putFReg(fd, load(Ity_F32, mkexpr(t2)));
22912 break;
22915 case 0x1: { /* LDXC1 */
22916 /* Load Doubleword Indexed to Floating Point
22917 LDXC1 (MIPS32r2 and MIPS64) */
22918 DIP("ldxc1 f%u, r%u(r%u)", fd, rt, rs);
22919 t0 = newTemp(ty);
22920 assign(t0, binop(mode64 ? Iop_Add64 : Iop_Add32, getIReg(rs),
22921 getIReg(rt)));
22922 putDReg(fd, load(Ity_F64, mkexpr(t0)));
22923 break;
22926 case 0x5: /* Load Doubleword Indexed Unaligned to Floating Point - LUXC1;
22927 MIPS32r2 and MIPS64 */
22928 DIP("luxc1 f%u, r%u(r%u)", fd, rt, rs);
22930 if ((mode64 || VEX_MIPS_CPU_HAS_MIPS32R2(archinfo->hwcaps))
22931 && fp_mode64) {
22932 t0 = newTemp(ty);
22933 t1 = newTemp(ty);
22934 assign(t0, binop(mode64 ? Iop_Add64 : Iop_Add32,
22935 getIReg(rs), getIReg(rt)));
22936 assign(t1, binop(mode64 ? Iop_And64 : Iop_And32,
22937 mkexpr(t0),
22938 mode64 ? mkU64(0xfffffffffffffff8ULL)
22939 : mkU32(0xfffffff8ULL)));
22940 putFReg(fd, load(Ity_F64, mkexpr(t1)));
22941 } else {
22942 ILLEGAL_INSTRUCTON
22945 break;
22947 case 0x8: { /* Store Word Indexed from Floating Point - SWXC1 */
22948 DIP("swxc1 f%u, r%u(r%u)", ft, rt, rs);
22949 t0 = newTemp(ty);
22950 assign(t0, binop(mode64 ? Iop_Add64 : Iop_Add32, getIReg(rs),
22951 getIReg(rt)));
22953 if (fp_mode64) {
22954 store(mkexpr(t0), getLoFromF64(tyF, getFReg(fs)));
22955 } else {
22956 store(mkexpr(t0), getFReg(fs));
22959 break;
22962 case 0x9: { /* Store Doubleword Indexed from Floating Point - SDXC1 */
22963 DIP("sdxc1 f%u, r%u(r%u)", fs, rt, rs);
22964 t0 = newTemp(ty);
22965 assign(t0, binop(mode64 ? Iop_Add64 : Iop_Add32, getIReg(rs),
22966 getIReg(rt)));
22967 store(mkexpr(t0), getDReg(fs));
22968 break;
22971 case 0xD: /* Store Doubleword Indexed Unaligned from Floating Point -
22972 SUXC1; MIPS64 MIPS32r2 */
22973 DIP("suxc1 f%u, r%u(r%u)", fd, rt, rs);
22975 if ((mode64 || VEX_MIPS_CPU_HAS_MIPS32R2(archinfo->hwcaps))
22976 && fp_mode64) {
22977 t0 = newTemp(ty);
22978 t1 = newTemp(ty);
22979 assign(t0, binop(mode64 ? Iop_Add64 : Iop_Add32,
22980 getIReg(rs), getIReg(rt)));
22981 assign(t1, binop(mode64 ? Iop_And64 : Iop_And32,
22982 mkexpr(t0),
22983 mode64 ? mkU64(0xfffffffffffffff8ULL)
22984 : mkU32(0xfffffff8ULL)));
22985 store(mkexpr(t1), getFReg(fs));
22986 } else {
22987 ILLEGAL_INSTRUCTON
22990 break;
22992 case 0x0F: {
22993 DIP("prefx");
22994 break;
22997 case 0x20: { /* MADD.S */
22998 DIP("madd.s f%u, f%u, f%u, f%u", fd, fmt, fs, ft);
22999 IRExpr *rm = get_IR_roundingmode();
23000 t1 = newTemp(Ity_F32);
23001 assign(t1, triop(Iop_AddF32, rm, getLoFromF64(tyF, getFReg(fmt)),
23002 triop(Iop_MulF32, rm, getLoFromF64(tyF, getFReg(fs)),
23003 getLoFromF64(tyF, getFReg(ft)))));
23004 putFReg(fd, mkWidenFromF32(tyF, mkexpr(t1)));
23005 break; /* MADD.S */
23008 case 0x21: { /* MADD.D */
23009 DIP("madd.d f%u, f%u, f%u, f%u", fd, fmt, fs, ft);
23010 IRExpr *rm = get_IR_roundingmode();
23011 putDReg(fd, triop(Iop_AddF64, rm, getDReg(fmt),
23012 triop(Iop_MulF64, rm, getDReg(fs),
23013 getDReg(ft))));
23014 break; /* MADD.D */
23017 case 0x28: { /* MSUB.S */
23018 DIP("msub.s f%u, f%u, f%u, f%u", fd, fmt, fs, ft);
23019 IRExpr *rm = get_IR_roundingmode();
23020 t1 = newTemp(Ity_F32);
23021 assign(t1, triop(Iop_SubF32, rm,
23022 triop(Iop_MulF32, rm, getLoFromF64(tyF, getFReg(fs)),
23023 getLoFromF64(tyF, getFReg(ft))),
23024 getLoFromF64(tyF, getFReg(fmt))));
23025 putFReg(fd, mkWidenFromF32(tyF, mkexpr(t1)));
23026 break; /* MSUB.S */
23029 case 0x29: { /* MSUB.D */
23030 DIP("msub.d f%u, f%u, f%u, f%u", fd, fmt, fs, ft);
23031 IRExpr *rm = get_IR_roundingmode();
23032 putDReg(fd, triop(Iop_SubF64, rm, triop(Iop_MulF64, rm, getDReg(fs),
23033 getDReg(ft)), getDReg(fmt)));
23034 break; /* MSUB.D */
23037 case 0x30: { /* NMADD.S */
23038 DIP("nmadd.s f%u, f%u, f%u, f%u", fd, fmt, fs, ft);
23039 IRExpr *rm = get_IR_roundingmode();
23040 t1 = newTemp(Ity_F32);
23041 assign(t1, triop(Iop_AddF32, rm, getLoFromF64(tyF, getFReg(fmt)),
23042 triop(Iop_MulF32, rm, getLoFromF64(tyF, getFReg(fs)),
23043 getLoFromF64(tyF, getFReg(ft)))));
23044 putFReg(fd, mkWidenFromF32(tyF, unop(Iop_NegF32, mkexpr(t1))));
23045 break; /* NMADD.S */
23048 case 0x31: { /* NMADD.D */
23049 DIP("nmadd.d f%u, f%u, f%u, f%u", fd, fmt, fs, ft);
23050 IRExpr *rm = get_IR_roundingmode();
23051 t1 = newTemp(Ity_F64);
23052 assign(t1, triop(Iop_AddF64, rm, getDReg(fmt),
23053 triop(Iop_MulF64, rm, getDReg(fs),
23054 getDReg(ft))));
23055 putDReg(fd, unop(Iop_NegF64, mkexpr(t1)));
23056 break; /* NMADD.D */
23059 case 0x38: { /* NMSUBB.S */
23060 DIP("nmsub.s f%u, f%u, f%u, f%u", fd, fmt, fs, ft);
23061 IRExpr *rm = get_IR_roundingmode();
23062 t1 = newTemp(Ity_F32);
23063 assign(t1, triop(Iop_SubF32, rm,
23064 triop(Iop_MulF32, rm, getLoFromF64(tyF, getFReg(fs)),
23065 getLoFromF64(tyF, getFReg(ft))),
23066 getLoFromF64(tyF, getFReg(fmt))));
23067 putFReg(fd, mkWidenFromF32(tyF, unop(Iop_NegF32, mkexpr(t1))));
23068 break; /* NMSUBB.S */
23071 case 0x39: { /* NMSUBB.D */
23072 DIP("nmsub.d f%u, f%u, f%u, f%u", fd, fmt, fs, ft);
23073 IRExpr *rm = get_IR_roundingmode();
23074 t1 = newTemp(Ity_F64);
23075 assign(t1, triop(Iop_SubF64, rm, triop(Iop_MulF64, rm, getDReg(fs),
23076 getDReg(ft)), getDReg(fmt)));
23077 putDReg(fd, unop(Iop_NegF64, mkexpr(t1)));
23078 break; /* NMSUBB.D */
23081 default:
23082 return -1;
23085 break;
23087 case 0x04: /* BEQL */
23088 DIP("beql r%u, r%u, %u", rs, rt, imm);
23089 *lastn = dis_branch_likely(binop(mode64 ? Iop_CmpNE64 : Iop_CmpNE32,
23090 getIReg(rs), getIReg(rt)), imm);
23091 break;
23093 case 0x05: /* BNEL */
23094 DIP("bnel r%u, r%u, %u", rs, rt, imm);
23095 *lastn = dis_branch_likely(binop(mode64 ? Iop_CmpEQ64 : Iop_CmpEQ32,
23096 getIReg(rs), getIReg(rt)), imm);
23097 break;
23099 case 0x06: /* 0x16 ??? BLEZL, BLEZC, BGEZC, BGEC */
23100 if (rt == 0) { /* BLEZL */
23101 DIP("blezl r%u, %u", rs, imm);
23102 *lastn = dis_branch_likely(unop(Iop_Not1, (binop(mode64 ? Iop_CmpLE64S :
23103 Iop_CmpLE32S, getIReg(rs), mode64 ?
23104 mkU64(0x0) : mkU32(0x0)))), imm);
23105 } else if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
23106 if (rs == 0) { /* BLEZC */
23107 DIP("blezc r%u, %u", rt, imm);
23109 if (mode64) {
23110 dis_branch_compact(False,
23111 binop(Iop_CmpLE64S, getIReg(rt), mkU64(0x0)),
23112 imm, dres);
23113 } else {
23114 dis_branch_compact(False,
23115 binop(Iop_CmpLE32S, getIReg(rt), mkU32(0x0)),
23116 imm, dres);
23118 } else if (rt == rs) { /* BGEZC */
23119 DIP("bgezc r%u, %u", rt, imm);
23121 if (mode64) {
23122 dis_branch_compact(False,
23123 binop(Iop_CmpLE64S, mkU64(0x0), getIReg(rt)),
23124 imm, dres);
23125 } else {
23126 dis_branch_compact(False,
23127 binop(Iop_CmpLE32S, mkU32(0x0), getIReg(rt)),
23128 imm, dres);
23130 } else { /* BGEC */
23131 DIP("bgec r%u, r%u, %u", rs, rt, imm);
23133 if (mode64) {
23134 dis_branch_compact(False,
23135 binop(Iop_CmpLE64S, getIReg(rt), getIReg(rs)),
23136 imm, dres);
23137 } else {
23138 dis_branch_compact(False,
23139 binop(Iop_CmpLE32S, getIReg(rt), getIReg(rs)),
23140 imm, dres);
23143 } else {
23144 ILLEGAL_INSTRUCTON
23147 break;
23149 case 0x07: /* BGTZL, BGTZC, BLTZC, BLTC */
23150 if (rt == 0) { /* BGTZL */
23151 DIP("bgtzl r%u, %u", rs, imm);
23153 if (mode64)
23154 *lastn = dis_branch_likely(binop(Iop_CmpLE64S, getIReg(rs),
23155 mkU64(0x00)), imm);
23156 else
23157 *lastn = dis_branch_likely(binop(Iop_CmpLE32S, getIReg(rs),
23158 mkU32(0x00)), imm);
23159 } else if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
23160 if (rs == 0) { /* BGTZC */
23161 DIP("bgtzc r%u, %u", rt, imm);
23163 if (mode64) {
23164 dis_branch_compact(False,
23165 unop(Iop_Not1,
23166 binop(Iop_CmpLE64S,
23167 getIReg(rt), mkU64(0x0))),
23168 imm, dres);
23169 } else {
23170 dis_branch_compact(False,
23171 unop(Iop_Not1,
23172 binop(Iop_CmpLE32S,
23173 getIReg(rt), mkU32(0x0))),
23174 imm, dres);
23176 } else if (rs == rt) { /* BLTZC */
23177 DIP("bltzc r%u, %u", rt, imm);
23179 if (mode64) {
23180 dis_branch_compact(False,
23181 unop(Iop_Not1,
23182 binop(Iop_CmpLE64S,
23183 mkU64(0x0), getIReg(rt))),
23184 imm, dres);
23185 } else {
23186 dis_branch_compact(False,
23187 unop(Iop_Not1,
23188 binop(Iop_CmpLE32S,
23189 mkU32(0x0), getIReg(rt))),
23190 imm, dres);
23192 } else { /* BLTC */
23193 DIP("bltc r%u, r%u, %u", rs, rt, imm);
23195 if (mode64) {
23196 dis_branch_compact(False,
23197 unop(Iop_Not1,
23198 binop(Iop_CmpLE64S,
23199 getIReg(rt), getIReg(rs))),
23200 imm, dres);
23201 } else {
23202 dis_branch_compact(False,
23203 unop(Iop_Not1,
23204 binop(Iop_CmpLE32S,
23205 getIReg(rt), getIReg(rs))),
23206 imm, dres);
23209 } else {
23210 ILLEGAL_INSTRUCTON
23213 break;
23215 #if defined(__mips__) && ((defined(__mips_isa_rev) && __mips_isa_rev < 6))
23217 case 0x08: { /* Doubleword Add Immidiate - DADDI; MIPS64 */
23218 DIP("daddi r%u, r%u, %u", rt, rs, imm);
23219 IRTemp tmpRs64 = newTemp(Ity_I64);
23220 assign(tmpRs64, getIReg(rs));
23222 t0 = newTemp(Ity_I64);
23223 t1 = newTemp(Ity_I64);
23224 t2 = newTemp(Ity_I64);
23225 t3 = newTemp(Ity_I64);
23226 t4 = newTemp(Ity_I64);
23227 /* dst = src0 + sign(imm)
23228 if(sign(src0 ) != sign(imm ))
23229 goto no overflow;
23230 if(sign(dst) == sign(src0 ))
23231 goto no overflow;
23232 we have overflow! */
23234 assign(t0, binop(Iop_Add64, mkexpr(tmpRs64),
23235 mkU64(extend_s_16to64(imm))));
23236 assign(t1, binop(Iop_Xor64, mkexpr(tmpRs64),
23237 mkU64(extend_s_16to64(imm))));
23238 assign(t2, unop(Iop_1Sto64, binop(Iop_CmpEQ64, binop(Iop_And64,
23239 mkexpr(t1), mkU64(0x8000000000000000ULL)),
23240 mkU64(0x8000000000000000ULL))));
23242 assign(t3, binop(Iop_Xor64, mkexpr(t0), mkexpr(tmpRs64)));
23243 assign(t4, unop(Iop_1Sto64, binop(Iop_CmpNE64, binop(Iop_And64,
23244 mkexpr(t3), mkU64(0x8000000000000000ULL)),
23245 mkU64(0x8000000000000000ULL))));
23247 stmt(IRStmt_Exit(binop(Iop_CmpEQ64, binop(Iop_Or64, mkexpr(t2),
23248 mkexpr(t4)), mkU64(0)), Ijk_SigFPE_IntOvf,
23249 IRConst_U64(guest_PC_curr_instr + 4),
23250 OFFB_PC));
23252 putIReg(rt, mkexpr(t0));
23253 break;
23256 #elif defined(__mips__) && ((defined(__mips_isa_rev) && __mips_isa_rev >= 6))
23258 case 0x08: { /* BNEZALC, BNEC, BNVC */
23259 if (rs == 0) { /* BNEZALC */
23260 DIP("bnezalc r%u, %u", rt, imm);
23262 if (mode64) {
23263 dis_branch_compact(True,
23264 unop(Iop_Not1,
23265 binop(Iop_CmpEQ64, getIReg(rt), mkU64(0x0))),
23266 imm, dres);
23267 } else {
23268 dis_branch_compact(True,
23269 unop(Iop_Not1,
23270 binop(Iop_CmpEQ32, getIReg(rt), mkU32(0x0))),
23271 imm, dres);
23273 } else if (rs < rt) { /* BNEC */
23274 DIP("bnec r%u, %u", rt, imm);
23276 if (mode64) {
23277 dis_branch_compact(False,
23278 unop(Iop_Not1,
23279 binop(Iop_CmpEQ64,
23280 getIReg(rt), getIReg(rs))),
23281 imm, dres);
23282 } else {
23283 dis_branch_compact(False,
23284 unop(Iop_Not1,
23285 binop(Iop_CmpEQ32,
23286 getIReg(rt), getIReg(rs))),
23287 imm, dres);
23289 } else { /* BNVC */
23290 DIP("bnvc r%u, r%u, %u", rs, rt, imm);
23292 if (mode64) {
23293 t0 = newTemp(Ity_I32);
23294 t1 = newTemp(Ity_I32);
23295 t2 = newTemp(Ity_I32);
23296 t3 = newTemp(Ity_I32);
23297 assign(t0, IRExpr_ITE(binop(Iop_CmpLT64S,
23298 getIReg(rt),
23299 mkU64(0xffffffff80000000ULL)),
23300 mkU32(1),
23301 IRExpr_ITE(binop(Iop_CmpLT64S,
23302 getIReg(rt),
23303 mkU64(0x7FFFFFFFULL)),
23304 mkU32(0), mkU32(1))));
23305 assign(t1, IRExpr_ITE(binop(Iop_CmpLT64S,
23306 getIReg(rs),
23307 mkU64(0xffffffff80000000ULL)),
23308 mkU32(1),
23309 IRExpr_ITE(binop(Iop_CmpLT64S,
23310 getIReg(rs),
23311 mkU64(0x7FFFFFFFULL)),
23312 mkU32(0), mkU32(1))));
23313 assign(t2, IRExpr_ITE(binop(Iop_CmpLT64S,
23314 binop(Iop_Add64,
23315 getIReg(rt), getIReg(rs)),
23316 mkU64(0xffffffff80000000ULL)),
23317 mkU32(1),
23318 IRExpr_ITE(binop(Iop_CmpLT64S,
23319 binop(Iop_Add64,
23320 getIReg(rt),
23321 getIReg(rs)),
23322 mkU64(0x7FFFFFFFULL)),
23323 mkU32(0), mkU32(1))));
23324 assign(t3, binop(Iop_Add32,
23325 mkexpr(t0),
23326 binop(Iop_Add32, mkexpr(t1), mkexpr(t2))));
23327 dis_branch_compact(False,
23328 binop(Iop_CmpEQ32, mkexpr(t3), mkU32(0)),
23329 imm, dres);
23330 } else {
23331 IRTemp tmpRs32 = newTemp(Ity_I32);
23332 IRTemp tmpRt32 = newTemp(Ity_I32);
23334 assign(tmpRs32, getIReg(rs));
23335 assign(tmpRt32, getIReg(rt));
23336 t0 = newTemp(Ity_I32);
23337 t1 = newTemp(Ity_I32);
23338 t2 = newTemp(Ity_I32);
23339 t3 = newTemp(Ity_I32);
23340 t4 = newTemp(Ity_I32);
23341 /* dst = src0 + src1
23342 if (sign(src0 ) != sign(src1 ))
23343 goto no overflow;
23344 if (sign(dst) == sign(src0 ))
23345 goto no overflow;
23346 we have overflow! */
23348 assign(t0, binop(Iop_Add32, mkexpr(tmpRs32), mkexpr(tmpRt32)));
23349 assign(t1, binop(Iop_Xor32, mkexpr(tmpRs32), mkexpr(tmpRt32)));
23350 assign(t2, unop(Iop_1Uto32,
23351 binop(Iop_CmpEQ32,
23352 binop(Iop_And32, mkexpr(t1), mkU32(0x80000000)),
23353 mkU32(0x80000000))));
23355 assign(t3, binop(Iop_Xor32, mkexpr(t0), mkexpr(tmpRs32)));
23356 assign(t4, unop(Iop_1Uto32,
23357 binop(Iop_CmpNE32,
23358 binop(Iop_And32, mkexpr(t3), mkU32(0x80000000)),
23359 mkU32(0x80000000))));
23361 dis_branch_compact(False, binop(Iop_CmpNE32 ,
23362 binop(Iop_Or32, mkexpr(t2), mkexpr(t4)),
23363 mkU32(0)), imm, dres);
23367 break;
23370 #endif
23372 case 0x09: /* Doubleword Add Immidiate Unsigned - DADDIU; MIPS64 */
23373 DIP("daddiu r%u, r%u, %u", rt, rs, imm);
23374 putIReg(rt, binop(Iop_Add64, getIReg(rs), mkU64(extend_s_16to64(imm))));
23375 break;
23377 case 0x0A: { /* LDL */
23378 /* Load Doubleword Left - LDL; MIPS64 */
23379 vassert(mode64);
23380 DIP("ldl r%u, %u(r%u)", rt, imm, rs);
23381 /* t1 = addr */
23382 #if defined (_MIPSEL)
23383 t1 = newTemp(Ity_I64);
23384 assign(t1, binop(Iop_Add64, getIReg(rs), mkU64(extend_s_16to64(imm))));
23385 #elif defined (_MIPSEB)
23386 t1 = newTemp(Ity_I64);
23387 assign(t1, binop(Iop_Xor64, mkU64(0x7), binop(Iop_Add64, getIReg(rs),
23388 mkU64(extend_s_16to64(imm)))));
23389 #endif
23390 /* t2 = word addr */
23391 /* t4 = addr mod 8 */
23392 LWX_SWX_PATTERN64_1;
23394 /* t3 = word content - shifted */
23395 t3 = newTemp(Ity_I64);
23396 assign(t3, binop(Iop_Shl64, load(Ity_I64, mkexpr(t2)),
23397 narrowTo(Ity_I8, binop(Iop_Shl64, binop(Iop_Sub64, mkU64(0x07),
23398 mkexpr(t4)), mkU8(3)))));
23400 /* rt content - adjusted */
23401 t5 = newTemp(Ity_I64);
23402 t6 = newTemp(Ity_I64);
23403 t7 = newTemp(Ity_I64);
23405 assign(t5, binop(Iop_Mul64, mkexpr(t4), mkU64(0x8)));
23407 assign(t6, binop(Iop_Shr64, mkU64(0x00FFFFFFFFFFFFFFULL),
23408 narrowTo(Ity_I8, mkexpr(t5))));
23410 assign(t7, binop(Iop_And64, getIReg(rt), mkexpr(t6)));
23412 putIReg(rt, binop(Iop_Or64, mkexpr(t7), mkexpr(t3)));
23413 break;
23416 case 0x0B: { /* LDR */
23417 /* Load Doubleword Right - LDR; MIPS64 */
23418 vassert(mode64);
23419 DIP("ldr r%u,%u(r%u)", rt, imm, rs);
23420 /* t1 = addr */
23421 #if defined (_MIPSEL)
23422 t1 = newTemp(Ity_I64);
23423 assign(t1, binop(Iop_Add64, getIReg(rs), mkU64(extend_s_16to64(imm))));
23424 #elif defined (_MIPSEB)
23425 t1 = newTemp(Ity_I64);
23426 assign(t1, binop(Iop_Xor64, mkU64(0x7), binop(Iop_Add64, getIReg(rs),
23427 mkU64(extend_s_16to64(imm)))));
23428 #endif
23429 /* t2 = word addr */
23430 /* t4 = addr mod 8 */
23431 LWX_SWX_PATTERN64_1;
23433 /* t3 = word content - shifted */
23434 t3 = newTemp(Ity_I64);
23435 assign(t3, binop(Iop_Shr64, load(Ity_I64, mkexpr(t2)),
23436 narrowTo(Ity_I8, binop(Iop_Shl64, mkexpr(t4), mkU8(3)))));
23438 /* rt content - adjusted */
23439 t5 = newTemp(Ity_I64);
23440 assign(t5, binop(Iop_And64, getIReg(rt), unop(Iop_Not64,
23441 binop(Iop_Shr64, mkU64(0xFFFFFFFFFFFFFFFFULL),
23442 narrowTo(Ity_I8, binop(Iop_Shl64, mkexpr(t4), mkU8(0x3)))))));
23444 putIReg(rt, binop(Iop_Or64, mkexpr(t5), mkexpr(t3)));
23445 break;
23448 case 0x0C: /* Special2 */
23449 return disInstr_MIPS_WRK_Special2(cins, archinfo, abiinfo,
23450 dres, bstmt, lastn);
23452 case 0x0D: /* DAUI */
23453 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
23454 DIP("daui r%u, r%u, %x", rt, rs, imm);
23455 putIReg(rt, binop(Iop_Add64, getIReg(rs), mkU64(extend_s_32to64(imm << 16))));
23456 } else {
23457 ILLEGAL_INSTRUCTON
23460 break;
23462 case 0x0E: /* MIPS MSA (SIMD) */
23463 if (has_msa) {
23464 Int retVal = disMSAInstr_MIPS_WRK(cins);
23466 if (retVal == 0) {
23467 break;
23468 } else if (retVal == -2) {
23469 ILLEGAL_INSTRUCTON
23470 break;
23474 vex_printf("Error occured while trying to decode MIPS MSA "
23475 "instruction.\nYour platform probably doesn't support "
23476 "MIPS MSA (SIMD) ASE.\n");
23477 return -1;
23479 case 0x0F: /* Special3 */
23480 return disInstr_MIPS_WRK_Special3(cins, archinfo, abiinfo,
23481 dres, bstmt, lastn);
23483 default:
23484 return -1;
23487 return 0;
23490 static UInt disInstr_MIPS_WRK_20(UInt cins)
23492 IRTemp t1 = 0, t2, t3, t4, t5;
23493 UInt opcode, rs, rt, imm;
23495 opcode = get_opcode(cins);
23496 imm = get_imm(cins);
23497 rs = get_rs(cins);
23498 rt = get_rt(cins);
23499 IRType ty = mode64 ? Ity_I64 : Ity_I32;
23501 switch (opcode & 0x0F) {
23502 case 0x00: /* LB */
23503 DIP("lb r%u, %u(r%u)", rt, imm, rs);
23504 LOAD_STORE_PATTERN;
23506 if (mode64)
23507 putIReg(rt, unop(Iop_8Sto64, load(Ity_I8, mkexpr(t1))));
23508 else
23509 putIReg(rt, unop(Iop_8Sto32, load(Ity_I8, mkexpr(t1))));
23511 break;
23513 case 0x01: /* LH */
23514 DIP("lh r%u, %u(r%u)", rt, imm, rs);
23515 LOAD_STORE_PATTERN;
23517 if (mode64)
23518 putIReg(rt, unop(Iop_16Sto64, load(Ity_I16, mkexpr(t1))));
23519 else
23520 putIReg(rt, unop(Iop_16Sto32, load(Ity_I16, mkexpr(t1))));
23522 break;
23524 case 0x02: /* LWL */
23525 DIP("lwl r%u, %u(r%u)", rt, imm, rs);
23527 if (mode64) {
23528 /* t1 = addr */
23529 t1 = newTemp(Ity_I64);
23530 #if defined (_MIPSEL)
23531 assign(t1, binop(Iop_Add64, getIReg(rs), mkU64(extend_s_16to64(imm))));
23532 #elif defined (_MIPSEB)
23533 assign(t1, binop(Iop_Xor64,
23534 mkU64(0x03),
23535 binop(Iop_Add64,
23536 getIReg(rs),
23537 mkU64(extend_s_16to64(imm)))));
23538 #endif
23539 /* t2 = word addr */
23540 /* t4 = addr mod 4 */
23541 LWX_SWX_PATTERN64;
23543 /* t3 = word content - shifted */
23544 t3 = newTemp(Ity_I32);
23545 assign(t3, binop(Iop_Shl32,
23546 load(Ity_I32, mkexpr(t2)),
23547 narrowTo(Ity_I8,
23548 binop(Iop_Shl32,
23549 binop(Iop_Sub32,
23550 mkU32(0x03),
23551 mkexpr(t4)),
23552 mkU8(3)))));
23554 /* rt content - adjusted */
23555 t5 = newTemp(Ity_I32);
23556 assign(t5, binop(Iop_And32,
23557 mkNarrowTo32(ty, getIReg(rt)),
23558 binop(Iop_Shr32,
23559 mkU32(0x00FFFFFF),
23560 narrowTo(Ity_I8, binop(Iop_Mul32,
23561 mkU32(0x08),
23562 mkexpr(t4))))));
23564 putIReg(rt, mkWidenFrom32(ty, binop(Iop_Or32, mkexpr(t5),
23565 mkexpr(t3)), True));
23566 } else {
23567 /* t1 = addr */
23568 t1 = newTemp(Ity_I32);
23569 #if defined (_MIPSEL)
23570 assign(t1, binop(Iop_Add32, getIReg(rs), mkU32(extend_s_16to32(imm))));
23571 #elif defined (_MIPSEB)
23572 assign(t1, binop(Iop_Xor32, mkU32(0x3), binop(Iop_Add32, getIReg(rs),
23573 mkU32(extend_s_16to32(imm)))));
23574 #endif
23576 /* t2 = word addr */
23577 /* t4 = addr mod 4 */
23578 LWX_SWX_PATTERN;
23580 /* t3 = word content - shifted */
23581 t3 = newTemp(Ity_I32);
23582 assign(t3, binop(Iop_Shl32, load(Ity_I32, mkexpr(t2)), narrowTo(Ity_I8,
23583 binop(Iop_Shl32, binop(Iop_Sub32, mkU32(0x03), mkexpr(t4)),
23584 mkU8(3)))));
23586 /* rt content - adjusted */
23587 t5 = newTemp(Ity_I32);
23588 assign(t5, binop(Iop_And32,
23589 getIReg(rt),
23590 binop(Iop_Shr32,
23591 mkU32(0x00FFFFFF),
23592 narrowTo(Ity_I8, binop(Iop_Mul32,
23593 mkU32(0x08),
23594 mkexpr(t4))))));
23596 putIReg(rt, binop(Iop_Or32, mkexpr(t5), mkexpr(t3)));
23599 break;
23601 case 0x03: /* LW */
23602 DIP("lw r%u, %u(r%u)", rt, imm, rs);
23603 LOAD_STORE_PATTERN;
23604 putIReg(rt, mkWidenFrom32(ty, load(Ity_I32, mkexpr(t1)), True));
23605 break;
23607 case 0x04: /* LBU */
23608 DIP("lbu r%u, %u(r%u)", rt, imm, rs);
23609 LOAD_STORE_PATTERN;
23611 if (mode64)
23612 putIReg(rt, unop(Iop_8Uto64, load(Ity_I8, mkexpr(t1))));
23613 else
23614 putIReg(rt, unop(Iop_8Uto32, load(Ity_I8, mkexpr(t1))));
23616 break;
23618 case 0x05: /* LHU */
23619 DIP("lhu r%u, %u(r%u)", rt, imm, rs);
23620 LOAD_STORE_PATTERN;
23622 if (mode64)
23623 putIReg(rt, unop(Iop_16Uto64, load(Ity_I16, mkexpr(t1))));
23624 else
23625 putIReg(rt, unop(Iop_16Uto32, load(Ity_I16, mkexpr(t1))));
23627 break;
23629 case 0x06: /* LWR */
23630 DIP("lwr r%u, %u(r%u)", rt, imm, rs);
23632 if (mode64) {
23633 /* t1 = addr */
23634 t1 = newTemp(Ity_I64);
23636 #if defined (_MIPSEL)
23637 assign(t1, binop(Iop_Add64, getIReg(rs), mkU64(extend_s_16to64(imm))));
23638 #elif defined (_MIPSEB)
23639 assign(t1, binop(Iop_Xor64,
23640 mkU64(0x3),
23641 binop(Iop_Add64,
23642 getIReg(rs),
23643 mkU64(extend_s_16to64(imm)))));
23644 #endif
23645 /* t2 = word addr */
23646 /* t4 = addr mod 4 */
23647 LWX_SWX_PATTERN64;
23649 /* t3 = word content - shifted */
23650 t3 = newTemp(Ity_I32);
23651 assign(t3, binop(Iop_Shr32,
23652 load(Ity_I32, mkexpr(t2)),
23653 narrowTo(Ity_I8,
23654 binop(Iop_Shl32, mkexpr(t4), mkU8(0x03)))));
23656 /* rt content - adjusted */
23657 t5 = newTemp(Ity_I32);
23658 assign(t5, binop(Iop_And32, mkNarrowTo32(ty, getIReg(rt)),
23659 unop(Iop_Not32, binop(Iop_Shr32, mkU32(0xFFFFFFFF),
23660 narrowTo(Ity_I8, binop(Iop_Shl32, mkexpr(t4), mkU8(0x3)))))));
23662 putIReg(rt, mkWidenFrom32(ty, binop(Iop_Or32, mkexpr(t5),
23663 mkexpr(t3)), True));
23665 } else {
23666 /* t1 = addr */
23667 t1 = newTemp(Ity_I32);
23668 #if defined (_MIPSEL)
23669 assign(t1, binop(Iop_Add32, getIReg(rs), mkU32(extend_s_16to32(imm))));
23670 #elif defined (_MIPSEB)
23671 assign(t1, binop(Iop_Xor32, mkU32(0x3), binop(Iop_Add32, getIReg(rs),
23672 mkU32(extend_s_16to32(imm)))));
23673 #endif
23675 /* t2 = word addr */
23676 /* t4 = addr mod 4 */
23677 LWX_SWX_PATTERN;
23679 /* t3 = word content - shifted */
23680 t3 = newTemp(Ity_I32);
23681 assign(t3, binop(Iop_Shr32, load(Ity_I32, mkexpr(t2)),
23682 narrowTo(Ity_I8, binop(Iop_Shl32, mkexpr(t4),
23683 mkU8(3)))));
23685 /* rt content - adjusted */
23686 t5 = newTemp(Ity_I32);
23687 assign(t5, binop(Iop_And32, getIReg(rt), unop(Iop_Not32,
23688 binop(Iop_Shr32, mkU32(0xFFFFFFFF), narrowTo(Ity_I8,
23689 binop(Iop_Shl32, mkexpr(t4), mkU8(0x3)))))));
23691 putIReg(rt, binop(Iop_Or32, mkexpr(t5), mkexpr(t3)));
23694 break;
23696 case 0x07: /* Load Word unsigned - LWU; MIPS64 */
23697 DIP("lwu r%u,%u(r%u)", rt, imm, rs);
23698 LOAD_STORE_PATTERN;
23700 putIReg(rt, mkWidenFrom32(ty, load(Ity_I32, mkexpr(t1)), False));
23701 break;
23703 case 0x08: /* SB */
23704 DIP("sb r%u, %u(r%u)", rt, imm, rs);
23705 LOAD_STORE_PATTERN;
23706 store(mkexpr(t1), narrowTo(Ity_I8, getIReg(rt)));
23707 break;
23709 case 0x09: /* SH */
23710 DIP("sh r%u, %u(r%u)", rt, imm, rs);
23711 LOAD_STORE_PATTERN;
23712 store(mkexpr(t1), narrowTo(Ity_I16, getIReg(rt)));
23713 break;
23715 case 0x0A: /* SWL */
23716 DIP("swl r%u, %u(r%u)", rt, imm, rs);
23718 if (mode64) {
23719 IRTemp E_byte = newTemp(Ity_I8);
23720 IRTemp F_byte = newTemp(Ity_I8);
23721 IRTemp G_byte = newTemp(Ity_I8);
23722 IRTemp H_byte = newTemp(Ity_I8);
23723 IRTemp F_pos = newTemp(Ity_I64);
23724 IRTemp G_pos = newTemp(Ity_I64);
23726 /* H byte */
23727 assign(H_byte, getByteFromReg(rt, 0));
23728 /* G byte */
23729 assign(G_byte, getByteFromReg(rt, 1));
23730 /* F byte */
23731 assign(F_byte, getByteFromReg(rt, 2));
23732 /* E byte */
23733 assign(E_byte, getByteFromReg(rt, 3));
23735 /* t1 = addr */
23736 t1 = newTemp(Ity_I64);
23737 assign(t1, binop(Iop_Add64, getIReg(rs), mkU64(extend_s_16to64(imm))));
23739 /* t2 = word addr */
23740 t2 = newTemp(Ity_I64);
23741 assign(t2, binop(Iop_And64, mkexpr(t1), mkU64(0xFFFFFFFFFFFFFFFCULL)));
23743 /* t3 = addr mod 4 */
23744 t3 = newTemp(Ity_I64);
23745 assign(t3, binop(Iop_And64, mkexpr(t1), mkU64(0x3)));
23747 #if defined (_MIPSEL)
23748 /* Calculate X_byte position. */
23749 assign(F_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x0)),
23750 mkU64(0x0),
23751 mkU64(0x1)));
23753 assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x3)),
23754 mkU64(0x1),
23755 mkU64(0x0)));
23757 /* Store X_byte on the right place. */
23758 store(mkexpr(t2), mkexpr(H_byte));
23759 store(binop(Iop_Add64, mkexpr(t2), mkexpr(G_pos)), mkexpr(G_byte));
23760 store(binop(Iop_Sub64, mkexpr(t1), mkexpr(F_pos)), mkexpr(F_byte));
23761 store(mkexpr(t1), mkexpr(E_byte));
23763 #else /* _MIPSEB */
23764 /* Calculate X_byte position. */
23765 assign(F_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x3)),
23766 mkU64(0x0),
23767 mkU64(0x1)));
23769 assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x0)),
23770 mkU64(0x2),
23771 mkU64(0x3)));
23773 store(binop(Iop_Add64, mkexpr(t2), mkU64(3)), mkexpr(H_byte));
23774 store(binop(Iop_Add64, mkexpr(t2), mkexpr(G_pos)), mkexpr(G_byte));
23775 store(binop(Iop_Add64, mkexpr(t1), mkexpr(F_pos)), mkexpr(F_byte));
23776 store(mkexpr(t1), mkexpr(E_byte));
23778 #endif
23779 } else {
23780 IRTemp E_byte = newTemp(Ity_I8);
23781 IRTemp F_byte = newTemp(Ity_I8);
23782 IRTemp G_byte = newTemp(Ity_I8);
23783 IRTemp H_byte = newTemp(Ity_I8);
23784 IRTemp F_pos = newTemp(Ity_I32);
23785 IRTemp G_pos = newTemp(Ity_I32);
23787 /* H byte */
23788 assign(H_byte, getByteFromReg(rt, 0));
23789 /* G byte */
23790 assign(G_byte, getByteFromReg(rt, 1));
23791 /* F byte */
23792 assign(F_byte, getByteFromReg(rt, 2));
23793 /* E byte */
23794 assign(E_byte, getByteFromReg(rt, 3));
23796 /* t1 = addr */
23797 t1 = newTemp(Ity_I32);
23798 assign(t1, binop(Iop_Add32, getIReg(rs), mkU32(extend_s_16to32(imm))));
23800 /* t2 = word addr */
23801 t2 = newTemp(Ity_I32);
23802 assign(t2, binop(Iop_And32, mkexpr(t1), mkU32(0xFFFFFFFCULL)));
23804 /* t3 = addr mod 4 */
23805 t3 = newTemp(Ity_I32);
23806 assign(t3, binop(Iop_And32, mkexpr(t1), mkU32(0x3)));
23808 #if defined (_MIPSEL)
23809 /* Calculate X_byte position. */
23810 assign(F_pos, IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t3), mkU32(0x0)),
23811 mkU32(0x0),
23812 mkU32(0x1)));
23814 assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t3), mkU32(0x3)),
23815 mkU32(0x1),
23816 mkU32(0x0)));
23818 /* Store X_byte on the right place. */
23819 store(mkexpr(t2), mkexpr(H_byte));
23820 store(binop(Iop_Add32, mkexpr(t2), mkexpr(G_pos)), mkexpr(G_byte));
23821 store(binop(Iop_Sub32, mkexpr(t1), mkexpr(F_pos)), mkexpr(F_byte));
23822 store(mkexpr(t1), mkexpr(E_byte));
23824 #else /* _MIPSEB */
23825 /* Calculate X_byte position. */
23826 assign(F_pos, IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t3), mkU32(0x3)),
23827 mkU32(0x0),
23828 mkU32(0x1)));
23830 assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t3), mkU32(0x0)),
23831 mkU32(0x2),
23832 mkU32(0x3)));
23834 store(binop(Iop_Add32, mkexpr(t2), mkU32(3)), mkexpr(H_byte));
23835 store(binop(Iop_Add32, mkexpr(t2), mkexpr(G_pos)), mkexpr(G_byte));
23836 store(binop(Iop_Add32, mkexpr(t1), mkexpr(F_pos)), mkexpr(F_byte));
23837 store(mkexpr(t1), mkexpr(E_byte));
23839 #endif
23842 break;
23844 case 0x0B: /* SW */
23845 DIP("sw r%u, %u(r%u)", rt, imm, rs);
23846 LOAD_STORE_PATTERN;
23847 store(mkexpr(t1), mkNarrowTo32(ty, getIReg(rt)));
23848 break;
23850 case 0x0C: { /* SDL rt, offset(base) MIPS64 */
23851 DIP("sdl r%u, %u(r%u)", rt, imm, rs);
23852 vassert(mode64);
23853 IRTemp A_byte = newTemp(Ity_I8);
23854 IRTemp B_byte = newTemp(Ity_I8);
23855 IRTemp C_byte = newTemp(Ity_I8);
23856 IRTemp D_byte = newTemp(Ity_I8);
23857 IRTemp E_byte = newTemp(Ity_I8);
23858 IRTemp F_byte = newTemp(Ity_I8);
23859 IRTemp G_byte = newTemp(Ity_I8);
23860 IRTemp H_byte = newTemp(Ity_I8);
23861 IRTemp B_pos = newTemp(Ity_I64);
23862 IRTemp C_pos = newTemp(Ity_I64);
23863 IRTemp D_pos = newTemp(Ity_I64);
23864 IRTemp E_pos = newTemp(Ity_I64);
23865 IRTemp F_pos = newTemp(Ity_I64);
23866 IRTemp G_pos = newTemp(Ity_I64);
23868 /* H byte */
23869 assign(H_byte, getByteFromReg(rt, 0));
23870 /* G byte */
23871 assign(G_byte, getByteFromReg(rt, 1));
23872 /* F byte */
23873 assign(F_byte, getByteFromReg(rt, 2));
23874 /* E byte */
23875 assign(E_byte, getByteFromReg(rt, 3));
23876 /* D byte */
23877 assign(D_byte, getByteFromReg(rt, 4));
23878 /* C byte */
23879 assign(C_byte, getByteFromReg(rt, 5));
23880 /* B byte */
23881 assign(B_byte, getByteFromReg(rt, 6));
23882 /* A byte */
23883 assign(A_byte, getByteFromReg(rt, 7));
23885 /* t1 = addr */
23886 t1 = newTemp(Ity_I64);
23887 assign(t1, binop(Iop_Add64, getIReg(rs), mkU64(extend_s_16to64(imm))));
23889 /* t2 = word addr */
23890 t2 = newTemp(Ity_I64);
23891 assign(t2, binop(Iop_And64, mkexpr(t1), mkU64(0xFFFFFFFFFFFFFFF8ULL)));
23893 /* t3 = addr mod 7 */
23894 t3 = newTemp(Ity_I64);
23895 assign(t3, binop(Iop_And64, mkexpr(t1), mkU64(0x7)));
23897 #if defined (_MIPSEL)
23898 /* Calculate X_byte position. */
23899 assign(B_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkexpr(t3), mkU64(0x1)),
23900 mkU64(0x0),
23901 mkU64(0x1)));
23903 assign(C_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkexpr(t3), mkU64(0x2)),
23904 mkU64(0x0),
23905 mkU64(0x2)));
23907 assign(D_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkexpr(t3), mkU64(0x3)),
23908 mkU64(0x0),
23909 mkU64(0x3)));
23911 assign(E_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkexpr(t3), mkU64(0x4)),
23912 mkU64(0x0),
23913 mkU64(0x4)));
23915 assign(F_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkexpr(t3), mkU64(0x5)),
23916 mkU64(0x0),
23917 mkU64(0x5)));
23919 assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x7)),
23920 mkU64(0x1),
23921 mkU64(0x0)));
23923 /* Store X_byte on the right place. */
23924 store(mkexpr(t2), mkexpr(H_byte));
23925 store(binop(Iop_Add64, mkexpr(t2), mkexpr(G_pos)), mkexpr(G_byte));
23926 store(binop(Iop_Sub64, mkexpr(t1), mkexpr(F_pos)), mkexpr(F_byte));
23927 store(binop(Iop_Sub64, mkexpr(t1), mkexpr(E_pos)), mkexpr(E_byte));
23928 store(binop(Iop_Sub64, mkexpr(t1), mkexpr(D_pos)), mkexpr(D_byte));
23929 store(binop(Iop_Sub64, mkexpr(t1), mkexpr(C_pos)), mkexpr(C_byte));
23930 store(binop(Iop_Sub64, mkexpr(t1), mkexpr(B_pos)), mkexpr(B_byte));
23931 store(mkexpr(t1), mkexpr(A_byte));
23933 #else /* _MIPSEB */
23934 /* Calculate X_byte position. */
23935 assign(B_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x7)),
23936 mkU64(0x0),
23937 mkU64(0x1)));
23939 assign(C_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkexpr(t3), mkU64(0x6)),
23940 mkU64(0x2),
23941 mkU64(0x0)));
23943 assign(D_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkexpr(t3), mkU64(0x5)),
23944 mkU64(0x3),
23945 mkU64(0x0)));
23947 assign(E_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkexpr(t3), mkU64(0x4)),
23948 mkU64(0x4),
23949 mkU64(0x0)));
23951 assign(F_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkexpr(t3), mkU64(0x3)),
23952 mkU64(0x5),
23953 mkU64(0x0)));
23955 assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x0)),
23956 mkU64(0x6),
23957 mkU64(0x7)));
23959 /* Store X_byte on the right place. */
23960 store(binop(Iop_Add64, mkexpr(t2), mkU64(0x7)), mkexpr(H_byte));
23961 store(binop(Iop_Add64, mkexpr(t2), mkexpr(G_pos)), mkexpr(G_byte));
23962 store(binop(Iop_Add64, mkexpr(t1), mkexpr(F_pos)), mkexpr(F_byte));
23963 store(binop(Iop_Add64, mkexpr(t1), mkexpr(E_pos)), mkexpr(E_byte));
23964 store(binop(Iop_Add64, mkexpr(t1), mkexpr(D_pos)), mkexpr(D_byte));
23965 store(binop(Iop_Add64, mkexpr(t1), mkexpr(C_pos)), mkexpr(C_byte));
23966 store(binop(Iop_Add64, mkexpr(t1), mkexpr(B_pos)), mkexpr(B_byte));
23967 store(mkexpr(t1), mkexpr(A_byte));
23968 #endif
23970 break;
23973 case 0x0D: {
23974 /* SDR rt, offset(base) - MIPS64 */
23975 vassert(mode64);
23976 DIP("sdr r%u, %u(r%u)", rt, imm, rs);
23977 IRTemp A_byte = newTemp(Ity_I8);
23978 IRTemp B_byte = newTemp(Ity_I8);
23979 IRTemp C_byte = newTemp(Ity_I8);
23980 IRTemp D_byte = newTemp(Ity_I8);
23981 IRTemp E_byte = newTemp(Ity_I8);
23982 IRTemp F_byte = newTemp(Ity_I8);
23983 IRTemp G_byte = newTemp(Ity_I8);
23984 IRTemp H_byte = newTemp(Ity_I8);
23985 IRTemp B_pos = newTemp(Ity_I64);
23986 IRTemp C_pos = newTemp(Ity_I64);
23987 IRTemp D_pos = newTemp(Ity_I64);
23988 IRTemp E_pos = newTemp(Ity_I64);
23989 IRTemp F_pos = newTemp(Ity_I64);
23990 IRTemp G_pos = newTemp(Ity_I64);
23992 /* H byte */
23993 assign(H_byte, getByteFromReg(rt, 0));
23994 /* G byte */
23995 assign(G_byte, getByteFromReg(rt, 1));
23996 /* F byte */
23997 assign(F_byte, getByteFromReg(rt, 2));
23998 /* E byte */
23999 assign(E_byte, getByteFromReg(rt, 3));
24000 /* D byte */
24001 assign(D_byte, getByteFromReg(rt, 4));
24002 /* C byte */
24003 assign(C_byte, getByteFromReg(rt, 5));
24004 /* B byte */
24005 assign(B_byte, getByteFromReg(rt, 6));
24006 /* A byte */
24007 assign(A_byte, getByteFromReg(rt, 7));
24009 /* t1 = addr */
24010 t1 = newTemp(Ity_I64);
24011 assign(t1, binop(Iop_Add64, getIReg(rs), mkU64(extend_s_16to64(imm))));
24013 /* t2 = word addr */
24014 t2 = newTemp(Ity_I64);
24015 assign(t2, binop(Iop_And64, mkexpr(t1), mkU64(0xFFFFFFFFFFFFFFF8ULL)));
24017 /* t3 = addr mod 7 */
24018 t3 = newTemp(Ity_I64);
24019 assign(t3, binop(Iop_And64, mkexpr(t1), mkU64(0x7)));
24021 #if defined (_MIPSEL)
24022 /* Calculate X_byte position. */
24023 assign(B_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkU64(0x1), mkexpr(t3)),
24024 mkU64(0x0),
24025 mkU64(0x6)));
24027 assign(C_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkU64(0x2), mkexpr(t3)),
24028 mkU64(0x0),
24029 mkU64(0x5)));
24031 assign(D_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkU64(0x3), mkexpr(t3)),
24032 mkU64(0x0),
24033 mkU64(0x4)));
24035 assign(E_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkU64(0x4), mkexpr(t3)),
24036 mkU64(0x0),
24037 mkU64(0x3)));
24039 assign(F_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkU64(0x5), mkexpr(t3)),
24040 mkU64(0x0),
24041 mkU64(0x2)));
24043 assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x7)),
24044 mkU64(0x0),
24045 mkU64(0x1)));
24047 /* Store X_byte on the right place. */
24048 store(binop(Iop_Add64, mkexpr(t2), mkU64(0x7)), mkexpr(A_byte));
24049 store(binop(Iop_Add64, mkexpr(t1), mkexpr(B_pos)), mkexpr(B_byte));
24050 store(binop(Iop_Add64, mkexpr(t1), mkexpr(C_pos)), mkexpr(C_byte));
24051 store(binop(Iop_Add64, mkexpr(t1), mkexpr(D_pos)), mkexpr(D_byte));
24052 store(binop(Iop_Add64, mkexpr(t1), mkexpr(E_pos)), mkexpr(E_byte));
24053 store(binop(Iop_Add64, mkexpr(t1), mkexpr(F_pos)), mkexpr(F_byte));
24054 store(binop(Iop_Add64, mkexpr(t1), mkexpr(G_pos)), mkexpr(G_byte));
24055 store(mkexpr(t1), mkexpr(H_byte));
24057 #else /* _MIPSEB */
24058 /* Calculate X_byte position. */
24059 assign(B_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkU64(0x5), mkexpr(t3)),
24060 mkU64(0x6),
24061 mkU64(0x0)));
24063 assign(C_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkU64(0x4), mkexpr(t3)),
24064 mkU64(0x5),
24065 mkU64(0x0)));
24067 assign(D_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkU64(0x3), mkexpr(t3)),
24068 mkU64(0x4),
24069 mkU64(0x0)));
24071 assign(E_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkU64(0x2), mkexpr(t3)),
24072 mkU64(0x3),
24073 mkU64(0x0)));
24075 assign(F_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkU64(0x1), mkexpr(t3)),
24076 mkU64(0x2),
24077 mkU64(0x0)));
24079 assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x0)),
24080 mkU64(0x0),
24081 mkU64(0x1)));
24083 /* Store X_byte on the right place. */
24084 store(mkexpr(t2), mkexpr(A_byte));
24085 store(binop(Iop_Sub64, mkexpr(t1), mkexpr(B_pos)), mkexpr(B_byte));
24086 store(binop(Iop_Sub64, mkexpr(t1), mkexpr(C_pos)), mkexpr(C_byte));
24087 store(binop(Iop_Sub64, mkexpr(t1), mkexpr(D_pos)), mkexpr(D_byte));
24088 store(binop(Iop_Sub64, mkexpr(t1), mkexpr(E_pos)), mkexpr(E_byte));
24089 store(binop(Iop_Sub64, mkexpr(t1), mkexpr(F_pos)), mkexpr(F_byte));
24090 store(binop(Iop_Sub64, mkexpr(t1), mkexpr(G_pos)), mkexpr(G_byte));
24091 store(mkexpr(t1), mkexpr(H_byte));
24092 #endif
24093 break;
24096 case 0x0E: /* SWR */
24097 DIP("swr r%u, %u(r%u)", rt, imm, rs);
24099 if (mode64) {
24100 IRTemp E_byte = newTemp(Ity_I8);
24101 IRTemp F_byte = newTemp(Ity_I8);
24102 IRTemp G_byte = newTemp(Ity_I8);
24103 IRTemp H_byte = newTemp(Ity_I8);
24104 IRTemp F_pos = newTemp(Ity_I64);
24105 IRTemp G_pos = newTemp(Ity_I64);
24107 /* H byte */
24108 assign(H_byte, getByteFromReg(rt, 0));
24109 /* G byte */
24110 assign(G_byte, getByteFromReg(rt, 1));
24111 /* F byte */
24112 assign(F_byte, getByteFromReg(rt, 2));
24113 /* E byte */
24114 assign(E_byte, getByteFromReg(rt, 3));
24116 /* t1 = addr */
24117 t1 = newTemp(Ity_I64);
24118 assign(t1, binop(Iop_Add64, getIReg(rs), mkU64(extend_s_16to64(imm))));
24120 /* t2 = word addr */
24121 t2 = newTemp(Ity_I64);
24122 assign(t2, binop(Iop_And64, mkexpr(t1), mkU64(0xFFFFFFFFFFFFFFFCULL)));
24124 /* t3 = addr mod 4 */
24125 t3 = newTemp(Ity_I64);
24126 assign(t3, binop(Iop_And64, mkexpr(t1), mkU64(0x3)));
24128 #if defined (_MIPSEL)
24129 /* Calculate X_byte position. */
24130 assign(F_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x0)),
24131 mkU64(0x2),
24132 mkU64(0x3)));
24134 assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x3)),
24135 mkU64(0x0),
24136 mkU64(0x1)));
24138 /* Store X_byte on the right place. */
24139 store(binop(Iop_Add64, mkexpr(t2), mkU64(0x3)), mkexpr(E_byte));
24140 store(binop(Iop_Add64, mkexpr(t2), mkexpr(F_pos)), mkexpr(F_byte));
24141 store(binop(Iop_Add64, mkexpr(t1), mkexpr(G_pos)), mkexpr(G_byte));
24142 store(mkexpr(t1), mkexpr(H_byte));
24144 #else /* _MIPSEB */
24145 /* Calculate X_byte position. */
24146 assign(F_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x3)),
24147 mkU64(0x1),
24148 mkU64(0x0)));
24150 assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x0)),
24151 mkU64(0x0),
24152 mkU64(0x1)));
24154 /* Store X_byte on the right place. */
24155 store(mkexpr(t2), mkexpr(E_byte));
24156 store(binop(Iop_Add64, mkexpr(t2), mkexpr(F_pos)), mkexpr(F_byte));
24157 store(binop(Iop_Sub64, mkexpr(t1), mkexpr(G_pos)), mkexpr(G_byte));
24158 store(mkexpr(t1), mkexpr(H_byte));
24159 #endif
24160 } else {
24161 IRTemp E_byte = newTemp(Ity_I8);
24162 IRTemp F_byte = newTemp(Ity_I8);
24163 IRTemp G_byte = newTemp(Ity_I8);
24164 IRTemp H_byte = newTemp(Ity_I8);
24165 IRTemp F_pos = newTemp(Ity_I32);
24166 IRTemp G_pos = newTemp(Ity_I32);
24168 /* H byte */
24169 assign(H_byte, getByteFromReg(rt, 0));
24170 /* G byte */
24171 assign(G_byte, getByteFromReg(rt, 1));
24172 /* F byte */
24173 assign(F_byte, getByteFromReg(rt, 2));
24174 /* E byte */
24175 assign(E_byte, getByteFromReg(rt, 3));
24177 /* t1 = addr */
24178 t1 = newTemp(Ity_I32);
24179 assign(t1, binop(Iop_Add32, getIReg(rs), mkU32(extend_s_16to32(imm))));
24181 /* t2 = word addr */
24182 t2 = newTemp(Ity_I32);
24183 assign(t2, binop(Iop_And32, mkexpr(t1), mkU32(0xFFFFFFFCULL)));
24185 /* t3 = addr mod 4 */
24186 t3 = newTemp(Ity_I32);
24187 assign(t3, binop(Iop_And32, mkexpr(t1), mkU32(0x3)));
24189 #if defined (_MIPSEL)
24190 /* Calculate X_byte position. */
24191 assign(F_pos, IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t3), mkU32(0x0)),
24192 mkU32(0x2),
24193 mkU32(0x3)));
24195 assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t3), mkU32(0x3)),
24196 mkU32(0x0),
24197 mkU32(0x1)));
24199 /* Store X_byte on the right place. */
24200 store(binop(Iop_Add32, mkexpr(t2), mkU32(0x3)), mkexpr(E_byte));
24201 store(binop(Iop_Add32, mkexpr(t2), mkexpr(F_pos)), mkexpr(F_byte));
24202 store(binop(Iop_Add32, mkexpr(t1), mkexpr(G_pos)), mkexpr(G_byte));
24203 store(mkexpr(t1), mkexpr(H_byte));
24205 #else /* _MIPSEB */
24206 /* Calculate X_byte position. */
24207 assign(F_pos, IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t3), mkU32(0x3)),
24208 mkU32(0x1),
24209 mkU32(0x0)));
24211 assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t3), mkU32(0x0)),
24212 mkU32(0x0),
24213 mkU32(0x1)));
24215 /* Store X_byte on the right place. */
24216 store(mkexpr(t2), mkexpr(E_byte));
24217 store(binop(Iop_Add32, mkexpr(t2), mkexpr(F_pos)), mkexpr(F_byte));
24218 store(binop(Iop_Sub32, mkexpr(t1), mkexpr(G_pos)), mkexpr(G_byte));
24219 store(mkexpr(t1), mkexpr(H_byte));
24220 #endif
24223 break;
24226 return 0;
24229 static UInt disInstr_MIPS_WRK_30(UInt cins, const VexArchInfo* archinfo,
24230 const VexAbiInfo* abiinfo, DisResult* dres,
24231 IRStmt** bstmt)
24233 IRTemp t0, t1 = 0, t2, t3, t4, t5;
24234 UInt opcode, rs, rt, rd, ft, function, imm, instr_index;
24236 opcode = get_opcode(cins);
24237 imm = get_imm(cins);
24238 rs = get_rs(cins);
24239 rt = get_rt(cins);
24240 rd = get_rd(cins);
24241 ft = get_ft(cins);
24243 instr_index = get_instr_index(cins);
24244 function = get_function(cins);
24245 IRType ty = mode64 ? Ity_I64 : Ity_I32;
24247 switch (opcode & 0x0F) {
24248 case 0x00: /* LL */
24249 DIP("ll r%u, %u(r%u)", rt, imm, rs);
24250 LOAD_STORE_PATTERN;
24252 if (abiinfo->guest__use_fallback_LLSC) {
24253 t2 = newTemp(ty);
24254 assign(t2, mkWidenFrom32(ty, load(Ity_I32, mkexpr(t1)), True));
24255 putLLaddr(mkexpr(t1));
24256 putLLdata(mkexpr(t2));
24257 putIReg(rt, mkexpr(t2));
24258 } else {
24259 t2 = newTemp(Ity_I32);
24260 stmt(IRStmt_LLSC(MIPS_IEND, t2, mkexpr(t1), NULL));
24261 putIReg(rt, mkWidenFrom32(ty, mkexpr(t2), True));
24264 break;
24266 case 0x01: /* LWC1 */
24267 /* Load Word to Floating Point - LWC1 (MIPS32) */
24268 DIP("lwc1 f%u, %u(r%u)", ft, imm, rs);
24269 LOAD_STORE_PATTERN;
24271 if (fp_mode64) {
24272 t0 = newTemp(Ity_F32);
24273 t2 = newTemp(Ity_I64);
24274 assign(t0, load(Ity_F32, mkexpr(t1)));
24275 assign(t2, mkWidenFrom32(Ity_I64, unop(Iop_ReinterpF32asI32,
24276 mkexpr(t0)), True));
24277 putDReg(ft, unop(Iop_ReinterpI64asF64, mkexpr(t2)));
24278 } else {
24279 putFReg(ft, load(Ity_F32, mkexpr(t1)));
24282 break;
24284 case 0x02: /* Branch on Bit Clear - BBIT0; Cavium OCTEON */
24286 /* Cavium Specific instructions. */
24287 if (VEX_MIPS_COMP_ID(archinfo->hwcaps) == VEX_PRID_COMP_CAVIUM) {
24288 DIP("bbit0 r%u, 0x%x, %x", rs, rt, imm);
24289 t0 = newTemp(Ity_I32);
24290 t1 = newTemp(Ity_I32);
24291 assign(t0, mkU32(0x1));
24292 assign(t1, binop(Iop_Shl32, mkexpr(t0), mkU8(rt)));
24293 dis_branch(False, binop(Iop_CmpEQ32,
24294 binop(Iop_And32,
24295 mkexpr(t1),
24296 mkNarrowTo32(ty, getIReg(rs))),
24297 mkU32(0x0)),
24298 imm, bstmt);
24299 } else if (archinfo->hwcaps & VEX_MIPS_CPU_ISA_M32R6) { /* BC */
24300 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
24301 DIP("bc %x", instr_index & 0x3FFFFFF);
24303 if (mode64) {
24304 t0 = newTemp(Ity_I64);
24305 assign(t0, mkU64(guest_PC_curr_instr +
24306 ((extend_s_26to64(instr_index & 0x3FFFFFF) + 1 ) << 2)));
24307 } else {
24308 t0 = newTemp(Ity_I32);
24309 assign(t0, mkU32(guest_PC_curr_instr +
24310 ((extend_s_26to32(instr_index & 0x3FFFFFF) + 1) << 2)));
24313 putPC(mkexpr(t0));
24314 dres->whatNext = Dis_StopHere;
24315 dres->jk_StopHere = Ijk_Boring;
24316 } else {
24317 ILLEGAL_INSTRUCTON;
24318 break;
24320 } else {
24321 return -1;
24324 break;
24326 case 0x03: /* PREF */
24327 DIP("pref");
24328 break;
24330 case 0x04: /* Load Linked Doubleword - LLD; MIPS64 */
24331 DIP("lld r%u, %u(r%u)", rt, imm, rs);
24333 if (mode64) {
24334 LOAD_STORE_PATTERN;
24335 t2 = newTemp(Ity_I64);
24337 if (abiinfo->guest__use_fallback_LLSC) {
24338 assign(t2, load(Ity_I64, mkexpr(t1)));
24339 putLLaddr(mkexpr(t1));
24340 putLLdata(mkexpr(t2));
24341 } else {
24342 stmt(IRStmt_LLSC(MIPS_IEND, t2, mkexpr(t1), NULL));
24345 putIReg(rt, mkexpr(t2));
24346 } else {
24347 ILLEGAL_INSTRUCTON
24350 break;
24352 case 0x05: /* Load Doubleword to Floating Point - LDC1 (MIPS32) */
24353 DIP("ldc1 f%u, %u(%u)", rt, imm, rs);
24354 LOAD_STORE_PATTERN;
24355 putDReg(ft, load(Ity_F64, mkexpr(t1)));
24356 break;
24358 case 0x06: /* Branch on Bit Clear Plus 32 - BBIT032; Cavium OCTEON */
24360 /* Cavium Specific instructions. */
24361 if (VEX_MIPS_COMP_ID(archinfo->hwcaps) == VEX_PRID_COMP_CAVIUM) {
24362 DIP("bbit032 r%u, 0x%x, %x", rs, rt, imm);
24363 t0 = newTemp(Ity_I64);
24364 t1 = newTemp(Ity_I8); /* Shift. */
24365 t2 = newTemp(Ity_I64);
24366 assign(t0, mkU64(0x1));
24367 assign(t1, binop(Iop_Add8, mkU8(rt), mkU8(32)));
24368 assign(t2, binop(Iop_Shl64, mkexpr(t0), mkexpr(t1)));
24369 dis_branch(False, binop(Iop_CmpEQ64,
24370 binop(Iop_And64,
24371 mkexpr(t2),
24372 getIReg(rs)),
24373 mkU64(0x0)),
24374 imm, bstmt);
24375 } else if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
24376 if (rs == 0) { /* JIC */
24377 DIP("jic r%u, %u", rt, instr_index & 0xFFFF);
24379 if (mode64) {
24380 t0 = newTemp(Ity_I64);
24381 assign(t0, binop(Iop_Add64, getIReg(rt),
24382 mkU64(extend_s_16to64((instr_index & 0xFFFF)))));
24383 } else {
24384 t0 = newTemp(Ity_I32);
24385 assign(t0, binop(Iop_Add32, getIReg(rt),
24386 mkU32(extend_s_16to32((instr_index & 0xFFFF)))));
24389 putPC(mkexpr(t0));
24390 dres->whatNext = Dis_StopHere;
24391 dres->jk_StopHere = Ijk_Boring;
24392 } else { /* BEQZC */
24393 DIP("beqzc r%u, %u", rs, imm);
24394 dres->jk_StopHere = Ijk_Boring;
24395 dres->whatNext = Dis_StopHere;
24396 ULong branch_offset;
24397 t0 = newTemp(Ity_I1);
24399 if (mode64) {
24400 branch_offset = extend_s_23to64((instr_index & 0x1fffff) << 2);
24401 assign(t0, binop(Iop_CmpEQ64, getIReg(rs), mkU64(0x0)));
24402 stmt(IRStmt_Exit(mkexpr(t0), Ijk_Boring,
24403 IRConst_U64(guest_PC_curr_instr + 4 + branch_offset),
24404 OFFB_PC));
24405 putPC(mkU64(guest_PC_curr_instr + 4));
24406 } else {
24407 branch_offset = extend_s_23to32((instr_index & 0x1fffff) << 2);
24408 assign(t0, binop(Iop_CmpEQ32, getIReg(rs), mkU32(0x0)));
24409 stmt(IRStmt_Exit(mkexpr(t0), Ijk_Boring,
24410 IRConst_U32(guest_PC_curr_instr + 4 +
24411 (UInt) branch_offset), OFFB_PC));
24412 putPC(mkU32(guest_PC_curr_instr + 4));
24415 } else {
24416 ILLEGAL_INSTRUCTON
24419 break;
24421 case 0x07: /* Load Doubleword - LD; MIPS64 */
24422 DIP("ld r%u, %u(r%u)", rt, imm, rs);
24423 LOAD_STORE_PATTERN;
24424 putIReg(rt, load(Ity_I64, mkexpr(t1)));
24425 break;
24427 case 0x08: /* SC */
24428 DIP("sc r%u, %u(r%u)", rt, imm, rs);
24429 t2 = newTemp(Ity_I1);
24430 LOAD_STORE_PATTERN;
24432 if (abiinfo->guest__use_fallback_LLSC) {
24433 t3 = newTemp(Ity_I32);
24434 assign(t2, binop(mode64 ? Iop_CmpNE64 : Iop_CmpNE32,
24435 mkexpr(t1), getLLaddr()));
24436 assign(t3, mkNarrowTo32(ty, getIReg(rt)));
24437 putLLaddr(LLADDR_INVALID);
24438 putIReg(rt, getIReg(0));
24440 mips_next_insn_if(mkexpr(t2));
24442 t4 = newTemp(Ity_I32);
24443 t5 = newTemp(Ity_I32);
24445 assign(t5, mkNarrowTo32(ty, getLLdata()));
24447 stmt(IRStmt_CAS(mkIRCAS(IRTemp_INVALID, t4, /* old_mem */
24448 MIPS_IEND, mkexpr(t1), /* addr */
24449 NULL, mkexpr(t5), /* expected value */
24450 NULL, mkexpr(t3) /* new value */)));
24452 putIReg(rt, unop(mode64 ? Iop_1Uto64 : Iop_1Uto32,
24453 binop(Iop_CmpEQ32, mkexpr(t4), mkexpr(t5))));
24454 } else {
24455 stmt(IRStmt_LLSC(MIPS_IEND, t2, mkexpr(t1),
24456 mkNarrowTo32(ty, getIReg(rt))));
24457 putIReg(rt, unop(mode64 ? Iop_1Uto64 : Iop_1Uto32, mkexpr(t2)));
24460 break;
24462 case 0x09: /* SWC1 */
24463 DIP("swc1 f%u, %u(r%u)", ft, imm, rs);
24465 if (fp_mode64) {
24466 t0 = newTemp(Ity_I64);
24467 t2 = newTemp(Ity_I32);
24468 LOAD_STORE_PATTERN;
24469 assign(t0, unop(Iop_ReinterpF64asI64, getFReg(ft)));
24470 assign(t2, unop(Iop_64to32, mkexpr(t0)));
24471 store(mkexpr(t1), unop(Iop_ReinterpI32asF32, mkexpr(t2)));
24472 } else {
24473 LOAD_STORE_PATTERN;
24474 store(mkexpr(t1), getFReg(ft));
24477 break;
24479 case 0x0A: /* Branch on Bit Set - BBIT1; Cavium OCTEON */
24481 /* Cavium Specific instructions. */
24482 if (VEX_MIPS_COMP_ID(archinfo->hwcaps) == VEX_PRID_COMP_CAVIUM) {
24483 DIP("bbit1 r%u, 0x%x, %x", rs, rt, imm);
24484 t0 = newTemp(Ity_I32);
24485 t1 = newTemp(Ity_I32);
24486 assign(t0, mkU32(0x1));
24487 assign(t1, binop(Iop_Shl32, mkexpr(t0), mkU8(rt)));
24488 dis_branch(False, binop(Iop_CmpNE32,
24489 binop(Iop_And32,
24490 mkexpr(t1),
24491 mkNarrowTo32(ty, getIReg(rs))),
24492 mkU32(0x0)),
24493 imm, bstmt);
24494 } else if (archinfo->hwcaps & VEX_MIPS_CPU_ISA_M32R6) {/* BALC */
24495 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
24496 DIP("balc %x", instr_index & 0x3FFFFFF);
24498 if (mode64) {
24499 t0 = newTemp(Ity_I64);
24500 assign(t0, mkU64(guest_PC_curr_instr + ((extend_s_26to64(
24501 instr_index & 0x3FFFFFF) + 1) << 2)));
24502 putIReg(31, mkU64(guest_PC_curr_instr + 4));
24503 } else {
24504 t0 = newTemp(Ity_I32);
24505 assign(t0, mkU32(guest_PC_curr_instr + ((extend_s_26to32(
24506 instr_index & 0x3FFFFFF) + 1) << 2)));
24507 putIReg(31, mkU32(guest_PC_curr_instr + 4));
24510 putPC(mkexpr(t0));
24511 dres->whatNext = Dis_StopHere;
24512 dres->jk_StopHere = Ijk_Call;
24513 } else {
24514 ILLEGAL_INSTRUCTON;
24515 break;
24517 } else {
24518 return -1;
24521 break;
24523 case 0x0B: /* PCREL */
24524 if (rt == 0x1E) { /* AUIPC */
24525 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
24526 DIP("auipc r%u, %u", rs, imm);
24528 if (mode64) {
24529 putIReg(rs, mkU64(guest_PC_curr_instr + (imm << 16)));
24530 } else {
24531 putIReg(rs, mkU32(guest_PC_curr_instr + (imm << 16)));
24533 } else {
24534 ILLEGAL_INSTRUCTON;
24537 break;
24538 } else if (rt == 0x1F) { /* ALUIPC */
24539 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
24540 DIP("aluipc r%u, %u", rs, imm);
24542 if (mode64) {
24543 putIReg(rs, mkU64((~0x0FFFFULL) &
24544 (guest_PC_curr_instr + extend_s_32to64(imm << 16))));
24545 } else {
24546 putIReg(rs, mkU32((~0x0FFFFULL) &
24547 (guest_PC_curr_instr + (imm << 16))));
24549 } else {
24550 ILLEGAL_INSTRUCTON;
24553 break;
24554 } else if ((rt & 0x18) == 0) { /* ADDIUPC */
24555 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
24556 DIP("addiupc r%u, %u", rs, instr_index & 0x7FFFF);
24558 if (mode64) {
24559 putIReg(rs, mkU64(guest_PC_curr_instr +
24560 (extend_s_19to64(instr_index & 0x7FFFF) << 2)));
24561 } else {
24562 putIReg(rs, mkU32(guest_PC_curr_instr +
24563 (extend_s_19to32(instr_index & 0x7FFFF) << 2)));
24565 } else {
24566 ILLEGAL_INSTRUCTON;
24569 break;
24570 } else if ((rt & 0x18) == 8) { /* LWPC */
24571 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
24572 DIP("lwpc r%u, %x", rs, instr_index & 0x7FFFF);
24574 if (mode64) {
24575 t1 = newTemp(Ity_I64);
24576 assign(t1, mkU64(guest_PC_curr_instr +
24577 (extend_s_19to64(instr_index & 0x7FFFF) << 2)));
24578 putIReg(rs, unop(Iop_32Sto64, load(Ity_I32, mkexpr(t1))));
24579 } else {
24580 t1 = newTemp(Ity_I32);
24581 assign(t1, mkU32(guest_PC_curr_instr +
24582 (extend_s_19to32(instr_index & 0x7FFFF) << 2)));
24583 putIReg(rs, load(Ity_I32, mkexpr(t1)));
24585 } else {
24586 ILLEGAL_INSTRUCTON;
24589 break;
24590 } else if ((rt & 0x18) == 16) { /* LWUPC */
24591 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
24592 DIP("lwupc r%u, %x", rs, instr_index & 0x7FFFF);
24594 if (mode64) {
24595 t1 = newTemp(Ity_I64);
24596 assign(t1, mkU64(guest_PC_curr_instr +
24597 (extend_s_19to64(instr_index & 0x7FFFF) << 2)));
24598 putIReg(rs, unop(Iop_32Uto64, load(Ity_I32, mkexpr(t1))));
24599 } else {
24600 t1 = newTemp(Ity_I32);
24601 assign(t1, mkU32(guest_PC_curr_instr +
24602 (extend_s_19to32(instr_index & 0x7FFFF) << 2)));
24603 putIReg(rs, load(Ity_I32, mkexpr(t1)));
24605 } else {
24606 ILLEGAL_INSTRUCTON
24609 break;
24610 } else if ((rt & 0x1C) == 0x18) { /* LDPC */
24611 if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
24612 DIP("ldpc r%u, %x", rs, instr_index & 0x3FFFF);
24613 t1 = newTemp(Ity_I64);
24614 assign(t1, mkU64(guest_PC_curr_instr +
24615 (extend_s_18to64(instr_index & 0x3FFFF) << 3)));
24616 putIReg(rs, load(Ity_I64, mkexpr(t1)));
24617 } else {
24618 ILLEGAL_INSTRUCTON
24621 break;
24622 } else {
24623 return -1;
24626 if (0x3B == function &&
24627 (VEX_MIPS_COMP_ID(archinfo->hwcaps) == VEX_PRID_COMP_BROADCOM)) {
24628 /*RDHWR*/
24629 DIP("rdhwr r%u, r%u", rt, rd);
24631 if (rd == 29) {
24632 putIReg(rt, getULR());
24633 } else
24634 return -1;
24636 break;
24637 } else {
24638 return -1;
24641 case 0x0C: /* Store Conditional Doubleword - SCD; MIPS64 */
24642 DIP("scd r%u, %u(r%u)", rt, imm, rs);
24644 if (mode64) {
24645 t2 = newTemp(Ity_I1);
24646 LOAD_STORE_PATTERN;
24648 if (abiinfo->guest__use_fallback_LLSC) {
24649 t3 = newTemp(Ity_I64);
24650 assign(t2, binop(Iop_CmpNE64, mkexpr(t1), getLLaddr()));
24651 assign(t3, getIReg(rt));
24652 putLLaddr(LLADDR_INVALID);
24653 putIReg(rt, getIReg(0));
24655 mips_next_insn_if(mkexpr(t2));
24657 t4 = newTemp(Ity_I64);
24658 t5 = newTemp(Ity_I64);
24660 assign(t5, getLLdata());
24662 stmt(IRStmt_CAS(mkIRCAS(IRTemp_INVALID, t4, /* old_mem */
24663 MIPS_IEND, mkexpr(t1), /* addr */
24664 NULL, mkexpr(t5), /* expected value */
24665 NULL, mkexpr(t3) /* new value */)));
24667 putIReg(rt, unop(Iop_1Uto64,
24668 binop(Iop_CmpEQ64, mkexpr(t4), mkexpr(t5))));
24669 } else {
24670 stmt(IRStmt_LLSC(MIPS_IEND, t2, mkexpr(t1), getIReg(rt)));
24671 putIReg(rt, unop(Iop_1Uto64, mkexpr(t2)));
24673 } else {
24674 ILLEGAL_INSTRUCTON
24677 break;
24679 case 0x0D: /* Store Doubleword from Floating Point - SDC1 */
24680 DIP("sdc1 f%u, %u(%u)", ft, imm, rs);
24681 LOAD_STORE_PATTERN;
24682 store(mkexpr(t1), getDReg(ft));
24683 break;
24685 case 0x0E: /* Branch on Bit Set Plus 32 - BBIT132; Cavium OCTEON */
24687 /* Cavium Specific instructions. */
24688 if (VEX_MIPS_COMP_ID(archinfo->hwcaps) == VEX_PRID_COMP_CAVIUM) {
24689 DIP("bbit132 r%u, 0x%x, %x", rs, rt, imm);
24690 t0 = newTemp(Ity_I64);
24691 t1 = newTemp(Ity_I8); /* Shift. */
24692 t2 = newTemp(Ity_I64);
24693 assign(t0, mkU64(0x1));
24694 assign(t1, binop(Iop_Add8, mkU8(rt), mkU8(32)));
24695 assign(t2, binop(Iop_Shl64, mkexpr(t0), mkexpr(t1)));
24696 dis_branch(False, binop(Iop_CmpNE64,
24697 binop(Iop_And64,
24698 mkexpr(t2),
24699 getIReg(rs)),
24700 mkU64(0x0)),
24701 imm, bstmt);
24702 } else if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
24703 if (rs == 0) {/* JIALC */
24704 DIP("jialc r%u, %u", rt, instr_index & 0xFFFF);
24706 if (rs) return -1;
24708 if (mode64) {
24709 t0 = newTemp(Ity_I64);
24710 assign(t0, binop(Iop_Add64, getIReg(rt),
24711 mkU64(extend_s_16to64((instr_index & 0xFFFF)))));
24712 putIReg(31, mkU64(guest_PC_curr_instr + 4));
24713 } else {
24714 t0 = newTemp(Ity_I32);
24715 assign(t0, binop(Iop_Add32, getIReg(rt),
24716 mkU32(extend_s_16to32((instr_index & 0xFFFF)))));
24717 putIReg(31, mkU32(guest_PC_curr_instr + 4));
24720 putPC(mkexpr(t0));
24721 dres->whatNext = Dis_StopHere;
24722 dres->jk_StopHere = Ijk_Call;
24723 } else { /* BNEZC */
24724 DIP("bnezc r%u, %u", rs, imm);
24725 dres->jk_StopHere = Ijk_Boring;
24726 dres->whatNext = Dis_StopHere;
24727 ULong branch_offset;
24728 t0 = newTemp(Ity_I1);
24730 if (mode64) {
24731 branch_offset = extend_s_23to64((instr_index & 0x1fffff) << 2);
24732 assign(t0, unop(Iop_Not1, binop(Iop_CmpEQ64, getIReg(rs), mkU64(0x0))));
24733 stmt(IRStmt_Exit(mkexpr(t0), Ijk_Boring,
24734 IRConst_U64(guest_PC_curr_instr + 4 + branch_offset),
24735 OFFB_PC));
24736 putPC(mkU64(guest_PC_curr_instr + 4));
24737 } else {
24738 branch_offset = extend_s_23to32((instr_index & 0x1fffff) << 2);
24739 assign(t0, unop(Iop_Not1, binop(Iop_CmpEQ32, getIReg(rs), mkU32(0x0))));
24740 stmt(IRStmt_Exit(mkexpr(t0), Ijk_Boring,
24741 IRConst_U32(guest_PC_curr_instr + 4 +
24742 (UInt) branch_offset), OFFB_PC));
24743 putPC(mkU32(guest_PC_curr_instr + 4));
24746 } else {
24747 return -1;
24750 break;
24752 case 0x0F: /* Store Doubleword - SD; MIPS64 */
24753 DIP("sd r%u, %u(r%u)", rt, imm, rs);
24754 LOAD_STORE_PATTERN;
24755 store(mkexpr(t1), getIReg(rt));
24756 break;
24758 default:
24759 return -1;
24762 return 0;
24765 static DisResult disInstr_MIPS_WRK ( Long delta64,
24766 const VexArchInfo* archinfo,
24767 const VexAbiInfo* abiinfo,
24768 Bool sigill_diag )
24771 UInt opcode, cins, result;
24773 DisResult dres;
24775 static IRExpr *lastn = NULL; /* last jump addr */
24776 static IRStmt *bstmt = NULL; /* branch (Exit) stmt */
24778 /* The running delta */
24779 Int delta = (Int) delta64;
24781 /* Holds eip at the start of the insn, so that we can print
24782 consistent error messages for unimplemented insns. */
24783 Int delta_start = delta;
24785 /* Are we in a delay slot ? */
24786 Bool delay_slot_branch, likely_delay_slot, delay_slot_jump;
24788 /* Set result defaults. */
24789 dres.whatNext = Dis_Continue;
24790 dres.len = 0;
24791 dres.jk_StopHere = Ijk_INVALID;
24792 dres.hint = Dis_HintNone;
24794 delay_slot_branch = likely_delay_slot = delay_slot_jump = False;
24796 const UChar *code = guest_code + delta;
24797 cins = getUInt(code);
24798 opcode = get_opcode(cins);
24799 DIP("\t0x%llx:\t0x%08x\t", (Addr64)guest_PC_curr_instr, cins);
24801 if (delta != 0) {
24802 if (branch_or_jump(guest_code + delta - 4)) {
24803 if (lastn == NULL && bstmt == NULL) {
24804 vassert(0);
24805 } else {
24806 dres.whatNext = Dis_StopHere;
24808 if (lastn != NULL) {
24809 delay_slot_jump = True;
24810 } else if (bstmt != NULL) {
24811 delay_slot_branch = True;
24816 if (branch_or_link_likely(guest_code + delta - 4)) {
24817 likely_delay_slot = True;
24821 /* Spot "Special" instructions (see comment at top of file). */
24823 /* Spot the 16-byte preamble:
24824 ****mips32****
24825 "srl $0, $0, 13
24826 "srl $0, $0, 29
24827 "srl $0, $0, 3
24828 "srl $0, $0, 19
24830 ****mips64****
24831 dsll $0, $0, 3
24832 dsll $0, $0, 13
24833 dsll $0, $0, 29
24834 dsll $0, $0, 19 */
24836 UInt word1 = mode64 ? 0xF8 : 0x342;
24837 UInt word2 = mode64 ? 0x378 : 0x742;
24838 UInt word3 = mode64 ? 0x778 : 0xC2;
24839 UInt word4 = mode64 ? 0x4F8 : 0x4C2;
24841 if (getUInt(code + 0) == word1 && getUInt(code + 4) == word2 &&
24842 getUInt(code + 8) == word3 && getUInt(code + 12) == word4) {
24843 /* Got a "Special" instruction preamble. Which one is it? */
24844 if (getUInt(code + 16) == 0x01ad6825 /* or $13, $13, $13 */ ) {
24845 /* $11 = client_request ( $12 ) */
24846 DIP("$11 = client_request ( $12 )");
24848 if (mode64)
24849 putPC(mkU64(guest_PC_curr_instr + 20));
24850 else
24851 putPC(mkU32(guest_PC_curr_instr + 20));
24853 dres.jk_StopHere = Ijk_ClientReq;
24854 dres.whatNext = Dis_StopHere;
24856 goto decode_success;
24857 } else if (getUInt(code + 16) == 0x01ce7025 /* or $14, $14, $14 */ ) {
24858 /* $11 = guest_NRADDR */
24859 DIP("$11 = guest_NRADDR");
24860 dres.len = 20;
24861 delta += 20;
24863 if (mode64)
24864 putIReg(11, IRExpr_Get(offsetof(VexGuestMIPS64State,
24865 guest_NRADDR), Ity_I64));
24866 else
24867 putIReg(11, IRExpr_Get(offsetof(VexGuestMIPS32State,
24868 guest_NRADDR), Ity_I32));
24870 goto decode_success;
24871 } else if (getUInt(code + 16) == 0x01ef7825 /* or $15, $15, $15 */ ) {
24872 /* branch-and-link-to-noredir $25 */
24873 DIP("branch-and-link-to-noredir $25");
24875 if (mode64)
24876 putIReg(31, mkU64(guest_PC_curr_instr + 20));
24877 else
24878 putIReg(31, mkU32(guest_PC_curr_instr + 20));
24880 putPC(getIReg(25));
24881 dres.jk_StopHere = Ijk_NoRedir;
24882 dres.whatNext = Dis_StopHere;
24883 goto decode_success;
24884 } else if (getUInt(code + 16) == 0x016b5825 /* or $11,$11,$11 */ ) {
24885 /* IR injection */
24886 DIP("IR injection");
24887 #if defined (_MIPSEL)
24888 vex_inject_ir(irsb, Iend_LE);
24889 #elif defined (_MIPSEB)
24890 vex_inject_ir(irsb, Iend_BE);
24891 #endif
24893 if (mode64) {
24894 stmt(IRStmt_Put(offsetof(VexGuestMIPS64State, guest_CMSTART),
24895 mkU64(guest_PC_curr_instr)));
24896 stmt(IRStmt_Put(offsetof(VexGuestMIPS64State, guest_CMLEN),
24897 mkU64(20)));
24899 putPC(mkU64(guest_PC_curr_instr + 20));
24900 } else {
24901 stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_CMSTART),
24902 mkU32(guest_PC_curr_instr)));
24903 stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_CMLEN),
24904 mkU32(20)));
24906 putPC(mkU32(guest_PC_curr_instr + 20));
24909 dres.whatNext = Dis_StopHere;
24910 dres.jk_StopHere = Ijk_InvalICache;
24911 dres.len = 20;
24912 delta += 20;
24913 goto decode_success;
24916 /* We don't know what it is. Set opc1/opc2 so decode_failure
24917 can print the insn following the Special-insn preamble. */
24918 delta += 16;
24919 goto decode_failure;
24920 /*NOTREACHED*/
24924 switch (opcode & 0x30) {
24925 case 0x00:
24926 result = disInstr_MIPS_WRK_00(cins, archinfo, abiinfo,
24927 &dres, &bstmt, &lastn);
24929 if (result == -1) goto decode_failure;
24931 if (result == -2) goto decode_failure_dsp;
24933 break;
24935 case 0x10:
24937 result = disInstr_MIPS_WRK_10(cins, archinfo, abiinfo,
24938 &dres, &bstmt, &lastn);
24940 if (result == -1) goto decode_failure;
24942 if (result == -2) goto decode_failure_dsp;
24944 break;
24946 case 0x20:
24947 result = disInstr_MIPS_WRK_20(cins);
24949 if (result == -1) goto decode_failure;
24951 if (result == -2) goto decode_failure_dsp;
24953 break;
24955 case 0x30:
24956 result = disInstr_MIPS_WRK_30(cins, archinfo, abiinfo, &dres, &bstmt);
24958 if (result == -1) goto decode_failure;
24960 if (result == -2) goto decode_failure_dsp;
24962 break;
24964 decode_failure_dsp:
24965 vex_printf("Error occured while trying to decode MIPS32 DSP "
24966 "instruction.\nYour platform probably doesn't support "
24967 "MIPS32 DSP ASE.\n");
24968 decode_failure:
24970 /* All decode failures end up here. */
24971 if (sigill_diag)
24972 vex_printf("vex mips->IR: unhandled instruction bytes: "
24973 "0x%x 0x%x 0x%x 0x%x\n",
24974 (UInt) getIByte(delta_start + 0),
24975 (UInt) getIByte(delta_start + 1),
24976 (UInt) getIByte(delta_start + 2),
24977 (UInt) getIByte(delta_start + 3));
24979 /* Tell the dispatcher that this insn cannot be decoded, and so has
24980 not been executed, and (is currently) the next to be executed.
24981 EIP should be up-to-date since it made so at the start bnezof each
24982 insn, but nevertheless be paranoid and update it again right
24983 now. */
24984 if (mode64) {
24985 stmt(IRStmt_Put(offsetof(VexGuestMIPS64State, guest_PC),
24986 mkU64(guest_PC_curr_instr)));
24987 jmp_lit64(&dres, Ijk_NoDecode, guest_PC_curr_instr);
24988 } else {
24989 stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_PC),
24990 mkU32(guest_PC_curr_instr)));
24991 jmp_lit32(&dres, Ijk_NoDecode, guest_PC_curr_instr);
24994 dres.whatNext = Dis_StopHere;
24995 dres.len = 0;
24996 return dres;
24997 } /* switch (opc) for the main (primary) opcode switch. */
24999 /* All MIPS insn have 4 bytes */
25001 if (delay_slot_branch) {
25002 delay_slot_branch = False;
25003 stmt(bstmt);
25004 bstmt = NULL;
25006 if (mode64)
25007 putPC(mkU64(guest_PC_curr_instr + 4));
25008 else
25009 putPC(mkU32(guest_PC_curr_instr + 4));
25011 dres.jk_StopHere = is_Branch_or_Jump_and_Link(guest_code + delta - 4) ?
25012 Ijk_Call : Ijk_Boring;
25015 if (likely_delay_slot) {
25016 dres.jk_StopHere = Ijk_Boring;
25017 dres.whatNext = Dis_StopHere;
25018 putPC(lastn);
25019 lastn = NULL;
25022 if (delay_slot_jump) {
25023 putPC(lastn);
25024 lastn = NULL;
25025 dres.jk_StopHere = is_Branch_or_Jump_and_Link(guest_code + delta - 4) ?
25026 Ijk_Call : Ijk_Boring;
25029 decode_success:
25031 /* All decode successes end up here. */
25032 switch (dres.whatNext) {
25033 case Dis_Continue:
25034 if (mode64)
25035 putPC(mkU64(guest_PC_curr_instr + 4));
25036 else
25037 putPC(mkU32(guest_PC_curr_instr + 4));
25039 break;
25041 case Dis_StopHere:
25042 break;
25044 default:
25045 vassert(0);
25046 break;
25049 /* On MIPS we need to check if the last instruction in block is branch or
25050 jump. */
25051 if (((vex_control.guest_max_insns - 1) == (delta + 4) / 4)
25052 && (dres.whatNext != Dis_StopHere))
25053 if (branch_or_jump(guest_code + delta + 4)) {
25054 dres.whatNext = Dis_StopHere;
25055 dres.jk_StopHere = Ijk_Boring;
25056 if (mode64)
25057 putPC(mkU64(guest_PC_curr_instr + 4));
25058 else
25059 putPC(mkU32(guest_PC_curr_instr + 4));
25061 dres.len = 4;
25063 DIP("\n");
25065 return dres;
25069 /*------------------------------------------------------------*/
25070 /*--- Top-level fn ---*/
25071 /*------------------------------------------------------------*/
25073 /* Disassemble a single instruction into IR. The instruction
25074 is located in host memory at &guest_code[delta]. */
25075 DisResult disInstr_MIPS( IRSB* irsb_IN,
25076 const UChar* guest_code_IN,
25077 Long delta,
25078 Addr guest_IP,
25079 VexArch guest_arch,
25080 const VexArchInfo* archinfo,
25081 const VexAbiInfo* abiinfo,
25082 VexEndness host_endness_IN,
25083 Bool sigill_diag_IN )
25085 DisResult dres;
25086 /* Set globals (see top of this file) */
25087 vassert(guest_arch == VexArchMIPS32 || guest_arch == VexArchMIPS64);
25089 mode64 = guest_arch != VexArchMIPS32;
25090 fp_mode64 = abiinfo->guest_mips_fp_mode & 1;
25091 fp_mode64_fre = abiinfo->guest_mips_fp_mode & 2;
25092 has_msa = VEX_MIPS_PROC_MSA(archinfo->hwcaps);
25094 vassert(VEX_MIPS_HOST_FP_MODE(archinfo->hwcaps) >= fp_mode64);
25096 guest_code = guest_code_IN;
25097 irsb = irsb_IN;
25098 host_endness = host_endness_IN;
25099 #if defined(VGP_mips32_linux)
25100 guest_PC_curr_instr = (Addr32)guest_IP;
25101 #elif defined(VGP_mips64_linux)
25102 guest_PC_curr_instr = (Addr64)guest_IP;
25103 #endif
25105 dres = disInstr_MIPS_WRK(delta, archinfo, abiinfo, sigill_diag_IN);
25107 return dres;
25110 /*--------------------------------------------------------------------*/
25111 /*--- end guest_mips_toIR.c ---*/
25112 /*--------------------------------------------------------------------*/