goto decode_success;
}
+ /* 66 0F 68 = PUNPCKHBW */
+ if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x68) {
+ delta = dis_SSEint_E_to_G( sorb, delta+2,
+ "punpckhbw",
+ Iop_InterleaveHI8x16, True );
+ goto decode_success;
+ }
+
+ /* 66 0F 6A = PUNPCKHDQ */
+ if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x6A) {
+ delta = dis_SSEint_E_to_G( sorb, delta+2,
+ "punpckhdq",
+ Iop_InterleaveHI32x4, True );
+ goto decode_success;
+ }
+
+ /* 66 0F 6D = PUNPCKHQDQ */
+ if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x6D) {
+ delta = dis_SSEint_E_to_G( sorb, delta+2,
+ "punpckhqdq",
+ Iop_InterleaveHI64x2, True );
+ goto decode_success;
+ }
+
+ /* 66 0F 69 = PUNPCKHWD */
+ if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x69) {
+ delta = dis_SSEint_E_to_G( sorb, delta+2,
+ "punpckhwd",
+ Iop_InterleaveHI16x8, True );
+ goto decode_success;
+ }
+
+ /* 66 0F 60 = PUNPCKLBW */
+ if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x60) {
+ delta = dis_SSEint_E_to_G( sorb, delta+2,
+ "punpcklbw",
+ Iop_InterleaveLO8x16, True );
+ goto decode_success;
+ }
+
+ /* 66 0F 62 = PUNPCKLDQ */
+ if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x62) {
+ delta = dis_SSEint_E_to_G( sorb, delta+2,
+ "punpckldq",
+ Iop_InterleaveLO32x4, True );
+ goto decode_success;
+ }
+
+ /* 66 0F 6C = PUNPCKLQDQ */
+ if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x6C) {
+ delta = dis_SSEint_E_to_G( sorb, delta+2,
+ "punpcklqdq",
+ Iop_InterleaveLO64x2, True );
+ goto decode_success;
+ }
+
+ /* 66 0F 61 = PUNPCKLWD */
+ if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x61) {
+ delta = dis_SSEint_E_to_G( sorb, delta+2,
+ "punpcklwd",
+ Iop_InterleaveLO16x8, True );
+ goto decode_success;
+ }
+
+ /* 66 0F EF = PXOR */
+ if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xEF) {
+ delta = dis_SSE_E_to_G_all( sorb, delta+2, "pxor", Iop_Xor128 );
+ goto decode_success;
+ }
+
//--
//-- /* FXSAVE/FXRSTOR m32 -- load/store the FPU/MMX/SSE state. */
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";
+ case Xsse_UNPCKHB: return "punpckhb";
+ case Xsse_UNPCKHW: return "punpckhw";
+ case Xsse_UNPCKHD: return "punpckhd";
+ case Xsse_UNPCKHQ: return "punpckhq";
+ case Xsse_UNPCKLB: return "punpcklb";
+ case Xsse_UNPCKLW: return "punpcklw";
+ case Xsse_UNPCKLD: return "punpckld";
+ case Xsse_UNPCKLQ: return "punpcklq";
default: vpanic("showX86SseOp");
}
}
vassert(sz == 4 || sz == 8);
return i;
}
-X86Instr* X86Instr_Sse128 ( X86SseOp op, HReg src, HReg dst ) {
- X86Instr* i = LibVEX_Alloc(sizeof(X86Instr));
- i->tag = Xin_Sse128;
- i->Xin.Sse128.op = op;
- i->Xin.Sse128.src = src;
- i->Xin.Sse128.dst = dst;
- vassert(op == Xsse_MOV
- || op == Xsse_AND || op == Xsse_OR || op == Xsse_XOR);
- return i;
-}
X86Instr* X86Instr_Sse32Fx4 ( X86SseOp op, HReg src, HReg dst ) {
X86Instr* i = LibVEX_Alloc(sizeof(X86Instr));
i->tag = Xin_Sse32Fx4;
i->Xin.SseReRg.op = op;
i->Xin.SseReRg.src = re;
i->Xin.SseReRg.dst = rg;
- vassert(op != Xsse_MOV);
return i;
}
X86Instr* X86Instr_SseCMov ( X86CondCode cond, HReg src, HReg dst ) {
vex_printf(",");
ppHRegX86(i->Xin.SseLdzLO.reg);
return;
- case Xin_Sse128:
- if (i->Xin.Sse128.op == Xsse_MOV) {
- vex_printf("mov ");
- } else {
- vex_printf("p%s ", showX86SseOp(i->Xin.Sse128.op));
- }
- ppHRegX86(i->Xin.Sse128.src);
- vex_printf(",");
- ppHRegX86(i->Xin.Sse128.dst);
- return;
case Xin_Sse32Fx4:
vex_printf("%sps ", showX86SseOp(i->Xin.Sse32Fx4.op));
ppHRegX86(i->Xin.Sse32Fx4.src);
case Xin_SseConst:
addHRegUse(u, HRmWrite, i->Xin.SseConst.dst);
return;
- case Xin_Sse128:
- addHRegUse(u, HRmRead, i->Xin.Sse128.src);
- addHRegUse(u, i->Xin.Sse128.op==Xsse_MOV ? HRmWrite : HRmModify,
- i->Xin.Sse128.dst);
- return;
case Xin_Sse32Fx4:
vassert(i->Xin.Sse32Fx4.op != Xsse_MOV);
unary = i->Xin.Sse32Fx4.op == Xsse_RCPF
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);
+ addHRegUse(u, HRmRead, i->Xin.SseReRg.src);
+ addHRegUse(u, i->Xin.SseReRg.op == Xsse_MOV ? HRmWrite : HRmModify,
+ i->Xin.SseReRg.dst);
return;
case Xin_SseCMov:
addHRegUse(u, HRmRead, i->Xin.SseCMov.src);
mapReg(m, &i->Xin.SseLdzLO.reg);
mapRegs_X86AMode(m, i->Xin.SseLdzLO.addr);
break;
- case Xin_Sse128:
- mapReg(m, &i->Xin.Sse128.src);
- mapReg(m, &i->Xin.Sse128.dst);
- return;
case Xin_Sse32Fx4:
mapReg(m, &i->Xin.Sse32Fx4.src);
mapReg(m, &i->Xin.Sse32Fx4.dst);
*dst = i->Xin.FpUnary.dst;
return True;
}
- if (i->tag == Xin_Sse128) {
- if (i->Xin.Sse128.op != Xsse_MOV)
+ if (i->tag == Xin_SseReRg) {
+ if (i->Xin.SseReRg.op != Xsse_MOV)
return False;
- *src = i->Xin.Sse128.src;
- *dst = i->Xin.Sse128.dst;
+ *src = i->Xin.SseReRg.src;
+ *dst = i->Xin.SseReRg.dst;
return True;
}
return False;
i->Xin.SseLdzLO.addr);
goto done;
- case Xin_Sse128:
- *p++ = 0x0F;
- switch (i->Xin.Sse128.op) {
- case Xsse_OR: *p++ = 0x56; break;
- case Xsse_XOR: *p++ = 0x57; break;
- case Xsse_AND: *p++ = 0x54; break;
- case Xsse_MOV: *p++ = 0x10; break;
- default: goto bad;
- }
- p = doAMode_R(p, fake(vregNo(i->Xin.Sse128.dst)),
- fake(vregNo(i->Xin.Sse128.src)) );
- goto done;
-
case Xin_Sse32Fx4:
xtra = 0;
*p++ = 0x0F;
case Xin_SseReRg:
# define XX(_n) *p++ = (_n)
switch (i->Xin.SseReRg.op) {
+ case Xsse_MOV: /*movups*/ XX(0x0F); XX(0x10); break;
+ case Xsse_OR: XX(0x0F); XX(0x56); break;
+ case Xsse_XOR: XX(0x0F); XX(0x57); break;
+ case Xsse_AND: XX(0x0F); XX(0x54); break;
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_QSUB16S: XX(0x66); XX(0x0F); XX(0xE9); break;
case Xsse_QSUB8U: XX(0x66); XX(0x0F); XX(0xD8); break;
case Xsse_QSUB16U: XX(0x66); XX(0x0F); XX(0xD9); break;
+ case Xsse_UNPCKHB: XX(0x66); XX(0x0F); XX(0x68); break;
+ case Xsse_UNPCKHW: XX(0x66); XX(0x0F); XX(0x69); break;
+ case Xsse_UNPCKHD: XX(0x66); XX(0x0F); XX(0x6A); break;
+ case Xsse_UNPCKHQ: XX(0x66); XX(0x0F); XX(0x6D); break;
+ case Xsse_UNPCKLB: XX(0x66); XX(0x0F); XX(0x60); break;
+ case Xsse_UNPCKLW: XX(0x66); XX(0x0F); XX(0x61); break;
+ case Xsse_UNPCKLD: XX(0x66); XX(0x0F); XX(0x62); break;
+ case Xsse_UNPCKLQ: XX(0x66); XX(0x0F); XX(0x6C); break;
default: goto bad;
}
p = doAMode_R(p, fake(vregNo(i->Xin.SseReRg.dst)),
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
+ Xsse_PACKSSD, Xsse_PACKSSW, Xsse_PACKUSW,
+ Xsse_UNPCKHB, Xsse_UNPCKHW, Xsse_UNPCKHD, Xsse_UNPCKHQ,
+ Xsse_UNPCKLB, Xsse_UNPCKLW, Xsse_UNPCKLD, Xsse_UNPCKLQ
}
X86SseOp;
Xin_SseConst, /* Generate restricted SSE literal */
Xin_SseLdSt, /* SSE load/store, no alignment constraints */
Xin_SseLdzLO, /* SSE load low 32/64 bits, zero remainder of reg */
- Xin_Sse128, /* SSE binary typeless (and/or/xor/andn) */
Xin_Sse32Fx4, /* SSE binary, 32Fx4 */
Xin_Sse32FLo, /* SSE binary, 32F in lowest lane only */
Xin_Sse64Fx2, /* SSE binary, 64Fx2 */
HReg reg;
X86AMode* addr;
} SseLdzLO;
- struct {
- X86SseOp op; /* MOV/AND/OR/XOR/ANDN only */
- HReg src;
- HReg dst;
- } Sse128;
struct {
X86SseOp op;
HReg src;
extern X86Instr* X86Instr_SseConst ( UShort con, HReg dst );
extern X86Instr* X86Instr_SseLdSt ( Bool isLoad, HReg, X86AMode* );
extern X86Instr* X86Instr_SseLdzLO ( Int sz, HReg, X86AMode* );
-extern X86Instr* X86Instr_Sse128 ( X86SseOp, HReg, HReg );
extern X86Instr* X86Instr_Sse32Fx4 ( X86SseOp, HReg, HReg );
extern X86Instr* X86Instr_Sse32FLo ( X86SseOp, HReg, HReg );
extern X86Instr* X86Instr_Sse64Fx2 ( X86SseOp, HReg, HReg );
{
vassert(hregClass(src) == HRcVec128);
vassert(hregClass(dst) == HRcVec128);
- return X86Instr_Sse128(Xsse_MOV, src, dst);
+ return X86Instr_SseReRg(Xsse_MOV, src, dst);
}
/* Advance/retreat %esp by n. */
return dst;
}
- case Iop_And128: op = Xsse_AND; goto do_128;
- case Iop_Or128: op = Xsse_OR; goto do_128;
- case Iop_Xor128: op = Xsse_XOR; goto do_128;
- do_128:
- {
- HReg argL = iselVecExpr(env, e->Iex.Binop.arg1);
- HReg argR = iselVecExpr(env, e->Iex.Binop.arg2);
- HReg dst = newVRegV(env);
- addInstr(env, mk_vMOVsd_RR(argL, dst));
- addInstr(env, X86Instr_Sse128(op, argR, dst));
- return dst;
- }
-
case Iop_CmpEQ32Fx4: op = Xsse_CMPEQF; goto do_32Fx4;
case Iop_CmpLT32Fx4: op = Xsse_CMPLTF; goto do_32Fx4;
case Iop_CmpLE32Fx4: op = Xsse_CMPLEF; goto do_32Fx4;
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_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_InterleaveHI8x16:
+ op = Xsse_UNPCKHB; arg1isEReg = True; goto do_SseReRg;
+ case Iop_InterleaveHI16x8:
+ op = Xsse_UNPCKHW; arg1isEReg = True; goto do_SseReRg;
+ case Iop_InterleaveHI32x4:
+ op = Xsse_UNPCKHD; arg1isEReg = True; goto do_SseReRg;
+ case Iop_InterleaveHI64x2:
+ op = Xsse_UNPCKHQ; arg1isEReg = True; goto do_SseReRg;
+
+ case Iop_InterleaveLO8x16:
+ op = Xsse_UNPCKLB; arg1isEReg = True; goto do_SseReRg;
+ case Iop_InterleaveLO16x8:
+ op = Xsse_UNPCKLW; arg1isEReg = True; goto do_SseReRg;
+ case Iop_InterleaveLO32x4:
+ op = Xsse_UNPCKLD; arg1isEReg = True; goto do_SseReRg;
+ case Iop_InterleaveLO64x2:
+ op = Xsse_UNPCKLQ; arg1isEReg = True; goto do_SseReRg;
+
+ case Iop_And128: op = Xsse_AND; goto do_SseReRg;
+ case Iop_Or128: op = Xsse_OR; goto do_SseReRg;
+ case Iop_Xor128: op = Xsse_XOR; 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;