return v;
}
-//.. static UInt getUDisp16 ( UInt delta )
+//.. static UInt getUDisp16 ( ULong delta )
//.. {
//.. UInt v = guest_code[delta+1]; v <<= 8;
//.. v |= guest_code[delta+0];
//.. return v & 0xFFFF;
//.. }
//..
-//.. static UInt getUDisp ( Int size, UInt delta )
+//.. static UInt getUDisp ( Int size, ULong delta )
//.. {
//.. switch (size) {
//.. case 4: return getUDisp32(delta);
//..
//..
//.. static
-//.. UInt dis_FPU ( Bool* decode_ok, UChar sorb, UInt delta )
+//.. UInt dis_FPU ( Bool* decode_ok, UChar sorb, ULong delta )
//.. {
//.. Int len;
//.. UInt r_src, r_dst;
//.. /* Vector by scalar shift of G by the amount specified at the bottom
//.. of E. This is a straight copy of dis_SSE_shiftG_byE. */
//..
-//.. static UInt dis_MMX_shiftG_byE ( UChar sorb, UInt delta,
+//.. static UInt dis_MMX_shiftG_byE ( UChar sorb, ULong delta,
//.. HChar* opname, IROp op )
//.. {
//.. HChar dis_buf[50];
//.. straight copy of dis_SSE_shiftE_imm. */
//..
//.. static
-//.. UInt dis_MMX_shiftE_imm ( UInt delta, HChar* opname, IROp op )
+//.. UInt dis_MMX_shiftE_imm ( ULong delta, HChar* opname, IROp op )
//.. {
//.. Bool shl, shr, sar;
//.. UChar rm = getUChar(delta);
//.. /* Completely handle all MMX instructions except emms. */
//..
//.. static
-//.. UInt dis_MMX ( Bool* decode_ok, UChar sorb, Int sz, UInt delta )
+//.. UInt dis_MMX ( Bool* decode_ok, UChar sorb, Int sz, ULong delta )
//.. {
//.. Int len;
//.. UChar modrm;
//.. v-size (no b- variant). */
//.. static
//.. UInt dis_SHLRD_Gv_Ev ( UChar sorb,
-//.. UInt delta, UChar modrm,
+//.. ULong delta, UChar modrm,
//.. Int sz,
//.. IRExpr* shift_amt,
//.. Bool amt_is_literal,
//..
//..
//.. static
-//.. UInt dis_bt_G_E ( UChar sorb, Int sz, UInt delta, BtOp op )
+//.. UInt dis_bt_G_E ( UChar sorb, Int sz, ULong delta, BtOp op )
//.. {
//.. HChar dis_buf[50];
//.. UChar modrm;
//..
//.. /* Handle BSF/BSR. Only v-size seems necessary. */
//.. static
-//.. UInt dis_bs_E_G ( UChar sorb, Int sz, UInt delta, Bool fwds )
+//.. UInt dis_bs_E_G ( UChar sorb, Int sz, ULong delta, Bool fwds )
//.. {
//.. Bool isReg;
//.. UChar modrm;
//.. static
-//.. UInt dis_xadd_G_E ( UChar sorb, Int sz, UInt delta0 )
+//.. UInt dis_xadd_G_E ( UChar sorb, Int sz, ULong delta0 )
//.. {
//.. Int len;
//.. UChar rm = getUChar(delta0);
//.. /* Move 16 bits from Ew (ireg or mem) to G (a segment register). */
//..
//.. static
-//.. UInt dis_mov_Ew_Sw ( UChar sorb, UInt delta0 )
+//.. UInt dis_mov_Ew_Sw ( UChar sorb, ULong delta0 )
//.. {
//.. Int len;
//.. IRTemp addr;
Handles full width G = G `op` E and G = (not G) `op` E.
*/
-//.. static UInt dis_SSE_E_to_G_all_wrk (
-//.. UChar sorb, UInt delta,
-//.. HChar* opname, IROp op,
-//.. Bool invertG
-//.. )
-//.. {
-//.. HChar dis_buf[50];
-//.. Int alen;
-//.. IRTemp addr;
-//.. UChar rm = getUChar(delta);
-//.. IRExpr* gpart
-//.. = invertG ? unop(Iop_Not128, getXMMReg(gregOfRM(rm)))
-//.. : getXMMReg(gregOfRM(rm));
-//.. if (epartIsReg(rm)) {
-//.. putXMMReg( gregOfRM(rm),
-//.. binop(op, gpart,
-//.. getXMMReg(eregOfRM(rm))) );
-//.. DIP("%s %s,%s\n", opname,
-//.. nameXMMReg(eregOfRM(rm)),
-//.. nameXMMReg(gregOfRM(rm)) );
-//.. return delta+1;
-//.. } else {
-//.. addr = disAMode ( &alen, sorb, delta, dis_buf );
-//.. putXMMReg( gregOfRM(rm),
-//.. binop(op, gpart,
-//.. loadLE(Ity_V128, mkexpr(addr))) );
-//.. DIP("%s %s,%s\n", opname,
-//.. dis_buf,
-//.. nameXMMReg(gregOfRM(rm)) );
-//.. return delta+alen;
-//.. }
-//.. }
-//..
-//..
-//.. /* All lanes SSE binary operation, G = G `op` E. */
-//..
-//.. static
-//.. UInt dis_SSE_E_to_G_all ( UChar sorb, UInt delta, HChar* opname, IROp op )
-//.. {
-//.. return dis_SSE_E_to_G_all_wrk( sorb, delta, opname, op, False );
-//.. }
-//..
+static UInt dis_SSE_E_to_G_all_wrk (
+ Prefix pfx, ULong delta,
+ HChar* opname, IROp op,
+ Bool invertG
+ )
+{
+ HChar dis_buf[50];
+ Int alen;
+ IRTemp addr;
+ UChar rm = getUChar(delta);
+ IRExpr* gpart
+ = invertG ? unop(Iop_NotV128, getXMMReg(gregOfRexRM(pfx,rm)))
+ : getXMMReg(gregOfRexRM(pfx,rm));
+ if (epartIsReg(rm)) {
+ putXMMReg( gregOfRexRM(pfx,rm),
+ binop(op, gpart,
+ getXMMReg(eregOfRexRM(pfx,rm))) );
+ DIP("%s %s,%s\n", opname,
+ nameXMMReg(eregOfRexRM(pfx,rm)),
+ nameXMMReg(gregOfRexRM(pfx,rm)) );
+ return delta+1;
+ } else {
+ addr = disAMode ( &alen, pfx, delta, dis_buf, 0 );
+ putXMMReg( gregOfRexRM(pfx,rm),
+ binop(op, gpart,
+ loadLE(Ity_V128, mkexpr(addr))) );
+ DIP("%s %s,%s\n", opname,
+ dis_buf,
+ nameXMMReg(gregOfRexRM(pfx,rm)) );
+ return delta+alen;
+ }
+}
+
+
+/* All lanes SSE binary operation, G = G `op` E. */
+
+static
+UInt dis_SSE_E_to_G_all ( Prefix pfx, ULong delta, HChar* opname, IROp op )
+{
+ return dis_SSE_E_to_G_all_wrk( pfx, delta, opname, op, False );
+}
+
//.. /* All lanes SSE binary operation, G = (not G) `op` E. */
//..
//.. static
-//.. UInt dis_SSE_E_to_G_all_invG ( UChar sorb, UInt delta,
+//.. UInt dis_SSE_E_to_G_all_invG ( UChar sorb, ULong delta,
//.. HChar* opname, IROp op )
//.. {
//.. 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,
+//.. static UInt dis_SSE_E_to_G_lo32 ( UChar sorb, ULong delta,
//.. HChar* opname, IROp op )
//.. {
//.. HChar dis_buf[50];
/* Lower 64-bit lane only SSE binary operation, G = G `op` E. */
-static UInt dis_SSE_E_to_G_lo64 ( Prefix pfx, UInt delta,
+static UInt dis_SSE_E_to_G_lo64 ( Prefix pfx, ULong delta,
HChar* opname, IROp op )
{
HChar dis_buf[50];
//.. /* All lanes unary SSE operation, G = op(E). */
//..
//.. static UInt dis_SSE_E_to_G_unary_all (
-//.. UChar sorb, UInt delta,
+//.. UChar sorb, ULong delta,
//.. HChar* opname, IROp op
//.. )
//.. {
//.. /* Lowest 32-bit lane only unary SSE operation, G = op(E). */
//..
//.. static UInt dis_SSE_E_to_G_unary_lo32 (
-//.. UChar sorb, UInt delta,
+//.. UChar sorb, ULong delta,
//.. HChar* opname, IROp op
//.. )
//.. {
/* Lowest 64-bit lane only unary SSE operation, G = op(E). */
static UInt dis_SSE_E_to_G_unary_lo64 (
- Prefix pfx, UInt delta,
+ Prefix pfx, ULong delta,
HChar* opname, IROp op
)
{
//.. G = E `op` G (eLeft == True)
//.. */
//.. static UInt dis_SSEint_E_to_G(
-//.. UChar sorb, UInt delta,
+//.. UChar sorb, ULong delta,
//.. HChar* opname, IROp op,
//.. Bool eLeft
//.. )
//..
//.. /* Handles SSE 32F comparisons. */
//..
-//.. static UInt dis_SSEcmp_E_to_G ( UChar sorb, UInt delta,
+//.. static UInt dis_SSEcmp_E_to_G ( UChar sorb, ULong delta,
//.. HChar* opname, Bool all_lanes, Int sz )
//.. {
//.. HChar dis_buf[50];
//.. /* Vector by scalar shift of G by the amount specified at the bottom
//.. of E. */
//..
-//.. static UInt dis_SSE_shiftG_byE ( UChar sorb, UInt delta,
+//.. static UInt dis_SSE_shiftG_byE ( UChar sorb, ULong delta,
//.. HChar* opname, IROp op )
//.. {
//.. HChar dis_buf[50];
//.. /* Vector by scalar shift of E by an immediate byte. */
//..
//.. static
-//.. UInt dis_SSE_shiftE_imm ( UInt delta, HChar* opname, IROp op )
+//.. UInt dis_SSE_shiftE_imm ( ULong delta, HChar* opname, IROp op )
//.. {
//.. Bool shl, shr, sar;
//.. UChar rm = getUChar(delta);
//..
//.. goto decode_success;
//.. }
-//..
-//.. /* 66 0F 57 = XORPD -- G = G and E */
-//.. if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x57) {
-//.. delta = dis_SSE_E_to_G_all( sorb, delta+2, "xorpd", Iop_Xor128 );
-//.. goto decode_success;
-//.. }
-//..
+
+ /* 66 0F 57 = XORPD -- G = G xor E */
+ if (have66noF2noF3(pfx) && insn[0] == 0x0F && insn[1] == 0x57) {
+ delta = dis_SSE_E_to_G_all( pfx, delta+2, "xorpd", Iop_XorV128 );
+ 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,
//.. case 0xDD:
//.. case 0xDE:
//.. case 0xDF: {
-//.. UInt delta0 = delta;
+//.. ULong delta0 = delta;
//.. Bool decode_OK = False;
//.. delta = dis_FPU ( &decode_OK, sorb, delta );
//.. if (!decode_OK) {
//.. case 0xE1: /* PSRAgg (src)mmxreg-or-mem, (dst)mmxreg */
//.. case 0xE2:
//.. {
-//.. UInt delta0 = delta-1;
+//.. ULong delta0 = delta-1;
//.. Bool decode_OK = False;
//..
//.. /* If sz==2 this is SSE, and we assume sse idec has
//.. add_to_esp(env, 8);
//.. return freg;
//.. }
-//..
-//.. if (e->tag == Iex_LDle) {
-//.. X86AMode* am;
-//.. HReg res = newVRegF(env);
-//.. vassert(e->Iex.LDle.ty == Ity_F64);
-//.. am = iselIntExpr_AMode(env, e->Iex.LDle.addr);
-//.. addInstr(env, X86Instr_FpLdSt(True/*load*/, 8, res, am));
-//.. return res;
-//.. }
+
+ if (e->tag == Iex_LDle) {
+ AMD64AMode* am;
+ HReg res = newVRegV(env);
+ vassert(e->Iex.LDle.ty == Ity_F64);
+ am = iselIntExpr_AMode(env, e->Iex.LDle.addr);
+ addInstr(env, AMD64Instr_SseLdSt( True/*load*/, 8, res, am ));
+ return res;
+ }
if (e->tag == Iex_Get) {
AMD64AMode* am = AMD64AMode_IR( e->Iex.Get.offset,
/* DO NOT CALL THIS DIRECTLY */
static HReg iselVecExpr_wrk ( ISelEnv* env, IRExpr* e )
{
-//.. Bool arg1isEReg = False;
+ Bool arg1isEReg = False;
AMD64SseOp op = Asse_INVALID;
IRType ty = typeOfIRExpr(env->type_env,e);
vassert(e);
//..
//.. 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_XorV128: op = Asse_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;
//.. case Iop_QSub16Sx8: op = Xsse_QSUB16S; goto do_SseReRg;
//.. case Iop_QSub8Ux16: op = Xsse_QSUB8U; goto do_SseReRg;
//.. case Iop_QSub16Ux8: op = Xsse_QSUB16U; 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 (op != Xsse_OR && op != Xsse_AND && op != Xsse_XOR)
-//.. REQUIRE_SSE2;
-//.. 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;
-//.. }
-//..
+ do_SseReRg: {
+ HReg arg1 = iselVecExpr(env, e->Iex.Binop.arg1);
+ HReg arg2 = iselVecExpr(env, e->Iex.Binop.arg2);
+ HReg dst = newVRegV(env);
+ if (arg1isEReg) {
+ goto vec_fail; /* awaiting test case */
+ addInstr(env, mk_vMOVsd_RR(arg2, dst));
+ addInstr(env, AMD64Instr_SseReRg(op, arg1, dst));
+ } else {
+ addInstr(env, mk_vMOVsd_RR(arg1, dst));
+ addInstr(env, AMD64Instr_SseReRg(op, arg2, dst));
+ }
+ return dst;
+ }
+
//.. case Iop_ShlN16x8: op = Xsse_SHL16; goto do_SseShift;
//.. case Iop_ShlN32x4: op = Xsse_SHL32; goto do_SseShift;
//.. case Iop_ShlN64x2: op = Xsse_SHL64; goto do_SseShift;
//.. return dst;
//.. }
//..
-//.. vec_fail:
+ vec_fail:
vex_printf("iselVecExpr (amd64, subarch = %s): can't reduce\n",
LibVEX_ppVexSubArch(env->subarch));
ppIRExpr(e);