]> rtime.felk.cvut.cz Git - l4.git/blobdiff - l4/pkg/valgrind/src/valgrind-3.6.0-svn/VEX/priv/guest_x86_toIR.c
update
[l4.git] / l4 / pkg / valgrind / src / valgrind-3.6.0-svn / VEX / priv / guest_x86_toIR.c
index 761cd7f94fe7d044074547e939117abf6b997037..c23890802d2b68ae3e8b9d43077f35cd0d113e24 100644 (file)
@@ -998,7 +998,10 @@ static void setFlags_DEP1_DEP2_shift ( IROp    op32,
                                    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) )));
 }
 
 
@@ -2166,9 +2169,16 @@ UInt dis_movx_E_G ( UChar      sorb,
 {
    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)),
@@ -2181,10 +2191,16 @@ UInt dis_movx_E_G ( UChar      sorb,
       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)));
@@ -7947,15 +7963,15 @@ DisResult disInstr_X86_WRK (
       }
 #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);
@@ -7970,7 +7986,7 @@ DisResult disInstr_X86_WRK (
       /* 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);
@@ -7978,7 +7994,7 @@ DisResult disInstr_X86_WRK (
           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);
@@ -7986,7 +8002,7 @@ DisResult disInstr_X86_WRK (
           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);
@@ -7995,7 +8011,7 @@ DisResult disInstr_X86_WRK (
       }
 
       /* 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);
@@ -8166,6 +8182,7 @@ DisResult disInstr_X86_WRK (
 
       addr = disAMode ( &alen, sorb, delta+2, dis_buf );
       delta += 2+alen;
+      gen_SEGV_if_not_16_aligned(addr);
 
       DIP("fxsave %s\n", dis_buf);
 
@@ -8236,11 +8253,15 @@ DisResult disInstr_X86_WRK (
 
       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", 
@@ -8658,6 +8679,8 @@ DisResult disInstr_X86_WRK (
          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,
@@ -8676,6 +8699,8 @@ DisResult disInstr_X86_WRK (
          /* 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 );
@@ -8802,6 +8827,7 @@ DisResult disInstr_X86_WRK (
       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,
@@ -10027,6 +10053,8 @@ DisResult disInstr_X86_WRK (
          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,
@@ -10046,6 +10074,8 @@ DisResult disInstr_X86_WRK (
          /* 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 );
@@ -10108,6 +10138,7 @@ DisResult disInstr_X86_WRK (
       } 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);
       }
@@ -10319,6 +10350,7 @@ DisResult disInstr_X86_WRK (
       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)));
@@ -11621,6 +11653,7 @@ DisResult disInstr_X86_WRK (
          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,
@@ -12966,25 +12999,51 @@ DisResult disInstr_X86_WRK (
      }
      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 -------------------- */
 
@@ -14708,9 +14767,9 @@ DisResult disInstr_X86_WRK (
          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 -=-=-=-=-=-=-=-=-= */