#include "main_globals.h"
#include "guest_generic_bb_to_IR.h"
#include "guest_mips_defs.h"
+#include "mips_defs.h"
/*------------------------------------------------------------*/
/*--- Globals ---*/
static VexEndness host_endness;
/* Pointer to the guest code area. */
-static const UChar *guest_code;
+const UChar *guest_code;
/* CONST: The guest address for the instruction currently being
translated. */
#endif
/* MOD: The IRSB* into which we're generating code. */
-static IRSB *irsb;
+IRSB *irsb;
/* Is our guest binary 32 or 64bit? Set at each call to
disInstr_MIPS below. */
-static Bool mode64 = False;
+Bool mode64 = False;
/* CPU has FPU and 32 dbl. prec. FP registers. */
-static Bool fp_mode64 = False;
+ static Bool fp_mode64 = False;
/* FPU works in FRE mode */
static Bool fp_mode64_fre = False;
#define ONE_SINGLE 0x3F800000
#define ONE_DOUBLE 0x3FF0000000000000ULL
-/*------------------------------------------------------------*/
-/*--- Debugging output ---*/
-/*------------------------------------------------------------*/
-
-#define DIP(format, args...) \
- if (vex_traceflags & VEX_TRACE_FE) \
- vex_printf(format, ## args)
-
/*------------------------------------------------------------*/
/*--- Helper bits and pieces for deconstructing the ---*/
/*--- mips insn stream. ---*/
registers are accessed, but I don't think that ever happens on
MIPS. */
UInt ret;
- if (!mode64)
- switch (iregNo) {
- case 0:
- ret = offsetof(VexGuestMIPS32State, guest_r0); break;
- case 1:
- ret = offsetof(VexGuestMIPS32State, guest_r1); break;
- case 2:
- ret = offsetof(VexGuestMIPS32State, guest_r2); break;
- case 3:
- ret = offsetof(VexGuestMIPS32State, guest_r3); break;
- case 4:
- ret = offsetof(VexGuestMIPS32State, guest_r4); break;
- case 5:
- ret = offsetof(VexGuestMIPS32State, guest_r5); break;
- case 6:
- ret = offsetof(VexGuestMIPS32State, guest_r6); break;
- case 7:
- ret = offsetof(VexGuestMIPS32State, guest_r7); break;
- case 8:
- ret = offsetof(VexGuestMIPS32State, guest_r8); break;
- case 9:
- ret = offsetof(VexGuestMIPS32State, guest_r9); break;
- case 10:
- ret = offsetof(VexGuestMIPS32State, guest_r10); break;
- case 11:
- ret = offsetof(VexGuestMIPS32State, guest_r11); break;
- case 12:
- ret = offsetof(VexGuestMIPS32State, guest_r12); break;
- case 13:
- ret = offsetof(VexGuestMIPS32State, guest_r13); break;
- case 14:
- ret = offsetof(VexGuestMIPS32State, guest_r14); break;
- case 15:
- ret = offsetof(VexGuestMIPS32State, guest_r15); break;
- case 16:
- ret = offsetof(VexGuestMIPS32State, guest_r16); break;
- case 17:
- ret = offsetof(VexGuestMIPS32State, guest_r17); break;
- case 18:
- ret = offsetof(VexGuestMIPS32State, guest_r18); break;
- case 19:
- ret = offsetof(VexGuestMIPS32State, guest_r19); break;
- case 20:
- ret = offsetof(VexGuestMIPS32State, guest_r20); break;
- case 21:
- ret = offsetof(VexGuestMIPS32State, guest_r21); break;
- case 22:
- ret = offsetof(VexGuestMIPS32State, guest_r22); break;
- case 23:
- ret = offsetof(VexGuestMIPS32State, guest_r23); break;
- case 24:
- ret = offsetof(VexGuestMIPS32State, guest_r24); break;
- case 25:
- ret = offsetof(VexGuestMIPS32State, guest_r25); break;
- case 26:
- ret = offsetof(VexGuestMIPS32State, guest_r26); break;
- case 27:
- ret = offsetof(VexGuestMIPS32State, guest_r27); break;
- case 28:
- ret = offsetof(VexGuestMIPS32State, guest_r28); break;
- case 29:
- ret = offsetof(VexGuestMIPS32State, guest_r29); break;
- case 30:
- ret = offsetof(VexGuestMIPS32State, guest_r30); break;
- case 31:
- ret = offsetof(VexGuestMIPS32State, guest_r31); break;
- default:
- vassert(0);
- break;
- }
- else
- switch (iregNo) {
- case 0:
- ret = offsetof(VexGuestMIPS64State, guest_r0); break;
- case 1:
- ret = offsetof(VexGuestMIPS64State, guest_r1); break;
- case 2:
- ret = offsetof(VexGuestMIPS64State, guest_r2); break;
- case 3:
- ret = offsetof(VexGuestMIPS64State, guest_r3); break;
- case 4:
- ret = offsetof(VexGuestMIPS64State, guest_r4); break;
- case 5:
- ret = offsetof(VexGuestMIPS64State, guest_r5); break;
- case 6:
- ret = offsetof(VexGuestMIPS64State, guest_r6); break;
- case 7:
- ret = offsetof(VexGuestMIPS64State, guest_r7); break;
- case 8:
- ret = offsetof(VexGuestMIPS64State, guest_r8); break;
- case 9:
- ret = offsetof(VexGuestMIPS64State, guest_r9); break;
- case 10:
- ret = offsetof(VexGuestMIPS64State, guest_r10); break;
- case 11:
- ret = offsetof(VexGuestMIPS64State, guest_r11); break;
- case 12:
- ret = offsetof(VexGuestMIPS64State, guest_r12); break;
- case 13:
- ret = offsetof(VexGuestMIPS64State, guest_r13); break;
- case 14:
- ret = offsetof(VexGuestMIPS64State, guest_r14); break;
- case 15:
- ret = offsetof(VexGuestMIPS64State, guest_r15); break;
- case 16:
- ret = offsetof(VexGuestMIPS64State, guest_r16); break;
- case 17:
- ret = offsetof(VexGuestMIPS64State, guest_r17); break;
- case 18:
- ret = offsetof(VexGuestMIPS64State, guest_r18); break;
- case 19:
- ret = offsetof(VexGuestMIPS64State, guest_r19); break;
- case 20:
- ret = offsetof(VexGuestMIPS64State, guest_r20); break;
- case 21:
- ret = offsetof(VexGuestMIPS64State, guest_r21); break;
- case 22:
- ret = offsetof(VexGuestMIPS64State, guest_r22); break;
- case 23:
- ret = offsetof(VexGuestMIPS64State, guest_r23); break;
- case 24:
- ret = offsetof(VexGuestMIPS64State, guest_r24); break;
- case 25:
- ret = offsetof(VexGuestMIPS64State, guest_r25); break;
- case 26:
- ret = offsetof(VexGuestMIPS64State, guest_r26); break;
- case 27:
- ret = offsetof(VexGuestMIPS64State, guest_r27); break;
- case 28:
- ret = offsetof(VexGuestMIPS64State, guest_r28); break;
- case 29:
- ret = offsetof(VexGuestMIPS64State, guest_r29); break;
- case 30:
- ret = offsetof(VexGuestMIPS64State, guest_r30); break;
- case 31:
- ret = offsetof(VexGuestMIPS64State, guest_r31); break;
- default:
- vassert(0);
- break;
- }
- return ret;
-}
-
-#if defined(VGP_mips32_linux)
-#define OFFB_PC offsetof(VexGuestMIPS32State, guest_PC)
-#else
-#define OFFB_PC offsetof(VexGuestMIPS64State, guest_PC)
-#endif
-/* ---------------- Floating point registers ---------------- */
-
-static UInt floatGuestRegOffset(UInt fregNo)
-{
- vassert(fregNo < 32);
- UInt ret;
if (!mode64)
- switch (fregNo) {
- case 0:
- ret = offsetof(VexGuestMIPS32State, guest_f0); break;
- case 1:
- ret = offsetof(VexGuestMIPS32State, guest_f1); break;
- case 2:
- ret = offsetof(VexGuestMIPS32State, guest_f2); break;
- case 3:
- ret = offsetof(VexGuestMIPS32State, guest_f3); break;
- case 4:
- ret = offsetof(VexGuestMIPS32State, guest_f4); break;
- case 5:
- ret = offsetof(VexGuestMIPS32State, guest_f5); break;
- case 6:
- ret = offsetof(VexGuestMIPS32State, guest_f6); break;
- case 7:
- ret = offsetof(VexGuestMIPS32State, guest_f7); break;
- case 8:
- ret = offsetof(VexGuestMIPS32State, guest_f8); break;
- case 9:
- ret = offsetof(VexGuestMIPS32State, guest_f9); break;
- case 10:
- ret = offsetof(VexGuestMIPS32State, guest_f10); break;
- case 11:
- ret = offsetof(VexGuestMIPS32State, guest_f11); break;
- case 12:
- ret = offsetof(VexGuestMIPS32State, guest_f12); break;
- case 13:
- ret = offsetof(VexGuestMIPS32State, guest_f13); break;
- case 14:
- ret = offsetof(VexGuestMIPS32State, guest_f14); break;
- case 15:
- ret = offsetof(VexGuestMIPS32State, guest_f15); break;
- case 16:
- ret = offsetof(VexGuestMIPS32State, guest_f16); break;
- case 17:
- ret = offsetof(VexGuestMIPS32State, guest_f17); break;
- case 18:
- ret = offsetof(VexGuestMIPS32State, guest_f18); break;
- case 19:
- ret = offsetof(VexGuestMIPS32State, guest_f19); break;
- case 20:
- ret = offsetof(VexGuestMIPS32State, guest_f20); break;
- case 21:
- ret = offsetof(VexGuestMIPS32State, guest_f21); break;
- case 22:
- ret = offsetof(VexGuestMIPS32State, guest_f22); break;
- case 23:
- ret = offsetof(VexGuestMIPS32State, guest_f23); break;
- case 24:
- ret = offsetof(VexGuestMIPS32State, guest_f24); break;
- case 25:
- ret = offsetof(VexGuestMIPS32State, guest_f25); break;
- case 26:
- ret = offsetof(VexGuestMIPS32State, guest_f26); break;
- case 27:
- ret = offsetof(VexGuestMIPS32State, guest_f27); break;
- case 28:
- ret = offsetof(VexGuestMIPS32State, guest_f28); break;
- case 29:
- ret = offsetof(VexGuestMIPS32State, guest_f29); break;
- case 30:
- ret = offsetof(VexGuestMIPS32State, guest_f30); break;
- case 31:
- ret = offsetof(VexGuestMIPS32State, guest_f31); break;
- default:
- vassert(0);
- break;
- }
- else
- switch (fregNo) {
- case 0:
- ret = offsetof(VexGuestMIPS64State, guest_f0); break;
- case 1:
- ret = offsetof(VexGuestMIPS64State, guest_f1); break;
- case 2:
- ret = offsetof(VexGuestMIPS64State, guest_f2); break;
- case 3:
- ret = offsetof(VexGuestMIPS64State, guest_f3); break;
- case 4:
- ret = offsetof(VexGuestMIPS64State, guest_f4); break;
- case 5:
- ret = offsetof(VexGuestMIPS64State, guest_f5); break;
- case 6:
- ret = offsetof(VexGuestMIPS64State, guest_f6); break;
- case 7:
- ret = offsetof(VexGuestMIPS64State, guest_f7); break;
- case 8:
- ret = offsetof(VexGuestMIPS64State, guest_f8); break;
- case 9:
- ret = offsetof(VexGuestMIPS64State, guest_f9); break;
- case 10:
- ret = offsetof(VexGuestMIPS64State, guest_f10); break;
- case 11:
- ret = offsetof(VexGuestMIPS64State, guest_f11); break;
- case 12:
- ret = offsetof(VexGuestMIPS64State, guest_f12); break;
- case 13:
- ret = offsetof(VexGuestMIPS64State, guest_f13); break;
- case 14:
- ret = offsetof(VexGuestMIPS64State, guest_f14); break;
- case 15:
- ret = offsetof(VexGuestMIPS64State, guest_f15); break;
- case 16:
- ret = offsetof(VexGuestMIPS64State, guest_f16); break;
- case 17:
- ret = offsetof(VexGuestMIPS64State, guest_f17); break;
- case 18:
- ret = offsetof(VexGuestMIPS64State, guest_f18); break;
- case 19:
- ret = offsetof(VexGuestMIPS64State, guest_f19); break;
- case 20:
- ret = offsetof(VexGuestMIPS64State, guest_f20); break;
- case 21:
- ret = offsetof(VexGuestMIPS64State, guest_f21); break;
- case 22:
- ret = offsetof(VexGuestMIPS64State, guest_f22); break;
- case 23:
- ret = offsetof(VexGuestMIPS64State, guest_f23); break;
- case 24:
- ret = offsetof(VexGuestMIPS64State, guest_f24); break;
- case 25:
- ret = offsetof(VexGuestMIPS64State, guest_f25); break;
- case 26:
- ret = offsetof(VexGuestMIPS64State, guest_f26); break;
- case 27:
- ret = offsetof(VexGuestMIPS64State, guest_f27); break;
- case 28:
- ret = offsetof(VexGuestMIPS64State, guest_f28); break;
- case 29:
- ret = offsetof(VexGuestMIPS64State, guest_f29); break;
- case 30:
- ret = offsetof(VexGuestMIPS64State, guest_f30); break;
- case 31:
- ret = offsetof(VexGuestMIPS64State, guest_f31); break;
- default:
- vassert(0);
- break;
- }
- return ret;
-}
-
-/* ---------------- MIPS32 DSP ASE(r2) accumulators ---------------- */
-
-static UInt accumulatorGuestRegOffset(UInt acNo)
-{
- vassert(!mode64);
- vassert(acNo <= 3);
- UInt ret;
- switch (acNo) {
- case 0:
- ret = offsetof(VexGuestMIPS32State, guest_ac0); break;
- case 1:
- ret = offsetof(VexGuestMIPS32State, guest_ac1); break;
- case 2:
- ret = offsetof(VexGuestMIPS32State, guest_ac2); break;
- case 3:
- ret = offsetof(VexGuestMIPS32State, guest_ac3); break;
- default:
- vassert(0);
- break;
- }
- return ret;
-}
-
-/* ---------------- MIPS32 MSA registers ---------------- */
-
-static UInt msaGuestRegOffset(UInt msaRegNo) {
- vassert(msaRegNo <= 31);
- UInt ret;
-
- if (mode64) {
- switch (msaRegNo) {
+ switch (iregNo) {
case 0:
- ret = offsetof(VexGuestMIPS64State, guest_w0);
+ ret = offsetof(VexGuestMIPS32State, guest_r0);
break;
case 1:
- ret = offsetof(VexGuestMIPS64State, guest_w1);
+ ret = offsetof(VexGuestMIPS32State, guest_r1);
break;
case 2:
- ret = offsetof(VexGuestMIPS64State, guest_w2);
+ ret = offsetof(VexGuestMIPS32State, guest_r2);
break;
case 3:
- ret = offsetof(VexGuestMIPS64State, guest_w3);
+ ret = offsetof(VexGuestMIPS32State, guest_r3);
break;
case 4:
- ret = offsetof(VexGuestMIPS64State, guest_w4);
+ ret = offsetof(VexGuestMIPS32State, guest_r4);
break;
case 5:
- ret = offsetof(VexGuestMIPS64State, guest_w5);
+ ret = offsetof(VexGuestMIPS32State, guest_r5);
break;
case 6:
- ret = offsetof(VexGuestMIPS64State, guest_w6);
+ ret = offsetof(VexGuestMIPS32State, guest_r6);
break;
case 7:
- ret = offsetof(VexGuestMIPS64State, guest_w7);
+ ret = offsetof(VexGuestMIPS32State, guest_r7);
break;
case 8:
- ret = offsetof(VexGuestMIPS64State, guest_w8);
+ ret = offsetof(VexGuestMIPS32State, guest_r8);
break;
case 9:
- ret = offsetof(VexGuestMIPS64State, guest_w9);
+ ret = offsetof(VexGuestMIPS32State, guest_r9);
break;
case 10:
- ret = offsetof(VexGuestMIPS64State, guest_w10);
+ ret = offsetof(VexGuestMIPS32State, guest_r10);
break;
case 11:
- ret = offsetof(VexGuestMIPS64State, guest_w11);
+ ret = offsetof(VexGuestMIPS32State, guest_r11);
break;
case 12:
- ret = offsetof(VexGuestMIPS64State, guest_w12);
+ ret = offsetof(VexGuestMIPS32State, guest_r12);
break;
case 13:
- ret = offsetof(VexGuestMIPS64State, guest_w13);
+ ret = offsetof(VexGuestMIPS32State, guest_r13);
break;
case 14:
- ret = offsetof(VexGuestMIPS64State, guest_w14);
+ ret = offsetof(VexGuestMIPS32State, guest_r14);
break;
case 15:
- ret = offsetof(VexGuestMIPS64State, guest_w15);
+ ret = offsetof(VexGuestMIPS32State, guest_r15);
break;
case 16:
- ret = offsetof(VexGuestMIPS64State, guest_w16);
+ ret = offsetof(VexGuestMIPS32State, guest_r16);
break;
case 17:
- ret = offsetof(VexGuestMIPS64State, guest_w17);
+ ret = offsetof(VexGuestMIPS32State, guest_r17);
break;
case 18:
- ret = offsetof(VexGuestMIPS64State, guest_w18);
+ ret = offsetof(VexGuestMIPS32State, guest_r18);
break;
case 19:
- ret = offsetof(VexGuestMIPS64State, guest_w19);
+ ret = offsetof(VexGuestMIPS32State, guest_r19);
break;
case 20:
- ret = offsetof(VexGuestMIPS64State, guest_w20);
+ ret = offsetof(VexGuestMIPS32State, guest_r20);
break;
case 21:
- ret = offsetof(VexGuestMIPS64State, guest_w21);
+ ret = offsetof(VexGuestMIPS32State, guest_r21);
break;
case 22:
- ret = offsetof(VexGuestMIPS64State, guest_w22);
+ ret = offsetof(VexGuestMIPS32State, guest_r22);
break;
case 23:
- ret = offsetof(VexGuestMIPS64State, guest_w23);
+ ret = offsetof(VexGuestMIPS32State, guest_r23);
break;
case 24:
- ret = offsetof(VexGuestMIPS64State, guest_w24);
+ ret = offsetof(VexGuestMIPS32State, guest_r24);
break;
case 25:
- ret = offsetof(VexGuestMIPS64State, guest_w25);
+ ret = offsetof(VexGuestMIPS32State, guest_r25);
break;
case 26:
- ret = offsetof(VexGuestMIPS64State, guest_w26);
+ ret = offsetof(VexGuestMIPS32State, guest_r26);
break;
case 27:
- ret = offsetof(VexGuestMIPS64State, guest_w27);
+ ret = offsetof(VexGuestMIPS32State, guest_r27);
break;
case 28:
- ret = offsetof(VexGuestMIPS64State, guest_w28);
+ ret = offsetof(VexGuestMIPS32State, guest_r28);
break;
case 29:
- ret = offsetof(VexGuestMIPS64State, guest_w29);
+ ret = offsetof(VexGuestMIPS32State, guest_r29);
break;
case 30:
- ret = offsetof(VexGuestMIPS64State, guest_w30);
+ ret = offsetof(VexGuestMIPS32State, guest_r30);
break;
case 31:
- ret = offsetof(VexGuestMIPS64State, guest_w31);
+ ret = offsetof(VexGuestMIPS32State, guest_r31);
break;
default:
vassert(0);
break;
}
- } else {
- switch (msaRegNo) {
+ else
+ switch (iregNo) {
case 0:
- ret = offsetof(VexGuestMIPS32State, guest_w0);
+ ret = offsetof(VexGuestMIPS64State, guest_r0);
break;
case 1:
- ret = offsetof(VexGuestMIPS32State, guest_w1);
+ ret = offsetof(VexGuestMIPS64State, guest_r1);
break;
case 2:
- ret = offsetof(VexGuestMIPS32State, guest_w2);
+ ret = offsetof(VexGuestMIPS64State, guest_r2);
break;
case 3:
- ret = offsetof(VexGuestMIPS32State, guest_w3);
+ ret = offsetof(VexGuestMIPS64State, guest_r3);
break;
case 4:
- ret = offsetof(VexGuestMIPS32State, guest_w4);
+ ret = offsetof(VexGuestMIPS64State, guest_r4);
break;
case 5:
- ret = offsetof(VexGuestMIPS32State, guest_w5);
+ ret = offsetof(VexGuestMIPS64State, guest_r5);
break;
case 6:
- ret = offsetof(VexGuestMIPS32State, guest_w6);
+ ret = offsetof(VexGuestMIPS64State, guest_r6);
break;
case 7:
- ret = offsetof(VexGuestMIPS32State, guest_w7);
+ ret = offsetof(VexGuestMIPS64State, guest_r7);
break;
case 8:
- ret = offsetof(VexGuestMIPS32State, guest_w8);
+ ret = offsetof(VexGuestMIPS64State, guest_r8);
break;
case 9:
- ret = offsetof(VexGuestMIPS32State, guest_w9);
+ ret = offsetof(VexGuestMIPS64State, guest_r9);
break;
case 10:
- ret = offsetof(VexGuestMIPS32State, guest_w10);
+ ret = offsetof(VexGuestMIPS64State, guest_r10);
break;
case 11:
- ret = offsetof(VexGuestMIPS32State, guest_w11);
+ ret = offsetof(VexGuestMIPS64State, guest_r11);
break;
case 12:
- ret = offsetof(VexGuestMIPS32State, guest_w12);
+ ret = offsetof(VexGuestMIPS64State, guest_r12);
break;
case 13:
- ret = offsetof(VexGuestMIPS32State, guest_w13);
+ ret = offsetof(VexGuestMIPS64State, guest_r13);
break;
case 14:
- ret = offsetof(VexGuestMIPS32State, guest_w14);
+ ret = offsetof(VexGuestMIPS64State, guest_r14);
break;
case 15:
- ret = offsetof(VexGuestMIPS32State, guest_w15);
+ ret = offsetof(VexGuestMIPS64State, guest_r15);
break;
case 16:
- ret = offsetof(VexGuestMIPS32State, guest_w16);
+ ret = offsetof(VexGuestMIPS64State, guest_r16);
break;
case 17:
- ret = offsetof(VexGuestMIPS32State, guest_w17);
+ ret = offsetof(VexGuestMIPS64State, guest_r17);
break;
case 18:
- ret = offsetof(VexGuestMIPS32State, guest_w18);
+ ret = offsetof(VexGuestMIPS64State, guest_r18);
break;
case 19:
- ret = offsetof(VexGuestMIPS32State, guest_w19);
+ ret = offsetof(VexGuestMIPS64State, guest_r19);
break;
case 20:
- ret = offsetof(VexGuestMIPS32State, guest_w20);
+ ret = offsetof(VexGuestMIPS64State, guest_r20);
break;
case 21:
- ret = offsetof(VexGuestMIPS32State, guest_w21);
+ ret = offsetof(VexGuestMIPS64State, guest_r21);
break;
case 22:
- ret = offsetof(VexGuestMIPS32State, guest_w22);
+ ret = offsetof(VexGuestMIPS64State, guest_r22);
break;
case 23:
- ret = offsetof(VexGuestMIPS32State, guest_w23);
+ ret = offsetof(VexGuestMIPS64State, guest_r23);
break;
case 24:
- ret = offsetof(VexGuestMIPS32State, guest_w24);
+ ret = offsetof(VexGuestMIPS64State, guest_r24);
break;
case 25:
- ret = offsetof(VexGuestMIPS32State, guest_w25);
+ ret = offsetof(VexGuestMIPS64State, guest_r25);
break;
case 26:
- ret = offsetof(VexGuestMIPS32State, guest_w26);
+ ret = offsetof(VexGuestMIPS64State, guest_r26);
break;
case 27:
- ret = offsetof(VexGuestMIPS32State, guest_w27);
+ ret = offsetof(VexGuestMIPS64State, guest_r27);
break;
case 28:
- ret = offsetof(VexGuestMIPS32State, guest_w28);
+ ret = offsetof(VexGuestMIPS64State, guest_r28);
break;
case 29:
- ret = offsetof(VexGuestMIPS32State, guest_w29);
+ ret = offsetof(VexGuestMIPS64State, guest_r29);
break;
case 30:
- ret = offsetof(VexGuestMIPS32State, guest_w30);
+ ret = offsetof(VexGuestMIPS64State, guest_r30);
break;
case 31:
- ret = offsetof(VexGuestMIPS32State, guest_w31);
+ ret = offsetof(VexGuestMIPS64State, guest_r31);
break;
default:
vassert(0);
break;
}
- }
return ret;
}
-
-/* Do a endian load of a 32-bit word, regardless of the endianness of the
- underlying host. */
-static inline UInt getUInt(const UChar * p)
-{
- UInt w = 0;
-#if defined (_MIPSEL)
- w = (w << 8) | p[3];
- w = (w << 8) | p[2];
- w = (w << 8) | p[1];
- w = (w << 8) | p[0];
-#elif defined (_MIPSEB)
- w = (w << 8) | p[0];
- w = (w << 8) | p[1];
- w = (w << 8) | p[2];
- w = (w << 8) | p[3];
+#if defined(VGP_mips32_linux)
+#define OFFB_PC offsetof(VexGuestMIPS32State, guest_PC)
+#else
+#define OFFB_PC offsetof(VexGuestMIPS64State, guest_PC)
#endif
- return w;
-}
-#define BITS2(_b1,_b0) \
- (((_b1) << 1) | (_b0))
+/* ---------------- Floating point registers ---------------- */
-#define BITS3(_b2,_b1,_b0) \
- (((_b2) << 2) | ((_b1) << 1) | (_b0))
+static UInt floatGuestRegOffset(UInt fregNo)
+{
+ vassert(fregNo < 32);
+ UInt ret;
-#define BITS4(_b3,_b2,_b1,_b0) \
- (((_b3) << 3) | ((_b2) << 2) | ((_b1) << 1) | (_b0))
+ if (!mode64)
+ switch (fregNo) {
+ case 0:
+ ret = offsetof(VexGuestMIPS32State, guest_f0);
+ break;
-#define BITS5(_b4,_b3,_b2,_b1,_b0) \
- (((_b4) << 4) | BITS4((_b3),(_b2),(_b1),(_b0)))
+ case 1:
+ ret = offsetof(VexGuestMIPS32State, guest_f1);
+ break;
-#define BITS6(_b5,_b4,_b3,_b2,_b1,_b0) \
- ((BITS2((_b5),(_b4)) << 4) \
- | BITS4((_b3),(_b2),(_b1),(_b0)))
+ case 2:
+ ret = offsetof(VexGuestMIPS32State, guest_f2);
+ break;
-#define BITS8(_b7,_b6,_b5,_b4,_b3,_b2,_b1,_b0) \
- ((BITS4((_b7),(_b6),(_b5),(_b4)) << 4) \
- | BITS4((_b3),(_b2),(_b1),(_b0)))
+ case 3:
+ ret = offsetof(VexGuestMIPS32State, guest_f3);
+ break;
-#define LOAD_STORE_PATTERN \
- t1 = newTemp(mode64 ? Ity_I64 : Ity_I32); \
- if(!mode64) \
- assign(t1, binop(Iop_Add32, getIReg(rs), \
- mkU32(extend_s_16to32(imm)))); \
- else \
- assign(t1, binop(Iop_Add64, getIReg(rs), \
- mkU64(extend_s_16to64(imm)))); \
+ case 4:
+ ret = offsetof(VexGuestMIPS32State, guest_f4);
+ break;
-#define LOAD_STORE_PATTERN_MSA(imm) \
- t1 = newTemp(mode64 ? Ity_I64 : Ity_I32); \
- if (!mode64) \
- assign(t1, binop(Iop_Add32, getIReg(ws), \
- mkU32(extend_s_10to32(imm)))); \
- else \
- assign(t1, binop(Iop_Add64, getIReg(ws), \
- mkU64(extend_s_10to64(imm)))); \
+ case 5:
+ ret = offsetof(VexGuestMIPS32State, guest_f5);
+ break;
-#define LOADX_STORE_PATTERN \
- t1 = newTemp(mode64 ? Ity_I64 : Ity_I32); \
- if(!mode64) \
- assign(t1, binop(Iop_Add32, getIReg(regRs), getIReg(regRt))); \
- else \
- assign(t1, binop(Iop_Add64, getIReg(regRs), getIReg(regRt)));
+ case 6:
+ ret = offsetof(VexGuestMIPS32State, guest_f6);
+ break;
-#define LWX_SWX_PATTERN64 \
- t2 = newTemp(Ity_I64); \
- assign(t2, binop(Iop_And64, mkexpr(t1), mkU64(0xFFFFFFFFFFFFFFFCULL))); \
- t4 = newTemp(Ity_I32); \
- assign(t4, mkNarrowTo32( ty, binop(Iop_And64, \
- mkexpr(t1), mkU64(0x3))));
+ case 7:
+ ret = offsetof(VexGuestMIPS32State, guest_f7);
+ break;
-#define LWX_SWX_PATTERN64_1 \
- t2 = newTemp(Ity_I64); \
- assign(t2, binop(Iop_And64, mkexpr(t1), mkU64(0xFFFFFFFFFFFFFFF8ULL))); \
- t4 = newTemp(Ity_I64); \
- assign(t4, binop(Iop_And64, mkexpr(t1), mkU64(0x7)));
+ case 8:
+ ret = offsetof(VexGuestMIPS32State, guest_f8);
+ break;
-#define LWX_SWX_PATTERN \
- t2 = newTemp(Ity_I32); \
- assign(t2, binop(Iop_And32, mkexpr(t1), mkU32(0xFFFFFFFC))); \
- t4 = newTemp(Ity_I32); \
- assign(t4, binop(Iop_And32, mkexpr(t1), mkU32(0x00000003)))
+ case 9:
+ ret = offsetof(VexGuestMIPS32State, guest_f9);
+ break;
-#define SXXV_PATTERN(op) \
- putIReg(rd, binop(op, \
- getIReg(rt), \
- unop(Iop_32to8, \
- binop(Iop_And32, \
- getIReg(rs), \
- mkU32(0x0000001F) \
- ) \
- ) \
- ) \
- )
+ case 10:
+ ret = offsetof(VexGuestMIPS32State, guest_f10);
+ break;
-#define SXXV_PATTERN64(op) \
- putIReg(rd, mkWidenFrom32(ty, binop(op, \
- mkNarrowTo32(ty, getIReg(rt)), \
- unop(Iop_32to8, \
- binop(Iop_And32, \
- mkNarrowTo32(ty, getIReg(rs)), \
- mkU32(0x0000001F) \
- ) \
- ) \
- ), True \
- ))
+ case 11:
+ ret = offsetof(VexGuestMIPS32State, guest_f11);
+ break;
-#define SXX_PATTERN(op) \
- putIReg(rd, binop(op, getIReg(rt), mkU8(sa)));
+ case 12:
+ ret = offsetof(VexGuestMIPS32State, guest_f12);
+ break;
-#define ALU_PATTERN(op) \
- putIReg(rd, binop(op, getIReg(rs), getIReg(rt)));
+ case 13:
+ ret = offsetof(VexGuestMIPS32State, guest_f13);
+ break;
-#define ALUI_PATTERN(op) \
- putIReg(rt, binop(op, getIReg(rs), mkU32(imm)));
+ case 14:
+ ret = offsetof(VexGuestMIPS32State, guest_f14);
+ break;
-#define ALUI_PATTERN64(op) \
- putIReg(rt, binop(op, getIReg(rs), mkU64(imm)));
+ case 15:
+ ret = offsetof(VexGuestMIPS32State, guest_f15);
+ break;
-#define ALU_PATTERN64(op) \
- putIReg(rd, mkWidenFrom32(ty, binop(op, \
- mkNarrowTo32(ty, getIReg(rs)), \
- mkNarrowTo32(ty, getIReg(rt))), True));
+ case 16:
+ ret = offsetof(VexGuestMIPS32State, guest_f16);
+ break;
-#define FP_CONDITIONAL_CODE \
- t3 = newTemp(Ity_I32); \
- assign(t3, binop(Iop_And32, \
- IRExpr_ITE( binop(Iop_CmpEQ32, mkU32(cc), mkU32(0)), \
- binop(Iop_Shr32, getFCSR(), mkU8(23)), \
- binop(Iop_Shr32, getFCSR(), mkU8(24+cc))), \
- mkU32(0x1)));
+ case 17:
+ ret = offsetof(VexGuestMIPS32State, guest_f17);
+ break;
-#define ILLEGAL_INSTRUCTON \
- putPC(mkU32(guest_PC_curr_instr + 4)); \
- dres.jk_StopHere = Ijk_SigILL; \
- dres.whatNext = Dis_StopHere;
+ case 18:
+ ret = offsetof(VexGuestMIPS32State, guest_f18);
+ break;
-#define LLADDR_INVALID \
- (mode64 ? mkU64(0xFFFFFFFFFFFFFFFFULL) : mkU32(0xFFFFFFFF))
+ case 19:
+ ret = offsetof(VexGuestMIPS32State, guest_f19);
+ break;
-/*------------------------------------------------------------*/
-/*--- Field helpers ---*/
-/*------------------------------------------------------------*/
+ case 20:
+ ret = offsetof(VexGuestMIPS32State, guest_f20);
+ break;
-static UInt get_opcode(UInt mipsins)
-{
- return (0xFC000000 & mipsins) >> 26;
-}
+ case 21:
+ ret = offsetof(VexGuestMIPS32State, guest_f21);
+ break;
-static UInt get_rs(UInt mipsins)
-{
- return (0x03E00000 & mipsins) >> 21;
-}
+ case 22:
+ ret = offsetof(VexGuestMIPS32State, guest_f22);
+ break;
-static UInt get_rt(UInt mipsins)
-{
- return (0x001F0000 & mipsins) >> 16;
-}
+ case 23:
+ ret = offsetof(VexGuestMIPS32State, guest_f23);
+ break;
-static UInt get_imm(UInt mipsins)
-{
- return (0x0000FFFF & mipsins);
-}
+ case 24:
+ ret = offsetof(VexGuestMIPS32State, guest_f24);
+ break;
-static UInt get_instr_index(UInt mipsins)
-{
- return (0x03FFFFFF & mipsins);
-}
+ case 25:
+ ret = offsetof(VexGuestMIPS32State, guest_f25);
+ break;
-static UInt get_rd(UInt mipsins)
-{
- return (0x0000F800 & mipsins) >> 11;
-}
+ case 26:
+ ret = offsetof(VexGuestMIPS32State, guest_f26);
+ break;
-static UInt get_sa(UInt mipsins)
-{
- return (0x000007C0 & mipsins) >> 6;
-}
+ case 27:
+ ret = offsetof(VexGuestMIPS32State, guest_f27);
+ break;
-static UInt get_function(UInt mipsins)
-{
- return (0x0000003F & mipsins);
-}
+ case 28:
+ ret = offsetof(VexGuestMIPS32State, guest_f28);
+ break;
-static UInt get_ft(UInt mipsins)
-{
- return (0x001F0000 & mipsins) >> 16;
-}
+ case 29:
+ ret = offsetof(VexGuestMIPS32State, guest_f29);
+ break;
-static UInt get_fs(UInt mipsins)
-{
- return (0x0000F800 & mipsins) >> 11;
-}
+ case 30:
+ ret = offsetof(VexGuestMIPS32State, guest_f30);
+ break;
-static UInt get_fd(UInt mipsins)
-{
- return (0x000007C0 & mipsins) >> 6;
-}
+ case 31:
+ ret = offsetof(VexGuestMIPS32State, guest_f31);
+ break;
-static UInt get_mov_cc(UInt mipsins)
-{
- return (0x001C0000 & mipsins) >> 18;
-}
+ default:
+ vassert(0);
+ break;
+ }
+ else
+ switch (fregNo) {
+ case 0:
+ ret = offsetof(VexGuestMIPS64State, guest_f0);
+ break;
-static UInt get_bc1_cc(UInt mipsins)
-{
- return (0x001C0000 & mipsins) >> 18;
-}
+ case 1:
+ ret = offsetof(VexGuestMIPS64State, guest_f1);
+ break;
-static UInt get_fpc_cc(UInt mipsins)
-{
- return (0x00000700 & mipsins) >> 8;
-}
+ case 2:
+ ret = offsetof(VexGuestMIPS64State, guest_f2);
+ break;
-static UInt get_tf(UInt mipsins)
-{
- return (0x00010000 & mipsins) >> 16;
-}
+ case 3:
+ ret = offsetof(VexGuestMIPS64State, guest_f3);
+ break;
-static UInt get_nd(UInt mipsins)
-{
- return (0x00020000 & mipsins) >> 17;
-}
+ case 4:
+ ret = offsetof(VexGuestMIPS64State, guest_f4);
+ break;
-static UInt get_fmt(UInt mipsins)
-{
- return (0x03E00000 & mipsins) >> 21;
-}
+ case 5:
+ ret = offsetof(VexGuestMIPS64State, guest_f5);
+ break;
-static UInt get_FC(UInt mipsins)
-{
- return (0x000000F0 & mipsins) >> 4;
-}
+ case 6:
+ ret = offsetof(VexGuestMIPS64State, guest_f6);
+ break;
-static UInt get_cond(UInt mipsins)
-{
- return (0x0000000F & mipsins);
-}
+ case 7:
+ ret = offsetof(VexGuestMIPS64State, guest_f7);
+ break;
-/* for break & syscall */
-static UInt get_code(UInt mipsins)
-{
- return (0xFFC0 & mipsins) >> 6;
-}
+ case 8:
+ ret = offsetof(VexGuestMIPS64State, guest_f8);
+ break;
-static UInt get_lsb(UInt mipsins)
-{
- return (0x7C0 & mipsins) >> 6;
-}
+ case 9:
+ ret = offsetof(VexGuestMIPS64State, guest_f9);
+ break;
-static UInt get_msb(UInt mipsins)
-{
- return (0x0000F800 & mipsins) >> 11;
-}
+ case 10:
+ ret = offsetof(VexGuestMIPS64State, guest_f10);
+ break;
-static UInt get_rot(UInt mipsins)
-{
- return (0x00200000 & mipsins) >> 21;
-}
+ case 11:
+ ret = offsetof(VexGuestMIPS64State, guest_f11);
+ break;
-static UInt get_rotv(UInt mipsins)
-{
- return (0x00000040 & mipsins) >> 6;
-}
+ case 12:
+ ret = offsetof(VexGuestMIPS64State, guest_f12);
+ break;
-static UInt get_sel(UInt mipsins)
-{
- return (0x00000007 & mipsins);
-}
+ case 13:
+ ret = offsetof(VexGuestMIPS64State, guest_f13);
+ break;
-/* Get acc number for all MIPS32 DSP ASE(r2) instructions that use them,
- except for MFHI and MFLO. */
-static UInt get_acNo(UInt mipsins)
-{
- return (0x00001800 & mipsins) >> 11;
-}
+ case 14:
+ ret = offsetof(VexGuestMIPS64State, guest_f14);
+ break;
-/* Get accumulator number for MIPS32 DSP ASEr2 MFHI and MFLO instructions. */
-static UInt get_acNo_mfhilo(UInt mipsins)
-{
- return (0x00600000 & mipsins) >> 21;
-}
+ case 15:
+ ret = offsetof(VexGuestMIPS64State, guest_f15);
+ break;
-/* Get mask field (helper function for wrdsp instruction). */
-static UInt get_wrdspMask(UInt mipsins)
-{
- return (0x001ff800 & mipsins) >> 11;
-}
+ case 16:
+ ret = offsetof(VexGuestMIPS64State, guest_f16);
+ break;
-/* Get mask field (helper function for rddsp instruction). */
-static UInt get_rddspMask(UInt mipsins)
-{
- return (0x03ff0000 & mipsins) >> 16;
-}
+ case 17:
+ ret = offsetof(VexGuestMIPS64State, guest_f17);
+ break;
-/* Get shift field (helper function for DSP ASE instructions). */
-static UInt get_shift(UInt mipsins)
-{
- return (0x03f00000 & mipsins) >> 20;
-}
+ case 18:
+ ret = offsetof(VexGuestMIPS64State, guest_f18);
+ break;
-/* Get immediate field for DSP ASE instructions. */
-static UInt get_dspImm(UInt mipsins)
-{
- return (0x03ff0000 & mipsins) >> 16;
-}
+ case 19:
+ ret = offsetof(VexGuestMIPS64State, guest_f19);
+ break;
-static Bool branch_or_jump(const UChar * addr)
-{
- UInt fmt;
- UInt cins = getUInt(addr);
+ case 20:
+ ret = offsetof(VexGuestMIPS64State, guest_f20);
+ break;
- UInt opcode = get_opcode(cins);
- UInt rt = get_rt(cins);
- UInt function = get_function(cins);
+ case 21:
+ ret = offsetof(VexGuestMIPS64State, guest_f21);
+ break;
- /* bgtz, blez, bne, beq, jal */
- if (opcode == 0x07 || opcode == 0x06 || opcode == 0x05 || opcode == 0x04
- || opcode == 0x03 || opcode == 0x02) {
- return True;
- }
+ case 22:
+ ret = offsetof(VexGuestMIPS64State, guest_f22);
+ break;
- /* bgez */
- if (opcode == 0x01 && rt == 0x01) {
- return True;
- }
+ case 23:
+ ret = offsetof(VexGuestMIPS64State, guest_f23);
+ break;
- /* bgezal */
- if (opcode == 0x01 && rt == 0x11) {
- return True;
- }
+ case 24:
+ ret = offsetof(VexGuestMIPS64State, guest_f24);
+ break;
- /* bltzal */
- if (opcode == 0x01 && rt == 0x10) {
- return True;
- }
+ case 25:
+ ret = offsetof(VexGuestMIPS64State, guest_f25);
+ break;
- /* bltz */
- if (opcode == 0x01 && rt == 0x00) {
- return True;
- }
+ case 26:
+ ret = offsetof(VexGuestMIPS64State, guest_f26);
+ break;
- /* jalr */
- if (opcode == 0x00 && function == 0x09) {
- return True;
- }
+ case 27:
+ ret = offsetof(VexGuestMIPS64State, guest_f27);
+ break;
- /* jr */
- if (opcode == 0x00 && function == 0x08) {
- return True;
- }
+ case 28:
+ ret = offsetof(VexGuestMIPS64State, guest_f28);
+ break;
- if (opcode == 0x11) {
- /* bc1f & bc1t */
- fmt = get_fmt(cins);
- if (fmt == 0x08) {
- return True;
- }
+ case 29:
+ ret = offsetof(VexGuestMIPS64State, guest_f29);
+ break;
- /* MSA branches */
- /* bnz.df, bz.df */
- if (fmt >= 0x18) {
- return True;
- }
- /* bnz.v */
- if (fmt == 0x0f) {
- return True;
- }
- /* bz.v */
- if (fmt == 0x0b) {
- return True;
- }
+ case 30:
+ ret = offsetof(VexGuestMIPS64State, guest_f30);
+ break;
- /* R6 branches */
- /* bc1eqz */
- if (fmt == 0x09) {
- return True;
- }
+ case 31:
+ ret = offsetof(VexGuestMIPS64State, guest_f31);
+ break;
- /* bc1nez */
- if (fmt == 0x0D) {
- return True;
+ default:
+ vassert(0);
+ break;
}
- }
-
- /* bposge32 */
- if (opcode == 0x01 && rt == 0x1c) {
- return True;
- }
-
- /* Cavium Specific instructions. */
- if (opcode == 0x32 || opcode == 0x3A || opcode == 0x36 || opcode == 0x3E) {
- /* BBIT0, BBIT1, BBIT032, BBIT132 */
- return True;
- }
- return False;
+ return ret;
}
-static Bool is_Branch_or_Jump_and_Link(const UChar * addr)
+/* ---------------- MIPS32 DSP ASE(r2) accumulators ---------------- */
+
+UInt accumulatorGuestRegOffset(UInt acNo)
{
- UInt cins = getUInt(addr);
+ vassert(!mode64);
+ vassert(acNo <= 3);
+ UInt ret;
- UInt opcode = get_opcode(cins);
- UInt rt = get_rt(cins);
- UInt function = get_function(cins);
+ switch (acNo) {
+ case 0:
+ ret = offsetof(VexGuestMIPS32State, guest_ac0);
+ break;
- /* jal */
- if (opcode == 0x02) {
- return True;
- }
+ case 1:
+ ret = offsetof(VexGuestMIPS32State, guest_ac1);
+ break;
- /* bgezal or bal(r6) */
- if (opcode == 0x01 && rt == 0x11) {
- return True;
- }
+ case 2:
+ ret = offsetof(VexGuestMIPS32State, guest_ac2);
+ break;
- /* bltzal */
- if (opcode == 0x01 && rt == 0x10) {
- return True;
- }
+ case 3:
+ ret = offsetof(VexGuestMIPS32State, guest_ac3);
+ break;
- /* jalr */
- if (opcode == 0x00 && function == 0x09) {
- return True;
+ default:
+ vassert(0);
+ break;
}
- return False;
+ return ret;
}
-static Bool branch_or_link_likely(const UChar * addr)
-{
- UInt cins = getUInt(addr);
- UInt opcode = get_opcode(cins);
- UInt rt = get_rt(cins);
+/* ---------------- MIPS32 MSA registers ---------------- */
- /* bgtzl, blezl, bnel, beql */
- if (opcode == 0x17 || opcode == 0x16 || opcode == 0x15 || opcode == 0x14)
- return True;
+static UInt msaGuestRegOffset(UInt msaRegNo)
+{
+ vassert(msaRegNo <= 31);
+ UInt ret;
- /* bgezl */
- if (opcode == 0x01 && rt == 0x03)
- return True;
+ if (mode64) {
+ switch (msaRegNo) {
+ case 0:
+ ret = offsetof(VexGuestMIPS64State, guest_w0);
+ break;
- /* bgezall */
- if (opcode == 0x01 && rt == 0x13)
- return True;
+ case 1:
+ ret = offsetof(VexGuestMIPS64State, guest_w1);
+ break;
- /* bltzall */
- if (opcode == 0x01 && rt == 0x12)
- return True;
+ case 2:
+ ret = offsetof(VexGuestMIPS64State, guest_w2);
+ break;
- /* bltzl */
- if (opcode == 0x01 && rt == 0x02)
- return True;
+ case 3:
+ ret = offsetof(VexGuestMIPS64State, guest_w3);
+ break;
- return False;
-}
+ case 4:
+ ret = offsetof(VexGuestMIPS64State, guest_w4);
+ break;
-/*------------------------------------------------------------*/
-/*--- Helper bits and pieces for creating IR fragments. ---*/
-/*------------------------------------------------------------*/
+ case 5:
+ ret = offsetof(VexGuestMIPS64State, guest_w5);
+ break;
-static IRExpr *mkU8(UInt i)
-{
- vassert(i < 256);
- return IRExpr_Const(IRConst_U8((UChar) i));
-}
+ case 6:
+ ret = offsetof(VexGuestMIPS64State, guest_w6);
+ break;
-/* Create an expression node for a 16-bit integer constant. */
-static IRExpr *mkU16(UInt i)
-{
- return IRExpr_Const(IRConst_U16(i));
-}
+ case 7:
+ ret = offsetof(VexGuestMIPS64State, guest_w7);
+ break;
-/* Create an expression node for a 32-bit integer constant. */
-static IRExpr *mkU32(UInt i)
-{
- return IRExpr_Const(IRConst_U32(i));
-}
+ case 8:
+ ret = offsetof(VexGuestMIPS64State, guest_w8);
+ break;
-/* Create an expression node for a 64-bit integer constant. */
-static IRExpr *mkU64(ULong i)
-{
- return IRExpr_Const(IRConst_U64(i));
-}
+ case 9:
+ ret = offsetof(VexGuestMIPS64State, guest_w9);
+ break;
-static IRExpr *mkexpr(IRTemp tmp)
-{
- return IRExpr_RdTmp(tmp);
-}
+ case 10:
+ ret = offsetof(VexGuestMIPS64State, guest_w10);
+ break;
-static IRExpr *unop(IROp op, IRExpr * a)
-{
- return IRExpr_Unop(op, a);
-}
+ case 11:
+ ret = offsetof(VexGuestMIPS64State, guest_w11);
+ break;
-static IRExpr *binop(IROp op, IRExpr * a1, IRExpr * a2)
-{
- return IRExpr_Binop(op, a1, a2);
-}
+ case 12:
+ ret = offsetof(VexGuestMIPS64State, guest_w12);
+ break;
-static IRExpr *triop(IROp op, IRExpr * a1, IRExpr * a2, IRExpr * a3)
-{
- return IRExpr_Triop(op, a1, a2, a3);
-}
+ case 13:
+ ret = offsetof(VexGuestMIPS64State, guest_w13);
+ break;
-static IRExpr *qop ( IROp op, IRExpr * a1, IRExpr * a2, IRExpr * a3,
- IRExpr * a4 )
-{
- return IRExpr_Qop(op, a1, a2, a3, a4);
-}
+ case 14:
+ ret = offsetof(VexGuestMIPS64State, guest_w14);
+ break;
-static IRExpr *load(IRType ty, IRExpr * addr)
-{
- IRExpr *load1 = NULL;
-#if defined (_MIPSEL)
- load1 = IRExpr_Load(Iend_LE, ty, addr);
-#elif defined (_MIPSEB)
- load1 = IRExpr_Load(Iend_BE, ty, addr);
-#endif
- return load1;
-}
+ case 15:
+ ret = offsetof(VexGuestMIPS64State, guest_w15);
+ break;
-/* Add a statement to the list held by "irsb". */
-static void stmt(IRStmt * st)
-{
- addStmtToIRSB(irsb, st);
-}
+ case 16:
+ ret = offsetof(VexGuestMIPS64State, guest_w16);
+ break;
-static void assign(IRTemp dst, IRExpr * e)
-{
- stmt(IRStmt_WrTmp(dst, e));
-}
+ case 17:
+ ret = offsetof(VexGuestMIPS64State, guest_w17);
+ break;
-static void store(IRExpr * addr, IRExpr * data)
-{
-#if defined (_MIPSEL)
- stmt(IRStmt_Store(Iend_LE, addr, data));
-#elif defined (_MIPSEB)
- stmt(IRStmt_Store(Iend_BE, addr, data));
-#endif
-}
+ case 18:
+ ret = offsetof(VexGuestMIPS64State, guest_w18);
+ break;
-/* Generate a new temporary of the given type. */
-static IRTemp newTemp(IRType ty)
-{
- vassert(isPlausibleIRType(ty));
- return newIRTemp(irsb->tyenv, ty);
-}
+ case 19:
+ ret = offsetof(VexGuestMIPS64State, guest_w19);
+ break;
-/* Generate an expression for SRC rotated right by ROT. */
-static IRExpr *genROR32(IRExpr * src, Int rot)
-{
- vassert(rot >= 0 && rot < 32);
- if (rot == 0)
- return src;
- return binop(Iop_Or32, binop(Iop_Shl32, src, mkU8(32 - rot)),
- binop(Iop_Shr32, src, mkU8(rot)));
-}
+ case 20:
+ ret = offsetof(VexGuestMIPS64State, guest_w20);
+ break;
-static IRExpr *genRORV32(IRExpr * src, IRExpr * rs)
-{
- IRTemp t0 = newTemp(Ity_I8);
- IRTemp t1 = newTemp(Ity_I8);
+ case 21:
+ ret = offsetof(VexGuestMIPS64State, guest_w21);
+ break;
- assign(t0, unop(Iop_32to8, binop(Iop_And32, rs, mkU32(0x0000001F))));
- assign(t1, binop(Iop_Sub8, mkU8(32), mkexpr(t0)));
- return binop(Iop_Or32, binop(Iop_Shl32, src, mkexpr(t1)),
- binop(Iop_Shr32, src, mkexpr(t0)));
-}
+ case 22:
+ ret = offsetof(VexGuestMIPS64State, guest_w22);
+ break;
+ case 23:
+ ret = offsetof(VexGuestMIPS64State, guest_w23);
+ break;
-static UShort extend_s_9to16(UInt x)
-{
- return (UShort) ((((Int) x) << 23) >> 23);
-}
+ case 24:
+ ret = offsetof(VexGuestMIPS64State, guest_w24);
+ break;
-static UShort extend_s_10to16(UInt x)
-{
- return (UShort) ((((Int) x) << 22) >> 22);
-}
+ case 25:
+ ret = offsetof(VexGuestMIPS64State, guest_w25);
+ break;
-static UInt extend_s_10to32(UInt x)
-{
- return (UInt)((((Int) x) << 22) >> 22);
-}
+ case 26:
+ ret = offsetof(VexGuestMIPS64State, guest_w26);
+ break;
-static ULong extend_s_10to64(UInt x)
-{
- return (ULong)((((Long) x) << 54) >> 54);
-}
+ case 27:
+ ret = offsetof(VexGuestMIPS64State, guest_w27);
+ break;
-static UInt extend_s_16to32(UInt x)
-{
- return (UInt) ((((Int) x) << 16) >> 16);
-}
+ case 28:
+ ret = offsetof(VexGuestMIPS64State, guest_w28);
+ break;
-static UInt extend_s_18to32(UInt x)
-{
- return (UInt) ((((Int) x) << 14) >> 14);
-}
+ case 29:
+ ret = offsetof(VexGuestMIPS64State, guest_w29);
+ break;
-static UInt extend_s_19to32(UInt x)
-{
- return (UInt) ((((Int) x) << 13) >> 13);
-}
+ case 30:
+ ret = offsetof(VexGuestMIPS64State, guest_w30);
+ break;
-static UInt extend_s_23to32(UInt x)
-{
- return (UInt) ((((Int) x) << 9) >> 9);
-}
+ case 31:
+ ret = offsetof(VexGuestMIPS64State, guest_w31);
+ break;
-static UInt extend_s_26to32(UInt x)
-{
- return (UInt) ((((Int) x) << 6) >> 6);
-}
+ default:
+ vassert(0);
+ break;
+ }
+ } else {
+ switch (msaRegNo) {
+ case 0:
+ ret = offsetof(VexGuestMIPS32State, guest_w0);
+ break;
-static ULong extend_s_16to64 ( UInt x )
-{
- return (ULong) ((((Long) x) << 48) >> 48);
-}
+ case 1:
+ ret = offsetof(VexGuestMIPS32State, guest_w1);
+ break;
-static ULong extend_s_18to64 ( UInt x )
-{
- return (ULong) ((((Long) x) << 46) >> 46);
-}
+ case 2:
+ ret = offsetof(VexGuestMIPS32State, guest_w2);
+ break;
-static ULong extend_s_19to64(UInt x)
-{
- return (ULong) ((((Long) x) << 45) >> 45);
-}
+ case 3:
+ ret = offsetof(VexGuestMIPS32State, guest_w3);
+ break;
-static ULong extend_s_23to64(UInt x)
-{
- return (ULong) ((((Long) x) << 41) >> 41);
-}
+ case 4:
+ ret = offsetof(VexGuestMIPS32State, guest_w4);
+ break;
-static ULong extend_s_26to64(UInt x)
-{
- return (ULong) ((((Long) x) << 38) >> 38);
-}
+ case 5:
+ ret = offsetof(VexGuestMIPS32State, guest_w5);
+ break;
-static ULong extend_s_32to64 ( UInt x )
-{
- return (ULong) ((((Long) x) << 32) >> 32);
-}
+ case 6:
+ ret = offsetof(VexGuestMIPS32State, guest_w6);
+ break;
-static void jmp_lit32 ( /*MOD*/ DisResult* dres, IRJumpKind kind, Addr32 d32 )
-{
- vassert(dres->whatNext == Dis_Continue);
- vassert(dres->len == 0);
- vassert(dres->continueAt == 0);
- vassert(dres->jk_StopHere == Ijk_INVALID);
- dres->whatNext = Dis_StopHere;
- dres->jk_StopHere = kind;
- stmt( IRStmt_Put( OFFB_PC, mkU32(d32) ) );
-}
+ case 7:
+ ret = offsetof(VexGuestMIPS32State, guest_w7);
+ break;
-static void jmp_lit64 ( /*MOD*/ DisResult* dres, IRJumpKind kind, Addr64 d64 )
-{
- vassert(dres->whatNext == Dis_Continue);
- vassert(dres->len == 0);
- vassert(dres->continueAt == 0);
- vassert(dres->jk_StopHere == Ijk_INVALID);
- dres->whatNext = Dis_StopHere;
- dres->jk_StopHere = kind;
- stmt(IRStmt_Put(OFFB_PC, mkU64(d64)));
-}
+ case 8:
+ ret = offsetof(VexGuestMIPS32State, guest_w8);
+ break;
-/* Get value from accumulator (helper function for MIPS32 DSP ASE instructions).
- This function should be called before any other operation if widening
- multiplications are used. */
-static IRExpr *getAcc(UInt acNo)
-{
- vassert(!mode64);
- vassert(acNo <= 3);
- return IRExpr_Get(accumulatorGuestRegOffset(acNo), Ity_I64);
-}
+ case 9:
+ ret = offsetof(VexGuestMIPS32State, guest_w9);
+ break;
-/* Get value from DSPControl register (helper function for MIPS32 DSP ASE
- instructions). */
-static IRExpr *getDSPControl(void)
-{
- vassert(!mode64);
- return IRExpr_Get(offsetof(VexGuestMIPS32State, guest_DSPControl), Ity_I32);
-}
+ case 10:
+ ret = offsetof(VexGuestMIPS32State, guest_w10);
+ break;
-/* Put value to DSPControl register. Expression e is written to DSPControl as
- is. If only certain bits of DSPControl need to be changed, it should be done
- before calling putDSPControl(). It could be done by reading DSPControl and
- ORing it with appropriate mask. */
-static void putDSPControl(IRExpr * e)
-{
- vassert(!mode64);
- stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_DSPControl), e));
-}
+ case 11:
+ ret = offsetof(VexGuestMIPS32State, guest_w11);
+ break;
-/* Fetch a byte from the guest insn stream. */
-static UChar getIByte(Int delta)
-{
- return guest_code[delta];
-}
+ case 12:
+ ret = offsetof(VexGuestMIPS32State, guest_w12);
+ break;
-static IRExpr *getIReg(UInt iregNo)
-{
- if (0 == iregNo) {
- return mode64 ? mkU64(0x0) : mkU32(0x0);
- } else {
- IRType ty = mode64 ? Ity_I64 : Ity_I32;
- vassert(iregNo < 32);
- return IRExpr_Get(integerGuestRegOffset(iregNo), ty);
- }
-}
+ case 13:
+ ret = offsetof(VexGuestMIPS32State, guest_w13);
+ break;
+ case 14:
+ ret = offsetof(VexGuestMIPS32State, guest_w14);
+ break;
-static IRExpr *getWReg(UInt wregNo) {
- vassert(wregNo <= 31);
- return IRExpr_Get(msaGuestRegOffset(wregNo), Ity_V128);
-}
+ case 15:
+ ret = offsetof(VexGuestMIPS32State, guest_w15);
+ break;
-static IRExpr *getHI(void)
-{
- if (mode64)
- return IRExpr_Get(offsetof(VexGuestMIPS64State, guest_HI), Ity_I64);
- else
- return IRExpr_Get(offsetof(VexGuestMIPS32State, guest_HI), Ity_I32);
-}
+ case 16:
+ ret = offsetof(VexGuestMIPS32State, guest_w16);
+ break;
-static IRExpr *getLO(void)
-{
- if (mode64)
- return IRExpr_Get(offsetof(VexGuestMIPS64State, guest_LO), Ity_I64);
- else
- return IRExpr_Get(offsetof(VexGuestMIPS32State, guest_LO), Ity_I32);
-}
+ case 17:
+ ret = offsetof(VexGuestMIPS32State, guest_w17);
+ break;
-static IRExpr *getFCSR(void)
-{
- if (mode64)
- return IRExpr_Get(offsetof(VexGuestMIPS64State, guest_FCSR), Ity_I32);
- else
- return IRExpr_Get(offsetof(VexGuestMIPS32State, guest_FCSR), Ity_I32);
-}
+ case 18:
+ ret = offsetof(VexGuestMIPS32State, guest_w18);
+ break;
-static IRExpr *getLLaddr(void)
-{
- if (mode64)
- return IRExpr_Get(offsetof(VexGuestMIPS64State, guest_LLaddr), Ity_I64);
- else
- return IRExpr_Get(offsetof(VexGuestMIPS32State, guest_LLaddr), Ity_I32);
-}
+ case 19:
+ ret = offsetof(VexGuestMIPS32State, guest_w19);
+ break;
-static IRExpr *getLLdata(void)
-{
- if (mode64)
- return IRExpr_Get(offsetof(VexGuestMIPS64State, guest_LLdata), Ity_I64);
- else
- return IRExpr_Get(offsetof(VexGuestMIPS32State, guest_LLdata), Ity_I32);
-}
+ case 20:
+ ret = offsetof(VexGuestMIPS32State, guest_w20);
+ break;
-static IRExpr *getMSACSR(void) {
- if (mode64)
- return IRExpr_Get(offsetof(VexGuestMIPS64State, guest_MSACSR), Ity_I32);
- else
- return IRExpr_Get(offsetof(VexGuestMIPS32State, guest_MSACSR), Ity_I32);
-}
+ case 21:
+ ret = offsetof(VexGuestMIPS32State, guest_w21);
+ break;
-/* Get byte from register reg, byte pos from 0 to 3 (or 7 for MIPS64) . */
-static IRExpr *getByteFromReg(UInt reg, UInt byte_pos)
-{
- UInt pos = byte_pos * 8;
- if (mode64)
- return unop(Iop_64to8, binop(Iop_And64,
- binop(Iop_Shr64, getIReg(reg), mkU8(pos)),
- mkU64(0xFF)));
- else
- return unop(Iop_32to8, binop(Iop_And32,
- binop(Iop_Shr32, getIReg(reg), mkU8(pos)),
- mkU32(0xFF)));
-}
+ case 22:
+ ret = offsetof(VexGuestMIPS32State, guest_w22);
+ break;
-static void putFCSR(IRExpr * e)
-{
- if (mode64)
- stmt(IRStmt_Put(offsetof(VexGuestMIPS64State, guest_FCSR), e));
- else
- stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_FCSR), e));
-}
+ case 23:
+ ret = offsetof(VexGuestMIPS32State, guest_w23);
+ break;
-static void putLLaddr(IRExpr * e)
-{
- if (mode64)
- stmt(IRStmt_Put(offsetof(VexGuestMIPS64State, guest_LLaddr), e));
- else
- stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_LLaddr), e));
-}
+ case 24:
+ ret = offsetof(VexGuestMIPS32State, guest_w24);
+ break;
-static void putLLdata(IRExpr * e)
-{
- if (mode64)
- stmt(IRStmt_Put(offsetof(VexGuestMIPS64State, guest_LLdata), e));
- else
- stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_LLdata), e));
-}
+ case 25:
+ ret = offsetof(VexGuestMIPS32State, guest_w25);
+ break;
-static void putMSACSR(IRExpr * e) {
- if (mode64)
- stmt(IRStmt_Put(offsetof(VexGuestMIPS64State, guest_MSACSR), e));
- else
- stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_MSACSR), e));
-}
+ case 26:
+ ret = offsetof(VexGuestMIPS32State, guest_w26);
+ break;
-/* fs - fpu source register number.
- inst - fpu instruction that needs to be executed.
- sz32 - size of source register.
- opN - number of operads:
- 1 - unary operation.
- 2 - binary operation. */
-static void calculateFCSR(UInt fs, UInt ft, UInt inst, Bool sz32, UInt opN)
-{
- IRDirty *d;
- IRTemp fcsr = newTemp(Ity_I32);
- /* IRExpr_GSPTR() => Need to pass pointer to guest state to helper. */
- if (fp_mode64)
- d = unsafeIRDirty_1_N(fcsr, 0,
- "mips_dirtyhelper_calculate_FCSR_fp64",
- &mips_dirtyhelper_calculate_FCSR_fp64,
- mkIRExprVec_4(IRExpr_GSPTR(),
- mkU32(fs),
- mkU32(ft),
- mkU32(inst)));
- else
- d = unsafeIRDirty_1_N(fcsr, 0,
- "mips_dirtyhelper_calculate_FCSR_fp32",
- &mips_dirtyhelper_calculate_FCSR_fp32,
- mkIRExprVec_4(IRExpr_GSPTR(),
- mkU32(fs),
- mkU32(ft),
- mkU32(inst)));
+ case 27:
+ ret = offsetof(VexGuestMIPS32State, guest_w27);
+ break;
- if (opN == 1) { /* Unary operation. */
- /* Declare we're reading guest state. */
- if (sz32 || fp_mode64)
- d->nFxState = 2;
- else
- d->nFxState = 3;
- vex_bzero(&d->fxState, sizeof(d->fxState));
+ case 28:
+ ret = offsetof(VexGuestMIPS32State, guest_w28);
+ break;
- d->fxState[0].fx = Ifx_Read; /* read */
- if (mode64)
- d->fxState[0].offset = offsetof(VexGuestMIPS64State, guest_FCSR);
- else
- d->fxState[0].offset = offsetof(VexGuestMIPS32State, guest_FCSR);
- d->fxState[0].size = sizeof(UInt);
- d->fxState[1].fx = Ifx_Read; /* read */
- d->fxState[1].offset = floatGuestRegOffset(fs);
- d->fxState[1].size = sizeof(ULong);
+ case 29:
+ ret = offsetof(VexGuestMIPS32State, guest_w29);
+ break;
- if (!(sz32 || fp_mode64)) {
- d->fxState[2].fx = Ifx_Read; /* read */
- d->fxState[2].offset = floatGuestRegOffset(fs+1);
- d->fxState[2].size = sizeof(ULong);
- }
- } else if (opN == 2) { /* Binary operation. */
- /* Declare we're reading guest state. */
- if (sz32 || fp_mode64)
- d->nFxState = 3;
- else
- d->nFxState = 5;
- vex_bzero(&d->fxState, sizeof(d->fxState));
+ case 30:
+ ret = offsetof(VexGuestMIPS32State, guest_w30);
+ break;
- d->fxState[0].fx = Ifx_Read; /* read */
- if (mode64)
- d->fxState[0].offset = offsetof(VexGuestMIPS64State, guest_FCSR);
- else
- d->fxState[0].offset = offsetof(VexGuestMIPS32State, guest_FCSR);
- d->fxState[0].size = sizeof(UInt);
- d->fxState[1].fx = Ifx_Read; /* read */
- d->fxState[1].offset = floatGuestRegOffset(fs);
- d->fxState[1].size = sizeof(ULong);
- d->fxState[2].fx = Ifx_Read; /* read */
- d->fxState[2].offset = floatGuestRegOffset(ft);
- d->fxState[2].size = sizeof(ULong);
+ case 31:
+ ret = offsetof(VexGuestMIPS32State, guest_w31);
+ break;
- if (!(sz32 || fp_mode64)) {
- d->fxState[3].fx = Ifx_Read; /* read */
- d->fxState[3].offset = floatGuestRegOffset(fs+1);
- d->fxState[3].size = sizeof(ULong);
- d->fxState[4].fx = Ifx_Read; /* read */
- d->fxState[4].offset = floatGuestRegOffset(ft+1);
- d->fxState[4].size = sizeof(ULong);
+ default:
+ vassert(0);
+ break;
}
}
- stmt(IRStmt_Dirty(d));
+ return ret;
+}
- putFCSR(mkexpr(fcsr));
+
+/* Do a endian load of a 32-bit word, regardless of the endianness of the
+ underlying host. */
+static inline UInt getUInt(const UChar * p)
+{
+ UInt w = 0;
+#if defined (_MIPSEL)
+ w = (w << 8) | p[3];
+ w = (w << 8) | p[2];
+ w = (w << 8) | p[1];
+ w = (w << 8) | p[0];
+#elif defined (_MIPSEB)
+ w = (w << 8) | p[0];
+ w = (w << 8) | p[1];
+ w = (w << 8) | p[2];
+ w = (w << 8) | p[3];
+#endif
+ return w;
}
-/* ws, wt - source MSA register numbers.
- inst - MSA fp instruction that needs to be executed.
- opN - number of operads:
- 1 - unary operation.
- 2 - binary operation. */
-static void calculateMSACSR(UInt ws, UInt wt, UInt inst, UInt opN) {
- IRDirty *d;
- IRTemp msacsr = newTemp(Ity_I32);
- /* IRExpr_BBPTR() => Need to pass pointer to guest state to helper. */
- d = unsafeIRDirty_1_N(msacsr, 0,
- "mips_dirtyhelper_calculate_MSACSR",
- &mips_dirtyhelper_calculate_MSACSR,
- mkIRExprVec_4(IRExpr_GSPTR(),
- mkU32(ws),
- mkU32(wt),
- mkU32(inst)));
+#define BITS2(_b1,_b0) \
+ (((_b1) << 1) | (_b0))
- if (opN == 1) { /* Unary operation. */
- /* Declare we're reading guest state. */
- d->nFxState = 2;
- vex_bzero(&d->fxState, sizeof(d->fxState));
- d->fxState[0].fx = Ifx_Read; /* read */
+#define BITS3(_b2,_b1,_b0) \
+ (((_b2) << 2) | ((_b1) << 1) | (_b0))
- if (mode64)
- d->fxState[0].offset = offsetof(VexGuestMIPS64State, guest_MSACSR);
- else
- d->fxState[0].offset = offsetof(VexGuestMIPS32State, guest_MSACSR);
+#define BITS4(_b3,_b2,_b1,_b0) \
+ (((_b3) << 3) | ((_b2) << 2) | ((_b1) << 1) | (_b0))
- d->fxState[0].size = sizeof(UInt);
- d->fxState[1].fx = Ifx_Read; /* read */
- d->fxState[1].offset = msaGuestRegOffset(ws);
- d->fxState[1].size = sizeof(ULong);
- } else if (opN == 2) { /* Binary operation. */
- /* Declare we're reading guest state. */
- d->nFxState = 3;
- vex_bzero(&d->fxState, sizeof(d->fxState));
- d->fxState[0].fx = Ifx_Read; /* read */
+#define BITS5(_b4,_b3,_b2,_b1,_b0) \
+ (((_b4) << 4) | BITS4((_b3),(_b2),(_b1),(_b0)))
- if (mode64)
- d->fxState[0].offset = offsetof(VexGuestMIPS64State, guest_MSACSR);
- else
- d->fxState[0].offset = offsetof(VexGuestMIPS32State, guest_MSACSR);
+#define BITS6(_b5,_b4,_b3,_b2,_b1,_b0) \
+ ((BITS2((_b5),(_b4)) << 4) \
+ | BITS4((_b3),(_b2),(_b1),(_b0)))
- d->fxState[0].size = sizeof(UInt);
- d->fxState[1].fx = Ifx_Read; /* read */
- d->fxState[1].offset = msaGuestRegOffset(ws);
- d->fxState[1].size = sizeof(ULong);
- d->fxState[2].fx = Ifx_Read; /* read */
- d->fxState[2].offset = msaGuestRegOffset(wt);
- d->fxState[2].size = sizeof(ULong);
- }
+#define BITS8(_b7,_b6,_b5,_b4,_b3,_b2,_b1,_b0) \
+ ((BITS4((_b7),(_b6),(_b5),(_b4)) << 4) \
+ | BITS4((_b3),(_b2),(_b1),(_b0)))
- stmt(IRStmt_Dirty(d));
- putMSACSR(mkexpr(msacsr));
-}
+#define LOAD_STORE_PATTERN \
+ t1 = newTemp(mode64 ? Ity_I64 : Ity_I32); \
+ if(!mode64) \
+ assign(t1, binop(Iop_Add32, getIReg(rs), \
+ mkU32(extend_s_16to32(imm)))); \
+ else \
+ assign(t1, binop(Iop_Add64, getIReg(rs), \
+ mkU64(extend_s_16to64(imm)))); \
-static IRExpr *getULR(void)
-{
- if (mode64)
- return IRExpr_Get(offsetof(VexGuestMIPS64State, guest_ULR), Ity_I64);
- else
- return IRExpr_Get(offsetof(VexGuestMIPS32State, guest_ULR), Ity_I32);
-}
+#define LOAD_STORE_PATTERN_MSA(imm) \
+ t1 = newTemp(mode64 ? Ity_I64 : Ity_I32); \
+ if (!mode64) \
+ assign(t1, binop(Iop_Add32, getIReg(ws), \
+ mkU32(extend_s_10to32(imm)))); \
+ else \
+ assign(t1, binop(Iop_Add64, getIReg(ws), \
+ mkU64(extend_s_10to64(imm)))); \
-static void putIReg(UInt archreg, IRExpr * e)
-{
- IRType ty = mode64 ? Ity_I64 : Ity_I32;
- vassert(archreg < 32);
- vassert(typeOfIRExpr(irsb->tyenv, e) == ty);
- if (archreg != 0)
- stmt(IRStmt_Put(integerGuestRegOffset(archreg), e));
-}
+#define LOADX_STORE_PATTERN \
+ t1 = newTemp(mode64 ? Ity_I64 : Ity_I32); \
+ if(!mode64) \
+ assign(t1, binop(Iop_Add32, getIReg(regRs), getIReg(regRt))); \
+ else \
+ assign(t1, binop(Iop_Add64, getIReg(regRs), getIReg(regRt)));
-static void putWReg(UInt wregNo, IRExpr * e) {
- vassert(wregNo <= 31);
- vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_V128);
- stmt(IRStmt_Put(msaGuestRegOffset(wregNo), e));
- stmt(IRStmt_Put(floatGuestRegOffset(wregNo),
- unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, e))));
-}
+#define LWX_SWX_PATTERN64 \
+ t2 = newTemp(Ity_I64); \
+ assign(t2, binop(Iop_And64, mkexpr(t1), mkU64(0xFFFFFFFFFFFFFFFCULL))); \
+ t4 = newTemp(Ity_I32); \
+ assign(t4, mkNarrowTo32( ty, binop(Iop_And64, \
+ mkexpr(t1), mkU64(0x3))));
-static IRExpr *mkNarrowTo32(IRType ty, IRExpr * src)
-{
- vassert(ty == Ity_I32 || ty == Ity_I64);
- return ty == Ity_I64 ? unop(Iop_64to32, src) : src;
-}
+#define LWX_SWX_PATTERN64_1 \
+ t2 = newTemp(Ity_I64); \
+ assign(t2, binop(Iop_And64, mkexpr(t1), mkU64(0xFFFFFFFFFFFFFFF8ULL))); \
+ t4 = newTemp(Ity_I64); \
+ assign(t4, binop(Iop_And64, mkexpr(t1), mkU64(0x7)));
-static void putLO(IRExpr * e)
-{
- if (mode64) {
- stmt(IRStmt_Put(offsetof(VexGuestMIPS64State, guest_LO), e));
- } else {
- stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_LO), e));
- /* Add value to lower 32 bits of ac0 to maintain compatibility between
- regular MIPS32 instruction set and MIPS DSP ASE. Keep higher 32bits
- unchanged. */
- IRTemp t_lo = newTemp(Ity_I32);
- IRTemp t_hi = newTemp(Ity_I32);
- assign(t_lo, e);
- assign(t_hi, unop(Iop_64HIto32, getAcc(0)));
- stmt(IRStmt_Put(accumulatorGuestRegOffset(0),
- binop(Iop_32HLto64, mkexpr(t_hi), mkexpr(t_lo))));
- }
-}
+#define LWX_SWX_PATTERN \
+ t2 = newTemp(Ity_I32); \
+ assign(t2, binop(Iop_And32, mkexpr(t1), mkU32(0xFFFFFFFC))); \
+ t4 = newTemp(Ity_I32); \
+ assign(t4, binop(Iop_And32, mkexpr(t1), mkU32(0x00000003)))
-static void putHI(IRExpr * e)
-{
- if (mode64) {
- stmt(IRStmt_Put(offsetof(VexGuestMIPS64State, guest_HI), e));
- } else {
- stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_HI), e));
- /* Add value to higher 32 bits of ac0 to maintain compatibility between
- regular MIPS32 instruction set and MIPS DSP ASE. Keep lower 32bits
- unchanged. */
- IRTemp t_lo = newTemp(Ity_I32);
- IRTemp t_hi = newTemp(Ity_I32);
- assign(t_hi, e);
- assign(t_lo, unop(Iop_64to32, getAcc(0)));
- stmt(IRStmt_Put(accumulatorGuestRegOffset(0),
- binop(Iop_32HLto64, mkexpr(t_hi), mkexpr(t_lo))));
- }
-}
+#define SXXV_PATTERN(op) \
+ putIReg(rd, binop(op, \
+ getIReg(rt), \
+ unop(Iop_32to8, \
+ binop(Iop_And32, \
+ getIReg(rs), \
+ mkU32(0x0000001F) \
+ ) \
+ ) \
+ ) \
+ )
-/* Put value to accumulator(helper function for MIPS32 DSP ASE instructions). */
-static void putAcc(UInt acNo, IRExpr * e)
-{
- vassert(!mode64);
- vassert(acNo <= 3);
- vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I64);
- stmt(IRStmt_Put(accumulatorGuestRegOffset(acNo), e));
-/* If acNo = 0, split value to HI and LO regs in order to maintain compatibility
- between MIPS32 and MIPS DSP ASE insn sets. */
- if (0 == acNo) {
- putLO(unop(Iop_64to32, e));
- putHI(unop(Iop_64HIto32, e));
- }
-}
+#define SXXV_PATTERN64(op) \
+ putIReg(rd, mkWidenFrom32(ty, binop(op, \
+ mkNarrowTo32(ty, getIReg(rt)), \
+ unop(Iop_32to8, \
+ binop(Iop_And32, \
+ mkNarrowTo32(ty, getIReg(rs)), \
+ mkU32(0x0000001F) \
+ ) \
+ ) \
+ ), True \
+ ))
-static IRExpr *mkNarrowTo8 ( IRType ty, IRExpr * src )
-{
- vassert(ty == Ity_I32 || ty == Ity_I64);
- return ty == Ity_I64 ? unop(Iop_64to8, src) : unop(Iop_32to8, src);
-}
+#define SXX_PATTERN(op) \
+ putIReg(rd, binop(op, getIReg(rt), mkU8(sa)));
-static IRExpr *mkNarrowTo16 ( IRType ty, IRExpr * src )
-{
- vassert(ty == Ity_I32 || ty == Ity_I64);
- return ty == Ity_I64 ? unop(Iop_64to16, src) : unop(Iop_32to16, src);
-}
+#define ALU_PATTERN(op) \
+ putIReg(rd, binop(op, getIReg(rs), getIReg(rt)));
-static void putPC(IRExpr * e)
-{
- stmt(IRStmt_Put(OFFB_PC, e));
-}
+#define ALUI_PATTERN(op) \
+ putIReg(rt, binop(op, getIReg(rs), mkU32(imm)));
-static IRExpr *mkWidenFrom32(IRType ty, IRExpr * src, Bool sined)
-{
- vassert(ty == Ity_I32 || ty == Ity_I64);
- if (ty == Ity_I32)
- return src;
- return (sined) ? unop(Iop_32Sto64, src) : unop(Iop_32Uto64, src);
-}
+#define ALUI_PATTERN64(op) \
+ putIReg(rt, binop(op, getIReg(rs), mkU64(imm)));
-/* Narrow 8/16/32 bit int expr to 8/16/32. Clearly only some
- of these combinations make sense. */
-static IRExpr *narrowTo(IRType dst_ty, IRExpr * e)
-{
- IRType src_ty = typeOfIRExpr(irsb->tyenv, e);
- if (src_ty == dst_ty)
- return e;
- if (src_ty == Ity_I32 && dst_ty == Ity_I16)
- return unop(Iop_32to16, e);
- if (src_ty == Ity_I32 && dst_ty == Ity_I8)
- return unop(Iop_32to8, e);
- if (src_ty == Ity_I64 && dst_ty == Ity_I8) {
- vassert(mode64);
- return unop(Iop_64to8, e);
- }
- if (src_ty == Ity_I64 && dst_ty == Ity_I16) {
- vassert(mode64);
- return unop(Iop_64to16, e);
- }
- vpanic("narrowTo(mips)");
- return 0;
-}
+#define ALU_PATTERN64(op) \
+ putIReg(rd, mkWidenFrom32(ty, binop(op, \
+ mkNarrowTo32(ty, getIReg(rs)), \
+ mkNarrowTo32(ty, getIReg(rt))), True));
-static IRExpr *getLoFromF64(IRType ty, IRExpr * src)
-{
- vassert(ty == Ity_F32 || ty == Ity_F64);
- if (ty == Ity_F64) {
- IRTemp t0, t1;
- t0 = newTemp(Ity_I64);
- t1 = newTemp(Ity_I32);
- assign(t0, unop(Iop_ReinterpF64asI64, src));
- assign(t1, unop(Iop_64to32, mkexpr(t0)));
- return unop(Iop_ReinterpI32asF32, mkexpr(t1));
- } else
- return src;
-}
+#define FP_CONDITIONAL_CODE \
+ t3 = newTemp(Ity_I32); \
+ assign(t3, binop(Iop_And32, \
+ IRExpr_ITE( binop(Iop_CmpEQ32, mkU32(cc), mkU32(0)), \
+ binop(Iop_Shr32, getFCSR(), mkU8(23)), \
+ binop(Iop_Shr32, getFCSR(), mkU8(24+cc))), \
+ mkU32(0x1)));
-static inline IRExpr *getHiFromF64(IRExpr * src)
-{
- vassert(typeOfIRExpr(irsb->tyenv, src) == Ity_F64);
- return unop(Iop_ReinterpI32asF32, unop(Iop_64HIto32,
- unop(Iop_ReinterpF64asI64, src)));
-}
-static IRExpr *mkWidenFromF32(IRType ty, IRExpr * src)
-{
- vassert(ty == Ity_F32 || ty == Ity_F64);
- if (ty == Ity_F64) {
- IRTemp t0 = newTemp(Ity_I32);
- IRTemp t1 = newTemp(Ity_I64);
- assign(t0, unop(Iop_ReinterpF32asI32, src));
- assign(t1, binop(Iop_32HLto64, mkU32(0x0), mkexpr(t0)));
- return unop(Iop_ReinterpI64asF64, mkexpr(t1));
- } else
- return src;
-}
-/* Convenience function to move to next instruction on condition. */
-static void mips_next_insn_if(IRExpr *condition) {
- vassert(typeOfIRExpr(irsb->tyenv, condition) == Ity_I1);
+#define ILLEGAL_INSTRUCTON \
+ putPC(mkU32(guest_PC_curr_instr + 4)); \
+ dres->jk_StopHere = Ijk_SigILL; \
+ dres->whatNext = Dis_StopHere;
- stmt(IRStmt_Exit(condition, Ijk_Boring,
- mode64 ? IRConst_U64(guest_PC_curr_instr + 4) :
- IRConst_U32(guest_PC_curr_instr + 4),
- OFFB_PC));
-}
+#define LLADDR_INVALID \
+ (mode64 ? mkU64(0xFFFFFFFFFFFFFFFFULL) : mkU32(0xFFFFFFFF))
-static IRExpr *dis_branch_likely(IRExpr * guard, UInt imm)
+/*------------------------------------------------------------*/
+/*--- Field helpers ---*/
+/*------------------------------------------------------------*/
+
+static Bool branch_or_jump(const UChar * addr)
{
- ULong branch_offset;
- IRTemp t0;
+ UInt fmt;
+ UInt cins = getUInt(addr);
- /* PC = PC + (SignExtend(signed_immed_24) << 2)
- An 18-bit signed offset (the 16-bit offset field shifted left 2 bits)
- is added to the address of the instruction following
- the branch (not the branch itself), in the branch delay slot, to form
- a PC-relative effective target address. */
- if (mode64)
- branch_offset = extend_s_18to64(imm << 2);
- else
- branch_offset = extend_s_18to32(imm << 2);
+ UInt opcode = get_opcode(cins);
+ UInt rt = get_rt(cins);
+ UInt function = get_function(cins);
- t0 = newTemp(Ity_I1);
- assign(t0, guard);
+ /* bgtz, blez, bne, beq, jal */
+ if (opcode == 0x07 || opcode == 0x06 || opcode == 0x05 || opcode == 0x04
+ || opcode == 0x03 || opcode == 0x02) {
+ return True;
+ }
- if (mode64)
- stmt(IRStmt_Exit(mkexpr(t0), Ijk_Boring,
- IRConst_U64(guest_PC_curr_instr + 8), OFFB_PC));
- else
- stmt(IRStmt_Exit(mkexpr(t0), Ijk_Boring,
- IRConst_U32(guest_PC_curr_instr + 8), OFFB_PC));
+ /* bgez */
+ if (opcode == 0x01 && rt == 0x01) {
+ return True;
+ }
- irsb->jumpkind = Ijk_Boring;
+ /* bgezal */
+ if (opcode == 0x01 && rt == 0x11) {
+ return True;
+ }
- if (mode64)
- return mkU64(guest_PC_curr_instr + 4 + branch_offset);
- else
- return mkU32(guest_PC_curr_instr + 4 + branch_offset);
-}
+ /* bltzal */
+ if (opcode == 0x01 && rt == 0x10) {
+ return True;
+ }
-static void dis_branch(Bool link, IRExpr * guard, UInt imm, IRStmt ** set)
-{
- ULong branch_offset;
- IRTemp t0;
+ /* bltz */
+ if (opcode == 0x01 && rt == 0x00) {
+ return True;
+ }
- if (link) { /* LR (GPR31) = addr of the 2nd instr after branch instr */
- if (mode64)
- putIReg(31, mkU64(guest_PC_curr_instr + 8));
- else
- putIReg(31, mkU32(guest_PC_curr_instr + 8));
+ /* jalr */
+ if (opcode == 0x00 && function == 0x09) {
+ return True;
}
- /* PC = PC + (SignExtend(signed_immed_24) << 2)
- An 18-bit signed offset (the 16-bit offset field shifted left 2 bits)
- is added to the address of the instruction following
- the branch (not the branch itself), in the branch delay slot, to form
- a PC-relative effective target address. */
+ /* jr */
+ if (opcode == 0x00 && function == 0x08) {
+ return True;
+ }
- if (mode64)
- branch_offset = extend_s_18to64(imm << 2);
- else
- branch_offset = extend_s_18to32(imm << 2);
+ if (opcode == 0x11) {
+ /* bc1f & bc1t */
+ fmt = get_fmt(cins);
- t0 = newTemp(Ity_I1);
- assign(t0, guard);
- if (mode64)
- *set = IRStmt_Exit(mkexpr(t0), link ? Ijk_Call : Ijk_Boring,
- IRConst_U64(guest_PC_curr_instr + 4 + branch_offset),
- OFFB_PC);
- else
- *set = IRStmt_Exit(mkexpr(t0), link ? Ijk_Call : Ijk_Boring,
- IRConst_U32(guest_PC_curr_instr + 4 +
- (UInt) branch_offset), OFFB_PC);
-}
+ if (fmt == 0x08) {
+ return True;
+ }
-static void dis_branch_compact(Bool link, IRExpr * guard, UInt imm,
- DisResult *dres)
-{
- ULong branch_offset;
- IRTemp t0;
+ /* MSA branches */
+ /* bnz.df, bz.df */
+ if (fmt >= 0x18) {
+ return True;
+ }
- if (link) { /* LR (GPR31) = addr of the instr after branch instr */
- if (mode64)
- putIReg(31, mkU64(guest_PC_curr_instr + 4));
- else
- putIReg(31, mkU32(guest_PC_curr_instr + 4));
- dres->jk_StopHere = Ijk_Call;
- } else {
- dres->jk_StopHere = Ijk_Boring;
- }
+ /* bnz.v */
+ if (fmt == 0x0f) {
+ return True;
+ }
- dres->whatNext = Dis_StopHere;
+ /* bz.v */
+ if (fmt == 0x0b) {
+ return True;
+ }
- /* PC = PC + (SignExtend(signed_immed_24) << 2)
- An 18-bit signed offset (the 16-bit offset field shifted left 2 bits)
- is added to the address of the instruction following
- the branch (not the branch itself), in the branch delay slot, to form
- a PC-relative effective target address. */
+ /* R6 branches */
+ /* bc1eqz */
+ if (fmt == 0x09) {
+ return True;
+ }
- if (mode64)
- branch_offset = extend_s_18to64(imm << 2);
- else
- branch_offset = extend_s_18to32(imm << 2);
+ /* bc1nez */
+ if (fmt == 0x0D) {
+ return True;
+ }
+ }
- t0 = newTemp(Ity_I1);
- assign(t0, guard);
+ /* bposge32 */
+ if (opcode == 0x01 && rt == 0x1c) {
+ return True;
+ }
- if (mode64) {
- stmt(IRStmt_Exit(mkexpr(t0), link ? Ijk_Call : Ijk_Boring,
- IRConst_U64(guest_PC_curr_instr + 4 + branch_offset),
- OFFB_PC));
- putPC(mkU64(guest_PC_curr_instr + 4));
- } else {
- stmt(IRStmt_Exit(mkexpr(t0), link ? Ijk_Call : Ijk_Boring,
- IRConst_U32(guest_PC_curr_instr + 4 +
- (UInt) branch_offset), OFFB_PC));
- putPC(mkU32(guest_PC_curr_instr + 4));
+ /* Cavium Specific instructions. */
+ if (opcode == 0x32 || opcode == 0x3A || opcode == 0x36 || opcode == 0x3E) {
+ /* BBIT0, BBIT1, BBIT032, BBIT132 */
+ return True;
}
-}
-static IRExpr *getFReg(UInt fregNo)
-{
- vassert(fregNo < 32);
- IRType ty = fp_mode64 ? Ity_F64 : Ity_F32;
- return IRExpr_Get(floatGuestRegOffset(fregNo), ty);
+ return False;
}
-static IRExpr *getDReg(UInt dregNo)
+static Bool is_Branch_or_Jump_and_Link(const UChar * addr)
{
- vassert(dregNo < 32);
- if (fp_mode64) {
- return IRExpr_Get(floatGuestRegOffset(dregNo), Ity_F64);
- } else {
- /* Read a floating point register pair and combine their contents into a
- 64-bit value */
- IRTemp t0 = newTemp(Ity_F32);
- IRTemp t1 = newTemp(Ity_F32);
- IRTemp t2 = newTemp(Ity_F64);
- IRTemp t3 = newTemp(Ity_I32);
- IRTemp t4 = newTemp(Ity_I32);
- IRTemp t5 = newTemp(Ity_I64);
+ UInt cins = getUInt(addr);
- assign(t0, getFReg(dregNo & (~1)));
- assign(t1, getFReg(dregNo | 1));
+ UInt opcode = get_opcode(cins);
+ UInt rt = get_rt(cins);
+ UInt function = get_function(cins);
- assign(t3, unop(Iop_ReinterpF32asI32, mkexpr(t0)));
- assign(t4, unop(Iop_ReinterpF32asI32, mkexpr(t1)));
- assign(t5, binop(Iop_32HLto64, mkexpr(t4), mkexpr(t3)));
- assign(t2, unop(Iop_ReinterpI64asF64, mkexpr(t5)));
+ /* jal */
+ if (opcode == 0x02) {
+ return True;
+ }
- return mkexpr(t2);
+ /* bgezal or bal(r6) */
+ if (opcode == 0x01 && rt == 0x11) {
+ return True;
+ }
+
+ /* bltzal */
+ if (opcode == 0x01 && rt == 0x10) {
+ return True;
+ }
+
+ /* jalr */
+ if (opcode == 0x00 && function == 0x09) {
+ return True;
}
+
+ return False;
}
-static void putFReg(UInt dregNo, IRExpr * e)
+static Bool branch_or_link_likely(const UChar * addr)
{
- vassert(dregNo < 32);
- IRType ty = fp_mode64 ? Ity_F64 : Ity_F32;
- vassert(typeOfIRExpr(irsb->tyenv, e) == ty);
+ UInt cins = getUInt(addr);
+ UInt opcode = get_opcode(cins);
+ UInt rt = get_rt(cins);
- if (fp_mode64_fre) {
- IRTemp t0 = newTemp(Ity_F32);
- assign(t0, getLoFromF64(ty, e));
-#if defined (_MIPSEL)
- stmt(IRStmt_Put(floatGuestRegOffset(dregNo), mkexpr(t0)));
- if (dregNo & 1)
- stmt(IRStmt_Put(floatGuestRegOffset(dregNo) - 4, mkexpr(t0)));
-#else
- stmt(IRStmt_Put(floatGuestRegOffset(dregNo) + 4, mkexpr(t0)));
- if (dregNo & 1)
- stmt(IRStmt_Put(floatGuestRegOffset(dregNo & (~1)), mkexpr(t0)));
-#endif
- } else {
- stmt(IRStmt_Put(floatGuestRegOffset(dregNo), e));
- }
+ /* bgtzl, blezl, bnel, beql */
+ if (opcode == 0x17 || opcode == 0x16 || opcode == 0x15 || opcode == 0x14)
+ return True;
- if (has_msa && fp_mode64) {
- stmt(IRStmt_Put(msaGuestRegOffset(dregNo),
- binop(Iop_64HLtoV128,
- unop(Iop_ReinterpF64asI64, e),
- unop(Iop_ReinterpF64asI64, e))));
- }
+ /* bgezl */
+ if (opcode == 0x01 && rt == 0x03)
+ return True;
+
+ /* bgezall */
+ if (opcode == 0x01 && rt == 0x13)
+ return True;
+
+ /* bltzall */
+ if (opcode == 0x01 && rt == 0x12)
+ return True;
+
+ /* bltzl */
+ if (opcode == 0x01 && rt == 0x02)
+ return True;
+
+ return False;
}
-static void putDReg(UInt dregNo, IRExpr * e)
+/*------------------------------------------------------------*/
+/*--- Helper bits and pieces for creating IR fragments. ---*/
+/*------------------------------------------------------------*/
+
+/* Generate an expression for SRC rotated right by ROT. */
+static IRExpr *genROR32(IRExpr * src, Int rot)
{
- if (fp_mode64) {
- vassert(dregNo < 32);
- IRType ty = Ity_F64;
- vassert(typeOfIRExpr(irsb->tyenv, e) == ty);
- stmt(IRStmt_Put(floatGuestRegOffset(dregNo), e));
- if (fp_mode64_fre) {
- IRTemp t0 = newTemp(Ity_F32);
- if (dregNo & 1) {
- assign(t0, getLoFromF64(ty, e));
-#if defined (_MIPSEL)
- stmt(IRStmt_Put(floatGuestRegOffset(dregNo) - 4, mkexpr(t0)));
-#else
- stmt(IRStmt_Put(floatGuestRegOffset(dregNo & (~1)), mkexpr(t0)));
-#endif
- } else {
- assign(t0, getHiFromF64(e));
-#if defined (_MIPSEL)
- stmt(IRStmt_Put(floatGuestRegOffset(dregNo | 1), mkexpr(t0)));
-#else
- stmt(IRStmt_Put(floatGuestRegOffset(dregNo | 1) + 4, mkexpr(t0)));
-#endif
- }
- }
- if (has_msa)
- stmt(IRStmt_Put(msaGuestRegOffset(dregNo),
- binop(Iop_64HLtoV128,
- unop(Iop_ReinterpF64asI64, e),
- unop(Iop_ReinterpF64asI64, e))));
- } else {
- vassert(dregNo < 32);
- vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_F64);
- IRTemp t1 = newTemp(Ity_F64);
- IRTemp t4 = newTemp(Ity_I32);
- IRTemp t5 = newTemp(Ity_I32);
- IRTemp t6 = newTemp(Ity_I64);
- assign(t1, e);
- assign(t6, unop(Iop_ReinterpF64asI64, mkexpr(t1)));
- assign(t4, unop(Iop_64HIto32, mkexpr(t6))); /* hi */
- assign(t5, unop(Iop_64to32, mkexpr(t6))); /* lo */
- putFReg(dregNo & (~1), unop(Iop_ReinterpI32asF32, mkexpr(t5)));
- putFReg(dregNo | 1, unop(Iop_ReinterpI32asF32, mkexpr(t4)));
- }
+ vassert(rot >= 0 && rot < 32);
+
+ if (rot == 0)
+ return src;
+
+ return binop(Iop_Or32, binop(Iop_Shl32, src, mkU8(32 - rot)),
+ binop(Iop_Shr32, src, mkU8(rot)));
}
-static void setFPUCondCode(IRExpr * e, UInt cc)
+static IRExpr *genRORV32(IRExpr * src, IRExpr * rs)
{
- if (cc == 0) {
- putFCSR(binop(Iop_And32, getFCSR(), mkU32(0xFF7FFFFF)));
- putFCSR(binop(Iop_Or32, getFCSR(), binop(Iop_Shl32, e, mkU8(23))));
+ IRTemp t0 = newTemp(Ity_I8);
+ IRTemp t1 = newTemp(Ity_I8);
+
+ assign(t0, unop(Iop_32to8, binop(Iop_And32, rs, mkU32(0x0000001F))));
+ assign(t1, binop(Iop_Sub8, mkU8(32), mkexpr(t0)));
+ return binop(Iop_Or32, binop(Iop_Shl32, src, mkexpr(t1)),
+ binop(Iop_Shr32, src, mkexpr(t0)));
+}
+
+static void jmp_lit32 ( /*MOD*/ DisResult* dres, IRJumpKind kind, Addr32 d32 )
+{
+ vassert(dres->whatNext == Dis_Continue);
+ vassert(dres->len == 0);
+ vassert(dres->continueAt == 0);
+ vassert(dres->jk_StopHere == Ijk_INVALID);
+ dres->whatNext = Dis_StopHere;
+ dres->jk_StopHere = kind;
+ stmt( IRStmt_Put( OFFB_PC, mkU32(d32) ) );
+}
+
+static void jmp_lit64 ( /*MOD*/ DisResult* dres, IRJumpKind kind, Addr64 d64 )
+{
+ vassert(dres->whatNext == Dis_Continue);
+ vassert(dres->len == 0);
+ vassert(dres->continueAt == 0);
+ vassert(dres->jk_StopHere == Ijk_INVALID);
+ dres->whatNext = Dis_StopHere;
+ dres->jk_StopHere = kind;
+ stmt(IRStmt_Put(OFFB_PC, mkU64(d64)));
+}
+
+/* Get value from accumulator (helper function for MIPS32 DSP ASE instructions).
+ This function should be called before any other operation if widening
+ multiplications are used. */
+IRExpr *getAcc(UInt acNo)
+{
+ vassert(!mode64);
+ vassert(acNo <= 3);
+ return IRExpr_Get(accumulatorGuestRegOffset(acNo), Ity_I64);
+}
+
+/* Get value from DSPControl register (helper function for MIPS32 DSP ASE
+ instructions). */
+IRExpr *getDSPControl(void)
+{
+ vassert(!mode64);
+ return IRExpr_Get(offsetof(VexGuestMIPS32State, guest_DSPControl), Ity_I32);
+}
+
+/* Fetch a byte from the guest insn stream. */
+static UChar getIByte(Int delta)
+{
+ return guest_code[delta];
+}
+
+IRExpr *getIReg(UInt iregNo)
+{
+ if (0 == iregNo) {
+ return mode64 ? mkU64(0x0) : mkU32(0x0);
} else {
- putFCSR(binop(Iop_And32, getFCSR(), unop(Iop_Not32,
- binop(Iop_Shl32, mkU32(0x01000000), mkU8(cc)))));
- putFCSR(binop(Iop_Or32, getFCSR(), binop(Iop_Shl32, e, mkU8(24 + cc))));
+ IRType ty = mode64 ? Ity_I64 : Ity_I32;
+ vassert(iregNo < 32);
+ return IRExpr_Get(integerGuestRegOffset(iregNo), ty);
}
}
-static IRExpr* get_IR_roundingmode ( void )
+static IRExpr *getWReg(UInt wregNo)
{
-/*
- rounding mode | MIPS | IR
- ------------------------
- to nearest | 00 | 00
- to zero | 01 | 11
- to +infinity | 10 | 10
- to -infinity | 11 | 01
-*/
- IRTemp rm_MIPS = newTemp(Ity_I32);
- /* Last two bits in FCSR are rounding mode. */
+ vassert(wregNo <= 31);
+ return IRExpr_Get(msaGuestRegOffset(wregNo), Ity_V128);
+}
+static IRExpr *getHI(void)
+{
if (mode64)
- assign(rm_MIPS, binop(Iop_And32, IRExpr_Get(offsetof(VexGuestMIPS64State,
- guest_FCSR), Ity_I32), mkU32(3)));
+ return IRExpr_Get(offsetof(VexGuestMIPS64State, guest_HI), Ity_I64);
else
- assign(rm_MIPS, binop(Iop_And32, IRExpr_Get(offsetof(VexGuestMIPS32State,
- guest_FCSR), Ity_I32), mkU32(3)));
-
- /* rm_IR = XOR( rm_MIPS32, (rm_MIPS32 << 1) & 2) */
+ return IRExpr_Get(offsetof(VexGuestMIPS32State, guest_HI), Ity_I32);
+}
- return binop(Iop_Xor32, mkexpr(rm_MIPS), binop(Iop_And32,
- binop(Iop_Shl32, mkexpr(rm_MIPS), mkU8(1)), mkU32(2)));
+static IRExpr *getLO(void)
+{
+ if (mode64)
+ return IRExpr_Get(offsetof(VexGuestMIPS64State, guest_LO), Ity_I64);
+ else
+ return IRExpr_Get(offsetof(VexGuestMIPS32State, guest_LO), Ity_I32);
}
-static IRExpr* get_IR_roundingmode_MSA ( void ) {
- /*
- rounding mode | MIPS | IR
- ------------------------
- to nearest | 00 | 00
- to zero | 01 | 11
- to +infinity | 10 | 10
- to -infinity | 11 | 01
- */
- IRTemp rm_MIPS = newTemp(Ity_I32);
- /* Last two bits in MSACSR are rounding mode. */
+static IRExpr *getFCSR(void)
+{
+ if (mode64)
+ return IRExpr_Get(offsetof(VexGuestMIPS64State, guest_FCSR), Ity_I32);
+ else
+ return IRExpr_Get(offsetof(VexGuestMIPS32State, guest_FCSR), Ity_I32);
+}
+static IRExpr *getLLaddr(void)
+{
if (mode64)
- assign(rm_MIPS, binop(Iop_And32, IRExpr_Get(offsetof(VexGuestMIPS64State,
- guest_MSACSR), Ity_I32), mkU32(3)));
+ return IRExpr_Get(offsetof(VexGuestMIPS64State, guest_LLaddr), Ity_I64);
else
- assign(rm_MIPS, binop(Iop_And32, IRExpr_Get(offsetof(VexGuestMIPS32State,
- guest_MSACSR), Ity_I32), mkU32(3)));
+ return IRExpr_Get(offsetof(VexGuestMIPS32State, guest_LLaddr), Ity_I32);
+}
- /* rm_IR = XOR( rm_MIPS32, (rm_MIPS32 << 1) & 2) */
- return binop(Iop_Xor32, mkexpr(rm_MIPS), binop(Iop_And32,
- binop(Iop_Shl32, mkexpr(rm_MIPS), mkU8(1)), mkU32(2)));
+static IRExpr *getLLdata(void)
+{
+ if (mode64)
+ return IRExpr_Get(offsetof(VexGuestMIPS64State, guest_LLdata), Ity_I64);
+ else
+ return IRExpr_Get(offsetof(VexGuestMIPS32State, guest_LLdata), Ity_I32);
}
-/* sz, ULong -> IRExpr */
-static IRExpr *mkSzImm ( IRType ty, ULong imm64 )
+static IRExpr *getMSACSR(void)
{
- vassert(ty == Ity_I32 || ty == Ity_I64);
- return ty == Ity_I64 ? mkU64(imm64) : mkU32((UInt) imm64);
+ if (mode64)
+ return IRExpr_Get(offsetof(VexGuestMIPS64State, guest_MSACSR), Ity_I32);
+ else
+ return IRExpr_Get(offsetof(VexGuestMIPS32State, guest_MSACSR), Ity_I32);
}
-static IRConst *mkSzConst ( IRType ty, ULong imm64 )
+/* Get byte from register reg, byte pos from 0 to 3 (or 7 for MIPS64) . */
+static IRExpr *getByteFromReg(UInt reg, UInt byte_pos)
{
- vassert(ty == Ity_I32 || ty == Ity_I64);
- return (ty == Ity_I64 ? IRConst_U64(imm64) : IRConst_U32((UInt) imm64));
+ UInt pos = byte_pos * 8;
+
+ if (mode64)
+ return unop(Iop_64to8, binop(Iop_And64,
+ binop(Iop_Shr64, getIReg(reg), mkU8(pos)),
+ mkU64(0xFF)));
+ else
+ return unop(Iop_32to8, binop(Iop_And32,
+ binop(Iop_Shr32, getIReg(reg), mkU8(pos)),
+ mkU32(0xFF)));
}
-/* Make sure we get valid 32 and 64bit addresses */
-static Addr64 mkSzAddr ( IRType ty, Addr64 addr )
+static void putFCSR(IRExpr * e)
{
- vassert(ty == Ity_I32 || ty == Ity_I64);
- return (ty == Ity_I64 ? (Addr64) addr :
- (Addr64) extend_s_32to64(toUInt(addr)));
+ if (mode64)
+ stmt(IRStmt_Put(offsetof(VexGuestMIPS64State, guest_FCSR), e));
+ else
+ stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_FCSR), e));
}
-/* Shift and Rotate instructions for MIPS64 */
-static Bool dis_instr_shrt ( UInt theInstr )
+static void putLLaddr(IRExpr * e)
{
- UInt opc2 = get_function(theInstr);
- UChar regRs = get_rs(theInstr);
- UChar regRt = get_rt(theInstr);
- UChar regRd = get_rd(theInstr);
- UChar uImmsa = get_sa(theInstr);
- Long sImmsa = extend_s_16to64(uImmsa);
- IRType ty = mode64 ? Ity_I64 : Ity_I32;
- IRTemp tmp = newTemp(ty);
- IRTemp tmpOr = newTemp(ty);
- IRTemp tmpRt = newTemp(ty);
- IRTemp tmpRs = newTemp(ty);
- IRTemp tmpRd = newTemp(ty);
+ if (mode64)
+ stmt(IRStmt_Put(offsetof(VexGuestMIPS64State, guest_LLaddr), e));
+ else
+ stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_LLaddr), e));
+}
- assign(tmpRs, getIReg(regRs));
- assign(tmpRt, getIReg(regRt));
+static void putLLdata(IRExpr * e)
+{
+ if (mode64)
+ stmt(IRStmt_Put(offsetof(VexGuestMIPS64State, guest_LLdata), e));
+ else
+ stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_LLdata), e));
+}
- switch (opc2) {
- case 0x3A:
- if ((regRs & 0x01) == 0) {
- /* Doubleword Shift Right Logical - DSRL; MIPS64 */
- DIP("dsrl r%u, r%u, %lld", regRd, regRt, sImmsa);
- assign(tmpRd, binop(Iop_Shr64, mkexpr(tmpRt), mkU8(uImmsa)));
- putIReg(regRd, mkexpr(tmpRd));
- } else if ((regRs & 0x01) == 1) {
- /* Doubleword Rotate Right - DROTR; MIPS64r2 */
- vassert(mode64);
- DIP("drotr r%u, r%u, %lld", regRd, regRt, sImmsa);
- IRTemp tmpL = newTemp(ty);
- IRTemp tmpR = newTemp(ty);
- assign(tmpR, binop(Iop_Shr64, mkexpr(tmpRt), mkU8(uImmsa)));
- assign(tmp, binop(Iop_Shl64, mkexpr(tmpRt), mkU8(63 - uImmsa)));
- assign(tmpL, binop(Iop_Shl64, mkexpr(tmp), mkU8(1)));
- assign(tmpRd, binop(Iop_Or64, mkexpr(tmpL), mkexpr(tmpR)));
- putIReg(regRd, mkexpr(tmpRd));
- } else
- return False;
- break;
+static void putMSACSR(IRExpr * e)
+{
+ if (mode64)
+ stmt(IRStmt_Put(offsetof(VexGuestMIPS64State, guest_MSACSR), e));
+ else
+ stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_MSACSR), e));
+}
- case 0x3E:
- if ((regRs & 0x01) == 0) {
- /* Doubleword Shift Right Logical Plus 32 - DSRL32; MIPS64 */
- DIP("dsrl32 r%u, r%u, %lld", regRd, regRt, sImmsa + 32);
- assign(tmpRd, binop(Iop_Shr64, mkexpr(tmpRt), mkU8(uImmsa + 32)));
- putIReg(regRd, mkexpr(tmpRd));
- } else if ((regRs & 0x01) == 1) {
- /* Doubleword Rotate Right Plus 32 - DROTR32; MIPS64r2 */
- DIP("drotr32 r%u, r%u, %lld", regRd, regRt, sImmsa);
- vassert(mode64);
- IRTemp tmpL = newTemp(ty);
- IRTemp tmpR = newTemp(ty);
- /* (tmpRt >> sa) | (tmpRt << (64 - sa)) */
- assign(tmpR, binop(Iop_Shr64, mkexpr(tmpRt), mkU8(uImmsa + 32)));
- assign(tmp, binop(Iop_Shl64, mkexpr(tmpRt),
- mkU8(63 - (uImmsa + 32))));
- assign(tmpL, binop(Iop_Shl64, mkexpr(tmp), mkU8(1)));
- assign(tmpRd, binop(Iop_Or64, mkexpr(tmpL), mkexpr(tmpR)));
- putIReg(regRd, mkexpr(tmpRd));
- } else
- return False;
- break;
+/* fs - fpu source register number.
+ inst - fpu instruction that needs to be executed.
+ sz32 - size of source register.
+ opN - number of operads:
+ 1 - unary operation.
+ 2 - binary operation. */
+static void calculateFCSR(UInt fs, UInt ft, UInt inst, Bool sz32, UInt opN)
+{
+ IRDirty *d;
+ IRTemp fcsr = newTemp(Ity_I32);
- case 0x16:
- if ((uImmsa & 0x01) == 0) {
- /* Doubleword Shift Right Logical Variable - DSRLV; MIPS64 */
- DIP("dsrlv r%u, r%u, r%u", regRd, regRt, regRs);
- IRTemp tmpRs8 = newTemp(Ity_I8);
- /* s = tmpRs[5..0] */
- assign(tmp, binop(Iop_And64, mkexpr(tmpRs), mkU64(63)));
- assign(tmpRs8, mkNarrowTo8(ty, mkexpr(tmp)));
- assign(tmpRd, binop(Iop_Shr64, mkexpr(tmpRt), mkexpr(tmpRs8)));
- putIReg(regRd, mkexpr(tmpRd));
- } else if ((uImmsa & 0x01) == 1) {
- /* Doubleword Rotate Right Variable - DROTRV; MIPS64r2 */
- DIP("drotrv r%u, r%u, r%u", regRd, regRt, regRs);
- IRTemp tmpL = newTemp(ty);
- IRTemp tmpR = newTemp(ty);
- IRTemp tmpRs8 = newTemp(Ity_I8);
- IRTemp tmpLs8 = newTemp(Ity_I8);
- IRTemp tmp64 = newTemp(ty);
- /* s = tmpRs[5...0]
- m = 64 - s
- (tmpRt << s) | (tmpRt >> m) */
+ /* IRExpr_GSPTR() => Need to pass pointer to guest state to helper. */
+ if (fp_mode64)
+ d = unsafeIRDirty_1_N(fcsr, 0,
+ "mips_dirtyhelper_calculate_FCSR_fp64",
+ &mips_dirtyhelper_calculate_FCSR_fp64,
+ mkIRExprVec_4(IRExpr_GSPTR(),
+ mkU32(fs),
+ mkU32(ft),
+ mkU32(inst)));
+ else
+ d = unsafeIRDirty_1_N(fcsr, 0,
+ "mips_dirtyhelper_calculate_FCSR_fp32",
+ &mips_dirtyhelper_calculate_FCSR_fp32,
+ mkIRExprVec_4(IRExpr_GSPTR(),
+ mkU32(fs),
+ mkU32(ft),
+ mkU32(inst)));
- assign(tmp64, binop(Iop_And64, mkexpr(tmpRs), mkSzImm(ty, 63)));
- assign(tmp, binop(Iop_Sub64, mkU64(63), mkexpr(tmp64)));
+ if (opN == 1) { /* Unary operation. */
+ /* Declare we're reading guest state. */
+ if (sz32 || fp_mode64)
+ d->nFxState = 2;
+ else
+ d->nFxState = 3;
- assign(tmpLs8, mkNarrowTo8(ty, mkexpr(tmp)));
- assign(tmpRs8, mkNarrowTo8(ty, mkexpr(tmp64)));
+ vex_bzero(&d->fxState, sizeof(d->fxState));
- assign(tmpR, binop(Iop_Shr64, mkexpr(tmpRt), mkexpr(tmpRs8)));
- assign(tmpL, binop(Iop_Shl64, mkexpr(tmpRt), mkexpr(tmpLs8)));
- assign(tmpRd, binop(Iop_Shl64, mkexpr(tmpL), mkU8(1)));
- assign(tmpOr, binop(Iop_Or64, mkexpr(tmpRd), mkexpr(tmpR)));
+ d->fxState[0].fx = Ifx_Read; /* read */
- putIReg(regRd, mkexpr(tmpOr));
- } else
- return False;
- break;
+ if (mode64)
+ d->fxState[0].offset = offsetof(VexGuestMIPS64State, guest_FCSR);
+ else
+ d->fxState[0].offset = offsetof(VexGuestMIPS32State, guest_FCSR);
- case 0x38: /* Doubleword Shift Left Logical - DSLL; MIPS64 */
- DIP("dsll r%u, r%u, %lld", regRd, regRt, sImmsa);
- vassert(mode64);
- assign(tmpRd, binop(Iop_Shl64, mkexpr(tmpRt), mkU8(uImmsa)));
- putIReg(regRd, mkexpr(tmpRd));
- break;
+ d->fxState[0].size = sizeof(UInt);
+ d->fxState[1].fx = Ifx_Read; /* read */
+ d->fxState[1].offset = floatGuestRegOffset(fs);
+ d->fxState[1].size = sizeof(ULong);
- case 0x3C: /* Doubleword Shift Left Logical Plus 32 - DSLL32; MIPS64 */
- DIP("dsll32 r%u, r%u, %lld", regRd, regRt, sImmsa);
- assign(tmpRd, binop(Iop_Shl64, mkexpr(tmpRt), mkU8(uImmsa + 32)));
- putIReg(regRd, mkexpr(tmpRd));
- break;
+ if (!(sz32 || fp_mode64)) {
+ d->fxState[2].fx = Ifx_Read; /* read */
+ d->fxState[2].offset = floatGuestRegOffset(fs + 1);
+ d->fxState[2].size = sizeof(ULong);
+ }
+ } else if (opN == 2) { /* Binary operation. */
+ /* Declare we're reading guest state. */
+ if (sz32 || fp_mode64)
+ d->nFxState = 3;
+ else
+ d->nFxState = 5;
- case 0x14: { /* Doubleword Shift Left Logical Variable - DSLLV; MIPS64 */
- DIP("dsllv r%u, r%u, r%u", regRd, regRt, regRs);
- IRTemp tmpRs8 = newTemp(Ity_I8);
+ vex_bzero(&d->fxState, sizeof(d->fxState));
- assign(tmp, binop(Iop_And64, mkexpr(tmpRs), mkSzImm(ty, 63)));
- assign(tmpRs8, mkNarrowTo8(ty, mkexpr(tmp)));
- assign(tmpRd, binop(Iop_Shl64, mkexpr(tmpRt), mkexpr(tmpRs8)));
- putIReg(regRd, mkexpr(tmpRd));
- break;
+ d->fxState[0].fx = Ifx_Read; /* read */
+
+ if (mode64)
+ d->fxState[0].offset = offsetof(VexGuestMIPS64State, guest_FCSR);
+ else
+ d->fxState[0].offset = offsetof(VexGuestMIPS32State, guest_FCSR);
+
+ d->fxState[0].size = sizeof(UInt);
+ d->fxState[1].fx = Ifx_Read; /* read */
+ d->fxState[1].offset = floatGuestRegOffset(fs);
+ d->fxState[1].size = sizeof(ULong);
+ d->fxState[2].fx = Ifx_Read; /* read */
+ d->fxState[2].offset = floatGuestRegOffset(ft);
+ d->fxState[2].size = sizeof(ULong);
+
+ if (!(sz32 || fp_mode64)) {
+ d->fxState[3].fx = Ifx_Read; /* read */
+ d->fxState[3].offset = floatGuestRegOffset(fs + 1);
+ d->fxState[3].size = sizeof(ULong);
+ d->fxState[4].fx = Ifx_Read; /* read */
+ d->fxState[4].offset = floatGuestRegOffset(ft + 1);
+ d->fxState[4].size = sizeof(ULong);
}
+ }
- case 0x3B: /* Doubleword Shift Right Arithmetic - DSRA; MIPS64 */
- DIP("dsra r%u, r%u, %lld", regRd, regRt, sImmsa);
- assign(tmpRd, binop(Iop_Sar64, mkexpr(tmpRt), mkU8(uImmsa)));
- putIReg(regRd, mkexpr(tmpRd));
- break;
+ stmt(IRStmt_Dirty(d));
- case 0x3F: /* Doubleword Shift Right Arithmetic Plus 32 - DSRA32;
- MIPS64 */
- DIP("dsra32 r%u, r%u, %lld", regRd, regRt, sImmsa);
- assign(tmpRd, binop(Iop_Sar64, mkexpr(tmpRt), mkU8(uImmsa + 32)));
- putIReg(regRd, mkexpr(tmpRd));
- break;
+ putFCSR(mkexpr(fcsr));
+}
- case 0x17: { /* Doubleword Shift Right Arithmetic Variable - DSRAV;
- MIPS64 */
- DIP("dsrav r%u, r%u, r%u", regRd, regRt, regRs);
- IRTemp tmpRs8 = newTemp(Ity_I8);
- assign(tmp, binop(Iop_And64, mkexpr(tmpRs), mkSzImm(ty, 63)));
- assign(tmpRs8, mkNarrowTo8(ty, mkexpr(tmp)));
- assign(tmpRd, binop(Iop_Sar64, mkexpr(tmpRt), mkexpr(tmpRs8)));
- putIReg(regRd, mkexpr(tmpRd));
- break;
+/* ws, wt - source MSA register numbers.
+ inst - MSA fp instruction that needs to be executed.
+ opN - number of operads:
+ 1 - unary operation.
+ 2 - binary operation. */
+static void calculateMSACSR(UInt ws, UInt wt, UInt inst, UInt opN)
+{
+ IRDirty *d;
+ IRTemp msacsr = newTemp(Ity_I32);
+ /* IRExpr_BBPTR() => Need to pass pointer to guest state to helper. */
+ d = unsafeIRDirty_1_N(msacsr, 0,
+ "mips_dirtyhelper_calculate_MSACSR",
+ &mips_dirtyhelper_calculate_MSACSR,
+ mkIRExprVec_4(IRExpr_GSPTR(),
+ mkU32(ws),
+ mkU32(wt),
+ mkU32(inst)));
- }
+ if (opN == 1) { /* Unary operation. */
+ /* Declare we're reading guest state. */
+ d->nFxState = 2;
+ vex_bzero(&d->fxState, sizeof(d->fxState));
+ d->fxState[0].fx = Ifx_Read; /* read */
- default:
- return False;
+ if (mode64)
+ d->fxState[0].offset = offsetof(VexGuestMIPS64State, guest_MSACSR);
+ else
+ d->fxState[0].offset = offsetof(VexGuestMIPS32State, guest_MSACSR);
+
+ d->fxState[0].size = sizeof(UInt);
+ d->fxState[1].fx = Ifx_Read; /* read */
+ d->fxState[1].offset = msaGuestRegOffset(ws);
+ d->fxState[1].size = sizeof(ULong);
+ } else if (opN == 2) { /* Binary operation. */
+ /* Declare we're reading guest state. */
+ d->nFxState = 3;
+ vex_bzero(&d->fxState, sizeof(d->fxState));
+ d->fxState[0].fx = Ifx_Read; /* read */
+
+ if (mode64)
+ d->fxState[0].offset = offsetof(VexGuestMIPS64State, guest_MSACSR);
+ else
+ d->fxState[0].offset = offsetof(VexGuestMIPS32State, guest_MSACSR);
+ d->fxState[0].size = sizeof(UInt);
+ d->fxState[1].fx = Ifx_Read; /* read */
+ d->fxState[1].offset = msaGuestRegOffset(ws);
+ d->fxState[1].size = sizeof(ULong);
+ d->fxState[2].fx = Ifx_Read; /* read */
+ d->fxState[2].offset = msaGuestRegOffset(wt);
+ d->fxState[2].size = sizeof(ULong);
}
- return True;
+
+ stmt(IRStmt_Dirty(d));
+ putMSACSR(mkexpr(msacsr));
}
-static IROp mkSzOp ( IRType ty, IROp op8 )
+static IRExpr *getULR(void)
{
- Int adj;
- vassert(ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32 || ty == Ity_I64);
- vassert(op8 == Iop_Add8 || op8 == Iop_Sub8 || op8 == Iop_Mul8
- || op8 == Iop_Or8 || op8 == Iop_And8 || op8 == Iop_Xor8
- || op8 == Iop_Shl8 || op8 == Iop_Shr8 || op8 == Iop_Sar8
- || op8 == Iop_CmpEQ8 || op8 == Iop_CmpNE8 || op8 == Iop_Not8);
- adj = ty == Ity_I8 ? 0 : (ty == Ity_I16 ? 1 : (ty == Ity_I32 ? 2 : 3));
- return adj + op8;
+ if (mode64)
+ return IRExpr_Get(offsetof(VexGuestMIPS64State, guest_ULR), Ity_I64);
+ else
+ return IRExpr_Get(offsetof(VexGuestMIPS32State, guest_ULR), Ity_I32);
}
-/*********************************************************/
-/*--- Floating Point Compare ---*/
-/*********************************************************/
-/* Function that returns a string that represent mips cond
- mnemonic for the input code. */
-static const HChar* showCondCode(UInt code) {
- const HChar* ret;
- switch (code) {
- case 0: ret = "f"; break;
- case 1: ret = "un"; break;
- case 2: ret = "eq"; break;
- case 3: ret = "ueq"; break;
- case 4: ret = "olt"; break;
- case 5: ret = "ult"; break;
- case 6: ret = "ole"; break;
- case 7: ret = "ule"; break;
- case 8: ret = "sf"; break;
- case 9: ret = "ngle"; break;
- case 10: ret = "seq"; break;
- case 11: ret = "ngl"; break;
- case 12: ret = "lt"; break;
- case 13: ret = "nge"; break;
- case 14: ret = "le"; break;
- case 15: ret = "ngt"; break;
- default: vpanic("showCondCode"); break;
- }
- return ret;
+void putIReg(UInt archreg, IRExpr * e)
+{
+ IRType ty = mode64 ? Ity_I64 : Ity_I32;
+ vassert(archreg < 32);
+ vassert(typeOfIRExpr(irsb->tyenv, e) == ty);
+
+ if (archreg != 0)
+ stmt(IRStmt_Put(integerGuestRegOffset(archreg), e));
}
-static Bool dis_instr_CCondFmt ( UInt cins )
+static void putWReg(UInt wregNo, IRExpr * e)
{
- IRTemp t0, t1, t2, t3, tmp5, tmp6;
- IRTemp ccIR = newTemp(Ity_I32);
- IRTemp ccMIPS = newTemp(Ity_I32);
+ vassert(wregNo <= 31);
+ vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_V128);
+ stmt(IRStmt_Put(msaGuestRegOffset(wregNo), e));
+ stmt(IRStmt_Put(floatGuestRegOffset(wregNo),
+ unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, e))));
+}
+
+IRExpr *mkNarrowTo32(IRType ty, IRExpr * src)
+{
+ vassert(ty == Ity_I32 || ty == Ity_I64);
+ return ty == Ity_I64 ? unop(Iop_64to32, src) : src;
+}
+
+void putLO(IRExpr * e)
+{
+ if (mode64) {
+ stmt(IRStmt_Put(offsetof(VexGuestMIPS64State, guest_LO), e));
+ } else {
+ stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_LO), e));
+ /* Add value to lower 32 bits of ac0 to maintain compatibility between
+ regular MIPS32 instruction set and MIPS DSP ASE. Keep higher 32bits
+ unchanged. */
+ IRTemp t_lo = newTemp(Ity_I32);
+ IRTemp t_hi = newTemp(Ity_I32);
+ assign(t_lo, e);
+ assign(t_hi, unop(Iop_64HIto32, getAcc(0)));
+ stmt(IRStmt_Put(accumulatorGuestRegOffset(0),
+ binop(Iop_32HLto64, mkexpr(t_hi), mkexpr(t_lo))));
+ }
+}
+
+void putHI(IRExpr * e)
+{
+ if (mode64) {
+ stmt(IRStmt_Put(offsetof(VexGuestMIPS64State, guest_HI), e));
+ } else {
+ stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_HI), e));
+ /* Add value to higher 32 bits of ac0 to maintain compatibility between
+ regular MIPS32 instruction set and MIPS DSP ASE. Keep lower 32bits
+ unchanged. */
+ IRTemp t_lo = newTemp(Ity_I32);
+ IRTemp t_hi = newTemp(Ity_I32);
+ assign(t_hi, e);
+ assign(t_lo, unop(Iop_64to32, getAcc(0)));
+ stmt(IRStmt_Put(accumulatorGuestRegOffset(0),
+ binop(Iop_32HLto64, mkexpr(t_hi), mkexpr(t_lo))));
+ }
+}
+
+static IRExpr *mkNarrowTo8 ( IRType ty, IRExpr * src )
+{
+ vassert(ty == Ity_I32 || ty == Ity_I64);
+ return ty == Ity_I64 ? unop(Iop_64to8, src) : unop(Iop_32to8, src);
+}
+
+static IRExpr *mkNarrowTo16 ( IRType ty, IRExpr * src )
+{
+ vassert(ty == Ity_I32 || ty == Ity_I64);
+ return ty == Ity_I64 ? unop(Iop_64to16, src) : unop(Iop_32to16, src);
+}
+
+static void putPC(IRExpr * e)
+{
+ stmt(IRStmt_Put(OFFB_PC, e));
+}
+
+static IRExpr *mkWidenFrom32(IRType ty, IRExpr * src, Bool sined)
+{
+ vassert(ty == Ity_I32 || ty == Ity_I64);
+
+ if (ty == Ity_I32)
+ return src;
+
+ return (sined) ? unop(Iop_32Sto64, src) : unop(Iop_32Uto64, src);
+}
+
+/* Narrow 8/16/32 bit int expr to 8/16/32. Clearly only some
+ of these combinations make sense. */
+static IRExpr *narrowTo(IRType dst_ty, IRExpr * e)
+{
+ IRType src_ty = typeOfIRExpr(irsb->tyenv, e);
+
+ if (src_ty == dst_ty)
+ return e;
+
+ if (src_ty == Ity_I32 && dst_ty == Ity_I16)
+ return unop(Iop_32to16, e);
+
+ if (src_ty == Ity_I32 && dst_ty == Ity_I8)
+ return unop(Iop_32to8, e);
+
+ if (src_ty == Ity_I64 && dst_ty == Ity_I8) {
+ vassert(mode64);
+ return unop(Iop_64to8, e);
+ }
+
+ if (src_ty == Ity_I64 && dst_ty == Ity_I16) {
+ vassert(mode64);
+ return unop(Iop_64to16, e);
+ }
+
+ vpanic("narrowTo(mips)");
+ return 0;
+}
+
+static IRExpr *getLoFromF64(IRType ty, IRExpr * src)
+{
+ vassert(ty == Ity_F32 || ty == Ity_F64);
+
+ if (ty == Ity_F64) {
+ IRTemp t0, t1;
+ t0 = newTemp(Ity_I64);
+ t1 = newTemp(Ity_I32);
+ assign(t0, unop(Iop_ReinterpF64asI64, src));
+ assign(t1, unop(Iop_64to32, mkexpr(t0)));
+ return unop(Iop_ReinterpI32asF32, mkexpr(t1));
+ } else
+ return src;
+}
+
+static inline IRExpr *getHiFromF64(IRExpr * src)
+{
+ vassert(typeOfIRExpr(irsb->tyenv, src) == Ity_F64);
+ return unop(Iop_ReinterpI32asF32, unop(Iop_64HIto32,
+ unop(Iop_ReinterpF64asI64, src)));
+}
+
+static IRExpr *mkWidenFromF32(IRType ty, IRExpr * src)
+{
+ vassert(ty == Ity_F32 || ty == Ity_F64);
+
+ if (ty == Ity_F64) {
+ IRTemp t0 = newTemp(Ity_I32);
+ IRTemp t1 = newTemp(Ity_I64);
+ assign(t0, unop(Iop_ReinterpF32asI32, src));
+ assign(t1, binop(Iop_32HLto64, mkU32(0x0), mkexpr(t0)));
+ return unop(Iop_ReinterpI64asF64, mkexpr(t1));
+ } else
+ return src;
+}
+
+/* Convenience function to move to next instruction on condition. */
+static void mips_next_insn_if(IRExpr *condition)
+{
+ vassert(typeOfIRExpr(irsb->tyenv, condition) == Ity_I1);
+
+ stmt(IRStmt_Exit(condition, Ijk_Boring,
+ mode64 ? IRConst_U64(guest_PC_curr_instr + 4) :
+ IRConst_U32(guest_PC_curr_instr + 4),
+ OFFB_PC));
+}
+
+static IRExpr *dis_branch_likely(IRExpr * guard, UInt imm)
+{
+ ULong branch_offset;
+ IRTemp t0;
+
+ /* PC = PC + (SignExtend(signed_immed_24) << 2)
+ An 18-bit signed offset (the 16-bit offset field shifted left 2 bits)
+ is added to the address of the instruction following
+ the branch (not the branch itself), in the branch delay slot, to form
+ a PC-relative effective target address. */
+ if (mode64)
+ branch_offset = extend_s_18to64(imm << 2);
+ else
+ branch_offset = extend_s_18to32(imm << 2);
+
+ t0 = newTemp(Ity_I1);
+ assign(t0, guard);
+
+ if (mode64)
+ stmt(IRStmt_Exit(mkexpr(t0), Ijk_Boring,
+ IRConst_U64(guest_PC_curr_instr + 8), OFFB_PC));
+ else
+ stmt(IRStmt_Exit(mkexpr(t0), Ijk_Boring,
+ IRConst_U32(guest_PC_curr_instr + 8), OFFB_PC));
+
+ irsb->jumpkind = Ijk_Boring;
+
+ if (mode64)
+ return mkU64(guest_PC_curr_instr + 4 + branch_offset);
+ else
+ return mkU32(guest_PC_curr_instr + 4 + branch_offset);
+}
+
+static void dis_branch(Bool link, IRExpr * guard, UInt imm, IRStmt ** set)
+{
+ ULong branch_offset;
+ IRTemp t0;
+
+ if (link) { /* LR (GPR31) = addr of the 2nd instr after branch instr */
+ if (mode64)
+ putIReg(31, mkU64(guest_PC_curr_instr + 8));
+ else
+ putIReg(31, mkU32(guest_PC_curr_instr + 8));
+ }
+
+ /* PC = PC + (SignExtend(signed_immed_24) << 2)
+ An 18-bit signed offset (the 16-bit offset field shifted left 2 bits)
+ is added to the address of the instruction following
+ the branch (not the branch itself), in the branch delay slot, to form
+ a PC-relative effective target address. */
+
+ if (mode64)
+ branch_offset = extend_s_18to64(imm << 2);
+ else
+ branch_offset = extend_s_18to32(imm << 2);
+
+ t0 = newTemp(Ity_I1);
+ assign(t0, guard);
+
+ if (mode64)
+ *set = IRStmt_Exit(mkexpr(t0), link ? Ijk_Call : Ijk_Boring,
+ IRConst_U64(guest_PC_curr_instr + 4 + branch_offset),
+ OFFB_PC);
+ else
+ *set = IRStmt_Exit(mkexpr(t0), link ? Ijk_Call : Ijk_Boring,
+ IRConst_U32(guest_PC_curr_instr + 4 +
+ (UInt) branch_offset), OFFB_PC);
+}
+
+static void dis_branch_compact(Bool link, IRExpr * guard, UInt imm,
+ DisResult *dres)
+{
+ ULong branch_offset;
+ IRTemp t0;
+
+ if (link) { /* LR (GPR31) = addr of the instr after branch instr */
+ if (mode64)
+ putIReg(31, mkU64(guest_PC_curr_instr + 4));
+ else
+ putIReg(31, mkU32(guest_PC_curr_instr + 4));
+
+ dres->jk_StopHere = Ijk_Call;
+ } else {
+ dres->jk_StopHere = Ijk_Boring;
+ }
+
+ dres->whatNext = Dis_StopHere;
+
+ /* PC = PC + (SignExtend(signed_immed_24) << 2)
+ An 18-bit signed offset (the 16-bit offset field shifted left 2 bits)
+ is added to the address of the instruction following
+ the branch (not the branch itself), in the branch delay slot, to form
+ a PC-relative effective target address. */
+
+ if (mode64)
+ branch_offset = extend_s_18to64(imm << 2);
+ else
+ branch_offset = extend_s_18to32(imm << 2);
+
+ t0 = newTemp(Ity_I1);
+ assign(t0, guard);
+
+ if (mode64) {
+ stmt(IRStmt_Exit(mkexpr(t0), link ? Ijk_Call : Ijk_Boring,
+ IRConst_U64(guest_PC_curr_instr + 4 + branch_offset),
+ OFFB_PC));
+ putPC(mkU64(guest_PC_curr_instr + 4));
+ } else {
+ stmt(IRStmt_Exit(mkexpr(t0), link ? Ijk_Call : Ijk_Boring,
+ IRConst_U32(guest_PC_curr_instr + 4 +
+ (UInt) branch_offset), OFFB_PC));
+ putPC(mkU32(guest_PC_curr_instr + 4));
+ }
+}
+
+static IRExpr *getFReg(UInt fregNo)
+{
+ vassert(fregNo < 32);
+ IRType ty = fp_mode64 ? Ity_F64 : Ity_F32;
+ return IRExpr_Get(floatGuestRegOffset(fregNo), ty);
+}
+
+static IRExpr *getDReg(UInt dregNo)
+{
+ vassert(dregNo < 32);
+
+ if (fp_mode64) {
+ return IRExpr_Get(floatGuestRegOffset(dregNo), Ity_F64);
+ } else {
+ /* Read a floating point register pair and combine their contents into a
+ 64-bit value */
+ IRTemp t0 = newTemp(Ity_F32);
+ IRTemp t1 = newTemp(Ity_F32);
+ IRTemp t2 = newTemp(Ity_F64);
+ IRTemp t3 = newTemp(Ity_I32);
+ IRTemp t4 = newTemp(Ity_I32);
+ IRTemp t5 = newTemp(Ity_I64);
+
+ assign(t0, getFReg(dregNo & (~1)));
+ assign(t1, getFReg(dregNo | 1));
+
+ assign(t3, unop(Iop_ReinterpF32asI32, mkexpr(t0)));
+ assign(t4, unop(Iop_ReinterpF32asI32, mkexpr(t1)));
+ assign(t5, binop(Iop_32HLto64, mkexpr(t4), mkexpr(t3)));
+ assign(t2, unop(Iop_ReinterpI64asF64, mkexpr(t5)));
+
+ return mkexpr(t2);
+ }
+}
+
+static void putFReg(UInt dregNo, IRExpr * e)
+{
+ vassert(dregNo < 32);
+ IRType ty = fp_mode64 ? Ity_F64 : Ity_F32;
+ vassert(typeOfIRExpr(irsb->tyenv, e) == ty);
+
+ if (fp_mode64_fre) {
+ IRTemp t0 = newTemp(Ity_F32);
+ assign(t0, getLoFromF64(ty, e));
+#if defined (_MIPSEL)
+ stmt(IRStmt_Put(floatGuestRegOffset(dregNo), mkexpr(t0)));
+
+ if (dregNo & 1)
+ stmt(IRStmt_Put(floatGuestRegOffset(dregNo) - 4, mkexpr(t0)));
+
+#else
+ stmt(IRStmt_Put(floatGuestRegOffset(dregNo) + 4, mkexpr(t0)));
+
+ if (dregNo & 1)
+ stmt(IRStmt_Put(floatGuestRegOffset(dregNo & (~1)), mkexpr(t0)));
+
+#endif
+ } else {
+ stmt(IRStmt_Put(floatGuestRegOffset(dregNo), e));
+ }
+
+ if (has_msa && fp_mode64) {
+ stmt(IRStmt_Put(msaGuestRegOffset(dregNo),
+ binop(Iop_64HLtoV128,
+ unop(Iop_ReinterpF64asI64, e),
+ unop(Iop_ReinterpF64asI64, e))));
+ }
+}
+
+static void putDReg(UInt dregNo, IRExpr * e)
+{
+ if (fp_mode64) {
+ vassert(dregNo < 32);
+ IRType ty = Ity_F64;
+ vassert(typeOfIRExpr(irsb->tyenv, e) == ty);
+ stmt(IRStmt_Put(floatGuestRegOffset(dregNo), e));
+
+ if (fp_mode64_fre) {
+ IRTemp t0 = newTemp(Ity_F32);
+
+ if (dregNo & 1) {
+ assign(t0, getLoFromF64(ty, e));
+#if defined (_MIPSEL)
+ stmt(IRStmt_Put(floatGuestRegOffset(dregNo) - 4, mkexpr(t0)));
+#else
+ stmt(IRStmt_Put(floatGuestRegOffset(dregNo & (~1)), mkexpr(t0)));
+#endif
+ } else {
+ assign(t0, getHiFromF64(e));
+#if defined (_MIPSEL)
+ stmt(IRStmt_Put(floatGuestRegOffset(dregNo | 1), mkexpr(t0)));
+#else
+ stmt(IRStmt_Put(floatGuestRegOffset(dregNo | 1) + 4, mkexpr(t0)));
+#endif
+ }
+ }
+
+ if (has_msa)
+ stmt(IRStmt_Put(msaGuestRegOffset(dregNo),
+ binop(Iop_64HLtoV128,
+ unop(Iop_ReinterpF64asI64, e),
+ unop(Iop_ReinterpF64asI64, e))));
+ } else {
+ vassert(dregNo < 32);
+ vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_F64);
+ IRTemp t1 = newTemp(Ity_F64);
+ IRTemp t4 = newTemp(Ity_I32);
+ IRTemp t5 = newTemp(Ity_I32);
+ IRTemp t6 = newTemp(Ity_I64);
+ assign(t1, e);
+ assign(t6, unop(Iop_ReinterpF64asI64, mkexpr(t1)));
+ assign(t4, unop(Iop_64HIto32, mkexpr(t6))); /* hi */
+ assign(t5, unop(Iop_64to32, mkexpr(t6))); /* lo */
+ putFReg(dregNo & (~1), unop(Iop_ReinterpI32asF32, mkexpr(t5)));
+ putFReg(dregNo | 1, unop(Iop_ReinterpI32asF32, mkexpr(t4)));
+ }
+}
+
+static void setFPUCondCode(IRExpr * e, UInt cc)
+{
+ if (cc == 0) {
+ putFCSR(binop(Iop_And32, getFCSR(), mkU32(0xFF7FFFFF)));
+ putFCSR(binop(Iop_Or32, getFCSR(), binop(Iop_Shl32, e, mkU8(23))));
+ } else {
+ putFCSR(binop(Iop_And32, getFCSR(), unop(Iop_Not32,
+ binop(Iop_Shl32, mkU32(0x01000000), mkU8(cc)))));
+ putFCSR(binop(Iop_Or32, getFCSR(), binop(Iop_Shl32, e, mkU8(24 + cc))));
+ }
+}
+
+static IRExpr* get_IR_roundingmode ( void )
+{
+ /*
+ rounding mode | MIPS | IR
+ ------------------------
+ to nearest | 00 | 00
+ to zero | 01 | 11
+ to +infinity | 10 | 10
+ to -infinity | 11 | 01
+ */
+ IRTemp rm_MIPS = newTemp(Ity_I32);
+ /* Last two bits in FCSR are rounding mode. */
+
+ if (mode64)
+ assign(rm_MIPS, binop(Iop_And32, IRExpr_Get(offsetof(VexGuestMIPS64State,
+ guest_FCSR), Ity_I32), mkU32(3)));
+ else
+ assign(rm_MIPS, binop(Iop_And32, IRExpr_Get(offsetof(VexGuestMIPS32State,
+ guest_FCSR), Ity_I32), mkU32(3)));
+
+ /* rm_IR = XOR( rm_MIPS32, (rm_MIPS32 << 1) & 2) */
+
+ return binop(Iop_Xor32, mkexpr(rm_MIPS), binop(Iop_And32,
+ binop(Iop_Shl32, mkexpr(rm_MIPS), mkU8(1)), mkU32(2)));
+}
+
+static IRExpr* get_IR_roundingmode_MSA ( void )
+{
+ /*
+ rounding mode | MIPS | IR
+ ------------------------
+ to nearest | 00 | 00
+ to zero | 01 | 11
+ to +infinity | 10 | 10
+ to -infinity | 11 | 01
+ */
+ IRTemp rm_MIPS = newTemp(Ity_I32);
+ /* Last two bits in MSACSR are rounding mode. */
+
+ if (mode64)
+ assign(rm_MIPS, binop(Iop_And32, IRExpr_Get(offsetof(VexGuestMIPS64State,
+ guest_MSACSR), Ity_I32), mkU32(3)));
+ else
+ assign(rm_MIPS, binop(Iop_And32, IRExpr_Get(offsetof(VexGuestMIPS32State,
+ guest_MSACSR), Ity_I32), mkU32(3)));
+
+ /* rm_IR = XOR( rm_MIPS32, (rm_MIPS32 << 1) & 2) */
+ return binop(Iop_Xor32, mkexpr(rm_MIPS), binop(Iop_And32,
+ binop(Iop_Shl32, mkexpr(rm_MIPS), mkU8(1)), mkU32(2)));
+}
+
+/* sz, ULong -> IRExpr */
+static IRExpr *mkSzImm ( IRType ty, ULong imm64 )
+{
+ vassert(ty == Ity_I32 || ty == Ity_I64);
+ return ty == Ity_I64 ? mkU64(imm64) : mkU32((UInt) imm64);
+}
+
+static IRConst *mkSzConst ( IRType ty, ULong imm64 )
+{
+ vassert(ty == Ity_I32 || ty == Ity_I64);
+ return (ty == Ity_I64 ? IRConst_U64(imm64) : IRConst_U32((UInt) imm64));
+}
+
+/* Make sure we get valid 32 and 64bit addresses */
+static Addr64 mkSzAddr ( IRType ty, Addr64 addr )
+{
+ vassert(ty == Ity_I32 || ty == Ity_I64);
+ return (ty == Ity_I64 ? (Addr64) addr :
+ (Addr64) extend_s_32to64(toUInt(addr)));
+}
+
+/* Shift and Rotate instructions for MIPS64 */
+static Bool dis_instr_shrt ( UInt theInstr )
+{
+ UInt opc2 = get_function(theInstr);
+ UChar regRs = get_rs(theInstr);
+ UChar regRt = get_rt(theInstr);
+ UChar regRd = get_rd(theInstr);
+ UChar uImmsa = get_sa(theInstr);
+ Long sImmsa = extend_s_16to64(uImmsa);
+ IRType ty = mode64 ? Ity_I64 : Ity_I32;
+ IRTemp tmp = newTemp(ty);
+ IRTemp tmpOr = newTemp(ty);
+ IRTemp tmpRt = newTemp(ty);
+ IRTemp tmpRs = newTemp(ty);
+ IRTemp tmpRd = newTemp(ty);
+
+ assign(tmpRs, getIReg(regRs));
+ assign(tmpRt, getIReg(regRt));
+
+ switch (opc2) {
+ case 0x3A:
+ if ((regRs & 0x01) == 0) {
+ /* Doubleword Shift Right Logical - DSRL; MIPS64 */
+ DIP("dsrl r%u, r%u, %lld", regRd, regRt, sImmsa);
+ assign(tmpRd, binop(Iop_Shr64, mkexpr(tmpRt), mkU8(uImmsa)));
+ putIReg(regRd, mkexpr(tmpRd));
+ } else if ((regRs & 0x01) == 1) {
+ /* Doubleword Rotate Right - DROTR; MIPS64r2 */
+ vassert(mode64);
+ DIP("drotr r%u, r%u, %lld", regRd, regRt, sImmsa);
+ IRTemp tmpL = newTemp(ty);
+ IRTemp tmpR = newTemp(ty);
+ assign(tmpR, binop(Iop_Shr64, mkexpr(tmpRt), mkU8(uImmsa)));
+ assign(tmp, binop(Iop_Shl64, mkexpr(tmpRt), mkU8(63 - uImmsa)));
+ assign(tmpL, binop(Iop_Shl64, mkexpr(tmp), mkU8(1)));
+ assign(tmpRd, binop(Iop_Or64, mkexpr(tmpL), mkexpr(tmpR)));
+ putIReg(regRd, mkexpr(tmpRd));
+ } else
+ return False;
+
+ break;
+
+ case 0x3E:
+ if ((regRs & 0x01) == 0) {
+ /* Doubleword Shift Right Logical Plus 32 - DSRL32; MIPS64 */
+ DIP("dsrl32 r%u, r%u, %lld", regRd, regRt, sImmsa + 32);
+ assign(tmpRd, binop(Iop_Shr64, mkexpr(tmpRt), mkU8(uImmsa + 32)));
+ putIReg(regRd, mkexpr(tmpRd));
+ } else if ((regRs & 0x01) == 1) {
+ /* Doubleword Rotate Right Plus 32 - DROTR32; MIPS64r2 */
+ DIP("drotr32 r%u, r%u, %lld", regRd, regRt, sImmsa);
+ vassert(mode64);
+ IRTemp tmpL = newTemp(ty);
+ IRTemp tmpR = newTemp(ty);
+ /* (tmpRt >> sa) | (tmpRt << (64 - sa)) */
+ assign(tmpR, binop(Iop_Shr64, mkexpr(tmpRt), mkU8(uImmsa + 32)));
+ assign(tmp, binop(Iop_Shl64, mkexpr(tmpRt),
+ mkU8(63 - (uImmsa + 32))));
+ assign(tmpL, binop(Iop_Shl64, mkexpr(tmp), mkU8(1)));
+ assign(tmpRd, binop(Iop_Or64, mkexpr(tmpL), mkexpr(tmpR)));
+ putIReg(regRd, mkexpr(tmpRd));
+ } else
+ return False;
+
+ break;
+
+ case 0x16:
+ if ((uImmsa & 0x01) == 0) {
+ /* Doubleword Shift Right Logical Variable - DSRLV; MIPS64 */
+ DIP("dsrlv r%u, r%u, r%u", regRd, regRt, regRs);
+ IRTemp tmpRs8 = newTemp(Ity_I8);
+ /* s = tmpRs[5..0] */
+ assign(tmp, binop(Iop_And64, mkexpr(tmpRs), mkU64(63)));
+ assign(tmpRs8, mkNarrowTo8(ty, mkexpr(tmp)));
+ assign(tmpRd, binop(Iop_Shr64, mkexpr(tmpRt), mkexpr(tmpRs8)));
+ putIReg(regRd, mkexpr(tmpRd));
+ } else if ((uImmsa & 0x01) == 1) {
+ /* Doubleword Rotate Right Variable - DROTRV; MIPS64r2 */
+ DIP("drotrv r%u, r%u, r%u", regRd, regRt, regRs);
+ IRTemp tmpL = newTemp(ty);
+ IRTemp tmpR = newTemp(ty);
+ IRTemp tmpRs8 = newTemp(Ity_I8);
+ IRTemp tmpLs8 = newTemp(Ity_I8);
+ IRTemp tmp64 = newTemp(ty);
+ /* s = tmpRs[5...0]
+ m = 64 - s
+ (tmpRt << s) | (tmpRt >> m) */
+
+ assign(tmp64, binop(Iop_And64, mkexpr(tmpRs), mkSzImm(ty, 63)));
+ assign(tmp, binop(Iop_Sub64, mkU64(63), mkexpr(tmp64)));
+
+ assign(tmpLs8, mkNarrowTo8(ty, mkexpr(tmp)));
+ assign(tmpRs8, mkNarrowTo8(ty, mkexpr(tmp64)));
+
+ assign(tmpR, binop(Iop_Shr64, mkexpr(tmpRt), mkexpr(tmpRs8)));
+ assign(tmpL, binop(Iop_Shl64, mkexpr(tmpRt), mkexpr(tmpLs8)));
+ assign(tmpRd, binop(Iop_Shl64, mkexpr(tmpL), mkU8(1)));
+ assign(tmpOr, binop(Iop_Or64, mkexpr(tmpRd), mkexpr(tmpR)));
+
+ putIReg(regRd, mkexpr(tmpOr));
+ } else
+ return False;
+
+ break;
+
+ case 0x38: /* Doubleword Shift Left Logical - DSLL; MIPS64 */
+ DIP("dsll r%u, r%u, %lld", regRd, regRt, sImmsa);
+ vassert(mode64);
+ assign(tmpRd, binop(Iop_Shl64, mkexpr(tmpRt), mkU8(uImmsa)));
+ putIReg(regRd, mkexpr(tmpRd));
+ break;
+
+ case 0x3C: /* Doubleword Shift Left Logical Plus 32 - DSLL32; MIPS64 */
+ DIP("dsll32 r%u, r%u, %lld", regRd, regRt, sImmsa);
+ assign(tmpRd, binop(Iop_Shl64, mkexpr(tmpRt), mkU8(uImmsa + 32)));
+ putIReg(regRd, mkexpr(tmpRd));
+ break;
+
+ case 0x14: { /* Doubleword Shift Left Logical Variable - DSLLV; MIPS64 */
+ DIP("dsllv r%u, r%u, r%u", regRd, regRt, regRs);
+ IRTemp tmpRs8 = newTemp(Ity_I8);
+
+ assign(tmp, binop(Iop_And64, mkexpr(tmpRs), mkSzImm(ty, 63)));
+ assign(tmpRs8, mkNarrowTo8(ty, mkexpr(tmp)));
+ assign(tmpRd, binop(Iop_Shl64, mkexpr(tmpRt), mkexpr(tmpRs8)));
+ putIReg(regRd, mkexpr(tmpRd));
+ break;
+ }
+
+ case 0x3B: /* Doubleword Shift Right Arithmetic - DSRA; MIPS64 */
+ DIP("dsra r%u, r%u, %lld", regRd, regRt, sImmsa);
+ assign(tmpRd, binop(Iop_Sar64, mkexpr(tmpRt), mkU8(uImmsa)));
+ putIReg(regRd, mkexpr(tmpRd));
+ break;
+
+ case 0x3F: /* Doubleword Shift Right Arithmetic Plus 32 - DSRA32;
+ MIPS64 */
+ DIP("dsra32 r%u, r%u, %lld", regRd, regRt, sImmsa);
+ assign(tmpRd, binop(Iop_Sar64, mkexpr(tmpRt), mkU8(uImmsa + 32)));
+ putIReg(regRd, mkexpr(tmpRd));
+ break;
+
+ case 0x17: {
+ /* Doubleword Shift Right Arithmetic Variable - DSRAV;
+ MIPS64 */
+ DIP("dsrav r%u, r%u, r%u", regRd, regRt, regRs);
+ IRTemp tmpRs8 = newTemp(Ity_I8);
+ assign(tmp, binop(Iop_And64, mkexpr(tmpRs), mkSzImm(ty, 63)));
+ assign(tmpRs8, mkNarrowTo8(ty, mkexpr(tmp)));
+ assign(tmpRd, binop(Iop_Sar64, mkexpr(tmpRt), mkexpr(tmpRs8)));
+ putIReg(regRd, mkexpr(tmpRd));
+ break;
+
+ }
+
+ default:
+ return False;
+
+ }
+
+ return True;
+}
+
+static IROp mkSzOp ( IRType ty, IROp op8 )
+{
+ Int adj;
+ vassert(ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32 || ty == Ity_I64);
+ vassert(op8 == Iop_Add8 || op8 == Iop_Sub8 || op8 == Iop_Mul8
+ || op8 == Iop_Or8 || op8 == Iop_And8 || op8 == Iop_Xor8
+ || op8 == Iop_Shl8 || op8 == Iop_Shr8 || op8 == Iop_Sar8
+ || op8 == Iop_CmpEQ8 || op8 == Iop_CmpNE8 || op8 == Iop_Not8);
+ adj = ty == Ity_I8 ? 0 : (ty == Ity_I16 ? 1 : (ty == Ity_I32 ? 2 : 3));
+ return adj + op8;
+}
+
+/*********************************************************/
+/*--- Floating Point Compare ---*/
+/*********************************************************/
+/* Function that returns a string that represent mips cond
+ mnemonic for the input code. */
+static const HChar* showCondCode(UInt code)
+{
+ const HChar* ret;
+
+ switch (code) {
+ case 0:
+ ret = "f";
+ break;
+
+ case 1:
+ ret = "un";
+ break;
+
+ case 2:
+ ret = "eq";
+ break;
+
+ case 3:
+ ret = "ueq";
+ break;
+
+ case 4:
+ ret = "olt";
+ break;
+
+ case 5:
+ ret = "ult";
+ break;
+
+ case 6:
+ ret = "ole";
+ break;
+
+ case 7:
+ ret = "ule";
+ break;
+
+ case 8:
+ ret = "sf";
+ break;
+
+ case 9:
+ ret = "ngle";
+ break;
+
+ case 10:
+ ret = "seq";
+ break;
+
+ case 11:
+ ret = "ngl";
+ break;
+
+ case 12:
+ ret = "lt";
+ break;
+
+ case 13:
+ ret = "nge";
+ break;
+
+ case 14:
+ ret = "le";
+ break;
+
+ case 15:
+ ret = "ngt";
+ break;
+
+ default:
+ vpanic("showCondCode");
+ break;
+ }
+
+ return ret;
+}
+
+static Bool dis_instr_CCondFmt ( UInt cins )
+{
+ IRTemp t0, t1, t2, t3, tmp5, tmp6;
+ IRTemp ccIR = newTemp(Ity_I32);
+ IRTemp ccMIPS = newTemp(Ity_I32);
UInt FC = get_FC(cins);
UInt fmt = get_fmt(cins);
UInt fs = get_fs(cins);
UInt ft = get_ft(cins);
UInt cond = get_cond(cins);
- if (FC == 0x3) { /* C.cond.fmt */
- UInt fpc_cc = get_fpc_cc(cins);
- switch (fmt) {
- case 0x10: { /* C.cond.S */
- DIP("c.%s.s %u, f%u, f%u", showCondCode(cond), fpc_cc, fs, ft);
- if (fp_mode64) {
- t0 = newTemp(Ity_I32);
- t1 = newTemp(Ity_I32);
- t2 = newTemp(Ity_I32);
- t3 = newTemp(Ity_I32);
+ if (FC == 0x3) { /* C.cond.fmt */
+ UInt fpc_cc = get_fpc_cc(cins);
+
+ switch (fmt) {
+ case 0x10: { /* C.cond.S */
+ DIP("c.%s.s %u, f%u, f%u", showCondCode(cond), fpc_cc, fs, ft);
+
+ if (fp_mode64) {
+ t0 = newTemp(Ity_I32);
+ t1 = newTemp(Ity_I32);
+ t2 = newTemp(Ity_I32);
+ t3 = newTemp(Ity_I32);
+
+ tmp5 = newTemp(Ity_F64);
+ tmp6 = newTemp(Ity_F64);
+
+ assign(tmp5, unop(Iop_F32toF64, getLoFromF64(Ity_F64,
+ getFReg(fs))));
+ assign(tmp6, unop(Iop_F32toF64, getLoFromF64(Ity_F64,
+ getFReg(ft))));
+
+ assign(ccIR, binop(Iop_CmpF64, mkexpr(tmp5), mkexpr(tmp6)));
+ putHI(mkWidenFrom32(mode64 ? Ity_I64 : Ity_I32,
+ mkexpr(ccIR), True));
+ /* Map compare result from IR to MIPS
+ FP cmp result | MIPS | IR
+ --------------------------
+ UN | 0x1 | 0x45
+ EQ | 0x2 | 0x40
+ GT | 0x4 | 0x00
+ LT | 0x8 | 0x01
+ */
+
+ /* ccMIPS = Shl(1, (~(ccIR>>5) & 2) | ((ccIR ^ (ccIR>>6)) & 1) */
+ assign(ccMIPS, binop(Iop_Shl32, mkU32(1), unop(Iop_32to8,
+ binop(Iop_Or32, binop(Iop_And32, unop(Iop_Not32,
+ binop(Iop_Shr32, mkexpr(ccIR), mkU8(5))), mkU32(2)),
+ binop(Iop_And32, binop(Iop_Xor32, mkexpr(ccIR),
+ binop(Iop_Shr32, mkexpr(ccIR), mkU8(6))),
+ mkU32(1))))));
+ putLO(mkWidenFrom32(mode64 ? Ity_I64 : Ity_I32,
+ mkexpr(ccMIPS), True));
+
+ /* UN */
+ assign(t0, binop(Iop_And32, mkexpr(ccMIPS), mkU32(0x1)));
+ /* EQ */
+ assign(t1, binop(Iop_And32, binop(Iop_Shr32, mkexpr(ccMIPS),
+ mkU8(0x1)), mkU32(0x1)));
+ /* NGT */
+ assign(t2, binop(Iop_And32, unop(Iop_Not32, binop(Iop_Shr32,
+ mkexpr(ccMIPS), mkU8(0x2))), mkU32(0x1)));
+ /* LT */
+ assign(t3, binop(Iop_And32, binop(Iop_Shr32, mkexpr(ccMIPS),
+ mkU8(0x3)), mkU32(0x1)));
+
+ switch (cond) {
+ case 0x0:
+ setFPUCondCode(mkU32(0), fpc_cc);
+ break;
+
+ case 0x1:
+ setFPUCondCode(mkexpr(t0), fpc_cc);
+ break;
+
+ case 0x2:
+ setFPUCondCode(mkexpr(t1), fpc_cc);
+ break;
+
+ case 0x3:
+ setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t1)),
+ fpc_cc);
+ break;
+
+ case 0x4:
+ setFPUCondCode(mkexpr(t3), fpc_cc);
+ break;
+
+ case 0x5:
+ setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t3)),
+ fpc_cc);
+ break;
+
+ case 0x6:
+ setFPUCondCode(binop(Iop_Or32, mkexpr(t3), mkexpr(t1)),
+ fpc_cc);
+ break;
+
+ case 0x7:
+ setFPUCondCode(mkexpr(t2), fpc_cc);
+ break;
+
+ case 0x8:
+ setFPUCondCode(mkU32(0), fpc_cc);
+ break;
+
+ case 0x9:
+ setFPUCondCode(mkexpr(t0), fpc_cc);
+ break;
+
+ case 0xA:
+ setFPUCondCode(mkexpr(t1), fpc_cc);
+ break;
+
+ case 0xB:
+ setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t1)),
+ fpc_cc);
+ break;
+
+ case 0xC:
+ setFPUCondCode(mkexpr(t3), fpc_cc);
+ break;
+
+ case 0xD:
+ setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t3)),
+ fpc_cc);
+ break;
+
+ case 0xE:
+ setFPUCondCode(binop(Iop_Or32, mkexpr(t3), mkexpr(t1)),
+ fpc_cc);
+ break;
+
+ case 0xF:
+ setFPUCondCode(mkexpr(t2), fpc_cc);
+ break;
+
+ default:
+ return False;
+ }
+
+ } else {
+ t0 = newTemp(Ity_I32);
+ t1 = newTemp(Ity_I32);
+ t2 = newTemp(Ity_I32);
+ t3 = newTemp(Ity_I32);
+
+ assign(ccIR, binop(Iop_CmpF64, unop(Iop_F32toF64, getFReg(fs)),
+ unop(Iop_F32toF64, getFReg(ft))));
+ /* Map compare result from IR to MIPS
+ FP cmp result | MIPS | IR
+ --------------------------
+ UN | 0x1 | 0x45
+ EQ | 0x2 | 0x40
+ GT | 0x4 | 0x00
+ LT | 0x8 | 0x01
+ */
+
+ /* ccMIPS = Shl(1, (~(ccIR>>5) & 2) | ((ccIR ^ (ccIR>>6)) & 1) */
+ assign(ccMIPS, binop(Iop_Shl32, mkU32(1), unop(Iop_32to8,
+ binop(Iop_Or32, binop(Iop_And32, unop(Iop_Not32,
+ binop(Iop_Shr32, mkexpr(ccIR), mkU8(5))),
+ mkU32(2)), binop(Iop_And32,
+ binop(Iop_Xor32, mkexpr(ccIR),
+ binop(Iop_Shr32, mkexpr(ccIR), mkU8(6))),
+ mkU32(1))))));
+ /* UN */
+ assign(t0, binop(Iop_And32, mkexpr(ccMIPS), mkU32(0x1)));
+ /* EQ */
+ assign(t1, binop(Iop_And32, binop(Iop_Shr32, mkexpr(ccMIPS),
+ mkU8(0x1)), mkU32(0x1)));
+ /* NGT */
+ assign(t2, binop(Iop_And32, unop(Iop_Not32, binop(Iop_Shr32,
+ mkexpr(ccMIPS), mkU8(0x2))), mkU32(0x1)));
+ /* LT */
+ assign(t3, binop(Iop_And32, binop(Iop_Shr32, mkexpr(ccMIPS),
+ mkU8(0x3)), mkU32(0x1)));
+
+ switch (cond) {
+ case 0x0:
+ setFPUCondCode(mkU32(0), fpc_cc);
+ break;
+
+ case 0x1:
+ setFPUCondCode(mkexpr(t0), fpc_cc);
+ break;
+
+ case 0x2:
+ setFPUCondCode(mkexpr(t1), fpc_cc);
+ break;
+
+ case 0x3:
+ setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t1)),
+ fpc_cc);
+ break;
+
+ case 0x4:
+ setFPUCondCode(mkexpr(t3), fpc_cc);
+ break;
+
+ case 0x5:
+ setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t3)),
+ fpc_cc);
+ break;
+
+ case 0x6:
+ setFPUCondCode(binop(Iop_Or32, mkexpr(t3), mkexpr(t1)),
+ fpc_cc);
+ break;
+
+ case 0x7:
+ setFPUCondCode(mkexpr(t2), fpc_cc);
+ break;
+
+ case 0x8:
+ setFPUCondCode(mkU32(0), fpc_cc);
+ break;
+
+ case 0x9:
+ setFPUCondCode(mkexpr(t0), fpc_cc);
+ break;
+
+ case 0xA:
+ setFPUCondCode(mkexpr(t1), fpc_cc);
+ break;
+
+ case 0xB:
+ setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t1)),
+ fpc_cc);
+ break;
+
+ case 0xC:
+ setFPUCondCode(mkexpr(t3), fpc_cc);
+ break;
+
+ case 0xD:
+ setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t3)),
+ fpc_cc);
+ break;
+
+ case 0xE:
+ setFPUCondCode(binop(Iop_Or32, mkexpr(t3), mkexpr(t1)),
+ fpc_cc);
+ break;
+
+ case 0xF:
+ setFPUCondCode(mkexpr(t2), fpc_cc);
+ break;
+
+ default:
+ return False;
+ }
+ }
+ }
+ break;
+
+ case 0x11: { /* C.cond.D */
+ DIP("c.%s.d %u, f%u, f%u", showCondCode(cond), fpc_cc, fs, ft);
+ t0 = newTemp(Ity_I32);
+ t1 = newTemp(Ity_I32);
+ t2 = newTemp(Ity_I32);
+ t3 = newTemp(Ity_I32);
+ assign(ccIR, binop(Iop_CmpF64, getDReg(fs), getDReg(ft)));
+ /* Map compare result from IR to MIPS
+ FP cmp result | MIPS | IR
+ --------------------------
+ UN | 0x1 | 0x45
+ EQ | 0x2 | 0x40
+ GT | 0x4 | 0x00
+ LT | 0x8 | 0x01
+ */
+
+ /* ccMIPS = Shl(1, (~(ccIR>>5) & 2) | ((ccIR ^ (ccIR>>6)) & 1) */
+ assign(ccMIPS, binop(Iop_Shl32, mkU32(1), unop(Iop_32to8,
+ binop(Iop_Or32, binop(Iop_And32, unop(Iop_Not32,
+ binop(Iop_Shr32, mkexpr(ccIR), mkU8(5))), mkU32(2)),
+ binop(Iop_And32, binop(Iop_Xor32, mkexpr(ccIR),
+ binop(Iop_Shr32, mkexpr(ccIR), mkU8(6))),
+ mkU32(1))))));
+
+ /* UN */
+ assign(t0, binop(Iop_And32, mkexpr(ccMIPS), mkU32(0x1)));
+ /* EQ */
+ assign(t1, binop(Iop_And32, binop(Iop_Shr32, mkexpr(ccMIPS),
+ mkU8(0x1)), mkU32(0x1)));
+ /* NGT */
+ assign(t2, binop(Iop_And32, unop(Iop_Not32, binop(Iop_Shr32,
+ mkexpr(ccMIPS), mkU8(0x2))), mkU32(0x1)));
+ /* LT */
+ assign(t3, binop(Iop_And32, binop(Iop_Shr32, mkexpr(ccMIPS),
+ mkU8(0x3)), mkU32(0x1)));
+
+ switch (cond) {
+ case 0x0:
+ setFPUCondCode(mkU32(0), fpc_cc);
+ break;
+
+ case 0x1:
+ setFPUCondCode(mkexpr(t0), fpc_cc);
+ break;
+
+ case 0x2:
+ setFPUCondCode(mkexpr(t1), fpc_cc);
+ break;
+
+ case 0x3:
+ setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t1)),
+ fpc_cc);
+ break;
+
+ case 0x4:
+ setFPUCondCode(mkexpr(t3), fpc_cc);
+ break;
+
+ case 0x5:
+ setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t3)),
+ fpc_cc);
+ break;
+
+ case 0x6:
+ setFPUCondCode(binop(Iop_Or32, mkexpr(t3), mkexpr(t1)),
+ fpc_cc);
+ break;
+
+ case 0x7:
+ setFPUCondCode(mkexpr(t2), fpc_cc);
+ break;
+
+ case 0x8:
+ setFPUCondCode(mkU32(0), fpc_cc);
+ break;
+
+ case 0x9:
+ setFPUCondCode(mkexpr(t0), fpc_cc);
+ break;
+
+ case 0xA:
+ setFPUCondCode(mkexpr(t1), fpc_cc);
+ break;
+
+ case 0xB:
+ setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t1)),
+ fpc_cc);
+ break;
+
+ case 0xC:
+ setFPUCondCode(mkexpr(t3), fpc_cc);
+ break;
+
+ case 0xD:
+ setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t3)),
+ fpc_cc);
+ break;
+
+ case 0xE:
+ setFPUCondCode(binop(Iop_Or32, mkexpr(t3), mkexpr(t1)),
+ fpc_cc);
+ break;
+
+ case 0xF:
+ setFPUCondCode(mkexpr(t2), fpc_cc);
+ break;
+
+ default:
+ return False;
+ }
+ }
+ break;
+
+ default:
+ return False;
+ }
+ } else {
+ return False;
+ }
+
+ return True;
+}
+
+/*********************************************************/
+/*--- Branch Instructions for mips64 ---*/
+/*********************************************************/
+static Bool dis_instr_branch ( UInt theInstr, DisResult * dres,
+ Bool(*resteerOkFn) (void *, Addr),
+ void *callback_opaque, IRStmt ** set )
+{
+ UInt jmpKind = 0;
+ UChar opc1 = get_opcode(theInstr);
+ UChar regRs = get_rs(theInstr);
+ UChar regRt = get_rt(theInstr);
+ UInt offset = get_imm(theInstr);
+ Long sOffset = extend_s_16to64(offset);
+ IRType ty = mode64 ? Ity_I64 : Ity_I32;
+ IROp opSlt = mode64 ? Iop_CmpLT64S : Iop_CmpLT32S;
+
+ IRTemp tmp = newTemp(ty);
+ IRTemp tmpRs = newTemp(ty);
+ IRTemp tmpRt = newTemp(ty);
+ IRTemp tmpLt = newTemp(ty);
+ IRTemp tmpReg0 = newTemp(ty);
+
+ UChar regLnk = 31; /* reg 31 is link reg in MIPS */
+ Addr64 addrTgt = 0;
+ Addr64 cia = guest_PC_curr_instr;
+
+ IRExpr *eConst0 = mkSzImm(ty, (UInt) 0);
+ IRExpr *eNia = mkSzImm(ty, cia + 8);
+ IRExpr *eCond = NULL;
+
+ assign(tmpRs, getIReg(regRs));
+ assign(tmpRt, getIReg(regRt));
+ assign(tmpReg0, getIReg(0));
+
+ eCond = binop(mkSzOp(ty, Iop_CmpNE8), mkexpr(tmpReg0), mkexpr(tmpReg0));
+
+ switch (opc1) {
+ case 0x01:
+ switch (regRt) {
+ case 0x00: { /* BLTZ rs, offset */
+ addrTgt = mkSzAddr(ty, cia + 4 + (sOffset << 2));
+ IRTemp tmpLtRes = newTemp(Ity_I1);
+
+ assign(tmp, eConst0);
+ assign(tmpLtRes, binop(opSlt, mkexpr(tmpRs), mkexpr(tmp)));
+ assign(tmpLt, mode64 ? unop(Iop_1Uto64, mkexpr(tmpLtRes)) :
+ unop(Iop_1Uto32, mkexpr(tmpLtRes)));
+
+ eCond = binop(mkSzOp(ty, Iop_CmpNE8), mkexpr(tmpLt),
+ mkexpr(tmpReg0));
+
+ jmpKind = Ijk_Boring;
+ break;
+ }
+
+ case 0x01: { /* BGEZ rs, offset */
+ IRTemp tmpLtRes = newTemp(Ity_I1);
+ addrTgt = mkSzAddr(ty, cia + 4 + (sOffset << 2));
+
+ assign(tmp, eConst0);
+ assign(tmpLtRes, binop(opSlt, mkexpr(tmpRs), mkexpr(tmp)));
+ assign(tmpLt, mode64 ? unop(Iop_1Uto64, mkexpr(tmpLtRes)) :
+ unop(Iop_1Uto32, mkexpr(tmpLtRes)));
+ eCond = binop(mkSzOp(ty, Iop_CmpEQ8), mkexpr(tmpLt),
+ mkexpr(tmpReg0));
+
+ jmpKind = Ijk_Boring;
+ break;
+ }
+
+ case 0x11: { /* BGEZAL rs, offset */
+ addrTgt = mkSzAddr(ty, cia + 4 + (sOffset << 2));
+ putIReg(regLnk, eNia);
+ IRTemp tmpLtRes = newTemp(Ity_I1);
+
+ assign(tmpLtRes, binop(opSlt, mkexpr(tmpRs), eConst0));
+ assign(tmpLt, mode64 ? unop(Iop_1Uto64, mkexpr(tmpLtRes)) :
+ unop(Iop_1Uto32, mkexpr(tmpLtRes)));
+
+ eCond = binop(mkSzOp(ty, Iop_CmpEQ8), mkexpr(tmpLt),
+ mkexpr(tmpReg0));
+
+ jmpKind = Ijk_Call;
+ break;
+ }
+
+ case 0x10: { /* BLTZAL rs, offset */
+ IRTemp tmpLtRes = newTemp(Ity_I1);
+ IRTemp tmpRes = newTemp(ty);
+
+ addrTgt = mkSzAddr(ty, cia + 4 + (sOffset << 2));
+ putIReg(regLnk, eNia);
+
+ assign(tmp, eConst0);
+ assign(tmpLtRes, binop(opSlt, mkexpr(tmpRs), mkexpr(tmp)));
+ assign(tmpRes, mode64 ? unop(Iop_1Uto64,
+ mkexpr(tmpLtRes)) : unop(Iop_1Uto32, mkexpr(tmpLtRes)));
+ eCond = binop(mkSzOp(ty, Iop_CmpNE8), mkexpr(tmpRes),
+ mkexpr(tmpReg0));
+
+ jmpKind = Ijk_Call;
+ break;
+ }
+
+ }
+
+ break;
+
+ default:
+ return False;
+ }
+
+ *set = IRStmt_Exit(eCond, jmpKind, mkSzConst(ty, addrTgt), OFFB_PC);
+ return True;
+}
+
+/*********************************************************/
+/*--- Cavium Specific Instructions ---*/
+/*********************************************************/
+
+/* Convenience function to yield to thread scheduler */
+static void jump_back(IRExpr *condition)
+{
+ stmt( IRStmt_Exit(condition,
+ Ijk_Yield,
+ IRConst_U64( guest_PC_curr_instr ),
+ OFFB_PC) );
+}
+
+/* Based on s390_irgen_load_and_add32. */
+static void mips_load_store32(IRTemp op1addr, IRTemp new_val,
+ IRTemp expd, UChar rd, Bool putIntoRd)
+{
+ IRCAS *cas;
+ IRTemp old_mem = newTemp(Ity_I32);
+ IRType ty = mode64 ? Ity_I64 : Ity_I32;
+
+ cas = mkIRCAS(IRTemp_INVALID, old_mem,
+#if defined (_MIPSEL)
+ Iend_LE, mkexpr(op1addr),
+#else /* _MIPSEB */
+ Iend_BE, mkexpr(op1addr),
+#endif
+ NULL, mkexpr(expd), /* expected value */
+ NULL, mkexpr(new_val) /* new value */);
+ stmt(IRStmt_CAS(cas));
+
+ /* If old_mem contains the expected value, then the CAS succeeded.
+ Otherwise, it did not */
+ jump_back(binop(Iop_CmpNE32, mkexpr(old_mem), mkexpr(expd)));
+
+ if (putIntoRd)
+ putIReg(rd, mkWidenFrom32(ty, mkexpr(old_mem), True));
+}
+
+/* Based on s390_irgen_load_and_add64. */
+static void mips_load_store64(IRTemp op1addr, IRTemp new_val,
+ IRTemp expd, UChar rd, Bool putIntoRd)
+{
+ IRCAS *cas;
+ IRTemp old_mem = newTemp(Ity_I64);
+ vassert(mode64);
+ cas = mkIRCAS(IRTemp_INVALID, old_mem,
+#if defined (_MIPSEL)
+ Iend_LE, mkexpr(op1addr),
+#else /* _MIPSEB */
+ Iend_BE, mkexpr(op1addr),
+#endif
+ NULL, mkexpr(expd), /* expected value */
+ NULL, mkexpr(new_val) /* new value */);
+ stmt(IRStmt_CAS(cas));
+
+ /* If old_mem contains the expected value, then the CAS succeeded.
+ Otherwise, it did not */
+ jump_back(binop(Iop_CmpNE64, mkexpr(old_mem), mkexpr(expd)));
- tmp5 = newTemp(Ity_F64);
- tmp6 = newTemp(Ity_F64);
+ if (putIntoRd)
+ putIReg(rd, mkexpr(old_mem));
+}
- assign(tmp5, unop(Iop_F32toF64, getLoFromF64(Ity_F64,
- getFReg(fs))));
- assign(tmp6, unop(Iop_F32toF64, getLoFromF64(Ity_F64,
- getFReg(ft))));
+static Bool dis_instr_CVM ( UInt theInstr )
+{
+ UChar opc2 = get_function(theInstr);
+ UChar opc1 = get_opcode(theInstr);
+ UChar regRs = get_rs(theInstr);
+ UChar regRt = get_rt(theInstr);
+ UChar regRd = get_rd(theInstr);
+ /* MIPS trap instructions extract code from theInstr[15:6].
+ Cavium OCTEON instructions SNEI, SEQI extract immediate operands
+ from the same bit field [15:6]. */
+ UInt imm = get_code(theInstr);
+ UChar lenM1 = get_msb(theInstr);
+ UChar p = get_lsb(theInstr);
+ IRType ty = mode64 ? Ity_I64 : Ity_I32;
+ IRTemp tmp = newTemp(ty);
+ IRTemp tmpRs = newTemp(ty);
+ IRTemp tmpRt = newTemp(ty);
+ IRTemp t1 = newTemp(ty);
+ UInt size;
+ assign(tmpRs, getIReg(regRs));
- assign(ccIR, binop(Iop_CmpF64, mkexpr(tmp5), mkexpr(tmp6)));
- putHI(mkWidenFrom32(mode64 ? Ity_I64: Ity_I32,
- mkexpr(ccIR), True));
- /* Map compare result from IR to MIPS
- FP cmp result | MIPS | IR
- --------------------------
- UN | 0x1 | 0x45
- EQ | 0x2 | 0x40
- GT | 0x4 | 0x00
- LT | 0x8 | 0x01
- */
+ switch (opc1) {
+ case 0x1C: {
+ switch (opc2) {
+ case 0x03: { /* DMUL rd, rs, rt */
+ DIP("dmul r%u, r%u, r%u", regRd, regRs, regRt);
+ IRTemp t0 = newTemp(Ity_I128);
+ assign(t0, binop(Iop_MullU64, getIReg(regRs), getIReg(regRt)));
+ putIReg(regRd, unop(Iop_128to64, mkexpr(t0)));
+ break;
+ }
- /* ccMIPS = Shl(1, (~(ccIR>>5) & 2) | ((ccIR ^ (ccIR>>6)) & 1) */
- assign(ccMIPS, binop(Iop_Shl32, mkU32(1), unop(Iop_32to8,
- binop(Iop_Or32, binop(Iop_And32, unop(Iop_Not32,
- binop(Iop_Shr32, mkexpr(ccIR),mkU8(5))),mkU32(2)),
- binop(Iop_And32, binop(Iop_Xor32, mkexpr(ccIR),
- binop(Iop_Shr32, mkexpr(ccIR), mkU8(6))),
- mkU32(1))))));
- putLO(mkWidenFrom32(mode64 ? Ity_I64: Ity_I32,
- mkexpr(ccMIPS), True));
+ case 0x18: { /* Store Atomic Add Word - SAA; Cavium OCTEON */
+ DIP("saa r%u, (r%u)", regRt, regRs);
+ IRTemp addr = newTemp(Ity_I64);
+ IRTemp new_val = newTemp(Ity_I32);
+ IRTemp old = newTemp(Ity_I32);
+ assign(addr, getIReg(regRs));
+ assign(old, load(Ity_I32, mkexpr(addr)));
+ assign(new_val, binop(Iop_Add32,
+ mkexpr(old),
+ mkNarrowTo32(ty, getIReg(regRt))));
+ mips_load_store32(addr, new_val, old, 0, False);
+ break;
+ }
- /* UN */
- assign(t0, binop(Iop_And32, mkexpr(ccMIPS), mkU32(0x1)));
- /* EQ */
- assign(t1, binop(Iop_And32, binop(Iop_Shr32, mkexpr(ccMIPS),
- mkU8(0x1)), mkU32(0x1)));
- /* NGT */
- assign(t2, binop(Iop_And32, unop(Iop_Not32, binop(Iop_Shr32,
- mkexpr(ccMIPS), mkU8(0x2))),mkU32(0x1)));
- /* LT */
- assign(t3, binop(Iop_And32, binop(Iop_Shr32, mkexpr(ccMIPS),
- mkU8(0x3)), mkU32(0x1)));
- switch (cond) {
- case 0x0:
- setFPUCondCode(mkU32(0), fpc_cc);
- break;
- case 0x1:
- setFPUCondCode(mkexpr(t0), fpc_cc);
- break;
- case 0x2:
- setFPUCondCode(mkexpr(t1), fpc_cc);
- break;
- case 0x3:
- setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t1)),
- fpc_cc);
- break;
- case 0x4:
- setFPUCondCode(mkexpr(t3), fpc_cc);
+ /* Store Atomic Add Doubleword - SAAD; Cavium OCTEON */
+ case 0x19: {
+ DIP( "saad r%u, (r%u)", regRt, regRs);
+ IRTemp addr = newTemp(Ity_I64);
+ IRTemp new_val = newTemp(Ity_I64);
+ IRTemp old = newTemp(Ity_I64);
+ assign(addr, getIReg(regRs));
+ assign(old, load(Ity_I64, mkexpr(addr)));
+ assign(new_val, binop(Iop_Add64,
+ mkexpr(old),
+ getIReg(regRt)));
+ mips_load_store64(addr, new_val, old, 0, False);
+ break;
+ }
+
+ /* LAI, LAID, LAD, LADD, LAS, LASD,
+ LAC, LACD, LAA, LAAD, LAW, LAWD */
+ case 0x1f: {
+ UInt opc3 = get_sa(theInstr);
+ IRTemp addr = newTemp(Ity_I64);
+
+ switch (opc3) {
+ /* Load Atomic Increment Word - LAI; Cavium OCTEON2 */
+ case 0x02: {
+ DIP("lai r%u,(r%u)\n", regRd, regRs);
+ IRTemp new_val = newTemp(Ity_I32);
+ IRTemp old = newTemp(Ity_I32);
+ assign(addr, getIReg(regRs));
+ assign(old, load(Ity_I32, mkexpr(addr)));
+ assign(new_val, binop(Iop_Add32,
+ mkexpr(old),
+ mkU32(1)));
+ mips_load_store32(addr, new_val, old, regRd, True);
break;
- case 0x5:
- setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t3)),
- fpc_cc);
+ }
+
+ /* Load Atomic Increment Doubleword - LAID; Cavium OCTEON2 */
+ case 0x03: {
+ DIP("laid r%u,(r%u)\n", regRd, regRs);
+ IRTemp new_val = newTemp(Ity_I64);
+ IRTemp old = newTemp(Ity_I64);
+ assign(addr, getIReg(regRs));
+ assign(old, load(Ity_I64, mkexpr(addr)));
+ assign(new_val, binop(Iop_Add64,
+ mkexpr(old),
+ mkU64(1)));
+ mips_load_store64(addr, new_val, old, regRd, True);
break;
- case 0x6:
- setFPUCondCode(binop(Iop_Or32, mkexpr(t3), mkexpr(t1)),
- fpc_cc);
+ }
+
+ /* Load Atomic Decrement Word - LAD; Cavium OCTEON2 */
+ case 0x06: {
+ DIP("lad r%u,(r%u)\n", regRd, regRs);
+ IRTemp new_val = newTemp(Ity_I32);
+ IRTemp old = newTemp(Ity_I32);
+ assign(addr, getIReg(regRs));
+ assign(old, load(Ity_I32, mkexpr(addr)));
+ assign(new_val, binop(Iop_Sub32,
+ mkexpr(old),
+ mkU32(1)));
+ mips_load_store32(addr, new_val, old, regRd, True);
break;
- case 0x7:
- setFPUCondCode(mkexpr(t2), fpc_cc);
+ }
+
+ /* Load Atomic Decrement Doubleword - LADD; Cavium OCTEON2 */
+ case 0x07: {
+ DIP("ladd r%u,(r%u)\n", regRd, regRs);
+ IRTemp new_val = newTemp(Ity_I64);
+ IRTemp old = newTemp(Ity_I64);
+ assign(addr, getIReg(regRs));
+ assign(old, load(Ity_I64, mkexpr(addr)));
+ assign(new_val, binop(Iop_Sub64,
+ mkexpr(old),
+ mkU64(1)));
+ mips_load_store64(addr, new_val, old, regRd, True);
break;
- case 0x8:
- setFPUCondCode(mkU32(0), fpc_cc);
+ }
+
+ /* Load Atomic Set Word - LAS; Cavium OCTEON2 */
+ case 0x0a: {
+ DIP("las r%u,(r%u)\n", regRd, regRs);
+ IRTemp new_val = newTemp(Ity_I32);
+ IRTemp old = newTemp(Ity_I32);
+ assign(addr, getIReg(regRs));
+ assign(new_val, mkU32(0xffffffff));
+ assign(old, load(Ity_I32, mkexpr(addr)));
+ mips_load_store32(addr, new_val, old, regRd, True);
break;
- case 0x9:
- setFPUCondCode(mkexpr(t0), fpc_cc);
+ }
+
+ /* Load Atomic Set Doubleword - LASD; Cavium OCTEON2 */
+ case 0x0b: {
+ DIP("lasd r%u,(r%u)\n", regRd, regRs);
+ IRTemp new_val = newTemp(Ity_I64);
+ IRTemp old = newTemp(Ity_I64);
+ assign(addr, getIReg(regRs));
+ assign(new_val, mkU64(0xffffffffffffffffULL));
+ assign(old, load(Ity_I64, mkexpr(addr)));
+ mips_load_store64(addr, new_val, old, regRd, True);
break;
- case 0xA:
- setFPUCondCode(mkexpr(t1), fpc_cc);
+ }
+
+ /* Load Atomic Clear Word - LAC; Cavium OCTEON2 */
+ case 0x0e: {
+ DIP("lac r%u,(r%u)\n", regRd, regRs);
+ IRTemp new_val = newTemp(Ity_I32);
+ IRTemp old = newTemp(Ity_I32);
+ assign(addr, getIReg(regRs));
+ assign(new_val, mkU32(0));
+ assign(old, load(Ity_I32, mkexpr(addr)));
+ mips_load_store32(addr, new_val, old, regRd, True);
break;
- case 0xB:
- setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t1)),
- fpc_cc);
+ }
+
+ /* Load Atomic Clear Doubleword - LACD; Cavium OCTEON2 */
+ case 0x0f: {
+ DIP("lacd r%u,(r%u)\n", regRd, regRs);
+ IRTemp new_val = newTemp(Ity_I64);
+ IRTemp old = newTemp(Ity_I64);
+ assign(addr, getIReg(regRs));
+ assign(new_val, mkU64(0));
+ assign(old, load(Ity_I64, mkexpr(addr)));
+ mips_load_store64(addr, new_val, old, regRd, True);
break;
- case 0xC:
- setFPUCondCode(mkexpr(t3), fpc_cc);
+ }
+
+ /* Load Atomic Add Word - LAA; Cavium OCTEON2 */
+ case 0x12: {
+ DIP("laa r%u,(r%u),r%u\n", regRd, regRs, regRt);
+ IRTemp new_val = newTemp(Ity_I32);
+ IRTemp old = newTemp(Ity_I32);
+ assign(addr, getIReg(regRs));
+ assign(old, load(Ity_I32, mkexpr(addr)));
+ assign(new_val, binop(Iop_Add32,
+ mkexpr(old),
+ mkNarrowTo32(ty, getIReg(regRt))));
+ mips_load_store32(addr, new_val, old, regRd, True);
break;
- case 0xD:
- setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t3)),
- fpc_cc);
+ }
+
+ /* Load Atomic Add Doubleword - LAAD; Cavium OCTEON2 */
+ case 0x13: {
+ DIP("laad r%u,(r%u),r%u\n", regRd, regRs, regRt);
+ IRTemp new_val = newTemp(Ity_I64);
+ IRTemp old = newTemp(Ity_I64);
+ assign(addr, getIReg(regRs));
+ assign(old, load(Ity_I64, mkexpr(addr)));
+ assign(new_val, binop(Iop_Add64,
+ load(Ity_I64, mkexpr(addr)),
+ getIReg(regRt)));
+ mips_load_store64(addr, new_val, old, regRd, True);
break;
- case 0xE:
- setFPUCondCode(binop(Iop_Or32, mkexpr(t3), mkexpr(t1)),
- fpc_cc);
+ }
+
+ /* Load Atomic Swap Word - LAW; Cavium OCTEON2 */
+ case 0x16: {
+ DIP("law r%u,(r%u)\n", regRd, regRs);
+ IRTemp new_val = newTemp(Ity_I32);
+ IRTemp old = newTemp(Ity_I32);
+ assign(addr, getIReg(regRs));
+ assign(new_val, mkNarrowTo32(ty, getIReg(regRt)));
+ assign(old, load(Ity_I32, mkexpr(addr)));
+ mips_load_store32(addr, new_val, old, regRd, True);
break;
- case 0xF:
- setFPUCondCode(mkexpr(t2), fpc_cc);
+ }
+
+ /* Load Atomic Swap Doubleword - LAWD; Cavium OCTEON2 */
+ case 0x17: {
+ DIP("lawd r%u,(r%u)\n", regRd, regRs);
+ IRTemp new_val = newTemp(Ity_I64);
+ IRTemp old = newTemp(Ity_I64);
+ assign(addr, getIReg(regRs));
+ assign(new_val, getIReg(regRt));
+ assign(old, load(Ity_I64, mkexpr(addr)));
+ mips_load_store64(addr, new_val, old, regRd, True);
break;
+ }
default:
+ vex_printf("Unknown laxx instruction, opc3=0x%x\n", opc3);
+ vex_printf("Instruction=0x%08x\n", theInstr);
return False;
}
- } else {
- t0 = newTemp(Ity_I32);
- t1 = newTemp(Ity_I32);
- t2 = newTemp(Ity_I32);
- t3 = newTemp(Ity_I32);
+ break;
+ }
+
+ /* Unsigned Byte Add - BADDU rd, rs, rt; Cavium OCTEON */
+ case 0x28: {
+ DIP("BADDU r%u, r%u, r%u", regRs, regRt, regRd);
+ IRTemp t0 = newTemp(Ity_I8);
+
+ assign(t0, binop(Iop_Add8,
+ mkNarrowTo8(ty, getIReg(regRs)),
+ mkNarrowTo8(ty, getIReg(regRt))));
+
+ if (mode64)
+ putIReg(regRd, binop(mkSzOp(ty, Iop_And8),
+ unop(Iop_8Uto64, mkexpr(t0)),
+ mkSzImm(ty, 0xFF)));
+ else
+ putIReg(regRd, binop(mkSzOp(ty, Iop_And8),
+ unop(Iop_8Uto32, mkexpr(t0)),
+ mkSzImm(ty, 0xFF)));
+
+ break;
+ }
+
+ case 0x2c: { /* Count Ones in a Word - POP; Cavium OCTEON */
+ int i, shift[5];
+ IRTemp mask[5];
+ IRTemp old = newTemp(ty);
+ IRTemp nyu = IRTemp_INVALID;
+ assign(old, getIReg(regRs));
+ DIP("pop r%u, r%u", regRd, regRs);
+
+ for (i = 0; i < 5; i++) {
+ mask[i] = newTemp(ty);
+ shift[i] = 1 << i;
+ }
+
+ if (mode64) {
+ assign(mask[0], mkU64(0x0000000055555555));
+ assign(mask[1], mkU64(0x0000000033333333));
+ assign(mask[2], mkU64(0x000000000F0F0F0F));
+ assign(mask[3], mkU64(0x0000000000FF00FF));
+ assign(mask[4], mkU64(0x000000000000FFFF));
+
+ for (i = 0; i < 5; i++) {
+ nyu = newTemp(ty);
+ assign(nyu,
+ binop(Iop_Add64,
+ binop(Iop_And64,
+ mkexpr(old), mkexpr(mask[i])),
+ binop(Iop_And64,
+ binop(Iop_Shr64,
+ mkexpr(old), mkU8(shift[i])),
+ mkexpr(mask[i]))));
+ old = nyu;
+ }
+ } else {
+ assign(mask[0], mkU32(0x55555555));
+ assign(mask[1], mkU32(0x33333333));
+ assign(mask[2], mkU32(0x0F0F0F0F));
+ assign(mask[3], mkU32(0x00FF00FF));
+ assign(mask[4], mkU32(0x0000FFFF));
+ assign(old, getIReg(regRs));
+
+ for (i = 0; i < 5; i++) {
+ nyu = newTemp(ty);
+ assign(nyu,
+ binop(Iop_Add32,
+ binop(Iop_And32,
+ mkexpr(old), mkexpr(mask[i])),
+ binop(Iop_And32,
+ binop(Iop_Shr32,
+ mkexpr(old), mkU8(shift[i])),
+ mkexpr(mask[i]))));
+ old = nyu;
+ }
+ }
+
+ putIReg(regRd, mkexpr(nyu));
+ break;
+ }
+
+ /* Count Ones in a Doubleword - DPOP; Cavium OCTEON */
+ case 0x2d: {
+ int i, shift[6];
+ IRTemp mask[6];
+ IRTemp old = newTemp(ty);
+ IRTemp nyu = IRTemp_INVALID;
+ DIP("dpop r%u, r%u", regRd, regRs);
+
+ for (i = 0; i < 6; i++) {
+ mask[i] = newTemp(ty);
+ shift[i] = 1 << i;
+ }
+
+ vassert(mode64); /*Caution! Only for Mode 64*/
+ assign(mask[0], mkU64(0x5555555555555555ULL));
+ assign(mask[1], mkU64(0x3333333333333333ULL));
+ assign(mask[2], mkU64(0x0F0F0F0F0F0F0F0FULL));
+ assign(mask[3], mkU64(0x00FF00FF00FF00FFULL));
+ assign(mask[4], mkU64(0x0000FFFF0000FFFFULL));
+ assign(mask[5], mkU64(0x00000000FFFFFFFFULL));
+ assign(old, getIReg(regRs));
+
+ for (i = 0; i < 6; i++) {
+ nyu = newTemp(Ity_I64);
+ assign(nyu,
+ binop(Iop_Add64,
+ binop(Iop_And64,
+ mkexpr(old), mkexpr(mask[i])),
+ binop(Iop_And64,
+ binop(Iop_Shr64,
+ mkexpr(old), mkU8(shift[i])),
+ mkexpr(mask[i]))));
+ old = nyu;
+ }
+
+ putIReg(regRd, mkexpr(nyu));
+ break;
+ }
+
+ case 0x32: /* 5. CINS rd, rs, p, lenm1 */
+ DIP("cins r%u, r%u, %u, %u\n", regRt, regRs, p, lenM1);
+ assign ( tmp , binop(Iop_Shl64, mkexpr(tmpRs),
+ mkU8(64 - ( lenM1 + 1 ))));
+ assign ( tmpRt, binop(Iop_Shr64, mkexpr( tmp ),
+ mkU8(64 - (p + lenM1 + 1))));
+ putIReg( regRt, mkexpr(tmpRt));
+ break;
+
+ case 0x33: /* 6. CINS32 rd, rs, p+32, lenm1 */
+ DIP("cins32 r%u, r%u, %d, %d\n", regRt, regRs, p + 32, lenM1);
+ assign ( tmp , binop(Iop_Shl64, mkexpr(tmpRs),
+ mkU8(64 - ( lenM1 + 1 ))));
+ assign ( tmpRt, binop(Iop_Shr64, mkexpr( tmp ),
+ mkU8(32 - (p + lenM1 + 1))));
+ putIReg( regRt, mkexpr(tmpRt));
+ break;
+
+ case 0x3A: /* 3. EXTS rt, rs, p len */
+ DIP("exts r%u, r%u, %d, %d\n", regRt, regRs, p, lenM1);
+ size = lenM1 + 1; /* lenm1+1 */
+ UChar lsAmt = 64 - (p + size); /* p+lenm1+1 */
+ UChar rsAmt = 64 - size; /* lenm1+1 */
+ tmp = newTemp(Ity_I64);
+ assign(tmp, binop(Iop_Shl64, mkexpr(tmpRs), mkU8(lsAmt)));
+ putIReg(regRt, binop(Iop_Sar64, mkexpr(tmp), mkU8(rsAmt)));
+ break;
+
+ case 0x3B: /* 4. EXTS32 rt, rs, p len */
+ DIP("exts32 r%u, r%u, %d, %d\n", regRt, regRs, p, lenM1);
+ assign ( tmp , binop(Iop_Shl64, mkexpr(tmpRs),
+ mkU8(32 - (p + lenM1 + 1))));
+ assign ( tmpRt, binop(Iop_Sar64, mkexpr(tmp),
+ mkU8(64 - (lenM1 + 1))) );
+ putIReg( regRt, mkexpr(tmpRt));
+ break;
+
+ case 0x2B: /* 20. SNE rd, rs, rt */
+ DIP("sne r%u, r%u, r%u", regRd, regRs, regRt);
+
+ if (mode64)
+ putIReg(regRd, unop(Iop_1Uto64, binop(Iop_CmpNE64,
+ getIReg(regRs),
+ getIReg(regRt))));
+ else
+ putIReg(regRd, unop(Iop_1Uto32, binop(Iop_CmpNE32,
+ getIReg(regRs),
+ getIReg(regRt))));
+
+ break;
+
+ case 0x2A: /* Set Equals - SEQ; Cavium OCTEON */
+ DIP("seq r%u, r%u, %d", regRd, regRs, regRt);
+
+ if (mode64)
+ putIReg(regRd, unop(Iop_1Uto64,
+ binop(Iop_CmpEQ64, getIReg(regRs),
+ getIReg(regRt))));
+ else
+ putIReg(regRd, unop(Iop_1Uto32,
+ binop(Iop_CmpEQ32, getIReg(regRs),
+ getIReg(regRt))));
+
+ break;
+
+ case 0x2E: /* Set Equals Immediate - SEQI; Cavium OCTEON */
+ DIP("seqi r%u, r%u, %u", regRt, regRs, imm);
+
+ if (mode64)
+ putIReg(regRt, unop(Iop_1Uto64,
+ binop(Iop_CmpEQ64, getIReg(regRs),
+ mkU64(extend_s_10to64(imm)))));
+ else
+ putIReg(regRt, unop(Iop_1Uto32,
+ binop(Iop_CmpEQ32, getIReg(regRs),
+ mkU32(extend_s_10to32(imm)))));
+
+ break;
+
+ case 0x2F: /* Set Not Equals Immediate - SNEI; Cavium OCTEON */
+ DIP("snei r%u, r%u, %u", regRt, regRs, imm);
+
+ if (mode64)
+ putIReg(regRt, unop(Iop_1Uto64,
+ binop(Iop_CmpNE64,
+ getIReg(regRs),
+ mkU64(extend_s_10to64(imm)))));
+ else
+ putIReg(regRt, unop(Iop_1Uto32,
+ binop(Iop_CmpNE32,
+ getIReg(regRs),
+ mkU32(extend_s_10to32(imm)))));
+
+ break;
+
+ default:
+ return False;
+ }
+
+ break;
+ } /* opc1 0x1C ends here*/
+
+ case 0x1F: {
+ switch (opc2) {
+ case 0x0A: { // lx - Load indexed instructions
+ switch (get_sa(theInstr)) {
+ case 0x00: { // LWX rd, index(base)
+ DIP("lwx r%u, r%u(r%u)", regRd, regRt, regRs);
+ LOADX_STORE_PATTERN;
+ putIReg(regRd, mkWidenFrom32(ty, load(Ity_I32, mkexpr(t1)),
+ True));
+ break;
+ }
- assign(ccIR, binop(Iop_CmpF64, unop(Iop_F32toF64, getFReg(fs)),
- unop(Iop_F32toF64, getFReg(ft))));
- /* Map compare result from IR to MIPS
- FP cmp result | MIPS | IR
- --------------------------
- UN | 0x1 | 0x45
- EQ | 0x2 | 0x40
- GT | 0x4 | 0x00
- LT | 0x8 | 0x01
- */
+ case 0x04: // LHX rd, index(base)
+ DIP("lhx r%u, r%u(r%u)", regRd, regRt, regRs);
+ LOADX_STORE_PATTERN;
- /* ccMIPS = Shl(1, (~(ccIR>>5) & 2) | ((ccIR ^ (ccIR>>6)) & 1) */
- assign(ccMIPS, binop(Iop_Shl32, mkU32(1), unop(Iop_32to8,
- binop(Iop_Or32, binop(Iop_And32, unop(Iop_Not32,
- binop(Iop_Shr32, mkexpr(ccIR), mkU8(5))),
- mkU32(2)), binop(Iop_And32,
- binop(Iop_Xor32, mkexpr(ccIR),
- binop(Iop_Shr32, mkexpr(ccIR), mkU8(6))),
- mkU32(1))))));
- /* UN */
- assign(t0, binop(Iop_And32, mkexpr(ccMIPS), mkU32(0x1)));
- /* EQ */
- assign(t1, binop(Iop_And32, binop(Iop_Shr32, mkexpr(ccMIPS),
- mkU8(0x1)), mkU32(0x1)));
- /* NGT */
- assign(t2, binop(Iop_And32, unop(Iop_Not32, binop(Iop_Shr32,
- mkexpr(ccMIPS), mkU8(0x2))), mkU32(0x1)));
- /* LT */
- assign(t3, binop(Iop_And32, binop(Iop_Shr32, mkexpr(ccMIPS),
- mkU8(0x3)), mkU32(0x1)));
+ if (mode64)
+ putIReg(regRd, unop(Iop_16Sto64, load(Ity_I16,
+ mkexpr(t1))));
+ else
+ putIReg(regRd, unop(Iop_16Sto32, load(Ity_I16,
+ mkexpr(t1))));
- switch (cond) {
- case 0x0:
- setFPUCondCode(mkU32(0), fpc_cc);
- break;
- case 0x1:
- setFPUCondCode(mkexpr(t0), fpc_cc);
- break;
- case 0x2:
- setFPUCondCode(mkexpr(t1), fpc_cc);
- break;
- case 0x3:
- setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t1)),
- fpc_cc);
- break;
- case 0x4:
- setFPUCondCode(mkexpr(t3), fpc_cc);
- break;
- case 0x5:
- setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t3)),
- fpc_cc);
- break;
- case 0x6:
- setFPUCondCode(binop(Iop_Or32, mkexpr(t3), mkexpr(t1)),
- fpc_cc);
- break;
- case 0x7:
- setFPUCondCode(mkexpr(t2), fpc_cc);
- break;
- case 0x8:
- setFPUCondCode(mkU32(0), fpc_cc);
- break;
- case 0x9:
- setFPUCondCode(mkexpr(t0), fpc_cc);
- break;
- case 0xA:
- setFPUCondCode(mkexpr(t1), fpc_cc);
break;
- case 0xB:
- setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t1)),
- fpc_cc);
+
+ case 0x08: { // LDX rd, index(base)
+ DIP("ldx r%u, r%u(r%u)", regRd, regRt, regRs);
+ vassert(mode64); /* Currently Implemented only for n64 */
+ LOADX_STORE_PATTERN;
+ putIReg(regRd, load(Ity_I64, mkexpr(t1)));
break;
- case 0xC:
- setFPUCondCode(mkexpr(t3), fpc_cc);
+ }
+
+ case 0x06: { // LBUX rd, index(base)
+ DIP("lbux r%u, r%u(r%u)", regRd, regRt, regRs);
+ LOADX_STORE_PATTERN;
+
+ if (mode64)
+ putIReg(regRd, unop(Iop_8Uto64, load(Ity_I8,
+ mkexpr(t1))));
+ else
+ putIReg(regRd, unop(Iop_8Uto32, load(Ity_I8,
+ mkexpr(t1))));
+
break;
- case 0xD:
- setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t3)),
- fpc_cc);
+ }
+
+ case 0x10: { // LWUX rd, index(base) (Cavium OCTEON)
+ DIP("lwux r%u, r%u(r%u)", regRd, regRt, regRs);
+ LOADX_STORE_PATTERN; /* same for both 32 and 64 modes*/
+ putIReg(regRd, mkWidenFrom32(ty, load(Ity_I32, mkexpr(t1)),
+ False));
break;
- case 0xE:
- setFPUCondCode(binop(Iop_Or32, mkexpr(t3), mkexpr(t1)),
- fpc_cc);
+ }
+
+ case 0x14: { // LHUX rd, index(base) (Cavium OCTEON)
+ DIP("lhux r%u, r%u(r%u)", regRd, regRt, regRs);
+ LOADX_STORE_PATTERN;
+
+ if (mode64)
+ putIReg(regRd,
+ unop(Iop_16Uto64, load(Ity_I16, mkexpr(t1))));
+ else
+ putIReg(regRd,
+ unop(Iop_16Uto32, load(Ity_I16, mkexpr(t1))));
+
break;
- case 0xF:
- setFPUCondCode(mkexpr(t2), fpc_cc);
+ }
+
+ case 0x16: { // LBX rd, index(base) (Cavium OCTEON)
+ DIP("lbx r%u, r%u(r%u)", regRd, regRs, regRt);
+ LOADX_STORE_PATTERN;
+
+ if (mode64)
+ putIReg(regRd,
+ unop(Iop_8Sto64, load(Ity_I8, mkexpr(t1))));
+ else
+ putIReg(regRd,
+ unop(Iop_8Sto32, load(Ity_I8, mkexpr(t1))));
+
break;
+ }
default:
+ vex_printf("\nUnhandled LX instruction opc3 = %x\n",
+ get_sa(theInstr));
return False;
}
- }
- }
- break;
-
- case 0x11: { /* C.cond.D */
- DIP("c.%s.d %u, f%u, f%u", showCondCode(cond), fpc_cc, fs, ft);
- t0 = newTemp(Ity_I32);
- t1 = newTemp(Ity_I32);
- t2 = newTemp(Ity_I32);
- t3 = newTemp(Ity_I32);
- assign(ccIR, binop(Iop_CmpF64, getDReg(fs), getDReg(ft)));
- /* Map compare result from IR to MIPS
- FP cmp result | MIPS | IR
- --------------------------
- UN | 0x1 | 0x45
- EQ | 0x2 | 0x40
- GT | 0x4 | 0x00
- LT | 0x8 | 0x01
- */
-
- /* ccMIPS = Shl(1, (~(ccIR>>5) & 2) | ((ccIR ^ (ccIR>>6)) & 1) */
- assign(ccMIPS, binop(Iop_Shl32, mkU32(1), unop(Iop_32to8,
- binop(Iop_Or32, binop(Iop_And32, unop(Iop_Not32,
- binop(Iop_Shr32, mkexpr(ccIR), mkU8(5))), mkU32(2)),
- binop(Iop_And32, binop(Iop_Xor32, mkexpr(ccIR),
- binop(Iop_Shr32, mkexpr(ccIR), mkU8(6))),
- mkU32(1))))));
-
- /* UN */
- assign(t0, binop(Iop_And32, mkexpr(ccMIPS), mkU32(0x1)));
- /* EQ */
- assign(t1, binop(Iop_And32, binop(Iop_Shr32, mkexpr(ccMIPS),
- mkU8(0x1)), mkU32(0x1)));
- /* NGT */
- assign(t2, binop(Iop_And32, unop(Iop_Not32, binop(Iop_Shr32,
- mkexpr(ccMIPS), mkU8(0x2))), mkU32(0x1)));
- /* LT */
- assign(t3, binop(Iop_And32, binop(Iop_Shr32, mkexpr(ccMIPS),
- mkU8(0x3)), mkU32(0x1)));
- switch (cond) {
- case 0x0:
- setFPUCondCode(mkU32(0), fpc_cc);
- break;
- case 0x1:
- setFPUCondCode(mkexpr(t0), fpc_cc);
- break;
- case 0x2:
- setFPUCondCode(mkexpr(t1), fpc_cc);
- break;
- case 0x3:
- setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t1)),
- fpc_cc);
- break;
- case 0x4:
- setFPUCondCode(mkexpr(t3), fpc_cc);
- break;
- case 0x5:
- setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t3)),
- fpc_cc);
- break;
- case 0x6:
- setFPUCondCode(binop(Iop_Or32, mkexpr(t3), mkexpr(t1)),
- fpc_cc);
- break;
- case 0x7:
- setFPUCondCode(mkexpr(t2), fpc_cc);
- break;
- case 0x8:
- setFPUCondCode(mkU32(0), fpc_cc);
- break;
- case 0x9:
- setFPUCondCode(mkexpr(t0), fpc_cc);
- break;
- case 0xA:
- setFPUCondCode(mkexpr(t1), fpc_cc);
- break;
- case 0xB:
- setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t1)),
- fpc_cc);
- break;
- case 0xC:
- setFPUCondCode(mkexpr(t3), fpc_cc);
- break;
- case 0xD:
- setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t3)),
- fpc_cc);
- break;
- case 0xE:
- setFPUCondCode(binop(Iop_Or32, mkexpr(t3), mkexpr(t1)),
- fpc_cc);
- break;
- case 0xF:
- setFPUCondCode(mkexpr(t2), fpc_cc);
- break;
- default:
- return False;
+ break;
}
- }
+ } /* opc1 = 0x1F & opc2 = 0xA (LX) ends here*/
+
break;
+ } /* opc1 = 0x1F ends here*/
- default:
- return False;
- }
- } else {
- return False;
- }
+ default:
+ return False;
+ } /* main opc1 switch ends here */
return True;
}
-/*********************************************************/
-/*--- Branch Instructions for mips64 ---*/
-/*********************************************************/
-static Bool dis_instr_branch ( UInt theInstr, DisResult * dres,
- Bool(*resteerOkFn) (void *, Addr),
- void *callback_opaque, IRStmt ** set )
+static Int msa_I8_logical(UInt cins, UChar wd, UChar ws)
{
- UInt jmpKind = 0;
- UChar opc1 = get_opcode(theInstr);
- UChar regRs = get_rs(theInstr);
- UChar regRt = get_rt(theInstr);
- UInt offset = get_imm(theInstr);
- Long sOffset = extend_s_16to64(offset);
- IRType ty = mode64 ? Ity_I64 : Ity_I32;
- IROp opSlt = mode64 ? Iop_CmpLT64S : Iop_CmpLT32S;
+ IRTemp t1, t2;
+ UShort operation;
+ UChar i8;
+
+ operation = (cins >> 24) & 3;
+ i8 = (cins & 0x00FF0000) >> 16;
+
+ switch (operation) {
+ case 0x00: { /* ANDI.B */
+ DIP("ANDI.B w%d, w%d, %d", wd, ws, i8);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ ULong tmp = i8;
+ tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
+ (tmp << 32) | (tmp << 24) | (tmp << 16) |
+ (tmp << 8);
+ assign(t1, getWReg(ws));
+ assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+ putWReg(wd, binop(Iop_AndV128, mkexpr(t1), mkexpr(t2)));
+ break;
+ }
+
+ case 0x01: { /* ORI.B */
+ DIP("ORI.B w%d, w%d, %d", wd, ws, i8);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ ULong tmp = i8;
+ tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
+ (tmp << 32) | (tmp << 24) | (tmp << 16) |
+ (tmp << 8);
+ assign(t1, getWReg(ws));
+ assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+ putWReg(wd, binop(Iop_OrV128, mkexpr(t1), mkexpr(t2)));
+ break;
+ }
- IRTemp tmp = newTemp(ty);
- IRTemp tmpRs = newTemp(ty);
- IRTemp tmpRt = newTemp(ty);
- IRTemp tmpLt = newTemp(ty);
- IRTemp tmpReg0 = newTemp(ty);
+ case 0x02: { /* NORI.B */
+ DIP("NORI.B w%d, w%d, %d", wd, ws, i8);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ ULong tmp = i8;
+ tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
+ (tmp << 32) | (tmp << 24) | (tmp << 16) |
+ (tmp << 8);
+ assign(t1, getWReg(ws));
+ assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+ putWReg(wd, unop(Iop_NotV128, binop(Iop_OrV128,
+ mkexpr(t1), mkexpr(t2))));
+ break;
+ }
- UChar regLnk = 31; /* reg 31 is link reg in MIPS */
- Addr64 addrTgt = 0;
- Addr64 cia = guest_PC_curr_instr;
+ case 0x03: { /* XORI.B */
+ DIP("XORI.B w%d, w%d, %d", wd, ws, i8);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ ULong tmp = i8;
+ tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
+ (tmp << 32) | (tmp << 24) | (tmp << 16) |
+ (tmp << 8);
+ assign(t1, getWReg(ws));
+ assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+ putWReg(wd, binop(Iop_XorV128, mkexpr(t1), mkexpr(t2)));
+ break;
+ }
- IRExpr *eConst0 = mkSzImm(ty, (UInt) 0);
- IRExpr *eNia = mkSzImm(ty, cia + 8);
- IRExpr *eCond = NULL;
+ default:
+ return -1;
+ }
- assign(tmpRs, getIReg(regRs));
- assign(tmpRt, getIReg(regRt));
- assign(tmpReg0, getIReg(0));
+ return 0;
+}
- eCond = binop(mkSzOp(ty, Iop_CmpNE8), mkexpr(tmpReg0), mkexpr(tmpReg0));
+static Int msa_I8_branch(UInt cins, UChar wd, UChar ws)
+{
+ IRTemp t1, t2, t3, t4;
+ UShort operation;
+ UChar i8;
- switch (opc1) {
- case 0x01:
- switch (regRt) {
- case 0x00: { /* BLTZ rs, offset */
- addrTgt = mkSzAddr(ty, cia + 4 + (sOffset << 2));
- IRTemp tmpLtRes = newTemp(Ity_I1);
+ operation = (cins >> 24) & 3;
+ i8 = (cins & 0x00FF0000) >> 16;
- assign(tmp, eConst0);
- assign(tmpLtRes, binop(opSlt, mkexpr(tmpRs), mkexpr(tmp)));
- assign(tmpLt, mode64 ? unop(Iop_1Uto64, mkexpr(tmpLtRes)) :
- unop(Iop_1Uto32, mkexpr(tmpLtRes)));
+ switch (operation) {
+ case 0x00: { /* BMNZI.B */
+ DIP("BMNZI.B w%d, w%d, %d", wd, ws, i8);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ t4 = newTemp(Ity_V128);
+ ULong tmp = i8;
+ tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
+ (tmp << 32) | (tmp << 24) | (tmp << 16) |
+ (tmp << 8);
+ assign(t4, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+ assign(t1, binop(Iop_AndV128, getWReg(ws), mkexpr(t4)));
+ assign(t2, binop(Iop_AndV128, getWReg(wd),
+ unop(Iop_NotV128, mkexpr(t4))));
+ assign(t3, binop(Iop_OrV128, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- eCond = binop(mkSzOp(ty, Iop_CmpNE8), mkexpr(tmpLt),
- mkexpr(tmpReg0));
+ case 0x01: { /* BMZI.B */
+ DIP("BMZI.B w%d, w%d, %d", wd, ws, i8);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ t4 = newTemp(Ity_V128);
+ ULong tmp = i8;
+ tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
+ (tmp << 32) | (tmp << 24) | (tmp << 16) |
+ (tmp << 8);
+ assign(t4, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+ assign(t1, binop(Iop_AndV128, getWReg(wd), mkexpr(t4)));
+ assign(t2, binop(Iop_AndV128, getWReg(ws),
+ unop(Iop_NotV128, mkexpr(t4))));
+ assign(t3, binop(Iop_OrV128, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- jmpKind = Ijk_Boring;
- break;
- }
+ case 0x02: { /* BSELI.B */
+ DIP("BSELI.B w%d, w%d, %d", wd, ws, i8);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ t4 = newTemp(Ity_V128);
+ ULong tmp = i8;
+ tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
+ (tmp << 32) | (tmp << 24) | (tmp << 16) |
+ (tmp << 8);
+ assign(t4, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+ assign(t1, binop(Iop_AndV128, getWReg(wd), mkexpr(t4)));
+ assign(t2, binop(Iop_AndV128, getWReg(ws),
+ unop(Iop_NotV128, getWReg(wd))));
+ assign(t3, binop(Iop_OrV128, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- case 0x01: { /* BGEZ rs, offset */
- IRTemp tmpLtRes = newTemp(Ity_I1);
- addrTgt = mkSzAddr(ty, cia + 4 + (sOffset << 2));
+ default:
+ return -1;
+ }
- assign(tmp, eConst0);
- assign(tmpLtRes, binop(opSlt, mkexpr(tmpRs), mkexpr(tmp)));
- assign(tmpLt, mode64 ? unop(Iop_1Uto64, mkexpr(tmpLtRes)) :
- unop(Iop_1Uto32, mkexpr(tmpLtRes)));
- eCond = binop(mkSzOp(ty, Iop_CmpEQ8), mkexpr(tmpLt),
- mkexpr(tmpReg0));
+ return 0;
+}
- jmpKind = Ijk_Boring;
- break;
- }
+static Int msa_I8_shift(UInt cins, UChar wd, UChar ws)
+{
+ IRTemp t1, t2;
+ UShort operation;
+ UChar i8;
- case 0x11: { /* BGEZAL rs, offset */
- addrTgt = mkSzAddr(ty, cia + 4 + (sOffset << 2));
- putIReg(regLnk, eNia);
- IRTemp tmpLtRes = newTemp(Ity_I1);
+ operation = (cins >> 24) & 3;
+ i8 = (cins & 0x00FF0000) >> 16;
- assign(tmpLtRes, binop(opSlt, mkexpr(tmpRs), eConst0));
- assign(tmpLt, mode64 ? unop(Iop_1Uto64, mkexpr(tmpLtRes)) :
- unop(Iop_1Uto32, mkexpr(tmpLtRes)));
+ switch (operation) {
+ case 0x00: { /* SHF.B */
+ DIP("SHF.B w%d, w%d, %d", wd, ws, i8);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ assign(t1, getWReg(wd));
+ assign(t2, getWReg(ws));
+ Int i;
+ IRTemp tmp[16];
- eCond = binop(mkSzOp(ty, Iop_CmpEQ8), mkexpr(tmpLt),
- mkexpr(tmpReg0));
+ for (i = 0; i < 16; i++) {
+ tmp[i] = newTemp(Ity_I8);
+ assign(tmp[i],
+ binop(Iop_GetElem8x16, mkexpr(t2),
+ mkU8(i - (i % 4) +
+ ((i8 >> (i % 4) * 2) & 0x03))));
+ }
- jmpKind = Ijk_Call;
- break;
- }
+ putWReg(wd, binop(Iop_64HLtoV128,
+ binop(Iop_32HLto64,
+ binop(Iop_16HLto32,
+ binop(Iop_8HLto16,
+ mkexpr(tmp[15]),
+ mkexpr(tmp[14])),
+ binop(Iop_8HLto16,
+ mkexpr(tmp[13]),
+ mkexpr(tmp[12]))),
+ binop(Iop_16HLto32,
+ binop(Iop_8HLto16,
+ mkexpr(tmp[11]),
+ mkexpr(tmp[10])),
+ binop(Iop_8HLto16,
+ mkexpr(tmp[9]),
+ mkexpr(tmp[8])))),
+ binop(Iop_32HLto64,
+ binop(Iop_16HLto32,
+ binop(Iop_8HLto16,
+ mkexpr(tmp[7]),
+ mkexpr(tmp[6])),
+ binop(Iop_8HLto16,
+ mkexpr(tmp[5]),
+ mkexpr(tmp[4]))),
+ binop(Iop_16HLto32,
+ binop(Iop_8HLto16,
+ mkexpr(tmp[3]),
+ mkexpr(tmp[2])),
+ binop(Iop_8HLto16,
+ mkexpr(tmp[1]),
+ mkexpr(tmp[0]))))));
+ break;
+ }
- case 0x10: { /* BLTZAL rs, offset */
- IRTemp tmpLtRes = newTemp(Ity_I1);
- IRTemp tmpRes = newTemp(ty);
+ case 0x01: { /* SHF.H */
+ DIP("SHF.H w%d, w%d, %d", wd, ws, i8);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ assign(t1, getWReg(wd));
+ assign(t2, getWReg(ws));
+ Int i;
+ IRTemp tmp[8];
- addrTgt = mkSzAddr(ty, cia + 4 + (sOffset << 2));
- putIReg(regLnk, eNia);
+ for (i = 0; i < 8; i++) {
+ tmp[i] = newTemp(Ity_I16);
+ assign(tmp[i],
+ binop(Iop_GetElem16x8, mkexpr(t2),
+ mkU8(i - (i % 4) +
+ ((i8 >> (i % 4) * 2) & 0x03))));
+ }
- assign(tmp, eConst0);
- assign(tmpLtRes, binop(opSlt, mkexpr(tmpRs), mkexpr(tmp)));
- assign(tmpRes, mode64 ? unop(Iop_1Uto64,
- mkexpr(tmpLtRes)) : unop(Iop_1Uto32, mkexpr(tmpLtRes)));
- eCond = binop(mkSzOp(ty, Iop_CmpNE8), mkexpr(tmpRes),
- mkexpr(tmpReg0));
+ putWReg(wd, binop(Iop_64HLtoV128,
+ binop(Iop_32HLto64,
+ binop(Iop_16HLto32,
+ mkexpr(tmp[7]), mkexpr(tmp[6])),
+ binop(Iop_16HLto32,
+ mkexpr(tmp[5]), mkexpr(tmp[4]))),
+ binop(Iop_32HLto64,
+ binop(Iop_16HLto32,
+ mkexpr(tmp[3]), mkexpr(tmp[2])),
+ binop(Iop_16HLto32,
+ mkexpr(tmp[1]), mkexpr(tmp[0])))));
+ break;
+ }
- jmpKind = Ijk_Call;
- break;
- }
+ case 0x02: { /* SHF.W */
+ DIP("SHF.W w%d, w%d, %d", wd, ws, i8);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ assign(t1, getWReg(wd));
+ assign(t2, getWReg(ws));
+ Int i;
+ IRTemp tmp[4];
+ for (i = 0; i < 4; i++) {
+ tmp[i] = newTemp(Ity_I32);
+ assign(tmp[i],
+ binop(Iop_GetElem32x4, mkexpr(t2),
+ mkU8(i - (i % 4) +
+ ((i8 >> (i % 4) * 2) & 0x03))));
}
+
+ putWReg(wd, binop(Iop_64HLtoV128,
+ binop(Iop_32HLto64,
+ mkexpr(tmp[3]), mkexpr(tmp[2])),
+ binop(Iop_32HLto64,
+ mkexpr(tmp[1]), mkexpr(tmp[0]))));
break;
- default:
- return False;
}
- *set = IRStmt_Exit(eCond, jmpKind, mkSzConst(ty, addrTgt), OFFB_PC);
- return True;
-}
-/*********************************************************/
-/*--- Cavium Specific Instructions ---*/
-/*********************************************************/
+ default:
+ return -1;
+ }
-/* Convenience function to yield to thread scheduler */
-static void jump_back(IRExpr *condition)
-{
- stmt( IRStmt_Exit(condition,
- Ijk_Yield,
- IRConst_U64( guest_PC_curr_instr ),
- OFFB_PC) );
+ return 0;
}
-/* Based on s390_irgen_load_and_add32. */
-static void mips_load_store32(IRTemp op1addr, IRTemp new_val,
- IRTemp expd, UChar rd, Bool putIntoRd)
+static Int msa_I5_06(UInt cins, UChar wd, UChar ws) /* I5 (0x06) */
{
- IRCAS *cas;
- IRTemp old_mem = newTemp(Ity_I32);
- IRType ty = mode64 ? Ity_I64 : Ity_I32;
+ IRTemp t1, t2, t3;
+ UShort operation;
+ UChar df, wt;
- cas = mkIRCAS(IRTemp_INVALID, old_mem,
-#if defined (_MIPSEL)
- Iend_LE, mkexpr(op1addr),
-#else /* _MIPSEB */
- Iend_BE, mkexpr(op1addr),
-#endif
- NULL, mkexpr(expd), /* expected value */
- NULL, mkexpr(new_val) /* new value */);
- stmt(IRStmt_CAS(cas));
+ operation = (cins & 0x03800000) >> 23;
+ df = (cins & 0x00600000) >> 21;
+ wt = (cins & 0x001F0000) >> 16;
- /* If old_mem contains the expected value, then the CAS succeeded.
- Otherwise, it did not */
- jump_back(binop(Iop_CmpNE32, mkexpr(old_mem), mkexpr(expd)));
- if (putIntoRd)
- putIReg(rd, mkWidenFrom32(ty, mkexpr(old_mem), True));
-}
+ switch (operation) {
+ case 0x00: { /* ADDVI */
+ ULong tmp = wt;
-/* Based on s390_irgen_load_and_add64. */
-static void mips_load_store64(IRTemp op1addr, IRTemp new_val,
- IRTemp expd, UChar rd, Bool putIntoRd)
-{
- IRCAS *cas;
- IRTemp old_mem = newTemp(Ity_I64);
- vassert(mode64);
- cas = mkIRCAS(IRTemp_INVALID, old_mem,
-#if defined (_MIPSEL)
- Iend_LE, mkexpr(op1addr),
-#else /* _MIPSEB */
- Iend_BE, mkexpr(op1addr),
-#endif
- NULL, mkexpr(expd), /* expected value */
- NULL, mkexpr(new_val) /* new value */);
- stmt(IRStmt_CAS(cas));
+ switch (df) {
+ case 0x00: { /* ADDVI.B */
+ DIP("ADDVI.B w%d, w%d, %d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
+ (tmp << 32) | (tmp << 24) | (tmp << 16) |
+ (tmp << 8);
+ assign(t1, getWReg(ws));
+ assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+ assign(t3, binop(Iop_Add8x16, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- /* If old_mem contains the expected value, then the CAS succeeded.
- Otherwise, it did not */
- jump_back(binop(Iop_CmpNE64, mkexpr(old_mem), mkexpr(expd)));
- if (putIntoRd)
- putIReg(rd, mkexpr(old_mem));
-}
+ case 0x01: { /* ADDVI.H */
+ DIP("ADDVI.H w%d, w%d, %d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
+ assign(t1, getWReg(ws));
+ assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+ assign(t3, binop(Iop_Add16x8, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
-static Bool dis_instr_CVM ( UInt theInstr )
-{
- UChar opc2 = get_function(theInstr);
- UChar opc1 = get_opcode(theInstr);
- UChar regRs = get_rs(theInstr);
- UChar regRt = get_rt(theInstr);
- UChar regRd = get_rd(theInstr);
- /* MIPS trap instructions extract code from theInstr[15:6].
- Cavium OCTEON instructions SNEI, SEQI extract immediate operands
- from the same bit field [15:6]. */
- UInt imm = get_code(theInstr);
- UChar lenM1 = get_msb(theInstr);
- UChar p = get_lsb(theInstr);
- IRType ty = mode64? Ity_I64 : Ity_I32;
- IRTemp tmp = newTemp(ty);
- IRTemp tmpRs = newTemp(ty);
- IRTemp tmpRt = newTemp(ty);
- IRTemp t1 = newTemp(ty);
- UInt size;
- assign(tmpRs, getIReg(regRs));
+ case 0x02: { /* ADDVI.W */
+ DIP("ADDVI.W w%d, w%d, %d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ tmp |= (tmp << 32);
+ assign(t1, getWReg(ws));
+ assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+ assign(t3, binop(Iop_Add32x4, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- switch(opc1) {
- case 0x1C: {
- switch(opc2) {
- case 0x03: { /* DMUL rd, rs, rt */
- DIP("dmul r%u, r%u, r%u", regRd, regRs, regRt);
- IRTemp t0 = newTemp(Ity_I128);
- assign(t0, binop(Iop_MullU64, getIReg(regRs), getIReg(regRt)));
- putIReg(regRd, unop(Iop_128to64, mkexpr(t0)));
+ case 0x03: { /* ADDVI.D */
+ DIP("ADDVI.D w%d, w%d, %d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+ assign(t3, binop(Iop_Add64x2, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
+ }
+
+ break;
+ }
+
+ case 0x01: { /* SUBVI */
+ ULong tmp = wt;
+
+ switch (df) {
+ case 0x00: { /* SUBVI.B */
+ DIP("SUBVI.B w%d, w%d, %d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
+ (tmp << 32) | (tmp << 24) | (tmp << 16) |
+ (tmp << 8);
+ assign(t1, getWReg(ws));
+ assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+ assign(t3, binop(Iop_Sub8x16, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
break;
}
- case 0x18: { /* Store Atomic Add Word - SAA; Cavium OCTEON */
- DIP("saa r%u, (r%u)", regRt, regRs);
- IRTemp addr = newTemp(Ity_I64);
- IRTemp new_val = newTemp(Ity_I32);
- IRTemp old = newTemp(Ity_I32);
- assign(addr, getIReg(regRs));
- assign(old, load(Ity_I32, mkexpr(addr)));
- assign(new_val, binop(Iop_Add32,
- mkexpr(old),
- mkNarrowTo32(ty, getIReg(regRt))));
- mips_load_store32(addr, new_val, old, 0, False);
+ case 0x01: { /* SUBVI.H */
+ DIP("SUBVI.H w%d, w%d, %d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
+ assign(t1, getWReg(ws));
+ assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+ assign(t3, binop(Iop_Sub16x8, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
break;
}
- /* Store Atomic Add Doubleword - SAAD; Cavium OCTEON */
- case 0x19: {
- DIP( "saad r%u, (r%u)", regRt, regRs);
- IRTemp addr = newTemp(Ity_I64);
- IRTemp new_val = newTemp(Ity_I64);
- IRTemp old = newTemp(Ity_I64);
- assign(addr, getIReg(regRs));
- assign(old, load(Ity_I64, mkexpr(addr)));
- assign(new_val, binop(Iop_Add64,
- mkexpr(old),
- getIReg(regRt)));
- mips_load_store64(addr, new_val, old, 0, False);
+ case 0x02: { /* SUBVI.W */
+ DIP("SUBVI.W w%d, w%d, %d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ tmp |= (tmp << 32);
+ assign(t1, getWReg(ws));
+ assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+ assign(t3, binop(Iop_Sub32x4, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
break;
}
- /* LAI, LAID, LAD, LADD, LAS, LASD,
- LAC, LACD, LAA, LAAD, LAW, LAWD */
- case 0x1f: {
- UInt opc3 = get_sa(theInstr);
- IRTemp addr = newTemp(Ity_I64);
- switch (opc3) {
- /* Load Atomic Increment Word - LAI; Cavium OCTEON2 */
- case 0x02: {
- DIP("lai r%u,(r%u)\n", regRd, regRs);
- IRTemp new_val = newTemp(Ity_I32);
- IRTemp old = newTemp(Ity_I32);
- assign(addr, getIReg(regRs));
- assign(old, load(Ity_I32, mkexpr(addr)));
- assign(new_val, binop(Iop_Add32,
- mkexpr(old),
- mkU32(1)));
- mips_load_store32(addr, new_val, old, regRd, True);
- break;
- }
- /* Load Atomic Increment Doubleword - LAID; Cavium OCTEON2 */
- case 0x03: {
- DIP("laid r%u,(r%u)\n", regRd, regRs);
- IRTemp new_val = newTemp(Ity_I64);
- IRTemp old = newTemp(Ity_I64);
- assign(addr, getIReg(regRs));
- assign(old, load(Ity_I64, mkexpr(addr)));
- assign(new_val, binop(Iop_Add64,
- mkexpr(old),
- mkU64(1)));
- mips_load_store64(addr, new_val, old, regRd, True);
- break;
- }
- /* Load Atomic Decrement Word - LAD; Cavium OCTEON2 */
- case 0x06: {
- DIP("lad r%u,(r%u)\n", regRd, regRs);
- IRTemp new_val = newTemp(Ity_I32);
- IRTemp old = newTemp(Ity_I32);
- assign(addr, getIReg(regRs));
- assign(old, load(Ity_I32, mkexpr(addr)));
- assign(new_val, binop(Iop_Sub32,
- mkexpr(old),
- mkU32(1)));
- mips_load_store32(addr, new_val, old, regRd, True);
- break;
- }
- /* Load Atomic Decrement Doubleword - LADD; Cavium OCTEON2 */
- case 0x07: {
- DIP("ladd r%u,(r%u)\n", regRd, regRs);
- IRTemp new_val = newTemp(Ity_I64);
- IRTemp old = newTemp(Ity_I64);
- assign(addr, getIReg(regRs));
- assign(old, load(Ity_I64, mkexpr(addr)));
- assign(new_val, binop(Iop_Sub64,
- mkexpr(old),
- mkU64(1)));
- mips_load_store64(addr, new_val, old, regRd, True);
- break;
- }
- /* Load Atomic Set Word - LAS; Cavium OCTEON2 */
- case 0x0a: {
- DIP("las r%u,(r%u)\n", regRd, regRs);
- IRTemp new_val = newTemp(Ity_I32);
- IRTemp old = newTemp(Ity_I32);
- assign(addr, getIReg(regRs));
- assign(new_val, mkU32(0xffffffff));
- assign(old, load(Ity_I32, mkexpr(addr)));
- mips_load_store32(addr, new_val, old, regRd, True);
- break;
- }
- /* Load Atomic Set Doubleword - LASD; Cavium OCTEON2 */
- case 0x0b: {
- DIP("lasd r%u,(r%u)\n", regRd, regRs);
- IRTemp new_val = newTemp(Ity_I64);
- IRTemp old = newTemp(Ity_I64);
- assign(addr, getIReg(regRs));
- assign(new_val, mkU64(0xffffffffffffffffULL));
- assign(old, load(Ity_I64, mkexpr(addr)));
- mips_load_store64(addr, new_val, old, regRd, True);
- break;
- }
- /* Load Atomic Clear Word - LAC; Cavium OCTEON2 */
- case 0x0e: {
- DIP("lac r%u,(r%u)\n", regRd, regRs);
- IRTemp new_val = newTemp(Ity_I32);
- IRTemp old = newTemp(Ity_I32);
- assign(addr, getIReg(regRs));
- assign(new_val, mkU32(0));
- assign(old, load(Ity_I32, mkexpr(addr)));
- mips_load_store32(addr, new_val, old, regRd, True);
- break;
- }
- /* Load Atomic Clear Doubleword - LACD; Cavium OCTEON2 */
- case 0x0f: {
- DIP("lacd r%u,(r%u)\n", regRd, regRs);
- IRTemp new_val = newTemp(Ity_I64);
- IRTemp old = newTemp(Ity_I64);
- assign(addr, getIReg(regRs));
- assign(new_val, mkU64(0));
- assign(old, load(Ity_I64, mkexpr(addr)));
- mips_load_store64(addr, new_val, old, regRd, True);
- break;
- }
- /* Load Atomic Add Word - LAA; Cavium OCTEON2 */
- case 0x12: {
- DIP("laa r%u,(r%u),r%u\n", regRd, regRs, regRt);
- IRTemp new_val = newTemp(Ity_I32);
- IRTemp old = newTemp(Ity_I32);
- assign(addr, getIReg(regRs));
- assign(old, load(Ity_I32, mkexpr(addr)));
- assign(new_val, binop(Iop_Add32,
- mkexpr(old),
- mkNarrowTo32(ty, getIReg(regRt))));
- mips_load_store32(addr, new_val, old, regRd, True);
- break;
- }
- /* Load Atomic Add Doubleword - LAAD; Cavium OCTEON2 */
- case 0x13: {
- DIP("laad r%u,(r%u),r%u\n", regRd, regRs, regRt);
- IRTemp new_val = newTemp(Ity_I64);
- IRTemp old = newTemp(Ity_I64);
- assign(addr, getIReg(regRs));
- assign(old, load(Ity_I64, mkexpr(addr)));
- assign(new_val, binop(Iop_Add64,
- load(Ity_I64, mkexpr(addr)),
- getIReg(regRt)));
- mips_load_store64(addr, new_val, old, regRd, True);
- break;
- }
- /* Load Atomic Swap Word - LAW; Cavium OCTEON2 */
- case 0x16: {
- DIP("law r%u,(r%u)\n", regRd, regRs);
- IRTemp new_val = newTemp(Ity_I32);
- IRTemp old = newTemp(Ity_I32);
- assign(addr, getIReg(regRs));
- assign(new_val, mkNarrowTo32(ty, getIReg(regRt)));
- assign(old, load(Ity_I32, mkexpr(addr)));
- mips_load_store32(addr, new_val, old, regRd, True);
- break;
- }
- /* Load Atomic Swap Doubleword - LAWD; Cavium OCTEON2 */
- case 0x17: {
- DIP("lawd r%u,(r%u)\n", regRd, regRs);
- IRTemp new_val = newTemp(Ity_I64);
- IRTemp old = newTemp(Ity_I64);
- assign(addr, getIReg(regRs));
- assign(new_val, getIReg(regRt));
- assign(old, load(Ity_I64, mkexpr(addr)));
- mips_load_store64(addr, new_val, old, regRd, True);
- break;
- }
- default:
- vex_printf("Unknown laxx instruction, opc3=0x%x\n", opc3);
- vex_printf("Instruction=0x%08x\n", theInstr);
- return False;
- }
+ case 0x03: { /* SUBVI.D */
+ DIP("SUBVI.D w%d, w%d, %d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+ assign(t3, binop(Iop_Sub64x2, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
break;
}
+ }
- /* Unsigned Byte Add - BADDU rd, rs, rt; Cavium OCTEON */
- case 0x28: {
- DIP("BADDU r%u, r%u, r%u", regRs, regRt, regRd);
- IRTemp t0 = newTemp(Ity_I8);
-
- assign(t0, binop(Iop_Add8,
- mkNarrowTo8(ty, getIReg(regRs)),
- mkNarrowTo8(ty, getIReg(regRt))));
-
- if (mode64)
- putIReg(regRd, binop(mkSzOp(ty, Iop_And8),
- unop(Iop_8Uto64, mkexpr(t0)),
- mkSzImm(ty, 0xFF)));
- else
- putIReg(regRd, binop(mkSzOp(ty, Iop_And8),
- unop(Iop_8Uto32, mkexpr(t0)),
- mkSzImm(ty, 0xFF)));
+ break;
+ }
+
+ case 0x02: { /* MAXI_S */
+ ULong tmp = wt;
+
+ switch (df) {
+ case 0x00: { /* MAXI_S.B */
+ DIP("MAXI_S.B w%d, w%d, %d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ char stemp = ((int)tmp << 27) >> 27;
+ tmp = (UChar)stemp;
+ tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
+ (tmp << 32) | (tmp << 24) | (tmp << 16) |
+ (tmp << 8);
+ assign(t1, getWReg(ws));
+ assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+ assign(t3, binop(Iop_Max8Sx16, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
break;
}
-
- case 0x2c: { /* Count Ones in a Word - POP; Cavium OCTEON */
- int i, shift[5];
- IRTemp mask[5];
- IRTemp old = newTemp(ty);
- IRTemp nyu = IRTemp_INVALID;
- assign(old, getIReg(regRs));
- DIP("pop r%u, r%u", regRd, regRs);
-
- for (i = 0; i < 5; i++) {
- mask[i] = newTemp(ty);
- shift[i] = 1 << i;
- }
- if(mode64) {
- assign(mask[0], mkU64(0x0000000055555555));
- assign(mask[1], mkU64(0x0000000033333333));
- assign(mask[2], mkU64(0x000000000F0F0F0F));
- assign(mask[3], mkU64(0x0000000000FF00FF));
- assign(mask[4], mkU64(0x000000000000FFFF));
-
- for (i = 0; i < 5; i++) {
- nyu = newTemp(ty);
- assign(nyu,
- binop(Iop_Add64,
- binop(Iop_And64,
- mkexpr(old), mkexpr(mask[i])),
- binop(Iop_And64,
- binop(Iop_Shr64,
- mkexpr(old), mkU8(shift[i])),
- mkexpr(mask[i]))));
- old = nyu;
- }
- } else {
- assign(mask[0], mkU32(0x55555555));
- assign(mask[1], mkU32(0x33333333));
- assign(mask[2], mkU32(0x0F0F0F0F));
- assign(mask[3], mkU32(0x00FF00FF));
- assign(mask[4], mkU32(0x0000FFFF));
- assign(old, getIReg(regRs));
-
- for (i = 0; i < 5; i++) {
- nyu = newTemp(ty);
- assign(nyu,
- binop(Iop_Add32,
- binop(Iop_And32,
- mkexpr(old), mkexpr(mask[i])),
- binop(Iop_And32,
- binop(Iop_Shr32,
- mkexpr(old), mkU8(shift[i])),
- mkexpr(mask[i]))));
- old = nyu;
- }
- }
- putIReg(regRd, mkexpr(nyu));
+
+ case 0x01: { /* MAXI_S.H */
+ DIP("MAXI_S.H w%d, w%d, %d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ short stemp = ((int)tmp << 27) >> 27;
+ tmp = (UShort)stemp;
+ tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
+ assign(t1, getWReg(ws));
+ assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+ assign(t3, binop(Iop_Max16Sx8, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
+
+ case 0x02: { /* MAXI_S.W */
+ DIP("MAXI_S.W w%d, w%d, %d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ int stemp = ((int)tmp << 27) >> 27;
+ tmp = (UInt)stemp;
+ tmp |= (tmp << 32);
+ assign(t1, getWReg(ws));
+ assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+ assign(t3, binop(Iop_Max32Sx4, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
+
+ case 0x03: { /* MAXI_S.D */
+ DIP("MAXI_S.D w%d, w%d, %d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ Long stemp = ((Long)tmp << 59) >> 59;
+ tmp = stemp;
+ assign(t1, getWReg(ws));
+ assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+ assign(t3, binop(Iop_Max64Sx2, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
break;
}
-
- /* Count Ones in a Doubleword - DPOP; Cavium OCTEON */
- case 0x2d: {
- int i, shift[6];
- IRTemp mask[6];
- IRTemp old = newTemp(ty);
- IRTemp nyu = IRTemp_INVALID;
- DIP("dpop r%u, r%u", regRd, regRs);
-
- for (i = 0; i < 6; i++) {
- mask[i] = newTemp(ty);
- shift[i] = 1 << i;
- }
- vassert(mode64); /*Caution! Only for Mode 64*/
- assign(mask[0], mkU64(0x5555555555555555ULL));
- assign(mask[1], mkU64(0x3333333333333333ULL));
- assign(mask[2], mkU64(0x0F0F0F0F0F0F0F0FULL));
- assign(mask[3], mkU64(0x00FF00FF00FF00FFULL));
- assign(mask[4], mkU64(0x0000FFFF0000FFFFULL));
- assign(mask[5], mkU64(0x00000000FFFFFFFFULL));
- assign(old, getIReg(regRs));
- for (i = 0; i < 6; i++) {
- nyu = newTemp(Ity_I64);
- assign(nyu,
- binop(Iop_Add64,
- binop(Iop_And64,
- mkexpr(old), mkexpr(mask[i])),
- binop(Iop_And64,
- binop(Iop_Shr64,
- mkexpr(old), mkU8(shift[i])),
- mkexpr(mask[i]))));
- old = nyu;
- }
- putIReg(regRd, mkexpr(nyu));
+ }
+
+ break;
+ }
+
+ case 0x03: { /* MAXI_U */
+ ULong tmp = wt;
+
+ switch (df) {
+ case 0x00: { /* MAXI_U.B */
+ DIP("MAXI_U.B w%d, w%d, %d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
+ (tmp << 32) | (tmp << 24) | (tmp << 16) |
+ (tmp << 8);
+ assign(t1, getWReg(ws));
+ assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+ assign(t3, binop(Iop_Max8Ux16, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
break;
}
- case 0x32: /* 5. CINS rd, rs, p, lenm1 */
- DIP("cins r%u, r%u, %u, %u\n", regRt, regRs, p, lenM1);
- assign ( tmp , binop(Iop_Shl64, mkexpr(tmpRs),
- mkU8(64-( lenM1+1 ))));
- assign ( tmpRt, binop(Iop_Shr64, mkexpr( tmp ),
- mkU8(64-(p+lenM1+1))));
- putIReg( regRt, mkexpr(tmpRt));
+ case 0x01: { /* MAXI_U.H */
+ DIP("MAXI_U.H w%d, w%d, %d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
+ assign(t1, getWReg(ws));
+ assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+ assign(t3, binop(Iop_Max16Ux8, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
break;
+ }
- case 0x33: /* 6. CINS32 rd, rs, p+32, lenm1 */
- DIP("cins32 r%u, r%u, %d, %d\n", regRt, regRs, p+32, lenM1);
- assign ( tmp , binop(Iop_Shl64, mkexpr(tmpRs),
- mkU8(64-( lenM1+1 ))));
- assign ( tmpRt, binop(Iop_Shr64, mkexpr( tmp ),
- mkU8(32-(p+lenM1+1))));
- putIReg( regRt, mkexpr(tmpRt));
+ case 0x02: { /* MAXI_U.W */
+ DIP("MAXI_U.W w%d, w%d, %d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ tmp |= (tmp << 32);
+ assign(t1, getWReg(ws));
+ assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+ assign(t3, binop(Iop_Max32Ux4, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
break;
+ }
- case 0x3A: /* 3. EXTS rt, rs, p len */
- DIP("exts r%u, r%u, %d, %d\n", regRt, regRs, p, lenM1);
- size = lenM1 + 1; /* lenm1+1 */
- UChar lsAmt = 64 - (p + size); /* p+lenm1+1 */
- UChar rsAmt = 64 - size; /* lenm1+1 */
- tmp = newTemp(Ity_I64);
- assign(tmp, binop(Iop_Shl64, mkexpr(tmpRs), mkU8(lsAmt)));
- putIReg(regRt, binop(Iop_Sar64, mkexpr(tmp), mkU8(rsAmt)));
+ case 0x03: { /* MAXI_U.D */
+ DIP("MAXI_U.D w%d, w%d, %d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+ assign(t3, binop(Iop_Max64Ux2, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
break;
+ }
+ }
- case 0x3B: /* 4. EXTS32 rt, rs, p len */
- DIP("exts32 r%u, r%u, %d, %d\n", regRt, regRs, p, lenM1);
- assign ( tmp , binop(Iop_Shl64, mkexpr(tmpRs),
- mkU8(32-(p+lenM1+1))));
- assign ( tmpRt, binop(Iop_Sar64, mkexpr(tmp),
- mkU8(64-(lenM1+1))) );
- putIReg( regRt, mkexpr(tmpRt));
+ break;
+ }
+
+ case 0x04: { /* MINI_S */
+ ULong tmp = wt;
+
+ switch (df) {
+ case 0x00: { /* MINI_S.B */
+ DIP("MINI_S.B w%d, w%d, %d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ char stemp = ((int)tmp << 27) >> 27;
+ tmp = (UChar)stemp;
+ tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
+ (tmp << 32) | (tmp << 24) | (tmp << 16) |
+ (tmp << 8);
+ assign(t1, getWReg(ws));
+ assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+ assign(t3, binop(Iop_Min8Sx16, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
break;
+ }
- case 0x2B: /* 20. SNE rd, rs, rt */
- DIP("sne r%u, r%u, r%u", regRd,regRs, regRt);
- if (mode64)
- putIReg(regRd, unop(Iop_1Uto64, binop(Iop_CmpNE64,
- getIReg(regRs),
- getIReg(regRt))));
- else
- putIReg(regRd,unop(Iop_1Uto32, binop(Iop_CmpNE32,
- getIReg(regRs),
- getIReg(regRt))));
+ case 0x01: { /* MINI_S.H */
+ DIP("MINI_S.H w%d, w%d, %d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ short stemp = ((int)tmp << 27) >> 27;
+ tmp = (UShort)stemp;
+ tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
+ assign(t1, getWReg(ws));
+ assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+ assign(t3, binop(Iop_Min16Sx8, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
break;
+ }
- case 0x2A: /* Set Equals - SEQ; Cavium OCTEON */
- DIP("seq r%u, r%u, %d", regRd, regRs, regRt);
- if (mode64)
- putIReg(regRd, unop(Iop_1Uto64,
- binop(Iop_CmpEQ64, getIReg(regRs),
- getIReg(regRt))));
- else
- putIReg(regRd, unop(Iop_1Uto32,
- binop(Iop_CmpEQ32, getIReg(regRs),
- getIReg(regRt))));
+ case 0x02: { /* MINI_S.W */
+ DIP("MINI_S.W w%d, w%d, %d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ int stemp = ((int)tmp << 27) >> 27;
+ tmp = (UInt)stemp;
+ tmp |= (tmp << 32);
+ assign(t1, getWReg(ws));
+ assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+ assign(t3, binop(Iop_Min32Sx4, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
break;
+ }
- case 0x2E: /* Set Equals Immediate - SEQI; Cavium OCTEON */
- DIP("seqi r%u, r%u, %u", regRt, regRs, imm);
- if (mode64)
- putIReg(regRt, unop(Iop_1Uto64,
- binop(Iop_CmpEQ64, getIReg(regRs),
- mkU64(extend_s_10to64(imm)))));
- else
- putIReg(regRt, unop(Iop_1Uto32,
- binop(Iop_CmpEQ32, getIReg(regRs),
- mkU32(extend_s_10to32(imm)))));
+ case 0x03: { /* MINI_S.D */
+ DIP("MINI_S.D w%d, w%d, %d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ Long stemp = ((Long)tmp << 59) >> 59;
+ tmp = stemp;
+ assign(t1, getWReg(ws));
+ assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+ assign(t3, binop(Iop_Min64Sx2, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
break;
+ }
+ }
- case 0x2F: /* Set Not Equals Immediate - SNEI; Cavium OCTEON */
- DIP("snei r%u, r%u, %u", regRt, regRs, imm);
- if (mode64)
- putIReg(regRt, unop(Iop_1Uto64,
- binop(Iop_CmpNE64,
- getIReg(regRs),
- mkU64(extend_s_10to64(imm)))));
- else
- putIReg(regRt, unop(Iop_1Uto32,
- binop(Iop_CmpNE32,
- getIReg(regRs),
- mkU32(extend_s_10to32(imm)))));
+ break;
+ }
+
+ case 0x05: { /* MINI_U */
+ ULong tmp = wt;
+
+ switch (df) {
+ case 0x00: { /* MINI_U.B */
+ DIP("MINI_U.B w%d, w%d, %d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
+ (tmp << 32) | (tmp << 24) | (tmp << 16) |
+ (tmp << 8);
+ assign(t1, getWReg(ws));
+ assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+ assign(t3, binop(Iop_Min8Ux16, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
break;
+ }
- default:
- return False;
+ case 0x01: { /* MINI_U.H */
+ DIP("MINI_U.H w%d, w%d, %d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
+ assign(t1, getWReg(ws));
+ assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+ assign(t3, binop(Iop_Min16Ux8, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
+
+ case 0x02: { /* MINI_U.W */
+ DIP("MINI_U.W w%d, w%d, %d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ tmp |= (tmp << 32);
+ assign(t1, getWReg(ws));
+ assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+ assign(t3, binop(Iop_Min32Ux4, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
+
+ case 0x03: { /* MINI_U.D */
+ DIP("MINI_U.D w%d, w%d, %d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+ assign(t3, binop(Iop_Min64Ux2, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
}
+
break;
- } /* opc1 0x1C ends here*/
- case 0x1F: {
- switch(opc2) {
- case 0x0A: { // lx - Load indexed instructions
- switch (get_sa(theInstr)) {
- case 0x00: { // LWX rd, index(base)
- DIP("lwx r%u, r%u(r%u)", regRd, regRt, regRs);
- LOADX_STORE_PATTERN;
- putIReg(regRd, mkWidenFrom32(ty, load(Ity_I32, mkexpr(t1)),
- True));
- break;
- }
- case 0x04: // LHX rd, index(base)
- DIP("lhx r%u, r%u(r%u)", regRd, regRt, regRs);
- LOADX_STORE_PATTERN;
- if (mode64)
- putIReg(regRd, unop(Iop_16Sto64, load(Ity_I16,
- mkexpr(t1))));
- else
- putIReg(regRd, unop(Iop_16Sto32, load(Ity_I16,
- mkexpr(t1))));
- break;
- case 0x08: { // LDX rd, index(base)
- DIP("ldx r%u, r%u(r%u)", regRd, regRt, regRs);
- vassert(mode64); /* Currently Implemented only for n64 */
- LOADX_STORE_PATTERN;
- putIReg(regRd, load(Ity_I64, mkexpr(t1)));
- break;
- }
- case 0x06: { // LBUX rd, index(base)
- DIP("lbux r%u, r%u(r%u)", regRd, regRt, regRs);
- LOADX_STORE_PATTERN;
- if (mode64)
- putIReg(regRd, unop(Iop_8Uto64, load(Ity_I8,
- mkexpr(t1))));
- else
- putIReg(regRd, unop(Iop_8Uto32, load(Ity_I8,
- mkexpr(t1))));
- break;
- }
- case 0x10: { // LWUX rd, index(base) (Cavium OCTEON)
- DIP("lwux r%u, r%u(r%u)", regRd, regRt, regRs);
- LOADX_STORE_PATTERN; /* same for both 32 and 64 modes*/
- putIReg(regRd, mkWidenFrom32(ty, load(Ity_I32, mkexpr(t1)),
- False));
- break;
- }
- case 0x14: { // LHUX rd, index(base) (Cavium OCTEON)
- DIP("lhux r%u, r%u(r%u)", regRd, regRt, regRs);
- LOADX_STORE_PATTERN;
- if (mode64)
- putIReg(regRd,
- unop(Iop_16Uto64, load(Ity_I16, mkexpr(t1))));
- else
- putIReg(regRd,
- unop(Iop_16Uto32, load(Ity_I16, mkexpr(t1))));
- break;
- }
- case 0x16: { // LBX rd, index(base) (Cavium OCTEON)
- DIP("lbx r%u, r%u(r%u)", regRd, regRs, regRt);
- LOADX_STORE_PATTERN;
- if (mode64)
- putIReg(regRd,
- unop(Iop_8Sto64, load(Ity_I8, mkexpr(t1))));
- else
- putIReg(regRd,
- unop(Iop_8Sto32, load(Ity_I8, mkexpr(t1))));
- break;
- }
- default:
- vex_printf("\nUnhandled LX instruction opc3 = %x\n",
- get_sa(theInstr));
- return False;
- }
+ }
+
+ default: {
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+static Int msa_I5_07(UInt cins, UChar wd, UChar ws) /* I5 (0x07) / I10 */
+{
+ IRTemp t1, t2, t3;
+ UShort operation;
+ UChar df, i5;
+
+ operation = (cins & 0x03800000) >> 23;
+ df = (cins & 0x00600000) >> 21;
+ i5 = (cins & 0x001F0000) >> 16;
+
+ switch (operation) {
+ case 0x00: {
+ ULong tmp = i5;
+
+ switch (df) {
+ case 0x00: { /* CEQI.B */
+ DIP("CEQI.B w%d, w%d, %d", wd, ws, i5);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ char stemp = ((int)tmp << 27) >> 27;
+ tmp = (UChar)stemp;
+ tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
+ (tmp << 32) | (tmp << 24) | (tmp << 16) |
+ (tmp << 8);
+ assign(t1, getWReg(ws));
+ assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+ assign(t3, binop(Iop_CmpEQ8x16, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
break;
}
- } /* opc1 = 0x1F & opc2 = 0xA (LX) ends here*/
+
+ case 0x01: { /* CEQI.H */
+ DIP("CEQI.H w%d, w%d, %d", wd, ws, i5);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ short stemp = ((int)tmp << 27) >> 27;
+ tmp = (UShort)stemp;
+ tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
+ assign(t1, getWReg(ws));
+ assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+ assign(t3, binop(Iop_CmpEQ16x8, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
+
+ case 0x02: { /* CEQI.W */
+ DIP("CEQI.W w%d, w%d, %d", wd, ws, i5);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ int stemp = ((int)tmp << 27) >> 27;
+ tmp = (UInt)stemp;
+ tmp |= (tmp << 32);
+ assign(t1, getWReg(ws));
+ assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+ assign(t3, binop(Iop_CmpEQ32x4, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
+
+ case 0x03: { /* CEQI.D */
+ DIP("CEQI.D w%d, w%d, %d", wd, ws, i5);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ Long stemp = ((Long)tmp << 59) >> 59;
+ tmp = stemp;
+ assign(t1, getWReg(ws));
+ assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+ assign(t3, binop(Iop_CmpEQ64x2, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
+ }
+
break;
- } /* opc1 = 0x1F ends here*/
- default:
- return False;
- } /* main opc1 switch ends here */
- return True;
-}
+ }
-/*------------------------------------------------------------*/
-/*--- Disassemble a single DSP ASE instruction ---*/
-/*------------------------------------------------------------*/
+ case 0x02: { /* CLTI_S.df */
+ ULong tmp = i5;
-static UInt disDSPInstr_MIPS_WRK ( UInt cins )
-{
- IRTemp t0, t1 = 0, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14,
- t15, t16, t17;
- UInt opcode, rs, rt, rd, sa, function, ac, ac_mfhilo, rddsp_mask,
- wrdsp_mask, dsp_imm, shift;
+ switch (df) {
+ case 0x00: { /* CLTI_S.B */
+ DIP("CLTI_S.B w%d, w%d, %d", wd, ws, i5);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ char stemp = ((int)tmp << 27) >> 27;
+ tmp = (UChar)stemp;
+ tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
+ (tmp << 32) | (tmp << 24) | (tmp << 16) |
+ (tmp << 8);
+ assign(t1, getWReg(ws));
+ assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+ assign(t3, binop(Iop_CmpGT8Sx16, mkexpr(t2), mkexpr(t1)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- opcode = get_opcode(cins);
- rs = get_rs(cins);
- rt = get_rt(cins);
- rd = get_rd(cins);
- sa = get_sa(cins);
- function = get_function(cins);
- ac = get_acNo(cins);
- ac_mfhilo = get_acNo_mfhilo(cins);
- rddsp_mask = get_rddspMask(cins);
- wrdsp_mask = get_wrdspMask(cins);
- dsp_imm = get_dspImm(cins);
- shift = get_shift(cins);
-
- switch (opcode) {
- case 0x00: { /* Special */
- switch (function) {
- case 0x10: { /* MFHI */
- DIP("mfhi ac%u r%u", ac_mfhilo, rd);
- putIReg(rd, unop(Iop_64HIto32, getAcc(ac_mfhilo)));
+ case 0x01: { /* CLTI_S.H */
+ DIP("CLTI_S.H w%d, w%d, %d", wd, ws, i5);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ short stemp = ((int)tmp << 27) >> 27;
+ tmp = (UShort)stemp;
+ tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
+ assign(t1, getWReg(ws));
+ assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+ assign(t3, binop(Iop_CmpGT16Sx8, mkexpr(t2), mkexpr(t1)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
+
+ case 0x02: { /* CLTI_S.W */
+ DIP("CLTI_S.W w%d, w%d, %d", wd, ws, i5);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ int stemp = ((int)tmp << 27) >> 27;
+ tmp = (UInt)stemp;
+ tmp |= (tmp << 32);
+ assign(t1, getWReg(ws));
+ assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+ assign(t3, binop(Iop_CmpGT32Sx4, mkexpr(t2), mkexpr(t1)));
+ putWReg(wd, mkexpr(t3));
break;
}
- case 0x11: { /* MTHI */
- DIP("mthi ac%u r%u", ac, rs);
- t1 = newTemp(Ity_I32);
- assign(t1, unop(Iop_64to32, getAcc(ac)));
- putAcc(ac, binop(Iop_32HLto64, getIReg(rs), mkexpr(t1)));
+ case 0x03: { /* CLTI_S.D */
+ DIP("CLTI_S.D w%d, w%d, %d", wd, ws, i5);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ Long stemp = ((Long)tmp << 59) >> 59;
+ tmp = stemp;
+ assign(t1, getWReg(ws));
+ assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+ assign(t3, binop(Iop_CmpGT64Sx2, mkexpr(t2), mkexpr(t1)));
+ putWReg(wd, mkexpr(t3));
break;
}
- case 0x12: { /* MFLO */
- DIP("mflo ac%u r%u", ac_mfhilo, rd);
- putIReg(rd, unop(Iop_64to32, getAcc(ac_mfhilo)));
+ default:
+ return -1;
+ }
+
+ break;
+ }
+
+ case 0x03: { /* CLTI_U.df */
+ ULong tmp = i5;
+
+ switch (df) {
+ case 0x00: { /* CLTI_U.B */
+ DIP("CLTI_U.B w%d, w%d, %d", wd, ws, i5);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
+ (tmp << 32) | (tmp << 24) | (tmp << 16) |
+ (tmp << 8);
+ assign(t1, getWReg(ws));
+ assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+ assign(t3, binop(Iop_CmpGT8Ux16, mkexpr(t2), mkexpr(t1)));
+ putWReg(wd, mkexpr(t3));
break;
}
- case 0x13: { /* MTLO */
- DIP("mtlo ac%u r%u", ac, rs);
- t1 = newTemp(Ity_I32);
- assign(t1, unop(Iop_64HIto32, getAcc(ac)));
- putAcc(ac, binop(Iop_32HLto64, mkexpr(t1), getIReg(rs)));
+ case 0x01: { /* CLTI_U.H */
+ DIP("CLTI_U.H w%d, w%d, %d", wd, ws, i5);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
+ assign(t1, getWReg(ws));
+ assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+ assign(t3, binop(Iop_CmpGT16Ux8, mkexpr(t2), mkexpr(t1)));
+ putWReg(wd, mkexpr(t3));
break;
}
- case 0x18: { /* MULT */
- DIP("mult ac%u r%u, r%u", ac, rs, rt);
- t1 = newTemp(Ity_I64);
- assign(t1, binop(Iop_MullS32, mkNarrowTo32(Ity_I32, getIReg(rs)),
- mkNarrowTo32(Ity_I32, getIReg(rt))));
- putAcc(ac, mkexpr(t1));
+ case 0x02: { /* CLTI_U.W */
+ DIP("CLTI_U.W w%d, w%d, %d", wd, ws, i5);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ tmp |= (tmp << 32);
+ assign(t1, getWReg(ws));
+ assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+ assign(t3, binop(Iop_CmpGT32Ux4, mkexpr(t2), mkexpr(t1)));
+ putWReg(wd, mkexpr(t3));
break;
}
- case 0x19: { /* MULTU */
- DIP("multu ac%u r%u, r%u", ac, rs, rt);
- t1 = newTemp(Ity_I64);
- assign(t1, binop(Iop_MullU32, mkNarrowTo32(Ity_I32, getIReg(rs)),
- mkNarrowTo32(Ity_I32,
- getIReg(rt))));
- putAcc(ac, mkexpr(t1));
- break;
+ case 0x03: { /* CLTI_U.D */
+ DIP("CLTI_U.D w%d, w%d, %d", wd, ws, i5);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+ assign(t3, binop(Iop_CmpGT64Ux2, mkexpr(t2), mkexpr(t1)));
+ putWReg(wd, mkexpr(t3));
+ break;
}
}
+
break;
}
- case 0x1C: { /* Special2 */
- switch (function) {
- case 0x00: { /* MADD */
- DIP("madd ac%u, r%u, r%u", ac, rs, rt);
- t1 = newTemp(Ity_I64);
- t2 = newTemp(Ity_I64);
- t3 = newTemp(Ity_I64);
- assign(t1, getAcc(ac));
- assign(t2, binop(Iop_MullS32, getIReg(rs), getIReg(rt)));
- assign(t3, binop(Iop_Add64, mkexpr(t1), mkexpr(t2)));
+ case 0x04: { /* CLEI_S.df */
+ ULong tmp = i5;
- putAcc(ac, mkexpr(t3));
+ switch (df) {
+ case 0x00: { /* CLEI_S.B */
+ DIP("CLEI_S.B w%d, w%d, %d", wd, ws, i5);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ char stemp = ((int)tmp << 27) >> 27;
+ tmp = (UChar)stemp;
+ tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
+ (tmp << 32) | (tmp << 24) | (tmp << 16) |
+ (tmp << 8);
+ assign(t1, getWReg(ws));
+ assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+ assign(t3, binop(Iop_OrV128, binop(Iop_CmpGT8Sx16,
+ mkexpr(t2), mkexpr(t1)),
+ binop(Iop_CmpEQ8x16,
+ mkexpr(t1), mkexpr(t2))));
+ putWReg(wd, mkexpr(t3));
break;
}
- case 0x01: { /* MADDU */
- DIP("maddu ac%u r%u, r%u", ac, rs, rt);
- t1 = newTemp(Ity_I64);
- t2 = newTemp(Ity_I64);
- t3 = newTemp(Ity_I64);
- assign(t1, getAcc(ac));
- assign(t2, binop(Iop_MullU32, getIReg(rs), getIReg(rt)));
- assign(t3, binop(Iop_Add64, mkexpr(t2), mkexpr(t1)));
-
- putAcc(ac, mkexpr(t3));
+ case 0x01: { /* CLEI_S.H */
+ DIP("CLEI_S.H w%d, w%d, %d", wd, ws, i5);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ short stemp = ((int)tmp << 27) >> 27;
+ tmp = (UShort)stemp;
+ tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
+ assign(t1, getWReg(ws));
+ assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+ assign(t3, binop(Iop_OrV128, binop(Iop_CmpGT16Sx8,
+ mkexpr(t2), mkexpr(t1)),
+ binop(Iop_CmpEQ16x8,
+ mkexpr(t1), mkexpr(t2))));
+ putWReg(wd, mkexpr(t3));
break;
}
- case 0x04: { /* MSUB */
- DIP("msub ac%u r%u, r%u", ac, rs, rt);
- t1 = newTemp(Ity_I64);
- t2 = newTemp(Ity_I64);
- t3 = newTemp(Ity_I64);
- assign(t1, getAcc(ac));
- assign(t2, binop(Iop_MullS32, getIReg(rs), getIReg(rt)));
- assign(t3, binop(Iop_Sub64, mkexpr(t1), mkexpr(t2)));
-
- putAcc(ac, mkexpr(t3));
+ case 0x02: { /* CLEI_S.W */
+ DIP("CLEI_S.W w%d, w%d, %d", wd, ws, i5);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ int stemp = ((int)tmp << 27) >> 27;
+ tmp = (UInt)stemp;
+ tmp |= (tmp << 32);
+ assign(t1, getWReg(ws));
+ assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+ assign(t3, binop(Iop_OrV128,
+ binop(Iop_CmpGT32Sx4,
+ mkexpr(t2), mkexpr(t1)),
+ binop(Iop_CmpEQ32x4,
+ mkexpr(t1), mkexpr(t2))));
+ putWReg(wd, mkexpr(t3));
break;
}
- case 0x05: { /* MSUBU */
- DIP("msubu ac%u r%u, r%u", ac, rs, rt);
- t1 = newTemp(Ity_I64);
- t2 = newTemp(Ity_I64);
- t3 = newTemp(Ity_I64);
- assign(t1, getAcc(ac));
- assign(t2, binop(Iop_MullU32, getIReg(rs), getIReg(rt)));
- assign(t3, binop(Iop_Sub64, mkexpr(t1), mkexpr(t2)));
-
- putAcc(ac, mkexpr(t3));
+ case 0x03: { /* CLEI_S.D */
+ DIP("CLEI_S.D w%d, w%d, %d", wd, ws, i5);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ Long stemp = ((Long)tmp << 59) >> 59;
+ tmp = stemp;
+ assign(t1, getWReg(ws));
+ assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+ assign(t3, binop(Iop_OrV128,
+ binop(Iop_CmpGT64Sx2,
+ mkexpr(t2), mkexpr(t1)),
+ binop(Iop_CmpEQ64x2,
+ mkexpr(t1), mkexpr(t2))));
+ putWReg(wd, mkexpr(t3));
break;
}
+
+ default:
+ return -1;
}
+
break;
}
- case 0x1F: { /* Special3 */
- switch (function) {
- case 0x12: { /* ABSQ_S.PH */
- switch (sa) {
- case 0x1: { /* ABSQ_S.QB */
- DIP("absq_s.qb r%u, r%u", rd, rt);
- vassert(!mode64);
- t0 = newTemp(Ity_I8);
- t1 = newTemp(Ity_I1);
- t2 = newTemp(Ity_I1);
- t3 = newTemp(Ity_I8);
- t4 = newTemp(Ity_I8);
- t5 = newTemp(Ity_I1);
- t6 = newTemp(Ity_I1);
- t7 = newTemp(Ity_I8);
- t8 = newTemp(Ity_I8);
- t9 = newTemp(Ity_I1);
- t10 = newTemp(Ity_I1);
- t11 = newTemp(Ity_I8);
- t12 = newTemp(Ity_I8);
- t13 = newTemp(Ity_I1);
- t14 = newTemp(Ity_I1);
- t15 = newTemp(Ity_I8);
- t16 = newTemp(Ity_I32);
- t17 = newTemp(Ity_I32);
-
- /* Absolute value of the rightmost byte (bits 7-0). */
- /* t0 - rightmost byte. */
- assign(t0, unop(Iop_16to8, unop(Iop_32to16, getIReg(rt))));
- /* t1 holds 1 if t0 is equal to 0x80, or 0 otherwise. */
- assign(t1, binop(Iop_CmpEQ32,
- unop(Iop_8Uto32, mkexpr(t0)),
- mkU32(0x00000080)));
- /* t2 holds 1 if value in t0 is negative, 0 otherwise. */
- assign(t2, unop(Iop_32to1,
- binop(Iop_Shr32,
- binop(Iop_And32,
- getIReg(rt),
- mkU32(0x00000080)),
- mkU8(0x7))));
- /* t3 holds abs(t0). */
- assign(t3, IRExpr_ITE(mkexpr(t1),
- mkU8(0x7F),
- IRExpr_ITE(mkexpr(t2),
- binop(Iop_Add8,
- unop(Iop_Not8,
- mkexpr(t0)),
- mkU8(0x1)),
- mkexpr(t0))));
-
- /* Absolute value of bits 15-8. */
- /* t4 - input byte. */
- assign(t4,
- unop(Iop_16HIto8, unop(Iop_32to16, getIReg(rt))));
- /* t5 holds 1 if t4 is equal to 0x80, or 0 otherwise. */
- assign(t5, binop(Iop_CmpEQ32,
- unop(Iop_8Uto32, mkexpr(t4)),
- mkU32(0x00000080)));
- /* t6 holds 1 if value in t4 is negative, 0 otherwise. */
- assign(t6, unop(Iop_32to1,
- binop(Iop_Shr32,
- binop(Iop_And32,
- getIReg(rt),
- mkU32(0x00008000)),
- mkU8(15))));
- /* t3 holds abs(t4). */
- assign(t7, IRExpr_ITE(mkexpr(t5),
- mkU8(0x7F),
- IRExpr_ITE(mkexpr(t6),
- binop(Iop_Add8,
- unop(Iop_Not8,
- mkexpr(t4)),
- mkU8(0x1)),
- mkexpr(t4))));
-
- /* Absolute value of bits 23-15. */
- /* t8 - input byte. */
- assign(t8,
- unop(Iop_16to8, unop(Iop_32HIto16, getIReg(rt))));
- /* t9 holds 1 if t8 is equal to 0x80, or 0 otherwise. */
- assign(t9, binop(Iop_CmpEQ32,
- unop(Iop_8Uto32, mkexpr(t8)),
- mkU32(0x00000080)));
- /* t6 holds 1 if value in t8 is negative, 0 otherwise. */
- assign(t10, unop(Iop_32to1,
- binop(Iop_Shr32,
- binop(Iop_And32,
- getIReg(rt),
- mkU32(0x00800000)),
- mkU8(23))));
- /* t3 holds abs(t8). */
- assign(t11, IRExpr_ITE(mkexpr(t9),
- mkU8(0x7F),
- IRExpr_ITE(mkexpr(t10),
- binop(Iop_Add8,
- unop(Iop_Not8,
- mkexpr(t8)),
- mkU8(0x1)),
- mkexpr(t8))));
-
- /* Absolute value of bits 31-24. */
- /* t12 - input byte. */
- assign(t12,
- unop(Iop_16HIto8, unop(Iop_32HIto16, getIReg(rt))));
- /* t13 holds 1 if t12 is equal to 0x80, or 0 otherwise. */
- assign(t13, binop(Iop_CmpEQ32,
- unop(Iop_8Uto32, mkexpr(t12)),
- mkU32(0x00000080)));
- /* t14 holds 1 if value in t12 is negative, 0 otherwise. */
- assign(t14, unop(Iop_32to1,
- binop(Iop_Shr32,
- binop(Iop_And32,
- getIReg(rt),
- mkU32(0x80000000)),
- mkU8(31))));
- /* t15 holds abs(t12). */
- assign(t15, IRExpr_ITE(mkexpr(t13),
- mkU8(0x7F),
- IRExpr_ITE(mkexpr(t14),
- binop(Iop_Add8,
- unop(Iop_Not8,
- mkexpr(t12)),
- mkU8(0x1)),
- mkexpr(t12))));
-
- /* t16 holds !0 if any of input bytes is 0x80 or 0
- otherwise. */
- assign(t16,
- binop(Iop_Or32,
- binop(Iop_Or32,
- binop(Iop_Or32,
- unop(Iop_1Sto32, mkexpr(t13)),
- unop(Iop_1Sto32, mkexpr(t9))),
- unop(Iop_1Sto32, mkexpr(t5))),
- unop(Iop_1Sto32, mkexpr(t1))));
-
- putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
- mkexpr(t16),
- mkU32(0x0)),
- getDSPControl(),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x00100000))));
-
- /* t17 = t15|t11|t7|t3 */
- assign(t17,
- binop(Iop_16HLto32,
- binop(Iop_8HLto16, mkexpr(t15), mkexpr(t11)),
- binop(Iop_8HLto16, mkexpr(t7), mkexpr(t3))));
-
- putIReg(rd, mkexpr(t17));
- break;
- }
- case 0x2: { /* REPL.QB */
- DIP("repl.qb r%u, %u", rd, dsp_imm);
- vassert(!mode64);
- putIReg(rd, mkU32((dsp_imm << 24) | (dsp_imm << 16) |
- (dsp_imm << 8) | (dsp_imm)));
- break;
- }
- case 0x3: { /* REPLV.QB */
- DIP("replv.qb r%u, r%u", rd, rt);
- vassert(!mode64);
- t0 = newTemp(Ity_I8);
-
- assign(t0, unop(Iop_32to8,
- binop(Iop_And32, getIReg(rt), mkU32(0xff))));
- putIReg(rd,
- binop(Iop_16HLto32,
- binop(Iop_8HLto16, mkexpr(t0), mkexpr(t0)),
- binop(Iop_8HLto16, mkexpr(t0), mkexpr(t0))));
- break;
- }
- case 0x4: { /* PRECEQU.PH.QBL */
- DIP("precequ.ph.qbl r%u, r%u", rd, rt);
- vassert(!mode64);
-
- putIReg(rd, binop(Iop_Or32,
- binop(Iop_Shr32,
- binop(Iop_And32,
- getIReg(rt),
- mkU32(0xff000000)),
- mkU8(1)),
- binop(Iop_Shr32,
- binop(Iop_And32,
- getIReg(rt),
- mkU32(0x00ff0000)),
- mkU8(9))));
- break;
- }
- case 0x5: { /* PRECEQU.PH.QBR */
- DIP("precequ.ph.qbr r%u, r%u", rd, rt);
- vassert(!mode64);
-
- putIReg(rd, binop(Iop_Or32,
- binop(Iop_Shl32,
- binop(Iop_And32,
- getIReg(rt),
- mkU32(0x0000ff00)),
- mkU8(15)),
- binop(Iop_Shl32,
- binop(Iop_And32,
- getIReg(rt),
- mkU32(0x000000ff)),
- mkU8(7))));
- break;
- }
- case 0x6: { /* PRECEQU.PH.QBLA */
- DIP("precequ.ph.qbla r%u, r%u", rd, rt);
- vassert(!mode64);
-
- putIReg(rd, binop(Iop_Or32,
- binop(Iop_Shr32,
- binop(Iop_And32,
- getIReg(rt),
- mkU32(0xff000000)),
- mkU8(1)),
- binop(Iop_Shr32,
- binop(Iop_And32,
- getIReg(rt),
- mkU32(0x0000ff00)),
- mkU8(1))));
- break;
- }
- case 0x7: { /* PRECEQU.PH.QBRA */
- DIP("precequ.ph.qbra r%u, r%u", rd, rt);
- vassert(!mode64);
-
- putIReg(rd, binop(Iop_Or32,
- binop(Iop_Shl32,
- binop(Iop_And32,
- getIReg(rt),
- mkU32(0x00ff0000)),
- mkU8(7)),
- binop(Iop_Shl32,
- binop(Iop_And32,
- getIReg(rt),
- mkU32(0x000000ff)),
- mkU8(7))));
- break;
- }
- case 0x9: { /* ABSQ_S.PH */
- DIP("absq_s.ph r%u, r%u", rd, rt);
- vassert(!mode64);
- t0 = newTemp(Ity_I16);
- t1 = newTemp(Ity_I1);
- t2 = newTemp(Ity_I1);
- t3 = newTemp(Ity_I16);
- t4 = newTemp(Ity_I16);
- t5 = newTemp(Ity_I1);
- t6 = newTemp(Ity_I1);
- t7 = newTemp(Ity_I16);
- t8 = newTemp(Ity_I32);
- t9 = newTemp(Ity_I32);
-
- /* t0 holds lower 16 bits of value in rt. */
- assign(t0, unop(Iop_32to16, getIReg(rt)));
- /* t1 holds 1 if t0 is equal to 0x8000. */
- assign(t1, binop(Iop_CmpEQ32,
- unop(Iop_16Uto32, mkexpr(t0)),
- mkU32(0x00008000)));
- /* t2 holds 1 if value in t0 is negative, 0 otherwise. */
- assign(t2, unop(Iop_32to1,
- binop(Iop_Shr32,
- binop(Iop_And32,
- getIReg(rt),
- mkU32(0x00008000)),
- mkU8(15))));
- /* t3 holds abs(t0). */
- assign(t3, IRExpr_ITE(mkexpr(t1),
- mkU16(0x7FFF),
- IRExpr_ITE(mkexpr(t2),
- binop(Iop_Add16,
- unop(Iop_Not16,
- mkexpr(t0)),
- mkU16(0x1)),
- mkexpr(t0))));
-
- /* t4 holds lower 16 bits of value in rt. */
- assign(t4, unop(Iop_32HIto16, getIReg(rt)));
- /* t5 holds 1 if t4 is equal to 0x8000. */
- assign(t5, binop(Iop_CmpEQ32,
- unop(Iop_16Uto32, mkexpr(t4)),
- mkU32(0x00008000)));
- /* t6 holds 1 if value in t4 is negative, 0 otherwise. */
- assign(t6, unop(Iop_32to1,
- binop(Iop_Shr32,
- binop(Iop_And32,
- getIReg(rt),
- mkU32(0x80000000)),
- mkU8(31))));
- /* t7 holds abs(t4). */
- assign(t7, IRExpr_ITE(mkexpr(t5),
- mkU16(0x7FFF),
- IRExpr_ITE(mkexpr(t6),
- binop(Iop_Add16,
- unop(Iop_Not16,
- mkexpr(t4)),
- mkU16(0x1)),
- mkexpr(t4))));
- /* If any of the two input halfwords is equal 0x8000,
- set bit 20 in DSPControl register. */
- assign(t8, binop(Iop_Or32,
- unop(Iop_1Sto32, mkexpr(t5)),
- unop(Iop_1Sto32, mkexpr(t1))));
-
- putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
- mkexpr(t8),
- mkU32(0x0)),
- getDSPControl(),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x00100000))));
-
- /* t9 = t7|t3 */
- assign(t9, binop(Iop_16HLto32, mkexpr(t7), mkexpr(t3)));
-
- putIReg(rd, mkexpr(t9));
- break;
- }
- case 0xA: { /* REPL.PH */
- DIP("repl.ph r%u, %u", rd, dsp_imm);
- vassert(!mode64);
- UShort immediate = extend_s_10to16(dsp_imm);
+ case 0x05: { /* CLEI_U.df */
+ ULong tmp = i5;
- putIReg(rd, mkU32(immediate << 16 | immediate));
- break;
- }
- case 0xB: { /* REPLV.PH */
- DIP("replv.ph r%u, r%u", rd, rt);
- vassert(!mode64);
+ switch (df) {
+ case 0x00: { /* CLEI_U.B */
+ DIP("CLEI_U.B w%d, w%d, %d", wd, ws, i5);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
+ (tmp << 32) | (tmp << 24) | (tmp << 16) |
+ (tmp << 8);
+ assign(t1, getWReg(ws));
+ assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+ assign(t3, binop(Iop_OrV128,
+ binop(Iop_CmpGT8Ux16,
+ mkexpr(t2), mkexpr(t1)),
+ binop(Iop_CmpEQ8x16,
+ mkexpr(t1), mkexpr(t2))));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- putIReg(rd, binop(Iop_16HLto32,
- unop(Iop_32to16, getIReg(rt)),
- unop(Iop_32to16, getIReg(rt))));
- break;
- }
- case 0xC: { /* PRECEQ.W.PHL */
- DIP("preceq.w.phl r%u, r%u", rd, rt);
- vassert(!mode64);
- putIReg(rd, binop(Iop_And32,
- getIReg(rt),
- mkU32(0xffff0000)));
- break;
- }
- case 0xD: { /* PRECEQ.W.PHR */
- DIP("preceq.w.phr r%u, r%u", rd, rt);
- vassert(!mode64);
- putIReg(rd, binop(Iop_16HLto32,
- unop(Iop_32to16, getIReg(rt)),
- mkU16(0x0)));
- break;
- }
- case 0x11: { /* ABSQ_S.W */
- DIP("absq_s.w r%u, r%u", rd, rt);
- vassert(!mode64);
- t0 = newTemp(Ity_I1);
- t1 = newTemp(Ity_I1);
- t2 = newTemp(Ity_I32);
-
- assign(t0,
- binop(Iop_CmpEQ32, getIReg(rt), mkU32(0x80000000)));
-
- putDSPControl(IRExpr_ITE(mkexpr(t0),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x00100000)),
- getDSPControl()));
-
- assign(t1, binop(Iop_CmpLT32S, getIReg(rt), mkU32(0x0)));
-
- assign(t2, IRExpr_ITE(mkexpr(t0),
- mkU32(0x7FFFFFFF),
- IRExpr_ITE(mkexpr(t1),
- binop(Iop_Add32,
- unop(Iop_Not32,
- getIReg(rt)),
- mkU32(0x1)),
- getIReg(rt))));
- putIReg(rd, mkexpr(t2));
- break;
- }
- case 0x1B: { /* BITREV */
- DIP("bitrev r%u, r%u", rd, rt);
- vassert(!mode64);
- /* 32bit reversal as seen on Bit Twiddling Hacks site
- http://graphics.stanford.edu/~seander/bithacks.html
- section ReverseParallel */
- t1 = newTemp(Ity_I32);
- t2 = newTemp(Ity_I32);
- t3 = newTemp(Ity_I32);
- t4 = newTemp(Ity_I32);
- t5 = newTemp(Ity_I32);
+ case 0x01: { /* CLEI_U.H */
+ DIP("CLEI_U.H w%d, w%d, %d", wd, ws, i5);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
+ assign(t1, getWReg(ws));
+ assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+ assign(t3, binop(Iop_OrV128,
+ binop(Iop_CmpGT16Ux8,
+ mkexpr(t2), mkexpr(t1)),
+ binop(Iop_CmpEQ16x8,
+ mkexpr(t1), mkexpr(t2))));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- assign(t1, binop(Iop_Or32,
- binop(Iop_Shr32,
- binop(Iop_And32,
- getIReg(rt),
- mkU32(0xaaaaaaaa)),
- mkU8(0x1)),
- binop(Iop_Shl32,
- binop(Iop_And32,
- getIReg(rt),
- mkU32(0x55555555)),
- mkU8(0x1))));
- assign(t2, binop(Iop_Or32,
- binop(Iop_Shr32,
- binop(Iop_And32,
- mkexpr(t1),
- mkU32(0xcccccccc)),
- mkU8(0x2)),
- binop(Iop_Shl32,
- binop(Iop_And32,
- mkexpr(t1),
- mkU32(0x33333333)),
- mkU8(0x2))));
- assign(t3, binop(Iop_Or32,
- binop(Iop_Shr32,
- binop(Iop_And32,
- mkexpr(t2),
- mkU32(0xf0f0f0f0)),
- mkU8(0x4)),
- binop(Iop_Shl32,
- binop(Iop_And32,
- mkexpr(t2),
- mkU32(0x0f0f0f0f)),
- mkU8(0x4))));
- assign(t4, binop(Iop_Or32,
- binop(Iop_Shr32,
- binop(Iop_And32,
- mkexpr(t3),
- mkU32(0xff00ff00)),
- mkU8(0x8)),
- binop(Iop_Shl32,
- binop(Iop_And32,
- mkexpr(t3),
- mkU32(0x00ff00ff)),
- mkU8(0x8))));
- assign(t5, binop(Iop_Or32,
- binop(Iop_Shr32,
- mkexpr(t4),
- mkU8(0x10)),
- binop(Iop_Shl32,
- mkexpr(t4),
- mkU8(0x10))));
- putIReg(rd, binop(Iop_Shr32,
- mkexpr(t5),
- mkU8(16)));
- break;
- }
- case 0x1C: { /* PRECEU.PH.QBL */
- DIP("preceu.ph.qbl r%u, r%u", rd, rt);
- vassert(!mode64);
-
- putIReg(rd, binop(Iop_Or32,
- binop(Iop_Shr32,
- binop(Iop_And32,
- getIReg(rt),
- mkU32(0xff000000)),
- mkU8(8)),
- binop(Iop_Shr32,
- binop(Iop_And32,
- getIReg(rt),
- mkU32(0x00ff0000)),
- mkU8(16))));
- break;
- }
- case 0x1E: { /* PRECEU.PH.QBLA */
- DIP("preceu.ph.qbla r%u, r%u", rd, rt);
- vassert(!mode64);
-
- putIReg(rd, binop(Iop_Or32,
- binop(Iop_Shr32,
- binop(Iop_And32,
- getIReg(rt),
- mkU32(0xff000000)),
- mkU8(8)),
- binop(Iop_Shr32,
- binop(Iop_And32,
- getIReg(rt),
- mkU32(0x0000ff00)),
- mkU8(8))));
- break;
- }
- case 0x1D: { /* PRECEU.PH.QBR */
- DIP("preceu.ph.qbr r%u, r%u", rd, rt);
- vassert(!mode64);
-
- putIReg(rd, binop(Iop_Or32,
- binop(Iop_Shl32,
- binop(Iop_And32,
- getIReg(rt),
- mkU32(0x0000ff00)),
- mkU8(8)),
- binop(Iop_And32,
- getIReg(rt),
- mkU32(0x000000ff))));
- break;
- }
- case 0x1F: { /* PRECEU.PH.QBRA */
- DIP("preceu.ph.qbra r%u, r%u", rd, rt);
- vassert(!mode64);
-
- putIReg(rd, binop(Iop_Or32,
- binop(Iop_And32,
- getIReg(rt),
- mkU32(0x00ff0000)),
- binop(Iop_And32,
- getIReg(rt),
- mkU32(0x000000ff))));
- break;
- }
- default:
- return -1;
- }
- break; /* end of ABSQ_S.PH */
- }
- case 0x38: { /* EXTR.W */
- switch(sa) {
- case 0x0: { /* EXTR.W */
- DIP("extr.w r%u, ac%u, %u", rt, ac, rs);
- vassert(!mode64);
- t0 = newTemp(Ity_I64);
- t1 = newTemp(Ity_I64);
- t2 = newTemp(Ity_I32);
- t3 = newTemp(Ity_I1);
- t4 = newTemp(Ity_I1);
- t5 = newTemp(Ity_I1);
- t6 = newTemp(Ity_I1);
- t7 = newTemp(Ity_I32);
- t8 = newTemp(Ity_I64);
- t9 = newTemp(Ity_I64);
- t10 = newTemp(Ity_I1);
- t11 = newTemp(Ity_I1);
- t12 = newTemp(Ity_I1);
- t13 = newTemp(Ity_I1);
- t14 = newTemp(Ity_I32);
-
- assign(t0, getAcc(ac));
- if (0 == rs) {
- assign(t1, mkexpr(t0));
- } else {
- assign(t1, binop(Iop_Sar64, mkexpr(t0), mkU8(rs)));
- }
- /* Check if bits 63..31 of the result in t1 aren't 0. */
- assign(t3, binop(Iop_CmpNE32,
- unop(Iop_64HIto32,
- mkexpr(t1)),
- mkU32(0)));
- assign(t4, binop(Iop_CmpNE32,
- binop(Iop_And32,
- unop(Iop_64to32,
- mkexpr(t1)),
- mkU32(0x80000000)),
- mkU32(0)));
- /* Check if bits 63..31 of the result in t1 aren't
- 0x1ffffffff. */
- assign(t5, binop(Iop_CmpNE32,
- unop(Iop_64HIto32,
- mkexpr(t1)),
- mkU32(0xffffffff)));
- assign(t6, binop(Iop_CmpNE32,
- binop(Iop_And32,
- unop(Iop_64to32,
- mkexpr(t1)),
- mkU32(0x80000000)),
- mkU32(0x80000000)));
- /* If bits 63..31 aren't 0 nor 0x1ffffffff, set DSP
- control register. */
- assign(t7, binop(Iop_And32,
- binop(Iop_Or32,
- unop(Iop_1Sto32, mkexpr(t3)),
- unop(Iop_1Sto32, mkexpr(t4))),
- binop(Iop_Or32,
- unop(Iop_1Sto32, mkexpr(t5)),
- unop(Iop_1Sto32, mkexpr(t6)))));
- putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
- mkexpr(t7),
- mkU32(0)),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x00800000)),
- getDSPControl()));
-
- /* If the last discarded bit is 1, there would be carry
- when rounding, otherwise there wouldn't. We use that
- fact and just add the value of the last discarded bit
- to the least sifgnificant bit of the shifted value
- from acc. */
- if (0 == rs) {
- assign(t8, mkU64(0x0ULL));
- } else {
- assign(t8, binop(Iop_And64,
- binop(Iop_Shr64,
- mkexpr(t0),
- mkU8(rs-1)),
- mkU64(0x1ULL)));
- }
- assign(t9, binop(Iop_Add64, mkexpr(t1), mkexpr(t8)));
+ case 0x02: { /* CLEI_U.W */
+ DIP("CLEI_U.W w%d, w%d, %d", wd, ws, i5);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ tmp |= (tmp << 32);
+ assign(t1, getWReg(ws));
+ assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+ assign(t3, binop(Iop_OrV128,
+ binop(Iop_CmpGT32Ux4,
+ mkexpr(t2), mkexpr(t1)),
+ binop(Iop_CmpEQ32x4,
+ mkexpr(t1), mkexpr(t2))));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- /* Repeat previous steps for the rounded value. */
- assign(t10, binop(Iop_CmpNE32,
- unop(Iop_64HIto32,
- mkexpr(t9)),
- mkU32(0)));
- assign(t11, binop(Iop_CmpNE32,
- binop(Iop_And32,
- unop(Iop_64to32,
- mkexpr(t9)),
- mkU32(0x80000000)),
- mkU32(0)));
+ case 0x03: { /* CLEI_U.D */
+ DIP("CLEI_U.D w%d, w%d, %d", wd, ws, i5);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+ assign(t3, binop(Iop_OrV128,
+ binop(Iop_CmpGT64Ux2,
+ mkexpr(t2), mkexpr(t1)),
+ binop(Iop_CmpEQ64x2,
+ mkexpr(t1), mkexpr(t2))));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
+ }
- assign(t12, binop(Iop_CmpNE32,
- unop(Iop_64HIto32,
- mkexpr(t9)),
- mkU32(0xffffffff)));
- assign(t13, binop(Iop_CmpNE32,
- binop(Iop_And32,
- unop(Iop_64to32,
- mkexpr(t9)),
- mkU32(0x80000000)),
- mkU32(0x80000000)));
-
- assign(t14, binop(Iop_And32,
- binop(Iop_Or32,
- unop(Iop_1Sto32, mkexpr(t10)),
- unop(Iop_1Sto32, mkexpr(t11))),
- binop(Iop_Or32,
- unop(Iop_1Sto32, mkexpr(t12)),
- unop(Iop_1Sto32, mkexpr(t13)))));
- putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
- mkexpr(t14),
- mkU32(0)),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x00800000)),
- getDSPControl()));
- if (0 == rs) {
- putIReg(rt, unop(Iop_64to32, mkexpr(t0)));
- } else {
- putIReg(rt, unop(Iop_64to32, mkexpr(t1)));
- }
- break;
- }
- case 0x1: { /* EXTRV.W */
- DIP("extrv.w r%u, ac%u, r%u", rt, ac, rs);
- vassert(!mode64);
- t0 = newTemp(Ity_I64);
- t1 = newTemp(Ity_I64);
- t2 = newTemp(Ity_I32);
- t3 = newTemp(Ity_I1);
- t4 = newTemp(Ity_I1);
- t5 = newTemp(Ity_I1);
- t6 = newTemp(Ity_I1);
- t7 = newTemp(Ity_I32);
- t8 = newTemp(Ity_I64);
- t9 = newTemp(Ity_I64);
- t10 = newTemp(Ity_I1);
- t11 = newTemp(Ity_I1);
- t12 = newTemp(Ity_I1);
- t13 = newTemp(Ity_I1);
- t14 = newTemp(Ity_I32);
- t15 = newTemp(Ity_I8);
-
- assign(t15, unop(Iop_32to8,
- binop(Iop_And32,
- getIReg(rs),
- mkU32(0x1f))));
- assign(t0, getAcc(ac));
- assign(t1, binop(Iop_Sar64, mkexpr(t0), mkexpr(t15)));
- putIReg(rt, IRExpr_ITE(binop(Iop_CmpEQ32,
- unop(Iop_8Uto32,
- mkexpr(t15)),
- mkU32(0)),
- unop(Iop_64to32, mkexpr(t0)),
- unop(Iop_64to32, mkexpr(t1))));
-
- /* Check if bits 63..31 of the result in t1 aren't 0. */
- assign(t3, binop(Iop_CmpNE32,
- unop(Iop_64HIto32,
- mkexpr(t1)),
- mkU32(0)));
- assign(t4, binop(Iop_CmpNE32,
- binop(Iop_And32,
- unop(Iop_64to32,
- mkexpr(t1)),
- mkU32(0x80000000)),
- mkU32(0)));
- /* Check if bits 63..31 of the result in t1 aren't
- 0x1ffffffff. */
- assign(t5, binop(Iop_CmpNE32,
- unop(Iop_64HIto32,
- mkexpr(t1)),
- mkU32(0xffffffff)));
- assign(t6, binop(Iop_CmpNE32,
- binop(Iop_And32,
- unop(Iop_64to32,
- mkexpr(t1)),
- mkU32(0x80000000)),
- mkU32(0x80000000)));
- /* If bits 63..31 aren't 0 nor 0x1ffffffff, set DSP
- control register. */
- assign(t7, binop(Iop_And32,
- binop(Iop_Or32,
- unop(Iop_1Sto32, mkexpr(t3)),
- unop(Iop_1Sto32, mkexpr(t4))),
- binop(Iop_Or32,
- unop(Iop_1Sto32, mkexpr(t5)),
- unop(Iop_1Sto32, mkexpr(t6)))));
- putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
- mkexpr(t7),
- mkU32(0)),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x00800000)),
- getDSPControl()));
-
- /* If the last discarded bit is 1, there would be carry
- when rounding, otherwise there wouldn't. We use that
- fact and just add the value of the last discarded bit
- to the least sifgnificant bit of the shifted value
- from acc. */
- assign(t8,
- IRExpr_ITE(binop(Iop_CmpEQ32,
- unop(Iop_8Uto32,
- mkexpr(t15)),
- mkU32(0)),
- mkU64(0x0ULL),
- binop(Iop_And64,
- binop(Iop_Shr64,
- mkexpr(t0),
- unop(Iop_32to8,
- binop(Iop_Sub32,
- unop(Iop_8Uto32,
- mkexpr(t15)),
- mkU32(1)))),
- mkU64(0x1ULL))));
-
- assign(t9, binop(Iop_Add64, mkexpr(t1), mkexpr(t8)));
-
- /* Repeat previous steps for the rounded value. */
- assign(t10, binop(Iop_CmpNE32,
- unop(Iop_64HIto32,
- mkexpr(t9)),
- mkU32(0)));
- assign(t11, binop(Iop_CmpNE32,
- binop(Iop_And32,
- unop(Iop_64to32,
- mkexpr(t9)),
- mkU32(0x80000000)),
- mkU32(0)));
+ break;
+ }
- assign(t12, binop(Iop_CmpNE32,
- unop(Iop_64HIto32,
- mkexpr(t9)),
- mkU32(0xffffffff)));
- assign(t13, binop(Iop_CmpNE32,
- binop(Iop_And32,
- unop(Iop_64to32,
- mkexpr(t9)),
- mkU32(0x80000000)),
- mkU32(0x80000000)));
-
- assign(t14, binop(Iop_And32,
- binop(Iop_Or32,
- unop(Iop_1Sto32, mkexpr(t10)),
- unop(Iop_1Sto32, mkexpr(t11))),
- binop(Iop_Or32,
- unop(Iop_1Sto32, mkexpr(t12)),
- unop(Iop_1Sto32, mkexpr(t13)))));
- putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
- mkexpr(t14),
- mkU32(0)),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x00800000)),
- getDSPControl()));
- break;
- }
- case 0x2: { /* EXTP */
- DIP("extp r%u, ac%u, %u", rt, ac, rs);
- vassert(!mode64);
- t0 = newTemp(Ity_I64);
- t1 = newTemp(Ity_I32);
- t2 = newTemp(Ity_I1);
- t3 = newTemp(Ity_I1);
- t4 = newTemp(Ity_I8);
- t5 = newTemp(Ity_I64);
- t6 = newTemp(Ity_I64);
- t7 = newTemp(Ity_I32);
-
- assign(t0, getAcc(ac));
- /* Extract pos field of DSPControl register. */
- assign(t1, binop(Iop_And32, getDSPControl(), mkU32(0x3f)));
-
- /* Check if (pos - size) >= 0 [size <= pos]
- if (pos < size)
- put 1 to EFI field of DSPControl register
- else
- extract bits from acc and put 0 to EFI field of
- DSPCtrl */
- assign(t2, binop(Iop_CmpLT32U, mkexpr(t1), mkU32(rs)));
-
- putDSPControl(IRExpr_ITE(mkexpr(t2),
- binop(Iop_Or32,
- binop(Iop_And32,
- getDSPControl(),
- mkU32(0xffffbfff)),
- mkU32(0x4000)),
- binop(Iop_And32,
- getDSPControl(),
- mkU32(0xffffbfff))));
-
- /* If pos <= 31, shift right the value from the acc
- (pos-size) times and take (size+1) bits from the least
- significant positions. Otherwise, shift left the value
- (63-pos) times, take (size+1) bits from the most
- significant positions and shift right (31-size) times.*/
- assign(t3, binop(Iop_CmpLE32U, mkexpr(t1), mkU32(31)));
-
- assign(t4,
- IRExpr_ITE(mkexpr(t3),
- unop(Iop_32to8,
- binop(Iop_Sub32,
- mkexpr(t1), mkU32(rs))),
- unop(Iop_32to8,
- binop(Iop_Sub32,
- mkU32(63), mkexpr(t1)))));
-
- assign(t5, IRExpr_ITE(mkexpr(t3),
- binop(Iop_Shr64,
- mkexpr(t0), mkexpr(t4)),
- binop(Iop_Shl64,
- mkexpr(t0), mkexpr(t4))));
-
- /* t6 holds a mask for bit extraction */
- assign(t6,
- IRExpr_ITE(mkexpr(t3),
- unop(Iop_Not64,
- binop(Iop_Shl64,
- mkU64(0xffffffffffffffffULL),
- mkU8(rs+1))),
- unop(Iop_Not64,
- binop(Iop_Shr64,
- mkU64(0xffffffffffffffffULL),
- mkU8(rs+1)))));
-
- assign(t7, IRExpr_ITE(mkexpr(t3),
- unop(Iop_64to32,
- binop(Iop_And64,
- mkexpr(t5),
- mkexpr(t6))),
- binop(Iop_Shr32,
- unop(Iop_64HIto32,
- binop(Iop_And64,
- mkexpr(t5),
- mkexpr(t6))),
- mkU8(31-rs))));
+ case 0x06: { /* LDI.df */
+ ULong tmp;
+ UShort s10;
+ s10 = (cins & 0x001FF800) >> 11;
- putIReg(rt, mkexpr(t7));
- break;
- }
- case 0x3: { /* EXTPV */
- DIP("extpv r%u, ac%u, r%u", rt, ac, rs);
- vassert(!mode64);
- t0 = newTemp(Ity_I64);
- t1 = newTemp(Ity_I32);
- t2 = newTemp(Ity_I1);
- t3 = newTemp(Ity_I1);
- t4 = newTemp(Ity_I8);
- t5 = newTemp(Ity_I64);
- t6 = newTemp(Ity_I64);
- t7 = newTemp(Ity_I32);
- t8 = newTemp(Ity_I32);
-
- assign(t8, binop(Iop_And32, getIReg(rs), mkU32(0x1f)));
- assign(t0, getAcc(ac));
- /* Extract pos field of DSPControl register. */
- assign(t1, binop(Iop_And32, getDSPControl(), mkU32(0x3f)));
-
- /* Check if (pos - size) >= 0 [size <= pos]
- if (pos < size)
- put 1 to EFI field of DSPControl register
- else
- extract bits from acc and put 0 to EFI field of
- DSPCtrl */
- assign(t2, binop(Iop_CmpLT32U, mkexpr(t1), mkexpr(t8)));
-
- putDSPControl(IRExpr_ITE(mkexpr(t2),
- binop(Iop_Or32,
- binop(Iop_And32,
- getDSPControl(),
- mkU32(0xffffbfff)),
- mkU32(0x4000)),
- binop(Iop_And32,
- getDSPControl(),
- mkU32(0xffffbfff))));
-
- /* If pos <= 31, shift right the value from the acc
- (pos-size) times and take (size+1) bits from the least
- significant positions. Otherwise, shift left the value
- (63-pos) times, take (size+1) bits from the most
- significant positions and shift right (31-size)
- times. */
- assign(t3, binop(Iop_CmpLE32U, mkexpr(t1), mkU32(31)));
-
- assign(t4,
- IRExpr_ITE(mkexpr(t3),
- unop(Iop_32to8,
- binop(Iop_Sub32,
- mkexpr(t1), mkexpr(t8))),
- unop(Iop_32to8,
- binop(Iop_Sub32,
- mkU32(63), mkexpr(t1)))));
-
- assign(t5, IRExpr_ITE(mkexpr(t3),
- binop(Iop_Shr64,
- mkexpr(t0), mkexpr(t4)),
- binop(Iop_Shl64,
- mkexpr(t0), mkexpr(t4))));
-
- /* t6 holds a mask for bit extraction. */
- assign(t6,
- IRExpr_ITE(mkexpr(t3),
- unop(Iop_Not64,
- binop(Iop_Shl64,
- mkU64(0xffffffffffffffffULL),
- unop(Iop_32to8,
- binop(Iop_Add32,
- mkexpr(t8),
- mkU32(1))))),
- unop(Iop_Not64,
- binop(Iop_Shr64,
- mkU64(0xffffffffffffffffULL),
- unop(Iop_32to8,
- binop(Iop_Add32,
- mkexpr(t8),
- mkU32(1)))))));
-
- assign(t7, IRExpr_ITE(mkexpr(t3),
- unop(Iop_64to32,
- binop(Iop_And64,
- mkexpr(t5),
- mkexpr(t6))),
- binop(Iop_Shr32,
- unop(Iop_64HIto32,
- binop(Iop_And64,
- mkexpr(t5),
- mkexpr(t6))),
- unop(Iop_32to8,
- binop(Iop_Sub32,
- mkU32(31),
- mkexpr(t8))))));
+ switch (df) {
+ case 0x00: /* LDI.B */
+ DIP("LDI.B w%d, %d", wd, s10);
+ tmp = s10 & 0xFFl;
+ tmp = tmp | (tmp << 8) | (tmp << 16) | (tmp << 24)
+ | (tmp << 32) | (tmp << 40) | (tmp << 48) |
+ (tmp << 56);
+ break;
- putIReg(rt, mkexpr(t7));
- break;
- }
- case 0x4: { /* EXTR_R.W */
- DIP("extr_r.w r%u, ac%u, %u", rt, ac, rs);
- vassert(!mode64);
- t0 = newTemp(Ity_I64);
- t1 = newTemp(Ity_I64);
- t2 = newTemp(Ity_I32);
- t3 = newTemp(Ity_I1);
- t4 = newTemp(Ity_I1);
- t5 = newTemp(Ity_I1);
- t6 = newTemp(Ity_I1);
- t7 = newTemp(Ity_I32);
- t8 = newTemp(Ity_I64);
- t9 = newTemp(Ity_I64);
- t10 = newTemp(Ity_I1);
- t11 = newTemp(Ity_I1);
- t12 = newTemp(Ity_I1);
- t13 = newTemp(Ity_I1);
- t14 = newTemp(Ity_I32);
- t15 = newTemp(Ity_I64);
- t16 = newTemp(Ity_I1);
-
- assign(t0, getAcc(ac));
- assign(t16, binop(Iop_CmpEQ32,
- mkU32(rs),
- mkU32(0)));
- assign(t1, IRExpr_ITE(mkexpr(t16),
- mkexpr(t0),
- binop(Iop_Sar64,
- mkexpr(t0),
- mkU8(rs))));
- /* If the last discarded bit is 1, there would be carry
- when rounding, otherwise there wouldn't. We use that
- fact and just add the value of the last discarded bit
- to the least significant bit of the shifted value
- from acc. */
- assign(t15, binop(Iop_Shr64,
- mkexpr(t0),
- unop(Iop_32to8,
- binop(Iop_Sub32,
- binop(Iop_And32,
- mkU32(rs),
- mkU32(0x1f)),
- mkU32(1)))));
-
- assign(t8,
- IRExpr_ITE(mkexpr(t16),
- mkU64(0x0ULL),
- binop(Iop_And64,
- mkexpr(t15),
- mkU64(0x0000000000000001ULL))));
- assign(t9, binop(Iop_Add64, mkexpr(t1), mkexpr(t8)));
- putIReg(rt, unop(Iop_64to32, mkexpr(t9)));
-
- /* Check if bits 63..31 of the result in t1 aren't 0. */
- assign(t3, binop(Iop_CmpNE32,
- unop(Iop_64HIto32,
- mkexpr(t1)),
- mkU32(0)));
- assign(t4, binop(Iop_CmpNE32,
- binop(Iop_And32,
- unop(Iop_64to32,
- mkexpr(t1)),
- mkU32(0x80000000)),
- mkU32(0)));
+ case 0x01: /* LDI.H */
+ DIP("LDI.H w%d, %d", wd, s10);
+ tmp = extend_s_10to16(s10);
+ tmp = tmp | (tmp << 16) | (tmp << 32) | (tmp << 48);
+ break;
- /* Check if bits 63..31 of the result in t1 aren't
- 0x1ffffffff. */
- assign(t5, binop(Iop_CmpNE32,
- unop(Iop_64HIto32,
- mkexpr(t1)),
- mkU32(0xffffffff)));
- assign(t6, binop(Iop_CmpNE32,
- binop(Iop_And32,
- unop(Iop_64to32,
- mkexpr(t1)),
- mkU32(0x80000000)),
- mkU32(0x80000000)));
- /* If bits 63..31 aren't 0 nor 0x1ffffffff, set DSP
- control register. */
- assign(t7, binop(Iop_And32,
- binop(Iop_Or32,
- unop(Iop_1Sto32, mkexpr(t3)),
- unop(Iop_1Sto32, mkexpr(t4))),
- binop(Iop_Or32,
- unop(Iop_1Sto32, mkexpr(t5)),
- unop(Iop_1Sto32, mkexpr(t6)))));
- putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
- mkexpr(t7),
- mkU32(0)),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x00800000)),
- getDSPControl()));
-
- /* Repeat previous steps for the rounded value. */
- assign(t10, binop(Iop_CmpNE32,
- unop(Iop_64HIto32,
- mkexpr(t9)),
- mkU32(0)));
- assign(t11, binop(Iop_CmpNE32,
- binop(Iop_And32,
- unop(Iop_64to32,
- mkexpr(t9)),
- mkU32(0x80000000)),
- mkU32(0)));
+ case 0x02: /* LDI.W */
+ DIP("LDI.W w%d, %d", wd, s10);
+ tmp = extend_s_10to32(s10);
+ tmp = tmp | (tmp << 32);
+ break;
- assign(t12, binop(Iop_CmpNE32,
- unop(Iop_64HIto32,
- mkexpr(t9)),
- mkU32(0xffffffff)));
- assign(t13, binop(Iop_CmpNE32,
- binop(Iop_And32,
- unop(Iop_64to32,
- mkexpr(t9)),
- mkU32(0x80000000)),
- mkU32(0x80000000)));
-
- assign(t14, binop(Iop_And32,
- binop(Iop_Or32,
- unop(Iop_1Sto32, mkexpr(t10)),
- unop(Iop_1Sto32, mkexpr(t11))),
- binop(Iop_Or32,
- unop(Iop_1Sto32, mkexpr(t12)),
- unop(Iop_1Sto32, mkexpr(t13)))));
- putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
- mkexpr(t14),
- mkU32(0)),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x00800000)),
- getDSPControl()));
- break;
- }
- case 0x5: { /* EXTRV_R.W */
- DIP("extrv_r.w r%u, ac%u, r%u", rt, ac, rs);
- vassert(!mode64);
- t0 = newTemp(Ity_I64);
- t1 = newTemp(Ity_I64);
- t2 = newTemp(Ity_I32);
- t3 = newTemp(Ity_I1);
- t4 = newTemp(Ity_I1);
- t5 = newTemp(Ity_I1);
- t6 = newTemp(Ity_I1);
- t7 = newTemp(Ity_I32);
- t8 = newTemp(Ity_I64);
- t9 = newTemp(Ity_I64);
- t10 = newTemp(Ity_I1);
- t11 = newTemp(Ity_I1);
- t12 = newTemp(Ity_I1);
- t13 = newTemp(Ity_I1);
- t14 = newTemp(Ity_I32);
- t15 = newTemp(Ity_I8);
-
- assign(t15, unop(Iop_32to8,
- binop(Iop_And32,
- getIReg(rs),
- mkU32(0x1f))));
- assign(t0, getAcc(ac));
- assign(t1, binop(Iop_Sar64, mkexpr(t0), mkexpr(t15)));
-
- /* Check if bits 63..31 of the result in t1 aren't 0. */
- assign(t3, binop(Iop_CmpNE32,
- unop(Iop_64HIto32,
- mkexpr(t1)),
- mkU32(0)));
- assign(t4, binop(Iop_CmpNE32,
- binop(Iop_And32,
- unop(Iop_64to32,
- mkexpr(t1)),
- mkU32(0x80000000)),
- mkU32(0)));
- /* Check if bits 63..31 of the result in t1 aren't
- 0x1ffffffff. */
- assign(t5, binop(Iop_CmpNE32,
- unop(Iop_64HIto32,
- mkexpr(t1)),
- mkU32(0xffffffff)));
- assign(t6, binop(Iop_CmpNE32,
- binop(Iop_And32,
- unop(Iop_64to32,
- mkexpr(t1)),
- mkU32(0x80000000)),
- mkU32(0x80000000)));
- /* If bits 63..31 aren't 0 nor 0x1ffffffff, set DSP
- control register. */
- assign(t7, binop(Iop_And32,
- binop(Iop_Or32,
- unop(Iop_1Sto32, mkexpr(t3)),
- unop(Iop_1Sto32, mkexpr(t4))),
- binop(Iop_Or32,
- unop(Iop_1Sto32, mkexpr(t5)),
- unop(Iop_1Sto32, mkexpr(t6)))));
- putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
- mkexpr(t7),
- mkU32(0)),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x00800000)),
- getDSPControl()));
-
- /* If the last discarded bit is 1, there would be carry
- when rounding, otherwise there wouldn't. We use that
- fact and just add the value of the last discarded bit
- to the least sifgnificant bit of the shifted value
- from acc. */
- assign(t8,
- IRExpr_ITE(binop(Iop_CmpEQ32,
- unop(Iop_8Uto32,
- mkexpr(t15)),
- mkU32(0)),
- mkU64(0x0ULL),
- binop(Iop_And64,
- binop(Iop_Shr64,
- mkexpr(t0),
- unop(Iop_32to8,
- binop(Iop_Sub32,
- unop(Iop_8Uto32,
- mkexpr(t15)),
- mkU32(1)))),
- mkU64(0x1ULL))));
-
- assign(t9, binop(Iop_Add64, mkexpr(t1), mkexpr(t8)));
- /* Put rounded value in destination register. */
- putIReg(rt, unop(Iop_64to32, mkexpr(t9)));
-
- /* Repeat previous steps for the rounded value. */
- assign(t10, binop(Iop_CmpNE32,
- unop(Iop_64HIto32,
- mkexpr(t9)),
- mkU32(0)));
- assign(t11, binop(Iop_CmpNE32,
- binop(Iop_And32,
- unop(Iop_64to32,
- mkexpr(t9)),
- mkU32(0x80000000)),
- mkU32(0)));
+ case 0x03: /* LDI.D */
+ DIP("LDI.D w%d, %d", wd, s10);
+ tmp = extend_s_10to64(s10);
+ break;
- assign(t12, binop(Iop_CmpNE32,
- unop(Iop_64HIto32,
- mkexpr(t9)),
- mkU32(0xffffffff)));
- assign(t13, binop(Iop_CmpNE32,
- binop(Iop_And32,
- unop(Iop_64to32,
- mkexpr(t9)),
- mkU32(0x80000000)),
- mkU32(0x80000000)));
-
- assign(t14, binop(Iop_And32,
- binop(Iop_Or32,
- unop(Iop_1Sto32, mkexpr(t10)),
- unop(Iop_1Sto32, mkexpr(t11))),
- binop(Iop_Or32,
- unop(Iop_1Sto32, mkexpr(t12)),
- unop(Iop_1Sto32, mkexpr(t13)))));
- putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
- mkexpr(t14),
- mkU32(0)),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x00800000)),
- getDSPControl()));
- break;
- }
- case 0x6: { /* EXTR_RS.W */
- DIP("extr_rs.w r%u, ac%u, %u", rt, ac, rs);
- vassert(!mode64);
- t0 = newTemp(Ity_I64);
- t1 = newTemp(Ity_I64);
- t2 = newTemp(Ity_I32);
- t3 = newTemp(Ity_I1);
- t4 = newTemp(Ity_I1);
- t5 = newTemp(Ity_I1);
- t6 = newTemp(Ity_I1);
- t7 = newTemp(Ity_I32);
- t8 = newTemp(Ity_I64);
- t9 = newTemp(Ity_I64);
- t10 = newTemp(Ity_I1);
- t11 = newTemp(Ity_I1);
- t12 = newTemp(Ity_I1);
- t13 = newTemp(Ity_I1);
- t14 = newTemp(Ity_I32);
- t16 = newTemp(Ity_I32);
-
- assign(t0, getAcc(ac));
- if (0 == rs) {
- assign(t1, mkexpr(t0));
- } else {
- assign(t1, binop(Iop_Sar64, mkexpr(t0), mkU8(rs)));
- }
+ default:
+ return -1;
+ }
- /* Check if bits 63..31 of the result in t1 aren't 0. */
- assign(t3, binop(Iop_CmpNE32,
- unop(Iop_64HIto32,
- mkexpr(t1)),
- mkU32(0)));
- assign(t4, binop(Iop_CmpNE32,
- binop(Iop_And32,
- unop(Iop_64to32,
- mkexpr(t1)),
- mkU32(0x80000000)),
- mkU32(0)));
- /* Check if bits 63..31 of the result in t1 aren't
- 0x1ffffffff. */
- assign(t5, binop(Iop_CmpNE32,
- unop(Iop_64HIto32,
- mkexpr(t1)),
- mkU32(0xffffffff)));
- assign(t6, binop(Iop_CmpNE32,
- binop(Iop_And32,
- unop(Iop_64to32,
- mkexpr(t1)),
- mkU32(0x80000000)),
- mkU32(0x80000000)));
- /* If bits 63..31 aren't 0 nor 0x1ffffffff, set DSP
- control register. */
- assign(t7, binop(Iop_And32,
- binop(Iop_Or32,
- unop(Iop_1Sto32, mkexpr(t3)),
- unop(Iop_1Sto32, mkexpr(t4))),
- binop(Iop_Or32,
- unop(Iop_1Sto32, mkexpr(t5)),
- unop(Iop_1Sto32, mkexpr(t6)))));
- putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
- mkexpr(t7),
- mkU32(0)),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x00800000)),
- getDSPControl()));
-
- /* If the last discarded bit is 1, there would be carry
- when rounding, otherwise there wouldn't. We use that
- fact and just add the value of the last discarded bit
- to the least sifgnificant bit of the shifted value
- from acc. */
- if (0 == rs) {
- assign(t8, mkU64(0x0ULL));
- } else {
- assign(t8, binop(Iop_And64,
- binop(Iop_Shr64,
- mkexpr(t0),
- mkU8(rs-1)),
- mkU64(0x1ULL)));
- }
+ putWReg(wd, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
+ break;
+ }
- assign(t9, binop(Iop_Add64, mkexpr(t1), mkexpr(t8)));
+ default:
+ return -1;
+ }
- /* Repeat previous steps for the rounded value. */
- assign(t10, binop(Iop_CmpNE32,
- unop(Iop_64HIto32,
- mkexpr(t9)),
- mkU32(0)));
- assign(t11, binop(Iop_CmpNE32,
- binop(Iop_And32,
- unop(Iop_64to32,
- mkexpr(t9)),
- mkU32(0x80000000)),
- mkU32(0)));
+ return 0;
+}
- assign(t12, binop(Iop_CmpNE32,
- unop(Iop_64HIto32,
- mkexpr(t9)),
- mkU32(0xffffffff)));
- assign(t13, binop(Iop_CmpNE32,
- binop(Iop_And32,
- unop(Iop_64to32,
- mkexpr(t9)),
- mkU32(0x80000000)),
- mkU32(0x80000000)));
-
- assign(t14, binop(Iop_And32,
- binop(Iop_Or32,
- unop(Iop_1Sto32, mkexpr(t10)),
- unop(Iop_1Sto32, mkexpr(t11))),
- binop(Iop_Or32,
- unop(Iop_1Sto32, mkexpr(t12)),
- unop(Iop_1Sto32, mkexpr(t13)))));
- putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
- mkexpr(t14),
- mkU32(0)),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x00800000)),
- getDSPControl()));
-
- assign(t16, binop(Iop_And32,
- unop(Iop_64HIto32,
- mkexpr(t9)),
- mkU32(0x80000000)));
- putIReg(rt, IRExpr_ITE(binop(Iop_CmpNE32,
- mkexpr(t14),
- mkU32(0)),
- IRExpr_ITE(binop(Iop_CmpEQ32,
- mkexpr(t16),
- mkU32(0)),
- mkU32(0x7fffffff),
- mkU32(0x80000000)),
- unop(Iop_64to32, mkexpr(t9))));
- break;
- }
- case 0x7: { /* EXTRV_RS.W */
- DIP("extrv_rs.w r%u, ac%u, r%u", rt, ac, rs);
- vassert(!mode64);
- t0 = newTemp(Ity_I64);
- t1 = newTemp(Ity_I64);
- t2 = newTemp(Ity_I32);
- t3 = newTemp(Ity_I1);
- t4 = newTemp(Ity_I1);
- t5 = newTemp(Ity_I1);
- t6 = newTemp(Ity_I1);
- t7 = newTemp(Ity_I32);
- t8 = newTemp(Ity_I64);
- t9 = newTemp(Ity_I64);
- t10 = newTemp(Ity_I1);
- t11 = newTemp(Ity_I1);
- t12 = newTemp(Ity_I1);
- t13 = newTemp(Ity_I1);
- t14 = newTemp(Ity_I32);
- t15 = newTemp(Ity_I32);
- t16 = newTemp(Ity_I32);
- t17 = newTemp(Ity_I1);
-
- assign(t15, binop(Iop_And32,
- getIReg(rs),
- mkU32(0x1f)));
- assign(t17, binop(Iop_CmpEQ32,
- mkexpr(t15),
- mkU32(0)));
- assign(t0, getAcc(ac));
- assign(t1, IRExpr_ITE(mkexpr(t17),
- mkexpr(t0),
- binop(Iop_Sar64,
- mkexpr(t0),
- unop(Iop_32to8,
- mkexpr(t15)))));
-
- /* Check if bits 63..31 of the result in t1 aren't 0. */
- assign(t3, binop(Iop_CmpNE32,
- unop(Iop_64HIto32,
- mkexpr(t1)),
- mkU32(0)));
- assign(t4, binop(Iop_CmpNE32,
- binop(Iop_And32,
- unop(Iop_64to32,
- mkexpr(t1)),
- mkU32(0x80000000)),
- mkU32(0)));
- /* Check if bits 63..31 of the result in t1 aren't
- 0x1ffffffff. */
- assign(t5, binop(Iop_CmpNE32,
- unop(Iop_64HIto32,
- mkexpr(t1)),
- mkU32(0xffffffff)));
- assign(t6, binop(Iop_CmpNE32,
- binop(Iop_And32,
- unop(Iop_64to32,
- mkexpr(t1)),
- mkU32(0x80000000)),
- mkU32(0x80000000)));
- /* If bits 63..31 aren't 0 nor 0x1ffffffff, set DSP
- control register. */
- assign(t7, binop(Iop_And32,
- binop(Iop_Or32,
- unop(Iop_1Sto32, mkexpr(t3)),
- unop(Iop_1Sto32, mkexpr(t4))),
- binop(Iop_Or32,
- unop(Iop_1Sto32, mkexpr(t5)),
- unop(Iop_1Sto32, mkexpr(t6)))));
- putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
- mkexpr(t7),
- mkU32(0)),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x00800000)),
- getDSPControl()));
-
- /* If the last discarded bit is 1, there would be carry
- when rounding, otherwise there wouldn't. We use that
- fact and just add the value of the last discarded bit
- to the least sifgnificant bit of the shifted value
- from acc. */
- assign(t8,
- IRExpr_ITE(mkexpr(t17),
- mkU64(0x0ULL),
- binop(Iop_And64,
- binop(Iop_Shr64,
- mkexpr(t0),
- unop(Iop_32to8,
- binop(Iop_Sub32,
- mkexpr(t15),
- mkU32(1)))),
- mkU64(0x1ULL))));
-
- assign(t9, binop(Iop_Add64, mkexpr(t1), mkexpr(t8)));
-
- /* Repeat previous steps for the rounded value. */
- assign(t10, binop(Iop_CmpNE32,
- unop(Iop_64HIto32,
- mkexpr(t9)),
- mkU32(0)));
- assign(t11, binop(Iop_CmpNE32,
- binop(Iop_And32,
- unop(Iop_64to32,
- mkexpr(t9)),
- mkU32(0x80000000)),
- mkU32(0)));
+static Int msa_BIT_09(UInt cins, UChar wd, UChar ws) /* BIT (0x09) */
+{
+ IRTemp t1, t2, t3;
+ UShort operation;
+ UChar df, m;
- assign(t12, binop(Iop_CmpNE32,
- unop(Iop_64HIto32,
- mkexpr(t9)),
- mkU32(0xffffffff)));
- assign(t13, binop(Iop_CmpNE32,
- binop(Iop_And32,
- unop(Iop_64to32,
- mkexpr(t9)),
- mkU32(0x80000000)),
- mkU32(0x80000000)));
-
- assign(t14, binop(Iop_And32,
- binop(Iop_Or32,
- unop(Iop_1Sto32, mkexpr(t10)),
- unop(Iop_1Sto32, mkexpr(t11))),
- binop(Iop_Or32,
- unop(Iop_1Sto32, mkexpr(t12)),
- unop(Iop_1Sto32, mkexpr(t13)))));
- putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
- mkexpr(t14),
- mkU32(0)),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x00800000)),
- getDSPControl()));
-
- assign(t16, binop(Iop_And32,
- unop(Iop_64HIto32,
- mkexpr(t9)),
- mkU32(0x80000000)));
- putIReg(rt, IRExpr_ITE(binop(Iop_CmpNE32,
- mkexpr(t14),
- mkU32(0)),
- IRExpr_ITE(binop(Iop_CmpEQ32,
- mkexpr(t16),
- mkU32(0)),
- mkU32(0x7fffffff),
- mkU32(0x80000000)),
- unop(Iop_64to32, mkexpr(t9))));
- break;
- }
- case 0xA: { /* EXTPDP */
- DIP("extpdp r%u, ac%u, %u", rt, ac, rs);
- vassert(!mode64);
- t0 = newTemp(Ity_I64);
- t1 = newTemp(Ity_I32);
- t2 = newTemp(Ity_I1);
- t3 = newTemp(Ity_I1);
- t4 = newTemp(Ity_I8);
- t5 = newTemp(Ity_I64);
- t6 = newTemp(Ity_I64);
- t7 = newTemp(Ity_I32);
- t8 = newTemp(Ity_I32);
-
- assign(t0, getAcc(ac));
- /* Extract pos field of DSPControl register. */
- assign(t1, binop(Iop_And32, getDSPControl(), mkU32(0x3f)));
-
- /* Check if (pos - size) >= 0 [size <= pos]
- if (pos < size)
- put 1 to EFI field of DSPControl register
- else
- extract bits from acc and put 0 to EFI field of
- DSPCtrl */
- assign(t2, binop(Iop_CmpLT32U, mkexpr(t1), mkU32(rs)));
-
- assign(t8, binop(Iop_Or32,
- binop(Iop_And32,
- getDSPControl(),
- mkU32(0xffffbfc0)),
- binop(Iop_And32,
- binop(Iop_Sub32,
- binop(Iop_And32,
- getDSPControl(),
- mkU32(0x3f)),
- mkU32(rs+1)),
- mkU32(0x3f))));
- putDSPControl(IRExpr_ITE(mkexpr(t2),
- binop(Iop_Or32,
- binop(Iop_And32,
- getDSPControl(),
- mkU32(0xffffbfff)),
- mkU32(0x4000)),
- mkexpr(t8)));
-
- /* If pos <= 31, shift right the value from the acc
- (pos-size) times and take (size+1) bits from the least
- significant positions. Otherwise, shift left the value
- (63-pos) times, take (size+1) bits from the most
- significant positions and shift right (31-size) times.
- */
- assign(t3, binop(Iop_CmpLE32U, mkexpr(t1), mkU32(31)));
-
- assign(t4,
- IRExpr_ITE(mkexpr(t3),
- unop(Iop_32to8,
- binop(Iop_Sub32,
- mkexpr(t1), mkU32(rs))),
- unop(Iop_32to8,
- binop(Iop_Sub32,
- mkU32(63), mkexpr(t1)))));
-
- assign(t5, IRExpr_ITE(mkexpr(t3),
- binop(Iop_Shr64,
- mkexpr(t0), mkexpr(t4)),
- binop(Iop_Shl64,
- mkexpr(t0), mkexpr(t4))));
-
- /* t6 holds a mask for bit extraction. */
- assign(t6,
- IRExpr_ITE(mkexpr(t3),
- unop(Iop_Not64,
- binop(Iop_Shl64,
- mkU64(0xffffffffffffffffULL),
- mkU8(rs+1))),
- unop(Iop_Not64,
- binop(Iop_Shr64,
- mkU64(0xffffffffffffffffULL),
- mkU8(rs+1)))));
-
- assign(t7, IRExpr_ITE(mkexpr(t3),
- unop(Iop_64to32,
- binop(Iop_And64,
- mkexpr(t5),
- mkexpr(t6))),
- binop(Iop_Shr32,
- unop(Iop_64HIto32,
- binop(Iop_And64,
- mkexpr(t5),
- mkexpr(t6))),
- mkU8(31-rs))));
+ operation = (cins & 0x03800000) >> 23;
+ df = (cins & 0x007F0000) >> 16;
- putIReg(rt, mkexpr(t7));
- break;
- }
- case 0xB: { /* EXTPDPV */
- DIP("extpdpv r%u, ac%u, r%u", rt, ac, rs);
- vassert(!mode64);
- t0 = newTemp(Ity_I64);
- t1 = newTemp(Ity_I32);
- t2 = newTemp(Ity_I1);
- t3 = newTemp(Ity_I1);
- t4 = newTemp(Ity_I8);
- t5 = newTemp(Ity_I64);
- t6 = newTemp(Ity_I64);
- t7 = newTemp(Ity_I32);
- t8 = newTemp(Ity_I32);
- t9 = newTemp(Ity_I32);
-
- assign(t8, binop(Iop_And32, getIReg(rs), mkU32(0x1f)));
- assign(t0, getAcc(ac));
- /* Extract pos field of DSPControl register. */
- assign(t1, binop(Iop_And32, getDSPControl(), mkU32(0x3f)));
-
- /* Check if (pos - size) >= 0 [size <= pos]
- if (pos < size)
- put 1 to EFI field of DSPControl register
- else
- extract bits from acc and put 0 to EFI field of
- DSPCtrl */
- assign(t2, binop(Iop_CmpLT32U, mkexpr(t1), mkexpr(t8)));
-
- assign(t9, binop(Iop_Or32,
- binop(Iop_And32,
- getDSPControl(),
- mkU32(0xffffbfc0)),
- binop(Iop_And32,
- binop(Iop_Sub32,
- binop(Iop_And32,
- getDSPControl(),
- mkU32(0x3f)),
- binop(Iop_Add32,
- mkexpr(t8),
- mkU32(0x1))),
- mkU32(0x3f))));
- putDSPControl(IRExpr_ITE(mkexpr(t2),
- binop(Iop_Or32,
- binop(Iop_And32,
- getDSPControl(),
- mkU32(0xffffbfff)),
- mkU32(0x4000)),
- mkexpr(t9)));
-
- /* If pos <= 31, shift right the value from the acc
- (pos-size) times and take (size+1) bits from the least
- significant positions. Otherwise, shift left the value
- (63-pos) times, take (size+1) bits from the most
- significant positions and shift right (31-size) times.
- */
- assign(t3, binop(Iop_CmpLE32U, mkexpr(t1), mkU32(31)));
-
- assign(t4,
- IRExpr_ITE(mkexpr(t3),
- unop(Iop_32to8,
- binop(Iop_Sub32,
- mkexpr(t1), mkexpr(t8))),
- unop(Iop_32to8,
- binop(Iop_Sub32,
- mkU32(63), mkexpr(t1)))));
-
- assign(t5, IRExpr_ITE(mkexpr(t3),
- binop(Iop_Shr64,
- mkexpr(t0), mkexpr(t4)),
- binop(Iop_Shl64,
- mkexpr(t0), mkexpr(t4))));
-
- /* t6 holds a mask for bit extraction. */
- assign(t6,
- IRExpr_ITE(mkexpr(t3),
- unop(Iop_Not64,
- binop(Iop_Shl64,
- mkU64(0xffffffffffffffffULL),
- unop(Iop_32to8,
- binop(Iop_Add32,
- mkexpr(t8),
- mkU32(1))))),
- unop(Iop_Not64,
- binop(Iop_Shr64,
- mkU64(0xffffffffffffffffULL),
- unop(Iop_32to8,
- binop(Iop_Add32,
- mkexpr(t8),
- mkU32(1)))))));
-
- assign(t7, IRExpr_ITE(mkexpr(t3),
- unop(Iop_64to32,
- binop(Iop_And64,
- mkexpr(t5),
- mkexpr(t6))),
- binop(Iop_Shr32,
- unop(Iop_64HIto32,
- binop(Iop_And64,
- mkexpr(t5),
- mkexpr(t6))),
- unop(Iop_32to8,
- binop(Iop_Sub32,
- mkU32(31),
- mkexpr(t8))))));
+ if ((df & 0x70) == 0x70) { // 111mmmm; b
+ m = df & 0x07;
+ df = 0;
+ } else if ((df & 0x60) == 0x60) { // 110mmmm; h
+ m = df & 0x0F;
+ df = 1;
+ } else if ((df & 0x40) == 0x40) { // 10mmmmm; w
+ m = df & 0x1F;
+ df = 2;
+ } else if ((df & 0x00) == 0x00) { // 0mmmmmm; d
+ m = df & 0x3F;
+ df = 3;
+ }
- putIReg(rt, mkexpr(t7));
- break;
- }
- case 0xE: { /* EXTR_S.H */
- DIP("extr_s.h r%u, ac%u, %u", rt, ac, rs);
- vassert(!mode64);
- t0 = newTemp(Ity_I64);
- t1 = newTemp(Ity_I64);
- t2 = newTemp(Ity_I32);
- t3 = newTemp(Ity_I64);
- t4 = newTemp(Ity_I32);
- t5 = newTemp(Ity_I32);
- t6 = newTemp(Ity_I64);
- t7 = newTemp(Ity_I32);
- t9 = newTemp(Ity_I32);
+ switch (operation) {
+ case 0x00: { /* SLLI.df */
+ switch (df) {
+ case 0x00: { /* SLLI.B */
+ DIP("SLLI.B w%d, w%d, %d", wd, ws, m);
+ putWReg(wd, binop(Iop_ShlN8x16, getWReg(ws), mkU8(m)));
+ break;
+ }
- assign(t0, getAcc(ac));
+ case 0x01: { /* SLLI.H */
+ DIP("SLLI.H w%d, w%d, %d", wd, ws, m);
+ putWReg(wd, binop(Iop_ShlN16x8, getWReg(ws), mkU8(m)));
+ break;
+ }
- assign(t1, binop(Iop_Sar64, mkexpr(t0), mkU8(rs)));
+ case 0x02: { /* SLLI.W */
+ DIP("SLLI.W w%d, w%d, %d", wd, ws, m);
+ putWReg(wd, binop(Iop_ShlN32x4, getWReg(ws), mkU8(m)));
+ break;
+ }
- assign(t2, binop(Iop_Or32,
- getDSPControl(), mkU32(0x00800000)));
+ case 0x03: { /* SLLI.D */
+ DIP("SLLI.D w%d, w%d, %d", wd, ws, m);
+ putWReg(wd, binop(Iop_ShlN64x2, getWReg(ws), mkU8(m)));
+ break;
+ }
+ }
- assign(t9, binop(Iop_And32,
- unop(Iop_64to32,
- mkexpr(t1)),
- mkU32(0x80000000)));
- putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
- mkexpr(t9),
- binop(Iop_And32,
- unop(Iop_64HIto32,
- mkexpr(t0)),
- mkU32(0x80000000))),
- mkexpr(t2),
- getDSPControl()));
+ break;
+ }
- /* Check if t1 > 0x7fff ((t1 - 0x7fff) > 0)
- 1. subtract 0x7fff from t1
- 2. if the resulting number is positive (sign bit = 0)
- and any of the other bits is 1, the value is > 0. */
- assign(t3, binop(Iop_Sub64,
- mkexpr(t1),
- mkU64(0x0000000000007fffULL)));
- assign(t4, binop(Iop_And32,
- binop(Iop_Or32,
- unop(Iop_1Sto32,
- binop(Iop_CmpNE32,
- mkU32(0),
- binop(Iop_And32,
- unop(Iop_64HIto32,
- mkexpr(t3)),
- mkU32(0x7fffffff)))),
- unop(Iop_1Sto32,
- binop(Iop_CmpNE32,
- mkU32(0),
- unop(Iop_64to32,
- mkexpr(t3))))),
- unop(Iop_1Sto32,
- binop(Iop_CmpEQ32,
- binop(Iop_And32,
- unop(Iop_64HIto32,
- mkexpr(t3)),
- mkU32(0x80000000)),
- mkU32(0)))));
- putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
- mkU32(0),
- mkexpr(t4)),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x00800000)),
- getDSPControl()));
- /* Check if t1<0xffffffffffff8000 (0xffffffffffff8000-t1)>0
- 1. subtract t1 from 0xffffffffffff8000
- 2. if the resulting number is positive (sign bit = 0)
- and any of the other bits is 1, the value is > 0 */
- assign(t6, binop(Iop_Sub64,
- mkU64(0xffffffffffff8000ULL),
- mkexpr(t1)));
- assign(t7, binop(Iop_And32,
- binop(Iop_Or32,
- unop(Iop_1Sto32,
- binop(Iop_CmpNE32,
- mkU32(0),
- binop(Iop_And32,
- unop(Iop_64HIto32,
- mkexpr(t6)),
- mkU32(0x7fffffff)))),
- unop(Iop_1Sto32,
- binop(Iop_CmpNE32,
- mkU32(0),
- unop(Iop_64to32,
- mkexpr(t6))))),
- unop(Iop_1Sto32,
- binop(Iop_CmpEQ32,
- binop(Iop_And32,
- unop(Iop_64HIto32,
- mkexpr(t6)),
- mkU32(0x80000000)),
- mkU32(0)))));
- putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
- mkU32(0),
- mkexpr(t7)),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x00800000)),
- getDSPControl()));
- putIReg(rt, IRExpr_ITE(binop(Iop_CmpNE32,
- mkU32(0),
- mkexpr(t4)),
- mkU32(0x00007fff),
- IRExpr_ITE(binop(Iop_CmpNE32,
- mkU32(0),
- mkexpr(t7)),
- mkU32(0xffff8000),
- unop(Iop_64to32,
- mkexpr(t1)))));
- break;
- }
- case 0xF: { /* EXTRV_S.H */
- DIP("extrv_s.h r%u, ac%u, %u", rt, ac, rs);
- vassert(!mode64);
- t0 = newTemp(Ity_I64);
- t1 = newTemp(Ity_I64);
- t2 = newTemp(Ity_I32);
- t3 = newTemp(Ity_I64);
- t4 = newTemp(Ity_I32);
- t5 = newTemp(Ity_I32);
- t6 = newTemp(Ity_I64);
- t7 = newTemp(Ity_I32);
- t9 = newTemp(Ity_I32);
+ case 0x01: { /* SRAI.df */
+ switch (df) {
+ case 0x00: { /* SRAI.B */
+ DIP("SRAI.B w%d, w%d, %d", wd, ws, m);
+ putWReg(wd, binop(Iop_SarN8x16, getWReg(ws), mkU8(m)));
+ break;
+ }
- assign(t0, getAcc(ac));
+ case 0x01: { /* SRAI.H */
+ DIP("SRAI.H w%d, w%d, %d", wd, ws, m);
+ putWReg(wd, binop(Iop_SarN16x8, getWReg(ws), mkU8(m)));
+ break;
+ }
- assign(t1, binop(Iop_Sar64,
- mkexpr(t0),
- unop(Iop_32to8,
- binop(Iop_And32,
- getIReg(rs),
- mkU32(0x1f)))));
+ case 0x02: { /* SRAI.W */
+ DIP("SRAI.W w%d, w%d, %d", wd, ws, m);
+ putWReg(wd, binop(Iop_SarN32x4, getWReg(ws), mkU8(m)));
+ break;
+ }
- assign(t2, binop(Iop_Or32,
- getDSPControl(), mkU32(0x00800000)));
+ case 0x03: { /* SRAI.D */
+ DIP("SRAI.D w%d, w%d, %d", wd, ws, m);
+ putWReg(wd, binop(Iop_SarN64x2, getWReg(ws), mkU8(m)));
+ break;
+ }
+ }
- assign(t9, binop(Iop_And32,
- unop(Iop_64to32,
- mkexpr(t1)),
- mkU32(0x80000000)));
- putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
- mkexpr(t9),
- binop(Iop_And32,
- unop(Iop_64HIto32,
- mkexpr(t0)),
- mkU32(0x80000000))),
- mkexpr(t2),
- getDSPControl()));
+ break;
+ }
- /* Check if t1 > 0x7fff ((t1 - 0x7fff) > 0)
- 1. subtract 0x7fff from t1
- 2. if the resulting number is positive (sign bit = 0)
- and any of the other bits is 1, the value is > 0. */
- assign(t3, binop(Iop_Sub64,
- mkexpr(t1),
- mkU64(0x0000000000007fffULL)));
- assign(t4, binop(Iop_And32,
- binop(Iop_Or32,
- unop(Iop_1Sto32,
- binop(Iop_CmpNE32,
- mkU32(0),
- binop(Iop_And32,
- unop(Iop_64HIto32,
- mkexpr(t3)),
- mkU32(0x7fffffff)))),
- unop(Iop_1Sto32,
- binop(Iop_CmpNE32,
- mkU32(0),
- unop(Iop_64to32,
- mkexpr(t3))))),
- unop(Iop_1Sto32,
- binop(Iop_CmpEQ32,
- binop(Iop_And32,
- unop(Iop_64HIto32,
- mkexpr(t3)),
- mkU32(0x80000000)),
- mkU32(0)))));
- putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
- mkU32(0),
- mkexpr(t4)),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x00800000)),
- getDSPControl()));
- /* Check if t1<0xffffffffffff8000 (0xffffffffffff8000-t1)>0
- 1. subtract t1 from 0xffffffffffff8000
- 2. if the resulting number is positive (sign bit = 0)
- and any of the other bits is 1, the value is > 0 */
- assign(t6, binop(Iop_Sub64,
- mkU64(0xffffffffffff8000ULL),
- mkexpr(t1)));
- assign(t7, binop(Iop_And32,
- binop(Iop_Or32,
- unop(Iop_1Sto32,
- binop(Iop_CmpNE32,
- mkU32(0),
- binop(Iop_And32,
- unop(Iop_64HIto32,
- mkexpr(t6)),
- mkU32(0x7fffffff)))),
- unop(Iop_1Sto32,
- binop(Iop_CmpNE32,
- mkU32(0),
- unop(Iop_64to32,
- mkexpr(t6))))),
- unop(Iop_1Sto32,
- binop(Iop_CmpEQ32,
- binop(Iop_And32,
- unop(Iop_64HIto32,
- mkexpr(t6)),
- mkU32(0x80000000)),
- mkU32(0)))));
- putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
- mkU32(0),
- mkexpr(t7)),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x00800000)),
- getDSPControl()));
- putIReg(rt, IRExpr_ITE(binop(Iop_CmpNE32,
- mkU32(0),
- mkexpr(t4)),
- mkU32(0x00007fff),
- IRExpr_ITE(binop(Iop_CmpNE32,
- mkU32(0),
- mkexpr(t7)),
- mkU32(0xffff8000),
- unop(Iop_64to32,
- mkexpr(t1)))));
- break;
- }
- case 0x12: { /* RDDSP*/
- DIP("rddsp r%u, mask 0x%x", rd, rddsp_mask);
- vassert(!mode64);
+ case 0x02: { /* SRLI.df */
+ switch (df) {
+ case 0x00: { /* SRLI.B */
+ DIP("SRLI.B w%d, w%d, %d", wd, ws, m);
+ putWReg(wd, binop(Iop_ShrN8x16, getWReg(ws), mkU8(m)));
+ break;
+ }
- putIReg(rd, mkU32(0x0));
+ case 0x01: { /* SRLI.H */
+ DIP("SRLI.H w%d, w%d, %d", wd, ws, m);
+ putWReg(wd, binop(Iop_ShrN16x8, getWReg(ws), mkU8(m)));
+ break;
+ }
- if ((rddsp_mask & 0x1) == 0x1) {
- /* Read pos field (bits 5-0) of DSPControl register. */
- putIReg(rd, binop(Iop_Or32,
- getIReg(rd),
- binop(Iop_And32,
- getDSPControl(),
- mkU32(0x0000003F))));
- }
+ case 0x02: { /* SRLI.W */
+ DIP("SRLI.W w%d, w%d, %d", wd, ws, m);
+ putWReg(wd, binop(Iop_ShrN32x4, getWReg(ws), mkU8(m)));
+ break;
+ }
- if ((rddsp_mask & 0x2) == 0x2) {
- /* Read scount field (bits 12-7) of DSPControl
- register. */
- putIReg(rd, binop(Iop_Or32,
- getIReg(rd),
- binop(Iop_And32,
- getDSPControl(),
- mkU32(0x00001F80))));
- }
+ case 0x03: { /* SRLI.D */
+ DIP("SRLI.D w%d, w%d, %d", wd, ws, m);
+ putWReg(wd, binop(Iop_ShrN64x2, getWReg(ws), mkU8(m)));
+ break;
+ }
+ }
- if ((rddsp_mask & 0x4) == 0x4) {
- /* Read C field (bit 13) of DSPControl register. */
- putIReg(rd, binop(Iop_Or32,
- getIReg(rd),
- binop(Iop_And32,
- getDSPControl(),
- mkU32(0x00002000))));
- }
+ break;
+ }
- if ((rddsp_mask & 0x8) == 0x8) {
- /* Read outflag field (bit s 23-16) of DSPControl
- register. */
- putIReg(rd, binop(Iop_Or32,
- getIReg(rd),
- binop(Iop_And32,
- getDSPControl(),
- mkU32(0x00FF0000))));
- }
+ case 0x03: { /* BCLRI.df */
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ ULong tmp = 1;
+ assign(t1, getWReg(ws));
- if ((rddsp_mask & 0x10) == 0x10) {
- /* Read ccond field (bits 31-24) of DSPControl
- register. */
- putIReg(rd, binop(Iop_Or32,
- getIReg(rd),
- binop(Iop_And32,
- getDSPControl(),
- mkU32(0xFF000000))));
- }
+ switch (df) {
+ case 0x00: { /* BCLRI.B */
+ DIP("BCLRI.B w%d, w%d, %d", wd, ws, m);
+ tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
+ (tmp << 32) | (tmp << 24) | (tmp << 16) |
+ (tmp << 8);
+ assign(t2, binop(Iop_ShlN8x16,
+ binop(Iop_64HLtoV128,
+ mkU64(tmp), mkU64(tmp)), mkU8(m)));
+ break;
+ }
- if ((rddsp_mask & 0x20) == 0x20) {
- /* Read EFI field (bit 14) of DSPControl register. */
- putIReg(rd, binop(Iop_Or32,
- getIReg(rd),
- binop(Iop_And32,
- getDSPControl(),
- mkU32(0x00004000))));
- }
+ case 0x01: { /* BCLRI.H */
+ DIP("BCLRI.H w%d, w%d, %d", wd, ws, m);
+ tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
+ assign(t2, binop(Iop_ShlN16x8,
+ binop(Iop_64HLtoV128,
+ mkU64(tmp), mkU64(tmp)), mkU8(m)));
+ break;
+ }
- if ((rddsp_mask & 0x3f) == 0x3f) {
- /* Read all fields of DSPControl register. */
- putIReg(rd, getDSPControl());
- }
- break;
- }
- case 0x13: { /* WRDSP */
- DIP("wrdsp r%u, mask 0x%x", rs, wrdsp_mask);
- vassert(!mode64);
-
- if ((wrdsp_mask & 0x3f) == 0x3f) {
- /* If mips64 put all fields of rs, except bit 15 and bit
- 6, to DSPControl register, otherwise put all except
- bits 15, 6 and bits 31..28. */
- putDSPControl(mode64 ?
- binop(Iop_And32,
- getIReg(rs),
- mkU32(0xffff7fbf)) :
- binop(Iop_And32,
- getIReg(rs),
- mkU32(0x0fff7fbf)));
- } else {
- if ((wrdsp_mask & 0x1) == 0x1) {
- /* Put bits 5-0 of rs to DSPControl register pos
- field. */
- putDSPControl(binop(Iop_Or32,
- binop(Iop_And32,
- getDSPControl(),
- mkU32(0xFFFF7F40)),
- binop(Iop_And32,
- getIReg(rs),
- mkU32(0x0000003F))));
- }
+ case 0x02: { /* BCLRI.W */
+ DIP("BCLRI.W w%d, w%d, %d", wd, ws, m);
+ tmp |= (tmp << 32);
+ assign(t2, binop(Iop_ShlN32x4,
+ binop(Iop_64HLtoV128,
+ mkU64(tmp), mkU64(tmp)), mkU8(m)));
+ break;
+ }
- if ((wrdsp_mask & 0x2) == 0x2) {
- /* Put bits 12-7 of rs to DSPControl scount field. */
- putDSPControl(binop(Iop_Or32,
- binop(Iop_And32,
- getDSPControl(),
- mkU32(0xFFFFE03F)),
- binop(Iop_And32,
- getIReg(rs),
- mkU32(0x00001F80))));
- }
+ case 0x03: { /* BCLRI.D */
+ DIP("BCLRI.D w%d, w%d, %d", wd, ws, m);
+ assign(t2, binop(Iop_ShlN64x2,
+ binop(Iop_64HLtoV128,
+ mkU64(tmp), mkU64(tmp)), mkU8(m)));
+ break;
+ }
+ }
- if ((wrdsp_mask & 0x4) == 0x4) {
- /* Put bit 13 of rs to DSPControl register C
- field. */
- putDSPControl(binop(Iop_Or32,
- binop(Iop_And32,
- getDSPControl(),
- mkU32(0xFFFF5FBF)),
- binop(Iop_And32,
- getIReg(rs),
- mkU32(0x00002000))));
- }
+ assign(t3, binop(Iop_AndV128,
+ mkexpr(t1), unop(Iop_NotV128, mkexpr(t2))));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- if ((wrdsp_mask & 0x8) == 0x8) {
- /* Put bits 23-16 of rs to DSPControl reg outflag
- field. */
- putDSPControl(binop(Iop_Or32,
- binop(Iop_And32,
- getDSPControl(),
- mkU32(0xFF007FBF)),
- binop(Iop_And32,
- getIReg(rs),
- mkU32(0x00FF0000))));
- }
+ case 0x04: { /* BSETI */
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ ULong tmp = 1;
+ assign(t1, getWReg(ws));
- if ((wrdsp_mask & 0x10) == 0x10) {
- /* Put bits 31-24 of rs to DSPControl reg ccond
- field. */
- putDSPControl(binop(Iop_Or32,
- binop(Iop_And32,
- getDSPControl(),
- mkU32(0x00FF7FBF)),
- binop(Iop_And32,
- getIReg(rs),
- mode64 ? mkU32(0xFF000000)
- : mkU32(0x0F000000))
- )
- );
- }
+ switch (df) {
+ case 0x00: { /* BSETI.B */
+ DIP("BSETI.B w%d, w%d, %d", wd, ws, m);
+ tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
+ (tmp << 32) | (tmp << 24) | (tmp << 16) |
+ (tmp << 8);
+ assign(t2, binop(Iop_ShlN8x16,
+ binop(Iop_64HLtoV128,
+ mkU64(tmp), mkU64(tmp)), mkU8(m)));
+ break;
+ }
- if ((wrdsp_mask & 0x20) == 0x20) {
- /* Put bit 14 of rs to DSPControl register EFI
- field. */
- putDSPControl(binop(Iop_Or32,
- binop(Iop_And32,
- getDSPControl(),
- mkU32(0xFFFF3FBF)),
- binop(Iop_And32,
- getIReg(rs),
- mkU32(0x00004000))));
- }
- }
- break;
- }
- case 0x1A: { /* SHILO */
- DIP("shilo ac%u, %u", ac, shift);
- vassert(!mode64);
- t0 = newTemp(Ity_I64);
- t1 = newTemp(Ity_I64);
+ case 0x01: { /* BSETI.H */
+ DIP("BSETI.H w%d, w%d, %d", wd, ws, m);
+ tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
+ assign(t2, binop(Iop_ShlN16x8,
+ binop(Iop_64HLtoV128,
+ mkU64(tmp), mkU64(tmp)), mkU8(m)));
+ break;
+ }
- assign(t0, getAcc(ac));
+ case 0x02: { /* BSETI.W */
+ DIP("BSETI.W w%d, w%d, %d", wd, ws, m);
+ tmp |= (tmp << 32);
+ assign(t2, binop(Iop_ShlN32x4,
+ binop(Iop_64HLtoV128,
+ mkU64(tmp), mkU64(tmp)), mkU8(m)));
+ break;
+ }
- putAcc(ac, mkexpr(t0));
+ case 0x03: { /* BSETI.D */
+ DIP("BSETI.D w%d, w%d, %d", wd, ws, m);
+ assign(t2, binop(Iop_ShlN64x2,
+ binop(Iop_64HLtoV128,
+ mkU64(tmp), mkU64(tmp)), mkU8(m)));
+ break;
+ }
+ }
- if (0x20 == (shift & 0x3f)) {
- putAcc(ac, binop(Iop_32HLto64,
- unop(Iop_64to32, mkexpr(t0)),
- mkU32(0x0)));
- } else if (0x20 == (shift & 0x20)) {
- assign(t1, binop(Iop_Shl64,
- mkexpr(t0),
- unop(Iop_32to8,
- binop(Iop_Add32,
- unop(Iop_Not32,
- mkU32(shift)),
- mkU32(0x1)))));
+ assign(t3, binop(Iop_OrV128, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- putAcc(ac, mkexpr(t1));
- } else {
- assign(t1, binop(Iop_Shr64, mkexpr(t0), mkU8(shift)));
+ case 0x05: { /* BNEGI.df */
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ ULong tmp = 1;
+ assign(t1, getWReg(ws));
- putAcc(ac, mkexpr(t1));
- }
- break;
- }
- case 0x1B: { /* SHILOV */
- DIP("shilov ac%u, r%u", ac, rs);
- vassert(!mode64);
- t0 = newTemp(Ity_I64);
- t1 = newTemp(Ity_I32);
- t2 = newTemp(Ity_I1);
- t3 = newTemp(Ity_I64);
- t4 = newTemp(Ity_I64);
-
- assign(t0, getAcc(ac));
- assign(t1, binop(Iop_And32, getIReg(rs), mkU32(0x3f)));
- assign(t2, binop(Iop_CmpEQ32, mkexpr(t1), mkU32(0x20)));
- assign(t3, binop(Iop_Shl64,
- mkexpr(t0),
- unop(Iop_32to8,
- binop(Iop_Add32,
- unop(Iop_Not32,
- mkexpr(t1)),
- mkU32(0x1)))));
- assign(t4, binop(Iop_Shr64,
- mkexpr(t0),
- unop(Iop_32to8,
- mkexpr(t1))));
-
- putAcc(ac,
- IRExpr_ITE(mkexpr(t2),
- binop(Iop_32HLto64,
- unop(Iop_64to32, mkexpr(t0)),
- mkU32(0x0)),
- IRExpr_ITE(binop(Iop_CmpEQ32,
- binop(Iop_And32,
- mkexpr(t1),
- mkU32(0x20)),
- mkU32(0x20)),
- mkexpr(t3),
- mkexpr(t4))));
- break;
- }
- case 0x1F: { /* MTHLIP */
- DIP("mthlip r%u, ac%u", rs, ac);
- vassert(!mode64);
- t0 = newTemp(Ity_I64);
- t1 = newTemp(Ity_I32);
- t2 = newTemp(Ity_I32);
- t3 = newTemp(Ity_I1);
-
- assign(t0, getAcc(ac));
- putAcc(ac, binop(Iop_32HLto64,
- unop(Iop_64to32, mkexpr(t0)),
- getIReg(rs)));
- assign(t1, binop(Iop_And32, getDSPControl(), mkU32(0x3f)));
- putDSPControl(IRExpr_ITE(binop(Iop_CmpLE32U,
- mkU32(32),
- mkexpr(t1)),
- binop(Iop_Or32,
- binop(Iop_Sub32,
- mkexpr(t1),
- mkU32(32)),
- binop(Iop_And32,
- getDSPControl(),
- mkU32(0xffffffc0))),
- binop(Iop_Or32,
- binop(Iop_Add32,
- mkexpr(t1),
- mkU32(32)),
- binop(Iop_And32,
- getDSPControl(),
- mkU32(0xffffffc0)))));
- break;
- }
- default:
- return -1;
- }
- break; /* end of EXTR.W */
+ switch (df) {
+ case 0x00: { /* BNEGI.B */
+ DIP("BNEGI.B w%d, w%d, %d", wd, ws, m);
+ tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
+ (tmp << 32) | (tmp << 24) | (tmp << 16) |
+ (tmp << 8);
+ assign(t2, binop(Iop_ShlN8x16,
+ binop(Iop_64HLtoV128,
+ mkU64(tmp), mkU64(tmp)), mkU8(m)));
+ break;
}
- case 0xA: { /* LX */
- switch(sa) {
- case 0x0: { /* LWX */
- DIP("lwx r%u, r%u(r%u)", rd, rt, rs);
- vassert(!mode64);
- t0 = newTemp(Ity_I32);
- assign(t0, binop(Iop_Add32, getIReg(rt), getIReg(rs)));
+ case 0x01: { /* BNEGI.H */
+ DIP("BNEGI.H w%d, w%d, %d", wd, ws, m);
+ tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
+ assign(t2, binop(Iop_ShlN16x8,
+ binop(Iop_64HLtoV128,
+ mkU64(tmp), mkU64(tmp)), mkU8(m)));
+ break;
+ }
- putIReg(rd, load(Ity_I32, mkexpr(t0)));
- break;
- }
- case 0x4: { /* LHX */
- DIP("lhx r%u, r%u(r%u)", rd, rt, rs);
- vassert(!mode64);
- t0 = newTemp(Ity_I32);
+ case 0x02: { /* BNEGI.W */
+ DIP("BNEGI.W w%d, w%d, %d", wd, ws, m);
+ tmp |= (tmp << 32);
+ assign(t2, binop(Iop_ShlN32x4,
+ binop(Iop_64HLtoV128,
+ mkU64(tmp), mkU64(tmp)), mkU8(m)));
+ break;
+ }
- assign(t0, binop(Iop_Add32, getIReg(rt), getIReg(rs)));
+ case 0x03: { /* BNEGI.D */
+ DIP("BNEGI.D w%d, w%d, %d", wd, ws, m);
+ assign(t2, binop(Iop_ShlN64x2,
+ binop(Iop_64HLtoV128,
+ mkU64(tmp), mkU64(tmp)), mkU8(m)));
+ break;
+ }
+ }
- putIReg(rd, unop(Iop_16Sto32, load(Ity_I16, mkexpr(t0))));
- break;
- }
- case 0x6: { /* LBUX */
- DIP("lbux r%u, r%u(r%u)", rd, rt, rs);
- vassert(!mode64);
- t0 = newTemp(Ity_I32);
+ assign(t3, binop(Iop_XorV128, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- assign(t0, binop(Iop_Add32, getIReg(rt), getIReg(rs)));
+ case 0x06: { /* BINSLI.df */
+ switch (df) {
+ case 0x00: { /* BINSLI.B */
+ DIP("BINSLI.B w%d, w%d, w%d", wd, ws, m);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ ULong tmp = 0x8080808080808080ULL;
+ assign(t1, binop(Iop_SarN8x16,
+ binop(Iop_64HLtoV128,
+ mkU64(tmp), mkU64(tmp)), mkU8(m)));
+ assign(t2,
+ binop(Iop_AndV128,
+ unop(Iop_NotV128, mkexpr(t1)), getWReg(wd)));
+ assign(t3,
+ binop(Iop_AndV128,
+ mkexpr(t1), getWReg(ws)));
+ putWReg(wd,
+ binop(Iop_OrV128,
+ mkexpr(t2), mkexpr(t3)));
+ break;
+ }
- putIReg(rd, unop(Iop_8Uto32, load(Ity_I8, mkexpr(t0))));
- break;
- }
- default:
- return -1;
- }
- break; /* end of LX */
- }
- case 0xC: { /* INSV */
- switch(sa) {
- case 0x0: { /* INSV */
- DIP("insv r%u, r%u", rt, rs);
- vassert(!mode64);
-
- t0 = newTemp(Ity_I32);
- t1 = newTemp(Ity_I32);
- t2 = newTemp(Ity_I8);
- t3 = newTemp(Ity_I8);
- t4 = newTemp(Ity_I32);
- t5 = newTemp(Ity_I1);
- t6 = newTemp(Ity_I32);
- t7 = newTemp(Ity_I32);
- t8 = newTemp(Ity_I32);
- t9 = newTemp(Ity_I32);
-
- /* t0 <- pos field of DSPControl register. */
- assign(t0, binop(Iop_And32, getDSPControl(), mkU32(0x3f)));
- /* t1 <- scount field of DSPControl register. */
- assign(t1, binop(Iop_Shr32,
- binop(Iop_And32,
- getDSPControl(),
- mkU32(0x1f80)),
- mkU8(7)));
-
- assign(t2, unop(Iop_32to8,
- binop(Iop_Add32,
- mkexpr(t1),
- mkexpr(t0))));
+ case 0x01: { /* BINSLI.H */
+ DIP("BINSLI.H w%d, w%d, w%d", wd, ws, m);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ ULong tmp = 0x8000800080008000ULL;
+ assign(t1,
+ binop(Iop_SarN16x8,
+ binop(Iop_64HLtoV128,
+ mkU64(tmp), mkU64(tmp)), mkU8(m)));
+ assign(t2,
+ binop(Iop_AndV128,
+ unop(Iop_NotV128, mkexpr(t1)), getWReg(wd)));
+ assign(t3,
+ binop(Iop_AndV128,
+ mkexpr(t1), getWReg(ws)));
+ putWReg(wd,
+ binop(Iop_OrV128,
+ mkexpr(t2), mkexpr(t3)));
+ break;
+ }
- /* 32-(pos+size) most significant bits of rt. */
- assign(t6, binop(Iop_Shl32,
- binop(Iop_Shr32,
- getIReg(rt),
- mkexpr(t2)),
- mkexpr(t2)));
+ case 0x02: { /* BINSLI.W */
+ DIP("BINSLI.W w%d, w%d, w%d", wd, ws, m);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ ULong tmp = 0x8000000080000000ULL;
+ assign(t1,
+ binop(Iop_SarN32x4,
+ binop(Iop_64HLtoV128,
+ mkU64(tmp), mkU64(tmp)), mkU8(m)));
+ assign(t2,
+ binop(Iop_AndV128,
+ unop(Iop_NotV128, mkexpr(t1)), getWReg(wd)));
+ assign(t3,
+ binop(Iop_AndV128,
+ mkexpr(t1), getWReg(ws)));
+ putWReg(wd,
+ binop(Iop_OrV128,
+ mkexpr(t2), mkexpr(t3)));
+ break;
+ }
- assign(t3, unop(Iop_32to8,
- binop(Iop_Sub32,
- mkU32(32),
- mkexpr(t0))));
- /* Pos least significant bits of rt. */
- assign(t7, binop(Iop_Shr32,
- binop(Iop_Shl32,
- getIReg(rt),
- mkexpr(t3)),
- mkexpr(t3)));
-
- /* Size least significant bits of rs,
- shifted to appropriate position. */
- assign(t8, binop(Iop_Shl32,
- binop(Iop_And32,
- getIReg(rs),
- unop(Iop_Not32,
- binop(Iop_Shl32,
- mkU32(0xffffffff),
- unop(Iop_32to8,
- mkexpr(t1))))),
- unop(Iop_32to8,
- mkexpr(t0))));
-
- putIReg(rt, IRExpr_ITE(binop(Iop_CmpEQ32,
- mkexpr(t0),
- mkU32(0)),
- IRExpr_ITE(binop(Iop_CmpEQ32,
- mkexpr(t1),
- mkU32(32)),
- getIReg(rs),
- binop(Iop_Or32,
- mkexpr(t6),
- mkexpr(t8))),
- IRExpr_ITE(binop(Iop_CmpEQ32,
- unop(Iop_8Uto32,
- mkexpr(t2)),
- mkU32(32)),
- binop(Iop_Or32,
- mkexpr(t7),
- mkexpr(t8)),
- binop(Iop_Or32,
- binop(Iop_Or32,
- mkexpr(t6),
- mkexpr(t7)),
- mkexpr(t8)))));
- break;
- }
- default:
- return -1;
- }
- break; /* enf of INSV */
- }
- case 0x10: { /* ADDU.QB */
- switch(sa) {
- case 0x00: { /* ADDU.QB */
- DIP("addu.qb r%u, r%u, r%u", rd, rs, rt);
- vassert(!mode64);
- t0 = newTemp(Ity_I32);
- t1 = newTemp(Ity_I1);
- t2 = newTemp(Ity_I32);
- t3 = newTemp(Ity_I1);
- t4 = newTemp(Ity_I32);
- t5 = newTemp(Ity_I1);
- t6 = newTemp(Ity_I32);
- t7 = newTemp(Ity_I1);
- t8 = newTemp(Ity_I32);
-
- /* Add rightmost bytes of rs and rt. */
- assign(t0,
- binop(Iop_Add32,
- unop(Iop_8Uto32,
- unop(Iop_16to8,
- unop(Iop_32to16, getIReg(rs)))),
- unop(Iop_8Uto32,
- unop(Iop_16to8,
- unop(Iop_32to16, getIReg(rt))))));
- /* t1 will be 1 if there is overflow, 0 otherwise. */
- assign(t1, binop(Iop_CmpEQ32,
- binop(Iop_And32,
- mkexpr(t0),
- mkU32(0x00000100)),
- mkU32(0x00000100)));
-
- /* Add bits 15-8 of rs and rt. */
- assign(t2,
- binop(Iop_Add32,
- unop(Iop_8Uto32,
- unop(Iop_16HIto8,
- unop(Iop_32to16, getIReg(rs)))),
- unop(Iop_8Uto32,
- unop(Iop_16HIto8,
- unop(Iop_32to16, getIReg(rt))))));
- /* t3 will be 1 if there is overflow, 0 otherwise. */
- assign(t3, binop(Iop_CmpEQ32,
- binop(Iop_And32,
- mkexpr(t2),
- mkU32(0x00000100)),
- mkU32(0x00000100)));
+ case 0x03: { /* BINSLI.D */
+ DIP("BINSLI.D w%d, w%d, w%d", wd, ws, m);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ ULong tmp = 0x8000000000000000ULL;
+ assign(t1,
+ binop(Iop_SarN64x2,
+ binop(Iop_64HLtoV128,
+ mkU64(tmp), mkU64(tmp)), mkU8(m)));
+ assign(t2,
+ binop(Iop_AndV128,
+ unop(Iop_NotV128, mkexpr(t1)), getWReg(wd)));
+ assign(t3,
+ binop(Iop_AndV128,
+ mkexpr(t1), getWReg(ws)));
+ putWReg(wd,
+ binop(Iop_OrV128,
+ mkexpr(t2), mkexpr(t3)));
+ break;
+ }
- /* Add bits 15-8 of rs and rt. */
- assign(t4,
- binop(Iop_Add32,
- unop(Iop_8Uto32,
- unop(Iop_16to8,
- unop(Iop_32HIto16, getIReg(rs)))),
- unop(Iop_8Uto32,
- unop(Iop_16to8,
- unop(Iop_32HIto16, getIReg(rt))))));
- /* t5 will be 1 if there is overflow, 0 otherwise. */
- assign(t5, binop(Iop_CmpEQ32,
- binop(Iop_And32,
- mkexpr(t4),
- mkU32(0x00000100)),
- mkU32(0x00000100)));
-
- /* Add bits 15-8 of rs and rt. */
- assign(t6,
- binop(Iop_Add32,
- unop(Iop_8Uto32,
- unop(Iop_16HIto8,
- unop(Iop_32HIto16, getIReg(rs)))),
- unop(Iop_8Uto32,
- unop(Iop_16HIto8,
- unop(Iop_32HIto16, getIReg(rt))))));
- /* t7 will be 1 if there is overflow, 0 otherwise. */
- assign(t7, binop(Iop_CmpEQ32,
- binop(Iop_And32,
- mkexpr(t6),
- mkU32(0x00000100)),
- mkU32(0x00000100)));
-
- assign(t8,
- binop(Iop_Or32,
- binop(Iop_Or32,
- binop(Iop_Or32,
- unop(Iop_1Sto32, mkexpr(t7)),
- unop(Iop_1Sto32, mkexpr(t5))),
- unop(Iop_1Sto32, mkexpr(t3))),
- unop(Iop_1Sto32, mkexpr(t1))));
-
- putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
- mkexpr(t8),
- mkU32(0x0)),
- getDSPControl(),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x00100000))));
-
- putIReg(rd, binop(Iop_16HLto32,
- binop(Iop_8HLto16,
- unop(Iop_32to8, mkexpr(t6)),
- unop(Iop_32to8, mkexpr(t4))),
- binop(Iop_8HLto16,
- unop(Iop_32to8, mkexpr(t2)),
- unop(Iop_32to8, mkexpr(t0)))));
- break;
- }
- case 0x1: { /* SUBU.QB */
- DIP("subu.qb r%u, r%u, r%u", rd, rs, rt);
- vassert(!mode64);
- t0 = newTemp(Ity_I32);
- t1 = newTemp(Ity_I1);
- t2 = newTemp(Ity_I32);
- t3 = newTemp(Ity_I1);
- t4 = newTemp(Ity_I32);
- t5 = newTemp(Ity_I1);
- t6 = newTemp(Ity_I32);
- t7 = newTemp(Ity_I1);
- t8 = newTemp(Ity_I32);
-
- /* Subtract rightmost bytes of rs and rt. */
- assign(t0,
- binop(Iop_Sub32,
- unop(Iop_8Uto32,
- unop(Iop_16to8,
- unop(Iop_32to16, getIReg(rs)))),
- unop(Iop_8Uto32,
- unop(Iop_16to8,
- unop(Iop_32to16, getIReg(rt))))));
- /* t1 will be 1 if there is overflow, 0 otherwise. */
- assign(t1, binop(Iop_CmpEQ32,
- binop(Iop_And32,
- mkexpr(t0),
- mkU32(0x00000100)),
- mkU32(0x00000100)));
-
- /* Subtract bits 15-8 of rs and rt. */
- assign(t2,
- binop(Iop_Sub32,
- unop(Iop_8Uto32,
- unop(Iop_16HIto8,
- unop(Iop_32to16, getIReg(rs)))),
- unop(Iop_8Uto32,
- unop(Iop_16HIto8,
- unop(Iop_32to16, getIReg(rt))))));
- /* t3 will be 1 if there is overflow, 0 otherwise. */
- assign(t3, binop(Iop_CmpEQ32,
- binop(Iop_And32,
- mkexpr(t2),
- mkU32(0x00000100)),
- mkU32(0x00000100)));
-
- /* Subtract bits 15-8 of rs and rt. */
- assign(t4,
- binop(Iop_Sub32,
- unop(Iop_8Uto32,
- unop(Iop_16to8,
- unop(Iop_32HIto16, getIReg(rs)))),
- unop(Iop_8Uto32,
- unop(Iop_16to8,
- unop(Iop_32HIto16, getIReg(rt))))));
- /* t5 will be 1 if there is overflow, 0 otherwise. */
- assign(t5, binop(Iop_CmpEQ32,
- binop(Iop_And32,
- mkexpr(t4),
- mkU32(0x00000100)),
- mkU32(0x00000100)));
-
- /* Subtract bits 15-8 of rs and rt. */
- assign(t6,
- binop(Iop_Sub32,
- unop(Iop_8Uto32,
- unop(Iop_16HIto8,
- unop(Iop_32HIto16, getIReg(rs)))),
- unop(Iop_8Uto32,
- unop(Iop_16HIto8,
- unop(Iop_32HIto16, getIReg(rt))))));
- /* t7 will be 1 if there is overflow, 0 otherwise. */
- assign(t7, binop(Iop_CmpEQ32,
- binop(Iop_And32,
- mkexpr(t6),
- mkU32(0x00000100)),
- mkU32(0x00000100)));
-
- assign(t8, binop(Iop_Or32,
- binop(Iop_Or32,
- binop(Iop_Or32,
- unop(Iop_1Sto32, mkexpr(t7)),
- unop(Iop_1Sto32, mkexpr(t5))),
- unop(Iop_1Sto32, mkexpr(t3))),
- unop(Iop_1Sto32, mkexpr(t1))));
-
- putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
- mkexpr(t8),
- mkU32(0x0)),
- getDSPControl(),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x00100000))));
-
- putIReg(rd, binop(Iop_16HLto32,
- binop(Iop_8HLto16,
- unop(Iop_32to8, mkexpr(t6)),
- unop(Iop_32to8, mkexpr(t4))),
- binop(Iop_8HLto16,
- unop(Iop_32to8, mkexpr(t2)),
- unop(Iop_32to8, mkexpr(t0)))));
- break;
- }
- case 0x04: { /* ADDU_S.QB */
- DIP("addu_s.qb r%u, r%u, r%u", rd, rs, rt);
- vassert(!mode64);
- t0 = newTemp(Ity_I32);
- t1 = newTemp(Ity_I1);
- t2 = newTemp(Ity_I8);
- t3 = newTemp(Ity_I32);
- t4 = newTemp(Ity_I1);
- t5 = newTemp(Ity_I8);
- t6 = newTemp(Ity_I32);
- t7 = newTemp(Ity_I1);
- t8 = newTemp(Ity_I8);
- t9 = newTemp(Ity_I32);
- t10 = newTemp(Ity_I1);
- t11 = newTemp(Ity_I8);
- t12 = newTemp(Ity_I32);
-
- /* Add rightmost bytes of rs and rt. */
- assign(t0,
- binop(Iop_Add32,
- unop(Iop_8Uto32,
- unop(Iop_16to8,
- unop(Iop_32to16, getIReg(rs)))),
- unop(Iop_8Uto32,
- unop(Iop_16to8,
- unop(Iop_32to16, getIReg(rt))))));
- /* t1 will be 1 if there is overflow, 0 otherwise. */
- assign(t1, binop(Iop_CmpEQ32,
- binop(Iop_And32,
- mkexpr(t0),
- mkU32(0x00000100)),
- mkU32(0x00000100)));
- /* Saturate if necessary. */
- assign(t2, IRExpr_ITE(mkexpr(t1),
- mkU8(0xff),
- unop(Iop_32to8, mkexpr(t0))));
-
- /* Add bits 15-8 of rs and rt. */
- assign(t3,
- binop(Iop_Add32,
- unop(Iop_8Uto32,
- unop(Iop_16HIto8,
- unop(Iop_32to16, getIReg(rs)))),
- unop(Iop_8Uto32,
- unop(Iop_16HIto8,
- unop(Iop_32to16, getIReg(rt))))));
- /* t4 will be 1 if there is overflow, 0 otherwise. */
- assign(t4, binop(Iop_CmpEQ32,
- binop(Iop_And32,
- mkexpr(t3),
- mkU32(0x00000100)),
- mkU32(0x00000100)));
- /* Saturate if necessary. */
- assign(t5, IRExpr_ITE(mkexpr(t4),
- mkU8(0xff),
- unop(Iop_32to8, mkexpr(t3))));
-
- /* Add bits 15-8 of rs and rt. */
- assign(t6,
- binop(Iop_Add32,
- unop(Iop_8Uto32,
- unop(Iop_16to8,
- unop(Iop_32HIto16, getIReg(rs)))),
- unop(Iop_8Uto32,
- unop(Iop_16to8,
- unop(Iop_32HIto16, getIReg(rt))))));
- /* t7 will be 1 if there is overflow, 0 otherwise. */
- assign(t7, binop(Iop_CmpEQ32,
- binop(Iop_And32,
- mkexpr(t6),
- mkU32(0x00000100)),
- mkU32(0x00000100)));
- /* Saturate if necessary. */
- assign(t8, IRExpr_ITE(mkexpr(t7),
- mkU8(0xff),
- unop(Iop_32to8, mkexpr(t6))));
-
- /* Add bits 15-8 of rs and rt. */
- assign(t9,
- binop(Iop_Add32,
- unop(Iop_8Uto32,
- unop(Iop_16HIto8,
- unop(Iop_32HIto16, getIReg(rs)))),
- unop(Iop_8Uto32,
- unop(Iop_16HIto8,
- unop(Iop_32HIto16, getIReg(rt))))));
- /* t10 will be 1 if there is overflow, 0 otherwise. */
- assign(t10, binop(Iop_CmpEQ32,
- binop(Iop_And32,
- mkexpr(t9),
- mkU32(0x00000100)),
- mkU32(0x00000100)));
- /* Saturate if necessary. */
- assign(t11, IRExpr_ITE(mkexpr(t10),
- mkU8(0xff),
- unop(Iop_32to8, mkexpr(t9))));
-
- assign(t12,
- binop(Iop_Or32,
- binop(Iop_Or32,
- binop(Iop_Or32,
- unop(Iop_1Sto32, mkexpr(t10)),
- unop(Iop_1Sto32, mkexpr(t7))),
- unop(Iop_1Sto32, mkexpr(t4))),
- unop(Iop_1Sto32, mkexpr(t1))));
-
- putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
- mkexpr(t12),
- mkU32(0x0)),
- getDSPControl(),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x00100000))));
-
- putIReg(rd,
- binop(Iop_16HLto32,
- binop(Iop_8HLto16, mkexpr(t11), mkexpr(t8)),
- binop(Iop_8HLto16, mkexpr(t5), mkexpr(t2))));
- break;
- }
- case 0x05: { /* SUBU_S.QB */
- DIP("subu_s.qb r%u, r%u, r%u", rd, rs, rt);
- vassert(!mode64);
- t1 = newTemp(Ity_I32);
- t2 = newTemp(Ity_I1);
- t3 = newTemp(Ity_I1);
- t4 = newTemp(Ity_I1);
- t5 = newTemp(Ity_I1);
- t6 = newTemp(Ity_I32);
- t7 = newTemp(Ity_I32);
- t8 = newTemp(Ity_I32);
- t9 = newTemp(Ity_I32);
-
- /* Use C function to easily calculate the result
- and write it in the register more conveniently
- Underflow is checked using step by step subtraction. */
- assign(t1, binop(Iop_QSub8Ux4, getIReg(rs), getIReg(rt)));
-
- /* Subtract each byte of rs and rt. */
- assign(t6,
- binop(Iop_Sub32,
- unop(Iop_8Uto32,
- unop(Iop_16to8,
- unop(Iop_32to16, getIReg(rs)))),
- unop(Iop_8Uto32,
- unop(Iop_16to8,
- unop(Iop_32to16, getIReg(rt))))));
- assign(t7,
- binop(Iop_Sub32,
- unop(Iop_8Uto32,
- unop(Iop_16HIto8,
- unop(Iop_32to16, getIReg(rs)))),
- unop(Iop_8Uto32,
- unop(Iop_16HIto8,
- unop(Iop_32to16, getIReg(rt))))));
- assign(t8,
- binop(Iop_Sub32,
- unop(Iop_8Uto32,
- unop(Iop_16to8,
- unop(Iop_32HIto16, getIReg(rs)))),
- unop(Iop_8Uto32,
- unop(Iop_16to8,
- unop(Iop_32HIto16, getIReg(rt))))));
- assign(t9,
- binop(Iop_Sub32,
- unop(Iop_8Uto32,
- unop(Iop_16HIto8,
- unop(Iop_32HIto16, getIReg(rs)))),
- unop(Iop_8Uto32,
- unop(Iop_16HIto8,
- unop(Iop_32HIto16, getIReg(rt))))));
-
- /* Put 1 to bit 20 in DSPControl if there is underflow
- in either byte. */
- assign(t2, binop(Iop_CmpEQ32,
- binop(Iop_And32,
- mkexpr(t6),
- mkU32(0x00000100)),
- mkU32(0x00000100)));
- putDSPControl(IRExpr_ITE(mkexpr(t2),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x00100000)),
- getDSPControl()));
- assign(t3, binop(Iop_CmpEQ32,
- binop(Iop_And32,
- mkexpr(t7),
- mkU32(0x00000100)),
- mkU32(0x00000100)));
- putDSPControl(IRExpr_ITE(mkexpr(t3),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x00100000)),
- getDSPControl()));
- assign(t4, binop(Iop_CmpEQ32,
- binop(Iop_And32,
- mkexpr(t8),
- mkU32(0x00000100)),
- mkU32(0x00000100)));
- putDSPControl(IRExpr_ITE(mkexpr(t4),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x00100000)),
- getDSPControl()));
- assign(t5, binop(Iop_CmpEQ32,
- binop(Iop_And32,
- mkexpr(t9),
- mkU32(0x00000100)),
- mkU32(0x00000100)));
- putDSPControl(IRExpr_ITE(mkexpr(t5),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x00100000)),
- getDSPControl()));
- putIReg(rd, mkexpr(t1));
- break;
- }
- case 0x6: { /* MULEU_S.PH.QBL */
- DIP("muleu_s.ph.qbl r%u, r%u, r%u", rd, rs, rt);
- vassert(!mode64);
- t0 = newTemp(Ity_I32);
- t1 = newTemp(Ity_I32);
- t2 = newTemp(Ity_I1);
- t3 = newTemp(Ity_I1);
-
- assign(t0,
- unop(Iop_64to32,
- binop(Iop_MullU32,
- unop(Iop_8Uto32,
- unop(Iop_16HIto8,
- unop(Iop_32HIto16,
- getIReg(rs)))),
- unop(Iop_16Uto32,
- unop(Iop_32HIto16, getIReg(rt))))));
- assign(t1,
- unop(Iop_64to32,
- binop(Iop_MullU32,
- unop(Iop_8Uto32,
- unop(Iop_16to8,
- unop(Iop_32HIto16,
- getIReg(rs)))),
- unop(Iop_16Uto32,
- unop(Iop_32to16, getIReg(rt))))));
-
- assign(t2, binop(Iop_CmpNE32,
- mkU32(0x0),
- binop(Iop_And32,
- mkexpr(t0),
- mkU32(0x03ff0000))));
- assign(t3, binop(Iop_CmpNE32,
- mkU32(0x0),
- binop(Iop_And32,
- mkexpr(t1),
- mkU32(0x03ff0000))));
- putDSPControl(IRExpr_ITE(mkexpr(t2),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x200000)),
- IRExpr_ITE(mkexpr(t3),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x200000)),
- getDSPControl())));
- putIReg(rd,
- binop(Iop_16HLto32,
- IRExpr_ITE(mkexpr(t2),
- mkU16(0xffff),
- unop(Iop_32to16, mkexpr(t0))),
- IRExpr_ITE(mkexpr(t3),
- mkU16(0xffff),
- unop(Iop_32to16, mkexpr(t1)))));
- break;
- }
- case 0x7: { /* MULEU_S.PH.QBR */
- DIP("muleu_s.ph.qbr r%u, r%u, r%u", rd, rs, rt);
- vassert(!mode64);
- t0 = newTemp(Ity_I32);
- t1 = newTemp(Ity_I32);
- t2 = newTemp(Ity_I1);
- t3 = newTemp(Ity_I1);
-
- assign(t0, unop(Iop_64to32,
- binop(Iop_MullU32,
- unop(Iop_8Uto32,
- unop(Iop_16HIto8,
- unop(Iop_32to16,
- getIReg(rs)))),
- unop(Iop_16Uto32,
- unop(Iop_32HIto16,
- getIReg(rt))))));
- assign(t1, unop(Iop_64to32,
- binop(Iop_MullU32,
- unop(Iop_8Uto32,
- unop(Iop_16to8,
- unop(Iop_32to16,
- getIReg(rs)))),
- unop(Iop_16Uto32,
- unop(Iop_32to16,
- getIReg(rt))))));
-
- assign(t2, binop(Iop_CmpNE32,
- mkU32(0x0),
- binop(Iop_And32,
- mkexpr(t0),
- mkU32(0x03ff0000))));
- assign(t3, binop(Iop_CmpNE32,
- mkU32(0x0),
- binop(Iop_And32,
- mkexpr(t1),
- mkU32(0x03ff0000))));
- putDSPControl(IRExpr_ITE(mkexpr(t2),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x200000)),
- IRExpr_ITE(mkexpr(t3),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x200000)),
- getDSPControl())));
- putIReg(rd, binop(Iop_16HLto32,
- IRExpr_ITE(mkexpr(t2),
- mkU16(0xffff),
- unop(Iop_32to16,
- mkexpr(t0))),
- IRExpr_ITE(mkexpr(t3),
- mkU16(0xffff),
- unop(Iop_32to16,
- mkexpr(t1)))));
- break;
- }
- case 0x08: { /* ADDU.PH */
- DIP("addu.ph r%u, r%u, r%u", rd, rs, rt);
- vassert(!mode64);
- t0 = newTemp(Ity_I32);
- t1 = newTemp(Ity_I1);
- t2 = newTemp(Ity_I32);
- t3 = newTemp(Ity_I1);
-
- /* Add lower halves. */
- assign(t0, binop(Iop_Add32,
- unop(Iop_16Uto32,
- unop(Iop_32to16, getIReg(rs))),
- unop(Iop_16Uto32,
- unop(Iop_32to16, getIReg(rt)))));
-
- /* Detect overflow. */
- assign(t1, binop(Iop_CmpLT32U,
- unop(Iop_16Uto32,
- unop(Iop_32to16, mkexpr(t0))),
- unop(Iop_16Uto32,
- unop(Iop_32to16, getIReg(rs)))));
-
- putDSPControl(IRExpr_ITE(mkexpr(t1),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x00100000)),
- getDSPControl()));
-
- /* Add higher halves. */
- assign(t2, binop(Iop_Add32,
- unop(Iop_16Uto32,
- unop(Iop_32HIto16, getIReg(rs))),
- unop(Iop_16Uto32,
- unop(Iop_32HIto16, getIReg(rt)))));
-
- /* Detect overflow. */
- assign(t3, binop(Iop_CmpLT32U,
- unop(Iop_16Uto32,
- unop(Iop_32to16, mkexpr(t2))),
- unop(Iop_16Uto32,
- unop(Iop_32HIto16,
- getIReg(rs)))));
-
- putDSPControl(IRExpr_ITE(mkexpr(t3),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x00100000)),
- getDSPControl()));
-
- putIReg(rd, binop(Iop_16HLto32,
- unop(Iop_32to16, mkexpr(t2)),
- unop(Iop_32to16, mkexpr(t0))));
- break;
- }
- case 0x9: { /* SUBU.PH */
- DIP("subu.ph r%u, r%u, r%u", rd, rs, rt);
- vassert(!mode64);
- t0 = newTemp(Ity_I32);
- t1 = newTemp(Ity_I1);
- t2 = newTemp(Ity_I32);
- t3 = newTemp(Ity_I1);
-
- /* Substract lower halves. */
- assign(t0, binop(Iop_Sub32,
- unop(Iop_16Uto32,
- unop(Iop_32to16, getIReg(rs))),
- unop(Iop_16Uto32,
- unop(Iop_32to16, getIReg(rt)))));
-
- /* Detect underflow. */
- assign(t1, binop(Iop_CmpNE32,
- binop(Iop_And32,
- mkexpr(t0),
- mkU32(0x00010000)),
- mkU32(0x0)));
-
- putDSPControl(IRExpr_ITE(mkexpr(t1),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x00100000)),
- getDSPControl()));
-
- /* Subtract higher halves. */
- assign(t2, binop(Iop_Sub32,
- unop(Iop_16Uto32,
- unop(Iop_32HIto16, getIReg(rs))),
- unop(Iop_16Uto32,
- unop(Iop_32HIto16, getIReg(rt)))));
-
- /* Detect underflow. */
- assign(t3, binop(Iop_CmpNE32,
- binop(Iop_And32,
- mkexpr(t2),
- mkU32(0x00010000)),
- mkU32(0x0)));
-
- putDSPControl(IRExpr_ITE(mkexpr(t3),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x00100000)),
- getDSPControl()));
-
- putIReg(rd, binop(Iop_16HLto32,
- unop(Iop_32to16, mkexpr(t2)),
- unop(Iop_32to16, mkexpr(t0))));
- break;
- }
- case 0xA: { /* ADDQ.PH */
- DIP("addq.ph r%u, r%u, r%u", rd, rs, rt);
- vassert(!mode64);
- t0 = newTemp(Ity_I32);
- t1 = newTemp(Ity_I1);
- t2 = newTemp(Ity_I32);
- t3 = newTemp(Ity_I1);
- t6 = newTemp(Ity_I32);
- t7 = newTemp(Ity_I32);
-
- /* Add lower halves. */
- assign(t0, binop(Iop_Add32,
- unop(Iop_16Sto32,
- unop(Iop_32to16, getIReg(rs))),
- unop(Iop_16Sto32,
- unop(Iop_32to16, getIReg(rt)))));
-
- /* Bit 16 of the result. */
- assign(t6, binop(Iop_And32,
- unop(Iop_16Uto32,
- unop(Iop_32HIto16, mkexpr(t0))),
- mkU32(0x1)));
- /* Detect overflow. */
- assign(t1, binop(Iop_CmpNE32,
- binop(Iop_Shr32,
- binop(Iop_And32,
- mkexpr(t0),
- mkU32(0x8000)),
- mkU8(15)),
- mkexpr(t6)));
-
- putDSPControl(IRExpr_ITE(mkexpr(t1),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x00100000)),
- getDSPControl()));
-
- /* Add higher halves. */
- assign(t2, binop(Iop_Add32,
- unop(Iop_16Sto32,
- unop(Iop_32HIto16, getIReg(rs))),
- unop(Iop_16Sto32,
- unop(Iop_32HIto16, getIReg(rt)))));
-
- /* Bit 16 of the result. */
- assign(t7, binop(Iop_And32,
- unop(Iop_16Uto32,
- unop(Iop_32HIto16, mkexpr(t2))),
- mkU32(0x1)));
- /* Detect overflow. */
- assign(t3, binop(Iop_CmpNE32,
- binop(Iop_Shr32,
- binop(Iop_And32,
- mkexpr(t2),
- mkU32(0x00008000)),
- mkU8(15)),
- mkexpr(t7)));
+ default:
+ return -1;
+ }
- putDSPControl(IRExpr_ITE(mkexpr(t3),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x00100000)),
- getDSPControl()));
+ break;
+ }
- putIReg(rd, binop(Iop_16HLto32,
- unop(Iop_32to16, mkexpr(t2)),
- unop(Iop_32to16, mkexpr(t0))));
- break;
- }
- case 0xB: { /* SUBQ.PH */
- DIP("subq.ph r%u, r%u, r%u", rd, rs, rt);
- vassert(!mode64);
- t0 = newTemp(Ity_I32);
- t1 = newTemp(Ity_I1);
- t2 = newTemp(Ity_I32);
- t3 = newTemp(Ity_I1);
- t6 = newTemp(Ity_I32);
- t7 = newTemp(Ity_I32);
-
- /* Subtract lower halves. */
- assign(t0, binop(Iop_Sub32,
- unop(Iop_16Sto32,
- unop(Iop_32to16, getIReg(rs))),
- unop(Iop_16Sto32,
- unop(Iop_32to16, getIReg(rt)))));
-
- /* Bit 16 of the result. */
- assign(t6, binop(Iop_And32,
- unop(Iop_16Uto32,
- unop(Iop_32HIto16, mkexpr(t0))),
- mkU32(0x1)));
- /* Compare the signs of input value and the result. */
- assign(t1, binop(Iop_CmpNE32,
- binop(Iop_Shr32,
- binop(Iop_And32,
- mkexpr(t0),
- mkU32(0x8000)),
- mkU8(15)),
- mkexpr(t6)));
-
- putDSPControl(IRExpr_ITE(mkexpr(t1),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x00100000)),
- getDSPControl()));
-
- /* Subtract higher halves. */
- assign(t2, binop(Iop_Sub32,
- unop(Iop_16Sto32,
- unop(Iop_32HIto16, getIReg(rs))),
- unop(Iop_16Sto32,
- unop(Iop_32HIto16, getIReg(rt)))));
-
- /* Bit 16 of the result. */
- assign(t7, binop(Iop_And32,
- unop(Iop_16Uto32,
- unop(Iop_32HIto16, mkexpr(t2))),
- mkU32(0x1)));
- /* Compare the signs of input value and the result. */
- assign(t3, binop(Iop_CmpNE32,
- binop(Iop_Shr32,
- binop(Iop_And32,
- mkexpr(t2),
- mkU32(0x00008000)),
- mkU8(15)),
- mkexpr(t7)));
+ case 0x07: {
+ switch (df) {
+ case 0x00: { /* BINSRI.B */
+ DIP("BINSRI.B w%d, w%d, w%d", wd, ws, m);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ ULong tmp = 0xFEFEFEFEFEFEFEFEULL;
+ assign(t1,
+ binop(Iop_ShlN8x16,
+ binop(Iop_64HLtoV128,
+ mkU64(tmp), mkU64(tmp)), mkU8(m)));
+ assign(t2,
+ binop(Iop_AndV128,
+ unop(Iop_NotV128, mkexpr(t1)), getWReg(ws)));
+ assign(t3,
+ binop(Iop_AndV128,
+ mkexpr(t1), getWReg(wd)));
+ putWReg(wd,
+ binop(Iop_OrV128,
+ mkexpr(t2), mkexpr(t3)));
+ break;
+ }
- putDSPControl(IRExpr_ITE(mkexpr(t3),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x00100000)),
- getDSPControl()));
+ case 0x01: { /* BINSRI.H */
+ DIP("BINSRI.H w%d, w%d, w%d", wd, ws, m);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ ULong tmp = 0xFFFEFFFEFFFEFFFEULL;
+ assign(t1,
+ binop(Iop_ShlN16x8,
+ binop(Iop_64HLtoV128,
+ mkU64(tmp), mkU64(tmp)),
+ mkU8(m)));
+ assign(t2,
+ binop(Iop_AndV128,
+ unop(Iop_NotV128, mkexpr(t1)),
+ getWReg(ws)));
+ assign(t3,
+ binop(Iop_AndV128,
+ mkexpr(t1), getWReg(wd)));
+ putWReg(wd,
+ binop(Iop_OrV128,
+ mkexpr(t2), mkexpr(t3)));
+ break;
+ }
- putIReg(rd, binop(Iop_16HLto32,
- unop(Iop_32to16, mkexpr(t2)),
- unop(Iop_32to16, mkexpr(t0))));
- break;
- }
- case 0xC: { /* ADDU_S.PH */
- DIP("addu_s.ph r%u, r%u, r%u", rd, rs, rt);
- vassert(!mode64);
- t0 = newTemp(Ity_I32);
- t1 = newTemp(Ity_I1);
- t2 = newTemp(Ity_I32);
- t3 = newTemp(Ity_I1);
-
- /* Add lower halves. */
- assign(t0, binop(Iop_Add32,
- unop(Iop_16Uto32,
- unop(Iop_32to16, getIReg(rs))),
- unop(Iop_16Uto32,
- unop(Iop_32to16, getIReg(rt)))));
-
- /* Detect overflow. */
- assign(t1, binop(Iop_CmpLT32U,
- unop(Iop_16Uto32,
- unop(Iop_32to16, mkexpr(t0))),
- unop(Iop_16Uto32,
- unop(Iop_32to16, getIReg(rs)))));
-
- putDSPControl(IRExpr_ITE(mkexpr(t1),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x00100000)),
- getDSPControl()));
-
- /* Add higher halves. */
- assign(t2, binop(Iop_Add32,
- unop(Iop_16Uto32,
- unop(Iop_32HIto16, getIReg(rs))),
- unop(Iop_16Uto32,
- unop(Iop_32HIto16, getIReg(rt)))));
-
- /* Detect overflow. */
- assign(t3, binop(Iop_CmpLT32U,
- unop(Iop_16Uto32,
- unop(Iop_32to16, mkexpr(t2))),
- unop(Iop_16Uto32,
- unop(Iop_32HIto16, getIReg(rs)))));
-
- putDSPControl(IRExpr_ITE(mkexpr(t3),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x00100000)),
- getDSPControl()));
-
- putIReg(rd, binop(Iop_16HLto32,
- IRExpr_ITE(mkexpr(t3),
- mkU16(0xffff),
- unop(Iop_32to16,
- mkexpr(t2))),
- IRExpr_ITE(mkexpr(t1),
- mkU16(0xffff),
- unop(Iop_32to16,
- mkexpr(t0)))));
- break;
- }
- case 0xD: { /* SUBU_S.PH */
- DIP("subu_s.ph r%u, r%u, r%u", rd, rs, rt);
- vassert(!mode64);
- t0 = newTemp(Ity_I32);
- t1 = newTemp(Ity_I1);
- t2 = newTemp(Ity_I32);
- t3 = newTemp(Ity_I1);
-
- /* Subtract lower halves. */
- assign(t0, binop(Iop_Sub32,
- unop(Iop_16Uto32,
- unop(Iop_32to16, getIReg(rs))),
- unop(Iop_16Uto32,
- unop(Iop_32to16, getIReg(rt)))));
-
- /* Detect underflow. */
- assign(t1, binop(Iop_CmpNE32,
- binop(Iop_And32,
- mkexpr(t0), mkU32(0x00010000)),
- mkU32(0x0)));
-
- putDSPControl(IRExpr_ITE(mkexpr(t1),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x00100000)),
- getDSPControl()));
-
- /* Subtract higher halves. */
- assign(t2, binop(Iop_Sub32,
- unop(Iop_16Uto32,
- unop(Iop_32HIto16, getIReg(rs))),
- unop(Iop_16Uto32,
- unop(Iop_32HIto16, getIReg(rt)))));
-
- /* Detect underflow. */
- assign(t3, binop(Iop_CmpNE32,
- binop(Iop_And32,
- mkexpr(t2), mkU32(0x00010000)),
- mkU32(0x0)));
-
- putDSPControl(IRExpr_ITE(mkexpr(t3),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x00100000)),
- getDSPControl()));
-
- putIReg(rd,
- binop(Iop_16HLto32,
- IRExpr_ITE(mkexpr(t3),
- mkU16(0x0000),
- unop(Iop_32to16, mkexpr(t2))),
- IRExpr_ITE(mkexpr(t1),
- mkU16(0x0000),
- unop(Iop_32to16, mkexpr(t0)))));
- break;
- }
- case 0xE: { /* ADDQ_S.PH */
- DIP("addq_s.ph r%u r%u, r%u", rd, rs, rt);
- vassert(!mode64);
- t0 = newTemp(Ity_I32);
- t1 = newTemp(Ity_I1);
- t2 = newTemp(Ity_I32);
- t3 = newTemp(Ity_I1);
- t4 = newTemp(Ity_I16);
- t5 = newTemp(Ity_I16);
- t6 = newTemp(Ity_I32);
- t7 = newTemp(Ity_I32);
-
- /* Add lower halves. */
- assign(t0, binop(Iop_Add32,
- unop(Iop_16Sto32,
- unop(Iop_32to16, getIReg(rs))),
- unop(Iop_16Sto32,
- unop(Iop_32to16, getIReg(rt)))));
-
- /* Bit 16 of the result. */
- assign(t6, binop(Iop_And32,
- unop(Iop_16Uto32,
- unop(Iop_32HIto16, mkexpr(t0))),
- mkU32(0x1)));
- /* Detect overflow. */
- assign(t1, binop(Iop_CmpNE32,
- binop(Iop_Shr32,
- binop(Iop_And32,
- mkexpr(t0),
- mkU32(0x8000)),
- mkU8(15)),
- mkexpr(t6)));
-
- putDSPControl(IRExpr_ITE(mkexpr(t1),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x00100000)),
- getDSPControl()));
- /* Saturate if needed. */
- assign(t4, IRExpr_ITE(mkexpr(t1),
- IRExpr_ITE(binop(Iop_CmpEQ32,
- mkexpr(t6),
- mkU32(0x0)),
- mkU16(0x7fff),
- mkU16(0x8000)),
- unop(Iop_32to16, mkexpr(t0))));
-
- /* Add higher halves. */
- assign(t2, binop(Iop_Add32,
- unop(Iop_16Sto32,
- unop(Iop_32HIto16, getIReg(rs))),
- unop(Iop_16Sto32,
- unop(Iop_32HIto16, getIReg(rt)))));
-
- /* Bit 16 of the result. */
- assign(t7, binop(Iop_And32,
- unop(Iop_16Uto32,
- unop(Iop_32HIto16, mkexpr(t2))),
- mkU32(0x1)));
- /* Detect overflow. */
- assign(t3, binop(Iop_CmpNE32,
- binop(Iop_Shr32,
- binop(Iop_And32,
- mkexpr(t2),
- mkU32(0x00008000)),
- mkU8(15)),
- mkexpr(t7)));
-
- putDSPControl(IRExpr_ITE(mkexpr(t3),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x00100000)),
- getDSPControl()));
- /* Saturate if needed. */
- assign(t5, IRExpr_ITE(mkexpr(t3),
- IRExpr_ITE(binop(Iop_CmpEQ32,
- mkexpr(t7),
- mkU32(0x0)),
- mkU16(0x7fff),
- mkU16(0x8000)),
- unop(Iop_32to16, mkexpr(t2))));
-
- putIReg(rd, binop(Iop_16HLto32, mkexpr(t5), mkexpr(t4)));
- break;
- }
- case 0xF: { /* SUBQ_S.PH */
- DIP("subq_s.ph r%u r%u, r%u", rd, rs, rt);
- vassert(!mode64);
- t0 = newTemp(Ity_I32);
- t1 = newTemp(Ity_I1);
- t2 = newTemp(Ity_I32);
- t3 = newTemp(Ity_I1);
- t4 = newTemp(Ity_I16);
- t5 = newTemp(Ity_I16);
- t6 = newTemp(Ity_I32);
- t7 = newTemp(Ity_I32);
-
- /* Subtract lower halves. */
- assign(t0, binop(Iop_Sub32,
- unop(Iop_16Sto32,
- unop(Iop_32to16, getIReg(rs))),
- unop(Iop_16Sto32,
- unop(Iop_32to16, getIReg(rt)))));
-
- /* Bit 16 of the result. */
- assign(t6, binop(Iop_And32,
- unop(Iop_16Uto32,
- unop(Iop_32HIto16, mkexpr(t0))),
- mkU32(0x1)));
- /* Detect overflow or underflow. */
- assign(t1, binop(Iop_CmpNE32,
- binop(Iop_Shr32,
- binop(Iop_And32,
- mkexpr(t0),
- mkU32(0x8000)),
- mkU8(15)),
- mkexpr(t6)));
-
- putDSPControl(IRExpr_ITE(mkexpr(t1),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x00100000)),
- getDSPControl()));
- /* Saturate if needed. */
- assign(t4, IRExpr_ITE(mkexpr(t1),
- IRExpr_ITE(binop(Iop_CmpEQ32,
- mkexpr(t6),
- mkU32(0x0)),
- mkU16(0x7fff),
- mkU16(0x8000)),
- unop(Iop_32to16, mkexpr(t0))));
-
- /* Subtract higher halves. */
- assign(t2, binop(Iop_Sub32,
- unop(Iop_16Sto32,
- unop(Iop_32HIto16, getIReg(rs))),
- unop(Iop_16Sto32,
- unop(Iop_32HIto16, getIReg(rt)))));
-
- /* Bit 16 of the result. */
- assign(t7, binop(Iop_And32,
- unop(Iop_16Uto32,
- unop(Iop_32HIto16, mkexpr(t2))),
- mkU32(0x1)));
- /* Detect overflow or underflow. */
- assign(t3, binop(Iop_CmpNE32,
- binop(Iop_Shr32,
- binop(Iop_And32,
- mkexpr(t2),
- mkU32(0x00008000)),
- mkU8(15)),
- mkexpr(t7)));
-
- putDSPControl(IRExpr_ITE(mkexpr(t3),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x00100000)),
- getDSPControl()));
- /* Saturate if needed. */
- assign(t5, IRExpr_ITE(mkexpr(t3),
- IRExpr_ITE(binop(Iop_CmpEQ32,
- mkexpr(t7),
- mkU32(0x0)),
- mkU16(0x7fff),
- mkU16(0x8000)),
- unop(Iop_32to16, mkexpr(t2))));
-
- putIReg(rd, binop(Iop_16HLto32, mkexpr(t5), mkexpr(t4)));
- break;
- }
- case 0x10: { /* ADDSC */
- DIP("addsc r%u, r%u, r%u", rd, rs, rt);
- vassert(!mode64);
- t0 = newTemp(Ity_I64);
- t1 = newTemp(Ity_I1);
-
- /* The carry bit result out of the addition operation is
- written to bit 13(the c field) of the DSPControl reg. */
- assign(t0, binop(Iop_Add64,
- unop(Iop_32Uto64, getIReg(rs)),
- unop(Iop_32Uto64, getIReg(rt))));
-
- assign(t1, binop(Iop_CmpEQ32,
- binop(Iop_And32,
- unop(Iop_64HIto32, mkexpr(t0)),
- mkU32(0x1)),
- mkU32(0x1)));
- putDSPControl(IRExpr_ITE(mkexpr(t1),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x2000)),
- binop(Iop_And32,
- getDSPControl(),
- mkU32(0xffffdfff))));
-
- putIReg(rd, unop(Iop_64to32, mkexpr(t0)));
- break;
- }
- case 0x11: { /* ADDWC */
- DIP("addwc r%u, r%u, r%u", rd, rs, rt);
- vassert(!mode64);
- t0 = newTemp(Ity_I32);
- t1 = newTemp(Ity_I64);
- t2 = newTemp(Ity_I32);
- t3 = newTemp(Ity_I32);
- t4 = newTemp(Ity_I1);
-
- /* Get carry bit from DSPControl register. */
- assign(t0, binop(Iop_Shr32,
- binop(Iop_And32,
- getDSPControl(),
- mkU32(0x2000)),
- mkU8(0xd)));
- assign(t1, binop(Iop_Add64,
- unop(Iop_32Sto64, getIReg(rs)),
- unop(Iop_32Sto64,
- binop(Iop_Add32,
- getIReg(rt),
- mkexpr(t0)))));
-
- /* Extract bits 32 and 31. */
- assign(t2, binop(Iop_And32,
- unop(Iop_64HIto32, mkexpr(t1)),
- mkU32(0x1)));
- assign(t3, binop(Iop_Shr32,
- binop(Iop_And32,
- unop(Iop_64to32, mkexpr(t1)),
- mkU32(0x80000000)),
- mkU8(31)));
- assign(t4, binop(Iop_CmpNE32, mkexpr(t2), mkexpr(t3)));
-
- putDSPControl(IRExpr_ITE(mkexpr(t4),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x00100000)),
- getDSPControl()));
- putIReg(rd, unop(Iop_64to32, mkexpr(t1)));
- break;
- }
- case 0x12: { /* MODSUB */
- DIP("modsub r%u, r%u, r%u", rd, rs, rt);
- vassert(!mode64);
- t0 = newTemp(Ity_I32);
- t1 = newTemp(Ity_I32);
- t2 = newTemp(Ity_I32);
-
- /* decr_7..0 */
- assign(t0,
- unop(Iop_8Uto32,
- unop(Iop_16to8,
- unop(Iop_32to16, getIReg(rt)))));
-
- /* lastindex_15..0 */
- assign(t1,
- unop(Iop_16Uto32,
- binop(Iop_8HLto16,
- unop(Iop_16to8,
- unop(Iop_32HIto16, getIReg(rt))),
- unop(Iop_16HIto8,
- unop(Iop_32to16, getIReg(rt))))));
- /* temp_15..0 */
- assign(t2,
- IRExpr_ITE(binop(Iop_CmpEQ32,
- getIReg(rs),
- mkU32(0x00000000)),
- mkexpr(t1),
- binop(Iop_Sub32,
- getIReg(rs), mkexpr(t0))));
- putIReg(rd, mkexpr(t2));
- break;
- }
- case 0x14: { /* RADDU.W.QB */
- DIP("raddu.w.qb r%u, r%u", rd, rs);
- vassert(!mode64);
- putIReg(rd, binop(Iop_Add32,
- binop(Iop_Add32,
- unop(Iop_8Uto32,
- unop(Iop_16to8,
- unop(Iop_32to16,
- getIReg(rs)))),
- unop(Iop_8Uto32,
- unop(Iop_16HIto8,
- unop(Iop_32to16,
- getIReg(rs))))),
- binop(Iop_Add32,
- unop(Iop_8Uto32,
- unop(Iop_16to8,
- unop(Iop_32HIto16,
- getIReg(rs)))),
- unop(Iop_8Uto32,
- unop(Iop_16HIto8,
- unop(Iop_32HIto16,
- getIReg(rs)))))));
- break;
- }
- case 0x16: { /* ADDQ_S.W */
- DIP("addq_s.w r%u, r%u, r%u", rd, rs, rt);
- vassert(!mode64);
- t0 = newTemp(Ity_I64);
- t1 = newTemp(Ity_I1);
- t2 = newTemp(Ity_I32);
- t3 = newTemp(Ity_I32);
-
- assign(t0, binop(Iop_Add64,
- unop(Iop_32Sto64, getIReg(rs)),
- unop(Iop_32Sto64, getIReg(rt))));
-
- assign(t3, binop(Iop_And32,
- unop(Iop_64HIto32, mkexpr(t0)),
- mkU32(0x1)));
- assign(t1, binop(Iop_CmpNE32,
- binop(Iop_Shr32,
- binop(Iop_And32,
- unop(Iop_64to32, mkexpr(t0)),
- mkU32(0x80000000)),
- mkU8(31)),
- mkexpr(t3)));
-
- putDSPControl(IRExpr_ITE(mkexpr(t1),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x00100000)),
- getDSPControl()));
-
- putIReg(rd, IRExpr_ITE(mkexpr(t1),
- IRExpr_ITE(binop(Iop_CmpEQ32,
- mkexpr(t3),
- mkU32(0x0)),
- mkU32(0x7fffffff),
- mkU32(0x80000000)),
- unop(Iop_64to32, mkexpr(t0))));
- break;
- }
- case 0x17: { /* SUBQ_S.W */
- DIP("subq_s.w r%u, r%u, r%u", rd, rs, rt);
- vassert(!mode64);
- t0 = newTemp(Ity_I64);
- t1 = newTemp(Ity_I1);
- t2 = newTemp(Ity_I32);
- t3 = newTemp(Ity_I32);
-
- assign(t0, binop(Iop_Sub64,
- unop(Iop_32Sto64, getIReg(rs)),
- unop(Iop_32Sto64, getIReg(rt))));
-
- assign(t3, binop(Iop_And32,
- unop(Iop_64HIto32, mkexpr(t0)),
- mkU32(0x1)));
- assign(t1, binop(Iop_CmpNE32,
- binop(Iop_Shr32,
- binop(Iop_And32,
- unop(Iop_64to32, mkexpr(t0)),
- mkU32(0x80000000)),
- mkU8(31)),
- mkexpr(t3)));
-
- putDSPControl(IRExpr_ITE(mkexpr(t1),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x00100000)),
- getDSPControl()));
-
- putIReg(rd, IRExpr_ITE(mkexpr(t1),
- IRExpr_ITE(binop(Iop_CmpEQ32,
- mkexpr(t3),
- mkU32(0x0)),
- mkU32(0x7fffffff),
- mkU32(0x80000000)),
- unop(Iop_64to32, mkexpr(t0))));
- break;
- }
- case 0x1C: { /* MULEQ_S.W.PHL */
- DIP("muleq_s.w.phl r%u, r%u, r%u", rd, rs, rt);
- vassert(!mode64);
- t0 = newTemp(Ity_I32);
- t1 = newTemp(Ity_I1);
- t2 = newTemp(Ity_I1);
- t3 = newTemp(Ity_I32);
-
- assign(t0,
- binop(Iop_Shl32,
- binop(Iop_Mul32,
- unop(Iop_16Sto32,
- unop(Iop_32HIto16, getIReg(rt))),
- unop(Iop_16Sto32,
- unop(Iop_32HIto16, getIReg(rs)))),
- mkU8(0x1)));
- assign(t1, binop(Iop_CmpEQ32,
- binop(Iop_And32,
- getIReg(rt),
- mkU32(0xffff0000)),
- mkU32(0x80000000)));
- assign(t2, binop(Iop_CmpEQ32,
- binop(Iop_And32,
- getIReg(rs),
- mkU32(0xffff0000)),
- mkU32(0x80000000)));
- assign(t3, IRExpr_ITE(mkexpr(t1),
- IRExpr_ITE(mkexpr(t2),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x00200000)),
- getDSPControl()),
- getDSPControl()));
- putDSPControl(mkexpr(t3));
-
- putIReg(rd, IRExpr_ITE(mkexpr(t1),
- IRExpr_ITE(mkexpr(t2),
- mkU32(0x7fffffff),
- mkexpr(t0)),
- mkexpr(t0)));
- break;
- }
- case 0x1D: { /* MULEQ_S.W.PHR */
- DIP("muleq_s.w.phr r%u, r%u, r%u", rd, rs, rt);
- vassert(!mode64);
- t0 = newTemp(Ity_I32);
- t1 = newTemp(Ity_I1);
- t2 = newTemp(Ity_I1);
-
- assign(t0,
- binop(Iop_Shl32,
- binop(Iop_Mul32,
- unop(Iop_16Sto32,
- unop(Iop_32to16, getIReg(rt))),
- unop(Iop_16Sto32,
- unop(Iop_32to16, getIReg(rs)))),
- mkU8(0x1)));
- assign(t1, binop(Iop_CmpEQ32,
- binop(Iop_And32,
- getIReg(rt),
- mkU32(0xffff)),
- mkU32(0x8000)));
- assign(t2, binop(Iop_CmpEQ32,
- binop(Iop_And32,
- getIReg(rs),
- mkU32(0xffff)),
- mkU32(0x8000)));
- putDSPControl(IRExpr_ITE(mkexpr(t1),
- IRExpr_ITE(mkexpr(t2),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x00200000)
- ),
- getDSPControl()),
- getDSPControl()));
- putIReg(rd, IRExpr_ITE(mkexpr(t1),
- IRExpr_ITE(mkexpr(t2),
- mkU32(0x7fffffff),
- mkexpr(t0)),
- mkexpr(t0)));
- break;
- }
- case 0x1E: { /* MULQ_S.PH */
- DIP("mulq_s.ph r%u, r%u, r%u", rd, rs, rt);
- vassert(!mode64);
- t0 = newTemp(Ity_I32);
- t1 = newTemp(Ity_I32);
- t2 = newTemp(Ity_I16);
- t3 = newTemp(Ity_I16);
- t5 = newTemp(Ity_I32);
- t6 = newTemp(Ity_I32);
- t7 = newTemp(Ity_I32);
- t8 = newTemp(Ity_I32);
-
- assign(t5,
- unop(Iop_16Sto32, unop(Iop_32to16, getIReg(rs))));
- assign(t6,
- unop(Iop_16Sto32, unop(Iop_32to16, getIReg(rt))));
-
- assign(t7,
- unop(Iop_16Sto32, unop(Iop_32HIto16, getIReg(rs))));
- assign(t8,
- unop(Iop_16Sto32, unop(Iop_32HIto16, getIReg(rt))));
-
- assign(t0, binop(Iop_And32,
- unop(Iop_1Sto32,
- binop(Iop_CmpEQ32,
- binop(Iop_And32,
- mkexpr(t5),
- mkU32(0xffff)),
- mkU32(0x8000))),
- unop(Iop_1Sto32,
- binop(Iop_CmpEQ32,
- binop(Iop_And32,
- mkexpr(t6),
- mkU32(0xffff)),
- mkU32(0x8000)))));
- assign(t1, binop(Iop_And32,
- unop(Iop_1Sto32,
- binop(Iop_CmpEQ32,
- binop(Iop_And32,
- mkexpr(t7),
- mkU32(0xffff)),
- mkU32(0x8000))),
- unop(Iop_1Sto32,
- binop(Iop_CmpEQ32,
- binop(Iop_And32,
- mkexpr(t8),
- mkU32(0xffff)),
- mkU32(0x8000)))));
+ case 0x02: { /* BINSRI.W */
+ DIP("BINSRI.W w%d, w%d, w%d", wd, ws, m);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ ULong tmp = 0xFFFFFFFEFFFFFFFEULL;
+ assign(t1,
+ binop(Iop_ShlN32x4,
+ binop(Iop_64HLtoV128,
+ mkU64(tmp), mkU64(tmp)),
+ mkU8(m)));
+ assign(t2,
+ binop(Iop_AndV128,
+ unop(Iop_NotV128, mkexpr(t1)),
+ getWReg(ws)));
+ assign(t3,
+ binop(Iop_AndV128,
+ mkexpr(t1), getWReg(wd)));
+ putWReg(wd,
+ binop(Iop_OrV128,
+ mkexpr(t2), mkexpr(t3)));
+ break;
+ }
- putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
- binop(Iop_Or32,
- mkexpr(t0),
- mkexpr(t1)),
- mkU32(0x0)),
- getDSPControl(),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x200000))));
-
- assign(t2, unop(Iop_32HIto16,
- binop(Iop_Shl32,
- unop(Iop_64to32,
- binop(Iop_MullS32,
- mkexpr(t7),
- mkexpr(t8))),
- mkU8(0x1))));
- assign(t3, unop(Iop_32HIto16,
- binop(Iop_Shl32,
- unop(Iop_64to32,
- binop(Iop_MullS32,
- mkexpr(t5),
- mkexpr(t6))),
- mkU8(0x1))));
- putIReg(rd, binop(Iop_16HLto32,
- IRExpr_ITE(binop(Iop_CmpEQ32,
- mkexpr(t1),
- mkU32(0x0)),
- mkexpr(t2),
- mkU16(0x7fff)),
- IRExpr_ITE(binop(Iop_CmpEQ32,
- mkexpr(t0),
- mkU32(0x0)),
- mkexpr(t3),
- mkU16(0x7fff))));
- break;
- }
- case 0x1F: { /* MULQ_RS.PH */
- DIP("mulq_rs.ph r%u, r%u, r%u", rd, rs, rt);
- vassert(!mode64);
- t0 = newTemp(Ity_I32);
- t1 = newTemp(Ity_I1);
- t2 = newTemp(Ity_I1);
- t3 = newTemp(Ity_I16);
- t4 = newTemp(Ity_I32);
- t5 = newTemp(Ity_I1);
- t6 = newTemp(Ity_I1);
- t7 = newTemp(Ity_I16);
-
- /* Multiply and round lower halfwords. */
- assign(t0, binop(Iop_Add32,
- binop(Iop_Shl32,
- binop(Iop_Mul32,
- unop(Iop_16Sto32,
- unop(Iop_32to16,
- getIReg(rt))),
- unop(Iop_16Sto32,
- unop(Iop_32to16,
- getIReg(rs)))),
- mkU8(0x1)),
- mkU32(0x00008000)));
- assign(t1, binop(Iop_CmpEQ32,
- binop(Iop_And32,
- getIReg(rt), mkU32(0xffff)),
- mkU32(0x8000)));
- assign(t2, binop(Iop_CmpEQ32,
- binop(Iop_And32,
- getIReg(rs), mkU32(0xffff)),
- mkU32(0x8000)));
- putDSPControl(IRExpr_ITE(mkexpr(t1),
- IRExpr_ITE(mkexpr(t2),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x00200000)
- ),
- getDSPControl()),
- getDSPControl()));
- assign(t3, IRExpr_ITE(mkexpr(t1),
- IRExpr_ITE(mkexpr(t2),
- mkU16(0x7fff),
- unop(Iop_32HIto16,
- mkexpr(t0))),
- unop(Iop_32HIto16, mkexpr(t0))));
-
- /* Multiply and round higher halfwords. */
- assign(t4, binop(Iop_Add32,
- binop(Iop_Shl32,
- binop(Iop_Mul32,
- unop(Iop_16Sto32,
- unop(Iop_32HIto16,
- getIReg(rt))),
- unop(Iop_16Sto32,
- unop(Iop_32HIto16,
- getIReg(rs)))),
- mkU8(0x1)),
- mkU32(0x00008000)));
- assign(t5, binop(Iop_CmpEQ32,
- binop(Iop_And32,
- getIReg(rt),
- mkU32(0xffff0000)),
- mkU32(0x80000000)));
- assign(t6, binop(Iop_CmpEQ32,
- binop(Iop_And32,
- getIReg(rs),
- mkU32(0xffff0000)),
- mkU32(0x80000000)));
- putDSPControl(IRExpr_ITE(mkexpr(t5),
- IRExpr_ITE(mkexpr(t6),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x00200000)),
- getDSPControl()),
- getDSPControl()));
- assign(t7, IRExpr_ITE(mkexpr(t5),
- IRExpr_ITE(mkexpr(t6),
- mkU16(0x7fff),
- unop(Iop_32HIto16,
- mkexpr(t4))),
- unop(Iop_32HIto16, mkexpr(t4))));
-
- putIReg(rd, binop(Iop_16HLto32, mkexpr(t7), mkexpr(t3)));
- break;
- }
- default:
- return -1;
- }
- break; /* end of ADDU.QB */
- }
- case 0x11: { /* CMPU.EQ.QB */
- switch(sa) {
- case 0x0: { /* CMPU.EQ.QB */
- DIP("cmpu.eq.qb r%u, r%u", rs, rt);
- vassert(!mode64);
- t1 = newTemp(Ity_I1);
- t2 = newTemp(Ity_I1);
- t3 = newTemp(Ity_I1);
- t4 = newTemp(Ity_I1);
+ case 0x03: { /* BINSRI.D */
+ DIP("BINSRI.D w%d, w%d, w%d", wd, ws, m);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ ULong tmp = -2;
+ assign(t1,
+ binop(Iop_ShlN64x2,
+ binop(Iop_64HLtoV128,
+ mkU64(tmp), mkU64(tmp)),
+ mkU8(m)));
+ assign(t2,
+ binop(Iop_AndV128,
+ unop(Iop_NotV128, mkexpr(t1)),
+ getWReg(ws)));
+ assign(t3,
+ binop(Iop_AndV128,
+ mkexpr(t1), getWReg(wd)));
+ putWReg(wd,
+ binop(Iop_OrV128,
+ mkexpr(t2), mkexpr(t3)));
+ break;
+ }
- assign(t1,
- binop(Iop_CmpEQ32,
- binop(Iop_And32, getIReg(rs), mkU32(0xff)),
- binop(Iop_And32, getIReg(rt), mkU32(0xff))));
- putDSPControl(IRExpr_ITE(mkexpr(t1),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x01000000)),
- binop(Iop_And32,
- getDSPControl(),
- mkU32(0xfeffffff))));
-
- assign(t2, binop(Iop_CmpEQ32,
- unop(Iop_8Uto32,
- unop(Iop_16HIto8,
- unop(Iop_32to16,
- getIReg(rs)))),
- unop(Iop_8Uto32,
- unop(Iop_16HIto8,
- unop(Iop_32to16,
- getIReg(rt))))));
- putDSPControl(IRExpr_ITE(mkexpr(t2),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x02000000)),
- binop(Iop_And32,
- getDSPControl(),
- mkU32(0xfdffffff))));
-
- assign(t3, binop(Iop_CmpEQ32,
- unop(Iop_8Uto32,
- unop(Iop_16to8,
- unop(Iop_32HIto16,
- getIReg(rs)))),
- unop(Iop_8Uto32,
- unop(Iop_16to8,
- unop(Iop_32HIto16,
- getIReg(rt))))));
- putDSPControl(IRExpr_ITE(mkexpr(t3),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x04000000)),
- binop(Iop_And32,
- getDSPControl(),
- mkU32(0xfbffffff))));
-
- assign(t4, binop(Iop_CmpEQ32,
- unop(Iop_8Uto32,
- unop(Iop_16HIto8,
- unop(Iop_32HIto16,
- getIReg(rs)))),
- unop(Iop_8Uto32,
- unop(Iop_16HIto8,
- unop(Iop_32HIto16,
- getIReg(rt))))));
- putDSPControl(IRExpr_ITE(mkexpr(t4),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x08000000)),
- binop(Iop_And32,
- getDSPControl(),
- mkU32(0xf7ffffff))));
- break;
- }
- case 0x1: { /* CMPU.LT.QB */
- DIP("cmpu.lt.qb r%u, r%u", rs, rt);
- vassert(!mode64);
- t1 = newTemp(Ity_I1);
- t2 = newTemp(Ity_I1);
- t3 = newTemp(Ity_I1);
- t4 = newTemp(Ity_I1);
-
- assign(t1, binop(Iop_CmpLT32U,
- unop(Iop_8Uto32,
- unop(Iop_16to8,
- unop(Iop_32to16,
- getIReg(rs)))),
- unop(Iop_8Uto32,
- unop(Iop_16to8,
- unop(Iop_32to16,
- getIReg(rt))))));
- putDSPControl(IRExpr_ITE(mkexpr(t1),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x01000000)),
- binop(Iop_And32,
- getDSPControl(),
- mkU32(0xfeffffff))));
-
- assign(t2, binop(Iop_CmpLT32U,
- unop(Iop_8Uto32,
- unop(Iop_16HIto8,
- unop(Iop_32to16,
- getIReg(rs)))),
- unop(Iop_8Uto32,
- unop(Iop_16HIto8,
- unop(Iop_32to16,
- getIReg(rt))))));
- putDSPControl(IRExpr_ITE(mkexpr(t2),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x02000000)),
- binop(Iop_And32,
- getDSPControl(),
- mkU32(0xfdffffff))));
-
- assign(t3, binop(Iop_CmpLT32U,
- unop(Iop_8Uto32,
- unop(Iop_16to8,
- unop(Iop_32HIto16,
- getIReg(rs)))),
- unop(Iop_8Uto32,
- unop(Iop_16to8,
- unop(Iop_32HIto16,
- getIReg(rt))))));
- putDSPControl(IRExpr_ITE(mkexpr(t3),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x04000000)),
- binop(Iop_And32,
- getDSPControl(),
- mkU32(0xfbffffff))));
-
- assign(t4, binop(Iop_CmpLT32U,
- unop(Iop_8Uto32,
- unop(Iop_16HIto8,
- unop(Iop_32HIto16,
- getIReg(rs)))),
- unop(Iop_8Uto32,
- unop(Iop_16HIto8,
- unop(Iop_32HIto16,
- getIReg(rt))))));
- putDSPControl(IRExpr_ITE(mkexpr(t4),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x08000000)),
- binop(Iop_And32,
- getDSPControl(),
- mkU32(0xf7ffffff))));
- break;
- }
- case 0x2: { /* CMPU.LE.QB */
- DIP("cmpu.le.qb r%u, r%u", rs, rt);
- vassert(!mode64);
- t1 = newTemp(Ity_I1);
- t2 = newTemp(Ity_I1);
- t3 = newTemp(Ity_I1);
- t4 = newTemp(Ity_I1);
-
- assign(t1, binop(Iop_CmpLE32U,
- unop(Iop_8Uto32,
- unop(Iop_16to8,
- unop(Iop_32to16,
- getIReg(rs)))),
- unop(Iop_8Uto32,
- unop(Iop_16to8,
- unop(Iop_32to16,
- getIReg(rt))))));
- putDSPControl(IRExpr_ITE(mkexpr(t1),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x01000000)),
- binop(Iop_And32,
- getDSPControl(),
- mkU32(0xfeffffff))));
-
- assign(t2, binop(Iop_CmpLE32U,
- unop(Iop_8Uto32,
- unop(Iop_16HIto8,
- unop(Iop_32to16,
- getIReg(rs)))),
- unop(Iop_8Uto32,
- unop(Iop_16HIto8,
- unop(Iop_32to16,
- getIReg(rt))))));
- putDSPControl(IRExpr_ITE(mkexpr(t2),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x02000000)),
- binop(Iop_And32,
- getDSPControl(),
- mkU32(0xfdffffff))));
-
- assign(t3, binop(Iop_CmpLE32U,
- unop(Iop_8Uto32,
- unop(Iop_16to8,
- unop(Iop_32HIto16,
- getIReg(rs)))),
- unop(Iop_8Uto32,
- unop(Iop_16to8,
- unop(Iop_32HIto16,
- getIReg(rt))))));
- putDSPControl(IRExpr_ITE(mkexpr(t3),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x04000000)),
- binop(Iop_And32,
- getDSPControl(),
- mkU32(0xfbffffff))));
-
- assign(t4, binop(Iop_CmpLE32U,
- unop(Iop_8Uto32,
- unop(Iop_16HIto8,
- unop(Iop_32HIto16,
- getIReg(rs)))),
- unop(Iop_8Uto32,
- unop(Iop_16HIto8,
- unop(Iop_32HIto16,
- getIReg(rt))))));
- putDSPControl(IRExpr_ITE(mkexpr(t4),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x08000000)),
- binop(Iop_And32,
- getDSPControl(),
- mkU32(0xf7ffffff))));
- break;
- }
- case 0x3: { /* PICK.QB */
- DIP("pick.qb r%u, r%u, r%u", rd, rs, rt);
- vassert(!mode64);
- t0 = newTemp(Ity_I32);
- t1 = newTemp(Ity_I8);
- t2 = newTemp(Ity_I8);
- t3 = newTemp(Ity_I8);
- t4 = newTemp(Ity_I8);
+ default:
+ return -1;
+ }
- assign(t0, getDSPControl());
- assign(t1, IRExpr_ITE(binop(Iop_CmpNE32,
- binop(Iop_And32,
- mkexpr(t0),
- mkU32(0x01000000)),
- mkU32(0x0)),
- unop(Iop_16to8,
- unop(Iop_32to16,
- getIReg(rs))),
- unop(Iop_16to8,
- unop(Iop_32to16,
- getIReg(rt)))));
- assign(t2, IRExpr_ITE(binop(Iop_CmpNE32,
- binop(Iop_And32,
- mkexpr(t0),
- mkU32(0x02000000)),
- mkU32(0x0)),
- unop(Iop_16HIto8,
- unop(Iop_32to16, getIReg(rs))),
- unop(Iop_16HIto8,
- unop(Iop_32to16,
- getIReg(rt)))));
- assign(t3, IRExpr_ITE(binop(Iop_CmpNE32,
- binop(Iop_And32,
- mkexpr(t0),
- mkU32(0x04000000)),
- mkU32(0x0)),
- unop(Iop_16to8,
- unop(Iop_32HIto16,
- getIReg(rs))),
- unop(Iop_16to8,
- unop(Iop_32HIto16,
- getIReg(rt)))));
- assign(t4, IRExpr_ITE(binop(Iop_CmpNE32,
- binop(Iop_And32,
- mkexpr(t0),
- mkU32(0x08000000)),
- mkU32(0x0)),
- unop(Iop_16HIto8,
- unop(Iop_32HIto16,
- getIReg(rs))),
- unop(Iop_16HIto8,
- unop(Iop_32HIto16,
- getIReg(rt)))));
- putIReg(rd,
- binop(Iop_16HLto32,
- binop(Iop_8HLto16, mkexpr(t4), mkexpr(t3)),
- binop(Iop_8HLto16, mkexpr(t2), mkexpr(t1))));
- break;
- }
- case 0x4: { /* CMPGU.EQ.QB */
- DIP("cmpgu.eq.qb r%u, r%u, r%u", rd, rs, rt);
- vassert(!mode64);
- t1 = newTemp(Ity_I1);
- t2 = newTemp(Ity_I1);
- t3 = newTemp(Ity_I1);
- t4 = newTemp(Ity_I1);
- t5 = newTemp(Ity_I32);
- t6 = newTemp(Ity_I32);
- t7 = newTemp(Ity_I32);
- t8 = newTemp(Ity_I32);
-
- assign(t1, binop(Iop_CmpEQ32,
- unop(Iop_8Uto32,
- unop(Iop_16to8,
- unop(Iop_32to16, getIReg(rs)))),
- unop(Iop_8Uto32,
- unop(Iop_16to8,
- unop(Iop_32to16,
- getIReg(rt))))));
- assign(t5, IRExpr_ITE(mkexpr(t1),
- mkU32(0x00000001), mkU32(0)));
-
- assign(t2, binop(Iop_CmpEQ32,
- unop(Iop_8Uto32,
- unop(Iop_16HIto8,
- unop(Iop_32to16, getIReg(rs)))),
- unop(Iop_8Uto32,
- unop(Iop_16HIto8,
- unop(Iop_32to16,
- getIReg(rt))))));
- assign(t6, IRExpr_ITE(mkexpr(t2),
- mkU32(0x00000002), mkU32(0)));
-
- assign(t3, binop(Iop_CmpEQ32,
- unop(Iop_8Uto32,
- unop(Iop_16to8,
- unop(Iop_32HIto16,
- getIReg(rs)))),
- unop(Iop_8Uto32,
- unop(Iop_16to8,
- unop(Iop_32HIto16,
- getIReg(rt))))));
- assign(t7, IRExpr_ITE(mkexpr(t3),
- mkU32(0x00000004), mkU32(0)));
-
- assign(t4, binop(Iop_CmpEQ32,
- unop(Iop_8Uto32,
- unop(Iop_16HIto8,
- unop(Iop_32HIto16,
- getIReg(rs)))),
- unop(Iop_8Uto32,
- unop(Iop_16HIto8,
- unop(Iop_32HIto16,
- getIReg(rt))))));
- assign(t8, IRExpr_ITE(mkexpr(t4),
- mkU32(0x00000008), mkU32(0)));
-
- putIReg(rd, binop(Iop_Or32,
- binop(Iop_Or32,
- binop(Iop_Or32,
- mkexpr(t5), mkexpr(t6)),
- mkexpr(t7)),
- mkexpr(t8)));
- break;
- }
- case 0x5: { /* CMPGU.LT.QB */
- DIP("cmpgu.lt.qb r%u, r%u, r%u", rd, rs, rt);
- vassert(!mode64);
- t1 = newTemp(Ity_I1);
- t2 = newTemp(Ity_I1);
- t3 = newTemp(Ity_I1);
- t4 = newTemp(Ity_I1);
- t5 = newTemp(Ity_I32);
- t6 = newTemp(Ity_I32);
- t7 = newTemp(Ity_I32);
- t8 = newTemp(Ity_I32);
-
- assign(t1, binop(Iop_CmpLT32U,
- unop(Iop_8Uto32,
- unop(Iop_16to8,
- unop(Iop_32to16, getIReg(rs)))),
- unop(Iop_8Uto32,
- unop(Iop_16to8,
- unop(Iop_32to16,
- getIReg(rt))))));
- assign(t5, IRExpr_ITE(mkexpr(t1),
- mkU32(0x00000001), mkU32(0)));
-
- assign(t2, binop(Iop_CmpLT32U,
- unop(Iop_8Uto32,
- unop(Iop_16HIto8,
- unop(Iop_32to16, getIReg(rs)))),
- unop(Iop_8Uto32,
- unop(Iop_16HIto8,
- unop(Iop_32to16,
- getIReg(rt))))));
- assign(t6, IRExpr_ITE(mkexpr(t2),
- mkU32(0x00000002), mkU32(0)));
-
- assign(t3, binop(Iop_CmpLT32U,
- unop(Iop_8Uto32,
- unop(Iop_16to8,
- unop(Iop_32HIto16,
- getIReg(rs)))),
- unop(Iop_8Uto32,
- unop(Iop_16to8,
- unop(Iop_32HIto16,
- getIReg(rt))))));
- assign(t7, IRExpr_ITE(mkexpr(t3),
- mkU32(0x00000004), mkU32(0)));
-
- assign(t4, binop(Iop_CmpLT32U,
- unop(Iop_8Uto32,
- unop(Iop_16HIto8,
- unop(Iop_32HIto16,
- getIReg(rs)))),
- unop(Iop_8Uto32,
- unop(Iop_16HIto8,
- unop(Iop_32HIto16,
- getIReg(rt))))));
- assign(t8, IRExpr_ITE(mkexpr(t4),
- mkU32(0x00000008), mkU32(0)));
- putIReg(rd, binop(Iop_Or32,
- binop(Iop_Or32,
- binop(Iop_Or32,
- mkexpr(t5), mkexpr(t6)),
- mkexpr(t7)),
- mkexpr(t8)));
- break;
- }
- case 0x6: { /* CMPGU.LE.QB */
- DIP("cmpgu.le.qb r%u, r%u, r%u", rd, rs, rt);
- vassert(!mode64);
- t1 = newTemp(Ity_I1);
- t2 = newTemp(Ity_I1);
- t3 = newTemp(Ity_I1);
- t4 = newTemp(Ity_I1);
- t5 = newTemp(Ity_I32);
- t6 = newTemp(Ity_I32);
- t7 = newTemp(Ity_I32);
- t8 = newTemp(Ity_I32);
-
- assign(t1, binop(Iop_CmpLE32U,
- unop(Iop_8Uto32,
- unop(Iop_16to8,
- unop(Iop_32to16, getIReg(rs)))),
- unop(Iop_8Uto32,
- unop(Iop_16to8,
- unop(Iop_32to16,
- getIReg(rt))))));
- assign(t5, IRExpr_ITE(mkexpr(t1),
- mkU32(0x00000001), mkU32(0)));
-
- assign(t2, binop(Iop_CmpLE32U,
- unop(Iop_8Uto32,
- unop(Iop_16HIto8,
- unop(Iop_32to16, getIReg(rs)))),
- unop(Iop_8Uto32,
- unop(Iop_16HIto8,
- unop(Iop_32to16,
- getIReg(rt))))));
- assign(t6, IRExpr_ITE(mkexpr(t2),
- mkU32(0x00000002), mkU32(0)));
-
- assign(t3, binop(Iop_CmpLE32U,
- unop(Iop_8Uto32,
- unop(Iop_16to8,
- unop(Iop_32HIto16,
- getIReg(rs)))),
- unop(Iop_8Uto32,
- unop(Iop_16to8,
- unop(Iop_32HIto16,
- getIReg(rt))))));
- assign(t7, IRExpr_ITE(mkexpr(t3),
- mkU32(0x00000004), mkU32(0)));
-
- assign(t4, binop(Iop_CmpLE32U,
- unop(Iop_8Uto32,
- unop(Iop_16HIto8,
- unop(Iop_32HIto16,
- getIReg(rs)))),
- unop(Iop_8Uto32,
- unop(Iop_16HIto8,
- unop(Iop_32HIto16,
- getIReg(rt))))));
- assign(t8, IRExpr_ITE(mkexpr(t4),
- mkU32(0x00000008), mkU32(0)));
- putIReg(rd, binop(Iop_Or32,
- binop(Iop_Or32,
- binop(Iop_Or32,
- mkexpr(t5), mkexpr(t6)),
- mkexpr(t7)),
- mkexpr(t8)));
- break;
- }
- case 0x8: { /* CMP.EQ.PH */
- DIP("cmp.eq.ph r%u, r%u", rs, rt);
- vassert(!mode64);
- t1 = newTemp(Ity_I1);
- t2 = newTemp(Ity_I1);
-
- assign(t1, binop(Iop_CmpEQ16,
- unop(Iop_32to16, getIReg(rs)),
- unop(Iop_32to16, getIReg(rt))));
- putDSPControl(IRExpr_ITE(mkexpr(t1),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x01000000)),
- binop(Iop_And32,
- getDSPControl(),
- mkU32(0xfeffffff))));
- assign(t2, binop(Iop_CmpEQ16,
- unop(Iop_32HIto16, getIReg(rs)),
- unop(Iop_32HIto16, getIReg(rt))));
- putDSPControl(IRExpr_ITE(mkexpr(t2),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x02000000)),
- binop(Iop_And32,
- getDSPControl(),
- mkU32(0xfdffffff))));
- break;
- }
- case 0x9: { /* CMP.LT.PH */
- DIP("cmp.lt.ph r%u, r%u", rs, rt);
- vassert(!mode64);
- t1 = newTemp(Ity_I1);
- t2 = newTemp(Ity_I1);
-
- assign(t1, binop(Iop_CmpLT32S,
- unop(Iop_16Sto32,
- unop(Iop_32to16, getIReg(rs))),
- unop(Iop_16Sto32,
- unop(Iop_32to16, getIReg(rt)))));
- putDSPControl(IRExpr_ITE(mkexpr(t1),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x01000000)),
- binop(Iop_And32,
- getDSPControl(),
- mkU32(0xfeffffff))));
-
- assign(t2, binop(Iop_CmpLT32S,
- unop(Iop_16Sto32,
- unop(Iop_32HIto16, getIReg(rs))),
- unop(Iop_16Sto32,
- unop(Iop_32HIto16, getIReg(rt)))));
- putDSPControl(IRExpr_ITE(mkexpr(t2),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x02000000)),
- binop(Iop_And32,
- getDSPControl(),
- mkU32(0xfdffffff))));
- break;
- }
- case 0xA: { /* CMP.LE.PH */
- DIP("cmp.le.ph r%u, r%u", rs, rt);
- vassert(!mode64);
- t1 = newTemp(Ity_I1);
- t2 = newTemp(Ity_I1);
-
- assign(t1, binop(Iop_CmpLE32S,
- unop(Iop_16Sto32,
- unop(Iop_32to16, getIReg(rs))),
- unop(Iop_16Sto32,
- unop(Iop_32to16, getIReg(rt)))));
- putDSPControl(IRExpr_ITE(mkexpr(t1),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x01000000)),
- binop(Iop_And32,
- getDSPControl(),
- mkU32(0xfeffffff))));
-
- assign(t2, binop(Iop_CmpLE32S,
- unop(Iop_16Sto32,
- unop(Iop_32HIto16, getIReg(rs))),
- unop(Iop_16Sto32,
- unop(Iop_32HIto16, getIReg(rt)))));
- putDSPControl(IRExpr_ITE(mkexpr(t2),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x02000000)),
- binop(Iop_And32,
- getDSPControl(),
- mkU32(0xfdffffff))));
- break;
- }
- case 0xB: { /* PICK.PH */
- DIP("pick.qb r%u, r%u, r%u", rd, rs, rt);
- vassert(!mode64);
- t0 = newTemp(Ity_I32);
- t1 = newTemp(Ity_I16);
- t2 = newTemp(Ity_I16);
+ break;
+ }
- assign(t0, getDSPControl());
+ default:
+ return -1;
+ }
- assign(t1, IRExpr_ITE(binop(Iop_CmpNE32,
- binop(Iop_And32,
- mkexpr(t0),
- mkU32(0x01000000)),
- mkU32(0x0)),
- unop(Iop_32to16, getIReg(rs)),
- unop(Iop_32to16, getIReg(rt))));
+ return 0;
+}
- assign(t2, IRExpr_ITE(binop(Iop_CmpNE32,
- binop(Iop_And32,
- mkexpr(t0),
- mkU32(0x02000000)),
- mkU32(0x0)),
- unop(Iop_32HIto16, getIReg(rs)),
- unop(Iop_32HIto16, getIReg(rt))));
+static Int msa_BIT_0A(UInt cins, UChar wd, UChar ws) /* BIT (0x0A) */
+{
+ IRTemp t1, t2;
+ UShort operation;
+ UChar df, m;
- putIReg(rd, binop(Iop_16HLto32, mkexpr(t2), mkexpr(t1)));
- break;
- }
- case 0xC: { /* PRECRQ.QB.PH */
- DIP("precrq.qb.ph r%u, r%u, %u", rd, rs, rt);
- vassert(!mode64);
- putIReg(rd,
- binop(Iop_16HLto32,
- binop(Iop_8HLto16,
- unop(Iop_16HIto8,
- unop(Iop_32HIto16, getIReg(rs))),
- unop(Iop_16HIto8,
- unop(Iop_32to16, getIReg(rs)))),
- binop(Iop_8HLto16,
- unop(Iop_16HIto8,
- unop(Iop_32HIto16, getIReg(rt))),
- unop(Iop_16HIto8,
- unop(Iop_32to16, getIReg(rt))))));
- break;
- }
- case 0xD: { /* PRECR.QB.PH */
- DIP("precr.qb.ph r%u, r%u, r%u", rd, rs, rt);
- vassert(!mode64);
-
- putIReg(rd,
- binop(Iop_16HLto32,
- binop(Iop_8HLto16,
- unop(Iop_16to8,
- unop(Iop_32HIto16, getIReg(rs))),
- unop(Iop_16to8,
- unop(Iop_32to16, getIReg(rs)))),
- binop(Iop_8HLto16,
- unop(Iop_16to8,
- unop(Iop_32HIto16, getIReg(rt))),
- unop(Iop_16to8,
- unop(Iop_32to16, getIReg(rt))))));
- break;
- }
- case 0xF: { /* PRECRQU_S.QB.PH */
- DIP("precrqu_s.qb.ph r%u, r%u, %u", rd, rs, rt);
- vassert(!mode64);
- t0 = newTemp(Ity_I8);
- t1 = newTemp(Ity_I8);
- t2 = newTemp(Ity_I8);
- t3 = newTemp(Ity_I8);
- t4 = newTemp(Ity_I8);
- t5 = newTemp(Ity_I32);
- t6 = newTemp(Ity_I1);
- t7 = newTemp(Ity_I8);
- t8 = newTemp(Ity_I1);
- t9 = newTemp(Ity_I32);
- t10 = newTemp(Ity_I8);
- t11 = newTemp(Ity_I1);
- t12 = newTemp(Ity_I32);
- t13 = newTemp(Ity_I8);
- t14 = newTemp(Ity_I1);
- t15 = newTemp(Ity_I32);
-
- assign(t4, IRExpr_ITE(binop(Iop_CmpLT32U,
- mkU32(0x7f80),
- binop(Iop_And32,
- unop(Iop_16Uto32,
- unop(Iop_32to16,
- getIReg(rs))),
- mkU32(0x7fff))),
- mkU8(0xff),
- unop(Iop_16HIto8,
- unop(Iop_32to16,
- binop(Iop_Shl32,
- getIReg(rs),
- mkU8(1))))));
- assign(t0, IRExpr_ITE(binop(Iop_CmpEQ32,
- binop(Iop_And32,
- unop(Iop_16Uto32,
- unop(Iop_32to16,
- getIReg(rs))),
- mkU32(0x00008000)),
- mkU32(0x0)),
- mkexpr(t4),
- mkU8(0x0)));
- assign(t5, binop(Iop_And32,
- unop(Iop_16Uto32,
- unop(Iop_32to16,
- getIReg(rs))),
- mkU32(0x00008000)));
- assign(t6, binop(Iop_CmpLT32U,
- mkU32(0x7f80),
- binop(Iop_And32,
- unop(Iop_16Uto32,
- unop(Iop_32to16,
- getIReg(rs))),
- mkU32(0x7fff))));
- putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
- mkexpr(t5),
- mkU32(0x0)),
- IRExpr_ITE(mkexpr(t6),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x00400000)
- ),
- getDSPControl()),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x00400000))));
-
- assign(t7, IRExpr_ITE(binop(Iop_CmpLT32U,
- mkU32(0x7f80),
- binop(Iop_And32,
- unop(Iop_16Uto32,
- unop(Iop_32HIto16,
- getIReg(rs))),
- mkU32(0x7fff))),
- mkU8(0xff),
- unop(Iop_16HIto8,
- unop(Iop_32HIto16,
- binop(Iop_Shl32,
- getIReg(rs),
- mkU8(1))))));
- assign(t1, IRExpr_ITE(binop(Iop_CmpEQ32,
- binop(Iop_And32,
- unop(Iop_16Uto32,
- unop(Iop_32HIto16,
- getIReg(rs))),
- mkU32(0x00008000)),
- mkU32(0x0)),
- mkexpr(t7),
- mkU8(0x0)));
- assign(t8, binop(Iop_CmpEQ32,
- binop(Iop_And32,
- unop(Iop_16Uto32,
- unop(Iop_32HIto16,
- getIReg(rs))),
- mkU32(0x00008000)),
- mkU32(0x0)));
- assign(t9, IRExpr_ITE(binop(Iop_CmpLT32U,
- mkU32(0x7f80),
- binop(Iop_And32,
- unop(Iop_16Uto32,
- unop(Iop_32HIto16,
- getIReg(rs))),
- mkU32(0x7fff))),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x00400000)),
- getDSPControl()));
- putDSPControl(IRExpr_ITE(mkexpr(t8),
- mkexpr(t9),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x00400000))));
-
- assign(t10, IRExpr_ITE(binop(Iop_CmpLT32U,
- mkU32(0x7f80),
- binop(Iop_And32,
- unop(Iop_16Uto32,
- unop(Iop_32to16,
- getIReg(rt))),
- mkU32(0x7fff))),
- mkU8(0xff),
- unop(Iop_16HIto8,
- unop(Iop_32to16,
- binop(Iop_Shl32,
- getIReg(rt),
- mkU8(1))))));
- assign(t2, IRExpr_ITE(binop(Iop_CmpEQ32,
- binop(Iop_And32,
- unop(Iop_16Uto32,
- unop(Iop_32to16,
- getIReg(rt))),
- mkU32(0x00008000)),
- mkU32(0x0)),
- mkexpr(t10),
- mkU8(0x0)));
- assign(t11, binop(Iop_CmpEQ32,
- binop(Iop_And32,
- unop(Iop_16Uto32,
- unop(Iop_32to16,
- getIReg(rt))),
- mkU32(0x00008000)),
- mkU32(0x0)));
- assign(t12, IRExpr_ITE(binop(Iop_CmpLT32U,
- mkU32(0x7f80),
- binop(Iop_And32,
- unop(Iop_16Uto32,
- unop(Iop_32to16,
- getIReg(rt))),
- mkU32(0x7fff))),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x00400000)),
- getDSPControl()));
- putDSPControl(IRExpr_ITE(mkexpr(t11),
- mkexpr(t12),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x00400000))));
-
- assign(t13, IRExpr_ITE(binop(Iop_CmpLT32U,
- mkU32(0x7f80),
- binop(Iop_And32,
- unop(Iop_16Uto32,
- unop(Iop_32HIto16,
- getIReg(rt))),
- mkU32(0x7fff))),
- mkU8(0xff),
- unop(Iop_16HIto8,
- unop(Iop_32HIto16,
- binop(Iop_Shl32,
- getIReg(rt),
- mkU8(1))))));
- assign(t3, IRExpr_ITE(binop(Iop_CmpEQ32,
- binop(Iop_And32,
- unop(Iop_16Uto32,
- unop(Iop_32HIto16,
- getIReg(rt))),
- mkU32(0x00008000)),
- mkU32(0x0)),
- mkexpr(t13),
- mkU8(0x0)));
- assign(t14, binop(Iop_CmpEQ32,
- binop(Iop_And32,
- unop(Iop_16Uto32,
- unop(Iop_32HIto16,
- getIReg(rt))),
- mkU32(0x00008000)),
- mkU32(0x0)));
- assign(t15, IRExpr_ITE(binop(Iop_CmpLT32U,
- mkU32(0x7f80),
- binop(Iop_And32,
- unop(Iop_16Uto32,
- unop(Iop_32HIto16,
- getIReg(rt))),
- mkU32(0x7fff))),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x00400000)),
- getDSPControl()));
- putDSPControl(IRExpr_ITE(mkexpr(t14),
- mkexpr(t15),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x00400000))));
-
- putIReg(rd, binop(Iop_16HLto32,
- binop(Iop_8HLto16,
- mkexpr(t1), mkexpr(t0)),
- binop(Iop_8HLto16,
- mkexpr(t3), mkexpr(t2))));
- break;
- }
- case 0x14: { /* PRECRQ.PH.W */
- DIP("precrq.ph.w r%u, r%u, %u", rd, rs, rt);
- vassert(!mode64);
- putIReg(rd, binop(Iop_16HLto32,
- unop(Iop_32HIto16, getIReg(rs)),
- unop(Iop_32HIto16, getIReg(rt))));
- break;
- }
- case 0x15: { /* PRECRQ_RS.PH.W */
- DIP("precrq_rs.ph.w r%u, r%u, %u", rd, rs, rt);
- vassert(!mode64);
- t0 = newTemp(Ity_I64);
- t1 = newTemp(Ity_I1);
- t2 = newTemp(Ity_I32);
- t3 = newTemp(Ity_I64);
- t4 = newTemp(Ity_I1);
- t5 = newTemp(Ity_I32);
+ operation = (cins & 0x03800000) >> 23;
+ df = (cins & 0x007F0000) >> 16;
- assign(t0, binop(Iop_Add64,
- binop(Iop_32HLto64,
- binop(Iop_Shr32,
- binop(Iop_And32,
- getIReg(rs),
- mkU32(0x80000000)),
- mkU8(31)),
- getIReg(rs)),
- mkU64(0x0000000000008000ULL)));
- assign(t1, binop(Iop_CmpNE32,
- binop(Iop_And32,
- unop(Iop_64HIto32, mkexpr(t0)),
- mkU32(0x1)),
- binop(Iop_And32,
- binop(Iop_Shr32,
- unop(Iop_64to32, mkexpr(t0)),
- mkU8(31)),
- mkU32(0x1))));
- assign(t2, IRExpr_ITE(mkexpr(t1),
- mkU32(0x7fffffff),
- unop(Iop_64to32, mkexpr(t0))));
- putDSPControl(IRExpr_ITE(mkexpr(t1),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x400000)),
- getDSPControl()));
- assign(t3, binop(Iop_Add64,
- binop(Iop_32HLto64,
- binop(Iop_Shr32,
- binop(Iop_And32,
- getIReg(rt),
- mkU32(0x80000000)),
- mkU8(31)),
- getIReg(rt)),
- mkU64(0x0000000000008000ULL)));
- assign(t4, binop(Iop_CmpNE32,
- binop(Iop_And32,
- unop(Iop_64HIto32, mkexpr(t3)),
- mkU32(0x1)),
- binop(Iop_And32,
- binop(Iop_Shr32,
- unop(Iop_64to32, mkexpr(t3)),
- mkU8(31)),
- mkU32(0x1))));
- assign(t5, IRExpr_ITE(mkexpr(t4),
- mkU32(0x7fffffff),
- unop(Iop_64to32, mkexpr(t3))));
- putDSPControl(IRExpr_ITE(mkexpr(t4),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x400000)),
- getDSPControl()));
- putIReg(rd, binop(Iop_16HLto32,
- unop(Iop_32HIto16, mkexpr(t2)),
- unop(Iop_32HIto16, mkexpr(t5))));
- break;
- }
- case 0x1E: { /* PRECR_SRA.PH.W */
- DIP("precr_sra.ph.w r%u, r%u, %u", rt, rs, rd);
- vassert(!mode64);
-
- if (0 == rd) {
- putIReg(rt, binop(Iop_16HLto32,
- unop(Iop_32to16, getIReg(rt)),
- unop(Iop_32to16, getIReg(rs))));
- } else {
- putIReg(rt, binop(Iop_16HLto32,
- unop(Iop_32to16, binop(Iop_Sar32,
- getIReg(rt),
- mkU8(rd))),
- unop(Iop_32to16, binop(Iop_Sar32,
- getIReg(rs),
- mkU8(rd)))));
- }
- break;
- }
- case 0x1F: { /* PRECR_SRA_R.PH.W */
- DIP("precr_sra_r.ph.w r%u, r%u, %u", rt, rs, rd);
- vassert(!mode64);
+ if ((df & 0x70) == 0x70) { // 111mmmm; b
+ m = df & 0x07;
+ df = 0;
+ } else if ((df & 0x60) == 0x60) { // 110mmmm; h
+ m = df & 0x0F;
+ df = 1;
+ } else if ((df & 0x40) == 0x40) { // 10mmmmm; w
+ m = df & 0x1F;
+ df = 2;
+ } else if ((df & 0x00) == 0x00) { // 0mmmmmm; d
+ m = df & 0x3F;
+ df = 3;
+ }
- t0 = newTemp(Ity_I32);
- t1 = newTemp(Ity_I32);
+ switch (operation) {
+ case 0x00: { /* SAT_S.df */
+ switch (df) {
+ case 0x00: { /* SAT_S.B */
+ DIP("SAT_S.B w%d, w%d, %d", wd, ws, m);
+ t1 = newTemp(Ity_V128);
+ assign(t1, binop(Iop_SarN8x16, getWReg(ws), mkU8(7)));
- if (0 == rd) {
- putIReg(rt, binop(Iop_16HLto32,
- unop(Iop_32to16, getIReg(rt)),
- unop(Iop_32to16, getIReg(rs))));
- } else {
- assign(t0, binop(Iop_Shr32,
- binop(Iop_Add32,
- binop(Iop_Sar32,
- getIReg(rt),
- mkU8(rd-1)),
- mkU32(0x1)),
- mkU8(0x1)));
- assign(t1, binop(Iop_Shr32,
- binop(Iop_Add32,
- binop(Iop_Sar32,
- getIReg(rs),
- mkU8(rd-1)),
- mkU32(0x1)),
- mkU8(0x1)));
- putIReg(rt, binop(Iop_16HLto32,
- unop(Iop_32to16, mkexpr(t0)),
- unop(Iop_32to16, mkexpr(t1))));
- };
- break;
- }
- case 0xE: { /* PACKRL.PH */
- DIP("packrl.ph r%u, r%u, r%u", rd, rs, rt);
- vassert(!mode64);
+ if (m == 0) {
+ putWReg(wd, mkexpr(t1));
+ } else {
+ t2 = newTemp(Ity_V128);
+ assign(t2,
+ binop(Iop_SarN8x16, getWReg(ws), mkU8(m)));
+ putWReg(wd,
+ binop(Iop_OrV128,
+ binop(Iop_OrV128,
+ binop(Iop_AndV128,
+ binop(Iop_CmpEQ8x16,
+ mkexpr(t1),
+ mkexpr(t2)),
+ getWReg(ws)),
+ binop(Iop_ShlN8x16,
+ binop(Iop_CmpGT8Sx16,
+ mkexpr(t1),
+ mkexpr(t2)),
+ mkU8(m))),
+ binop(Iop_ShrN8x16,
+ binop(Iop_CmpGT8Sx16,
+ mkexpr(t2),
+ mkexpr(t1)),
+ mkU8(8 - m))));
+ }
- putIReg(rd, binop(Iop_16HLto32,
- unop(Iop_32to16, getIReg(rs)),
- unop(Iop_32HIto16, getIReg(rt))));
- break;
- }
- case 0x18: { /* CMPGDU.EQ.QB */
- DIP("cmpgdu.eq.qb r%u, r%u, r%u", rd, rs, rt);
- vassert(!mode64);
- t1 = newTemp(Ity_I1);
- t2 = newTemp(Ity_I1);
- t3 = newTemp(Ity_I1);
- t4 = newTemp(Ity_I1);
- t5 = newTemp(Ity_I32);
- t6 = newTemp(Ity_I32);
- t7 = newTemp(Ity_I32);
- t8 = newTemp(Ity_I32);
+ break;
+ }
- assign(t1,
- binop(Iop_CmpEQ32,
- unop(Iop_8Uto32,
- unop(Iop_16to8,
- unop(Iop_32to16, getIReg(rs)))),
- unop(Iop_8Uto32,
- unop(Iop_16to8,
- unop(Iop_32to16, getIReg(rt))))));
- assign(t5, IRExpr_ITE(mkexpr(t1),
- mkU32(0x00000001), mkU32(0)));
- putDSPControl(IRExpr_ITE(mkexpr(t1),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x01000000)),
- binop(Iop_And32,
- getDSPControl(),
- mkU32(0xfeffffff))));
-
- assign(t2, binop(Iop_CmpEQ32,
- unop(Iop_8Uto32,
- unop(Iop_16HIto8,
- unop(Iop_32to16, getIReg(rs)))),
- unop(Iop_8Uto32,
- unop(Iop_16HIto8,
- unop(Iop_32to16,
- getIReg(rt))))));
- assign(t6, IRExpr_ITE(mkexpr(t2),
- mkU32(0x00000002), mkU32(0)));
- putDSPControl(IRExpr_ITE(mkexpr(t2),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x02000000)),
- binop(Iop_And32,
- getDSPControl(),
- mkU32(0xfdffffff))));
-
- assign(t3, binop(Iop_CmpEQ32,
- unop(Iop_8Uto32,
- unop(Iop_16to8,
- unop(Iop_32HIto16,
- getIReg(rs)))),
- unop(Iop_8Uto32,
- unop(Iop_16to8,
- unop(Iop_32HIto16,
- getIReg(rt))))));
- assign(t7, IRExpr_ITE(mkexpr(t3),
- mkU32(0x00000004), mkU32(0)));
- putDSPControl(IRExpr_ITE(mkexpr(t3),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x04000000)),
- binop(Iop_And32,
- getDSPControl(),
- mkU32(0xfbffffff))));
-
- assign(t4, binop(Iop_CmpEQ32,
- unop(Iop_8Uto32,
- unop(Iop_16HIto8,
- unop(Iop_32HIto16,
- getIReg(rs)))),
- unop(Iop_8Uto32,
- unop(Iop_16HIto8,
- unop(Iop_32HIto16,
- getIReg(rt))))));
- assign(t8, IRExpr_ITE(mkexpr(t4),
- mkU32(0x00000008), mkU32(0)));
- putDSPControl(IRExpr_ITE(mkexpr(t4),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x08000000)),
- binop(Iop_And32,
- getDSPControl(),
- mkU32(0xf7ffffff))));
-
- putIReg(rd, binop(Iop_Or32,
- binop(Iop_Or32,
- binop(Iop_Or32,
- mkexpr(t5), mkexpr(t6)),
- mkexpr(t7)),
- mkexpr(t8)));
- break;
- }
- case 0x19: { /* CMPGDU.LT.QB */
- DIP("cmpgdu.lt.qb r%u, r%u, r%u", rd, rs, rt);
- vassert(!mode64);
- t1 = newTemp(Ity_I1);
- t2 = newTemp(Ity_I1);
- t3 = newTemp(Ity_I1);
- t4 = newTemp(Ity_I1);
- t5 = newTemp(Ity_I32);
- t6 = newTemp(Ity_I32);
- t7 = newTemp(Ity_I32);
- t8 = newTemp(Ity_I32);
-
- assign(t1, binop(Iop_CmpLT32U,
- unop(Iop_8Uto32,
- unop(Iop_16to8,
- unop(Iop_32to16, getIReg(rs)))),
- unop(Iop_8Uto32,
- unop(Iop_16to8,
- unop(Iop_32to16,
- getIReg(rt))))));
- assign(t5, IRExpr_ITE(mkexpr(t1),
- mkU32(0x00000001), mkU32(0)));
- putDSPControl(IRExpr_ITE(mkexpr(t1),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x01000000)),
- binop(Iop_And32,
- getDSPControl(),
- mkU32(0xfeffffff))));
-
- assign(t2, binop(Iop_CmpLT32U,
- unop(Iop_8Uto32,
- unop(Iop_16HIto8,
- unop(Iop_32to16, getIReg(rs)))),
- unop(Iop_8Uto32,
- unop(Iop_16HIto8,
- unop(Iop_32to16,
- getIReg(rt))))));
- assign(t6, IRExpr_ITE(mkexpr(t2),
- mkU32(0x00000002), mkU32(0)));
- putDSPControl(IRExpr_ITE(mkexpr(t2),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x02000000)),
- binop(Iop_And32,
- getDSPControl(),
- mkU32(0xfdffffff))));
-
- assign(t3, binop(Iop_CmpLT32U,
- unop(Iop_8Uto32,
- unop(Iop_16to8,
- unop(Iop_32HIto16,
- getIReg(rs)))),
- unop(Iop_8Uto32,
- unop(Iop_16to8,
- unop(Iop_32HIto16,
- getIReg(rt))))));
- assign(t7, IRExpr_ITE(mkexpr(t3),
- mkU32(0x00000004), mkU32(0)));
- putDSPControl(IRExpr_ITE(mkexpr(t3),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x04000000)),
- binop(Iop_And32,
- getDSPControl(),
- mkU32(0xfbffffff))));
-
- assign(t4, binop(Iop_CmpLT32U,
- unop(Iop_8Uto32,
- unop(Iop_16HIto8,
- unop(Iop_32HIto16,
- getIReg(rs)))),
- unop(Iop_8Uto32,
- unop(Iop_16HIto8,
- unop(Iop_32HIto16,
- getIReg(rt))))));
- assign(t8, IRExpr_ITE(mkexpr(t4),
- mkU32(0x00000008), mkU32(0)));
- putDSPControl(IRExpr_ITE(mkexpr(t4),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x08000000)),
- binop(Iop_And32,
- getDSPControl(),
- mkU32(0xf7ffffff))));
-
- putIReg(rd, binop(Iop_Or32,
- binop(Iop_Or32,
- binop(Iop_Or32,
- mkexpr(t5), mkexpr(t6)),
- mkexpr(t7)),
- mkexpr(t8)));
- break;
- }
- case 0x1A: { /* CMPGDU.LE.QB */
- DIP("cmpgdu.le.qb r%u, r%u, r%u", rd, rs, rt);
- vassert(!mode64);
- t1 = newTemp(Ity_I1);
- t2 = newTemp(Ity_I1);
- t3 = newTemp(Ity_I1);
- t4 = newTemp(Ity_I1);
- t5 = newTemp(Ity_I32);
- t6 = newTemp(Ity_I32);
- t7 = newTemp(Ity_I32);
- t8 = newTemp(Ity_I32);
-
- assign(t1, binop(Iop_CmpLE32U,
- unop(Iop_8Uto32,
- unop(Iop_16to8,
- unop(Iop_32to16, getIReg(rs)))),
- unop(Iop_8Uto32,
- unop(Iop_16to8,
- unop(Iop_32to16,
- getIReg(rt))))));
- assign(t5, IRExpr_ITE(mkexpr(t1),
- mkU32(0x00000001),
- mkU32(0)));
- putDSPControl(IRExpr_ITE(mkexpr(t1),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x01000000)),
- binop(Iop_And32,
- getDSPControl(),
- mkU32(0xfeffffff))));
-
- assign(t2, binop(Iop_CmpLE32U,
- unop(Iop_8Uto32,
- unop(Iop_16HIto8,
- unop(Iop_32to16, getIReg(rs)))),
- unop(Iop_8Uto32,
- unop(Iop_16HIto8,
- unop(Iop_32to16,
- getIReg(rt))))));
- assign(t6, IRExpr_ITE(mkexpr(t2),
- mkU32(0x00000002), mkU32(0)));
- putDSPControl(IRExpr_ITE(mkexpr(t2),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x02000000)),
- binop(Iop_And32,
- getDSPControl(),
- mkU32(0xfdffffff))));
-
- assign(t3, binop(Iop_CmpLE32U,
- unop(Iop_8Uto32,
- unop(Iop_16to8,
- unop(Iop_32HIto16,
- getIReg(rs)))),
- unop(Iop_8Uto32,
- unop(Iop_16to8,
- unop(Iop_32HIto16,
- getIReg(rt))))));
- assign(t7, IRExpr_ITE(mkexpr(t3),
- mkU32(0x00000004), mkU32(0)));
- putDSPControl(IRExpr_ITE(mkexpr(t3),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x04000000)),
- binop(Iop_And32,
- getDSPControl(),
- mkU32(0xfbffffff))));
-
- assign(t4, binop(Iop_CmpLE32U,
- unop(Iop_8Uto32,
- unop(Iop_16HIto8,
- unop(Iop_32HIto16,
- getIReg(rs)))),
- unop(Iop_8Uto32,
- unop(Iop_16HIto8,
- unop(Iop_32HIto16,
- getIReg(rt))))));
- assign(t8, IRExpr_ITE(mkexpr(t4),
- mkU32(0x00000008), mkU32(0)));
- putDSPControl(IRExpr_ITE(mkexpr(t4),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x08000000)),
- binop(Iop_And32,
- getDSPControl(),
- mkU32(0xf7ffffff))));
-
- putIReg(rd, binop(Iop_Or32,
- binop(Iop_Or32,
- binop(Iop_Or32,
- mkexpr(t5), mkexpr(t6)),
- mkexpr(t7)),
- mkexpr(t8)));
- break;
- }
- default:
- return -1;
+ case 0x01: { /* SAT_S.H */
+ DIP("SAT_S.H w%d, w%d, %d", wd, ws, m);
+ t1 = newTemp(Ity_V128);
+ assign(t1, binop(Iop_SarN16x8, getWReg(ws), mkU8(15)));
+
+ if (m == 0) {
+ putWReg(wd, mkexpr(t1));
+ } else {
+ t2 = newTemp(Ity_V128);
+ assign(t2,
+ binop(Iop_SarN16x8,
+ getWReg(ws),
+ mkU8(m)));
+ putWReg(wd,
+ binop(Iop_OrV128,
+ binop(Iop_OrV128,
+ binop(Iop_AndV128,
+ binop(Iop_CmpEQ16x8,
+ mkexpr(t1),
+ mkexpr(t2)),
+ getWReg(ws)),
+ binop(Iop_ShlN16x8,
+ binop(Iop_CmpGT16Sx8,
+ mkexpr(t1),
+ mkexpr(t2)),
+ mkU8(m))),
+ binop(Iop_ShrN16x8,
+ binop(Iop_CmpGT16Sx8,
+ mkexpr(t2),
+ mkexpr(t1)),
+ mkU8(16 - m))));
+ }
+
+ break;
+ }
+
+ case 0x02: { /* SAT_S.W */
+ DIP("SAT_S.W w%d, w%d, %d", wd, ws, m);
+ t1 = newTemp(Ity_V128);
+ assign(t1, binop(Iop_SarN32x4, getWReg(ws), mkU8(31)));
+
+ if (m == 0) {
+ putWReg(wd, mkexpr(t1));
+ } else {
+ t2 = newTemp(Ity_V128);
+ assign(t2,
+ binop(Iop_SarN32x4,
+ getWReg(ws),
+ mkU8(m)));
+ putWReg(wd,
+ binop(Iop_OrV128,
+ binop(Iop_OrV128,
+ binop(Iop_AndV128,
+ binop(Iop_CmpEQ32x4,
+ mkexpr(t1),
+ mkexpr(t2)),
+ getWReg(ws)),
+ binop(Iop_ShlN32x4,
+ binop(Iop_CmpGT32Sx4,
+ mkexpr(t1),
+ mkexpr(t2)),
+ mkU8(m))),
+ binop(Iop_ShrN32x4,
+ binop(Iop_CmpGT32Sx4,
+ mkexpr(t2),
+ mkexpr(t1)),
+ mkU8(32 - m))));
+ }
+
+ break;
+ }
+
+ case 0x03: { /* SAT_S.D */
+ DIP("SAT_S.D w%d, w%d, %d", wd, ws, m);
+ t1 = newTemp(Ity_V128);
+ assign(t1, binop(Iop_SarN64x2, getWReg(ws), mkU8(63)));
+
+ if (m == 0) {
+ putWReg(wd, mkexpr(t1));
+ } else {
+ t2 = newTemp(Ity_V128);
+ assign(t2,
+ binop(Iop_SarN64x2,
+ getWReg(ws),
+ mkU8(m)));
+ putWReg(wd,
+ binop(Iop_OrV128,
+ binop(Iop_OrV128,
+ binop(Iop_AndV128,
+ binop(Iop_CmpEQ64x2,
+ mkexpr(t1),
+ mkexpr(t2)),
+ getWReg(ws)),
+ binop(Iop_ShlN64x2,
+ binop(Iop_CmpGT64Sx2,
+ mkexpr(t1),
+ mkexpr(t2)),
+ mkU8(m))),
+ binop(Iop_ShrN64x2,
+ binop(Iop_CmpGT64Sx2,
+ mkexpr(t2),
+ mkexpr(t1)),
+ mkU8(64 - m))));
}
- break; /* end of CMPU.EQ.QB */
- }
- case 0x13: { /* SHLL.QB */
- switch(sa) {
- case 0x0: { /* SHLL.QB */
- DIP("shll.qb r%u, r%u, %u", rd, rt, rs);
- vassert(!mode64);
- t0 = newTemp(Ity_I32);
- t1 = newTemp(Ity_I1);
- t2 = newTemp(Ity_I1);
- t3 = newTemp(Ity_I32);
- t4 = newTemp(Ity_I1);
- t5 = newTemp(Ity_I1);
- t6 = newTemp(Ity_I32);
- t7 = newTemp(Ity_I1);
- t8 = newTemp(Ity_I1);
- t9 = newTemp(Ity_I1);
- t10 = newTemp(Ity_I1);
-
- if (0 == rs) {
- putIReg(rd, getIReg(rt));
- } else {
- /* Shift bits 7..0 and 23..16. */
- assign(t0, binop(Iop_Shl32,
- binop(Iop_And32,
- getIReg(rt),
- mkU32(0x00ff00ff)),
- mkU8(rs)));
- assign(t1, binop(Iop_CmpNE32,
- binop(Iop_And32,
- mkexpr(t0),
- mkU32(0xff000000)),
- mkU32(0x00000000)));
- assign(t2, binop(Iop_CmpNE32,
- binop(Iop_And32,
- mkexpr(t0),
- mkU32(0xff000000)),
- mkU32(0xff000000)));
- assign(t7, binop(Iop_CmpNE32,
- binop(Iop_And32,
- mkexpr(t0),
- mkU32(0x0000ff00)),
- mkU32(0x00000000)));
- assign(t8, binop(Iop_CmpNE32,
- binop(Iop_And32,
- mkexpr(t0),
- mkU32(0x0000ff00)),
- mkU32(0x000ff00)));
- /* Shift bits 15..8 and 31..24. */
- assign(t3, binop(Iop_Shl32,
- binop(Iop_Shr32,
- binop(Iop_And32,
- getIReg(rt),
- mkU32(0xff00ff00)),
- mkU8(8)),
- mkU8(rs)));
- assign(t4, binop(Iop_CmpNE32,
- binop(Iop_And32,
- mkexpr(t3),
- mkU32(0xff000000)),
- mkU32(0x00000000)));
- assign(t5, binop(Iop_CmpNE32,
- binop(Iop_And32,
- mkexpr(t3),
- mkU32(0xff000000)),
- mkU32(0xff000000)));
- assign(t9, binop(Iop_CmpNE32,
- binop(Iop_And32,
- mkexpr(t3),
- mkU32(0x0000ff00)),
- mkU32(0x00000000)));
- assign(t10, binop(Iop_CmpNE32,
- binop(Iop_And32,
- mkexpr(t3),
- mkU32(0x0000ff00)),
- mkU32(0x0000ff00)));
-
- assign(t6, binop(Iop_Or32,
- binop(Iop_Or32,
- binop(Iop_And32,
- unop(Iop_1Uto32,
- mkexpr(t1)),
- unop(Iop_1Uto32,
- mkexpr(t2))),
- binop(Iop_And32,
- unop(Iop_1Uto32,
- mkexpr(t7)),
- unop(Iop_1Uto32,
- mkexpr(t8)))),
- binop(Iop_Or32,
- binop(Iop_And32,
- unop(Iop_1Uto32,
- mkexpr(t4)),
- unop(Iop_1Uto32,
- mkexpr(t5))),
- binop(Iop_And32,
- unop(Iop_1Uto32,
- mkexpr(t9)),
- unop(Iop_1Uto32,
- mkexpr(t10))))));
-
- putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
- mkexpr(t6),
- mkU32(0x0)),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x400000)),
- getDSPControl()));
- putIReg(rd, binop(Iop_Or32,
- binop(Iop_Shl32,
- binop(Iop_And32,
- mkexpr(t3),
- mkU32(0x00ff00ff)),
- mkU8(8)),
- binop(Iop_And32,
- mkexpr(t0),
- mkU32(0x00ff00ff))));
- }
- break;
- }
- case 0x3: { /* SHRL.QB */
- DIP("shrl.qb r%u, r%u, %u", rd, rt, rs);
- vassert(!mode64);
- t0 = newTemp(Ity_I32);
- t1 = newTemp(Ity_I8);
- t2 = newTemp(Ity_I32);
- t3 = newTemp(Ity_I8);
- t4 = newTemp(Ity_I32);
- t5 = newTemp(Ity_I8);
- t6 = newTemp(Ity_I32);
- t7 = newTemp(Ity_I8);
- t9 = newTemp(Ity_I32);
-
- assign(t9, binop(Iop_And32, getIReg(rs), mkU32(0x7)));
- assign(t0, unop(Iop_8Uto32,
- unop(Iop_16to8,
- unop(Iop_32to16, getIReg(rt)))));
- assign(t1, unop(Iop_32to8,
- binop(Iop_Shr32,
- mkexpr(t0),
- unop(Iop_32to8, mkexpr(t9)))));
-
- assign(t2, unop(Iop_8Uto32,
- unop(Iop_16HIto8,
- unop(Iop_32to16, getIReg(rt)))));
- assign(t3, unop(Iop_32to8,
- binop(Iop_Shr32,
- mkexpr(t2),
- unop(Iop_32to8, mkexpr(t9)))));
- assign(t4, unop(Iop_8Uto32,
- unop(Iop_16to8,
- unop(Iop_32HIto16, getIReg(rt)))));
- assign(t5, unop(Iop_32to8,
- binop(Iop_Shr32,
- mkexpr(t4),
- unop(Iop_32to8, mkexpr(t9)))));
-
- assign(t6, unop(Iop_8Uto32,
- unop(Iop_16HIto8,
- unop(Iop_32HIto16, getIReg(rt)))));
- assign(t7, unop(Iop_32to8,
- binop(Iop_Shr32,
- mkexpr(t6),
- unop(Iop_32to8, mkexpr(t9)))));
- putIReg(rd, IRExpr_ITE(binop(Iop_CmpEQ32,
- mkexpr(t9),
- mkU32(0x0)),
- getIReg(rt),
- binop(Iop_16HLto32,
- binop(Iop_8HLto16,
- mkexpr(t7),
- mkexpr(t5)),
- binop(Iop_8HLto16,
- mkexpr(t3),
- mkexpr(t1)))));
- break;
- }
- case 0x2: { /* SHLLV.QB */
- DIP("shllv.qb r%u, r%u, r%u", rd, rt, rs);
- vassert(!mode64);
- t0 = newTemp(Ity_I32);
- t1 = newTemp(Ity_I1);
- t2 = newTemp(Ity_I1);
- t3 = newTemp(Ity_I32);
- t4 = newTemp(Ity_I1);
- t5 = newTemp(Ity_I1);
- t6 = newTemp(Ity_I32);
- t7 = newTemp(Ity_I1);
- t8 = newTemp(Ity_I1);
- t9 = newTemp(Ity_I1);
- t10 = newTemp(Ity_I1);
- t11 = newTemp(Ity_I8);
-
- assign(t11, unop(Iop_32to8,
- binop(Iop_And32,
- getIReg(rs),
- mkU32(0x7))));
- /* Shift bits 7..0 and 23..16. */
- assign(t0, binop(Iop_Shl32,
- binop(Iop_And32,
- getIReg(rt),
- mkU32(0x00ff00ff)),
- mkexpr(t11)));
- assign(t1, binop(Iop_CmpNE32,
- binop(Iop_And32,
- mkexpr(t0),
- mkU32(0xff000000)),
- mkU32(0x00000000)));
- assign(t2, binop(Iop_CmpNE32,
- binop(Iop_And32,
- mkexpr(t0),
- mkU32(0xff000000)),
- mkU32(0xff000000)));
- assign(t7, binop(Iop_CmpNE32,
- binop(Iop_And32,
- mkexpr(t0),
- mkU32(0x0000ff00)),
- mkU32(0x00000000)));
- assign(t8, binop(Iop_CmpNE32,
- binop(Iop_And32,
- mkexpr(t0),
- mkU32(0x0000ff00)),
- mkU32(0x000ff00)));
- /* Shift bits 15..8 and 31..24. */
- assign(t3, binop(Iop_Shl32,
- binop(Iop_Shr32,
- binop(Iop_And32,
- getIReg(rt),
- mkU32(0xff00ff00)),
- mkU8(8)),
- mkexpr(t11)));
- assign(t4, binop(Iop_CmpNE32,
- binop(Iop_And32,
- mkexpr(t3),
- mkU32(0xff000000)),
- mkU32(0x00000000)));
- assign(t5, binop(Iop_CmpNE32,
- binop(Iop_And32,
- mkexpr(t3),
- mkU32(0xff000000)),
- mkU32(0xff000000)));
- assign(t9, binop(Iop_CmpNE32,
- binop(Iop_And32,
- mkexpr(t3),
- mkU32(0x0000ff00)),
- mkU32(0x00000000)));
- assign(t10, binop(Iop_CmpNE32,
- binop(Iop_And32,
- mkexpr(t3),
- mkU32(0x0000ff00)),
- mkU32(0x0000ff00)));
+ break;
+ }
+ }
- assign(t6, binop(Iop_Or32,
- binop(Iop_Or32,
- binop(Iop_And32,
- unop(Iop_1Uto32,
- mkexpr(t1)),
- unop(Iop_1Uto32,
- mkexpr(t2))),
- binop(Iop_And32,
- unop(Iop_1Uto32,
- mkexpr(t7)),
- unop(Iop_1Uto32,
- mkexpr(t8)))),
- binop(Iop_Or32,
- binop(Iop_And32,
- unop(Iop_1Uto32,
- mkexpr(t4)),
- unop(Iop_1Uto32,
- mkexpr(t5))),
- binop(Iop_And32,
- unop(Iop_1Uto32,
- mkexpr(t9)),
- unop(Iop_1Uto32,
- mkexpr(t10))))));
-
- putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
- mkexpr(t6),
- mkU32(0x0)),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x400000)),
- getDSPControl()));
- putIReg(rd, IRExpr_ITE(binop(Iop_CmpEQ32,
- unop(Iop_8Uto32, mkexpr(t11)),
- mkU32(0)),
- getIReg(rt),
- binop(Iop_Or32,
- binop(Iop_Shl32,
- binop(Iop_And32,
- mkexpr(t3),
- mkU32(0xff00ff)),
- mkU8(8)),
- binop(Iop_And32,
- mkexpr(t0),
- mkU32(0x00ff00ff)))));
- break;
- }
- case 0x1: { /* SHRLV.QB */
- DIP("shrlv.qb r%u, r%u, r%u", rd, rt, rs);
- vassert(!mode64);
- t0 = newTemp(Ity_I8);
- t1 = newTemp(Ity_I8);
- t2 = newTemp(Ity_I8);
- t3 = newTemp(Ity_I8);
+ break;
+ }
- assign(t0, unop(Iop_32to8,
- binop(Iop_Shr32,
- unop(Iop_8Uto32,
- unop(Iop_32to8, getIReg(rt))),
- mkU8(rs))));
- assign(t1, unop(Iop_32to8,
- binop(Iop_Shr32,
- unop(Iop_8Uto32,
- unop(Iop_16HIto8,
- unop(Iop_32to16,
- getIReg(rt)))),
- mkU8(rs))));
- assign(t2, unop(Iop_32to8,
- binop(Iop_Shr32,
- unop(Iop_8Uto32,
- unop(Iop_16to8,
- unop(Iop_32HIto16,
- getIReg(rt)))),
- mkU8(rs))));
- assign(t3, unop(Iop_32to8,
- binop(Iop_Shr32,
- unop(Iop_8Uto32,
- unop(Iop_16HIto8,
- unop(Iop_32HIto16,
- getIReg(rt)))),
- mkU8(rs))));
- putIReg(rd,
- binop(Iop_16HLto32,
- binop(Iop_8HLto16, mkexpr(t3), mkexpr(t2)),
- binop(Iop_8HLto16, mkexpr(t1), mkexpr(t0))));
- break;
- }
- case 0x4: { /* SHRA.QB */
- DIP("shra.qb r%u, r%u, %u", rd, rt, rs);
- vassert(!mode64);
- t0 = newTemp(Ity_I32);
- t1 = newTemp(Ity_I32);
- t2 = newTemp(Ity_I32);
- t3 = newTemp(Ity_I32);
- t4 = newTemp(Ity_I32);
- t5 = newTemp(Ity_I32);
- t6 = newTemp(Ity_I32);
- t7 = newTemp(Ity_I32);
- t8 = newTemp(Ity_I32);
- t9 = newTemp(Ity_I32);
- t10 = newTemp(Ity_I32);
- t11 = newTemp(Ity_I32);
-
- /* ========== GPR[rt]_31..24 ========== */
- assign(t1,
- unop(Iop_8Uto32,
- unop(Iop_16HIto8,
- unop(Iop_32HIto16, getIReg(rt)))));
- assign(t2,
- binop(Iop_Shr32, mkexpr(t1), mkU8(rs)));
- /* tempD_7..0 */
- assign(t0,
- binop(Iop_Or32,
- mkexpr(t2),
- binop(Iop_Shl32,
- IRExpr_ITE(binop(Iop_CmpEQ32,
- binop(Iop_And32,
- mkexpr(t1),
- mkU32(0x00000080)
- ),
- mkU32(0x00000080)),
- mkU32(0xFFFFFFFF),
- mkU32(0x00000000)),
- binop(Iop_Sub8, mkU8(0x8), mkU8(rs)))));
-
- /* ========== GPR[rt]_23..16 ========== */
- assign(t4,
- unop(Iop_8Uto32,
- unop(Iop_16to8,
- unop(Iop_32HIto16, getIReg(rt)))));
- assign(t5, binop(Iop_Shr32, mkexpr(t4), mkU8(rs)));
- /* tempC_7..0 */
- assign(t3,
- binop(Iop_Or32,
- mkexpr(t5),
- binop(Iop_Shl32,
- IRExpr_ITE(binop(Iop_CmpEQ32,
- binop(Iop_And32,
- mkexpr(t4),
- mkU32(0x00000080)
- ),
- mkU32(0x00000080)),
- mkU32(0xFFFFFFFF),
- mkU32(0x00000000)),
- binop(Iop_Sub8, mkU8(0x8), mkU8(rs)))));
-
- /* ========== GPR[rt]_15..8 ========== */
- assign(t7,
- unop(Iop_8Uto32,
- unop(Iop_16HIto8,
- unop(Iop_32to16, getIReg(rt)))));
- assign(t8, binop(Iop_Shr32, mkexpr(t7), mkU8(rs)));
- /* tempB_7..0 */
- assign(t6,
- binop(Iop_Or32,
- mkexpr(t8),
- binop(Iop_Shl32,
- IRExpr_ITE(binop(Iop_CmpEQ32,
- binop(Iop_And32,
- mkexpr(t7),
- mkU32(0x00000080)
- ),
- mkU32(0x00000080)),
- mkU32(0xFFFFFFFF),
- mkU32(0x00000000)),
- binop(Iop_Sub8, mkU8(0x8), mkU8(rs)))));
-
- /* ========== GPR[rt]_7..0 ========== */
- assign(t10,
- unop(Iop_8Uto32,
- unop(Iop_16to8,
- unop(Iop_32to16, getIReg(rt)))));
- assign(t11, binop(Iop_Shr32, mkexpr(t10), mkU8(rs)));
- /* tempB_7..0 */
- assign(t9,
- binop(Iop_Or32,
- mkexpr(t11),
- binop(Iop_Shl32,
- IRExpr_ITE(binop(Iop_CmpEQ32,
- binop(Iop_And32,
- mkexpr(t10),
- mkU32(0x00000080)
- ),
- mkU32(0x00000080)),
- mkU32(0xFFFFFFFF),
- mkU32(0x00000000)),
- binop(Iop_Sub8, mkU8(0x8), mkU8(rs)))));
-
- putIReg(rd,
- binop(Iop_16HLto32,
- binop(Iop_8HLto16,
- unop(Iop_32to8, mkexpr(t0)),
- unop(Iop_32to8, mkexpr(t3))),
- binop(Iop_8HLto16,
- unop(Iop_32to8, mkexpr(t6)),
- unop(Iop_32to8, mkexpr(t9)))));
- break;
- }
- case 0x5: { /* SHRA_R.QB */
- DIP("shra_r.qb r%u, r%u, %u", rd, rt, rs);
- vassert(!mode64);
- t0 = newTemp(Ity_I32);
- t1 = newTemp(Ity_I8);
- t2 = newTemp(Ity_I32);
- t3 = newTemp(Ity_I8);
- t4 = newTemp(Ity_I32);
- t5 = newTemp(Ity_I8);
- t6 = newTemp(Ity_I32);
- t7 = newTemp(Ity_I8);
-
- if (0 == rs) {
- putIReg(rd, getIReg(rt));
- } else {
- assign(t0, unop(Iop_8Sto32,
- unop(Iop_16to8,
- unop(Iop_32to16, getIReg(rt)))));
- assign(t1, unop(Iop_32to8,
- binop(Iop_Sar32,
- binop(Iop_Add32,
- mkexpr(t0),
- binop(Iop_Shl32,
- mkU32(0x1),
- mkU8(rs-1))),
- mkU8(rs))));
-
- assign(t2, unop(Iop_8Sto32,
- unop(Iop_16HIto8,
- unop(Iop_32to16, getIReg(rt)))));
- assign(t3, unop(Iop_32to8,
- binop(Iop_Sar32,
- binop(Iop_Add32,
- mkexpr(t2),
- binop(Iop_Shl32,
- mkU32(0x1),
- mkU8(rs-1))),
- mkU8(rs))));
-
- assign(t4, unop(Iop_8Sto32,
- unop(Iop_16to8,
- unop(Iop_32HIto16, getIReg(rt)))));
- assign(t5, unop(Iop_32to8,
- binop(Iop_Sar32,
- binop(Iop_Add32,
- mkexpr(t4),
- binop(Iop_Shl32,
- mkU32(0x1),
- mkU8(rs-1))),
- mkU8(rs))));
-
- assign(t6, unop(Iop_8Sto32,
- unop(Iop_16HIto8,
- unop(Iop_32HIto16, getIReg(rt)))));
- assign(t7, unop(Iop_32to8,
- binop(Iop_Sar32,
- binop(Iop_Add32,
- mkexpr(t6),
- binop(Iop_Shl32,
- mkU32(0x1),
- mkU8(rs-1))),
- mkU8(rs))));
- putIReg(rd, binop(Iop_16HLto32,
- binop(Iop_8HLto16,
- mkexpr(t7), mkexpr(t5)),
- binop(Iop_8HLto16,
- mkexpr(t3), mkexpr(t1))));
- }
- break;
- }
- case 0x6: { /* SHRAV.QB */
- DIP("shrav.qb r%u, r%u, %u", rd, rt, rs);
- vassert(!mode64);
+ case 0x01: { /* SAT_U.df */
+ switch (df) {
+ case 0x00: { /* SAT_U.B */
+ DIP("SAT_U.B w%d, w%d, %d", wd, ws, m);
- t0 = newTemp(Ity_I32);
- t1 = newTemp(Ity_I32);
- t2 = newTemp(Ity_I32);
+ if (m == 7) {
+ putWReg(wd, getWReg(ws));
+ } else {
+ t1 = newTemp(Ity_V128);
+ assign(t1,
+ binop(Iop_CmpEQ8x16,
+ binop(Iop_ShrN8x16,
+ getWReg(ws),
+ mkU8(m + 1)),
+ binop(Iop_64HLtoV128,
+ mkU64(0), mkU64(0))));
+ putWReg(wd,
+ binop(Iop_OrV128,
+ binop(Iop_AndV128,
+ mkexpr(t1),
+ getWReg(ws)),
+ binop(Iop_ShrN8x16,
+ unop(Iop_NotV128,
+ mkexpr(t1)),
+ mkU8(7 - m))));
+ }
- t3 = newTemp(Ity_I32);
- t4 = newTemp(Ity_I32);
- t5 = newTemp(Ity_I32);
+ break;
+ }
- t6 = newTemp(Ity_I32);
- t7 = newTemp(Ity_I32);
- t8 = newTemp(Ity_I32);
+ case 0x01: { /* SAT_U.H */
+ DIP("SAT_U.H w%d, w%d, %d", wd, ws, m);
- t9 = newTemp(Ity_I32);
- t10 = newTemp(Ity_I32);
- t11 = newTemp(Ity_I32);
+ if (m == 15) {
+ putWReg(wd, getWReg(ws));
+ } else {
+ t1 = newTemp(Ity_V128);
+ assign(t1,
+ binop(Iop_CmpEQ16x8,
+ binop(Iop_ShrN16x8,
+ getWReg(ws),
+ mkU8(m + 1)),
+ binop(Iop_64HLtoV128,
+ mkU64(0), mkU64(0))));
+ putWReg(wd,
+ binop(Iop_OrV128,
+ binop(Iop_AndV128,
+ mkexpr(t1),
+ getWReg(ws)),
+ binop(Iop_ShrN16x8,
+ unop(Iop_NotV128,
+ mkexpr(t1)),
+ mkU8(15 - m))));
+ }
- /* ========== GPR[rt]_31..24 ========== */
- assign(t1,
- unop(Iop_8Uto32,
- unop(Iop_16HIto8,
- unop(Iop_32HIto16, getIReg(rt)))));
- assign(t2,
- binop(Iop_Shr32,
- mkexpr(t1),
- unop(Iop_32to8, binop(Iop_And32,
- getIReg(rs),
- mkU32(0x7)))));
- /* tempD_7..0 */
- assign(t0,
- binop(Iop_Or32,
- mkexpr(t2),
- binop(Iop_Shl32,
- IRExpr_ITE(binop(Iop_CmpEQ32,
- binop(Iop_And32,
- mkexpr(t1),
- mkU32(0x00000080)
- ),
- mkU32(0x00000080)),
- mkU32(0xFFFFFFFF),
- mkU32(0x00000000)),
- binop(Iop_Sub8,
- mkU8(0x8),
- unop(Iop_32to8, binop(Iop_And32,
- getIReg(rs),
- mkU32(0x7)))
- ))));
-
- /* ========== GPR[rt]_23..16 ========== */
- assign(t4,
- unop(Iop_8Uto32,
- unop(Iop_16to8,
- unop(Iop_32HIto16, getIReg(rt)))));
- assign(t5,
- binop(Iop_Shr32,
- mkexpr(t4),
- unop(Iop_32to8, binop(Iop_And32,
- getIReg(rs),
- mkU32(0x7)))));
- /* tempC_7..0 */
- assign(t3,
- binop(Iop_Or32,
- mkexpr(t5),
- binop(Iop_Shl32,
- IRExpr_ITE(binop(Iop_CmpEQ32,
- binop(Iop_And32,
- mkexpr(t4),
- mkU32(0x00000080)
- ),
- mkU32(0x00000080)),
- mkU32(0xFFFFFFFF),
- mkU32(0x00000000)),
- binop(Iop_Sub8,
- mkU8(0x8),
- unop(Iop_32to8, binop(Iop_And32,
- getIReg(rs),
- mkU32(0x7)))
- ))));
-
- /* ========== GPR[rt]_15..8 ========== */
- assign(t7,
- unop(Iop_8Uto32,
- unop(Iop_16HIto8,
- unop(Iop_32to16, getIReg(rt)))));
- assign(t8,
- binop(Iop_Shr32,
- mkexpr(t7),
- unop(Iop_32to8, binop(Iop_And32,
- getIReg(rs),
- mkU32(0x7)))));
- /* tempB_7..0 */
- assign(t6,
- binop(Iop_Or32,
- mkexpr(t8),
- binop(Iop_Shl32,
- IRExpr_ITE(binop(Iop_CmpEQ32,
- binop(Iop_And32,
- mkexpr(t7),
- mkU32(0x00000080)
- ),
- mkU32(0x00000080)),
- mkU32(0xFFFFFFFF),
- mkU32(0x00000000)),
- binop(Iop_Sub8,
- mkU8(0x8),
- unop(Iop_32to8, binop(Iop_And32,
- getIReg(rs),
- mkU32(0x7)))
- ))));
-
- /* ========== GPR[rt]_7..0 ========== */
- assign(t10,
- unop(Iop_8Uto32,
- unop(Iop_16to8,
- unop(Iop_32to16, getIReg(rt)))));
- assign(t11,
- binop(Iop_Shr32,
- mkexpr(t10),
- unop(Iop_32to8, binop(Iop_And32,
- getIReg(rs),
- mkU32(0x7)))));
- /* tempB_7..0 */
- assign(t9,
- binop(Iop_Or32,
- mkexpr(t11),
- binop(Iop_Shl32,
- IRExpr_ITE(binop(Iop_CmpEQ32,
- binop(Iop_And32,
- mkexpr(t10),
- mkU32(0x00000080)
- ),
- mkU32(0x00000080)),
- mkU32(0xFFFFFFFF),
- mkU32(0x00000000)),
- binop(Iop_Sub8,
- mkU8(0x8),
- unop(Iop_32to8, binop(Iop_And32,
- getIReg(rs),
- mkU32(0x7)))
- ))));
-
- putIReg(rd,
- binop(Iop_16HLto32,
- binop(Iop_8HLto16,
- unop(Iop_32to8,
- IRExpr_ITE(binop(Iop_CmpEQ32,
- binop(Iop_And32,
- mkU32(rs),
- mkU32(0x7)
- ),
- mkU32(0x0)),
- mkexpr(t1),
- mkexpr(t0))),
- unop(Iop_32to8,
- IRExpr_ITE(binop(Iop_CmpEQ32,
- binop(Iop_And32,
- mkU32(rs),
- mkU32(0x7)
- ),
- mkU32(0x0)),
- mkexpr(t2),
- mkexpr(t3)))),
- binop(Iop_8HLto16,
- unop(Iop_32to8,
- IRExpr_ITE(binop(Iop_CmpEQ32,
- binop(Iop_And32,
- mkU32(rs),
- mkU32(0x7)
- ),
- mkU32(0x0)),
- mkexpr(t5),
- mkexpr(t6))),
- unop(Iop_32to8,
- IRExpr_ITE(binop(Iop_CmpEQ32,
- binop(Iop_And32,
- mkU32(rs),
- mkU32(0x7)
- ),
- mkU32(0x0)),
- mkexpr(t8),
- mkexpr(t9))))));
- break;
- }
- case 0x7: { /* SHRAV_R.QB */
- DIP("shrav_r.qb r%u, r%u, r%u", rd, rt, rs);
- vassert(!mode64);
- t0 = newTemp(Ity_I32);
- t1 = newTemp(Ity_I8);
- t2 = newTemp(Ity_I32);
- t3 = newTemp(Ity_I8);
- t4 = newTemp(Ity_I32);
- t5 = newTemp(Ity_I8);
- t6 = newTemp(Ity_I32);
- t7 = newTemp(Ity_I8);
- t8 = newTemp(Ity_I8);
- t9 = newTemp(Ity_I32);
-
- assign(t9, binop(Iop_And32, getIReg(rs), mkU32(0x7)));
- assign(t8, unop(Iop_32to8,
- binop(Iop_Sub32, mkexpr(t9), mkU32(0x1))));
- assign(t0, unop(Iop_8Sto32,
- unop(Iop_16to8,
- unop(Iop_32to16, getIReg(rt)))));
- assign(t1, unop(Iop_32to8,
- binop(Iop_Sar32,
- binop(Iop_Add32,
- mkexpr(t0),
- binop(Iop_Shl32,
- mkU32(0x1),
- mkexpr(t8))),
- unop(Iop_32to8,
- mkexpr(t9)))));
-
- assign(t2, unop(Iop_8Sto32,
- unop(Iop_16HIto8,
- unop(Iop_32to16, getIReg(rt)))));
- assign(t3, unop(Iop_32to8,
- binop(Iop_Sar32,
- binop(Iop_Add32,
- mkexpr(t2),
- binop(Iop_Shl32,
- mkU32(0x1),
- mkexpr(t8))),
- unop(Iop_32to8, mkexpr(t9)))));
-
- assign(t4, unop(Iop_8Sto32,
- unop(Iop_16to8,
- unop(Iop_32HIto16, getIReg(rt)))));
- assign(t5, unop(Iop_32to8,
- binop(Iop_Sar32,
- binop(Iop_Add32,
- mkexpr(t4),
- binop(Iop_Shl32,
- mkU32(0x1),
- mkexpr(t8))),
- unop(Iop_32to8, mkexpr(t9)))));
-
- assign(t6, unop(Iop_8Sto32,
- unop(Iop_16HIto8,
- unop(Iop_32HIto16, getIReg(rt)))));
- assign(t7, unop(Iop_32to8,
- binop(Iop_Sar32,
- binop(Iop_Add32,
- mkexpr(t6),
- binop(Iop_Shl32,
- mkU32(0x1),
- mkexpr(t8))),
- unop(Iop_32to8, mkexpr(t9)))));
- putIReg(rd, IRExpr_ITE(binop(Iop_CmpEQ32,
- mkexpr(t9),
- mkU32(0x0)),
- getIReg(rt),
- binop(Iop_16HLto32,
- binop(Iop_8HLto16,
- mkexpr(t7),
- mkexpr(t5)),
- binop(Iop_8HLto16,
- mkexpr(t3),
- mkexpr(t1)))));
- break;
- }
- case 0x8: { /* SHLL.PH */
- DIP("shll.ph r%u, r%u, %u", rd, rt, rs);
- vassert(!mode64);
- t0 = newTemp(Ity_I32);
- t1 = newTemp(Ity_I32);
- t2 = newTemp(Ity_I32);
- t3 = newTemp(Ity_I32);
- t4 = newTemp(Ity_I32);
- t5 = newTemp(Ity_I32);
- t6 = newTemp(Ity_I32);
- t7 = newTemp(Ity_I32);
+ break;
+ }
- if (0 == rs) {
- putIReg(rd, getIReg(rt));
- } else {
- /* Shift lower 16 bits. */
- assign(t0, binop(Iop_Shl32,
- unop(Iop_16Sto32,
- unop(Iop_32to16, getIReg(rt))),
- mkU8(rs)));
-
- assign(t1, unop(Iop_1Uto32,
- binop(Iop_CmpNE32,
- binop(Iop_Sar32,
- mkexpr(t0),
- mkU8(16)),
- mkU32(0))));
- assign(t2, unop(Iop_1Uto32,
- binop(Iop_CmpNE32,
- binop(Iop_Sar32,
- mkexpr(t0),
- mkU8(16)),
- mkU32(0xffffffff))));
- assign(t3, binop(Iop_And32,
- mkexpr(t1),
- mkexpr(t2)));
- putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
- mkexpr(t3),
- mkU32(0x1)),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x400000)),
- getDSPControl()));
- putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
- binop(Iop_And32,
- getIReg(rt),
- mkU32(0x00008000)),
- binop(Iop_And32,
- mkexpr(t0),
- mkU32(0x00008000))
- ),
- getDSPControl(),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x400000))));
- /* Shift higher 16 bits. */
- assign(t4, binop(Iop_Shl32,
- unop(Iop_16Sto32,
- unop(Iop_32HIto16, getIReg(rt))),
- mkU8(rs)));
-
- assign(t5, unop(Iop_1Uto32,
- binop(Iop_CmpNE32,
- binop(Iop_Sar32,
- mkexpr(t4),
- mkU8(16)),
- mkU32(0))));
- assign(t6, unop(Iop_1Uto32,
- binop(Iop_CmpNE32,
- binop(Iop_Sar32,
- mkexpr(t4),
- mkU8(16)),
- mkU32(0xffffffff))));
- assign(t7, binop(Iop_And32,
- mkexpr(t5),
- mkexpr(t6)));
- putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
- mkexpr(t7),
- mkU32(0x1)),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x400000)),
- getDSPControl()));
- putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
- mkexpr(t7),
- mkU32(0x1)),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x400000)),
- getDSPControl()));
- putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
- binop(Iop_And32,
- getIReg(rt),
- mkU32(0x80000000)),
- binop(Iop_Shl32,
- binop(Iop_And32,
- mkexpr(t4),
- mkU32(0x00008000)),
- mkU8(16))
- ),
- getDSPControl(),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x400000))));
- putIReg(rd, binop(Iop_16HLto32,
- unop(Iop_32to16, mkexpr(t4)),
- unop(Iop_32to16, mkexpr(t0))));
- }
- break;
- }
- case 0x9: { /* SHRA.PH */
- DIP("shra.ph r%u, r%u, %u", rd, rt, rs);
- vassert(!mode64);
- t0 = newTemp(Ity_I32);
- t1 = newTemp(Ity_I32);
- if (0 == rs) {
- putIReg(rd, getIReg(rt));
- } else {
- assign(t0, binop(Iop_Sar32,
- unop(Iop_16Sto32,
- unop(Iop_32to16, getIReg(rt))),
- mkU8(rs)));
- assign(t1, binop(Iop_Sar32,
- unop(Iop_16Sto32,
- unop(Iop_32HIto16, getIReg(rt))),
- mkU8(rs)));
- putIReg(rd, binop(Iop_16HLto32,
- unop(Iop_32to16, mkexpr(t1)),
- unop(Iop_32to16, mkexpr(t0))));
- }
- break;
- }
- case 0xA: { /* SHLLV.PH */
- DIP("shllv.ph r%u, r%u, r%u", rd, rt, rs);
- vassert(!mode64);
- t0 = newTemp(Ity_I32);
- t2 = newTemp(Ity_I32);
- t3 = newTemp(Ity_I1);
- t4 = newTemp(Ity_I1);
- t5 = newTemp(Ity_I32);
- t6 = newTemp(Ity_I32);
- t7 = newTemp(Ity_I1);
- t8 = newTemp(Ity_I1);
- t9 = newTemp(Ity_I32);
- t10 = newTemp(Ity_I32);
- t11 = newTemp(Ity_I32);
- t12 = newTemp(Ity_I1);
- t13 = newTemp(Ity_I1);
-
- assign(t0, binop(Iop_And32, getIReg(rs), mkU32(0x0f)));
-
- /* Shift lower 16 bits. */
- assign(t2, binop(Iop_Shl32,
- unop(Iop_16Sto32,
- unop(Iop_32to16, getIReg(rt))),
- unop(Iop_32to8, mkexpr(t0))));
-
- assign(t3, binop(Iop_CmpNE32,
- unop(Iop_16Sto32,
- unop(Iop_32HIto16, mkexpr(t2))),
- mkU32(0x00000000)));
- assign(t4, binop(Iop_CmpNE32,
- unop(Iop_16Sto32,
- unop(Iop_32HIto16, mkexpr(t2))),
- mkU32(0xffffffff)));
- assign(t10, binop(Iop_And32,
- unop(Iop_1Sto32, mkexpr(t3)),
- unop(Iop_1Sto32, mkexpr(t4))));
- assign(t5, binop(Iop_Shr32,
- binop(Iop_And32,
- getIReg(rt),
- mkU32(0x00008000)),
- mkU8(15)));
- assign(t12, binop(Iop_CmpEQ32,
- mkexpr(t5),
- binop(Iop_Shr32,
- binop(Iop_And32,
- mkexpr(t2),
- mkU32(0x00008000)),
- mkU8(15))));
-
- putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
- mkexpr(t10),
- mkU32(0x0)),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x400000)),
- IRExpr_ITE(mkexpr(t12),
- getDSPControl(),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x400000)))
- ));
- /* Shift higher 16 bits. */
- assign(t6, binop(Iop_Shl32,
- unop(Iop_16Sto32,
- unop(Iop_32HIto16, getIReg(rt))),
- unop(Iop_32to8, mkexpr(t0))));
-
- assign(t7, binop(Iop_CmpNE32,
- unop(Iop_16Sto32,
- unop(Iop_32HIto16, mkexpr(t6))),
- mkU32(0x00000000)));
- assign(t8, binop(Iop_CmpNE32,
- unop(Iop_16Sto32,
- unop(Iop_32HIto16, mkexpr(t6))),
- mkU32(0xffffffff)));
- assign(t11, binop(Iop_And32,
- unop(Iop_1Sto32, mkexpr(t7)),
- unop(Iop_1Sto32, mkexpr(t8))));
-
- assign(t9, binop(Iop_Shr32,
- binop(Iop_And32,
- getIReg(rt),
- mkU32(0x80000000)),
- mkU8(31)));
- assign(t13, binop(Iop_CmpEQ32,
- mkexpr(t9),
- binop(Iop_Shr32,
- binop(Iop_And32,
- mkexpr(t6),
- mkU32(0x00008000)),
- mkU8(15))));
-
- putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
- mkexpr(t11),
- mkU32(0x0)),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x400000)),
- IRExpr_ITE(mkexpr(t13),
- getDSPControl(),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x400000)))
- ));
-
- putIReg(rd, binop(Iop_16HLto32,
- unop(Iop_32to16, mkexpr(t6)),
- unop(Iop_32to16, mkexpr(t2))));
- break;
- }
- case 0xB: { /* SHRAV.PH */
- DIP("shrav.ph r%u, r%u, r%u", rd, rt, rs);
- vassert(!mode64);
- t0 = newTemp(Ity_I32);
- t1 = newTemp(Ity_I1);
- t2 = newTemp(Ity_I32);
- t3 = newTemp(Ity_I32);
-
- assign(t0, binop(Iop_And32, getIReg(rs), mkU32(0x0f)));
- assign(t1, binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x0)));
- assign(t2, binop(Iop_Sar32,
- unop(Iop_16Sto32,
- unop(Iop_32to16, getIReg(rt))),
- unop(Iop_32to8, mkexpr(t0))));
- assign(t3, binop(Iop_Sar32,
- unop(Iop_16Sto32,
- unop(Iop_32HIto16, getIReg(rt))),
- unop(Iop_32to8, mkexpr(t0))));
- putIReg(rd,
- binop(Iop_16HLto32,
- IRExpr_ITE(mkexpr(t1),
- unop(Iop_32HIto16, getIReg(rt)),
- unop(Iop_32to16, mkexpr(t3))),
- IRExpr_ITE(mkexpr(t1),
- unop(Iop_32to16, getIReg(rt)),
- unop(Iop_32to16, mkexpr(t2)))));
- break;
- }
- case 0xC: { /* SHLL_S.PH */
- DIP("shll_s.ph r%u, r%u, %u", rd, rt, rs);
- vassert(!mode64);
- t0 = newTemp(Ity_I32);
- t1 = newTemp(Ity_I32);
- t2 = newTemp(Ity_I32);
- t3 = newTemp(Ity_I32);
- t4 = newTemp(Ity_I32);
- t5 = newTemp(Ity_I32);
- t6 = newTemp(Ity_I32);
- t7 = newTemp(Ity_I32);
- t8 = newTemp(Ity_I32);
- t9 = newTemp(Ity_I32);
- t10 = newTemp(Ity_I32);
- t11 = newTemp(Ity_I32);
- t12 = newTemp(Ity_I32);
- t13 = newTemp(Ity_I32);
- t14 = newTemp(Ity_I32);
-
- if (0 == rs) {
- putIReg(rd, getIReg(rt));
- } else {
- /* Shift lower 16 bits. */
- assign(t0, binop(Iop_Shl32,
- unop(Iop_16Sto32,
- unop(Iop_32to16, getIReg(rt))),
- mkU8(rs)));
-
- assign(t1, unop(Iop_1Uto32,
- binop(Iop_CmpNE32,
- binop(Iop_Sar32,
- mkexpr(t0),
- mkU8(16)),
- mkU32(0))));
- assign(t2, unop(Iop_1Uto32,
- binop(Iop_CmpNE32,
- binop(Iop_Sar32,
- mkexpr(t0),
- mkU8(16)),
- mkU32(0xffffffff))));
- assign(t3, binop(Iop_And32,
- mkexpr(t1),
- mkexpr(t2)));
- putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
- mkexpr(t3),
- mkU32(0x1)),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x400000)),
- getDSPControl()));
- putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
- binop(Iop_And32,
- getIReg(rt),
- mkU32(0x00008000)),
- binop(Iop_And32,
- mkexpr(t0),
- mkU32(0x00008000))
- ),
- getDSPControl(),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x400000))));
- assign(t8,
- IRExpr_ITE(binop(Iop_CmpEQ32,
- mkexpr(t3),
- mkU32(0x1)),
- IRExpr_ITE(binop(Iop_CmpEQ32,
- binop(Iop_And32,
- getIReg(rt),
- mkU32(0x8000)),
- mkU32(0)),
- mkU32(0x00007fff),
- mkU32(0x00008000)),
- binop(Iop_And32,
- mkexpr(t0),
- mkU32(0x0000ffff))));
- assign(t10,
- IRExpr_ITE(binop(Iop_CmpEQ32,
- binop(Iop_And32,
- getIReg(rt),
- mkU32(0x00008000)),
- binop(Iop_And32,
- mkexpr(t0),
- mkU32(0x00008000))),
- mkexpr(t8),
- IRExpr_ITE(binop(Iop_CmpEQ32,
- binop(Iop_And32,
- getIReg(rt),
- mkU32(0x8000)),
- mkU32(0)),
- mkU32(0x00007fff),
- mkU32(0x00008000))));
- /* Shift higher 16 bits. */
- assign(t4, binop(Iop_Shl32,
- unop(Iop_16Sto32,
- unop(Iop_32HIto16, getIReg(rt))),
- mkU8(rs)));
-
- assign(t5, unop(Iop_1Uto32,
- binop(Iop_CmpNE32,
- binop(Iop_Sar32,
- mkexpr(t4),
- mkU8(16)),
- mkU32(0))));
- assign(t6, unop(Iop_1Uto32,
- binop(Iop_CmpNE32,
- binop(Iop_Sar32,
- mkexpr(t4),
- mkU8(16)),
- mkU32(0xffffffff))));
- assign(t7, binop(Iop_And32,
- mkexpr(t5),
- mkexpr(t6)));
- putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
- mkexpr(t7),
- mkU32(0x1)),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x400000)),
- getDSPControl()));
- putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
- mkexpr(t7),
- mkU32(0x1)),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x400000)),
- getDSPControl()));
- assign(t12, binop(Iop_Shl32,
- binop(Iop_And32,
- mkexpr(t4),
- mkU32(0x8000)),
- mkU8(16)));
- putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
- binop(Iop_And32,
- getIReg(rt),
- mkU32(0x80000000)),
- mkexpr(t12)),
- getDSPControl(),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x400000))));
- assign(t13, IRExpr_ITE(binop(Iop_CmpEQ32,
- binop(Iop_And32,
- getIReg(rt),
- mkU32(0x80000000)),
- mkU32(0)),
- mkU32(0x7fff0000),
- mkU32(0x80000000)));
- assign(t9,
- IRExpr_ITE(binop(Iop_CmpEQ32,
- mkexpr(t7),
- mkU32(0x1)),
- mkexpr(t13),
- binop(Iop_Shl32,
- binop(Iop_And32,
- mkexpr(t4),
- mkU32(0x0000ffff)),
- mkU8(16))));
- assign(t14, IRExpr_ITE(binop(Iop_CmpEQ32,
- binop(Iop_And32,
- getIReg(rt),
- mkU32(0x80000000)),
- mkU32(0)),
- mkU32(0x7fff0000),
- mkU32(0x80000000)));
- assign(t11,
- IRExpr_ITE(binop(Iop_CmpEQ32,
- binop(Iop_And32,
- getIReg(rt),
- mkU32(0x80000000)),
- binop(Iop_Shl32,
- binop(Iop_And32,
- mkexpr(t4),
- mkU32(0x00008000)),
- mkU8(16))),
- mkexpr(t9),
- mkexpr(t14)));
- putIReg(rd, binop(Iop_Or32,
- mkexpr(t10),
- mkexpr(t11)));
- }
- break;
- }
- case 0xD: { /* SHRA_R.PH */
- DIP("shra.ph r%u, r%u, %u", rd, rt, rs);
- vassert(!mode64);
- t0 = newTemp(Ity_I32);
- t1 = newTemp(Ity_I32);
- if (0 == rs) {
- putIReg(rd, getIReg(rt));
- } else {
- assign(t0, binop(Iop_Sar32,
- binop(Iop_Add32,
- unop(Iop_16Sto32,
- unop(Iop_32to16,
- getIReg(rt))),
- binop(Iop_Shl32,
- mkU32(0x1),
- mkU8(rs-1))),
- mkU8(rs)));
- assign(t1, binop(Iop_Sar32,
- binop(Iop_Add32,
- unop(Iop_16Sto32,
- unop(Iop_32HIto16,
- getIReg(rt))),
- binop(Iop_Shl32,
- mkU32(0x1),
- mkU8(rs-1))),
- mkU8(rs)));
- putIReg(rd, binop(Iop_16HLto32,
- unop(Iop_32to16, mkexpr(t1)),
- unop(Iop_32to16, mkexpr(t0))));
- }
- break;
- }
- case 0xE: { /* SHLLV_S.PH */
- DIP("shllv_s.ph r%u, r%u, r%u", rd, rt, rs);
- vassert(!mode64);
- t0 = newTemp(Ity_I32);
- t2 = newTemp(Ity_I32);
- t3 = newTemp(Ity_I1);
- t4 = newTemp(Ity_I1);
- t5 = newTemp(Ity_I32);
- t6 = newTemp(Ity_I32);
- t7 = newTemp(Ity_I1);
- t8 = newTemp(Ity_I1);
- t9 = newTemp(Ity_I32);
- t10 = newTemp(Ity_I32);
- t11 = newTemp(Ity_I32);
- t12 = newTemp(Ity_I1);
- t13 = newTemp(Ity_I1);
- t14 = newTemp(Ity_I16);
- t15 = newTemp(Ity_I16);
- t16 = newTemp(Ity_I16);
- t17 = newTemp(Ity_I16);
-
- assign(t0, binop(Iop_And32, getIReg(rs), mkU32(0x0f)));
-
- /* Shift lower 16 bits. */
- assign(t2, binop(Iop_Shl32,
- unop(Iop_16Sto32,
- unop(Iop_32to16, getIReg(rt))),
- unop(Iop_32to8, mkexpr(t0))));
-
- assign(t3, binop(Iop_CmpNE32,
- unop(Iop_16Sto32,
- unop(Iop_32HIto16, mkexpr(t2))),
- mkU32(0x00000000)));
- assign(t4, binop(Iop_CmpNE32,
- unop(Iop_16Sto32,
- unop(Iop_32HIto16, mkexpr(t2))),
- mkU32(0xffffffff)));
- assign(t10, binop(Iop_And32,
- unop(Iop_1Sto32, mkexpr(t3)),
- unop(Iop_1Sto32, mkexpr(t4))));
- assign(t5, binop(Iop_Shr32,
- binop(Iop_And32,
- getIReg(rt),
- mkU32(0x00008000)),
- mkU8(15)));
- assign(t12, binop(Iop_CmpEQ32,
- mkexpr(t5),
- binop(Iop_Shr32,
- binop(Iop_And32,
- mkexpr(t2),
- mkU32(0x00008000)),
- mkU8(15))));
-
- putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
- mkexpr(t10),
- mkU32(0x0)),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x400000)),
- IRExpr_ITE(mkexpr(t12),
- getDSPControl(),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x400000)))
- ));
- assign(t14, IRExpr_ITE(binop(Iop_CmpNE32,
- mkexpr(t5),
- mkU32(0x0)),
- mkU16(0x8000),
- mkU16(0x7fff)));
- assign(t15, IRExpr_ITE(binop(Iop_CmpNE32,
- mkexpr(t10),
- mkU32(0x0)),
- mkexpr(t14),
- IRExpr_ITE(mkexpr(t12),
- unop(Iop_32to16,
- mkexpr(t2)),
- mkexpr(t14))));
- /* Shift higher 16 bits. */
- assign(t6, binop(Iop_Shl32,
- unop(Iop_16Sto32,
- unop(Iop_32HIto16, getIReg(rt))),
- unop(Iop_32to8, mkexpr(t0))));
-
- assign(t7, binop(Iop_CmpNE32,
- unop(Iop_16Sto32,
- unop(Iop_32HIto16, mkexpr(t6))),
- mkU32(0x00000000)));
- assign(t8, binop(Iop_CmpNE32,
- unop(Iop_16Sto32,
- unop(Iop_32HIto16, mkexpr(t6))),
- mkU32(0xffffffff)));
- assign(t11, binop(Iop_And32,
- unop(Iop_1Sto32, mkexpr(t7)),
- unop(Iop_1Sto32, mkexpr(t8))));
-
- assign(t9, binop(Iop_Shr32,
- binop(Iop_And32,
- getIReg(rt),
- mkU32(0x80000000)),
- mkU8(31)));
- assign(t13, binop(Iop_CmpEQ32,
- mkexpr(t9),
- binop(Iop_Shr32,
- binop(Iop_And32,
- mkexpr(t6),
- mkU32(0x00008000)),
- mkU8(15))));
-
- putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
- mkexpr(t11),
- mkU32(0x0)),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x400000)),
- IRExpr_ITE(mkexpr(t13),
- getDSPControl(),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x400000)))
- ));
-
- assign(t16, IRExpr_ITE(binop(Iop_CmpNE32,
- mkexpr(t9),
- mkU32(0x0)),
- mkU16(0x8000),
- mkU16(0x7fff)));
- assign(t17, IRExpr_ITE(binop(Iop_CmpNE32,
- mkexpr(t11),
- mkU32(0x0)),
- mkexpr(t16),
- IRExpr_ITE(mkexpr(t13),
- unop(Iop_32to16,
- mkexpr(t6)),
- mkexpr(t16))));
-
- putIReg(rd, binop(Iop_16HLto32, mkexpr(t17), mkexpr(t15)));
- break;
- }
- case 0xF: { /* SHRAV_R.PH */
- DIP("shrav_r.ph r%u, r%u, r%u", rd, rt, rs);
- vassert(!mode64);
- t0 = newTemp(Ity_I32);
- t1 = newTemp(Ity_I1);
- t2 = newTemp(Ity_I8);
- t3 = newTemp(Ity_I32);
- t4 = newTemp(Ity_I32);
-
- assign(t0, binop(Iop_And32, getIReg(rs), mkU32(0x0f)));
- assign(t1, binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x0)));
- assign(t2, unop(Iop_32to8,
- binop(Iop_Sub32, mkexpr(t0), mkU32(1))));
-
- assign(t3, binop(Iop_Sar32,
- binop(Iop_Add32,
- unop(Iop_16Sto32,
- unop(Iop_32to16, getIReg(rt))),
- binop(Iop_Shl32,
- mkU32(0x1),
- mkexpr(t2))),
- unop(Iop_32to8, mkexpr(t0))));
- assign(t4, binop(Iop_Sar32,
- binop(Iop_Add32,
- unop(Iop_16Sto32,
- unop(Iop_32HIto16,
- getIReg(rt))),
- binop(Iop_Shl32,
- mkU32(0x1),
- mkexpr(t2))),
- unop(Iop_32to8, mkexpr(t0))));
-
- putIReg(rd, binop(Iop_16HLto32,
- IRExpr_ITE(mkexpr(t1),
- unop(Iop_32HIto16,
- getIReg(rt)),
- unop(Iop_32to16,
- mkexpr(t4))),
- IRExpr_ITE(mkexpr(t1),
- unop(Iop_32to16, getIReg(rt)),
- unop(Iop_32to16,
- mkexpr(t3)))));
- break;
- }
- case 0x14: { /* SHLL_S.W */
- DIP("shll_s.w r%u, r%u, %u", rd, rt, rs);
- vassert(!mode64);
- t0 = newTemp(Ity_I32);
- t1 = newTemp(Ity_I32);
- t2 = newTemp(Ity_I32);
- t3 = newTemp(Ity_I32);
- t4 = newTemp(Ity_I32);
- t5 = newTemp(Ity_I32);
+ case 0x02: { /* SAT_U.W */
+ DIP("SAT_U.W w%d, w%d, %d", wd, ws, m);
- if (0 == rs) {
- putIReg(rd, getIReg(rt));
- } else {
- /* t0-bits that will be discarded, sign extended to
- 32bits. */
- assign(t0, binop(Iop_Sar32,
- binop(Iop_And32,
- getIReg(rt),
- binop(Iop_Sar32,
- mkU32(0x80000000),
- mkU8(rs-1))),
- mkU8(32-rs)));
-
- assign(t1, IRExpr_ITE(binop(Iop_CmpEQ32,
- binop(Iop_And32,
- getIReg(rt),
- mkU32(0x80000000)),
- mkU32(0x0)),
- mkU32(0x7fffffff),
- mkU32(0x80000000)));
-
- assign(t2, binop(Iop_Shl32, getIReg(rt), mkU8(rs)));
- assign(t3, IRExpr_ITE(binop(Iop_CmpEQ32,
- binop(Iop_And32,
- getIReg(rt),
- mkU32(0x80000000)),
- binop(Iop_And32,
- mkexpr(t2),
- mkU32(0x80000000))),
- mkexpr(t2),
- mkexpr(t1)));
-
- assign(t4, IRExpr_ITE(binop(Iop_CmpNE32,
- mkexpr(t0),
- mkU32(0x0)),
- IRExpr_ITE(binop(Iop_CmpNE32,
- mkexpr(t0),
- mkU32(0xffffffff)
- ),
- mkexpr(t1),
- mkexpr(t3)),
- mkexpr(t3)));
- assign(t5, IRExpr_ITE(binop(Iop_CmpNE32,
- mkexpr(t0),
- mkU32(0xffffffff)),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x400000)),
- getDSPControl()));
- putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
- mkexpr(t0),
- mkU32(0x0)),
- mkexpr(t5),
- getDSPControl()));
- putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
- binop(Iop_And32,
- getIReg(rt),
- mkU32(0x80000000)),
- binop(Iop_And32,
- mkexpr(t2),
- mkU32(0x80000000))
- ),
- getDSPControl(),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x400000))));
- putIReg(rd, mkexpr(t4));
- }
- break;
- }
- case 0x15: { /* SHRA_R.W */
- DIP("shra_r.w r%u, r%u, %u", rd, rt, rs);
- vassert(!mode64);
- if (0 == rs) {
- putIReg(rd, getIReg(rt));
- } else {
- putIReg(rd, binop(Iop_Add32,
- binop(Iop_Sar32,
- getIReg(rt), mkU8(rs)),
- binop(Iop_Shr32,
- binop(Iop_And32,
- getIReg(rt),
- binop(Iop_Shl32,
- mkU32(0x1),
- mkU8(rs-1))),
- mkU8(rs-1))));
- }
- break;
- }
- case 0x16: { /* SHLLV_S.W */
- DIP("shllv_s.w r%u, r%u, r%u", rd, rt, rs);
- vassert(!mode64);
- t0 = newTemp(Ity_I32);
- t1 = newTemp(Ity_I1);
- t2 = newTemp(Ity_I32);
- t3 = newTemp(Ity_I64);
- t4 = newTemp(Ity_I1);
- t5 = newTemp(Ity_I1);
- t6 = newTemp(Ity_I32);
- t7 = newTemp(Ity_I1);
- t8 = newTemp(Ity_I32);
-
- /* Check if shift amount is zero. */
- assign(t0, binop(Iop_And32, getIReg(rs), mkU32(0x1f)));
- assign(t1, binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x0)));
-
- /* t2 = sign of the input value. */
- assign(t2, binop(Iop_Shr32,
- binop(Iop_And32,
- getIReg(rt),
- mkU32(0x80000000)),
- mkU8(31)));
- /* Shift left input value and check for overflow. */
- assign(t3, binop(Iop_Shl64,
- unop(Iop_32Sto64, getIReg(rt)),
- unop(Iop_32to8, mkexpr(t0))));
- assign(t4, binop(Iop_CmpNE32,
- unop(Iop_64HIto32, mkexpr(t3)),
- mkU32(0x00000000)));
- assign(t5, binop(Iop_CmpNE32,
- unop(Iop_64HIto32, mkexpr(t3)),
- mkU32(0xffffffff)));
- assign(t6, binop(Iop_And32,
- unop(Iop_1Uto32, mkexpr(t4)),
- unop(Iop_1Uto32, mkexpr(t5))));
- assign(t7, binop(Iop_CmpEQ32,
- binop(Iop_Shr32,
- binop(Iop_And32,
- getIReg(rt),
- mkU32(0x80000000)),
- mkU8(31)),
- binop(Iop_Shr32,
- binop(Iop_And32,
- unop(Iop_64to32, mkexpr(t3)),
- mkU32(0x80000000)),
- mkU8(31))));
-
- putDSPControl(IRExpr_ITE(unop(Iop_32to1, mkexpr(t6)),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x400000)),
- IRExpr_ITE(mkexpr(t7),
- getDSPControl(),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x400000)))
- ));
-
- assign(t8, IRExpr_ITE(unop(Iop_32to1,
- mkexpr(t2)),
- mkU32(0x80000000),
- mkU32(0x7fffffff)));
- putIReg(rd, IRExpr_ITE(unop(Iop_32to1, mkexpr(t6)),
- IRExpr_ITE(unop(Iop_32to1,
- mkexpr(t2)),
- mkU32(0x80000000),
- mkU32(0x7fffffff)),
- IRExpr_ITE(mkexpr(t7),
- unop(Iop_64to32,
- mkexpr(t3)),
- mkexpr(t8))));
- break;
- }
- case 0x17: { /* SHRAV_R.W */
- DIP("shrav_r.w r%u, r%u, r%u", rd, rt, rs);
- vassert(!mode64);
- t0 = newTemp(Ity_I32);
- t1 = newTemp(Ity_I1);
- t2 = newTemp(Ity_I8);
- t3 = newTemp(Ity_I32);
-
- assign(t0, binop(Iop_And32, getIReg(rs), mkU32(0x1f)));
- assign(t1, binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x0)));
- assign(t2, unop(Iop_32to8,
- binop(Iop_Sub32, mkexpr(t0), mkU32(1))));
-
- putIReg(rd, IRExpr_ITE(mkexpr(t1),
- getIReg(rt),
- binop(Iop_Sar32,
- binop(Iop_Add32,
- binop(Iop_Sar32,
- getIReg(rt),
- mkexpr(t2)),
- mkU32(0x1)),
- mkU8(1))));
- break;
- }
- case 0x19: { /* SHRL.PH */
- DIP("shrl.ph r%u, r%u, %u", rd, rt, rs);
- vassert(!mode64);
- t0 = newTemp(Ity_I32);
- t1 = newTemp(Ity_I32);
- assign(t0, binop(Iop_Shr32,
- unop(Iop_16Uto32,
- unop(Iop_32to16, getIReg(rt))),
- mkU8(rs)));
- assign(t1, binop(Iop_Shr32,
- unop(Iop_16Uto32,
- unop(Iop_32HIto16, getIReg(rt))),
- mkU8(rs)));
- putIReg(rd, binop(Iop_16HLto32,
- unop(Iop_32to16, mkexpr(t1)),
- unop(Iop_32to16, mkexpr(t0))));
- break;
- }
- case 0x1B: { /* SHRLV.PH */
- DIP("shrlv.ph r%u, r%u, r%u", rd, rt, rs);
- vassert(!mode64);
- t0 = newTemp(Ity_I32);
- t1 = newTemp(Ity_I1);
- t2 = newTemp(Ity_I32);
- t3 = newTemp(Ity_I32);
- t4 = newTemp(Ity_I16);
- t5 = newTemp(Ity_I16);
-
- /* Get shift amount from lower 5 bits of rs
- and check if it is zero. */
- assign(t0, binop(Iop_And32, getIReg(rs), mkU32(0x0f)));
- assign(t1, binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x0)));
-
- assign(t2, binop(Iop_Shr32,
- unop(Iop_16Uto32,
- unop(Iop_32to16, getIReg(rt))),
- unop(Iop_32to8, mkexpr(t0))));
- assign(t3, binop(Iop_Shr32,
- unop(Iop_16Uto32,
- unop(Iop_32HIto16, getIReg(rt))),
- unop(Iop_32to8, mkexpr(t0))));
-
- assign(t4, IRExpr_ITE(mkexpr(t1),
- unop(Iop_32HIto16, getIReg(rt)),
- unop(Iop_32to16, mkexpr(t3))));
- assign(t5, IRExpr_ITE(mkexpr(t1),
- unop(Iop_32to16, getIReg(rt)),
- unop(Iop_32to16, mkexpr(t2))));
- putIReg(rd, binop(Iop_16HLto32, mkexpr(t4), mkexpr(t5)));
- break;
- }
- default:
- return -1;
+ if (m == 31) {
+ putWReg(wd, getWReg(ws));
+ } else {
+ t1 = newTemp(Ity_V128);
+ assign(t1,
+ binop(Iop_CmpEQ32x4,
+ binop(Iop_ShrN32x4,
+ getWReg(ws),
+ mkU8(m + 1)),
+ binop(Iop_64HLtoV128,
+ mkU64(0), mkU64(0))));
+ putWReg(wd,
+ binop(Iop_OrV128,
+ binop(Iop_AndV128,
+ mkexpr(t1), \
+ getWReg(ws)),
+ binop(Iop_ShrN32x4,
+ unop(Iop_NotV128,
+ mkexpr(t1)),
+ mkU8(31 - m))));
}
- break; /* end of SHLL.QB */
+
+ break;
}
- case 0x18: { /* ADDUH.QB/MUL.PH */
- switch(sa) {
- case 0x00: { /* ADDUH.QB */
- DIP("adduh.qb r%u, r%u, r%u", rd, rs, rt);
- vassert(!mode64);
- t0 = newTemp(Ity_I32);
- assign(t0, binop(Iop_HAdd8Ux4, getIReg(rs), getIReg(rt)));
+ case 0x03: { /* SAT_U.D */
+ DIP("SAT_U.D w%d, w%d, %d", wd, ws, m);
- putIReg(rd, mkexpr(t0));
- break;
- }
- case 0x1: { /* SUBUH.QB */
- DIP("subuh.qb r%u, r%u, r%u", rd, rs, rt);
- vassert(!mode64);
- t0 = newTemp(Ity_I32);
+ if (m == 63) {
+ putWReg(wd, getWReg(ws));
+ } else {
+ t1 = newTemp(Ity_V128);
+ assign(t1,
+ binop(Iop_CmpEQ64x2,
+ binop(Iop_ShrN64x2,
+ getWReg(ws),
+ mkU8(m + 1)),
+ binop(Iop_64HLtoV128,
+ mkU64(0), mkU64(0))));
+ putWReg(wd,
+ binop(Iop_OrV128,
+ binop(Iop_AndV128,
+ mkexpr(t1),
+ getWReg(ws)),
+ binop(Iop_ShrN64x2,
+ unop(Iop_NotV128,
+ mkexpr(t1)),
+ mkU8(63 - m))));
+ }
- assign(t0, binop(Iop_HSub8Ux4, getIReg(rs), getIReg(rt)));
+ break;
+ }
+ }
- putIReg(rd, mkexpr(t0));
- break;
- }
- case 0x02: { /* ADDUH_R.QB */
- DIP("adduh_r.qb r%u, r%u, r%u", rd, rs, rt);
- vassert(!mode64);
- t0 = newTemp(Ity_I32);
- t1 = newTemp(Ity_I32);
- t2 = newTemp(Ity_I8);
- t3 = newTemp(Ity_I32);
- t4 = newTemp(Ity_I32);
- t5 = newTemp(Ity_I8);
- t6 = newTemp(Ity_I32);
- t7 = newTemp(Ity_I32);
- t8 = newTemp(Ity_I8);
- t9 = newTemp(Ity_I32);
- t10 = newTemp(Ity_I32);
- t11 = newTemp(Ity_I8);
-
- /* Extract input bytes, add values, add 1 and half the
- result. */
- assign(t0, unop(Iop_8Uto32,
- unop(Iop_16to8,
- unop(Iop_32to16, getIReg(rs)))));
- assign(t1, unop(Iop_8Uto32,
- unop(Iop_16to8,
- unop(Iop_32to16, getIReg(rt)))));
- assign(t2, unop(Iop_16to8,
- unop(Iop_32to16,
- binop(Iop_Shr32,
- binop(Iop_Add32,
- binop(Iop_Add32,
- mkexpr(t0),
- mkexpr(t1)),
- mkU32(0x00000001)),
- mkU8(0x01)))));
-
- assign(t3, unop(Iop_8Uto32,
- unop(Iop_16HIto8,
- unop(Iop_32to16, getIReg(rs)))));
- assign(t4, unop(Iop_8Uto32,
- unop(Iop_16HIto8,
- unop(Iop_32to16, getIReg(rt)))));
- assign(t5, unop(Iop_16to8,
- unop(Iop_32to16,
- binop(Iop_Shr32,
- binop(Iop_Add32,
- binop(Iop_Add32,
- mkexpr(t3),
- mkexpr(t4)),
- mkU32(0x00000001)),
- mkU8(0x01)))));
-
- assign(t6, unop(Iop_8Uto32,
- unop(Iop_16to8,
- unop(Iop_32HIto16, getIReg(rs)))));
- assign(t7, unop(Iop_8Uto32,
- unop(Iop_16to8,
- unop(Iop_32HIto16, getIReg(rt)))));
- assign(t8, unop(Iop_16to8,
- unop(Iop_32to16,
- binop(Iop_Shr32,
- binop(Iop_Add32,
- binop(Iop_Add32,
- mkexpr(t7),
- mkexpr(t6)),
- mkU32(0x00000001)),
- mkU8(0x01)))));
-
- assign(t9, unop(Iop_8Uto32,
- unop(Iop_16HIto8,
- unop(Iop_32HIto16, getIReg(rs)))));
- assign(t10, unop(Iop_8Uto32,
- unop(Iop_16HIto8,
- unop(Iop_32HIto16, getIReg(rt)))));
- assign(t11, unop(Iop_16to8,
- unop(Iop_32to16,
- binop(Iop_Shr32,
- binop(Iop_Add32,
- binop(Iop_Add32,
- mkexpr(t9),
- mkexpr(t10)),
- mkU32(0x00000001)),
- mkU8(0x01)))));
-
- putIReg(rd, binop(Iop_16HLto32,
- binop(Iop_8HLto16,
- mkexpr(t11), mkexpr(t8)),
- binop(Iop_8HLto16,
- mkexpr(t5), mkexpr(t2))));
- break;
- }
- case 0x3: { /* SUBUH_R.QB */
- DIP("subuh_r.qb r%u, r%u, r%u", rd, rs, rt);
- vassert(!mode64);
- t1 = newTemp(Ity_I32);
- t2 = newTemp(Ity_I32);
- t3 = newTemp(Ity_I32);
- t4 = newTemp(Ity_I32);
- t5 = newTemp(Ity_I32);
- t6 = newTemp(Ity_I32);
- t7 = newTemp(Ity_I32);
- t8 = newTemp(Ity_I32);
- t9 = newTemp(Ity_I8);
- t10 = newTemp(Ity_I8);
- t11 = newTemp(Ity_I8);
- t12 = newTemp(Ity_I8);
-
- /* Extract each byte of rs and rt. */
- assign(t1, unop(Iop_8Uto32,
- unop(Iop_16to8,
- unop(Iop_32to16, getIReg(rs)))));
- assign(t2, unop(Iop_8Uto32,
- unop(Iop_16HIto8,
- unop(Iop_32to16, getIReg(rs)))));
- assign(t3, unop(Iop_8Uto32,
- unop(Iop_16to8,
- unop(Iop_32HIto16, getIReg(rs)))));
- assign(t4, unop(Iop_8Uto32,
- unop(Iop_16HIto8,
- unop(Iop_32HIto16, getIReg(rs)))));
+ break;
+ }
- assign(t5, unop(Iop_8Uto32,
- unop(Iop_16to8,
- unop(Iop_32to16, getIReg(rt)))));
- assign(t6, unop(Iop_8Uto32,
- unop(Iop_16HIto8,
- unop(Iop_32to16, getIReg(rt)))));
- assign(t7, unop(Iop_8Uto32,
- unop(Iop_16to8,
- unop(Iop_32HIto16, getIReg(rt)))));
- assign(t8, unop(Iop_8Uto32,
- unop(Iop_16HIto8,
- unop(Iop_32HIto16, getIReg(rt)))));
-
- /* Add 1 to each resulting byte and half the results. */
- assign(t9, unop(Iop_16to8,
- unop(Iop_32to16,
- binop(Iop_Shr32,
- binop(Iop_Add32,
- binop(Iop_Sub32,
- mkexpr(t1),
- mkexpr(t5)),
- mkU32(0x00000001)),
- mkU8(0x01)))));
- assign(t10, unop(Iop_16to8,
- unop(Iop_32to16,
- binop(Iop_Shr32,
- binop(Iop_Add32,
- binop(Iop_Sub32,
- mkexpr(t2),
- mkexpr(t6)),
- mkU32(0x00000001)),
- mkU8(0x01)))));
- assign(t11, unop(Iop_16to8,
- unop(Iop_32to16,
- binop(Iop_Shr32,
- binop(Iop_Add32,
- binop(Iop_Sub32,
- mkexpr(t3),
- mkexpr(t7)),
- mkU32(0x00000001)),
- mkU8(0x01)))));
- assign(t12, unop(Iop_16to8,
- unop(Iop_32to16,
- binop(Iop_Shr32,
- binop(Iop_Add32,
- binop(Iop_Sub32,
- mkexpr(t4),
- mkexpr(t8)),
- mkU32(0x00000001)),
- mkU8(0x01)))));
-
- putIReg(rd, binop(Iop_16HLto32,
- binop(Iop_8HLto16,
- mkexpr(t12), mkexpr(t11)),
- binop(Iop_8HLto16,
- mkexpr(t10), mkexpr(t9))));
- break;
- }
- case 0x8: { /* ADDQH.PH */
- DIP("addqh.ph r%u, r%u, r%u", rd, rs, rt);
- vassert(!mode64);
- t0 = newTemp(Ity_I32);
- t1 = newTemp(Ity_I16);
- t2 = newTemp(Ity_I32);
- t3 = newTemp(Ity_I16);
-
- /* Add lower halfs of rs and rt
- and right shift the result by 1. */
- assign(t0, binop(Iop_Add32,
- unop(Iop_16Sto32,
- unop(Iop_32to16, getIReg(rs))),
- unop(Iop_16Sto32,
- unop(Iop_32to16, getIReg(rt)))));
- assign(t1, unop(Iop_32to16,
- binop(Iop_Shr32,
- binop(Iop_And32,
- mkexpr(t0),
- mkU32(0x0001fffe)),
- mkU8(0x1))));
- /* Add higher halfs of rs and rt
- and right shift the result by 1. */
- assign(t2, binop(Iop_Add32,
- unop(Iop_16Sto32,
- unop(Iop_32HIto16, getIReg(rs))),
- unop(Iop_16Sto32,
- unop(Iop_32HIto16, getIReg(rt)))));
- assign(t3, unop(Iop_32to16,
- binop(Iop_Shr32,
- binop(Iop_And32,
- mkexpr(t2),
- mkU32(0x0001fffe)),
- mkU8(0x1))));
- putIReg(rd, binop(Iop_16HLto32, mkexpr(t3), mkexpr(t1)));
- break;
- }
- case 0x9: { /* SUBQH.PH */
- DIP("subqh.ph r%u, r%u, r%u", rd, rs, rt);
- vassert(!mode64);
+ case 0x02: { /* SRARI.df */
+ switch (df) {
+ case 0x00: { /* SRARI.B */
+ DIP("SRARI.B w%d, w%d, %d", wd, ws, m);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ assign(t1,
+ binop(Iop_SarN8x16,
+ getWReg(ws),
+ mkU8(m)));
+ assign(t2,
+ binop(Iop_ShrN8x16,
+ binop(Iop_ShlN8x16,
+ getWReg(ws),
+ mkU8(8 - m)),
+ mkU8(7)));
- putIReg(rd, binop(Iop_HSub16Sx2,
- getIReg(rs), getIReg(rt)));
- break;
- }
- case 0xA: {/* ADDQH_R.PH */
- DIP("addqh_r.ph r%u, r%u, r%u", rd, rs, rt);
- vassert(!mode64);
- t0 = newTemp(Ity_I32);
- t1 = newTemp(Ity_I16);
- t2 = newTemp(Ity_I32);
- t3 = newTemp(Ity_I16);
-
- /* Add lower halfs of rs and rt, add 1
- and right shift the result by 1. */
- assign(t0, binop(Iop_Add32,
- unop(Iop_16Sto32,
- unop(Iop_32to16, getIReg(rs))),
- unop(Iop_16Sto32,
- unop(Iop_32to16, getIReg(rt)))));
- assign(t1, unop(Iop_32to16,
- binop(Iop_Shr32,
- binop(Iop_And32,
- binop(Iop_Add32,
- mkexpr(t0),
- mkU32(0x1)),
- mkU32(0x0001fffe)),
- mkU8(0x1))));
- /* Add higher halfs of rs and rt, add 1
- and right shift the result by 1. */
- assign(t2, binop(Iop_Add32,
- unop(Iop_16Sto32,
- unop(Iop_32HIto16, getIReg(rs))),
- unop(Iop_16Sto32,
- unop(Iop_32HIto16, getIReg(rt)))));
- assign(t3, unop(Iop_32to16,
- binop(Iop_Shr32,
- binop(Iop_And32,
- binop(Iop_Add32,
- mkexpr(t2),
- mkU32(0x1)),
- mkU32(0x0001fffe)),
- mkU8(0x1))));
+ if (m) putWReg(wd, binop(Iop_Add8x16,
+ mkexpr(t1),
+ mkexpr(t2)));
+ else putWReg(wd, mkexpr(t1));
- putIReg(rd, binop(Iop_16HLto32, mkexpr(t3), mkexpr(t1)));
- break;
- }
- case 0xB: { /* SUBQH_R.PH */
- DIP("subqh_r.ph r%u, r%u, r%u", rd, rs, rt);
- vassert(!mode64);
- t0 = newTemp(Ity_I32);
- t1 = newTemp(Ity_I16);
- t2 = newTemp(Ity_I32);
- t3 = newTemp(Ity_I16);
-
- /* Sub lower halfs of rs and rt, add 1
- and right shift the result by 1. */
- assign(t0, binop(Iop_Sub32,
- unop(Iop_16Sto32,
- unop(Iop_32to16, getIReg(rs))),
- unop(Iop_16Sto32,
- unop(Iop_32to16, getIReg(rt)))));
- assign(t1, unop(Iop_32to16,
- binop(Iop_Shr32,
- binop(Iop_And32,
- binop(Iop_Add32,
- mkexpr(t0),
- mkU32(0x1)),
- mkU32(0x0001fffe)),
- mkU8(0x1))));
- /* Sub higher halfs of rs and rt, add 1
- and right shift the result by 1. */
- assign(t2, binop(Iop_Sub32,
- unop(Iop_16Sto32,
- unop(Iop_32HIto16, getIReg(rs))),
- unop(Iop_16Sto32,
- unop(Iop_32HIto16, getIReg(rt)))));
- assign(t3, unop(Iop_32to16,
- binop(Iop_Shr32,
- binop(Iop_And32,
- binop(Iop_Add32,
- mkexpr(t2),
- mkU32(0x1)),
- mkU32(0x0001fffe)),
- mkU8(0x1))));
+ break;
+ }
- putIReg(rd, binop(Iop_16HLto32, mkexpr(t3), mkexpr(t1)));
- break;
- }
- case 0xC: { /* MUL.PH */
- DIP("mul.ph r%u, r%u, r%u", rd, rs, rt);
- vassert(!mode64);
- t0 = newTemp(Ity_I32);
- t1 = newTemp(Ity_I32);
- t2 = newTemp(Ity_I32);
-
- assign(t0,
- binop(Iop_Mul32,
- unop(Iop_16Sto32,
- unop(Iop_32HIto16, getIReg(rs))),
- unop(Iop_16Sto32,
- unop(Iop_32HIto16, getIReg(rt)))));
- /* DSP Control flag. */
- putDSPControl(IRExpr_ITE(unop(Iop_Not1,
- binop(Iop_CmpLE32S,
- mkexpr(t0),
- mkU32(0x7FFF))),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x00200000)),
- IRExpr_ITE(binop(Iop_CmpLT32S,
- mkexpr(t0),
- mkU32(0xFFFF8000)
- ),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x00200000)
- ),
- getDSPControl())));
+ case 0x01: { /* SRARI.H */
+ DIP("SRARI.H w%d, w%d, %d", wd, ws, m);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ assign(t1,
+ binop(Iop_SarN16x8,
+ getWReg(ws),
+ mkU8(m)));
+ assign(t2,
+ binop(Iop_ShrN16x8,
+ binop(Iop_ShlN16x8,
+ getWReg(ws),
+ mkU8(16 - m)),
+ mkU8(15)));
- assign(t1,
- binop(Iop_Mul32,
- unop(Iop_16Sto32,
- unop(Iop_32to16, getIReg(rs))),
- unop(Iop_16Sto32,
- unop(Iop_32to16, getIReg(rt)))));
- /* DSP Control flag. */
- putDSPControl(IRExpr_ITE(unop(Iop_Not1,
- binop(Iop_CmpLE32S,
- mkexpr(t1),
- mkU32(0x7FFF))),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x00200000)),
- IRExpr_ITE(binop(Iop_CmpLT32S,
- mkexpr(t1),
- mkU32(0xFFFF8000)
- ),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x00200000)
- ),
- getDSPControl())));
-
- assign(t2, binop(Iop_16HLto32,
- unop(Iop_32to16, mkexpr(t0)),
- unop(Iop_32to16, mkexpr(t1))));
- putIReg(rd, mkexpr(t2));
- break;
- }
- case 0xE: { /* MUL_S.PH */
- DIP("mul_s.ph r%u r%u, r%u", rd, rs, rt);
- vassert(!mode64);
-
- t0 = newTemp(Ity_I32);
- t1 = newTemp(Ity_I32);
- t2 = newTemp(Ity_I32);
- t3 = newTemp(Ity_I32);
- t4 = newTemp(Ity_I32);
-
- /* t0 - signed intermediate result. */
- assign(t0,
- binop(Iop_Mul32,
- unop(Iop_16Sto32,
- unop(Iop_32HIto16, getIReg(rs))),
- unop(Iop_16Sto32,
- unop(Iop_32HIto16, getIReg(rt)))));
+ if (m)
+ putWReg(wd,
+ binop(Iop_Add16x8,
+ mkexpr(t1), mkexpr(t2)));
+ else putWReg(wd, mkexpr(t1));
- assign(t1,
- IRExpr_ITE(unop(Iop_Not1,
- binop(Iop_CmpLE32S,
- mkexpr(t0),
- mkU32(0x7FFF))),
- mkU32(0x00007FFF),
- IRExpr_ITE(binop(Iop_CmpLT32S,
- mkexpr(t0),
- mkU32(0xFFFF8000)),
- mkU32(0xFFFF8000),
- mkexpr(t0))));
-
- /* DSP Control flag. */
- putDSPControl(IRExpr_ITE(unop(Iop_Not1,
- binop(Iop_CmpLE32S,
- mkexpr(t0),
- mkU32(0x7FFF))),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x00200000)),
- IRExpr_ITE(binop(Iop_CmpLT32S,
- mkexpr(t0),
- mkU32(0xFFFF8000)
- ),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x00200000)
- ),
- getDSPControl())));
-
- /* t2 - signed intermediate result. */
- assign(t2, binop(Iop_Mul32,
- unop(Iop_16Sto32,
- unop(Iop_32to16, getIReg(rs))),
- unop(Iop_16Sto32,
- unop(Iop_32to16, getIReg(rt)))));
-
- assign(t3, IRExpr_ITE(unop(Iop_Not1,
- binop(Iop_CmpLE32S,
- mkexpr(t2),
- mkU32(0x7FFF))),
- mkU32(0x00007FFF),
- IRExpr_ITE(binop(Iop_CmpLT32S,
- mkexpr(t2),
- mkU32(0xFFFF8000)),
- mkU32(0xFFFF8000),
- mkexpr(t2))));
-
- /* DSP Control flag. */
- putDSPControl(IRExpr_ITE(unop(Iop_Not1,
- binop(Iop_CmpLE32S,
- mkexpr(t2),
- mkU32(0x7FFF))),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x00200000)),
- IRExpr_ITE(binop(Iop_CmpLT32S,
- mkexpr(t2),
- mkU32(0xFFFF8000)
- ),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x00200000)
- ),
- getDSPControl())));
-
- assign(t4, binop(Iop_16HLto32,
- unop(Iop_32to16, mkexpr(t1)),
- unop(Iop_32to16, mkexpr(t3))));
- putIReg(rd, mkexpr(t4));
- break;
- }
- case 0x10: { /* ADDQH.W */
- DIP("addqh.w r%u, r%u, r%u", rd, rs, rt);
- vassert(!mode64);
- t0 = newTemp(Ity_I64);
- t1 = newTemp(Ity_I64);
+ break;
+ }
- assign(t0, binop(Iop_Add64,
- unop(Iop_32Sto64, getIReg(rs)),
- unop(Iop_32Sto64, getIReg(rt))));
- assign(t1, binop(Iop_And64,
- mkexpr(t0),
- mkU64(0x00000001fffffffeULL)));
- putIReg(rd, unop(Iop_64to32,
- binop(Iop_Shr64, mkexpr(t1), mkU8(0x1))));
- break;
- }
- case 0x11: { /* SUBQH.W */
- DIP("subqh.w r%u, r%u, r%u", rd, rs, rt);
- vassert(!mode64);
- t0 = newTemp(Ity_I64);
- t1 = newTemp(Ity_I64);
+ case 0x02: { /* SRARI.W */
+ DIP("SRARI.W w%d, w%d, %d", wd, ws, m);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ assign(t1,
+ binop(Iop_SarN32x4,
+ getWReg(ws),
+ mkU8(m)));
+ assign(t2,
+ binop(Iop_ShrN32x4,
+ binop(Iop_ShlN32x4,
+ getWReg(ws),
+ mkU8(32 - m)),
+ mkU8(31)));
- assign(t0, binop(Iop_Sub64,
- unop(Iop_32Sto64, getIReg(rs)),
- unop(Iop_32Sto64, getIReg(rt))));
- assign(t1, binop(Iop_And64,
- mkexpr(t0),
- mkU64(0x00000001fffffffeULL)));
- putIReg(rd, unop(Iop_64to32,
- binop(Iop_Shr64, mkexpr(t1), mkU8(0x1))));
- break;
- }
- case 0x12: { /* ADDQH_R.W */
- DIP("addqh_r.w r%u, r%u, r%u", rd, rs, rt);
- vassert(!mode64);
- t0 = newTemp(Ity_I64);
- t1 = newTemp(Ity_I64);
- t2 = newTemp(Ity_I64);
-
- assign(t0, binop(Iop_Add64,
- unop(Iop_32Sto64, getIReg(rs)),
- unop(Iop_32Sto64, getIReg(rt))));
- assign(t1, binop(Iop_Add64,
- mkexpr(t0),
- mkU64(0x0000000000000001ULL)));
- assign(t2, binop(Iop_And64,
- mkexpr(t1),
- mkU64(0x00000001fffffffeULL)));
- putIReg(rd, unop(Iop_64to32,
- binop(Iop_Shr64, mkexpr(t2), mkU8(0x1))));
- break;
- }
- case 0x13: { /* SUBQH_R.W */
- DIP("subqh_r.w r%u, r%u, r%u", rd, rs, rt);
- vassert(!mode64);
- t0 = newTemp(Ity_I64);
- t1 = newTemp(Ity_I64);
- t2 = newTemp(Ity_I64);
-
- assign(t0, binop(Iop_Sub64,
- unop(Iop_32Sto64, getIReg(rs)),
- unop(Iop_32Sto64, getIReg(rt))));
- assign(t1, binop(Iop_Add64,
- mkexpr(t0),
- mkU64(0x0000000000000001ULL)));
- assign(t2, binop(Iop_And64,
- mkexpr(t1),
- mkU64(0x00000001fffffffeULL)));
- putIReg(rd, unop(Iop_64to32,
- binop(Iop_Shr64, mkexpr(t2), mkU8(0x1))));
- break;
- }
- case 0x16: { /* MULQ_S.W */
- DIP("mulq_s.w r%u, r%u, r%u", rd, rs, rt);
- vassert(!mode64);
- t0 = newTemp(Ity_I64);
- t1 = newTemp(Ity_I1);
- t2 = newTemp(Ity_I1);
-
- assign(t0, binop(Iop_Shl64,
- binop(Iop_MullS32,
- getIReg(rt), getIReg(rs)),
- mkU8(0x1)));
- assign(t1, binop(Iop_CmpEQ32,
- getIReg(rt), mkU32(0x80000000)));
- assign(t2, binop(Iop_CmpEQ32,
- getIReg(rs), mkU32(0x80000000)));
-
- putDSPControl(IRExpr_ITE(mkexpr(t1),
- IRExpr_ITE(mkexpr(t2),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x00200000)
- ),
- getDSPControl()),
- getDSPControl()));
- putIReg(rd, IRExpr_ITE(mkexpr(t1),
- IRExpr_ITE(mkexpr(t2),
- mkU32(0x7fffffff),
- unop(Iop_64HIto32,
- mkexpr(t0))),
- unop(Iop_64HIto32, mkexpr(t0))));
- break;
- }
- case 0x17: { /* MULQ_RS.W */
- DIP("mulq_rs.w r%u, r%u, r%u", rd, rs, rt);
- vassert(!mode64);
- t0 = newTemp(Ity_I64);
- t1 = newTemp(Ity_I1);
- t2 = newTemp(Ity_I1);
-
- assign(t0, binop(Iop_Add64,
- binop(Iop_Shl64,
- binop(Iop_MullS32,
- getIReg(rt),
- getIReg(rs)),
- mkU8(0x1)),
- mkU64(0x0000000080000000ULL)));
- assign(t1,
- binop(Iop_CmpEQ32, getIReg(rt), mkU32(0x80000000)));
- assign(t2,
- binop(Iop_CmpEQ32, getIReg(rs), mkU32(0x80000000)));
- putDSPControl(IRExpr_ITE(mkexpr(t1),
- IRExpr_ITE(mkexpr(t2),
- binop(Iop_Or32,
- getDSPControl(),
- mkU32(0x00200000)
- ),
- getDSPControl()),
- getDSPControl()));
- putIReg(rd, IRExpr_ITE(mkexpr(t1),
- IRExpr_ITE(mkexpr(t2),
- mkU32(0x7fffffff),
- unop(Iop_64HIto32,
- mkexpr(t0))),
- unop(Iop_64HIto32, mkexpr(t0))));
- break;
- }
- default:
- return -1;
- }
- break; /* end of ADDUH.QB/MUL.PH */
+ if (m)
+ putWReg(wd,
+ binop(Iop_Add32x4,
+ mkexpr(t1), mkexpr(t2)));
+ else putWReg(wd, mkexpr(t1));
+
+ break;
}
- case 0x30: { /* DPAQ.W.PH */
- switch(sa) {
- case 0x0: { /* DPA.W.PH */
- DIP("dpa.w.ph ac%u, r%u, r%u", ac, rs, rt);
- vassert(!mode64);
- t0 = newTemp(Ity_I64);
- t1 = newTemp(Ity_I64);
- t2 = newTemp(Ity_I64);
-
- assign(t0,
- unop(Iop_32Sto64,
- binop(Iop_Mul32,
- unop(Iop_16Sto32,
- unop(Iop_32HIto16, getIReg(rs))),
- unop(Iop_16Sto32,
- unop(Iop_32HIto16, getIReg(rt))))));
- assign(t1,
- unop(Iop_32Sto64,
- binop(Iop_Mul32,
- unop(Iop_16Sto32,
- unop(Iop_32to16, getIReg(rs))),
- unop(Iop_16Sto32,
- unop(Iop_32to16, getIReg(rt))))));
- assign(t2,
- binop(Iop_Add64,
- getAcc(ac),
- binop(Iop_Add64, mkexpr(t0), mkexpr(t1))));
- putAcc(ac, mkexpr(t2));
- break;
- }
- case 0x1: { /* DPS.W.PH */
- DIP("dps.w.ph ac%u, r%u, r%u", ac, rs, rt);
- vassert(!mode64);
+ case 0x03: { /* SRARI.D */
+ DIP("SRARI.D w%d, w%d, %d", wd, ws, m);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ assign(t1,
+ binop(Iop_SarN64x2,
+ getWReg(ws),
+ mkU8(m)));
+ assign(t2,
+ binop(Iop_ShrN64x2,
+ binop(Iop_ShlN64x2,
+ getWReg(ws),
+ mkU8(64 - m)),
+ mkU8(63)));
- t0 = newTemp(Ity_I64);
- t1 = newTemp(Ity_I64);
- t2 = newTemp(Ity_I64);
-
- assign(t0,
- unop(Iop_32Sto64,
- binop(Iop_Mul32,
- unop(Iop_16Sto32,
- unop(Iop_32HIto16, getIReg(rs))),
- unop(Iop_16Sto32,
- unop(Iop_32HIto16, getIReg(rt))))));
- assign(t1,
- unop(Iop_32Sto64,
- binop(Iop_Mul32,
- unop(Iop_16Sto32,
- unop(Iop_32to16, getIReg(rs))),
- unop(Iop_16Sto32,
- unop(Iop_32to16, getIReg(rt))))));
- assign(t2,
- binop(Iop_Sub64,
- getAcc(ac),
- binop(Iop_Add64, mkexpr(t0), mkexpr(t1))));
- putAcc(ac, mkexpr(t2));
- break;
- }
- case 0x2: { /* MULSA.W.PH */
- DIP("mulsa.w.ph ac%u, r%u, r%u", ac, rs, rt);
- vassert(!mode64);
- t0 = newTemp(Ity_I32);
- t1 = newTemp(Ity_I32);
- t2 = newTemp(Ity_I32);
- t3 = newTemp(Ity_I1);
- t4 = newTemp(Ity_I64);
-
- assign(t4, getAcc(ac));
- assign(t0, binop(Iop_Mul32,
- unop(Iop_16Sto32,
- unop(Iop_32to16, getIReg(rt))),
- unop(Iop_16Sto32,
- unop(Iop_32to16, getIReg(rs)))));
- assign(t1, binop(Iop_Mul32,
- unop(Iop_16Sto32,
- unop(Iop_32HIto16, getIReg(rt))),
- unop(Iop_16Sto32,
- unop(Iop_32HIto16, getIReg(rs)))));
- assign(t2, binop(Iop_Sub32, mkexpr(t1), mkexpr(t0)));
- putAcc(ac, binop(Iop_Add64,
- mkexpr(t4),
- unop(Iop_32Sto64, mkexpr(t2))));
- break;
- }
- case 0x3: { /* DPAU.H.QBL */
- DIP("dpau.h.qbl ac%u, r%u, r%u", ac, rs, rt);
- vassert(!mode64);
- t0 = newTemp(Ity_I32);
- t1 = newTemp(Ity_I32);
- t2 = newTemp(Ity_I64);
- t3 = newTemp(Ity_I64);
-
- assign(t0,
- binop(Iop_Mul32,
- unop(Iop_8Uto32,
- unop(Iop_16HIto8,
- unop(Iop_32HIto16, getIReg(rs)))),
- unop(Iop_8Uto32,
- unop(Iop_16HIto8,
- unop(Iop_32HIto16, getIReg(rt))))));
- assign(t1,
- binop(Iop_Mul32,
- unop(Iop_8Uto32,
- unop(Iop_16to8,
- unop(Iop_32HIto16, getIReg(rs)))),
- unop(Iop_8Uto32,
- unop(Iop_16to8,
- unop(Iop_32HIto16, getIReg(rt))))));
- assign(t2,
- unop(Iop_32Uto64,
- binop(Iop_Add32,
- mkexpr(t0),
- mkexpr(t1))));
- assign(t3,
- binop(Iop_Add64, getAcc(ac), mkexpr(t2)));
- putAcc(ac, mkexpr(t3));
- break;
- }
- case 0x4: { /* DPAQ_S.W.PH */
- DIP("dpaq_s.w.ph ac%u, r%u, r%u", ac, rs, rt);
- vassert(!mode64);
- t0 = newTemp(Ity_I64);
- t1 = newTemp(Ity_I64);
- t2 = newTemp(Ity_I1);
- t3 = newTemp(Ity_I1);
- t4 = newTemp(Ity_I64);
- t5 = newTemp(Ity_I64);
- t6 = newTemp(Ity_I1);
- t7 = newTemp(Ity_I1);
- t8 = newTemp(Ity_I64);
- t9 = newTemp(Ity_I64);
-
- assign(t0, getAcc(ac));
-
- assign(t1, binop(Iop_Shl64,
- binop(Iop_MullS32,
- unop(Iop_16Sto32,
- unop(Iop_32HIto16,
- getIReg(rs))),
- unop(Iop_16Sto32,
- unop(Iop_32HIto16,
- getIReg(rt)))),
- mkU8(0x1)));
- assign(t2, binop(Iop_CmpEQ32,
- unop(Iop_16Uto32,
- unop(Iop_32HIto16, getIReg(rs))),
- mkU32(0x00008000)));
- assign(t3, binop(Iop_CmpEQ32,
- unop(Iop_16Uto32,
- unop(Iop_32HIto16, getIReg(rt))),
- mkU32(0x00008000)));
- assign(t4,
- IRExpr_ITE(mkexpr(t2),
- IRExpr_ITE(mkexpr(t3),
- mkU64(0x000000007fffffffULL),
- mkexpr(t1)),
- mkexpr(t1)));
-
- putDSPControl(IRExpr_ITE(mkexpr(t2),
- IRExpr_ITE(mkexpr(t3),
- binop(Iop_Or32,
- getDSPControl(),
- binop(Iop_Shl32,
- mkU32(0x1),
- mkU8(ac+16)
- )
- ),
- getDSPControl()),
- getDSPControl()));
-
- assign(t5, binop(Iop_Shl64,
- binop(Iop_MullS32,
- unop(Iop_16Sto32,
- unop(Iop_32to16, getIReg(rs))),
- unop(Iop_16Sto32,
- unop(Iop_32to16, getIReg(rt)))
- ),
- mkU8(0x1)));
- assign(t6, binop(Iop_CmpEQ32,
- unop(Iop_16Uto32,
- unop(Iop_32to16, getIReg(rs))),
- mkU32(0x00008000)));
- assign(t7, binop(Iop_CmpEQ32,
- unop(Iop_16Uto32,
- unop(Iop_32to16, getIReg(rt))),
- mkU32(0x00008000)));
- assign(t8,
- IRExpr_ITE(mkexpr(t6),
- IRExpr_ITE(mkexpr(t7),
- mkU64(0x000000007fffffffULL),
- mkexpr(t5)),
- mkexpr(t5)));
-
- putDSPControl(IRExpr_ITE(mkexpr(t6),
- IRExpr_ITE(mkexpr(t7),
- binop(Iop_Or32,
- getDSPControl(),
- binop(Iop_Shl32,
- mkU32(0x1),
- mkU8(ac+16)
- )
- ),
- getDSPControl()),
- getDSPControl()));
-
- assign(t9, binop(Iop_Add64,
- binop(Iop_Add64, mkexpr(t4), mkexpr(t8)),
- mkexpr(t0)));
- putAcc(ac, mkexpr(t9));
- break;
- }
- case 0x5: { /* DPSQ_S.W.PH */
- DIP("dpsq_s.w.ph ac%u r%u, r%u", ac, rs, rt);
- vassert(!mode64);
- t0 = newTemp(Ity_I64);
- t1 = newTemp(Ity_I64);
- t2 = newTemp(Ity_I1);
- t3 = newTemp(Ity_I1);
- t4 = newTemp(Ity_I64);
- t5 = newTemp(Ity_I64);
- t6 = newTemp(Ity_I1);
- t7 = newTemp(Ity_I1);
- t8 = newTemp(Ity_I64);
- t9 = newTemp(Ity_I64);
-
- assign(t0, getAcc(ac));
-
- assign(t1, binop(Iop_Shl64,
- binop(Iop_MullS32,
- unop(Iop_16Sto32,
- unop(Iop_32HIto16,
- getIReg(rs))),
- unop(Iop_16Sto32,
- unop(Iop_32HIto16,
- getIReg(rt)))),
- mkU8(0x1)));
- assign(t2, binop(Iop_CmpEQ32,
- unop(Iop_16Uto32,
- unop(Iop_32HIto16, getIReg(rs))),
- mkU32(0x00008000)));
- assign(t3, binop(Iop_CmpEQ32,
- unop(Iop_16Uto32,
- unop(Iop_32HIto16, getIReg(rt))),
- mkU32(0x00008000)));
- assign(t4,
- IRExpr_ITE(mkexpr(t2),
- IRExpr_ITE(mkexpr(t3),
- mkU64(0x000000007fffffffULL),
- mkexpr(t1)),
- mkexpr(t1)));
-
- putDSPControl(IRExpr_ITE(mkexpr(t2),
- IRExpr_ITE(mkexpr(t3),
- binop(Iop_Or32,
- getDSPControl(),
- binop(Iop_Shl32,
- mkU32(0x1),
- mkU8(ac+16)
- )
- ),
- getDSPControl()),
- getDSPControl()));
-
- assign(t5,
- binop(Iop_Shl64,
- binop(Iop_MullS32,
- unop(Iop_16Sto32,
- unop(Iop_32to16, getIReg(rs))),
- unop(Iop_16Sto32,
- unop(Iop_32to16, getIReg(rt)))),
- mkU8(0x1)));
- assign(t6, binop(Iop_CmpEQ32,
- unop(Iop_16Uto32,
- unop(Iop_32to16, getIReg(rs))),
- mkU32(0x00008000)));
- assign(t7, binop(Iop_CmpEQ32,
- unop(Iop_16Uto32,
- unop(Iop_32to16, getIReg(rt))),
- mkU32(0x00008000)));
- assign(t8,
- IRExpr_ITE(mkexpr(t6),
- IRExpr_ITE(mkexpr(t7),
- mkU64(0x000000007fffffffULL),
- mkexpr(t5)),
- mkexpr(t5)));
-
- putDSPControl(IRExpr_ITE(mkexpr(t6),
- IRExpr_ITE(mkexpr(t7),
- binop(Iop_Or32,
- getDSPControl(),
- binop(Iop_Shl32,
- mkU32(0x1),
- mkU8(ac+16)
- )
- ),
- getDSPControl()),
- getDSPControl()));
-
- assign(t9,
- binop(Iop_Sub64,
- mkexpr(t0),
- binop(Iop_Add64, mkexpr(t4), mkexpr(t8))));
- putAcc(ac, mkexpr(t9));
- break;
- }
- case 0x6: { /* MULSAQ_S.W.PH */
- DIP("mulsaq_s.w.ph ac%u r%u, r%u", ac, rs, rt);
- vassert(!mode64);
-
- t0 = newTemp(Ity_I32);
- t1 = newTemp(Ity_I32);
- t2 = newTemp(Ity_I32);
- t3 = newTemp(Ity_I32);
- t4 = newTemp(Ity_I32);
- t5 = newTemp(Ity_I32);
- t6 = newTemp(Ity_I64);
- t7 = newTemp(Ity_I64);
- t8 = newTemp(Ity_I32);
- t9 = newTemp(Ity_I32);
-
- assign(t0, unop(Iop_16Sto32,
- unop(Iop_32HIto16, getIReg(rs))));
- assign(t1, unop(Iop_16Sto32,
- unop(Iop_32HIto16, getIReg(rt))));
-
- assign(t8, binop(Iop_And32,
- unop(Iop_1Sto32,
- binop(Iop_CmpEQ32,
- unop(Iop_16Uto32,
- unop(Iop_32HIto16,
- getIReg(rs))),
- mkU32(0x8000))),
- unop(Iop_1Sto32,
- binop(Iop_CmpEQ32,
- unop(Iop_16Uto32,
- unop(Iop_32HIto16,
- getIReg(rt))),
- mkU32(0x8000)))));
- /* DSPControl_outflag:16+acc <- 1 */
- putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
- mkexpr(t8),
- mkU32(0x0)),
- binop(Iop_Or32,
- getDSPControl(),
- binop(Iop_Shl32,
- mkU32(0x00010000),
- mkU8(ac))),
- getDSPControl()));
-
- /* tempB_31..0 */
- assign(t2,
- IRExpr_ITE(binop(Iop_CmpNE32,
- mkexpr(t8), mkU32(0x0)),
- mkU32(0x7FFFFFFF),
- binop(Iop_Shl32,
- binop(Iop_Mul32,
- mkexpr(t0), mkexpr(t1)),
- mkU8(1))));
-
- assign(t3, unop(Iop_16Sto32,
- unop(Iop_32to16, getIReg(rs))));
- assign(t4, unop(Iop_16Sto32,
- unop(Iop_32to16, getIReg(rt))));
-
- assign(t9, binop(Iop_And32,
- unop(Iop_1Sto32,
- binop(Iop_CmpEQ32,
- unop(Iop_16Uto32,
- unop(Iop_32to16,
- getIReg(rs))),
- mkU32(0x8000))),
- unop(Iop_1Sto32,
- binop(Iop_CmpEQ32,
- unop(Iop_16Uto32,
- unop(Iop_32to16,
- getIReg(rt))),
- mkU32(0x8000)))));
- /* DSPControl_outflag:16+acc <- 1 */
- putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
- mkexpr(t9),
- mkU32(0x0)),
- binop(Iop_Or32,
- getDSPControl(),
- binop(Iop_Shl32,
- mkU32(0x00010000),
- mkU8(ac))),
- getDSPControl()));
- /* tempA_31..0 */
- assign(t5,
- IRExpr_ITE(binop(Iop_CmpNE32,
- mkexpr(t9),
- mkU32(0x0)),
- mkU32(0x7FFFFFFF),
- binop(Iop_Shl32,
- binop(Iop_Mul32,
- mkexpr(t3),
- mkexpr(t4)),
- mkU8(1))));
- /* dotp_63..0 */
- assign(t6,
- binop(Iop_Sub64,
- unop(Iop_32Sto64, mkexpr(t2)),
- unop(Iop_32Sto64, mkexpr(t5))));
- /* tempC_63..0 */
- assign(t7, binop(Iop_Add64, getAcc(ac), mkexpr(t6)));
-
- putAcc(ac, mkexpr(t7));
- break;
- }
- case 0x7: { /* DPAU.H.QBR */
- DIP("dpau.h.qbr ac%u, r%u, r%u", ac, rs, rt);
- vassert(!mode64);
- t0 = newTemp(Ity_I32);
- t1 = newTemp(Ity_I32);
- t2 = newTemp(Ity_I64);
- t3 = newTemp(Ity_I64);
-
- assign(t0,
- binop(Iop_Mul32,
- unop(Iop_8Uto32,
- unop(Iop_16HIto8,
- unop(Iop_32to16, getIReg(rs)))),
- unop(Iop_8Uto32,
- unop(Iop_16HIto8,
- unop(Iop_32to16, getIReg(rt))))));
- assign(t1,
- binop(Iop_Mul32,
- unop(Iop_8Uto32,
- unop(Iop_16to8,
- unop(Iop_32to16, getIReg(rs)))),
- unop(Iop_8Uto32,
- unop(Iop_16to8,
- unop(Iop_32to16, getIReg(rt))))));
- assign(t2, unop(Iop_32Uto64,
- binop(Iop_Add32, mkexpr(t0), mkexpr(t1))));
- assign(t3, binop(Iop_Add64, getAcc(ac), mkexpr(t2)));
- putAcc(ac, mkexpr(t3));
- break;
- }
- case 0x8: { /* DPAX.W.PH */
- DIP("dpax.w.ph ac%u, r%u, r%u", ac, rs, rt);
- vassert(!mode64);
- t0 = newTemp(Ity_I64);
- t1 = newTemp(Ity_I64);
- t2 = newTemp(Ity_I64);
-
- assign(t0,
- unop(Iop_32Sto64,
- binop(Iop_Mul32,
- unop(Iop_16Sto32,
- unop(Iop_32HIto16, getIReg(rs))),
- unop(Iop_16Sto32,
- unop(Iop_32to16, getIReg(rt))))));
- assign(t1,
- unop(Iop_32Sto64,
- binop(Iop_Mul32,
- unop(Iop_16Sto32,
- unop(Iop_32to16, getIReg(rs))),
- unop(Iop_16Sto32,
- unop(Iop_32HIto16, getIReg(rt))))));
- assign(t2,
- binop(Iop_Add64,
- getAcc(ac),
- binop(Iop_Add64, mkexpr(t0), mkexpr(t1))));
- putAcc(ac, mkexpr(t2));
- break;
- }
- case 0x9: { /* DPSX.W.PH */
- DIP("dpsx.w.ph ac%u r%u, r%u", ac, rs, rt);
- vassert(!mode64);
+ if (m)
+ putWReg(wd,
+ binop(Iop_Add64x2,
+ mkexpr(t1), mkexpr(t2)));
+ else putWReg(wd, mkexpr(t1));
- t0 = newTemp(Ity_I64);
- t1 = newTemp(Ity_I64);
- t2 = newTemp(Ity_I64);
-
- assign(t0,
- unop(Iop_32Sto64,
- binop(Iop_Mul32,
- unop(Iop_16Sto32,
- unop(Iop_32HIto16, getIReg(rs))),
- unop(Iop_16Sto32,
- unop(Iop_32to16, getIReg(rt))))));
- assign(t1,
- unop(Iop_32Sto64,
- binop(Iop_Mul32,
- unop(Iop_16Sto32,
- unop(Iop_32to16, getIReg(rs))),
- unop(Iop_16Sto32,
- unop(Iop_32HIto16, getIReg(rt))))));
- assign(t2,
- binop(Iop_Sub64,
- getAcc(ac),
- binop(Iop_Add64, mkexpr(t0), mkexpr(t1))));
- putAcc(ac, mkexpr(t2));
- break;
- }
- case 0xB: { /* DPSU.H.QBL */
- DIP("dpsu.h.qbl ac%u, r%u, r%u", ac, rs, rt);
- vassert(!mode64);
-
- t0 = newTemp(Ity_I32);
- t1 = newTemp(Ity_I32);
- t2 = newTemp(Ity_I64);
- t3 = newTemp(Ity_I64);
-
- assign(t0,
- binop(Iop_Mul32,
- unop(Iop_8Uto32,
- unop(Iop_16HIto8,
- unop(Iop_32HIto16, getIReg(rs)))),
- unop(Iop_8Uto32,
- unop(Iop_16HIto8,
- unop(Iop_32HIto16, getIReg(rt))))));
- assign(t1,
- binop(Iop_Mul32,
- unop(Iop_8Uto32,
- unop(Iop_16to8,
- unop(Iop_32HIto16, getIReg(rs)))),
- unop(Iop_8Uto32,
- unop(Iop_16to8,
- unop(Iop_32HIto16, getIReg(rt))))));
- assign(t2,
- unop(Iop_32Uto64,
- binop(Iop_Add32, mkexpr(t0), mkexpr(t1))));
- assign(t3,
- binop(Iop_Sub64, getAcc(ac), mkexpr(t2)));
- putAcc(ac, mkexpr(t3));
- break;
- }
- case 0xC: { /* DPAQ_SA.L.W */
- DIP("dpaq_sa.l.w ac%u, r%u, r%u", ac, rs, rt);
- vassert(!mode64);
- t0 = newTemp(Ity_I64);
- t1 = newTemp(Ity_I64);
- t2 = newTemp(Ity_I1);
- t3 = newTemp(Ity_I1);
- t4 = newTemp(Ity_I64);
- t5 = newTemp(Ity_I64);
- t6 = newTemp(Ity_I64);
- t7 = newTemp(Ity_I64);
- t8 = newTemp(Ity_I1);
- t9 = newTemp(Ity_I1);
-
- assign(t0, getAcc(ac));
-
- assign(t1, binop(Iop_Shl64,
- binop(Iop_MullS32,
- getIReg(rs), getIReg(rt)),
- mkU8(0x1)));
-
- assign(t2, binop(Iop_CmpEQ32,
- getIReg(rs),
- mkU32(0x80000000)));
- assign(t3, binop(Iop_CmpEQ32,
- getIReg(rt),
- mkU32(0x80000000)));
-
- assign(t4,
- IRExpr_ITE(mkexpr(t2),
- IRExpr_ITE(mkexpr(t3),
- mkU64(0x7fffffffffffffffULL),
- mkexpr(t1)),
- mkexpr(t1)));
-
- putDSPControl(IRExpr_ITE(mkexpr(t2),
- IRExpr_ITE(mkexpr(t3),
- binop(Iop_Or32,
- getDSPControl(),
- binop(Iop_Shl32,
- mkU32(0x1),
- mkU8(ac+16)
- )
- ),
- getDSPControl()),
- getDSPControl()));
-
- assign(t5, binop(Iop_Add64,
- unop(Iop_32Uto64,
- unop(Iop_64to32, mkexpr(t0))),
- unop(Iop_32Uto64,
- unop(Iop_64to32, mkexpr(t4)))));
- assign(t6,
- binop(Iop_Add64,
- binop(Iop_Add64,
- unop(Iop_32Sto64,
- unop(Iop_64HIto32, mkexpr(t0))),
- unop(Iop_32Sto64,
- unop(Iop_64HIto32, mkexpr(t4)))),
- unop(Iop_32Uto64,
- binop(Iop_And32,
- unop(Iop_64HIto32, mkexpr(t5)),
- mkU32(0x1)))));
- assign(t7, binop(Iop_32HLto64,
- unop(Iop_64to32, mkexpr(t6)),
- unop(Iop_64to32, mkexpr(t5))));
- assign(t8, binop(Iop_CmpEQ32,
- binop(Iop_Shr32,
- binop(Iop_And32,
- unop(Iop_64to32, mkexpr(t6)),
- mkU32(0x80000000)),
- mkU8(31)),
- binop(Iop_And32,
- unop(Iop_64HIto32, mkexpr(t6)),
- mkU32(0x00000001))));
- assign(t9, binop(Iop_CmpEQ32,
- binop(Iop_And32,
- unop(Iop_64HIto32,
- mkexpr(t6)),
- mkU32(0x00000001)),
- mkU32(0x1)));
- putDSPControl(IRExpr_ITE(mkexpr(t8),
- getDSPControl(),
- binop(Iop_Or32,
- getDSPControl(),
- binop(Iop_Shl32,
- mkU32(0x1),
- mkU8(ac+16)))));
- putAcc(ac,
- IRExpr_ITE(mkexpr(t8),
- mkexpr(t7),
- IRExpr_ITE(mkexpr(t9),
- mkU64(0x8000000000000000ULL),
- mkU64(0x7fffffffffffffffULL)))
- );
- break;
- }
- case 0xD: { /* DPSQ_SA.L.W */
- DIP("dpsq_sa.l.w ac%u, r%u, r%u", ac, rs, rt);
- vassert(!mode64);
- t0 = newTemp(Ity_I64);
- t1 = newTemp(Ity_I64);
- t2 = newTemp(Ity_I1);
- t3 = newTemp(Ity_I1);
- t4 = newTemp(Ity_I64);
- t5 = newTemp(Ity_I64);
- t6 = newTemp(Ity_I64);
- t7 = newTemp(Ity_I64);
- t8 = newTemp(Ity_I1);
- t9 = newTemp(Ity_I1);
-
- assign(t0, getAcc(ac));
-
- assign(t1, binop(Iop_Shl64,
- binop(Iop_MullS32,
- getIReg(rs), getIReg(rt)),
- mkU8(0x1)));
-
- assign(t2, binop(Iop_CmpEQ32,
- getIReg(rs),
- mkU32(0x80000000)));
- assign(t3, binop(Iop_CmpEQ32,
- getIReg(rt),
- mkU32(0x80000000)));
-
- assign(t4,
- IRExpr_ITE(mkexpr(t2),
- IRExpr_ITE(mkexpr(t3),
- mkU64(0x7fffffffffffffffULL),
- mkexpr(t1)),
- mkexpr(t1)));
-
- putDSPControl(IRExpr_ITE(mkexpr(t2),
- IRExpr_ITE(mkexpr(t3),
- binop(Iop_Or32,
- getDSPControl(),
- binop(Iop_Shl32,
- mkU32(0x1),
- mkU8(ac+16)
- )
- ),
- getDSPControl()),
- getDSPControl()));
-
- assign(t5, binop(Iop_Sub64,
- unop(Iop_32Uto64,
- unop(Iop_64to32, mkexpr(t0))),
- unop(Iop_32Uto64,
- unop(Iop_64to32, mkexpr(t4)))));
- assign(t6, binop(Iop_Sub64,
- binop(Iop_Add64,
- unop(Iop_32Sto64,
- unop(Iop_64HIto32, mkexpr(t0))
- ),
- unop(Iop_32Sto64,
- unop(Iop_1Sto32,
- binop(Iop_CmpLT32U,
- unop(Iop_64to32,
- mkexpr(t0)),
- unop(Iop_64to32,
- mkexpr(t4)))))),
- unop(Iop_32Sto64,
- unop(Iop_64HIto32, mkexpr(t4)))));
- assign(t7, binop(Iop_32HLto64,
- unop(Iop_64to32, mkexpr(t6)),
- unop(Iop_64to32, mkexpr(t5))));
- assign(t8, binop(Iop_CmpEQ32,
- binop(Iop_Shr32,
- binop(Iop_And32,
- unop(Iop_64to32, mkexpr(t6)),
- mkU32(0x80000000)),
- mkU8(31)),
- binop(Iop_And32,
- unop(Iop_64HIto32, mkexpr(t6)),
- mkU32(0x00000001))));
- assign(t9, binop(Iop_CmpEQ32,
- binop(Iop_And32,
- unop(Iop_64HIto32, mkexpr(t6)),
- mkU32(0x00000001)),
- mkU32(0x1)));
- putDSPControl(IRExpr_ITE(mkexpr(t8),
- getDSPControl(),
- binop(Iop_Or32,
- getDSPControl(),
- binop(Iop_Shl32,
- mkU32(0x1),
- mkU8(ac+16)))));
- putAcc(ac,
- IRExpr_ITE(mkexpr(t8),
- mkexpr(t7),
- IRExpr_ITE(mkexpr(t9),
- mkU64(0x8000000000000000ULL),
- mkU64(0x7fffffffffffffffULL)))
- );
- break;
- }
- case 0xF: { /* DPSU.H.QBR */
- DIP("dpsu.h.qbr ac%u r%u, r%u", ac, rs, rt);
- vassert(!mode64);
-
- t0 = newTemp(Ity_I32);
- t1 = newTemp(Ity_I32);
- t2 = newTemp(Ity_I64);
- t3 = newTemp(Ity_I64);
-
- assign(t0,
- binop(Iop_Mul32,
- unop(Iop_8Uto32,
- unop(Iop_16HIto8,
- unop(Iop_32to16, getIReg(rs)))),
- unop(Iop_8Uto32,
- unop(Iop_16HIto8,
- unop(Iop_32to16, getIReg(rt))))));
- assign(t1,
- binop(Iop_Mul32,
- unop(Iop_8Uto32,
- unop(Iop_16to8,
- unop(Iop_32to16, getIReg(rs)))),
- unop(Iop_8Uto32,
- unop(Iop_16to8,
- unop(Iop_32to16, getIReg(rt))))));
- assign(t2, unop(Iop_32Uto64,
- binop(Iop_Add32, mkexpr(t0), mkexpr(t1))));
- assign(t3, binop(Iop_Sub64, getAcc(ac), mkexpr(t2)));
- putAcc(ac, mkexpr(t3));
+ break;
+ }
+ }
- break;
- }
- case 0x10: { /* MAQ_SA.W.PHL */
- DIP("maq_sa.w.phl ac%u, r%u, r%u", ac, rs, rt);
- vassert(!mode64);
- t0 = newTemp(Ity_I64);
- t1 = newTemp(Ity_I64);
- t2 = newTemp(Ity_I1);
- t3 = newTemp(Ity_I1);
- t4 = newTemp(Ity_I64);
- t5 = newTemp(Ity_I64);
- t6 = newTemp(Ity_I1);
- t7 = newTemp(Ity_I64);
-
- assign(t0, getAcc(ac));
- assign(t1, unop(Iop_32Sto64,
- binop(Iop_Shl32,
- binop(Iop_Mul32,
- unop(Iop_16Sto32,
- unop(Iop_32HIto16,
- getIReg(rs))),
- unop(Iop_16Sto32,
- unop(Iop_32HIto16,
- getIReg(rt)))),
- mkU8(0x1))));
-
- /* If both input arguments are equal 0x8000, saturate
- intermediate product and write to DSPControl register.
- */
- assign(t2, binop(Iop_CmpEQ32,
- unop(Iop_16Uto32,
- unop(Iop_32HIto16, getIReg(rs))),
- mkU32(0x00008000)));
- assign(t3, binop(Iop_CmpEQ32,
- unop(Iop_16Uto32,
- unop(Iop_32HIto16, getIReg(rt))),
- mkU32(0x00008000)));
-
- assign(t4,
- IRExpr_ITE(mkexpr(t2),
- IRExpr_ITE(mkexpr(t3),
- mkU64(0x000000007fffffffULL),
- mkexpr(t1)),
- mkexpr(t1)));
-
- putDSPControl(IRExpr_ITE(mkexpr(t2),
- IRExpr_ITE(mkexpr(t3),
- binop(Iop_Or32,
- getDSPControl(),
- binop(Iop_Shl32,
- mkU32(0x1),
- mkU8(ac+16)
- )
- ),
- getDSPControl()),
- getDSPControl()));
- /* Add intermediate product and value in the
- accumulator. */
- assign(t5, binop(Iop_Add64, mkexpr(t0), mkexpr(t4)));
-
- /* Compare bits 31 and 32 of the value in t5. */
- assign(t6, binop(Iop_CmpEQ32,
- binop(Iop_Shr32,
- binop(Iop_And32,
- unop(Iop_64to32, mkexpr(t5)),
- mkU32(0x80000000)),
- mkU8(31)),
- binop(Iop_And32,
- unop(Iop_64HIto32, mkexpr(t5)),
- mkU32(1))));
- putDSPControl(IRExpr_ITE(mkexpr(t6),
- getDSPControl(),
- binop(Iop_Or32,
- getDSPControl(),
- binop(Iop_Shl32,
- mkU32(0x1),
- mkU8(ac+16)))));
- assign(t7,
- IRExpr_ITE(mkexpr(t6),
- mkexpr(t5),
- IRExpr_ITE(binop(Iop_CmpEQ32,
- binop(Iop_And32,
- unop(Iop_64HIto32,
- mkexpr(t5)),
- mkU32(1)),
- mkU32(0x0)),
- mkU64(0x000000007fffffffULL),
- mkU64(0xffffffff80000000ULL)))
- );
- putAcc(ac, mkexpr(t7));
- break;
- }
- case 0x12: { /* MAQ_SA.W.PHR */
- DIP("maq_sa.w.phr ac%u, r%u, r%u", ac, rs, rt);
- vassert(!mode64);
- t0 = newTemp(Ity_I64);
- t1 = newTemp(Ity_I64);
- t2 = newTemp(Ity_I1);
- t3 = newTemp(Ity_I1);
- t4 = newTemp(Ity_I64);
- t5 = newTemp(Ity_I64);
- t6 = newTemp(Ity_I1);
- t7 = newTemp(Ity_I64);
-
- assign(t0, getAcc(ac));
- assign(t1, unop(Iop_32Sto64,
- binop(Iop_Shl32,
- binop(Iop_Mul32,
- unop(Iop_16Sto32,
- unop(Iop_32to16,
- getIReg(rs))),
- unop(Iop_16Sto32,
- unop(Iop_32to16,
- getIReg(rt)))),
- mkU8(0x1))));
-
- /* If both input arguments are equal 0x8000, saturate
- intermediate product and write to DSPControl
- register. */
- assign(t2, binop(Iop_CmpEQ32,
- unop(Iop_16Uto32,
- unop(Iop_32to16, getIReg(rs))),
- mkU32(0x00008000)));
- assign(t3, binop(Iop_CmpEQ32,
- unop(Iop_16Uto32,
- unop(Iop_32to16, getIReg(rt))),
- mkU32(0x00008000)));
-
- assign(t4,
- IRExpr_ITE(mkexpr(t2),
- IRExpr_ITE(mkexpr(t3),
- mkU64(0x000000007fffffffULL),
- mkexpr(t1)),
- mkexpr(t1)));
-
- putDSPControl(IRExpr_ITE(mkexpr(t2),
- IRExpr_ITE(mkexpr(t3),
- binop(Iop_Or32,
- getDSPControl(),
- binop(Iop_Shl32,
- mkU32(0x1),
- mkU8(ac+16)
- )
- ),
- getDSPControl()),
- getDSPControl()));
- /* Add intermediate product and value in the
- accumulator. */
- assign(t5, binop(Iop_Add64, mkexpr(t0), mkexpr(t4)));
-
- /* Compare bits 31 and 32 of the value in t5. */
- assign(t6, binop(Iop_CmpEQ32,
- binop(Iop_Shr32,
- binop(Iop_And32,
- unop(Iop_64to32, mkexpr(t5)),
- mkU32(0x80000000)),
- mkU8(31)),
- binop(Iop_And32,
- unop(Iop_64HIto32, mkexpr(t5)),
- mkU32(1))));
- putDSPControl(IRExpr_ITE(mkexpr(t6),
- getDSPControl(),
- binop(Iop_Or32,
- getDSPControl(),
- binop(Iop_Shl32,
- mkU32(0x1),
- mkU8(ac+16)))));
- assign(t7,
- IRExpr_ITE(mkexpr(t6),
- mkexpr(t5),
- IRExpr_ITE(binop(Iop_CmpEQ32,
- binop(Iop_And32,
- unop(Iop_64HIto32,
- mkexpr(t5)),
- mkU32(1)),
- mkU32(0x0)),
- mkU64(0x000000007fffffffULL),
- mkU64(0xffffffff80000000ULL)))
- );
- putAcc(ac, mkexpr(t7));
- break;
- }
- case 0x14: { /* MAQ_S.W.PHL */
- DIP("maq_s.w.phl ac%u, r%u, r%u", ac, rs, rt);
- vassert(!mode64);
- t0 = newTemp(Ity_I32);
- t1 = newTemp(Ity_I32);
- t2 = newTemp(Ity_I32);
- t3 = newTemp(Ity_I1);
- t4 = newTemp(Ity_I32);
- t5 = newTemp(Ity_I64);
-
- assign(t5, getAcc(ac));
-
- assign(t0, unop(Iop_16Sto32,
- unop(Iop_32HIto16, getIReg(rs))));
- assign(t1, unop(Iop_16Sto32,
- unop(Iop_32HIto16, getIReg(rt))));
-
- assign(t2, binop(Iop_And32,
- unop(Iop_1Sto32,
- binop(Iop_CmpEQ32,
- binop(Iop_And32,
- mkexpr(t0),
- mkU32(0xffff)),
- mkU32(0x8000))),
- unop(Iop_1Sto32,
- binop(Iop_CmpEQ32,
- binop(Iop_And32,
- mkexpr(t1),
- mkU32(0xffff)),
- mkU32(0x8000)))));
+ break;
+ }
- assign(t3, binop(Iop_CmpEQ32, mkexpr(t2), mkU32(0x0)));
+ case 0x03: { /* SRLRI.df */
+ switch (df) {
+ case 0x00: { /* SRLRI.B */
+ DIP("SRLRI.B w%d, w%d, %d", wd, ws, m);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ assign(t1,
+ binop(Iop_ShrN8x16,
+ getWReg(ws),
+ mkU8(m)));
+ assign(t2,
+ binop(Iop_ShrN8x16,
+ binop(Iop_ShlN8x16,
+ getWReg(ws),
+ mkU8(8 - m)),
+ mkU8(7)));
- putDSPControl(IRExpr_ITE(mkexpr(t3),
- getDSPControl(),
- binop(Iop_Or32,
- getDSPControl(),
- binop(Iop_Shl32,
- mkU32(0x1),
- mkU8(ac+16)))));
+ if (m)
+ putWReg(wd,
+ binop(Iop_Add8x16,
+ mkexpr(t1), mkexpr(t2)));
+ else putWReg(wd, mkexpr(t1));
- assign(t4, unop(Iop_64to32,
- binop(Iop_MullS32,
- mkexpr(t0), mkexpr(t1))));
- putAcc(ac, IRExpr_ITE(mkexpr(t3),
- binop(Iop_Add64,
- unop(Iop_32Sto64,
- binop(Iop_Shl32,
- mkexpr(t4),
- mkU8(0x1))),
- mkexpr(t5)),
- binop(Iop_Add64,
- mkexpr(t5),
- unop(Iop_32Sto64,
- mkU32(0x7fffffff)))));
- break;
- }
- case 0x16: { /* MAQ_S.W.PHR */
- DIP("maq_s.w.phr ac%u, r%u, r%u", ac, rs, rt);
- vassert(!mode64);
- t0 = newTemp(Ity_I32);
- t1 = newTemp(Ity_I32);
- t2 = newTemp(Ity_I32);
- t3 = newTemp(Ity_I1);
- t4 = newTemp(Ity_I32);
- t5 = newTemp(Ity_I64);
-
- assign(t5, getAcc(ac));
-
- assign(t0, unop(Iop_16Sto32,
- unop(Iop_32to16, getIReg(rs))));
- assign(t1, unop(Iop_16Sto32,
- unop(Iop_32to16, getIReg(rt))));
-
- assign(t2, binop(Iop_And32,
- unop(Iop_1Sto32,
- binop(Iop_CmpEQ32,
- binop(Iop_And32,
- mkexpr(t0),
- mkU32(0xffff)),
- mkU32(0x8000))),
- unop(Iop_1Sto32,
- binop(Iop_CmpEQ32,
- binop(Iop_And32,
- mkexpr(t1),
- mkU32(0xffff)),
- mkU32(0x8000)))));
+ break;
+ }
- assign(t3, binop(Iop_CmpEQ32, mkexpr(t2), mkU32(0x0)));
+ case 0x01: { /* SRLRI.H */
+ DIP("SRLRI.H w%d, w%d, %d", wd, ws, m);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ assign(t1,
+ binop(Iop_ShrN16x8,
+ getWReg(ws),
+ mkU8(m)));
+ assign(t2,
+ binop(Iop_ShrN16x8,
+ binop(Iop_ShlN16x8,
+ getWReg(ws),
+ mkU8(16 - m)),
+ mkU8(15)));
- putDSPControl(IRExpr_ITE(mkexpr(t3),
- getDSPControl(),
- binop(Iop_Or32,
- getDSPControl(),
- binop(Iop_Shl32,
- mkU32(0x1),
- mkU8(ac+16)))));
+ if (m)
+ putWReg(wd,
+ binop(Iop_Add16x8,
+ mkexpr(t1), mkexpr(t2)));
+ else putWReg(wd, mkexpr(t1));
- assign(t4, unop(Iop_64to32,
- binop(Iop_MullS32,
- mkexpr(t0), mkexpr(t1))));
- putAcc(ac, IRExpr_ITE(mkexpr(t3),
- binop(Iop_Add64,
- unop(Iop_32Sto64,
- binop(Iop_Shl32,
- mkexpr(t4),
- mkU8(0x1))),
- mkexpr(t5)),
- binop(Iop_Add64,
- mkexpr(t5),
- unop(Iop_32Sto64,
- mkU32(0x7fffffff)))));
- break;
- }
- case 0x18: { /* DPAQX_S.W.PH */
- DIP("dpaqx_s.w.ph ac%u, r%u, r%u", ac, rs, rt);
- vassert(!mode64);
- t0 = newTemp(Ity_I64);
- t1 = newTemp(Ity_I64);
- t2 = newTemp(Ity_I1);
- t3 = newTemp(Ity_I1);
- t4 = newTemp(Ity_I64);
- t5 = newTemp(Ity_I64);
- t6 = newTemp(Ity_I1);
- t7 = newTemp(Ity_I1);
- t8 = newTemp(Ity_I64);
- t9 = newTemp(Ity_I64);
-
- assign(t0, getAcc(ac));
-
- assign(t1, binop(Iop_Shl64,
- binop(Iop_MullS32,
- unop(Iop_16Sto32,
- unop(Iop_32HIto16,
- getIReg(rs))),
- unop(Iop_16Sto32,
- unop(Iop_32to16,
- getIReg(rt)))),
- mkU8(0x1)));
- assign(t2, binop(Iop_CmpEQ32,
- unop(Iop_16Uto32,
- unop(Iop_32HIto16, getIReg(rs))),
- mkU32(0x00008000)));
- assign(t3, binop(Iop_CmpEQ32,
- unop(Iop_16Uto32,
- unop(Iop_32to16, getIReg(rt))),
- mkU32(0x00008000)));
- assign(t4,
- IRExpr_ITE(mkexpr(t2),
- IRExpr_ITE(mkexpr(t3),
- mkU64(0x000000007fffffffULL),
- mkexpr(t1)),
- mkexpr(t1)));
-
- putDSPControl(IRExpr_ITE(mkexpr(t2),
- IRExpr_ITE(mkexpr(t3),
- binop(Iop_Or32,
- getDSPControl(),
- binop(Iop_Shl32,
- mkU32(0x1),
- mkU8(ac+16))),
- getDSPControl()),
- getDSPControl()));
-
- assign(t5, binop(Iop_Shl64,
- binop(Iop_MullS32,
- unop(Iop_16Sto32,
- unop(Iop_32to16,
- getIReg(rs))),
- unop(Iop_16Sto32,
- unop(Iop_32HIto16,
- getIReg(rt)))),
- mkU8(0x1)));
- assign(t6, binop(Iop_CmpEQ32,
- unop(Iop_16Uto32,
- unop(Iop_32to16, getIReg(rs))),
- mkU32(0x00008000)));
- assign(t7, binop(Iop_CmpEQ32,
- unop(Iop_16Uto32,
- unop(Iop_32HIto16, getIReg(rt))),
- mkU32(0x00008000)));
- assign(t8,
- IRExpr_ITE(mkexpr(t6),
- IRExpr_ITE(mkexpr(t7),
- mkU64(0x000000007fffffffULL),
- mkexpr(t5)),
- mkexpr(t5)));
-
- putDSPControl(IRExpr_ITE(mkexpr(t6),
- IRExpr_ITE(mkexpr(t7),
- binop(Iop_Or32,
- getDSPControl(),
- binop(Iop_Shl32,
- mkU32(0x1),
- mkU8(ac+16)
- )
- ),
- getDSPControl()),
- getDSPControl()));
-
- assign(t9, binop(Iop_Add64,
- binop(Iop_Add64, mkexpr(t4), mkexpr(t8)),
- mkexpr(t0)));
- putAcc(ac, mkexpr(t9));
- break;
- }
- case 0x19: { /* DPSQX_S.W.PH */
- DIP("dpsqx_s.w.ph ac%u, r%u, r%u", ac, rs, rt);
- vassert(!mode64);
- t0 = newTemp(Ity_I64);
- t1 = newTemp(Ity_I64);
- t2 = newTemp(Ity_I1);
- t3 = newTemp(Ity_I1);
- t4 = newTemp(Ity_I64);
- t5 = newTemp(Ity_I64);
- t6 = newTemp(Ity_I1);
- t7 = newTemp(Ity_I1);
- t8 = newTemp(Ity_I64);
- t9 = newTemp(Ity_I64);
-
- assign(t0, getAcc(ac));
-
- assign(t1, binop(Iop_Shl64,
- binop(Iop_MullS32,
- unop(Iop_16Sto32,
- unop(Iop_32HIto16,
- getIReg(rs))),
- unop(Iop_16Sto32,
- unop(Iop_32to16,
- getIReg(rt)))),
- mkU8(0x1)));
- assign(t2, binop(Iop_CmpEQ32,
- unop(Iop_16Uto32,
- unop(Iop_32HIto16, getIReg(rs))),
- mkU32(0x00008000)));
- assign(t3, binop(Iop_CmpEQ32,
- unop(Iop_16Uto32,
- unop(Iop_32to16, getIReg(rt))),
- mkU32(0x00008000)));
- assign(t4,
- IRExpr_ITE(mkexpr(t2),
- IRExpr_ITE(mkexpr(t3),
- mkU64(0x000000007fffffffULL),
- mkexpr(t1)),
- mkexpr(t1)));
-
- putDSPControl(IRExpr_ITE(mkexpr(t2),
- IRExpr_ITE(mkexpr(t3),
- binop(Iop_Or32,
- getDSPControl(),
- binop(Iop_Shl32,
- mkU32(0x1),
- mkU8(ac+16)
- )
- ),
- getDSPControl()),
- getDSPControl()));
-
- assign(t5, binop(Iop_Shl64,
- binop(Iop_MullS32,
- unop(Iop_16Sto32,
- unop(Iop_32to16,
- getIReg(rs))),
- unop(Iop_16Sto32,
- unop(Iop_32HIto16,
- getIReg(rt)))),
- mkU8(0x1)));
- assign(t6, binop(Iop_CmpEQ32,
- unop(Iop_16Uto32,
- unop(Iop_32to16, getIReg(rs))),
- mkU32(0x00008000)));
- assign(t7, binop(Iop_CmpEQ32,
- unop(Iop_16Uto32,
- unop(Iop_32HIto16, getIReg(rt))),
- mkU32(0x00008000)));
- assign(t8,
- IRExpr_ITE(mkexpr(t6),
- IRExpr_ITE(mkexpr(t7),
- mkU64(0x000000007fffffffULL),
- mkexpr(t5)),
- mkexpr(t5)));
-
- putDSPControl(IRExpr_ITE(mkexpr(t6),
- IRExpr_ITE(mkexpr(t7),
- binop(Iop_Or32,
- getDSPControl(),
- binop(Iop_Shl32,
- mkU32(0x1),
- mkU8(ac+16)
- )
- ),
- getDSPControl()),
- getDSPControl()));
-
- assign(t9, binop(Iop_Sub64,
- mkexpr(t0),
- binop(Iop_Add64, mkexpr(t4), mkexpr(t8))));
- putAcc(ac, mkexpr(t9));
- break;
- }
- case 0x1A: { /* DPAQX_SA.W.PH */
- DIP("dpaqx_sa.w.ph ac%u, r%u, r%u", ac, rs, rt);
- vassert(!mode64);
- t0 = newTemp(Ity_I64);
- t1 = newTemp(Ity_I64);
- t2 = newTemp(Ity_I1);
- t3 = newTemp(Ity_I1);
- t4 = newTemp(Ity_I64);
- t5 = newTemp(Ity_I64);
- t6 = newTemp(Ity_I1);
- t7 = newTemp(Ity_I1);
- t8 = newTemp(Ity_I64);
- t9 = newTemp(Ity_I64);
- t10 = newTemp(Ity_I32);
-
- assign(t0, getAcc(ac));
- /* Calculate the first cross dot product and saturate if
- needed. */
- assign(t1, unop(Iop_32Sto64,
- binop(Iop_Shl32,
- binop(Iop_Mul32,
- unop(Iop_16Sto32,
- unop(Iop_32HIto16,
- getIReg(rs))),
- unop(Iop_16Sto32,
- unop(Iop_32to16,
- getIReg(rt)))),
- mkU8(0x1))));
-
- /* If both input arguments are equal 0x8000, saturate
- intermediate product and write to DSPControl
- register. */
- assign(t2, binop(Iop_CmpEQ32,
- unop(Iop_16Uto32,
- unop(Iop_32HIto16, getIReg(rs))),
- mkU32(0x00008000)));
- assign(t3, binop(Iop_CmpEQ32,
- unop(Iop_16Uto32,
- unop(Iop_32to16, getIReg(rt))),
- mkU32(0x00008000)));
-
- assign(t4, IRExpr_ITE(binop(Iop_CmpNE32,
- binop(Iop_And32,
- unop(Iop_1Sto32,
- mkexpr(t2)),
- unop(Iop_1Sto32,
- mkexpr(t3))),
- mkU32(0)),
- mkU64(0x000000007fffffffULL),
- mkexpr(t1)));
-
- putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
- binop(Iop_And32,
- unop(Iop_1Sto32,
- mkexpr(t2)),
- unop(Iop_1Sto32,
- mkexpr(t3))),
- mkU32(0)),
- binop(Iop_Or32,
- getDSPControl(),
- binop(Iop_Shl32,
- mkU32(0x1),
- mkU8(ac+16))),
- getDSPControl()));
- /* Calculate second cross dot product and saturate if
- needed. */
- assign(t5, unop(Iop_32Sto64,
- binop(Iop_Shl32,
- binop(Iop_Mul32,
- unop(Iop_16Sto32,
- unop(Iop_32to16,
- getIReg(rs))),
- unop(Iop_16Sto32,
- unop(Iop_32HIto16,
- getIReg(rt)))),
- mkU8(0x1))));
-
- /* If both input arguments are equal 0x8000, saturate
- intermediate product and write to DSPControl
- register. */
- assign(t6, binop(Iop_CmpEQ32,
- unop(Iop_16Uto32,
- unop(Iop_32to16, getIReg(rs))),
- mkU32(0x00008000)));
- assign(t7, binop(Iop_CmpEQ32,
- unop(Iop_16Uto32,
- unop(Iop_32HIto16, getIReg(rt))),
- mkU32(0x00008000)));
-
- assign(t8, IRExpr_ITE(binop(Iop_CmpNE32,
- binop(Iop_And32,
- unop(Iop_1Sto32,
- mkexpr(t6)),
- unop(Iop_1Sto32,
- mkexpr(t7))),
- mkU32(0)),
- mkU64(0x000000007fffffffULL),
- mkexpr(t5)));
-
- putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
- binop(Iop_And32,
- unop(Iop_1Sto32,
- mkexpr(t6)),
- unop(Iop_1Sto32,
- mkexpr(t7))),
- mkU32(0)),
- binop(Iop_Or32,
- getDSPControl(),
- binop(Iop_Shl32,
- mkU32(0x1),
- mkU8(ac+16))),
- getDSPControl()));
- /* Subtract intermediate products from value in the
- accumulator. */
- assign(t9,
- binop(Iop_Add64,
- mkexpr(t0),
- binop(Iop_Add64, mkexpr(t8), mkexpr(t4))));
-
- putAcc(ac,
- IRExpr_ITE(binop(Iop_CmpEQ32,
- binop(Iop_And32,
- unop(Iop_64HIto32,
- mkexpr(t9)),
- mkU32(0x80000000)),
- mkU32(0x0)),
- IRExpr_ITE(binop(Iop_CmpNE32,
- unop(Iop_64HIto32,
- binop(Iop_Shl64,
- mkexpr(t9),
- mkU8(1))),
- mkU32(0x0)),
- mkU64(0x000000007fffffffULL),
- mkexpr(t9)),
- IRExpr_ITE(binop(Iop_CmpNE32,
- unop(Iop_64HIto32,
- binop(Iop_Shl64,
- mkexpr(t9),
- mkU8(1))),
- mkU32(0xffffffff)),
- mkU64(0xffffffff80000000ULL),
- mkexpr(t9))));
- assign(t10, IRExpr_ITE(binop(Iop_CmpEQ32,
- unop(Iop_64to32,
- mkexpr(t9)),
- unop(Iop_64to32,
- getAcc(ac))),
- getDSPControl(),
- binop(Iop_Or32,
- getDSPControl(),
- binop(Iop_Shl32,
- mkU32(0x1),
- mkU8(ac+16)))));
- putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
- unop(Iop_64HIto32,
- mkexpr(t9)),
- unop(Iop_64HIto32,
- getAcc(ac))),
- mkexpr(t10),
- binop(Iop_Or32,
- getDSPControl(),
- binop(Iop_Shl32,
- mkU32(0x1),
- mkU8(ac+16)))));
- break;
- }
- case 0x1B: { /* DPSQX_SA.W.PH */
- DIP("dpsqx_sa.w.ph ac%u, r%u, r%u", ac, rs, rt);
- vassert(!mode64);
- t0 = newTemp(Ity_I64);
- t1 = newTemp(Ity_I64);
- t2 = newTemp(Ity_I1);
- t3 = newTemp(Ity_I1);
- t4 = newTemp(Ity_I64);
- t5 = newTemp(Ity_I64);
- t6 = newTemp(Ity_I1);
- t7 = newTemp(Ity_I1);
- t8 = newTemp(Ity_I64);
- t9 = newTemp(Ity_I64);
- t10 = newTemp(Ity_I32);
-
- assign(t0, getAcc(ac));
- /* Calculate the first cross dot product and saturate if
- needed. */
- assign(t1, unop(Iop_32Sto64,
- binop(Iop_Shl32,
- binop(Iop_Mul32,
- unop(Iop_16Sto32,
- unop(Iop_32HIto16,
- getIReg(rs))),
- unop(Iop_16Sto32,
- unop(Iop_32to16,
- getIReg(rt)))),
- mkU8(0x1))));
-
- /* If both input arguments are equal 0x8000, saturate
- intermediate product and write to DSPControl
- register. */
- assign(t2, binop(Iop_CmpEQ32,
- unop(Iop_16Uto32,
- unop(Iop_32HIto16, getIReg(rs))),
- mkU32(0x00008000)));
- assign(t3, binop(Iop_CmpEQ32,
- unop(Iop_16Uto32,
- unop(Iop_32to16, getIReg(rt))),
- mkU32(0x00008000)));
-
- assign(t4, IRExpr_ITE(binop(Iop_CmpNE32,
- binop(Iop_And32,
- unop(Iop_1Sto32,
- mkexpr(t2)),
- unop(Iop_1Sto32,
- mkexpr(t3))),
- mkU32(0)),
- mkU64(0x000000007fffffffULL),
- mkexpr(t1)));
-
- putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
- binop(Iop_And32,
- unop(Iop_1Sto32,
- mkexpr(t2)),
- unop(Iop_1Sto32,
- mkexpr(t3))),
- mkU32(0)),
- binop(Iop_Or32,
- getDSPControl(),
- binop(Iop_Shl32,
- mkU32(0x1),
- mkU8(ac+16))),
- getDSPControl()));
- /* Calculate second cross dot product and saturate if
- needed. */
- assign(t5, unop(Iop_32Sto64,
- binop(Iop_Shl32,
- binop(Iop_Mul32,
- unop(Iop_16Sto32,
- unop(Iop_32to16,
- getIReg(rs))),
- unop(Iop_16Sto32,
- unop(Iop_32HIto16,
- getIReg(rt)))),
- mkU8(0x1))));
-
- /* If both input arguments are equal 0x8000, saturate
- intermediate product and write to DSPControl
- register. */
- assign(t6, binop(Iop_CmpEQ32,
- unop(Iop_16Uto32,
- unop(Iop_32to16, getIReg(rs))),
- mkU32(0x00008000)));
- assign(t7, binop(Iop_CmpEQ32,
- unop(Iop_16Uto32,
- unop(Iop_32HIto16, getIReg(rt))),
- mkU32(0x00008000)));
-
- assign(t8, IRExpr_ITE(binop(Iop_CmpNE32,
- binop(Iop_And32,
- unop(Iop_1Sto32,
- mkexpr(t6)),
- unop(Iop_1Sto32,
- mkexpr(t7))),
- mkU32(0)),
- mkU64(0x000000007fffffffULL),
- mkexpr(t5)));
-
- putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32,
- binop(Iop_And32,
- unop(Iop_1Sto32,
- mkexpr(t6)),
- unop(Iop_1Sto32,
- mkexpr(t7))),
- mkU32(0)),
- binop(Iop_Or32,
- getDSPControl(),
- binop(Iop_Shl32,
- mkU32(0x1),
- mkU8(ac+16))),
- getDSPControl()));
- /* Subtract intermediate products from value in the
- accumulator. */
- assign(t9,
- binop(Iop_Sub64,
- mkexpr(t0),
- binop(Iop_Add64, mkexpr(t8), mkexpr(t4))));
-
- putAcc(ac,
- IRExpr_ITE(binop(Iop_CmpEQ32,
- binop(Iop_And32,
- unop(Iop_64HIto32,
- mkexpr(t9)),
- mkU32(0x80000000)),
- mkU32(0x0)),
- IRExpr_ITE(binop(Iop_CmpNE32,
- unop(Iop_64HIto32,
- binop(Iop_Shl64,
- mkexpr(t9),
- mkU8(1))),
- mkU32(0x0)),
- mkU64(0x000000007fffffffULL),
- mkexpr(t9)),
- IRExpr_ITE(binop(Iop_CmpNE32,
- unop(Iop_64HIto32,
- binop(Iop_Shl64,
- mkexpr(t9),
- mkU8(1))),
- mkU32(0xffffffff)),
- mkU64(0xffffffff80000000ULL),
- mkexpr(t9))));
- assign(t10, IRExpr_ITE(binop(Iop_CmpEQ32,
- unop(Iop_64to32,
- mkexpr(t9)),
- unop(Iop_64to32,
- getAcc(ac))),
- getDSPControl(),
- binop(Iop_Or32,
- getDSPControl(),
- binop(Iop_Shl32,
- mkU32(0x1),
- mkU8(ac+16)))));
- putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32,
- unop(Iop_64HIto32,
- mkexpr(t9)),
- unop(Iop_64HIto32,
- getAcc(ac))),
- mkexpr(t10),
- binop(Iop_Or32,
- getDSPControl(),
- binop(Iop_Shl32,
- mkU32(0x1),
- mkU8(ac+16)))));
- break;
- }
- default:
- return -1;
- }
- break; /* end of DPAQ.W.PH */
+ break;
}
- case 0x31: { /* APPEND */
- switch(sa) {
- case 0x0: { /* APPEND */
- DIP("append r%u, r%u, %u", rt, rs, rd);
- vassert(!mode64);
- t1 = newTemp(Ity_I32);
- t2 = newTemp(Ity_I32);
- t3 = newTemp(Ity_I32);
- assign(t1, binop(Iop_Shl32, getIReg(rt), mkU8(rd)));
+ case 0x02: { /* SRLRI.W */
+ DIP("SRLRI.W w%d, w%d, %d", wd, ws, m);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ assign(t1,
+ binop(Iop_ShrN32x4,
+ getWReg(ws),
+ mkU8(m)));
+ assign(t2,
+ binop(Iop_ShrN32x4,
+ binop(Iop_ShlN32x4,
+ getWReg(ws),
+ mkU8(32 - m)),
+ mkU8(31)));
+
+ if (m)
+ putWReg(wd,
+ binop(Iop_Add32x4,
+ mkexpr(t1), mkexpr(t2)));
+ else putWReg(wd, mkexpr(t1));
- if (31 == rd) {
- putIReg(rt, binop(Iop_Or32,
- mkexpr(t1),
- binop(Iop_And32,
- getIReg(rs),
- mkU32(0x7fffffff))));
- } else if (1 == rd) {
- putIReg(rt,
- binop(Iop_Or32,
- mkexpr(t1),
- binop(Iop_And32,
- getIReg(rs), mkU32(0x1))));
- } else {
- assign(t2,
- unop(Iop_Not32,
- binop(Iop_Shl32,
- mkU32(0xffffffff), mkU8(rd))));
+ break;
+ }
- putIReg(rt, binop(Iop_Or32,
- mkexpr(t1),
- binop(Iop_And32,
- getIReg(rs), mkexpr(t2))));
- }
- break;
- }
- case 0x1: { /* PREPEND */
- DIP("prepend r%u, r%u, %u", rt, rs, rd);
- vassert(!mode64);
- t1 = newTemp(Ity_I32);
- t2 = newTemp(Ity_I32);
- t3 = newTemp(Ity_I32);
-
- if (0 != rd) {
- assign(t1, binop(Iop_Shr32, getIReg(rt), mkU8(rd)));
-
- if (31 == rd) {
- putIReg(rt, binop(Iop_Or32,
- mkexpr(t1),
- binop(Iop_Shl32,
- binop(Iop_And32,
- getIReg(rs),
- mkU32(0x7fffffff)),
- mkU8(1))));
- } else if (1 == rd) {
- putIReg(rt, binop(Iop_Or32,
- mkexpr(t1),
- binop(Iop_Shl32,
- binop(Iop_And32,
- getIReg(rs),
- mkU32(0x1)),
- mkU8(31))));
- } else {
- assign(t2, binop(Iop_Add32, mkU32(rd), mkU32(0x1)));
+ case 0x03: { /* SRLRI.D */
+ DIP("SRLRI.D w%d, w%d, %d", wd, ws, m);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ assign(t1,
+ binop(Iop_ShrN64x2,
+ getWReg(ws),
+ mkU8(m)));
+ assign(t2,
+ binop(Iop_ShrN64x2,
+ binop(Iop_ShlN64x2,
+ getWReg(ws),
+ mkU8(64 - m)),
+ mkU8(63)));
- assign(t3, unop(Iop_Not32,
- binop(Iop_Shl32,
- mkU32(0xffffffff),
- unop(Iop_32to8, mkexpr(t2)))));
+ if (m)
+ putWReg(wd,
+ binop(Iop_Add64x2,
+ mkexpr(t1), mkexpr(t2)));
+ else putWReg(wd, mkexpr(t1));
- putIReg(rt, binop(Iop_Or32,
- mkexpr(t1),
- binop(Iop_Shl32,
- binop(Iop_And32,
- getIReg(rs),
- mkexpr(t3)),
- mkU8(32-rd))));
- }
- }
- break;
- }
- case 0x10: { /* BALIGN */
- DIP("balign r%u, r%u, %u", rt, rs, rd);
- vassert(!mode64);
- t1 = newTemp(Ity_I32);
- t2 = newTemp(Ity_I32);
- t3 = newTemp(Ity_I32);
-
- if ((2 != rd) && (0 != rd)) {
- assign(t1, binop(Iop_Shl32,
- binop(Iop_And32,
- mkU32(rd), mkU32(0x3)),
- mkU8(0x3)));
- assign(t2, binop(Iop_Shl32,
- getIReg(rt),
- unop(Iop_32to8, mkexpr(t1))));
- assign(t3, binop(Iop_Shr32,
- getIReg(rs),
- unop(Iop_32to8,
- binop(Iop_Shl32,
- binop(Iop_Sub32,
- mkU32(0x4),
- binop(Iop_And32,
- mkU32(rd),
- mkU32(0x3))),
- mkU8(0x3)))));
- putIReg(rt, binop(Iop_Or32, mkexpr(t2), mkexpr(t3)));
- }
- break;
- }
- default:
- return -1;
- }
- break; /* end of APPEND */
+ break;
}
- default:
- return -1;
}
+
break;
}
+
default:
- return -1;
+ return -1;
}
+
return 0;
}
-static Int msa_I8_logical(UInt cins, UChar wd, UChar ws) {
- IRTemp t1, t2;
+static Int msa_3R_0D(UInt cins, UChar wd, UChar ws) /* 3R (0x0D) */
+{
+ IRTemp t1, t2, t3;
UShort operation;
- UChar i8;
+ UChar df, wt;
+
+ operation = (cins & 0x03800000) >> 23;
+ df = (cins & 0x00600000) >> 21;
+ wt = (cins & 0x001F0000) >> 16;
- operation = (cins >> 24) & 3;
- i8 = (cins & 0x00FF0000) >> 16;
switch (operation) {
- case 0x00: { /* ANDI.B */
- DIP("ANDI.B w%d, w%d, %d", wd, ws, i8);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- ULong tmp = i8;
- tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
- (tmp << 32) | (tmp << 24) | (tmp << 16) |
- (tmp << 8);
- assign(t1, getWReg(ws));
- assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
- putWReg(wd, binop(Iop_AndV128, mkexpr(t1), mkexpr(t2)));
- break;
+ case 0x00: { /* SLL.df */
+ switch (df) {
+ case 0x00: { /* SLL.B */
+ DIP("SLL.B w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3, binop(Iop_Shl8x16, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
+
+ case 0x01: { /* SLL.H */
+ DIP("SLL.H w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3, binop(Iop_Shl16x8, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
+
+ case 0x02: { /* SLL.W */
+ DIP("SLL.W w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3, binop(Iop_Shl32x4, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
+
+ case 0x03: { /* SLL.D */
+ DIP("SLL.D w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3, binop(Iop_Shl64x2, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
+
+ default:
+ return -1;
}
- case 0x01: { /* ORI.B */
- DIP("ORI.B w%d, w%d, %d", wd, ws, i8);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- ULong tmp = i8;
- tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
- (tmp << 32) | (tmp << 24) | (tmp << 16) |
- (tmp << 8);
- assign(t1, getWReg(ws));
- assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
- putWReg(wd, binop(Iop_OrV128, mkexpr(t1), mkexpr(t2)));
- break;
+ break;
+ }
+
+ case 0x01: { /* SRA.df */
+ switch (df) {
+ case 0x00: { /* SRA.B */
+ DIP("SRA.B w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3, binop(Iop_Sar8x16, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
+
+ case 0x01: { /* SRA.H */
+ DIP("SRA.H w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3, binop(Iop_Sar16x8, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
+
+ case 0x02: { /* SRA.W */
+ DIP("SRA.W w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3, binop(Iop_Sar32x4, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
+
+ case 0x03: { /* SRA.D */
+ DIP("SRA.D w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3, binop(Iop_Sar64x2, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
+
+ default:
+ return -1;
}
- case 0x02: { /* NORI.B */
- DIP("NORI.B w%d, w%d, %d", wd, ws, i8);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- ULong tmp = i8;
- tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
- (tmp << 32) | (tmp << 24) | (tmp << 16) |
- (tmp << 8);
- assign(t1, getWReg(ws));
- assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
- putWReg(wd, unop(Iop_NotV128, binop(Iop_OrV128,
- mkexpr(t1), mkexpr(t2))));
- break;
+ break;
+ }
+
+ case 0x02: { /* SRL.df */
+ switch (df) {
+ case 0x00: { /* SRL.B */
+ DIP("SRL.B w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3, binop(Iop_Shr8x16, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
+
+ case 0x01: { /* SRL.H */
+ DIP("SRL.H w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3, binop(Iop_Shr16x8, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
+
+ case 0x02: { /* SRL.W */
+ DIP("SRL.W w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3, binop(Iop_Shr32x4, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
+
+ case 0x03: { /* SRL.D */
+ DIP("SRL.D w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3, binop(Iop_Shr64x2, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
+
+ default:
+ return -1;
}
- case 0x03: { /* XORI.B */
- DIP("XORI.B w%d, w%d, %d", wd, ws, i8);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- ULong tmp = i8;
- tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
- (tmp << 32) | (tmp << 24) | (tmp << 16) |
- (tmp << 8);
- assign(t1, getWReg(ws));
- assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
- putWReg(wd, binop(Iop_XorV128, mkexpr(t1), mkexpr(t2)));
- break;
+ break;
+ }
+
+ case 0x03: { /* BCLR.df */
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ ULong tmp = 1;
+ assign(t1, getWReg(ws));
+
+ switch (df) {
+ case 0x00: { /* BCLR.B */
+ DIP("BCLR.B w%d, w%d, w%d", wd, ws, wt);
+ tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
+ (tmp << 32) | (tmp << 24) | (tmp << 16) |
+ (tmp << 8);
+ assign(t2, binop(Iop_Shl8x16,
+ binop(Iop_64HLtoV128,
+ mkU64(tmp), mkU64(tmp)),
+ getWReg(wt)));
+ break;
+ }
+
+ case 0x01: { /* BCLR.H */
+ DIP("BCLR.H w%d, w%d, w%d", wd, ws, wt);
+ tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
+ assign(t2,
+ binop(Iop_Shl16x8,
+ binop(Iop_64HLtoV128,
+ mkU64(tmp), mkU64(tmp)),
+ getWReg(wt)));
+ break;
+ }
+
+ case 0x02: { /* BCLR.W */
+ DIP("BCLR.W w%d, w%d, w%d", wd, ws, wt);
+ tmp |= (tmp << 32);
+ assign(t2,
+ binop(Iop_Shl32x4,
+ binop(Iop_64HLtoV128,
+ mkU64(tmp), mkU64(tmp)),
+ getWReg(wt)));
+ break;
+ }
+
+ case 0x03: { /* BCLR.D */
+ DIP("BCLR.D w%d, w%d, w%d", wd, ws, wt);
+ assign(t2,
+ binop(Iop_Shl64x2,
+ binop(Iop_64HLtoV128,
+ mkU64(tmp), mkU64(tmp)),
+ getWReg(wt)));
+ break;
+ }
}
- default:
- return -1;
- }
+ assign(t3,
+ binop(Iop_AndV128,
+ mkexpr(t1), unop(Iop_NotV128, mkexpr(t2))));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- return 0;
-}
+ case 0x04: { /* BSET.df */
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ ULong tmp = 1;
+ assign(t1, getWReg(ws));
-static Int msa_I8_branch(UInt cins, UChar wd, UChar ws) {
- IRTemp t1, t2, t3, t4;
- UShort operation;
- UChar i8;
+ switch (df) {
+ case 0x00: { /* BSET.B */
+ DIP("BSET.B w%d, w%d, w%d", wd, ws, wt);
+ tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
+ (tmp << 32) | (tmp << 24) | (tmp << 16) |
+ (tmp << 8);
+ assign(t2,
+ binop(Iop_Shl8x16,
+ binop(Iop_64HLtoV128,
+ mkU64(tmp), mkU64(tmp)),
+ getWReg(wt)));
+ break;
+ }
- operation = (cins >> 24) & 3;
- i8 = (cins & 0x00FF0000) >> 16;
- switch (operation) {
- case 0x00: { /* BMNZI.B */
- DIP("BMNZI.B w%d, w%d, %d", wd, ws, i8);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- t4 = newTemp(Ity_V128);
- ULong tmp = i8;
- tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
- (tmp << 32) | (tmp << 24) | (tmp << 16) |
- (tmp << 8);
- assign(t4, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
- assign(t1, binop(Iop_AndV128, getWReg(ws), mkexpr(t4)));
- assign(t2, binop(Iop_AndV128, getWReg(wd),
- unop(Iop_NotV128, mkexpr(t4))));
- assign(t3, binop(Iop_OrV128, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
+ case 0x01: { /* BSET.H */
+ DIP("BSET.H w%d, w%d, w%d", wd, ws, wt);
+ tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
+ assign(t2,
+ binop(Iop_Shl16x8,
+ binop(Iop_64HLtoV128,
+ mkU64(tmp), mkU64(tmp)),
+ getWReg(wt)));
+ break;
+ }
+
+ case 0x02: { /* BSET.W */
+ DIP("BSET.W w%d, w%d, w%d", wd, ws, wt);
+ tmp |= (tmp << 32);
+ assign(t2,
+ binop(Iop_Shl32x4,
+ binop(Iop_64HLtoV128,
+ mkU64(tmp), mkU64(tmp)),
+ getWReg(wt)));
+ break;
+ }
+
+ case 0x03: { /* BSET.D */
+ DIP("BSET.D w%d, w%d, w%d", wd, ws, wt);
+ assign(t2,
+ binop(Iop_Shl64x2,
+ binop(Iop_64HLtoV128,
+ mkU64(tmp), mkU64(tmp)),
+ getWReg(wt)));
+ break;
+ }
}
- case 0x01: { /* BMZI.B */
- DIP("BMZI.B w%d, w%d, %d", wd, ws, i8);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- t4 = newTemp(Ity_V128);
- ULong tmp = i8;
- tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
- (tmp << 32) | (tmp << 24) | (tmp << 16) |
- (tmp << 8);
- assign(t4, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
- assign(t1, binop(Iop_AndV128, getWReg(wd), mkexpr(t4)));
- assign(t2, binop(Iop_AndV128, getWReg(ws),
- unop(Iop_NotV128, mkexpr(t4))));
- assign(t3, binop(Iop_OrV128, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
+ assign(t3, binop(Iop_OrV128, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
+
+ case 0x05: { /* BNEG.df */
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ ULong tmp = 1;
+ assign(t1, getWReg(ws));
+
+ switch (df) {
+ case 0x00: { /* BNEG.B */
+ DIP("BNEG.B w%d, w%d, w%d", wd, ws, wt);
+ tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
+ (tmp << 32) | (tmp << 24) | (tmp << 16) |
+ (tmp << 8);
+ assign(t2,
+ binop(Iop_Shl8x16,
+ binop(Iop_64HLtoV128,
+ mkU64(tmp), mkU64(tmp)),
+ getWReg(wt)));
+ break;
+ }
+
+ case 0x01: { /* BNEG.H */
+ DIP("BNEG.H w%d, w%d, w%d", wd, ws, wt);
+ tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
+ assign(t2,
+ binop(Iop_Shl16x8,
+ binop(Iop_64HLtoV128,
+ mkU64(tmp), mkU64(tmp)),
+ getWReg(wt)));
+ break;
+ }
+
+ case 0x02: { /* BNEG.W */
+ DIP("BNEG.W w%d, w%d, w%d", wd, ws, wt);
+ tmp |= (tmp << 32);
+ assign(t2,
+ binop(Iop_Shl32x4,
+ binop(Iop_64HLtoV128,
+ mkU64(tmp), mkU64(tmp)),
+ getWReg(wt)));
+ break;
+ }
+
+ case 0x03: { /* BNEG.D */
+ DIP("BNEG.D w%d, w%d, w%d", wd, ws, wt);
+ assign(t2,
+ binop(Iop_Shl64x2,
+ binop(Iop_64HLtoV128,
+ mkU64(tmp), mkU64(tmp)),
+ getWReg(wt)));
+ break;
+ }
}
- case 0x02: { /* BSELI.B */
- DIP("BSELI.B w%d, w%d, %d", wd, ws, i8);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- t4 = newTemp(Ity_V128);
- ULong tmp = i8;
- tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
- (tmp << 32) | (tmp << 24) | (tmp << 16) |
- (tmp << 8);
- assign(t4, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
- assign(t1, binop(Iop_AndV128, getWReg(wd), mkexpr(t4)));
- assign(t2, binop(Iop_AndV128, getWReg(ws),
- unop(Iop_NotV128, getWReg(wd))));
- assign(t3, binop(Iop_OrV128, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
+ assign(t3, binop(Iop_XorV128, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
+
+ case 0x06: { /* BINSL.df */
+ switch (df) {
+ case 0x00: { /* BINSL.B */
+ DIP("BINSL.B w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ ULong tmp = 0x8080808080808080ULL;
+ assign(t1,
+ binop(Iop_Sar8x16,
+ binop(Iop_64HLtoV128,
+ mkU64(tmp), mkU64(tmp)),
+ getWReg(wt)));
+ assign(t2,
+ binop(Iop_AndV128,
+ unop(Iop_NotV128, mkexpr(t1)),
+ getWReg(wd)));
+ assign(t3,
+ binop(Iop_AndV128,
+ mkexpr(t1), getWReg(ws)));
+ putWReg(wd,
+ binop(Iop_OrV128,
+ mkexpr(t2), mkexpr(t3)));
+ break;
+ }
+
+ case 0x01: { /* BINSL.H */
+ DIP("BINSL.H w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ ULong tmp = 0x8000800080008000ULL;
+ assign(t1,
+ binop(Iop_Sar16x8,
+ binop(Iop_64HLtoV128,
+ mkU64(tmp), mkU64(tmp)),
+ getWReg(wt)));
+ assign(t2,
+ binop(Iop_AndV128,
+ unop(Iop_NotV128, mkexpr(t1)),
+ getWReg(wd)));
+ assign(t3,
+ binop(Iop_AndV128,
+ mkexpr(t1), getWReg(ws)));
+ putWReg(wd,
+ binop(Iop_OrV128,
+ mkexpr(t2), mkexpr(t3)));
+ break;
+ }
+
+ case 0x02: { /* BINSL.W */
+ DIP("BINSL.W w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ ULong tmp = 0x8000000080000000ULL;
+ assign(t1,
+ binop(Iop_Sar32x4,
+ binop(Iop_64HLtoV128,
+ mkU64(tmp), mkU64(tmp)),
+ getWReg(wt)));
+ assign(t2,
+ binop(Iop_AndV128,
+ unop(Iop_NotV128, mkexpr(t1)),
+ getWReg(wd)));
+ assign(t3,
+ binop(Iop_AndV128,
+ mkexpr(t1), getWReg(ws)));
+ putWReg(wd,
+ binop(Iop_OrV128,
+ mkexpr(t2), mkexpr(t3)));
+ break;
+ }
+
+ case 0x03: { /* BINSL.D */
+ DIP("BINSL.D w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ ULong tmp = 0x8000000000000000ULL;
+ assign(t1,
+ binop(Iop_Sar64x2,
+ binop(Iop_64HLtoV128,
+ mkU64(tmp), mkU64(tmp)),
+ getWReg(wt)));
+ assign(t2,
+ binop(Iop_AndV128,
+ unop(Iop_NotV128, mkexpr(t1)),
+ getWReg(wd)));
+ assign(t3,
+ binop(Iop_AndV128,
+ mkexpr(t1), getWReg(ws)));
+ putWReg(wd,
+ binop(Iop_OrV128,
+ mkexpr(t2), mkexpr(t3)));
+ break;
+ }
+
+ default:
+ return -1;
}
- default:
- return -1;
- }
+ break;
+ }
+
+ case 0x07: { /* BINSR.df */
+ switch (df) {
+ case 0x00: { /* BINSR.B */
+ DIP("BINSR.B w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ ULong tmp = 0xFEFEFEFEFEFEFEFEULL;
+ assign(t1,
+ binop(Iop_Shl8x16,
+ binop(Iop_64HLtoV128,
+ mkU64(tmp), mkU64(tmp)),
+ getWReg(wt)));
+ assign(t2,
+ binop(Iop_AndV128,
+ unop(Iop_NotV128, mkexpr(t1)),
+ getWReg(ws)));
+ assign(t3,
+ binop(Iop_AndV128,
+ mkexpr(t1), getWReg(wd)));
+ putWReg(wd,
+ binop(Iop_OrV128,
+ mkexpr(t2), mkexpr(t3)));
+ break;
+ }
- return 0;
-}
+ case 0x01: { /* BINSR.H */
+ DIP("BINSR.H w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ ULong tmp = 0xFFFEFFFEFFFEFFFEULL;
+ assign(t1,
+ binop(Iop_Shl16x8,
+ binop(Iop_64HLtoV128,
+ mkU64(tmp), mkU64(tmp)),
+ getWReg(wt)));
+ assign(t2,
+ binop(Iop_AndV128,
+ unop(Iop_NotV128, mkexpr(t1)),
+ getWReg(ws)));
+ assign(t3,
+ binop(Iop_AndV128,
+ mkexpr(t1), getWReg(wd)));
+ putWReg(wd,
+ binop(Iop_OrV128,
+ mkexpr(t2), mkexpr(t3)));
+ break;
+ }
-static Int msa_I8_shift(UInt cins, UChar wd, UChar ws) {
- IRTemp t1, t2;
- UShort operation;
- UChar i8;
+ case 0x02: { /* BINSR.W */
+ DIP("BINSR.W w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ ULong tmp = 0xFFFFFFFEFFFFFFFEULL;
+ assign(t1,
+ binop(Iop_Shl32x4,
+ binop(Iop_64HLtoV128,
+ mkU64(tmp), mkU64(tmp)),
+ getWReg(wt)));
+ assign(t2,
+ binop(Iop_AndV128,
+ unop(Iop_NotV128, mkexpr(t1)),
+ getWReg(ws)));
+ assign(t3,
+ binop(Iop_AndV128,
+ mkexpr(t1), getWReg(wd)));
+ putWReg(wd,
+ binop(Iop_OrV128,
+ mkexpr(t2), mkexpr(t3)));
+ break;
+ }
- operation = (cins >> 24) & 3;
- i8 = (cins & 0x00FF0000) >> 16;
- switch (operation) {
- case 0x00: { /* SHF.B */
- DIP("SHF.B w%d, w%d, %d", wd, ws, i8);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- assign(t1, getWReg(wd));
- assign(t2, getWReg(ws));
- Int i;
- IRTemp tmp[16];
-
- for (i = 0; i < 16; i++) {
- tmp[i] = newTemp(Ity_I8);
- assign(tmp[i],
- binop(Iop_GetElem8x16, mkexpr(t2),
- mkU8(i - (i % 4) +
- ((i8 >> (i % 4) * 2) & 0x03))));
- }
-
- putWReg(wd, binop(Iop_64HLtoV128,
- binop(Iop_32HLto64,
- binop(Iop_16HLto32,
- binop(Iop_8HLto16,
- mkexpr(tmp[15]),
- mkexpr(tmp[14])),
- binop(Iop_8HLto16,
- mkexpr(tmp[13]),
- mkexpr(tmp[12]))),
- binop(Iop_16HLto32,
- binop(Iop_8HLto16,
- mkexpr(tmp[11]),
- mkexpr(tmp[10])),
- binop(Iop_8HLto16,
- mkexpr(tmp[9]),
- mkexpr(tmp[8])))),
- binop(Iop_32HLto64,
- binop(Iop_16HLto32,
- binop(Iop_8HLto16,
- mkexpr(tmp[7]),
- mkexpr(tmp[6])),
- binop(Iop_8HLto16,
- mkexpr(tmp[5]),
- mkexpr(tmp[4]))),
- binop(Iop_16HLto32,
- binop(Iop_8HLto16,
- mkexpr(tmp[3]),
- mkexpr(tmp[2])),
- binop(Iop_8HLto16,
- mkexpr(tmp[1]),
- mkexpr(tmp[0]))))));
- break;
- }
+ case 0x03: { /* BINSR.D */
+ DIP("BINSR.D w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ ULong tmp = -2;
+ assign(t1,
+ binop(Iop_Shl64x2,
+ binop(Iop_64HLtoV128,
+ mkU64(tmp), mkU64(tmp)),
+ getWReg(wt)));
+ assign(t2,
+ binop(Iop_AndV128,
+ unop(Iop_NotV128, mkexpr(t1)),
+ getWReg(ws)));
+ assign(t3,
+ binop(Iop_AndV128,
+ mkexpr(t1), getWReg(wd)));
+ putWReg(wd,
+ binop(Iop_OrV128,
+ mkexpr(t2), mkexpr(t3)));
+ break;
+ }
- case 0x01: { /* SHF.H */
- DIP("SHF.H w%d, w%d, %d", wd, ws, i8);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- assign(t1, getWReg(wd));
- assign(t2, getWReg(ws));
- Int i;
- IRTemp tmp[8];
-
- for (i = 0; i < 8; i++) {
- tmp[i] = newTemp(Ity_I16);
- assign(tmp[i],
- binop(Iop_GetElem16x8, mkexpr(t2),
- mkU8(i - (i % 4) +
- ((i8 >> (i % 4) * 2) & 0x03))));
- }
-
- putWReg(wd, binop(Iop_64HLtoV128,
- binop(Iop_32HLto64,
- binop(Iop_16HLto32,
- mkexpr(tmp[7]), mkexpr(tmp[6])),
- binop(Iop_16HLto32,
- mkexpr(tmp[5]), mkexpr(tmp[4]))),
- binop(Iop_32HLto64,
- binop(Iop_16HLto32,
- mkexpr(tmp[3]), mkexpr(tmp[2])),
- binop(Iop_16HLto32,
- mkexpr(tmp[1]), mkexpr(tmp[0])))));
- break;
+ default:
+ return -1;
}
- case 0x02: { /* SHF.W */
- DIP("SHF.W w%d, w%d, %d", wd, ws, i8);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- assign(t1, getWReg(wd));
- assign(t2, getWReg(ws));
- Int i;
- IRTemp tmp[4];
-
- for (i = 0; i < 4; i++) {
- tmp[i] = newTemp(Ity_I32);
- assign(tmp[i],
- binop(Iop_GetElem32x4, mkexpr(t2),
- mkU8(i - (i % 4) +
- ((i8 >> (i % 4) * 2) & 0x03))));
- }
-
- putWReg(wd, binop(Iop_64HLtoV128,
- binop(Iop_32HLto64,
- mkexpr(tmp[3]), mkexpr(tmp[2])),
- binop(Iop_32HLto64,
- mkexpr(tmp[1]), mkexpr(tmp[0]))));
- break;
- }
+ break;
+ }
default:
return -1;
return 0;
}
-static Int msa_I5_06(UInt cins, UChar wd, UChar ws) { /* I5 (0x06) */
- IRTemp t1, t2, t3;
+static Int msa_3R_0E(UInt cins, UChar wd, UChar ws) /* 3R (0x0E) */
+{
+ IRTemp t1, t2, t3, t4;
UShort operation;
UChar df, wt;
wt = (cins & 0x001F0000) >> 16;
switch (operation) {
- case 0x00: { /* ADDVI */
- ULong tmp = wt;
+ case 0x00: { /* ADDV.df */
+ switch (df) {
+ case 0x00: { /* ADDV.B */
+ DIP("ADDV.B w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3, binop(Iop_Add8x16, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- switch (df) {
- case 0x00: { /* ADDVI.B */
- DIP("ADDVI.B w%d, w%d, %d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
- (tmp << 32) | (tmp << 24) | (tmp << 16) |
- (tmp << 8);
- assign(t1, getWReg(ws));
- assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
- assign(t3, binop(Iop_Add8x16, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ case 0x01: { /* ADDV.H */
+ DIP("ADDV.H w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3, binop(Iop_Add16x8, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- case 0x01: { /* ADDVI.H */
- DIP("ADDVI.H w%d, w%d, %d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
- assign(t1, getWReg(ws));
- assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
- assign(t3, binop(Iop_Add16x8, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ case 0x02: { /* ADDV.W */
+ DIP("ADDV.W w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3, binop(Iop_Add32x4, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- case 0x02: { /* ADDVI.W */
- DIP("ADDVI.W w%d, w%d, %d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- tmp |= (tmp << 32);
- assign(t1, getWReg(ws));
- assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
- assign(t3, binop(Iop_Add32x4, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ case 0x03: { /* ADDV.D */
+ DIP("ADDV.D w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3, binop(Iop_Add64x2, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- case 0x03: { /* ADDVI.D */
- DIP("ADDVI.D w%d, w%d, %d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
- assign(t3, binop(Iop_Add64x2, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ default:
+ return -1;
+ }
+
+ break;
+ }
+
+ case 0x01: { /* SUBV.df */
+ switch (df) {
+ case 0x00: { /* SUBV.B */
+ DIP("SUBV.B w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3, binop(Iop_Sub8x16, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
}
- break;
+ case 0x01: { /* SUBV.H */
+ DIP("SUBV.H w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3, binop(Iop_Sub16x8, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
+
+ case 0x02: { /* SUBV.W */
+ DIP("SUBV.W w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3, binop(Iop_Sub32x4, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
+
+ case 0x03: { /* SUBV.D */
+ DIP("SUBV.D w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3, binop(Iop_Sub64x2, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
+
+ default:
+ return -1;
}
- case 0x01: { /* SUBVI */
- ULong tmp = wt;
+ break;
+ }
- switch (df) {
- case 0x00: { /* SUBVI.B */
- DIP("SUBVI.B w%d, w%d, %d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
- (tmp << 32) | (tmp << 24) | (tmp << 16) |
- (tmp << 8);
- assign(t1, getWReg(ws));
- assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
- assign(t3, binop(Iop_Sub8x16, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ case 0x02: { /* MAX_S.df */
+ switch (df) {
+ case 0x00: { /* MAX_S.B */
+ DIP("MAX_S.B w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3, binop(Iop_Max8Sx16, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- case 0x01: { /* SUBVI.H */
- DIP("SUBVI.H w%d, w%d, %d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
- assign(t1, getWReg(ws));
- assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
- assign(t3, binop(Iop_Sub16x8, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ case 0x01: { /* MAX_S.H */
+ DIP("MAX_S.H w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3, binop(Iop_Max16Sx8, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- case 0x02: { /* SUBVI.W */
- DIP("SUBVI.W w%d, w%d, %d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- tmp |= (tmp << 32);
- assign(t1, getWReg(ws));
- assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
- assign(t3, binop(Iop_Sub32x4, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ case 0x02: { /* MAX_S.W */
+ DIP("MAX_S.W w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3, binop(Iop_Max32Sx4, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- case 0x03: { /* SUBVI.D */
- DIP("SUBVI.D w%d, w%d, %d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
- assign(t3, binop(Iop_Sub64x2, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ case 0x03: { /* MAX_S.D */
+ DIP("MAX_S.D w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3, binop(Iop_Max64Sx2, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
}
- break;
+ default:
+ return -1;
}
- case 0x02: { /* MAXI_S */
- ULong tmp = wt;
+ break;
+ }
- switch (df) {
- case 0x00: { /* MAXI_S.B */
- DIP("MAXI_S.B w%d, w%d, %d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- char stemp = ((int)tmp << 27) >> 27;
- tmp = (UChar)stemp;
- tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
- (tmp << 32) | (tmp << 24) | (tmp << 16) |
- (tmp << 8);
- assign(t1, getWReg(ws));
- assign(t2,binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
- assign(t3, binop(Iop_Max8Sx16, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ case 0x03: { /* MAX_U.df */
+ switch (df) {
+ case 0x00: { /* MAX_U.B */
+ DIP("MAX_U.B w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3, binop(Iop_Max8Ux16, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- case 0x01: { /* MAXI_S.H */
- DIP("MAXI_S.H w%d, w%d, %d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- short stemp = ((int)tmp << 27) >> 27;
- tmp = (UShort)stemp;
- tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
- assign(t1, getWReg(ws));
- assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
- assign(t3, binop(Iop_Max16Sx8, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ case 0x01: { /* MAX_U.H */
+ DIP("MAX_U.H w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3, binop(Iop_Max16Ux8, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- case 0x02: { /* MAXI_S.W */
- DIP("MAXI_S.W w%d, w%d, %d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- int stemp = ((int)tmp << 27) >> 27;
- tmp = (UInt)stemp;
- tmp |= (tmp << 32);
- assign(t1, getWReg(ws));
- assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
- assign(t3, binop(Iop_Max32Sx4, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ case 0x02: { /* MAX_U.W */
+ DIP("MAX_U.W w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3, binop(Iop_Max32Ux4, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- case 0x03: { /* MAXI_S.D */
- DIP("MAXI_S.D w%d, w%d, %d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- Long stemp = ((Long)tmp << 59) >> 59;
- tmp = stemp;
- assign(t1, getWReg(ws));
- assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
- assign(t3, binop(Iop_Max64Sx2, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ case 0x03: { /* MAX_U.D */
+ DIP("MAX_U.D w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3, binop(Iop_Max64Ux2, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
}
- break;
+ default:
+ return -1;
}
- case 0x03: { /* MAXI_U */
- ULong tmp = wt;
+ break;
+ }
- switch (df) {
- case 0x00: { /* MAXI_U.B */
- DIP("MAXI_U.B w%d, w%d, %d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
- (tmp << 32) | (tmp << 24) | (tmp << 16) |
- (tmp << 8);
- assign(t1, getWReg(ws));
- assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
- assign(t3, binop(Iop_Max8Ux16, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ case 0x04: { /* MIN_S.df */
+ switch (df) {
+ case 0x00: { /* MIN_S.B */
+ DIP("MIN_S.B w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3, binop(Iop_Min8Sx16, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- case 0x01: { /* MAXI_U.H */
- DIP("MAXI_U.H w%d, w%d, %d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
- assign(t1, getWReg(ws));
- assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
- assign(t3, binop(Iop_Max16Ux8, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ case 0x01: { /* MIN_S.H */
+ DIP("MIN_S.H w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3, binop(Iop_Min16Sx8, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- case 0x02: { /* MAXI_U.W */
- DIP("MAXI_U.W w%d, w%d, %d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- tmp |= (tmp << 32);
- assign(t1, getWReg(ws));
- assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
- assign(t3, binop(Iop_Max32Ux4, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ case 0x02: { /* MIN_S.W */
+ DIP("MIN_S.W w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3, binop(Iop_Min32Sx4, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- case 0x03: { /* MAXI_U.D */
- DIP("MAXI_U.D w%d, w%d, %d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
- assign(t3, binop(Iop_Max64Ux2, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ case 0x03: { /* MIN_S.D */
+ DIP("MIN_S.D w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3, binop(Iop_Min64Sx2, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
}
- break;
+ default:
+ return -1;
+ }
+
+ break;
+ }
+
+ case 0x05: { /* MIN_U.df */
+ switch (df) {
+ case 0x00: { /* MIN_U.B */
+ DIP("MIN_U.B w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3, binop(Iop_Min8Ux16, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
+
+ case 0x01: { /* MIN_U.H */
+ DIP("MIN_U.H w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3, binop(Iop_Min16Ux8, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
+
+ case 0x02: { /* MIN_U.W */
+ DIP("MIN_U.W w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3, binop(Iop_Min32Ux4, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
+
+ case 0x03: { /* MIN_U.D */
+ DIP("MIN_U.D w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3, binop(Iop_Min64Ux2, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
+
+ default:
+ return -1;
}
- case 0x04: { /* MINI_S */
- ULong tmp = wt;
+ break;
+ }
- switch (df) {
- case 0x00: { /* MINI_S.B */
- DIP("MINI_S.B w%d, w%d, %d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- char stemp = ((int)tmp << 27) >> 27;
- tmp = (UChar)stemp;
- tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
- (tmp << 32) | (tmp << 24) | (tmp << 16) |
- (tmp << 8);
- assign(t1, getWReg(ws));
- assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
- assign(t3, binop(Iop_Min8Sx16, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ case 0x06: { /* MAX_A.df */
+ switch (df) {
+ case 0x00: { /* MAX_A.B */
+ DIP("MAX_A.B w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ t4 = newTemp(Ity_V128);
+ assign(t1, unop(Iop_Abs8x16, getWReg(ws)));
+ assign(t2, unop(Iop_Abs8x16, getWReg(wt)));
+ assign(t4, binop(Iop_CmpGT8Ux16, mkexpr(t1), mkexpr(t2)));
+ assign(t3, binop(Iop_OrV128,
+ binop(Iop_AndV128,
+ mkexpr(t4),
+ getWReg(ws)),
+ binop(Iop_AndV128,
+ unop(Iop_NotV128, mkexpr(t4)),
+ getWReg(wt))));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- case 0x01: { /* MINI_S.H */
- DIP("MINI_S.H w%d, w%d, %d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- short stemp = ((int)tmp << 27) >> 27;
- tmp = (UShort)stemp;
- tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
- assign(t1, getWReg(ws));
- assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
- assign(t3, binop(Iop_Min16Sx8, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ case 0x01: { /* MAX_A.H */
+ DIP("MAX_A.H w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ t4 = newTemp(Ity_V128);
+ assign(t1, unop(Iop_Abs16x8, getWReg(ws)));
+ assign(t2, unop(Iop_Abs16x8, getWReg(wt)));
+ assign(t4, binop(Iop_CmpGT16Ux8, mkexpr(t1), mkexpr(t2)));
+ assign(t3, binop(Iop_OrV128,
+ binop(Iop_AndV128,
+ mkexpr(t4),
+ getWReg(ws)),
+ binop(Iop_AndV128,
+ unop(Iop_NotV128, mkexpr(t4)),
+ getWReg(wt))));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- case 0x02: { /* MINI_S.W */
- DIP("MINI_S.W w%d, w%d, %d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- int stemp = ((int)tmp << 27) >> 27;
- tmp = (UInt)stemp;
- tmp |= (tmp << 32);
- assign(t1, getWReg(ws));
- assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
- assign(t3, binop(Iop_Min32Sx4, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ case 0x02: { /* MAX_A.W */
+ DIP("MAX_A.W w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ t4 = newTemp(Ity_V128);
+ assign(t1, unop(Iop_Abs32x4, getWReg(ws)));
+ assign(t2, unop(Iop_Abs32x4, getWReg(wt)));
+ assign(t4, binop(Iop_CmpGT32Ux4, mkexpr(t1), mkexpr(t2)));
+ assign(t3, binop(Iop_OrV128,
+ binop(Iop_AndV128,
+ mkexpr(t4),
+ getWReg(ws)),
+ binop(Iop_AndV128,
+ unop(Iop_NotV128, mkexpr(t4)),
+ getWReg(wt))));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- case 0x03: { /* MINI_S.D */
- DIP("MINI_S.D w%d, w%d, %d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- Long stemp = ((Long)tmp << 59) >> 59;
- tmp = stemp;
- assign(t1, getWReg(ws));
- assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
- assign(t3, binop(Iop_Min64Sx2, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ case 0x03: { /* MAX_A.D */
+ DIP("MAX_A.D w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ t4 = newTemp(Ity_V128);
+ assign(t1, unop(Iop_Abs64x2, getWReg(ws)));
+ assign(t2, unop(Iop_Abs64x2, getWReg(wt)));
+ assign(t4, binop(Iop_CmpGT64Ux2, mkexpr(t1), mkexpr(t2)));
+ assign(t3, binop(Iop_OrV128,
+ binop(Iop_AndV128,
+ mkexpr(t4),
+ getWReg(ws)),
+ binop(Iop_AndV128,
+ unop(Iop_NotV128, mkexpr(t4)),
+ getWReg(wt))));
+ putWReg(wd, mkexpr(t3));
+ break;
}
- break;
+ default:
+ return -1;
}
- case 0x05: { /* MINI_U */
- ULong tmp = wt;
+ break;
+ }
- switch (df) {
- case 0x00: { /* MINI_U.B */
- DIP("MINI_U.B w%d, w%d, %d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
- (tmp << 32) | (tmp << 24) | (tmp << 16) |
- (tmp << 8);
- assign(t1, getWReg(ws));
- assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
- assign(t3, binop(Iop_Min8Ux16, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ case 0x07: { /* MIN_A.df */
+ switch (df) {
+ case 0x00: { /* MIN_A.B */
+ DIP("MIN_A.B w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ t4 = newTemp(Ity_V128);
+ assign(t1, unop(Iop_Abs8x16, getWReg(ws)));
+ assign(t2, unop(Iop_Abs8x16, getWReg(wt)));
+ assign(t4, binop(Iop_OrV128,
+ binop(Iop_CmpGT8Ux16,
+ mkexpr(t1), mkexpr(t2)),
+ binop(Iop_CmpEQ8x16,
+ mkexpr(t1), mkexpr(t2))));
+ assign(t3, binop(Iop_OrV128,
+ binop(Iop_AndV128,
+ mkexpr(t4),
+ getWReg(wt)),
+ binop(Iop_AndV128,
+ unop(Iop_NotV128, mkexpr(t4)),
+ getWReg(ws))));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- case 0x01: { /* MINI_U.H */
- DIP("MINI_U.H w%d, w%d, %d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
- assign(t1, getWReg(ws));
- assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
- assign(t3, binop(Iop_Min16Ux8, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ case 0x01: { /* MIN_A.H */
+ DIP("MIN_A.H w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ t4 = newTemp(Ity_V128);
+ assign(t1, unop(Iop_Abs16x8, getWReg(ws)));
+ assign(t2, unop(Iop_Abs16x8, getWReg(wt)));
+ assign(t4, binop(Iop_OrV128,
+ binop(Iop_CmpGT16Ux8,
+ mkexpr(t1), mkexpr(t2)),
+ binop(Iop_CmpEQ16x8,
+ mkexpr(t1), mkexpr(t2))));
+ assign(t3, binop(Iop_OrV128,
+ binop(Iop_AndV128,
+ mkexpr(t4),
+ getWReg(wt)),
+ binop(Iop_AndV128,
+ unop(Iop_NotV128, mkexpr(t4)),
+ getWReg(ws))));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- case 0x02: { /* MINI_U.W */
- DIP("MINI_U.W w%d, w%d, %d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- tmp |= (tmp << 32);
- assign(t1, getWReg(ws));
- assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
- assign(t3, binop(Iop_Min32Ux4, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ case 0x02: { /* MIN_A.W */
+ DIP("MIN_A.W w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ t4 = newTemp(Ity_V128);
+ assign(t1, unop(Iop_Abs32x4, getWReg(ws)));
+ assign(t2, unop(Iop_Abs32x4, getWReg(wt)));
+ assign(t4, binop(Iop_OrV128,
+ binop(Iop_CmpGT32Ux4,
+ mkexpr(t1), mkexpr(t2)),
+ binop(Iop_CmpEQ32x4,
+ mkexpr(t1), mkexpr(t2))));
+ assign(t3, binop(Iop_OrV128,
+ binop(Iop_AndV128,
+ mkexpr(t4),
+ getWReg(wt)),
+ binop(Iop_AndV128,
+ unop(Iop_NotV128, mkexpr(t4)),
+ getWReg(ws))));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- case 0x03: { /* MINI_U.D */
- DIP("MINI_U.D w%d, w%d, %d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
- assign(t3, binop(Iop_Min64Ux2, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ case 0x03: { /* MIN_A.D */
+ DIP("MIN_A.D w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ t4 = newTemp(Ity_V128);
+ assign(t1, unop(Iop_Abs64x2, getWReg(ws)));
+ assign(t2, unop(Iop_Abs64x2, getWReg(wt)));
+ assign(t4, binop(Iop_OrV128,
+ binop(Iop_CmpGT64Ux2,
+ mkexpr(t1), mkexpr(t2)),
+ binop(Iop_CmpEQ64x2,
+ mkexpr(t1), mkexpr(t2))));
+ assign(t3, binop(Iop_OrV128,
+ binop(Iop_AndV128,
+ mkexpr(t4),
+ getWReg(wt)),
+ binop(Iop_AndV128,
+ unop(Iop_NotV128, mkexpr(t4)),
+ getWReg(ws))));
+ putWReg(wd, mkexpr(t3));
+ break;
}
- break;
+ default:
+ return -1;
}
- default: {
- return -1;
- }
+ break;
+ }
+
+ default:
+ return -1;
}
return 0;
}
-static Int msa_I5_07(UInt cins, UChar wd, UChar ws) { /* I5 (0x07) / I10 */
+static Int msa_3R_0F(UInt cins, UChar wd, UChar ws) /* 3R (0x0F) */
+{
IRTemp t1, t2, t3;
UShort operation;
- UChar df, i5;
+ UChar df, wt;
operation = (cins & 0x03800000) >> 23;
df = (cins & 0x00600000) >> 21;
- i5 = (cins & 0x001F0000) >> 16;
+ wt = (cins & 0x001F0000) >> 16;
switch (operation) {
- case 0x00: {
- ULong tmp = i5;
-
- switch (df) {
- case 0x00: { /* CEQI.B */
- DIP("CEQI.B w%d, w%d, %d", wd, ws, i5);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- char stemp = ((int)tmp << 27) >> 27;
- tmp = (UChar)stemp;
- tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
- (tmp << 32) | (tmp << 24) | (tmp << 16) |
- (tmp << 8);
- assign(t1, getWReg(ws));
- assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
- assign(t3, binop(Iop_CmpEQ8x16, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
-
- case 0x01: { /* CEQI.H */
- DIP("CEQI.H w%d, w%d, %d", wd, ws, i5);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- short stemp = ((int)tmp << 27) >> 27;
- tmp = (UShort)stemp;
- tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
- assign(t1, getWReg(ws));
- assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
- assign(t3, binop(Iop_CmpEQ16x8, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
-
- case 0x02: { /* CEQI.W */
- DIP("CEQI.W w%d, w%d, %d", wd, ws, i5);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- int stemp = ((int)tmp << 27) >> 27;
- tmp = (UInt)stemp;
- tmp |= (tmp << 32);
- assign(t1, getWReg(ws));
- assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
- assign(t3, binop(Iop_CmpEQ32x4, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
-
- case 0x03: { /* CEQI.D */
- DIP("CEQI.D w%d, w%d, %d", wd, ws, i5);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- Long stemp = ((Long)tmp << 59) >> 59;
- tmp = stemp;
- assign(t1, getWReg(ws));
- assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
- assign(t3, binop(Iop_CmpEQ64x2, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ case 0x00: { /* CEQ.df */
+ switch (df) {
+ case 0x00: { /* CEQ.B */
+ DIP("CEQ.B w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3, binop(Iop_CmpEQ8x16, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
}
- break;
- }
-
- case 0x02: { /* CLTI_S.df */
- ULong tmp = i5;
-
- switch (df) {
- case 0x00: { /* CLTI_S.B */
- DIP("CLTI_S.B w%d, w%d, %d", wd, ws, i5);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- char stemp = ((int)tmp << 27) >> 27;
- tmp = (UChar)stemp;
- tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
- (tmp << 32) | (tmp << 24) | (tmp << 16) |
- (tmp << 8);
- assign(t1, getWReg(ws));
- assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
- assign(t3, binop(Iop_CmpGT8Sx16, mkexpr(t2), mkexpr(t1)));
- putWReg(wd, mkexpr(t3));
- break;
- }
-
- case 0x01: { /* CLTI_S.H */
- DIP("CLTI_S.H w%d, w%d, %d", wd, ws, i5);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- short stemp = ((int)tmp << 27) >> 27;
- tmp = (UShort)stemp;
- tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
- assign(t1, getWReg(ws));
- assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
- assign(t3, binop(Iop_CmpGT16Sx8, mkexpr(t2), mkexpr(t1)));
- putWReg(wd, mkexpr(t3));
- break;
- }
-
- case 0x02: { /* CLTI_S.W */
- DIP("CLTI_S.W w%d, w%d, %d", wd, ws, i5);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- int stemp = ((int)tmp << 27) >> 27;
- tmp = (UInt)stemp;
- tmp |= (tmp << 32);
- assign(t1, getWReg(ws));
- assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
- assign(t3, binop(Iop_CmpGT32Sx4, mkexpr(t2), mkexpr(t1)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ case 0x01: { /* CEQ.H */
+ DIP("CEQ.H w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3, binop(Iop_CmpEQ16x8, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- case 0x03: { /* CLTI_S.D */
- DIP("CLTI_S.D w%d, w%d, %d", wd, ws, i5);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- Long stemp = ((Long)tmp << 59) >> 59;
- tmp = stemp;
- assign(t1, getWReg(ws));
- assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
- assign(t3, binop(Iop_CmpGT64Sx2, mkexpr(t2), mkexpr(t1)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ case 0x02: { /* CEQ.W */
+ DIP("CEQ.W w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3, binop(Iop_CmpEQ32x4, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- default:
- return -1;
+ case 0x03: { /* CEQ.D */
+ DIP("CEQ.D w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3, binop(Iop_CmpEQ64x2, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
}
- break;
+ default:
+ return -1;
}
- case 0x03: { /* CLTI_U.df */
- ULong tmp = i5;
-
- switch (df) {
- case 0x00: { /* CLTI_U.B */
- DIP("CLTI_U.B w%d, w%d, %d", wd, ws, i5);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
- (tmp << 32) | (tmp << 24) | (tmp << 16) |
- (tmp << 8);
- assign(t1, getWReg(ws));
- assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
- assign(t3, binop(Iop_CmpGT8Ux16, mkexpr(t2), mkexpr(t1)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ break;
+ }
- case 0x01: { /* CLTI_U.H */
- DIP("CLTI_U.H w%d, w%d, %d", wd, ws, i5);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
- assign(t1, getWReg(ws));
- assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
- assign(t3, binop(Iop_CmpGT16Ux8, mkexpr(t2), mkexpr(t1)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ case 0x02: { /* CLT_S.df */
+ switch (df) {
+ case 0x00: { /* CLT_S.B */
+ DIP("CLT_S.B w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3, binop(Iop_CmpGT8Sx16, mkexpr(t2), mkexpr(t1)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- case 0x02: { /* CLTI_U.W */
- DIP("CLTI_U.W w%d, w%d, %d", wd, ws, i5);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- tmp |= (tmp << 32);
- assign(t1, getWReg(ws));
- assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
- assign(t3, binop(Iop_CmpGT32Ux4, mkexpr(t2), mkexpr(t1)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ case 0x01: { /* CLT_S.H */
+ DIP("CLT_S.H w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3, binop(Iop_CmpGT16Sx8, mkexpr(t2), mkexpr(t1)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- case 0x03: { /* CLTI_U.D */
- DIP("CLTI_U.D w%d, w%d, %d", wd, ws, i5);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
- assign(t3, binop(Iop_CmpGT64Ux2, mkexpr(t2), mkexpr(t1)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ case 0x02: { /* CLT_S.W */
+ DIP("CLT_S.W w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3, binop(Iop_CmpGT32Sx4, mkexpr(t2), mkexpr(t1)));
+ putWReg(wd, mkexpr(t3));
+ break;
}
- break;
- }
+ case 0x03: { /* CLT_S.D */
+ DIP("CLT_S.D w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3, binop(Iop_CmpGT64Sx2, mkexpr(t2), mkexpr(t1)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- case 0x04: { /* CLEI_S.df */
- ULong tmp = i5;
+ default:
+ return -1;
+ }
- switch (df) {
- case 0x00: { /* CLEI_S.B */
- DIP("CLEI_S.B w%d, w%d, %d", wd, ws, i5);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- char stemp = ((int)tmp << 27) >> 27;
- tmp = (UChar)stemp;
- tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
- (tmp << 32) | (tmp << 24) | (tmp << 16) |
- (tmp << 8);
- assign(t1, getWReg(ws));
- assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
- assign(t3, binop(Iop_OrV128, binop(Iop_CmpGT8Sx16,
- mkexpr(t2), mkexpr(t1)),
- binop(Iop_CmpEQ8x16,
- mkexpr(t1), mkexpr(t2))));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ break;
+ }
- case 0x01: { /* CLEI_S.H */
- DIP("CLEI_S.H w%d, w%d, %d", wd, ws, i5);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- short stemp = ((int)tmp << 27) >> 27;
- tmp = (UShort)stemp;
- tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
- assign(t1, getWReg(ws));
- assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
- assign(t3, binop(Iop_OrV128, binop(Iop_CmpGT16Sx8,
- mkexpr(t2), mkexpr(t1)),
- binop(Iop_CmpEQ16x8,
- mkexpr(t1), mkexpr(t2))));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ case 0x03: { /* CLT_U.df */
+ switch (df) {
+ case 0x00: { /* CLT_U.B */
+ DIP("CLT_U.B w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3, binop(Iop_CmpGT8Ux16, mkexpr(t2), mkexpr(t1)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- case 0x02: { /* CLEI_S.W */
- DIP("CLEI_S.W w%d, w%d, %d", wd, ws, i5);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- int stemp = ((int)tmp << 27) >> 27;
- tmp = (UInt)stemp;
- tmp |= (tmp << 32);
- assign(t1, getWReg(ws));
- assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
- assign(t3, binop(Iop_OrV128,
- binop(Iop_CmpGT32Sx4,
- mkexpr(t2), mkexpr(t1)),
- binop(Iop_CmpEQ32x4,
- mkexpr(t1), mkexpr(t2))));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ case 0x01: { /* CLT_U.H */
+ DIP("CLT_U.H w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3, binop(Iop_CmpGT16Ux8, mkexpr(t2), mkexpr(t1)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- case 0x03: { /* CLEI_S.D */
- DIP("CLEI_S.D w%d, w%d, %d", wd, ws, i5);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- Long stemp = ((Long)tmp << 59) >> 59;
- tmp = stemp;
- assign(t1, getWReg(ws));
- assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
- assign(t3, binop(Iop_OrV128,
- binop(Iop_CmpGT64Sx2,
- mkexpr(t2), mkexpr(t1)),
- binop(Iop_CmpEQ64x2,
- mkexpr(t1), mkexpr(t2))));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ case 0x02: { /* CLT_U.W */
+ DIP("CLT_U.W w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3, binop(Iop_CmpGT32Ux4, mkexpr(t2), mkexpr(t1)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- default:
- return -1;
+ case 0x03: { /* CLT_U.D */
+ DIP("CLT_U.D w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3, binop(Iop_CmpGT64Ux2, mkexpr(t2), mkexpr(t1)));
+ putWReg(wd, mkexpr(t3));
+ break;
}
- break;
+ default:
+ return -1;
}
- case 0x05: { /* CLEI_U.df */
- ULong tmp = i5;
+ break;
+ }
- switch (df) {
- case 0x00: { /* CLEI_U.B */
- DIP("CLEI_U.B w%d, w%d, %d", wd, ws, i5);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
- (tmp << 32) | (tmp << 24) | (tmp << 16) |
- (tmp << 8);
- assign(t1, getWReg(ws));
- assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
- assign(t3, binop(Iop_OrV128,
- binop(Iop_CmpGT8Ux16,
- mkexpr(t2), mkexpr(t1)),
- binop(Iop_CmpEQ8x16,
- mkexpr(t1), mkexpr(t2))));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ case 0x04: { /* CLE_S.df */
+ switch (df) {
+ case 0x00: { /* CLE_S.B */
+ DIP("CLE_S.B w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3, binop(Iop_OrV128,
+ binop(Iop_CmpGT8Sx16,
+ mkexpr(t2), mkexpr(t1)),
+ binop(Iop_CmpEQ8x16,
+ mkexpr(t1), mkexpr(t2))));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- case 0x01: { /* CLEI_U.H */
- DIP("CLEI_U.H w%d, w%d, %d", wd, ws, i5);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
- assign(t1, getWReg(ws));
- assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
- assign(t3, binop(Iop_OrV128,
- binop(Iop_CmpGT16Ux8,
- mkexpr(t2), mkexpr(t1)),
- binop(Iop_CmpEQ16x8,
- mkexpr(t1), mkexpr(t2))));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ case 0x01: { /* CLE_S.H */
+ DIP("CLE_S.H w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3, binop(Iop_OrV128,
+ binop(Iop_CmpGT16Sx8,
+ mkexpr(t2), mkexpr(t1)),
+ binop(Iop_CmpEQ16x8,
+ mkexpr(t1), mkexpr(t2))));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- case 0x02: { /* CLEI_U.W */
- DIP("CLEI_U.W w%d, w%d, %d", wd, ws, i5);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- tmp |= (tmp << 32);
- assign(t1, getWReg(ws));
- assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
- assign(t3, binop(Iop_OrV128,
- binop(Iop_CmpGT32Ux4,
- mkexpr(t2), mkexpr(t1)),
- binop(Iop_CmpEQ32x4,
- mkexpr(t1), mkexpr(t2))));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ case 0x02: { /* CLE_S.W */
+ DIP("CLE_S.W w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3, binop(Iop_OrV128,
+ binop(Iop_CmpGT32Sx4,
+ mkexpr(t2), mkexpr(t1)),
+ binop(Iop_CmpEQ32x4,
+ mkexpr(t1), mkexpr(t2))));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- case 0x03: { /* CLEI_U.D */
- DIP("CLEI_U.D w%d, w%d, %d", wd, ws, i5);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
- assign(t3, binop(Iop_OrV128,
- binop(Iop_CmpGT64Ux2,
- mkexpr(t2), mkexpr(t1)),
- binop(Iop_CmpEQ64x2,
- mkexpr(t1), mkexpr(t2))));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ case 0x03: { /* CLE_S.D */
+ DIP("CLE_S.D w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3, binop(Iop_OrV128,
+ binop(Iop_CmpGT64Sx2,
+ mkexpr(t2), mkexpr(t1)),
+ binop(Iop_CmpEQ64x2,
+ mkexpr(t1), mkexpr(t2))));
+ putWReg(wd, mkexpr(t3));
+ break;
}
- break;
+ default:
+ return -1;
}
- case 0x06: { /* LDI.df */
- ULong tmp;
- UShort s10;
- s10 = (cins & 0x001FF800) >> 11;
- switch (df) {
- case 0x00: /* LDI.B */
- DIP("LDI.B w%d, %d", wd, s10);
- tmp = s10 & 0xFFl;
- tmp = tmp | (tmp << 8) | (tmp << 16) | (tmp << 24)
- | (tmp << 32) | (tmp << 40) | (tmp << 48) |
- (tmp << 56);
- break;
+ break;
+ }
- case 0x01: /* LDI.H */
- DIP("LDI.H w%d, %d", wd, s10);
- tmp = extend_s_10to16(s10);
- tmp = tmp | (tmp << 16) | (tmp << 32) | (tmp << 48);
- break;
+ case 0x05: { /* CLE_U.df */
+ switch (df) {
+ case 0x00: { /* CLE_U.B */
+ DIP("CLE_U.B w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3, binop(Iop_OrV128,
+ binop(Iop_CmpGT8Ux16,
+ mkexpr(t2), mkexpr(t1)),
+ binop(Iop_CmpEQ8x16,
+ mkexpr(t1), mkexpr(t2))));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- case 0x02: /* LDI.W */
- DIP("LDI.W w%d, %d", wd, s10);
- tmp = extend_s_10to32(s10);
- tmp = tmp | (tmp << 32);
- break;
+ case 0x01: { /* CLE_U.H */
+ DIP("CLE_U.H w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3, binop(Iop_OrV128,
+ binop(Iop_CmpGT16Ux8,
+ mkexpr(t2), mkexpr(t1)),
+ binop(Iop_CmpEQ16x8,
+ mkexpr(t1), mkexpr(t2))));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- case 0x03: /* LDI.D */
- DIP("LDI.D w%d, %d", wd, s10);
- tmp = extend_s_10to64(s10);
- break;
+ case 0x02: { /* CLE_U.W */
+ DIP("CLE_U.W w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3, binop(Iop_OrV128,
+ binop(Iop_CmpGT32Ux4,
+ mkexpr(t2), mkexpr(t1)),
+ binop(Iop_CmpEQ32x4,
+ mkexpr(t1), mkexpr(t2))));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- default:
- return -1;
+ case 0x03: { /* CLE_U.D */
+ DIP("CLE_U.D w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3,
+ binop(Iop_OrV128,
+ binop(Iop_CmpGT64Ux2,
+ mkexpr(t2), mkexpr(t1)),
+ binop(Iop_CmpEQ64x2,
+ mkexpr(t1), mkexpr(t2))));
+ putWReg(wd, mkexpr(t3));
+ break;
}
- putWReg(wd, binop(Iop_64HLtoV128, mkU64(tmp), mkU64(tmp)));
- break;
+ default:
+ return -1;
}
+ break;
+ }
+
default:
return -1;
}
return 0;
}
-static Int msa_BIT_09(UInt cins, UChar wd, UChar ws) { /* BIT (0x09) */
- IRTemp t1, t2, t3;
+static Int msa_3R_10(UInt cins, UChar wd, UChar ws) /* 3R (0x10) */
+{
+ IRTemp t1, t2, t3, t4;
UShort operation;
- UChar df, m;
+ UChar df, wt;
operation = (cins & 0x03800000) >> 23;
- df = (cins & 0x007F0000) >> 16;
-
- if ((df & 0x70) == 0x70) { // 111mmmm; b
- m = df & 0x07;
- df = 0;
- } else if ((df & 0x60) == 0x60) { // 110mmmm; h
- m = df & 0x0F;
- df = 1;
- } else if ((df & 0x40) == 0x40) { // 10mmmmm; w
- m = df & 0x1F;
- df = 2;
- } else if ((df & 0x00) == 0x00) { // 0mmmmmm; d
- m = df & 0x3F;
- df = 3;
- }
+ df = (cins & 0x00600000) >> 21;
+ wt = (cins & 0x001F0000) >> 16;
switch (operation) {
- case 0x00: { /* SLLI.df */
- switch (df) {
- case 0x00: { /* SLLI.B */
- DIP("SLLI.B w%d, w%d, %d", wd, ws, m);
- putWReg(wd, binop(Iop_ShlN8x16, getWReg(ws), mkU8(m)));
- break;
- }
+ case 0x00: { /* ADD_A.df */
+ switch (df) {
+ case 0x00: { /* ADD_A.B */
+ DIP("ADD_A.B w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, unop(Iop_Abs8x16, getWReg(ws)));
+ assign(t2, unop(Iop_Abs8x16, getWReg(wt)));
+ assign(t3, binop(Iop_Add8x16, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- case 0x01: { /* SLLI.H */
- DIP("SLLI.H w%d, w%d, %d", wd, ws, m);
- putWReg(wd, binop(Iop_ShlN16x8, getWReg(ws), mkU8(m)));
- break;
- }
+ case 0x01: { /* ADD_A.H */
+ DIP("ADD_A.H w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, unop(Iop_Abs16x8, getWReg(ws)));
+ assign(t2, unop(Iop_Abs16x8, getWReg(wt)));
+ assign(t3, binop(Iop_Add16x8, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- case 0x02: { /* SLLI.W */
- DIP("SLLI.W w%d, w%d, %d", wd, ws, m);
- putWReg(wd, binop(Iop_ShlN32x4, getWReg(ws), mkU8(m)));
- break;
- }
+ case 0x02: { /* ADD_A.W */
+ DIP("ADD_A.W w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, unop(Iop_Abs32x4, getWReg(ws)));
+ assign(t2, unop(Iop_Abs32x4, getWReg(wt)));
+ assign(t3, binop(Iop_Add32x4, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- case 0x03: { /* SLLI.D */
- DIP("SLLI.D w%d, w%d, %d", wd, ws, m);
- putWReg(wd, binop(Iop_ShlN64x2, getWReg(ws), mkU8(m)));
- break;
- }
+ case 0x03: { /* ADD_A.D */
+ DIP("ADD_A.D w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, unop(Iop_Abs64x2, getWReg(ws)));
+ assign(t2, unop(Iop_Abs64x2, getWReg(wt)));
+ assign(t3, binop(Iop_Add64x2, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
}
- break;
+ default:
+ return -1;
}
- case 0x01: { /* SRAI.df */
- switch (df) {
- case 0x00: { /* SRAI.B */
- DIP("SRAI.B w%d, w%d, %d", wd, ws, m);
- putWReg(wd, binop(Iop_SarN8x16, getWReg(ws), mkU8(m)));
- break;
- }
+ break;
+ }
- case 0x01: { /* SRAI.H */
- DIP("SRAI.H w%d, w%d, %d", wd, ws, m);
- putWReg(wd, binop(Iop_SarN16x8, getWReg(ws), mkU8(m)));
- break;
- }
+ case 0x01: { /* ADDS_A.df */
+ switch (df) {
+ case 0x00: { /* ADDS_A.B */
+ DIP("ADDS_A.B w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ t4 = newTemp(Ity_V128);
+ assign(t1, unop(Iop_Abs8x16, getWReg(ws)));
+ assign(t2, unop(Iop_Abs8x16, getWReg(wt)));
+ assign(t3, binop(Iop_SarN8x16,
+ binop(Iop_AndV128,
+ mkexpr(t1),
+ getWReg(ws)),
+ mkU8(7)));
+ assign(t4, binop(Iop_SarN8x16,
+ binop(Iop_AndV128,
+ mkexpr(t2),
+ getWReg(wt)),
+ mkU8(7)));
+ putWReg(wd, binop(Iop_QAdd8Sx16,
+ binop(Iop_OrV128,
+ binop(Iop_AndV128,
+ unop(Iop_NotV128,
+ mkexpr(t3)),
+ mkexpr(t1)),
+ binop(Iop_AndV128,
+ unop(Iop_NotV128,
+ mkexpr(t1)),
+ mkexpr(t3))),
+ binop(Iop_OrV128,
+ binop(Iop_AndV128,
+ unop(Iop_NotV128,
+ mkexpr(t4)),
+ mkexpr(t2)),
+ binop(Iop_AndV128,
+ unop(Iop_NotV128,
+ mkexpr(t2)),
+ mkexpr(t4)))));
+ break;
+ }
- case 0x02: { /* SRAI.W */
- DIP("SRAI.W w%d, w%d, %d", wd, ws, m);
- putWReg(wd, binop(Iop_SarN32x4, getWReg(ws), mkU8(m)));
- break;
- }
+ case 0x01: { /* ADDS_A.H */
+ DIP("ADDS_A.H w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ t4 = newTemp(Ity_V128);
+ assign(t1, unop(Iop_Abs16x8, getWReg(ws)));
+ assign(t2, unop(Iop_Abs16x8, getWReg(wt)));
+ assign(t3, binop(Iop_SarN16x8,
+ binop(Iop_AndV128,
+ mkexpr(t1),
+ getWReg(ws)),
+ mkU8(15)));
+ assign(t4, binop(Iop_SarN16x8,
+ binop(Iop_AndV128,
+ mkexpr(t2),
+ getWReg(wt)),
+ mkU8(15)));
+ putWReg(wd, binop(Iop_QAdd16Sx8,
+ binop(Iop_OrV128,
+ binop(Iop_AndV128,
+ unop(Iop_NotV128,
+ mkexpr(t3)),
+ mkexpr(t1)),
+ binop(Iop_AndV128,
+ unop(Iop_NotV128,
+ mkexpr(t1)),
+ mkexpr(t3))),
+ binop(Iop_OrV128,
+ binop(Iop_AndV128,
+ unop(Iop_NotV128,
+ mkexpr(t4)),
+ mkexpr(t2)),
+ binop(Iop_AndV128,
+ unop(Iop_NotV128,
+ mkexpr(t2)),
+ mkexpr(t4)))));
+ break;
+ }
- case 0x03: { /* SRAI.D */
- DIP("SRAI.D w%d, w%d, %d", wd, ws, m);
- putWReg(wd, binop(Iop_SarN64x2, getWReg(ws), mkU8(m)));
- break;
- }
+ case 0x02: { /* ADDS_A.W */
+ DIP("ADDS_A.W w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ t4 = newTemp(Ity_V128);
+ assign(t1, unop(Iop_Abs32x4, getWReg(ws)));
+ assign(t2, unop(Iop_Abs32x4, getWReg(wt)));
+ assign(t3, binop(Iop_SarN32x4,
+ binop(Iop_AndV128,
+ mkexpr(t1),
+ getWReg(ws)),
+ mkU8(31)));
+ assign(t4, binop(Iop_SarN32x4,
+ binop(Iop_AndV128,
+ mkexpr(t2),
+ getWReg(wt)),
+ mkU8(31)));
+ putWReg(wd, binop(Iop_QAdd32Sx4,
+ binop(Iop_OrV128,
+ binop(Iop_AndV128,
+ unop(Iop_NotV128,
+ mkexpr(t3)),
+ mkexpr(t1)),
+ binop(Iop_AndV128,
+ unop(Iop_NotV128,
+ mkexpr(t1)),
+ mkexpr(t3))),
+ binop(Iop_OrV128,
+ binop(Iop_AndV128,
+ unop(Iop_NotV128,
+ mkexpr(t4)),
+ mkexpr(t2)),
+ binop(Iop_AndV128,
+ unop(Iop_NotV128,
+ mkexpr(t2)),
+ mkexpr(t4)))));
+ break;
}
- break;
+ case 0x03: { /* ADDS_A.D */
+ DIP("ADDS_A.D w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ t4 = newTemp(Ity_V128);
+ assign(t1, unop(Iop_Abs64x2, getWReg(ws)));
+ assign(t2, unop(Iop_Abs64x2, getWReg(wt)));
+ assign(t3, binop(Iop_SarN64x2,
+ binop(Iop_AndV128,
+ mkexpr(t1),
+ getWReg(ws)),
+ mkU8(63)));
+ assign(t4, binop(Iop_SarN64x2,
+ binop(Iop_AndV128,
+ mkexpr(t2),
+ getWReg(wt)),
+ mkU8(63)));
+ putWReg(wd,
+ binop(Iop_QAdd64Sx2,
+ binop(Iop_OrV128,
+ binop(Iop_AndV128,
+ unop(Iop_NotV128,
+ mkexpr(t3)),
+ mkexpr(t1)),
+ binop(Iop_AndV128,
+ unop(Iop_NotV128,
+ mkexpr(t1)),
+ mkexpr(t3))),
+ binop(Iop_OrV128,
+ binop(Iop_AndV128,
+ unop(Iop_NotV128,
+ mkexpr(t4)),
+ mkexpr(t2)),
+ binop(Iop_AndV128,
+ unop(Iop_NotV128,
+ mkexpr(t2)),
+ mkexpr(t4)))));
+ break;
+ }
+
+ default:
+ return -1;
}
- case 0x02: { /* SRLI.df */
- switch (df) {
- case 0x00: { /* SRLI.B */
- DIP("SRLI.B w%d, w%d, %d", wd, ws, m);
- putWReg(wd, binop(Iop_ShrN8x16, getWReg(ws), mkU8(m)));
- break;
- }
+ break;
+ }
- case 0x01: { /* SRLI.H */
- DIP("SRLI.H w%d, w%d, %d", wd, ws, m);
- putWReg(wd, binop(Iop_ShrN16x8, getWReg(ws), mkU8(m)));
- break;
- }
+ case 0x02: { /* ADDS_S.df */
+ switch (df) {
+ case 0x00: { /* ADDS_S.B */
+ DIP("ADDS_S.B w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3, binop(Iop_QAdd8Sx16, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- case 0x02: { /* SRLI.W */
- DIP("SRLI.W w%d, w%d, %d", wd, ws, m);
- putWReg(wd, binop(Iop_ShrN32x4, getWReg(ws), mkU8(m)));
- break;
- }
+ case 0x01: { /* ADDS_S.H */
+ DIP("ADDS_S.H w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3, binop(Iop_QAdd16Sx8, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- case 0x03: { /* SRLI.D */
- DIP("SRLI.D w%d, w%d, %d", wd, ws, m);
- putWReg(wd, binop(Iop_ShrN64x2, getWReg(ws), mkU8(m)));
- break;
- }
+ case 0x02: { /* ADDS_S.W */
+ DIP("ADDS_S.W w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3, binop(Iop_QAdd32Sx4, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
}
- break;
- }
+ case 0x03: { /* ADDS_S.D */
+ DIP("ADDS_S.D w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3, binop(Iop_QAdd64Sx2, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- case 0x03: { /* BCLRI.df */
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- ULong tmp = 1;
- assign(t1, getWReg(ws));
+ default:
+ return -1;
+ }
- switch (df) {
- case 0x00: { /* BCLRI.B */
- DIP("BCLRI.B w%d, w%d, %d", wd, ws, m);
- tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
- (tmp << 32) | (tmp << 24) | (tmp << 16) |
- (tmp << 8);
- assign(t2, binop(Iop_ShlN8x16,
- binop(Iop_64HLtoV128,
- mkU64(tmp), mkU64(tmp)),mkU8(m)));
- break;
- }
+ break;
+ }
- case 0x01: { /* BCLRI.H */
- DIP("BCLRI.H w%d, w%d, %d", wd, ws, m);
- tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
- assign(t2, binop(Iop_ShlN16x8,
- binop(Iop_64HLtoV128,
- mkU64(tmp), mkU64(tmp)), mkU8(m)));
- break;
- }
+ case 0x03: { /* ADDS_U.df */
+ switch (df) {
+ case 0x00: { /* ADDS_U.B */
+ DIP("ADDS_U.B w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3, binop(Iop_QAdd8Ux16, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- case 0x02: { /* BCLRI.W */
- DIP("BCLRI.W w%d, w%d, %d", wd, ws, m);
- tmp |= (tmp << 32);
- assign(t2, binop(Iop_ShlN32x4,
- binop(Iop_64HLtoV128,
- mkU64(tmp), mkU64(tmp)), mkU8(m)));
- break;
- }
+ case 0x01: { /* ADDS_U.H */
+ DIP("ADDS_U.H w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3, binop(Iop_QAdd16Ux8, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- case 0x03: { /* BCLRI.D */
- DIP("BCLRI.D w%d, w%d, %d", wd, ws, m);
- assign(t2, binop(Iop_ShlN64x2,
- binop(Iop_64HLtoV128,
- mkU64(tmp), mkU64(tmp)), mkU8(m)));
- break;
- }
+ case 0x02: { /* ADDS_U.W */
+ DIP("ADDS_U.W w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3, binop(Iop_QAdd32Ux4, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
}
- assign(t3, binop(Iop_AndV128,
- mkexpr(t1), unop(Iop_NotV128, mkexpr(t2))));
- putWReg(wd, mkexpr(t3));
- break;
+ case 0x03: { /* ADDS_U.D */
+ DIP("ADDS_U.D w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3, binop(Iop_QAdd64Ux2, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
+
+ default:
+ return -1;
}
- case 0x04: { /* BSETI */
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- ULong tmp = 1;
- assign(t1, getWReg(ws));
+ break;
+ }
- switch (df) {
- case 0x00: { /* BSETI.B */
- DIP("BSETI.B w%d, w%d, %d", wd, ws, m);
- tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
- (tmp << 32) | (tmp << 24) | (tmp << 16) |
- (tmp << 8);
- assign(t2, binop(Iop_ShlN8x16,
- binop(Iop_64HLtoV128,
- mkU64(tmp), mkU64(tmp)), mkU8(m)));
- break;
- }
+ case 0x04: { /* AVE_S.df */
+ switch (df) {
+ case 0x00: { /* AVE_S.B */
+ DIP("AVE_S.B w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3, binop(Iop_Add8x16,
+ binop(Iop_Add8x16,
+ binop(Iop_SarN8x16,
+ mkexpr(t1), mkU8(1)),
+ binop(Iop_SarN8x16,
+ mkexpr(t2), mkU8(1))),
+ binop(Iop_ShrN8x16,
+ binop(Iop_ShlN8x16,
+ binop(Iop_AndV128,
+ mkexpr(t1),
+ mkexpr(t2)),
+ mkU8(7)),
+ mkU8(7))));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- case 0x01: { /* BSETI.H */
- DIP("BSETI.H w%d, w%d, %d", wd, ws, m);
- tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
- assign(t2, binop(Iop_ShlN16x8,
- binop(Iop_64HLtoV128,
- mkU64(tmp), mkU64(tmp)), mkU8(m)));
- break;
- }
+ case 0x01: { /* AVE_S.H */
+ DIP("AVE_S.H w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3,
+ binop(Iop_Add16x8,
+ binop(Iop_Add16x8,
+ binop(Iop_SarN16x8,
+ mkexpr(t1), mkU8(1)),
+ binop(Iop_SarN16x8,
+ mkexpr(t2), mkU8(1))),
+ binop(Iop_ShrN16x8,
+ binop(Iop_ShlN16x8,
+ binop(Iop_AndV128,
+ mkexpr(t1),
+ mkexpr(t2)),
+ mkU8(15)),
+ mkU8(15))));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- case 0x02: { /* BSETI.W */
- DIP("BSETI.W w%d, w%d, %d", wd, ws, m);
- tmp |= (tmp << 32);
- assign(t2, binop(Iop_ShlN32x4,
- binop(Iop_64HLtoV128,
- mkU64(tmp), mkU64(tmp)), mkU8(m)));
- break;
- }
+ case 0x02: { /* AVE_S.W */
+ DIP("AVE_S.W w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3, binop(Iop_Add32x4,
+ binop(Iop_Add32x4,
+ binop(Iop_SarN32x4,
+ mkexpr(t1), mkU8(1)),
+ binop(Iop_SarN32x4,
+ mkexpr(t2), mkU8(1))),
+ binop(Iop_ShrN32x4,
+ binop(Iop_ShlN32x4,
+ binop(Iop_AndV128,
+ mkexpr(t1),
+ mkexpr(t2)),
+ mkU8(31)),
+ mkU8(31))));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- case 0x03: { /* BSETI.D */
- DIP("BSETI.D w%d, w%d, %d", wd, ws, m);
- assign(t2, binop(Iop_ShlN64x2,
- binop(Iop_64HLtoV128,
- mkU64(tmp), mkU64(tmp)), mkU8(m)));
- break;
- }
+ case 0x03: { /* AVE_S.D */
+ DIP("AVE_S.D w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3, binop(Iop_Add64x2,
+ binop(Iop_Add64x2,
+ binop(Iop_SarN64x2,
+ mkexpr(t1), mkU8(1)),
+ binop(Iop_SarN64x2,
+ mkexpr(t2), mkU8(1))),
+ binop(Iop_ShrN64x2,
+ binop(Iop_ShlN64x2,
+ binop(Iop_AndV128,
+ mkexpr(t1),
+ mkexpr(t2)),
+ mkU8(63)),
+ mkU8(63))));
+ putWReg(wd, mkexpr(t3));
+ break;
}
- assign(t3, binop(Iop_OrV128, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
+ default:
+ return -1;
}
- case 0x05: { /* BNEGI.df */
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- ULong tmp = 1;
- assign(t1, getWReg(ws));
+ break;
+ }
- switch (df) {
- case 0x00: { /* BNEGI.B */
- DIP("BNEGI.B w%d, w%d, %d", wd, ws, m);
- tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
- (tmp << 32) | (tmp << 24) | (tmp << 16) |
- (tmp << 8);
- assign(t2, binop(Iop_ShlN8x16,
- binop(Iop_64HLtoV128,
- mkU64(tmp), mkU64(tmp)), mkU8(m)));
- break;
- }
+ case 0x05: { /* AVE_U.df */
+ switch (df) {
+ case 0x00: { /* AVE_U.B */
+ DIP("AVE_U.B w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3, binop(Iop_Add16x8,
+ binop(Iop_Add8x16,
+ binop(Iop_ShrN8x16,
+ mkexpr(t1), mkU8(1)),
+ binop(Iop_ShrN8x16,
+ mkexpr(t2), mkU8(1))),
+ binop(Iop_ShrN8x16,
+ binop(Iop_ShlN8x16,
+ binop(Iop_AndV128,
+ mkexpr(t1),
+ mkexpr(t2)),
+ mkU8(7)),
+ mkU8(7))));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- case 0x01: { /* BNEGI.H */
- DIP("BNEGI.H w%d, w%d, %d", wd, ws, m);
- tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
- assign(t2, binop(Iop_ShlN16x8,
- binop(Iop_64HLtoV128,
- mkU64(tmp), mkU64(tmp)), mkU8(m)));
- break;
- }
+ case 0x01: { /* AVE_U.H */
+ DIP("AVE_U.H w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3, binop(Iop_Add16x8,
+ binop(Iop_Add16x8,
+ binop(Iop_ShrN16x8,
+ mkexpr(t1), mkU8(1)),
+ binop(Iop_ShrN16x8,
+ mkexpr(t2), mkU8(1))),
+ binop(Iop_ShrN16x8,
+ binop(Iop_ShlN16x8,
+ binop(Iop_AndV128,
+ mkexpr(t1),
+ mkexpr(t2)),
+ mkU8(15)),
+ mkU8(15))));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- case 0x02: { /* BNEGI.W */
- DIP("BNEGI.W w%d, w%d, %d", wd, ws, m);
- tmp |= (tmp << 32);
- assign(t2, binop(Iop_ShlN32x4,
- binop(Iop_64HLtoV128,
- mkU64(tmp), mkU64(tmp)), mkU8(m)));
- break;
- }
+ case 0x02: { /* AVE_U.W */
+ DIP("AVE_U.W w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3, binop(Iop_Add32x4,
+ binop(Iop_Add32x4,
+ binop(Iop_ShrN32x4,
+ mkexpr(t1), mkU8(1)),
+ binop(Iop_ShrN32x4,
+ mkexpr(t2), mkU8(1))),
+ binop(Iop_ShrN32x4,
+ binop(Iop_ShlN32x4,
+ binop(Iop_AndV128,
+ mkexpr(t1),
+ mkexpr(t2)),
+ mkU8(31)),
+ mkU8(31))));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- case 0x03: { /* BNEGI.D */
- DIP("BNEGI.D w%d, w%d, %d", wd, ws, m);
- assign(t2, binop(Iop_ShlN64x2,
- binop(Iop_64HLtoV128,
- mkU64(tmp), mkU64(tmp)), mkU8(m)));
- break;
- }
+ case 0x03: { /* AVE_U.D */
+ DIP("AVE_U.D w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3, binop(Iop_Add64x2,
+ binop(Iop_Add64x2,
+ binop(Iop_ShrN64x2,
+ mkexpr(t1), mkU8(1)),
+ binop(Iop_ShrN64x2,
+ mkexpr(t2), mkU8(1))),
+ binop(Iop_ShrN64x2,
+ binop(Iop_ShlN64x2,
+ binop(Iop_AndV128,
+ mkexpr(t1),
+ mkexpr(t2)),
+ mkU8(63)),
+ mkU8(63))));
+ putWReg(wd, mkexpr(t3));
+ break;
}
- assign(t3, binop(Iop_XorV128, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
+ default:
+ return -1;
}
- case 0x06: { /* BINSLI.df */
- switch (df) {
- case 0x00: { /* BINSLI.B */
- DIP("BINSLI.B w%d, w%d, w%d", wd, ws, m);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- ULong tmp = 0x8080808080808080ULL;
- assign(t1, binop(Iop_SarN8x16,
- binop(Iop_64HLtoV128,
- mkU64(tmp), mkU64(tmp)), mkU8(m)));
- assign(t2,
- binop(Iop_AndV128,
- unop(Iop_NotV128, mkexpr(t1)), getWReg(wd)));
- assign(t3,
- binop(Iop_AndV128,
- mkexpr(t1), getWReg(ws)));
- putWReg(wd,
- binop(Iop_OrV128,
- mkexpr(t2), mkexpr(t3)));
- break;
- }
+ break;
+ }
- case 0x01: { /* BINSLI.H */
- DIP("BINSLI.H w%d, w%d, w%d", wd, ws, m);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- ULong tmp = 0x8000800080008000ULL;
- assign(t1,
- binop(Iop_SarN16x8,
- binop(Iop_64HLtoV128,
- mkU64(tmp), mkU64(tmp)), mkU8(m)));
- assign(t2,
- binop(Iop_AndV128,
- unop(Iop_NotV128, mkexpr(t1)), getWReg(wd)));
- assign(t3,
- binop(Iop_AndV128,
- mkexpr(t1), getWReg(ws)));
- putWReg(wd,
- binop(Iop_OrV128,
- mkexpr(t2), mkexpr(t3)));
- break;
- }
+ case 0x06: { /* AVER_S.df */
+ switch (df) {
+ case 0x00: { /* AVER_S.B */
+ DIP("AVER_S.B w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3, binop(Iop_Avg8Sx16, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- case 0x02: { /* BINSLI.W */
- DIP("BINSLI.W w%d, w%d, w%d", wd, ws, m);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- ULong tmp = 0x8000000080000000ULL;
- assign(t1,
- binop(Iop_SarN32x4,
- binop(Iop_64HLtoV128,
- mkU64(tmp), mkU64(tmp)), mkU8(m)));
- assign(t2,
- binop(Iop_AndV128,
- unop(Iop_NotV128, mkexpr(t1)), getWReg(wd)));
- assign(t3,
- binop(Iop_AndV128,
- mkexpr(t1), getWReg(ws)));
- putWReg(wd,
- binop(Iop_OrV128,
- mkexpr(t2), mkexpr(t3)));
- break;
- }
+ case 0x01: { /* AVER_S.H */
+ DIP("AVER_S.H w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3, binop(Iop_Avg16Sx8, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- case 0x03: { /* BINSLI.D */
- DIP("BINSLI.D w%d, w%d, w%d", wd, ws, m);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- ULong tmp = 0x8000000000000000ULL;
- assign(t1,
- binop(Iop_SarN64x2,
- binop(Iop_64HLtoV128,
- mkU64(tmp), mkU64(tmp)), mkU8(m)));
- assign(t2,
- binop(Iop_AndV128,
- unop(Iop_NotV128, mkexpr(t1)), getWReg(wd)));
- assign(t3,
- binop(Iop_AndV128,
- mkexpr(t1), getWReg(ws)));
- putWReg(wd,
- binop(Iop_OrV128,
- mkexpr(t2), mkexpr(t3)));
- break;
- }
+ case 0x02: { /* AVER_S.W */
+ DIP("AVER_S.W w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3, binop(Iop_Avg32Sx4, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- default:
- return -1;
+ case 0x03: { /* AVER_S.D */
+ DIP("AVER_S.D w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3, binop(Iop_Add64x2,
+ binop(Iop_Add64x2,
+ binop(Iop_SarN64x2,
+ mkexpr(t1), mkU8(1)),
+ binop(Iop_SarN64x2,
+ mkexpr(t2), mkU8(1))),
+ binop(Iop_ShrN64x2,
+ binop(Iop_ShlN64x2,
+ binop(Iop_OrV128,
+ mkexpr(t1),
+ mkexpr(t2)),
+ mkU8(63)),
+ mkU8(63))));
+ putWReg(wd, mkexpr(t3));
+ break;
}
- break;
+ default:
+ return -1;
}
- case 0x07: {
- switch (df) {
- case 0x00: { /* BINSRI.B */
- DIP("BINSRI.B w%d, w%d, w%d", wd, ws, m);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- ULong tmp = 0xFEFEFEFEFEFEFEFEULL;
- assign(t1,
- binop(Iop_ShlN8x16,
- binop(Iop_64HLtoV128,
- mkU64(tmp), mkU64(tmp)), mkU8(m)));
- assign(t2,
- binop(Iop_AndV128,
- unop(Iop_NotV128, mkexpr(t1)), getWReg(ws)));
- assign(t3,
- binop(Iop_AndV128,
- mkexpr(t1), getWReg(wd)));
- putWReg(wd,
- binop(Iop_OrV128,
- mkexpr(t2), mkexpr(t3)));
- break;
- }
+ break;
+ }
- case 0x01: { /* BINSRI.H */
- DIP("BINSRI.H w%d, w%d, w%d", wd, ws, m);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- ULong tmp = 0xFFFEFFFEFFFEFFFEULL;
- assign(t1,
- binop(Iop_ShlN16x8,
- binop(Iop_64HLtoV128,
- mkU64(tmp), mkU64(tmp)),
- mkU8(m)));
- assign(t2,
- binop(Iop_AndV128,
- unop(Iop_NotV128, mkexpr(t1)),
- getWReg(ws)));
- assign(t3,
- binop(Iop_AndV128,
- mkexpr(t1), getWReg(wd)));
- putWReg(wd,
- binop(Iop_OrV128,
- mkexpr(t2), mkexpr(t3)));
- break;
- }
+ case 0x07: { /* AVER_U.df */
+ switch (df) {
+ case 0x00: { /* AVER_U.B */
+ DIP("AVER_U.B w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3, binop(Iop_Avg8Ux16, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- case 0x02: { /* BINSRI.W */
- DIP("BINSRI.W w%d, w%d, w%d", wd, ws, m);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- ULong tmp = 0xFFFFFFFEFFFFFFFEULL;
- assign(t1,
- binop(Iop_ShlN32x4,
- binop(Iop_64HLtoV128,
- mkU64(tmp), mkU64(tmp)),
- mkU8(m)));
- assign(t2,
- binop(Iop_AndV128,
- unop(Iop_NotV128, mkexpr(t1)),
- getWReg(ws)));
- assign(t3,
- binop(Iop_AndV128,
- mkexpr(t1), getWReg(wd)));
- putWReg(wd,
- binop(Iop_OrV128,
- mkexpr(t2), mkexpr(t3)));
- break;
- }
+ case 0x01: { /* AVER_U.H */
+ DIP("AVER_U.H w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3, binop(Iop_Avg16Ux8, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- case 0x03: { /* BINSRI.D */
- DIP("BINSRI.D w%d, w%d, w%d", wd, ws, m);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- ULong tmp = -2;
- assign(t1,
- binop(Iop_ShlN64x2,
- binop(Iop_64HLtoV128,
- mkU64(tmp), mkU64(tmp)),
- mkU8(m)));
- assign(t2,
- binop(Iop_AndV128,
- unop(Iop_NotV128, mkexpr(t1)),
- getWReg(ws)));
- assign(t3,
- binop(Iop_AndV128,
- mkexpr(t1), getWReg(wd)));
- putWReg(wd,
- binop(Iop_OrV128,
- mkexpr(t2), mkexpr(t3)));
- break;
- }
+ case 0x02: { /* AVER_U.W */
+ DIP("AVER_U.W w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3, binop(Iop_Avg32Ux4, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- default:
- return -1;
+ case 0x03: { /* AVER_U.D */
+ DIP("AVER_U.D w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3, binop(Iop_Add64x2,
+ binop(Iop_Add64x2,
+ binop(Iop_ShrN64x2,
+ mkexpr(t1), mkU8(1)),
+ binop(Iop_ShrN64x2,
+ mkexpr(t2), mkU8(1))),
+ binop(Iop_ShrN64x2,
+ binop(Iop_ShlN64x2,
+ binop(Iop_OrV128,
+ mkexpr(t1),
+ mkexpr(t2)),
+ mkU8(63)),
+ mkU8(63))));
+ putWReg(wd, mkexpr(t3));
+ break;
}
- break;
+ default:
+ return -1;
}
+ break;
+ }
+
default:
return -1;
}
return 0;
}
-static Int msa_BIT_0A(UInt cins, UChar wd, UChar ws) { /* BIT (0x0A) */
- IRTemp t1, t2;
+static Int msa_3R_11(UInt cins, UChar wd, UChar ws) /* 3R (0x11) */
+{
+ IRTemp t1, t2, t3;
UShort operation;
- UChar df, m;
+ UChar df, wt;
operation = (cins & 0x03800000) >> 23;
- df = (cins & 0x007F0000) >> 16;
-
- if ((df & 0x70) == 0x70) { // 111mmmm; b
- m = df & 0x07;
- df = 0;
- } else if ((df & 0x60) == 0x60) { // 110mmmm; h
- m = df & 0x0F;
- df = 1;
- } else if ((df & 0x40) == 0x40) { // 10mmmmm; w
- m = df & 0x1F;
- df = 2;
- } else if ((df & 0x00) == 0x00) { // 0mmmmmm; d
- m = df & 0x3F;
- df = 3;
- }
+ df = (cins & 0x00600000) >> 21;
+ wt = (cins & 0x001F0000) >> 16;
switch (operation) {
- case 0x00: { /* SAT_S.df */
- switch (df) {
- case 0x00: { /* SAT_S.B */
- DIP("SAT_S.B w%d, w%d, %d", wd, ws, m);
- t1 = newTemp(Ity_V128);
- assign(t1, binop(Iop_SarN8x16, getWReg(ws), mkU8(7)));
-
- if (m == 0) {
- putWReg(wd, mkexpr(t1));
- } else {
- t2 = newTemp(Ity_V128);
- assign(t2,
- binop(Iop_SarN8x16, getWReg(ws), mkU8(m)));
- putWReg(wd,
- binop(Iop_OrV128,
- binop(Iop_OrV128,
- binop(Iop_AndV128,
- binop(Iop_CmpEQ8x16,
- mkexpr(t1),
- mkexpr(t2)),
- getWReg(ws)),
- binop(Iop_ShlN8x16,
- binop(Iop_CmpGT8Sx16,
- mkexpr(t1),
- mkexpr(t2)),
- mkU8(m))),
- binop(Iop_ShrN8x16,
- binop(Iop_CmpGT8Sx16,
- mkexpr(t2),
- mkexpr(t1)),
- mkU8(8 - m))));
- }
-
- break;
- }
-
- case 0x01: { /* SAT_S.H */
- DIP("SAT_S.H w%d, w%d, %d", wd, ws, m);
- t1 = newTemp(Ity_V128);
- assign(t1, binop(Iop_SarN16x8, getWReg(ws), mkU8(15)));
-
- if (m == 0) {
- putWReg(wd, mkexpr(t1));
- } else {
- t2 = newTemp(Ity_V128);
- assign(t2,
- binop(Iop_SarN16x8,
- getWReg(ws),
- mkU8(m)));
- putWReg(wd,
- binop(Iop_OrV128,
- binop(Iop_OrV128,
- binop(Iop_AndV128,
- binop(Iop_CmpEQ16x8,
- mkexpr(t1),
- mkexpr(t2)),
- getWReg(ws)),
- binop(Iop_ShlN16x8,
- binop(Iop_CmpGT16Sx8,
- mkexpr(t1),
- mkexpr(t2)),
- mkU8(m))),
- binop(Iop_ShrN16x8,
- binop(Iop_CmpGT16Sx8,
- mkexpr(t2),
- mkexpr(t1)),
- mkU8(16 - m))));
- }
-
- break;
- }
-
- case 0x02: { /* SAT_S.W */
- DIP("SAT_S.W w%d, w%d, %d", wd, ws, m);
- t1 = newTemp(Ity_V128);
- assign(t1, binop(Iop_SarN32x4, getWReg(ws), mkU8(31)));
-
- if (m == 0) {
- putWReg(wd, mkexpr(t1));
- } else {
- t2 = newTemp(Ity_V128);
- assign(t2,
- binop(Iop_SarN32x4,
- getWReg(ws),
- mkU8(m)));
- putWReg(wd,
- binop(Iop_OrV128,
- binop(Iop_OrV128,
- binop(Iop_AndV128,
- binop(Iop_CmpEQ32x4,
- mkexpr(t1),
- mkexpr(t2)),
- getWReg(ws)),
- binop(Iop_ShlN32x4,
- binop(Iop_CmpGT32Sx4,
- mkexpr(t1),
- mkexpr(t2)),
- mkU8(m))),
- binop(Iop_ShrN32x4,
- binop(Iop_CmpGT32Sx4,
- mkexpr(t2),
- mkexpr(t1)),
- mkU8(32 - m))));
- }
-
- break;
- }
+ case 0x00: { /* SUBS_S.df */
+ switch (df) {
+ case 0x00: { /* SUBS_S.B */
+ DIP("SUBS_S.B w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3, binop(Iop_QSub8Sx16, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- case 0x03: { /* SAT_S.D */
- DIP("SAT_S.D w%d, w%d, %d", wd, ws, m);
- t1 = newTemp(Ity_V128);
- assign(t1, binop(Iop_SarN64x2, getWReg(ws), mkU8(63)));
+ case 0x01: { /* SUBS_S.H */
+ DIP("SUBS_S.H w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3, binop(Iop_QSub16Sx8, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- if (m == 0) {
- putWReg(wd, mkexpr(t1));
- } else {
- t2 = newTemp(Ity_V128);
- assign(t2,
- binop(Iop_SarN64x2,
- getWReg(ws),
- mkU8(m)));
- putWReg(wd,
- binop(Iop_OrV128,
- binop(Iop_OrV128,
- binop(Iop_AndV128,
- binop(Iop_CmpEQ64x2,
- mkexpr(t1),
- mkexpr(t2)),
- getWReg(ws)),
- binop(Iop_ShlN64x2,
- binop(Iop_CmpGT64Sx2,
- mkexpr(t1),
- mkexpr(t2)),
- mkU8(m))),
- binop(Iop_ShrN64x2,
- binop(Iop_CmpGT64Sx2,
- mkexpr(t2),
- mkexpr(t1)),
- mkU8(64 - m))));
- }
+ case 0x02: { /* SUBS_S.W */
+ DIP("SUBS_S.W w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3, binop(Iop_QSub32Sx4, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- break;
- }
+ case 0x03: { /* SUBS_S.D */
+ DIP("SUBS_S.D w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3, binop(Iop_QSub64Sx2, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
}
- break;
+ default:
+ return -1;
}
- case 0x01: { /* SAT_U.df */
- switch (df) {
- case 0x00: { /* SAT_U.B */
- DIP("SAT_U.B w%d, w%d, %d", wd, ws, m);
-
- if (m == 7) {
- putWReg(wd, getWReg(ws));
- } else {
- t1 = newTemp(Ity_V128);
- assign(t1,
- binop(Iop_CmpEQ8x16,
- binop(Iop_ShrN8x16,
- getWReg(ws),
- mkU8(m + 1)),
- binop(Iop_64HLtoV128,
- mkU64(0), mkU64(0))));
- putWReg(wd,
- binop(Iop_OrV128,
- binop(Iop_AndV128,
- mkexpr(t1),
- getWReg(ws)),
- binop(Iop_ShrN8x16,
- unop(Iop_NotV128,
- mkexpr(t1)),
- mkU8(7 - m))));
- }
-
- break;
- }
-
- case 0x01: { /* SAT_U.H */
- DIP("SAT_U.H w%d, w%d, %d", wd, ws, m);
-
- if (m == 15) {
- putWReg(wd, getWReg(ws));
- } else {
- t1 = newTemp(Ity_V128);
- assign(t1,
- binop(Iop_CmpEQ16x8,
- binop(Iop_ShrN16x8,
- getWReg(ws),
- mkU8(m + 1)),
- binop(Iop_64HLtoV128,
- mkU64(0), mkU64(0))));
- putWReg(wd,
- binop(Iop_OrV128,
- binop(Iop_AndV128,
- mkexpr(t1),
- getWReg(ws)),
- binop(Iop_ShrN16x8,
- unop(Iop_NotV128,
- mkexpr(t1)),
- mkU8(15 - m))));
- }
+ break;
+ }
- break;
- }
+ case 0x01: { /* SUBS_U.df */
+ switch (df) {
+ case 0x00: { /* SUBS_U.B */
+ DIP("SUBS_U.B w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3, binop(Iop_QSub8Ux16, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- case 0x02: { /* SAT_U.W */
- DIP("SAT_U.W w%d, w%d, %d", wd, ws, m);
+ case 0x01: { /* SUBS_U.H */
+ DIP("SUBS_U.H w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3, binop(Iop_QSub16Ux8, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- if (m == 31) {
- putWReg(wd, getWReg(ws));
- } else {
- t1 = newTemp(Ity_V128);
- assign(t1,
- binop(Iop_CmpEQ32x4,
- binop(Iop_ShrN32x4,
- getWReg(ws),
- mkU8(m + 1)),
- binop(Iop_64HLtoV128,
- mkU64(0), mkU64(0))));
- putWReg(wd,
- binop(Iop_OrV128,
- binop(Iop_AndV128,
- mkexpr(t1), \
- getWReg(ws)),
- binop(Iop_ShrN32x4,
- unop(Iop_NotV128,
- mkexpr(t1)),
- mkU8(31 - m))));
- }
+ case 0x02: { /* SUBS_U.W */
+ DIP("SUBS_U.W w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3, binop(Iop_QSub32Ux4, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- break;
- }
+ case 0x03: { /* SUBS_U.D */
+ DIP("SUBS_U.D w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3, binop(Iop_QSub64Ux2, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- case 0x03: { /* SAT_U.D */
- DIP("SAT_U.D w%d, w%d, %d", wd, ws, m);
+ default:
+ return -1;
+ }
- if (m == 63) {
- putWReg(wd, getWReg(ws));
- } else {
- t1 = newTemp(Ity_V128);
- assign(t1,
- binop(Iop_CmpEQ64x2,
- binop(Iop_ShrN64x2,
- getWReg(ws),
- mkU8(m + 1)),
- binop(Iop_64HLtoV128,
- mkU64(0), mkU64(0))));
- putWReg(wd,
- binop(Iop_OrV128,
- binop(Iop_AndV128,
- mkexpr(t1),
- getWReg(ws)),
- binop(Iop_ShrN64x2,
- unop(Iop_NotV128,
- mkexpr(t1)),
- mkU8(63 - m))));
- }
+ break;
+ }
- break;
- }
+ case 0x02: { /* SUBSUS_U.df */
+ switch (df) {
+ case 0x00: { /* SUBSUS_U.B */
+ DIP("SUBSUS_U.B w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, binop(Iop_Sub8x16, getWReg(ws), getWReg(wt)));
+ assign(t2, binop(Iop_SarN8x16, getWReg(wt), mkU8(7)));
+ assign(t3, binop(Iop_OrV128,
+ binop(Iop_CmpGT8Ux16,
+ getWReg(ws),
+ getWReg(wt)),
+ binop(Iop_CmpEQ8x16,
+ getWReg(ws),
+ getWReg(wt))));
+ putWReg(wd,
+ binop(Iop_OrV128,
+ binop(Iop_AndV128,
+ mkexpr(t3), mkexpr(t2)),
+ binop(Iop_AndV128,
+ mkexpr(t1),
+ binop(Iop_XorV128,
+ mkexpr(t3),
+ mkexpr(t2)))));
+ break;
}
- break;
- }
+ case 0x01: { /* SUBSUS_U.H */
+ DIP("SUBSUS_U.H w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, binop(Iop_Sub16x8, getWReg(ws), getWReg(wt)));
+ assign(t2, binop(Iop_SarN16x8, getWReg(wt), mkU8(15)));
+ assign(t3,
+ binop(Iop_OrV128,
+ binop(Iop_CmpGT16Ux8,
+ getWReg(ws),
+ getWReg(wt)),
+ binop(Iop_CmpEQ16x8,
+ getWReg(ws),
+ getWReg(wt))));
+ putWReg(wd,
+ binop(Iop_OrV128,
+ binop(Iop_AndV128,
+ mkexpr(t3), mkexpr(t2)),
+ binop(Iop_AndV128,
+ mkexpr(t1),
+ binop(Iop_XorV128,
+ mkexpr(t3),
+ mkexpr(t2)))));
+ break;
+ }
- case 0x02: { /* SRARI.df */
- switch (df) {
- case 0x00: { /* SRARI.B */
- DIP("SRARI.B w%d, w%d, %d", wd, ws, m);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- assign(t1,
- binop(Iop_SarN8x16,
+ case 0x02: { /* SUBSUS_U.W */
+ DIP("SUBSUS_U.W w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, binop(Iop_Sub32x4, getWReg(ws), getWReg(wt)));
+ assign(t2, binop(Iop_SarN32x4, getWReg(wt), mkU8(31)));
+ assign(t3,
+ binop(Iop_OrV128,
+ binop(Iop_CmpGT32Ux4,
getWReg(ws),
- mkU8(m)));
- assign(t2,
- binop(Iop_ShrN8x16,
- binop(Iop_ShlN8x16,
- getWReg(ws),
- mkU8(8 - m)),
- mkU8(7)));
+ getWReg(wt)),
+ binop(Iop_CmpEQ32x4,
+ getWReg(ws),
+ getWReg(wt))));
+ putWReg(wd,
+ binop(Iop_OrV128,
+ binop(Iop_AndV128,
+ mkexpr(t3), mkexpr(t2)),
+ binop(Iop_AndV128,
+ mkexpr(t1),
+ binop(Iop_XorV128,
+ mkexpr(t3),
+ mkexpr(t2)))));
+ break;
+ }
- if (m) putWReg(wd, binop(Iop_Add8x16,
- mkexpr(t1),
- mkexpr(t2)));
- else putWReg(wd, mkexpr(t1));
+ case 0x03: { /* SUBSUS_U.D */
+ DIP("SUBSUS_U.D w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, binop(Iop_Sub64x2, getWReg(ws), getWReg(wt)));
+ assign(t2, binop(Iop_SarN64x2, getWReg(wt), mkU8(63)));
+ assign(t3,
+ binop(Iop_OrV128,
+ binop(Iop_CmpGT64Ux2,
+ getWReg(ws),
+ getWReg(wt)),
+ binop(Iop_CmpEQ64x2,
+ getWReg(ws),
+ getWReg(wt))));
+ putWReg(wd,
+ binop(Iop_OrV128,
+ binop(Iop_AndV128,
+ mkexpr(t3), mkexpr(t2)),
+ binop(Iop_AndV128,
+ mkexpr(t1),
+ binop(Iop_XorV128,
+ mkexpr(t3),
+ mkexpr(t2)))));
+ break;
+ }
- break;
- }
+ default:
+ return -1;
+ }
- case 0x01: { /* SRARI.H */
- DIP("SRARI.H w%d, w%d, %d", wd, ws, m);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- assign(t1,
- binop(Iop_SarN16x8,
- getWReg(ws),
- mkU8(m)));
- assign(t2,
- binop(Iop_ShrN16x8,
- binop(Iop_ShlN16x8,
- getWReg(ws),
- mkU8(16 - m)),
- mkU8(15)));
+ break;
+ }
- if (m)
- putWReg(wd,
- binop(Iop_Add16x8,
- mkexpr(t1), mkexpr(t2)));
- else putWReg(wd, mkexpr(t1));
+ case 0x03: { /* SUBSUU_S.df */
+ switch (df) {
+ case 0x00: { /* SUBSUU_S.B */
+ DIP("SUBSUU_S.B w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, binop(Iop_Sub8x16, getWReg(ws), getWReg(wt)));
+ assign(t2,
+ binop(Iop_SarN8x16,
+ binop (Iop_AndV128,
+ binop(Iop_XorV128,
+ getWReg(ws),
+ getWReg(wt)),
+ binop(Iop_XorV128,
+ mkexpr(t1),
+ getWReg(wt))),
+ mkU8(7)));
+ assign(t3,
+ binop(Iop_AndV128,
+ binop(Iop_SarN8x16,
+ getWReg(ws), mkU8(7)),
+ mkexpr(t2)));
+ putWReg(wd,
+ binop(Iop_OrV128,
+ binop(Iop_AndV128,
+ mkexpr(t1),
+ unop(Iop_NotV128,
+ mkexpr(t2))),
+ binop(Iop_XorV128,
+ binop(Iop_ShlN8x16,
+ mkexpr(t2), mkU8(7)),
+ mkexpr(t3))));
+ break;
+ }
- break;
- }
+ case 0x01: { /* SUBSUU_S.H */
+ DIP("SUBSUU_S.H w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, binop(Iop_Sub16x8, getWReg(ws), getWReg(wt)));
+ assign(t2,
+ binop(Iop_SarN16x8,
+ binop (Iop_AndV128,
+ binop(Iop_XorV128,
+ getWReg(ws),
+ getWReg(wt)),
+ binop(Iop_XorV128,
+ mkexpr(t1),
+ getWReg(wt))),
+ mkU8(15)));
+ assign(t3,
+ binop(Iop_AndV128,
+ binop(Iop_SarN16x8,
+ getWReg(ws),
+ mkU8(15)),
+ mkexpr(t2)));
+ putWReg(wd,
+ binop(Iop_OrV128,
+ binop(Iop_AndV128,
+ mkexpr(t1),
+ unop(Iop_NotV128,
+ mkexpr(t2))),
+ binop(Iop_XorV128,
+ binop(Iop_ShlN16x8,
+ mkexpr(t2), mkU8(15)),
+ mkexpr(t3))));
+ break;
+ }
- case 0x02: { /* SRARI.W */
- DIP("SRARI.W w%d, w%d, %d", wd, ws, m);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- assign(t1,
+ case 0x02: { /* SUBSUU_S.W */
+ DIP("SUBSUU_S.W w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, binop(Iop_Sub32x4, getWReg(ws), getWReg(wt)));
+ assign(t2,
+ binop(Iop_SarN32x4,
+ binop (Iop_AndV128,
+ binop(Iop_XorV128,
+ getWReg(ws),
+ getWReg(wt)),
+ binop(Iop_XorV128,
+ mkexpr(t1),
+ getWReg(wt))),
+ mkU8(31)));
+ assign(t3,
+ binop(Iop_AndV128,
binop(Iop_SarN32x4,
getWReg(ws),
- mkU8(m)));
- assign(t2,
- binop(Iop_ShrN32x4,
- binop(Iop_ShlN32x4,
- getWReg(ws),
- mkU8(32 - m)),
- mkU8(31)));
-
- if (m)
- putWReg(wd,
- binop(Iop_Add32x4,
- mkexpr(t1), mkexpr(t2)));
- else putWReg(wd, mkexpr(t1));
-
- break;
- }
+ mkU8(31)),
+ mkexpr(t2)));
+ putWReg(wd,
+ binop(Iop_OrV128,
+ binop(Iop_AndV128,
+ mkexpr(t1),
+ unop(Iop_NotV128,
+ mkexpr(t2))),
+ binop(Iop_XorV128,
+ binop(Iop_ShlN32x4,
+ mkexpr(t2),
+ mkU8(31)),
+ mkexpr(t3))));
+ break;
+ }
- case 0x03: { /* SRARI.D */
- DIP("SRARI.D w%d, w%d, %d", wd, ws, m);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- assign(t1,
+ case 0x03: { /* SUBSUU_S.D */
+ DIP("SUBSUU_S.D w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, binop(Iop_Sub64x2, getWReg(ws), getWReg(wt)));
+ assign(t2,
+ binop(Iop_SarN64x2,
+ binop (Iop_AndV128,
+ binop(Iop_XorV128,
+ getWReg(ws),
+ getWReg(wt)),
+ binop(Iop_XorV128,
+ mkexpr(t1),
+ getWReg(wt))),
+ mkU8(63)));
+ assign(t3,
+ binop(Iop_AndV128,
binop(Iop_SarN64x2,
getWReg(ws),
- mkU8(m)));
- assign(t2,
- binop(Iop_ShrN64x2,
- binop(Iop_ShlN64x2,
- getWReg(ws),
- mkU8(64 - m)),
- mkU8(63)));
-
- if (m)
- putWReg(wd,
- binop(Iop_Add64x2,
- mkexpr(t1), mkexpr(t2)));
- else putWReg(wd, mkexpr(t1));
-
- break;
- }
+ mkU8(63)),
+ mkexpr(t2)));
+ putWReg(wd,
+ binop(Iop_OrV128,
+ binop(Iop_AndV128,
+ mkexpr(t1),
+ unop(Iop_NotV128,
+ mkexpr(t2))),
+ binop(Iop_XorV128,
+ binop(Iop_ShlN64x2,
+ mkexpr(t2), mkU8(63)),
+ mkexpr(t3))));
+ break;
}
- break;
+ default:
+ return -1;
}
- case 0x03: { /* SRLRI.df */
- switch (df) {
- case 0x00: { /* SRLRI.B */
- DIP("SRLRI.B w%d, w%d, %d", wd, ws, m);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- assign(t1,
- binop(Iop_ShrN8x16,
- getWReg(ws),
- mkU8(m)));
- assign(t2,
- binop(Iop_ShrN8x16,
- binop(Iop_ShlN8x16,
- getWReg(ws),
- mkU8(8 - m)),
- mkU8(7)));
-
- if (m)
- putWReg(wd,
- binop(Iop_Add8x16,
- mkexpr(t1), mkexpr(t2)));
- else putWReg(wd, mkexpr(t1));
+ break;
+ }
- break;
- }
+ case 0x04: { /* ASUB_S.df */
+ switch (df) {
+ case 0x00: { /* ASUB_S.B */
+ DIP("ASUB_S.B w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, binop(Iop_SarN8x16, getWReg(ws), mkU8(7)));
+ assign(t2, binop(Iop_SarN8x16, getWReg(wt), mkU8(7)));
+ assign(t3, binop(Iop_Sub8x16, getWReg(ws), getWReg(wt)));
+ putWReg(wd,
+ binop(Iop_OrV128,
+ binop(Iop_OrV128,
+ binop(Iop_AndV128,
+ binop(Iop_AndV128,
+ unop(Iop_NotV128,
+ mkexpr(t1)),
+ mkexpr(t2)),
+ mkexpr(t3)),
+ binop(Iop_AndV128,
+ unop(Iop_NotV128,
+ binop(Iop_XorV128,
+ mkexpr(t1),
+ mkexpr(t2))),
+ unop(Iop_Abs8x16,
+ mkexpr(t3)))),
+ binop(Iop_AndV128,
+ binop(Iop_AndV128,
+ mkexpr(t1),
+ unop(Iop_NotV128,
+ mkexpr(t2))),
+ binop(Iop_Sub8x16,
+ getWReg(wt),
+ getWReg(ws)))));
+ break;
+ }
- case 0x01: { /* SRLRI.H */
- DIP("SRLRI.H w%d, w%d, %d", wd, ws, m);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- assign(t1,
- binop(Iop_ShrN16x8,
- getWReg(ws),
- mkU8(m)));
- assign(t2,
- binop(Iop_ShrN16x8,
- binop(Iop_ShlN16x8,
- getWReg(ws),
- mkU8(16 - m)),
- mkU8(15)));
+ case 0x01: { /* ASUB_S.H */
+ DIP("ASUB_S.H w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, binop(Iop_SarN16x8, getWReg(ws), mkU8(15)));
+ assign(t2, binop(Iop_SarN16x8, getWReg(wt), mkU8(15)));
+ assign(t3, binop(Iop_Sub16x8, getWReg(ws), getWReg(wt)));
+ putWReg(wd,
+ binop(Iop_OrV128,
+ binop(Iop_OrV128,
+ binop(Iop_AndV128,
+ binop(Iop_AndV128,
+ unop(Iop_NotV128,
+ mkexpr(t1)),
+ mkexpr(t2)),
+ mkexpr(t3)),
+ binop(Iop_AndV128,
+ unop(Iop_NotV128,
+ binop(Iop_XorV128,
+ mkexpr(t1),
+ mkexpr(t2))),
+ unop(Iop_Abs16x8,
+ mkexpr(t3)))),
+ binop(Iop_AndV128,
+ binop(Iop_AndV128,
+ mkexpr(t1),
+ unop(Iop_NotV128,
+ mkexpr(t2))),
+ binop(Iop_Sub16x8,
+ getWReg(wt),
+ getWReg(ws)))));
+ break;
+ }
- if (m)
- putWReg(wd,
- binop(Iop_Add16x8,
- mkexpr(t1), mkexpr(t2)));
- else putWReg(wd, mkexpr(t1));
+ case 0x02: { /* ASUB_S.W */
+ DIP("ASUB_S.W w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, binop(Iop_SarN32x4, getWReg(ws), mkU8(31)));
+ assign(t2, binop(Iop_SarN32x4, getWReg(wt), mkU8(31)));
+ assign(t3, binop(Iop_Sub32x4, getWReg(ws), getWReg(wt)));
+ putWReg(wd,
+ binop(Iop_OrV128,
+ binop(Iop_OrV128,
+ binop(Iop_AndV128,
+ binop(Iop_AndV128,
+ unop(Iop_NotV128,
+ mkexpr(t1)),
+ mkexpr(t2)),
+ mkexpr(t3)),
+ binop(Iop_AndV128,
+ unop(Iop_NotV128,
+ binop(Iop_XorV128,
+ mkexpr(t1),
+ mkexpr(t2))),
+ unop(Iop_Abs32x4,
+ mkexpr(t3)))),
+ binop(Iop_AndV128,
+ binop(Iop_AndV128,
+ mkexpr(t1),
+ unop(Iop_NotV128,
+ mkexpr(t2))),
+ binop(Iop_Sub32x4,
+ getWReg(wt),
+ getWReg(ws)))));
+ break;
+ }
- break;
- }
+ case 0x03: { /* ASUB_S.D */
+ DIP("ASUB_S.D w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, binop(Iop_SarN64x2, getWReg(ws), mkU8(63)));
+ assign(t2, binop(Iop_SarN64x2, getWReg(wt), mkU8(63)));
+ assign(t3, binop(Iop_Sub64x2, getWReg(ws), getWReg(wt)));
+ putWReg(wd,
+ binop(Iop_OrV128,
+ binop(Iop_OrV128,
+ binop(Iop_AndV128,
+ binop(Iop_AndV128,
+ unop(Iop_NotV128,
+ mkexpr(t1)),
+ mkexpr(t2)),
+ mkexpr(t3)),
+ binop(Iop_AndV128,
+ unop(Iop_NotV128,
+ binop(Iop_XorV128,
+ mkexpr(t1),
+ mkexpr(t2))),
+ unop(Iop_Abs64x2,
+ mkexpr(t3)))),
+ binop(Iop_AndV128,
+ binop(Iop_AndV128,
+ mkexpr(t1),
+ unop(Iop_NotV128,
+ mkexpr(t2))),
+ binop(Iop_Sub64x2,
+ getWReg(wt),
+ getWReg(ws)))));
+ break;
+ }
- case 0x02: { /* SRLRI.W */
- DIP("SRLRI.W w%d, w%d, %d", wd, ws, m);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- assign(t1,
- binop(Iop_ShrN32x4,
- getWReg(ws),
- mkU8(m)));
- assign(t2,
- binop(Iop_ShrN32x4,
- binop(Iop_ShlN32x4,
- getWReg(ws),
- mkU8(32 - m)),
- mkU8(31)));
+ default:
+ return -1;
+ }
- if (m)
- putWReg(wd,
- binop(Iop_Add32x4,
- mkexpr(t1), mkexpr(t2)));
- else putWReg(wd, mkexpr(t1));
+ break;
+ }
- break;
- }
+ case 0x05: { /* ASUB_U.df */
+ switch (df) {
+ case 0x00: { /* ASUB_U.B */
+ DIP("ASUB_U.B w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3,
+ binop(Iop_SarN8x16,
+ binop(Iop_XorV128,
+ mkexpr(t1), mkexpr(t2)),
+ mkU8(7)));
+ putWReg(wd,
+ binop(Iop_OrV128,
+ binop(Iop_AndV128,
+ unop(Iop_NotV128, mkexpr(t3)),
+ unop(Iop_Abs8x16,
+ binop(Iop_Sub8x16,
+ mkexpr(t1),
+ mkexpr(t2)))),
+ binop(Iop_AndV128, mkexpr(t3),
+ binop(Iop_Sub8x16,
+ binop(Iop_Max8Ux16,
+ mkexpr(t1),
+ mkexpr(t2)),
+ binop(Iop_Min8Ux16,
+ mkexpr(t1),
+ mkexpr(t2))))));
+ break;
+ }
- case 0x03: { /* SRLRI.D */
- DIP("SRLRI.D w%d, w%d, %d", wd, ws, m);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- assign(t1,
- binop(Iop_ShrN64x2,
- getWReg(ws),
- mkU8(m)));
- assign(t2,
- binop(Iop_ShrN64x2,
- binop(Iop_ShlN64x2,
- getWReg(ws),
- mkU8(64 - m)),
- mkU8(63)));
+ case 0x01: { /* ASUB_U.H */
+ DIP("ASUB_U.H w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3,
+ binop(Iop_SarN16x8,
+ binop(Iop_XorV128,
+ mkexpr(t1), mkexpr(t2)),
+ mkU8(15)));
+ putWReg(wd,
+ binop(Iop_OrV128,
+ binop(Iop_AndV128,
+ unop(Iop_NotV128,
+ mkexpr(t3)),
+ unop(Iop_Abs16x8,
+ binop(Iop_Sub16x8,
+ mkexpr(t1),
+ mkexpr(t2)))),
+ binop(Iop_AndV128,
+ mkexpr(t3),
+ binop(Iop_Sub16x8,
+ binop(Iop_Max16Ux8,
+ mkexpr(t1),
+ mkexpr(t2)),
+ binop(Iop_Min16Ux8,
+ mkexpr(t1),
+ mkexpr(t2))))));
+ break;
+ }
- if (m)
- putWReg(wd,
- binop(Iop_Add64x2,
- mkexpr(t1), mkexpr(t2)));
- else putWReg(wd, mkexpr(t1));
+ case 0x02: { /* ASUB_U.W */
+ DIP("ASUB_U.W w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3,
+ binop(Iop_SarN32x4,
+ binop(Iop_XorV128,
+ mkexpr(t1), mkexpr(t2)),
+ mkU8(31)));
+ putWReg(wd,
+ binop(Iop_OrV128,
+ binop(Iop_AndV128,
+ unop(Iop_NotV128, mkexpr(t3)),
+ unop(Iop_Abs32x4,
+ binop(Iop_Sub32x4,
+ mkexpr(t1),
+ mkexpr(t2)))),
+ binop(Iop_AndV128,
+ mkexpr(t3),
+ binop(Iop_Sub32x4,
+ binop(Iop_Max32Ux4,
+ mkexpr(t1),
+ mkexpr(t2)),
+ binop(Iop_Min32Ux4,
+ mkexpr(t1),
+ mkexpr(t2))))));
+ break;
+ }
- break;
- }
+ case 0x03: { /* ASUB_U.D */
+ DIP("ASUB_U.D w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3,
+ binop(Iop_SarN64x2,
+ binop(Iop_XorV128,
+ mkexpr(t1), mkexpr(t2)),
+ mkU8(63)));
+ putWReg(wd,
+ binop(Iop_OrV128,
+ binop(Iop_AndV128,
+ unop(Iop_NotV128, mkexpr(t3)),
+ unop(Iop_Abs64x2,
+ binop(Iop_Sub64x2,
+ mkexpr(t1),
+ mkexpr(t2)))),
+ binop(Iop_AndV128,
+ mkexpr(t3),
+ binop(Iop_Sub64x2,
+ binop(Iop_Max64Ux2,
+ mkexpr(t1),
+ mkexpr(t2)),
+ binop(Iop_Min64Ux2,
+ mkexpr(t1),
+ mkexpr(t2))))));
+ break;
}
- break;
+ default:
+ return -1;
}
+ break;
+ }
+
default:
return -1;
}
return 0;
}
-static Int msa_3R_0D(UInt cins, UChar wd, UChar ws) { /* 3R (0x0D) */
- IRTemp t1, t2, t3;
+static Int msa_3R_12(UInt cins, UChar wd, UChar ws) /* 3R (0x12) */
+{
+ IRTemp t1, t2, t3, t4, t5, t6;
UShort operation;
UChar df, wt;
wt = (cins & 0x001F0000) >> 16;
switch (operation) {
- case 0x00: { /* SLL.df */
- switch (df) {
- case 0x00: { /* SLL.B */
- DIP("SLL.B w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3, binop(Iop_Shl8x16, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
-
- case 0x01: { /* SLL.H */
- DIP("SLL.H w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3, binop(Iop_Shl16x8, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
-
- case 0x02: { /* SLL.W */
- DIP("SLL.W w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3, binop(Iop_Shl32x4, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
-
- case 0x03: { /* SLL.D */
- DIP("SLL.D w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3, binop(Iop_Shl64x2, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
-
- default:
- return -1;
+ case 0x00: { /* MULV.df */
+ switch (df) {
+ case 0x00: { /* MULV.B */
+ DIP("MULV.B w%d, w%d, w%d", wd, ws, wt);
+ putWReg(wd, binop(Iop_Mul8x16, getWReg(ws), getWReg(wt)));
+ break;
}
- break;
- }
-
- case 0x01: { /* SRA.df */
- switch (df) {
- case 0x00: { /* SRA.B */
- DIP("SRA.B w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3, binop(Iop_Sar8x16, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
-
- case 0x01: { /* SRA.H */
- DIP("SRA.H w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3, binop(Iop_Sar16x8, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
-
- case 0x02: { /* SRA.W */
- DIP("SRA.W w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3, binop(Iop_Sar32x4, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ case 0x01: { /* MULV.H */
+ DIP("MULV.H w%d, w%d, w%d", wd, ws, wt);
+ putWReg(wd, binop(Iop_Mul16x8, getWReg(ws), getWReg(wt)));
+ break;
+ }
- case 0x03: { /* SRA.D */
- DIP("SRA.D w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3, binop(Iop_Sar64x2, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ case 0x02: { /* MULV.W */
+ DIP("MULV.W w%d, w%d, w%d", wd, ws, wt);
+ putWReg(wd, binop(Iop_Mul32x4, getWReg(ws), getWReg(wt)));
+ break;
+ }
- default:
- return -1;
+ case 0x03: { /* MULV.D */
+ DIP("MULV.D w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ putWReg(wd,
+ binop(Iop_64HLtoV128,
+ binop(Iop_Mul64,
+ unop(Iop_V128HIto64,
+ mkexpr(t1)),
+ unop(Iop_V128HIto64,
+ mkexpr(t2))),
+ binop(Iop_Mul64,
+ unop(Iop_V128to64,
+ mkexpr(t1)),
+ unop(Iop_V128to64,
+ mkexpr(t2)))));
+ break;
}
- break;
+ default:
+ return -1;
}
- case 0x02: { /* SRL.df */
- switch (df) {
- case 0x00: { /* SRL.B */
- DIP("SRL.B w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3, binop(Iop_Shr8x16, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ break;
+ }
- case 0x01: { /* SRL.H */
- DIP("SRL.H w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3, binop(Iop_Shr16x8, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ case 0x01: { /* MADDV.df */
+ switch (df) {
+ case 0x00: { /* MADDV.B */
+ DIP("MADDV.B w%d, w%d, w%d", wd, ws, wt);
+ putWReg(wd,
+ binop(Iop_Add8x16,
+ getWReg(wd),
+ binop(Iop_Mul8x16,
+ getWReg(ws),
+ getWReg(wt))));
+ break;
+ }
- case 0x02: { /* SRL.W */
- DIP("SRL.W w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3, binop(Iop_Shr32x4, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ case 0x01: { /* MADDV.H */
+ DIP("MADDV.H w%d, w%d, w%d", wd, ws, wt);
+ putWReg(wd,
+ binop(Iop_Add16x8,
+ getWReg(wd),
+ binop(Iop_Mul16x8,
+ getWReg(ws),
+ getWReg(wt))));
+ break;
+ }
- case 0x03: { /* SRL.D */
- DIP("SRL.D w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3, binop(Iop_Shr64x2, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ case 0x02: { /* MADDV.W */
+ DIP("MADDV.W w%d, w%d, w%d", wd, ws, wt);
+ putWReg(wd,
+ binop(Iop_Add32x4,
+ getWReg(wd),
+ binop(Iop_Mul32x4,
+ getWReg(ws),
+ getWReg(wt))));
+ break;
+ }
- default:
- return -1;
+ case 0x03: { /* MADDV.D */
+ DIP("MADDV.D w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ putWReg(wd,
+ binop(Iop_Add64x2,
+ getWReg(wd),
+ binop(Iop_64HLtoV128,
+ binop(Iop_Mul64,
+ unop(Iop_V128HIto64,
+ mkexpr(t1)),
+ unop(Iop_V128HIto64,
+ mkexpr(t2))),
+ binop(Iop_Mul64,
+ unop(Iop_V128to64,
+ mkexpr(t1)),
+ unop(Iop_V128to64,
+ mkexpr(t2))))));
+ break;
}
- break;
+ default:
+ return -1;
}
- case 0x03: { /* BCLR.df */
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- ULong tmp = 1;
- assign(t1, getWReg(ws));
+ break;
+ }
- switch (df) {
- case 0x00: { /* BCLR.B */
- DIP("BCLR.B w%d, w%d, w%d", wd, ws, wt);
- tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
- (tmp << 32) | (tmp << 24) | (tmp << 16) |
- (tmp << 8);
- assign(t2, binop(Iop_Shl8x16,
- binop(Iop_64HLtoV128,
- mkU64(tmp), mkU64(tmp)),
- getWReg(wt)));
- break;
- }
+ case 0x02: { /* MSUBV.df */
+ switch (df) {
+ case 0x00: { /* MSUBV.B */
+ DIP("MSUBV.B w%d, w%d, w%d", wd, ws, wt);
+ putWReg(wd,
+ binop(Iop_Sub8x16,
+ getWReg(wd),
+ binop(Iop_Mul8x16,
+ getWReg(ws),
+ getWReg(wt))));
+ break;
+ }
- case 0x01: { /* BCLR.H */
- DIP("BCLR.H w%d, w%d, w%d", wd, ws, wt);
- tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
- assign(t2,
- binop(Iop_Shl16x8,
- binop(Iop_64HLtoV128,
- mkU64(tmp), mkU64(tmp)),
- getWReg(wt)));
- break;
- }
+ case 0x01: { /* MSUBV.H */
+ DIP("MSUBV.H w%d, w%d, w%d", wd, ws, wt);
+ putWReg(wd,
+ binop(Iop_Sub16x8,
+ getWReg(wd),
+ binop(Iop_Mul16x8,
+ getWReg(ws),
+ getWReg(wt))));
+ break;
+ }
- case 0x02: { /* BCLR.W */
- DIP("BCLR.W w%d, w%d, w%d", wd, ws, wt);
- tmp |= (tmp << 32);
- assign(t2,
- binop(Iop_Shl32x4,
- binop(Iop_64HLtoV128,
- mkU64(tmp), mkU64(tmp)),
- getWReg(wt)));
- break;
- }
+ case 0x02: { /* MSUBV.W */
+ DIP("MSUBV.W w%d, w%d, w%d", wd, ws, wt);
+ putWReg(wd,
+ binop(Iop_Sub32x4,
+ getWReg(wd),
+ binop(Iop_Mul32x4,
+ getWReg(ws),
+ getWReg(wt))));
+ break;
+ }
- case 0x03: { /* BCLR.D */
- DIP("BCLR.D w%d, w%d, w%d", wd, ws, wt);
- assign(t2,
- binop(Iop_Shl64x2,
- binop(Iop_64HLtoV128,
- mkU64(tmp), mkU64(tmp)),
- getWReg(wt)));
- break;
- }
+ case 0x03: { /* MSUBV.D */
+ DIP("MSUBV.D w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ putWReg(wd,
+ binop(Iop_Sub64x2,
+ getWReg(wd),
+ binop(Iop_64HLtoV128,
+ binop(Iop_Mul64,
+ unop(Iop_V128HIto64,
+ mkexpr(t1)),
+ unop(Iop_V128HIto64,
+ mkexpr(t2))),
+ binop(Iop_Mul64,
+ unop(Iop_V128to64,
+ mkexpr(t1)),
+ unop(Iop_V128to64,
+ mkexpr(t2))))));
+ break;
}
- assign(t3,
- binop(Iop_AndV128,
- mkexpr(t1), unop(Iop_NotV128, mkexpr(t2))));
- putWReg(wd, mkexpr(t3));
- break;
+ default:
+ return -1;
}
- case 0x04: { /* BSET.df */
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- ULong tmp = 1;
- assign(t1, getWReg(ws));
-
- switch (df) {
- case 0x00: { /* BSET.B */
- DIP("BSET.B w%d, w%d, w%d", wd, ws, wt);
- tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
- (tmp << 32) | (tmp << 24) | (tmp << 16) |
- (tmp << 8);
- assign(t2,
- binop(Iop_Shl8x16,
- binop(Iop_64HLtoV128,
- mkU64(tmp), mkU64(tmp)),
- getWReg(wt)));
- break;
- }
+ break;
+ }
- case 0x01: { /* BSET.H */
- DIP("BSET.H w%d, w%d, w%d", wd, ws, wt);
- tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
- assign(t2,
- binop(Iop_Shl16x8,
- binop(Iop_64HLtoV128,
- mkU64(tmp), mkU64(tmp)),
- getWReg(wt)));
- break;
- }
+ case 0x04: { /* DIV_S.df */
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
- case 0x02: { /* BSET.W */
- DIP("BSET.W w%d, w%d, w%d", wd, ws, wt);
- tmp |= (tmp << 32);
- assign(t2,
- binop(Iop_Shl32x4,
- binop(Iop_64HLtoV128,
- mkU64(tmp), mkU64(tmp)),
- getWReg(wt)));
- break;
- }
+ switch (df) {
+ case 0x00: { /* DIV_S.B */
+ DIP("DIV_S.B w%d, w%d, w%d", wd, ws, wt);
+ IRTemp tmp[16];
+ Int i;
+
+ for (i = 0; i < 16; i++) {
+ tmp[i] = newTemp(Ity_I32);
+ assign(tmp[i],
+ binop(Iop_Shl32,
+ binop(Iop_And32,
+ mkU32(0xFF),
+ binop(Iop_DivS32,
+ unop(Iop_8Sto32,
+ binop(Iop_GetElem8x16,
+ mkexpr(t1),
+ mkU8(i))),
+ unop(Iop_8Sto32,
+ binop(Iop_GetElem8x16,
+ mkexpr(t2),
+ mkU8(i))))),
+ mkU8((i & 3) << 3)));
+ }
- case 0x03: { /* BSET.D */
- DIP("BSET.D w%d, w%d, w%d", wd, ws, wt);
- assign(t2,
- binop(Iop_Shl64x2,
- binop(Iop_64HLtoV128,
- mkU64(tmp), mkU64(tmp)),
- getWReg(wt)));
- break;
- }
+ putWReg(wd,
+ binop(Iop_64HLtoV128,
+ binop(Iop_32HLto64,
+ binop(Iop_Or32,
+ mkexpr(tmp[15]),
+ binop(Iop_Or32,
+ mkexpr(tmp[14]),
+ binop(Iop_Or32,
+ mkexpr(tmp[13]),
+ mkexpr(tmp[12])))),
+ binop(Iop_Or32,
+ mkexpr(tmp[11]),
+ binop(Iop_Or32,
+ mkexpr(tmp[10]),
+ binop(Iop_Or32,
+ mkexpr(tmp[9]),
+ mkexpr(tmp[8]))))),
+ binop(Iop_32HLto64,
+ binop(Iop_Or32,
+ mkexpr(tmp[7]),
+ binop(Iop_Or32,
+ mkexpr(tmp[6]),
+ binop(Iop_Or32,
+ mkexpr(tmp[5]),
+ mkexpr(tmp[4])))),
+ binop(Iop_Or32,
+ mkexpr(tmp[3]),
+ binop(Iop_Or32,
+ mkexpr(tmp[2]),
+ binop(Iop_Or32,
+ mkexpr(tmp[1]),
+ mkexpr(tmp[0]))))))
+ );
+ break;
}
- assign(t3, binop(Iop_OrV128, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ case 0x01: { /* DIV_S.H */
+ DIP("DIV_S.H w%d, w%d, w%d", wd, ws, wt);
+ IRTemp tmp[8];
+ Int i;
- case 0x05: { /* BNEG.df */
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- ULong tmp = 1;
- assign(t1, getWReg(ws));
+ for (i = 0; i < 8; i++) {
+ tmp[i] = newTemp(Ity_I32);
+ assign(tmp[i],
+ binop(Iop_Shl32,
+ binop(Iop_And32,
+ mkU32(0xFFFF),
+ binop(Iop_DivS32,
+ unop(Iop_16Sto32,
+ binop(Iop_GetElem16x8,
+ mkexpr(t1),
+ mkU8(i))),
+ unop(Iop_16Sto32,
+ binop(Iop_GetElem16x8,
+ mkexpr(t2),
+ mkU8(i))))),
+ mkU8((i & 1) << 4)));
+ }
- switch (df) {
- case 0x00: { /* BNEG.B */
- DIP("BNEG.B w%d, w%d, w%d", wd, ws, wt);
- tmp |= (tmp << 56) | (tmp << 48) | (tmp << 40) |
- (tmp << 32) | (tmp << 24) | (tmp << 16) |
- (tmp << 8);
- assign(t2,
- binop(Iop_Shl8x16,
- binop(Iop_64HLtoV128,
- mkU64(tmp), mkU64(tmp)),
- getWReg(wt)));
- break;
- }
+ putWReg(wd,
+ binop(Iop_64HLtoV128,
+ binop(Iop_32HLto64,
+ binop(Iop_Or32,
+ mkexpr(tmp[7]),
+ mkexpr(tmp[6])),
+ binop(Iop_Or32,
+ mkexpr(tmp[5]),
+ mkexpr(tmp[4]))),
+ binop(Iop_32HLto64,
+ binop(Iop_Or32,
+ mkexpr(tmp[3]),
+ mkexpr(tmp[2])),
+ binop(Iop_Or32,
+ mkexpr(tmp[1]),
+ mkexpr(tmp[0])))));
+ break;
+ }
- case 0x01: { /* BNEG.H */
- DIP("BNEG.H w%d, w%d, w%d", wd, ws, wt);
- tmp |= (tmp << 48) | (tmp << 32) | (tmp << 16);
- assign(t2,
- binop(Iop_Shl16x8,
- binop(Iop_64HLtoV128,
- mkU64(tmp), mkU64(tmp)),
- getWReg(wt)));
- break;
- }
+ case 0x02: { /* DIV_S.W */
+ DIP("DIV_S.W w%d, w%d, w%d", wd, ws, wt);
+ IRTemp tmp[4];
+ Int i;
- case 0x02: { /* BNEG.W */
- DIP("BNEG.W w%d, w%d, w%d", wd, ws, wt);
- tmp |= (tmp << 32);
- assign(t2,
- binop(Iop_Shl32x4,
- binop(Iop_64HLtoV128,
- mkU64(tmp), mkU64(tmp)),
- getWReg(wt)));
- break;
- }
+ for (i = 0; i < 4; i++) {
+ tmp[i] = newTemp(Ity_I32);
+ assign(tmp[i],
+ binop(Iop_DivS32,
+ binop(Iop_GetElem32x4,
+ mkexpr(t1), mkU8(i)),
+ binop(Iop_GetElem32x4,
+ mkexpr(t2), mkU8(i))));
+ }
- case 0x03: { /* BNEG.D */
- DIP("BNEG.D w%d, w%d, w%d", wd, ws, wt);
- assign(t2,
- binop(Iop_Shl64x2,
- binop(Iop_64HLtoV128,
- mkU64(tmp), mkU64(tmp)),
- getWReg(wt)));
- break;
- }
+ putWReg(wd,
+ binop(Iop_64HLtoV128, \
+ binop(Iop_32HLto64,
+ mkexpr(tmp[3]),
+ mkexpr(tmp[2])),
+ binop(Iop_32HLto64,
+ mkexpr(tmp[1]),
+ mkexpr(tmp[0]))));
+ break;
}
- assign(t3, binop(Iop_XorV128, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ case 0x03: { /* DIV_S.D */
+ DIP("DIV_S.D w%d, w%d, w%d", wd, ws, wt);
+ putWReg(wd,
+ binop(Iop_64HLtoV128,
+ binop(Iop_DivS64,
+ unop(Iop_V128HIto64,
+ mkexpr(t1)),
+ unop(Iop_V128HIto64,
+ mkexpr(t2))),
+ binop(Iop_DivS64,
+ unop(Iop_V128to64,
+ mkexpr(t1)),
+ unop(Iop_V128to64,
+ mkexpr(t2)))));
+ break;
+ }
- case 0x06: { /* BINSL.df */
- switch (df) {
- case 0x00: { /* BINSL.B */
- DIP("BINSL.B w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- ULong tmp = 0x8080808080808080ULL;
- assign(t1,
- binop(Iop_Sar8x16,
- binop(Iop_64HLtoV128,
- mkU64(tmp), mkU64(tmp)),
- getWReg(wt)));
- assign(t2,
- binop(Iop_AndV128,
- unop(Iop_NotV128, mkexpr(t1)),
- getWReg(wd)));
- assign(t3,
- binop(Iop_AndV128,
- mkexpr(t1), getWReg(ws)));
- putWReg(wd,
- binop(Iop_OrV128,
- mkexpr(t2), mkexpr(t3)));
- break;
- }
+ default:
+ return -1;
+ }
- case 0x01: { /* BINSL.H */
- DIP("BINSL.H w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- ULong tmp = 0x8000800080008000ULL;
- assign(t1,
- binop(Iop_Sar16x8,
- binop(Iop_64HLtoV128,
- mkU64(tmp), mkU64(tmp)),
- getWReg(wt)));
- assign(t2,
- binop(Iop_AndV128,
- unop(Iop_NotV128, mkexpr(t1)),
- getWReg(wd)));
- assign(t3,
- binop(Iop_AndV128,
- mkexpr(t1), getWReg(ws)));
- putWReg(wd,
- binop(Iop_OrV128,
- mkexpr(t2), mkexpr(t3)));
- break;
- }
+ break;
+ }
- case 0x02: { /* BINSL.W */
- DIP("BINSL.W w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- ULong tmp = 0x8000000080000000ULL;
- assign(t1,
- binop(Iop_Sar32x4,
- binop(Iop_64HLtoV128,
- mkU64(tmp), mkU64(tmp)),
- getWReg(wt)));
- assign(t2,
- binop(Iop_AndV128,
- unop(Iop_NotV128, mkexpr(t1)),
- getWReg(wd)));
- assign(t3,
- binop(Iop_AndV128,
- mkexpr(t1), getWReg(ws)));
- putWReg(wd,
- binop(Iop_OrV128,
- mkexpr(t2), mkexpr(t3)));
- break;
- }
+ case 0x05: { /* DIV_U.df */
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
- case 0x03: { /* BINSL.D */
- DIP("BINSL.D w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- ULong tmp = 0x8000000000000000ULL;
- assign(t1,
- binop(Iop_Sar64x2,
- binop(Iop_64HLtoV128,
- mkU64(tmp), mkU64(tmp)),
- getWReg(wt)));
- assign(t2,
- binop(Iop_AndV128,
- unop(Iop_NotV128, mkexpr(t1)),
- getWReg(wd)));
- assign(t3,
- binop(Iop_AndV128,
- mkexpr(t1), getWReg(ws)));
- putWReg(wd,
- binop(Iop_OrV128,
- mkexpr(t2), mkexpr(t3)));
- break;
- }
+ switch (df) {
+ case 0x00: { /* DIV_U.B */
+ DIP("DIV_U.B w%d, w%d, w%d", wd, ws, wt);
+ IRTemp tmp[16];
+ Int i;
+
+ for (i = 0; i < 16; i++) {
+ tmp[i] = newTemp(Ity_I32);
+ assign(tmp[i],
+ binop(Iop_Shl32,
+ binop(Iop_And32,
+ mkU32(0xFF),
+ binop(Iop_DivU32,
+ unop(Iop_8Uto32,
+ binop(Iop_GetElem8x16,
+ mkexpr(t1),
+ mkU8(i))),
+ unop(Iop_8Uto32,
+ binop(Iop_GetElem8x16,
+ mkexpr(t2),
+ mkU8(i))))),
+ mkU8((i & 3) << 3)));
+ }
- default:
- return -1;
+ putWReg(wd,
+ binop(Iop_64HLtoV128,
+ binop(Iop_32HLto64,
+ binop(Iop_Or32,
+ mkexpr(tmp[15]),
+ binop(Iop_Or32,
+ mkexpr(tmp[14]),
+ binop(Iop_Or32,
+ mkexpr(tmp[13]),
+ mkexpr(tmp[12])))),
+ binop(Iop_Or32,
+ mkexpr(tmp[11]),
+ binop(Iop_Or32,
+ mkexpr(tmp[10]),
+ binop(Iop_Or32,
+ mkexpr(tmp[9]),
+ mkexpr(tmp[8]))))),
+ binop(Iop_32HLto64,
+ binop(Iop_Or32,
+ mkexpr(tmp[7]),
+ binop(Iop_Or32,
+ mkexpr(tmp[6]),
+ binop(Iop_Or32,
+ mkexpr(tmp[5]),
+ mkexpr(tmp[4])))),
+ binop(Iop_Or32,
+ mkexpr(tmp[3]),
+ binop(Iop_Or32,
+ mkexpr(tmp[2]),
+ binop(Iop_Or32,
+ mkexpr(tmp[1]),
+ mkexpr(tmp[0]))))))
+ );
+ break;
}
- break;
- }
+ case 0x01: { /* DIV_U.H */
+ DIP("DIV_U.H w%d, w%d, w%d", wd, ws, wt);
+ IRTemp tmp[8];
+ Int i;
- case 0x07: { /* BINSR.df */
- switch (df) {
- case 0x00: { /* BINSR.B */
- DIP("BINSR.B w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- ULong tmp = 0xFEFEFEFEFEFEFEFEULL;
- assign(t1,
- binop(Iop_Shl8x16,
- binop(Iop_64HLtoV128,
- mkU64(tmp), mkU64(tmp)),
- getWReg(wt)));
- assign(t2,
- binop(Iop_AndV128,
- unop(Iop_NotV128, mkexpr(t1)),
- getWReg(ws)));
- assign(t3,
- binop(Iop_AndV128,
- mkexpr(t1), getWReg(wd)));
- putWReg(wd,
- binop(Iop_OrV128,
- mkexpr(t2), mkexpr(t3)));
- break;
- }
+ for (i = 0; i < 8; i++) {
+ tmp[i] = newTemp(Ity_I32);
+ assign(tmp[i],
+ binop(Iop_Shl32,
+ binop(Iop_And32,
+ mkU32(0xFFFF),
+ binop(Iop_DivU32,
+ unop(Iop_16Uto32,
+ binop(Iop_GetElem16x8,
+ mkexpr(t1),
+ mkU8(i))),
+ unop(Iop_16Uto32,
+ binop(Iop_GetElem16x8,
+ mkexpr(t2),
+ mkU8(i))))),
+ mkU8((i & 1) << 4)));
+ }
- case 0x01: { /* BINSR.H */
- DIP("BINSR.H w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- ULong tmp = 0xFFFEFFFEFFFEFFFEULL;
- assign(t1,
- binop(Iop_Shl16x8,
- binop(Iop_64HLtoV128,
- mkU64(tmp), mkU64(tmp)),
- getWReg(wt)));
- assign(t2,
- binop(Iop_AndV128,
- unop(Iop_NotV128, mkexpr(t1)),
- getWReg(ws)));
- assign(t3,
- binop(Iop_AndV128,
- mkexpr(t1), getWReg(wd)));
- putWReg(wd,
- binop(Iop_OrV128,
- mkexpr(t2), mkexpr(t3)));
- break;
- }
+ putWReg(wd,
+ binop(Iop_64HLtoV128,
+ binop(Iop_32HLto64,
+ binop(Iop_Or32,
+ mkexpr(tmp[7]),
+ mkexpr(tmp[6])),
+ binop(Iop_Or32,
+ mkexpr(tmp[5]),
+ mkexpr(tmp[4]))),
+ binop(Iop_32HLto64,
+ binop(Iop_Or32,
+ mkexpr(tmp[3]),
+ mkexpr(tmp[2])),
+ binop(Iop_Or32,
+ mkexpr(tmp[1]),
+ mkexpr(tmp[0])))));
+ break;
+ }
- case 0x02: { /* BINSR.W */
- DIP("BINSR.W w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- ULong tmp = 0xFFFFFFFEFFFFFFFEULL;
- assign(t1,
- binop(Iop_Shl32x4,
- binop(Iop_64HLtoV128,
- mkU64(tmp), mkU64(tmp)),
- getWReg(wt)));
- assign(t2,
- binop(Iop_AndV128,
- unop(Iop_NotV128, mkexpr(t1)),
- getWReg(ws)));
- assign(t3,
- binop(Iop_AndV128,
- mkexpr(t1), getWReg(wd)));
- putWReg(wd,
- binop(Iop_OrV128,
- mkexpr(t2), mkexpr(t3)));
- break;
- }
+ case 0x02: { /* DIV_U.W */
+ DIP("DIV_U.W w%d, w%d, w%d", wd, ws, wt);
+ IRTemp tmp[4];
+ Int i;
- case 0x03: { /* BINSR.D */
- DIP("BINSR.D w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- ULong tmp = -2;
- assign(t1,
- binop(Iop_Shl64x2,
- binop(Iop_64HLtoV128,
- mkU64(tmp), mkU64(tmp)),
- getWReg(wt)));
- assign(t2,
- binop(Iop_AndV128,
- unop(Iop_NotV128, mkexpr(t1)),
- getWReg(ws)));
- assign(t3,
- binop(Iop_AndV128,
- mkexpr(t1), getWReg(wd)));
- putWReg(wd,
- binop(Iop_OrV128,
- mkexpr(t2), mkexpr(t3)));
- break;
- }
+ for (i = 0; i < 4; i++) {
+ tmp[i] = newTemp(Ity_I32);
+ assign(tmp[i],
+ binop(Iop_DivU32,
+ binop(Iop_GetElem32x4,
+ mkexpr(t1), mkU8(i)),
+ binop(Iop_GetElem32x4,
+ mkexpr(t2), mkU8(i))));
+ }
- default:
- return -1;
+ putWReg(wd,
+ binop(Iop_64HLtoV128,
+ binop(Iop_32HLto64,
+ mkexpr(tmp[3]),
+ mkexpr(tmp[2])),
+ binop(Iop_32HLto64,
+ mkexpr(tmp[1]),
+ mkexpr(tmp[0]))));
+ break;
}
- break;
+ case 0x03: { /* DIV_U.D */
+ DIP("DIV_U.D w%d, w%d, w%d", wd, ws, wt);
+ putWReg(wd,
+ binop(Iop_64HLtoV128,
+ binop(Iop_DivU64,
+ unop(Iop_V128HIto64,
+ mkexpr(t1)),
+ unop(Iop_V128HIto64,
+ mkexpr(t2))),
+ binop(Iop_DivU64,
+ unop(Iop_V128to64,
+ mkexpr(t1)),
+ unop(Iop_V128to64,
+ mkexpr(t2)))));
+ break;
+ }
+
+ default:
+ return -1;
}
- default:
- return -1;
- }
+ break;
+ }
- return 0;
-}
+ case 0x06: { /* MOD_S.df */
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
-static Int msa_3R_0E(UInt cins, UChar wd, UChar ws) { /* 3R (0x0E) */
- IRTemp t1, t2, t3, t4;
- UShort operation;
- UChar df, wt;
+ switch (df) {
+ case 0x00: { /* MOD_S.B */
+ DIP("MOD_S.B w%d, w%d, w%d", wd, ws, wt);
+ IRTemp tmp[16];
+ Int i;
+
+ for (i = 0; i < 16; i++) {
+ tmp[i] = newTemp(Ity_I32);
+ assign(tmp[i],
+ binop(Iop_Shl32,
+ binop(Iop_And32,
+ mkU32(0xFF),
+ unop(Iop_64HIto32,
+ binop(Iop_DivModS32to32,
+ unop(Iop_8Sto32,
+ binop(Iop_GetElem8x16,
+ mkexpr(t1),
+ mkU8(i))),
+ unop(Iop_8Sto32,
+ binop(Iop_GetElem8x16,
+ mkexpr(t2),
+ mkU8(i)))))),
+ mkU8((i & 3) << 3)));
+ }
- operation = (cins & 0x03800000) >> 23;
- df = (cins & 0x00600000) >> 21;
- wt = (cins & 0x001F0000) >> 16;
+ putWReg(wd,
+ binop(Iop_64HLtoV128,
+ binop(Iop_32HLto64,
+ binop(Iop_Or32,
+ mkexpr(tmp[15]),
+ binop(Iop_Or32,
+ mkexpr(tmp[14]),
+ binop(Iop_Or32,
+ mkexpr(tmp[13]),
+ mkexpr(tmp[12])))),
+ binop(Iop_Or32,
+ mkexpr(tmp[11]),
+ binop(Iop_Or32,
+ mkexpr(tmp[10]),
+ binop(Iop_Or32,
+ mkexpr(tmp[9]),
+ mkexpr(tmp[8]))))),
+ binop(Iop_32HLto64,
+ binop(Iop_Or32,
+ mkexpr(tmp[7]),
+ binop(Iop_Or32,
+ mkexpr(tmp[6]),
+ binop(Iop_Or32,
+ mkexpr(tmp[5]),
+ mkexpr(tmp[4])))),
+ binop(Iop_Or32,
+ mkexpr(tmp[3]),
+ binop(Iop_Or32,
+ mkexpr(tmp[2]),
+ binop(Iop_Or32,
+ mkexpr(tmp[1]),
+ mkexpr(tmp[0])))))));
+ break;
+ }
- switch (operation) {
- case 0x00: { /* ADDV.df */
- switch (df) {
- case 0x00: { /* ADDV.B */
- DIP("ADDV.B w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3, binop(Iop_Add8x16, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ case 0x01: { /* MOD_S.H */
+ DIP("MOD_S.H w%d, w%d, w%d", wd, ws, wt);
+ IRTemp tmp[8];
+ Int i;
- case 0x01: { /* ADDV.H */
- DIP("ADDV.H w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3, binop(Iop_Add16x8, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ for (i = 0; i < 8; i++) {
+ tmp[i] = newTemp(Ity_I32);
+ assign(tmp[i],
+ binop(Iop_Shl32,
+ binop(Iop_And32,
+ mkU32(0xFFFF),
+ unop(Iop_64HIto32,
+ binop(Iop_DivModS32to32,
+ unop(Iop_16Sto32,
+ binop(Iop_GetElem16x8,
+ mkexpr(t1),
+ mkU8(i))),
+ unop(Iop_16Sto32,
+ binop(Iop_GetElem16x8,
+ mkexpr(t2),
+ mkU8(i)))))),
+ mkU8((i & 1) << 4)));
+ }
- case 0x02: { /* ADDV.W */
- DIP("ADDV.W w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3, binop(Iop_Add32x4, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ putWReg(wd,
+ binop(Iop_64HLtoV128,
+ binop(Iop_32HLto64,
+ binop(Iop_Or32,
+ mkexpr(tmp[7]),
+ mkexpr(tmp[6])),
+ binop(Iop_Or32,
+ mkexpr(tmp[5]),
+ mkexpr(tmp[4]))),
+ binop(Iop_32HLto64,
+ binop(Iop_Or32,
+ mkexpr(tmp[3]),
+ mkexpr(tmp[2])),
+ binop(Iop_Or32,
+ mkexpr(tmp[1]),
+ mkexpr(tmp[0])))));
+ break;
+ }
- case 0x03: { /* ADDV.D */
- DIP("ADDV.D w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3, binop(Iop_Add64x2, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ case 0x02: { /* MOD_S.W */
+ DIP("MOD_S.W w%d, w%d, w%d", wd, ws, wt);
+ IRTemp tmp[4];
+ Int i;
+
+ for (i = 0; i < 4; i++) {
+ tmp[i] = newTemp(Ity_I32);
+ assign(tmp[i],
+ unop(Iop_64HIto32,
+ binop(Iop_DivModS32to32,
+ binop(Iop_GetElem32x4,
+ mkexpr(t1),
+ mkU8(i)),
+ binop(Iop_GetElem32x4,
+ mkexpr(t2),
+ mkU8(i)))));
+ }
- default:
- return -1;
+ putWReg(wd,
+ binop(Iop_64HLtoV128,
+ binop(Iop_32HLto64,
+ mkexpr(tmp[3]),
+ mkexpr(tmp[2])),
+ binop(Iop_32HLto64,
+ mkexpr(tmp[1]),
+ mkexpr(tmp[0]))));
+ break;
}
- break;
- }
+ case 0x03: { /* MOD_S.D */
+ DIP("MOD_S.D w%d, w%d, w%d", wd, ws, wt);
+ t3 = newTemp(Ity_I64);
+ t4 = newTemp(Ity_I64);
+ t5 = newTemp(Ity_I64);
+ t6 = newTemp(Ity_I64);
+ assign(t3, unop(Iop_V128HIto64, mkexpr(t1)));
+ assign(t4, unop(Iop_V128HIto64, mkexpr(t2)));
+ assign(t5, unop(Iop_V128to64, mkexpr(t1)));
+ assign(t6, unop(Iop_V128to64, mkexpr(t2)));
+ putWReg(wd,
+ binop(Iop_64HLtoV128,
+ binop(Iop_Sub64,
+ mkexpr(t3),
+ binop(Iop_Mul64,
+ mkexpr(t4),
+ binop(Iop_DivS64,
+ mkexpr(t3),
+ mkexpr(t4)))),
+ binop(Iop_Sub64,
+ mkexpr(t5),
+ binop(Iop_Mul64,
+ mkexpr(t6),
+ binop(Iop_DivS64,
+ mkexpr(t5),
+ mkexpr(t6))))));
+ break;
+ }
- case 0x01: { /* SUBV.df */
- switch (df) {
- case 0x00: { /* SUBV.B */
- DIP("SUBV.B w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3, binop(Iop_Sub8x16, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ default:
+ return -1;
+ }
- case 0x01: { /* SUBV.H */
- DIP("SUBV.H w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3, binop(Iop_Sub16x8, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ break;
+ }
- case 0x02: { /* SUBV.W */
- DIP("SUBV.W w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3, binop(Iop_Sub32x4, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ case 0x07: { /* MOD_U.df */
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
- case 0x03: { /* SUBV.D */
- DIP("SUBV.D w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3, binop(Iop_Sub64x2, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ switch (df) {
+ case 0x00: { /* MOD_U.B */
+ DIP("MOD_U.B w%d, w%d, w%d", wd, ws, wt);
+ IRTemp tmp[16];
+ Int i;
+
+ for (i = 0; i < 16; i++) {
+ tmp[i] = newTemp(Ity_I32);
+ assign(tmp[i],
+ binop(Iop_Shl32,
+ binop(Iop_And32,
+ mkU32(0xFF),
+ unop(Iop_64HIto32,
+ binop(Iop_DivModU32to32,
+ unop(Iop_8Uto32,
+ binop(Iop_GetElem8x16,
+ mkexpr(t1),
+ mkU8(i))),
+ unop(Iop_8Uto32,
+ binop(Iop_GetElem8x16,
+ mkexpr(t2),
+ mkU8(i)))))),
+ mkU8((i & 3) << 3)));
+ }
- default:
- return -1;
+ putWReg(wd,
+ binop(Iop_64HLtoV128,
+ binop(Iop_32HLto64,
+ binop(Iop_Or32,
+ mkexpr(tmp[15]),
+ binop(Iop_Or32,
+ mkexpr(tmp[14]),
+ binop(Iop_Or32,
+ mkexpr(tmp[13]),
+ mkexpr(tmp[12])))),
+ binop(Iop_Or32,
+ mkexpr(tmp[11]),
+ binop(Iop_Or32,
+ mkexpr(tmp[10]),
+ binop(Iop_Or32,
+ mkexpr(tmp[9]),
+ mkexpr(tmp[8]))))),
+ binop(Iop_32HLto64,
+ binop(Iop_Or32,
+ mkexpr(tmp[7]),
+ binop(Iop_Or32,
+ mkexpr(tmp[6]),
+ binop(Iop_Or32,
+ mkexpr(tmp[5]),
+ mkexpr(tmp[4])))),
+ binop(Iop_Or32,
+ mkexpr(tmp[3]),
+ binop(Iop_Or32,
+ mkexpr(tmp[2]),
+ binop(Iop_Or32,
+ mkexpr(tmp[1]),
+ mkexpr(tmp[0])))))));
+ break;
}
- break;
- }
+ case 0x01: { /* MOD_U.H */
+ DIP("MOD_U.H w%d, w%d, w%d", wd, ws, wt);
+ IRTemp tmp[8];
+ Int i;
- case 0x02: { /* MAX_S.df */
- switch (df) {
- case 0x00: { /* MAX_S.B */
- DIP("MAX_S.B w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3, binop(Iop_Max8Sx16, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ for (i = 0; i < 8; i++) {
+ tmp[i] = newTemp(Ity_I32);
+ assign(tmp[i],
+ binop(Iop_Shl32,
+ binop(Iop_And32,
+ mkU32(0xFFFF),
+ unop(Iop_64HIto32,
+ binop(Iop_DivModU32to32,
+ unop(Iop_16Uto32,
+ binop(Iop_GetElem16x8,
+ mkexpr(t1),
+ mkU8(i))),
+ unop(Iop_16Uto32,
+ binop(Iop_GetElem16x8,
+ mkexpr(t2),
+ mkU8(i)))))),
+ mkU8((i & 1) << 4)));
+ }
- case 0x01: { /* MAX_S.H */
- DIP("MAX_S.H w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3, binop(Iop_Max16Sx8, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ putWReg(wd,
+ binop(Iop_64HLtoV128,
+ binop(Iop_32HLto64,
+ binop(Iop_Or32,
+ mkexpr(tmp[7]),
+ mkexpr(tmp[6])),
+ binop(Iop_Or32,
+ mkexpr(tmp[5]),
+ mkexpr(tmp[4]))),
+ binop(Iop_32HLto64,
+ binop(Iop_Or32,
+ mkexpr(tmp[3]),
+ mkexpr(tmp[2])),
+ binop(Iop_Or32,
+ mkexpr(tmp[1]),
+ mkexpr(tmp[0])))));
+ break;
+ }
- case 0x02: { /* MAX_S.W */
- DIP("MAX_S.W w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3, binop(Iop_Max32Sx4, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ case 0x02: { /* MOD_U.W */
+ DIP("MOD_U.W w%d, w%d, w%d", wd, ws, wt);
+ IRTemp tmp[4];
+ Int i;
+
+ for (i = 0; i < 4; i++) {
+ tmp[i] = newTemp(Ity_I32);
+ assign(tmp[i],
+ unop(Iop_64HIto32,
+ binop(Iop_DivModU32to32,
+ binop(Iop_GetElem32x4,
+ mkexpr(t1),
+ mkU8(i)),
+ binop(Iop_GetElem32x4,
+ mkexpr(t2),
+ mkU8(i)))));
+ }
- case 0x03: { /* MAX_S.D */
- DIP("MAX_S.D w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3, binop(Iop_Max64Sx2, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ putWReg(wd,
+ binop(Iop_64HLtoV128,
+ binop(Iop_32HLto64,
+ mkexpr(tmp[3]),
+ mkexpr(tmp[2])),
+ binop(Iop_32HLto64,
+ mkexpr(tmp[1]),
+ mkexpr(tmp[0]))));
+ break;
+ }
- default:
- return -1;
+ case 0x03: { /* MOD_U.D */
+ DIP("MOD_U.D w%d, w%d, w%d", wd, ws, wt);
+ t3 = newTemp(Ity_I64);
+ t4 = newTemp(Ity_I64);
+ t5 = newTemp(Ity_I64);
+ t6 = newTemp(Ity_I64);
+ assign(t3, unop(Iop_V128HIto64, mkexpr(t1)));
+ assign(t4, unop(Iop_V128HIto64, mkexpr(t2)));
+ assign(t5, unop(Iop_V128to64, mkexpr(t1)));
+ assign(t6, unop(Iop_V128to64, mkexpr(t2)));
+ putWReg(wd,
+ binop(Iop_64HLtoV128,
+ binop(Iop_Sub64,
+ mkexpr(t3),
+ binop(Iop_Mul64,
+ mkexpr(t4),
+ binop(Iop_DivU64,
+ mkexpr(t3),
+ mkexpr(t4)))),
+ binop(Iop_Sub64,
+ mkexpr(t5),
+ binop(Iop_Mul64,
+ mkexpr(t6),
+ binop(Iop_DivU64,
+ mkexpr(t5),
+ mkexpr(t6))))));
+ break;
}
- break;
+ default:
+ return -1;
}
- case 0x03: { /* MAX_U.df */
- switch (df) {
- case 0x00: { /* MAX_U.B */
- DIP("MAX_U.B w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3, binop(Iop_Max8Ux16, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ break;
+ }
- case 0x01: { /* MAX_U.H */
- DIP("MAX_U.H w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3, binop(Iop_Max16Ux8, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ default:
+ return -1;
+ }
- case 0x02: { /* MAX_U.W */
- DIP("MAX_U.W w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3, binop(Iop_Max32Ux4, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ return 0;
+}
- case 0x03: { /* MAX_U.D */
- DIP("MAX_U.D w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3, binop(Iop_Max64Ux2, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+static Int msa_3R_13(UInt cins, UChar wd, UChar ws) /* 3R (0x13) */
+{
+ IRTemp t1, t2;
+ UShort operation;
+ UChar df, wt;
- default:
- return -1;
+ operation = (cins & 0x03800000) >> 23;
+ df = (cins & 0x00600000) >> 21;
+ wt = (cins & 0x001F0000) >> 16;
+
+ switch (operation) {
+ case 0x00: { /* DOTP_S.df */
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+
+ switch (df) {
+ case 0x01: { /* DOTP_S.H */
+ DIP("DOTP_S.H w%d, w%d, w%d", wd, ws, wt);
+ IRTemp tmp[8];
+ Int i;
+
+ for (i = 0; i < 8; i++) {
+ tmp[i] = newTemp(Ity_I16);
+ assign(tmp[i],
+ binop(Iop_Add16,
+ binop(Iop_MullS8,
+ binop(Iop_GetElem8x16,
+ mkexpr(t1),
+ mkU8(2 * i)),
+ binop(Iop_GetElem8x16,
+ mkexpr(t2),
+ mkU8(2 * i))),
+ binop(Iop_MullS8,
+ binop(Iop_GetElem8x16,
+ mkexpr(t1),
+ mkU8(2 * i + 1)),
+ binop(Iop_GetElem8x16,
+ mkexpr(t2),
+ mkU8(2 * i + 1)))));
+ }
+
+ putWReg(wd,
+ binop(Iop_64HLtoV128,
+ binop(Iop_32HLto64,
+ binop(Iop_16HLto32,
+ mkexpr(tmp[7]),
+ mkexpr(tmp[6])),
+ binop(Iop_16HLto32,
+ mkexpr(tmp[5]),
+ mkexpr(tmp[4]))),
+ binop(Iop_32HLto64,
+ binop(Iop_16HLto32,
+ mkexpr(tmp[3]),
+ mkexpr(tmp[2])),
+ binop(Iop_16HLto32,
+ mkexpr(tmp[1]),
+ mkexpr(tmp[0])))));
+ break;
}
- break;
- }
+ case 0x02: { /* DOTP_S.W */
+ DIP("DOTP_S.W w%d, w%d, w%d", wd, ws, wt);
+ IRTemp tmp[4];
+ Int i;
- case 0x04: { /* MIN_S.df */
- switch (df) {
- case 0x00: { /* MIN_S.B */
- DIP("MIN_S.B w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3, binop(Iop_Min8Sx16, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ for (i = 0; i < 4; i++) {
+ tmp[i] = newTemp(Ity_I32);
+ assign(tmp[i],
+ binop(Iop_Add32,
+ binop(Iop_MullS16,
+ binop(Iop_GetElem16x8,
+ mkexpr(t1),
+ mkU8(2 * i)),
+ binop(Iop_GetElem16x8,
+ mkexpr(t2),
+ mkU8(2 * i))),
+ binop(Iop_MullS16,
+ binop(Iop_GetElem16x8,
+ mkexpr(t1),
+ mkU8(2 * i + 1)),
+ binop(Iop_GetElem16x8,
+ mkexpr(t2),
+ mkU8(2 * i + 1)))));
+ }
- case 0x01: { /* MIN_S.H */
- DIP("MIN_S.H w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3, binop(Iop_Min16Sx8, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ putWReg(wd,
+ binop(Iop_64HLtoV128,
+ binop(Iop_32HLto64,
+ mkexpr(tmp[3]),
+ mkexpr(tmp[2])),
+ binop(Iop_32HLto64,
+ mkexpr(tmp[1]),
+ mkexpr(tmp[0]))));
+ break;
+ }
- case 0x02: { /* MIN_S.W */
- DIP("MIN_S.W w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3, binop(Iop_Min32Sx4, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ case 0x03: { /* DOTP_S.D */
+ DIP("DOTP_S.D w%d, w%d, w%d", wd, ws, wt);
+ IRTemp tmp[2];
+ Int i;
- case 0x03: { /* MIN_S.D */
- DIP("MIN_S.D w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3, binop(Iop_Min64Sx2, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ for (i = 0; i < 2; i++) {
+ tmp[i] = newTemp(Ity_I64);
+ assign(tmp[i],
+ binop(Iop_Add64,
+ binop(Iop_MullS32,
+ binop(Iop_GetElem32x4,
+ mkexpr(t1),
+ mkU8(2 * i)),
+ binop(Iop_GetElem32x4,
+ mkexpr(t2),
+ mkU8(2 * i))),
+ binop(Iop_MullS32,
+ binop(Iop_GetElem32x4,
+ mkexpr(t1),
+ mkU8(2 * i + 1)),
+ binop(Iop_GetElem32x4,
+ mkexpr(t2),
+ mkU8(2 * i + 1)))));
+ }
- default:
- return -1;
+ putWReg(wd,
+ binop(Iop_64HLtoV128,
+ mkexpr(tmp[1]), mkexpr(tmp[0])));
+ break;
}
- break;
+ default:
+ return -1;
}
- case 0x05: { /* MIN_U.df */
- switch (df) {
- case 0x00: { /* MIN_U.B */
- DIP("MIN_U.B w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3, binop(Iop_Min8Ux16, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
-
- case 0x01: { /* MIN_U.H */
- DIP("MIN_U.H w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3, binop(Iop_Min16Ux8, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ break;
+ }
- case 0x02: { /* MIN_U.W */
- DIP("MIN_U.W w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3, binop(Iop_Min32Ux4, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ case 0x01: { /* DOTP_U.df */
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
- case 0x03: { /* MIN_U.D */
- DIP("MIN_U.D w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3, binop(Iop_Min64Ux2, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ switch (df) {
+ case 0x01: { /* DOTP_U.H */
+ DIP("DOTP_U.H w%d, w%d, w%d", wd, ws, wt);
+ IRTemp tmp[8];
+ Int i;
+
+ for (i = 0; i < 8; i++) {
+ tmp[i] = newTemp(Ity_I16);
+ assign(tmp[i],
+ binop(Iop_Add16,
+ binop(Iop_MullU8,
+ binop(Iop_GetElem8x16,
+ mkexpr(t1),
+ mkU8(2 * i)),
+ binop(Iop_GetElem8x16,
+ mkexpr(t2),
+ mkU8(2 * i))),
+ binop(Iop_MullU8,
+ binop(Iop_GetElem8x16,
+ mkexpr(t1),
+ mkU8(2 * i + 1)),
+ binop(Iop_GetElem8x16,
+ mkexpr(t2),
+ mkU8(2 * i + 1)))));
+ }
- default:
- return -1;
+ putWReg(wd,
+ binop(Iop_64HLtoV128,
+ binop(Iop_32HLto64,
+ binop(Iop_16HLto32,
+ mkexpr(tmp[7]),
+ mkexpr(tmp[6])),
+ binop(Iop_16HLto32,
+ mkexpr(tmp[5]),
+ mkexpr(tmp[4]))),
+ binop(Iop_32HLto64,
+ binop(Iop_16HLto32,
+ mkexpr(tmp[3]),
+ mkexpr(tmp[2])),
+ binop(Iop_16HLto32,
+ mkexpr(tmp[1]),
+ mkexpr(tmp[0])))));
+ break;
}
- break;
- }
+ case 0x02: { /* DOTP_U.W */
+ DIP("DOTP_U.W w%d, w%d, w%d", wd, ws, wt);
+ IRTemp tmp[4];
+ Int i;
- case 0x06: { /* MAX_A.df */
- switch (df) {
- case 0x00: { /* MAX_A.B */
- DIP("MAX_A.B w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- t4 = newTemp(Ity_V128);
- assign(t1, unop(Iop_Abs8x16, getWReg(ws)));
- assign(t2, unop(Iop_Abs8x16, getWReg(wt)));
- assign(t4, binop(Iop_CmpGT8Ux16, mkexpr(t1), mkexpr(t2)));
- assign(t3, binop(Iop_OrV128,
- binop(Iop_AndV128,
- mkexpr(t4),
- getWReg(ws)),
- binop(Iop_AndV128,
- unop(Iop_NotV128, mkexpr(t4)),
- getWReg(wt))));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ for (i = 0; i < 4; i++) {
+ tmp[i] = newTemp(Ity_I32);
+ assign(tmp[i],
+ binop(Iop_Add32,
+ binop(Iop_MullU16,
+ binop(Iop_GetElem16x8,
+ mkexpr(t1),
+ mkU8(2 * i)),
+ binop(Iop_GetElem16x8,
+ mkexpr(t2),
+ mkU8(2 * i))),
+ binop(Iop_MullU16,
+ binop(Iop_GetElem16x8,
+ mkexpr(t1),
+ mkU8(2 * i + 1)),
+ binop(Iop_GetElem16x8,
+ mkexpr(t2),
+ mkU8(2 * i + 1)))));
+ }
- case 0x01: { /* MAX_A.H */
- DIP("MAX_A.H w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- t4 = newTemp(Ity_V128);
- assign(t1, unop(Iop_Abs16x8, getWReg(ws)));
- assign(t2, unop(Iop_Abs16x8, getWReg(wt)));
- assign(t4, binop(Iop_CmpGT16Ux8, mkexpr(t1), mkexpr(t2)));
- assign(t3, binop(Iop_OrV128,
- binop(Iop_AndV128,
- mkexpr(t4),
- getWReg(ws)),
- binop(Iop_AndV128,
- unop(Iop_NotV128, mkexpr(t4)),
- getWReg(wt))));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ putWReg(wd,
+ binop(Iop_64HLtoV128,
+ binop(Iop_32HLto64,
+ mkexpr(tmp[3]),
+ mkexpr(tmp[2])),
+ binop(Iop_32HLto64,
+ mkexpr(tmp[1]),
+ mkexpr(tmp[0]))));
+ break;
+ }
- case 0x02: { /* MAX_A.W */
- DIP("MAX_A.W w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- t4 = newTemp(Ity_V128);
- assign(t1, unop(Iop_Abs32x4, getWReg(ws)));
- assign(t2, unop(Iop_Abs32x4, getWReg(wt)));
- assign(t4, binop(Iop_CmpGT32Ux4, mkexpr(t1), mkexpr(t2)));
- assign(t3, binop(Iop_OrV128,
- binop(Iop_AndV128,
- mkexpr(t4),
- getWReg(ws)),
- binop(Iop_AndV128,
- unop(Iop_NotV128, mkexpr(t4)),
- getWReg(wt))));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ case 0x03: { /* DOTP_U.D */
+ DIP("DOTP_U.D w%d, w%d, w%d", wd, ws, wt);
+ IRTemp tmp[2];
+ Int i;
- case 0x03: { /* MAX_A.D */
- DIP("MAX_A.D w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- t4 = newTemp(Ity_V128);
- assign(t1, unop(Iop_Abs64x2, getWReg(ws)));
- assign(t2, unop(Iop_Abs64x2, getWReg(wt)));
- assign(t4, binop(Iop_CmpGT64Ux2, mkexpr(t1), mkexpr(t2)));
- assign(t3, binop(Iop_OrV128,
- binop(Iop_AndV128,
- mkexpr(t4),
- getWReg(ws)),
- binop(Iop_AndV128,
- unop(Iop_NotV128, mkexpr(t4)),
- getWReg(wt))));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ for (i = 0; i < 2; i++) {
+ tmp[i] = newTemp(Ity_I64);
+ assign(tmp[i],
+ binop(Iop_Add64,
+ binop(Iop_MullU32,
+ binop(Iop_GetElem32x4,
+ mkexpr(t1),
+ mkU8(2 * i)),
+ binop(Iop_GetElem32x4,
+ mkexpr(t2),
+ mkU8(2 * i))),
+ binop(Iop_MullU32,
+ binop(Iop_GetElem32x4,
+ mkexpr(t1),
+ mkU8(2 * i + 1)),
+ binop(Iop_GetElem32x4,
+ mkexpr(t2),
+ mkU8(2 * i + 1)))));
+ }
- default:
- return -1;
+ putWReg(wd,
+ binop(Iop_64HLtoV128,
+ mkexpr(tmp[1]), mkexpr(tmp[0])));
+ break;
}
- break;
+ default:
+ return -1;
}
- case 0x07: { /* MIN_A.df */
- switch (df) {
- case 0x00: { /* MIN_A.B */
- DIP("MIN_A.B w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- t4 = newTemp(Ity_V128);
- assign(t1, unop(Iop_Abs8x16, getWReg(ws)));
- assign(t2, unop(Iop_Abs8x16, getWReg(wt)));
- assign(t4, binop(Iop_OrV128,
- binop(Iop_CmpGT8Ux16,
- mkexpr(t1), mkexpr(t2)),
- binop(Iop_CmpEQ8x16,
- mkexpr(t1), mkexpr(t2))));
- assign(t3, binop(Iop_OrV128,
- binop(Iop_AndV128,
- mkexpr(t4),
- getWReg(wt)),
- binop(Iop_AndV128,
- unop(Iop_NotV128, mkexpr(t4)),
- getWReg(ws))));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ break;
+ }
- case 0x01: { /* MIN_A.H */
- DIP("MIN_A.H w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- t4 = newTemp(Ity_V128);
- assign(t1, unop(Iop_Abs16x8, getWReg(ws)));
- assign(t2, unop(Iop_Abs16x8, getWReg(wt)));
- assign(t4, binop(Iop_OrV128,
- binop(Iop_CmpGT16Ux8,
- mkexpr(t1), mkexpr(t2)),
- binop(Iop_CmpEQ16x8,
- mkexpr(t1), mkexpr(t2))));
- assign(t3, binop(Iop_OrV128,
- binop(Iop_AndV128,
- mkexpr(t4),
- getWReg(wt)),
- binop(Iop_AndV128,
- unop(Iop_NotV128, mkexpr(t4)),
- getWReg(ws))));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ case 0x02: { /* DPADD_S.df */
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
- case 0x02: { /* MIN_A.W */
- DIP("MIN_A.W w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- t4 = newTemp(Ity_V128);
- assign(t1, unop(Iop_Abs32x4, getWReg(ws)));
- assign(t2, unop(Iop_Abs32x4, getWReg(wt)));
- assign(t4, binop(Iop_OrV128,
- binop(Iop_CmpGT32Ux4,
- mkexpr(t1), mkexpr(t2)),
- binop(Iop_CmpEQ32x4,
- mkexpr(t1), mkexpr(t2))));
- assign(t3, binop(Iop_OrV128,
- binop(Iop_AndV128,
- mkexpr(t4),
- getWReg(wt)),
- binop(Iop_AndV128,
- unop(Iop_NotV128, mkexpr(t4)),
- getWReg(ws))));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ switch (df) {
+ case 0x01: { /* DPADD_S.H */
+ DIP("DPADD_S.H w%d, w%d, w%d", wd, ws, wt);
+ IRTemp tmp[8];
+ Int i;
+
+ for (i = 0; i < 8; i++) {
+ tmp[i] = newTemp(Ity_I16);
+ assign(tmp[i],
+ binop(Iop_Add16,
+ binop(Iop_MullS8,
+ binop(Iop_GetElem8x16,
+ mkexpr(t1),
+ mkU8(2 * i)),
+ binop(Iop_GetElem8x16,
+ mkexpr(t2),
+ mkU8(2 * i))),
+ binop(Iop_MullS8,
+ binop(Iop_GetElem8x16,
+ mkexpr(t1),
+ mkU8(2 * i + 1)),
+ binop(Iop_GetElem8x16,
+ mkexpr(t2),
+ mkU8(2 * i + 1)))));
+ }
- case 0x03: { /* MIN_A.D */
- DIP("MIN_A.D w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- t4 = newTemp(Ity_V128);
- assign(t1, unop(Iop_Abs64x2, getWReg(ws)));
- assign(t2, unop(Iop_Abs64x2, getWReg(wt)));
- assign(t4, binop(Iop_OrV128,
- binop(Iop_CmpGT64Ux2,
- mkexpr(t1), mkexpr(t2)),
- binop(Iop_CmpEQ64x2,
- mkexpr(t1), mkexpr(t2))));
- assign(t3, binop(Iop_OrV128,
- binop(Iop_AndV128,
- mkexpr(t4),
- getWReg(wt)),
- binop(Iop_AndV128,
- unop(Iop_NotV128, mkexpr(t4)),
- getWReg(ws))));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ putWReg(wd,
+ binop(Iop_Add16x8,
+ getWReg(wd),
+ binop(Iop_64HLtoV128,
+ binop(Iop_32HLto64,
+ binop(Iop_16HLto32,
+ mkexpr(tmp[7]),
+ mkexpr(tmp[6])),
+ binop(Iop_16HLto32,
+ mkexpr(tmp[5]),
+ mkexpr(tmp[4]))),
+ binop(Iop_32HLto64,
+ binop(Iop_16HLto32,
+ mkexpr(tmp[3]),
+ mkexpr(tmp[2])),
+ binop(Iop_16HLto32,
+ mkexpr(tmp[1]),
+ mkexpr(tmp[0]))))));
+ break;
+ }
- default:
- return -1;
+ case 0x02: { /* DPADD_S.W */
+ DIP("DPADD_S.W w%d, w%d, w%d", wd, ws, wt);
+ IRTemp tmp[4];
+ Int i;
+
+ for (i = 0; i < 4; i++) {
+ tmp[i] = newTemp(Ity_I32);
+ assign(tmp[i],
+ binop(Iop_Add32,
+ binop(Iop_MullS16,
+ binop(Iop_GetElem16x8,
+ mkexpr(t1),
+ mkU8(2 * i)),
+ binop(Iop_GetElem16x8,
+ mkexpr(t2),
+ mkU8(2 * i))),
+ binop(Iop_MullS16,
+ binop(Iop_GetElem16x8,
+ mkexpr(t1),
+ mkU8(2 * i + 1)),
+ binop(Iop_GetElem16x8,
+ mkexpr(t2),
+ mkU8(2 * i + 1)))));
+ }
+
+ putWReg(wd,
+ binop(Iop_Add32x4,
+ getWReg(wd),
+ binop(Iop_64HLtoV128,
+ binop(Iop_32HLto64,
+ mkexpr(tmp[3]),
+ mkexpr(tmp[2])),
+ binop(Iop_32HLto64,
+ mkexpr(tmp[1]),
+ mkexpr(tmp[0])))));
+ break;
}
- break;
+ case 0x03: { /* DPADD_S.D */
+ DIP("DPADD_S.D w%d, w%d, w%d", wd, ws, wt);
+ IRTemp tmp[2];
+ Int i;
+
+ for (i = 0; i < 2; i++) {
+ tmp[i] = newTemp(Ity_I64);
+ assign(tmp[i],
+ binop(Iop_Add64,
+ binop(Iop_MullS32,
+ binop(Iop_GetElem32x4,
+ mkexpr(t1),
+ mkU8(2 * i)),
+ binop(Iop_GetElem32x4,
+ mkexpr(t2),
+ mkU8(2 * i))),
+ binop(Iop_MullS32,
+ binop(Iop_GetElem32x4,
+ mkexpr(t1),
+ mkU8(2 * i + 1)),
+ binop(Iop_GetElem32x4,
+ mkexpr(t2),
+ mkU8(2 * i + 1)))));
+ }
+
+ putWReg(wd,
+ binop(Iop_Add64x2,
+ getWReg(wd),
+ binop(Iop_64HLtoV128,
+ mkexpr(tmp[1]),
+ mkexpr(tmp[0]))));
+ break;
+ }
+
+ default:
+ return -1;
}
- default:
- return -1;
- }
+ break;
+ }
- return 0;
-}
+ case 0x03: { /* DPADD_U.df */
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
-static Int msa_3R_0F(UInt cins, UChar wd, UChar ws) { /* 3R (0x0F) */
- IRTemp t1, t2, t3;
- UShort operation;
- UChar df, wt;
+ switch (df) {
+ case 0x01: { /* DPADD_U.H */
+ DIP("DPADD_U.H w%d, w%d, w%d", wd, ws, wt);
+ IRTemp tmp[8];
+ Int i;
+
+ for (i = 0; i < 8; i++) {
+ tmp[i] = newTemp(Ity_I16);
+ assign(tmp[i],
+ binop(Iop_Add16,
+ binop(Iop_MullU8,
+ binop(Iop_GetElem8x16,
+ mkexpr(t1),
+ mkU8(2 * i)),
+ binop(Iop_GetElem8x16,
+ mkexpr(t2),
+ mkU8(2 * i))),
+ binop(Iop_MullU8,
+ binop(Iop_GetElem8x16,
+ mkexpr(t1),
+ mkU8(2 * i + 1)),
+ binop(Iop_GetElem8x16,
+ mkexpr(t2),
+ mkU8(2 * i + 1)))));
+ }
- operation = (cins & 0x03800000) >> 23;
- df = (cins & 0x00600000) >> 21;
- wt = (cins & 0x001F0000) >> 16;
+ putWReg(wd,
+ binop(Iop_Add16x8,
+ getWReg(wd),
+ binop(Iop_64HLtoV128,
+ binop(Iop_32HLto64,
+ binop(Iop_16HLto32,
+ mkexpr(tmp[7]),
+ mkexpr(tmp[6])),
+ binop(Iop_16HLto32,
+ mkexpr(tmp[5]),
+ mkexpr(tmp[4]))),
+ binop(Iop_32HLto64,
+ binop(Iop_16HLto32,
+ mkexpr(tmp[3]),
+ mkexpr(tmp[2])),
+ binop(Iop_16HLto32,
+ mkexpr(tmp[1]),
+ mkexpr(tmp[0]))))));
+ break;
+ }
- switch (operation) {
- case 0x00: { /* CEQ.df */
- switch (df) {
- case 0x00: { /* CEQ.B */
- DIP("CEQ.B w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3, binop(Iop_CmpEQ8x16, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ case 0x02: { /* DPADD_U.W */
+ DIP("DPADD_U.W w%d, w%d, w%d", wd, ws, wt);
+ IRTemp tmp[4];
+ Int i;
- case 0x01: { /* CEQ.H */
- DIP("CEQ.H w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3, binop(Iop_CmpEQ16x8, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ for (i = 0; i < 4; i++) {
+ tmp[i] = newTemp(Ity_I32);
+ assign(tmp[i],
+ binop(Iop_Add32,
+ binop(Iop_MullU16,
+ binop(Iop_GetElem16x8,
+ mkexpr(t1),
+ mkU8(2 * i)),
+ binop(Iop_GetElem16x8,
+ mkexpr(t2),
+ mkU8(2 * i))),
+ binop(Iop_MullU16,
+ binop(Iop_GetElem16x8,
+ mkexpr(t1),
+ mkU8(2 * i + 1)),
+ binop(Iop_GetElem16x8,
+ mkexpr(t2),
+ mkU8(2 * i + 1)))));
+ }
- case 0x02: { /* CEQ.W */
- DIP("CEQ.W w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3, binop(Iop_CmpEQ32x4, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ putWReg(wd,
+ binop(Iop_Add32x4,
+ getWReg(wd),
+ binop(Iop_64HLtoV128,
+ binop(Iop_32HLto64,
+ mkexpr(tmp[3]),
+ mkexpr(tmp[2])),
+ binop(Iop_32HLto64,
+ mkexpr(tmp[1]),
+ mkexpr(tmp[0])))));
+ break;
+ }
- case 0x03: { /* CEQ.D */
- DIP("CEQ.D w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3, binop(Iop_CmpEQ64x2, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ case 0x03: { /* DPADD_U.D */
+ DIP("DPADD_U.D w%d, w%d, w%d", wd, ws, wt);
+ IRTemp tmp[2];
+ Int i;
- default:
- return -1;
+ for (i = 0; i < 2; i++) {
+ tmp[i] = newTemp(Ity_I64);
+ assign(tmp[i],
+ binop(Iop_Add64,
+ binop(Iop_MullU32,
+ binop(Iop_GetElem32x4,
+ mkexpr(t1),
+ mkU8(2 * i)),
+ binop(Iop_GetElem32x4,
+ mkexpr(t2),
+ mkU8(2 * i))),
+ binop(Iop_MullU32,
+ binop(Iop_GetElem32x4,
+ mkexpr(t1),
+ mkU8(2 * i + 1)),
+ binop(Iop_GetElem32x4,
+ mkexpr(t2),
+ mkU8(2 * i + 1)))));
+ }
+
+ putWReg(wd,
+ binop(Iop_Add64x2,
+ getWReg(wd),
+ binop(Iop_64HLtoV128,
+ mkexpr(tmp[1]),
+ mkexpr(tmp[0]))));
+ break;
}
- break;
+ default:
+ return -1;
}
- case 0x02: { /* CLT_S.df */
- switch (df) {
- case 0x00: { /* CLT_S.B */
- DIP("CLT_S.B w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3, binop(Iop_CmpGT8Sx16, mkexpr(t2), mkexpr(t1)));
- putWReg(wd, mkexpr(t3));
- break;
- }
-
- case 0x01: { /* CLT_S.H */
- DIP("CLT_S.H w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3, binop(Iop_CmpGT16Sx8, mkexpr(t2), mkexpr(t1)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ break;
+ }
- case 0x02: { /* CLT_S.W */
- DIP("CLT_S.W w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3, binop(Iop_CmpGT32Sx4, mkexpr(t2), mkexpr(t1)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ case 0x04: { /* DPSUB_S.df */
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
- case 0x03: { /* CLT_S.D */
- DIP("CLT_S.D w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3, binop(Iop_CmpGT64Sx2, mkexpr(t2), mkexpr(t1)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ switch (df) {
+ case 0x01: { /* DPSUB_S.H */
+ DIP("DPSUB_S.H w%d, w%d, w%d", wd, ws, wt);
+ IRTemp tmp[8];
+ Int i;
+
+ for (i = 0; i < 8; i++) {
+ tmp[i] = newTemp(Ity_I16);
+ assign(tmp[i],
+ binop(Iop_Add16,
+ binop(Iop_MullS8,
+ binop(Iop_GetElem8x16,
+ mkexpr(t1),
+ mkU8(2 * i)),
+ binop(Iop_GetElem8x16,
+ mkexpr(t2),
+ mkU8(2 * i))),
+ binop(Iop_MullS8,
+ binop(Iop_GetElem8x16,
+ mkexpr(t1),
+ mkU8(2 * i + 1)),
+ binop(Iop_GetElem8x16,
+ mkexpr(t2),
+ mkU8(2 * i + 1)))));
+ }
- default:
- return -1;
+ putWReg(wd,
+ binop(Iop_Sub16x8,
+ getWReg(wd),
+ binop(Iop_64HLtoV128,
+ binop(Iop_32HLto64,
+ binop(Iop_16HLto32,
+ mkexpr(tmp[7]),
+ mkexpr(tmp[6])),
+ binop(Iop_16HLto32,
+ mkexpr(tmp[5]),
+ mkexpr(tmp[4]))),
+ binop(Iop_32HLto64,
+ binop(Iop_16HLto32,
+ mkexpr(tmp[3]),
+ mkexpr(tmp[2])),
+ binop(Iop_16HLto32,
+ mkexpr(tmp[1]),
+ mkexpr(tmp[0]))))));
+ break;
}
- break;
- }
+ case 0x02: { /* DPSUB_S.W */
+ DIP("DPSUB_S.W w%d, w%d, w%d", wd, ws, wt);
+ IRTemp tmp[4];
+ Int i;
- case 0x03: { /* CLT_U.df */
- switch (df) {
- case 0x00: { /* CLT_U.B */
- DIP("CLT_U.B w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3, binop(Iop_CmpGT8Ux16, mkexpr(t2), mkexpr(t1)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ for (i = 0; i < 4; i++) {
+ tmp[i] = newTemp(Ity_I32);
+ assign(tmp[i],
+ binop(Iop_Add32,
+ binop(Iop_MullS16,
+ binop(Iop_GetElem16x8,
+ mkexpr(t1),
+ mkU8(2 * i)),
+ binop(Iop_GetElem16x8,
+ mkexpr(t2),
+ mkU8(2 * i))),
+ binop(Iop_MullS16,
+ binop(Iop_GetElem16x8,
+ mkexpr(t1),
+ mkU8(2 * i + 1)),
+ binop(Iop_GetElem16x8,
+ mkexpr(t2),
+ mkU8(2 * i + 1)))));
+ }
- case 0x01: { /* CLT_U.H */
- DIP("CLT_U.H w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3, binop(Iop_CmpGT16Ux8, mkexpr(t2), mkexpr(t1)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ putWReg(wd,
+ binop(Iop_Sub32x4,
+ getWReg(wd),
+ binop(Iop_64HLtoV128,
+ binop(Iop_32HLto64,
+ mkexpr(tmp[3]),
+ mkexpr(tmp[2])),
+ binop(Iop_32HLto64,
+ mkexpr(tmp[1]),
+ mkexpr(tmp[0])))));
+ break;
+ }
- case 0x02: { /* CLT_U.W */
- DIP("CLT_U.W w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3, binop(Iop_CmpGT32Ux4, mkexpr(t2), mkexpr(t1)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ case 0x03: { /* DPSUB_S.D */
+ DIP("DPSUB_S.D w%d, w%d, w%d", wd, ws, wt);
+ IRTemp tmp[2];
+ Int i;
- case 0x03: { /* CLT_U.D */
- DIP("CLT_U.D w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3, binop(Iop_CmpGT64Ux2, mkexpr(t2), mkexpr(t1)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ for (i = 0; i < 2; i++) {
+ tmp[i] = newTemp(Ity_I64);
+ assign(tmp[i],
+ binop(Iop_Add64,
+ binop(Iop_MullS32,
+ binop(Iop_GetElem32x4,
+ mkexpr(t1),
+ mkU8(2 * i)),
+ binop(Iop_GetElem32x4,
+ mkexpr(t2),
+ mkU8(2 * i))),
+ binop(Iop_MullS32,
+ binop(Iop_GetElem32x4,
+ mkexpr(t1),
+ mkU8(2 * i + 1)),
+ binop(Iop_GetElem32x4,
+ mkexpr(t2),
+ mkU8(2 * i + 1)))));
+ }
- default:
- return -1;
+ putWReg(wd,
+ binop(Iop_Sub64x2,
+ getWReg(wd),
+ binop(Iop_64HLtoV128,
+ mkexpr(tmp[1]),
+ mkexpr(tmp[0]))));
+ break;
}
- break;
+ default:
+ return -1;
}
- case 0x04: { /* CLE_S.df */
- switch (df) {
- case 0x00: { /* CLE_S.B */
- DIP("CLE_S.B w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3, binop(Iop_OrV128,
- binop(Iop_CmpGT8Sx16,
- mkexpr(t2), mkexpr(t1)),
- binop(Iop_CmpEQ8x16,
- mkexpr(t1), mkexpr(t2))));
- putWReg(wd, mkexpr(t3));
- break;
- }
-
- case 0x01: { /* CLE_S.H */
- DIP("CLE_S.H w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3, binop(Iop_OrV128,
- binop(Iop_CmpGT16Sx8,
- mkexpr(t2), mkexpr(t1)),
- binop(Iop_CmpEQ16x8,
- mkexpr(t1), mkexpr(t2))));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ break;
+ }
- case 0x02: { /* CLE_S.W */
- DIP("CLE_S.W w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3, binop(Iop_OrV128,
- binop(Iop_CmpGT32Sx4,
- mkexpr(t2), mkexpr(t1)),
- binop(Iop_CmpEQ32x4,
- mkexpr(t1), mkexpr(t2))));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ case 0x05: { /* DPSUB_U.df */
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
- case 0x03: { /* CLE_S.D */
- DIP("CLE_S.D w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3, binop(Iop_OrV128,
- binop(Iop_CmpGT64Sx2,
- mkexpr(t2), mkexpr(t1)),
- binop(Iop_CmpEQ64x2,
- mkexpr(t1), mkexpr(t2))));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ switch (df) {
+ case 0x01: { /* DPSUB_U.H */
+ DIP("DPSUB_U.H w%d, w%d, w%d", wd, ws, wt);
+ IRTemp tmp[8];
+ Int i;
+
+ for (i = 0; i < 8; i++) {
+ tmp[i] = newTemp(Ity_I16);
+ assign(tmp[i],
+ binop(Iop_Add16,
+ binop(Iop_MullU8,
+ binop(Iop_GetElem8x16,
+ mkexpr(t1),
+ mkU8(2 * i)),
+ binop(Iop_GetElem8x16,
+ mkexpr(t2),
+ mkU8(2 * i))),
+ binop(Iop_MullU8,
+ binop(Iop_GetElem8x16,
+ mkexpr(t1),
+ mkU8(2 * i + 1)),
+ binop(Iop_GetElem8x16,
+ mkexpr(t2),
+ mkU8(2 * i + 1)))));
+ }
- default:
- return -1;
+ putWReg(wd,
+ binop(Iop_Sub16x8,
+ getWReg(wd),
+ binop(Iop_64HLtoV128,
+ binop(Iop_32HLto64,
+ binop(Iop_16HLto32,
+ mkexpr(tmp[7]),
+ mkexpr(tmp[6])),
+ binop(Iop_16HLto32,
+ mkexpr(tmp[5]),
+ mkexpr(tmp[4]))),
+ binop(Iop_32HLto64,
+ binop(Iop_16HLto32,
+ mkexpr(tmp[3]),
+ mkexpr(tmp[2])),
+ binop(Iop_16HLto32,
+ mkexpr(tmp[1]),
+ mkexpr(tmp[0]))))));
+ break;
}
- break;
- }
+ case 0x02: { /* DPSUB_U.W */
+ DIP("DPSUB_U.W w%d, w%d, w%d", wd, ws, wt);
+ IRTemp tmp[4];
+ Int i;
- case 0x05: { /* CLE_U.df */
- switch (df) {
- case 0x00: { /* CLE_U.B */
- DIP("CLE_U.B w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3, binop(Iop_OrV128,
- binop(Iop_CmpGT8Ux16,
- mkexpr(t2), mkexpr(t1)),
- binop(Iop_CmpEQ8x16,
- mkexpr(t1), mkexpr(t2))));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ for (i = 0; i < 4; i++) {
+ tmp[i] = newTemp(Ity_I32);
+ assign(tmp[i],
+ binop(Iop_Add32,
+ binop(Iop_MullU16,
+ binop(Iop_GetElem16x8,
+ mkexpr(t1),
+ mkU8(2 * i)),
+ binop(Iop_GetElem16x8,
+ mkexpr(t2),
+ mkU8(2 * i))),
+ binop(Iop_MullU16,
+ binop(Iop_GetElem16x8,
+ mkexpr(t1),
+ mkU8(2 * i + 1)),
+ binop(Iop_GetElem16x8,
+ mkexpr(t2),
+ mkU8(2 * i + 1)))));
+ }
- case 0x01: { /* CLE_U.H */
- DIP("CLE_U.H w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3, binop(Iop_OrV128,
- binop(Iop_CmpGT16Ux8,
- mkexpr(t2), mkexpr(t1)),
- binop(Iop_CmpEQ16x8,
- mkexpr(t1), mkexpr(t2))));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ putWReg(wd,
+ binop(Iop_Sub32x4,
+ getWReg(wd),
+ binop(Iop_64HLtoV128,
+ binop(Iop_32HLto64,
+ mkexpr(tmp[3]),
+ mkexpr(tmp[2])),
+ binop(Iop_32HLto64,
+ mkexpr(tmp[1]),
+ mkexpr(tmp[0])))));
+ break;
+ }
- case 0x02: { /* CLE_U.W */
- DIP("CLE_U.W w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3, binop(Iop_OrV128,
- binop(Iop_CmpGT32Ux4,
- mkexpr(t2), mkexpr(t1)),
- binop(Iop_CmpEQ32x4,
- mkexpr(t1), mkexpr(t2))));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ case 0x03: { /* DPSUB_U.D */
+ DIP("DPSUB_U.D w%d, w%d, w%d", wd, ws, wt);
+ IRTemp tmp[2];
+ Int i;
- case 0x03: { /* CLE_U.D */
- DIP("CLE_U.D w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3,
- binop(Iop_OrV128,
- binop(Iop_CmpGT64Ux2,
- mkexpr(t2), mkexpr(t1)),
- binop(Iop_CmpEQ64x2,
- mkexpr(t1), mkexpr(t2))));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ for (i = 0; i < 2; i++) {
+ tmp[i] = newTemp(Ity_I64);
+ assign(tmp[i],
+ binop(Iop_Add64,
+ binop(Iop_MullU32,
+ binop(Iop_GetElem32x4,
+ mkexpr(t1),
+ mkU8(2 * i)),
+ binop(Iop_GetElem32x4,
+ mkexpr(t2),
+ mkU8(2 * i))),
+ binop(Iop_MullU32,
+ binop(Iop_GetElem32x4,
+ mkexpr(t1),
+ mkU8(2 * i + 1)),
+ binop(Iop_GetElem32x4,
+ mkexpr(t2),
+ mkU8(2 * i + 1)))));
+ }
- default:
- return -1;
+ putWReg(wd,
+ binop(Iop_Sub64x2,
+ getWReg(wd),
+ binop(Iop_64HLtoV128,
+ mkexpr(tmp[1]),
+ mkexpr(tmp[0]))));
+ break;
}
- break;
+ default:
+ return -1;
}
+ break;
+ }
+
default:
return -1;
}
return 0;
}
-static Int msa_3R_10(UInt cins, UChar wd, UChar ws) { /* 3R (0x10) */
- IRTemp t1, t2, t3, t4;
- UShort operation;
- UChar df, wt;
-
- operation = (cins & 0x03800000) >> 23;
- df = (cins & 0x00600000) >> 21;
- wt = (cins & 0x001F0000) >> 16;
-
- switch (operation) {
- case 0x00: { /* ADD_A.df */
- switch (df) {
- case 0x00: { /* ADD_A.B */
- DIP("ADD_A.B w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, unop(Iop_Abs8x16, getWReg(ws)));
- assign(t2, unop(Iop_Abs8x16, getWReg(wt)));
- assign(t3, binop(Iop_Add8x16, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+static Int msa_3R_14(UInt cins, UChar wd, UChar ws) /* 3R (0x14) */
+{
+ IRTemp t1, t2, t3, t4;
+ IRType ty;
+ UShort operation;
+ UChar df, wt;
- case 0x01: { /* ADD_A.H */
- DIP("ADD_A.H w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, unop(Iop_Abs16x8, getWReg(ws)));
- assign(t2, unop(Iop_Abs16x8, getWReg(wt)));
- assign(t3, binop(Iop_Add16x8, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ operation = (cins & 0x03800000) >> 23;
+ df = (cins & 0x00600000) >> 21;
+ wt = (cins & 0x001F0000) >> 16;
+ ty = mode64 ? Ity_I64 : Ity_I32;
- case 0x02: { /* ADD_A.W */
- DIP("ADD_A.W w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, unop(Iop_Abs32x4, getWReg(ws)));
- assign(t2, unop(Iop_Abs32x4, getWReg(wt)));
- assign(t3, binop(Iop_Add32x4, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ switch (operation) {
+ case 0x00: { /* SLD.df */
+ switch (df) {
+ case 0x00: {
+ DIP("SLD.B w%d, w%d[%d]", wd, ws, wt);
+ t1 = newTemp(Ity_I32);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1,
+ binop(Iop_Shl32,
+ binop(Iop_And32,
+ mkNarrowTo32(ty,
+ getIReg(wt)),
+ mkU32(15)),
+ mkU8(3)));
+ assign(t2,
+ binop(Iop_ShrV128,
+ getWReg(ws),
+ unop(Iop_32to8, mkexpr(t1))));
+ assign(t3,
+ binop(Iop_ShlV128,
+ getWReg(wd),
+ unop(Iop_32to8,
+ binop(Iop_Sub32,
+ mkU32(128),
+ mkexpr(t1)))));
+ putWReg(wd,
+ binop(Iop_OrV128,
+ mkexpr(t2), mkexpr(t3)));
+ break;
+ }
- case 0x03: { /* ADD_A.D */
- DIP("ADD_A.D w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, unop(Iop_Abs64x2, getWReg(ws)));
- assign(t2, unop(Iop_Abs64x2, getWReg(wt)));
- assign(t3, binop(Iop_Add64x2, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ case 0x01: {/* SLD.H */
+ DIP("SLD.H w%d, w%d[%d]", wd, ws, wt);
+ t1 = newTemp(Ity_I32);
+ t2 = newTemp(Ity_I64);
+ t3 = newTemp(Ity_V128);
+ t4 = newTemp(Ity_V128);
+ assign(t1,
+ binop(Iop_Shl32,
+ binop(Iop_And32,
+ mkNarrowTo32(ty,
+ getIReg(wt)),
+ mkU32(7)),
+ mkU8(3)));
+ assign(t2,
+ binop(Iop_32HLto64, mkU32(0), mkexpr(t1)));
+ assign(t3,
+ binop(Iop_Shr64x2,
+ getWReg(ws),
+ binop(Iop_64HLtoV128,
+ mkexpr(t2), mkexpr(t2))));
+ assign(t4,
+ binop(Iop_Shl64x2,
+ getWReg(wd),
+ binop(Iop_Sub64x2,
+ binop(Iop_64HLtoV128,
+ mkU64(0x40ul),
+ mkU64(0x40ul)),
+ binop(Iop_64HLtoV128,
+ mkexpr(t2),
+ mkexpr(t2)))));
+ putWReg(wd,
+ binop(Iop_OrV128,
+ mkexpr(t3),
+ IRExpr_ITE(
+ binop(Iop_CmpNE32,
+ mkexpr(t1), mkU32(0)),
+ mkexpr(t4),
+ binop(Iop_64HLtoV128,
+ mkU64(0), mkU64(0)))));
+ break;
+ }
- default:
- return -1;
+ case 0x02: {/* SLD.W */
+ DIP("SLD.W w%d, w%d[%d]", wd, ws, wt);
+ t1 = newTemp(Ity_I32);
+ t2 = newTemp(Ity_I64);
+ t3 = newTemp(Ity_V128);
+ t4 = newTemp(Ity_V128);
+ assign(t1,
+ binop(Iop_Shl32,
+ binop(Iop_And32,
+ mkNarrowTo32(ty,
+ getIReg(wt)),
+ mkU32(3)),
+ mkU8(3)));
+ assign(t2,
+ binop(Iop_32HLto64,
+ mkexpr(t1), mkexpr(t1)));
+ assign(t3,
+ binop(Iop_Shr32x4,
+ getWReg(ws),
+ binop(Iop_64HLtoV128,
+ mkexpr(t2), mkexpr(t2))));
+ assign(t4,
+ binop(Iop_Shl32x4,
+ getWReg(wd),
+ binop(Iop_Sub32x4,
+ binop(Iop_64HLtoV128,
+ mkU64(0x2000000020ul),
+ mkU64(0x2000000020ul)),
+ binop(Iop_64HLtoV128,
+ mkexpr(t2),
+ mkexpr(t2)))));
+ putWReg(wd,
+ binop(Iop_OrV128,
+ mkexpr(t3),
+ IRExpr_ITE(
+ binop(Iop_CmpNE32,
+ mkexpr(t1), mkU32(0)),
+ mkexpr(t4),
+ binop(Iop_64HLtoV128,
+ mkU64(0), mkU64(0)))));
+ break;
}
- break;
+ case 0x03: { /* SLD.D */
+ DIP("SLD.D w%d, w%d[%d]", wd, ws, wt);
+ t1 = newTemp(Ity_I32);
+ t2 = newTemp(Ity_I64);
+ t3 = newTemp(Ity_V128);
+ t4 = newTemp(Ity_V128);
+ assign(t1,
+ binop(Iop_Shl32,
+ binop(Iop_And32,
+ mkNarrowTo32(ty,
+ getIReg(wt)),
+ mkU32(1)),
+ mkU8(3)));
+ assign(t2,
+ binop(Iop_32HLto64,
+ binop(Iop_Or32,
+ mkexpr(t1),
+ binop(Iop_Shl32,
+ mkexpr(t1), mkU8(16))),
+ binop(Iop_Or32,
+ mkexpr(t1),
+ binop(Iop_Shl32,
+ mkexpr(t1), mkU8(16)))));
+ assign(t3,
+ binop(Iop_Shr16x8,
+ getWReg(ws),
+ binop(Iop_64HLtoV128,
+ mkexpr(t2), mkexpr(t2))));
+ assign(t4,
+ binop(Iop_Shl16x8,
+ getWReg(wd),
+ binop(Iop_Sub16x8,
+ binop(Iop_64HLtoV128,
+ mkU64(0x10001000100010ul),
+ mkU64(0x10001000100010ul)),
+ binop(Iop_64HLtoV128,
+ mkexpr(t2),
+ mkexpr(t2)))));
+ putWReg(wd,
+ binop(Iop_OrV128,
+ mkexpr(t3),
+ IRExpr_ITE(
+ binop(Iop_CmpNE32,
+ mkexpr(t1), mkU32(0)),
+ mkexpr(t4),
+ binop(Iop_64HLtoV128,
+ mkU64(0), mkU64(0)))));
+ break;
+ }
}
- case 0x01: { /* ADDS_A.df */
- switch (df) {
- case 0x00: { /* ADDS_A.B */
- DIP("ADDS_A.B w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- t4 = newTemp(Ity_V128);
- assign(t1, unop(Iop_Abs8x16, getWReg(ws)));
- assign(t2, unop(Iop_Abs8x16, getWReg(wt)));
- assign(t3, binop(Iop_SarN8x16,
- binop(Iop_AndV128,
- mkexpr(t1),
- getWReg(ws)),
- mkU8(7)));
- assign(t4, binop(Iop_SarN8x16,
- binop(Iop_AndV128,
- mkexpr(t2),
- getWReg(wt)),
- mkU8(7)));
- putWReg(wd, binop(Iop_QAdd8Sx16,
- binop(Iop_OrV128,
- binop(Iop_AndV128,
- unop(Iop_NotV128,
- mkexpr(t3)),
- mkexpr(t1)),
- binop(Iop_AndV128,
- unop(Iop_NotV128,
- mkexpr(t1)),
- mkexpr(t3))),
- binop(Iop_OrV128,
- binop(Iop_AndV128,
- unop(Iop_NotV128,
- mkexpr(t4)),
- mkexpr(t2)),
- binop(Iop_AndV128,
- unop(Iop_NotV128,
- mkexpr(t2)),
- mkexpr(t4)))));
- break;
- }
+ break;
+ }
- case 0x01: { /* ADDS_A.H */
- DIP("ADDS_A.H w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- t4 = newTemp(Ity_V128);
- assign(t1, unop(Iop_Abs16x8, getWReg(ws)));
- assign(t2, unop(Iop_Abs16x8, getWReg(wt)));
- assign(t3, binop(Iop_SarN16x8,
- binop(Iop_AndV128,
- mkexpr(t1),
- getWReg(ws)),
- mkU8(15)));
- assign(t4, binop(Iop_SarN16x8,
- binop(Iop_AndV128,
- mkexpr(t2),
- getWReg(wt)),
- mkU8(15)));
- putWReg(wd, binop(Iop_QAdd16Sx8,
- binop(Iop_OrV128,
- binop(Iop_AndV128,
- unop(Iop_NotV128,
- mkexpr(t3)),
- mkexpr(t1)),
- binop(Iop_AndV128,
- unop(Iop_NotV128,
- mkexpr(t1)),
- mkexpr(t3))),
- binop(Iop_OrV128,
- binop(Iop_AndV128,
- unop(Iop_NotV128,
- mkexpr(t4)),
- mkexpr(t2)),
- binop(Iop_AndV128,
- unop(Iop_NotV128,
- mkexpr(t2)),
- mkexpr(t4)))));
- break;
- }
+ case 0x01: { /* SPLAT.df */
+ switch (df) {
+ Int i;
- case 0x02: { /* ADDS_A.W */
- DIP("ADDS_A.W w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- t4 = newTemp(Ity_V128);
- assign(t1, unop(Iop_Abs32x4, getWReg(ws)));
- assign(t2, unop(Iop_Abs32x4, getWReg(wt)));
- assign(t3, binop(Iop_SarN32x4,
- binop(Iop_AndV128,
- mkexpr(t1),
- getWReg(ws)),
- mkU8(31)));
- assign(t4, binop(Iop_SarN32x4,
- binop(Iop_AndV128,
- mkexpr(t2),
- getWReg(wt)),
- mkU8(31)));
- putWReg(wd, binop(Iop_QAdd32Sx4,
- binop(Iop_OrV128,
- binop(Iop_AndV128,
- unop(Iop_NotV128,
- mkexpr(t3)),
- mkexpr(t1)),
- binop(Iop_AndV128,
- unop(Iop_NotV128,
- mkexpr(t1)),
- mkexpr(t3))),
- binop(Iop_OrV128,
- binop(Iop_AndV128,
- unop(Iop_NotV128,
- mkexpr(t4)),
- mkexpr(t2)),
- binop(Iop_AndV128,
- unop(Iop_NotV128,
- mkexpr(t2)),
- mkexpr(t4)))));
- break;
- }
+ case 0x00: { /* SPLAT.B */
+ DIP("SPLAT.B w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_I32);
+ assign(t1, getWReg(ws));
+ assign(t2,
+ mkNarrowTo32(ty, getIReg(wt)));
+ IRTemp tmp[16];
+
+ for (i = 0; i < 16; i++) {
+ tmp[i] = newTemp(Ity_I8);
+ assign(tmp[i],
+ binop(Iop_GetElem8x16,
+ mkexpr(t1),
+ unop(Iop_32to8, mkexpr(t2))));
+ }
- case 0x03: { /* ADDS_A.D */
- DIP("ADDS_A.D w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- t4 = newTemp(Ity_V128);
- assign(t1, unop(Iop_Abs64x2, getWReg(ws)));
- assign(t2, unop(Iop_Abs64x2, getWReg(wt)));
- assign(t3, binop(Iop_SarN64x2,
- binop(Iop_AndV128,
- mkexpr(t1),
- getWReg(ws)),
- mkU8(63)));
- assign(t4, binop(Iop_SarN64x2,
- binop(Iop_AndV128,
- mkexpr(t2),
- getWReg(wt)),
- mkU8(63)));
- putWReg(wd,
- binop(Iop_QAdd64Sx2,
- binop(Iop_OrV128,
- binop(Iop_AndV128,
- unop(Iop_NotV128,
- mkexpr(t3)),
- mkexpr(t1)),
- binop(Iop_AndV128,
- unop(Iop_NotV128,
- mkexpr(t1)),
- mkexpr(t3))),
- binop(Iop_OrV128,
- binop(Iop_AndV128,
- unop(Iop_NotV128,
- mkexpr(t4)),
- mkexpr(t2)),
- binop(Iop_AndV128,
- unop(Iop_NotV128,
- mkexpr(t2)),
- mkexpr(t4)))));
- break;
- }
+ putWReg(wd,
+ binop(Iop_64HLtoV128,
+ binop(Iop_32HLto64,
+ binop(Iop_16HLto32,
+ binop(Iop_8HLto16,
+ mkexpr(tmp[15]),
+ mkexpr(tmp[14])),
+ binop(Iop_8HLto16,
+ mkexpr(tmp[13]),
+ mkexpr(tmp[12]))),
+ binop(Iop_16HLto32,
+ binop(Iop_8HLto16,
+ mkexpr(tmp[11]),
+ mkexpr(tmp[10])),
+ binop(Iop_8HLto16,
+ mkexpr(tmp[9]),
+ mkexpr(tmp[8])))),
+ binop(Iop_32HLto64,
+ binop(Iop_16HLto32,
+ binop(Iop_8HLto16,
+ mkexpr(tmp[7]),
+ mkexpr(tmp[6])),
+ binop(Iop_8HLto16,
+ mkexpr(tmp[5]),
+ mkexpr(tmp[4]))),
+ binop(Iop_16HLto32,
+ binop(Iop_8HLto16,
+ mkexpr(tmp[3]),
+ mkexpr(tmp[2])),
+ binop(Iop_8HLto16,
+ mkexpr(tmp[1]),
+ mkexpr(tmp[0]))))));
+ break;
+ }
- default:
- return -1;
+ case 0x01: { /* SPLAT.H */
+ DIP("SPLAT.H w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_I32);
+ assign(t1, getWReg(ws));
+ assign(t2,
+ mkNarrowTo32(ty, getIReg(wt)));
+ IRTemp tmp[8];
+
+ for (i = 0; i < 8; i++) {
+ tmp[i] = newTemp(Ity_I16);
+ assign(tmp[i],
+ binop(Iop_GetElem16x8,
+ mkexpr(t1),
+ unop(Iop_32to8, mkexpr(t2))));
+ }
+
+ putWReg(wd,
+ binop(Iop_64HLtoV128,
+ binop(Iop_32HLto64,
+ binop(Iop_16HLto32,
+ mkexpr(tmp[7]),
+ mkexpr(tmp[6])),
+ binop(Iop_16HLto32,
+ mkexpr(tmp[5]),
+ mkexpr(tmp[4]))),
+ binop(Iop_32HLto64,
+ binop(Iop_16HLto32,
+ mkexpr(tmp[3]),
+ mkexpr(tmp[2])),
+ binop(Iop_16HLto32,
+ mkexpr(tmp[1]),
+ mkexpr(tmp[0])))));
+ break;
}
- break;
- }
+ case 0x02: { /* SPLAT.W */
+ DIP("SPLAT.W w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_I32);
+ assign(t1, getWReg(ws));
+ assign(t2,
+ mkNarrowTo32(ty, getIReg(wt)));
+ IRTemp tmp[4];
+
+ for (i = 0; i < 4; i++) {
+ tmp[i] = newTemp(Ity_I32);
+ assign(tmp[i],
+ binop(Iop_GetElem32x4,
+ mkexpr(t1),
+ unop(Iop_32to8, mkexpr(t2))));
+ }
- case 0x02: { /* ADDS_S.df */
- switch (df) {
- case 0x00: { /* ADDS_S.B */
- DIP("ADDS_S.B w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3, binop(Iop_QAdd8Sx16, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ putWReg(wd,
+ binop(Iop_64HLtoV128,
+ binop(Iop_32HLto64,
+ mkexpr(tmp[3]),
+ mkexpr(tmp[2])),
+ binop(Iop_32HLto64,
+ mkexpr(tmp[1]),
+ mkexpr(tmp[0]))));
+ break;
+ }
- case 0x01: { /* ADDS_S.H */
- DIP("ADDS_S.H w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3, binop(Iop_QAdd16Sx8, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ case 0x03: { /* SPLAT.D */
+ DIP("SPLAT.D w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_I32);
+ assign(t1, getWReg(ws));
+ assign(t2,
+ mkNarrowTo32(ty, getIReg(wt)));
+ IRTemp tmp[2];
+
+ for (i = 0; i < 2; i++) {
+ tmp[i] = newTemp(Ity_I64);
+ assign(tmp[i],
+ binop(Iop_GetElem64x2,
+ mkexpr(t1),
+ unop(Iop_32to8, mkexpr(t2))));
+ }
- case 0x02: { /* ADDS_S.W */
- DIP("ADDS_S.W w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3, binop(Iop_QAdd32Sx4, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ putWReg(wd,
+ binop(Iop_64HLtoV128,
+ mkexpr(tmp[1]), mkexpr(tmp[0])));
+ break;
+ }
+ }
- case 0x03: { /* ADDS_S.D */
- DIP("ADDS_S.D w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3, binop(Iop_QAdd64Sx2, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ break;
+ }
- default:
- return -1;
+ case 0x02: { /* PCKEV.df */
+ switch (df) {
+ case 0x00: { /* PCKEV.B */
+ DIP("PCKEV.B w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3,
+ binop(Iop_PackEvenLanes8x16,
+ mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
}
- break;
- }
+ case 0x01: { /* PCKEV.H */
+ DIP("PCKEV.H w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3,
+ binop(Iop_PackEvenLanes16x8,
+ mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- case 0x03: { /* ADDS_U.df */
- switch (df) {
- case 0x00: { /* ADDS_U.B */
- DIP("ADDS_U.B w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3, binop(Iop_QAdd8Ux16, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ case 0x02: { /* PCKEV.W */
+ DIP("PCKEV.W w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3,
+ binop(Iop_PackEvenLanes32x4,
+ mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- case 0x01: { /* ADDS_U.H */
- DIP("ADDS_U.H w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3, binop(Iop_QAdd16Ux8, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ case 0x03: { /* PCKEV.D */
+ DIP("PCKEV.D w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3,
+ binop(Iop_InterleaveLO64x2,
+ mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
+
+ default:
+ return -1;
+ }
- case 0x02: { /* ADDS_U.W */
- DIP("ADDS_U.W w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3, binop(Iop_QAdd32Ux4, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ break;
+ }
- case 0x03: { /* ADDS_U.D */
- DIP("ADDS_U.D w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3, binop(Iop_QAdd64Ux2, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ case 0x03: { /* PCKOD.df */
+ switch (df) {
+ case 0x00: { /* PCKOD.B */
+ DIP("PCKOD.B w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3,
+ binop(Iop_PackOddLanes8x16,
+ mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- default:
- return -1;
+ case 0x01: { /* PCKOD.H */
+ DIP("PCKOD.H w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3,
+ binop(Iop_PackOddLanes16x8,
+ mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
}
- break;
+ case 0x02: { /* PCKOD.W */
+ DIP("PCKOD.W w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3,
+ binop(Iop_PackOddLanes32x4,
+ mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
+
+ case 0x03: { /* PCKOD.D */
+ DIP("PCKOD.D w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3,
+ binop(Iop_InterleaveHI64x2,
+ mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
+
+ default:
+ return -1;
}
- case 0x04: { /* AVE_S.df */
- switch (df) {
- case 0x00: { /* AVE_S.B */
- DIP("AVE_S.B w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3, binop(Iop_Add8x16,
- binop(Iop_Add8x16,
- binop(Iop_SarN8x16,
- mkexpr(t1), mkU8(1)),
- binop(Iop_SarN8x16,
- mkexpr(t2), mkU8(1))),
- binop(Iop_ShrN8x16,
- binop(Iop_ShlN8x16,
- binop(Iop_AndV128,
- mkexpr(t1),
- mkexpr(t2)),
- mkU8(7)),
- mkU8(7))));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ break;
+ }
- case 0x01: { /* AVE_S.H */
- DIP("AVE_S.H w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3,
- binop(Iop_Add16x8,
- binop(Iop_Add16x8,
- binop(Iop_SarN16x8,
- mkexpr(t1), mkU8(1)),
- binop(Iop_SarN16x8,
- mkexpr(t2), mkU8(1))),
- binop(Iop_ShrN16x8,
- binop(Iop_ShlN16x8,
- binop(Iop_AndV128,
- mkexpr(t1),
- mkexpr(t2)),
- mkU8(15)),
- mkU8(15))));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ case 0x04: { /* ILVL.df */
+ switch (df) {
+ case 0x00: { /* ILVL.B */
+ DIP("ILVL.B w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3,
+ binop(Iop_InterleaveHI8x16,
+ mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- case 0x02: { /* AVE_S.W */
- DIP("AVE_S.W w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3, binop(Iop_Add32x4,
- binop(Iop_Add32x4,
- binop(Iop_SarN32x4,
- mkexpr(t1), mkU8(1)),
- binop(Iop_SarN32x4,
- mkexpr(t2), mkU8(1))),
- binop(Iop_ShrN32x4,
- binop(Iop_ShlN32x4,
- binop(Iop_AndV128,
- mkexpr(t1),
- mkexpr(t2)),
- mkU8(31)),
- mkU8(31))));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ case 0x01: { /* ILVL.H */
+ DIP("ILVL.H w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3,
+ binop(Iop_InterleaveHI16x8,
+ mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- case 0x03: { /* AVE_S.D */
- DIP("AVE_S.D w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3, binop(Iop_Add64x2,
- binop(Iop_Add64x2,
- binop(Iop_SarN64x2,
- mkexpr(t1), mkU8(1)),
- binop(Iop_SarN64x2,
- mkexpr(t2), mkU8(1))),
- binop(Iop_ShrN64x2,
- binop(Iop_ShlN64x2,
- binop(Iop_AndV128,
- mkexpr(t1),
- mkexpr(t2)),
- mkU8(63)),
- mkU8(63))));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ case 0x02: { /* ILVL.W */
+ DIP("ILVL.W w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3,
+ binop(Iop_InterleaveHI32x4,
+ mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- default:
- return -1;
+ case 0x03: { /* ILVL.D */
+ DIP("ILVL.D w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3,
+ binop(Iop_InterleaveHI64x2,
+ mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
}
- break;
+ default:
+ return -1;
}
- case 0x05: { /* AVE_U.df */
- switch (df) {
- case 0x00: { /* AVE_U.B */
- DIP("AVE_U.B w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3, binop(Iop_Add16x8,
- binop(Iop_Add8x16,
- binop(Iop_ShrN8x16,
- mkexpr(t1), mkU8(1)),
- binop(Iop_ShrN8x16,
- mkexpr(t2), mkU8(1))),
- binop(Iop_ShrN8x16,
- binop(Iop_ShlN8x16,
- binop(Iop_AndV128,
- mkexpr(t1),
- mkexpr(t2)),
- mkU8(7)),
- mkU8(7))));
- putWReg(wd, mkexpr(t3));
- break;
- }
-
- case 0x01: { /* AVE_U.H */
- DIP("AVE_U.H w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3, binop(Iop_Add16x8,
- binop(Iop_Add16x8,
- binop(Iop_ShrN16x8,
- mkexpr(t1), mkU8(1)),
- binop(Iop_ShrN16x8,
- mkexpr(t2), mkU8(1))),
- binop(Iop_ShrN16x8,
- binop(Iop_ShlN16x8,
- binop(Iop_AndV128,
- mkexpr(t1),
- mkexpr(t2)),
- mkU8(15)),
- mkU8(15))));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ break;
+ }
- case 0x02: { /* AVE_U.W */
- DIP("AVE_U.W w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3, binop(Iop_Add32x4,
- binop(Iop_Add32x4,
- binop(Iop_ShrN32x4,
- mkexpr(t1), mkU8(1)),
- binop(Iop_ShrN32x4,
- mkexpr(t2), mkU8(1))),
- binop(Iop_ShrN32x4,
- binop(Iop_ShlN32x4,
- binop(Iop_AndV128,
- mkexpr(t1),
- mkexpr(t2)),
- mkU8(31)),
- mkU8(31))));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ case 0x05: { /* ILVR.df */
+ switch (df) {
+ case 0x00: { /* ILVL.B */
+ DIP("ILVL.B w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3,
+ binop(Iop_InterleaveLO8x16,
+ mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- case 0x03: { /* AVE_U.D */
- DIP("AVE_U.D w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3, binop(Iop_Add64x2,
- binop(Iop_Add64x2,
- binop(Iop_ShrN64x2,
- mkexpr(t1), mkU8(1)),
- binop(Iop_ShrN64x2,
- mkexpr(t2), mkU8(1))),
- binop(Iop_ShrN64x2,
- binop(Iop_ShlN64x2,
- binop(Iop_AndV128,
- mkexpr(t1),
- mkexpr(t2)),
- mkU8(63)),
- mkU8(63))));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ case 0x01: { /* ILVL.H */
+ DIP("ILVL.H w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3,
+ binop(Iop_InterleaveLO16x8,
+ mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- default:
- return -1;
+ case 0x02: { /* ILVL.W */
+ DIP("ILVL.W w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3,
+ binop(Iop_InterleaveLO32x4,
+ mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
}
- break;
+ case 0x03: { /* ILVL.D */
+ DIP("ILVL.D w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3,
+ binop(Iop_InterleaveLO64x2,
+ mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
}
- case 0x06: { /* AVER_S.df */
- switch (df) {
- case 0x00: { /* AVER_S.B */
- DIP("AVER_S.B w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3, binop(Iop_Avg8Sx16, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ break;
+ }
- case 0x01: { /* AVER_S.H */
- DIP("AVER_S.H w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3, binop(Iop_Avg16Sx8, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ case 0x06: { /* ILVEV.df */
+ switch (df) {
+ case 0x00: { /* ILVEV.B */
+ DIP("ILVEV.B w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3,
+ binop(Iop_InterleaveEvenLanes8x16,
+ mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- case 0x02: { /* AVER_S.W */
- DIP("AVER_S.W w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3, binop(Iop_Avg32Sx4, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ case 0x01: { /* ILVEV.H */
+ DIP("ILVEV.H w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3,
+ binop(Iop_InterleaveEvenLanes16x8,
+ mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- case 0x03: { /* AVER_S.D */
- DIP("AVER_S.D w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3, binop(Iop_Add64x2,
- binop(Iop_Add64x2,
- binop(Iop_SarN64x2,
- mkexpr(t1), mkU8(1)),
- binop(Iop_SarN64x2,
- mkexpr(t2), mkU8(1))),
- binop(Iop_ShrN64x2,
- binop(Iop_ShlN64x2,
- binop(Iop_OrV128,
- mkexpr(t1),
- mkexpr(t2)),
- mkU8(63)),
- mkU8(63))));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ case 0x02: { /* ILVEV.W */
+ DIP("ILVEV.W w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3,
+ binop(Iop_InterleaveEvenLanes32x4,
+ mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- default:
- return -1;
+ case 0x03: { /* ILVEV.D */
+ DIP("ILVEV.D w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3,
+ binop(Iop_InterleaveLO64x2,
+ mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
}
- break;
+ default:
+ return -1;
}
- case 0x07: { /* AVER_U.df */
- switch (df) {
- case 0x00: { /* AVER_U.B */
- DIP("AVER_U.B w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3, binop(Iop_Avg8Ux16, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ break;
+ }
- case 0x01: { /* AVER_U.H */
- DIP("AVER_U.H w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3, binop(Iop_Avg16Ux8, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ case 0x07: { /* ILVOD.df */
+ switch (df) {
+ case 0x00: { /* ILVOD.B */
+ DIP("ILVOD.B w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3,
+ binop(Iop_InterleaveOddLanes8x16,
+ mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- case 0x02: { /* AVER_U.W */
- DIP("AVER_U.W w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3, binop(Iop_Avg32Ux4, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ case 0x01: { /* ILVOD.H */
+ DIP("ILVOD.H w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3,
+ binop(Iop_InterleaveOddLanes16x8,
+ mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- case 0x03: { /* AVER_U.D */
- DIP("AVER_U.D w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3, binop(Iop_Add64x2,
- binop(Iop_Add64x2,
- binop(Iop_ShrN64x2,
- mkexpr(t1), mkU8(1)),
- binop(Iop_ShrN64x2,
- mkexpr(t2), mkU8(1))),
- binop(Iop_ShrN64x2,
- binop(Iop_ShlN64x2,
- binop(Iop_OrV128,
- mkexpr(t1),
- mkexpr(t2)),
- mkU8(63)),
- mkU8(63))));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ case 0x02: { /* ILVOD.W */
+ DIP("ILVOD.W w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3,
+ binop(Iop_InterleaveOddLanes32x4,
+ mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- default:
- return -1;
+ case 0x03: { /* ILVOD.D */
+ DIP("ILVOD.D w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3,
+ binop(Iop_InterleaveHI64x2,
+ mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
}
- break;
+ default:
+ return -1;
}
+ break;
+ }
+
default:
return -1;
}
return 0;
}
-static Int msa_3R_11(UInt cins, UChar wd, UChar ws) { /* 3R (0x11) */
- IRTemp t1, t2, t3;
+static Int msa_3R_15(UInt cins, UChar wd, UChar ws) /* 3R (0x15) */
+{
+ IRTemp t1, t2, t3, t4;
UShort operation;
UChar df, wt;
wt = (cins & 0x001F0000) >> 16;
switch (operation) {
- case 0x00: { /* SUBS_S.df */
- switch (df) {
- case 0x00: { /* SUBS_S.B */
- DIP("SUBS_S.B w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3, binop(Iop_QSub8Sx16, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ case 0x00: { /* VSHF.df */
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(wd));
+ assign(t2, getWReg(ws));
+ assign(t3, getWReg(wt));
- case 0x01: { /* SUBS_S.H */
- DIP("SUBS_S.H w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3, binop(Iop_QSub16Sx8, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ switch (df) {
+ case 0x00: { /* VSHF.B */
+ DIP("VSHF.B w%d, w%d, w%d", wd, ws, wt);
+ IRTemp tmp[16];
+ Int i;
+
+ for (i = 0; i < 16; i++) {
+ tmp[i] = newTemp(Ity_I8);
+ assign(tmp[i],
+ IRExpr_ITE(
+ binop(Iop_CmpEQ8,
+ binop(Iop_And8,
+ binop(Iop_GetElem8x16,
+ mkexpr(t1),
+ mkU8(i)),
+ mkU8(0xC0)),
+ mkU8(0x0)),
+ IRExpr_ITE(
+ binop(Iop_CmpEQ8,
+ binop(Iop_And8,
+ binop(Iop_GetElem8x16,
+ mkexpr(t1),
+ mkU8(i)),
+ mkU8(0x10)),
+ mkU8(0x0)),
+ binop(Iop_GetElem8x16,
+ mkexpr(t3),
+ binop(Iop_GetElem8x16,
+ mkexpr(t1),
+ mkU8(i))),
+ binop(Iop_GetElem8x16,
+ mkexpr(t2),
+ binop(Iop_GetElem8x16,
+ mkexpr(t1),
+ mkU8(i)))),
+ mkU8(0x0)));
+ }
- case 0x02: { /* SUBS_S.W */
- DIP("SUBS_S.W w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3, binop(Iop_QSub32Sx4, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ putWReg(wd,
+ binop(Iop_64HLtoV128,
+ binop(Iop_32HLto64,
+ binop(Iop_16HLto32,
+ binop(Iop_8HLto16,
+ mkexpr(tmp[15]),
+ mkexpr(tmp[14])),
+ binop(Iop_8HLto16,
+ mkexpr(tmp[13]),
+ mkexpr(tmp[12]))),
+ binop(Iop_16HLto32,
+ binop(Iop_8HLto16,
+ mkexpr(tmp[11]),
+ mkexpr(tmp[10])),
+ binop(Iop_8HLto16,
+ mkexpr(tmp[9]),
+ mkexpr(tmp[8])))),
+ binop(Iop_32HLto64,
+ binop(Iop_16HLto32,
+ binop(Iop_8HLto16,
+ mkexpr(tmp[7]),
+ mkexpr(tmp[6])),
+ binop(Iop_8HLto16,
+ mkexpr(tmp[5]),
+ mkexpr(tmp[4]))),
+ binop(Iop_16HLto32,
+ binop(Iop_8HLto16,
+ mkexpr(tmp[3]),
+ mkexpr(tmp[2])),
+ binop(Iop_8HLto16,
+ mkexpr(tmp[1]),
+ mkexpr(tmp[0]))))));
+ break;
+ }
- case 0x03: { /* SUBS_S.D */
- DIP("SUBS_S.D w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3, binop(Iop_QSub64Sx2, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ case 0x01: { /* VSHF.H */
+ DIP("VSHF.H w%d, w%d, w%d", wd, ws, wt);
+ IRTemp tmp[8];
+ Int i;
+
+ for (i = 0; i < 8; i++) {
+ tmp[i] = newTemp(Ity_I16);
+ assign(tmp[i],
+ IRExpr_ITE(
+ binop(Iop_CmpEQ16,
+ binop(Iop_And16,
+ binop(Iop_GetElem16x8,
+ mkexpr(t1),
+ mkU8(i)),
+ mkU16(0xC0)),
+ mkU16(0x0)),
+ IRExpr_ITE(
+ binop(Iop_CmpEQ16,
+ binop(Iop_And16,
+ binop(Iop_GetElem16x8,
+ mkexpr(t1),
+ mkU8(i)),
+ mkU16(0x08)),
+ mkU16(0x0)),
+ binop(Iop_GetElem16x8,
+ mkexpr(t3),
+ unop(Iop_16to8,
+ binop(Iop_GetElem16x8,
+ mkexpr(t1),
+ mkU8(i)))),
+ binop(Iop_GetElem16x8,
+ mkexpr(t2),
+ unop(Iop_16to8,
+ binop(Iop_GetElem16x8,
+ mkexpr(t1),
+ mkU8(i))))),
+ mkU16(0x0)));
+ }
- default:
- return -1;
+ putWReg(wd,
+ binop(Iop_64HLtoV128,
+ binop(Iop_32HLto64,
+ binop(Iop_16HLto32,
+ mkexpr(tmp[7]),
+ mkexpr(tmp[6])),
+ binop(Iop_16HLto32,
+ mkexpr(tmp[5]),
+ mkexpr(tmp[4]))),
+ binop(Iop_32HLto64,
+ binop(Iop_16HLto32,
+ mkexpr(tmp[3]),
+ mkexpr(tmp[2])),
+ binop(Iop_16HLto32,
+ mkexpr(tmp[1]),
+ mkexpr(tmp[0])))));
+ break;
}
- break;
- }
+ case 0x02: { /* VSHF.W */
+ DIP("VSHF.W w%d, w%d, w%d", wd, ws, wt);
+ IRTemp tmp[4];
+ Int i;
- case 0x01: { /* SUBS_U.df */
- switch (df) {
- case 0x00: { /* SUBS_U.B */
- DIP("SUBS_U.B w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3, binop(Iop_QSub8Ux16, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ for (i = 0; i < 4; i++) {
+ tmp[i] = newTemp(Ity_I32);
+ assign(tmp[i],
+ IRExpr_ITE(
+ binop(Iop_CmpEQ32,
+ binop(Iop_And32,
+ binop(Iop_GetElem32x4,
+ mkexpr(t1),
+ mkU8(i)),
+ mkU32(0xC0)),
+ mkU32(0x0)),
+ IRExpr_ITE(
+ binop(Iop_CmpEQ32,
+ binop(Iop_And32,
+ binop(Iop_GetElem32x4,
+ mkexpr(t1),
+ mkU8(i)),
+ mkU32(0x04)),
+ mkU32(0x0)),
+ binop(Iop_GetElem32x4,
+ mkexpr(t3),
+ unop(Iop_32to8,
+ binop(Iop_GetElem32x4,
+ mkexpr(t1),
+ mkU8(i)))),
+ binop(Iop_GetElem32x4,
+ mkexpr(t2),
+ unop(Iop_32to8,
+ binop(Iop_GetElem32x4,
+ mkexpr(t1),
+ mkU8(i))))),
+ mkU32(0x0)));
+ }
- case 0x01: { /* SUBS_U.H */
- DIP("SUBS_U.H w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3, binop(Iop_QSub16Ux8, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ putWReg(wd,
+ binop(Iop_64HLtoV128,
+ binop(Iop_32HLto64,
+ mkexpr(tmp[3]),
+ mkexpr(tmp[2])),
+ binop(Iop_32HLto64,
+ mkexpr(tmp[1]),
+ mkexpr(tmp[0]))));
+ break;
+ }
- case 0x02: { /* SUBS_U.W */
- DIP("SUBS_U.W w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3, binop(Iop_QSub32Ux4, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ case 0x03: { /* VSHF.D */
+ DIP("VSHF.D w%d, w%d, w%d", wd, ws, wt);
+ IRTemp tmp[2];
+ Int i;
- case 0x03: { /* SUBS_U.D */
- DIP("SUBS_U.D w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3, binop(Iop_QSub64Ux2, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ for (i = 0; i < 2; i++) {
+ tmp[i] = newTemp(Ity_I64);
+ assign(tmp[i],
+ IRExpr_ITE(
+ binop(Iop_CmpEQ64,
+ binop(Iop_And64,
+ binop(Iop_GetElem64x2,
+ mkexpr(t1),
+ mkU8(i)),
+ mkU64(0xC0)),
+ mkU64(0x0)),
+ IRExpr_ITE(
+ binop(Iop_CmpEQ64,
+ binop(Iop_And64,
+ binop(Iop_GetElem64x2,
+ mkexpr(t1),
+ mkU8(i)),
+ mkU64(0x02)),
+ mkU64(0x0)),
+ binop(Iop_GetElem64x2,
+ mkexpr(t3),
+ unop(Iop_64to8,
+ binop(Iop_GetElem64x2,
+ mkexpr(t1),
+ mkU8(i)))),
+ binop(Iop_GetElem64x2,
+ mkexpr(t2),
+ unop(Iop_64to8,
+ binop(Iop_GetElem64x2,
+ mkexpr(t1),
+ mkU8(i))))),
+ mkU64(0x0)));
+ }
- default:
- return -1;
+ putWReg(wd,
+ binop(Iop_64HLtoV128,
+ mkexpr(tmp[1]), mkexpr(tmp[0])));
+ break;
}
- break;
+ default:
+ return -1;
}
- case 0x02: { /* SUBSUS_U.df */
- switch (df) {
- case 0x00: { /* SUBSUS_U.B */
- DIP("SUBSUS_U.B w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, binop(Iop_Sub8x16, getWReg(ws), getWReg(wt)));
- assign(t2, binop(Iop_SarN8x16, getWReg(wt), mkU8(7)));
- assign(t3, binop(Iop_OrV128,
- binop(Iop_CmpGT8Ux16,
- getWReg(ws),
- getWReg(wt)),
- binop(Iop_CmpEQ8x16,
- getWReg(ws),
- getWReg(wt))));
- putWReg(wd,
- binop(Iop_OrV128,
- binop(Iop_AndV128,
- mkexpr(t3), mkexpr(t2)),
- binop(Iop_AndV128,
- mkexpr(t1),
- binop(Iop_XorV128,
- mkexpr(t3),
- mkexpr(t2)))));
- break;
- }
+ break;
+ }
- case 0x01: { /* SUBSUS_U.H */
- DIP("SUBSUS_U.H w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, binop(Iop_Sub16x8, getWReg(ws), getWReg(wt)));
- assign(t2, binop(Iop_SarN16x8, getWReg(wt), mkU8(15)));
- assign(t3,
- binop(Iop_OrV128,
- binop(Iop_CmpGT16Ux8,
- getWReg(ws),
- getWReg(wt)),
- binop(Iop_CmpEQ16x8,
+ case 0x01: { /* SRAR.df */
+ switch (df) {
+ case 0x00: { /* SRAR.B */
+ DIP("SRAR.B w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ t4 = newTemp(Ity_V128);
+ assign(t1,
+ binop(Iop_Sar8x16,
+ getWReg(ws),
+ getWReg(wt)));
+ assign(t2,
+ binop(Iop_Sub8x16,
+ binop(Iop_64HLtoV128,
+ mkU64(0x808080808080808ull),
+ mkU64(0x808080808080808ull)),
+ getWReg(wt)));
+ assign(t4,
+ unop(Iop_NotV128,
+ binop(Iop_CmpEQ8x16,
+ binop(Iop_ShlN8x16,
+ getWReg(wt),
+ mkU8(5)),
+ binop(Iop_64HLtoV128,
+ mkU64(0), mkU64(0)))));
+ assign(t3,
+ binop(Iop_ShrN8x16,
+ binop(Iop_AndV128,
+ binop(Iop_Shl8x16,
getWReg(ws),
- getWReg(wt))));
- putWReg(wd,
- binop(Iop_OrV128,
- binop(Iop_AndV128,
- mkexpr(t3), mkexpr(t2)),
- binop(Iop_AndV128,
- mkexpr(t1),
- binop(Iop_XorV128,
- mkexpr(t3),
- mkexpr(t2)))));
- break;
- }
+ mkexpr(t2)),
+ mkexpr(t4)),
+ mkU8(7)));
+ putWReg(wd,
+ binop(Iop_Add8x16,
+ mkexpr(t1), mkexpr(t3)));
+ break;
+ }
- case 0x02: { /* SUBSUS_U.W */
- DIP("SUBSUS_U.W w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, binop(Iop_Sub32x4, getWReg(ws), getWReg(wt)));
- assign(t2, binop(Iop_SarN32x4, getWReg(wt), mkU8(31)));
- assign(t3,
- binop(Iop_OrV128,
- binop(Iop_CmpGT32Ux4,
- getWReg(ws),
- getWReg(wt)),
- binop(Iop_CmpEQ32x4,
+ case 0x01: { /* SRAR.H */
+ DIP("SRAR.H w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ t4 = newTemp(Ity_V128);
+ assign(t1,
+ binop(Iop_Sar16x8,
+ getWReg(ws),
+ getWReg(wt)));
+ assign(t2,
+ binop(Iop_Sub16x8,
+ binop(Iop_64HLtoV128,
+ mkU64(0x10001000100010ul),
+ mkU64(0x10001000100010ul)),
+ getWReg(wt)));
+ assign(t4,
+ unop(Iop_NotV128,
+ binop(Iop_CmpEQ16x8,
+ binop(Iop_ShlN16x8,
+ getWReg(wt),
+ mkU8(12)),
+ binop(Iop_64HLtoV128,
+ mkU64(0), mkU64(0)))));
+ assign(t3,
+ binop(Iop_ShrN16x8,
+ binop(Iop_AndV128,
+ binop(Iop_Shl16x8,
getWReg(ws),
- getWReg(wt))));
- putWReg(wd,
- binop(Iop_OrV128,
- binop(Iop_AndV128,
- mkexpr(t3), mkexpr(t2)),
- binop(Iop_AndV128,
- mkexpr(t1),
- binop(Iop_XorV128,
- mkexpr(t3),
- mkexpr(t2)))));
- break;
- }
+ mkexpr(t2)),
+ mkexpr(t4)),
+ mkU8(15)));
+ putWReg(wd,
+ binop(Iop_Add16x8,
+ mkexpr(t1), mkexpr(t3)));
+ break;
+ }
- case 0x03: { /* SUBSUS_U.D */
- DIP("SUBSUS_U.D w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, binop(Iop_Sub64x2, getWReg(ws), getWReg(wt)));
- assign(t2, binop(Iop_SarN64x2, getWReg(wt), mkU8(63)));
- assign(t3,
- binop(Iop_OrV128,
- binop(Iop_CmpGT64Ux2,
- getWReg(ws),
- getWReg(wt)),
- binop(Iop_CmpEQ64x2,
+ case 0x02: { /* SRAR.W */
+ DIP("SRAR.W w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128); // shifted
+ t2 = newTemp(Ity_V128); // 32 - wt
+ t3 = newTemp(Ity_V128); // rv
+ t4 = newTemp(Ity_V128); // wt % 32 == 0
+ assign(t1,
+ binop(Iop_Sar32x4,
+ getWReg(ws),
+ getWReg(wt)));
+ assign(t2,
+ binop(Iop_Sub32x4,
+ binop(Iop_64HLtoV128,
+ mkU64(0x2000000020ul),
+ mkU64(0x2000000020ul)),
+ getWReg(wt)));
+ assign(t4,
+ unop(Iop_NotV128,
+ binop(Iop_CmpEQ32x4,
+ binop(Iop_ShlN32x4,
+ getWReg(wt),
+ mkU8(27)),
+ binop(Iop_64HLtoV128,
+ mkU64(0), mkU64(0)))));
+ assign(t3,
+ binop(Iop_ShrN32x4,
+ binop(Iop_AndV128,
+ binop(Iop_Shl32x4,
getWReg(ws),
- getWReg(wt))));
- putWReg(wd,
- binop(Iop_OrV128,
- binop(Iop_AndV128,
- mkexpr(t3), mkexpr(t2)),
- binop(Iop_AndV128,
- mkexpr(t1),
- binop(Iop_XorV128,
- mkexpr(t3),
- mkexpr(t2)))));
- break;
- }
+ mkexpr(t2)),
+ mkexpr(t4)),
+ mkU8(31)));
+ putWReg(wd,
+ binop(Iop_Add32x4,
+ mkexpr(t1), mkexpr(t3)));
+ break;
+ }
- default:
- return -1;
+ case 0x03: { /* SRAR.D */
+ DIP("SRAR.D w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ t4 = newTemp(Ity_V128);
+ assign(t1,
+ binop(Iop_Sar64x2,
+ getWReg(ws),
+ getWReg(wt)));
+ assign(t2,
+ binop(Iop_Sub64x2,
+ binop(Iop_64HLtoV128,
+ mkU64(64ul), mkU64(64ul)),
+ getWReg(wt)));
+ assign(t4,
+ unop(Iop_NotV128,
+ binop(Iop_CmpEQ64x2,
+ binop(Iop_ShlN64x2,
+ getWReg(wt),
+ mkU8(58)),
+ binop(Iop_64HLtoV128,
+ mkU64(0), mkU64(0)))));
+ assign(t3,
+ binop(Iop_ShrN64x2,
+ binop(Iop_AndV128,
+ binop(Iop_Shl64x2,
+ getWReg(ws),
+ mkexpr(t2)),
+ mkexpr(t4)),
+ mkU8(63)));
+ putWReg(wd,
+ binop(Iop_Add64x2,
+ mkexpr(t1), mkexpr(t3)));
+ break;
}
- break;
+ default:
+ return -1;
}
- case 0x03: { /* SUBSUU_S.df */
- switch (df) {
- case 0x00: { /* SUBSUU_S.B */
- DIP("SUBSUU_S.B w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, binop(Iop_Sub8x16, getWReg(ws), getWReg(wt)));
- assign(t2,
- binop(Iop_SarN8x16,
- binop (Iop_AndV128,
- binop(Iop_XorV128,
- getWReg(ws),
- getWReg(wt)),
- binop(Iop_XorV128,
- mkexpr(t1),
- getWReg(wt))),
- mkU8(7)));
- assign(t3,
- binop(Iop_AndV128,
- binop(Iop_SarN8x16,
- getWReg(ws), mkU8(7)),
- mkexpr(t2)));
- putWReg(wd,
- binop(Iop_OrV128,
- binop(Iop_AndV128,
- mkexpr(t1),
- unop(Iop_NotV128,
- mkexpr(t2))),
- binop(Iop_XorV128,
- binop(Iop_ShlN8x16,
- mkexpr(t2), mkU8(7)),
- mkexpr(t3))));
- break;
- }
+ break;
+ }
- case 0x01: { /* SUBSUU_S.H */
- DIP("SUBSUU_S.H w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, binop(Iop_Sub16x8, getWReg(ws), getWReg(wt)));
- assign(t2,
- binop(Iop_SarN16x8,
- binop (Iop_AndV128,
- binop(Iop_XorV128,
- getWReg(ws),
- getWReg(wt)),
- binop(Iop_XorV128,
- mkexpr(t1),
- getWReg(wt))),
- mkU8(15)));
- assign(t3,
+ case 0x02: { /* SRLR.df */
+ switch (df) {
+ case 0x00: { /* SRLR.B */
+ DIP("SRLR.B w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ t4 = newTemp(Ity_V128);
+ assign(t1,
+ binop(Iop_Shr8x16,
+ getWReg(ws),
+ getWReg(wt)));
+ assign(t2,
+ binop(Iop_Sub8x16,
+ binop(Iop_64HLtoV128,
+ mkU64(0x808080808080808ull),
+ mkU64(0x808080808080808ull)),
+ getWReg(wt)));
+ assign(t4,
+ unop(Iop_NotV128,
+ binop(Iop_CmpEQ8x16,
+ binop(Iop_ShlN8x16,
+ getWReg(wt),
+ mkU8(5)),
+ binop(Iop_64HLtoV128,
+ mkU64(0), mkU64(0)))));
+ assign(t3,
+ binop(Iop_ShrN8x16,
binop(Iop_AndV128,
- binop(Iop_SarN16x8,
+ binop(Iop_Shl8x16,
getWReg(ws),
- mkU8(15)),
- mkexpr(t2)));
- putWReg(wd,
- binop(Iop_OrV128,
- binop(Iop_AndV128,
- mkexpr(t1),
- unop(Iop_NotV128,
- mkexpr(t2))),
- binop(Iop_XorV128,
- binop(Iop_ShlN16x8,
- mkexpr(t2), mkU8(15)),
- mkexpr(t3))));
- break;
- }
+ mkexpr(t2)),
+ mkexpr(t4)),
+ mkU8(7)));
+ putWReg(wd,
+ binop(Iop_Add8x16,
+ mkexpr(t1), mkexpr(t3)));
+ break;
+ }
- case 0x02: { /* SUBSUU_S.W */
- DIP("SUBSUU_S.W w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, binop(Iop_Sub32x4, getWReg(ws), getWReg(wt)));
- assign(t2,
- binop(Iop_SarN32x4,
- binop (Iop_AndV128,
- binop(Iop_XorV128,
- getWReg(ws),
- getWReg(wt)),
- binop(Iop_XorV128,
- mkexpr(t1),
- getWReg(wt))),
- mkU8(31)));
- assign(t3,
+ case 0x01: { /* SRLR.H */
+ DIP("SRLR.H w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ t4 = newTemp(Ity_V128);
+ assign(t1,
+ binop(Iop_Shr16x8,
+ getWReg(ws),
+ getWReg(wt)));
+ assign(t2,
+ binop(Iop_Sub16x8,
+ binop(Iop_64HLtoV128,
+ mkU64(0x10001000100010ul),
+ mkU64(0x10001000100010ul)),
+ getWReg(wt)));
+ assign(t4,
+ unop(Iop_NotV128,
+ binop(Iop_CmpEQ16x8,
+ binop(Iop_ShlN16x8,
+ getWReg(wt),
+ mkU8(12)),
+ binop(Iop_64HLtoV128,
+ mkU64(0), mkU64(0)))));
+ assign(t3,
+ binop(Iop_ShrN16x8,
binop(Iop_AndV128,
- binop(Iop_SarN32x4,
+ binop(Iop_Shl16x8,
getWReg(ws),
- mkU8(31)),
- mkexpr(t2)));
- putWReg(wd,
- binop(Iop_OrV128,
- binop(Iop_AndV128,
- mkexpr(t1),
- unop(Iop_NotV128,
- mkexpr(t2))),
- binop(Iop_XorV128,
- binop(Iop_ShlN32x4,
- mkexpr(t2),
- mkU8(31)),
- mkexpr(t3))));
- break;
- }
+ mkexpr(t2)),
+ mkexpr(t4)),
+ mkU8(15)));
+ putWReg(wd,
+ binop(Iop_Add16x8,
+ mkexpr(t1), mkexpr(t3)));
+ break;
+ }
- case 0x03: { /* SUBSUU_S.D */
- DIP("SUBSUU_S.D w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, binop(Iop_Sub64x2, getWReg(ws), getWReg(wt)));
- assign(t2,
- binop(Iop_SarN64x2,
- binop (Iop_AndV128,
- binop(Iop_XorV128,
- getWReg(ws),
- getWReg(wt)),
- binop(Iop_XorV128,
- mkexpr(t1),
- getWReg(wt))),
- mkU8(63)));
- assign(t3,
+ case 0x02: { /* SRLR.W */
+ DIP("SRLR.W w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ t4 = newTemp(Ity_V128);
+ assign(t1,
+ binop(Iop_Shr32x4,
+ getWReg(ws),
+ getWReg(wt)));
+ assign(t2,
+ binop(Iop_Sub32x4,
+ binop(Iop_64HLtoV128,
+ mkU64(0x2000000020ul),
+ mkU64(0x2000000020ul)),
+ getWReg(wt)));
+ assign(t4,
+ unop(Iop_NotV128,
+ binop(Iop_CmpEQ32x4,
+ binop(Iop_ShlN32x4,
+ getWReg(wt),
+ mkU8(27)),
+ binop(Iop_64HLtoV128,
+ mkU64(0), mkU64(0)))));
+ assign(t3,
+ binop(Iop_ShrN32x4,
binop(Iop_AndV128,
- binop(Iop_SarN64x2,
+ binop(Iop_Shl32x4,
getWReg(ws),
- mkU8(63)),
- mkexpr(t2)));
- putWReg(wd,
- binop(Iop_OrV128,
- binop(Iop_AndV128,
- mkexpr(t1),
- unop(Iop_NotV128,
- mkexpr(t2))),
- binop(Iop_XorV128,
- binop(Iop_ShlN64x2,
- mkexpr(t2), mkU8(63)),
- mkexpr(t3))));
- break;
- }
+ mkexpr(t2)),
+ mkexpr(t4)),
+ mkU8(31)));
+ putWReg(wd,
+ binop(Iop_Add32x4,
+ mkexpr(t1), mkexpr(t3)));
+ break;
+ }
- default:
- return -1;
+ case 0x03: { /* SRLR.D */
+ DIP("SRLR.D w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ t4 = newTemp(Ity_V128);
+ assign(t1,
+ binop(Iop_Shr64x2,
+ getWReg(ws),
+ getWReg(wt)));
+ assign(t2,
+ binop(Iop_Sub64x2,
+ binop(Iop_64HLtoV128,
+ mkU64(64ul), mkU64(64ul)),
+ getWReg(wt)));
+ assign(t4,
+ unop(Iop_NotV128,
+ binop(Iop_CmpEQ64x2,
+ binop(Iop_ShlN64x2,
+ getWReg(wt),
+ mkU8(58)),
+ binop(Iop_64HLtoV128,
+ mkU64(0), mkU64(0)))));
+ assign(t3,
+ binop(Iop_ShrN64x2,
+ binop(Iop_AndV128,
+ binop(Iop_Shl64x2,
+ getWReg(ws),
+ mkexpr(t2)),
+ mkexpr(t4)),
+ mkU8(63)));
+ putWReg(wd,
+ binop(Iop_Add64x2,
+ mkexpr(t1), mkexpr(t3)));
+ break;
}
- break;
+ default:
+ return -1;
}
- case 0x04: { /* ASUB_S.df */
- switch (df) {
- case 0x00: { /* ASUB_S.B */
- DIP("ASUB_S.B w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, binop(Iop_SarN8x16, getWReg(ws), mkU8(7)));
- assign(t2, binop(Iop_SarN8x16, getWReg(wt), mkU8(7)));
- assign(t3, binop(Iop_Sub8x16, getWReg(ws), getWReg(wt)));
- putWReg(wd,
- binop(Iop_OrV128,
- binop(Iop_OrV128,
- binop(Iop_AndV128,
- binop(Iop_AndV128,
- unop(Iop_NotV128,
- mkexpr(t1)),
- mkexpr(t2)),
- mkexpr(t3)),
- binop(Iop_AndV128,
- unop(Iop_NotV128,
- binop(Iop_XorV128,
- mkexpr(t1),
- mkexpr(t2))),
- unop(Iop_Abs8x16,
- mkexpr(t3)))),
- binop(Iop_AndV128,
- binop(Iop_AndV128,
- mkexpr(t1),
- unop(Iop_NotV128,
- mkexpr(t2))),
- binop(Iop_Sub8x16,
- getWReg(wt),
- getWReg(ws)))));
- break;
- }
+ break;
+ }
- case 0x01: { /* ASUB_S.H */
- DIP("ASUB_S.H w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, binop(Iop_SarN16x8, getWReg(ws), mkU8(15)));
- assign(t2, binop(Iop_SarN16x8, getWReg(wt), mkU8(15)));
- assign(t3, binop(Iop_Sub16x8, getWReg(ws), getWReg(wt)));
- putWReg(wd,
- binop(Iop_OrV128,
- binop(Iop_OrV128,
- binop(Iop_AndV128,
- binop(Iop_AndV128,
- unop(Iop_NotV128,
- mkexpr(t1)),
- mkexpr(t2)),
- mkexpr(t3)),
- binop(Iop_AndV128,
- unop(Iop_NotV128,
- binop(Iop_XorV128,
- mkexpr(t1),
- mkexpr(t2))),
- unop(Iop_Abs16x8,
- mkexpr(t3)))),
- binop(Iop_AndV128,
- binop(Iop_AndV128,
- mkexpr(t1),
- unop(Iop_NotV128,
- mkexpr(t2))),
- binop(Iop_Sub16x8,
- getWReg(wt),
- getWReg(ws)))));
- break;
- }
+ case 0x04: { /* HADD_S.df */
+ switch (df) {
+ case 0x01: { /* HADD_S.H */
+ DIP("HADD_S.H w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3,
+ binop(Iop_Add16x8,
+ binop(Iop_SarN16x8,
+ mkexpr(t1), mkU8(8)),
+ binop(Iop_SarN16x8,
+ binop(Iop_ShlN16x8,
+ mkexpr(t2), mkU8(8)),
+ mkU8(8))));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- case 0x02: { /* ASUB_S.W */
- DIP("ASUB_S.W w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, binop(Iop_SarN32x4, getWReg(ws), mkU8(31)));
- assign(t2, binop(Iop_SarN32x4, getWReg(wt), mkU8(31)));
- assign(t3, binop(Iop_Sub32x4, getWReg(ws), getWReg(wt)));
- putWReg(wd,
- binop(Iop_OrV128,
- binop(Iop_OrV128,
- binop(Iop_AndV128,
- binop(Iop_AndV128,
- unop(Iop_NotV128,
- mkexpr(t1)),
- mkexpr(t2)),
- mkexpr(t3)),
- binop(Iop_AndV128,
- unop(Iop_NotV128,
- binop(Iop_XorV128,
- mkexpr(t1),
- mkexpr(t2))),
- unop(Iop_Abs32x4,
- mkexpr(t3)))),
- binop(Iop_AndV128,
- binop(Iop_AndV128,
- mkexpr(t1),
- unop(Iop_NotV128,
- mkexpr(t2))),
- binop(Iop_Sub32x4,
- getWReg(wt),
- getWReg(ws)))));
- break;
- }
+ case 0x02: { /* HADD_S.W */
+ DIP("HADD_S.W w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3,
+ binop(Iop_Add32x4,
+ binop(Iop_SarN32x4,
+ mkexpr(t1), mkU8(16)),
+ binop(Iop_SarN32x4,
+ binop(Iop_ShlN32x4,
+ mkexpr(t2), mkU8(16)),
+ mkU8(16))));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- case 0x03: { /* ASUB_S.D */
- DIP("ASUB_S.D w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, binop(Iop_SarN64x2, getWReg(ws), mkU8(63)));
- assign(t2, binop(Iop_SarN64x2, getWReg(wt), mkU8(63)));
- assign(t3, binop(Iop_Sub64x2, getWReg(ws), getWReg(wt)));
- putWReg(wd,
- binop(Iop_OrV128,
- binop(Iop_OrV128,
- binop(Iop_AndV128,
- binop(Iop_AndV128,
- unop(Iop_NotV128,
- mkexpr(t1)),
- mkexpr(t2)),
- mkexpr(t3)),
- binop(Iop_AndV128,
- unop(Iop_NotV128,
- binop(Iop_XorV128,
- mkexpr(t1),
- mkexpr(t2))),
- unop(Iop_Abs64x2,
- mkexpr(t3)))),
- binop(Iop_AndV128,
- binop(Iop_AndV128,
- mkexpr(t1),
- unop(Iop_NotV128,
- mkexpr(t2))),
- binop(Iop_Sub64x2,
- getWReg(wt),
- getWReg(ws)))));
- break;
- }
+ case 0x03: { /* HADD_S.D */
+ DIP("HADD_S.D w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3,
+ binop(Iop_Add64x2,
+ binop(Iop_SarN64x2,
+ mkexpr(t1), mkU8(32)),
+ binop(Iop_SarN64x2,
+ binop(Iop_ShlN64x2,
+ mkexpr(t2), mkU8(32)),
+ mkU8(32))));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- default:
- return -1;
+ default:
+ return -1;
+ }
+
+ break;
+ }
+
+ case 0x05: { /* HADD_U.df */
+ switch (df) {
+ case 0x01: { /* HADD_U.H */
+ DIP("HADD_U.H w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3,
+ binop(Iop_Add16x8,
+ binop(Iop_ShrN16x8,
+ mkexpr(t1), mkU8(8)),
+ binop(Iop_ShrN16x8,
+ binop(Iop_ShlN16x8,
+ mkexpr(t2), mkU8(8)),
+ mkU8(8))));
+ putWReg(wd, mkexpr(t3));
+ break;
}
- break;
+ case 0x02: { /* HADD_U.W */
+ DIP("HADD_U.W w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3,
+ binop(Iop_Add32x4,
+ binop(Iop_ShrN32x4,
+ mkexpr(t1), mkU8(16)),
+ binop(Iop_ShrN32x4,
+ binop(Iop_ShlN32x4,
+ mkexpr(t2), mkU8(16)),
+ mkU8(16))));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
+
+ case 0x03: { /* HADD_U.D */
+ DIP("HADD_U.D w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3,
+ binop(Iop_Add64x2,
+ binop(Iop_ShrN64x2,
+ mkexpr(t1), mkU8(32)),
+ binop(Iop_ShrN64x2,
+ binop(Iop_ShlN64x2,
+ mkexpr(t2), mkU8(32)),
+ mkU8(32))));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
+
+ default:
+ return -1;
}
- case 0x05: { /* ASUB_U.df */
- switch (df) {
- case 0x00: { /* ASUB_U.B */
- DIP("ASUB_U.B w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3,
- binop(Iop_SarN8x16,
- binop(Iop_XorV128,
- mkexpr(t1), mkexpr(t2)),
- mkU8(7)));
- putWReg(wd,
- binop(Iop_OrV128,
- binop(Iop_AndV128,
- unop(Iop_NotV128, mkexpr(t3)),
- unop(Iop_Abs8x16,
- binop(Iop_Sub8x16,
- mkexpr(t1),
- mkexpr(t2)))),
- binop(Iop_AndV128, mkexpr(t3),
- binop(Iop_Sub8x16,
- binop(Iop_Max8Ux16,
- mkexpr(t1),
- mkexpr(t2)),
- binop(Iop_Min8Ux16,
- mkexpr(t1),
- mkexpr(t2))))));
- break;
- }
+ break;
+ }
- case 0x01: { /* ASUB_U.H */
- DIP("ASUB_U.H w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3,
+ case 0x06: { /* HSUB_S.df */
+ switch (df) {
+ case 0x01: { /* HSUB_S.H */
+ DIP("HSUB_S.H w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3,
+ binop(Iop_Sub16x8,
binop(Iop_SarN16x8,
- binop(Iop_XorV128,
- mkexpr(t1), mkexpr(t2)),
- mkU8(15)));
- putWReg(wd,
- binop(Iop_OrV128,
- binop(Iop_AndV128,
- unop(Iop_NotV128,
- mkexpr(t3)),
- unop(Iop_Abs16x8,
- binop(Iop_Sub16x8,
- mkexpr(t1),
- mkexpr(t2)))),
- binop(Iop_AndV128,
- mkexpr(t3),
- binop(Iop_Sub16x8,
- binop(Iop_Max16Ux8,
- mkexpr(t1),
- mkexpr(t2)),
- binop(Iop_Min16Ux8,
- mkexpr(t1),
- mkexpr(t2))))));
- break;
- }
+ mkexpr(t1), mkU8(8)),
+ binop(Iop_SarN16x8,
+ binop(Iop_ShlN16x8,
+ mkexpr(t2), mkU8(8)),
+ mkU8(8))));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- case 0x02: { /* ASUB_U.W */
- DIP("ASUB_U.W w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3,
+ case 0x02: { /* HSUB_S.W */
+ DIP("HSUB_S.W w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3,
+ binop(Iop_Sub32x4,
binop(Iop_SarN32x4,
- binop(Iop_XorV128,
- mkexpr(t1), mkexpr(t2)),
- mkU8(31)));
- putWReg(wd,
- binop(Iop_OrV128,
- binop(Iop_AndV128,
- unop(Iop_NotV128, mkexpr(t3)),
- unop(Iop_Abs32x4,
- binop(Iop_Sub32x4,
- mkexpr(t1),
- mkexpr(t2)))),
- binop(Iop_AndV128,
- mkexpr(t3),
- binop(Iop_Sub32x4,
- binop(Iop_Max32Ux4,
- mkexpr(t1),
- mkexpr(t2)),
- binop(Iop_Min32Ux4,
- mkexpr(t1),
- mkexpr(t2))))));
- break;
- }
+ mkexpr(t1), mkU8(16)),
+ binop(Iop_SarN32x4,
+ binop(Iop_ShlN32x4,
+ mkexpr(t2), mkU8(16)),
+ mkU8(16))));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
+
+ case 0x03: { /* HSUB_S.D */
+ DIP("HSUB_S.D w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3,
+ binop(Iop_Sub64x2,
+ binop(Iop_SarN64x2,
+ mkexpr(t1), mkU8(32)),
+ binop(Iop_SarN64x2,
+ binop(Iop_ShlN64x2,
+ mkexpr(t2), mkU8(32)),
+ mkU8(32))));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
+
+ default:
+ return -1;
+ }
+
+ break;
+ }
+
+ case 0x07: { /* HSUB_U.df */
+ switch (df) {
+ case 0x01: { /* HSUB_U.H */
+ DIP("HSUB_U.H w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3,
+ binop(Iop_Sub16x8,
+ binop(Iop_ShrN16x8,
+ mkexpr(t1), mkU8(8)),
+ binop(Iop_ShrN16x8,
+ binop(Iop_ShlN16x8,
+ mkexpr(t2), mkU8(8)),
+ mkU8(8))));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- case 0x03: { /* ASUB_U.D */
- DIP("ASUB_U.D w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3,
- binop(Iop_SarN64x2,
- binop(Iop_XorV128,
- mkexpr(t1), mkexpr(t2)),
- mkU8(63)));
- putWReg(wd,
- binop(Iop_OrV128,
- binop(Iop_AndV128,
- unop(Iop_NotV128, mkexpr(t3)),
- unop(Iop_Abs64x2,
- binop(Iop_Sub64x2,
- mkexpr(t1),
- mkexpr(t2)))),
- binop(Iop_AndV128,
- mkexpr(t3),
- binop(Iop_Sub64x2,
- binop(Iop_Max64Ux2,
- mkexpr(t1),
- mkexpr(t2)),
- binop(Iop_Min64Ux2,
- mkexpr(t1),
- mkexpr(t2))))));
- break;
- }
+ case 0x02: { /* HSUB_U.W */
+ DIP("HSUB_U.W w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3,
+ binop(Iop_Sub32x4,
+ binop(Iop_ShrN32x4,
+ mkexpr(t1), mkU8(16)),
+ binop(Iop_ShrN32x4,
+ binop(Iop_ShlN32x4,
+ mkexpr(t2), mkU8(16)),
+ mkU8(16))));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- default:
- return -1;
+ case 0x03: { /* HSUB_U.D */
+ DIP("HSUB_U.D w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3,
+ binop(Iop_Sub64x2,
+ binop(Iop_ShrN64x2,
+ mkexpr(t1), mkU8(32)),
+ binop(Iop_ShrN64x2,
+ binop(Iop_ShlN64x2,
+ mkexpr(t2), mkU8(32)),
+ mkU8(32))));
+ putWReg(wd, mkexpr(t3));
+ break;
}
- break;
+ default:
+ return -1;
}
+ break;
+ }
+
default:
return -1;
}
return 0;
}
-static Int msa_3R_12(UInt cins, UChar wd, UChar ws) { /* 3R (0x12) */
- IRTemp t1, t2, t3, t4, t5, t6;
+static Int msa_3R_1A(UInt cins, UChar wd, UChar ws) /* 3R (0x1A) */
+{
UShort operation;
UChar df, wt;
- operation = (cins & 0x03800000) >> 23;
- df = (cins & 0x00600000) >> 21;
+ operation = (cins & 0x03C00000) >> 22;
+ df = (cins & 0x00200000) >> 21;
wt = (cins & 0x001F0000) >> 16;
switch (operation) {
- case 0x00: { /* MULV.df */
- switch (df) {
- case 0x00: { /* MULV.B */
- DIP("MULV.B w%d, w%d, w%d", wd, ws, wt);
- putWReg(wd, binop(Iop_Mul8x16, getWReg(ws), getWReg(wt)));
- break;
- }
+ case 0x00: { /* FCAF.df */
+ switch (df) {
+ case 0x00: { /* FCAF.W */
+ DIP("FCAF.W w%d, w%d, w%d", wd, ws, wt);
+ calculateMSACSR(ws, wt, FCAFW, 2);
+ putWReg(wd, binop(Iop_64HLtoV128, mkU64(0ul), mkU64(0ul)));
+ break;
+ }
- case 0x01: { /* MULV.H */
- DIP("MULV.H w%d, w%d, w%d", wd, ws, wt);
- putWReg(wd, binop(Iop_Mul16x8, getWReg(ws), getWReg(wt)));
- break;
- }
+ case 0x01: { /* FCAF.D */
+ DIP("FCAF.D w%d, w%d, w%d", wd, ws, wt);
+ calculateMSACSR(ws, wt, FCAFD, 2);
+ putWReg(wd, binop(Iop_64HLtoV128, mkU64(0ul), mkU64(0ul)));
+ break;
+ }
- case 0x02: { /* MULV.W */
- DIP("MULV.W w%d, w%d, w%d", wd, ws, wt);
- putWReg(wd, binop(Iop_Mul32x4, getWReg(ws), getWReg(wt)));
- break;
- }
+ default:
+ return -1;
+ }
- case 0x03: { /* MULV.D */
- DIP("MULV.D w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- putWReg(wd,
- binop(Iop_64HLtoV128,
- binop(Iop_Mul64,
- unop(Iop_V128HIto64,
- mkexpr(t1)),
- unop(Iop_V128HIto64,
- mkexpr(t2))),
- binop(Iop_Mul64,
- unop(Iop_V128to64,
- mkexpr(t1)),
- unop(Iop_V128to64,
- mkexpr(t2)))));
- break;
- }
+ break;
+ }
- default:
- return -1;
+ case 0x01: { /* FCUN.df */
+ switch (df) {
+ case 0x00: { /* FCUN.W */
+ DIP("FCUN.W w%d, w%d, w%d", wd, ws, wt);
+ calculateMSACSR(ws, wt, FCUNW, 2);
+ putWReg(wd, binop(Iop_CmpUN32Fx4,
+ getWReg(ws),
+ getWReg(wt)));
+ break;
}
- break;
+ case 0x01: { /* FCUN.D */
+ DIP("FCUN.D w%d, w%d, w%d", wd, ws, wt);
+ calculateMSACSR(ws, wt, FCUND, 2);
+ putWReg(wd, binop(Iop_CmpUN64Fx2,
+ getWReg(ws),
+ getWReg(wt)));
+ break;
+ }
+
+ default:
+ return -1;
}
- case 0x01: { /* MADDV.df */
- switch (df) {
- case 0x00: { /* MADDV.B */
- DIP("MADDV.B w%d, w%d, w%d", wd, ws, wt);
- putWReg(wd,
- binop(Iop_Add8x16,
- getWReg(wd),
- binop(Iop_Mul8x16,
- getWReg(ws),
- getWReg(wt))));
- break;
- }
+ break;
+ }
- case 0x01: { /* MADDV.H */
- DIP("MADDV.H w%d, w%d, w%d", wd, ws, wt);
- putWReg(wd,
- binop(Iop_Add16x8,
- getWReg(wd),
- binop(Iop_Mul16x8,
- getWReg(ws),
- getWReg(wt))));
- break;
- }
+ case 0x02: { /* FCEQ.df */
+ switch (df) {
+ case 0x00: { /* FCEQ.W */
+ DIP("FCEQ.W w%d, w%d, w%d", wd, ws, wt);
+ calculateMSACSR(ws, wt, FCEQW, 2);
+ putWReg(wd, binop(Iop_CmpEQ32Fx4,
+ getWReg(ws),
+ getWReg(wt)));
+ break;
+ }
- case 0x02: { /* MADDV.W */
- DIP("MADDV.W w%d, w%d, w%d", wd, ws, wt);
- putWReg(wd,
- binop(Iop_Add32x4,
- getWReg(wd),
- binop(Iop_Mul32x4,
- getWReg(ws),
- getWReg(wt))));
- break;
- }
+ case 0x01: { /* FCEQ.D */
+ DIP("FCEQ.D w%d, w%d, w%d", wd, ws, wt);
+ calculateMSACSR(ws, wt, FCEQD, 2);
+ putWReg(wd, binop(Iop_CmpEQ64Fx2,
+ getWReg(ws),
+ getWReg(wt)));
+ break;
+ }
- case 0x03: { /* MADDV.D */
- DIP("MADDV.D w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- putWReg(wd,
- binop(Iop_Add64x2,
- getWReg(wd),
- binop(Iop_64HLtoV128,
- binop(Iop_Mul64,
- unop(Iop_V128HIto64,
- mkexpr(t1)),
- unop(Iop_V128HIto64,
- mkexpr(t2))),
- binop(Iop_Mul64,
- unop(Iop_V128to64,
- mkexpr(t1)),
- unop(Iop_V128to64,
- mkexpr(t2))))));
- break;
- }
+ default:
+ return -1;
+ }
- default:
- return -1;
+ break;
+ }
+
+ case 0x03: { /* FCUEQ.df */
+ switch (df) {
+ case 0x00: { /* FCUEQ.W */
+ DIP("FCUEQ.W w%d, w%d, w%d", wd, ws, wt);
+ calculateMSACSR(ws, wt, FCUEQW, 2);
+ putWReg(wd,
+ binop(Iop_OrV128,
+ binop(Iop_CmpEQ32Fx4,
+ getWReg(ws),
+ getWReg(wt)),
+ binop(Iop_CmpUN32Fx4,
+ getWReg(ws),
+ getWReg(wt))));
+ break;
}
- break;
+ case 0x01: { /* FCUEQ.D */
+ DIP("FCUEQ.D w%d, w%d, w%d", wd, ws, wt);
+ calculateMSACSR(ws, wt, FCUEQD, 2);
+ putWReg(wd,
+ binop(Iop_OrV128,
+ binop(Iop_CmpEQ64Fx2,
+ getWReg(ws),
+ getWReg(wt)),
+ binop(Iop_CmpUN64Fx2,
+ getWReg(ws),
+ getWReg(wt))));
+ break;
+ }
+
+ default:
+ return -1;
}
- case 0x02: { /* MSUBV.df */
- switch (df) {
- case 0x00: { /* MSUBV.B */
- DIP("MSUBV.B w%d, w%d, w%d", wd, ws, wt);
- putWReg(wd,
- binop(Iop_Sub8x16,
- getWReg(wd),
- binop(Iop_Mul8x16,
- getWReg(ws),
- getWReg(wt))));
- break;
- }
+ break;
+ }
- case 0x01: { /* MSUBV.H */
- DIP("MSUBV.H w%d, w%d, w%d", wd, ws, wt);
- putWReg(wd,
- binop(Iop_Sub16x8,
- getWReg(wd),
- binop(Iop_Mul16x8,
- getWReg(ws),
- getWReg(wt))));
- break;
- }
+ case 0x04: { /* FCLT.df */
+ switch (df) {
+ case 0x00: { /* FCLT.W */
+ DIP("FCLT.W w%d, w%d, w%d", wd, ws, wt);
+ calculateMSACSR(ws, wt, FCLTW, 2);
+ putWReg(wd,
+ binop(Iop_CmpLT32Fx4,
+ getWReg(ws),
+ getWReg(wt)));
+ break;
+ }
- case 0x02: { /* MSUBV.W */
- DIP("MSUBV.W w%d, w%d, w%d", wd, ws, wt);
- putWReg(wd,
- binop(Iop_Sub32x4,
- getWReg(wd),
- binop(Iop_Mul32x4,
- getWReg(ws),
- getWReg(wt))));
- break;
- }
+ case 0x01: { /* FCLT.D */
+ DIP("FCLT.D w%d, w%d, w%d", wd, ws, wt);
+ calculateMSACSR(ws, wt, FCLTD, 2);
+ putWReg(wd,
+ binop(Iop_CmpLT64Fx2,
+ getWReg(ws),
+ getWReg(wt)));
+ break;
+ }
- case 0x03: { /* MSUBV.D */
- DIP("MSUBV.D w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- putWReg(wd,
- binop(Iop_Sub64x2,
- getWReg(wd),
- binop(Iop_64HLtoV128,
- binop(Iop_Mul64,
- unop(Iop_V128HIto64,
- mkexpr(t1)),
- unop(Iop_V128HIto64,
- mkexpr(t2))),
- binop(Iop_Mul64,
- unop(Iop_V128to64,
- mkexpr(t1)),
- unop(Iop_V128to64,
- mkexpr(t2))))));
- break;
- }
+ default:
+ return -1;
+ }
- default:
- return -1;
+ break;
+ }
+
+ case 0x05: { /* FCULT.df */
+ switch (df) {
+ case 0x00: { /* FCULT.W */
+ DIP("FCULT.W w%d, w%d, w%d", wd, ws, wt);
+ calculateMSACSR(ws, wt, FCULTW, 2);
+ putWReg(wd,
+ binop(Iop_OrV128,
+ binop(Iop_CmpLT32Fx4,
+ getWReg(ws),
+ getWReg(wt)),
+ binop(Iop_CmpUN32Fx4,
+ getWReg(ws),
+ getWReg(wt))));
+ break;
+ }
+
+ case 0x01: { /* FCULT.D */
+ DIP("FCULT.D w%d, w%d, w%d", wd, ws, wt);
+ calculateMSACSR(ws, wt, FCULTD, 2);
+ putWReg(wd,
+ binop(Iop_OrV128,
+ binop(Iop_CmpLT64Fx2,
+ getWReg(ws),
+ getWReg(wt)),
+ binop(Iop_CmpUN64Fx2,
+ getWReg(ws),
+ getWReg(wt))));
+ break;
+ }
+
+ default:
+ return -1;
+ }
+
+ break;
+ }
+
+ case 0x06: { /* FCLE.df */
+ switch (df) {
+ case 0x00: { /* FCLE.W */
+ DIP("FCLE.W w%d, w%d, w%d", wd, ws, wt);
+ calculateMSACSR(ws, wt, FCLEW, 2);
+ putWReg(wd,
+ binop(Iop_CmpLE32Fx4,
+ getWReg(ws),
+ getWReg(wt)));
+ break;
+ }
+
+ case 0x01: { /* FCLE.D */
+ DIP("FCLE.D w%d, w%d, w%d", wd, ws, wt);
+ calculateMSACSR(ws, wt, FCLED, 2);
+ putWReg(wd,
+ binop(Iop_CmpLE64Fx2,
+ getWReg(ws),
+ getWReg(wt)));
+ break;
+ }
+
+ default:
+ return -1;
+ }
+
+ break;
+ }
+
+ case 0x07: { /* FCULE.df */
+ switch (df) {
+ case 0x00: { /* FCULE.W */
+ DIP("FCULE.W w%d, w%d, w%d", wd, ws, wt);
+ calculateMSACSR(ws, wt, FCULEW, 2);
+ putWReg(wd,
+ binop(Iop_OrV128,
+ binop(Iop_CmpLE32Fx4,
+ getWReg(ws),
+ getWReg(wt)),
+ binop(Iop_CmpUN32Fx4,
+ getWReg(ws),
+ getWReg(wt))));
+ break;
+ }
+
+ case 0x01: { /* FCULE.D */
+ DIP("FCULE.D w%d, w%d, w%d", wd, ws, wt);
+ calculateMSACSR(ws, wt, FCULED, 2);
+ putWReg(wd,
+ binop(Iop_OrV128,
+ binop(Iop_CmpLE64Fx2,
+ getWReg(ws),
+ getWReg(wt)),
+ binop(Iop_CmpUN64Fx2,
+ getWReg(ws),
+ getWReg(wt))));
+ break;
+ }
+
+ default:
+ return -1;
+ }
+
+ break;
+ }
+
+ case 0x08: { /* FSAF.df */
+ switch (df) {
+ case 0x00: { /* FSAF.W */
+ DIP("FSAF.W w%d, w%d, w%d", wd, ws, wt);
+ calculateMSACSR(ws, wt, FSAFW, 2);
+ putWReg(wd,
+ binop(Iop_64HLtoV128,
+ mkU64(0ul), mkU64(0ul)));
+ break;
+ }
+
+ case 0x01: { /* FSAF.D */
+ DIP("FSAF.D w%d, w%d, w%d", wd, ws, wt);
+ calculateMSACSR(ws, wt, FSAFD, 2);
+ putWReg(wd,
+ binop(Iop_64HLtoV128,
+ mkU64(0ul), mkU64(0ul)));
+ break;
}
- break;
+ default:
+ return -1;
}
- case 0x04: { /* DIV_S.df */
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
-
- switch (df) {
- case 0x00: { /* DIV_S.B */
- DIP("DIV_S.B w%d, w%d, w%d", wd, ws, wt);
- IRTemp tmp[16];
- Int i;
+ break;
+ }
- for (i = 0; i < 16; i++) {
- tmp[i] = newTemp(Ity_I32);
- assign(tmp[i],
- binop(Iop_Shl32,
- binop(Iop_And32,
- mkU32(0xFF),
- binop(Iop_DivS32,
- unop(Iop_8Sto32,
- binop(Iop_GetElem8x16,
- mkexpr(t1),
- mkU8(i))),
- unop(Iop_8Sto32,
- binop(Iop_GetElem8x16,
- mkexpr(t2),
- mkU8(i))))),
- mkU8((i & 3) << 3)));
- }
+ case 0x09: { /* FSUN.df */
+ switch (df) {
+ case 0x00: { /* FSUN.W */
+ DIP("FSUN.W w%d, w%d, w%d", wd, ws, wt);
+ calculateMSACSR(ws, wt, FSUNW, 2);
+ putWReg(wd,
+ binop(Iop_CmpUN32Fx4,
+ getWReg(ws),
+ getWReg(wt)));
+ break;
+ }
- putWReg(wd,
- binop(Iop_64HLtoV128,
- binop(Iop_32HLto64,
- binop(Iop_Or32,
- mkexpr(tmp[15]),
- binop(Iop_Or32,
- mkexpr(tmp[14]),
- binop(Iop_Or32,
- mkexpr(tmp[13]),
- mkexpr(tmp[12])))),
- binop(Iop_Or32,
- mkexpr(tmp[11]),
- binop(Iop_Or32,
- mkexpr(tmp[10]),
- binop(Iop_Or32,
- mkexpr(tmp[9]),
- mkexpr(tmp[8]))))),
- binop(Iop_32HLto64,
- binop(Iop_Or32,
- mkexpr(tmp[7]),
- binop(Iop_Or32,
- mkexpr(tmp[6]),
- binop(Iop_Or32,
- mkexpr(tmp[5]),
- mkexpr(tmp[4])))),
- binop(Iop_Or32,
- mkexpr(tmp[3]),
- binop(Iop_Or32,
- mkexpr(tmp[2]),
- binop(Iop_Or32,
- mkexpr(tmp[1]),
- mkexpr(tmp[0]))))))
- );
- break;
- }
+ case 0x01: { /* FSUN.D */
+ DIP("FSUN.D w%d, w%d, w%d", wd, ws, wt);
+ calculateMSACSR(ws, wt, FSUND, 2);
+ putWReg(wd,
+ binop(Iop_CmpUN64Fx2,
+ getWReg(ws),
+ getWReg(wt)));
+ break;
+ }
- case 0x01: { /* DIV_S.H */
- DIP("DIV_S.H w%d, w%d, w%d", wd, ws, wt);
- IRTemp tmp[8];
- Int i;
+ default:
+ return -1;
+ }
- for (i = 0; i < 8; i++) {
- tmp[i] = newTemp(Ity_I32);
- assign(tmp[i],
- binop(Iop_Shl32,
- binop(Iop_And32,
- mkU32(0xFFFF),
- binop(Iop_DivS32,
- unop(Iop_16Sto32,
- binop(Iop_GetElem16x8,
- mkexpr(t1),
- mkU8(i))),
- unop(Iop_16Sto32,
- binop(Iop_GetElem16x8,
- mkexpr(t2),
- mkU8(i))))),
- mkU8((i & 1) << 4)));
- }
+ break;
+ }
- putWReg(wd,
- binop(Iop_64HLtoV128,
- binop(Iop_32HLto64,
- binop(Iop_Or32,
- mkexpr(tmp[7]),
- mkexpr(tmp[6])),
- binop(Iop_Or32,
- mkexpr(tmp[5]),
- mkexpr(tmp[4]))),
- binop(Iop_32HLto64,
- binop(Iop_Or32,
- mkexpr(tmp[3]),
- mkexpr(tmp[2])),
- binop(Iop_Or32,
- mkexpr(tmp[1]),
- mkexpr(tmp[0])))));
- break;
- }
+ case 0x0A: { /* FSEQ.df */
+ switch (df) {
+ case 0x00: { /* FSEQ.W */
+ DIP("FSEQ.W w%d, w%d, w%d", wd, ws, wt);
+ calculateMSACSR(ws, wt, FSEQW, 2);
+ putWReg(wd,
+ binop(Iop_CmpEQ32Fx4,
+ getWReg(ws),
+ getWReg(wt)));
+ break;
+ }
- case 0x02: { /* DIV_S.W */
- DIP("DIV_S.W w%d, w%d, w%d", wd, ws, wt);
- IRTemp tmp[4];
- Int i;
+ case 0x01: { /* FSEQ.D */
+ DIP("FSEQ.D w%d, w%d, w%d", wd, ws, wt);
+ calculateMSACSR(ws, wt, FSEQD, 2);
+ putWReg(wd,
+ binop(Iop_CmpEQ64Fx2,
+ getWReg(ws),
+ getWReg(wt)));
+ break;
+ }
- for (i = 0; i < 4; i++) {
- tmp[i] = newTemp(Ity_I32);
- assign(tmp[i],
- binop(Iop_DivS32,
- binop(Iop_GetElem32x4,
- mkexpr(t1), mkU8(i)),
- binop(Iop_GetElem32x4,
- mkexpr(t2), mkU8(i))));
- }
+ default:
+ return -1;
+ }
- putWReg(wd,
- binop(Iop_64HLtoV128, \
- binop(Iop_32HLto64,
- mkexpr(tmp[3]),
- mkexpr(tmp[2])),
- binop(Iop_32HLto64,
- mkexpr(tmp[1]),
- mkexpr(tmp[0]))));
- break;
- }
+ break;
+ }
- case 0x03: { /* DIV_S.D */
- DIP("DIV_S.D w%d, w%d, w%d", wd, ws, wt);
- putWReg(wd,
- binop(Iop_64HLtoV128,
- binop(Iop_DivS64,
- unop(Iop_V128HIto64,
- mkexpr(t1)),
- unop(Iop_V128HIto64,
- mkexpr(t2))),
- binop(Iop_DivS64,
- unop(Iop_V128to64,
- mkexpr(t1)),
- unop(Iop_V128to64,
- mkexpr(t2)))));
- break;
- }
+ case 0x0B: { /* FSUEQ.df */
+ switch (df) {
+ case 0x00: { /* FSUEQ.W */
+ DIP("FSUEQ.W w%d, w%d, w%d", wd, ws, wt);
+ calculateMSACSR(ws, wt, FSUEQW, 2);
+ putWReg(wd,
+ binop(Iop_OrV128,
+ binop(Iop_CmpEQ32Fx4,
+ getWReg(ws),
+ getWReg(wt)),
+ binop(Iop_CmpUN32Fx4,
+ getWReg(ws),
+ getWReg(wt))));
+ break;
+ }
- default:
- return -1;
+ case 0x01: { /* FSUEQ.D */
+ DIP("FSUEQ.D w%d, w%d, w%d", wd, ws, wt);
+ calculateMSACSR(ws, wt, FSUEQD, 2);
+ putWReg(wd,
+ binop(Iop_OrV128,
+ binop(Iop_CmpEQ64Fx2,
+ getWReg(ws),
+ getWReg(wt)),
+ binop(Iop_CmpUN64Fx2,
+ getWReg(ws),
+ getWReg(wt))));
+ break;
}
- break;
+ default:
+ return -1;
}
- case 0x05: { /* DIV_U.df */
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
+ break;
+ }
- switch (df) {
- case 0x00: { /* DIV_U.B */
- DIP("DIV_U.B w%d, w%d, w%d", wd, ws, wt);
- IRTemp tmp[16];
- Int i;
+ case 0x0C: { /* FSLT.df */
+ switch (df) {
+ case 0x00: { /* FSLT.W */
+ DIP("FSLT.W w%d, w%d, w%d", wd, ws, wt);
+ calculateMSACSR(ws, wt, FSLTW, 2);
+ putWReg(wd,
+ binop(Iop_CmpLT32Fx4,
+ getWReg(ws),
+ getWReg(wt)));
+ break;
+ }
- for (i = 0; i < 16; i++) {
- tmp[i] = newTemp(Ity_I32);
- assign(tmp[i],
- binop(Iop_Shl32,
- binop(Iop_And32,
- mkU32(0xFF),
- binop(Iop_DivU32,
- unop(Iop_8Uto32,
- binop(Iop_GetElem8x16,
- mkexpr(t1),
- mkU8(i))),
- unop(Iop_8Uto32,
- binop(Iop_GetElem8x16,
- mkexpr(t2),
- mkU8(i))))),
- mkU8((i & 3) << 3)));
- }
+ case 0x01: { /* FSLT.D */
+ DIP("FSLT.D w%d, w%d, w%d", wd, ws, wt);
+ calculateMSACSR(ws, wt, FSLTD, 2);
+ putWReg(wd,
+ binop(Iop_CmpLT64Fx2,
+ getWReg(ws),
+ getWReg(wt)));
+ break;
+ }
- putWReg(wd,
- binop(Iop_64HLtoV128,
- binop(Iop_32HLto64,
- binop(Iop_Or32,
- mkexpr(tmp[15]),
- binop(Iop_Or32,
- mkexpr(tmp[14]),
- binop(Iop_Or32,
- mkexpr(tmp[13]),
- mkexpr(tmp[12])))),
- binop(Iop_Or32,
- mkexpr(tmp[11]),
- binop(Iop_Or32,
- mkexpr(tmp[10]),
- binop(Iop_Or32,
- mkexpr(tmp[9]),
- mkexpr(tmp[8]))))),
- binop(Iop_32HLto64,
- binop(Iop_Or32,
- mkexpr(tmp[7]),
- binop(Iop_Or32,
- mkexpr(tmp[6]),
- binop(Iop_Or32,
- mkexpr(tmp[5]),
- mkexpr(tmp[4])))),
- binop(Iop_Or32,
- mkexpr(tmp[3]),
- binop(Iop_Or32,
- mkexpr(tmp[2]),
- binop(Iop_Or32,
- mkexpr(tmp[1]),
- mkexpr(tmp[0]))))))
- );
- break;
- }
+ default:
+ return -1;
+ }
- case 0x01: { /* DIV_U.H */
- DIP("DIV_U.H w%d, w%d, w%d", wd, ws, wt);
- IRTemp tmp[8];
- Int i;
+ break;
+ }
- for (i = 0; i < 8; i++) {
- tmp[i] = newTemp(Ity_I32);
- assign(tmp[i],
- binop(Iop_Shl32,
- binop(Iop_And32,
- mkU32(0xFFFF),
- binop(Iop_DivU32,
- unop(Iop_16Uto32,
- binop(Iop_GetElem16x8,
- mkexpr(t1),
- mkU8(i))),
- unop(Iop_16Uto32,
- binop(Iop_GetElem16x8,
- mkexpr(t2),
- mkU8(i))))),
- mkU8((i & 1) << 4)));
- }
+ case 0x0D: { /* FSULT.df */
+ switch (df) {
+ case 0x00: { /* FSULT.W */
+ DIP("FSULT.W w%d, w%d, w%d", wd, ws, wt);
+ calculateMSACSR(ws, wt, FSULTW, 2);
+ putWReg(wd,
+ binop(Iop_OrV128,
+ binop(Iop_CmpLT32Fx4,
+ getWReg(ws),
+ getWReg(wt)),
+ binop(Iop_CmpUN32Fx4,
+ getWReg(ws),
+ getWReg(wt))));
+ break;
+ }
+
+ case 0x01: { /* FSULT.D */
+ DIP("FSULT.D w%d, w%d, w%d", wd, ws, wt);
+ calculateMSACSR(ws, wt, FSULTD, 2);
+ putWReg(wd,
+ binop(Iop_OrV128,
+ binop(Iop_CmpLT64Fx2,
+ getWReg(ws),
+ getWReg(wt)),
+ binop(Iop_CmpUN64Fx2,
+ getWReg(ws),
+ getWReg(wt))));
+ break;
+ }
+
+ default:
+ return -1;
+ }
- putWReg(wd,
- binop(Iop_64HLtoV128,
- binop(Iop_32HLto64,
- binop(Iop_Or32,
- mkexpr(tmp[7]),
- mkexpr(tmp[6])),
- binop(Iop_Or32,
- mkexpr(tmp[5]),
- mkexpr(tmp[4]))),
- binop(Iop_32HLto64,
- binop(Iop_Or32,
- mkexpr(tmp[3]),
- mkexpr(tmp[2])),
- binop(Iop_Or32,
- mkexpr(tmp[1]),
- mkexpr(tmp[0])))));
- break;
- }
+ break;
+ }
- case 0x02: { /* DIV_U.W */
- DIP("DIV_U.W w%d, w%d, w%d", wd, ws, wt);
- IRTemp tmp[4];
- Int i;
+ case 0x0E: { /* FSLE.df */
+ switch (df) {
+ case 0x00: { /* FSLE.W */
+ DIP("FSLE.W w%d, w%d, w%d", wd, ws, wt);
+ calculateMSACSR(ws, wt, FSLEW, 2);
+ putWReg(wd,
+ binop(Iop_CmpLE32Fx4,
+ getWReg(ws),
+ getWReg(wt)));
+ break;
+ }
- for (i = 0; i < 4; i++) {
- tmp[i] = newTemp(Ity_I32);
- assign(tmp[i],
- binop(Iop_DivU32,
- binop(Iop_GetElem32x4,
- mkexpr(t1), mkU8(i)),
- binop(Iop_GetElem32x4,
- mkexpr(t2), mkU8(i))));
- }
+ case 0x01: { /* FSLE.D */
+ DIP("FSLE.D w%d, w%d, w%d", wd, ws, wt);
+ calculateMSACSR(ws, wt, FSLED, 2);
+ putWReg(wd,
+ binop(Iop_CmpLE64Fx2,
+ getWReg(ws),
+ getWReg(wt)));
+ break;
+ }
- putWReg(wd,
- binop(Iop_64HLtoV128,
- binop(Iop_32HLto64,
- mkexpr(tmp[3]),
- mkexpr(tmp[2])),
- binop(Iop_32HLto64,
- mkexpr(tmp[1]),
- mkexpr(tmp[0]))));
- break;
- }
+ default:
+ return -1;
+ }
- case 0x03: { /* DIV_U.D */
- DIP("DIV_U.D w%d, w%d, w%d", wd, ws, wt);
- putWReg(wd,
- binop(Iop_64HLtoV128,
- binop(Iop_DivU64,
- unop(Iop_V128HIto64,
- mkexpr(t1)),
- unop(Iop_V128HIto64,
- mkexpr(t2))),
- binop(Iop_DivU64,
- unop(Iop_V128to64,
- mkexpr(t1)),
- unop(Iop_V128to64,
- mkexpr(t2)))));
- break;
- }
+ break;
+ }
- default:
- return -1;
+ case 0x0F: { /* FSULE.df */
+ switch (df) {
+ case 0x00: { /* FSULE.W */
+ DIP("FSULE.W w%d, w%d, w%d", wd, ws, wt);
+ calculateMSACSR(ws, wt, FSULEW, 2);
+ putWReg(wd,
+ binop(Iop_OrV128,
+ binop(Iop_CmpLE32Fx4,
+ getWReg(ws),
+ getWReg(wt)),
+ binop(Iop_CmpUN32Fx4,
+ getWReg(ws),
+ getWReg(wt))));
+ break;
}
- break;
+ case 0x01: { /* FSULE.D */
+ DIP("FSULE.D w%d, w%d, w%d", wd, ws, wt);
+ calculateMSACSR(ws, wt, FSULED, 2);
+ putWReg(wd,
+ binop(Iop_OrV128,
+ binop(Iop_CmpLE64Fx2,
+ getWReg(ws),
+ getWReg(wt)),
+ binop(Iop_CmpUN64Fx2,
+ getWReg(ws),
+ getWReg(wt))));
+ break;
+ }
+
+ default:
+ return -1;
}
- case 0x06: { /* MOD_S.df */
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
+ break;
+ }
- switch (df) {
- case 0x00: { /* MOD_S.B */
- DIP("MOD_S.B w%d, w%d, w%d", wd, ws, wt);
- IRTemp tmp[16];
- Int i;
+ default:
+ return -1;
+ }
- for (i = 0; i < 16; i++) {
- tmp[i] = newTemp(Ity_I32);
- assign(tmp[i],
- binop(Iop_Shl32,
- binop(Iop_And32,
- mkU32(0xFF),
- unop(Iop_64HIto32,
- binop(Iop_DivModS32to32,
- unop(Iop_8Sto32,
- binop(Iop_GetElem8x16,
- mkexpr(t1),
- mkU8(i))),
- unop(Iop_8Sto32,
- binop(Iop_GetElem8x16,
- mkexpr(t2),
- mkU8(i)))))),
- mkU8((i & 3) << 3)));
- }
+ return 0;
+}
- putWReg(wd,
- binop(Iop_64HLtoV128,
- binop(Iop_32HLto64,
- binop(Iop_Or32,
- mkexpr(tmp[15]),
- binop(Iop_Or32,
- mkexpr(tmp[14]),
- binop(Iop_Or32,
- mkexpr(tmp[13]),
- mkexpr(tmp[12])))),
- binop(Iop_Or32,
- mkexpr(tmp[11]),
- binop(Iop_Or32,
- mkexpr(tmp[10]),
- binop(Iop_Or32,
- mkexpr(tmp[9]),
- mkexpr(tmp[8]))))),
- binop(Iop_32HLto64,
- binop(Iop_Or32,
- mkexpr(tmp[7]),
- binop(Iop_Or32,
- mkexpr(tmp[6]),
- binop(Iop_Or32,
- mkexpr(tmp[5]),
- mkexpr(tmp[4])))),
- binop(Iop_Or32,
- mkexpr(tmp[3]),
- binop(Iop_Or32,
- mkexpr(tmp[2]),
- binop(Iop_Or32,
- mkexpr(tmp[1]),
- mkexpr(tmp[0])))))));
- break;
- }
+static Int msa_3R_1B(UInt cins, UChar wd, UChar ws) /* 3R (0x1B) */
+{
+ IRTemp t1, t2, t3, t4;
+ UShort operation;
+ UChar df, wt;
- case 0x01: { /* MOD_S.H */
- DIP("MOD_S.H w%d, w%d, w%d", wd, ws, wt);
- IRTemp tmp[8];
- Int i;
+ operation = (cins & 0x03C00000) >> 22;
+ df = (cins & 0x00200000) >> 21;
+ wt = (cins & 0x001F0000) >> 16;
- for (i = 0; i < 8; i++) {
- tmp[i] = newTemp(Ity_I32);
- assign(tmp[i],
- binop(Iop_Shl32,
- binop(Iop_And32,
- mkU32(0xFFFF),
- unop(Iop_64HIto32,
- binop(Iop_DivModS32to32,
- unop(Iop_16Sto32,
- binop(Iop_GetElem16x8,
- mkexpr(t1),
- mkU8(i))),
- unop(Iop_16Sto32,
- binop(Iop_GetElem16x8,
- mkexpr(t2),
- mkU8(i)))))),
- mkU8((i & 1) << 4)));
- }
+ switch (operation) {
+ case 0x00: { /* FADD.df */
+ switch (df) {
+ case 0x00: { /* FADD.W */
+ DIP("FADD.W w%d, w%d, w%d", wd, ws, wt);
+ calculateMSACSR(ws, wt, FADDW, 2);
+ IRExpr *rm = get_IR_roundingmode_MSA();
+ putWReg(wd,
+ triop(Iop_Add32Fx4, rm,
+ getWReg(ws),
+ getWReg(wt)));
+ break;
+ }
- putWReg(wd,
- binop(Iop_64HLtoV128,
- binop(Iop_32HLto64,
- binop(Iop_Or32,
- mkexpr(tmp[7]),
- mkexpr(tmp[6])),
- binop(Iop_Or32,
- mkexpr(tmp[5]),
- mkexpr(tmp[4]))),
- binop(Iop_32HLto64,
- binop(Iop_Or32,
- mkexpr(tmp[3]),
- mkexpr(tmp[2])),
- binop(Iop_Or32,
- mkexpr(tmp[1]),
- mkexpr(tmp[0])))));
- break;
- }
+ case 0x01: { /* FADD.D */
+ DIP("FADD.D w%d, w%d, w%d", wd, ws, wt);
+ calculateMSACSR(ws, wt, FADDD, 2);
+ IRExpr *rm = get_IR_roundingmode_MSA();
+ putWReg(wd,
+ triop(Iop_Add64Fx2, rm,
+ getWReg(ws),
+ getWReg(wt)));
+ break;
+ }
- case 0x02: { /* MOD_S.W */
- DIP("MOD_S.W w%d, w%d, w%d", wd, ws, wt);
- IRTemp tmp[4];
- Int i;
+ default:
+ return -1;
+ }
- for (i = 0; i < 4; i++) {
- tmp[i] = newTemp(Ity_I32);
- assign(tmp[i],
- unop(Iop_64HIto32,
- binop(Iop_DivModS32to32,
- binop(Iop_GetElem32x4,
- mkexpr(t1),
- mkU8(i)),
- binop(Iop_GetElem32x4,
- mkexpr(t2),
- mkU8(i)))));
- }
+ break;
+ }
- putWReg(wd,
- binop(Iop_64HLtoV128,
- binop(Iop_32HLto64,
- mkexpr(tmp[3]),
- mkexpr(tmp[2])),
- binop(Iop_32HLto64,
- mkexpr(tmp[1]),
- mkexpr(tmp[0]))));
- break;
- }
+ case 0x01: { /* FSUB.df */
+ switch (df) {
+ case 0x00: { /* FSUB.W */
+ DIP("FSUB.W w%d, w%d, w%d", wd, ws, wt);
+ calculateMSACSR(ws, wt, FSUBW, 2);
+ IRExpr *rm = get_IR_roundingmode_MSA();
+ putWReg(wd,
+ triop(Iop_Sub32Fx4, rm,
+ getWReg(ws),
+ getWReg(wt)));
+ break;
+ }
- case 0x03: { /* MOD_S.D */
- DIP("MOD_S.D w%d, w%d, w%d", wd, ws, wt);
- t3 = newTemp(Ity_I64);
- t4 = newTemp(Ity_I64);
- t5 = newTemp(Ity_I64);
- t6 = newTemp(Ity_I64);
- assign(t3, unop(Iop_V128HIto64, mkexpr(t1)));
- assign(t4, unop(Iop_V128HIto64, mkexpr(t2)));
- assign(t5, unop(Iop_V128to64, mkexpr(t1)));
- assign(t6, unop(Iop_V128to64, mkexpr(t2)));
- putWReg(wd,
- binop(Iop_64HLtoV128,
- binop(Iop_Sub64,
- mkexpr(t3),
- binop(Iop_Mul64,
- mkexpr(t4),
- binop(Iop_DivS64,
- mkexpr(t3),
- mkexpr(t4)))),
- binop(Iop_Sub64,
- mkexpr(t5),
- binop(Iop_Mul64,
- mkexpr(t6),
- binop(Iop_DivS64,
- mkexpr(t5),
- mkexpr(t6))))));
- break;
- }
+ case 0x01: { /* FSUB.D */
+ DIP("FSUB.D w%d, w%d, w%d", wd, ws, wt);
+ calculateMSACSR(ws, wt, FSUBD, 2);
+ IRExpr *rm = get_IR_roundingmode_MSA();
+ putWReg(wd,
+ triop(Iop_Sub64Fx2, rm,
+ getWReg(ws),
+ getWReg(wt)));
+ break;
+ }
- default:
- return -1;
+ default:
+ return -1;
+ }
+
+ break;
+ }
+
+ case 0x02: { /* FMUL.df */
+ switch (df) {
+ case 0x00: { /* FMUL.W */
+ DIP("FMUL.W w%d, w%d, w%d", wd, ws, wt);
+ calculateMSACSR(ws, wt, FMULW, 2);
+ IRExpr *rm = get_IR_roundingmode_MSA();
+ putWReg(wd,
+ triop(Iop_Mul32Fx4, rm,
+ getWReg(ws),
+ getWReg(wt)));
+ break;
}
- break;
+ case 0x01: { /* FMUL.D */
+ DIP("FMUL.D w%d, w%d, w%d", wd, ws, wt);
+ calculateMSACSR(ws, wt, FMULW, 2);
+ IRExpr *rm = get_IR_roundingmode_MSA();
+ putWReg(wd,
+ triop(Iop_Mul64Fx2, rm,
+ getWReg(ws),
+ getWReg(wt)));
+ break;
+ }
+
+ default:
+ return -1;
}
- case 0x07: { /* MOD_U.df */
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
+ break;
+ }
- switch (df) {
- case 0x00: { /* MOD_U.B */
- DIP("MOD_U.B w%d, w%d, w%d", wd, ws, wt);
- IRTemp tmp[16];
- Int i;
+ case 0x03: { /* FDIV.df */
+ switch (df) {
+ case 0x00: { /* FDIV.W */
+ DIP("FDIV.W w%d, w%d, w%d", wd, ws, wt);
+ calculateMSACSR(ws, wt, FDIVW, 2);
+ IRExpr *rm = get_IR_roundingmode_MSA();
+ putWReg(wd,
+ triop(Iop_Div32Fx4, rm,
+ getWReg(ws),
+ getWReg(wt)));
+ break;
+ }
- for (i = 0; i < 16; i++) {
- tmp[i] = newTemp(Ity_I32);
- assign(tmp[i],
- binop(Iop_Shl32,
- binop(Iop_And32,
- mkU32(0xFF),
- unop(Iop_64HIto32,
- binop(Iop_DivModU32to32,
- unop(Iop_8Uto32,
- binop(Iop_GetElem8x16,
- mkexpr(t1),
- mkU8(i))),
- unop(Iop_8Uto32,
- binop(Iop_GetElem8x16,
- mkexpr(t2),
- mkU8(i)))))),
- mkU8((i & 3) << 3)));
- }
+ case 0x01: { /* FDIV.D */
+ DIP("FDIV.D w%d, w%d, w%d", wd, ws, wt);
+ calculateMSACSR(ws, wt, FDIVD, 2);
+ IRExpr *rm = get_IR_roundingmode_MSA();
+ putWReg(wd,
+ triop(Iop_Div64Fx2, rm,
+ getWReg(ws),
+ getWReg(wt)));
+ break;
+ }
- putWReg(wd,
- binop(Iop_64HLtoV128,
- binop(Iop_32HLto64,
- binop(Iop_Or32,
- mkexpr(tmp[15]),
- binop(Iop_Or32,
- mkexpr(tmp[14]),
- binop(Iop_Or32,
- mkexpr(tmp[13]),
- mkexpr(tmp[12])))),
- binop(Iop_Or32,
- mkexpr(tmp[11]),
- binop(Iop_Or32,
- mkexpr(tmp[10]),
- binop(Iop_Or32,
- mkexpr(tmp[9]),
- mkexpr(tmp[8]))))),
- binop(Iop_32HLto64,
- binop(Iop_Or32,
- mkexpr(tmp[7]),
- binop(Iop_Or32,
- mkexpr(tmp[6]),
- binop(Iop_Or32,
- mkexpr(tmp[5]),
- mkexpr(tmp[4])))),
- binop(Iop_Or32,
- mkexpr(tmp[3]),
- binop(Iop_Or32,
- mkexpr(tmp[2]),
- binop(Iop_Or32,
- mkexpr(tmp[1]),
- mkexpr(tmp[0])))))));
- break;
- }
+ default:
+ return -1;
+ }
- case 0x01: { /* MOD_U.H */
- DIP("MOD_U.H w%d, w%d, w%d", wd, ws, wt);
- IRTemp tmp[8];
- Int i;
+ break;
+ }
- for (i = 0; i < 8; i++) {
- tmp[i] = newTemp(Ity_I32);
- assign(tmp[i],
- binop(Iop_Shl32,
- binop(Iop_And32,
- mkU32(0xFFFF),
- unop(Iop_64HIto32,
- binop(Iop_DivModU32to32,
- unop(Iop_16Uto32,
- binop(Iop_GetElem16x8,
- mkexpr(t1),
- mkU8(i))),
- unop(Iop_16Uto32,
- binop(Iop_GetElem16x8,
- mkexpr(t2),
- mkU8(i)))))),
- mkU8((i & 1) << 4)));
- }
+ case 0x04: { /* FMADD.df */
+ switch (df) {
+ case 0x00: { /* FMADD.W */
+ DIP("FMADD.W w%d, w%d, w%d", wd, ws, wt);
+ calculateMSACSR(ws, wt, FMADDW, 2);
+ IRExpr *rm = get_IR_roundingmode_MSA();
+ IRTemp tmp[4];
+ Int i;
+
+ for (i = 0; i < 4; i++) {
+ tmp[i] = newTemp(Ity_F32);
+ assign(tmp[i],
+ qop(Iop_MAddF32, rm,
+ unop(Iop_ReinterpI32asF32,
+ binop(Iop_GetElem32x4,
+ getWReg(ws),
+ mkU8(i))),
+ unop(Iop_ReinterpI32asF32,
+ binop(Iop_GetElem32x4,
+ getWReg(wt),
+ mkU8(i))),
+ unop(Iop_ReinterpI32asF32,
+ binop(Iop_GetElem32x4,
+ getWReg(wd),
+ mkU8(i)))));
+ }
- putWReg(wd,
- binop(Iop_64HLtoV128,
- binop(Iop_32HLto64,
- binop(Iop_Or32,
- mkexpr(tmp[7]),
- mkexpr(tmp[6])),
- binop(Iop_Or32,
- mkexpr(tmp[5]),
- mkexpr(tmp[4]))),
- binop(Iop_32HLto64,
- binop(Iop_Or32,
- mkexpr(tmp[3]),
- mkexpr(tmp[2])),
- binop(Iop_Or32,
- mkexpr(tmp[1]),
- mkexpr(tmp[0])))));
- break;
- }
+ putWReg(wd,
+ binop(Iop_64HLtoV128,
+ binop(Iop_32HLto64,
+ unop(Iop_ReinterpF32asI32,
+ mkexpr(tmp[3])),
+ unop(Iop_ReinterpF32asI32,
+ mkexpr(tmp[2]))),
+ binop(Iop_32HLto64,
+ unop(Iop_ReinterpF32asI32,
+ mkexpr(tmp[1])),
+ unop(Iop_ReinterpF32asI32,
+ mkexpr(tmp[0])))));
+ break;
+ }
+
+ case 0x01: { /* FMADD.D */
+ DIP("FMADD.D w%d, w%d, w%d", wd, ws, wt);
+ calculateMSACSR(ws, wt, FMADDW, 2);
+ IRExpr *rm = get_IR_roundingmode_MSA();
+ IRTemp tmp[2];
+ Int i;
+
+ for (i = 0; i < 2; i++) {
+ tmp[i] = newTemp(Ity_F64);
+ assign(tmp[i],
+ qop(Iop_MAddF64, rm,
+ unop(Iop_ReinterpI64asF64,
+ binop(Iop_GetElem64x2,
+ getWReg(ws),
+ mkU8(i))),
+ unop(Iop_ReinterpI64asF64,
+ binop(Iop_GetElem64x2,
+ getWReg(wt),
+ mkU8(i))),
+ unop(Iop_ReinterpI64asF64,
+ binop(Iop_GetElem64x2,
+ getWReg(wd),
+ mkU8(i)))));
+ }
- case 0x02: { /* MOD_U.W */
- DIP("MOD_U.W w%d, w%d, w%d", wd, ws, wt);
- IRTemp tmp[4];
- Int i;
+ putWReg(wd,
+ binop(Iop_64HLtoV128,
+ unop(Iop_ReinterpF64asI64,
+ mkexpr(tmp[1])),
+ unop(Iop_ReinterpF64asI64,
+ mkexpr(tmp[0]))));
+ break;
+ }
- for (i = 0; i < 4; i++) {
- tmp[i] = newTemp(Ity_I32);
- assign(tmp[i],
- unop(Iop_64HIto32,
- binop(Iop_DivModU32to32,
- binop(Iop_GetElem32x4,
- mkexpr(t1),
- mkU8(i)),
- binop(Iop_GetElem32x4,
- mkexpr(t2),
- mkU8(i)))));
- }
+ default:
+ return -1;
+ }
- putWReg(wd,
- binop(Iop_64HLtoV128,
- binop(Iop_32HLto64,
- mkexpr(tmp[3]),
- mkexpr(tmp[2])),
- binop(Iop_32HLto64,
- mkexpr(tmp[1]),
- mkexpr(tmp[0]))));
- break;
- }
+ break;
+ }
- case 0x03: { /* MOD_U.D */
- DIP("MOD_U.D w%d, w%d, w%d", wd, ws, wt);
- t3 = newTemp(Ity_I64);
- t4 = newTemp(Ity_I64);
- t5 = newTemp(Ity_I64);
- t6 = newTemp(Ity_I64);
- assign(t3, unop(Iop_V128HIto64, mkexpr(t1)));
- assign(t4, unop(Iop_V128HIto64, mkexpr(t2)));
- assign(t5, unop(Iop_V128to64, mkexpr(t1)));
- assign(t6, unop(Iop_V128to64, mkexpr(t2)));
- putWReg(wd,
- binop(Iop_64HLtoV128,
- binop(Iop_Sub64,
- mkexpr(t3),
- binop(Iop_Mul64,
- mkexpr(t4),
- binop(Iop_DivU64,
- mkexpr(t3),
- mkexpr(t4)))),
- binop(Iop_Sub64,
- mkexpr(t5),
- binop(Iop_Mul64,
- mkexpr(t6),
- binop(Iop_DivU64,
- mkexpr(t5),
- mkexpr(t6))))));
- break;
- }
+ case 0x05: { /* FMSUB.df */
+ switch (df) {
+ case 0x00: { /* FMSUB.W */
+ DIP("FMSUB.W w%d, w%d, w%d", wd, ws, wt);
+ calculateMSACSR(ws, wt, FMADDW, 2);
+ IRExpr *rm = get_IR_roundingmode_MSA();
+ IRTemp tmp[4];
+ Int i;
+
+ for (i = 0; i < 4; i++) {
+ tmp[i] = newTemp(Ity_F32);
+ assign(tmp[i],
+ qop(Iop_MSubF32, rm,
+ unop(Iop_ReinterpI32asF32,
+ binop(Iop_GetElem32x4,
+ getWReg(ws),
+ mkU8(i))),
+ unop(Iop_ReinterpI32asF32,
+ binop(Iop_GetElem32x4,
+ getWReg(wt),
+ mkU8(i))),
+ unop(Iop_ReinterpI32asF32,
+ binop(Iop_GetElem32x4,
+ getWReg(wd),
+ mkU8(i)))));
+ }
- default:
- return -1;
+ putWReg(wd,
+ binop(Iop_64HLtoV128,
+ binop(Iop_32HLto64,
+ unop(Iop_ReinterpF32asI32,
+ mkexpr(tmp[3])),
+ unop(Iop_ReinterpF32asI32,
+ mkexpr(tmp[2]))),
+ binop(Iop_32HLto64,
+ unop(Iop_ReinterpF32asI32,
+ mkexpr(tmp[1])),
+ unop(Iop_ReinterpF32asI32,
+ mkexpr(tmp[0])))));
+ break;
}
- break;
+ case 0x01: { /* FMSUB.D */
+ DIP("FMSUB.D w%d, w%d, w%d", wd, ws, wt);
+ calculateMSACSR(ws, wt, FMADDD, 2);
+ IRExpr *rm = get_IR_roundingmode_MSA();
+ IRTemp tmp[2];
+ Int i;
+
+ for (i = 0; i < 2; i++) {
+ tmp[i] = newTemp(Ity_F64);
+ assign(tmp[i],
+ qop(Iop_MSubF64, rm,
+ unop(Iop_ReinterpI64asF64,
+ binop(Iop_GetElem64x2,
+ getWReg(ws),
+ mkU8(i))),
+ unop(Iop_ReinterpI64asF64,
+ binop(Iop_GetElem64x2,
+ getWReg(wt),
+ mkU8(i))),
+ unop(Iop_ReinterpI64asF64,
+ binop(Iop_GetElem64x2,
+ getWReg(wd),
+ mkU8(i)))));
+ }
+
+ putWReg(wd,
+ binop(Iop_64HLtoV128,
+ unop(Iop_ReinterpF64asI64,
+ mkexpr(tmp[1])),
+ unop(Iop_ReinterpF64asI64,
+ mkexpr(tmp[0]))));
+ break;
+ }
+
+ default:
+ return -1;
}
- default:
- return -1;
- }
+ break;
+ }
- return 0;
-}
+ case 0x07: { /* FEXP2.df */
+ switch (df) {
+ case 0x00: { /* FEXP2.W */
+ DIP("FEXP2.W w%d, w%d, w%d", wd, ws, wt);
+ calculateMSACSR(ws, wt, FEXP2W, 2);
+ IRExpr *rm = get_IR_roundingmode_MSA();
+ putWReg(wd,
+ triop(Iop_Scale2_32Fx4, rm,
+ getWReg(ws),
+ getWReg(wt)));
+ break;
+ }
-static Int msa_3R_13(UInt cins, UChar wd, UChar ws) { /* 3R (0x13) */
- IRTemp t1, t2;
- UShort operation;
- UChar df, wt;
+ case 0x01: { /* FEXP2.D */
+ DIP("FEXP2.D w%d, w%d, w%d", wd, ws, wt);
+ calculateMSACSR(ws, wt, FEXP2D, 2);
+ IRExpr *rm = get_IR_roundingmode_MSA();
+ putWReg(wd,
+ triop(Iop_Scale2_64Fx2, rm,
+ getWReg(ws),
+ getWReg(wt)));
+ break;
+ }
- operation = (cins & 0x03800000) >> 23;
- df = (cins & 0x00600000) >> 21;
- wt = (cins & 0x001F0000) >> 16;
+ default:
+ return -1;
+ }
- switch (operation) {
- case 0x00: { /* DOTP_S.df */
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
+ break;
+ }
- switch (df) {
- case 0x01: { /* DOTP_S.H */
- DIP("DOTP_S.H w%d, w%d, w%d", wd, ws, wt);
- IRTemp tmp[8];
- Int i;
+ case 0x08: { /* FEXDO.df */
+ switch (df) {
+ case 0x00: { /* FEXDO.H */
+ DIP("FEXDO.H w%d, w%d, w%d", wd, ws, wt);
+ calculateMSACSR(ws, wt, FEXDOH, 2);
+ t1 = newTemp(Ity_I64);
+ t2 = newTemp(Ity_I64);
+ assign(t1,
+ unop(Iop_F32toF16x4_DEP,
+ getWReg(ws)));
+ assign(t2,
+ unop(Iop_F32toF16x4_DEP,
+ getWReg(wt)));
+ putWReg(wd,
+ binop(Iop_64HLtoV128,
+ mkexpr(t1), mkexpr(t2)));
+ break;
+ }
- for (i = 0; i < 8; i++) {
- tmp[i] = newTemp(Ity_I16);
- assign(tmp[i],
- binop(Iop_Add16,
- binop(Iop_MullS8,
- binop(Iop_GetElem8x16,
- mkexpr(t1),
- mkU8(2 * i)),
- binop(Iop_GetElem8x16,
- mkexpr(t2),
- mkU8(2 * i))),
- binop(Iop_MullS8,
- binop(Iop_GetElem8x16,
- mkexpr(t1),
- mkU8(2 * i + 1)),
- binop(Iop_GetElem8x16,
- mkexpr(t2),
- mkU8(2 * i + 1)))));
- }
+ case 0x01: { /* FEXDO.W */
+ DIP("FEXDO.W w%d, w%d, w%d", wd, ws, wt);
+ calculateMSACSR(ws, wt, FEXDOW, 2);
+ t1 = newTemp(Ity_I32);
+ t2 = newTemp(Ity_I32);
+ t3 = newTemp(Ity_I32);
+ t4 = newTemp(Ity_I32);
+ IRExpr *rm = get_IR_roundingmode_MSA();
+ assign(t1,
+ unop(Iop_ReinterpF32asI32,
+ binop(Iop_F64toF32, rm,
+ unop(Iop_ReinterpI64asF64,
+ unop(Iop_V128to64,
+ getWReg(ws))))));
+ assign(t2,
+ unop(Iop_ReinterpF32asI32,
+ binop(Iop_F64toF32, rm,
+ unop(Iop_ReinterpI64asF64,
+ unop(Iop_V128HIto64,
+ getWReg(ws))))));
+ assign(t3,
+ unop(Iop_ReinterpF32asI32,
+ binop(Iop_F64toF32, rm,
+ unop(Iop_ReinterpI64asF64,
+ unop(Iop_V128to64,
+ getWReg(wt))))));
+ assign(t4,
+ unop(Iop_ReinterpF32asI32,
+ binop(Iop_F64toF32, rm,
+ unop(Iop_ReinterpI64asF64,
+ unop(Iop_V128HIto64,
+ getWReg(wt))))));
+ putWReg(wd,
+ binop(Iop_64HLtoV128,
+ binop(Iop_32HLto64,
+ mkexpr(t2), mkexpr(t1)),
+ binop(Iop_32HLto64,
+ mkexpr(t4), mkexpr(t3))));
+ break;
+ }
- putWReg(wd,
- binop(Iop_64HLtoV128,
- binop(Iop_32HLto64,
- binop(Iop_16HLto32,
- mkexpr(tmp[7]),
- mkexpr(tmp[6])),
- binop(Iop_16HLto32,
- mkexpr(tmp[5]),
- mkexpr(tmp[4]))),
- binop(Iop_32HLto64,
- binop(Iop_16HLto32,
- mkexpr(tmp[3]),
- mkexpr(tmp[2])),
- binop(Iop_16HLto32,
- mkexpr(tmp[1]),
- mkexpr(tmp[0])))));
- break;
- }
+ default:
+ return -1;
+ }
- case 0x02: { /* DOTP_S.W */
- DIP("DOTP_S.W w%d, w%d, w%d", wd, ws, wt);
- IRTemp tmp[4];
- Int i;
+ break;
+ }
- for (i = 0; i < 4; i++) {
- tmp[i] = newTemp(Ity_I32);
- assign(tmp[i],
- binop(Iop_Add32,
- binop(Iop_MullS16,
- binop(Iop_GetElem16x8,
- mkexpr(t1),
- mkU8(2 * i)),
- binop(Iop_GetElem16x8,
- mkexpr(t2),
- mkU8(2 * i))),
- binop(Iop_MullS16,
- binop(Iop_GetElem16x8,
- mkexpr(t1),
- mkU8(2 * i + 1)),
- binop(Iop_GetElem16x8,
- mkexpr(t2),
- mkU8(2 * i + 1)))));
- }
+ case 0x0A: { /* FTQ.df */
+ switch (df) {
+ case 0x00: { /* FTQ.H */
+ DIP("FTQ.H w%d, w%d, w%d", wd, ws, wt);
+ calculateMSACSR(ws, wt, FTQH, 2);
+ IRExpr *rm = get_IR_roundingmode_MSA();
+ putWReg(wd,
+ triop(Iop_F32x4_2toQ16x8, rm,
+ getWReg(ws),
+ getWReg(wt)));
+ break;
+ }
- putWReg(wd,
- binop(Iop_64HLtoV128,
- binop(Iop_32HLto64,
- mkexpr(tmp[3]),
- mkexpr(tmp[2])),
- binop(Iop_32HLto64,
- mkexpr(tmp[1]),
- mkexpr(tmp[0]))));
- break;
- }
+ case 0x01: { /* FTQ.W */
+ DIP("FTQ.W w%d, w%d, w%d", wd, ws, wt);
+ calculateMSACSR(ws, wt, FTQW, 2);
+ IRExpr *rm = get_IR_roundingmode_MSA();
+ putWReg(wd,
+ triop(Iop_F64x2_2toQ32x4, rm,
+ getWReg(ws),
+ getWReg(wt)));
+ break;
+ }
- case 0x03: { /* DOTP_S.D */
- DIP("DOTP_S.D w%d, w%d, w%d", wd, ws, wt);
- IRTemp tmp[2];
- Int i;
+ default:
+ return -1;
+ }
- for (i = 0; i < 2; i++) {
- tmp[i] = newTemp(Ity_I64);
- assign(tmp[i],
- binop(Iop_Add64,
- binop(Iop_MullS32,
- binop(Iop_GetElem32x4,
- mkexpr(t1),
- mkU8(2 * i)),
- binop(Iop_GetElem32x4,
- mkexpr(t2),
- mkU8(2 * i))),
- binop(Iop_MullS32,
- binop(Iop_GetElem32x4,
- mkexpr(t1),
- mkU8(2 * i + 1)),
- binop(Iop_GetElem32x4,
- mkexpr(t2),
- mkU8(2 * i + 1)))));
- }
+ break;
+ }
- putWReg(wd,
- binop(Iop_64HLtoV128,
- mkexpr(tmp[1]), mkexpr(tmp[0])));
- break;
- }
+ case 0x0C: { /* FMIN.df */
+ switch (df) {
+ case 0x00: { /* FMIN.W */
+ DIP("FMIN.W w%d, w%d, w%d", wd, ws, wt);
+ calculateMSACSR(ws, wt, FMINW, 2);
+ putWReg(wd,
+ binop(Iop_Min32Fx4,
+ getWReg(ws),
+ getWReg(wt)));
+ break;
+ }
- default:
- return -1;
+ case 0x01: { /* FMIN.D */
+ DIP("FMIN.D w%d, w%d, w%d", wd, ws, wt);
+ calculateMSACSR(ws, wt, FMINW, 2);
+ putWReg(wd,
+ binop(Iop_Min64Fx2,
+ getWReg(ws),
+ getWReg(wt)));
+ break;
}
- break;
+ default:
+ return -1;
}
- case 0x01: { /* DOTP_U.df */
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
+ break;
+ }
- switch (df) {
- case 0x01: { /* DOTP_U.H */
- DIP("DOTP_U.H w%d, w%d, w%d", wd, ws, wt);
- IRTemp tmp[8];
- Int i;
+ case 0x0D: { /* FMIN_A.df */
+ switch (df) {
+ case 0x00: { /* FMIN_A.W */
+ DIP("FMIN_A.W w%d, w%d, w%d", wd, ws, wt);
+ calculateMSACSR(ws, wt, FMINAW, 2);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ t4 = newTemp(Ity_V128);
+ assign(t1,
+ binop(Iop_AndV128,
+ getWReg(ws),
+ binop(Iop_64HLtoV128,
+ mkU64(0x7FFFFFFF7FFFFFFF),
+ mkU64(0x7FFFFFFF7FFFFFFF))));
+ assign(t2,
+ binop(Iop_AndV128,
+ getWReg(wt),
+ binop(Iop_64HLtoV128,
+ mkU64(0x7FFFFFFF7FFFFFFF),
+ mkU64(0x7FFFFFFF7FFFFFFF))));
+ assign(t3,
+ binop(Iop_Min32Fx4,
+ mkexpr(t2), mkexpr(t1)));
+ assign(t4,
+ binop(Iop_AndV128,
+ binop(Iop_AndV128,
+ unop(Iop_NotV128,
+ binop(Iop_CmpUN32Fx4,
+ mkexpr(t3),
+ mkexpr(t3))),
+ binop(Iop_OrV128,
+ binop(Iop_AndV128,
+ binop(Iop_CmpEQ32Fx4,
+ mkexpr(t1),
+ mkexpr(t2)),
+ binop(Iop_OrV128,
+ getWReg(ws),
+ getWReg(wt))),
+ binop(Iop_OrV128,
+ binop(Iop_AndV128,
+ binop(Iop_OrV128,
+ binop(Iop_CmpUN32Fx4,
+ mkexpr(t1),
+ mkexpr(t1)),
+ binop(Iop_CmpLT32Fx4,
+ mkexpr(t3),
+ mkexpr(t1))),
+ getWReg(wt)),
+ binop(Iop_AndV128,
+ binop(Iop_OrV128,
+ binop(Iop_CmpUN32Fx4,
+ mkexpr(t2),
+ mkexpr(t2)),
+ binop(Iop_CmpLT32Fx4,
+ mkexpr(t3),
+ mkexpr(t2))),
+ getWReg(ws))))),
+ binop(Iop_64HLtoV128,
+ mkU64(0x8000000080000000),
+ mkU64(0x8000000080000000))));
+ putWReg(wd,
+ binop(Iop_OrV128,
+ mkexpr(t3), mkexpr(t4)));
+ break;
+ }
- for (i = 0; i < 8; i++) {
- tmp[i] = newTemp(Ity_I16);
- assign(tmp[i],
- binop(Iop_Add16,
- binop(Iop_MullU8,
- binop(Iop_GetElem8x16,
- mkexpr(t1),
- mkU8(2 * i)),
- binop(Iop_GetElem8x16,
- mkexpr(t2),
- mkU8(2 * i))),
- binop(Iop_MullU8,
- binop(Iop_GetElem8x16,
- mkexpr(t1),
- mkU8(2 * i + 1)),
- binop(Iop_GetElem8x16,
- mkexpr(t2),
- mkU8(2 * i + 1)))));
- }
+ case 0x01: { /* FMIN_A.D */
+ DIP("FMIN_A.D w%d, w%d, w%d", wd, ws, wt);
+ calculateMSACSR(ws, wt, FMINAD, 2);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ t4 = newTemp(Ity_V128);
+ assign(t1,
+ binop(Iop_AndV128,
+ getWReg(ws),
+ binop(Iop_64HLtoV128,
+ mkU64(0x7FFFFFFFFFFFFFFF),
+ mkU64(0x7FFFFFFFFFFFFFFF))));
+ assign(t2,
+ binop(Iop_AndV128,
+ getWReg(wt),
+ binop(Iop_64HLtoV128,
+ mkU64(0x7FFFFFFFFFFFFFFF),
+ mkU64(0x7FFFFFFFFFFFFFFF))));
+ assign(t3,
+ binop(Iop_Min64Fx2,
+ mkexpr(t2), mkexpr(t1)));
+ assign(t4,
+ binop(Iop_AndV128,
+ binop(Iop_AndV128,
+ unop(Iop_NotV128,
+ binop(Iop_CmpUN64Fx2,
+ mkexpr(t3),
+ mkexpr(t3))),
+ binop(Iop_OrV128,
+ binop(Iop_AndV128,
+ binop(Iop_CmpEQ64Fx2,
+ mkexpr(t1),
+ mkexpr(t2)),
+ binop(Iop_OrV128,
+ getWReg(ws),
+ getWReg(wt))),
+ binop(Iop_OrV128,
+ binop(Iop_AndV128,
+ binop(Iop_OrV128,
+ binop(Iop_CmpUN64Fx2,
+ mkexpr(t1),
+ mkexpr(t1)),
+ binop(Iop_CmpLT64Fx2,
+ mkexpr(t3),
+ mkexpr(t1))),
+ getWReg(wt)),
+ binop(Iop_AndV128,
+ binop(Iop_OrV128,
+ binop(Iop_CmpUN64Fx2,
+ mkexpr(t2),
+ mkexpr(t2)),
+ binop(Iop_CmpLT64Fx2,
+ mkexpr(t3),
+ mkexpr(t2))),
+ getWReg(ws))))),
+ binop(Iop_64HLtoV128,
+ mkU64(0x8000000000000000),
+ mkU64(0x8000000000000000))));
+ putWReg(wd,
+ binop(Iop_OrV128,
+ mkexpr(t3), mkexpr(t4)));
+ break;
+ }
- putWReg(wd,
- binop(Iop_64HLtoV128,
- binop(Iop_32HLto64,
- binop(Iop_16HLto32,
- mkexpr(tmp[7]),
- mkexpr(tmp[6])),
- binop(Iop_16HLto32,
- mkexpr(tmp[5]),
- mkexpr(tmp[4]))),
- binop(Iop_32HLto64,
- binop(Iop_16HLto32,
- mkexpr(tmp[3]),
- mkexpr(tmp[2])),
- binop(Iop_16HLto32,
- mkexpr(tmp[1]),
- mkexpr(tmp[0])))));
- break;
- }
+ default:
+ return -1;
+ }
- case 0x02: { /* DOTP_U.W */
- DIP("DOTP_U.W w%d, w%d, w%d", wd, ws, wt);
- IRTemp tmp[4];
- Int i;
+ break;
+ }
- for (i = 0; i < 4; i++) {
- tmp[i] = newTemp(Ity_I32);
- assign(tmp[i],
- binop(Iop_Add32,
- binop(Iop_MullU16,
- binop(Iop_GetElem16x8,
- mkexpr(t1),
- mkU8(2 * i)),
- binop(Iop_GetElem16x8,
- mkexpr(t2),
- mkU8(2 * i))),
- binop(Iop_MullU16,
- binop(Iop_GetElem16x8,
- mkexpr(t1),
- mkU8(2 * i + 1)),
- binop(Iop_GetElem16x8,
- mkexpr(t2),
- mkU8(2 * i + 1)))));
- }
+ case 0x0E: { /* FMAX.df */
+ switch (df) {
+ case 0x00: { /* FMAX.W */
+ DIP("FMAX.W w%d, w%d, w%d", wd, ws, wt);
+ calculateMSACSR(ws, wt, FMAXW, 2);
+ putWReg(wd,
+ binop(Iop_Max32Fx4,
+ getWReg(ws),
+ getWReg(wt)));
+ break;
+ }
- putWReg(wd,
- binop(Iop_64HLtoV128,
- binop(Iop_32HLto64,
- mkexpr(tmp[3]),
- mkexpr(tmp[2])),
- binop(Iop_32HLto64,
- mkexpr(tmp[1]),
- mkexpr(tmp[0]))));
- break;
- }
+ case 0x01: { /* FMAX.D */
+ DIP("FMAX.D w%d, w%d, w%d", wd, ws, wt);
+ calculateMSACSR(ws, wt, FMAXW, 2);
+ putWReg(wd,
+ binop(Iop_Max64Fx2,
+ getWReg(ws),
+ getWReg(wt)));
+ break;
+ }
- case 0x03: { /* DOTP_U.D */
- DIP("DOTP_U.D w%d, w%d, w%d", wd, ws, wt);
- IRTemp tmp[2];
- Int i;
+ default:
+ return -1;
+ }
- for (i = 0; i < 2; i++) {
- tmp[i] = newTemp(Ity_I64);
- assign(tmp[i],
- binop(Iop_Add64,
- binop(Iop_MullU32,
- binop(Iop_GetElem32x4,
- mkexpr(t1),
- mkU8(2 * i)),
- binop(Iop_GetElem32x4,
- mkexpr(t2),
- mkU8(2 * i))),
- binop(Iop_MullU32,
- binop(Iop_GetElem32x4,
- mkexpr(t1),
- mkU8(2 * i + 1)),
- binop(Iop_GetElem32x4,
- mkexpr(t2),
- mkU8(2 * i + 1)))));
- }
+ break;
+ }
- putWReg(wd,
- binop(Iop_64HLtoV128,
- mkexpr(tmp[1]), mkexpr(tmp[0])));
- break;
- }
+ case 0x0F: { /* FMAX_A.df */
+ switch (df) {
+ case 0x00: { /* FMAX_A.W */
+ DIP("FMAX_A.W w%d, w%d, w%d", wd, ws, wt);
+ calculateMSACSR(ws, wt, FMAXAW, 2);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ t4 = newTemp(Ity_V128);
+ assign(t1,
+ binop(Iop_AndV128,
+ getWReg(ws),
+ binop(Iop_64HLtoV128,
+ mkU64(0x7FFFFFFF7FFFFFFF),
+ mkU64(0x7FFFFFFF7FFFFFFF))));
+ assign(t2,
+ binop(Iop_AndV128,
+ getWReg(wt),
+ binop(Iop_64HLtoV128,
+ mkU64(0x7FFFFFFF7FFFFFFF),
+ mkU64(0x7FFFFFFF7FFFFFFF))));
+ assign(t3,
+ binop(Iop_Max32Fx4,
+ mkexpr(t2), mkexpr(t1)));
+ assign(t4,
+ binop(Iop_AndV128,
+ binop(Iop_AndV128,
+ unop(Iop_NotV128,
+ binop(Iop_CmpUN32Fx4,
+ mkexpr(t3),
+ mkexpr(t3))),
+ binop(Iop_OrV128,
+ binop(Iop_AndV128,
+ binop(Iop_CmpEQ32Fx4,
+ mkexpr(t1),
+ mkexpr(t2)),
+ binop(Iop_AndV128,
+ getWReg(ws),
+ getWReg(wt))),
+ binop(Iop_OrV128,
+ binop(Iop_AndV128,
+ binop(Iop_OrV128,
+ binop(Iop_CmpUN32Fx4,
+ mkexpr(t1),
+ mkexpr(t1)),
+ binop(Iop_CmpLT32Fx4,
+ mkexpr(t1),
+ mkexpr(t3))),
+ getWReg(wt)),
+ binop(Iop_AndV128,
+ binop(Iop_OrV128,
+ binop(Iop_CmpUN32Fx4,
+ mkexpr(t2),
+ mkexpr(t2)),
+ binop(Iop_CmpLT32Fx4,
+ mkexpr(t2),
+ mkexpr(t3))),
+ getWReg(ws))))),
+ binop(Iop_64HLtoV128,
+ mkU64(0x8000000080000000),
+ mkU64(0x8000000080000000))));
+ putWReg(wd,
+ binop(Iop_OrV128,
+ mkexpr(t3), mkexpr(t4)));
+ break;
+ }
- default:
- return -1;
+ case 0x01: { /* FMAX_A.D */
+ DIP("FMAX_A.D w%d, w%d, w%d", wd, ws, wt);
+ calculateMSACSR(ws, wt, FMAXAD, 2);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ t4 = newTemp(Ity_V128);
+ assign(t1,
+ binop(Iop_AndV128,
+ getWReg(ws),
+ binop(Iop_64HLtoV128,
+ mkU64(0x7FFFFFFFFFFFFFFF),
+ mkU64(0x7FFFFFFFFFFFFFFF))));
+ assign(t2,
+ binop(Iop_AndV128,
+ getWReg(wt),
+ binop(Iop_64HLtoV128,
+ mkU64(0x7FFFFFFFFFFFFFFF),
+ mkU64(0x7FFFFFFFFFFFFFFF))));
+ assign(t3,
+ binop(Iop_Max64Fx2,
+ mkexpr(t2), mkexpr(t1)));
+ assign(t4,
+ binop(Iop_AndV128,
+ binop(Iop_AndV128,
+ unop(Iop_NotV128,
+ binop(Iop_CmpUN64Fx2,
+ mkexpr(t3),
+ mkexpr(t3))),
+ binop(Iop_OrV128,
+ binop(Iop_AndV128,
+ binop(Iop_CmpEQ64Fx2,
+ mkexpr(t1),
+ mkexpr(t2)),
+ binop(Iop_AndV128,
+ getWReg(ws),
+ getWReg(wt))),
+ binop(Iop_OrV128,
+ binop(Iop_AndV128,
+ binop(Iop_OrV128,
+ binop(Iop_CmpUN64Fx2,
+ mkexpr(t1),
+ mkexpr(t1)),
+ binop(Iop_CmpLT64Fx2,
+ mkexpr(t1),
+ mkexpr(t3))),
+ getWReg(wt)),
+ binop(Iop_AndV128,
+ binop(Iop_OrV128,
+ binop(Iop_CmpUN64Fx2,
+ mkexpr(t2),
+ mkexpr(t2)),
+ binop(Iop_CmpLT64Fx2,
+ mkexpr(t2),
+ mkexpr(t3))),
+ getWReg(ws))))),
+ binop(Iop_64HLtoV128,
+ mkU64(0x8000000000000000),
+ mkU64(0x8000000000000000))));
+ putWReg(wd,
+ binop(Iop_OrV128,
+ mkexpr(t3), mkexpr(t4)));
+ break;
}
- break;
+ default:
+ return -1;
}
- case 0x02: { /* DPADD_S.df */
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
+ break;
+ }
- switch (df) {
- case 0x01: { /* DPADD_S.H */
- DIP("DPADD_S.H w%d, w%d, w%d", wd, ws, wt);
- IRTemp tmp[8];
- Int i;
+ default:
+ return -1;
+ }
- for (i = 0; i < 8; i++) {
- tmp[i] = newTemp(Ity_I16);
- assign(tmp[i],
- binop(Iop_Add16,
- binop(Iop_MullS8,
- binop(Iop_GetElem8x16,
- mkexpr(t1),
- mkU8(2 * i)),
- binop(Iop_GetElem8x16,
- mkexpr(t2),
- mkU8(2 * i))),
- binop(Iop_MullS8,
- binop(Iop_GetElem8x16,
- mkexpr(t1),
- mkU8(2 * i + 1)),
- binop(Iop_GetElem8x16,
- mkexpr(t2),
- mkU8(2 * i + 1)))));
- }
+ return 0;
+}
- putWReg(wd,
- binop(Iop_Add16x8,
- getWReg(wd),
- binop(Iop_64HLtoV128,
- binop(Iop_32HLto64,
- binop(Iop_16HLto32,
- mkexpr(tmp[7]),
- mkexpr(tmp[6])),
- binop(Iop_16HLto32,
- mkexpr(tmp[5]),
- mkexpr(tmp[4]))),
- binop(Iop_32HLto64,
- binop(Iop_16HLto32,
- mkexpr(tmp[3]),
- mkexpr(tmp[2])),
- binop(Iop_16HLto32,
- mkexpr(tmp[1]),
- mkexpr(tmp[0]))))));
- break;
- }
+static Int msa_3R_1C(UInt cins, UChar wd, UChar ws) /* 3R (0x1C) */
+{
+ IRTemp t1, t2, t3, t4, t5, t6;
+ UShort operation;
+ UChar df, wt;
- case 0x02: { /* DPADD_S.W */
- DIP("DPADD_S.W w%d, w%d, w%d", wd, ws, wt);
- IRTemp tmp[4];
- Int i;
+ operation = (cins & 0x03C00000) >> 22;
+ df = (cins & 0x00200000) >> 21;
+ wt = (cins & 0x001F0000) >> 16;
- for (i = 0; i < 4; i++) {
- tmp[i] = newTemp(Ity_I32);
- assign(tmp[i],
- binop(Iop_Add32,
- binop(Iop_MullS16,
- binop(Iop_GetElem16x8,
- mkexpr(t1),
- mkU8(2 * i)),
- binop(Iop_GetElem16x8,
- mkexpr(t2),
- mkU8(2 * i))),
- binop(Iop_MullS16,
- binop(Iop_GetElem16x8,
- mkexpr(t1),
- mkU8(2 * i + 1)),
- binop(Iop_GetElem16x8,
- mkexpr(t2),
- mkU8(2 * i + 1)))));
- }
+ switch (operation) {
+ case 0x01: { /* FCOR.df */
+ switch (df) {
+ case 0x00: { /* FCOR.W */
+ DIP("FCOR.W w%d, w%d, w%d", wd, ws, wt);
+ calculateMSACSR(ws, wt, FCORW, 2);
+ putWReg(wd,
+ unop(Iop_NotV128,
+ binop(Iop_CmpUN32Fx4,
+ getWReg(ws),
+ getWReg(wt))));
+ break;
+ }
- putWReg(wd,
- binop(Iop_Add32x4,
- getWReg(wd),
- binop(Iop_64HLtoV128,
- binop(Iop_32HLto64,
- mkexpr(tmp[3]),
- mkexpr(tmp[2])),
- binop(Iop_32HLto64,
- mkexpr(tmp[1]),
- mkexpr(tmp[0])))));
- break;
- }
+ case 0x01: { /* FCOR.D */
+ DIP("FCOR.D w%d, w%d, w%d", wd, ws, wt);
+ calculateMSACSR(ws, wt, FCORD, 2);
+ putWReg(wd,
+ unop(Iop_NotV128,
+ binop(Iop_CmpUN64Fx2,
+ getWReg(ws),
+ getWReg(wt))));
+ break;
+ }
- case 0x03: { /* DPADD_S.D */
- DIP("DPADD_S.D w%d, w%d, w%d", wd, ws, wt);
- IRTemp tmp[2];
- Int i;
+ default:
+ return -1;
+ }
- for (i = 0; i < 2; i++) {
- tmp[i] = newTemp(Ity_I64);
- assign(tmp[i],
- binop(Iop_Add64,
- binop(Iop_MullS32,
- binop(Iop_GetElem32x4,
- mkexpr(t1),
- mkU8(2 * i)),
- binop(Iop_GetElem32x4,
- mkexpr(t2),
- mkU8(2 * i))),
- binop(Iop_MullS32,
- binop(Iop_GetElem32x4,
- mkexpr(t1),
- mkU8(2 * i + 1)),
- binop(Iop_GetElem32x4,
- mkexpr(t2),
- mkU8(2 * i + 1)))));
- }
+ break;
+ }
- putWReg(wd,
- binop(Iop_Add64x2,
- getWReg(wd),
- binop(Iop_64HLtoV128,
- mkexpr(tmp[1]),
- mkexpr(tmp[0]))));
- break;
- }
+ case 0x02: { /* FCUNE.df */
+ switch (df) {
+ case 0x00: { /* FCUNE.W */
+ DIP("FCUNE.W w%d, w%d, w%d", wd, ws, wt);
+ calculateMSACSR(ws, wt, FCUNEW, 2);
+ putWReg(wd,
+ unop(Iop_NotV128,
+ binop(Iop_CmpEQ32Fx4,
+ getWReg(ws),
+ getWReg(wt))));
+ break;
+ }
- default:
- return -1;
+ case 0x01: { /* FCUNE.D */
+ DIP("FCUNE.D w%d, w%d, w%d", wd, ws, wt);
+ calculateMSACSR(ws, wt, FCUNED, 2);
+ putWReg(wd,
+ unop(Iop_NotV128,
+ binop(Iop_CmpEQ64Fx2,
+ getWReg(ws),
+ getWReg(wt))));
+ break;
}
- break;
+ default:
+ return -1;
}
- case 0x03: { /* DPADD_U.df */
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
+ break;
+ }
- switch (df) {
- case 0x01: { /* DPADD_U.H */
- DIP("DPADD_U.H w%d, w%d, w%d", wd, ws, wt);
- IRTemp tmp[8];
- Int i;
+ case 0x03: { /* FCNE.df */
+ switch (df) {
+ case 0x00: { /* FCNE.W */
+ DIP("FCNE.W w%d, w%d, w%d", wd, ws, wt);
+ calculateMSACSR(ws, wt, FCNEW, 2);
+ putWReg(wd,
+ binop(Iop_XorV128,
+ unop(Iop_NotV128,
+ binop(Iop_CmpEQ32Fx4,
+ getWReg(ws),
+ getWReg(wt))),
+ binop(Iop_CmpUN32Fx4,
+ getWReg(ws),
+ getWReg(wt))));
+ break;
+ }
- for (i = 0; i < 8; i++) {
- tmp[i] = newTemp(Ity_I16);
- assign(tmp[i],
- binop(Iop_Add16,
- binop(Iop_MullU8,
- binop(Iop_GetElem8x16,
- mkexpr(t1),
- mkU8(2 * i)),
- binop(Iop_GetElem8x16,
- mkexpr(t2),
- mkU8(2 * i))),
- binop(Iop_MullU8,
- binop(Iop_GetElem8x16,
- mkexpr(t1),
- mkU8(2 * i + 1)),
- binop(Iop_GetElem8x16,
- mkexpr(t2),
- mkU8(2 * i + 1)))));
- }
+ case 0x01: { /* FCNE.D */
+ DIP("FCNE.D w%d, w%d, w%d", wd, ws, wt);
+ calculateMSACSR(ws, wt, FCNED, 2);
+ putWReg(wd,
+ binop(Iop_XorV128,
+ unop(Iop_NotV128,
+ binop(Iop_CmpEQ64Fx2,
+ getWReg(ws),
+ getWReg(wt))),
+ binop(Iop_CmpUN64Fx2,
+ getWReg(ws),
+ getWReg(wt))));
+ break;
+ }
+
+ default:
+ return -1;
+ }
+
+ break;
+ }
+
+ case 0x04: { /* MUL_Q.df */
+ switch (df) {
+ case 0x00: { /* MUL_Q.H */
+ DIP("MUL_Q.H w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3,
+ binop(Iop_QDMulHi16Sx8,
+ mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- putWReg(wd,
- binop(Iop_Add16x8,
- getWReg(wd),
- binop(Iop_64HLtoV128,
- binop(Iop_32HLto64,
- binop(Iop_16HLto32,
- mkexpr(tmp[7]),
- mkexpr(tmp[6])),
- binop(Iop_16HLto32,
- mkexpr(tmp[5]),
- mkexpr(tmp[4]))),
- binop(Iop_32HLto64,
- binop(Iop_16HLto32,
- mkexpr(tmp[3]),
- mkexpr(tmp[2])),
- binop(Iop_16HLto32,
- mkexpr(tmp[1]),
- mkexpr(tmp[0]))))));
- break;
- }
+ case 0x01: { /* MUL_Q.W */
+ DIP("MUL_Q.W w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3,
+ binop(Iop_QDMulHi32Sx4,
+ mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- case 0x02: { /* DPADD_U.W */
- DIP("DPADD_U.W w%d, w%d, w%d", wd, ws, wt);
- IRTemp tmp[4];
- Int i;
+ default:
+ return -1;
+ }
- for (i = 0; i < 4; i++) {
- tmp[i] = newTemp(Ity_I32);
- assign(tmp[i],
- binop(Iop_Add32,
- binop(Iop_MullU16,
- binop(Iop_GetElem16x8,
- mkexpr(t1),
- mkU8(2 * i)),
- binop(Iop_GetElem16x8,
- mkexpr(t2),
- mkU8(2 * i))),
- binop(Iop_MullU16,
- binop(Iop_GetElem16x8,
- mkexpr(t1),
- mkU8(2 * i + 1)),
- binop(Iop_GetElem16x8,
- mkexpr(t2),
- mkU8(2 * i + 1)))));
- }
+ break;
+ }
- putWReg(wd,
- binop(Iop_Add32x4,
- getWReg(wd),
- binop(Iop_64HLtoV128,
- binop(Iop_32HLto64,
- mkexpr(tmp[3]),
- mkexpr(tmp[2])),
- binop(Iop_32HLto64,
- mkexpr(tmp[1]),
- mkexpr(tmp[0])))));
- break;
- }
+ case 0x05: { /* MADD_Q.df */
+ switch (df) {
+ case 0x00: { /* MADD_Q.W */
+ DIP("MADD_Q.W w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ t4 = newTemp(Ity_V128);
+ t5 = newTemp(Ity_V128);
+ t6 = newTemp(Ity_V128);
+ assign(t1, // even
+ binop(Iop_SarN32x4,
+ binop(Iop_InterleaveEvenLanes16x8,
+ getWReg(ws),
+ getWReg(ws)),
+ mkU8(16)));
+ assign(t2, // odd
+ binop(Iop_SarN32x4,
+ getWReg(ws), mkU8(16)));
+ assign(t3, // even
+ binop(Iop_SarN32x4,
+ binop(Iop_InterleaveEvenLanes16x8,
+ getWReg(wt),
+ getWReg(wt)),
+ mkU8(16)));
+ assign(t4, // odd
+ binop(Iop_SarN32x4,
+ getWReg(wt), mkU8(16)));
+ assign(t5,
+ binop(Iop_Add32x4,
+ binop(Iop_ShlN32x4,
+ binop(Iop_SarN32x4,
+ binop(Iop_InterleaveEvenLanes16x8,
+ getWReg(wd),
+ getWReg(wd)),
+ mkU8(16)),
+ mkU8(15)),
+ binop(Iop_Mul32x4,
+ mkexpr(t1), mkexpr(t3))));
+ assign(t6,
+ binop(Iop_Add32x4,
+ binop(Iop_ShlN32x4,
+ binop(Iop_SarN32x4,
+ getWReg(wd),
+ mkU8(16)),
+ mkU8(15)),
+ binop(Iop_Mul32x4,
+ mkexpr(t2), mkexpr(t4))));
+ putWReg(wd,
+ binop(Iop_InterleaveEvenLanes16x8,
+ binop(Iop_QandQSarNnarrow32Sto16Sx4,
+ mkexpr(t6), mkU8(15)),
+ binop(Iop_QandQSarNnarrow32Sto16Sx4,
+ mkexpr(t5), mkU8(15))));
+ break;
+ }
- case 0x03: { /* DPADD_U.D */
- DIP("DPADD_U.D w%d, w%d, w%d", wd, ws, wt);
- IRTemp tmp[2];
- Int i;
+ case 0x01: { /* MADD_Q.W */
+ DIP("MADD_Q.W w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ t4 = newTemp(Ity_V128);
+ t5 = newTemp(Ity_V128);
+ t6 = newTemp(Ity_V128);
+ assign(t1, // even
+ binop(Iop_SarN64x2,
+ binop(Iop_InterleaveEvenLanes32x4,
+ getWReg(ws),
+ getWReg(ws)),
+ mkU8(32)));
+ assign(t2, // odd
+ binop(Iop_SarN64x2,
+ getWReg(ws), mkU8(32)));
+ assign(t3, // even
+ binop(Iop_SarN64x2,
+ binop(Iop_InterleaveEvenLanes32x4,
+ getWReg(wt),
+ getWReg(wt)),
+ mkU8(32)));
+ assign(t4, // odd
+ binop(Iop_SarN64x2,
+ getWReg(wt), mkU8(32)));
+ assign(t5,
+ binop(Iop_Add64x2,
+ binop(Iop_ShlN64x2,
+ binop(Iop_SarN64x2,
+ binop(Iop_InterleaveEvenLanes32x4,
+ getWReg(wd),
+ getWReg(wd)),
+ mkU8(32)),
+ mkU8(31)),
+ binop(Iop_64HLtoV128,
+ binop(Iop_Mul64,
+ unop(Iop_V128HIto64,
+ mkexpr(t1)),
+ unop(Iop_V128HIto64,
+ mkexpr(t3))),
+ binop(Iop_Mul64,
+ unop(Iop_V128to64,
+ mkexpr(t1)),
+ unop(Iop_V128to64,
+ mkexpr(t3))))));
+ assign(t6,
+ binop(Iop_Add64x2,
+ binop(Iop_ShlN64x2,
+ binop(Iop_SarN64x2,
+ getWReg(wd),
+ mkU8(32)),
+ mkU8(31)),
+ binop(Iop_64HLtoV128,
+ binop(Iop_Mul64,
+ unop(Iop_V128HIto64,
+ mkexpr(t2)),
+ unop(Iop_V128HIto64,
+ mkexpr(t4))),
+ binop(Iop_Mul64,
+ unop(Iop_V128to64,
+ mkexpr(t2)),
+ unop(Iop_V128to64,
+ mkexpr(t4))))));
+ putWReg(wd,
+ binop(Iop_InterleaveEvenLanes32x4,
+ binop(Iop_QandQSarNnarrow64Sto32Sx2,
+ mkexpr(t6), mkU8(31)),
+ binop(Iop_QandQSarNnarrow64Sto32Sx2,
+ mkexpr(t5), mkU8(31))));
+ break;
+ }
- for (i = 0; i < 2; i++) {
- tmp[i] = newTemp(Ity_I64);
- assign(tmp[i],
- binop(Iop_Add64,
- binop(Iop_MullU32,
- binop(Iop_GetElem32x4,
- mkexpr(t1),
- mkU8(2 * i)),
- binop(Iop_GetElem32x4,
- mkexpr(t2),
- mkU8(2 * i))),
- binop(Iop_MullU32,
- binop(Iop_GetElem32x4,
- mkexpr(t1),
- mkU8(2 * i + 1)),
- binop(Iop_GetElem32x4,
- mkexpr(t2),
- mkU8(2 * i + 1)))));
- }
+ default:
+ return -1;
+ }
- putWReg(wd,
- binop(Iop_Add64x2,
- getWReg(wd),
- binop(Iop_64HLtoV128,
- mkexpr(tmp[1]),
- mkexpr(tmp[0]))));
- break;
- }
+ break;
+ }
- default:
- return -1;
+ case 0x06: { /* MSUB_Q.df */
+ switch (df) {
+ case 0x00: { /* MSUB_Q.H */
+ DIP("MSUB_Q.H w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ t4 = newTemp(Ity_V128);
+ t5 = newTemp(Ity_V128);
+ t6 = newTemp(Ity_V128);
+ assign(t1, // even
+ binop(Iop_SarN32x4,
+ binop(Iop_InterleaveEvenLanes16x8,
+ getWReg(ws),
+ getWReg(ws)),
+ mkU8(16)));
+ assign(t2, // odd
+ binop(Iop_SarN32x4,
+ getWReg(ws), mkU8(16)));
+ assign(t3, // even
+ binop(Iop_SarN32x4,
+ binop(Iop_InterleaveEvenLanes16x8,
+ getWReg(wt),
+ getWReg(wt)),
+ mkU8(16)));
+ assign(t4, // odd
+ binop(Iop_SarN32x4,
+ getWReg(wt), mkU8(16)));
+ assign(t5,
+ binop(Iop_Sub32x4,
+ binop(Iop_ShlN32x4,
+ binop(Iop_SarN32x4,
+ binop(Iop_InterleaveEvenLanes16x8,
+ getWReg(wd),
+ getWReg(wd)),
+ mkU8(16)),
+ mkU8(15)),
+ binop(Iop_Mul32x4,
+ mkexpr(t1), mkexpr(t3))));
+ assign(t6,
+ binop(Iop_Sub32x4,
+ binop(Iop_ShlN32x4,
+ binop(Iop_SarN32x4,
+ getWReg(wd),
+ mkU8(16)),
+ mkU8(15)),
+ binop(Iop_Mul32x4,
+ mkexpr(t2), mkexpr(t4))));
+ putWReg(wd,
+ binop(Iop_InterleaveEvenLanes16x8,
+ binop(Iop_QandQSarNnarrow32Sto16Sx4,
+ mkexpr(t6), mkU8(15)),
+ binop(Iop_QandQSarNnarrow32Sto16Sx4,
+ mkexpr(t5), mkU8(15))));
+ break;
}
- break;
+ case 0x01: { /* MSUB_Q.W */
+ DIP("MSUB_Q.W w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ t4 = newTemp(Ity_V128);
+ t5 = newTemp(Ity_V128);
+ t6 = newTemp(Ity_V128);
+ assign(t1, // even
+ binop(Iop_SarN64x2,
+ binop(Iop_InterleaveEvenLanes32x4,
+ getWReg(ws),
+ getWReg(ws)),
+ mkU8(32)));
+ assign(t2, // odd
+ binop(Iop_SarN64x2,
+ getWReg(ws), mkU8(32)));
+ assign(t3, // even
+ binop(Iop_SarN64x2,
+ binop(Iop_InterleaveEvenLanes32x4,
+ getWReg(wt),
+ getWReg(wt)),
+ mkU8(32)));
+ assign(t4, // odd
+ binop(Iop_SarN64x2,
+ getWReg(wt), mkU8(32)));
+ assign(t5,
+ binop(Iop_Sub64x2,
+ binop(Iop_ShlN64x2,
+ binop(Iop_SarN64x2,
+ binop(Iop_InterleaveEvenLanes32x4,
+ getWReg(wd),
+ getWReg(wd)),
+ mkU8(32)),
+ mkU8(31)),
+ binop(Iop_64HLtoV128,
+ binop(Iop_Mul64,
+ unop(Iop_V128HIto64,
+ mkexpr(t1)),
+ unop(Iop_V128HIto64,
+ mkexpr(t3))),
+ binop(Iop_Mul64,
+ unop(Iop_V128to64,
+ mkexpr(t1)),
+ unop(Iop_V128to64,
+ mkexpr(t3))))));
+ assign(t6,
+ binop(Iop_Sub64x2,
+ binop(Iop_ShlN64x2,
+ binop(Iop_SarN64x2,
+ getWReg(wd),
+ mkU8(32)),
+ mkU8(31)),
+ binop(Iop_64HLtoV128,
+ binop(Iop_Mul64,
+ unop(Iop_V128HIto64,
+ mkexpr(t2)),
+ unop(Iop_V128HIto64,
+ mkexpr(t4))),
+ binop(Iop_Mul64,
+ unop(Iop_V128to64,
+ mkexpr(t2)),
+ unop(Iop_V128to64,
+ mkexpr(t4))))));
+ putWReg(wd,
+ binop(Iop_InterleaveEvenLanes32x4,
+ binop(Iop_QandQSarNnarrow64Sto32Sx2,
+ mkexpr(t6), mkU8(31)),
+ binop(Iop_QandQSarNnarrow64Sto32Sx2,
+ mkexpr(t5), mkU8(31))));
+ break;
+ }
+
+ default:
+ return -1;
}
- case 0x04: { /* DPSUB_S.df */
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
+ break;
+ }
- switch (df) {
- case 0x01: { /* DPSUB_S.H */
- DIP("DPSUB_S.H w%d, w%d, w%d", wd, ws, wt);
- IRTemp tmp[8];
- Int i;
+ case 0x09: { /* FSOR.df */
+ switch (df) {
+ case 0x00: { /* FSOR.W */
+ DIP("FSOR.W w%d, w%d, w%d", wd, ws, wt);
+ calculateMSACSR(ws, wt, FSORW, 2);
+ putWReg(wd,
+ unop(Iop_NotV128,
+ binop(Iop_CmpUN32Fx4,
+ getWReg(ws),
+ getWReg(wt))));
+ break;
+ }
- for (i = 0; i < 8; i++) {
- tmp[i] = newTemp(Ity_I16);
- assign(tmp[i],
- binop(Iop_Add16,
- binop(Iop_MullS8,
- binop(Iop_GetElem8x16,
- mkexpr(t1),
- mkU8(2 * i)),
- binop(Iop_GetElem8x16,
- mkexpr(t2),
- mkU8(2 * i))),
- binop(Iop_MullS8,
- binop(Iop_GetElem8x16,
- mkexpr(t1),
- mkU8(2 * i + 1)),
- binop(Iop_GetElem8x16,
- mkexpr(t2),
- mkU8(2 * i + 1)))));
- }
+ case 0x01: { /* FSOR.D */
+ DIP("FSOR.D w%d, w%d, w%d", wd, ws, wt);
+ calculateMSACSR(ws, wt, FSORD, 2);
+ putWReg(wd,
+ unop(Iop_NotV128,
+ binop(Iop_CmpUN64Fx2,
+ getWReg(ws),
+ getWReg(wt))));
+ break;
+ }
- putWReg(wd,
- binop(Iop_Sub16x8,
- getWReg(wd),
- binop(Iop_64HLtoV128,
- binop(Iop_32HLto64,
- binop(Iop_16HLto32,
- mkexpr(tmp[7]),
- mkexpr(tmp[6])),
- binop(Iop_16HLto32,
- mkexpr(tmp[5]),
- mkexpr(tmp[4]))),
- binop(Iop_32HLto64,
- binop(Iop_16HLto32,
- mkexpr(tmp[3]),
- mkexpr(tmp[2])),
- binop(Iop_16HLto32,
- mkexpr(tmp[1]),
- mkexpr(tmp[0]))))));
- break;
- }
+ default:
+ return -1;
+ }
- case 0x02: { /* DPSUB_S.W */
- DIP("DPSUB_S.W w%d, w%d, w%d", wd, ws, wt);
- IRTemp tmp[4];
- Int i;
+ break;
+ }
- for (i = 0; i < 4; i++) {
- tmp[i] = newTemp(Ity_I32);
- assign(tmp[i],
- binop(Iop_Add32,
- binop(Iop_MullS16,
- binop(Iop_GetElem16x8,
- mkexpr(t1),
- mkU8(2 * i)),
- binop(Iop_GetElem16x8,
- mkexpr(t2),
- mkU8(2 * i))),
- binop(Iop_MullS16,
- binop(Iop_GetElem16x8,
- mkexpr(t1),
- mkU8(2 * i + 1)),
- binop(Iop_GetElem16x8,
- mkexpr(t2),
- mkU8(2 * i + 1)))));
- }
+ case 0x0A: { /* FSUNE.df */
+ switch (df) {
+ case 0x00: { /* FSUNE.W */
+ DIP("FSUNE.W w%d, w%d, w%d", wd, ws, wt);
+ calculateMSACSR(ws, wt, FSUNEW, 2);
+ putWReg(wd,
+ unop(Iop_NotV128,
+ binop(Iop_CmpEQ32Fx4,
+ getWReg(ws),
+ getWReg(wt))));
+ break;
+ }
- putWReg(wd,
- binop(Iop_Sub32x4,
- getWReg(wd),
- binop(Iop_64HLtoV128,
- binop(Iop_32HLto64,
- mkexpr(tmp[3]),
- mkexpr(tmp[2])),
- binop(Iop_32HLto64,
- mkexpr(tmp[1]),
- mkexpr(tmp[0])))));
- break;
- }
+ case 0x01: { /* FSUNE.D */
+ DIP("FSUNE.D w%d, w%d, w%d", wd, ws, wt);
+ calculateMSACSR(ws, wt, FSUNED, 2);
+ putWReg(wd,
+ unop(Iop_NotV128,
+ binop(Iop_CmpEQ64Fx2,
+ getWReg(ws),
+ getWReg(wt))));
+ break;
+ }
- case 0x03: { /* DPSUB_S.D */
- DIP("DPSUB_S.D w%d, w%d, w%d", wd, ws, wt);
- IRTemp tmp[2];
- Int i;
+ default:
+ return -1;
+ }
- for (i = 0; i < 2; i++) {
- tmp[i] = newTemp(Ity_I64);
- assign(tmp[i],
- binop(Iop_Add64,
- binop(Iop_MullS32,
- binop(Iop_GetElem32x4,
- mkexpr(t1),
- mkU8(2 * i)),
- binop(Iop_GetElem32x4,
- mkexpr(t2),
- mkU8(2 * i))),
- binop(Iop_MullS32,
- binop(Iop_GetElem32x4,
- mkexpr(t1),
- mkU8(2 * i + 1)),
- binop(Iop_GetElem32x4,
- mkexpr(t2),
- mkU8(2 * i + 1)))));
- }
+ break;
+ }
- putWReg(wd,
- binop(Iop_Sub64x2,
- getWReg(wd),
- binop(Iop_64HLtoV128,
- mkexpr(tmp[1]),
- mkexpr(tmp[0]))));
- break;
- }
+ case 0x0B: { /* FSNE.df */
+ switch (df) {
+ case 0x00: { /* FSNE.W */
+ DIP("FSNE.W w%d, w%d, w%d", wd, ws, wt);
+ calculateMSACSR(ws, wt, FSNEW, 2);
+ putWReg(wd,
+ binop(Iop_XorV128,
+ unop(Iop_NotV128,
+ binop(Iop_CmpEQ32Fx4,
+ getWReg(ws),
+ getWReg(wt))),
+ binop(Iop_CmpUN32Fx4,
+ getWReg(ws),
+ getWReg(wt))));
+ break;
+ }
- default:
- return -1;
+ case 0x01: { /* FSNE.D */
+ DIP("FSNE.D w%d, w%d, w%d", wd, ws, wt);
+ calculateMSACSR(ws, wt, FSNED, 2);
+ putWReg(wd,
+ binop(Iop_XorV128,
+ unop(Iop_NotV128,
+ binop(Iop_CmpEQ64Fx2,
+ getWReg(ws),
+ getWReg(wt))),
+ binop(Iop_CmpUN64Fx2,
+ getWReg(ws),
+ getWReg(wt))));
+ break;
}
- break;
+ default:
+ return -1;
}
- case 0x05: { /* DPSUB_U.df */
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
+ break;
+ }
- switch (df) {
- case 0x01: { /* DPSUB_U.H */
- DIP("DPSUB_U.H w%d, w%d, w%d", wd, ws, wt);
- IRTemp tmp[8];
- Int i;
+ case 0x0C: { /* MULR_Q.df */
+ switch (df) {
+ case 0x00: { /* MULR_Q.H */
+ DIP("MULR_Q.H w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3, binop(Iop_QRDMulHi16Sx8,
+ mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- for (i = 0; i < 8; i++) {
- tmp[i] = newTemp(Ity_I16);
- assign(tmp[i],
- binop(Iop_Add16,
- binop(Iop_MullU8,
- binop(Iop_GetElem8x16,
- mkexpr(t1),
- mkU8(2 * i)),
- binop(Iop_GetElem8x16,
- mkexpr(t2),
- mkU8(2 * i))),
- binop(Iop_MullU8,
- binop(Iop_GetElem8x16,
- mkexpr(t1),
- mkU8(2 * i + 1)),
- binop(Iop_GetElem8x16,
- mkexpr(t2),
- mkU8(2 * i + 1)))));
- }
+ case 0x01: { /* MULR_Q.W */
+ DIP("MULR_Q.W w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3, binop(Iop_QRDMulHi32Sx4,
+ mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- putWReg(wd,
- binop(Iop_Sub16x8,
- getWReg(wd),
- binop(Iop_64HLtoV128,
- binop(Iop_32HLto64,
- binop(Iop_16HLto32,
- mkexpr(tmp[7]),
- mkexpr(tmp[6])),
- binop(Iop_16HLto32,
- mkexpr(tmp[5]),
- mkexpr(tmp[4]))),
- binop(Iop_32HLto64,
- binop(Iop_16HLto32,
- mkexpr(tmp[3]),
- mkexpr(tmp[2])),
- binop(Iop_16HLto32,
- mkexpr(tmp[1]),
- mkexpr(tmp[0]))))));
- break;
- }
+ default:
+ return -1;
+ }
- case 0x02: { /* DPSUB_U.W */
- DIP("DPSUB_U.W w%d, w%d, w%d", wd, ws, wt);
- IRTemp tmp[4];
- Int i;
+ break;
+ }
- for (i = 0; i < 4; i++) {
- tmp[i] = newTemp(Ity_I32);
- assign(tmp[i],
- binop(Iop_Add32,
- binop(Iop_MullU16,
- binop(Iop_GetElem16x8,
- mkexpr(t1),
- mkU8(2 * i)),
- binop(Iop_GetElem16x8,
- mkexpr(t2),
- mkU8(2 * i))),
- binop(Iop_MullU16,
- binop(Iop_GetElem16x8,
- mkexpr(t1),
- mkU8(2 * i + 1)),
- binop(Iop_GetElem16x8,
- mkexpr(t2),
- mkU8(2 * i + 1)))));
- }
+ case 0x0D: { /* MADDR_Q.df */
+ switch (df) {
+ case 0x00: { /* MADDR_Q.W */
+ DIP("MADDR_Q.W w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ t4 = newTemp(Ity_V128);
+ t5 = newTemp(Ity_V128);
+ t6 = newTemp(Ity_V128);
+ assign(t1, // even
+ binop(Iop_SarN32x4,
+ binop(Iop_InterleaveEvenLanes16x8,
+ getWReg(ws),
+ getWReg(ws)),
+ mkU8(16)));
+ assign(t2, // odd
+ binop(Iop_SarN32x4,
+ getWReg(ws), mkU8(16)));
+ assign(t3, // even
+ binop(Iop_SarN32x4,
+ binop(Iop_InterleaveEvenLanes16x8,
+ getWReg(wt),
+ getWReg(wt)),
+ mkU8(16)));
+ assign(t4, // odd
+ binop(Iop_SarN32x4,
+ getWReg(wt), mkU8(16)));
+ assign(t5,
+ binop(Iop_Add32x4,
+ binop(Iop_ShlN32x4,
+ binop(Iop_SarN32x4,
+ binop(Iop_InterleaveEvenLanes16x8,
+ getWReg(wd),
+ getWReg(wd)),
+ mkU8(16)),
+ mkU8(15)),
+ binop(Iop_Mul32x4,
+ mkexpr(t1), mkexpr(t3))));
+ assign(t6,
+ binop(Iop_Add32x4,
+ binop(Iop_ShlN32x4,
+ binop(Iop_SarN32x4,
+ getWReg(wd),
+ mkU8(16)),
+ mkU8(15)),
+ binop(Iop_Mul32x4,
+ mkexpr(t2), mkexpr(t4))));
+ putWReg(wd,
+ binop(Iop_InterleaveEvenLanes16x8,
+ binop(Iop_QandQRSarNnarrow32Sto16Sx4,
+ mkexpr(t6), mkU8(15)),
+ binop(Iop_QandQRSarNnarrow32Sto16Sx4,
+ mkexpr(t5), mkU8(15))));
+ break;
+ }
- putWReg(wd,
- binop(Iop_Sub32x4,
- getWReg(wd),
- binop(Iop_64HLtoV128,
- binop(Iop_32HLto64,
- mkexpr(tmp[3]),
- mkexpr(tmp[2])),
- binop(Iop_32HLto64,
- mkexpr(tmp[1]),
- mkexpr(tmp[0])))));
- break;
- }
+ case 0x01: { /* MADDR_Q.D */
+ DIP("MADDR_Q.D w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ t4 = newTemp(Ity_V128);
+ t5 = newTemp(Ity_V128);
+ t6 = newTemp(Ity_V128);
+ assign(t1, // even
+ binop(Iop_SarN64x2,
+ binop(Iop_InterleaveEvenLanes32x4,
+ getWReg(ws),
+ getWReg(ws)),
+ mkU8(32)));
+ assign(t2, // odd
+ binop(Iop_SarN64x2,
+ getWReg(ws), mkU8(32)));
+ assign(t3, // even
+ binop(Iop_SarN64x2,
+ binop(Iop_InterleaveEvenLanes32x4,
+ getWReg(wt),
+ getWReg(wt)),
+ mkU8(32)));
+ assign(t4, // odd
+ binop(Iop_SarN64x2,
+ getWReg(wt), mkU8(32)));
+ assign(t5,
+ binop(Iop_Add64x2,
+ binop(Iop_ShlN64x2,
+ binop(Iop_SarN64x2,
+ binop(Iop_InterleaveEvenLanes32x4,
+ getWReg(wd),
+ getWReg(wd)),
+ mkU8(32)),
+ mkU8(31)),
+ binop(Iop_64HLtoV128,
+ binop(Iop_Mul64,
+ unop(Iop_V128HIto64,
+ mkexpr(t1)),
+ unop(Iop_V128HIto64,
+ mkexpr(t3))),
+ binop(Iop_Mul64,
+ unop(Iop_V128to64,
+ mkexpr(t1)),
+ unop(Iop_V128to64,
+ mkexpr(t3))))));
+ assign(t6,
+ binop(Iop_Add64x2,
+ binop(Iop_ShlN64x2,
+ binop(Iop_SarN64x2,
+ getWReg(wd),
+ mkU8(32)),
+ mkU8(31)),
+ binop(Iop_64HLtoV128,
+ binop(Iop_Mul64,
+ unop(Iop_V128HIto64,
+ mkexpr(t2)),
+ unop(Iop_V128HIto64,
+ mkexpr(t4))),
+ binop(Iop_Mul64,
+ unop(Iop_V128to64,
+ mkexpr(t2)),
+ unop(Iop_V128to64,
+ mkexpr(t4))))));
+ putWReg(wd,
+ binop(Iop_InterleaveEvenLanes32x4,
+ binop(Iop_QandQRSarNnarrow64Sto32Sx2,
+ mkexpr(t6), mkU8(31)),
+ binop(Iop_QandQRSarNnarrow64Sto32Sx2,
+ mkexpr(t5), mkU8(31))));
+ break;
+ }
- case 0x03: { /* DPSUB_U.D */
- DIP("DPSUB_U.D w%d, w%d, w%d", wd, ws, wt);
- IRTemp tmp[2];
- Int i;
+ default:
+ return -1;
+ }
- for (i = 0; i < 2; i++) {
- tmp[i] = newTemp(Ity_I64);
- assign(tmp[i],
- binop(Iop_Add64,
- binop(Iop_MullU32,
- binop(Iop_GetElem32x4,
- mkexpr(t1),
- mkU8(2 * i)),
- binop(Iop_GetElem32x4,
- mkexpr(t2),
- mkU8(2 * i))),
- binop(Iop_MullU32,
- binop(Iop_GetElem32x4,
- mkexpr(t1),
- mkU8(2 * i + 1)),
- binop(Iop_GetElem32x4,
- mkexpr(t2),
- mkU8(2 * i + 1)))));
- }
+ break;
+ }
- putWReg(wd,
- binop(Iop_Sub64x2,
- getWReg(wd),
- binop(Iop_64HLtoV128,
- mkexpr(tmp[1]),
- mkexpr(tmp[0]))));
- break;
- }
+ case 0x0E: { /* MSUBR_Q.df */
+ switch (df) {
+ case 0x00: { /* MSUBR_Q.W */
+ DIP("MSUBR_Q.W w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ t4 = newTemp(Ity_V128);
+ t5 = newTemp(Ity_V128);
+ t6 = newTemp(Ity_V128);
+ assign(t1, // even
+ binop(Iop_SarN32x4,
+ binop(Iop_InterleaveEvenLanes16x8,
+ getWReg(ws),
+ getWReg(ws)),
+ mkU8(16)));
+ assign(t2, // odd
+ binop(Iop_SarN32x4,
+ getWReg(ws), mkU8(16)));
+ assign(t3, // even
+ binop(Iop_SarN32x4,
+ binop(Iop_InterleaveEvenLanes16x8,
+ getWReg(wt),
+ getWReg(wt)),
+ mkU8(16)));
+ assign(t4, // odd
+ binop(Iop_SarN32x4,
+ getWReg(wt), mkU8(16)));
+ assign(t5,
+ binop(Iop_Sub32x4,
+ binop(Iop_ShlN32x4,
+ binop(Iop_SarN32x4,
+ binop(Iop_InterleaveEvenLanes16x8,
+ getWReg(wd),
+ getWReg(wd)),
+ mkU8(16)),
+ mkU8(15)),
+ binop(Iop_Mul32x4,
+ mkexpr(t1), mkexpr(t3))));
+ assign(t6,
+ binop(Iop_Sub32x4,
+ binop(Iop_ShlN32x4,
+ binop(Iop_SarN32x4,
+ getWReg(wd),
+ mkU8(16)),
+ mkU8(15)),
+ binop(Iop_Mul32x4,
+ mkexpr(t2), mkexpr(t4))));
+ putWReg(wd,
+ binop(Iop_InterleaveEvenLanes16x8,
+ binop(Iop_QandQRSarNnarrow32Sto16Sx4,
+ mkexpr(t6), mkU8(15)),
+ binop(Iop_QandQRSarNnarrow32Sto16Sx4,
+ mkexpr(t5), mkU8(15))));
+ break;
+ }
- default:
- return -1;
+ case 0x01: { /* MSUBR_Q.D */
+ DIP("MSUBR_Q.D w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ t4 = newTemp(Ity_V128);
+ t5 = newTemp(Ity_V128);
+ t6 = newTemp(Ity_V128);
+ assign(t1, // even
+ binop(Iop_SarN64x2,
+ binop(Iop_InterleaveEvenLanes32x4,
+ getWReg(ws),
+ getWReg(ws)),
+ mkU8(32)));
+ assign(t2, // odd
+ binop(Iop_SarN64x2,
+ getWReg(ws), mkU8(32)));
+ assign(t3, // even
+ binop(Iop_SarN64x2,
+ binop(Iop_InterleaveEvenLanes32x4,
+ getWReg(wt),
+ getWReg(wt)),
+ mkU8(32)));
+ assign(t4, // odd
+ binop(Iop_SarN64x2,
+ getWReg(wt), mkU8(32)));
+ assign(t5,
+ binop(Iop_Sub64x2,
+ binop(Iop_ShlN64x2,
+ binop(Iop_SarN64x2,
+ binop(Iop_InterleaveEvenLanes32x4,
+ getWReg(wd),
+ getWReg(wd)),
+ mkU8(32)),
+ mkU8(31)),
+ binop(Iop_64HLtoV128,
+ binop(Iop_Mul64,
+ unop(Iop_V128HIto64,
+ mkexpr(t1)),
+ unop(Iop_V128HIto64,
+ mkexpr(t3))),
+ binop(Iop_Mul64,
+ unop(Iop_V128to64,
+ mkexpr(t1)),
+ unop(Iop_V128to64,
+ mkexpr(t3))))));
+ assign(t6,
+ binop(Iop_Sub64x2,
+ binop(Iop_ShlN64x2,
+ binop(Iop_SarN64x2,
+ getWReg(wd),
+ mkU8(32)),
+ mkU8(31)),
+ binop(Iop_64HLtoV128,
+ binop(Iop_Mul64,
+ unop(Iop_V128HIto64,
+ mkexpr(t2)),
+ unop(Iop_V128HIto64,
+ mkexpr(t4))),
+ binop(Iop_Mul64,
+ unop(Iop_V128to64,
+ mkexpr(t2)),
+ unop(Iop_V128to64,
+ mkexpr(t4))))));
+ putWReg(wd,
+ binop(Iop_InterleaveEvenLanes32x4,
+ binop(Iop_QandQRSarNnarrow64Sto32Sx2,
+ mkexpr(t6), mkU8(31)),
+ binop(Iop_QandQRSarNnarrow64Sto32Sx2,
+ mkexpr(t5), mkU8(31))));
+ break;
}
- break;
+ default:
+ return -1;
}
+ break;
+ }
+
default:
return -1;
}
return 0;
}
-static Int msa_3R_14(UInt cins, UChar wd, UChar ws) { /* 3R (0x14) */
- IRTemp t1, t2, t3, t4;
+static Int msa_ELM(UInt cins, UChar wd, UChar ws) /* ELM (0x19) */
+{
+ IRTemp t1, t2, t3, t4, t5;
IRType ty;
UShort operation;
- UChar df, wt;
+ UChar df, n;
+
+ operation = (cins & 0x03C00000) >> 22;
+ ty = mode64 ? Ity_I64 : Ity_I32;
+
+ switch ((cins & 0x03FF0000) >> 16) {
+ case 0x07E: /* CFCMSA */
+ DIP("CFCMSA r%d, c%d", wd, ws);
+
+ switch (ws) {
+ case 0: { /* MSAIR */
+ IRDirty *d;
+ t1 = newTemp(Ity_I32);
+ /* IRExpr_BBPTR() =>
+ Need to pass pointer to
+ guest state to helper. */
+ d = unsafeIRDirty_1_N(t1, 0,
+ "mips_dirtyhelper_get_MSAIR",
+ &mips_dirtyhelper_get_MSAIR,
+ mkIRExprVec_0());
+ /* d->nFxState = 0; */
+ stmt(IRStmt_Dirty(d));
+ putIReg(wd,
+ mkWidenFrom32(ty, mkexpr(t1), True));
+ break;
+ }
+
+ case 1: /* MSACSR */
+ putIReg(wd,
+ mkWidenFrom32(ty, getMSACSR(), True));
+ break;
+
+ default:
+ putIReg(wd,
+ mkWidenFrom32(ty, mkU32(0), False));
+ break;
+ }
+
+ break;
+
+ case 0x03E: /* CTCMSA */
+ DIP("CTCMSA r%d, c%d", ws, wd);
+
+ if (wd == 1) { /* MSACSR */
+ putMSACSR(
+ binop(Iop_And32, mkNarrowTo32(ty, getIReg(ws)),
+ mkU32(0x1FFFFFF)));
+ }
+
+ break;
+
+ case 0x0BE: /* MOVE.V */
+ DIP("MOVE.V w%d, w%d", ws, wd);
+ putWReg(wd, getWReg(ws));
+ break;
+
+ default:
+ df = (cins & 0x003F0000) >> 16;
- operation = (cins & 0x03800000) >> 23;
- df = (cins & 0x00600000) >> 21;
- wt = (cins & 0x001F0000) >> 16;
- ty = mode64 ? Ity_I64 : Ity_I32;
+ if ((df & 0x38) == 0x38) { // 11100n; dw
+ n = df & 0x01;
+ df = 0x38;
+ } else if ((df & 0x30) == 0x30) { // 1100nn; w
+ n = df & 0x03;
+ df = 0x30;
+ } else if ((df & 0x20) == 0x20) { // 100nnn; hw
+ n = df & 0x07;
+ df = 0x20;
+ } else if ((df & 0x00) == 0x00) { // 00nnnn; b
+ n = df & 0x0F;
+ df = 0x00;
+ }
- switch (operation) {
- case 0x00: { /* SLD.df */
- switch (df) {
- case 0x00: {
- DIP("SLD.B w%d, w%d[%d]", wd, ws, wt);
- t1 = newTemp(Ity_I32);
+ switch (operation) {
+ case 0x00: /* SLDI.df */
+ switch (df) {
+ case 0x00: /* SLDI.B */
+ DIP("SLDI.B w%d, w%d[%d]", wd, ws, n);
+ t1 = newTemp(Ity_V128);
t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
assign(t1,
- binop(Iop_Shl32,
- binop(Iop_And32,
- mkNarrowTo32(ty,
- getIReg(wt)),
- mkU32(15)),
- mkU8(3)));
- assign(t2,
binop(Iop_ShrV128,
getWReg(ws),
- unop(Iop_32to8, mkexpr(t1))));
- assign(t3,
+ mkU8(n << 3)));
+ assign(t2,
binop(Iop_ShlV128,
getWReg(wd),
- unop(Iop_32to8,
- binop(Iop_Sub32,
- mkU32(128),
- mkexpr(t1)))));
+ mkU8(n ?
+ (16 - n) << 3 : 0)));
putWReg(wd,
- binop(Iop_OrV128,
- mkexpr(t2), mkexpr(t3)));
+ binop(Iop_OrV128, mkexpr(t1), mkexpr(t2)));
break;
- }
- case 0x01: {/* SLD.H */
- DIP("SLD.H w%d, w%d[%d]", wd, ws, wt);
- t1 = newTemp(Ity_I32);
- t2 = newTemp(Ity_I64);
- t3 = newTemp(Ity_V128);
- t4 = newTemp(Ity_V128);
- assign(t1,
- binop(Iop_Shl32,
- binop(Iop_And32,
- mkNarrowTo32(ty,
- getIReg(wt)),
- mkU32(7)),
- mkU8(3)));
- assign(t2,
- binop(Iop_32HLto64, mkU32(0), mkexpr(t1)));
- assign(t3,
- binop(Iop_Shr64x2,
- getWReg(ws),
- binop(Iop_64HLtoV128,
- mkexpr(t2), mkexpr(t2))));
- assign(t4,
- binop(Iop_Shl64x2,
- getWReg(wd),
- binop(Iop_Sub64x2,
- binop(Iop_64HLtoV128,
- mkU64(0x40ul),
- mkU64(0x40ul)),
- binop(Iop_64HLtoV128,
- mkexpr(t2),
- mkexpr(t2)))));
- putWReg(wd,
- binop(Iop_OrV128,
- mkexpr(t3),
- IRExpr_ITE(
- binop(Iop_CmpNE32,
- mkexpr(t1), mkU32(0)),
- mkexpr(t4),
- binop(Iop_64HLtoV128,
- mkU64(0), mkU64(0)))));
- break;
- }
+ case 0x20: /* SLDI.H */
+ DIP("SLDI.H w%d, w%d[%d]", wd, ws, n);
- case 0x02: {/* SLD.W */
- DIP("SLD.W w%d, w%d[%d]", wd, ws, wt);
- t1 = newTemp(Ity_I32);
- t2 = newTemp(Ity_I64);
- t3 = newTemp(Ity_V128);
- t4 = newTemp(Ity_V128);
- assign(t1,
- binop(Iop_Shl32,
- binop(Iop_And32,
- mkNarrowTo32(ty,
- getIReg(wt)),
- mkU32(3)),
- mkU8(3)));
- assign(t2,
- binop(Iop_32HLto64,
- mkexpr(t1), mkexpr(t1)));
- assign(t3,
- binop(Iop_Shr32x4,
- getWReg(ws),
- binop(Iop_64HLtoV128,
- mkexpr(t2), mkexpr(t2))));
- assign(t4,
- binop(Iop_Shl32x4,
- getWReg(wd),
- binop(Iop_Sub32x4,
- binop(Iop_64HLtoV128,
- mkU64(0x2000000020ul),
- mkU64(0x2000000020ul)),
- binop(Iop_64HLtoV128,
- mkexpr(t2),
- mkexpr(t2)))));
- putWReg(wd,
- binop(Iop_OrV128,
- mkexpr(t3),
- IRExpr_ITE(
- binop(Iop_CmpNE32,
- mkexpr(t1), mkU32(0)),
- mkexpr(t4),
- binop(Iop_64HLtoV128,
- mkU64(0), mkU64(0)))));
- break;
- }
+ if (n == 0) {
+ putWReg(wd, getWReg(ws));
+ } else {
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ assign(t1,
+ binop(Iop_ShrN64x2,
+ getWReg(ws),
+ mkU8(n << 3)));
+ assign(t2,
+ binop(Iop_ShlN64x2,
+ getWReg(wd),
+ mkU8((8 - n) << 3)));
+ putWReg(wd,
+ binop(Iop_OrV128,
+ mkexpr(t1),
+ mkexpr(t2)));
+ }
- case 0x03: { /* SLD.D */
- DIP("SLD.D w%d, w%d[%d]", wd, ws, wt);
- t1 = newTemp(Ity_I32);
- t2 = newTemp(Ity_I64);
- t3 = newTemp(Ity_V128);
- t4 = newTemp(Ity_V128);
- assign(t1,
- binop(Iop_Shl32,
- binop(Iop_And32,
- mkNarrowTo32(ty,
- getIReg(wt)),
- mkU32(1)),
- mkU8(3)));
- assign(t2,
- binop(Iop_32HLto64,
- binop(Iop_Or32,
- mkexpr(t1),
- binop(Iop_Shl32,
- mkexpr(t1), mkU8(16))),
- binop(Iop_Or32,
- mkexpr(t1),
- binop(Iop_Shl32,
- mkexpr(t1), mkU8(16)))));
- assign(t3,
- binop(Iop_Shr16x8,
- getWReg(ws),
- binop(Iop_64HLtoV128,
- mkexpr(t2), mkexpr(t2))));
- assign(t4,
- binop(Iop_Shl16x8,
- getWReg(wd),
- binop(Iop_Sub16x8,
- binop(Iop_64HLtoV128,
- mkU64(0x10001000100010ul),
- mkU64(0x10001000100010ul)),
- binop(Iop_64HLtoV128,
- mkexpr(t2),
- mkexpr(t2)))));
- putWReg(wd,
- binop(Iop_OrV128,
- mkexpr(t3),
- IRExpr_ITE(
- binop(Iop_CmpNE32,
- mkexpr(t1), mkU32(0)),
- mkexpr(t4),
- binop(Iop_64HLtoV128,
- mkU64(0), mkU64(0)))));
break;
- }
- }
-
- break;
- }
-
- case 0x01: { /* SPLAT.df */
- switch (df) {
- Int i;
- case 0x00: { /* SPLAT.B */
- DIP("SPLAT.B w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_I32);
- assign(t1, getWReg(ws));
- assign(t2,
- mkNarrowTo32(ty, getIReg(wt)));
- IRTemp tmp[16];
+ case 0x30: /* SLDI.W */
+ DIP("SLDI.W w%d, w%d[%d]", wd, ws, n);
- for (i = 0; i < 16; i++) {
- tmp[i] = newTemp(Ity_I8);
- assign(tmp[i],
- binop(Iop_GetElem8x16,
- mkexpr(t1),
- unop(Iop_32to8, mkexpr(t2))));
+ if (n == 0) {
+ putWReg(wd, getWReg(ws));
+ } else {
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ assign(t1,
+ binop(Iop_ShrN32x4,
+ getWReg(ws),
+ mkU8(n << 3)));
+ assign(t2,
+ binop(Iop_ShlN32x4,
+ getWReg(wd),
+ mkU8((4 - n) << 3)));
+ putWReg(wd,
+ binop(Iop_OrV128,
+ mkexpr(t1),
+ mkexpr(t2)));
}
- putWReg(wd,
- binop(Iop_64HLtoV128,
- binop(Iop_32HLto64,
- binop(Iop_16HLto32,
- binop(Iop_8HLto16,
- mkexpr(tmp[15]),
- mkexpr(tmp[14])),
- binop(Iop_8HLto16,
- mkexpr(tmp[13]),
- mkexpr(tmp[12]))),
- binop(Iop_16HLto32,
- binop(Iop_8HLto16,
- mkexpr(tmp[11]),
- mkexpr(tmp[10])),
- binop(Iop_8HLto16,
- mkexpr(tmp[9]),
- mkexpr(tmp[8])))),
- binop(Iop_32HLto64,
- binop(Iop_16HLto32,
- binop(Iop_8HLto16,
- mkexpr(tmp[7]),
- mkexpr(tmp[6])),
- binop(Iop_8HLto16,
- mkexpr(tmp[5]),
- mkexpr(tmp[4]))),
- binop(Iop_16HLto32,
- binop(Iop_8HLto16,
- mkexpr(tmp[3]),
- mkexpr(tmp[2])),
- binop(Iop_8HLto16,
- mkexpr(tmp[1]),
- mkexpr(tmp[0]))))));
break;
- }
- case 0x01: { /* SPLAT.H */
- DIP("SPLAT.H w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_I32);
- assign(t1, getWReg(ws));
- assign(t2,
- mkNarrowTo32(ty, getIReg(wt)));
- IRTemp tmp[8];
+ case 0x38: /* SLDI.D */
+ DIP("SLDI.D w%d, w%d[%d]", wd, ws, n);
- for (i = 0; i < 8; i++) {
- tmp[i] = newTemp(Ity_I16);
- assign(tmp[i],
- binop(Iop_GetElem16x8,
- mkexpr(t1),
- unop(Iop_32to8, mkexpr(t2))));
+ if (n == 0) {
+ putWReg(wd, getWReg(ws));
+ } else {
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ assign(t1,
+ binop(Iop_ShrN16x8,
+ getWReg(ws),
+ mkU8(n << 3)));
+ assign(t2,
+ binop(Iop_ShlN16x8,
+ getWReg(wd),
+ mkU8((2 - n) << 3)));
+ putWReg(wd,
+ binop(Iop_OrV128,
+ mkexpr(t1),
+ mkexpr(t2)));
}
- putWReg(wd,
- binop(Iop_64HLtoV128,
- binop(Iop_32HLto64,
- binop(Iop_16HLto32,
- mkexpr(tmp[7]),
- mkexpr(tmp[6])),
- binop(Iop_16HLto32,
- mkexpr(tmp[5]),
- mkexpr(tmp[4]))),
- binop(Iop_32HLto64,
- binop(Iop_16HLto32,
- mkexpr(tmp[3]),
- mkexpr(tmp[2])),
- binop(Iop_16HLto32,
- mkexpr(tmp[1]),
- mkexpr(tmp[0])))));
break;
- }
-
- case 0x02: { /* SPLAT.W */
- DIP("SPLAT.W w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_I32);
- assign(t1, getWReg(ws));
- assign(t2,
- mkNarrowTo32(ty, getIReg(wt)));
- IRTemp tmp[4];
- for (i = 0; i < 4; i++) {
- tmp[i] = newTemp(Ity_I32);
- assign(tmp[i],
- binop(Iop_GetElem32x4,
- mkexpr(t1),
- unop(Iop_32to8, mkexpr(t2))));
- }
+ default:
+ return -1;
+ }
- putWReg(wd,
- binop(Iop_64HLtoV128,
- binop(Iop_32HLto64,
- mkexpr(tmp[3]),
- mkexpr(tmp[2])),
- binop(Iop_32HLto64,
- mkexpr(tmp[1]),
- mkexpr(tmp[0]))));
- break;
- }
+ break;
- case 0x03: { /* SPLAT.D */
- DIP("SPLAT.D w%d, w%d, w%d", wd, ws, wt);
+ case 0x01: /* SPLATI.df */
+ switch (df) {
+ case 0x00: { /* SPLATI.B */
+ DIP("SPLATI.B w%d, w%d[%d]", wd, ws, n);
t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_I32);
- assign(t1, getWReg(ws));
- assign(t2,
- mkNarrowTo32(ty, getIReg(wt)));
- IRTemp tmp[2];
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ t4 = newTemp(Ity_V128);
- for (i = 0; i < 2; i++) {
- tmp[i] = newTemp(Ity_I64);
- assign(tmp[i],
- binop(Iop_GetElem64x2,
- mkexpr(t1),
- unop(Iop_32to8, mkexpr(t2))));
- }
+ if (n & 1)
+ assign(t1,
+ binop(Iop_InterleaveOddLanes8x16,
+ getWReg(ws),
+ getWReg(ws)));
+ else
+ assign(t1,
+ binop(Iop_InterleaveEvenLanes8x16,
+ getWReg(ws),
+ getWReg(ws)));
- putWReg(wd,
- binop(Iop_64HLtoV128,
- mkexpr(tmp[1]), mkexpr(tmp[0])));
- break;
- }
- }
+ n /= 2;
- break;
- }
+ if (n & 1)
+ assign(t2,
+ binop(Iop_InterleaveOddLanes16x8,
+ mkexpr(t1), mkexpr(t1)));
+ else
+ assign(t2,
+ binop(Iop_InterleaveEvenLanes16x8,
+ mkexpr(t1), mkexpr(t1)));
- case 0x02: { /* PCKEV.df */
- switch (df) {
- case 0x00: { /* PCKEV.B */
- DIP("PCKEV.B w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3,
- binop(Iop_PackEvenLanes8x16,
- mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
+ n /= 2;
+
+ if (n & 1)
+ assign(t3,
+ binop(Iop_InterleaveOddLanes32x4,
+ mkexpr(t2), mkexpr(t2)));
+ else
+ assign(t3,
+ binop(Iop_InterleaveEvenLanes32x4,
+ mkexpr(t2), mkexpr(t2)));
+
+ n /= 2;
+
+ if (n & 1)
+ assign(t4,
+ binop(Iop_InterleaveHI64x2,
+ mkexpr(t3), mkexpr(t3)));
+ else
+ assign(t4,
+ binop(Iop_InterleaveLO64x2,
+ mkexpr(t3), mkexpr(t3)));
+
+ putWReg(wd, mkexpr(t4));
break;
}
- case 0x01: { /* PCKEV.H */
- DIP("PCKEV.H w%d, w%d, w%d", wd, ws, wt);
+ case 0x20: { /* SPLATI.H */
+ DIP("SPLATI.H w%d, w%d[%d]", wd, ws, n);
t1 = newTemp(Ity_V128);
t2 = newTemp(Ity_V128);
t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3,
- binop(Iop_PackEvenLanes16x8,
- mkexpr(t1), mkexpr(t2)));
+
+ if (n & 1)
+ assign(t1,
+ binop(Iop_InterleaveOddLanes16x8,
+ getWReg(ws),
+ getWReg(ws)));
+ else
+ assign(t1,
+ binop(Iop_InterleaveEvenLanes16x8,
+ getWReg(ws),
+ getWReg(ws)));
+
+ n /= 2;
+
+ if (n & 1)
+ assign(t2,
+ binop(Iop_InterleaveOddLanes32x4,
+ mkexpr(t1), mkexpr(t1)));
+ else
+ assign(t2,
+ binop(Iop_InterleaveEvenLanes32x4,
+ mkexpr(t1), mkexpr(t1)));
+
+ n /= 2;
+
+ if (n & 1)
+ assign(t3,
+ binop(Iop_InterleaveHI64x2,
+ mkexpr(t2), mkexpr(t2)));
+ else
+ assign(t3,
+ binop(Iop_InterleaveLO64x2,
+ mkexpr(t2), mkexpr(t2)));
+
putWReg(wd, mkexpr(t3));
break;
}
- case 0x02: { /* PCKEV.W */
- DIP("PCKEV.W w%d, w%d, w%d", wd, ws, wt);
+ case 0x30: { /* SPLATI.W */
+ DIP("SPLATI.W w%d, w%d[%d]", wd, ws, n);
t1 = newTemp(Ity_V128);
t2 = newTemp(Ity_V128);
t3 = newTemp(Ity_V128);
assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3,
- binop(Iop_PackEvenLanes32x4,
- mkexpr(t1), mkexpr(t2)));
+
+ if (n & 1)
+ assign(t2,
+ binop(Iop_InterleaveOddLanes32x4,
+ mkexpr(t1), mkexpr(t1)));
+ else
+ assign(t2,
+ binop(Iop_InterleaveEvenLanes32x4,
+ mkexpr(t1), mkexpr(t1)));
+
+ n /= 2;
+
+ if (n & 1)
+ assign(t3,
+ binop(Iop_InterleaveHI64x2,
+ mkexpr(t2), mkexpr(t2)));
+ else
+ assign(t3,
+ binop(Iop_InterleaveLO64x2,
+ mkexpr(t2), mkexpr(t2)));
+
putWReg(wd, mkexpr(t3));
break;
}
- case 0x03: { /* PCKEV.D */
- DIP("PCKEV.D w%d, w%d, w%d", wd, ws, wt);
+ case 0x38: /* SPLATI.D */
+ DIP("SPLATI.D w%d, w%d[%d]", wd, ws, n);
t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
t3 = newTemp(Ity_V128);
assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3,
- binop(Iop_InterleaveLO64x2,
- mkexpr(t1), mkexpr(t2)));
+
+ if (n)
+ assign(t3,
+ binop(Iop_InterleaveHI64x2,
+ mkexpr(t1), mkexpr(t1)));
+ else
+ assign(t3,
+ binop(Iop_InterleaveLO64x2,
+ mkexpr(t1), mkexpr(t1)));
+
putWReg(wd, mkexpr(t3));
break;
- }
- default:
- return -1;
- }
+ default:
+ return -1;
+ }
- break;
- }
+ break;
- case 0x03: { /* PCKOD.df */
- switch (df) {
- case 0x00: { /* PCKOD.B */
- DIP("PCKOD.B w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3,
- binop(Iop_PackOddLanes8x16,
- mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
+ case 0x02: /* COPY_S.df */
+ switch (df) {
+ case 0x00: /* COPY_S.B */
+ DIP("COPY_S.B r%d, w%d[%d]", wd, ws, n);
+ t1 = newTemp(Ity_I8);
+
+ switch (n) {
+ case 0:
+ assign(t1,
+ unop(Iop_32to8,
+ unop(Iop_V128to32,
+ getWReg(ws))));
+ break;
+
+ case 1:
+ assign(t1,
+ unop(Iop_16HIto8,
+ unop(Iop_32to16,
+ unop(Iop_V128to32,
+ getWReg(ws)))));
+ break;
+
+ case 2:
+ assign(t1,
+ unop(Iop_16to8,
+ unop(Iop_32HIto16,
+ unop(Iop_64to32,
+ unop(Iop_V128to64,
+ getWReg(ws))))));
+ break;
+
+ case 3:
+ assign(t1,
+ unop(Iop_16HIto8,
+ unop(Iop_32HIto16,
+ unop(Iop_64to32,
+ unop(Iop_V128to64,
+ getWReg(ws))))));
+ break;
+
+ case 4:
+ assign(t1,
+ unop(Iop_16to8,
+ unop(Iop_32to16,
+ unop(Iop_64HIto32,
+ unop(Iop_V128to64,
+ getWReg(ws))))));
+ break;
+
+ case 5:
+ assign(t1,
+ unop(Iop_16HIto8,
+ unop(Iop_32to16,
+ unop(Iop_64HIto32,
+ unop(Iop_V128to64,
+ getWReg(ws))))));
+ break;
+
+ case 6:
+ assign(t1,
+ unop(Iop_16to8,
+ unop(Iop_32HIto16,
+ unop(Iop_64HIto32,
+ unop(Iop_V128to64,
+ getWReg(ws))))));
+ break;
+
+ case 7:
+ assign(t1,
+ unop(Iop_16HIto8,
+ unop(Iop_32HIto16,
+ unop(Iop_64HIto32,
+ unop(Iop_V128to64,
+ getWReg(ws))))));
+ break;
+
+ case 8:
+ assign(t1,
+ unop(Iop_16to8,
+ unop(Iop_32to16,
+ unop(Iop_64to32,
+ unop(Iop_V128HIto64,
+ getWReg(ws))))));
+ break;
+
+ case 9:
+ assign(t1,
+ unop(Iop_16HIto8,
+ unop(Iop_32to16,
+ unop(Iop_64to32,
+ unop(Iop_V128HIto64,
+ getWReg(ws))))));
+ break;
+
+ case 10:
+ assign(t1,
+ unop(Iop_16to8,
+ unop(Iop_32HIto16,
+ unop(Iop_64to32,
+ unop(Iop_V128HIto64,
+ getWReg(ws))))));
+ break;
+
+ case 11:
+ assign(t1,
+ unop(Iop_16HIto8,
+ unop(Iop_32HIto16,
+ unop(Iop_64to32,
+ unop(Iop_V128HIto64,
+ getWReg(ws))))));
+ break;
+
+ case 12:
+ assign(t1,
+ unop(Iop_16to8,
+ unop(Iop_32to16,
+ unop(Iop_64HIto32,
+ unop(Iop_V128HIto64,
+ getWReg(ws))))));
+ break;
+
+ case 13:
+ assign(t1,
+ unop(Iop_16HIto8,
+ unop(Iop_32to16,
+ unop(Iop_64HIto32,
+ unop(Iop_V128HIto64,
+ getWReg(ws))))));
+ break;
+
+ case 14:
+ assign(t1,
+ unop(Iop_16to8,
+ unop(Iop_32HIto16,
+ unop(Iop_64HIto32,
+ unop(Iop_V128HIto64,
+ getWReg(ws))))));
+ break;
+
+ case 15:
+ assign(t1,
+ unop(Iop_16HIto8,
+ unop(Iop_32HIto16,
+ unop(Iop_64HIto32,
+ unop(Iop_V128HIto64,
+ getWReg(ws))))));
+ break;
+ }
+
+ putIReg(wd,
+ unop(mode64 ? Iop_8Sto64 : Iop_8Sto32,
+ mkexpr(t1)));
break;
- }
- case 0x01: { /* PCKOD.H */
- DIP("PCKOD.H w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3,
- binop(Iop_PackOddLanes16x8,
- mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ case 0x20: /* COPY_S.H */
+ DIP("COPY_S.H r%d, w%d[%d]", wd, ws, n);
+ t1 = newTemp(Ity_I16);
+
+ switch (n) {
+ case 0:
+ assign(t1,
+ unop(Iop_32to16,
+ unop(Iop_64to32,
+ unop(Iop_V128to64,
+ getWReg(ws)))));
+ break;
+
+ case 1:
+ assign(t1,
+ unop(Iop_32HIto16,
+ unop(Iop_64to32,
+ unop(Iop_V128to64,
+ getWReg(ws)))));
+ break;
+
+ case 2:
+ assign(t1,
+ unop(Iop_32to16,
+ unop(Iop_64HIto32,
+ unop(Iop_V128to64,
+ getWReg(ws)))));
+ break;
+
+ case 3:
+ assign(t1,
+ unop(Iop_32HIto16,
+ unop(Iop_64HIto32,
+ unop(Iop_V128to64,
+ getWReg(ws)))));
+ break;
- case 0x02: { /* PCKOD.W */
- DIP("PCKOD.W w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3,
- binop(Iop_PackOddLanes32x4,
- mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ case 4:
+ assign(t1,
+ unop(Iop_32to16,
+ unop(Iop_64to32,
+ unop(Iop_V128HIto64,
+ getWReg(ws)))));
+ break;
- case 0x03: { /* PCKOD.D */
- DIP("PCKOD.D w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3,
- binop(Iop_InterleaveHI64x2,
- mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ case 5:
+ assign(t1,
+ unop(Iop_32HIto16,
+ unop(Iop_64to32,
+ unop(Iop_V128HIto64,
+ getWReg(ws)))));
+ break;
- default:
- return -1;
- }
+ case 6:
+ assign(t1,
+ unop(Iop_32to16,
+ unop(Iop_64HIto32,
+ unop(Iop_V128HIto64,
+ getWReg(ws)))));
+ break;
- break;
- }
+ case 7:
+ assign(t1,
+ unop(Iop_32HIto16,
+ unop(Iop_64HIto32,
+ unop(Iop_V128HIto64,
+ getWReg(ws)))));
+ break;
+ }
- case 0x04: { /* ILVL.df */
- switch (df) {
- case 0x00: { /* ILVL.B */
- DIP("ILVL.B w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3,
- binop(Iop_InterleaveHI8x16,
- mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
+ putIReg(wd,
+ unop(mode64 ? Iop_16Sto64 : Iop_16Sto32,
+ mkexpr(t1)));
break;
- }
- case 0x01: { /* ILVL.H */
- DIP("ILVL.H w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3,
- binop(Iop_InterleaveHI16x8,
- mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ case 0x30: /* COPY_S.W */
+ DIP("COPY_S.W r%d, w%d[%d]", wd, ws, n);
- case 0x02: { /* ILVL.W */
- DIP("ILVL.W w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3,
- binop(Iop_InterleaveHI32x4,
- mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ switch (n) {
+ case 0:
+ putIReg(wd,
+ mkWidenFrom32(ty,
+ unop(Iop_V128to32,
+ getWReg(ws)),
+ True));
+ break;
- case 0x03: { /* ILVL.D */
- DIP("ILVL.D w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3,
- binop(Iop_InterleaveHI64x2,
- mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ case 1:
+ t2 = newTemp(Ity_I64);
+ assign(t2,
+ unop(Iop_V128to64, getWReg(ws)));
+ putIReg(wd,
+ mkWidenFrom32(ty,
+ unop(Iop_64HIto32,
+ mkexpr(t2)),
+ True));
+ break;
- default:
- return -1;
- }
+ case 2:
+ t2 = newTemp(Ity_I64);
+ assign(t2,
+ unop(Iop_V128HIto64,
+ getWReg(ws)));
+ putIReg(wd,
+ mkWidenFrom32(ty,
+ unop(Iop_64to32,
+ mkexpr(t2)),
+ True));
+ break;
- break;
- }
+ case 3:
+ t2 = newTemp(Ity_I64);
+ assign(t2,
+ unop(Iop_V128HIto64,
+ getWReg(ws)));
+ putIReg(wd,
+ mkWidenFrom32(ty,
+ unop(Iop_64HIto32,
+ mkexpr(t2)),
+ True));
+ break;
- case 0x05: { /* ILVR.df */
- switch (df) {
- case 0x00: { /* ILVL.B */
- DIP("ILVL.B w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3,
- binop(Iop_InterleaveLO8x16,
- mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ default:
+ break;
+ }
- case 0x01: { /* ILVL.H */
- DIP("ILVL.H w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3,
- binop(Iop_InterleaveLO16x8,
- mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
break;
- }
- case 0x02: { /* ILVL.W */
- DIP("ILVL.W w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3,
- binop(Iop_InterleaveLO32x4,
- mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ case 0x38: /* COPY_S.D */
+ if (mode64) {
+ DIP("COPY_S.D r%d, w%d[%d]", wd, ws, n);
- case 0x03: { /* ILVL.D */
- DIP("ILVL.D w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3,
- binop(Iop_InterleaveLO64x2,
- mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
- }
+ switch (n) {
+ case 0:
+ putIReg(wd,
+ unop(Iop_V128to64,
+ getWReg(ws)));
+ break;
- break;
- }
+ case 1:
+ putIReg(wd,
+ unop(Iop_V128HIto64,
+ getWReg(ws)));
+ break;
+ }
+ } else {
+ return -2;
+ }
- case 0x06: { /* ILVEV.df */
- switch (df) {
- case 0x00: { /* ILVEV.B */
- DIP("ILVEV.B w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3,
- binop(Iop_InterleaveEvenLanes8x16,
- mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
break;
- }
- case 0x01: { /* ILVEV.H */
- DIP("ILVEV.H w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3,
- binop(Iop_InterleaveEvenLanes16x8,
- mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ default:
+ return -1;
+ }
- case 0x02: { /* ILVEV.W */
- DIP("ILVEV.W w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3,
- binop(Iop_InterleaveEvenLanes32x4,
- mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ break;
- case 0x03: { /* ILVEV.D */
- DIP("ILVEV.D w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3,
- binop(Iop_InterleaveLO64x2,
- mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ case 0x03: { /* COPY_U.df */
+ switch (df) {
+ case 0x00: /* COPY_U.B */
+ DIP("COPY_U.B r%d, w%d[%d]", wd, ws, n);
+ t1 = newTemp(Ity_I8);
- default:
- return -1;
- }
+ switch (n) {
+ case 0:
+ assign(t1,
+ unop(Iop_16to8,
+ unop(Iop_32to16,
+ unop(Iop_64to32,
+ unop(Iop_V128to64,
+ getWReg(ws))))));
+ break;
+
+ case 1:
+ assign(t1,
+ unop(Iop_16HIto8,
+ unop(Iop_32to16,
+ unop(Iop_64to32,
+ unop(Iop_V128to64,
+ getWReg(ws))))));
+ break;
- break;
- }
+ case 2:
+ assign(t1,
+ unop(Iop_16to8,
+ unop(Iop_32HIto16,
+ unop(Iop_64to32,
+ unop(Iop_V128to64,
+ getWReg(ws))))));
+ break;
- case 0x07: { /* ILVOD.df */
- switch (df) {
- case 0x00: { /* ILVOD.B */
- DIP("ILVOD.B w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3,
- binop(Iop_InterleaveOddLanes8x16,
- mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ case 3:
+ assign(t1,
+ unop(Iop_16HIto8,
+ unop(Iop_32HIto16,
+ unop(Iop_64to32,
+ unop(Iop_V128to64,
+ getWReg(ws))))));
+ break;
- case 0x01: { /* ILVOD.H */
- DIP("ILVOD.H w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3,
- binop(Iop_InterleaveOddLanes16x8,
- mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ case 4:
+ assign(t1,
+ unop(Iop_16to8,
+ unop(Iop_32to16,
+ unop(Iop_64HIto32,
+ unop(Iop_V128to64,
+ getWReg(ws))))));
+ break;
- case 0x02: { /* ILVOD.W */
- DIP("ILVOD.W w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3,
- binop(Iop_InterleaveOddLanes32x4,
- mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ case 5:
+ assign(t1,
+ unop(Iop_16HIto8,
+ unop(Iop_32to16,
+ unop(Iop_64HIto32,
+ unop(Iop_V128to64,
+ getWReg(ws))))));
+ break;
- case 0x03: { /* ILVOD.D */
- DIP("ILVOD.D w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3,
- binop(Iop_InterleaveHI64x2,
- mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ case 6:
+ assign(t1,
+ unop(Iop_16to8,
+ unop(Iop_32HIto16,
+ unop(Iop_64HIto32,
+ unop(Iop_V128to64,
+ getWReg(ws))))));
+ break;
- default:
- return -1;
- }
+ case 7:
+ assign(t1,
+ unop(Iop_16HIto8,
+ unop(Iop_32HIto16,
+ unop(Iop_64HIto32,
+ unop(Iop_V128to64,
+ getWReg(ws))))));
+ break;
- break;
- }
+ case 8:
+ assign(t1,
+ unop(Iop_16to8,
+ unop(Iop_32to16,
+ unop(Iop_64to32,
+ unop(Iop_V128HIto64,
+ getWReg(ws))))));
+ break;
- default:
- return -1;
- }
+ case 9:
+ assign(t1,
+ unop(Iop_16HIto8,
+ unop(Iop_32to16,
+ unop(Iop_64to32,
+ unop(Iop_V128HIto64,
+ getWReg(ws))))));
+ break;
- return 0;
-}
+ case 10:
+ assign(t1,
+ unop(Iop_16to8,
+ unop(Iop_32HIto16,
+ unop(Iop_64to32,
+ unop(Iop_V128HIto64,
+ getWReg(ws))))));
+ break;
-static Int msa_3R_15(UInt cins, UChar wd, UChar ws) { /* 3R (0x15) */
- IRTemp t1, t2, t3, t4;
- UShort operation;
- UChar df, wt;
+ case 11:
+ assign(t1,
+ unop(Iop_16HIto8,
+ unop(Iop_32HIto16,
+ unop(Iop_64to32,
+ unop(Iop_V128HIto64,
+ getWReg(ws))))));
+ break;
- operation = (cins & 0x03800000) >> 23;
- df = (cins & 0x00600000) >> 21;
- wt = (cins & 0x001F0000) >> 16;
+ case 12:
+ assign(t1,
+ unop(Iop_16to8,
+ unop(Iop_32to16,
+ unop(Iop_64HIto32,
+ unop(Iop_V128HIto64,
+ getWReg(ws))))));
+ break;
- switch (operation) {
- case 0x00: { /* VSHF.df */
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(wd));
- assign(t2, getWReg(ws));
- assign(t3, getWReg(wt));
+ case 13:
+ assign(t1,
+ unop(Iop_16HIto8,
+ unop(Iop_32to16,
+ unop(Iop_64HIto32,
+ unop(Iop_V128HIto64,
+ getWReg(ws))))));
+ break;
- switch (df) {
- case 0x00: { /* VSHF.B */
- DIP("VSHF.B w%d, w%d, w%d", wd, ws, wt);
- IRTemp tmp[16];
- Int i;
+ case 14:
+ assign(t1,
+ unop(Iop_16to8,
+ unop(Iop_32HIto16,
+ unop(Iop_64HIto32,
+ unop(Iop_V128HIto64,
+ getWReg(ws))))));
+ break;
- for (i = 0; i < 16; i++) {
- tmp[i] = newTemp(Ity_I8);
- assign(tmp[i],
- IRExpr_ITE(
- binop(Iop_CmpEQ8,
- binop(Iop_And8,
- binop(Iop_GetElem8x16,
- mkexpr(t1),
- mkU8(i)),
- mkU8(0xC0)),
- mkU8(0x0)),
- IRExpr_ITE(
- binop(Iop_CmpEQ8,
- binop(Iop_And8,
- binop(Iop_GetElem8x16,
- mkexpr(t1),
- mkU8(i)),
- mkU8(0x10)),
- mkU8(0x0)),
- binop(Iop_GetElem8x16,
- mkexpr(t3),
- binop(Iop_GetElem8x16,
- mkexpr(t1),
- mkU8(i))),
- binop(Iop_GetElem8x16,
- mkexpr(t2),
- binop(Iop_GetElem8x16,
- mkexpr(t1),
- mkU8(i)))),
- mkU8(0x0)));
+ case 15:
+ assign(t1,
+ unop(Iop_16HIto8,
+ unop(Iop_32HIto16,
+ unop(Iop_64HIto32,
+ unop(Iop_V128HIto64,
+ getWReg(ws))))));
+ break;
}
- putWReg(wd,
- binop(Iop_64HLtoV128,
- binop(Iop_32HLto64,
- binop(Iop_16HLto32,
- binop(Iop_8HLto16,
- mkexpr(tmp[15]),
- mkexpr(tmp[14])),
- binop(Iop_8HLto16,
- mkexpr(tmp[13]),
- mkexpr(tmp[12]))),
- binop(Iop_16HLto32,
- binop(Iop_8HLto16,
- mkexpr(tmp[11]),
- mkexpr(tmp[10])),
- binop(Iop_8HLto16,
- mkexpr(tmp[9]),
- mkexpr(tmp[8])))),
- binop(Iop_32HLto64,
- binop(Iop_16HLto32,
- binop(Iop_8HLto16,
- mkexpr(tmp[7]),
- mkexpr(tmp[6])),
- binop(Iop_8HLto16,
- mkexpr(tmp[5]),
- mkexpr(tmp[4]))),
- binop(Iop_16HLto32,
- binop(Iop_8HLto16,
- mkexpr(tmp[3]),
- mkexpr(tmp[2])),
- binop(Iop_8HLto16,
- mkexpr(tmp[1]),
- mkexpr(tmp[0]))))));
+ putIReg(wd,
+ unop(mode64 ? Iop_8Uto64 : Iop_8Uto32,
+ mkexpr(t1)));
break;
- }
- case 0x01: { /* VSHF.H */
- DIP("VSHF.H w%d, w%d, w%d", wd, ws, wt);
- IRTemp tmp[8];
- Int i;
+ case 0x20: /* COPY_U.H */
+ DIP("COPY_U.H r%d, w%d[%d]", wd, ws, n);
+ t1 = newTemp(Ity_I16);
- for (i = 0; i < 8; i++) {
- tmp[i] = newTemp(Ity_I16);
- assign(tmp[i],
- IRExpr_ITE(
- binop(Iop_CmpEQ16,
- binop(Iop_And16,
- binop(Iop_GetElem16x8,
- mkexpr(t1),
- mkU8(i)),
- mkU16(0xC0)),
- mkU16(0x0)),
- IRExpr_ITE(
- binop(Iop_CmpEQ16,
- binop(Iop_And16,
- binop(Iop_GetElem16x8,
- mkexpr(t1),
- mkU8(i)),
- mkU16(0x08)),
- mkU16(0x0)),
- binop(Iop_GetElem16x8,
- mkexpr(t3),
- unop(Iop_16to8,
- binop(Iop_GetElem16x8,
- mkexpr(t1),
- mkU8(i)))),
- binop(Iop_GetElem16x8,
- mkexpr(t2),
- unop(Iop_16to8,
- binop(Iop_GetElem16x8,
- mkexpr(t1),
- mkU8(i))))),
- mkU16(0x0)));
- }
+ switch (n) {
+ case 0:
+ assign(t1,
+ unop(Iop_32to16,
+ unop(Iop_64to32,
+ unop(Iop_V128to64,
+ getWReg(ws)))));
+ break;
- putWReg(wd,
- binop(Iop_64HLtoV128,
- binop(Iop_32HLto64,
- binop(Iop_16HLto32,
- mkexpr(tmp[7]),
- mkexpr(tmp[6])),
- binop(Iop_16HLto32,
- mkexpr(tmp[5]),
- mkexpr(tmp[4]))),
- binop(Iop_32HLto64,
- binop(Iop_16HLto32,
- mkexpr(tmp[3]),
- mkexpr(tmp[2])),
- binop(Iop_16HLto32,
- mkexpr(tmp[1]),
- mkexpr(tmp[0])))));
- break;
- }
+ case 1:
+ assign(t1,
+ unop(Iop_32HIto16,
+ unop(Iop_64to32,
+ unop(Iop_V128to64,
+ getWReg(ws)))));
+ break;
+
+ case 2:
+ assign(t1,
+ unop(Iop_32to16,
+ unop(Iop_64HIto32,
+ unop(Iop_V128to64,
+ getWReg(ws)))));
+ break;
+
+ case 3:
+ assign(t1,
+ unop(Iop_32HIto16,
+ unop(Iop_64HIto32,
+ unop(Iop_V128to64,
+ getWReg(ws)))));
+ break;
+
+ case 4:
+ assign(t1,
+ unop(Iop_32to16,
+ unop(Iop_64to32,
+ unop(Iop_V128HIto64,
+ getWReg(ws)))));
+ break;
+
+ case 5:
+ assign(t1,
+ unop(Iop_32HIto16,
+ unop(Iop_64to32,
+ unop(Iop_V128HIto64,
+ getWReg(ws)))));
+ break;
- case 0x02: { /* VSHF.W */
- DIP("VSHF.W w%d, w%d, w%d", wd, ws, wt);
- IRTemp tmp[4];
- Int i;
+ case 6:
+ assign(t1,
+ unop(Iop_32to16,
+ unop(Iop_64HIto32,
+ unop(Iop_V128HIto64,
+ getWReg(ws)))));
+ break;
- for (i = 0; i < 4; i++) {
- tmp[i] = newTemp(Ity_I32);
- assign(tmp[i],
- IRExpr_ITE(
- binop(Iop_CmpEQ32,
- binop(Iop_And32,
- binop(Iop_GetElem32x4,
- mkexpr(t1),
- mkU8(i)),
- mkU32(0xC0)),
- mkU32(0x0)),
- IRExpr_ITE(
- binop(Iop_CmpEQ32,
- binop(Iop_And32,
- binop(Iop_GetElem32x4,
- mkexpr(t1),
- mkU8(i)),
- mkU32(0x04)),
- mkU32(0x0)),
- binop(Iop_GetElem32x4,
- mkexpr(t3),
- unop(Iop_32to8,
- binop(Iop_GetElem32x4,
- mkexpr(t1),
- mkU8(i)))),
- binop(Iop_GetElem32x4,
- mkexpr(t2),
- unop(Iop_32to8,
- binop(Iop_GetElem32x4,
- mkexpr(t1),
- mkU8(i))))),
- mkU32(0x0)));
+ case 7:
+ assign(t1,
+ unop(Iop_32HIto16,
+ unop(Iop_64HIto32,
+ unop(Iop_V128HIto64,
+ getWReg(ws)))));
+ break;
}
- putWReg(wd,
- binop(Iop_64HLtoV128,
- binop(Iop_32HLto64,
- mkexpr(tmp[3]),
- mkexpr(tmp[2])),
- binop(Iop_32HLto64,
- mkexpr(tmp[1]),
- mkexpr(tmp[0]))));
+ putIReg(wd,
+ unop(mode64 ? Iop_16Uto64 : Iop_16Uto32,
+ mkexpr(t1)));
break;
- }
-
- case 0x03: { /* VSHF.D */
- DIP("VSHF.D w%d, w%d, w%d", wd, ws, wt);
- IRTemp tmp[2];
- Int i;
- for (i = 0; i < 2; i++) {
- tmp[i] = newTemp(Ity_I64);
- assign(tmp[i],
- IRExpr_ITE(
- binop(Iop_CmpEQ64,
- binop(Iop_And64,
- binop(Iop_GetElem64x2,
- mkexpr(t1),
- mkU8(i)),
- mkU64(0xC0)),
- mkU64(0x0)),
- IRExpr_ITE(
- binop(Iop_CmpEQ64,
- binop(Iop_And64,
- binop(Iop_GetElem64x2,
- mkexpr(t1),
- mkU8(i)),
- mkU64(0x02)),
- mkU64(0x0)),
- binop(Iop_GetElem64x2,
- mkexpr(t3),
- unop(Iop_64to8,
- binop(Iop_GetElem64x2,
- mkexpr(t1),
- mkU8(i)))),
- binop(Iop_GetElem64x2,
- mkexpr(t2),
- unop(Iop_64to8,
- binop(Iop_GetElem64x2,
- mkexpr(t1),
- mkU8(i))))),
- mkU64(0x0)));
- }
+ case 0x30: /* COPY_U.W */
+ DIP("COPY_U.W r%d, w%d[%d]", wd, ws, n);
- putWReg(wd,
- binop(Iop_64HLtoV128,
- mkexpr(tmp[1]), mkexpr(tmp[0])));
- break;
- }
+ switch (n) {
+ case 0:
+ putIReg(wd,
+ mkWidenFrom32(ty,
+ unop(Iop_V128to32,
+ getWReg(ws)),
+ False));
+ break;
- default:
- return -1;
- }
+ case 1:
+ t2 = newTemp(Ity_I64);
+ assign(t2,
+ unop(Iop_V128to64,
+ getWReg(ws)));
+ putIReg(wd,
+ mkWidenFrom32(ty,
+ unop(Iop_64HIto32,
+ mkexpr(t2)),
+ False));
+ break;
- break;
- }
+ case 2:
+ t2 = newTemp(Ity_I64);
+ assign(t2,
+ unop(Iop_V128HIto64,
+ getWReg(ws)));
+ putIReg(wd,
+ mkWidenFrom32(ty,
+ unop(Iop_64to32,
+ mkexpr(t2)),
+ False));
+ break;
- case 0x01: { /* SRAR.df */
- switch (df) {
- case 0x00: { /* SRAR.B */
- DIP("SRAR.B w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- t4 = newTemp(Ity_V128);
- assign(t1,
- binop(Iop_Sar8x16,
- getWReg(ws),
- getWReg(wt)));
- assign(t2,
- binop(Iop_Sub8x16,
- binop(Iop_64HLtoV128,
- mkU64(0x808080808080808ull),
- mkU64(0x808080808080808ull)),
- getWReg(wt)));
- assign(t4,
- unop(Iop_NotV128,
- binop(Iop_CmpEQ8x16,
- binop(Iop_ShlN8x16,
- getWReg(wt),
- mkU8(5)),
- binop(Iop_64HLtoV128,
- mkU64(0), mkU64(0)))));
- assign(t3,
- binop(Iop_ShrN8x16,
- binop(Iop_AndV128,
- binop(Iop_Shl8x16,
- getWReg(ws),
- mkexpr(t2)),
- mkexpr(t4)),
- mkU8(7)));
- putWReg(wd,
- binop(Iop_Add8x16,
- mkexpr(t1), mkexpr(t3)));
- break;
- }
+ case 3:
+ t2 = newTemp(Ity_I64);
+ assign(t2,
+ unop(Iop_V128HIto64,
+ getWReg(ws)));
+ putIReg(wd,
+ mkWidenFrom32(ty,
+ unop(Iop_64HIto32,
+ mkexpr(t2)),
+ False));
+ break;
- case 0x01: { /* SRAR.H */
- DIP("SRAR.H w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- t4 = newTemp(Ity_V128);
- assign(t1,
- binop(Iop_Sar16x8,
- getWReg(ws),
- getWReg(wt)));
- assign(t2,
- binop(Iop_Sub16x8,
- binop(Iop_64HLtoV128,
- mkU64(0x10001000100010ul),
- mkU64(0x10001000100010ul)),
- getWReg(wt)));
- assign(t4,
- unop(Iop_NotV128,
- binop(Iop_CmpEQ16x8,
- binop(Iop_ShlN16x8,
- getWReg(wt),
- mkU8(12)),
- binop(Iop_64HLtoV128,
- mkU64(0), mkU64(0)))));
- assign(t3,
- binop(Iop_ShrN16x8,
- binop(Iop_AndV128,
- binop(Iop_Shl16x8,
- getWReg(ws),
- mkexpr(t2)),
- mkexpr(t4)),
- mkU8(15)));
- putWReg(wd,
- binop(Iop_Add16x8,
- mkexpr(t1), mkexpr(t3)));
- break;
- }
+ default:
+ break;
+ }
- case 0x02: { /* SRAR.W */
- DIP("SRAR.W w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128); // shifted
- t2 = newTemp(Ity_V128); // 32 - wt
- t3 = newTemp(Ity_V128); // rv
- t4 = newTemp(Ity_V128); // wt % 32 == 0
- assign(t1,
- binop(Iop_Sar32x4,
- getWReg(ws),
- getWReg(wt)));
- assign(t2,
- binop(Iop_Sub32x4,
- binop(Iop_64HLtoV128,
- mkU64(0x2000000020ul),
- mkU64(0x2000000020ul)),
- getWReg(wt)));
- assign(t4,
- unop(Iop_NotV128,
- binop(Iop_CmpEQ32x4,
- binop(Iop_ShlN32x4,
- getWReg(wt),
- mkU8(27)),
- binop(Iop_64HLtoV128,
- mkU64(0), mkU64(0)))));
- assign(t3,
- binop(Iop_ShrN32x4,
- binop(Iop_AndV128,
- binop(Iop_Shl32x4,
- getWReg(ws),
- mkexpr(t2)),
- mkexpr(t4)),
- mkU8(31)));
- putWReg(wd,
- binop(Iop_Add32x4,
- mkexpr(t1), mkexpr(t3)));
break;
- }
- case 0x03: { /* SRAR.D */
- DIP("SRAR.D w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- t4 = newTemp(Ity_V128);
- assign(t1,
- binop(Iop_Sar64x2,
- getWReg(ws),
- getWReg(wt)));
- assign(t2,
- binop(Iop_Sub64x2,
- binop(Iop_64HLtoV128,
- mkU64(64ul), mkU64(64ul)),
- getWReg(wt)));
- assign(t4,
- unop(Iop_NotV128,
- binop(Iop_CmpEQ64x2,
- binop(Iop_ShlN64x2,
- getWReg(wt),
- mkU8(58)),
- binop(Iop_64HLtoV128,
- mkU64(0), mkU64(0)))));
- assign(t3,
- binop(Iop_ShrN64x2,
- binop(Iop_AndV128,
- binop(Iop_Shl64x2,
- getWReg(ws),
- mkexpr(t2)),
- mkexpr(t4)),
- mkU8(63)));
- putWReg(wd,
- binop(Iop_Add64x2,
- mkexpr(t1), mkexpr(t3)));
- break;
- }
+ default:
+ return -1;
+ }
- default:
- return -1;
+ break;
}
- break;
- }
-
- case 0x02: { /* SRLR.df */
- switch (df) {
- case 0x00: { /* SRLR.B */
- DIP("SRLR.B w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- t4 = newTemp(Ity_V128);
- assign(t1,
- binop(Iop_Shr8x16,
- getWReg(ws),
- getWReg(wt)));
- assign(t2,
- binop(Iop_Sub8x16,
- binop(Iop_64HLtoV128,
- mkU64(0x808080808080808ull),
- mkU64(0x808080808080808ull)),
- getWReg(wt)));
- assign(t4,
- unop(Iop_NotV128,
- binop(Iop_CmpEQ8x16,
- binop(Iop_ShlN8x16,
- getWReg(wt),
- mkU8(5)),
- binop(Iop_64HLtoV128,
- mkU64(0), mkU64(0)))));
- assign(t3,
- binop(Iop_ShrN8x16,
- binop(Iop_AndV128,
- binop(Iop_Shl8x16,
- getWReg(ws),
- mkexpr(t2)),
- mkexpr(t4)),
- mkU8(7)));
- putWReg(wd,
- binop(Iop_Add8x16,
- mkexpr(t1), mkexpr(t3)));
- break;
- }
-
- case 0x01: { /* SRLR.H */
- DIP("SRLR.H w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- t4 = newTemp(Ity_V128);
- assign(t1,
- binop(Iop_Shr16x8,
- getWReg(ws),
- getWReg(wt)));
- assign(t2,
- binop(Iop_Sub16x8,
- binop(Iop_64HLtoV128,
- mkU64(0x10001000100010ul),
- mkU64(0x10001000100010ul)),
- getWReg(wt)));
- assign(t4,
- unop(Iop_NotV128,
- binop(Iop_CmpEQ16x8,
- binop(Iop_ShlN16x8,
- getWReg(wt),
- mkU8(12)),
- binop(Iop_64HLtoV128,
- mkU64(0), mkU64(0)))));
- assign(t3,
- binop(Iop_ShrN16x8,
- binop(Iop_AndV128,
- binop(Iop_Shl16x8,
- getWReg(ws),
- mkexpr(t2)),
- mkexpr(t4)),
- mkU8(15)));
- putWReg(wd,
- binop(Iop_Add16x8,
- mkexpr(t1), mkexpr(t3)));
- break;
- }
+ case 0x04: { /* INSERT.df */
+ t5 = newTemp(Ity_I64);
+ UInt hi = 1;
+ ULong mask;
+ IRTemp *src, *dst;
+ assign(t5, mode64 ? getIReg(ws) :
+ unop(Iop_32Uto64, getIReg(ws)));
- case 0x02: { /* SRLR.W */
- DIP("SRLR.W w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- t4 = newTemp(Ity_V128);
- assign(t1,
- binop(Iop_Shr32x4,
- getWReg(ws),
- getWReg(wt)));
- assign(t2,
- binop(Iop_Sub32x4,
- binop(Iop_64HLtoV128,
- mkU64(0x2000000020ul),
- mkU64(0x2000000020ul)),
- getWReg(wt)));
- assign(t4,
- unop(Iop_NotV128,
- binop(Iop_CmpEQ32x4,
- binop(Iop_ShlN32x4,
- getWReg(wt),
- mkU8(27)),
- binop(Iop_64HLtoV128,
- mkU64(0), mkU64(0)))));
- assign(t3,
- binop(Iop_ShrN32x4,
- binop(Iop_AndV128,
- binop(Iop_Shl32x4,
- getWReg(ws),
- mkexpr(t2)),
- mkexpr(t4)),
- mkU8(31)));
- putWReg(wd,
- binop(Iop_Add32x4,
- mkexpr(t1), mkexpr(t3)));
- break;
- }
+ if (df == 0x38) { /* INSERT.D */
+ if (mode64) {
+ DIP("INSERT.D w%d[%d], r%d", wd, n, ws);
+
+ if (n == 0) {
+ putWReg(wd,
+ binop(Iop_64HLtoV128,
+ unop(Iop_V128HIto64,
+ getWReg(wd)),
+ mkexpr(t5)));
+ } else {
+ putWReg(wd,
+ binop(Iop_64HLtoV128,
+ mkexpr(t5),
+ unop(Iop_V128to64,
+ getWReg(wd))));
+ }
- case 0x03: { /* SRLR.D */
- DIP("SRLR.D w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- t4 = newTemp(Ity_V128);
- assign(t1,
- binop(Iop_Shr64x2,
- getWReg(ws),
- getWReg(wt)));
- assign(t2,
- binop(Iop_Sub64x2,
- binop(Iop_64HLtoV128,
- mkU64(64ul), mkU64(64ul)),
- getWReg(wt)));
- assign(t4,
- unop(Iop_NotV128,
- binop(Iop_CmpEQ64x2,
- binop(Iop_ShlN64x2,
- getWReg(wt),
- mkU8(58)),
- binop(Iop_64HLtoV128,
- mkU64(0), mkU64(0)))));
- assign(t3,
- binop(Iop_ShrN64x2,
- binop(Iop_AndV128,
- binop(Iop_Shl64x2,
- getWReg(ws),
- mkexpr(t2)),
- mkexpr(t4)),
- mkU8(63)));
- putWReg(wd,
- binop(Iop_Add64x2,
- mkexpr(t1), mkexpr(t3)));
break;
+ } else {
+ return -2;
}
+ } else {
+ t1 = newTemp(Ity_I64);
+ t2 = newTemp(Ity_I64);
+ assign(t1, unop(Iop_V128to64, getWReg(wd)));
+ assign(t2, unop(Iop_V128HIto64, getWReg(wd)));
+ }
- default:
- return -1;
- }
+ switch (df) {
+ case 0x00: /* INSERT.B */
+ DIP("INSERT.B w%d[%d], r%d", wd, n, ws);
- break;
- }
+ if (n >= 8) {
+ n -= 8;
+ } else {
+ hi = 0;
+ }
- case 0x04: { /* HADD_S.df */
- switch (df) {
- case 0x01: { /* HADD_S.H */
- DIP("HADD_S.H w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3,
- binop(Iop_Add16x8,
- binop(Iop_SarN16x8,
- mkexpr(t1), mkU8(8)),
- binop(Iop_SarN16x8,
- binop(Iop_ShlN16x8,
- mkexpr(t2), mkU8(8)),
- mkU8(8))));
- putWReg(wd, mkexpr(t3));
+ n <<= 3;
+ mask = 0xFFull;
break;
- }
- case 0x02: { /* HADD_S.W */
- DIP("HADD_S.W w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3,
- binop(Iop_Add32x4,
- binop(Iop_SarN32x4,
- mkexpr(t1), mkU8(16)),
- binop(Iop_SarN32x4,
- binop(Iop_ShlN32x4,
- mkexpr(t2), mkU8(16)),
- mkU8(16))));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ case 0x20: /* INSERT.H */
+ DIP("INSERT.H w%d[%d], r%d", wd, n, ws);
- case 0x03: { /* HADD_S.D */
- DIP("HADD_S.D w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3,
- binop(Iop_Add64x2,
- binop(Iop_SarN64x2,
- mkexpr(t1), mkU8(32)),
- binop(Iop_SarN64x2,
- binop(Iop_ShlN64x2,
- mkexpr(t2), mkU8(32)),
- mkU8(32))));
- putWReg(wd, mkexpr(t3));
+ if (n >= 4) {
+ n -= 4;
+ } else {
+ hi = 0;
+ }
+
+ n <<= 4;
+ mask = 0xFFFFull;
break;
- }
- default:
- return -1;
- }
+ case 0x30: /* INSERT.W */
+ DIP("INSERT.W w%d[%d], r%d", wd, n, ws);
- break;
- }
+ if (n >= 2) {
+ n -= 2;
+ } else {
+ hi = 0;
+ }
- case 0x05: { /* HADD_U.df */
- switch (df) {
- case 0x01: { /* HADD_U.H */
- DIP("HADD_U.H w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3,
- binop(Iop_Add16x8,
- binop(Iop_ShrN16x8,
- mkexpr(t1), mkU8(8)),
- binop(Iop_ShrN16x8,
- binop(Iop_ShlN16x8,
- mkexpr(t2), mkU8(8)),
- mkU8(8))));
- putWReg(wd, mkexpr(t3));
+ n <<= 5;
+ mask = 0xFFFFFFFFull;
break;
- }
- case 0x02: { /* HADD_U.W */
- DIP("HADD_U.W w%d, w%d, w%d", wd, ws, wt);
+ default:
+ return -1;
+ }
+
+ if (hi) {
+ t4 = newTemp(Ity_I64);
+ src = &t2;
+ dst = &t4;
+ t3 = t1;
+ } else {
+ t3 = newTemp(Ity_I64);
+ src = &t1;
+ dst = &t3;
+ t4 = t2;
+ }
+
+ mask <<= n;
+ assign(*dst,
+ binop(Iop_Or64,
+ binop(Iop_And64, mkexpr(*src), mkU64(~mask)),
+ binop(Iop_And64,
+ binop(Iop_Shl64, mkexpr(t5), mkU8(n)),
+ mkU64(mask))));
+ putWReg(wd,
+ binop(Iop_64HLtoV128, mkexpr(t4), mkexpr(t3)));
+ break;
+ }
+
+ case 0x05: { /* INSVE.df */
+ switch (df) {
+ case 0x00: { /* INSVE.B */
+ DIP("INSVE.B w%d[%d], w%d[0]", wd, n, ws);
t1 = newTemp(Ity_V128);
t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3,
- binop(Iop_Add32x4,
- binop(Iop_ShrN32x4,
- mkexpr(t1), mkU8(16)),
- binop(Iop_ShrN32x4,
- binop(Iop_ShlN32x4,
- mkexpr(t2), mkU8(16)),
- mkU8(16))));
- putWReg(wd, mkexpr(t3));
+ assign(t1, getWReg(wd));
+ assign(t2, getWReg(ws));
+ Int i;
+ IRTemp tmp[16];
+
+ for (i = 0; i < 16; i++) {
+ tmp[i] = newTemp(Ity_I8);
+
+ if (n == i)
+ assign(tmp[i],
+ binop(Iop_GetElem8x16,
+ mkexpr(t2), mkU8(0x0)));
+ else
+ assign(tmp[i],
+ binop(Iop_GetElem8x16,
+ mkexpr(t1), mkU8(i)));
+ }
+
+ putWReg(wd,
+ binop(Iop_64HLtoV128,
+ binop(Iop_32HLto64,
+ binop(Iop_16HLto32,
+ binop(Iop_8HLto16,
+ mkexpr(tmp[15]),
+ mkexpr(tmp[14])),
+ binop(Iop_8HLto16,
+ mkexpr(tmp[13]),
+ mkexpr(tmp[12]))),
+ binop(Iop_16HLto32,
+ binop(Iop_8HLto16,
+ mkexpr(tmp[11]),
+ mkexpr(tmp[10])),
+ binop(Iop_8HLto16,
+ mkexpr(tmp[9]),
+ mkexpr(tmp[8])))),
+ binop(Iop_32HLto64,
+ binop(Iop_16HLto32,
+ binop(Iop_8HLto16,
+ mkexpr(tmp[7]),
+ mkexpr(tmp[6])),
+ binop(Iop_8HLto16,
+ mkexpr(tmp[5]),
+ mkexpr(tmp[4]))),
+ binop(Iop_16HLto32,
+ binop(Iop_8HLto16,
+ mkexpr(tmp[3]),
+ mkexpr(tmp[2])),
+ binop(Iop_8HLto16,
+ mkexpr(tmp[1]),
+ mkexpr(tmp[0]))))));
break;
}
- case 0x03: { /* HADD_U.D */
- DIP("HADD_U.D w%d, w%d, w%d", wd, ws, wt);
+ case 0x20: { /* INSVE.H */
+ DIP("INSVE.H w%d[%d], r%d[0]", wd, n, ws);
t1 = newTemp(Ity_V128);
t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3,
- binop(Iop_Add64x2,
- binop(Iop_ShrN64x2,
- mkexpr(t1), mkU8(32)),
- binop(Iop_ShrN64x2,
- binop(Iop_ShlN64x2,
- mkexpr(t2), mkU8(32)),
- mkU8(32))));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ assign(t1, getWReg(wd));
+ assign(t2, getWReg(ws));
+ Int i;
+ IRTemp tmp[8];
- default:
- return -1;
- }
+ for (i = 0; i < 8; i++) {
+ tmp[i] = newTemp(Ity_I16);
- break;
- }
+ if (n == i)
+ assign(tmp[i],
+ binop(Iop_GetElem16x8,
+ mkexpr(t2), mkU8(0x0)));
+ else
+ assign(tmp[i],
+ binop(Iop_GetElem16x8,
+ mkexpr(t1), mkU8(i)));
+ }
- case 0x06: { /* HSUB_S.df */
- switch (df) {
- case 0x01: { /* HSUB_S.H */
- DIP("HSUB_S.H w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3,
- binop(Iop_Sub16x8,
- binop(Iop_SarN16x8,
- mkexpr(t1), mkU8(8)),
- binop(Iop_SarN16x8,
- binop(Iop_ShlN16x8,
- mkexpr(t2), mkU8(8)),
- mkU8(8))));
- putWReg(wd, mkexpr(t3));
+ putWReg(wd,
+ binop(Iop_64HLtoV128,
+ binop(Iop_32HLto64,
+ binop(Iop_16HLto32,
+ mkexpr(tmp[7]),
+ mkexpr(tmp[6])),
+ binop(Iop_16HLto32,
+ mkexpr(tmp[5]),
+ mkexpr(tmp[4]))),
+ binop(Iop_32HLto64,
+ binop(Iop_16HLto32,
+ mkexpr(tmp[3]),
+ mkexpr(tmp[2])),
+ binop(Iop_16HLto32,
+ mkexpr(tmp[1]),
+ mkexpr(tmp[0])))));
break;
}
- case 0x02: { /* HSUB_S.W */
- DIP("HSUB_S.W w%d, w%d, w%d", wd, ws, wt);
+ case 0x30: { /* INSVE.W */
+ DIP("INSVE.W w%d[%d], r%d[0]", wd, n, ws);
t1 = newTemp(Ity_V128);
t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3,
- binop(Iop_Sub32x4,
- binop(Iop_SarN32x4,
- mkexpr(t1), mkU8(16)),
- binop(Iop_SarN32x4,
- binop(Iop_ShlN32x4,
- mkexpr(t2), mkU8(16)),
- mkU8(16))));
- putWReg(wd, mkexpr(t3));
+ assign(t1, getWReg(wd));
+ assign(t2, getWReg(ws));
+ Int i;
+ IRTemp tmp[4];
+
+ for (i = 0; i < 4; i++) {
+ tmp[i] = newTemp(Ity_I32);
+
+ if (n == i)
+ assign(tmp[i],
+ binop(Iop_GetElem32x4,
+ mkexpr(t2), mkU8(0x0)));
+ else
+ assign(tmp[i],
+ binop(Iop_GetElem32x4,
+ mkexpr(t1), mkU8(i)));
+ }
+
+ putWReg(wd,
+ binop(Iop_64HLtoV128,
+ binop(Iop_32HLto64,
+ mkexpr(tmp[3]),
+ mkexpr(tmp[2])),
+ binop(Iop_32HLto64,
+ mkexpr(tmp[1]),
+ mkexpr(tmp[0]))));
break;
}
- case 0x03: { /* HSUB_S.D */
- DIP("HSUB_S.D w%d, w%d, w%d", wd, ws, wt);
+ case 0x38: { /* INSVE.D */
+ DIP("INSVE.D w%d[%d], r%d[0]", wd, n, ws);
t1 = newTemp(Ity_V128);
t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3,
- binop(Iop_Sub64x2,
- binop(Iop_SarN64x2,
- mkexpr(t1), mkU8(32)),
- binop(Iop_SarN64x2,
- binop(Iop_ShlN64x2,
- mkexpr(t2), mkU8(32)),
- mkU8(32))));
- putWReg(wd, mkexpr(t3));
+ assign(t1, getWReg(wd));
+ assign(t2, getWReg(ws));
+ Int i;
+ IRTemp tmp[2];
+
+ for (i = 0; i < 2; i++) {
+ tmp[i] = newTemp(Ity_I64);
+
+ if (n == i)
+ assign(tmp[i],
+ binop(Iop_GetElem64x2,
+ mkexpr(t2), mkU8(0x0)));
+ else
+ assign(tmp[i],
+ binop(Iop_GetElem64x2,
+ mkexpr(t1), mkU8(i)));
+ }
+
+ putWReg(wd,
+ binop(Iop_64HLtoV128,
+ mkexpr(tmp[1]), mkexpr(tmp[0])));
break;
}
+ }
- default:
- return -1;
+ break;
}
- break;
+ default:
+ return -1;
}
+ }
- case 0x07: { /* HSUB_U.df */
- switch (df) {
- case 0x01: { /* HSUB_U.H */
- DIP("HSUB_U.H w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3,
- binop(Iop_Sub16x8,
- binop(Iop_ShrN16x8,
- mkexpr(t1), mkU8(8)),
- binop(Iop_ShrN16x8,
- binop(Iop_ShlN16x8,
- mkexpr(t2), mkU8(8)),
- mkU8(8))));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ return 0;
+}
+
+static Int msa_VEC(UInt cins, UChar wd, UChar ws) /* VEC */
+{
+ IRTemp t1, t2, t3;
+ UShort operation;
+ UChar wt;
+
+ vassert((cins & 0x03000000) == 0);
+
+ operation = (cins & 0x03E00000) >> 21;
+ wt = (cins & 0x001F0000) >> 16;
+
+ switch (operation) {
+ case 0x00: { /* AND.V */
+ DIP("AND.V w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3, binop(Iop_AndV128, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- case 0x02: { /* HSUB_U.W */
- DIP("HSUB_U.W w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3,
- binop(Iop_Sub32x4,
- binop(Iop_ShrN32x4,
- mkexpr(t1), mkU8(16)),
- binop(Iop_ShrN32x4,
- binop(Iop_ShlN32x4,
- mkexpr(t2), mkU8(16)),
- mkU8(16))));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ case 0x01: { /* OR.V */
+ DIP("OR.V w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3, binop(Iop_OrV128, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- case 0x03: { /* HSUB_U.D */
- DIP("HSUB_U.D w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3,
- binop(Iop_Sub64x2,
- binop(Iop_ShrN64x2,
- mkexpr(t1), mkU8(32)),
- binop(Iop_ShrN64x2,
- binop(Iop_ShlN64x2,
- mkexpr(t2), mkU8(32)),
- mkU8(32))));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ case 0x02: { /* NOR.V */
+ DIP("NOR.V w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3,
+ unop(Iop_NotV128,
+ binop(Iop_OrV128, mkexpr(t1), mkexpr(t2))));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- default:
- return -1;
- }
+ case 0x03: { /* XOR.V */
+ DIP("XOR.V w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ assign(t2, getWReg(wt));
+ assign(t3, binop(Iop_XorV128, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
- break;
- }
+ case 0x04: { /* BMNZ (ws AND wt) OR (wd AND NOT wt) */
+ DIP("BMNZ.V w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1,
+ binop(Iop_AndV128,
+ getWReg(ws), getWReg(wt)));
+ assign(t2,
+ binop(Iop_AndV128,
+ getWReg(wd),
+ unop(Iop_NotV128, getWReg(wt))));
+ assign(t3, binop(Iop_OrV128, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
+
+ case 0x05: { /* BMZ.V (ws AND NOT wt) OR (wd AND wt) */
+ DIP("BMZ.V w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1,
+ binop(Iop_AndV128,
+ getWReg(wd), getWReg(wt)));
+ assign(t2,
+ binop(Iop_AndV128,
+ getWReg(ws),
+ unop(Iop_NotV128, getWReg(wt))));
+ assign(t3, binop(Iop_OrV128, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
+
+ case 0x06: { /* BSEL (ws AND NOT wd) OR (wt AND wd) */
+ DIP("BSEL.V w%d, w%d, w%d", wd, ws, wt);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1,
+ binop(Iop_AndV128,
+ getWReg(wd), getWReg(wt)));
+ assign(t2,
+ binop(Iop_AndV128,
+ getWReg(ws),
+ unop(Iop_NotV128, getWReg(wd))));
+ assign(t3, binop(Iop_OrV128, mkexpr(t1), mkexpr(t2)));
+ putWReg(wd, mkexpr(t3));
+ break;
+ }
default:
return -1;
return 0;
}
-static Int msa_3R_1A(UInt cins, UChar wd, UChar ws) { /* 3R (0x1A) */
+static Int msa_2R(UInt cins, UChar wd, UChar ws) /* 2R */
+{
+ IRTemp t1, t2, t3, t4;
+ IRType ty;
UShort operation;
- UChar df, wt;
+ UChar df;
- operation = (cins & 0x03C00000) >> 22;
- df = (cins & 0x00200000) >> 21;
- wt = (cins & 0x001F0000) >> 16;
+ vassert((cins & 0x00200000) == 0);
+
+ operation = (cins & 0x03FC0000) >> 18;
+ df = (cins & 0x00030000) >> 16;
+ ty = mode64 ? Ity_I64 : Ity_I32;
switch (operation) {
- case 0x00: { /* FCAF.df */
- switch (df) {
- case 0x00: { /* FCAF.W */
- DIP("FCAF.W w%d, w%d, w%d", wd, ws, wt);
- calculateMSACSR(ws, wt, FCAFW, 2);
- putWReg(wd, binop(Iop_64HLtoV128, mkU64(0ul), mkU64(0ul)));
- break;
- }
+ case 0xC0: { /* FILL.df */
+ t1 = newTemp(Ity_I64);
- case 0x01: { /* FCAF.D */
- DIP("FCAF.D w%d, w%d, w%d", wd, ws, wt);
- calculateMSACSR(ws, wt, FCAFD, 2);
- putWReg(wd, binop(Iop_64HLtoV128, mkU64(0ul), mkU64(0ul)));
- break;
- }
+ switch (df) {
+ case 0x00: /* FILL.B */
+ DIP("FILL.B w%d, r%d", wd, ws);
+ t2 = newTemp(Ity_I32);
+ t3 = newTemp(Ity_I16);
+ t4 = newTemp(Ity_I8);
+ assign(t4, mkNarrowTo8(ty, getIReg(ws)));
+ assign(t3,
+ binop(Iop_8HLto16, mkexpr(t4), mkexpr(t4)));
+ assign(t2,
+ binop(Iop_16HLto32, mkexpr(t3), mkexpr(t3)));
+ assign(t1,
+ binop(Iop_32HLto64, mkexpr(t2), mkexpr(t2)));
+ break;
- default:
- return -1;
- }
+ case 0x01: /* FILL.H */
+ DIP("FILL.H w%d, r%d", wd, ws);
+ t2 = newTemp(Ity_I32);
+ t3 = newTemp(Ity_I16);
+ assign(t3, mkNarrowTo16(ty, getIReg(ws)));
+ assign(t2,
+ binop(Iop_16HLto32, mkexpr(t3), mkexpr(t3)));
+ assign(t1,
+ binop(Iop_32HLto64, mkexpr(t2), mkexpr(t2)));
+ break;
- break;
+ case 0x02: /* FILL.W */
+ DIP("FILL.W w%d, r%d", wd, ws);
+ t2 = newTemp(Ity_I32);
+ assign(t2, mkNarrowTo32(ty, getIReg(ws)));
+ assign(t1,
+ binop(Iop_32HLto64, mkexpr(t2), mkexpr(t2)));
+ break;
+
+ case 0x03: /* FILL.D */
+ if (mode64) {
+ DIP("FILL.W w%d, r%d", wd, ws);
+ t2 = newTemp(Ity_I32);
+ assign(t1, getIReg(ws));
+ } else {
+ return -2;
+ }
+
+ break;
+
+ default:
+ return -1;
}
- case 0x01: { /* FCUN.df */
- switch (df) {
- case 0x00: { /* FCUN.W */
- DIP("FCUN.W w%d, w%d, w%d", wd, ws, wt);
- calculateMSACSR(ws, wt, FCUNW, 2);
- putWReg(wd, binop(Iop_CmpUN32Fx4,
- getWReg(ws),
- getWReg(wt)));
- break;
- }
+ putWReg(wd,
+ binop(Iop_64HLtoV128, mkexpr(t1), mkexpr(t1)));
+ break;
+ }
- case 0x01: { /* FCUN.D */
- DIP("FCUN.D w%d, w%d, w%d", wd, ws, wt);
- calculateMSACSR(ws, wt, FCUND, 2);
- putWReg(wd, binop(Iop_CmpUN64Fx2,
- getWReg(ws),
- getWReg(wt)));
- break;
- }
+ case 0xC1: { /* PCNT.df */
+ switch (df) {
+ case 0x00: /* PCNT.B */
+ DIP("PCNT.B w%d, r%d", wd, ws);
+ putWReg(wd,
+ unop(Iop_Cnt8x16, getWReg(ws)));
+ break;
- default:
- return -1;
- }
+ case 0x01: /* PCNT.H */
+ DIP("PCNT.H w%d, r%d", wd, ws);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ assign(t1, unop(Iop_Cnt8x16, getWReg(ws)));
+ assign(t2,
+ binop(Iop_Add16x8,
+ binop(Iop_AndV128,
+ mkexpr(t1),
+ binop(Iop_64HLtoV128,
+ mkU64(0x00FF00FF00FF00FFULL),
+ mkU64(0x00FF00FF00FF00FFULL))),
+ binop(Iop_AndV128,
+ binop(Iop_ShrN16x8,
+ mkexpr(t1), mkU8(8)),
+ binop(Iop_64HLtoV128,
+ mkU64(0x00FF00FF00FF00FFULL),
+ mkU64(0x00FF00FF00FF00FFULL)))));
+ putWReg(wd, mkexpr(t2));
+ break;
- break;
+ case 0x02: /* PCNT.W */
+ DIP("PCNT.W w%d, r%d", wd, ws);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, unop(Iop_Cnt8x16, getWReg(ws)));
+ assign(t2,
+ binop(Iop_Add32x4,
+ binop(Iop_AndV128,
+ mkexpr(t1),
+ binop(Iop_64HLtoV128,
+ mkU64(0x00FF00FF00FF00FFULL),
+ mkU64(0x00FF00FF00FF00FFULL))),
+ binop(Iop_AndV128,
+ binop(Iop_ShrN32x4,
+ mkexpr(t1), mkU8(8)),
+ binop(Iop_64HLtoV128,
+ mkU64(0x00FF00FF00FF00FFULL),
+ mkU64(0x00FF00FF00FF00FFULL)))));
+ assign(t3,
+ binop(Iop_Add32x4,
+ binop(Iop_AndV128,
+ mkexpr(t2),
+ binop(Iop_64HLtoV128,
+ mkU64(0x0000FFFF0000FFFFULL),
+ mkU64(0x0000FFFF0000FFFFULL))),
+ binop(Iop_AndV128,
+ binop(Iop_ShrN32x4,
+ mkexpr(t2), mkU8(16)),
+ binop(Iop_64HLtoV128,
+ mkU64(0x0000FFFF0000FFFFULL),
+ mkU64(0x0000FFFF0000FFFFULL)))));
+ putWReg(wd, mkexpr(t3));
+ break;
+
+ case 0x03: /* PCNT.D */
+ DIP("PCNT.D w%d, r%d", wd, ws);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ t4 = newTemp(Ity_V128);;
+ assign(t1, unop(Iop_Cnt8x16, getWReg(ws)));
+ assign(t2,
+ binop(Iop_Add64x2,
+ binop(Iop_AndV128,
+ mkexpr(t1),
+ binop(Iop_64HLtoV128,
+ mkU64(0x00FF00FF00FF00FFULL),
+ mkU64(0x00FF00FF00FF00FFULL))),
+ binop(Iop_AndV128,
+ binop(Iop_ShrN64x2,
+ mkexpr(t1), mkU8(8)),
+ binop(Iop_64HLtoV128,
+ mkU64(0x00FF00FF00FF00FFULL),
+ mkU64(0x00FF00FF00FF00FFULL)))));
+ assign(t3,
+ binop(Iop_Add64x2,
+ binop(Iop_AndV128,
+ mkexpr(t2),
+ binop(Iop_64HLtoV128,
+ mkU64(0x0000FFFF0000FFFFULL),
+ mkU64(0x0000FFFF0000FFFFULL))),
+ binop(Iop_AndV128,
+ binop(Iop_ShrN64x2,
+ mkexpr(t2), mkU8(16)),
+ binop(Iop_64HLtoV128,
+ mkU64(0x0000FFFF0000FFFFULL),
+ mkU64(0x0000FFFF0000FFFFULL)))));
+ assign(t4,
+ binop(Iop_Add64x2,
+ binop(Iop_AndV128,
+ mkexpr(t3),
+ binop(Iop_64HLtoV128,
+ mkU64(0x00000000FFFFFFFFULL),
+ mkU64(0x00000000FFFFFFFFULL))),
+ binop(Iop_AndV128,
+ binop(Iop_ShrN64x2,
+ mkexpr(t3), mkU8(32)),
+ binop(Iop_64HLtoV128,
+ mkU64(0x00000000FFFFFFFFULL),
+ mkU64(0x00000000FFFFFFFFULL)))));
+ putWReg(wd, mkexpr(t4));
+ break;
+
+ default:
+ return -1;
}
- case 0x02: { /* FCEQ.df */
- switch (df) {
- case 0x00: { /* FCEQ.W */
- DIP("FCEQ.W w%d, w%d, w%d", wd, ws, wt);
- calculateMSACSR(ws, wt, FCEQW, 2);
- putWReg(wd, binop(Iop_CmpEQ32Fx4,
- getWReg(ws),
- getWReg(wt)));
- break;
- }
+ break;
+ }
- case 0x01: { /* FCEQ.D */
- DIP("FCEQ.D w%d, w%d, w%d", wd, ws, wt);
- calculateMSACSR(ws, wt, FCEQD, 2);
- putWReg(wd, binop(Iop_CmpEQ64Fx2,
- getWReg(ws),
- getWReg(wt)));
- break;
- }
+ case 0xC2: { /* NLOC.df */
+ switch (df) {
+ case 0x00: /* NLOC.B */
+ DIP("NLOC.B w%d, w%d", wd, ws);
+ putWReg(wd,
+ unop(Iop_Cls8x16, getWReg(ws)));
+ break;
- default:
- return -1;
- }
+ case 0x01: /* NLOC.H */
+ DIP("NLOC.H w%d, w%d", wd, ws);
+ putWReg(wd,
+ unop(Iop_Cls16x8, getWReg(ws)));
+ break;
- break;
+ case 0x02: /* NLOC.W */
+ DIP("NLOC.W w%d, w%d", wd, ws);
+ putWReg(wd,
+ unop(Iop_Cls32x4, getWReg(ws)));
+ break;
+
+ case 0x03: /* NLOC.D */
+ DIP("NLOC.D w%d, w%d", wd, ws);
+ t1 = newTemp(Ity_V128);
+ assign(t1, unop(Iop_NotV128, getWReg(ws)));
+ putWReg(wd, unop(Iop_Clz64x2, mkexpr(t1)));
+ break;
+
+ default:
+ return -1;
}
- case 0x03: { /* FCUEQ.df */
- switch (df) {
- case 0x00: { /* FCUEQ.W */
- DIP("FCUEQ.W w%d, w%d, w%d", wd, ws, wt);
- calculateMSACSR(ws, wt, FCUEQW, 2);
- putWReg(wd,
- binop(Iop_OrV128,
- binop(Iop_CmpEQ32Fx4,
- getWReg(ws),
- getWReg(wt)),
- binop(Iop_CmpUN32Fx4,
- getWReg(ws),
- getWReg(wt))));
- break;
- }
+ break;
+ }
- case 0x01: { /* FCUEQ.D */
- DIP("FCUEQ.D w%d, w%d, w%d", wd, ws, wt);
- calculateMSACSR(ws, wt, FCUEQD, 2);
- putWReg(wd,
- binop(Iop_OrV128,
- binop(Iop_CmpEQ64Fx2,
- getWReg(ws),
- getWReg(wt)),
- binop(Iop_CmpUN64Fx2,
- getWReg(ws),
- getWReg(wt))));
- break;
- }
+ case 0xC3: { /* NLZC.df */
+ switch (df) {
+ case 0x00: /* NLZC.B */
+ DIP("NLZC.W w%d, w%d", wd, ws);
+ putWReg(wd,
+ unop(Iop_Clz8x16, getWReg(ws)));
+ break;
- default:
- return -1;
+ case 0x01: /* NLZC.H */
+ DIP("NLZC.H w%d, w%d", wd, ws);
+ putWReg(wd,
+ unop(Iop_Clz16x8, getWReg(ws)));
+ break;
+
+ case 0x02: /* NLZC.W */
+ DIP("NLZC.W w%d, w%d", wd, ws);
+ putWReg(wd,
+ unop(Iop_Clz32x4, getWReg(ws)));
+ break;
+
+ case 0x03: {/* NLZC.D */
+ putWReg(wd,
+ unop(Iop_Clz64x2, getWReg(ws)));
+ break;
}
- break;
+ default:
+ return -1;
}
- case 0x04: { /* FCLT.df */
- switch (df) {
- case 0x00: { /* FCLT.W */
- DIP("FCLT.W w%d, w%d, w%d", wd, ws, wt);
- calculateMSACSR(ws, wt, FCLTW, 2);
- putWReg(wd,
- binop(Iop_CmpLT32Fx4,
- getWReg(ws),
- getWReg(wt)));
- break;
- }
+ break;
+ }
- case 0x01: { /* FCLT.D */
- DIP("FCLT.D w%d, w%d, w%d", wd, ws, wt);
- calculateMSACSR(ws, wt, FCLTD, 2);
- putWReg(wd,
- binop(Iop_CmpLT64Fx2,
- getWReg(ws),
- getWReg(wt)));
- break;
- }
+ default:
+ return -1;
+ }
+
+ return 0;
+}
+
+static Int msa_2RF(UInt cins, UChar wd, UChar ws) /* 2RF */
+{
+ IRTemp t1, t2, t3, t4, t5;
+ UShort operation;
+ UChar df, wt;
- default:
- return -1;
- }
+ operation = (cins & 0x03FE0000) >> 17;
+ df = (cins & 0x00010000) >> 16;
+ wt = (cins & 0x001F0000) >> 16;
- break;
- }
+ switch (operation) {
- case 0x05: { /* FCULT.df */
- switch (df) {
- case 0x00: { /* FCULT.W */
- DIP("FCULT.W w%d, w%d, w%d", wd, ws, wt);
- calculateMSACSR(ws, wt, FCULTW, 2);
- putWReg(wd,
- binop(Iop_OrV128,
- binop(Iop_CmpLT32Fx4,
- getWReg(ws),
- getWReg(wt)),
- binop(Iop_CmpUN32Fx4,
- getWReg(ws),
- getWReg(wt))));
- break;
- }
+ case 0x190: { /* FCLASS.df */
+ IRTemp t0 = newTemp(Ity_V128);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ t4 = newTemp(Ity_V128);
+ t5 = newTemp(Ity_V128);
- case 0x01: { /* FCULT.D */
- DIP("FCULT.D w%d, w%d, w%d", wd, ws, wt);
- calculateMSACSR(ws, wt, FCULTD, 2);
- putWReg(wd,
- binop(Iop_OrV128,
- binop(Iop_CmpLT64Fx2,
- getWReg(ws),
- getWReg(wt)),
- binop(Iop_CmpUN64Fx2,
- getWReg(ws),
- getWReg(wt))));
- break;
- }
+ switch (df) {
+ case 0x00: { /* FCLASS.W */
+ DIP("FCLASS.W w%d, w%d", wd, ws);
+ assign(t0,
+ binop(Iop_CmpEQ32x4,
+ binop(Iop_AndV128,
+ getWReg(ws),
+ binop(Iop_64HLtoV128,
+ mkU64(0x7F8000007F800000ull),
+ mkU64(0x7F8000007F800000ull))),
+ binop(Iop_64HLtoV128,
+ mkU64(0ull), mkU64(0ull))));
+ assign(t1,
+ binop(Iop_CmpEQ32x4,
+ binop(Iop_AndV128,
+ getWReg(ws),
+ binop(Iop_64HLtoV128,
+ mkU64(0x7F8000007F800000ull),
+ mkU64(0x7F8000007F800000ull))),
+ binop(Iop_64HLtoV128,
+ mkU64(0x7F8000007F800000ull),
+ mkU64(0x7F8000007F800000ull))));
+ assign(t2,
+ binop(Iop_SarN32x4,
+ getWReg(ws), mkU8(31)));
+ assign(t3,
+ binop(Iop_CmpEQ32x4,
+ binop(Iop_AndV128,
+ getWReg(ws),
+ binop(Iop_64HLtoV128,
+ mkU64(0x0040000000400000ull),
+ mkU64(0x0040000000400000ull))),
+ binop(Iop_64HLtoV128,
+ mkU64(0x0040000000400000ull),
+ mkU64(0x0040000000400000ull))));
+ assign(t4,
+ binop(Iop_CmpEQ32x4,
+ binop(Iop_AndV128,
+ getWReg(ws),
+ binop(Iop_64HLtoV128,
+ mkU64(0x007FFFFF007FFFFFULL),
+ mkU64(0x007FFFFF007FFFFFULL))),
+ binop(Iop_64HLtoV128,
+ mkU64(0ull), mkU64(0ull))));
+ assign(t5,
+ binop(Iop_Shl32x4,
+ binop(Iop_OrV128,
+ binop(Iop_AndV128,
+ mkexpr(t1),
+ binop(Iop_AndV128,
+ mkexpr(t4),
+ binop(Iop_64HLtoV128,
+ mkU64(0x100000001ull),
+ mkU64(0x100000001ull)))),
+ binop(Iop_OrV128,
+ binop(Iop_AndV128,
+ mkexpr(t0),
+ binop(Iop_OrV128,
+ binop(Iop_AndV128,
+ mkexpr(t4),
+ binop(Iop_64HLtoV128,
+ mkU64(0x800000008ull),
+ mkU64(0x800000008ull))),
+ binop(Iop_AndV128,
+ unop(Iop_NotV128,
+ mkexpr(t4)),
+ binop(Iop_64HLtoV128,
+ mkU64(0x400000004ull),
+ mkU64(0x400000004ull))))),
+ binop(Iop_AndV128,
+ unop(Iop_NotV128,
+ mkexpr(t1)),
+ binop(Iop_AndV128,
+ unop(Iop_NotV128,
+ mkexpr(t0)),
+ binop(Iop_64HLtoV128,
+ mkU64(0x200000002ull),
+ mkU64(0x200000002ull)))))),
+ binop(Iop_OrV128,
+ binop(Iop_AndV128,
+ mkexpr(t2),
+ binop(Iop_64HLtoV128,
+ mkU64(0x200000002ull),
+ mkU64(0x200000002ull))),
+ binop(Iop_AndV128,
+ unop(Iop_NotV128,
+ mkexpr(t2)),
+ binop(Iop_64HLtoV128,
+ mkU64(0x600000006ull),
+ mkU64(0x600000006ull))))));
+ putWReg(wd,
+ binop(Iop_OrV128,
+ mkexpr(t5),
+ binop(Iop_AndV128,
+ binop(Iop_CmpEQ32x4,
+ mkexpr(t5),
+ binop(Iop_64HLtoV128,
+ mkU64(0ull),
+ mkU64(0ull))),
+ binop(Iop_OrV128,
+ binop(Iop_AndV128,
+ mkexpr(t3),
+ binop(Iop_64HLtoV128,
+ mkU64(0x100000001ull),
+ mkU64(0x100000001ull))),
+ binop(Iop_AndV128,
+ unop(Iop_NotV128, mkexpr(t3)),
+ binop(Iop_64HLtoV128,
+ mkU64(0x200000002ull),
+ mkU64(0x200000002ull)))))));
+ break;
+ }
- default:
- return -1;
+ case 0x01: { /* FCLASS.D */
+ DIP("FCLASS.D w%d, w%d", wd, ws);
+ assign(t0,
+ binop(Iop_CmpEQ64x2,
+ binop(Iop_AndV128,
+ getWReg(ws),
+ binop(Iop_64HLtoV128,
+ mkU64(0x7FF0000000000000ull),
+ mkU64(0x7FF0000000000000ull))),
+ binop(Iop_64HLtoV128,
+ mkU64(0ull), mkU64(0ull))));
+ assign(t1,
+ binop(Iop_CmpEQ64x2,
+ binop(Iop_AndV128,
+ getWReg(ws),
+ binop(Iop_64HLtoV128,
+ mkU64(0x7FF0000000000000ull),
+ mkU64(0x7FF0000000000000ull))),
+ binop(Iop_64HLtoV128,
+ mkU64(0x7FF0000000000000ull),
+ mkU64(0x7FF0000000000000ull))));
+ assign(t2,
+ binop(Iop_SarN64x2,
+ getWReg(ws), mkU8(63)));
+ assign(t3,
+ binop(Iop_CmpEQ64x2,
+ binop(Iop_AndV128,
+ getWReg(ws),
+ binop(Iop_64HLtoV128,
+ mkU64(0x0008000000000000ull),
+ mkU64(0x0008000000000000ull))),
+ binop(Iop_64HLtoV128,
+ mkU64(0x0008000000000000ull),
+ mkU64(0x0008000000000000ull))));
+ assign(t4,
+ binop(Iop_CmpEQ64x2,
+ binop(Iop_AndV128,
+ getWReg(ws),
+ binop(Iop_64HLtoV128,
+ mkU64(0x000FFFFFFFFFFFFFULL),
+ mkU64(0x000FFFFFFFFFFFFFULL))),
+ binop(Iop_64HLtoV128,
+ mkU64(0ull), mkU64(0ull))));
+ assign(t5,
+ binop(Iop_Shl64x2,
+ binop(Iop_OrV128,
+ binop(Iop_AndV128,
+ mkexpr(t1),
+ binop(Iop_AndV128,
+ mkexpr(t4),
+ binop(Iop_64HLtoV128,
+ mkU64(1ull),
+ mkU64(1ull)))),
+ binop(Iop_OrV128,
+ binop(Iop_AndV128,
+ mkexpr(t0),
+ binop(Iop_OrV128,
+ binop(Iop_AndV128,
+ mkexpr(t4),
+ binop(Iop_64HLtoV128,
+ mkU64(8ull),
+ mkU64(8ull))),
+ binop(Iop_AndV128,
+ unop(Iop_NotV128,
+ mkexpr(t4)),
+ binop(Iop_64HLtoV128,
+ mkU64(4ull),
+ mkU64(4ull))))),
+ binop(Iop_AndV128,
+ unop(Iop_NotV128,
+ mkexpr(t1)),
+ binop(Iop_AndV128,
+ unop(Iop_NotV128,
+ mkexpr(t0)),
+ binop(Iop_64HLtoV128,
+ mkU64(2ull),
+ mkU64(2ull)))))),
+ binop(Iop_OrV128,
+ binop(Iop_AndV128,
+ mkexpr(t2),
+ binop(Iop_64HLtoV128,
+ mkU64(2ull),
+ mkU64(2ull))),
+ binop(Iop_AndV128,
+ unop(Iop_NotV128,
+ mkexpr(t2)),
+ binop(Iop_64HLtoV128,
+ mkU64(6ull),
+ mkU64(6ull))))));
+ putWReg(wd,
+ binop(Iop_OrV128,
+ mkexpr(t5),
+ binop(Iop_AndV128,
+ binop(Iop_CmpEQ64x2,
+ mkexpr(t5),
+ binop(Iop_64HLtoV128,
+ mkU64(0ull),
+ mkU64(0ull))),
+ binop(Iop_OrV128,
+ binop(Iop_AndV128,
+ mkexpr(t3),
+ binop(Iop_64HLtoV128,
+ mkU64(1ull),
+ mkU64(1ull))),
+ binop(Iop_AndV128,
+ unop(Iop_NotV128,
+ mkexpr(t3)),
+ binop(Iop_64HLtoV128,
+ mkU64(2ull),
+ mkU64(2ull)))))));
+ break;
}
- break;
+ default:
+ return -1;
}
- case 0x06: { /* FCLE.df */
- switch (df) {
- case 0x00: { /* FCLE.W */
- DIP("FCLE.W w%d, w%d, w%d", wd, ws, wt);
- calculateMSACSR(ws, wt, FCLEW, 2);
- putWReg(wd,
- binop(Iop_CmpLE32Fx4,
- getWReg(ws),
- getWReg(wt)));
- break;
- }
+ break;
+ }
- case 0x01: { /* FCLE.D */
- DIP("FCLE.D w%d, w%d, w%d", wd, ws, wt);
- calculateMSACSR(ws, wt, FCLED, 2);
- putWReg(wd,
- binop(Iop_CmpLE64Fx2,
- getWReg(ws),
- getWReg(wt)));
- break;
- }
+ case 0x191: { /* FTRUNC_S.df */
+ switch (df) {
+ case 0x00: { /* FTRUNC_S.W */
+ DIP("FTRUNC_S.W w%d, w%d", wd, ws);
+ calculateMSACSR(ws, wd, FTRUNCSW, 1);
+ putWReg(wd, unop(Iop_F32toI32Sx4_RZ, getWReg(ws)));
+ break;
+ }
- default:
- return -1;
+ case 0x01: { /* FTRUNC_S.D */
+ DIP("FTRUNC_S.D w%d, w%d", wd, ws);
+ calculateMSACSR(ws, wd, FTRUNCSD, 1);
+ t1 = newTemp(Ity_I64);
+ t2 = newTemp(Ity_I64);
+ t3 = newTemp(Ity_V128);
+ assign(t3,
+ binop(Iop_AndV128,
+ unop(Iop_NotV128,
+ binop(Iop_CmpUN64Fx2,
+ getWReg(ws),
+ getWReg(ws))),
+ binop(Iop_Max64Fx2,
+ getWReg(ws),
+ binop(Iop_64HLtoV128,
+ mkU64(0xC3E0000000000000),
+ mkU64(0xC3E0000000000000)))));
+ assign(t1,
+ binop(Iop_F64toI64S, mkU32(0x3),
+ unop(Iop_ReinterpI64asF64,
+ unop(Iop_V128to64, mkexpr(t3)))));
+ assign(t2,
+ binop(Iop_F64toI64S, mkU32(0x3),
+ unop(Iop_ReinterpI64asF64,
+ unop(Iop_V128HIto64, mkexpr(t3)))));
+ putWReg(wd,
+ binop(Iop_64HLtoV128,
+ mkexpr(t2), mkexpr(t1)));
+ break;
}
- break;
+ default:
+ return -1;
}
- case 0x07: { /* FCULE.df */
- switch (df) {
- case 0x00: { /* FCULE.W */
- DIP("FCULE.W w%d, w%d, w%d", wd, ws, wt);
- calculateMSACSR(ws, wt, FCULEW, 2);
- putWReg(wd,
- binop(Iop_OrV128,
- binop(Iop_CmpLE32Fx4,
- getWReg(ws),
- getWReg(wt)),
- binop(Iop_CmpUN32Fx4,
- getWReg(ws),
- getWReg(wt))));
- break;
- }
+ break;
+ }
- case 0x01: { /* FCULE.D */
- DIP("FCULE.D w%d, w%d, w%d", wd, ws, wt);
- calculateMSACSR(ws, wt, FCULED, 2);
- putWReg(wd,
- binop(Iop_OrV128,
- binop(Iop_CmpLE64Fx2,
- getWReg(ws),
- getWReg(wt)),
- binop(Iop_CmpUN64Fx2,
- getWReg(ws),
- getWReg(wt))));
- break;
- }
+ case 0x192: { /* FTRUNC_U.df */
+ switch (df) {
+ case 0x00: { /* FTRUNC_U.W */
+ DIP("FTRUNC_U.W w%d, w%d", wd, ws);
+ calculateMSACSR(ws, wd, FTRUNCUW, 1);
+ putWReg(wd, unop(Iop_F32toI32Ux4_RZ, getWReg(ws)));
+ break;
+ }
- default:
- return -1;
+ case 0x01: { /* FTRUNC_U.D */
+ DIP("FTRUNC_U.D w%d, w%d", wd, ws);
+ calculateMSACSR(ws, wd, FTRUNCUD, 1);
+ t1 = newTemp(Ity_I64);
+ t2 = newTemp(Ity_I64);
+ assign(t1,
+ binop(Iop_F64toI64U,
+ mkU32(0x3),
+ unop(Iop_ReinterpI64asF64,
+ unop(Iop_V128to64,
+ getWReg(ws)))));
+ assign(t2,
+ binop(Iop_F64toI64U,
+ mkU32(0x3),
+ unop(Iop_ReinterpI64asF64,
+ unop(Iop_V128HIto64,
+ getWReg(ws)))));
+ putWReg(wd,
+ binop(Iop_64HLtoV128,
+ mkexpr(t2), mkexpr(t1)));
+ break;
}
- break;
+ default:
+ return -1;
}
- case 0x08: { /* FSAF.df */
- switch (df) {
- case 0x00: { /* FSAF.W */
- DIP("FSAF.W w%d, w%d, w%d", wd, ws, wt);
- calculateMSACSR(ws, wt, FSAFW, 2);
- putWReg(wd,
- binop(Iop_64HLtoV128,
- mkU64(0ul), mkU64(0ul)));
- break;
- }
+ break;
+ }
- case 0x01: { /* FSAF.D */
- DIP("FSAF.D w%d, w%d, w%d", wd, ws, wt);
- calculateMSACSR(ws, wt, FSAFD, 2);
- putWReg(wd,
- binop(Iop_64HLtoV128,
- mkU64(0ul), mkU64(0ul)));
- break;
- }
+ case 0x193: { /* FSQRT.df */
+ switch (df) {
+ case 0x00: { /* FSQRT.W */
+ DIP("FSQRT.W w%d, w%d", wd, ws);
+ IRExpr *rm = get_IR_roundingmode_MSA();
+ calculateMSACSR(ws, wd, FSQRTW, 1);
+ putWReg(wd, binop(Iop_Sqrt32Fx4, rm, getWReg(ws)));
+ break;
+ }
- default:
- return -1;
+ case 0x01: { /* FSQRT.D */
+ DIP("FSQRT.D w%d, w%d", wd, ws);
+ IRExpr *rm = get_IR_roundingmode_MSA();
+ calculateMSACSR(ws, wd, FSQRTD, 1);
+ putWReg(wd, binop(Iop_Sqrt64Fx2, rm, getWReg(ws)));
+ break;
}
- break;
+ default:
+ return -1;
}
- case 0x09: { /* FSUN.df */
- switch (df) {
- case 0x00: { /* FSUN.W */
- DIP("FSUN.W w%d, w%d, w%d", wd, ws, wt);
- calculateMSACSR(ws, wt, FSUNW, 2);
- putWReg(wd,
- binop(Iop_CmpUN32Fx4,
- getWReg(ws),
- getWReg(wt)));
- break;
- }
+ break;
+ }
- case 0x01: { /* FSUN.D */
- DIP("FSUN.D w%d, w%d, w%d", wd, ws, wt);
- calculateMSACSR(ws, wt, FSUND, 2);
- putWReg(wd,
- binop(Iop_CmpUN64Fx2,
- getWReg(ws),
- getWReg(wt)));
- break;
- }
+ case 0x194: { /* FRSQRT.df */
+ switch (df) {
+ case 0x00: { /* FRSQRT.W */
+ DIP("FRSQRT.W w%d, w%d", wd, ws);
+ calculateMSACSR(ws, wd, FRSQRTW, 1);
+ putWReg(wd, unop(Iop_RSqrtEst32Fx4, getWReg(ws)));
+ break;
+ }
- default:
- return -1;
+ case 0x01: { /* FRSQRT.D */
+ DIP("FRSQRT.D w%d, w%d", wd, ws);
+ calculateMSACSR(ws, wd, FRSQRTD, 1);
+ putWReg(wd, unop(Iop_RSqrtEst64Fx2, getWReg(ws)));
+ break;
}
- break;
+ default:
+ return -1;
}
- case 0x0A: { /* FSEQ.df */
- switch (df) {
- case 0x00: { /* FSEQ.W */
- DIP("FSEQ.W w%d, w%d, w%d", wd, ws, wt);
- calculateMSACSR(ws, wt, FSEQW, 2);
- putWReg(wd,
- binop(Iop_CmpEQ32Fx4,
- getWReg(ws),
- getWReg(wt)));
- break;
- }
+ break;
+ }
- case 0x01: { /* FSEQ.D */
- DIP("FSEQ.D w%d, w%d, w%d", wd, ws, wt);
- calculateMSACSR(ws, wt, FSEQD, 2);
- putWReg(wd,
- binop(Iop_CmpEQ64Fx2,
- getWReg(ws),
- getWReg(wt)));
- break;
- }
+ case 0x195: { /* FRCP.df */
+ switch (df) { /* FRCP.W */
+ case 0x00: {
+ DIP("FRCP.W w%d, w%d", wd, ws);
+ calculateMSACSR(ws, wd, FRCPW, 1);
+ putWReg(wd, unop(Iop_RecipEst32Fx4, getWReg(ws)));
+ break;
+ }
- default:
- return -1;
+ case 0x01: { /* FRCP.D */
+ DIP("FRCP.D w%d, w%d", wd, ws);
+ calculateMSACSR(ws, wd, FRCPD, 1);
+ putWReg(wd, unop(Iop_RecipEst64Fx2, getWReg(ws)));
+ break;
}
- break;
+ default:
+ return -1;
}
- case 0x0B: { /* FSUEQ.df */
- switch (df) {
- case 0x00: { /* FSUEQ.W */
- DIP("FSUEQ.W w%d, w%d, w%d", wd, ws, wt);
- calculateMSACSR(ws, wt, FSUEQW, 2);
- putWReg(wd,
+ break;
+ }
+
+ case 0x196: { /* FRINT.df */
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ t4 = newTemp(Ity_V128);
+ IRExpr *rm = get_IR_roundingmode_MSA();
+ assign(t1, getWReg(ws));
+
+ switch (df) {
+ case 0x00: { /* FRINT.W */
+ DIP("FRINT.W w%d, w%d", wd, ws);
+ calculateMSACSR(ws, wt, FRINTW, 1);
+ assign(t2,
+ binop(Iop_OrV128,
+ binop(Iop_CmpLT32Fx4,
+ mkexpr(t1),
+ binop(Iop_64HLtoV128,
+ mkU64(0xCF000000CF000000ull),
+ mkU64(0xCF000000CF000000ull))),
+ binop(Iop_CmpLT32Fx4,
+ binop(Iop_64HLtoV128,
+ mkU64(0x4F0000004F000000ull),
+ mkU64(0x4F0000004F000000ull)),
+ mkexpr(t1))));
+ assign(t3,
+ binop(Iop_CmpEQ32x4,
+ binop(Iop_AndV128,
+ mkexpr(t1),
+ binop(Iop_64HLtoV128,
+ mkU64(0x0040000000400000ull),
+ mkU64(0x0040000000400000ull))),
+ binop(Iop_64HLtoV128,
+ mkU64(0x0040000000400000ull),
+ mkU64(0x0040000000400000ull))));
+ assign(t4,
+ binop(Iop_CmpUN32Fx4,
+ mkexpr(t1), mkexpr(t1)));
+ IRTemp tmp[4];
+ Int i;
+
+ for (i = 0; i < 4; i++) {
+ tmp[i] = newTemp(Ity_I32);
+ assign(tmp[i],
+ unop(Iop_ReinterpF32asI32,
+ binop(Iop_RoundF32toInt, rm,
+ unop(Iop_ReinterpI32asF32,
+ binop(Iop_GetElem32x4,
+ mkexpr(t1), mkU8(i))))));
+ }
+
+ putWReg(wd,
+ binop(Iop_OrV128,
binop(Iop_OrV128,
- binop(Iop_CmpEQ32Fx4,
- getWReg(ws),
- getWReg(wt)),
- binop(Iop_CmpUN32Fx4,
- getWReg(ws),
- getWReg(wt))));
- break;
- }
+ binop(Iop_AndV128,
+ binop(Iop_OrV128,
+ mkexpr(t2),
+ binop(Iop_AndV128,
+ mkexpr(t4),
+ unop(Iop_NotV128,
+ mkexpr(t3)))),
+ mkexpr(t1)),
+ binop(Iop_AndV128,
+ binop(Iop_AndV128,
+ mkexpr(t4),
+ mkexpr(t3)),
+ binop(Iop_64HLtoV128,
+ mkU64(0x7FBFFFFF7FBFFFFF),
+ mkU64(0x7FBFFFFF7FBFFFFF)))),
+ binop(Iop_AndV128,
+ unop(Iop_NotV128,
+ binop(Iop_OrV128,
+ mkexpr(t2),
+ mkexpr(t4))),
+ binop(Iop_OrV128,
+ binop(Iop_64HLtoV128,
+ binop(Iop_32HLto64,
+ mkexpr(tmp[3]),
+ mkexpr(tmp[2])),
+ binop(Iop_32HLto64,
+ mkexpr(tmp[1]),
+ mkexpr(tmp[0]))),
+ binop(Iop_AndV128,
+ mkexpr(t1),
+ binop(Iop_64HLtoV128,
+ mkU64(0x8000000080000000ull),
+ mkU64(0x8000000080000000ull)))
+ ))));
+ break;
+ }
- case 0x01: { /* FSUEQ.D */
- DIP("FSUEQ.D w%d, w%d, w%d", wd, ws, wt);
- calculateMSACSR(ws, wt, FSUEQD, 2);
- putWReg(wd,
+ case 0x01: { /* FRINT.D */
+ DIP("FRINT.D w%d, w%d", wd, ws);
+ calculateMSACSR(ws, wt, FRINTD, 1);
+ assign(t2,
+ binop(Iop_OrV128,
+ binop(Iop_CmpLT64Fx2,
+ mkexpr(t1),
+ binop(Iop_64HLtoV128,
+ mkU64(0xC3E0000000000000ull),
+ mkU64(0xC3E0000000000000ull))),
+ binop(Iop_CmpLT64Fx2,
+ binop(Iop_64HLtoV128,
+ mkU64(0x43E0000000000000ull),
+ mkU64(0x43E0000000000000ull)),
+ mkexpr(t1))));
+ assign(t3,
+ binop(Iop_CmpEQ64x2,
+ binop(Iop_AndV128,
+ getWReg(ws),
+ binop(Iop_64HLtoV128,
+ mkU64(0x0008000000000000ull),
+ mkU64(0x0008000000000000ull))),
+ binop(Iop_64HLtoV128,
+ mkU64(0x0008000000000000ull),
+ mkU64(0x0008000000000000ull))));
+ assign(t4,
+ binop(Iop_CmpUN64Fx2,
+ mkexpr(t1), mkexpr(t1)));
+ IRTemp tmp[2];
+ Int i;
+
+ for (i = 0; i < 2; i++) {
+ tmp[i] = newTemp(Ity_I64);
+ assign(tmp[i],
+ unop(Iop_ReinterpF64asI64,
+ binop(Iop_RoundF64toInt, rm,
+ unop(Iop_ReinterpI64asF64,
+ binop(Iop_GetElem64x2,
+ mkexpr(t1), mkU8(i))))));
+ }
+
+ putWReg(wd,
+ binop(Iop_OrV128,
binop(Iop_OrV128,
- binop(Iop_CmpEQ64Fx2,
- getWReg(ws),
- getWReg(wt)),
- binop(Iop_CmpUN64Fx2,
- getWReg(ws),
- getWReg(wt))));
- break;
- }
+ binop(Iop_AndV128,
+ binop(Iop_OrV128,
+ mkexpr(t2),
+ binop(Iop_AndV128,
+ mkexpr(t4),
+ unop(Iop_NotV128,
+ mkexpr(t3)))),
+ mkexpr(t1)),
+ binop(Iop_AndV128,
+ binop(Iop_AndV128,
+ mkexpr(t4),
+ mkexpr(t3)),
+ binop(Iop_64HLtoV128,
+ mkU64(0x7FF7FFFFFFFFFFFF),
+ mkU64(0x7FF7FFFFFFFFFFFF)))),
+ binop(Iop_AndV128,
+ unop(Iop_NotV128,
+ binop(Iop_OrV128,
+ mkexpr(t2),
+ mkexpr(t4))),
+ binop(Iop_OrV128,
+ binop(Iop_64HLtoV128,
+ mkexpr(tmp[1]),
+ mkexpr(tmp[0])),
+ binop(Iop_AndV128,
+ mkexpr(t1),
+ binop(Iop_64HLtoV128,
+ mkU64(0x8000000000000000ull),
+ mkU64(0x8000000000000000ull))
+ )))));
+ break;
+ }
- default:
- return -1;
+ default:
+ return -1;
+ }
+
+ break;
+ }
+
+ case 0x197: { /* FLOG2.df */
+
+ switch (df) {
+ case 0x00: { /* FLOG2.W */
+ DIP("FLOG2.W w%d, w%d", wd, ws);
+ calculateMSACSR(ws, wt, FLOG2W, 1);
+ putWReg(wd, unop(Iop_Log2_32Fx4, getWReg(ws)));
+ break;
}
- break;
+ case 0x01: { /* FLOG2.D */
+ DIP("FLOG2.D w%d, w%d", wd, ws);
+ calculateMSACSR(ws, wt, FLOG2D, 1);
+ putWReg(wd, unop(Iop_Log2_64Fx2, getWReg(ws)));
+ break;
+ }
+
+ default:
+ return -1;
}
- case 0x0C: { /* FSLT.df */
- switch (df) {
- case 0x00: { /* FSLT.W */
- DIP("FSLT.W w%d, w%d, w%d", wd, ws, wt);
- calculateMSACSR(ws, wt, FSLTW, 2);
- putWReg(wd,
- binop(Iop_CmpLT32Fx4,
- getWReg(ws),
- getWReg(wt)));
- break;
- }
+ break;
+ }
- case 0x01: { /* FSLT.D */
- DIP("FSLT.D w%d, w%d, w%d", wd, ws, wt);
- calculateMSACSR(ws, wt, FSLTD, 2);
- putWReg(wd,
- binop(Iop_CmpLT64Fx2,
- getWReg(ws),
- getWReg(wt)));
- break;
- }
+ case 0x198: { /* FEXUPL.df */
+ switch (df) {
+ case 0x00: { /* FEXUPL.W */
+ DIP("FEXUPL.W w%d, w%d", wd, ws);
+ calculateMSACSR(ws, wt, FEXUPLW, 1);
+ putWReg(wd,
+ unop(Iop_F16toF32x4,
+ unop(Iop_V128HIto64,
+ getWReg(ws))));
+ break;
+ }
- default:
- return -1;
+ case 0x01: { /* FEXUPL.D */
+ DIP("FEXUPL.D w%d, w%d", wd, ws);
+ calculateMSACSR(ws, wt, FEXUPLD, 1);
+ t1 = newTemp(Ity_I64);
+ t2 = newTemp(Ity_I64);
+ assign(t1,
+ unop(Iop_ReinterpF64asI64,
+ unop(Iop_F32toF64,
+ unop(Iop_ReinterpI32asF32,
+ unop(Iop_64to32,
+ unop(Iop_V128HIto64,
+ getWReg(ws)))))));
+ assign(t2,
+ unop(Iop_ReinterpF64asI64,
+ unop(Iop_F32toF64,
+ unop(Iop_ReinterpI32asF32,
+ unop(Iop_64HIto32,
+ unop(Iop_V128HIto64,
+ getWReg(ws)))))));
+ putWReg(wd,
+ binop(Iop_64HLtoV128,
+ mkexpr(t2), mkexpr(t1)));
+ break;
}
- break;
+ default:
+ return -1;
}
- case 0x0D: { /* FSULT.df */
- switch (df) {
- case 0x00: { /* FSULT.W */
- DIP("FSULT.W w%d, w%d, w%d", wd, ws, wt);
- calculateMSACSR(ws, wt, FSULTW, 2);
- putWReg(wd,
- binop(Iop_OrV128,
- binop(Iop_CmpLT32Fx4,
- getWReg(ws),
- getWReg(wt)),
- binop(Iop_CmpUN32Fx4,
- getWReg(ws),
- getWReg(wt))));
- break;
- }
+ break;
+ }
- case 0x01: { /* FSULT.D */
- DIP("FSULT.D w%d, w%d, w%d", wd, ws, wt);
- calculateMSACSR(ws, wt, FSULTD, 2);
- putWReg(wd,
- binop(Iop_OrV128,
- binop(Iop_CmpLT64Fx2,
- getWReg(ws),
- getWReg(wt)),
- binop(Iop_CmpUN64Fx2,
- getWReg(ws),
- getWReg(wt))));
- break;
- }
+ case 0x199: { /* FEXUPR.df */
+ switch (df) {
+ case 0x00: { /* FEXUPR.W */
+ DIP("FEXUPR.W w%d, w%d", wd, ws);
+ calculateMSACSR(ws, wt, FEXUPRW, 1);
+ putWReg(wd,
+ unop(Iop_F16toF32x4,
+ unop(Iop_V128to64,
+ getWReg(ws))));
+ break;
+ }
- default:
- return -1;
+ case 0x01: { /* FEXUPR.D */
+ DIP("FEXUPR.D w%d, w%d", wd, ws);
+ calculateMSACSR(ws, wt, FEXUPRD, 1);
+ t1 = newTemp(Ity_I64);
+ t2 = newTemp(Ity_I64);
+ assign(t1,
+ unop(Iop_ReinterpF64asI64,
+ unop(Iop_F32toF64,
+ unop(Iop_ReinterpI32asF32,
+ unop(Iop_64to32,
+ unop(Iop_V128to64,
+ getWReg(ws)))))));
+ assign(t2,
+ unop(Iop_ReinterpF64asI64,
+ unop(Iop_F32toF64,
+ unop(Iop_ReinterpI32asF32,
+ unop(Iop_64HIto32,
+ unop(Iop_V128to64,
+ getWReg(ws)))))));
+ putWReg(wd,
+ binop(Iop_64HLtoV128,
+ mkexpr(t2), mkexpr(t1)));
+ break;
}
- break;
+ default:
+ return -1;
}
- case 0x0E: { /* FSLE.df */
- switch (df) {
- case 0x00: { /* FSLE.W */
- DIP("FSLE.W w%d, w%d, w%d", wd, ws, wt);
- calculateMSACSR(ws, wt, FSLEW, 2);
- putWReg(wd,
- binop(Iop_CmpLE32Fx4,
- getWReg(ws),
- getWReg(wt)));
- break;
- }
+ break;
+ }
- case 0x01: { /* FSLE.D */
- DIP("FSLE.D w%d, w%d, w%d", wd, ws, wt);
- calculateMSACSR(ws, wt, FSLED, 2);
- putWReg(wd,
- binop(Iop_CmpLE64Fx2,
- getWReg(ws),
- getWReg(wt)));
- break;
- }
+ case 0x19A: { /* FFQL.df */
+ switch (df) {
+ case 0x00: { /* FFQL.W */
+ DIP("FFQL.W w%d, w%d", wd, ws);
+ calculateMSACSR(ws, wt, FFQLW, 1);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_I64);
+ t3 = newTemp(Ity_I64);
+ IRExpr *rm = get_IR_roundingmode_MSA();
+ assign(t1,
+ binop(Iop_SarN32x4,
+ binop(Iop_InterleaveHI16x8,
+ getWReg(ws),
+ getWReg(ws)),
+ mkU8(16)));
+ assign(t2,
+ binop(Iop_32HLto64,
+ unop(Iop_ReinterpF32asI32,
+ binop(Iop_I32StoF32, rm,
+ binop(Iop_GetElem32x4,
+ mkexpr(t1),
+ mkU8(1)))),
+ unop(Iop_ReinterpF32asI32,
+ binop(Iop_I32StoF32, rm,
+ binop(Iop_GetElem32x4,
+ mkexpr(t1),
+ mkU8(0))))));
+ assign(t3,
+ binop(Iop_32HLto64,
+ unop(Iop_ReinterpF32asI32,
+ binop(Iop_I32StoF32, rm,
+ binop(Iop_GetElem32x4,
+ mkexpr(t1),
+ mkU8(3)))),
+ unop(Iop_ReinterpF32asI32,
+ binop(Iop_I32StoF32, rm,
+ binop(Iop_GetElem32x4,
+ mkexpr(t1),
+ mkU8(2))))));
+ putWReg(wd,
+ triop(Iop_Div32Fx4, rm,
+ binop(Iop_64HLtoV128,
+ mkexpr(t3), mkexpr(t2)),
+ binop(Iop_64HLtoV128,
+ mkU64(0x4700000047000000),
+ mkU64(0x4700000047000000))));
+ break;
+ }
- default:
- return -1;
+ case 0x01: { /* FFQL.D */
+ DIP("FFQL.D w%d, w%d", wd, ws);
+ calculateMSACSR(ws, wt, FFQLD, 1);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_I64);
+ t3 = newTemp(Ity_I64);
+ IRExpr *rm = get_IR_roundingmode_MSA();
+ assign(t1,
+ binop(Iop_SarN64x2,
+ binop(Iop_InterleaveHI32x4,
+ getWReg(ws),
+ getWReg(ws)),
+ mkU8(32)));
+ assign(t2,
+ unop(Iop_ReinterpF64asI64,
+ binop(Iop_I64StoF64, rm,
+ unop(Iop_V128to64,
+ mkexpr(t1)))));
+ assign(t3,
+ unop(Iop_ReinterpF64asI64,
+ binop(Iop_I64StoF64, rm,
+ unop(Iop_V128HIto64,
+ mkexpr(t1)))));
+ putWReg(wd,
+ triop(Iop_Div64Fx2, rm,
+ binop(Iop_64HLtoV128,
+ mkexpr(t3), mkexpr(t2)),
+ binop(Iop_64HLtoV128,
+ mkU64(0x41E0000000000000),
+ mkU64(0x41E0000000000000))));
+ break;
}
- break;
+ default:
+ return -1;
}
- case 0x0F: { /* FSULE.df */
- switch (df) {
- case 0x00: { /* FSULE.W */
- DIP("FSULE.W w%d, w%d, w%d", wd, ws, wt);
- calculateMSACSR(ws, wt, FSULEW, 2);
- putWReg(wd,
- binop(Iop_OrV128,
- binop(Iop_CmpLE32Fx4,
- getWReg(ws),
- getWReg(wt)),
- binop(Iop_CmpUN32Fx4,
- getWReg(ws),
- getWReg(wt))));
- break;
- }
+ break;
+ }
- case 0x01: { /* FSULE.D */
- DIP("FSULE.D w%d, w%d, w%d", wd, ws, wt);
- calculateMSACSR(ws, wt, FSULED, 2);
- putWReg(wd,
- binop(Iop_OrV128,
- binop(Iop_CmpLE64Fx2,
- getWReg(ws),
- getWReg(wt)),
- binop(Iop_CmpUN64Fx2,
- getWReg(ws),
- getWReg(wt))));
- break;
- }
+ case 0x19B: { /* FFQR.df */
+ switch (df) {
+ case 0x00: { /* FFQR.W */
+ DIP("FFQR.W w%d, w%d", wd, ws);
+ calculateMSACSR(ws, wt, FFQRW, 1);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_I64);
+ t3 = newTemp(Ity_I64);
+ IRExpr *rm = get_IR_roundingmode_MSA();
+ assign(t1,
+ binop(Iop_SarN32x4,
+ binop(Iop_InterleaveLO16x8,
+ getWReg(ws),
+ getWReg(ws)),
+ mkU8(16)));
+ assign(t2,
+ binop(Iop_32HLto64,
+ unop(Iop_ReinterpF32asI32,
+ binop(Iop_I32StoF32, rm,
+ binop(Iop_GetElem32x4,
+ mkexpr(t1),
+ mkU8(1)))),
+ unop(Iop_ReinterpF32asI32,
+ binop(Iop_I32StoF32, rm,
+ binop(Iop_GetElem32x4,
+ mkexpr(t1),
+ mkU8(0))))));
+ assign(t3,
+ binop(Iop_32HLto64,
+ unop(Iop_ReinterpF32asI32,
+ binop(Iop_I32StoF32, rm,
+ binop(Iop_GetElem32x4,
+ mkexpr(t1),
+ mkU8(3)))),
+ unop(Iop_ReinterpF32asI32,
+ binop(Iop_I32StoF32, rm,
+ binop(Iop_GetElem32x4,
+ mkexpr(t1),
+ mkU8(2))))));
+ putWReg(wd,
+ triop(Iop_Div32Fx4, rm,
+ binop(Iop_64HLtoV128,
+ mkexpr(t3), mkexpr(t2)),
+ binop(Iop_64HLtoV128,
+ mkU64(0x4700000047000000),
+ mkU64(0x4700000047000000))));
+ break;
+ }
- default:
- return -1;
+ case 0x01: { /* FFQR.D */
+ DIP("FFQR.D w%d, w%d", wd, ws);
+ calculateMSACSR(ws, wt, FFQRD, 1);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_I64);
+ t3 = newTemp(Ity_I64);
+ IRExpr *rm = get_IR_roundingmode_MSA();
+ assign(t1,
+ binop(Iop_SarN64x2,
+ binop(Iop_InterleaveLO32x4,
+ getWReg(ws),
+ getWReg(ws)),
+ mkU8(32)));
+ assign(t2,
+ unop(Iop_ReinterpF64asI64,
+ binop(Iop_I64StoF64, rm,
+ unop(Iop_V128to64,
+ mkexpr(t1)))));
+ assign(t3,
+ unop(Iop_ReinterpF64asI64,
+ binop(Iop_I64StoF64, rm,
+ unop(Iop_V128HIto64,
+ mkexpr(t1)))));
+ putWReg(wd,
+ triop(Iop_Div64Fx2, rm,
+ binop(Iop_64HLtoV128,
+ mkexpr(t3), mkexpr(t2)),
+ binop(Iop_64HLtoV128,
+ mkU64(0x41E0000000000000),
+ mkU64(0x41E0000000000000))));
+ break;
}
- break;
+ default:
+ return -1;
}
- default:
- return -1;
- }
+ break;
+ }
- return 0;
-}
+ case 0x19C: { /* FTINT_S.df */
+ switch (df) { /* FTINT_S.W */
+ case 0x00: {
+ DIP("FTINT_S.W w%d, w%d", wd, ws);
+ calculateMSACSR(ws, wd, FTINT_SW, 1);
+ t1 = newTemp(Ity_I64);
+ t2 = newTemp(Ity_I64);
+ t3 = newTemp(Ity_V128);
+ t4 = newTemp(Ity_I32);
+ assign(t3,
+ binop(Iop_AndV128,
+ unop(Iop_NotV128,
+ binop(Iop_CmpUN32Fx4,
+ getWReg(ws),
+ getWReg(ws))),
+ binop(Iop_Max32Fx4,
+ getWReg(ws),
+ binop(Iop_64HLtoV128,
+ mkU64(0xCF000000CF000000),
+ mkU64(0xCF000000CF000000)))));
+ IRExpr *rm = get_IR_roundingmode_MSA();
+ assign(t1,
+ binop(Iop_32HLto64,
+ binop(Iop_F32toI32S, rm,
+ unop(Iop_ReinterpI32asF32,
+ binop(Iop_GetElem32x4,
+ mkexpr(t3), mkU8(1)))),
+ binop(Iop_F32toI32S, rm,
+ unop(Iop_ReinterpI32asF32,
+ binop(Iop_GetElem32x4,
+ mkexpr(t3), mkU8(0))))));
+ assign(t2,
+ binop(Iop_32HLto64,
+ binop(Iop_F32toI32S, rm,
+ unop(Iop_ReinterpI32asF32,
+ binop(Iop_GetElem32x4,
+ mkexpr(t3), mkU8(3)))),
+ binop(Iop_F32toI32S, rm,
+ unop(Iop_ReinterpI32asF32,
+ binop(Iop_GetElem32x4,
+ mkexpr(t3), mkU8(2))))));
+ putWReg(wd,
+ binop(Iop_64HLtoV128,
+ mkexpr(t2), mkexpr(t1)));
+ break;
+ }
-static Int msa_3R_1B(UInt cins, UChar wd, UChar ws) { /* 3R (0x1B) */
- IRTemp t1, t2, t3, t4;
- UShort operation;
- UChar df, wt;
+ case 0x01: { /* FTINT_S.D */
+ DIP("FTINT_S.D w%d, w%d", wd, ws);
+ calculateMSACSR(ws, wd, FTINT_SD, 1);
+ t1 = newTemp(Ity_I64);
+ t2 = newTemp(Ity_I64);
+ t3 = newTemp(Ity_V128);
+ assign(t3,
+ binop(Iop_AndV128,
+ unop(Iop_NotV128,
+ binop(Iop_CmpUN64Fx2,
+ getWReg(ws),
+ getWReg(ws))),
+ binop(Iop_Max64Fx2,
+ getWReg(ws),
+ binop(Iop_64HLtoV128,
+ mkU64(0xC3E0000000000000),
+ mkU64(0xC3E0000000000000)))));
+ IRExpr *rm = get_IR_roundingmode_MSA();
+ assign(t1,
+ binop(Iop_F64toI64S, rm,
+ unop(Iop_ReinterpI64asF64,
+ unop(Iop_V128to64, mkexpr(t3)))));
+ assign(t2,
+ binop(Iop_F64toI64S, rm,
+ unop(Iop_ReinterpI64asF64,
+ unop(Iop_V128HIto64, mkexpr(t3)))));
+ putWReg(wd,
+ binop(Iop_64HLtoV128,
+ mkexpr(t2), mkexpr(t1)));
+ break;
+ }
- operation = (cins & 0x03C00000) >> 22;
- df = (cins & 0x00200000) >> 21;
- wt = (cins & 0x001F0000) >> 16;
+ default:
+ return -1;
+ }
- switch (operation) {
- case 0x00: { /* FADD.df */
- switch (df) {
- case 0x00: { /* FADD.W */
- DIP("FADD.W w%d, w%d, w%d", wd, ws, wt);
- calculateMSACSR(ws, wt, FADDW, 2);
- IRExpr *rm = get_IR_roundingmode_MSA();
- putWReg(wd,
- triop(Iop_Add32Fx4, rm,
- getWReg(ws),
- getWReg(wt)));
- break;
- }
+ break;
+ }
- case 0x01: { /* FADD.D */
- DIP("FADD.D w%d, w%d, w%d", wd, ws, wt);
- calculateMSACSR(ws, wt, FADDD, 2);
- IRExpr *rm = get_IR_roundingmode_MSA();
- putWReg(wd,
- triop(Iop_Add64Fx2, rm,
- getWReg(ws),
- getWReg(wt)));
- break;
- }
+ case 0x19D: {/* FTINT_U.df */
+ switch (df) { /* FTINT_U.W */
+ case 0x00: {
+ DIP("FTINT_U.W w%d, w%d", wd, ws);
+ calculateMSACSR(ws, wd, FTINT_UW, 1);
+ t1 = newTemp(Ity_I64);
+ t2 = newTemp(Ity_I64);
+ t3 = newTemp(Ity_V128);
+ t4 = newTemp(Ity_V128);
+ IRExpr *rm = get_IR_roundingmode_MSA();
+ assign(t1,
+ binop(Iop_32HLto64,
+ binop(Iop_F32toI32U, rm,
+ unop(Iop_ReinterpI32asF32,
+ binop(Iop_GetElem32x4,
+ getWReg(ws), mkU8(1)))),
+ binop(Iop_F32toI32U, rm,
+ unop(Iop_ReinterpI32asF32,
+ binop(Iop_GetElem32x4,
+ getWReg(ws), mkU8(0))))));
+ assign(t2,
+ binop(Iop_32HLto64,
+ binop(Iop_F32toI32U, rm,
+ unop(Iop_ReinterpI32asF32,
+ binop(Iop_GetElem32x4,
+ getWReg(ws), mkU8(3)))),
+ binop(Iop_F32toI32U, rm,
+ unop(Iop_ReinterpI32asF32,
+ binop(Iop_GetElem32x4,
+ getWReg(ws), mkU8(2))))));
+ assign(t3,
+ unop(Iop_NotV128,
+ binop(Iop_SarN32x4,
+ getWReg(ws),
+ mkU8(31))));
+ assign(t4,
+ binop(Iop_CmpLT32Fx4,
+ getWReg(ws),
+ binop(Iop_64HLtoV128,
+ mkU64(0x4EFFFFFF4EFFFFFF),
+ mkU64(0x4EFFFFFF4EFFFFFF))));
+ putWReg(wd,
+ binop(Iop_OrV128,
+ binop(Iop_AndV128,
+ mkexpr(t4),
+ binop(Iop_AndV128,
+ binop(Iop_64HLtoV128,
+ mkexpr(t2),
+ mkexpr(t1)),
+ mkexpr(t3))),
+ binop(Iop_AndV128,
+ unop(Iop_NotV128, mkexpr(t4)),
+ unop(Iop_F32toI32Ux4_RZ,
+ getWReg(ws)))));
+ break;
+ }
- default:
- return -1;
+ case 0x01: { /* FTINT_U.D */
+ DIP("FTINT_U.D w%d, w%d", wd, ws);
+ calculateMSACSR(ws, wd, FTINT_UD, 1);
+ t1 = newTemp(Ity_I64);
+ t2 = newTemp(Ity_I64);
+ IRExpr *rm = get_IR_roundingmode_MSA();
+ assign(t1,
+ binop(Iop_F64toI64U, rm,
+ unop(Iop_ReinterpI64asF64,
+ unop(Iop_V128to64,
+ getWReg(ws)))));
+ assign(t2,
+ binop(Iop_F64toI64U, rm,
+ unop(Iop_ReinterpI64asF64,
+ unop(Iop_V128HIto64,
+ getWReg(ws)))));
+ putWReg(wd,
+ binop(Iop_64HLtoV128,
+ mkexpr(t2), mkexpr(t1)));
+ break;
}
- break;
+ default:
+ return -1;
}
- case 0x01: { /* FSUB.df */
- switch (df) {
- case 0x00: { /* FSUB.W */
- DIP("FSUB.W w%d, w%d, w%d", wd, ws, wt);
- calculateMSACSR(ws, wt, FSUBW, 2);
- IRExpr *rm = get_IR_roundingmode_MSA();
- putWReg(wd,
- triop(Iop_Sub32Fx4, rm,
- getWReg(ws),
- getWReg(wt)));
- break;
- }
+ break;
+ }
- case 0x01: { /* FSUB.D */
- DIP("FSUB.D w%d, w%d, w%d", wd, ws, wt);
- calculateMSACSR(ws, wt, FSUBD, 2);
- IRExpr *rm = get_IR_roundingmode_MSA();
- putWReg(wd,
- triop(Iop_Sub64Fx2, rm,
- getWReg(ws),
- getWReg(wt)));
- break;
- }
+ case 0x19E: { /* FFINT_S.df */
+ t1 = newTemp(Ity_V128);
+ assign(t1, getWReg(ws));
+ IRExpr *rm = get_IR_roundingmode_MSA();
- default:
- return -1;
- }
+ switch (df) {
+ case 0x00: { /* FFINT_S.W */
+ DIP("FFINT_S.W w%d, w%d", wd, ws);
+ calculateMSACSR(ws, wt, FFINTSW, 1);
+ IRTemp tmp[4];
+ Int i;
+
+ for (i = 0; i < 4; i++) {
+ tmp[i] = newTemp(Ity_F32);
+ assign(tmp[i],
+ binop(Iop_I32StoF32, rm,
+ binop(Iop_GetElem32x4,
+ mkexpr(t1), mkU8(i))));
+ }
- break;
- }
+ putWReg(wd,
+ binop(Iop_64HLtoV128,
+ binop(Iop_32HLto64,
+ unop(Iop_ReinterpF32asI32,
+ mkexpr(tmp[3])),
+ unop(Iop_ReinterpF32asI32,
+ mkexpr(tmp[2]))),
+ binop(Iop_32HLto64,
+ unop(Iop_ReinterpF32asI32,
+ mkexpr(tmp[1])),
+ unop(Iop_ReinterpF32asI32,
+ mkexpr(tmp[0])))));
+ break;
+ }
- case 0x02: { /* FMUL.df */
- switch (df) {
- case 0x00: { /* FMUL.W */
- DIP("FMUL.W w%d, w%d, w%d", wd, ws, wt);
- calculateMSACSR(ws, wt, FMULW, 2);
- IRExpr *rm = get_IR_roundingmode_MSA();
- putWReg(wd,
- triop(Iop_Mul32Fx4, rm,
- getWReg(ws),
- getWReg(wt)));
- break;
- }
+ case 0x01: { /* FFINT_S.D */
+ DIP("FFINT_S.D w%d, w%d", wd, ws);
+ calculateMSACSR(ws, wt, FFINTSD, 1);
+ IRTemp tmp[2];
+ Int i;
- case 0x01: { /* FMUL.D */
- DIP("FMUL.D w%d, w%d, w%d", wd, ws, wt);
- calculateMSACSR(ws, wt, FMULW, 2);
- IRExpr *rm = get_IR_roundingmode_MSA();
- putWReg(wd,
- triop(Iop_Mul64Fx2, rm,
- getWReg(ws),
- getWReg(wt)));
- break;
- }
+ for (i = 0; i < 2; i++) {
+ tmp[i] = newTemp(Ity_F64);
+ assign(tmp[i],
+ binop(Iop_I64StoF64, rm,
+ binop(Iop_GetElem64x2,
+ mkexpr(t1), mkU8(i))));
+ }
- default:
- return -1;
+ putWReg(wd,
+ binop(Iop_64HLtoV128,
+ unop(Iop_ReinterpF64asI64,
+ mkexpr(tmp[1])),
+ unop(Iop_ReinterpF64asI64,
+ mkexpr(tmp[0]))));
+ break;
}
- break;
+ default:
+ return -1;
}
- case 0x03: { /* FDIV.df */
- switch (df) {
- case 0x00: { /* FDIV.W */
- DIP("FDIV.W w%d, w%d, w%d", wd, ws, wt);
- calculateMSACSR(ws, wt, FDIVW, 2);
- IRExpr *rm = get_IR_roundingmode_MSA();
- putWReg(wd,
- triop(Iop_Div32Fx4, rm,
- getWReg(ws),
- getWReg(wt)));
- break;
- }
+ break;
+ }
- case 0x01: { /* FDIV.D */
- DIP("FDIV.D w%d, w%d, w%d", wd, ws, wt);
- calculateMSACSR(ws, wt, FDIVD, 2);
- IRExpr *rm = get_IR_roundingmode_MSA();
- putWReg(wd,
- triop(Iop_Div64Fx2, rm,
- getWReg(ws),
- getWReg(wt)));
- break;
- }
+ case 0x19F: { /* FFINT_U.df */
+ IRExpr *rm = get_IR_roundingmode_MSA();
- default:
- return -1;
+ switch (df) {
+ case 0x00: { /* FFINT_U.W */
+ DIP("FFINT_U.W w%d, w%d", wd, ws);
+ calculateMSACSR(ws, wt, FFINT_UW, 1);
+ putWReg(wd, unop(Iop_I32UtoF32x4_DEP, getWReg(ws)));
+ break;
}
- break;
+ case 0x01: { /* FFINT_U.D */
+ DIP("FFINT_U.D w%d, w%d",
+ wd, ws);
+ calculateMSACSR(ws, wt,
+ FFINT_UD, 1);
+ t1 = newTemp(Ity_I64);
+ t2 = newTemp(Ity_I64);
+ assign(t1,
+ unop(Iop_ReinterpF64asI64,
+ binop(Iop_I64UtoF64, rm,
+ unop(Iop_V128to64,
+ getWReg(ws)))));
+ assign(t2,
+ unop(Iop_ReinterpF64asI64,
+ binop(Iop_I64UtoF64, rm,
+ unop(Iop_V128HIto64,
+ getWReg(ws)))));
+ putWReg(wd,
+ binop(Iop_64HLtoV128,
+ mkexpr(t2), mkexpr(t1)));
+ break;
+ }
+
+ default:
+ return -1;
}
- case 0x04: { /* FMADD.df */
- switch (df) {
- case 0x00: { /* FMADD.W */
- DIP("FMADD.W w%d, w%d, w%d", wd, ws, wt);
- calculateMSACSR(ws, wt, FMADDW, 2);
- IRExpr *rm = get_IR_roundingmode_MSA();
- IRTemp tmp[4];
- Int i;
+ break;
+ }
- for (i = 0; i < 4; i++) {
- tmp[i] = newTemp(Ity_F32);
- assign(tmp[i],
- qop(Iop_MAddF32, rm,
- unop(Iop_ReinterpI32asF32,
- binop(Iop_GetElem32x4,
- getWReg(ws),
- mkU8(i))),
- unop(Iop_ReinterpI32asF32,
- binop(Iop_GetElem32x4,
- getWReg(wt),
- mkU8(i))),
- unop(Iop_ReinterpI32asF32,
- binop(Iop_GetElem32x4,
- getWReg(wd),
- mkU8(i)))));
- }
+ default:
+ return -1;
+ }
- putWReg(wd,
- binop(Iop_64HLtoV128,
- binop(Iop_32HLto64,
- unop(Iop_ReinterpF32asI32,
- mkexpr(tmp[3])),
- unop(Iop_ReinterpF32asI32,
- mkexpr(tmp[2]))),
- binop(Iop_32HLto64,
- unop(Iop_ReinterpF32asI32,
- mkexpr(tmp[1])),
- unop(Iop_ReinterpF32asI32,
- mkexpr(tmp[0])))));
- break;
- }
+ return 0;
+}
- case 0x01: { /* FMADD.D */
- DIP("FMADD.D w%d, w%d, w%d", wd, ws, wt);
- calculateMSACSR(ws, wt, FMADDW, 2);
- IRExpr *rm = get_IR_roundingmode_MSA();
- IRTemp tmp[2];
- Int i;
+static Int msa_MI10_load(UInt cins, UChar wd, UChar ws) /* MI10 (0x20) */
+{
+ IRTemp t1;
+ UShort i10;
+ UChar df;
- for (i = 0; i < 2; i++) {
- tmp[i] = newTemp(Ity_F64);
- assign(tmp[i],
- qop(Iop_MAddF64, rm,
- unop(Iop_ReinterpI64asF64,
- binop(Iop_GetElem64x2,
- getWReg(ws),
- mkU8(i))),
- unop(Iop_ReinterpI64asF64,
- binop(Iop_GetElem64x2,
- getWReg(wt),
- mkU8(i))),
- unop(Iop_ReinterpI64asF64,
- binop(Iop_GetElem64x2,
- getWReg(wd),
- mkU8(i)))));
- }
+ i10 = (cins & 0x03FF0000) >> 16;
+ df = cins & 0x00000003;
- putWReg(wd,
- binop(Iop_64HLtoV128,
- unop(Iop_ReinterpF64asI64,
- mkexpr(tmp[1])),
- unop(Iop_ReinterpF64asI64,
- mkexpr(tmp[0]))));
- break;
- }
+ switch (df) {
+ case 0x00: { /* LD.B */
+ DIP("LD.B w%d, %d(r%d)", wd, ws, i10);
+ LOAD_STORE_PATTERN_MSA(i10);
+ putWReg(wd, load(Ity_V128, mkexpr(t1)));
+ break;
+ }
- default:
- return -1;
- }
+ case 0x01: { /* LD.H */
+ DIP("LD.H w%d, %d(r%d)", wd, ws, i10);
+ LOAD_STORE_PATTERN_MSA(i10 << 1);
+#if defined (_MIPSEL)
+ putWReg(wd, load(Ity_V128, mkexpr(t1)));
+#elif defined (_MIPSEB)
+ putWReg(wd,
+ unop(Iop_Reverse8sIn16_x8,
+ load(Ity_V128, mkexpr(t1))));
+#endif
+ break;
+ }
- break;
- }
+ case 0x02: { /* LD.W */
+ DIP("LD.W w%d, %d(r%d)", wd, ws, i10);
+ LOAD_STORE_PATTERN_MSA(i10 << 2);
+#if defined (_MIPSEL)
+ putWReg(wd, load(Ity_V128, mkexpr(t1)));
+#elif defined (_MIPSEB)
+ putWReg(wd,
+ unop(Iop_Reverse8sIn32_x4,
+ load(Ity_V128, mkexpr(t1))));
+#endif
+ break;
+ }
- case 0x05: { /* FMSUB.df */
- switch (df) {
- case 0x00: { /* FMSUB.W */
- DIP("FMSUB.W w%d, w%d, w%d", wd, ws, wt);
- calculateMSACSR(ws, wt, FMADDW, 2);
- IRExpr *rm = get_IR_roundingmode_MSA();
- IRTemp tmp[4];
- Int i;
+ case 0x03: { /* LD.D */
+ DIP("LD.D w%d, %d(r%d)", wd, ws, i10);
+ LOAD_STORE_PATTERN_MSA(i10 << 3);
+#if defined (_MIPSEL)
+ putWReg(wd, load(Ity_V128, mkexpr(t1)));
+#elif defined (_MIPSEB)
+ putWReg(wd,
+ unop(Iop_Reverse8sIn64_x2,
+ load(Ity_V128, mkexpr(t1))));
+#endif
+ break;
+ }
- for (i = 0; i < 4; i++) {
- tmp[i] = newTemp(Ity_F32);
- assign(tmp[i],
- qop(Iop_MSubF32, rm,
- unop(Iop_ReinterpI32asF32,
- binop(Iop_GetElem32x4,
- getWReg(ws),
- mkU8(i))),
- unop(Iop_ReinterpI32asF32,
- binop(Iop_GetElem32x4,
- getWReg(wt),
- mkU8(i))),
- unop(Iop_ReinterpI32asF32,
- binop(Iop_GetElem32x4,
- getWReg(wd),
- mkU8(i)))));
- }
+ default:
+ return -1;
+ }
- putWReg(wd,
- binop(Iop_64HLtoV128,
- binop(Iop_32HLto64,
- unop(Iop_ReinterpF32asI32,
- mkexpr(tmp[3])),
- unop(Iop_ReinterpF32asI32,
- mkexpr(tmp[2]))),
- binop(Iop_32HLto64,
- unop(Iop_ReinterpF32asI32,
- mkexpr(tmp[1])),
- unop(Iop_ReinterpF32asI32,
- mkexpr(tmp[0])))));
- break;
- }
+ return 0;
+}
- case 0x01: { /* FMSUB.D */
- DIP("FMSUB.D w%d, w%d, w%d", wd, ws, wt);
- calculateMSACSR(ws, wt, FMADDD, 2);
- IRExpr *rm = get_IR_roundingmode_MSA();
- IRTemp tmp[2];
- Int i;
+static Int msa_MI10_store(UInt cins, UChar wd, UChar ws) /* MI10 (0x24) */
+{
+ IRTemp t1;
+ UShort i10;
+ UChar df;
- for (i = 0; i < 2; i++) {
- tmp[i] = newTemp(Ity_F64);
- assign(tmp[i],
- qop(Iop_MSubF64, rm,
- unop(Iop_ReinterpI64asF64,
- binop(Iop_GetElem64x2,
- getWReg(ws),
- mkU8(i))),
- unop(Iop_ReinterpI64asF64,
- binop(Iop_GetElem64x2,
- getWReg(wt),
- mkU8(i))),
- unop(Iop_ReinterpI64asF64,
- binop(Iop_GetElem64x2,
- getWReg(wd),
- mkU8(i)))));
- }
+ df = cins & 0x00000003;
+ i10 = (cins & 0x03FF0000) >> 16;
- putWReg(wd,
- binop(Iop_64HLtoV128,
- unop(Iop_ReinterpF64asI64,
- mkexpr(tmp[1])),
- unop(Iop_ReinterpF64asI64,
- mkexpr(tmp[0]))));
- break;
- }
+ switch (df) {
+ case 0x00: { /* ST.B */
+ DIP("ST.B w%d, %d(r%d)", wd, ws, i10);
+ LOAD_STORE_PATTERN_MSA(i10);
+ store(mkexpr(t1), getWReg(wd));
+ break;
+ }
- default:
- return -1;
- }
+ case 0x01: { /* ST.H */
+ DIP("ST.H w%d, %d(r%d)", wd, ws, i10);
+ LOAD_STORE_PATTERN_MSA(i10 << 1);
+#if defined (_MIPSEL)
+ store(mkexpr(t1), getWReg(wd));
+#elif defined (_MIPSEB)
+ store(mkexpr(t1),
+ unop(Iop_Reverse8sIn16_x8, getWReg(wd)));
+#endif
+ break;
+ }
- break;
- }
+ case 0x02: { /* ST.W */
+ DIP("ST.W w%d, %d(r%d)", wd, ws, i10);
+ LOAD_STORE_PATTERN_MSA(i10 << 2);
+#if defined (_MIPSEL)
+ store(mkexpr(t1), getWReg(wd));
+#elif defined (_MIPSEB)
+ store(mkexpr(t1),
+ unop(Iop_Reverse8sIn32_x4, getWReg(wd)));
+#endif
+ break;
+ }
- case 0x07: { /* FEXP2.df */
- switch (df) {
- case 0x00: { /* FEXP2.W */
- DIP("FEXP2.W w%d, w%d, w%d", wd, ws, wt);
- calculateMSACSR(ws, wt, FEXP2W, 2);
- IRExpr *rm = get_IR_roundingmode_MSA();
- putWReg(wd,
- triop(Iop_Scale2_32Fx4, rm,
- getWReg(ws),
- getWReg(wt)));
- break;
- }
+ case 0x03: { /* ST.D */
+ DIP("ST.D w%d, %d(r%d)", wd, ws, i10);
+ LOAD_STORE_PATTERN_MSA(i10 << 3);
+#if defined (_MIPSEL)
+ store(mkexpr(t1), getWReg(wd));
+#elif defined (_MIPSEB)
+ store(mkexpr(t1),
+ unop(Iop_Reverse8sIn64_x2, getWReg(wd)));
+#endif
+ break;
+ }
- case 0x01: { /* FEXP2.D */
- DIP("FEXP2.D w%d, w%d, w%d", wd, ws, wt);
- calculateMSACSR(ws, wt, FEXP2D, 2);
- IRExpr *rm = get_IR_roundingmode_MSA();
- putWReg(wd,
- triop(Iop_Scale2_64Fx2, rm,
- getWReg(ws),
- getWReg(wt)));
- break;
- }
+ default:
+ return -1;
+ }
- default:
- return -1;
- }
+ return 0;
+}
- break;
- }
+/*------------------------------------------------------------*/
+/*--- Disassemble a single MIPS MSA (SIMD) instruction ---*/
+/*--- Return values: ---*/
+/*--- 0: Success ---*/
+/*--- -1: Decode failure (unknown instruction) ---*/
+/*--- -2: Illegal instruction ---*/
+/*------------------------------------------------------------*/
+static Int disMSAInstr_MIPS_WRK ( UInt cins )
+{
+ UChar minor_opcode, wd, ws;
- case 0x08: { /* FEXDO.df */
- switch (df) {
- case 0x00: { /* FEXDO.H */
- DIP("FEXDO.H w%d, w%d, w%d", wd, ws, wt);
- calculateMSACSR(ws, wt, FEXDOH, 2);
- t1 = newTemp(Ity_I64);
- t2 = newTemp(Ity_I64);
- assign(t1,
- unop(Iop_F32toF16x4_DEP,
- getWReg(ws)));
- assign(t2,
- unop(Iop_F32toF16x4_DEP,
- getWReg(wt)));
- putWReg(wd,
- binop(Iop_64HLtoV128,
- mkexpr(t1), mkexpr(t2)));
- break;
- }
+ vassert(has_msa);
+ vassert((cins & 0xFC000000) == 0x78000000);
- case 0x01: { /* FEXDO.W */
- DIP("FEXDO.W w%d, w%d, w%d", wd, ws, wt);
- calculateMSACSR(ws, wt, FEXDOW, 2);
- t1 = newTemp(Ity_I32);
- t2 = newTemp(Ity_I32);
- t3 = newTemp(Ity_I32);
- t4 = newTemp(Ity_I32);
- IRExpr *rm = get_IR_roundingmode_MSA();
- assign(t1,
- unop(Iop_ReinterpF32asI32,
- binop(Iop_F64toF32, rm,
- unop(Iop_ReinterpI64asF64,
- unop(Iop_V128to64,
- getWReg(ws))))));
- assign(t2,
- unop(Iop_ReinterpF32asI32,
- binop(Iop_F64toF32, rm,
- unop(Iop_ReinterpI64asF64,
- unop(Iop_V128HIto64,
- getWReg(ws))))));
- assign(t3,
- unop(Iop_ReinterpF32asI32,
- binop(Iop_F64toF32, rm,
- unop(Iop_ReinterpI64asF64,
- unop(Iop_V128to64,
- getWReg(wt))))));
- assign(t4,
- unop(Iop_ReinterpF32asI32,
- binop(Iop_F64toF32, rm,
- unop(Iop_ReinterpI64asF64,
- unop(Iop_V128HIto64,
- getWReg(wt))))));
- putWReg(wd,
- binop(Iop_64HLtoV128,
- binop(Iop_32HLto64,
- mkexpr(t2), mkexpr(t1)),
- binop(Iop_32HLto64,
- mkexpr(t4), mkexpr(t3))));
- break;
- }
+ minor_opcode = (cins & 0x20) > 0 ? (cins & 0x3C) : (cins & 0x3F);
+ wd = (cins & 0x000007C0) >> 6;
+ ws = (cins & 0x0000F800) >> 11;
- default:
- return -1;
- }
+ switch (minor_opcode) {
+ case 0x0:
+ return msa_I8_logical(cins, wd, ws);
- break;
- }
+ case 0x01:
+ return msa_I8_branch(cins, wd, ws);
- case 0x0A: { /* FTQ.df */
- switch (df) {
- case 0x00: { /* FTQ.H */
- DIP("FTQ.H w%d, w%d, w%d", wd, ws, wt);
- calculateMSACSR(ws, wt, FTQH, 2);
- IRExpr *rm = get_IR_roundingmode_MSA();
- putWReg(wd,
- triop(Iop_F32x4_2toQ16x8, rm,
- getWReg(ws),
- getWReg(wt)));
- break;
- }
+ case 0x02:
+ return msa_I8_shift(cins, wd, ws);
- case 0x01: { /* FTQ.W */
- DIP("FTQ.W w%d, w%d, w%d", wd, ws, wt);
- calculateMSACSR(ws, wt, FTQW, 2);
- IRExpr *rm = get_IR_roundingmode_MSA();
- putWReg(wd,
- triop(Iop_F64x2_2toQ32x4, rm,
- getWReg(ws),
- getWReg(wt)));
- break;
- }
+ case 0x06:
+ return msa_I5_06(cins, wd, ws);
- default:
- return -1;
- }
+ case 0x07:
+ return msa_I5_07(cins, wd, ws);
- break;
- }
+ case 0x09:
+ return msa_BIT_09(cins, wd, ws);
- case 0x0C: { /* FMIN.df */
- switch (df) {
- case 0x00: { /* FMIN.W */
- DIP("FMIN.W w%d, w%d, w%d", wd, ws, wt);
- calculateMSACSR(ws, wt, FMINW, 2);
- putWReg(wd,
- binop(Iop_Min32Fx4,
- getWReg(ws),
- getWReg(wt)));
- break;
- }
+ case 0x0A:
+ return msa_BIT_0A(cins, wd, ws);
- case 0x01: { /* FMIN.D */
- DIP("FMIN.D w%d, w%d, w%d", wd, ws, wt);
- calculateMSACSR(ws, wt, FMINW, 2);
- putWReg(wd,
- binop(Iop_Min64Fx2,
- getWReg(ws),
- getWReg(wt)));
- break;
- }
+ case 0x0D:
+ return msa_3R_0D(cins, wd, ws);
- default:
- return -1;
- }
+ case 0x0E:
+ return msa_3R_0E(cins, wd, ws);
- break;
- }
+ case 0x0F:
+ return msa_3R_0F(cins, wd, ws);
- case 0x0D: { /* FMIN_A.df */
- switch (df) {
- case 0x00: { /* FMIN_A.W */
- DIP("FMIN_A.W w%d, w%d, w%d", wd, ws, wt);
- calculateMSACSR(ws, wt, FMINAW, 2);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- t4 = newTemp(Ity_V128);
- assign(t1,
- binop(Iop_AndV128,
- getWReg(ws),
- binop(Iop_64HLtoV128,
- mkU64(0x7FFFFFFF7FFFFFFF),
- mkU64(0x7FFFFFFF7FFFFFFF))));
- assign(t2,
- binop(Iop_AndV128,
- getWReg(wt),
- binop(Iop_64HLtoV128,
- mkU64(0x7FFFFFFF7FFFFFFF),
- mkU64(0x7FFFFFFF7FFFFFFF))));
- assign(t3,
- binop(Iop_Min32Fx4,
- mkexpr(t2), mkexpr(t1)));
- assign(t4,
- binop(Iop_AndV128,
- binop(Iop_AndV128,
- unop(Iop_NotV128,
- binop(Iop_CmpUN32Fx4,
- mkexpr(t3),
- mkexpr(t3))),
- binop(Iop_OrV128,
- binop(Iop_AndV128,
- binop(Iop_CmpEQ32Fx4,
- mkexpr(t1),
- mkexpr(t2)),
- binop(Iop_OrV128,
- getWReg(ws),
- getWReg(wt))),
- binop(Iop_OrV128,
- binop(Iop_AndV128,
- binop(Iop_OrV128,
- binop(Iop_CmpUN32Fx4,
- mkexpr(t1),
- mkexpr(t1)),
- binop(Iop_CmpLT32Fx4,
- mkexpr(t3),
- mkexpr(t1))),
- getWReg(wt)),
- binop(Iop_AndV128,
- binop(Iop_OrV128,
- binop(Iop_CmpUN32Fx4,
- mkexpr(t2),
- mkexpr(t2)),
- binop(Iop_CmpLT32Fx4,
- mkexpr(t3),
- mkexpr(t2))),
- getWReg(ws))))),
- binop(Iop_64HLtoV128,
- mkU64(0x8000000080000000),
- mkU64(0x8000000080000000))));
- putWReg(wd,
- binop(Iop_OrV128,
- mkexpr(t3), mkexpr(t4)));
- break;
- }
+ case 0x10:
+ return msa_3R_10(cins, wd, ws);
- case 0x01: { /* FMIN_A.D */
- DIP("FMIN_A.D w%d, w%d, w%d", wd, ws, wt);
- calculateMSACSR(ws, wt, FMINAD, 2);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- t4 = newTemp(Ity_V128);
- assign(t1,
- binop(Iop_AndV128,
- getWReg(ws),
- binop(Iop_64HLtoV128,
- mkU64(0x7FFFFFFFFFFFFFFF),
- mkU64(0x7FFFFFFFFFFFFFFF))));
- assign(t2,
- binop(Iop_AndV128,
- getWReg(wt),
- binop(Iop_64HLtoV128,
- mkU64(0x7FFFFFFFFFFFFFFF),
- mkU64(0x7FFFFFFFFFFFFFFF))));
- assign(t3,
- binop(Iop_Min64Fx2,
- mkexpr(t2), mkexpr(t1)));
- assign(t4,
- binop(Iop_AndV128,
- binop(Iop_AndV128,
- unop(Iop_NotV128,
- binop(Iop_CmpUN64Fx2,
- mkexpr(t3),
- mkexpr(t3))),
- binop(Iop_OrV128,
- binop(Iop_AndV128,
- binop(Iop_CmpEQ64Fx2,
- mkexpr(t1),
- mkexpr(t2)),
- binop(Iop_OrV128,
- getWReg(ws),
- getWReg(wt))),
- binop(Iop_OrV128,
- binop(Iop_AndV128,
- binop(Iop_OrV128,
- binop(Iop_CmpUN64Fx2,
- mkexpr(t1),
- mkexpr(t1)),
- binop(Iop_CmpLT64Fx2,
- mkexpr(t3),
- mkexpr(t1))),
- getWReg(wt)),
- binop(Iop_AndV128,
- binop(Iop_OrV128,
- binop(Iop_CmpUN64Fx2,
- mkexpr(t2),
- mkexpr(t2)),
- binop(Iop_CmpLT64Fx2,
- mkexpr(t3),
- mkexpr(t2))),
- getWReg(ws))))),
- binop(Iop_64HLtoV128,
- mkU64(0x8000000000000000),
- mkU64(0x8000000000000000))));
- putWReg(wd,
- binop(Iop_OrV128,
- mkexpr(t3), mkexpr(t4)));
- break;
- }
+ case 0x11:
+ return msa_3R_11(cins, wd, ws);
- default:
- return -1;
- }
+ case 0x12:
+ return msa_3R_12(cins, wd, ws);
- break;
- }
+ case 0x13:
+ return msa_3R_13(cins, wd, ws);
- case 0x0E: { /* FMAX.df */
- switch (df) {
- case 0x00: { /* FMAX.W */
- DIP("FMAX.W w%d, w%d, w%d", wd, ws, wt);
- calculateMSACSR(ws, wt, FMAXW, 2);
- putWReg(wd,
- binop(Iop_Max32Fx4,
- getWReg(ws),
- getWReg(wt)));
- break;
- }
+ case 0x14:
+ return msa_3R_14(cins, wd, ws);
- case 0x01: { /* FMAX.D */
- DIP("FMAX.D w%d, w%d, w%d", wd, ws, wt);
- calculateMSACSR(ws, wt, FMAXW, 2);
- putWReg(wd,
- binop(Iop_Max64Fx2,
- getWReg(ws),
- getWReg(wt)));
- break;
- }
+ case 0x15:
+ return msa_3R_15(cins, wd, ws);
- default:
- return -1;
- }
+ case 0x19:
+ return msa_ELM(cins, wd, ws);
- break;
- }
+ case 0x1A:
+ return msa_3R_1A(cins, wd, ws);
- case 0x0F: { /* FMAX_A.df */
- switch (df) {
- case 0x00: { /* FMAX_A.W */
- DIP("FMAX_A.W w%d, w%d, w%d", wd, ws, wt);
- calculateMSACSR(ws, wt, FMAXAW, 2);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- t4 = newTemp(Ity_V128);
- assign(t1,
- binop(Iop_AndV128,
- getWReg(ws),
- binop(Iop_64HLtoV128,
- mkU64(0x7FFFFFFF7FFFFFFF),
- mkU64(0x7FFFFFFF7FFFFFFF))));
- assign(t2,
- binop(Iop_AndV128,
- getWReg(wt),
- binop(Iop_64HLtoV128,
- mkU64(0x7FFFFFFF7FFFFFFF),
- mkU64(0x7FFFFFFF7FFFFFFF))));
- assign(t3,
- binop(Iop_Max32Fx4,
- mkexpr(t2), mkexpr(t1)));
- assign(t4,
- binop(Iop_AndV128,
- binop(Iop_AndV128,
- unop(Iop_NotV128,
- binop(Iop_CmpUN32Fx4,
- mkexpr(t3),
- mkexpr(t3))),
- binop(Iop_OrV128,
- binop(Iop_AndV128,
- binop(Iop_CmpEQ32Fx4,
- mkexpr(t1),
- mkexpr(t2)),
- binop(Iop_AndV128,
- getWReg(ws),
- getWReg(wt))),
- binop(Iop_OrV128,
- binop(Iop_AndV128,
- binop(Iop_OrV128,
- binop(Iop_CmpUN32Fx4,
- mkexpr(t1),
- mkexpr(t1)),
- binop(Iop_CmpLT32Fx4,
- mkexpr(t1),
- mkexpr(t3))),
- getWReg(wt)),
- binop(Iop_AndV128,
- binop(Iop_OrV128,
- binop(Iop_CmpUN32Fx4,
- mkexpr(t2),
- mkexpr(t2)),
- binop(Iop_CmpLT32Fx4,
- mkexpr(t2),
- mkexpr(t3))),
- getWReg(ws))))),
- binop(Iop_64HLtoV128,
- mkU64(0x8000000080000000),
- mkU64(0x8000000080000000))));
- putWReg(wd,
- binop(Iop_OrV128,
- mkexpr(t3), mkexpr(t4)));
- break;
- }
+ case 0x1B:
+ return msa_3R_1B(cins, wd, ws);
- case 0x01: { /* FMAX_A.D */
- DIP("FMAX_A.D w%d, w%d, w%d", wd, ws, wt);
- calculateMSACSR(ws, wt, FMAXAD, 2);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- t4 = newTemp(Ity_V128);
- assign(t1,
- binop(Iop_AndV128,
- getWReg(ws),
- binop(Iop_64HLtoV128,
- mkU64(0x7FFFFFFFFFFFFFFF),
- mkU64(0x7FFFFFFFFFFFFFFF))));
- assign(t2,
- binop(Iop_AndV128,
- getWReg(wt),
- binop(Iop_64HLtoV128,
- mkU64(0x7FFFFFFFFFFFFFFF),
- mkU64(0x7FFFFFFFFFFFFFFF))));
- assign(t3,
- binop(Iop_Max64Fx2,
- mkexpr(t2), mkexpr(t1)));
- assign(t4,
- binop(Iop_AndV128,
- binop(Iop_AndV128,
- unop(Iop_NotV128,
- binop(Iop_CmpUN64Fx2,
- mkexpr(t3),
- mkexpr(t3))),
- binop(Iop_OrV128,
- binop(Iop_AndV128,
- binop(Iop_CmpEQ64Fx2,
- mkexpr(t1),
- mkexpr(t2)),
- binop(Iop_AndV128,
- getWReg(ws),
- getWReg(wt))),
- binop(Iop_OrV128,
- binop(Iop_AndV128,
- binop(Iop_OrV128,
- binop(Iop_CmpUN64Fx2,
- mkexpr(t1),
- mkexpr(t1)),
- binop(Iop_CmpLT64Fx2,
- mkexpr(t1),
- mkexpr(t3))),
- getWReg(wt)),
- binop(Iop_AndV128,
- binop(Iop_OrV128,
- binop(Iop_CmpUN64Fx2,
- mkexpr(t2),
- mkexpr(t2)),
- binop(Iop_CmpLT64Fx2,
- mkexpr(t2),
- mkexpr(t3))),
- getWReg(ws))))),
- binop(Iop_64HLtoV128,
- mkU64(0x8000000000000000),
- mkU64(0x8000000000000000))));
- putWReg(wd,
- binop(Iop_OrV128,
- mkexpr(t3), mkexpr(t4)));
- break;
- }
+ case 0x1C:
+ return msa_3R_1C(cins, wd, ws);
- default:
- return -1;
- }
+ case 0x1E:
+ if ((cins & 0x03000000) == 0)
+ return msa_VEC(cins, wd, ws);
+ else if ((cins & 0x00200000) == 0)
+ return msa_2R(cins, wd, ws);
+ else
+ return msa_2RF(cins, wd, ws);
- break;
- }
+ case 0x20:
+ return msa_MI10_load(cins, wd, ws);
- default:
- return -1;
+ case 0x24:
+ return msa_MI10_store(cins, wd, ws);
}
- return 0;
+ return -1;
}
-static Int msa_3R_1C(UInt cins, UChar wd, UChar ws) { /* 3R (0x1C) */
- IRTemp t1, t2, t3, t4, t5, t6;
- UShort operation;
- UChar df, wt;
+/*------------------------------------------------------------*/
+/*--- DSP to IR function ---*/
+/*------------------------------------------------------------*/
- operation = (cins & 0x03C00000) >> 22;
- df = (cins & 0x00200000) >> 21;
- wt = (cins & 0x001F0000) >> 16;
+extern UInt disDSPInstr_MIPS_WRK ( UInt );
- switch (operation) {
- case 0x01: { /* FCOR.df */
- switch (df) {
- case 0x00: { /* FCOR.W */
- DIP("FCOR.W w%d, w%d, w%d", wd, ws, wt);
- calculateMSACSR(ws, wt, FCORW, 2);
- putWReg(wd,
- unop(Iop_NotV128,
- binop(Iop_CmpUN32Fx4,
- getWReg(ws),
- getWReg(wt))));
- break;
- }
+/*------------------------------------------------------------*/
+/*--- Disassemble a single instruction ---*/
+/*------------------------------------------------------------*/
- case 0x01: { /* FCOR.D */
- DIP("FCOR.D w%d, w%d, w%d", wd, ws, wt);
- calculateMSACSR(ws, wt, FCORD, 2);
- putWReg(wd,
- unop(Iop_NotV128,
- binop(Iop_CmpUN64Fx2,
- getWReg(ws),
- getWReg(wt))));
- break;
- }
+/* Disassemble a single instruction into IR. The instruction is
+ located in host memory at guest_instr, and has guest IP of
+ guest_PC_curr_instr, which will have been set before the call
+ here. */
- default:
- return -1;
+
+static UInt disInstr_MIPS_WRK_Special(UInt cins, const VexArchInfo* archinfo,
+ const VexAbiInfo* abiinfo, DisResult* dres,
+ IRStmt** bstmt, IRExpr** lastn,
+ Bool(*resteerOkFn) (/*opaque */void *,
+ Addr),
+ void* callback_opaque)
+{
+ IRTemp t0, t1 = 0, t2, t3, t4, t5;
+ UInt rs, rt, rd, sa, tf, function, trap_code, imm, instr_index, rot, sel;
+ /* Additional variables for instruction fields in DSP ASE insructions */
+ UInt ac;
+
+ imm = get_imm(cins);
+ rs = get_rs(cins);
+ rt = get_rt(cins);
+ rd = get_rd(cins);
+ sa = get_sa(cins);
+ tf = get_tf(cins);
+ sel = get_sel(cins);
+ instr_index = get_instr_index(cins);
+ trap_code = get_code(cins);
+ function = get_function(cins);
+ IRType ty = mode64 ? Ity_I64 : Ity_I32;
+
+ ac = get_acNo(cins);
+
+ switch (function) {
+ case 0x00: { /* SLL */
+ DIP("sll r%u, r%u, %u", rd, rt, sa);
+ IRTemp tmpRt32 = newTemp(Ity_I32);
+ IRTemp tmpSh32 = newTemp(Ity_I32);
+ IRTemp tmpRd = newTemp(Ity_I64);
+
+ if (mode64) {
+ assign(tmpRt32, mkNarrowTo32(ty, getIReg(rt)));
+ assign(tmpSh32, binop(Iop_Shl32, mkexpr(tmpRt32), mkU8(sa)));
+ assign(tmpRd, mkWidenFrom32(ty, mkexpr(tmpSh32), True));
+ putIReg(rd, mkexpr(tmpRd));
+ } else
+ SXX_PATTERN(Iop_Shl32);
+
+ break;
+ }
+
+ case 0x01: { /* MOVCI */
+ UInt mov_cc = get_mov_cc(cins);
+
+ if (tf == 0) { /* MOVF */
+ DIP("movf r%u, r%u, %u", rd, rs, mov_cc);
+ t1 = newTemp(Ity_I1);
+ t2 = newTemp(Ity_I32);
+ t3 = newTemp(Ity_I1);
+
+ assign(t1, binop(Iop_CmpEQ32, mkU32(0), mkU32(mov_cc)));
+ assign(t2, IRExpr_ITE(mkexpr(t1),
+ binop(Iop_And32,
+ binop(Iop_Shr32, getFCSR(),
+ mkU8(23)),
+ mkU32(0x1)),
+ binop(Iop_And32,
+ binop(Iop_Shr32, getFCSR(),
+ mkU8(24 + mov_cc)),
+ mkU32(0x1))
+ ));
+ assign(t3, binop(Iop_CmpEQ32, mkU32(0), mkexpr(t2)));
+ putIReg(rd, IRExpr_ITE(mkexpr(t3), getIReg(rs), getIReg(rd)));
+ } else if (tf == 1) { /* MOVT */
+ DIP("movt r%u, r%u, %u", rd, rs, mov_cc);
+ t1 = newTemp(Ity_I1);
+ t2 = newTemp(Ity_I32);
+ t3 = newTemp(Ity_I1);
+
+ assign(t1, binop(Iop_CmpEQ32, mkU32(0), mkU32(mov_cc)));
+ assign(t2, IRExpr_ITE(mkexpr(t1),
+ binop(Iop_And32,
+ binop(Iop_Shr32, getFCSR(),
+ mkU8(23)),
+ mkU32(0x1)),
+ binop(Iop_And32,
+ binop(Iop_Shr32, getFCSR(),
+ mkU8(24 + mov_cc)),
+ mkU32(0x1))
+ ));
+ assign(t3, binop(Iop_CmpEQ32, mkU32(1), mkexpr(t2)));
+ putIReg(rd, IRExpr_ITE(mkexpr(t3), getIReg(rs), getIReg(rd)));
+ }
+
+ break;
+ }
+
+ case 0x02: { /* SRL */
+ rot = get_rot(cins);
+
+ if (rot) {
+ DIP("rotr r%u, r%u, %u", rd, rt, sa);
+ putIReg(rd, mkWidenFrom32(ty, genROR32(mkNarrowTo32(ty,
+ getIReg(rt)), sa), True));
+ } else {
+ DIP("srl r%u, r%u, %u", rd, rt, sa);
+
+ if (mode64) {
+ IRTemp tmpSh32 = newTemp(Ity_I32);
+ IRTemp tmpRt32 = newTemp(Ity_I32);
+
+ assign(tmpRt32, mkNarrowTo32(ty, getIReg(rt)));
+ assign(tmpSh32, binop(Iop_Shr32, mkexpr(tmpRt32), mkU8(sa)));
+ putIReg(rd, mkWidenFrom32(ty, mkexpr(tmpSh32), True));
+ } else {
+ SXX_PATTERN(Iop_Shr32);
}
+ }
+
+ break;
+ }
+
+ case 0x03: /* SRA */
+ DIP("sra r%u, r%u, %u", rd, rt, sa);
+
+ if (mode64) {
+ IRTemp tmpRt32 = newTemp(Ity_I32);
+ IRTemp tmpSh32 = newTemp(Ity_I32);
- break;
- }
+ t1 = newTemp(Ity_I64);
+ t2 = newTemp(Ity_I64);
+ t3 = newTemp(Ity_I64);
- case 0x02: { /* FCUNE.df */
- switch (df) {
- case 0x00: { /* FCUNE.W */
- DIP("FCUNE.W w%d, w%d, w%d", wd, ws, wt);
- calculateMSACSR(ws, wt, FCUNEW, 2);
- putWReg(wd,
- unop(Iop_NotV128,
- binop(Iop_CmpEQ32Fx4,
- getWReg(ws),
- getWReg(wt))));
- break;
- }
+ assign(t1, binop(Iop_And64, getIReg(rt), /* hi */
+ mkU64(0xFFFFFFFF00000000ULL)));
- case 0x01: { /* FCUNE.D */
- DIP("FCUNE.D w%d, w%d, w%d", wd, ws, wt);
- calculateMSACSR(ws, wt, FCUNED, 2);
- putWReg(wd,
- unop(Iop_NotV128,
- binop(Iop_CmpEQ64Fx2,
- getWReg(ws),
- getWReg(wt))));
- break;
- }
+ assign(t2, binop(Iop_Sar64, mkexpr(t1), mkU8(sa)));
- default:
- return -1;
- }
+ assign(tmpRt32, mkNarrowTo32(ty, getIReg(rt)));
+ assign(tmpSh32, binop(Iop_Sar32, mkexpr(tmpRt32), mkU8(sa)));
- break;
+ putIReg(rd, mkWidenFrom32(ty, mkexpr(tmpSh32), True));
+ } else {
+ SXX_PATTERN(Iop_Sar32);
}
- case 0x03: { /* FCNE.df */
- switch (df) {
- case 0x00: { /* FCNE.W */
- DIP("FCNE.W w%d, w%d, w%d", wd, ws, wt);
- calculateMSACSR(ws, wt, FCNEW, 2);
- putWReg(wd,
- binop(Iop_XorV128,
- unop(Iop_NotV128,
- binop(Iop_CmpEQ32Fx4,
- getWReg(ws),
- getWReg(wt))),
- binop(Iop_CmpUN32Fx4,
- getWReg(ws),
- getWReg(wt))));
- break;
- }
-
- case 0x01: { /* FCNE.D */
- DIP("FCNE.D w%d, w%d, w%d", wd, ws, wt);
- calculateMSACSR(ws, wt, FCNED, 2);
- putWReg(wd,
- binop(Iop_XorV128,
- unop(Iop_NotV128,
- binop(Iop_CmpEQ64Fx2,
- getWReg(ws),
- getWReg(wt))),
- binop(Iop_CmpUN64Fx2,
- getWReg(ws),
- getWReg(wt))));
- break;
- }
+ break;
- default:
- return -1;
- }
+ case 0x04: { /* SLLV */
+ DIP("sllv r%u, r%u, r%u", rd, rt, rs);
- break;
+ if (mode64) {
+ IRTemp tmpRs8 = newTemp(Ity_I8);
+ IRTemp tmpRt32 = newTemp(Ity_I32);
+ IRTemp tmpSh32 = newTemp(Ity_I32);
+ IRTemp tmp = newTemp(ty);
+ assign(tmp, binop(mkSzOp(ty, Iop_And8), getIReg(rs),
+ mkSzImm(ty, 31)));
+ assign(tmpRs8, mkNarrowTo8(ty, mkexpr(tmp)));
+ assign(tmpRt32, mkNarrowTo32(ty, getIReg(rt)));
+ assign(tmpSh32, binop(Iop_Shl32, mkexpr(tmpRt32), mkexpr(tmpRs8)));
+ putIReg(rd, mkWidenFrom32(ty, mkexpr(tmpSh32), True));
+ } else {
+ SXXV_PATTERN(Iop_Shl32);
}
- case 0x04: { /* MUL_Q.df */
- switch (df) {
- case 0x00: { /* MUL_Q.H */
- DIP("MUL_Q.H w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3,
- binop(Iop_QDMulHi16Sx8,
- mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ break;
+ }
- case 0x01: { /* MUL_Q.W */
- DIP("MUL_Q.W w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3,
- binop(Iop_QDMulHi32Sx4,
- mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ case 0x05: { /* LSA */
+ UInt imm2 = (imm & 0xC0) >> 6;
- default:
- return -1;
- }
+ if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps) || has_msa) {
+ DIP("lsa r%u, r%u, r%u, imm: 0x%x", rd, rs, rt, imm2);
+ if (mode64) {
+ DIP("lsa r%u, r%u, r%u, imm: 0x%x", rd, rs, rt, imm2);
+ putIReg(rd, unop(Iop_32Sto64,
+ binop(Iop_Add32,
+ binop(Iop_Shl32,
+ unop(Iop_64to32, getIReg(rs)),
+ mkU8(imm2 + 1)),
+ unop(Iop_64to32, getIReg(rt)))));
+ break;
+ } else {
+ DIP("lsa r%u, r%u, r%u, imm: 0x%x", rd, rs, rt, imm2);
+ putIReg(rd, binop(Iop_Add32,
+ binop(Iop_Shl32,
+ getIReg(rs), mkU8(imm2 + 1)), getIReg(rt)));
+ break;
+ }
+ } else {
+ ILLEGAL_INSTRUCTON;
break;
}
+ }
- case 0x05: { /* MADD_Q.df */
- switch (df) {
- case 0x00: { /* MADD_Q.W */
- DIP("MADD_Q.W w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- t4 = newTemp(Ity_V128);
- t5 = newTemp(Ity_V128);
- t6 = newTemp(Ity_V128);
- assign(t1, // even
- binop(Iop_SarN32x4,
- binop(Iop_InterleaveEvenLanes16x8,
- getWReg(ws),
- getWReg(ws)),
- mkU8(16)));
- assign(t2, // odd
- binop(Iop_SarN32x4,
- getWReg(ws), mkU8(16)));
- assign(t3, // even
- binop(Iop_SarN32x4,
- binop(Iop_InterleaveEvenLanes16x8,
- getWReg(wt),
- getWReg(wt)),
- mkU8(16)));
- assign(t4, // odd
- binop(Iop_SarN32x4,
- getWReg(wt), mkU8(16)));
- assign(t5,
- binop(Iop_Add32x4,
- binop(Iop_ShlN32x4,
- binop(Iop_SarN32x4,
- binop(Iop_InterleaveEvenLanes16x8,
- getWReg(wd),
- getWReg(wd)),
- mkU8(16)),
- mkU8(15)),
- binop(Iop_Mul32x4,
- mkexpr(t1), mkexpr(t3))));
- assign(t6,
- binop(Iop_Add32x4,
- binop(Iop_ShlN32x4,
- binop(Iop_SarN32x4,
- getWReg(wd),
- mkU8(16)),
- mkU8(15)),
- binop(Iop_Mul32x4,
- mkexpr(t2), mkexpr(t4))));
- putWReg(wd,
- binop(Iop_InterleaveEvenLanes16x8,
- binop(Iop_QandQSarNnarrow32Sto16Sx4,
- mkexpr(t6), mkU8(15)),
- binop(Iop_QandQSarNnarrow32Sto16Sx4,
- mkexpr(t5), mkU8(15))));
- break;
- }
+ case 0x06: { /* SRLV */
+ rot = get_rotv(cins);
- case 0x01: { /* MADD_Q.W */
- DIP("MADD_Q.W w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- t4 = newTemp(Ity_V128);
- t5 = newTemp(Ity_V128);
- t6 = newTemp(Ity_V128);
- assign(t1, // even
- binop(Iop_SarN64x2,
- binop(Iop_InterleaveEvenLanes32x4,
- getWReg(ws),
- getWReg(ws)),
- mkU8(32)));
- assign(t2, // odd
- binop(Iop_SarN64x2,
- getWReg(ws), mkU8(32)));
- assign(t3, // even
- binop(Iop_SarN64x2,
- binop(Iop_InterleaveEvenLanes32x4,
- getWReg(wt),
- getWReg(wt)),
- mkU8(32)));
- assign(t4, // odd
- binop(Iop_SarN64x2,
- getWReg(wt), mkU8(32)));
- assign(t5,
- binop(Iop_Add64x2,
- binop(Iop_ShlN64x2,
- binop(Iop_SarN64x2,
- binop(Iop_InterleaveEvenLanes32x4,
- getWReg(wd),
- getWReg(wd)),
- mkU8(32)),
- mkU8(31)),
- binop(Iop_64HLtoV128,
- binop(Iop_Mul64,
- unop(Iop_V128HIto64,
- mkexpr(t1)),
- unop(Iop_V128HIto64,
- mkexpr(t3))),
- binop(Iop_Mul64,
- unop(Iop_V128to64,
- mkexpr(t1)),
- unop(Iop_V128to64,
- mkexpr(t3))))));
- assign(t6,
- binop(Iop_Add64x2,
- binop(Iop_ShlN64x2,
- binop(Iop_SarN64x2,
- getWReg(wd),
- mkU8(32)),
- mkU8(31)),
- binop(Iop_64HLtoV128,
- binop(Iop_Mul64,
- unop(Iop_V128HIto64,
- mkexpr(t2)),
- unop(Iop_V128HIto64,
- mkexpr(t4))),
- binop(Iop_Mul64,
- unop(Iop_V128to64,
- mkexpr(t2)),
- unop(Iop_V128to64,
- mkexpr(t4))))));
- putWReg(wd,
- binop(Iop_InterleaveEvenLanes32x4,
- binop(Iop_QandQSarNnarrow64Sto32Sx2,
- mkexpr(t6), mkU8(31)),
- binop(Iop_QandQSarNnarrow64Sto32Sx2,
- mkexpr(t5), mkU8(31))));
- break;
- }
+ if (rot) {
+ DIP("rotrv r%u, r%u, r%u", rd, rt, rs);
+ putIReg(rd, mkWidenFrom32(ty, genRORV32(mkNarrowTo32(ty,
+ getIReg(rt)), mkNarrowTo32(ty, getIReg(rs))), True));
+ break;
+ } else { /* SRLV */
+ DIP("srlv r%u, r%u, r%u", rd, rt, rs);
- default:
- return -1;
+ if (mode64) {
+ SXXV_PATTERN64(Iop_Shr32);
+ } else {
+ SXXV_PATTERN(Iop_Shr32);
}
break;
}
+ }
- case 0x06: { /* MSUB_Q.df */
- switch (df) {
- case 0x00: { /* MSUB_Q.H */
- DIP("MSUB_Q.H w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- t4 = newTemp(Ity_V128);
- t5 = newTemp(Ity_V128);
- t6 = newTemp(Ity_V128);
- assign(t1, // even
- binop(Iop_SarN32x4,
- binop(Iop_InterleaveEvenLanes16x8,
- getWReg(ws),
- getWReg(ws)),
- mkU8(16)));
- assign(t2, // odd
- binop(Iop_SarN32x4,
- getWReg(ws), mkU8(16)));
- assign(t3, // even
- binop(Iop_SarN32x4,
- binop(Iop_InterleaveEvenLanes16x8,
- getWReg(wt),
- getWReg(wt)),
- mkU8(16)));
- assign(t4, // odd
- binop(Iop_SarN32x4,
- getWReg(wt), mkU8(16)));
- assign(t5,
- binop(Iop_Sub32x4,
- binop(Iop_ShlN32x4,
- binop(Iop_SarN32x4,
- binop(Iop_InterleaveEvenLanes16x8,
- getWReg(wd),
- getWReg(wd)),
- mkU8(16)),
- mkU8(15)),
- binop(Iop_Mul32x4,
- mkexpr(t1), mkexpr(t3))));
- assign(t6,
- binop(Iop_Sub32x4,
- binop(Iop_ShlN32x4,
- binop(Iop_SarN32x4,
- getWReg(wd),
- mkU8(16)),
- mkU8(15)),
- binop(Iop_Mul32x4,
- mkexpr(t2), mkexpr(t4))));
- putWReg(wd,
- binop(Iop_InterleaveEvenLanes16x8,
- binop(Iop_QandQSarNnarrow32Sto16Sx4,
- mkexpr(t6), mkU8(15)),
- binop(Iop_QandQSarNnarrow32Sto16Sx4,
- mkexpr(t5), mkU8(15))));
- break;
- }
+ case 0x07: /* SRAV */
+ DIP("srav r%u, r%u, r%u", rd, rt, rs);
- case 0x01: { /* MSUB_Q.W */
- DIP("MSUB_Q.W w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- t4 = newTemp(Ity_V128);
- t5 = newTemp(Ity_V128);
- t6 = newTemp(Ity_V128);
- assign(t1, // even
- binop(Iop_SarN64x2,
- binop(Iop_InterleaveEvenLanes32x4,
- getWReg(ws),
- getWReg(ws)),
- mkU8(32)));
- assign(t2, // odd
- binop(Iop_SarN64x2,
- getWReg(ws), mkU8(32)));
- assign(t3, // even
- binop(Iop_SarN64x2,
- binop(Iop_InterleaveEvenLanes32x4,
- getWReg(wt),
- getWReg(wt)),
- mkU8(32)));
- assign(t4, // odd
- binop(Iop_SarN64x2,
- getWReg(wt), mkU8(32)));
- assign(t5,
- binop(Iop_Sub64x2,
- binop(Iop_ShlN64x2,
- binop(Iop_SarN64x2,
- binop(Iop_InterleaveEvenLanes32x4,
- getWReg(wd),
- getWReg(wd)),
- mkU8(32)),
- mkU8(31)),
- binop(Iop_64HLtoV128,
- binop(Iop_Mul64,
- unop(Iop_V128HIto64,
- mkexpr(t1)),
- unop(Iop_V128HIto64,
- mkexpr(t3))),
- binop(Iop_Mul64,
- unop(Iop_V128to64,
- mkexpr(t1)),
- unop(Iop_V128to64,
- mkexpr(t3))))));
- assign(t6,
- binop(Iop_Sub64x2,
- binop(Iop_ShlN64x2,
- binop(Iop_SarN64x2,
- getWReg(wd),
- mkU8(32)),
- mkU8(31)),
- binop(Iop_64HLtoV128,
- binop(Iop_Mul64,
- unop(Iop_V128HIto64,
- mkexpr(t2)),
- unop(Iop_V128HIto64,
- mkexpr(t4))),
- binop(Iop_Mul64,
- unop(Iop_V128to64,
- mkexpr(t2)),
- unop(Iop_V128to64,
- mkexpr(t4))))));
- putWReg(wd,
- binop(Iop_InterleaveEvenLanes32x4,
- binop(Iop_QandQSarNnarrow64Sto32Sx2,
- mkexpr(t6), mkU8(31)),
- binop(Iop_QandQSarNnarrow64Sto32Sx2,
- mkexpr(t5), mkU8(31))));
- break;
- }
+ if (mode64) {
+ IRTemp tmpRt32 = newTemp(Ity_I32);
+ IRTemp tmpSh32 = newTemp(Ity_I32);
- default:
- return -1;
- }
+ t1 = newTemp(Ity_I64);
+ t2 = newTemp(Ity_I64);
+ t3 = newTemp(Ity_I64);
+ t4 = newTemp(Ity_I8);
- break;
- }
+ assign(t4, unop(Iop_32to8, binop(Iop_And32,
+ mkNarrowTo32(ty, getIReg(rs)), mkU32(0x0000001F))));
- case 0x09: { /* FSOR.df */
- switch (df) {
- case 0x00: { /* FSOR.W */
- DIP("FSOR.W w%d, w%d, w%d", wd, ws, wt);
- calculateMSACSR(ws, wt, FSORW, 2);
- putWReg(wd,
- unop(Iop_NotV128,
- binop(Iop_CmpUN32Fx4,
- getWReg(ws),
- getWReg(wt))));
- break;
- }
+ assign(t1, binop(Iop_And64, getIReg(rt), /* hi */
+ mkU64(0xFFFFFFFF00000000ULL)));
- case 0x01: { /* FSOR.D */
- DIP("FSOR.D w%d, w%d, w%d", wd, ws, wt);
- calculateMSACSR(ws, wt, FSORD, 2);
- putWReg(wd,
- unop(Iop_NotV128,
- binop(Iop_CmpUN64Fx2,
- getWReg(ws),
- getWReg(wt))));
- break;
- }
+ assign(t2, binop(Iop_Sar64, mkexpr(t1), mkexpr(t4)));
- default:
- return -1;
- }
+ assign(tmpRt32, mkNarrowTo32(ty, getIReg(rt)));
+ assign(tmpSh32, binop(Iop_Sar32, mkexpr(tmpRt32), mkexpr(t4)));
- break;
+ putIReg(rd, mkWidenFrom32(ty, mkexpr(tmpSh32), True));
+ } else {
+ SXXV_PATTERN(Iop_Sar32);
}
- case 0x0A: { /* FSUNE.df */
- switch (df) {
- case 0x00: { /* FSUNE.W */
- DIP("FSUNE.W w%d, w%d, w%d", wd, ws, wt);
- calculateMSACSR(ws, wt, FSUNEW, 2);
- putWReg(wd,
- unop(Iop_NotV128,
- binop(Iop_CmpEQ32Fx4,
- getWReg(ws),
- getWReg(wt))));
- break;
- }
+ break;
- case 0x01: { /* FSUNE.D */
- DIP("FSUNE.D w%d, w%d, w%d", wd, ws, wt);
- calculateMSACSR(ws, wt, FSUNED, 2);
- putWReg(wd,
- unop(Iop_NotV128,
- binop(Iop_CmpEQ64Fx2,
- getWReg(ws),
- getWReg(wt))));
- break;
- }
+ case 0x08: /* JR */
+ DIP("jr r%u", rs);
+ t0 = newTemp(ty);
+ assign(t0, getIReg(rs));
+ *lastn = mkexpr(t0);
+ break;
- default:
- return -1;
- }
+ case 0x09: /* JALR */
+ DIP("jalr r%u r%u", rd, rs);
- break;
+ if (mode64) {
+ putIReg(rd, mkU64(guest_PC_curr_instr + 8));
+ t0 = newTemp(Ity_I64);
+ assign(t0, getIReg(rs));
+ *lastn = mkexpr(t0);
+ } else {
+ putIReg(rd, mkU32(guest_PC_curr_instr + 8));
+ t0 = newTemp(Ity_I32);
+ assign(t0, getIReg(rs));
+ *lastn = mkexpr(t0);
}
- case 0x0B: { /* FSNE.df */
- switch (df) {
- case 0x00: { /* FSNE.W */
- DIP("FSNE.W w%d, w%d, w%d", wd, ws, wt);
- calculateMSACSR(ws, wt, FSNEW, 2);
- putWReg(wd,
- binop(Iop_XorV128,
- unop(Iop_NotV128,
- binop(Iop_CmpEQ32Fx4,
- getWReg(ws),
- getWReg(wt))),
- binop(Iop_CmpUN32Fx4,
- getWReg(ws),
- getWReg(wt))));
- break;
- }
+ break;
- case 0x01: { /* FSNE.D */
- DIP("FSNE.D w%d, w%d, w%d", wd, ws, wt);
- calculateMSACSR(ws, wt, FSNED, 2);
- putWReg(wd,
- binop(Iop_XorV128,
- unop(Iop_NotV128,
- binop(Iop_CmpEQ64Fx2,
- getWReg(ws),
- getWReg(wt))),
- binop(Iop_CmpUN64Fx2,
- getWReg(ws),
- getWReg(wt))));
- break;
- }
+ case 0x0A: { /* MOVZ */
+ DIP("movz r%u, r%u, r%u", rd, rs, rt);
+ t1 = newTemp(ty);
+ t2 = newTemp(ty);
- default:
- return -1;
- }
+ if (mode64) {
+ assign(t1, unop(Iop_32Sto64, unop(Iop_1Sto32, binop(Iop_CmpEQ64,
+ getIReg(rt), mkU64(0x0)))));
+ assign(t2, unop(Iop_32Sto64, unop(Iop_1Sto32, binop(Iop_CmpNE64,
+ getIReg(rt), mkU64(0x0)))));
+ putIReg(rd, binop(Iop_Add64, binop(Iop_And64, getIReg(rs),
+ mkexpr(t1)), binop(Iop_And64, getIReg(rd), mkexpr(t2))));
+ } else {
+ assign(t1, unop(Iop_1Sto32, binop(Iop_CmpEQ32, getIReg(rt),
+ mkU32(0x0))));
+ assign(t2, unop(Iop_1Sto32, binop(Iop_CmpNE32, getIReg(rt),
+ mkU32(0x0))));
+ putIReg(rd, binop(Iop_Add32, binop(Iop_And32, getIReg(rs),
+ mkexpr(t1)), binop(Iop_And32, getIReg(rd),
+ mkexpr(t2))));
+ }
- break;
+ break;
+ }
+
+ case 0x0B: { /* MOVN */
+ DIP("movn r%u, r%u, r%u", rd, rs, rt);
+ t1 = newTemp(ty);
+ t2 = newTemp(ty);
+
+ if (mode64) {
+ assign(t1, unop(Iop_32Sto64, unop(Iop_1Sto32, binop(Iop_CmpEQ64,
+ getIReg(rt), mkU64(0x0)))));
+ assign(t2, unop(Iop_32Sto64, unop(Iop_1Sto32, binop(Iop_CmpNE64,
+ getIReg(rt), mkU64(0x0)))));
+ putIReg(rd, binop(Iop_Add64, binop(Iop_And64, getIReg(rs),
+ mkexpr(t2)), binop(Iop_And64, getIReg(rd),
+ mkexpr(t1))));
+ } else {
+ assign(t1, unop(Iop_1Sto32, binop(Iop_CmpEQ32, getIReg(rt),
+ mkU32(0x0))));
+ assign(t2, unop(Iop_1Sto32, binop(Iop_CmpNE32, getIReg(rt),
+ mkU32(0x0))));
+ putIReg(rd, binop(Iop_Add32, binop(Iop_And32, getIReg(rs),
+ mkexpr(t2)), binop(Iop_And32, getIReg(rd),
+ mkexpr(t1))));
}
- case 0x0C: { /* MULR_Q.df */
- switch (df) {
- case 0x00: { /* MULR_Q.H */
- DIP("MULR_Q.H w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3, binop(Iop_QRDMulHi16Sx8,
- mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ break;
+ }
- case 0x01: { /* MULR_Q.W */
- DIP("MULR_Q.W w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3, binop(Iop_QRDMulHi32Sx4,
- mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ case 0x0C: /* SYSCALL */
+ DIP("syscall");
- default:
- return -1;
- }
+ if (mode64)
+ putPC(mkU64(guest_PC_curr_instr + 4));
+ else
+ putPC(mkU32(guest_PC_curr_instr + 4));
- break;
- }
+ dres->jk_StopHere = Ijk_Sys_syscall;
+ dres->whatNext = Dis_StopHere;
+ break;
- case 0x0D: { /* MADDR_Q.df */
- switch (df) {
- case 0x00: { /* MADDR_Q.W */
- DIP("MADDR_Q.W w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- t4 = newTemp(Ity_V128);
- t5 = newTemp(Ity_V128);
- t6 = newTemp(Ity_V128);
- assign(t1, // even
- binop(Iop_SarN32x4,
- binop(Iop_InterleaveEvenLanes16x8,
- getWReg(ws),
- getWReg(ws)),
- mkU8(16)));
- assign(t2, // odd
- binop(Iop_SarN32x4,
- getWReg(ws), mkU8(16)));
- assign(t3, // even
- binop(Iop_SarN32x4,
- binop(Iop_InterleaveEvenLanes16x8,
- getWReg(wt),
- getWReg(wt)),
- mkU8(16)));
- assign(t4, // odd
- binop(Iop_SarN32x4,
- getWReg(wt), mkU8(16)));
- assign(t5,
- binop(Iop_Add32x4,
- binop(Iop_ShlN32x4,
- binop(Iop_SarN32x4,
- binop(Iop_InterleaveEvenLanes16x8,
- getWReg(wd),
- getWReg(wd)),
- mkU8(16)),
- mkU8(15)),
- binop(Iop_Mul32x4,
- mkexpr(t1), mkexpr(t3))));
- assign(t6,
- binop(Iop_Add32x4,
- binop(Iop_ShlN32x4,
- binop(Iop_SarN32x4,
- getWReg(wd),
- mkU8(16)),
- mkU8(15)),
- binop(Iop_Mul32x4,
- mkexpr(t2), mkexpr(t4))));
- putWReg(wd,
- binop(Iop_InterleaveEvenLanes16x8,
- binop(Iop_QandQRSarNnarrow32Sto16Sx4,
- mkexpr(t6), mkU8(15)),
- binop(Iop_QandQRSarNnarrow32Sto16Sx4,
- mkexpr(t5), mkU8(15))));
- break;
- }
+ case 0x0D: /* BREAK */
+ DIP("break 0x%x", trap_code);
- case 0x01: { /* MADDR_Q.D */
- DIP("MADDR_Q.D w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- t4 = newTemp(Ity_V128);
- t5 = newTemp(Ity_V128);
- t6 = newTemp(Ity_V128);
- assign(t1, // even
- binop(Iop_SarN64x2,
- binop(Iop_InterleaveEvenLanes32x4,
- getWReg(ws),
- getWReg(ws)),
- mkU8(32)));
- assign(t2, // odd
- binop(Iop_SarN64x2,
- getWReg(ws), mkU8(32)));
- assign(t3, // even
- binop(Iop_SarN64x2,
- binop(Iop_InterleaveEvenLanes32x4,
- getWReg(wt),
- getWReg(wt)),
- mkU8(32)));
- assign(t4, // odd
- binop(Iop_SarN64x2,
- getWReg(wt), mkU8(32)));
- assign(t5,
- binop(Iop_Add64x2,
- binop(Iop_ShlN64x2,
- binop(Iop_SarN64x2,
- binop(Iop_InterleaveEvenLanes32x4,
- getWReg(wd),
- getWReg(wd)),
- mkU8(32)),
- mkU8(31)),
- binop(Iop_64HLtoV128,
- binop(Iop_Mul64,
- unop(Iop_V128HIto64,
- mkexpr(t1)),
- unop(Iop_V128HIto64,
- mkexpr(t3))),
- binop(Iop_Mul64,
- unop(Iop_V128to64,
- mkexpr(t1)),
- unop(Iop_V128to64,
- mkexpr(t3))))));
- assign(t6,
- binop(Iop_Add64x2,
- binop(Iop_ShlN64x2,
- binop(Iop_SarN64x2,
- getWReg(wd),
- mkU8(32)),
- mkU8(31)),
- binop(Iop_64HLtoV128,
- binop(Iop_Mul64,
- unop(Iop_V128HIto64,
- mkexpr(t2)),
- unop(Iop_V128HIto64,
- mkexpr(t4))),
- binop(Iop_Mul64,
- unop(Iop_V128to64,
- mkexpr(t2)),
- unop(Iop_V128to64,
- mkexpr(t4))))));
- putWReg(wd,
- binop(Iop_InterleaveEvenLanes32x4,
- binop(Iop_QandQRSarNnarrow64Sto32Sx2,
- mkexpr(t6), mkU8(31)),
- binop(Iop_QandQRSarNnarrow64Sto32Sx2,
- mkexpr(t5), mkU8(31))));
- break;
- }
+ if (mode64)
+ jmp_lit64(dres, Ijk_SigTRAP, (guest_PC_curr_instr + 4));
+ else
+ jmp_lit32(dres, Ijk_SigTRAP, (guest_PC_curr_instr + 4));
- default:
- return -1;
- }
+ vassert(dres->whatNext == Dis_StopHere);
+ break;
- break;
- }
+ case 0x0F: /* SYNC */
+ DIP("sync 0x%x", sel);
+ /* Just ignore it. */
+ break;
- case 0x0E: { /* MSUBR_Q.df */
- switch (df) {
- case 0x00: { /* MSUBR_Q.W */
- DIP("MSUBR_Q.W w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- t4 = newTemp(Ity_V128);
- t5 = newTemp(Ity_V128);
- t6 = newTemp(Ity_V128);
- assign(t1, // even
- binop(Iop_SarN32x4,
- binop(Iop_InterleaveEvenLanes16x8,
- getWReg(ws),
- getWReg(ws)),
- mkU8(16)));
- assign(t2, // odd
- binop(Iop_SarN32x4,
- getWReg(ws), mkU8(16)));
- assign(t3, // even
- binop(Iop_SarN32x4,
- binop(Iop_InterleaveEvenLanes16x8,
- getWReg(wt),
- getWReg(wt)),
- mkU8(16)));
- assign(t4, // odd
- binop(Iop_SarN32x4,
- getWReg(wt), mkU8(16)));
- assign(t5,
- binop(Iop_Sub32x4,
- binop(Iop_ShlN32x4,
- binop(Iop_SarN32x4,
- binop(Iop_InterleaveEvenLanes16x8,
- getWReg(wd),
- getWReg(wd)),
- mkU8(16)),
- mkU8(15)),
- binop(Iop_Mul32x4,
- mkexpr(t1), mkexpr(t3))));
- assign(t6,
- binop(Iop_Sub32x4,
- binop(Iop_ShlN32x4,
- binop(Iop_SarN32x4,
- getWReg(wd),
- mkU8(16)),
- mkU8(15)),
- binop(Iop_Mul32x4,
- mkexpr(t2), mkexpr(t4))));
- putWReg(wd,
- binop(Iop_InterleaveEvenLanes16x8,
- binop(Iop_QandQRSarNnarrow32Sto16Sx4,
- mkexpr(t6), mkU8(15)),
- binop(Iop_QandQRSarNnarrow32Sto16Sx4,
- mkexpr(t5), mkU8(15))));
- break;
- }
+ case 0x10: { /* MFHI, CLZ R6 */
+ if (((instr_index >> 6) & 0x1f) == 1) { /* CLZ */
+ if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+ DIP("clz r%u, r%u", rd, rs);
- case 0x01: { /* MSUBR_Q.D */
- DIP("MSUBR_Q.D w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- t4 = newTemp(Ity_V128);
- t5 = newTemp(Ity_V128);
- t6 = newTemp(Ity_V128);
- assign(t1, // even
- binop(Iop_SarN64x2,
- binop(Iop_InterleaveEvenLanes32x4,
- getWReg(ws),
- getWReg(ws)),
- mkU8(32)));
- assign(t2, // odd
- binop(Iop_SarN64x2,
- getWReg(ws), mkU8(32)));
- assign(t3, // even
- binop(Iop_SarN64x2,
- binop(Iop_InterleaveEvenLanes32x4,
- getWReg(wt),
- getWReg(wt)),
- mkU8(32)));
- assign(t4, // odd
- binop(Iop_SarN64x2,
- getWReg(wt), mkU8(32)));
- assign(t5,
- binop(Iop_Sub64x2,
- binop(Iop_ShlN64x2,
- binop(Iop_SarN64x2,
- binop(Iop_InterleaveEvenLanes32x4,
- getWReg(wd),
- getWReg(wd)),
- mkU8(32)),
- mkU8(31)),
- binop(Iop_64HLtoV128,
- binop(Iop_Mul64,
- unop(Iop_V128HIto64,
- mkexpr(t1)),
- unop(Iop_V128HIto64,
- mkexpr(t3))),
- binop(Iop_Mul64,
- unop(Iop_V128to64,
- mkexpr(t1)),
- unop(Iop_V128to64,
- mkexpr(t3))))));
- assign(t6,
- binop(Iop_Sub64x2,
- binop(Iop_ShlN64x2,
- binop(Iop_SarN64x2,
- getWReg(wd),
- mkU8(32)),
- mkU8(31)),
- binop(Iop_64HLtoV128,
- binop(Iop_Mul64,
- unop(Iop_V128HIto64,
- mkexpr(t2)),
- unop(Iop_V128HIto64,
- mkexpr(t4))),
- binop(Iop_Mul64,
- unop(Iop_V128to64,
- mkexpr(t2)),
- unop(Iop_V128to64,
- mkexpr(t4))))));
- putWReg(wd,
- binop(Iop_InterleaveEvenLanes32x4,
- binop(Iop_QandQRSarNnarrow64Sto32Sx2,
- mkexpr(t6), mkU8(31)),
- binop(Iop_QandQRSarNnarrow64Sto32Sx2,
- mkexpr(t5), mkU8(31))));
- break;
- }
+ if (mode64) {
+ IRTemp tmpClz32 = newTemp(Ity_I32);
+ IRTemp tmpRs32 = newTemp(Ity_I32);
- default:
- return -1;
+ assign(tmpRs32, mkNarrowTo32(ty, getIReg(rs)));
+ assign(tmpClz32, unop(Iop_Clz32, mkexpr(tmpRs32)));
+ putIReg(rd, mkWidenFrom32(ty, mkexpr(tmpClz32), True));
+ } else {
+ t1 = newTemp(Ity_I1);
+ assign(t1, binop(Iop_CmpEQ32, getIReg(rs), mkU32(0)));
+ putIReg(rd, IRExpr_ITE(mkexpr(t1),
+ mkU32(0x00000020),
+ unop(Iop_Clz32, getIReg(rs))));
+ }
+ } else {
+ ILLEGAL_INSTRUCTON;
}
break;
- }
+ } else if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
+ /* If DSP is present -> DSP ASE MFHI */
+ UInt retVal = disDSPInstr_MIPS_WRK ( cins );
- default:
- return -1;
- }
+ if (0 != retVal ) {
+ return -1;
+ }
- return 0;
-}
+ break;
+ } else {
+ DIP("mfhi r%u", rd);
+ putIReg(rd, getHI());
+ break;
+ }
+ }
-static Int msa_ELM(UInt cins, UChar wd, UChar ws) { /* ELM (0x19) */
- IRTemp t1, t2, t3, t4, t5;
- IRType ty;
- UShort operation;
- UChar df, n;
+ case 0x11: { /* MTHI, CLO R6 */
+ if (((instr_index >> 6) & 0x1f) == 1) { /* CLO */
+ if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+ DIP("clo r%u, r%u", rd, rs);
- operation = (cins & 0x03C00000) >> 22;
- ty = mode64 ? Ity_I64 : Ity_I32;
+ if (mode64) {
+ IRTemp tmpClo32 = newTemp(Ity_I32);
+ IRTemp tmpRs32 = newTemp(Ity_I32);
+ assign(tmpRs32, mkNarrowTo32(ty, getIReg(rs)));
- switch ((cins & 0x03FF0000) >> 16) {
- case 0x07E: /* CFCMSA */
- DIP("CFCMSA r%d, c%d", wd, ws);
+ t1 = newTemp(Ity_I1);
+ assign(t1, binop(Iop_CmpEQ32, mkexpr(tmpRs32), mkU32(0xffffffff)));
+ assign(tmpClo32, IRExpr_ITE(mkexpr(t1),
+ mkU32(0x00000020),
+ unop(Iop_Clz32, unop(Iop_Not32, mkexpr(tmpRs32)))));
- switch (ws) {
- case 0: { /* MSAIR */
- IRDirty *d;
- t1 = newTemp(Ity_I32);
- /* IRExpr_BBPTR() =>
- Need to pass pointer to
- guest state to helper. */
- d = unsafeIRDirty_1_N(t1, 0,
- "mips_dirtyhelper_get_MSAIR",
- &mips_dirtyhelper_get_MSAIR,
- mkIRExprVec_0());
- /* d->nFxState = 0; */
- stmt(IRStmt_Dirty(d));
- putIReg(wd,
- mkWidenFrom32(ty, mkexpr(t1), True));
+ putIReg(rd, mkWidenFrom32(ty, mkexpr(tmpClo32), True));
break;
+ } else {
+ t1 = newTemp(Ity_I1);
+ assign(t1, binop(Iop_CmpEQ32, getIReg(rs), mkU32(0xffffffff)));
+ putIReg(rd, IRExpr_ITE(mkexpr(t1),
+ mkU32(0x00000020),
+ unop(Iop_Clz32,
+ unop(Iop_Not32, getIReg(rs)))));
}
+ } else {
+ ILLEGAL_INSTRUCTON;
+ }
- case 1: /* MSACSR */
- putIReg(wd,
- mkWidenFrom32(ty, getMSACSR(), True));
- break;
+ break;
+ } else if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
+ /* If DSP is present -> DSP ASE MTHI */
+ UInt retVal = disDSPInstr_MIPS_WRK ( cins );
- default:
- putIReg(wd,
- mkWidenFrom32(ty, mkU32(0), False));
- break;
- }
+ if (0 != retVal ) {
+ return -1;
+ }
- break;
+ break;
+ } else {
+ DIP("mthi r%u", rs);
+ putHI(getIReg(rs));
+ break;
+ }
+ }
- case 0x03E: /* CTCMSA */
- DIP("CTCMSA r%d, c%d", ws, wd);
+ case 0x12: { /* MFLO */
+ if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
+ /* If DSP is present -> DSP ASE MFLO */
+ UInt retVal = disDSPInstr_MIPS_WRK ( cins );
- if (wd == 1) { /* MSACSR */
- putMSACSR(
- binop(Iop_And32, mkNarrowTo32(ty, getIReg(ws)),
- mkU32(0x1FFFFFF)));
- }
+ if (0 != retVal ) {
+ return -1;
+ }
- break;
+ break;
+ } else {
+ switch (sa) {
+ case 0:
+ DIP("mflo r%u", rd);
- case 0x0BE: /* MOVE.V */
- DIP("MOVE.V w%d, w%d", ws, wd);
- putWReg(wd, getWReg(ws));
- break;
+ if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps) &&
+ !VEX_MIPS_CPU_HAS_MIPS32R2(archinfo->hwcaps)) {
+ ILLEGAL_INSTRUCTON
+ }
- default:
- df = (cins & 0x003F0000) >> 16;
- if ((df & 0x38) == 0x38) { // 11100n; dw
- n = df & 0x01;
- df = 0x38;
- } else if ((df & 0x30) == 0x30) { // 1100nn; w
- n = df & 0x03;
- df = 0x30;
- } else if ((df & 0x20) == 0x20) { // 100nnn; hw
- n = df & 0x07;
- df = 0x20;
- } else if ((df & 0x00) == 0x00) { // 00nnnn; b
- n = df & 0x0F;
- df = 0x00;
- }
+ putIReg(rd, getLO());
+ break;
- switch (operation) {
- case 0x00: /* SLDI.df */
- switch (df) {
- case 0x00: /* SLDI.B */
- DIP("SLDI.B w%d, w%d[%d]", wd, ws, n);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- assign(t1,
- binop(Iop_ShrV128,
- getWReg(ws),
- mkU8(n << 3)));
- assign(t2,
- binop(Iop_ShlV128,
- getWReg(wd),
- mkU8(n ?
- (16 - n) << 3 : 0)));
- putWReg(wd,
- binop(Iop_OrV128, mkexpr(t1), mkexpr(t2)));
- break;
+ case 1:
+ DIP("dclz r%u, r%u", rd, rs);
+ t1 = newTemp(Ity_I1);
+ assign(t1, binop(Iop_CmpEQ64, getIReg(rs), mkU64(0)));
+ putIReg(rd, IRExpr_ITE(mkexpr(t1),
+ mkU64(0x00000040),
+ unop(Iop_Clz64, getIReg(rs))));
+ break;
+ }
- case 0x20: /* SLDI.H */
- DIP("SLDI.H w%d, w%d[%d]", wd, ws, n);
+ break;
+ }
+ }
- if (n == 0) {
- putWReg(wd, getWReg(ws));
- } else {
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- assign(t1,
- binop(Iop_ShrN64x2,
- getWReg(ws),
- mkU8(n << 3)));
- assign(t2,
- binop(Iop_ShlN64x2,
- getWReg(wd),
- mkU8((8 - n) << 3)));
- putWReg(wd,
- binop(Iop_OrV128,
- mkexpr(t1),
- mkexpr(t2)));
- }
+ case 0x13: { /* MTLO */
+ if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
+ /* If DSP is present -> DSP ASE MTLO */
+ UInt retVal = disDSPInstr_MIPS_WRK ( cins );
- break;
+ if (0 != retVal ) {
+ return -1;
+ }
- case 0x30: /* SLDI.W */
- DIP("SLDI.W w%d, w%d[%d]", wd, ws, n);
+ break;
+ } else {
+ switch (sa) {
+ case 0:
+ DIP("mtlo r%u", rs);
- if (n == 0) {
- putWReg(wd, getWReg(ws));
- } else {
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- assign(t1,
- binop(Iop_ShrN32x4,
- getWReg(ws),
- mkU8(n << 3)));
- assign(t2,
- binop(Iop_ShlN32x4,
- getWReg(wd),
- mkU8((4 - n) << 3)));
- putWReg(wd,
- binop(Iop_OrV128,
- mkexpr(t1),
- mkexpr(t2)));
- }
+ if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps) &&
+ !VEX_MIPS_CPU_HAS_MIPS32R2(archinfo->hwcaps)) {
+ ILLEGAL_INSTRUCTON
+ }
- break;
+ putLO(getIReg(rs));
+ break;
- case 0x38: /* SLDI.D */
- DIP("SLDI.D w%d, w%d[%d]", wd, ws, n);
+ case 1:
+ DIP("dclo r%u, r%u", rd, rs);
+ t1 = newTemp(Ity_I1);
+ assign(t1, binop(Iop_CmpEQ64, getIReg(rs),
+ mkU64(0xffffffffffffffffULL)));
+ putIReg(rd, IRExpr_ITE(mkexpr(t1),
+ mkU64(0x40),
+ unop(Iop_Clz64, unop(Iop_Not64,
+ getIReg(rs)))));
+ break;
+ }
- if (n == 0) {
- putWReg(wd, getWReg(ws));
- } else {
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- assign(t1,
- binop(Iop_ShrN16x8,
- getWReg(ws),
- mkU8(n << 3)));
- assign(t2,
- binop(Iop_ShlN16x8,
- getWReg(wd),
- mkU8((2 - n) << 3)));
- putWReg(wd,
- binop(Iop_OrV128,
- mkexpr(t1),
- mkexpr(t2)));
- }
+ break;
+ }
+ }
- break;
+ case 0x15: { /* DLSA */
+ UInt imm2 = (imm & 0xC0) >> 6;
- default:
- return -1;
- }
+ if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps) || has_msa) {
+ DIP("dlsa r%u, r%u, r%u, imm: 0x%x", rd, rs, rt, imm2);
+ putIReg(rd, binop(Iop_Add64,
+ binop(Iop_Shl64, getIReg(rs), mkU8(imm2 + 1)),
+ getIReg(rt)));
+ } else {
+ ILLEGAL_INSTRUCTON
+ }
- break;
+ break;
+ }
- case 0x01: /* SPLATI.df */
- switch (df) {
- case 0x00: { /* SPLATI.B */
- DIP("SPLATI.B w%d, w%d[%d]", wd, ws, n);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- t4 = newTemp(Ity_V128);
+ case 0x18: { /* MULT */
+ switch (sa & 0x3) {
+ case 0: {
+ if ((1 <= ac) && ( 3 >= ac)) {
+ if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
+ /* If DSP is present -> DSP ASE MULT */
+ UInt retVal = disDSPInstr_MIPS_WRK(cins);
- if (n & 1)
- assign(t1,
- binop(Iop_InterleaveOddLanes8x16,
- getWReg(ws),
- getWReg(ws)));
- else
- assign(t1,
- binop(Iop_InterleaveEvenLanes8x16,
- getWReg(ws),
- getWReg(ws)));
+ if (0 != retVal) {
+ return -2;
+ }
- n /= 2;
+ break;
+ } else {
+ return -2;
+ }
+ } else {
+ DIP("mult r%u, r%u", rs, rt);
- if (n & 1)
- assign(t2,
- binop(Iop_InterleaveOddLanes16x8,
- mkexpr(t1), mkexpr(t1)));
- else
- assign(t2,
- binop(Iop_InterleaveEvenLanes16x8,
- mkexpr(t1), mkexpr(t1)));
+ if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps) &&
+ !VEX_MIPS_CPU_HAS_MIPS32R2(archinfo->hwcaps)) {
+ ILLEGAL_INSTRUCTON
+ }
- n /= 2;
+ t2 = newTemp(Ity_I64);
- if (n & 1)
- assign(t3,
- binop(Iop_InterleaveOddLanes32x4,
- mkexpr(t2), mkexpr(t2)));
- else
- assign(t3,
- binop(Iop_InterleaveEvenLanes32x4,
- mkexpr(t2), mkexpr(t2)));
+ assign(t2, binop(Iop_MullS32, mkNarrowTo32(ty, getIReg(rs)),
+ mkNarrowTo32(ty, getIReg(rt))));
- n /= 2;
+ putHI(mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(t2)), True));
+ putLO(mkWidenFrom32(ty, unop(Iop_64to32, mkexpr(t2)), True));
+ break;
+ }
+ }
- if (n & 1)
- assign(t4,
- binop(Iop_InterleaveHI64x2,
- mkexpr(t3), mkexpr(t3)));
- else
- assign(t4,
- binop(Iop_InterleaveLO64x2,
- mkexpr(t3), mkexpr(t3)));
+ case 2: { /* MUL R6 */
+ if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+ DIP("mul r%u, r%u, r%u", rs, rt, rd);
- putWReg(wd, mkexpr(t4));
- break;
- }
+ if (mode64) {
+ putIReg(rd, unop(Iop_32Sto64,
+ unop(Iop_64to32,
+ binop(Iop_MullS32,
+ unop(Iop_64to32, getIReg(rs)),
+ unop(Iop_64to32, getIReg(rt))))));
+ } else {
+ putIReg(rd, unop(Iop_64to32,
+ binop(Iop_MullS32,
+ getIReg(rs), getIReg(rt))));
+ }
+ } else {
+ ILLEGAL_INSTRUCTON;
+ }
- case 0x20: { /* SPLATI.H */
- DIP("SPLATI.H w%d, w%d[%d]", wd, ws, n);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
+ break;
+ }
- if (n & 1)
- assign(t1,
- binop(Iop_InterleaveOddLanes16x8,
- getWReg(ws),
- getWReg(ws)));
- else
- assign(t1,
- binop(Iop_InterleaveEvenLanes16x8,
- getWReg(ws),
- getWReg(ws)));
+ case 3: { /* MUH R6 */
+ if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+ DIP("muh r%u, r%u, r%u", rs, rt, rd);
- n /= 2;
+ if (mode64) {
+ putIReg(rd, unop(Iop_32Sto64,
+ unop(Iop_64HIto32,
+ binop(Iop_MullS32,
+ unop(Iop_64to32, getIReg(rs)),
+ unop(Iop_64to32, getIReg(rt))))));
+ } else {
+ putIReg(rd, unop(Iop_64HIto32,
+ binop(Iop_MullS32,
+ getIReg(rs), getIReg(rt))));
+ }
+ } else {
+ ILLEGAL_INSTRUCTON;
+ }
- if (n & 1)
- assign(t2,
- binop(Iop_InterleaveOddLanes32x4,
- mkexpr(t1), mkexpr(t1)));
- else
- assign(t2,
- binop(Iop_InterleaveEvenLanes32x4,
- mkexpr(t1), mkexpr(t1)));
+ break;
+ }
+ }
- n /= 2;
+ break;
+ }
- if (n & 1)
- assign(t3,
- binop(Iop_InterleaveHI64x2,
- mkexpr(t2), mkexpr(t2)));
- else
- assign(t3,
- binop(Iop_InterleaveLO64x2,
- mkexpr(t2), mkexpr(t2)));
+ case 0x19: { /* MULTU */
+ switch (sa & 0x3) {
+ case 0: {
+ if ((1 <= ac) && ( 3 >= ac)) {
+ if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
+ /* If DSP is present -> DSP ASE MULTU */
+ UInt retVal = disDSPInstr_MIPS_WRK ( cins );
- putWReg(wd, mkexpr(t3));
- break;
+ if (0 != retVal) {
+ return -2;
}
- case 0x30: { /* SPLATI.W */
- DIP("SPLATI.W w%d, w%d[%d]", wd, ws, n);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
+ break;
+ } else {
+ return -2;
+ }
+ } else {
+ DIP("multu r%u, r%u", rs, rt);
- if (n & 1)
- assign(t2,
- binop(Iop_InterleaveOddLanes32x4,
- mkexpr(t1), mkexpr(t1)));
- else
- assign(t2,
- binop(Iop_InterleaveEvenLanes32x4,
- mkexpr(t1), mkexpr(t1)));
+ if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps) &&
+ !VEX_MIPS_CPU_HAS_MIPS32R2(archinfo->hwcaps)) {
+ ILLEGAL_INSTRUCTON
+ }
- n /= 2;
+ t2 = newTemp(Ity_I64);
- if (n & 1)
- assign(t3,
- binop(Iop_InterleaveHI64x2,
- mkexpr(t2), mkexpr(t2)));
- else
- assign(t3,
- binop(Iop_InterleaveLO64x2,
- mkexpr(t2), mkexpr(t2)));
+ assign(t2, binop(Iop_MullU32, mkNarrowTo32(ty, getIReg(rs)),
+ mkNarrowTo32(ty, getIReg(rt))));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ putHI(mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(t2)), True));
+ putLO(mkWidenFrom32(ty, unop(Iop_64to32, mkexpr(t2)), True));
+ break;
+ }
+ }
- case 0x38: /* SPLATI.D */
- DIP("SPLATI.D w%d, w%d[%d]", wd, ws, n);
- t1 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
+ case 2: { /* MULU R6 */
+ if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+ DIP("mulu r%u, r%u, r%u", rs, rt, rd);
- if (n)
- assign(t3,
- binop(Iop_InterleaveHI64x2,
- mkexpr(t1), mkexpr(t1)));
- else
- assign(t3,
- binop(Iop_InterleaveLO64x2,
- mkexpr(t1), mkexpr(t1)));
+ if (mode64) {
+ putIReg(rd, unop(Iop_32Uto64,
+ unop(Iop_64to32,
+ binop(Iop_MullU32,
+ unop(Iop_64to32, getIReg(rs)),
+ unop(Iop_64to32, getIReg(rt))))));
+ } else {
+ putIReg(rd, unop(Iop_64to32,
+ binop(Iop_MullU32,
+ getIReg(rs), getIReg(rt))));
+ }
+ } else {
+ ILLEGAL_INSTRUCTON;
+ }
- putWReg(wd, mkexpr(t3));
- break;
+ break;
+ }
- default:
- return -1;
+ case 3: { /* MUHU R6 */
+ if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+ DIP("muhu r%u, r%u, r%u", rs, rt, rd);
+
+ if (mode64) {
+ putIReg(rd, unop(Iop_32Uto64,
+ unop(Iop_64HIto32,
+ binop(Iop_MullU32,
+ unop(Iop_64to32, getIReg(rs)),
+ unop(Iop_64to32, getIReg(rt))))));
+ } else {
+ putIReg(rd, unop(Iop_64HIto32,
+ binop(Iop_MullU32,
+ getIReg(rs), getIReg(rt))));
+ }
+ } else {
+ ILLEGAL_INSTRUCTON;
}
break;
+ }
+ }
- case 0x02: /* COPY_S.df */
- switch (df) {
- case 0x00: /* COPY_S.B */
- DIP("COPY_S.B r%d, w%d[%d]", wd, ws, n);
- t1 = newTemp(Ity_I8);
+ break;
+ }
- switch (n) {
- case 0:
- assign(t1,
- unop(Iop_32to8,
- unop(Iop_V128to32,
- getWReg(ws))));
- break;
+ case 0x1A: /* DIV */
+ switch (sa & 0x3) {
+ case 0:
+ DIP("div r%u, r%u", rs, rt);
- case 1:
- assign(t1,
- unop(Iop_16HIto8,
- unop(Iop_32to16,
- unop(Iop_V128to32,
- getWReg(ws)))));
- break;
+ if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps) &&
+ !VEX_MIPS_CPU_HAS_MIPS32R2(archinfo->hwcaps)) {
+ ILLEGAL_INSTRUCTON
+ }
- case 2:
- assign(t1,
- unop(Iop_16to8,
- unop(Iop_32HIto16,
- unop(Iop_64to32,
- unop(Iop_V128to64,
- getWReg(ws))))));
- break;
+ if (mode64) {
+ t2 = newTemp(Ity_I64);
- case 3:
- assign(t1,
- unop(Iop_16HIto8,
- unop(Iop_32HIto16,
- unop(Iop_64to32,
- unop(Iop_V128to64,
- getWReg(ws))))));
- break;
+ assign(t2, binop(Iop_DivModS32to32,
+ mkNarrowTo32(ty, getIReg(rs)),
+ mkNarrowTo32(ty, getIReg(rt))));
- case 4:
- assign(t1,
- unop(Iop_16to8,
- unop(Iop_32to16,
- unop(Iop_64HIto32,
- unop(Iop_V128to64,
- getWReg(ws))))));
- break;
+ putHI(mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(t2)), True));
+ putLO(mkWidenFrom32(ty, unop(Iop_64to32, mkexpr(t2)), True));
+ } else {
+ t1 = newTemp(Ity_I64);
- case 5:
- assign(t1,
- unop(Iop_16HIto8,
- unop(Iop_32to16,
- unop(Iop_64HIto32,
- unop(Iop_V128to64,
- getWReg(ws))))));
- break;
+ assign(t1, binop(Iop_DivModS32to32, getIReg(rs), getIReg(rt)));
- case 6:
- assign(t1,
- unop(Iop_16to8,
- unop(Iop_32HIto16,
- unop(Iop_64HIto32,
- unop(Iop_V128to64,
- getWReg(ws))))));
- break;
+ putHI(unop(Iop_64HIto32, mkexpr(t1)));
+ putLO(unop(Iop_64to32, mkexpr(t1)));
+ }
- case 7:
- assign(t1,
- unop(Iop_16HIto8,
- unop(Iop_32HIto16,
- unop(Iop_64HIto32,
- unop(Iop_V128to64,
- getWReg(ws))))));
- break;
+ break;
- case 8:
- assign(t1,
- unop(Iop_16to8,
- unop(Iop_32to16,
- unop(Iop_64to32,
- unop(Iop_V128HIto64,
- getWReg(ws))))));
- break;
+ case 2:
+ if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+ DIP("div r%u, r%u, r%u", rs, rt, rd);
- case 9:
- assign(t1,
- unop(Iop_16HIto8,
- unop(Iop_32to16,
- unop(Iop_64to32,
- unop(Iop_V128HIto64,
- getWReg(ws))))));
- break;
+ if (mode64) {
+ putIReg(rd, unop(Iop_32Sto64,
+ binop(Iop_DivS32,
+ unop(Iop_64to32, getIReg(rs)),
+ unop(Iop_64to32, getIReg(rt)))));
+ } else {
+ putIReg(rd, binop(Iop_DivS32, getIReg(rs), getIReg(rt)));
+ }
+ } else {
+ ILLEGAL_INSTRUCTON
+ }
- case 10:
- assign(t1,
- unop(Iop_16to8,
- unop(Iop_32HIto16,
- unop(Iop_64to32,
- unop(Iop_V128HIto64,
- getWReg(ws))))));
- break;
+ break;
- case 11:
- assign(t1,
- unop(Iop_16HIto8,
- unop(Iop_32HIto16,
- unop(Iop_64to32,
- unop(Iop_V128HIto64,
- getWReg(ws))))));
- break;
+ case 3:
+ if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+ DIP("mod r%u, r%u, r%u", rs, rt, rd);
- case 12:
- assign(t1,
- unop(Iop_16to8,
- unop(Iop_32to16,
- unop(Iop_64HIto32,
- unop(Iop_V128HIto64,
- getWReg(ws))))));
- break;
+ if (mode64) {
+ putIReg(rd, unop(Iop_32Sto64,
+ unop(Iop_64HIto32,
+ binop(Iop_DivModS32to32,
+ unop(Iop_64to32, getIReg(rs)),
+ unop(Iop_64to32, getIReg(rt))))));
+ } else {
+ t1 = newTemp(Ity_I64);
- case 13:
- assign(t1,
- unop(Iop_16HIto8,
- unop(Iop_32to16,
- unop(Iop_64HIto32,
- unop(Iop_V128HIto64,
- getWReg(ws))))));
- break;
+ assign(t1, binop(Iop_DivModS32to32, getIReg(rs), getIReg(rt)));
+ putIReg(rd, unop(Iop_64HIto32, mkexpr(t1)));
+ }
+ } else {
+ ILLEGAL_INSTRUCTON
+ }
- case 14:
- assign(t1,
- unop(Iop_16to8,
- unop(Iop_32HIto16,
- unop(Iop_64HIto32,
- unop(Iop_V128HIto64,
- getWReg(ws))))));
- break;
+ break;
+ }
- case 15:
- assign(t1,
- unop(Iop_16HIto8,
- unop(Iop_32HIto16,
- unop(Iop_64HIto32,
- unop(Iop_V128HIto64,
- getWReg(ws))))));
- break;
- }
+ break;
- putIReg(wd,
- unop(mode64 ? Iop_8Sto64 : Iop_8Sto32,
- mkexpr(t1)));
- break;
+ case 0x1B: /* DIVU */
+ switch (sa & 0x3) {
+ case 0:
+ DIP("divu r%u, r%u", rs, rt);
- case 0x20: /* COPY_S.H */
- DIP("COPY_S.H r%d, w%d[%d]", wd, ws, n);
- t1 = newTemp(Ity_I16);
+ if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps) &&
+ !VEX_MIPS_CPU_HAS_MIPS32R2(archinfo->hwcaps)) {
+ ILLEGAL_INSTRUCTON
+ }
- switch (n) {
- case 0:
- assign(t1,
- unop(Iop_32to16,
- unop(Iop_64to32,
- unop(Iop_V128to64,
- getWReg(ws)))));
- break;
+ if (mode64) {
+ t1 = newTemp(Ity_I64);
- case 1:
- assign(t1,
- unop(Iop_32HIto16,
- unop(Iop_64to32,
- unop(Iop_V128to64,
- getWReg(ws)))));
- break;
+ assign(t1, binop(Iop_DivModU32to32,
+ mkNarrowTo32(ty, getIReg(rs)),
+ mkNarrowTo32(ty, getIReg(rt))));
- case 2:
- assign(t1,
- unop(Iop_32to16,
- unop(Iop_64HIto32,
- unop(Iop_V128to64,
- getWReg(ws)))));
- break;
+ putHI(mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(t1)), True));
+ putLO(mkWidenFrom32(ty, unop(Iop_64to32, mkexpr(t1)), True));
+ } else {
+ t1 = newTemp(Ity_I64);
- case 3:
- assign(t1,
- unop(Iop_32HIto16,
- unop(Iop_64HIto32,
- unop(Iop_V128to64,
- getWReg(ws)))));
- break;
+ assign(t1, binop(Iop_DivModU32to32, getIReg(rs), getIReg(rt)));
+ putHI(unop(Iop_64HIto32, mkexpr(t1)));
+ putLO(unop(Iop_64to32, mkexpr(t1)));
+ }
- case 4:
- assign(t1,
- unop(Iop_32to16,
- unop(Iop_64to32,
- unop(Iop_V128HIto64,
- getWReg(ws)))));
- break;
+ break;
- case 5:
- assign(t1,
- unop(Iop_32HIto16,
- unop(Iop_64to32,
- unop(Iop_V128HIto64,
- getWReg(ws)))));
- break;
+ case 2:
+ if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+ DIP("divu r%u, r%u, r%u", rs, rt, rd);
- case 6:
- assign(t1,
- unop(Iop_32to16,
- unop(Iop_64HIto32,
- unop(Iop_V128HIto64,
- getWReg(ws)))));
- break;
+ if (mode64) {
+ putIReg(rd, unop(Iop_32Sto64,
+ binop(Iop_DivU32,
+ unop(Iop_64to32, getIReg(rs)),
+ unop(Iop_64to32, getIReg(rt)))));
+ } else {
+ putIReg(rd, binop(Iop_DivU32, getIReg(rs), getIReg(rt)));
+ }
- case 7:
- assign(t1,
- unop(Iop_32HIto16,
- unop(Iop_64HIto32,
- unop(Iop_V128HIto64,
- getWReg(ws)))));
- break;
- }
+ break;
+ } else {
+ ILLEGAL_INSTRUCTON
+ }
- putIReg(wd,
- unop(mode64 ? Iop_16Sto64 : Iop_16Sto32,
- mkexpr(t1)));
- break;
+ break;
- case 0x30: /* COPY_S.W */
- DIP("COPY_S.W r%d, w%d[%d]", wd, ws, n);
+ case 3:
+ if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+ DIP("modu r%u, r%u, r%u", rs, rt, rd);
- switch (n) {
- case 0:
- putIReg(wd,
- mkWidenFrom32(ty,
- unop(Iop_V128to32,
- getWReg(ws)),
- True));
- break;
+ if (mode64) {
+ putIReg(rd, unop(Iop_32Uto64,
+ unop(Iop_64HIto32,
+ binop(Iop_DivModU32to32,
+ unop(Iop_64to32, getIReg(rs)),
+ unop(Iop_64to32, getIReg(rt))))));
+ } else {
+ t1 = newTemp(Ity_I64);
+
+ assign(t1, binop(Iop_DivModU32to32, getIReg(rs), getIReg(rt)));
+ putIReg(rd, unop(Iop_64HIto32, mkexpr(t1)));
+ }
+ } else {
+ ILLEGAL_INSTRUCTON
+ }
- case 1:
- t2 = newTemp(Ity_I64);
- assign(t2,
- unop(Iop_V128to64, getWReg(ws)));
- putIReg(wd,
- mkWidenFrom32(ty,
- unop(Iop_64HIto32,
- mkexpr(t2)),
- True));
- break;
+ break;
+ }
- case 2:
- t2 = newTemp(Ity_I64);
- assign(t2,
- unop(Iop_V128HIto64,
- getWReg(ws)));
- putIReg(wd,
- mkWidenFrom32(ty,
- unop(Iop_64to32,
- mkexpr(t2)),
- True));
- break;
+ break;
- case 3:
- t2 = newTemp(Ity_I64);
- assign(t2,
- unop(Iop_V128HIto64,
- getWReg(ws)));
- putIReg(wd,
- mkWidenFrom32(ty,
- unop(Iop_64HIto32,
- mkexpr(t2)),
- True));
- break;
+ case 0x1C: /* Doubleword Multiply - DMULT; MIPS64 */
+ switch (sa) {
+ case 0:
+ DIP("dmult r%u, r%u", rs, rt);
- default:
- break;
- }
+ if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps) &&
+ !VEX_MIPS_CPU_HAS_MIPS32R2(archinfo->hwcaps)) {
+ ILLEGAL_INSTRUCTON
+ }
- break;
+ t0 = newTemp(Ity_I128);
- case 0x38: /* COPY_S.D */
- if (mode64) {
- DIP("COPY_S.D r%d, w%d[%d]", wd, ws, n);
+ assign(t0, binop(Iop_MullS64, getIReg(rs), getIReg(rt)));
- switch (n) {
- case 0:
- putIReg(wd,
- unop(Iop_V128to64,
- getWReg(ws)));
- break;
+ putHI(unop(Iop_128HIto64, mkexpr(t0)));
+ putLO(unop(Iop_128to64, mkexpr(t0)));
+ break;
- case 1:
- putIReg(wd,
- unop(Iop_V128HIto64,
- getWReg(ws)));
- break;
- }
- } else {
- return -2;
- }
+ case 2: /* DMUL */
+ if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+ DIP("dmul r%u, r%u, r%u", rd, rs, rt);
+ putIReg(rd, unop(Iop_128to64,
+ binop(Iop_MullS64, getIReg(rs), getIReg(rt))));
+ } else {
+ ILLEGAL_INSTRUCTON
+ }
- break;
+ break;
- default:
- return -1;
+ case 3: /* DMUH */
+ if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+ DIP("dmuh r%u, r%u, r%u", rd, rs, rt);
+ putIReg(rd, unop(Iop_128HIto64,
+ binop(Iop_MullS64, getIReg(rs), getIReg(rt))));
+ } else {
+ ILLEGAL_INSTRUCTON
}
break;
+ }
- case 0x03: { /* COPY_U.df */
- switch (df) {
- case 0x00: /* COPY_U.B */
- DIP("COPY_U.B r%d, w%d[%d]", wd, ws, n);
- t1 = newTemp(Ity_I8);
+ break;
- switch (n) {
- case 0:
- assign(t1,
- unop(Iop_16to8,
- unop(Iop_32to16,
- unop(Iop_64to32,
- unop(Iop_V128to64,
- getWReg(ws))))));
- break;
+ case 0x1D: /* Doubleword Multiply Unsigned - DMULTU; MIPS64 */
+ switch (sa) {
+ case 0:
+ DIP("dmultu r%u, r%u", rs, rt);
- case 1:
- assign(t1,
- unop(Iop_16HIto8,
- unop(Iop_32to16,
- unop(Iop_64to32,
- unop(Iop_V128to64,
- getWReg(ws))))));
- break;
+ if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps) &&
+ !VEX_MIPS_CPU_HAS_MIPS32R2(archinfo->hwcaps)) {
+ ILLEGAL_INSTRUCTON
+ }
- case 2:
- assign(t1,
- unop(Iop_16to8,
- unop(Iop_32HIto16,
- unop(Iop_64to32,
- unop(Iop_V128to64,
- getWReg(ws))))));
- break;
+ t0 = newTemp(Ity_I128);
- case 3:
- assign(t1,
- unop(Iop_16HIto8,
- unop(Iop_32HIto16,
- unop(Iop_64to32,
- unop(Iop_V128to64,
- getWReg(ws))))));
- break;
+ assign(t0, binop(Iop_MullU64, getIReg(rs), getIReg(rt)));
- case 4:
- assign(t1,
- unop(Iop_16to8,
- unop(Iop_32to16,
- unop(Iop_64HIto32,
- unop(Iop_V128to64,
- getWReg(ws))))));
- break;
+ putHI(unop(Iop_128HIto64, mkexpr(t0)));
+ putLO(unop(Iop_128to64, mkexpr(t0)));
+ break;
- case 5:
- assign(t1,
- unop(Iop_16HIto8,
- unop(Iop_32to16,
- unop(Iop_64HIto32,
- unop(Iop_V128to64,
- getWReg(ws))))));
- break;
+ case 2: /* DMULU */
+ if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+ DIP("dmulu r%u, r%u, r%u", rd, rs, rt);
+ putIReg(rd, unop(Iop_128to64,
+ binop(Iop_MullU64, getIReg(rs), getIReg(rt))));
+ } else {
+ ILLEGAL_INSTRUCTON
+ }
- case 6:
- assign(t1,
- unop(Iop_16to8,
- unop(Iop_32HIto16,
- unop(Iop_64HIto32,
- unop(Iop_V128to64,
- getWReg(ws))))));
- break;
+ break;
- case 7:
- assign(t1,
- unop(Iop_16HIto8,
- unop(Iop_32HIto16,
- unop(Iop_64HIto32,
- unop(Iop_V128to64,
- getWReg(ws))))));
- break;
+ case 3: /* DMUHU */
+ if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+ DIP("dmuhu r%u, r%u, r%u", rd, rs, rt);
+ putIReg(rd, unop(Iop_128HIto64,
+ binop(Iop_MullU64, getIReg(rs), getIReg(rt))));
+ } else {
+ ILLEGAL_INSTRUCTON
+ }
- case 8:
- assign(t1,
- unop(Iop_16to8,
- unop(Iop_32to16,
- unop(Iop_64to32,
- unop(Iop_V128HIto64,
- getWReg(ws))))));
- break;
+ break;
+ }
- case 9:
- assign(t1,
- unop(Iop_16HIto8,
- unop(Iop_32to16,
- unop(Iop_64to32,
- unop(Iop_V128HIto64,
- getWReg(ws))))));
- break;
+ break;
- case 10:
- assign(t1,
- unop(Iop_16to8,
- unop(Iop_32HIto16,
- unop(Iop_64to32,
- unop(Iop_V128HIto64,
- getWReg(ws))))));
- break;
+ case 0x1E: /* Doubleword Divide DDIV; MIPS64 */
+ switch (sa) {
+ case 0:
+ DIP("ddiv r%u, r%u", rs, rt);
- case 11:
- assign(t1,
- unop(Iop_16HIto8,
- unop(Iop_32HIto16,
- unop(Iop_64to32,
- unop(Iop_V128HIto64,
- getWReg(ws))))));
- break;
+ if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps) &&
+ !VEX_MIPS_CPU_HAS_MIPS32R2(archinfo->hwcaps)) {
+ ILLEGAL_INSTRUCTON
+ }
- case 12:
- assign(t1,
- unop(Iop_16to8,
- unop(Iop_32to16,
- unop(Iop_64HIto32,
- unop(Iop_V128HIto64,
- getWReg(ws))))));
- break;
+ t1 = newTemp(Ity_I128);
- case 13:
- assign(t1,
- unop(Iop_16HIto8,
- unop(Iop_32to16,
- unop(Iop_64HIto32,
- unop(Iop_V128HIto64,
- getWReg(ws))))));
- break;
+ assign(t1, binop(Iop_DivModS64to64, getIReg(rs), getIReg(rt)));
- case 14:
- assign(t1,
- unop(Iop_16to8,
- unop(Iop_32HIto16,
- unop(Iop_64HIto32,
- unop(Iop_V128HIto64,
- getWReg(ws))))));
- break;
+ putHI(unop(Iop_128HIto64, mkexpr(t1)));
+ putLO(unop(Iop_128to64, mkexpr(t1)));
+ break;
- case 15:
- assign(t1,
- unop(Iop_16HIto8,
- unop(Iop_32HIto16,
- unop(Iop_64HIto32,
- unop(Iop_V128HIto64,
- getWReg(ws))))));
- break;
- }
+ case 2: /* DDIV r6 */
+ if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+ DIP("ddiv r%u, r%u, r%u", rs, rt, rd);
+ putIReg(rd, unop(Iop_128to64,
+ binop(Iop_DivModS64to64,
+ getIReg(rs), getIReg(rt))));
+ } else {
+ ILLEGAL_INSTRUCTON
+ }
- putIReg(wd,
- unop(mode64 ? Iop_8Uto64 : Iop_8Uto32,
- mkexpr(t1)));
- break;
+ break;
- case 0x20: /* COPY_U.H */
- DIP("COPY_U.H r%d, w%d[%d]", wd, ws, n);
- t1 = newTemp(Ity_I16);
+ case 3: /* DMOD r6 */
+ if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+ DIP("dmod r%u, r%u, r%u", rs, rt, rd);
+ t2 = newTemp(Ity_I128);
+ assign(t2, binop(Iop_DivModS64to64, getIReg(rs), getIReg(rt)));
+ putIReg(rd, unop(Iop_128HIto64, mkexpr(t2)));
+ } else {
+ ILLEGAL_INSTRUCTON
+ }
- switch (n) {
- case 0:
- assign(t1,
- unop(Iop_32to16,
- unop(Iop_64to32,
- unop(Iop_V128to64,
- getWReg(ws)))));
- break;
+ break;
+ }
- case 1:
- assign(t1,
- unop(Iop_32HIto16,
- unop(Iop_64to32,
- unop(Iop_V128to64,
- getWReg(ws)))));
- break;
+ break;
- case 2:
- assign(t1,
- unop(Iop_32to16,
- unop(Iop_64HIto32,
- unop(Iop_V128to64,
- getWReg(ws)))));
- break;
+ case 0x1F: /* Doubleword Divide Unsigned DDIVU; MIPS64 check this */
+ switch (sa) {
+ case 0:
+ DIP("ddivu r%u, r%u", rs, rt);
- case 3:
- assign(t1,
- unop(Iop_32HIto16,
- unop(Iop_64HIto32,
- unop(Iop_V128to64,
- getWReg(ws)))));
- break;
+ if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps) &&
+ !VEX_MIPS_CPU_HAS_MIPS32R2(archinfo->hwcaps)) {
+ ILLEGAL_INSTRUCTON
+ }
- case 4:
- assign(t1,
- unop(Iop_32to16,
- unop(Iop_64to32,
- unop(Iop_V128HIto64,
- getWReg(ws)))));
- break;
+ t1 = newTemp(Ity_I128);
- case 5:
- assign(t1,
- unop(Iop_32HIto16,
- unop(Iop_64to32,
- unop(Iop_V128HIto64,
- getWReg(ws)))));
- break;
+ assign(t1, binop(Iop_DivModU64to64, getIReg(rs), getIReg(rt)));
- case 6:
- assign(t1,
- unop(Iop_32to16,
- unop(Iop_64HIto32,
- unop(Iop_V128HIto64,
- getWReg(ws)))));
- break;
+ putHI(unop(Iop_128HIto64, mkexpr(t1)));
+ putLO(unop(Iop_128to64, mkexpr(t1)));
+ break;
- case 7:
- assign(t1,
- unop(Iop_32HIto16,
- unop(Iop_64HIto32,
- unop(Iop_V128HIto64,
- getWReg(ws)))));
- break;
- }
+ case 2:
+ if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+ DIP("ddivu r%u, r%u, r%u", rs, rt, rd);
+ putIReg(rd, unop(Iop_128to64, binop(Iop_DivModU64to64,
+ getIReg(rs), getIReg(rt))));
+ } else {
+ ILLEGAL_INSTRUCTON
+ }
- putIReg(wd,
- unop(mode64 ? Iop_16Uto64 : Iop_16Uto32,
- mkexpr(t1)));
- break;
+ break;
- case 0x30: /* COPY_U.W */
- DIP("COPY_U.W r%d, w%d[%d]", wd, ws, n);
+ case 3:
+ if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+ DIP("dmodu r%u, r%u, r%u", rs, rt, rd);
+ putIReg(rd, unop(Iop_128HIto64, binop(Iop_DivModU64to64,
+ getIReg(rs), getIReg(rt))));
+ } else {
+ ILLEGAL_INSTRUCTON
+ }
- switch (n) {
- case 0:
- putIReg(wd,
- mkWidenFrom32(ty,
- unop(Iop_V128to32,
- getWReg(ws)),
- False));
- break;
+ break;
+ }
- case 1:
- t2 = newTemp(Ity_I64);
- assign(t2,
- unop(Iop_V128to64,
- getWReg(ws)));
- putIReg(wd,
- mkWidenFrom32(ty,
- unop(Iop_64HIto32,
- mkexpr(t2)),
- False));
- break;
+ break;
- case 2:
- t2 = newTemp(Ity_I64);
- assign(t2,
- unop(Iop_V128HIto64,
- getWReg(ws)));
- putIReg(wd,
- mkWidenFrom32(ty,
- unop(Iop_64to32,
- mkexpr(t2)),
- False));
- break;
+ case 0x20: { /* ADD */
+ DIP("add r%u, r%u, r%u", rd, rs, rt);
+ IRTemp tmpRs32 = newTemp(Ity_I32);
+ IRTemp tmpRt32 = newTemp(Ity_I32);
- case 3:
- t2 = newTemp(Ity_I64);
- assign(t2,
- unop(Iop_V128HIto64,
- getWReg(ws)));
- putIReg(wd,
- mkWidenFrom32(ty,
- unop(Iop_64HIto32,
- mkexpr(t2)),
- False));
- break;
+ assign(tmpRs32, mkNarrowTo32(ty, getIReg(rs)));
+ assign(tmpRt32, mkNarrowTo32(ty, getIReg(rt)));
- default:
- break;
- }
+ t0 = newTemp(Ity_I32);
+ t1 = newTemp(Ity_I32);
+ t2 = newTemp(Ity_I32);
+ t3 = newTemp(Ity_I32);
+ t4 = newTemp(Ity_I32);
+ /* dst = src0 + src1
+ if (sign(src0 ) != sign(src1 ))
+ goto no overflow;
+ if (sign(dst) == sign(src0 ))
+ goto no overflow;
+ we have overflow! */
- break;
+ assign(t0, binop(Iop_Add32, mkexpr(tmpRs32), mkexpr(tmpRt32)));
+ assign(t1, binop(Iop_Xor32, mkexpr(tmpRs32), mkexpr(tmpRt32)));
+ assign(t2, unop(Iop_1Uto32,
+ binop(Iop_CmpEQ32,
+ binop(Iop_And32, mkexpr(t1), mkU32(0x80000000)),
+ mkU32(0x80000000))));
- default:
- return -1;
- }
+ assign(t3, binop(Iop_Xor32, mkexpr(t0), mkexpr(tmpRs32)));
+ assign(t4, unop(Iop_1Uto32,
+ binop(Iop_CmpNE32,
+ binop(Iop_And32, mkexpr(t3), mkU32(0x80000000)),
+ mkU32(0x80000000))));
- break;
- }
+ stmt(IRStmt_Exit(binop(Iop_CmpEQ32,
+ binop(Iop_Or32, mkexpr(t2), mkexpr(t4)),
+ mkU32(0)),
+ Ijk_SigFPE_IntOvf,
+ mode64 ? IRConst_U64(guest_PC_curr_instr + 4) :
+ IRConst_U32(guest_PC_curr_instr + 4),
+ OFFB_PC));
- case 0x04: { /* INSERT.df */
- t5 = newTemp(Ity_I64);
- UInt hi = 1;
- ULong mask;
- IRTemp *src, *dst;
- assign(t5, mode64 ? getIReg(ws) :
- unop(Iop_32Uto64, getIReg(ws)));
-
- if (df == 0x38) { /* INSERT.D */
- if (mode64) {
- DIP("INSERT.D w%d[%d], r%d", wd, n, ws);
+ putIReg(rd, mkWidenFrom32(ty, mkexpr(t0), True));
+ break;
+ }
- if (n == 0) {
- putWReg(wd,
- binop(Iop_64HLtoV128,
- unop(Iop_V128HIto64,
- getWReg(wd)),
- mkexpr(t5)));
- } else {
- putWReg(wd,
- binop(Iop_64HLtoV128,
- mkexpr(t5),
- unop(Iop_V128to64,
- getWReg(wd))));
- }
+ case 0x21: /* ADDU */
+ DIP("addu r%u, r%u, r%u", rd, rs, rt);
- break;
- } else {
- return -2;
- }
- } else {
- t1 = newTemp(Ity_I64);
- t2 = newTemp(Ity_I64);
- assign(t1, unop(Iop_V128to64, getWReg(wd)));
- assign(t2, unop(Iop_V128HIto64, getWReg(wd)));
- }
+ if (mode64) {
+ ALU_PATTERN64(Iop_Add32);
+ } else {
+ ALU_PATTERN(Iop_Add32);
+ }
- switch (df) {
- case 0x00: /* INSERT.B */
- DIP("INSERT.B w%d[%d], r%d", wd, n, ws);
+ break;
- if (n >= 8) {
- n -= 8;
- } else {
- hi = 0;
- }
+ case 0x22: { /* SUB */
+ DIP("sub r%u, r%u, r%u", rd, rs, rt);
+ IRTemp tmpRs32 = newTemp(Ity_I32);
+ IRTemp tmpRt32 = newTemp(Ity_I32);
- n <<= 3;
- mask = 0xFFull;
- break;
+ assign(tmpRs32, mkNarrowTo32(ty, getIReg(rs)));
+ assign(tmpRt32, mkNarrowTo32(ty, getIReg(rt)));
+ t0 = newTemp(Ity_I32);
+ t1 = newTemp(Ity_I32);
+ t2 = newTemp(Ity_I32);
+ t3 = newTemp(Ity_I32);
+ t4 = newTemp(Ity_I32);
+ t5 = newTemp(Ity_I32);
+ /* dst = src0 + (-1 * src1)
+ if(sign(src0 ) != sign((-1 * src1) ))
+ goto no overflow;
+ if(sign(dst) == sign(src0 ))
+ goto no overflow;
+ we have overflow! */
- case 0x20: /* INSERT.H */
- DIP("INSERT.H w%d[%d], r%d", wd, n, ws);
+ assign(t5, binop(Iop_Mul32, mkexpr(tmpRt32), mkU32(-1)));
+ assign(t0, binop(Iop_Add32, mkexpr(tmpRs32), mkexpr(t5)));
+ assign(t1, binop(Iop_Xor32, mkexpr(tmpRs32), mkexpr(t5)));
+ assign(t2, unop(Iop_1Sto32, binop(Iop_CmpEQ32, binop(Iop_And32,
+ mkexpr(t1), mkU32(0x80000000)), mkU32(0x80000000))));
- if (n >= 4) {
- n -= 4;
- } else {
- hi = 0;
- }
+ assign(t3, binop(Iop_Xor32, mkexpr(t0), mkexpr(tmpRs32)));
+ assign(t4, unop(Iop_1Sto32, binop(Iop_CmpNE32, binop(Iop_And32,
+ mkexpr(t3), mkU32(0x80000000)), mkU32(0x80000000))));
- n <<= 4;
- mask = 0xFFFFull;
- break;
+ stmt(IRStmt_Exit(binop(Iop_CmpEQ32, binop(Iop_Or32, mkexpr(t2),
+ mkexpr(t4)), mkU32(0)), Ijk_SigFPE_IntOvf,
+ mode64 ? IRConst_U64(guest_PC_curr_instr + 4) :
+ IRConst_U32(guest_PC_curr_instr + 4),
+ OFFB_PC));
- case 0x30: /* INSERT.W */
- DIP("INSERT.W w%d[%d], r%d", wd, n, ws);
+ putIReg(rd, mkWidenFrom32(ty, mkexpr(t0), True));
+ break;
+ }
- if (n >= 2) {
- n -= 2;
- } else {
- hi = 0;
- }
+ case 0x23: /* SUBU */
+ DIP("subu r%u, r%u, r%u", rd, rs, rt);
- n <<= 5;
- mask = 0xFFFFFFFFull;
- break;
+ if (mode64) {
+ ALU_PATTERN64(Iop_Sub32);
+ } else {
+ ALU_PATTERN(Iop_Sub32);
+ }
- default:
- return -1;
- }
+ break;
- if (hi) {
- t4 = newTemp(Ity_I64);
- src = &t2;
- dst = &t4;
- t3 = t1;
- } else {
- t3 = newTemp(Ity_I64);
- src = &t1;
- dst = &t3;
- t4 = t2;
- }
+ case 0x24: /* AND */
+ DIP("and r%u, r%u, r%u", rd, rs, rt);
- mask <<= n;
- assign(*dst,
- binop(Iop_Or64,
- binop(Iop_And64, mkexpr(*src), mkU64(~mask)),
- binop(Iop_And64,
- binop(Iop_Shl64, mkexpr(t5), mkU8(n)),
- mkU64(mask))));
- putWReg(wd,
- binop(Iop_64HLtoV128, mkexpr(t4), mkexpr(t3)));
- break;
- }
+ if (mode64) {
+ ALU_PATTERN(Iop_And64);
+ } else {
+ ALU_PATTERN(Iop_And32);
+ }
- case 0x05: { /* INSVE.df */
- switch (df) {
- case 0x00: { /* INSVE.B */
- DIP("INSVE.B w%d[%d], w%d[0]", wd, n, ws);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- assign(t1, getWReg(wd));
- assign(t2, getWReg(ws));
- Int i;
- IRTemp tmp[16];
-
- for (i = 0; i < 16; i++) {
- tmp[i] = newTemp(Ity_I8);
-
- if (n == i)
- assign(tmp[i],
- binop(Iop_GetElem8x16,
- mkexpr(t2), mkU8(0x0)));
- else
- assign(tmp[i],
- binop(Iop_GetElem8x16,
- mkexpr(t1), mkU8(i)));
- }
+ break;
- putWReg(wd,
- binop(Iop_64HLtoV128,
- binop(Iop_32HLto64,
- binop(Iop_16HLto32,
- binop(Iop_8HLto16,
- mkexpr(tmp[15]),
- mkexpr(tmp[14])),
- binop(Iop_8HLto16,
- mkexpr(tmp[13]),
- mkexpr(tmp[12]))),
- binop(Iop_16HLto32,
- binop(Iop_8HLto16,
- mkexpr(tmp[11]),
- mkexpr(tmp[10])),
- binop(Iop_8HLto16,
- mkexpr(tmp[9]),
- mkexpr(tmp[8])))),
- binop(Iop_32HLto64,
- binop(Iop_16HLto32,
- binop(Iop_8HLto16,
- mkexpr(tmp[7]),
- mkexpr(tmp[6])),
- binop(Iop_8HLto16,
- mkexpr(tmp[5]),
- mkexpr(tmp[4]))),
- binop(Iop_16HLto32,
- binop(Iop_8HLto16,
- mkexpr(tmp[3]),
- mkexpr(tmp[2])),
- binop(Iop_8HLto16,
- mkexpr(tmp[1]),
- mkexpr(tmp[0]))))));
- break;
- }
+ case 0x25: /* OR */
+ DIP("or r%u, r%u, r%u", rd, rs, rt);
- case 0x20: { /* INSVE.H */
- DIP("INSVE.H w%d[%d], r%d[0]", wd, n, ws);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- assign(t1, getWReg(wd));
- assign(t2, getWReg(ws));
- Int i;
- IRTemp tmp[8];
+ if (mode64) {
+ ALU_PATTERN(Iop_Or64);
+ } else {
+ ALU_PATTERN(Iop_Or32);
+ }
- for (i = 0; i < 8; i++) {
- tmp[i] = newTemp(Ity_I16);
+ break;
- if (n == i)
- assign(tmp[i],
- binop(Iop_GetElem16x8,
- mkexpr(t2), mkU8(0x0)));
- else
- assign(tmp[i],
- binop(Iop_GetElem16x8,
- mkexpr(t1), mkU8(i)));
- }
+ case 0x26: /* XOR */
+ DIP("xor r%u, r%u, r%u", rd, rs, rt);
- putWReg(wd,
- binop(Iop_64HLtoV128,
- binop(Iop_32HLto64,
- binop(Iop_16HLto32,
- mkexpr(tmp[7]),
- mkexpr(tmp[6])),
- binop(Iop_16HLto32,
- mkexpr(tmp[5]),
- mkexpr(tmp[4]))),
- binop(Iop_32HLto64,
- binop(Iop_16HLto32,
- mkexpr(tmp[3]),
- mkexpr(tmp[2])),
- binop(Iop_16HLto32,
- mkexpr(tmp[1]),
- mkexpr(tmp[0])))));
- break;
- }
+ if (mode64) {
+ ALU_PATTERN(Iop_Xor64);
+ } else {
+ ALU_PATTERN(Iop_Xor32);
+ }
- case 0x30: { /* INSVE.W */
- DIP("INSVE.W w%d[%d], r%d[0]", wd, n, ws);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- assign(t1, getWReg(wd));
- assign(t2, getWReg(ws));
- Int i;
- IRTemp tmp[4];
+ break;
- for (i = 0; i < 4; i++) {
- tmp[i] = newTemp(Ity_I32);
+ case 0x27: /* NOR */
+ DIP("nor r%u, r%u, r%u", rd, rs, rt);
- if (n == i)
- assign(tmp[i],
- binop(Iop_GetElem32x4,
- mkexpr(t2), mkU8(0x0)));
- else
- assign(tmp[i],
- binop(Iop_GetElem32x4,
- mkexpr(t1), mkU8(i)));
- }
+ if (mode64)
+ putIReg(rd, unop(Iop_Not64, binop(Iop_Or64, getIReg(rs),
+ getIReg(rt))));
+ else
+ putIReg(rd, unop(Iop_Not32, binop(Iop_Or32, getIReg(rs),
+ getIReg(rt))));
- putWReg(wd,
- binop(Iop_64HLtoV128,
- binop(Iop_32HLto64,
- mkexpr(tmp[3]),
- mkexpr(tmp[2])),
- binop(Iop_32HLto64,
- mkexpr(tmp[1]),
- mkexpr(tmp[0]))));
- break;
- }
+ break;
- case 0x38: { /* INSVE.D */
- DIP("INSVE.D w%d[%d], r%d[0]", wd, n, ws);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- assign(t1, getWReg(wd));
- assign(t2, getWReg(ws));
- Int i;
- IRTemp tmp[2];
+ case 0x2A: /* SLT */
+ DIP("slt r%u, r%u, r%u", rd, rs, rt);
- for (i = 0; i < 2; i++) {
- tmp[i] = newTemp(Ity_I64);
+ if (mode64)
+ putIReg(rd, unop(Iop_1Uto64, binop(Iop_CmpLT64S, getIReg(rs),
+ getIReg(rt))));
+ else
+ putIReg(rd, unop(Iop_1Uto32, binop(Iop_CmpLT32S, getIReg(rs),
+ getIReg(rt))));
- if (n == i)
- assign(tmp[i],
- binop(Iop_GetElem64x2,
- mkexpr(t2), mkU8(0x0)));
- else
- assign(tmp[i],
- binop(Iop_GetElem64x2,
- mkexpr(t1), mkU8(i)));
- }
+ break;
- putWReg(wd,
- binop(Iop_64HLtoV128,
- mkexpr(tmp[1]), mkexpr(tmp[0])));
- break;
- }
- }
+ case 0x2B: /* SLTU */
+ DIP("sltu r%u, r%u, r%u", rd, rs, rt);
- break;
- }
+ if (mode64)
+ putIReg(rd, unop(Iop_1Uto64, binop(Iop_CmpLT64U, getIReg(rs),
+ getIReg(rt))));
+ else
+ putIReg(rd, unop(Iop_1Uto32, binop(Iop_CmpLT32U, getIReg(rs),
+ getIReg(rt))));
- default:
- return -1;
- }
- }
- return 0;
-}
+ break;
-static Int msa_VEC(UInt cins, UChar wd, UChar ws) { /* VEC */
- IRTemp t1, t2, t3;
- UShort operation;
- UChar wt;
+ case 0x2C: { /* Doubleword Add - DADD; MIPS64 */
+ DIP("dadd r%u, r%u, r%u", rd, rs, rt);
+ IRTemp tmpRs64 = newTemp(Ity_I64);
+ IRTemp tmpRt64 = newTemp(Ity_I64);
- vassert((cins & 0x03000000) == 0);
+ assign(tmpRs64, getIReg(rs));
+ assign(tmpRt64, getIReg(rt));
- operation = (cins & 0x03E00000) >> 21;
- wt = (cins & 0x001F0000) >> 16;
+ t0 = newTemp(Ity_I64);
+ t1 = newTemp(Ity_I64);
+ t2 = newTemp(Ity_I64);
+ t3 = newTemp(Ity_I64);
+ t4 = newTemp(Ity_I64);
+ /* dst = src0 + src1
+ if(sign(src0 ) != sign(src1 ))
+ goto no overflow;
+ if(sign(dst) == sign(src0 ))
+ goto no overflow;
+ we have overflow! */
- switch (operation) {
- case 0x00: { /* AND.V */
- DIP("AND.V w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3, binop(Iop_AndV128, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ assign(t0, binop(Iop_Add64, mkexpr(tmpRs64), mkexpr(tmpRt64)));
+ assign(t1, binop(Iop_Xor64, mkexpr(tmpRs64), mkexpr(tmpRt64)));
+ assign(t2, unop(Iop_1Uto64,
+ binop(Iop_CmpEQ64,
+ binop(Iop_And64, mkexpr(t1),
+ mkU64(0x8000000000000000ULL)),
+ mkU64(0x8000000000000000ULL))));
- case 0x01: { /* OR.V */
- DIP("OR.V w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3, binop(Iop_OrV128, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ assign(t3, binop(Iop_Xor64, mkexpr(t0), mkexpr(tmpRs64)));
+ assign(t4, unop(Iop_1Uto64,
+ binop(Iop_CmpNE64,
+ binop(Iop_And64, mkexpr(t3),
+ mkU64(0x8000000000000000ULL)),
+ mkU64(0x8000000000000000ULL))));
- case 0x02: { /* NOR.V */
- DIP("NOR.V w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3,
- unop(Iop_NotV128,
- binop(Iop_OrV128, mkexpr(t1), mkexpr(t2))));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ stmt(IRStmt_Exit(binop(Iop_CmpEQ64,
+ binop(Iop_Or64, mkexpr(t2), mkexpr(t4)),
+ mkU64(0)),
+ Ijk_SigFPE_IntOvf,
+ IRConst_U64(guest_PC_curr_instr + 4),
+ OFFB_PC));
- case 0x03: { /* XOR.V */
- DIP("XOR.V w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- assign(t2, getWReg(wt));
- assign(t3, binop(Iop_XorV128, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ putIReg(rd, mkexpr(t0));
+ break;
+ }
- case 0x04: { /* BMNZ (ws AND wt) OR (wd AND NOT wt) */
- DIP("BMNZ.V w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1,
- binop(Iop_AndV128,
- getWReg(ws), getWReg(wt)));
- assign(t2,
- binop(Iop_AndV128,
- getWReg(wd),
- unop(Iop_NotV128, getWReg(wt))));
- assign(t3, binop(Iop_OrV128, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ case 0x2D: /* Doubleword Add Unsigned - DADDU; MIPS64 */
+ DIP("daddu r%u, r%u, r%u", rd, rs, rt);
+ ALU_PATTERN(Iop_Add64);
+ break;
- case 0x05: { /* BMZ.V (ws AND NOT wt) OR (wd AND wt) */
- DIP("BMZ.V w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1,
- binop(Iop_AndV128,
- getWReg(wd), getWReg(wt)));
- assign(t2,
- binop(Iop_AndV128,
- getWReg(ws),
- unop(Iop_NotV128, getWReg(wt))));
- assign(t3, binop(Iop_OrV128, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ case 0x2E: { /* Doubleword Subtract - DSUB; MIPS64 */
+ DIP("dsub r%u, r%u, r%u", rd, rs, rt);
+ IRTemp tmpRs64 = newTemp(Ity_I64);
+ IRTemp tmpRt64 = newTemp(Ity_I64);
- case 0x06: { /* BSEL (ws AND NOT wd) OR (wt AND wd) */
- DIP("BSEL.V w%d, w%d, w%d", wd, ws, wt);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1,
- binop(Iop_AndV128,
- getWReg(wd), getWReg(wt)));
- assign(t2,
- binop(Iop_AndV128,
- getWReg(ws),
- unop(Iop_NotV128, getWReg(wd))));
- assign(t3, binop(Iop_OrV128, mkexpr(t1), mkexpr(t2)));
- putWReg(wd, mkexpr(t3));
- break;
- }
+ assign(tmpRs64, getIReg(rs));
+ assign(tmpRt64, getIReg(rt));
+ t0 = newTemp(Ity_I64);
+ t1 = newTemp(Ity_I64);
+ t2 = newTemp(Ity_I64);
+ t3 = newTemp(Ity_I64);
+ t4 = newTemp(Ity_I64);
+ t5 = newTemp(Ity_I64);
+ /* dst = src0 + (-1 * src1)
+ if(sign(src0 ) != sign((-1 * src1) ))
+ goto no overflow;
+ if(sign(dst) == sign(src0 ))
+ goto no overflow;
+ we have overflow! */
- default:
- return -1;
- }
+ assign(t5, binop(Iop_Mul64,
+ mkexpr(tmpRt64),
+ mkU64(0xffffffffffffffffULL)));
+ assign(t0, binop(Iop_Add64, mkexpr(tmpRs64), mkexpr(t5)));
+ assign(t1, binop(Iop_Xor64, mkexpr(tmpRs64), mkexpr(t5)));
+ assign(t2, unop(Iop_1Sto64,
+ binop(Iop_CmpEQ64,
+ binop(Iop_And64,
+ mkexpr(t1),
+ mkU64(0x8000000000000000ULL)),
+ mkU64(0x8000000000000000ULL))));
- return 0;
-}
+ assign(t3, binop(Iop_Xor64, mkexpr(t0), mkexpr(tmpRs64)));
+ assign(t4, unop(Iop_1Sto64,
+ binop(Iop_CmpNE64,
+ binop(Iop_And64,
+ mkexpr(t3),
+ mkU64(0x8000000000000000ULL)),
+ mkU64(0x8000000000000000ULL))));
-static Int msa_2R(UInt cins, UChar wd, UChar ws) { /* 2R */
- IRTemp t1, t2, t3, t4;
- IRType ty;
- UShort operation;
- UChar df;
+ stmt(IRStmt_Exit(binop(Iop_CmpEQ64, binop(Iop_Or64, mkexpr(t2),
+ mkexpr(t4)), mkU64(0)), Ijk_SigFPE_IntOvf,
+ IRConst_U64(guest_PC_curr_instr + 4),
+ OFFB_PC));
- vassert((cins & 0x00200000) == 0);
+ putIReg(rd, binop(Iop_Sub64, getIReg(rs), getIReg(rt)));
+ break;
+ }
- operation = (cins & 0x03FC0000) >> 18;
- df = (cins & 0x00030000) >> 16;
- ty = mode64 ? Ity_I64 : Ity_I32;
+ case 0x2F: /* Doubleword Subtract Unsigned - DSUBU; MIPS64 */
+ DIP("dsub r%u, r%u,r%u", rd, rt, rt);
+ ALU_PATTERN(Iop_Sub64);
+ break;
- switch (operation) {
- case 0xC0: { /* FILL.df */
- t1 = newTemp(Ity_I64);
+ case 0x30: { /* TGE */
+ DIP("tge r%u, r%u %u", rs, rt, trap_code);
- switch (df) {
- case 0x00: /* FILL.B */
- DIP("FILL.B w%d, r%d", wd, ws);
- t2 = newTemp(Ity_I32);
- t3 = newTemp(Ity_I16);
- t4 = newTemp(Ity_I8);
- assign(t4, mkNarrowTo8(ty, getIReg(ws)));
- assign(t3,
- binop(Iop_8HLto16, mkexpr(t4), mkexpr(t4)));
- assign(t2,
- binop(Iop_16HLto32, mkexpr(t3), mkexpr(t3)));
- assign(t1,
- binop(Iop_32HLto64, mkexpr(t2), mkexpr(t2)));
- break;
+ if (mode64) {
+ if (trap_code == 7)
+ stmt (IRStmt_Exit (unop (Iop_Not1,
+ binop (Iop_CmpLT64S,
+ getIReg (rs),
+ getIReg (rt))),
+ Ijk_SigFPE_IntDiv,
+ IRConst_U64(guest_PC_curr_instr + 4),
+ OFFB_PC));
+ else if (trap_code == 6)
+ stmt (IRStmt_Exit (unop (Iop_Not1,
+ binop (Iop_CmpLT64S,
+ getIReg (rs),
+ getIReg (rt))),
+ Ijk_SigFPE_IntOvf,
+ IRConst_U64(guest_PC_curr_instr + 4),
+ OFFB_PC));
+ else
+ stmt (IRStmt_Exit (unop (Iop_Not1,
+ binop (Iop_CmpLT64S,
+ getIReg (rs),
+ getIReg (rt))),
+ Ijk_SigTRAP,
+ IRConst_U64(guest_PC_curr_instr + 4),
+ OFFB_PC));
+ } else {
+ if (trap_code == 7)
+ stmt (IRStmt_Exit (unop (Iop_Not1,
+ binop (Iop_CmpLT32S,
+ getIReg (rs),
+ getIReg (rt))),
+ Ijk_SigFPE_IntDiv,
+ IRConst_U32(guest_PC_curr_instr + 4),
+ OFFB_PC));
+ else if (trap_code == 6)
+ stmt (IRStmt_Exit (unop (Iop_Not1,
+ binop (Iop_CmpLT32S,
+ getIReg (rs),
+ getIReg (rt))),
+ Ijk_SigFPE_IntOvf,
+ IRConst_U32(guest_PC_curr_instr + 4),
+ OFFB_PC));
+ else
+ stmt (IRStmt_Exit (unop (Iop_Not1,
+ binop (Iop_CmpLT32S,
+ getIReg (rs),
+ getIReg (rt))),
+ Ijk_SigTRAP,
+ IRConst_U32(guest_PC_curr_instr + 4),
+ OFFB_PC));
+ }
- case 0x01: /* FILL.H */
- DIP("FILL.H w%d, r%d", wd, ws);
- t2 = newTemp(Ity_I32);
- t3 = newTemp(Ity_I16);
- assign(t3, mkNarrowTo16(ty, getIReg(ws)));
- assign(t2,
- binop(Iop_16HLto32, mkexpr(t3), mkexpr(t3)));
- assign(t1,
- binop(Iop_32HLto64, mkexpr(t2), mkexpr(t2)));
- break;
+ break;
+ }
- case 0x02: /* FILL.W */
- DIP("FILL.W w%d, r%d", wd, ws);
- t2 = newTemp(Ity_I32);
- assign(t2, mkNarrowTo32(ty, getIReg(ws)));
- assign(t1,
- binop(Iop_32HLto64, mkexpr(t2), mkexpr(t2)));
- break;
+ case 0x31: { /* TGEU */
+ DIP("tgeu r%u, r%u %u", rs, rt, trap_code);
- case 0x03: /* FILL.D */
- if (mode64) {
- DIP("FILL.W w%d, r%d", wd, ws);
- t2 = newTemp(Ity_I32);
- assign(t1, getIReg(ws));
- } else {
- return -2;
- }
+ if (mode64) {
+ if (trap_code == 7)
+ stmt (IRStmt_Exit (unop (Iop_Not1,
+ binop (Iop_CmpLT64U,
+ getIReg (rs),
+ getIReg (rt))),
+ Ijk_SigFPE_IntDiv,
+ IRConst_U64(guest_PC_curr_instr + 4),
+ OFFB_PC));
+ else if (trap_code == 6)
+ stmt (IRStmt_Exit (unop (Iop_Not1,
+ binop (Iop_CmpLT64U,
+ getIReg (rs),
+ getIReg (rt))),
+ Ijk_SigFPE_IntOvf,
+ IRConst_U64(guest_PC_curr_instr + 4),
+ OFFB_PC));
+ else
+ stmt (IRStmt_Exit (unop (Iop_Not1,
+ binop (Iop_CmpLT64U,
+ getIReg (rs),
+ getIReg (rt))),
+ Ijk_SigTRAP,
+ IRConst_U64(guest_PC_curr_instr + 4),
+ OFFB_PC));
+ } else {
+ if (trap_code == 7)
+ stmt (IRStmt_Exit (unop (Iop_Not1,
+ binop (Iop_CmpLT32U,
+ getIReg (rs),
+ getIReg (rt))),
+ Ijk_SigFPE_IntDiv,
+ IRConst_U32(guest_PC_curr_instr + 4),
+ OFFB_PC));
+ else if (trap_code == 6)
+ stmt (IRStmt_Exit (unop (Iop_Not1,
+ binop (Iop_CmpLT32U,
+ getIReg (rs),
+ getIReg (rt))),
+ Ijk_SigFPE_IntOvf,
+ IRConst_U32(guest_PC_curr_instr + 4),
+ OFFB_PC));
+ else
+ stmt (IRStmt_Exit (unop (Iop_Not1,
+ binop (Iop_CmpLT32U,
+ getIReg (rs),
+ getIReg (rt))),
+ Ijk_SigTRAP,
+ IRConst_U32(guest_PC_curr_instr + 4),
+ OFFB_PC));
+ }
- break;
+ break;
+ }
- default:
- return -1;
- }
+ case 0x32: { /* TLT */
+ DIP("tlt r%u, r%u %u", rs, rt, trap_code);
- putWReg(wd,
- binop(Iop_64HLtoV128, mkexpr(t1), mkexpr(t1)));
- break;
+ if (mode64) {
+ if (trap_code == 7)
+ stmt(IRStmt_Exit(binop(Iop_CmpLT64S, getIReg(rs),
+ getIReg(rt)), Ijk_SigFPE_IntDiv,
+ IRConst_U64(guest_PC_curr_instr + 4),
+ OFFB_PC));
+ else if (trap_code == 6)
+ stmt(IRStmt_Exit(binop(Iop_CmpLT64S, getIReg(rs),
+ getIReg(rt)), Ijk_SigFPE_IntOvf,
+ IRConst_U64(guest_PC_curr_instr + 4),
+ OFFB_PC));
+ else
+ stmt(IRStmt_Exit(binop(Iop_CmpLT64S, getIReg(rs),
+ getIReg(rt)), Ijk_SigTRAP,
+ IRConst_U64(guest_PC_curr_instr + 4),
+ OFFB_PC));
+ } else {
+ if (trap_code == 7)
+ stmt(IRStmt_Exit(binop(Iop_CmpLT32S, getIReg(rs),
+ getIReg(rt)), Ijk_SigFPE_IntDiv,
+ IRConst_U32(guest_PC_curr_instr + 4),
+ OFFB_PC));
+ else if (trap_code == 6)
+ stmt(IRStmt_Exit(binop(Iop_CmpLT32S, getIReg(rs),
+ getIReg(rt)), Ijk_SigFPE_IntOvf,
+ IRConst_U32(guest_PC_curr_instr + 4),
+ OFFB_PC));
+ else
+ stmt(IRStmt_Exit(binop(Iop_CmpLT32S, getIReg(rs),
+ getIReg(rt)), Ijk_SigTRAP,
+ IRConst_U32(guest_PC_curr_instr + 4),
+ OFFB_PC));
}
- case 0xC1: { /* PCNT.df */
- switch (df) {
- case 0x00: /* PCNT.B */
- DIP("PCNT.B w%d, r%d", wd, ws);
- putWReg(wd,
- unop(Iop_Cnt8x16, getWReg(ws)));
- break;
+ break;
+ }
- case 0x01: /* PCNT.H */
- DIP("PCNT.H w%d, r%d", wd, ws);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- assign(t1, unop(Iop_Cnt8x16, getWReg(ws)));
- assign(t2,
- binop(Iop_Add16x8,
- binop(Iop_AndV128,
- mkexpr(t1),
- binop(Iop_64HLtoV128,
- mkU64(0x00FF00FF00FF00FFULL),
- mkU64(0x00FF00FF00FF00FFULL))),
- binop(Iop_AndV128,
- binop(Iop_ShrN16x8,
- mkexpr(t1), mkU8(8)),
- binop(Iop_64HLtoV128,
- mkU64(0x00FF00FF00FF00FFULL),
- mkU64(0x00FF00FF00FF00FFULL)))));
- putWReg(wd, mkexpr(t2));
- break;
+ case 0x33: { /* TLTU */
+ DIP("tltu r%u, r%u %u", rs, rt, trap_code);
- case 0x02: /* PCNT.W */
- DIP("PCNT.W w%d, r%d", wd, ws);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, unop(Iop_Cnt8x16, getWReg(ws)));
- assign(t2,
- binop(Iop_Add32x4,
- binop(Iop_AndV128,
- mkexpr(t1),
- binop(Iop_64HLtoV128,
- mkU64(0x00FF00FF00FF00FFULL),
- mkU64(0x00FF00FF00FF00FFULL))),
- binop(Iop_AndV128,
- binop(Iop_ShrN32x4,
- mkexpr(t1), mkU8(8)),
- binop(Iop_64HLtoV128,
- mkU64(0x00FF00FF00FF00FFULL),
- mkU64(0x00FF00FF00FF00FFULL)))));
- assign(t3,
- binop(Iop_Add32x4,
- binop(Iop_AndV128,
- mkexpr(t2),
- binop(Iop_64HLtoV128,
- mkU64(0x0000FFFF0000FFFFULL),
- mkU64(0x0000FFFF0000FFFFULL))),
- binop(Iop_AndV128,
- binop(Iop_ShrN32x4,
- mkexpr(t2), mkU8(16)),
- binop(Iop_64HLtoV128,
- mkU64(0x0000FFFF0000FFFFULL),
- mkU64(0x0000FFFF0000FFFFULL)))));
- putWReg(wd, mkexpr(t3));
- break;
+ if (mode64) {
+ if (trap_code == 7)
+ stmt(IRStmt_Exit(binop(Iop_CmpLT64U, getIReg(rs),
+ getIReg(rt)), Ijk_SigFPE_IntDiv,
+ IRConst_U64(guest_PC_curr_instr + 4),
+ OFFB_PC));
+ else if (trap_code == 6)
+ stmt(IRStmt_Exit(binop(Iop_CmpLT64U, getIReg(rs),
+ getIReg(rt)), Ijk_SigFPE_IntOvf,
+ IRConst_U64(guest_PC_curr_instr + 4),
+ OFFB_PC));
+ else
+ stmt(IRStmt_Exit(binop(Iop_CmpLT64U, getIReg(rs),
+ getIReg(rt)), Ijk_SigTRAP,
+ IRConst_U64(guest_PC_curr_instr + 4),
+ OFFB_PC));
+ } else {
+ if (trap_code == 7)
+ stmt(IRStmt_Exit(binop(Iop_CmpLT32U, getIReg(rs),
+ getIReg(rt)), Ijk_SigFPE_IntDiv,
+ IRConst_U32(guest_PC_curr_instr + 4),
+ OFFB_PC));
+ else if (trap_code == 6)
+ stmt(IRStmt_Exit(binop(Iop_CmpLT32U, getIReg(rs),
+ getIReg(rt)), Ijk_SigFPE_IntOvf,
+ IRConst_U32(guest_PC_curr_instr + 4),
+ OFFB_PC));
+ else
+ stmt(IRStmt_Exit(binop(Iop_CmpLT32U, getIReg(rs),
+ getIReg (rt)), Ijk_SigTRAP,
+ IRConst_U32(guest_PC_curr_instr + 4),
+ OFFB_PC));
+ }
- case 0x03: /* PCNT.D */
- DIP("PCNT.D w%d, r%d", wd, ws);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- t4 = newTemp(Ity_V128);;
- assign(t1, unop(Iop_Cnt8x16, getWReg(ws)));
- assign(t2,
- binop(Iop_Add64x2,
- binop(Iop_AndV128,
- mkexpr(t1),
- binop(Iop_64HLtoV128,
- mkU64(0x00FF00FF00FF00FFULL),
- mkU64(0x00FF00FF00FF00FFULL))),
- binop(Iop_AndV128,
- binop(Iop_ShrN64x2,
- mkexpr(t1), mkU8(8)),
- binop(Iop_64HLtoV128,
- mkU64(0x00FF00FF00FF00FFULL),
- mkU64(0x00FF00FF00FF00FFULL)))));
- assign(t3,
- binop(Iop_Add64x2,
- binop(Iop_AndV128,
- mkexpr(t2),
- binop(Iop_64HLtoV128,
- mkU64(0x0000FFFF0000FFFFULL),
- mkU64(0x0000FFFF0000FFFFULL))),
- binop(Iop_AndV128,
- binop(Iop_ShrN64x2,
- mkexpr(t2), mkU8(16)),
- binop(Iop_64HLtoV128,
- mkU64(0x0000FFFF0000FFFFULL),
- mkU64(0x0000FFFF0000FFFFULL)))));
- assign(t4,
- binop(Iop_Add64x2,
- binop(Iop_AndV128,
- mkexpr(t3),
- binop(Iop_64HLtoV128,
- mkU64(0x00000000FFFFFFFFULL),
- mkU64(0x00000000FFFFFFFFULL))),
- binop(Iop_AndV128,
- binop(Iop_ShrN64x2,
- mkexpr(t3), mkU8(32)),
- binop(Iop_64HLtoV128,
- mkU64(0x00000000FFFFFFFFULL),
- mkU64(0x00000000FFFFFFFFULL)))));
- putWReg(wd, mkexpr(t4));
- break;
+ break;
+ }
- default:
- return -1;
- }
+ case 0x34: { /* TEQ */
+ DIP("teq r%u, r%u, %u", rs, rt, trap_code);
- break;
+ if (mode64) {
+ if (trap_code == 7)
+ stmt(IRStmt_Exit(binop(Iop_CmpEQ64, getIReg(rs),
+ getIReg(rt)), Ijk_SigFPE_IntDiv,
+ IRConst_U64(guest_PC_curr_instr + 4),
+ OFFB_PC));
+ else if (trap_code == 6)
+ stmt(IRStmt_Exit(binop(Iop_CmpEQ64, getIReg(rs),
+ getIReg(rt)), Ijk_SigFPE_IntOvf,
+ IRConst_U64(guest_PC_curr_instr + 4),
+ OFFB_PC));
+ else
+ stmt(IRStmt_Exit(binop(Iop_CmpEQ64, getIReg(rs),
+ getIReg(rt)), Ijk_SigTRAP,
+ IRConst_U64(guest_PC_curr_instr + 4),
+ OFFB_PC));
+ } else {
+ if (trap_code == 7)
+ stmt(IRStmt_Exit(binop(Iop_CmpEQ32, getIReg(rs),
+ getIReg(rt)), Ijk_SigFPE_IntDiv,
+ IRConst_U32(guest_PC_curr_instr + 4),
+ OFFB_PC));
+ else if (trap_code == 6)
+ stmt(IRStmt_Exit(binop(Iop_CmpEQ32, getIReg(rs),
+ getIReg(rt)), Ijk_SigFPE_IntOvf,
+ IRConst_U32(guest_PC_curr_instr + 4),
+ OFFB_PC));
+ else
+ stmt(IRStmt_Exit(binop(Iop_CmpEQ32, getIReg(rs),
+ getIReg(rt)), Ijk_SigTRAP,
+ IRConst_U32(guest_PC_curr_instr + 4),
+ OFFB_PC));
}
- case 0xC2: { /* NLOC.df */
- switch (df) {
- case 0x00: /* NLOC.B */
- DIP("NLOC.B w%d, w%d", wd, ws);
- putWReg(wd,
- unop(Iop_Cls8x16, getWReg(ws)));
- break;
-
- case 0x01: /* NLOC.H */
- DIP("NLOC.H w%d, w%d", wd, ws);
- putWReg(wd,
- unop(Iop_Cls16x8, getWReg(ws)));
- break;
-
- case 0x02: /* NLOC.W */
- DIP("NLOC.W w%d, w%d", wd, ws);
- putWReg(wd,
- unop(Iop_Cls32x4, getWReg(ws)));
- break;
+ break;
+ }
- case 0x03: /* NLOC.D */
- DIP("NLOC.D w%d, w%d", wd, ws);
- t1 = newTemp(Ity_V128);
- assign(t1, unop(Iop_NotV128, getWReg(ws)));
- putWReg(wd, unop(Iop_Clz64x2, mkexpr(t1)));
- break;
+ case 0x35: { /* SELEQZ */
+ if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+ DIP("seleqz r%u, r%u, r%u", rd, rs, rt);
- default:
- return -1;
+ if (mode64) {
+ putIReg(rd, binop(Iop_And64,
+ unop(Iop_Not64,
+ unop(Iop_CmpwNEZ64, getIReg(rt))),
+ getIReg(rs)));
+ } else {
+ putIReg(rd, binop(Iop_And32,
+ unop(Iop_Not32,
+ unop(Iop_CmpwNEZ32, getIReg(rt))),
+ getIReg(rs)));
}
-
- break;
+ } else {
+ ILLEGAL_INSTRUCTON;
}
- case 0xC3: { /* NLZC.df */
- switch (df) {
- case 0x00: /* NLZC.B */
- DIP("NLZC.W w%d, w%d", wd, ws);
- putWReg(wd,
- unop(Iop_Clz8x16, getWReg(ws)));
- break;
+ break;
+ }
- case 0x01: /* NLZC.H */
- DIP("NLZC.H w%d, w%d", wd, ws);
- putWReg(wd,
- unop(Iop_Clz16x8, getWReg(ws)));
- break;
+ case 0x36: { /* TNE */
+ DIP("tne r%u, r%u %u", rs, rt, trap_code);
- case 0x02: /* NLZC.W */
- DIP("NLZC.W w%d, w%d", wd, ws);
- putWReg(wd,
- unop(Iop_Clz32x4, getWReg(ws)));
- break;
+ if (mode64) {
+ if (trap_code == 7)
+ stmt(IRStmt_Exit(binop(Iop_CmpNE64, getIReg(rs),
+ getIReg(rt)), Ijk_SigFPE_IntDiv,
+ IRConst_U64(guest_PC_curr_instr + 4),
+ OFFB_PC));
+ else if (trap_code == 6)
+ stmt(IRStmt_Exit(binop(Iop_CmpNE64, getIReg(rs),
+ getIReg(rt)), Ijk_SigFPE_IntOvf,
+ IRConst_U64(guest_PC_curr_instr + 4),
+ OFFB_PC));
+ else
+ stmt(IRStmt_Exit(binop(Iop_CmpNE64, getIReg(rs),
+ getIReg(rt)), Ijk_SigTRAP,
+ IRConst_U64(guest_PC_curr_instr + 4),
+ OFFB_PC));
+ } else {
+ if (trap_code == 7)
+ stmt(IRStmt_Exit(binop(Iop_CmpNE32, getIReg(rs),
+ getIReg(rt)), Ijk_SigFPE_IntDiv,
+ IRConst_U32(guest_PC_curr_instr + 4),
+ OFFB_PC));
+ else if (trap_code == 6)
+ stmt(IRStmt_Exit(binop(Iop_CmpNE32, getIReg(rs),
+ getIReg(rt)), Ijk_SigFPE_IntOvf,
+ IRConst_U32(guest_PC_curr_instr + 4),
+ OFFB_PC));
+ else
+ stmt(IRStmt_Exit(binop(Iop_CmpNE32, getIReg(rs),
+ getIReg(rt)), Ijk_SigTRAP,
+ IRConst_U32(guest_PC_curr_instr + 4),
+ OFFB_PC));
+ }
- case 0x03: {/* NLZC.D */
- putWReg(wd,
- unop(Iop_Clz64x2, getWReg(ws)));
- break;
- }
+ break;
+ }
- default:
- return -1;
+ case 0x37: { /* SELNEZ */
+ if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+ DIP("selnez r%u, r%u, r%u", rd, rs, rt);
+
+ if (mode64) {
+ putIReg(rd, binop(Iop_And64,
+ unop(Iop_CmpwNEZ64, getIReg(rt)), getIReg(rs)));
+ } else {
+ putIReg(rd, binop(Iop_And32,
+ unop(Iop_CmpwNEZ32, getIReg(rt)), getIReg(rs)));
}
+ } else {
+ ILLEGAL_INSTRUCTON;
+ }
+
+ break;
+ }
+ case 0x14:
+ case 0x16:
+ case 0x17: /* DSLLV, DROTRV:DSRLV, DSRAV */
+ case 0x38:
+ case 0x3A:
+ case 0x3B: /* DSLL, DROTL:DSRL, DSRA */
+ case 0x3C:
+ case 0x3E:
+ case 0x3F: /* DSLL32, DROTR32:DSRL32, DSRA32 */
+ if (dis_instr_shrt(cins))
break;
- }
+
+ return -1;
default:
return -1;
return 0;
}
-static Int msa_2RF(UInt cins, UChar wd, UChar ws) { /* 2RF */
- IRTemp t1, t2, t3, t4, t5;
- UShort operation;
- UChar df, wt;
-
- operation = (cins & 0x03FE0000) >> 17;
- df = (cins & 0x00010000) >> 16;
- wt = (cins & 0x001F0000) >> 16;
+static UInt disInstr_MIPS_WRK_Special2(UInt cins, const VexArchInfo* archinfo,
+ const VexAbiInfo* abiinfo, DisResult* dres,
+ IRStmt** bstmt, IRExpr** lastn,
+ Bool(*resteerOkFn) (/*opaque */void *,
+ Addr),
+ void* callback_opaque)
+{
+ IRTemp t0, t1 = 0, t2, t3, t4, t5, t6;
+ UInt rs, rt, rd, function;
+ /* Additional variables for instruction fields in DSP ASE insructions */
+ UInt ac;
- switch (operation) {
+ rs = get_rs(cins);
+ rt = get_rt(cins);
+ rd = get_rd(cins);
+ function = get_function(cins);
+ IRType ty = mode64 ? Ity_I64 : Ity_I32;
- case 0x190: { /* FCLASS.df */
- IRTemp t0 = newTemp(Ity_V128);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- t4 = newTemp(Ity_V128);
- t5 = newTemp(Ity_V128);
+ ac = get_acNo(cins);
- switch (df) {
- case 0x00: { /* FCLASS.W */
- DIP("FCLASS.W w%d, w%d", wd, ws);
- assign(t0,
- binop(Iop_CmpEQ32x4,
- binop(Iop_AndV128,
- getWReg(ws),
- binop(Iop_64HLtoV128,
- mkU64(0x7F8000007F800000ull),
- mkU64(0x7F8000007F800000ull))),
- binop(Iop_64HLtoV128,
- mkU64(0ull), mkU64(0ull))));
- assign(t1,
- binop(Iop_CmpEQ32x4,
- binop(Iop_AndV128,
- getWReg(ws),
- binop(Iop_64HLtoV128,
- mkU64(0x7F8000007F800000ull),
- mkU64(0x7F8000007F800000ull))),
- binop(Iop_64HLtoV128,
- mkU64(0x7F8000007F800000ull),
- mkU64(0x7F8000007F800000ull))));
- assign(t2,
- binop(Iop_SarN32x4,
- getWReg(ws), mkU8(31)));
- assign(t3,
- binop(Iop_CmpEQ32x4,
- binop(Iop_AndV128,
- getWReg(ws),
- binop(Iop_64HLtoV128,
- mkU64(0x0040000000400000ull),
- mkU64(0x0040000000400000ull))),
- binop(Iop_64HLtoV128,
- mkU64(0x0040000000400000ull),
- mkU64(0x0040000000400000ull))));
- assign(t4,
- binop(Iop_CmpEQ32x4,
- binop(Iop_AndV128,
- getWReg(ws),
- binop(Iop_64HLtoV128,
- mkU64(0x007FFFFF007FFFFFULL),
- mkU64(0x007FFFFF007FFFFFULL))),
- binop(Iop_64HLtoV128,
- mkU64(0ull), mkU64(0ull))));
- assign(t5,
- binop(Iop_Shl32x4,
- binop(Iop_OrV128,
- binop(Iop_AndV128,
- mkexpr(t1),
- binop(Iop_AndV128,
- mkexpr(t4),
- binop(Iop_64HLtoV128,
- mkU64(0x100000001ull),
- mkU64(0x100000001ull)))),
- binop(Iop_OrV128,
- binop(Iop_AndV128,
- mkexpr(t0),
- binop(Iop_OrV128,
- binop(Iop_AndV128,
- mkexpr(t4),
- binop(Iop_64HLtoV128,
- mkU64(0x800000008ull),
- mkU64(0x800000008ull))),
- binop(Iop_AndV128,
- unop(Iop_NotV128,
- mkexpr(t4)),
- binop(Iop_64HLtoV128,
- mkU64(0x400000004ull),
- mkU64(0x400000004ull))))),
- binop(Iop_AndV128,
- unop(Iop_NotV128,
- mkexpr(t1)),
- binop(Iop_AndV128,
- unop(Iop_NotV128,
- mkexpr(t0)),
- binop(Iop_64HLtoV128,
- mkU64(0x200000002ull),
- mkU64(0x200000002ull)))))),
- binop(Iop_OrV128,
- binop(Iop_AndV128,
- mkexpr(t2),
- binop(Iop_64HLtoV128,
- mkU64(0x200000002ull),
- mkU64(0x200000002ull))),
- binop(Iop_AndV128,
- unop(Iop_NotV128,
- mkexpr(t2)),
- binop(Iop_64HLtoV128,
- mkU64(0x600000006ull),
- mkU64(0x600000006ull))))));
- putWReg(wd,
- binop(Iop_OrV128,
- mkexpr(t5),
- binop(Iop_AndV128,
- binop(Iop_CmpEQ32x4,
- mkexpr(t5),
- binop(Iop_64HLtoV128,
- mkU64(0ull),
- mkU64(0ull))),
- binop(Iop_OrV128,
- binop(Iop_AndV128,
- mkexpr(t3),
- binop(Iop_64HLtoV128,
- mkU64(0x100000001ull),
- mkU64(0x100000001ull))),
- binop(Iop_AndV128,
- unop(Iop_NotV128, mkexpr(t3)),
- binop(Iop_64HLtoV128,
- mkU64(0x200000002ull),
- mkU64(0x200000002ull)))))));
- break;
- }
+ switch (function) {
+ /* Cavium Specific instructions */
+ case 0x03:
+ case 0x32:
+ case 0x33: /* DMUL, CINS , CINS32 */
+ case 0x3A:
+ case 0x3B:
+ case 0x2B: /* EXT, EXT32, SNE */
- case 0x01: { /* FCLASS.D */
- DIP("FCLASS.D w%d, w%d", wd, ws);
- assign(t0,
- binop(Iop_CmpEQ64x2,
- binop(Iop_AndV128,
- getWReg(ws),
- binop(Iop_64HLtoV128,
- mkU64(0x7FF0000000000000ull),
- mkU64(0x7FF0000000000000ull))),
- binop(Iop_64HLtoV128,
- mkU64(0ull), mkU64(0ull))));
- assign(t1,
- binop(Iop_CmpEQ64x2,
- binop(Iop_AndV128,
- getWReg(ws),
- binop(Iop_64HLtoV128,
- mkU64(0x7FF0000000000000ull),
- mkU64(0x7FF0000000000000ull))),
- binop(Iop_64HLtoV128,
- mkU64(0x7FF0000000000000ull),
- mkU64(0x7FF0000000000000ull))));
- assign(t2,
- binop(Iop_SarN64x2,
- getWReg(ws), mkU8(63)));
- assign(t3,
- binop(Iop_CmpEQ64x2,
- binop(Iop_AndV128,
- getWReg(ws),
- binop(Iop_64HLtoV128,
- mkU64(0x0008000000000000ull),
- mkU64(0x0008000000000000ull))),
- binop(Iop_64HLtoV128,
- mkU64(0x0008000000000000ull),
- mkU64(0x0008000000000000ull))));
- assign(t4,
- binop(Iop_CmpEQ64x2,
- binop(Iop_AndV128,
- getWReg(ws),
- binop(Iop_64HLtoV128,
- mkU64(0x000FFFFFFFFFFFFFULL),
- mkU64(0x000FFFFFFFFFFFFFULL))),
- binop(Iop_64HLtoV128,
- mkU64(0ull), mkU64(0ull))));
- assign(t5,
- binop(Iop_Shl64x2,
- binop(Iop_OrV128,
- binop(Iop_AndV128,
- mkexpr(t1),
- binop(Iop_AndV128,
- mkexpr(t4),
- binop(Iop_64HLtoV128,
- mkU64(1ull),
- mkU64(1ull)))),
- binop(Iop_OrV128,
- binop(Iop_AndV128,
- mkexpr(t0),
- binop(Iop_OrV128,
- binop(Iop_AndV128,
- mkexpr(t4),
- binop(Iop_64HLtoV128,
- mkU64(8ull),
- mkU64(8ull))),
- binop(Iop_AndV128,
- unop(Iop_NotV128,
- mkexpr(t4)),
- binop(Iop_64HLtoV128,
- mkU64(4ull),
- mkU64(4ull))))),
- binop(Iop_AndV128,
- unop(Iop_NotV128,
- mkexpr(t1)),
- binop(Iop_AndV128,
- unop(Iop_NotV128,
- mkexpr(t0)),
- binop(Iop_64HLtoV128,
- mkU64(2ull),
- mkU64(2ull)))))),
- binop(Iop_OrV128,
- binop(Iop_AndV128,
- mkexpr(t2),
- binop(Iop_64HLtoV128,
- mkU64(2ull),
- mkU64(2ull))),
- binop(Iop_AndV128,
- unop(Iop_NotV128,
- mkexpr(t2)),
- binop(Iop_64HLtoV128,
- mkU64(6ull),
- mkU64(6ull))))));
- putWReg(wd,
- binop(Iop_OrV128,
- mkexpr(t5),
- binop(Iop_AndV128,
- binop(Iop_CmpEQ64x2,
- mkexpr(t5),
- binop(Iop_64HLtoV128,
- mkU64(0ull),
- mkU64(0ull))),
- binop(Iop_OrV128,
- binop(Iop_AndV128,
- mkexpr(t3),
- binop(Iop_64HLtoV128,
- mkU64(1ull),
- mkU64(1ull))),
- binop(Iop_AndV128,
- unop(Iop_NotV128,
- mkexpr(t3)),
- binop(Iop_64HLtoV128,
- mkU64(2ull),
- mkU64(2ull)))))));
- break;
- }
+ /* CVM Compare Instructions */
+ case 0x2A:
+ case 0x2E:
+ case 0x2F: /* SEQ, SEQI, SNEI */
- default:
- return -1;
- }
+ /* CPU Load, Store, Memory, and Control Instructions */
+ case 0x18:
+ case 0x19: /* SAA, SAAD */
+ case 0x1F: /* LAA, LAAD, LAI, LAID */
+ case 0x28:
+ case 0x2C:
+ case 0x2D: /* BADDU, POP, DPOP */
+ if (VEX_MIPS_COMP_ID(archinfo->hwcaps) == VEX_PRID_COMP_CAVIUM) {
+ if (dis_instr_CVM(cins))
+ break;
- break;
+ return -1;
+ } else {
+ return -1;
}
- case 0x191: { /* FTRUNC_S.df */
- switch (df) {
- case 0x00: { /* FTRUNC_S.W */
- DIP("FTRUNC_S.W w%d, w%d", wd, ws);
- calculateMSACSR(ws, wd, FTRUNCSW, 1);
- putWReg(wd, unop(Iop_F32toI32Sx4_RZ, getWReg(ws)));
- break;
- }
-
- case 0x01: { /* FTRUNC_S.D */
- DIP("FTRUNC_S.D w%d, w%d", wd, ws);
- calculateMSACSR(ws, wd, FTRUNCSD, 1);
- t1 = newTemp(Ity_I64);
- t2 = newTemp(Ity_I64);
- t3 = newTemp(Ity_V128);
- assign(t3,
- binop(Iop_AndV128,
- unop(Iop_NotV128,
- binop(Iop_CmpUN64Fx2,
- getWReg(ws),
- getWReg(ws))),
- binop(Iop_Max64Fx2,
- getWReg(ws),
- binop(Iop_64HLtoV128,
- mkU64(0xC3E0000000000000),
- mkU64(0xC3E0000000000000)))));
- assign(t1,
- binop(Iop_F64toI64S, mkU32(0x3),
- unop(Iop_ReinterpI64asF64,
- unop(Iop_V128to64, mkexpr(t3)))));
- assign(t2,
- binop(Iop_F64toI64S, mkU32(0x3),
- unop(Iop_ReinterpI64asF64,
- unop(Iop_V128HIto64, mkexpr(t3)))));
- putWReg(wd,
- binop(Iop_64HLtoV128,
- mkexpr(t2), mkexpr(t1)));
- break;
- }
-
- default:
- return -1;
- }
+ break;
- break;
- }
+ case 0x02: { /* MUL */
+ DIP("mul r%u, r%u, r%u", rd, rs, rt);
- case 0x192: { /* FTRUNC_U.df */
- switch (df) {
- case 0x00: { /* FTRUNC_U.W */
- DIP("FTRUNC_U.W w%d, w%d", wd, ws);
- calculateMSACSR(ws, wd, FTRUNCUW, 1);
- putWReg(wd, unop(Iop_F32toI32Ux4_RZ, getWReg(ws)));
- break;
- }
+ if (mode64) {
+ IRTemp tmpRs32 = newTemp(Ity_I32);
+ IRTemp tmpRt32 = newTemp(Ity_I32);
+ IRTemp tmpRes = newTemp(Ity_I32);
- case 0x01: { /* FTRUNC_U.D */
- DIP("FTRUNC_U.D w%d, w%d", wd, ws);
- calculateMSACSR(ws, wd, FTRUNCUD, 1);
- t1 = newTemp(Ity_I64);
- t2 = newTemp(Ity_I64);
- assign(t1,
- binop(Iop_F64toI64U,
- mkU32(0x3),
- unop(Iop_ReinterpI64asF64,
- unop(Iop_V128to64,
- getWReg(ws)))));
- assign(t2,
- binop(Iop_F64toI64U,
- mkU32(0x3),
- unop(Iop_ReinterpI64asF64,
- unop(Iop_V128HIto64,
- getWReg(ws)))));
- putWReg(wd,
- binop(Iop_64HLtoV128,
- mkexpr(t2), mkexpr(t1)));
- break;
- }
+ assign(tmpRs32, mkNarrowTo32(ty, getIReg(rs)));
+ assign(tmpRt32, mkNarrowTo32(ty, getIReg(rt)));
+ assign(tmpRes, binop(Iop_Mul32,
+ mkexpr(tmpRs32), mkexpr(tmpRt32)));
+ putIReg(rd, mkWidenFrom32(ty, mkexpr(tmpRes), True));
+ } else
+ putIReg(rd, binop(Iop_Mul32, getIReg(rs), getIReg(rt)));
- default:
- return -1;
- }
+ break;
+ }
- break;
- }
+ case 0x00: { /* MADD */
+ if (mode64) {
+ DIP("madd r%u, r%u", rs, rt);
+ t1 = newTemp(Ity_I32);
+ t2 = newTemp(Ity_I32);
+ t3 = newTemp(Ity_I64);
+ t4 = newTemp(Ity_I64);
+ t5 = newTemp(Ity_I64);
+ t6 = newTemp(Ity_I32);
- case 0x193: { /* FSQRT.df */
- switch (df) {
- case 0x00: { /* FSQRT.W */
- DIP("FSQRT.W w%d, w%d", wd, ws);
- IRExpr *rm = get_IR_roundingmode_MSA();
- calculateMSACSR(ws, wd, FSQRTW, 1);
- putWReg(wd, binop(Iop_Sqrt32Fx4, rm, getWReg(ws)));
- break;
- }
+ assign(t1, mkNarrowTo32(ty, getHI()));
+ assign(t2, mkNarrowTo32(ty, getLO()));
- case 0x01: { /* FSQRT.D */
- DIP("FSQRT.D w%d, w%d", wd, ws);
- IRExpr *rm = get_IR_roundingmode_MSA();
- calculateMSACSR(ws, wd, FSQRTD, 1);
- putWReg(wd, binop(Iop_Sqrt64Fx2, rm, getWReg(ws)));
- break;
- }
+ assign(t3, binop(Iop_MullS32, mkNarrowTo32(ty, getIReg(rs)),
+ mkNarrowTo32(ty, getIReg(rt))));
- default:
- return -1;
- }
+ assign(t4, binop(Iop_32HLto64, mkexpr(t1), mkexpr(t2)));
+ assign(t5, binop(Iop_Add64, mkexpr(t3), mkexpr(t4)));
- break;
- }
+ putHI(mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(t5)), True));
+ putLO(mkWidenFrom32(ty, unop(Iop_64to32, mkexpr(t5)), True));
+ } else {
+ if ( (1 <= ac) && ( 3 >= ac) ) {
+ if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
+ /* If DSP is present -> DSP ASE MADD */
+ UInt retVal = disDSPInstr_MIPS_WRK ( cins );
- case 0x194: { /* FRSQRT.df */
- switch (df) {
- case 0x00: { /* FRSQRT.W */
- DIP("FRSQRT.W w%d, w%d", wd, ws);
- calculateMSACSR(ws, wd, FRSQRTW, 1);
- putWReg(wd, unop(Iop_RSqrtEst32Fx4, getWReg(ws)));
- break;
+ if (0 != retVal ) {
+ return -2;
}
- case 0x01: { /* FRSQRT.D */
- DIP("FRSQRT.D w%d, w%d", wd, ws);
- calculateMSACSR(ws, wd, FRSQRTD, 1);
- putWReg(wd, unop(Iop_RSqrtEst64Fx2, getWReg(ws)));
- break;
- }
+ break;
+ } else {
+ return -2;
+ }
+ } else {
+ DIP("madd r%u, r%u", rs, rt);
+ t1 = newTemp(Ity_I32);
+ t2 = newTemp(Ity_I32);
+ t3 = newTemp(Ity_I64);
+ t4 = newTemp(Ity_I32);
+ t5 = newTemp(Ity_I32);
+ t6 = newTemp(Ity_I32);
- default:
- return -1;
- }
+ assign(t1, getHI());
+ assign(t2, getLO());
- break;
- }
+ assign(t3, binop(Iop_MullS32, getIReg(rs), getIReg(rt)));
- case 0x195: { /* FRCP.df */
- switch (df) { /* FRCP.W */
- case 0x00: {
- DIP("FRCP.W w%d, w%d", wd, ws);
- calculateMSACSR(ws, wd, FRCPW, 1);
- putWReg(wd, unop(Iop_RecipEst32Fx4, getWReg(ws)));
- break;
- }
+ assign(t4, binop(Iop_Add32, mkexpr(t2), unop(Iop_64to32,
+ mkexpr(t3))));
- case 0x01: { /* FRCP.D */
- DIP("FRCP.D w%d, w%d", wd, ws);
- calculateMSACSR(ws, wd, FRCPD, 1);
- putWReg(wd, unop(Iop_RecipEst64Fx2, getWReg(ws)));
- break;
- }
+ assign(t5, unop(Iop_1Uto32, binop(Iop_CmpLT32U, mkexpr(t4),
+ unop(Iop_64to32, mkexpr(t3)))));
+ assign(t6, binop(Iop_Add32, mkexpr(t5), mkexpr(t1)));
- default:
- return -1;
+ putHI(binop(Iop_Add32, mkexpr(t6), unop(Iop_64HIto32,
+ mkexpr(t3))));
+ putLO(mkexpr(t4));
+ break;
}
-
- break;
}
- case 0x196: { /* FRINT.df */
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- t4 = newTemp(Ity_V128);
- IRExpr *rm = get_IR_roundingmode_MSA();
- assign(t1, getWReg(ws));
+ break;
+ }
- switch (df) {
- case 0x00: { /* FRINT.W */
- DIP("FRINT.W w%d, w%d", wd, ws);
- calculateMSACSR(ws, wt, FRINTW, 1);
- assign(t2,
- binop(Iop_OrV128,
- binop(Iop_CmpLT32Fx4,
- mkexpr(t1),
- binop(Iop_64HLtoV128,
- mkU64(0xCF000000CF000000ull),
- mkU64(0xCF000000CF000000ull))),
- binop(Iop_CmpLT32Fx4,
- binop(Iop_64HLtoV128,
- mkU64(0x4F0000004F000000ull),
- mkU64(0x4F0000004F000000ull)),
- mkexpr(t1))));
- assign(t3,
- binop(Iop_CmpEQ32x4,
- binop(Iop_AndV128,
- mkexpr(t1),
- binop(Iop_64HLtoV128,
- mkU64(0x0040000000400000ull),
- mkU64(0x0040000000400000ull))),
- binop(Iop_64HLtoV128,
- mkU64(0x0040000000400000ull),
- mkU64(0x0040000000400000ull))));
- assign(t4,
- binop(Iop_CmpUN32Fx4,
- mkexpr(t1), mkexpr(t1)));
- IRTemp tmp[4];
- Int i;
+ case 0x01: { /* MADDU */
+ if (mode64) {
+ DIP("maddu r%u, r%u", rs, rt);
+ t1 = newTemp(Ity_I32);
+ t2 = newTemp(Ity_I32);
+ t3 = newTemp(Ity_I64);
+ t4 = newTemp(Ity_I64);
+ t5 = newTemp(Ity_I64);
+ t6 = newTemp(Ity_I32);
- for (i = 0; i < 4; i++) {
- tmp[i] = newTemp(Ity_I32);
- assign(tmp[i],
- unop(Iop_ReinterpF32asI32,
- binop(Iop_RoundF32toInt, rm,
- unop(Iop_ReinterpI32asF32,
- binop(Iop_GetElem32x4,
- mkexpr(t1), mkU8(i))))));
- }
+ assign(t1, mkNarrowTo32(ty, getHI()));
+ assign(t2, mkNarrowTo32(ty, getLO()));
- putWReg(wd,
- binop(Iop_OrV128,
- binop(Iop_OrV128,
- binop(Iop_AndV128,
- binop(Iop_OrV128,
- mkexpr(t2),
- binop(Iop_AndV128,
- mkexpr(t4),
- unop(Iop_NotV128,
- mkexpr(t3)))),
- mkexpr(t1)),
- binop(Iop_AndV128,
- binop(Iop_AndV128,
- mkexpr(t4),
- mkexpr(t3)),
- binop(Iop_64HLtoV128,
- mkU64(0x7FBFFFFF7FBFFFFF),
- mkU64(0x7FBFFFFF7FBFFFFF)))),
- binop(Iop_AndV128,
- unop(Iop_NotV128,
- binop(Iop_OrV128,
- mkexpr(t2),
- mkexpr(t4))),
- binop(Iop_OrV128,
- binop(Iop_64HLtoV128,
- binop(Iop_32HLto64,
- mkexpr(tmp[3]),
- mkexpr(tmp[2])),
- binop(Iop_32HLto64,
- mkexpr(tmp[1]),
- mkexpr(tmp[0]))),
- binop(Iop_AndV128,
- mkexpr(t1),
- binop(Iop_64HLtoV128,
- mkU64(0x8000000080000000ull),
- mkU64(0x8000000080000000ull)))
- ))));
- break;
- }
+ assign(t3, binop(Iop_MullU32, mkNarrowTo32(ty, getIReg(rs)),
+ mkNarrowTo32(ty, getIReg(rt))));
- case 0x01: { /* FRINT.D */
- DIP("FRINT.D w%d, w%d", wd, ws);
- calculateMSACSR(ws, wt, FRINTD, 1);
- assign(t2,
- binop(Iop_OrV128,
- binop(Iop_CmpLT64Fx2,
- mkexpr(t1),
- binop(Iop_64HLtoV128,
- mkU64(0xC3E0000000000000ull),
- mkU64(0xC3E0000000000000ull))),
- binop(Iop_CmpLT64Fx2,
- binop(Iop_64HLtoV128,
- mkU64(0x43E0000000000000ull),
- mkU64(0x43E0000000000000ull)),
- mkexpr(t1))));
- assign(t3,
- binop(Iop_CmpEQ64x2,
- binop(Iop_AndV128,
- getWReg(ws),
- binop(Iop_64HLtoV128,
- mkU64(0x0008000000000000ull),
- mkU64(0x0008000000000000ull))),
- binop(Iop_64HLtoV128,
- mkU64(0x0008000000000000ull),
- mkU64(0x0008000000000000ull))));
- assign(t4,
- binop(Iop_CmpUN64Fx2,
- mkexpr(t1), mkexpr(t1)));
- IRTemp tmp[2];
- Int i;
+ assign(t4, binop(Iop_32HLto64, mkexpr(t1), mkexpr(t2)));
+ assign(t5, binop(Iop_Add64, mkexpr(t3), mkexpr(t4)));
- for (i = 0; i < 2; i++) {
- tmp[i] = newTemp(Ity_I64);
- assign(tmp[i],
- unop(Iop_ReinterpF64asI64,
- binop(Iop_RoundF64toInt, rm,
- unop(Iop_ReinterpI64asF64,
- binop(Iop_GetElem64x2,
- mkexpr(t1), mkU8(i))))));
- }
+ putHI(mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(t5)), True));
+ putLO(mkWidenFrom32(ty, unop(Iop_64to32, mkexpr(t5)), True));
+ } else {
+ if ( (1 <= ac) && ( 3 >= ac) ) {
+ if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
+ /* If DSP is present -> DSP ASE MADDU */
+ UInt retVal = disDSPInstr_MIPS_WRK ( cins );
- putWReg(wd,
- binop(Iop_OrV128,
- binop(Iop_OrV128,
- binop(Iop_AndV128,
- binop(Iop_OrV128,
- mkexpr(t2),
- binop(Iop_AndV128,
- mkexpr(t4),
- unop(Iop_NotV128,
- mkexpr(t3)))),
- mkexpr(t1)),
- binop(Iop_AndV128,
- binop(Iop_AndV128,
- mkexpr(t4),
- mkexpr(t3)),
- binop(Iop_64HLtoV128,
- mkU64(0x7FF7FFFFFFFFFFFF),
- mkU64(0x7FF7FFFFFFFFFFFF)))),
- binop(Iop_AndV128,
- unop(Iop_NotV128,
- binop(Iop_OrV128,
- mkexpr(t2),
- mkexpr(t4))),
- binop(Iop_OrV128,
- binop(Iop_64HLtoV128,
- mkexpr(tmp[1]),
- mkexpr(tmp[0])),
- binop(Iop_AndV128,
- mkexpr(t1),
- binop(Iop_64HLtoV128,
- mkU64(0x8000000000000000ull),
- mkU64(0x8000000000000000ull))
- )))));
- break;
+ if (0 != retVal ) {
+ return -2;
}
- default:
- return -1;
- }
-
- break;
- }
+ break;
+ } else {
+ return -2;
+ }
+ } else {
+ DIP("maddu r%u, r%u", rs, rt);
+ t1 = newTemp(Ity_I32);
+ t2 = newTemp(Ity_I32);
+ t3 = newTemp(Ity_I64);
+ t4 = newTemp(Ity_I32);
+ t5 = newTemp(Ity_I32);
+ t6 = newTemp(Ity_I32);
- case 0x197: { /* FLOG2.df */
+ assign(t1, getHI());
+ assign(t2, getLO());
- switch (df) {
- case 0x00: { /* FLOG2.W */
- DIP("FLOG2.W w%d, w%d", wd, ws);
- calculateMSACSR(ws, wt, FLOG2W, 1);
- putWReg(wd, unop(Iop_Log2_32Fx4, getWReg(ws)));
- break;
- }
+ assign(t3, binop(Iop_MullU32, getIReg(rs), getIReg(rt)));
- case 0x01: { /* FLOG2.D */
- DIP("FLOG2.D w%d, w%d", wd, ws);
- calculateMSACSR(ws, wt, FLOG2D, 1);
- putWReg(wd, unop(Iop_Log2_64Fx2, getWReg(ws)));
- break;
- }
+ assign(t4, binop(Iop_Add32, mkexpr(t2), unop(Iop_64to32,
+ mkexpr(t3))));
+ assign(t5, unop(Iop_1Uto32, binop(Iop_CmpLT32U, mkexpr(t4),
+ unop(Iop_64to32, mkexpr(t3)))));
+ assign(t6, binop(Iop_Add32, mkexpr(t5), mkexpr(t1)));
- default:
- return -1;
+ putHI(binop(Iop_Add32, mkexpr(t6), unop(Iop_64HIto32,
+ mkexpr(t3))));
+ putLO(mkexpr(t4));
+ break;
}
-
- break;
}
- case 0x198: { /* FEXUPL.df */
- switch (df) {
- case 0x00: { /* FEXUPL.W */
- DIP("FEXUPL.W w%d, w%d", wd, ws);
- calculateMSACSR(ws, wt, FEXUPLW, 1);
- putWReg(wd,
- unop(Iop_F16toF32x4,
- unop(Iop_V128HIto64,
- getWReg(ws))));
- break;
- }
-
- case 0x01: { /* FEXUPL.D */
- DIP("FEXUPL.D w%d, w%d", wd, ws);
- calculateMSACSR(ws, wt, FEXUPLD, 1);
- t1 = newTemp(Ity_I64);
- t2 = newTemp(Ity_I64);
- assign(t1,
- unop(Iop_ReinterpF64asI64,
- unop(Iop_F32toF64,
- unop(Iop_ReinterpI32asF32,
- unop(Iop_64to32,
- unop(Iop_V128HIto64,
- getWReg(ws)))))));
- assign(t2,
- unop(Iop_ReinterpF64asI64,
- unop(Iop_F32toF64,
- unop(Iop_ReinterpI32asF32,
- unop(Iop_64HIto32,
- unop(Iop_V128HIto64,
- getWReg(ws)))))));
- putWReg(wd,
- binop(Iop_64HLtoV128,
- mkexpr(t2), mkexpr(t1)));
- break;
- }
-
- default:
- return -1;
- }
-
- break;
- }
+ break;
+ }
- case 0x199: { /* FEXUPR.df */
- switch (df) {
- case 0x00: { /* FEXUPR.W */
- DIP("FEXUPR.W w%d, w%d", wd, ws);
- calculateMSACSR(ws, wt, FEXUPRW, 1);
- putWReg(wd,
- unop(Iop_F16toF32x4,
- unop(Iop_V128to64,
- getWReg(ws))));
- break;
- }
+ case 0x04: { /* MSUB */
+ if (mode64) {
+ DIP("msub r%u, r%u", rs, rt);
+ t1 = newTemp(Ity_I32);
+ t2 = newTemp(Ity_I32);
+ t3 = newTemp(Ity_I64);
+ t4 = newTemp(Ity_I64);
+ t5 = newTemp(Ity_I64);
+ t6 = newTemp(Ity_I32);
- case 0x01: { /* FEXUPR.D */
- DIP("FEXUPR.D w%d, w%d", wd, ws);
- calculateMSACSR(ws, wt, FEXUPRD, 1);
- t1 = newTemp(Ity_I64);
- t2 = newTemp(Ity_I64);
- assign(t1,
- unop(Iop_ReinterpF64asI64,
- unop(Iop_F32toF64,
- unop(Iop_ReinterpI32asF32,
- unop(Iop_64to32,
- unop(Iop_V128to64,
- getWReg(ws)))))));
- assign(t2,
- unop(Iop_ReinterpF64asI64,
- unop(Iop_F32toF64,
- unop(Iop_ReinterpI32asF32,
- unop(Iop_64HIto32,
- unop(Iop_V128to64,
- getWReg(ws)))))));
- putWReg(wd,
- binop(Iop_64HLtoV128,
- mkexpr(t2), mkexpr(t1)));
- break;
- }
+ assign(t1, mkNarrowTo32(ty, getHI()));
+ assign(t2, mkNarrowTo32(ty, getLO()));
- default:
- return -1;
- }
+ assign(t3, binop(Iop_MullS32, mkNarrowTo32(ty, getIReg(rs)),
+ mkNarrowTo32(ty, getIReg(rt))));
- break;
- }
+ assign(t4, binop(Iop_32HLto64, mkexpr(t1), mkexpr(t2)));
+ assign(t5, binop(Iop_Sub64, mkexpr(t4), mkexpr(t3)));
- case 0x19A: { /* FFQL.df */
- switch (df) {
- case 0x00: { /* FFQL.W */
- DIP("FFQL.W w%d, w%d", wd, ws);
- calculateMSACSR(ws, wt, FFQLW, 1);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_I64);
- t3 = newTemp(Ity_I64);
- IRExpr *rm = get_IR_roundingmode_MSA();
- assign(t1,
- binop(Iop_SarN32x4,
- binop(Iop_InterleaveHI16x8,
- getWReg(ws),
- getWReg(ws)),
- mkU8(16)));
- assign(t2,
- binop(Iop_32HLto64,
- unop(Iop_ReinterpF32asI32,
- binop(Iop_I32StoF32, rm,
- binop(Iop_GetElem32x4,
- mkexpr(t1),
- mkU8(1)))),
- unop(Iop_ReinterpF32asI32,
- binop(Iop_I32StoF32, rm,
- binop(Iop_GetElem32x4,
- mkexpr(t1),
- mkU8(0))))));
- assign(t3,
- binop(Iop_32HLto64,
- unop(Iop_ReinterpF32asI32,
- binop(Iop_I32StoF32, rm,
- binop(Iop_GetElem32x4,
- mkexpr(t1),
- mkU8(3)))),
- unop(Iop_ReinterpF32asI32,
- binop(Iop_I32StoF32, rm,
- binop(Iop_GetElem32x4,
- mkexpr(t1),
- mkU8(2))))));
- putWReg(wd,
- triop(Iop_Div32Fx4, rm,
- binop(Iop_64HLtoV128,
- mkexpr(t3), mkexpr(t2)),
- binop(Iop_64HLtoV128,
- mkU64(0x4700000047000000),
- mkU64(0x4700000047000000))));
- break;
- }
+ putHI(mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(t5)), True));
+ putLO(mkWidenFrom32(ty, unop(Iop_64to32, mkexpr(t5)), True));
+ } else {
+ if ( (1 <= ac) && ( 3 >= ac) ) {
+ if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
+ /* If DSP is present -> DSP ASE MSUB */
+ UInt retVal = disDSPInstr_MIPS_WRK ( cins );
- case 0x01: { /* FFQL.D */
- DIP("FFQL.D w%d, w%d", wd, ws);
- calculateMSACSR(ws, wt, FFQLD, 1);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_I64);
- t3 = newTemp(Ity_I64);
- IRExpr *rm = get_IR_roundingmode_MSA();
- assign(t1,
- binop(Iop_SarN64x2,
- binop(Iop_InterleaveHI32x4,
- getWReg(ws),
- getWReg(ws)),
- mkU8(32)));
- assign(t2,
- unop(Iop_ReinterpF64asI64,
- binop(Iop_I64StoF64, rm,
- unop(Iop_V128to64,
- mkexpr(t1)))));
- assign(t3,
- unop(Iop_ReinterpF64asI64,
- binop(Iop_I64StoF64, rm,
- unop(Iop_V128HIto64,
- mkexpr(t1)))));
- putWReg(wd,
- triop(Iop_Div64Fx2, rm,
- binop(Iop_64HLtoV128,
- mkexpr(t3), mkexpr(t2)),
- binop(Iop_64HLtoV128,
- mkU64(0x41E0000000000000),
- mkU64(0x41E0000000000000))));
- break;
+ if (0 != retVal ) {
+ return -2;
}
- default:
- return -1;
- }
+ break;
+ } else {
+ return -2;
+ }
+ } else {
+ DIP("msub r%u, r%u", rs, rt);
+ t1 = newTemp(Ity_I32);
+ t2 = newTemp(Ity_I32);
+ t3 = newTemp(Ity_I64);
+ t4 = newTemp(Ity_I32);
+ t5 = newTemp(Ity_I1);
+ t6 = newTemp(Ity_I32);
- break;
- }
+ assign(t1, getHI());
+ assign(t2, getLO());
- case 0x19B: { /* FFQR.df */
- switch (df) {
- case 0x00: { /* FFQR.W */
- DIP("FFQR.W w%d, w%d", wd, ws);
- calculateMSACSR(ws, wt, FFQRW, 1);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_I64);
- t3 = newTemp(Ity_I64);
- IRExpr *rm = get_IR_roundingmode_MSA();
- assign(t1,
- binop(Iop_SarN32x4,
- binop(Iop_InterleaveLO16x8,
- getWReg(ws),
- getWReg(ws)),
- mkU8(16)));
- assign(t2,
- binop(Iop_32HLto64,
- unop(Iop_ReinterpF32asI32,
- binop(Iop_I32StoF32, rm,
- binop(Iop_GetElem32x4,
- mkexpr(t1),
- mkU8(1)))),
- unop(Iop_ReinterpF32asI32,
- binop(Iop_I32StoF32, rm,
- binop(Iop_GetElem32x4,
- mkexpr(t1),
- mkU8(0))))));
- assign(t3,
- binop(Iop_32HLto64,
- unop(Iop_ReinterpF32asI32,
- binop(Iop_I32StoF32, rm,
- binop(Iop_GetElem32x4,
- mkexpr(t1),
- mkU8(3)))),
- unop(Iop_ReinterpF32asI32,
- binop(Iop_I32StoF32, rm,
- binop(Iop_GetElem32x4,
- mkexpr(t1),
- mkU8(2))))));
- putWReg(wd,
- triop(Iop_Div32Fx4, rm,
- binop(Iop_64HLtoV128,
- mkexpr(t3), mkexpr(t2)),
- binop(Iop_64HLtoV128,
- mkU64(0x4700000047000000),
- mkU64(0x4700000047000000))));
- break;
- }
+ assign(t3, binop(Iop_MullS32, getIReg(rs), getIReg(rt)));
+ assign(t4, unop(Iop_64to32, mkexpr(t3))); /* new lo */
- case 0x01: { /* FFQR.D */
- DIP("FFQR.D w%d, w%d", wd, ws);
- calculateMSACSR(ws, wt, FFQRD, 1);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_I64);
- t3 = newTemp(Ity_I64);
- IRExpr *rm = get_IR_roundingmode_MSA();
- assign(t1,
- binop(Iop_SarN64x2,
- binop(Iop_InterleaveLO32x4,
- getWReg(ws),
- getWReg(ws)),
- mkU8(32)));
- assign(t2,
- unop(Iop_ReinterpF64asI64,
- binop(Iop_I64StoF64, rm,
- unop(Iop_V128to64,
- mkexpr(t1)))));
- assign(t3,
- unop(Iop_ReinterpF64asI64,
- binop(Iop_I64StoF64, rm,
- unop(Iop_V128HIto64,
- mkexpr(t1)))));
- putWReg(wd,
- triop(Iop_Div64Fx2, rm,
- binop(Iop_64HLtoV128,
- mkexpr(t3), mkexpr(t2)),
- binop(Iop_64HLtoV128,
- mkU64(0x41E0000000000000),
- mkU64(0x41E0000000000000))));
- break;
- }
+ /* if lo<lo(mul) hi = hi - 1 */
+ assign(t5, binop(Iop_CmpLT32U,
+ mkexpr(t2),
+ mkexpr(t4)));
- default:
- return -1;
- }
+ assign(t6, IRExpr_ITE(mkexpr(t5),
+ binop(Iop_Sub32, mkexpr(t1), mkU32(0x1)),
+ mkexpr(t1)));
- break;
+ putHI(binop(Iop_Sub32, mkexpr(t6), unop(Iop_64HIto32,
+ mkexpr(t3))));
+ putLO(binop(Iop_Sub32, mkexpr(t2), mkexpr(t4)));
+ break;
+ }
}
- case 0x19C: { /* FTINT_S.df */
- switch (df) { /* FTINT_S.W */
- case 0x00: {
- DIP("FTINT_S.W w%d, w%d", wd, ws);
- calculateMSACSR(ws, wd, FTINT_SW, 1);
- t1 = newTemp(Ity_I64);
- t2 = newTemp(Ity_I64);
- t3 = newTemp(Ity_V128);
- t4 = newTemp(Ity_I32);
- assign(t3,
- binop(Iop_AndV128,
- unop(Iop_NotV128,
- binop(Iop_CmpUN32Fx4,
- getWReg(ws),
- getWReg(ws))),
- binop(Iop_Max32Fx4,
- getWReg(ws),
- binop(Iop_64HLtoV128,
- mkU64(0xCF000000CF000000),
- mkU64(0xCF000000CF000000)))));
- IRExpr *rm = get_IR_roundingmode_MSA();
- assign(t1,
- binop(Iop_32HLto64,
- binop(Iop_F32toI32S, rm,
- unop(Iop_ReinterpI32asF32,
- binop(Iop_GetElem32x4,
- mkexpr(t3), mkU8(1)))),
- binop(Iop_F32toI32S, rm,
- unop(Iop_ReinterpI32asF32,
- binop(Iop_GetElem32x4,
- mkexpr(t3), mkU8(0))))));
- assign(t2,
- binop(Iop_32HLto64,
- binop(Iop_F32toI32S, rm,
- unop(Iop_ReinterpI32asF32,
- binop(Iop_GetElem32x4,
- mkexpr(t3), mkU8(3)))),
- binop(Iop_F32toI32S, rm,
- unop(Iop_ReinterpI32asF32,
- binop(Iop_GetElem32x4,
- mkexpr(t3), mkU8(2))))));
- putWReg(wd,
- binop(Iop_64HLtoV128,
- mkexpr(t2), mkexpr(t1)));
- break;
- }
+ break;
+ }
- case 0x01: { /* FTINT_S.D */
- DIP("FTINT_S.D w%d, w%d", wd, ws);
- calculateMSACSR(ws, wd, FTINT_SD, 1);
- t1 = newTemp(Ity_I64);
- t2 = newTemp(Ity_I64);
- t3 = newTemp(Ity_V128);
- assign(t3,
- binop(Iop_AndV128,
- unop(Iop_NotV128,
- binop(Iop_CmpUN64Fx2,
- getWReg(ws),
- getWReg(ws))),
- binop(Iop_Max64Fx2,
- getWReg(ws),
- binop(Iop_64HLtoV128,
- mkU64(0xC3E0000000000000),
- mkU64(0xC3E0000000000000)))));
- IRExpr *rm = get_IR_roundingmode_MSA();
- assign(t1,
- binop(Iop_F64toI64S, rm,
- unop(Iop_ReinterpI64asF64,
- unop(Iop_V128to64, mkexpr(t3)))));
- assign(t2,
- binop(Iop_F64toI64S, rm,
- unop(Iop_ReinterpI64asF64,
- unop(Iop_V128HIto64, mkexpr(t3)))));
- putWReg(wd,
- binop(Iop_64HLtoV128,
- mkexpr(t2), mkexpr(t1)));
- break;
- }
+ case 0x05: { /* MSUBU */
+ if (mode64) {
+ DIP("msubu r%u, r%u", rs, rt);
+ t1 = newTemp(Ity_I32);
+ t2 = newTemp(Ity_I32);
+ t3 = newTemp(Ity_I64);
+ t4 = newTemp(Ity_I64);
+ t5 = newTemp(Ity_I64);
+ t6 = newTemp(Ity_I32);
- default:
- return -1;
- }
+ assign(t1, mkNarrowTo32(ty, getHI()));
+ assign(t2, mkNarrowTo32(ty, getLO()));
- break;
- }
+ assign(t3, binop(Iop_MullU32, mkNarrowTo32(ty, getIReg(rs)),
+ mkNarrowTo32(ty, getIReg(rt))));
- case 0x19D: {/* FTINT_U.df */
- switch (df) { /* FTINT_U.W */
- case 0x00: {
- DIP("FTINT_U.W w%d, w%d", wd, ws);
- calculateMSACSR(ws, wd, FTINT_UW, 1);
- t1 = newTemp(Ity_I64);
- t2 = newTemp(Ity_I64);
- t3 = newTemp(Ity_V128);
- t4 = newTemp(Ity_V128);
- IRExpr *rm = get_IR_roundingmode_MSA();
- assign(t1,
- binop(Iop_32HLto64,
- binop(Iop_F32toI32U, rm,
- unop(Iop_ReinterpI32asF32,
- binop(Iop_GetElem32x4,
- getWReg(ws), mkU8(1)))),
- binop(Iop_F32toI32U, rm,
- unop(Iop_ReinterpI32asF32,
- binop(Iop_GetElem32x4,
- getWReg(ws), mkU8(0))))));
- assign(t2,
- binop(Iop_32HLto64,
- binop(Iop_F32toI32U, rm,
- unop(Iop_ReinterpI32asF32,
- binop(Iop_GetElem32x4,
- getWReg(ws), mkU8(3)))),
- binop(Iop_F32toI32U, rm,
- unop(Iop_ReinterpI32asF32,
- binop(Iop_GetElem32x4,
- getWReg(ws), mkU8(2))))));
- assign(t3,
- unop(Iop_NotV128,
- binop(Iop_SarN32x4,
- getWReg(ws),
- mkU8(31))));
- assign(t4,
- binop(Iop_CmpLT32Fx4,
- getWReg(ws),
- binop(Iop_64HLtoV128,
- mkU64(0x4EFFFFFF4EFFFFFF),
- mkU64(0x4EFFFFFF4EFFFFFF))));
- putWReg(wd,
- binop(Iop_OrV128,
- binop(Iop_AndV128,
- mkexpr(t4),
- binop(Iop_AndV128,
- binop(Iop_64HLtoV128,
- mkexpr(t2),
- mkexpr(t1)),
- mkexpr(t3))),
- binop(Iop_AndV128,
- unop(Iop_NotV128, mkexpr(t4)),
- unop(Iop_F32toI32Ux4_RZ,
- getWReg(ws)))));
- break;
- }
+ assign(t4, binop(Iop_32HLto64, mkexpr(t1), mkexpr(t2)));
+ assign(t5, binop(Iop_Sub64, mkexpr(t4), mkexpr(t3)));
- case 0x01: { /* FTINT_U.D */
- DIP("FTINT_U.D w%d, w%d", wd, ws);
- calculateMSACSR(ws, wd, FTINT_UD, 1);
- t1 = newTemp(Ity_I64);
- t2 = newTemp(Ity_I64);
- IRExpr *rm = get_IR_roundingmode_MSA();
- assign(t1,
- binop(Iop_F64toI64U, rm,
- unop(Iop_ReinterpI64asF64,
- unop(Iop_V128to64,
- getWReg(ws)))));
- assign(t2,
- binop(Iop_F64toI64U, rm,
- unop(Iop_ReinterpI64asF64,
- unop(Iop_V128HIto64,
- getWReg(ws)))));
- putWReg(wd,
- binop(Iop_64HLtoV128,
- mkexpr(t2), mkexpr(t1)));
- break;
- }
+ putHI(mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(t5)), True));
+ putLO(mkWidenFrom32(ty, unop(Iop_64to32, mkexpr(t5)), True));
+ } else {
+ if ( (1 <= ac) && ( 3 >= ac) ) {
+ if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
+ /* If DSP is present -> DSP ASE MSUBU */
+ UInt retVal = disDSPInstr_MIPS_WRK ( cins );
- default:
- return -1;
- }
+ if (0 != retVal ) {
+ return -2;
+ }
- break;
- }
+ break;
+ } else {
+ return -2;
+ }
+ } else {
+ DIP("msubu r%u, r%u", rs, rt);
+ t1 = newTemp(Ity_I32);
+ t2 = newTemp(Ity_I32);
+ t3 = newTemp(Ity_I64);
+ t4 = newTemp(Ity_I32);
+ t5 = newTemp(Ity_I1);
+ t6 = newTemp(Ity_I32);
- case 0x19E: { /* FFINT_S.df */
- t1 = newTemp(Ity_V128);
- assign(t1, getWReg(ws));
- IRExpr *rm = get_IR_roundingmode_MSA();
+ assign(t1, getHI());
+ assign(t2, getLO());
- switch (df) {
- case 0x00: { /* FFINT_S.W */
- DIP("FFINT_S.W w%d, w%d", wd, ws);
- calculateMSACSR(ws, wt, FFINTSW, 1);
- IRTemp tmp[4];
- Int i;
+ assign(t3, binop(Iop_MullU32, getIReg(rs), getIReg(rt)));
+ assign(t4, unop(Iop_64to32, mkexpr(t3))); /* new lo */
- for (i = 0; i < 4; i++) {
- tmp[i] = newTemp(Ity_F32);
- assign(tmp[i],
- binop(Iop_I32StoF32, rm,
- binop(Iop_GetElem32x4,
- mkexpr(t1), mkU8(i))));
- }
+ /* if lo<lo(mul) hi = hi - 1 */
+ assign(t5, binop(Iop_CmpLT32U,
+ mkexpr(t2),
+ mkexpr(t4)));
- putWReg(wd,
- binop(Iop_64HLtoV128,
- binop(Iop_32HLto64,
- unop(Iop_ReinterpF32asI32,
- mkexpr(tmp[3])),
- unop(Iop_ReinterpF32asI32,
- mkexpr(tmp[2]))),
- binop(Iop_32HLto64,
- unop(Iop_ReinterpF32asI32,
- mkexpr(tmp[1])),
- unop(Iop_ReinterpF32asI32,
- mkexpr(tmp[0])))));
- break;
- }
+ assign(t6, IRExpr_ITE(mkexpr(t5),
+ binop(Iop_Sub32,
+ mkexpr(t1),
+ mkU32(0x1)),
+ mkexpr(t1)));
- case 0x01: { /* FFINT_S.D */
- DIP("FFINT_S.D w%d, w%d", wd, ws);
- calculateMSACSR(ws, wt, FFINTSD, 1);
- IRTemp tmp[2];
- Int i;
+ putHI(binop(Iop_Sub32, mkexpr(t6), unop(Iop_64HIto32,
+ mkexpr(t3))));
+ putLO(binop(Iop_Sub32, mkexpr(t2), mkexpr(t4)));
+ break;
+ }
+ }
- for (i = 0; i < 2; i++) {
- tmp[i] = newTemp(Ity_F64);
- assign(tmp[i],
- binop(Iop_I64StoF64, rm,
- binop(Iop_GetElem64x2,
- mkexpr(t1), mkU8(i))));
- }
+ break;
+ }
- putWReg(wd,
- binop(Iop_64HLtoV128,
- unop(Iop_ReinterpF64asI64,
- mkexpr(tmp[1])),
- unop(Iop_ReinterpF64asI64,
- mkexpr(tmp[0]))));
- break;
- }
+ case 0x6: /* dmul MIPS64 - Netlogic */
+ DIP("dmul r%u, r%u, r%u", rd, rs, rt);
+ t0 = newTemp(Ity_I128);
- default:
- return -1;
- }
+ assign(t0, binop(Iop_MullU64, getIReg(rs), getIReg(rt)));
- break;
- }
+ putIReg(rd, unop(Iop_128to64, mkexpr(t0)));
+ break;
- case 0x19F: { /* FFINT_U.df */
- IRExpr *rm = get_IR_roundingmode_MSA();
+ case 0x10: /* LDADDW - Swap Word - Netlogic */
+ DIP("ldaddw r%u, r%u", rt, rs);
+ t0 = newTemp(Ity_I32);
+ t1 = newTemp(Ity_I32);
+ t2 = newTemp(Ity_I32);
+ t3 = newTemp(Ity_I64);
+ t4 = newTemp(Ity_I32);
+ t5 = newTemp(Ity_I32);
+ t6 = newTemp(Ity_I32);
- switch (df) {
- case 0x00: { /* FFINT_U.W */
- DIP("FFINT_U.W w%d, w%d", wd, ws);
- calculateMSACSR(ws, wt, FFINT_UW, 1);
- putWReg(wd, unop(Iop_I32UtoF32x4_DEP, getWReg(ws)));
- break;
- }
+ /* v = GPR[rt] */
+ assign(t0, mkNarrowTo32(ty, getIReg(rt)));
- case 0x01: { /* FFINT_U.D */
- DIP("FFINT_U.D w%d, w%d",
- wd, ws);
- calculateMSACSR(ws, wt,
- FFINT_UD, 1);
- t1 = newTemp(Ity_I64);
- t2 = newTemp(Ity_I64);
- assign(t1,
- unop(Iop_ReinterpF64asI64,
- binop(Iop_I64UtoF64, rm,
- unop(Iop_V128to64,
- getWReg(ws)))));
- assign(t2,
- unop(Iop_ReinterpF64asI64,
- binop(Iop_I64UtoF64, rm,
- unop(Iop_V128HIto64,
- getWReg(ws)))));
- putWReg(wd,
- binop(Iop_64HLtoV128,
- mkexpr(t2), mkexpr(t1)));
- break;
- }
+ /* GPR[rt] = memory[base]; */
+ assign(t1, load(Ity_I32, getIReg(rs)));
+ putIReg(rt, mkWidenFrom32(ty, mkexpr(t1), True));
- default:
- return -1;
- }
+ /* memory[base] = memory[base] + v; */
+ store(getIReg(rs), binop(Iop_Add32, mkexpr(t0), mkexpr(t1)));
+ break;
- break;
- }
+ case 0x12: /* LDADDD - Swap Word - Netlogic */
+ DIP("ldaddw r%u, r%u", rt, rs);
+ t0 = newTemp(Ity_I64);
+ t1 = newTemp(Ity_I64);
- default:
- return -1;
- }
+ /* v = GPR[rt] */
+ assign(t0, getIReg(rt));
- return 0;
-}
+ /* GPR[rt] = memory[base]; */
+ assign(t1, load(Ity_I64, getIReg(rs)));
+ putIReg(rt, mkexpr(t1));
-static Int msa_MI10_load(UInt cins, UChar wd, UChar ws) { /* MI10 (0x20) */
- IRTemp t1;
- UShort i10;
- UChar df;
+ /* memory[base] = memory[base] + v; */
+ store(getIReg(rs), binop(Iop_Add64, mkexpr(t0), mkexpr(t1)));
+ break;
- i10 = (cins & 0x03FF0000) >> 16;
- df = cins & 0x00000003;
+ case 0x14: /* SWAPW - Swap Word - Netlogic */
+ DIP("swapw r%u, r%u", rt, rs);
+ t0 = newTemp(Ity_I32);
+ t1 = newTemp(Ity_I32);
+ assign(t0, mkNarrowTo32(ty, getIReg(rt)));
+ assign(t1, load(Ity_I32, getIReg(rs)));
+ putIReg(rt, mkWidenFrom32(ty, mkexpr(t1), True));
+ store(getIReg(rs), mkexpr(t0));
+ break;
- switch (df) {
- case 0x00: { /* LD.B */
- DIP("LD.B w%d, %d(r%d)", wd, ws, i10);
- LOAD_STORE_PATTERN_MSA(i10);
- putWReg(wd, load(Ity_V128, mkexpr(t1)));
- break;
- }
+ case 0x16: /* SWAPD - Swap Double - Netlogic */
+ DIP("swapw r%u, r%u", rt, rs);
+ t0 = newTemp(Ity_I64);
+ t1 = newTemp(Ity_I64);
+ assign(t0, getIReg(rt));
+ assign(t1, load(Ity_I64, getIReg(rs)));
+ putIReg(rt, mkexpr(t1));
+ store(getIReg(rs), mkexpr(t0));
+ break;
- case 0x01: { /* LD.H */
- DIP("LD.H w%d, %d(r%d)", wd, ws, i10);
- LOAD_STORE_PATTERN_MSA(i10 << 1);
-#if defined (_MIPSEL)
- putWReg(wd, load(Ity_V128, mkexpr(t1)));
-#elif defined (_MIPSEB)
- putWReg(wd,
- unop(Iop_Reverse8sIn16_x8,
- load(Ity_V128, mkexpr(t1))));
-#endif
- break;
- }
+ case 0x20: { /* CLZ */
+ DIP("clz r%u, r%u", rd, rs);
- case 0x02: { /* LD.W */
- DIP("LD.W w%d, %d(r%d)", wd, ws, i10);
- LOAD_STORE_PATTERN_MSA(i10 << 2);
-#if defined (_MIPSEL)
- putWReg(wd, load(Ity_V128, mkexpr(t1)));
-#elif defined (_MIPSEB)
- putWReg(wd,
- unop(Iop_Reverse8sIn32_x4,
- load(Ity_V128, mkexpr(t1))));
-#endif
- break;
- }
+ if (mode64) {
+ IRTemp tmpClz32 = newTemp(Ity_I32);
+ IRTemp tmpRs32 = newTemp(Ity_I32);
- case 0x03: { /* LD.D */
- DIP("LD.D w%d, %d(r%d)", wd, ws, i10);
- LOAD_STORE_PATTERN_MSA(i10 << 3);
-#if defined (_MIPSEL)
- putWReg(wd, load(Ity_V128, mkexpr(t1)));
-#elif defined (_MIPSEB)
- putWReg(wd,
- unop(Iop_Reverse8sIn64_x2,
- load(Ity_V128, mkexpr(t1))));
-#endif
- break;
+ assign(tmpRs32, mkNarrowTo32(ty, getIReg(rs)));
+ assign(tmpClz32, unop(Iop_Clz32, mkexpr(tmpRs32)));
+ putIReg(rd, mkWidenFrom32(ty, mkexpr(tmpClz32), True));
+ } else {
+ t1 = newTemp(Ity_I1);
+ assign(t1, binop(Iop_CmpEQ32, getIReg(rs), mkU32(0)));
+ putIReg(rd, IRExpr_ITE(mkexpr(t1),
+ mkU32(0x00000020),
+ unop(Iop_Clz32, getIReg(rs))));
}
- default:
- return -1;
- }
+ break;
+ }
- return 0;
-}
+ case 0x21: { /* CLO */
+ DIP("clo r%u, r%u", rd, rs);
-static Int msa_MI10_store(UInt cins, UChar wd, UChar ws) { /* MI10 (0x24) */
- IRTemp t1;
- UShort i10;
- UChar df;
+ if (mode64) {
+ IRTemp tmpClo32 = newTemp(Ity_I32);
+ IRTemp tmpRs32 = newTemp(Ity_I32);
+ assign(tmpRs32, mkNarrowTo32(ty, getIReg(rs)));
- df = cins & 0x00000003;
- i10 = (cins & 0x03FF0000) >> 16;
+ t1 = newTemp(Ity_I1);
+ assign(t1, binop(Iop_CmpEQ32, mkexpr(tmpRs32), mkU32(0xffffffff)));
+ assign(tmpClo32, IRExpr_ITE(mkexpr(t1),
+ mkU32(0x00000020),
+ unop(Iop_Clz32, unop(Iop_Not32, mkexpr(tmpRs32)))));
- switch (df) {
- case 0x00: { /* ST.B */
- DIP("ST.B w%d, %d(r%d)", wd, ws, i10);
- LOAD_STORE_PATTERN_MSA(i10);
- store(mkexpr(t1), getWReg(wd));
+ putIReg(rd, mkWidenFrom32(ty, mkexpr(tmpClo32), True));
break;
- }
-
- case 0x01: { /* ST.H */
- DIP("ST.H w%d, %d(r%d)", wd, ws, i10);
- LOAD_STORE_PATTERN_MSA(i10 << 1);
-#if defined (_MIPSEL)
- store(mkexpr(t1), getWReg(wd));
-#elif defined (_MIPSEB)
- store(mkexpr(t1),
- unop(Iop_Reverse8sIn16_x8, getWReg(wd)));
-#endif
+ } else {
+ t1 = newTemp(Ity_I1);
+ assign(t1, binop(Iop_CmpEQ32, getIReg(rs), mkU32(0xffffffff)));
+ putIReg(rd, IRExpr_ITE(mkexpr(t1),
+ mkU32(0x00000020),
+ unop(Iop_Clz32,
+ unop(Iop_Not32, getIReg(rs)))));
break;
}
+ }
- case 0x02: { /* ST.W */
- DIP("ST.W w%d, %d(r%d)", wd, ws, i10);
- LOAD_STORE_PATTERN_MSA(i10 << 2);
-#if defined (_MIPSEL)
- store(mkexpr(t1), getWReg(wd));
-#elif defined (_MIPSEB)
- store(mkexpr(t1),
- unop(Iop_Reverse8sIn32_x4, getWReg(wd)));
-#endif
- break;
- }
+ case 0x24: /* Count Leading Zeros in Doubleword - DCLZ; MIPS64 */
+ DIP("dclz r%u, r%u", rd, rs);
+ t1 = newTemp(Ity_I1);
+ assign(t1, binop(Iop_CmpEQ64, getIReg(rs), mkU64(0)));
+ putIReg(rd, IRExpr_ITE(mkexpr(t1),
+ mkU64(0x00000040),
+ unop(Iop_Clz64, getIReg(rs))));
+ break;
- case 0x03: { /* ST.D */
- DIP("ST.D w%d, %d(r%d)", wd, ws, i10);
- LOAD_STORE_PATTERN_MSA(i10 << 3);
-#if defined (_MIPSEL)
- store(mkexpr(t1), getWReg(wd));
-#elif defined (_MIPSEB)
- store(mkexpr(t1),
- unop(Iop_Reverse8sIn64_x2, getWReg(wd)));
-#endif
- break;
- }
+ case 0x25: /* Count Leading Ones in Doubleword - DCLO; MIPS64 */
+ DIP("dclo r%u, r%u", rd, rs);
+ t1 = newTemp(Ity_I1);
+ assign(t1, binop(Iop_CmpEQ64, getIReg(rs),
+ mkU64(0xffffffffffffffffULL)));
+ putIReg(rd, IRExpr_ITE(mkexpr(t1),
+ mkU64(0x40),
+ unop(Iop_Clz64, unop(Iop_Not64,
+ getIReg(rs)))));
+ break;
default:
return -1;
return 0;
}
-/*------------------------------------------------------------*/
-/*--- Disassemble a single MIPS MSA (SIMD) instruction ---*/
-/*--- Return values: ---*/
-/*--- 0: Success ---*/
-/*--- -1: Decode failure (unknown instruction) ---*/
-/*--- -2: Illegal instruction ---*/
-/*------------------------------------------------------------*/
-static Int disMSAInstr_MIPS_WRK ( UInt cins ) {
- UChar minor_opcode, wd, ws;
-
- vassert(has_msa);
- vassert((cins & 0xFC000000) == 0x78000000);
-
- minor_opcode = (cins & 0x20) > 0 ? (cins & 0x3C) : (cins & 0x3F);
- wd = (cins & 0x000007C0) >> 6;
- ws = (cins & 0x0000F800) >> 11;
-
- switch (minor_opcode) {
- case 0x0:
- return msa_I8_logical(cins, wd, ws);
-
- case 0x01:
- return msa_I8_branch(cins, wd, ws);
-
- case 0x02:
- return msa_I8_shift(cins, wd, ws);
-
- case 0x06:
- return msa_I5_06(cins, wd, ws);
-
- case 0x07:
- return msa_I5_07(cins, wd, ws);
-
- case 0x09:
- return msa_BIT_09(cins, wd, ws);
-
- case 0x0A:
- return msa_BIT_0A(cins, wd, ws);
+static UInt disInstr_MIPS_WRK_Special3(UInt cins, const VexArchInfo* archinfo,
+ const VexAbiInfo* abiinfo, DisResult* dres,
+ IRStmt** bstmt, IRExpr** lastn,
+ Bool(*resteerOkFn) (/*opaque */void *,
+ Addr),
+ void* callback_opaque)
- case 0x0D:
- return msa_3R_0D(cins, wd, ws);
+{
+ IRTemp t0, t1 = 0, t2, t3, t4, t5, t6;
+ UInt rs, rt, rd, sa, function, imm, instr_index, msb, lsb, size;
+ /* Additional variables for instruction fields in DSP ASE insructions */
- case 0x0E:
- return msa_3R_0E(cins, wd, ws);
+ imm = get_imm(cins);
+ rs = get_rs(cins);
+ rt = get_rt(cins);
+ rd = get_rd(cins);
+ sa = get_sa(cins);
+ instr_index = get_instr_index(cins);
+ function = get_function(cins);
+ IRType ty = mode64 ? Ity_I64 : Ity_I32;
- case 0x0F:
- return msa_3R_0F(cins, wd, ws);
+ switch (function) {
+ case 0x01: { /* Doubleword Extract Bit Field - DEXTM; MIPS64r2 */
+ msb = get_msb(cins);
+ lsb = get_lsb(cins);
+ size = msb + 1;
+ UInt srcPos = lsb;
+ UInt dstSz = msb + 33;
+ t1 = newTemp(Ity_I64);
+ DIP("dextm r%u, r%u, %u, %u", rt, rs, lsb, msb + 1);
- case 0x10:
- return msa_3R_10(cins, wd, ws);
+ UChar lsAmt = 64 - (srcPos + dstSz); /* left shift amount; */
+ UChar rsAmt = 64 - dstSz; /* right shift amount; */
- case 0x11:
- return msa_3R_11(cins, wd, ws);
+ assign(t1, binop(Iop_Shl64, getIReg(rs), mkU8(lsAmt)));
+ putIReg(rt, binop(Iop_Shr64, mkexpr(t1), mkU8(rsAmt)));
- case 0x12:
- return msa_3R_12(cins, wd, ws);
+ break;
+ }
- case 0x13:
- return msa_3R_13(cins, wd, ws);
+ case 0x02: { /* Doubleword Extract Bit Field Upper - DEXTU; MIPS64r2 */
+ msb = get_msb(cins);
+ lsb = get_lsb(cins);
+ size = msb + 1;
+ UInt srcPos = lsb + 32;
+ UInt dstSz = msb + 1;
+ DIP("dextu r%u, r%u, %u, %u", rt, rs, srcPos, dstSz);
+ t1 = newTemp(Ity_I64);
- case 0x14:
- return msa_3R_14(cins, wd, ws);
+ vassert(srcPos >= 32 && srcPos < 64);
+ vassert(dstSz > 0 && dstSz <= 32);
+ vassert((srcPos + dstSz) > 32 && (srcPos + dstSz) <= 64);
- case 0x15:
- return msa_3R_15(cins, wd, ws);
+ UChar lsAmt = 64 - (srcPos + dstSz); /* left shift amount; */
+ UChar rsAmt = 64 - dstSz; /* right shift amount; */
- case 0x19:
- return msa_ELM(cins, wd, ws);
+ assign(t1, binop(Iop_Shl64, getIReg(rs), mkU8(lsAmt)));
+ putIReg(rt, binop(Iop_Shr64, mkexpr(t1), mkU8(rsAmt)));
+ break;
+ }
- case 0x1A:
- return msa_3R_1A(cins, wd, ws);
+ case 0x05: { /* Doubleword Insert Bit Field Middle - DINSM; MIPS64r2 */
+ msb = get_msb(cins);
+ lsb = get_lsb(cins);
+ size = msb + 1;
+ UInt dstPos = lsb;
+ UInt srcSz = msb - lsb + 33;
+ t1 = newTemp(ty);
+ t2 = newTemp(ty);
+ t3 = newTemp(ty);
+ t4 = newTemp(ty);
+ IRTemp tmpT1 = newTemp(ty);
+ IRTemp tmpT2 = newTemp(ty);
+ IRTemp tmpT3 = newTemp(ty);
+ IRTemp tmpT4 = newTemp(ty);
+ IRTemp tmpT5 = newTemp(ty);
+ IRTemp tmpT6 = newTemp(ty);
+ IRTemp tmpT7 = newTemp(ty);
+ IRTemp tmpRs = newTemp(ty);
+ IRTemp tmpRt = newTemp(ty);
+ IRTemp tmpRd = newTemp(ty);
- case 0x1B:
- return msa_3R_1B(cins, wd, ws);
+ assign(tmpRs, getIReg(rs));
+ assign(tmpRt, getIReg(rt));
+ DIP("dinsm r%u, r%u, %u, %u", rt, rs, lsb, msb);
- case 0x1C:
- return msa_3R_1C(cins, wd, ws);
+ UChar lsAmt = dstPos + srcSz - 1; /* left shift amount; */
+ UChar rsAmt = dstPos + srcSz - 1; /* right shift amount; */
- case 0x1E:
- if ((cins & 0x03000000) == 0)
- return msa_VEC(cins, wd, ws);
- else if ((cins & 0x00200000) == 0)
- return msa_2R(cins, wd, ws);
- else
- return msa_2RF(cins, wd, ws);
+ assign(t1, binop(Iop_Shr64, mkexpr(tmpRt), mkU8(rsAmt)));
+ assign(tmpT1, binop(Iop_Shr64, mkexpr(t1), mkU8(1)));
+ assign(t2, binop(Iop_Shl64, mkexpr(tmpT1), mkU8(lsAmt)));
+ assign(tmpT2, binop(Iop_Shl64, mkexpr(t2), mkU8(1)));
- case 0x20:
- return msa_MI10_load(cins, wd, ws);
+ lsAmt = 63 - dstPos; /* left shift amount; */
+ rsAmt = 63 - dstPos; /* right shift amount; */
- case 0x24:
- return msa_MI10_store(cins, wd, ws);
- }
+ assign(t3, binop(Iop_Shl64, mkexpr(tmpRt), mkU8(lsAmt)));
+ assign(tmpT3, binop(Iop_Shl64, mkexpr(t3), mkU8(1)));
+ assign(t4, binop(Iop_Shr64, mkexpr(tmpT3), mkU8(rsAmt)));
+ assign(tmpT4, binop(Iop_Shr64, mkexpr(t4), mkU8(1)));
- return -1;
-}
+ /* extract size from src register */
+ lsAmt = 64 - srcSz; /* left shift amount; */
+ rsAmt = 64 - (lsb + srcSz); /* right shift amount; */
-/*------------------------------------------------------------*/
-/*--- Disassemble a single instruction ---*/
-/*------------------------------------------------------------*/
+ assign(tmpT5, binop(Iop_Shl64, mkexpr(tmpRs), mkU8(lsAmt)));
+ assign(tmpT6, binop(Iop_Shr64, mkexpr(tmpT5), mkU8(rsAmt)));
-/* Disassemble a single instruction into IR. The instruction is
- located in host memory at guest_instr, and has guest IP of
- guest_PC_curr_instr, which will have been set before the call
- here. */
+ assign(tmpT7, binop(Iop_Or64, mkexpr(tmpT2), mkexpr(tmpT4)));
+ assign(tmpRd, binop(Iop_Or64, mkexpr(tmpT6), mkexpr(tmpT7)));
+ putIReg(rt, mkexpr(tmpRd));
+ break;
+ }
-static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *,
- Addr),
- Bool resteerCisOk,
- void* callback_opaque,
- Long delta64,
- const VexArchInfo* archinfo,
- const VexAbiInfo* abiinfo,
- Bool sigill_diag )
-{
- IRTemp t0, t1 = 0, t2, t3, t4, t5, t6, t7;
+ case 0x06: { /* Doubleword Insert Bit Field Upper - DINSU; MIPS64r2 */
+ msb = get_msb(cins);
+ lsb = get_lsb(cins);
+ size = msb + 1;
+ UInt dstPos = lsb + 32;
+ UInt srcSz = msb - lsb + 1;
+ IRTemp tmpT1 = newTemp(ty);
+ IRTemp tmpT2 = newTemp(ty);
+ IRTemp tmpT3 = newTemp(ty);
+ IRTemp tmpT4 = newTemp(ty);
+ IRTemp tmpT5 = newTemp(ty);
+ IRTemp tmpT6 = newTemp(ty);
+ IRTemp tmpT7 = newTemp(ty);
+ IRTemp tmpT8 = newTemp(ty);
+ IRTemp tmpT9 = newTemp(ty);
+ IRTemp tmpRs = newTemp(ty);
+ IRTemp tmpRt = newTemp(ty);
+ IRTemp tmpRd = newTemp(ty);
- UInt opcode, cins, rs, rt, rd, sa, ft, fs, fd, fmt, tf, nd, function,
- trap_code, imm, instr_index, p, msb, lsb, size, rot, sel;
- /* Additional variables for instruction fields in DSP ASE insructions */
- UInt ac;
+ assign(tmpRs, getIReg(rs));
+ assign(tmpRt, getIReg(rt));
+ DIP("dinsu r%u, r%u, %u, %u", rt, rs, lsb, msb);
- DisResult dres;
+ UChar lsAmt = 64 - srcSz; /* left shift amount; */
+ UChar rsAmt = 64 - (dstPos + srcSz); /* right shift amount; */
+ assign(tmpT1, binop(Iop_Shl64, mkexpr(tmpRs), mkU8(lsAmt)));
+ assign(tmpT2, binop(Iop_Shr64, mkexpr(tmpT1), mkU8(rsAmt)));
- static IRExpr *lastn = NULL; /* last jump addr */
- static IRStmt *bstmt = NULL; /* branch (Exit) stmt */
+ lsAmt = 64 - dstPos; /* left shift amount; */
+ rsAmt = 64 - dstPos; /* right shift amount; */
+ assign(tmpT3, binop(Iop_Shl64, mkexpr(tmpRt), mkU8(lsAmt)));
+ assign(tmpT4, binop(Iop_Shr64, mkexpr(tmpT3), mkU8(rsAmt)));
- /* The running delta */
- Int delta = (Int) delta64;
+ lsAmt = dstPos; /* left shift amount; */
+ rsAmt = srcSz; /* right shift amount; */
+ assign(tmpT5, binop(Iop_Shr64, mkexpr(tmpRt), mkU8(rsAmt)));
+ assign(tmpT6, binop(Iop_Shr64, mkexpr(tmpT5), mkU8(lsAmt)));
- /* Holds eip at the start of the insn, so that we can print
- consistent error messages for unimplemented insns. */
- Int delta_start = delta;
+ assign(tmpT7, binop(Iop_Shl64, mkexpr(tmpT6), mkU8(rsAmt)));
+ assign(tmpT8, binop(Iop_Shl64, mkexpr(tmpT7), mkU8(lsAmt)));
- /* Are we in a delay slot ? */
- Bool delay_slot_branch, likely_delay_slot, delay_slot_jump;
+ assign(tmpT9, binop(Iop_Or64, mkexpr(tmpT8), mkexpr(tmpT4)));
+ assign(tmpRd, binop(Iop_Or64, mkexpr(tmpT2), mkexpr(tmpT9)));
+ putIReg(rt, mkexpr(tmpRd));
+ break;
+ }
- /* Set result defaults. */
- dres.whatNext = Dis_Continue;
- dres.len = 0;
- dres.continueAt = 0;
- dres.jk_StopHere = Ijk_INVALID;
- dres.hint = Dis_HintNone;
+ case 0x07: { /* Doubleword Insert Bit Field - DINS; MIPS64r2 */
+ IRTemp tmp1 = newTemp(ty);
+ IRTemp tmpT1 = newTemp(ty);
+ IRTemp tmpT2 = newTemp(ty);
+ IRTemp tmpT3 = newTemp(ty);
+ IRTemp tmpT4 = newTemp(ty);
+ IRTemp tmpT5 = newTemp(ty);
+ IRTemp tmpT6 = newTemp(ty);
+ IRTemp tmpT7 = newTemp(ty);
+ IRTemp tmpT8 = newTemp(ty);
+ IRTemp tmpT9 = newTemp(ty);
+ IRTemp tmp = newTemp(ty);
+ IRTemp tmpRs = newTemp(ty);
+ IRTemp tmpRt = newTemp(ty);
+ IRTemp tmpRd = newTemp(ty);
- delay_slot_branch = likely_delay_slot = delay_slot_jump = False;
+ assign(tmpRs, getIReg(rs));
+ assign(tmpRt, getIReg(rt));
- const UChar *code = guest_code + delta;
- cins = getUInt(code);
- DIP("\t0x%llx:\t0x%08x\t", (Addr64)guest_PC_curr_instr, cins);
+ msb = get_msb(cins);
+ lsb = get_lsb(cins);
+ size = msb + 1;
+ DIP("dins r%u, r%u, %u, %u", rt, rs, lsb,
+ msb - lsb + 1);
+ UChar lsAmt = 63 - lsb; /* left shift amount; */
+ UChar rsAmt = 63 - lsb; /* right shift amount; */
+ assign(tmp, binop(Iop_Shl64, mkexpr(tmpRt), mkU8(lsAmt)));
+ assign(tmpT1, binop(Iop_Shl64, mkexpr(tmp), mkU8(1)));
+ assign(tmp1, binop(Iop_Shr64, mkexpr(tmpT1), mkU8(rsAmt)));
+ assign(tmpT2, binop(Iop_Shr64, mkexpr(tmp1), mkU8(1)));
+
+ lsAmt = msb; /* left shift amount; */
+ rsAmt = 1; /*right shift amount; */
+ assign(tmpT3, binop(Iop_Shr64, mkexpr(tmpRt), mkU8(rsAmt)));
+ assign(tmpT4, binop(Iop_Shr64, mkexpr(tmpT3), mkU8(lsAmt)));
+ assign(tmpT5, binop(Iop_Shl64, mkexpr(tmpT4), mkU8(rsAmt)));
+ assign(tmpT6, binop(Iop_Shl64, mkexpr(tmpT5), mkU8(lsAmt)));
+
+ lsAmt = 64 - (msb - lsb + 1); /* left shift amount; */
+ rsAmt = 64 - (msb + 1); /* right shift amount; */
+ assign(tmpT7, binop(Iop_Shl64, mkexpr(tmpRs), mkU8(lsAmt)));
+ assign(tmpT8, binop(Iop_Shr64, mkexpr(tmpT7), mkU8(rsAmt)));
+
+ assign(tmpT9, binop(Iop_Or64, mkexpr(tmpT2), mkexpr(tmpT8)));
+ assign(tmpRd, binop(Iop_Or64, mkexpr(tmpT6), mkexpr(tmpT9)));
+ putIReg(rt, mkexpr(tmpRd));
+ break;
+ }
- if (delta != 0) {
- if (branch_or_jump(guest_code + delta - 4)) {
- if (lastn == NULL && bstmt == NULL) {
- vassert(0);
- } else {
- dres.whatNext = Dis_StopHere;
- if (lastn != NULL) {
- delay_slot_jump = True;
- } else if (bstmt != NULL) {
- delay_slot_branch = True;
+ case 0x24: /* DBSHFL */
+ lsb = get_lsb(cins);
+ IRTemp tmpRs = newTemp(ty);
+ IRTemp tmpRt = newTemp(ty);
+ IRTemp tmpRd = newTemp(ty);
+ assign(tmpRs, getIReg(rs));
+ assign(tmpRt, getIReg(rt));
+
+ switch (lsb) {
+ case 0x02: { /* DSBH */
+ DIP("dsbh r%u, r%u", rd, rt);
+ IRTemp tmpT1 = newTemp(ty);
+ IRTemp tmpT2 = newTemp(ty);
+ IRTemp tmpT3 = newTemp(ty);
+ IRTemp tmpT4 = newTemp(ty);
+ IRTemp tmpT5 = newTemp(Ity_I64);
+ IRTemp tmpT6 = newTemp(ty);
+ assign(tmpT5, mkU64(0xFF00FF00FF00FF00ULL));
+ assign(tmpT6, mkU64(0x00FF00FF00FF00FFULL));
+ assign(tmpT1, binop(Iop_And64, mkexpr(tmpRt), mkexpr(tmpT5)));
+ assign(tmpT2, binop(Iop_Shr64, mkexpr(tmpT1), mkU8(8)));
+ assign(tmpT3, binop(Iop_And64, mkexpr(tmpRt), mkexpr(tmpT6)));
+ assign(tmpT4, binop(Iop_Shl64, mkexpr(tmpT3), mkU8(8)));
+ assign(tmpRd, binop(Iop_Or64, mkexpr(tmpT4), mkexpr(tmpT2)));
+ putIReg(rd, mkexpr(tmpRd));
+ break;
}
- }
- }
- if (branch_or_link_likely(guest_code + delta - 4)) {
- likely_delay_slot = True;
- }
- }
+ case 0x05: { /* DSHD */
+ DIP("dshd r%u, r%u\n", rd, rt);
+ IRTemp tmpT1 = newTemp(ty);
+ IRTemp tmpT2 = newTemp(ty);
+ IRTemp tmpT3 = newTemp(ty);
+ IRTemp tmpT4 = newTemp(ty);
+ IRTemp tmpT5 = newTemp(Ity_I64);
+ IRTemp tmpT6 = newTemp(ty);
+ IRTemp tmpT7 = newTemp(ty);
+ IRTemp tmpT8 = newTemp(ty);
+ IRTemp tmpT9 = newTemp(ty);
+ assign(tmpT5, mkU64(0xFFFF0000FFFF0000ULL));
+ assign(tmpT6, mkU64(0x0000FFFF0000FFFFULL));
+ assign(tmpT1, binop(Iop_And64, mkexpr(tmpRt), mkexpr(tmpT5)));
+ assign(tmpT2, binop(Iop_Shr64, mkexpr(tmpT1), mkU8(16)));
+ assign(tmpT3, binop(Iop_And64, mkexpr(tmpRt), mkexpr(tmpT6)));
+ assign(tmpT4, binop(Iop_Shl64, mkexpr(tmpT3), mkU8(16)));
+ assign(tmpT7, binop(Iop_Or64, mkexpr(tmpT4), mkexpr(tmpT2)));
+ assign(tmpT8, binop(Iop_Shl64, mkexpr(tmpT7), mkU8(32)));
+ assign(tmpT9, binop(Iop_Shr64, mkexpr(tmpT7), mkU8(32)));
+ assign(tmpRd, binop(Iop_Or64, mkexpr(tmpT8), mkexpr(tmpT9)));
+ putIReg(rd, mkexpr(tmpRd));
+ break;
+ }
- /* Spot "Special" instructions (see comment at top of file). */
- {
- /* Spot the 16-byte preamble:
- ****mips32****
- "srl $0, $0, 13
- "srl $0, $0, 29
- "srl $0, $0, 3
- "srl $0, $0, 19
+ case 0x08 ... 0x0f: { /* DALIGN */
+ if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+ DIP("dalign r%u, r%u, r%u, %u", rd, rs, rt, lsb & 0x7);
+ UInt bp = (lsb & 0x7) << 3;
+
+ if (bp) {
+ putIReg(rd, binop(Iop_Or64,
+ binop(Iop_Shl64, getIReg(rt), mkU8(bp)),
+ binop(Iop_Shr64,
+ getIReg(rs), mkU8(64 - bp))));
+ } else
+ putIReg(rd, getIReg(rt));
+ } else {
+ ILLEGAL_INSTRUCTON
+ }
- ****mips64****
- dsll $0, $0, 3
- dsll $0, $0, 13
- dsll $0, $0, 29
- dsll $0, $0, 19 */
+ break;
+ }
- UInt word1 = mode64 ? 0xF8 : 0x342;
- UInt word2 = mode64 ? 0x378 : 0x742;
- UInt word3 = mode64 ? 0x778 : 0xC2;
- UInt word4 = mode64 ? 0x4F8 : 0x4C2;
- if (getUInt(code + 0) == word1 && getUInt(code + 4) == word2 &&
- getUInt(code + 8) == word3 && getUInt(code + 12) == word4) {
- /* Got a "Special" instruction preamble. Which one is it? */
- if (getUInt(code + 16) == 0x01ad6825 /* or $13, $13, $13 */ ) {
- /* $11 = client_request ( $12 ) */
- DIP("$11 = client_request ( $12 )");
- if (mode64)
- putPC(mkU64(guest_PC_curr_instr + 20));
- else
- putPC(mkU32(guest_PC_curr_instr + 20));
- dres.jk_StopHere = Ijk_ClientReq;
- dres.whatNext = Dis_StopHere;
+ case 0: /* DBITSWAP */
+ if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+ DIP("dbitswap r%u, r%u", rd, rt);
+ putIReg(rd, qop(Iop_Rotx64, getIReg(rt), mkU8(7), mkU8(8), mkU8(1)));
+ } else {
+ ILLEGAL_INSTRUCTON
+ }
- goto decode_success;
- } else if (getUInt(code + 16) == 0x01ce7025 /* or $14, $14, $14 */ ) {
- /* $11 = guest_NRADDR */
- DIP("$11 = guest_NRADDR");
- dres.len = 20;
- delta += 20;
- if (mode64)
- putIReg(11, IRExpr_Get(offsetof(VexGuestMIPS64State,
- guest_NRADDR), Ity_I64));
- else
- putIReg(11, IRExpr_Get(offsetof(VexGuestMIPS32State,
- guest_NRADDR), Ity_I32));
- goto decode_success;
- } else if (getUInt(code + 16) == 0x01ef7825 /* or $15, $15, $15 */ ) {
- /* branch-and-link-to-noredir $25 */
- DIP("branch-and-link-to-noredir $25");
- if (mode64)
- putIReg(31, mkU64(guest_PC_curr_instr + 20));
- else
- putIReg(31, mkU32(guest_PC_curr_instr + 20));
- putPC(getIReg(25));
- dres.jk_StopHere = Ijk_NoRedir;
- dres.whatNext = Dis_StopHere;
- goto decode_success;
- } else if (getUInt(code + 16) == 0x016b5825 /* or $11,$11,$11 */ ) {
- /* IR injection */
- DIP("IR injection");
-#if defined (_MIPSEL)
- vex_inject_ir(irsb, Iend_LE);
-#elif defined (_MIPSEB)
- vex_inject_ir(irsb, Iend_BE);
-#endif
- if (mode64) {
- stmt(IRStmt_Put(offsetof(VexGuestMIPS64State, guest_CMSTART),
- mkU64(guest_PC_curr_instr)));
- stmt(IRStmt_Put(offsetof(VexGuestMIPS64State, guest_CMLEN),
- mkU64(20)));
+ break;
- putPC(mkU64(guest_PC_curr_instr + 20));
- } else {
- stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_CMSTART),
- mkU32(guest_PC_curr_instr)));
- stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_CMLEN),
- mkU32(20)));
+ default:
+ return -1;;
+ }
- putPC(mkU32(guest_PC_curr_instr + 20));
- }
- dres.whatNext = Dis_StopHere;
- dres.jk_StopHere = Ijk_InvalICache;
- dres.len = 20;
- delta += 20;
- goto decode_success;
+ break;
+
+ case 0x3B: /* RDHWR */
+ DIP("rdhwr r%u, r%u", rt, rd);
+
+ if (VEX_MIPS_CPU_HAS_MIPS32R2(archinfo->hwcaps) ||
+ VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps) ||
+ (VEX_MIPS_COMP_ID(archinfo->hwcaps) == VEX_PRID_COMP_BROADCOM)) {
+ if (rd == 29) {
+ putIReg(rt, getULR());
+ } else if (rd <= 3
+ || (rd == 31
+ && VEX_MIPS_COMP_ID(archinfo->hwcaps)
+ == VEX_PRID_COMP_CAVIUM)) {
+ IRExpr** arg = mkIRExprVec_1(mkU32(rd));
+ IRTemp val = newTemp(ty);
+ IRDirty *d = unsafeIRDirty_1_N(val,
+ 0,
+ "mips_dirtyhelper_rdhwr",
+ &mips_dirtyhelper_rdhwr,
+ arg);
+ stmt(IRStmt_Dirty(d));
+ putIReg(rt, mkexpr(val));
+ } else
+ return -1;
+ } else {
+ ILLEGAL_INSTRUCTON
}
- /* We don't know what it is. Set opc1/opc2 so decode_failure
- can print the insn following the Special-insn preamble. */
- delta += 16;
- goto decode_failure;
- /*NOTREACHED*/}
- }
+ break;
- opcode = get_opcode(cins);
- imm = get_imm(cins);
- rs = get_rs(cins);
- rt = get_rt(cins);
- rd = get_rd(cins);
- sa = get_sa(cins);
- fs = get_fs(cins);
- fd = get_fd(cins);
- ft = get_ft(cins);
- tf = get_tf(cins);
- nd = get_nd(cins);
- sel = get_sel(cins);
- fmt = get_fmt(cins);
- instr_index = get_instr_index(cins);
- trap_code = get_code(cins);
- function = get_function(cins);
- IRType ty = mode64 ? Ity_I64 : Ity_I32;
- IRType tyF = fp_mode64 ? Ity_F64 : Ity_F32;
+ case 0x04: /* INS */
+ msb = get_msb(cins);
+ lsb = get_lsb(cins);
+ size = msb - lsb + 1;
+ DIP("ins size:%u msb:%u lsb:%u", size, msb, lsb);
+
+ vassert(lsb + size <= 32);
+ vassert(lsb + size > 0);
+
+ /* put size bits from rs at the pos in temporary */
+ t0 = newTemp(Ity_I32);
+ t3 = newTemp(Ity_I32);
+ /* shift left for 32 - size to clear leading bits and get zeros
+ at the end */
+ assign(t0, binop(Iop_Shl32, mkNarrowTo32(ty, getIReg(rs)),
+ mkU8(32 - size)));
+ /* now set it at pos */
+ t1 = newTemp(Ity_I32);
+ assign(t1, binop(Iop_Shr32, mkexpr(t0), mkU8(32 - size - lsb)));
- ac = get_acNo(cins);
+ if (lsb > 0) {
+ t2 = newTemp(Ity_I32);
+ /* clear everything but lower pos bits from rt */
+ assign(t2, binop(Iop_Shl32, mkNarrowTo32(ty, getIReg(rt)),
+ mkU8(32 - lsb)));
+ assign(t3, binop(Iop_Shr32, mkexpr(t2), mkU8(32 - lsb)));
+ } else
+ assign(t3, mkU32(0));
- switch (opcode) {
+ if (msb < 31) {
+ t4 = newTemp(Ity_I32);
+ /* clear everything but upper msb + 1 bits from rt */
+ assign(t4, binop(Iop_Shr32, mkNarrowTo32(ty, getIReg(rt)),
+ mkU8(msb + 1)));
+ t5 = newTemp(Ity_I32);
+ assign(t5, binop(Iop_Shl32, mkexpr(t4), mkU8(msb + 1)));
- case 0x03: /* JAL */
- DIP("jal 0x%x", instr_index);
- if (mode64) {
- putIReg(31, mkU64(guest_PC_curr_instr + 8));
- t0 = newTemp(ty);
- assign(t0, mkU64((guest_PC_curr_instr & 0xFFFFFFFFF0000000ULL) |
- (instr_index << 2)));
- } else {
- putIReg(31, mkU32(guest_PC_curr_instr + 8));
- t0 = newTemp(ty);
- assign(t0, mkU32((guest_PC_curr_instr & 0xF0000000) |
- (instr_index << 2)));
- }
- lastn = mkexpr(t0);
- break;
- case 0x02: /* J */
- DIP("j 0x%x", instr_index);
- t0 = newTemp(ty);
- if (mode64)
- assign(t0, mkU64((guest_PC_curr_instr & 0xFFFFFFFFF0000000ULL) |
- (instr_index << 2)));
- else
- assign(t0, mkU32((guest_PC_curr_instr & 0xF0000000) |
- (instr_index << 2)));
- lastn = mkexpr(t0);
- break;
-
- case 0x11: { /* COP1 */
- if (fmt == 0x3 && fd == 0 && function == 0) { /* MFHC1 */
- DIP("mfhc1 r%u, f%u", rt, fs);
- if (VEX_MIPS_CPU_HAS_MIPS32R2(archinfo->hwcaps) ||
- VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
- if (fp_mode64) {
- t0 = newTemp(Ity_I64);
- t1 = newTemp(Ity_I32);
- assign(t0, unop(Iop_ReinterpF64asI64, getDReg(fs)));
- assign(t1, unop(Iop_64HIto32, mkexpr(t0)));
- putIReg(rt, mkWidenFrom32(ty, mkexpr(t1), True));
+ /* now combine these registers */
+ if (lsb > 0) {
+ t6 = newTemp(Ity_I32);
+ assign(t6, binop(Iop_Or32, mkexpr(t5), mkexpr(t1)));
+ putIReg(rt, mkWidenFrom32(ty, binop(Iop_Or32, mkexpr(t6),
+ mkexpr(t3)), True));
} else {
- putIReg(rt, mkWidenFrom32(ty, unop(Iop_ReinterpF32asI32,
- getFReg(fs | 1)), True));
+ putIReg(rt, mkWidenFrom32(ty, binop(Iop_Or32, mkexpr(t1),
+ mkexpr(t5)), True));
}
} else {
- ILLEGAL_INSTRUCTON;
+ putIReg(rt, mkWidenFrom32(ty, binop(Iop_Or32, mkexpr(t1),
+ mkexpr(t3)), True));
}
+
break;
- } else if (fmt == 0x7 && fd == 0 && function == 0) { /* MTHC1 */
- DIP("mthc1 r%u, f%u", rt, fs);
- if (VEX_MIPS_CPU_HAS_MIPS32R2(archinfo->hwcaps) ||
- VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
- if (fp_mode64) {
- t0 = newTemp(Ity_I64);
- assign(t0, binop(Iop_32HLto64, mkNarrowTo32(ty, getIReg(rt)),
- unop(Iop_ReinterpF32asI32,
- getLoFromF64(Ity_F64, getDReg(fs)))));
- putDReg(fs, unop(Iop_ReinterpI64asF64, mkexpr(t0)));
- } else {
- putFReg(fs | 1, unop(Iop_ReinterpI32asF32,
- mkNarrowTo32(ty, getIReg(rt))));
- }
+
+ case 0x00: /* EXT */
+ msb = get_msb(cins);
+ lsb = get_lsb(cins);
+ size = msb + 1;
+ DIP("ext size:%u msb:%u lsb:%u", size, msb, lsb);
+ vassert(lsb + size <= 32);
+ vassert(lsb + size > 0);
+
+ /* put size bits from rs at the top of in temporary */
+ if (lsb + size < 32) {
+ t0 = newTemp(Ity_I32);
+ assign(t0, binop(Iop_Shl32, mkNarrowTo32(ty, getIReg(rs)),
+ mkU8(32 - lsb - size)));
+
+ putIReg(rt, mkWidenFrom32(ty, binop(Iop_Shr32, mkexpr(t0),
+ mkU8(32 - size)), True));
} else {
- ILLEGAL_INSTRUCTON;
+ putIReg(rt, mkWidenFrom32(ty, binop(Iop_Shr32,
+ mkNarrowTo32(ty, getIReg(rs)),
+ mkU8(32 - size)), True));
}
+
break;
- } else if (fmt == 0x8) { /* BC */
- /* FcConditionalCode(bc1_cc) */
- UInt bc1_cc = get_bc1_cc(cins);
- t1 = newTemp(Ity_I1);
- t2 = newTemp(Ity_I32);
- t3 = newTemp(Ity_I1);
- assign(t1, binop(Iop_CmpEQ32, mkU32(0), mkU32(bc1_cc)));
- assign(t2, IRExpr_ITE(mkexpr(t1),
- binop(Iop_And32,
- binop(Iop_Shr32, getFCSR(), mkU8(23)),
- mkU32(0x1)),
- binop(Iop_And32,
- binop(Iop_Shr32, getFCSR(),
- mkU8(24 + bc1_cc)),
- mkU32(0x1))));
+ case 0x03: /* Doubleword Extract Bit Field - DEXT; MIPS64r2 */
+ msb = get_msb(cins);
+ lsb = get_lsb(cins);
+ size = msb + 1;
+ DIP("dext r%u, r%u, %u, %u", rt, rs, lsb, msb + 1);
+ t1 = newTemp(Ity_I64);
+ vassert(lsb >= 0 && lsb < 32);
+ vassert(size > 0 && size <= 32);
+ vassert((lsb + size) > 0 && (lsb + size) <= 63);
- if (tf == 1 && nd == 0) {
- /* branch on true */
- DIP("bc1t %u, %u", bc1_cc, imm);
- assign(t3, binop(Iop_CmpEQ32, mkU32(1), mkexpr(t2)));
- dis_branch(False, mkexpr(t3), imm, &bstmt);
- break;
- } else if (tf == 0 && nd == 0) {
- /* branch on false */
- DIP("bc1f %u, %u", bc1_cc, imm);
- assign(t3, binop(Iop_CmpEQ32, mkU32(0), mkexpr(t2)));
- dis_branch(False, mkexpr(t3), imm, &bstmt);
- break;
- } else if (nd == 1 && tf == 0) {
- DIP("bc1fl %u, %u", bc1_cc, imm);
- lastn = dis_branch_likely(binop(Iop_CmpNE32, mkexpr(t2),
- mkU32(0x0)), imm);
- break;
- } else if (nd == 1 && tf == 1) {
- DIP("bc1tl %u, %u", bc1_cc, imm);
- lastn = dis_branch_likely(binop(Iop_CmpEQ32, mkexpr(t2),
- mkU32(0x0)), imm);
- break;
- } else
- goto decode_failure;
- } else if (fmt >= 0x1c && has_msa) { /* BNZ.df */
- Int df = fmt & 3;
- t0 = newTemp(Ity_I32);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ft));
- assign(t2, binop(Iop_64HLtoV128, mkU64(0), mkU64(0)));
+ UChar lsAmt = 63 - (lsb + msb); /* left shift amount; */
+ UChar rsAmt = 63 - msb; /* right shift amount; */
- switch (df) {
- case 0x00: { /* BNZ.B */
- DIP("BNZ.B w%u, %u", ft, imm);
- assign(t3, binop(Iop_CmpEQ8x16, mkexpr(t1), mkexpr(t2)));
- break;
- }
+ assign(t1, binop(Iop_Shl64, getIReg(rs), mkU8(lsAmt)));
+ putIReg(rt, binop(Iop_Shr64, mkexpr(t1), mkU8(rsAmt)));
- case 0x01: { /* BNZ.H */
- DIP("BNZ.H w%u, %u", ft, imm);
- assign(t3, binop(Iop_CmpEQ16x8, mkexpr(t1), mkexpr(t2)));
- break;
- }
+ break;
- case 0x02: { /* BNZ.W */
- DIP("BNZ.W w%u, %u", ft, imm);
- assign(t3, binop(Iop_CmpEQ32x4, mkexpr(t1), mkexpr(t2)));
- break;
- }
+ case 0x20: /* BSHFL */
+ switch (sa) {
+ case 0x0: /* BITSWAP */
+ if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+ DIP("bitswap r%u, r%u", rd, rt);
- case 0x03: { /* BNZ.D */
- DIP("BNZ.D w%u, %u", ft, imm);
- assign(t3, binop(Iop_CmpEQ64x2, mkexpr(t1), mkexpr(t2)));
- break;
+ if (mode64) {
+ putIReg(rd, unop(Iop_32Uto64, qop(Iop_Rotx32, unop(Iop_64to32, getIReg(rt)),
+ mkU8(7), mkU8(8), mkU8(1))));
+ } else {
+ putIReg(rd, qop(Iop_Rotx32, getIReg(rt), mkU8(7),
+ mkU8(8), mkU8(1)));
+ }
+ } else {
+ ILLEGAL_INSTRUCTON;
}
- }
- assign(t0,
- binop(Iop_Or32,
- binop(Iop_Or32,
- unop(Iop_V128to32, mkexpr(t3)),
- unop(Iop_64HIto32, unop(Iop_V128to64, mkexpr(t3)))),
- binop(Iop_Or32,
- unop(Iop_64to32,
- unop(Iop_V128HIto64, mkexpr(t3))),
- unop(Iop_64HIto32,
- unop(Iop_V128HIto64, mkexpr(t3))))));
- dis_branch(False,
- binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0)), imm, &bstmt);
- } else if (fmt == 0x0F && has_msa) { /* BNZ.V */
- t0 = newTemp(Ity_I32);
- t1 = newTemp(Ity_V128);
- assign(t1, getWReg(ft));
- assign(t0,
- binop(Iop_Or32,
- binop(Iop_Or32,
- unop(Iop_V128to32, mkexpr(t1)),
- unop(Iop_64HIto32, unop(Iop_V128to64, mkexpr(t1)))),
- binop(Iop_Or32,
- unop(Iop_64to32, unop(Iop_V128HIto64, mkexpr(t1))),
- unop(Iop_64HIto32,
- unop(Iop_V128HIto64, mkexpr(t1))))));
- dis_branch(False,
- binop(Iop_CmpNE32, mkexpr(t0), mkU32(0)), imm, &bstmt);
- } else if (fmt >= 0x18 && has_msa) { /* BZ.df */
- Int df = fmt & 3;
- t0 = newTemp(Ity_I32);
- t1 = newTemp(Ity_V128);
- t2 = newTemp(Ity_V128);
- t3 = newTemp(Ity_V128);
- assign(t1, getWReg(ft));
- assign(t2, binop(Iop_64HLtoV128, mkU64(0), mkU64(0)));
+ break;
- switch (df) {
- case 0x00: { /* BZ.B */
- DIP("BZ.B w%u, %u", ft, imm);
- assign(t3, binop(Iop_CmpEQ8x16, mkexpr(t1), mkexpr(t2)));
- break;
- }
+ case 0x02: /* WSBH */
+ DIP("wsbh r%u, r%u", rd, rt);
+ t0 = newTemp(Ity_I32);
+ t1 = newTemp(Ity_I32);
+ t2 = newTemp(Ity_I32);
+ t3 = newTemp(Ity_I32);
+ assign(t0, binop(Iop_Shl32, binop(Iop_And32, mkNarrowTo32(ty,
+ getIReg(rt)), mkU32(0x00FF0000)),
+ mkU8(0x8)));
+ assign(t1, binop(Iop_Shr32, binop(Iop_And32, mkNarrowTo32(ty,
+ getIReg(rt)), mkU32(0xFF000000)), mkU8(0x8)));
+ assign(t2, binop(Iop_Shl32, binop(Iop_And32, mkNarrowTo32(ty,
+ getIReg(rt)), mkU32(0x000000FF)), mkU8(0x8)));
+ assign(t3, binop(Iop_Shr32, binop(Iop_And32, mkNarrowTo32(ty,
+ getIReg(rt)), mkU32(0x0000FF00)), mkU8(0x8)));
+ putIReg(rd, mkWidenFrom32(ty, binop(Iop_Or32, binop(Iop_Or32,
+ mkexpr(t0), mkexpr(t1)),
+ binop(Iop_Or32, mkexpr(t2),
+ mkexpr(t3))), True));
+ break;
- case 0x01: { /* BZ.H */
- DIP("BZ.H w%u, %u", ft, imm);
- assign(t3, binop(Iop_CmpEQ16x8, mkexpr(t1), mkexpr(t2)));
- break;
- }
+ case 0x10: /* SEB */
+ DIP("seb r%u, r%u", rd, rt);
- case 0x02: { /* BZ.W */
- DIP("BZ.W w%u, %u", ft, imm);
- assign(t3, binop(Iop_CmpEQ32x4, mkexpr(t1), mkexpr(t2)));
- break;
- }
+ if (mode64)
+ putIReg(rd, unop(Iop_8Sto64, unop(Iop_64to8, getIReg(rt))));
+ else
+ putIReg(rd, unop(Iop_8Sto32, unop(Iop_32to8, getIReg(rt))));
- case 0x03: { /* BZ.D */
- DIP("BZ.D w%u, %u", ft, imm);
- assign(t3, binop(Iop_CmpEQ64x2, mkexpr(t1), mkexpr(t2)));
- break;
+ break;
+
+ case 0x18: /* SEH */
+ DIP("seh r%u, r%u", rd, rt);
+
+ if (mode64)
+ putIReg(rd, unop(Iop_16Sto64, unop(Iop_64to16, getIReg(rt))));
+ else
+ putIReg(rd, unop(Iop_16Sto32, unop(Iop_32to16, getIReg(rt))));
+
+ break;
+
+ case 0x08 ... 0x0b: /* ALIGN */
+ if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+ if (mode64) {
+ UInt bp = (sa & 0x3) << 3;
+
+ if (bp) {
+ putIReg(rd, unop(Iop_32Sto64,
+ binop(Iop_Or32,
+ binop(Iop_Shl32,
+ unop(Iop_64to32,
+ getIReg(rt)),
+ mkU8(bp)),
+ binop(Iop_Shr32,
+ unop(Iop_64to32,
+ getIReg(rs)),
+ mkU8(32 - bp)))));
+ } else
+ putIReg(rd, getIReg(rt));
+ } else {
+ UInt bp = (sa & 0x3) << 3;
+
+ if (bp) {
+ putIReg(rd, binop(Iop_Or32,
+ binop(Iop_Shl32,
+ getIReg(rt), mkU8(bp)),
+ binop(Iop_Shr32,
+ getIReg(rs), mkU8(32 - bp))));
+ } else
+ putIReg(rd, getIReg(rt));
+ }
+ } else {
+ ILLEGAL_INSTRUCTON;
}
+
+ break;
+
+ default:
+ return -1;
+
}
- assign(t0,
- binop(Iop_Or32,
- binop(Iop_Or32,
- unop(Iop_V128to32, mkexpr(t3)),
- unop(Iop_64HIto32, unop(Iop_V128to64, mkexpr(t3)))),
- binop(Iop_Or32,
- unop(Iop_64to32, unop(Iop_V128HIto64, mkexpr(t3))),
- unop(Iop_64HIto32,
- unop(Iop_V128HIto64, mkexpr(t3))))));
- dis_branch(False,
- binop(Iop_CmpNE32, mkexpr(t0), mkU32(0)), imm, &bstmt);
- } else if (fmt == 0x0B && has_msa) { /* BZ.V */
- t0 = newTemp(Ity_I32);
- t1 = newTemp(Ity_V128);
- assign(t1, getWReg(ft));
- assign(t0,
- binop(Iop_Or32,
- binop(Iop_Or32,
- unop(Iop_V128to32, mkexpr(t1)),
- unop(Iop_64HIto32, unop(Iop_V128to64, mkexpr(t1)))),
- binop(Iop_Or32,
- unop(Iop_64to32, unop(Iop_V128HIto64, mkexpr(t1))),
- unop(Iop_64HIto32,
- unop(Iop_V128HIto64, mkexpr(t1))))));
- dis_branch(False,
- binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0)), imm, &bstmt);
- } else if (fmt == 0x09) { /* BC1EQZ */
- if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
- DIP("bc1eqz f%u, %u", ft, imm);
- t1 = newTemp(Ity_I1);
- if (mode64) {
- assign(t1, binop(Iop_CmpEQ64,
- binop(Iop_And64,
- unop(Iop_ReinterpF64asI64, getDReg(ft)),
- mkU64(1)),
- mkU64(0)));
- } else {
- assign(t1, binop(Iop_CmpEQ32,
- binop(Iop_And32,
- unop(Iop_64to32,
- unop(Iop_ReinterpF64asI64, getDReg(ft))),
- mkU32(1)),
- mkU32(0)));
- }
- dis_branch(False, mkexpr(t1), imm, &bstmt);
- } else {
- ILLEGAL_INSTRUCTON;
+ break; /* BSHFL */
+
+ /* --- MIPS32(r2) DSP ASE(r2) / Cavium Specfic (LX) instructions --- */
+ case 0xA: /* LX */
+ if (VEX_MIPS_COMP_ID(archinfo->hwcaps) == VEX_PRID_COMP_CAVIUM) {
+ if (dis_instr_CVM(cins))
+ break;
+
+ return -1;
}
- } else if (fmt == 0x0D) { /* BC1NEZ */
- if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
- DIP("bc1nez f%u, %u", ft, imm);
- t1 = newTemp(Ity_I1);
- if (mode64) {
- assign(t1, binop(Iop_CmpNE64,
- binop(Iop_And64,
- unop(Iop_ReinterpF64asI64, getDReg(ft)),
- mkU64(1)),
- mkU64(0)));
- } else {
- assign(t1, binop(Iop_CmpNE32,
- binop(Iop_And32,
- unop(Iop_64to32,
- unop(Iop_ReinterpF64asI64, getDReg(ft))),
- mkU32(1)),
- mkU32(0)));
+ /* fallthrough */
+ case 0xC: /* INSV */
+ case 0x38: { /* EXTR.W */
+ if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
+ UInt retVal = disDSPInstr_MIPS_WRK ( cins );
+
+ if (0 != retVal ) {
+ return -2;
}
- dis_branch(False, mkexpr(t1), imm, &bstmt);
+
+ break;
} else {
- ILLEGAL_INSTRUCTON;
+ return -2;
}
- } else {
- if (fmt == 0x15) { /* CMP.cond.d */
- Bool comparison = True;
- UInt signaling = CMPAFD;
- DIP("cmp.cond.d f%u, f%u, f%u, cond %u", fd, fs, ft, function);
- t0 = newTemp(Ity_I32);
- /* Conditions starting with S should signal exception on QNaN inputs. */
- switch (function) {
- case 8: /* SAF */
- signaling = CMPSAFD; /* fallthrough */
- case 0: /* AF */
- assign(t0, binop(Iop_CmpF64, getDReg(fs), getDReg(ft)));
- calculateFCSR(fs, ft, signaling, False, 2);
- putDReg(fd,
- binop(Iop_I64StoF64,
- get_IR_roundingmode(), mkU64(0)));
- break;
- case 9: /* SUN */
- signaling = CMPSAFD; /* fallthrough */
- case 1: /* UN */
- assign(t0, binop(Iop_CmpF64, getDReg(fs), getDReg(ft)));
- calculateFCSR(fs, ft, signaling, False, 2);
- putDReg(fd,
- IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x45)),
- unop(Iop_ReinterpI64asF64,
- mkU64(0xFFFFFFFFFFFFFFFFULL)),
- binop(Iop_I64StoF64,
- get_IR_roundingmode(), mkU64(0))));
- break;
- case 0x19: /* SOR */
- signaling = CMPSAFD; /* fallthrough */
- case 0x11: /* OR */
- assign(t0, binop(Iop_CmpF64, getDReg(fs), getDReg(ft)));
- calculateFCSR(fs, ft, signaling, False, 2);
- putDReg(fd,
- IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x45)),
- binop(Iop_I64StoF64,
- get_IR_roundingmode(), mkU64(0)),
- unop(Iop_ReinterpI64asF64,
- mkU64(0xFFFFFFFFFFFFFFFFULL))));
- break;
- case 0xa: /* SEQ */
- signaling = CMPSAFD; /* fallthrough */
- case 2: /* EQ */
- assign(t0, binop(Iop_CmpF64, getDReg(fs), getDReg(ft)));
- calculateFCSR(fs, ft, signaling, False, 2);
- putDReg(fd,
- IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x40)),
- unop(Iop_ReinterpI64asF64,
- mkU64(0xFFFFFFFFFFFFFFFFULL)),
- binop(Iop_I64StoF64,
- get_IR_roundingmode(), mkU64(0))));
- break;
- case 0x1A: /* SNEQ */
- signaling = CMPSAFD; /* fallthrough */
- case 0x12: /* NEQ */
- assign(t0, binop(Iop_CmpF64, getDReg(fs), getDReg(ft)));
- calculateFCSR(fs, ft, signaling, False, 2);
- putDReg(fd,
- IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x40)),
- binop(Iop_I64StoF64,
- get_IR_roundingmode(), mkU64(0)),
- unop(Iop_ReinterpI64asF64,
- mkU64(0xFFFFFFFFFFFFFFFFULL))));
- break;
- case 0xB: /* SUEQ */
- signaling = CMPSAFD; /* fallthrough */
- case 0x3: /* UEQ */
- assign(t0, binop(Iop_CmpF64, getDReg(fs), getDReg(ft)));
- calculateFCSR(fs, ft, signaling, False, 2);
- putDReg(fd,
- IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x40)),
- unop(Iop_ReinterpI64asF64,
- mkU64(0xFFFFFFFFFFFFFFFFULL)),
- IRExpr_ITE(binop(Iop_CmpEQ32,
- mkexpr(t0), mkU32(0x45)),
- unop(Iop_ReinterpI64asF64,
- mkU64(0xFFFFFFFFFFFFFFFFULL)),
- binop(Iop_I64StoF64,
- get_IR_roundingmode(),
- mkU64(0)))));
- break;
- case 0x1B: /* SNEQ */
- signaling = CMPSAFD; /* fallthrough */
- case 0x13: /* NEQ */
- assign(t0, binop(Iop_CmpF64, getDReg(fs), getDReg(ft)));
- calculateFCSR(fs, ft, signaling, False, 2);
- putDReg(fd,
- IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0),mkU32(0x01)),
- unop(Iop_ReinterpI64asF64,
- mkU64(0xFFFFFFFFFFFFFFFFULL)),
- IRExpr_ITE(binop(Iop_CmpEQ32,
- mkexpr(t0),mkU32(0x00)),
- unop(Iop_ReinterpI64asF64,
- mkU64(0xFFFFFFFFFFFFFFFFULL)),
- binop(Iop_I64StoF64,
- get_IR_roundingmode(),
- mkU64(0)))));
- break;
- case 0xC: /* SLT */
- signaling = CMPSAFD; /* fallthrough */
- case 0x4: /* LT */
- assign(t0, binop(Iop_CmpF64, getDReg(fs), getDReg(ft)));
- calculateFCSR(fs, ft, signaling, False, 2);
- putDReg(fd,
- IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x01)),
- unop(Iop_ReinterpI64asF64,
- mkU64(0xFFFFFFFFFFFFFFFFULL)),
- binop(Iop_I64StoF64,
- get_IR_roundingmode(), mkU64(0))));
- break;
- case 0xD: /* SULT */
- signaling = CMPSAFD; /* fallthrough */
- case 0x5: /* ULT */
- assign(t0, binop(Iop_CmpF64, getDReg(fs), getDReg(ft)));
- calculateFCSR(fs, ft, signaling, False, 2);
- putDReg(fd,
- IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x01)),
- unop(Iop_ReinterpI64asF64,
- mkU64(0xFFFFFFFFFFFFFFFFULL)),
- IRExpr_ITE(binop(Iop_CmpEQ32,
- mkexpr(t0), mkU32(0x45)),
- unop(Iop_ReinterpI64asF64,
- mkU64(0xFFFFFFFFFFFFFFFFULL)),
- binop(Iop_I64StoF64,
- get_IR_roundingmode(),
- mkU64(0)))));
- break;
- case 0xE: /* SLE */
- signaling = CMPSAFD; /* fallthrough */
- case 0x6: /* LE */
- assign(t0, binop(Iop_CmpF64, getDReg(fs), getDReg(ft)));
- calculateFCSR(fs, ft, signaling, False, 2);
- putDReg(fd,
- IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0),mkU32(0x01)),
- unop(Iop_ReinterpI64asF64,
- mkU64(0xFFFFFFFFFFFFFFFFULL)),
- IRExpr_ITE(binop(Iop_CmpEQ32,
- mkexpr(t0),mkU32(0x40)),
- unop(Iop_ReinterpI64asF64,
- mkU64(0xFFFFFFFFFFFFFFFFULL)),
- binop(Iop_I64StoF64,
- get_IR_roundingmode(),
- mkU64(0)))));
- break;
- case 0xF: /* SULE */
- signaling = CMPSAFD; /* fallthrough */
- case 0x7: /* ULE */
- assign(t0, binop(Iop_CmpF64, getDReg(fs), getDReg(ft)));
- calculateFCSR(fs, ft, signaling, False, 2);
- putDReg(fd,
- IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x0)),
- binop(Iop_I64StoF64,
- get_IR_roundingmode(), mkU64(0)),
- unop(Iop_ReinterpI64asF64,
- mkU64(0xFFFFFFFFFFFFFFFFULL))));
+
+ break;
+ }
+
+ case 0x10: { /* ADDU.QB */
+ switch (sa) {
+ case 0xC: /* SUBU_S.PH */
+ case 0xD: /* ADDU_S.PH */
+ case 0x1E: { /* MULQ_S.PH */
+ if (VEX_MIPS_PROC_DSP2(archinfo->hwcaps)) {
+ UInt retVal = disDSPInstr_MIPS_WRK ( cins );
+
+ if (0 != retVal ) {
+ return -2;
+ }
+
break;
- default:
- comparison = False;
- }
- if (comparison) {
- if (!VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
- ILLEGAL_INSTRUCTON;
+ } else {
+ return -2;
}
+
break;
}
- } else if (fmt == 0x14) {
- Bool comparison = True;
- UInt signaling = CMPAFS;
- DIP("cmp.cond.s f%u, f%u, f%u, cond %u", fd, fs, ft, function);
- t0 = newTemp(Ity_I32);
- /* Conditions starting with S should signal exception on QNaN inputs. */
- switch (function) {
- case 8: /* SAF */
- signaling = CMPSAFS; /* fallthrough */
- case 0: /* AF */
- assign(t0, binop(Iop_CmpF32,
- getLoFromF64(Ity_F64, getFReg(fs)),
- getLoFromF64(Ity_F64, getFReg(ft))));
- calculateFCSR(fs, ft, signaling, True, 2);
- putFReg(fd,
- mkWidenFromF32(tyF,
- binop(Iop_I32StoF32,
- get_IR_roundingmode(), mkU32(0))));
- break;
- case 9: /* SUN */
- signaling = CMPSAFS; /* fallthrough */
- case 1: /* UN */
- assign(t0, binop(Iop_CmpF32,
- getLoFromF64(Ity_F64, getFReg(fs)),
- getLoFromF64(Ity_F64, getFReg(ft))));
- calculateFCSR(fs, ft, signaling, True, 2);
- putFReg(fd,
- IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x45)),
- mkWidenFromF32(tyF,
- unop(Iop_ReinterpI32asF32,
- mkU32(0xFFFFFFFFU))),
- mkWidenFromF32(tyF,
- binop(Iop_I32StoF32,
- get_IR_roundingmode(),
- mkU32(0)))));
- break;
- case 0x19: /* SOR */
- signaling = CMPSAFS; /* fallthrough */
- case 0x11: /* OR */
- assign(t0, binop(Iop_CmpF32,
- getLoFromF64(Ity_F64, getFReg(fs)),
- getLoFromF64(Ity_F64, getFReg(ft))));
- calculateFCSR(fs, ft, signaling, True, 2);
- putFReg(fd,
- IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x45)),
- mkWidenFromF32(tyF,
- binop(Iop_I32StoF32,
- get_IR_roundingmode(),
- mkU32(0))),
- mkWidenFromF32(tyF,
- unop(Iop_ReinterpI32asF32,
- mkU32(0xFFFFFFFFU)))));
- break;
- case 0xa: /* SEQ */
- signaling = CMPSAFS; /* fallthrough */
- case 2: /* EQ */
- assign(t0, binop(Iop_CmpF32,
- getLoFromF64(Ity_F64, getFReg(fs)),
- getLoFromF64(Ity_F64, getFReg(ft))));
- calculateFCSR(fs, ft, signaling, True, 2);
- putFReg(fd,
- IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x40)),
- mkWidenFromF32(tyF,
- unop(Iop_ReinterpI32asF32,
- mkU32(0xFFFFFFFFU))),
- mkWidenFromF32(tyF,
- binop(Iop_I32StoF32,
- get_IR_roundingmode(),
- mkU32(0)))));
- break;
- case 0x1A: /* SNEQ */
- signaling = CMPSAFS; /* fallthrough */
- case 0x12: /* NEQ */
- assign(t0, binop(Iop_CmpF32,
- getLoFromF64(Ity_F64, getFReg(fs)),
- getLoFromF64(Ity_F64, getFReg(ft))));
- calculateFCSR(fs, ft, signaling, True, 2);
- putFReg(fd,
- IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x40)),
- mkWidenFromF32(tyF,
- binop(Iop_I32StoF32,
- get_IR_roundingmode(),
- mkU32(0))),
- mkWidenFromF32(tyF,
- unop(Iop_ReinterpI32asF32,
- mkU32(0xFFFFFFFFU)))));
- break;
- case 0xB: /* SUEQ */
- signaling = CMPSAFS; /* fallthrough */
- case 0x3: /* UEQ */
- assign(t0, binop(Iop_CmpF32,
- getLoFromF64(Ity_F64, getFReg(fs)),
- getLoFromF64(Ity_F64, getFReg(ft))));
- calculateFCSR(fs, ft, signaling, True, 2);
- putFReg(fd,
- IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x40)),
- mkWidenFromF32(tyF,
- unop(Iop_ReinterpI32asF32,
- mkU32(0xFFFFFFFFU))),
- IRExpr_ITE(binop(Iop_CmpEQ32,
- mkexpr(t0), mkU32(0x45)),
- mkWidenFromF32(tyF,
- unop(Iop_ReinterpI32asF32,
- mkU32(0xFFFFFFFFU))),
- mkWidenFromF32(tyF,
- binop(Iop_I32StoF32,
- get_IR_roundingmode(),
- mkU32(0))))));
- break;
- case 0x1B: /* SNEQ */
- signaling = CMPSAFS; /* fallthrough */
- case 0x13: /* NEQ */
- assign(t0, binop(Iop_CmpF32,
- getLoFromF64(Ity_F64, getFReg(fs)),
- getLoFromF64(Ity_F64, getFReg(ft))));
- calculateFCSR(fs, ft, signaling, True, 2);
- putFReg(fd,
- IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0),mkU32(0x01)),
- mkWidenFromF32(tyF,
- unop(Iop_ReinterpI32asF32,
- mkU32(0xFFFFFFFFU))),
- IRExpr_ITE(binop(Iop_CmpEQ32,
- mkexpr(t0),mkU32(0x00)),
- mkWidenFromF32(tyF,
- unop(Iop_ReinterpI32asF32,
- mkU32(0xFFFFFFFFU))),
- mkWidenFromF32(tyF,
- binop(Iop_I32StoF32,
- get_IR_roundingmode(),
- mkU32(0))))));
- break;
- case 0xC: /* SLT */
- signaling = CMPSAFS; /* fallthrough */
- case 0x4: /* LT */
- assign(t0, binop(Iop_CmpF32,
- getLoFromF64(Ity_F64, getFReg(fs)),
- getLoFromF64(Ity_F64, getFReg(ft))));
- calculateFCSR(fs, ft, signaling, True, 2);
- putFReg(fd,
- IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x01)),
- mkWidenFromF32(tyF,
- unop(Iop_ReinterpI32asF32,
- mkU32(0xFFFFFFFFU))),
- mkWidenFromF32(tyF,
- binop(Iop_I32StoF32,
- get_IR_roundingmode(),
- mkU32(0)))));
- break;
- case 0xD: /* SULT */
- signaling = CMPSAFS; /* fallthrough */
- case 0x5: /* ULT */
- assign(t0, binop(Iop_CmpF32,
- getLoFromF64(Ity_F64, getFReg(fs)),
- getLoFromF64(Ity_F64, getFReg(ft))));
- calculateFCSR(fs, ft, signaling, True, 2);
- putFReg(fd,
- IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x01)),
- mkWidenFromF32(tyF,
- unop(Iop_ReinterpI32asF32,
- mkU32(0xFFFFFFFFU))),
- IRExpr_ITE(binop(Iop_CmpEQ32,
- mkexpr(t0), mkU32(0x45)),
- mkWidenFromF32(tyF,
- unop(Iop_ReinterpI32asF32,
- mkU32(0xFFFFFFFFU))),
- mkWidenFromF32(tyF,
- binop(Iop_I32StoF32,
- get_IR_roundingmode(),
- mkU32(0))))));
- break;
- case 0xE: /* SLE */
- signaling = CMPSAFS; /* fallthrough */
- case 0x6: /* LE */
- assign(t0, binop(Iop_CmpF32,
- getLoFromF64(Ity_F64, getFReg(fs)),
- getLoFromF64(Ity_F64, getFReg(ft))));
- calculateFCSR(fs, ft, signaling, True, 2);
- putFReg(fd,
- IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0),mkU32(0x01)),
- mkWidenFromF32(tyF,
- unop(Iop_ReinterpI32asF32,
- mkU32(0xFFFFFFFFU))),
- IRExpr_ITE(binop(Iop_CmpEQ32,
- mkexpr(t0),mkU32(0x40)),
- mkWidenFromF32(tyF,
- unop(Iop_ReinterpI32asF32,
- mkU32(0xFFFFFFFFU))),
- mkWidenFromF32(tyF,
- binop(Iop_I32StoF32,
- get_IR_roundingmode(),
- mkU32(0))))));
- break;
- case 0xF: /* SULE */
- signaling = CMPSAFS; /* fallthrough */
- case 0x7: /* ULE */
- assign(t0, binop(Iop_CmpF32,
- getLoFromF64(Ity_F64, getFReg(fs)),
- getLoFromF64(Ity_F64, getFReg(ft))));
- calculateFCSR(fs, ft, signaling, True, 2);
- putFReg(fd,
- IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x0)),
- mkWidenFromF32(tyF,
- binop(Iop_I32StoF32,
- get_IR_roundingmode(),
- mkU32(0))),
- mkWidenFromF32(tyF,
- unop(Iop_ReinterpI32asF32,
- mkU32(0xFFFFFFFFU)))));
+ default: {
+ if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
+ UInt retVal = disDSPInstr_MIPS_WRK ( cins );
+
+ if (0 != retVal ) {
+ return -2;
+ }
+
break;
- default:
- comparison = False;
- }
- if (comparison) {
- if (!VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
- ILLEGAL_INSTRUCTON;
+ } else {
+ return -2;
}
+
break;
}
}
- switch (function) {
- case 0x4: { /* SQRT.fmt */
- switch (fmt) {
- case 0x10: { /* S */
- IRExpr *rm = get_IR_roundingmode();
- putFReg(fd, mkWidenFromF32(tyF, binop(Iop_SqrtF32, rm,
- getLoFromF64(tyF, getFReg(fs)))));
- break;
- }
- case 0x11: { /* D */
- IRExpr *rm = get_IR_roundingmode();
- putDReg(fd, binop(Iop_SqrtF64, rm, getDReg(fs)));
- break;
- }
- default:
- goto decode_failure;
+ break;
+ }
+
+ case 0x11: { /* CMPU.EQ.QB */
+ switch (sa) {
+ case 0x18: /* CMPGDU.EQ.QB */
+ case 0x19: /* CMPGDU.LT.QB */
+ case 0x1A: /* CMPGDU.LE.QB */
+ case 0x0D: /* PRECR.QB.PH */
+ case 0x1E: /* PRECR_SRA.PH.W */
+ case 0x1F: { /* PRECR_SRA_R.PH.W */
+ if (VEX_MIPS_PROC_DSP2(archinfo->hwcaps)) {
+ UInt retVal = disDSPInstr_MIPS_WRK ( cins );
+
+ if (0 != retVal ) {
+ return -2;
}
+
+ break;
+ } else {
+ return -2;
}
+
break;
- case 0x5: /* abs.fmt */
- switch (fmt) {
- case 0x10: /* S */
- DIP("abs.s f%u, f%u", fd, fs);
- putFReg(fd, mkWidenFromF32(tyF, unop(Iop_AbsF32,
- getLoFromF64(tyF, getFReg(fs)))));
- break;
- case 0x11: /* D */
- DIP("abs.d f%u, f%u", fd, fs);
- putDReg(fd, unop(Iop_AbsF64, getDReg(fs)));
- break;
- default:
- goto decode_failure;
- }
- break; /* case 0x5 */
-
- case 0x02: /* MUL.fmt */
- switch (fmt) {
- case 0x11: { /* D */
- DIP("mul.d f%u, f%u, f%u", fd, fs, ft);
- IRExpr *rm = get_IR_roundingmode();
- putDReg(fd, triop(Iop_MulF64, rm, getDReg(fs),
- getDReg(ft)));
- break;
- }
- case 0x10: { /* S */
- DIP("mul.s f%u, f%u, f%u", fd, fs, ft);
- IRExpr *rm = get_IR_roundingmode();
- putFReg(fd, mkWidenFromF32(tyF, triop(Iop_MulF32, rm,
- getLoFromF64(tyF, getFReg(fs)),
- getLoFromF64(tyF, getFReg(ft)))));
- break;
- }
- default:
- goto decode_failure;
- }
- break; /* MUL.fmt */
-
- case 0x03: /* DIV.fmt */
- switch (fmt) {
- case 0x11: { /* D */
- DIP("div.d f%u, f%u, f%u", fd, fs, ft);
- IRExpr *rm = get_IR_roundingmode();
- putDReg(fd, triop(Iop_DivF64, rm, getDReg(fs),
- getDReg(ft)));
- break;
- }
- case 0x10: { /* S */
- DIP("div.s f%u, f%u, f%u", fd, fs, ft);
- calculateFCSR(fs, ft, DIVS, False, 2);
- IRExpr *rm = get_IR_roundingmode();
- putFReg(fd, mkWidenFromF32(tyF, triop(Iop_DivF32, rm,
- getLoFromF64(tyF, getFReg(fs)),
- getLoFromF64(tyF, getFReg(ft)))));
- break;
- }
- default:
- goto decode_failure;
- }
- break; /* DIV.fmt */
-
- case 0x01: /* SUB.fmt */
- switch (fmt) {
- case 0x11: { /* D */
- DIP("sub.d f%u, f%u, f%u", fd, fs, ft);
- calculateFCSR(fs, ft, SUBD, False, 2);
- IRExpr *rm = get_IR_roundingmode();
- putDReg(fd, triop(Iop_SubF64, rm, getDReg(fs),
- getDReg(ft)));
- break;
- }
- case 0x10: { /* S */
- DIP("sub.s f%u, f%u, f%u", fd, fs, ft);
- calculateFCSR(fs, ft, SUBS, True, 2);
- IRExpr *rm = get_IR_roundingmode();
- putFReg(fd, mkWidenFromF32(tyF, triop(Iop_SubF32, rm,
- getLoFromF64(tyF, getFReg(fs)),
- getLoFromF64(tyF, getFReg(ft)))));
- break;
+ }
+
+ default: {
+ if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
+ UInt retVal = disDSPInstr_MIPS_WRK ( cins );
+
+ if (0 != retVal ) {
+ return -2;
}
- default:
- goto decode_failure;
- }
- break; /* SUB.fmt */
-
- case 0x06: /* MOV.fmt */
- switch (fmt) {
- case 0x11: /* D */
- DIP("mov.d f%u, f%u", fd, fs);
- if (fp_mode64) {
- putDReg(fd, getDReg(fs));
- } else {
- putFReg(fd, getFReg(fs));
- putFReg(fd + 1, getFReg(fs + 1));
- }
- break;
- case 0x10: /* S */
- DIP("mov.s f%u, f%u", fd, fs);
- putFReg(fd, getFReg(fs));
- break;
- default:
- goto decode_failure;
- }
- break; /* MOV.fmt */
-
- case 0x7: /* neg.fmt */
- switch (fmt) {
- case 0x10: /* S */
- DIP("neg.s f%u, f%u", fd, fs);
- putFReg(fd, mkWidenFromF32(tyF, unop(Iop_NegF32,
- getLoFromF64(tyF, getFReg(fs)))));
- break;
- case 0x11: /* D */
- DIP("neg.d f%u, f%u", fd, fs);
- putDReg(fd, unop(Iop_NegF64, getDReg(fs)));
- break;
- default:
- goto decode_failure;
+
+ break;
+ } else {
+ return -2;
}
- break; /* case 0x7 */
- case 0x08: /* ROUND.L.fmt */
- switch (fmt) {
- case 0x10: /* S */
- DIP("round.l.s f%u, f%u", fd, fs);
- if (fp_mode64) {
- calculateFCSR(fs, 0, ROUNDLS, True, 1);
- t0 = newTemp(Ity_I64);
+ break;
+ }
+ }
- assign(t0, binop(Iop_F32toI64S, mkU32(0x0),
- getLoFromF64(Ity_F64, getFReg(fs))));
+ break;
+ }
- putDReg(fd, unop(Iop_ReinterpI64asF64, mkexpr(t0)));
- } else {
- ILLEGAL_INSTRUCTON;
- }
- break;
- case 0x11: /* D */
- DIP("round.l.d f%u, f%u", fd, fs);
- if (fp_mode64) {
- calculateFCSR(fs, 0, ROUNDLD, False, 1);
- putDReg(fd, unop(Iop_ReinterpI64asF64,
- binop(Iop_F64toI64S,
- mkU32(0x0),
- getDReg(fs))));
- } else {
- ILLEGAL_INSTRUCTON;
- }
- break;
- default:
- goto decode_failure;
+ case 0x12: { /* ABSQ_S.PH */
+ switch (sa) {
+ case 0x1: { /* ABSQ_S.QB */
+ if (VEX_MIPS_PROC_DSP2(archinfo->hwcaps)) {
+ UInt retVal = disDSPInstr_MIPS_WRK ( cins );
- }
- break; /* ROUND.L.fmt */
-
- case 0x09: /* TRUNC.L.fmt */
- switch (fmt) {
- case 0x10: /* S */
- DIP("trunc.l.s f%u, f%u", fd, fs);
- if (fp_mode64) {
- calculateFCSR(fs, 0, TRUNCLS, True, 1);
- t0 = newTemp(Ity_I64);
- assign(t0, binop(Iop_F32toI64S, mkU32(0x3),
- getLoFromF64(Ity_F64, getFReg(fs))));
-
- putDReg(fd, unop(Iop_ReinterpI64asF64, mkexpr(t0)));
- } else {
- ILLEGAL_INSTRUCTON;
- }
- break;
- case 0x11: /* D */
- DIP("trunc.l.d f%u, f%u", fd, fs);
- if (fp_mode64) {
- calculateFCSR(fs, 0, TRUNCLD, False, 1);
- putDReg(fd, unop(Iop_ReinterpI64asF64,
- binop(Iop_F64toI64S,
- mkU32(0x3),
- getDReg(fs))));
- } else {
- ILLEGAL_INSTRUCTON;
- }
- break;
- default:
- goto decode_failure;
- }
- break; /* TRUNC.L.fmt */
-
- case 0x15: /* RECIP.fmt */
- switch (fmt) {
- case 0x10: { /* S */
- DIP("recip.s f%u, f%u", fd, fs);
- IRExpr *rm = get_IR_roundingmode();
- putFReg(fd, mkWidenFromF32(tyF, triop(Iop_DivF32,
- rm, unop(Iop_ReinterpI32asF32,
- mkU32(ONE_SINGLE)), getLoFromF64(tyF,
- getFReg(fs)))));
- break;
- }
- case 0x11: { /* D */
- DIP("recip.d f%u, f%u", fd, fs);
- IRExpr *rm = get_IR_roundingmode();
- /* putDReg(fd, 1.0/getDreg(fs)); */
- putDReg(fd, triop(Iop_DivF64, rm,
- unop(Iop_ReinterpI64asF64,
- mkU64(ONE_DOUBLE)), getDReg(fs)));
- break;
+ if (0 != retVal ) {
+ return -2;
}
- default:
- goto decode_failure;
+ break;
+ } else {
+ return -2;
}
- break; /* case 0x15 */
-
- case 0x13: /* MOVN.fmt */
- switch (fmt) {
- case 0x10: /* S */
- DIP("movn.s f%u, f%u, r%u", fd, fs, rt);
- t1 = newTemp(Ity_I1);
- if (mode64)
- assign(t1, binop(Iop_CmpNE64, mkU64(0), getIReg(rt)));
- else
- assign(t1, binop(Iop_CmpNE32, mkU32(0), getIReg(rt)));
+ break;
+ }
- putFReg(fd, IRExpr_ITE(mkexpr(t1), getFReg(fs), getFReg(fd)));
- break;
- case 0x11: /* D */
- DIP("movn.d f%u, f%u, r%u", fd, fs, rt);
- t1 = newTemp(Ity_I1);
+ default: {
+ if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
+ UInt retVal = disDSPInstr_MIPS_WRK ( cins );
- if (mode64)
- assign(t1, binop(Iop_CmpNE64, mkU64(0), getIReg(rt)));
- else
- assign(t1, binop(Iop_CmpNE32, mkU32(0), getIReg(rt)));
+ if (0 != retVal ) {
+ return -2;
+ }
- putDReg(fd, IRExpr_ITE(mkexpr(t1), getDReg(fs), getDReg(fd)));
break;
- default:
- goto decode_failure;
+ } else {
+ return -2;
}
- break; /* MOVN.fmt */
- case 0x12: /* MOVZ.fmt */
- switch (fmt) {
- case 0x10: /* S */
- DIP("movz.s f%u, f%u, r%u", fd, fs, rt);
- t1 = newTemp(Ity_I1);
+ break;
+ }
+ }
- if (mode64)
- assign(t1, binop(Iop_CmpEQ64, mkU64(0), getIReg(rt)));
- else
- assign(t1, binop(Iop_CmpEQ32, mkU32(0), getIReg(rt)));
+ break;
+ }
- putFReg(fd, IRExpr_ITE(mkexpr(t1), getFReg(fs), getFReg(fd)));
- break;
- case 0x11: /* D */
- DIP("movz.d f%u, f%u, r%u", fd, fs, rt);
- t1 = newTemp(Ity_I1);
+ case 0x13: { /* SHLL.QB */
+ switch (sa) {
+ case 0x04: /* SHRA.QB */
+ case 0x05: /* SHRA_R.QB */
+ case 0x06: /* SHRAV.QB */
+ case 0x07: /* SHRAV_R.QB */
+ case 0x19: /* SHLR.PH */
+ case 0x1B: { /* SHLRV.PH */
+ if (VEX_MIPS_PROC_DSP2(archinfo->hwcaps)) {
+ UInt retVal = disDSPInstr_MIPS_WRK ( cins );
- if (mode64)
- assign(t1, binop(Iop_CmpEQ64, mkU64(0), getIReg(rt)));
- else
- assign(t1, binop(Iop_CmpEQ32, mkU32(0), getIReg(rt)));
+ if (0 != retVal ) {
+ return -2;
+ }
- putDReg(fd, IRExpr_ITE(mkexpr(t1), getDReg(fs), getDReg(fd)));
break;
- default:
- goto decode_failure;
+ } else {
+ return -2;
}
- break; /* MOVZ.fmt */
-
- case 0x11: /* MOVT.fmt */
- if (tf == 1) {
- UInt mov_cc = get_mov_cc(cins);
- switch (fmt) { /* MOVCF = 010001 */
- case 0x11: /* D */
- DIP("movt.d f%u, f%u, %u", fd, fs, mov_cc);
- t1 = newTemp(Ity_I1);
- t2 = newTemp(Ity_I32);
- t3 = newTemp(Ity_I1);
- t4 = newTemp(Ity_F64);
-
- assign(t1, binop(Iop_CmpEQ32, mkU32(0), mkU32(mov_cc)));
- assign(t2, IRExpr_ITE(mkexpr(t1),
- binop(Iop_And32,
- binop(Iop_Shr32, getFCSR(),
- mkU8(23)),
- mkU32(0x1)),
- binop(Iop_And32,
- binop(Iop_Shr32, getFCSR(),
- mkU8(24 + mov_cc)),
- mkU32(0x1))
- ));
-
- assign(t3, binop(Iop_CmpEQ32, mkU32(1), mkexpr(t2)));
- assign(t4, IRExpr_ITE(mkexpr(t3),
- getDReg(fs), getDReg(fd)));
- putDReg(fd, mkexpr(t4));
- break;
- case 0x10: /* S */
- DIP("movt.s f%u, f%u, %u", fd, fs, mov_cc);
- t1 = newTemp(Ity_I1);
- t2 = newTemp(Ity_I32);
- t3 = newTemp(Ity_I1);
- t4 = newTemp(Ity_F64);
- t5 = newTemp(Ity_F64);
- t6 = newTemp(Ity_F64);
- t7 = newTemp(Ity_I64);
-
- if (fp_mode64) {
- assign(t5, getFReg(fs));
- assign(t6, getFReg(fd));
- } else {
- assign(t5, unop(Iop_F32toF64, getFReg(fs)));
- assign(t6, unop(Iop_F32toF64, getFReg(fd)));
- }
- assign(t1, binop(Iop_CmpEQ32, mkU32(0), mkU32(mov_cc)));
- assign(t2, IRExpr_ITE(mkexpr(t1),
- binop(Iop_And32,
- binop(Iop_Shr32, getFCSR(),
- mkU8(23)),
- mkU32(0x1)),
- binop(Iop_And32,
- binop(Iop_Shr32, getFCSR(),
- mkU8(24 + mov_cc)),
- mkU32(0x1))
- ));
-
- assign(t3, binop(Iop_CmpEQ32, mkU32(1), mkexpr(t2)));
- assign(t4, IRExpr_ITE(mkexpr(t3),
- mkexpr(t5), mkexpr(t6)));
-
- if (fp_mode64) {
- IRTemp f = newTemp(Ity_F64);
- IRTemp fd_hi = newTemp(Ity_I32);
- assign(f, getFReg(fd));
- assign(fd_hi, unop(Iop_64HIto32,
- unop(Iop_ReinterpF64asI64, mkexpr(f))));
- assign(t7, mkWidenFrom32(Ity_I64, unop(Iop_64to32,
- unop(Iop_ReinterpF64asI64, mkexpr(t4))),
- True));
+ break;
+ }
- putFReg(fd, unop(Iop_ReinterpI64asF64, mkexpr(t7)));
- } else
- putFReg(fd, binop(Iop_F64toF32, get_IR_roundingmode(),
- mkexpr(t4)));
- break;
- default:
- goto decode_failure;
- }
- } else if (tf == 0) /* movf.fmt */
- {
- UInt mov_cc = get_mov_cc(cins);
- switch (fmt) /* MOVCF = 010001 */
- {
- case 0x11: /* D */
- DIP("movf.d f%u, f%u, %u", fd, fs, mov_cc);
- t1 = newTemp(Ity_I1);
- t2 = newTemp(Ity_I32);
- t3 = newTemp(Ity_I1);
- t4 = newTemp(Ity_F64);
-
- assign(t1, binop(Iop_CmpEQ32, mkU32(0), mkU32(mov_cc)));
- assign(t2, IRExpr_ITE(mkexpr(t1),
- binop(Iop_And32,
- binop(Iop_Shr32, getFCSR(),
- mkU8(23)),
- mkU32(0x1)),
- binop(Iop_And32,
- binop(Iop_Shr32, getFCSR(),
- mkU8(24 + mov_cc)),
- mkU32(0x1))
- ));
-
- assign(t3, binop(Iop_CmpEQ32, mkU32(0), mkexpr(t2)));
- assign(t4, IRExpr_ITE(mkexpr(t3),
- getDReg(fs), getDReg(fd)));
- putDReg(fd, mkexpr(t4));
- break;
- case 0x10: /* S */
- DIP("movf.s f%u, f%u, %u", fd, fs, mov_cc);
- t1 = newTemp(Ity_I1);
- t2 = newTemp(Ity_I32);
- t3 = newTemp(Ity_I1);
- t4 = newTemp(Ity_F64);
- t5 = newTemp(Ity_F64);
- t6 = newTemp(Ity_F64);
-
- if (fp_mode64) {
- assign(t5, getFReg(fs));
- assign(t6, getFReg(fd));
- } else {
- assign(t5, unop(Iop_F32toF64, getFReg(fs)));
- assign(t6, unop(Iop_F32toF64, getFReg(fd)));
- }
+ default: {
+ if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
+ UInt retVal = disDSPInstr_MIPS_WRK ( cins );
- assign(t1, binop(Iop_CmpEQ32, mkU32(0), mkU32(mov_cc)));
- assign(t2, IRExpr_ITE(mkexpr(t1),
- binop(Iop_And32,
- binop(Iop_Shr32, getFCSR(),
- mkU8(23)),
- mkU32(0x1)),
- binop(Iop_And32,
- binop(Iop_Shr32, getFCSR(),
- mkU8(24 + mov_cc)),
- mkU32(0x1))
- ));
-
- assign(t3, binop(Iop_CmpEQ32, mkU32(0), mkexpr(t2)));
- assign(t4, IRExpr_ITE(mkexpr(t3),
- mkexpr(t5), mkexpr(t6)));
-
- if (fp_mode64) {
- IRTemp f = newTemp(Ity_F64);
- IRTemp fd_hi = newTemp(Ity_I32);
- t7 = newTemp(Ity_I64);
- assign(f, getFReg(fd));
- assign(fd_hi, unop(Iop_64HIto32,
- unop(Iop_ReinterpF64asI64, mkexpr(f))));
- assign(t7, mkWidenFrom32(Ity_I64, unop(Iop_64to32,
- unop(Iop_ReinterpF64asI64, mkexpr(t4))),
- True));
-
- putFReg(fd, unop(Iop_ReinterpI64asF64, mkexpr(t7)));
- } else
- putFReg(fd, binop(Iop_F64toF32, get_IR_roundingmode(),
- mkexpr(t4)));
- break;
- default:
- goto decode_failure;
+ if (0 != retVal ) {
+ return -2;
}
- }
- break; /* MOVT.fmt */
-
- case 0x0: /* add.fmt */
- switch (fmt) {
- case 0x10: { /* S */
- DIP("add.s f%u, f%u, f%u", fd, fs, ft);
- calculateFCSR(fs, ft, ADDS, True, 2);
- IRExpr *rm = get_IR_roundingmode();
- putFReg(fd, mkWidenFromF32(tyF, triop(Iop_AddF32, rm,
- getLoFromF64(tyF, getFReg(fs)),
- getLoFromF64(tyF, getFReg(ft)))));
- break;
- }
- case 0x11: { /* D */
- DIP("add.d f%u, f%u, f%u", fd, fs, ft);
- calculateFCSR(fs, ft, ADDD, False, 2);
- IRExpr *rm = get_IR_roundingmode();
- putDReg(fd, triop(Iop_AddF64, rm, getDReg(fs), getDReg(ft)));
break;
+ } else {
+ return -2;
}
- case 0x4: /* MTC1 (Move Word to Floating Point) */
- DIP("mtc1 r%u, f%u", rt, fs);
- if (fp_mode64) {
- t0 = newTemp(Ity_I32);
- t1 = newTemp(Ity_F32);
- assign(t0, mkNarrowTo32(ty, getIReg(rt)));
- assign(t1, unop(Iop_ReinterpI32asF32, mkexpr(t0)));
+ break;
+ }
+ }
- putFReg(fs, mkWidenFromF32(tyF, mkexpr(t1)));
- } else
- putFReg(fs, unop(Iop_ReinterpI32asF32,
- mkNarrowTo32(ty, getIReg(rt))));
- break;
+ break;
+ }
- case 0x5: /* Doubleword Move to Floating Point DMTC1; MIPS64 */
- DIP("dmtc1 r%u, f%u", rt, fs);
- vassert(mode64);
- putDReg(fs, unop(Iop_ReinterpI64asF64, getIReg(rt)));
- break;
+ case 0x30: { /* DPAQ.W.PH */
+ switch (sa) {
+ case 0x0: /* DPA.W.PH */
+ case 0x18: /* DPAQX_S.W.PH */
+ case 0x1A: /* DPAQX_SA.W.PH */
+ case 0x8: /* DPAX.W.PH */
+ case 0x1: /* DPS.W.PH */
+ case 0x19: /* DPSQX_S.W.PH */
+ case 0x1B: /* DPSQX_SA.W.PH */
+ case 0x9: /* DPSX.W.PH */
+ case 0x2: { /* MULSA.W.PH */
+ if (VEX_MIPS_PROC_DSP2(archinfo->hwcaps)) {
+ UInt retVal = disDSPInstr_MIPS_WRK ( cins );
- case 0x0: /* MFC1 */
- DIP("mfc1 r%u, f%u", rt, fs);
- if (fp_mode64) {
- t0 = newTemp(Ity_I64);
- t1 = newTemp(Ity_I32);
- assign(t0, unop(Iop_ReinterpF64asI64, getFReg(fs)));
- assign(t1, unop(Iop_64to32, mkexpr(t0)));
- putIReg(rt, mkWidenFrom32(ty, mkexpr(t1), True));
- } else
- putIReg(rt, mkWidenFrom32(ty,
- unop(Iop_ReinterpF32asI32, getFReg(fs)),
- True));
- break;
+ if (0 != retVal ) {
+ return -2;
+ }
- case 0x1: /* Doubleword Move from Floating Point DMFC1;
- MIPS64 */
- DIP("dmfc1 r%u, f%u", rt, fs);
- putIReg(rt, unop(Iop_ReinterpF64asI64, getDReg(fs)));
break;
+ } else {
+ return -2;
+ }
- case 0x6: /* CTC1 */
- DIP("ctc1 r%u, f%u", rt, fs);
- t0 = newTemp(Ity_I32);
- t1 = newTemp(Ity_I32);
- t2 = newTemp(Ity_I32);
- t3 = newTemp(Ity_I32);
- t4 = newTemp(Ity_I32);
- t5 = newTemp(Ity_I32);
- t6 = newTemp(Ity_I32);
- assign(t0, mkNarrowTo32(ty, getIReg(rt)));
- if (fs == 25) { /* FCCR */
- assign(t1, binop(Iop_Shl32, binop(Iop_And32, mkexpr(t0),
- mkU32(0x000000FE)), mkU8(24)));
- assign(t2, binop(Iop_And32, mkexpr(t0),
- mkU32(0x01000000)));
- assign(t3, binop(Iop_Shl32, binop(Iop_And32, mkexpr(t0),
- mkU32(0x00000001)), mkU8(23)));
- assign(t4, binop(Iop_And32, mkexpr(t0),
- mkU32(0x007FFFFF)));
- putFCSR(binop(Iop_Or32, binop(Iop_Or32, mkexpr(t1),
- mkexpr(t2)), binop(Iop_Or32, mkexpr(t3),
- mkexpr(t4))));
- } else if (fs == 26) { /* FEXR */
- assign(t1, binop(Iop_And32, getFCSR(), mkU32(0xFFFC0000)));
- assign(t2, binop(Iop_And32, mkexpr(t0),
- mkU32(0x0003F000)));
- assign(t3, binop(Iop_And32, getFCSR(), mkU32(0x00000F80)));
- assign(t4, binop(Iop_And32, mkexpr(t0),
- mkU32(0x0000007C)));
- assign(t5, binop(Iop_And32, getFCSR(), mkU32(0x00000003)));
- putFCSR(binop(Iop_Or32, binop(Iop_Or32, binop(Iop_Or32,
- mkexpr(t1), mkexpr(t2)), binop(Iop_Or32,
- mkexpr(t3), mkexpr(t4))), mkexpr(t5)));
- } else if (fs == 28) {
- assign(t1, binop(Iop_And32, getFCSR(), mkU32(0xFE000000)));
- assign(t2, binop(Iop_Shl32, binop(Iop_And32, mkexpr(t0),
- mkU32(0x00000002)), mkU8(22)));
- assign(t3, binop(Iop_And32, getFCSR(), mkU32(0x00FFF000)));
- assign(t4, binop(Iop_And32, mkexpr(t0),
- mkU32(0x00000F80)));
- assign(t5, binop(Iop_And32, getFCSR(), mkU32(0x0000007C)));
- assign(t6, binop(Iop_And32, mkexpr(t0),
- mkU32(0x00000003)));
- putFCSR(binop(Iop_Or32, binop(Iop_Or32, binop(Iop_Or32,
- mkexpr(t1), mkexpr(t2)), binop(Iop_Or32,
- mkexpr(t3), mkexpr(t4))), binop(Iop_Or32,
- mkexpr(t5), mkexpr(t6))));
- } else if (fs == 31) {
- putFCSR(mkexpr(t0));
- }
- break;
- case 0x2: /* CFC1 */
- DIP("cfc1 r%u, f%u", rt, fs);
- t0 = newTemp(Ity_I32);
- t1 = newTemp(Ity_I32);
- t2 = newTemp(Ity_I32);
- t3 = newTemp(Ity_I32);
- t4 = newTemp(Ity_I32);
- t5 = newTemp(Ity_I32);
- t6 = newTemp(Ity_I32);
- assign(t0, getFCSR());
- if (fs == 0) {
- putIReg(rt, mkWidenFrom32(ty,
- IRExpr_Get(offsetof(VexGuestMIPS32State,
- guest_FIR),
- Ity_I32),
- False));
- } else if (fs == 25) {
- assign(t1, mkU32(0x000000FF));
- assign(t2, binop(Iop_Shr32, binop(Iop_And32, mkexpr(t0),
- mkU32(0xFE000000)), mkU8(25)));
- assign(t3, binop(Iop_Shr32, binop(Iop_And32, mkexpr(t0),
- mkU32(0x00800000)), mkU8(23)));
- putIReg(rt, mkWidenFrom32(ty, binop(Iop_Or32,
- binop(Iop_Or32, mkexpr(t1), mkexpr(t2)),
- mkexpr(t3)), False));
- } else if (fs == 26) {
- assign(t1, mkU32(0xFFFFF07C));
- assign(t2, binop(Iop_And32, mkexpr(t0),
- mkU32(0x0003F000)));
- assign(t3, binop(Iop_And32, mkexpr(t0),
- mkU32(0x0000007C)));
- putIReg(rt, mkWidenFrom32(ty, binop(Iop_Or32,
- binop(Iop_Or32, mkexpr(t1), mkexpr(t2)),
- mkexpr(t3)), False));
- } else if (fs == 28) {
- assign(t1, mkU32(0x00000F87));
- assign(t2, binop(Iop_And32, mkexpr(t0),
- mkU32(0x00000F83)));
- assign(t3, binop(Iop_Shr32, binop(Iop_And32, mkexpr(t0),
- mkU32(0x01000000)), mkU8(22)));
- putIReg(rt, mkWidenFrom32(ty, binop(Iop_Or32,
- binop(Iop_Or32, mkexpr(t1), mkexpr(t2)),
- mkexpr(t3)), False));
- } else if (fs == 31) {
- putIReg(rt, mkWidenFrom32(ty, getFCSR(), False));
+ break;
+ }
+
+ default: {
+ if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
+ UInt retVal = disDSPInstr_MIPS_WRK ( cins );
+
+ if (0 != retVal ) {
+ return -2;
}
+
break;
- default:
- goto decode_failure;
+ } else {
+ return -2;
}
- break;
- case 0x21: /* CVT.D */
- switch (fmt) {
- case 0x10: /* S */
- DIP("cvt.d.s f%u, f%u", fd, fs);
- calculateFCSR(fs, 0, CVTDS, True, 1);
- if (fp_mode64) {
- t0 = newTemp(Ity_I64);
- t1 = newTemp(Ity_I32);
- t3 = newTemp(Ity_F32);
- t4 = newTemp(Ity_F32);
- /* get lo half of FPR */
- assign(t0, unop(Iop_ReinterpF64asI64, getFReg(fs)));
+ break;
+ }
+ }
- assign(t1, unop(Iop_64to32, mkexpr(t0)));
+ break;
+ }
- assign(t3, unop(Iop_ReinterpI32asF32, mkexpr(t1)));
+ case 0x18: /* ADDUH.QB/MUL.PH */
+ case 0x31: { /* APPEND */
+ if (VEX_MIPS_PROC_DSP2(archinfo->hwcaps)) {
+ UInt retVal = disDSPInstr_MIPS_WRK ( cins );
- putFReg(fd, unop(Iop_F32toF64, mkexpr(t3)));
- } else
- putDReg(fd, unop(Iop_F32toF64, getFReg(fs)));
- break;
+ if (0 != retVal ) {
+ return -2;
+ }
- case 0x14:
- DIP("cvt.d.w %u, %u", fd, fs);
- calculateFCSR(fs, 0, CVTDW, True, 1);
- if (fp_mode64) {
- t0 = newTemp(Ity_I64);
- t1 = newTemp(Ity_I32);
- t3 = newTemp(Ity_F32);
- t4 = newTemp(Ity_F32);
- /* get lo half of FPR */
- assign(t0, unop(Iop_ReinterpF64asI64, getFReg(fs)));
+ break;
+ } else {
+ return -2;
+ }
+ }
- assign(t1, unop(Iop_64to32, mkexpr(t0)));
- putDReg(fd,unop(Iop_I32StoF64, mkexpr(t1)));
- break;
- } else {
- t0 = newTemp(Ity_I32);
- assign(t0, unop(Iop_ReinterpF32asI32, getFReg(fs)));
- putDReg(fd, unop(Iop_I32StoF64, mkexpr(t0)));
- break;
- }
+ case 0x35: { /* PREF r6*/
+ DIP("pref");
+ break;
+ }
- case 0x15: { /* L */
- if (fp_mode64) {
- DIP("cvt.d.l %u, %u", fd, fs);
- calculateFCSR(fs, 0, CVTDL, False, 1);
- t0 = newTemp(Ity_I64);
- assign(t0, unop(Iop_ReinterpF64asI64, getFReg(fs)));
+ case 0x36: { /* LL */
+ imm = extend_s_9to16((instr_index >> 7) & 0x1ff);
+ DIP("ll r%u, %u(r%u)", rt, imm, rs);
+ LOAD_STORE_PATTERN;
+ t2 = newTemp(ty);
+ assign(t2, mkWidenFrom32(ty, load(Ity_I32, mkexpr(t1)), True));
+ putLLaddr(mkexpr(t1));
+ putLLdata(mkexpr(t2));
+ putIReg(rt, mkexpr(t2));
+ break;
+ }
- putFReg(fd, binop(Iop_I64StoF64,
- get_IR_roundingmode(), mkexpr(t0)));
- break;
- } else
- goto decode_failure;
- }
- default:
- goto decode_failure;
- }
- break; /* CVT.D */
-
- case 0x20: /* cvt.s */
- switch (fmt) {
- case 0x14: /* W */
- DIP("cvt.s.w %u, %u", fd, fs);
- calculateFCSR(fs, 0, CVTSW, True, 1);
- if (fp_mode64) {
- t0 = newTemp(Ity_I64);
- t1 = newTemp(Ity_I32);
- t3 = newTemp(Ity_F32);
- t4 = newTemp(Ity_F32);
- /* get lo half of FPR */
- assign(t0, unop(Iop_ReinterpF64asI64, getFReg(fs)));
-
- assign(t1, unop(Iop_64to32, mkexpr(t0)));
- putFReg(fd, mkWidenFromF32(tyF, binop(Iop_I32StoF32,
- get_IR_roundingmode(), mkexpr(t1))));
- } else {
- t0 = newTemp(Ity_I32);
- assign(t0, unop(Iop_ReinterpF32asI32, getFReg(fs)));
- putFReg(fd, binop(Iop_I32StoF32, get_IR_roundingmode(),
- mkexpr(t0)));
- }
- break;
+ case 0x26: { /* SC */
+ imm = extend_s_9to16((instr_index >> 7) & 0x1ff);
+ DIP("sc r%u, %u(r%u)", rt, imm, rs);
+ LOAD_STORE_PATTERN;
- case 0x11: /* D */
- DIP("cvt.s.d %u, %u", fd, fs);
- calculateFCSR(fs, 0, CVTSD, False, 1);
- t0 = newTemp(Ity_F32);
- assign(t0, binop(Iop_F64toF32, get_IR_roundingmode(),
- getDReg(fs)));
- putFReg(fd, mkWidenFromF32(tyF, mkexpr(t0)));
- break;
+ t2 = newTemp(Ity_I1);
+ t3 = newTemp(Ity_I32);
+ assign(t2, binop(mode64 ? Iop_CmpNE64 : Iop_CmpNE32,
+ mkexpr(t1), getLLaddr()));
+ assign(t3, mkNarrowTo32(ty, getIReg(rt)));
+ putLLaddr(LLADDR_INVALID);
+ putIReg(rt, getIReg(0));
- case 0x15: /* L */
- DIP("cvt.s.l %u, %u", fd, fs);
- if (fp_mode64) {
- calculateFCSR(fs, 0, CVTSL, False, 1);
- t0 = newTemp(Ity_I64);
- assign(t0, unop(Iop_ReinterpF64asI64, getFReg(fs)));
+ mips_next_insn_if(mkexpr(t2));
- putFReg(fd, mkWidenFromF32(tyF, binop(Iop_I64StoF32,
- get_IR_roundingmode(), mkexpr(t0))));
- } else {
- ILLEGAL_INSTRUCTON;
- }
- break;
+ t4 = newTemp(Ity_I32);
+ t5 = newTemp(Ity_I32);
- default:
- goto decode_failure;
- }
- break; /* cvt.s */
-
- case 0x24: /* cvt.w */
- switch (fmt) {
- case 0x10: /* S */
- DIP("cvt.w.s %u, %u", fd, fs);
- calculateFCSR(fs, 0, CVTWS, True, 1);
- putFReg(fd,
- mkWidenFromF32(tyF,
- unop(Iop_ReinterpI32asF32,
- binop(Iop_F32toI32S,
- get_IR_roundingmode(),
- getLoFromF64(tyF,
- getFReg(fs))))));
- break;
+ assign(t5, mkNarrowTo32(ty, getLLdata()));
- case 0x11:
- DIP("cvt.w.d %u, %u", fd, fs);
- calculateFCSR(fs, 0, CVTWD, False, 1);
- t0 = newTemp(Ity_I32);
- t1 = newTemp(Ity_F32);
- assign(t0, binop(Iop_F64toI32S, get_IR_roundingmode(),
- getDReg(fs)));
- assign(t1, unop(Iop_ReinterpI32asF32, mkexpr(t0)));
- putFReg(fd, mkWidenFromF32(tyF, mkexpr(t1)));
- break;
+ stmt(IRStmt_CAS(mkIRCAS(IRTemp_INVALID, t4, /* old_mem */
+ MIPS_IEND, mkexpr(t1), /* addr */
+ NULL, mkexpr(t5), /* expected value */
+ NULL, mkexpr(t3) /* new value */)));
- default:
- goto decode_failure;
+ putIReg(rt, unop(mode64 ? Iop_1Uto64 : Iop_1Uto32,
+ binop(Iop_CmpEQ32, mkexpr(t4), mkexpr(t5))));
+ break;
+ }
- }
- break;
+ case 0x37: { /* LLD */
+ imm = extend_s_9to16((instr_index >> 7) & 0x1ff);
+ DIP("lld r%u, %u(r%u)", rt, imm, rs);
+ LOAD_STORE_PATTERN;
- case 0x25: /* cvt.l */
- switch (fmt) {
- case 0x10: /* S */
- DIP("cvt.l.s %u, %u", fd, fs);
- if (fp_mode64) {
- calculateFCSR(fs, 0, CVTLS, True, 1);
- t0 = newTemp(Ity_I64);
+ t2 = newTemp(Ity_I64);
+ assign(t2, load(Ity_I64, mkexpr(t1)));
+ putLLaddr(mkexpr(t1));
+ putLLdata(mkexpr(t2));
+ putIReg(rt, mkexpr(t2));
+ break;
+ }
- assign(t0, binop(Iop_F32toI64S, get_IR_roundingmode(),
- getLoFromF64(tyF, getFReg(fs))));
+ case 0x27: { /* SCD */
+ imm = extend_s_9to16((instr_index >> 7) & 0x1ff);
+ DIP("sdc r%u, %u(r%u)", rt, imm, rs);
+ LOAD_STORE_PATTERN;
- putDReg(fd, unop(Iop_ReinterpI64asF64, mkexpr(t0)));
- } else {
- ILLEGAL_INSTRUCTON;
- }
- break;
+ t2 = newTemp(Ity_I1);
+ t3 = newTemp(Ity_I64);
+ assign(t2, binop(Iop_CmpNE64, mkexpr(t1), getLLaddr()));
+ assign(t3, getIReg(rt));
+ putLLaddr(LLADDR_INVALID);
+ putIReg(rt, getIReg(0));
- case 0x11: { /* D */
- DIP("cvt.l.d %u, %u", fd, fs);
- if (fp_mode64) {
- calculateFCSR(fs, 0, CVTLD, False, 1);
- putDReg(fd, unop(Iop_ReinterpI64asF64,
- binop(Iop_F64toI64S,
- get_IR_roundingmode(),
- getDReg(fs))));
- } else {
- ILLEGAL_INSTRUCTON;
- }
- break;
- }
+ mips_next_insn_if(mkexpr(t2));
- default:
- goto decode_failure;
- }
- break;
+ t4 = newTemp(Ity_I64);
+ t5 = newTemp(Ity_I64);
- case 0x0B: /* FLOOR.L.fmt */
- switch (fmt) {
- case 0x10: /* S */
- DIP("floor.l.s %u, %u", fd, fs);
- if (fp_mode64) {
- calculateFCSR(fs, 0, FLOORLS, True, 1);
- t0 = newTemp(Ity_I64);
+ assign(t5, getLLdata());
- assign(t0, binop(Iop_F32toI64S, mkU32(0x1),
- getLoFromF64(tyF, getFReg(fs))));
+ stmt(IRStmt_CAS(mkIRCAS(IRTemp_INVALID, t4, /* old_mem */
+ MIPS_IEND, mkexpr(t1), /* addr */
+ NULL, mkexpr(t5), /* expected value */
+ NULL, mkexpr(t3) /* new value */)));
- putDReg(fd, unop(Iop_ReinterpI64asF64, mkexpr(t0)));
- } else {
- ILLEGAL_INSTRUCTON;
- }
- break;
+ putIReg(rt, unop(Iop_1Uto64,
+ binop(Iop_CmpEQ64, mkexpr(t4), mkexpr(t5))));
+ break;
+ }
- case 0x11: /* D */
- DIP("floor.l.d %u, %u", fd, fs);
- if (fp_mode64) {
- calculateFCSR(fs, 0, FLOORLD, False, 1);
- putDReg(fd, unop(Iop_ReinterpI64asF64,
- binop(Iop_F64toI64S,
- mkU32(0x01),
- getDReg(fs))));
- } else {
- ILLEGAL_INSTRUCTON;
- }
- break;
- default:
- goto decode_failure;
- }
- break;
+ default:
+ return -1;
+ }
- case 0x0C: /* ROUND.W.fmt */
- switch (fmt) {
- case 0x10: /* S */
- DIP("round.w.s f%u, f%u", fd, fs);
- calculateFCSR(fs, 0, ROUNDWS, True, 1);
- putFReg(fd,
- mkWidenFromF32(tyF,
- unop(Iop_ReinterpI32asF32,
- binop(Iop_F32toI32S,
- mkU32(0x0),
- getLoFromF64(tyF,
- getFReg(fs))))));
- break;
+ return 0;
+}
- case 0x11: /* D */
- DIP("round.w.d f%u, f%u", fd, fs);
- calculateFCSR(fs, 0, ROUNDWD, False, 1);
- if (fp_mode64) {
- t0 = newTemp(Ity_I32);
- assign(t0, binop(Iop_F64toI32S, mkU32(0x0),
- getDReg(fs)));
- putFReg(fd, mkWidenFromF32(tyF,
- unop(Iop_ReinterpI32asF32, mkexpr(t0))));
- } else {
- t0 = newTemp(Ity_I32);
+static UInt disInstr_MIPS_WRK_00(UInt cins, const VexArchInfo* archinfo,
+ const VexAbiInfo* abiinfo, DisResult* dres,
+ IRStmt** bstmt, IRExpr** lastn,
+ Bool(*resteerOkFn) (/*opaque */void *,
+ Addr),
+ void* callback_opaque)
+{
+ IRTemp t0;
+ UInt opcode, rs, rt, trap_code, imm, instr_index, p;
+ /* Additional variables for instruction fields in DSP ASE insructions */
- assign(t0, binop(Iop_F64toI32S, mkU32(0x0),
- getDReg(fs)));
+ opcode = get_opcode(cins);
+ imm = get_imm(cins);
+ rs = get_rs(cins);
+ rt = get_rt(cins);
+ instr_index = get_instr_index(cins);
+ trap_code = get_code(cins);
+ IRType ty = mode64 ? Ity_I64 : Ity_I32;
- putFReg(fd, unop(Iop_ReinterpI32asF32, mkexpr(t0)));
- }
- break;
- default:
- goto decode_failure;
+ switch (opcode & 0x0F) {
+ case 0x00: /* Special */
+ return disInstr_MIPS_WRK_Special(cins, archinfo, abiinfo, dres, bstmt, lastn,
+ resteerOkFn, callback_opaque);
- }
- break; /* ROUND.W.fmt */
+ case 0x01: /* Regimm */
+ switch (rt) {
+ case 0x00: /* BLTZ */
+ DIP("bltz r%u, %u", rs, imm);
- case 0x0F: /* FLOOR.W.fmt */
- switch (fmt) {
- case 0x10: /* S */
- DIP("floor.w.s f%u, f%u", fd, fs);
- calculateFCSR(fs, 0, FLOORWS, True, 1);
- putFReg(fd,
- mkWidenFromF32(tyF,
- unop(Iop_ReinterpI32asF32,
- binop(Iop_F32toI32S,
- mkU32(0x1),
- getLoFromF64(tyF,
- getFReg(fs))))));
- break;
+ if (mode64) {
+ if (!dis_instr_branch(cins, dres, resteerOkFn,
+ callback_opaque, bstmt))
+ return -1;
+ } else
+ dis_branch(False, binop(Iop_CmpEQ32, binop(Iop_And32, getIReg(rs),
+ mkU32(0x80000000)), mkU32(0x80000000)), imm, bstmt);
- case 0x11: /* D */
- DIP("floor.w.d f%u, f%u", fd, fs);
- calculateFCSR(fs, 0, FLOORWD, False, 1);
- if (fp_mode64) {
- t0 = newTemp(Ity_I32);
- assign(t0, binop(Iop_F64toI32S, mkU32(0x1),
- getDReg(fs)));
- putFReg(fd, mkWidenFromF32(tyF,
- unop(Iop_ReinterpI32asF32, mkexpr(t0))));
- break;
- } else {
- t0 = newTemp(Ity_I32);
+ break;
- assign(t0, binop(Iop_F64toI32S, mkU32(0x1),
- getDReg(fs)));
+ case 0x01: /* BGEZ */
+ DIP("bgez r%u, %u", rs, imm);
- putFReg(fd, unop(Iop_ReinterpI32asF32, mkexpr(t0)));
- break;
- }
- default:
- goto decode_failure;
+ if (mode64) {
+ if (!dis_instr_branch(cins, dres, resteerOkFn,
+ callback_opaque, bstmt))
+ return -1;
+ } else
+ dis_branch(False, binop(Iop_CmpEQ32, binop(Iop_And32, getIReg(rs),
+ mkU32(0x80000000)), mkU32(0x0)), imm, bstmt);
- }
- break; /* FLOOR.W.fmt */
+ break;
- case 0x0D: /* TRUNC.W */
- switch (fmt) {
- case 0x10: /* S */
- DIP("trunc.w.s %u, %u", fd, fs);
- calculateFCSR(fs, 0, TRUNCWS, True, 1);
- putFReg(fd,
- mkWidenFromF32(tyF,
- unop(Iop_ReinterpI32asF32,
- binop(Iop_F32toI32S,
- mkU32(0x3),
- getLoFromF64(tyF,
- getFReg(fs))))));
- break;
- case 0x11: /* D */
- DIP("trunc.w.d %u, %u", fd, fs);
- calculateFCSR(fs, 0, TRUNCWD, False, 1);
- if (fp_mode64) {
- t0 = newTemp(Ity_I32);
+ case 0x02: /* BLTZL */
+ DIP("bltzl r%u, %u", rs, imm);
+ *lastn = dis_branch_likely(binop(mode64 ? Iop_CmpNE64 : Iop_CmpNE32,
+ binop(mode64 ? Iop_And64 : Iop_And32, getIReg(rs),
+ mode64 ? mkU64(0x8000000000000000ULL) : mkU32(0x80000000)),
+ mode64 ? mkU64(0x8000000000000000ULL) : mkU32(0x80000000)),
+ imm);
+ break;
- assign(t0, binop(Iop_F64toI32S, mkU32(0x3),
- getFReg(fs)));
+ case 0x03: /* BGEZL */
+ DIP("bgezl r%u, %u", rs, imm);
+ *lastn = dis_branch_likely(binop(mode64 ? Iop_CmpNE64 : Iop_CmpNE32,
+ binop(mode64 ? Iop_And64 : Iop_And32, getIReg(rs),
+ mode64 ? mkU64(0x8000000000000000ULL) : mkU32(0x80000000)),
+ mode64 ? mkU64(0x0) : mkU32(0x0)), imm);
+ break;
- putFReg(fd, mkWidenFromF32(tyF,
- unop(Iop_ReinterpI32asF32, mkexpr(t0))));
- } else {
- t0 = newTemp(Ity_I32);
+ case 0x06: { /* DAHI */
+ if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+ DIP("dahi r%u, %x", rs, imm);
+ putIReg(rs, binop(Iop_Add64,
+ getIReg(rs), mkU64(extend_s_16to64 (imm) << 32)));
+ } else {
+ ILLEGAL_INSTRUCTON
+ }
- assign(t0, binop(Iop_F64toI32S, mkU32(0x3),
- getDReg(fs)));
+ break;
+ }
- putFReg(fd, unop(Iop_ReinterpI32asF32, mkexpr(t0)));
- }
- break;
- default:
- goto decode_failure;
+ case 0x08: /* TGEI */
+ DIP("tgei r%u, %u %u", rs, imm, trap_code);
+ if (mode64) {
+ stmt (IRStmt_Exit (unop (Iop_Not1,
+ binop (Iop_CmpLT64S,
+ getIReg (rs),
+ mkU64 (extend_s_16to64 (imm)))),
+ Ijk_SigTRAP,
+ IRConst_U64(guest_PC_curr_instr + 4),
+ OFFB_PC));
+ } else {
+ stmt (IRStmt_Exit (unop (Iop_Not1,
+ binop (Iop_CmpLT32S,
+ getIReg (rs),
+ mkU32 (extend_s_16to32 (imm)))),
+ Ijk_SigTRAP,
+ IRConst_U32(guest_PC_curr_instr + 4),
+ OFFB_PC));
}
- break;
- case 0x0E: /* CEIL.W.fmt */
- switch (fmt) {
- case 0x10: /* S */
- DIP("ceil.w.s %u, %u", fd, fs);
- calculateFCSR(fs, 0, CEILWS, True, 1);
- putFReg(fd,
- mkWidenFromF32(tyF,
- unop(Iop_ReinterpI32asF32,
- binop(Iop_F32toI32S,
- mkU32(0x2),
- getLoFromF64(tyF,
- getFReg(fs))))));
- break;
-
- case 0x11: /* D */
- DIP("ceil.w.d %u, %u", fd, fs);
- calculateFCSR(fs, 0, CEILWD, False, 1);
- if (!fp_mode64) {
- t0 = newTemp(Ity_I32);
- assign(t0, binop(Iop_F64toI32S, mkU32(0x2),
- getDReg(fs)));
- putFReg(fd, unop(Iop_ReinterpI32asF32, mkexpr(t0)));
- } else {
- t0 = newTemp(Ity_I32);
- assign(t0, binop(Iop_F64toI32S, mkU32(0x2),
- getDReg(fs)));
- putFReg(fd, mkWidenFromF32(tyF,
- unop(Iop_ReinterpI32asF32, mkexpr(t0))));
- }
- break;
+ break;
- default:
- goto decode_failure;
+ case 0x09: { /* TGEIU */
+ DIP("tgeiu r%u, %u %u", rs, imm, trap_code);
+ if (mode64) {
+ stmt (IRStmt_Exit (unop (Iop_Not1,
+ binop (Iop_CmpLT64U,
+ getIReg (rs),
+ mkU64 (extend_s_16to64 (imm)))),
+ Ijk_SigTRAP,
+ IRConst_U64(guest_PC_curr_instr + 4),
+ OFFB_PC));
+ } else {
+ stmt (IRStmt_Exit (unop (Iop_Not1,
+ binop (Iop_CmpLT32U,
+ getIReg (rs),
+ mkU32 (extend_s_16to32 (imm)))),
+ Ijk_SigTRAP,
+ IRConst_U32(guest_PC_curr_instr + 4),
+ OFFB_PC));
}
- break;
- case 0x0A: /* CEIL.L.fmt */
- switch (fmt) {
- case 0x10: /* S */
- DIP("ceil.l.s %u, %u", fd, fs);
- if (fp_mode64) {
- calculateFCSR(fs, 0, CEILLS, True, 1);
- t0 = newTemp(Ity_I64);
+ break;
+ }
- assign(t0, binop(Iop_F32toI64S, mkU32(0x2),
- getLoFromF64(tyF, getFReg(fs))));
+ case 0x0A: { /* TLTI */
+ DIP("tlti r%u, %u %u", rs, imm, trap_code);
- putFReg(fd, unop(Iop_ReinterpI64asF64, mkexpr(t0)));
- } else {
- ILLEGAL_INSTRUCTON;
- }
- break;
+ if (mode64) {
+ stmt (IRStmt_Exit (binop (Iop_CmpLT64S, getIReg (rs),
+ mkU64 (extend_s_16to64 (imm))),
+ Ijk_SigTRAP,
+ IRConst_U64(guest_PC_curr_instr + 4),
+ OFFB_PC));
+ } else {
+ stmt (IRStmt_Exit (binop (Iop_CmpLT32S, getIReg (rs),
+ mkU32 (extend_s_16to32 (imm))),
+ Ijk_SigTRAP,
+ IRConst_U32(guest_PC_curr_instr + 4),
+ OFFB_PC));
+ }
- case 0x11: /* D */
- DIP("ceil.l.d %u, %u", fd, fs);
- if (fp_mode64) {
- calculateFCSR(fs, 0, CEILLD, False, 1);
- putDReg(fd, unop(Iop_ReinterpI64asF64,
- binop(Iop_F64toI64S,
- mkU32(0x2),
- getDReg(fs))));
- } else {
- ILLEGAL_INSTRUCTON;
- }
- break;
+ break;
+ }
- default:
- goto decode_failure;
+ case 0x0B: { /* TLTIU */
+ DIP("tltiu r%u, %u %u", rs, imm, trap_code);
+ if (mode64) {
+ stmt (IRStmt_Exit (binop (Iop_CmpLT64U, getIReg (rs),
+ mkU64 (extend_s_16to64 (imm))),
+ Ijk_SigTRAP,
+ IRConst_U64(guest_PC_curr_instr + 4),
+ OFFB_PC));
+ } else {
+ stmt (IRStmt_Exit (binop (Iop_CmpLT32U, getIReg (rs),
+ mkU32 (extend_s_16to32 (imm))),
+ Ijk_SigTRAP,
+ IRConst_U32(guest_PC_curr_instr + 4),
+ OFFB_PC));
}
+
break;
+ }
- case 0x16: /* RSQRT.fmt */
- switch (fmt) {
- case 0x10: { /* S */
- DIP("rsqrt.s %u, %u", fd, fs);
- IRExpr *rm = get_IR_roundingmode();
- putFReg(fd, mkWidenFromF32(tyF, triop(Iop_DivF32, rm,
- unop(Iop_ReinterpI32asF32, mkU32(ONE_SINGLE)),
- binop(Iop_SqrtF32, rm, getLoFromF64(tyF,
- getFReg(fs))))));
- break;
- }
- case 0x11: { /* D */
- DIP("rsqrt.d %u, %u", fd, fs);
- IRExpr *rm = get_IR_roundingmode();
- putDReg(fd, triop(Iop_DivF64, rm,
- unop(Iop_ReinterpI64asF64,
- mkU64(ONE_DOUBLE)),
- binop(Iop_SqrtF64, rm, getDReg(fs))));
- break;
- }
- default:
- goto decode_failure;
+ case 0x0C: { /* TEQI */
+ DIP("teqi r%u, %u %u", rs, imm, trap_code);
+ if (mode64) {
+ stmt (IRStmt_Exit (binop (Iop_CmpEQ64, getIReg (rs),
+ mkU64 (extend_s_16to64 (imm))),
+ Ijk_SigTRAP,
+ IRConst_U64(guest_PC_curr_instr + 4),
+ OFFB_PC));
+ } else {
+ stmt (IRStmt_Exit (binop (Iop_CmpEQ32, getIReg (rs),
+ mkU32 (extend_s_16to32 (imm))),
+ Ijk_SigTRAP,
+ IRConst_U32(guest_PC_curr_instr + 4),
+ OFFB_PC));
}
- break;
- case 0x18: /* MADDF.fmt */
- if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
- switch (fmt) {
- case 0x11: { /* D */
- DIP("maddf.d f%u, f%u, f%u", fd, fs, ft);
- IRExpr *rm = get_IR_roundingmode();
- putDReg(fd, qop(Iop_MAddF64, rm, getDReg(fs), getDReg(ft),
- getDReg(fd)));
- break;
- }
+ break;
+ }
- case 0x10: { /* S */
- DIP("maddf.s f%u, f%u, f%u", fd, fs, ft);
- IRExpr *rm = get_IR_roundingmode();
- t1 = newTemp(Ity_F32);
- assign(t1, qop(Iop_MAddF32, rm,
- getLoFromF64(tyF, getFReg(fs)),
- getLoFromF64(tyF, getFReg(ft)),
- getLoFromF64(tyF, getFReg(fd))));
- putFReg(fd, mkWidenFromF32(tyF, mkexpr(t1)));
- break;
- }
+ case 0x0E: { /* TNEI */
+ DIP("tnei r%u, %u %u", rs, imm, trap_code);
- default:
- goto decode_failure;
- }
+ if (mode64) {
+ stmt (IRStmt_Exit (binop (Iop_CmpNE64, getIReg (rs),
+ mkU64 (extend_s_16to64 (imm))),
+ Ijk_SigTRAP,
+ IRConst_U64(guest_PC_curr_instr + 4),
+ OFFB_PC));
} else {
- ILLEGAL_INSTRUCTON;
+ stmt (IRStmt_Exit (binop (Iop_CmpNE32, getIReg (rs),
+ mkU32 (extend_s_16to32 (imm))),
+ Ijk_SigTRAP,
+ IRConst_U32(guest_PC_curr_instr + 4),
+ OFFB_PC));
}
break;
+ }
- case 0x19: /* MSUBF.fmt */
- if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
- switch (fmt) {
- case 0x11: { /* D */
- DIP("msubf.d f%u, f%u, f%u", fd, fs, ft);
- IRExpr *rm = get_IR_roundingmode();
- putDReg(fd, qop(Iop_MSubF64, rm, getDReg(fs),
- getDReg(ft), getDReg(fd)));
- break;
- }
+ case 0x10: /* BLTZAL */
+ DIP("bltzal r%u, %u", rs, imm);
- case 0x10: { /* S */
- DIP("msubf.s f%u, f%u, f%u", fd, fs, ft);
- IRExpr *rm = get_IR_roundingmode();
- t1 = newTemp(Ity_F32);
- assign(t1, qop(Iop_MSubF32, rm,
- getLoFromF64(tyF, getFReg(fs)),
- getLoFromF64(tyF, getFReg(ft)),
- getLoFromF64(tyF, getFReg(fd))));
- putFReg(fd, mkWidenFromF32(tyF, mkexpr(t1)));
- break;
- }
+ if (mode64) {
+ if (!dis_instr_branch(cins, dres, resteerOkFn,
+ callback_opaque, bstmt))
+ return -1;
+ } else
+ dis_branch(True, binop(Iop_CmpEQ32, binop(Iop_And32, getIReg(rs),
+ mkU32(0x80000000)), mkU32(0x80000000)), imm, bstmt);
- default:
- goto decode_failure;
- }
- } else {
- ILLEGAL_INSTRUCTON;
- }
+ break;
+
+ case 0x11: /* BGEZAL */
+ DIP("bgezal r%u, %u", rs, imm);
+
+ if (mode64) {
+ if (!dis_instr_branch(cins, dres, resteerOkFn,
+ callback_opaque, bstmt))
+ return -1;
+ } else
+ dis_branch(True, binop(Iop_CmpEQ32, binop(Iop_And32, getIReg(rs),
+ mkU32(0x80000000)), mkU32(0x0)), imm, bstmt);
break;
- case 0x1E: /* MAX.fmt */
- if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
- switch (fmt) {
- case 0x11: { /* D */
- DIP("max.d f%u, f%u, f%u", fd, fs, ft);
- calculateFCSR(fs, ft, MAXD, False, 2);
- putDReg(fd, binop(Iop_MaxNumF64, getDReg(fs), getDReg(ft)));
- break;
- }
+ case 0x12: /* BLTZALL */
+ DIP("bltzall r%u, %u", rs, imm);
+ putIReg(31, mode64 ? mkU64(guest_PC_curr_instr + 8) :
+ mkU32(guest_PC_curr_instr + 8));
+ *lastn = dis_branch_likely(binop(mode64 ? Iop_CmpNE64 : Iop_CmpNE32,
+ binop(mode64 ? Iop_And64 : Iop_And32, getIReg(rs),
+ mode64 ? mkU64(0x8000000000000000ULL) : mkU32(0x80000000)),
+ mode64 ? mkU64(0x8000000000000000ULL) : mkU32(0x80000000)),
+ imm);
+ break;
- case 0x10: { /* S */
- DIP("max.s f%u, f%u, f%u", fd, fs, ft);
- calculateFCSR(fs, ft, MAXS, True, 2);
- putFReg(fd, mkWidenFromF32(tyF, binop(Iop_MaxNumF32,
- getLoFromF64(Ity_F64,
- getFReg(fs)),
- getLoFromF64(Ity_F64,
- getFReg(ft)))));
- break;
- }
+ case 0x13: /* BGEZALL */
+ DIP("bgezall r%u, %u", rs, imm);
- default:
- goto decode_failure;
- }
+ if (mode64) {
+ putIReg(31, mkU64(guest_PC_curr_instr + 8));
+ *lastn = dis_branch_likely(binop(Iop_CmpNE64,
+ binop(Iop_And64,
+ getIReg(rs),
+ mkU64(0x8000000000000000ULL)),
+ mkU64(0x0)),
+ imm);
} else {
- ILLEGAL_INSTRUCTON;
+ putIReg(31, mkU32(guest_PC_curr_instr + 8));
+ *lastn = dis_branch_likely(binop(Iop_CmpNE32, binop(Iop_And32,
+ getIReg(rs), mkU32(0x80000000)),
+ mkU32(0x0)), imm);
}
break;
- case 0x1C: /* MIN.fmt */
- if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
- switch (fmt) {
- case 0x11: { /* D */
- DIP("min.d f%u, f%u, f%u", fd, fs, ft);
- calculateFCSR(fs, ft, MIND, False, 2);
- putDReg(fd, binop(Iop_MinNumF64, getDReg(fs), getDReg(ft)));
- break;
- }
+ case 0x1C: { /* BPOSGE32 */
+ DIP("bposge32 %u", imm);
+ vassert(!mode64);
+ t0 = newTemp(Ity_I32);
+ /* Get pos field from DSPControl register. */
+ assign(t0, binop(Iop_And32, getDSPControl(), mkU32(0x3f)));
+ dis_branch(False, unop(Iop_Not1, binop(Iop_CmpLT32U, mkexpr(t0),
+ mkU32(32))), imm, bstmt);
+ break;
+ }
- case 0x10: { /* S */
- DIP("min.s f%u, f%u, f%u", fd, fs, ft);
- calculateFCSR(fs, ft, MINS, True, 2);
- putFReg(fd, mkWidenFromF32(tyF, binop(Iop_MinNumF32,
- getLoFromF64(Ity_F64,
- getFReg(fs)),
- getLoFromF64(Ity_F64,
- getFReg(ft)))));
- break;
- }
- default:
- goto decode_failure;
- }
+ case 0x1E: { /* DATI */
+ if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+ DIP("dati r%u, %x", rs, imm);
+ putIReg(rs, binop(Iop_Add64,
+ getIReg(rs), mkU64((long long)imm << 48)));
} else {
- ILLEGAL_INSTRUCTON;
+ ILLEGAL_INSTRUCTON
}
break;
+ }
- case 0x1F: /* MAXA.fmt */
- if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
- switch (fmt) {
- case 0x11: { /* D */
- DIP("maxa.d f%u, f%u, f%u", fd, fs, ft);
- calculateFCSR(fs, ft, MAXAD, False, 2);
- t1 = newTemp(Ity_F64);
- t2 = newTemp(Ity_F64);
- t3 = newTemp(Ity_F64);
- t4 = newTemp(Ity_I1);
- assign(t1, unop(Iop_AbsF64, getFReg(fs)));
- assign(t2, unop(Iop_AbsF64, getFReg(ft)));
- assign(t3, binop(Iop_MaxNumF64, mkexpr(t1), mkexpr(t2)));
- assign(t4, binop(Iop_CmpEQ32,
- binop(Iop_CmpF64, mkexpr(t3), mkexpr(t1)),
- mkU32(0x40)));
- putFReg(fd, IRExpr_ITE(mkexpr(t4),
- getFReg(fs), getFReg(ft)));
- break;
- }
+ case 0x1F: /* SYNCI */
+ /* Just ignore it */
+ break;
- case 0x10: { /* S */
- DIP("maxa.s f%u, f%u, f%u", fd, fs, ft);
- calculateFCSR(fs, ft, MAXAS, True, 2);
- t1 = newTemp(Ity_F32);
- t2 = newTemp(Ity_F32);
- t3 = newTemp(Ity_F32);
- t4 = newTemp(Ity_I1);
- assign(t1, unop(Iop_AbsF32, getLoFromF64(Ity_F64,
- getFReg(fs))));
- assign(t2, unop(Iop_AbsF32, getLoFromF64(Ity_F64,
- getFReg(ft))));
- assign(t3, binop(Iop_MaxNumF32, mkexpr(t1), mkexpr(t2)));
- assign(t4, binop(Iop_CmpEQ32,
- binop(Iop_CmpF32, mkexpr(t3), mkexpr(t1)),
- mkU32(0x40)));
- putFReg(fd, IRExpr_ITE(mkexpr(t4),
- getFReg(fs), getFReg(ft)));
- break;
- }
+ default:
+ return -1;
+ }
- default:
- goto decode_failure;
- }
- /* missing in documentation */
- } else {
- ILLEGAL_INSTRUCTON;
- }
- break;
+ break;
- case 0x1D: /* MINA.fmt */
- if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
- switch (fmt) {
- case 0x11: { /* D */
- DIP("mina.d f%u, f%u, f%u", fd, fs, ft);
- calculateFCSR(fs, ft, MINAD, False, 2);
- t1 = newTemp(Ity_F64);
- t2 = newTemp(Ity_F64);
- t3 = newTemp(Ity_F64);
- t4 = newTemp(Ity_I1);
- assign(t1, unop(Iop_AbsF64, getFReg(fs)));
- assign(t2, unop(Iop_AbsF64, getFReg(ft)));
- assign(t3, binop(Iop_MinNumF64, mkexpr(t1), mkexpr(t2)));
- assign(t4, binop(Iop_CmpEQ32,
- binop(Iop_CmpF64, mkexpr(t3), mkexpr(t1)),
- mkU32(0x40)));
- putFReg(fd, IRExpr_ITE(mkexpr(t4),
- getFReg(fs), getFReg(ft)));
- break;
- }
+ case 0x02: /* J */
+ DIP("j 0x%x", instr_index);
+ t0 = newTemp(ty);
- case 0x10: { /* S */
- DIP("mina.s f%u, f%u, f%u", fd, fs, ft);
- calculateFCSR(fs, ft, MINAS, True, 2);
- t1 = newTemp(Ity_F32);
- t2 = newTemp(Ity_F32);
- t3 = newTemp(Ity_F32);
- t4 = newTemp(Ity_I1);
- assign(t1, unop(Iop_AbsF32, getLoFromF64(Ity_F64,
- getFReg(fs))));
- assign(t2, unop(Iop_AbsF32, getLoFromF64(Ity_F64,
- getFReg(ft))));
- assign(t3, binop(Iop_MinNumF32, mkexpr(t1), mkexpr(t2)));
- assign(t4, binop(Iop_CmpEQ32,
- binop(Iop_CmpF32, mkexpr(t3), mkexpr(t1)),
- mkU32(0x40)));
- putFReg(fd, IRExpr_ITE(mkexpr(t4),
- getFReg(fs), getFReg(ft)));
- break;
- }
+ if (mode64)
+ assign(t0, mkU64((guest_PC_curr_instr & 0xFFFFFFFFF0000000ULL) |
+ (instr_index << 2)));
+ else
+ assign(t0, mkU32((guest_PC_curr_instr & 0xF0000000) |
+ (instr_index << 2)));
- default:
- goto decode_failure;
- }
- } else {
- ILLEGAL_INSTRUCTON;
- }
- break;
+ *lastn = mkexpr(t0);
+ break;
- case 0x1A: /* RINT.fmt */
- if (ft == 0) {
- switch (fmt) {
- case 0x11: { /* D */
- DIP("rint.d f%u, f%u", fd, fs);
- calculateFCSR(fs, 0, RINTS, True, 1);
- IRExpr *rm = get_IR_roundingmode();
- putDReg(fd, binop(Iop_RoundF64toInt, rm, getDReg(fs)));
- break;
- }
+ case 0x03: /* JAL */
+ DIP("jal 0x%x", instr_index);
- case 0x10: { /* S */
- DIP("rint.s f%u, f%u", fd, fs);
- calculateFCSR(fs, 0, RINTD, True, 1);
- IRExpr *rm = get_IR_roundingmode();
- putFReg(fd,
- mkWidenFromF32(tyF,
- binop(Iop_RoundF32toInt, rm,
- getLoFromF64(tyF,
- getFReg(fs)))));
- break;
- }
+ if (mode64) {
+ putIReg(31, mkU64(guest_PC_curr_instr + 8));
+ t0 = newTemp(ty);
+ assign(t0, mkU64((guest_PC_curr_instr & 0xFFFFFFFFF0000000ULL) |
+ (instr_index << 2)));
+ } else {
+ putIReg(31, mkU32(guest_PC_curr_instr + 8));
+ t0 = newTemp(ty);
+ assign(t0, mkU32((guest_PC_curr_instr & 0xF0000000) |
+ (instr_index << 2)));
+ }
- default:
- goto decode_failure;
- }
+ *lastn = mkexpr(t0);
+ break;
- }
- break;
+ case 0x04: /* BEQ */
+ DIP("beq r%u, r%u, %u", rs, rt, imm);
- case 0x10: /* SEL.fmt */
- switch (fmt) {
- case 0x11: { /* D */
- if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
- DIP("sel.d f%u, f%u, f%u", fd, fs, ft);
- t1 = newTemp(Ity_I1);
- if (mode64) {
- assign(t1,binop(Iop_CmpNE64,
- binop(Iop_And64,
- unop(Iop_ReinterpF64asI64,
- getDReg(fd)),
- mkU64(1)),
- mkU64(0)));
- } else {
- assign(t1,binop(Iop_CmpNE32,
- binop(Iop_And32,
- unop(Iop_64to32,
- unop(Iop_ReinterpF64asI64,
- getDReg(fd))),
- mkU32(1)),
- mkU32(0)));
- }
- putDReg(fd, IRExpr_ITE(mkexpr(t1),
- getDReg(ft), getDReg(fs)));
- break;
- } else {
- ILLEGAL_INSTRUCTON;
- break;
- }
+ if (mode64)
+ dis_branch(False, binop(Iop_CmpEQ64, getIReg(rs), getIReg(rt)),
+ imm, bstmt);
+ else
+ dis_branch(False, binop(Iop_CmpEQ32, getIReg(rs), getIReg(rt)),
+ imm, bstmt);
- }
+ break;
- case 0x10: { /* S */
- DIP("sel.s f%u, f%u, f%u", fd, fs, ft);
- t1 = newTemp(Ity_I1);
- assign(t1,binop(Iop_CmpNE32,
- binop(Iop_And32,
- unop(Iop_ReinterpF32asI32,
- getLoFromF64(tyF, getFReg(fd))),
- mkU32(1)),
- mkU32(0)));
- putFReg(fd, IRExpr_ITE( mkexpr(t1),
- getFReg(ft), getFReg(fs)));
- break;
- }
- default:
- goto decode_failure;
- }
- break;
+ case 0x05: /* BNE */
+ DIP("bne r%u, r%u, %u", rs, rt, imm);
- case 0x14: /* SELEQZ.fmt */
- if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
- switch (fmt) { /* SELEQZ.df */
- case 0x11: { /* D */
- DIP("seleqz.d f%u, f%u, f%u", fd, fs, ft);
- t1 = newTemp(Ity_I1);
- if (mode64) {
- assign(t1, binop(Iop_CmpNE64,
- binop(Iop_And64,
- unop(Iop_ReinterpF64asI64,
- getDReg(ft)),
- mkU64(1)),
- mkU64(0)));
- } else {
- assign(t1, binop(Iop_CmpNE32,
- binop(Iop_And32,
- unop(Iop_64to32,
- unop(Iop_ReinterpF64asI64,
- getDReg(ft))),
- mkU32(1)),
- mkU32(0)));
- }
- putDReg(fd, IRExpr_ITE( mkexpr(t1),
- binop(Iop_I64StoF64,
- get_IR_roundingmode(),mkU64(0)),
- getDReg(fs)));
- break;
- }
+ if (mode64)
+ dis_branch(False, binop(Iop_CmpNE64, getIReg(rs), getIReg(rt)),
+ imm, bstmt);
+ else
+ dis_branch(False, binop(Iop_CmpNE32, getIReg(rs), getIReg(rt)),
+ imm, bstmt);
- case 0x10: { /* S */
- DIP("seleqz.s f%u, f%u, f%u", fd, fs, ft);
- t1 = newTemp(Ity_I1);
- assign(t1, binop(Iop_CmpNE32,
- binop(Iop_And32,
- unop(Iop_ReinterpF32asI32,
- getLoFromF64(tyF, getFReg(ft))),
- mkU32(1)),
- mkU32(0)));
- putFReg(fd, IRExpr_ITE(mkexpr(t1),
- mkWidenFromF32(tyF,
- binop(Iop_I32StoF32,
- get_IR_roundingmode(),
- mkU32(0))),
- getFReg(fs)));
- break;
- }
+ break;
- default:
- goto decode_failure;
- }
- } else {
- ILLEGAL_INSTRUCTON;
- }
- break;
+ case 0x06: /* BLEZ, BLEZALC, BGEZALC, BGEUC */
+ if (rt == 0) { /* BLEZ */
+ DIP("blez r%u, %u", rs, imm);
- case 0x17: /* SELNEZ.fmt */
- if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
- switch (fmt) {
- case 0x11: { /* D */
- DIP("selnez.d f%u, f%u, f%u", fd, fs, ft);
- t1 = newTemp(Ity_I1);
- if (mode64) {
- assign(t1, binop(Iop_CmpNE64,
- binop(Iop_And64,
- unop(Iop_ReinterpF64asI64,
- getDReg(ft)),
- mkU64(1)),
- mkU64(0)));
- } else {
- assign(t1, binop(Iop_CmpNE32,
- binop(Iop_And32,
- unop(Iop_64to32,
- unop(Iop_ReinterpF64asI64,
- getDReg(ft))),
- mkU32(1)),
- mkU32(0)));
- }
- putDReg(fd, IRExpr_ITE( mkexpr(t1),
- getDReg(fs),
- binop(Iop_I64StoF64,
- get_IR_roundingmode(),
- mkU64(0))));
- break;
- }
+ if (mode64)
+ dis_branch(False, binop(Iop_CmpLE64S, getIReg(rs), mkU64(0x0)),
+ imm, bstmt);
+ else
+ dis_branch(False, binop(Iop_CmpLE32S, getIReg(rs), mkU32(0x0)), imm,
+ bstmt);
+ } else if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+ if (rs == 0) { /* BLEZALC */
+ DIP("blezalc r%u, %u", rt, imm);
- case 0x10: { /* S */
- DIP("selnez.s f%u, f%u, f%u", fd, fs, ft);
- t1 = newTemp(Ity_I1);
- assign(t1,binop(Iop_CmpNE32,
- binop(Iop_And32,
- unop(Iop_ReinterpF32asI32,
- getLoFromF64(tyF, getFReg(ft))),
- mkU32(1)),
- mkU32(0)));
- putFReg(fd, IRExpr_ITE(mkexpr(t1),
- getFReg(fs),
- mkWidenFromF32(tyF,
- binop(Iop_I32StoF32,
- get_IR_roundingmode(),
- mkU32(0)))));
- break;
- }
+ if (mode64)
+ dis_branch_compact(True,
+ binop(Iop_CmpLE64S, getIReg(rt), mkU64(0x0)),
+ imm, dres);
+ else
+ dis_branch_compact(True,
+ binop(Iop_CmpLE32S, getIReg(rt), mkU32(0x0)),
+ imm, dres);
+ } else if (rt == rs) { /* BGEZALC */
+ DIP("bgezalc r%u, %u", rt, imm);
- default:
- goto decode_failure;
- }
+ if (mode64)
+ dis_branch_compact(True,
+ binop(Iop_CmpLE64S, mkU64(0x0), getIReg(rt)),
+ imm, dres);
+ else
+ dis_branch_compact(True,
+ binop(Iop_CmpLE32S, mkU32(0x0), getIReg(rt)),
+ imm, dres);
+ } else { /* BGEUC */
+ DIP("bgeuc r%u, r%u, %u", rt, rs, imm);
+
+ if (mode64)
+ dis_branch_compact(False,
+ unop(Iop_Not1,
+ binop(Iop_CmpLT64U,
+ getIReg(rs), getIReg(rt))),
+ imm, dres);
+ else
+ dis_branch_compact(False,
+ unop(Iop_Not1,
+ binop(Iop_CmpLT32U,
+ getIReg(rs), getIReg(rt))),
+ imm, dres);
+ }
+ } else {
+ ILLEGAL_INSTRUCTON
+ }
+
+ break;
+
+ case 0x07: /* BGTZ, BGTZALC, BLTZALC, BLTUC */
+ if (rt == 0) { /* BGTZ */
+ DIP("bgtz r%u, %u", rs, imm);
+
+ if (mode64)
+ dis_branch(False, unop(Iop_Not1, binop(Iop_CmpLE64S, getIReg(rs),
+ mkU64(0x00))), imm, bstmt);
+ else
+ dis_branch(False, unop(Iop_Not1, binop(Iop_CmpLE32S, getIReg(rs),
+ mkU32(0x00))), imm, bstmt);
+ } else if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+ if (rs == 0) { /* BGTZALC */
+ DIP("bgtzalc r%u, %u", rt, imm);
+
+ if (mode64) {
+ dis_branch_compact(True,
+ unop(Iop_Not1,
+ binop(Iop_CmpLE64S,
+ getIReg(rt), mkU64(0x0))),
+ imm, dres);
} else {
- ILLEGAL_INSTRUCTON;
+ dis_branch_compact(True,
+ unop(Iop_Not1,
+ binop(Iop_CmpLE32S,
+ getIReg(rt), mkU32(0x0))),
+ imm, dres);
}
- break;
+ } else if (rs == rt) { /* BLTZALC */
+ DIP("bltzalc r%u, %u", rt, imm);
- case 0x1B: /* CLASS.fmt */
- if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
- t0 = newTemp(Ity_I1); // exp zero
- t1 = newTemp(Ity_I1); // exp max
- t2 = newTemp(Ity_I1); // sign
- t3 = newTemp(Ity_I1); // first
- t4 = newTemp(Ity_I1); // val not zero
- t5 = newTemp(Ity_I32);
- switch (fmt) {
- case 0x11: { /* D */
- DIP("class.d f%u, f%u", fd, fs);
- assign(t0, binop(Iop_CmpEQ32,
- binop(Iop_And32,
- unop(Iop_64HIto32,
- unop(Iop_ReinterpF64asI64,
- getDReg(fs))),
- mkU32(0x7ff00000)),
- mkU32(0)));
- assign(t1, binop(Iop_CmpEQ32,
- binop(Iop_And32,
- unop(Iop_64HIto32,
- unop(Iop_ReinterpF64asI64,
- getDReg(fs))),
- mkU32(0x7ff00000)),
- mkU32(0x7ff00000)));
- assign(t2, binop(Iop_CmpEQ32,
- binop(Iop_And32,
- unop(Iop_64HIto32,
- unop(Iop_ReinterpF64asI64,
- getDReg(fs))),
- mkU32(0x80000000)),
- mkU32(0x80000000)));
- assign(t3, binop(Iop_CmpEQ32,
- binop(Iop_And32,
- unop(Iop_64HIto32,
- unop(Iop_ReinterpF64asI64,
- getDReg(fs))),
- mkU32(0x00080000)),
- mkU32(0x00080000)));
- if (mode64) assign(t4, binop(Iop_CmpNE64,
- binop(Iop_And64,
- unop(Iop_ReinterpF64asI64,
- getDReg(fs)),
- mkU64(0x000fffffffffffffULL)),
- mkU64(0)));
- else assign(t4, binop(Iop_CmpNE32,
- binop(Iop_Or32,
- binop(Iop_And32,
- unop(Iop_64HIto32,
- unop(Iop_ReinterpF64asI64,
- getDReg(fs))),
- mkU32(0x000fffff)),
- unop(Iop_64to32,
- unop(Iop_ReinterpF64asI64,
- getDReg(fs)))),
- mkU32(0)));
- assign(t5, binop(Iop_Shl32,
- IRExpr_ITE(mkexpr(t1),
- IRExpr_ITE(mkexpr(t4),
- mkU32(0), mkU32(1)),
- IRExpr_ITE(mkexpr(t0),
- IRExpr_ITE(mkexpr(t4),
- mkU32(0x4),
- mkU32(0x8)),
- mkU32(2))),
- IRExpr_ITE(mkexpr(t2), mkU8(2), mkU8(6))));
- putDReg(fd, unop(Iop_ReinterpI64asF64,
- unop(Iop_32Uto64,
- IRExpr_ITE(binop(Iop_CmpNE32,
- mkexpr(t5), mkU32(0)),
- mkexpr(t5),
- IRExpr_ITE(mkexpr(t3),
- mkU32(2),
- mkU32(1))))));
- break;
- }
- case 0x10: { /* S */
- DIP("class.s f%u, f%u", fd, fs);
- assign(t0, binop(Iop_CmpEQ32,
- binop(Iop_And32,
- unop(Iop_ReinterpF32asI32,
- getLoFromF64(tyF, getFReg(fs))),
- mkU32(0x7f800000)),
- mkU32(0)));
- assign(t1, binop(Iop_CmpEQ32,
- binop(Iop_And32,
- unop(Iop_ReinterpF32asI32,
- getLoFromF64(tyF, getFReg(fs))),
- mkU32(0x7f800000)),
- mkU32(0x7f800000)));
- assign(t2, binop(Iop_CmpEQ32,
- binop(Iop_And32,
- unop(Iop_ReinterpF32asI32,
- getLoFromF64(tyF, getFReg(fs))),
- mkU32(0x80000000)),
- mkU32(0x80000000)));
- assign(t3, binop(Iop_CmpEQ32,
- binop(Iop_And32,
- unop(Iop_ReinterpF32asI32,
- getLoFromF64(tyF, getFReg(fs))),
- mkU32(0x00400000)),
- mkU32(0x00400000)));
- assign(t4, binop(Iop_CmpNE32,
- binop(Iop_And32,
- unop(Iop_ReinterpF32asI32,
- getLoFromF64(tyF, getFReg(fs))),
- mkU32(0x007fffff)),
- mkU32(0)));
- assign(t5, binop(Iop_Shl32,
- IRExpr_ITE(mkexpr(t1),
- IRExpr_ITE(mkexpr(t4),
- mkU32(0), mkU32(1)),
- IRExpr_ITE(mkexpr(t0),
- IRExpr_ITE(mkexpr(t4),
- mkU32(0x4),
- mkU32(0x8)), //zero or subnorm
- mkU32(2))),
- IRExpr_ITE(mkexpr(t2), mkU8(2), mkU8(6))));
- putDReg(fd, unop(Iop_ReinterpI64asF64,
- unop(Iop_32Uto64,
- IRExpr_ITE(binop(Iop_CmpNE32,
- mkexpr(t5), mkU32(0)),
- mkexpr(t5),
- IRExpr_ITE(mkexpr(t3),
- mkU32(2),
- mkU32(1))))));
- break;
- }
- default:
- goto decode_failure;
- }
+ if (mode64) {
+ dis_branch_compact(True,
+ unop(Iop_Not1,
+ binop(Iop_CmpLE64S,
+ mkU64(0x0), getIReg(rt))),
+ imm, dres);
} else {
- ILLEGAL_INSTRUCTON;
+ dis_branch_compact(True,
+ unop(Iop_Not1,
+ binop(Iop_CmpLE32S,
+ mkU32(0x0), getIReg(rt))),
+ imm, dres);
}
- break;
+ } else { /* BLTUC */
+ DIP("bltuc r%u, r%u, %u", rt, rs, imm);
+
+ if (mode64) {
+ dis_branch_compact(False,
+ binop(Iop_CmpLT64U, getIReg(rs), getIReg(rt)),
+ imm, dres);
+ } else {
+ dis_branch_compact(False,
+ binop(Iop_CmpLT32U, getIReg(rs), getIReg(rt)),
+ imm, dres);
+ }
+ }
+ } else {
+ ILLEGAL_INSTRUCTON
+ }
+
+ break;
+
+#if defined(__mips__) && ((defined(__mips_isa_rev) && __mips_isa_rev < 6))
+
+ case 0x08: { /* ADDI */
+ DIP("addi r%u, r%u, %u", rt, rs, imm);
+ IRTemp tmpRs32, t1, t2, t3, t4;
+ tmpRs32 = newTemp(Ity_I32);
+ assign(tmpRs32, mkNarrowTo32(ty, getIReg(rs)));
+
+ t0 = newTemp(Ity_I32);
+ t1 = newTemp(Ity_I32);
+ t2 = newTemp(Ity_I32);
+ t3 = newTemp(Ity_I32);
+ t4 = newTemp(Ity_I32);
+ /* dst = src0 + sign(imm)
+ if(sign(src0 ) != sign(imm ))
+ goto no overflow;
+ if(sign(dst) == sign(src0 ))
+ goto no overflow;
+ we have overflow! */
+
+ assign(t0, binop(Iop_Add32, mkexpr(tmpRs32),
+ mkU32(extend_s_16to32(imm))));
+ assign(t1, binop(Iop_Xor32, mkexpr(tmpRs32),
+ mkU32(extend_s_16to32(imm))));
+ assign(t2, unop(Iop_1Sto32, binop(Iop_CmpEQ32, binop(Iop_And32,
+ mkexpr(t1), mkU32(0x80000000)), mkU32(0x80000000))));
+
+ assign(t3, binop(Iop_Xor32, mkexpr(t0), mkexpr(tmpRs32)));
+ assign(t4, unop(Iop_1Sto32, binop(Iop_CmpNE32, binop(Iop_And32,
+ mkexpr(t3), mkU32(0x80000000)), mkU32(0x80000000))));
+
+ stmt(IRStmt_Exit(binop(Iop_CmpEQ32, binop(Iop_Or32, mkexpr(t2),
+ mkexpr(t4)), mkU32(0)), Ijk_SigFPE_IntOvf,
+ mode64 ? IRConst_U64(guest_PC_curr_instr + 4) :
+ IRConst_U32(guest_PC_curr_instr + 4),
+ OFFB_PC));
+
+ putIReg(rt, mkWidenFrom32(ty, mkexpr(t0), True));
+ break;
+ }
- default:
- if (dis_instr_CCondFmt(cins))
- break;
- goto decode_failure;
+#elif defined(__mips__) && ((defined(__mips_isa_rev) && __mips_isa_rev >= 6))
+
+ case 0x08: { /* BEQZALC, BEQC, BOVC */
+ if (rs == 0) { /* BEQZALC */
+ DIP("beqzalc r%u, %u", rt, imm);
+
+ if (mode64) {
+ dis_branch_compact(True,
+ binop(Iop_CmpEQ64, getIReg(rt), mkU64(0x0)),
+ imm, dres);
+ } else {
+ dis_branch_compact(True,
+ binop(Iop_CmpEQ32, getIReg(rt), mkU32(0x0)),
+ imm, dres);
+ }
+ } else if (rs < rt) { /* BEQC */
+ DIP("beqc r%u, r%u, %u", rs, rt, imm);
+ if (mode64) {
+ dis_branch_compact(False,
+ binop(Iop_CmpEQ64, getIReg(rt), getIReg(rs)),
+ imm, dres);
+ } else {
+ dis_branch_compact(False,
+ binop(Iop_CmpEQ32, getIReg(rt), getIReg(rs)),
+ imm, dres);
}
+ } else { /* BOVC */
+ DIP("bovc r%u, r%u, %u", rs, rt, imm);
+
+ if (mode64) {
+ t0 = newTemp(Ity_I32);
+ t1 = newTemp(Ity_I32);
+ t2 = newTemp(Ity_I32);
+ t3 = newTemp(Ity_I32);
+ assign(t0, IRExpr_ITE(binop(Iop_CmpLT64S,
+ getIReg(rt),
+ mkU64(0xffffffff80000000ULL)),
+ mkU32(1),
+ IRExpr_ITE(binop(Iop_CmpLT64S,
+ getIReg(rt),
+ mkU64(0x7FFFFFFFULL)),
+ mkU32(0), mkU32(1))));
+ assign(t1, IRExpr_ITE(binop(Iop_CmpLT64S,
+ getIReg(rs),
+ mkU64(0xffffffff80000000ULL)),
+ mkU32(1),
+ IRExpr_ITE(binop(Iop_CmpLT64S,
+ getIReg(rs),
+ mkU64(0x7FFFFFFFULL)),
+ mkU32(0), mkU32(1))));
+ assign(t2, IRExpr_ITE(binop(Iop_CmpLT64S,
+ binop(Iop_Add64,
+ getIReg(rt), getIReg(rs)),
+ mkU64(0xffffffff80000000ULL)),
+ mkU32(1),
+ IRExpr_ITE(binop(Iop_CmpLT64S,
+ binop(Iop_Add64,
+ getIReg(rt),
+ getIReg(rs)),
+ mkU64(0x7FFFFFFFULL)),
+ mkU32(0), mkU32(1))));
+ assign(t3, binop(Iop_Add32,
+ mkexpr(t0),
+ binop(Iop_Add32, mkexpr(t1), mkexpr(t2))));
+ dis_branch_compact(False,
+ binop(Iop_CmpNE32, mkexpr(t3), mkU32(0)),
+ imm, dres);
+ } else {
+ IRTemp tmpRs32 = newTemp(Ity_I32);
+ IRTemp tmpRt32 = newTemp(Ity_I32);
+ assign(tmpRs32, getIReg(rs));
+ assign(tmpRt32, getIReg(rt));
+
+ t0 = newTemp(Ity_I32);
+ t1 = newTemp(Ity_I32);
+ t2 = newTemp(Ity_I32);
+ t3 = newTemp(Ity_I32);
+ t4 = newTemp(Ity_I32);
+ /* dst = src0 + src1
+ if (sign(src0 ) != sign(src1 ))
+ goto no overflow;
+ if (sign(dst) == sign(src0 ))
+ goto no overflow;
+ we have overflow! */
+ assign(t0, binop(Iop_Add32, mkexpr(tmpRs32), mkexpr(tmpRt32)));
+ assign(t1, binop(Iop_Xor32, mkexpr(tmpRs32), mkexpr(tmpRt32)));
+ assign(t2, unop(Iop_1Uto32,
+ binop(Iop_CmpEQ32,
+ binop(Iop_And32, mkexpr(t1), mkU32(0x80000000)),
+ mkU32(0x80000000))));
+
+ assign(t3, binop(Iop_Xor32, mkexpr(t0), mkexpr(tmpRs32)));
+ assign(t4, unop(Iop_1Uto32,
+ binop(Iop_CmpNE32,
+ binop(Iop_And32, mkexpr(t3), mkU32(0x80000000)),
+ mkU32(0x80000000))));
+
+ dis_branch_compact(False, binop(Iop_CmpEQ32,
+ binop(Iop_Or32, mkexpr(t2), mkexpr(t4)),
+ mkU32(0)), imm, dres);
+ }
}
+
+ break;
+ /* In documentation for BEQC stands rs > rt and for BOVC stands rs >= rt! */
}
- break; /* COP1 */
- case 0x31: /* LWC1 */
- /* Load Word to Floating Point - LWC1 (MIPS32) */
- DIP("lwc1 f%u, %u(r%u)", ft, imm, rs);
- LOAD_STORE_PATTERN;
- if (fp_mode64) {
- t0 = newTemp(Ity_F32);
- t2 = newTemp(Ity_I64);
- assign(t0, load(Ity_F32, mkexpr(t1)));
- assign(t2, mkWidenFrom32(Ity_I64, unop(Iop_ReinterpF32asI32,
- mkexpr(t0)), True));
- putDReg(ft, unop(Iop_ReinterpI64asF64, mkexpr(t2)));
- } else {
- putFReg(ft, load(Ity_F32, mkexpr(t1)));
- }
- break;
-
- case 0x39: /* SWC1 */
- DIP("swc1 f%u, %u(r%u)", ft, imm, rs);
- if (fp_mode64) {
- t0 = newTemp(Ity_I64);
- t2 = newTemp(Ity_I32);
- LOAD_STORE_PATTERN;
- assign(t0, unop(Iop_ReinterpF64asI64, getFReg(ft)));
- assign(t2, unop(Iop_64to32, mkexpr(t0)));
- store(mkexpr(t1), unop(Iop_ReinterpI32asF32, mkexpr(t2)));
- } else {
- LOAD_STORE_PATTERN;
- store(mkexpr(t1), getFReg(ft));
- }
- break;
-
- case 0x33: /* PREF */
- DIP("pref");
- break;
-
- case 0x35:
- /* Load Doubleword to Floating Point - LDC1 (MIPS32) */
- DIP("ldc1 f%u, %u(%u)", rt, imm, rs);
- LOAD_STORE_PATTERN;
- putDReg(ft, load(Ity_F64, mkexpr(t1)));
- break;
-
- case 0x3D:
- /* Store Doubleword from Floating Point - SDC1 */
- DIP("sdc1 f%u, %u(%u)", ft, imm, rs);
- LOAD_STORE_PATTERN;
- store(mkexpr(t1), getDReg(ft));
- break;
-
- case 0x23: /* LW */
- DIP("lw r%u, %u(r%u)", rt, imm, rs);
- LOAD_STORE_PATTERN;
- putIReg(rt, mkWidenFrom32(ty, load(Ity_I32, mkexpr(t1)), True));
- break;
-
- case 0x20: /* LB */
- DIP("lb r%u, %u(r%u)", rt, imm, rs);
- LOAD_STORE_PATTERN;
- if (mode64)
- putIReg(rt, unop(Iop_8Sto64, load(Ity_I8, mkexpr(t1))));
- else
- putIReg(rt, unop(Iop_8Sto32, load(Ity_I8, mkexpr(t1))));
- break;
+#endif
- case 0x24: /* LBU */
- DIP("lbu r%u, %u(r%u)", rt, imm, rs);
- LOAD_STORE_PATTERN;
- if (mode64)
- putIReg(rt, unop(Iop_8Uto64, load(Ity_I8, mkexpr(t1))));
- else
- putIReg(rt, unop(Iop_8Uto32, load(Ity_I8, mkexpr(t1))));
- break;
+ case 0x09: /* ADDIU */
+ DIP("addiu r%u, r%u, %u", rt, rs, imm);
- case 0x21: /* LH */
- DIP("lh r%u, %u(r%u)", rt, imm, rs);
- LOAD_STORE_PATTERN;
- if (mode64)
- putIReg(rt, unop(Iop_16Sto64, load(Ity_I16, mkexpr(t1))));
- else
- putIReg(rt, unop(Iop_16Sto32, load(Ity_I16, mkexpr(t1))));
- break;
+ if (mode64) {
+ putIReg(rt, mkWidenFrom32(ty, binop(Iop_Add32,
+ mkNarrowTo32(ty, getIReg(rs)), mkU32(extend_s_16to32(imm))),
+ True));
+ } else
+ putIReg(rt, binop(Iop_Add32, getIReg(rs), mkU32(extend_s_16to32(imm))));
- case 0x25: /* LHU */
- DIP("lhu r%u, %u(r%u)", rt, imm, rs);
- LOAD_STORE_PATTERN;
- if (mode64)
- putIReg(rt, unop(Iop_16Uto64, load(Ity_I16, mkexpr(t1))));
- else
- putIReg(rt, unop(Iop_16Uto32, load(Ity_I16, mkexpr(t1))));
- break;
+ break;
+
+ case 0x0A: /* SLTI */
+ DIP("slti r%u, r%u, %u", rt, rs, imm);
- case 0x0F: /* LUI */
- if (rs == 0) {
- p = (imm << 16);
- DIP("lui r%u, imm: 0x%x", rt, imm);
if (mode64)
- putIReg(rt, mkU64(extend_s_32to64(p)));
+ putIReg(rt, unop(Iop_1Uto64, binop(Iop_CmpLT64S, getIReg(rs),
+ mkU64(extend_s_16to64(imm)))));
else
- putIReg(rt, mkU32(p));
+ putIReg(rt, unop(Iop_1Uto32, binop(Iop_CmpLT32S, getIReg(rs),
+ mkU32(extend_s_16to32(imm)))));
+
break;
- } else if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) { /* AUI */
- DIP("aui r%u, imm: 0x%x", rt, imm);
- if (mode64) {
- putIReg(rt, unop(Iop_32Sto64,
- unop(Iop_64to32,
- binop(Iop_Add64,
- getIReg(rs),
- mkU64(extend_s_32to64(imm << 16))))));
- } else {
- putIReg(rt, binop(Iop_Add32, getIReg(rs), mkU32(imm << 16)));
- }
- } else {
- ILLEGAL_INSTRUCTON;
- }
- break;
- case 0x13: /* COP1X */
- switch (function) {
- case 0x0: { /* LWXC1 */
- /* Load Word Indexed to Floating Point - LWXC1 (MIPS32r2) */
- DIP("lwxc1 f%u, r%u(r%u)", fd, rt, rs);
- t2 = newTemp(ty);
- assign(t2, binop(mode64 ? Iop_Add64 : Iop_Add32, getIReg(rs),
- getIReg(rt)));
- if (fp_mode64) {
- t0 = newTemp(Ity_I64);
- t1 = newTemp(Ity_I32);
- t3 = newTemp(Ity_F32);
- t4 = newTemp(Ity_I64);
- assign(t3, load(Ity_F32, mkexpr(t2)));
+ case 0x0B: /* SLTIU */
+ DIP("sltiu r%u, r%u, %u", rt, rs, imm);
- assign(t4, mkWidenFrom32(Ity_I64, unop(Iop_ReinterpF32asI32,
- mkexpr(t3)), True));
+ if (mode64)
+ putIReg(rt, unop(Iop_1Uto64, binop(Iop_CmpLT64U, getIReg(rs),
+ mkU64(extend_s_16to64(imm)))));
+ else
+ putIReg(rt, unop(Iop_1Uto32, binop(Iop_CmpLT32U, getIReg(rs),
+ mkU32(extend_s_16to32(imm)))));
- putFReg(fd, unop(Iop_ReinterpI64asF64, mkexpr(t4)));
- } else {
- putFReg(fd, load(Ity_F32, mkexpr(t2)));
- }
break;
- }
- case 0x1: { /* LDXC1 */
- /* Load Doubleword Indexed to Floating Point
- LDXC1 (MIPS32r2 and MIPS64) */
- DIP("ldxc1 f%u, r%u(r%u)", fd, rt, rs);
- t0 = newTemp(ty);
- assign(t0, binop(mode64 ? Iop_Add64 : Iop_Add32, getIReg(rs),
- getIReg(rt)));
- putDReg(fd, load(Ity_F64, mkexpr(t0)));
- break;
- }
+ case 0x0C: /* ANDI */
+ DIP("andi r%u, r%u, %u", rt, rs, imm);
- case 0x5: /* Load Doubleword Indexed Unaligned to Floating Point - LUXC1;
- MIPS32r2 and MIPS64 */
- DIP("luxc1 f%u, r%u(r%u)", fd, rt, rs);
- if ((mode64 || VEX_MIPS_CPU_HAS_MIPS32R2(archinfo->hwcaps))
- && fp_mode64) {
- t0 = newTemp(ty);
- t1 = newTemp(ty);
- assign(t0, binop(mode64 ? Iop_Add64 : Iop_Add32,
- getIReg(rs), getIReg(rt)));
- assign(t1, binop(mode64 ? Iop_And64 : Iop_And32,
- mkexpr(t0),
- mode64 ? mkU64(0xfffffffffffffff8ULL)
- : mkU32(0xfffffff8ULL)));
- putFReg(fd, load(Ity_F64, mkexpr(t1)));
+ if (mode64) {
+ ALUI_PATTERN64(Iop_And64);
} else {
- ILLEGAL_INSTRUCTON;
+ ALUI_PATTERN(Iop_And32);
}
- break;
- case 0x8: { /* Store Word Indexed from Floating Point - SWXC1 */
- DIP("swxc1 f%u, r%u(r%u)", ft, rt, rs);
- t0 = newTemp(ty);
- assign(t0, binop(mode64 ? Iop_Add64 : Iop_Add32, getIReg(rs),
- getIReg(rt)));
- if (fp_mode64) {
- store(mkexpr(t0), getLoFromF64(tyF, getFReg(fs)));
- } else {
- store(mkexpr(t0), getFReg(fs));
- }
- break;
- }
- case 0x9: { /* Store Doubleword Indexed from Floating Point - SDXC1 */
- DIP("sdxc1 f%u, r%u(r%u)", fs, rt, rs);
- t0 = newTemp(ty);
- assign(t0, binop(mode64 ? Iop_Add64 : Iop_Add32, getIReg(rs),
- getIReg(rt)));
- store(mkexpr(t0), getDReg(fs));
- break;
- }
- case 0xD: /* Store Doubleword Indexed Unaligned from Floating Point -
- SUXC1; MIPS64 MIPS32r2 */
- DIP("suxc1 f%u, r%u(r%u)", fd, rt, rs);
- if ((mode64 || VEX_MIPS_CPU_HAS_MIPS32R2(archinfo->hwcaps))
- && fp_mode64) {
- t0 = newTemp(ty);
- t1 = newTemp(ty);
- assign(t0, binop(mode64 ? Iop_Add64 : Iop_Add32,
- getIReg(rs), getIReg(rt)));
- assign(t1, binop(mode64 ? Iop_And64 : Iop_And32,
- mkexpr(t0),
- mode64 ? mkU64(0xfffffffffffffff8ULL)
- : mkU32(0xfffffff8ULL)));
- store(mkexpr(t1), getFReg(fs));
- } else {
- ILLEGAL_INSTRUCTON;
- }
break;
- case 0x0F: {
- DIP("prefx");
- break;
- }
- case 0x20: { /* MADD.S */
- DIP("madd.s f%u, f%u, f%u, f%u", fd, fmt, fs, ft);
- IRExpr *rm = get_IR_roundingmode();
- t1 = newTemp(Ity_F32);
- assign(t1, triop(Iop_AddF32, rm, getLoFromF64(tyF, getFReg(fmt)),
- triop(Iop_MulF32, rm, getLoFromF64(tyF, getFReg(fs)),
- getLoFromF64(tyF, getFReg(ft)))));
- putFReg(fd, mkWidenFromF32(tyF, mkexpr(t1)));
- break; /* MADD.S */
- }
- case 0x21: { /* MADD.D */
- DIP("madd.d f%u, f%u, f%u, f%u", fd, fmt, fs, ft);
- IRExpr *rm = get_IR_roundingmode();
- putDReg(fd, triop(Iop_AddF64, rm, getDReg(fmt),
- triop(Iop_MulF64, rm, getDReg(fs),
- getDReg(ft))));
- break; /* MADD.D */
- }
- case 0x28: { /* MSUB.S */
- DIP("msub.s f%u, f%u, f%u, f%u", fd, fmt, fs, ft);
- IRExpr *rm = get_IR_roundingmode();
- t1 = newTemp(Ity_F32);
- assign(t1, triop(Iop_SubF32, rm,
- triop(Iop_MulF32, rm, getLoFromF64(tyF, getFReg(fs)),
- getLoFromF64(tyF, getFReg(ft))),
- getLoFromF64(tyF, getFReg(fmt))));
- putFReg(fd, mkWidenFromF32(tyF, mkexpr(t1)));
- break; /* MSUB.S */
- }
- case 0x29: { /* MSUB.D */
- DIP("msub.d f%u, f%u, f%u, f%u", fd, fmt, fs, ft);
- IRExpr *rm = get_IR_roundingmode();
- putDReg(fd, triop(Iop_SubF64, rm, triop(Iop_MulF64, rm, getDReg(fs),
- getDReg(ft)), getDReg(fmt)));
- break; /* MSUB.D */
- }
- case 0x30: { /* NMADD.S */
- DIP("nmadd.s f%u, f%u, f%u, f%u", fd, fmt, fs, ft);
- IRExpr *rm = get_IR_roundingmode();
- t1 = newTemp(Ity_F32);
- assign(t1, triop(Iop_AddF32, rm, getLoFromF64(tyF, getFReg(fmt)),
- triop(Iop_MulF32, rm, getLoFromF64(tyF, getFReg(fs)),
- getLoFromF64(tyF, getFReg(ft)))));
- putFReg(fd, mkWidenFromF32(tyF, unop(Iop_NegF32, mkexpr(t1))));
- break; /* NMADD.S */
- }
- case 0x31: { /* NMADD.D */
- DIP("nmadd.d f%u, f%u, f%u, f%u", fd, fmt, fs, ft);
- IRExpr *rm = get_IR_roundingmode();
- t1 = newTemp(Ity_F64);
- assign(t1, triop(Iop_AddF64, rm, getDReg(fmt),
- triop(Iop_MulF64, rm, getDReg(fs),
- getDReg(ft))));
- putDReg(fd, unop(Iop_NegF64, mkexpr(t1)));
- break; /* NMADD.D */
- }
- case 0x38: { /* NMSUBB.S */
- DIP("nmsub.s f%u, f%u, f%u, f%u", fd, fmt, fs, ft);
- IRExpr *rm = get_IR_roundingmode();
- t1 = newTemp(Ity_F32);
- assign(t1, triop(Iop_SubF32, rm,
- triop(Iop_MulF32, rm, getLoFromF64(tyF, getFReg(fs)),
- getLoFromF64(tyF, getFReg(ft))),
- getLoFromF64(tyF, getFReg(fmt))));
- putFReg(fd, mkWidenFromF32(tyF, unop(Iop_NegF32, mkexpr(t1))));
- break; /* NMSUBB.S */
- }
- case 0x39: { /* NMSUBB.D */
- DIP("nmsub.d f%u, f%u, f%u, f%u", fd, fmt, fs, ft);
- IRExpr *rm = get_IR_roundingmode();
- t1 = newTemp(Ity_F64);
- assign(t1, triop(Iop_SubF64, rm, triop(Iop_MulF64, rm, getDReg(fs),
- getDReg(ft)), getDReg(fmt)));
- putDReg(fd, unop(Iop_NegF64, mkexpr(t1)));
- break; /* NMSUBB.D */
- }
-
- default:
- goto decode_failure;
- }
- break;
-
- case 0x22: /* LWL */
- DIP("lwl r%u, %u(r%u)", rt, imm, rs);
- if (mode64) {
- /* t1 = addr */
- t1 = newTemp(Ity_I64);
-#if defined (_MIPSEL)
- assign(t1, binop(Iop_Add64, getIReg(rs), mkU64(extend_s_16to64(imm))));
-#elif defined (_MIPSEB)
- assign(t1, binop(Iop_Xor64,
- mkU64(0x03),
- binop(Iop_Add64,
- getIReg(rs),
- mkU64(extend_s_16to64(imm)))));
-#endif
- /* t2 = word addr */
- /* t4 = addr mod 4 */
- LWX_SWX_PATTERN64;
-
- /* t3 = word content - shifted */
- t3 = newTemp(Ity_I32);
- assign(t3, binop(Iop_Shl32,
- load(Ity_I32, mkexpr(t2)),
- narrowTo(Ity_I8,
- binop(Iop_Shl32,
- binop(Iop_Sub32,
- mkU32(0x03),
- mkexpr(t4)),
- mkU8(3)))));
-
- /* rt content - adjusted */
- t5 = newTemp(Ity_I32);
- assign(t5, binop(Iop_And32,
- mkNarrowTo32(ty, getIReg(rt)),
- binop(Iop_Shr32,
- mkU32(0x00FFFFFF),
- narrowTo(Ity_I8, binop(Iop_Mul32,
- mkU32(0x08),
- mkexpr(t4))))));
-
- putIReg(rt, mkWidenFrom32(ty, binop(Iop_Or32, mkexpr(t5),
- mkexpr(t3)), True));
- } else {
- /* t1 = addr */
- t1 = newTemp(Ity_I32);
-#if defined (_MIPSEL)
- assign(t1, binop(Iop_Add32, getIReg(rs), mkU32(extend_s_16to32(imm))));
-#elif defined (_MIPSEB)
- assign(t1, binop(Iop_Xor32, mkU32(0x3), binop(Iop_Add32, getIReg(rs),
- mkU32(extend_s_16to32(imm)))));
-#endif
+ case 0x0D: /* ORI */
+ DIP("ori r%u, r%u, %u", rt, rs, imm);
- /* t2 = word addr */
- /* t4 = addr mod 4 */
- LWX_SWX_PATTERN;
+ if (mode64) {
+ ALUI_PATTERN64(Iop_Or64);
+ } else {
+ ALUI_PATTERN(Iop_Or32);
+ }
- /* t3 = word content - shifted */
- t3 = newTemp(Ity_I32);
- assign(t3, binop(Iop_Shl32, load(Ity_I32, mkexpr(t2)), narrowTo(Ity_I8,
- binop(Iop_Shl32, binop(Iop_Sub32, mkU32(0x03), mkexpr(t4)),
- mkU8(3)))));
+ break;
- /* rt content - adjusted */
- t5 = newTemp(Ity_I32);
- assign(t5, binop(Iop_And32,
- getIReg(rt),
- binop(Iop_Shr32,
- mkU32(0x00FFFFFF),
- narrowTo(Ity_I8, binop(Iop_Mul32,
- mkU32(0x08),
- mkexpr(t4))))));
+ case 0x0E: /* XORI */
+ DIP("xori r%u, r%u, %u", rt, rs, imm);
- putIReg(rt, binop(Iop_Or32, mkexpr(t5), mkexpr(t3)));
- }
- break;
+ if (mode64) {
+ ALUI_PATTERN64(Iop_Xor64);
+ } else {
+ ALUI_PATTERN(Iop_Xor32);
+ }
- case 0x26: /* LWR */
- DIP("lwr r%u, %u(r%u)", rt, imm, rs);
- if (mode64) {
- /* t1 = addr */
- t1 = newTemp(Ity_I64);
-#if defined (_MIPSEL)
- assign(t1, binop(Iop_Add64, getIReg(rs), mkU64(extend_s_16to64(imm))));
-#elif defined (_MIPSEB)
- assign(t1, binop(Iop_Xor64,
- mkU64(0x3),
- binop(Iop_Add64,
- getIReg(rs),
- mkU64(extend_s_16to64(imm)))));
-#endif
- /* t2 = word addr */
- /* t4 = addr mod 4 */
- LWX_SWX_PATTERN64;
+ break;
- /* t3 = word content - shifted */
- t3 = newTemp(Ity_I32);
- assign(t3, binop(Iop_Shr32,
- load(Ity_I32, mkexpr(t2)),
- narrowTo(Ity_I8,
- binop(Iop_Shl32, mkexpr(t4), mkU8(0x03)))));
+ case 0x0F: /* LUI */
+ if (rs == 0) {
+ p = (imm << 16);
+ DIP("lui r%u, imm: 0x%x", rt, imm);
- /* rt content - adjusted */
- t5 = newTemp(Ity_I32);
- assign(t5, binop(Iop_And32, mkNarrowTo32(ty, getIReg(rt)),
- unop(Iop_Not32, binop(Iop_Shr32, mkU32(0xFFFFFFFF),
- narrowTo(Ity_I8, binop(Iop_Shl32, mkexpr(t4), mkU8(0x3)))))));
+ if (mode64)
+ putIReg(rt, mkU64(extend_s_32to64(p)));
+ else
+ putIReg(rt, mkU32(p));
- putIReg(rt, mkWidenFrom32(ty, binop(Iop_Or32, mkexpr(t5),
- mkexpr(t3)), True));
+ break;
+ } else if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) { /* AUI */
+ DIP("aui r%u, imm: 0x%x", rt, imm);
- } else {
- /* t1 = addr */
- t1 = newTemp(Ity_I32);
-#if defined (_MIPSEL)
- assign(t1, binop(Iop_Add32, getIReg(rs), mkU32(extend_s_16to32(imm))));
-#elif defined (_MIPSEB)
- assign(t1, binop(Iop_Xor32, mkU32(0x3), binop(Iop_Add32, getIReg(rs),
- mkU32(extend_s_16to32(imm)))));
-#endif
+ if (mode64) {
+ putIReg(rt, unop(Iop_32Sto64,
+ unop(Iop_64to32,
+ binop(Iop_Add64,
+ getIReg(rs),
+ mkU64(extend_s_32to64(imm << 16))))));
+ } else {
+ putIReg(rt, binop(Iop_Add32, getIReg(rs), mkU32(imm << 16)));
+ }
- /* t2 = word addr */
- /* t4 = addr mod 4 */
- LWX_SWX_PATTERN;
+ } else {
+ ILLEGAL_INSTRUCTON
+ }
- /* t3 = word content - shifted */
- t3 = newTemp(Ity_I32);
- assign(t3, binop(Iop_Shr32, load(Ity_I32, mkexpr(t2)),
- narrowTo(Ity_I8, binop(Iop_Shl32, mkexpr(t4),
- mkU8(3)))));
+ break;
- /* rt content - adjusted */
- t5 = newTemp(Ity_I32);
- assign(t5, binop(Iop_And32, getIReg(rt), unop(Iop_Not32,
- binop(Iop_Shr32, mkU32(0xFFFFFFFF), narrowTo(Ity_I8,
- binop(Iop_Shl32, mkexpr(t4), mkU8(0x3)))))));
+ default:
+ return -1;
+ }
- putIReg(rt, binop(Iop_Or32, mkexpr(t5), mkexpr(t3)));
- }
- break;
+ return 0;
+}
- case 0x2B: /* SW */
- DIP("sw r%u, %u(r%u)", rt, imm, rs);
- LOAD_STORE_PATTERN;
- store(mkexpr(t1), mkNarrowTo32(ty, getIReg(rt)));
- break;
+static UInt disInstr_MIPS_WRK_10(UInt cins, const VexArchInfo* archinfo,
+ const VexAbiInfo* abiinfo, DisResult* dres,
+ IRStmt** bstmt, IRExpr** lastn,
+ Bool(*resteerOkFn) (/*opaque */void *,
+ Addr),
+ void* callback_opaque)
+{
+ IRTemp t0, t1 = 0, t2, t3, t4, t5, t6, t7;
+ UInt opcode, rs, rt, ft, fs, fd, fmt, tf, nd, function, imm;
+ /* Additional variables for instruction fields in DSP ASE insructions */
- case 0x2C: { /* SDL rt, offset(base) MIPS64 */
- DIP("sdl r%u, %u(r%u)", rt, imm, rs);
- vassert(mode64);
- IRTemp A_byte = newTemp(Ity_I8);
- IRTemp B_byte = newTemp(Ity_I8);
- IRTemp C_byte = newTemp(Ity_I8);
- IRTemp D_byte = newTemp(Ity_I8);
- IRTemp E_byte = newTemp(Ity_I8);
- IRTemp F_byte = newTemp(Ity_I8);
- IRTemp G_byte = newTemp(Ity_I8);
- IRTemp H_byte = newTemp(Ity_I8);
- IRTemp B_pos = newTemp(Ity_I64);
- IRTemp C_pos = newTemp(Ity_I64);
- IRTemp D_pos = newTemp(Ity_I64);
- IRTemp E_pos = newTemp(Ity_I64);
- IRTemp F_pos = newTemp(Ity_I64);
- IRTemp G_pos = newTemp(Ity_I64);
-
- /* H byte */
- assign(H_byte, getByteFromReg(rt, 0));
- /* G byte */
- assign(G_byte, getByteFromReg(rt, 1));
- /* F byte */
- assign(F_byte, getByteFromReg(rt, 2));
- /* E byte */
- assign(E_byte, getByteFromReg(rt, 3));
- /* D byte */
- assign(D_byte, getByteFromReg(rt, 4));
- /* C byte */
- assign(C_byte, getByteFromReg(rt, 5));
- /* B byte */
- assign(B_byte, getByteFromReg(rt, 6));
- /* A byte */
- assign(A_byte, getByteFromReg(rt, 7));
-
- /* t1 = addr */
- t1 = newTemp(Ity_I64);
- assign(t1, binop(Iop_Add64, getIReg(rs), mkU64(extend_s_16to64(imm))));
-
- /* t2 = word addr */
- t2 = newTemp(Ity_I64);
- assign(t2, binop(Iop_And64, mkexpr(t1), mkU64(0xFFFFFFFFFFFFFFF8ULL)));
-
- /* t3 = addr mod 7 */
- t3 = newTemp(Ity_I64);
- assign(t3, binop(Iop_And64, mkexpr(t1), mkU64(0x7)));
+ opcode = get_opcode(cins);
+ imm = get_imm(cins);
+ rs = get_rs(cins);
+ rt = get_rt(cins);
+ fs = get_fs(cins);
+ fd = get_fd(cins);
+ ft = get_ft(cins);
+ tf = get_tf(cins);
+ nd = get_nd(cins);
+ fmt = get_fmt(cins);
+ function = get_function(cins);
+ IRType ty = mode64 ? Ity_I64 : Ity_I32;
+ IRType tyF = fp_mode64 ? Ity_F64 : Ity_F32;
-#if defined (_MIPSEL)
- /* Calculate X_byte position. */
- assign(B_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkexpr(t3), mkU64(0x1)),
- mkU64(0x0),
- mkU64(0x1)));
-
- assign(C_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkexpr(t3), mkU64(0x2)),
- mkU64(0x0),
- mkU64(0x2)));
-
- assign(D_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkexpr(t3), mkU64(0x3)),
- mkU64(0x0),
- mkU64(0x3)));
-
- assign(E_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkexpr(t3), mkU64(0x4)),
- mkU64(0x0),
- mkU64(0x4)));
-
- assign(F_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkexpr(t3), mkU64(0x5)),
- mkU64(0x0),
- mkU64(0x5)));
-
- assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x7)),
- mkU64(0x1),
- mkU64(0x0)));
-
- /* Store X_byte on the right place. */
- store(mkexpr(t2), mkexpr(H_byte));
- store(binop(Iop_Add64, mkexpr(t2), mkexpr(G_pos)), mkexpr(G_byte));
- store(binop(Iop_Sub64, mkexpr(t1), mkexpr(F_pos)), mkexpr(F_byte));
- store(binop(Iop_Sub64, mkexpr(t1), mkexpr(E_pos)), mkexpr(E_byte));
- store(binop(Iop_Sub64, mkexpr(t1), mkexpr(D_pos)), mkexpr(D_byte));
- store(binop(Iop_Sub64, mkexpr(t1), mkexpr(C_pos)), mkexpr(C_byte));
- store(binop(Iop_Sub64, mkexpr(t1), mkexpr(B_pos)), mkexpr(B_byte));
- store(mkexpr(t1), mkexpr(A_byte));
+ switch (opcode & 0x0F) {
+ case 0x01: { /* COP1 */
+ if (fmt == 0x3 && fd == 0 && function == 0) { /* MFHC1 */
+ DIP("mfhc1 r%u, f%u", rt, fs);
-#else /* _MIPSEB */
- /* Calculate X_byte position. */
- assign(B_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x7)),
- mkU64(0x0),
- mkU64(0x1)));
-
- assign(C_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkexpr(t3), mkU64(0x6)),
- mkU64(0x2),
- mkU64(0x0)));
-
- assign(D_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkexpr(t3), mkU64(0x5)),
- mkU64(0x3),
- mkU64(0x0)));
-
- assign(E_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkexpr(t3), mkU64(0x4)),
- mkU64(0x4),
- mkU64(0x0)));
-
- assign(F_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkexpr(t3), mkU64(0x3)),
- mkU64(0x5),
- mkU64(0x0)));
-
- assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x0)),
- mkU64(0x6),
- mkU64(0x7)));
-
- /* Store X_byte on the right place. */
- store(binop(Iop_Add64, mkexpr(t2), mkU64(0x7)), mkexpr(H_byte));
- store(binop(Iop_Add64, mkexpr(t2), mkexpr(G_pos)), mkexpr(G_byte));
- store(binop(Iop_Add64, mkexpr(t1), mkexpr(F_pos)), mkexpr(F_byte));
- store(binop(Iop_Add64, mkexpr(t1), mkexpr(E_pos)), mkexpr(E_byte));
- store(binop(Iop_Add64, mkexpr(t1), mkexpr(D_pos)), mkexpr(D_byte));
- store(binop(Iop_Add64, mkexpr(t1), mkexpr(C_pos)), mkexpr(C_byte));
- store(binop(Iop_Add64, mkexpr(t1), mkexpr(B_pos)), mkexpr(B_byte));
- store(mkexpr(t1), mkexpr(A_byte));
-#endif
+ if (VEX_MIPS_CPU_HAS_MIPS32R2(archinfo->hwcaps) ||
+ VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+ if (fp_mode64) {
+ t0 = newTemp(Ity_I64);
+ t1 = newTemp(Ity_I32);
+ assign(t0, unop(Iop_ReinterpF64asI64, getDReg(fs)));
+ assign(t1, unop(Iop_64HIto32, mkexpr(t0)));
+ putIReg(rt, mkWidenFrom32(ty, mkexpr(t1), True));
+ } else {
+ putIReg(rt, mkWidenFrom32(ty, unop(Iop_ReinterpF32asI32,
+ getFReg(fs | 1)), True));
+ }
+ } else {
+ ILLEGAL_INSTRUCTON;
+ }
- break;
- }
+ break;
+ } else if (fmt == 0x7 && fd == 0 && function == 0) { /* MTHC1 */
+ DIP("mthc1 r%u, f%u", rt, fs);
- case 0x2D: {
- /* SDR rt, offset(base) - MIPS64 */
- vassert(mode64);
- DIP("sdr r%u, %u(r%u)", rt, imm, rs);
- IRTemp A_byte = newTemp(Ity_I8);
- IRTemp B_byte = newTemp(Ity_I8);
- IRTemp C_byte = newTemp(Ity_I8);
- IRTemp D_byte = newTemp(Ity_I8);
- IRTemp E_byte = newTemp(Ity_I8);
- IRTemp F_byte = newTemp(Ity_I8);
- IRTemp G_byte = newTemp(Ity_I8);
- IRTemp H_byte = newTemp(Ity_I8);
- IRTemp B_pos = newTemp(Ity_I64);
- IRTemp C_pos = newTemp(Ity_I64);
- IRTemp D_pos = newTemp(Ity_I64);
- IRTemp E_pos = newTemp(Ity_I64);
- IRTemp F_pos = newTemp(Ity_I64);
- IRTemp G_pos = newTemp(Ity_I64);
-
- /* H byte */
- assign(H_byte, getByteFromReg(rt, 0));
- /* G byte */
- assign(G_byte, getByteFromReg(rt, 1));
- /* F byte */
- assign(F_byte, getByteFromReg(rt, 2));
- /* E byte */
- assign(E_byte, getByteFromReg(rt, 3));
- /* D byte */
- assign(D_byte, getByteFromReg(rt, 4));
- /* C byte */
- assign(C_byte, getByteFromReg(rt, 5));
- /* B byte */
- assign(B_byte, getByteFromReg(rt, 6));
- /* A byte */
- assign(A_byte, getByteFromReg(rt, 7));
-
- /* t1 = addr */
- t1 = newTemp(Ity_I64);
- assign(t1, binop(Iop_Add64, getIReg(rs), mkU64(extend_s_16to64(imm))));
-
- /* t2 = word addr */
- t2 = newTemp(Ity_I64);
- assign(t2, binop(Iop_And64, mkexpr(t1), mkU64(0xFFFFFFFFFFFFFFF8ULL)));
-
- /* t3 = addr mod 7 */
- t3 = newTemp(Ity_I64);
- assign(t3, binop(Iop_And64, mkexpr(t1), mkU64(0x7)));
+ if (VEX_MIPS_CPU_HAS_MIPS32R2(archinfo->hwcaps) ||
+ VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+ if (fp_mode64) {
+ t0 = newTemp(Ity_I64);
+ assign(t0, binop(Iop_32HLto64, mkNarrowTo32(ty, getIReg(rt)),
+ unop(Iop_ReinterpF32asI32,
+ getLoFromF64(Ity_F64, getDReg(fs)))));
+ putDReg(fs, unop(Iop_ReinterpI64asF64, mkexpr(t0)));
+ } else {
+ putFReg(fs | 1, unop(Iop_ReinterpI32asF32,
+ mkNarrowTo32(ty, getIReg(rt))));
+ }
+ } else {
+ ILLEGAL_INSTRUCTON;
+ }
-#if defined (_MIPSEL)
- /* Calculate X_byte position. */
- assign(B_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkU64(0x1), mkexpr(t3)),
- mkU64(0x0),
- mkU64(0x6)));
-
- assign(C_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkU64(0x2), mkexpr(t3)),
- mkU64(0x0),
- mkU64(0x5)));
-
- assign(D_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkU64(0x3), mkexpr(t3)),
- mkU64(0x0),
- mkU64(0x4)));
-
- assign(E_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkU64(0x4), mkexpr(t3)),
- mkU64(0x0),
- mkU64(0x3)));
-
- assign(F_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkU64(0x5), mkexpr(t3)),
- mkU64(0x0),
- mkU64(0x2)));
-
- assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x7)),
- mkU64(0x0),
- mkU64(0x1)));
-
- /* Store X_byte on the right place. */
- store(binop(Iop_Add64, mkexpr(t2), mkU64(0x7)), mkexpr(A_byte));
- store(binop(Iop_Add64, mkexpr(t1), mkexpr(B_pos)), mkexpr(B_byte));
- store(binop(Iop_Add64, mkexpr(t1), mkexpr(C_pos)), mkexpr(C_byte));
- store(binop(Iop_Add64, mkexpr(t1), mkexpr(D_pos)), mkexpr(D_byte));
- store(binop(Iop_Add64, mkexpr(t1), mkexpr(E_pos)), mkexpr(E_byte));
- store(binop(Iop_Add64, mkexpr(t1), mkexpr(F_pos)), mkexpr(F_byte));
- store(binop(Iop_Add64, mkexpr(t1), mkexpr(G_pos)), mkexpr(G_byte));
- store(mkexpr(t1), mkexpr(H_byte));
+ break;
+ } else if (fmt == 0x8) { /* BC */
+ /* FcConditionalCode(bc1_cc) */
+ UInt bc1_cc = get_bc1_cc(cins);
+ t1 = newTemp(Ity_I1);
+ t2 = newTemp(Ity_I32);
+ t3 = newTemp(Ity_I1);
-#else /* _MIPSEB */
- /* Calculate X_byte position. */
- assign(B_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkU64(0x5), mkexpr(t3)),
- mkU64(0x6),
- mkU64(0x0)));
-
- assign(C_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkU64(0x4), mkexpr(t3)),
- mkU64(0x5),
- mkU64(0x0)));
-
- assign(D_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkU64(0x3), mkexpr(t3)),
- mkU64(0x4),
- mkU64(0x0)));
-
- assign(E_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkU64(0x2), mkexpr(t3)),
- mkU64(0x3),
- mkU64(0x0)));
-
- assign(F_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkU64(0x1), mkexpr(t3)),
- mkU64(0x2),
- mkU64(0x0)));
-
- assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x0)),
- mkU64(0x0),
- mkU64(0x1)));
-
- /* Store X_byte on the right place. */
- store(mkexpr(t2), mkexpr(A_byte));
- store(binop(Iop_Sub64, mkexpr(t1), mkexpr(B_pos)), mkexpr(B_byte));
- store(binop(Iop_Sub64, mkexpr(t1), mkexpr(C_pos)), mkexpr(C_byte));
- store(binop(Iop_Sub64, mkexpr(t1), mkexpr(D_pos)), mkexpr(D_byte));
- store(binop(Iop_Sub64, mkexpr(t1), mkexpr(E_pos)), mkexpr(E_byte));
- store(binop(Iop_Sub64, mkexpr(t1), mkexpr(F_pos)), mkexpr(F_byte));
- store(binop(Iop_Sub64, mkexpr(t1), mkexpr(G_pos)), mkexpr(G_byte));
- store(mkexpr(t1), mkexpr(H_byte));
-#endif
- break;
- }
+ assign(t1, binop(Iop_CmpEQ32, mkU32(0), mkU32(bc1_cc)));
+ assign(t2, IRExpr_ITE(mkexpr(t1),
+ binop(Iop_And32,
+ binop(Iop_Shr32, getFCSR(), mkU8(23)),
+ mkU32(0x1)),
+ binop(Iop_And32,
+ binop(Iop_Shr32, getFCSR(),
+ mkU8(24 + bc1_cc)),
+ mkU32(0x1))));
+
+ if (tf == 1 && nd == 0) {
+ /* branch on true */
+ DIP("bc1t %u, %u", bc1_cc, imm);
+ assign(t3, binop(Iop_CmpEQ32, mkU32(1), mkexpr(t2)));
+ dis_branch(False, mkexpr(t3), imm, bstmt);
+ break;
+ } else if (tf == 0 && nd == 0) {
+ /* branch on false */
+ DIP("bc1f %u, %u", bc1_cc, imm);
+ assign(t3, binop(Iop_CmpEQ32, mkU32(0), mkexpr(t2)));
+ dis_branch(False, mkexpr(t3), imm, bstmt);
+ break;
+ } else if (nd == 1 && tf == 0) {
+ DIP("bc1fl %u, %u", bc1_cc, imm);
+ *lastn = dis_branch_likely(binop(Iop_CmpNE32, mkexpr(t2),
+ mkU32(0x0)), imm);
+ break;
+ } else if (nd == 1 && tf == 1) {
+ DIP("bc1tl %u, %u", bc1_cc, imm);
+ *lastn = dis_branch_likely(binop(Iop_CmpEQ32, mkexpr(t2),
+ mkU32(0x0)), imm);
+ break;
+ } else
+ return -1;
+ } else if (fmt >= 0x1c && has_msa) { /* BNZ.df */
+ Int df = fmt & 3;
+ t0 = newTemp(Ity_I32);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ft));
+ assign(t2, binop(Iop_64HLtoV128, mkU64(0), mkU64(0)));
- case 0x28: /* SB */
- DIP("sb r%u, %u(r%u)", rt, imm, rs);
- LOAD_STORE_PATTERN;
- store(mkexpr(t1), narrowTo(Ity_I8, getIReg(rt)));
- break;
-
- case 0x29: /* SH */
- DIP("sh r%u, %u(r%u)", rt, imm, rs);
- LOAD_STORE_PATTERN;
- store(mkexpr(t1), narrowTo(Ity_I16, getIReg(rt)));
- break;
-
- case 0x2A: /* SWL */
- DIP("swl r%u, %u(r%u)", rt, imm, rs);
- if (mode64) {
- IRTemp E_byte = newTemp(Ity_I8);
- IRTemp F_byte = newTemp(Ity_I8);
- IRTemp G_byte = newTemp(Ity_I8);
- IRTemp H_byte = newTemp(Ity_I8);
- IRTemp F_pos = newTemp(Ity_I64);
- IRTemp G_pos = newTemp(Ity_I64);
+ switch (df) {
+ case 0x00: { /* BNZ.B */
+ DIP("BNZ.B w%u, %u", ft, imm);
+ assign(t3, binop(Iop_CmpEQ8x16, mkexpr(t1), mkexpr(t2)));
+ break;
+ }
- /* H byte */
- assign(H_byte, getByteFromReg(rt, 0));
- /* G byte */
- assign(G_byte, getByteFromReg(rt, 1));
- /* F byte */
- assign(F_byte, getByteFromReg(rt, 2));
- /* E byte */
- assign(E_byte, getByteFromReg(rt, 3));
+ case 0x01: { /* BNZ.H */
+ DIP("BNZ.H w%u, %u", ft, imm);
+ assign(t3, binop(Iop_CmpEQ16x8, mkexpr(t1), mkexpr(t2)));
+ break;
+ }
- /* t1 = addr */
- t1 = newTemp(Ity_I64);
- assign(t1, binop(Iop_Add64, getIReg(rs), mkU64(extend_s_16to64(imm))));
+ case 0x02: { /* BNZ.W */
+ DIP("BNZ.W w%u, %u", ft, imm);
+ assign(t3, binop(Iop_CmpEQ32x4, mkexpr(t1), mkexpr(t2)));
+ break;
+ }
- /* t2 = word addr */
- t2 = newTemp(Ity_I64);
- assign(t2, binop(Iop_And64, mkexpr(t1), mkU64(0xFFFFFFFFFFFFFFFCULL)));
+ case 0x03: { /* BNZ.D */
+ DIP("BNZ.D w%u, %u", ft, imm);
+ assign(t3, binop(Iop_CmpEQ64x2, mkexpr(t1), mkexpr(t2)));
+ break;
+ }
+ }
- /* t3 = addr mod 4 */
- t3 = newTemp(Ity_I64);
- assign(t3, binop(Iop_And64, mkexpr(t1), mkU64(0x3)));
+ assign(t0,
+ binop(Iop_Or32,
+ binop(Iop_Or32,
+ unop(Iop_V128to32, mkexpr(t3)),
+ unop(Iop_64HIto32, unop(Iop_V128to64, mkexpr(t3)))),
+ binop(Iop_Or32,
+ unop(Iop_64to32,
+ unop(Iop_V128HIto64, mkexpr(t3))),
+ unop(Iop_64HIto32,
+ unop(Iop_V128HIto64, mkexpr(t3))))));
+ dis_branch(False,
+ binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0)), imm, bstmt);
+ } else if (fmt == 0x0F && has_msa) { /* BNZ.V */
+ t0 = newTemp(Ity_I32);
+ t1 = newTemp(Ity_V128);
+ assign(t1, getWReg(ft));
+ assign(t0,
+ binop(Iop_Or32,
+ binop(Iop_Or32,
+ unop(Iop_V128to32, mkexpr(t1)),
+ unop(Iop_64HIto32, unop(Iop_V128to64, mkexpr(t1)))),
+ binop(Iop_Or32,
+ unop(Iop_64to32, unop(Iop_V128HIto64, mkexpr(t1))),
+ unop(Iop_64HIto32,
+ unop(Iop_V128HIto64, mkexpr(t1))))));
+ dis_branch(False,
+ binop(Iop_CmpNE32, mkexpr(t0), mkU32(0)), imm, bstmt);
+ } else if (fmt >= 0x18 && has_msa) { /* BZ.df */
+ Int df = fmt & 3;
+ t0 = newTemp(Ity_I32);
+ t1 = newTemp(Ity_V128);
+ t2 = newTemp(Ity_V128);
+ t3 = newTemp(Ity_V128);
+ assign(t1, getWReg(ft));
+ assign(t2, binop(Iop_64HLtoV128, mkU64(0), mkU64(0)));
-#if defined (_MIPSEL)
- /* Calculate X_byte position. */
- assign(F_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x0)),
- mkU64(0x0),
- mkU64(0x1)));
+ switch (df) {
+ case 0x00: { /* BZ.B */
+ DIP("BZ.B w%u, %u", ft, imm);
+ assign(t3, binop(Iop_CmpEQ8x16, mkexpr(t1), mkexpr(t2)));
+ break;
+ }
- assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x3)),
- mkU64(0x1),
- mkU64(0x0)));
+ case 0x01: { /* BZ.H */
+ DIP("BZ.H w%u, %u", ft, imm);
+ assign(t3, binop(Iop_CmpEQ16x8, mkexpr(t1), mkexpr(t2)));
+ break;
+ }
- /* Store X_byte on the right place. */
- store(mkexpr(t2), mkexpr(H_byte));
- store(binop(Iop_Add64, mkexpr(t2), mkexpr(G_pos)), mkexpr(G_byte));
- store(binop(Iop_Sub64, mkexpr(t1), mkexpr(F_pos)), mkexpr(F_byte));
- store(mkexpr(t1), mkexpr(E_byte));
+ case 0x02: { /* BZ.W */
+ DIP("BZ.W w%u, %u", ft, imm);
+ assign(t3, binop(Iop_CmpEQ32x4, mkexpr(t1), mkexpr(t2)));
+ break;
+ }
-#else /* _MIPSEB */
- /* Calculate X_byte position. */
- assign(F_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x3)),
- mkU64(0x0),
- mkU64(0x1)));
+ case 0x03: { /* BZ.D */
+ DIP("BZ.D w%u, %u", ft, imm);
+ assign(t3, binop(Iop_CmpEQ64x2, mkexpr(t1), mkexpr(t2)));
+ break;
+ }
+ }
- assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x0)),
- mkU64(0x2),
- mkU64(0x3)));
+ assign(t0,
+ binop(Iop_Or32,
+ binop(Iop_Or32,
+ unop(Iop_V128to32, mkexpr(t3)),
+ unop(Iop_64HIto32, unop(Iop_V128to64, mkexpr(t3)))),
+ binop(Iop_Or32,
+ unop(Iop_64to32, unop(Iop_V128HIto64, mkexpr(t3))),
+ unop(Iop_64HIto32,
+ unop(Iop_V128HIto64, mkexpr(t3))))));
+ dis_branch(False,
+ binop(Iop_CmpNE32, mkexpr(t0), mkU32(0)), imm, bstmt);
+ } else if (fmt == 0x0B && has_msa) { /* BZ.V */
+ t0 = newTemp(Ity_I32);
+ t1 = newTemp(Ity_V128);
+ assign(t1, getWReg(ft));
+ assign(t0,
+ binop(Iop_Or32,
+ binop(Iop_Or32,
+ unop(Iop_V128to32, mkexpr(t1)),
+ unop(Iop_64HIto32, unop(Iop_V128to64, mkexpr(t1)))),
+ binop(Iop_Or32,
+ unop(Iop_64to32, unop(Iop_V128HIto64, mkexpr(t1))),
+ unop(Iop_64HIto32,
+ unop(Iop_V128HIto64, mkexpr(t1))))));
+ dis_branch(False,
+ binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0)), imm, bstmt);
+ } else if (fmt == 0x09) { /* BC1EQZ */
+ if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+ DIP("bc1eqz f%u, %u", ft, imm);
+ t1 = newTemp(Ity_I1);
- store(binop(Iop_Add64, mkexpr(t2), mkU64(3)), mkexpr(H_byte));
- store(binop(Iop_Add64, mkexpr(t2), mkexpr(G_pos)), mkexpr(G_byte));
- store(binop(Iop_Add64, mkexpr(t1), mkexpr(F_pos)), mkexpr(F_byte));
- store(mkexpr(t1), mkexpr(E_byte));
+ if (mode64) {
+ assign(t1, binop(Iop_CmpEQ64,
+ binop(Iop_And64,
+ unop(Iop_ReinterpF64asI64, getDReg(ft)),
+ mkU64(1)),
+ mkU64(0)));
+ } else {
+ assign(t1, binop(Iop_CmpEQ32,
+ binop(Iop_And32,
+ unop(Iop_64to32,
+ unop(Iop_ReinterpF64asI64,
+ getDReg(ft))),
+ mkU32(1)),
+ mkU32(0)));
+ }
-#endif
- } else {
- IRTemp E_byte = newTemp(Ity_I8);
- IRTemp F_byte = newTemp(Ity_I8);
- IRTemp G_byte = newTemp(Ity_I8);
- IRTemp H_byte = newTemp(Ity_I8);
- IRTemp F_pos = newTemp(Ity_I32);
- IRTemp G_pos = newTemp(Ity_I32);
+ dis_branch(False, mkexpr(t1), imm, bstmt);
+ } else {
+ ILLEGAL_INSTRUCTON
+ }
+ } else if (fmt == 0x0D) { /* BC1NEZ */
+ if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+ DIP("bc1nez f%u, %u", ft, imm);
+ t1 = newTemp(Ity_I1);
- /* H byte */
- assign(H_byte, getByteFromReg(rt, 0));
- /* G byte */
- assign(G_byte, getByteFromReg(rt, 1));
- /* F byte */
- assign(F_byte, getByteFromReg(rt, 2));
- /* E byte */
- assign(E_byte, getByteFromReg(rt, 3));
+ if (mode64) {
+ assign(t1, binop(Iop_CmpNE64,
+ binop(Iop_And64,
+ unop(Iop_ReinterpF64asI64, getDReg(ft)),
+ mkU64(1)),
+ mkU64(0)));
+ } else {
+ assign(t1, binop(Iop_CmpNE32,
+ binop(Iop_And32,
+ unop(Iop_64to32,
+ unop(Iop_ReinterpF64asI64, getDReg(ft))),
+ mkU32(1)),
+ mkU32(0)));
+ }
- /* t1 = addr */
- t1 = newTemp(Ity_I32);
- assign(t1, binop(Iop_Add32, getIReg(rs), mkU32(extend_s_16to32(imm))));
+ dis_branch(False, mkexpr(t1), imm, bstmt);
+ } else {
+ ILLEGAL_INSTRUCTON;
+ break;
+ }
+ } else {
+ if (fmt == 0x15) { /* CMP.cond.d */
+ Bool comparison = True;
+ UInt signaling = CMPAFD;
+ DIP("cmp.cond.d f%u, f%u, f%u, cond %u", fd, fs, ft, function);
+ t0 = newTemp(Ity_I32);
- /* t2 = word addr */
- t2 = newTemp(Ity_I32);
- assign(t2, binop(Iop_And32, mkexpr(t1), mkU32(0xFFFFFFFCULL)));
+ /* Conditions starting with S should signal exception on QNaN inputs. */
+ switch (function) {
+ case 0x08: /* SAF */
+ signaling = CMPSAFD; /* fallthrough */
+
+ case 0x00: /* AF */
+ assign(t0, binop(Iop_CmpF64, getDReg(fs), getDReg(ft)));
+ calculateFCSR(fs, ft, signaling, False, 2);
+ putDReg(fd,
+ binop(Iop_I64StoF64,
+ get_IR_roundingmode(), mkU64(0)));
+ break;
+
+ case 0x09: /* SUN */
+ signaling = CMPSAFD; /* fallthrough */
+
+ case 0x01: /* UN */
+ assign(t0, binop(Iop_CmpF64, getDReg(fs), getDReg(ft)));
+ calculateFCSR(fs, ft, signaling, False, 2);
+ putDReg(fd,
+ IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x45)),
+ unop(Iop_ReinterpI64asF64,
+ mkU64(0xFFFFFFFFFFFFFFFFULL)),
+ binop(Iop_I64StoF64,
+ get_IR_roundingmode(), mkU64(0))));
+ break;
+
+ case 0x19: /* SOR */
+ signaling = CMPSAFD; /* fallthrough */
+
+ case 0x11: /* OR */
+ assign(t0, binop(Iop_CmpF64, getDReg(fs), getDReg(ft)));
+ calculateFCSR(fs, ft, signaling, False, 2);
+ putDReg(fd,
+ IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x45)),
+ binop(Iop_I64StoF64,
+ get_IR_roundingmode(), mkU64(0)),
+ unop(Iop_ReinterpI64asF64,
+ mkU64(0xFFFFFFFFFFFFFFFFULL))));
+ break;
+
+ case 0x0A: /* SEQ */
+ signaling = CMPSAFD; /* fallthrough */
+
+ case 0x02: /* EQ */
+ assign(t0, binop(Iop_CmpF64, getDReg(fs), getDReg(ft)));
+ calculateFCSR(fs, ft, signaling, False, 2);
+ putDReg(fd,
+ IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x40)),
+ unop(Iop_ReinterpI64asF64,
+ mkU64(0xFFFFFFFFFFFFFFFFULL)),
+ binop(Iop_I64StoF64,
+ get_IR_roundingmode(), mkU64(0))));
+ break;
+
+ case 0x1A: /* SNEQ */
+ signaling = CMPSAFD; /* fallthrough */
+
+ case 0x12: /* NEQ */
+ assign(t0, binop(Iop_CmpF64, getDReg(fs), getDReg(ft)));
+ calculateFCSR(fs, ft, signaling, False, 2);
+ putDReg(fd,
+ IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x40)),
+ binop(Iop_I64StoF64,
+ get_IR_roundingmode(), mkU64(0)),
+ unop(Iop_ReinterpI64asF64,
+ mkU64(0xFFFFFFFFFFFFFFFFULL))));
+ break;
+
+ case 0x0B: /* SUEQ */
+ signaling = CMPSAFD; /* fallthrough */
+
+ case 0x03: /* UEQ */
+ assign(t0, binop(Iop_CmpF64, getDReg(fs), getDReg(ft)));
+ calculateFCSR(fs, ft, signaling, False, 2);
+ putDReg(fd,
+ IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x40)),
+ unop(Iop_ReinterpI64asF64,
+ mkU64(0xFFFFFFFFFFFFFFFFULL)),
+ IRExpr_ITE(binop(Iop_CmpEQ32,
+ mkexpr(t0), mkU32(0x45)),
+ unop(Iop_ReinterpI64asF64,
+ mkU64(0xFFFFFFFFFFFFFFFFULL)),
+ binop(Iop_I64StoF64,
+ get_IR_roundingmode(),
+ mkU64(0)))));
+ break;
+
+ case 0x1B: /* SNEQ */
+ signaling = CMPSAFD; /* fallthrough */
+
+ case 0x13: /* NEQ */
+ assign(t0, binop(Iop_CmpF64, getDReg(fs), getDReg(ft)));
+ calculateFCSR(fs, ft, signaling, False, 2);
+ putDReg(fd,
+ IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x01)),
+ unop(Iop_ReinterpI64asF64,
+ mkU64(0xFFFFFFFFFFFFFFFFULL)),
+ IRExpr_ITE(binop(Iop_CmpEQ32,
+ mkexpr(t0), mkU32(0x00)),
+ unop(Iop_ReinterpI64asF64,
+ mkU64(0xFFFFFFFFFFFFFFFFULL)),
+ binop(Iop_I64StoF64,
+ get_IR_roundingmode(),
+ mkU64(0)))));
+ break;
+
+ case 0x0C: /* SLT */
+ signaling = CMPSAFD; /* fallthrough */
+
+ case 0x04: /* LT */
+ assign(t0, binop(Iop_CmpF64, getDReg(fs), getDReg(ft)));
+ calculateFCSR(fs, ft, signaling, False, 2);
+ putDReg(fd,
+ IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x01)),
+ unop(Iop_ReinterpI64asF64,
+ mkU64(0xFFFFFFFFFFFFFFFFULL)),
+ binop(Iop_I64StoF64,
+ get_IR_roundingmode(), mkU64(0))));
+ break;
+
+ case 0x0D: /* SULT */
+ signaling = CMPSAFD; /* fallthrough */
+
+ case 0x05: /* ULT */
+ assign(t0, binop(Iop_CmpF64, getDReg(fs), getDReg(ft)));
+ calculateFCSR(fs, ft, signaling, False, 2);
+ putDReg(fd,
+ IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x01)),
+ unop(Iop_ReinterpI64asF64,
+ mkU64(0xFFFFFFFFFFFFFFFFULL)),
+ IRExpr_ITE(binop(Iop_CmpEQ32,
+ mkexpr(t0), mkU32(0x45)),
+ unop(Iop_ReinterpI64asF64,
+ mkU64(0xFFFFFFFFFFFFFFFFULL)),
+ binop(Iop_I64StoF64,
+ get_IR_roundingmode(),
+ mkU64(0)))));
+ break;
+
+ case 0x0E: /* SLE */
+ signaling = CMPSAFD; /* fallthrough */
+
+ case 0x06: /* LE */
+ assign(t0, binop(Iop_CmpF64, getDReg(fs), getDReg(ft)));
+ calculateFCSR(fs, ft, signaling, False, 2);
+ putDReg(fd,
+ IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x01)),
+ unop(Iop_ReinterpI64asF64,
+ mkU64(0xFFFFFFFFFFFFFFFFULL)),
+ IRExpr_ITE(binop(Iop_CmpEQ32,
+ mkexpr(t0), mkU32(0x40)),
+ unop(Iop_ReinterpI64asF64,
+ mkU64(0xFFFFFFFFFFFFFFFFULL)),
+ binop(Iop_I64StoF64,
+ get_IR_roundingmode(),
+ mkU64(0)))));
+ break;
- /* t3 = addr mod 4 */
- t3 = newTemp(Ity_I32);
- assign(t3, binop(Iop_And32, mkexpr(t1), mkU32(0x3)));
+ case 0x0F: /* SULE */
+ signaling = CMPSAFD; /* fallthrough */
-#if defined (_MIPSEL)
- /* Calculate X_byte position. */
- assign(F_pos, IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t3), mkU32(0x0)),
- mkU32(0x0),
- mkU32(0x1)));
+ case 0x07: /* ULE */
+ assign(t0, binop(Iop_CmpF64, getDReg(fs), getDReg(ft)));
+ calculateFCSR(fs, ft, signaling, False, 2);
+ putDReg(fd,
+ IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x0)),
+ binop(Iop_I64StoF64,
+ get_IR_roundingmode(), mkU64(0)),
+ unop(Iop_ReinterpI64asF64,
+ mkU64(0xFFFFFFFFFFFFFFFFULL))));
+ break;
- assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t3), mkU32(0x3)),
- mkU32(0x1),
- mkU32(0x0)));
+ default:
+ comparison = False;
+ }
- /* Store X_byte on the right place. */
- store(mkexpr(t2), mkexpr(H_byte));
- store(binop(Iop_Add32, mkexpr(t2), mkexpr(G_pos)), mkexpr(G_byte));
- store(binop(Iop_Sub32, mkexpr(t1), mkexpr(F_pos)), mkexpr(F_byte));
- store(mkexpr(t1), mkexpr(E_byte));
+ if (comparison) {
+ if (!VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+ ILLEGAL_INSTRUCTON
+ }
-#else /* _MIPSEB */
- /* Calculate X_byte position. */
- assign(F_pos, IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t3), mkU32(0x3)),
- mkU32(0x0),
- mkU32(0x1)));
+ break;
+ }
- assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t3), mkU32(0x0)),
- mkU32(0x2),
- mkU32(0x3)));
+ } else if (fmt == 0x14) {
+ Bool comparison = True;
+ UInt signaling = CMPAFS;
+ DIP("cmp.cond.s f%u, f%u, f%u, cond %u", fd, fs, ft, function);
+ t0 = newTemp(Ity_I32);
- store(binop(Iop_Add32, mkexpr(t2), mkU32(3)), mkexpr(H_byte));
- store(binop(Iop_Add32, mkexpr(t2), mkexpr(G_pos)), mkexpr(G_byte));
- store(binop(Iop_Add32, mkexpr(t1), mkexpr(F_pos)), mkexpr(F_byte));
- store(mkexpr(t1), mkexpr(E_byte));
+ /* Conditions starting with S should signal exception on QNaN inputs. */
+ switch (function) {
+ case 0x08: /* SAF */
+ signaling = CMPSAFS; /* fallthrough */
-#endif
- }
- break;
+ case 0x00: /* AF */
+ assign(t0, binop(Iop_CmpF32,
+ getLoFromF64(Ity_F64, getFReg(fs)),
+ getLoFromF64(Ity_F64, getFReg(ft))));
+ calculateFCSR(fs, ft, signaling, True, 2);
+ putFReg(fd,
+ mkWidenFromF32(tyF,
+ binop(Iop_I32StoF32,
+ get_IR_roundingmode(), mkU32(0))));
+ break;
- case 0x2E: /* SWR */
- DIP("swr r%u, %u(r%u)", rt, imm, rs);
- if (mode64) {
- IRTemp E_byte = newTemp(Ity_I8);
- IRTemp F_byte = newTemp(Ity_I8);
- IRTemp G_byte = newTemp(Ity_I8);
- IRTemp H_byte = newTemp(Ity_I8);
- IRTemp F_pos = newTemp(Ity_I64);
- IRTemp G_pos = newTemp(Ity_I64);
+ case 0x09: /* SUN */
+ signaling = CMPSAFS; /* fallthrough */
- /* H byte */
- assign(H_byte, getByteFromReg(rt, 0));
- /* G byte */
- assign(G_byte, getByteFromReg(rt, 1));
- /* F byte */
- assign(F_byte, getByteFromReg(rt, 2));
- /* E byte */
- assign(E_byte, getByteFromReg(rt, 3));
+ case 0x01: /* UN */
+ assign(t0, binop(Iop_CmpF32,
+ getLoFromF64(Ity_F64, getFReg(fs)),
+ getLoFromF64(Ity_F64, getFReg(ft))));
+ calculateFCSR(fs, ft, signaling, True, 2);
+ putFReg(fd,
+ IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x45)),
+ mkWidenFromF32(tyF,
+ unop(Iop_ReinterpI32asF32,
+ mkU32(0xFFFFFFFFU))),
+ mkWidenFromF32(tyF,
+ binop(Iop_I32StoF32,
+ get_IR_roundingmode(),
+ mkU32(0)))));
+ break;
+
+ case 0x19: /* SOR */
+ signaling = CMPSAFS; /* fallthrough */
+
+ case 0x11: /* OR */
+ assign(t0, binop(Iop_CmpF32,
+ getLoFromF64(Ity_F64, getFReg(fs)),
+ getLoFromF64(Ity_F64, getFReg(ft))));
+ calculateFCSR(fs, ft, signaling, True, 2);
+ putFReg(fd,
+ IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x45)),
+ mkWidenFromF32(tyF,
+ binop(Iop_I32StoF32,
+ get_IR_roundingmode(),
+ mkU32(0))),
+ mkWidenFromF32(tyF,
+ unop(Iop_ReinterpI32asF32,
+ mkU32(0xFFFFFFFFU)))));
+ break;
+
+ case 0x0A: /* SEQ */
+ signaling = CMPSAFS; /* fallthrough */
+
+ case 0x02: /* EQ */
+ assign(t0, binop(Iop_CmpF32,
+ getLoFromF64(Ity_F64, getFReg(fs)),
+ getLoFromF64(Ity_F64, getFReg(ft))));
+ calculateFCSR(fs, ft, signaling, True, 2);
+ putFReg(fd,
+ IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x40)),
+ mkWidenFromF32(tyF,
+ unop(Iop_ReinterpI32asF32,
+ mkU32(0xFFFFFFFFU))),
+ mkWidenFromF32(tyF,
+ binop(Iop_I32StoF32,
+ get_IR_roundingmode(),
+ mkU32(0)))));
+ break;
+
+ case 0x1A: /* SNEQ */
+ signaling = CMPSAFS; /* fallthrough */
+
+ case 0x12: /* NEQ */
+ assign(t0, binop(Iop_CmpF32,
+ getLoFromF64(Ity_F64, getFReg(fs)),
+ getLoFromF64(Ity_F64, getFReg(ft))));
+ calculateFCSR(fs, ft, signaling, True, 2);
+ putFReg(fd,
+ IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x40)),
+ mkWidenFromF32(tyF,
+ binop(Iop_I32StoF32,
+ get_IR_roundingmode(),
+ mkU32(0))),
+ mkWidenFromF32(tyF,
+ unop(Iop_ReinterpI32asF32,
+ mkU32(0xFFFFFFFFU)))));
+ break;
+
+ case 0x0B: /* SUEQ */
+ signaling = CMPSAFS; /* fallthrough */
+
+ case 0x03: /* UEQ */
+ assign(t0, binop(Iop_CmpF32,
+ getLoFromF64(Ity_F64, getFReg(fs)),
+ getLoFromF64(Ity_F64, getFReg(ft))));
+ calculateFCSR(fs, ft, signaling, True, 2);
+ putFReg(fd,
+ IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x40)),
+ mkWidenFromF32(tyF,
+ unop(Iop_ReinterpI32asF32,
+ mkU32(0xFFFFFFFFU))),
+ IRExpr_ITE(binop(Iop_CmpEQ32,
+ mkexpr(t0), mkU32(0x45)),
+ mkWidenFromF32(tyF,
+ unop(Iop_ReinterpI32asF32,
+ mkU32(0xFFFFFFFFU))),
+ mkWidenFromF32(tyF,
+ binop(Iop_I32StoF32,
+ get_IR_roundingmode(),
+ mkU32(0))))));
+ break;
- /* t1 = addr */
- t1 = newTemp(Ity_I64);
- assign(t1, binop(Iop_Add64, getIReg(rs), mkU64(extend_s_16to64(imm))));
+ case 0x1B: /* SNEQ */
+ signaling = CMPSAFS; /* fallthrough */
- /* t2 = word addr */
- t2 = newTemp(Ity_I64);
- assign(t2, binop(Iop_And64, mkexpr(t1), mkU64(0xFFFFFFFFFFFFFFFCULL)));
+ case 0x13: /* NEQ */
+ assign(t0, binop(Iop_CmpF32,
+ getLoFromF64(Ity_F64, getFReg(fs)),
+ getLoFromF64(Ity_F64, getFReg(ft))));
+ calculateFCSR(fs, ft, signaling, True, 2);
+ putFReg(fd,
+ IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x01)),
+ mkWidenFromF32(tyF,
+ unop(Iop_ReinterpI32asF32,
+ mkU32(0xFFFFFFFFU))),
+ IRExpr_ITE(binop(Iop_CmpEQ32,
+ mkexpr(t0), mkU32(0x00)),
+ mkWidenFromF32(tyF,
+ unop(Iop_ReinterpI32asF32,
+ mkU32(0xFFFFFFFFU))),
+ mkWidenFromF32(tyF,
+ binop(Iop_I32StoF32,
+ get_IR_roundingmode(),
+ mkU32(0))))));
+ break;
- /* t3 = addr mod 4 */
- t3 = newTemp(Ity_I64);
- assign(t3, binop(Iop_And64, mkexpr(t1), mkU64(0x3)));
+ case 0x0C: /* SLT */
+ signaling = CMPSAFS; /* fallthrough */
-#if defined (_MIPSEL)
- /* Calculate X_byte position. */
- assign(F_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x0)),
- mkU64(0x2),
- mkU64(0x3)));
+ case 0x04: /* LT */
+ assign(t0, binop(Iop_CmpF32,
+ getLoFromF64(Ity_F64, getFReg(fs)),
+ getLoFromF64(Ity_F64, getFReg(ft))));
+ calculateFCSR(fs, ft, signaling, True, 2);
+ putFReg(fd,
+ IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x01)),
+ mkWidenFromF32(tyF,
+ unop(Iop_ReinterpI32asF32,
+ mkU32(0xFFFFFFFFU))),
+ mkWidenFromF32(tyF,
+ binop(Iop_I32StoF32,
+ get_IR_roundingmode(),
+ mkU32(0)))));
+ break;
+
+ case 0x0D: /* SULT */
+ signaling = CMPSAFS; /* fallthrough */
+
+ case 0x05: /* ULT */
+ assign(t0, binop(Iop_CmpF32,
+ getLoFromF64(Ity_F64, getFReg(fs)),
+ getLoFromF64(Ity_F64, getFReg(ft))));
+ calculateFCSR(fs, ft, signaling, True, 2);
+ putFReg(fd,
+ IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x01)),
+ mkWidenFromF32(tyF,
+ unop(Iop_ReinterpI32asF32,
+ mkU32(0xFFFFFFFFU))),
+ IRExpr_ITE(binop(Iop_CmpEQ32,
+ mkexpr(t0), mkU32(0x45)),
+ mkWidenFromF32(tyF,
+ unop(Iop_ReinterpI32asF32,
+ mkU32(0xFFFFFFFFU))),
+ mkWidenFromF32(tyF,
+ binop(Iop_I32StoF32,
+ get_IR_roundingmode(),
+ mkU32(0))))));
+ break;
- assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x3)),
- mkU64(0x0),
- mkU64(0x1)));
+ case 0x0E: /* SLE */
+ signaling = CMPSAFS; /* fallthrough */
- /* Store X_byte on the right place. */
- store(binop(Iop_Add64, mkexpr(t2), mkU64(0x3)), mkexpr(E_byte));
- store(binop(Iop_Add64, mkexpr(t2), mkexpr(F_pos)), mkexpr(F_byte));
- store(binop(Iop_Add64, mkexpr(t1), mkexpr(G_pos)), mkexpr(G_byte));
- store(mkexpr(t1), mkexpr(H_byte));
+ case 0x06: /* LE */
+ assign(t0, binop(Iop_CmpF32,
+ getLoFromF64(Ity_F64, getFReg(fs)),
+ getLoFromF64(Ity_F64, getFReg(ft))));
+ calculateFCSR(fs, ft, signaling, True, 2);
+ putFReg(fd,
+ IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x01)),
+ mkWidenFromF32(tyF,
+ unop(Iop_ReinterpI32asF32,
+ mkU32(0xFFFFFFFFU))),
+ IRExpr_ITE(binop(Iop_CmpEQ32,
+ mkexpr(t0), mkU32(0x40)),
+ mkWidenFromF32(tyF,
+ unop(Iop_ReinterpI32asF32,
+ mkU32(0xFFFFFFFFU))),
+ mkWidenFromF32(tyF,
+ binop(Iop_I32StoF32,
+ get_IR_roundingmode(),
+ mkU32(0))))));
+ break;
-#else /* _MIPSEB */
- /* Calculate X_byte position. */
- assign(F_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x3)),
- mkU64(0x1),
- mkU64(0x0)));
+ case 0x0F: /* SULE */
+ signaling = CMPSAFS; /* fallthrough */
- assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x0)),
- mkU64(0x0),
- mkU64(0x1)));
+ case 0x07: /* ULE */
+ assign(t0, binop(Iop_CmpF32,
+ getLoFromF64(Ity_F64, getFReg(fs)),
+ getLoFromF64(Ity_F64, getFReg(ft))));
+ calculateFCSR(fs, ft, signaling, True, 2);
+ putFReg(fd,
+ IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x0)),
+ mkWidenFromF32(tyF,
+ binop(Iop_I32StoF32,
+ get_IR_roundingmode(),
+ mkU32(0))),
+ mkWidenFromF32(tyF,
+ unop(Iop_ReinterpI32asF32,
+ mkU32(0xFFFFFFFFU)))));
+ break;
- /* Store X_byte on the right place. */
- store(mkexpr(t2), mkexpr(E_byte));
- store(binop(Iop_Add64, mkexpr(t2), mkexpr(F_pos)), mkexpr(F_byte));
- store(binop(Iop_Sub64, mkexpr(t1), mkexpr(G_pos)), mkexpr(G_byte));
- store(mkexpr(t1), mkexpr(H_byte));
-#endif
- } else {
- IRTemp E_byte = newTemp(Ity_I8);
- IRTemp F_byte = newTemp(Ity_I8);
- IRTemp G_byte = newTemp(Ity_I8);
- IRTemp H_byte = newTemp(Ity_I8);
- IRTemp F_pos = newTemp(Ity_I32);
- IRTemp G_pos = newTemp(Ity_I32);
+ default:
+ comparison = False;
+ }
- /* H byte */
- assign(H_byte, getByteFromReg(rt, 0));
- /* G byte */
- assign(G_byte, getByteFromReg(rt, 1));
- /* F byte */
- assign(F_byte, getByteFromReg(rt, 2));
- /* E byte */
- assign(E_byte, getByteFromReg(rt, 3));
+ if (comparison) {
+ if (!VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+ ILLEGAL_INSTRUCTON
+ }
- /* t1 = addr */
- t1 = newTemp(Ity_I32);
- assign(t1, binop(Iop_Add32, getIReg(rs), mkU32(extend_s_16to32(imm))));
+ break;
+ }
+ }
- /* t2 = word addr */
- t2 = newTemp(Ity_I32);
- assign(t2, binop(Iop_And32, mkexpr(t1), mkU32(0xFFFFFFFCULL)));
+ switch (function) {
+ case 0x04: { /* SQRT.fmt */
+ switch (fmt) {
+ case 0x10: { /* S */
+ IRExpr *rm = get_IR_roundingmode();
+ putFReg(fd, mkWidenFromF32(tyF, binop(Iop_SqrtF32, rm,
+ getLoFromF64(tyF, getFReg(fs)))));
+ break;
+ }
- /* t3 = addr mod 4 */
- t3 = newTemp(Ity_I32);
- assign(t3, binop(Iop_And32, mkexpr(t1), mkU32(0x3)));
+ case 0x11: { /* D */
+ IRExpr *rm = get_IR_roundingmode();
+ putDReg(fd, binop(Iop_SqrtF64, rm, getDReg(fs)));
+ break;
+ }
-#if defined (_MIPSEL)
- /* Calculate X_byte position. */
- assign(F_pos, IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t3), mkU32(0x0)),
- mkU32(0x2),
- mkU32(0x3)));
+ default:
+ return -1;
+ }
+ }
+ break; /* SQRT.fmt */
- assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t3), mkU32(0x3)),
- mkU32(0x0),
- mkU32(0x1)));
+ case 0x05: /* ABS.fmt */
+ switch (fmt) {
+ case 0x10: /* S */
+ DIP("abs.s f%u, f%u", fd, fs);
+ putFReg(fd, mkWidenFromF32(tyF, unop(Iop_AbsF32,
+ getLoFromF64(tyF, getFReg(fs)))));
+ break;
- /* Store X_byte on the right place. */
- store(binop(Iop_Add32, mkexpr(t2), mkU32(0x3)), mkexpr(E_byte));
- store(binop(Iop_Add32, mkexpr(t2), mkexpr(F_pos)), mkexpr(F_byte));
- store(binop(Iop_Add32, mkexpr(t1), mkexpr(G_pos)), mkexpr(G_byte));
- store(mkexpr(t1), mkexpr(H_byte));
+ case 0x11: /* D */
+ DIP("abs.d f%u, f%u", fd, fs);
+ putDReg(fd, unop(Iop_AbsF64, getDReg(fs)));
+ break;
-#else /* _MIPSEB */
- /* Calculate X_byte position. */
- assign(F_pos, IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t3), mkU32(0x3)),
- mkU32(0x1),
- mkU32(0x0)));
+ default:
+ return -1;
+ }
- assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t3), mkU32(0x0)),
- mkU32(0x0),
- mkU32(0x1)));
+ break; /* ABS.fmt */
- /* Store X_byte on the right place. */
- store(mkexpr(t2), mkexpr(E_byte));
- store(binop(Iop_Add32, mkexpr(t2), mkexpr(F_pos)), mkexpr(F_byte));
- store(binop(Iop_Sub32, mkexpr(t1), mkexpr(G_pos)), mkexpr(G_byte));
- store(mkexpr(t1), mkexpr(H_byte));
-#endif
- }
- break;
+ case 0x02: /* MUL.fmt */
+ switch (fmt) {
+ case 0x11: { /* D */
+ DIP("mul.d f%u, f%u, f%u", fd, fs, ft);
+ IRExpr *rm = get_IR_roundingmode();
+ putDReg(fd, triop(Iop_MulF64, rm, getDReg(fs),
+ getDReg(ft)));
+ break;
+ }
- case 0x1C: /* Special2 */
- switch (function) {
- /* Cavium Specific instructions */
- case 0x03: case 0x32: case 0x33: /* DMUL, CINS , CINS32 */
- case 0x3A: case 0x3B: case 0x2B: /* EXT, EXT32, SNE */
- /* CVM Compare Instructions */
- case 0x2A: case 0x2E: case 0x2F: /* SEQ, SEQI, SNEI */
- /* CPU Load, Store, Memory, and Control Instructions */
- case 0x18: case 0x19: /* SAA, SAAD */
- case 0x1F: /* LAA, LAAD, LAI, LAID */
- case 0x28: case 0x2C: case 0x2D: /* BADDU, POP, DPOP */
- if (VEX_MIPS_COMP_ID(archinfo->hwcaps) == VEX_PRID_COMP_CAVIUM) {
- if (dis_instr_CVM(cins))
- break;
- goto decode_failure;
- } else {
- goto decode_failure;
- }
- break;
+ case 0x10: { /* S */
+ DIP("mul.s f%u, f%u, f%u", fd, fs, ft);
+ IRExpr *rm = get_IR_roundingmode();
+ putFReg(fd, mkWidenFromF32(tyF, triop(Iop_MulF32, rm,
+ getLoFromF64(tyF, getFReg(fs)),
+ getLoFromF64(tyF, getFReg(ft)))));
+ break;
+ }
- case 0x02: { /* MUL */
- DIP("mul r%u, r%u, r%u", rd, rs, rt);
- if (mode64) {
- IRTemp tmpRs32 = newTemp(Ity_I32);
- IRTemp tmpRt32 = newTemp(Ity_I32);
- IRTemp tmpRes = newTemp(Ity_I32);
+ default:
+ return -1;
+ }
- assign(tmpRs32, mkNarrowTo32(ty, getIReg(rs)));
- assign(tmpRt32, mkNarrowTo32(ty, getIReg(rt)));
- assign(tmpRes, binop(Iop_Mul32,
- mkexpr(tmpRs32), mkexpr(tmpRt32)));
- putIReg(rd, mkWidenFrom32(ty, mkexpr(tmpRes), True));
- } else
- putIReg(rd, binop(Iop_Mul32, getIReg(rs), getIReg(rt)));
- break;
- }
+ break; /* MUL.fmt */
- case 0x00: { /* MADD */
- if (mode64) {
- DIP("madd r%u, r%u", rs, rt);
- t1 = newTemp(Ity_I32);
- t2 = newTemp(Ity_I32);
- t3 = newTemp(Ity_I64);
- t4 = newTemp(Ity_I64);
- t5 = newTemp(Ity_I64);
- t6 = newTemp(Ity_I32);
+ case 0x03: /* DIV.fmt */
+ switch (fmt) {
+ case 0x11: { /* D */
+ DIP("div.d f%u, f%u, f%u", fd, fs, ft);
+ IRExpr *rm = get_IR_roundingmode();
+ putDReg(fd, triop(Iop_DivF64, rm, getDReg(fs),
+ getDReg(ft)));
+ break;
+ }
- assign(t1, mkNarrowTo32(ty, getHI()));
- assign(t2, mkNarrowTo32(ty, getLO()));
+ case 0x10: { /* S */
+ DIP("div.s f%u, f%u, f%u", fd, fs, ft);
+ calculateFCSR(fs, ft, DIVS, False, 2);
+ IRExpr *rm = get_IR_roundingmode();
+ putFReg(fd, mkWidenFromF32(tyF, triop(Iop_DivF32, rm,
+ getLoFromF64(tyF, getFReg(fs)),
+ getLoFromF64(tyF, getFReg(ft)))));
+ break;
+ }
- assign(t3, binop(Iop_MullS32, mkNarrowTo32(ty, getIReg(rs)),
- mkNarrowTo32(ty, getIReg(rt))));
+ default:
+ return -1;
+ }
- assign(t4, binop(Iop_32HLto64, mkexpr(t1), mkexpr(t2)));
- assign(t5, binop(Iop_Add64, mkexpr(t3), mkexpr(t4)));
+ break; /* DIV.fmt */
- putHI(mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(t5)), True));
- putLO(mkWidenFrom32(ty, unop(Iop_64to32, mkexpr(t5)), True));
- } else {
- if ( (1 <= ac) && ( 3 >= ac) ) {
- if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
- /* If DSP is present -> DSP ASE MADD */
- UInt retVal = disDSPInstr_MIPS_WRK ( cins );
- if (0 != retVal ) {
- goto decode_failure_dsp;
+ case 0x01: /* SUB.fmt */
+ switch (fmt) {
+ case 0x11: { /* D */
+ DIP("sub.d f%u, f%u, f%u", fd, fs, ft);
+ calculateFCSR(fs, ft, SUBD, False, 2);
+ IRExpr *rm = get_IR_roundingmode();
+ putDReg(fd, triop(Iop_SubF64, rm, getDReg(fs),
+ getDReg(ft)));
+ break;
}
- break;
- } else {
- goto decode_failure_dsp;
+
+ case 0x10: { /* S */
+ DIP("sub.s f%u, f%u, f%u", fd, fs, ft);
+ calculateFCSR(fs, ft, SUBS, True, 2);
+ IRExpr *rm = get_IR_roundingmode();
+ putFReg(fd, mkWidenFromF32(tyF, triop(Iop_SubF32, rm,
+ getLoFromF64(tyF, getFReg(fs)),
+ getLoFromF64(tyF, getFReg(ft)))));
+ break;
+ }
+
+ default:
+ return -1;
}
- } else {
- DIP("madd r%u, r%u", rs, rt);
- t1 = newTemp(Ity_I32);
- t2 = newTemp(Ity_I32);
- t3 = newTemp(Ity_I64);
- t4 = newTemp(Ity_I32);
- t5 = newTemp(Ity_I32);
- t6 = newTemp(Ity_I32);
- assign(t1, getHI());
- assign(t2, getLO());
+ break; /* SUB.fmt */
- assign(t3, binop(Iop_MullS32, getIReg(rs), getIReg(rt)));
+ case 0x06: /* MOV.fmt */
+ switch (fmt) {
+ case 0x11: /* D */
+ DIP("mov.d f%u, f%u", fd, fs);
- assign(t4, binop(Iop_Add32, mkexpr(t2), unop(Iop_64to32,
- mkexpr(t3))));
+ if (fp_mode64) {
+ putDReg(fd, getDReg(fs));
+ } else {
+ putFReg(fd, getFReg(fs));
+ putFReg(fd + 1, getFReg(fs + 1));
+ }
- assign(t5, unop(Iop_1Uto32, binop(Iop_CmpLT32U, mkexpr(t4),
- unop(Iop_64to32, mkexpr(t3)))));
- assign(t6, binop(Iop_Add32, mkexpr(t5), mkexpr(t1)));
+ break;
- putHI(binop(Iop_Add32, mkexpr(t6), unop(Iop_64HIto32,
- mkexpr(t3))));
- putLO(mkexpr(t4));
- break;
- }
- }
- break;
- }
+ case 0x10: /* S */
+ DIP("mov.s f%u, f%u", fd, fs);
+ putFReg(fd, getFReg(fs));
+ break;
- case 0x01: { /* MADDU */
- if (mode64) {
- DIP("maddu r%u, r%u", rs, rt);
- t1 = newTemp(Ity_I32);
- t2 = newTemp(Ity_I32);
- t3 = newTemp(Ity_I64);
- t4 = newTemp(Ity_I64);
- t5 = newTemp(Ity_I64);
- t6 = newTemp(Ity_I32);
+ default:
+ return -1;
+ }
- assign(t1, mkNarrowTo32(ty, getHI()));
- assign(t2, mkNarrowTo32(ty, getLO()));
+ break; /* MOV.fmt */
- assign(t3, binop(Iop_MullU32, mkNarrowTo32(ty, getIReg(rs)),
- mkNarrowTo32(ty, getIReg(rt))));
+ case 0x07: /* NEG.fmt */
+ switch (fmt) {
+ case 0x10: /* S */
+ DIP("neg.s f%u, f%u", fd, fs);
+ putFReg(fd, mkWidenFromF32(tyF, unop(Iop_NegF32,
+ getLoFromF64(tyF, getFReg(fs)))));
+ break;
- assign(t4, binop(Iop_32HLto64, mkexpr(t1), mkexpr(t2)));
- assign(t5, binop(Iop_Add64, mkexpr(t3), mkexpr(t4)));
+ case 0x11: /* D */
+ DIP("neg.d f%u, f%u", fd, fs);
+ putDReg(fd, unop(Iop_NegF64, getDReg(fs)));
+ break;
- putHI(mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(t5)), True));
- putLO(mkWidenFrom32(ty, unop(Iop_64to32, mkexpr(t5)), True));
- } else {
- if ( (1 <= ac) && ( 3 >= ac) ) {
- if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
- /* If DSP is present -> DSP ASE MADDU */
- UInt retVal = disDSPInstr_MIPS_WRK ( cins );
- if (0 != retVal ) {
- goto decode_failure_dsp;
+ default:
+ return -1;
}
- break;
- } else {
- goto decode_failure_dsp;
- }
- } else {
- DIP("maddu r%u, r%u", rs, rt);
- t1 = newTemp(Ity_I32);
- t2 = newTemp(Ity_I32);
- t3 = newTemp(Ity_I64);
- t4 = newTemp(Ity_I32);
- t5 = newTemp(Ity_I32);
- t6 = newTemp(Ity_I32);
- assign(t1, getHI());
- assign(t2, getLO());
+ break; /* NEG.fmt */
- assign(t3, binop(Iop_MullU32, getIReg(rs), getIReg(rt)));
+ case 0x08: /* ROUND.L.fmt */
+ switch (fmt) {
+ case 0x10: /* S */
+ DIP("round.l.s f%u, f%u", fd, fs);
- assign(t4, binop(Iop_Add32, mkexpr(t2), unop(Iop_64to32,
- mkexpr(t3))));
- assign(t5, unop(Iop_1Uto32, binop(Iop_CmpLT32U, mkexpr(t4),
- unop(Iop_64to32, mkexpr(t3)))));
- assign(t6, binop(Iop_Add32, mkexpr(t5), mkexpr(t1)));
+ if (fp_mode64) {
+ calculateFCSR(fs, 0, ROUNDLS, True, 1);
+ t0 = newTemp(Ity_I64);
- putHI(binop(Iop_Add32, mkexpr(t6), unop(Iop_64HIto32,
- mkexpr(t3))));
- putLO(mkexpr(t4));
- break;
- }
- }
- break;
- }
+ assign(t0, binop(Iop_F32toI64S, mkU32(0x0),
+ getLoFromF64(Ity_F64, getFReg(fs))));
- case 0x04: { /* MSUB */
- if (mode64) {
- DIP("msub r%u, r%u", rs, rt);
- t1 = newTemp(Ity_I32);
- t2 = newTemp(Ity_I32);
- t3 = newTemp(Ity_I64);
- t4 = newTemp(Ity_I64);
- t5 = newTemp(Ity_I64);
- t6 = newTemp(Ity_I32);
+ putDReg(fd, unop(Iop_ReinterpI64asF64, mkexpr(t0)));
+ } else {
+ ILLEGAL_INSTRUCTON
+ }
- assign(t1, mkNarrowTo32(ty, getHI()));
- assign(t2, mkNarrowTo32(ty, getLO()));
+ break;
- assign(t3, binop(Iop_MullS32, mkNarrowTo32(ty, getIReg(rs)),
- mkNarrowTo32(ty, getIReg(rt))));
+ case 0x11: /* D */
+ DIP("round.l.d f%u, f%u", fd, fs);
- assign(t4, binop(Iop_32HLto64, mkexpr(t1), mkexpr(t2)));
- assign(t5, binop(Iop_Sub64, mkexpr(t4), mkexpr(t3)));
+ if (fp_mode64) {
+ calculateFCSR(fs, 0, ROUNDLD, False, 1);
+ putDReg(fd, unop(Iop_ReinterpI64asF64,
+ binop(Iop_F64toI64S,
+ mkU32(0x0),
+ getDReg(fs))));
+ } else {
+ ILLEGAL_INSTRUCTON
+ }
- putHI(mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(t5)), True));
- putLO(mkWidenFrom32(ty, unop(Iop_64to32, mkexpr(t5)), True));
- } else {
- if ( (1 <= ac) && ( 3 >= ac) ) {
- if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
- /* If DSP is present -> DSP ASE MSUB */
- UInt retVal = disDSPInstr_MIPS_WRK ( cins );
- if (0 != retVal ) {
- goto decode_failure_dsp;
- }
- break;
- } else {
- goto decode_failure_dsp;
- }
- } else {
- DIP("msub r%u, r%u", rs, rt);
- t1 = newTemp(Ity_I32);
- t2 = newTemp(Ity_I32);
- t3 = newTemp(Ity_I64);
- t4 = newTemp(Ity_I32);
- t5 = newTemp(Ity_I1);
- t6 = newTemp(Ity_I32);
+ break;
- assign(t1, getHI());
- assign(t2, getLO());
+ default:
+ return -1;
- assign(t3, binop(Iop_MullS32, getIReg(rs), getIReg(rt)));
- assign(t4, unop(Iop_64to32, mkexpr(t3))); /* new lo */
+ }
- /* if lo<lo(mul) hi = hi - 1 */
- assign(t5, binop(Iop_CmpLT32U,
- mkexpr(t2),
- mkexpr(t4)));
+ break; /* ROUND.L.fmt */
- assign(t6, IRExpr_ITE(mkexpr(t5),
- binop(Iop_Sub32, mkexpr(t1), mkU32(0x1)),
- mkexpr(t1)));
+ case 0x09: /* TRUNC.L.fmt */
+ switch (fmt) {
+ case 0x10: /* S */
+ DIP("trunc.l.s f%u, f%u", fd, fs);
- putHI(binop(Iop_Sub32, mkexpr(t6), unop(Iop_64HIto32,
- mkexpr(t3))));
- putLO(binop(Iop_Sub32, mkexpr(t2), mkexpr(t4)));
- break;
- }
- }
- break;
- }
+ if (fp_mode64) {
+ calculateFCSR(fs, 0, TRUNCLS, True, 1);
+ t0 = newTemp(Ity_I64);
+ assign(t0, binop(Iop_F32toI64S, mkU32(0x3),
+ getLoFromF64(Ity_F64, getFReg(fs))));
- case 0x05: { /* MSUBU */
- if (mode64) {
- DIP("msubu r%u, r%u", rs, rt);
- t1 = newTemp(Ity_I32);
- t2 = newTemp(Ity_I32);
- t3 = newTemp(Ity_I64);
- t4 = newTemp(Ity_I64);
- t5 = newTemp(Ity_I64);
- t6 = newTemp(Ity_I32);
+ putDReg(fd, unop(Iop_ReinterpI64asF64, mkexpr(t0)));
+ } else {
+ ILLEGAL_INSTRUCTON
+ }
- assign(t1, mkNarrowTo32(ty, getHI()));
- assign(t2, mkNarrowTo32(ty, getLO()));
+ break;
- assign(t3, binop(Iop_MullU32, mkNarrowTo32(ty, getIReg(rs)),
- mkNarrowTo32(ty, getIReg(rt))));
+ case 0x11: /* D */
+ DIP("trunc.l.d f%u, f%u", fd, fs);
- assign(t4, binop(Iop_32HLto64, mkexpr(t1), mkexpr(t2)));
- assign(t5, binop(Iop_Sub64, mkexpr(t4), mkexpr(t3)));
+ if (fp_mode64) {
+ calculateFCSR(fs, 0, TRUNCLD, False, 1);
+ putDReg(fd, unop(Iop_ReinterpI64asF64,
+ binop(Iop_F64toI64S,
+ mkU32(0x3),
+ getDReg(fs))));
+ } else {
+ ILLEGAL_INSTRUCTON
+ }
- putHI(mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(t5)), True));
- putLO(mkWidenFrom32(ty, unop(Iop_64to32, mkexpr(t5)), True));
- } else {
- if ( (1 <= ac) && ( 3 >= ac) ) {
- if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
- /* If DSP is present -> DSP ASE MSUBU */
- UInt retVal = disDSPInstr_MIPS_WRK ( cins );
- if (0 != retVal ) {
- goto decode_failure_dsp;
+ break;
+
+ default:
+ return -1;
}
- break;
- } else {
- goto decode_failure_dsp;
- }
- } else {
- DIP("msubu r%u, r%u", rs, rt);
- t1 = newTemp(Ity_I32);
- t2 = newTemp(Ity_I32);
- t3 = newTemp(Ity_I64);
- t4 = newTemp(Ity_I32);
- t5 = newTemp(Ity_I1);
- t6 = newTemp(Ity_I32);
- assign(t1, getHI());
- assign(t2, getLO());
+ break; /* TRUNC.L.fmt */
- assign(t3, binop(Iop_MullU32, getIReg(rs), getIReg(rt)));
- assign(t4, unop(Iop_64to32, mkexpr(t3))); /* new lo */
+ case 0x15: /* RECIP.fmt */
+ switch (fmt) {
+ case 0x10: { /* S */
+ DIP("recip.s f%u, f%u", fd, fs);
+ IRExpr *rm = get_IR_roundingmode();
+ putFReg(fd, mkWidenFromF32(tyF, triop(Iop_DivF32,
+ rm, unop(Iop_ReinterpI32asF32,
+ mkU32(ONE_SINGLE)), getLoFromF64(tyF,
+ getFReg(fs)))));
+ break;
+ }
- /* if lo<lo(mul) hi = hi - 1 */
- assign(t5, binop(Iop_CmpLT32U,
- mkexpr(t2),
- mkexpr(t4)));
+ case 0x11: { /* D */
+ DIP("recip.d f%u, f%u", fd, fs);
+ IRExpr *rm = get_IR_roundingmode();
+ /* putDReg(fd, 1.0/getDreg(fs)); */
+ putDReg(fd, triop(Iop_DivF64, rm,
+ unop(Iop_ReinterpI64asF64,
+ mkU64(ONE_DOUBLE)), getDReg(fs)));
+ break;
+ }
- assign(t6, IRExpr_ITE(mkexpr(t5),
- binop(Iop_Sub32,
- mkexpr(t1),
- mkU32(0x1)),
- mkexpr(t1)));
+ default:
+ return -1;
- putHI(binop(Iop_Sub32, mkexpr(t6), unop(Iop_64HIto32,
- mkexpr(t3))));
- putLO(binop(Iop_Sub32, mkexpr(t2), mkexpr(t4)));
- break;
- }
- }
- break;
- }
+ }
- case 0x6: /* dmul MIPS64 - Netlogic */
- DIP("dmul r%u, r%u, r%u", rd, rs, rt);
- t0 = newTemp(Ity_I128);
+ break; /* RECIP.fmt */
- assign(t0, binop(Iop_MullU64, getIReg(rs), getIReg(rt)));
+ case 0x13: /* MOVN.fmt */
+ switch (fmt) {
+ case 0x10: /* S */
+ DIP("movn.s f%u, f%u, r%u", fd, fs, rt);
+ t1 = newTemp(Ity_I1);
- putIReg(rd, unop(Iop_128to64, mkexpr(t0)));
- break;
+ if (mode64)
+ assign(t1, binop(Iop_CmpNE64, mkU64(0), getIReg(rt)));
+ else
+ assign(t1, binop(Iop_CmpNE32, mkU32(0), getIReg(rt)));
- case 0x10: /* LDADDW - Swap Word - Netlogic */
- DIP("ldaddw r%u, r%u", rt, rs);
- t0 = newTemp(Ity_I32);
- t1 = newTemp(Ity_I32);
- t2 = newTemp(Ity_I32);
- t3 = newTemp(Ity_I64);
- t4 = newTemp(Ity_I32);
- t5 = newTemp(Ity_I32);
- t6 = newTemp(Ity_I32);
+ putFReg(fd, IRExpr_ITE(mkexpr(t1), getFReg(fs), getFReg(fd)));
+ break;
- /* v = GPR[rt] */
- assign(t0, mkNarrowTo32(ty, getIReg(rt)));
+ case 0x11: /* D */
+ DIP("movn.d f%u, f%u, r%u", fd, fs, rt);
+ t1 = newTemp(Ity_I1);
- /* GPR[rt] = memory[base]; */
- assign(t1, load(Ity_I32, getIReg(rs)));
- putIReg(rt, mkWidenFrom32(ty, mkexpr(t1), True));
+ if (mode64)
+ assign(t1, binop(Iop_CmpNE64, mkU64(0), getIReg(rt)));
+ else
+ assign(t1, binop(Iop_CmpNE32, mkU32(0), getIReg(rt)));
- /* memory[base] = memory[base] + v; */
- store(getIReg(rs), binop(Iop_Add32, mkexpr(t0), mkexpr(t1)));
- break;
+ putDReg(fd, IRExpr_ITE(mkexpr(t1), getDReg(fs), getDReg(fd)));
+ break;
- case 0x12: /* LDADDD - Swap Word - Netlogic */
- DIP("ldaddw r%u, r%u", rt, rs);
- t0 = newTemp(Ity_I64);
- t1 = newTemp(Ity_I64);
+ default:
+ return -1;
+ }
- /* v = GPR[rt] */
- assign(t0, getIReg(rt));
+ break; /* MOVN.fmt */
- /* GPR[rt] = memory[base]; */
- assign(t1, load(Ity_I64, getIReg(rs)));
- putIReg(rt, mkexpr(t1));
+ case 0x12: /* MOVZ.fmt */
+ switch (fmt) {
+ case 0x10: /* S */
+ DIP("movz.s f%u, f%u, r%u", fd, fs, rt);
+ t1 = newTemp(Ity_I1);
- /* memory[base] = memory[base] + v; */
- store(getIReg(rs), binop(Iop_Add64, mkexpr(t0), mkexpr(t1)));
- break;
+ if (mode64)
+ assign(t1, binop(Iop_CmpEQ64, mkU64(0), getIReg(rt)));
+ else
+ assign(t1, binop(Iop_CmpEQ32, mkU32(0), getIReg(rt)));
- case 0x14: /* SWAPW - Swap Word - Netlogic */
- DIP("swapw r%u, r%u", rt, rs);
- t0 = newTemp(Ity_I32);
- t1 = newTemp(Ity_I32);
- assign(t0, mkNarrowTo32(ty, getIReg(rt)));
- assign(t1, load(Ity_I32, getIReg(rs)));
- putIReg(rt, mkWidenFrom32(ty, mkexpr(t1), True));
- store(getIReg(rs), mkexpr(t0));
- break;
+ putFReg(fd, IRExpr_ITE(mkexpr(t1), getFReg(fs), getFReg(fd)));
+ break;
- case 0x16: /* SWAPD - Swap Double - Netlogic */
- DIP("swapw r%u, r%u", rt, rs);
- t0 = newTemp(Ity_I64);
- t1 = newTemp(Ity_I64);
- assign(t0, getIReg(rt));
- assign(t1, load(Ity_I64, getIReg(rs)));
- putIReg(rt, mkexpr(t1));
- store(getIReg(rs), mkexpr(t0));
- break;
+ case 0x11: /* D */
+ DIP("movz.d f%u, f%u, r%u", fd, fs, rt);
+ t1 = newTemp(Ity_I1);
- case 0x20: { /* CLZ */
- DIP("clz r%u, r%u", rd, rs);
- if (mode64) {
- IRTemp tmpClz32 = newTemp(Ity_I32);
- IRTemp tmpRs32 = newTemp(Ity_I32);
+ if (mode64)
+ assign(t1, binop(Iop_CmpEQ64, mkU64(0), getIReg(rt)));
+ else
+ assign(t1, binop(Iop_CmpEQ32, mkU32(0), getIReg(rt)));
- assign(tmpRs32, mkNarrowTo32(ty, getIReg(rs)));
- assign(tmpClz32, unop(Iop_Clz32, mkexpr(tmpRs32)));
- putIReg(rd, mkWidenFrom32(ty, mkexpr(tmpClz32), True));
- } else {
- t1 = newTemp(Ity_I1);
- assign(t1, binop(Iop_CmpEQ32, getIReg(rs), mkU32(0)));
- putIReg(rd, IRExpr_ITE(mkexpr(t1),
- mkU32(0x00000020),
- unop(Iop_Clz32, getIReg(rs))));
- }
- break;
- }
+ putDReg(fd, IRExpr_ITE(mkexpr(t1), getDReg(fs), getDReg(fd)));
+ break;
- case 0x21: { /* CLO */
- DIP("clo r%u, r%u", rd, rs);
- if (mode64) {
- IRTemp tmpClo32 = newTemp(Ity_I32);
- IRTemp tmpRs32 = newTemp(Ity_I32);
- assign(tmpRs32, mkNarrowTo32(ty, getIReg(rs)));
+ default:
+ return -1;
+ }
- t1 = newTemp(Ity_I1);
- assign(t1, binop(Iop_CmpEQ32, mkexpr(tmpRs32), mkU32(0xffffffff)));
- assign(tmpClo32, IRExpr_ITE(mkexpr(t1),
- mkU32(0x00000020),
- unop(Iop_Clz32, unop(Iop_Not32, mkexpr(tmpRs32)))));
+ break; /* MOVZ.fmt */
- putIReg(rd, mkWidenFrom32(ty, mkexpr(tmpClo32), True));
- break;
- } else {
- t1 = newTemp(Ity_I1);
- assign(t1, binop(Iop_CmpEQ32, getIReg(rs), mkU32(0xffffffff)));
- putIReg(rd, IRExpr_ITE(mkexpr(t1),
- mkU32(0x00000020),
- unop(Iop_Clz32,
- unop(Iop_Not32, getIReg(rs)))));
- break;
- }
- }
+ case 0x11: /* MOVT.fmt */
+ if (tf == 1) {
+ UInt mov_cc = get_mov_cc(cins);
- case 0x24: /* Count Leading Zeros in Doubleword - DCLZ; MIPS64 */
- DIP("dclz r%u, r%u", rd, rs);
- t1 = newTemp(Ity_I1);
- assign(t1, binop(Iop_CmpEQ64, getIReg(rs), mkU64(0)));
- putIReg(rd, IRExpr_ITE(mkexpr(t1),
- mkU64(0x00000040),
- unop(Iop_Clz64, getIReg(rs))));
- break;
+ switch (fmt) { /* MOVCF = 010001 */
+ case 0x11: /* D */
+ DIP("movt.d f%u, f%u, %u", fd, fs, mov_cc);
+ t1 = newTemp(Ity_I1);
+ t2 = newTemp(Ity_I32);
+ t3 = newTemp(Ity_I1);
+ t4 = newTemp(Ity_F64);
- case 0x25: /* Count Leading Ones in Doubleword - DCLO; MIPS64 */
- DIP("dclo r%u, r%u", rd, rs);
- t1 = newTemp(Ity_I1);
- assign(t1, binop(Iop_CmpEQ64, getIReg(rs),
- mkU64(0xffffffffffffffffULL)));
- putIReg(rd, IRExpr_ITE(mkexpr(t1),
- mkU64(0x40),
- unop(Iop_Clz64, unop(Iop_Not64,
- getIReg(rs)))));
- break;
+ assign(t1, binop(Iop_CmpEQ32, mkU32(0), mkU32(mov_cc)));
+ assign(t2, IRExpr_ITE(mkexpr(t1),
+ binop(Iop_And32,
+ binop(Iop_Shr32, getFCSR(),
+ mkU8(23)),
+ mkU32(0x1)),
+ binop(Iop_And32,
+ binop(Iop_Shr32, getFCSR(),
+ mkU8(24 + mov_cc)),
+ mkU32(0x1))
+ ));
+
+ assign(t3, binop(Iop_CmpEQ32, mkU32(1), mkexpr(t2)));
+ assign(t4, IRExpr_ITE(mkexpr(t3),
+ getDReg(fs), getDReg(fd)));
+ putDReg(fd, mkexpr(t4));
+ break;
- default:
- goto decode_failure;
- }
- break;
-
- case 0x1F: /* Special3 */
- switch (function) {
- case 0x01: {
- /* Doubleword Extract Bit Field - DEXTM; MIPS64r2 */
- msb = get_msb(cins);
- lsb = get_lsb(cins);
- size = msb + 1;
- UInt srcPos = lsb;
- UInt dstSz = msb + 33;
- t1 = newTemp(Ity_I64);
- DIP("dextm r%u, r%u, %u, %u", rt, rs, lsb, msb + 1);
+ case 0x10: /* S */
+ DIP("movt.s f%u, f%u, %u", fd, fs, mov_cc);
+ t1 = newTemp(Ity_I1);
+ t2 = newTemp(Ity_I32);
+ t3 = newTemp(Ity_I1);
+ t4 = newTemp(Ity_F64);
+ t5 = newTemp(Ity_F64);
+ t6 = newTemp(Ity_F64);
+ t7 = newTemp(Ity_I64);
+
+ if (fp_mode64) {
+ assign(t5, getFReg(fs));
+ assign(t6, getFReg(fd));
+ } else {
+ assign(t5, unop(Iop_F32toF64, getFReg(fs)));
+ assign(t6, unop(Iop_F32toF64, getFReg(fd)));
+ }
- UChar lsAmt = 64 - (srcPos + dstSz); /* left shift amount; */
- UChar rsAmt = 64 - dstSz; /* right shift amount; */
+ assign(t1, binop(Iop_CmpEQ32, mkU32(0), mkU32(mov_cc)));
+ assign(t2, IRExpr_ITE(mkexpr(t1),
+ binop(Iop_And32,
+ binop(Iop_Shr32, getFCSR(),
+ mkU8(23)),
+ mkU32(0x1)),
+ binop(Iop_And32,
+ binop(Iop_Shr32, getFCSR(),
+ mkU8(24 + mov_cc)),
+ mkU32(0x1))
+ ));
+
+ assign(t3, binop(Iop_CmpEQ32, mkU32(1), mkexpr(t2)));
+ assign(t4, IRExpr_ITE(mkexpr(t3),
+ mkexpr(t5), mkexpr(t6)));
+
+ if (fp_mode64) {
+ IRTemp f = newTemp(Ity_F64);
+ IRTemp fd_hi = newTemp(Ity_I32);
+ assign(f, getFReg(fd));
+ assign(fd_hi, unop(Iop_64HIto32,
+ unop(Iop_ReinterpF64asI64, mkexpr(f))));
+ assign(t7, mkWidenFrom32(Ity_I64, unop(Iop_64to32,
+ unop(Iop_ReinterpF64asI64, mkexpr(t4))),
+ True));
+
+ putFReg(fd, unop(Iop_ReinterpI64asF64, mkexpr(t7)));
+ } else
+ putFReg(fd, binop(Iop_F64toF32, get_IR_roundingmode(),
+ mkexpr(t4)));
- assign(t1, binop(Iop_Shl64, getIReg(rs), mkU8(lsAmt)));
- putIReg(rt, binop(Iop_Shr64, mkexpr(t1), mkU8(rsAmt)));
+ break;
- break;
- }
- case 0x02: {
- /* Doubleword Extract Bit Field Upper - DEXTU; MIPS64r2 */
- msb = get_msb(cins);
- lsb = get_lsb(cins);
- size = msb + 1;
- UInt srcPos = lsb + 32;
- UInt dstSz = msb + 1;
- DIP("dextu r%u, r%u, %u, %u", rt, rs, srcPos, dstSz);
- t1 = newTemp(Ity_I64);
+ default:
+ return -1;
+ }
+ } else if (tf == 0) { /* MOVF.fmt */
+ UInt mov_cc = get_mov_cc(cins);
+
+ switch (fmt) { /* MOVCF = 010001 */
+ case 0x11: /* D */
+ DIP("movf.d f%u, f%u, %u", fd, fs, mov_cc);
+ t1 = newTemp(Ity_I1);
+ t2 = newTemp(Ity_I32);
+ t3 = newTemp(Ity_I1);
+ t4 = newTemp(Ity_F64);
+
+ assign(t1, binop(Iop_CmpEQ32, mkU32(0), mkU32(mov_cc)));
+ assign(t2, IRExpr_ITE(mkexpr(t1),
+ binop(Iop_And32,
+ binop(Iop_Shr32, getFCSR(),
+ mkU8(23)),
+ mkU32(0x1)),
+ binop(Iop_And32,
+ binop(Iop_Shr32, getFCSR(),
+ mkU8(24 + mov_cc)),
+ mkU32(0x1))
+ ));
+
+ assign(t3, binop(Iop_CmpEQ32, mkU32(0), mkexpr(t2)));
+ assign(t4, IRExpr_ITE(mkexpr(t3),
+ getDReg(fs), getDReg(fd)));
+ putDReg(fd, mkexpr(t4));
+ break;
+
+ case 0x10: /* S */
+ DIP("movf.s f%u, f%u, %u", fd, fs, mov_cc);
+ t1 = newTemp(Ity_I1);
+ t2 = newTemp(Ity_I32);
+ t3 = newTemp(Ity_I1);
+ t4 = newTemp(Ity_F64);
+ t5 = newTemp(Ity_F64);
+ t6 = newTemp(Ity_F64);
+
+ if (fp_mode64) {
+ assign(t5, getFReg(fs));
+ assign(t6, getFReg(fd));
+ } else {
+ assign(t5, unop(Iop_F32toF64, getFReg(fs)));
+ assign(t6, unop(Iop_F32toF64, getFReg(fd)));
+ }
- vassert(srcPos >= 32 && srcPos < 64);
- vassert(dstSz > 0 && dstSz <= 32);
- vassert((srcPos + dstSz) > 32 && (srcPos + dstSz) <= 64);
+ assign(t1, binop(Iop_CmpEQ32, mkU32(0), mkU32(mov_cc)));
+ assign(t2, IRExpr_ITE(mkexpr(t1),
+ binop(Iop_And32,
+ binop(Iop_Shr32, getFCSR(),
+ mkU8(23)),
+ mkU32(0x1)),
+ binop(Iop_And32,
+ binop(Iop_Shr32, getFCSR(),
+ mkU8(24 + mov_cc)),
+ mkU32(0x1))
+ ));
+
+ assign(t3, binop(Iop_CmpEQ32, mkU32(0), mkexpr(t2)));
+ assign(t4, IRExpr_ITE(mkexpr(t3),
+ mkexpr(t5), mkexpr(t6)));
+
+ if (fp_mode64) {
+ IRTemp f = newTemp(Ity_F64);
+ IRTemp fd_hi = newTemp(Ity_I32);
+ t7 = newTemp(Ity_I64);
+ assign(f, getFReg(fd));
+ assign(fd_hi, unop(Iop_64HIto32,
+ unop(Iop_ReinterpF64asI64, mkexpr(f))));
+ assign(t7, mkWidenFrom32(Ity_I64, unop(Iop_64to32,
+ unop(Iop_ReinterpF64asI64, mkexpr(t4))),
+ True));
+
+ putFReg(fd, unop(Iop_ReinterpI64asF64, mkexpr(t7)));
+ } else
+ putFReg(fd, binop(Iop_F64toF32, get_IR_roundingmode(),
+ mkexpr(t4)));
- UChar lsAmt = 64 - (srcPos + dstSz); /* left shift amount; */
- UChar rsAmt = 64 - dstSz; /* right shift amount; */
+ break;
- assign(t1, binop(Iop_Shl64, getIReg(rs), mkU8(lsAmt)));
- putIReg(rt, binop(Iop_Shr64, mkexpr(t1), mkU8(rsAmt)));
- break;
- }
- case 0x05: {
- /* Doubleword Insert Bit Field Middle - DINSM; MIPS64r2 */
- msb = get_msb(cins);
- lsb = get_lsb(cins);
- size = msb + 1;
- UInt dstPos = lsb;
- UInt srcSz = msb - lsb + 33;
- t1 = newTemp(ty);
- t2 = newTemp(ty);
- t3 = newTemp(ty);
- t4 = newTemp(ty);
- IRTemp tmpT1 = newTemp(ty);
- IRTemp tmpT2 = newTemp(ty);
- IRTemp tmpT3 = newTemp(ty);
- IRTemp tmpT4 = newTemp(ty);
- IRTemp tmpT5 = newTemp(ty);
- IRTemp tmpT6 = newTemp(ty);
- IRTemp tmpT7 = newTemp(ty);
- IRTemp tmpRs = newTemp(ty);
- IRTemp tmpRt = newTemp(ty);
- IRTemp tmpRd = newTemp(ty);
-
- assign(tmpRs, getIReg(rs));
- assign(tmpRt, getIReg(rt));
- DIP("dinsm r%u, r%u, %u, %u", rt, rs, lsb, msb);
-
- UChar lsAmt = dstPos + srcSz - 1; /* left shift amount; */
- UChar rsAmt = dstPos + srcSz - 1; /* right shift amount; */
-
- assign(t1, binop(Iop_Shr64, mkexpr(tmpRt), mkU8(rsAmt)));
- assign(tmpT1, binop(Iop_Shr64, mkexpr(t1), mkU8(1)));
- assign(t2, binop(Iop_Shl64, mkexpr(tmpT1), mkU8(lsAmt)));
- assign(tmpT2, binop(Iop_Shl64, mkexpr(t2), mkU8(1)));
-
- lsAmt = 63 - dstPos; /* left shift amount; */
- rsAmt = 63 - dstPos; /* right shift amount; */
-
- assign(t3, binop(Iop_Shl64, mkexpr(tmpRt), mkU8(lsAmt)));
- assign(tmpT3, binop(Iop_Shl64, mkexpr(t3), mkU8(1)));
- assign(t4, binop(Iop_Shr64, mkexpr(tmpT3), mkU8(rsAmt)));
- assign(tmpT4, binop(Iop_Shr64, mkexpr(t4), mkU8(1)));
-
- /* extract size from src register */
- lsAmt = 64 - srcSz; /* left shift amount; */
- rsAmt = 64 - (lsb + srcSz); /* right shift amount; */
-
- assign(tmpT5, binop(Iop_Shl64, mkexpr(tmpRs), mkU8(lsAmt)));
- assign(tmpT6, binop(Iop_Shr64, mkexpr(tmpT5), mkU8(rsAmt)));
-
- assign(tmpT7, binop(Iop_Or64, mkexpr(tmpT2), mkexpr(tmpT4)));
- assign(tmpRd, binop(Iop_Or64, mkexpr(tmpT6), mkexpr(tmpT7)));
- putIReg(rt, mkexpr(tmpRd));
- break;
- }
- case 0x06: {
- /* Doubleword Insert Bit Field Upper - DINSU; MIPS64r2 */
- msb = get_msb(cins);
- lsb = get_lsb(cins);
- size = msb + 1;
- UInt dstPos = lsb + 32;
- UInt srcSz = msb - lsb + 1;
- IRTemp tmpT1 = newTemp(ty);
- IRTemp tmpT2 = newTemp(ty);
- IRTemp tmpT3 = newTemp(ty);
- IRTemp tmpT4 = newTemp(ty);
- IRTemp tmpT5 = newTemp(ty);
- IRTemp tmpT6 = newTemp(ty);
- IRTemp tmpT7 = newTemp(ty);
- IRTemp tmpT8 = newTemp(ty);
- IRTemp tmpT9 = newTemp(ty);
- IRTemp tmpRs = newTemp(ty);
- IRTemp tmpRt = newTemp(ty);
- IRTemp tmpRd = newTemp(ty);
-
- assign(tmpRs, getIReg(rs));
- assign(tmpRt, getIReg(rt));
- DIP("dinsu r%u, r%u, %u, %u", rt, rs, lsb, msb);
-
- UChar lsAmt = 64 - srcSz; /* left shift amount; */
- UChar rsAmt = 64 - (dstPos + srcSz); /* right shift amount; */
- assign(tmpT1, binop(Iop_Shl64, mkexpr(tmpRs), mkU8(lsAmt)));
- assign(tmpT2, binop(Iop_Shr64, mkexpr(tmpT1), mkU8(rsAmt)));
-
- lsAmt = 64 - dstPos; /* left shift amount; */
- rsAmt = 64 - dstPos; /* right shift amount; */
- assign(tmpT3, binop(Iop_Shl64, mkexpr(tmpRt), mkU8(lsAmt)));
- assign(tmpT4, binop(Iop_Shr64, mkexpr(tmpT3), mkU8(rsAmt)));
-
- lsAmt = dstPos; /* left shift amount; */
- rsAmt = srcSz; /* right shift amount; */
- assign(tmpT5, binop(Iop_Shr64, mkexpr(tmpRt), mkU8(rsAmt)));
- assign(tmpT6, binop(Iop_Shr64, mkexpr(tmpT5), mkU8(lsAmt)));
-
- assign(tmpT7, binop(Iop_Shl64, mkexpr(tmpT6), mkU8(rsAmt)));
- assign(tmpT8, binop(Iop_Shl64, mkexpr(tmpT7), mkU8(lsAmt)));
-
- assign(tmpT9, binop(Iop_Or64, mkexpr(tmpT8), mkexpr(tmpT4)));
- assign(tmpRd, binop(Iop_Or64, mkexpr(tmpT2), mkexpr(tmpT9)));
- putIReg(rt, mkexpr(tmpRd));
- break;
- }
- case 0x07: {
- /* Doubleword Insert Bit Field - DINS; MIPS64r2 */
- IRTemp tmp1 = newTemp(ty);
- IRTemp tmpT1 = newTemp(ty);
- IRTemp tmpT2 = newTemp(ty);
- IRTemp tmpT3 = newTemp(ty);
- IRTemp tmpT4 = newTemp(ty);
- IRTemp tmpT5 = newTemp(ty);
- IRTemp tmpT6 = newTemp(ty);
- IRTemp tmpT7 = newTemp(ty);
- IRTemp tmpT8 = newTemp(ty);
- IRTemp tmpT9 = newTemp(ty);
- IRTemp tmp = newTemp(ty);
- IRTemp tmpRs = newTemp(ty);
- IRTemp tmpRt = newTemp(ty);
- IRTemp tmpRd = newTemp(ty);
-
- assign(tmpRs, getIReg(rs));
- assign(tmpRt, getIReg(rt));
-
- msb = get_msb(cins);
- lsb = get_lsb(cins);
- size = msb + 1;
- DIP("dins r%u, r%u, %u, %u", rt, rs, lsb,
- msb - lsb + 1);
- UChar lsAmt = 63 - lsb; /* left shift amount; */
- UChar rsAmt = 63 - lsb; /* right shift amount; */
- assign(tmp, binop(Iop_Shl64, mkexpr(tmpRt), mkU8(lsAmt)));
- assign(tmpT1, binop(Iop_Shl64, mkexpr(tmp), mkU8(1)));
- assign(tmp1, binop(Iop_Shr64, mkexpr(tmpT1), mkU8(rsAmt)));
- assign(tmpT2, binop(Iop_Shr64, mkexpr(tmp1), mkU8(1)));
-
- lsAmt = msb; /* left shift amount; */
- rsAmt = 1; /*right shift amount; */
- assign(tmpT3, binop(Iop_Shr64, mkexpr(tmpRt), mkU8(rsAmt)));
- assign(tmpT4, binop(Iop_Shr64, mkexpr(tmpT3), mkU8(lsAmt)));
- assign(tmpT5, binop(Iop_Shl64, mkexpr(tmpT4), mkU8(rsAmt)));
- assign(tmpT6, binop(Iop_Shl64, mkexpr(tmpT5), mkU8(lsAmt)));
-
- lsAmt = 64 - (msb - lsb + 1); /* left shift amount; */
- rsAmt = 64 - (msb + 1); /* right shift amount; */
- assign(tmpT7, binop(Iop_Shl64, mkexpr(tmpRs), mkU8(lsAmt)));
- assign(tmpT8, binop(Iop_Shr64, mkexpr(tmpT7), mkU8(rsAmt)));
-
- assign(tmpT9, binop(Iop_Or64, mkexpr(tmpT2), mkexpr(tmpT8)));
- assign(tmpRd, binop(Iop_Or64, mkexpr(tmpT6), mkexpr(tmpT9)));
- putIReg(rt, mkexpr(tmpRd));
- break;
- }
- case 0x24: /* DBSHFL */
- lsb = get_lsb(cins);
- IRTemp tmpRs = newTemp(ty);
- IRTemp tmpRt = newTemp(ty);
- IRTemp tmpRd = newTemp(ty);
- assign(tmpRs, getIReg(rs));
- assign(tmpRt, getIReg(rt));
- switch (lsb) {
- case 0x02: { /* DSBH */
- DIP("dsbh r%u, r%u", rd, rt);
- IRTemp tmpT1 = newTemp(ty);
- IRTemp tmpT2 = newTemp(ty);
- IRTemp tmpT3 = newTemp(ty);
- IRTemp tmpT4 = newTemp(ty);
- IRTemp tmpT5 = newTemp(Ity_I64);
- IRTemp tmpT6 = newTemp(ty);
- assign(tmpT5, mkU64(0xFF00FF00FF00FF00ULL));
- assign(tmpT6, mkU64(0x00FF00FF00FF00FFULL));
- assign(tmpT1, binop(Iop_And64, mkexpr(tmpRt), mkexpr(tmpT5)));
- assign(tmpT2, binop(Iop_Shr64, mkexpr(tmpT1), mkU8(8)));
- assign(tmpT3, binop(Iop_And64, mkexpr(tmpRt), mkexpr(tmpT6)));
- assign(tmpT4, binop(Iop_Shl64, mkexpr(tmpT3), mkU8(8)));
- assign(tmpRd, binop(Iop_Or64, mkexpr(tmpT4), mkexpr(tmpT2)));
- putIReg(rd, mkexpr(tmpRd));
- break;
- }
- case 0x05: { /* DSHD */
- DIP("dshd r%u, r%u\n", rd, rt);
- IRTemp tmpT1 = newTemp(ty);
- IRTemp tmpT2 = newTemp(ty);
- IRTemp tmpT3 = newTemp(ty);
- IRTemp tmpT4 = newTemp(ty);
- IRTemp tmpT5 = newTemp(Ity_I64);
- IRTemp tmpT6 = newTemp(ty);
- IRTemp tmpT7 = newTemp(ty);
- IRTemp tmpT8 = newTemp(ty);
- IRTemp tmpT9 = newTemp(ty);
- assign(tmpT5, mkU64(0xFFFF0000FFFF0000ULL));
- assign(tmpT6, mkU64(0x0000FFFF0000FFFFULL));
- assign(tmpT1, binop(Iop_And64, mkexpr(tmpRt), mkexpr(tmpT5)));
- assign(tmpT2, binop(Iop_Shr64, mkexpr(tmpT1), mkU8(16)));
- assign(tmpT3, binop(Iop_And64, mkexpr(tmpRt), mkexpr(tmpT6)));
- assign(tmpT4, binop(Iop_Shl64, mkexpr(tmpT3), mkU8(16)));
- assign(tmpT7, binop(Iop_Or64, mkexpr(tmpT4), mkexpr(tmpT2)));
- assign(tmpT8, binop(Iop_Shl64, mkexpr(tmpT7), mkU8(32)));
- assign(tmpT9, binop(Iop_Shr64, mkexpr(tmpT7), mkU8(32)));
- assign(tmpRd, binop(Iop_Or64, mkexpr(tmpT8), mkexpr(tmpT9)));
- putIReg(rd, mkexpr(tmpRd));
- break;
- }
- case 0x08 ... 0x0f: { /* DALIGN */
- if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
- DIP("daling r%u, r%u, r%u, %u", rd, rs, rt, lsb & 0x7);
- UInt bp = (lsb & 0x7) << 3;
- if (bp) {
- putIReg(rd, binop(Iop_Or64,
- binop(Iop_Shl64, getIReg(rt), mkU8(bp)),
- binop(Iop_Shr64,
- getIReg(rs), mkU8(64 - bp))));
- } else
- putIReg(rd, getIReg(rt));
- } else {
- ILLEGAL_INSTRUCTON;
+ default:
+ return -1;
+ }
}
- break;
- }
- case 0: /* DBITSWAP */
- if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
- DIP("dbitswap r%u, r%u", rd, rt);
- putIReg(rd, qop(Iop_Rotx64, getIReg(rt), mkU8(7), mkU8(8), mkU8(1)));
- } else {
- ILLEGAL_INSTRUCTON;
- }
- break;
- default:
- vex_printf("\nop6o10 = %u", lsb);
- goto decode_failure;;
- }
- break;
- case 0x3B: /* RDHWR */
- DIP("rdhwr r%u, r%u", rt, rd);
- if (VEX_MIPS_CPU_HAS_MIPS32R2(archinfo->hwcaps) ||
- VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps) ||
- (VEX_MIPS_COMP_ID(archinfo->hwcaps) == VEX_PRID_COMP_BROADCOM)) {
- if (rd == 29) {
- putIReg(rt, getULR());
- } else if (rd <= 3
- || (rd == 31
- && VEX_MIPS_COMP_ID(archinfo->hwcaps)
- == VEX_PRID_COMP_CAVIUM)) {
- IRExpr** arg = mkIRExprVec_1(mkU32(rd));
- IRTemp val = newTemp(ty);
- IRDirty *d = unsafeIRDirty_1_N(val,
- 0,
- "mips_dirtyhelper_rdhwr",
- &mips_dirtyhelper_rdhwr,
- arg);
- stmt(IRStmt_Dirty(d));
- putIReg(rt, mkexpr(val));
- } else
- goto decode_failure;
- } else {
- ILLEGAL_INSTRUCTON;
- }
- break;
- case 0x04: /* INS */
- msb = get_msb(cins);
- lsb = get_lsb(cins);
- size = msb - lsb + 1;
- DIP("ins size:%u msb:%u lsb:%u", size, msb, lsb);
+ break; /* MOVT.fmt */
- vassert(lsb + size <= 32);
- vassert(lsb + size > 0);
+ case 0x00: /* ADD.fmt */
+ switch (fmt) {
+ case 0x10: { /* S */
+ DIP("add.s f%u, f%u, f%u", fd, fs, ft);
+ calculateFCSR(fs, ft, ADDS, True, 2);
+ IRExpr *rm = get_IR_roundingmode();
+ putFReg(fd, mkWidenFromF32(tyF, triop(Iop_AddF32, rm,
+ getLoFromF64(tyF, getFReg(fs)),
+ getLoFromF64(tyF, getFReg(ft)))));
+ break;
+ }
- /* put size bits from rs at the pos in temporary */
- t0 = newTemp(Ity_I32);
- t3 = newTemp(Ity_I32);
- /* shift left for 32 - size to clear leading bits and get zeros
- at the end */
- assign(t0, binop(Iop_Shl32, mkNarrowTo32(ty, getIReg(rs)),
- mkU8(32 - size)));
- /* now set it at pos */
- t1 = newTemp(Ity_I32);
- assign(t1, binop(Iop_Shr32, mkexpr(t0), mkU8(32 - size - lsb)));
+ case 0x11: { /* D */
+ DIP("add.d f%u, f%u, f%u", fd, fs, ft);
+ calculateFCSR(fs, ft, ADDD, False, 2);
+ IRExpr *rm = get_IR_roundingmode();
+ putDReg(fd, triop(Iop_AddF64, rm, getDReg(fs), getDReg(ft)));
+ break;
+ }
- if (lsb > 0) {
- t2 = newTemp(Ity_I32);
- /* clear everything but lower pos bits from rt */
- assign(t2, binop(Iop_Shl32, mkNarrowTo32(ty, getIReg(rt)),
- mkU8(32 - lsb)));
- assign(t3, binop(Iop_Shr32, mkexpr(t2), mkU8(32 - lsb)));
- } else
- assign(t3, mkU32(0));
+ case 0x04: /* MTC1 (Move Word to Floating Point) */
+ DIP("mtc1 r%u, f%u", rt, fs);
- if (msb < 31) {
- t4 = newTemp(Ity_I32);
- /* clear everything but upper msb + 1 bits from rt */
- assign(t4, binop(Iop_Shr32, mkNarrowTo32(ty, getIReg(rt)),
- mkU8(msb + 1)));
- t5 = newTemp(Ity_I32);
- assign(t5, binop(Iop_Shl32, mkexpr(t4), mkU8(msb + 1)));
+ if (fp_mode64) {
+ t0 = newTemp(Ity_I32);
+ t1 = newTemp(Ity_F32);
+ assign(t0, mkNarrowTo32(ty, getIReg(rt)));
+ assign(t1, unop(Iop_ReinterpI32asF32, mkexpr(t0)));
- /* now combine these registers */
- if (lsb > 0) {
- t6 = newTemp(Ity_I32);
- assign(t6, binop(Iop_Or32, mkexpr(t5), mkexpr(t1)));
- putIReg(rt, mkWidenFrom32(ty, binop(Iop_Or32, mkexpr(t6),
- mkexpr(t3)), True));
- } else {
- putIReg(rt, mkWidenFrom32(ty, binop(Iop_Or32, mkexpr(t1),
- mkexpr(t5)), True));
- }
- } else {
- putIReg(rt, mkWidenFrom32(ty, binop(Iop_Or32, mkexpr(t1),
- mkexpr(t3)), True));
- }
- break;
+ putFReg(fs, mkWidenFromF32(tyF, mkexpr(t1)));
+ } else
+ putFReg(fs, unop(Iop_ReinterpI32asF32,
+ mkNarrowTo32(ty, getIReg(rt))));
- case 0x00: /* EXT */
- msb = get_msb(cins);
- lsb = get_lsb(cins);
- size = msb + 1;
- DIP("ext size:%u msb:%u lsb:%u", size, msb, lsb);
- vassert(lsb + size <= 32);
- vassert(lsb + size > 0);
- /* put size bits from rs at the top of in temporary */
- if (lsb + size < 32) {
- t0 = newTemp(Ity_I32);
- assign(t0, binop(Iop_Shl32, mkNarrowTo32(ty, getIReg(rs)),
- mkU8(32 - lsb - size)));
+ break;
- putIReg(rt, mkWidenFrom32(ty, binop(Iop_Shr32, mkexpr(t0),
- mkU8(32 - size)), True));
- } else {
- putIReg(rt, mkWidenFrom32(ty, binop(Iop_Shr32,
- mkNarrowTo32(ty, getIReg(rs)),
- mkU8(32 - size)), True));
- }
- break;
+ case 0x05: /* Doubleword Move to Floating Point DMTC1; MIPS64 */
+ DIP("dmtc1 r%u, f%u", rt, fs);
+ vassert(mode64);
+ putDReg(fs, unop(Iop_ReinterpI64asF64, getIReg(rt)));
+ break;
- case 0x03: /* Doubleword Extract Bit Field - DEXT; MIPS64r2 */
- msb = get_msb(cins);
- lsb = get_lsb(cins);
- size = msb + 1;
- DIP("dext r%u, r%u, %u, %u", rt, rs, lsb, msb + 1);
- t1 = newTemp(Ity_I64);
- vassert(lsb >= 0 && lsb < 32);
- vassert(size > 0 && size <= 32);
- vassert((lsb + size) > 0 && (lsb + size) <= 63);
+ case 0x00: /* MFC1 */
+ DIP("mfc1 r%u, f%u", rt, fs);
- UChar lsAmt = 63 - (lsb + msb); /* left shift amount; */
- UChar rsAmt = 63 - msb; /* right shift amount; */
+ if (fp_mode64) {
+ t0 = newTemp(Ity_I64);
+ t1 = newTemp(Ity_I32);
+ assign(t0, unop(Iop_ReinterpF64asI64, getFReg(fs)));
+ assign(t1, unop(Iop_64to32, mkexpr(t0)));
+ putIReg(rt, mkWidenFrom32(ty, mkexpr(t1), True));
+ } else
+ putIReg(rt, mkWidenFrom32(ty,
+ unop(Iop_ReinterpF32asI32, getFReg(fs)),
+ True));
- assign(t1, binop(Iop_Shl64, getIReg(rs), mkU8(lsAmt)));
- putIReg(rt, binop(Iop_Shr64, mkexpr(t1), mkU8(rsAmt)));
+ break;
- break;
+ case 0x01: /* Doubleword Move from Floating Point DMFC1;
+ MIPS64 */
+ DIP("dmfc1 r%u, f%u", rt, fs);
+ putIReg(rt, unop(Iop_ReinterpF64asI64, getDReg(fs)));
+ break;
- case 0x20: /* BSHFL */
- switch (sa) {
- case 0x0: /* BITSWAP */
- if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
- DIP("bitswap r%u, r%u", rd, rt);
- if (mode64) {
- putIReg(rd, unop(Iop_32Uto64, qop(Iop_Rotx32, unop(Iop_64to32, getIReg(rt)),
- mkU8(7), mkU8(8), mkU8(1))));
- } else {
- putIReg(rd, qop(Iop_Rotx32, getIReg(rt), mkU8(7),
- mkU8(8), mkU8(1)));
- }
- } else {
- ILLEGAL_INSTRUCTON;
+ case 0x06: /* CTC1 */
+ DIP("ctc1 r%u, f%u", rt, fs);
+ t0 = newTemp(Ity_I32);
+ t1 = newTemp(Ity_I32);
+ t2 = newTemp(Ity_I32);
+ t3 = newTemp(Ity_I32);
+ t4 = newTemp(Ity_I32);
+ t5 = newTemp(Ity_I32);
+ t6 = newTemp(Ity_I32);
+ assign(t0, mkNarrowTo32(ty, getIReg(rt)));
+
+ if (fs == 25) { /* FCCR */
+ assign(t1, binop(Iop_Shl32, binop(Iop_And32, mkexpr(t0),
+ mkU32(0x000000FE)), mkU8(24)));
+ assign(t2, binop(Iop_And32, mkexpr(t0),
+ mkU32(0x01000000)));
+ assign(t3, binop(Iop_Shl32, binop(Iop_And32, mkexpr(t0),
+ mkU32(0x00000001)), mkU8(23)));
+ assign(t4, binop(Iop_And32, mkexpr(t0),
+ mkU32(0x007FFFFF)));
+ putFCSR(binop(Iop_Or32, binop(Iop_Or32, mkexpr(t1),
+ mkexpr(t2)), binop(Iop_Or32, mkexpr(t3),
+ mkexpr(t4))));
+ } else if (fs == 26) { /* FEXR */
+ assign(t1, binop(Iop_And32, getFCSR(), mkU32(0xFFFC0000)));
+ assign(t2, binop(Iop_And32, mkexpr(t0),
+ mkU32(0x0003F000)));
+ assign(t3, binop(Iop_And32, getFCSR(), mkU32(0x00000F80)));
+ assign(t4, binop(Iop_And32, mkexpr(t0),
+ mkU32(0x0000007C)));
+ assign(t5, binop(Iop_And32, getFCSR(), mkU32(0x00000003)));
+ putFCSR(binop(Iop_Or32, binop(Iop_Or32, binop(Iop_Or32,
+ mkexpr(t1), mkexpr(t2)), binop(Iop_Or32,
+ mkexpr(t3), mkexpr(t4))), mkexpr(t5)));
+ } else if (fs == 28) {
+ assign(t1, binop(Iop_And32, getFCSR(), mkU32(0xFE000000)));
+ assign(t2, binop(Iop_Shl32, binop(Iop_And32, mkexpr(t0),
+ mkU32(0x00000002)), mkU8(22)));
+ assign(t3, binop(Iop_And32, getFCSR(), mkU32(0x00FFF000)));
+ assign(t4, binop(Iop_And32, mkexpr(t0),
+ mkU32(0x00000F80)));
+ assign(t5, binop(Iop_And32, getFCSR(), mkU32(0x0000007C)));
+ assign(t6, binop(Iop_And32, mkexpr(t0),
+ mkU32(0x00000003)));
+ putFCSR(binop(Iop_Or32, binop(Iop_Or32, binop(Iop_Or32,
+ mkexpr(t1), mkexpr(t2)), binop(Iop_Or32,
+ mkexpr(t3), mkexpr(t4))), binop(Iop_Or32,
+ mkexpr(t5), mkexpr(t6))));
+ } else if (fs == 31) {
+ putFCSR(mkexpr(t0));
+ }
+
+ break;
+
+ case 0x02: /* CFC1 */
+ DIP("cfc1 r%u, f%u", rt, fs);
+ t0 = newTemp(Ity_I32);
+ t1 = newTemp(Ity_I32);
+ t2 = newTemp(Ity_I32);
+ t3 = newTemp(Ity_I32);
+ t4 = newTemp(Ity_I32);
+ t5 = newTemp(Ity_I32);
+ t6 = newTemp(Ity_I32);
+ assign(t0, getFCSR());
+
+ if (fs == 0) {
+ putIReg(rt, mkWidenFrom32(ty,
+ IRExpr_Get(offsetof(VexGuestMIPS32State,
+ guest_FIR),
+ Ity_I32),
+ False));
+ } else if (fs == 25) {
+ assign(t1, mkU32(0x000000FF));
+ assign(t2, binop(Iop_Shr32, binop(Iop_And32, mkexpr(t0),
+ mkU32(0xFE000000)), mkU8(25)));
+ assign(t3, binop(Iop_Shr32, binop(Iop_And32, mkexpr(t0),
+ mkU32(0x00800000)), mkU8(23)));
+ putIReg(rt, mkWidenFrom32(ty, binop(Iop_Or32,
+ binop(Iop_Or32, mkexpr(t1), mkexpr(t2)),
+ mkexpr(t3)), False));
+ } else if (fs == 26) {
+ assign(t1, mkU32(0xFFFFF07C));
+ assign(t2, binop(Iop_And32, mkexpr(t0),
+ mkU32(0x0003F000)));
+ assign(t3, binop(Iop_And32, mkexpr(t0),
+ mkU32(0x0000007C)));
+ putIReg(rt, mkWidenFrom32(ty, binop(Iop_Or32,
+ binop(Iop_Or32, mkexpr(t1), mkexpr(t2)),
+ mkexpr(t3)), False));
+ } else if (fs == 28) {
+ assign(t1, mkU32(0x00000F87));
+ assign(t2, binop(Iop_And32, mkexpr(t0),
+ mkU32(0x00000F83)));
+ assign(t3, binop(Iop_Shr32, binop(Iop_And32, mkexpr(t0),
+ mkU32(0x01000000)), mkU8(22)));
+ putIReg(rt, mkWidenFrom32(ty, binop(Iop_Or32,
+ binop(Iop_Or32, mkexpr(t1), mkexpr(t2)),
+ mkexpr(t3)), False));
+ } else if (fs == 31) {
+ putIReg(rt, mkWidenFrom32(ty, getFCSR(), False));
+ }
+
+ break;
+
+ default:
+ return -1;
}
- break;
- case 0x02: /* WSBH */
- DIP("wsbh r%u, r%u", rd, rt);
- t0 = newTemp(Ity_I32);
- t1 = newTemp(Ity_I32);
- t2 = newTemp(Ity_I32);
- t3 = newTemp(Ity_I32);
- assign(t0, binop(Iop_Shl32, binop(Iop_And32, mkNarrowTo32(ty,
- getIReg(rt)), mkU32(0x00FF0000)),
- mkU8(0x8)));
- assign(t1, binop(Iop_Shr32, binop(Iop_And32, mkNarrowTo32(ty,
- getIReg(rt)), mkU32(0xFF000000)), mkU8(0x8)));
- assign(t2, binop(Iop_Shl32, binop(Iop_And32, mkNarrowTo32(ty,
- getIReg(rt)), mkU32(0x000000FF)), mkU8(0x8)));
- assign(t3, binop(Iop_Shr32, binop(Iop_And32, mkNarrowTo32(ty,
- getIReg(rt)), mkU32(0x0000FF00)), mkU8(0x8)));
- putIReg(rd, mkWidenFrom32(ty, binop(Iop_Or32, binop(Iop_Or32,
- mkexpr(t0), mkexpr(t1)),
- binop(Iop_Or32, mkexpr(t2),
- mkexpr(t3))), True));
- break;
+ break;
- case 0x10: /* SEB */
- DIP("seb r%u, r%u", rd, rt);
- if (mode64)
- putIReg(rd, unop(Iop_8Sto64, unop(Iop_64to8, getIReg(rt))));
- else
- putIReg(rd, unop(Iop_8Sto32, unop(Iop_32to8, getIReg(rt))));
- break;
+ case 0x21: /* CVT.D */
+ switch (fmt) {
+ case 0x10: /* S */
+ DIP("cvt.d.s f%u, f%u", fd, fs);
+ calculateFCSR(fs, 0, CVTDS, True, 1);
- case 0x18: /* SEH */
- DIP("seh r%u, r%u", rd, rt);
- if (mode64)
- putIReg(rd, unop(Iop_16Sto64, unop(Iop_64to16, getIReg(rt))));
- else
- putIReg(rd, unop(Iop_16Sto32, unop(Iop_32to16, getIReg(rt))));
- break;
+ if (fp_mode64) {
+ t0 = newTemp(Ity_I64);
+ t1 = newTemp(Ity_I32);
+ t3 = newTemp(Ity_F32);
+ t4 = newTemp(Ity_F32);
+ /* get lo half of FPR */
+ assign(t0, unop(Iop_ReinterpF64asI64, getFReg(fs)));
- case 0x08 ... 0x0b: /* ALIGN */
- if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
- if (mode64) {
- UInt bp = (sa & 0x3) << 3;
- if (bp) {
- putIReg(rd, unop(Iop_32Sto64,
- binop(Iop_Or32,
- binop(Iop_Shl32,
- unop(Iop_64to32,
- getIReg(rt)),
- mkU8(bp)),
- binop(Iop_Shr32,
- unop(Iop_64to32,
- getIReg(rs)),
- mkU8(32 - bp)))));
+ assign(t1, unop(Iop_64to32, mkexpr(t0)));
+
+ assign(t3, unop(Iop_ReinterpI32asF32, mkexpr(t1)));
+
+ putFReg(fd, unop(Iop_F32toF64, mkexpr(t3)));
} else
- putIReg(rd, getIReg(rt));
- } else {
- UInt bp = (sa & 0x3) << 3;
- if (bp) {
- putIReg(rd, binop(Iop_Or32,
- binop(Iop_Shl32,
- getIReg(rt), mkU8(bp)),
- binop(Iop_Shr32,
- getIReg(rs), mkU8(32 - bp))));
+ putDReg(fd, unop(Iop_F32toF64, getFReg(fs)));
+
+ break;
+
+ case 0x14: /* W */
+ DIP("cvt.d.w %u, %u", fd, fs);
+ calculateFCSR(fs, 0, CVTDW, True, 1);
+
+ if (fp_mode64) {
+ t0 = newTemp(Ity_I64);
+ t1 = newTemp(Ity_I32);
+ t3 = newTemp(Ity_F32);
+ t4 = newTemp(Ity_F32);
+ /* get lo half of FPR */
+ assign(t0, unop(Iop_ReinterpF64asI64, getFReg(fs)));
+
+ assign(t1, unop(Iop_64to32, mkexpr(t0)));
+ putDReg(fd, unop(Iop_I32StoF64, mkexpr(t1)));
+ break;
+ } else {
+ t0 = newTemp(Ity_I32);
+ assign(t0, unop(Iop_ReinterpF32asI32, getFReg(fs)));
+ putDReg(fd, unop(Iop_I32StoF64, mkexpr(t0)));
+ break;
+ }
+
+ case 0x15: { /* L */
+ if (fp_mode64) {
+ DIP("cvt.d.l %u, %u", fd, fs);
+ calculateFCSR(fs, 0, CVTDL, False, 1);
+ t0 = newTemp(Ity_I64);
+ assign(t0, unop(Iop_ReinterpF64asI64, getFReg(fs)));
+
+ putFReg(fd, binop(Iop_I64StoF64,
+ get_IR_roundingmode(), mkexpr(t0)));
+ break;
} else
- putIReg(rd, getIReg(rt));
+ return -1;
}
- } else {
- ILLEGAL_INSTRUCTON;
+
+ default:
+ return -1;
}
- break;
- default:
- goto decode_failure;
+ break; /* CVT.D */
- }
- break; /* BSHFL */
+ case 0x20: /* CVT.s */
+ switch (fmt) {
+ case 0x14: /* W */
+ DIP("cvt.s.w %u, %u", fd, fs);
+ calculateFCSR(fs, 0, CVTSW, True, 1);
+
+ if (fp_mode64) {
+ t0 = newTemp(Ity_I64);
+ t1 = newTemp(Ity_I32);
+ t3 = newTemp(Ity_F32);
+ t4 = newTemp(Ity_F32);
+ /* get lo half of FPR */
+ assign(t0, unop(Iop_ReinterpF64asI64, getFReg(fs)));
+
+ assign(t1, unop(Iop_64to32, mkexpr(t0)));
+ putFReg(fd, mkWidenFromF32(tyF, binop(Iop_I32StoF32,
+ get_IR_roundingmode(), mkexpr(t1))));
+ } else {
+ t0 = newTemp(Ity_I32);
+ assign(t0, unop(Iop_ReinterpF32asI32, getFReg(fs)));
+ putFReg(fd, binop(Iop_I32StoF32, get_IR_roundingmode(),
+ mkexpr(t0)));
+ }
- /* --- MIPS32(r2) DSP ASE(r2) / Cavium Specfic (LX) instructions --- */
- case 0xA: /* LX */
- if (VEX_MIPS_COMP_ID(archinfo->hwcaps) == VEX_PRID_COMP_CAVIUM) {
- if (dis_instr_CVM(cins))
- break;
- goto decode_failure;
- }
- /* fallthrough */
- case 0xC: /* INSV */
- case 0x38: { /* EXTR.W */
- if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
- UInt retVal = disDSPInstr_MIPS_WRK ( cins );
- if (0 != retVal ) {
- goto decode_failure_dsp;
- }
- break;
- } else {
- goto decode_failure_dsp;
- }
- break;
- }
- case 0x10: { /* ADDU.QB */
- switch(sa) {
- case 0xC: /* SUBU_S.PH */
- case 0xD: /* ADDU_S.PH */
- case 0x1E: { /* MULQ_S.PH */
- if (VEX_MIPS_PROC_DSP2(archinfo->hwcaps)) {
- UInt retVal = disDSPInstr_MIPS_WRK ( cins );
- if (0 != retVal ) {
- goto decode_failure_dsp;
- }
- break;
- } else {
- goto decode_failure_dsp;
- }
- break;
- }
- default: {
- if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
- UInt retVal = disDSPInstr_MIPS_WRK ( cins );
- if (0 != retVal ) {
- goto decode_failure_dsp;
- }
- break;
- } else {
- goto decode_failure_dsp;
- }
- break;
- }
- }
- break;
- }
- case 0x11: { /* CMPU.EQ.QB */
- switch(sa) {
- case 0x18: /* CMPGDU.EQ.QB */
- case 0x19: /* CMPGDU.LT.QB */
- case 0x1A: /* CMPGDU.LE.QB */
- case 0x0D: /* PRECR.QB.PH */
- case 0x1E: /* PRECR_SRA.PH.W */
- case 0x1F: { /* PRECR_SRA_R.PH.W */
- if (VEX_MIPS_PROC_DSP2(archinfo->hwcaps)) {
- UInt retVal = disDSPInstr_MIPS_WRK ( cins );
- if (0 != retVal ) {
- goto decode_failure_dsp;
- }
- break;
- } else {
- goto decode_failure_dsp;
- }
- break;
- }
- default: {
- if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
- UInt retVal = disDSPInstr_MIPS_WRK ( cins );
- if (0 != retVal ) {
- goto decode_failure_dsp;
+ break;
+
+ case 0x11: /* D */
+ DIP("cvt.s.d %u, %u", fd, fs);
+ calculateFCSR(fs, 0, CVTSD, False, 1);
+ t0 = newTemp(Ity_F32);
+ assign(t0, binop(Iop_F64toF32, get_IR_roundingmode(),
+ getDReg(fs)));
+ putFReg(fd, mkWidenFromF32(tyF, mkexpr(t0)));
+ break;
+
+ case 0x15: /* L */
+ DIP("cvt.s.l %u, %u", fd, fs);
+
+ if (fp_mode64) {
+ calculateFCSR(fs, 0, CVTSL, False, 1);
+ t0 = newTemp(Ity_I64);
+ assign(t0, unop(Iop_ReinterpF64asI64, getFReg(fs)));
+
+ putFReg(fd, mkWidenFromF32(tyF, binop(Iop_I64StoF32,
+ get_IR_roundingmode(), mkexpr(t0))));
+ } else {
+ ILLEGAL_INSTRUCTON
+ }
+
+ break;
+
+ default:
+ return -1;
}
- break;
- } else {
- goto decode_failure_dsp;
- }
- break;
- }
- }
- break;
- }
- case 0x12: { /* ABSQ_S.PH */
- switch(sa){
- case 0x1: { /* ABSQ_S.QB */
- if (VEX_MIPS_PROC_DSP2(archinfo->hwcaps)) {
- UInt retVal = disDSPInstr_MIPS_WRK ( cins );
- if (0 != retVal ) {
- goto decode_failure_dsp;
+
+ break; /* CVT.s */
+
+ case 0x24: /* CVT.w */
+ switch (fmt) {
+ case 0x10: /* S */
+ DIP("cvt.w.s %u, %u", fd, fs);
+ calculateFCSR(fs, 0, CVTWS, True, 1);
+ putFReg(fd,
+ mkWidenFromF32(tyF,
+ unop(Iop_ReinterpI32asF32,
+ binop(Iop_F32toI32S,
+ get_IR_roundingmode(),
+ getLoFromF64(tyF,
+ getFReg(fs))))));
+ break;
+
+ case 0x11: /* D */
+ DIP("cvt.w.d %u, %u", fd, fs);
+ calculateFCSR(fs, 0, CVTWD, False, 1);
+ t0 = newTemp(Ity_I32);
+ t1 = newTemp(Ity_F32);
+ assign(t0, binop(Iop_F64toI32S, get_IR_roundingmode(),
+ getDReg(fs)));
+ assign(t1, unop(Iop_ReinterpI32asF32, mkexpr(t0)));
+ putFReg(fd, mkWidenFromF32(tyF, mkexpr(t1)));
+ break;
+
+ default:
+ return -1;
+
}
+
break;
- } else {
- goto decode_failure_dsp;
- }
- break;
- }
- default: {
- if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
- UInt retVal = disDSPInstr_MIPS_WRK ( cins );
- if (0 != retVal ) {
- goto decode_failure_dsp;
+
+ case 0x25: /* CVT.l */
+ switch (fmt) {
+ case 0x10: /* S */
+ DIP("cvt.l.s %u, %u", fd, fs);
+
+ if (fp_mode64) {
+ calculateFCSR(fs, 0, CVTLS, True, 1);
+ t0 = newTemp(Ity_I64);
+
+ assign(t0, binop(Iop_F32toI64S, get_IR_roundingmode(),
+ getLoFromF64(tyF, getFReg(fs))));
+
+ putDReg(fd, unop(Iop_ReinterpI64asF64, mkexpr(t0)));
+ } else {
+ ILLEGAL_INSTRUCTON
+ }
+
+ break;
+
+ case 0x11: { /* D */
+ DIP("cvt.l.d %u, %u", fd, fs);
+
+ if (fp_mode64) {
+ calculateFCSR(fs, 0, CVTLD, False, 1);
+ putDReg(fd, unop(Iop_ReinterpI64asF64,
+ binop(Iop_F64toI64S,
+ get_IR_roundingmode(),
+ getDReg(fs))));
+ } else {
+ ILLEGAL_INSTRUCTON
+ }
+
+ break;
+ }
+
+ default:
+ return -1;
}
+
break;
- } else {
- goto decode_failure_dsp;
- }
- break;
- }
- }
- break;
- }
- case 0x13: { /* SHLL.QB */
- switch(sa) {
- case 0x04: /* SHRA.QB */
- case 0x05: /* SHRA_R.QB */
- case 0x06: /* SHRAV.QB */
- case 0x07: /* SHRAV_R.QB */
- case 0x19: /* SHLR.PH */
- case 0x1B: { /* SHLRV.PH */
- if (VEX_MIPS_PROC_DSP2(archinfo->hwcaps)) {
- UInt retVal = disDSPInstr_MIPS_WRK ( cins );
- if (0 != retVal ) {
- goto decode_failure_dsp;
+
+ case 0x0B: /* FLOOR.L.fmt */
+ switch (fmt) {
+ case 0x10: /* S */
+ DIP("floor.l.s %u, %u", fd, fs);
+
+ if (fp_mode64) {
+ calculateFCSR(fs, 0, FLOORLS, True, 1);
+ t0 = newTemp(Ity_I64);
+
+ assign(t0, binop(Iop_F32toI64S, mkU32(0x1),
+ getLoFromF64(tyF, getFReg(fs))));
+
+ putDReg(fd, unop(Iop_ReinterpI64asF64, mkexpr(t0)));
+ } else {
+ ILLEGAL_INSTRUCTON
+ }
+
+ break;
+
+ case 0x11: /* D */
+ DIP("floor.l.d %u, %u", fd, fs);
+
+ if (fp_mode64) {
+ calculateFCSR(fs, 0, FLOORLD, False, 1);
+ putDReg(fd, unop(Iop_ReinterpI64asF64,
+ binop(Iop_F64toI64S,
+ mkU32(0x01),
+ getDReg(fs))));
+ } else {
+ ILLEGAL_INSTRUCTON
+ }
+
+ break;
+
+ default:
+ return -1;
}
+
break;
- } else {
- goto decode_failure_dsp;
- }
- break;
- }
- default: {
- if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
- UInt retVal = disDSPInstr_MIPS_WRK ( cins );
- if (0 != retVal ) {
- goto decode_failure_dsp;
+
+ case 0x0C: /* ROUND.W.fmt */
+ switch (fmt) {
+ case 0x10: /* S */
+ DIP("round.w.s f%u, f%u", fd, fs);
+ calculateFCSR(fs, 0, ROUNDWS, True, 1);
+ putFReg(fd,
+ mkWidenFromF32(tyF,
+ unop(Iop_ReinterpI32asF32,
+ binop(Iop_F32toI32S,
+ mkU32(0x0),
+ getLoFromF64(tyF,
+ getFReg(fs))))));
+ break;
+
+ case 0x11: /* D */
+ DIP("round.w.d f%u, f%u", fd, fs);
+ calculateFCSR(fs, 0, ROUNDWD, False, 1);
+
+ if (fp_mode64) {
+ t0 = newTemp(Ity_I32);
+ assign(t0, binop(Iop_F64toI32S, mkU32(0x0),
+ getDReg(fs)));
+ putFReg(fd, mkWidenFromF32(tyF,
+ unop(Iop_ReinterpI32asF32, mkexpr(t0))));
+ } else {
+ t0 = newTemp(Ity_I32);
+
+ assign(t0, binop(Iop_F64toI32S, mkU32(0x0),
+ getDReg(fs)));
+
+ putFReg(fd, unop(Iop_ReinterpI32asF32, mkexpr(t0)));
+ }
+
+ break;
+
+ default:
+ return -1;
+
}
- break;
- } else {
- goto decode_failure_dsp;
- }
- break;
- }
- }
- break;
- }
- case 0x30: { /* DPAQ.W.PH */
- switch(sa) {
- case 0x0: /* DPA.W.PH */
- case 0x18: /* DPAQX_S.W.PH */
- case 0x1A: /* DPAQX_SA.W.PH */
- case 0x8: /* DPAX.W.PH */
- case 0x1: /* DPS.W.PH */
- case 0x19: /* DPSQX_S.W.PH */
- case 0x1B: /* DPSQX_SA.W.PH */
- case 0x9: /* DPSX.W.PH */
- case 0x2: { /* MULSA.W.PH */
- if (VEX_MIPS_PROC_DSP2(archinfo->hwcaps)) {
- UInt retVal = disDSPInstr_MIPS_WRK ( cins );
- if (0 != retVal ) {
- goto decode_failure_dsp;
+
+ break; /* ROUND.W.fmt */
+
+ case 0x0F: /* FLOOR.W.fmt */
+ switch (fmt) {
+ case 0x10: /* S */
+ DIP("floor.w.s f%u, f%u", fd, fs);
+ calculateFCSR(fs, 0, FLOORWS, True, 1);
+ putFReg(fd,
+ mkWidenFromF32(tyF,
+ unop(Iop_ReinterpI32asF32,
+ binop(Iop_F32toI32S,
+ mkU32(0x1),
+ getLoFromF64(tyF,
+ getFReg(fs))))));
+ break;
+
+ case 0x11: /* D */
+ DIP("floor.w.d f%u, f%u", fd, fs);
+ calculateFCSR(fs, 0, FLOORWD, False, 1);
+
+ if (fp_mode64) {
+ t0 = newTemp(Ity_I32);
+ assign(t0, binop(Iop_F64toI32S, mkU32(0x1),
+ getDReg(fs)));
+ putFReg(fd, mkWidenFromF32(tyF,
+ unop(Iop_ReinterpI32asF32, mkexpr(t0))));
+ break;
+ } else {
+ t0 = newTemp(Ity_I32);
+
+ assign(t0, binop(Iop_F64toI32S, mkU32(0x1),
+ getDReg(fs)));
+
+ putFReg(fd, unop(Iop_ReinterpI32asF32, mkexpr(t0)));
+ break;
+ }
+
+ default:
+ return -1;
+
+ }
+
+ break; /* FLOOR.W.fmt */
+
+ case 0x0D: /* TRUNC.W */
+ switch (fmt) {
+ case 0x10: /* S */
+ DIP("trunc.w.s %u, %u", fd, fs);
+ calculateFCSR(fs, 0, TRUNCWS, True, 1);
+ putFReg(fd,
+ mkWidenFromF32(tyF,
+ unop(Iop_ReinterpI32asF32,
+ binop(Iop_F32toI32S,
+ mkU32(0x3),
+ getLoFromF64(tyF,
+ getFReg(fs))))));
+ break;
+
+ case 0x11: /* D */
+ DIP("trunc.w.d %u, %u", fd, fs);
+ calculateFCSR(fs, 0, TRUNCWD, False, 1);
+
+ if (fp_mode64) {
+ t0 = newTemp(Ity_I32);
+
+ assign(t0, binop(Iop_F64toI32S, mkU32(0x3),
+ getFReg(fs)));
+
+ putFReg(fd, mkWidenFromF32(tyF,
+ unop(Iop_ReinterpI32asF32, mkexpr(t0))));
+ } else {
+ t0 = newTemp(Ity_I32);
+
+ assign(t0, binop(Iop_F64toI32S, mkU32(0x3),
+ getDReg(fs)));
+
+ putFReg(fd, unop(Iop_ReinterpI32asF32, mkexpr(t0)));
+ }
+
+ break;
+
+ default:
+ return -1;
+
}
+
break;
- } else {
- goto decode_failure_dsp;
- }
- break;
- }
- default: {
- if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
- UInt retVal = disDSPInstr_MIPS_WRK ( cins );
- if (0 != retVal ) {
- goto decode_failure_dsp;
+
+ case 0x0E: /* CEIL.W.fmt */
+ switch (fmt) {
+ case 0x10: /* S */
+ DIP("ceil.w.s %u, %u", fd, fs);
+ calculateFCSR(fs, 0, CEILWS, True, 1);
+ putFReg(fd,
+ mkWidenFromF32(tyF,
+ unop(Iop_ReinterpI32asF32,
+ binop(Iop_F32toI32S,
+ mkU32(0x2),
+ getLoFromF64(tyF,
+ getFReg(fs))))));
+ break;
+
+ case 0x11: /* D */
+ DIP("ceil.w.d %u, %u", fd, fs);
+ calculateFCSR(fs, 0, CEILWD, False, 1);
+
+ if (!fp_mode64) {
+ t0 = newTemp(Ity_I32);
+ assign(t0, binop(Iop_F64toI32S, mkU32(0x2),
+ getDReg(fs)));
+ putFReg(fd, unop(Iop_ReinterpI32asF32, mkexpr(t0)));
+ } else {
+ t0 = newTemp(Ity_I32);
+ assign(t0, binop(Iop_F64toI32S, mkU32(0x2),
+ getDReg(fs)));
+ putFReg(fd, mkWidenFromF32(tyF,
+ unop(Iop_ReinterpI32asF32, mkexpr(t0))));
+ }
+
+ break;
+
+ default:
+ return -1;
+
}
+
break;
- } else {
- goto decode_failure_dsp;
- }
- break;
- }
- }
- break;
- }
- case 0x18: /* ADDUH.QB/MUL.PH */
- case 0x31: { /* APPEND */
- if (VEX_MIPS_PROC_DSP2(archinfo->hwcaps)) {
- UInt retVal = disDSPInstr_MIPS_WRK ( cins );
- if (0 != retVal ) {
- goto decode_failure_dsp;
- }
- break;
- } else {
- goto decode_failure_dsp;
- }
- }
- case 0x35: { /* PREF r6*/
- DIP("pref");
- break;
- }
- case 0x36: { /* LL */
- imm = extend_s_9to16((instr_index >> 7) & 0x1ff);
- DIP("ll r%u, %u(r%u)", rt, imm, rs);
- LOAD_STORE_PATTERN;
- t2 = newTemp(ty);
- assign(t2, mkWidenFrom32(ty, load(Ity_I32, mkexpr(t1)), True));
- putLLaddr(mkexpr(t1));
- putLLdata(mkexpr(t2));
- putIReg(rt, mkexpr(t2));
- break;
- }
- case 0x26: { /* SC */
- imm = extend_s_9to16((instr_index >> 7) & 0x1ff);
- DIP("sc r%u, %u(r%u)", rt, imm, rs);
- LOAD_STORE_PATTERN;
- t2 = newTemp(Ity_I1);
- t3 = newTemp(Ity_I32);
- assign(t2, binop(mode64 ? Iop_CmpNE64 : Iop_CmpNE32,
- mkexpr(t1), getLLaddr()));
- assign(t3, mkNarrowTo32(ty, getIReg(rt)));
- putLLaddr(LLADDR_INVALID);
- putIReg(rt, getIReg(0));
+ case 0x0A: /* CEIL.L.fmt */
+ switch (fmt) {
+ case 0x10: /* S */
+ DIP("ceil.l.s %u, %u", fd, fs);
- mips_next_insn_if(mkexpr(t2));
+ if (fp_mode64) {
+ calculateFCSR(fs, 0, CEILLS, True, 1);
+ t0 = newTemp(Ity_I64);
- t4 = newTemp(Ity_I32);
- t5 = newTemp(Ity_I32);
+ assign(t0, binop(Iop_F32toI64S, mkU32(0x2),
+ getLoFromF64(tyF, getFReg(fs))));
- assign(t5, mkNarrowTo32(ty, getLLdata()));
+ putFReg(fd, unop(Iop_ReinterpI64asF64, mkexpr(t0)));
+ } else {
+ ILLEGAL_INSTRUCTON
+ }
- stmt(IRStmt_CAS(mkIRCAS(IRTemp_INVALID, t4, /* old_mem */
- MIPS_IEND, mkexpr(t1), /* addr */
- NULL, mkexpr(t5), /* expected value */
- NULL, mkexpr(t3) /* new value */)));
+ break;
- putIReg(rt, unop(mode64 ? Iop_1Uto64 : Iop_1Uto32,
- binop(Iop_CmpEQ32, mkexpr(t4), mkexpr(t5))));
- break;
- }
- case 0x37: { /* LLD */
- imm = extend_s_9to16((instr_index >> 7) & 0x1ff);
- DIP("lld r%u, %u(r%u)", rt, imm, rs);
- LOAD_STORE_PATTERN;
+ case 0x11: /* D */
+ DIP("ceil.l.d %u, %u", fd, fs);
- t2 = newTemp(Ity_I64);
- assign(t2, load(Ity_I64, mkexpr(t1)));
- putLLaddr(mkexpr(t1));
- putLLdata(mkexpr(t2));
- putIReg(rt, mkexpr(t2));
- break;
- }
- case 0x27: { /* SCD */
- imm = extend_s_9to16((instr_index >> 7) & 0x1ff);
- DIP("sdc r%u, %u(r%u)", rt, imm, rs);
- LOAD_STORE_PATTERN;
+ if (fp_mode64) {
+ calculateFCSR(fs, 0, CEILLD, False, 1);
+ putDReg(fd, unop(Iop_ReinterpI64asF64,
+ binop(Iop_F64toI64S,
+ mkU32(0x2),
+ getDReg(fs))));
+ } else {
+ ILLEGAL_INSTRUCTON
+ }
- t2 = newTemp(Ity_I1);
- t3 = newTemp(Ity_I64);
- assign(t2, binop(Iop_CmpNE64, mkexpr(t1), getLLaddr()));
- assign(t3, getIReg(rt));
- putLLaddr(LLADDR_INVALID);
- putIReg(rt, getIReg(0));
+ break;
+
+ default:
+ return -1;
+
+ }
+
+ break;
+
+ case 0x16: /* RSQRT.fmt */
+ switch (fmt) {
+ case 0x10: { /* S */
+ DIP("rsqrt.s %u, %u", fd, fs);
+ IRExpr *rm = get_IR_roundingmode();
+ putFReg(fd, mkWidenFromF32(tyF, triop(Iop_DivF32, rm,
+ unop(Iop_ReinterpI32asF32, mkU32(ONE_SINGLE)),
+ binop(Iop_SqrtF32, rm, getLoFromF64(tyF,
+ getFReg(fs))))));
+ break;
+ }
+
+ case 0x11: { /* D */
+ DIP("rsqrt.d %u, %u", fd, fs);
+ IRExpr *rm = get_IR_roundingmode();
+ putDReg(fd, triop(Iop_DivF64, rm,
+ unop(Iop_ReinterpI64asF64,
+ mkU64(ONE_DOUBLE)),
+ binop(Iop_SqrtF64, rm, getDReg(fs))));
+ break;
+ }
- mips_next_insn_if(mkexpr(t2));
+ default:
+ return -1;
- t4 = newTemp(Ity_I64);
- t5 = newTemp(Ity_I64);
+ }
- assign(t5, getLLdata());
+ break;
- stmt(IRStmt_CAS(mkIRCAS(IRTemp_INVALID, t4, /* old_mem */
- MIPS_IEND, mkexpr(t1), /* addr */
- NULL, mkexpr(t5), /* expected value */
- NULL, mkexpr(t3) /* new value */)));
+ case 0x18: /* MADDF.fmt */
+ if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+ switch (fmt) {
+ case 0x11: { /* D */
+ DIP("maddf.d f%u, f%u, f%u", fd, fs, ft);
+ IRExpr *rm = get_IR_roundingmode();
+ putDReg(fd, qop(Iop_MAddF64, rm, getDReg(fs), getDReg(ft),
+ getDReg(fd)));
+ break;
+ }
- putIReg(rt, unop(Iop_1Uto64,
- binop(Iop_CmpEQ64, mkexpr(t4), mkexpr(t5))));
- break;
- }
- default:
- goto decode_failure;
+ case 0x10: { /* S */
+ DIP("maddf.s f%u, f%u, f%u", fd, fs, ft);
+ IRExpr *rm = get_IR_roundingmode();
+ t1 = newTemp(Ity_F32);
+ assign(t1, qop(Iop_MAddF32, rm,
+ getLoFromF64(tyF, getFReg(fs)),
+ getLoFromF64(tyF, getFReg(ft)),
+ getLoFromF64(tyF, getFReg(fd))));
+ putFReg(fd, mkWidenFromF32(tyF, mkexpr(t1)));
+ break;
+ }
- }
- break; /* Special3 */
+ default:
+ return -1;
+ }
+ } else {
+ ILLEGAL_INSTRUCTON;
+ }
- case 0x3B: /* PCREL */
- if (rt == 0x1E) { /* AUIPC */
- if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
- DIP("auipc r%u, %u", rs, imm);
- if (mode64) {
- putIReg(rs, mkU64(guest_PC_curr_instr + (imm << 16)));
- } else {
- putIReg(rs, mkU32(guest_PC_curr_instr + (imm << 16)));
- }
- } else {
- ILLEGAL_INSTRUCTON;
- }
- break;
- } else if (rt == 0x1F) { /* ALUIPC */
- if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
- DIP("aluipc r%u, %u", rs, imm);
- if (mode64) {
- putIReg(rs, mkU64((~0x0FFFFULL) &
- (guest_PC_curr_instr + extend_s_32to64(imm << 16))));
- } else {
- putIReg(rs, mkU32((~0x0FFFFULL) &
- (guest_PC_curr_instr + (imm << 16))));
- }
- } else {
- ILLEGAL_INSTRUCTON;
- }
- break;
- } else if ((rt & 0x18) == 0) { /* ADDIUPC */
- if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
- DIP("addiupc r%u, %u", rs, instr_index & 0x7FFFF);
- if (mode64) {
- putIReg(rs, mkU64(guest_PC_curr_instr +
- (extend_s_19to64(instr_index & 0x7FFFF) << 2)));
- } else {
- putIReg(rs, mkU32(guest_PC_curr_instr +
- (extend_s_19to32(instr_index & 0x7FFFF) << 2)));
- }
- } else {
- ILLEGAL_INSTRUCTON;
- }
- break;
- } else if ((rt & 0x18) == 8) { /* LWPC */
- if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
- DIP("lwpc r%u, %x", rs, instr_index & 0x7FFFF);
- if (mode64) {
- t1 = newTemp(Ity_I64);
- assign(t1, mkU64(guest_PC_curr_instr +
- (extend_s_19to64(instr_index & 0x7FFFF) << 2)));
- putIReg(rs, unop(Iop_32Sto64, load(Ity_I32, mkexpr(t1))));
- } else {
- t1 = newTemp(Ity_I32);
- assign(t1, mkU32(guest_PC_curr_instr +
- (extend_s_19to32(instr_index & 0x7FFFF) << 2)));
- putIReg(rs, load(Ity_I32, mkexpr(t1)));
- }
- } else {
- ILLEGAL_INSTRUCTON;
- }
- break;
- } else if ((rt & 0x18) == 16) { /* LWUPC */
- if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
- DIP("lwupc r%u, %x", rs, instr_index & 0x7FFFF);
- if (mode64) {
- t1 = newTemp(Ity_I64);
- assign(t1, mkU64(guest_PC_curr_instr +
- (extend_s_19to64(instr_index & 0x7FFFF) << 2)));
- putIReg(rs, unop(Iop_32Uto64, load(Ity_I32, mkexpr(t1))));
- } else {
- t1 = newTemp(Ity_I32);
- assign(t1, mkU32(guest_PC_curr_instr +
- (extend_s_19to32(instr_index & 0x7FFFF) << 2)));
- putIReg(rs, load(Ity_I32, mkexpr(t1)));
- }
- } else {
- ILLEGAL_INSTRUCTON;
- }
- break;
- } else if ((rt & 0x1C) == 0x18) { /* LDPC */
- if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
- DIP("ldpc r%u, %x", rs, instr_index & 0x3FFFF);
- t1 = newTemp(Ity_I64);
- assign(t1, mkU64(guest_PC_curr_instr +
- (extend_s_18to64(instr_index & 0x3FFFF) << 3)));
- putIReg(rs, load(Ity_I64, mkexpr(t1)));
- } else {
- ILLEGAL_INSTRUCTON;
- }
- break;
- } else {
- goto decode_failure;
- }
+ break;
- if (0x3B == function &&
- (VEX_MIPS_COMP_ID(archinfo->hwcaps) == VEX_PRID_COMP_BROADCOM)) {
- /*RDHWR*/
- DIP("rdhwr r%u, r%u", rt, rd);
- if (rd == 29) {
- putIReg(rt, getULR());
- } else
- goto decode_failure;
- break;
- } else {
- goto decode_failure;
- }
+ case 0x19: /* MSUBF.fmt */
+ if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+ switch (fmt) {
+ case 0x11: { /* D */
+ DIP("msubf.d f%u, f%u, f%u", fd, fs, ft);
+ IRExpr *rm = get_IR_roundingmode();
+ putDReg(fd, qop(Iop_MSubF64, rm, getDReg(fs),
+ getDReg(ft), getDReg(fd)));
+ break;
+ }
- case 0x00: /* Special */
+ case 0x10: { /* S */
+ DIP("msubf.s f%u, f%u, f%u", fd, fs, ft);
+ IRExpr *rm = get_IR_roundingmode();
+ t1 = newTemp(Ity_F32);
+ assign(t1, qop(Iop_MSubF32, rm,
+ getLoFromF64(tyF, getFReg(fs)),
+ getLoFromF64(tyF, getFReg(ft)),
+ getLoFromF64(tyF, getFReg(fd))));
+ putFReg(fd, mkWidenFromF32(tyF, mkexpr(t1)));
+ break;
+ }
- switch (function) {
- case 0x1: {
- UInt mov_cc = get_mov_cc(cins);
- if (tf == 0) { /* MOVF */
- DIP("movf r%u, r%u, %u", rd, rs, mov_cc);
- t1 = newTemp(Ity_I1);
- t2 = newTemp(Ity_I32);
- t3 = newTemp(Ity_I1);
+ default:
+ return -1;
+ }
+ } else {
+ ILLEGAL_INSTRUCTON;
+ }
- assign(t1, binop(Iop_CmpEQ32, mkU32(0), mkU32(mov_cc)));
- assign(t2, IRExpr_ITE(mkexpr(t1),
- binop(Iop_And32,
- binop(Iop_Shr32, getFCSR(),
- mkU8(23)),
- mkU32(0x1)),
- binop(Iop_And32,
- binop(Iop_Shr32, getFCSR(),
- mkU8(24 + mov_cc)),
- mkU32(0x1))
- ));
- assign(t3, binop(Iop_CmpEQ32, mkU32(0), mkexpr(t2)));
- putIReg(rd, IRExpr_ITE(mkexpr(t3), getIReg(rs), getIReg(rd)));
- } else if (tf == 1) { /* MOVT */
- DIP("movt r%u, r%u, %u", rd, rs, mov_cc);
- t1 = newTemp(Ity_I1);
- t2 = newTemp(Ity_I32);
- t3 = newTemp(Ity_I1);
+ break;
- assign(t1, binop(Iop_CmpEQ32, mkU32(0), mkU32(mov_cc)));
- assign(t2, IRExpr_ITE(mkexpr(t1),
- binop(Iop_And32,
- binop(Iop_Shr32, getFCSR(),
- mkU8(23)),
- mkU32(0x1)),
- binop(Iop_And32,
- binop(Iop_Shr32, getFCSR(),
- mkU8(24 + mov_cc)),
- mkU32(0x1))
- ));
- assign(t3, binop(Iop_CmpEQ32, mkU32(1), mkexpr(t2)));
- putIReg(rd, IRExpr_ITE(mkexpr(t3), getIReg(rs), getIReg(rd)));
- }
- break;
- }
- case 0x0A: { /* MOVZ */
- DIP("movz r%u, r%u, r%u", rd, rs, rt);
- t1 = newTemp(ty);
- t2 = newTemp(ty);
- if (mode64) {
- assign(t1, unop(Iop_32Sto64, unop(Iop_1Sto32, binop(Iop_CmpEQ64,
- getIReg(rt), mkU64(0x0)))));
- assign(t2, unop(Iop_32Sto64, unop(Iop_1Sto32, binop(Iop_CmpNE64,
- getIReg(rt), mkU64(0x0)))));
- putIReg(rd, binop(Iop_Add64, binop(Iop_And64, getIReg(rs),
- mkexpr(t1)), binop(Iop_And64, getIReg(rd),mkexpr(t2))));
- } else {
- assign(t1, unop(Iop_1Sto32, binop(Iop_CmpEQ32, getIReg(rt),
- mkU32(0x0))));
- assign(t2, unop(Iop_1Sto32, binop(Iop_CmpNE32, getIReg(rt),
- mkU32(0x0))));
- putIReg(rd, binop(Iop_Add32, binop(Iop_And32, getIReg(rs),
- mkexpr(t1)), binop(Iop_And32, getIReg(rd),
- mkexpr(t2))));
- }
- break;
- }
+ case 0x1E: /* MAX.fmt */
+ if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+ switch (fmt) {
+ case 0x11: { /* D */
+ DIP("max.d f%u, f%u, f%u", fd, fs, ft);
+ calculateFCSR(fs, ft, MAXD, False, 2);
+ putDReg(fd, binop(Iop_MaxNumF64, getDReg(fs), getDReg(ft)));
+ break;
+ }
- case 0x0B: { /* MOVN */
- DIP("movn r%u, r%u, r%u", rd, rs, rt);
- t1 = newTemp(ty);
- t2 = newTemp(ty);
- if (mode64) {
- assign(t1, unop(Iop_32Sto64, unop(Iop_1Sto32, binop(Iop_CmpEQ64,
- getIReg(rt), mkU64(0x0)))));
- assign(t2, unop(Iop_32Sto64, unop(Iop_1Sto32, binop(Iop_CmpNE64,
- getIReg(rt), mkU64(0x0)))));
- putIReg(rd, binop(Iop_Add64, binop(Iop_And64, getIReg(rs),
- mkexpr(t2)), binop(Iop_And64, getIReg(rd),
- mkexpr(t1))));
- } else {
- assign(t1, unop(Iop_1Sto32, binop(Iop_CmpEQ32, getIReg(rt),
- mkU32(0x0))));
- assign(t2, unop(Iop_1Sto32, binop(Iop_CmpNE32, getIReg(rt),
- mkU32(0x0))));
- putIReg(rd, binop(Iop_Add32, binop(Iop_And32, getIReg(rs),
- mkexpr(t2)), binop(Iop_And32, getIReg(rd),
- mkexpr(t1))));
- }
- break;
- }
+ case 0x10: { /* S */
+ DIP("max.s f%u, f%u, f%u", fd, fs, ft);
+ calculateFCSR(fs, ft, MAXS, True, 2);
+ putFReg(fd, mkWidenFromF32(tyF, binop(Iop_MaxNumF32,
+ getLoFromF64(Ity_F64,
+ getFReg(fs)),
+ getLoFromF64(Ity_F64,
+ getFReg(ft)))));
+ break;
+ }
- case 0x18: { /* MULT */
- switch (sa & 0x3) {
- case 0: {
- if ((1 <= ac) && ( 3 >= ac)) {
- if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
- /* If DSP is present -> DSP ASE MULT */
- UInt retVal = disDSPInstr_MIPS_WRK(cins);
- if (0 != retVal) {
- goto decode_failure_dsp;
+ default:
+ return -1;
}
- break;
} else {
- goto decode_failure_dsp;
- }
- } else {
- DIP("mult r%u, r%u", rs, rt);
- if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps) &&
- !VEX_MIPS_CPU_HAS_MIPS32R2(archinfo->hwcaps)) {
ILLEGAL_INSTRUCTON;
}
- t2 = newTemp(Ity_I64);
-
- assign(t2, binop(Iop_MullS32, mkNarrowTo32(ty, getIReg(rs)),
- mkNarrowTo32(ty, getIReg(rt))));
- putHI(mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(t2)), True));
- putLO(mkWidenFrom32(ty, unop(Iop_64to32, mkexpr(t2)), True));
break;
- }
- }
- case 2: { /* MUL R6 */
- if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
- DIP("mul r%u, r%u, r%u", rs, rt, rd);
- if (mode64) {
- putIReg(rd, unop(Iop_32Sto64,
- unop(Iop_64to32,
- binop(Iop_MullS32,
- unop(Iop_64to32, getIReg(rs)),
- unop(Iop_64to32, getIReg(rt))))));
- } else {
- putIReg(rd, unop(Iop_64to32,
- binop(Iop_MullS32,
- getIReg(rs), getIReg(rt))));
- }
- } else {
- ILLEGAL_INSTRUCTON;
- }
- break;
- }
- case 3: { /* MUH R6 */
- if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
- DIP("muh r%u, r%u, r%u", rs, rt, rd);
- if (mode64) {
- putIReg(rd, unop(Iop_32Sto64,
- unop(Iop_64HIto32,
- binop(Iop_MullS32,
- unop(Iop_64to32, getIReg(rs)),
- unop(Iop_64to32, getIReg(rt))))));
+ case 0x1C: /* MIN.fmt */
+ if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+ switch (fmt) {
+ case 0x11: { /* D */
+ DIP("min.d f%u, f%u, f%u", fd, fs, ft);
+ calculateFCSR(fs, ft, MIND, False, 2);
+ putDReg(fd, binop(Iop_MinNumF64, getDReg(fs), getDReg(ft)));
+ break;
+ }
+
+ case 0x10: { /* S */
+ DIP("min.s f%u, f%u, f%u", fd, fs, ft);
+ calculateFCSR(fs, ft, MINS, True, 2);
+ putFReg(fd, mkWidenFromF32(tyF, binop(Iop_MinNumF32,
+ getLoFromF64(Ity_F64,
+ getFReg(fs)),
+ getLoFromF64(Ity_F64,
+ getFReg(ft)))));
+ break;
+ }
+
+ default:
+ return -1;
+ }
} else {
- putIReg(rd, unop(Iop_64HIto32,
- binop(Iop_MullS32,
- getIReg(rs), getIReg(rt))));
+ ILLEGAL_INSTRUCTON;
}
- } else {
- ILLEGAL_INSTRUCTON;
- }
- break;
- }
- }
- break;
- }
- case 0x19: { /* MULTU */
- switch (sa & 0x3) {
- case 0: {
- if ((1 <= ac) && ( 3 >= ac)) {
- if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
- /* If DSP is present -> DSP ASE MULTU */
- UInt retVal = disDSPInstr_MIPS_WRK ( cins );
- if (0 != retVal) {
- goto decode_failure_dsp;
+ break;
+
+ case 0x1F: /* MAXA.fmt */
+ if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+ switch (fmt) {
+ case 0x11: { /* D */
+ DIP("maxa.d f%u, f%u, f%u", fd, fs, ft);
+ calculateFCSR(fs, ft, MAXAD, False, 2);
+ t1 = newTemp(Ity_F64);
+ t2 = newTemp(Ity_F64);
+ t3 = newTemp(Ity_F64);
+ t4 = newTemp(Ity_I1);
+ assign(t1, unop(Iop_AbsF64, getFReg(fs)));
+ assign(t2, unop(Iop_AbsF64, getFReg(ft)));
+ assign(t3, binop(Iop_MaxNumF64, mkexpr(t1), mkexpr(t2)));
+ assign(t4, binop(Iop_CmpEQ32,
+ binop(Iop_CmpF64, mkexpr(t3), mkexpr(t1)),
+ mkU32(0x40)));
+ putFReg(fd, IRExpr_ITE(mkexpr(t4),
+ getFReg(fs), getFReg(ft)));
+ break;
+ }
+
+ case 0x10: { /* S */
+ DIP("maxa.s f%u, f%u, f%u", fd, fs, ft);
+ calculateFCSR(fs, ft, MAXAS, True, 2);
+ t1 = newTemp(Ity_F32);
+ t2 = newTemp(Ity_F32);
+ t3 = newTemp(Ity_F32);
+ t4 = newTemp(Ity_I1);
+ assign(t1, unop(Iop_AbsF32, getLoFromF64(Ity_F64,
+ getFReg(fs))));
+ assign(t2, unop(Iop_AbsF32, getLoFromF64(Ity_F64,
+ getFReg(ft))));
+ assign(t3, binop(Iop_MaxNumF32, mkexpr(t1), mkexpr(t2)));
+ assign(t4, binop(Iop_CmpEQ32,
+ binop(Iop_CmpF32, mkexpr(t3), mkexpr(t1)),
+ mkU32(0x40)));
+ putFReg(fd, IRExpr_ITE(mkexpr(t4),
+ getFReg(fs), getFReg(ft)));
+ break;
+ }
+
+ default:
+ return -1;
}
- break;
+
} else {
- goto decode_failure_dsp;
- }
- } else {
- DIP("multu r%u, r%u", rs, rt);
- if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps) &&
- !VEX_MIPS_CPU_HAS_MIPS32R2(archinfo->hwcaps)) {
ILLEGAL_INSTRUCTON;
}
- t2 = newTemp(Ity_I64);
- assign(t2, binop(Iop_MullU32, mkNarrowTo32(ty, getIReg(rs)),
- mkNarrowTo32(ty, getIReg(rt))));
+ break;
+
+ case 0x1D: /* MINA.fmt */
+ if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+ switch (fmt) {
+ case 0x11: { /* D */
+ DIP("mina.d f%u, f%u, f%u", fd, fs, ft);
+ calculateFCSR(fs, ft, MINAD, False, 2);
+ t1 = newTemp(Ity_F64);
+ t2 = newTemp(Ity_F64);
+ t3 = newTemp(Ity_F64);
+ t4 = newTemp(Ity_I1);
+ assign(t1, unop(Iop_AbsF64, getFReg(fs)));
+ assign(t2, unop(Iop_AbsF64, getFReg(ft)));
+ assign(t3, binop(Iop_MinNumF64, mkexpr(t1), mkexpr(t2)));
+ assign(t4, binop(Iop_CmpEQ32,
+ binop(Iop_CmpF64, mkexpr(t3), mkexpr(t1)),
+ mkU32(0x40)));
+ putFReg(fd, IRExpr_ITE(mkexpr(t4),
+ getFReg(fs), getFReg(ft)));
+ break;
+ }
+
+ case 0x10: { /* S */
+ DIP("mina.s f%u, f%u, f%u", fd, fs, ft);
+ calculateFCSR(fs, ft, MINAS, True, 2);
+ t1 = newTemp(Ity_F32);
+ t2 = newTemp(Ity_F32);
+ t3 = newTemp(Ity_F32);
+ t4 = newTemp(Ity_I1);
+ assign(t1, unop(Iop_AbsF32, getLoFromF64(Ity_F64,
+ getFReg(fs))));
+ assign(t2, unop(Iop_AbsF32, getLoFromF64(Ity_F64,
+ getFReg(ft))));
+ assign(t3, binop(Iop_MinNumF32, mkexpr(t1), mkexpr(t2)));
+ assign(t4, binop(Iop_CmpEQ32,
+ binop(Iop_CmpF32, mkexpr(t3), mkexpr(t1)),
+ mkU32(0x40)));
+ putFReg(fd, IRExpr_ITE(mkexpr(t4),
+ getFReg(fs), getFReg(ft)));
+ break;
+ }
+
+ default:
+ return -1;
+ }
+ }
- putHI(mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(t2)), True));
- putLO(mkWidenFrom32(ty, unop(Iop_64to32, mkexpr(t2)), True));
break;
- }
- }
- case 2: { /* MULU R6 */
- if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
- DIP("mulu r%u, r%u, r%u", rs, rt, rd);
- if (mode64) {
- putIReg(rd, unop(Iop_32Uto64,
- unop(Iop_64to32,
- binop(Iop_MullU32,
- unop(Iop_64to32, getIReg(rs)),
- unop(Iop_64to32, getIReg(rt))))));
- } else {
- putIReg(rd, unop(Iop_64to32,
- binop(Iop_MullU32,
- getIReg(rs), getIReg(rt))));
+
+ case 0x1A: /* RINT.fmt */
+ if (ft == 0) {
+ switch (fmt) {
+ case 0x11: { /* D */
+ DIP("rint.d f%u, f%u", fd, fs);
+ calculateFCSR(fs, 0, RINTS, True, 1);
+ IRExpr *rm = get_IR_roundingmode();
+ putDReg(fd, binop(Iop_RoundF64toInt, rm, getDReg(fs)));
+ break;
+ }
+
+ case 0x10: { /* S */
+ DIP("rint.s f%u, f%u", fd, fs);
+ calculateFCSR(fs, 0, RINTD, True, 1);
+ IRExpr *rm = get_IR_roundingmode();
+ putFReg(fd,
+ mkWidenFromF32(tyF,
+ binop(Iop_RoundF32toInt, rm,
+ getLoFromF64(tyF,
+ getFReg(fs)))));
+ break;
+ }
+
+ default:
+ return -1;
+ }
+
}
- } else {
- ILLEGAL_INSTRUCTON;
- }
- break;
- }
- case 3: { /* MUHU R6 */
- if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
- DIP("muhu r%u, r%u, r%u", rs, rt, rd);
- if (mode64) {
- putIReg(rd, unop(Iop_32Uto64,
- unop(Iop_64HIto32,
- binop(Iop_MullU32,
- unop(Iop_64to32, getIReg(rs)),
- unop(Iop_64to32, getIReg(rt))))));
- } else {
- putIReg(rd, unop(Iop_64HIto32,
- binop(Iop_MullU32,
- getIReg(rs), getIReg(rt))));
+
+ break;
+
+ case 0x10: /* SEL.fmt */
+ switch (fmt) {
+ case 0x11: { /* D */
+ if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+ DIP("sel.d f%u, f%u, f%u", fd, fs, ft);
+ t1 = newTemp(Ity_I1);
+
+ if (mode64) {
+ assign(t1, binop(Iop_CmpNE64,
+ binop(Iop_And64,
+ unop(Iop_ReinterpF64asI64,
+ getDReg(fd)),
+ mkU64(1)),
+ mkU64(0)));
+ } else {
+ assign(t1, binop(Iop_CmpNE32,
+ binop(Iop_And32,
+ unop(Iop_64to32,
+ unop(Iop_ReinterpF64asI64,
+ getDReg(fd))),
+ mkU32(1)),
+ mkU32(0)));
+ }
+
+ putDReg(fd, IRExpr_ITE(mkexpr(t1),
+ getDReg(ft), getDReg(fs)));
+ break;
+ } else {
+ ILLEGAL_INSTRUCTON;
+ break;
+ }
+
+ }
+
+ case 0x10: { /* S */
+ DIP("sel.s f%u, f%u, f%u", fd, fs, ft);
+ t1 = newTemp(Ity_I1);
+ assign(t1, binop(Iop_CmpNE32,
+ binop(Iop_And32,
+ unop(Iop_ReinterpF32asI32,
+ getLoFromF64(tyF, getFReg(fd))),
+ mkU32(1)),
+ mkU32(0)));
+ putFReg(fd, IRExpr_ITE( mkexpr(t1),
+ getFReg(ft), getFReg(fs)));
+ break;
+ }
+
+ default:
+ return -1;
}
- } else {
- ILLEGAL_INSTRUCTON;
- }
- break;
- }
- }
- }
- break;
- case 0x20: { /* ADD */
- DIP("add r%u, r%u, r%u", rd, rs, rt);
- IRTemp tmpRs32 = newTemp(Ity_I32);
- IRTemp tmpRt32 = newTemp(Ity_I32);
+ break;
- assign(tmpRs32, mkNarrowTo32(ty, getIReg(rs)));
- assign(tmpRt32, mkNarrowTo32(ty, getIReg(rt)));
+ case 0x14: /* SELEQZ.fmt */
+ if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+ switch (fmt) { /* SELEQZ.df */
+ case 0x11: { /* D */
+ DIP("seleqz.d f%u, f%u, f%u", fd, fs, ft);
+ t1 = newTemp(Ity_I1);
+
+ if (mode64) {
+ assign(t1, binop(Iop_CmpNE64,
+ binop(Iop_And64,
+ unop(Iop_ReinterpF64asI64,
+ getDReg(ft)),
+ mkU64(1)),
+ mkU64(0)));
+ } else {
+ assign(t1, binop(Iop_CmpNE32,
+ binop(Iop_And32,
+ unop(Iop_64to32,
+ unop(Iop_ReinterpF64asI64,
+ getDReg(ft))),
+ mkU32(1)),
+ mkU32(0)));
+ }
- t0 = newTemp(Ity_I32);
- t1 = newTemp(Ity_I32);
- t2 = newTemp(Ity_I32);
- t3 = newTemp(Ity_I32);
- t4 = newTemp(Ity_I32);
- /* dst = src0 + src1
- if (sign(src0 ) != sign(src1 ))
- goto no overflow;
- if (sign(dst) == sign(src0 ))
- goto no overflow;
- we have overflow! */
+ putDReg(fd, IRExpr_ITE( mkexpr(t1),
+ binop(Iop_I64StoF64,
+ get_IR_roundingmode(), mkU64(0)),
+ getDReg(fs)));
+ break;
+ }
- assign(t0, binop(Iop_Add32, mkexpr(tmpRs32), mkexpr(tmpRt32)));
- assign(t1, binop(Iop_Xor32, mkexpr(tmpRs32), mkexpr(tmpRt32)));
- assign(t2, unop(Iop_1Uto32,
- binop(Iop_CmpEQ32,
- binop(Iop_And32, mkexpr(t1), mkU32(0x80000000)),
- mkU32(0x80000000))));
+ case 0x10: { /* S */
+ DIP("seleqz.s f%u, f%u, f%u", fd, fs, ft);
+ t1 = newTemp(Ity_I1);
+ assign(t1, binop(Iop_CmpNE32,
+ binop(Iop_And32,
+ unop(Iop_ReinterpF32asI32,
+ getLoFromF64(tyF, getFReg(ft))),
+ mkU32(1)),
+ mkU32(0)));
+ putFReg(fd, IRExpr_ITE(mkexpr(t1),
+ mkWidenFromF32(tyF,
+ binop(Iop_I32StoF32,
+ get_IR_roundingmode(),
+ mkU32(0))),
+ getFReg(fs)));
+ break;
+ }
- assign(t3, binop(Iop_Xor32, mkexpr(t0), mkexpr(tmpRs32)));
- assign(t4, unop(Iop_1Uto32,
- binop(Iop_CmpNE32,
- binop(Iop_And32, mkexpr(t3), mkU32(0x80000000)),
- mkU32(0x80000000))));
+ default:
+ return -1;
+ }
+ } else {
+ ILLEGAL_INSTRUCTON;
+ }
- stmt(IRStmt_Exit(binop(Iop_CmpEQ32,
- binop(Iop_Or32, mkexpr(t2), mkexpr(t4)),
- mkU32(0)),
- Ijk_SigFPE_IntOvf,
- mode64 ? IRConst_U64(guest_PC_curr_instr + 4) :
- IRConst_U32(guest_PC_curr_instr + 4),
- OFFB_PC));
+ break;
- putIReg(rd, mkWidenFrom32(ty, mkexpr(t0), True));
- break;
- }
+ case 0x17: /* SELNEZ.fmt */
+ if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+ switch (fmt) {
+ case 0x11: { /* D */
+ DIP("selnez.d f%u, f%u, f%u", fd, fs, ft);
+ t1 = newTemp(Ity_I1);
+
+ if (mode64) {
+ assign(t1, binop(Iop_CmpNE64,
+ binop(Iop_And64,
+ unop(Iop_ReinterpF64asI64,
+ getDReg(ft)),
+ mkU64(1)),
+ mkU64(0)));
+ } else {
+ assign(t1, binop(Iop_CmpNE32,
+ binop(Iop_And32,
+ unop(Iop_64to32,
+ unop(Iop_ReinterpF64asI64,
+ getDReg(ft))),
+ mkU32(1)),
+ mkU32(0)));
+ }
- case 0x1A: /* DIV */
- switch (sa & 0x3) {
- case 0:
- DIP("div r%u, r%u", rs, rt);
- if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps) &&
- !VEX_MIPS_CPU_HAS_MIPS32R2(archinfo->hwcaps)) {
- ILLEGAL_INSTRUCTON;
- }
- if (mode64) {
- t2 = newTemp(Ity_I64);
+ putDReg(fd, IRExpr_ITE( mkexpr(t1),
+ getDReg(fs),
+ binop(Iop_I64StoF64,
+ get_IR_roundingmode(),
+ mkU64(0))));
+ break;
+ }
- assign(t2, binop(Iop_DivModS32to32,
- mkNarrowTo32(ty, getIReg(rs)),
- mkNarrowTo32(ty, getIReg(rt))));
+ case 0x10: { /* S */
+ DIP("selnez.s f%u, f%u, f%u", fd, fs, ft);
+ t1 = newTemp(Ity_I1);
+ assign(t1, binop(Iop_CmpNE32,
+ binop(Iop_And32,
+ unop(Iop_ReinterpF32asI32,
+ getLoFromF64(tyF, getFReg(ft))),
+ mkU32(1)),
+ mkU32(0)));
+ putFReg(fd, IRExpr_ITE(mkexpr(t1),
+ getFReg(fs),
+ mkWidenFromF32(tyF,
+ binop(Iop_I32StoF32,
+ get_IR_roundingmode(),
+ mkU32(0)))));
+ break;
+ }
- putHI(mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(t2)), True));
- putLO(mkWidenFrom32(ty, unop(Iop_64to32, mkexpr(t2)), True));
- } else {
- t1 = newTemp(Ity_I64);
+ default:
+ return -1;
- assign(t1, binop(Iop_DivModS32to32, getIReg(rs), getIReg(rt)));
+ }
- putHI(unop(Iop_64HIto32, mkexpr(t1)));
- putLO(unop(Iop_64to32, mkexpr(t1)));
- }
- break;
- case 2:
- if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
- DIP("div r%u, r%u, r%u", rs, rt, rd);
- if (mode64) {
- putIReg(rd, unop(Iop_32Sto64,
- binop(Iop_DivS32,
- unop(Iop_64to32, getIReg(rs)),
- unop(Iop_64to32, getIReg(rt)))));
- } else
- putIReg(rd, binop(Iop_DivS32, getIReg(rs), getIReg(rt)));
- } else {
- ILLEGAL_INSTRUCTON;
- }
- break;
- case 3:
- if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
- DIP("mod r%u, r%u, r%u", rs, rt, rd);
- if (mode64) {
- putIReg(rd, unop(Iop_32Sto64,
- unop(Iop_64HIto32,
- binop(Iop_DivModS32to32,
- unop(Iop_64to32, getIReg(rs)),
- unop(Iop_64to32, getIReg(rt))))));
} else {
- t1 = newTemp(Ity_I64);
-
- assign(t1, binop(Iop_DivModS32to32, getIReg(rs), getIReg(rt)));
- putIReg(rd, unop(Iop_64HIto32, mkexpr(t1)));
+ ILLEGAL_INSTRUCTON;
}
- } else {
- ILLEGAL_INSTRUCTON;
- }
- break;
- }
- break;
- case 0x1B: /* DIVU */
- switch (sa & 0x3) {
- case 0:
- DIP("divu r%u, r%u", rs, rt);
- if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps) &&
- !VEX_MIPS_CPU_HAS_MIPS32R2(archinfo->hwcaps)) {
- ILLEGAL_INSTRUCTON;
- }
- if (mode64) {
- t1 = newTemp(Ity_I64);
+ break;
- assign(t1, binop(Iop_DivModU32to32,
- mkNarrowTo32(ty, getIReg(rs)),
- mkNarrowTo32(ty, getIReg(rt))));
+ case 0x1B: /* CLASS.fmt */
+ if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+ t0 = newTemp(Ity_I1); // exp zero
+ t1 = newTemp(Ity_I1); // exp max
+ t2 = newTemp(Ity_I1); // sign
+ t3 = newTemp(Ity_I1); // first
+ t4 = newTemp(Ity_I1); // val not zero
+ t5 = newTemp(Ity_I32);
+
+ switch (fmt) {
+ case 0x11: { /* D */
+ DIP("class.d f%u, f%u", fd, fs);
+ assign(t0, binop(Iop_CmpEQ32,
+ binop(Iop_And32,
+ unop(Iop_64HIto32,
+ unop(Iop_ReinterpF64asI64,
+ getDReg(fs))),
+ mkU32(0x7ff00000)),
+ mkU32(0)));
+ assign(t1, binop(Iop_CmpEQ32,
+ binop(Iop_And32,
+ unop(Iop_64HIto32,
+ unop(Iop_ReinterpF64asI64,
+ getDReg(fs))),
+ mkU32(0x7ff00000)),
+ mkU32(0x7ff00000)));
+ assign(t2, binop(Iop_CmpEQ32,
+ binop(Iop_And32,
+ unop(Iop_64HIto32,
+ unop(Iop_ReinterpF64asI64,
+ getDReg(fs))),
+ mkU32(0x80000000)),
+ mkU32(0x80000000)));
+ assign(t3, binop(Iop_CmpEQ32,
+ binop(Iop_And32,
+ unop(Iop_64HIto32,
+ unop(Iop_ReinterpF64asI64,
+ getDReg(fs))),
+ mkU32(0x00080000)),
+ mkU32(0x00080000)));
+
+ if (mode64) assign(t4, binop(Iop_CmpNE64,
+ binop(Iop_And64,
+ unop(Iop_ReinterpF64asI64,
+ getDReg(fs)),
+ mkU64(0x000fffffffffffffULL)),
+ mkU64(0)));
+ else assign(t4, binop(Iop_CmpNE32,
+ binop(Iop_Or32,
+ binop(Iop_And32,
+ unop(Iop_64HIto32,
+ unop(Iop_ReinterpF64asI64,
+ getDReg(fs))),
+ mkU32(0x000fffff)),
+ unop(Iop_64to32,
+ unop(Iop_ReinterpF64asI64,
+ getDReg(fs)))),
+ mkU32(0)));
+
+ assign(t5, binop(Iop_Shl32,
+ IRExpr_ITE(mkexpr(t1),
+ IRExpr_ITE(mkexpr(t4),
+ mkU32(0), mkU32(1)),
+ IRExpr_ITE(mkexpr(t0),
+ IRExpr_ITE(mkexpr(t4),
+ mkU32(0x4),
+ mkU32(0x8)),
+ mkU32(2))),
+ IRExpr_ITE(mkexpr(t2), mkU8(2), mkU8(6))));
+ putDReg(fd, unop(Iop_ReinterpI64asF64,
+ unop(Iop_32Uto64,
+ IRExpr_ITE(binop(Iop_CmpNE32,
+ mkexpr(t5), mkU32(0)),
+ mkexpr(t5),
+ IRExpr_ITE(mkexpr(t3),
+ mkU32(2),
+ mkU32(1))))));
+ break;
+ }
- putHI(mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(t1)), True));
- putLO(mkWidenFrom32(ty, unop(Iop_64to32, mkexpr(t1)), True));
- } else {
- t1 = newTemp(Ity_I64);
+ case 0x10: { /* S */
+ DIP("class.s f%u, f%u", fd, fs);
+ assign(t0, binop(Iop_CmpEQ32,
+ binop(Iop_And32,
+ unop(Iop_ReinterpF32asI32,
+ getLoFromF64(tyF, getFReg(fs))),
+ mkU32(0x7f800000)),
+ mkU32(0)));
+ assign(t1, binop(Iop_CmpEQ32,
+ binop(Iop_And32,
+ unop(Iop_ReinterpF32asI32,
+ getLoFromF64(tyF, getFReg(fs))),
+ mkU32(0x7f800000)),
+ mkU32(0x7f800000)));
+ assign(t2, binop(Iop_CmpEQ32,
+ binop(Iop_And32,
+ unop(Iop_ReinterpF32asI32,
+ getLoFromF64(tyF, getFReg(fs))),
+ mkU32(0x80000000)),
+ mkU32(0x80000000)));
+ assign(t3, binop(Iop_CmpEQ32,
+ binop(Iop_And32,
+ unop(Iop_ReinterpF32asI32,
+ getLoFromF64(tyF, getFReg(fs))),
+ mkU32(0x00400000)),
+ mkU32(0x00400000)));
+ assign(t4, binop(Iop_CmpNE32,
+ binop(Iop_And32,
+ unop(Iop_ReinterpF32asI32,
+ getLoFromF64(tyF, getFReg(fs))),
+ mkU32(0x007fffff)),
+ mkU32(0)));
+ assign(t5, binop(Iop_Shl32,
+ IRExpr_ITE(mkexpr(t1),
+ IRExpr_ITE(mkexpr(t4),
+ mkU32(0), mkU32(1)),
+ IRExpr_ITE(mkexpr(t0),
+ IRExpr_ITE(mkexpr(t4),
+ mkU32(0x4),
+ mkU32(0x8)), //zero or subnorm
+ mkU32(2))),
+ IRExpr_ITE(mkexpr(t2), mkU8(2), mkU8(6))));
+ putDReg(fd, unop(Iop_ReinterpI64asF64,
+ unop(Iop_32Uto64,
+ IRExpr_ITE(binop(Iop_CmpNE32,
+ mkexpr(t5), mkU32(0)),
+ mkexpr(t5),
+ IRExpr_ITE(mkexpr(t3),
+ mkU32(2),
+ mkU32(1))))));
+ break;
+ }
- assign(t1, binop(Iop_DivModU32to32, getIReg(rs), getIReg(rt)));
- putHI(unop(Iop_64HIto32, mkexpr(t1)));
- putLO(unop(Iop_64to32, mkexpr(t1)));
- }
- break;
- case 2:
- if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
- DIP("divu r%u, r%u, r%u", rs, rt, rd);
- if (mode64) {
- putIReg(rd, unop(Iop_32Sto64,
- binop(Iop_DivU32,
- unop(Iop_64to32, getIReg(rs)),
- unop(Iop_64to32, getIReg(rt)))));
+ default:
+ return -1;
+ }
} else {
- putIReg(rd, binop(Iop_DivU32, getIReg(rs), getIReg(rt)));
+ ILLEGAL_INSTRUCTON;
}
+
break;
- } else {
- ILLEGAL_INSTRUCTON;
- }
- break;
- case 3:
- if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
- DIP("modu r%u, r%u, r%u", rs, rt, rd);
- if (mode64) {
- putIReg(rd, unop(Iop_32Uto64,
- unop(Iop_64HIto32,
- binop(Iop_DivModU32to32,
- unop(Iop_64to32, getIReg(rs)),
- unop(Iop_64to32, getIReg(rt))))));
- } else {
- t1 = newTemp(Ity_I64);
- assign(t1, binop(Iop_DivModU32to32, getIReg(rs), getIReg(rt)));
- putIReg(rd, unop(Iop_64HIto32, mkexpr(t1)));
- }
- } else {
- ILLEGAL_INSTRUCTON;
- }
- break;
- }
- break;
+ default:
+ if (dis_instr_CCondFmt(cins))
+ break;
- case 0x1C: /* Doubleword Multiply - DMULT; MIPS64 */
- switch (sa) {
- case 0:
- DIP("dmult r%u, r%u", rs, rt);
- if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps) &&
- !VEX_MIPS_CPU_HAS_MIPS32R2(archinfo->hwcaps)) {
- ILLEGAL_INSTRUCTON;
- }
- t0 = newTemp(Ity_I128);
+ return -1;
- assign(t0, binop(Iop_MullS64, getIReg(rs), getIReg(rt)));
+ }
- putHI(unop(Iop_128HIto64, mkexpr(t0)));
- putLO(unop(Iop_128to64, mkexpr(t0)));
- break;
- case 2: /* DMUL */
- if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
- DIP("dmul r%u, r%u, r%u", rd, rs, rt);
- putIReg(rd, unop(Iop_128to64,
- binop(Iop_MullS64, getIReg(rs), getIReg(rt))));
- } else {
- ILLEGAL_INSTRUCTON;
- }
- /* Value for function in documentation is 111000 */
- break;
- case 3: /* DMUH */
- if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
- DIP("dmuh r%u, r%u, r%u", rd, rs, rt);
- putIReg(rd, unop(Iop_128HIto64,
- binop(Iop_MullS64, getIReg(rs), getIReg(rt))));
- } else {
- ILLEGAL_INSTRUCTON;
- }
- break;
}
- break;
+ }
+ break; /* COP1 */
- case 0x1D: /* Doubleword Multiply Unsigned - DMULTU; MIPS64 */
- switch (sa) {
- case 0:
- DIP("dmultu r%u, r%u", rs, rt);
- if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps) &&
- !VEX_MIPS_CPU_HAS_MIPS32R2(archinfo->hwcaps)) {
- ILLEGAL_INSTRUCTON;
- }
- t0 = newTemp(Ity_I128);
+ case 0x03: /* COP1X */
+ switch (function) {
+ case 0x0: { /* LWXC1 */
+ /* Load Word Indexed to Floating Point - LWXC1 (MIPS32r2) */
+ DIP("lwxc1 f%u, r%u(r%u)", fd, rt, rs);
+ t2 = newTemp(ty);
+ assign(t2, binop(mode64 ? Iop_Add64 : Iop_Add32, getIReg(rs),
+ getIReg(rt)));
+
+ if (fp_mode64) {
+ t0 = newTemp(Ity_I64);
+ t1 = newTemp(Ity_I32);
+ t3 = newTemp(Ity_F32);
+ t4 = newTemp(Ity_I64);
+ assign(t3, load(Ity_F32, mkexpr(t2)));
- assign(t0, binop(Iop_MullU64, getIReg(rs), getIReg(rt)));
+ assign(t4, mkWidenFrom32(Ity_I64, unop(Iop_ReinterpF32asI32,
+ mkexpr(t3)), True));
- putHI(unop(Iop_128HIto64, mkexpr(t0)));
- putLO(unop(Iop_128to64, mkexpr(t0)));
- break;
- case 2: /* DMULU */
- if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
- DIP("dmulu r%u, r%u, r%u", rd, rs, rt);
- putIReg(rd, unop(Iop_128to64,
- binop(Iop_MullU64, getIReg(rs), getIReg(rt))));
+ putFReg(fd, unop(Iop_ReinterpI64asF64, mkexpr(t4)));
} else {
- ILLEGAL_INSTRUCTON;
+ putFReg(fd, load(Ity_F32, mkexpr(t2)));
}
+
break;
- case 3: /* DMUHU */
- if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
- DIP("dmuhu r%u, r%u, r%u", rd, rs, rt);
- putIReg(rd, unop(Iop_128HIto64,
- binop(Iop_MullU64, getIReg(rs), getIReg(rt))));
+ }
+
+ case 0x1: { /* LDXC1 */
+ /* Load Doubleword Indexed to Floating Point
+ LDXC1 (MIPS32r2 and MIPS64) */
+ DIP("ldxc1 f%u, r%u(r%u)", fd, rt, rs);
+ t0 = newTemp(ty);
+ assign(t0, binop(mode64 ? Iop_Add64 : Iop_Add32, getIReg(rs),
+ getIReg(rt)));
+ putDReg(fd, load(Ity_F64, mkexpr(t0)));
+ break;
+ }
+
+ case 0x5: /* Load Doubleword Indexed Unaligned to Floating Point - LUXC1;
+ MIPS32r2 and MIPS64 */
+ DIP("luxc1 f%u, r%u(r%u)", fd, rt, rs);
+
+ if ((mode64 || VEX_MIPS_CPU_HAS_MIPS32R2(archinfo->hwcaps))
+ && fp_mode64) {
+ t0 = newTemp(ty);
+ t1 = newTemp(ty);
+ assign(t0, binop(mode64 ? Iop_Add64 : Iop_Add32,
+ getIReg(rs), getIReg(rt)));
+ assign(t1, binop(mode64 ? Iop_And64 : Iop_And32,
+ mkexpr(t0),
+ mode64 ? mkU64(0xfffffffffffffff8ULL)
+ : mkU32(0xfffffff8ULL)));
+ putFReg(fd, load(Ity_F64, mkexpr(t1)));
} else {
- ILLEGAL_INSTRUCTON;
+ ILLEGAL_INSTRUCTON
}
+
break;
- }
- break;
- case 0x1E: /* Doubleword Divide DDIV; MIPS64 */
- switch (sa) {
- case 0:
- DIP("ddiv r%u, r%u", rs, rt);
- if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps) &&
- !VEX_MIPS_CPU_HAS_MIPS32R2(archinfo->hwcaps)) {
- ILLEGAL_INSTRUCTON;
+ case 0x8: { /* Store Word Indexed from Floating Point - SWXC1 */
+ DIP("swxc1 f%u, r%u(r%u)", ft, rt, rs);
+ t0 = newTemp(ty);
+ assign(t0, binop(mode64 ? Iop_Add64 : Iop_Add32, getIReg(rs),
+ getIReg(rt)));
+
+ if (fp_mode64) {
+ store(mkexpr(t0), getLoFromF64(tyF, getFReg(fs)));
+ } else {
+ store(mkexpr(t0), getFReg(fs));
}
- t1 = newTemp(Ity_I128);
- assign(t1, binop(Iop_DivModS64to64, getIReg(rs), getIReg(rt)));
+ break;
+ }
- putHI(unop(Iop_128HIto64, mkexpr(t1)));
- putLO(unop(Iop_128to64, mkexpr(t1)));
+ case 0x9: { /* Store Doubleword Indexed from Floating Point - SDXC1 */
+ DIP("sdxc1 f%u, r%u(r%u)", fs, rt, rs);
+ t0 = newTemp(ty);
+ assign(t0, binop(mode64 ? Iop_Add64 : Iop_Add32, getIReg(rs),
+ getIReg(rt)));
+ store(mkexpr(t0), getDReg(fs));
break;
- case 2: /* DDIV r6 */
- if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
- DIP("ddiv r%u, r%u, r%u", rs, rt, rd);
- putIReg(rd, unop(Iop_128to64,
- binop(Iop_DivModS64to64,
- getIReg(rs), getIReg(rt))));
+ }
+
+ case 0xD: /* Store Doubleword Indexed Unaligned from Floating Point -
+ SUXC1; MIPS64 MIPS32r2 */
+ DIP("suxc1 f%u, r%u(r%u)", fd, rt, rs);
+
+ if ((mode64 || VEX_MIPS_CPU_HAS_MIPS32R2(archinfo->hwcaps))
+ && fp_mode64) {
+ t0 = newTemp(ty);
+ t1 = newTemp(ty);
+ assign(t0, binop(mode64 ? Iop_Add64 : Iop_Add32,
+ getIReg(rs), getIReg(rt)));
+ assign(t1, binop(mode64 ? Iop_And64 : Iop_And32,
+ mkexpr(t0),
+ mode64 ? mkU64(0xfffffffffffffff8ULL)
+ : mkU32(0xfffffff8ULL)));
+ store(mkexpr(t1), getFReg(fs));
} else {
- ILLEGAL_INSTRUCTON;
+ ILLEGAL_INSTRUCTON
}
+
break;
- case 3: /* DMOD r6 */
- if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
- DIP("dmod r%u, r%u, r%u", rs, rt, rd);
- t2 = newTemp(Ity_I128);
- assign(t2, binop(Iop_DivModS64to64, getIReg(rs), getIReg(rt)));
- putIReg(rd, unop(Iop_128HIto64, mkexpr(t2)));
- } else {
- ILLEGAL_INSTRUCTON;
- }
+
+ case 0x0F: {
+ DIP("prefx");
break;
+ }
+
+ case 0x20: { /* MADD.S */
+ DIP("madd.s f%u, f%u, f%u, f%u", fd, fmt, fs, ft);
+ IRExpr *rm = get_IR_roundingmode();
+ t1 = newTemp(Ity_F32);
+ assign(t1, triop(Iop_AddF32, rm, getLoFromF64(tyF, getFReg(fmt)),
+ triop(Iop_MulF32, rm, getLoFromF64(tyF, getFReg(fs)),
+ getLoFromF64(tyF, getFReg(ft)))));
+ putFReg(fd, mkWidenFromF32(tyF, mkexpr(t1)));
+ break; /* MADD.S */
+ }
+
+ case 0x21: { /* MADD.D */
+ DIP("madd.d f%u, f%u, f%u, f%u", fd, fmt, fs, ft);
+ IRExpr *rm = get_IR_roundingmode();
+ putDReg(fd, triop(Iop_AddF64, rm, getDReg(fmt),
+ triop(Iop_MulF64, rm, getDReg(fs),
+ getDReg(ft))));
+ break; /* MADD.D */
+ }
+
+ case 0x28: { /* MSUB.S */
+ DIP("msub.s f%u, f%u, f%u, f%u", fd, fmt, fs, ft);
+ IRExpr *rm = get_IR_roundingmode();
+ t1 = newTemp(Ity_F32);
+ assign(t1, triop(Iop_SubF32, rm,
+ triop(Iop_MulF32, rm, getLoFromF64(tyF, getFReg(fs)),
+ getLoFromF64(tyF, getFReg(ft))),
+ getLoFromF64(tyF, getFReg(fmt))));
+ putFReg(fd, mkWidenFromF32(tyF, mkexpr(t1)));
+ break; /* MSUB.S */
+ }
+
+ case 0x29: { /* MSUB.D */
+ DIP("msub.d f%u, f%u, f%u, f%u", fd, fmt, fs, ft);
+ IRExpr *rm = get_IR_roundingmode();
+ putDReg(fd, triop(Iop_SubF64, rm, triop(Iop_MulF64, rm, getDReg(fs),
+ getDReg(ft)), getDReg(fmt)));
+ break; /* MSUB.D */
+ }
+
+ case 0x30: { /* NMADD.S */
+ DIP("nmadd.s f%u, f%u, f%u, f%u", fd, fmt, fs, ft);
+ IRExpr *rm = get_IR_roundingmode();
+ t1 = newTemp(Ity_F32);
+ assign(t1, triop(Iop_AddF32, rm, getLoFromF64(tyF, getFReg(fmt)),
+ triop(Iop_MulF32, rm, getLoFromF64(tyF, getFReg(fs)),
+ getLoFromF64(tyF, getFReg(ft)))));
+ putFReg(fd, mkWidenFromF32(tyF, unop(Iop_NegF32, mkexpr(t1))));
+ break; /* NMADD.S */
+ }
+
+ case 0x31: { /* NMADD.D */
+ DIP("nmadd.d f%u, f%u, f%u, f%u", fd, fmt, fs, ft);
+ IRExpr *rm = get_IR_roundingmode();
+ t1 = newTemp(Ity_F64);
+ assign(t1, triop(Iop_AddF64, rm, getDReg(fmt),
+ triop(Iop_MulF64, rm, getDReg(fs),
+ getDReg(ft))));
+ putDReg(fd, unop(Iop_NegF64, mkexpr(t1)));
+ break; /* NMADD.D */
+ }
+
+ case 0x38: { /* NMSUBB.S */
+ DIP("nmsub.s f%u, f%u, f%u, f%u", fd, fmt, fs, ft);
+ IRExpr *rm = get_IR_roundingmode();
+ t1 = newTemp(Ity_F32);
+ assign(t1, triop(Iop_SubF32, rm,
+ triop(Iop_MulF32, rm, getLoFromF64(tyF, getFReg(fs)),
+ getLoFromF64(tyF, getFReg(ft))),
+ getLoFromF64(tyF, getFReg(fmt))));
+ putFReg(fd, mkWidenFromF32(tyF, unop(Iop_NegF32, mkexpr(t1))));
+ break; /* NMSUBB.S */
+ }
+
+ case 0x39: { /* NMSUBB.D */
+ DIP("nmsub.d f%u, f%u, f%u, f%u", fd, fmt, fs, ft);
+ IRExpr *rm = get_IR_roundingmode();
+ t1 = newTemp(Ity_F64);
+ assign(t1, triop(Iop_SubF64, rm, triop(Iop_MulF64, rm, getDReg(fs),
+ getDReg(ft)), getDReg(fmt)));
+ putDReg(fd, unop(Iop_NegF64, mkexpr(t1)));
+ break; /* NMSUBB.D */
+ }
+
+ default:
+ return -1;
}
+
break;
- case 0x1F: /* Doubleword Divide Unsigned DDIVU; MIPS64 check this */
- switch (sa) {
- case 0:
- DIP("ddivu r%u, r%u", rs, rt);
- if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps) &&
- !VEX_MIPS_CPU_HAS_MIPS32R2(archinfo->hwcaps)) {
- ILLEGAL_INSTRUCTON;
- }
- t1 = newTemp(Ity_I128);
+ case 0x04: /* BEQL */
+ DIP("beql r%u, r%u, %u", rs, rt, imm);
+ *lastn = dis_branch_likely(binop(mode64 ? Iop_CmpNE64 : Iop_CmpNE32,
+ getIReg(rs), getIReg(rt)), imm);
+ break;
- assign(t1, binop(Iop_DivModU64to64, getIReg(rs), getIReg(rt)));
+ case 0x05: /* BNEL */
+ DIP("bnel r%u, r%u, %u", rs, rt, imm);
+ *lastn = dis_branch_likely(binop(mode64 ? Iop_CmpEQ64 : Iop_CmpEQ32,
+ getIReg(rs), getIReg(rt)), imm);
+ break;
- putHI(unop(Iop_128HIto64, mkexpr(t1)));
- putLO(unop(Iop_128to64, mkexpr(t1)));
- break;
- case 2:
- if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
- DIP("ddivu r%u, r%u, r%u", rs, rt, rd);
- putIReg(rd, unop(Iop_128to64, binop(Iop_DivModU64to64,
- getIReg(rs), getIReg(rt))));
+ case 0x06: /* 0x16 ??? BLEZL, BLEZC, BGEZC, BGEC */
+ if (rt == 0) { /* BLEZL */
+ DIP("blezl r%u, %u", rs, imm);
+ *lastn = dis_branch_likely(unop(Iop_Not1, (binop(mode64 ? Iop_CmpLE64S :
+ Iop_CmpLE32S, getIReg(rs), mode64 ?
+ mkU64(0x0) : mkU32(0x0)))), imm);
+ } else if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+ if (rs == 0) { /* BLEZC */
+ DIP("blezc r%u, %u", rt, imm);
+
+ if (mode64) {
+ dis_branch_compact(False,
+ binop(Iop_CmpLE64S, getIReg(rt), mkU64(0x0)),
+ imm, dres);
} else {
- ILLEGAL_INSTRUCTON;
+ dis_branch_compact(False,
+ binop(Iop_CmpLE32S, getIReg(rt), mkU32(0x0)),
+ imm, dres);
}
- break;
- case 3:
- if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
- DIP("dmodu r%u, r%u, r%u", rs, rt, rd);
- putIReg(rd, unop(Iop_128HIto64, binop(Iop_DivModU64to64,
- getIReg(rs), getIReg(rt))));
+ } else if (rt == rs) { /* BGEZC */
+ DIP("bgezc r%u, %u", rt, imm);
+
+ if (mode64) {
+ dis_branch_compact(False,
+ binop(Iop_CmpLE64S, mkU64(0x0), getIReg(rt)),
+ imm, dres);
} else {
- ILLEGAL_INSTRUCTON;
+ dis_branch_compact(False,
+ binop(Iop_CmpLE32S, mkU32(0x0), getIReg(rt)),
+ imm, dres);
}
- break;
- }
- break;
+ } else { /* BGEC */
+ DIP("bgec r%u, r%u, %u", rs, rt, imm);
- case 0x10: { /* MFHI, CLZ R6 */
- if (((instr_index >> 6) & 0x1f) == 1) { /* CLZ */
- if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
- DIP("clz r%u, r%u", rd, rs);
if (mode64) {
- IRTemp tmpClz32 = newTemp(Ity_I32);
- IRTemp tmpRs32 = newTemp(Ity_I32);
-
- assign(tmpRs32, mkNarrowTo32(ty, getIReg(rs)));
- assign(tmpClz32, unop(Iop_Clz32, mkexpr(tmpRs32)));
- putIReg(rd, mkWidenFrom32(ty, mkexpr(tmpClz32), True));
+ dis_branch_compact(False,
+ binop(Iop_CmpLE64S, getIReg(rt), getIReg(rs)),
+ imm, dres);
} else {
- t1 = newTemp(Ity_I1);
- assign(t1, binop(Iop_CmpEQ32, getIReg(rs), mkU32(0)));
- putIReg(rd, IRExpr_ITE(mkexpr(t1),
- mkU32(0x00000020),
- unop(Iop_Clz32, getIReg(rs))));
+ dis_branch_compact(False,
+ binop(Iop_CmpLE32S, getIReg(rt), getIReg(rs)),
+ imm, dres);
}
- } else {
- ILLEGAL_INSTRUCTON;
- }
- break;
- } else if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
- /* If DSP is present -> DSP ASE MFHI */
- UInt retVal = disDSPInstr_MIPS_WRK ( cins );
- if (0 != retVal ) {
- goto decode_failure;
}
- break;
} else {
- DIP("mfhi r%u", rd);
- putIReg(rd, getHI());
- break;
+ ILLEGAL_INSTRUCTON
}
- }
- case 0x11: { /* MTHI, CLO R6 */
- if (((instr_index >> 6) & 0x1f) == 1) { /* CLO */
- if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
- DIP("clo r%u, r%u", rd, rs);
+ break;
+
+ case 0x07: /* BGTZL, BGTZC, BLTZC, BLTC */
+ if (rt == 0) { /* BGTZL */
+ DIP("bgtzl r%u, %u", rs, imm);
+
+ if (mode64)
+ *lastn = dis_branch_likely(binop(Iop_CmpLE64S, getIReg(rs),
+ mkU64(0x00)), imm);
+ else
+ *lastn = dis_branch_likely(binop(Iop_CmpLE32S, getIReg(rs),
+ mkU32(0x00)), imm);
+ } else if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+ if (rs == 0) { /* BGTZC */
+ DIP("bgtzc r%u, %u", rt, imm);
+
if (mode64) {
- IRTemp tmpClo32 = newTemp(Ity_I32);
- IRTemp tmpRs32 = newTemp(Ity_I32);
- assign(tmpRs32, mkNarrowTo32(ty, getIReg(rs)));
+ dis_branch_compact(False,
+ unop(Iop_Not1,
+ binop(Iop_CmpLE64S,
+ getIReg(rt), mkU64(0x0))),
+ imm, dres);
+ } else {
+ dis_branch_compact(False,
+ unop(Iop_Not1,
+ binop(Iop_CmpLE32S,
+ getIReg(rt), mkU32(0x0))),
+ imm, dres);
+ }
+ } else if (rs == rt) { /* BLTZC */
+ DIP("bltzc r%u, %u", rt, imm);
- t1 = newTemp(Ity_I1);
- assign(t1, binop(Iop_CmpEQ32, mkexpr(tmpRs32), mkU32(0xffffffff)));
- assign(tmpClo32, IRExpr_ITE(mkexpr(t1),
- mkU32(0x00000020),
- unop(Iop_Clz32, unop(Iop_Not32, mkexpr(tmpRs32)))));
+ if (mode64) {
+ dis_branch_compact(False,
+ unop(Iop_Not1,
+ binop(Iop_CmpLE64S,
+ mkU64(0x0), getIReg(rt))),
+ imm, dres);
+ } else {
+ dis_branch_compact(False,
+ unop(Iop_Not1,
+ binop(Iop_CmpLE32S,
+ mkU32(0x0), getIReg(rt))),
+ imm, dres);
+ }
+ } else { /* BLTC */
+ DIP("bltc r%u, r%u, %u", rs, rt, imm);
- putIReg(rd, mkWidenFrom32(ty, mkexpr(tmpClo32), True));
- break;
+ if (mode64) {
+ dis_branch_compact(False,
+ unop(Iop_Not1,
+ binop(Iop_CmpLE64S,
+ getIReg(rt), getIReg(rs))),
+ imm, dres);
} else {
- t1 = newTemp(Ity_I1);
- assign(t1, binop(Iop_CmpEQ32, getIReg(rs), mkU32(0xffffffff)));
- putIReg(rd, IRExpr_ITE(mkexpr(t1),
- mkU32(0x00000020),
- unop(Iop_Clz32,
- unop(Iop_Not32, getIReg(rs)))));
+ dis_branch_compact(False,
+ unop(Iop_Not1,
+ binop(Iop_CmpLE32S,
+ getIReg(rt), getIReg(rs))),
+ imm, dres);
}
- } else {
- ILLEGAL_INSTRUCTON;
- }
- break;
- } else if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
- /* If DSP is present -> DSP ASE MTHI */
- UInt retVal = disDSPInstr_MIPS_WRK ( cins );
- if (0 != retVal ) {
- goto decode_failure;
}
- break;
} else {
- DIP("mthi r%u", rs);
- putHI(getIReg(rs));
- break;
+ ILLEGAL_INSTRUCTON
}
+
+ break;
+
+#if defined(__mips__) && ((defined(__mips_isa_rev) && __mips_isa_rev < 6))
+
+ case 0x08: { /* Doubleword Add Immidiate - DADDI; MIPS64 */
+ DIP("daddi r%u, r%u, %u", rt, rs, imm);
+ IRTemp tmpRs64 = newTemp(Ity_I64);
+ assign(tmpRs64, getIReg(rs));
+
+ t0 = newTemp(Ity_I64);
+ t1 = newTemp(Ity_I64);
+ t2 = newTemp(Ity_I64);
+ t3 = newTemp(Ity_I64);
+ t4 = newTemp(Ity_I64);
+ /* dst = src0 + sign(imm)
+ if(sign(src0 ) != sign(imm ))
+ goto no overflow;
+ if(sign(dst) == sign(src0 ))
+ goto no overflow;
+ we have overflow! */
+
+ assign(t0, binop(Iop_Add64, mkexpr(tmpRs64),
+ mkU64(extend_s_16to64(imm))));
+ assign(t1, binop(Iop_Xor64, mkexpr(tmpRs64),
+ mkU64(extend_s_16to64(imm))));
+ assign(t2, unop(Iop_1Sto64, binop(Iop_CmpEQ64, binop(Iop_And64,
+ mkexpr(t1), mkU64(0x8000000000000000ULL)),
+ mkU64(0x8000000000000000ULL))));
+
+ assign(t3, binop(Iop_Xor64, mkexpr(t0), mkexpr(tmpRs64)));
+ assign(t4, unop(Iop_1Sto64, binop(Iop_CmpNE64, binop(Iop_And64,
+ mkexpr(t3), mkU64(0x8000000000000000ULL)),
+ mkU64(0x8000000000000000ULL))));
+
+ stmt(IRStmt_Exit(binop(Iop_CmpEQ64, binop(Iop_Or64, mkexpr(t2),
+ mkexpr(t4)), mkU64(0)), Ijk_SigFPE_IntOvf,
+ IRConst_U64(guest_PC_curr_instr + 4),
+ OFFB_PC));
+
+ putIReg(rt, mkexpr(t0));
+ break;
}
- case 0x12: { /* MFLO */
- if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
- /* If DSP is present -> DSP ASE MFLO */
- UInt retVal = disDSPInstr_MIPS_WRK ( cins );
- if (0 != retVal ) {
- goto decode_failure;
- }
- break;
- } else {
- switch (sa) {
- case 0:
- DIP("mflo r%u", rd);
- if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps) &&
- !VEX_MIPS_CPU_HAS_MIPS32R2(archinfo->hwcaps)) {
- ILLEGAL_INSTRUCTON;
- }
- putIReg(rd, getLO());
- break;
- case 1:
- DIP("dclz r%u, r%u", rd, rs);
- t1 = newTemp(Ity_I1);
- assign(t1, binop(Iop_CmpEQ64, getIReg(rs), mkU64(0)));
- putIReg(rd, IRExpr_ITE(mkexpr(t1),
- mkU64(0x00000040),
- unop(Iop_Clz64, getIReg(rs))));
- break;
+#elif defined(__mips__) && ((defined(__mips_isa_rev) && __mips_isa_rev >= 6))
+
+ case 0x08: { /* BNEZALC, BNEC, BNVC */
+ if (rs == 0) { /* BNEZALC */
+ DIP("bnezalc r%u, %u", rt, imm);
+
+ if (mode64) {
+ dis_branch_compact(True,
+ unop(Iop_Not1,
+ binop(Iop_CmpEQ64, getIReg(rt), mkU64(0x0))),
+ imm, dres);
+ } else {
+ dis_branch_compact(True,
+ unop(Iop_Not1,
+ binop(Iop_CmpEQ32, getIReg(rt), mkU32(0x0))),
+ imm, dres);
}
- break;
- }
- }
+ } else if (rs < rt) { /* BNEC */
+ DIP("bnec r%u, %u", rt, imm);
- case 0x13: { /* MTLO */
- if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) {
- /* If DSP is present -> DSP ASE MTLO */
- UInt retVal = disDSPInstr_MIPS_WRK ( cins );
- if (0 != retVal ) {
- goto decode_failure;
+ if (mode64) {
+ dis_branch_compact(False,
+ unop(Iop_Not1,
+ binop(Iop_CmpEQ64,
+ getIReg(rt), getIReg(rs))),
+ imm, dres);
+ } else {
+ dis_branch_compact(False,
+ unop(Iop_Not1,
+ binop(Iop_CmpEQ32,
+ getIReg(rt), getIReg(rs))),
+ imm, dres);
}
- break;
- } else {
- switch (sa) {
- case 0:
- DIP("mtlo r%u", rs);
- if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps) &&
- !VEX_MIPS_CPU_HAS_MIPS32R2(archinfo->hwcaps)) {
- ILLEGAL_INSTRUCTON;
- }
- putLO(getIReg(rs));
- break;
- case 1:
- DIP("dclo r%u, r%u", rd, rs);
- t1 = newTemp(Ity_I1);
- assign(t1, binop(Iop_CmpEQ64, getIReg(rs),
- mkU64(0xffffffffffffffffULL)));
- putIReg(rd, IRExpr_ITE(mkexpr(t1),
- mkU64(0x40),
- unop(Iop_Clz64, unop(Iop_Not64,
- getIReg(rs)))));
- break;
+ } else { /* BNVC */
+ DIP("bnvc r%u, r%u, %u", rs, rt, imm);
+
+ if (mode64) {
+ t0 = newTemp(Ity_I32);
+ t1 = newTemp(Ity_I32);
+ t2 = newTemp(Ity_I32);
+ t3 = newTemp(Ity_I32);
+ assign(t0, IRExpr_ITE(binop(Iop_CmpLT64S,
+ getIReg(rt),
+ mkU64(0xffffffff80000000ULL)),
+ mkU32(1),
+ IRExpr_ITE(binop(Iop_CmpLT64S,
+ getIReg(rt),
+ mkU64(0x7FFFFFFFULL)),
+ mkU32(0), mkU32(1))));
+ assign(t1, IRExpr_ITE(binop(Iop_CmpLT64S,
+ getIReg(rs),
+ mkU64(0xffffffff80000000ULL)),
+ mkU32(1),
+ IRExpr_ITE(binop(Iop_CmpLT64S,
+ getIReg(rs),
+ mkU64(0x7FFFFFFFULL)),
+ mkU32(0), mkU32(1))));
+ assign(t2, IRExpr_ITE(binop(Iop_CmpLT64S,
+ binop(Iop_Add64,
+ getIReg(rt), getIReg(rs)),
+ mkU64(0xffffffff80000000ULL)),
+ mkU32(1),
+ IRExpr_ITE(binop(Iop_CmpLT64S,
+ binop(Iop_Add64,
+ getIReg(rt),
+ getIReg(rs)),
+ mkU64(0x7FFFFFFFULL)),
+ mkU32(0), mkU32(1))));
+ assign(t3, binop(Iop_Add32,
+ mkexpr(t0),
+ binop(Iop_Add32, mkexpr(t1), mkexpr(t2))));
+ dis_branch_compact(False,
+ binop(Iop_CmpEQ32, mkexpr(t3), mkU32(0)),
+ imm, dres);
+ } else {
+ IRTemp tmpRs32 = newTemp(Ity_I32);
+ IRTemp tmpRt32 = newTemp(Ity_I32);
+
+ assign(tmpRs32, getIReg(rs));
+ assign(tmpRt32, getIReg(rt));
+ t0 = newTemp(Ity_I32);
+ t1 = newTemp(Ity_I32);
+ t2 = newTemp(Ity_I32);
+ t3 = newTemp(Ity_I32);
+ t4 = newTemp(Ity_I32);
+ /* dst = src0 + src1
+ if (sign(src0 ) != sign(src1 ))
+ goto no overflow;
+ if (sign(dst) == sign(src0 ))
+ goto no overflow;
+ we have overflow! */
+
+ assign(t0, binop(Iop_Add32, mkexpr(tmpRs32), mkexpr(tmpRt32)));
+ assign(t1, binop(Iop_Xor32, mkexpr(tmpRs32), mkexpr(tmpRt32)));
+ assign(t2, unop(Iop_1Uto32,
+ binop(Iop_CmpEQ32,
+ binop(Iop_And32, mkexpr(t1), mkU32(0x80000000)),
+ mkU32(0x80000000))));
+
+ assign(t3, binop(Iop_Xor32, mkexpr(t0), mkexpr(tmpRs32)));
+ assign(t4, unop(Iop_1Uto32,
+ binop(Iop_CmpNE32,
+ binop(Iop_And32, mkexpr(t3), mkU32(0x80000000)),
+ mkU32(0x80000000))));
+
+ dis_branch_compact(False, binop(Iop_CmpNE32 ,
+ binop(Iop_Or32, mkexpr(t2), mkexpr(t4)),
+ mkU32(0)), imm, dres);
}
- break;
}
+
+ break;
}
- case 0x21: /* ADDU */
- DIP("addu r%u, r%u, r%u", rd, rs, rt);
- if (mode64) {
- ALU_PATTERN64(Iop_Add32);
- } else {
- ALU_PATTERN(Iop_Add32);
- }
+#endif
+
+ case 0x09: /* Doubleword Add Immidiate Unsigned - DADDIU; MIPS64 */
+ DIP("daddiu r%u, r%u, %u", rt, rs, imm);
+ putIReg(rt, binop(Iop_Add64, getIReg(rs), mkU64(extend_s_16to64(imm))));
break;
- case 0x22: { /* SUB */
- DIP("sub r%u, r%u, r%u", rd, rs, rt);
- IRTemp tmpRs32 = newTemp(Ity_I32);
- IRTemp tmpRt32 = newTemp(Ity_I32);
+ case 0x0A: { /* LDL */
+ /* Load Doubleword Left - LDL; MIPS64 */
+ vassert(mode64);
+ DIP("ldl r%u, %u(r%u)", rt, imm, rs);
+ /* t1 = addr */
+#if defined (_MIPSEL)
+ t1 = newTemp(Ity_I64);
+ assign(t1, binop(Iop_Add64, getIReg(rs), mkU64(extend_s_16to64(imm))));
+#elif defined (_MIPSEB)
+ t1 = newTemp(Ity_I64);
+ assign(t1, binop(Iop_Xor64, mkU64(0x7), binop(Iop_Add64, getIReg(rs),
+ mkU64(extend_s_16to64(imm)))));
+#endif
+ /* t2 = word addr */
+ /* t4 = addr mod 8 */
+ LWX_SWX_PATTERN64_1;
- assign(tmpRs32, mkNarrowTo32(ty, getIReg(rs)));
- assign(tmpRt32, mkNarrowTo32(ty, getIReg(rt)));
- t0 = newTemp(Ity_I32);
- t1 = newTemp(Ity_I32);
- t2 = newTemp(Ity_I32);
- t3 = newTemp(Ity_I32);
- t4 = newTemp(Ity_I32);
- t5 = newTemp(Ity_I32);
- /* dst = src0 + (-1 * src1)
- if(sign(src0 ) != sign((-1 * src1) ))
- goto no overflow;
- if(sign(dst) == sign(src0 ))
- goto no overflow;
- we have overflow! */
+ /* t3 = word content - shifted */
+ t3 = newTemp(Ity_I64);
+ assign(t3, binop(Iop_Shl64, load(Ity_I64, mkexpr(t2)),
+ narrowTo(Ity_I8, binop(Iop_Shl64, binop(Iop_Sub64, mkU64(0x07),
+ mkexpr(t4)), mkU8(3)))));
- assign(t5, binop(Iop_Mul32, mkexpr(tmpRt32), mkU32(-1)));
- assign(t0, binop(Iop_Add32, mkexpr(tmpRs32), mkexpr(t5)));
- assign(t1, binop(Iop_Xor32, mkexpr(tmpRs32), mkexpr(t5)));
- assign(t2, unop(Iop_1Sto32, binop(Iop_CmpEQ32, binop(Iop_And32,
- mkexpr(t1), mkU32(0x80000000)), mkU32(0x80000000))));
+ /* rt content - adjusted */
+ t5 = newTemp(Ity_I64);
+ t6 = newTemp(Ity_I64);
+ t7 = newTemp(Ity_I64);
- assign(t3, binop(Iop_Xor32, mkexpr(t0), mkexpr(tmpRs32)));
- assign(t4, unop(Iop_1Sto32, binop(Iop_CmpNE32, binop(Iop_And32,
- mkexpr(t3), mkU32(0x80000000)), mkU32(0x80000000))));
+ assign(t5, binop(Iop_Mul64, mkexpr(t4), mkU64(0x8)));
- stmt(IRStmt_Exit(binop(Iop_CmpEQ32, binop(Iop_Or32, mkexpr(t2),
- mkexpr(t4)), mkU32(0)), Ijk_SigFPE_IntOvf,
- mode64 ? IRConst_U64(guest_PC_curr_instr + 4) :
- IRConst_U32(guest_PC_curr_instr + 4),
- OFFB_PC));
+ assign(t6, binop(Iop_Shr64, mkU64(0x00FFFFFFFFFFFFFFULL),
+ narrowTo(Ity_I8, mkexpr(t5))));
- putIReg(rd, mkWidenFrom32(ty, mkexpr(t0), True));
+ assign(t7, binop(Iop_And64, getIReg(rt), mkexpr(t6)));
+
+ putIReg(rt, binop(Iop_Or64, mkexpr(t7), mkexpr(t3)));
break;
}
- case 0x23: /* SUBU */
- DIP("subu r%u, r%u, r%u", rd, rs, rt);
- if (mode64) {
- ALU_PATTERN64(Iop_Sub32);
+
+ case 0x0B: { /* LDR */
+ /* Load Doubleword Right - LDR; MIPS64 */
+ vassert(mode64);
+ DIP("ldr r%u,%u(r%u)", rt, imm, rs);
+ /* t1 = addr */
+#if defined (_MIPSEL)
+ t1 = newTemp(Ity_I64);
+ assign(t1, binop(Iop_Add64, getIReg(rs), mkU64(extend_s_16to64(imm))));
+#elif defined (_MIPSEB)
+ t1 = newTemp(Ity_I64);
+ assign(t1, binop(Iop_Xor64, mkU64(0x7), binop(Iop_Add64, getIReg(rs),
+ mkU64(extend_s_16to64(imm)))));
+#endif
+ /* t2 = word addr */
+ /* t4 = addr mod 8 */
+ LWX_SWX_PATTERN64_1;
+
+ /* t3 = word content - shifted */
+ t3 = newTemp(Ity_I64);
+ assign(t3, binop(Iop_Shr64, load(Ity_I64, mkexpr(t2)),
+ narrowTo(Ity_I8, binop(Iop_Shl64, mkexpr(t4), mkU8(3)))));
+
+ /* rt content - adjusted */
+ t5 = newTemp(Ity_I64);
+ assign(t5, binop(Iop_And64, getIReg(rt), unop(Iop_Not64,
+ binop(Iop_Shr64, mkU64(0xFFFFFFFFFFFFFFFFULL),
+ narrowTo(Ity_I8, binop(Iop_Shl64, mkexpr(t4), mkU8(0x3)))))));
+
+ putIReg(rt, binop(Iop_Or64, mkexpr(t5), mkexpr(t3)));
+ break;
+ }
+
+ case 0x0C: /* Special2 */
+ return disInstr_MIPS_WRK_Special2(cins, archinfo, abiinfo, dres, bstmt, lastn,
+ resteerOkFn, callback_opaque);
+
+ case 0x0D: /* DAUI */
+ if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+ DIP("daui r%u, r%u, %x", rt, rs, imm);
+ putIReg(rt, binop(Iop_Add64, getIReg(rs), mkU64(extend_s_32to64(imm << 16))));
} else {
- ALU_PATTERN(Iop_Sub32);
+ ILLEGAL_INSTRUCTON
+ }
+
+ break;
+
+ case 0x0E: /* MIPS MSA (SIMD) */
+ if (has_msa) {
+ Int retVal = disMSAInstr_MIPS_WRK(cins);
+
+ if (retVal == 0) {
+ break;
+ } else if (retVal == -2) {
+ ILLEGAL_INSTRUCTON
+ break;
+ }
}
+
+ vex_printf("Error occured while trying to decode MIPS MSA "
+ "instruction.\nYour platform probably doesn't support "
+ "MIPS MSA (SIMD) ASE.\n");
+ return -1;
+
+ case 0x0F: /* Special3 */
+ return disInstr_MIPS_WRK_Special3(cins, archinfo, abiinfo, dres, bstmt, lastn,
+ resteerOkFn, callback_opaque);
+
+ default:
+ return -1;
+ }
+
+ return 0;
+}
+
+static UInt disInstr_MIPS_WRK_20(UInt cins)
+{
+ IRTemp t1 = 0, t2, t3, t4, t5;
+ UInt opcode, rs, rt, imm;
+
+ opcode = get_opcode(cins);
+ imm = get_imm(cins);
+ rs = get_rs(cins);
+ rt = get_rt(cins);
+ IRType ty = mode64 ? Ity_I64 : Ity_I32;
+
+ switch (opcode & 0x0F) {
+ case 0x00: /* LB */
+ DIP("lb r%u, %u(r%u)", rt, imm, rs);
+ LOAD_STORE_PATTERN;
+
+ if (mode64)
+ putIReg(rt, unop(Iop_8Sto64, load(Ity_I8, mkexpr(t1))));
+ else
+ putIReg(rt, unop(Iop_8Sto32, load(Ity_I8, mkexpr(t1))));
+
break;
- case 0x24: /* AND */
- DIP("and r%u, r%u, r%u", rd, rs, rt);
- if (mode64) {
- ALU_PATTERN(Iop_And64);
- } else {
- ALU_PATTERN(Iop_And32);
- }
+ case 0x01: /* LH */
+ DIP("lh r%u, %u(r%u)", rt, imm, rs);
+ LOAD_STORE_PATTERN;
+
+ if (mode64)
+ putIReg(rt, unop(Iop_16Sto64, load(Ity_I16, mkexpr(t1))));
+ else
+ putIReg(rt, unop(Iop_16Sto32, load(Ity_I16, mkexpr(t1))));
+
break;
- case 0x25: /* OR */
- DIP("or r%u, r%u, r%u", rd, rs, rt);
+ case 0x02: /* LWL */
+ DIP("lwl r%u, %u(r%u)", rt, imm, rs);
+
if (mode64) {
- ALU_PATTERN(Iop_Or64);
+ /* t1 = addr */
+ t1 = newTemp(Ity_I64);
+#if defined (_MIPSEL)
+ assign(t1, binop(Iop_Add64, getIReg(rs), mkU64(extend_s_16to64(imm))));
+#elif defined (_MIPSEB)
+ assign(t1, binop(Iop_Xor64,
+ mkU64(0x03),
+ binop(Iop_Add64,
+ getIReg(rs),
+ mkU64(extend_s_16to64(imm)))));
+#endif
+ /* t2 = word addr */
+ /* t4 = addr mod 4 */
+ LWX_SWX_PATTERN64;
+
+ /* t3 = word content - shifted */
+ t3 = newTemp(Ity_I32);
+ assign(t3, binop(Iop_Shl32,
+ load(Ity_I32, mkexpr(t2)),
+ narrowTo(Ity_I8,
+ binop(Iop_Shl32,
+ binop(Iop_Sub32,
+ mkU32(0x03),
+ mkexpr(t4)),
+ mkU8(3)))));
+
+ /* rt content - adjusted */
+ t5 = newTemp(Ity_I32);
+ assign(t5, binop(Iop_And32,
+ mkNarrowTo32(ty, getIReg(rt)),
+ binop(Iop_Shr32,
+ mkU32(0x00FFFFFF),
+ narrowTo(Ity_I8, binop(Iop_Mul32,
+ mkU32(0x08),
+ mkexpr(t4))))));
+
+ putIReg(rt, mkWidenFrom32(ty, binop(Iop_Or32, mkexpr(t5),
+ mkexpr(t3)), True));
} else {
- ALU_PATTERN(Iop_Or32);
+ /* t1 = addr */
+ t1 = newTemp(Ity_I32);
+#if defined (_MIPSEL)
+ assign(t1, binop(Iop_Add32, getIReg(rs), mkU32(extend_s_16to32(imm))));
+#elif defined (_MIPSEB)
+ assign(t1, binop(Iop_Xor32, mkU32(0x3), binop(Iop_Add32, getIReg(rs),
+ mkU32(extend_s_16to32(imm)))));
+#endif
+
+ /* t2 = word addr */
+ /* t4 = addr mod 4 */
+ LWX_SWX_PATTERN;
+
+ /* t3 = word content - shifted */
+ t3 = newTemp(Ity_I32);
+ assign(t3, binop(Iop_Shl32, load(Ity_I32, mkexpr(t2)), narrowTo(Ity_I8,
+ binop(Iop_Shl32, binop(Iop_Sub32, mkU32(0x03), mkexpr(t4)),
+ mkU8(3)))));
+
+ /* rt content - adjusted */
+ t5 = newTemp(Ity_I32);
+ assign(t5, binop(Iop_And32,
+ getIReg(rt),
+ binop(Iop_Shr32,
+ mkU32(0x00FFFFFF),
+ narrowTo(Ity_I8, binop(Iop_Mul32,
+ mkU32(0x08),
+ mkexpr(t4))))));
+
+ putIReg(rt, binop(Iop_Or32, mkexpr(t5), mkexpr(t3)));
}
+
break;
- case 0x26: /* XOR */
- DIP("xor r%u, r%u, r%u", rd, rs, rt);
- if (mode64) {
- ALU_PATTERN(Iop_Xor64);
- } else {
- ALU_PATTERN(Iop_Xor32);
- }
+ case 0x03: /* LW */
+ DIP("lw r%u, %u(r%u)", rt, imm, rs);
+ LOAD_STORE_PATTERN;
+ putIReg(rt, mkWidenFrom32(ty, load(Ity_I32, mkexpr(t1)), True));
break;
- case 0x27: /* NOR */
- DIP("nor r%u, r%u, r%u", rd, rs, rt);
+ case 0x04: /* LBU */
+ DIP("lbu r%u, %u(r%u)", rt, imm, rs);
+ LOAD_STORE_PATTERN;
+
if (mode64)
- putIReg(rd, unop(Iop_Not64, binop(Iop_Or64, getIReg(rs),
- getIReg(rt))));
+ putIReg(rt, unop(Iop_8Uto64, load(Ity_I8, mkexpr(t1))));
else
- putIReg(rd, unop(Iop_Not32, binop(Iop_Or32, getIReg(rs),
- getIReg(rt))));
+ putIReg(rt, unop(Iop_8Uto32, load(Ity_I8, mkexpr(t1))));
+
break;
- case 0x08: /* JR */
- DIP("jr r%u", rs);
- t0 = newTemp(ty);
- assign(t0, getIReg(rs));
- lastn = mkexpr(t0);
+ case 0x05: /* LHU */
+ DIP("lhu r%u, %u(r%u)", rt, imm, rs);
+ LOAD_STORE_PATTERN;
+
+ if (mode64)
+ putIReg(rt, unop(Iop_16Uto64, load(Ity_I16, mkexpr(t1))));
+ else
+ putIReg(rt, unop(Iop_16Uto32, load(Ity_I16, mkexpr(t1))));
+
break;
- case 0x09: /* JALR */
- DIP("jalr r%u r%u", rd, rs);
+ case 0x06: /* LWR */
+ DIP("lwr r%u, %u(r%u)", rt, imm, rs);
+
if (mode64) {
- putIReg(rd, mkU64(guest_PC_curr_instr + 8));
- t0 = newTemp(Ity_I64);
- assign(t0, getIReg(rs));
- lastn = mkexpr(t0);
+ /* t1 = addr */
+ t1 = newTemp(Ity_I64);
+
+#if defined (_MIPSEL)
+ assign(t1, binop(Iop_Add64, getIReg(rs), mkU64(extend_s_16to64(imm))));
+#elif defined (_MIPSEB)
+ assign(t1, binop(Iop_Xor64,
+ mkU64(0x3),
+ binop(Iop_Add64,
+ getIReg(rs),
+ mkU64(extend_s_16to64(imm)))));
+#endif
+ /* t2 = word addr */
+ /* t4 = addr mod 4 */
+ LWX_SWX_PATTERN64;
+
+ /* t3 = word content - shifted */
+ t3 = newTemp(Ity_I32);
+ assign(t3, binop(Iop_Shr32,
+ load(Ity_I32, mkexpr(t2)),
+ narrowTo(Ity_I8,
+ binop(Iop_Shl32, mkexpr(t4), mkU8(0x03)))));
+
+ /* rt content - adjusted */
+ t5 = newTemp(Ity_I32);
+ assign(t5, binop(Iop_And32, mkNarrowTo32(ty, getIReg(rt)),
+ unop(Iop_Not32, binop(Iop_Shr32, mkU32(0xFFFFFFFF),
+ narrowTo(Ity_I8, binop(Iop_Shl32, mkexpr(t4), mkU8(0x3)))))));
+
+ putIReg(rt, mkWidenFrom32(ty, binop(Iop_Or32, mkexpr(t5),
+ mkexpr(t3)), True));
+
} else {
- putIReg(rd, mkU32(guest_PC_curr_instr + 8));
- t0 = newTemp(Ity_I32);
- assign(t0, getIReg(rs));
- lastn = mkexpr(t0);
+ /* t1 = addr */
+ t1 = newTemp(Ity_I32);
+#if defined (_MIPSEL)
+ assign(t1, binop(Iop_Add32, getIReg(rs), mkU32(extend_s_16to32(imm))));
+#elif defined (_MIPSEB)
+ assign(t1, binop(Iop_Xor32, mkU32(0x3), binop(Iop_Add32, getIReg(rs),
+ mkU32(extend_s_16to32(imm)))));
+#endif
+
+ /* t2 = word addr */
+ /* t4 = addr mod 4 */
+ LWX_SWX_PATTERN;
+
+ /* t3 = word content - shifted */
+ t3 = newTemp(Ity_I32);
+ assign(t3, binop(Iop_Shr32, load(Ity_I32, mkexpr(t2)),
+ narrowTo(Ity_I8, binop(Iop_Shl32, mkexpr(t4),
+ mkU8(3)))));
+
+ /* rt content - adjusted */
+ t5 = newTemp(Ity_I32);
+ assign(t5, binop(Iop_And32, getIReg(rt), unop(Iop_Not32,
+ binop(Iop_Shr32, mkU32(0xFFFFFFFF), narrowTo(Ity_I8,
+ binop(Iop_Shl32, mkexpr(t4), mkU8(0x3)))))));
+
+ putIReg(rt, binop(Iop_Or32, mkexpr(t5), mkexpr(t3)));
}
- break;
- case 0x0C: /* SYSCALL */
- DIP("syscall");
- if (mode64)
- putPC(mkU64(guest_PC_curr_instr + 4));
- else
- putPC(mkU32(guest_PC_curr_instr + 4));
- dres.jk_StopHere = Ijk_Sys_syscall;
- dres.whatNext = Dis_StopHere;
break;
- case 0x2A: /* SLT */
- DIP("slt r%u, r%u, r%u", rd, rs, rt);
- if (mode64)
- putIReg(rd, unop(Iop_1Uto64, binop(Iop_CmpLT64S, getIReg(rs),
- getIReg(rt))));
- else
- putIReg(rd, unop(Iop_1Uto32, binop(Iop_CmpLT32S, getIReg(rs),
- getIReg(rt))));
+ case 0x07: /* Load Word unsigned - LWU; MIPS64 */
+ DIP("lwu r%u,%u(r%u)", rt, imm, rs);
+ LOAD_STORE_PATTERN;
+
+ putIReg(rt, mkWidenFrom32(ty, load(Ity_I32, mkexpr(t1)), False));
break;
- case 0x2B: /* SLTU */
- DIP("sltu r%u, r%u, r%u", rd, rs, rt);
- if (mode64)
- putIReg(rd, unop(Iop_1Uto64, binop(Iop_CmpLT64U, getIReg(rs),
- getIReg(rt))));
- else
- putIReg(rd, unop(Iop_1Uto32, binop(Iop_CmpLT32U, getIReg(rs),
- getIReg(rt))));
+ case 0x08: /* SB */
+ DIP("sb r%u, %u(r%u)", rt, imm, rs);
+ LOAD_STORE_PATTERN;
+ store(mkexpr(t1), narrowTo(Ity_I8, getIReg(rt)));
break;
- case 0x00: { /* SLL */
- DIP("sll r%u, r%u, %u", rd, rt, sa);
- IRTemp tmpRt32 = newTemp(Ity_I32);
- IRTemp tmpSh32 = newTemp(Ity_I32);
- IRTemp tmpRd = newTemp(Ity_I64);
- if (mode64) {
- assign(tmpRt32, mkNarrowTo32(ty, getIReg(rt)));
- assign(tmpSh32, binop(Iop_Shl32, mkexpr(tmpRt32), mkU8(sa)));
- assign(tmpRd, mkWidenFrom32(ty, mkexpr(tmpSh32), True));
- putIReg(rd, mkexpr(tmpRd));
- } else
- SXX_PATTERN(Iop_Shl32);
+ case 0x09: /* SH */
+ DIP("sh r%u, %u(r%u)", rt, imm, rs);
+ LOAD_STORE_PATTERN;
+ store(mkexpr(t1), narrowTo(Ity_I16, getIReg(rt)));
break;
- }
- case 0x04: { /* SLLV */
- DIP("sllv r%u, r%u, r%u", rd, rt, rs);
+ case 0x0A: /* SWL */
+ DIP("swl r%u, %u(r%u)", rt, imm, rs);
+
if (mode64) {
- IRTemp tmpRs8 = newTemp(Ity_I8);
- IRTemp tmpRt32 = newTemp(Ity_I32);
- IRTemp tmpSh32 = newTemp(Ity_I32);
- IRTemp tmp = newTemp(ty);
- assign(tmp, binop(mkSzOp(ty, Iop_And8), getIReg(rs),
- mkSzImm(ty, 31)));
- assign(tmpRs8, mkNarrowTo8(ty, mkexpr(tmp)));
- assign(tmpRt32, mkNarrowTo32(ty, getIReg(rt)));
- assign(tmpSh32, binop(Iop_Shl32, mkexpr(tmpRt32), mkexpr(tmpRs8)));
- putIReg(rd, mkWidenFrom32(ty, mkexpr(tmpSh32), True));
+ IRTemp E_byte = newTemp(Ity_I8);
+ IRTemp F_byte = newTemp(Ity_I8);
+ IRTemp G_byte = newTemp(Ity_I8);
+ IRTemp H_byte = newTemp(Ity_I8);
+ IRTemp F_pos = newTemp(Ity_I64);
+ IRTemp G_pos = newTemp(Ity_I64);
+
+ /* H byte */
+ assign(H_byte, getByteFromReg(rt, 0));
+ /* G byte */
+ assign(G_byte, getByteFromReg(rt, 1));
+ /* F byte */
+ assign(F_byte, getByteFromReg(rt, 2));
+ /* E byte */
+ assign(E_byte, getByteFromReg(rt, 3));
+
+ /* t1 = addr */
+ t1 = newTemp(Ity_I64);
+ assign(t1, binop(Iop_Add64, getIReg(rs), mkU64(extend_s_16to64(imm))));
+
+ /* t2 = word addr */
+ t2 = newTemp(Ity_I64);
+ assign(t2, binop(Iop_And64, mkexpr(t1), mkU64(0xFFFFFFFFFFFFFFFCULL)));
+
+ /* t3 = addr mod 4 */
+ t3 = newTemp(Ity_I64);
+ assign(t3, binop(Iop_And64, mkexpr(t1), mkU64(0x3)));
+
+#if defined (_MIPSEL)
+ /* Calculate X_byte position. */
+ assign(F_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x0)),
+ mkU64(0x0),
+ mkU64(0x1)));
+
+ assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x3)),
+ mkU64(0x1),
+ mkU64(0x0)));
+
+ /* Store X_byte on the right place. */
+ store(mkexpr(t2), mkexpr(H_byte));
+ store(binop(Iop_Add64, mkexpr(t2), mkexpr(G_pos)), mkexpr(G_byte));
+ store(binop(Iop_Sub64, mkexpr(t1), mkexpr(F_pos)), mkexpr(F_byte));
+ store(mkexpr(t1), mkexpr(E_byte));
+
+#else /* _MIPSEB */
+ /* Calculate X_byte position. */
+ assign(F_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x3)),
+ mkU64(0x0),
+ mkU64(0x1)));
+
+ assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x0)),
+ mkU64(0x2),
+ mkU64(0x3)));
+
+ store(binop(Iop_Add64, mkexpr(t2), mkU64(3)), mkexpr(H_byte));
+ store(binop(Iop_Add64, mkexpr(t2), mkexpr(G_pos)), mkexpr(G_byte));
+ store(binop(Iop_Add64, mkexpr(t1), mkexpr(F_pos)), mkexpr(F_byte));
+ store(mkexpr(t1), mkexpr(E_byte));
+
+#endif
} else {
- SXXV_PATTERN(Iop_Shl32);
+ IRTemp E_byte = newTemp(Ity_I8);
+ IRTemp F_byte = newTemp(Ity_I8);
+ IRTemp G_byte = newTemp(Ity_I8);
+ IRTemp H_byte = newTemp(Ity_I8);
+ IRTemp F_pos = newTemp(Ity_I32);
+ IRTemp G_pos = newTemp(Ity_I32);
+
+ /* H byte */
+ assign(H_byte, getByteFromReg(rt, 0));
+ /* G byte */
+ assign(G_byte, getByteFromReg(rt, 1));
+ /* F byte */
+ assign(F_byte, getByteFromReg(rt, 2));
+ /* E byte */
+ assign(E_byte, getByteFromReg(rt, 3));
+
+ /* t1 = addr */
+ t1 = newTemp(Ity_I32);
+ assign(t1, binop(Iop_Add32, getIReg(rs), mkU32(extend_s_16to32(imm))));
+
+ /* t2 = word addr */
+ t2 = newTemp(Ity_I32);
+ assign(t2, binop(Iop_And32, mkexpr(t1), mkU32(0xFFFFFFFCULL)));
+
+ /* t3 = addr mod 4 */
+ t3 = newTemp(Ity_I32);
+ assign(t3, binop(Iop_And32, mkexpr(t1), mkU32(0x3)));
+
+#if defined (_MIPSEL)
+ /* Calculate X_byte position. */
+ assign(F_pos, IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t3), mkU32(0x0)),
+ mkU32(0x0),
+ mkU32(0x1)));
+
+ assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t3), mkU32(0x3)),
+ mkU32(0x1),
+ mkU32(0x0)));
+
+ /* Store X_byte on the right place. */
+ store(mkexpr(t2), mkexpr(H_byte));
+ store(binop(Iop_Add32, mkexpr(t2), mkexpr(G_pos)), mkexpr(G_byte));
+ store(binop(Iop_Sub32, mkexpr(t1), mkexpr(F_pos)), mkexpr(F_byte));
+ store(mkexpr(t1), mkexpr(E_byte));
+
+#else /* _MIPSEB */
+ /* Calculate X_byte position. */
+ assign(F_pos, IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t3), mkU32(0x3)),
+ mkU32(0x0),
+ mkU32(0x1)));
+
+ assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t3), mkU32(0x0)),
+ mkU32(0x2),
+ mkU32(0x3)));
+
+ store(binop(Iop_Add32, mkexpr(t2), mkU32(3)), mkexpr(H_byte));
+ store(binop(Iop_Add32, mkexpr(t2), mkexpr(G_pos)), mkexpr(G_byte));
+ store(binop(Iop_Add32, mkexpr(t1), mkexpr(F_pos)), mkexpr(F_byte));
+ store(mkexpr(t1), mkexpr(E_byte));
+
+#endif
}
+
break;
- }
- case 0x03: /* SRA */
- DIP("sra r%u, r%u, %u", rd, rt, sa);
- if (mode64) {
- IRTemp tmpRt32 = newTemp(Ity_I32);
- IRTemp tmpSh32 = newTemp(Ity_I32);
+ case 0x0B: /* SW */
+ DIP("sw r%u, %u(r%u)", rt, imm, rs);
+ LOAD_STORE_PATTERN;
+ store(mkexpr(t1), mkNarrowTo32(ty, getIReg(rt)));
+ break;
+
+ case 0x0C: { /* SDL rt, offset(base) MIPS64 */
+ DIP("sdl r%u, %u(r%u)", rt, imm, rs);
+ vassert(mode64);
+ IRTemp A_byte = newTemp(Ity_I8);
+ IRTemp B_byte = newTemp(Ity_I8);
+ IRTemp C_byte = newTemp(Ity_I8);
+ IRTemp D_byte = newTemp(Ity_I8);
+ IRTemp E_byte = newTemp(Ity_I8);
+ IRTemp F_byte = newTemp(Ity_I8);
+ IRTemp G_byte = newTemp(Ity_I8);
+ IRTemp H_byte = newTemp(Ity_I8);
+ IRTemp B_pos = newTemp(Ity_I64);
+ IRTemp C_pos = newTemp(Ity_I64);
+ IRTemp D_pos = newTemp(Ity_I64);
+ IRTemp E_pos = newTemp(Ity_I64);
+ IRTemp F_pos = newTemp(Ity_I64);
+ IRTemp G_pos = newTemp(Ity_I64);
+
+ /* H byte */
+ assign(H_byte, getByteFromReg(rt, 0));
+ /* G byte */
+ assign(G_byte, getByteFromReg(rt, 1));
+ /* F byte */
+ assign(F_byte, getByteFromReg(rt, 2));
+ /* E byte */
+ assign(E_byte, getByteFromReg(rt, 3));
+ /* D byte */
+ assign(D_byte, getByteFromReg(rt, 4));
+ /* C byte */
+ assign(C_byte, getByteFromReg(rt, 5));
+ /* B byte */
+ assign(B_byte, getByteFromReg(rt, 6));
+ /* A byte */
+ assign(A_byte, getByteFromReg(rt, 7));
+
+ /* t1 = addr */
+ t1 = newTemp(Ity_I64);
+ assign(t1, binop(Iop_Add64, getIReg(rs), mkU64(extend_s_16to64(imm))));
+
+ /* t2 = word addr */
+ t2 = newTemp(Ity_I64);
+ assign(t2, binop(Iop_And64, mkexpr(t1), mkU64(0xFFFFFFFFFFFFFFF8ULL)));
+
+ /* t3 = addr mod 7 */
+ t3 = newTemp(Ity_I64);
+ assign(t3, binop(Iop_And64, mkexpr(t1), mkU64(0x7)));
+
+#if defined (_MIPSEL)
+ /* Calculate X_byte position. */
+ assign(B_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkexpr(t3), mkU64(0x1)),
+ mkU64(0x0),
+ mkU64(0x1)));
+
+ assign(C_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkexpr(t3), mkU64(0x2)),
+ mkU64(0x0),
+ mkU64(0x2)));
+
+ assign(D_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkexpr(t3), mkU64(0x3)),
+ mkU64(0x0),
+ mkU64(0x3)));
+
+ assign(E_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkexpr(t3), mkU64(0x4)),
+ mkU64(0x0),
+ mkU64(0x4)));
+
+ assign(F_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkexpr(t3), mkU64(0x5)),
+ mkU64(0x0),
+ mkU64(0x5)));
+
+ assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x7)),
+ mkU64(0x1),
+ mkU64(0x0)));
+
+ /* Store X_byte on the right place. */
+ store(mkexpr(t2), mkexpr(H_byte));
+ store(binop(Iop_Add64, mkexpr(t2), mkexpr(G_pos)), mkexpr(G_byte));
+ store(binop(Iop_Sub64, mkexpr(t1), mkexpr(F_pos)), mkexpr(F_byte));
+ store(binop(Iop_Sub64, mkexpr(t1), mkexpr(E_pos)), mkexpr(E_byte));
+ store(binop(Iop_Sub64, mkexpr(t1), mkexpr(D_pos)), mkexpr(D_byte));
+ store(binop(Iop_Sub64, mkexpr(t1), mkexpr(C_pos)), mkexpr(C_byte));
+ store(binop(Iop_Sub64, mkexpr(t1), mkexpr(B_pos)), mkexpr(B_byte));
+ store(mkexpr(t1), mkexpr(A_byte));
+
+#else /* _MIPSEB */
+ /* Calculate X_byte position. */
+ assign(B_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x7)),
+ mkU64(0x0),
+ mkU64(0x1)));
+
+ assign(C_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkexpr(t3), mkU64(0x6)),
+ mkU64(0x2),
+ mkU64(0x0)));
+
+ assign(D_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkexpr(t3), mkU64(0x5)),
+ mkU64(0x3),
+ mkU64(0x0)));
- t1 = newTemp(Ity_I64);
- t2 = newTemp(Ity_I64);
- t3 = newTemp(Ity_I64);
+ assign(E_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkexpr(t3), mkU64(0x4)),
+ mkU64(0x4),
+ mkU64(0x0)));
- assign(t1, binop(Iop_And64, getIReg(rt), /* hi */
- mkU64(0xFFFFFFFF00000000ULL)));
+ assign(F_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkexpr(t3), mkU64(0x3)),
+ mkU64(0x5),
+ mkU64(0x0)));
- assign(t2, binop(Iop_Sar64, mkexpr(t1), mkU8(sa)));
+ assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x0)),
+ mkU64(0x6),
+ mkU64(0x7)));
- assign(tmpRt32, mkNarrowTo32(ty, getIReg(rt)));
- assign(tmpSh32, binop(Iop_Sar32, mkexpr(tmpRt32), mkU8(sa)));
+ /* Store X_byte on the right place. */
+ store(binop(Iop_Add64, mkexpr(t2), mkU64(0x7)), mkexpr(H_byte));
+ store(binop(Iop_Add64, mkexpr(t2), mkexpr(G_pos)), mkexpr(G_byte));
+ store(binop(Iop_Add64, mkexpr(t1), mkexpr(F_pos)), mkexpr(F_byte));
+ store(binop(Iop_Add64, mkexpr(t1), mkexpr(E_pos)), mkexpr(E_byte));
+ store(binop(Iop_Add64, mkexpr(t1), mkexpr(D_pos)), mkexpr(D_byte));
+ store(binop(Iop_Add64, mkexpr(t1), mkexpr(C_pos)), mkexpr(C_byte));
+ store(binop(Iop_Add64, mkexpr(t1), mkexpr(B_pos)), mkexpr(B_byte));
+ store(mkexpr(t1), mkexpr(A_byte));
+#endif
- putIReg(rd, mkWidenFrom32(ty, mkexpr(tmpSh32), True));
- } else {
- SXX_PATTERN(Iop_Sar32);
- }
break;
+ }
- case 0x07: /* SRAV */
- DIP("srav r%u, r%u, r%u", rd, rt, rs);
- if (mode64) {
- IRTemp tmpRt32 = newTemp(Ity_I32);
- IRTemp tmpSh32 = newTemp(Ity_I32);
+ case 0x0D: {
+ /* SDR rt, offset(base) - MIPS64 */
+ vassert(mode64);
+ DIP("sdr r%u, %u(r%u)", rt, imm, rs);
+ IRTemp A_byte = newTemp(Ity_I8);
+ IRTemp B_byte = newTemp(Ity_I8);
+ IRTemp C_byte = newTemp(Ity_I8);
+ IRTemp D_byte = newTemp(Ity_I8);
+ IRTemp E_byte = newTemp(Ity_I8);
+ IRTemp F_byte = newTemp(Ity_I8);
+ IRTemp G_byte = newTemp(Ity_I8);
+ IRTemp H_byte = newTemp(Ity_I8);
+ IRTemp B_pos = newTemp(Ity_I64);
+ IRTemp C_pos = newTemp(Ity_I64);
+ IRTemp D_pos = newTemp(Ity_I64);
+ IRTemp E_pos = newTemp(Ity_I64);
+ IRTemp F_pos = newTemp(Ity_I64);
+ IRTemp G_pos = newTemp(Ity_I64);
- t1 = newTemp(Ity_I64);
- t2 = newTemp(Ity_I64);
- t3 = newTemp(Ity_I64);
- t4 = newTemp(Ity_I8);
+ /* H byte */
+ assign(H_byte, getByteFromReg(rt, 0));
+ /* G byte */
+ assign(G_byte, getByteFromReg(rt, 1));
+ /* F byte */
+ assign(F_byte, getByteFromReg(rt, 2));
+ /* E byte */
+ assign(E_byte, getByteFromReg(rt, 3));
+ /* D byte */
+ assign(D_byte, getByteFromReg(rt, 4));
+ /* C byte */
+ assign(C_byte, getByteFromReg(rt, 5));
+ /* B byte */
+ assign(B_byte, getByteFromReg(rt, 6));
+ /* A byte */
+ assign(A_byte, getByteFromReg(rt, 7));
- assign(t4, unop(Iop_32to8, binop(Iop_And32,
- mkNarrowTo32(ty, getIReg(rs)), mkU32(0x0000001F))));
+ /* t1 = addr */
+ t1 = newTemp(Ity_I64);
+ assign(t1, binop(Iop_Add64, getIReg(rs), mkU64(extend_s_16to64(imm))));
- assign(t1, binop(Iop_And64, getIReg(rt), /* hi */
- mkU64(0xFFFFFFFF00000000ULL)));
+ /* t2 = word addr */
+ t2 = newTemp(Ity_I64);
+ assign(t2, binop(Iop_And64, mkexpr(t1), mkU64(0xFFFFFFFFFFFFFFF8ULL)));
- assign(t2, binop(Iop_Sar64, mkexpr(t1), mkexpr(t4)));
+ /* t3 = addr mod 7 */
+ t3 = newTemp(Ity_I64);
+ assign(t3, binop(Iop_And64, mkexpr(t1), mkU64(0x7)));
- assign(tmpRt32, mkNarrowTo32(ty, getIReg(rt)));
- assign(tmpSh32, binop(Iop_Sar32, mkexpr(tmpRt32), mkexpr(t4)));
+#if defined (_MIPSEL)
+ /* Calculate X_byte position. */
+ assign(B_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkU64(0x1), mkexpr(t3)),
+ mkU64(0x0),
+ mkU64(0x6)));
- putIReg(rd, mkWidenFrom32(ty, mkexpr(tmpSh32), True));
- } else {
- SXXV_PATTERN(Iop_Sar32);
- }
- break;
+ assign(C_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkU64(0x2), mkexpr(t3)),
+ mkU64(0x0),
+ mkU64(0x5)));
- case 0x02: { /* SRL */
- rot = get_rot(cins);
- if (rot) {
- DIP("rotr r%u, r%u, %u", rd, rt, sa);
- putIReg(rd, mkWidenFrom32(ty, genROR32(mkNarrowTo32(ty,
- getIReg(rt)), sa), True));
- } else {
- DIP("srl r%u, r%u, %u", rd, rt, sa);
- if (mode64) {
- IRTemp tmpSh32 = newTemp(Ity_I32);
- IRTemp tmpRt32 = newTemp(Ity_I32);
+ assign(D_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkU64(0x3), mkexpr(t3)),
+ mkU64(0x0),
+ mkU64(0x4)));
- assign(tmpRt32, mkNarrowTo32(ty, getIReg(rt)));
- assign(tmpSh32, binop(Iop_Shr32, mkexpr(tmpRt32), mkU8(sa)));
- putIReg(rd, mkWidenFrom32(ty, mkexpr(tmpSh32), True));
- } else {
- SXX_PATTERN(Iop_Shr32);
- }
- }
- break;
- }
+ assign(E_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkU64(0x4), mkexpr(t3)),
+ mkU64(0x0),
+ mkU64(0x3)));
- case 0x06: {
- rot = get_rotv(cins);
- if (rot) {
- DIP("rotrv r%u, r%u, r%u", rd, rt, rs);
- putIReg(rd, mkWidenFrom32(ty, genRORV32(mkNarrowTo32(ty,
- getIReg(rt)), mkNarrowTo32(ty, getIReg(rs))), True));
- break;
- } else { /* SRLV */
- DIP("srlv r%u, r%u, r%u", rd, rt, rs);
- if (mode64) {
- SXXV_PATTERN64(Iop_Shr32);
- } else {
- SXXV_PATTERN(Iop_Shr32);
- }
- break;
- }
- }
- case 0x05: { /* LSA */
- UInt imm2 = (imm & 0xC0) >> 6;
- if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps) || has_msa) {
- DIP("lsa r%u, r%u, r%u, imm: 0x%x", rd, rs, rt, imm2);
- if (mode64) {
- DIP("lsa r%u, r%u, r%u, imm: 0x%x", rd, rs, rt, imm2);
- putIReg(rd, unop(Iop_32Sto64,
- binop(Iop_Add32,
- binop(Iop_Shl32,
- unop(Iop_64to32, getIReg(rs)),
- mkU8(imm2 + 1)),
- unop(Iop_64to32, getIReg(rt)))));
- break;
- } else {
- DIP("lsa r%u, r%u, r%u, imm: 0x%x", rd, rs, rt, imm2);
- putIReg(rd, binop(Iop_Add32,
- binop(Iop_Shl32,
- getIReg(rs), mkU8(imm2 + 1)), getIReg(rt)));
- break;
- }
- } else {
- ILLEGAL_INSTRUCTON;
- break;
- }
+ assign(F_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkU64(0x5), mkexpr(t3)),
+ mkU64(0x0),
+ mkU64(0x2)));
- }
- case 0x15:{ /* DLSA */
- UInt imm2 = (imm & 0xC0) >> 6;
- if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps) || has_msa) {
- DIP("dlsa r%u, r%u, r%u, imm: 0x%x", rd, rs, rt, imm2);
- putIReg(rd, binop(Iop_Add64,
- binop(Iop_Shl64, getIReg(rs), mkU8(imm2 + 1)),
- getIReg(rt)));
- } else {
- ILLEGAL_INSTRUCTON;
- }
- break;
- }
+ assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x7)),
+ mkU64(0x0),
+ mkU64(0x1)));
- case 0x0D: /* BREAK */
- DIP("break 0x%x", trap_code);
- if (mode64)
- jmp_lit64(&dres, Ijk_SigTRAP, (guest_PC_curr_instr + 4));
- else
- jmp_lit32(&dres, Ijk_SigTRAP, (guest_PC_curr_instr + 4));
- vassert(dres.whatNext == Dis_StopHere);
- break;
+ /* Store X_byte on the right place. */
+ store(binop(Iop_Add64, mkexpr(t2), mkU64(0x7)), mkexpr(A_byte));
+ store(binop(Iop_Add64, mkexpr(t1), mkexpr(B_pos)), mkexpr(B_byte));
+ store(binop(Iop_Add64, mkexpr(t1), mkexpr(C_pos)), mkexpr(C_byte));
+ store(binop(Iop_Add64, mkexpr(t1), mkexpr(D_pos)), mkexpr(D_byte));
+ store(binop(Iop_Add64, mkexpr(t1), mkexpr(E_pos)), mkexpr(E_byte));
+ store(binop(Iop_Add64, mkexpr(t1), mkexpr(F_pos)), mkexpr(F_byte));
+ store(binop(Iop_Add64, mkexpr(t1), mkexpr(G_pos)), mkexpr(G_byte));
+ store(mkexpr(t1), mkexpr(H_byte));
- case 0x30: { /* TGE */
- DIP("tge r%u, r%u %u", rs, rt, trap_code);
- if (mode64) {
- if (trap_code == 7)
- stmt (IRStmt_Exit (unop (Iop_Not1,
- binop (Iop_CmpLT64S,
- getIReg (rs),
- getIReg (rt))),
- Ijk_SigFPE_IntDiv,
- IRConst_U64(guest_PC_curr_instr + 4),
- OFFB_PC));
- else if (trap_code == 6)
- stmt (IRStmt_Exit (unop (Iop_Not1,
- binop (Iop_CmpLT64S,
- getIReg (rs),
- getIReg (rt))),
- Ijk_SigFPE_IntOvf,
- IRConst_U64(guest_PC_curr_instr + 4),
- OFFB_PC));
- else
- stmt (IRStmt_Exit (unop (Iop_Not1,
- binop (Iop_CmpLT64S,
- getIReg (rs),
- getIReg (rt))),
- Ijk_SigTRAP,
- IRConst_U64(guest_PC_curr_instr + 4),
- OFFB_PC));
- } else {
- if (trap_code == 7)
- stmt (IRStmt_Exit (unop (Iop_Not1,
- binop (Iop_CmpLT32S,
- getIReg (rs),
- getIReg (rt))),
- Ijk_SigFPE_IntDiv,
- IRConst_U32(guest_PC_curr_instr + 4),
- OFFB_PC));
- else if (trap_code == 6)
- stmt (IRStmt_Exit (unop (Iop_Not1,
- binop (Iop_CmpLT32S,
- getIReg (rs),
- getIReg (rt))),
- Ijk_SigFPE_IntOvf,
- IRConst_U32(guest_PC_curr_instr + 4),
- OFFB_PC));
- else
- stmt (IRStmt_Exit (unop (Iop_Not1,
- binop (Iop_CmpLT32S,
- getIReg (rs),
- getIReg (rt))),
- Ijk_SigTRAP,
- IRConst_U32(guest_PC_curr_instr + 4),
- OFFB_PC));
- }
- break;
- }
- case 0x31: { /* TGEU */
- DIP("tgeu r%u, r%u %u", rs, rt, trap_code);
- if (mode64) {
- if (trap_code == 7)
- stmt (IRStmt_Exit (unop (Iop_Not1,
- binop (Iop_CmpLT64U,
- getIReg (rs),
- getIReg (rt))),
- Ijk_SigFPE_IntDiv,
- IRConst_U64(guest_PC_curr_instr + 4),
- OFFB_PC));
- else if (trap_code == 6)
- stmt (IRStmt_Exit (unop (Iop_Not1,
- binop (Iop_CmpLT64U,
- getIReg (rs),
- getIReg (rt))),
- Ijk_SigFPE_IntOvf,
- IRConst_U64(guest_PC_curr_instr + 4),
- OFFB_PC));
- else
- stmt (IRStmt_Exit (unop (Iop_Not1,
- binop (Iop_CmpLT64U,
- getIReg (rs),
- getIReg (rt))),
- Ijk_SigTRAP,
- IRConst_U64(guest_PC_curr_instr + 4),
- OFFB_PC));
- } else {
- if (trap_code == 7)
- stmt (IRStmt_Exit (unop (Iop_Not1,
- binop (Iop_CmpLT32U,
- getIReg (rs),
- getIReg (rt))),
- Ijk_SigFPE_IntDiv,
- IRConst_U32(guest_PC_curr_instr + 4),
- OFFB_PC));
- else if (trap_code == 6)
- stmt (IRStmt_Exit (unop (Iop_Not1,
- binop (Iop_CmpLT32U,
- getIReg (rs),
- getIReg (rt))),
- Ijk_SigFPE_IntOvf,
- IRConst_U32(guest_PC_curr_instr + 4),
- OFFB_PC));
- else
- stmt (IRStmt_Exit (unop (Iop_Not1,
- binop (Iop_CmpLT32U,
- getIReg (rs),
- getIReg (rt))),
- Ijk_SigTRAP,
- IRConst_U32(guest_PC_curr_instr + 4),
- OFFB_PC));
- }
+#else /* _MIPSEB */
+ /* Calculate X_byte position. */
+ assign(B_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkU64(0x5), mkexpr(t3)),
+ mkU64(0x6),
+ mkU64(0x0)));
+
+ assign(C_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkU64(0x4), mkexpr(t3)),
+ mkU64(0x5),
+ mkU64(0x0)));
+
+ assign(D_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkU64(0x3), mkexpr(t3)),
+ mkU64(0x4),
+ mkU64(0x0)));
+
+ assign(E_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkU64(0x2), mkexpr(t3)),
+ mkU64(0x3),
+ mkU64(0x0)));
+
+ assign(F_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkU64(0x1), mkexpr(t3)),
+ mkU64(0x2),
+ mkU64(0x0)));
+
+ assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x0)),
+ mkU64(0x0),
+ mkU64(0x1)));
+
+ /* Store X_byte on the right place. */
+ store(mkexpr(t2), mkexpr(A_byte));
+ store(binop(Iop_Sub64, mkexpr(t1), mkexpr(B_pos)), mkexpr(B_byte));
+ store(binop(Iop_Sub64, mkexpr(t1), mkexpr(C_pos)), mkexpr(C_byte));
+ store(binop(Iop_Sub64, mkexpr(t1), mkexpr(D_pos)), mkexpr(D_byte));
+ store(binop(Iop_Sub64, mkexpr(t1), mkexpr(E_pos)), mkexpr(E_byte));
+ store(binop(Iop_Sub64, mkexpr(t1), mkexpr(F_pos)), mkexpr(F_byte));
+ store(binop(Iop_Sub64, mkexpr(t1), mkexpr(G_pos)), mkexpr(G_byte));
+ store(mkexpr(t1), mkexpr(H_byte));
+#endif
break;
}
- case 0x32: { /* TLT */
- DIP("tlt r%u, r%u %u", rs, rt, trap_code);
+
+ case 0x0E: /* SWR */
+ DIP("swr r%u, %u(r%u)", rt, imm, rs);
+
if (mode64) {
- if (trap_code == 7)
- stmt(IRStmt_Exit(binop(Iop_CmpLT64S, getIReg(rs),
- getIReg(rt)), Ijk_SigFPE_IntDiv,
- IRConst_U64(guest_PC_curr_instr + 4),
- OFFB_PC));
- else if (trap_code == 6)
- stmt(IRStmt_Exit(binop(Iop_CmpLT64S, getIReg(rs),
- getIReg(rt)), Ijk_SigFPE_IntOvf,
- IRConst_U64(guest_PC_curr_instr + 4),
- OFFB_PC));
- else
- stmt(IRStmt_Exit(binop(Iop_CmpLT64S, getIReg(rs),
- getIReg(rt)), Ijk_SigTRAP,
- IRConst_U64(guest_PC_curr_instr + 4),
- OFFB_PC));
+ IRTemp E_byte = newTemp(Ity_I8);
+ IRTemp F_byte = newTemp(Ity_I8);
+ IRTemp G_byte = newTemp(Ity_I8);
+ IRTemp H_byte = newTemp(Ity_I8);
+ IRTemp F_pos = newTemp(Ity_I64);
+ IRTemp G_pos = newTemp(Ity_I64);
+
+ /* H byte */
+ assign(H_byte, getByteFromReg(rt, 0));
+ /* G byte */
+ assign(G_byte, getByteFromReg(rt, 1));
+ /* F byte */
+ assign(F_byte, getByteFromReg(rt, 2));
+ /* E byte */
+ assign(E_byte, getByteFromReg(rt, 3));
+
+ /* t1 = addr */
+ t1 = newTemp(Ity_I64);
+ assign(t1, binop(Iop_Add64, getIReg(rs), mkU64(extend_s_16to64(imm))));
+
+ /* t2 = word addr */
+ t2 = newTemp(Ity_I64);
+ assign(t2, binop(Iop_And64, mkexpr(t1), mkU64(0xFFFFFFFFFFFFFFFCULL)));
+
+ /* t3 = addr mod 4 */
+ t3 = newTemp(Ity_I64);
+ assign(t3, binop(Iop_And64, mkexpr(t1), mkU64(0x3)));
+
+#if defined (_MIPSEL)
+ /* Calculate X_byte position. */
+ assign(F_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x0)),
+ mkU64(0x2),
+ mkU64(0x3)));
+
+ assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x3)),
+ mkU64(0x0),
+ mkU64(0x1)));
+
+ /* Store X_byte on the right place. */
+ store(binop(Iop_Add64, mkexpr(t2), mkU64(0x3)), mkexpr(E_byte));
+ store(binop(Iop_Add64, mkexpr(t2), mkexpr(F_pos)), mkexpr(F_byte));
+ store(binop(Iop_Add64, mkexpr(t1), mkexpr(G_pos)), mkexpr(G_byte));
+ store(mkexpr(t1), mkexpr(H_byte));
+
+#else /* _MIPSEB */
+ /* Calculate X_byte position. */
+ assign(F_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x3)),
+ mkU64(0x1),
+ mkU64(0x0)));
+
+ assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x0)),
+ mkU64(0x0),
+ mkU64(0x1)));
+
+ /* Store X_byte on the right place. */
+ store(mkexpr(t2), mkexpr(E_byte));
+ store(binop(Iop_Add64, mkexpr(t2), mkexpr(F_pos)), mkexpr(F_byte));
+ store(binop(Iop_Sub64, mkexpr(t1), mkexpr(G_pos)), mkexpr(G_byte));
+ store(mkexpr(t1), mkexpr(H_byte));
+#endif
} else {
- if (trap_code == 7)
- stmt(IRStmt_Exit(binop(Iop_CmpLT32S, getIReg(rs),
- getIReg(rt)), Ijk_SigFPE_IntDiv,
- IRConst_U32(guest_PC_curr_instr + 4),
- OFFB_PC));
- else if (trap_code == 6)
- stmt(IRStmt_Exit(binop(Iop_CmpLT32S, getIReg(rs),
- getIReg(rt)), Ijk_SigFPE_IntOvf,
- IRConst_U32(guest_PC_curr_instr + 4),
- OFFB_PC));
- else
- stmt(IRStmt_Exit(binop(Iop_CmpLT32S, getIReg(rs),
- getIReg(rt)), Ijk_SigTRAP,
- IRConst_U32(guest_PC_curr_instr + 4),
- OFFB_PC));
+ IRTemp E_byte = newTemp(Ity_I8);
+ IRTemp F_byte = newTemp(Ity_I8);
+ IRTemp G_byte = newTemp(Ity_I8);
+ IRTemp H_byte = newTemp(Ity_I8);
+ IRTemp F_pos = newTemp(Ity_I32);
+ IRTemp G_pos = newTemp(Ity_I32);
+
+ /* H byte */
+ assign(H_byte, getByteFromReg(rt, 0));
+ /* G byte */
+ assign(G_byte, getByteFromReg(rt, 1));
+ /* F byte */
+ assign(F_byte, getByteFromReg(rt, 2));
+ /* E byte */
+ assign(E_byte, getByteFromReg(rt, 3));
+
+ /* t1 = addr */
+ t1 = newTemp(Ity_I32);
+ assign(t1, binop(Iop_Add32, getIReg(rs), mkU32(extend_s_16to32(imm))));
+
+ /* t2 = word addr */
+ t2 = newTemp(Ity_I32);
+ assign(t2, binop(Iop_And32, mkexpr(t1), mkU32(0xFFFFFFFCULL)));
+
+ /* t3 = addr mod 4 */
+ t3 = newTemp(Ity_I32);
+ assign(t3, binop(Iop_And32, mkexpr(t1), mkU32(0x3)));
+
+#if defined (_MIPSEL)
+ /* Calculate X_byte position. */
+ assign(F_pos, IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t3), mkU32(0x0)),
+ mkU32(0x2),
+ mkU32(0x3)));
+
+ assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t3), mkU32(0x3)),
+ mkU32(0x0),
+ mkU32(0x1)));
+
+ /* Store X_byte on the right place. */
+ store(binop(Iop_Add32, mkexpr(t2), mkU32(0x3)), mkexpr(E_byte));
+ store(binop(Iop_Add32, mkexpr(t2), mkexpr(F_pos)), mkexpr(F_byte));
+ store(binop(Iop_Add32, mkexpr(t1), mkexpr(G_pos)), mkexpr(G_byte));
+ store(mkexpr(t1), mkexpr(H_byte));
+
+#else /* _MIPSEB */
+ /* Calculate X_byte position. */
+ assign(F_pos, IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t3), mkU32(0x3)),
+ mkU32(0x1),
+ mkU32(0x0)));
+
+ assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t3), mkU32(0x0)),
+ mkU32(0x0),
+ mkU32(0x1)));
+
+ /* Store X_byte on the right place. */
+ store(mkexpr(t2), mkexpr(E_byte));
+ store(binop(Iop_Add32, mkexpr(t2), mkexpr(F_pos)), mkexpr(F_byte));
+ store(binop(Iop_Sub32, mkexpr(t1), mkexpr(G_pos)), mkexpr(G_byte));
+ store(mkexpr(t1), mkexpr(H_byte));
+#endif
}
+
break;
- }
- case 0x33: { /* TLTU */
- DIP("tltu r%u, r%u %u", rs, rt, trap_code);
- if (mode64) {
- if (trap_code == 7)
- stmt(IRStmt_Exit(binop(Iop_CmpLT64U, getIReg(rs),
- getIReg(rt)), Ijk_SigFPE_IntDiv,
- IRConst_U64(guest_PC_curr_instr + 4),
- OFFB_PC));
- else if (trap_code == 6)
- stmt(IRStmt_Exit(binop(Iop_CmpLT64U, getIReg(rs),
- getIReg(rt)), Ijk_SigFPE_IntOvf,
- IRConst_U64(guest_PC_curr_instr + 4),
- OFFB_PC));
- else
- stmt(IRStmt_Exit(binop(Iop_CmpLT64U, getIReg(rs),
- getIReg(rt)), Ijk_SigTRAP,
- IRConst_U64(guest_PC_curr_instr + 4),
- OFFB_PC));
+ }
+
+ return 0;
+}
+
+static UInt disInstr_MIPS_WRK_30(UInt cins, const VexArchInfo* archinfo,
+ const VexAbiInfo* abiinfo, DisResult* dres,
+ IRStmt** bstmt)
+{
+ IRTemp t0, t1 = 0, t2, t3, t4, t5;
+ UInt opcode, rs, rt, rd, ft, function, imm, instr_index;
+
+ opcode = get_opcode(cins);
+ imm = get_imm(cins);
+ rs = get_rs(cins);
+ rt = get_rt(cins);
+ rd = get_rd(cins);
+ ft = get_ft(cins);
+
+ instr_index = get_instr_index(cins);
+ function = get_function(cins);
+ IRType ty = mode64 ? Ity_I64 : Ity_I32;
+
+ switch (opcode & 0x0F) {
+ case 0x00: /* LL */
+ DIP("ll r%u, %u(r%u)", rt, imm, rs);
+ LOAD_STORE_PATTERN;
+
+ if (abiinfo->guest__use_fallback_LLSC) {
+ t2 = newTemp(ty);
+ assign(t2, mkWidenFrom32(ty, load(Ity_I32, mkexpr(t1)), True));
+ putLLaddr(mkexpr(t1));
+ putLLdata(mkexpr(t2));
+ putIReg(rt, mkexpr(t2));
} else {
- if (trap_code == 7)
- stmt(IRStmt_Exit(binop(Iop_CmpLT32U, getIReg(rs),
- getIReg(rt)), Ijk_SigFPE_IntDiv,
- IRConst_U32(guest_PC_curr_instr + 4),
- OFFB_PC));
- else if (trap_code == 6)
- stmt(IRStmt_Exit(binop(Iop_CmpLT32U, getIReg(rs),
- getIReg(rt)), Ijk_SigFPE_IntOvf,
- IRConst_U32(guest_PC_curr_instr + 4),
- OFFB_PC));
- else
- stmt(IRStmt_Exit(binop(Iop_CmpLT32U, getIReg(rs),
- getIReg (rt)), Ijk_SigTRAP,
- IRConst_U32(guest_PC_curr_instr + 4),
- OFFB_PC));
+ t2 = newTemp(Ity_I32);
+ stmt(IRStmt_LLSC(MIPS_IEND, t2, mkexpr(t1), NULL));
+ putIReg(rt, mkWidenFrom32(ty, mkexpr(t2), True));
}
+
break;
- }
- case 0x34: { /* TEQ */
- DIP("teq r%u, r%u, %u", rs, rt, trap_code);
- if (mode64) {
- if (trap_code == 7)
- stmt(IRStmt_Exit(binop(Iop_CmpEQ64, getIReg(rs),
- getIReg(rt)), Ijk_SigFPE_IntDiv,
- IRConst_U64(guest_PC_curr_instr + 4),
- OFFB_PC));
- else if (trap_code == 6)
- stmt(IRStmt_Exit(binop(Iop_CmpEQ64, getIReg(rs),
- getIReg(rt)), Ijk_SigFPE_IntOvf,
- IRConst_U64(guest_PC_curr_instr + 4),
- OFFB_PC));
- else
- stmt(IRStmt_Exit(binop(Iop_CmpEQ64, getIReg(rs),
- getIReg(rt)), Ijk_SigTRAP,
- IRConst_U64(guest_PC_curr_instr + 4),
- OFFB_PC));
+
+ case 0x01: /* LWC1 */
+ /* Load Word to Floating Point - LWC1 (MIPS32) */
+ DIP("lwc1 f%u, %u(r%u)", ft, imm, rs);
+ LOAD_STORE_PATTERN;
+
+ if (fp_mode64) {
+ t0 = newTemp(Ity_F32);
+ t2 = newTemp(Ity_I64);
+ assign(t0, load(Ity_F32, mkexpr(t1)));
+ assign(t2, mkWidenFrom32(Ity_I64, unop(Iop_ReinterpF32asI32,
+ mkexpr(t0)), True));
+ putDReg(ft, unop(Iop_ReinterpI64asF64, mkexpr(t2)));
} else {
- if (trap_code == 7)
- stmt(IRStmt_Exit(binop(Iop_CmpEQ32, getIReg(rs),
- getIReg(rt)), Ijk_SigFPE_IntDiv,
- IRConst_U32(guest_PC_curr_instr + 4),
- OFFB_PC));
- else if (trap_code == 6)
- stmt(IRStmt_Exit(binop(Iop_CmpEQ32, getIReg(rs),
- getIReg(rt)), Ijk_SigFPE_IntOvf,
- IRConst_U32(guest_PC_curr_instr + 4),
- OFFB_PC));
- else
- stmt(IRStmt_Exit(binop(Iop_CmpEQ32, getIReg(rs),
- getIReg(rt)), Ijk_SigTRAP,
- IRConst_U32(guest_PC_curr_instr + 4),
- OFFB_PC));
+ putFReg(ft, load(Ity_F32, mkexpr(t1)));
}
+
break;
- }
- case 0x35: { /* SELEQZ */
- if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
- DIP("seleqz r%u, r%u, r%u", rd, rs, rt);
- if (mode64) {
- putIReg(rd, binop(Iop_And64,
- unop(Iop_Not64,
- unop(Iop_CmpwNEZ64, getIReg(rt))),
- getIReg(rs)));
+
+ case 0x02: /* Branch on Bit Clear - BBIT0; Cavium OCTEON */
+
+ /* Cavium Specific instructions. */
+ if (VEX_MIPS_COMP_ID(archinfo->hwcaps) == VEX_PRID_COMP_CAVIUM) {
+ DIP("bbit0 r%u, 0x%x, %x", rs, rt, imm);
+ t0 = newTemp(Ity_I32);
+ t1 = newTemp(Ity_I32);
+ assign(t0, mkU32(0x1));
+ assign(t1, binop(Iop_Shl32, mkexpr(t0), mkU8(rt)));
+ dis_branch(False, binop(Iop_CmpEQ32,
+ binop(Iop_And32,
+ mkexpr(t1),
+ mkNarrowTo32(ty, getIReg(rs))),
+ mkU32(0x0)),
+ imm, bstmt);
+ } else if (archinfo->hwcaps & VEX_MIPS_CPU_ISA_M32R6) { /* BC */
+ if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+ DIP("bc %x", instr_index & 0x3FFFFFF);
+
+ if (mode64) {
+ t0 = newTemp(Ity_I64);
+ assign(t0, mkU64(guest_PC_curr_instr +
+ ((extend_s_26to64(instr_index & 0x3FFFFFF) + 1 ) << 2)));
+ } else {
+ t0 = newTemp(Ity_I32);
+ assign(t0, mkU32(guest_PC_curr_instr +
+ ((extend_s_26to32(instr_index & 0x3FFFFFF) + 1) << 2)));
+ }
+
+ putPC(mkexpr(t0));
+ dres->whatNext = Dis_StopHere;
+ dres->jk_StopHere = Ijk_Boring;
} else {
- putIReg(rd, binop(Iop_And32,
- unop(Iop_Not32,
- unop(Iop_CmpwNEZ32, getIReg(rt))),
- getIReg(rs)));
+ ILLEGAL_INSTRUCTON;
+ break;
}
} else {
- ILLEGAL_INSTRUCTON;
+ return -1;
}
+
break;
- }
- case 0x36: { /* TNE */
- DIP("tne r%u, r%u %u", rs, rt, trap_code);
- if (mode64) {
- if (trap_code == 7)
- stmt(IRStmt_Exit(binop(Iop_CmpNE64, getIReg(rs),
- getIReg(rt)), Ijk_SigFPE_IntDiv,
- IRConst_U64(guest_PC_curr_instr + 4),
- OFFB_PC));
- else if (trap_code == 6)
- stmt(IRStmt_Exit(binop(Iop_CmpNE64, getIReg(rs),
- getIReg(rt)), Ijk_SigFPE_IntOvf,
- IRConst_U64(guest_PC_curr_instr + 4),
- OFFB_PC));
- else
- stmt(IRStmt_Exit(binop(Iop_CmpNE64, getIReg(rs),
- getIReg(rt)), Ijk_SigTRAP,
- IRConst_U64(guest_PC_curr_instr + 4),
- OFFB_PC));
- } else {
- if (trap_code == 7)
- stmt(IRStmt_Exit(binop(Iop_CmpNE32, getIReg(rs),
- getIReg(rt)), Ijk_SigFPE_IntDiv,
- IRConst_U32(guest_PC_curr_instr + 4),
- OFFB_PC));
- else if (trap_code == 6)
- stmt(IRStmt_Exit(binop(Iop_CmpNE32, getIReg(rs),
- getIReg(rt)), Ijk_SigFPE_IntOvf,
- IRConst_U32(guest_PC_curr_instr + 4),
- OFFB_PC));
- else
- stmt(IRStmt_Exit(binop(Iop_CmpNE32, getIReg(rs),
- getIReg(rt)), Ijk_SigTRAP,
- IRConst_U32(guest_PC_curr_instr + 4),
- OFFB_PC));
- }
+ case 0x03: /* PREF */
+ DIP("pref");
break;
- }
- case 0x37: { /* SELNEZ */
- if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
- DIP("selnez r%u, r%u, r%u", rd, rs, rt);
- if (mode64) {
- putIReg(rd, binop(Iop_And64,
- unop(Iop_CmpwNEZ64, getIReg(rt)), getIReg(rs)));
+
+ case 0x04: /* Load Linked Doubleword - LLD; MIPS64 */
+ DIP("lld r%u, %u(r%u)", rt, imm, rs);
+
+ if (mode64) {
+ LOAD_STORE_PATTERN;
+ t2 = newTemp(Ity_I64);
+
+ if (abiinfo->guest__use_fallback_LLSC) {
+ assign(t2, load(Ity_I64, mkexpr(t1)));
+ putLLaddr(mkexpr(t1));
+ putLLdata(mkexpr(t2));
} else {
- putIReg(rd, binop(Iop_And32,
- unop(Iop_CmpwNEZ32, getIReg(rt)), getIReg(rs)));
+ stmt(IRStmt_LLSC(MIPS_IEND, t2, mkexpr(t1), NULL));
}
+
+ putIReg(rt, mkexpr(t2));
} else {
- ILLEGAL_INSTRUCTON;
+ ILLEGAL_INSTRUCTON
}
- break;
- }
- case 0x14:
- case 0x16:
- case 0x17: /* DSLLV, DROTRV:DSRLV, DSRAV */
- case 0x38:
- case 0x3A:
- case 0x3B: /* DSLL, DROTL:DSRL, DSRA */
- case 0x3C:
- case 0x3E:
- case 0x3F: /* DSLL32, DROTR32:DSRL32, DSRA32 */
- if (dis_instr_shrt(cins))
- break;
- goto decode_failure;
- case 0x0F: /* SYNC */
- DIP("sync 0x%x", sel);
- /* Just ignore it. */
break;
- case 0x2C: { /* Doubleword Add - DADD; MIPS64 */
- DIP("dadd r%u, r%u, r%u", rd, rs, rt);
- IRTemp tmpRs64 = newTemp(Ity_I64);
- IRTemp tmpRt64 = newTemp(Ity_I64);
+ case 0x05: /* Load Doubleword to Floating Point - LDC1 (MIPS32) */
+ DIP("ldc1 f%u, %u(%u)", rt, imm, rs);
+ LOAD_STORE_PATTERN;
+ putDReg(ft, load(Ity_F64, mkexpr(t1)));
+ break;
- assign(tmpRs64, getIReg(rs));
- assign(tmpRt64, getIReg(rt));
+ case 0x06: /* Branch on Bit Clear Plus 32 - BBIT032; Cavium OCTEON */
- t0 = newTemp(Ity_I64);
- t1 = newTemp(Ity_I64);
- t2 = newTemp(Ity_I64);
- t3 = newTemp(Ity_I64);
- t4 = newTemp(Ity_I64);
- /* dst = src0 + src1
- if(sign(src0 ) != sign(src1 ))
- goto no overflow;
- if(sign(dst) == sign(src0 ))
- goto no overflow;
- we have overflow! */
+ /* Cavium Specific instructions. */
+ if (VEX_MIPS_COMP_ID(archinfo->hwcaps) == VEX_PRID_COMP_CAVIUM) {
+ DIP("bbit032 r%u, 0x%x, %x", rs, rt, imm);
+ t0 = newTemp(Ity_I64);
+ t1 = newTemp(Ity_I8); /* Shift. */
+ t2 = newTemp(Ity_I64);
+ assign(t0, mkU64(0x1));
+ assign(t1, binop(Iop_Add8, mkU8(rt), mkU8(32)));
+ assign(t2, binop(Iop_Shl64, mkexpr(t0), mkexpr(t1)));
+ dis_branch(False, binop(Iop_CmpEQ64,
+ binop(Iop_And64,
+ mkexpr(t2),
+ getIReg(rs)),
+ mkU64(0x0)),
+ imm, bstmt);
+ } else if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+ if (rs == 0) { /* JIC */
+ DIP("jic r%u, %u", rt, instr_index & 0xFFFF);
- assign(t0, binop(Iop_Add64, mkexpr(tmpRs64), mkexpr(tmpRt64)));
- assign(t1, binop(Iop_Xor64, mkexpr(tmpRs64), mkexpr(tmpRt64)));
- assign(t2, unop(Iop_1Uto64,
- binop(Iop_CmpEQ64,
- binop(Iop_And64, mkexpr(t1),
- mkU64(0x8000000000000000ULL)),
- mkU64(0x8000000000000000ULL))));
+ if (mode64) {
+ t0 = newTemp(Ity_I64);
+ assign(t0, binop(Iop_Add64, getIReg(rt),
+ mkU64(extend_s_16to64((instr_index & 0xFFFF)))));
+ } else {
+ t0 = newTemp(Ity_I32);
+ assign(t0, binop(Iop_Add32, getIReg(rt),
+ mkU32(extend_s_16to32((instr_index & 0xFFFF)))));
+ }
- assign(t3, binop(Iop_Xor64, mkexpr(t0), mkexpr(tmpRs64)));
- assign(t4, unop(Iop_1Uto64,
- binop(Iop_CmpNE64,
- binop(Iop_And64, mkexpr(t3),
- mkU64(0x8000000000000000ULL)),
- mkU64(0x8000000000000000ULL))));
+ putPC(mkexpr(t0));
+ dres->whatNext = Dis_StopHere;
+ dres->jk_StopHere = Ijk_Boring;
+ } else { /* BEQZC */
+ DIP("beqzc r%u, %u", rs, imm);
+ dres->jk_StopHere = Ijk_Boring;
+ dres->whatNext = Dis_StopHere;
+ ULong branch_offset;
+ t0 = newTemp(Ity_I1);
- stmt(IRStmt_Exit(binop(Iop_CmpEQ64,
- binop(Iop_Or64, mkexpr(t2), mkexpr(t4)),
- mkU64(0)),
- Ijk_SigFPE_IntOvf,
- IRConst_U64(guest_PC_curr_instr + 4),
- OFFB_PC));
+ if (mode64) {
+ branch_offset = extend_s_23to64((instr_index & 0x1fffff) << 2);
+ assign(t0, binop(Iop_CmpEQ64, getIReg(rs), mkU64(0x0)));
+ stmt(IRStmt_Exit(mkexpr(t0), Ijk_Boring,
+ IRConst_U64(guest_PC_curr_instr + 4 + branch_offset),
+ OFFB_PC));
+ putPC(mkU64(guest_PC_curr_instr + 4));
+ } else {
+ branch_offset = extend_s_23to32((instr_index & 0x1fffff) << 2);
+ assign(t0, binop(Iop_CmpEQ32, getIReg(rs), mkU32(0x0)));
+ stmt(IRStmt_Exit(mkexpr(t0), Ijk_Boring,
+ IRConst_U32(guest_PC_curr_instr + 4 +
+ (UInt) branch_offset), OFFB_PC));
+ putPC(mkU32(guest_PC_curr_instr + 4));
+ }
+ }
+ } else {
+ ILLEGAL_INSTRUCTON
+ }
- putIReg(rd, mkexpr(t0));
break;
- }
- case 0x2D: /* Doubleword Add Unsigned - DADDU; MIPS64 */
- DIP("daddu r%u, r%u, r%u", rd, rs, rt);
- ALU_PATTERN(Iop_Add64);
+ case 0x07: /* Load Doubleword - LD; MIPS64 */
+ DIP("ld r%u, %u(r%u)", rt, imm, rs);
+ LOAD_STORE_PATTERN;
+ putIReg(rt, load(Ity_I64, mkexpr(t1)));
break;
- case 0x2E: { /* Doubleword Subtract - DSUB; MIPS64 */
- DIP("dsub r%u, r%u, r%u", rd, rs, rt);
- IRTemp tmpRs64 = newTemp(Ity_I64);
- IRTemp tmpRt64 = newTemp(Ity_I64);
+ case 0x08: /* SC */
+ DIP("sc r%u, %u(r%u)", rt, imm, rs);
+ t2 = newTemp(Ity_I1);
+ LOAD_STORE_PATTERN;
- assign(tmpRs64, getIReg(rs));
- assign(tmpRt64, getIReg(rt));
- t0 = newTemp(Ity_I64);
- t1 = newTemp(Ity_I64);
- t2 = newTemp(Ity_I64);
- t3 = newTemp(Ity_I64);
- t4 = newTemp(Ity_I64);
- t5 = newTemp(Ity_I64);
- /* dst = src0 + (-1 * src1)
- if(sign(src0 ) != sign((-1 * src1) ))
- goto no overflow;
- if(sign(dst) == sign(src0 ))
- goto no overflow;
- we have overflow! */
+ if (abiinfo->guest__use_fallback_LLSC) {
+ t3 = newTemp(Ity_I32);
+ assign(t2, binop(mode64 ? Iop_CmpNE64 : Iop_CmpNE32,
+ mkexpr(t1), getLLaddr()));
+ assign(t3, mkNarrowTo32(ty, getIReg(rt)));
+ putLLaddr(LLADDR_INVALID);
+ putIReg(rt, getIReg(0));
- assign(t5, binop(Iop_Mul64,
- mkexpr(tmpRt64),
- mkU64(0xffffffffffffffffULL)));
- assign(t0, binop(Iop_Add64, mkexpr(tmpRs64), mkexpr(t5)));
- assign(t1, binop(Iop_Xor64, mkexpr(tmpRs64), mkexpr(t5)));
- assign(t2, unop(Iop_1Sto64,
- binop(Iop_CmpEQ64,
- binop(Iop_And64,
- mkexpr(t1),
- mkU64(0x8000000000000000ULL)),
- mkU64(0x8000000000000000ULL))));
+ mips_next_insn_if(mkexpr(t2));
- assign(t3, binop(Iop_Xor64, mkexpr(t0), mkexpr(tmpRs64)));
- assign(t4, unop(Iop_1Sto64,
- binop(Iop_CmpNE64,
- binop(Iop_And64,
- mkexpr(t3),
- mkU64(0x8000000000000000ULL)),
- mkU64(0x8000000000000000ULL))));
+ t4 = newTemp(Ity_I32);
+ t5 = newTemp(Ity_I32);
- stmt(IRStmt_Exit(binop(Iop_CmpEQ64, binop(Iop_Or64, mkexpr(t2),
- mkexpr(t4)), mkU64(0)), Ijk_SigFPE_IntOvf,
- IRConst_U64(guest_PC_curr_instr + 4),
- OFFB_PC));
+ assign(t5, mkNarrowTo32(ty, getLLdata()));
+
+ stmt(IRStmt_CAS(mkIRCAS(IRTemp_INVALID, t4, /* old_mem */
+ MIPS_IEND, mkexpr(t1), /* addr */
+ NULL, mkexpr(t5), /* expected value */
+ NULL, mkexpr(t3) /* new value */)));
+
+ putIReg(rt, unop(mode64 ? Iop_1Uto64 : Iop_1Uto32,
+ binop(Iop_CmpEQ32, mkexpr(t4), mkexpr(t5))));
+ } else {
+ stmt(IRStmt_LLSC(MIPS_IEND, t2, mkexpr(t1),
+ mkNarrowTo32(ty, getIReg(rt))));
+ putIReg(rt, unop(mode64 ? Iop_1Uto64 : Iop_1Uto32, mkexpr(t2)));
+ }
- putIReg(rd, binop(Iop_Sub64, getIReg(rs), getIReg(rt)));
break;
- }
- case 0x2F: /* Doubleword Subtract Unsigned - DSUBU; MIPS64 */
- DIP("dsub r%u, r%u,r%u", rd, rt, rt);
- ALU_PATTERN(Iop_Sub64);
+ case 0x09: /* SWC1 */
+ DIP("swc1 f%u, %u(r%u)", ft, imm, rs);
+
+ if (fp_mode64) {
+ t0 = newTemp(Ity_I64);
+ t2 = newTemp(Ity_I32);
+ LOAD_STORE_PATTERN;
+ assign(t0, unop(Iop_ReinterpF64asI64, getFReg(ft)));
+ assign(t2, unop(Iop_64to32, mkexpr(t0)));
+ store(mkexpr(t1), unop(Iop_ReinterpI32asF32, mkexpr(t2)));
+ } else {
+ LOAD_STORE_PATTERN;
+ store(mkexpr(t1), getFReg(ft));
+ }
+
break;
- default:
- goto decode_failure;
- }
- break;
+ case 0x0A: /* Branch on Bit Set - BBIT1; Cavium OCTEON */
- case 0x01: /* Regimm */
+ /* Cavium Specific instructions. */
+ if (VEX_MIPS_COMP_ID(archinfo->hwcaps) == VEX_PRID_COMP_CAVIUM) {
+ DIP("bbit1 r%u, 0x%x, %x", rs, rt, imm);
+ t0 = newTemp(Ity_I32);
+ t1 = newTemp(Ity_I32);
+ assign(t0, mkU32(0x1));
+ assign(t1, binop(Iop_Shl32, mkexpr(t0), mkU8(rt)));
+ dis_branch(False, binop(Iop_CmpNE32,
+ binop(Iop_And32,
+ mkexpr(t1),
+ mkNarrowTo32(ty, getIReg(rs))),
+ mkU32(0x0)),
+ imm, bstmt);
+ } else if (archinfo->hwcaps & VEX_MIPS_CPU_ISA_M32R6) {/* BALC */
+ if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+ DIP("balc %x", instr_index & 0x3FFFFFF);
+
+ if (mode64) {
+ t0 = newTemp(Ity_I64);
+ assign(t0, mkU64(guest_PC_curr_instr + ((extend_s_26to64(
+ instr_index & 0x3FFFFFF) + 1) << 2)));
+ putIReg(31, mkU64(guest_PC_curr_instr + 4));
+ } else {
+ t0 = newTemp(Ity_I32);
+ assign(t0, mkU32(guest_PC_curr_instr + ((extend_s_26to32(
+ instr_index & 0x3FFFFFF) + 1) << 2)));
+ putIReg(31, mkU32(guest_PC_curr_instr + 4));
+ }
+
+ putPC(mkexpr(t0));
+ dres->whatNext = Dis_StopHere;
+ dres->jk_StopHere = Ijk_Call;
+ } else {
+ ILLEGAL_INSTRUCTON;
+ break;
+ }
+ } else {
+ return -1;
+ }
- switch (rt) {
- case 0x00: /* BLTZ */
- DIP("bltz r%u, %u", rs, imm);
- if (mode64) {
- if (!dis_instr_branch(cins, &dres, resteerOkFn,
- callback_opaque, &bstmt))
- goto decode_failure;
- } else
- dis_branch(False, binop(Iop_CmpEQ32, binop(Iop_And32, getIReg(rs),
- mkU32(0x80000000)), mkU32(0x80000000)), imm, &bstmt);
break;
- case 0x01: /* BGEZ */
- DIP("bgez r%u, %u", rs, imm);
+ case 0x0B: /* PCREL */
+ if (rt == 0x1E) { /* AUIPC */
+ if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+ DIP("auipc r%u, %u", rs, imm);
+
+ if (mode64) {
+ putIReg(rs, mkU64(guest_PC_curr_instr + (imm << 16)));
+ } else {
+ putIReg(rs, mkU32(guest_PC_curr_instr + (imm << 16)));
+ }
+ } else {
+ ILLEGAL_INSTRUCTON;
+ }
+
+ break;
+ } else if (rt == 0x1F) { /* ALUIPC */
+ if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+ DIP("aluipc r%u, %u", rs, imm);
+
+ if (mode64) {
+ putIReg(rs, mkU64((~0x0FFFFULL) &
+ (guest_PC_curr_instr + extend_s_32to64(imm << 16))));
+ } else {
+ putIReg(rs, mkU32((~0x0FFFFULL) &
+ (guest_PC_curr_instr + (imm << 16))));
+ }
+ } else {
+ ILLEGAL_INSTRUCTON;
+ }
+
+ break;
+ } else if ((rt & 0x18) == 0) { /* ADDIUPC */
+ if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+ DIP("addiupc r%u, %u", rs, instr_index & 0x7FFFF);
+
+ if (mode64) {
+ putIReg(rs, mkU64(guest_PC_curr_instr +
+ (extend_s_19to64(instr_index & 0x7FFFF) << 2)));
+ } else {
+ putIReg(rs, mkU32(guest_PC_curr_instr +
+ (extend_s_19to32(instr_index & 0x7FFFF) << 2)));
+ }
+ } else {
+ ILLEGAL_INSTRUCTON;
+ }
+
+ break;
+ } else if ((rt & 0x18) == 8) { /* LWPC */
+ if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+ DIP("lwpc r%u, %x", rs, instr_index & 0x7FFFF);
+
+ if (mode64) {
+ t1 = newTemp(Ity_I64);
+ assign(t1, mkU64(guest_PC_curr_instr +
+ (extend_s_19to64(instr_index & 0x7FFFF) << 2)));
+ putIReg(rs, unop(Iop_32Sto64, load(Ity_I32, mkexpr(t1))));
+ } else {
+ t1 = newTemp(Ity_I32);
+ assign(t1, mkU32(guest_PC_curr_instr +
+ (extend_s_19to32(instr_index & 0x7FFFF) << 2)));
+ putIReg(rs, load(Ity_I32, mkexpr(t1)));
+ }
+ } else {
+ ILLEGAL_INSTRUCTON;
+ }
+
+ break;
+ } else if ((rt & 0x18) == 16) { /* LWUPC */
+ if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+ DIP("lwupc r%u, %x", rs, instr_index & 0x7FFFF);
+
+ if (mode64) {
+ t1 = newTemp(Ity_I64);
+ assign(t1, mkU64(guest_PC_curr_instr +
+ (extend_s_19to64(instr_index & 0x7FFFF) << 2)));
+ putIReg(rs, unop(Iop_32Uto64, load(Ity_I32, mkexpr(t1))));
+ } else {
+ t1 = newTemp(Ity_I32);
+ assign(t1, mkU32(guest_PC_curr_instr +
+ (extend_s_19to32(instr_index & 0x7FFFF) << 2)));
+ putIReg(rs, load(Ity_I32, mkexpr(t1)));
+ }
+ } else {
+ ILLEGAL_INSTRUCTON
+ }
+
+ break;
+ } else if ((rt & 0x1C) == 0x18) { /* LDPC */
+ if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+ DIP("ldpc r%u, %x", rs, instr_index & 0x3FFFF);
+ t1 = newTemp(Ity_I64);
+ assign(t1, mkU64(guest_PC_curr_instr +
+ (extend_s_18to64(instr_index & 0x3FFFF) << 3)));
+ putIReg(rs, load(Ity_I64, mkexpr(t1)));
+ } else {
+ ILLEGAL_INSTRUCTON
+ }
+
+ break;
+ } else {
+ return -1;
+ }
+
+ if (0x3B == function &&
+ (VEX_MIPS_COMP_ID(archinfo->hwcaps) == VEX_PRID_COMP_BROADCOM)) {
+ /*RDHWR*/
+ DIP("rdhwr r%u, r%u", rt, rd);
+
+ if (rd == 29) {
+ putIReg(rt, getULR());
+ } else
+ return -1;
+
+ break;
+ } else {
+ return -1;
+ }
+
+ case 0x0C: /* Store Conditional Doubleword - SCD; MIPS64 */
+ DIP("scd r%u, %u(r%u)", rt, imm, rs);
+
if (mode64) {
- if (!dis_instr_branch(cins, &dres, resteerOkFn,
- callback_opaque, &bstmt))
- goto decode_failure;
- } else
- dis_branch(False, binop(Iop_CmpEQ32, binop(Iop_And32, getIReg(rs),
- mkU32(0x80000000)), mkU32(0x0)), imm, &bstmt);
- break;
+ t2 = newTemp(Ity_I1);
+ LOAD_STORE_PATTERN;
- case 0x02: /* BLTZL */
- DIP("bltzl r%u, %u", rs, imm);
- lastn = dis_branch_likely(binop(mode64 ? Iop_CmpNE64 : Iop_CmpNE32,
- binop(mode64 ? Iop_And64 : Iop_And32, getIReg(rs),
- mode64 ? mkU64(0x8000000000000000ULL) : mkU32(0x80000000)),
- mode64 ? mkU64(0x8000000000000000ULL) : mkU32(0x80000000)),
- imm);
- break;
+ if (abiinfo->guest__use_fallback_LLSC) {
+ t3 = newTemp(Ity_I64);
+ assign(t2, binop(Iop_CmpNE64, mkexpr(t1), getLLaddr()));
+ assign(t3, getIReg(rt));
+ putLLaddr(LLADDR_INVALID);
+ putIReg(rt, getIReg(0));
- case 0x03: /* BGEZL */
- DIP("bgezl r%u, %u", rs, imm);
- lastn = dis_branch_likely(binop(mode64 ? Iop_CmpNE64 : Iop_CmpNE32,
- binop(mode64 ? Iop_And64 : Iop_And32, getIReg(rs),
- mode64 ? mkU64(0x8000000000000000ULL) : mkU32(0x80000000)),
- mode64 ? mkU64(0x0) : mkU32(0x0)), imm);
- break;
+ mips_next_insn_if(mkexpr(t2));
- case 0x10: /* BLTZAL */
- DIP("bltzal r%u, %u", rs, imm);
- if (mode64) {
- if (!dis_instr_branch(cins, &dres, resteerOkFn,
- callback_opaque, &bstmt))
- goto decode_failure;
- } else
- dis_branch(True, binop(Iop_CmpEQ32, binop(Iop_And32, getIReg(rs),
- mkU32(0x80000000)), mkU32(0x80000000)), imm, &bstmt);
- break;
+ t4 = newTemp(Ity_I64);
+ t5 = newTemp(Ity_I64);
- case 0x12: /* BLTZALL */
- DIP("bltzall r%u, %u", rs, imm);
- putIReg(31, mode64 ? mkU64(guest_PC_curr_instr + 8) :
- mkU32(guest_PC_curr_instr + 8));
- lastn = dis_branch_likely(binop(mode64 ? Iop_CmpNE64 : Iop_CmpNE32,
- binop(mode64 ? Iop_And64 : Iop_And32, getIReg(rs),
- mode64 ? mkU64(0x8000000000000000ULL) : mkU32(0x80000000)),
- mode64 ? mkU64(0x8000000000000000ULL) : mkU32(0x80000000)),
- imm);
- break;
+ assign(t5, getLLdata());
- case 0x11: /* BGEZAL */
- DIP("bgezal r%u, %u", rs, imm);
- if (mode64) {
- if (!dis_instr_branch(cins, &dres, resteerOkFn,
- callback_opaque, &bstmt))
- goto decode_failure;
- } else
- dis_branch(True, binop(Iop_CmpEQ32, binop(Iop_And32, getIReg(rs),
- mkU32(0x80000000)), mkU32(0x0)), imm, &bstmt);
- break;
+ stmt(IRStmt_CAS(mkIRCAS(IRTemp_INVALID, t4, /* old_mem */
+ MIPS_IEND, mkexpr(t1), /* addr */
+ NULL, mkexpr(t5), /* expected value */
+ NULL, mkexpr(t3) /* new value */)));
- case 0x13: /* BGEZALL */
- DIP("bgezall r%u, %u", rs, imm);
- if (mode64) {
- putIReg(31, mkU64(guest_PC_curr_instr + 8));
- lastn = dis_branch_likely(binop(Iop_CmpNE64,
- binop(Iop_And64,
- getIReg(rs),
- mkU64(0x8000000000000000ULL)),
- mkU64(0x0)),
- imm);
+ putIReg(rt, unop(Iop_1Uto64,
+ binop(Iop_CmpEQ64, mkexpr(t4), mkexpr(t5))));
+ } else {
+ stmt(IRStmt_LLSC(MIPS_IEND, t2, mkexpr(t1), getIReg(rt)));
+ putIReg(rt, unop(Iop_1Uto64, mkexpr(t2)));
+ }
} else {
- putIReg(31, mkU32(guest_PC_curr_instr + 8));
- lastn = dis_branch_likely(binop(Iop_CmpNE32, binop(Iop_And32,
- getIReg(rs), mkU32(0x80000000)),
- mkU32(0x0)), imm);
+ ILLEGAL_INSTRUCTON
}
- break;
- case 0x08: /* TGEI */
- DIP("tgei r%u, %u %u", rs, imm, trap_code);
- if (mode64) {
- stmt (IRStmt_Exit(unop(Iop_Not1,
- binop(Iop_CmpLT64S,
- getIReg(rs),
- mkU64(extend_s_16to64 (imm)))),
- Ijk_SigTRAP,
- IRConst_U64(guest_PC_curr_instr + 4),
- OFFB_PC));
- } else {
- stmt (IRStmt_Exit(unop(Iop_Not1,
- binop(Iop_CmpLT32S,
- getIReg(rs),
- mkU32(extend_s_16to32 (imm)))),
- Ijk_SigTRAP,
- IRConst_U32(guest_PC_curr_instr + 4),
- OFFB_PC));
- }
break;
- case 0x09: { /* TGEIU */
- DIP("tgeiu r%u, %u %u", rs, imm, trap_code);
- if (mode64) {
- stmt (IRStmt_Exit (unop (Iop_Not1,
- binop (Iop_CmpLT64U,
- getIReg (rs),
- mkU64 (extend_s_16to64 (imm)))),
- Ijk_SigTRAP,
- IRConst_U64(guest_PC_curr_instr + 4),
- OFFB_PC));
- } else {
- stmt (IRStmt_Exit (unop (Iop_Not1,
- binop (Iop_CmpLT32U,
- getIReg (rs),
- mkU32 (extend_s_16to32 (imm)))),
- Ijk_SigTRAP,
- IRConst_U32(guest_PC_curr_instr + 4),
- OFFB_PC));
- }
- break;
- }
- case 0x0A: { /* TLTI */
- DIP("tlti r%u, %u %u", rs, imm, trap_code);
- if (mode64) {
- stmt (IRStmt_Exit (binop (Iop_CmpLT64S, getIReg (rs),
- mkU64 (extend_s_16to64 (imm))),
- Ijk_SigTRAP,
- IRConst_U64(guest_PC_curr_instr + 4),
- OFFB_PC));
- } else {
- stmt (IRStmt_Exit (binop (Iop_CmpLT32S, getIReg (rs),
- mkU32 (extend_s_16to32 (imm))),
- Ijk_SigTRAP,
- IRConst_U32(guest_PC_curr_instr + 4),
- OFFB_PC));
- }
- break;
- }
- case 0x0B: { /* TLTIU */
- DIP("tltiu r%u, %u %u", rs, imm, trap_code);
- if (mode64) {
- stmt (IRStmt_Exit (binop (Iop_CmpLT64U, getIReg (rs),
- mkU64 (extend_s_16to64 (imm))),
- Ijk_SigTRAP,
- IRConst_U64(guest_PC_curr_instr + 4),
- OFFB_PC));
- } else {
- stmt (IRStmt_Exit (binop (Iop_CmpLT32U, getIReg (rs),
- mkU32 (extend_s_16to32 (imm))),
- Ijk_SigTRAP,
- IRConst_U32(guest_PC_curr_instr + 4),
- OFFB_PC));
- }
- break;
- }
- case 0x0C: { /* TEQI */
- DIP("teqi r%u, %u %u", rs, imm, trap_code);
- if (mode64) {
- stmt (IRStmt_Exit (binop (Iop_CmpEQ64, getIReg (rs),
- mkU64 (extend_s_16to64 (imm))),
- Ijk_SigTRAP,
- IRConst_U64(guest_PC_curr_instr + 4),
- OFFB_PC));
- } else {
- stmt (IRStmt_Exit (binop (Iop_CmpEQ32, getIReg (rs),
- mkU32 (extend_s_16to32 (imm))),
- Ijk_SigTRAP,
- IRConst_U32(guest_PC_curr_instr + 4),
- OFFB_PC));
- }
- break;
- }
- case 0x0E: { /* TNEI */
- DIP("tnei r%u, %u %u", rs, imm, trap_code);
- if (mode64) {
- stmt (IRStmt_Exit (binop (Iop_CmpNE64, getIReg (rs),
- mkU64 (extend_s_16to64 (imm))),
- Ijk_SigTRAP,
- IRConst_U64(guest_PC_curr_instr + 4),
- OFFB_PC));
- } else {
- stmt (IRStmt_Exit (binop (Iop_CmpNE32, getIReg (rs),
- mkU32 (extend_s_16to32 (imm))),
- Ijk_SigTRAP,
- IRConst_U32(guest_PC_curr_instr + 4),
- OFFB_PC));
- }
- break;
- }
- case 0x1C: { /* BPOSGE32 */
- DIP("bposge32 %u", imm);
- vassert(!mode64);
- t0 = newTemp(Ity_I32);
- /* Get pos field from DSPControl register. */
- assign(t0, binop(Iop_And32, getDSPControl(), mkU32(0x3f)));
- dis_branch(False, unop(Iop_Not1, binop(Iop_CmpLT32U, mkexpr(t0),
- mkU32(32))), imm, &bstmt);
- }
- case 0x1F:
- /* SYNCI */
- /* Just ignore it */
+ case 0x0D: /* Store Doubleword from Floating Point - SDC1 */
+ DIP("sdc1 f%u, %u(%u)", ft, imm, rs);
+ LOAD_STORE_PATTERN;
+ store(mkexpr(t1), getDReg(ft));
break;
- case 0x06: { /* DAHI */
- if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
- DIP("dahi r%u, %x", rs, imm);
- putIReg(rs, binop(Iop_Add64,
- getIReg(rs), mkU64(extend_s_16to64 (imm) << 32)));
+ case 0x0E: /* Branch on Bit Set Plus 32 - BBIT132; Cavium OCTEON */
+
+ /* Cavium Specific instructions. */
+ if (VEX_MIPS_COMP_ID(archinfo->hwcaps) == VEX_PRID_COMP_CAVIUM) {
+ DIP("bbit132 r%u, 0x%x, %x", rs, rt, imm);
+ t0 = newTemp(Ity_I64);
+ t1 = newTemp(Ity_I8); /* Shift. */
+ t2 = newTemp(Ity_I64);
+ assign(t0, mkU64(0x1));
+ assign(t1, binop(Iop_Add8, mkU8(rt), mkU8(32)));
+ assign(t2, binop(Iop_Shl64, mkexpr(t0), mkexpr(t1)));
+ dis_branch(False, binop(Iop_CmpNE64,
+ binop(Iop_And64,
+ mkexpr(t2),
+ getIReg(rs)),
+ mkU64(0x0)),
+ imm, bstmt);
+ } else if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
+ if (rs == 0) {/* JIALC */
+ DIP("jialc r%u, %u", rt, instr_index & 0xFFFF);
+
+ if (rs) return -1;
+
+ if (mode64) {
+ t0 = newTemp(Ity_I64);
+ assign(t0, binop(Iop_Add64, getIReg(rt),
+ mkU64(extend_s_16to64((instr_index & 0xFFFF)))));
+ putIReg(31, mkU64(guest_PC_curr_instr + 4));
+ } else {
+ t0 = newTemp(Ity_I32);
+ assign(t0, binop(Iop_Add32, getIReg(rt),
+ mkU32(extend_s_16to32((instr_index & 0xFFFF)))));
+ putIReg(31, mkU32(guest_PC_curr_instr + 4));
+ }
+
+ putPC(mkexpr(t0));
+ dres->whatNext = Dis_StopHere;
+ dres->jk_StopHere = Ijk_Call;
+ } else { /* BNEZC */
+ DIP("bnezc r%u, %u", rs, imm);
+ dres->jk_StopHere = Ijk_Boring;
+ dres->whatNext = Dis_StopHere;
+ ULong branch_offset;
+ t0 = newTemp(Ity_I1);
+
+ if (mode64) {
+ branch_offset = extend_s_23to64((instr_index & 0x1fffff) << 2);
+ assign(t0, unop(Iop_Not1, binop(Iop_CmpEQ64, getIReg(rs), mkU64(0x0))));
+ stmt(IRStmt_Exit(mkexpr(t0), Ijk_Boring,
+ IRConst_U64(guest_PC_curr_instr + 4 + branch_offset),
+ OFFB_PC));
+ putPC(mkU64(guest_PC_curr_instr + 4));
+ } else {
+ branch_offset = extend_s_23to32((instr_index & 0x1fffff) << 2);
+ assign(t0, unop(Iop_Not1, binop(Iop_CmpEQ32, getIReg(rs), mkU32(0x0))));
+ stmt(IRStmt_Exit(mkexpr(t0), Ijk_Boring,
+ IRConst_U32(guest_PC_curr_instr + 4 +
+ (UInt) branch_offset), OFFB_PC));
+ putPC(mkU32(guest_PC_curr_instr + 4));
+ }
+ }
} else {
- ILLEGAL_INSTRUCTON;
+ return -1;
}
+
break;
- }
- case 0x1E: { /* DATI */
- if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
- DIP("dati r%u, %x", rs, imm);
- putIReg(rs, binop(Iop_Add64,
- getIReg(rs), mkU64((long long)imm << 48)));
- } else {
- ILLEGAL_INSTRUCTON;
- }
+ case 0x0F: /* Store Doubleword - SD; MIPS64 */
+ DIP("sd r%u, %u(r%u)", rt, imm, rs);
+ LOAD_STORE_PATTERN;
+ store(mkexpr(t1), getIReg(rt));
break;
- }
default:
- goto decode_failure;
- }
- break;
+ return -1;
+ }
- case 0x04:
- DIP("beq r%u, r%u, %u", rs, rt, imm);
- if (mode64)
- dis_branch(False, binop(Iop_CmpEQ64, getIReg(rs), getIReg(rt)),
- imm, &bstmt);
- else
- dis_branch(False, binop(Iop_CmpEQ32, getIReg(rs), getIReg(rt)),
- imm, &bstmt);
- break;
-
- case 0x14:
- DIP("beql r%u, r%u, %u", rs, rt, imm);
- lastn = dis_branch_likely(binop(mode64 ? Iop_CmpNE64 : Iop_CmpNE32,
- getIReg(rs), getIReg(rt)), imm);
- break;
-
- case 0x05:
- DIP("bne r%u, r%u, %u", rs, rt, imm);
- if (mode64)
- dis_branch(False, binop(Iop_CmpNE64, getIReg(rs), getIReg(rt)),
- imm, &bstmt);
- else
- dis_branch(False, binop(Iop_CmpNE32, getIReg(rs), getIReg(rt)),
- imm, &bstmt);
- break;
-
- case 0x15:
- DIP("bnel r%u, r%u, %u", rs, rt, imm);
- lastn = dis_branch_likely(binop(mode64 ? Iop_CmpEQ64 : Iop_CmpEQ32,
- getIReg(rs), getIReg(rt)), imm);
- break;
-
- case 0x07: /* BGTZ, BGTZALC, BLTZALC, BLTUC */
- if (rt == 0) { /* BGTZ */
- DIP("bgtz r%u, %u", rs, imm);
- if (mode64)
- dis_branch(False, unop(Iop_Not1, binop(Iop_CmpLE64S, getIReg(rs),
- mkU64(0x00))), imm, &bstmt);
- else
- dis_branch(False, unop(Iop_Not1, binop(Iop_CmpLE32S, getIReg(rs),
- mkU32(0x00))), imm, &bstmt);
- } else if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
- if (rs == 0) { /* BGTZALC */
- DIP("bgtzalc r%u, %u", rt, imm);
- if (mode64) {
- dis_branch_compact(True,
- unop(Iop_Not1,
- binop(Iop_CmpLE64S,
- getIReg(rt), mkU64(0x0))),
- imm, &dres);
- } else {
- dis_branch_compact(True,
- unop(Iop_Not1,
- binop(Iop_CmpLE32S,
- getIReg(rt), mkU32(0x0))),
- imm, &dres);
- }
- } else if (rs == rt) { /* BLTZALC */
- DIP("bltzalc r%u, %u", rt, imm);
- if (mode64) {
- dis_branch_compact(True,
- unop(Iop_Not1,
- binop(Iop_CmpLE64S,
- mkU64(0x0), getIReg(rt))),
- imm, &dres);
- } else {
- dis_branch_compact(True,
- unop(Iop_Not1,
- binop(Iop_CmpLE32S,
- mkU32(0x0), getIReg(rt))),
- imm, &dres);
- }
- } else { /* BLTUC */
- DIP("bltuc r%u, r%u, %u", rt, rs, imm);
- if (mode64) {
- dis_branch_compact(False,
- binop(Iop_CmpLT64U, getIReg(rs), getIReg(rt)),
- imm, &dres);
- } else {
- dis_branch_compact(False,
- binop(Iop_CmpLT32U, getIReg(rs), getIReg(rt)),
- imm, &dres);
- }
- }
- } else {
- ILLEGAL_INSTRUCTON;
- }
- break;
+ return 0;
+}
- case 0x17: /* BGTZL, BGTZC, BLTZC, BLTC */
- if (rt == 0) { /* BGTZL */
- DIP("bgtzl r%u, %u", rs, imm);
- if (mode64)
- lastn = dis_branch_likely(binop(Iop_CmpLE64S, getIReg(rs),
- mkU64(0x00)), imm);
- else
- lastn = dis_branch_likely(binop(Iop_CmpLE32S, getIReg(rs),
- mkU32(0x00)), imm);
- } else if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
- if (rs == 0) { /* BGTZC */
- DIP("bgtzc r%u, %u", rt, imm);
- if (mode64) {
- dis_branch_compact(False,
- unop(Iop_Not1,
- binop(Iop_CmpLE64S,
- getIReg(rt), mkU64(0x0))),
- imm, &dres);
- } else {
- dis_branch_compact(False,
- unop(Iop_Not1,
- binop(Iop_CmpLE32S,
- getIReg(rt), mkU32(0x0))),
- imm, &dres);
- }
- } else if (rs == rt) { /* BLTZC */
- DIP("bltzc r%u, %u", rt, imm);
- if (mode64) {
- dis_branch_compact(False,
- unop(Iop_Not1,
- binop(Iop_CmpLE64S,
- mkU64(0x0), getIReg(rt))),
- imm, &dres);
- } else {
- dis_branch_compact(False,
- unop(Iop_Not1,
- binop(Iop_CmpLE32S,
- mkU32(0x0), getIReg(rt))),
- imm, &dres);
- }
- } else { /* BLTC */
- DIP("bltc r%u, r%u, %u", rs, rt, imm);
- if (mode64) {
- dis_branch_compact(False,
- unop(Iop_Not1,
- binop(Iop_CmpLE64S,
- getIReg(rt), getIReg(rs))),
- imm, &dres);
- } else {
- dis_branch_compact(False,
- unop(Iop_Not1,
- binop(Iop_CmpLE32S,
- getIReg(rt), getIReg(rs))),
- imm, &dres);
- }
- }
- } else {
- ILLEGAL_INSTRUCTON;
- }
- break;
+static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *,
+ Addr),
+ Bool resteerCisOk,
+ void* callback_opaque,
+ Long delta64,
+ const VexArchInfo* archinfo,
+ const VexAbiInfo* abiinfo,
+ Bool sigill_diag )
+{
- case 0x06: /* BLEZ, BLEZALC, BGEZALC, BGEUC */
- if (rt == 0) { /* BLEZ */
- DIP("blez r%u, %u", rs, imm);
- if (mode64)
- dis_branch(False, binop(Iop_CmpLE64S, getIReg(rs), mkU64(0x0)),
- imm, &bstmt);
- else
- dis_branch(False, binop(Iop_CmpLE32S, getIReg(rs), mkU32(0x0)), imm,
- &bstmt);
- } else if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
- if (rs == 0) { /* BLEZALC */
- DIP("blezalc r%u, %u", rt, imm);
- if (mode64)
- dis_branch_compact(True,
- binop(Iop_CmpLE64S, getIReg(rt), mkU64(0x0)),
- imm, &dres);
- else
- dis_branch_compact(True,
- binop(Iop_CmpLE32S, getIReg(rt), mkU32(0x0)),
- imm, &dres);
- } else if (rt == rs) {/* BGEZALC */
- DIP("bgezalc r%u, %u", rt, imm);
- if (mode64)
- dis_branch_compact(True,
- binop(Iop_CmpLE64S, mkU64(0x0), getIReg(rt)),
- imm, &dres);
- else
- dis_branch_compact(True,
- binop(Iop_CmpLE32S, mkU32(0x0), getIReg(rt)),
- imm, &dres);
- } else { /* BGEUC */
- DIP("bgeuc r%u, r%u, %u", rt, rs, imm);
- if (mode64)
- dis_branch_compact(False,
- unop(Iop_Not1,
- binop(Iop_CmpLT64U,
- getIReg(rs), getIReg(rt))),
- imm, &dres);
- else
- dis_branch_compact(False,
- unop(Iop_Not1,
- binop(Iop_CmpLT32U,
- getIReg(rs), getIReg(rt))),
- imm, &dres);
- }
- } else {
- ILLEGAL_INSTRUCTON;
- }
- break;
-
- case 0x16: /* BLEZL, BLEZC, BGEZC, BGEC */
- if (rt == 0) { /* BLEZL */
- DIP("blezl r%u, %u", rs, imm);
- lastn = dis_branch_likely(unop(Iop_Not1, (binop(mode64 ? Iop_CmpLE64S :
- Iop_CmpLE32S, getIReg(rs), mode64 ?
- mkU64(0x0) : mkU32(0x0)))), imm);
- } else if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
- if (rs == 0) { /* BLEZC */
- DIP("blezc r%u, %u", rt, imm);
- if (mode64) {
- dis_branch_compact(False,
- binop(Iop_CmpLE64S, getIReg(rt), mkU64(0x0)),
- imm, &dres);
- } else {
- dis_branch_compact(False,
- binop(Iop_CmpLE32S, getIReg(rt), mkU32(0x0)),
- imm, &dres);
- }
- } else if (rt == rs) { /* BGEZC */
- DIP("bgezc r%u, %u", rt, imm);
- if (mode64) {
- dis_branch_compact(False,
- binop(Iop_CmpLE64S, mkU64(0x0), getIReg(rt)),
- imm, &dres);
- } else {
- dis_branch_compact(False,
- binop(Iop_CmpLE32S, mkU32(0x0), getIReg(rt)),
- imm, &dres);
- }
- } else { /* BGEC */
- DIP("bgec r%u, r%u, %u", rs, rt, imm);
- if (mode64) {
- dis_branch_compact(False,
- binop(Iop_CmpLE64S, getIReg(rt), getIReg(rs)),
- imm, &dres);
- } else {
- dis_branch_compact(False,
- binop(Iop_CmpLE32S, getIReg(rt), getIReg(rs)),
- imm, &dres);
- }
- }
- } else {
- ILLEGAL_INSTRUCTON;
- }
- break;
+ UInt opcode, cins, result;
-#if defined(__mips__) && ((defined(__mips_isa_rev) && __mips_isa_rev < 6))
- case 0x08: { /* ADDI */
- DIP("addi r%u, r%u, %u", rt, rs, imm);
- IRTemp tmpRs32 = newTemp(Ity_I32);
- assign(tmpRs32, mkNarrowTo32(ty, getIReg(rs)));
+ DisResult dres;
- t0 = newTemp(Ity_I32);
- t1 = newTemp(Ity_I32);
- t2 = newTemp(Ity_I32);
- t3 = newTemp(Ity_I32);
- t4 = newTemp(Ity_I32);
- /* dst = src0 + sign(imm)
- if(sign(src0 ) != sign(imm ))
- goto no overflow;
- if(sign(dst) == sign(src0 ))
- goto no overflow;
- we have overflow! */
+ static IRExpr *lastn = NULL; /* last jump addr */
+ static IRStmt *bstmt = NULL; /* branch (Exit) stmt */
- assign(t0, binop(Iop_Add32, mkexpr(tmpRs32),
- mkU32(extend_s_16to32(imm))));
- assign(t1, binop(Iop_Xor32, mkexpr(tmpRs32),
- mkU32(extend_s_16to32(imm))));
- assign(t2, unop(Iop_1Sto32, binop(Iop_CmpEQ32, binop(Iop_And32,
- mkexpr(t1), mkU32(0x80000000)), mkU32(0x80000000))));
+ /* The running delta */
+ Int delta = (Int) delta64;
- assign(t3, binop(Iop_Xor32, mkexpr(t0), mkexpr(tmpRs32)));
- assign(t4, unop(Iop_1Sto32, binop(Iop_CmpNE32, binop(Iop_And32,
- mkexpr(t3), mkU32(0x80000000)), mkU32(0x80000000))));
+ /* Holds eip at the start of the insn, so that we can print
+ consistent error messages for unimplemented insns. */
+ Int delta_start = delta;
- stmt(IRStmt_Exit(binop(Iop_CmpEQ32, binop(Iop_Or32, mkexpr(t2),
- mkexpr(t4)), mkU32(0)), Ijk_SigFPE_IntOvf,
- mode64 ? IRConst_U64(guest_PC_curr_instr + 4) :
- IRConst_U32(guest_PC_curr_instr + 4),
- OFFB_PC));
+ /* Are we in a delay slot ? */
+ Bool delay_slot_branch, likely_delay_slot, delay_slot_jump;
- putIReg(rt, mkWidenFrom32(ty, mkexpr(t0), True));
- break;
- }
-#elif defined(__mips__) && ((defined(__mips_isa_rev) && __mips_isa_rev >= 6))
- case 0x08: { /* BEQZALC, BEQC, BOVC */
- if (rs == 0) { /* BEQZALC */
- DIP("beqzalc r%u, %u", rt, imm);
- if (mode64) {
- dis_branch_compact(True,
- binop(Iop_CmpEQ64, getIReg(rt), mkU64(0x0)),
- imm, &dres);
- } else {
- dis_branch_compact(True,
- binop(Iop_CmpEQ32, getIReg(rt), mkU32(0x0)),
- imm, &dres);
- }
- } else if (rs < rt) { /* BEQC */
- DIP("beqc r%u, r%u, %u",rs, rt, imm);
- if (mode64) {
- dis_branch_compact(False,
- binop(Iop_CmpEQ64, getIReg(rt), getIReg(rs)),
- imm, &dres);
- } else {
- dis_branch_compact(False,
- binop(Iop_CmpEQ32, getIReg(rt), getIReg(rs)),
- imm, &dres);
- }
- } else { /* BOVC */
- DIP("bovc r%u, r%u, %u",rs, rt, imm);
- if (mode64) {
- t0 = newTemp(Ity_I32);
- t1 = newTemp(Ity_I32);
- t2 = newTemp(Ity_I32);
- t3 = newTemp(Ity_I32);
- assign(t0, IRExpr_ITE(binop(Iop_CmpLT64S,
- getIReg(rt),
- mkU64(0xffffffff80000000ULL)),
- mkU32(1),
- IRExpr_ITE(binop(Iop_CmpLT64S,
- getIReg(rt),
- mkU64(0x7FFFFFFFULL)),
- mkU32(0),mkU32(1))));
- assign(t1, IRExpr_ITE(binop(Iop_CmpLT64S,
- getIReg(rs),
- mkU64(0xffffffff80000000ULL)),
- mkU32(1),
- IRExpr_ITE(binop(Iop_CmpLT64S,
- getIReg(rs),
- mkU64(0x7FFFFFFFULL)),
- mkU32(0), mkU32(1))));
- assign(t2, IRExpr_ITE(binop(Iop_CmpLT64S,
- binop(Iop_Add64,
- getIReg(rt), getIReg(rs)),
- mkU64(0xffffffff80000000ULL)),
- mkU32(1),
- IRExpr_ITE(binop(Iop_CmpLT64S,
- binop(Iop_Add64,
- getIReg(rt),
- getIReg(rs)),
- mkU64(0x7FFFFFFFULL)),
- mkU32(0), mkU32(1))));
- assign(t3, binop(Iop_Add32,
- mkexpr(t0),
- binop(Iop_Add32, mkexpr(t1), mkexpr(t2))));
- dis_branch_compact(False,
- binop(Iop_CmpNE32, mkexpr(t3), mkU32(0)),
- imm, &dres);
- } else {
- IRTemp tmpRs32 = newTemp(Ity_I32);
- IRTemp tmpRt32 = newTemp(Ity_I32);
- assign(tmpRs32, getIReg(rs));
- assign(tmpRt32, getIReg(rt));
+ /* Set result defaults. */
+ dres.whatNext = Dis_Continue;
+ dres.len = 0;
+ dres.continueAt = 0;
+ dres.jk_StopHere = Ijk_INVALID;
+ dres.hint = Dis_HintNone;
- t0 = newTemp(Ity_I32);
- t1 = newTemp(Ity_I32);
- t2 = newTemp(Ity_I32);
- t3 = newTemp(Ity_I32);
- t4 = newTemp(Ity_I32);
- /* dst = src0 + src1
- if (sign(src0 ) != sign(src1 ))
- goto no overflow;
- if (sign(dst) == sign(src0 ))
- goto no overflow;
- we have overflow! */
+ delay_slot_branch = likely_delay_slot = delay_slot_jump = False;
- assign(t0, binop(Iop_Add32, mkexpr(tmpRs32), mkexpr(tmpRt32)));
- assign(t1, binop(Iop_Xor32, mkexpr(tmpRs32), mkexpr(tmpRt32)));
- assign(t2, unop(Iop_1Uto32,
- binop(Iop_CmpEQ32,
- binop(Iop_And32, mkexpr(t1), mkU32(0x80000000)),
- mkU32(0x80000000))));
-
- assign(t3, binop(Iop_Xor32, mkexpr(t0), mkexpr(tmpRs32)));
- assign(t4, unop(Iop_1Uto32,
- binop(Iop_CmpNE32,
- binop(Iop_And32, mkexpr(t3), mkU32(0x80000000)),
- mkU32(0x80000000))));
-
- dis_branch_compact(False, binop(Iop_CmpEQ32,
- binop(Iop_Or32, mkexpr(t2), mkexpr(t4)),
- mkU32(0)), imm, &dres);
+ const UChar *code = guest_code + delta;
+ cins = getUInt(code);
+ opcode = get_opcode(cins);
+ DIP("\t0x%llx:\t0x%08x\t", (Addr64)guest_PC_curr_instr, cins);
+
+ if (delta != 0) {
+ if (branch_or_jump(guest_code + delta - 4)) {
+ if (lastn == NULL && bstmt == NULL) {
+ vassert(0);
+ } else {
+ dres.whatNext = Dis_StopHere;
+
+ if (lastn != NULL) {
+ delay_slot_jump = True;
+ } else if (bstmt != NULL) {
+ delay_slot_branch = True;
+ }
}
}
- break;
- /* In documentation for BEQC stands rs > rt and for BOVC stands rs >= rt! */
+
+ if (branch_or_link_likely(guest_code + delta - 4)) {
+ likely_delay_slot = True;
+ }
}
-#endif
- case 0x09: /* ADDIU */
- DIP("addiu r%u, r%u, %u", rt, rs, imm);
- if (mode64) {
- putIReg(rt, mkWidenFrom32(ty, binop(Iop_Add32,
- mkNarrowTo32(ty, getIReg(rs)),mkU32(extend_s_16to32(imm))),
- True));
- } else
- putIReg(rt, binop(Iop_Add32, getIReg(rs),mkU32(extend_s_16to32(imm))));
- break;
- case 0x0C: /* ANDI */
- DIP("andi r%u, r%u, %u", rt, rs, imm);
- if (mode64) {
- ALUI_PATTERN64(Iop_And64);
- } else {
- ALUI_PATTERN(Iop_And32);
- }
- break;
-
- case 0x0E: /* XORI */
- DIP("xori r%u, r%u, %u", rt, rs, imm);
- if (mode64) {
- ALUI_PATTERN64(Iop_Xor64);
- } else {
- ALUI_PATTERN(Iop_Xor32);
- }
- break;
-
- case 0x0D: /* ORI */
- DIP("ori r%u, r%u, %u", rt, rs, imm);
- if (mode64) {
- ALUI_PATTERN64(Iop_Or64);
- } else {
- ALUI_PATTERN(Iop_Or32);
- }
- break;
-
- case 0x0A: /* SLTI */
- DIP("slti r%u, r%u, %u", rt, rs, imm);
- if (mode64)
- putIReg(rt, unop(Iop_1Uto64, binop(Iop_CmpLT64S, getIReg(rs),
- mkU64(extend_s_16to64(imm)))));
- else
- putIReg(rt, unop(Iop_1Uto32, binop(Iop_CmpLT32S, getIReg(rs),
- mkU32(extend_s_16to32(imm)))));
- break;
+ /* Spot "Special" instructions (see comment at top of file). */
+ {
+ /* Spot the 16-byte preamble:
+ ****mips32****
+ "srl $0, $0, 13
+ "srl $0, $0, 29
+ "srl $0, $0, 3
+ "srl $0, $0, 19
- case 0x0B: /* SLTIU */
- DIP("sltiu r%u, r%u, %u", rt, rs, imm);
- if (mode64)
- putIReg(rt, unop(Iop_1Uto64, binop(Iop_CmpLT64U, getIReg(rs),
- mkU64(extend_s_16to64(imm)))));
- else
- putIReg(rt, unop(Iop_1Uto32, binop(Iop_CmpLT32U, getIReg(rs),
- mkU32(extend_s_16to32(imm)))));
- break;
+ ****mips64****
+ dsll $0, $0, 3
+ dsll $0, $0, 13
+ dsll $0, $0, 29
+ dsll $0, $0, 19 */
-#if defined(__mips__) && ((defined(__mips_isa_rev) && __mips_isa_rev < 6))
- case 0x18: { /* Doubleword Add Immidiate - DADDI; MIPS64 */
- DIP("daddi r%u, r%u, %u", rt, rs, imm);
- IRTemp tmpRs64 = newTemp(Ity_I64);
- assign(tmpRs64, getIReg(rs));
+ UInt word1 = mode64 ? 0xF8 : 0x342;
+ UInt word2 = mode64 ? 0x378 : 0x742;
+ UInt word3 = mode64 ? 0x778 : 0xC2;
+ UInt word4 = mode64 ? 0x4F8 : 0x4C2;
- t0 = newTemp(Ity_I64);
- t1 = newTemp(Ity_I64);
- t2 = newTemp(Ity_I64);
- t3 = newTemp(Ity_I64);
- t4 = newTemp(Ity_I64);
- /* dst = src0 + sign(imm)
- if(sign(src0 ) != sign(imm ))
- goto no overflow;
- if(sign(dst) == sign(src0 ))
- goto no overflow;
- we have overflow! */
+ if (getUInt(code + 0) == word1 && getUInt(code + 4) == word2 &&
+ getUInt(code + 8) == word3 && getUInt(code + 12) == word4) {
+ /* Got a "Special" instruction preamble. Which one is it? */
+ if (getUInt(code + 16) == 0x01ad6825 /* or $13, $13, $13 */ ) {
+ /* $11 = client_request ( $12 ) */
+ DIP("$11 = client_request ( $12 )");
- assign(t0, binop(Iop_Add64, mkexpr(tmpRs64),
- mkU64(extend_s_16to64(imm))));
- assign(t1, binop(Iop_Xor64, mkexpr(tmpRs64),
- mkU64(extend_s_16to64(imm))));
- assign(t2, unop(Iop_1Sto64, binop(Iop_CmpEQ64, binop(Iop_And64,
- mkexpr(t1), mkU64(0x8000000000000000ULL)),
- mkU64(0x8000000000000000ULL))));
-
- assign(t3, binop(Iop_Xor64, mkexpr(t0), mkexpr(tmpRs64)));
- assign(t4, unop(Iop_1Sto64, binop(Iop_CmpNE64, binop(Iop_And64,
- mkexpr(t3), mkU64(0x8000000000000000ULL)),
- mkU64(0x8000000000000000ULL))));
-
- stmt(IRStmt_Exit(binop(Iop_CmpEQ64, binop(Iop_Or64, mkexpr(t2),
- mkexpr(t4)), mkU64(0)), Ijk_SigFPE_IntOvf,
- IRConst_U64(guest_PC_curr_instr + 4),
- OFFB_PC));
+ if (mode64)
+ putPC(mkU64(guest_PC_curr_instr + 20));
+ else
+ putPC(mkU32(guest_PC_curr_instr + 20));
- putIReg(rt, mkexpr(t0));
- break;
- }
-#elif defined(__mips__) && ((defined(__mips_isa_rev) && __mips_isa_rev >= 6))
- case 0x18: { /* BNEZALC, BNEC, BNVC */
- if (rs == 0) { /* BNEZALC */
- DIP("bnezalc r%u, %u", rt, imm);
- if (mode64) {
- dis_branch_compact(True,
- unop(Iop_Not1,
- binop(Iop_CmpEQ64, getIReg(rt), mkU64(0x0))),
- imm, &dres);
- } else {
- dis_branch_compact(True,
- unop(Iop_Not1,
- binop(Iop_CmpEQ32, getIReg(rt), mkU32(0x0))),
- imm, &dres);
- }
- } else if (rs < rt) { /* BNEC */
- DIP("bnec r%u, %u", rt, imm);
- if (mode64) {
- dis_branch_compact(False,
- unop(Iop_Not1,
- binop(Iop_CmpEQ64,
- getIReg(rt), getIReg(rs))),
- imm, &dres);
- } else {
- dis_branch_compact(False,
- unop(Iop_Not1,
- binop(Iop_CmpEQ32,
- getIReg(rt), getIReg(rs))),
- imm, &dres);
- }
- } else { /* BNVC */
- DIP("bnvc r%u, r%u, %u", rs, rt, imm);
- if (mode64) {
- t0 = newTemp(Ity_I32);
- t1 = newTemp(Ity_I32);
- t2 = newTemp(Ity_I32);
- t3 = newTemp(Ity_I32);
- assign(t0, IRExpr_ITE(binop(Iop_CmpLT64S,
- getIReg(rt),
- mkU64(0xffffffff80000000ULL)),
- mkU32(1),
- IRExpr_ITE(binop(Iop_CmpLT64S,
- getIReg(rt),
- mkU64(0x7FFFFFFFULL)),
- mkU32(0),mkU32(1))));
- assign(t1, IRExpr_ITE(binop(Iop_CmpLT64S,
- getIReg(rs),
- mkU64(0xffffffff80000000ULL)),
- mkU32(1),
- IRExpr_ITE(binop(Iop_CmpLT64S,
- getIReg(rs),
- mkU64(0x7FFFFFFFULL)),
- mkU32(0),mkU32(1))));
- assign(t2, IRExpr_ITE(binop(Iop_CmpLT64S,
- binop(Iop_Add64,
- getIReg(rt), getIReg(rs)),
- mkU64(0xffffffff80000000ULL)),
- mkU32(1),
- IRExpr_ITE(binop(Iop_CmpLT64S,
- binop(Iop_Add64,
- getIReg(rt),
- getIReg(rs)),
- mkU64(0x7FFFFFFFULL)),
- mkU32(0),mkU32(1))));
- assign(t3, binop(Iop_Add32,
- mkexpr(t0),
- binop(Iop_Add32, mkexpr(t1), mkexpr(t2))));
- dis_branch_compact(False,
- binop(Iop_CmpEQ32, mkexpr(t3), mkU32(0)),
- imm, &dres);
- } else {
- IRTemp tmpRs32 = newTemp(Ity_I32);
- IRTemp tmpRt32 = newTemp(Ity_I32);
+ dres.jk_StopHere = Ijk_ClientReq;
+ dres.whatNext = Dis_StopHere;
- assign(tmpRs32, getIReg(rs));
- assign(tmpRt32, getIReg(rt));
- t0 = newTemp(Ity_I32);
- t1 = newTemp(Ity_I32);
- t2 = newTemp(Ity_I32);
- t3 = newTemp(Ity_I32);
- t4 = newTemp(Ity_I32);
- /* dst = src0 + src1
- if (sign(src0 ) != sign(src1 ))
- goto no overflow;
- if (sign(dst) == sign(src0 ))
- goto no overflow;
- we have overflow! */
+ goto decode_success;
+ } else if (getUInt(code + 16) == 0x01ce7025 /* or $14, $14, $14 */ ) {
+ /* $11 = guest_NRADDR */
+ DIP("$11 = guest_NRADDR");
+ dres.len = 20;
+ delta += 20;
- assign(t0, binop(Iop_Add32, mkexpr(tmpRs32), mkexpr(tmpRt32)));
- assign(t1, binop(Iop_Xor32, mkexpr(tmpRs32), mkexpr(tmpRt32)));
- assign(t2, unop(Iop_1Uto32,
- binop(Iop_CmpEQ32,
- binop(Iop_And32, mkexpr(t1), mkU32(0x80000000)),
- mkU32(0x80000000))));
-
- assign(t3, binop(Iop_Xor32, mkexpr(t0), mkexpr(tmpRs32)));
- assign(t4, unop(Iop_1Uto32,
- binop(Iop_CmpNE32,
- binop(Iop_And32, mkexpr(t3), mkU32(0x80000000)),
- mkU32(0x80000000))));
-
- dis_branch_compact(False, binop(Iop_CmpNE32 ,
- binop(Iop_Or32, mkexpr(t2), mkexpr(t4)),
- mkU32(0)), imm, &dres);
- }
- }
- break;
- }
-#endif
+ if (mode64)
+ putIReg(11, IRExpr_Get(offsetof(VexGuestMIPS64State,
+ guest_NRADDR), Ity_I64));
+ else
+ putIReg(11, IRExpr_Get(offsetof(VexGuestMIPS32State,
+ guest_NRADDR), Ity_I32));
+
+ goto decode_success;
+ } else if (getUInt(code + 16) == 0x01ef7825 /* or $15, $15, $15 */ ) {
+ /* branch-and-link-to-noredir $25 */
+ DIP("branch-and-link-to-noredir $25");
- case 0x19: /* Doubleword Add Immidiate Unsigned - DADDIU; MIPS64 */
- DIP("daddiu r%u, r%u, %u", rt, rs, imm);
- putIReg(rt, binop(Iop_Add64, getIReg(rs), mkU64(extend_s_16to64(imm))));
- break;
+ if (mode64)
+ putIReg(31, mkU64(guest_PC_curr_instr + 20));
+ else
+ putIReg(31, mkU32(guest_PC_curr_instr + 20));
- case 0x1A: {
- /* Load Doubleword Left - LDL; MIPS64 */
- vassert(mode64);
- DIP("ldl r%u, %u(r%u)", rt, imm, rs);
- /* t1 = addr */
+ putPC(getIReg(25));
+ dres.jk_StopHere = Ijk_NoRedir;
+ dres.whatNext = Dis_StopHere;
+ goto decode_success;
+ } else if (getUInt(code + 16) == 0x016b5825 /* or $11,$11,$11 */ ) {
+ /* IR injection */
+ DIP("IR injection");
#if defined (_MIPSEL)
- t1 = newTemp(Ity_I64);
- assign(t1, binop(Iop_Add64, getIReg(rs), mkU64(extend_s_16to64(imm))));
+ vex_inject_ir(irsb, Iend_LE);
#elif defined (_MIPSEB)
- t1 = newTemp(Ity_I64);
- assign(t1, binop(Iop_Xor64, mkU64(0x7), binop(Iop_Add64, getIReg(rs),
- mkU64(extend_s_16to64(imm)))));
+ vex_inject_ir(irsb, Iend_BE);
#endif
- /* t2 = word addr */
- /* t4 = addr mod 8 */
- LWX_SWX_PATTERN64_1;
- /* t3 = word content - shifted */
- t3 = newTemp(Ity_I64);
- assign(t3, binop(Iop_Shl64, load(Ity_I64, mkexpr(t2)),
- narrowTo(Ity_I8, binop(Iop_Shl64, binop(Iop_Sub64, mkU64(0x07),
- mkexpr(t4)), mkU8(3)))));
-
- /* rt content - adjusted */
- t5 = newTemp(Ity_I64);
- t6 = newTemp(Ity_I64);
- t7 = newTemp(Ity_I64);
+ if (mode64) {
+ stmt(IRStmt_Put(offsetof(VexGuestMIPS64State, guest_CMSTART),
+ mkU64(guest_PC_curr_instr)));
+ stmt(IRStmt_Put(offsetof(VexGuestMIPS64State, guest_CMLEN),
+ mkU64(20)));
- assign(t5, binop(Iop_Mul64, mkexpr(t4), mkU64(0x8)));
+ putPC(mkU64(guest_PC_curr_instr + 20));
+ } else {
+ stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_CMSTART),
+ mkU32(guest_PC_curr_instr)));
+ stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_CMLEN),
+ mkU32(20)));
- assign(t6, binop(Iop_Shr64, mkU64(0x00FFFFFFFFFFFFFFULL),
- narrowTo(Ity_I8, mkexpr(t5))));
+ putPC(mkU32(guest_PC_curr_instr + 20));
+ }
- assign(t7, binop(Iop_And64, getIReg(rt), mkexpr(t6)));
+ dres.whatNext = Dis_StopHere;
+ dres.jk_StopHere = Ijk_InvalICache;
+ dres.len = 20;
+ delta += 20;
+ goto decode_success;
+ }
- putIReg(rt, binop(Iop_Or64, mkexpr(t7), mkexpr(t3)));
- break;
+ /* We don't know what it is. Set opc1/opc2 so decode_failure
+ can print the insn following the Special-insn preamble. */
+ delta += 16;
+ goto decode_failure;
+ /*NOTREACHED*/
+ }
}
- case 0x1B: {
- /* Load Doubleword Right - LDR; MIPS64 */
- vassert(mode64);
- DIP("ldr r%u,%u(r%u)", rt, imm, rs);
- /* t1 = addr */
-#if defined (_MIPSEL)
- t1 = newTemp(Ity_I64);
- assign(t1, binop(Iop_Add64, getIReg(rs), mkU64(extend_s_16to64(imm))));
-#elif defined (_MIPSEB)
- t1 = newTemp(Ity_I64);
- assign(t1, binop(Iop_Xor64, mkU64(0x7), binop(Iop_Add64, getIReg(rs),
- mkU64(extend_s_16to64(imm)))));
-#endif
- /* t2 = word addr */
- /* t4 = addr mod 8 */
- LWX_SWX_PATTERN64_1;
-
- /* t3 = word content - shifted */
- t3 = newTemp(Ity_I64);
- assign(t3, binop(Iop_Shr64, load(Ity_I64, mkexpr(t2)),
- narrowTo(Ity_I8, binop(Iop_Shl64, mkexpr(t4), mkU8(3)))));
-
- /* rt content - adjusted */
- t5 = newTemp(Ity_I64);
- assign(t5, binop(Iop_And64, getIReg(rt), unop(Iop_Not64,
- binop(Iop_Shr64, mkU64(0xFFFFFFFFFFFFFFFFULL),
- narrowTo(Ity_I8, binop(Iop_Shl64, mkexpr(t4), mkU8(0x3)))))));
-
- putIReg(rt, binop(Iop_Or64, mkexpr(t5), mkexpr(t3)));
- break;
- }
+ switch (opcode & 0x30) {
+ case 0x00:
+ result = disInstr_MIPS_WRK_00(cins, archinfo, abiinfo, &dres, &bstmt, &lastn,
+ resteerOkFn, callback_opaque);
- case 0x27: /* Load Word unsigned - LWU; MIPS64 */
- DIP("lwu r%u,%u(r%u)", rt, imm, rs);
- LOAD_STORE_PATTERN;
+ if (result == -1) goto decode_failure;
- putIReg(rt, mkWidenFrom32(ty, load(Ity_I32, mkexpr(t1)), False));
- break;
+ if (result == -2) goto decode_failure_dsp;
- case 0x30: /* LL */
- DIP("ll r%u, %u(r%u)", rt, imm, rs);
- LOAD_STORE_PATTERN;
- if (abiinfo->guest__use_fallback_LLSC) {
- t2 = newTemp(ty);
- assign(t2, mkWidenFrom32(ty, load(Ity_I32, mkexpr(t1)), True));
- putLLaddr(mkexpr(t1));
- putLLdata(mkexpr(t2));
- putIReg(rt, mkexpr(t2));
- } else {
- t2 = newTemp(Ity_I32);
- stmt(IRStmt_LLSC(MIPS_IEND, t2, mkexpr(t1), NULL));
- putIReg(rt, mkWidenFrom32(ty, mkexpr(t2), True));
- }
- break;
+ break;
- case 0x34: /* Load Linked Doubleword - LLD; MIPS64 */
- DIP("lld r%u, %u(r%u)", rt, imm, rs);
- if (mode64) {
- LOAD_STORE_PATTERN;
- t2 = newTemp(Ity_I64);
- if (abiinfo->guest__use_fallback_LLSC) {
- assign(t2, load(Ity_I64, mkexpr(t1)));
- putLLaddr(mkexpr(t1));
- putLLdata(mkexpr(t2));
- } else {
- stmt(IRStmt_LLSC(MIPS_IEND, t2, mkexpr(t1), NULL));
- }
- putIReg(rt, mkexpr(t2));
- } else {
- ILLEGAL_INSTRUCTON;
- }
- break;
+ case 0x10:
- case 0x38: /* SC */
- DIP("sc r%u, %u(r%u)", rt, imm, rs);
- t2 = newTemp(Ity_I1);
- LOAD_STORE_PATTERN;
- if (abiinfo->guest__use_fallback_LLSC) {
- t3 = newTemp(Ity_I32);
- assign(t2, binop(mode64 ? Iop_CmpNE64 : Iop_CmpNE32,
- mkexpr(t1), getLLaddr()));
- assign(t3, mkNarrowTo32(ty, getIReg(rt)));
- putLLaddr(LLADDR_INVALID);
- putIReg(rt, getIReg(0));
+ result = disInstr_MIPS_WRK_10(cins, archinfo, abiinfo, &dres, &bstmt, &lastn,
+ resteerOkFn, callback_opaque);
- mips_next_insn_if(mkexpr(t2));
+ if (result == -1) goto decode_failure;
- t4 = newTemp(Ity_I32);
- t5 = newTemp(Ity_I32);
+ if (result == -2) goto decode_failure_dsp;
- assign(t5, mkNarrowTo32(ty, getLLdata()));
+ break;
- stmt(IRStmt_CAS(mkIRCAS(IRTemp_INVALID, t4, /* old_mem */
- MIPS_IEND, mkexpr(t1), /* addr */
- NULL, mkexpr(t5), /* expected value */
- NULL, mkexpr(t3) /* new value */)));
+ case 0x20:
+ result = disInstr_MIPS_WRK_20(cins);
- putIReg(rt, unop(mode64 ? Iop_1Uto64 : Iop_1Uto32,
- binop(Iop_CmpEQ32, mkexpr(t4), mkexpr(t5))));
- } else {
- stmt(IRStmt_LLSC(MIPS_IEND, t2, mkexpr(t1),
- mkNarrowTo32(ty, getIReg(rt))));
- putIReg(rt, unop(mode64 ? Iop_1Uto64 : Iop_1Uto32, mkexpr(t2)));
- }
- break;
+ if (result == -1) goto decode_failure;
- case 0x3C: /* Store Conditional Doubleword - SCD; MIPS64 */
- DIP("scd r%u, %u(r%u)", rt, imm, rs);
- if (mode64) {
- t2 = newTemp(Ity_I1);
- LOAD_STORE_PATTERN;
- if (abiinfo->guest__use_fallback_LLSC) {
- t3 = newTemp(Ity_I64);
- assign(t2, binop(Iop_CmpNE64, mkexpr(t1), getLLaddr()));
- assign(t3, getIReg(rt));
- putLLaddr(LLADDR_INVALID);
- putIReg(rt, getIReg(0));
+ if (result == -2) goto decode_failure_dsp;
- mips_next_insn_if(mkexpr(t2));
+ break;
- t4 = newTemp(Ity_I64);
- t5 = newTemp(Ity_I64);
+ case 0x30:
+ result = disInstr_MIPS_WRK_30(cins, archinfo, abiinfo, &dres, &bstmt);
- assign(t5, getLLdata());
+ if (result == -1) goto decode_failure;
- stmt(IRStmt_CAS(mkIRCAS(IRTemp_INVALID, t4, /* old_mem */
- MIPS_IEND, mkexpr(t1), /* addr */
- NULL, mkexpr(t5), /* expected value */
- NULL, mkexpr(t3) /* new value */)));
+ if (result == -2) goto decode_failure_dsp;
- putIReg(rt, unop(Iop_1Uto64,
- binop(Iop_CmpEQ64, mkexpr(t4), mkexpr(t5))));
- } else {
- stmt(IRStmt_LLSC(MIPS_IEND, t2, mkexpr(t1), getIReg(rt)));
- putIReg(rt, unop(Iop_1Uto64, mkexpr(t2)));
- }
- } else {
- ILLEGAL_INSTRUCTON;
- }
- break;
-
- case 0x37: /* Load Doubleword - LD; MIPS64 */
- DIP("ld r%u, %u(r%u)", rt, imm, rs);
- LOAD_STORE_PATTERN;
- putIReg(rt, load(Ity_I64, mkexpr(t1)));
- break;
-
- case 0x3F: /* Store Doubleword - SD; MIPS64 */
- DIP("sd r%u, %u(r%u)", rt, imm, rs);
- LOAD_STORE_PATTERN;
- store(mkexpr(t1), getIReg(rt));
- break;
-
- case 0x32: /* Branch on Bit Clear - BBIT0; Cavium OCTEON */
- /* Cavium Specific instructions. */
- if (VEX_MIPS_COMP_ID(archinfo->hwcaps) == VEX_PRID_COMP_CAVIUM) {
- DIP("bbit0 r%u, 0x%x, %x", rs, rt, imm);
- t0 = newTemp(Ity_I32);
- t1 = newTemp(Ity_I32);
- assign(t0, mkU32(0x1));
- assign(t1, binop(Iop_Shl32, mkexpr(t0), mkU8(rt)));
- dis_branch(False, binop(Iop_CmpEQ32,
- binop(Iop_And32,
- mkexpr(t1),
- mkNarrowTo32(ty, getIReg(rs))),
- mkU32(0x0)),
- imm, &bstmt);
- } else if (archinfo->hwcaps & VEX_MIPS_CPU_ISA_M32R6) { /* BC */
- if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
- DIP("bc %x", instr_index & 0x3FFFFFF);
- if (mode64) {
- t0 = newTemp(Ity_I64);
- assign(t0, mkU64(guest_PC_curr_instr +
- ((extend_s_26to64(instr_index & 0x3FFFFFF) + 1 ) << 2)));
- } else {
- t0 = newTemp(Ity_I32);
- assign(t0, mkU32(guest_PC_curr_instr +
- ((extend_s_26to32(instr_index & 0x3FFFFFF) + 1) << 2)));
- }
- putPC(mkexpr(t0));
- dres.whatNext = Dis_StopHere;
- dres.jk_StopHere = Ijk_Boring;
- } else {
- ILLEGAL_INSTRUCTON;
- }
- } else {
- goto decode_failure;
- }
- break;
- case 0x36: /* Branch on Bit Clear Plus 32 - BBIT032; Cavium OCTEON */
- /* Cavium Specific instructions. */
- if (VEX_MIPS_COMP_ID(archinfo->hwcaps) == VEX_PRID_COMP_CAVIUM) {
- DIP("bbit032 r%u, 0x%x, %x", rs, rt, imm);
- t0 = newTemp(Ity_I64);
- t1 = newTemp(Ity_I8); /* Shift. */
- t2 = newTemp(Ity_I64);
- assign(t0, mkU64(0x1));
- assign(t1, binop(Iop_Add8, mkU8(rt), mkU8(32)));
- assign(t2, binop(Iop_Shl64, mkexpr(t0), mkexpr(t1)));
- dis_branch(False, binop(Iop_CmpEQ64,
- binop(Iop_And64,
- mkexpr(t2),
- getIReg(rs)),
- mkU64(0x0)),
- imm, &bstmt);
- } else if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
- if (rs == 0) { /* JIC */
- DIP("jic r%u, %u", rt, instr_index & 0xFFFF);
- if (mode64) {
- t0 = newTemp(Ity_I64);
- assign(t0, binop(Iop_Add64, getIReg(rt),
- mkU64(extend_s_16to64((instr_index & 0xFFFF)))));
- } else {
- t0 = newTemp(Ity_I32);
- assign(t0, binop(Iop_Add32, getIReg(rt),
- mkU32(extend_s_16to32((instr_index & 0xFFFF)))));
- }
- putPC(mkexpr(t0));
- dres.whatNext = Dis_StopHere;
- dres.jk_StopHere = Ijk_Boring;
- } else { /* BEQZC */
- DIP("beqzc r%u, %u", rs, imm);
- dres.jk_StopHere = Ijk_Boring;
- dres.whatNext = Dis_StopHere;
- ULong branch_offset;
- t0 = newTemp(Ity_I1);
- if (mode64) {
- branch_offset = extend_s_23to64((instr_index& 0x1fffff) << 2);
- assign(t0, binop(Iop_CmpEQ64, getIReg(rs), mkU64(0x0)));
- stmt(IRStmt_Exit(mkexpr(t0), Ijk_Boring,
- IRConst_U64(guest_PC_curr_instr + 4 + branch_offset),
- OFFB_PC));
- putPC(mkU64(guest_PC_curr_instr + 4));
- } else {
- branch_offset = extend_s_23to32((instr_index& 0x1fffff) << 2);
- assign(t0, binop(Iop_CmpEQ32, getIReg(rs), mkU32(0x0)));
- stmt(IRStmt_Exit(mkexpr(t0), Ijk_Boring,
- IRConst_U32(guest_PC_curr_instr + 4 +
- (UInt) branch_offset), OFFB_PC));
- putPC(mkU32(guest_PC_curr_instr + 4));
- }
- }
- } else {
- ILLEGAL_INSTRUCTON;
- }
- break;
- case 0x3A: /* Branch on Bit Set - BBIT1; Cavium OCTEON */
- /* Cavium Specific instructions. */
- if (VEX_MIPS_COMP_ID(archinfo->hwcaps) == VEX_PRID_COMP_CAVIUM) {
- DIP("bbit1 r%u, 0x%x, %x", rs, rt, imm);
- t0 = newTemp(Ity_I32);
- t1 = newTemp(Ity_I32);
- assign(t0, mkU32(0x1));
- assign(t1, binop(Iop_Shl32, mkexpr(t0), mkU8(rt)));
- dis_branch(False, binop(Iop_CmpNE32,
- binop(Iop_And32,
- mkexpr(t1),
- mkNarrowTo32(ty, getIReg(rs))),
- mkU32(0x0)),
- imm, &bstmt);
- } else if (archinfo->hwcaps & VEX_MIPS_CPU_ISA_M32R6) {/* BALC */
- if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
- DIP("balc %x", instr_index & 0x3FFFFFF);
- if (mode64) {
- t0 = newTemp(Ity_I64);
- assign(t0, mkU64(guest_PC_curr_instr + ((extend_s_26to64(instr_index & 0x3FFFFFF)+1)<<2)));
- putIReg(31, mkU64(guest_PC_curr_instr + 4));
- } else {
- t0 = newTemp(Ity_I32);
- assign(t0, mkU32(guest_PC_curr_instr+((extend_s_26to32(instr_index & 0x3FFFFFF)+1)<<2)));
- putIReg(31, mkU32(guest_PC_curr_instr + 4));
- }
- putPC(mkexpr(t0));
- dres.whatNext = Dis_StopHere;
- dres.jk_StopHere = Ijk_Call;
+ break;
+
+decode_failure_dsp:
+ vex_printf("Error occured while trying to decode MIPS32 DSP "
+ "instruction.\nYour platform probably doesn't support "
+ "MIPS32 DSP ASE.\n");
+decode_failure:
+
+ /* All decode failures end up here. */
+ if (sigill_diag)
+ vex_printf("vex mips->IR: unhandled instruction bytes: "
+ "0x%x 0x%x 0x%x 0x%x\n",
+ (UInt) getIByte(delta_start + 0),
+ (UInt) getIByte(delta_start + 1),
+ (UInt) getIByte(delta_start + 2),
+ (UInt) getIByte(delta_start + 3));
+
+ /* Tell the dispatcher that this insn cannot be decoded, and so has
+ not been executed, and (is currently) the next to be executed.
+ EIP should be up-to-date since it made so at the start bnezof each
+ insn, but nevertheless be paranoid and update it again right
+ now. */
+ if (mode64) {
+ stmt(IRStmt_Put(offsetof(VexGuestMIPS64State, guest_PC),
+ mkU64(guest_PC_curr_instr)));
+ jmp_lit64(&dres, Ijk_NoDecode, guest_PC_curr_instr);
} else {
- ILLEGAL_INSTRUCTON;
- }
- } else {
- goto decode_failure;
- }
- break;
- case 0x3E: /* Branch on Bit Set Plus 32 - BBIT132; Cavium OCTEON */
- /* Cavium Specific instructions. */
- if (VEX_MIPS_COMP_ID(archinfo->hwcaps) == VEX_PRID_COMP_CAVIUM) {
- DIP("bbit132 r%u, 0x%x, %x", rs, rt, imm);
- t0 = newTemp(Ity_I64);
- t1 = newTemp(Ity_I8); /* Shift. */
- t2 = newTemp(Ity_I64);
- assign(t0, mkU64(0x1));
- assign(t1, binop(Iop_Add8, mkU8(rt), mkU8(32)));
- assign(t2, binop(Iop_Shl64, mkexpr(t0), mkexpr(t1)));
- dis_branch(False, binop(Iop_CmpNE64,
- binop(Iop_And64,
- mkexpr(t2),
- getIReg(rs)),
- mkU64(0x0)),
- imm, &bstmt);
- } else if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
- if (rs == 0) {/* JIALC */
- DIP("jialc r%u, %u", rt, instr_index & 0xFFFF);
- if (rs) goto decode_failure;
- if (mode64) {
- t0 = newTemp(Ity_I64);
- assign(t0, binop(Iop_Add64, getIReg(rt),
- mkU64(extend_s_16to64((instr_index & 0xFFFF)))));
- putIReg(31, mkU64(guest_PC_curr_instr + 4));
- } else {
- t0 = newTemp(Ity_I32);
- assign(t0, binop(Iop_Add32, getIReg(rt),
- mkU32(extend_s_16to32((instr_index & 0xFFFF)))));
- putIReg(31, mkU32(guest_PC_curr_instr + 4));
- }
- putPC(mkexpr(t0));
- dres.whatNext = Dis_StopHere;
- dres.jk_StopHere = Ijk_Call;
- } else { /* BNEZC */
- DIP("bnezc r%u, %u", rs, imm);
- dres.jk_StopHere = Ijk_Boring;
- dres.whatNext = Dis_StopHere;
- ULong branch_offset;
- t0 = newTemp(Ity_I1);
- if (mode64) {
- branch_offset = extend_s_23to64((instr_index& 0x1fffff) << 2);
- assign(t0, unop(Iop_Not1, binop(Iop_CmpEQ64, getIReg(rs), mkU64(0x0))));
- stmt(IRStmt_Exit(mkexpr(t0), Ijk_Boring,
- IRConst_U64(guest_PC_curr_instr + 4 + branch_offset),
- OFFB_PC));
- putPC(mkU64(guest_PC_curr_instr + 4));
- } else {
- branch_offset = extend_s_23to32((instr_index& 0x1fffff) << 2);
- assign(t0, unop(Iop_Not1, binop(Iop_CmpEQ32, getIReg(rs), mkU32(0x0))));
- stmt(IRStmt_Exit(mkexpr(t0), Ijk_Boring,
- IRConst_U32(guest_PC_curr_instr + 4 +
- (UInt) branch_offset), OFFB_PC));
- putPC(mkU32(guest_PC_curr_instr + 4));
- }
+ stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_PC),
+ mkU32(guest_PC_curr_instr)));
+ jmp_lit32(&dres, Ijk_NoDecode, guest_PC_curr_instr);
}
- } else {
- goto decode_failure;
- }
- break;
-
- case 0x1D: /* DAUI */
- if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) {
- DIP("daui r%u, r%u, %x", rt, rs, imm);
- putIReg(rt, binop(Iop_Add64, getIReg(rs), mkU64(extend_s_32to64(imm << 16))));
- } else {
- ILLEGAL_INSTRUCTON;
- }
- break;
- case 0x1E: /* MIPS MSA (SIMD) */
- if (has_msa) {
- Int retVal = disMSAInstr_MIPS_WRK(cins);
- if (retVal == 0) {
- break;
- } else if (retVal == -2) {
- ILLEGAL_INSTRUCTON
- break;
- }
- }
- vex_printf("Error occured while trying to decode MIPS MSA "
- "instruction.\nYour platform probably doesn't support "
- "MIPS MSA (SIMD) ASE.\n");
-
- default:
- goto decode_failure;
-
- decode_failure_dsp:
- vex_printf("Error occured while trying to decode MIPS32 DSP "
- "instruction.\nYour platform probably doesn't support "
- "MIPS32 DSP ASE.\n");
- decode_failure:
- /* All decode failures end up here. */
- if (sigill_diag)
- vex_printf("vex mips->IR: unhandled instruction bytes: "
- "0x%x 0x%x 0x%x 0x%x\n",
- (UInt) getIByte(delta_start + 0),
- (UInt) getIByte(delta_start + 1),
- (UInt) getIByte(delta_start + 2),
- (UInt) getIByte(delta_start + 3));
-
- /* Tell the dispatcher that this insn cannot be decoded, and so has
- not been executed, and (is currently) the next to be executed.
- EIP should be up-to-date since it made so at the start bnezof each
- insn, but nevertheless be paranoid and update it again right
- now. */
- if (mode64) {
- stmt(IRStmt_Put(offsetof(VexGuestMIPS64State, guest_PC),
- mkU64(guest_PC_curr_instr)));
- jmp_lit64(&dres, Ijk_NoDecode, guest_PC_curr_instr);
- } else {
- stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_PC),
- mkU32(guest_PC_curr_instr)));
- jmp_lit32(&dres, Ijk_NoDecode, guest_PC_curr_instr);
- }
- dres.whatNext = Dis_StopHere;
- dres.len = 0;
- return dres;
+ dres.whatNext = Dis_StopHere;
+ dres.len = 0;
+ return dres;
} /* switch (opc) for the main (primary) opcode switch. */
/* All MIPS insn have 4 bytes */
delay_slot_branch = False;
stmt(bstmt);
bstmt = NULL;
+
if (mode64)
putPC(mkU64(guest_PC_curr_instr + 4));
else
putPC(mkU32(guest_PC_curr_instr + 4));
+
dres.jk_StopHere = is_Branch_or_Jump_and_Link(guest_code + delta - 4) ?
Ijk_Call : Ijk_Boring;
}
putPC(lastn);
lastn = NULL;
}
+
if (delay_slot_jump) {
putPC(lastn);
lastn = NULL;
Ijk_Call : Ijk_Boring;
}
- decode_success:
+decode_success:
+
/* All decode successes end up here. */
switch (dres.whatNext) {
case Dis_Continue:
putPC(mkU64(guest_PC_curr_instr + 4));
else
putPC(mkU32(guest_PC_curr_instr + 4));
+
break;
+
case Dis_ResteerU:
case Dis_ResteerC:
if (mode64)
putPC(mkU64(dres.continueAt));
else
putPC(mkU32(dres.continueAt));
+
break;
+
case Dis_StopHere:
break;
+
default:
vassert(0);
break;
/* On MIPS we need to check if the last instruction in block is branch or
jump. */
if (((vex_control.guest_max_insns - 1) == (delta + 4) / 4)
- && (dres.whatNext != Dis_StopHere))
+ && (dres.whatNext != Dis_StopHere))
if (branch_or_jump(guest_code + delta + 4)) {
dres.whatNext = Dis_StopHere;
dres.jk_StopHere = Ijk_Boring;