widenUto32(mkexpr(resUS)))) );
/* Set NDEP even though it isn't used. This makes redundant-PUT
elimination of previous stores to this field work better. */
- stmt( IRStmt_Put( OFFB_CC_NDEP, mkU32(0) ));
+ stmt( IRStmt_Put( OFFB_CC_NDEP,
+ IRExpr_Mux0X( mkexpr(guard),
+ IRExpr_Get(OFFB_CC_NDEP,Ity_I32),
+ mkU32(0) )));
}
{
UChar rm = getIByte(delta);
if (epartIsReg(rm)) {
- putIReg(szd, gregOfRM(rm),
- unop(mkWidenOp(szs,szd,sign_extend),
- getIReg(szs,eregOfRM(rm))));
+ if (szd == szs) {
+ // mutant case. See #250799
+ putIReg(szd, gregOfRM(rm),
+ getIReg(szs,eregOfRM(rm)));
+ } else {
+ // normal case
+ putIReg(szd, gregOfRM(rm),
+ unop(mkWidenOp(szs,szd,sign_extend),
+ getIReg(szs,eregOfRM(rm))));
+ }
DIP("mov%c%c%c %s,%s\n", sign_extend ? 's' : 'z',
nameISize(szs), nameISize(szd),
nameIReg(szs,eregOfRM(rm)),
Int len;
HChar dis_buf[50];
IRTemp addr = disAMode ( &len, sorb, delta, dis_buf );
-
- putIReg(szd, gregOfRM(rm),
- unop(mkWidenOp(szs,szd,sign_extend),
- loadLE(szToITy(szs),mkexpr(addr))));
+ if (szd == szs) {
+ // mutant case. See #250799
+ putIReg(szd, gregOfRM(rm),
+ loadLE(szToITy(szs),mkexpr(addr)));
+ } else {
+ // normal case
+ putIReg(szd, gregOfRM(rm),
+ unop(mkWidenOp(szs,szd,sign_extend),
+ loadLE(szToITy(szs),mkexpr(addr))));
+ }
DIP("mov%c%c%c %s,%s\n", sign_extend ? 's' : 'z',
nameISize(szs), nameISize(szd),
dis_buf, nameIReg(szd,gregOfRM(rm)));
}
#if 1
/* To make a syscall in L4Re the guest must access its UTCB.
- * The address of the UTCB is stored in %gs, so we look for
+ * The address of the UTCB is stored in %fs, so we look for
* the following instructions:
- * 65 a1 00 00 00 00 mov %gs:0x0,%eax
- * 65 8b 0d 00 00 00 00 mov %gs:0x0,%ecx
- * 65 8b 15 00 00 00 00 mov %gs:0x0,%edx
- * 65 8b 3d 00 00 00 00 mov %gs:0x0,%edi
- * 65 8b 35 00 00 00 00 mov %gs:0x0,%esi
+ * 64 a1 00 00 00 00 mov %fs:0x0,%eax
+ * 64 8b 0d 00 00 00 00 mov %fs:0x0,%ecx
+ * 64 8b 15 00 00 00 00 mov %fs:0x0,%edx
+ * 64 8b 3d 00 00 00 00 mov %fs:0x0,%edi
+ * 64 8b 35 00 00 00 00 mov %fs:0x0,%esi
*/
- if (code[ 0] == 0x65 && code[ 1] == 0xa1 && code[ 2] == 0x0 &&
+ if (code[ 0] == 0x64 && code[ 1] == 0xa1 && code[ 2] == 0x0 &&
code[ 3] == 0x0 && code[ 4] == 0x0 && code[ 5] == 0x0) {
// printf("%x\n", code);
// printf("0x%x\n", guest_EIP_bbstart+delta);
/* utcb -> ebx */
// TODO implement me
/* utcb -> ecx */
- if (code[ 0] == 0x65 && code[ 1] == 0x8b && code[ 2] == 0x0d &&
+ if (code[ 0] == 0x64 && code[ 1] == 0x8b && code[ 2] == 0x0d &&
code[ 3] == 0x0 && code[ 4] == 0x0 && code[ 5] == 0x0 && code[ 6] == 0x0) {
delta += 7;
jmp_lit(Ijk_l4_utcb_ecx, guest_EIP_bbstart+delta);
goto decode_success;
}
/* utcb -> edx */
- if (code[ 0] == 0x65 && code[ 1] == 0x8b && code[ 2] == 0x15 &&
+ if (code[ 0] == 0x64 && code[ 1] == 0x8b && code[ 2] == 0x15 &&
code[ 3] == 0x0 && code[ 4] == 0x0 && code[ 5] == 0x0 && code[ 6] == 0x0) {
delta += 7;
jmp_lit(Ijk_l4_utcb_edx, guest_EIP_bbstart+delta);
goto decode_success;
}
/* utcb -> edi */
- if (code[ 0] == 0x65 && code[ 1] == 0x8b && code[ 2] == 0x3d &&
+ if (code[ 0] == 0x64 && code[ 1] == 0x8b && code[ 2] == 0x3d &&
code[ 3] == 0x0 && code[ 4] == 0x0 && code[ 5] == 0x0 && code[ 6] == 0x0) {
delta += 7;
jmp_lit(Ijk_l4_utcb_edi, guest_EIP_bbstart+delta);
}
/* utcb -> esi */
- if (code[ 0] == 0x65 && code[ 1] == 0x8b && code[ 2] == 0x35 &&
+ if (code[ 0] == 0x64 && code[ 1] == 0x8b && code[ 2] == 0x35 &&
code[ 3] == 0x0 && code[ 4] == 0x0 && code[ 5] == 0x0 && code[ 6] == 0x0) {
delta += 7;
jmp_lit(Ijk_l4_utcb_esi, guest_EIP_bbstart+delta);
addr = disAMode ( &alen, sorb, delta+2, dis_buf );
delta += 2+alen;
+ gen_SEGV_if_not_16_aligned(addr);
DIP("fxsave %s\n", dis_buf);
addr = disAMode ( &alen, sorb, delta+2, dis_buf );
delta += 2+alen;
+ gen_SEGV_if_not_16_aligned(addr);
DIP("fxrstor %s\n", dis_buf);
/* Uses dirty helper:
- void x86g_do_FXRSTOR ( VexGuestX86State*, UInt ) */
+ VexEmWarn x86g_do_FXRSTOR ( VexGuestX86State*, UInt )
+ NOTE:
+ the VexEmWarn value is simply ignored (unlike for FRSTOR)
+ */
d = unsafeIRDirty_0_N (
0/*regparms*/,
"x86g_dirtyhelper_FXRSTOR",
delta += 2+1;
} else {
addr = disAMode ( &alen, sorb, delta+2, dis_buf );
+ if (insn[1] == 0x28/*movaps*/)
+ gen_SEGV_if_not_16_aligned( addr );
putXMMReg( gregOfRM(modrm),
loadLE(Ity_V128, mkexpr(addr)) );
DIP("mov[ua]ps %s,%s\n", dis_buf,
/* fall through; awaiting test case */
} else {
addr = disAMode ( &alen, sorb, delta+2, dis_buf );
+ if (insn[1] == 0x29/*movaps*/)
+ gen_SEGV_if_not_16_aligned( addr );
storeLE( mkexpr(addr), getXMMReg(gregOfRM(modrm)) );
DIP("mov[ua]ps %s,%s\n", nameXMMReg(gregOfRM(modrm)),
dis_buf );
modrm = getIByte(delta+2);
if (!epartIsReg(modrm)) {
addr = disAMode ( &alen, sorb, delta+2, dis_buf );
+ gen_SEGV_if_not_16_aligned( addr );
storeLE( mkexpr(addr), getXMMReg(gregOfRM(modrm)) );
DIP("movntp%s %s,%s\n", sz==2 ? "d" : "s",
dis_buf,
delta += 2+1;
} else {
addr = disAMode ( &alen, sorb, delta+2, dis_buf );
+ if (insn[1] == 0x28/*movapd*/ || insn[1] == 0x6F/*movdqa*/)
+ gen_SEGV_if_not_16_aligned( addr );
putXMMReg( gregOfRM(modrm),
loadLE(Ity_V128, mkexpr(addr)) );
DIP("mov%s %s,%s\n", wot, dis_buf,
/* fall through; awaiting test case */
} else {
addr = disAMode ( &alen, sorb, delta+2, dis_buf );
+ if (insn[1] == 0x29/*movapd*/)
+ gen_SEGV_if_not_16_aligned( addr );
storeLE( mkexpr(addr), getXMMReg(gregOfRM(modrm)) );
DIP("mov%s %s,%s\n", wot, nameXMMReg(gregOfRM(modrm)),
dis_buf );
} else {
addr = disAMode( &alen, sorb, delta+2, dis_buf );
delta += 2+alen;
+ gen_SEGV_if_not_16_aligned( addr );
storeLE( mkexpr(addr), getXMMReg(gregOfRM(modrm)) );
DIP("movdqa %s, %s\n", nameXMMReg(gregOfRM(modrm)), dis_buf);
}
modrm = getIByte(delta+2);
if (sz == 2 && !epartIsReg(modrm)) {
addr = disAMode ( &alen, sorb, delta+2, dis_buf );
+ gen_SEGV_if_not_16_aligned( addr );
storeLE( mkexpr(addr), getXMMReg(gregOfRM(modrm)) );
DIP("movntdq %s,%s\n", dis_buf,
nameXMMReg(gregOfRM(modrm)));
delta += 3+1;
} else {
addr = disAMode ( &alen, sorb, delta+3, dis_buf );
+ gen_SEGV_if_not_16_aligned( addr );
assign( sV, loadLE(Ity_V128, mkexpr(addr)) );
DIP("movs%cdup %s,%s\n", isH ? 'h' : 'l',
dis_buf,
}
break;
-//-- case 0xD4: /* AAM */
-//-- case 0xD5: /* AAD */
-//-- d32 = getIByte(delta); delta++;
-//-- if (d32 != 10) VG_(core_panic)("disInstr: AAM/AAD but base not 10 !");
-//-- t1 = newTemp(cb);
-//-- uInstr2(cb, GET, 2, ArchReg, R_EAX, TempReg, t1);
-//-- /* Widen %AX to 32 bits, so it's all defined when we push it. */
-//-- uInstr1(cb, WIDEN, 4, TempReg, t1);
-//-- uWiden(cb, 2, False);
-//-- uInstr0(cb, CALLM_S, 0);
-//-- uInstr1(cb, PUSH, 4, TempReg, t1);
-//-- uInstr1(cb, CALLM, 0, Lit16,
-//-- opc == 0xD4 ? VGOFF_(helper_AAM) : VGOFF_(helper_AAD) );
-//-- uFlagsRWU(cb, FlagsEmpty, FlagsSZP, FlagsEmpty);
-//-- uInstr1(cb, POP, 4, TempReg, t1);
-//-- uInstr0(cb, CALLM_E, 0);
-//-- uInstr2(cb, PUT, 2, TempReg, t1, ArchReg, R_EAX);
-//-- DIP(opc == 0xD4 ? "aam\n" : "aad\n");
-//-- break;
+ case 0xD4: /* AAM */
+ case 0xD5: /* AAD */
+ d32 = getIByte(delta); delta++;
+ if (sz != 4 || d32 != 10) goto decode_failure;
+ t1 = newTemp(Ity_I32);
+ t2 = newTemp(Ity_I32);
+ /* Make up a 32-bit value (t1), with the old value of AX in the
+ bottom 16 bits, and the old OSZACP bitmask in the upper 16
+ bits. */
+ assign(t1,
+ binop(Iop_16HLto32,
+ unop(Iop_32to16,
+ mk_x86g_calculate_eflags_all()),
+ getIReg(2, R_EAX)
+ ));
+ /* Call the helper fn, to get a new AX and OSZACP value, and
+ poke both back into the guest state. Also pass the helper
+ the actual opcode so it knows which of the 2 instructions it
+ is doing the computation for. */
+ assign(t2,
+ mkIRExprCCall(
+ Ity_I32, 0/*regparm*/, "x86g_calculate_aad_aam",
+ &x86g_calculate_aad_aam,
+ mkIRExprVec_2( mkexpr(t1), mkU32( opc & 0xFF) )
+ ));
+ putIReg(2, R_EAX, unop(Iop_32to16, mkexpr(t2) ));
+
+ stmt( IRStmt_Put( OFFB_CC_OP, mkU32(X86G_CC_OP_COPY) ));
+ stmt( IRStmt_Put( OFFB_CC_DEP2, mkU32(0) ));
+ stmt( IRStmt_Put( OFFB_CC_DEP1,
+ binop(Iop_And32,
+ binop(Iop_Shr32, mkexpr(t2), mkU8(16)),
+ mkU32( X86G_CC_MASK_C | X86G_CC_MASK_P
+ | X86G_CC_MASK_A | X86G_CC_MASK_Z
+ | X86G_CC_MASK_S| X86G_CC_MASK_O )
+ )
+ )
+ );
+ /* Set NDEP even though it isn't used. This makes
+ redundant-PUT elimination of previous stores to this field
+ work better. */
+ stmt( IRStmt_Put( OFFB_CC_NDEP, mkU32(0) ));
+
+ DIP(opc == 0xD4 ? "aam\n" : "aad\n");
+ break;
/* ------------------------ CWD/CDQ -------------------- */
break;
case 0xBF: /* MOVSXw Ew,Gv */
- if (sz != 4)
+ if (sz != 4 && /* accept movsww, sigh, see #250799 */sz != 2)
goto decode_failure;
- delta = dis_movx_E_G ( sorb, delta, 2, 4, True );
+ delta = dis_movx_E_G ( sorb, delta, 2, sz, True );
break;
//-- /* =-=-=-=-=-=-=-=-=-=-= MOVNTI -=-=-=-=-=-=-=-=-= */