]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Make rflag-thunk evaluation work (ghelpers); fix various missing cases
authorJulian Seward <jseward@acm.org>
Mon, 7 Feb 2005 18:55:29 +0000 (18:55 +0000)
committerJulian Seward <jseward@acm.org>
Mon, 7 Feb 2005 18:55:29 +0000 (18:55 +0000)
(toIR, isel).

git-svn-id: svn://svn.valgrind.org/vex/trunk@866

VEX/priv/guest-amd64/ghelpers.c
VEX/priv/guest-amd64/toIR.c
VEX/priv/host-amd64/isel.c

index 4d32ec07168f1b4f16c3460bf13dd7c4a1ce610a..b5ff928f56b2e6abe2a86ee5d116c30cf627bc15 100644 (file)
 #include "guest-amd64/gdefs.h"
 
 
-ULong amd64g_calculate_rflags_all ( 
-                ULong cc_op, 
-                ULong cc_dep1, ULong cc_dep2, ULong cc_ndep 
-             )
+
+/* This file contains helper functions for amd64 guest code.
+   Calls to these functions are generated by the back end.
+   These calls are of course in the host machine code and 
+   this file will be compiled to host machine code, so that
+   all makes sense.  
+
+   Only change the signatures of these helper functions very
+   carefully.  If you change the signature here, you'll have to change
+   the parameters passed to it in the IR calls constructed by
+   guest-amd64/toIR.c.
+
+   The convention used is that all functions called from generated
+   code are named amd64g_<something>, and any function whose name lacks
+   that prefix is not called from generated code.  Note that some
+   LibVEX_* functions can however be called by VEX's client, but that
+   is not the same as calling them from VEX-generated code.
+*/
+
+
+/* Set to 1 to get detailed profiling info about use of the flag
+   machinery. */
+#define PROFILE_RFLAGS 0
+
+
+/*---------------------------------------------------------------*/
+/*--- %rflags run-time helpers.                               ---*/
+/*---------------------------------------------------------------*/
+
+static const UChar parity_table[256] = {
+    AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0,
+    0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P,
+    0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P,
+    AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0,
+    0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P,
+    AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0,
+    AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0,
+    0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P,
+    0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P,
+    AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0,
+    AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0,
+    0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P,
+    AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0,
+    0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P,
+    0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P,
+    AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0,
+    0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P,
+    AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0,
+    AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0,
+    0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P,
+    AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0,
+    0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P,
+    0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P,
+    AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0,
+    AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0,
+    0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P,
+    0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P,
+    AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0,
+    0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P,
+    AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0,
+    AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0,
+    0, AMD64G_CC_MASK_P, AMD64G_CC_MASK_P, 0, AMD64G_CC_MASK_P, 0, 0, AMD64G_CC_MASK_P,
+};
+
+/* n must be a constant to be efficient */
+inline static Long lshift ( Long x, Int n )
+{
+   if (n >= 0)
+      return x << n;
+   else
+      return x >> (-n);
+}
+
+
+#define PREAMBLE(__data_bits)                                  \
+   /* const */ ULong DATA_MASK                                         \
+      = __data_bits==8                                          \
+           ? 0xFFULL                                           \
+           : (__data_bits==16                                   \
+                ? 0xFFFFULL                                    \
+                : (__data_bits==32                              \
+                     ? 0xFFFFFFFFULL                            \
+                     : 0xFFFFFFFFFFFFFFFFULL));                 \
+   /* const */ ULong SIGN_MASK = 1ULL << (__data_bits - 1);     \
+   /* const */ ULong CC_DEP1 = cc_dep1_formal;                 \
+   /* const */ ULong CC_DEP2 = cc_dep2_formal;                 \
+   /* const */ ULong CC_NDEP = cc_ndep_formal;                 \
+   /* Four bogus assignments, which hopefully gcc can     */   \
+   /* optimise away, and which stop it complaining about  */   \
+   /* unused variables.                                   */   \
+   SIGN_MASK = SIGN_MASK;                                      \
+   DATA_MASK = DATA_MASK;                                      \
+   CC_DEP2 = CC_DEP2;                                          \
+   CC_NDEP = CC_NDEP;
+
+
+/*-------------------------------------------------------------*/
+
+#define ACTIONS_ADD(DATA_BITS,DATA_UTYPE)                      \
+{                                                              \
+   PREAMBLE(DATA_BITS);                                                \
+   { Long cf, pf, af, zf, sf, of;                              \
+     Long argL, argR, res;                                     \
+     argL = CC_DEP1;                                           \
+     argR = CC_DEP2;                                           \
+     res  = argL + argR;                                       \
+     cf = (DATA_UTYPE)res < (DATA_UTYPE)argL;                  \
+     pf = parity_table[(UChar)res];                            \
+     af = (res ^ argL ^ argR) & 0x10;                          \
+     zf = ((DATA_UTYPE)res == 0) << 6;                         \
+     sf = lshift(res, 8 - DATA_BITS) & 0x80;                   \
+     of = lshift((argL ^ argR ^ -1) & (argL ^ res),            \
+                 12 - DATA_BITS) & AMD64G_CC_MASK_O;           \
+     return cf | pf | af | zf | sf | of;                       \
+   }                                                           \
+}
+
+/*-------------------------------------------------------------*/
+
+#define ACTIONS_SUB(DATA_BITS,DATA_UTYPE)                      \
+{                                                              \
+   PREAMBLE(DATA_BITS);                                                \
+   { Long cf, pf, af, zf, sf, of;                              \
+     Long argL, argR, res;                                     \
+     argL = CC_DEP1;                                           \
+     argR = CC_DEP2;                                           \
+     res  = argL - argR;                                       \
+     cf = (DATA_UTYPE)argL < (DATA_UTYPE)argR;                 \
+     pf = parity_table[(UChar)res];                            \
+     af = (res ^ argL ^ argR) & 0x10;                          \
+     zf = ((DATA_UTYPE)res == 0) << 6;                         \
+     sf = lshift(res, 8 - DATA_BITS) & 0x80;                   \
+     of = lshift((argL ^ argR) & (argL ^ res),                 \
+                 12 - DATA_BITS) & AMD64G_CC_MASK_O;           \
+     return cf | pf | af | zf | sf | of;                       \
+   }                                                           \
+}
+
+/*-------------------------------------------------------------*/
+
+#define ACTIONS_ADC(DATA_BITS,DATA_UTYPE)                      \
+{                                                              \
+   PREAMBLE(DATA_BITS);                                                \
+   { Long cf, pf, af, zf, sf, of;                              \
+     Long argL, argR, oldC, res;                               \
+     oldC = CC_NDEP & AMD64G_CC_MASK_C;                                \
+     argL = CC_DEP1;                                           \
+     argR = CC_DEP2 ^ oldC;                                    \
+     res  = (argL + argR) + oldC;                              \
+     if (oldC)                                                 \
+        cf = (DATA_UTYPE)res <= (DATA_UTYPE)argL;              \
+     else                                                      \
+        cf = (DATA_UTYPE)res < (DATA_UTYPE)argL;               \
+     pf = parity_table[(UChar)res];                            \
+     af = (res ^ argL ^ argR) & 0x10;                          \
+     zf = ((DATA_UTYPE)res == 0) << 6;                         \
+     sf = lshift(res, 8 - DATA_BITS) & 0x80;                   \
+     of = lshift((argL ^ argR ^ -1) & (argL ^ res),            \
+                  12 - DATA_BITS) & AMD64G_CC_MASK_O;          \
+     return cf | pf | af | zf | sf | of;                       \
+   }                                                           \
+}
+
+/*-------------------------------------------------------------*/
+
+#define ACTIONS_SBB(DATA_BITS,DATA_UTYPE)                      \
+{                                                              \
+   PREAMBLE(DATA_BITS);                                                \
+   { Long cf, pf, af, zf, sf, of;                              \
+     Long argL, argR, oldC, res;                               \
+     oldC = CC_NDEP & AMD64G_CC_MASK_C;                                \
+     argL = CC_DEP1;                                           \
+     argR = CC_DEP2 ^ oldC;                                    \
+     res  = (argL - argR) - oldC;                              \
+     if (oldC)                                                 \
+        cf = (DATA_UTYPE)argL <= (DATA_UTYPE)argR;             \
+     else                                                      \
+        cf = (DATA_UTYPE)argL < (DATA_UTYPE)argR;              \
+     pf = parity_table[(UChar)res];                            \
+     af = (res ^ argL ^ argR) & 0x10;                          \
+     zf = ((DATA_UTYPE)res == 0) << 6;                         \
+     sf = lshift(res, 8 - DATA_BITS) & 0x80;                   \
+     of = lshift((argL ^ argR) & (argL ^ res),                         \
+                 12 - DATA_BITS) & AMD64G_CC_MASK_O;           \
+     return cf | pf | af | zf | sf | of;                       \
+   }                                                           \
+}
+
+/*-------------------------------------------------------------*/
+
+#define ACTIONS_LOGIC(DATA_BITS,DATA_UTYPE)                    \
+{                                                              \
+   PREAMBLE(DATA_BITS);                                                \
+   { Long cf, pf, af, zf, sf, of;                              \
+     cf = 0;                                                   \
+     pf = parity_table[(UChar)CC_DEP1];                                \
+     af = 0;                                                   \
+     zf = ((DATA_UTYPE)CC_DEP1 == 0) << 6;                     \
+     sf = lshift(CC_DEP1, 8 - DATA_BITS) & 0x80;               \
+     of = 0;                                                   \
+     return cf | pf | af | zf | sf | of;                       \
+   }                                                           \
+}
+
+/*-------------------------------------------------------------*/
+
+#define ACTIONS_INC(DATA_BITS,DATA_UTYPE)                      \
+{                                                              \
+   PREAMBLE(DATA_BITS);                                                \
+   { Long cf, pf, af, zf, sf, of;                              \
+     Long argL, argR, res;                                     \
+     res  = CC_DEP1;                                           \
+     argL = res - 1;                                           \
+     argR = 1;                                                 \
+     cf = CC_NDEP & AMD64G_CC_MASK_C;                          \
+     pf = parity_table[(UChar)res];                            \
+     af = (res ^ argL ^ argR) & 0x10;                          \
+     zf = ((DATA_UTYPE)res == 0) << 6;                         \
+     sf = lshift(res, 8 - DATA_BITS) & 0x80;                   \
+     of = ((res & DATA_MASK) == SIGN_MASK) << 11;              \
+     return cf | pf | af | zf | sf | of;                       \
+   }                                                           \
+}
+
+/*-------------------------------------------------------------*/
+
+#define ACTIONS_DEC(DATA_BITS,DATA_UTYPE)                      \
+{                                                              \
+   PREAMBLE(DATA_BITS);                                                \
+   { Long cf, pf, af, zf, sf, of;                              \
+     Long argL, argR, res;                                     \
+     res  = CC_DEP1;                                           \
+     argL = res + 1;                                           \
+     argR = 1;                                                 \
+     cf = CC_NDEP & AMD64G_CC_MASK_C;                          \
+     pf = parity_table[(UChar)res];                            \
+     af = (res ^ argL ^ argR) & 0x10;                          \
+     zf = ((DATA_UTYPE)res == 0) << 6;                         \
+     sf = lshift(res, 8 - DATA_BITS) & 0x80;                   \
+     of = ((res & DATA_MASK)                                   \
+          == ((ULong)SIGN_MASK - 1)) << 11;                    \
+     return cf | pf | af | zf | sf | of;                       \
+   }                                                           \
+}
+
+/*-------------------------------------------------------------*/
+
+#define ACTIONS_SHL(DATA_BITS,DATA_UTYPE)                      \
+{                                                              \
+   PREAMBLE(DATA_BITS);                                                \
+   { Long cf, pf, af, zf, sf, of;                              \
+     cf = (CC_DEP2 >> (DATA_BITS - 1)) & AMD64G_CC_MASK_C;     \
+     pf = parity_table[(UChar)CC_DEP1];                                \
+     af = 0; /* undefined */                                   \
+     zf = ((DATA_UTYPE)CC_DEP1 == 0) << 6;                     \
+     sf = lshift(CC_DEP1, 8 - DATA_BITS) & 0x80;               \
+     /* of is defined if shift count == 1 */                   \
+     of = lshift(CC_DEP2 ^ CC_DEP1, 12 - DATA_BITS)            \
+          & AMD64G_CC_MASK_O;                                  \
+     return cf | pf | af | zf | sf | of;                       \
+   }                                                           \
+}
+
+/*-------------------------------------------------------------*/
+
+#define ACTIONS_SHR(DATA_BITS,DATA_UTYPE)                      \
+{                                                              \
+   PREAMBLE(DATA_BITS);                                        \
+   { Long cf, pf, af, zf, sf, of;                              \
+     cf = CC_DEP2 & 1;                                         \
+     pf = parity_table[(UChar)CC_DEP1];                                \
+     af = 0; /* undefined */                                   \
+     zf = ((DATA_UTYPE)CC_DEP1 == 0) << 6;                     \
+     sf = lshift(CC_DEP1, 8 - DATA_BITS) & 0x80;               \
+     /* of is defined if shift count == 1 */                   \
+     of = lshift(CC_DEP2 ^ CC_DEP1, 12 - DATA_BITS)            \
+          & AMD64G_CC_MASK_O;                                  \
+     return cf | pf | af | zf | sf | of;                       \
+   }                                                           \
+}
+
+/*-------------------------------------------------------------*/
+
+/* ROL: cf' = lsb(result).  of' = msb(result) ^ lsb(result). */
+/* DEP1 = result, NDEP = old flags */
+#define ACTIONS_ROL(DATA_BITS,DATA_UTYPE)                      \
+{                                                              \
+   PREAMBLE(DATA_BITS);                                                \
+   { Long fl                                                   \
+        = (CC_NDEP & ~(AMD64G_CC_MASK_O | AMD64G_CC_MASK_C))   \
+          | (AMD64G_CC_MASK_C & CC_DEP1)                               \
+          | (AMD64G_CC_MASK_O & (lshift(CC_DEP1,               \
+                                      11-(DATA_BITS-1))        \
+                     ^ lshift(CC_DEP1, 11)));                  \
+     return fl;                                                        \
+   }                                                           \
+}
+
+/*-------------------------------------------------------------*/
+
+/* ROR: cf' = msb(result).  of' = msb(result) ^ msb-1(result). */
+/* DEP1 = result, NDEP = old flags */
+#define ACTIONS_ROR(DATA_BITS,DATA_UTYPE)                      \
+{                                                              \
+   PREAMBLE(DATA_BITS);                                                \
+   { Long fl                                                   \
+        = (CC_NDEP & ~(AMD64G_CC_MASK_O | AMD64G_CC_MASK_C))   \
+          | (AMD64G_CC_MASK_C & (CC_DEP1 >> (DATA_BITS-1)))    \
+          | (AMD64G_CC_MASK_O & (lshift(CC_DEP1,               \
+                                      11-(DATA_BITS-1))        \
+                     ^ lshift(CC_DEP1, 11-(DATA_BITS-1)+1)));  \
+     return fl;                                                        \
+   }                                                           \
+}
+
+/*-------------------------------------------------------------*/
+
+#define ACTIONS_UMUL(DATA_BITS,DATA_UTYPE,DATA_U2TYPE)          \
+{                                                               \
+   PREAMBLE(DATA_BITS);                                         \
+   { Long cf, pf, af, zf, sf, of;                               \
+     DATA_UTYPE  hi;                                            \
+     DATA_UTYPE  lo = ((DATA_UTYPE)CC_DEP1)                     \
+                      * ((DATA_UTYPE)CC_DEP2);                  \
+     DATA_U2TYPE rr = ((DATA_U2TYPE)((DATA_UTYPE)CC_DEP1))      \
+                      * ((DATA_U2TYPE)((DATA_UTYPE)CC_DEP2));   \
+     hi = (DATA_UTYPE)(rr >>/*u*/ DATA_BITS);                   \
+     cf = (hi != 0);                                            \
+     pf = parity_table[(UChar)lo];                              \
+     af = 0; /* undefined */                                    \
+     zf = (lo == 0) << 6;                                       \
+     sf = lshift(lo, 8 - DATA_BITS) & 0x80;                     \
+     of = cf << 11;                                             \
+     return cf | pf | af | zf | sf | of;                        \
+   }                                                           \
+}
+
+/*-------------------------------------------------------------*/
+
+#define ACTIONS_SMUL(DATA_BITS,DATA_STYPE,DATA_S2TYPE)          \
+{                                                               \
+   PREAMBLE(DATA_BITS);                                         \
+   { Long cf, pf, af, zf, sf, of;                               \
+     DATA_STYPE  hi;                                            \
+     DATA_STYPE  lo = ((DATA_STYPE)CC_DEP1)                     \
+                      * ((DATA_STYPE)CC_DEP2);                  \
+     DATA_S2TYPE rr = ((DATA_S2TYPE)((DATA_STYPE)CC_DEP1))      \
+                      * ((DATA_S2TYPE)((DATA_STYPE)CC_DEP2));   \
+     hi = (DATA_STYPE)(rr >>/*s*/ DATA_BITS);                   \
+     cf = (hi != (lo >>/*s*/ (DATA_BITS-1)));                   \
+     pf = parity_table[(UChar)lo];                              \
+     af = 0; /* undefined */                                    \
+     zf = (lo == 0) << 6;                                       \
+     sf = lshift(lo, 8 - DATA_BITS) & 0x80;                     \
+     of = cf << 11;                                             \
+     return cf | pf | af | zf | sf | of;                        \
+   }                                                           \
+}
+
+
+#if PROFILE_EFLAGS
+
+static Bool initted     = False;
+
+/* C flag, fast route */
+static UInt tabc_fast[AMD64G_CC_OP_NUMBER];
+/* C flag, slow route */
+static UInt tabc_slow[AMD64G_CC_OP_NUMBER];
+/* table for calculate_cond */
+static UInt tab_cond[AMD64G_CC_OP_NUMBER][16];
+/* total entry counts for calc_all, calc_c, calc_cond. */
+static UInt n_calc_all  = 0;
+static UInt n_calc_c    = 0;
+static UInt n_calc_cond = 0;
+
+#define SHOW_COUNTS_NOW (0 == (0x3FFFFF & (n_calc_all+n_calc_c+n_calc_cond)))
+
+
+static void showCounts ( void )
+{
+   Int op, co;
+   Char ch;
+   vex_printf("\nTotal calls: calc_all=%d   calc_cond=%d   calc_c=%d\n",
+              n_calc_all, n_calc_cond, n_calc_c);
+
+   vex_printf("      cSLOW  cFAST    O   NO    B   NB    Z   NZ   BE  NBE"
+              "    S   NS    P   NP    L   NL   LE  NLE\n");
+   vex_printf("     -----------------------------------------------------"
+              "----------------------------------------\n");
+   for (op = 0; op < AMD64G_CC_OP_NUMBER; op++) {
+
+      ch = ' ';
+      if (op > 0 && (op-1) % 3 == 0) 
+         ch = 'B';
+      if (op > 0 && (op-1) % 3 == 1) 
+         ch = 'W';
+      if (op > 0 && (op-1) % 3 == 2) 
+         ch = 'L';
+
+      vex_printf("%2d%c: ", op, ch);
+      vex_printf("%6d ", tabc_slow[op]);
+      vex_printf("%6d ", tabc_fast[op]);
+      for (co = 0; co < 16; co++) {
+         Int n = tab_cond[op][co];
+         if (n >= 1000) {
+            vex_printf(" %3dK", n / 1000);
+         } else 
+         if (n >= 0) {
+            vex_printf(" %3d ", n );
+         } else {
+            vex_printf("     ");
+         }
+      }
+      vex_printf("\n");
+   }
+   vex_printf("\n");
+}
+
+static void initCounts ( void )
+{
+   Int op, co;
+   initted = True;
+   for (op = 0; op < AMD64G_CC_OP_NUMBER; op++) {
+      tabc_fast[op] = tabc_slow[op] = 0;
+      for (co = 0; co < 16; co++)
+         tab_cond[op][co] = 0;
+   }
+}
+
+#endif /* PROFILE_EFLAGS */
+
+
+/* CALLED FROM GENERATED CODE: CLEAN HELPER */
+/* Calculate all the 6 flags from the supplied thunk parameters.
+   Worker function, not directly called from generated code. */
+static
+ULong amd64g_calculate_rflags_all_WRK ( ULong cc_op, 
+                                        ULong cc_dep1_formal, 
+                                        ULong cc_dep2_formal,
+                                        ULong cc_ndep_formal )
 {
-  vassert(0);
-  return 0;
+   switch (cc_op) {
+      case AMD64G_CC_OP_COPY:
+         return cc_dep1_formal
+                & (AMD64G_CC_MASK_O | AMD64G_CC_MASK_S | AMD64G_CC_MASK_Z 
+                   | AMD64G_CC_MASK_A | AMD64G_CC_MASK_C | AMD64G_CC_MASK_P);
+
+      case AMD64G_CC_OP_ADDB:   ACTIONS_ADD( 8,  UChar  );
+      case AMD64G_CC_OP_ADDW:   ACTIONS_ADD( 16, UShort );
+      case AMD64G_CC_OP_ADDL:   ACTIONS_ADD( 32, UInt   );
+
+      case AMD64G_CC_OP_ADCB:   ACTIONS_ADC( 8,  UChar  );
+      case AMD64G_CC_OP_ADCW:   ACTIONS_ADC( 16, UShort );
+      case AMD64G_CC_OP_ADCL:   ACTIONS_ADC( 32, UInt   );
+
+      case AMD64G_CC_OP_SUBB:   ACTIONS_SUB(  8, UChar  );
+      case AMD64G_CC_OP_SUBW:   ACTIONS_SUB( 16, UShort );
+      case AMD64G_CC_OP_SUBL:   ACTIONS_SUB( 32, UInt   );
+      case AMD64G_CC_OP_SUBQ:   ACTIONS_SUB( 64, ULong  );
+
+      case AMD64G_CC_OP_SBBB:   ACTIONS_SBB(  8, UChar  );
+      case AMD64G_CC_OP_SBBW:   ACTIONS_SBB( 16, UShort );
+      case AMD64G_CC_OP_SBBL:   ACTIONS_SBB( 32, UInt   );
+
+      case AMD64G_CC_OP_LOGICB: ACTIONS_LOGIC(  8, UChar  );
+      case AMD64G_CC_OP_LOGICW: ACTIONS_LOGIC( 16, UShort );
+      case AMD64G_CC_OP_LOGICL: ACTIONS_LOGIC( 32, UInt   );
+      case AMD64G_CC_OP_LOGICQ: ACTIONS_LOGIC( 64, ULong  );
+
+      case AMD64G_CC_OP_INCB:   ACTIONS_INC(  8, UChar  );
+      case AMD64G_CC_OP_INCW:   ACTIONS_INC( 16, UShort );
+      case AMD64G_CC_OP_INCL:   ACTIONS_INC( 32, UInt   );
+
+      case AMD64G_CC_OP_DECB:   ACTIONS_DEC(  8, UChar  );
+      case AMD64G_CC_OP_DECW:   ACTIONS_DEC( 16, UShort );
+      case AMD64G_CC_OP_DECL:   ACTIONS_DEC( 32, UInt   );
+
+      case AMD64G_CC_OP_SHLB:   ACTIONS_SHL(  8, UChar  );
+      case AMD64G_CC_OP_SHLW:   ACTIONS_SHL( 16, UShort );
+      case AMD64G_CC_OP_SHLL:   ACTIONS_SHL( 32, UInt   );
+
+      case AMD64G_CC_OP_SHRB:   ACTIONS_SHR(  8, UChar  );
+      case AMD64G_CC_OP_SHRW:   ACTIONS_SHR( 16, UShort );
+      case AMD64G_CC_OP_SHRL:   ACTIONS_SHR( 32, UInt   );
+
+      case AMD64G_CC_OP_ROLB:   ACTIONS_ROL(  8, UChar  );
+      case AMD64G_CC_OP_ROLW:   ACTIONS_ROL( 16, UShort );
+      case AMD64G_CC_OP_ROLL:   ACTIONS_ROL( 32, UInt   );
+
+      case AMD64G_CC_OP_RORB:   ACTIONS_ROR(  8, UChar  );
+      case AMD64G_CC_OP_RORW:   ACTIONS_ROR( 16, UShort );
+      case AMD64G_CC_OP_RORL:   ACTIONS_ROR( 32, UInt   );
+
+      case AMD64G_CC_OP_UMULB:  ACTIONS_UMUL(  8, UChar,  UShort );
+      case AMD64G_CC_OP_UMULW:  ACTIONS_UMUL( 16, UShort, UInt   );
+      case AMD64G_CC_OP_UMULL:  ACTIONS_UMUL( 32, UInt,   ULong  );
+
+      case AMD64G_CC_OP_SMULB:  ACTIONS_SMUL(  8, Char,   Short );
+      case AMD64G_CC_OP_SMULW:  ACTIONS_SMUL( 16, Short,  Int   );
+      case AMD64G_CC_OP_SMULL:  ACTIONS_SMUL( 32, Int,    Long  );
+
+      default:
+         /* shouldn't really make these calls from generated code */
+         vex_printf("amd64g_calculate_rflags_all_WRK(AMD64)"
+                    "( %lld, 0x%llx, 0x%llx, 0x%llx )\n",
+                    cc_op, cc_dep1_formal, cc_dep2_formal, cc_ndep_formal );
+         vpanic("amd64g_calculate_rflags_all_WRK(AMD64)");
+   }
+}
+
+
+/* CALLED FROM GENERATED CODE: CLEAN HELPER */
+/* Calculate all the 6 flags from the supplied thunk parameters. */
+ULong amd64g_calculate_rflags_all ( ULong cc_op, 
+                                    ULong cc_dep1, 
+                                    ULong cc_dep2,
+                                    ULong cc_ndep )
+{
+#  if PROFILE_EFLAGS
+   if (!initted) initCounts();
+   n_calc_all++;
+   if (SHOW_COUNTS_NOW) showCounts();
+#  endif
+   return
+      amd64g_calculate_rflags_all_WRK ( cc_op, cc_dep1, cc_dep2, cc_ndep );
+}
+
+
+/* CALLED FROM GENERATED CODE: CLEAN HELPER */
+/* Calculate just the carry flag from the supplied thunk parameters. */
+ULong amd64g_calculate_rflags_c ( ULong cc_op, 
+                                  ULong cc_dep1, 
+                                  ULong cc_dep2,
+                                  ULong cc_ndep )
+{
+#  if PROFILE_EFLAGS
+   if (!initted) initCounts();
+   n_calc_c++;
+   tabc_fast[cc_op]++;
+   if (SHOW_COUNTS_NOW) showCounts();
+#  endif
+
+   /* Fast-case some common ones. */
+   switch (cc_op) {
+#  if 0 // REINSTATE CAREFULLY
+      case AMD64G_CC_OP_LOGICL: 
+      case AMD64G_CC_OP_LOGICW: 
+      case AMD64G_CC_OP_LOGICB:
+         return 0;
+      case AMD64G_CC_OP_SUBL:
+         return ((UInt)cc_dep1) < ((UInt)cc_dep2)
+                   ? AMD64G_CC_MASK_C : 0;
+      case AMD64G_CC_OP_SUBW:
+         return ((UInt)(cc_dep1 & 0xFFFF)) < ((UInt)(cc_dep2 & 0xFFFF))
+                   ? AMD64G_CC_MASK_C : 0;
+      case AMD64G_CC_OP_SUBB:
+         return ((UInt)(cc_dep1 & 0xFF)) < ((UInt)(cc_dep2 & 0xFF))
+                   ? AMD64G_CC_MASK_C : 0;
+      case AMD64G_CC_OP_INCL:
+      case AMD64G_CC_OP_DECL:
+         return cc_ndep & AMD64G_CC_MASK_C;
+#  endif // REINSTATE CAREFULLY
+      default: 
+         break;
+   }
+
+#  if PROFILE_EFLAGS
+   tabc_fast[cc_op]--;
+   tabc_slow[cc_op]++;
+#  endif
+
+   return amd64g_calculate_rflags_all_WRK(cc_op,cc_dep1,cc_dep2,cc_ndep) 
+          & AMD64G_CC_MASK_C;
 }
 
 
-ULong amd64g_calculate_rflags_c ( 
-                ULong cc_op, 
-                ULong cc_dep1, ULong cc_dep2, ULong cc_ndep 
-             )
+/* CALLED FROM GENERATED CODE: CLEAN HELPER */
+/* returns 1 or 0 */
+ULong amd64g_calculate_condition ( ULong/*AMD64Condcode*/ cond, 
+                                   ULong cc_op, 
+                                   ULong cc_dep1, 
+                                   ULong cc_dep2,
+                                   ULong cc_ndep )
 {
-  vassert(0);
-  return 0;
+   ULong rflags = amd64g_calculate_rflags_all_WRK(cc_op, cc_dep1, 
+                                                  cc_dep2, cc_ndep);
+   ULong of,sf,zf,cf,pf;
+   ULong inv = cond & 1;
+
+#  if PROFILE_EFLAGS
+   if (!initted) initCounts();
+   tab_cond[cc_op][cond]++;
+   n_calc_cond++;
+   if (SHOW_COUNTS_NOW) showCounts();
+#  endif
+
+   switch (cond) {
+      case AMD64CondNO:
+      case AMD64CondO: /* OF == 1 */
+         of = rflags >> AMD64G_CC_SHIFT_O;
+         return 1 & (inv ^ of);
+
+      case AMD64CondNZ:
+      case AMD64CondZ: /* ZF == 1 */
+         zf = rflags >> AMD64G_CC_SHIFT_Z;
+         return 1 & (inv ^ zf);
+
+      case AMD64CondNB:
+      case AMD64CondB: /* CF == 1 */
+         cf = rflags >> AMD64G_CC_SHIFT_C;
+         return 1 & (inv ^ cf);
+         break;
+
+      case AMD64CondNBE:
+      case AMD64CondBE: /* (CF or ZF) == 1 */
+         cf = rflags >> AMD64G_CC_SHIFT_C;
+         zf = rflags >> AMD64G_CC_SHIFT_Z;
+         return 1 & (inv ^ (cf | zf));
+         break;
+
+      case AMD64CondNS:
+      case AMD64CondS: /* SF == 1 */
+         sf = rflags >> AMD64G_CC_SHIFT_S;
+         return 1 & (inv ^ sf);
+
+      case AMD64CondNP:
+      case AMD64CondP: /* PF == 1 */
+         pf = rflags >> AMD64G_CC_SHIFT_P;
+         return 1 & (inv ^ pf);
+
+      case AMD64CondNL:
+      case AMD64CondL: /* (SF xor OF) == 1 */
+         sf = rflags >> AMD64G_CC_SHIFT_S;
+         of = rflags >> AMD64G_CC_SHIFT_O;
+         return 1 & (inv ^ (sf ^ of));
+         break;
+
+      case AMD64CondNLE:
+      case AMD64CondLE: /* ((SF xor OF) or ZF)  == 1 */
+         sf = rflags >> AMD64G_CC_SHIFT_S;
+         of = rflags >> AMD64G_CC_SHIFT_O;
+         zf = rflags >> AMD64G_CC_SHIFT_Z;
+         return 1 & (inv ^ ((sf ^ of) | zf));
+         break;
+
+      default:
+         /* shouldn't really make these calls from generated code */
+         vex_printf("amd64g_calculate_condition"
+                    "( %lld, %lld, 0x%llx, 0x%llx, 0x%llx )\n",
+                    cond, cc_op, cc_dep1, cc_dep2, cc_ndep );
+         vpanic("amd64g_calculate_condition");
+   }
 }
 
-ULong amd64g_calculate_condition ( 
-                ULong/*AMD64Condcode*/ cond, 
-                ULong cc_op, 
-                ULong cc_dep1, ULong cc_dep2, ULong cc_ndep 
-             )
+
+/* VISIBLE TO LIBVEX CLIENT */
+#if 0
+ULong LibVEX_GuestAMD64_get_rflags ( /*IN*/VexGuestAMD64State* vex_state )
 {
-  vassert(0);
-  return 0;
+   ULong rflags = amd64g_calculate_rflags_all_WRK(
+                     vex_state->guest_CC_OP,
+                     vex_state->guest_CC_DEP1,
+                     vex_state->guest_CC_DEP2,
+                     vex_state->guest_CC_NDEP
+                  );
+   //   UInt dflag = vex_state->guest_DFLAG;
+   vassert(0); //FIXME
+#if 0
+   vassert(dflag == 1 || dflag == 0xFFFFFFFF);
+   if (dflag == 0xFFFFFFFF)
+      rflags |= (1<<10);
+   if (vex_state->guest_IDFLAG == 1)
+      rflags |= (1<<21);
+#endif                                      
+   return rflags;
 }
+#endif
+
+
+/*---------------------------------------------------------------*/
+/*--- %rflags translation-time function specialisers.         ---*/
+/*--- These help iropt specialise calls the above run-time    ---*/
+/*--- %rflags functions.                                      ---*/
+/*---------------------------------------------------------------*/
 
+//.. /* Used by the optimiser to try specialisations.  Returns an
+//..    equivalent expression, or NULL if none. */
+//.. 
+//.. static Bool isU32 ( IRExpr* e, UInt n )
+//.. {
+//..    return e->tag == Iex_Const
+//..           && e->Iex.Const.con->tag == Ico_U32
+//..           && e->Iex.Const.con->Ico.U32 == n;
+//.. }
 
 IRExpr* guest_amd64_spechelper ( HChar* function_name,
                                  IRExpr** args )
 {
-  return NULL;
+//.. #  define unop(_op,_a1) IRExpr_Unop((_op),(_a1))
+//.. #  define binop(_op,_a1,_a2) IRExpr_Binop((_op),(_a1),(_a2))
+//.. #  define mkU32(_n) IRExpr_Const(IRConst_U32(_n))
+//.. #  define mkU8(_n)  IRExpr_Const(IRConst_U8(_n))
+//.. 
+//..    Int i, arity = 0;
+//..    for (i = 0; args[i]; i++)
+//..       arity++;
+//.. #  if 0
+//..    vex_printf("spec request:\n");
+//..    vex_printf("   %s  ", function_name);
+//..    for (i = 0; i < arity; i++) {
+//..       vex_printf("  ");
+//..       ppIRExpr(args[i]);
+//..    }
+//..    vex_printf("\n");
+//.. #  endif
+//.. 
+//..    /* --------- specialising "x86g_calculate_condition" --------- */
+//.. 
+//..    if (vex_streq(function_name, "x86g_calculate_condition")) {
+//..       /* specialise calls to above "calculate condition" function */
+//..       IRExpr *cond, *cc_op, *cc_dep1, *cc_dep2;
+//..       vassert(arity == 5);
+//..       cond    = args[0];
+//..       cc_op   = args[1];
+//..       cc_dep1 = args[2];
+//..       cc_dep2 = args[3];
+//.. 
+//..       /*---------------- ADDL ----------------*/
+//.. 
+//..       if (isU32(cc_op, AMD64G_CC_OP_ADDL) && isU32(cond, X86CondZ)) {
+//..          /* long add, then Z --> test (dst+src == 0) */
+//..          return unop(Iop_1Uto32,
+//..                      binop(Iop_CmpEQ32, 
+//..                            binop(Iop_Add32, cc_dep1, cc_dep2),
+//..                            mkU32(0)));
+//..       }
+//.. 
+//..       /*---------------- SUBL ----------------*/
+//.. 
+//..       if (isU32(cc_op, AMD64G_CC_OP_SUBL) && isU32(cond, X86CondZ)) {
+//..          /* long sub/cmp, then Z --> test dst==src */
+//..          return unop(Iop_1Uto32,
+//..                      binop(Iop_CmpEQ32, cc_dep1, cc_dep2));
+//..       }
+//.. 
+//..       if (isU32(cc_op, AMD64G_CC_OP_SUBL) && isU32(cond, X86CondNZ)) {
+//..          /* long sub/cmp, then NZ --> test dst!=src */
+//..          return unop(Iop_1Uto32,
+//..                      binop(Iop_CmpNE32, cc_dep1, cc_dep2));
+//..       }
+//.. 
+//..       if (isU32(cc_op, AMD64G_CC_OP_SUBL) && isU32(cond, X86CondL)) {
+//..          /* long sub/cmp, then L (signed less than) 
+//..             --> test dst <s src */
+//..          return unop(Iop_1Uto32,
+//..                      binop(Iop_CmpLT32S, cc_dep1, cc_dep2));
+//..       }
+//.. 
+//..       if (isU32(cc_op, AMD64G_CC_OP_SUBL) && isU32(cond, X86CondLE)) {
+//..          /* long sub/cmp, then LE (signed less than or equal)
+//..             --> test dst <=s src */
+//..          return unop(Iop_1Uto32,
+//..                      binop(Iop_CmpLE32S, cc_dep1, cc_dep2));
+//..       }
+//.. 
+//..       if (isU32(cc_op, AMD64G_CC_OP_SUBL) && isU32(cond, X86CondBE)) {
+//..          /* long sub/cmp, then BE (unsigned less than or equal)
+//..             --> test dst <=u src */
+//..          return unop(Iop_1Uto32,
+//..                      binop(Iop_CmpLE32U, cc_dep1, cc_dep2));
+//..       }
+//.. 
+//..       if (isU32(cc_op, AMD64G_CC_OP_SUBL) && isU32(cond, X86CondB)) {
+//..          /* long sub/cmp, then B (unsigned less than)
+//..             --> test dst <u src */
+//..          return unop(Iop_1Uto32,
+//..                      binop(Iop_CmpLT32U, cc_dep1, cc_dep2));
+//..       }
+//.. 
+//..       /*---------------- SUBW ----------------*/
+//.. 
+//..       if (isU32(cc_op, AMD64G_CC_OP_SUBW) && isU32(cond, X86CondZ)) {
+//..          /* byte sub/cmp, then Z --> test dst==src */
+//..          return unop(Iop_1Uto32,
+//..                      binop(Iop_CmpEQ16, 
+//..                            unop(Iop_32to16,cc_dep1), 
+//..                            unop(Iop_32to16,cc_dep2)));
+//..       }
+//.. 
+//..       /*---------------- SUBB ----------------*/
+//.. 
+//..       if (isU32(cc_op, AMD64G_CC_OP_SUBB) && isU32(cond, X86CondZ)) {
+//..          /* byte sub/cmp, then Z --> test dst==src */
+//..          return unop(Iop_1Uto32,
+//..                      binop(Iop_CmpEQ8, 
+//..                            unop(Iop_32to8,cc_dep1), 
+//..                            unop(Iop_32to8,cc_dep2)));
+//..       }
+//.. 
+//..       if (isU32(cc_op, AMD64G_CC_OP_SUBB) && isU32(cond, X86CondNZ)) {
+//..          /* byte sub/cmp, then NZ --> test dst!=src */
+//..          return unop(Iop_1Uto32,
+//..                      binop(Iop_CmpNE8, 
+//..                            unop(Iop_32to8,cc_dep1), 
+//..                            unop(Iop_32to8,cc_dep2)));
+//..       }
+//.. 
+//..       if (isU32(cc_op, AMD64G_CC_OP_SUBB) && isU32(cond, X86CondNBE)) {
+//..          /* long sub/cmp, then NBE (unsigned greater than)
+//..             --> test src <=u dst */
+//..          /* Note, args are opposite way round from the usual */
+//..          return unop(Iop_1Uto32,
+//..                      binop(Iop_CmpLT32U, 
+//..                            binop(Iop_And32,cc_dep2,mkU32(0xFF)),
+//..                      binop(Iop_And32,cc_dep1,mkU32(0xFF))));
+//..       }
+//.. 
+//..       /*---------------- LOGICL ----------------*/
+//.. 
+//..       if (isU32(cc_op, AMD64G_CC_OP_LOGICL) && isU32(cond, X86CondZ)) {
+//..          /* long and/or/xor, then Z --> test dst==0 */
+//..          return unop(Iop_1Uto32,binop(Iop_CmpEQ32, cc_dep1, mkU32(0)));
+//..       }
+//.. 
+//..       if (isU32(cc_op, AMD64G_CC_OP_LOGICL) && isU32(cond, X86CondS)) {
+//..          /* long and/or/xor, then S --> test dst <s 0 */
+//..          return unop(Iop_1Uto32,binop(Iop_CmpLT32S, cc_dep1, mkU32(0)));
+//..       }
+//.. 
+//..       if (isU32(cc_op, AMD64G_CC_OP_LOGICL) && isU32(cond, X86CondLE)) {
+//..          /* long and/or/xor, then LE
+//..             This is pretty subtle.  LOGIC sets SF and ZF according to the
+//..             result and makes OF be zero.  LE computes (SZ ^ OF) | ZF, but
+//..             OF is zero, so this reduces to SZ | ZF -- which will be 1 iff
+//..             the result is <=signed 0.  Hence ...
+//..          */
+//..          return unop(Iop_1Uto32,binop(Iop_CmpLE32S, cc_dep1, mkU32(0)));
+//..       }
+//.. 
+//..       if (isU32(cc_op, AMD64G_CC_OP_LOGICL) && isU32(cond, X86CondBE)) {
+//..          /* long and/or/xor, then BE
+//..             LOGIC sets ZF according to the result and makes CF be zero.
+//..             BE computes (CF | ZF), but CF is zero, so this reduces ZF 
+//..             -- which will be 1 iff the result is zero.  Hence ...
+//..          */
+//..          return unop(Iop_1Uto32,binop(Iop_CmpEQ32, cc_dep1, mkU32(0)));
+//..       }
+//.. 
+//..       /*---------------- LOGICW ----------------*/
+//.. 
+//..       if (isU32(cc_op, AMD64G_CC_OP_LOGICW) && isU32(cond, X86CondZ)) {
+//..          /* byte and/or/xor, then Z --> test dst==0 */
+//..          return unop(Iop_1Uto32,
+//..                      binop(Iop_CmpEQ32, binop(Iop_And32,cc_dep1,mkU32(0xFFFF)), 
+//..                                         mkU32(0)));
+//..       }
+//.. 
+//..       /*---------------- LOGICB ----------------*/
+//.. 
+//..       if (isU32(cc_op, AMD64G_CC_OP_LOGICB) && isU32(cond, X86CondZ)) {
+//..          /* byte and/or/xor, then Z --> test dst==0 */
+//..          return unop(Iop_1Uto32,
+//..                      binop(Iop_CmpEQ32, binop(Iop_And32,cc_dep1,mkU32(255)), 
+//..                                         mkU32(0)));
+//..       }
+//.. 
+//..       /*---------------- DECL ----------------*/
+//.. 
+//..       if (isU32(cc_op, AMD64G_CC_OP_DECL) && isU32(cond, X86CondZ)) {
+//..          /* dec L, then Z --> test dst == 0 */
+//..          return unop(Iop_1Uto32,binop(Iop_CmpEQ32, cc_dep1, mkU32(0)));
+//..       }
+//.. 
+//..       if (isU32(cc_op, AMD64G_CC_OP_DECL) && isU32(cond, X86CondS)) {
+//..          /* dec L, then S --> compare DST <s 0 */
+//..          return unop(Iop_1Uto32,binop(Iop_CmpLT32S, cc_dep1, mkU32(0)));
+//..       }
+//.. 
+//..       /*---------------- SHRL ----------------*/
+//.. 
+//..       if (isU32(cc_op, AMD64G_CC_OP_SHRL) && isU32(cond, X86CondZ)) {
+//..          /* SHRL, then Z --> test dep1 == 0 */
+//..          return unop(Iop_1Uto32,binop(Iop_CmpEQ32, cc_dep1, mkU32(0)));
+//..       }
+//.. 
+//..       /*---------------- COPY ----------------*/
+//..       /* This can happen, as a result of x87 FP compares: "fcom ... ;
+//..          fnstsw %ax ; sahf ; jbe" for example. */
+//.. 
+//..       if (isU32(cc_op, AMD64G_CC_OP_COPY) && 
+//..           (isU32(cond, X86CondBE) || isU32(cond, X86CondNBE))) {
+//..          /* COPY, then BE --> extract C and Z from dep1, and test (C
+//..             or Z == 1). */
+//..          /* COPY, then NBE --> extract C and Z from dep1, and test (C
+//..             or Z == 0). */
+//..          UInt nnn = isU32(cond, X86CondBE) ? 1 : 0;
+//..          return
+//..             unop(
+//..                Iop_1Uto32,
+//..                binop(
+//..                   Iop_CmpEQ32,
+//..                   binop(
+//..                      Iop_And32,
+//..                      binop(
+//..                         Iop_Or32,
+//..                         binop(Iop_Shr32, cc_dep1, mkU8(AMD64G_CC_SHIFT_C)),
+//..                         binop(Iop_Shr32, cc_dep1, mkU8(AMD64G_CC_SHIFT_Z))
+//..                      ),
+//..                      mkU32(1)
+//..                   ),
+//..                   mkU32(nnn)
+//..                )
+//..             );
+//..       }
+//..       
+//..       if (isU32(cc_op, AMD64G_CC_OP_COPY) && isU32(cond, X86CondB)) {
+//..          /* COPY, then B --> extract C dep1, and test (C == 1). */
+//..          return
+//..             unop(
+//..                Iop_1Uto32,
+//..                binop(
+//..                   Iop_CmpNE32,
+//..                   binop(
+//..                      Iop_And32,
+//..                      binop(Iop_Shr32, cc_dep1, mkU8(AMD64G_CC_SHIFT_C)),
+//..                      mkU32(1)
+//..                   ),
+//..                   mkU32(0)
+//..                )
+//..             );
+//..       }
+//.. 
+//..       return NULL;
+//..    }
+//.. 
+//..    /* --------- specialising "x86g_calculate_eflags_c" --------- */
+//.. 
+//..    if (vex_streq(function_name, "x86g_calculate_eflags_c")) {
+//..       /* specialise calls to above "calculate_eflags_c" function */
+//..       IRExpr *cc_op, *cc_dep1, *cc_dep2, *cc_ndep;
+//..       vassert(arity == 4);
+//..       cc_op   = args[0];
+//..       cc_dep1 = args[1];
+//..       cc_dep2 = args[2];
+//..       cc_ndep = args[3];
+//.. 
+//..       if (isU32(cc_op, AMD64G_CC_OP_SUBL)) {
+//..          /* C after sub denotes unsigned less than */
+//..          return unop(Iop_1Uto32,
+//..                      binop(Iop_CmpLT32U, cc_dep1, cc_dep2));
+//..       }
+//..       if (isU32(cc_op, AMD64G_CC_OP_SUBB)) {
+//..          /* C after sub denotes unsigned less than */
+//..          return unop(Iop_1Uto32,
+//..                      binop(Iop_CmpLT32U, 
+//..                            binop(Iop_And32,cc_dep1,mkU32(0xFF)),
+//..                            binop(Iop_And32,cc_dep2,mkU32(0xFF))));
+//..       }
+//..       if (isU32(cc_op, AMD64G_CC_OP_LOGICL)
+//..           || isU32(cc_op, AMD64G_CC_OP_LOGICW)
+//..           || isU32(cc_op, AMD64G_CC_OP_LOGICB)) {
+//..          /* cflag after logic is zero */
+//..          return mkU32(0);
+//..       }
+//..       if (isU32(cc_op, AMD64G_CC_OP_DECL) || isU32(cc_op, AMD64G_CC_OP_INCL)) {
+//..          /* If the thunk is dec or inc, the cflag is supplied as CC_NDEP. */
+//..          return cc_ndep;
+//..       }
+//..       if (isU32(cc_op, AMD64G_CC_OP_COPY)) {
+//..          /* cflag after COPY is stored in DEP1. */
+//..          return
+//..             binop(
+//..                Iop_And32,
+//..                binop(Iop_Shr32, cc_dep1, mkU8(AMD64G_CC_SHIFT_C)),
+//..                mkU32(1)
+//..             );
+//..       }
+//.. #     if 0
+//..       if (cc_op->tag == Iex_Const) {
+//..          vex_printf("CFLAG "); ppIRExpr(cc_op); vex_printf("\n");
+//..       }
+//.. #     endif
+//.. 
+//..       return NULL;
+//..    }
+//.. 
+//..    /* --------- specialising "x86g_calculate_eflags_all" --------- */
+//.. 
+//..    if (vex_streq(function_name, "x86g_calculate_eflags_all")) {
+//..       /* specialise calls to above "calculate_eflags_all" function */
+//..       IRExpr *cc_op, *cc_dep1, *cc_dep2, *cc_ndep;
+//..       vassert(arity == 4);
+//..       cc_op   = args[0];
+//..       cc_dep1 = args[1];
+//..       cc_dep2 = args[2];
+//..       cc_ndep = args[3];
+//.. 
+//..       if (isU32(cc_op, AMD64G_CC_OP_COPY)) {
+//..          /* eflags after COPY are stored in DEP1. */
+//..          return
+//..             binop(
+//..                Iop_And32,
+//..                cc_dep1,
+//..                mkU32(AMD64G_CC_MASK_O | AMD64G_CC_MASK_S | AMD64G_CC_MASK_Z 
+//..                      | AMD64G_CC_MASK_A | AMD64G_CC_MASK_C | AMD64G_CC_MASK_P)
+//..             );
+//..       }
+//..       return NULL;
+//..    }
+
+#  undef unop
+#  undef binop
+#  undef mkU32
+#  undef mkU8
+
+   return NULL;
+}
+
+
+/*---------------------------------------------------------------*/
+/*--- Helpers for dealing with, and describing,               ---*/
+/*--- guest state as a whole.                                 ---*/
+/*---------------------------------------------------------------*/
+
+/* Initialise the entire amd64 guest state. */
+/* VISIBLE TO LIBVEX CLIENT */
+void LibVEX_GuestAMD64_initialise ( /*OUT*/VexGuestAMD64State* vex_state )
+{
+   //Int i;
+
+   vex_state->guest_RAX = 0;
+   vex_state->guest_RCX = 0;
+   vex_state->guest_RDX = 0;
+   vex_state->guest_RBX = 0;
+   vex_state->guest_RSP = 0;
+   vex_state->guest_RBP = 0;
+   vex_state->guest_RSI = 0;
+   vex_state->guest_RDI = 0;
+   vex_state->guest_R8  = 0;
+   vex_state->guest_R9  = 0;
+   vex_state->guest_R10 = 0;
+   vex_state->guest_R11 = 0;
+   vex_state->guest_R12 = 0;
+   vex_state->guest_R13 = 0;
+   vex_state->guest_R14 = 0;
+   vex_state->guest_R15 = 0;
+
+   vex_state->guest_CC_OP   = AMD64G_CC_OP_COPY;
+   vex_state->guest_CC_DEP1 = 0;
+   vex_state->guest_CC_DEP2 = 0;
+   vex_state->guest_CC_NDEP = 0;
+
+   // XXX: add more here later, for D/ID flags
+
+   vex_state->guest_RIP = 0;
+
+   // XXX: add more here later, for segment registers, FPU, etc.
+
+   vex_state->guest_EMWARN = EmWarn_NONE;
 }
 
+
 /* Figure out if any part of the guest state contained in minoff
    .. maxoff requires precise memory exceptions.  If in doubt return
    True (but this is generates significantly slower code).  
@@ -109,7 +1135,6 @@ Bool guest_amd64_state_requires_precise_mem_exns ( Int minoff,
 }
 
 
-
 #define ALWAYSDEFD(field)                             \
     { offsetof(VexGuestAMD64State, field),            \
       (sizeof ((VexGuestAMD64State*)0)->field) }
@@ -158,42 +1183,6 @@ VexGuestLayout
         };
 
 
-/* VISIBLE TO LIBVEX CLIENT */
-void LibVEX_GuestAMD64_initialise ( /*OUT*/VexGuestAMD64State* vex_state )
-{
-   //Int i;
-
-   vex_state->guest_RAX = 0;
-   vex_state->guest_RCX = 0;
-   vex_state->guest_RDX = 0;
-   vex_state->guest_RBX = 0;
-   vex_state->guest_RSP = 0;
-   vex_state->guest_RBP = 0;
-   vex_state->guest_RSI = 0;
-   vex_state->guest_RDI = 0;
-   vex_state->guest_R8  = 0;
-   vex_state->guest_R9  = 0;
-   vex_state->guest_R10 = 0;
-   vex_state->guest_R11 = 0;
-   vex_state->guest_R12 = 0;
-   vex_state->guest_R13 = 0;
-   vex_state->guest_R14 = 0;
-   vex_state->guest_R15 = 0;
-
-   vex_state->guest_CC_OP   = AMD64G_CC_OP_COPY;
-   vex_state->guest_CC_DEP1 = 0;
-   vex_state->guest_CC_DEP2 = 0;
-   vex_state->guest_CC_NDEP = 0;
-
-   // XXX: add more here later, for D/ID flags
-
-   vex_state->guest_RIP = 0;
-
-   // XXX: add more here later, for segment registers, FPU, etc.
-
-   vex_state->guest_EMWARN = EmWarn_NONE;
-}
-
 /*---------------------------------------------------------------*/
 /*--- end                              guest-amd64/ghelpers.c ---*/
 /*---------------------------------------------------------------*/
index d47771d03feef8cb0afe8747c29e36042cee798a..ce70a5ac728a37d5c0f90c2d43588e71ba7c0483 100644 (file)
@@ -33,6 +33,9 @@
    USA.
 */
 
+/* EFLAGS after multiply-Q is wrong because there is no way to do
+   a 128-bit multiply in C (directly). */
+
 //.. /* TODO:
 //..    SBB reg with itself
 //.. 
@@ -11106,24 +11109,27 @@ DisResult disInstr ( /*IN*/  Bool       resteerOK,
 //..       whatNext = Dis_StopHere;
 //..       DIP("int $0x80\n");
 //..       break;
-//.. 
-//..    /* ------------------------ Jcond, byte offset --------- */
-//.. 
-//..    case 0xEB: /* Jb (jump, byte offset) */
-//..       d32 = (((Addr32)guest_eip_bbstart)+delta+1) + getSDisp8(delta); 
-//..       delta++;
-//..       if (resteerOK && resteerOkFn((Addr64)(Addr32)d32)) {
-//..          whatNext   = Dis_Resteer;
-//..          *whereNext = d32;
-//..       } else {
-//..          jmp_lit(Ijk_Boring,d32);
-//..          whatNext = Dis_StopHere;
-//..       }
-//..       DIP("jmp-8 0x%x\n", d32);
-//..       break;
+
+   /* ------------------------ Jcond, byte offset --------- */
+
+   case 0xEB: /* Jb (jump, byte offset) */
+      if (sz != 4) 
+         goto decode_failure; /* JRS added 2004 July 11 */
+      d64 = (guest_rip_bbstart+delta+1) + getSDisp8(delta); 
+      delta++;
+      if (resteerOK && resteerOkFn(d64)) {
+         whatNext   = Dis_Resteer;
+         *whereNext = d64;
+      } else {
+         jmp_lit(Ijk_Boring,d64);
+         whatNext = Dis_StopHere;
+      }
+      DIP("jmp-8 0x%llx\n", d64);
+      break;
 
    case 0xE9: /* Jv (jump, 16/32 offset) */
-      if (sz != 4) goto decode_failure; /* JRS added 2004 July 11 */
+      if (sz != 4) 
+         goto decode_failure; /* JRS added 2004 July 11 */
       d64 = (guest_rip_bbstart+delta+sz) + getSDisp(sz,delta); 
       delta += sz;
       if (resteerOK && resteerOkFn(d64)) {
@@ -11136,29 +11142,31 @@ DisResult disInstr ( /*IN*/  Bool       resteerOK,
       DIP("jmp 0x%llx\n", d64);
       break;
 
-//..    case 0x70:
-//..    case 0x71:
-//..    case 0x72: /* JBb/JNAEb (jump below) */
-//..    case 0x73: /* JNBb/JAEb (jump not below) */
-//..    case 0x74: /* JZb/JEb (jump zero) */
-//..    case 0x75: /* JNZb/JNEb (jump not zero) */
-//..    case 0x76: /* JBEb/JNAb (jump below or equal) */
-//..    case 0x77: /* JNBEb/JAb (jump not below or equal) */
-//..    case 0x78: /* JSb (jump negative) */
-//..    case 0x79: /* JSb (jump not negative) */
-//..    case 0x7A: /* JP (jump parity even) */
-//..    case 0x7B: /* JNP/JPO (jump parity odd) */
-//..    case 0x7C: /* JLb/JNGEb (jump less) */
-//..    case 0x7D: /* JGEb/JNLb (jump greater or equal) */
-//..    case 0x7E: /* JLEb/JNGb (jump less or equal) */
-//..    case 0x7F: /* JGb/JNLEb (jump greater) */
-//..       d32 = (((Addr32)guest_eip_bbstart)+delta+1) + getSDisp8(delta); 
-//..       delta++;
-//..       jcc_01((X86Condcode)(opc - 0x70), (Addr32)(guest_eip_bbstart+delta), d32);
-//..       whatNext = Dis_StopHere;
-//..       DIP("j%s-8 0x%x\n", name_X86Condcode(opc - 0x70), d32);
-//..       break;
-//.. 
+   case 0x70:
+   case 0x71:
+   case 0x72: /* JBb/JNAEb (jump below) */
+   case 0x73: /* JNBb/JAEb (jump not below) */
+   case 0x74: /* JZb/JEb (jump zero) */
+   case 0x75: /* JNZb/JNEb (jump not zero) */
+   case 0x76: /* JBEb/JNAb (jump below or equal) */
+   case 0x77: /* JNBEb/JAb (jump not below or equal) */
+   case 0x78: /* JSb (jump negative) */
+   case 0x79: /* JSb (jump not negative) */
+   case 0x7A: /* JP (jump parity even) */
+   case 0x7B: /* JNP/JPO (jump parity odd) */
+   case 0x7C: /* JLb/JNGEb (jump less) */
+   case 0x7D: /* JGEb/JNLb (jump greater or equal) */
+   case 0x7E: /* JLEb/JNGb (jump less or equal) */
+   case 0x7F: /* JGb/JNLEb (jump greater) */
+      d64 = (guest_rip_bbstart+delta+1) + getSDisp8(delta); 
+      delta++;
+      jcc_01( (AMD64Condcode)(opc - 0x70), 
+              guest_rip_bbstart+delta,
+              d64 );
+      whatNext = Dis_StopHere;
+      DIP("j%s-8 0x%llx\n", name_AMD64Condcode(opc - 0x70), d64);
+      break;
+
 //..    case 0xE3: /* JECXZ or perhaps JCXZ, depending on OSO ?  Intel
 //..                  manual says it depends on address size override,
 //..                  which doesn't sound right to me. */
index eb992733209a6be2f57717ce10617a2eb7cc6c5c..435b7f916b57f25a67fcabdca67036fabb139d17 100644 (file)
@@ -1543,8 +1543,8 @@ static AMD64CondCode iselCondCode ( ISelEnv* env, IRExpr* e )
 /* DO NOT CALL THIS DIRECTLY ! */
 static AMD64CondCode iselCondCode_wrk ( ISelEnv* env, IRExpr* e )
 {
-//..    MatchInfo mi;
-//..    DECLARE_PATTERN(p_32to1);
+   MatchInfo mi;
+   DECLARE_PATTERN(p_32to1_64to32);
 //..    DECLARE_PATTERN(p_1Uto32_then_32to1);
 //..    DECLARE_PATTERN(p_1Sto32_then_32to1);
 
@@ -1582,17 +1582,17 @@ static AMD64CondCode iselCondCode_wrk ( ISelEnv* env, IRExpr* e )
 //..       IRExpr* expr1 = mi.bindee[0];
 //..       return iselCondCode(env, expr1);
 //..    }
-//.. 
-//..    /* pattern: 32to1(expr32) */
-//..    DEFINE_PATTERN(p_32to1
-//..       unop(Iop_32to1,bind(0))
-//..    );
-//..    if (matchIRExpr(&mi,p_32to1,e)) {
-//..       X86RM* rm = iselIntExpr_RM(env, mi.bindee[0]);
-//..       addInstr(env, X86Instr_Test32(X86RI_Imm(1),rm));
-//..       return Xcc_NZ;
-//..    }
-//.. 
+
+   /* pattern: 32to1(64to32(expr64)) */
+   DEFINE_PATTERN(p_32to1_64to32
+      unop(Iop_32to1,unop(Iop_64to32, bind(0)))
+   );
+   if (matchIRExpr(&mi,p_32to1_64to32,e)) {
+      AMD64RM* rm = iselIntExpr_RM(env, mi.bindee[0]);
+      addInstr(env, AMD64Instr_Test64(AMD64RI_Imm(1),rm));
+      return Acc_NZ;
+   }
+
 //..    /* CmpEQ8 / CmpNE8 */
 //..    if (e->tag == Iex_Binop 
 //..        && (e->Iex.Binop.op == Iop_CmpEQ8
@@ -3434,18 +3434,18 @@ static void iselStmt ( ISelEnv* env, IRStmt* stmt )
 //..    case Ist_MFence:
 //..       addInstr(env, X86Instr_MFence(env->subarch));
 //..       return;
-//.. 
-//..    /* --------- EXIT --------- */
-//..    case Ist_Exit: {
-//..       X86RI*      dst;
-//..       X86CondCode cc;
-//..       if (stmt->Ist.Exit.dst->tag != Ico_U32)
-//..          vpanic("isel_x86: Ist_Exit: dst is not a 32-bit value");
-//..       dst = iselIntExpr_RI(env, IRExpr_Const(stmt->Ist.Exit.dst));
-//..       cc  = iselCondCode(env,stmt->Ist.Exit.guard);
-//..       addInstr(env, X86Instr_Goto(stmt->Ist.Exit.jk, cc, dst));
-//..       return;
-//..    }
+
+   /* --------- EXIT --------- */
+   case Ist_Exit: {
+      AMD64RI*      dst;
+      AMD64CondCode cc;
+      if (stmt->Ist.Exit.dst->tag != Ico_U64)
+         vpanic("iselStmt(amd64): Ist_Exit: dst is not a 64-bit value");
+      dst = iselIntExpr_RI(env, IRExpr_Const(stmt->Ist.Exit.dst));
+      cc  = iselCondCode(env,stmt->Ist.Exit.guard);
+      addInstr(env, AMD64Instr_Goto(stmt->Ist.Exit.jk, cc, dst));
+      return;
+   }
 
    default: break;
    }