SSE2 integer operations (x86 guest/host).
git-svn-id: svn://svn.valgrind.org/vex/trunk@636
/* --- Clean helpers for MMX --- */
+extern ULong x86g_calculate_add64x1 ( ULong, ULong );
extern ULong x86g_calculate_add32x2 ( ULong, ULong );
extern ULong x86g_calculate_add16x4 ( ULong, ULong );
extern ULong x86g_calculate_add8x8 ( ULong, ULong );
/* ------------ Normal addition ------------ */
+ULong x86g_calculate_add64x1 ( ULong xx, ULong yy )
+{
+ /* uh, why, exactly, is this not done in-line??? */
+ return xx + yy;
+}
+
ULong x86g_calculate_add32x2 ( ULong xx, ULong yy )
{
return mk32x2(
case 0xE4: XXX(x86g_calculate_mull16uHIx4); break;
case 0xF6: XXX(x86g_calculate_psadbw); break;
+ /* Introduced in SSE2 */
+ case 0xD4: XXX(x86g_calculate_add64x1); break;
+
default:
vex_printf("\n0x%x\n", (Int)opc);
vpanic("dis_MMXop_regmem_to_reg");
return dis_SSE_E_to_G_all_wrk( sorb, delta, opname, op, True );
}
+
/* Lowest 32-bit lane only SSE binary operation, G = G `op` E. */
static UInt dis_SSE_E_to_G_lo32 ( UChar sorb, UInt delta,
}
}
+
/* Lower 64-bit lane only SSE binary operation, G = G `op` E. */
static UInt dis_SSE_E_to_G_lo64 ( UChar sorb, UInt delta,
}
}
+
/* All lanes unary SSE operation, G = op(E). */
static UInt dis_SSE_E_to_G_unary_all (
}
}
+
/* Lowest 32-bit lane only unary SSE operation, G = op(E). */
static UInt dis_SSE_E_to_G_unary_lo32 (
}
}
+
/* Lowest 64-bit lane only unary SSE operation, G = op(E). */
static UInt dis_SSE_E_to_G_unary_lo64 (
}
}
+
+/* SSE integer binary operation:
+ G = G `op` E (eLeft == False)
+ G = E `op` G (eLeft == True)
+*/
+static UInt dis_SSEint_E_to_G(
+ UChar sorb, UInt delta,
+ HChar* opname, IROp op,
+ Bool eLeft
+ )
+{
+ HChar dis_buf[50];
+ Int alen;
+ IRTemp addr;
+ UChar rm = getIByte(delta);
+ IRExpr* gpart = getXMMReg(gregOfRM(rm));
+ IRExpr* epart = NULL;
+ if (epartIsReg(rm)) {
+ epart = getXMMReg(eregOfRM(rm));
+ DIP("%s %s,%s\n", opname,
+ nameXMMReg(eregOfRM(rm)),
+ nameXMMReg(gregOfRM(rm)) );
+ delta += 1;
+ } else {
+ addr = disAMode ( &alen, sorb, delta, dis_buf );
+ epart = loadLE(Ity_V128, mkexpr(addr));
+ DIP("%s %s,%s\n", opname,
+ dis_buf,
+ nameXMMReg(gregOfRM(rm)) );
+ delta += alen;
+ }
+ putXMMReg( gregOfRM(rm),
+ eLeft ? binop(op, epart, gpart)
+ : binop(op, gpart, epart) );
+ return delta;
+}
+
+
/* Helper for doing SSE FP comparisons. */
static void findSSECmpOp ( Bool* needNot, IROp* op,
/* ***--- this is an MMX class insn introduced in SSE1 ---*** */
/* 0F E0 = PAVGB -- 8x8 unsigned Packed Average, with rounding */
- if (insn[0] == 0x0F && insn[1] == 0xE0) {
- vassert(sz == 4);
+ if (sz == 4 && insn[0] == 0x0F && insn[1] == 0xE0) {
do_MMX_preamble();
delta = dis_MMXop_regmem_to_reg (
sorb, delta+2, insn[1], "pavgb", False );
/* ***--- this is an MMX class insn introduced in SSE1 ---*** */
/* 0F E3 = PAVGW -- 16x4 unsigned Packed Average, with rounding */
- if (insn[0] == 0x0F && insn[1] == 0xE3) {
- vassert(sz == 4);
+ if (sz == 4 && insn[0] == 0x0F && insn[1] == 0xE3) {
do_MMX_preamble();
delta = dis_MMXop_regmem_to_reg (
sorb, delta+2, insn[1], "pavgw", False );
goto decode_success;
}
+ ///////////////////////////////////////////////////////////////////
+
+ /* 66 0F 6B = PACKSSDW */
+ if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x6B) {
+ delta = dis_SSEint_E_to_G( sorb, delta+2,
+ "packssdw", Iop_QNarrow32Sx4, True );
+ goto decode_success;
+ }
+
+ /* 66 0F 63 = PACKSSWB */
+ if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x63) {
+ delta = dis_SSEint_E_to_G( sorb, delta+2,
+ "packsswb", Iop_QNarrow16Sx8, True );
+ goto decode_success;
+ }
+
+ /* 66 0F 67 = PACKUSWB */
+ if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x67) {
+ delta = dis_SSEint_E_to_G( sorb, delta+2,
+ "packuswb", Iop_QNarrow16Ux8, True );
+ goto decode_success;
+ }
+
+ /* 66 0F FC = PADDB */
+ if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xFC) {
+ delta = dis_SSEint_E_to_G( sorb, delta+2,
+ "paddb", Iop_Add8x16, False );
+ goto decode_success;
+ }
+
+ /* 66 0F FE = PADDD */
+ if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xFE) {
+ delta = dis_SSEint_E_to_G( sorb, delta+2,
+ "paddd", Iop_Add32x4, False );
+ goto decode_success;
+ }
+
+ /* ***--- this is an MMX class insn introduced in SSE2 ---*** */
+ /* 0F D4 = PADDQ -- add 64x1 */
+ if (sz == 4 && insn[0] == 0x0F && insn[1] == 0xD4) {
+ do_MMX_preamble();
+ delta = dis_MMXop_regmem_to_reg (
+ sorb, delta+2, insn[1], "paddq", False );
+ goto decode_success;
+ }
+
+ /* 66 0F D4 = PADDQ */
+ if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xD4) {
+ delta = dis_SSEint_E_to_G( sorb, delta+2,
+ "paddq", Iop_Add64x2, False );
+ goto decode_success;
+ }
+
+ /* 66 0F FD = PADDW */
+ if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xFD) {
+ delta = dis_SSEint_E_to_G( sorb, delta+2,
+ "paddw", Iop_Add16x8, False );
+ goto decode_success;
+ }
+
+ /* 66 0F EC = PADDSB */
+ if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xEC) {
+ delta = dis_SSEint_E_to_G( sorb, delta+2,
+ "paddsb", Iop_QAdd8Sx16, False );
+ goto decode_success;
+ }
+
+ /* 66 0F ED = PADDSW */
+ if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xED) {
+ delta = dis_SSEint_E_to_G( sorb, delta+2,
+ "paddsw", Iop_QAdd16Sx8, False );
+ goto decode_success;
+ }
+
+ /* 66 0F DC = PADDUSB */
+ if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xDC) {
+ delta = dis_SSEint_E_to_G( sorb, delta+2,
+ "paddusb", Iop_QAdd8Ux16, False );
+ goto decode_success;
+ }
+
+ /* 66 0F DD = PADDUSW */
+ if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xDD) {
+ delta = dis_SSEint_E_to_G( sorb, delta+2,
+ "paddusw", Iop_QAdd16Ux8, False );
+ goto decode_success;
+ }
+
+ /* 66 0F DB = PAND */
+ if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xDB) {
+ delta = dis_SSE_E_to_G_all( sorb, delta+2, "pand", Iop_And128 );
+ goto decode_success;
+ }
+
+ /* 66 0F DF = PANDN */
+ if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xDF) {
+ delta = dis_SSE_E_to_G_all_invG( sorb, delta+2, "pandn", Iop_And128 );
+ goto decode_success;
+ }
+
+ /* 66 0F E0 = PAVGB */
+ if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xE0) {
+ delta = dis_SSEint_E_to_G( sorb, delta+2,
+ "pavgb", Iop_Avg8Ux16, False );
+ goto decode_success;
+ }
+
+ /* 66 0F E3 = PAVGW */
+ if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xE3) {
+ delta = dis_SSEint_E_to_G( sorb, delta+2,
+ "pavgw", Iop_Avg16Ux8, False );
+ goto decode_success;
+ }
+
+
//--
//-- /* FXSAVE/FXRSTOR m32 -- load/store the FPU/MMX/SSE state. */
//-- if (insn[0] == 0x0F && insn[1] == 0xAE
HChar* showX86SseOp ( X86SseOp op ) {
switch (op) {
- case Xsse_MOV: return "mov(?!)";
- case Xsse_AND: return "and";
- case Xsse_OR: return "or";
- case Xsse_XOR: return "xor";
- case Xsse_ANDN: return "andn";
- case Xsse_ADDF: return "add";
- case Xsse_SUBF: return "sub";
- case Xsse_MULF: return "mul";
- case Xsse_DIVF: return "div";
- case Xsse_MAXF: return "max";
- case Xsse_MINF: return "min";
- case Xsse_RCPF: return "rcp";
- case Xsse_RSQRTF: return "rsqrt";
- case Xsse_SQRTF: return "sqrt";
- case Xsse_CMPEQF: return "cmpFeq";
- case Xsse_CMPLTF: return "cmpFlt";
- case Xsse_CMPLEF: return "cmpFle";
- case Xsse_CMPUNF: return "cmpFun";
+ case Xsse_MOV: return "mov(?!)";
+ case Xsse_ADDF: return "add";
+ case Xsse_SUBF: return "sub";
+ case Xsse_MULF: return "mul";
+ case Xsse_DIVF: return "div";
+ case Xsse_MAXF: return "max";
+ case Xsse_MINF: return "min";
+ case Xsse_CMPEQF: return "cmpFeq";
+ case Xsse_CMPLTF: return "cmpFlt";
+ case Xsse_CMPLEF: return "cmpFle";
+ case Xsse_CMPUNF: return "cmpFun";
+ case Xsse_RCPF: return "rcp";
+ case Xsse_RSQRTF: return "rsqrt";
+ case Xsse_SQRTF: return "sqrt";
+ case Xsse_AND: return "and";
+ case Xsse_OR: return "or";
+ case Xsse_XOR: return "xor";
+ case Xsse_ANDN: return "andn";
+ case Xsse_ADD8: return "paddb";
+ case Xsse_ADD16: return "paddw";
+ case Xsse_ADD32: return "paddd";
+ case Xsse_ADD64: return "paddq";
+ case Xsse_QADD8U: return "paddusb";
+ case Xsse_QADD16U: return "paddusw";
+ case Xsse_QADD8S: return "paddsb";
+ case Xsse_QADD16S: return "paddsw";
+ case Xsse_SUB8: return "psubb";
+ case Xsse_SUB16: return "psubw";
+ case Xsse_SUB32: return "psubd";
+ case Xsse_SUB64: return "psubq";
+ case Xsse_QSUB8U: return "psubusb";
+ case Xsse_QSUB16U: return "psubusw";
+ case Xsse_QSUB8S: return "psubsb";
+ case Xsse_QSUB16S: return "psubsw";
+ case Xsse_MUL16: return "pmullw";
+ case Xsse_MULHI16U: return "pmulhuw";
+ case Xsse_MULHI16S: return "pmulhw";
+ case Xsse_AVG8U: return "pavgb";
+ case Xsse_AVG16U: return "pavgw";
+ case Xsse_MAX16S: return "pmaxw";
+ case Xsse_MAX8U: return "pmaxub";
+ case Xsse_MIN16S: return "pminw";
+ case Xsse_MIN8U: return "pminub";
+ case Xsse_CMPEQ8: return "pcmpeqb";
+ case Xsse_CMPEQ16: return "pcmpeqw";
+ case Xsse_CMPEQ32: return "pcmpeqd";
+ case Xsse_CMPGT8S: return "pcmpgtb";
+ case Xsse_CMPGT16S: return "pcmpgtw";
+ case Xsse_CMPGT32S: return "pcmpgtd";
+ case Xsse_SHL16: return "psllw";
+ case Xsse_SHL32: return "pslld";
+ case Xsse_SHL64: return "psllq";
+ case Xsse_SHR16: return "psrlw";
+ case Xsse_SHR32: return "psrld";
+ case Xsse_SHR64: return "psrlq";
+ case Xsse_SAR16: return "psraw";
+ case Xsse_SAR32: return "psrad";
+ case Xsse_PACKSSD: return "packssdw";
+ case Xsse_PACKSSW: return "packsswb";
+ case Xsse_PACKUSW: return "packuswb";
+ case Xsse_PUNPCKHB: return "punpckhb";
+ case Xsse_PUNPCKHW: return "punpckhw";
+ case Xsse_PUNPCKHD: return "punpckhd";
+ case Xsse_PUNPCKLB: return "punpcklb";
+ case Xsse_PUNPCKLW: return "punpcklw";
+ case Xsse_PUNPCKLD: return "punpckld";
default: vpanic("showX86SseOp");
}
}
i->Xin.Sse32Fx4.op = op;
i->Xin.Sse32Fx4.src = src;
i->Xin.Sse32Fx4.dst = dst;
+ vassert(op != Xsse_MOV);
return i;
}
X86Instr* X86Instr_Sse32FLo ( X86SseOp op, HReg src, HReg dst ) {
i->Xin.Sse32FLo.op = op;
i->Xin.Sse32FLo.src = src;
i->Xin.Sse32FLo.dst = dst;
+ vassert(op != Xsse_MOV);
return i;
}
X86Instr* X86Instr_Sse64Fx2 ( X86SseOp op, HReg src, HReg dst ) {
i->Xin.Sse64Fx2.op = op;
i->Xin.Sse64Fx2.src = src;
i->Xin.Sse64Fx2.dst = dst;
+ vassert(op != Xsse_MOV);
return i;
}
X86Instr* X86Instr_Sse64FLo ( X86SseOp op, HReg src, HReg dst ) {
i->Xin.Sse64FLo.op = op;
i->Xin.Sse64FLo.src = src;
i->Xin.Sse64FLo.dst = dst;
+ vassert(op != Xsse_MOV);
+ return i;
+}
+X86Instr* X86Instr_SseReRg ( X86SseOp op, HReg re, HReg rg ) {
+ X86Instr* i = LibVEX_Alloc(sizeof(X86Instr));
+ i->tag = Xin_SseReRg;
+ i->Xin.SseReRg.op = op;
+ i->Xin.SseReRg.src = re;
+ i->Xin.SseReRg.dst = rg;
+ vassert(op != Xsse_MOV);
return i;
}
vex_printf(",");
ppHRegX86(i->Xin.Sse64FLo.dst);
return;
+ case Xin_SseReRg:
+ vex_printf("%s ", showX86SseOp(i->Xin.SseReRg.op));
+ ppHRegX86(i->Xin.SseReRg.src);
+ vex_printf(",");
+ ppHRegX86(i->Xin.SseReRg.dst);
+ return;
default:
vpanic("ppX86Instr");
addHRegUse(u, unary ? HRmWrite : HRmModify,
i->Xin.Sse64FLo.dst);
return;
+ case Xin_SseReRg:
+ vassert(i->Xin.SseReRg.op != Xsse_MOV);
+ addHRegUse(u, HRmRead, i->Xin.SseReRg.src);
+ addHRegUse(u, HRmModify, i->Xin.SseReRg.dst);
+ return;
default:
ppX86Instr(i);
vpanic("getRegUsage_X86Instr");
mapReg(m, &i->Xin.Sse64FLo.src);
mapReg(m, &i->Xin.Sse64FLo.dst);
return;
+ case Xin_SseReRg:
+ mapReg(m, &i->Xin.SseReRg.src);
+ mapReg(m, &i->Xin.SseReRg.dst);
+ return;
default:
ppX86Instr(i);
vpanic("mapRegs_X86Instr");
*p++ = (UChar)(xtra & 0xFF);
goto done;
+ case Xin_SseReRg:
+# define XX(_n) *p++ = (_n)
+ switch (i->Xin.SseReRg.op) {
+ case Xsse_PACKSSD: XX(0x66); XX(0x0F); XX(0x6B); break;
+ case Xsse_PACKSSW: XX(0x66); XX(0x0F); XX(0x63); break;
+ case Xsse_PACKUSW: XX(0x66); XX(0x0F); XX(0x67); break;
+ case Xsse_ADD8: XX(0x66); XX(0x0F); XX(0xFC); break;
+ case Xsse_ADD16: XX(0x66); XX(0x0F); XX(0xFD); break;
+ case Xsse_ADD32: XX(0x66); XX(0x0F); XX(0xFE); break;
+ case Xsse_ADD64: XX(0x66); XX(0x0F); XX(0xD4); break;
+ case Xsse_QADD8S: XX(0x66); XX(0x0F); XX(0xEC); break;
+ case Xsse_QADD16S: XX(0x66); XX(0x0F); XX(0xED); break;
+ case Xsse_QADD8U: XX(0x66); XX(0x0F); XX(0xDC); break;
+ case Xsse_QADD16U: XX(0x66); XX(0x0F); XX(0xDD); break;
+ case Xsse_AVG8U: XX(0x66); XX(0x0F); XX(0xE0); break;
+ case Xsse_AVG16U: XX(0x66); XX(0x0F); XX(0xE3); break;
+ default: goto bad;
+ }
+ p = doAMode_R(p, fake(vregNo(i->Xin.SseReRg.dst)),
+ fake(vregNo(i->Xin.SseReRg.src)) );
+# undef XX
+ goto done;
+
default:
goto bad;
}
typedef
enum {
Xsse_INVALID,
- Xsse_MOV, Xsse_AND, Xsse_OR, Xsse_XOR, Xsse_ANDN,
+ /* mov */
+ Xsse_MOV,
+ /* Floating point binary */
Xsse_ADDF, Xsse_SUBF, Xsse_MULF, Xsse_DIVF,
Xsse_MAXF, Xsse_MINF,
+ Xsse_CMPEQF, Xsse_CMPLTF, Xsse_CMPLEF, Xsse_CMPUNF,
+ /* Floating point unary */
Xsse_RCPF, Xsse_RSQRTF, Xsse_SQRTF,
- Xsse_CMPEQF, Xsse_CMPLTF, Xsse_CMPLEF, Xsse_CMPUNF
+ /* Bitwise */
+ Xsse_AND, Xsse_OR, Xsse_XOR, Xsse_ANDN,
+ /* Integer binary */
+ Xsse_ADD8, Xsse_ADD16, Xsse_ADD32, Xsse_ADD64,
+ Xsse_QADD8U, Xsse_QADD16U,
+ Xsse_QADD8S, Xsse_QADD16S,
+ Xsse_SUB8, Xsse_SUB16, Xsse_SUB32, Xsse_SUB64,
+ Xsse_QSUB8U, Xsse_QSUB16U,
+ Xsse_QSUB8S, Xsse_QSUB16S,
+ Xsse_MUL16,
+ Xsse_MULHI16U,
+ Xsse_MULHI16S,
+ Xsse_AVG8U, Xsse_AVG16U,
+ Xsse_MAX16S,
+ Xsse_MAX8U,
+ Xsse_MIN16S,
+ Xsse_MIN8U,
+ Xsse_CMPEQ8, Xsse_CMPEQ16, Xsse_CMPEQ32,
+ Xsse_CMPGT8S, Xsse_CMPGT16S, Xsse_CMPGT32S,
+ Xsse_SHL16, Xsse_SHL32, Xsse_SHL64,
+ Xsse_SHR16, Xsse_SHR32, Xsse_SHR64,
+ Xsse_SAR16, Xsse_SAR32,
+ Xsse_PACKSSD, Xsse_PACKSSW, Xsse_PACKUSW,
+ Xsse_PUNPCKHB, Xsse_PUNPCKHW, Xsse_PUNPCKHD,
+ Xsse_PUNPCKLB, Xsse_PUNPCKLW, Xsse_PUNPCKLD
}
X86SseOp;
Xin_Sse32Fx4, /* SSE binary, 32Fx4 */
Xin_Sse32FLo, /* SSE binary, 32F in lowest lane only */
Xin_Sse64Fx2, /* SSE binary, 64Fx2 */
- Xin_Sse64FLo /* SSE binary, 64F in lowest lane only */
- /* Xin_SseUn32Fx4 */
+ Xin_Sse64FLo, /* SSE binary, 64F in lowest lane only */
+ Xin_SseReRg /* SSE binary general reg-reg, Re, Rg */
}
X86InstrTag;
HReg src;
HReg dst;
} Sse64FLo;
+ struct {
+ X86SseOp op;
+ HReg src;
+ HReg dst;
+ } SseReRg;
} Xin;
}
extern X86Instr* X86Instr_Sse32FLo ( X86SseOp, HReg, HReg );
extern X86Instr* X86Instr_Sse64Fx2 ( X86SseOp, HReg, HReg );
extern X86Instr* X86Instr_Sse64FLo ( X86SseOp, HReg, HReg );
+extern X86Instr* X86Instr_SseReRg ( X86SseOp, HReg, HReg );
extern void ppX86Instr ( X86Instr* );
/* DO NOT CALL THIS DIRECTLY */
static HReg iselVecExpr_wrk ( ISelEnv* env, IRExpr* e )
{
+ Bool arg1isEReg = False;
X86SseOp op = Xsse_INVALID;
IRType ty = typeOfIRExpr(env->type_env,e);
vassert(e);
return dst;
}
+ case Iop_QNarrow32Sx4: op = Xsse_PACKSSD;
+ arg1isEReg = True; goto do_SseReRg;
+ case Iop_QNarrow16Sx8: op = Xsse_PACKSSW;
+ arg1isEReg = True; goto do_SseReRg;
+ case Iop_QNarrow16Ux8: op = Xsse_PACKUSW;
+ arg1isEReg = True; goto do_SseReRg;
+ case Iop_Add8x16: op = Xsse_ADD8; goto do_SseReRg;
+ case Iop_Add16x8: op = Xsse_ADD16; goto do_SseReRg;
+ case Iop_Add32x4: op = Xsse_ADD32; goto do_SseReRg;
+ case Iop_Add64x2: op = Xsse_ADD64; goto do_SseReRg;
+ case Iop_QAdd8Sx16: op = Xsse_QADD8S; goto do_SseReRg;
+ case Iop_QAdd16Sx8: op = Xsse_QADD16S; goto do_SseReRg;
+ case Iop_QAdd8Ux16: op = Xsse_QADD8U; goto do_SseReRg;
+ case Iop_QAdd16Ux8: op = Xsse_QADD16U; goto do_SseReRg;
+ case Iop_Avg8Ux16: op = Xsse_AVG8U; goto do_SseReRg;
+ case Iop_Avg16Ux8: op = Xsse_AVG16U; goto do_SseReRg;
+ do_SseReRg: {
+ HReg arg1 = iselVecExpr(env, e->Iex.Binop.arg1);
+ HReg arg2 = iselVecExpr(env, e->Iex.Binop.arg2);
+ HReg dst = newVRegV(env);
+ if (arg1isEReg) {
+ addInstr(env, mk_vMOVsd_RR(arg2, dst));
+ addInstr(env, X86Instr_SseReRg(op, arg1, dst));
+ } else {
+ addInstr(env, mk_vMOVsd_RR(arg1, dst));
+ addInstr(env, X86Instr_SseReRg(op, arg2, dst));
+ }
+ return dst;
+ }
+
default:
break;
} /* switch (e->Iex.Binop.op) */
case Iop_ReinterpF32asI32: vex_printf("ReinterpF32asI32"); return;
case Iop_ReinterpI32asF32: vex_printf("ReinterpI32asF32"); return;
- case Iop_And128: vex_printf("And128"); return;
- case Iop_Or128: vex_printf("Or128"); return;
- case Iop_Xor128: vex_printf("Xor128"); return;
-
case Iop_Add32Fx4: vex_printf("Add32Fx4"); return;
case Iop_Add32F0x4: vex_printf("Add32F0x4"); return;
case Iop_Add64Fx2: vex_printf("Add64Fx2"); return;
case Iop_Set128lo32: vex_printf("Set128lo32"); return;
case Iop_Set128lo64: vex_printf("Set128lo64"); return;
+ case Iop_And128: vex_printf("And128"); return;
+ case Iop_Or128: vex_printf("Or128"); return;
+ case Iop_Xor128: vex_printf("Xor128"); return;
+
+ case Iop_Add8x16: vex_printf("Add8x16"); return;
+ case Iop_Add16x8: vex_printf("Add16x8"); return;
+ case Iop_Add32x4: vex_printf("Add32x4"); return;
+ case Iop_Add64x2: vex_printf("Add64x2"); return;
+ case Iop_QAdd8Ux16: vex_printf("QAdd8Ux16"); return;
+ case Iop_QAdd16Ux8: vex_printf("QAdd16Ux8"); return;
+ case Iop_QAdd8Sx16: vex_printf("QAdd8Sx16"); return;
+ case Iop_QAdd16Sx8: vex_printf("QAdd16Sx8"); return;
+
+ case Iop_Sub8x16: vex_printf("Sub8x16"); return;
+ case Iop_Sub16x8: vex_printf("Sub16x8"); return;
+ case Iop_Sub32x4: vex_printf("Sub32x4"); return;
+ case Iop_Sub64x2: vex_printf("Sub64x2"); return;
+ case Iop_QSub8Ux16: vex_printf("QSub8Ux16"); return;
+ case Iop_QSub16Ux8: vex_printf("QSub16Ux8"); return;
+ case Iop_QSub8Sx16: vex_printf("QSub8Sx16"); return;
+ case Iop_QSub16Sx8: vex_printf("QSub16Sx8"); return;
+
+ case Iop_Mul16x8: vex_printf("Mul16x8"); return;
+ case Iop_MulHi16Ux8: vex_printf("MulHi16Ux8"); return;
+ case Iop_MulHi16Sx8: vex_printf("MulHi16Sx8"); return;
+
+ case Iop_Avg8Ux16: vex_printf("Avg8Ux16"); return;
+ case Iop_Avg16Ux8: vex_printf("Avg16Ux8"); return;
+
+ case Iop_Max16Sx8: vex_printf("Max16Sx8"); return;
+ case Iop_Max8Ux16: vex_printf("Max8Ux16"); return;
+ case Iop_Min16Sx8: vex_printf("Min16Sx8"); return;
+ case Iop_Min8Ux16: vex_printf("Min8Ux16"); return;
+
+ case Iop_CmpEQ8x16: vex_printf("CmpEQ8x16"); return;
+ case Iop_CmpEQ16x8: vex_printf("CmpEQ16x8"); return;
+ case Iop_CmpEQ32x4: vex_printf("CmpEQ32x4"); return;
+ case Iop_CmpGT8Sx16: vex_printf("CmpGT8Sx16"); return;
+ case Iop_CmpGT16Sx8: vex_printf("CmpGT16Sx8"); return;
+ case Iop_CmpGT32Sx4: vex_printf("CmpGT32Sx4"); return;
+
+ case Iop_ShlN16x8: vex_printf("ShlN16x8"); return;
+ case Iop_ShlN32x4: vex_printf("ShlN32x4"); return;
+ case Iop_ShlN64x2: vex_printf("ShlN64x2"); return;
+ case Iop_ShrN16x8: vex_printf("ShrN16x8"); return;
+ case Iop_ShrN32x4: vex_printf("ShrN32x4"); return;
+ case Iop_ShrN64x2: vex_printf("ShrN64x2"); return;
+ case Iop_SarN16x8: vex_printf("SarN16x8"); return;
+ case Iop_SarN32x4: vex_printf("SarN32x4"); return;
+
+ case Iop_QNarrow16Ux8: vex_printf("QNarrow16Ux8"); return;
+ case Iop_QNarrow16Sx8: vex_printf("QNarrow16Sx8"); return;
+ case Iop_QNarrow32Sx4: vex_printf("QNarrow32Sx4"); return;
+
+ case Iop_InterleaveHI8x16: vex_printf("InterleaveHI8x16"); return;
+ case Iop_InterleaveHI16x8: vex_printf("InterleaveHI16x8"); return;
+ case Iop_InterleaveHI32x4: vex_printf("InterleaveHI32x4"); return;
+ case Iop_InterleaveHI64x2: vex_printf("InterleaveHI64x2"); return;
+ case Iop_InterleaveLO8x16: vex_printf("InterleaveLO8x16"); return;
+ case Iop_InterleaveLO16x8: vex_printf("InterleaveLO16x8"); return;
+ case Iop_InterleaveLO32x4: vex_printf("InterleaveLO32x4"); return;
+ case Iop_InterleaveLO64x2: vex_printf("InterleaveLO64x2"); return;
+
default: vpanic("ppIROp(1)");
}
case Iop_Sub32Fx4: case Iop_Sub32F0x4:
case Iop_Sub64Fx2: case Iop_Sub64F0x2:
case Iop_And128: case Iop_Or128: case Iop_Xor128:
+ case Iop_Add8x16: case Iop_Add16x8:
+ case Iop_Add32x4: case Iop_Add64x2:
+ case Iop_QAdd8Ux16: case Iop_QAdd16Ux8:
+ case Iop_QAdd8Sx16: case Iop_QAdd16Sx8:
+ case Iop_Sub8x16: case Iop_Sub16x8:
+ case Iop_Sub32x4: case Iop_Sub64x2:
+ case Iop_QSub8Ux16: case Iop_QSub16Ux8:
+ case Iop_QSub8Sx16: case Iop_QSub16Sx8:
+ case Iop_Mul16x8:
+ case Iop_MulHi16Ux8:
+ case Iop_MulHi16Sx8:
+ case Iop_Avg8Ux16:
+ case Iop_Avg16Ux8:
+ case Iop_Max16Sx8:
+ case Iop_Max8Ux16:
+ case Iop_Min16Sx8:
+ case Iop_Min8Ux16:
+ case Iop_CmpEQ8x16: case Iop_CmpEQ16x8: case Iop_CmpEQ32x4:
+ case Iop_CmpGT8Sx16: case Iop_CmpGT16Sx8: case Iop_CmpGT32Sx4:
+ case Iop_QNarrow16Ux8:
+ case Iop_QNarrow16Sx8: case Iop_QNarrow32Sx4:
+ case Iop_InterleaveHI8x16: case Iop_InterleaveHI16x8:
+ case Iop_InterleaveHI32x4: case Iop_InterleaveHI64x2:
+ case Iop_InterleaveLO8x16: case Iop_InterleaveLO16x8:
+ case Iop_InterleaveLO32x4: case Iop_InterleaveLO64x2:
BINARY(Ity_V128, Ity_V128,Ity_V128);
case Iop_Recip32Fx4: case Iop_Recip32F0x4:
case Iop_Sqrt64Fx2: case Iop_Sqrt64F0x2:
UNARY(Ity_V128, Ity_V128);
+ case Iop_ShlN16x8: case Iop_ShlN32x4: case Iop_ShlN64x2:
+ case Iop_ShrN16x8: case Iop_ShrN32x4: case Iop_ShrN64x2:
+ case Iop_SarN16x8: case Iop_SarN32x4:
+ BINARY(Ity_V128, Ity_V128, Ity_I8);
+
default:
ppIROp(op);
vpanic("typeOfPrimop");
Iop_ReinterpF64asI64, Iop_ReinterpI64asF64,
Iop_ReinterpF32asI32, Iop_ReinterpI32asF32,
- /* ------------------ 128-bit SIMD. ------------------ */
-
- /* 128-bit ops */
- Iop_And128, Iop_Or128, Iop_Xor128,
+ /* ------------------ 128-bit SIMD FP. ------------------ */
/* --- 32x4 vector FP --- */
Iop_64Uto128,
Iop_Set128lo32,
Iop_Set128lo64,
- /* 128 -> 32 bit unpack */
- //Iop_128W3to32, // :: V128 -> I32, bits 127-96
- //Iop_128W2to32, // :: V128 -> I32, bits 95-64
- //Iop_128W1to32, // :: V128 -> I32, bits 63-32
- //Iop_128W0to32 // :: V128 -> I32, bits 31-0
+
+ /* ------------------ 128-bit SIMD Integer. ------------------ */
+
+ /* BITWISE OPS */
+ Iop_And128, Iop_Or128, Iop_Xor128,
+
+ /* ADDITION (normal / unsigned sat / signed sat) */
+ Iop_Add8x16, Iop_Add16x8, Iop_Add32x4, Iop_Add64x2,
+ Iop_QAdd8Ux16, Iop_QAdd16Ux8,
+ Iop_QAdd8Sx16, Iop_QAdd16Sx8,
+
+ /* SUBTRACTION (normal / unsigned sat / signed sat) */
+ Iop_Sub8x16, Iop_Sub16x8, Iop_Sub32x4, Iop_Sub64x2,
+ Iop_QSub8Ux16, Iop_QSub16Ux8,
+ Iop_QSub8Sx16, Iop_QSub16Sx8,
+
+ /* MULTIPLICATION (normal / high half of signed/unsigned) */
+ Iop_Mul16x8,
+ Iop_MulHi16Ux8,
+ Iop_MulHi16Sx8,
+
+ /* AVERAGING: note: (arg1 + arg2 + 1) >> 1 */
+ Iop_Avg8Ux16,
+ Iop_Avg16Ux8,
+
+ /* MIN/MAX */
+ Iop_Max16Sx8,
+ Iop_Max8Ux16,
+ Iop_Min16Sx8,
+ Iop_Min8Ux16,
+
+ /* COMPARISON */
+ Iop_CmpEQ8x16, Iop_CmpEQ16x8, Iop_CmpEQ32x4,
+ Iop_CmpGT8Sx16, Iop_CmpGT16Sx8, Iop_CmpGT32Sx4,
+
+ /* VECTOR x SCALAR SHIFT (shift amt :: Ity_I8) */
+ Iop_ShlN16x8, Iop_ShlN32x4, Iop_ShlN64x2,
+ Iop_ShrN16x8, Iop_ShrN32x4, Iop_ShrN64x2,
+ Iop_SarN16x8, Iop_SarN32x4,
+
+ /* NARROWING -- narrow 2xV128 into 1xV128, hi half from left arg */
+ Iop_QNarrow16Ux8,
+ Iop_QNarrow16Sx8,
+ Iop_QNarrow32Sx4,
+
+ /* INTERLEAVING -- interleave lanes from low or high halves of
+ operands. Most-significant result lane is from the left
+ arg. */
+ Iop_InterleaveHI8x16, Iop_InterleaveHI16x8,
+ Iop_InterleaveHI32x4, Iop_InterleaveHI64x2,
+ Iop_InterleaveLO8x16, Iop_InterleaveLO16x8,
+ Iop_InterleaveLO32x4, Iop_InterleaveLO64x2
}
IROp;