Implement MOVBE. Fixes #302287.
git-svn-id: svn://svn.valgrind.org/vex/trunk@2435 8f6e269a-dfd6-0310-a8e1-e2731360e62c
diff --git a/priv/guest_amd64_toIR.c b/priv/guest_amd64_toIR.c
index 56a0249..31320d9 100644
--- a/priv/guest_amd64_toIR.c
+++ b/priv/guest_amd64_toIR.c
@@ -19559,6 +19559,83 @@
/*--- ---*/
/*------------------------------------------------------------*/
+static IRTemp math_BSWAP ( IRTemp t1, IRType ty )
+{
+ IRTemp t2 = newTemp(ty);
+ if (ty == Ity_I64) {
+ IRTemp m8 = newTemp(Ity_I64);
+ IRTemp s8 = newTemp(Ity_I64);
+ IRTemp m16 = newTemp(Ity_I64);
+ IRTemp s16 = newTemp(Ity_I64);
+ IRTemp m32 = newTemp(Ity_I64);
+ assign( m8, mkU64(0xFF00FF00FF00FF00ULL) );
+ assign( s8,
+ binop(Iop_Or64,
+ binop(Iop_Shr64,
+ binop(Iop_And64,mkexpr(t1),mkexpr(m8)),
+ mkU8(8)),
+ binop(Iop_And64,
+ binop(Iop_Shl64,mkexpr(t1),mkU8(8)),
+ mkexpr(m8))
+ )
+ );
+
+ assign( m16, mkU64(0xFFFF0000FFFF0000ULL) );
+ assign( s16,
+ binop(Iop_Or64,
+ binop(Iop_Shr64,
+ binop(Iop_And64,mkexpr(s8),mkexpr(m16)),
+ mkU8(16)),
+ binop(Iop_And64,
+ binop(Iop_Shl64,mkexpr(s8),mkU8(16)),
+ mkexpr(m16))
+ )
+ );
+
+ assign( m32, mkU64(0xFFFFFFFF00000000ULL) );
+ assign( t2,
+ binop(Iop_Or64,
+ binop(Iop_Shr64,
+ binop(Iop_And64,mkexpr(s16),mkexpr(m32)),
+ mkU8(32)),
+ binop(Iop_And64,
+ binop(Iop_Shl64,mkexpr(s16),mkU8(32)),
+ mkexpr(m32))
+ )
+ );
+ return t2;
+ }
+ if (ty == Ity_I32) {
+ assign( t2,
+ binop(
+ Iop_Or32,
+ binop(Iop_Shl32, mkexpr(t1), mkU8(24)),
+ binop(
+ Iop_Or32,
+ binop(Iop_And32, binop(Iop_Shl32, mkexpr(t1), mkU8(8)),
+ mkU32(0x00FF0000)),
+ binop(Iop_Or32,
+ binop(Iop_And32, binop(Iop_Shr32, mkexpr(t1), mkU8(8)),
+ mkU32(0x0000FF00)),
+ binop(Iop_And32, binop(Iop_Shr32, mkexpr(t1), mkU8(24)),
+ mkU32(0x000000FF) )
+ )))
+ );
+ return t2;
+ }
+ if (ty == Ity_I16) {
+ assign(t2,
+ binop(Iop_Or16,
+ binop(Iop_Shl16, mkexpr(t1), mkU8(8)),
+ binop(Iop_Shr16, mkexpr(t1), mkU8(8)) ));
+ return t2;
+ }
+ vassert(0);
+ /*NOTREACHED*/
+ return IRTemp_INVALID;
+}
+
+
__attribute__((noinline))
static
Long dis_ESC_0F (
@@ -20162,71 +20239,17 @@
8. */
if (sz == 4) {
t1 = newTemp(Ity_I32);
- t2 = newTemp(Ity_I32);
assign( t1, getIRegRexB(4, pfx, opc-0xC8) );
- assign( t2,
- binop(Iop_Or32,
- binop(Iop_Shl32, mkexpr(t1), mkU8(24)),
- binop(Iop_Or32,
- binop(Iop_And32, binop(Iop_Shl32, mkexpr(t1), mkU8(8)),
- mkU32(0x00FF0000)),
- binop(Iop_Or32,
- binop(Iop_And32, binop(Iop_Shr32, mkexpr(t1), mkU8(8)),
- mkU32(0x0000FF00)),
- binop(Iop_And32, binop(Iop_Shr32, mkexpr(t1), mkU8(24)),
- mkU32(0x000000FF) )
- )))
- );
+ t2 = math_BSWAP( t1, Ity_I32 );
putIRegRexB(4, pfx, opc-0xC8, mkexpr(t2));
DIP("bswapl %s\n", nameIRegRexB(4, pfx, opc-0xC8));
return delta;
}
if (sz == 8) {
- IRTemp m8 = newTemp(Ity_I64);
- IRTemp s8 = newTemp(Ity_I64);
- IRTemp m16 = newTemp(Ity_I64);
- IRTemp s16 = newTemp(Ity_I64);
- IRTemp m32 = newTemp(Ity_I64);
t1 = newTemp(Ity_I64);
t2 = newTemp(Ity_I64);
assign( t1, getIRegRexB(8, pfx, opc-0xC8) );
-
- assign( m8, mkU64(0xFF00FF00FF00FF00ULL) );
- assign( s8,
- binop(Iop_Or64,
- binop(Iop_Shr64,
- binop(Iop_And64,mkexpr(t1),mkexpr(m8)),
- mkU8(8)),
- binop(Iop_And64,
- binop(Iop_Shl64,mkexpr(t1),mkU8(8)),
- mkexpr(m8))
- )
- );
-
- assign( m16, mkU64(0xFFFF0000FFFF0000ULL) );
- assign( s16,
- binop(Iop_Or64,
- binop(Iop_Shr64,
- binop(Iop_And64,mkexpr(s8),mkexpr(m16)),
- mkU8(16)),
- binop(Iop_And64,
- binop(Iop_Shl64,mkexpr(s8),mkU8(16)),
- mkexpr(m16))
- )
- );
-
- assign( m32, mkU64(0xFFFFFFFF00000000ULL) );
- assign( t2,
- binop(Iop_Or64,
- binop(Iop_Shr64,
- binop(Iop_And64,mkexpr(s16),mkexpr(m32)),
- mkU8(32)),
- binop(Iop_And64,
- binop(Iop_Shl64,mkexpr(s16),mkU8(32)),
- mkexpr(m32))
- )
- );
-
+ t2 = math_BSWAP( t1, Ity_I64 );
putIRegRexB(8, pfx, opc-0xC8, mkexpr(t2));
DIP("bswapq %s\n", nameIRegRexB(8, pfx, opc-0xC8));
return delta;
@@ -20400,6 +20423,34 @@
delta++;
switch (opc) {
+ case 0xF0: /* MOVBE m16/32/64(E), r16/32/64(G) */
+ case 0xF1: { /* MOVBE r16/32/64(G), m16/32/64(E) */
+ IRTemp addr = IRTemp_INVALID;
+ UChar modrm = 0;
+ Int alen = 0;
+ HChar dis_buf[50];
+ if (haveF2orF3(pfx) || haveVEX(pfx)) goto decode_failure;
+ if (sz != 2 && sz != 4 && sz != 8) goto decode_failure;
+ modrm = getUChar(delta);
+ if (epartIsReg(modrm)) break;
+ addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 0 );
+ delta += alen;
+ IRType ty = szToITy(sz);
+ IRTemp src = newTemp(ty);
+ if (opc == 0xF0) { /* LOAD */
+ assign(src, loadLE(ty, mkexpr(addr)));
+ IRTemp dst = math_BSWAP(src, ty);
+ putIRegG(sz, pfx, modrm, mkexpr(dst));
+ DIP("movbe %s,%s\n", dis_buf, nameIRegG(sz, pfx, modrm));
+ } else { /* STORE */
+ assign(src, getIRegG(sz, pfx, modrm));
+ IRTemp dst = math_BSWAP(src, ty);
+ storeLE(mkexpr(addr), mkexpr(dst));
+ DIP("movbe %s,%s\n", nameIRegG(sz, pfx, modrm), dis_buf);
+ }
+ return delta;
+ }
+
default:
break;
@@ -20425,7 +20476,7 @@
return delta;
}
- //decode_failure:
+ decode_failure:
return deltaIN; /* fail */
}