]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Add a dummy AMD64 front end, as a completely commented-out version of
authorJulian Seward <jseward@acm.org>
Thu, 20 Jan 2005 20:04:07 +0000 (20:04 +0000)
committerJulian Seward <jseward@acm.org>
Thu, 20 Jan 2005 20:04:07 +0000 (20:04 +0000)
the x86 equivalents.

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

VEX/Makefile
VEX/priv/guest-amd64/gdefs.h [new file with mode: 0644]
VEX/priv/guest-amd64/toIR.c [new file with mode: 0644]

index 6721b2a092231f8432cc09945685f1adb95cb5f2..25ef33f897413929b75b5cae3c7e7a3a7bd4d8d7 100644 (file)
@@ -15,6 +15,7 @@ PRIV_HEADERS =        priv/host-x86/hdefs.h                   \
                priv/main/vex_globals.h                 \
                priv/main/vex_util.h                    \
                priv/guest-x86/gdefs.h                  \
+               priv/guest-amd64/gdefs.h                \
                priv/guest-arm/gdefs.h                  \
                priv/ir/irmatch.h                       \
                priv/ir/iropt.h
@@ -36,6 +37,7 @@ LIB_OBJS =    priv/ir/irdefs.o                        \
                priv/guest-amd64/ghelpers.o             \
                priv/guest-arm/ghelpers.o               \
                priv/guest-x86/toIR.o                   \
+               priv/guest-amd64/toIR.o                 \
                priv/guest-arm/toIR.o
 
 PUB_INCLUDES = -Ipub
@@ -166,6 +168,10 @@ priv/guest-amd64/ghelpers.o: $(ALL_HEADERS) priv/guest-amd64/ghelpers.c
        $(CC) $(CCFLAGS) $(ALL_INCLUDES) -o priv/guest-amd64/ghelpers.o \
                                         -c priv/guest-amd64/ghelpers.c
 
+priv/guest-amd64/toIR.o: $(ALL_HEADERS) priv/guest-amd64/toIR.c
+       $(CC) $(CCFLAGS) $(ALL_INCLUDES) -o priv/guest-amd64/toIR.o \
+                                        -c priv/guest-amd64/toIR.c
+
 priv/guest-arm/ghelpers.o: $(ALL_HEADERS) priv/guest-arm/ghelpers.c
        $(CC) $(CCFLAGS) $(ALL_INCLUDES) -o priv/guest-arm/ghelpers.o \
                                         -c priv/guest-arm/ghelpers.c
diff --git a/VEX/priv/guest-amd64/gdefs.h b/VEX/priv/guest-amd64/gdefs.h
new file mode 100644 (file)
index 0000000..bee00ee
--- /dev/null
@@ -0,0 +1,384 @@
+
+/*---------------------------------------------------------------*/
+/*---                                                         ---*/
+/*--- This file (guest-amd64/gdefs.h) is                      ---*/
+/*--- Copyright (c) 2005 OpenWorks LLP.  All rights reserved. ---*/
+/*---                                                         ---*/
+/*---------------------------------------------------------------*/
+
+/*
+   This file is part of LibVEX, a library for dynamic binary
+   instrumentation and translation.
+
+   Copyright (C) 2005 OpenWorks, LLP.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; Version 2 dated June 1991 of the
+   license.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or liability
+   for damages.  See the GNU General Public License for more details.
+
+   Neither the names of the U.S. Department of Energy nor the
+   University of California nor the names of its contributors may be
+   used to endorse or promote products derived from this software
+   without prior written permission.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+   USA.
+*/
+
+/* Only to be used within the guest-amd64 directory. */
+
+#ifndef __LIBVEX_GUEST_AMD64_DEFS_H
+#define __LIBVEX_GUEST_AMD64_DEFS_H
+
+
+/*---------------------------------------------------------*/
+/*--- amd64 to IR conversion                            ---*/
+/*---------------------------------------------------------*/
+
+extern
+IRBB* bbToIR_AMD64 ( UChar*           amd64code, 
+                     Addr64           eip, 
+                     VexGuestExtents* vge,
+                     Bool             (*byte_accessible)(Addr64),
+                     Bool             (*resteerOkFn)(Addr64),
+                     Bool             host_bigendian,
+                     VexSubArch       subarch_guest );
+
+/* Used by the optimiser to specialise calls to helpers. */
+extern
+IRExpr* guest_amd64_spechelper ( Char* function_name,
+                                 IRExpr** args );
+
+/* Describes to the optimiser which part of the guest state require
+   precise memory exceptions.  This is logically part of the guest
+   state description. */
+extern 
+Bool guest_amd64_state_requires_precise_mem_exns ( Int, Int );
+
+extern
+VexGuestLayout amd64guest_layout;
+
+
+/*---------------------------------------------------------*/
+/*--- amd64 guest helpers                               ---*/
+/*---------------------------------------------------------*/
+
+/* --- CLEAN HELPERS --- */
+
+extern ULong amd64g_calculate_rflags_all ( 
+                ULong cc_op, 
+                ULong cc_dep1, ULong cc_dep2, ULong cc_ndep 
+             );
+
+extern Ulong amd64g_calculate_eflags_c ( 
+                ULong cc_op, 
+                ULong cc_dep1, ULong cc_dep2, ULong cc_ndep 
+             );
+
+extern ULong amd64g_calculate_condition ( 
+                ULong/*AMD64Condcode*/ cond, 
+                ULong cc_op, 
+                ULong cc_dep1, ULong cc_dep2, ULong cc_ndep 
+             );
+
+//extern ULong amd64g_calculate_FXAM ( ULong tag, ULong dbl );
+
+// Hmm.  This is going to be a problem as it needs to return
+// 64bits and rflags.
+//extern ULong amd64g_calculate_RCR  ( 
+//                UInt arg, UInt rot_amt, UInt eflags_in, UInt sz 
+//             );
+
+//extern ULong amd64g_check_fldcw ( ULong fpucw );
+
+//extern ULong amd64g_create_fpucw ( ULong fpround );
+
+//extern ULong amd64g_check_ldmxcsr ( ULong mxcsr );
+
+//extern ULong amd64g_create_mxcsr ( ULong sseround );
+
+/* Translate a guest virtual_addr into a guest linear address by
+   consulting the supplied LDT/GDT structures.  Their representation
+   must be as specified in pub/libvex_guest_amd64.h.  To indicate a
+   translation failure, 1<<32 is returned.  On success, the lower 32
+   bits of the returned result indicate the linear address.  
+*/
+//extern 
+//ULong amd64g_use_seg_selector ( HWord ldt, HWord gdt, 
+//                              UInt seg_selector, UInt virtual_addr );
+
+extern ULong amd64g_calculate_mmx_pmaddwd  ( ULong, ULong );
+extern ULong amd64g_calculate_mmx_psadbw   ( ULong, ULong );
+extern UInt  amd64g_calculate_mmx_pmovmskb ( ULong );
+extern UInt  amd64g_calculate_sse_pmovmskb ( ULong w64hi, ULong w64lo );
+
+
+/* --- DIRTY HELPERS --- */
+
+//extern ULong amd64g_loadF80le  ( ULong/*addr*/ );
+
+//extern void  amd64g_storeF80le ( ULong/*addr*/, ULong );
+
+//extern void  amd64g_dirtyhelper_CPUID_sse0 ( VexGuestAMD64State* );
+//extern void  amd64g_dirtyhelper_CPUID_sse1 ( VexGuestAMD64State* );
+//extern void  amd64g_dirtyhelper_CPUID_sse2 ( VexGuestAMD64State* );
+
+//extern void  amd64g_dirtyhelper_FSAVE ( VexGuestAMD64State*, HWord );
+
+//extern void  amd64g_dirtyhelper_FINIT ( VexGuestAMD64State* );
+
+//extern VexEmWarn
+//            amd64g_dirtyhelper_FRSTOR ( VexGuestAMD64State*, HWord );
+
+//extern void amd64g_dirtyhelper_FSTENV ( VexGuestAMD64State*, HWord );
+
+//extern VexEmWarn 
+//            amd64g_dirtyhelper_FLDENV ( VexGuestAMD64State*, HWord );
+
+//extern void  amd64g_dirtyhelper_FXSAVE ( VexGuestAMD64State*, HWord );
+
+
+/*---------------------------------------------------------*/
+/*--- Condition code stuff                              ---*/
+/*---------------------------------------------------------*/
+
+/* rflags masks */
+#define AMD64G_CC_SHIFT_O   11
+#define AMD64G_CC_SHIFT_S   7
+#define AMD64G_CC_SHIFT_Z   6
+#define AMD64G_CC_SHIFT_A   4
+#define AMD64G_CC_SHIFT_C   0
+#define AMD64G_CC_SHIFT_P   2
+
+#define AMD64G_CC_MASK_O    (1 << AMD64G_CC_SHIFT_O)
+#define AMD64G_CC_MASK_S    (1 << AMD64G_CC_SHIFT_S)
+#define AMD64G_CC_MASK_Z    (1 << AMD64G_CC_SHIFT_Z)
+#define AMD64G_CC_MASK_A    (1 << AMD64G_CC_SHIFT_A)
+#define AMD64G_CC_MASK_C    (1 << AMD64G_CC_SHIFT_C)
+#define AMD64G_CC_MASK_P    (1 << AMD64G_CC_SHIFT_P)
+
+/* FPU flag masks */
+//#define AMD64G_FC_MASK_C3   (1 << 14)
+//#define AMD64G_FC_MASK_C2   (1 << 10)
+//#define AMD64G_FC_MASK_C1   (1 << 9)
+//#define AMD64G_FC_MASK_C0   (1 << 8)
+
+/* %RFLAGS thunk descriptors.  A four-word thunk is used to record
+   details of the most recent flag-setting operation, so the flags can
+   be computed later if needed.  It is possible to do this a little
+   more efficiently using a 3-word thunk, but that makes it impossible
+   to describe the flag data dependencies sufficiently accurately for
+   Memcheck.  Hence 4 words are used, with minimal loss of efficiency.
+
+   The four words are:
+
+      CC_OP, which describes the operation.
+
+      CC_DEP1 and CC_DEP2.  These are arguments to the operation.
+         We want Memcheck to believe that the resulting flags are
+         data-dependent on both CC_DEP1 and CC_DEP2, hence the 
+         name DEP.
+
+      CC_NDEP.  This is a 3rd argument to the operation which is
+         sometimes needed.  We arrange things so that Memcheck does
+         not believe the resulting flags are data-dependent on CC_NDEP
+         ("not dependent").
+
+   To make Memcheck believe that (the definedness of) the encoded
+   flags depends only on (the definedness of) CC_DEP1 and CC_DEP2
+   requires two things:
+
+   (1) In the guest state layout info (amd64guest_layout), CC_OP and
+       CC_NDEP are marked as always defined.
+
+   (2) When passing the thunk components to an evaluation function
+       (calculate_condition, calculate_eflags, calculate_eflags_c) the
+       IRCallee's mcx_mask must be set so as to exclude from
+       consideration all passed args except CC_DEP1 and CC_DEP2.
+
+   Strictly speaking only (2) is necessary for correctness.  However,
+   (1) helps efficiency in that since (2) means we never ask about the
+   definedness of CC_OP or CC_NDEP, we may as well not even bother to
+   track their definedness.
+
+   When building the thunk, it is always necessary to write words into
+   CC_DEP1 and CC_DEP2, even if those args are not used given the
+   CC_OP field (eg, CC_DEP2 is not used if CC_OP is CC_LOGIC1/2/4).
+   This is important because otherwise Memcheck could give false
+   positives as it does not understand the relationship between the
+   CC_OP field and CC_DEP1 and CC_DEP2, and so believes that the 
+   definedness of the stored flags always depends on both CC_DEP1 and
+   CC_DEP2.
+
+   However, it is only necessary to set CC_NDEP when the CC_OP value
+   requires it, because Memcheck ignores CC_NDEP, and the evaluation
+   functions do understand the CC_OP fields and will only examine
+   CC_NDEP for suitable values of CC_OP.
+
+   A summary of the field usages is:
+
+   Operation          DEP1               DEP2               NDEP
+   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+   add/sub/mul        first arg          second arg         unused
+
+   adc/sbb            first arg          (second arg)
+                                         XOR old_carry      old_carry
+
+   and/or/xor         result             zero               unused
+
+   inc/dec            result             zero               old_carry
+
+   shl/shr/sar        result             subshifted-        unused
+                                         result
+
+   rol/ror            result             zero               old_flags
+
+   copy               old_flags          zero               unused.
+
+
+   Therefore Memcheck will believe the following:
+
+   * add/sub/mul -- definedness of result flags depends on definedness
+     of both args.
+
+   * adc/sbb -- definedness of result flags depends on definedness of
+     both args and definedness of the old C flag.  Because only two
+     DEP fields are available, the old C flag is XOR'd into the second
+     arg so that Memcheck sees the data dependency on it.  That means
+     the NDEP field must contain a second copy of the old C flag
+     so that the evaluation functions can correctly recover the second
+     arg.
+
+   * and/or/xor are straightforward -- definedness of result flags
+     depends on definedness of result value.
+
+   * inc/dec -- definedness of result flags depends only on
+     definedness of result.  This isn't really true -- it also depends
+     on the old C flag.  However, we don't want Memcheck to see that,
+     and so the old C flag must be passed in NDEP and not in DEP2.
+     It's inconceivable that a compiler would generate code that puts
+     the C flag in an undefined state, then does an inc/dec, which
+     leaves C unchanged, and then makes a conditional jump/move based
+     on C.  So our fiction seems a good approximation.
+
+   * shl/shr/sar -- straightforward, again, definedness of result
+     flags depends on definedness of result value.  The subshifted
+     value (value shifted one less) is also needed, but its
+     definedness is the same as the definedness of the shifted value.
+
+   * rol/ror -- these only set O and C, and leave A Z C P alone.
+     However it seems prudent (as per inc/dec) to say the definedness
+     of all resulting flags depends on the definedness of the result,
+     hence the old flags must go in as NDEP and not DEP2.
+
+   * rcl/rcr are too difficult to do in-line, and so are done by a
+     helper function.  They are not part of this scheme.  The helper
+     function takes the value to be rotated, the rotate amount and the
+     old flags, and returns the new flags and the rotated value.
+     Since the helper's mcx_mask does not have any set bits, Memcheck
+     will lazily propagate undefinedness from any of the 3 args into 
+     both results (flags and actual value).
+*/
+enum {
+    AMD64G_CC_OP_COPY,    /* DEP1 = current flags, DEP2 = 0, NDEP = unused */
+                          /* just copy DEP1 to output */
+
+    AMD64G_CC_OP_ADDB,    /* 1 */
+    AMD64G_CC_OP_ADDW,    /* 2 DEP1 = argL, DEP2 = argR, NDEP = unused */
+    AMD64G_CC_OP_ADDL,    /* 3 */
+
+    AMD64G_CC_OP_SUBB,    /* 4 */
+    AMD64G_CC_OP_SUBW,    /* 5 DEP1 = argL, DEP2 = argR, NDEP = unused */
+    AMD64G_CC_OP_SUBL,    /* 6 */
+
+    AMD64G_CC_OP_ADCB,    /* 7 */
+    AMD64G_CC_OP_ADCW,    /* 8 DEP1 = argL, DEP2 = argR ^ oldCarry, NDEP = oldCarry */
+    AMD64G_CC_OP_ADCL,    /* 9 */
+
+    AMD64G_CC_OP_SBBB,    /* 10 */
+    AMD64G_CC_OP_SBBW,    /* 11 DEP1 = argL, DEP2 = argR ^ oldCarry, NDEP = oldCarry */
+    AMD64G_CC_OP_SBBL,    /* 12 */
+
+    AMD64G_CC_OP_LOGICB,  /* 13 */
+    AMD64G_CC_OP_LOGICW,  /* 14 DEP1 = result, DEP2 = 0, NDEP = unused */
+    AMD64G_CC_OP_LOGICL,  /* 15 */
+
+    AMD64G_CC_OP_INCB,    /* 16 */
+    AMD64G_CC_OP_INCW,    /* 17 DEP1 = result, DEP2 = 0, NDEP = oldCarry (0 or 1) */
+    AMD64G_CC_OP_INCL,    /* 18 */
+
+    AMD64G_CC_OP_DECB,    /* 19 */
+    AMD64G_CC_OP_DECW,    /* 20 DEP1 = result, DEP2 = 0, NDEP = oldCarry (0 or 1) */
+    AMD64G_CC_OP_DECL,    /* 21 */
+
+    AMD64G_CC_OP_SHLB,    /* 22 DEP1 = res, DEP2 = res', NDEP = unused */
+    AMD64G_CC_OP_SHLW,    /* 23 where res' is like res but shifted one bit less */
+    AMD64G_CC_OP_SHLL,    /* 24 */
+
+    AMD64G_CC_OP_SHRB,    /* 25 DEP1 = res, DEP2 = res', NDEP = unused */
+    AMD64G_CC_OP_SHRW,    /* 26 where res' is like res but shifted one bit less */
+    AMD64G_CC_OP_SHRL,    /* 27 */
+
+    AMD64G_CC_OP_ROLB,    /* 28 */
+    AMD64G_CC_OP_ROLW,    /* 29 DEP1 = res, DEP2 = 0, NDEP = old flags */
+    AMD64G_CC_OP_ROLL,    /* 30 */
+
+    AMD64G_CC_OP_RORB,    /* 31 */
+    AMD64G_CC_OP_RORW,    /* 32 DEP1 = res, DEP2 = 0, NDEP = old flags */
+    AMD64G_CC_OP_RORL,    /* 33 */
+
+    AMD64G_CC_OP_UMULB,   /* 34 */
+    AMD64G_CC_OP_UMULW,   /* 35 DEP1 = argL, DEP2 = argR, NDEP = unused */
+    AMD64G_CC_OP_UMULL,   /* 36 */
+
+    AMD64G_CC_OP_SMULB,   /* 37 */
+    AMD64G_CC_OP_SMULW,   /* 38 DEP1 = argL, DEP2 = argR, NDEP = unused */
+    AMD64G_CC_OP_SMULL,   /* 39 */
+
+    AMD64G_CC_OP_NUMBER
+};
+
+typedef
+   enum {
+      AMD64CondO      = 0,  /* overflow           */
+      AMD64CondNO     = 1,  /* no overflow        */
+
+      AMD64CondB      = 2,  /* below              */
+      AMD64CondNB     = 3,  /* not below          */
+
+      AMD64CondZ      = 4,  /* zero               */
+      AMD64CondNZ     = 5,  /* not zero           */
+
+      AMD64CondBE     = 6,  /* below or equal     */
+      AMD64CondNBE    = 7,  /* not below or equal */
+
+      AMD64CondS      = 8,  /* negative           */
+      AMD64CondNS     = 9,  /* not negative       */
+
+      AMD64CondP      = 10, /* parity even        */
+      AMD64CondNP     = 11, /* not parity even    */
+
+      AMD64CondL      = 12, /* jump less          */
+      AMD64CondNL     = 13, /* not less           */
+
+      AMD64CondLE     = 14, /* less or equal      */
+      AMD64CondNLE    = 15, /* not less or equal  */
+
+      AMD64CondAlways = 16  /* HACK */
+   }
+   AMD64Condcode;
+
+#endif /* ndef __LIBVEX_GUEST_AMD64_DEFS_H */
+
+/*---------------------------------------------------------------*/
+/*--- end                                 guest-amd64/gdefs.h ---*/
+/*---------------------------------------------------------------*/
diff --git a/VEX/priv/guest-amd64/toIR.c b/VEX/priv/guest-amd64/toIR.c
new file mode 100644 (file)
index 0000000..38c9e0c
--- /dev/null
@@ -0,0 +1,12060 @@
+
+/*--------------------------------------------------------------------*/
+/*---                                                              ---*/
+/*--- This file (guest-amd64/toIR.c) is                            ---*/
+/*--- Copyright (c) 2004 OpenWorks LLP.  All rights reserved.      ---*/
+/*---                                                              ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+   This file is part of LibVEX, a library for dynamic binary
+   instrumentation and translation.
+
+   Copyright (C) 2004-2005 OpenWorks, LLP.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; Version 2 dated June 1991 of the
+   license.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or liability
+   for damages.  See the GNU General Public License for more details.
+
+   Neither the names of the U.S. Department of Energy nor the
+   University of California nor the names of its contributors may be
+   used to endorse or promote products derived from this software
+   without prior written permission.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+   USA.
+*/
+
+//.. /* TODO:
+//..    SBB reg with itself
+//.. 
+//..    check flag settings for cmpxchg
+//..    FUCOMI(P): what happens to A and S flags?  Currently are forced
+//..       to zero.
+//.. 
+//..    x87 FP Limitations:
+//.. 
+//..    * all arithmetic done at 64 bits
+//.. 
+//..    * no FP exceptions, except for handling stack over/underflow
+//.. 
+//..    * FP rounding mode observed only for float->int conversions
+//..      and int->float conversions which could lose accuracy, and
+//..      for float-to-float rounding.  For all other operations, 
+//..      round-to-nearest is used, regardless.
+//.. 
+//..    * FP sin/cos/tan/sincos: C2 flag is always cleared.  IOW the
+//..      simulation claims the argument is in-range (-2^63 <= arg <= 2^63)
+//..      even when it isn't.
+//.. 
+//..    * some of the FCOM cases could do with testing -- not convinced
+//..      that the args are the right way round.
+//.. 
+//..    * FSAVE does not re-initialise the FPU; it should do
+//.. 
+//..    * FINIT not only initialises the FPU environment, it also
+//..      zeroes all the FP registers.  It should leave the registers
+//..      unchanged.
+//.. 
+//..    RDTSC returns zero, always.
+//.. 
+//..    SAHF should cause eflags[1] == 1, and in fact it produces 0.  As
+//..    per Intel docs this bit has no meaning anyway.  Since PUSHF is the
+//..    only way to observe eflags[1], a proper fix would be to make that
+//..    bit be set by PUSHF.
+//.. 
+//..    This module uses global variables and so is not MT-safe (if that
+//..    should ever become relevant).  */
+//.. 
+//.. /* Translates AMD64 code to IR. */
+//.. 
+//.. #include "libvex_basictypes.h"
+//.. #include "libvex_ir.h"
+//.. #include "libvex.h"
+//.. #include "libvex_guest_amd64.h"
+//.. 
+//.. #include "main/vex_util.h"
+//.. #include "main/vex_globals.h"
+//.. #include "guest-amd64/gdefs.h"
+//.. 
+//.. 
+//.. /*------------------------------------------------------------*/
+//.. /*--- Globals                                              ---*/
+//.. /*------------------------------------------------------------*/
+//.. 
+//.. /* These are set at the start of the translation of a BB, so
+//..    that we don't have to pass them around endlessly. */
+//.. 
+//.. /* We need to know this to do sub-register accesses correctly. */
+//.. /* CONST */
+//.. static Bool host_is_bigendian;
+//.. 
+//.. /* Pointer to the guest code area. */
+//.. /* CONST */
+//.. static UChar* guest_code;
+//.. 
+//.. /* The guest address corresponding to guest_code[0]. */
+//.. /* CONST */
+//.. static Addr32 guest_eip_bbstart;
+//.. 
+//.. /* The guest address for the instruction currently being
+//..    translated. */
+//.. /* CONST for any specific insn, not for the entire BB */
+//.. static Addr32 guest_eip_curr_instr;
+//.. 
+//.. /* The IRBB* into which we're generating code. */
+//.. static IRBB* irbb;
+//.. 
+//.. /* Emergency verboseness just for this insn?  DEBUG ONLY */
+//.. static Bool  insn_verbose = False;
+//.. 
+//.. 
+//.. /*------------------------------------------------------------*/
+//.. /*--- Debugging output                                     ---*/
+//.. /*------------------------------------------------------------*/
+//.. 
+//.. #define DIP(format, args...)           \
+//..    if (insn_verbose || (vex_traceflags & VEX_TRACE_FE))  \
+//..       vex_printf(format, ## args)
+//.. 
+//.. #define DIS(buf, format, args...)      \
+//..    if (insn_verbose || (vex_traceflags & VEX_TRACE_FE))  \
+//..       vex_sprintf(buf, format, ## args)
+//.. 
+//.. 
+//.. /*------------------------------------------------------------*/
+//.. /*--- Offsets of various parts of the x86 guest state.     ---*/
+//.. /*------------------------------------------------------------*/
+//.. 
+//.. #define OFFB_EAX       offsetof(VexGuestX86State,guest_EAX)
+//.. #define OFFB_EBX       offsetof(VexGuestX86State,guest_EBX)
+//.. #define OFFB_ECX       offsetof(VexGuestX86State,guest_ECX)
+//.. #define OFFB_EDX       offsetof(VexGuestX86State,guest_EDX)
+//.. #define OFFB_ESP       offsetof(VexGuestX86State,guest_ESP)
+//.. #define OFFB_EBP       offsetof(VexGuestX86State,guest_EBP)
+//.. #define OFFB_ESI       offsetof(VexGuestX86State,guest_ESI)
+//.. #define OFFB_EDI       offsetof(VexGuestX86State,guest_EDI)
+//.. 
+//.. #define OFFB_EIP       offsetof(VexGuestX86State,guest_EIP)
+//.. 
+//.. #define OFFB_CC_OP     offsetof(VexGuestX86State,guest_CC_OP)
+//.. #define OFFB_CC_DEP1   offsetof(VexGuestX86State,guest_CC_DEP1)
+//.. #define OFFB_CC_DEP2   offsetof(VexGuestX86State,guest_CC_DEP2)
+//.. #define OFFB_CC_NDEP   offsetof(VexGuestX86State,guest_CC_NDEP)
+//.. 
+//.. #define OFFB_FPREGS    offsetof(VexGuestX86State,guest_FPREG[0])
+//.. #define OFFB_FPTAGS    offsetof(VexGuestX86State,guest_FPTAG[0])
+//.. #define OFFB_DFLAG     offsetof(VexGuestX86State,guest_DFLAG)
+//.. #define OFFB_IDFLAG    offsetof(VexGuestX86State,guest_IDFLAG)
+//.. #define OFFB_FTOP      offsetof(VexGuestX86State,guest_FTOP)
+//.. #define OFFB_FC3210    offsetof(VexGuestX86State,guest_FC3210)
+//.. #define OFFB_FPROUND   offsetof(VexGuestX86State,guest_FPROUND)
+//.. 
+//.. #define OFFB_CS        offsetof(VexGuestX86State,guest_CS)
+//.. #define OFFB_DS        offsetof(VexGuestX86State,guest_DS)
+//.. #define OFFB_ES        offsetof(VexGuestX86State,guest_ES)
+//.. #define OFFB_FS        offsetof(VexGuestX86State,guest_FS)
+//.. #define OFFB_GS        offsetof(VexGuestX86State,guest_GS)
+//.. #define OFFB_SS        offsetof(VexGuestX86State,guest_SS)
+//.. #define OFFB_LDT       offsetof(VexGuestX86State,guest_LDT)
+//.. #define OFFB_GDT       offsetof(VexGuestX86State,guest_GDT)
+//.. 
+//.. #define OFFB_SSEROUND  offsetof(VexGuestX86State,guest_SSEROUND)
+//.. #define OFFB_XMM0      offsetof(VexGuestX86State,guest_XMM0)
+//.. #define OFFB_XMM1      offsetof(VexGuestX86State,guest_XMM1)
+//.. #define OFFB_XMM2      offsetof(VexGuestX86State,guest_XMM2)
+//.. #define OFFB_XMM3      offsetof(VexGuestX86State,guest_XMM3)
+//.. #define OFFB_XMM4      offsetof(VexGuestX86State,guest_XMM4)
+//.. #define OFFB_XMM5      offsetof(VexGuestX86State,guest_XMM5)
+//.. #define OFFB_XMM6      offsetof(VexGuestX86State,guest_XMM6)
+//.. #define OFFB_XMM7      offsetof(VexGuestX86State,guest_XMM7)
+//.. 
+//.. #define OFFB_EMWARN    offsetof(VexGuestX86State,guest_EMWARN)
+//.. 
+//.. 
+//.. /*------------------------------------------------------------*/
+//.. /*--- Disassemble an entire basic block                    ---*/
+//.. /*------------------------------------------------------------*/
+//.. 
+//.. /* The results of disassembling an instruction.  There are three
+//..    possible outcomes.  For Dis_Resteer, the disassembler _must_
+//..    continue at the specified address.  For Dis_StopHere, the
+//..    disassembler _must_ terminate the BB.  For Dis_Continue, we may at
+//..    our option either disassemble the next insn, or terminate the BB;
+//..    but in the latter case we must set the bb's ->next field to point
+//..    to the next instruction.  */
+//.. 
+//.. typedef
+//..    enum { 
+//..       Dis_StopHere, /* this insn terminates the BB; we must stop. */
+//..       Dis_Continue, /* we can optionally continue into the next insn */
+//..       Dis_Resteer   /* followed a branch; continue at the spec'd addr */
+//..    }
+//..    DisResult;
+//.. 
+//.. 
+//.. /* forward decls .. */
+//.. static IRExpr* mkU32 ( UInt i );
+//.. static void stmt ( IRStmt* st );
+//.. 
+//.. 
+//.. /* disInstr disassembles an instruction located at &guest_code[delta],
+//..    and sets *size to its size.  If the returned value is Dis_Resteer,
+//..    the next guest address is assigned to *whereNext.  disInstr is not
+//..    permitted to return Dis_Resteer if either (1) resteerOK is False,
+//..    or (2) resteerOkFn, when applied to the address which it wishes to
+//..    resteer into, returns False.  */
+//..    
+//.. static 
+//.. DisResult disInstr ( /*IN*/  Bool       resteerOK,
+//..                      /*IN*/  Bool       (*resteerOkFn) ( Addr64 ),
+//..                      /*IN*/  UInt       delta, 
+//..                      /*IN*/  VexSubArch subarch,
+//..                      /*OUT*/ UInt*      size,
+//..                      /*OUT*/ Addr64*    whereNext );
+//.. 
+//.. 
+//.. /* This is the main (only, in fact) entry point for this module. */
+//.. 
+//.. /* Disassemble a complete basic block, starting at eip, and dumping
+//..    the ucode into cb.  Returns the size, in bytes, of the basic
+//..    block. */
+//.. IRBB* bbToIR_X86 ( UChar*           x86code, 
+//..                    Addr64           guest_eip_start, 
+//..                    VexGuestExtents* vge, 
+//..                    Bool             (*byte_accessible)(Addr64),
+//..                    Bool             (*chase_into_ok)(Addr64),
+//..                    Bool             host_bigendian,
+//..                    VexSubArch       subarch_guest )
+//.. {
+//..    UInt       delta;
+//..    Int        i, n_instrs, size, first_stmt_idx;
+//..    Addr64     guest_next;
+//..    Bool       resteerOK;
+//..    DisResult  dres;
+//..    static Int n_resteers = 0;
+//..    Int        d_resteers = 0;
+//.. 
+//..    /* check sanity .. */
+//..    vassert(vex_control.guest_max_insns >= 1);
+//..    vassert(vex_control.guest_max_insns < 500);
+//..    vassert(vex_control.guest_chase_thresh >= 0);
+//..    vassert(vex_control.guest_chase_thresh < vex_control.guest_max_insns);
+//.. 
+//..    vassert(subarch_guest == VexSubArchX86_sse0
+//..            || subarch_guest == VexSubArchX86_sse1
+//..            || subarch_guest == VexSubArchX86_sse2);
+//.. 
+//..    vassert((guest_eip_start >> 32) == 0);
+//.. 
+//..    /* Start a new, empty extent. */
+//..    vge->n_used  = 1;
+//..    vge->base[0] = guest_eip_start;
+//..    vge->len[0]  = 0;
+//.. 
+//..    /* Set up globals. */
+//..    host_is_bigendian = host_bigendian;
+//..    guest_code        = x86code;
+//..    guest_eip_bbstart = (Addr32)guest_eip_start;
+//..    irbb              = emptyIRBB();
+//..    insn_verbose      = False;
+//.. 
+//..    /* Delta keeps track of how far along the x86code array we
+//..       have so far gone. */
+//..    delta             = 0;
+//..    n_instrs          = 0;
+//.. 
+//..    while (True) {
+//..       vassert(n_instrs < vex_control.guest_max_insns);
+//.. 
+//..       guest_next = 0;
+//..       resteerOK 
+//..          = n_instrs < vex_control.guest_chase_thresh
+//..            /* we can't afford to have a resteer once we're on the last
+//..               extent slot. */
+//..            && vge->n_used < 3;
+//.. 
+//..       first_stmt_idx = irbb->stmts_used;
+//.. 
+//..       if (n_instrs > 0) {
+//..          /* for the first insn, the dispatch loop will have set
+//..             %EIP, but for all the others we have to do it ourselves. */
+//..          stmt( IRStmt_Put( OFFB_EIP, mkU32(guest_eip_bbstart + delta)) );
+//..       }
+//.. 
+//..       guest_eip_curr_instr = guest_eip_bbstart + delta;
+//.. 
+//..       dres = disInstr( resteerOK, chase_into_ok, 
+//..                        delta, subarch_guest, &size, &guest_next );
+//..       insn_verbose = False;
+//.. 
+//..       /* Print the resulting IR, if needed. */
+//..       if (vex_traceflags & VEX_TRACE_FE) {
+//..          for (i = first_stmt_idx; i < irbb->stmts_used; i++) {
+//..             vex_printf("              ");
+//..             ppIRStmt(irbb->stmts[i]);
+//..             vex_printf("\n");
+//..          }
+//..       }
+//..    
+//..       if (dres == Dis_StopHere) {
+//..          vassert(irbb->next != NULL);
+//..          if (vex_traceflags & VEX_TRACE_FE) {
+//..             vex_printf("              ");
+//..             vex_printf( "goto {");
+//..             ppIRJumpKind(irbb->jumpkind);
+//..             vex_printf( "} ");
+//..             ppIRExpr( irbb->next );
+//..             vex_printf( "\n");
+//..          }
+//..       }
+//.. 
+//..       delta += size;
+//..       vge->len[vge->n_used-1] += size;
+//..       n_instrs++;
+//..       DIP("\n");
+//.. 
+//..       vassert(size >= 0 && size <= 18);
+//..       if (!resteerOK) 
+//..          vassert(dres != Dis_Resteer);
+//..       if (dres != Dis_Resteer) 
+//..          vassert(guest_next == 0);
+//.. 
+//..       switch (dres) {
+//..          case Dis_Continue:
+//..             vassert(irbb->next == NULL);
+//..             if (n_instrs < vex_control.guest_max_insns) {
+//..                /* keep going */
+//..             } else {
+//..                irbb->next = mkU32(((Addr32)guest_eip_start)+delta);
+//..                return irbb;
+//..             }
+//..             break;
+//..          case Dis_StopHere:
+//..             vassert(irbb->next != NULL);
+//..             return irbb;
+//..          case Dis_Resteer:
+//..             vassert(irbb->next == NULL);
+//..             /* figure out a new delta to continue at. */
+//..             vassert(chase_into_ok(guest_next));
+//..             delta = (UInt)(guest_next - guest_eip_start);
+//..             /* we now have to start a new extent slot. */
+//..       vge->n_used++;
+//..       vassert(vge->n_used <= 3);
+//..             vge->base[vge->n_used-1] = guest_next;
+//..             vge->len[vge->n_used-1] = 0;
+//..             n_resteers++;
+//..             d_resteers++;
+//..             if (0 && (n_resteers & 0xFF) == 0)
+//..             vex_printf("resteer[%d,%d] to %p (delta = %d)\n",
+//..                        n_resteers, d_resteers,
+//..                        (void*)(UInt)(guest_next), delta);
+//..             break;
+//..       }
+//..    }
+//.. }
+//.. 
+//.. 
+//.. /*------------------------------------------------------------*/
+//.. /*--- Helper bits and pieces for deconstructing the        ---*/
+//.. /*--- x86 insn stream.                                     ---*/
+//.. /*------------------------------------------------------------*/
+//.. 
+//.. /* This is the Intel register encoding -- integer regs. */
+//.. #define R_EAX 0
+//.. #define R_ECX 1
+//.. #define R_EDX 2
+//.. #define R_EBX 3
+//.. #define R_ESP 4
+//.. #define R_EBP 5
+//.. #define R_ESI 6
+//.. #define R_EDI 7
+//.. 
+//.. #define R_AL (0+R_EAX)
+//.. #define R_AH (4+R_EAX)
+//.. 
+//.. /* This is the Intel register encoding -- segment regs. */
+//.. #define R_ES 0
+//.. #define R_CS 1
+//.. #define R_SS 2
+//.. #define R_DS 3
+//.. #define R_FS 4
+//.. #define R_GS 5
+//.. 
+//.. 
+//.. /* Add a statement to the list held by "irbb". */
+//.. static void stmt ( IRStmt* st )
+//.. {
+//..    addStmtToIRBB( irbb, st );
+//.. }
+//.. 
+//.. /* Generate a new temporary of the given type. */
+//.. static IRTemp newTemp ( IRType ty )
+//.. {
+//..    vassert(isPlausibleType(ty));
+//..    return newIRTemp( irbb->tyenv, ty );
+//.. }
+//.. 
+//.. /* Bomb out if we can't handle something. */
+//.. __attribute__ ((noreturn))
+//.. static void unimplemented ( Char* str )
+//.. {
+//..    vex_printf("x86toIR: unimplemented feature\n");
+//..    vpanic(str);
+//.. }
+//.. 
+//.. /* Various simple conversions */
+//.. 
+//.. static UInt extend_s_8to32( UInt x )
+//.. {
+//..    return (UInt)((((Int)x) << 24) >> 24);
+//.. }
+//.. 
+//.. static UInt extend_s_16to32 ( UInt x )
+//.. {
+//..    return (UInt)((((Int)x) << 16) >> 16);
+//.. }
+//.. 
+//.. /* Fetch a byte from the guest insn stream. */
+//.. static UChar getIByte ( UInt delta )
+//.. {
+//..    return guest_code[delta];
+//.. }
+//.. 
+//.. /* Extract the reg field from a modRM byte. */
+//.. static Int gregOfRM ( UChar mod_reg_rm )
+//.. {
+//..    return (Int)( (mod_reg_rm >> 3) & 7 );
+//.. }
+//.. 
+//.. /* Figure out whether the mod and rm parts of a modRM byte refer to a
+//..    register or memory.  If so, the byte will have the form 11XXXYYY,
+//..    where YYY is the register number. */
+//.. static Bool epartIsReg ( UChar mod_reg_rm )
+//.. {
+//..    return (0xC0 == (mod_reg_rm & 0xC0));
+//.. }
+//.. 
+//.. /* ... and extract the register number ... */
+//.. static Int eregOfRM ( UChar mod_reg_rm )
+//.. {
+//..    return (Int)(mod_reg_rm & 0x7);
+//.. }
+//.. 
+//.. /* Get a 8/16/32-bit unsigned value out of the insn stream. */
+//.. 
+//.. static UInt getUChar ( UInt delta )
+//.. {
+//..    UInt v = guest_code[delta+0];
+//..    return v & 0xFF;
+//.. }
+//.. 
+//.. static UInt getUDisp16 ( UInt delta )
+//.. {
+//..    UInt v = guest_code[delta+1]; v <<= 8;
+//..    v |= guest_code[delta+0];
+//..    return v & 0xFFFF;
+//.. }
+//.. 
+//.. static UInt getUDisp32 ( UInt delta )
+//.. {
+//..    UInt v = guest_code[delta+3]; v <<= 8;
+//..    v |= guest_code[delta+2]; v <<= 8;
+//..    v |= guest_code[delta+1]; v <<= 8;
+//..    v |= guest_code[delta+0];
+//..    return v;
+//.. }
+//.. 
+//.. static UInt getUDisp ( Int size, UInt delta )
+//.. {
+//..    switch (size) {
+//..       case 4: return getUDisp32(delta);
+//..       case 2: return getUDisp16(delta);
+//..       case 1: return getUChar(delta);
+//..       default: vpanic("getUDisp(x86)");
+//..    }
+//..    return 0; /*notreached*/
+//.. }
+//.. 
+//.. 
+//.. /* Get a byte value out of the insn stream and sign-extend to 32
+//..    bits. */
+//.. static UInt getSDisp8 ( UInt delta )
+//.. {
+//..    return extend_s_8to32( (UInt) (guest_code[delta]) );
+//.. }
+//.. 
+//.. static UInt getSDisp16 ( UInt delta0 )
+//.. {
+//..    UChar* eip = (UChar*)(&guest_code[delta0]);
+//..    UInt d = *eip++;
+//..    d |= ((*eip++) << 8);
+//..    return extend_s_16to32(d);
+//.. }
+//.. 
+//.. static UInt getSDisp ( Int size, UInt delta )
+//.. {
+//..    switch (size) {
+//..       case 4: return getUDisp32(delta);
+//..       case 2: return getSDisp16(delta);
+//..       case 1: return getSDisp8(delta);
+//..       default: vpanic("getSDisp(x86)");
+//..   }
+//..   return 0; /*notreached*/
+//.. }
+//.. 
+//.. 
+//.. /*------------------------------------------------------------*/
+//.. /*--- Helpers for constructing IR.                         ---*/
+//.. /*------------------------------------------------------------*/
+//.. 
+//.. /* Create a 1/2/4 byte read of an x86 integer registers.  For 16/8 bit
+//..    register references, we need to take the host endianness into
+//..    account.  Supplied value is 0 .. 7 and in the Intel instruction
+//..    encoding. */
+//.. 
+//.. static IRType szToITy ( Int n )
+//.. {
+//..    switch (n) {
+//..       case 1: return Ity_I8;
+//..       case 2: return Ity_I16;
+//..       case 4: return Ity_I32;
+//..       default: vpanic("szToITy(x86)");
+//..    }
+//.. }
+//.. 
+//.. /* On a little-endian host, less significant bits of the guest
+//..    registers are at lower addresses.  Therefore, if a reference to a
+//..    register low half has the safe guest state offset as a reference to
+//..    the full register.
+//.. */
+//.. static Int integerGuestRegOffset ( Int sz, UInt archreg )
+//.. {
+//..    vassert(archreg < 8);
+//.. 
+//..    /* Correct for little-endian host only. */
+//..    vassert(!host_is_bigendian);
+//.. 
+//..    if (sz == 4 || sz == 2 || (sz == 1 && archreg < 4)) {
+//..       switch (archreg) {
+//..          case R_EAX: return OFFB_EAX;
+//..          case R_EBX: return OFFB_EBX;
+//..          case R_ECX: return OFFB_ECX;
+//..          case R_EDX: return OFFB_EDX;
+//..          case R_ESI: return OFFB_ESI;
+//..          case R_EDI: return OFFB_EDI;
+//..          case R_ESP: return OFFB_ESP;
+//..          case R_EBP: return OFFB_EBP;
+//..          default: vpanic("integerGuestRegOffset(x86,le)(4,2)");
+//..       }
+//..    }
+//.. 
+//..    vassert(archreg >= 4 && archreg < 8 && sz == 1);
+//..    switch (archreg-4) {
+//..       case R_EAX: return 1+ OFFB_EAX;
+//..       case R_EBX: return 1+ OFFB_EBX;
+//..       case R_ECX: return 1+ OFFB_ECX;
+//..       case R_EDX: return 1+ OFFB_EDX;
+//..       default: vpanic("integerGuestRegOffset(x86,le)(1h)");
+//..    }
+//.. 
+//..    /* NOTREACHED */
+//..    vpanic("integerGuestRegOffset(x86,le)");
+//.. }
+//.. 
+//.. static Int segmentGuestRegOffset ( UInt sreg )
+//.. {
+//..    switch (sreg) {
+//..       case R_ES: return OFFB_ES;
+//..       case R_CS: return OFFB_CS;
+//..       case R_SS: return OFFB_SS;
+//..       case R_DS: return OFFB_DS;
+//..       case R_FS: return OFFB_FS;
+//..       case R_GS: return OFFB_GS;
+//..       default: vpanic("segmentGuestRegOffset(x86)");
+//..    }
+//.. }
+//.. 
+//.. static Int xmmGuestRegOffset ( UInt xmmreg )
+//.. {
+//..    switch (xmmreg) {
+//..       case 0: return OFFB_XMM0;
+//..       case 1: return OFFB_XMM1;
+//..       case 2: return OFFB_XMM2;
+//..       case 3: return OFFB_XMM3;
+//..       case 4: return OFFB_XMM4;
+//..       case 5: return OFFB_XMM5;
+//..       case 6: return OFFB_XMM6;
+//..       case 7: return OFFB_XMM7;
+//..       default: vpanic("xmmGuestRegOffset");
+//..    }
+//.. }
+//.. 
+//.. /* Lanes of vector registers are always numbered from zero being the
+//..    least significant lane (rightmost in the register).  */
+//.. 
+//.. static Int xmmGuestRegLane16offset ( UInt xmmreg, Int laneno )
+//.. {
+//..    /* Correct for little-endian host only. */
+//..    vassert(!host_is_bigendian);
+//..    vassert(laneno >= 0 && laneno < 8);
+//..    return xmmGuestRegOffset( xmmreg ) + 2 * laneno;
+//.. }
+//.. 
+//.. static Int xmmGuestRegLane32offset ( UInt xmmreg, Int laneno )
+//.. {
+//..    /* Correct for little-endian host only. */
+//..    vassert(!host_is_bigendian);
+//..    vassert(laneno >= 0 && laneno < 4);
+//..    return xmmGuestRegOffset( xmmreg ) + 4 * laneno;
+//.. }
+//.. 
+//.. static Int xmmGuestRegLane64offset ( UInt xmmreg, Int laneno )
+//.. {
+//..    /* Correct for little-endian host only. */
+//..    vassert(!host_is_bigendian);
+//..    vassert(laneno >= 0 && laneno < 2);
+//..    return xmmGuestRegOffset( xmmreg ) + 8 * laneno;
+//.. }
+//.. 
+//.. static IRExpr* getIReg ( Int sz, UInt archreg )
+//.. {
+//..    vassert(sz == 1 || sz == 2 || sz == 4);
+//..    vassert(archreg < 8);
+//..    return IRExpr_Get( integerGuestRegOffset(sz,archreg),
+//..                       szToITy(sz) );
+//.. }
+//.. 
+//.. /* Ditto, but write to a reg instead. */
+//.. static void putIReg ( Int sz, UInt archreg, IRExpr* e )
+//.. {
+//..    IRType ty = typeOfIRExpr(irbb->tyenv, e);
+//..    vassert(sz == 1 || sz == 2 || sz == 4);
+//..    vassert(archreg < 8);
+//..    vassert(ty == Ity_I32 || ty == Ity_I16 || ty == Ity_I8);
+//..    stmt( IRStmt_Put(integerGuestRegOffset(sz,archreg), e) );
+//.. }
+//.. 
+//.. static IRExpr* getSReg ( UInt sreg )
+//.. {
+//..    return IRExpr_Get( segmentGuestRegOffset(sreg), Ity_I16 );
+//.. }
+//.. 
+//.. static void putSReg ( UInt sreg, IRExpr* e )
+//.. {
+//..    vassert(typeOfIRExpr(irbb->tyenv,e) == Ity_I16);
+//..    stmt( IRStmt_Put( segmentGuestRegOffset(sreg), e ) );
+//.. }
+//.. 
+//.. static IRExpr* getXMMReg ( UInt xmmreg )
+//.. {
+//..    return IRExpr_Get( xmmGuestRegOffset(xmmreg), Ity_V128 );
+//.. }
+//.. 
+//.. static IRExpr* getXMMRegLane64 ( UInt xmmreg, Int laneno )
+//.. {
+//..    return IRExpr_Get( xmmGuestRegLane64offset(xmmreg,laneno), Ity_I64 );
+//.. }
+//.. 
+//.. static IRExpr* getXMMRegLane64F ( UInt xmmreg, Int laneno )
+//.. {
+//..    return IRExpr_Get( xmmGuestRegLane64offset(xmmreg,laneno), Ity_F64 );
+//.. }
+//.. 
+//.. static IRExpr* getXMMRegLane32 ( UInt xmmreg, Int laneno )
+//.. {
+//..    return IRExpr_Get( xmmGuestRegLane32offset(xmmreg,laneno), Ity_I32 );
+//.. }
+//.. 
+//.. static IRExpr* getXMMRegLane32F ( UInt xmmreg, Int laneno )
+//.. {
+//..    return IRExpr_Get( xmmGuestRegLane32offset(xmmreg,laneno), Ity_F32 );
+//.. }
+//.. 
+//.. static void putXMMReg ( UInt xmmreg, IRExpr* e )
+//.. {
+//..    vassert(typeOfIRExpr(irbb->tyenv,e) == Ity_V128);
+//..    stmt( IRStmt_Put( xmmGuestRegOffset(xmmreg), e ) );
+//.. }
+//.. 
+//.. static void putXMMRegLane64 ( UInt xmmreg, Int laneno, IRExpr* e )
+//.. {
+//..    vassert(typeOfIRExpr(irbb->tyenv,e) == Ity_I64);
+//..    stmt( IRStmt_Put( xmmGuestRegLane64offset(xmmreg,laneno), e ) );
+//.. }
+//.. 
+//.. static void putXMMRegLane64F ( UInt xmmreg, Int laneno, IRExpr* e )
+//.. {
+//..    vassert(typeOfIRExpr(irbb->tyenv,e) == Ity_F64);
+//..    stmt( IRStmt_Put( xmmGuestRegLane64offset(xmmreg,laneno), e ) );
+//.. }
+//.. 
+//.. static void putXMMRegLane32F ( UInt xmmreg, Int laneno, IRExpr* e )
+//.. {
+//..    vassert(typeOfIRExpr(irbb->tyenv,e) == Ity_F32);
+//..    stmt( IRStmt_Put( xmmGuestRegLane32offset(xmmreg,laneno), e ) );
+//.. }
+//.. 
+//.. static void putXMMRegLane32 ( UInt xmmreg, Int laneno, IRExpr* e )
+//.. {
+//..    vassert(typeOfIRExpr(irbb->tyenv,e) == Ity_I32);
+//..    stmt( IRStmt_Put( xmmGuestRegLane32offset(xmmreg,laneno), e ) );
+//.. }
+//.. 
+//.. static void putXMMRegLane16 ( UInt xmmreg, Int laneno, IRExpr* e )
+//.. {
+//..    vassert(typeOfIRExpr(irbb->tyenv,e) == Ity_I16);
+//..    stmt( IRStmt_Put( xmmGuestRegLane16offset(xmmreg,laneno), e ) );
+//.. }
+//.. 
+//.. static void assign ( IRTemp dst, IRExpr* e )
+//.. {
+//..    stmt( IRStmt_Tmp(dst, e) );
+//.. }
+//.. 
+//.. static void storeLE ( IRExpr* addr, IRExpr* data )
+//.. {
+//..    stmt( IRStmt_STle(addr,data) );
+//.. }
+//.. 
+//.. static IRExpr* unop ( IROp op, IRExpr* a )
+//.. {
+//..    return IRExpr_Unop(op, a);
+//.. }
+//.. 
+//.. static IRExpr* binop ( IROp op, IRExpr* a1, IRExpr* a2 )
+//.. {
+//..    return IRExpr_Binop(op, a1, a2);
+//.. }
+//.. 
+//.. static IRExpr* mkexpr ( IRTemp tmp )
+//.. {
+//..    return IRExpr_Tmp(tmp);
+//.. }
+//.. 
+//.. static IRExpr* mkU8 ( UInt i )
+//.. {
+//..    vassert(i < 256);
+//..    return IRExpr_Const(IRConst_U8(i));
+//.. }
+//.. 
+//.. static IRExpr* mkU16 ( UInt i )
+//.. {
+//..    vassert(i < 65536);
+//..    return IRExpr_Const(IRConst_U16(i));
+//.. }
+//.. 
+//.. static IRExpr* mkU32 ( UInt i )
+//.. {
+//..    return IRExpr_Const(IRConst_U32(i));
+//.. }
+//.. 
+//.. static IRExpr* mkU64 ( ULong i )
+//.. {
+//..    return IRExpr_Const(IRConst_U64(i));
+//.. }
+//.. 
+//.. static IRExpr* mkU ( IRType ty, UInt i )
+//.. {
+//..    if (ty == Ity_I8)  return mkU8(i);
+//..    if (ty == Ity_I16) return mkU16(i);
+//..    if (ty == Ity_I32) return mkU32(i);
+//..    /* If this panics, it usually means you passed a size (1,2,4)
+//..       value as the IRType, rather than a real IRType. */
+//..    vpanic("mkU(x86)");
+//.. }
+//.. 
+//.. static IRExpr* mkV128 ( UShort mask )
+//.. {
+//..    return IRExpr_Const(IRConst_V128(mask));
+//.. }
+//.. 
+//.. static IRExpr* loadLE ( IRType ty, IRExpr* data )
+//.. {
+//..    return IRExpr_LDle(ty,data);
+//.. }
+//.. 
+//.. static IROp mkSizedOp ( IRType ty, IROp op8 )
+//.. {
+//..    Int adj;
+//..    vassert(ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32);
+//..    vassert(op8 == Iop_Add8 || op8 == Iop_Sub8 
+//..            || op8 == Iop_Mul8 
+//..            || op8 == Iop_Or8 || op8 == Iop_And8 || op8 == Iop_Xor8
+//..            || op8 == Iop_Shl8 || op8 == Iop_Shr8 || op8 == Iop_Sar8
+//..            || op8 == Iop_CmpEQ8 || op8 == Iop_CmpNE8
+//..            || op8 == Iop_Not8 );
+//..    adj = ty==Ity_I8 ? 0 : (ty==Ity_I16 ? 1 : 2);
+//..    return adj + op8;
+//.. }
+//.. 
+//.. static IROp mkWidenOp ( Int szSmall, Int szBig, Bool signd )
+//.. {
+//..    if (szSmall == 1 && szBig == 4) {
+//..       return signd ? Iop_8Sto32 : Iop_8Uto32;
+//..    }
+//..    if (szSmall == 1 && szBig == 2) {
+//..       return signd ? Iop_8Sto16 : Iop_8Uto16;
+//..    }
+//..    if (szSmall == 2 && szBig == 4) {
+//..       return signd ? Iop_16Sto32 : Iop_16Uto32;
+//..    }
+//..    vpanic("mkWidenOp(x86,guest)");
+//.. }
+//.. 
+//.. 
+//.. /*------------------------------------------------------------*/
+//.. /*--- Helpers for %eflags.                                 ---*/
+//.. /*------------------------------------------------------------*/
+//.. 
+//.. /* -------------- Evaluating the flags-thunk. -------------- */
+//.. 
+//.. /* Build IR to calculate all the eflags from stored
+//..    CC_OP/CC_DEP1/CC_DEP2/CC_NDEP.  Returns an expression ::
+//..    Ity_I32. */
+//.. static IRExpr* mk_x86g_calculate_eflags_all ( void )
+//.. {
+//..    IRExpr** args
+//..       = mkIRExprVec_4( IRExpr_Get(OFFB_CC_OP,   Ity_I32),
+//..                        IRExpr_Get(OFFB_CC_DEP1, Ity_I32),
+//..                        IRExpr_Get(OFFB_CC_DEP2, Ity_I32),
+//..                        IRExpr_Get(OFFB_CC_NDEP, Ity_I32) );
+//..    IRExpr* call
+//..       = mkIRExprCCall(
+//..            Ity_I32,
+//..            0/*regparm*/, 
+//..            "x86g_calculate_eflags_all", &x86g_calculate_eflags_all,
+//..            args
+//..         );
+//..    /* Exclude OP and NDEP from definedness checking.  We're only
+//..       interested in DEP1 and DEP2. */
+//..    call->Iex.CCall.cee->mcx_mask = (1<<0) | (1<<3);
+//..    return call;
+//.. }
+//.. 
+//.. /* Build IR to calculate some particular condition from stored
+//..    CC_OP/CC_DEP1/CC_DEP2/CC_NDEP.  Returns an expression ::
+//..    Ity_Bit. */
+//.. static IRExpr* mk_x86g_calculate_condition ( X86Condcode cond )
+//.. {
+//..    IRExpr** args
+//..       = mkIRExprVec_5( mkU32(cond),
+//..                        IRExpr_Get(OFFB_CC_OP,  Ity_I32),
+//..                        IRExpr_Get(OFFB_CC_DEP1, Ity_I32),
+//..                        IRExpr_Get(OFFB_CC_DEP2, Ity_I32),
+//..                        IRExpr_Get(OFFB_CC_NDEP, Ity_I32) );
+//..    IRExpr* call
+//..       = mkIRExprCCall(
+//..            Ity_I32,
+//..            0/*regparm*/, 
+//..            "x86g_calculate_condition", &x86g_calculate_condition,
+//..            args
+//..         );
+//..    /* Exclude the requested condition, OP and NDEP from definedness
+//..       checking.  We're only interested in DEP1 and DEP2. */
+//..    call->Iex.CCall.cee->mcx_mask = (1<<0) | (1<<1) | (1<<4);
+//..    return unop(Iop_32to1, call);
+//.. }
+//.. 
+//.. /* Build IR to calculate just the carry flag from stored
+//..    CC_OP/CC_DEP1/CC_DEP2/CC_NDEP.  Returns an expression :: Ity_I32. */
+//.. static IRExpr* mk_x86g_calculate_eflags_c ( void )
+//.. {
+//..    IRExpr** args
+//..       = mkIRExprVec_4( IRExpr_Get(OFFB_CC_OP,   Ity_I32),
+//..                        IRExpr_Get(OFFB_CC_DEP1, Ity_I32),
+//..                        IRExpr_Get(OFFB_CC_DEP2, Ity_I32),
+//..                        IRExpr_Get(OFFB_CC_NDEP, Ity_I32) );
+//..    IRExpr* call
+//..       = mkIRExprCCall(
+//..            Ity_I32,
+//..            0/*regparm*/, 
+//..            "x86g_calculate_eflags_c", &x86g_calculate_eflags_c,
+//..            args
+//..         );
+//..    /* Exclude OP and NDEP from definedness checking.  We're only
+//..       interested in DEP1 and DEP2. */
+//..    call->Iex.CCall.cee->mcx_mask = (1<<0) | (1<<3);
+//..    return call;
+//.. }
+//.. 
+//.. 
+//.. /* -------------- Building the flags-thunk. -------------- */
+//.. 
+//.. /* The machinery in this section builds the flag-thunk following a
+//..    flag-setting operation.  Hence the various setFlags_* functions.
+//.. */
+//.. 
+//.. static Bool isAddSub ( IROp op8 )
+//.. {
+//..    return op8 == Iop_Add8 || op8 == Iop_Sub8;
+//.. }
+//.. 
+//.. static Bool isLogic ( IROp op8 )
+//.. {
+//..    return op8 == Iop_And8 || op8 == Iop_Or8 || op8 == Iop_Xor8;
+//.. }
+//.. 
+//.. /* U-widen 8/16/32 bit int expr to 32. */
+//.. static IRExpr* widenUto32 ( IRExpr* e )
+//.. {
+//..    switch (typeOfIRExpr(irbb->tyenv,e)) {
+//..       case Ity_I32: return e;
+//..       case Ity_I16: return unop(Iop_16Uto32,e);
+//..       case Ity_I8:  return unop(Iop_8Uto32,e);
+//..       default: vpanic("widenUto32");
+//..    }
+//.. }
+//.. 
+//.. /* S-widen 8/16/32 bit int expr to 32. */
+//.. static IRExpr* widenSto32 ( IRExpr* e )
+//.. {
+//..    switch (typeOfIRExpr(irbb->tyenv,e)) {
+//..       case Ity_I32: return e;
+//..       case Ity_I16: return unop(Iop_16Sto32,e);
+//..       case Ity_I8:  return unop(Iop_8Sto32,e);
+//..       default: vpanic("widenSto32");
+//..    }
+//.. }
+//.. 
+//.. /* Narrow 8/16/32 bit int expr to 8/16/32.  Clearly only some
+//..    of these combinations make sense. */
+//.. static IRExpr* narrowTo ( IRType dst_ty, IRExpr* e )
+//.. {
+//..    IRType src_ty = typeOfIRExpr(irbb->tyenv,e);
+//..    if (src_ty == dst_ty)
+//..       return e;
+//..    if (src_ty == Ity_I32 && dst_ty == Ity_I16)
+//..       return unop(Iop_32to16, e);
+//..    if (src_ty == Ity_I32 && dst_ty == Ity_I8)
+//..       return unop(Iop_32to8, e);
+//.. 
+//..    vex_printf("\nsrc, dst tys are: ");
+//..    ppIRType(src_ty);
+//..    vex_printf(", ");
+//..    ppIRType(dst_ty);
+//..    vex_printf("\n");
+//..    vpanic("narrowTo(x86)");
+//.. }
+//.. 
+//.. 
+//.. /* Set the flags thunk OP, DEP1 and DEP2 fields.  The supplied op is
+//..    auto-sized up to the real op. */
+//.. 
+//.. static 
+//.. void setFlags_DEP1_DEP2 ( IROp op8, IRTemp dep1, IRTemp dep2, IRType ty )
+//.. {
+//..    Int ccOp = ty==Ity_I8 ? 0 : (ty==Ity_I16 ? 1 : 2);
+//.. 
+//..    vassert(ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32);
+//.. 
+//..    switch (op8) {
+//..       case Iop_Add8: ccOp += X86G_CC_OP_ADDB;   break;
+//..       case Iop_Sub8: ccOp += X86G_CC_OP_SUBB;   break;
+//..       default:       ppIROp(op8);
+//..                      vpanic("setFlags_DEP1_DEP2(x86)");
+//..    }
+//..    stmt( IRStmt_Put( OFFB_CC_OP,   mkU32(ccOp)) );
+//..    stmt( IRStmt_Put( OFFB_CC_DEP1, widenUto32(mkexpr(dep1))) );
+//..    stmt( IRStmt_Put( OFFB_CC_DEP2, widenUto32(mkexpr(dep2))) );
+//.. }
+//.. 
+//.. 
+//.. /* Set the OP and DEP1 fields only, and write zero to DEP2. */
+//.. 
+//.. static 
+//.. void setFlags_DEP1 ( IROp op8, IRTemp dep1, IRType ty )
+//.. {
+//..    Int ccOp = ty==Ity_I8 ? 0 : (ty==Ity_I16 ? 1 : 2);
+//.. 
+//..    vassert(ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32);
+//.. 
+//..    switch (op8) {
+//..       case Iop_Or8:
+//..       case Iop_And8:
+//..       case Iop_Xor8: ccOp += X86G_CC_OP_LOGICB; break;
+//..       default:       ppIROp(op8);
+//..                      vpanic("setFlags_DEP1(x86)");
+//..    }
+//..    stmt( IRStmt_Put( OFFB_CC_OP,   mkU32(ccOp)) );
+//..    stmt( IRStmt_Put( OFFB_CC_DEP1, widenUto32(mkexpr(dep1))) );
+//..    stmt( IRStmt_Put( OFFB_CC_DEP2, mkU32(0)) );
+//.. }
+//.. 
+//.. 
+//.. /* For shift operations, we put in the result and the undershifted
+//..    result.  Except if the shift amount is zero, the thunk is left
+//..    unchanged. */
+//.. 
+//.. static void setFlags_DEP1_DEP2_shift ( IROp    op32,
+//..                                        IRTemp  res,
+//..                                        IRTemp  resUS,
+//..                                        IRType  ty,
+//..                                        IRTemp  guard )
+//.. {
+//..    Int ccOp = ty==Ity_I8 ? 2 : (ty==Ity_I16 ? 1 : 0);
+//.. 
+//..    vassert(ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32);
+//..    vassert(guard);
+//.. 
+//..    /* Both kinds of right shifts are handled by the same thunk
+//..       operation. */
+//..    switch (op32) {
+//..       case Iop_Shr32:
+//..       case Iop_Sar32: ccOp = X86G_CC_OP_SHRL - ccOp; break;
+//..       case Iop_Shl32: ccOp = X86G_CC_OP_SHLL - ccOp; break;
+//..       default:        ppIROp(op32);
+//..                       vpanic("setFlags_DEP1_DEP2_shift(x86)");
+//..    }
+//.. 
+//..    /* DEP1 contains the result, DEP2 contains the undershifted value. */
+//..    stmt( IRStmt_Put( OFFB_CC_OP,
+//..                      IRExpr_Mux0X( mkexpr(guard),
+//..                                    IRExpr_Get(OFFB_CC_OP,Ity_I32),
+//..                                    mkU32(ccOp))) );
+//..    stmt( IRStmt_Put( OFFB_CC_DEP1,
+//..                      IRExpr_Mux0X( mkexpr(guard),
+//..                                    IRExpr_Get(OFFB_CC_DEP1,Ity_I32),
+//..                                    widenUto32(mkexpr(res)))) );
+//..    stmt( IRStmt_Put( OFFB_CC_DEP2, 
+//..                      IRExpr_Mux0X( mkexpr(guard),
+//..                                    IRExpr_Get(OFFB_CC_DEP2,Ity_I32),
+//..                                    widenUto32(mkexpr(resUS)))) );
+//.. }
+//.. 
+//.. 
+//.. /* For the inc/dec case, we store in DEP1 the result value and in NDEP
+//..    the former value of the carry flag, which unfortunately we have to
+//..    compute. */
+//.. 
+//.. static void setFlags_INC_DEC ( Bool inc, IRTemp res, IRType ty )
+//.. {
+//..    Int ccOp = inc ? X86G_CC_OP_INCB : X86G_CC_OP_DECB;
+//..    
+//..    ccOp += ty==Ity_I8 ? 0 : (ty==Ity_I16 ? 1 : 2);
+//..    vassert(ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32);
+//.. 
+//..    /* This has to come first, because calculating the C flag 
+//..       may require reading all four thunk fields. */
+//..    stmt( IRStmt_Put( OFFB_CC_NDEP, mk_x86g_calculate_eflags_c()) );
+//..    stmt( IRStmt_Put( OFFB_CC_OP,   mkU32(ccOp)) );
+//..    stmt( IRStmt_Put( OFFB_CC_DEP1, mkexpr(res)) );
+//..    stmt( IRStmt_Put( OFFB_CC_DEP2, mkU32(0)) );
+//.. }
+//.. 
+//.. 
+//.. /* Multiplies are pretty much like add and sub: DEP1 and DEP2 hold the
+//..    two arguments. */
+//.. 
+//.. static
+//.. void setFlags_MUL ( IRType ty, IRTemp arg1, IRTemp arg2, UInt base_op )
+//.. {
+//..    switch (ty) {
+//..       case Ity_I8:
+//..          stmt( IRStmt_Put( OFFB_CC_OP, mkU32(base_op+0) ) );
+//..          break;
+//..       case Ity_I16:
+//..          stmt( IRStmt_Put( OFFB_CC_OP, mkU32(base_op+1) ) );
+//..          break;
+//..       case Ity_I32:
+//..          stmt( IRStmt_Put( OFFB_CC_OP, mkU32(base_op+2) ) );
+//..          break;
+//..       default:
+//..          vpanic("setFlags_MUL(x86)");
+//..    }
+//..    stmt( IRStmt_Put( OFFB_CC_DEP1, widenUto32(mkexpr(arg1)) ));
+//..    stmt( IRStmt_Put( OFFB_CC_DEP2, widenUto32(mkexpr(arg2)) ));
+//.. }
+//.. 
+//.. 
+//.. /* -------------- Condition codes. -------------- */
+//.. 
+//.. /* Condition codes, using the Intel encoding.  */
+//.. 
+//.. static Char* name_X86Condcode ( X86Condcode cond )
+//.. {
+//..    switch (cond) {
+//..       case X86CondO:      return "o";
+//..       case X86CondNO:     return "no";
+//..       case X86CondB:      return "b";
+//..       case X86CondNB:     return "nb";
+//..       case X86CondZ:      return "z";
+//..       case X86CondNZ:     return "nz";
+//..       case X86CondBE:     return "be";
+//..       case X86CondNBE:    return "nbe";
+//..       case X86CondS:      return "s";
+//..       case X86CondNS:     return "ns";
+//..       case X86CondP:      return "p";
+//..       case X86CondNP:     return "np";
+//..       case X86CondL:      return "l";
+//..       case X86CondNL:     return "nl";
+//..       case X86CondLE:     return "le";
+//..       case X86CondNLE:    return "nle";
+//..       case X86CondAlways: return "ALWAYS";
+//..       default: vpanic("name_X86Condcode");
+//..    }
+//.. }
+//.. 
+//.. static 
+//.. X86Condcode positiveIse_X86Condcode ( X86Condcode  cond,
+//..                                       Bool*     needInvert )
+//.. {
+//..    vassert(cond >= X86CondO && cond <= X86CondNLE);
+//..    if (cond & 1) {
+//..       *needInvert = True;
+//..       return cond-1;
+//..    } else {
+//..       *needInvert = False;
+//..       return cond;
+//..    }
+//.. }
+//.. 
+//.. 
+//.. /* -------------- Helpers for ADD/SUB with carry. -------------- */
+//.. 
+//.. /* Given ta1, ta2 and tres, compute tres = ADC(ta1,ta2) and set flags
+//..    appropriately.
+//.. */
+//.. static void helper_ADC ( Int sz,
+//..                          IRTemp tres, IRTemp ta1, IRTemp ta2 )
+//.. {
+//..    UInt    thunkOp;
+//..    IRType  ty    = szToITy(sz);
+//..    IRTemp  oldc  = newTemp(Ity_I32);
+//..    IRTemp  oldcn = newTemp(ty);
+//..    IROp    plus  = mkSizedOp(ty, Iop_Add8);
+//..    IROp    xor   = mkSizedOp(ty, Iop_Xor8);
+//.. 
+//..    vassert(sz == 1 || sz == 2 || sz == 4);
+//..    thunkOp = sz==4 ? X86G_CC_OP_ADCL 
+//..                    : (sz==2 ? X86G_CC_OP_ADCW : X86G_CC_OP_ADCB);
+//.. 
+//..    /* oldc = old carry flag, 0 or 1 */
+//..    assign( oldc,  binop(Iop_And32,
+//..                         mk_x86g_calculate_eflags_c(),
+//..                         mkU32(1)) );
+//.. 
+//..    assign( oldcn, narrowTo(ty, mkexpr(oldc)) );
+//.. 
+//..    assign( tres, binop(plus,
+//..                        binop(plus,mkexpr(ta1),mkexpr(ta2)),
+//..                        mkexpr(oldcn)) );
+//.. 
+//..    stmt( IRStmt_Put( OFFB_CC_OP,   mkU32(thunkOp) ) );
+//..    stmt( IRStmt_Put( OFFB_CC_DEP1, mkexpr(ta1) ) );
+//..    stmt( IRStmt_Put( OFFB_CC_DEP2, binop(xor, mkexpr(ta2), 
+//..                                               mkexpr(oldcn)) ) );
+//..    stmt( IRStmt_Put( OFFB_CC_NDEP, mkexpr(oldc) ) );
+//.. }
+//.. 
+//.. 
+//.. /* Given ta1, ta2 and tres, compute tres = SBB(ta1,ta2) and set flags
+//..    appropriately.
+//.. */
+//.. static void helper_SBB ( Int sz,
+//..                          IRTemp tres, IRTemp ta1, IRTemp ta2 )
+//.. {
+//..    UInt    thunkOp;
+//..    IRType  ty    = szToITy(sz);
+//..    IRTemp  oldc  = newTemp(Ity_I32);
+//..    IRTemp  oldcn = newTemp(ty);
+//..    IROp    minus = mkSizedOp(ty, Iop_Sub8);
+//..    IROp    xor   = mkSizedOp(ty, Iop_Xor8);
+//.. 
+//..    vassert(sz == 1 || sz == 2 || sz == 4);
+//..    thunkOp = sz==4 ? X86G_CC_OP_SBBL 
+//..                    : (sz==2 ? X86G_CC_OP_SBBW : X86G_CC_OP_SBBB);
+//.. 
+//..    /* oldc = old carry flag, 0 or 1 */
+//..    assign( oldc, binop(Iop_And32,
+//..                        mk_x86g_calculate_eflags_c(),
+//..                        mkU32(1)) );
+//.. 
+//..    assign( oldcn, narrowTo(ty, mkexpr(oldc)) );
+//.. 
+//..    assign( tres, binop(minus,
+//..                        binop(minus,mkexpr(ta1),mkexpr(ta2)),
+//..                        mkexpr(oldcn)) );
+//.. 
+//..    stmt( IRStmt_Put( OFFB_CC_OP,   mkU32(thunkOp) ) );
+//..    stmt( IRStmt_Put( OFFB_CC_DEP1, mkexpr(ta1) ) );
+//..    stmt( IRStmt_Put( OFFB_CC_DEP2, binop(xor, mkexpr(ta2), 
+//..                                               mkexpr(oldcn)) ) );
+//..    stmt( IRStmt_Put( OFFB_CC_NDEP, mkexpr(oldc) ) );
+//.. }
+//.. 
+//.. 
+//.. /* -------------- Helpers for disassembly printing. -------------- */
+//.. 
+//.. static HChar* nameGrp1 ( Int opc_aux )
+//.. {
+//..    static HChar* grp1_names[8] 
+//..      = { "add", "or", "adc", "sbb", "and", "sub", "xor", "cmp" };
+//..    if (opc_aux < 0 || opc_aux > 7) vpanic("nameGrp1(x86)");
+//..    return grp1_names[opc_aux];
+//.. }
+//.. 
+//.. static HChar* nameGrp2 ( Int opc_aux )
+//.. {
+//..    static HChar* grp2_names[8] 
+//..      = { "rol", "ror", "rcl", "rcr", "shl", "shr", "shl", "sar" };
+//..    if (opc_aux < 0 || opc_aux > 7) vpanic("nameGrp2(x86)");
+//..    return grp2_names[opc_aux];
+//.. }
+//.. 
+//.. static HChar* nameGrp4 ( Int opc_aux )
+//.. {
+//..    static HChar* grp4_names[8] 
+//..      = { "inc", "dec", "???", "???", "???", "???", "???", "???" };
+//..    if (opc_aux < 0 || opc_aux > 1) vpanic("nameGrp4(x86)");
+//..    return grp4_names[opc_aux];
+//.. }
+//.. 
+//.. static HChar* nameGrp5 ( Int opc_aux )
+//.. {
+//..    static HChar* grp5_names[8] 
+//..      = { "inc", "dec", "call*", "call*", "jmp*", "jmp*", "push", "???" };
+//..    if (opc_aux < 0 || opc_aux > 6) vpanic("nameGrp5(x86)");
+//..    return grp5_names[opc_aux];
+//.. }
+//.. 
+//.. //-- static Char* nameGrp8 ( Int opc_aux )
+//.. //-- {
+//.. //--    static Char* grp8_names[8] 
+//.. //--      = { "???", "???", "???", "???", "bt", "bts", "btr", "btc" };
+//.. //--    if (opc_aux < 4 || opc_aux > 7) VG_(core_panic)("nameGrp8");
+//.. //--    return grp8_names[opc_aux];
+//.. //-- }
+//.. 
+//.. static HChar* nameIReg ( Int size, Int reg )
+//.. {
+//..    static HChar* ireg32_names[8] 
+//..      = { "%eax", "%ecx", "%edx", "%ebx", 
+//..          "%esp", "%ebp", "%esi", "%edi" };
+//..    static HChar* ireg16_names[8] 
+//..      = { "%ax", "%cx", "%dx", "%bx", "%sp", "%bp", "%si", "%di" };
+//..    static HChar* ireg8_names[8] 
+//..      = { "%al", "%cl", "%dl", "%bl", 
+//..          "%ah{sp}", "%ch{bp}", "%dh{si}", "%bh{di}" };
+//..    if (reg < 0 || reg > 7) goto bad;
+//..    switch (size) {
+//..       case 4: return ireg32_names[reg];
+//..       case 2: return ireg16_names[reg];
+//..       case 1: return ireg8_names[reg];
+//..    }
+//..   bad:
+//..    vpanic("nameIReg(X86)");
+//..    return NULL; /*notreached*/
+//.. }
+//.. 
+//.. static HChar* nameSReg ( UInt sreg )
+//.. {
+//..    switch (sreg) {
+//..       case R_ES: return "%es";
+//..       case R_CS: return "%cs";
+//..       case R_SS: return "%ss";
+//..       case R_DS: return "%ds";
+//..       case R_FS: return "%fs";
+//..       case R_GS: return "%gs";
+//..       default: vpanic("nameSReg(x86)");
+//..    }
+//.. }
+//.. 
+//.. static HChar* nameMMXReg ( Int mmxreg )
+//.. {
+//..    static HChar* mmx_names[8] 
+//..      = { "%mm0", "%mm1", "%mm2", "%mm3", "%mm4", "%mm5", "%mm6", "%mm7" };
+//..    if (mmxreg < 0 || mmxreg > 7) vpanic("nameMMXReg(x86,guest)");
+//..    return mmx_names[mmxreg];
+//.. }
+//.. 
+//.. static HChar* nameXMMReg ( Int xmmreg )
+//.. {
+//..    static HChar* xmm_names[8] 
+//..      = { "%xmm0", "%xmm1", "%xmm2", "%xmm3", 
+//..          "%xmm4", "%xmm5", "%xmm6", "%xmm7" };
+//..    if (xmmreg < 0 || xmmreg > 7) vpanic("name_of_xmm_reg");
+//..    return xmm_names[xmmreg];
+//.. }
+//..  
+//.. static Char* nameMMXGran ( UChar gran )
+//.. {
+//..    switch (gran) {
+//..       case 0: return "b";
+//..       case 1: return "w";
+//..       case 2: return "d";
+//..       case 3: return "q";
+//..       default: vpanic("nameMMXGran(x86,guest)");
+//..    }
+//.. }
+//.. 
+//.. static Char nameISize ( Int size )
+//.. {
+//..    switch (size) {
+//..       case 4: return 'l';
+//..       case 2: return 'w';
+//..       case 1: return 'b';
+//..       default: vpanic("nameISize(x86)");
+//..    }
+//.. }
+//.. 
+//.. 
+//.. /*------------------------------------------------------------*/
+//.. /*--- JMP helpers                                          ---*/
+//.. /*------------------------------------------------------------*/
+//.. 
+//.. static void jmp_lit( IRJumpKind kind, Addr32 d32 )
+//.. {
+//..   irbb->next     = mkU32(d32);
+//..   irbb->jumpkind = kind;
+//.. }
+//.. 
+//.. static void jmp_treg( IRJumpKind kind, IRTemp t )
+//.. {
+//..    irbb->next = mkexpr(t);
+//..    irbb->jumpkind = kind;
+//.. }
+//.. 
+//.. static 
+//.. void jcc_01( X86Condcode cond, Addr32 d32_false, Addr32 d32_true )
+//.. {
+//..    Bool        invert;
+//..    X86Condcode condPos;
+//..    condPos = positiveIse_X86Condcode ( cond, &invert );
+//..    if (invert) {
+//..       stmt( IRStmt_Exit( mk_x86g_calculate_condition(condPos),
+//..                          Ijk_Boring,
+//..                          IRConst_U32(d32_false) ) );
+//..       irbb->next     = mkU32(d32_true);
+//..       irbb->jumpkind = Ijk_Boring;
+//..    } else {
+//..       stmt( IRStmt_Exit( mk_x86g_calculate_condition(condPos),
+//..                          Ijk_Boring,
+//..                          IRConst_U32(d32_true) ) );
+//..       irbb->next     = mkU32(d32_false);
+//..       irbb->jumpkind = Ijk_Boring;
+//..    }
+//.. }
+//.. 
+//.. 
+//.. /*------------------------------------------------------------*/
+//.. /*--- Disassembling addressing modes                       ---*/
+//.. /*------------------------------------------------------------*/
+//.. 
+//.. static 
+//.. UChar* sorbTxt ( UChar sorb )
+//.. {
+//..    switch (sorb) {
+//..       case 0:    return ""; /* no override */
+//..       case 0x3E: return "%ds";
+//..       case 0x26: return "%es:";
+//..       case 0x64: return "%fs:";
+//..       case 0x65: return "%gs:";
+//..       default: vpanic("sorbTxt(x86,guest)");
+//..    }
+//.. }
+//.. 
+//.. 
+//.. /* 'virtual' is an IRExpr* holding a virtual address.  Convert it to a
+//..    linear address by adding any required segment override as indicated
+//..    by sorb. */
+//.. static
+//.. IRExpr* handleSegOverride ( UChar sorb, IRExpr* virtual )
+//.. {
+//..    Int    sreg;
+//..    IRType hWordTy;
+//..    IRTemp ldt_ptr, gdt_ptr, seg_selector, r64;
+//.. 
+//..    if (sorb == 0)
+//..       /* the common case - no override */
+//..       return virtual;
+//.. 
+//..    switch (sorb) {
+//..       case 0x3E: sreg = R_DS; break;
+//..       case 0x26: sreg = R_ES; break;
+//..       case 0x64: sreg = R_FS; break;
+//..       case 0x65: sreg = R_GS; break;
+//..       default: vpanic("handleSegOverride(x86,guest)");
+//..    }
+//.. 
+//..    hWordTy = sizeof(HWord)==4 ? Ity_I32 : Ity_I64;
+//.. 
+//..    seg_selector = newTemp(Ity_I32);
+//..    ldt_ptr      = newTemp(hWordTy);
+//..    gdt_ptr      = newTemp(hWordTy);
+//..    r64          = newTemp(Ity_I64);
+//.. 
+//..    assign( seg_selector, unop(Iop_16Uto32, getSReg(sreg)) );
+//..    assign( ldt_ptr, IRExpr_Get( OFFB_LDT, hWordTy ));
+//..    assign( gdt_ptr, IRExpr_Get( OFFB_GDT, hWordTy ));
+//.. 
+//..    /*
+//..    Call this to do the translation and limit checks: 
+//..    ULong x86g_use_seg_selector ( HWord ldt, HWord gdt,
+//..                                  UInt seg_selector, UInt virtual_addr )
+//..    */
+//..    assign( 
+//..       r64, 
+//..       mkIRExprCCall( 
+//..          Ity_I64, 
+//..          0/*regparms*/, 
+//..          "x86g_use_seg_selector", 
+//..          &x86g_use_seg_selector, 
+//..          mkIRExprVec_4( mkexpr(ldt_ptr), mkexpr(gdt_ptr), 
+//..                         mkexpr(seg_selector), virtual)
+//..       )
+//..    );
+//.. 
+//..    /* If the high 32 of the result are non-zero, there was a 
+//..       failure in address translation.  In which case, make a
+//..       quick exit.
+//..    */
+//..    stmt( 
+//..       IRStmt_Exit(
+//..          binop(Iop_CmpNE32, unop(Iop_64HIto32, mkexpr(r64)), mkU32(0)),
+//..          Ijk_MapFail,
+//..          IRConst_U32( guest_eip_curr_instr )
+//..       )
+//..    );
+//.. 
+//..    /* otherwise, here's the translated result. */
+//..    return unop(Iop_64to32, mkexpr(r64));
+//.. }
+//.. 
+//.. 
+//.. /* Generate IR to calculate an address indicated by a ModRM and
+//..    following SIB bytes.  The expression, and the number of bytes in
+//..    the address mode, are returned.  Note that this fn should not be
+//..    called if the R/M part of the address denotes a register instead of
+//..    memory.  If print_codegen is true, text of the addressing mode is
+//..    placed in buf. 
+//.. 
+//..    The computed address is stored in a new tempreg, and the
+//..    identity of the tempreg is returned.  */
+//.. 
+//.. static IRTemp disAMode_copy2tmp ( IRExpr* addr32 )
+//.. {
+//..    IRTemp tmp = newTemp(Ity_I32);
+//..    assign( tmp, addr32 );
+//..    return tmp;
+//.. }
+//.. 
+//.. static 
+//.. IRTemp disAMode ( Int* len, UChar sorb, UInt delta, UChar* buf )
+//.. {
+//..    UChar mod_reg_rm = getIByte(delta);
+//..    delta++;
+//.. 
+//..    buf[0] = (UChar)0;
+//.. 
+//..    /* squeeze out the reg field from mod_reg_rm, since a 256-entry
+//..       jump table seems a bit excessive. 
+//..    */
+//..    mod_reg_rm &= 0xC7;               /* is now XX000YYY */
+//..    mod_reg_rm |= (mod_reg_rm >> 3);  /* is now XX0XXYYY */
+//..    mod_reg_rm &= 0x1F;               /* is now 000XXYYY */
+//..    switch (mod_reg_rm) {
+//.. 
+//..       /* (%eax) .. (%edi), not including (%esp) or (%ebp).
+//..          --> GET %reg, t 
+//..       */
+//..       case 0x00: case 0x01: case 0x02: case 0x03: 
+//..       /* ! 04 */ /* ! 05 */ case 0x06: case 0x07:
+//..          { UChar rm = mod_reg_rm;
+//..            DIS(buf, "%s(%s)", sorbTxt(sorb), nameIReg(4,rm));
+//..            *len = 1;
+//..            return disAMode_copy2tmp(
+//..                   handleSegOverride(sorb, getIReg(4,rm)));
+//..          }
+//.. 
+//..       /* d8(%eax) ... d8(%edi), not including d8(%esp) 
+//..          --> GET %reg, t ; ADDL d8, t
+//..       */
+//..       case 0x08: case 0x09: case 0x0A: case 0x0B: 
+//..       /* ! 0C */ case 0x0D: case 0x0E: case 0x0F:
+//..          { UChar rm = mod_reg_rm & 7;
+//..            UInt  d  = getSDisp8(delta);
+//..            DIS(buf, "%s%d(%s)", sorbTxt(sorb), d, nameIReg(4,rm));
+//..            *len = 2;
+//..            return disAMode_copy2tmp(
+//..                   handleSegOverride(sorb,
+//..                      binop(Iop_Add32,getIReg(4,rm),mkU32(d))));
+//..          }
+//.. 
+//..       /* d32(%eax) ... d32(%edi), not including d32(%esp)
+//..          --> GET %reg, t ; ADDL d8, t
+//..       */
+//..       case 0x10: case 0x11: case 0x12: case 0x13: 
+//..       /* ! 14 */ case 0x15: case 0x16: case 0x17:
+//..          { UChar rm = mod_reg_rm & 7;
+//..            UInt  d  = getUDisp32(delta);
+//..            DIS(buf, "%s0x%x(%s)", sorbTxt(sorb), d, nameIReg(4,rm));
+//..            *len = 5;
+//..            return disAMode_copy2tmp(
+//..                   handleSegOverride(sorb,
+//..                      binop(Iop_Add32,getIReg(4,rm),mkU32(d))));
+//..          }
+//.. 
+//..       /* a register, %eax .. %edi.  This shouldn't happen. */
+//..       case 0x18: case 0x19: case 0x1A: case 0x1B:
+//..       case 0x1C: case 0x1D: case 0x1E: case 0x1F:
+//..          vpanic("disAMode(x86): not an addr!");
+//.. 
+//..       /* a 32-bit literal address
+//..          --> MOV d32, tmp 
+//..       */
+//..       case 0x05: 
+//..          { UInt d = getUDisp32(delta);
+//..            *len = 5;
+//..            DIS(buf, "%s(0x%x)", sorbTxt(sorb), d);
+//..            return disAMode_copy2tmp( 
+//..                      handleSegOverride(sorb, mkU32(d)));
+//..          }
+//.. 
+//..       case 0x04: {
+//..          /* SIB, with no displacement.  Special cases:
+//..             -- %esp cannot act as an index value.  
+//..                If index_r indicates %esp, zero is used for the index.
+//..             -- when mod is zero and base indicates EBP, base is instead
+//..                a 32-bit literal.
+//..             It's all madness, I tell you.  Extract %index, %base and 
+//..             scale from the SIB byte.  The value denoted is then:
+//..                | %index == %ESP && %base == %EBP
+//..                = d32 following SIB byte
+//..                | %index == %ESP && %base != %EBP
+//..                = %base
+//..                | %index != %ESP && %base == %EBP
+//..                = d32 following SIB byte + (%index << scale)
+//..                | %index != %ESP && %base != %ESP
+//..                = %base + (%index << scale)
+//.. 
+//..             What happens to the souls of CPU architects who dream up such
+//..             horrendous schemes, do you suppose?  
+//..          */
+//..          UChar sib     = getIByte(delta);
+//..          UChar scale   = (sib >> 6) & 3;
+//..          UChar index_r = (sib >> 3) & 7;
+//..          UChar base_r  = sib & 7;
+//..          delta++;
+//.. 
+//..          if (index_r != R_ESP && base_r != R_EBP) {
+//..             DIS(buf, "%s(%s,%s,%d)", sorbTxt(sorb), 
+//..                       nameIReg(4,base_r), nameIReg(4,index_r), 1<<scale);
+//..             *len = 2;
+//..             return
+//..                disAMode_copy2tmp( 
+//..                handleSegOverride(sorb,
+//..                   binop(Iop_Add32, 
+//..                         getIReg(4,base_r),
+//..                         binop(Iop_Shl32, getIReg(4,index_r),
+//..                               mkU8(scale)))));
+//..          }
+//.. 
+//..          if (index_r != R_ESP && base_r == R_EBP) {
+//..             UInt d = getUDisp32(delta);
+//..             DIS(buf, "%s0x%x(,%s,%d)", sorbTxt(sorb), d, 
+//..                       nameIReg(4,index_r), 1<<scale);
+//..             *len = 6;
+//..             return
+//..                disAMode_copy2tmp(
+//..                handleSegOverride(sorb, 
+//..                   binop(Iop_Add32,
+//..                         binop(Iop_Shl32, getIReg(4,index_r), mkU8(scale)),
+//..                         mkU32(d))));
+//..          }
+//.. 
+//..          if (index_r == R_ESP && base_r != R_EBP) {
+//..             DIS(buf, "%s(%s,,)", sorbTxt(sorb), nameIReg(4,base_r));
+//..             *len = 2;
+//..             return disAMode_copy2tmp(
+//..                    handleSegOverride(sorb, getIReg(4,base_r)));
+//..          }
+//.. 
+//..          if (index_r == R_ESP && base_r == R_EBP) {
+//..             UInt d = getUDisp32(delta);
+//..             DIS(buf, "%s0x%x()", sorbTxt(sorb), d);
+//..             *len = 6;
+//..             vpanic("amode 8");
+//..             return disAMode_copy2tmp(
+//..                    handleSegOverride(sorb, mkU32(d)));
+//..          }
+//.. 
+//..          vassert(0);
+//..       }
+//.. 
+//..       /* SIB, with 8-bit displacement.  Special cases:
+//..          -- %esp cannot act as an index value.  
+//..             If index_r indicates %esp, zero is used for the index.
+//..          Denoted value is:
+//..             | %index == %ESP
+//..             = d8 + %base
+//..             | %index != %ESP
+//..             = d8 + %base + (%index << scale)
+//..       */
+//..       case 0x0C: {
+//..          UChar sib     = getIByte(delta);
+//..          UChar scale   = (sib >> 6) & 3;
+//..          UChar index_r = (sib >> 3) & 7;
+//..          UChar base_r  = sib & 7;
+//..          UInt  d       = getSDisp8(delta+1);
+//.. 
+//..          if (index_r == R_ESP) {
+//..             DIS(buf, "%s%d(%s,,)", sorbTxt(sorb), d, nameIReg(4,base_r));
+//..             *len = 3;
+//..             return disAMode_copy2tmp(
+//..                    handleSegOverride(sorb, 
+//..                       binop(Iop_Add32, getIReg(4,base_r), mkU32(d)) ));
+//..          } else {
+//..             DIS(buf, "%s%d(%s,%s,%d)", sorbTxt(sorb), d, 
+//..                      nameIReg(4,base_r), nameIReg(4,index_r), 1<<scale);
+//..             *len = 3;
+//..             return 
+//..                 disAMode_copy2tmp(
+//..                 handleSegOverride(sorb,
+//..                   binop(Iop_Add32,
+//..                         binop(Iop_Add32, 
+//..                               getIReg(4,base_r), 
+//..                               binop(Iop_Shl32, 
+//..                                     getIReg(4,index_r), mkU8(scale))),
+//..                         mkU32(d))));
+//..          }
+//..          vassert(0);
+//..       }
+//.. 
+//..       /* SIB, with 32-bit displacement.  Special cases:
+//..          -- %esp cannot act as an index value.  
+//..             If index_r indicates %esp, zero is used for the index.
+//..          Denoted value is:
+//..             | %index == %ESP
+//..             = d32 + %base
+//..             | %index != %ESP
+//..             = d32 + %base + (%index << scale)
+//..       */
+//..       case 0x14: {
+//..          UChar sib     = getIByte(delta);
+//..          UChar scale   = (sib >> 6) & 3;
+//..          UChar index_r = (sib >> 3) & 7;
+//..          UChar base_r  = sib & 7;
+//..          UInt d        = getUDisp32(delta+1);
+//.. 
+//..          if (index_r == R_ESP) {
+//..             DIS(buf, "%s%d(%s,,)", sorbTxt(sorb), d, nameIReg(4,base_r));
+//..             *len = 6;
+//..             return disAMode_copy2tmp(
+//..                    handleSegOverride(sorb, 
+//..                       binop(Iop_Add32, getIReg(4,base_r), mkU32(d)) ));
+//..          } else {
+//..             DIS(buf, "%s%d(%s,%s,%d)", sorbTxt(sorb), d, 
+//..                       nameIReg(4,base_r), nameIReg(4,index_r), 1<<scale);
+//..             *len = 6;
+//..             return 
+//..                 disAMode_copy2tmp(
+//..                 handleSegOverride(sorb,
+//..                   binop(Iop_Add32,
+//..                         binop(Iop_Add32, 
+//..                               getIReg(4,base_r), 
+//..                               binop(Iop_Shl32, 
+//..                                     getIReg(4,index_r), mkU8(scale))),
+//..                         mkU32(d))));
+//..          }
+//..          vassert(0);
+//..       }
+//.. 
+//..       default:
+//..          vpanic("disAMode(x86)");
+//..          return 0; /*notreached*/
+//..    }
+//.. }
+//.. 
+//.. 
+//.. /* Figure out the number of (insn-stream) bytes constituting the amode
+//..    beginning at delta.  Is useful for getting hold of literals beyond
+//..    the end of the amode before it has been disassembled.  */
+//.. 
+//.. static UInt lengthAMode ( UInt delta )
+//.. {
+//..    UChar mod_reg_rm = getIByte(delta); delta++;
+//.. 
+//..    /* squeeze out the reg field from mod_reg_rm, since a 256-entry
+//..       jump table seems a bit excessive. 
+//..    */
+//..    mod_reg_rm &= 0xC7;               /* is now XX000YYY */
+//..    mod_reg_rm |= (mod_reg_rm >> 3);  /* is now XX0XXYYY */
+//..    mod_reg_rm &= 0x1F;               /* is now 000XXYYY */
+//..    switch (mod_reg_rm) {
+//.. 
+//..       /* (%eax) .. (%edi), not including (%esp) or (%ebp). */
+//..       case 0x00: case 0x01: case 0x02: case 0x03: 
+//..       /* ! 04 */ /* ! 05 */ case 0x06: case 0x07:
+//..          return 1;
+//.. 
+//..       /* d8(%eax) ... d8(%edi), not including d8(%esp). */ 
+//..       case 0x08: case 0x09: case 0x0A: case 0x0B: 
+//..       /* ! 0C */ case 0x0D: case 0x0E: case 0x0F:
+//..          return 2;
+//.. 
+//..       /* d32(%eax) ... d32(%edi), not including d32(%esp). */
+//..       case 0x10: case 0x11: case 0x12: case 0x13: 
+//..       /* ! 14 */ case 0x15: case 0x16: case 0x17:
+//..          return 5;
+//.. 
+//..       /* a register, %eax .. %edi.  (Not an addr, but still handled.) */
+//..       case 0x18: case 0x19: case 0x1A: case 0x1B:
+//..       case 0x1C: case 0x1D: case 0x1E: case 0x1F:
+//..          return 1;
+//.. 
+//..       /* a 32-bit literal address. */
+//..       case 0x05: return 5;
+//.. 
+//..       /* SIB, no displacement.  */
+//..       case 0x04: {
+//..          UChar sib    = getIByte(delta);
+//..          UChar base_r = sib & 7;
+//..          if (base_r == R_EBP) return 6; else return 2;
+//..       }
+//..       /* SIB, with 8-bit displacement.  */
+//..       case 0x0C: return 3;
+//.. 
+//..       /* SIB, with 32-bit displacement.  */
+//..       case 0x14: return 6;
+//.. 
+//..       default:
+//..          vpanic("lengthAMode");
+//..          return 0; /*notreached*/
+//..    }
+//.. }
+//.. 
+//.. /*------------------------------------------------------------*/
+//.. /*--- Disassembling common idioms                          ---*/
+//.. /*------------------------------------------------------------*/
+//.. 
+//.. static
+//.. void codegen_XOR_reg_with_itself ( Int size, Int ge_reg )
+//.. {
+//..    IRType ty = szToITy(size);
+//..    /* reg := 0 */
+//..    putIReg(size, ge_reg, mkU(ty,0));
+//..    /* Flags: C,A,O=0, Z=1, S=0, P=1 */
+//..    stmt( IRStmt_Put( OFFB_CC_OP,   mkU32(X86G_CC_OP_COPY) ));
+//..    stmt( IRStmt_Put( OFFB_CC_DEP1, mkU32(X86G_CC_MASK_Z|X86G_CC_MASK_P) ));
+//..    stmt( IRStmt_Put( OFFB_CC_DEP2, mkU32(0) ));
+//..    DIP("xor%c %s, %s\n", nameISize(size),
+//..                          nameIReg(size,ge_reg), nameIReg(size,ge_reg) );
+//.. }
+//.. 
+//.. 
+//.. /* Handle binary integer instructions of the form
+//..       op E, G  meaning
+//..       op reg-or-mem, reg
+//..    Is passed the a ptr to the modRM byte, the actual operation, and the
+//..    data size.  Returns the address advanced completely over this
+//..    instruction.
+//.. 
+//..    E(src) is reg-or-mem
+//..    G(dst) is reg.
+//.. 
+//..    If E is reg, -->    GET %G,  tmp
+//..                        OP %E,   tmp
+//..                        PUT tmp, %G
+//..  
+//..    If E is mem and OP is not reversible, 
+//..                 -->    (getAddr E) -> tmpa
+//..                        LD (tmpa), tmpa
+//..                        GET %G, tmp2
+//..                        OP tmpa, tmp2
+//..                        PUT tmp2, %G
+//.. 
+//..    If E is mem and OP is reversible
+//..                 -->    (getAddr E) -> tmpa
+//..                        LD (tmpa), tmpa
+//..                        OP %G, tmpa
+//..                        PUT tmpa, %G
+//.. */
+//.. static
+//.. UInt dis_op2_E_G ( UChar       sorb,
+//..                    Bool        addSubCarry,
+//..                    IROp        op8, 
+//..                    Bool        keep,
+//..                    Int         size, 
+//..                    UInt        delta0,
+//..                    Char*       t_x86opc )
+//.. {
+//..    HChar   dis_buf[50];
+//..    Int     len;
+//..    IRType  ty   = szToITy(size);
+//..    IRTemp  dst1 = newTemp(ty);
+//..    IRTemp  src  = newTemp(ty);
+//..    IRTemp  dst0 = newTemp(ty);
+//..    UChar   rm   = getUChar(delta0);
+//..    IRTemp  addr = IRTemp_INVALID;
+//.. 
+//..    /* addSubCarry == True indicates the intended operation is
+//..       add-with-carry or subtract-with-borrow. */
+//..    if (addSubCarry) {
+//..       vassert(op8 == Iop_Add8 || op8 == Iop_Sub8);
+//..       vassert(keep);
+//..    }
+//.. 
+//..    if (epartIsReg(rm)) {
+//..       /* Specially handle XOR reg,reg, because that doesn't really
+//..          depend on reg, and doing the obvious thing potentially
+//..          generates a spurious value check failure due to the bogus
+//..          dependency. */
+//..       if (op8 == Iop_Xor8 && gregOfRM(rm) == eregOfRM(rm)) {
+//..          codegen_XOR_reg_with_itself ( size, gregOfRM(rm) );
+//..          return 1+delta0;
+//..       }
+//..       assign( dst0, getIReg(size,gregOfRM(rm)) );
+//..       assign( src,  getIReg(size,eregOfRM(rm)) );
+//.. 
+//..       if (addSubCarry && op8 == Iop_Add8) {
+//..          helper_ADC( size, dst1, dst0, src );
+//..          putIReg(size, gregOfRM(rm), mkexpr(dst1));
+//..       } else
+//..       if (addSubCarry && op8 == Iop_Sub8) {
+//..          helper_SBB( size, dst1, dst0, src );
+//..          putIReg(size, gregOfRM(rm), mkexpr(dst1));
+//..       } else {
+//..          assign( dst1, binop(mkSizedOp(ty,op8), mkexpr(dst0), mkexpr(src)) );
+//..          if (isAddSub(op8))
+//..             setFlags_DEP1_DEP2(op8, dst0, src, ty);
+//..          else
+//..             setFlags_DEP1(op8, dst1, ty);
+//..          if (keep)
+//..             putIReg(size, gregOfRM(rm), mkexpr(dst1));
+//..       }
+//.. 
+//..       DIP("%s%c %s,%s\n", t_x86opc, nameISize(size), 
+//..                           nameIReg(size,eregOfRM(rm)),
+//..                           nameIReg(size,gregOfRM(rm)));
+//..       return 1+delta0;
+//..    } else {
+//..       /* E refers to memory */
+//..       addr = disAMode ( &len, sorb, delta0, dis_buf);
+//..       assign( dst0, getIReg(size,gregOfRM(rm)) );
+//..       assign( src,  loadLE(szToITy(size), mkexpr(addr)) );
+//.. 
+//..       if (addSubCarry && op8 == Iop_Add8) {
+//..          helper_ADC( size, dst1, dst0, src );
+//..          putIReg(size, gregOfRM(rm), mkexpr(dst1));
+//..       } else
+//..       if (addSubCarry && op8 == Iop_Sub8) {
+//..          helper_SBB( size, dst1, dst0, src );
+//..          putIReg(size, gregOfRM(rm), mkexpr(dst1));
+//..       } else {
+//..          assign( dst1, binop(mkSizedOp(ty,op8), mkexpr(dst0), mkexpr(src)) );
+//..          if (isAddSub(op8))
+//..             setFlags_DEP1_DEP2(op8, dst0, src, ty);
+//..          else
+//..             setFlags_DEP1(op8, dst1, ty);
+//..          if (keep)
+//..             putIReg(size, gregOfRM(rm), mkexpr(dst1));
+//..       }
+//.. 
+//..       DIP("%s%c %s,%s\n", t_x86opc, nameISize(size), 
+//..                           dis_buf,nameIReg(size,gregOfRM(rm)));
+//..       return len+delta0;
+//..    }
+//.. }
+//.. 
+//.. 
+//.. 
+//.. /* Handle binary integer instructions of the form
+//..       op G, E  meaning
+//..       op reg, reg-or-mem
+//..    Is passed the a ptr to the modRM byte, the actual operation, and the
+//..    data size.  Returns the address advanced completely over this
+//..    instruction.
+//.. 
+//..    G(src) is reg.
+//..    E(dst) is reg-or-mem
+//.. 
+//..    If E is reg, -->    GET %E,  tmp
+//..                        OP %G,   tmp
+//..                        PUT tmp, %E
+//..  
+//..    If E is mem, -->    (getAddr E) -> tmpa
+//..                        LD (tmpa), tmpv
+//..                        OP %G, tmpv
+//..                        ST tmpv, (tmpa)
+//.. */
+//.. static
+//.. UInt dis_op2_G_E ( UChar       sorb,
+//..                    Bool        addSubCarry,
+//..                    IROp        op8, 
+//..                    Bool        keep,
+//..                    Int         size, 
+//..                    UInt        delta0,
+//..                    Char*       t_x86opc )
+//.. {
+//..    HChar   dis_buf[50];
+//..    Int     len;
+//..    IRType  ty   = szToITy(size);
+//..    IRTemp  dst1 = newTemp(ty);
+//..    IRTemp  src  = newTemp(ty);
+//..    IRTemp  dst0 = newTemp(ty);
+//..    UChar   rm   = getIByte(delta0);
+//..    IRTemp  addr = IRTemp_INVALID;
+//.. 
+//..    /* addSubCarry == True indicates the intended operation is
+//..       add-with-carry or subtract-with-borrow. */
+//..    if (addSubCarry) {
+//..       vassert(op8 == Iop_Add8 || op8 == Iop_Sub8);
+//..       vassert(keep);
+//..    }
+//.. 
+//..    if (epartIsReg(rm)) {
+//..       /* Specially handle XOR reg,reg, because that doesn't really
+//..          depend on reg, and doing the obvious thing potentially
+//..          generates a spurious value check failure due to the bogus
+//..          dependency. */
+//..       if (op8 == Iop_Xor8 && gregOfRM(rm) == eregOfRM(rm)) {
+//..          codegen_XOR_reg_with_itself ( size, gregOfRM(rm) );
+//..          return 1+delta0;
+//..       }
+//..       assign(dst0, getIReg(size,eregOfRM(rm)));
+//..       assign(src,  getIReg(size,gregOfRM(rm)));
+//.. 
+//..       if (addSubCarry && op8 == Iop_Add8) {
+//..          helper_ADC( size, dst1, dst0, src );
+//..          putIReg(size, eregOfRM(rm), mkexpr(dst1));
+//..       } else
+//..       if (addSubCarry && op8 == Iop_Sub8) {
+//..          helper_SBB( size, dst1, dst0, src );
+//..          putIReg(size, eregOfRM(rm), mkexpr(dst1));
+//..       } else {
+//..          assign(dst1, binop(mkSizedOp(ty,op8), mkexpr(dst0), mkexpr(src)));
+//..          if (isAddSub(op8))
+//..             setFlags_DEP1_DEP2(op8, dst0, src, ty);
+//..          else
+//..             setFlags_DEP1(op8, dst1, ty);
+//..          if (keep)
+//..             putIReg(size, eregOfRM(rm), mkexpr(dst1));
+//..       }
+//.. 
+//..       DIP("%s%c %s,%s\n", t_x86opc, nameISize(size), 
+//..                           nameIReg(size,gregOfRM(rm)),
+//..                           nameIReg(size,eregOfRM(rm)));
+//..       return 1+delta0;
+//..    }
+//.. 
+//..    /* E refers to memory */    
+//..    {
+//..       addr = disAMode ( &len, sorb, delta0, dis_buf);
+//..       assign(dst0, loadLE(ty,mkexpr(addr)));
+//..       assign(src,  getIReg(size,gregOfRM(rm)));
+//.. 
+//..       if (addSubCarry && op8 == Iop_Add8) {
+//..          helper_ADC( size, dst1, dst0, src );
+//..          storeLE(mkexpr(addr), mkexpr(dst1));
+//..       } else
+//..       if (addSubCarry && op8 == Iop_Sub8) {
+//..          helper_SBB( size, dst1, dst0, src );
+//..          storeLE(mkexpr(addr), mkexpr(dst1));
+//..       } else {
+//..          assign(dst1, binop(mkSizedOp(ty,op8), mkexpr(dst0), mkexpr(src)));
+//..          if (isAddSub(op8))
+//..             setFlags_DEP1_DEP2(op8, dst0, src, ty);
+//..          else
+//..             setFlags_DEP1(op8, dst1, ty);
+//..          if (keep)
+//..             storeLE(mkexpr(addr), mkexpr(dst1));
+//..       }
+//.. 
+//..       DIP("%s%c %s,%s\n", t_x86opc, nameISize(size), 
+//..                           nameIReg(size,gregOfRM(rm)), dis_buf);
+//..       return len+delta0;
+//..    }
+//.. }
+//.. 
+//.. 
+//.. /* Handle move instructions of the form
+//..       mov E, G  meaning
+//..       mov reg-or-mem, reg
+//..    Is passed the a ptr to the modRM byte, and the data size.  Returns
+//..    the address advanced completely over this instruction.
+//.. 
+//..    E(src) is reg-or-mem
+//..    G(dst) is reg.
+//.. 
+//..    If E is reg, -->    GET %E,  tmpv
+//..                        PUT tmpv, %G
+//..  
+//..    If E is mem  -->    (getAddr E) -> tmpa
+//..                        LD (tmpa), tmpb
+//..                        PUT tmpb, %G
+//.. */
+//.. static
+//.. UInt dis_mov_E_G ( UChar       sorb,
+//..                    Int         size, 
+//..                    UInt        delta0 )
+//.. {
+//..    Int len;
+//..    UChar rm = getIByte(delta0);
+//..    HChar dis_buf[50];
+//.. 
+//..    if (epartIsReg(rm)) {
+//..       putIReg(size, gregOfRM(rm), getIReg(size, eregOfRM(rm)));
+//..       DIP("mov%c %s,%s\n", nameISize(size), 
+//..                            nameIReg(size,eregOfRM(rm)),
+//..                            nameIReg(size,gregOfRM(rm)));
+//..       return 1+delta0;
+//..    }
+//.. 
+//..    /* E refers to memory */    
+//..    {
+//..       IRTemp addr = disAMode ( &len, sorb, delta0, dis_buf );
+//..       putIReg(size, gregOfRM(rm), loadLE(szToITy(size), mkexpr(addr)));
+//..       DIP("mov%c %s,%s\n", nameISize(size), 
+//..                            dis_buf,nameIReg(size,gregOfRM(rm)));
+//..       return delta0+len;
+//..    }
+//.. }
+//.. 
+//.. 
+//.. /* Handle move instructions of the form
+//..       mov G, E  meaning
+//..       mov reg, reg-or-mem
+//..    Is passed the a ptr to the modRM byte, and the data size.  Returns
+//..    the address advanced completely over this instruction.
+//.. 
+//..    G(src) is reg.
+//..    E(dst) is reg-or-mem
+//.. 
+//..    If E is reg, -->    GET %G,  tmp
+//..                        PUT tmp, %E
+//..  
+//..    If E is mem, -->    (getAddr E) -> tmpa
+//..                        GET %G, tmpv
+//..                        ST tmpv, (tmpa) 
+//.. */
+//.. static
+//.. UInt dis_mov_G_E ( UChar       sorb,
+//..                    Int         size, 
+//..                    UInt        delta0 )
+//.. {
+//..    Int len;
+//..    UChar rm = getIByte(delta0);
+//..    HChar dis_buf[50];
+//.. 
+//..    if (epartIsReg(rm)) {
+//..       putIReg(size, eregOfRM(rm), getIReg(size, gregOfRM(rm)));
+//..       DIP("mov%c %s,%s\n", nameISize(size), 
+//..                            nameIReg(size,gregOfRM(rm)),
+//..                            nameIReg(size,eregOfRM(rm)));
+//..       return 1+delta0;
+//..    }
+//.. 
+//..    /* E refers to memory */    
+//..    {
+//..       IRTemp addr = disAMode ( &len, sorb, delta0, dis_buf);
+//..       storeLE( mkexpr(addr), getIReg(size, gregOfRM(rm)) );
+//..       DIP("mov%c %s,%s\n", nameISize(size), 
+//..                            nameIReg(size,gregOfRM(rm)), dis_buf);
+//..       return len+delta0;
+//..    }
+//.. }
+//.. 
+//.. 
+//.. /* op $immediate, AL/AX/EAX. */
+//.. static
+//.. UInt dis_op_imm_A ( Int    size,
+//..                     IROp   op8,
+//..                     Bool   keep,
+//..                     UInt   delta,
+//..                     Char*  t_x86opc )
+//.. {
+//..    IRType ty   = szToITy(size);
+//..    IRTemp dst0 = newTemp(ty);
+//..    IRTemp src  = newTemp(ty);
+//..    IRTemp dst1 = newTemp(ty);
+//..    UInt lit    = getUDisp(size,delta);
+//..    assign(dst0, getIReg(size,R_EAX));
+//..    assign(src,  mkU(ty,lit));
+//..    assign(dst1, binop(mkSizedOp(ty,op8), mkexpr(dst0), mkexpr(src)) );
+//..    if (isAddSub(op8))
+//..       setFlags_DEP1_DEP2(op8, dst0, src, ty);
+//..    else
+//..    if (isLogic(op8))
+//..       setFlags_DEP1(op8, dst1, ty);
+//..    else
+//..       vpanic("dis_op_imm_A(x86,guest)");
+//.. 
+//..    if (keep)
+//..       putIReg(size, R_EAX, mkexpr(dst1));
+//.. 
+//..    DIP("%s%c $0x%x, %s\n", t_x86opc, nameISize(size), 
+//..                            lit, nameIReg(size,R_EAX));
+//..    return delta+size;
+//.. }
+//.. 
+//.. 
+//.. /* Sign- and Zero-extending moves. */
+//.. static
+//.. UInt dis_movx_E_G ( UChar       sorb,
+//..                     UInt delta, Int szs, Int szd, Bool sign_extend )
+//.. {
+//..    UChar rm = getIByte(delta);
+//..    if (epartIsReg(rm)) {
+//..       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)),
+//..                                nameIReg(szd,gregOfRM(rm)));
+//..       return 1+delta;
+//..    }
+//.. 
+//..    /* E refers to memory */    
+//..    {
+//..       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))));
+//..       DIP("mov%c%c%c %s,%s\n", sign_extend ? 's' : 'z',
+//..                                nameISize(szs), nameISize(szd),
+//..                                dis_buf, nameIReg(szd,gregOfRM(rm)));
+//..       return len+delta;
+//..    }
+//.. }
+//.. 
+//.. 
+//.. /* Generate code to divide ArchRegs EDX:EAX / DX:AX / AX by the 32 /
+//..    16 / 8 bit quantity in the given IRTemp.  */
+//.. static
+//.. void codegen_div ( Int sz, IRTemp t, Bool signed_divide )
+//.. {
+//..    IROp   op    = signed_divide ? Iop_DivModS64to32 : Iop_DivModU64to32;
+//..    IRTemp src64 = newTemp(Ity_I64);
+//..    IRTemp dst64 = newTemp(Ity_I64);
+//..    switch (sz) {
+//..       case 4:
+//..          assign( src64, binop(Iop_32HLto64, 
+//..                               getIReg(4,R_EDX), getIReg(4,R_EAX)) );
+//..          assign( dst64, binop(op, mkexpr(src64), mkexpr(t)) );
+//..          putIReg( 4, R_EAX, unop(Iop_64to32,mkexpr(dst64)) );
+//..          putIReg( 4, R_EDX, unop(Iop_64HIto32,mkexpr(dst64)) );
+//..          break;
+//..       case 2: {
+//..          IROp widen3264 = signed_divide ? Iop_32Sto64 : Iop_32Uto64;
+//..          IROp widen1632 = signed_divide ? Iop_16Sto32 : Iop_16Uto32;
+//..          assign( src64, unop(widen3264,
+//..                              binop(Iop_16HLto32, 
+//..                                    getIReg(2,R_EDX), getIReg(2,R_EAX))) );
+//..          assign( dst64, binop(op, mkexpr(src64), unop(widen1632,mkexpr(t))) );
+//..          putIReg( 2, R_EAX, unop(Iop_32to16,unop(Iop_64to32,mkexpr(dst64))) );
+//..          putIReg( 2, R_EDX, unop(Iop_32to16,unop(Iop_64HIto32,mkexpr(dst64))) );
+//..          break;
+//..       }
+//..       case 1: {
+//..          IROp widen3264 = signed_divide ? Iop_32Sto64 : Iop_32Uto64;
+//..          IROp widen1632 = signed_divide ? Iop_16Sto32 : Iop_16Uto32;
+//..          IROp widen816  = signed_divide ? Iop_8Sto16  : Iop_8Uto16;
+//..          assign( src64, unop(widen3264, unop(widen1632, getIReg(2,R_EAX))) );
+//..          assign( dst64, 
+//..                  binop(op, mkexpr(src64), 
+//..                            unop(widen1632, unop(widen816, mkexpr(t)))) );
+//..          putIReg( 1, R_AL, unop(Iop_16to8, unop(Iop_32to16,
+//..                            unop(Iop_64to32,mkexpr(dst64)))) );
+//..          putIReg( 1, R_AH, unop(Iop_16to8, unop(Iop_32to16,
+//..                            unop(Iop_64HIto32,mkexpr(dst64)))) );
+//..          break;
+//..       }
+//..       default: vpanic("codegen_div(x86)");
+//..    }
+//.. }
+//.. 
+//.. 
+//.. static 
+//.. UInt dis_Grp1 ( UChar sorb,
+//..                 UInt delta, UChar modrm, 
+//..                 Int am_sz, Int d_sz, Int sz, UInt d32 )
+//.. {
+//..    Int     len;
+//..    HChar   dis_buf[50];
+//..    IRType  ty   = szToITy(sz);
+//..    IRTemp  dst1 = newTemp(ty);
+//..    IRTemp  src  = newTemp(ty);
+//..    IRTemp  dst0 = newTemp(ty);
+//..    IRTemp  addr = IRTemp_INVALID;
+//..    IROp    op8  = Iop_INVALID;
+//..    UInt    mask = sz==1 ? 0xFF : (sz==2 ? 0xFFFF : 0xFFFFFFFF);
+//.. 
+//..    switch (gregOfRM(modrm)) {
+//..       case 0: op8 = Iop_Add8; break;  case 1: op8 = Iop_Or8;  break;
+//..       case 2: break;  // ADC
+//..       case 3: break;  // SBB
+//..       case 4: op8 = Iop_And8; break;  case 5: op8 = Iop_Sub8; break;
+//..       case 6: op8 = Iop_Xor8; break;  case 7: op8 = Iop_Sub8; break;
+//..       default: vpanic("dis_Grp1: unhandled case");
+//..    }
+//.. 
+//..    if (epartIsReg(modrm)) {
+//..       vassert(am_sz == 1);
+//.. 
+//..       assign(dst0, getIReg(sz,eregOfRM(modrm)));
+//..       assign(src,  mkU(ty,d32 & mask));
+//.. 
+//..       if (gregOfRM(modrm) == 2 /* ADC */) {
+//..          helper_ADC( sz, dst1, dst0, src );
+//..       } else 
+//..       if (gregOfRM(modrm) == 3 /* SBB */) {
+//..          helper_SBB( sz, dst1, dst0, src );
+//..       } else {
+//..          assign(dst1, binop(mkSizedOp(ty,op8), mkexpr(dst0), mkexpr(src)));
+//..          if (isAddSub(op8))
+//..             setFlags_DEP1_DEP2(op8, dst0, src, ty);
+//..          else
+//..             setFlags_DEP1(op8, dst1, ty);
+//..       }
+//.. 
+//..       if (gregOfRM(modrm) < 7)
+//..          putIReg(sz, eregOfRM(modrm), mkexpr(dst1));
+//.. 
+//..       delta += (am_sz + d_sz);
+//..       DIP("%s%c $0x%x, %s\n", nameGrp1(gregOfRM(modrm)), nameISize(sz), d32, 
+//..                               nameIReg(sz,eregOfRM(modrm)));
+//..    } else {
+//..       addr = disAMode ( &len, sorb, delta, dis_buf);
+//.. 
+//..       assign(dst0, loadLE(ty,mkexpr(addr)));
+//..       assign(src, mkU(ty,d32 & mask));
+//.. 
+//..       if (gregOfRM(modrm) == 2 /* ADC */) {
+//..          helper_ADC( sz, dst1, dst0, src );
+//..       } else 
+//..       if (gregOfRM(modrm) == 3 /* SBB */) {
+//..          helper_SBB( sz, dst1, dst0, src );
+//..       } else {
+//..          assign(dst1, binop(mkSizedOp(ty,op8), mkexpr(dst0), mkexpr(src)));
+//..          if (isAddSub(op8))
+//..             setFlags_DEP1_DEP2(op8, dst0, src, ty);
+//..          else
+//..             setFlags_DEP1(op8, dst1, ty);
+//..       }
+//.. 
+//..       if (gregOfRM(modrm) < 7)
+//..           storeLE(mkexpr(addr), mkexpr(dst1));
+//.. 
+//..       delta += (len+d_sz);
+//..       DIP("%s%c $0x%x, %s\n", nameGrp1(gregOfRM(modrm)), nameISize(sz),
+//..                               d32, dis_buf);
+//..    }
+//..    return delta;
+//.. }
+//.. 
+//.. 
+//.. /* Group 2 extended opcodes.  shift_expr must be an 8-bit typed
+//..    expression. */
+//.. 
+//.. static
+//.. UInt dis_Grp2 ( UChar  sorb,
+//..                 UInt delta, UChar modrm,
+//..                 Int am_sz, Int d_sz, Int sz, IRExpr* shift_expr,
+//..                 Char* shift_expr_txt )
+//.. {
+//..    /* delta on entry points at the modrm byte. */
+//..    HChar  dis_buf[50];
+//..    Int    len;
+//..    Bool   isShift, isRotate, isRotateRC;
+//..    IRType ty    = szToITy(sz);
+//..    IRTemp dst0  = newTemp(ty);
+//..    IRTemp dst1  = newTemp(ty);
+//..    IRTemp addr  = IRTemp_INVALID;
+//.. 
+//..    vassert(sz == 1 || sz == 2 || sz == 4);
+//.. 
+//..    /* Put value to shift/rotate in dst0. */
+//..    if (epartIsReg(modrm)) {
+//..       assign(dst0, getIReg(sz, eregOfRM(modrm)));
+//..       delta += (am_sz + d_sz);
+//..    } else {
+//..       addr = disAMode ( &len, sorb, delta, dis_buf);
+//..       assign(dst0, loadLE(ty,mkexpr(addr)));
+//..       delta += len + d_sz;
+//..    }
+//.. 
+//..    isShift = False;
+//..    switch (gregOfRM(modrm)) { case 4: case 5: case 7: isShift = True; }
+//.. 
+//..    isRotate = False;
+//..    switch (gregOfRM(modrm)) { case 0: case 1: isRotate = True; }
+//.. 
+//..    isRotateRC = gregOfRM(modrm) == 3;
+//.. 
+//..    if (!isShift && !isRotate && !isRotateRC) {
+//..       vex_printf("\ncase %d\n", gregOfRM(modrm));
+//..       vpanic("dis_Grp2(Reg): unhandled case(x86)");
+//..    }
+//.. 
+//..    if (isRotateRC) {
+//..       /* call a helper; this insn is so ridiculous it does not deserve
+//..          better */
+//..       IRTemp   r64  = newTemp(Ity_I64);
+//..       IRExpr** args 
+//..          = mkIRExprVec_4( widenUto32(mkexpr(dst0)), /* thing to rotate */
+//..                           widenUto32(shift_expr),   /* rotate amount */
+//..                           widenUto32(mk_x86g_calculate_eflags_all()),
+//..                           mkU32(sz) );
+//..       assign( r64, mkIRExprCCall(
+//..                       Ity_I64, 
+//..                       0/*regparm*/, 
+//..                       "x86g_calculate_RCR", &x86g_calculate_RCR,
+//..                       args
+//..                    )
+//..             );
+//..       /* new eflags in hi half r64; new value in lo half r64 */
+//..       assign( dst1, narrowTo(ty, unop(Iop_64to32, mkexpr(r64))) );
+//..       stmt( IRStmt_Put( OFFB_CC_OP,   mkU32(X86G_CC_OP_COPY) ));
+//..       stmt( IRStmt_Put( OFFB_CC_DEP1, unop(Iop_64HIto32, mkexpr(r64)) ));
+//..       stmt( IRStmt_Put( OFFB_CC_DEP2, mkU32(0) ));
+//..    }
+//.. 
+//..    if (isShift) {
+//.. 
+//..       IRTemp pre32     = newTemp(Ity_I32);
+//..       IRTemp res32     = newTemp(Ity_I32);
+//..       IRTemp res32ss   = newTemp(Ity_I32);
+//..       IRTemp shift_amt = newTemp(Ity_I8);
+//..       IROp   op32;
+//.. 
+//..       switch (gregOfRM(modrm)) { 
+//..          case 4: op32 = Iop_Shl32; break;
+//..          case 5: op32 = Iop_Shr32; break;
+//..          case 7: op32 = Iop_Sar32; break;
+//..          default: vpanic("dis_Grp2:shift"); break;
+//..       }
+//.. 
+//..       /* Widen the value to be shifted to 32 bits, do the shift, and
+//..          narrow back down.  This seems surprisingly long-winded, but
+//..          unfortunately the Intel semantics requires that 8/16-bit
+//..          shifts give defined results for shift values all the way up
+//..          to 31, and this seems the simplest way to do it.  It has the
+//..          advantage that the only IR level shifts generated are of 32
+//..          bit values, and the shift amount is guaranteed to be in the
+//..          range 0 .. 31, thereby observing the IR semantics requiring
+//..          all shift values to be in the range 0 .. 2^word_size-1. */
+//.. 
+//..       /* shift_amt = shift_expr & 31, regardless of operation size */
+//..       assign( shift_amt, binop(Iop_And8, shift_expr, mkU8(31)) );
+//.. 
+//..       /* suitably widen the value to be shifted to 32 bits. */
+//..       assign( pre32, op32==Iop_Sar32 ? widenSto32(mkexpr(dst0))
+//..                                      : widenUto32(mkexpr(dst0)) );
+//.. 
+//..       /* res32 = pre32 `shift` shift_amt */
+//..       assign( res32, binop(op32, mkexpr(pre32), mkexpr(shift_amt)) );
+//.. 
+//..       /* res32ss = pre32 `shift` ((shift_amt - 1) & 31) */
+//..       assign( res32ss,
+//..               binop(op32,
+//..                     mkexpr(pre32), 
+//..                     binop(Iop_And8,
+//..                           binop(Iop_Sub8,
+//..                                 mkexpr(shift_amt), mkU8(1)),
+//..                           mkU8(31))) );
+//.. 
+//..       /* Build the flags thunk. */
+//..       setFlags_DEP1_DEP2_shift(op32, res32, res32ss, ty, shift_amt);
+//.. 
+//..       /* Narrow the result back down. */
+//..       assign( dst1, narrowTo(ty, mkexpr(res32)) );
+//.. 
+//..    } /* if (isShift) */
+//.. 
+//..    else 
+//..    if (isRotate) {
+//..       Int    ccOp      = ty==Ity_I8 ? 0 : (ty==Ity_I16 ? 1 : 2);
+//..       Bool   left      = gregOfRM(modrm) == 0;
+//..       IRTemp rot_amt   = newTemp(Ity_I8);
+//..       IRTemp rot_amt32 = newTemp(Ity_I8);
+//..       IRTemp oldFlags  = newTemp(Ity_I32);
+//.. 
+//..       /* rot_amt = shift_expr & mask */
+//..       /* By masking the rotate amount thusly, the IR-level Shl/Shr
+//..          expressions never shift beyond the word size and thus remain
+//..          well defined. */
+//..       assign(rot_amt32, binop(Iop_And8, shift_expr, mkU8(31)));
+//.. 
+//..       if (ty == Ity_I32)
+//..          assign(rot_amt, mkexpr(rot_amt32));
+//..       else
+//..          assign(rot_amt, binop(Iop_And8, mkexpr(rot_amt32), mkU8(8*sz-1)));
+//.. 
+//..       if (left) {
+//.. 
+//..          /* dst1 = (dst0 << rot_amt) | (dst0 >>u (wordsize-rot_amt)) */
+//..          assign(dst1, 
+//..             binop( mkSizedOp(ty,Iop_Or8),
+//..                    binop( mkSizedOp(ty,Iop_Shl8), 
+//..                           mkexpr(dst0),
+//..                           mkexpr(rot_amt)
+//..                    ),
+//..                    binop( mkSizedOp(ty,Iop_Shr8), 
+//..                           mkexpr(dst0), 
+//..                           binop(Iop_Sub8,mkU8(8*sz), mkexpr(rot_amt))
+//..                    )
+//..             )
+//..          );
+//..          ccOp += X86G_CC_OP_ROLB;
+//.. 
+//..       } else { /* right */
+//.. 
+//..          /* dst1 = (dst0 >>u rot_amt) | (dst0 << (wordsize-rot_amt)) */
+//..          assign(dst1, 
+//..             binop( mkSizedOp(ty,Iop_Or8),
+//..                    binop( mkSizedOp(ty,Iop_Shr8), 
+//..                           mkexpr(dst0),
+//..                           mkexpr(rot_amt)
+//..                    ),
+//..                    binop( mkSizedOp(ty,Iop_Shl8), 
+//..                           mkexpr(dst0), 
+//..                           binop(Iop_Sub8,mkU8(8*sz), mkexpr(rot_amt))
+//..                    )
+//..             )
+//..          );
+//..          ccOp += X86G_CC_OP_RORB;
+//.. 
+//..       }
+//.. 
+//..       /* dst1 now holds the rotated value.  Build flag thunk.  We
+//..          need the resulting value for this, and the previous flags.
+//..          Except don't set it if the rotate count is zero. */
+//.. 
+//..       assign(oldFlags, mk_x86g_calculate_eflags_all());
+//.. 
+//..       /* CC_DEP1 is the rotated value.  CC_NDEP is flags before. */
+//..       stmt( IRStmt_Put( OFFB_CC_OP,
+//..                         IRExpr_Mux0X( mkexpr(rot_amt32),
+//..                                       IRExpr_Get(OFFB_CC_OP,Ity_I32),
+//..                                       mkU32(ccOp))) );
+//..       stmt( IRStmt_Put( OFFB_CC_DEP1, 
+//..                         IRExpr_Mux0X( mkexpr(rot_amt32),
+//..                                       IRExpr_Get(OFFB_CC_DEP1,Ity_I32),
+//..                                       widenUto32(mkexpr(dst1)))) );
+//..       stmt( IRStmt_Put( OFFB_CC_DEP2, 
+//..                         IRExpr_Mux0X( mkexpr(rot_amt32),
+//..                                       IRExpr_Get(OFFB_CC_DEP2,Ity_I32),
+//..                                       mkU32(0))) );
+//..       stmt( IRStmt_Put( OFFB_CC_NDEP, 
+//..                         IRExpr_Mux0X( mkexpr(rot_amt32),
+//..                                       IRExpr_Get(OFFB_CC_NDEP,Ity_I32),
+//..                                       mkexpr(oldFlags))) );
+//..    } /* if (isRotate) */
+//.. 
+//..    /* Save result, and finish up. */
+//..    if (epartIsReg(modrm)) {
+//..       putIReg(sz, eregOfRM(modrm), mkexpr(dst1));
+//..       if (vex_traceflags & VEX_TRACE_FE) {
+//..          vex_printf("%s%c ",
+//..                     nameGrp2(gregOfRM(modrm)), nameISize(sz) );
+//..          if (shift_expr_txt)
+//..             vex_printf("%s", shift_expr_txt);
+//..          else
+//..             ppIRExpr(shift_expr);
+//..          vex_printf(", %s\n", nameIReg(sz,eregOfRM(modrm)));
+//..       }
+//..    } else {
+//..       storeLE(mkexpr(addr), mkexpr(dst1));
+//..       if (vex_traceflags & VEX_TRACE_FE) {
+//..          vex_printf("%s%c ",
+//..                     nameGrp2(gregOfRM(modrm)), nameISize(sz) );
+//..          if (shift_expr_txt)
+//..             vex_printf("%s", shift_expr_txt);
+//..          else
+//..             ppIRExpr(shift_expr);
+//..          vex_printf(", %s\n", dis_buf);
+//..       }
+//..    }
+//..    return delta;
+//.. }
+//.. 
+//.. 
+//.. 
+//.. //-- /* Group 8 extended opcodes (but BT/BTS/BTC/BTR only). */
+//.. //-- static
+//.. //-- Addr dis_Grp8_BT ( UCodeBlock* cb, 
+//.. //--                    UChar       sorb,
+//.. //--                    Addr eip, UChar modrm,
+//.. //--                    Int am_sz, Int sz, UInt src_val )
+//.. //-- {
+//.. #  define MODIFY_t2_AND_SET_CARRY_FLAG                                        \
+//..       /* t2 is the value to be op'd on.  Copy to t_fetched, then        \
+//..          modify t2, if non-BT. */                                        \
+//..       uInstr2(cb, MOV,   4,  TempReg, t2, TempReg, t_fetched);                \
+//..       uInstr2(cb, MOV,  sz,  Literal, 0,  TempReg, t_mask);                \
+//..       uLiteral(cb, v_mask);                                                \
+//..       switch (gregOfRM(modrm)) {                                        \
+//..          case 4: /* BT */  break;                                        \
+//..          case 5: /* BTS */                                                 \
+//..             uInstr2(cb, OR, sz, TempReg, t_mask, TempReg, t2); break;        \
+//..          case 6: /* BTR */                                                \
+//..             uInstr2(cb, AND, sz, TempReg, t_mask, TempReg, t2); break;        \
+//..          case 7: /* BTC */                                                 \
+//..             uInstr2(cb, XOR, sz, TempReg, t_mask, TempReg, t2); break;        \
+//..       }                                                                        \
+//..      /* Copy relevant bit from t_fetched into carry flag. */                \
+//..       uInstr2(cb, SHR, sz, Literal, 0, TempReg, t_fetched);                \
+//..       uLiteral(cb, src_val);                                                \
+//..       uInstr2(cb, MOV, sz, Literal, 0, TempReg, t_mask);                \
+//..       uLiteral(cb, 1);                                                        \
+//..       uInstr2(cb, AND, sz, TempReg, t_mask, TempReg, t_fetched);        \
+//..       uInstr1(cb, NEG, sz, TempReg, t_fetched);                                \
+//..       setFlagsFromUOpcode(cb, NEG);
+//.. 
+//.. 
+//--    /* src_val denotes a d8.
+//--       And eip on entry points at the modrm byte. */
+//--    Int   t1, t2, t_fetched, t_mask;
+//--    UInt  pair;
+//--    HChar dis_buf[50];
+//--    UInt  v_mask;
+//-- 
+//--    /* There is no 1-byte form of this instruction, AFAICS. */
+//--    vg_assert(sz == 2 || sz == 4);
+//-- 
+//--    /* Limit src_val -- the bit offset -- to something within a word.
+//--       The Intel docs say that literal offsets larger than a word are
+//--       masked in this way. */
+//--    switch (sz) {
+//--       case 2: src_val &= 15; break;
+//--       case 4: src_val &= 31; break;
+//--       default: VG_(core_panic)("dis_Grp8_BT: invalid size");
+//--    }
+//-- 
+//--    /* Invent a mask suitable for the operation. */
+//-- 
+//--    switch (gregOfRM(modrm)) {
+//--       case 4: /* BT */  v_mask = 0; break;
+//--       case 5: /* BTS */ v_mask = 1 << src_val; break;
+//--       case 6: /* BTR */ v_mask = ~(1 << src_val); break;
+//--       case 7: /* BTC */ v_mask = 1 << src_val; break;
+//--          /* If this needs to be extended, probably simplest to make a
+//--             new function to handle the other cases (0 .. 3).  The
+//--             Intel docs do however not indicate any use for 0 .. 3, so
+//--             we don't expect this to happen. */
+//--       default: VG_(core_panic)("dis_Grp8_BT");
+//--    }
+//--    /* Probably excessively paranoid. */
+//--    if (sz == 2)
+//--       v_mask &= 0x0000FFFF;
+//-- 
+//--    t1        = INVALID_TEMPREG;
+//--    t_fetched = newTemp(cb);
+//--    t_mask    = newTemp(cb);
+//-- 
+//--    if (epartIsReg(modrm)) {
+//--       vg_assert(am_sz == 1);
+//--       t2 = newTemp(cb);
+//-- 
+//--       /* Fetch the value to be tested and modified. */
+//--       uInstr2(cb, GET, sz, ArchReg, eregOfRM(modrm), TempReg, t2);
+//--       /* Do it! */
+//--       MODIFY_t2_AND_SET_CARRY_FLAG;
+//--       /* Dump the result back, if non-BT. */
+//--       if (gregOfRM(modrm) != 4 /* BT */)
+//--          uInstr2(cb, PUT, sz, TempReg, t2, ArchReg, eregOfRM(modrm));
+//-- 
+//--       eip += (am_sz + 1);
+//--       DIP("%s%c $0x%x, %s\n", nameGrp8(gregOfRM(modrm)), nameISize(sz),
+//--                               src_val, nameIReg(sz,eregOfRM(modrm)));
+//--    } else {
+//--       pair = disAMode ( cb, sorb, eip, dis_buf);
+//--       t1   = LOW24(pair);
+//--       t2   = newTemp(cb);
+//--       eip  += HI8(pair);
+//--       eip  += 1;
+//-- 
+//--       /* Fetch the value to be tested and modified. */
+//--       uInstr2(cb, LOAD,  sz, TempReg, t1, TempReg, t2);
+//--       /* Do it! */
+//--       MODIFY_t2_AND_SET_CARRY_FLAG;
+//--       /* Dump the result back, if non-BT. */
+//--       if (gregOfRM(modrm) != 4 /* BT */) {
+//--          uInstr2(cb, STORE, sz, TempReg, t2, TempReg, t1);
+//--       }
+//--       DIP("%s%c $0x%x, %s\n", nameGrp8(gregOfRM(modrm)), nameISize(sz),
+//--                               src_val, dis_buf);
+//--    }
+//--    return eip;
+//-- 
+//-- #  undef MODIFY_t2_AND_SET_CARRY_FLAG
+//-- }
+//.. 
+//.. 
+//.. 
+//.. /* Signed/unsigned widening multiply.  Generate IR to multiply the
+//..    value in EAX/AX/AL by the given IRTemp, and park the result in
+//..    EDX:EAX/DX:AX/AX.
+//.. */
+//.. static void codegen_mulL_A_D ( Int sz, Bool syned, 
+//..                                IRTemp tmp, Char* tmp_txt )
+//.. {
+//..    IRType ty = szToITy(sz);
+//..    IRTemp t1 = newTemp(ty);
+//.. 
+//..    assign( t1, getIReg(sz, R_EAX) );
+//.. 
+//..    switch (ty) {
+//..       case Ity_I32: {
+//..          IRTemp res64   = newTemp(Ity_I64);
+//..          IRTemp resHi   = newTemp(Ity_I32);
+//..          IRTemp resLo   = newTemp(Ity_I32);
+//..          IROp   mulOp   = syned ? Iop_MullS32 : Iop_MullU32;
+//..          UInt   tBaseOp = syned ? X86G_CC_OP_SMULB : X86G_CC_OP_UMULB;
+//..          setFlags_MUL ( Ity_I32, t1, tmp, tBaseOp );
+//..          assign( res64, binop(mulOp, mkexpr(t1), mkexpr(tmp)) );
+//..          assign( resHi, unop(Iop_64HIto32,mkexpr(res64)));
+//..          assign( resLo, unop(Iop_64to32,mkexpr(res64)));
+//..          putIReg(4, R_EDX, mkexpr(resHi));
+//..          putIReg(4, R_EAX, mkexpr(resLo));
+//..          break;
+//..       }
+//..       case Ity_I16: {
+//..          IRTemp res32   = newTemp(Ity_I32);
+//..          IRTemp resHi   = newTemp(Ity_I16);
+//..          IRTemp resLo   = newTemp(Ity_I16);
+//..          IROp   mulOp   = syned ? Iop_MullS16 : Iop_MullU16;
+//..          UInt   tBaseOp = syned ? X86G_CC_OP_SMULB : X86G_CC_OP_UMULB;
+//..          setFlags_MUL ( Ity_I16, t1, tmp, tBaseOp );
+//..          assign( res32, binop(mulOp, mkexpr(t1), mkexpr(tmp)) );
+//..          assign( resHi, unop(Iop_32HIto16,mkexpr(res32)));
+//..          assign( resLo, unop(Iop_32to16,mkexpr(res32)));
+//..          putIReg(2, R_EDX, mkexpr(resHi));
+//..          putIReg(2, R_EAX, mkexpr(resLo));
+//..          break;
+//..       }
+//..       case Ity_I8: {
+//..          IRTemp res16   = newTemp(Ity_I16);
+//..          IRTemp resHi   = newTemp(Ity_I8);
+//..          IRTemp resLo   = newTemp(Ity_I8);
+//..          IROp   mulOp   = syned ? Iop_MullS8 : Iop_MullU8;
+//..          UInt   tBaseOp = syned ? X86G_CC_OP_SMULB : X86G_CC_OP_UMULB;
+//..          setFlags_MUL ( Ity_I8, t1, tmp, tBaseOp );
+//..          assign( res16, binop(mulOp, mkexpr(t1), mkexpr(tmp)) );
+//..          assign( resHi, unop(Iop_16HIto8,mkexpr(res16)));
+//..          assign( resLo, unop(Iop_16to8,mkexpr(res16)));
+//..          putIReg(2, R_EAX, mkexpr(res16));
+//..          break;
+//..       }
+//..       default:
+//..          vpanic("codegen_mulL_A_D(x86)");
+//..    }
+//..    DIP("%s%c %s\n", syned ? "imul" : "mul", nameISize(sz), tmp_txt);
+//.. }
+//.. 
+//.. 
+//.. /* Group 3 extended opcodes. */
+//.. static 
+//.. UInt dis_Grp3 ( UChar sorb, Int sz, UInt delta )
+//.. {
+//..    UInt    d32;
+//..    UChar   modrm;
+//..    HChar   dis_buf[50];
+//..    Int     len;
+//..    IRTemp  addr;
+//..    IRType  ty = szToITy(sz);
+//..    IRTemp  t1 = newTemp(ty);
+//..    //   IRTemp  t2 = IRTemp_INVALID;
+//..    IRTemp dst1, src, dst0;
+//..    modrm = getIByte(delta);
+//..    if (epartIsReg(modrm)) {
+//..       switch (gregOfRM(modrm)) {
+//..          case 0: { /* TEST */
+//..             delta++; d32 = getUDisp(sz, delta); delta += sz;
+//..             dst1 = newTemp(ty);
+//..             assign(dst1, binop(mkSizedOp(ty,Iop_And8),
+//..                                getIReg(sz,eregOfRM(modrm)),
+//..                                mkU(ty,d32)));
+//..             setFlags_DEP1( Iop_And8, dst1, ty );
+//..             DIP("test%c $0x%x, %s\n", nameISize(sz), d32, 
+//..                                       nameIReg(sz, eregOfRM(modrm)));
+//..             break;
+//..          }
+//..          case 2: /* NOT */
+//..             delta++;
+//..             putIReg(sz, eregOfRM(modrm),
+//..                         unop(mkSizedOp(ty,Iop_Not8),
+//..                              getIReg(sz, eregOfRM(modrm))));
+//..             DIP("not%c %s\n", nameISize(sz), nameIReg(sz, eregOfRM(modrm)));
+//..             break;
+//..          case 3: /* NEG */
+//..             delta++;
+//..             dst0 = newTemp(ty);
+//..             src  = newTemp(ty);
+//..             dst1 = newTemp(ty);
+//..             assign(dst0, mkU(ty,0));
+//..             assign(src,  getIReg(sz,eregOfRM(modrm)));
+//..             assign(dst1, binop(mkSizedOp(ty,Iop_Sub8), mkexpr(dst0), mkexpr(src)));
+//..             setFlags_DEP1_DEP2(Iop_Sub8, dst0, src, ty);
+//..             putIReg(sz, eregOfRM(modrm), mkexpr(dst1));
+//..             DIP("neg%c %s\n", nameISize(sz), nameIReg(sz, eregOfRM(modrm)));
+//..             break;
+//..          case 4: /* MUL (unsigned widening) */
+//..             delta++;
+//..             src = newTemp(ty);
+//..             assign(src, getIReg(sz,eregOfRM(modrm)));
+//..             codegen_mulL_A_D ( sz, False, src, nameIReg(sz,eregOfRM(modrm)) );
+//..             break;
+//..          case 5: /* IMUL (signed widening) */
+//..             delta++;
+//..             src = newTemp(ty);
+//..             assign(src, getIReg(sz,eregOfRM(modrm)));
+//..             codegen_mulL_A_D ( sz, True, src, nameIReg(sz,eregOfRM(modrm)) );
+//..             break;
+//..          case 6: /* DIV */
+//..             delta++;
+//..             assign( t1, getIReg(sz, eregOfRM(modrm)) );
+//..             codegen_div ( sz, t1, False );
+//..             DIP("div%c %s\n", nameISize(sz), nameIReg(sz, eregOfRM(modrm)));
+//..             break;
+//..          case 7: /* IDIV */
+//..             delta++;
+//..             assign( t1, getIReg(sz, eregOfRM(modrm)) );
+//..             codegen_div ( sz, t1, True );
+//..             DIP("idiv%c %s\n", nameISize(sz), nameIReg(sz, eregOfRM(modrm)));
+//..             break;
+//..          default: 
+//..             vex_printf(
+//..                "unhandled Grp3(R) case %d\n", (UInt)gregOfRM(modrm));
+//..             vpanic("Grp3(x86)");
+//..       }
+//..    } else {
+//..       addr = disAMode ( &len, sorb, delta, dis_buf );
+//..       t1   = newTemp(ty);
+//..       delta += len;
+//..       assign(t1, loadLE(ty,mkexpr(addr)));
+//..       switch (gregOfRM(modrm)) {
+//..          case 0: { /* TEST */
+//..             d32 = getUDisp(sz, delta); delta += sz;
+//..             dst1 = newTemp(ty);
+//..             assign(dst1, binop(mkSizedOp(ty,Iop_And8),
+//..                                mkexpr(t1), mkU(ty,d32)));
+//..             setFlags_DEP1( Iop_And8, dst1, ty );
+//..             DIP("test%c $0x%x, %s\n", nameISize(sz), d32, dis_buf);
+//..             break;
+//..          }
+//..          /* probably OK, but awaiting test case */
+//..          case 2: /* NOT */
+//..             storeLE( mkexpr(addr), unop(mkSizedOp(ty,Iop_Not8), mkexpr(t1)));
+//..             DIP("not%c %s\n", nameISize(sz), dis_buf);
+//..             break;
+//..          case 3: /* NEG */
+//..             dst0 = newTemp(ty);
+//..             src  = newTemp(ty);
+//..             dst1 = newTemp(ty);
+//..             assign(dst0, mkU(ty,0));
+//..             assign(src,  mkexpr(t1));
+//..             assign(dst1, binop(mkSizedOp(ty,Iop_Sub8), mkexpr(dst0), mkexpr(src)));
+//..             setFlags_DEP1_DEP2(Iop_Sub8, dst0, src, ty);
+//..             storeLE( mkexpr(addr), mkexpr(dst1) );
+//..             DIP("neg%c %s\n", nameISize(sz), dis_buf);
+//..             break;
+//..          case 4: /* MUL */
+//..             codegen_mulL_A_D ( sz, False, t1, dis_buf );
+//..             break;
+//..          case 5: /* IMUL */
+//..             codegen_mulL_A_D ( sz, True, t1, dis_buf );
+//..             break;
+//..          case 6: /* DIV */
+//..             codegen_div ( sz, t1, False );
+//..             DIP("div%c %s\n", nameISize(sz), dis_buf);
+//..             break;
+//..          case 7: /* IDIV */
+//..             codegen_div ( sz, t1, True );
+//..             DIP("idiv%c %s\n", nameISize(sz), dis_buf);
+//..             break;
+//..          default: 
+//..             vex_printf(
+//..                "unhandled Grp3(M) case %d\n", (UInt)gregOfRM(modrm));
+//..             vpanic("Grp3(x86)");
+//..       }
+//..    }
+//..    return delta;
+//.. }
+//.. 
+//.. 
+//.. /* Group 4 extended opcodes. */
+//.. static
+//.. UInt dis_Grp4 ( UChar sorb, UInt delta )
+//.. {
+//..    Int   alen;
+//..    UChar modrm;
+//..    HChar dis_buf[50];
+//..    IRType ty = Ity_I8;
+//..    IRTemp t1 = newTemp(ty);
+//..    IRTemp t2 = newTemp(ty);
+//.. 
+//..    modrm = getIByte(delta);
+//..    if (epartIsReg(modrm)) {
+//..       assign(t1, getIReg(1, eregOfRM(modrm)));
+//..       switch (gregOfRM(modrm)) {
+//..          case 0: /* INC */
+//..             assign(t2, binop(Iop_Add8, mkexpr(t1), mkU8(1)));
+//..             putIReg(1, eregOfRM(modrm), mkexpr(t2));
+//..             setFlags_INC_DEC( True, t2, ty );
+//..             break;
+//..          case 1: /* DEC */
+//..             assign(t2, binop(Iop_Sub8, mkexpr(t1), mkU8(1)));
+//..             putIReg(1, eregOfRM(modrm), mkexpr(t2));
+//..             setFlags_INC_DEC( False, t2, ty );
+//..             break;
+//..          default: 
+//..             vex_printf(
+//..                "unhandled Grp4(R) case %d\n", (UInt)gregOfRM(modrm));
+//..             vpanic("Grp4(x86,R)");
+//..       }
+//..       delta++;
+//..       DIP("%sb %s\n", nameGrp4(gregOfRM(modrm)),
+//..                       nameIReg(1, eregOfRM(modrm)));
+//..    } else {
+//..       IRTemp addr = disAMode ( &alen, sorb, delta, dis_buf );
+//..       assign( t1, loadLE(ty, mkexpr(addr)) );
+//..       switch (gregOfRM(modrm)) {
+//..          case 0: /* INC */
+//..             assign(t2, binop(Iop_Add8, mkexpr(t1), mkU8(1)));
+//..             storeLE( mkexpr(addr), mkexpr(t2) );
+//..             setFlags_INC_DEC( True, t2, ty );
+//..             break;
+//..          case 1: /* DEC */
+//..             assign(t2, binop(Iop_Sub8, mkexpr(t1), mkU8(1)));
+//..             storeLE( mkexpr(addr), mkexpr(t2) );
+//..             setFlags_INC_DEC( False, t2, ty );
+//..             break;
+//..          default: 
+//..             vex_printf(
+//..                "unhandled Grp4(M) case %d\n", (UInt)gregOfRM(modrm));
+//..             vpanic("Grp4(x86,M)");
+//..       }
+//..       delta += alen;
+//..       DIP("%sb %s\n", nameGrp4(gregOfRM(modrm)), dis_buf);
+//..    }
+//..    return delta;
+//.. }
+//.. 
+//.. 
+//.. /* Group 5 extended opcodes. */
+//.. static
+//.. UInt dis_Grp5 ( UChar sorb, Int sz, UInt delta, DisResult* whatNext )
+//.. {
+//..    Int     len;
+//..    UChar   modrm;
+//..    HChar   dis_buf[50];
+//..    IRTemp  addr = IRTemp_INVALID;
+//..    IRType  ty = szToITy(sz);
+//..    IRTemp  t1 = newTemp(ty);
+//..    IRTemp  t2 = IRTemp_INVALID;
+//.. 
+//..    modrm = getIByte(delta);
+//..    if (epartIsReg(modrm)) {
+//..       assign(t1, getIReg(sz,eregOfRM(modrm)));
+//..       switch (gregOfRM(modrm)) {
+//.. //--          case 0: /* INC */
+//.. //--             uInstr1(cb, INC, sz, TempReg, t1);
+//.. //--             setFlagsFromUOpcode(cb, INC);
+//.. //--             uInstr2(cb, PUT, sz, TempReg, t1, ArchReg, eregOfRM(modrm));
+//.. //--             break;
+//.. //--          case 1: /* DEC */
+//.. //--             uInstr1(cb, DEC, sz, TempReg, t1);
+//.. //--             setFlagsFromUOpcode(cb, DEC);
+//.. //--             uInstr2(cb, PUT, sz, TempReg, t1, ArchReg, eregOfRM(modrm));
+//.. //--             break;
+//..          case 2: /* call Ev */
+//..             vassert(sz == 4);
+//..             t2 = newTemp(Ity_I32);
+//..             assign(t2, binop(Iop_Sub32, getIReg(4,R_ESP), mkU32(4)));
+//..             putIReg(4, R_ESP, mkexpr(t2));
+//..             storeLE( mkexpr(t2), mkU32(guest_eip_bbstart+delta+1));
+//..             jmp_treg(Ijk_Call,t1);
+//..             *whatNext = Dis_StopHere;
+//..             break;
+//..          case 4: /* jmp Ev */
+//..             vassert(sz == 4);
+//..             jmp_treg(Ijk_Boring,t1);
+//..             *whatNext = Dis_StopHere;
+//..             break;
+//..          default: 
+//..             vex_printf(
+//..                "unhandled Grp5(R) case %d\n", (UInt)gregOfRM(modrm));
+//..             vpanic("Grp5(x86)");
+//..       }
+//..       delta++;
+//..       DIP("%s%c %s\n", nameGrp5(gregOfRM(modrm)),
+//..                        nameISize(sz), nameIReg(sz, eregOfRM(modrm)));
+//..    } else {
+//..       addr = disAMode ( &len, sorb, delta, dis_buf );
+//..       assign(t1, loadLE(ty,mkexpr(addr)));
+//..       switch (gregOfRM(modrm)) {
+//..          case 0: /* INC */ 
+//..             t2 = newTemp(ty);
+//..             assign(t2, binop(mkSizedOp(ty,Iop_Add8),
+//..                              mkexpr(t1), mkU(ty,1)));
+//..             setFlags_INC_DEC( True, t2, ty );
+//..             storeLE(mkexpr(addr),mkexpr(t2));
+//..             break;
+//..          case 1: /* DEC */ 
+//..             t2 = newTemp(ty);
+//..             assign(t2, binop(mkSizedOp(ty,Iop_Sub8),
+//..                              mkexpr(t1), mkU(ty,1)));
+//..             setFlags_INC_DEC( False, t2, ty );
+//..             storeLE(mkexpr(addr),mkexpr(t2));
+//..             break;
+//..          case 2: /* call Ev */
+//..             vassert(sz == 4);
+//..             t2 = newTemp(Ity_I32);
+//..             assign(t2, binop(Iop_Sub32, getIReg(4,R_ESP), mkU32(4)));
+//..             putIReg(4, R_ESP, mkexpr(t2));
+//..             storeLE( mkexpr(t2), mkU32(guest_eip_bbstart+delta+len));
+//..             jmp_treg(Ijk_Call,t1);
+//..             *whatNext = Dis_StopHere;
+//..             break;
+//..          case 4: /* JMP Ev */
+//..             vassert(sz == 4);
+//..             jmp_treg(Ijk_Boring,t1);
+//..             *whatNext = Dis_StopHere;
+//..             break;
+//..          case 6: /* PUSH Ev */
+//..             vassert(sz == 4 || sz == 2);
+//..             t2 = newTemp(Ity_I32);
+//..             assign( t2, binop(Iop_Sub32,getIReg(4,R_ESP),mkU32(sz)) );
+//..             putIReg(4, R_ESP, mkexpr(t2) );
+//..             storeLE( mkexpr(t2), mkexpr(t1) );
+//..             break;
+//..          default: 
+//..             vex_printf(
+//..                "unhandled Grp5(M) case %d\n", (UInt)gregOfRM(modrm));
+//..             vpanic("Grp5(x86)");
+//..       }
+//..       delta += len;
+//..       DIP("%s%c %s\n", nameGrp5(gregOfRM(modrm)),
+//..                        nameISize(sz), dis_buf);
+//..    }
+//..    return delta;
+//.. }
+//.. 
+//.. 
+//.. /*------------------------------------------------------------*/
+//.. /*--- Disassembling string ops (including REP prefixes)    ---*/
+//.. /*------------------------------------------------------------*/
+//.. 
+//.. /* Code shared by all the string ops */
+//.. static
+//.. void dis_string_op_increment(Int sz, Int t_inc)
+//.. {
+//..    if (sz == 4 || sz == 2) {
+//..       assign( t_inc, 
+//..               binop(Iop_Shl32, IRExpr_Get( OFFB_DFLAG, Ity_I32 ),
+//..                                mkU8(sz/2) ) );
+//..    } else {
+//..       assign( t_inc, 
+//..               IRExpr_Get( OFFB_DFLAG, Ity_I32 ) );
+//..    }
+//.. }
+//.. 
+//.. static
+//.. void dis_string_op( void (*dis_OP)( Int, IRTemp ), 
+//..                     Int sz, Char* name, UChar sorb )
+//.. {
+//..    IRTemp t_inc = newTemp(Ity_I32);
+//..    vassert(sorb == 0);
+//..    dis_string_op_increment(sz, t_inc);
+//..    dis_OP( sz, t_inc );
+//..    DIP("%s%c\n", name, nameISize(sz));
+//.. }
+//.. 
+//.. static 
+//.. void dis_MOVS ( Int sz, IRTemp t_inc )
+//.. {
+//..    IRType ty = szToITy(sz);
+//..    //IRTemp tv = newTemp(ty);        /* value being copied */
+//..    IRTemp td = newTemp(Ity_I32);   /* EDI */
+//..    IRTemp ts = newTemp(Ity_I32);   /* ESI */
+//.. 
+//..    //uInstr2(cb, GET,   4, ArchReg, R_EDI, TempReg, td);
+//..    //uInstr2(cb, GET,   4, ArchReg, R_ESI, TempReg, ts);
+//..    assign( td, getIReg(4, R_EDI) );
+//..    assign( ts, getIReg(4, R_ESI) );
+//.. 
+//..    //uInstr2(cb, LOAD, sz, TempReg, ts,    TempReg, tv);
+//..    //uInstr2(cb, STORE,sz, TempReg, tv,    TempReg, td);
+//..    storeLE( mkexpr(td), loadLE(ty,mkexpr(ts)) );
+//.. 
+//..    //uInstr2(cb, ADD,   4, TempReg, t_inc, TempReg, td);
+//..    //uInstr2(cb, ADD,   4, TempReg, t_inc, TempReg, ts);
+//.. 
+//..    //uInstr2(cb, PUT,   4, TempReg, td,    ArchReg, R_EDI);
+//..    //uInstr2(cb, PUT,   4, TempReg, ts,    ArchReg, R_ESI);
+//..    putIReg( 4, R_EDI, binop(Iop_Add32, mkexpr(td), mkexpr(t_inc)) );
+//..    putIReg( 4, R_ESI, binop(Iop_Add32, mkexpr(ts), mkexpr(t_inc)) );
+//.. }
+//.. 
+//.. //-- static 
+//.. //-- void dis_LODS ( UCodeBlock* cb, Int sz, Int t_inc )
+//.. //-- {
+//.. //--    Int ta = newTemp(cb);   /* EAX */
+//.. //--    Int ts = newTemp(cb);   /* ESI */
+//.. //-- 
+//.. //--    uInstr2(cb, GET,    4, ArchReg, R_ESI, TempReg, ts);
+//.. //--    uInstr2(cb, LOAD,  sz, TempReg, ts,    TempReg, ta);
+//.. //--    uInstr2(cb, PUT,   sz, TempReg, ta,    ArchReg, R_EAX);
+//.. //-- 
+//.. //--    uInstr2(cb, ADD,   4, TempReg, t_inc, TempReg, ts);
+//.. //--    uInstr2(cb, PUT,   4, TempReg, ts,    ArchReg, R_ESI);
+//.. //-- }
+//.. 
+//.. static 
+//.. void dis_STOS ( Int sz, IRTemp t_inc )
+//.. {
+//..    IRType ty = szToITy(sz);
+//..    IRTemp ta = newTemp(ty);        /* EAX */
+//..    IRTemp td = newTemp(Ity_I32);   /* EDI */
+//.. 
+//..    //uInstr2(cb, GET,   sz, ArchReg, R_EAX, TempReg, ta);
+//..    assign( ta, getIReg(sz, R_EAX) );
+//.. 
+//..    //uInstr2(cb, GET,    4, ArchReg, R_EDI, TempReg, td);
+//..    assign( td, getIReg(4, R_EDI) );
+//.. 
+//..    //uInstr2(cb, STORE, sz, TempReg, ta,    TempReg, td);
+//..    storeLE( mkexpr(td), mkexpr(ta) );
+//.. 
+//..    //uInstr2(cb, ADD,   4, TempReg, t_inc, TempReg, td);
+//..    //uInstr2(cb, PUT,   4, TempReg, td,    ArchReg, R_EDI);
+//..    putIReg( 4, R_EDI, binop(Iop_Add32, mkexpr(td), mkexpr(t_inc)) );
+//.. }
+//.. 
+//.. static 
+//.. void dis_CMPS ( Int sz, IRTemp t_inc )
+//.. {
+//..    IRType ty  = szToITy(sz);
+//..    IRTemp tdv = newTemp(ty);      /* (EDI) */
+//..    IRTemp tsv = newTemp(ty);      /* (ESI) */
+//..    //IRTemp res = newTemp(ty);
+//..    IRTemp td  = newTemp(Ity_I32); /*  EDI  */
+//..    IRTemp ts  = newTemp(Ity_I32); /*  ESI  */
+//.. 
+//..    //uInstr2(cb, GET,   4, ArchReg, R_EDI, TempReg, td);
+//..    assign( td, getIReg(4, R_EDI) );
+//.. 
+//..    //uInstr2(cb, GET,   4, ArchReg, R_ESI, TempReg, ts);
+//..    assign( ts, getIReg(4, R_ESI) );
+//.. 
+//..    //uInstr2(cb, LOAD, sz, TempReg, td,    TempReg, tdv);
+//..    assign( tdv, loadLE(ty,mkexpr(td)) );
+//.. 
+//..    //uInstr2(cb, LOAD, sz, TempReg, ts,    TempReg, tsv);
+//..    assign( tsv, loadLE(ty,mkexpr(ts)) );
+//.. 
+//..    //uInstr2(cb, SUB,  sz, TempReg, tdv,   TempReg, tsv); 
+//..    //setFlagsFromUOpcode(cb, SUB);
+//..    //assign( res, binop(mkSizedOp(ty, Iop_Sub8), mkexpr(tsv), mkexpr(tdv)) );
+//..    setFlags_DEP1_DEP2 ( Iop_Sub8, tsv, tdv, ty );
+//.. 
+//..    //uInstr2(cb, ADD,   4, TempReg, t_inc, TempReg, td);
+//..    //uInstr2(cb, ADD,   4, TempReg, t_inc, TempReg, ts);
+//.. 
+//..    //uInstr2(cb, PUT,   4, TempReg, td,    ArchReg, R_EDI);
+//..    putIReg(4, R_EDI, binop(Iop_Add32, mkexpr(td), mkexpr(t_inc)) );
+//.. 
+//..    //uInstr2(cb, PUT,   4, TempReg, ts,    ArchReg, R_ESI);
+//..    putIReg(4, R_ESI, binop(Iop_Add32, mkexpr(ts), mkexpr(t_inc)) );
+//.. }
+//.. 
+//.. static 
+//.. void dis_SCAS ( Int sz, IRTemp t_inc )
+//.. {
+//..    IRType ty  = szToITy(sz);
+//..    IRTemp ta  = newTemp(ty);       /*  EAX  */
+//..    IRTemp td  = newTemp(Ity_I32);  /*  EDI  */
+//..    IRTemp tdv = newTemp(ty);       /* (EDI) */
+//..    //IRTemp res = newTemp(ty);
+//.. 
+//..    //uInstr2(cb, GET,  sz, ArchReg, R_EAX, TempReg, ta);
+//..    assign( ta, getIReg(sz, R_EAX) );
+//.. 
+//..    //uInstr2(cb, GET,   4, ArchReg, R_EDI, TempReg, td);
+//..    assign( td, getIReg(4, R_EDI) );
+//.. 
+//..    //uInstr2(cb, LOAD, sz, TempReg, td,    TempReg, tdv);
+//..    assign( tdv, loadLE(ty,mkexpr(td)) );
+//.. 
+//..    //uInstr2(cb, SUB,  sz, TempReg, tdv,   TempReg, ta);
+//..    //setFlagsFromUOpcode(cb, SUB);
+//..    //assign( res, binop(mkSizedOp(ty, Iop_Sub8), mkexpr(ta), mkexpr(tdv)) );
+//..    setFlags_DEP1_DEP2 ( Iop_Sub8, ta, tdv, ty );
+//.. 
+//..    //uInstr2(cb, ADD,   4, TempReg, t_inc, TempReg, td);
+//..    //uInstr2(cb, PUT,   4, TempReg, td,    ArchReg, R_EDI);
+//..    putIReg(4, R_EDI, binop(Iop_Add32, mkexpr(td), mkexpr(t_inc)) );
+//.. }
+//.. 
+//.. 
+//.. /* Wrap the appropriate string op inside a REP/REPE/REPNE.
+//..    We assume the insn is the last one in the basic block, and so emit a jump
+//..    to the next insn, rather than just falling through. */
+//.. static 
+//.. void dis_REP_op ( X86Condcode cond,
+//..                   void (*dis_OP)(Int, IRTemp),
+//..                   Int sz, Addr32 eip, Addr32 eip_next, Char* name )
+//.. {
+//..    IRTemp t_inc = newTemp(Ity_I32);
+//..    IRTemp tc    = newTemp(Ity_I32);  /*  ECX  */
+//.. 
+//..    //uInstr2 (cb, GET,   4, ArchReg, R_ECX, TempReg, tc);
+//..    assign( tc, getIReg(4,R_ECX) );
+//.. 
+//..    //uInstr2 (cb, JIFZ,  4, TempReg, tc,    Literal, 0);
+//..    //uLiteral(cb, eip_next);
+//..    stmt( IRStmt_Exit( binop(Iop_CmpEQ32,mkexpr(tc),mkU32(0)),
+//..                       Ijk_Boring,
+//..                       IRConst_U32(eip_next) ) );
+//.. 
+//..    //uInstr1 (cb, DEC,   4, TempReg, tc);
+//..    //uInstr2 (cb, PUT,   4, TempReg, tc,    ArchReg, R_ECX);
+//..    putIReg(4, R_ECX, binop(Iop_Sub32, mkexpr(tc), mkU32(1)) );
+//.. 
+//..    dis_string_op_increment(sz, t_inc);
+//..    dis_OP (sz, t_inc);
+//.. 
+//..    if (cond == X86CondAlways) {
+//..       jmp_lit(Ijk_Boring,eip);
+//..    } else {
+//..       stmt( IRStmt_Exit( mk_x86g_calculate_condition(cond),
+//..                          Ijk_Boring,
+//..                          IRConst_U32(eip) ) );
+//..       jmp_lit(Ijk_Boring,eip_next);
+//..    }
+//..    DIP("%s%c\n", name, nameISize(sz));
+//.. }
+//.. 
+//.. 
+//.. /*------------------------------------------------------------*/
+//.. /*--- Arithmetic, etc.                                     ---*/
+//.. /*------------------------------------------------------------*/
+//.. 
+//.. /* IMUL E, G.  Supplied eip points to the modR/M byte. */
+//.. static
+//.. UInt dis_mul_E_G ( UChar       sorb,
+//..                    Int         size, 
+//..                    UInt        delta0 )
+//.. {
+//..    Int    alen;
+//..    HChar  dis_buf[50];
+//..    UChar  rm = getIByte(delta0);
+//..    IRType ty = szToITy(size);
+//..    IRTemp te = newTemp(ty);
+//..    IRTemp tg = newTemp(ty);
+//..    IRTemp resLo = newTemp(ty);
+//.. 
+//..    assign( tg, getIReg(size, gregOfRM(rm)) );
+//..    if (epartIsReg(rm)) {
+//..       assign( te, getIReg(size, eregOfRM(rm)) );
+//..    } else {
+//..       IRTemp addr = disAMode( &alen, sorb, delta0, dis_buf );
+//..       assign( te, loadLE(ty,mkexpr(addr)) );
+//..    }
+//.. 
+//..    setFlags_MUL ( ty, te, tg, X86G_CC_OP_SMULB );
+//.. 
+//..    assign( resLo, binop( mkSizedOp(ty, Iop_Mul8), mkexpr(te), mkexpr(tg) ) );
+//.. 
+//..    putIReg(size, gregOfRM(rm), mkexpr(resLo) );
+//.. 
+//..    if (epartIsReg(rm)) {
+//..       DIP("imul%c %s, %s\n", nameISize(size), 
+//..                              nameIReg(size,eregOfRM(rm)),
+//..                              nameIReg(size,gregOfRM(rm)));
+//..       return 1+delta0;
+//..    } else {
+//..       DIP("imul%c %s, %s\n", nameISize(size), 
+//..                              dis_buf, nameIReg(size,gregOfRM(rm)));
+//..       return alen+delta0;
+//..    }
+//.. }
+//.. 
+//.. 
+//.. /* IMUL I * E -> G.  Supplied eip points to the modR/M byte. */
+//.. static
+//.. UInt dis_imul_I_E_G ( UChar       sorb,
+//..                       Int         size, 
+//..                       UInt        delta,
+//..                       Int         litsize )
+//.. {
+//..    Int    d32, alen;
+//..    HChar  dis_buf[50];
+//..    UChar  rm = getIByte(delta);
+//..    IRType ty = szToITy(size);
+//..    IRTemp te = newTemp(ty);
+//..    IRTemp tl = newTemp(ty);
+//..    IRTemp resLo = newTemp(ty);
+//.. 
+//..    vassert(size == 1 || size == 2 || size == 4);
+//.. 
+//..    if (epartIsReg(rm)) {
+//..       assign(te, getIReg(size, eregOfRM(rm)));
+//..       delta++;
+//..    } else {
+//..       IRTemp addr = disAMode( &alen, sorb, delta, dis_buf );
+//..       assign(te, loadLE(ty, mkexpr(addr)));
+//..       delta += alen;
+//..    }
+//..    d32 = getSDisp(litsize,delta);
+//..    delta += litsize;
+//.. 
+//..    if (size == 1) d32 &= 0xFF;
+//..    if (size == 2) d32 &= 0xFFFF;
+//.. 
+//..    assign(tl, mkU(ty,d32));
+//.. 
+//..    assign( resLo, binop( mkSizedOp(ty, Iop_Mul8), mkexpr(te), mkexpr(tl) ));
+//.. 
+//..    setFlags_MUL ( ty, te, tl, X86G_CC_OP_SMULB );
+//.. 
+//..    putIReg(size, gregOfRM(rm), mkexpr(resLo));
+//.. 
+//..    DIP("imul %d, %s, %s\n", d32, 
+//..        ( epartIsReg(rm) ? nameIReg(size,eregOfRM(rm)) : dis_buf ),
+//..        nameIReg(size,gregOfRM(rm)) );
+//..    return delta;
+//.. }
+//.. 
+//.. 
+//.. /*------------------------------------------------------------*/
+//.. /*---                                                      ---*/
+//.. /*--- x87 FLOATING POINT INSTRUCTIONS                      ---*/
+//.. /*---                                                      ---*/
+//.. /*------------------------------------------------------------*/
+//.. 
+//.. /* --- Helper functions for dealing with the register stack. --- */
+//.. 
+//.. /* --- Set the emulation-warning pseudo-register. --- */
+//.. 
+//.. static void put_emwarn ( IRExpr* e /* :: Ity_I32 */ )
+//.. {
+//..    stmt( IRStmt_Put( OFFB_EMWARN, e ) );
+//.. }
+//.. 
+//.. /* --- Produce an IRExpr* denoting a 64-bit QNaN. --- */
+//.. 
+//.. static IRExpr* mkQNaN64 ( void )
+//.. {
+//..   /* QNaN is 0 2047 1 0(51times) 
+//..      == 0b 11111111111b 1 0(51times)
+//..      == 0x7FF8 0000 0000 0000
+//..    */
+//..    return IRExpr_Const(IRConst_F64i(0x7FF8000000000000ULL));
+//.. }
+//.. 
+//.. /* --------- Get/put the top-of-stack pointer. --------- */
+//.. 
+//.. static IRExpr* get_ftop ( void )
+//.. {
+//..    return IRExpr_Get( OFFB_FTOP, Ity_I32 );
+//.. }
+//.. 
+//.. static void put_ftop ( IRExpr* e )
+//.. {
+//..    stmt( IRStmt_Put( OFFB_FTOP, e ) );
+//.. }
+//.. 
+//.. /* --------- Get/put the C3210 bits. --------- */
+//.. 
+//.. static IRExpr* get_C3210 ( void )
+//.. {
+//..    return IRExpr_Get( OFFB_FC3210, Ity_I32 );
+//.. }
+//.. 
+//.. static void put_C3210 ( IRExpr* e )
+//.. {
+//..    stmt( IRStmt_Put( OFFB_FC3210, e ) );
+//.. }
+//.. 
+//.. /* --------- Get/put the FPU rounding mode. --------- */
+//.. static IRExpr* /* :: Ity_I32 */ get_fpround ( void )
+//.. {
+//..    return IRExpr_Get( OFFB_FPROUND, Ity_I32 );
+//.. }
+//.. 
+//.. static void put_fpround ( IRExpr* /* :: Ity_I32 */ e )
+//.. {
+//..    stmt( IRStmt_Put( OFFB_FPROUND, e ) );
+//.. }
+//.. 
+//.. 
+//.. /* --------- Synthesise a 2-bit FPU rounding mode. --------- */
+//.. /* Produces a value in 0 .. 3, which is encoded as per the type
+//..    IRRoundingMode.  Since the guest_FPROUND value is also encoded as
+//..    per IRRoundingMode, we merely need to get it and mask it for
+//..    safety.
+//.. */
+//.. static IRExpr* /* :: Ity_I32 */ get_roundingmode ( void )
+//.. {
+//..    return binop( Iop_And32, get_fpround(), mkU32(3) );
+//.. }
+//.. 
+//.. 
+//.. /* --------- Get/set FP register tag bytes. --------- */
+//.. 
+//.. /* Given i, and some expression e, generate 'ST_TAG(i) = e'. */
+//.. 
+//.. static void put_ST_TAG ( Int i, IRExpr* value )
+//.. {
+//..    IRArray* descr;
+//..    vassert(typeOfIRExpr(irbb->tyenv, value) == Ity_I8);
+//..    descr = mkIRArray( OFFB_FPTAGS, Ity_I8, 8 );
+//..    stmt( IRStmt_PutI( descr, get_ftop(), i, value ) );
+//.. }
+//.. 
+//.. /* Given i, generate an expression yielding 'ST_TAG(i)'.  This will be
+//..    zero to indicate "Empty" and nonzero to indicate "NonEmpty".  */
+//.. 
+//.. static IRExpr* get_ST_TAG ( Int i )
+//.. {
+//..    IRArray* descr = mkIRArray( OFFB_FPTAGS, Ity_I8, 8 );
+//..    return IRExpr_GetI( descr, get_ftop(), i );
+//.. }
+//.. 
+//.. 
+//.. /* --------- Get/set FP registers. --------- */
+//.. 
+//.. /* Given i, and some expression e, emit 'ST(i) = e' and set the
+//..    register's tag to indicate the register is full.  The previous
+//..    state of the register is not checked. */
+//.. 
+//.. static void put_ST_UNCHECKED ( Int i, IRExpr* value )
+//.. {
+//..    IRArray* descr;
+//..    vassert(typeOfIRExpr(irbb->tyenv, value) == Ity_F64);
+//..    descr = mkIRArray( OFFB_FPREGS, Ity_F64, 8 );
+//..    stmt( IRStmt_PutI( descr, get_ftop(), i, value ) );
+//..    /* Mark the register as in-use. */
+//..    put_ST_TAG(i, mkU8(1));
+//.. }
+//.. 
+//.. /* Given i, and some expression e, emit
+//..       ST(i) = is_full(i) ? NaN : e
+//..    and set the tag accordingly.
+//.. */
+//.. 
+//.. static void put_ST ( Int i, IRExpr* value )
+//.. {
+//..    put_ST_UNCHECKED( i,
+//..                      IRExpr_Mux0X( get_ST_TAG(i),
+//..                                    /* 0 means empty */
+//..                                    value,
+//..                                    /* non-0 means full */
+//..                                    mkQNaN64()
+//..                    )
+//..    );
+//.. }
+//.. 
+//.. 
+//.. /* Given i, generate an expression yielding 'ST(i)'. */
+//.. 
+//.. static IRExpr* get_ST_UNCHECKED ( Int i )
+//.. {
+//..    IRArray* descr = mkIRArray( OFFB_FPREGS, Ity_F64, 8 );
+//..    return IRExpr_GetI( descr, get_ftop(), i );
+//.. }
+//.. 
+//.. 
+//.. /* Given i, generate an expression yielding 
+//..   is_full(i) ? ST(i) : NaN
+//.. */
+//.. 
+//.. static IRExpr* get_ST ( Int i )
+//.. {
+//..    return
+//..       IRExpr_Mux0X( get_ST_TAG(i),
+//..                     /* 0 means empty */
+//..                     mkQNaN64(),
+//..                     /* non-0 means full */
+//..                     get_ST_UNCHECKED(i));
+//.. }
+//.. 
+//.. 
+//.. /* Adjust FTOP downwards by one register. */
+//.. 
+//.. static void fp_push ( void )
+//.. {
+//..    put_ftop( binop(Iop_Sub32, get_ftop(), mkU32(1)) );
+//.. }
+//.. 
+//.. /* Adjust FTOP upwards by one register, and mark the vacated register
+//..    as empty.  */
+//.. 
+//.. static void fp_pop ( void )
+//.. {
+//..    put_ST_TAG(0, mkU8(0));
+//..    put_ftop( binop(Iop_Add32, get_ftop(), mkU32(1)) );
+//.. }
+//.. 
+//.. /* Clear the C2 bit of the FPU status register, for
+//..    sin/cos/tan/sincos. */
+//.. 
+//.. static void clear_C2 ( void )
+//.. {
+//..    put_C3210( binop(Iop_And32, get_C3210(), mkU32(~X86G_FC_MASK_C2)) );
+//.. }
+//.. 
+//.. 
+//.. /* ------------------------------------------------------- */
+//.. /* Given all that stack-mangling junk, we can now go ahead
+//..    and describe FP instructions. 
+//.. */
+//.. 
+//.. /* ST(0) = ST(0) `op` mem64/32(addr)
+//..    Need to check ST(0)'s tag on read, but not on write.
+//.. */
+//.. static
+//.. void fp_do_op_mem_ST_0 ( IRTemp addr, UChar* op_txt, UChar* dis_buf, 
+//..                          IROp op, Bool dbl )
+//.. {
+//..    DIP("f%s%c %s\n", op_txt, dbl?'l':'s', dis_buf);
+//..    if (dbl) {
+//..       put_ST_UNCHECKED(0, 
+//..          binop( op, 
+//..                 get_ST(0), 
+//..                 loadLE(Ity_F64,mkexpr(addr))
+//..          ));
+//..    } else {
+//..       put_ST_UNCHECKED(0, 
+//..          binop( op, 
+//..                 get_ST(0), 
+//..                 unop(Iop_F32toF64, loadLE(Ity_F32,mkexpr(addr)))
+//..          ));
+//..    }
+//.. }
+//.. 
+//.. 
+//.. /* ST(0) = mem64/32(addr) `op` ST(0)
+//..    Need to check ST(0)'s tag on read, but not on write.
+//.. */
+//.. static
+//.. void fp_do_oprev_mem_ST_0 ( IRTemp addr, UChar* op_txt, UChar* dis_buf, 
+//..                             IROp op, Bool dbl )
+//.. {
+//..    DIP("f%s%c %s\n", op_txt, dbl?'l':'s', dis_buf);
+//..    if (dbl) {
+//..       put_ST_UNCHECKED(0, 
+//..          binop( op, 
+//..                 loadLE(Ity_F64,mkexpr(addr)),
+//..                 get_ST(0)
+//..          ));
+//..    } else {
+//..       put_ST_UNCHECKED(0, 
+//..          binop( op, 
+//..                 unop(Iop_F32toF64, loadLE(Ity_F32,mkexpr(addr))),
+//..                 get_ST(0)
+//..          ));
+//..    }
+//.. }
+//.. 
+//.. 
+//.. /* ST(dst) = ST(dst) `op` ST(src).
+//..    Check dst and src tags when reading but not on write.
+//.. */
+//.. static
+//.. void fp_do_op_ST_ST ( UChar* op_txt, IROp op, UInt st_src, UInt st_dst,
+//..                       Bool pop_after )
+//.. {
+//..    DIP("f%s%s st(%d), st(%d)\n", op_txt, pop_after?"p":"", st_src, st_dst );
+//..    put_ST_UNCHECKED( 
+//..       st_dst, 
+//..       binop(op, get_ST(st_dst), get_ST(st_src) ) 
+//..    );
+//..    if (pop_after)
+//..       fp_pop();
+//.. }
+//.. 
+//.. /* ST(dst) = ST(src) `op` ST(dst).
+//..    Check dst and src tags when reading but not on write.
+//.. */
+//.. static
+//.. void fp_do_oprev_ST_ST ( UChar* op_txt, IROp op, UInt st_src, UInt st_dst,
+//..                          Bool pop_after )
+//.. {
+//..    DIP("f%s%s st(%d), st(%d)\n", op_txt, pop_after?"p":"", st_src, st_dst );
+//..    put_ST_UNCHECKED( 
+//..       st_dst, 
+//..       binop(op, get_ST(st_src), get_ST(st_dst) ) 
+//..    );
+//..    if (pop_after)
+//..       fp_pop();
+//.. }
+//.. 
+//.. /* %eflags(Z,P,C) = UCOMI( st(0), st(i) ) */
+//.. static void fp_do_ucomi_ST0_STi ( UInt i, Bool pop_after )
+//.. {
+//..    DIP("fucomi%s %%st(0),%%st(%d)\n", pop_after ? "p" : "", i);
+//..    /* This is a bit of a hack (and isn't really right).  It sets
+//..       Z,P,C,O correctly, but forces A and S to zero, whereas the Intel
+//..       documentation implies A and S are unchanged. 
+//..    */
+//..    /* It's also fishy in that it is used both for COMIP and
+//..       UCOMIP, and they aren't the same (although similar). */
+//..    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_CmpF64, get_ST(0), get_ST(i)),
+//..                             mkU32(0x45)
+//..        )));
+//..    if (pop_after)
+//..       fp_pop();
+//.. }
+//.. 
+//.. 
+//.. static
+//.. UInt dis_FPU ( Bool* decode_ok, UChar sorb, UInt delta )
+//.. {
+//..    Int    len;
+//..    UInt   r_src, r_dst;
+//..    HChar  dis_buf[50];
+//..    IRTemp t1, t2;
+//.. 
+//..    /* On entry, delta points at the second byte of the insn (the modrm
+//..       byte).*/
+//..    UChar first_opcode = getIByte(delta-1);
+//..    UChar modrm        = getIByte(delta+0);
+//.. 
+//..    /* -+-+-+-+-+-+-+-+-+-+-+-+ 0xD8 opcodes +-+-+-+-+-+-+-+ */
+//.. 
+//..    if (first_opcode == 0xD8) {
+//..       if (modrm < 0xC0) {
+//.. 
+//..          /* bits 5,4,3 are an opcode extension, and the modRM also
+//..            specifies an address. */
+//..          IRTemp addr = disAMode( &len, sorb, delta, dis_buf );
+//..          delta += len;
+//.. 
+//..          switch (gregOfRM(modrm)) {
+//.. 
+//..             case 0: /* FADD single-real */
+//..                fp_do_op_mem_ST_0 ( addr, "add", dis_buf, Iop_AddF64, False );
+//..                break;
+//.. 
+//..             case 1: /* FMUL single-real */
+//..                fp_do_op_mem_ST_0 ( addr, "mul", dis_buf, Iop_MulF64, False );
+//..                break;
+//.. 
+//..             case 2: /* FCOM single-real */
+//..                DIP("fcoms %s\n", dis_buf);
+//..                /* This forces C1 to zero, which isn't right. */
+//..                put_C3210( 
+//..                    binop( Iop_And32,
+//..                           binop(Iop_Shl32, 
+//..                                 binop(Iop_CmpF64, 
+//..                                       get_ST(0),
+//..                                       unop(Iop_F32toF64, 
+//..                                            loadLE(Ity_F32,mkexpr(addr)))),
+//..                                 mkU8(8)),
+//..                           mkU32(0x4500)
+//..                    ));
+//..                break;  
+//.. 
+//..             case 3: /* FCOMP single-real */
+//..                DIP("fcomps %s\n", dis_buf);
+//..                /* This forces C1 to zero, which isn't right. */
+//..                put_C3210( 
+//..                    binop( Iop_And32,
+//..                           binop(Iop_Shl32, 
+//..                                 binop(Iop_CmpF64, 
+//..                                       get_ST(0),
+//..                                       unop(Iop_F32toF64, 
+//..                                            loadLE(Ity_F32,mkexpr(addr)))),
+//..                                 mkU8(8)),
+//..                           mkU32(0x4500)
+//..                    ));
+//..                fp_pop();
+//..                break;  
+//.. 
+//..             case 4: /* FSUB single-real */
+//..                fp_do_op_mem_ST_0 ( addr, "sub", dis_buf, Iop_SubF64, False );
+//..                break;
+//.. 
+//..             case 5: /* FSUBR single-real */
+//..                fp_do_oprev_mem_ST_0 ( addr, "subr", dis_buf, Iop_SubF64, False );
+//..                break;
+//.. 
+//..             case 6: /* FDIV single-real */
+//..                fp_do_op_mem_ST_0 ( addr, "div", dis_buf, Iop_DivF64, False );
+//..                break;
+//.. 
+//..             case 7: /* FDIVR single-real */
+//..                fp_do_oprev_mem_ST_0 ( addr, "divr", dis_buf, Iop_DivF64, False );
+//..                break;
+//.. 
+//..             default:
+//..                vex_printf("unhandled opc_aux = 0x%2x\n", gregOfRM(modrm));
+//..                vex_printf("first_opcode == 0xD8\n");
+//..                goto decode_fail;
+//..          }
+//..       } else {
+//..          delta++;
+//..          switch (modrm) {
+//.. 
+//..             case 0xC0 ... 0xC7: /* FADD %st(?),%st(0) */
+//..                fp_do_op_ST_ST ( "add", Iop_AddF64, modrm - 0xC0, 0, False );
+//..                break;
+//.. 
+//..             case 0xC8 ... 0xCF: /* FMUL %st(?),%st(0) */
+//..                fp_do_op_ST_ST ( "mul", Iop_MulF64, modrm - 0xC8, 0, False );
+//..                break;
+//.. 
+//.. #if 1
+//..             /* Dunno if this is right */
+//..             case 0xD0 ... 0xD7: /* FCOM %st(?),%st(0) */
+//..                r_dst = (UInt)modrm - 0xD0;
+//..                DIP("fcom %%st(0),%%st(%d)\n", r_dst);
+//..                /* This forces C1 to zero, which isn't right. */
+//..                put_C3210( 
+//..                    binop( Iop_And32,
+//..                           binop(Iop_Shl32, 
+//..                                 binop(Iop_CmpF64, get_ST(0), get_ST(r_dst)),
+//..                                 mkU8(8)),
+//..                           mkU32(0x4500)
+//..                    ));
+//..                break;
+//.. #endif
+//.. #if 1
+//..             /* Dunno if this is right */
+//..             case 0xD8 ... 0xDF: /* FCOMP %st(?),%st(0) */
+//..                r_dst = (UInt)modrm - 0xD8;
+//..                DIP("fcomp %%st(0),%%st(%d)\n", r_dst);
+//..                /* This forces C1 to zero, which isn't right. */
+//..                put_C3210( 
+//..                    binop( Iop_And32,
+//..                           binop(Iop_Shl32, 
+//..                                 binop(Iop_CmpF64, get_ST(0), get_ST(r_dst)),
+//..                                 mkU8(8)),
+//..                           mkU32(0x4500)
+//..                    ));
+//..                fp_pop();
+//..                break;
+//.. #endif
+//..             case 0xE0 ... 0xE7: /* FSUB %st(?),%st(0) */
+//..                fp_do_op_ST_ST ( "sub", Iop_SubF64, modrm - 0xE0, 0, False );
+//..                break;
+//.. 
+//..             case 0xE8 ... 0xEF: /* FSUBR %st(?),%st(0) */
+//..                fp_do_oprev_ST_ST ( "subr", Iop_SubF64, modrm - 0xE8, 0, False );
+//..                break;
+//.. 
+//..             case 0xF0 ... 0xF7: /* FDIV %st(?),%st(0) */
+//..                fp_do_op_ST_ST ( "div", Iop_DivF64, modrm - 0xF0, 0, False );
+//..                break;
+//.. 
+//..             case 0xF8 ... 0xFF: /* FDIVR %st(?),%st(0) */
+//..                fp_do_oprev_ST_ST ( "divr", Iop_DivF64, modrm - 0xF8, 0, False );
+//..                break;
+//.. 
+//..             default:
+//..                goto decode_fail;
+//..          }
+//..       }
+//..    }
+//.. 
+//..    /* -+-+-+-+-+-+-+-+-+-+-+-+ 0xD9 opcodes +-+-+-+-+-+-+-+ */
+//..    else
+//..    if (first_opcode == 0xD9) {
+//..       if (modrm < 0xC0) {
+//.. 
+//..          /* bits 5,4,3 are an opcode extension, and the modRM also
+//..             specifies an address. */
+//..          IRTemp addr = disAMode( &len, sorb, delta, dis_buf );
+//..          delta += len;
+//.. 
+//..          switch (gregOfRM(modrm)) {
+//.. 
+//..             case 0: /* FLD single-real */
+//..                DIP("flds %s\n", dis_buf);
+//..                fp_push();
+//..                put_ST(0, unop(Iop_F32toF64,
+//..                               loadLE(Ity_F32, mkexpr(addr))));
+//..                break;
+//.. 
+//..             case 2: /* FST single-real */
+//..                DIP("fsts %s\n", dis_buf);
+//..                storeLE(mkexpr(addr),
+//..                        binop(Iop_F64toF32, get_roundingmode(), get_ST(0)));
+//..                break;
+//.. 
+//..             case 3: /* FSTP single-real */
+//..                DIP("fstps %s\n", dis_buf);
+//..                storeLE(mkexpr(addr), 
+//..                        binop(Iop_F64toF32, get_roundingmode(), get_ST(0)));
+//..                fp_pop();
+//..                break;
+//.. 
+//..             case 4: { /* FLDENV m108 */
+//..                /* Uses dirty helper: 
+//..                      VexEmWarn x86g_do_FLDENV ( VexGuestX86State*, Addr32 ) */
+//..                IRTemp   ew = newTemp(Ity_I32);
+//..                IRDirty* d  = unsafeIRDirty_0_N ( 
+//..                                 0/*regparms*/, 
+//..                                 "x86g_dirtyhelper_FLDENV", 
+//..                                 &x86g_dirtyhelper_FLDENV,
+//..                                 mkIRExprVec_1( mkexpr(addr) )
+//..                              );
+//..                d->needsBBP = True;
+//..                d->tmp      = ew;
+//..                /* declare we're reading memory */
+//..                d->mFx   = Ifx_Read;
+//..                d->mAddr = mkexpr(addr);
+//..                d->mSize = 28;
+//.. 
+//..                /* declare we're writing guest state */
+//..                d->nFxState = 5;
+//.. 
+//..                d->fxState[0].fx     = Ifx_Write;
+//..                d->fxState[0].offset = OFFB_FTOP;
+//..                d->fxState[0].size   = sizeof(UInt);
+//.. 
+//..                d->fxState[1].fx     = Ifx_Write;
+//..                d->fxState[1].offset = OFFB_FPREGS;
+//..                d->fxState[1].size   = 8 * sizeof(ULong);
+//.. 
+//..                d->fxState[2].fx     = Ifx_Write;
+//..                d->fxState[2].offset = OFFB_FPTAGS;
+//..                d->fxState[2].size   = 8 * sizeof(UChar);
+//.. 
+//..                d->fxState[3].fx     = Ifx_Write;
+//..                d->fxState[3].offset = OFFB_FPROUND;
+//..                d->fxState[3].size   = sizeof(UInt);
+//.. 
+//..                d->fxState[4].fx     = Ifx_Write;
+//..                d->fxState[4].offset = OFFB_FC3210;
+//..                d->fxState[4].size   = sizeof(UInt);
+//.. 
+//..                stmt( IRStmt_Dirty(d) );
+//.. 
+//..                /* ew contains any emulation warning we may need to
+//..                   issue.  If needed, side-exit to the next insn,
+//..                   reporting the warning, so that Valgrind's dispatcher
+//..                   sees the warning. */
+//..                put_emwarn( mkexpr(ew) );
+//..                stmt( 
+//..                   IRStmt_Exit(
+//..                      binop(Iop_CmpNE32, mkexpr(ew), mkU32(0)),
+//..                      Ijk_EmWarn,
+//..                      IRConst_U32( ((Addr32)guest_eip_bbstart)+delta)
+//..                   )
+//..                );
+//.. 
+//..                DIP("fldenv %s\n", dis_buf);
+//..                break;
+//..             }
+//.. 
+//..             case 5: {/* FLDCW */
+//..                /* The only thing we observe in the control word is the
+//..                   rounding mode.  Therefore, pass the 16-bit value
+//..                   (x87 native-format control word) to a clean helper,
+//..                   getting back a 64-bit value, the lower half of which
+//..                   is the FPROUND value to store, and the upper half of
+//..                   which is the emulation-warning token which may be
+//..                   generated.
+//..                */
+//..                /* ULong x86h_check_fldcw ( UInt ); */
+//..                IRTemp t64 = newTemp(Ity_I64);
+//..                IRTemp ew = newTemp(Ity_I32);
+//..                DIP("fldcw %s\n", dis_buf);
+//..                assign( t64, mkIRExprCCall(
+//..                                Ity_I64, 0/*regparms*/, 
+//..                                "x86g_check_fldcw",
+//..                                &x86g_check_fldcw, 
+//..                                mkIRExprVec_1( 
+//..                                   unop( Iop_16Uto32, 
+//..                                         loadLE(Ity_I16, mkexpr(addr)))
+//..                                )
+//..                             )
+//..                      );
+//.. 
+//..                put_fpround( unop(Iop_64to32, mkexpr(t64)) );
+//..                assign( ew, unop(Iop_64HIto32, mkexpr(t64) ) );
+//..                put_emwarn( mkexpr(ew) );
+//..                /* Finally, if an emulation warning was reported,
+//..                   side-exit to the next insn, reporting the warning,
+//..                   so that Valgrind's dispatcher sees the warning. */
+//..                stmt( 
+//..                   IRStmt_Exit(
+//..                      binop(Iop_CmpNE32, mkexpr(ew), mkU32(0)),
+//..                      Ijk_EmWarn,
+//..                      IRConst_U32( ((Addr32)guest_eip_bbstart)+delta)
+//..                   )
+//..                );
+//..                break;
+//..             }
+//.. 
+//..             case 6: { /* FNSTENV m28 */
+//..                /* Uses dirty helper: 
+//..                      void x86g_do_FSTENV ( VexGuestX86State*, UInt ) */
+//..                IRDirty* d = unsafeIRDirty_0_N ( 
+//..                                0/*regparms*/, 
+//..                                "x86g_dirtyhelper_FSTENV", 
+//..                                &x86g_dirtyhelper_FSTENV,
+//..                                mkIRExprVec_1( mkexpr(addr) )
+//..                             );
+//..                d->needsBBP = True;
+//..                /* declare we're writing memory */
+//..                d->mFx   = Ifx_Write;
+//..                d->mAddr = mkexpr(addr);
+//..                d->mSize = 28;
+//.. 
+//..                /* declare we're reading guest state */
+//..                d->nFxState = 4;
+//.. 
+//..                d->fxState[0].fx     = Ifx_Read;
+//..                d->fxState[0].offset = OFFB_FTOP;
+//..                d->fxState[0].size   = sizeof(UInt);
+//.. 
+//..                d->fxState[1].fx     = Ifx_Read;
+//..                d->fxState[1].offset = OFFB_FPTAGS;
+//..                d->fxState[1].size   = 8 * sizeof(UChar);
+//.. 
+//..                d->fxState[2].fx     = Ifx_Read;
+//..                d->fxState[2].offset = OFFB_FPROUND;
+//..                d->fxState[2].size   = sizeof(UInt);
+//.. 
+//..                d->fxState[3].fx     = Ifx_Read;
+//..                d->fxState[3].offset = OFFB_FC3210;
+//..                d->fxState[3].size   = sizeof(UInt);
+//.. 
+//..                stmt( IRStmt_Dirty(d) );
+//.. 
+//..                DIP("fnstenv %s\n", dis_buf);
+//..                break;
+//..             }
+//.. 
+//..             case 7: /* FNSTCW */
+//..               /* Fake up a native x87 FPU control word.  The only
+//..                  thing it depends on is FPROUND[1:0], so call a clean
+//..                  helper to cook it up. */
+//..                /* UInt x86h_create_fpucw ( UInt fpround ) */
+//..                DIP("fnstcw %s\n", dis_buf);
+//..                storeLE(
+//..                   mkexpr(addr), 
+//..                   unop( Iop_32to16, 
+//..                         mkIRExprCCall(
+//..                            Ity_I32, 0/*regp*/,
+//..                            "x86g_create_fpucw", &x86g_create_fpucw, 
+//..                            mkIRExprVec_1( get_fpround() ) 
+//..                         ) 
+//..                   ) 
+//..                );
+//..                break;
+//.. 
+//..             default:
+//..                vex_printf("unhandled opc_aux = 0x%2x\n", gregOfRM(modrm));
+//..                vex_printf("first_opcode == 0xD9\n");
+//..                goto decode_fail;
+//..          }
+//.. 
+//..       } else {
+//..          delta++;
+//..          switch (modrm) {
+//.. 
+//..             case 0xC0 ... 0xC7: /* FLD %st(?) */
+//..                r_src = (UInt)modrm - 0xC0;
+//..                DIP("fld %%st(%d)\n", r_src);
+//..                t1 = newTemp(Ity_F64);
+//..                assign(t1, get_ST(r_src));
+//..                fp_push();
+//..                put_ST(0, mkexpr(t1));
+//..                break;
+//.. 
+//..             case 0xC8 ... 0xCF: /* FXCH %st(?) */
+//..                r_src = (UInt)modrm - 0xC8;
+//..                DIP("fxch %%st(%d)\n", r_src);
+//..                t1 = newTemp(Ity_F64);
+//..                t2 = newTemp(Ity_F64);
+//..                assign(t1, get_ST(0));
+//..                assign(t2, get_ST(r_src));
+//..                put_ST_UNCHECKED(0, mkexpr(t2));
+//..                put_ST_UNCHECKED(r_src, mkexpr(t1));
+//..                break;
+//.. 
+//..             case 0xE0: /* FCHS */
+//..                DIP("fchs\n");
+//..                put_ST_UNCHECKED(0, unop(Iop_NegF64, get_ST(0)));
+//..                break;
+//.. 
+//..             case 0xE1: /* FABS */
+//..                DIP("fabs\n");
+//..                put_ST_UNCHECKED(0, unop(Iop_AbsF64, get_ST(0)));
+//..                break;
+//.. 
+//..             case 0xE5: { /* FXAM */
+//..                /* This is an interesting one.  It examines %st(0),
+//..                   regardless of whether the tag says it's empty or not.
+//..                   Here, just pass both the tag (in our format) and the
+//..                   value (as a double, actually a ULong) to a helper
+//..                   function. */
+//..                IRExpr** args
+//..                   = mkIRExprVec_2( unop(Iop_8Uto32, get_ST_TAG(0)),
+//..                                    unop(Iop_ReinterpF64asI64, 
+//..                                         get_ST_UNCHECKED(0)) );
+//..                put_C3210(mkIRExprCCall(
+//..                             Ity_I32, 
+//..                             0/*regparm*/, 
+//..                             "x86g_calculate_FXAM", &x86g_calculate_FXAM,
+//..                             args
+//..                         ));
+//..                DIP("fxam\n");
+//..                break;
+//..             }
+//.. 
+//..             case 0xE8: /* FLD1 */
+//..                DIP("fld1\n");
+//..                fp_push();
+//..                /* put_ST(0, IRExpr_Const(IRConst_F64(1.0))); */
+//..                put_ST(0, IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL)));
+//..                break;
+//.. 
+//..             case 0xE9: /* FLDL2T */
+//..                DIP("fldl2t\n");
+//..                fp_push();
+//..                /* put_ST(0, IRExpr_Const(IRConst_F64(3.32192809488736234781))); */
+//..                put_ST(0, IRExpr_Const(IRConst_F64i(0x400a934f0979a371ULL)));
+//..                break;
+//.. 
+//..             case 0xEA: /* FLDL2E */
+//..                DIP("fldl2e\n");
+//..                fp_push();
+//..                /* put_ST(0, IRExpr_Const(IRConst_F64(1.44269504088896340739))); */
+//..                put_ST(0, IRExpr_Const(IRConst_F64i(0x3ff71547652b82feULL)));
+//..                break;
+//.. 
+//..             case 0xEB: /* FLDPI */
+//..                DIP("fldpi\n");
+//..                fp_push();
+//..                /* put_ST(0, IRExpr_Const(IRConst_F64(3.14159265358979323851))); */
+//..                put_ST(0, IRExpr_Const(IRConst_F64i(0x400921fb54442d18ULL)));
+//..                break;
+//.. 
+//..             case 0xEC: /* FLDLG2 */
+//..                DIP("fldlg2\n");
+//..                fp_push();
+//..                /* put_ST(0, IRExpr_Const(IRConst_F64(0.301029995663981143))); */
+//..                put_ST(0, IRExpr_Const(IRConst_F64i(0x3fd34413509f79ffULL)));
+//..                break;
+//.. 
+//..             case 0xED: /* FLDLN2 */
+//..                DIP("fldln2\n");
+//..                fp_push();
+//..                /* put_ST(0, IRExpr_Const(IRConst_F64(0.69314718055994530942))); */
+//..                put_ST(0, IRExpr_Const(IRConst_F64i(0x3fe62e42fefa39efULL)));
+//..                break;
+//.. 
+//..             case 0xEE: /* FLDZ */
+//..                DIP("fldz\n");
+//..                fp_push();
+//..                /* put_ST(0, IRExpr_Const(IRConst_F64(0.0))); */
+//..                put_ST(0, IRExpr_Const(IRConst_F64i(0x0000000000000000ULL)));
+//..                break;
+//.. 
+//..             case 0xF0: /* F2XM1 */
+//..                DIP("f2xm1\n");
+//..                put_ST_UNCHECKED(0, unop(Iop_2xm1F64, get_ST(0)));
+//..                break;
+//.. 
+//..             case 0xF1: /* FYL2X */
+//..                DIP("fyl2x\n");
+//..                put_ST_UNCHECKED(1, binop(Iop_Yl2xF64,
+//..                                          get_ST(1), get_ST(0)));
+//..                fp_pop();
+//..                break;
+//.. 
+//..             case 0xF2: /* FPTAN */
+//..                DIP("ftan\n");
+//..                put_ST_UNCHECKED(0, unop(Iop_TanF64, get_ST(0)));
+//..                fp_push();
+//..                put_ST(0, IRExpr_Const(IRConst_F64(1.0)));
+//..                clear_C2(); /* HACK */
+//..                break;
+//.. 
+//..             case 0xF3: /* FPATAN */
+//..                DIP("fpatan\n");
+//..                put_ST_UNCHECKED(1, binop(Iop_AtanF64,
+//..                                          get_ST(1), get_ST(0)));
+//..                fp_pop();
+//..                break;
+//.. 
+//..             case 0xF5: { /* FPREM1 -- IEEE compliant */
+//..                IRTemp a1 = newTemp(Ity_F64);
+//..                IRTemp a2 = newTemp(Ity_F64);
+//..                DIP("fprem1\n");
+//..                /* Do FPREM1 twice, once to get the remainder, and once
+//..                   to get the C3210 flag values. */
+//..                assign( a1, get_ST(0) );
+//..                assign( a2, get_ST(1) );
+//..                put_ST_UNCHECKED(0, binop(Iop_PRem1F64,
+//..                                          mkexpr(a1), mkexpr(a2)));
+//..                put_C3210( binop(Iop_PRem1C3210F64, mkexpr(a1), mkexpr(a2)) );
+//..                break;
+//..             }
+//.. 
+//..             case 0xF7: /* FINCSTP */
+//..                DIP("fprem\n");
+//..                put_ftop( binop(Iop_Add32, get_ftop(), mkU32(1)) );
+//..                break;
+//.. 
+//..             case 0xF8: { /* FPREM -- not IEEE compliant */
+//..                IRTemp a1 = newTemp(Ity_F64);
+//..                IRTemp a2 = newTemp(Ity_F64);
+//..                DIP("fprem\n");
+//..                /* Do FPREM twice, once to get the remainder, and once
+//..                   to get the C3210 flag values. */
+//..                assign( a1, get_ST(0) );
+//..                assign( a2, get_ST(1) );
+//..                put_ST_UNCHECKED(0, binop(Iop_PRemF64,
+//..                                          mkexpr(a1), mkexpr(a2)));
+//..                put_C3210( binop(Iop_PRemC3210F64, mkexpr(a1), mkexpr(a2)) );
+//..                break;
+//..             }
+//.. 
+//..             case 0xF9: /* FYL2XP1 */
+//..                DIP("fyl2xp1\n");
+//..                put_ST_UNCHECKED(1, binop(Iop_Yl2xp1F64,
+//..                                          get_ST(1), get_ST(0)));
+//..                fp_pop();
+//..                break;
+//.. 
+//..             case 0xFA: /* FSQRT */
+//..                DIP("fsqrt\n");
+//..                put_ST_UNCHECKED(0, unop(Iop_SqrtF64, get_ST(0)));
+//..                break;
+//.. 
+//..             case 0xFB: { /* FSINCOS */
+//..                IRTemp a1 = newTemp(Ity_F64);
+//..                assign( a1, get_ST(0) );
+//..                DIP("fsincos\n");
+//..                put_ST_UNCHECKED(0, unop(Iop_SinF64, mkexpr(a1)));
+//..                fp_push();
+//..                put_ST(0, unop(Iop_CosF64, mkexpr(a1)));
+//..                break;
+//..             }
+//.. 
+//..             case 0xFC: /* FRNDINT */
+//..                DIP("frndint\n");
+//..                put_ST_UNCHECKED(0,
+//..                   binop(Iop_RoundF64, get_roundingmode(), get_ST(0)) );
+//..                break;
+//.. 
+//..             case 0xFD: /* FSCALE */
+//..                DIP("fscale\n");
+//..                put_ST_UNCHECKED(0, binop(Iop_ScaleF64,
+//..                                          get_ST(0), get_ST(1)));
+//..                break;
+//.. 
+//..             case 0xFE: /* FSIN */
+//..                DIP("fsin\n");
+//..                put_ST_UNCHECKED(0, unop(Iop_SinF64, get_ST(0)));
+//..                clear_C2(); /* HACK */
+//..                break;
+//.. 
+//..             case 0xFF: /* FCOS */
+//..                DIP("fcos\n");
+//..                put_ST_UNCHECKED(0, unop(Iop_CosF64, get_ST(0)));
+//..                clear_C2(); /* HACK */
+//..                break;
+//.. 
+//..             default:
+//..                goto decode_fail;
+//..          }
+//..       }
+//..    }
+//.. 
+//..    /* -+-+-+-+-+-+-+-+-+-+-+-+ 0xDA opcodes +-+-+-+-+-+-+-+ */
+//..    else
+//..    if (first_opcode == 0xDA) {
+//.. 
+//..       if (modrm < 0xC0) {
+//.. 
+//..          /* bits 5,4,3 are an opcode extension, and the modRM also
+//..             specifies an address. */
+//..          IROp   fop;
+//..          IRTemp addr = disAMode( &len, sorb, delta, dis_buf );
+//..          delta += len;
+//..          switch (gregOfRM(modrm)) {
+//.. 
+//..             case 0: /* FIADD m32int */ /* ST(0) += m32int */
+//..                DIP("fiaddl %s\n", dis_buf);
+//..                fop = Iop_AddF64;
+//..                goto do_fop_m32;
+//.. 
+//..             case 1: /* FIMUL m32int */ /* ST(0) *= m32int */
+//..                DIP("fimull %s\n", dis_buf);
+//..                fop = Iop_MulF64;
+//..                goto do_fop_m32;
+//.. 
+//..             case 4: /* FISUB m32int */ /* ST(0) -= m32int */
+//..                DIP("fisubl %s\n", dis_buf);
+//..                fop = Iop_SubF64;
+//..                goto do_fop_m32;
+//.. 
+//..             case 5: /* FISUBR m32int */ /* ST(0) = m32int - ST(0) */
+//..                DIP("fisubrl %s\n", dis_buf);
+//..                fop = Iop_SubF64;
+//..                goto do_foprev_m32;
+//.. 
+//..             case 6: /* FIDIV m32int */ /* ST(0) /= m32int */
+//..                DIP("fisubl %s\n", dis_buf);
+//..                fop = Iop_DivF64;
+//..                goto do_fop_m32;
+//.. 
+//..             case 7: /* FIDIVR m32int */ /* ST(0) = m32int / ST(0) */
+//..                DIP("fidivrl %s\n", dis_buf);
+//..                fop = Iop_DivF64;
+//..                goto do_foprev_m32;
+//.. 
+//..             do_fop_m32:
+//..                put_ST_UNCHECKED(0, 
+//..                   binop(fop, 
+//..                         get_ST(0),
+//..                         unop(Iop_I32toF64,
+//..                              loadLE(Ity_I32, mkexpr(addr)))));
+//..                break;
+//.. 
+//..             do_foprev_m32:
+//..                put_ST_UNCHECKED(0, 
+//..                   binop(fop, 
+//..                         unop(Iop_I32toF64,
+//..                              loadLE(Ity_I32, mkexpr(addr))),
+//..                         get_ST(0)));
+//..                break;
+//.. 
+//..             default:
+//..                vex_printf("unhandled opc_aux = 0x%2x\n", gregOfRM(modrm));
+//..                vex_printf("first_opcode == 0xDA\n");
+//..                goto decode_fail;
+//..          }
+//.. 
+//..       } else {
+//.. 
+//..          delta++;
+//..          switch (modrm) {
+//.. 
+//..             case 0xC0 ... 0xC7: /* FCMOVB ST(i), ST(0) */
+//..                r_src = (UInt)modrm - 0xC0;
+//..                DIP("fcmovb %%st(%d), %%st(0)\n", r_src);
+//..                put_ST_UNCHECKED(0, 
+//..                                 IRExpr_Mux0X( 
+//..                                     unop(Iop_1Uto8,
+//..                                          mk_x86g_calculate_condition(X86CondB)), 
+//..                                     get_ST(0), get_ST(r_src)) );
+//..                break;
+//.. 
+//..             case 0xC8 ... 0xCF: /* FCMOVE(Z) ST(i), ST(0) */
+//..                r_src = (UInt)modrm - 0xC8;
+//..                DIP("fcmovz %%st(%d), %%st(0)\n", r_src);
+//..                put_ST_UNCHECKED(0, 
+//..                                 IRExpr_Mux0X( 
+//..                                     unop(Iop_1Uto8,
+//..                                          mk_x86g_calculate_condition(X86CondZ)), 
+//..                                     get_ST(0), get_ST(r_src)) );
+//..                break;
+//.. 
+//..             case 0xD0 ... 0xD7: /* FCMOVBE ST(i), ST(0) */
+//..                r_src = (UInt)modrm - 0xD0;
+//..                DIP("fcmovbe %%st(%d), %%st(0)\n", r_src);
+//..                put_ST_UNCHECKED(0, 
+//..                                 IRExpr_Mux0X( 
+//..                                     unop(Iop_1Uto8,
+//..                                          mk_x86g_calculate_condition(X86CondBE)), 
+//..                                     get_ST(0), get_ST(r_src)) );
+//..                break;
+//.. 
+//..             case 0xE9: /* FUCOMPP %st(0),%st(1) */
+//..                DIP("fucompp %%st(0),%%st(1)\n");
+//..                /* This forces C1 to zero, which isn't right. */
+//..                put_C3210( 
+//..                    binop( Iop_And32,
+//..                           binop(Iop_Shl32, 
+//..                                 binop(Iop_CmpF64, get_ST(0), get_ST(1)),
+//..                                 mkU8(8)),
+//..                           mkU32(0x4500)
+//..                    ));
+//..                fp_pop();
+//..                fp_pop();
+//..                break;
+//.. 
+//..             default:
+//..                goto decode_fail;
+//..          }
+//.. 
+//..       }
+//..    }
+//.. 
+//..    /* -+-+-+-+-+-+-+-+-+-+-+-+ 0xDB opcodes +-+-+-+-+-+-+-+ */
+//..    else
+//..    if (first_opcode == 0xDB) {
+//..       if (modrm < 0xC0) {
+//.. 
+//..          /* bits 5,4,3 are an opcode extension, and the modRM also
+//..             specifies an address. */
+//..          IRTemp addr = disAMode( &len, sorb, delta, dis_buf );
+//..          delta += len;
+//.. 
+//..          switch (gregOfRM(modrm)) {
+//.. 
+//..             case 0: /* FILD m32int */
+//..                DIP("fildl %s\n", dis_buf);
+//..                fp_push();
+//..                put_ST(0, unop(Iop_I32toF64,
+//..                               loadLE(Ity_I32, mkexpr(addr))));
+//..                break;
+//.. 
+//..             case 2: /* FIST m32 */
+//..                DIP("fistl %s\n", dis_buf);
+//..                storeLE( mkexpr(addr), 
+//..                         binop(Iop_F64toI32, get_roundingmode(), get_ST(0)) );
+//..                break;
+//.. 
+//..             case 3: /* FISTP m32 */
+//..                DIP("fistpl %s\n", dis_buf);
+//..                storeLE( mkexpr(addr), 
+//..                         binop(Iop_F64toI32, get_roundingmode(), get_ST(0)) );
+//..                fp_pop();
+//..                break;
+//.. 
+//..             case 5: { /* FLD extended-real */
+//..                /* Uses dirty helper: 
+//..                      ULong loadF80le ( VexGuestX86State*, UInt )
+//..                   addr holds the address.  First, do a dirty call to
+//..                   get hold of the data. */
+//..                IRTemp   val  = newTemp(Ity_I64);
+//..                IRExpr** args = mkIRExprVec_1 ( mkexpr(addr) );
+//.. 
+//..                IRDirty* d = unsafeIRDirty_1_N ( 
+//..                                val, 
+//..                                0/*regparms*/, 
+//..                                "x86g_loadF80le", &x86g_loadF80le, 
+//..                                args 
+//..                             );
+//..                /* declare that we're reading memory */
+//..                d->mFx   = Ifx_Read;
+//..                d->mAddr = mkexpr(addr);
+//..                d->mSize = 10;
+//.. 
+//..                /* execute the dirty call, dumping the result in val. */
+//..                stmt( IRStmt_Dirty(d) );
+//..                fp_push();
+//..                put_ST(0, unop(Iop_ReinterpI64asF64, mkexpr(val)));
+//.. 
+//..                DIP("fldt %s\n", dis_buf);
+//..                break;
+//..             }
+//.. 
+//..             case 7: { /* FSTP extended-real */
+//..                /* Uses dirty helper: void x86g_storeF80le ( UInt, ULong ) */
+//..                IRExpr** args 
+//..                   = mkIRExprVec_2( mkexpr(addr), 
+//..                                    unop(Iop_ReinterpF64asI64, get_ST(0)) );
+//.. 
+//..                IRDirty* d = unsafeIRDirty_0_N ( 
+//..                                0/*regparms*/, 
+//..                                "x86g_storeF80le", &x86g_storeF80le,
+//..                                args 
+//..                             );
+//..                /* declare we're writing memory */
+//..                d->mFx   = Ifx_Write;
+//..                d->mAddr = mkexpr(addr);
+//..                d->mSize = 10;
+//.. 
+//..                /* execute the dirty call. */
+//..                stmt( IRStmt_Dirty(d) );
+//..                fp_pop();
+//.. 
+//..                DIP("fstpt\n %s", dis_buf);
+//..                break;
+//..             }
+//.. 
+//..             default:
+//..                vex_printf("unhandled opc_aux = 0x%2x\n", gregOfRM(modrm));
+//..                vex_printf("first_opcode == 0xDB\n");
+//..                goto decode_fail;
+//..          }
+//.. 
+//..       } else {
+//.. 
+//..          delta++;
+//..          switch (modrm) {
+//.. 
+//..             case 0xC0 ... 0xC7: /* FCMOVNB ST(i), ST(0) */
+//..                r_src = (UInt)modrm - 0xC0;
+//..                DIP("fcmovnb %%st(%d), %%st(0)\n", r_src);
+//..                put_ST_UNCHECKED(0, 
+//..                                 IRExpr_Mux0X( 
+//..                                     unop(Iop_1Uto8,
+//..                                          mk_x86g_calculate_condition(X86CondNB)), 
+//..                                     get_ST(0), get_ST(r_src)) );
+//..                break;
+//.. 
+//..             case 0xC8 ... 0xCF: /* FCMOVNE(NZ) ST(i), ST(0) */
+//..                r_src = (UInt)modrm - 0xC8;
+//..                DIP("fcmovnz %%st(%d), %%st(0)\n", r_src);
+//..                put_ST_UNCHECKED(0, 
+//..                                 IRExpr_Mux0X( 
+//..                                     unop(Iop_1Uto8,
+//..                                          mk_x86g_calculate_condition(X86CondNZ)), 
+//..                                     get_ST(0), get_ST(r_src)) );
+//..                break;
+//.. 
+//..             case 0xD0 ... 0xD7: /* FCMOVNBE ST(i), ST(0) */
+//..                r_src = (UInt)modrm - 0xD0;
+//..                DIP("fcmovnbe %%st(%d), %%st(0)\n", r_src);
+//..                put_ST_UNCHECKED(0, 
+//..                                 IRExpr_Mux0X( 
+//..                                     unop(Iop_1Uto8,
+//..                                          mk_x86g_calculate_condition(X86CondNBE)), 
+//..                                     get_ST(0), get_ST(r_src)) );
+//..                break;
+//.. 
+//..             case 0xE2:
+//..                DIP("fnclex\n");
+//..                break;
+//.. 
+//..             case 0xE3: {
+//..                /* Uses dirty helper: 
+//..                      void x86g_do_FINIT ( VexGuestX86State* ) */
+//..                IRDirty* d  = unsafeIRDirty_0_N ( 
+//..                                 0/*regparms*/, 
+//..                                 "x86g_dirtyhelper_FINIT", 
+//..                                 &x86g_dirtyhelper_FINIT,
+//..                                 mkIRExprVec_0()
+//..                              );
+//..                d->needsBBP = True;
+//.. 
+//..                /* declare we're writing guest state */
+//..                d->nFxState = 5;
+//.. 
+//..                d->fxState[0].fx     = Ifx_Write;
+//..                d->fxState[0].offset = OFFB_FTOP;
+//..                d->fxState[0].size   = sizeof(UInt);
+//.. 
+//..                d->fxState[1].fx     = Ifx_Write;
+//..                d->fxState[1].offset = OFFB_FPREGS;
+//..                d->fxState[1].size   = 8 * sizeof(ULong);
+//.. 
+//..                d->fxState[2].fx     = Ifx_Write;
+//..                d->fxState[2].offset = OFFB_FPTAGS;
+//..                d->fxState[2].size   = 8 * sizeof(UChar);
+//.. 
+//..                d->fxState[3].fx     = Ifx_Write;
+//..                d->fxState[3].offset = OFFB_FPROUND;
+//..                d->fxState[3].size   = sizeof(UInt);
+//.. 
+//..                d->fxState[4].fx     = Ifx_Write;
+//..                d->fxState[4].offset = OFFB_FC3210;
+//..                d->fxState[4].size   = sizeof(UInt);
+//.. 
+//..                stmt( IRStmt_Dirty(d) );
+//.. 
+//..                DIP("fninit\n");
+//..                break;
+//..             }
+//.. 
+//..             case 0xE8 ... 0xEF: /* FUCOMI %st(0),%st(?) */
+//..                fp_do_ucomi_ST0_STi( (UInt)modrm - 0xE8, False );
+//..                break;
+//.. 
+//..             case 0xF0 ... 0xF7: /* FCOMI %st(0),%st(?) */
+//..                fp_do_ucomi_ST0_STi( (UInt)modrm - 0xF0, False );
+//..                break;
+//.. 
+//..             default:
+//..                goto decode_fail;
+//..          }
+//..       }
+//..    }
+//.. 
+//..    /* -+-+-+-+-+-+-+-+-+-+-+-+ 0xDC opcodes +-+-+-+-+-+-+-+ */
+//..    else
+//..    if (first_opcode == 0xDC) {
+//..       if (modrm < 0xC0) {
+//.. 
+//..          /* bits 5,4,3 are an opcode extension, and the modRM also
+//..             specifies an address. */
+//..          IRTemp addr = disAMode( &len, sorb, delta, dis_buf );
+//..          delta += len;
+//.. 
+//..          switch (gregOfRM(modrm)) {
+//.. 
+//..             case 0: /* FADD double-real */
+//..                fp_do_op_mem_ST_0 ( addr, "add", dis_buf, Iop_AddF64, True );
+//..                break;
+//.. 
+//..             case 1: /* FMUL double-real */
+//..                fp_do_op_mem_ST_0 ( addr, "mul", dis_buf, Iop_MulF64, True );
+//..                break;
+//.. 
+//..             case 2: /* FCOM double-real */
+//..                DIP("fcoml %s\n", dis_buf);
+//..                /* This forces C1 to zero, which isn't right. */
+//..                put_C3210( 
+//..                    binop( Iop_And32,
+//..                           binop(Iop_Shl32, 
+//..                                 binop(Iop_CmpF64, 
+//..                                       get_ST(0),
+//..                                       loadLE(Ity_F64,mkexpr(addr))),
+//..                                 mkU8(8)),
+//..                           mkU32(0x4500)
+//..                    ));
+//..                break;  
+//.. 
+//..             case 3: /* FCOMP double-real */
+//..                DIP("fcompl %s\n", dis_buf);
+//..                /* This forces C1 to zero, which isn't right. */
+//..                put_C3210( 
+//..                    binop( Iop_And32,
+//..                           binop(Iop_Shl32, 
+//..                                 binop(Iop_CmpF64, 
+//..                                       get_ST(0),
+//..                                       loadLE(Ity_F64,mkexpr(addr))),
+//..                                 mkU8(8)),
+//..                           mkU32(0x4500)
+//..                    ));
+//..                fp_pop();
+//..                break;  
+//.. 
+//..             case 4: /* FSUB double-real */
+//..                fp_do_op_mem_ST_0 ( addr, "sub", dis_buf, Iop_SubF64, True );
+//..                break;
+//.. 
+//..             case 5: /* FSUBR double-real */
+//..                fp_do_oprev_mem_ST_0 ( addr, "subr", dis_buf, Iop_SubF64, True );
+//..                break;
+//.. 
+//..             case 6: /* FDIV double-real */
+//..                fp_do_op_mem_ST_0 ( addr, "div", dis_buf, Iop_DivF64, True );
+//..                break;
+//.. 
+//..             case 7: /* FDIVR double-real */
+//..                fp_do_oprev_mem_ST_0 ( addr, "divr", dis_buf, Iop_DivF64, True );
+//..                break;
+//.. 
+//..             default:
+//..                vex_printf("unhandled opc_aux = 0x%2x\n", gregOfRM(modrm));
+//..                vex_printf("first_opcode == 0xDC\n");
+//..                goto decode_fail;
+//..          }
+//.. 
+//..       } else {
+//.. 
+//..          delta++;
+//..          switch (modrm) {
+//.. 
+//..             case 0xC0 ... 0xC7: /* FADD %st(0),%st(?) */
+//..                fp_do_op_ST_ST ( "add", Iop_AddF64, 0, modrm - 0xC0, False );
+//..                break;
+//.. 
+//..             case 0xC8 ... 0xCF: /* FMUL %st(0),%st(?) */
+//..                fp_do_op_ST_ST ( "mul", Iop_MulF64, 0, modrm - 0xC8, False );
+//..                break;
+//.. 
+//..             case 0xE0 ... 0xE7: /* FSUBR %st(0),%st(?) */
+//..                fp_do_oprev_ST_ST ( "subr", Iop_SubF64, 0, modrm - 0xE0, False );
+//..                break;
+//.. 
+//..             case 0xE8 ... 0xEF: /* FSUB %st(0),%st(?) */
+//..                fp_do_op_ST_ST ( "sub", Iop_SubF64, 0, modrm - 0xE8, False );
+//..                break;
+//.. 
+//..             case 0xF0 ... 0xF7: /* FDIVR %st(0),%st(?) */
+//..                fp_do_oprev_ST_ST ( "divr", Iop_DivF64, 0, modrm - 0xF0, False );
+//..                break;
+//.. 
+//..             case 0xF8 ... 0xFF: /* FDIV %st(0),%st(?) */
+//..                fp_do_op_ST_ST ( "div", Iop_DivF64, 0, modrm - 0xF8, False );
+//..                break;
+//.. 
+//..             default:
+//..                goto decode_fail;
+//..          }
+//.. 
+//..       }
+//..    }
+//.. 
+//..    /* -+-+-+-+-+-+-+-+-+-+-+-+ 0xDD opcodes +-+-+-+-+-+-+-+ */
+//..    else
+//..    if (first_opcode == 0xDD) {
+//.. 
+//..       if (modrm < 0xC0) {
+//.. 
+//..          /* bits 5,4,3 are an opcode extension, and the modRM also
+//..             specifies an address. */
+//..          IRTemp addr = disAMode( &len, sorb, delta, dis_buf );
+//..          delta += len;
+//.. 
+//..          switch (gregOfRM(modrm)) {
+//.. 
+//..             case 0: /* FLD double-real */
+//..                DIP("fldl %s\n", dis_buf);
+//..                fp_push();
+//..                put_ST(0, IRExpr_LDle(Ity_F64, mkexpr(addr)));
+//..                break;
+//.. 
+//..             case 2: /* FST double-real */
+//..                DIP("fstl %s\n", dis_buf);
+//..                storeLE(mkexpr(addr), get_ST(0));
+//..                break;
+//.. 
+//..             case 3: /* FSTP double-real */
+//..                DIP("fstpl %s\n", dis_buf);
+//..                storeLE(mkexpr(addr), get_ST(0));
+//..                fp_pop();
+//..                break;
+//.. 
+//..             case 4: { /* FRSTOR m108 */
+//..                /* Uses dirty helper: 
+//..                      VexEmWarn x86g_do_FRSTOR ( VexGuestX86State*, Addr32 ) */
+//..                IRTemp   ew = newTemp(Ity_I32);
+//..                IRDirty* d  = unsafeIRDirty_0_N ( 
+//..                                 0/*regparms*/, 
+//..                                 "x86g_dirtyhelper_FRSTOR", 
+//..                                 &x86g_dirtyhelper_FRSTOR,
+//..                                 mkIRExprVec_1( mkexpr(addr) )
+//..                              );
+//..                d->needsBBP = True;
+//..                d->tmp      = ew;
+//..                /* declare we're reading memory */
+//..                d->mFx   = Ifx_Read;
+//..                d->mAddr = mkexpr(addr);
+//..                d->mSize = 108;
+//.. 
+//..                /* declare we're writing guest state */
+//..                d->nFxState = 5;
+//.. 
+//..                d->fxState[0].fx     = Ifx_Write;
+//..                d->fxState[0].offset = OFFB_FTOP;
+//..                d->fxState[0].size   = sizeof(UInt);
+//.. 
+//..                d->fxState[1].fx     = Ifx_Write;
+//..                d->fxState[1].offset = OFFB_FPREGS;
+//..                d->fxState[1].size   = 8 * sizeof(ULong);
+//.. 
+//..                d->fxState[2].fx     = Ifx_Write;
+//..                d->fxState[2].offset = OFFB_FPTAGS;
+//..                d->fxState[2].size   = 8 * sizeof(UChar);
+//.. 
+//..                d->fxState[3].fx     = Ifx_Write;
+//..                d->fxState[3].offset = OFFB_FPROUND;
+//..                d->fxState[3].size   = sizeof(UInt);
+//.. 
+//..                d->fxState[4].fx     = Ifx_Write;
+//..                d->fxState[4].offset = OFFB_FC3210;
+//..                d->fxState[4].size   = sizeof(UInt);
+//.. 
+//..                stmt( IRStmt_Dirty(d) );
+//.. 
+//..                /* ew contains any emulation warning we may need to
+//..                   issue.  If needed, side-exit to the next insn,
+//..                   reporting the warning, so that Valgrind's dispatcher
+//..                   sees the warning. */
+//..                put_emwarn( mkexpr(ew) );
+//..                stmt( 
+//..                   IRStmt_Exit(
+//..                      binop(Iop_CmpNE32, mkexpr(ew), mkU32(0)),
+//..                      Ijk_EmWarn,
+//..                      IRConst_U32( ((Addr32)guest_eip_bbstart)+delta)
+//..                   )
+//..                );
+//.. 
+//..                DIP("frstor %s\n", dis_buf);
+//..                break;
+//..             }
+//.. 
+//..             case 6: { /* FNSAVE m108 */
+//..                /* Uses dirty helper: 
+//..                      void x86g_do_FSAVE ( VexGuestX86State*, UInt ) */
+//..                IRDirty* d = unsafeIRDirty_0_N ( 
+//..                                0/*regparms*/, 
+//..                                "x86g_dirtyhelper_FSAVE", 
+//..                                &x86g_dirtyhelper_FSAVE,
+//..                                mkIRExprVec_1( mkexpr(addr) )
+//..                             );
+//..                d->needsBBP = True;
+//..                /* declare we're writing memory */
+//..                d->mFx   = Ifx_Write;
+//..                d->mAddr = mkexpr(addr);
+//..                d->mSize = 108;
+//.. 
+//..                /* declare we're reading guest state */
+//..                d->nFxState = 5;
+//.. 
+//..                d->fxState[0].fx     = Ifx_Read;
+//..                d->fxState[0].offset = OFFB_FTOP;
+//..                d->fxState[0].size   = sizeof(UInt);
+//.. 
+//..                d->fxState[1].fx     = Ifx_Read;
+//..                d->fxState[1].offset = OFFB_FPREGS;
+//..                d->fxState[1].size   = 8 * sizeof(ULong);
+//.. 
+//..                d->fxState[2].fx     = Ifx_Read;
+//..                d->fxState[2].offset = OFFB_FPTAGS;
+//..                d->fxState[2].size   = 8 * sizeof(UChar);
+//.. 
+//..                d->fxState[3].fx     = Ifx_Read;
+//..                d->fxState[3].offset = OFFB_FPROUND;
+//..                d->fxState[3].size   = sizeof(UInt);
+//.. 
+//..                d->fxState[4].fx     = Ifx_Read;
+//..                d->fxState[4].offset = OFFB_FC3210;
+//..                d->fxState[4].size   = sizeof(UInt);
+//.. 
+//..                stmt( IRStmt_Dirty(d) );
+//.. 
+//..                DIP("fnsave %s\n", dis_buf);
+//..                break;
+//..             }
+//.. 
+//..             default:
+//..                vex_printf("unhandled opc_aux = 0x%2x\n", gregOfRM(modrm));
+//..                vex_printf("first_opcode == 0xDD\n");
+//..                goto decode_fail;
+//..          }
+//..       } else {
+//..          delta++;
+//..          switch (modrm) {
+//.. 
+//..             case 0xD0 ... 0xD7: /* FST %st(0),%st(?) */
+//..                r_dst = (UInt)modrm - 0xD0;
+//..                DIP("fst %%st(0),%%st(%d)\n", r_dst);
+//..                /* P4 manual says: "If the destination operand is a
+//..                   non-empty register, the invalid-operation exception
+//..                   is not generated.  Hence put_ST_UNCHECKED. */
+//..                put_ST_UNCHECKED(r_dst, get_ST(0));
+//..                break;
+//.. 
+//..             case 0xD8 ... 0xDF: /* FSTP %st(0),%st(?) */
+//..                r_dst = (UInt)modrm - 0xD8;
+//..                DIP("fstp %%st(0),%%st(%d)\n", r_dst);
+//..                /* P4 manual says: "If the destination operand is a
+//..                   non-empty register, the invalid-operation exception
+//..                   is not generated.  Hence put_ST_UNCHECKED. */
+//..                put_ST_UNCHECKED(r_dst, get_ST(0));
+//..                fp_pop();
+//..                break;
+//.. 
+//..             case 0xE0 ... 0xE7: /* FUCOM %st(0),%st(?) */
+//..                r_dst = (UInt)modrm - 0xE0;
+//..                DIP("fucom %%st(0),%%st(%d)\n", r_dst);
+//..                /* This forces C1 to zero, which isn't right. */
+//..                put_C3210( 
+//..                    binop( Iop_And32,
+//..                           binop(Iop_Shl32, 
+//..                                 binop(Iop_CmpF64, get_ST(0), get_ST(r_dst)),
+//..                                 mkU8(8)),
+//..                           mkU32(0x4500)
+//..                    ));
+//..                break;
+//.. 
+//..             case 0xE8 ... 0xEF: /* FUCOMP %st(0),%st(?) */
+//..                r_dst = (UInt)modrm - 0xE8;
+//..                DIP("fucomp %%st(0),%%st(%d)\n", r_dst);
+//..                /* This forces C1 to zero, which isn't right. */
+//..                put_C3210( 
+//..                    binop( Iop_And32,
+//..                           binop(Iop_Shl32, 
+//..                                 binop(Iop_CmpF64, get_ST(0), get_ST(r_dst)),
+//..                                 mkU8(8)),
+//..                           mkU32(0x4500)
+//..                    ));
+//..                fp_pop();
+//..                break;
+//.. 
+//..             default:
+//..                goto decode_fail;
+//..          }
+//..       }
+//..    }
+//.. 
+//..    /* -+-+-+-+-+-+-+-+-+-+-+-+ 0xDE opcodes +-+-+-+-+-+-+-+ */
+//..    else
+//..    if (first_opcode == 0xDE) {
+//.. 
+//..       if (modrm < 0xC0) {
+//.. 
+//..          /* bits 5,4,3 are an opcode extension, and the modRM also
+//..             specifies an address. */
+//..          IROp   fop;
+//..          IRTemp addr = disAMode( &len, sorb, delta, dis_buf );
+//..          delta += len;
+//.. 
+//..          switch (gregOfRM(modrm)) {
+//.. 
+//..             case 0: /* FIADD m16int */ /* ST(0) += m16int */
+//..                DIP("fiaddw %s\n", dis_buf);
+//..                fop = Iop_AddF64;
+//..                goto do_fop_m16;
+//.. 
+//..             case 1: /* FIMUL m16int */ /* ST(0) *= m16int */
+//..                DIP("fimulw %s\n", dis_buf);
+//..                fop = Iop_MulF64;
+//..                goto do_fop_m16;
+//.. 
+//..             case 4: /* FISUB m16int */ /* ST(0) -= m16int */
+//..                DIP("fisubw %s\n", dis_buf);
+//..                fop = Iop_SubF64;
+//..                goto do_fop_m16;
+//.. 
+//..             case 5: /* FISUBR m16int */ /* ST(0) = m16int - ST(0) */
+//..                DIP("fisubrw %s\n", dis_buf);
+//..                fop = Iop_SubF64;
+//..                goto do_foprev_m16;
+//.. 
+//..             case 6: /* FIDIV m16int */ /* ST(0) /= m16int */
+//..                DIP("fisubw %s\n", dis_buf);
+//..                fop = Iop_DivF64;
+//..                goto do_fop_m16;
+//.. 
+//..             case 7: /* FIDIVR m16int */ /* ST(0) = m16int / ST(0) */
+//..                DIP("fidivrw %s\n", dis_buf);
+//..                fop = Iop_DivF64;
+//..                goto do_foprev_m16;
+//.. 
+//..             do_fop_m16:
+//..                put_ST_UNCHECKED(0, 
+//..                   binop(fop, 
+//..                         get_ST(0),
+//..                         unop(Iop_I32toF64,
+//..                              unop(Iop_16Sto32, 
+//..                                   loadLE(Ity_I16, mkexpr(addr))))));
+//..                break;
+//.. 
+//..             do_foprev_m16:
+//..                put_ST_UNCHECKED(0, 
+//..                   binop(fop, 
+//..                         unop(Iop_I32toF64,
+//..                              unop(Iop_16Sto32, 
+//..                                   loadLE(Ity_I16, mkexpr(addr)))),
+//..                         get_ST(0)));
+//..                break;
+//.. 
+//..             default:
+//..                vex_printf("unhandled opc_aux = 0x%2x\n", gregOfRM(modrm));
+//..                vex_printf("first_opcode == 0xDE\n");
+//..                goto decode_fail;
+//..          }
+//.. 
+//..       } else {
+//.. 
+//..          delta++;
+//..          switch (modrm) {
+//.. 
+//..             case 0xC0 ... 0xC7: /* FADDP %st(0),%st(?) */
+//..                fp_do_op_ST_ST ( "add", Iop_AddF64, 0, modrm - 0xC0, True );
+//..                break;
+//.. 
+//..             case 0xC8 ... 0xCF: /* FMULP %st(0),%st(?) */
+//..                fp_do_op_ST_ST ( "mul", Iop_MulF64, 0, modrm - 0xC8, True );
+//..                break;
+//.. 
+//..             case 0xD9: /* FCOMPP %st(0),%st(1) */
+//..                DIP("fuompp %%st(0),%%st(1)\n");
+//..                /* This forces C1 to zero, which isn't right. */
+//..                put_C3210( 
+//..                    binop( Iop_And32,
+//..                           binop(Iop_Shl32, 
+//..                                 binop(Iop_CmpF64, get_ST(0), get_ST(1)),
+//..                                 mkU8(8)),
+//..                           mkU32(0x4500)
+//..                    ));
+//..                fp_pop();
+//..                fp_pop();
+//..                break;
+//.. 
+//..             case 0xE0 ... 0xE7: /* FSUBRP %st(0),%st(?) */
+//..                fp_do_oprev_ST_ST ( "subr", Iop_SubF64, 0,  modrm - 0xE0, True );
+//..                break;
+//.. 
+//..             case 0xE8 ... 0xEF: /* FSUBP %st(0),%st(?) */
+//..                fp_do_op_ST_ST ( "sub", Iop_SubF64, 0,  modrm - 0xE8, True );
+//..                break;
+//.. 
+//..             case 0xF0 ... 0xF7: /* FDIVRP %st(0),%st(?) */
+//..                fp_do_oprev_ST_ST ( "divr", Iop_DivF64, 0, modrm - 0xF0, True );
+//..                break;
+//.. 
+//..             case 0xF8 ... 0xFF: /* FDIVP %st(0),%st(?) */
+//..                fp_do_op_ST_ST ( "div", Iop_DivF64, 0, modrm - 0xF8, True );
+//..                break;
+//.. 
+//..             default: 
+//..                goto decode_fail;
+//..          }
+//.. 
+//..       }
+//..    }
+//.. 
+//..    /* -+-+-+-+-+-+-+-+-+-+-+-+ 0xDF opcodes +-+-+-+-+-+-+-+ */
+//..    else
+//..    if (first_opcode == 0xDF) {
+//.. 
+//..       if (modrm < 0xC0) {
+//.. 
+//..          /* bits 5,4,3 are an opcode extension, and the modRM also
+//..             specifies an address. */
+//..          IRTemp addr = disAMode( &len, sorb, delta, dis_buf );
+//..          delta += len;
+//.. 
+//..          switch (gregOfRM(modrm)) {
+//.. 
+//..             case 0: /* FILD m16int */
+//..                DIP("fildw %s\n", dis_buf);
+//..                fp_push();
+//..                put_ST(0, unop(Iop_I32toF64,
+//..                               unop(Iop_16Sto32,
+//..                                    loadLE(Ity_I16, mkexpr(addr)))));
+//..                break;
+//.. 
+//..             case 2: /* FIST m16 */
+//..                DIP("fistp %s\n", dis_buf);
+//..                storeLE( mkexpr(addr), 
+//..                         binop(Iop_F64toI16, get_roundingmode(), get_ST(0)) );
+//..                break;
+//.. 
+//..             case 3: /* FISTP m16 */
+//..                DIP("fistps %s\n", dis_buf);
+//..                storeLE( mkexpr(addr), 
+//..                         binop(Iop_F64toI16, get_roundingmode(), get_ST(0)) );
+//..                fp_pop();
+//..                break;
+//.. 
+//..             case 5: /* FILD m64 */
+//..                DIP("fildll %s\n", dis_buf);
+//..                fp_push();
+//..                put_ST(0, binop(Iop_I64toF64,
+//..                                get_roundingmode(),
+//..                                loadLE(Ity_I64, mkexpr(addr))));
+//..                break;
+//.. 
+//..             case 7: /* FISTP m64 */
+//..                DIP("fistpll %s\n", dis_buf);
+//..                storeLE( mkexpr(addr), 
+//..                         binop(Iop_F64toI64, get_roundingmode(), get_ST(0)) );
+//..                fp_pop();
+//..                break;
+//.. 
+//..             default:
+//..                vex_printf("unhandled opc_aux = 0x%2x\n", gregOfRM(modrm));
+//..                vex_printf("first_opcode == 0xDF\n");
+//..                goto decode_fail;
+//..          }
+//.. 
+//..       } else {
+//.. 
+//..          delta++;
+//..          switch (modrm) {
+//.. 
+//..             case 0xE0: /* FNSTSW %ax */
+//..                DIP("fnstsw %%ax\n");
+//..                /* Invent a plausible-looking FPU status word value and
+//..                   dump it in %AX:
+//..                      ((ftop & 7) << 11) | (c3210 & 0x4700)
+//..                */
+//..                putIReg(2, R_EAX,
+//..                   unop(Iop_32to16,
+//..                        binop(Iop_Or32,
+//..                              binop(Iop_Shl32, 
+//..                                    binop(Iop_And32, get_ftop(), mkU32(7)), 
+//..                                    mkU8(11)),
+//..                              binop(Iop_And32, get_C3210(), mkU32(0x4700))
+//..                )));
+//..                break;
+//.. 
+//..             case 0xE8 ... 0xEF: /* FUCOMIP %st(0),%st(?) */
+//..                fp_do_ucomi_ST0_STi( (UInt)modrm - 0xE8, True );
+//..                break;
+//.. 
+//..             case 0xF0 ... 0xF7: /* FCOMIP %st(0),%st(?) */
+//..                /* not really right since COMIP != UCOMIP */
+//..                fp_do_ucomi_ST0_STi( (UInt)modrm - 0xF0, True );
+//..                break;
+//.. 
+//..             default: 
+//..                goto decode_fail;
+//..          }
+//..       }
+//.. 
+//..    }
+//.. 
+//..    else
+//..    vpanic("dis_FPU(x86): invalid primary opcode");
+//.. 
+//..    *decode_ok = True;
+//..    return delta;
+//.. 
+//..   decode_fail:
+//..    *decode_ok = False;
+//..    return delta;
+//.. }
+//.. 
+//.. 
+//.. /*------------------------------------------------------------*/
+//.. /*---                                                      ---*/
+//.. /*--- MMX INSTRUCTIONS                                     ---*/
+//.. /*---                                                      ---*/
+//.. /*------------------------------------------------------------*/
+//.. 
+//.. /* Effect of MMX insns on x87 FPU state (table 11-2 of 
+//..    IA32 arch manual, volume 3):
+//.. 
+//..    Read from, or write to MMX register (viz, any insn except EMMS):
+//..    * All tags set to Valid (non-empty) -- FPTAGS[i] := nonzero
+//..    * FP stack pointer set to zero
+//.. 
+//..    EMMS:
+//..    * All tags set to Invalid (empty) -- FPTAGS[i] := zero
+//..    * FP stack pointer set to zero
+//.. */
+//.. 
+//.. static void do_MMX_preamble ( void )
+//.. {
+//..    Int      i;
+//..    IRArray* descr = mkIRArray( OFFB_FPTAGS, Ity_I8, 8 );
+//..    IRExpr*  zero  = mkU32(0);
+//..    IRExpr*  tag1  = mkU8(1);
+//..    put_ftop(zero);
+//..    for (i = 0; i < 8; i++)
+//..       stmt( IRStmt_PutI( descr, zero, i, tag1 ) );
+//.. }
+//.. 
+//.. static void do_EMMS_preamble ( void )
+//.. {
+//..    Int      i;
+//..    IRArray* descr = mkIRArray( OFFB_FPTAGS, Ity_I8, 8 );
+//..    IRExpr*  zero  = mkU32(0);
+//..    IRExpr*  tag0  = mkU8(0);
+//..    put_ftop(zero);
+//..    for (i = 0; i < 8; i++)
+//..       stmt( IRStmt_PutI( descr, zero, i, tag0 ) );
+//.. }
+//.. 
+//.. 
+//.. static IRExpr* getMMXReg ( UInt archreg )
+//.. {
+//..    vassert(archreg < 8);
+//..    return IRExpr_Get( OFFB_FPREGS + 8 * archreg, Ity_I64 );
+//.. }
+//.. 
+//.. 
+//.. static void putMMXReg ( UInt archreg, IRExpr* e )
+//.. {
+//..    vassert(archreg < 8);
+//..    vassert(typeOfIRExpr(irbb->tyenv,e) == Ity_I64);
+//..    stmt( IRStmt_Put( OFFB_FPREGS + 8 * archreg, e ) );
+//.. }
+//.. 
+//.. 
+//.. /* Helper for non-shift MMX insns.  Note this is incomplete in the
+//..    sense that it does not first call do_MMX_preamble() -- that is the
+//..    responsibility of its caller. */
+//.. 
+//.. static 
+//.. UInt dis_MMXop_regmem_to_reg ( UChar sorb,
+//..                                UInt  delta,
+//..                                UChar opc,
+//..                                Char* name,
+//..                                Bool  show_granularity )
+//.. {
+//..    HChar   dis_buf[50];
+//..    UChar   modrm = getIByte(delta);
+//..    Bool    isReg = epartIsReg(modrm);
+//..    IRExpr* argL  = NULL;
+//..    IRExpr* argR  = NULL;
+//..    IRExpr* argG  = NULL;
+//..    IRExpr* argE  = NULL;
+//..    IRTemp  res   = newTemp(Ity_I64);
+//.. 
+//..    Bool    invG  = False;
+//..    IROp    op    = Iop_INVALID;
+//..    void*   hAddr = NULL;
+//..    Char*   hName = NULL;
+//..    Bool    eLeft = False;
+//.. 
+//.. #  define XXX(_name) do { hAddr = &_name; hName = #_name; } while (0)
+//.. 
+//..    switch (opc) {
+//..       /* Original MMX ones */
+//..       case 0xFC: op = Iop_Add8x8; break;
+//..       case 0xFD: op = Iop_Add16x4; break;
+//..       case 0xFE: op = Iop_Add32x2; break;
+//.. 
+//..       case 0xEC: op = Iop_QAdd8Sx8; break;
+//..       case 0xED: op = Iop_QAdd16Sx4; break;
+//.. 
+//..       case 0xDC: op = Iop_QAdd8Ux8; break;
+//..       case 0xDD: op = Iop_QAdd16Ux4; break;
+//.. 
+//..       case 0xF8: op = Iop_Sub8x8;  break;
+//..       case 0xF9: op = Iop_Sub16x4; break;
+//..       case 0xFA: op = Iop_Sub32x2; break;
+//.. 
+//..       case 0xE8: op = Iop_QSub8Sx8; break;
+//..       case 0xE9: op = Iop_QSub16Sx4; break;
+//.. 
+//..       case 0xD8: op = Iop_QSub8Ux8; break;
+//..       case 0xD9: op = Iop_QSub16Ux4; break;
+//.. 
+//..       case 0xE5: op = Iop_MulHi16Sx4; break;
+//..       case 0xD5: op = Iop_Mul16x4; break;
+//..       case 0xF5: XXX(x86g_calculate_mmx_pmaddwd); break;
+//.. 
+//..       case 0x74: op = Iop_CmpEQ8x8; break;
+//..       case 0x75: op = Iop_CmpEQ16x4; break;
+//..       case 0x76: op = Iop_CmpEQ32x2; break;
+//.. 
+//..       case 0x64: op = Iop_CmpGT8Sx8; break;
+//..       case 0x65: op = Iop_CmpGT16Sx4; break;
+//..       case 0x66: op = Iop_CmpGT32Sx2; break;
+//.. 
+//..       case 0x6B: op = Iop_QNarrow32Sx2; eLeft = True; break;
+//..       case 0x63: op = Iop_QNarrow16Sx4; eLeft = True; break;
+//..       case 0x67: op = Iop_QNarrow16Ux4; eLeft = True; break;
+//.. 
+//..       case 0x68: op = Iop_InterleaveHI8x8;  eLeft = True; break;
+//..       case 0x69: op = Iop_InterleaveHI16x4; eLeft = True; break;
+//..       case 0x6A: op = Iop_InterleaveHI32x2; eLeft = True; break;
+//.. 
+//..       case 0x60: op = Iop_InterleaveLO8x8;  eLeft = True; break;
+//..       case 0x61: op = Iop_InterleaveLO16x4; eLeft = True; break;
+//..       case 0x62: op = Iop_InterleaveLO32x2; eLeft = True; break;
+//.. 
+//..       case 0xDB: op = Iop_And64; break;
+//..       case 0xDF: op = Iop_And64; invG = True; break;
+//..       case 0xEB: op = Iop_Or64; break;
+//..       case 0xEF: /* Possibly do better here if argL and argR are the
+//..                     same reg */
+//..                  op = Iop_Xor64; break;
+//.. 
+//..       /* Introduced in SSE1 */
+//..       case 0xE0: op = Iop_Avg8Ux8;    break;
+//..       case 0xE3: op = Iop_Avg16Ux4;   break;
+//..       case 0xEE: op = Iop_Max16Sx4;   break;
+//..       case 0xDE: op = Iop_Max8Ux8;    break;
+//..       case 0xEA: op = Iop_Min16Sx4;   break;
+//..       case 0xDA: op = Iop_Min8Ux8;    break;
+//..       case 0xE4: op = Iop_MulHi16Ux4; break;
+//..       case 0xF6: XXX(x86g_calculate_mmx_psadbw); break;
+//.. 
+//..       /* Introduced in SSE2 */
+//..       case 0xD4: op = Iop_Add64; break;
+//..       case 0xFB: op = Iop_Sub64; break;
+//.. 
+//..       default: 
+//..          vex_printf("\n0x%x\n", (Int)opc);
+//..          vpanic("dis_MMXop_regmem_to_reg");
+//..    }
+//.. 
+//.. #  undef XXX
+//.. 
+//..    argG = getMMXReg(gregOfRM(modrm));
+//..    if (invG)
+//..       argG = unop(Iop_Not64, argG);
+//.. 
+//..    if (isReg) {
+//..       delta++;
+//..       argE = getMMXReg(eregOfRM(modrm));
+//..    } else {
+//..       Int    len;
+//..       IRTemp addr = disAMode( &len, sorb, delta, dis_buf );
+//..       delta += len;
+//..       argE = loadLE(Ity_I64, mkexpr(addr));
+//..    }
+//.. 
+//..    if (eLeft) {
+//..       argL = argE;
+//..       argR = argG;
+//..    } else {
+//..       argL = argG;
+//..       argR = argE;
+//..    }
+//.. 
+//..    if (op != Iop_INVALID) {
+//..       vassert(hName == NULL);
+//..       vassert(hAddr == NULL);
+//..       assign(res, binop(op, argL, argR));
+//..    } else {
+//..       vassert(hName != NULL);
+//..       vassert(hAddr != NULL);
+//..       assign( res, 
+//..               mkIRExprCCall(
+//..                  Ity_I64, 
+//..                  0/*regparms*/, hName, hAddr,
+//..                  mkIRExprVec_2( argL, argR )
+//..               ) 
+//..             );
+//..    }
+//.. 
+//..    putMMXReg( gregOfRM(modrm), mkexpr(res) );
+//.. 
+//..    DIP("%s%s %s, %s\n", 
+//..        name, show_granularity ? nameMMXGran(opc & 3) : (Char*)"",
+//..        ( isReg ? nameMMXReg(eregOfRM(modrm)) : dis_buf ),
+//..        nameMMXReg(gregOfRM(modrm)) );
+//.. 
+//..    return delta;
+//.. }
+//.. 
+//.. 
+//.. /* Vector by scalar shift of G by the amount specified at the bottom
+//..    of E.  This is a straight copy of dis_SSE_shiftG_byE. */
+//.. 
+//.. static UInt dis_MMX_shiftG_byE ( UChar sorb, UInt delta, 
+//..                                  HChar* opname, IROp op )
+//.. {
+//..    HChar   dis_buf[50];
+//..    Int     alen, size;
+//..    IRTemp  addr;
+//..    Bool    shl, shr, sar;
+//..    UChar   rm   = getIByte(delta);
+//..    IRTemp  g0   = newTemp(Ity_I64);
+//..    IRTemp  g1   = newTemp(Ity_I64);
+//..    IRTemp  amt  = newTemp(Ity_I32);
+//..    IRTemp  amt8 = newTemp(Ity_I8);
+//.. 
+//..    if (epartIsReg(rm)) {
+//..       assign( amt, unop(Iop_64to32, getMMXReg(eregOfRM(rm))) );
+//..       DIP("%s %s,%s\n", opname,
+//..                         nameMMXReg(eregOfRM(rm)),
+//..                         nameMMXReg(gregOfRM(rm)) );
+//..       delta++;
+//..    } else {
+//..       addr = disAMode ( &alen, sorb, delta, dis_buf );
+//..       assign( amt, loadLE(Ity_I32, mkexpr(addr)) );
+//..       DIP("%s %s,%s\n", opname,
+//..                         dis_buf,
+//..                         nameMMXReg(gregOfRM(rm)) );
+//..       delta += alen;
+//..    }
+//..    assign( g0,   getMMXReg(gregOfRM(rm)) );
+//..    assign( amt8, unop(Iop_32to8, mkexpr(amt)) );
+//.. 
+//..    shl = shr = sar = False;
+//..    size = 0;
+//..    switch (op) {
+//..       case Iop_ShlN16x4: shl = True; size = 32; break;
+//..       case Iop_ShlN32x2: shl = True; size = 32; break;
+//..       case Iop_Shl64:    shl = True; size = 64; break;
+//..       case Iop_ShrN16x4: shr = True; size = 16; break;
+//..       case Iop_ShrN32x2: shr = True; size = 32; break;
+//..       case Iop_Shr64:    shr = True; size = 64; break;
+//..       case Iop_SarN16x4: sar = True; size = 16; break;
+//..       case Iop_SarN32x2: sar = True; size = 32; break;
+//..       default: vassert(0);
+//..    }
+//.. 
+//..    if (shl || shr) {
+//..      assign( 
+//..         g1,
+//..         IRExpr_Mux0X(
+//..            unop(Iop_1Uto8,binop(Iop_CmpLT32U,mkexpr(amt),mkU32(size))),
+//..            mkU64(0),
+//..            binop(op, mkexpr(g0), mkexpr(amt8))
+//..         )
+//..      );
+//..    } else 
+//..    if (sar) {
+//..      assign( 
+//..         g1,
+//..         IRExpr_Mux0X(
+//..            unop(Iop_1Uto8,binop(Iop_CmpLT32U,mkexpr(amt),mkU32(size))),
+//..            binop(op, mkexpr(g0), mkU8(size-1)),
+//..            binop(op, mkexpr(g0), mkexpr(amt8))
+//..         )
+//..      );
+//..    } else {
+//..       vassert(0);
+//..    }
+//.. 
+//..    putMMXReg( gregOfRM(rm), mkexpr(g1) );
+//..    return delta;
+//.. }
+//.. 
+//.. 
+//.. /* Vector by scalar shift of E by an immediate byte.  This is a
+//..    straight copy of dis_SSE_shiftE_imm. */
+//.. 
+//.. static 
+//.. UInt dis_MMX_shiftE_imm ( UInt delta, HChar* opname, IROp op )
+//.. {
+//..    Bool    shl, shr, sar;
+//..    UChar   rm   = getIByte(delta);
+//..    IRTemp  e0   = newTemp(Ity_I64);
+//..    IRTemp  e1   = newTemp(Ity_I64);
+//..    UChar   amt, size;
+//..    vassert(epartIsReg(rm));
+//..    vassert(gregOfRM(rm) == 2 
+//..            || gregOfRM(rm) == 4 || gregOfRM(rm) == 6);
+//..    amt = (Int)(getIByte(delta+1));
+//..    delta += 2;
+//..    DIP("%s $%d,%s\n", opname,
+//..                       (Int)amt,
+//..                       nameMMXReg(eregOfRM(rm)) );
+//.. 
+//..    assign( e0, getMMXReg(eregOfRM(rm)) );
+//.. 
+//..    shl = shr = sar = False;
+//..    size = 0;
+//..    switch (op) {
+//..       case Iop_ShlN16x4: shl = True; size = 16; break;
+//..       case Iop_ShlN32x2: shl = True; size = 32; break;
+//..       case Iop_Shl64:    shl = True; size = 64; break;
+//..       case Iop_SarN16x4: sar = True; size = 16; break;
+//..       case Iop_SarN32x2: sar = True; size = 32; break;
+//..       case Iop_ShrN16x4: shr = True; size = 16; break;
+//..       case Iop_ShrN32x2: shr = True; size = 32; break;
+//..       case Iop_Shr64:    shr = True; size = 64; break;
+//..       default: vassert(0);
+//..    }
+//.. 
+//..    if (shl || shr) {
+//..      assign( e1, amt >= size 
+//..                     ? mkU64(0)
+//..                     : binop(op, mkexpr(e0), mkU8(amt))
+//..      );
+//..    } else 
+//..    if (sar) {
+//..      assign( e1, amt >= size 
+//..                     ? binop(op, mkexpr(e0), mkU8(size-1))
+//..                     : binop(op, mkexpr(e0), mkU8(amt))
+//..      );
+//..    } else {
+//..       vassert(0);
+//..    }
+//.. 
+//..    putMMXReg( eregOfRM(rm), mkexpr(e1) );
+//..    return delta;
+//.. }
+//.. 
+//.. 
+//.. /* Completely handle all MMX instructions except emms. */
+//.. 
+//.. static
+//.. UInt dis_MMX ( Bool* decode_ok, UChar sorb, Int sz, UInt delta )
+//.. {
+//..    Int   len;
+//..    UChar modrm;
+//..    HChar dis_buf[50];
+//..    UChar opc = getIByte(delta);
+//..    delta++;
+//.. 
+//..    /* dis_MMX handles all insns except emms. */
+//..    do_MMX_preamble();
+//.. 
+//..    switch (opc) {
+//.. 
+//..       case 0x6E: 
+//..          /* MOVD (src)ireg-or-mem (E), (dst)mmxreg (G)*/
+//..          if (sz != 4) 
+//..             goto mmx_decode_failure;
+//..          modrm = getIByte(delta);
+//..          if (epartIsReg(modrm)) {
+//..             delta++;
+//..             putMMXReg(
+//..                gregOfRM(modrm),
+//..                binop( Iop_32HLto64,
+//..                       mkU32(0),
+//..                       getIReg(4, eregOfRM(modrm)) ) );
+//..             DIP("movd %s, %s\n", 
+//..                 nameIReg(4,eregOfRM(modrm)), nameMMXReg(gregOfRM(modrm)));
+//..          } else {
+//..             IRTemp addr = disAMode( &len, sorb, delta, dis_buf );
+//..             delta += len;
+//..             putMMXReg(
+//..                gregOfRM(modrm),
+//..                binop( Iop_32HLto64,
+//..                       mkU32(0),
+//..                       loadLE(Ity_I32, mkexpr(addr)) ) );
+//..             DIP("movd %s, %s\n", dis_buf, nameMMXReg(gregOfRM(modrm)));
+//..          }
+//..          break;
+//.. 
+//..       case 0x7E: /* MOVD (src)mmxreg (G), (dst)ireg-or-mem (E) */
+//..          if (sz != 4) 
+//..             goto mmx_decode_failure;
+//..          modrm = getIByte(delta);
+//..          if (epartIsReg(modrm)) {
+//..             delta++;
+//..             putIReg( 4, eregOfRM(modrm),
+//..                      unop(Iop_64to32, getMMXReg(gregOfRM(modrm)) ) );
+//..             DIP("movd %s, %s\n", 
+//..                 nameMMXReg(gregOfRM(modrm)), nameIReg(4,eregOfRM(modrm)));
+//..          } else {
+//..             IRTemp addr = disAMode( &len, sorb, delta, dis_buf );
+//..             delta += len;
+//..             storeLE( mkexpr(addr),
+//..                      unop(Iop_64to32, getMMXReg(gregOfRM(modrm)) ) );
+//..             DIP("movd %s, %s\n", nameMMXReg(gregOfRM(modrm)), dis_buf);
+//..          }
+//..          break;
+//.. 
+//..       case 0x6F:
+//..          /* MOVQ (src)mmxreg-or-mem, (dst)mmxreg */
+//..          if (sz != 4) 
+//..             goto mmx_decode_failure;
+//..          modrm = getIByte(delta);
+//..          if (epartIsReg(modrm)) {
+//..             delta++;
+//..             putMMXReg( gregOfRM(modrm), getMMXReg(eregOfRM(modrm)) );
+//..             DIP("movq %s, %s\n", 
+//..                 nameMMXReg(eregOfRM(modrm)), nameMMXReg(gregOfRM(modrm)));
+//..          } else {
+//..             IRTemp addr = disAMode( &len, sorb, delta, dis_buf );
+//..             delta += len;
+//..             putMMXReg( gregOfRM(modrm), loadLE(Ity_I64, mkexpr(addr)) );
+//..             DIP("movq %s, %s\n", 
+//..                 dis_buf, nameMMXReg(gregOfRM(modrm)));
+//..          }
+//..          break;
+//.. 
+//..       case 0x7F:
+//..          /* MOVQ (src)mmxreg, (dst)mmxreg-or-mem */
+//..          if (sz != 4) 
+//..             goto mmx_decode_failure;
+//..          modrm = getIByte(delta);
+//..          if (epartIsReg(modrm)) {
+//..             /* Fall through.  The assembler doesn't appear to generate
+//..                these. */
+//..             goto mmx_decode_failure;
+//..          } else {
+//..             IRTemp addr = disAMode( &len, sorb, delta, dis_buf );
+//..             delta += len;
+//..             storeLE( mkexpr(addr), getMMXReg(gregOfRM(modrm)) );
+//..             DIP("mov(nt)q %s, %s\n", 
+//..                 nameMMXReg(gregOfRM(modrm)), dis_buf);
+//..          }
+//..          break;
+//.. 
+//..       case 0xFC: 
+//..       case 0xFD: 
+//..       case 0xFE: /* PADDgg (src)mmxreg-or-mem, (dst)mmxreg */
+//..          if (sz != 4) 
+//..             goto mmx_decode_failure;
+//..          delta = dis_MMXop_regmem_to_reg ( sorb, delta, opc, "padd", True );
+//..          break;
+//.. 
+//..       case 0xEC: 
+//..       case 0xED: /* PADDSgg (src)mmxreg-or-mem, (dst)mmxreg */
+//..          if (sz != 4) 
+//..             goto mmx_decode_failure;
+//..          delta = dis_MMXop_regmem_to_reg ( sorb, delta, opc, "padds", True );
+//..          break;
+//.. 
+//..       case 0xDC: 
+//..       case 0xDD: /* PADDUSgg (src)mmxreg-or-mem, (dst)mmxreg */
+//..          if (sz != 4) 
+//..             goto mmx_decode_failure;
+//..          delta = dis_MMXop_regmem_to_reg ( sorb, delta, opc, "paddus", True );
+//..          break;
+//.. 
+//..       case 0xF8: 
+//..       case 0xF9: 
+//..       case 0xFA: /* PSUBgg (src)mmxreg-or-mem, (dst)mmxreg */
+//..          if (sz != 4) 
+//..             goto mmx_decode_failure;
+//..          delta = dis_MMXop_regmem_to_reg ( sorb, delta, opc, "psub", True );
+//..          break;
+//.. 
+//..       case 0xE8: 
+//..       case 0xE9: /* PSUBSgg (src)mmxreg-or-mem, (dst)mmxreg */
+//..          if (sz != 4) 
+//..             goto mmx_decode_failure;
+//..          delta = dis_MMXop_regmem_to_reg ( sorb, delta, opc, "psubs", True );
+//..          break;
+//.. 
+//..       case 0xD8: 
+//..       case 0xD9: /* PSUBUSgg (src)mmxreg-or-mem, (dst)mmxreg */
+//..          if (sz != 4) 
+//..             goto mmx_decode_failure;
+//..          delta = dis_MMXop_regmem_to_reg ( sorb, delta, opc, "psubus", True );
+//..          break;
+//.. 
+//..       case 0xE5: /* PMULHW (src)mmxreg-or-mem, (dst)mmxreg */
+//..          if (sz != 4) 
+//..             goto mmx_decode_failure;
+//..          delta = dis_MMXop_regmem_to_reg ( sorb, delta, opc, "pmulhw", False );
+//..          break;
+//.. 
+//..       case 0xD5: /* PMULLW (src)mmxreg-or-mem, (dst)mmxreg */
+//..          if (sz != 4) 
+//..             goto mmx_decode_failure;
+//..          delta = dis_MMXop_regmem_to_reg ( sorb, delta, opc, "pmullw", False );
+//..          break;
+//.. 
+//..       case 0xF5: /* PMADDWD (src)mmxreg-or-mem, (dst)mmxreg */
+//..          vassert(sz == 4);
+//..          delta = dis_MMXop_regmem_to_reg ( sorb, delta, opc, "pmaddwd", False );
+//..          break;
+//.. 
+//..       case 0x74: 
+//..       case 0x75: 
+//..       case 0x76: /* PCMPEQgg (src)mmxreg-or-mem, (dst)mmxreg */
+//..          if (sz != 4) 
+//..             goto mmx_decode_failure;
+//..          delta = dis_MMXop_regmem_to_reg ( sorb, delta, opc, "pcmpeq", True );
+//..          break;
+//.. 
+//..       case 0x64: 
+//..       case 0x65: 
+//..       case 0x66: /* PCMPGTgg (src)mmxreg-or-mem, (dst)mmxreg */
+//..          if (sz != 4) 
+//..             goto mmx_decode_failure;
+//..          delta = dis_MMXop_regmem_to_reg ( sorb, delta, opc, "pcmpgt", True );
+//..          break;
+//.. 
+//..       case 0x6B: /* PACKSSDW (src)mmxreg-or-mem, (dst)mmxreg */
+//..          if (sz != 4) 
+//..             goto mmx_decode_failure;
+//..          delta = dis_MMXop_regmem_to_reg ( sorb, delta, opc, "packssdw", False );
+//..          break;
+//.. 
+//..       case 0x63: /* PACKSSWB (src)mmxreg-or-mem, (dst)mmxreg */
+//..          if (sz != 4) 
+//..             goto mmx_decode_failure;
+//..          delta = dis_MMXop_regmem_to_reg ( sorb, delta, opc, "packsswb", False );
+//..          break;
+//.. 
+//..       case 0x67: /* PACKUSWB (src)mmxreg-or-mem, (dst)mmxreg */
+//..          if (sz != 4) 
+//..             goto mmx_decode_failure;
+//..          delta = dis_MMXop_regmem_to_reg ( sorb, delta, opc, "packuswb", False );
+//..          break;
+//.. 
+//..       case 0x68: 
+//..       case 0x69: 
+//..       case 0x6A: /* PUNPCKHgg (src)mmxreg-or-mem, (dst)mmxreg */
+//..          if (sz != 4) 
+//..             goto mmx_decode_failure;
+//..          delta = dis_MMXop_regmem_to_reg ( sorb, delta, opc, "punpckh", True );
+//..          break;
+//.. 
+//..       case 0x60: 
+//..       case 0x61: 
+//..       case 0x62: /* PUNPCKLgg (src)mmxreg-or-mem, (dst)mmxreg */
+//..          if (sz != 4) 
+//..             goto mmx_decode_failure;
+//..          delta = dis_MMXop_regmem_to_reg ( sorb, delta, opc, "punpckl", True );
+//..          break;
+//.. 
+//..       case 0xDB: /* PAND (src)mmxreg-or-mem, (dst)mmxreg */
+//..          if (sz != 4) 
+//..             goto mmx_decode_failure;
+//..          delta = dis_MMXop_regmem_to_reg ( sorb, delta, opc, "pand", False );
+//..          break;
+//.. 
+//..       case 0xDF: /* PANDN (src)mmxreg-or-mem, (dst)mmxreg */
+//..          if (sz != 4) 
+//..             goto mmx_decode_failure;
+//..          delta = dis_MMXop_regmem_to_reg ( sorb, delta, opc, "pandn", False );
+//..          break;
+//.. 
+//..       case 0xEB: /* POR (src)mmxreg-or-mem, (dst)mmxreg */
+//..          if (sz != 4) 
+//..             goto mmx_decode_failure;
+//..          delta = dis_MMXop_regmem_to_reg ( sorb, delta, opc, "por", False );
+//..          break;
+//.. 
+//..       case 0xEF: /* PXOR (src)mmxreg-or-mem, (dst)mmxreg */
+//..          if (sz != 4) 
+//..             goto mmx_decode_failure;
+//..          delta = dis_MMXop_regmem_to_reg ( sorb, delta, opc, "pxor", False );
+//..          break; 
+//.. 
+//.. #     define SHIFT_BY_REG(_name,_op)                                 \
+//..                 delta = dis_MMX_shiftG_byE(sorb, delta, _name, _op); \
+//..                 break;
+//.. 
+//..       /* PSLLgg (src)mmxreg-or-mem, (dst)mmxreg */
+//..       case 0xF1: SHIFT_BY_REG("psllw", Iop_ShlN16x4);
+//..       case 0xF2: SHIFT_BY_REG("pslld", Iop_ShlN32x2);
+//..       case 0xF3: SHIFT_BY_REG("psllq", Iop_Shl64);
+//.. 
+//..       /* PSRLgg (src)mmxreg-or-mem, (dst)mmxreg */
+//..       case 0xD1: SHIFT_BY_REG("psrlw", Iop_ShrN16x4);
+//..       case 0xD2: SHIFT_BY_REG("psrld", Iop_ShrN32x2);
+//..       case 0xD3: SHIFT_BY_REG("psrlq", Iop_Shr64);
+//.. 
+//..       /* PSRAgg (src)mmxreg-or-mem, (dst)mmxreg */
+//..       case 0xE1: SHIFT_BY_REG("psraw", Iop_SarN16x4);
+//..       case 0xE2: SHIFT_BY_REG("psrad", Iop_SarN32x2);
+//.. 
+//.. #     undef SHIFT_BY_REG
+//.. 
+//..       case 0x71: 
+//..       case 0x72: 
+//..       case 0x73: {
+//..          /* (sz==4): PSLLgg/PSRAgg/PSRLgg mmxreg by imm8 */
+//..          UChar byte1, byte2, subopc;
+//..          void* hAddr;
+//..          Char* hName;
+//..          if (sz != 4) 
+//..             goto mmx_decode_failure;
+//..          byte1  = opc;                       /* 0x71/72/73 */
+//..          byte2  = getIByte(delta);           /* amode / sub-opcode */
+//..          subopc = (byte2 >> 3) & 7;
+//.. 
+//.. #        define SHIFT_BY_IMM(_name,_op)                         \
+//..              do { delta = dis_MMX_shiftE_imm(delta,_name,_op);  \
+//..              } while (0)
+//.. 
+//..          hAddr = NULL;
+//..          hName = NULL;
+//.. 
+//..               if (subopc == 2 /*SRL*/ && opc == 0x71) 
+//..                  SHIFT_BY_IMM("psrlw", Iop_ShrN16x4);
+//..          else if (subopc == 2 /*SRL*/ && opc == 0x72) 
+//..                  SHIFT_BY_IMM("psrld", Iop_ShrN32x2);
+//..          else if (subopc == 2 /*SRL*/ && opc == 0x73) 
+//..                  SHIFT_BY_IMM("psrlq", Iop_Shr64);
+//.. 
+//..          else if (subopc == 4 /*SAR*/ && opc == 0x71) 
+//..                  SHIFT_BY_IMM("psraw", Iop_SarN16x4);
+//..          else if (subopc == 4 /*SAR*/ && opc == 0x72) 
+//..                  SHIFT_BY_IMM("psrad", Iop_SarN32x2);
+//.. 
+//..          else if (subopc == 6 /*SHL*/ && opc == 0x71) 
+//..                  SHIFT_BY_IMM("psllw", Iop_ShlN16x4);
+//..          else if (subopc == 6 /*SHL*/ && opc == 0x72) 
+//..                  SHIFT_BY_IMM("pslld", Iop_ShlN32x2);
+//..          else if (subopc == 6 /*SHL*/ && opc == 0x73) 
+//..                  SHIFT_BY_IMM("psllq", Iop_Shl64);
+//.. 
+//..          else goto mmx_decode_failure;
+//.. 
+//.. #        undef SHIFT_BY_IMM
+//..          break;
+//..       }
+//.. 
+//..       /* --- MMX decode failure --- */
+//..       default:
+//..       mmx_decode_failure:
+//..          *decode_ok = False;
+//..          return delta; /* ignored */
+//.. 
+//..    }
+//.. 
+//..    *decode_ok = True;
+//..    return delta;
+//.. }
+//.. 
+//.. 
+//.. /*------------------------------------------------------------*/
+//.. /*--- More misc arithmetic and other obscure insns.        ---*/
+//.. /*------------------------------------------------------------*/
+//.. 
+//.. /* Double length left and right shifts.  Apparently only required in
+//..    v-size (no b- variant). */
+//.. static
+//.. UInt dis_SHLRD_Gv_Ev ( UChar sorb,
+//..                        UInt delta, UChar modrm,
+//..                        Int sz,
+//..                        IRExpr* shift_amt,
+//..                        Bool amt_is_literal,
+//..                        Char* shift_amt_txt,
+//..                        Bool left_shift )
+//.. {
+//..    /* shift_amt :: Ity_I8 is the amount to shift.  shift_amt_txt is used
+//..       for printing it.   And eip on entry points at the modrm byte. */
+//..    Int len;
+//..    HChar dis_buf[50];
+//.. 
+//..    IRType ty       = szToITy(sz);
+//..    IRTemp gsrc     = newTemp(ty);
+//..    IRTemp esrc     = newTemp(ty);
+//..    IRTemp addr     = IRTemp_INVALID;
+//..    IRTemp tmpSH    = newTemp(Ity_I8);
+//..    IRTemp tmpL     = IRTemp_INVALID;
+//..    IRTemp tmpRes   = IRTemp_INVALID;
+//..    IRTemp tmpSubSh = IRTemp_INVALID;
+//..    IROp   mkpair;
+//..    IROp   getres;
+//..    IROp   shift;
+//..    IRExpr* mask = NULL;
+//.. 
+//..    vassert(sz == 2 || sz == 4);
+//.. 
+//..    /* The E-part is the destination; this is shifted.  The G-part
+//..       supplies bits to be shifted into the E-part, but is not
+//..       changed.  
+//.. 
+//..       If shifting left, form a double-length word with E at the top
+//..       and G at the bottom, and shift this left.  The result is then in
+//..       the high part.
+//.. 
+//..       If shifting right, form a double-length word with G at the top
+//..       and E at the bottom, and shift this right.  The result is then
+//..       at the bottom.  */
+//.. 
+//..    /* Fetch the operands. */
+//.. 
+//..    assign( gsrc, getIReg(sz, gregOfRM(modrm)) );
+//.. 
+//..    if (epartIsReg(modrm)) {
+//..       delta++;
+//..       assign( esrc, getIReg(sz, eregOfRM(modrm)) );
+//..       DIP("sh%cd%c %s, %s, %s\n",
+//..           ( left_shift ? 'l' : 'r' ), nameISize(sz), 
+//..           shift_amt_txt,
+//..           nameIReg(sz, gregOfRM(modrm)), nameIReg(sz, eregOfRM(modrm)));
+//..    } else {
+//..       addr = disAMode ( &len, sorb, delta, dis_buf );
+//..       delta += len;
+//..       assign( esrc, loadLE(ty, mkexpr(addr)) );
+//..       DIP("sh%cd%c %s, %s, %s\n", 
+//..           ( left_shift ? 'l' : 'r' ), nameISize(sz), 
+//..           shift_amt_txt,
+//..           nameIReg(sz, gregOfRM(modrm)), dis_buf);
+//..    }
+//.. 
+//..    /* Round up the relevant primops. */
+//.. 
+//..    if (sz == 4) {
+//..       tmpL     = newTemp(Ity_I64);
+//..       tmpRes   = newTemp(Ity_I32);
+//..       tmpSubSh = newTemp(Ity_I32);
+//..       mkpair   = Iop_32HLto64;
+//..       getres   = left_shift ? Iop_64HIto32 : Iop_64to32;
+//..       shift    = left_shift ? Iop_Shl64 : Iop_Shr64;
+//..       mask     = mkU8(31);
+//..    } else {
+//..       /* sz == 2 */
+//..       tmpL     = newTemp(Ity_I32);
+//..       tmpRes   = newTemp(Ity_I16);
+//..       tmpSubSh = newTemp(Ity_I16);
+//..       mkpair   = Iop_16HLto32;
+//..       getres   = left_shift ? Iop_32HIto16 : Iop_32to16;
+//..       shift    = left_shift ? Iop_Shl32 : Iop_Shr32;
+//..       mask     = mkU8(15);
+//..    }
+//.. 
+//..    /* Do the shift, calculate the subshift value, and set 
+//..       the flag thunk. */
+//.. 
+//..    assign( tmpSH, binop(Iop_And8, shift_amt, mask) );
+//.. 
+//..    if (left_shift)
+//..       assign( tmpL, binop(mkpair, mkexpr(esrc), mkexpr(gsrc)) );
+//..    else
+//..       assign( tmpL, binop(mkpair, mkexpr(gsrc), mkexpr(esrc)) );
+//.. 
+//..    assign( tmpRes, unop(getres, binop(shift, mkexpr(tmpL), mkexpr(tmpSH)) ) );
+//..    assign( tmpSubSh, 
+//..            unop(getres, 
+//..                 binop(shift, 
+//..                       mkexpr(tmpL), 
+//..                       binop(Iop_And8, 
+//..                             binop(Iop_Sub8, mkexpr(tmpSH), mkU8(1) ),
+//..                             mask))) );
+//.. 
+//..    setFlags_DEP1_DEP2_shift ( left_shift ? Iop_Shl32 : Iop_Sar32,
+//..                               tmpRes, tmpSubSh, ty, tmpSH );
+//.. 
+//..    /* Put result back. */
+//.. 
+//..    if (epartIsReg(modrm)) {
+//..       putIReg(sz, eregOfRM(modrm), mkexpr(tmpRes));
+//..    } else {
+//..       storeLE( mkexpr(addr), mkexpr(tmpRes) );
+//..    }
+//.. 
+//..    if (amt_is_literal) delta++;
+//..    return delta;
+//.. }
+//.. 
+//.. 
+//.. /* Handle BT/BTS/BTR/BTC Gv, Ev.  Apparently b-size is not
+//..    required. */
+//.. 
+//.. typedef enum { BtOpNone, BtOpSet, BtOpReset, BtOpComp } BtOp;
+//.. 
+//.. static Char* nameBtOp ( BtOp op )
+//.. {
+//..    switch (op) {
+//..       case BtOpNone:  return "";
+//..       case BtOpSet:   return "s";
+//..       case BtOpReset: return "r";
+//..       case BtOpComp:  return "c";
+//..       default: vpanic("nameBtOp(x86)");
+//..    }
+//.. }
+//.. 
+//.. 
+//.. static
+//.. UInt dis_bt_G_E ( UChar sorb, Int sz, UInt delta, BtOp op )
+//.. {
+//..    HChar  dis_buf[50];
+//..    UChar  modrm;
+//..    Int    len;
+//..    IRTemp t_fetched, t_bitno0, t_bitno1, t_bitno2, t_addr0, 
+//..           t_addr1, t_esp, t_mask;
+//.. 
+//..    vassert(sz == 2 || sz == 4);
+//.. 
+//..    t_fetched = t_bitno0 = t_bitno1 = t_bitno2 
+//..              = t_addr0 = t_addr1 = t_esp = t_mask = IRTemp_INVALID;
+//.. 
+//..    t_fetched = newTemp(Ity_I8);
+//..    t_bitno0  = newTemp(Ity_I32);
+//..    t_bitno1  = newTemp(Ity_I32);
+//..    t_bitno2  = newTemp(Ity_I8);
+//..    t_addr1   = newTemp(Ity_I32);
+//..    modrm     = getIByte(delta);
+//.. 
+//..    assign( t_bitno0, widenUto32(getIReg(sz, gregOfRM(modrm))) );
+//..    
+//..    if (epartIsReg(modrm)) {
+//..       delta++;
+//..       /* Get it onto the client's stack. */
+//..       t_esp = newTemp(Ity_I32);
+//..       t_addr0 = newTemp(Ity_I32);
+//.. 
+//..       assign( t_esp, binop(Iop_Sub32, getIReg(4, R_ESP), mkU32(sz)) );
+//..       putIReg(4, R_ESP, mkexpr(t_esp));
+//.. 
+//..       storeLE( mkexpr(t_esp), getIReg(sz, eregOfRM(modrm)) );
+//.. 
+//..       /* Make t_addr0 point at it. */
+//..       assign( t_addr0, mkexpr(t_esp) );
+//.. 
+//..       /* Mask out upper bits of the shift amount, since we're doing a
+//..          reg. */
+//..       assign( t_bitno1, binop(Iop_And32, 
+//..                               mkexpr(t_bitno0), 
+//..                               mkU32(sz == 4 ? 31 : 15)) );
+//.. 
+//..    } else {
+//..       t_addr0 = disAMode ( &len, sorb, delta, dis_buf );
+//..       delta += len;
+//..       assign( t_bitno1, mkexpr(t_bitno0) );
+//..    }
+//..   
+//..    /* At this point: t_addr0 is the address being operated on.  If it
+//..       was a reg, we will have pushed it onto the client's stack.
+//..       t_bitno1 is the bit number, suitably masked in the case of a
+//..       reg.  */
+//..   
+//..    /* Now the main sequence. */
+//..    assign( t_addr1, 
+//..            binop(Iop_Add32, 
+//..                  mkexpr(t_addr0), 
+//..                  binop(Iop_Sar32, mkexpr(t_bitno1), mkU8(3))) );
+//.. 
+//..    /* t_addr1 now holds effective address */
+//.. 
+//..    assign( t_bitno2, 
+//..            unop(Iop_32to8, 
+//..                 binop(Iop_And32, mkexpr(t_bitno1), mkU32(7))) );
+//.. 
+//..    /* t_bitno2 contains offset of bit within byte */
+//.. 
+//..    if (op != BtOpNone) {
+//..       t_mask = newTemp(Ity_I8);
+//..       assign( t_mask, binop(Iop_Shl8, mkU8(1), mkexpr(t_bitno2)) );
+//..    }
+//.. 
+//..    /* t_mask is now a suitable byte mask */
+//.. 
+//..    assign( t_fetched, loadLE(Ity_I8, mkexpr(t_addr1)) );
+//.. 
+//..    if (op != BtOpNone) {
+//..       switch (op) {
+//..          case BtOpSet: 
+//..             storeLE( mkexpr(t_addr1), 
+//..                      binop(Iop_Or8, mkexpr(t_fetched), 
+//..                                     mkexpr(t_mask)) );
+//..             break;
+//..          case BtOpComp: 
+//..             storeLE( mkexpr(t_addr1), 
+//..                      binop(Iop_Xor8, mkexpr(t_fetched), 
+//..                                      mkexpr(t_mask)) );
+//..             break;
+//..          case BtOpReset: 
+//..             storeLE( mkexpr(t_addr1), 
+//..                      binop(Iop_And8, mkexpr(t_fetched), 
+//..                                      unop(Iop_Not8, mkexpr(t_mask))) );
+//..             break;
+//..          default: 
+//..             vpanic("dis_bt_G_E(x86)");
+//..       }
+//..    }
+//..  
+//..    /* Side effect done; now get selected bit into Carry flag */
+//..    /* Flags: C=selected bit, O,S,Z,A,P undefined, so are set to zero. */
+//..    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, 
+//..                         unop(Iop_8Uto32, mkexpr(t_fetched)),
+//..                         mkexpr(t_bitno2)),
+//..                   mkU32(1)))
+//..        );
+//.. 
+//..    /* Move reg operand from stack back to reg */
+//..    if (epartIsReg(modrm)) {
+//..       /* t_esp still points at it. */
+//..       putIReg(sz, eregOfRM(modrm), loadLE(szToITy(sz), mkexpr(t_esp)) );
+//..       putIReg(4, R_ESP, binop(Iop_Add32, mkexpr(t_esp), mkU32(sz)) );
+//..    }
+//.. 
+//..    DIP("bt%s%c %s, %s\n",
+//..        nameBtOp(op), nameISize(sz), nameIReg(sz, gregOfRM(modrm)), 
+//..        ( epartIsReg(modrm) ? nameIReg(sz, eregOfRM(modrm)) : dis_buf ) );
+//..  
+//..    return delta;
+//.. }
+//.. 
+//.. 
+//.. 
+//.. /* Handle BSF/BSR.  Only v-size seems necessary. */
+//.. static
+//.. UInt dis_bs_E_G ( UChar sorb, Int sz, UInt delta, Bool fwds )
+//.. {
+//..    Bool   isReg;
+//..    UChar  modrm;
+//..    HChar  dis_buf[50];
+//..    
+//..    IRType ty  = szToITy(sz);
+//..    IRTemp src = newTemp(ty);
+//..    IRTemp dst = newTemp(ty);
+//.. 
+//..    IRTemp src32 = newTemp(Ity_I32);
+//..    IRTemp dst32 = newTemp(Ity_I32);
+//..    IRTemp src8  = newTemp(Ity_I8);
+//.. 
+//..    vassert(sz == 4 || sz == 2);
+//.. 
+//..    modrm = getIByte(delta);
+//.. 
+//..    isReg = epartIsReg(modrm);
+//..    if (isReg) {
+//..       delta++;
+//..       assign( src, getIReg(sz, eregOfRM(modrm)) );
+//..    } else {
+//..       Int    len;
+//..       IRTemp addr = disAMode( &len, sorb, delta, dis_buf );
+//..       delta += len;
+//..       assign( src, loadLE(ty, mkexpr(addr)) );
+//..    }
+//.. 
+//..    DIP("bs%c%c %s, %s\n",
+//..        fwds ? 'f' : 'r', nameISize(sz), 
+//..        ( isReg ? nameIReg(sz, eregOfRM(modrm)) : dis_buf ), 
+//..        nameIReg(sz, gregOfRM(modrm)));
+//.. 
+//..    /* Generate an 8-bit expression which is zero iff the 
+//..       original is zero, and nonzero otherwise */
+//..    assign( src8,
+//..            unop(Iop_1Uto8, binop(mkSizedOp(ty,Iop_CmpNE8),
+//..                            mkexpr(src), mkU(ty,0))) );
+//.. 
+//..    /* Flags: Z is 1 iff source value is zero.  All others 
+//..       are undefined -- we force them to zero. */
+//..    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,
+//..             IRExpr_Mux0X( mkexpr(src8),
+//..                           /* src==0 */
+//..                           mkU32(X86G_CC_MASK_Z),
+//..                           /* src!=0 */
+//..                           mkU32(0)
+//..                         )
+//..        ));
+//.. 
+//..    /* Result: iff source value is zero, we can't use
+//..       Iop_Clz32/Iop_Ctz32 as they have no defined result in that case.
+//..       But anyway, Intel x86 semantics say the result is undefined in
+//..       such situations.  Hence handle the zero case specially. */
+//.. 
+//..    /* Bleh.  What we compute:
+//.. 
+//..           bsf32:  if src == 0 then 0 else  Ctz32(src)
+//..           bsr32:  if src == 0 then 0 else  31 - Clz32(src)
+//.. 
+//..           bsf16:  if src == 0 then 0 else  Ctz32(16Uto32(src))
+//..           bsr16:  if src == 0 then 0 else  31 - Clz32(16Uto32(src))
+//.. 
+//..       First, widen src to 32 bits if it is not already.
+//.. 
+//..       Postscript 15 Oct 04: it seems that at least VIA Nehemiah leaves the
+//..       dst register unchanged when src == 0.  Hence change accordingly.
+//..    */
+//..    if (sz == 2)
+//..       assign( src32, unop(Iop_16Uto32, mkexpr(src)) );
+//..    else
+//..       assign( src32, mkexpr(src) );
+//.. 
+//..    /* The main computation, guarding against zero. */
+//..    assign( dst32,   
+//..            IRExpr_Mux0X( 
+//..               mkexpr(src8),
+//..               /* src == 0 -- leave dst unchanged */
+//..               widenUto32( getIReg( sz, gregOfRM(modrm) ) ),
+//..               /* src != 0 */
+//..               fwds ? unop(Iop_Ctz32, mkexpr(src32))
+//..                    : binop(Iop_Sub32, 
+//..                            mkU32(31), 
+//..                            unop(Iop_Clz32, mkexpr(src32)))
+//..            )
+//..          );
+//.. 
+//..    if (sz == 2)
+//..       assign( dst, unop(Iop_32to16, mkexpr(dst32)) );
+//..    else
+//..       assign( dst, mkexpr(dst32) );
+//.. 
+//..    /* dump result back */
+//..    putIReg( sz, gregOfRM(modrm), mkexpr(dst) );
+//.. 
+//..    return delta;
+//.. }
+//.. 
+//.. 
+//.. static 
+//.. void codegen_xchg_eAX_Reg ( Int sz, Int reg )
+//.. {
+//..    IRType ty = szToITy(sz);
+//..    IRTemp t1 = newTemp(ty);
+//..    IRTemp t2 = newTemp(ty);
+//..    vassert(sz == 2 || sz == 4);
+//..    assign( t1, getIReg(sz, R_EAX) );
+//..    assign( t2, getIReg(sz, reg) );
+//..    putIReg( sz, R_EAX, mkexpr(t2) );
+//..    putIReg( sz, reg, mkexpr(t1) );
+//..    DIP("xchg%c %s, %s\n", 
+//..        nameISize(sz), nameIReg(sz, R_EAX), nameIReg(sz, reg));
+//.. }
+//.. 
+//.. 
+//.. static 
+//.. void codegen_SAHF ( void )
+//.. {
+//..    /* Set the flags to:
+//..       (x86g_calculate_flags_all() & X86G_CC_MASK_O)  -- retain the old O flag
+//..       | (%AH & (X86G_CC_MASK_S|X86G_CC_MASK_Z|X86G_CC_MASK_A
+//..                 |X86G_CC_MASK_P|X86G_CC_MASK_C)
+//..    */
+//..    UInt   mask_SZACP = X86G_CC_MASK_S|X86G_CC_MASK_Z|X86G_CC_MASK_A
+//..                        |X86G_CC_MASK_C|X86G_CC_MASK_P;
+//..    IRTemp oldflags   = newTemp(Ity_I32);
+//..    assign( oldflags, mk_x86g_calculate_eflags_all() );
+//..    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_Or32,
+//..                binop(Iop_And32, mkexpr(oldflags), mkU32(X86G_CC_MASK_O)),
+//..                binop(Iop_And32, 
+//..                      binop(Iop_Shr32, getIReg(4, R_EAX), mkU8(8)),
+//..                      mkU32(mask_SZACP))
+//..               )
+//..    ));
+//.. }
+//.. 
+//.. 
+//.. //-- static 
+//.. //-- void codegen_LAHF ( UCodeBlock* cb )
+//.. //-- {
+//.. //--    Int t = newTemp(cb);
+//.. //-- 
+//.. //--    /* Pushed arg is ignored, it just provides somewhere to put the
+//.. //--       return value. */
+//.. //--    uInstr2(cb, GET,   4, ArchReg, R_EAX, TempReg, t);
+//.. //--    uInstr0(cb, CALLM_S, 0);
+//.. //--    uInstr1(cb, PUSH,  4, TempReg, t);
+//.. //--    uInstr1(cb, CALLM, 0, Lit16,   VGOFF_(helper_LAHF));
+//.. //--    uFlagsRWU(cb, FlagsSZACP, FlagsEmpty, FlagsEmpty);
+//.. //--    uInstr1(cb, POP,   4, TempReg, t);
+//.. //--    uInstr0(cb, CALLM_E, 0);
+//.. //-- 
+//.. //--    /* At this point, the %ah sub-register in %eax has been updated,
+//.. //--       the rest is the same, so do a PUT of the whole thing. */
+//.. //--    uInstr2(cb, PUT,   4,  TempReg, t,   ArchReg, R_EAX);
+//.. //-- }
+//.. //-- 
+//.. 
+//.. static
+//.. UInt dis_cmpxchg_G_E ( UChar       sorb,
+//..                        Int         size, 
+//..                        UInt        delta0 )
+//.. {
+//..    HChar dis_buf[50];
+//..    Int   len;
+//.. 
+//..    IRType ty    = szToITy(size);
+//..    IRTemp acc   = newTemp(ty);
+//..    IRTemp src   = newTemp(ty);
+//..    //IRTemp res   = newTemp(ty);
+//..    IRTemp dest  = newTemp(ty);
+//..    IRTemp dest2 = newTemp(ty);
+//..    IRTemp acc2  = newTemp(ty);
+//..    IRTemp cond8 = newTemp(Ity_I8);
+//..    IRTemp addr  = IRTemp_INVALID;
+//..    UChar  rm    = getUChar(delta0);
+//.. 
+//..    if (epartIsReg(rm)) {
+//..       assign( dest, getIReg(size, eregOfRM(rm)) );
+//..       delta0++;
+//..       DIP("cmpxchg%c %s,%s\n", nameISize(size),
+//..                                nameIReg(size,gregOfRM(rm)),
+//..                                nameIReg(size,eregOfRM(rm)) );
+//..    } else {
+//..       addr = disAMode ( &len, sorb, delta0, dis_buf );
+//..       assign( dest, loadLE(ty, mkexpr(addr)) );
+//..       delta0 += len;
+//..       DIP("cmpxchg%c %s,%s\n", nameISize(size), 
+//..                                nameIReg(size,gregOfRM(rm)), dis_buf);
+//..    }
+//.. 
+//..    assign( src, getIReg(size, gregOfRM(rm)) );
+//..    assign( acc, getIReg(size, R_EAX) );
+//..    //assign( res, binop( mkSizedOp(ty,Iop_Sub8), mkexpr(acc), mkexpr(dest) ));
+//..    setFlags_DEP1_DEP2(Iop_Sub8, acc, dest, ty);
+//..    assign( cond8, unop(Iop_1Uto8, mk_x86g_calculate_condition(X86CondZ)) );
+//..    assign( dest2, IRExpr_Mux0X(mkexpr(cond8), mkexpr(dest), mkexpr(src)) );
+//..    assign( acc2,  IRExpr_Mux0X(mkexpr(cond8), mkexpr(dest), mkexpr(acc)) );
+//..    putIReg(size, R_EAX, mkexpr(acc2));
+//.. 
+//..    if (epartIsReg(rm)) {
+//..       putIReg(size, eregOfRM(rm), mkexpr(dest2));
+//..    } else {
+//..       storeLE( mkexpr(addr), mkexpr(dest2) );
+//..    }
+//.. 
+//..    return delta0;
+//.. }
+//.. 
+//.. 
+//.. //-- static
+//.. //-- Addr dis_cmpxchg8b ( UCodeBlock* cb, 
+//.. //--                      UChar       sorb,
+//.. //--                      Addr        eip0 )
+//.. //-- {
+//.. //--    Int   tal, tah, junkl, junkh, destl, desth, srcl, srch, accl, acch;
+//.. //--    HChar dis_buf[50];
+//.. //--    UChar rm;
+//.. //--    UInt  pair;
+//.. //-- 
+//.. //--    rm    = getUChar(eip0);
+//.. //--    accl  = newTemp(cb);
+//.. //--    acch  = newTemp(cb);
+//.. //--    srcl  = newTemp(cb);
+//.. //--    srch  = newTemp(cb);
+//.. //--    destl = newTemp(cb);
+//.. //--    desth = newTemp(cb);
+//.. //--    junkl = newTemp(cb);
+//.. //--    junkh = newTemp(cb);
+//.. //-- 
+//.. //--    vg_assert(!epartIsReg(rm));
+//.. //-- 
+//.. //--    pair = disAMode ( cb, sorb, eip0, dis_buf );
+//.. //--    tal = LOW24(pair);
+//.. //--    tah = newTemp(cb);
+//.. //--    uInstr2(cb, MOV, 4, TempReg, tal, TempReg, tah);
+//.. //--    uInstr2(cb, ADD, 4, Literal, 0, TempReg, tah);
+//.. //--    uLiteral(cb, 4);
+//.. //--    eip0 += HI8(pair);
+//.. //--    DIP("cmpxchg8b %s\n", dis_buf);
+//.. //--    
+//.. //--    uInstr0(cb, CALLM_S, 0);
+//.. //-- 
+//.. //--    uInstr2(cb, LOAD,  4, TempReg, tah, TempReg, desth);
+//.. //--    uInstr1(cb, PUSH,  4, TempReg, desth);
+//.. //--    uInstr2(cb, LOAD,  4, TempReg, tal, TempReg, destl);
+//.. //--    uInstr1(cb, PUSH,  4, TempReg, destl);
+//.. //--    uInstr2(cb, GET,   4, ArchReg, R_ECX, TempReg, srch);
+//.. //--    uInstr1(cb, PUSH,  4, TempReg, srch);
+//.. //--    uInstr2(cb, GET,   4, ArchReg, R_EBX, TempReg, srcl);
+//.. //--    uInstr1(cb, PUSH,  4, TempReg, srcl);
+//.. //--    uInstr2(cb, GET,   4, ArchReg, R_EDX, TempReg, acch);
+//.. //--    uInstr1(cb, PUSH,  4, TempReg, acch);
+//.. //--    uInstr2(cb, GET,   4, ArchReg, R_EAX, TempReg, accl);
+//.. //--    uInstr1(cb, PUSH,  4, TempReg, accl);
+//.. //--    
+//.. //--    uInstr1(cb, CALLM, 0, Lit16,   VGOFF_(helper_cmpxchg8b));
+//.. //--    uFlagsRWU(cb, FlagsEmpty, FlagZ, FlagsEmpty);
+//.. //--    
+//.. //--    uInstr1(cb, POP,   4, TempReg, accl);
+//.. //--    uInstr2(cb, PUT,   4, TempReg, accl, ArchReg, R_EAX);
+//.. //--    uInstr1(cb, POP,   4, TempReg, acch);
+//.. //--    uInstr2(cb, PUT,   4, TempReg, acch, ArchReg, R_EDX);
+//.. //--    uInstr1(cb, POP,   4, TempReg, srcl);
+//.. //--    uInstr2(cb, PUT,   4, TempReg, srcl, ArchReg, R_EBX);
+//.. //--    uInstr1(cb, POP,   4, TempReg, srch);
+//.. //--    uInstr2(cb, PUT,   4, TempReg, srch, ArchReg, R_ECX);
+//.. //--    uInstr1(cb, POP,   4, TempReg, destl);
+//.. //--    uInstr2(cb, STORE, 4, TempReg, destl, TempReg, tal);
+//.. //--    uInstr1(cb, POP,   4, TempReg, desth);
+//.. //--    uInstr2(cb, STORE, 4, TempReg, desth, TempReg, tah);
+//.. //-- 
+//.. //--    uInstr0(cb, CALLM_E, 0);
+//.. //--    
+//.. //--    return eip0;
+//.. //-- }
+//.. 
+//.. 
+//.. /* Handle conditional move instructions of the form
+//..       cmovcc E(reg-or-mem), G(reg)
+//.. 
+//..    E(src) is reg-or-mem
+//..    G(dst) is reg.
+//.. 
+//..    If E is reg, -->    GET %E, tmps
+//..                        GET %G, tmpd
+//..                        CMOVcc tmps, tmpd
+//..                        PUT tmpd, %G
+//..  
+//..    If E is mem  -->    (getAddr E) -> tmpa
+//..                        LD (tmpa), tmps
+//..                        GET %G, tmpd
+//..                        CMOVcc tmps, tmpd
+//..                        PUT tmpd, %G
+//.. */
+//.. static
+//.. UInt dis_cmov_E_G ( UChar       sorb,
+//..                     Int         sz, 
+//..                     X86Condcode cond,
+//..                     UInt        delta0 )
+//.. {
+//..    UChar rm  = getIByte(delta0);
+//..    HChar dis_buf[50];
+//..    Int   len;
+//.. 
+//..    IRType ty   = szToITy(sz);
+//..    IRTemp tmps = newTemp(ty);
+//..    IRTemp tmpd = newTemp(ty);
+//.. 
+//..    if (epartIsReg(rm)) {
+//..       assign( tmps, getIReg(sz, eregOfRM(rm)) );
+//..       assign( tmpd, getIReg(sz, gregOfRM(rm)) );
+//.. 
+//..       putIReg(sz, gregOfRM(rm),
+//..                   IRExpr_Mux0X( unop(Iop_1Uto8,
+//..                                      mk_x86g_calculate_condition(cond)),
+//..                                 mkexpr(tmpd),
+//..                                 mkexpr(tmps) )
+//..              );
+//..       DIP("cmov%c%s %s,%s\n", nameISize(sz), 
+//..                               name_X86Condcode(cond),
+//..                               nameIReg(sz,eregOfRM(rm)),
+//..                               nameIReg(sz,gregOfRM(rm)));
+//..       return 1+delta0;
+//..    }
+//.. 
+//..    /* E refers to memory */    
+//..    {
+//..       IRTemp addr = disAMode ( &len, sorb, delta0, dis_buf );
+//..       assign( tmps, loadLE(ty, mkexpr(addr)) );
+//..       assign( tmpd, getIReg(sz, gregOfRM(rm)) );
+//.. 
+//..       putIReg(sz, gregOfRM(rm),
+//..                   IRExpr_Mux0X( unop(Iop_1Uto8,
+//..                                      mk_x86g_calculate_condition(cond)),
+//..                                 mkexpr(tmpd),
+//..                                 mkexpr(tmps) )
+//..              );
+//.. 
+//..       DIP("cmov%c%s %s,%s\n", nameISize(sz), 
+//..                               name_X86Condcode(cond),
+//..                               dis_buf,
+//..                               nameIReg(sz,gregOfRM(rm)));
+//..       return len+delta0;
+//..    }
+//.. }
+//.. 
+//.. 
+//.. static
+//.. UInt dis_xadd_G_E ( UChar sorb, Int sz, UInt delta0 )
+//.. {
+//..    Int   len;
+//..    UChar rm = getIByte(delta0);
+//..    HChar dis_buf[50];
+//.. 
+//..    //   Int tmpd = newTemp(cb);
+//..    //Int tmpt = newTemp(cb);
+//.. 
+//..    IRType ty    = szToITy(sz);
+//..    IRTemp tmpd  = newTemp(ty);
+//..    IRTemp tmpt0 = newTemp(ty);
+//..    IRTemp tmpt1 = newTemp(ty);
+//.. 
+//..    if (epartIsReg(rm)) {
+//..      vassert(0);
+//.. #if 0
+//..       uInstr2(cb, GET, sz, ArchReg, eregOfRM(rm), TempReg, tmpd);
+//..       uInstr2(cb, GET, sz, ArchReg, gregOfRM(rm), TempReg, tmpt);
+//..       uInstr2(cb, ADD, sz, TempReg, tmpd, TempReg, tmpt);
+//..       setFlagsFromUOpcode(cb, ADD);
+//..       uInstr2(cb, PUT, sz, TempReg, tmpd, ArchReg, gregOfRM(rm));
+//..       uInstr2(cb, PUT, sz, TempReg, tmpt, ArchReg, eregOfRM(rm));
+//..       DIP("xadd%c %s, %s\n",
+//..           nameISize(sz), nameIReg(sz,gregOfRM(rm)), nameIReg(sz,eregOfRM(rm)));
+//..       return 1+eip0;
+//.. #endif
+//..    } else {
+//..       IRTemp addr = disAMode ( &len, sorb, delta0, dis_buf );
+//..       assign( tmpd,  loadLE(ty, mkexpr(addr)) );
+//..       assign( tmpt0, getIReg(sz, gregOfRM(rm)) );
+//..       assign( tmpt1, binop(mkSizedOp(ty,Iop_Add8), mkexpr(tmpd), mkexpr(tmpt0)) );
+//..       setFlags_DEP1_DEP2( Iop_Add8, tmpd, tmpt0, ty );
+//..       storeLE( mkexpr(addr), mkexpr(tmpt1) );
+//..       putIReg(sz, gregOfRM(rm), mkexpr(tmpd));
+//..       DIP("xadd%c %s, %s\n",
+//..           nameISize(sz), nameIReg(sz,gregOfRM(rm)), dis_buf);
+//..       return len+delta0;
+//..    }
+//.. }
+//.. 
+//.. /* Move 16 bits from Ew (ireg or mem) to G (a segment register). */
+//.. 
+//.. static
+//.. UInt dis_mov_Ew_Sw ( UChar sorb, UInt delta0 )
+//.. {
+//..    Int    len;
+//..    IRTemp addr;
+//..    UChar  rm  = getIByte(delta0);
+//..    HChar  dis_buf[50];
+//.. 
+//..    if (epartIsReg(rm)) {
+//..       putSReg( gregOfRM(rm), getIReg(2, eregOfRM(rm)) );
+//..       DIP("movw %s,%s\n", nameIReg(2,eregOfRM(rm)), nameSReg(gregOfRM(rm)));
+//..       return 1+delta0;
+//..    } else {
+//..       addr = disAMode ( &len, sorb, delta0, dis_buf );
+//..       putSReg( gregOfRM(rm), loadLE(Ity_I16, mkexpr(addr)) );
+//..       DIP("movw %s,%s\n", dis_buf, nameSReg(gregOfRM(rm)));
+//..       return len+delta0;
+//..    }
+//.. }
+//.. 
+//.. /* Move 16 bits from G (a segment register) to Ew (ireg or mem).  If
+//..    dst is ireg and sz==4, zero out top half of it.  */
+//.. 
+//.. static
+//.. UInt dis_mov_Sw_Ew ( UChar sorb,
+//..                      Int   sz,
+//..                      UInt  delta0 )
+//.. {
+//..    Int    len;
+//..    IRTemp addr;
+//..    UChar  rm  = getIByte(delta0);
+//..    HChar  dis_buf[50];
+//.. 
+//..    vassert(sz == 2 || sz == 4);
+//.. 
+//..    if (epartIsReg(rm)) {
+//..       if (sz == 4)
+//..          putIReg(4, eregOfRM(rm), unop(Iop_16Uto32, getSReg(gregOfRM(rm))));
+//..       else
+//..          putIReg(2, eregOfRM(rm), getSReg(gregOfRM(rm)));
+//.. 
+//..       DIP("mov %s,%s\n", nameSReg(gregOfRM(rm)), nameIReg(sz,eregOfRM(rm)));
+//..       return 1+delta0;
+//..    } else {
+//..       addr = disAMode ( &len, sorb, delta0, dis_buf );
+//..       storeLE( mkexpr(addr), getSReg(gregOfRM(rm)) );
+//..       DIP("mov %s,%s\n", nameSReg(gregOfRM(rm)), dis_buf);
+//..       return len+delta0;
+//..    }
+//.. }
+//.. 
+//.. 
+//.. static 
+//.. void dis_push_segreg ( UInt sreg, Int sz )
+//.. {
+//..     IRTemp t1 = newTemp(Ity_I16);
+//..     IRTemp ta = newTemp(Ity_I32);
+//..     vassert(sz == 2 || sz == 4);
+//.. 
+//..     assign( t1, getSReg(sreg) );
+//..     assign( ta, binop(Iop_Sub32, getIReg(4, R_ESP), mkU32(sz)) );
+//..     putIReg(4, R_ESP, mkexpr(ta));
+//..     storeLE( mkexpr(ta), mkexpr(t1) );
+//.. 
+//..     DIP("pushw %s\n", nameSReg(sreg));
+//.. }
+//.. 
+//.. static
+//.. void dis_pop_segreg ( UInt sreg, Int sz )
+//.. {
+//..     IRTemp t1 = newTemp(Ity_I16);
+//..     IRTemp ta = newTemp(Ity_I32);
+//..     vassert(sz == 2 || sz == 4);
+//.. 
+//..     assign( ta, getIReg(4, R_ESP) );
+//..     assign( t1, loadLE(Ity_I16, mkexpr(ta)) );
+//.. 
+//..     putIReg(4, R_ESP, binop(Iop_Add32, mkexpr(ta), mkU32(sz)) );
+//..     putSReg( sreg, mkexpr(t1) );
+//..     DIP("pop %s\n", nameSReg(sreg));
+//.. }
+//.. 
+//.. static
+//.. void dis_ret ( UInt d32 )
+//.. {
+//..    IRTemp t1 = newTemp(Ity_I32), t2 = newTemp(Ity_I32);
+//..    assign(t1, getIReg(4,R_ESP));
+//..    assign(t2, loadLE(Ity_I32,mkexpr(t1)));
+//..    putIReg(4, R_ESP,binop(Iop_Add32, mkexpr(t1), mkU32(4+d32)));
+//..    jmp_treg(Ijk_Ret,t2);
+//.. }
+//.. 
+//.. /*------------------------------------------------------------*/
+//.. /*--- SSE/SSE2/SSE3 helpers                                ---*/
+//.. /*------------------------------------------------------------*/
+//.. 
+//.. /* Worker function; do not call directly. 
+//..    Handles full width G = G `op` E   and   G = (not G) `op` E.
+//.. */
+//.. 
+//.. static UInt dis_SSE_E_to_G_all_wrk ( 
+//..                UChar sorb, UInt delta, 
+//..                HChar* opname, IROp op,
+//..                Bool   invertG
+//..             )
+//.. {
+//..    HChar   dis_buf[50];
+//..    Int     alen;
+//..    IRTemp  addr;
+//..    UChar   rm = getIByte(delta);
+//..    IRExpr* gpart
+//..       = invertG ? unop(Iop_Not128, getXMMReg(gregOfRM(rm)))
+//..                 : getXMMReg(gregOfRM(rm));
+//..    if (epartIsReg(rm)) {
+//..       putXMMReg( gregOfRM(rm), 
+//..                  binop(op, gpart,
+//..                            getXMMReg(eregOfRM(rm))) );
+//..       DIP("%s %s,%s\n", opname,
+//..                         nameXMMReg(eregOfRM(rm)),
+//..                         nameXMMReg(gregOfRM(rm)) );
+//..       return delta+1;
+//..    } else {
+//..       addr = disAMode ( &alen, sorb, delta, dis_buf );
+//..       putXMMReg( gregOfRM(rm), 
+//..                  binop(op, gpart,
+//..                            loadLE(Ity_V128, mkexpr(addr))) );
+//..       DIP("%s %s,%s\n", opname,
+//..                         dis_buf,
+//..                         nameXMMReg(gregOfRM(rm)) );
+//..       return delta+alen;
+//..    }
+//.. }
+//.. 
+//.. 
+//.. /* All lanes SSE binary operation, G = G `op` E. */
+//.. 
+//.. static
+//.. UInt dis_SSE_E_to_G_all ( UChar sorb, UInt delta, HChar* opname, IROp op )
+//.. {
+//..    return dis_SSE_E_to_G_all_wrk( sorb, delta, opname, op, False );
+//.. }
+//.. 
+//.. /* All lanes SSE binary operation, G = (not G) `op` E. */
+//.. 
+//.. static
+//.. UInt dis_SSE_E_to_G_all_invG ( UChar sorb, UInt delta, 
+//..                                HChar* opname, IROp op )
+//.. {
+//..    return dis_SSE_E_to_G_all_wrk( sorb, delta, opname, op, True );
+//.. }
+//.. 
+//.. 
+//.. /* Lowest 32-bit lane only SSE binary operation, G = G `op` E. */
+//.. 
+//.. static UInt dis_SSE_E_to_G_lo32 ( UChar sorb, UInt delta, 
+//..                                   HChar* opname, IROp op )
+//.. {
+//..    HChar   dis_buf[50];
+//..    Int     alen;
+//..    IRTemp  addr;
+//..    UChar   rm = getIByte(delta);
+//..    IRExpr* gpart = getXMMReg(gregOfRM(rm));
+//..    if (epartIsReg(rm)) {
+//..       putXMMReg( gregOfRM(rm), 
+//..                  binop(op, gpart,
+//..                            getXMMReg(eregOfRM(rm))) );
+//..       DIP("%s %s,%s\n", opname,
+//..                         nameXMMReg(eregOfRM(rm)),
+//..                         nameXMMReg(gregOfRM(rm)) );
+//..       return delta+1;
+//..    } else {
+//..       /* We can only do a 32-bit memory read, so the upper 3/4 of the
+//..          E operand needs to be made simply of zeroes. */
+//..       IRTemp epart = newTemp(Ity_V128);
+//..       addr = disAMode ( &alen, sorb, delta, dis_buf );
+//..       assign( epart, unop( Iop_32Uto128,
+//..                            loadLE(Ity_I32, mkexpr(addr))) );
+//..       putXMMReg( gregOfRM(rm), 
+//..                  binop(op, gpart, mkexpr(epart)) );
+//..       DIP("%s %s,%s\n", opname,
+//..                         dis_buf,
+//..                         nameXMMReg(gregOfRM(rm)) );
+//..       return delta+alen;
+//..    }
+//.. }
+//.. 
+//.. 
+//.. /* Lower 64-bit lane only SSE binary operation, G = G `op` E. */
+//.. 
+//.. static UInt dis_SSE_E_to_G_lo64 ( UChar sorb, UInt delta, 
+//..                                   HChar* opname, IROp op )
+//.. {
+//..    HChar   dis_buf[50];
+//..    Int     alen;
+//..    IRTemp  addr;
+//..    UChar   rm = getIByte(delta);
+//..    IRExpr* gpart = getXMMReg(gregOfRM(rm));
+//..    if (epartIsReg(rm)) {
+//..       putXMMReg( gregOfRM(rm), 
+//..                  binop(op, gpart,
+//..                            getXMMReg(eregOfRM(rm))) );
+//..       DIP("%s %s,%s\n", opname,
+//..                         nameXMMReg(eregOfRM(rm)),
+//..                         nameXMMReg(gregOfRM(rm)) );
+//..       return delta+1;
+//..    } else {
+//..       /* We can only do a 64-bit memory read, so the upper half of the
+//..          E operand needs to be made simply of zeroes. */
+//..       IRTemp epart = newTemp(Ity_V128);
+//..       addr = disAMode ( &alen, sorb, delta, dis_buf );
+//..       assign( epart, unop( Iop_64Uto128,
+//..                            loadLE(Ity_I64, mkexpr(addr))) );
+//..       putXMMReg( gregOfRM(rm), 
+//..                  binop(op, gpart, mkexpr(epart)) );
+//..       DIP("%s %s,%s\n", opname,
+//..                         dis_buf,
+//..                         nameXMMReg(gregOfRM(rm)) );
+//..       return delta+alen;
+//..    }
+//.. }
+//.. 
+//.. 
+//.. /* All lanes unary SSE operation, G = op(E). */
+//.. 
+//.. static UInt dis_SSE_E_to_G_unary_all ( 
+//..                UChar sorb, UInt delta, 
+//..                HChar* opname, IROp op
+//..             )
+//.. {
+//..    HChar   dis_buf[50];
+//..    Int     alen;
+//..    IRTemp  addr;
+//..    UChar   rm = getIByte(delta);
+//..    if (epartIsReg(rm)) {
+//..       putXMMReg( gregOfRM(rm), 
+//..                  unop(op, getXMMReg(eregOfRM(rm))) );
+//..       DIP("%s %s,%s\n", opname,
+//..                         nameXMMReg(eregOfRM(rm)),
+//..                         nameXMMReg(gregOfRM(rm)) );
+//..       return delta+1;
+//..    } else {
+//..       addr = disAMode ( &alen, sorb, delta, dis_buf );
+//..       putXMMReg( gregOfRM(rm), 
+//..                  unop(op, loadLE(Ity_V128, mkexpr(addr))) );
+//..       DIP("%s %s,%s\n", opname,
+//..                         dis_buf,
+//..                         nameXMMReg(gregOfRM(rm)) );
+//..       return delta+alen;
+//..    }
+//.. }
+//.. 
+//.. 
+//.. /* Lowest 32-bit lane only unary SSE operation, G = op(E). */
+//.. 
+//.. static UInt dis_SSE_E_to_G_unary_lo32 ( 
+//..                UChar sorb, UInt delta, 
+//..                HChar* opname, IROp op
+//..             )
+//.. {
+//..    /* First we need to get the old G value and patch the low 32 bits
+//..       of the E operand into it.  Then apply op and write back to G. */
+//..    HChar   dis_buf[50];
+//..    Int     alen;
+//..    IRTemp  addr;
+//..    UChar   rm = getIByte(delta);
+//..    IRTemp  oldG0 = newTemp(Ity_V128);
+//..    IRTemp  oldG1 = newTemp(Ity_V128);
+//.. 
+//..    assign( oldG0, getXMMReg(gregOfRM(rm)) );
+//.. 
+//..    if (epartIsReg(rm)) {
+//..       assign( oldG1, 
+//..               binop( Iop_Set128lo32,
+//..                      mkexpr(oldG0),
+//..                      getXMMRegLane32(eregOfRM(rm), 0)) );
+//..       putXMMReg( gregOfRM(rm), unop(op, mkexpr(oldG1)) );
+//..       DIP("%s %s,%s\n", opname,
+//..                         nameXMMReg(eregOfRM(rm)),
+//..                         nameXMMReg(gregOfRM(rm)) );
+//..       return delta+1;
+//..    } else {
+//..       addr = disAMode ( &alen, sorb, delta, dis_buf );
+//..       assign( oldG1, 
+//..               binop( Iop_Set128lo32,
+//..                      mkexpr(oldG0),
+//..                      loadLE(Ity_I32, mkexpr(addr)) ));
+//..       putXMMReg( gregOfRM(rm), unop(op, mkexpr(oldG1)) );
+//..       DIP("%s %s,%s\n", opname,
+//..                         dis_buf,
+//..                         nameXMMReg(gregOfRM(rm)) );
+//..       return delta+alen;
+//..    }
+//.. }
+//.. 
+//.. 
+//.. /* Lowest 64-bit lane only unary SSE operation, G = op(E). */
+//.. 
+//.. static UInt dis_SSE_E_to_G_unary_lo64 ( 
+//..                UChar sorb, UInt delta, 
+//..                HChar* opname, IROp op
+//..             )
+//.. {
+//..    /* First we need to get the old G value and patch the low 64 bits
+//..       of the E operand into it.  Then apply op and write back to G. */
+//..    HChar   dis_buf[50];
+//..    Int     alen;
+//..    IRTemp  addr;
+//..    UChar   rm = getIByte(delta);
+//..    IRTemp  oldG0 = newTemp(Ity_V128);
+//..    IRTemp  oldG1 = newTemp(Ity_V128);
+//.. 
+//..    assign( oldG0, getXMMReg(gregOfRM(rm)) );
+//.. 
+//..    if (epartIsReg(rm)) {
+//..       assign( oldG1, 
+//..               binop( Iop_Set128lo64,
+//..                      mkexpr(oldG0),
+//..                      getXMMRegLane64(eregOfRM(rm), 0)) );
+//..       putXMMReg( gregOfRM(rm), unop(op, mkexpr(oldG1)) );
+//..       DIP("%s %s,%s\n", opname,
+//..                         nameXMMReg(eregOfRM(rm)),
+//..                         nameXMMReg(gregOfRM(rm)) );
+//..       return delta+1;
+//..    } else {
+//..       addr = disAMode ( &alen, sorb, delta, dis_buf );
+//..       assign( oldG1, 
+//..               binop( Iop_Set128lo64,
+//..                      mkexpr(oldG0),
+//..                      loadLE(Ity_I64, mkexpr(addr)) ));
+//..       putXMMReg( gregOfRM(rm), unop(op, mkexpr(oldG1)) );
+//..       DIP("%s %s,%s\n", opname,
+//..                         dis_buf,
+//..                         nameXMMReg(gregOfRM(rm)) );
+//..       return delta+alen;
+//..    }
+//.. }
+//.. 
+//.. 
+//.. /* SSE integer binary operation:
+//..       G = G `op` E   (eLeft == False)
+//..       G = E `op` G   (eLeft == True)
+//.. */
+//.. static UInt dis_SSEint_E_to_G( 
+//..                UChar sorb, UInt delta, 
+//..                HChar* opname, IROp op,
+//..                Bool   eLeft
+//..             )
+//.. {
+//..    HChar   dis_buf[50];
+//..    Int     alen;
+//..    IRTemp  addr;
+//..    UChar   rm = getIByte(delta);
+//..    IRExpr* gpart = getXMMReg(gregOfRM(rm));
+//..    IRExpr* epart = NULL;
+//..    if (epartIsReg(rm)) {
+//..       epart = getXMMReg(eregOfRM(rm));
+//..       DIP("%s %s,%s\n", opname,
+//..                         nameXMMReg(eregOfRM(rm)),
+//..                         nameXMMReg(gregOfRM(rm)) );
+//..       delta += 1;
+//..    } else {
+//..       addr  = disAMode ( &alen, sorb, delta, dis_buf );
+//..       epart = loadLE(Ity_V128, mkexpr(addr));
+//..       DIP("%s %s,%s\n", opname,
+//..                         dis_buf,
+//..                         nameXMMReg(gregOfRM(rm)) );
+//..       delta += alen;
+//..    }
+//..    putXMMReg( gregOfRM(rm), 
+//..               eLeft ? binop(op, epart, gpart)
+//..               : binop(op, gpart, epart) );
+//..    return delta;
+//.. }
+//.. 
+//.. 
+//.. /* Helper for doing SSE FP comparisons. */
+//.. 
+//.. static void findSSECmpOp ( Bool* needNot, IROp* op, 
+//..                            Int imm8, Bool all_lanes, Int sz )
+//.. {
+//..    imm8 &= 7;
+//..    *needNot = False;
+//..    *op      = Iop_INVALID;
+//..    if (imm8 >= 4) {
+//..       *needNot = True;
+//..       imm8 -= 4;
+//..    }
+//.. 
+//..    if (sz == 4 && all_lanes) {
+//..       switch (imm8) {
+//..          case 0: *op = Iop_CmpEQ32Fx4; return;
+//..          case 1: *op = Iop_CmpLT32Fx4; return;
+//..          case 2: *op = Iop_CmpLE32Fx4; return;
+//..          case 3: *op = Iop_CmpUN32Fx4; return;
+//..          default: break;
+//..       }
+//..    }
+//..    if (sz == 4 && !all_lanes) {
+//..       switch (imm8) {
+//..          case 0: *op = Iop_CmpEQ32F0x4; return;
+//..          case 1: *op = Iop_CmpLT32F0x4; return;
+//..          case 2: *op = Iop_CmpLE32F0x4; return;
+//..          case 3: *op = Iop_CmpUN32F0x4; return;
+//..          default: break;
+//..       }
+//..    }
+//..    if (sz == 8 && all_lanes) {
+//..       switch (imm8) {
+//..          case 0: *op = Iop_CmpEQ64Fx2; return;
+//..          case 1: *op = Iop_CmpLT64Fx2; return;
+//..          case 2: *op = Iop_CmpLE64Fx2; return;
+//..          case 3: *op = Iop_CmpUN64Fx2; return;
+//..          default: break;
+//..       }
+//..    }
+//..    if (sz == 8 && !all_lanes) {
+//..       switch (imm8) {
+//..          case 0: *op = Iop_CmpEQ64F0x2; return;
+//..          case 1: *op = Iop_CmpLT64F0x2; return;
+//..          case 2: *op = Iop_CmpLE64F0x2; return;
+//..          case 3: *op = Iop_CmpUN64F0x2; return;
+//..          default: break;
+//..       }
+//..    }
+//..    vpanic("findSSECmpOp(x86,guest)");
+//.. }
+//.. 
+//.. /* Handles SSE 32F comparisons. */
+//.. 
+//.. static UInt dis_SSEcmp_E_to_G ( UChar sorb, UInt delta, 
+//..                           HChar* opname, Bool all_lanes, Int sz )
+//.. {
+//..    HChar   dis_buf[50];
+//..    Int     alen, imm8;
+//..    IRTemp  addr;
+//..    Bool    needNot = False;
+//..    IROp    op      = Iop_INVALID;
+//..    IRTemp  plain   = newTemp(Ity_V128);
+//..    UChar   rm      = getIByte(delta);
+//..    UShort  mask    = 0;
+//..    vassert(sz == 4 || sz == 8);
+//..    if (epartIsReg(rm)) {
+//..       imm8 = getIByte(delta+1);
+//..       findSSECmpOp(&needNot, &op, imm8, all_lanes, sz);
+//..       assign( plain, binop(op, getXMMReg(gregOfRM(rm)), 
+//..                                getXMMReg(eregOfRM(rm))) );
+//..       delta += 2;
+//..       DIP("%s $%d,%s,%s\n", opname,
+//..                             (Int)imm8,
+//..                             nameXMMReg(eregOfRM(rm)),
+//..                             nameXMMReg(gregOfRM(rm)) );
+//..    } else {
+//..       addr = disAMode ( &alen, sorb, delta, dis_buf );
+//..       imm8 = getIByte(delta+alen);
+//..       findSSECmpOp(&needNot, &op, imm8, all_lanes, sz);
+//..       assign( plain, binop(op, getXMMReg(gregOfRM(rm)), 
+//..                                loadLE(Ity_V128, mkexpr(addr))) );
+//..       delta += alen+1;
+//..       DIP("%s $%d,%s,%s\n", opname,
+//..                             (Int)imm8,
+//..                             dis_buf,
+//..                             nameXMMReg(gregOfRM(rm)) );
+//..    }
+//.. 
+//..    if (needNot && all_lanes) {
+//..       putXMMReg( gregOfRM(rm), 
+//..                  unop(Iop_Not128, mkexpr(plain)) );
+//..    }
+//..    else
+//..    if (needNot && !all_lanes) {
+//..       mask = sz==4 ? 0x000F : 0x00FF;
+//..       putXMMReg( gregOfRM(rm), 
+//..                  binop(Iop_Xor128, mkexpr(plain), mkV128(mask)) );
+//..    }
+//..    else {
+//..       putXMMReg( gregOfRM(rm), mkexpr(plain) );
+//..    }
+//.. 
+//..    return delta;
+//.. }
+//.. 
+//.. 
+//.. /* Vector by scalar shift of G by the amount specified at the bottom
+//..    of E. */
+//.. 
+//.. static UInt dis_SSE_shiftG_byE ( UChar sorb, UInt delta, 
+//..                                  HChar* opname, IROp op )
+//.. {
+//..    HChar   dis_buf[50];
+//..    Int     alen, size;
+//..    IRTemp  addr;
+//..    Bool    shl, shr, sar;
+//..    UChar   rm   = getIByte(delta);
+//..    IRTemp  g0   = newTemp(Ity_V128);
+//..    IRTemp  g1   = newTemp(Ity_V128);
+//..    IRTemp  amt  = newTemp(Ity_I32);
+//..    IRTemp  amt8 = newTemp(Ity_I8);
+//..    if (epartIsReg(rm)) {
+//..       assign( amt, getXMMRegLane32(eregOfRM(rm), 0) );
+//..       DIP("%s %s,%s\n", opname,
+//..                         nameXMMReg(eregOfRM(rm)),
+//..                         nameXMMReg(gregOfRM(rm)) );
+//..       delta++;
+//..    } else {
+//..       addr = disAMode ( &alen, sorb, delta, dis_buf );
+//..       assign( amt, loadLE(Ity_I32, mkexpr(addr)) );
+//..       DIP("%s %s,%s\n", opname,
+//..                         dis_buf,
+//..                         nameXMMReg(gregOfRM(rm)) );
+//..       delta += alen;
+//..    }
+//..    assign( g0,   getXMMReg(gregOfRM(rm)) );
+//..    assign( amt8, unop(Iop_32to8, mkexpr(amt)) );
+//.. 
+//..    shl = shr = sar = False;
+//..    size = 0;
+//..    switch (op) {
+//..       case Iop_ShlN16x8: shl = True; size = 32; break;
+//..       case Iop_ShlN32x4: shl = True; size = 32; break;
+//..       case Iop_ShlN64x2: shl = True; size = 64; break;
+//..       case Iop_SarN16x8: sar = True; size = 16; break;
+//..       case Iop_SarN32x4: sar = True; size = 32; break;
+//..       case Iop_ShrN16x8: shr = True; size = 16; break;
+//..       case Iop_ShrN32x4: shr = True; size = 32; break;
+//..       case Iop_ShrN64x2: shr = True; size = 64; break;
+//..       default: vassert(0);
+//..    }
+//.. 
+//..    if (shl || shr) {
+//..      assign( 
+//..         g1,
+//..         IRExpr_Mux0X(
+//..            unop(Iop_1Uto8,binop(Iop_CmpLT32U,mkexpr(amt),mkU32(size))),
+//..            mkV128(0x0000),
+//..            binop(op, mkexpr(g0), mkexpr(amt8))
+//..         )
+//..      );
+//..    } else 
+//..    if (sar) {
+//..      assign( 
+//..         g1,
+//..         IRExpr_Mux0X(
+//..            unop(Iop_1Uto8,binop(Iop_CmpLT32U,mkexpr(amt),mkU32(size))),
+//..            binop(op, mkexpr(g0), mkU8(size-1)),
+//..            binop(op, mkexpr(g0), mkexpr(amt8))
+//..         )
+//..      );
+//..    } else {
+//..       vassert(0);
+//..    }
+//.. 
+//..    putXMMReg( gregOfRM(rm), mkexpr(g1) );
+//..    return delta;
+//.. }
+//.. 
+//.. 
+//.. /* Vector by scalar shift of E by an immediate byte. */
+//.. 
+//.. static 
+//.. UInt dis_SSE_shiftE_imm ( UInt delta, HChar* opname, IROp op )
+//.. {
+//..    Bool    shl, shr, sar;
+//..    UChar   rm   = getIByte(delta);
+//..    IRTemp  e0   = newTemp(Ity_V128);
+//..    IRTemp  e1   = newTemp(Ity_V128);
+//..    UChar   amt, size;
+//..    vassert(epartIsReg(rm));
+//..    vassert(gregOfRM(rm) == 2 
+//..            || gregOfRM(rm) == 4 || gregOfRM(rm) == 6);
+//..    amt = (Int)(getIByte(delta+1));
+//..    delta += 2;
+//..    DIP("%s $%d,%s\n", opname,
+//..                       (Int)amt,
+//..                       nameXMMReg(eregOfRM(rm)) );
+//..    assign( e0, getXMMReg(eregOfRM(rm)) );
+//.. 
+//..    shl = shr = sar = False;
+//..    size = 0;
+//..    switch (op) {
+//..       case Iop_ShlN16x8: shl = True; size = 16; break;
+//..       case Iop_ShlN32x4: shl = True; size = 32; break;
+//..       case Iop_ShlN64x2: shl = True; size = 64; break;
+//..       case Iop_SarN16x8: sar = True; size = 16; break;
+//..       case Iop_SarN32x4: sar = True; size = 32; break;
+//..       case Iop_ShrN16x8: shr = True; size = 16; break;
+//..       case Iop_ShrN32x4: shr = True; size = 32; break;
+//..       case Iop_ShrN64x2: shr = True; size = 64; break;
+//..       default: vassert(0);
+//..    }
+//.. 
+//..    if (shl || shr) {
+//..      assign( e1, amt >= size 
+//..                     ? mkV128(0x0000)
+//..                     : binop(op, mkexpr(e0), mkU8(amt))
+//..      );
+//..    } else 
+//..    if (sar) {
+//..      assign( e1, amt >= size 
+//..                     ? binop(op, mkexpr(e0), mkU8(size-1))
+//..                     : binop(op, mkexpr(e0), mkU8(amt))
+//..      );
+//..    } else {
+//..       vassert(0);
+//..    }
+//.. 
+//..    putXMMReg( eregOfRM(rm), mkexpr(e1) );
+//..    return delta;
+//.. }
+//.. 
+//.. 
+//.. /* Get the current SSE rounding mode. */
+//.. 
+//.. static IRExpr* /* :: Ity_I32 */ get_sse_roundingmode ( void )
+//.. {
+//..    return binop( Iop_And32, 
+//..                  IRExpr_Get( OFFB_SSEROUND, Ity_I32 ), 
+//..                  mkU32(3) );
+//.. }
+//.. 
+//.. static void put_sse_roundingmode ( IRExpr* sseround )
+//.. {
+//..    vassert(typeOfIRExpr(irbb->tyenv, sseround) == Ity_I32);
+//..    stmt( IRStmt_Put( OFFB_SSEROUND, sseround ) );
+//.. }
+//.. 
+//.. /* Break a 128-bit value up into four 32-bit ints. */
+//.. 
+//.. static void breakup128to32s ( IRTemp t128,
+//..                         /*OUTs*/
+//..                               IRTemp* t3, IRTemp* t2,
+//..                               IRTemp* t1, IRTemp* t0 )
+//.. {
+//..    IRTemp hi64 = newTemp(Ity_I64);
+//..    IRTemp lo64 = newTemp(Ity_I64);
+//..    assign( hi64, unop(Iop_128HIto64, mkexpr(t128)) );
+//..    assign( lo64, unop(Iop_128to64,   mkexpr(t128)) );
+//.. 
+//..    vassert(t0 && *t0 == IRTemp_INVALID);
+//..    vassert(t1 && *t1 == IRTemp_INVALID);
+//..    vassert(t2 && *t2 == IRTemp_INVALID);
+//..    vassert(t3 && *t3 == IRTemp_INVALID);
+//.. 
+//..    *t0 = newTemp(Ity_I32);
+//..    *t1 = newTemp(Ity_I32);
+//..    *t2 = newTemp(Ity_I32);
+//..    *t3 = newTemp(Ity_I32);
+//..    assign( *t0, unop(Iop_64to32,   mkexpr(lo64)) );
+//..    assign( *t1, unop(Iop_64HIto32, mkexpr(lo64)) );
+//..    assign( *t2, unop(Iop_64to32,   mkexpr(hi64)) );
+//..    assign( *t3, unop(Iop_64HIto32, mkexpr(hi64)) );
+//.. }
+//.. 
+//.. /* Construct a 128-bit value from four 32-bit ints. */
+//.. 
+//.. static IRExpr* mk128from32s ( IRTemp t3, IRTemp t2,
+//..                               IRTemp t1, IRTemp t0 )
+//.. {
+//..    return
+//..       binop( Iop_64HLto128,
+//..              binop(Iop_32HLto64, mkexpr(t3), mkexpr(t2)),
+//..              binop(Iop_32HLto64, mkexpr(t1), mkexpr(t0))
+//..    );
+//.. }
+//.. 
+//.. /* Break a 64-bit value up into four 16-bit ints. */
+//.. 
+//.. static void breakup64to16s ( IRTemp t64,
+//..                              /*OUTs*/
+//..                              IRTemp* t3, IRTemp* t2,
+//..                              IRTemp* t1, IRTemp* t0 )
+//.. {
+//..    IRTemp hi32 = newTemp(Ity_I32);
+//..    IRTemp lo32 = newTemp(Ity_I32);
+//..    assign( hi32, unop(Iop_64HIto32, mkexpr(t64)) );
+//..    assign( lo32, unop(Iop_64to32,   mkexpr(t64)) );
+//.. 
+//..    vassert(t0 && *t0 == IRTemp_INVALID);
+//..    vassert(t1 && *t1 == IRTemp_INVALID);
+//..    vassert(t2 && *t2 == IRTemp_INVALID);
+//..    vassert(t3 && *t3 == IRTemp_INVALID);
+//.. 
+//..    *t0 = newTemp(Ity_I16);
+//..    *t1 = newTemp(Ity_I16);
+//..    *t2 = newTemp(Ity_I16);
+//..    *t3 = newTemp(Ity_I16);
+//..    assign( *t0, unop(Iop_32to16,   mkexpr(lo32)) );
+//..    assign( *t1, unop(Iop_32HIto16, mkexpr(lo32)) );
+//..    assign( *t2, unop(Iop_32to16,   mkexpr(hi32)) );
+//..    assign( *t3, unop(Iop_32HIto16, mkexpr(hi32)) );
+//.. }
+//.. 
+//.. /* Construct a 64-bit value from four 16-bit ints. */
+//.. 
+//.. static IRExpr* mk64from16s ( IRTemp t3, IRTemp t2,
+//..                              IRTemp t1, IRTemp t0 )
+//.. {
+//..    return
+//..       binop( Iop_32HLto64,
+//..              binop(Iop_16HLto32, mkexpr(t3), mkexpr(t2)),
+//..              binop(Iop_16HLto32, mkexpr(t1), mkexpr(t0))
+//..    );
+//.. }
+//.. 
+//.. 
+//.. /*------------------------------------------------------------*/
+//.. /*--- Disassemble a single instruction                     ---*/
+//.. /*------------------------------------------------------------*/
+//.. 
+//.. /* Disassemble a single instruction into IR.  The instruction
+//..    is located in host memory at &guest_code[delta].
+//..    Set *size to be the size of the instruction.
+//..    If the returned value is Dis_Resteer,
+//..    the next guest address is assigned to *whereNext.  If resteerOK
+//..    is False, disInstr may not return Dis_Resteer. */
+//..    
+//.. static 
+//.. DisResult disInstr ( /*IN*/  Bool       resteerOK,
+//..                      /*IN*/  Bool       (*resteerOkFn) ( Addr64 ),
+//..                      /*IN*/  UInt       delta, 
+//..                      /*IN*/  VexSubArch subarch,
+//..                      /*OUT*/ UInt*      size,
+//..                      /*OUT*/ Addr64*    whereNext )
+//.. {
+//..    IRType    ty;
+//..    IRTemp    addr, t0, t1, t2, t3, t4, t5, t6;
+//..    Int       alen;
+//..    UChar     opc, modrm, abyte;
+//..    UInt      d32;
+//..    HChar     dis_buf[50];
+//..    Int       am_sz, d_sz;
+//..    DisResult whatNext = Dis_Continue;
+//..    UChar*    insn; /* used in SSE decoders */
+//.. 
+//..    /* Holds eip at the start of the insn, so that we can print
+//..       consistent error messages for unimplemented insns. */
+//..    UInt delta_start = delta;
+//.. 
+//..    /* sz denotes the nominal data-op size of the insn; we change it to
+//..       2 if an 0x66 prefix is seen */
+//..    Int sz = 4;
+//.. 
+//..    /* sorb holds the segment-override-prefix byte, if any.  Zero if no
+//..       prefix has been seen, else one of {0x26, 0x3E, 0x64, 0x65}
+//..       indicating the prefix.  */
+//..    UChar sorb = 0;
+//.. 
+//..    /* If we don't set *size properly, this causes bbToIR_X86Instr to
+//..       assert. */
+//..    *size = 0;
+//.. 
+//..    addr = t0 = t1 = t2 = t3 = t4 = t5 = t6 = IRTemp_INVALID; 
+//.. 
+//..    DIP("\t0x%x:  ", guest_eip_bbstart+delta);
+//.. 
+//..    /* Spot the client-request magic sequence. */
+//..    {
+//..       UChar* code = (UChar*)(guest_code + delta);
+//..       /* Spot this:
+//..          C1C01D                roll $29, %eax
+//..          C1C003                roll $3,  %eax
+//..          C1C81B                rorl $27, %eax
+//..          C1C805                rorl $5,  %eax
+//..          C1C00D                roll $13, %eax
+//..          C1C013                roll $19, %eax      
+//..       */
+//..       if (code[ 0] == 0xC1 && code[ 1] == 0xC0 && code[ 2] == 0x1D &&
+//..           code[ 3] == 0xC1 && code[ 4] == 0xC0 && code[ 5] == 0x03 &&
+//..           code[ 6] == 0xC1 && code[ 7] == 0xC8 && code[ 8] == 0x1B &&
+//..           code[ 9] == 0xC1 && code[10] == 0xC8 && code[11] == 0x05 &&
+//..           code[12] == 0xC1 && code[13] == 0xC0 && code[14] == 0x0D &&
+//..           code[15] == 0xC1 && code[16] == 0xC0 && code[17] == 0x13
+//..          ) {
+//..          DIP("%%edx = client_request ( %%eax )\n");         
+//..          delta += 18;
+//..          jmp_lit(Ijk_ClientReq, guest_eip_bbstart+delta);
+//..          whatNext = Dis_StopHere;
+//..          goto decode_success;
+//..       }
+//..    }
+//.. 
+//..    /* Skip a LOCK prefix. */
+//..    /* 2005 Jan 06: the following insns are observed to sometimes
+//..       have a LOCK prefix:
+//..          cmpxchgl %ecx,(%edx)
+//..          cmpxchgl %edx,0x278(%ebx) etc
+//..          xchgl %eax, (%ecx)
+//..          xaddl %eax, (%ecx)
+//..       We need to catch any such which appear to be being used as
+//..       a memory barrier, for example  lock addl $0,0(%esp)
+//..       and emit an IR MFence construct.
+//..    */
+//..    if (getIByte(delta) == 0xF0) {
+//.. 
+//..       UChar* code = (UChar*)(guest_code + delta);
+//.. 
+//..       /* Various bits of kernel headers use the following as a memory
+//..          barrier.  Hence, first emit an MFence and then let the insn
+//..          go through as usual. */
+//..       /* F08344240000:  lock addl $0, 0(%esp) */
+//..       if (code[0] == 0xF0 && code[1] == 0x83 && code[2] == 0x44 && 
+//..           code[3] == 0x24 && code[4] == 0x00 && code[5] == 0x00) {
+//..          stmt( IRStmt_MFence() );
+//..       }
+//..       else
+//..       if (0) {
+//..          vex_printf("vex x86->IR: ignoring LOCK prefix on: ");
+//..          insn_verbose = True;
+//..       }
+//.. 
+//..       /* In any case, skip the prefix. */
+//..       delta++;
+//..    }
+//.. 
+//..    /* Detect operand-size overrides. */
+//..    if (getIByte(delta) == 0x66) { sz = 2; delta++; };
+//.. 
+//..    /* segment override prefixes come after the operand-size override,
+//..       it seems */
+//..    switch (getIByte(delta)) {
+//..       case 0x3E: /* %DS: */
+//..       case 0x26: /* %ES: */
+//..       case 0x64: /* %FS: */
+//..       case 0x65: /* %GS: */
+//..          sorb = getIByte(delta); delta++; 
+//..          break;
+//..       case 0x2E: /* %CS: */
+//..          /* 2E prefix on a conditional branch instruction is a
+//..             branch-prediction hint, which can safely be ignored.  */
+//..          {
+//..             UChar op1 = getIByte(delta+1);
+//..             UChar op2 = getIByte(delta+2);
+//..             if ((op1 >= 0x70 && op1 <= 0x7F)
+//..                 || (op1 == 0xE3)
+//..                 || (op1 == 0x0F && op2 >= 0x80 && op2 <= 0x8F)) {
+//..                vex_printf("vex x86->IR: ignoring branch hint\n");
+//..                sorb = getIByte(delta); delta++;
+//..                break;
+//..             }
+//..          }
+//..          unimplemented("x86 segment override (SEG=CS) prefix");
+//..          /*NOTREACHED*/
+//..          break;
+//..       case 0x36: /* %SS: */
+//..          unimplemented("x86 segment override (SEG=SS) prefix");
+//..          /*NOTREACHED*/
+//..          break;
+//..       default:
+//..          break;
+//..    }
+//.. 
+//..    /* ---------------------------------------------------- */
+//..    /* --- The SSE decoder.                             --- */
+//..    /* ---------------------------------------------------- */
+//.. 
+//..    /* What did I do to deserve SSE ?  Perhaps I was really bad in a
+//..       previous life? */
+//.. 
+//..    /* Note, this doesn't handle SSE2 or SSE3.  That is handled in a
+//..       later section, further on. */
+//.. 
+//..    insn = (UChar*)&guest_code[delta];
+//.. 
+//..    /* Treat fxsave specially.  It should be doable even on an SSE0
+//..       (Pentium-II class) CPU.  Hence be prepared to handle it on
+//..       any subarchitecture variant.
+//..    */
+//.. 
+//..    /* 0F AE /0 = FXSAVE m512 -- write x87 and SSE state to memory */
+//..    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0xAE
+//..        && !epartIsReg(insn[2]) && gregOfRM(insn[2]) == 0) {
+//..       modrm = getIByte(delta+2);
+//..       vassert(sz == 4);
+//..       vassert(!epartIsReg(modrm));
+//.. 
+//..       addr = disAMode ( &alen, sorb, delta+2, dis_buf );
+//..       delta += 2+alen;
+//.. 
+//..       DIP("fxsave %s\n", dis_buf);
+//.. 
+//..       /* Uses dirty helper: 
+//..             void x86g_do_FXSAVE ( VexGuestX86State*, UInt ) */
+//..       IRDirty* d = unsafeIRDirty_0_N ( 
+//..                       0/*regparms*/, 
+//..                       "x86g_dirtyhelper_FXSAVE", 
+//..                       &x86g_dirtyhelper_FXSAVE,
+//..                       mkIRExprVec_1( mkexpr(addr) )
+//..                    );
+//..       d->needsBBP = True;
+//.. 
+//..       /* declare we're writing memory */
+//..       d->mFx   = Ifx_Write;
+//..       d->mAddr = mkexpr(addr);
+//..       d->mSize = 512;
+//.. 
+//..       /* declare we're reading guest state */
+//..       d->nFxState = 7;
+//.. 
+//..       d->fxState[0].fx     = Ifx_Read;
+//..       d->fxState[0].offset = OFFB_FTOP;
+//..       d->fxState[0].size   = sizeof(UInt);
+//.. 
+//..       d->fxState[1].fx     = Ifx_Read;
+//..       d->fxState[1].offset = OFFB_FPREGS;
+//..       d->fxState[1].size   = 8 * sizeof(ULong);
+//.. 
+//..       d->fxState[2].fx     = Ifx_Read;
+//..       d->fxState[2].offset = OFFB_FPTAGS;
+//..       d->fxState[2].size   = 8 * sizeof(UChar);
+//.. 
+//..       d->fxState[3].fx     = Ifx_Read;
+//..       d->fxState[3].offset = OFFB_FPROUND;
+//..       d->fxState[3].size   = sizeof(UInt);
+//.. 
+//..       d->fxState[4].fx     = Ifx_Read;
+//..       d->fxState[4].offset = OFFB_FC3210;
+//..       d->fxState[4].size   = sizeof(UInt);
+//.. 
+//..       d->fxState[5].fx     = Ifx_Read;
+//..       d->fxState[5].offset = OFFB_XMM0;
+//..       d->fxState[5].size   = 8 * sizeof(U128);
+//.. 
+//..       d->fxState[6].fx     = Ifx_Read;
+//..       d->fxState[6].offset = OFFB_SSEROUND;
+//..       d->fxState[6].size   = sizeof(UInt);
+//.. 
+//..       /* Be paranoid ... this assertion tries to ensure the 8 %xmm
+//..    images are packed back-to-back.  If not, the value of
+//..    d->fxState[5].size is wrong. */
+//..       vassert(16 == sizeof(U128));
+//..       vassert(OFFB_XMM7 == (OFFB_XMM0 + 7 * 16));
+//.. 
+//..       stmt( IRStmt_Dirty(d) );
+//.. 
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* ------ SSE decoder main ------ */
+//.. 
+//..    /* Skip parts of the decoder which don't apply given the stated
+//..       guest subarchitecture. */
+//..    if (subarch == VexSubArchX86_sse0)
+//..       goto after_sse_decoders;
+//..    
+//..    /* Otherwise we must be doing sse1 or sse2, so we can at least try
+//..       for SSE1 here. */
+//.. 
+//..    /* 0F 58 = ADDPS -- add 32Fx4 from R/M to R */
+//..    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0x58) {
+//..       delta = dis_SSE_E_to_G_all( sorb, delta+2, "addps", Iop_Add32Fx4 );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* F3 0F 58 = ADDSS -- add 32F0x4 from R/M to R */
+//..    if (insn[0] == 0xF3 && insn[1] == 0x0F && insn[2] == 0x58) {
+//..       vassert(sz == 4);
+//..       delta = dis_SSE_E_to_G_lo32( sorb, delta+3, "addss", Iop_Add32F0x4 );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 0F 55 = ANDNPS -- G = (not G) and E */
+//..    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0x55) {
+//..       delta = dis_SSE_E_to_G_all_invG( sorb, delta+2, "andnps", Iop_And128 );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 0F 54 = ANDPS -- G = G and E */
+//..    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0x54) {
+//..       delta = dis_SSE_E_to_G_all( sorb, delta+2, "andps", Iop_And128 );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 0F C2 = CMPPS -- 32Fx4 comparison from R/M to R */
+//..    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0xC2) {
+//..       delta = dis_SSEcmp_E_to_G( sorb, delta+2, "cmpps", True, 4 );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* F3 0F C2 = CMPSS -- 32F0x4 comparison from R/M to R */
+//..    if (insn[0] == 0xF3 && insn[1] == 0x0F && insn[2] == 0xC2) {
+//..       vassert(sz == 4);
+//..       delta = dis_SSEcmp_E_to_G( sorb, delta+3, "cmpss", False, 4 );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 0F 2F = COMISS  -- 32F0x4 comparison G,E, and set ZCP */
+//..    /* 0F 2E = UCOMISS -- 32F0x4 comparison G,E, and set ZCP */
+//..    if (sz == 4 && insn[0] == 0x0F && (insn[1] == 0x2F || insn[1] == 0x2E)) {
+//..       IRTemp argL = newTemp(Ity_F32);
+//..       IRTemp argR = newTemp(Ity_F32);
+//..       modrm = getIByte(delta+2);
+//..       if (epartIsReg(modrm)) {
+//..          assign( argR, getXMMRegLane32F( eregOfRM(modrm), 0/*lowest lane*/ ) );
+//..          delta += 2+1;
+//..          DIP("[u]comiss %s,%s\n", nameXMMReg(eregOfRM(modrm)),
+//..                                   nameXMMReg(gregOfRM(modrm)) );
+//..       } else {
+//..          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
+//..    assign( argR, loadLE(Ity_F32, mkexpr(addr)) );
+//..          delta += 2+alen;
+//..          DIP("[u]comiss %s,%s\n", dis_buf,
+//..                                   nameXMMReg(gregOfRM(modrm)) );
+//..       }
+//..       assign( argL, getXMMRegLane32F( gregOfRM(modrm), 0/*lowest lane*/ ) );
+//.. 
+//..       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_CmpF64, 
+//..                             unop(Iop_F32toF64,mkexpr(argL)),
+//..                             unop(Iop_F32toF64,mkexpr(argR))),
+//..                       mkU32(0x45)
+//..           )));
+//.. 
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 0F 2A = CVTPI2PS -- convert 2 x I32 in mem/mmx to 2 x F32 in low
+//..       half xmm */
+//..    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0x2A) {
+//..       IRTemp arg64 = newTemp(Ity_I64);
+//..       IRTemp rmode = newTemp(Ity_I32);
+//..       vassert(sz == 4);
+//.. 
+//..       modrm = getIByte(delta+2);
+//..       do_MMX_preamble();
+//..       if (epartIsReg(modrm)) {
+//..          assign( arg64, getMMXReg(eregOfRM(modrm)) );
+//..          delta += 2+1;
+//..          DIP("cvtpi2ps %s,%s\n", nameMMXReg(eregOfRM(modrm)),
+//..                                  nameXMMReg(gregOfRM(modrm)));
+//..       } else {
+//..          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
+//..    assign( arg64, loadLE(Ity_I64, mkexpr(addr)) );
+//..          delta += 2+alen;
+//..          DIP("cvtpi2ps %s,%s\n", dis_buf,
+//..                                  nameXMMReg(gregOfRM(modrm)) );
+//..       }
+//.. 
+//..       assign( rmode, get_sse_roundingmode() );
+//.. 
+//..       putXMMRegLane32F( 
+//..          gregOfRM(modrm), 0,
+//..          binop(Iop_F64toF32, 
+//..                mkexpr(rmode),
+//..                unop(Iop_I32toF64, 
+//..                     unop(Iop_64to32, mkexpr(arg64)) )) );
+//.. 
+//..       putXMMRegLane32F(
+//..          gregOfRM(modrm), 1, 
+//..          binop(Iop_F64toF32, 
+//..                mkexpr(rmode),
+//..                unop(Iop_I32toF64,
+//..                     unop(Iop_64HIto32, mkexpr(arg64)) )) );
+//.. 
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* F3 0F 2A = CVTSI2SS -- convert I32 in mem/ireg to F32 in low
+//..       quarter xmm */
+//..    if (insn[0] == 0xF3 && insn[1] == 0x0F && insn[2] == 0x2A) {
+//..       IRTemp arg32 = newTemp(Ity_I32);
+//..       IRTemp rmode = newTemp(Ity_I32);
+//..       vassert(sz == 4);
+//.. 
+//..       modrm = getIByte(delta+3);
+//..       if (epartIsReg(modrm)) {
+//..          assign( arg32, getIReg(4, eregOfRM(modrm)) );
+//..          delta += 3+1;
+//..          DIP("cvtsi2ss %s,%s\n", nameIReg(4, eregOfRM(modrm)),
+//..                                  nameXMMReg(gregOfRM(modrm)));
+//..       } else {
+//..          addr = disAMode ( &alen, sorb, delta+3, dis_buf );
+//..    assign( arg32, loadLE(Ity_I32, mkexpr(addr)) );
+//..          delta += 3+alen;
+//..          DIP("cvtsi2ss %s,%s\n", dis_buf,
+//..                                  nameXMMReg(gregOfRM(modrm)) );
+//..       }
+//.. 
+//..       assign( rmode, get_sse_roundingmode() );
+//.. 
+//..       putXMMRegLane32F( 
+//..          gregOfRM(modrm), 0,
+//..          binop(Iop_F64toF32,
+//..                mkexpr(rmode),
+//..                unop(Iop_I32toF64, mkexpr(arg32)) ) );
+//.. 
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 0F 2D = CVTPS2PI -- convert 2 x F32 in mem/low half xmm to 2 x
+//..       I32 in mmx, according to prevailing SSE rounding mode */
+//..    /* 0F 2C = CVTTPS2PI -- convert 2 x F32 in mem/low half xmm to 2 x
+//..       I32 in mmx, rounding towards zero */
+//..    if (sz == 4 && insn[0] == 0x0F && (insn[1] == 0x2D || insn[1] == 0x2C)) {
+//..       IRTemp dst64  = newTemp(Ity_I64);
+//..       IRTemp rmode  = newTemp(Ity_I32);
+//..       IRTemp f32lo  = newTemp(Ity_F32);
+//..       IRTemp f32hi  = newTemp(Ity_F32);
+//..       Bool   r2zero = insn[1] == 0x2C;
+//.. 
+//..       do_MMX_preamble();
+//..       modrm = getIByte(delta+2);
+//.. 
+//..       if (epartIsReg(modrm)) {
+//..          delta += 2+1;
+//..    assign(f32lo, getXMMRegLane32F(eregOfRM(modrm), 0));
+//..    assign(f32hi, getXMMRegLane32F(eregOfRM(modrm), 1));
+//..          DIP("cvt%sps2pi %s,%s\n", r2zero ? "t" : "",
+//..                                    nameXMMReg(eregOfRM(modrm)),
+//..                                    nameMMXReg(gregOfRM(modrm)));
+//..       } else {
+//..          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
+//..    assign(f32lo, loadLE(Ity_F32, mkexpr(addr)));
+//..    assign(f32hi, loadLE(Ity_F32, binop( Iop_Add32, 
+//..                                               mkexpr(addr), 
+//..                                               mkU32(4) )));
+//..          delta += 2+alen;
+//..          DIP("cvt%sps2pi %s,%s\n", r2zero ? "t" : "",
+//..                                    dis_buf,
+//..                                    nameMMXReg(gregOfRM(modrm)));
+//..       }
+//.. 
+//..       if (r2zero) {
+//..          assign(rmode, mkU32((UInt)Irrm_ZERO) );
+//..       } else {
+//..          assign( rmode, get_sse_roundingmode() );
+//..       }
+//.. 
+//..       assign( 
+//..          dst64,
+//..          binop( Iop_32HLto64,
+//..                 binop( Iop_F64toI32, 
+//..                        mkexpr(rmode), 
+//..                        unop( Iop_F32toF64, mkexpr(f32hi) ) ),
+//..                 binop( Iop_F64toI32, 
+//..                        mkexpr(rmode), 
+//..                        unop( Iop_F32toF64, mkexpr(f32lo) ) )
+//..               )
+//..       );
+//.. 
+//..       putMMXReg(gregOfRM(modrm), mkexpr(dst64));
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* F3 0F 2D = CVTSS2SI -- convert F32 in mem/low quarter xmm to
+//..       I32 in ireg, according to prevailing SSE rounding mode */
+//..    /* F3 0F 2C = CVTTSS2SI -- convert F32 in mem/low quarter xmm to
+//..       I32 in ireg, according to prevailing SSE rounding mode */
+//..    if (insn[0] == 0xF3 && insn[1] == 0x0F 
+//..        && (insn[2] == 0x2D || insn[2] == 0x2C)) {
+//..       IRTemp rmode = newTemp(Ity_I32);
+//..       IRTemp f32lo = newTemp(Ity_F32);
+//..       Bool   r2zero = insn[2] == 0x2C;
+//..       vassert(sz == 4);
+//.. 
+//..       modrm = getIByte(delta+3);
+//..       if (epartIsReg(modrm)) {
+//..          delta += 3+1;
+//..    assign(f32lo, getXMMRegLane32F(eregOfRM(modrm), 0));
+//..          DIP("cvt%sss2si %s,%s\n", r2zero ? "t" : "",
+//..                                    nameXMMReg(eregOfRM(modrm)),
+//..                                    nameIReg(4, gregOfRM(modrm)));
+//..       } else {
+//..          addr = disAMode ( &alen, sorb, delta+3, dis_buf );
+//..    assign(f32lo, loadLE(Ity_F32, mkexpr(addr)));
+//..          delta += 3+alen;
+//..          DIP("cvt%sss2si %s,%s\n", r2zero ? "t" : "",
+//..                                    dis_buf,
+//..                                    nameIReg(4, gregOfRM(modrm)));
+//..       }
+//.. 
+//..       if (r2zero) {
+//..          assign( rmode, mkU32((UInt)Irrm_ZERO) );
+//..       } else {
+//..          assign( rmode, get_sse_roundingmode() );
+//..       }
+//.. 
+//..       putIReg(4, gregOfRM(modrm),
+//..                  binop( Iop_F64toI32, 
+//..                         mkexpr(rmode), 
+//..                         unop( Iop_F32toF64, mkexpr(f32lo) ) )
+//..       );
+//.. 
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 0F 5E = DIVPS -- div 32Fx4 from R/M to R */
+//..    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0x5E) {
+//..       delta = dis_SSE_E_to_G_all( sorb, delta+2, "divps", Iop_Div32Fx4 );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* F3 0F 5E = DIVSS -- div 32F0x4 from R/M to R */
+//..    if (insn[0] == 0xF3 && insn[1] == 0x0F && insn[2] == 0x5E) {
+//..       vassert(sz == 4);
+//..       delta = dis_SSE_E_to_G_lo32( sorb, delta+3, "divss", Iop_Div32F0x4 );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 0F AE /2 = LDMXCSR m32 -- load %mxcsr */
+//..    if (insn[0] == 0x0F && insn[1] == 0xAE
+//..        && !epartIsReg(insn[2]) && gregOfRM(insn[2]) == 2) {
+//.. 
+//..       IRTemp t64 = newTemp(Ity_I64);
+//..       IRTemp ew = newTemp(Ity_I32);
+//.. 
+//..       modrm = getIByte(delta+2);
+//..       vassert(!epartIsReg(modrm));
+//..       vassert(sz == 4);
+//.. 
+//..       addr = disAMode ( &alen, sorb, delta+2, dis_buf );
+//..       delta += 2+alen;
+//..       DIP("ldmxcsr %s\n", dis_buf);
+//.. 
+//..       /* The only thing we observe in %mxcsr is the rounding mode.
+//..          Therefore, pass the 32-bit value (SSE native-format control
+//..          word) to a clean helper, getting back a 64-bit value, the
+//..          lower half of which is the SSEROUND value to store, and the
+//..          upper half of which is the emulation-warning token which may
+//..          be generated.  
+//..       */
+//..       /* ULong x86h_check_ldmxcsr ( UInt ); */
+//..       assign( t64, mkIRExprCCall(
+//..                       Ity_I64, 0/*regparms*/, 
+//..                       "x86g_check_ldmxcsr",
+//..                       &x86g_check_ldmxcsr, 
+//..                       mkIRExprVec_1( loadLE(Ity_I32, mkexpr(addr)) )
+//..                    )
+//..             );
+//.. 
+//..       put_sse_roundingmode( unop(Iop_64to32, mkexpr(t64)) );
+//..       assign( ew, unop(Iop_64HIto32, mkexpr(t64) ) );
+//..       put_emwarn( mkexpr(ew) );
+//..       /* Finally, if an emulation warning was reported, side-exit to
+//..          the next insn, reporting the warning, so that Valgrind's
+//..          dispatcher sees the warning. */
+//..       stmt( 
+//..          IRStmt_Exit(
+//..             binop(Iop_CmpNE32, mkexpr(ew), mkU32(0)),
+//..             Ijk_EmWarn,
+//..             IRConst_U32( ((Addr32)guest_eip_bbstart)+delta)
+//..          )
+//..       );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 0F 5F = MAXPS -- max 32Fx4 from R/M to R */
+//..    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0x5F) {
+//..       delta = dis_SSE_E_to_G_all( sorb, delta+2, "maxps", Iop_Max32Fx4 );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* F3 0F 5F = MAXSS -- max 32F0x4 from R/M to R */
+//..    if (insn[0] == 0xF3 && insn[1] == 0x0F && insn[2] == 0x5F) {
+//..       vassert(sz == 4);
+//..       delta = dis_SSE_E_to_G_lo32( sorb, delta+3, "maxss", Iop_Max32F0x4 );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 0F 5D = MINPS -- min 32Fx4 from R/M to R */
+//..    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0x5D) {
+//..       delta = dis_SSE_E_to_G_all( sorb, delta+2, "minps", Iop_Min32Fx4 );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* F3 0F 5D = MINSS -- min 32F0x4 from R/M to R */
+//..    if (insn[0] == 0xF3 && insn[1] == 0x0F && insn[2] == 0x5D) {
+//..       vassert(sz == 4);
+//..       delta = dis_SSE_E_to_G_lo32( sorb, delta+3, "minss", Iop_Min32F0x4 );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 0F 28 = MOVAPS -- move from E (mem or xmm) to G (xmm). */
+//..    /* 0F 10 = MOVUPS -- move from E (mem or xmm) to G (xmm). */
+//..    if (sz == 4 && insn[0] == 0x0F && (insn[1] == 0x28 || insn[1] == 0x10)) {
+//..       modrm = getIByte(delta+2);
+//..       if (epartIsReg(modrm)) {
+//..          putXMMReg( gregOfRM(modrm), 
+//..                     getXMMReg( eregOfRM(modrm) ));
+//..          DIP("mov[ua]ps %s,%s\n", nameXMMReg(eregOfRM(modrm)),
+//..                                   nameXMMReg(gregOfRM(modrm)));
+//..          delta += 2+1;
+//..       } else {
+//..          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
+//..          putXMMReg( gregOfRM(modrm), 
+//..                     loadLE(Ity_V128, mkexpr(addr)) );
+//..          DIP("mov[ua]ps %s,%s\n", dis_buf,
+//..                                   nameXMMReg(gregOfRM(modrm)));
+//..          delta += 2+alen;
+//..       }
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 0F 29 = MOVAPS -- move from G (xmm) to E (mem or xmm). */
+//..    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0x29) {
+//..       modrm = getIByte(delta+2);
+//..       if (epartIsReg(modrm)) {
+//..          /* fall through; awaiting test case */
+//..       } else {
+//..          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
+//..          storeLE( mkexpr(addr), getXMMReg(gregOfRM(modrm)) );
+//..          DIP("movaps %s,%s\n", nameXMMReg(gregOfRM(modrm)),
+//..                                dis_buf );
+//..          delta += 2+alen;
+//..          goto decode_success;
+//..       }
+//..    }
+//.. 
+//..    /* 0F 16 = MOVHPS -- move from mem to high half of XMM. */
+//..    /* 0F 16 = MOVLHPS -- move from lo half to hi half of XMM. */
+//..    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0x16) {
+//..       modrm = getIByte(delta+2);
+//..       if (epartIsReg(modrm)) {
+//..          delta += 2+1;
+//..          putXMMRegLane64( gregOfRM(modrm), 1/*upper lane*/,
+//..                           getXMMRegLane64( eregOfRM(modrm), 0 ) );
+//..          DIP("movhps %s,%s\n", nameXMMReg(eregOfRM(modrm)), 
+//..                                nameXMMReg(gregOfRM(modrm)));
+//..       } else {
+//..          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
+//..          delta += 2+alen;
+//..          putXMMRegLane64( gregOfRM(modrm), 1/*upper lane*/,
+//..                           loadLE(Ity_I64, mkexpr(addr)) );
+//..          DIP("movhps %s,%s\n", dis_buf, 
+//..                                nameXMMReg( gregOfRM(modrm) ));
+//..       }
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 0F 17 = MOVHPS -- move from high half of XMM to mem. */
+//..    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0x17) {
+//..       if (!epartIsReg(insn[2])) {
+//..          delta += 2;
+//..          addr = disAMode ( &alen, sorb, delta, dis_buf );
+//..          delta += alen;
+//..          storeLE( mkexpr(addr), 
+//..                   getXMMRegLane64( gregOfRM(insn[2]),
+//..                                    1/*upper lane*/ ) );
+//..          DIP("movhps %s,%s\n", nameXMMReg( gregOfRM(insn[2]) ),
+//..                                dis_buf);
+//..          goto decode_success;
+//..       }
+//..       /* else fall through */
+//..    }
+//.. 
+//..    /* 0F 12 = MOVLPS -- move from mem to low half of XMM. */
+//..    /* OF 12 = MOVHLPS -- from from hi half to lo half of XMM. */
+//..    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0x12) {
+//..       modrm = getIByte(delta+2);
+//..       if (epartIsReg(modrm)) {
+//..          delta += 2+1;
+//..          putXMMRegLane64( gregOfRM(modrm),  
+//..                           0/*lower lane*/,
+//..                           getXMMRegLane64( eregOfRM(modrm), 1 ));
+//..          DIP("movhlps %s, %s\n", nameXMMReg(eregOfRM(modrm)), 
+//..                                  nameXMMReg(gregOfRM(modrm)));
+//..       } else {
+//..          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
+//..          delta += 2+alen;
+//..          putXMMRegLane64( gregOfRM(modrm),  0/*lower lane*/,
+//..                           loadLE(Ity_I64, mkexpr(addr)) );
+//..          DIP("movlps %s, %s\n", 
+//..              dis_buf, nameXMMReg( gregOfRM(modrm) ));
+//..       }
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 0F 13 = MOVLPS -- move from low half of XMM to mem. */
+//..    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0x13) {
+//..       if (!epartIsReg(insn[2])) {
+//..          delta += 2;
+//..          addr = disAMode ( &alen, sorb, delta, dis_buf );
+//..          delta += alen;
+//..          storeLE( mkexpr(addr), 
+//..                   getXMMRegLane64( gregOfRM(insn[2]), 
+//..                                    0/*lower lane*/ ) );
+//..          DIP("movlps %s, %s\n", nameXMMReg( gregOfRM(insn[2]) ),
+//..                                 dis_buf);
+//..          goto decode_success;
+//..       }
+//..       /* else fall through */
+//..    }
+//.. 
+//..    /* 0F 50 = MOVMSKPS - move 4 sign bits from 4 x F32 in xmm(E)
+//..       to 4 lowest bits of ireg(G) */
+//..    if (insn[0] == 0x0F && insn[1] == 0x50) {
+//..       modrm = getIByte(delta+2);
+//..       if (sz == 4 && epartIsReg(modrm)) {
+//..          Int src;
+//..          t0 = newTemp(Ity_I32);
+//..          t1 = newTemp(Ity_I32);
+//..          t2 = newTemp(Ity_I32);
+//..          t3 = newTemp(Ity_I32);
+//..          delta += 2+1;
+//..          src = eregOfRM(modrm);
+//..          assign( t0, binop( Iop_And32,
+//..                             binop(Iop_Shr32, getXMMRegLane32(src,0), mkU8(31)),
+//..                             mkU32(1) ));
+//..          assign( t1, binop( Iop_And32,
+//..                             binop(Iop_Shr32, getXMMRegLane32(src,1), mkU8(30)),
+//..                             mkU32(2) ));
+//..          assign( t2, binop( Iop_And32,
+//..                             binop(Iop_Shr32, getXMMRegLane32(src,2), mkU8(29)),
+//..                             mkU32(4) ));
+//..          assign( t3, binop( Iop_And32,
+//..                             binop(Iop_Shr32, getXMMRegLane32(src,3), mkU8(28)),
+//..                             mkU32(8) ));
+//..          putIReg(4, gregOfRM(modrm),
+//..                     binop(Iop_Or32,
+//..                           binop(Iop_Or32, mkexpr(t0), mkexpr(t1)),
+//..                           binop(Iop_Or32, mkexpr(t2), mkexpr(t3))
+//..                          )
+//..                  );
+//..          DIP("movmskps %s,%s\n", nameXMMReg(src), 
+//..                                  nameIReg(4, gregOfRM(modrm)));
+//..          goto decode_success;
+//..       }
+//..       /* else fall through */
+//..    }
+//.. 
+//..    /* 0F 2B = MOVNTPS -- for us, just a plain SSE store. */
+//..    if (insn[0] == 0x0F && insn[1] == 0x2B) {
+//..       modrm = getIByte(delta+2);
+//..       if (!epartIsReg(modrm)) {
+//..          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
+//..          storeLE( mkexpr(addr), getXMMReg(gregOfRM(modrm)) );
+//..          DIP("movntps %s,%s\n", dis_buf,
+//..                                 nameXMMReg(gregOfRM(modrm)));
+//..          delta += 2+alen;
+//..          goto decode_success;
+//..       }
+//..       /* else fall through */
+//..    }
+//.. 
+//..    /* ***--- this is an MMX class insn introduced in SSE1 ---*** */
+//..    /* 0F E7 = MOVNTQ -- for us, just a plain MMX store.  Note, the
+//..       Intel manual does not say anything about the usual business of
+//..       the FP reg tags getting trashed whenever an MMX insn happens.
+//..       So we just leave them alone. 
+//..    */
+//..    if (insn[0] == 0x0F && insn[1] == 0xE7) {
+//..       modrm = getIByte(delta+2);
+//..       if (sz == 4 && !epartIsReg(modrm)) {
+//..          /* do_MMX_preamble(); Intel docs don't specify this */
+//..          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
+//..          storeLE( mkexpr(addr), getMMXReg(gregOfRM(modrm)) );
+//..          DIP("movntq %s,%s\n", dis_buf,
+//..                                nameMMXReg(gregOfRM(modrm)));
+//..          delta += 2+alen;
+//..          goto decode_success;
+//..       }
+//..       /* else fall through */
+//..    }
+//.. 
+//..    /* F3 0F 10 = MOVSS -- move 32 bits from E (mem or lo 1/4 xmm) to G
+//..       (lo 1/4 xmm).  If E is mem, upper 3/4 of G is zeroed out. */
+//..    if (insn[0] == 0xF3 && insn[1] == 0x0F && insn[2] == 0x10) {
+//..       vassert(sz == 4);
+//..       modrm = getIByte(delta+3);
+//..       if (epartIsReg(modrm)) {
+//..          putXMMRegLane32( gregOfRM(modrm), 0,
+//..                           getXMMRegLane32( eregOfRM(modrm), 0 ));
+//..          DIP("movss %s,%s\n", nameXMMReg(eregOfRM(modrm)),
+//..                               nameXMMReg(gregOfRM(modrm)));
+//..          delta += 3+1;
+//..       } else {
+//..          addr = disAMode ( &alen, sorb, delta+3, dis_buf );
+//..          putXMMReg( gregOfRM(modrm), mkV128(0) );
+//..          putXMMRegLane32( gregOfRM(modrm), 0,
+//..                           loadLE(Ity_I32, mkexpr(addr)) );
+//..          DIP("movss %s,%s\n", dis_buf,
+//..                               nameXMMReg(gregOfRM(modrm)));
+//..          delta += 3+alen;
+//..       }
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* F3 0F 11 = MOVSS -- move 32 bits from G (lo 1/4 xmm) to E (mem
+//..       or lo 1/4 xmm). */
+//..    if (insn[0] == 0xF3 && insn[1] == 0x0F && insn[2] == 0x11) {
+//..       vassert(sz == 4);
+//..       modrm = getIByte(delta+3);
+//..       if (epartIsReg(modrm)) {
+//..          /* fall through, we don't yet have a test case */
+//..       } else {
+//..          addr = disAMode ( &alen, sorb, delta+3, dis_buf );
+//..          storeLE( mkexpr(addr),
+//..                   getXMMRegLane32(gregOfRM(modrm), 0) );
+//..          DIP("movss %s,%s\n", nameXMMReg(gregOfRM(modrm)),
+//..                               dis_buf);
+//..          delta += 3+alen;
+//..          goto decode_success;
+//..       }
+//..    }
+//.. 
+//..    /* 0F 59 = MULPS -- mul 32Fx4 from R/M to R */
+//..    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0x59) {
+//..       delta = dis_SSE_E_to_G_all( sorb, delta+2, "mulps", Iop_Mul32Fx4 );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* F3 0F 59 = MULSS -- mul 32F0x4 from R/M to R */
+//..    if (insn[0] == 0xF3 && insn[1] == 0x0F && insn[2] == 0x59) {
+//..       vassert(sz == 4);
+//..       delta = dis_SSE_E_to_G_lo32( sorb, delta+3, "mulss", Iop_Mul32F0x4 );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 0F 56 = ORPS -- G = G and E */
+//..    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0x56) {
+//..       delta = dis_SSE_E_to_G_all( sorb, delta+2, "orps", Iop_Or128 );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* ***--- this is an MMX class insn introduced in SSE1 ---*** */
+//..    /* 0F E0 = PAVGB -- 8x8 unsigned Packed Average, with rounding */
+//..    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0xE0) {
+//..       do_MMX_preamble();
+//..       delta = dis_MMXop_regmem_to_reg ( 
+//..                 sorb, delta+2, insn[1], "pavgb", False );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* ***--- this is an MMX class insn introduced in SSE1 ---*** */
+//..    /* 0F E3 = PAVGW -- 16x4 unsigned Packed Average, with rounding */
+//..    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0xE3) {
+//..       do_MMX_preamble();
+//..       delta = dis_MMXop_regmem_to_reg ( 
+//..                 sorb, delta+2, insn[1], "pavgw", False );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* ***--- this is an MMX class insn introduced in SSE1 ---*** */
+//..    /* 0F C5 = PEXTRW -- extract 16-bit field from mmx(E) and put 
+//..       zero-extend of it in ireg(G). */
+//..    if (insn[0] == 0x0F && insn[1] == 0xC5) {
+//..       modrm = insn[2];
+//..       if (sz == 4 && epartIsReg(modrm)) {
+//..          IRTemp sV = newTemp(Ity_I64);
+//..          t5 = newTemp(Ity_I16);
+//..          do_MMX_preamble();
+//..          assign(sV, getMMXReg(eregOfRM(modrm)));
+//..          breakup64to16s( sV, &t3, &t2, &t1, &t0 );
+//..          switch (insn[3] & 3) {
+//..             case 0:  assign(t5, mkexpr(t0)); break;
+//..             case 1:  assign(t5, mkexpr(t1)); break;
+//..             case 2:  assign(t5, mkexpr(t2)); break;
+//..             case 3:  assign(t5, mkexpr(t3)); break;
+//..             default: vassert(0);
+//..          }
+//..          putIReg(4, gregOfRM(modrm), unop(Iop_16Uto32, mkexpr(t5)));
+//..          DIP("pextrw $%d,%s,%s\n",
+//..              (Int)insn[3], nameMMXReg(eregOfRM(modrm)),
+//..                            nameIReg(4,gregOfRM(modrm)));
+//..          delta += 4;
+//..          goto decode_success;
+//..       } 
+//..       /* else fall through */
+//..    }
+//.. 
+//..    /* ***--- this is an MMX class insn introduced in SSE1 ---*** */
+//..    /* 0F C4 = PINSRW -- get 16 bits from E(mem or low half ireg) and
+//..       put it into the specified lane of mmx(G). */
+//..    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0xC4) {
+//..       /* Use t0 .. t3 to hold the 4 original 16-bit lanes of the
+//..          mmx reg.  t4 is the new lane value.  t5 is the original
+//..          mmx value. t6 is the new mmx value. */
+//..       Int lane;
+//..       t4 = newTemp(Ity_I16);
+//..       t5 = newTemp(Ity_I64);
+//..       t6 = newTemp(Ity_I64);
+//..       modrm = insn[2];
+//..       do_MMX_preamble();
+//.. 
+//..       assign(t5, getMMXReg(gregOfRM(modrm)));
+//..       breakup64to16s( t5, &t3, &t2, &t1, &t0 );
+//.. 
+//..       if (epartIsReg(modrm)) {
+//..          assign(t4, getIReg(2, eregOfRM(modrm)));
+//..          lane = insn[3];
+//..          delta += 2+2;
+//..          DIP("pinsrw $%d,%s,%s\n", (Int)lane, 
+//..                                    nameIReg(2,eregOfRM(modrm)),
+//..                                    nameMMXReg(gregOfRM(modrm)));
+//..       } else {
+//..          /* awaiting test case */
+//..          goto decode_failure;
+//..       }
+//.. 
+//..       switch (lane & 3) {
+//..          case 0:  assign(t6, mk64from16s(t3,t2,t1,t4)); break;
+//..          case 1:  assign(t6, mk64from16s(t3,t2,t4,t0)); break;
+//..          case 2:  assign(t6, mk64from16s(t3,t4,t1,t0)); break;
+//..          case 3:  assign(t6, mk64from16s(t4,t2,t1,t0)); break;
+//..          default: vassert(0);
+//..       }
+//..       putMMXReg(gregOfRM(modrm), mkexpr(t6));
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* ***--- this is an MMX class insn introduced in SSE1 ---*** */
+//..    /* 0F EE = PMAXSW -- 16x4 signed max */
+//..    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0xEE) {
+//..       do_MMX_preamble();
+//..       delta = dis_MMXop_regmem_to_reg ( 
+//..                 sorb, delta+2, insn[1], "pmaxsw", False );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* ***--- this is an MMX class insn introduced in SSE1 ---*** */
+//..    /* 0F DE = PMAXUB -- 8x8 unsigned max */
+//..    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0xDE) {
+//..       do_MMX_preamble();
+//..       delta = dis_MMXop_regmem_to_reg ( 
+//..                 sorb, delta+2, insn[1], "pmaxub", False );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* ***--- this is an MMX class insn introduced in SSE1 ---*** */
+//..    /* 0F EA = PMINSW -- 16x4 signed min */
+//..    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0xEA) {
+//..       do_MMX_preamble();
+//..       delta = dis_MMXop_regmem_to_reg ( 
+//..                 sorb, delta+2, insn[1], "pminsw", False );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* ***--- this is an MMX class insn introduced in SSE1 ---*** */
+//..    /* 0F DA = PMINUB -- 8x8 unsigned min */
+//..    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0xDA) {
+//..       do_MMX_preamble();
+//..       delta = dis_MMXop_regmem_to_reg ( 
+//..                 sorb, delta+2, insn[1], "pminub", False );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* ***--- this is an MMX class insn introduced in SSE1 ---*** */
+//..    /* 0F D7 = PMOVMSKB -- extract sign bits from each of 8 lanes in
+//..       mmx(G), turn them into a byte, and put zero-extend of it in
+//..       ireg(G). */
+//..    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0xD7) {
+//..       modrm = insn[2];
+//..       if (epartIsReg(modrm)) {
+//..          do_MMX_preamble();
+//..          t0 = newTemp(Ity_I64);
+//..          t1 = newTemp(Ity_I32);
+//..          assign(t0, getMMXReg(eregOfRM(modrm)));
+//..          assign(t1, mkIRExprCCall(
+//..                        Ity_I32, 0/*regparms*/, 
+//..                        "x86g_calculate_mmx_pmovmskb",
+//..                        &x86g_calculate_mmx_pmovmskb,
+//..                        mkIRExprVec_1(mkexpr(t0))));
+//..          putIReg(4, gregOfRM(modrm), mkexpr(t1));
+//..          DIP("pmovmskb %s,%s\n", nameMMXReg(eregOfRM(modrm)),
+//..                                  nameIReg(4,gregOfRM(modrm)));
+//..          delta += 3;
+//..          goto decode_success;
+//..       } 
+//..       /* else fall through */
+//..    }
+//.. 
+//..    /* ***--- this is an MMX class insn introduced in SSE1 ---*** */
+//..    /* 0F E4 = PMULUH -- 16x4 hi-half of unsigned widening multiply */
+//..    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0xE4) {
+//..       do_MMX_preamble();
+//..       delta = dis_MMXop_regmem_to_reg ( 
+//..                 sorb, delta+2, insn[1], "pmuluh", False );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 0F 18 /0 = PREFETCHNTA -- prefetch into caches, */
+//..    /* 0F 18 /1 = PREFETCH0   -- with various different hints */
+//..    /* 0F 18 /2 = PREFETCH1 */
+//..    /* 0F 18 /3 = PREFETCH2 */
+//..    if (insn[0] == 0x0F && insn[1] == 0x18
+//..        && !epartIsReg(insn[2]) 
+//..        && gregOfRM(insn[2]) >= 0 && gregOfRM(insn[2]) <= 3) {
+//..       HChar* hintstr = "??";
+//.. 
+//..       modrm = getIByte(delta+2);
+//..       vassert(!epartIsReg(modrm));
+//.. 
+//..       addr = disAMode ( &alen, sorb, delta+2, dis_buf );
+//..       delta += 2+alen;
+//.. 
+//..       switch (gregOfRM(modrm)) {
+//..          case 0: hintstr = "nta"; break;
+//..          case 1: hintstr = "t0"; break;
+//..          case 2: hintstr = "t1"; break;
+//..          case 3: hintstr = "t2"; break;
+//..          default: vassert(0);
+//..       }
+//.. 
+//..       DIP("prefetch%s %s\n", hintstr, dis_buf);
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* ***--- this is an MMX class insn introduced in SSE1 ---*** */
+//..    /* 0F F6 = PSADBW -- sum of 8Ux8 absolute differences */
+//..    if (insn[0] == 0x0F && insn[1] == 0xF6) {
+//..       vassert(sz == 4);
+//..       do_MMX_preamble();
+//..       delta = dis_MMXop_regmem_to_reg ( 
+//..                  sorb, delta+2, insn[1], "psadbw", False );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* ***--- this is an MMX class insn introduced in SSE1 ---*** */
+//..    /* 0F 70 = PSHUFW -- rearrange 4x16 from E(mmx or mem) to G(mmx) */
+//..    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0x70) {
+//..       Int order;
+//..       IRTemp sV, dV, s3, s2, s1, s0;
+//..       s3 = s2 = s1 = s0 = IRTemp_INVALID;
+//..       sV = newTemp(Ity_I64);
+//..       dV = newTemp(Ity_I64);
+//..       do_MMX_preamble();
+//..       modrm = insn[2];
+//..       if (epartIsReg(modrm)) {
+//..          assign( sV, getMMXReg(eregOfRM(modrm)) );
+//..          order = (Int)insn[3];
+//..          delta += 2+2;
+//..          DIP("pshufw $%d,%s,%s\n", order, 
+//..                                    nameMMXReg(eregOfRM(modrm)),
+//..                                    nameMMXReg(gregOfRM(modrm)));
+//..       } else {
+//..          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
+//..          assign( sV, loadLE(Ity_I64, mkexpr(addr)) );
+//..    order = (Int)insn[2+alen];
+//..          delta += 3+alen;
+//..          DIP("pshufw $%d,%s,%s\n", order, 
+//..                                    dis_buf,
+//..                                    nameMMXReg(gregOfRM(modrm)));
+//..       }
+//..       breakup64to16s( sV, &s3, &s2, &s1, &s0 );
+//.. 
+//.. #     define SEL(n) \
+//..                 ((n)==0 ? s0 : ((n)==1 ? s1 : ((n)==2 ? s2 : s3)))
+//..       assign(dV,
+//..        mk64from16s( SEL((order>>6)&3), SEL((order>>4)&3),
+//..                           SEL((order>>2)&3), SEL((order>>0)&3) )
+//..       );
+//..       putMMXReg(gregOfRM(modrm), mkexpr(dV));
+//.. #     undef SEL
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 0F 53 = RCPPS -- approx reciprocal 32Fx4 from R/M to R */
+//..    if (insn[0] == 0x0F && insn[1] == 0x53) {
+//..       vassert(sz == 4);
+//..       delta = dis_SSE_E_to_G_unary_all( sorb, delta+2, 
+//..                                         "rcpps", Iop_Recip32Fx4 );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* F3 0F 53 = RCPSS -- approx reciprocal 32F0x4 from R/M to R */
+//..    if (insn[0] == 0xF3 && insn[1] == 0x0F && insn[2] == 0x53) {
+//..       vassert(sz == 4);
+//..       delta = dis_SSE_E_to_G_unary_lo32( sorb, delta+3, 
+//..                                          "rcpss", Iop_Recip32F0x4 );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 0F 52 = RSQRTPS -- approx reciprocal sqrt 32Fx4 from R/M to R */
+//..    if (insn[0] == 0x0F && insn[1] == 0x52) {
+//..       vassert(sz == 4);
+//..       delta = dis_SSE_E_to_G_unary_all( sorb, delta+2, 
+//..                                         "rsqrtps", Iop_RSqrt32Fx4 );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* F3 0F 52 = RSQRTSS -- approx reciprocal sqrt 32F0x4 from R/M to R */
+//..    if (insn[0] == 0xF3 && insn[1] == 0x0F && insn[2] == 0x52) {
+//..       vassert(sz == 4);
+//..       delta = dis_SSE_E_to_G_unary_lo32( sorb, delta+3, 
+//..                                          "rsqrtss", Iop_RSqrt32F0x4 );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 0F AE /7 = SFENCE -- flush pending operations to memory */
+//..    if (insn[0] == 0x0F && insn[1] == 0xAE
+//..        && epartIsReg(insn[2]) && gregOfRM(insn[2]) == 7) {
+//..       vassert(sz == 4);
+//..       delta += 3;
+//..       /* Insert a memory fence.  It's sometimes important that these
+//..          are carried through to the generated code. */
+//..       stmt( IRStmt_MFence() );
+//..       DIP("sfence\n");
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 0F C6 /r ib = SHUFPS -- shuffle packed F32s */
+//..    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0xC6) {
+//..       Int    select;
+//..       IRTemp sV, dV;
+//..       IRTemp s3, s2, s1, s0, d3, d2, d1, d0;
+//..       sV = newTemp(Ity_V128);
+//..       dV = newTemp(Ity_V128);
+//..       s3 = s2 = s1 = s0 = d3 = d2 = d1 = d0 = IRTemp_INVALID;
+//..       modrm = insn[2];
+//..       assign( dV, getXMMReg(gregOfRM(modrm)) );
+//.. 
+//..       if (epartIsReg(modrm)) {
+//..          assign( sV, getXMMReg(eregOfRM(modrm)) );
+//..          select = (Int)insn[3];
+//..          delta += 2+2;
+//..          DIP("shufps $%d,%s,%s\n", select, 
+//..                                    nameXMMReg(eregOfRM(modrm)),
+//..                                    nameXMMReg(gregOfRM(modrm)));
+//..       } else {
+//..          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
+//..          assign( sV, loadLE(Ity_V128, mkexpr(addr)) );
+//..          select = (Int)insn[2+alen];
+//..          delta += 3+alen;
+//..          DIP("shufps $%d,%s,%s\n", select, 
+//..                                    dis_buf,
+//..                                    nameXMMReg(gregOfRM(modrm)));
+//..       }
+//.. 
+//..       breakup128to32s( dV, &d3, &d2, &d1, &d0 );
+//..       breakup128to32s( sV, &s3, &s2, &s1, &s0 );
+//.. 
+//.. #     define SELD(n) ((n)==0 ? d0 : ((n)==1 ? d1 : ((n)==2 ? d2 : d3)))
+//.. #     define SELS(n) ((n)==0 ? s0 : ((n)==1 ? s1 : ((n)==2 ? s2 : s3)))
+//.. 
+//..       putXMMReg(
+//..          gregOfRM(modrm), 
+//..          mk128from32s( SELS((select>>6)&3), SELS((select>>4)&3), 
+//..                        SELD((select>>2)&3), SELD((select>>0)&3) )
+//..       );
+//.. 
+//.. #     undef SELD
+//.. #     undef SELS
+//.. 
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 0F 51 = SQRTPS -- approx sqrt 32Fx4 from R/M to R */
+//..    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0x51) {
+//..       delta = dis_SSE_E_to_G_unary_all( sorb, delta+2, 
+//..                                         "sqrtps", Iop_Sqrt32Fx4 );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* F3 0F 51 = SQRTSS -- approx sqrt 32F0x4 from R/M to R */
+//..    if (insn[0] == 0xF3 && insn[1] == 0x0F && insn[2] == 0x51) {
+//..       vassert(sz == 4);
+//..       delta = dis_SSE_E_to_G_unary_lo32( sorb, delta+3, 
+//..                                          "sqrtss", Iop_Sqrt32F0x4 );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 0F AE /3 = STMXCSR m32 -- store %mxcsr */
+//..    if (insn[0] == 0x0F && insn[1] == 0xAE
+//..        && !epartIsReg(insn[2]) && gregOfRM(insn[2]) == 3) {
+//..       modrm = getIByte(delta+2);
+//..       vassert(sz == 4);
+//..       vassert(!epartIsReg(modrm));
+//.. 
+//..       addr = disAMode ( &alen, sorb, delta+2, dis_buf );
+//..       delta += 2+alen;
+//.. 
+//..       /* Fake up a native SSE mxcsr word.  The only thing it depends
+//..          on is SSEROUND[1:0], so call a clean helper to cook it up. 
+//..       */
+//..       /* UInt x86h_create_mxcsr ( UInt sseround ) */
+//..       DIP("stmxcsr %s\n", dis_buf);
+//..       storeLE( mkexpr(addr), 
+//..                mkIRExprCCall(
+//..                   Ity_I32, 0/*regp*/,
+//..                   "x86g_create_mxcsr", &x86g_create_mxcsr, 
+//..                   mkIRExprVec_1( get_sse_roundingmode() ) 
+//..                ) 
+//..              );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 0F 5C = SUBPS -- sub 32Fx4 from R/M to R */
+//..    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0x5C) {
+//..       delta = dis_SSE_E_to_G_all( sorb, delta+2, "subps", Iop_Sub32Fx4 );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* F3 0F 5C = SUBSS -- sub 32F0x4 from R/M to R */
+//..    if (insn[0] == 0xF3 && insn[1] == 0x0F && insn[2] == 0x5C) {
+//..       vassert(sz == 4);
+//..       delta = dis_SSE_E_to_G_lo32( sorb, delta+3, "subss", Iop_Sub32F0x4 );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 0F 15 = UNPCKHPS -- unpack and interleave high part F32s */
+//..    /* 0F 14 = UNPCKLPS -- unpack and interleave low part F32s */
+//..    /* These just appear to be special cases of SHUFPS */
+//..    if (sz == 4 && insn[0] == 0x0F && (insn[1] == 0x15 || insn[1] == 0x14)) {
+//..       IRTemp sV, dV;
+//..       IRTemp s3, s2, s1, s0, d3, d2, d1, d0;
+//..       Bool hi = insn[1] == 0x15;
+//..       sV = newTemp(Ity_V128);
+//..       dV = newTemp(Ity_V128);
+//..       s3 = s2 = s1 = s0 = d3 = d2 = d1 = d0 = IRTemp_INVALID;
+//..       modrm = insn[2];
+//..       assign( dV, getXMMReg(gregOfRM(modrm)) );
+//.. 
+//..       if (epartIsReg(modrm)) {
+//..          assign( sV, getXMMReg(eregOfRM(modrm)) );
+//..          delta += 2+1;
+//..          DIP("unpck%sps %s,%s\n", hi ? "h" : "l",
+//..                                   nameXMMReg(eregOfRM(modrm)),
+//..                                   nameXMMReg(gregOfRM(modrm)));
+//..       } else {
+//..          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
+//..          assign( sV, loadLE(Ity_V128, mkexpr(addr)) );
+//..          delta += 2+alen;
+//..          DIP("unpck%sps %s,%s\n", hi ? "h" : "l",
+//..                                   dis_buf,
+//..                                   nameXMMReg(gregOfRM(modrm)));
+//..       }
+//.. 
+//..       breakup128to32s( dV, &d3, &d2, &d1, &d0 );
+//..       breakup128to32s( sV, &s3, &s2, &s1, &s0 );
+//.. 
+//..       if (hi) {
+//..          putXMMReg( gregOfRM(modrm), mk128from32s( s3, d3, s2, d2 ) );
+//..       } else {
+//..          putXMMReg( gregOfRM(modrm), mk128from32s( s1, d1, s0, d0 ) );
+//..       }
+//.. 
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 0F 57 = XORPS -- G = G and E */
+//..    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0x57) {
+//..       delta = dis_SSE_E_to_G_all( sorb, delta+2, "xorps", Iop_Xor128 );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* ---------------------------------------------------- */
+//..    /* --- end of the SSE decoder.                      --- */
+//..    /* ---------------------------------------------------- */
+//.. 
+//..    /* ---------------------------------------------------- */
+//..    /* --- start of the SSE2 decoder.                   --- */
+//..    /* ---------------------------------------------------- */
+//.. 
+//..    /* Skip parts of the decoder which don't apply given the stated
+//..       guest subarchitecture. */
+//..    if (subarch == VexSubArchX86_sse0 || subarch == VexSubArchX86_sse1)
+//..       goto after_sse_decoders;
+//.. 
+//..    insn = (UChar*)&guest_code[delta];
+//.. 
+//..    /* 66 0F 58 = ADDPD -- add 32Fx4 from R/M to R */
+//..    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x58) {
+//..       delta = dis_SSE_E_to_G_all( sorb, delta+2, "addpd", Iop_Add64Fx2 );
+//..       goto decode_success;
+//..    }
+//..  
+//..    /* F2 0F 58 = ADDSD -- add 64F0x2 from R/M to R */
+//..    if (insn[0] == 0xF2 && insn[1] == 0x0F && insn[2] == 0x58) {
+//..       vassert(sz == 4);
+//..       delta = dis_SSE_E_to_G_lo64( sorb, delta+3, "addsd", Iop_Add64F0x2 );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 66 0F 55 = ANDNPD -- G = (not G) and E */
+//..    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x55) {
+//..       delta = dis_SSE_E_to_G_all_invG( sorb, delta+2, "andnpd", Iop_And128 );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 66 0F 54 = ANDPD -- G = G and E */
+//..    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x54) {
+//..       delta = dis_SSE_E_to_G_all( sorb, delta+2, "andpd", Iop_And128 );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 66 0F C2 = CMPPD -- 64Fx2 comparison from R/M to R */
+//..    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xC2) {
+//..       delta = dis_SSEcmp_E_to_G( sorb, delta+2, "cmppd", True, 8 );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* F2 0F C2 = CMPSD -- 64F0x2 comparison from R/M to R */
+//..    if (insn[0] == 0xF2 && insn[1] == 0x0F && insn[2] == 0xC2) {
+//..       vassert(sz == 4);
+//..       delta = dis_SSEcmp_E_to_G( sorb, delta+3, "cmpsd", False, 8 );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 66 0F 2F = COMISD  -- 64F0x2 comparison G,E, and set ZCP */
+//..    /* 66 0F 2E = UCOMISD -- 64F0x2 comparison G,E, and set ZCP */
+//..    if (sz == 2 && insn[0] == 0x0F && (insn[1] == 0x2F || insn[1] == 0x2E)) {
+//..       IRTemp argL = newTemp(Ity_F64);
+//..       IRTemp argR = newTemp(Ity_F64);
+//..       modrm = getIByte(delta+2);
+//..       if (epartIsReg(modrm)) {
+//..          assign( argR, getXMMRegLane64F( eregOfRM(modrm), 0/*lowest lane*/ ) );
+//..          delta += 2+1;
+//..          DIP("[u]comisd %s,%s\n", nameXMMReg(eregOfRM(modrm)),
+//..                                   nameXMMReg(gregOfRM(modrm)) );
+//..       } else {
+//..          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
+//..    assign( argR, loadLE(Ity_F64, mkexpr(addr)) );
+//..          delta += 2+alen;
+//..          DIP("[u]comisd %s,%s\n", dis_buf,
+//..                                   nameXMMReg(gregOfRM(modrm)) );
+//..       }
+//..       assign( argL, getXMMRegLane64F( gregOfRM(modrm), 0/*lowest lane*/ ) );
+//.. 
+//..       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_CmpF64, mkexpr(argL), mkexpr(argR)),
+//..                       mkU32(0x45)
+//..           )));
+//.. 
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* F3 0F E6 = CVTDQ2PD -- convert 2 x I32 in mem/lo half xmm to 2 x
+//..       F64 in xmm(G) */
+//..    if (insn[0] == 0xF3 && insn[1] == 0x0F && insn[2] == 0xE6) {
+//..       IRTemp arg64 = newTemp(Ity_I64);
+//..       vassert(sz == 4);
+//.. 
+//..       modrm = getIByte(delta+3);
+//..       if (epartIsReg(modrm)) {
+//..          assign( arg64, getXMMRegLane64(eregOfRM(modrm), 0) );
+//..          delta += 3+1;
+//..          DIP("cvtdq2pd %s,%s\n", nameXMMReg(eregOfRM(modrm)),
+//..                                  nameXMMReg(gregOfRM(modrm)));
+//..       } else {
+//..          addr = disAMode ( &alen, sorb, delta+3, dis_buf );
+//..    assign( arg64, loadLE(Ity_I64, mkexpr(addr)) );
+//..          delta += 3+alen;
+//..          DIP("cvtdq2pd %s,%s\n", dis_buf,
+//..                                  nameXMMReg(gregOfRM(modrm)) );
+//..       }
+//.. 
+//..       putXMMRegLane64F( 
+//..          gregOfRM(modrm), 0,
+//..          unop(Iop_I32toF64, unop(Iop_64to32, mkexpr(arg64)))
+//..       );
+//.. 
+//..       putXMMRegLane64F(
+//..          gregOfRM(modrm), 1, 
+//..          unop(Iop_I32toF64, unop(Iop_64HIto32, mkexpr(arg64)))
+//..       );
+//.. 
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 0F 5B = CVTDQ2PS -- convert 4 x I32 in mem/xmm to 4 x F32 in
+//..       xmm(G) */
+//..    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0x5B) {
+//..       IRTemp argV  = newTemp(Ity_V128);
+//..       IRTemp rmode = newTemp(Ity_I32);
+//.. 
+//..       modrm = getIByte(delta+2);
+//..       if (epartIsReg(modrm)) {
+//..          assign( argV, getXMMReg(eregOfRM(modrm)) );
+//..          delta += 2+1;
+//..          DIP("cvtdq2ps %s,%s\n", nameXMMReg(eregOfRM(modrm)),
+//..                                  nameXMMReg(gregOfRM(modrm)));
+//..       } else {
+//..          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
+//..    assign( argV, loadLE(Ity_V128, mkexpr(addr)) );
+//..          delta += 2+alen;
+//..          DIP("cvtdq2ps %s,%s\n", dis_buf,
+//..                                  nameXMMReg(gregOfRM(modrm)) );
+//..       }
+//..          
+//..       assign( rmode, get_sse_roundingmode() );
+//..       breakup128to32s( argV, &t3, &t2, &t1, &t0 );
+//.. 
+//.. #     define CVT(_t)  binop( Iop_F64toF32,                    \
+//..                              mkexpr(rmode),                   \
+//..                              unop(Iop_I32toF64,mkexpr(_t)))
+//..       
+//..       putXMMRegLane32F( gregOfRM(modrm), 3, CVT(t3) );
+//..       putXMMRegLane32F( gregOfRM(modrm), 2, CVT(t2) );
+//..       putXMMRegLane32F( gregOfRM(modrm), 1, CVT(t1) );
+//..       putXMMRegLane32F( gregOfRM(modrm), 0, CVT(t0) );
+//.. 
+//.. #     undef CVT
+//.. 
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* F2 0F E6 = CVTPD2DQ -- convert 2 x F64 in mem/xmm to 2 x I32 in
+//..       lo half xmm(G), and zero upper half */
+//..    if (insn[0] == 0xF2 && insn[1] == 0x0F && insn[2] == 0xE6) {
+//..       IRTemp argV  = newTemp(Ity_V128);
+//..       IRTemp rmode = newTemp(Ity_I32);
+//..       vassert(sz == 4);
+//.. 
+//..       modrm = getIByte(delta+3);
+//..       if (epartIsReg(modrm)) {
+//..          assign( argV, getXMMReg(eregOfRM(modrm)) );
+//..          delta += 3+1;
+//..          DIP("cvtpd2dq %s,%s\n", nameXMMReg(eregOfRM(modrm)),
+//..                                  nameXMMReg(gregOfRM(modrm)));
+//..       } else {
+//..          addr = disAMode ( &alen, sorb, delta+3, dis_buf );
+//..    assign( argV, loadLE(Ity_V128, mkexpr(addr)) );
+//..          delta += 3+alen;
+//..          DIP("cvtpd2dq %s,%s\n", dis_buf,
+//..                                  nameXMMReg(gregOfRM(modrm)) );
+//..       }
+//..          
+//..       assign( rmode, get_sse_roundingmode() );
+//..       t0 = newTemp(Ity_F64);
+//..       t1 = newTemp(Ity_F64);
+//..       assign( t0, unop(Iop_ReinterpI64asF64, 
+//..                        unop(Iop_128to64, mkexpr(argV))) );
+//..       assign( t1, unop(Iop_ReinterpI64asF64, 
+//..                        unop(Iop_128HIto64, mkexpr(argV))) );
+//..       
+//.. #     define CVT(_t)  binop( Iop_F64toI32,                    \
+//..                              mkexpr(rmode),                   \
+//..                              mkexpr(_t) )
+//..       
+//..       putXMMRegLane32( gregOfRM(modrm), 3, mkU32(0) );
+//..       putXMMRegLane32( gregOfRM(modrm), 2, mkU32(0) );
+//..       putXMMRegLane32( gregOfRM(modrm), 1, CVT(t1) );
+//..       putXMMRegLane32( gregOfRM(modrm), 0, CVT(t0) );
+//.. 
+//.. #     undef CVT
+//.. 
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 66 0F 2D = CVTPD2PI -- convert 2 x F64 in mem/xmm to 2 x
+//..       I32 in mmx, according to prevailing SSE rounding mode */
+//..    /* 66 0F 2C = CVTTPD2PI -- convert 2 x F64 in mem/xmm to 2 x
+//..       I32 in mmx, rounding towards zero */
+//..    if (sz == 2 && insn[0] == 0x0F && (insn[1] == 0x2D || insn[1] == 0x2C)) {
+//..       IRTemp dst64  = newTemp(Ity_I64);
+//..       IRTemp rmode  = newTemp(Ity_I32);
+//..       IRTemp f64lo  = newTemp(Ity_F64);
+//..       IRTemp f64hi  = newTemp(Ity_F64);
+//..       Bool   r2zero = insn[1] == 0x2C;
+//.. 
+//..       do_MMX_preamble();
+//..       modrm = getIByte(delta+2);
+//.. 
+//..       if (epartIsReg(modrm)) {
+//..          delta += 2+1;
+//..    assign(f64lo, getXMMRegLane64F(eregOfRM(modrm), 0));
+//..    assign(f64hi, getXMMRegLane64F(eregOfRM(modrm), 1));
+//..          DIP("cvt%spd2pi %s,%s\n", r2zero ? "t" : "",
+//..                                    nameXMMReg(eregOfRM(modrm)),
+//..                                    nameMMXReg(gregOfRM(modrm)));
+//..       } else {
+//..          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
+//..    assign(f64lo, loadLE(Ity_F64, mkexpr(addr)));
+//..    assign(f64hi, loadLE(Ity_F64, binop( Iop_Add32, 
+//..                                               mkexpr(addr), 
+//..                                               mkU32(8) )));
+//..          delta += 2+alen;
+//..          DIP("cvt%spf2pi %s,%s\n", r2zero ? "t" : "",
+//..                                    dis_buf,
+//..                                    nameMMXReg(gregOfRM(modrm)));
+//..       }
+//.. 
+//..       if (r2zero) {
+//..          assign(rmode, mkU32((UInt)Irrm_ZERO) );
+//..       } else {
+//..          assign( rmode, get_sse_roundingmode() );
+//..       }
+//.. 
+//..       assign( 
+//..          dst64,
+//..          binop( Iop_32HLto64,
+//..                 binop( Iop_F64toI32, mkexpr(rmode), mkexpr(f64hi) ),
+//..                 binop( Iop_F64toI32, mkexpr(rmode), mkexpr(f64lo) )
+//..               )
+//..       );
+//.. 
+//..       putMMXReg(gregOfRM(modrm), mkexpr(dst64));
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 66 0F 5A = CVTPD2PS -- convert 2 x F64 in mem/xmm to 2 x F32 in
+//..       lo half xmm(G), and zero upper half */
+//..    /* Note, this is practically identical to CVTPD2DQ.  It would have
+//..       been nicer to merge them together, but the insn[] offsets differ
+//..       by one. */
+//..    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x5A) {
+//..       IRTemp argV  = newTemp(Ity_V128);
+//..       IRTemp rmode = newTemp(Ity_I32);
+//.. 
+//..       modrm = getIByte(delta+2);
+//..       if (epartIsReg(modrm)) {
+//..          assign( argV, getXMMReg(eregOfRM(modrm)) );
+//..          delta += 2+1;
+//..          DIP("cvtpd2ps %s,%s\n", nameXMMReg(eregOfRM(modrm)),
+//..                                  nameXMMReg(gregOfRM(modrm)));
+//..       } else {
+//..          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
+//..    assign( argV, loadLE(Ity_V128, mkexpr(addr)) );
+//..          delta += 2+alen;
+//..          DIP("cvtpd2ps %s,%s\n", dis_buf,
+//..                                  nameXMMReg(gregOfRM(modrm)) );
+//..       }
+//..          
+//..       assign( rmode, get_sse_roundingmode() );
+//..       t0 = newTemp(Ity_F64);
+//..       t1 = newTemp(Ity_F64);
+//..       assign( t0, unop(Iop_ReinterpI64asF64, 
+//..                        unop(Iop_128to64, mkexpr(argV))) );
+//..       assign( t1, unop(Iop_ReinterpI64asF64, 
+//..                        unop(Iop_128HIto64, mkexpr(argV))) );
+//..       
+//.. #     define CVT(_t)  binop( Iop_F64toF32,                    \
+//..                              mkexpr(rmode),                   \
+//..                              mkexpr(_t) )
+//..       
+//..       putXMMRegLane32(  gregOfRM(modrm), 3, mkU32(0) );
+//..       putXMMRegLane32(  gregOfRM(modrm), 2, mkU32(0) );
+//..       putXMMRegLane32F( gregOfRM(modrm), 1, CVT(t1) );
+//..       putXMMRegLane32F( gregOfRM(modrm), 0, CVT(t0) );
+//.. 
+//.. #     undef CVT
+//.. 
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 66 0F 2A = CVTPI2PD -- convert 2 x I32 in mem/mmx to 2 x F64 in
+//..       xmm(G) */
+//..    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x2A) {
+//..       IRTemp arg64 = newTemp(Ity_I64);
+//.. 
+//..       modrm = getIByte(delta+2);
+//..       do_MMX_preamble();
+//..       if (epartIsReg(modrm)) {
+//..          assign( arg64, getMMXReg(eregOfRM(modrm)) );
+//..          delta += 2+1;
+//..          DIP("cvtpi2pd %s,%s\n", nameMMXReg(eregOfRM(modrm)),
+//..                                  nameXMMReg(gregOfRM(modrm)));
+//..       } else {
+//..          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
+//..    assign( arg64, loadLE(Ity_I64, mkexpr(addr)) );
+//..          delta += 2+alen;
+//..          DIP("cvtpi2pd %s,%s\n", dis_buf,
+//..                                  nameXMMReg(gregOfRM(modrm)) );
+//..       }
+//.. 
+//..       putXMMRegLane64F( 
+//..          gregOfRM(modrm), 0,
+//..          unop(Iop_I32toF64, unop(Iop_64to32, mkexpr(arg64)) )
+//..       );
+//.. 
+//..       putXMMRegLane64F( 
+//..          gregOfRM(modrm), 1,
+//..          unop(Iop_I32toF64, unop(Iop_64HIto32, mkexpr(arg64)) )
+//..       );
+//.. 
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 66 0F 5B = CVTPS2DQ -- convert 4 x F32 in mem/xmm to 4 x I32 in
+//..       xmm(G) */
+//..    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x5B) {
+//..       IRTemp argV  = newTemp(Ity_V128);
+//..       IRTemp rmode = newTemp(Ity_I32);
+//.. 
+//..       modrm = getIByte(delta+2);
+//..       if (epartIsReg(modrm)) {
+//..          assign( argV, getXMMReg(eregOfRM(modrm)) );
+//..          delta += 2+1;
+//..          DIP("cvtps2dq %s,%s\n", nameXMMReg(eregOfRM(modrm)),
+//..                                  nameXMMReg(gregOfRM(modrm)));
+//..       } else {
+//..          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
+//..    assign( argV, loadLE(Ity_V128, mkexpr(addr)) );
+//..          delta += 2+alen;
+//..          DIP("cvtps2dq %s,%s\n", dis_buf,
+//..                                  nameXMMReg(gregOfRM(modrm)) );
+//..       }
+//..          
+//..       assign( rmode, get_sse_roundingmode() );
+//..       breakup128to32s( argV, &t3, &t2, &t1, &t0 );
+//.. 
+//..       /* This is less than ideal.  If it turns out to be a performance
+//..    bottleneck it can be improved. */
+//.. #     define CVT(_t)                            \
+//..         binop( Iop_F64toI32,                    \
+//..                mkexpr(rmode),                   \
+//..                unop( Iop_F32toF64,              \
+//..                      unop( Iop_ReinterpI32asF32, mkexpr(_t))) )
+//..       
+//..       putXMMRegLane32( gregOfRM(modrm), 3, CVT(t3) );
+//..       putXMMRegLane32( gregOfRM(modrm), 2, CVT(t2) );
+//..       putXMMRegLane32( gregOfRM(modrm), 1, CVT(t1) );
+//..       putXMMRegLane32( gregOfRM(modrm), 0, CVT(t0) );
+//.. 
+//.. #     undef CVT
+//.. 
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 0F 5A = CVTPS2PD -- convert 2 x F32 in low half mem/xmm to 2 x
+//..       F64 in xmm(G). */
+//..    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0x5A) {
+//..       IRTemp f32lo = newTemp(Ity_F32);
+//..       IRTemp f32hi = newTemp(Ity_F32);
+//.. 
+//..       modrm = getIByte(delta+2);
+//..       if (epartIsReg(modrm)) {
+//..          assign( f32lo, getXMMRegLane32F(eregOfRM(modrm), 0) );
+//..          assign( f32hi, getXMMRegLane32F(eregOfRM(modrm), 1) );
+//..          delta += 2+1;
+//..          DIP("cvtps2pd %s,%s\n", nameXMMReg(eregOfRM(modrm)),
+//..                                  nameXMMReg(gregOfRM(modrm)));
+//..       } else {
+//..          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
+//..    assign( f32lo, loadLE(Ity_F32, mkexpr(addr)) );
+//..    assign( f32hi, loadLE(Ity_F32, 
+//..                                binop(Iop_Add32,mkexpr(addr),mkU32(4))) );
+//..          delta += 2+alen;
+//..          DIP("cvtps2pd %s,%s\n", dis_buf,
+//..                                  nameXMMReg(gregOfRM(modrm)) );
+//..       }
+//.. 
+//..       putXMMRegLane64F( gregOfRM(modrm), 1,
+//..                         unop(Iop_F32toF64, mkexpr(f32hi)) );
+//..       putXMMRegLane64F( gregOfRM(modrm), 0,
+//..                         unop(Iop_F32toF64, mkexpr(f32lo)) );
+//.. 
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* F2 0F 2D = CVTSD2SI -- convert F64 in mem/low half xmm to
+//..       I32 in ireg, according to prevailing SSE rounding mode */
+//..    /* F2 0F 2C = CVTTSD2SI -- convert F64 in mem/low half xmm to
+//..       I32 in ireg, according to prevailing SSE rounding mode */
+//..    if (insn[0] == 0xF2 && insn[1] == 0x0F 
+//..        && (insn[2] == 0x2D || insn[2] == 0x2C)) {
+//..       IRTemp rmode = newTemp(Ity_I32);
+//..       IRTemp f64lo = newTemp(Ity_F64);
+//..       Bool   r2zero = insn[2] == 0x2C;
+//..       vassert(sz == 4);
+//.. 
+//..       modrm = getIByte(delta+3);
+//..       if (epartIsReg(modrm)) {
+//..          delta += 3+1;
+//..    assign(f64lo, getXMMRegLane64F(eregOfRM(modrm), 0));
+//..          DIP("cvt%ssd2si %s,%s\n", r2zero ? "t" : "",
+//..                                    nameXMMReg(eregOfRM(modrm)),
+//..                                    nameIReg(4, gregOfRM(modrm)));
+//..       } else {
+//..          addr = disAMode ( &alen, sorb, delta+3, dis_buf );
+//..    assign(f64lo, loadLE(Ity_F64, mkexpr(addr)));
+//..          delta += 3+alen;
+//..          DIP("cvt%ssd2si %s,%s\n", r2zero ? "t" : "",
+//..                                    dis_buf,
+//..                                    nameIReg(4, gregOfRM(modrm)));
+//..       }
+//.. 
+//..       if (r2zero) {
+//..          assign( rmode, mkU32((UInt)Irrm_ZERO) );
+//..       } else {
+//..          assign( rmode, get_sse_roundingmode() );
+//..       }
+//.. 
+//..       putIReg(4, gregOfRM(modrm),
+//..                  binop( Iop_F64toI32, mkexpr(rmode), mkexpr(f64lo)) );
+//.. 
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* F2 0F 5A = CVTSD2SS -- convert F64 in mem/low half xmm to F32 in
+//..       low 1/4 xmm(G), according to prevailing SSE rounding mode */
+//..    if (insn[0] == 0xF2 && insn[1] == 0x0F && insn[2] == 0x5A) {
+//..       IRTemp rmode = newTemp(Ity_I32);
+//..       IRTemp f64lo = newTemp(Ity_F64);
+//..       vassert(sz == 4);
+//.. 
+//..       modrm = getIByte(delta+3);
+//..       if (epartIsReg(modrm)) {
+//..          delta += 3+1;
+//..    assign(f64lo, getXMMRegLane64F(eregOfRM(modrm), 0));
+//..          DIP("cvtsd2ss %s,%s\n", nameXMMReg(eregOfRM(modrm)),
+//..                                  nameXMMReg(gregOfRM(modrm)));
+//..       } else {
+//..          addr = disAMode ( &alen, sorb, delta+3, dis_buf );
+//..    assign(f64lo, loadLE(Ity_F64, mkexpr(addr)));
+//..          delta += 3+alen;
+//..          DIP("cvtsd2ss %s,%s\n", dis_buf,
+//..                                  nameXMMReg(gregOfRM(modrm)));
+//..       }
+//.. 
+//..       assign( rmode, get_sse_roundingmode() );
+//..       putXMMRegLane32F( 
+//..          gregOfRM(modrm), 0, 
+//..          binop( Iop_F64toF32, mkexpr(rmode), mkexpr(f64lo) )
+//..       );
+//.. 
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* F2 0F 2A = CVTSI2SD -- convert I32 in mem/ireg to F64 in low
+//..       half xmm */
+//..    if (insn[0] == 0xF2 && insn[1] == 0x0F && insn[2] == 0x2A) {
+//..       IRTemp arg32 = newTemp(Ity_I32);
+//..       vassert(sz == 4);
+//.. 
+//..       modrm = getIByte(delta+3);
+//..       if (epartIsReg(modrm)) {
+//..          assign( arg32, getIReg(4, eregOfRM(modrm)) );
+//..          delta += 3+1;
+//..          DIP("cvtsi2sd %s,%s\n", nameIReg(4, eregOfRM(modrm)),
+//..                                  nameXMMReg(gregOfRM(modrm)));
+//..       } else {
+//..          addr = disAMode ( &alen, sorb, delta+3, dis_buf );
+//..    assign( arg32, loadLE(Ity_I32, mkexpr(addr)) );
+//..          delta += 3+alen;
+//..          DIP("cvtsi2sd %s,%s\n", dis_buf,
+//..                                  nameXMMReg(gregOfRM(modrm)) );
+//..       }
+//.. 
+//..       putXMMRegLane64F( 
+//..          gregOfRM(modrm), 0,
+//..          unop(Iop_I32toF64, mkexpr(arg32)) );
+//.. 
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* F3 0F 5A = CVTSS2SD -- convert F32 in mem/low 1/4 xmm to F64 in
+//..       low half xmm(G) */
+//..    if (insn[0] == 0xF3 && insn[1] == 0x0F && insn[2] == 0x5A) {
+//..       IRTemp f32lo = newTemp(Ity_F32);
+//..       vassert(sz == 4);
+//.. 
+//..       modrm = getIByte(delta+3);
+//..       if (epartIsReg(modrm)) {
+//..          delta += 3+1;
+//..    assign(f32lo, getXMMRegLane32F(eregOfRM(modrm), 0));
+//..          DIP("cvtss2sd %s,%s\n", nameXMMReg(eregOfRM(modrm)),
+//..                                  nameXMMReg(gregOfRM(modrm)));
+//..       } else {
+//..          addr = disAMode ( &alen, sorb, delta+3, dis_buf );
+//..    assign(f32lo, loadLE(Ity_F32, mkexpr(addr)));
+//..          delta += 3+alen;
+//..          DIP("cvtss2sd %s,%s\n", dis_buf,
+//..                                  nameXMMReg(gregOfRM(modrm)));
+//..       }
+//.. 
+//..       putXMMRegLane64F( gregOfRM(modrm), 0, 
+//..                         unop( Iop_F32toF64, mkexpr(f32lo) ) );
+//.. 
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 66 0F E6 = CVTTPD2DQ -- convert 2 x F64 in mem/xmm to 2 x I32 in
+//..       lo half xmm(G), and zero upper half, rounding towards zero */
+//..    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xE6) {
+//..       IRTemp argV  = newTemp(Ity_V128);
+//..       IRTemp rmode = newTemp(Ity_I32);
+//.. 
+//..       modrm = getIByte(delta+2);
+//..       if (epartIsReg(modrm)) {
+//..          assign( argV, getXMMReg(eregOfRM(modrm)) );
+//..          delta += 2+1;
+//..          DIP("cvttpd2dq %s,%s\n", nameXMMReg(eregOfRM(modrm)),
+//..                                   nameXMMReg(gregOfRM(modrm)));
+//..       } else {
+//..          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
+//..    assign( argV, loadLE(Ity_V128, mkexpr(addr)) );
+//..          delta += 2+alen;
+//..          DIP("cvttpd2dq %s,%s\n", dis_buf,
+//..                                   nameXMMReg(gregOfRM(modrm)) );
+//..       }
+//.. 
+//..       assign( rmode, mkU32((UInt)Irrm_ZERO) );
+//.. 
+//..       t0 = newTemp(Ity_F64);
+//..       t1 = newTemp(Ity_F64);
+//..       assign( t0, unop(Iop_ReinterpI64asF64, 
+//..                        unop(Iop_128to64, mkexpr(argV))) );
+//..       assign( t1, unop(Iop_ReinterpI64asF64, 
+//..                        unop(Iop_128HIto64, mkexpr(argV))) );
+//..       
+//.. #     define CVT(_t)  binop( Iop_F64toI32,                    \
+//..                              mkexpr(rmode),                   \
+//..                              mkexpr(_t) )
+//..       
+//..       putXMMRegLane32( gregOfRM(modrm), 3, mkU32(0) );
+//..       putXMMRegLane32( gregOfRM(modrm), 2, mkU32(0) );
+//..       putXMMRegLane32( gregOfRM(modrm), 1, CVT(t1) );
+//..       putXMMRegLane32( gregOfRM(modrm), 0, CVT(t0) );
+//.. 
+//.. #     undef CVT
+//.. 
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* F3 0F 5B = CVTTPS2DQ -- convert 4 x F32 in mem/xmm to 4 x I32 in
+//..       xmm(G), rounding towards zero */
+//..    if (insn[0] == 0xF3 && insn[1] == 0x0F && insn[2] == 0x5B) {
+//..       IRTemp argV  = newTemp(Ity_V128);
+//..       IRTemp rmode = newTemp(Ity_I32);
+//..       vassert(sz == 4);
+//.. 
+//..       modrm = getIByte(delta+3);
+//..       if (epartIsReg(modrm)) {
+//..          assign( argV, getXMMReg(eregOfRM(modrm)) );
+//..          delta += 3+1;
+//..          DIP("cvttps2dq %s,%s\n", nameXMMReg(eregOfRM(modrm)),
+//..                                   nameXMMReg(gregOfRM(modrm)));
+//..       } else {
+//..          addr = disAMode ( &alen, sorb, delta+3, dis_buf );
+//..    assign( argV, loadLE(Ity_V128, mkexpr(addr)) );
+//..          delta += 3+alen;
+//..          DIP("cvttps2dq %s,%s\n", dis_buf,
+//..                                   nameXMMReg(gregOfRM(modrm)) );
+//..       }
+//..          
+//..       assign( rmode, mkU32((UInt)Irrm_ZERO) );
+//..       breakup128to32s( argV, &t3, &t2, &t1, &t0 );
+//.. 
+//..       /* This is less than ideal.  If it turns out to be a performance
+//..    bottleneck it can be improved. */
+//.. #     define CVT(_t)                            \
+//..         binop( Iop_F64toI32,                    \
+//..                mkexpr(rmode),                   \
+//..                unop( Iop_F32toF64,              \
+//..                      unop( Iop_ReinterpI32asF32, mkexpr(_t))) )
+//..       
+//..       putXMMRegLane32( gregOfRM(modrm), 3, CVT(t3) );
+//..       putXMMRegLane32( gregOfRM(modrm), 2, CVT(t2) );
+//..       putXMMRegLane32( gregOfRM(modrm), 1, CVT(t1) );
+//..       putXMMRegLane32( gregOfRM(modrm), 0, CVT(t0) );
+//.. 
+//.. #     undef CVT
+//.. 
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 66 0F 5E = DIVPD -- div 64Fx2 from R/M to R */
+//..    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x5E) {
+//..       delta = dis_SSE_E_to_G_all( sorb, delta+2, "divpd", Iop_Div64Fx2 );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* F2 0F 5E = DIVSD -- div 64F0x2 from R/M to R */
+//..    if (insn[0] == 0xF2 && insn[1] == 0x0F && insn[2] == 0x5E) {
+//..       vassert(sz == 4);
+//..       delta = dis_SSE_E_to_G_lo64( sorb, delta+3, "divsd", Iop_Div64F0x2 );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 0F AE /5 = LFENCE -- flush pending operations to memory */
+//..    /* 0F AE /6 = MFENCE -- flush pending operations to memory */
+//..    if (insn[0] == 0x0F && insn[1] == 0xAE
+//..        && epartIsReg(insn[2]) 
+//..        && (gregOfRM(insn[2]) == 5 || gregOfRM(insn[2]) == 6)) {
+//..       vassert(sz == 4);
+//..       delta += 3;
+//..       /* Insert a memory fence.  It's sometimes important that these
+//..          are carried through to the generated code. */
+//..       stmt( IRStmt_MFence() );
+//..       DIP("%sfence\n", gregOfRM(insn[2])==5 ? "l" : "m");
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 66 0F 5F = MAXPD -- max 64Fx2 from R/M to R */
+//..    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x5F) {
+//..       delta = dis_SSE_E_to_G_all( sorb, delta+2, "maxpd", Iop_Max64Fx2 );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* F2 0F 5F = MAXSD -- max 64F0x2 from R/M to R */
+//..    if (insn[0] == 0xF2 && insn[1] == 0x0F && insn[2] == 0x5F) {
+//..       vassert(sz == 4);
+//..       delta = dis_SSE_E_to_G_lo64( sorb, delta+3, "maxsd", Iop_Max64F0x2 );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 66 0F 5D = MINPD -- min 64Fx2 from R/M to R */
+//..    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x5D) {
+//..       delta = dis_SSE_E_to_G_all( sorb, delta+2, "minpd", Iop_Min64Fx2 );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* F2 0F 5D = MINSD -- min 64F0x2 from R/M to R */
+//..    if (insn[0] == 0xF2 && insn[1] == 0x0F && insn[2] == 0x5D) {
+//..       vassert(sz == 4);
+//..       delta = dis_SSE_E_to_G_lo64( sorb, delta+3, "minsd", Iop_Min64F0x2 );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 66 0F 28 = MOVAPD -- move from E (mem or xmm) to G (xmm). */
+//..    /* 66 0F 10 = MOVUPD -- move from E (mem or xmm) to G (xmm). */
+//..    /* 66 0F 6F = MOVDQA -- move from E (mem or xmm) to G (xmm). */
+//..    if (sz == 2 && insn[0] == 0x0F 
+//..        && (insn[1] == 0x28 || insn[1] == 0x10 || insn[1] == 0x6F)) {
+//..       HChar* wot = insn[1]==0x28 ? "apd" :
+//..                    insn[1]==0x10 ? "upd" : "dqa";
+//..       modrm = getIByte(delta+2);
+//..       if (epartIsReg(modrm)) {
+//..          putXMMReg( gregOfRM(modrm), 
+//..                     getXMMReg( eregOfRM(modrm) ));
+//..          DIP("mov%s %s,%s\n", wot, nameXMMReg(eregOfRM(modrm)),
+//..                                    nameXMMReg(gregOfRM(modrm)));
+//..          delta += 2+1;
+//..       } else {
+//..          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
+//..          putXMMReg( gregOfRM(modrm), 
+//..                     loadLE(Ity_V128, mkexpr(addr)) );
+//..          DIP("mov%s %s,%s\n", wot, dis_buf,
+//..                                    nameXMMReg(gregOfRM(modrm)));
+//..          delta += 2+alen;
+//..       }
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 66 0F 29 = MOVAPD -- move from G (xmm) to E (mem or xmm). */
+//..    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x29) {
+//..       modrm = getIByte(delta+2);
+//..       if (epartIsReg(modrm)) {
+//..          /* fall through; awaiting test case */
+//..       } else {
+//..          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
+//..          storeLE( mkexpr(addr), getXMMReg(gregOfRM(modrm)) );
+//..          DIP("movapd %s,%s\n", nameXMMReg(gregOfRM(modrm)),
+//..                                dis_buf );
+//..          delta += 2+alen;
+//..          goto decode_success;
+//..       }
+//..    }
+//.. 
+//..    /* 66 0F 6E = MOVD from r/m32 to xmm, zeroing high 3/4 of xmm. */
+//..    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x6E) {
+//..       modrm = getIByte(delta+2);
+//..       if (epartIsReg(modrm)) {
+//..          delta += 2+1;
+//..          putXMMReg(
+//..             gregOfRM(modrm),
+//..             unop( Iop_32Uto128, getIReg(4, eregOfRM(modrm)) ) 
+//..          );
+//..          DIP("movd %s, %s\n", 
+//..              nameIReg(4,eregOfRM(modrm)), nameXMMReg(gregOfRM(modrm)));
+//..       } else {
+//..          addr = disAMode( &alen, sorb, delta+2, dis_buf );
+//..          delta += 2+alen;
+//..          putXMMReg(
+//..             gregOfRM(modrm),
+//..             unop( Iop_32Uto128,loadLE(Ity_I32, mkexpr(addr)) ) 
+//..          );
+//..          DIP("movd %s, %s\n", dis_buf, nameXMMReg(gregOfRM(modrm)));
+//..       }
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 66 0F 7E = MOVD from xmm low 1/4 to r/m32. */
+//..    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x7E) {
+//..       modrm = getIByte(delta+2);
+//..       if (epartIsReg(modrm)) {
+//..          delta += 2+1;
+//..          putIReg( 4, eregOfRM(modrm),
+//..                   getXMMRegLane32(gregOfRM(modrm), 0) );
+//..          DIP("movd %s, %s\n", 
+//..              nameXMMReg(gregOfRM(modrm)), nameIReg(4,eregOfRM(modrm)));
+//..       } else {
+//..          addr = disAMode( &alen, sorb, delta+2, dis_buf );
+//..          delta += 2+alen;
+//..          storeLE( mkexpr(addr),
+//..                   getXMMRegLane32(gregOfRM(modrm), 0) );
+//..          DIP("movd %s, %s\n", nameXMMReg(gregOfRM(modrm)), dis_buf);
+//..       }
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 66 0F 7F = MOVDQA -- move from G (xmm) to E (mem or xmm). */
+//..    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x7F) {
+//..       modrm = getIByte(delta+2);
+//..       if (epartIsReg(modrm)) {
+//..          delta += 2+1;
+//..          putXMMReg( eregOfRM(modrm),
+//..                     getXMMReg(gregOfRM(modrm)) );
+//..          DIP("movdqa %s, %s\n", nameXMMReg(gregOfRM(modrm)), 
+//..                                 nameXMMReg(eregOfRM(modrm)));
+//..       } else {
+//..          addr = disAMode( &alen, sorb, delta+2, dis_buf );
+//..          delta += 2+alen;
+//..          storeLE( mkexpr(addr), getXMMReg(gregOfRM(modrm)) );
+//..          DIP("movdqa %s, %s\n", nameXMMReg(gregOfRM(modrm)), dis_buf);
+//..       }
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* F3 0F 6F = MOVDQU -- move from E (mem or xmm) to G (xmm). */
+//..    /* Unfortunately can't simply use the MOVDQA case since the
+//..       prefix lengths are different (66 vs F3) */
+//..    if (insn[0] == 0xF3 && insn[1] == 0x0F && insn[2] == 0x6F) {
+//..       vassert(sz == 4);
+//..       modrm = getIByte(delta+3);
+//..       if (epartIsReg(modrm)) {
+//..          putXMMReg( gregOfRM(modrm), 
+//..                     getXMMReg( eregOfRM(modrm) ));
+//..          DIP("movdqu %s,%s\n", nameXMMReg(eregOfRM(modrm)),
+//..                                nameXMMReg(gregOfRM(modrm)));
+//..          delta += 3+1;
+//..       } else {
+//..          addr = disAMode ( &alen, sorb, delta+3, dis_buf );
+//..          putXMMReg( gregOfRM(modrm), 
+//..                     loadLE(Ity_V128, mkexpr(addr)) );
+//..          DIP("movdqu %s,%s\n", dis_buf,
+//..                                nameXMMReg(gregOfRM(modrm)));
+//..          delta += 3+alen;
+//..       }
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* F3 0F 7F = MOVDQU -- move from G (xmm) to E (mem or xmm). */
+//..    /* Unfortunately can't simply use the MOVDQA case since the
+//..       prefix lengths are different (66 vs F3) */
+//..    if (insn[0] == 0xF3 && insn[1] == 0x0F && insn[2] == 0x7F) {
+//..       vassert(sz == 4);
+//..       modrm = getIByte(delta+3);
+//..       if (epartIsReg(modrm)) {
+//..          delta += 3+1;
+//..          putXMMReg( eregOfRM(modrm),
+//..                     getXMMReg(gregOfRM(modrm)) );
+//..          DIP("movdqu %s, %s\n", nameXMMReg(gregOfRM(modrm)), 
+//..                                 nameXMMReg(eregOfRM(modrm)));
+//..       } else {
+//..          addr = disAMode( &alen, sorb, delta+3, dis_buf );
+//..          delta += 3+alen;
+//..          storeLE( mkexpr(addr), getXMMReg(gregOfRM(modrm)) );
+//..          DIP("movdqu %s, %s\n", nameXMMReg(gregOfRM(modrm)), dis_buf);
+//..       }
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* F2 0F D6 = MOVDQ2Q -- move from E (lo half xmm, not mem) to G (mmx). */
+//..    if (insn[0] == 0xF2 && insn[1] == 0x0F && insn[2] == 0xD6) {
+//..       vassert(sz == 4);
+//..       modrm = getIByte(delta+3);
+//..       if (epartIsReg(modrm)) {
+//..          do_MMX_preamble();
+//..          putMMXReg( gregOfRM(modrm), 
+//..                     getXMMRegLane64( eregOfRM(modrm), 0 ));
+//..          DIP("movdq2q %s,%s\n", nameXMMReg(eregOfRM(modrm)),
+//..                                 nameMMXReg(gregOfRM(modrm)));
+//..          delta += 3+1;
+//..          goto decode_success;
+//..       } else {
+//..          /* fall through, apparently no mem case for this insn */
+//..       }
+//..    }
+//.. 
+//..    /* 66 0F 16 = MOVHPD -- move from mem to high half of XMM. */
+//..    /* These seems identical to MOVHPS.  This instruction encoding is
+//..       completely crazy. */
+//..    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x16) {
+//..       modrm = getIByte(delta+2);
+//..       if (epartIsReg(modrm)) {
+//..          /* fall through; apparently reg-reg is not possible */
+//..       } else {
+//..          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
+//..          delta += 2+alen;
+//..          putXMMRegLane64( gregOfRM(modrm), 1/*upper lane*/,
+//..                           loadLE(Ity_I64, mkexpr(addr)) );
+//..          DIP("movhpd %s,%s\n", dis_buf, 
+//..                                nameXMMReg( gregOfRM(modrm) ));
+//..          goto decode_success;
+//..       }
+//..    }
+//.. 
+//..    /* 66 0F 17 = MOVHPD -- move from high half of XMM to mem. */
+//..    /* Again, this seems identical to MOVHPS. */
+//..    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x17) {
+//..       if (!epartIsReg(insn[2])) {
+//..          delta += 2;
+//..          addr = disAMode ( &alen, sorb, delta, dis_buf );
+//..          delta += alen;
+//..          storeLE( mkexpr(addr), 
+//..                   getXMMRegLane64( gregOfRM(insn[2]),
+//..                                    1/*upper lane*/ ) );
+//..          DIP("movhpd %s,%s\n", nameXMMReg( gregOfRM(insn[2]) ),
+//..                                dis_buf);
+//..          goto decode_success;
+//..       }
+//..       /* else fall through */
+//..    }
+//.. 
+//..    /* 66 0F 12 = MOVLPD -- move from mem to low half of XMM. */
+//..    /* Identical to MOVLPS ? */
+//..    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x12) {
+//..       modrm = getIByte(delta+2);
+//..       if (epartIsReg(modrm)) {
+//..          /* fall through; apparently reg-reg is not possible */
+//..       } else {
+//..          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
+//..          delta += 2+alen;
+//..          putXMMRegLane64( gregOfRM(modrm),  0/*lower lane*/,
+//..                           loadLE(Ity_I64, mkexpr(addr)) );
+//..          DIP("movlpd %s, %s\n", 
+//..              dis_buf, nameXMMReg( gregOfRM(modrm) ));
+//..          goto decode_success;
+//..       }
+//..    }
+//.. 
+//..    /* 66 0F 13 = MOVLPD -- move from low half of XMM to mem. */
+//..    /* Identical to MOVLPS ? */
+//..    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x13) {
+//..       if (!epartIsReg(insn[2])) {
+//..          delta += 2;
+//..          addr = disAMode ( &alen, sorb, delta, dis_buf );
+//..          delta += alen;
+//..          storeLE( mkexpr(addr), 
+//..                   getXMMRegLane64( gregOfRM(insn[2]), 
+//..                                    0/*lower lane*/ ) );
+//..          DIP("movlpd %s, %s\n", nameXMMReg( gregOfRM(insn[2]) ),
+//..                                 dis_buf);
+//..          goto decode_success;
+//..       }
+//..       /* else fall through */
+//..    }
+//.. 
+//..    /* 66 0F 50 = MOVMSKPD - move 2 sign bits from 2 x F64 in xmm(E) to
+//..       2 lowest bits of ireg(G) */
+//..    if (insn[0] == 0x0F && insn[1] == 0x50) {
+//..       modrm = getIByte(delta+2);
+//..       if (sz == 2 && epartIsReg(modrm)) {
+//..          Int src;
+//..          t0 = newTemp(Ity_I32);
+//..          t1 = newTemp(Ity_I32);
+//..          delta += 2+1;
+//..          src = eregOfRM(modrm);
+//..          assign( t0, binop( Iop_And32,
+//..                             binop(Iop_Shr32, getXMMRegLane32(src,1), mkU8(31)),
+//..                             mkU32(1) ));
+//..          assign( t1, binop( Iop_And32,
+//..                             binop(Iop_Shr32, getXMMRegLane32(src,3), mkU8(30)),
+//..                             mkU32(2) ));
+//..          putIReg(4, gregOfRM(modrm),
+//..                     binop(Iop_Or32, mkexpr(t0), mkexpr(t1))
+//..                  );
+//..          DIP("movmskpd %s,%s\n", nameXMMReg(src), 
+//..                                  nameIReg(4, gregOfRM(modrm)));
+//..          goto decode_success;
+//..       }
+//..       /* else fall through */
+//..    }
+//.. 
+//..    /* 66 0F E7 = MOVNTDQ -- for us, just a plain SSE store. */
+//..    if (insn[0] == 0x0F && insn[1] == 0xE7) {
+//..       modrm = getIByte(delta+2);
+//..       if (sz == 2 && !epartIsReg(modrm)) {
+//..          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
+//..          storeLE( mkexpr(addr), getXMMReg(gregOfRM(modrm)) );
+//..          DIP("movntdq %s,%s\n", dis_buf,
+//..                                 nameXMMReg(gregOfRM(modrm)));
+//..          delta += 2+alen;
+//..          goto decode_success;
+//..       }
+//..       /* else fall through */
+//..    }
+//.. 
+//..    /* 0F C3 = MOVNTI -- for us, just a plain ireg store. */
+//..    if (insn[0] == 0x0F && insn[1] == 0xC3) {
+//..       vassert(sz == 4);
+//..       modrm = getIByte(delta+2);
+//..       if (!epartIsReg(modrm)) {
+//..          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
+//..          storeLE( mkexpr(addr), getIReg(4, gregOfRM(modrm)) );
+//..          DIP("movnti %s,%s\n", dis_buf,
+//..                                nameIReg(4, gregOfRM(modrm)));
+//..          delta += 2+alen;
+//..          goto decode_success;
+//..       }
+//..       /* else fall through */
+//..    }
+//.. 
+//..    /* 66 0F D6 = MOVQ -- move 64 bits from G (lo half xmm) to E (mem
+//..       or lo half xmm).  */
+//..    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xD6) {
+//..       modrm = getIByte(delta+2);
+//..       if (epartIsReg(modrm)) {
+//..          /* fall through, awaiting test case */
+//..       } else {
+//..          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
+//..          storeLE( mkexpr(addr), 
+//..                   getXMMRegLane64( gregOfRM(modrm), 0 ));
+//..          DIP("movq %s,%s\n", nameXMMReg(gregOfRM(modrm)), dis_buf );
+//..          delta += 2+alen;
+//..          goto decode_success;
+//..       }
+//..    }
+//.. 
+//..    /* F3 0F D6 = MOVQ2DQ -- move from E (mmx) to G (lo half xmm, zero
+//..       hi half). */
+//..    if (insn[0] == 0xF3 && insn[1] == 0x0F && insn[2] == 0xD6) {
+//..       vassert(sz == 4);
+//..       modrm = getIByte(delta+3);
+//..       if (epartIsReg(modrm)) {
+//..          do_MMX_preamble();
+//..          putXMMReg( gregOfRM(modrm), 
+//..                     unop(Iop_64Uto128, getMMXReg( eregOfRM(modrm) )) );
+//..          DIP("movq2dq %s,%s\n", nameMMXReg(eregOfRM(modrm)),
+//..                                 nameXMMReg(gregOfRM(modrm)));
+//..          delta += 3+1;
+//..          goto decode_success;
+//..       } else {
+//..          /* fall through, apparently no mem case for this insn */
+//..       }
+//..    }
+//.. 
+//..    /* F3 0F 7E = MOVQ -- move 64 bits from E (mem or lo half xmm) to
+//..       G (lo half xmm).  If E is mem, upper half of G is zeroed out. */
+//..    /* F2 0F 10 = MOVSD -- move 64 bits from E (mem or lo half xmm) to
+//..       G (lo half xmm).  If E is mem, upper half of G is zeroed out.
+//..       (original defn) */
+//..    if ((insn[0] == 0xF2 && insn[1] == 0x0F && insn[2] == 0x10)
+//..        || (insn[0] == 0xF3 && insn[1] == 0x0F && insn[2] == 0x7E)) {
+//..       vassert(sz == 4);
+//..       modrm = getIByte(delta+3);
+//..       if (epartIsReg(modrm)) {
+//..          putXMMRegLane64( gregOfRM(modrm), 0,
+//..                           getXMMRegLane64( eregOfRM(modrm), 0 ));
+//..          DIP("movsd %s,%s\n", nameXMMReg(eregOfRM(modrm)),
+//..                               nameXMMReg(gregOfRM(modrm)));
+//..          delta += 3+1;
+//..       } else {
+//..          addr = disAMode ( &alen, sorb, delta+3, dis_buf );
+//..          putXMMReg( gregOfRM(modrm), mkV128(0) );
+//..          putXMMRegLane64( gregOfRM(modrm), 0,
+//..                           loadLE(Ity_I64, mkexpr(addr)) );
+//..          DIP("movsd %s,%s\n", dis_buf,
+//..                               nameXMMReg(gregOfRM(modrm)));
+//..          delta += 3+alen;
+//..       }
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* F2 0F 11 = MOVSD -- move 64 bits from G (lo half xmm) to E (mem
+//..       or lo half xmm). */
+//..    if (insn[0] == 0xF2 && insn[1] == 0x0F && insn[2] == 0x11) {
+//..       vassert(sz == 4);
+//..       modrm = getIByte(delta+3);
+//..       if (epartIsReg(modrm)) {
+//..          /* fall through, we don't yet have a test case */
+//..       } else {
+//..          addr = disAMode ( &alen, sorb, delta+3, dis_buf );
+//..          storeLE( mkexpr(addr),
+//..                   getXMMRegLane64(gregOfRM(modrm), 0) );
+//..          DIP("movsd %s,%s\n", nameXMMReg(gregOfRM(modrm)),
+//..                               dis_buf);
+//..          delta += 3+alen;
+//..          goto decode_success;
+//..       }
+//..    }
+//.. 
+//..    /* 66 0F 59 = MULPD -- mul 64Fx2 from R/M to R */
+//..    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x59) {
+//..       delta = dis_SSE_E_to_G_all( sorb, delta+2, "mulpd", Iop_Mul64Fx2 );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* F2 0F 59 = MULSD -- mul 64F0x2 from R/M to R */
+//..    if (insn[0] == 0xF2 && insn[1] == 0x0F && insn[2] == 0x59) {
+//..       vassert(sz == 4);
+//..       delta = dis_SSE_E_to_G_lo64( sorb, delta+3, "mulsd", Iop_Mul64F0x2 );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 66 0F 56 = ORPD -- G = G and E */
+//..    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x56) {
+//..       delta = dis_SSE_E_to_G_all( sorb, delta+2, "orpd", Iop_Or128 );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 66 0F C6 /r ib = SHUFPD -- shuffle packed F64s */
+//..    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xC6) {
+//..       Int    select;
+//..       IRTemp sV = newTemp(Ity_V128);
+//..       IRTemp dV = newTemp(Ity_V128);
+//..       IRTemp s1 = newTemp(Ity_I64);
+//..       IRTemp s0 = newTemp(Ity_I64);
+//..       IRTemp d1 = newTemp(Ity_I64);
+//..       IRTemp d0 = newTemp(Ity_I64);
+//.. 
+//..       modrm = insn[2];
+//..       assign( dV, getXMMReg(gregOfRM(modrm)) );
+//.. 
+//..       if (epartIsReg(modrm)) {
+//..          assign( sV, getXMMReg(eregOfRM(modrm)) );
+//..          select = (Int)insn[3];
+//..          delta += 2+2;
+//..          DIP("shufpd $%d,%s,%s\n", select, 
+//..                                    nameXMMReg(eregOfRM(modrm)),
+//..                                    nameXMMReg(gregOfRM(modrm)));
+//..       } else {
+//..          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
+//..          assign( sV, loadLE(Ity_V128, mkexpr(addr)) );
+//..          select = (Int)insn[2+alen];
+//..          delta += 3+alen;
+//..          DIP("shufpd $%d,%s,%s\n", select, 
+//..                                    dis_buf,
+//..                                    nameXMMReg(gregOfRM(modrm)));
+//..       }
+//.. 
+//..       assign( d1, unop(Iop_128HIto64, mkexpr(dV)) );
+//..       assign( d0, unop(Iop_128to64,   mkexpr(dV)) );
+//..       assign( s1, unop(Iop_128HIto64, mkexpr(sV)) );
+//..       assign( s0, unop(Iop_128to64,   mkexpr(sV)) );
+//.. 
+//.. #     define SELD(n) mkexpr((n)==0 ? d0 : d1)
+//.. #     define SELS(n) mkexpr((n)==0 ? s0 : s1)
+//.. 
+//..       putXMMReg(
+//..          gregOfRM(modrm), 
+//..          binop(Iop_64HLto128, SELS((select>>1)&1), SELD((select>>0)&1) )
+//..       );
+//.. 
+//.. #     undef SELD
+//.. #     undef SELS
+//.. 
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 66 0F 51 = SQRTPD -- approx sqrt 64Fx2 from R/M to R */
+//..    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x51) {
+//..       delta = dis_SSE_E_to_G_unary_all( sorb, delta+2, 
+//..                                         "sqrtpd", Iop_Sqrt64Fx2 );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* F2 0F 51 = SQRTSD -- approx sqrt 64F0x2 from R/M to R */
+//..    if (insn[0] == 0xF2 && insn[1] == 0x0F && insn[2] == 0x51) {
+//..       vassert(sz == 4);
+//..       delta = dis_SSE_E_to_G_unary_lo64( sorb, delta+3, 
+//..                                          "sqrtsd", Iop_Sqrt64F0x2 );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 66 0F 5C = SUBPD -- sub 64Fx2 from R/M to R */
+//..    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x5C) {
+//..       delta = dis_SSE_E_to_G_all( sorb, delta+2, "subpd", Iop_Sub64Fx2 );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* F2 0F 5C = SUBSD -- sub 64F0x2 from R/M to R */
+//..    if (insn[0] == 0xF2 && insn[1] == 0x0F && insn[2] == 0x5C) {
+//..       vassert(sz == 4);
+//..       delta = dis_SSE_E_to_G_lo64( sorb, delta+3, "subsd", Iop_Sub64F0x2 );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 66 0F 15 = UNPCKHPD -- unpack and interleave high part F64s */
+//..    /* 66 0F 14 = UNPCKLPD -- unpack and interleave low part F64s */
+//..    /* These just appear to be special cases of SHUFPS */
+//..    if (sz == 2 && insn[0] == 0x0F && (insn[1] == 0x15 || insn[1] == 0x14)) {
+//..       IRTemp s1 = newTemp(Ity_I64);
+//..       IRTemp s0 = newTemp(Ity_I64);
+//..       IRTemp d1 = newTemp(Ity_I64);
+//..       IRTemp d0 = newTemp(Ity_I64);
+//..       IRTemp sV = newTemp(Ity_V128);
+//..       IRTemp dV = newTemp(Ity_V128);
+//..       Bool   hi = insn[1] == 0x15;
+//.. 
+//..       modrm = insn[2];
+//..       assign( dV, getXMMReg(gregOfRM(modrm)) );
+//.. 
+//..       if (epartIsReg(modrm)) {
+//..          assign( sV, getXMMReg(eregOfRM(modrm)) );
+//..          delta += 2+1;
+//..          DIP("unpck%sps %s,%s\n", hi ? "h" : "l",
+//..                                   nameXMMReg(eregOfRM(modrm)),
+//..                                   nameXMMReg(gregOfRM(modrm)));
+//..       } else {
+//..          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
+//..          assign( sV, loadLE(Ity_V128, mkexpr(addr)) );
+//..          delta += 2+alen;
+//..          DIP("unpck%sps %s,%s\n", hi ? "h" : "l",
+//..                                   dis_buf,
+//..                                   nameXMMReg(gregOfRM(modrm)));
+//..       }
+//.. 
+//..       assign( d1, unop(Iop_128HIto64, mkexpr(dV)) );
+//..       assign( d0, unop(Iop_128to64,   mkexpr(dV)) );
+//..       assign( s1, unop(Iop_128HIto64, mkexpr(sV)) );
+//..       assign( s0, unop(Iop_128to64,   mkexpr(sV)) );
+//.. 
+//..       if (hi) {
+//..          putXMMReg( gregOfRM(modrm), 
+//..                     binop(Iop_64HLto128, mkexpr(s1), mkexpr(d1)) );
+//..       } else {
+//..          putXMMReg( gregOfRM(modrm), 
+//..                     binop(Iop_64HLto128, mkexpr(s0), mkexpr(d0)) );
+//..       }
+//.. 
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 66 0F 57 = XORPD -- G = G and E */
+//..    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x57) {
+//..       delta = dis_SSE_E_to_G_all( sorb, delta+2, "xorpd", Iop_Xor128 );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 66 0F 6B = PACKSSDW */
+//..    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x6B) {
+//..       delta = dis_SSEint_E_to_G( sorb, delta+2, 
+//..                                  "packssdw", Iop_QNarrow32Sx4, True );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 66 0F 63 = PACKSSWB */
+//..    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x63) {
+//..       delta = dis_SSEint_E_to_G( sorb, delta+2, 
+//..                                  "packsswb", Iop_QNarrow16Sx8, True );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 66 0F 67 = PACKUSWB */
+//..    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x67) {
+//..       delta = dis_SSEint_E_to_G( sorb, delta+2, 
+//..                                  "packuswb", Iop_QNarrow16Ux8, True );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 66 0F FC = PADDB */
+//..    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xFC) {
+//..       delta = dis_SSEint_E_to_G( sorb, delta+2, 
+//..                                  "paddb", Iop_Add8x16, False );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 66 0F FE = PADDD */
+//..    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xFE) {
+//..       delta = dis_SSEint_E_to_G( sorb, delta+2, 
+//..                                  "paddd", Iop_Add32x4, False );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* ***--- this is an MMX class insn introduced in SSE2 ---*** */
+//..    /* 0F D4 = PADDQ -- add 64x1 */
+//..    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0xD4) {
+//..       do_MMX_preamble();
+//..       delta = dis_MMXop_regmem_to_reg ( 
+//..                 sorb, delta+2, insn[1], "paddq", False );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 66 0F D4 = PADDQ */
+//..    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xD4) {
+//..       delta = dis_SSEint_E_to_G( sorb, delta+2, 
+//..                                  "paddq", Iop_Add64x2, False );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 66 0F FD = PADDW */
+//..    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xFD) {
+//..       delta = dis_SSEint_E_to_G( sorb, delta+2, 
+//..                                  "paddw", Iop_Add16x8, False );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 66 0F EC = PADDSB */
+//..    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xEC) {
+//..       delta = dis_SSEint_E_to_G( sorb, delta+2, 
+//..                                  "paddsb", Iop_QAdd8Sx16, False );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 66 0F ED = PADDSW */
+//..    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xED) {
+//..       delta = dis_SSEint_E_to_G( sorb, delta+2, 
+//..                                  "paddsw", Iop_QAdd16Sx8, False );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 66 0F DC = PADDUSB */
+//..    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xDC) {
+//..       delta = dis_SSEint_E_to_G( sorb, delta+2, 
+//..                                  "paddusb", Iop_QAdd8Ux16, False );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 66 0F DD = PADDUSW */
+//..    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xDD) {
+//..       delta = dis_SSEint_E_to_G( sorb, delta+2, 
+//..                                  "paddusw", Iop_QAdd16Ux8, False );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 66 0F DB = PAND */
+//..    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xDB) {
+//..       delta = dis_SSE_E_to_G_all( sorb, delta+2, "pand", Iop_And128 );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 66 0F DF = PANDN */
+//..    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xDF) {
+//..       delta = dis_SSE_E_to_G_all_invG( sorb, delta+2, "pandn", Iop_And128 );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 66 0F E0 = PAVGB */
+//..    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xE0) {
+//..       delta = dis_SSEint_E_to_G( sorb, delta+2, 
+//..                                  "pavgb", Iop_Avg8Ux16, False );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 66 0F E3 = PAVGW */
+//..    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xE3) {
+//..       delta = dis_SSEint_E_to_G( sorb, delta+2, 
+//..                                  "pavgw", Iop_Avg16Ux8, False );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 66 0F 74 = PCMPEQB */
+//..    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x74) {
+//..       delta = dis_SSEint_E_to_G( sorb, delta+2, 
+//..                                  "pcmpeqb", Iop_CmpEQ8x16, False );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 66 0F 76 = PCMPEQD */
+//..    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x76) {
+//..       delta = dis_SSEint_E_to_G( sorb, delta+2, 
+//..                                  "pcmpeqd", Iop_CmpEQ32x4, False );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 66 0F 75 = PCMPEQW */
+//..    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x75) {
+//..       delta = dis_SSEint_E_to_G( sorb, delta+2, 
+//..                                  "pcmpeqw", Iop_CmpEQ16x8, False );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 66 0F 64 = PCMPGTB */
+//..    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x64) {
+//..       delta = dis_SSEint_E_to_G( sorb, delta+2, 
+//..                                  "pcmpgtb", Iop_CmpGT8Sx16, False );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 66 0F 66 = PCMPGTD */
+//..    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x66) {
+//..       delta = dis_SSEint_E_to_G( sorb, delta+2, 
+//..                                  "pcmpgtd", Iop_CmpGT32Sx4, False );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 66 0F 65 = PCMPGTW */
+//..    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x65) {
+//..       delta = dis_SSEint_E_to_G( sorb, delta+2, 
+//..                                  "pcmpgtw", Iop_CmpGT16Sx8, False );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 66 0F C5 = PEXTRW -- extract 16-bit field from xmm(E) and put 
+//..       zero-extend of it in ireg(G). */
+//..    if (insn[0] == 0x0F && insn[1] == 0xC5) {
+//..       modrm = insn[2];
+//..       if (sz == 2 && epartIsReg(modrm)) {
+//..          t5 = newTemp(Ity_V128);
+//..          t4 = newTemp(Ity_I16);
+//..          assign(t5, getXMMReg(eregOfRM(modrm)));
+//..          breakup128to32s( t5, &t3, &t2, &t1, &t0 );
+//..          switch (insn[3] & 7) {
+//..             case 0:  assign(t4, unop(Iop_32to16,   mkexpr(t0))); break;
+//..             case 1:  assign(t4, unop(Iop_32HIto16, mkexpr(t0))); break;
+//..             case 2:  assign(t4, unop(Iop_32to16,   mkexpr(t1))); break;
+//..             case 3:  assign(t4, unop(Iop_32HIto16, mkexpr(t1))); break;
+//..             case 4:  assign(t4, unop(Iop_32to16,   mkexpr(t2))); break;
+//..             case 5:  assign(t4, unop(Iop_32HIto16, mkexpr(t2))); break;
+//..             case 6:  assign(t4, unop(Iop_32to16,   mkexpr(t3))); break;
+//..             case 7:  assign(t4, unop(Iop_32HIto16, mkexpr(t3))); break;
+//..             default: vassert(0);
+//..          }
+//..          putIReg(4, gregOfRM(modrm), unop(Iop_16Uto32, mkexpr(t4)));
+//..          DIP("pextrw $%d,%s,%s\n",
+//..              (Int)insn[3], nameXMMReg(eregOfRM(modrm)),
+//..                            nameIReg(4,gregOfRM(modrm)));
+//..          delta += 4;
+//..          goto decode_success;
+//..       } 
+//..       /* else fall through */
+//..    }
+//.. 
+//..    /* 66 0F C4 = PINSRW -- get 16 bits from E(mem or low half ireg) and
+//..       put it into the specified lane of xmm(G). */
+//..    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xC4) {
+//..       Int lane;
+//..       t4 = newTemp(Ity_I16);
+//..       modrm = insn[2];
+//.. 
+//..       if (epartIsReg(modrm)) {
+//..          assign(t4, getIReg(2, eregOfRM(modrm)));
+//..          lane = insn[3];
+//..          delta += 2+2;
+//..          DIP("pinsrw $%d,%s,%s\n", (Int)lane, 
+//..                                    nameIReg(2,eregOfRM(modrm)),
+//..                                    nameXMMReg(gregOfRM(modrm)));
+//..       } else {
+//..          /* awaiting test case */
+//..          goto decode_failure;
+//..       }
+//.. 
+//..       putXMMRegLane16( gregOfRM(modrm), lane & 7, mkexpr(t4) );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 66 0F EE = PMAXSW -- 16x8 signed max */
+//..    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xEE) {
+//..       delta = dis_SSEint_E_to_G( sorb, delta+2, 
+//..                                  "pmaxsw", Iop_Max16Sx8, False );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 66 0F DE = PMAXUB -- 8x16 unsigned max */
+//..    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xDE) {
+//..       delta = dis_SSEint_E_to_G( sorb, delta+2, 
+//..                                  "pmaxub", Iop_Max8Ux16, False );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 66 0F EA = PMINSW -- 16x8 signed min */
+//..    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xEA) {
+//..       delta = dis_SSEint_E_to_G( sorb, delta+2, 
+//..                                  "pminsw", Iop_Min16Sx8, False );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 66 0F DA = PMINUB -- 8x16 unsigned min */
+//..    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xDA) {
+//..       delta = dis_SSEint_E_to_G( sorb, delta+2, 
+//..                                  "pminub", Iop_Min8Ux16, False );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 66 0F D7 = PMOVMSKB -- extract sign bits from each of 16 lanes in
+//..       xmm(G), turn them into a byte, and put zero-extend of it in
+//..       ireg(G).  Doing this directly is just too cumbersome; give up
+//..       therefore and call a helper. */
+//..    /* UInt x86g_calculate_sse_pmovmskb ( ULong w64hi, ULong w64lo ); */
+//..    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xD7) {
+//..       modrm = insn[2];
+//..       if (epartIsReg(modrm)) {
+//..          t0 = newTemp(Ity_I64);
+//..          t1 = newTemp(Ity_I64);
+//..          assign(t0, getXMMRegLane64(eregOfRM(modrm), 0));
+//..          assign(t1, getXMMRegLane64(eregOfRM(modrm), 1));
+//..          t5 = newTemp(Ity_I32);
+//..          assign(t5, mkIRExprCCall(
+//..                        Ity_I32, 0/*regparms*/, 
+//..                        "x86g_calculate_sse_pmovmskb",
+//..                        &x86g_calculate_sse_pmovmskb,
+//..                        mkIRExprVec_2( mkexpr(t1), mkexpr(t0) )));
+//..          putIReg(4, gregOfRM(modrm), mkexpr(t5));
+//..          DIP("pmovmskb %s,%s\n", nameXMMReg(eregOfRM(modrm)),
+//..                                  nameIReg(4,gregOfRM(modrm)));
+//..          delta += 3;
+//..          goto decode_success;
+//..       } 
+//..       /* else fall through */
+//..    }
+//.. 
+//..    /* 66 0F E4 = PMULHUW -- 16x8 hi-half of unsigned widening multiply */
+//..    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xE4) {
+//..       delta = dis_SSEint_E_to_G( sorb, delta+2, 
+//..                                  "pmulhuw", Iop_MulHi16Ux8, False );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 66 0F E5 = PMULHW -- 16x8 hi-half of signed widening multiply */
+//..    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xE5) {
+//..       delta = dis_SSEint_E_to_G( sorb, delta+2, 
+//..                                  "pmulhw", Iop_MulHi16Sx8, False );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 66 0F D5 = PMULHL -- 16x8 multiply */
+//..    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xD5) {
+//..       delta = dis_SSEint_E_to_G( sorb, delta+2, 
+//..                                  "pmullw", Iop_Mul16x8, False );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* ***--- this is an MMX class insn introduced in SSE2 ---*** */
+//..    /* 0F F4 = PMULUDQ -- unsigned widening multiply of 32-lanes 0 x
+//..       0 to form 64-bit result */
+//..    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0xF4) {
+//..       IRTemp sV = newTemp(Ity_I64);
+//..       IRTemp dV = newTemp(Ity_I64);
+//..       t1 = newTemp(Ity_I32);
+//..       t0 = newTemp(Ity_I32);
+//..       modrm = insn[2];
+//.. 
+//..       do_MMX_preamble();
+//..       assign( dV, getMMXReg(gregOfRM(modrm)) );
+//.. 
+//..       if (epartIsReg(modrm)) {
+//..          assign( sV, getMMXReg(eregOfRM(modrm)) );
+//..          delta += 2+1;
+//..          DIP("pmuludq %s,%s\n", nameMMXReg(eregOfRM(modrm)),
+//..                                 nameMMXReg(gregOfRM(modrm)));
+//..       } else {
+//..          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
+//..          assign( sV, loadLE(Ity_I64, mkexpr(addr)) );
+//..          delta += 2+alen;
+//..          DIP("pmuludq %s,%s\n", dis_buf,
+//..                                 nameMMXReg(gregOfRM(modrm)));
+//..       }
+//.. 
+//..       assign( t0, unop(Iop_64to32, mkexpr(dV)) );
+//..       assign( t1, unop(Iop_64to32, mkexpr(sV)) );
+//..       putMMXReg( gregOfRM(modrm),
+//..                  binop( Iop_MullU32, mkexpr(t0), mkexpr(t1) ) );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 66 0F F4 = PMULUDQ -- unsigned widening multiply of 32-lanes 0 x
+//..       0 to form lower 64-bit half and lanes 2 x 2 to form upper 64-bit
+//..       half */
+//..    /* This is a really poor translation -- could be improved if
+//..       performance critical */
+//..    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xF4) {
+//..       IRTemp sV, dV;
+//..       IRTemp s3, s2, s1, s0, d3, d2, d1, d0;
+//..       sV = newTemp(Ity_V128);
+//..       dV = newTemp(Ity_V128);
+//..       s3 = s2 = s1 = s0 = d3 = d2 = d1 = d0 = IRTemp_INVALID;
+//..       t1 = newTemp(Ity_I64);
+//..       t0 = newTemp(Ity_I64);
+//..       modrm = insn[2];
+//..       assign( dV, getXMMReg(gregOfRM(modrm)) );
+//.. 
+//..       if (epartIsReg(modrm)) {
+//..          assign( sV, getXMMReg(eregOfRM(modrm)) );
+//..          delta += 2+1;
+//..          DIP("pmuludq %s,%s\n", nameXMMReg(eregOfRM(modrm)),
+//..                                 nameXMMReg(gregOfRM(modrm)));
+//..       } else {
+//..          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
+//..          assign( sV, loadLE(Ity_V128, mkexpr(addr)) );
+//..          delta += 2+alen;
+//..          DIP("pmuludq %s,%s\n", dis_buf,
+//..                                 nameXMMReg(gregOfRM(modrm)));
+//..       }
+//.. 
+//..       breakup128to32s( dV, &d3, &d2, &d1, &d0 );
+//..       breakup128to32s( sV, &s3, &s2, &s1, &s0 );
+//.. 
+//..       assign( t0, binop( Iop_MullU32, mkexpr(d0), mkexpr(s0)) );
+//..       putXMMRegLane64( gregOfRM(modrm), 0, mkexpr(t0) );
+//..       assign( t1, binop( Iop_MullU32, mkexpr(d2), mkexpr(s2)) );
+//..       putXMMRegLane64( gregOfRM(modrm), 1, mkexpr(t1) );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 66 0F EB = POR */
+//..    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xEB) {
+//..       delta = dis_SSE_E_to_G_all( sorb, delta+2, "por", Iop_Or128 );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 66 0F 70 = PSHUFD -- rearrange 4x32 from E(xmm or mem) to G(xmm) */
+//..    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x70) {
+//..       Int order;
+//..       IRTemp sV, dV, s3, s2, s1, s0;
+//..       s3 = s2 = s1 = s0 = IRTemp_INVALID;
+//..       sV = newTemp(Ity_V128);
+//..       dV = newTemp(Ity_V128);
+//..       modrm = insn[2];
+//..       if (epartIsReg(modrm)) {
+//..          assign( sV, getXMMReg(eregOfRM(modrm)) );
+//..          order = (Int)insn[3];
+//..          delta += 2+2;
+//..          DIP("pshufd $%d,%s,%s\n", order, 
+//..                                    nameXMMReg(eregOfRM(modrm)),
+//..                                    nameXMMReg(gregOfRM(modrm)));
+//..       } else {
+//..          addr = disAMode ( &alen, sorb, delta+2, dis_buf );
+//..          assign( sV, loadLE(Ity_V128, mkexpr(addr)) );
+//..    order = (Int)insn[2+alen];
+//..          delta += 3+alen;
+//..          DIP("pshufd $%d,%s,%s\n", order, 
+//..                                    dis_buf,
+//..                                    nameXMMReg(gregOfRM(modrm)));
+//..       }
+//..       breakup128to32s( sV, &s3, &s2, &s1, &s0 );
+//.. 
+//.. #     define SEL(n) \
+//..                 ((n)==0 ? s0 : ((n)==1 ? s1 : ((n)==2 ? s2 : s3)))
+//..       assign(dV,
+//..        mk128from32s( SEL((order>>6)&3), SEL((order>>4)&3),
+//..                            SEL((order>>2)&3), SEL((order>>0)&3) )
+//..       );
+//..       putXMMReg(gregOfRM(modrm), mkexpr(dV));
+//.. #     undef SEL
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* F3 0F 70 = PSHUFHW -- rearrange upper half 4x16 from E(xmm or
+//..       mem) to G(xmm), and copy lower half */
+//..    if (insn[0] == 0xF3 && insn[1] == 0x0F && insn[2] == 0x70) {
+//..       Int order;
+//..       IRTemp sVhi, dVhi, sV, dV, s3, s2, s1, s0;
+//..       s3 = s2 = s1 = s0 = IRTemp_INVALID;
+//..       sV   = newTemp(Ity_V128);
+//..       dV   = newTemp(Ity_V128);
+//..       sVhi = newTemp(Ity_I64);
+//..       dVhi = newTemp(Ity_I64);
+//..       modrm = insn[3];
+//..       if (epartIsReg(modrm)) {
+//..          assign( sV, getXMMReg(eregOfRM(modrm)) );
+//..          order = (Int)insn[4];
+//..          delta += 4+1;
+//..          DIP("pshufhw $%d,%s,%s\n", order, 
+//..                                     nameXMMReg(eregOfRM(modrm)),
+//..                                     nameXMMReg(gregOfRM(modrm)));
+//..       } else {
+//..          addr = disAMode ( &alen, sorb, delta+3, dis_buf );
+//..          assign( sV, loadLE(Ity_V128, mkexpr(addr)) );
+//..    order = (Int)insn[3+alen];
+//..          delta += 4+alen;
+//..          DIP("pshufhw $%d,%s,%s\n", order, 
+//..                                     dis_buf,
+//..                                     nameXMMReg(gregOfRM(modrm)));
+//..       }
+//..       assign( sVhi, unop(Iop_128HIto64, mkexpr(sV)) );
+//..       breakup64to16s( sVhi, &s3, &s2, &s1, &s0 );
+//.. 
+//.. #     define SEL(n) \
+//..                 ((n)==0 ? s0 : ((n)==1 ? s1 : ((n)==2 ? s2 : s3)))
+//..       assign(dVhi,
+//..        mk64from16s( SEL((order>>6)&3), SEL((order>>4)&3),
+//..                           SEL((order>>2)&3), SEL((order>>0)&3) )
+//..       );
+//..       assign(dV, binop( Iop_64HLto128, 
+//..                         mkexpr(dVhi),
+//..                         unop(Iop_128to64, mkexpr(sV))) );
+//..       putXMMReg(gregOfRM(modrm), mkexpr(dV));
+//.. #     undef SEL
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* F2 0F 70 = PSHUFLW -- rearrange lower half 4x16 from E(xmm or
+//..       mem) to G(xmm), and copy upper half */
+//..    if (insn[0] == 0xF2 && insn[1] == 0x0F && insn[2] == 0x70) {
+//..       Int order;
+//..       IRTemp sVlo, dVlo, sV, dV, s3, s2, s1, s0;
+//..       s3 = s2 = s1 = s0 = IRTemp_INVALID;
+//..       sV   = newTemp(Ity_V128);
+//..       dV   = newTemp(Ity_V128);
+//..       sVlo = newTemp(Ity_I64);
+//..       dVlo = newTemp(Ity_I64);
+//..       modrm = insn[3];
+//..       if (epartIsReg(modrm)) {
+//..          assign( sV, getXMMReg(eregOfRM(modrm)) );
+//..          order = (Int)insn[4];
+//..          delta += 4+1;
+//..          DIP("pshuflw $%d,%s,%s\n", order, 
+//..                                     nameXMMReg(eregOfRM(modrm)),
+//..                                     nameXMMReg(gregOfRM(modrm)));
+//..       } else {
+//..          addr = disAMode ( &alen, sorb, delta+3, dis_buf );
+//..          assign( sV, loadLE(Ity_V128, mkexpr(addr)) );
+//..    order = (Int)insn[3+alen];
+//..          delta += 4+alen;
+//..          DIP("pshuflw $%d,%s,%s\n", order, 
+//..                                     dis_buf,
+//..                                     nameXMMReg(gregOfRM(modrm)));
+//..       }
+//..       assign( sVlo, unop(Iop_128to64, mkexpr(sV)) );
+//..       breakup64to16s( sVlo, &s3, &s2, &s1, &s0 );
+//.. 
+//.. #     define SEL(n) \
+//..                 ((n)==0 ? s0 : ((n)==1 ? s1 : ((n)==2 ? s2 : s3)))
+//..       assign(dVlo,
+//..        mk64from16s( SEL((order>>6)&3), SEL((order>>4)&3),
+//..                           SEL((order>>2)&3), SEL((order>>0)&3) )
+//..       );
+//..       assign(dV, binop( Iop_64HLto128,
+//..                         unop(Iop_128HIto64, mkexpr(sV)),
+//..                         mkexpr(dVlo) ) );
+//..       putXMMReg(gregOfRM(modrm), mkexpr(dV));
+//.. #     undef SEL
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 66 0F 72 /6 ib = PSLLD by immediate */
+//..    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x72
+//..        && epartIsReg(insn[2])
+//..        && gregOfRM(insn[2]) == 6) {
+//..       delta = dis_SSE_shiftE_imm( delta+2, "pslld", Iop_ShlN32x4 );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 66 0F F2 = PSLLD by E */
+//..    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xF2) {
+//..       delta = dis_SSE_shiftG_byE( sorb, delta+2, "pslld", Iop_ShlN32x4 );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 66 0F 73 /7 ib = PSLLDQ by immediate */
+//..    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x73
+//..        && epartIsReg(insn[2])
+//..        && gregOfRM(insn[2]) == 7) {
+//..       IRTemp sV, dV, hi64, lo64, hi64r, lo64r;
+//..       Int    imm = (Int)insn[3];
+//..       Int    reg = eregOfRM(insn[2]);
+//..       DIP("pslldq $%d,%s\n", imm, nameXMMReg(reg));
+//..       vassert(imm >= 0 && imm <= 255);
+//..       delta += 4;
+//.. 
+//..       sV    = newTemp(Ity_V128);
+//..       dV    = newTemp(Ity_V128);
+//..       hi64  = newTemp(Ity_I64);
+//..       lo64  = newTemp(Ity_I64);
+//..       hi64r = newTemp(Ity_I64);
+//..       lo64r = newTemp(Ity_I64);
+//.. 
+//..       if (imm >= 16) {
+//..          vassert(0); /* awaiting test case */
+//..          putXMMReg(reg, mkV128(0x0000));
+//..          goto decode_success;
+//..       }
+//.. 
+//..       assign( sV, getXMMReg(reg) );
+//..       assign( hi64, unop(Iop_128HIto64, mkexpr(sV)) );
+//..       assign( lo64, unop(Iop_128to64, mkexpr(sV)) );
+//.. 
+//..       if (imm == 8) {
+//..          assign( lo64r, mkU64(0) );
+//..          assign( hi64r, mkexpr(lo64) );
+//..       }
+//..       else
+//..       if (imm > 8) {
+//..          vassert(0); /* awaiting test case */
+//..          assign( lo64r, mkU64(0) );
+//..          assign( hi64r, binop( Iop_Shl64, 
+//..                                mkexpr(lo64),
+//..                                mkU8( 8*(imm-8) ) ));
+//..       } else {
+//..          assign( lo64r, binop( Iop_Shl64, 
+//..                                mkexpr(lo64),
+//..                                mkU8(8 * imm) ));
+//..          assign( hi64r, 
+//..                  binop( Iop_Or64,
+//..                         binop(Iop_Shl64, mkexpr(hi64), 
+//..                                          mkU8(8 * imm)),
+//..                         binop(Iop_Shr64, mkexpr(lo64),
+//..                                          mkU8(8 * (8 - imm)) )
+//..                       )
+//..                );
+//..       }
+//..       assign( dV, binop(Iop_64HLto128, mkexpr(hi64r), mkexpr(lo64r)) );
+//..       putXMMReg(reg, mkexpr(dV));
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 66 0F 73 /6 ib = PSLLQ by immediate */
+//..    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x73
+//..        && epartIsReg(insn[2])
+//..        && gregOfRM(insn[2]) == 6) {
+//..       delta = dis_SSE_shiftE_imm( delta+2, "psllq", Iop_ShlN64x2 );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 66 0F F3 = PSLLQ by E */
+//..    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xF3) {
+//..       delta = dis_SSE_shiftG_byE( sorb, delta+2, "psllq", Iop_ShlN64x2 );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 66 0F 71 /6 ib = PSLLW by immediate */
+//..    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x71
+//..        && epartIsReg(insn[2])
+//..        && gregOfRM(insn[2]) == 6) {
+//..       delta = dis_SSE_shiftE_imm( delta+2, "psllw", Iop_ShlN16x8 );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 66 0F F1 = PSLLW by E */
+//..    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xF1) {
+//..       delta = dis_SSE_shiftG_byE( sorb, delta+2, "psllw", Iop_ShlN16x8 );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 66 0F 72 /4 ib = PSRAD by immediate */
+//..    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x72
+//..        && epartIsReg(insn[2])
+//..        && gregOfRM(insn[2]) == 4) {
+//..       delta = dis_SSE_shiftE_imm( delta+2, "psrad", Iop_SarN32x4 );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 66 0F E2 = PSRAD by E */
+//..    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xE2) {
+//..       delta = dis_SSE_shiftG_byE( sorb, delta+2, "psrad", Iop_SarN32x4 );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 66 0F 71 /4 ib = PSRAW by immediate */
+//..    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x71
+//..        && epartIsReg(insn[2])
+//..        && gregOfRM(insn[2]) == 4) {
+//..       delta = dis_SSE_shiftE_imm( delta+2, "psraw", Iop_SarN16x8 );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 66 0F E1 = PSRAW by E */
+//..    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xE1) {
+//..       delta = dis_SSE_shiftG_byE( sorb, delta+2, "psraw", Iop_SarN16x8 );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 66 0F 72 /2 ib = PSRLD by immediate */
+//..    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x72
+//..        && epartIsReg(insn[2])
+//..        && gregOfRM(insn[2]) == 2) {
+//..       delta = dis_SSE_shiftE_imm( delta+2, "psrld", Iop_ShrN32x4 );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 66 0F D2 = PSRLD by E */
+//..    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xD2) {
+//..       delta = dis_SSE_shiftG_byE( sorb, delta+2, "psrld", Iop_ShrN32x4 );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 66 0F 73 /3 ib = PSRLDQ by immediate */
+//..    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x73
+//..        && epartIsReg(insn[2])
+//..        && gregOfRM(insn[2]) == 3) {
+//..       IRTemp sV, dV, hi64, lo64, hi64r, lo64r;
+//..       Int    imm = (Int)insn[3];
+//..       Int    reg = eregOfRM(insn[2]);
+//..       DIP("psrldq $%d,%s\n", imm, nameXMMReg(reg));
+//..       vassert(imm >= 0 && imm <= 255);
+//..       delta += 4;
+//.. 
+//..       sV    = newTemp(Ity_V128);
+//..       dV    = newTemp(Ity_V128);
+//..       hi64  = newTemp(Ity_I64);
+//..       lo64  = newTemp(Ity_I64);
+//..       hi64r = newTemp(Ity_I64);
+//..       lo64r = newTemp(Ity_I64);
+//.. 
+//..       if (imm >= 16) {
+//..          vassert(0); /* awaiting test case */
+//..          putXMMReg(reg, mkV128(0x0000));
+//..          goto decode_success;
+//..       }
+//.. 
+//..       assign( sV, getXMMReg(reg) );
+//..       assign( hi64, unop(Iop_128HIto64, mkexpr(sV)) );
+//..       assign( lo64, unop(Iop_128to64, mkexpr(sV)) );
+//.. 
+//..       if (imm == 8) {
+//..          assign( hi64r, mkU64(0) );
+//..          assign( lo64r, mkexpr(hi64) );
+//..       }
+//..       else 
+//..       if (imm > 8) {
+//..          vassert(0); /* awaiting test case */
+//..          assign( hi64r, mkU64(0) );
+//..          assign( lo64r, binop( Iop_Shr64, 
+//..                                mkexpr(hi64),
+//..                                mkU8( 8*(imm-8) ) ));
+//..       } else {
+//..          assign( hi64r, binop( Iop_Shr64, 
+//..                                mkexpr(hi64),
+//..                                mkU8(8 * imm) ));
+//..          assign( lo64r, 
+//..                  binop( Iop_Or64,
+//..                         binop(Iop_Shr64, mkexpr(lo64), 
+//..                                          mkU8(8 * imm)),
+//..                         binop(Iop_Shl64, mkexpr(hi64),
+//..                                          mkU8(8 * (8 - imm)) )
+//..                       )
+//..                );
+//..       }
+//.. 
+//..       assign( dV, binop(Iop_64HLto128, mkexpr(hi64r), mkexpr(lo64r)) );
+//..       putXMMReg(reg, mkexpr(dV));
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 66 0F 73 /2 ib = PSRLQ by immediate */
+//..    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x73
+//..        && epartIsReg(insn[2])
+//..        && gregOfRM(insn[2]) == 2) {
+//..       delta = dis_SSE_shiftE_imm( delta+2, "psrlq", Iop_ShrN64x2 );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 66 0F D3 = PSRLQ by E */
+//..    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xD3) {
+//..       delta = dis_SSE_shiftG_byE( sorb, delta+2, "psrlq", Iop_ShrN64x2 );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 66 0F 71 /2 ib = PSRLW by immediate */
+//..    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x71
+//..        && epartIsReg(insn[2])
+//..        && gregOfRM(insn[2]) == 2) {
+//..       delta = dis_SSE_shiftE_imm( delta+2, "psrlw", Iop_ShrN16x8 );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 66 0F D1 = PSRLW by E */
+//..    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xD1) {
+//..       delta = dis_SSE_shiftG_byE( sorb, delta+2, "psrlw", Iop_ShrN16x8 );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 66 0F F8 = PSUBB */
+//..    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xF8) {
+//..       delta = dis_SSEint_E_to_G( sorb, delta+2, 
+//..                                  "psubb", Iop_Sub8x16, False );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 66 0F FA = PSUBD */
+//..    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xFA) {
+//..       delta = dis_SSEint_E_to_G( sorb, delta+2, 
+//..                                  "psubd", Iop_Sub32x4, False );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* ***--- this is an MMX class insn introduced in SSE2 ---*** */
+//..    /* 0F FB = PSUBQ -- sub 64x1 */
+//..    if (sz == 4 && insn[0] == 0x0F && insn[1] == 0xFB) {
+//..       do_MMX_preamble();
+//..       delta = dis_MMXop_regmem_to_reg ( 
+//..                 sorb, delta+2, insn[1], "psubq", False );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 66 0F FB = PSUBQ */
+//..    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xFB) {
+//..       delta = dis_SSEint_E_to_G( sorb, delta+2, 
+//..                                  "psubq", Iop_Sub64x2, False );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 66 0F F9 = PSUBW */
+//..    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xF9) {
+//..       delta = dis_SSEint_E_to_G( sorb, delta+2, 
+//..                                  "psubw", Iop_Sub16x8, False );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 66 0F E8 = PSUBSB */
+//..    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xE8) {
+//..       delta = dis_SSEint_E_to_G( sorb, delta+2, 
+//..                                  "psubsb", Iop_QSub8Sx16, False );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 66 0F E9 = PSUBSW */
+//..    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xE9) {
+//..       delta = dis_SSEint_E_to_G( sorb, delta+2, 
+//..                                  "psubsw", Iop_QSub16Sx8, False );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 66 0F D8 = PSUBSB */
+//..    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xD8) {
+//..       delta = dis_SSEint_E_to_G( sorb, delta+2, 
+//..                                  "psubusb", Iop_QSub8Ux16, False );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 66 0F D9 = PSUBSW */
+//..    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xD9) {
+//..       delta = dis_SSEint_E_to_G( sorb, delta+2, 
+//..                                  "psubusw", Iop_QSub16Ux8, False );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 66 0F 68 = PUNPCKHBW */
+//..    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x68) {
+//..       delta = dis_SSEint_E_to_G( sorb, delta+2, 
+//..                                  "punpckhbw",
+//..                                  Iop_InterleaveHI8x16, True );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 66 0F 6A = PUNPCKHDQ */
+//..    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x6A) {
+//..       delta = dis_SSEint_E_to_G( sorb, delta+2, 
+//..                                  "punpckhdq",
+//..                                  Iop_InterleaveHI32x4, True );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 66 0F 6D = PUNPCKHQDQ */
+//..    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x6D) {
+//..       delta = dis_SSEint_E_to_G( sorb, delta+2, 
+//..                                  "punpckhqdq",
+//..                                  Iop_InterleaveHI64x2, True );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 66 0F 69 = PUNPCKHWD */
+//..    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x69) {
+//..       delta = dis_SSEint_E_to_G( sorb, delta+2, 
+//..                                  "punpckhwd",
+//..                                  Iop_InterleaveHI16x8, True );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 66 0F 60 = PUNPCKLBW */
+//..    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x60) {
+//..       delta = dis_SSEint_E_to_G( sorb, delta+2, 
+//..                                  "punpcklbw",
+//..                                  Iop_InterleaveLO8x16, True );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 66 0F 62 = PUNPCKLDQ */
+//..    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x62) {
+//..       delta = dis_SSEint_E_to_G( sorb, delta+2, 
+//..                                  "punpckldq",
+//..                                  Iop_InterleaveLO32x4, True );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 66 0F 6C = PUNPCKLQDQ */
+//..    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x6C) {
+//..       delta = dis_SSEint_E_to_G( sorb, delta+2, 
+//..                                  "punpcklqdq",
+//..                                  Iop_InterleaveLO64x2, True );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 66 0F 61 = PUNPCKLWD */
+//..    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x61) {
+//..       delta = dis_SSEint_E_to_G( sorb, delta+2, 
+//..                                  "punpcklwd",
+//..                                  Iop_InterleaveLO16x8, True );
+//..       goto decode_success;
+//..    }
+//.. 
+//..    /* 66 0F EF = PXOR */
+//..    if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xEF) {
+//..       delta = dis_SSE_E_to_G_all( sorb, delta+2, "pxor", Iop_Xor128 );
+//..       goto decode_success;
+//..    }
+//.. 
+//.. 
+//.. //--    /* FXSAVE/FXRSTOR m32 -- load/store the FPU/MMX/SSE state. */
+//.. //--    if (insn[0] == 0x0F && insn[1] == 0xAE 
+//.. //--        && (!epartIsReg(insn[2]))
+//.. //--        && (gregOfRM(insn[2]) == 1 || gregOfRM(insn[2]) == 0) ) {
+//.. //--       Bool store = gregOfRM(insn[2]) == 0;
+//.. //--       vg_assert(sz == 4);
+//.. //--       pair = disAMode ( cb, sorb, eip+2, dis_buf );
+//.. //--       t1   = LOW24(pair);
+//.. //--       eip += 2+HI8(pair);
+//.. //--       uInstr3(cb, store ? SSE2a_MemWr : SSE2a_MemRd, 512,
+//.. //--                   Lit16, (((UShort)insn[0]) << 8) | (UShort)insn[1],
+//.. //--                   Lit16, (UShort)insn[2],
+//.. //--                   TempReg, t1 );
+//.. //--       DIP("fx%s %s\n", store ? "save" : "rstor", dis_buf );
+//.. //--       goto decode_success;
+//.. //--    }
+//.. //-- 
+//.. //--    /* CLFLUSH -- flush cache line */
+//.. //--    if (insn[0] == 0x0F && insn[1] == 0xAE
+//.. //--        && (!epartIsReg(insn[2]))
+//.. //--        && (gregOfRM(insn[2]) == 7))
+//.. //--    {
+//.. //--       vg_assert(sz == 4);
+//.. //--       pair = disAMode ( cb, sorb, eip+2, dis_buf );
+//.. //--       t1   = LOW24(pair);
+//.. //--       eip += 2+HI8(pair);
+//.. //--       uInstr3(cb, SSE2a_MemRd, 0,  /* ignore sz for internal ops */
+//.. //--                   Lit16, (((UShort)0x0F) << 8) | (UShort)0xAE,
+//.. //--                   Lit16, (UShort)insn[2],
+//.. //--                   TempReg, t1 );
+//.. //--       DIP("clflush %s\n", dis_buf);
+//.. //--       goto decode_success;
+//.. //--    }
+//.. 
+//.. 
+//..    /* ---------------------------------------------------- */
+//..    /* --- end of the SSE/SSE2 decoder.                 --- */
+//..    /* ---------------------------------------------------- */
+//.. 
+//..    after_sse_decoders:
+//.. 
+//..    /* Get the primary opcode. */
+//..    opc = getIByte(delta); delta++;
+//.. 
+//..    /* We get here if the current insn isn't SSE, or this CPU doesn't
+//..       support SSE. */
+//.. 
+//..    switch (opc) {
+//.. 
+//..    /* ------------------------ Control flow --------------- */
+//.. 
+//..    case 0xC2: /* RET imm16 */
+//..       d32 = getUDisp16(delta); 
+//..       delta += 2;
+//..       dis_ret(d32);
+//..       whatNext = Dis_StopHere;
+//..       DIP("ret %d\n", d32);
+//..       break;
+//..    case 0xC3: /* RET */
+//..       dis_ret(0);
+//..       whatNext = Dis_StopHere;
+//..       DIP("ret\n");
+//..       break;
+//..       
+//..    case 0xE8: /* CALL J4 */
+//..       d32 = getUDisp32(delta); delta += 4;
+//..       d32 += (guest_eip_bbstart+delta); 
+//..       /* (guest_eip_bbstart+delta) == return-to addr, d32 == call-to addr */
+//..       if (d32 == guest_eip_bbstart+delta && getIByte(delta) >= 0x58 
+//..                                          && getIByte(delta) <= 0x5F) {
+//..          /* Specially treat the position-independent-code idiom 
+//..                  call X
+//..               X: popl %reg
+//..             as 
+//..                  movl %eip, %reg.
+//..             since this generates better code, but for no other reason. */
+//..          Int archReg = getIByte(delta) - 0x58;
+//..          /* vex_printf("-- fPIC thingy\n"); */
+//..          putIReg(4, archReg, mkU32(guest_eip_bbstart+delta));
+//..          delta++; /* Step over the POP */
+//..          DIP("call 0x%x ; popl %s\n",d32,nameIReg(4,archReg));
+//..       } else {
+//..          /* The normal sequence for a call. */
+//..          t1 = newTemp(Ity_I32); 
+//..          assign(t1, binop(Iop_Sub32, getIReg(4,R_ESP), mkU32(4)));
+//..          putIReg(4, R_ESP, mkexpr(t1));
+//..          storeLE( mkexpr(t1), mkU32(guest_eip_bbstart+delta));
+//..          if (resteerOK && resteerOkFn((Addr64)(Addr32)d32)) {
+//..             /* follow into the call target. */
+//..             whatNext = Dis_Resteer;
+//..             *whereNext = d32;
+//..          } else {
+//..             jmp_lit(Ijk_Call,d32);
+//..             whatNext = Dis_StopHere;
+//..          }
+//..          DIP("call 0x%x\n",d32);
+//..       }
+//..       break;
+//.. 
+//.. //--    case 0xC8: /* ENTER */ 
+//.. //--       d32 = getUDisp16(eip); eip += 2;
+//.. //--       abyte = getIByte(delta); delta++;
+//.. //-- 
+//.. //--       vg_assert(sz == 4);           
+//.. //--       vg_assert(abyte == 0);
+//.. //-- 
+//.. //--       t1 = newTemp(cb); t2 = newTemp(cb);
+//.. //--       uInstr2(cb, GET,   sz, ArchReg, R_EBP, TempReg, t1);
+//.. //--       uInstr2(cb, GET,    4, ArchReg, R_ESP, TempReg, t2);
+//.. //--       uInstr2(cb, SUB,    4, Literal, 0,     TempReg, t2);
+//.. //--       uLiteral(cb, sz);
+//.. //--       uInstr2(cb, PUT,    4, TempReg, t2,    ArchReg, R_ESP);
+//.. //--       uInstr2(cb, STORE,  4, TempReg, t1,    TempReg, t2);
+//.. //--       uInstr2(cb, PUT,    4, TempReg, t2,    ArchReg, R_EBP);
+//.. //--       if (d32) {
+//.. //--          uInstr2(cb, SUB,    4, Literal, 0,     TempReg, t2);
+//.. //--          uLiteral(cb, d32);
+//.. //--          uInstr2(cb, PUT,    4, TempReg, t2,    ArchReg, R_ESP);
+//.. //--       }
+//.. //--       DIP("enter 0x%x, 0x%x", d32, abyte);
+//.. //--       break;
+//.. 
+//..    case 0xC9: /* LEAVE */
+//..       vassert(sz == 4);
+//..       t1 = newTemp(Ity_I32); t2 = newTemp(Ity_I32);
+//..       assign(t1, getIReg(4,R_EBP));
+//..       /* First PUT ESP looks redundant, but need it because ESP must
+//..          always be up-to-date for Memcheck to work... */
+//..       putIReg(4, R_ESP, mkexpr(t1));
+//..       assign(t2, loadLE(Ity_I32,mkexpr(t1)));
+//..       putIReg(4, R_EBP, mkexpr(t2));
+//..       putIReg(4, R_ESP, binop(Iop_Add32, mkexpr(t1), mkU32(4)) );
+//..       DIP("leave\n");
+//..       break;
+//.. 
+//.. //--    /* ---------------- Misc weird-ass insns --------------- */
+//.. //-- 
+//.. //--    case 0x27: /* DAA */
+//.. //--    case 0x2F: /* DAS */
+//.. //--       t1 = newTemp(cb);
+//.. //--       uInstr2(cb, GET, 1, ArchReg, R_AL, TempReg, t1);
+//.. //--       /* Widen %AL to 32 bits, so it's all defined when we push it. */
+//.. //--       uInstr1(cb, WIDEN, 4, TempReg, t1);
+//.. //--       uWiden(cb, 1, False);
+//.. //--       uInstr0(cb, CALLM_S, 0);
+//.. //--       uInstr1(cb, PUSH, 4, TempReg, t1);
+//.. //--       uInstr1(cb, CALLM, 0, Lit16, 
+//.. //--                   opc == 0x27 ? VGOFF_(helper_DAA) : VGOFF_(helper_DAS) );
+//.. //--       uFlagsRWU(cb, FlagsAC, FlagsSZACP, FlagO);
+//.. //--       uInstr1(cb, POP, 4, TempReg, t1);
+//.. //--       uInstr0(cb, CALLM_E, 0);
+//.. //--       uInstr2(cb, PUT, 1, TempReg, t1, ArchReg, R_AL);
+//.. //--       DIP(opc == 0x27 ? "daa\n" : "das\n");
+//.. //--       break;
+//.. //-- 
+//.. //--    case 0x37: /* AAA */
+//.. //--    case 0x3F: /* AAS */
+//.. //--       t1 = newTemp(cb);
+//.. //--       uInstr2(cb, GET, 2, ArchReg, R_EAX, TempReg, t1);
+//.. //--       /* Widen %AL 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 == 0x37 ? VGOFF_(helper_AAA) : VGOFF_(helper_AAS) );
+//.. //--       uFlagsRWU(cb, FlagA, FlagsAC, FlagsEmpty);
+//.. //--       uInstr1(cb, POP, 4, TempReg, t1);
+//.. //--       uInstr0(cb, CALLM_E, 0);
+//.. //--       uInstr2(cb, PUT, 2, TempReg, t1, ArchReg, R_EAX);
+//.. //--       DIP(opc == 0x37 ? "aaa\n" : "aas\n");
+//.. //--       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;
+//.. 
+//..    /* ------------------------ CWD/CDQ -------------------- */
+//.. 
+//..    case 0x98: /* CBW */
+//..       if (sz == 4) {
+//..          putIReg(4, R_EAX, unop(Iop_16Sto32, getIReg(2, R_EAX)));
+//..          DIP("cwde\n");
+//..       } else {
+//..          vassert(sz == 2);
+//..          putIReg(2, R_EAX, unop(Iop_8Sto16, getIReg(1, R_EAX)));
+//..          DIP("cbw\n");
+//..       }
+//..       break;
+//.. 
+//..    case 0x99: /* CWD/CDQ */
+//..       ty = szToITy(sz);
+//..       putIReg(sz, R_EDX,
+//..                   binop(mkSizedOp(ty,Iop_Sar8), 
+//..                         getIReg(sz, R_EAX),
+//..                         mkU8(sz == 2 ? 15 : 31)) );
+//..       DIP(sz == 2 ? "cwdq\n" : "cdqq\n");
+//..       break;
+//.. 
+//..    /* ------------------------ FPU ops -------------------- */
+//.. 
+//..    case 0x9E: /* SAHF */
+//..       codegen_SAHF();
+//..       DIP("sahf\n");
+//..       break;
+//.. 
+//.. //--    case 0x9F: /* LAHF */
+//.. //--       codegen_LAHF ( cb );
+//.. //--       DIP("lahf\n");
+//.. //--       break;
+//.. //-- 
+//..    case 0x9B: /* FWAIT */
+//..       /* ignore? */
+//..       DIP("fwait\n");
+//..       break;
+//.. 
+//..    case 0xD8:
+//..    case 0xD9:
+//..    case 0xDA:
+//..    case 0xDB:
+//..    case 0xDC:
+//..    case 0xDD:
+//..    case 0xDE:
+//..    case 0xDF: {
+//..       UInt delta0    = delta;
+//..       Bool decode_OK = False;
+//..       delta = dis_FPU ( &decode_OK, sorb, delta );
+//..       if (!decode_OK) {
+//..          delta = delta0;
+//..          goto decode_failure;
+//..       }
+//..       break;
+//..    }
+//.. 
+//..    /* ------------------------ INC & DEC ------------------ */
+//.. 
+//..    case 0x40: /* INC eAX */
+//..    case 0x41: /* INC eCX */
+//..    case 0x42: /* INC eDX */
+//..    case 0x43: /* INC eBX */
+//..    case 0x44: /* INC eSP */
+//..    case 0x45: /* INC eBP */
+//..    case 0x46: /* INC eSI */
+//..    case 0x47: /* INC eDI */
+//..       vassert(sz == 2 || sz == 4);
+//..       ty = szToITy(sz);
+//..       t1 = newTemp(ty);
+//..       assign( t1, binop(mkSizedOp(ty,Iop_Add8),
+//..                         getIReg(sz, (UInt)(opc - 0x40)),
+//..                         mkU(ty,1)) );
+//..       setFlags_INC_DEC( True, t1, ty );
+//..       putIReg(sz, (UInt)(opc - 0x40), mkexpr(t1));
+//..       DIP("inc%c %s\n", nameISize(sz), nameIReg(sz,opc-0x40));
+//..       break;
+//.. 
+//..    case 0x48: /* DEC eAX */
+//..    case 0x49: /* DEC eCX */
+//..    case 0x4A: /* DEC eDX */
+//..    case 0x4B: /* DEC eBX */
+//..    case 0x4C: /* DEC eSP */
+//..    case 0x4D: /* DEC eBP */
+//..    case 0x4E: /* DEC eSI */
+//..    case 0x4F: /* DEC eDI */
+//..       vassert(sz == 2 || sz == 4);
+//..       ty = szToITy(sz);
+//..       t1 = newTemp(ty);
+//..       assign( t1, binop(mkSizedOp(ty,Iop_Sub8),
+//..                         getIReg(sz, (UInt)(opc - 0x48)),
+//..                         mkU(ty,1)) );
+//..       setFlags_INC_DEC( False, t1, ty );
+//..       putIReg(sz, (UInt)(opc - 0x48), mkexpr(t1));
+//..       DIP("dec%c %s\n", nameISize(sz), nameIReg(sz,opc-0x48));
+//..       break;
+//.. 
+//..    /* ------------------------ INT ------------------------ */
+//.. 
+//..    case 0xCD: /* INT imm8 */
+//..       d32 = getIByte(delta); delta++;
+//..       if (d32 != 0x80) goto decode_failure;
+//..       /* It's important that all ArchRegs carry their up-to-date value
+//..          at this point.  So we declare an end-of-block here, which
+//..          forces any TempRegs caching ArchRegs to be flushed. */
+//..       jmp_lit(Ijk_Syscall,((Addr32)guest_eip_bbstart)+delta);
+//..       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;
+//.. 
+//..    case 0xE9: /* Jv (jump, 16/32 offset) */
+//..       vassert(sz == 4); /* JRS added 2004 July 11 */
+//..       d32 = (((Addr32)guest_eip_bbstart)+delta+sz) + getSDisp(sz,delta); 
+//..       delta += sz;
+//..       if (resteerOK && resteerOkFn((Addr64)(Addr32)d32)) {
+//..          whatNext   = Dis_Resteer;
+//..          *whereNext = d32;
+//..       } else {
+//..          jmp_lit(Ijk_Boring,d32);
+//..          whatNext = Dis_StopHere;
+//..       }
+//..       DIP("jmp 0x%x\n", 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) */
+//..       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 0xE3: /* JECXZ or perhaps JCXZ, depending on OSO ?  Intel
+//..                  manual says it depends on address size override,
+//..                  which doesn't sound right to me. */
+//..       vassert(sz==4); /* possibly also OK for sz==2 */
+//..       d32 = (((Addr32)guest_eip_bbstart)+delta+1) + getSDisp8(delta);
+//..       delta++;
+//..       ty = szToITy(sz);
+//..       stmt( IRStmt_Exit(
+//..                binop(mkSizedOp(ty,Iop_CmpEQ8),
+//..                      getIReg(sz,R_ECX),
+//..                      mkU(ty,0)),
+//..             Ijk_Boring,
+//..             IRConst_U32(d32)) 
+//..           );
+//.. 
+//..       DIP("j%sz 0x%x\n", nameIReg(sz, R_ECX), d32);
+//..       break;
+//.. 
+//.. //--    case 0xE0: /* LOOPNE disp8 */
+//.. //--    case 0xE1: /* LOOPE  disp8 */
+//.. //--    case 0xE2: /* LOOP   disp8 */
+//.. //--       /* Again, the docs say this uses ECX/CX as a count depending on
+//.. //--          the address size override, not the operand one.  Since we
+//.. //--          don't handle address size overrides, I guess that means
+//.. //--          ECX. */
+//.. //--       d32 = (eip+1) + getSDisp8(eip); eip++;
+//.. //--       t1 = newTemp(cb);
+//.. //--       uInstr2(cb, GET,  4, ArchReg, R_ECX, TempReg, t1);
+//.. //--       uInstr1(cb, DEC,  4, TempReg, t1);
+//.. //--       uInstr2(cb, PUT,  4, TempReg, t1,    ArchReg, R_ECX);
+//.. //--       uInstr2(cb, JIFZ, 4, TempReg, t1,    Literal, 0);
+//.. //--       uLiteral(cb, eip);
+//.. //--       if (opc == 0xE0 || opc == 0xE1) {   /* LOOPE/LOOPNE */
+//.. //--          jcc_lit(cb, eip, (opc == 0xE1 ? CondNZ : CondZ));
+//.. //--       }
+//.. //--       jmp_lit(cb, d32);
+//.. //--       whatNext = Dis_StopHere;
+//.. //--       DIP("loop 0x%x\n", d32);
+//.. //--       break;
+//.. 
+//..    /* ------------------------ IMUL ----------------------- */
+//.. 
+//..    case 0x69: /* IMUL Iv, Ev, Gv */
+//..       delta = dis_imul_I_E_G ( sorb, sz, delta, sz );
+//..       break;
+//..    case 0x6B: /* IMUL Ib, Ev, Gv */
+//..       delta = dis_imul_I_E_G ( sorb, sz, delta, 1 );
+//..       break;
+//.. 
+//..    /* ------------------------ MOV ------------------------ */
+//.. 
+//..    case 0x88: /* MOV Gb,Eb */
+//..       delta = dis_mov_G_E(sorb, 1, delta);
+//..       break;
+//.. 
+//..    case 0x89: /* MOV Gv,Ev */
+//..       delta = dis_mov_G_E(sorb, sz, delta);
+//..       break;
+//.. 
+//..    case 0x8A: /* MOV Eb,Gb */
+//..       delta = dis_mov_E_G(sorb, 1, delta);
+//..       break;
+//..  
+//..    case 0x8B: /* MOV Ev,Gv */
+//..       delta = dis_mov_E_G(sorb, sz, delta);
+//..       break;
+//..  
+//..    case 0x8D: /* LEA M,Gv */
+//..       vassert(sz == 4);
+//..       modrm = getIByte(delta);
+//..       if (epartIsReg(modrm)) 
+//..          vpanic("LEA M,Gv: modRM refers to register (x86)");
+//..       /* NOTE!  this is the one place where a segment override prefix
+//..          has no effect on the address calculation.  Therefore we pass
+//..          zero instead of sorb here. */
+//..       addr = disAMode ( &alen, /*sorb*/ 0, delta, dis_buf );
+//..       delta += alen;
+//..       putIReg(sz, gregOfRM(modrm), mkexpr(addr));
+//..       DIP("lea%c %s, %s\n", nameISize(sz), dis_buf, 
+//..                             nameIReg(sz,gregOfRM(modrm)));
+//..       break;
+//.. 
+//..    case 0x8C: /* MOV Sw,Ew -- MOV from a SEGMENT REGISTER */
+//..       delta = dis_mov_Sw_Ew(sorb, sz, delta);
+//..       break;
+//.. 
+//..    case 0x8E: /* MOV Ew,Sw -- MOV to a SEGMENT REGISTER */
+//..       delta = dis_mov_Ew_Sw(sorb, delta);
+//..       break;
+//..  
+//..    case 0xA0: /* MOV Ob,AL */
+//..       sz = 1;
+//..       /* Fall through ... */
+//..    case 0xA1: /* MOV Ov,eAX */
+//..       d32 = getUDisp32(delta); delta += 4;
+//..       ty = szToITy(sz);
+//..       addr = newTemp(Ity_I32);
+//..       assign( addr, handleSegOverride(sorb, mkU32(d32)) );
+//..       putIReg(sz, R_EAX, loadLE(ty, mkexpr(addr)));
+//..       DIP("mov%c %s0x%x, %s\n", nameISize(sz), sorbTxt(sorb),
+//..                                 d32, nameIReg(sz,R_EAX));
+//..       break;
+//.. 
+//..    case 0xA2: /* MOV Ob,AL */
+//..       sz = 1;
+//..       /* Fall through ... */
+//..    case 0xA3: /* MOV eAX,Ov */
+//..       d32 = getUDisp32(delta); delta += 4;
+//..       ty = szToITy(sz);
+//..       addr = newTemp(Ity_I32);
+//..       assign( addr, handleSegOverride(sorb, mkU32(d32)) );
+//..       storeLE( mkexpr(addr), getIReg(sz,R_EAX) );
+//..       DIP("mov%c %s, %s0x%x\n", nameISize(sz), nameIReg(sz,R_EAX),
+//..                                 sorbTxt(sorb), d32);
+//..       break;
+//.. 
+//..    case 0xB0: /* MOV imm,AL */
+//..    case 0xB1: /* MOV imm,CL */
+//..    case 0xB2: /* MOV imm,DL */
+//..    case 0xB3: /* MOV imm,BL */
+//..    case 0xB4: /* MOV imm,AH */
+//..    case 0xB5: /* MOV imm,CH */
+//..    case 0xB6: /* MOV imm,DH */
+//..    case 0xB7: /* MOV imm,BH */
+//..       d32 = getIByte(delta); delta += 1;
+//..       putIReg(1, opc-0xB0, mkU8(d32));
+//..       DIP("movb $0x%x,%s\n", d32, nameIReg(1,opc-0xB0));
+//..       break;
+//.. 
+//..    case 0xB8: /* MOV imm,eAX */
+//..    case 0xB9: /* MOV imm,eCX */
+//..    case 0xBA: /* MOV imm,eDX */
+//..    case 0xBB: /* MOV imm,eBX */
+//..    case 0xBC: /* MOV imm,eSP */
+//..    case 0xBD: /* MOV imm,eBP */
+//..    case 0xBE: /* MOV imm,eSI */
+//..    case 0xBF: /* MOV imm,eDI */
+//..       d32 = getUDisp(sz,delta); delta += sz;
+//..       putIReg(sz, opc-0xB8, mkU(szToITy(sz), d32));
+//..       DIP("mov%c $0x%x,%s\n", nameISize(sz), d32, nameIReg(sz,opc-0xB8));
+//..       break;
+//.. 
+//..    case 0xC6: /* MOV Ib,Eb */
+//..       sz = 1;
+//..       goto do_Mov_I_E;
+//..    case 0xC7: /* MOV Iv,Ev */
+//..       goto do_Mov_I_E;
+//.. 
+//..    do_Mov_I_E:
+//..       modrm = getIByte(delta);
+//..       if (epartIsReg(modrm)) {
+//..          delta++; /* mod/rm byte */
+//..          d32 = getUDisp(sz,delta); delta += sz;
+//..          putIReg(sz, eregOfRM(modrm), mkU(szToITy(sz), d32));
+//..          DIP("mov%c $0x%x, %s\n", nameISize(sz), d32, 
+//..                                   nameIReg(sz,eregOfRM(modrm)));
+//..          vassert(0);
+//..       } else {
+//..          addr = disAMode ( &alen, sorb, delta, dis_buf );
+//..          delta += alen;
+//..          d32 = getUDisp(sz,delta); delta += sz;
+//..          storeLE(mkexpr(addr), mkU(szToITy(sz), d32));
+//..          DIP("mov%c $0x%x, %s\n", nameISize(sz), d32, dis_buf);
+//..       }
+//..       break;
+//.. 
+//..    /* ------------------------ opl imm, A ----------------- */
+//.. 
+//..    case 0x04: /* ADD Ib, AL */
+//..       delta = dis_op_imm_A( 1, Iop_Add8, True, delta, "add" );
+//..       break;
+//..    case 0x05: /* ADD Iv, eAX */
+//..       delta = dis_op_imm_A(sz, Iop_Add8, True, delta, "add" );
+//..       break;
+//.. 
+//..    case 0x0C: /* OR Ib, AL */
+//..       delta = dis_op_imm_A( 1, Iop_Or8, True, delta, "or" );
+//..       break;
+//..    case 0x0D: /* OR Iv, eAX */
+//..       delta = dis_op_imm_A( sz, Iop_Or8, True, delta, "or" );
+//..       break;
+//.. 
+//.. //--    case 0x14: /* ADC Ib, AL */
+//.. //--       delta = dis_op_imm_A( 1, ADC, True, delta, "adc" );
+//.. //--       break;
+//.. //--    case 0x15: /* ADC Iv, eAX */
+//.. //--       delta = dis_op_imm_A( sz, ADC, True, delta, "adc" );
+//.. //--       break;
+//.. //-- 
+//.. //--    case 0x1C: /* SBB Ib, AL */
+//.. //--       delta = dis_op_imm_A( 1, SBB, True, delta, "sbb" );
+//.. //--       break;
+//.. //--    case 0x1D: /* SBB Iv, eAX */
+//.. //--       delta = dis_op_imm_A( sz, SBB, True, delta, "sbb" );
+//.. //--       break;
+//.. //-- 
+//..    case 0x24: /* AND Ib, AL */
+//..       delta = dis_op_imm_A( 1, Iop_And8, True, delta, "and" );
+//..       break;
+//..    case 0x25: /* AND Iv, eAX */
+//..       delta = dis_op_imm_A( sz, Iop_And8, True, delta, "and" );
+//..       break;
+//.. 
+//..    case 0x2C: /* SUB Ib, AL */
+//..       delta = dis_op_imm_A(1, Iop_Sub8, True, delta, "sub" );
+//..       break;
+//..    case 0x2D: /* SUB Iv, eAX */
+//..       delta = dis_op_imm_A( sz, Iop_Sub8, True, delta, "sub" );
+//..       break;
+//.. 
+//..    case 0x34: /* XOR Ib, AL */
+//..       delta = dis_op_imm_A( 1, Iop_Xor8, True, delta, "xor" );
+//..       break;
+//..    case 0x35: /* XOR Iv, eAX */
+//..       delta = dis_op_imm_A( sz, Iop_Xor8, True, delta, "xor" );
+//..       break;
+//.. 
+//..    case 0x3C: /* CMP Ib, AL */
+//..       delta = dis_op_imm_A( 1, Iop_Sub8, False, delta, "cmp" );
+//..       break;
+//..    case 0x3D: /* CMP Iv, eAX */
+//..       delta = dis_op_imm_A( sz, Iop_Sub8, False, delta, "cmp" );
+//..       break;
+//.. 
+//..    case 0xA8: /* TEST Ib, AL */
+//..       delta = dis_op_imm_A( 1, Iop_And8, False, delta, "test" );
+//..       break;
+//..    case 0xA9: /* TEST Iv, eAX */
+//..       delta = dis_op_imm_A( sz, Iop_And8, False, delta, "test" );
+//..       break;
+//.. 
+//..    /* ------------------------ opl Ev, Gv ----------------- */
+//..  
+//..    case 0x02: /* ADD Eb,Gb */
+//..       delta = dis_op2_E_G ( sorb, False, Iop_Add8, True, 1, delta, "add" );
+//..       break;
+//..    case 0x03: /* ADD Ev,Gv */
+//..       delta = dis_op2_E_G ( sorb, False, Iop_Add8, True, sz, delta, "add" );
+//..       break;
+//.. 
+//..    case 0x0A: /* OR Eb,Gb */
+//..       delta = dis_op2_E_G ( sorb, False, Iop_Or8, True, 1, delta, "or" );
+//..       break;
+//..    case 0x0B: /* OR Ev,Gv */
+//..       delta = dis_op2_E_G ( sorb, False, Iop_Or8, True, sz, delta, "or" );
+//..       break;
+//.. //-- 
+//.. //--    case 0x12: /* ADC Eb,Gb */
+//.. //--       delta = dis_op2_E_G ( sorb, True, ADC, True, 1, delta, "adc" );
+//.. //--       break;
+//..    case 0x13: /* ADC Ev,Gv */
+//..       delta = dis_op2_E_G ( sorb, True, Iop_Add8, True, sz, delta, "adc" );
+//..       break;
+//.. 
+//.. //--    case 0x1A: /* SBB Eb,Gb */
+//.. //--       delta = dis_op2_E_G ( sorb, True, SBB, True, 1, delta, "sbb" );
+//.. //--       break;
+//..    case 0x1B: /* SBB Ev,Gv */
+//..       delta = dis_op2_E_G ( sorb, True, Iop_Sub8, True, sz, delta, "sbb" );
+//..       break;
+//.. 
+//..    case 0x22: /* AND Eb,Gb */
+//..       delta = dis_op2_E_G ( sorb, False, Iop_And8, True, 1, delta, "and" );
+//..       break;
+//..    case 0x23: /* AND Ev,Gv */
+//..       delta = dis_op2_E_G ( sorb, False, Iop_And8, True, sz, delta, "and" );
+//..       break;
+//.. 
+//..    case 0x2A: /* SUB Eb,Gb */
+//..       delta = dis_op2_E_G ( sorb, False, Iop_Sub8, True, 1, delta, "sub" );
+//..       break;
+//..    case 0x2B: /* SUB Ev,Gv */
+//..       delta = dis_op2_E_G ( sorb, False, Iop_Sub8, True, sz, delta, "sub" );
+//..       break;
+//.. 
+//..    case 0x32: /* XOR Eb,Gb */
+//..       delta = dis_op2_E_G ( sorb, False, Iop_Xor8, True, 1, delta, "xor" );
+//..       break;
+//..    case 0x33: /* XOR Ev,Gv */
+//..       delta = dis_op2_E_G ( sorb, False, Iop_Xor8, True, sz, delta, "xor" );
+//..       break;
+//.. 
+//..    case 0x3A: /* CMP Eb,Gb */
+//..       delta = dis_op2_E_G ( sorb, False, Iop_Sub8, False, 1, delta, "cmp" );
+//..       break;
+//..    case 0x3B: /* CMP Ev,Gv */
+//..       delta = dis_op2_E_G ( sorb, False, Iop_Sub8, False, sz, delta, "cmp" );
+//..       break;
+//.. 
+//..    case 0x84: /* TEST Eb,Gb */
+//..       delta = dis_op2_E_G ( sorb, False, Iop_And8, False, 1, delta, "test" );
+//..       break;
+//..    case 0x85: /* TEST Ev,Gv */
+//..       delta = dis_op2_E_G ( sorb, False, Iop_And8, False, sz, delta, "test" );
+//..       break;
+//.. 
+//..    /* ------------------------ opl Gv, Ev ----------------- */
+//.. 
+//..    case 0x00: /* ADD Gb,Eb */
+//..       delta = dis_op2_G_E ( sorb, False, Iop_Add8, True, 1, delta, "add" );
+//..       break;
+//..    case 0x01: /* ADD Gv,Ev */
+//..       delta = dis_op2_G_E ( sorb, False, Iop_Add8, True, sz, delta, "add" );
+//..       break;
+//.. 
+//..    case 0x08: /* OR Gb,Eb */
+//..       delta = dis_op2_G_E ( sorb, False, Iop_Or8, True, 1, delta, "or" );
+//..       break;
+//..    case 0x09: /* OR Gv,Ev */
+//..       delta = dis_op2_G_E ( sorb, False, Iop_Or8, True, sz, delta, "or" );
+//..       break;
+//.. 
+//..    case 0x10: /* ADC Gb,Eb */
+//..       delta = dis_op2_G_E ( sorb, True, Iop_Add8, True, 1, delta, "adc" );
+//..       break;
+//..    case 0x11: /* ADC Gv,Ev */
+//..       delta = dis_op2_G_E ( sorb, True, Iop_Add8, True, sz, delta, "adc" );
+//..       break;
+//.. 
+//..    case 0x18: /* SBB Gb,Eb */
+//..       delta = dis_op2_G_E ( sorb, True, Iop_Sub8, True, 1, delta, "sbb" );
+//..       break;
+//..    case 0x19: /* SBB Gv,Ev */
+//..       delta = dis_op2_G_E ( sorb, True, Iop_Sub8, True, sz, delta, "sbb" );
+//..       break;
+//.. 
+//..    case 0x20: /* AND Gb,Eb */
+//..       delta = dis_op2_G_E ( sorb, False, Iop_And8, True, 1, delta, "and" );
+//..       break;
+//..    case 0x21: /* AND Gv,Ev */
+//..       delta = dis_op2_G_E ( sorb, False, Iop_And8, True, sz, delta, "and" );
+//..       break;
+//.. 
+//..    case 0x28: /* SUB Gb,Eb */
+//..       delta = dis_op2_G_E ( sorb, False, Iop_Sub8, True, 1, delta, "sub" );
+//..       break;
+//..    case 0x29: /* SUB Gv,Ev */
+//..       delta = dis_op2_G_E ( sorb, False, Iop_Sub8, True, sz, delta, "sub" );
+//..       break;
+//.. 
+//..    case 0x30: /* XOR Gb,Eb */
+//..       delta = dis_op2_G_E ( sorb, False, Iop_Xor8, True, 1, delta, "xor" );
+//..       break;
+//..    case 0x31: /* XOR Gv,Ev */
+//..       delta = dis_op2_G_E ( sorb, False, Iop_Xor8, True, sz, delta, "xor" );
+//..       break;
+//.. 
+//..    case 0x38: /* CMP Gb,Eb */
+//..       delta = dis_op2_G_E ( sorb, False, Iop_Sub8, False, 1, delta, "cmp" );
+//..       break;
+//..    case 0x39: /* CMP Gv,Ev */
+//..       delta = dis_op2_G_E ( sorb, False, Iop_Sub8, False, sz, delta, "cmp" );
+//..       break;
+//.. 
+//..    /* ------------------------ POP ------------------------ */
+//.. 
+//..    case 0x58: /* POP eAX */
+//..    case 0x59: /* POP eCX */
+//..    case 0x5A: /* POP eDX */
+//..    case 0x5B: /* POP eBX */
+//..    case 0x5D: /* POP eBP */
+//..    case 0x5E: /* POP eSI */
+//..    case 0x5F: /* POP eDI */
+//..    case 0x5C: /* POP eSP */
+//..       vassert(sz == 2 || sz == 4);
+//..       t1 = newTemp(szToITy(sz)); t2 = newTemp(Ity_I32);
+//..       assign(t2, getIReg(4, R_ESP));
+//..       assign(t1, loadLE(szToITy(sz),mkexpr(t2)));
+//..       putIReg(4, R_ESP, binop(Iop_Add32, mkexpr(t2), mkU32(sz)));
+//..       putIReg(sz, opc-0x58, mkexpr(t1));
+//..       DIP("pop%c %s\n", nameISize(sz), nameIReg(sz,opc-0x58));
+//..       break;
+//.. 
+//..    case 0x9D: /* POPF */
+//..       vassert(sz == 2 || sz == 4);
+//..       vassert(sz == 4); // until we know a sz==2 test case exists
+//..       t1 = newTemp(Ity_I32); t2 = newTemp(Ity_I32);
+//..       assign(t2, getIReg(4, R_ESP));
+//..       assign(t1, widenUto32(loadLE(szToITy(sz),mkexpr(t2))));
+//..       putIReg(4, R_ESP, binop(Iop_Add32, mkexpr(t2), mkU32(sz)));
+//..       /* t1 is the flag word.  Mask out everything except OSZACP and 
+//..          set the flags thunk to X86G_CC_OP_COPY. */
+//..       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,
+//..                               mkexpr(t1), 
+//..                               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 )
+//..                              )
+//..                        )
+//..           );
+//.. 
+//..       /* Also need to set the D flag, which is held in bit 10 of t1.
+//..          If zero, put 1 in OFFB_DFLAG, else -1 in OFFB_DFLAG. */
+//..       stmt( IRStmt_Put( 
+//..                OFFB_DFLAG,
+//..                IRExpr_Mux0X( 
+//..                   unop(Iop_32to8,
+//..                        binop(Iop_And32, 
+//..                              binop(Iop_Shr32, mkexpr(t1), mkU8(10)), 
+//..                              mkU32(1))),
+//..                   mkU32(1), 
+//..                   mkU32(0xFFFFFFFF))) 
+//..           );
+//.. 
+//..       /* And set the ID flag */
+//..       stmt( IRStmt_Put( 
+//..                OFFB_IDFLAG,
+//..                IRExpr_Mux0X( 
+//..                   unop(Iop_32to8,
+//..                        binop(Iop_And32, 
+//..                              binop(Iop_Shr32, mkexpr(t1), mkU8(21)), 
+//..                              mkU32(1))),
+//..                   mkU32(0), 
+//..                   mkU32(1))) 
+//..           );
+//.. 
+//..       DIP("popf%c\n", nameISize(sz));
+//..       break;
+//.. 
+//..    case 0x61: /* POPA */
+//..       /* This is almost certainly wrong for sz==2.  So ... */
+//..       if (sz != 4) goto decode_failure;
+//.. 
+//..       /* t5 is the old %ESP value. */
+//..       t5 = newTemp(Ity_I32);
+//..       assign( t5, getIReg(4, R_ESP) );
+//.. 
+//..       /* Reload all the registers, except %esp. */
+//..       putIReg(4,R_EAX, loadLE(Ity_I32, binop(Iop_Add32,mkexpr(t5),mkU32(28)) ));
+//..       putIReg(4,R_ECX, loadLE(Ity_I32, binop(Iop_Add32,mkexpr(t5),mkU32(24)) ));
+//..       putIReg(4,R_EDX, loadLE(Ity_I32, binop(Iop_Add32,mkexpr(t5),mkU32(20)) ));
+//..       putIReg(4,R_EBX, loadLE(Ity_I32, binop(Iop_Add32,mkexpr(t5),mkU32(16)) ));
+//..       /* ignore saved %ESP */
+//..       putIReg(4,R_EBP, loadLE(Ity_I32, binop(Iop_Add32,mkexpr(t5),mkU32( 8)) ));
+//..       putIReg(4,R_ESI, loadLE(Ity_I32, binop(Iop_Add32,mkexpr(t5),mkU32( 4)) ));
+//..       putIReg(4,R_EDI, loadLE(Ity_I32, binop(Iop_Add32,mkexpr(t5),mkU32( 0)) ));
+//.. 
+//..       /* and move %ESP back up */
+//..       putIReg( 4, R_ESP, binop(Iop_Add32, mkexpr(t5), mkU32(8*4)) );
+//.. 
+//..       DIP("pusha%c\n", nameISize(sz));
+//..       break;
+//.. 
+//..    case 0x8F: /* POPL/POPW m32 */
+//..      { Int len;
+//..        UChar rm = getIByte(delta);
+//.. 
+//..        /* make sure this instruction is correct POP */
+//..        vassert(!epartIsReg(rm) && (gregOfRM(rm) == 0));
+//..        /* and has correct size */
+//..        vassert(sz == 4);      
+//..        
+//..        t1 = newTemp(Ity_I32); t3 = newTemp(Ity_I32);
+//..        /* set t1 to ESP: t1 = ESP */
+//..        assign( t1, getIReg(4, R_ESP) );
+//..        /* load M[ESP] to virtual register t3: t3 = M[t1] */
+//..        assign( t3, loadLE(Ity_I32, mkexpr(t1)) );
+//..        
+//..        /* increase ESP; must be done before the STORE.  Intel manual says:
+//..             If the ESP register is used as a base register for addressing
+//..             a destination operand in memory, the POP instruction computes
+//..             the effective address of the operand after it increments the
+//..             ESP register.
+//..        */
+//..        putIReg(4, R_ESP, binop(Iop_Add32, mkexpr(t1), mkU32(sz)) );
+//.. 
+//..        /* resolve MODR/M */
+//..        addr = disAMode ( &len, sorb, delta, dis_buf);
+//..        storeLE( mkexpr(addr), mkexpr(t3) );
+//.. 
+//..        DIP("popl %s\n", dis_buf);
+//.. 
+//..        delta += len;
+//..        break;
+//..      }
+//.. 
+//.. //--    case 0x1F: /* POP %DS */
+//.. //--       dis_pop_segreg( cb, R_DS, sz ); break;
+//.. //--    case 0x07: /* POP %ES */
+//.. //--       dis_pop_segreg( cb, R_ES, sz ); break;
+//.. //--    case 0x17: /* POP %SS */
+//.. //--       dis_pop_segreg( cb, R_SS, sz ); break;
+//.. 
+//..    /* ------------------------ PUSH ----------------------- */
+//.. 
+//..    case 0x50: /* PUSH eAX */
+//..    case 0x51: /* PUSH eCX */
+//..    case 0x52: /* PUSH eDX */
+//..    case 0x53: /* PUSH eBX */
+//..    case 0x55: /* PUSH eBP */
+//..    case 0x56: /* PUSH eSI */
+//..    case 0x57: /* PUSH eDI */
+//..    case 0x54: /* PUSH eSP */
+//..       /* This is the Right Way, in that the value to be pushed is
+//..          established before %esp is changed, so that pushl %esp
+//..          correctly pushes the old value. */
+//..       vassert(sz == 2 || sz == 4);
+//..       ty = sz==2 ? Ity_I16 : Ity_I32;
+//..       t1 = newTemp(ty); t2 = newTemp(Ity_I32);
+//..       assign(t1, getIReg(sz, opc-0x50));
+//..       assign(t2, binop(Iop_Sub32, getIReg(4, R_ESP), mkU32(sz)));
+//..       putIReg(4, R_ESP, mkexpr(t2) );
+//..       storeLE(mkexpr(t2),mkexpr(t1));
+//..       DIP("push%c %s\n", nameISize(sz), nameIReg(sz,opc-0x50));
+//..       break;
+//.. 
+//.. 
+//..    case 0x68: /* PUSH Iv */
+//..       d32 = getUDisp(sz,delta); delta += sz;
+//..       goto do_push_I;
+//..    case 0x6A: /* PUSH Ib, sign-extended to sz */
+//..       d32 = getSDisp8(delta); delta += 1;
+//..       goto do_push_I;
+//..    do_push_I:
+//..       ty = szToITy(sz);
+//..       t1 = newTemp(Ity_I32); t2 = newTemp(ty);
+//..       assign( t1, binop(Iop_Sub32,getIReg(4,R_ESP),mkU32(sz)) );
+//..       putIReg(4, R_ESP, mkexpr(t1) );
+//..       storeLE( mkexpr(t1), mkU(ty,d32) );
+//..       DIP("push%c $0x%x\n", nameISize(sz), d32);
+//..       break;
+//.. 
+//..    case 0x9C: /* PUSHF */ {
+//..       vassert(sz == 2 || sz == 4);
+//..       vassert(sz == 4);  // wait for sz==2 test case
+//.. 
+//..       t1 = newTemp(Ity_I32);
+//..       assign( t1, binop(Iop_Sub32,getIReg(4,R_ESP),mkU32(sz)) );
+//..       putIReg(4, R_ESP, mkexpr(t1) );
+//.. 
+//..       t2 = newTemp(Ity_I32);
+//..       assign( t2, mk_x86g_calculate_eflags_all() );
+//.. 
+//..       /* Patch in the D flag.  This can simply be a copy of bit 10 of
+//..          baseBlock[OFFB_DFLAG]. */
+//..       t3 = newTemp(Ity_I32);
+//..       assign( t3, binop(Iop_Or32,
+//..                         mkexpr(t2),
+//..                         binop(Iop_And32,
+//..                               IRExpr_Get(OFFB_DFLAG,Ity_I32),
+//..                               mkU32(1<<10))) 
+//..             );
+//.. 
+//..       /* And patch in the ID flag. */
+//..       t4 = newTemp(Ity_I32);
+//..       assign( t4, binop(Iop_Or32,
+//..                         mkexpr(t3),
+//..                         binop(Iop_And32,
+//..                               binop(Iop_Shl32, IRExpr_Get(OFFB_IDFLAG,Ity_I32), 
+//..                                                mkU8(21)),
+//..                               mkU32(1<<21)))
+//..             );
+//.. 
+//..       /* if sz==2, the stored value needs to be narrowed. */
+//..       if (sz == 2)
+//..         storeLE( mkexpr(t1), unop(Iop_32to16,mkexpr(t4)) );
+//..       else 
+//..         storeLE( mkexpr(t1), mkexpr(t4) );
+//.. 
+//..       DIP("pushf%c\n", nameISize(sz));
+//..       break;
+//..    }
+//.. 
+//..    case 0x60: /* PUSHA */
+//..       /* This is almost certainly wrong for sz==2.  So ... */
+//..       if (sz != 4) goto decode_failure;
+//.. 
+//..       /* This is the Right Way, in that the value to be pushed is
+//..          established before %esp is changed, so that pusha
+//..          correctly pushes the old %esp value.  New value of %esp is
+//..          pushed at start. */
+//..       /* t0 is the %ESP value we're going to push. */
+//..       t0 = newTemp(Ity_I32);
+//..       assign( t0, getIReg(4, R_ESP) );
+//.. 
+//..       /* t5 will be the new %ESP value. */
+//..       t5 = newTemp(Ity_I32);
+//..       assign( t5, binop(Iop_Sub32, mkexpr(t0), mkU32(8*4)) );
+//.. 
+//..       /* Update guest state before prodding memory. */
+//..       putIReg(4, R_ESP, mkexpr(t5));
+//.. 
+//..       /* Dump all the registers. */
+//..       storeLE( binop(Iop_Add32,mkexpr(t5),mkU32(28)), getIReg(4,R_EAX) );
+//..       storeLE( binop(Iop_Add32,mkexpr(t5),mkU32(24)), getIReg(4,R_ECX) );
+//..       storeLE( binop(Iop_Add32,mkexpr(t5),mkU32(20)), getIReg(4,R_EDX) );
+//..       storeLE( binop(Iop_Add32,mkexpr(t5),mkU32(16)), getIReg(4,R_EBX) );
+//..       storeLE( binop(Iop_Add32,mkexpr(t5),mkU32(12)), mkexpr(t0) /*esp*/);
+//..       storeLE( binop(Iop_Add32,mkexpr(t5),mkU32( 8)), getIReg(4,R_EBP) );
+//..       storeLE( binop(Iop_Add32,mkexpr(t5),mkU32( 4)), getIReg(4,R_ESI) );
+//..       storeLE( binop(Iop_Add32,mkexpr(t5),mkU32( 0)), getIReg(4,R_EDI) );
+//.. 
+//..       DIP("pusha%c\n", nameISize(sz));
+//..       break;
+//.. 
+//.. 
+//.. //--    case 0x0E: /* PUSH %CS */
+//.. //--       dis_push_segreg( cb, R_CS, sz ); break;
+//.. //--    case 0x1E: /* PUSH %DS */
+//.. //--       dis_push_segreg( cb, R_DS, sz ); break;
+//.. //--    case 0x06: /* PUSH %ES */
+//.. //--       dis_push_segreg( cb, R_ES, sz ); break;
+//.. //--    case 0x16: /* PUSH %SS */
+//.. //--       dis_push_segreg( cb, R_SS, sz ); break;
+//.. 
+//..    /* ------------------------ SCAS et al ----------------- */
+//.. 
+//..    case 0xA4: /* MOVS, no REP prefix */
+//..    case 0xA5: 
+//..       dis_string_op( dis_MOVS, ( opc == 0xA4 ? 1 : sz ), "movs", sorb );
+//..       break;
+//.. 
+//..   case 0xA6: /* CMPSb, no REP prefix */
+//.. //--    case 0xA7:
+//..      dis_string_op( dis_CMPS, ( opc == 0xA6 ? 1 : sz ), "cmps", sorb );
+//..      break;
+//.. //-- 
+//..    case 0xAA: /* STOS, no REP prefix */
+//..    case 0xAB:
+//..       dis_string_op( dis_STOS, ( opc == 0xAA ? 1 : sz ), "stos", sorb );
+//..       break;
+//.. //--    
+//.. //--    case 0xAC: /* LODS, no REP prefix */
+//.. //--    case 0xAD:
+//.. //--       dis_string_op( cb, dis_LODS, ( opc == 0xAC ? 1 : sz ), "lods", sorb );
+//.. //--       break;
+//.. 
+//..    case 0xAE: /* SCAS, no REP prefix */
+//..    case 0xAF:
+//..       dis_string_op( dis_SCAS, ( opc == 0xAE ? 1 : sz ), "scas", sorb );
+//..       break;
+//.. 
+//.. 
+//..    case 0xFC: /* CLD */
+//..       stmt( IRStmt_Put( OFFB_DFLAG, mkU32(1)) );
+//..       DIP("cld\n");
+//..       break;
+//.. 
+//..    case 0xFD: /* STD */
+//..       stmt( IRStmt_Put( OFFB_DFLAG, mkU32(0xFFFFFFFF)) );
+//..       DIP("std\n");
+//..       break;
+//.. 
+//.. //--    case 0xF8: /* CLC */
+//.. //--       uInstr0(cb, CALLM_S, 0);
+//.. //--       uInstr1(cb, CALLM, 0, Lit16, VGOFF_(helper_CLC));
+//.. //--       uFlagsRWU(cb, FlagsEmpty, FlagC, FlagsOSZAP);
+//.. //--       uInstr0(cb, CALLM_E, 0);
+//.. //--       DIP("clc\n");
+//.. //--       break;
+//.. //-- 
+//.. //--    case 0xF9: /* STC */
+//.. //--       uInstr0(cb, CALLM_S, 0);
+//.. //--       uInstr1(cb, CALLM, 0, Lit16, VGOFF_(helper_STC));
+//.. //--       uFlagsRWU(cb, FlagsEmpty, FlagC, FlagsOSZAP);
+//.. //--       uInstr0(cb, CALLM_E, 0);
+//.. //--       DIP("stc\n");
+//.. //--       break;
+//.. //-- 
+//.. //--    case 0xF5: /* CMC */
+//.. //--       uInstr0(cb, CALLM_S, 0);
+//.. //--       uInstr1(cb, CALLM, 0, Lit16, VGOFF_(helper_CMC));
+//.. //--       uFlagsRWU(cb, FlagC, FlagC, FlagsOSZAP);
+//.. //--       uInstr0(cb, CALLM_E, 0);
+//.. //--       DIP("cmc\n");
+//.. //--       break;
+//.. 
+//..    /* REPNE prefix insn */
+//..    case 0xF2: { 
+//..       Addr32 eip_orig = guest_eip_bbstart + delta - 1;
+//..       vassert(sorb == 0);
+//..       abyte = getIByte(delta); delta++;
+//.. 
+//..       if (abyte == 0x66) { sz = 2; abyte = getIByte(delta); delta++; }
+//..       whatNext = Dis_StopHere;         
+//.. 
+//..       switch (abyte) {
+//..       /* According to the Intel manual, "repne movs" should never occur, but
+//..        * in practice it has happened, so allow for it here... */
+//..       case 0xA4: sz = 1;   /* REPNE MOVS<sz> */
+//..         goto decode_failure;
+//.. //--       case 0xA5: 
+//..         //         dis_REP_op ( CondNZ, dis_MOVS, sz, eip_orig,
+//..         //                              guest_eip_bbstart+delta, "repne movs" );
+//..         //         break;
+//.. //-- 
+//.. //--       case 0xA6: sz = 1;   /* REPNE CMPS<sz> */
+//.. //--       case 0xA7:
+//.. //--          dis_REP_op ( cb, CondNZ, dis_CMPS, sz, eip_orig, eip, "repne cmps" );
+//.. //--          break;
+//.. //-- 
+//..       case 0xAE: sz = 1;   /* REPNE SCAS<sz> */
+//..       case 0xAF:
+//..          dis_REP_op ( X86CondNZ, dis_SCAS, sz, eip_orig,
+//..                                  guest_eip_bbstart+delta, "repne scas" );
+//..          break;
+//.. 
+//..       default:
+//..          goto decode_failure;
+//..       }
+//..       break;
+//..    }
+//.. 
+//..    /* REP/REPE prefix insn (for SCAS and CMPS, 0xF3 means REPE,
+//..       for the rest, it means REP) */
+//..    case 0xF3: { 
+//..       Addr32 eip_orig = guest_eip_bbstart + delta - 1;
+//..       vassert(sorb == 0);
+//..       abyte = getIByte(delta); delta++;
+//.. 
+//..       if (abyte == 0x66) { sz = 2; abyte = getIByte(delta); delta++; }
+//..       whatNext = Dis_StopHere;
+//.. 
+//..       switch (abyte) {
+//..       case 0xA4: sz = 1;   /* REP MOVS<sz> */
+//..       case 0xA5:
+//..          dis_REP_op ( X86CondAlways, dis_MOVS, sz, eip_orig, 
+//..                                      guest_eip_bbstart+delta, "rep movs" );
+//..          break;
+//.. 
+//..       case 0xA6: sz = 1;   /* REPE CMP<sz> */
+//..       case 0xA7:
+//..          dis_REP_op ( X86CondZ, dis_CMPS, sz, eip_orig, 
+//..                                 guest_eip_bbstart+delta, "repe cmps" );
+//..          break;
+//.. 
+//..       case 0xAA: sz = 1;   /* REP STOS<sz> */
+//..       case 0xAB:
+//..          dis_REP_op ( X86CondAlways, dis_STOS, sz, eip_orig, 
+//..                                      guest_eip_bbstart+delta, "rep stos" );
+//..          break;
+//.. //-- 
+//.. //--       case 0xAE: sz = 1;   /* REPE SCAS<sz> */
+//.. //--       case 0xAF: 
+//.. //--          dis_REP_op ( cb, CondZ, dis_SCAS, sz, eip_orig, eip, "repe scas" );
+//.. //--          break;
+//..       
+//..       case 0x90:           /* REP NOP (PAUSE) */
+//..          /* a hint to the P4 re spin-wait loop */
+//..          DIP("rep nop (P4 pause)\n");
+//..          jmp_lit(Ijk_Yield, ((Addr32)guest_eip_bbstart)+delta);
+//..          whatNext = Dis_StopHere;
+//..          break;
+//.. 
+//.. //--       case 0xC3:           /* REP RET */
+//.. //--          /* AMD K7/K8-specific optimisation; faster than vanilla RET */
+//.. //--          dis_ret(cb, 0);
+//.. //--          DIP("rep ret\n");
+//.. //--          break;
+//.. 
+//..       default:
+//..          goto decode_failure;
+//..       }
+//..       break;
+//..    }
+//.. 
+//..    /* ------------------------ XCHG ----------------------- */
+//.. 
+//..    case 0x86: /* XCHG Gb,Eb */
+//..       sz = 1;
+//..       /* Fall through ... */
+//..    case 0x87: /* XCHG Gv,Ev */
+//..       modrm = getIByte(delta);
+//..       ty = szToITy(sz);
+//..       t1 = newTemp(ty); t2 = newTemp(ty);
+//..       if (epartIsReg(modrm)) {
+//..          assign(t1, getIReg(sz, eregOfRM(modrm)));
+//..          assign(t2, getIReg(sz, gregOfRM(modrm)));
+//..          putIReg(sz, gregOfRM(modrm), mkexpr(t1));
+//..          putIReg(sz, eregOfRM(modrm), mkexpr(t2));
+//..          delta++;
+//..          DIP("xchg%c %s, %s\n", 
+//..              nameISize(sz), nameIReg(sz,gregOfRM(modrm)), 
+//..                             nameIReg(sz,eregOfRM(modrm)));
+//..       } else {
+//..          addr = disAMode ( &alen, sorb, delta, dis_buf );
+//..          assign( t1, loadLE(ty,mkexpr(addr)) );
+//..          assign( t2, getIReg(sz,gregOfRM(modrm)) );
+//..          storeLE( mkexpr(addr), mkexpr(t2) );
+//..          putIReg( sz, gregOfRM(modrm), mkexpr(t1) );
+//..          delta += alen;
+//..          DIP("xchg%c %s, %s\n", nameISize(sz), 
+//..                                 nameIReg(sz,gregOfRM(modrm)), dis_buf);
+//..       }
+//..       break;
+//.. 
+//..    case 0x90: /* XCHG eAX,eAX */
+//..       DIP("nop\n");
+//..       break;
+//..    case 0x91: /* XCHG eAX,eCX */
+//..    case 0x92: /* XCHG eAX,eDX */
+//..    case 0x93: /* XCHG eAX,eBX */
+//..    case 0x94: /* XCHG eAX,eSP */
+//..    case 0x95: /* XCHG eAX,eBP */
+//..    case 0x96: /* XCHG eAX,eSI */
+//..    case 0x97: /* XCHG eAX,eDI */
+//..       codegen_xchg_eAX_Reg ( sz, opc - 0x90 );
+//..       break;
+//.. 
+//.. //--    /* ------------------------ XLAT ----------------------- */
+//.. //-- 
+//.. //--    case 0xD7: /* XLAT */
+//.. //--       t1 = newTemp(cb); t2 = newTemp(cb);
+//.. //--       uInstr2(cb, GET, sz, ArchReg, R_EBX, TempReg, t1); /* get eBX */
+//.. //--       handleSegOverride( cb, sorb, t1 );               /* make t1 DS:eBX */
+//.. //--       uInstr2(cb, GET, 1, ArchReg, R_AL, TempReg, t2); /* get AL */
+//.. //--       /* Widen %AL to 32 bits, so it's all defined when we add it. */
+//.. //--       uInstr1(cb, WIDEN, 4, TempReg, t2);
+//.. //--       uWiden(cb, 1, False);
+//.. //--       uInstr2(cb, ADD, sz, TempReg, t2, TempReg, t1);  /* add AL to eBX */
+//.. //--       uInstr2(cb, LOAD, 1, TempReg, t1,  TempReg, t2); /* get byte at t1 into t2 */
+//.. //--       uInstr2(cb, PUT, 1, TempReg, t2, ArchReg, R_AL); /* put byte into AL */
+//.. //-- 
+//.. //--       DIP("xlat%c [ebx]\n", nameISize(sz));
+//.. //--       break;
+//.. //-- 
+//.. //--    /* ------------------------ IN / OUT ----------------------- */
+//.. //-- 
+//.. //--    case 0xE4: /* IN ib, %al        */
+//.. //--    case 0xE5: /* IN ib, %{e}ax     */
+//.. //--    case 0xEC: /* IN (%dx),%al      */
+//.. //--    case 0xED: /* IN (%dx),%{e}ax   */
+//.. //--       t1 = newTemp(cb);
+//.. //--       t2 = newTemp(cb);
+//.. //--       t3 = newTemp(cb);
+//.. //-- 
+//.. //--       uInstr0(cb, CALLM_S, 0);
+//.. //--       /* operand size? */
+//.. //--       uInstr2(cb, MOV,   4, Literal, 0, TempReg, t1);
+//.. //--       uLiteral(cb, ( opc == 0xE4 || opc == 0xEC ) ? 1 : sz);
+//.. //--       uInstr1(cb, PUSH,  4, TempReg, t1);
+//.. //--       /* port number ? */
+//.. //--       if ( opc == 0xE4 || opc == 0xE5 ) {
+//.. //--          abyte = getUChar(eip); eip++;
+//.. //--          uInstr2(cb, MOV,   4, Literal, 0, TempReg, t2);
+//.. //--          uLiteral(cb, abyte);
+//.. //--       }
+//.. //--       else
+//.. //--          uInstr2(cb, GET,   4, ArchReg, R_EDX, TempReg, t2);
+//.. //-- 
+//.. //--       uInstr1(cb, PUSH,  4, TempReg, t2);
+//.. //--       uInstr1(cb, CALLM, 0, Lit16,   VGOFF_(helper_IN));
+//.. //--       uFlagsRWU(cb, FlagsEmpty, FlagsEmpty, FlagsEmpty);
+//.. //--       uInstr1(cb, POP,   4, TempReg, t2);
+//.. //--       uInstr1(cb, CLEAR, 0, Lit16,   4);
+//.. //--       uInstr0(cb, CALLM_E, 0);
+//.. //--       uInstr2(cb, PUT,   4, TempReg, t2, ArchReg, R_EAX);
+//.. //--       if ( opc == 0xE4 || opc == 0xE5 ) {
+//.. //--          DIP("in 0x%x, %%eax/%%ax/%%al\n", getUChar(eip-1) );
+//.. //--       } else {
+//.. //--          DIP("in (%%dx), %%eax/%%ax/%%al\n");
+//.. //--       }
+//.. //--       break;
+//.. //--    case 0xE6: /* OUT %al,ib       */
+//.. //--    case 0xE7: /* OUT %{e}ax,ib    */
+//.. //--    case 0xEE: /* OUT %al,(%dx)    */
+//.. //--    case 0xEF: /* OUT %{e}ax,(%dx) */
+//.. //--       t1 = newTemp(cb);
+//.. //--       t2 = newTemp(cb);
+//.. //--       t3 = newTemp(cb);
+//.. //-- 
+//.. //--       uInstr0(cb, CALLM_S, 0);
+//.. //--       /* operand size? */
+//.. //--       uInstr2(cb, MOV,   4, Literal, 0, TempReg, t1);
+//.. //--       uLiteral(cb, ( opc == 0xE6 || opc == 0xEE ) ? 1 : sz);
+//.. //--       uInstr1(cb, PUSH,  4, TempReg, t1);
+//.. //--       /* port number ? */
+//.. //--       if ( opc == 0xE6 || opc == 0xE7 ) {
+//.. //--          abyte = getUChar(eip); eip++;
+//.. //--          uInstr2(cb, MOV,   4, Literal, 0, TempReg, t2);
+//.. //--          uLiteral(cb, abyte);
+//.. //--       }
+//.. //--       else
+//.. //--          uInstr2(cb, GET,   4, ArchReg, R_EDX, TempReg, t2);
+//.. //--       uInstr1(cb, PUSH,  4, TempReg, t2);
+//.. //--       uInstr2(cb, GET,   4, ArchReg, R_EAX, TempReg, t3);
+//.. //--       uInstr1(cb, PUSH,  4, TempReg, t3);
+//.. //--       uInstr1(cb, CALLM, 0, Lit16,   VGOFF_(helper_OUT));
+//.. //--       uFlagsRWU(cb, FlagsEmpty, FlagsEmpty, FlagsEmpty);
+//.. //--       uInstr1(cb, CLEAR,  0, Lit16,  12);
+//.. //--       uInstr0(cb, CALLM_E, 0);
+//.. //--       if ( opc == 0xE4 || opc == 0xE5 ) {
+//.. //--          DIP("out %%eax/%%ax/%%al, 0x%x\n", getUChar(eip-1) );
+//.. //--       } else {
+//.. //--          DIP("out %%eax/%%ax/%%al, (%%dx)\n");
+//.. //--       }
+//.. //--       break;
+//.. 
+//..    /* ------------------------ (Grp1 extensions) ---------- */
+//.. 
+//..    case 0x80: /* Grp1 Ib,Eb */
+//..       modrm = getIByte(delta);
+//..       am_sz = lengthAMode(delta);
+//..       sz    = 1;
+//..       d_sz  = 1;
+//..       d32   = getUChar(delta + am_sz);
+//..       delta = dis_Grp1 ( sorb, delta, modrm, am_sz, d_sz, sz, d32 );
+//..       break;
+//.. 
+//..    case 0x81: /* Grp1 Iv,Ev */
+//..       modrm = getIByte(delta);
+//..       am_sz = lengthAMode(delta);
+//..       d_sz  = sz;
+//..       d32   = getUDisp(d_sz, delta + am_sz);
+//..       delta = dis_Grp1 ( sorb, delta, modrm, am_sz, d_sz, sz, d32 );
+//..       break;
+//.. 
+//..    case 0x83: /* Grp1 Ib,Ev */
+//..       modrm = getIByte(delta);
+//..       am_sz = lengthAMode(delta);
+//..       d_sz  = 1;
+//..       d32   = getSDisp8(delta + am_sz);
+//..       delta = dis_Grp1 ( sorb, delta, modrm, am_sz, d_sz, sz, d32 );
+//..       break;
+//.. 
+//..    /* ------------------------ (Grp2 extensions) ---------- */
+//.. 
+//..    case 0xC0: /* Grp2 Ib,Eb */
+//..       modrm = getIByte(delta);
+//..       am_sz = lengthAMode(delta);
+//..       d_sz  = 1;
+//..       d32   = getUChar(delta + am_sz);
+//..       sz    = 1;
+//..       delta = dis_Grp2 ( sorb, delta, modrm, am_sz, d_sz, sz, 
+//..                          mkU8(d32 & 0xFF), NULL );
+//..       break;
+//.. 
+//..    case 0xC1: /* Grp2 Ib,Ev */
+//..       modrm = getIByte(delta);
+//..       am_sz = lengthAMode(delta);
+//..       d_sz  = 1;
+//..       d32   = getUChar(delta + am_sz);
+//..       delta = dis_Grp2 ( sorb, delta, modrm, am_sz, d_sz, sz, 
+//..                          mkU8(d32 & 0xFF), NULL );
+//..       break;
+//.. 
+//..    case 0xD0: /* Grp2 1,Eb */
+//..       modrm = getIByte(delta);
+//..       am_sz = lengthAMode(delta);
+//..       d_sz  = 0;
+//..       d32   = 1;
+//..       sz    = 1;
+//..       delta = dis_Grp2 ( sorb, delta, modrm, am_sz, d_sz, sz, 
+//..                          mkU8(d32), NULL );
+//..       break;
+//.. 
+//..    case 0xD1: /* Grp2 1,Ev */
+//..       modrm = getUChar(delta);
+//..       am_sz = lengthAMode(delta);
+//..       d_sz  = 0;
+//..       d32   = 1;
+//..       delta = dis_Grp2 ( sorb, delta, modrm, am_sz, d_sz, sz, 
+//..                          mkU8(d32), NULL );
+//..       break;
+//.. 
+//..    case 0xD2: /* Grp2 CL,Eb */
+//..       modrm = getUChar(delta);
+//..       am_sz = lengthAMode(delta);
+//..       d_sz  = 0;
+//..       sz    = 1;
+//..       delta = dis_Grp2 ( sorb, delta, modrm, am_sz, d_sz, sz, 
+//..                          getIReg(1,R_ECX), "%cl" );
+//..       break;
+//.. 
+//..    case 0xD3: /* Grp2 CL,Ev */
+//..       modrm = getIByte(delta);
+//..       am_sz = lengthAMode(delta);
+//..       d_sz  = 0;
+//..       delta = dis_Grp2 ( sorb, delta, modrm, am_sz, d_sz, sz, 
+//..                          getIReg(1,R_ECX), "%cl" );
+//..       break;
+//.. 
+//..    /* ------------------------ (Grp3 extensions) ---------- */
+//.. 
+//..    case 0xF6: /* Grp3 Eb */
+//..       delta = dis_Grp3 ( sorb, 1, delta );
+//..       break;
+//..    case 0xF7: /* Grp3 Ev */
+//..       delta = dis_Grp3 ( sorb, sz, delta );
+//..       break;
+//.. 
+//..    /* ------------------------ (Grp4 extensions) ---------- */
+//.. 
+//..    case 0xFE: /* Grp4 Eb */
+//..       delta = dis_Grp4 ( sorb, delta );
+//..       break;
+//.. 
+//..    /* ------------------------ (Grp5 extensions) ---------- */
+//.. 
+//..    case 0xFF: /* Grp5 Ev */
+//..       delta = dis_Grp5 ( sorb, sz, delta, &whatNext );
+//..       break;
+//.. 
+//..    /* ------------------------ Escapes to 2-byte opcodes -- */
+//.. 
+//..    case 0x0F: {
+//..       opc = getIByte(delta); delta++;
+//..       switch (opc) {
+//.. 
+//.. //--       /* =-=-=-=-=-=-=-=-=- Grp8 =-=-=-=-=-=-=-=-=-=-=-= */
+//.. //-- 
+//.. //--       case 0xBA: /* Grp8 Ib,Ev */
+//.. //--          modrm = getUChar(eip);
+//.. //--          am_sz = lengthAMode(eip);
+//.. //--          d32   = getSDisp8(eip + am_sz);
+//.. //--          eip = dis_Grp8_BT ( cb, sorb, eip, modrm, am_sz, sz, d32 );
+//.. //--          break;
+//.. 
+//..       /* =-=-=-=-=-=-=-=-=- BSF/BSR -=-=-=-=-=-=-=-=-=-= */
+//.. 
+//..       case 0xBC: /* BSF Gv,Ev */
+//..          delta = dis_bs_E_G ( sorb, sz, delta, True );
+//..          break;
+//..       case 0xBD: /* BSR Gv,Ev */
+//..          delta = dis_bs_E_G ( sorb, sz, delta, False );
+//..          break;
+//.. 
+//..       /* =-=-=-=-=-=-=-=-=- BSWAP -=-=-=-=-=-=-=-=-=-=-= */
+//.. 
+//..       case 0xC8: /* BSWAP %eax */
+//..       case 0xC9:
+//..       case 0xCA:
+//..       case 0xCB:
+//..       case 0xCC:
+//..       case 0xCD:
+//..       case 0xCE:
+//..       case 0xCF: /* BSWAP %edi */
+//..          /* AFAICS from the Intel docs, this only exists at size 4. */
+//..          vassert(sz == 4);
+//..          t1 = newTemp(Ity_I32);
+//..          t2 = newTemp(Ity_I32);
+//..          assign( t1, getIReg(4, 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) )
+//..             )))
+//..          );
+//.. 
+//..          putIReg(4, opc-0xC8, mkexpr(t2));
+//..          DIP("bswapl %s\n", nameIReg(4, opc-0xC8));
+//..          break;
+//.. 
+//..       /* =-=-=-=-=-=-=-=-=- BT/BTS/BTR/BTC =-=-=-=-=-=-= */
+//.. 
+//..       case 0xA3: /* BT Gv,Ev */
+//..          delta = dis_bt_G_E ( sorb, sz, delta, BtOpNone );
+//..          break;
+//..       case 0xB3: /* BTR Gv,Ev */
+//..          delta = dis_bt_G_E ( sorb, sz, delta, BtOpReset );
+//..          break;
+//..       case 0xAB: /* BTS Gv,Ev */
+//..          delta = dis_bt_G_E ( sorb, sz, delta, BtOpSet );
+//..          break;
+//..       case 0xBB: /* BTC Gv,Ev */
+//..          delta = dis_bt_G_E ( sorb, sz, delta, BtOpComp );
+//..          break;
+//.. 
+//..       /* =-=-=-=-=-=-=-=-=- CMOV =-=-=-=-=-=-=-=-=-=-=-= */
+//..  
+//..       case 0x40:
+//..       case 0x41:
+//..       case 0x42: /* CMOVBb/CMOVNAEb (cmov below) */
+//..       case 0x43: /* CMOVNBb/CMOVAEb (cmov not below) */
+//..       case 0x44: /* CMOVZb/CMOVEb (cmov zero) */
+//..       case 0x45: /* CMOVNZb/CMOVNEb (cmov not zero) */
+//..       case 0x46: /* CMOVBEb/CMOVNAb (cmov below or equal) */
+//..       case 0x47: /* CMOVNBEb/CMOVAb (cmov not below or equal) */
+//..       case 0x48: /* CMOVSb (cmov negative) */
+//..       case 0x49: /* CMOVSb (cmov not negative) */
+//..       case 0x4A: /* CMOVP (cmov parity even) */
+//..       case 0x4B: /* CMOVNP (cmov parity odd) */
+//..       case 0x4C: /* CMOVLb/CMOVNGEb (cmov less) */
+//..       case 0x4D: /* CMOVGEb/CMOVNLb (cmov greater or equal) */
+//..       case 0x4E: /* CMOVLEb/CMOVNGb (cmov less or equal) */
+//..       case 0x4F: /* CMOVGb/CMOVNLEb (cmov greater) */
+//..          delta = dis_cmov_E_G(sorb, sz, (X86Condcode)(opc - 0x40), delta);
+//..          break;
+//.. 
+//..       /* =-=-=-=-=-=-=-=-=- CMPXCHG -=-=-=-=-=-=-=-=-=-= */
+//.. 
+//..       case 0xB0: /* CMPXCHG Gb,Eb */
+//..          delta = dis_cmpxchg_G_E ( sorb, 1, delta );
+//..          break;
+//..       case 0xB1: /* CMPXCHG Gv,Ev */
+//..          delta = dis_cmpxchg_G_E ( sorb, sz, delta );
+//..          break;
+//.. //--       case 0xC7: /* CMPXCHG8B Gv */
+//.. //--          eip = dis_cmpxchg8b ( cb, sorb, eip );
+//.. //--          break;
+//.. //-- 
+//..       /* =-=-=-=-=-=-=-=-=- CPUID -=-=-=-=-=-=-=-=-=-=-= */
+//.. 
+//..       case 0xA2: { /* CPUID */
+//..          /* Uses dirty helper: 
+//..                void dirtyhelper_CPUID_sse[012] ( VexGuestX86State* )
+//..             declared to mod eax, wr ebx, ecx, edx
+//..          */
+//..          IRDirty* d     = NULL;
+//..          HChar*   fName = NULL;
+//..          void*    fAddr = NULL;
+//..          switch (subarch) {
+//..             case VexSubArchX86_sse0:
+//..                fName = "x86g_dirtyhelper_CPUID_sse0";
+//..                fAddr = &x86g_dirtyhelper_CPUID_sse0; 
+//..                break;
+//..             case VexSubArchX86_sse1:
+//..                fName = "x86g_dirtyhelper_CPUID_sse1";
+//..                fAddr = &x86g_dirtyhelper_CPUID_sse1; 
+//..                break;
+//..             case VexSubArchX86_sse2:
+//..                fName = "x86g_dirtyhelper_CPUID_sse2";
+//..                fAddr = &x86g_dirtyhelper_CPUID_sse2; 
+//..                break;
+//..             default:
+//..                vpanic("disInstr(x86)(cpuid)");
+//..          }
+//..          vassert(fName); vassert(fAddr);
+//..          d = unsafeIRDirty_0_N ( 0/*regparms*/, 
+//..                                  fName, fAddr, mkIRExprVec_0() );
+//..          /* declare guest state effects */
+//..          d->needsBBP = True;
+//..          d->nFxState = 4;
+//..          d->fxState[0].fx     = Ifx_Modify;
+//..          d->fxState[0].offset = OFFB_EAX;
+//..          d->fxState[0].size   = 4;
+//..          d->fxState[1].fx     = Ifx_Write;
+//..          d->fxState[1].offset = OFFB_EBX;
+//..          d->fxState[1].size   = 4;
+//..          d->fxState[2].fx     = Ifx_Write;
+//..          d->fxState[2].offset = OFFB_ECX;
+//..          d->fxState[2].size   = 4;
+//..          d->fxState[3].fx     = Ifx_Write;
+//..          d->fxState[3].offset = OFFB_EDX;
+//..          d->fxState[3].size   = 4;
+//..          /* execute the dirty call, side-effecting guest state */
+//..          stmt( IRStmt_Dirty(d) );
+//..          /* CPUID is a serialising insn.  So, just in case someone is
+//..             using it as a memory fence ... */
+//..          stmt( IRStmt_MFence() );
+//..          DIP("cpuid\n");
+//..          break;
+//..       }
+//.. 
+//.. //--          if (!VG_(cpu_has_feature)(VG_X86_FEAT_CPUID))
+//.. //--             goto decode_failure;
+//.. //-- 
+//.. //--          t1 = newTemp(cb);
+//.. //--          t2 = newTemp(cb);
+//.. //--          t3 = newTemp(cb);
+//.. //--          t4 = newTemp(cb);
+//.. //--          uInstr0(cb, CALLM_S, 0);
+//.. //-- 
+//.. //--          uInstr2(cb, GET,   4, ArchReg, R_EAX, TempReg, t1);
+//.. //--          uInstr1(cb, PUSH,  4, TempReg, t1);
+//.. //-- 
+//.. //--          uInstr2(cb, MOV,   4, Literal, 0, TempReg, t2);
+//.. //--          uLiteral(cb, 0);
+//.. //--          uInstr1(cb, PUSH,  4, TempReg, t2);
+//.. //-- 
+//.. //--          uInstr2(cb, MOV,   4, Literal, 0, TempReg, t3);
+//.. //--          uLiteral(cb, 0);
+//.. //--          uInstr1(cb, PUSH,  4, TempReg, t3);
+//.. //-- 
+//.. //--          uInstr2(cb, MOV,   4, Literal, 0, TempReg, t4);
+//.. //--          uLiteral(cb, 0);
+//.. //--          uInstr1(cb, PUSH,  4, TempReg, t4);
+//.. //-- 
+//.. //--          uInstr1(cb, CALLM, 0, Lit16,   VGOFF_(helper_CPUID));
+//.. //--          uFlagsRWU(cb, FlagsEmpty, FlagsEmpty, FlagsEmpty);
+//.. //-- 
+//.. //--          uInstr1(cb, POP,   4, TempReg, t4);
+//.. //--          uInstr2(cb, PUT,   4, TempReg, t4, ArchReg, R_EDX);
+//.. //-- 
+//.. //--          uInstr1(cb, POP,   4, TempReg, t3);
+//.. //--          uInstr2(cb, PUT,   4, TempReg, t3, ArchReg, R_ECX);
+//.. //-- 
+//.. //--          uInstr1(cb, POP,   4, TempReg, t2);
+//.. //--          uInstr2(cb, PUT,   4, TempReg, t2, ArchReg, R_EBX);
+//.. //-- 
+//.. //--          uInstr1(cb, POP,   4, TempReg, t1);
+//.. //--          uInstr2(cb, PUT,   4, TempReg, t1, ArchReg, R_EAX);
+//.. //-- 
+//.. //--          uInstr0(cb, CALLM_E, 0);
+//.. //--          DIP("cpuid\n");
+//.. //--          break;
+//.. //-- 
+//..       /* =-=-=-=-=-=-=-=-=- MOVZX, MOVSX =-=-=-=-=-=-=-= */
+//.. 
+//..       case 0xB6: /* MOVZXb Eb,Gv */
+//..          delta = dis_movx_E_G ( sorb, delta, 1, 4, False );
+//..          break;
+//..       case 0xB7: /* MOVZXw Ew,Gv */
+//..          delta = dis_movx_E_G ( sorb, delta, 2, 4, False );
+//..          break;
+//.. 
+//..       case 0xBE: /* MOVSXb Eb,Gv */
+//..          delta = dis_movx_E_G ( sorb, delta, 1, 4, True );
+//..          break;
+//..       case 0xBF: /* MOVSXw Ew,Gv */
+//..          delta = dis_movx_E_G ( sorb, delta, 2, 4, True );
+//..          break;
+//.. 
+//.. //--       /* =-=-=-=-=-=-=-=-=-=-= MOVNTI -=-=-=-=-=-=-=-=-= */
+//.. //-- 
+//.. //--       case 0xC3: /* MOVNTI Gv,Ev */
+//.. //--          vg_assert(sz == 4);
+//.. //--          modrm = getUChar(eip);
+//.. //--          vg_assert(!epartIsReg(modrm));
+//.. //--          t1 = newTemp(cb);
+//.. //--          uInstr2(cb, GET, 4, ArchReg, gregOfRM(modrm), TempReg, t1);
+//.. //--          pair = disAMode ( cb, sorb, eip, dis_buf );
+//.. //--          t2 = LOW24(pair);
+//.. //--          eip += HI8(pair);
+//.. //--          uInstr2(cb, STORE, 4, TempReg, t1, TempReg, t2);
+//.. //--          DIP("movnti %s,%s\n", nameIReg(4,gregOfRM(modrm)), dis_buf);
+//.. //--          break;
+//.. 
+//..       /* =-=-=-=-=-=-=-=-=- MUL/IMUL =-=-=-=-=-=-=-=-=-= */
+//.. 
+//..       case 0xAF: /* IMUL Ev, Gv */
+//..          delta = dis_mul_E_G ( sorb, sz, delta );
+//..          break;
+//.. 
+//..       /* =-=-=-=-=-=-=-=-=- Jcond d32 -=-=-=-=-=-=-=-=-= */
+//..       case 0x80:
+//..       case 0x81:
+//..       case 0x82: /* JBb/JNAEb (jump below) */
+//..       case 0x83: /* JNBb/JAEb (jump not below) */
+//..       case 0x84: /* JZb/JEb (jump zero) */
+//..       case 0x85: /* JNZb/JNEb (jump not zero) */
+//..       case 0x86: /* JBEb/JNAb (jump below or equal) */
+//..       case 0x87: /* JNBEb/JAb (jump not below or equal) */
+//..       case 0x88: /* JSb (jump negative) */
+//..       case 0x89: /* JSb (jump not negative) */
+//..       case 0x8A: /* JP (jump parity even) */
+//..       case 0x8B: /* JNP/JPO (jump parity odd) */
+//..       case 0x8C: /* JLb/JNGEb (jump less) */
+//..       case 0x8D: /* JGEb/JNLb (jump greater or equal) */
+//..       case 0x8E: /* JLEb/JNGb (jump less or equal) */
+//..       case 0x8F: /* JGb/JNLEb (jump greater) */
+//..          d32 = (((Addr32)guest_eip_bbstart)+delta+4) + getUDisp32(delta); 
+//..          delta += 4;
+//..          jcc_01( (X86Condcode)(opc - 0x80), 
+//..                  (Addr32)(guest_eip_bbstart+delta), 
+//..                  d32 );
+//..          whatNext = Dis_StopHere;
+//..          DIP("j%s-32 0x%x\n", name_X86Condcode(opc - 0x80), d32);
+//..          break;
+//.. 
+//..       /* =-=-=-=-=-=-=-=-=- RDTSC -=-=-=-=-=-=-=-=-=-=-= */
+//.. 
+//..       case 0x31: /* RDTSC */
+//..          if (0) vex_printf("vex x86->IR: kludged rdtsc\n");
+//..          putIReg(4, R_EAX, mkU32(0));
+//..          putIReg(4, R_EDX, mkU32(0));
+//.. 
+//.. //--          t1 = newTemp(cb);
+//.. //--          t2 = newTemp(cb);
+//.. //--          t3 = newTemp(cb);
+//.. //--          uInstr0(cb, CALLM_S, 0);
+//.. //--          // Nb: even though these args aren't used by RDTSC_helper, need
+//.. //--          // them to be defined (for Memcheck).  The TempRegs pushed must
+//.. //--          // also be distinct.
+//.. //--          uInstr2(cb, MOV,   4, Literal, 0, TempReg, t1);
+//.. //--          uLiteral(cb, 0);
+//.. //--          uInstr1(cb, PUSH,  4, TempReg, t1);
+//.. //--          uInstr2(cb, MOV,   4, Literal, 0, TempReg, t2);
+//.. //--          uLiteral(cb, 0);
+//.. //--          uInstr1(cb, PUSH,  4, TempReg, t2);
+//.. //--          uInstr1(cb, CALLM, 0, Lit16,   VGOFF_(helper_RDTSC));
+//.. //--          uFlagsRWU(cb, FlagsEmpty, FlagsEmpty, FlagsEmpty);
+//.. //--          uInstr1(cb, POP,   4, TempReg, t3);
+//.. //--          uInstr2(cb, PUT,   4, TempReg, t3, ArchReg, R_EDX);
+//.. //--          uInstr1(cb, POP,   4, TempReg, t3);
+//.. //--          uInstr2(cb, PUT,   4, TempReg, t3, ArchReg, R_EAX);
+//.. //--          uInstr0(cb, CALLM_E, 0);
+//..          DIP("rdtsc\n");
+//..          break;
+//.. 
+//..       /* =-=-=-=-=-=-=-=-=- PUSH/POP Sreg =-=-=-=-=-=-=-=-=-= */
+//.. 
+//..       case 0xA1: /* POP %FS */
+//..          dis_pop_segreg( R_FS, sz ); break;
+//..       case 0xA9: /* POP %GS */
+//..          dis_pop_segreg( R_GS, sz ); break;
+//.. 
+//..       case 0xA0: /* PUSH %FS */
+//..          dis_push_segreg( R_FS, sz ); break;
+//..       case 0xA8: /* PUSH %GS */
+//..          dis_push_segreg( R_GS, sz ); break;
+//.. 
+//..       /* =-=-=-=-=-=-=-=-=- SETcc Eb =-=-=-=-=-=-=-=-=-= */
+//..       case 0x90:
+//..       case 0x91:
+//..       case 0x92: /* set-Bb/set-NAEb (jump below) */
+//..       case 0x93: /* set-NBb/set-AEb (jump not below) */
+//..       case 0x94: /* set-Zb/set-Eb (jump zero) */
+//..       case 0x95: /* set-NZb/set-NEb (jump not zero) */
+//..       case 0x96: /* set-BEb/set-NAb (jump below or equal) */
+//..       case 0x97: /* set-NBEb/set-Ab (jump not below or equal) */
+//..       case 0x98: /* set-Sb (jump negative) */
+//..       case 0x99: /* set-Sb (jump not negative) */
+//..       case 0x9A: /* set-P (jump parity even) */
+//..       case 0x9B: /* set-NP (jump parity odd) */
+//..       case 0x9C: /* set-Lb/set-NGEb (jump less) */
+//..       case 0x9D: /* set-GEb/set-NLb (jump greater or equal) */
+//..       case 0x9E: /* set-LEb/set-NGb (jump less or equal) */
+//..       case 0x9F: /* set-Gb/set-NLEb (jump greater) */
+//..          t1 = newTemp(Ity_I8);
+//..          assign( t1, unop(Iop_1Uto8,mk_x86g_calculate_condition(opc-0x90)) );
+//..          modrm = getIByte(delta);
+//..          if (epartIsReg(modrm)) {
+//..             delta++;
+//..             putIReg(1, eregOfRM(modrm), mkexpr(t1));
+//..             DIP("set%s %s\n", name_X86Condcode(opc-0x90), 
+//..                               nameIReg(1,eregOfRM(modrm)));
+//..          } else {
+//..            addr = disAMode ( &alen, sorb, delta, dis_buf );
+//..            delta += alen;
+//..            storeLE( mkexpr(addr), mkexpr(t1) );
+//..            DIP("set%s %s\n", name_X86Condcode(opc-0x90), dis_buf);
+//..          }
+//..          break;
+//.. 
+//..       /* =-=-=-=-=-=-=-=-=- SHLD/SHRD -=-=-=-=-=-=-=-=-= */
+//.. 
+//..       case 0xA4: /* SHLDv imm8,Gv,Ev */
+//..          modrm = getIByte(delta);
+//..          d32   = delta + lengthAMode(delta);
+//..          vex_sprintf(dis_buf, "$%d", delta);
+//..          delta = dis_SHLRD_Gv_Ev ( 
+//..                   sorb, delta, modrm, sz, 
+//..                   mkU8(getIByte(d32)), True, /* literal */
+//..                   dis_buf, True );
+//..          break;
+//..       case 0xA5: /* SHLDv %cl,Gv,Ev */
+//..          modrm = getIByte(delta);
+//..          delta = dis_SHLRD_Gv_Ev ( 
+//..                     sorb, delta, modrm, sz,
+//..                     getIReg(1,R_ECX), False, /* not literal */
+//..                     "%cl", True );
+//..          break;
+//.. 
+//..       case 0xAC: /* SHRDv imm8,Gv,Ev */
+//..          modrm = getIByte(delta);
+//..          d32   = delta + lengthAMode(delta);
+//..          vex_sprintf(dis_buf, "$%d", delta);
+//..          delta = dis_SHLRD_Gv_Ev ( 
+//..                     sorb, delta, modrm, sz, 
+//..                     mkU8(getIByte(d32)), True, /* literal */
+//..                     dis_buf, False );
+//..          break;
+//..       case 0xAD: /* SHRDv %cl,Gv,Ev */
+//..          modrm = getIByte(delta);
+//..          delta = dis_SHLRD_Gv_Ev ( 
+//..                     sorb, delta, modrm, sz, 
+//..                     getIReg(1,R_ECX), False, /* not literal */
+//..                     "%cl", False );
+//..          break;
+//.. 
+//..       /* =-=-=-=-=-=-=-=-=- XADD -=-=-=-=-=-=-=-=-=-= */
+//.. 
+//.. //--       case 0xC0: /* XADD Gb,Eb */
+//.. //--          eip = dis_xadd_G_E ( cb, sorb, 1, eip );
+//.. //--          break;
+//..       case 0xC1: /* XADD Gv,Ev */
+//..          delta = dis_xadd_G_E ( sorb, sz, delta );
+//..          break;
+//.. 
+//..       /* =-=-=-=-=-=-=-=-=- MMXery =-=-=-=-=-=-=-=-=-=-= */
+//.. 
+//..       case 0x71: 
+//..       case 0x72: 
+//..       case 0x73: /* PSLLgg/PSRAgg/PSRLgg mmxreg by imm8 */
+//.. 
+//..       case 0x6E: /* MOVD (src)ireg-or-mem, (dst)mmxreg */
+//..       case 0x7E: /* MOVD (src)mmxreg, (dst)ireg-or-mem */
+//..       case 0x7F: /* MOVQ (src)mmxreg, (dst)mmxreg-or-mem */
+//..       case 0x6F: /* MOVQ (src)mmxreg-or-mem, (dst)mmxreg */
+//.. 
+//..       case 0xFC: 
+//..       case 0xFD: 
+//..       case 0xFE: /* PADDgg (src)mmxreg-or-mem, (dst)mmxreg */
+//.. 
+//..       case 0xEC: 
+//..       case 0xED: /* PADDSgg (src)mmxreg-or-mem, (dst)mmxreg */
+//.. 
+//..       case 0xDC:
+//..       case 0xDD: /* PADDUSgg (src)mmxreg-or-mem, (dst)mmxreg */
+//.. 
+//..       case 0xF8: 
+//..       case 0xF9: 
+//..       case 0xFA: /* PSUBgg (src)mmxreg-or-mem, (dst)mmxreg */
+//.. 
+//..       case 0xE8: 
+//..       case 0xE9: /* PSUBSgg (src)mmxreg-or-mem, (dst)mmxreg */
+//.. 
+//..       case 0xD8: 
+//..       case 0xD9: /* PSUBUSgg (src)mmxreg-or-mem, (dst)mmxreg */
+//.. 
+//..       case 0xE5: /* PMULHW (src)mmxreg-or-mem, (dst)mmxreg */
+//..       case 0xD5: /* PMULLW (src)mmxreg-or-mem, (dst)mmxreg */
+//.. 
+//..       case 0xF5: /* PMADDWD (src)mmxreg-or-mem, (dst)mmxreg */
+//.. 
+//..       case 0x74: 
+//..       case 0x75: 
+//..       case 0x76: /* PCMPEQgg (src)mmxreg-or-mem, (dst)mmxreg */
+//.. 
+//..       case 0x64: 
+//..       case 0x65: 
+//..       case 0x66: /* PCMPGTgg (src)mmxreg-or-mem, (dst)mmxreg */
+//.. 
+//..       case 0x6B: /* PACKSSDW (src)mmxreg-or-mem, (dst)mmxreg */
+//..       case 0x63: /* PACKSSWB (src)mmxreg-or-mem, (dst)mmxreg */
+//..       case 0x67: /* PACKUSWB (src)mmxreg-or-mem, (dst)mmxreg */
+//.. 
+//..       case 0x68: 
+//..       case 0x69: 
+//..       case 0x6A: /* PUNPCKHgg (src)mmxreg-or-mem, (dst)mmxreg */
+//.. 
+//..       case 0x60: 
+//..       case 0x61: 
+//..       case 0x62: /* PUNPCKLgg (src)mmxreg-or-mem, (dst)mmxreg */
+//.. 
+//..       case 0xDB: /* PAND (src)mmxreg-or-mem, (dst)mmxreg */
+//..       case 0xDF: /* PANDN (src)mmxreg-or-mem, (dst)mmxreg */
+//..       case 0xEB: /* POR (src)mmxreg-or-mem, (dst)mmxreg */
+//..       case 0xEF: /* PXOR (src)mmxreg-or-mem, (dst)mmxreg */
+//.. 
+//..       case 0xF1: /* PSLLgg (src)mmxreg-or-mem, (dst)mmxreg */
+//..       case 0xF2: 
+//..       case 0xF3: 
+//.. 
+//..       case 0xD1: /* PSRLgg (src)mmxreg-or-mem, (dst)mmxreg */
+//..       case 0xD2: 
+//..       case 0xD3: 
+//.. 
+//..       case 0xE1: /* PSRAgg (src)mmxreg-or-mem, (dst)mmxreg */
+//..       case 0xE2: 
+//..       {
+//..          UInt delta0    = delta-1;
+//..          Bool decode_OK = False;
+//.. 
+//..          /* If sz==2 this is SSE, and we assume sse idec has
+//..             already spotted those cases by now. */
+//..          if (sz != 4)
+//..             goto decode_failure;
+//.. 
+//..          delta = dis_MMX ( &decode_OK, sorb, sz, delta-1 );
+//..          if (!decode_OK) {
+//..             delta = delta0;
+//..             goto decode_failure;
+//..          }
+//..          break;
+//..       }
+//.. 
+//..       case 0x77: /* EMMS */
+//..          if (sz != 4)
+//..             goto decode_failure;
+//..          do_EMMS_preamble();
+//..          DIP("emms\n");
+//..          break;
+//.. 
+//..       /* =-=-=-=-=-=-=-=-=- unimp2 =-=-=-=-=-=-=-=-=-=-= */
+//.. 
+//..       default:
+//..          goto decode_failure;
+//..    } /* switch (opc) for the 2-byte opcodes */
+//..    goto decode_success;
+//..    } /* case 0x0F: of primary opcode */
+//.. 
+//..    /* ------------------------ ??? ------------------------ */
+//..   
+//..   default:
+//..   decode_failure:
+//..    /* All decode failures end up here. */
+//..    vex_printf("vex x86->IR: unhandled instruction bytes: "
+//..               "0x%x 0x%x 0x%x 0x%x\n",
+//..               (Int)getIByte(delta_start+0),
+//..               (Int)getIByte(delta_start+1),
+//..               (Int)getIByte(delta_start+2),
+//..               (Int)getIByte(delta_start+3) );
+//.. 
+//..    /* Tell the dispatcher that this insn cannot be decoded, and so has
+//..       not been executed, and (is currently) the next to be executed.
+//..       EIP should be up-to-date since it made so at the start of each
+//..       insn, but nevertheless be paranoid and update it again right
+//..       now. */
+//..    stmt( IRStmt_Put( OFFB_EIP, mkU32(guest_eip_curr_instr) ) );
+//..    jmp_lit(Ijk_NoDecode, guest_eip_curr_instr);
+//..    whatNext = Dis_StopHere;
+//..    *size = 0;
+//..    return whatNext;
+//.. 
+//..    } /* switch (opc) for the main (primary) opcode switch. */
+//.. 
+//..   decode_success:
+//..    /* All decode successes end up here. */
+//..    DIP("\n");
+//.. 
+//..    *size = delta - delta_start;
+//..    return whatNext;
+//.. }
+//.. 
+//.. #undef DIP
+//.. #undef DIS
+
+/*--------------------------------------------------------------------*/
+/*--- end                                       guest-amd64/toIR.c ---*/
+/*--------------------------------------------------------------------*/