]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Merge from trunk, r2078 (Add support for AAD and AAM (base 10 only).)
authorJulian Seward <jseward@acm.org>
Mon, 14 Feb 2011 13:33:36 +0000 (13:33 +0000)
committerJulian Seward <jseward@acm.org>
Mon, 14 Feb 2011 13:33:36 +0000 (13:33 +0000)
git-svn-id: svn://svn.valgrind.org/vex/branches/VEX_3_6_BRANCH@2094

VEX/priv/guest_x86_defs.h
VEX/priv/guest_x86_helpers.c
VEX/priv/guest_x86_toIR.c

index 09d647a9d9db8dbed9332493effde46387337fe5..96335335f19cf5177b8e0fca39f04f1a3dffb7b4 100644 (file)
@@ -108,6 +108,8 @@ extern ULong x86g_calculate_RCL (
 
 extern UInt x86g_calculate_daa_das_aaa_aas ( UInt AX_and_flags, UInt opcode );
 
+extern UInt x86g_calculate_aad_aam ( UInt AX_and_flags, UInt opcode );
+
 extern ULong x86g_check_fldcw ( UInt fpucw );
 
 extern UInt  x86g_create_fpucw ( UInt fpround );
index 7aa7a3392a15400c3503f8ff81bc3e2413cbbb4b..c538c076621e57732cd5eba4f1c108c36904fb96 100644 (file)
@@ -2109,6 +2109,51 @@ UInt x86g_calculate_daa_das_aaa_aas ( UInt flags_and_AX, UInt opcode )
    return result;
 }
 
+UInt x86g_calculate_aad_aam ( UInt flags_and_AX, UInt opcode )
+{
+   UInt r_AL = (flags_and_AX >> 0) & 0xFF;
+   UInt r_AH = (flags_and_AX >> 8) & 0xFF;
+   UInt r_O  = (flags_and_AX >> (16 + X86G_CC_SHIFT_O)) & 1;
+   UInt r_S  = (flags_and_AX >> (16 + X86G_CC_SHIFT_S)) & 1;
+   UInt r_Z  = (flags_and_AX >> (16 + X86G_CC_SHIFT_Z)) & 1;
+   UInt r_A  = (flags_and_AX >> (16 + X86G_CC_SHIFT_A)) & 1;
+   UInt r_C  = (flags_and_AX >> (16 + X86G_CC_SHIFT_C)) & 1;
+   UInt r_P  = (flags_and_AX >> (16 + X86G_CC_SHIFT_P)) & 1;
+   UInt result = 0;
+
+   switch (opcode) {
+      case 0xD4: { /* AAM */
+         r_AH = r_AL / 10;
+         r_AL = r_AL % 10;
+         break;
+      }
+      case 0xD5: { /* AAD */
+         r_AL = ((r_AH * 10) + r_AL) & 0xff;
+         r_AH = 0;
+         break;
+      }
+      default:
+         vassert(0);
+   }
+
+   r_O = 0; /* let's say (undefined) */
+   r_C = 0; /* let's say (undefined) */
+   r_A = 0; /* let's say (undefined) */
+   r_S = (r_AL & 0x80) ? 1 : 0;
+   r_Z = (r_AL == 0) ? 1 : 0;
+   r_P = calc_parity_8bit( r_AL );
+
+   result =   ( (r_O & 1) << (16 + X86G_CC_SHIFT_O) )
+            | ( (r_S & 1) << (16 + X86G_CC_SHIFT_S) )
+            | ( (r_Z & 1) << (16 + X86G_CC_SHIFT_Z) )
+            | ( (r_A & 1) << (16 + X86G_CC_SHIFT_A) )
+            | ( (r_C & 1) << (16 + X86G_CC_SHIFT_C) )
+            | ( (r_P & 1) << (16 + X86G_CC_SHIFT_P) )
+            | ( (r_AH & 0xFF) << 8 )
+            | ( (r_AL & 0xFF) << 0 );
+   return result;
+}
+
 
 /* CALLED FROM GENERATED CODE */
 /* DIRTY HELPER (non-referentially-transparent) */
index d03b6f1fa269bd6b2a94c6ca49b30f63eef2f30a..50a9e327e7c744078c96c5ed5e711a50322817f5 100644 (file)
@@ -12907,25 +12907,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 -------------------- */