]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Get the PPC32 back-end show on the road.
authorCerion Armour-Brown <cerion@valgrind.org>
Fri, 4 Feb 2005 16:17:07 +0000 (16:17 +0000)
committerCerion Armour-Brown <cerion@valgrind.org>
Fri, 4 Feb 2005 16:17:07 +0000 (16:17 +0000)
git-svn-id: svn://svn.valgrind.org/vex/trunk@837

VEX/Makefile
VEX/Makefile-icc
VEX/priv/host-ppc32/hdefs.c [new file with mode: 0644]
VEX/priv/host-ppc32/hdefs.h [new file with mode: 0644]
VEX/priv/host-ppc32/isel.c [new file with mode: 0644]

index 634469c112f91bffadaac4f089a69d9fa747f90b..38ecee237413e1cb54472c8b9c909294163b4c04 100644 (file)
@@ -12,6 +12,7 @@ PUB_HEADERS =         pub/libvex_basictypes.h                 \
 PRIV_HEADERS =         priv/host-x86/hdefs.h                   \
                priv/host-amd64/hdefs.h                 \
                priv/host-arm/hdefs.h                   \
+               priv/host-ppc32/hdefs.h                 \
                priv/host-generic/h_generic_regs.h      \
                priv/host-generic/h_generic_simd64.h    \
                priv/main/vex_globals.h                 \
@@ -32,9 +33,11 @@ LIB_OBJS =   priv/ir/irdefs.o                        \
                priv/host-x86/hdefs.o                   \
                priv/host-amd64/hdefs.o                 \
                priv/host-arm/hdefs.o                   \
+               priv/host-ppc32/hdefs.o                 \
                priv/host-x86/isel.o                    \
                priv/host-amd64/isel.o                  \
                priv/host-arm/isel.o                    \
+               priv/host-ppc32/isel.o                  \
                priv/host-generic/h_generic_regs.o      \
                priv/host-generic/h_generic_simd64.o    \
                priv/host-generic/reg_alloc2.o          \
@@ -148,6 +151,10 @@ priv/host-arm/hdefs.o: $(ALL_HEADERS) priv/host-arm/hdefs.c
        $(CC) $(CCFLAGS) $(ALL_INCLUDES) -o priv/host-arm/hdefs.o \
                                         -c priv/host-arm/hdefs.c
 
+priv/host-ppc32/hdefs.o: $(ALL_HEADERS) priv/host-ppc32/hdefs.c
+       $(CC) $(CCFLAGS) $(ALL_INCLUDES) -o priv/host-ppc32/hdefs.o \
+                                        -c priv/host-ppc32/hdefs.c
+
 priv/host-x86/isel.o: $(ALL_HEADERS) priv/host-x86/isel.c
        $(CC) $(CCFLAGS) $(ALL_INCLUDES) -o priv/host-x86/isel.o \
                                         -c priv/host-x86/isel.c
@@ -160,6 +167,10 @@ priv/host-arm/isel.o: $(ALL_HEADERS) priv/host-arm/isel.c
        $(CC) $(CCFLAGS) $(ALL_INCLUDES) -o priv/host-arm/isel.o \
                                         -c priv/host-arm/isel.c
 
+priv/host-ppc32/isel.o: $(ALL_HEADERS) priv/host-ppc32/isel.c
+       $(CC) $(CCFLAGS) $(ALL_INCLUDES) -o priv/host-ppc32/isel.o \
+                                        -c priv/host-ppc32/isel.c
+
 priv/host-generic/h_generic_regs.o: $(ALL_HEADERS) priv/host-generic/h_generic_regs.c
        $(CC) $(CCFLAGS) $(ALL_INCLUDES) -o priv/host-generic/h_generic_regs.o \
                                         -c priv/host-generic/h_generic_regs.c
index 5595b9dc8d1bb21717590fc13fcd9c139af3a218..8280234b0473024de56fb37a608e96d309b787d7 100644 (file)
@@ -12,6 +12,7 @@ PUB_HEADERS =         pub/libvex_basictypes.h                 \
 PRIV_HEADERS =         priv/host-x86/hdefs.h                   \
                priv/host-amd64/hdefs.h                 \
                priv/host-arm/hdefs.h                   \
+               priv/host-ppc32/hdefs.h                 \
                priv/host-generic/h_generic_regs.h      \
                priv/host-generic/h_generic_simd64.h    \
                priv/main/vex_globals.h                 \
@@ -32,9 +33,11 @@ LIB_OBJS =   priv/ir/irdefs.o                        \
                priv/host-x86/hdefs.o                   \
                priv/host-amd64/hdefs.o                 \
                priv/host-arm/hdefs.o                   \
+               priv/host-ppc32/hdefs.o                 \
                priv/host-x86/isel.o                    \
                priv/host-amd64/isel.o                  \
                priv/host-arm/isel.o                    \
+               priv/host-ppc32/isel.o                  \
                priv/host-generic/h_generic_regs.o      \
                priv/host-generic/h_generic_simd64.o    \
                priv/host-generic/reg_alloc2.o          \
@@ -148,6 +151,10 @@ priv/host-arm/hdefs.o: $(ALL_HEADERS) priv/host-arm/hdefs.c
        $(CC) $(CCFLAGS) $(ALL_INCLUDES) -o priv/host-arm/hdefs.o \
                                         -c priv/host-arm/hdefs.c
 
+priv/host-ppc32/hdefs.o: $(ALL_HEADERS) priv/host-ppc32/hdefs.c
+       $(CC) $(CCFLAGS) $(ALL_INCLUDES) -o priv/host-ppc32/hdefs.o \
+                                        -c priv/host-ppc32/hdefs.c
+
 priv/host-x86/isel.o: $(ALL_HEADERS) priv/host-x86/isel.c
        $(CC) $(CCFLAGS) $(ALL_INCLUDES) -o priv/host-x86/isel.o \
                                         -c priv/host-x86/isel.c
@@ -160,6 +167,10 @@ priv/host-arm/isel.o: $(ALL_HEADERS) priv/host-arm/isel.c
        $(CC) $(CCFLAGS) $(ALL_INCLUDES) -o priv/host-arm/isel.o \
                                         -c priv/host-arm/isel.c
 
+priv/host-ppc32/isel.o: $(ALL_HEADERS) priv/host-ppc32/isel.c
+       $(CC) $(CCFLAGS) $(ALL_INCLUDES) -o priv/host-ppc32/isel.o \
+                                        -c priv/host-ppc32/isel.c
+
 priv/host-generic/h_generic_regs.o: $(ALL_HEADERS) priv/host-generic/h_generic_regs.c
        $(CC) $(CCFLAGS) $(ALL_INCLUDES) -o priv/host-generic/h_generic_regs.o \
                                         -c priv/host-generic/h_generic_regs.c
diff --git a/VEX/priv/host-ppc32/hdefs.c b/VEX/priv/host-ppc32/hdefs.c
new file mode 100644 (file)
index 0000000..f100f61
--- /dev/null
@@ -0,0 +1,2862 @@
+
+/*---------------------------------------------------------------*/
+/*---                                                         ---*/
+/*--- This file (host-ppc32/hdefs.c) 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) 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.
+*/
+
+#include "libvex_basictypes.h"
+#include "libvex.h"
+#include "libvex_trc_values.h"
+
+#include "main/vex_util.h"
+#include "host-generic/h_generic_regs.h"
+#include "host-ppc32/hdefs.h"
+
+
+/* --------- Registers. --------- */
+
+void ppHRegPPC32 ( HReg reg ) 
+{ vassert(0);
+//..    Int r;
+//..    static HChar* ireg32_names[8] 
+//..      = { "%eax", "%ecx", "%edx", "%ebx", "%esp", "%ebp", "%esi", "%edi" };
+//..    /* Be generic for all virtual regs. */
+//..    if (hregIsVirtual(reg)) {
+//..       ppHReg(reg);
+//..       return;
+//..    }
+//..    /* But specific for real regs. */
+//..    switch (hregClass(reg)) {
+//..       case HRcInt32:
+//..          r = hregNumber(reg);
+//..          vassert(r >= 0 && r < 8);
+//..          vex_printf("%s", ireg32_names[r]);
+//..          return;
+//..       case HRcFlt64:
+//..          r = hregNumber(reg);
+//..          vassert(r >= 0 && r < 6);
+//..          vex_printf("%%fake%d", r);
+//..          return;
+//..       case HRcVec128:
+//..          r = hregNumber(reg);
+//..          vassert(r >= 0 && r < 8);
+//..          vex_printf("%%xmm%d", r);
+//..          return;
+//..       default:
+//..          vpanic("ppHRegX86");
+//..    }
+}
+
+//.. HReg hregX86_EAX ( void ) { return mkHReg(0, HRcInt32, False); }
+//.. HReg hregX86_ECX ( void ) { return mkHReg(1, HRcInt32, False); }
+//.. HReg hregX86_EDX ( void ) { return mkHReg(2, HRcInt32, False); }
+//.. HReg hregX86_EBX ( void ) { return mkHReg(3, HRcInt32, False); }
+//.. HReg hregX86_ESP ( void ) { return mkHReg(4, HRcInt32, False); }
+//.. HReg hregX86_EBP ( void ) { return mkHReg(5, HRcInt32, False); }
+//.. HReg hregX86_ESI ( void ) { return mkHReg(6, HRcInt32, False); }
+//.. HReg hregX86_EDI ( void ) { return mkHReg(7, HRcInt32, False); }
+//.. 
+//.. HReg hregX86_FAKE0 ( void ) { return mkHReg(0, HRcFlt64, False); }
+//.. HReg hregX86_FAKE1 ( void ) { return mkHReg(1, HRcFlt64, False); }
+//.. HReg hregX86_FAKE2 ( void ) { return mkHReg(2, HRcFlt64, False); }
+//.. HReg hregX86_FAKE3 ( void ) { return mkHReg(3, HRcFlt64, False); }
+//.. HReg hregX86_FAKE4 ( void ) { return mkHReg(4, HRcFlt64, False); }
+//.. HReg hregX86_FAKE5 ( void ) { return mkHReg(5, HRcFlt64, False); }
+//.. 
+//.. HReg hregX86_XMM0 ( void ) { return mkHReg(0, HRcVec128, False); }
+//.. HReg hregX86_XMM1 ( void ) { return mkHReg(1, HRcVec128, False); }
+//.. HReg hregX86_XMM2 ( void ) { return mkHReg(2, HRcVec128, False); }
+//.. HReg hregX86_XMM3 ( void ) { return mkHReg(3, HRcVec128, False); }
+//.. HReg hregX86_XMM4 ( void ) { return mkHReg(4, HRcVec128, False); }
+//.. HReg hregX86_XMM5 ( void ) { return mkHReg(5, HRcVec128, False); }
+//.. HReg hregX86_XMM6 ( void ) { return mkHReg(6, HRcVec128, False); }
+//.. HReg hregX86_XMM7 ( void ) { return mkHReg(7, HRcVec128, False); }
+
+
+void getAllocableRegs_PPC32 ( Int* nregs, HReg** arr )
+{ *nregs= 0; *arr=NULL;
+//..    *nregs = 20;
+//..    *arr = LibVEX_Alloc(*nregs * sizeof(HReg));
+//..    (*arr)[0] = hregX86_EAX();
+//..    (*arr)[1] = hregX86_EBX();
+//..    (*arr)[2] = hregX86_ECX();
+//..    (*arr)[3] = hregX86_EDX();
+//..    (*arr)[4] = hregX86_ESI();
+//..    (*arr)[5] = hregX86_EDI();
+//..    (*arr)[6] = hregX86_FAKE0();
+//..    (*arr)[7] = hregX86_FAKE1();
+//..    (*arr)[8] = hregX86_FAKE2();
+//..    (*arr)[9] = hregX86_FAKE3();
+//..    (*arr)[10] = hregX86_FAKE4();
+//..    (*arr)[11] = hregX86_FAKE5();
+//..    (*arr)[12] = hregX86_XMM0();
+//..    (*arr)[13] = hregX86_XMM1();
+//..    (*arr)[14] = hregX86_XMM2();
+//..    (*arr)[15] = hregX86_XMM3();
+//..    (*arr)[16] = hregX86_XMM4();
+//..    (*arr)[17] = hregX86_XMM5();
+//..    (*arr)[18] = hregX86_XMM6();
+//..    (*arr)[19] = hregX86_XMM7();
+}
+
+
+//.. /* --------- Condition codes, Intel encoding. --------- */
+//.. 
+//.. HChar* showX86CondCode ( X86CondCode cond )
+//.. {
+//..    switch (cond) {
+//..       case Xcc_O:      return "o";
+//..       case Xcc_NO:     return "no";
+//..       case Xcc_B:      return "b";
+//..       case Xcc_NB:     return "nb";
+//..       case Xcc_Z:      return "z";
+//..       case Xcc_NZ:     return "nz";
+//..       case Xcc_BE:     return "be";
+//..       case Xcc_NBE:    return "nbe";
+//..       case Xcc_S:      return "s";
+//..       case Xcc_NS:     return "ns";
+//..       case Xcc_P:      return "p";
+//..       case Xcc_NP:     return "np";
+//..       case Xcc_L:      return "l";
+//..       case Xcc_NL:     return "nl";
+//..       case Xcc_LE:     return "le";
+//..       case Xcc_NLE:    return "nle";
+//..       case Xcc_ALWAYS: return "ALWAYS";
+//..       default: vpanic("ppX86CondCode");
+//..    }
+//.. }
+//.. 
+//.. 
+//.. /* --------- X86AMode: memory address expressions. --------- */
+//.. 
+//.. X86AMode* X86AMode_IR ( UInt imm32, HReg reg ) {
+//..    X86AMode* am = LibVEX_Alloc(sizeof(X86AMode));
+//..    am->tag = Xam_IR;
+//..    am->Xam.IR.imm = imm32;
+//..    am->Xam.IR.reg = reg;
+//..    return am;
+//.. }
+//.. X86AMode* X86AMode_IRRS ( UInt imm32, HReg base, HReg indEx, Int shift ) {
+//..    X86AMode* am = LibVEX_Alloc(sizeof(X86AMode));
+//..    am->tag = Xam_IRRS;
+//..    am->Xam.IRRS.imm = imm32;
+//..    am->Xam.IRRS.base = base;
+//..    am->Xam.IRRS.index = indEx;
+//..    am->Xam.IRRS.shift = shift;
+//..    vassert(shift >= 0 && shift <= 3);
+//..    return am;
+//.. }
+//.. 
+//.. X86AMode* dopyX86AMode ( X86AMode* am ) {
+//..    switch (am->tag) {
+//..       case Xam_IR: 
+//..          return X86AMode_IR( am->Xam.IR.imm, am->Xam.IR.reg );
+//..       case Xam_IRRS: 
+//..          return X86AMode_IRRS( am->Xam.IRRS.imm, am->Xam.IRRS.base, 
+//..                                am->Xam.IRRS.index, am->Xam.IRRS.shift );
+//..       default:
+//..          vpanic("dopyX86AMode");
+//..    }
+//.. }
+//.. 
+//.. void ppX86AMode ( X86AMode* am ) {
+//..    switch (am->tag) {
+//..       case Xam_IR: 
+//..          if (am->Xam.IR.imm == 0)
+//..             vex_printf("(");
+//..          else
+//..             vex_printf("0x%x(", am->Xam.IR.imm);
+//..          ppHRegX86(am->Xam.IR.reg);
+//..          vex_printf(")");
+//..          return;
+//..       case Xam_IRRS:
+//..          vex_printf("0x%x(", am->Xam.IRRS.imm);
+//..          ppHRegX86(am->Xam.IRRS.base);
+//..          vex_printf(",");
+//..          ppHRegX86(am->Xam.IRRS.index);
+//..          vex_printf(",%d)", 1 << am->Xam.IRRS.shift);
+//..          return;
+//..       default:
+//..          vpanic("ppX86AMode");
+//..    }
+//.. }
+//.. 
+//.. static void addRegUsage_X86AMode ( HRegUsage* u, X86AMode* am ) {
+//..    switch (am->tag) {
+//..       case Xam_IR: 
+//..          addHRegUse(u, HRmRead, am->Xam.IR.reg);
+//..          return;
+//..       case Xam_IRRS:
+//..          addHRegUse(u, HRmRead, am->Xam.IRRS.base);
+//..          addHRegUse(u, HRmRead, am->Xam.IRRS.index);
+//..          return;
+//..       default:
+//..          vpanic("addRegUsage_X86AMode");
+//..    }
+//.. }
+//.. 
+//.. static void mapRegs_X86AMode ( HRegRemap* m, X86AMode* am ) {
+//..    switch (am->tag) {
+//..       case Xam_IR: 
+//..          am->Xam.IR.reg = lookupHRegRemap(m, am->Xam.IR.reg);
+//..          return;
+//..       case Xam_IRRS:
+//..          am->Xam.IRRS.base = lookupHRegRemap(m, am->Xam.IRRS.base);
+//..          am->Xam.IRRS.index = lookupHRegRemap(m, am->Xam.IRRS.index);
+//..          return;
+//..       default:
+//..          vpanic("mapRegs_X86AMode");
+//..    }
+//.. }
+//.. 
+//.. /* --------- Operand, which can be reg, immediate or memory. --------- */
+//.. 
+//.. X86RMI* X86RMI_Imm ( UInt imm32 ) {
+//..    X86RMI* op         = LibVEX_Alloc(sizeof(X86RMI));
+//..    op->tag            = Xrmi_Imm;
+//..    op->Xrmi.Imm.imm32 = imm32;
+//..    return op;
+//.. }
+//.. X86RMI* X86RMI_Reg ( HReg reg ) {
+//..    X86RMI* op       = LibVEX_Alloc(sizeof(X86RMI));
+//..    op->tag          = Xrmi_Reg;
+//..    op->Xrmi.Reg.reg = reg;
+//..    return op;
+//.. }
+//.. X86RMI* X86RMI_Mem ( X86AMode* am ) {
+//..    X86RMI* op      = LibVEX_Alloc(sizeof(X86RMI));
+//..    op->tag         = Xrmi_Mem;
+//..    op->Xrmi.Mem.am = am;
+//..    return op;
+//.. }
+//.. 
+//.. void ppX86RMI ( X86RMI* op ) {
+//..    switch (op->tag) {
+//..       case Xrmi_Imm: 
+//..          vex_printf("$0x%x", op->Xrmi.Imm.imm32);
+//..          return;
+//..       case Xrmi_Reg: 
+//..          ppHRegX86(op->Xrmi.Reg.reg);
+//..          return;
+//..       case Xrmi_Mem: 
+//..          ppX86AMode(op->Xrmi.Mem.am);
+//..          return;
+//..      default: 
+//..          vpanic("ppX86RMI");
+//..    }
+//.. }
+//.. 
+//.. /* An X86RMI can only be used in a "read" context (what would it mean
+//..    to write or modify a literal?) and so we enumerate its registers
+//..    accordingly. */
+//.. static void addRegUsage_X86RMI ( HRegUsage* u, X86RMI* op ) {
+//..    switch (op->tag) {
+//..       case Xrmi_Imm: 
+//..          return;
+//..       case Xrmi_Reg: 
+//..          addHRegUse(u, HRmRead, op->Xrmi.Reg.reg);
+//..          return;
+//..       case Xrmi_Mem: 
+//..          addRegUsage_X86AMode(u, op->Xrmi.Mem.am);
+//..          return;
+//..       default: 
+//..          vpanic("addRegUsage_X86RMI");
+//..    }
+//.. }
+//.. 
+//.. static void mapRegs_X86RMI ( HRegRemap* m, X86RMI* op ) {
+//..    switch (op->tag) {
+//..       case Xrmi_Imm: 
+//..          return;
+//..       case Xrmi_Reg: 
+//..          op->Xrmi.Reg.reg = lookupHRegRemap(m, op->Xrmi.Reg.reg);
+//..          return;
+//..       case Xrmi_Mem: 
+//..          mapRegs_X86AMode(m, op->Xrmi.Mem.am);
+//..          return;
+//..       default: 
+//..          vpanic("mapRegs_X86RMI");
+//..    }
+//.. }
+//.. 
+//.. 
+//.. /* --------- Operand, which can be reg or immediate only. --------- */
+//.. 
+//.. X86RI* X86RI_Imm ( UInt imm32 ) {
+//..    X86RI* op         = LibVEX_Alloc(sizeof(X86RI));
+//..    op->tag           = Xri_Imm;
+//..    op->Xri.Imm.imm32 = imm32;
+//..    return op;
+//.. }
+//.. X86RI* X86RI_Reg ( HReg reg ) {
+//..    X86RI* op       = LibVEX_Alloc(sizeof(X86RI));
+//..    op->tag         = Xri_Reg;
+//..    op->Xri.Reg.reg = reg;
+//..    return op;
+//.. }
+//.. 
+//.. void ppX86RI ( X86RI* op ) {
+//..    switch (op->tag) {
+//..       case Xri_Imm: 
+//..          vex_printf("$0x%x", op->Xri.Imm.imm32);
+//..          return;
+//..       case Xri_Reg: 
+//..          ppHRegX86(op->Xri.Reg.reg);
+//..          return;
+//..      default: 
+//..          vpanic("ppX86RI");
+//..    }
+//.. }
+//.. 
+//.. /* An X86RI can only be used in a "read" context (what would it mean
+//..    to write or modify a literal?) and so we enumerate its registers
+//..    accordingly. */
+//.. static void addRegUsage_X86RI ( HRegUsage* u, X86RI* op ) {
+//..    switch (op->tag) {
+//..       case Xri_Imm: 
+//..          return;
+//..       case Xri_Reg: 
+//..          addHRegUse(u, HRmRead, op->Xri.Reg.reg);
+//..          return;
+//..       default: 
+//..          vpanic("addRegUsage_X86RI");
+//..    }
+//.. }
+//.. 
+//.. static void mapRegs_X86RI ( HRegRemap* m, X86RI* op ) {
+//..    switch (op->tag) {
+//..       case Xri_Imm: 
+//..          return;
+//..       case Xri_Reg: 
+//..          op->Xri.Reg.reg = lookupHRegRemap(m, op->Xri.Reg.reg);
+//..          return;
+//..       default: 
+//..          vpanic("mapRegs_X86RI");
+//..    }
+//.. }
+//.. 
+//.. 
+//.. /* --------- Operand, which can be reg or memory only. --------- */
+//.. 
+//.. X86RM* X86RM_Reg ( HReg reg ) {
+//..    X86RM* op       = LibVEX_Alloc(sizeof(X86RM));
+//..    op->tag         = Xrm_Reg;
+//..    op->Xrm.Reg.reg = reg;
+//..    return op;
+//.. }
+//.. X86RM* X86RM_Mem ( X86AMode* am ) {
+//..    X86RM* op      = LibVEX_Alloc(sizeof(X86RM));
+//..    op->tag        = Xrm_Mem;
+//..    op->Xrm.Mem.am = am;
+//..    return op;
+//.. }
+//.. 
+//.. void ppX86RM ( X86RM* op ) {
+//..    switch (op->tag) {
+//..       case Xrm_Mem: 
+//..          ppX86AMode(op->Xrm.Mem.am);
+//..          return;
+//..       case Xrm_Reg: 
+//..          ppHRegX86(op->Xrm.Reg.reg);
+//..          return;
+//..      default: 
+//..          vpanic("ppX86RM");
+//..    }
+//.. }
+//.. 
+//.. /* Because an X86RM can be both a source or destination operand, we
+//..    have to supply a mode -- pertaining to the operand as a whole --
+//..    indicating how it's being used. */
+//.. static void addRegUsage_X86RM ( HRegUsage* u, X86RM* op, HRegMode mode ) {
+//..    switch (op->tag) {
+//..       case Xrm_Mem: 
+//..          /* Memory is read, written or modified.  So we just want to
+//..             know the regs read by the amode. */
+//..          addRegUsage_X86AMode(u, op->Xrm.Mem.am);
+//..          return;
+//..       case Xrm_Reg: 
+//..          /* reg is read, written or modified.  Add it in the
+//..             appropriate way. */
+//..          addHRegUse(u, mode, op->Xrm.Reg.reg);
+//..          return;
+//..      default: 
+//..          vpanic("addRegUsage_X86RM");
+//..    }
+//.. }
+//.. 
+//.. static void mapRegs_X86RM ( HRegRemap* m, X86RM* op )
+//.. {
+//..    switch (op->tag) {
+//..       case Xrm_Mem: 
+//..          mapRegs_X86AMode(m, op->Xrm.Mem.am);
+//..          return;
+//..       case Xrm_Reg: 
+//..          op->Xrm.Reg.reg = lookupHRegRemap(m, op->Xrm.Reg.reg);
+//..          return;
+//..      default: 
+//..          vpanic("mapRegs_X86RM");
+//..    }
+//.. }
+//.. 
+//.. 
+//.. /* --------- Instructions. --------- */
+//.. 
+//.. HChar* showX86ScalarSz ( X86ScalarSz sz ) {
+//..    switch (sz) {
+//..       case Xss_16: return "w";
+//..       case Xss_32: return "l";
+//..       default: vpanic("showX86ScalarSz");
+//..    }
+//.. }
+//.. 
+//.. HChar* showX86UnaryOp ( X86UnaryOp op ) {
+//..    switch (op) {
+//..       case Xun_NOT: return "not";
+//..       case Xun_NEG: return "neg";
+//..       default: vpanic("showX86UnaryOp");
+//..    }
+//.. }
+//.. 
+//.. HChar* showX86AluOp ( X86AluOp op ) {
+//..    switch (op) {
+//..       case Xalu_MOV:  return "mov";
+//..       case Xalu_CMP:  return "cmp";
+//..       case Xalu_ADD:  return "add";
+//..       case Xalu_SUB:  return "sub";
+//..       case Xalu_ADC:  return "adc";
+//..       case Xalu_SBB:  return "sbb";
+//..       case Xalu_AND:  return "and";
+//..       case Xalu_OR:   return "or";
+//..       case Xalu_XOR:  return "xor";
+//..       case Xalu_MUL:  return "mul";
+//..       default: vpanic("showX86AluOp");
+//..    }
+//.. }
+//.. 
+//.. HChar* showX86ShiftOp ( X86ShiftOp op ) {
+//..    switch (op) {
+//..       case Xsh_SHL: return "shl";
+//..       case Xsh_SHR: return "shr";
+//..       case Xsh_SAR: return "sar";
+//..       case Xsh_ROL: return "rol";
+//..       case Xsh_ROR: return "ror";
+//..       default: vpanic("showX86ShiftOp");
+//..    }
+//.. }
+//.. 
+//.. HChar* showX86FpOp ( X86FpOp op ) {
+//..    switch (op) {
+//..       case Xfp_ADD:    return "add";
+//..       case Xfp_SUB:    return "sub";
+//..       case Xfp_MUL:    return "mul";
+//..       case Xfp_DIV:    return "div";
+//..       case Xfp_SCALE:  return "scale";
+//..       case Xfp_ATAN:   return "atan";
+//..       case Xfp_YL2X:   return "yl2x";
+//..       case Xfp_YL2XP1: return "yl2xp1";
+//..       case Xfp_PREM:   return "prem";
+//..       case Xfp_PREM1:  return "prem1";
+//..       case Xfp_SQRT:   return "sqrt";
+//..       case Xfp_ABS:    return "abs";
+//..       case Xfp_NEG:    return "chs";
+//..       case Xfp_MOV:    return "mov";
+//..       case Xfp_SIN:    return "sin";
+//..       case Xfp_COS:    return "cos";
+//..       case Xfp_TAN:    return "tan";
+//..       case Xfp_ROUND:  return "round";
+//..       case Xfp_2XM1:   return "2xm1";
+//..       default: vpanic("showX86FpOp");
+//..    }
+//.. }
+//.. 
+//.. HChar* showX86SseOp ( X86SseOp op ) {
+//..    switch (op) {
+//..       case Xsse_MOV:      return "mov(?!)";
+//..       case Xsse_ADDF:     return "add";
+//..       case Xsse_SUBF:     return "sub";
+//..       case Xsse_MULF:     return "mul";
+//..       case Xsse_DIVF:     return "div";
+//..       case Xsse_MAXF:     return "max";
+//..       case Xsse_MINF:     return "min";
+//..       case Xsse_CMPEQF:   return "cmpFeq";
+//..       case Xsse_CMPLTF:   return "cmpFlt";
+//..       case Xsse_CMPLEF:   return "cmpFle";
+//..       case Xsse_CMPUNF:   return "cmpFun";
+//..       case Xsse_RCPF:     return "rcp";
+//..       case Xsse_RSQRTF:   return "rsqrt";
+//..       case Xsse_SQRTF:    return "sqrt";
+//..       case Xsse_AND:      return "and";
+//..       case Xsse_OR:       return "or";
+//..       case Xsse_XOR:      return "xor";
+//..       case Xsse_ANDN:     return "andn";
+//..       case Xsse_ADD8:     return "paddb";
+//..       case Xsse_ADD16:    return "paddw";
+//..       case Xsse_ADD32:    return "paddd";
+//..       case Xsse_ADD64:    return "paddq";
+//..       case Xsse_QADD8U:   return "paddusb";
+//..       case Xsse_QADD16U:  return "paddusw";
+//..       case Xsse_QADD8S:   return "paddsb";
+//..       case Xsse_QADD16S:  return "paddsw";
+//..       case Xsse_SUB8:     return "psubb";
+//..       case Xsse_SUB16:    return "psubw";
+//..       case Xsse_SUB32:    return "psubd";
+//..       case Xsse_SUB64:    return "psubq";
+//..       case Xsse_QSUB8U:   return "psubusb";
+//..       case Xsse_QSUB16U:  return "psubusw";
+//..       case Xsse_QSUB8S:   return "psubsb";
+//..       case Xsse_QSUB16S:  return "psubsw";
+//..       case Xsse_MUL16:    return "pmullw";
+//..       case Xsse_MULHI16U: return "pmulhuw";
+//..       case Xsse_MULHI16S: return "pmulhw";
+//..       case Xsse_AVG8U:    return "pavgb";
+//..       case Xsse_AVG16U:   return "pavgw";
+//..       case Xsse_MAX16S:   return "pmaxw";
+//..       case Xsse_MAX8U:    return "pmaxub";
+//..       case Xsse_MIN16S:   return "pminw";
+//..       case Xsse_MIN8U:    return "pminub";
+//..       case Xsse_CMPEQ8:   return "pcmpeqb";
+//..       case Xsse_CMPEQ16:  return "pcmpeqw";
+//..       case Xsse_CMPEQ32:  return "pcmpeqd";
+//..       case Xsse_CMPGT8S:  return "pcmpgtb";
+//..       case Xsse_CMPGT16S: return "pcmpgtw";
+//..       case Xsse_CMPGT32S: return "pcmpgtd";
+//..       case Xsse_SHL16:    return "psllw";
+//..       case Xsse_SHL32:    return "pslld";
+//..       case Xsse_SHL64:    return "psllq";
+//..       case Xsse_SHR16:    return "psrlw";
+//..       case Xsse_SHR32:    return "psrld";
+//..       case Xsse_SHR64:    return "psrlq";
+//..       case Xsse_SAR16:    return "psraw";
+//..       case Xsse_SAR32:    return "psrad";
+//..       case Xsse_PACKSSD:  return "packssdw";
+//..       case Xsse_PACKSSW:  return "packsswb";
+//..       case Xsse_PACKUSW:  return "packuswb";
+//..       case Xsse_UNPCKHB:  return "punpckhb";
+//..       case Xsse_UNPCKHW:  return "punpckhw";
+//..       case Xsse_UNPCKHD:  return "punpckhd";
+//..       case Xsse_UNPCKHQ:  return "punpckhq";
+//..       case Xsse_UNPCKLB:  return "punpcklb";
+//..       case Xsse_UNPCKLW:  return "punpcklw";
+//..       case Xsse_UNPCKLD:  return "punpckld";
+//..       case Xsse_UNPCKLQ:  return "punpcklq";
+//..       default: vpanic("showX86SseOp");
+//..    }
+//.. }
+//.. 
+//.. X86Instr* X86Instr_Alu32R ( X86AluOp op, X86RMI* src, HReg dst ) {
+//..    X86Instr* i       = LibVEX_Alloc(sizeof(X86Instr));
+//..    i->tag            = Xin_Alu32R;
+//..    i->Xin.Alu32R.op  = op;
+//..    i->Xin.Alu32R.src = src;
+//..    i->Xin.Alu32R.dst = dst;
+//..    return i;
+//.. }
+//.. X86Instr* X86Instr_Alu32M ( X86AluOp op, X86RI* src, X86AMode* dst ) {
+//..    X86Instr* i       = LibVEX_Alloc(sizeof(X86Instr));
+//..    i->tag            = Xin_Alu32M;
+//..    i->Xin.Alu32M.op  = op;
+//..    i->Xin.Alu32M.src = src;
+//..    i->Xin.Alu32M.dst = dst;
+//..    vassert(op != Xalu_MUL);
+//..    return i;
+//.. }
+//.. X86Instr* X86Instr_Sh32 ( X86ShiftOp op, UInt src, X86RM* dst ) {
+//..    X86Instr* i     = LibVEX_Alloc(sizeof(X86Instr));
+//..    i->tag          = Xin_Sh32;
+//..    i->Xin.Sh32.op  = op;
+//..    i->Xin.Sh32.src = src;
+//..    i->Xin.Sh32.dst = dst;
+//..    return i;
+//.. }
+//.. X86Instr* X86Instr_Test32  ( X86RI* src, X86RM* dst ) {
+//..    X86Instr* i       = LibVEX_Alloc(sizeof(X86Instr));
+//..    i->tag            = Xin_Test32;
+//..    i->Xin.Test32.src = src;
+//..    i->Xin.Test32.dst = dst;
+//..    return i;
+//.. }
+//.. X86Instr* X86Instr_Unary32  ( X86UnaryOp op, X86RM* dst ) {
+//..    X86Instr* i        = LibVEX_Alloc(sizeof(X86Instr));
+//..    i->tag             = Xin_Unary32;
+//..    i->Xin.Unary32.op  = op;
+//..    i->Xin.Unary32.dst = dst;
+//..    return i;
+//.. }
+//.. X86Instr* X86Instr_MulL ( Bool syned, X86ScalarSz ssz , X86RM* src ) {
+//..    X86Instr* i        = LibVEX_Alloc(sizeof(X86Instr));
+//..    i->tag             = Xin_MulL;
+//..    i->Xin.MulL.syned  = syned;
+//..    i->Xin.MulL.ssz    = ssz;
+//..    i->Xin.MulL.src    = src;
+//..    return i;
+//.. }
+//.. X86Instr* X86Instr_Div ( Bool syned, X86ScalarSz ssz, X86RM* src ) {
+//..    X86Instr* i        = LibVEX_Alloc(sizeof(X86Instr));
+//..    i->tag             = Xin_Div;
+//..    i->Xin.Div.syned   = syned;
+//..    i->Xin.Div.ssz     = ssz;
+//..    i->Xin.Div.src     = src;
+//..    return i;
+//.. }
+//.. X86Instr* X86Instr_Sh3232  ( X86ShiftOp op, UInt amt, HReg src, HReg dst ) {
+//..    X86Instr* i       = LibVEX_Alloc(sizeof(X86Instr));
+//..    i->tag            = Xin_Sh3232;
+//..    i->Xin.Sh3232.op  = op;
+//..    i->Xin.Sh3232.amt = amt;
+//..    i->Xin.Sh3232.src = src;
+//..    i->Xin.Sh3232.dst = dst;
+//..    vassert(op == Xsh_SHL || op == Xsh_SHR);
+//..    return i;
+//.. }
+//.. X86Instr* X86Instr_Push( X86RMI* src ) {
+//..    X86Instr* i     = LibVEX_Alloc(sizeof(X86Instr));
+//..    i->tag          = Xin_Push;
+//..    i->Xin.Push.src = src;
+//..    return i;
+//.. }
+//.. X86Instr* X86Instr_Call ( X86CondCode cond, Addr32 target, Int regparms ) {
+//..    X86Instr* i          = LibVEX_Alloc(sizeof(X86Instr));
+//..    i->tag               = Xin_Call;
+//..    i->Xin.Call.cond     = cond;
+//..    i->Xin.Call.target   = target;
+//..    i->Xin.Call.regparms = regparms;
+//..    vassert(regparms >= 0 && regparms <= 3);
+//..    return i;
+//.. }
+//.. X86Instr* X86Instr_Goto ( IRJumpKind jk, X86CondCode cond, X86RI* dst ) {
+//..    X86Instr* i      = LibVEX_Alloc(sizeof(X86Instr));
+//..    i->tag           = Xin_Goto;
+//..    i->Xin.Goto.cond = cond;
+//..    i->Xin.Goto.dst  = dst;
+//..    i->Xin.Goto.jk   = jk;
+//..    return i;
+//.. }
+//.. X86Instr* X86Instr_CMov32  ( X86CondCode cond, X86RM* src, HReg dst ) {
+//..    X86Instr* i        = LibVEX_Alloc(sizeof(X86Instr));
+//..    i->tag             = Xin_CMov32;
+//..    i->Xin.CMov32.cond = cond;
+//..    i->Xin.CMov32.src  = src;
+//..    i->Xin.CMov32.dst  = dst;
+//..    vassert(cond != Xcc_ALWAYS);
+//..    return i;
+//.. }
+//.. X86Instr* X86Instr_LoadEX ( UChar szSmall, Bool syned,
+//..                             X86AMode* src, HReg dst ) {
+//..    X86Instr* i           = LibVEX_Alloc(sizeof(X86Instr));
+//..    i->tag                = Xin_LoadEX;
+//..    i->Xin.LoadEX.szSmall = szSmall;
+//..    i->Xin.LoadEX.syned   = syned;
+//..    i->Xin.LoadEX.src     = src;
+//..    i->Xin.LoadEX.dst     = dst;
+//..    vassert(szSmall == 1 || szSmall == 2);
+//..    return i;
+//.. }
+//.. X86Instr* X86Instr_Store ( UChar sz, HReg src, X86AMode* dst ) {
+//..    X86Instr* i      = LibVEX_Alloc(sizeof(X86Instr));
+//..    i->tag           = Xin_Store;
+//..    i->Xin.Store.sz  = sz;
+//..    i->Xin.Store.src = src;
+//..    i->Xin.Store.dst = dst;
+//..    vassert(sz == 1 || sz == 2);
+//..    return i;
+//.. }
+//.. X86Instr* X86Instr_Set32 ( X86CondCode cond, HReg dst ) {
+//..    X86Instr* i       = LibVEX_Alloc(sizeof(X86Instr));
+//..    i->tag            = Xin_Set32;
+//..    i->Xin.Set32.cond = cond;
+//..    i->Xin.Set32.dst  = dst;
+//..    return i;
+//.. }
+//.. X86Instr* X86Instr_Bsfr32 ( Bool isFwds, HReg src, HReg dst ) {
+//..    X86Instr* i          = LibVEX_Alloc(sizeof(X86Instr));
+//..    i->tag               = Xin_Bsfr32;
+//..    i->Xin.Bsfr32.isFwds = isFwds;
+//..    i->Xin.Bsfr32.src    = src;
+//..    i->Xin.Bsfr32.dst    = dst;
+//..    return i;
+//.. }
+//.. X86Instr* X86Instr_MFence ( VexSubArch subarch )
+//.. {
+//..    X86Instr* i           = LibVEX_Alloc(sizeof(X86Instr));
+//..    i->tag                = Xin_MFence;
+//..    i->Xin.MFence.subarch = subarch;
+//..    vassert(subarch == VexSubArchX86_sse0
+//..            || subarch == VexSubArchX86_sse1
+//..            || subarch == VexSubArchX86_sse2);
+//..    return i;
+//.. }
+//.. 
+//.. X86Instr* X86Instr_FpUnary ( X86FpOp op, HReg src, HReg dst ) {
+//..    X86Instr* i        = LibVEX_Alloc(sizeof(X86Instr));
+//..    i->tag             = Xin_FpUnary;
+//..    i->Xin.FpUnary.op  = op;
+//..    i->Xin.FpUnary.src = src;
+//..    i->Xin.FpUnary.dst = dst;
+//..    return i;
+//.. }
+//.. X86Instr* X86Instr_FpBinary ( X86FpOp op, HReg srcL, HReg srcR, HReg dst ) {
+//..    X86Instr* i          = LibVEX_Alloc(sizeof(X86Instr));
+//..    i->tag               = Xin_FpBinary;
+//..    i->Xin.FpBinary.op   = op;
+//..    i->Xin.FpBinary.srcL = srcL;
+//..    i->Xin.FpBinary.srcR = srcR;
+//..    i->Xin.FpBinary.dst  = dst;
+//..    return i;
+//.. }
+//.. X86Instr* X86Instr_FpLdSt ( Bool isLoad, UChar sz, HReg reg, X86AMode* addr ) {
+//..    X86Instr* i          = LibVEX_Alloc(sizeof(X86Instr));
+//..    i->tag               = Xin_FpLdSt;
+//..    i->Xin.FpLdSt.isLoad = isLoad;
+//..    i->Xin.FpLdSt.sz     = sz;
+//..    i->Xin.FpLdSt.reg    = reg;
+//..    i->Xin.FpLdSt.addr   = addr;
+//..    vassert(sz == 4 || sz == 8);
+//..    return i;
+//.. }
+//.. X86Instr* X86Instr_FpLdStI ( Bool isLoad, UChar sz,  
+//..                              HReg reg, X86AMode* addr ) {
+//..    X86Instr* i           = LibVEX_Alloc(sizeof(X86Instr));
+//..    i->tag                = Xin_FpLdStI;
+//..    i->Xin.FpLdStI.isLoad = isLoad;
+//..    i->Xin.FpLdStI.sz     = sz;
+//..    i->Xin.FpLdStI.reg    = reg;
+//..    i->Xin.FpLdStI.addr   = addr;
+//..    vassert(sz == 2 || sz == 4 || sz == 8);
+//..    return i;
+//.. }
+//.. X86Instr* X86Instr_Fp64to32 ( HReg src, HReg dst ) {
+//..    X86Instr* i         = LibVEX_Alloc(sizeof(X86Instr));
+//..    i->tag              = Xin_Fp64to32;
+//..    i->Xin.Fp64to32.src = src;
+//..    i->Xin.Fp64to32.dst = dst;
+//..    return i;
+//.. }
+//.. X86Instr* X86Instr_FpCMov ( X86CondCode cond, HReg src, HReg dst ) {
+//..    X86Instr* i        = LibVEX_Alloc(sizeof(X86Instr));
+//..    i->tag             = Xin_FpCMov;
+//..    i->Xin.FpCMov.cond = cond;
+//..    i->Xin.FpCMov.src  = src;
+//..    i->Xin.FpCMov.dst  = dst;
+//..    vassert(cond != Xcc_ALWAYS);
+//..    return i;
+//.. }
+//.. X86Instr* X86Instr_FpLdStCW ( Bool isLoad, X86AMode* addr ) {
+//..    X86Instr* i            = LibVEX_Alloc(sizeof(X86Instr));
+//..    i->tag                 = Xin_FpLdStCW;
+//..    i->Xin.FpLdStCW.isLoad = isLoad;
+//..    i->Xin.FpLdStCW.addr   = addr;
+//..    return i;
+//.. }
+//.. X86Instr* X86Instr_FpStSW_AX ( void ) {
+//..    X86Instr* i = LibVEX_Alloc(sizeof(X86Instr));
+//..    i->tag      = Xin_FpStSW_AX;
+//..    return i;
+//.. }
+//.. X86Instr* X86Instr_FpCmp ( HReg srcL, HReg srcR, HReg dst ) {
+//..    X86Instr* i       = LibVEX_Alloc(sizeof(X86Instr));
+//..    i->tag            = Xin_FpCmp;
+//..    i->Xin.FpCmp.srcL = srcL;
+//..    i->Xin.FpCmp.srcR = srcR;
+//..    i->Xin.FpCmp.dst  = dst;
+//..    return i;
+//.. }
+//.. 
+//.. X86Instr* X86Instr_SseConst ( UShort con, HReg dst ) {
+//..    X86Instr* i            = LibVEX_Alloc(sizeof(X86Instr));
+//..    i->tag                 = Xin_SseConst;
+//..    i->Xin.SseConst.con    = con;
+//..    i->Xin.SseConst.dst    = dst;
+//..    vassert(hregClass(dst) == HRcVec128);
+//..    return i;
+//.. }
+//.. X86Instr* X86Instr_SseLdSt ( Bool isLoad, HReg reg, X86AMode* addr ) {
+//..    X86Instr* i           = LibVEX_Alloc(sizeof(X86Instr));
+//..    i->tag                = Xin_SseLdSt;
+//..    i->Xin.SseLdSt.isLoad = isLoad;
+//..    i->Xin.SseLdSt.reg    = reg;
+//..    i->Xin.SseLdSt.addr   = addr;
+//..    return i;
+//.. }
+//.. X86Instr* X86Instr_SseLdzLO  ( Int sz, HReg reg, X86AMode* addr )
+//.. {
+//..    X86Instr* i           = LibVEX_Alloc(sizeof(X86Instr));
+//..    i->tag                = Xin_SseLdzLO;
+//..    i->Xin.SseLdzLO.sz    = sz;
+//..    i->Xin.SseLdzLO.reg   = reg;
+//..    i->Xin.SseLdzLO.addr  = addr;
+//..    vassert(sz == 4 || sz == 8);
+//..    return i;
+//.. }
+//.. X86Instr* X86Instr_Sse32Fx4 ( X86SseOp op, HReg src, HReg dst ) {
+//..    X86Instr* i         = LibVEX_Alloc(sizeof(X86Instr));
+//..    i->tag              = Xin_Sse32Fx4;
+//..    i->Xin.Sse32Fx4.op  = op;
+//..    i->Xin.Sse32Fx4.src = src;
+//..    i->Xin.Sse32Fx4.dst = dst;
+//..    vassert(op != Xsse_MOV);
+//..    return i;
+//.. }
+//.. X86Instr* X86Instr_Sse32FLo ( X86SseOp op, HReg src, HReg dst ) {
+//..    X86Instr* i         = LibVEX_Alloc(sizeof(X86Instr));
+//..    i->tag              = Xin_Sse32FLo;
+//..    i->Xin.Sse32FLo.op  = op;
+//..    i->Xin.Sse32FLo.src = src;
+//..    i->Xin.Sse32FLo.dst = dst;
+//..    vassert(op != Xsse_MOV);
+//..    return i;
+//.. }
+//.. X86Instr* X86Instr_Sse64Fx2 ( X86SseOp op, HReg src, HReg dst ) {
+//..    X86Instr* i         = LibVEX_Alloc(sizeof(X86Instr));
+//..    i->tag              = Xin_Sse64Fx2;
+//..    i->Xin.Sse64Fx2.op  = op;
+//..    i->Xin.Sse64Fx2.src = src;
+//..    i->Xin.Sse64Fx2.dst = dst;
+//..    vassert(op != Xsse_MOV);
+//..    return i;
+//.. }
+//.. X86Instr* X86Instr_Sse64FLo ( X86SseOp op, HReg src, HReg dst ) {
+//..    X86Instr* i         = LibVEX_Alloc(sizeof(X86Instr));
+//..    i->tag              = Xin_Sse64FLo;
+//..    i->Xin.Sse64FLo.op  = op;
+//..    i->Xin.Sse64FLo.src = src;
+//..    i->Xin.Sse64FLo.dst = dst;
+//..    vassert(op != Xsse_MOV);
+//..    return i;
+//.. }
+//.. X86Instr* X86Instr_SseReRg ( X86SseOp op, HReg re, HReg rg ) {
+//..    X86Instr* i        = LibVEX_Alloc(sizeof(X86Instr));
+//..    i->tag             = Xin_SseReRg;
+//..    i->Xin.SseReRg.op  = op;
+//..    i->Xin.SseReRg.src = re;
+//..    i->Xin.SseReRg.dst = rg;
+//..    return i;
+//.. }
+//.. X86Instr* X86Instr_SseCMov ( X86CondCode cond, HReg src, HReg dst ) {
+//..    X86Instr* i         = LibVEX_Alloc(sizeof(X86Instr));
+//..    i->tag              = Xin_SseCMov;
+//..    i->Xin.SseCMov.cond = cond;
+//..    i->Xin.SseCMov.src  = src;
+//..    i->Xin.SseCMov.dst  = dst;
+//..    vassert(cond != Xcc_ALWAYS);
+//..    return i;
+//.. }
+//.. X86Instr* X86Instr_SseShuf ( Int order, HReg src, HReg dst ) {
+//..    X86Instr* i          = LibVEX_Alloc(sizeof(X86Instr));
+//..    i->tag               = Xin_SseShuf;
+//..    i->Xin.SseShuf.order = order;
+//..    i->Xin.SseShuf.src   = src;
+//..    i->Xin.SseShuf.dst   = dst;
+//..    vassert(order >= 0 && order <= 0xFF);
+//..    return i;
+//.. }
+
+void ppPPC32Instr ( PPC32Instr* i )
+{
+   switch (i->tag) {
+//..       case Xin_Alu32R:
+//..          vex_printf("%sl ", showX86AluOp(i->Xin.Alu32R.op));
+//..          ppX86RMI(i->Xin.Alu32R.src);
+//..          vex_printf(",");
+//..          ppHRegX86(i->Xin.Alu32R.dst);
+//..          return;
+//..       case Xin_Alu32M:
+//..          vex_printf("%sl ", showX86AluOp(i->Xin.Alu32M.op));
+//..          ppX86RI(i->Xin.Alu32M.src);
+//..          vex_printf(",");
+//..          ppX86AMode(i->Xin.Alu32M.dst);
+//..          return;
+//..       case Xin_Sh32:
+//..          vex_printf("%sl ", showX86ShiftOp(i->Xin.Sh32.op));
+//..          if (i->Xin.Sh32.src == 0)
+//..            vex_printf("%%cl,"); 
+//..          else 
+//..             vex_printf("$%d,", i->Xin.Sh32.src);
+//..          ppX86RM(i->Xin.Sh32.dst);
+//..          return;
+//..       case Xin_Test32:
+//..          vex_printf("testl ");
+//..          ppX86RI(i->Xin.Test32.src);
+//..          vex_printf(",");
+//..          ppX86RM(i->Xin.Test32.dst);
+//..          return;
+//..       case Xin_Unary32:
+//..          vex_printf("%sl ", showX86UnaryOp(i->Xin.Unary32.op));
+//..          ppX86RM(i->Xin.Unary32.dst);
+//..          return;
+//..       case Xin_MulL:
+//..          vex_printf("%cmul%s ",
+//..                     i->Xin.MulL.syned ? 's' : 'u',
+//..                     showX86ScalarSz(i->Xin.MulL.ssz));
+//..          ppX86RM(i->Xin.MulL.src);
+//..          return;
+//..       case Xin_Div:
+//..          vex_printf("%cdiv%s ",
+//..                     i->Xin.Div.syned ? 's' : 'u',
+//..                     showX86ScalarSz(i->Xin.Div.ssz));
+//..          ppX86RM(i->Xin.Div.src);
+//..          return;
+//..       case Xin_Sh3232:
+//..          vex_printf("%sdl ", showX86ShiftOp(i->Xin.Sh3232.op));
+//..          if (i->Xin.Sh3232.amt == 0)
+//..            vex_printf(" %%cl,"); 
+//..          else 
+//..             vex_printf(" $%d,", i->Xin.Sh3232.amt);
+//..          ppHRegX86(i->Xin.Sh3232.src);
+//..          vex_printf(",");
+//..          ppHRegX86(i->Xin.Sh3232.dst);
+//..          return;
+//..       case Xin_Push:
+//..          vex_printf("pushl ");
+//..          ppX86RMI(i->Xin.Push.src);
+//..          return;
+//..       case Xin_Call:
+//..          vex_printf("call%s[%d] ", 
+//..                     i->Xin.Call.cond==Xcc_ALWAYS 
+//..                        ? "" : showX86CondCode(i->Xin.Call.cond), 
+//..                     i->Xin.Call.regparms);
+//..          vex_printf("0x%x", i->Xin.Call.target);
+//..          break;
+//..       case Xin_Goto:
+//..          if (i->Xin.Goto.cond != Xcc_ALWAYS) {
+//..             vex_printf("if (%%eflags.%s) { ", 
+//..                        showX86CondCode(i->Xin.Goto.cond));
+//..    }
+//..          if (i->Xin.Goto.jk != Ijk_Boring) {
+//..             vex_printf("movl $");
+//..             ppIRJumpKind(i->Xin.Goto.jk);
+//..             vex_printf(",%%ebp ; ");
+//..          }
+//..          vex_printf("movl ");
+//..          ppX86RI(i->Xin.Goto.dst);
+//..          vex_printf(",%%eax ; ret");
+//..          if (i->Xin.Goto.cond != Xcc_ALWAYS) {
+//..             vex_printf(" }");
+//..    }
+//..          return;
+//..       case Xin_CMov32:
+//..          vex_printf("cmov%s ", showX86CondCode(i->Xin.CMov32.cond));
+//..          ppX86RM(i->Xin.CMov32.src);
+//..          vex_printf(",");
+//..          ppHRegX86(i->Xin.CMov32.dst);
+//..          return;
+//..       case Xin_LoadEX:
+//..          vex_printf("mov%c%cl ",
+//..                     i->Xin.LoadEX.syned ? 's' : 'z',
+//..                     i->Xin.LoadEX.szSmall==1 ? 'b' : 'w');
+//..          ppX86AMode(i->Xin.LoadEX.src);
+//..          vex_printf(",");
+//..          ppHRegX86(i->Xin.LoadEX.dst);
+//..          return;
+//..       case Xin_Store:
+//..          vex_printf("mov%c ", i->Xin.Store.sz==1 ? 'b' : 'w');
+//..          ppHRegX86(i->Xin.Store.src);
+//..          vex_printf(",");
+//..          ppX86AMode(i->Xin.Store.dst);
+//..          return;
+//..       case Xin_Set32:
+//..          vex_printf("setl%s ", showX86CondCode(i->Xin.Set32.cond));
+//..          ppHRegX86(i->Xin.Set32.dst);
+//..          return;
+//..       case Xin_Bsfr32:
+//..          vex_printf("bs%cl ", i->Xin.Bsfr32.isFwds ? 'f' : 'r');
+//..          ppHRegX86(i->Xin.Bsfr32.src);
+//..          vex_printf(",");
+//..          ppHRegX86(i->Xin.Bsfr32.dst);
+//..          return;
+//..       case Xin_MFence:
+//..          vex_printf("mfence(%s)",
+//..                     LibVEX_ppVexSubArch(i->Xin.MFence.subarch));
+//..          return;
+//..       case Xin_FpUnary:
+//..          vex_printf("g%sD ", showX86FpOp(i->Xin.FpUnary.op));
+//..          ppHRegX86(i->Xin.FpUnary.src);
+//..          vex_printf(",");
+//..          ppHRegX86(i->Xin.FpUnary.dst);
+//..          break;
+//..       case Xin_FpBinary:
+//..          vex_printf("g%sD ", showX86FpOp(i->Xin.FpBinary.op));
+//..          ppHRegX86(i->Xin.FpBinary.srcL);
+//..          vex_printf(",");
+//..          ppHRegX86(i->Xin.FpBinary.srcR);
+//..          vex_printf(",");
+//..          ppHRegX86(i->Xin.FpBinary.dst);
+//..          break;
+//..       case Xin_FpLdSt:
+//..          if (i->Xin.FpLdSt.isLoad) {
+//..             vex_printf("gld%c " , i->Xin.FpLdSt.sz==8 ? 'D' : 'F');
+//..             ppX86AMode(i->Xin.FpLdSt.addr);
+//..             vex_printf(", ");
+//..             ppHRegX86(i->Xin.FpLdSt.reg);
+//..          } else {
+//..             vex_printf("gst%c " , i->Xin.FpLdSt.sz==8 ? 'D' : 'F');
+//..             ppHRegX86(i->Xin.FpLdSt.reg);
+//..             vex_printf(", ");
+//..             ppX86AMode(i->Xin.FpLdSt.addr);
+//..          }
+//..          return;
+//..       case Xin_FpLdStI:
+//..          if (i->Xin.FpLdStI.isLoad) {
+//..             vex_printf("gild%s ", i->Xin.FpLdStI.sz==8 ? "ll" : 
+//..                                   i->Xin.FpLdStI.sz==4 ? "l" : "w");
+//..             ppX86AMode(i->Xin.FpLdStI.addr);
+//..             vex_printf(", ");
+//..             ppHRegX86(i->Xin.FpLdStI.reg);
+//..          } else {
+//..             vex_printf("gist%s ", i->Xin.FpLdStI.sz==8 ? "ll" : 
+//..                                   i->Xin.FpLdStI.sz==4 ? "l" : "w");
+//..             ppHRegX86(i->Xin.FpLdStI.reg);
+//..             vex_printf(", ");
+//..             ppX86AMode(i->Xin.FpLdStI.addr);
+//..          }
+//..          return;
+//..       case Xin_Fp64to32:
+//..          vex_printf("gdtof ");
+//..          ppHRegX86(i->Xin.Fp64to32.src);
+//..          vex_printf(",");
+//..          ppHRegX86(i->Xin.Fp64to32.dst);
+//..          return;
+//..       case Xin_FpCMov:
+//..          vex_printf("gcmov%s ", showX86CondCode(i->Xin.FpCMov.cond));
+//..          ppHRegX86(i->Xin.FpCMov.src);
+//..          vex_printf(",");
+//..          ppHRegX86(i->Xin.FpCMov.dst);
+//..          return;
+//..       case Xin_FpLdStCW:
+//..          vex_printf(i->Xin.FpLdStCW.isLoad ? "fldcw " : "fstcw ");
+//..          ppX86AMode(i->Xin.FpLdStCW.addr);
+//..          return;
+//..       case Xin_FpStSW_AX:
+//..          vex_printf("fstsw %%ax");
+//..          return;
+//..       case Xin_FpCmp:
+//..          vex_printf("gcmp ");
+//..          ppHRegX86(i->Xin.FpCmp.srcL);
+//..          vex_printf(",");
+//..          ppHRegX86(i->Xin.FpCmp.srcR);
+//..          vex_printf(",");
+//..          ppHRegX86(i->Xin.FpCmp.dst);
+//..          break;
+//..       case Xin_SseConst:
+//..          vex_printf("const $0x%04x,", (Int)i->Xin.SseConst.con);
+//..          ppHRegX86(i->Xin.SseConst.dst);
+//..          break;
+//..       case Xin_SseLdSt:
+//..          vex_printf("movups ");
+//..          if (i->Xin.SseLdSt.isLoad) {
+//..             ppX86AMode(i->Xin.SseLdSt.addr);
+//..             vex_printf(",");
+//..             ppHRegX86(i->Xin.SseLdSt.reg);
+//..          } else {
+//..             ppHRegX86(i->Xin.SseLdSt.reg);
+//..             vex_printf(",");
+//..             ppX86AMode(i->Xin.SseLdSt.addr);
+//..          }
+//..          return;
+//..       case Xin_SseLdzLO:
+//..          vex_printf("movs%s ", i->Xin.SseLdzLO.sz==4 ? "s" : "d");
+//..          ppX86AMode(i->Xin.SseLdzLO.addr);
+//..          vex_printf(",");
+//..          ppHRegX86(i->Xin.SseLdzLO.reg);
+//..          return;
+//..       case Xin_Sse32Fx4:
+//..          vex_printf("%sps ", showX86SseOp(i->Xin.Sse32Fx4.op));
+//..          ppHRegX86(i->Xin.Sse32Fx4.src);
+//..          vex_printf(",");
+//..          ppHRegX86(i->Xin.Sse32Fx4.dst);
+//..          return;
+//..       case Xin_Sse32FLo:
+//..          vex_printf("%sss ", showX86SseOp(i->Xin.Sse32FLo.op));
+//..          ppHRegX86(i->Xin.Sse32FLo.src);
+//..          vex_printf(",");
+//..          ppHRegX86(i->Xin.Sse32FLo.dst);
+//..          return;
+//..       case Xin_Sse64Fx2:
+//..          vex_printf("%spd ", showX86SseOp(i->Xin.Sse64Fx2.op));
+//..          ppHRegX86(i->Xin.Sse64Fx2.src);
+//..          vex_printf(",");
+//..          ppHRegX86(i->Xin.Sse64Fx2.dst);
+//..          return;
+//..       case Xin_Sse64FLo:
+//..          vex_printf("%ssd ", showX86SseOp(i->Xin.Sse64FLo.op));
+//..          ppHRegX86(i->Xin.Sse64FLo.src);
+//..          vex_printf(",");
+//..          ppHRegX86(i->Xin.Sse64FLo.dst);
+//..          return;
+//..       case Xin_SseReRg:
+//..          vex_printf("%s ", showX86SseOp(i->Xin.SseReRg.op));
+//..          ppHRegX86(i->Xin.SseReRg.src);
+//..          vex_printf(",");
+//..          ppHRegX86(i->Xin.SseReRg.dst);
+//..          return;
+//..       case Xin_SseCMov:
+//..          vex_printf("cmov%s ", showX86CondCode(i->Xin.SseCMov.cond));
+//..          ppHRegX86(i->Xin.SseCMov.src);
+//..          vex_printf(",");
+//..          ppHRegX86(i->Xin.SseCMov.dst);
+//..          return;
+//..       case Xin_SseShuf:
+//..          vex_printf("pshufd $0x%x,", i->Xin.SseShuf.order);
+//..          ppHRegX86(i->Xin.SseShuf.src);
+//..          vex_printf(",");
+//..          ppHRegX86(i->Xin.SseShuf.dst);
+//..          return;
+
+      default:
+         vpanic("ppPPC32Instr");
+   }
+}
+
+/* --------- Helpers for register allocation. --------- */
+
+void getRegUsage_PPC32Instr ( HRegUsage* u, PPC32Instr* i )
+{
+//   Bool unary;
+   initHRegUsage(u);
+   switch (i->tag) {
+//..       case Xin_Alu32R:
+//..          addRegUsage_X86RMI(u, i->Xin.Alu32R.src);
+//..          if (i->Xin.Alu32R.op == Xalu_MOV) {
+//..             addHRegUse(u, HRmWrite,  i->Xin.Alu32R.dst);
+//..             return;
+//..          }
+//..          if (i->Xin.Alu32R.op == Xalu_CMP) { 
+//..             addHRegUse(u, HRmRead,  i->Xin.Alu32R.dst);
+//..             return;
+//..          }
+//..          addHRegUse(u, HRmModify, i->Xin.Alu32R.dst);
+//..          return;
+//..       case Xin_Alu32M:
+//..          addRegUsage_X86RI(u, i->Xin.Alu32M.src);
+//..          addRegUsage_X86AMode(u, i->Xin.Alu32M.dst);
+//..          return;
+//..       case Xin_Sh32:
+//..          addRegUsage_X86RM(u, i->Xin.Sh32.dst, HRmModify);
+//..          if (i->Xin.Sh32.src == 0)
+//..             addHRegUse(u, HRmRead, hregX86_ECX());
+//..          return;
+//..       case Xin_Test32:
+//..          addRegUsage_X86RI(u, i->Xin.Test32.src);
+//..          addRegUsage_X86RM(u, i->Xin.Test32.dst, HRmRead);
+//..          return;
+//..       case Xin_Unary32:
+//..          addRegUsage_X86RM(u, i->Xin.Unary32.dst, HRmModify);
+//..          return;
+//..       case Xin_MulL:
+//..          addRegUsage_X86RM(u, i->Xin.MulL.src, HRmRead);
+//..          addHRegUse(u, HRmModify, hregX86_EAX());
+//..          addHRegUse(u, HRmWrite, hregX86_EDX());
+//..          return;
+//..       case Xin_Div:
+//..          addRegUsage_X86RM(u, i->Xin.Div.src, HRmRead);
+//..          addHRegUse(u, HRmModify, hregX86_EAX());
+//..          addHRegUse(u, HRmModify, hregX86_EDX());
+//..          return;
+//..       case Xin_Sh3232:
+//..          addHRegUse(u, HRmRead, i->Xin.Sh3232.src);
+//..          addHRegUse(u, HRmModify, i->Xin.Sh3232.dst);
+//..          if (i->Xin.Sh3232.amt == 0)
+//..             addHRegUse(u, HRmRead, hregX86_ECX());
+//..          return;
+//..       case Xin_Push:
+//..          addRegUsage_X86RMI(u, i->Xin.Push.src);
+//..          addHRegUse(u, HRmModify, hregX86_ESP());
+//..          return;
+//..       case Xin_Call:
+//..          /* This is a bit subtle. */
+//..          /* First off, claim it trashes all the callee-saved regs */
+//..          /* which I believe to be %eax,%ecx,%edx. */
+//..          addHRegUse(u, HRmWrite, hregX86_EAX());
+//..          addHRegUse(u, HRmWrite, hregX86_ECX());
+//..          addHRegUse(u, HRmWrite, hregX86_EDX());
+//..          /* Now we have to state any parameter-carrying registers
+//..             which might be read.  This depends on the regparmness. */
+//..          switch (i->Xin.Call.regparms) {
+//..             case 3: addHRegUse(u, HRmRead, hregX86_ECX()); /*fallthru*/
+//..             case 2: addHRegUse(u, HRmRead, hregX86_EDX()); /*fallthru*/
+//..             case 1: addHRegUse(u, HRmRead, hregX86_EAX()); break;
+//..             case 0: break;
+//..             default: vpanic("getRegUsage_X86Instr:Call:regparms");
+//..          }
+//..          /* Finally, there is the issue that the insn trashes a
+//..             register because the literal target address has to be
+//..             loaded into a register.  Fortunately, for the 0/1/2
+//..             regparm case, we can use EAX, EDX and ECX respectively, so
+//..             this does not cause any further damage.  For the 3-regparm
+//..             case, we'll have to choose another register arbitrarily --
+//..             since A, D and C are used for parameters -- and so we might
+//..             as well choose EDI. */
+//..          if (i->Xin.Call.regparms == 3)
+//..             addHRegUse(u, HRmWrite, hregX86_EDI());
+//..          /* Upshot of this is that the assembler really must observe
+//..             the here-stated convention of which register to use as an
+//..             address temporary, depending on the regparmness: 0==EAX,
+//..             1==EDX, 2==ECX, 3==EDI. */
+//..          return;
+//..       case Xin_Goto:
+//..          addRegUsage_X86RI(u, i->Xin.Goto.dst);
+//..          addHRegUse(u, HRmWrite, hregX86_EAX());
+//..          if (i->Xin.Goto.jk != Ijk_Boring)
+//..             addHRegUse(u, HRmWrite, hregX86_EBP());
+//..          return;
+//..       case Xin_CMov32:
+//..          addRegUsage_X86RM(u, i->Xin.CMov32.src, HRmRead);
+//..          addHRegUse(u, HRmModify, i->Xin.CMov32.dst);
+//..          return;
+//..       case Xin_LoadEX:
+//..          addRegUsage_X86AMode(u, i->Xin.LoadEX.src);
+//..          addHRegUse(u, HRmWrite, i->Xin.LoadEX.dst);
+//..          return;
+//..       case Xin_Store:
+//..          addHRegUse(u, HRmRead, i->Xin.Store.src);
+//..          addRegUsage_X86AMode(u, i->Xin.Store.dst);
+//..          return;
+//..       case Xin_Set32:
+//..          addHRegUse(u, HRmWrite, i->Xin.Set32.dst);
+//..          return;
+//..       case Xin_Bsfr32:
+//..          addHRegUse(u, HRmRead, i->Xin.Bsfr32.src);
+//..          addHRegUse(u, HRmWrite, i->Xin.Bsfr32.dst);
+//..          return;
+//..       case Xin_MFence:
+//..          return;
+//..       case Xin_FpUnary:
+//..          addHRegUse(u, HRmRead, i->Xin.FpUnary.src);
+//..          addHRegUse(u, HRmWrite, i->Xin.FpUnary.dst);
+//..          return;
+//..       case Xin_FpBinary:
+//..          addHRegUse(u, HRmRead, i->Xin.FpBinary.srcL);
+//..          addHRegUse(u, HRmRead, i->Xin.FpBinary.srcR);
+//..          addHRegUse(u, HRmWrite, i->Xin.FpBinary.dst);
+//..          return;
+//..       case Xin_FpLdSt:
+//..          addRegUsage_X86AMode(u, i->Xin.FpLdSt.addr);
+//..          addHRegUse(u, i->Xin.FpLdSt.isLoad ? HRmWrite : HRmRead,
+//..                        i->Xin.FpLdSt.reg);
+//..          return;
+//..       case Xin_FpLdStI:
+//..          addRegUsage_X86AMode(u, i->Xin.FpLdStI.addr);
+//..          addHRegUse(u, i->Xin.FpLdStI.isLoad ? HRmWrite : HRmRead,
+//..                        i->Xin.FpLdStI.reg);
+//..          return;
+//..       case Xin_Fp64to32:
+//..          addHRegUse(u, HRmRead,  i->Xin.Fp64to32.src);
+//..          addHRegUse(u, HRmWrite, i->Xin.Fp64to32.dst);
+//..          return;
+//..       case Xin_FpCMov:
+//..          addHRegUse(u, HRmRead,   i->Xin.FpCMov.src);
+//..          addHRegUse(u, HRmModify, i->Xin.FpCMov.dst);
+//..          return;
+//..       case Xin_FpLdStCW:
+//..          addRegUsage_X86AMode(u, i->Xin.FpLdStCW.addr);
+//..          return;
+//..       case Xin_FpStSW_AX:
+//..          addHRegUse(u, HRmWrite, hregX86_EAX());
+//..          return;
+//..       case Xin_FpCmp:
+//..          addHRegUse(u, HRmRead, i->Xin.FpCmp.srcL);
+//..          addHRegUse(u, HRmRead, i->Xin.FpCmp.srcR);
+//..          addHRegUse(u, HRmWrite, i->Xin.FpCmp.dst);
+//..          addHRegUse(u, HRmWrite, hregX86_EAX());
+//..          return;
+//..       case Xin_SseLdSt:
+//..          addRegUsage_X86AMode(u, i->Xin.SseLdSt.addr);
+//..          addHRegUse(u, i->Xin.SseLdSt.isLoad ? HRmWrite : HRmRead,
+//..                        i->Xin.SseLdSt.reg);
+//..          return;
+//..       case Xin_SseLdzLO:
+//..          addRegUsage_X86AMode(u, i->Xin.SseLdzLO.addr);
+//..          addHRegUse(u, HRmWrite, i->Xin.SseLdzLO.reg);
+//..          return;
+//..       case Xin_SseConst:
+//..          addHRegUse(u, HRmWrite, i->Xin.SseConst.dst);
+//..          return;
+//..       case Xin_Sse32Fx4:
+//..          vassert(i->Xin.Sse32Fx4.op != Xsse_MOV);
+//..          unary = i->Xin.Sse32Fx4.op == Xsse_RCPF
+//..                  || i->Xin.Sse32Fx4.op == Xsse_RSQRTF
+//..                  || i->Xin.Sse32Fx4.op == Xsse_SQRTF;
+//..          addHRegUse(u, HRmRead, i->Xin.Sse32Fx4.src);
+//..          addHRegUse(u, unary ? HRmWrite : HRmModify, 
+//..                        i->Xin.Sse32Fx4.dst);
+//..          return;
+//..       case Xin_Sse32FLo:
+//..          vassert(i->Xin.Sse32FLo.op != Xsse_MOV);
+//..          unary = i->Xin.Sse32FLo.op == Xsse_RCPF
+//..                  || i->Xin.Sse32FLo.op == Xsse_RSQRTF
+//..                  || i->Xin.Sse32FLo.op == Xsse_SQRTF;
+//..          addHRegUse(u, HRmRead, i->Xin.Sse32FLo.src);
+//..          addHRegUse(u, unary ? HRmWrite : HRmModify, 
+//..                        i->Xin.Sse32FLo.dst);
+//..          return;
+//..       case Xin_Sse64Fx2:
+//..          vassert(i->Xin.Sse64Fx2.op != Xsse_MOV);
+//..          unary = i->Xin.Sse64Fx2.op == Xsse_RCPF
+//..                  || i->Xin.Sse64Fx2.op == Xsse_RSQRTF
+//..                  || i->Xin.Sse64Fx2.op == Xsse_SQRTF;
+//..          addHRegUse(u, HRmRead, i->Xin.Sse64Fx2.src);
+//..          addHRegUse(u, unary ? HRmWrite : HRmModify, 
+//..                        i->Xin.Sse64Fx2.dst);
+//..          return;
+//..       case Xin_Sse64FLo:
+//..          vassert(i->Xin.Sse64FLo.op != Xsse_MOV);
+//..          unary = i->Xin.Sse64FLo.op == Xsse_RCPF
+//..                  || i->Xin.Sse64FLo.op == Xsse_RSQRTF
+//..                  || i->Xin.Sse64FLo.op == Xsse_SQRTF;
+//..          addHRegUse(u, HRmRead, i->Xin.Sse64FLo.src);
+//..          addHRegUse(u, unary ? HRmWrite : HRmModify, 
+//..                        i->Xin.Sse64FLo.dst);
+//..          return;
+//..       case Xin_SseReRg:
+//..          if (i->Xin.SseReRg.op == Xsse_XOR
+//..              && i->Xin.SseReRg.src == i->Xin.SseReRg.dst) {
+//..             /* reg-alloc needs to understand 'xor r,r' as a write of r */
+//..             /* (as opposed to a rite of passage :-) */
+//..             addHRegUse(u, HRmWrite, i->Xin.SseReRg.dst);
+//..          } else {
+//..             addHRegUse(u, HRmRead, i->Xin.SseReRg.src);
+//..             addHRegUse(u, i->Xin.SseReRg.op == Xsse_MOV 
+//..                              ? HRmWrite : HRmModify, 
+//..                           i->Xin.SseReRg.dst);
+//..          }
+//..          return;
+//..       case Xin_SseCMov:
+//..          addHRegUse(u, HRmRead,   i->Xin.SseCMov.src);
+//..          addHRegUse(u, HRmModify, i->Xin.SseCMov.dst);
+//..          return;
+//..       case Xin_SseShuf:
+//..          addHRegUse(u, HRmRead,  i->Xin.SseShuf.src);
+//..          addHRegUse(u, HRmWrite, i->Xin.SseShuf.dst);
+//..          return;
+      default:
+         ppPPC32Instr(i);
+         vpanic("getRegUsage_PPC32Instr");
+   }
+}
+
+//.. /* local helper */
+//.. static void mapReg(HRegRemap* m, HReg* r)
+//.. {
+//..    *r = lookupHRegRemap(m, *r);
+//.. }
+
+void mapRegs_PPC32Instr (HRegRemap* m, PPC32Instr* i)
+{
+   switch (i->tag) {
+//..       case Xin_Alu32R:
+//..          mapRegs_X86RMI(m, i->Xin.Alu32R.src);
+//..          mapReg(m, &i->Xin.Alu32R.dst);
+//..          return;
+//..       case Xin_Alu32M:
+//..          mapRegs_X86RI(m, i->Xin.Alu32M.src);
+//..          mapRegs_X86AMode(m, i->Xin.Alu32M.dst);
+//..          return;
+//..       case Xin_Sh32:
+//..          mapRegs_X86RM(m, i->Xin.Sh32.dst);
+//..          return;
+//..       case Xin_Test32:
+//..          mapRegs_X86RI(m, i->Xin.Test32.src);
+//..          mapRegs_X86RM(m, i->Xin.Test32.dst);
+//..          return;
+//..       case Xin_Unary32:
+//..          mapRegs_X86RM(m, i->Xin.Unary32.dst);
+//..          return;
+//..       case Xin_MulL:
+//..          mapRegs_X86RM(m, i->Xin.MulL.src);
+//..          return;
+//..       case Xin_Div:
+//..          mapRegs_X86RM(m, i->Xin.Div.src);
+//..          return;
+//..       case Xin_Sh3232:
+//..          mapReg(m, &i->Xin.Sh3232.src);
+//..          mapReg(m, &i->Xin.Sh3232.dst);
+//..          return;
+//..       case Xin_Push:
+//..          mapRegs_X86RMI(m, i->Xin.Push.src);
+//..          return;
+//..       case Xin_Call:
+//..          return;
+//..       case Xin_Goto:
+//..          mapRegs_X86RI(m, i->Xin.Goto.dst);
+//..          return;
+//..       case Xin_CMov32:
+//..          mapRegs_X86RM(m, i->Xin.CMov32.src);
+//..          mapReg(m, &i->Xin.CMov32.dst);
+//..          return;
+//..       case Xin_LoadEX:
+//..          mapRegs_X86AMode(m, i->Xin.LoadEX.src);
+//..          mapReg(m, &i->Xin.LoadEX.dst);
+//..          return;
+//..       case Xin_Store:
+//..          mapReg(m, &i->Xin.Store.src);
+//..          mapRegs_X86AMode(m, i->Xin.Store.dst);
+//..          return;
+//..       case Xin_Set32:
+//..          mapReg(m, &i->Xin.Set32.dst);
+//..          return;
+//..       case Xin_Bsfr32:
+//..          mapReg(m, &i->Xin.Bsfr32.src);
+//..          mapReg(m, &i->Xin.Bsfr32.dst);
+//..          return;
+//..       case Xin_MFence:
+//..          return;
+//..       case Xin_FpUnary:
+//..          mapReg(m, &i->Xin.FpUnary.src);
+//..          mapReg(m, &i->Xin.FpUnary.dst);
+//..          return;
+//..       case Xin_FpBinary:
+//..          mapReg(m, &i->Xin.FpBinary.srcL);
+//..          mapReg(m, &i->Xin.FpBinary.srcR);
+//..          mapReg(m, &i->Xin.FpBinary.dst);
+//..          return;
+//..       case Xin_FpLdSt:
+//..          mapRegs_X86AMode(m, i->Xin.FpLdSt.addr);
+//..          mapReg(m, &i->Xin.FpLdSt.reg);
+//..          return;
+//..       case Xin_FpLdStI:
+//..          mapRegs_X86AMode(m, i->Xin.FpLdStI.addr);
+//..          mapReg(m, &i->Xin.FpLdStI.reg);
+//..          return;
+//..       case Xin_Fp64to32:
+//..          mapReg(m, &i->Xin.Fp64to32.src);
+//..          mapReg(m, &i->Xin.Fp64to32.dst);
+//..          return;
+//..       case Xin_FpCMov:
+//..          mapReg(m, &i->Xin.FpCMov.src);
+//..          mapReg(m, &i->Xin.FpCMov.dst);
+//..          return;
+//..       case Xin_FpLdStCW:
+//..          mapRegs_X86AMode(m, i->Xin.FpLdStCW.addr);
+//..          return;
+//..       case Xin_FpStSW_AX:
+//..          return;
+//..       case Xin_FpCmp:
+//..          mapReg(m, &i->Xin.FpCmp.srcL);
+//..          mapReg(m, &i->Xin.FpCmp.srcR);
+//..          mapReg(m, &i->Xin.FpCmp.dst);
+//..          return;
+//..       case Xin_SseConst:
+//..          mapReg(m, &i->Xin.SseConst.dst);
+//..          return;
+//..       case Xin_SseLdSt:
+//..          mapReg(m, &i->Xin.SseLdSt.reg);
+//..          mapRegs_X86AMode(m, i->Xin.SseLdSt.addr);
+//..          break;
+//..       case Xin_SseLdzLO:
+//..          mapReg(m, &i->Xin.SseLdzLO.reg);
+//..          mapRegs_X86AMode(m, i->Xin.SseLdzLO.addr);
+//..          break;
+//..       case Xin_Sse32Fx4:
+//..          mapReg(m, &i->Xin.Sse32Fx4.src);
+//..          mapReg(m, &i->Xin.Sse32Fx4.dst);
+//..          return;
+//..       case Xin_Sse32FLo:
+//..          mapReg(m, &i->Xin.Sse32FLo.src);
+//..          mapReg(m, &i->Xin.Sse32FLo.dst);
+//..          return;
+//..       case Xin_Sse64Fx2:
+//..          mapReg(m, &i->Xin.Sse64Fx2.src);
+//..          mapReg(m, &i->Xin.Sse64Fx2.dst);
+//..          return;
+//..       case Xin_Sse64FLo:
+//..          mapReg(m, &i->Xin.Sse64FLo.src);
+//..          mapReg(m, &i->Xin.Sse64FLo.dst);
+//..          return;
+//..       case Xin_SseReRg:
+//..          mapReg(m, &i->Xin.SseReRg.src);
+//..          mapReg(m, &i->Xin.SseReRg.dst);
+//..          return;
+//..       case Xin_SseCMov:
+//..          mapReg(m, &i->Xin.SseCMov.src);
+//..          mapReg(m, &i->Xin.SseCMov.dst);
+//..          return;
+//..       case Xin_SseShuf:
+//..          mapReg(m, &i->Xin.SseShuf.src);
+//..          mapReg(m, &i->Xin.SseShuf.dst);
+//..          return;
+      default:
+         ppPPC32Instr(i);
+         vpanic("mapRegs_PPC32Instr");
+   }
+}
+
+/* Figure out if i represents a reg-reg move, and if so assign the
+   source and destination to *src and *dst.  If in doubt say No.  Used
+   by the register allocator to do move coalescing. 
+*/
+Bool isMove_PPC32Instr ( PPC32Instr* i, HReg* src, HReg* dst )
+{
+//..    /* Moves between integer regs */
+//..    if (i->tag == Xin_Alu32R) {
+//..       if (i->Xin.Alu32R.op != Xalu_MOV)
+//..          return False;
+//..       if (i->Xin.Alu32R.src->tag != Xrmi_Reg)
+//..          return False;
+//..       *src = i->Xin.Alu32R.src->Xrmi.Reg.reg;
+//..       *dst = i->Xin.Alu32R.dst;
+//..       return True;
+//..    }
+//..    /* Moves between FP regs */
+//..    if (i->tag == Xin_FpUnary) {
+//..       if (i->Xin.FpUnary.op != Xfp_MOV)
+//..          return False;
+//..       *src = i->Xin.FpUnary.src;
+//..       *dst = i->Xin.FpUnary.dst;
+//..       return True;
+//..    }
+//..    if (i->tag == Xin_SseReRg) {
+//..       if (i->Xin.SseReRg.op != Xsse_MOV)
+//..          return False;
+//..       *src = i->Xin.SseReRg.src;
+//..       *dst = i->Xin.SseReRg.dst;
+//..       return True;
+//..    }
+   return False;
+}
+
+
+/* Generate x86 spill/reload instructions under the direction of the
+   register allocator.  Note it's critical these don't write the
+   condition codes. */
+
+PPC32Instr* genSpill_PPC32 ( HReg rreg, Int offsetB )
+{ vassert(0);
+//..    X86AMode* am;
+//..    vassert(offsetB >= 0);
+//..    vassert(!hregIsVirtual(rreg));
+//..    am = X86AMode_IR(offsetB, hregX86_EBP());
+//.. 
+//..    switch (hregClass(rreg)) {
+//..       case HRcInt32:
+//..          return X86Instr_Alu32M ( Xalu_MOV, X86RI_Reg(rreg), am );
+//..       case HRcFlt64:
+//..          return X86Instr_FpLdSt ( False/*store*/, 8, rreg, am );
+//..       case HRcVec128:
+//..          return X86Instr_SseLdSt ( False/*store*/, rreg, am );
+//..       default: 
+//..          ppHRegClass(hregClass(rreg));
+//..          vpanic("genSpill_X86: unimplemented regclass");
+//..    }
+}
+
+PPC32Instr* genReload_PPC32 ( HReg rreg, Int offsetB )
+{ vassert(0);
+//..    X86AMode* am;
+//..    vassert(offsetB >= 0);
+//..    vassert(!hregIsVirtual(rreg));
+//..    am = X86AMode_IR(offsetB, hregX86_EBP());
+//..    switch (hregClass(rreg)) {
+//..       case HRcInt32:
+//..          return X86Instr_Alu32R ( Xalu_MOV, X86RMI_Mem(am), rreg );
+//..       case HRcFlt64:
+//..          return X86Instr_FpLdSt ( True/*load*/, 8, rreg, am );
+//..       case HRcVec128:
+//..          return X86Instr_SseLdSt ( True/*load*/, rreg, am );
+//..       default: 
+//..          ppHRegClass(hregClass(rreg));
+//..          vpanic("genReload_X86: unimplemented regclass");
+//..    }
+}
+
+
+//.. /* --------- The x86 assembler (bleh.) --------- */
+//.. 
+//.. static UInt iregNo ( HReg r )
+//.. {
+//..    UInt n;
+//..    vassert(hregClass(r) == HRcInt32);
+//..    vassert(!hregIsVirtual(r));
+//..    n = hregNumber(r);
+//..    vassert(n <= 7);
+//..    return n;
+//.. }
+//.. 
+//.. static UInt fregNo ( HReg r )
+//.. {
+//..    UInt n;
+//..    vassert(hregClass(r) == HRcFlt64);
+//..    vassert(!hregIsVirtual(r));
+//..    n = hregNumber(r);
+//..    vassert(n <= 5);
+//..    return n;
+//.. }
+//.. 
+//.. static UInt vregNo ( HReg r )
+//.. {
+//..    UInt n;
+//..    vassert(hregClass(r) == HRcVec128);
+//..    vassert(!hregIsVirtual(r));
+//..    n = hregNumber(r);
+//..    vassert(n <= 7);
+//..    return n;
+//.. }
+//.. 
+//.. static UChar mkModRegRM ( UChar mod, UChar reg, UChar regmem )
+//.. {
+//..    return ((mod & 3) << 6) | ((reg & 7) << 3) | (regmem & 7);
+//.. }
+//.. 
+//.. static UChar mkSIB ( Int shift, Int regindex, Int regbase )
+//.. {
+//..    return ((shift & 3) << 6) | ((regindex & 7) << 3) | (regbase & 7);
+//.. }
+//.. 
+//.. static UChar* emit32 ( UChar* p, UInt w32 )
+//.. {
+//..    *p++ = (w32)       & 0x000000FF;
+//..    *p++ = (w32 >>  8) & 0x000000FF;
+//..    *p++ = (w32 >> 16) & 0x000000FF;
+//..    *p++ = (w32 >> 24) & 0x000000FF;
+//..    return p;
+//.. }
+//.. 
+//.. /* Does a sign-extend of the lowest 8 bits give 
+//..    the original number? */
+//.. static Bool fits8bits ( UInt w32 )
+//.. {
+//..    Int i32 = (Int)w32;
+//..    return i32 == ((i32 << 24) >> 24);
+//.. }
+//.. 
+//.. 
+//.. /* Forming mod-reg-rm bytes and scale-index-base bytes.
+//.. 
+//..      greg,  0(ereg)    |  ereg != ESP && ereg != EBP
+//..                        =  00 greg ereg
+//.. 
+//..      greg,  d8(ereg)   |  ereg != ESP
+//..                        =  01 greg ereg, d8
+//.. 
+//..      greg,  d32(ereg)  |  ereg != ESP
+//..                        =  10 greg ereg, d32
+//.. 
+//..      greg,  d8(%esp)   =  01 greg 100, 0x24, d8
+//.. 
+//..      -----------------------------------------------
+//.. 
+//..      greg,  d8(base,index,scale)  
+//..                |  index != ESP
+//..                =  01 greg 100, scale index base, d8
+//.. 
+//..      greg,  d32(base,index,scale)
+//..                |  index != ESP
+//..                =  10 greg 100, scale index base, d32
+//.. */
+//.. static UChar* doAMode_M ( UChar* p, HReg greg, X86AMode* am ) 
+//.. {
+//..    if (am->tag == Xam_IR) {
+//..       if (am->Xam.IR.imm == 0 
+//..           && am->Xam.IR.reg != hregX86_ESP()
+//..           && am->Xam.IR.reg != hregX86_EBP() ) {
+//..          *p++ = mkModRegRM(0, iregNo(greg), iregNo(am->Xam.IR.reg));
+//..          return p;
+//..       }
+//..       if (fits8bits(am->Xam.IR.imm)
+//..           && am->Xam.IR.reg != hregX86_ESP()) {
+//..          *p++ = mkModRegRM(1, iregNo(greg), iregNo(am->Xam.IR.reg));
+//..          *p++ = am->Xam.IR.imm & 0xFF;
+//..          return p;
+//..       }
+//..       if (am->Xam.IR.reg != hregX86_ESP()) {
+//..          *p++ = mkModRegRM(2, iregNo(greg), iregNo(am->Xam.IR.reg));
+//..          p = emit32(p, am->Xam.IR.imm);
+//..          return p;
+//..       }
+//..       if (am->Xam.IR.reg == hregX86_ESP()
+//..           && fits8bits(am->Xam.IR.imm)) {
+//..    *p++ = mkModRegRM(1, iregNo(greg), 4);
+//..          *p++ = 0x24;
+//..          *p++ = am->Xam.IR.imm & 0xFF;
+//..          return p;
+//..       }
+//..       ppX86AMode(am);
+//..       vpanic("doAMode_M: can't emit amode IR");
+//..       /*NOTREACHED*/
+//..    }
+//..    if (am->tag == Xam_IRRS) {
+//..       if (fits8bits(am->Xam.IRRS.imm)
+//..           && am->Xam.IRRS.index != hregX86_ESP()) {
+//..          *p++ = mkModRegRM(1, iregNo(greg), 4);
+//..          *p++ = mkSIB(am->Xam.IRRS.shift, am->Xam.IRRS.index, 
+//..                                           am->Xam.IRRS.base);
+//..          *p++ = am->Xam.IRRS.imm & 0xFF;
+//..          return p;
+//..       }
+//..       if (am->Xam.IRRS.index != hregX86_ESP()) {
+//..          *p++ = mkModRegRM(2, iregNo(greg), 4);
+//..          *p++ = mkSIB(am->Xam.IRRS.shift, am->Xam.IRRS.index,
+//..                                           am->Xam.IRRS.base);
+//..          p = emit32(p, am->Xam.IRRS.imm);
+//..          return p;
+//..       }
+//..       ppX86AMode(am);
+//..       vpanic("doAMode_M: can't emit amode IRRS");
+//..       /*NOTREACHED*/
+//..    }
+//..    vpanic("doAMode_M: unknown amode");
+//..    /*NOTREACHED*/
+//.. }
+//.. 
+//.. 
+//.. /* Emit a mod-reg-rm byte when the rm bit denotes a reg. */
+//.. static UChar* doAMode_R ( UChar* p, HReg greg, HReg ereg ) 
+//.. {
+//..    *p++ = mkModRegRM(3, iregNo(greg), iregNo(ereg));
+//..    return p;
+//.. }
+//.. 
+//.. 
+//.. /* Emit ffree %st(7) */
+//.. static UChar* do_ffree_st7 ( UChar* p )
+//.. {
+//..    *p++ = 0xDD;
+//..    *p++ = 0xC7;
+//..    return p;
+//.. }
+//.. 
+//.. /* Emit fstp %st(i), 1 <= i <= 7 */
+//.. static UChar* do_fstp_st ( UChar* p, Int i )
+//.. {
+//..    vassert(1 <= i && i <= 7);
+//..    *p++ = 0xDD;
+//..    *p++ = 0xD8+i;
+//..    return p;
+//.. }
+//.. 
+//.. /* Emit fld %st(i), 0 <= i <= 6 */
+//.. static UChar* do_fld_st ( UChar* p, Int i )
+//.. {
+//..    vassert(0 <= i && i <= 6);
+//..    *p++ = 0xD9;
+//..    *p++ = 0xC0+i;
+//..    return p;
+//.. }
+//.. 
+//.. /* Emit f<op> %st(0) */
+//.. static UChar* do_fop1_st ( UChar* p, X86FpOp op )
+//.. {
+//..    switch (op) {
+//..       case Xfp_NEG:    *p++ = 0xD9; *p++ = 0xE0; break;
+//..       case Xfp_ABS:    *p++ = 0xD9; *p++ = 0xE1; break;
+//..       case Xfp_SQRT:   *p++ = 0xD9; *p++ = 0xFA; break;
+//..       case Xfp_ROUND:  *p++ = 0xD9; *p++ = 0xFC; break;
+//..       case Xfp_SIN:    *p++ = 0xD9; *p++ = 0xFE; break;
+//..       case Xfp_COS:    *p++ = 0xD9; *p++ = 0xFF; break;
+//..       case Xfp_2XM1:   *p++ = 0xD9; *p++ = 0xF0; break;
+//..       case Xfp_MOV:    break;
+//..       case Xfp_TAN:    p = do_ffree_st7(p); /* since fptan pushes 1.0 */
+//..                        *p++ = 0xD9; *p++ = 0xF2; /* fptan */
+//..                        *p++ = 0xD9; *p++ = 0xF7; /* fincstp */
+//..                        break;
+//..       default: vpanic("do_fop1_st: unknown op");
+//..    }
+//..    return p;
+//.. }
+//.. 
+//.. /* Emit f<op> %st(i), 1 <= i <= 5 */
+//.. static UChar* do_fop2_st ( UChar* p, X86FpOp op, Int i )
+//.. {
+//.. #  define fake(_n) mkHReg((_n), HRcInt32, False)
+//..    Int subopc;
+//..    switch (op) {
+//..       case Xfp_ADD: subopc = 0; break;
+//..       case Xfp_SUB: subopc = 4; break;
+//..       case Xfp_MUL: subopc = 1; break;
+//..       case Xfp_DIV: subopc = 6; break;
+//..       default: vpanic("do_fop2_st: unknown op");
+//..    }
+//..    *p++ = 0xD8;
+//..    p    = doAMode_R(p, fake(subopc), fake(i));
+//..    return p;
+//.. #  undef fake
+//.. }
+//.. 
+//.. /* Push a 32-bit word on the stack.  The word depends on tags[3:0];
+//.. each byte is either 0x00 or 0xFF depending on the corresponding bit in tags[].
+//.. */
+//.. static UChar* push_word_from_tags ( UChar* p, UShort tags )
+//.. {
+//..    UInt w;
+//..    vassert(0 == (tags & ~0xF));
+//..    if (tags == 0) {
+//..       /* pushl $0x00000000 */
+//..       *p++ = 0x6A;
+//..       *p++ = 0x00;
+//..    }
+//..    else 
+//..    /* pushl $0xFFFFFFFF */
+//..    if (tags == 0xF) {
+//..       *p++ = 0x6A;
+//..       *p++ = 0xFF;
+//..    } else {
+//..       vassert(0); /* awaiting test case */
+//..       w = 0;
+//..       if (tags & 1) w |= 0x000000FF;
+//..       if (tags & 2) w |= 0x0000FF00;
+//..       if (tags & 4) w |= 0x00FF0000;
+//..       if (tags & 8) w |= 0xFF000000;
+//..       *p++ = 0x68;
+//..       p = emit32(p, w);
+//..    }
+//..    return p;
+//.. }
+
+/* Emit an instruction into buf and return the number of bytes used.
+   Note that buf is not the insn's final place, and therefore it is
+   imperative to emit position-independent code. */
+
+Int emit_PPC32Instr ( UChar* buf, Int nbuf, PPC32Instr* i )
+{
+//..    UInt irno, opc, opc_rr, subopc_imm, opc_imma, opc_cl, opc_imm, subopc;
+//.. 
+//..    UInt   xtra;
+   UChar* p = &buf[0];
+//..    UChar* ptmp;
+//..    vassert(nbuf >= 32);
+//.. 
+//..    /* Wrap an integer as a int register, for use assembling
+//..       GrpN insns, in which the greg field is used as a sub-opcode
+//..       and does not really contain a register. */
+//.. #  define fake(_n) mkHReg((_n), HRcInt32, False)
+//.. 
+//..    /* vex_printf("asm  ");ppX86Instr(i); vex_printf("\n"); */
+
+   switch (i->tag) {
+
+//..    case Xin_Alu32R:
+//..       /* Deal specially with MOV */
+//..       if (i->Xin.Alu32R.op == Xalu_MOV) {
+//..          switch (i->Xin.Alu32R.src->tag) {
+//..             case Xrmi_Imm:
+//..                *p++ = 0xB8 + iregNo(i->Xin.Alu32R.dst);
+//..                p = emit32(p, i->Xin.Alu32R.src->Xrmi.Imm.imm32);
+//..                goto done;
+//..             case Xrmi_Reg:
+//..                *p++ = 0x89;
+//..                p = doAMode_R(p, i->Xin.Alu32R.src->Xrmi.Reg.reg,
+//..                                 i->Xin.Alu32R.dst);
+//..                goto done;
+//..             case Xrmi_Mem:
+//..                *p++ = 0x8B;
+//..                p = doAMode_M(p, i->Xin.Alu32R.dst, 
+//..                                 i->Xin.Alu32R.src->Xrmi.Mem.am);
+//..                goto done;
+//..             default:
+//..                goto bad;
+//..          }
+//..       }
+//..       /* MUL */
+//..       if (i->Xin.Alu32R.op == Xalu_MUL) {
+//..          switch (i->Xin.Alu32R.src->tag) {
+//..             case Xrmi_Reg:
+//..                *p++ = 0x0F;
+//..                *p++ = 0xAF;
+//..                p = doAMode_R(p, i->Xin.Alu32R.dst,
+//..                                 i->Xin.Alu32R.src->Xrmi.Reg.reg);
+//..                goto done;
+//..             case Xrmi_Mem:
+//..                *p++ = 0x0F;
+//..                *p++ = 0xAF;
+//..                p = doAMode_M(p, i->Xin.Alu32R.dst,
+//..                                 i->Xin.Alu32R.src->Xrmi.Mem.am);
+//..                goto done;
+//..             case Xrmi_Imm:
+//..                if (fits8bits(i->Xin.Alu32R.src->Xrmi.Imm.imm32)) {
+//..                   *p++ = 0x6B;
+//..                   p = doAMode_R(p, i->Xin.Alu32R.dst, i->Xin.Alu32R.dst);
+//..                   *p++ = 0xFF & i->Xin.Alu32R.src->Xrmi.Imm.imm32;
+//..                } else {
+//..                   *p++ = 0x69;
+//..                   p = doAMode_R(p, i->Xin.Alu32R.dst, i->Xin.Alu32R.dst);
+//..                   p = emit32(p, i->Xin.Alu32R.src->Xrmi.Imm.imm32);
+//..                }
+//..                goto done;
+//..             default:
+//..                goto bad;
+//..          }
+//..       }
+//..       /* ADD/SUB/ADC/SBB/AND/OR/XOR/CMP */
+//..       opc = opc_rr = subopc_imm = opc_imma = 0;
+//..       switch (i->Xin.Alu32R.op) {
+//..          case Xalu_ADC: opc = 0x13; opc_rr = 0x11; 
+//..                         subopc_imm = 2; opc_imma = 0x15; break;
+//..          case Xalu_ADD: opc = 0x03; opc_rr = 0x01; 
+//..                         subopc_imm = 0; opc_imma = 0x05; break;
+//..          case Xalu_SUB: opc = 0x2B; opc_rr = 0x29; 
+//..                         subopc_imm = 5; opc_imma = 0x2D; break;
+//..          case Xalu_SBB: opc = 0x1B; opc_rr = 0x19; 
+//..                         subopc_imm = 3; opc_imma = 0x1D; break;
+//..          case Xalu_AND: opc = 0x23; opc_rr = 0x21; 
+//..                         subopc_imm = 4; opc_imma = 0x25; break;
+//..          case Xalu_XOR: opc = 0x33; opc_rr = 0x31; 
+//..                         subopc_imm = 6; opc_imma = 0x35; break;
+//..          case Xalu_OR:  opc = 0x0B; opc_rr = 0x09; 
+//..                         subopc_imm = 1; opc_imma = 0x0D; break;
+//..          case Xalu_CMP: opc = 0x3B; opc_rr = 0x39; 
+//..                         subopc_imm = 7; opc_imma = 0x3D; break;
+//..          default: goto bad;
+//..       }
+//..       switch (i->Xin.Alu32R.src->tag) {
+//..          case Xrmi_Imm:
+//..             if (i->Xin.Alu32R.dst == hregX86_EAX()
+//..                 && !fits8bits(i->Xin.Alu32R.src->Xrmi.Imm.imm32)) {
+//..                *p++ = opc_imma;
+//..                p = emit32(p, i->Xin.Alu32R.src->Xrmi.Imm.imm32);
+//..             } else
+//..             if (fits8bits(i->Xin.Alu32R.src->Xrmi.Imm.imm32)) {
+//..                *p++ = 0x83; 
+//..                p    = doAMode_R(p, fake(subopc_imm), i->Xin.Alu32R.dst);
+//..                *p++ = 0xFF & i->Xin.Alu32R.src->Xrmi.Imm.imm32;
+//..             } else {
+//..                *p++ = 0x81; 
+//..                p    = doAMode_R(p, fake(subopc_imm), i->Xin.Alu32R.dst);
+//..                p    = emit32(p, i->Xin.Alu32R.src->Xrmi.Imm.imm32);
+//..             }
+//..             goto done;
+//..          case Xrmi_Reg:
+//..             *p++ = opc_rr;
+//..             p = doAMode_R(p, i->Xin.Alu32R.src->Xrmi.Reg.reg,
+//..                              i->Xin.Alu32R.dst);
+//..             goto done;
+//..          case Xrmi_Mem:
+//..             *p++ = opc;
+//..             p = doAMode_M(p, i->Xin.Alu32R.dst,
+//..                              i->Xin.Alu32R.src->Xrmi.Mem.am);
+//..             goto done;
+//..          default: 
+//..             goto bad;
+//..       }
+//..       break;
+//.. 
+//..    case Xin_Alu32M:
+//..       /* Deal specially with MOV */
+//..       if (i->Xin.Alu32M.op == Xalu_MOV) {
+//..          switch (i->Xin.Alu32M.src->tag) {
+//..             case Xri_Reg:
+//..                *p++ = 0x89;
+//..                p = doAMode_M(p, i->Xin.Alu32M.src->Xri.Reg.reg,
+//..                                 i->Xin.Alu32M.dst);
+//..                goto done;
+//..             case Xri_Imm:
+//..                *p++ = 0xC7;
+//..                p = doAMode_M(p, fake(0), i->Xin.Alu32M.dst);
+//..                p = emit32(p, i->Xin.Alu32M.src->Xri.Imm.imm32);
+//..                goto done;
+//..             default: 
+//..                goto bad;
+//..          }
+//..       }
+//..       /* ADD/SUB/ADC/SBB/AND/OR/XOR/CMP.  MUL is not
+//..          allowed here. */
+//..       opc = subopc_imm = opc_imma = 0;
+//..       switch (i->Xin.Alu32M.op) {
+//..          case Xalu_ADD: opc = 0x01; subopc_imm = 0; break;
+//..          case Xalu_SUB: opc = 0x29; subopc_imm = 5; break;
+//..          default: goto bad;
+//..       }
+//..       switch (i->Xin.Alu32M.src->tag) {
+//..          case Xri_Reg:
+//..             *p++ = opc;
+//..             p = doAMode_M(p, i->Xin.Alu32M.src->Xri.Reg.reg,
+//..                              i->Xin.Alu32M.dst);
+//..             goto done;
+//..          case Xri_Imm:
+//..             if (fits8bits(i->Xin.Alu32M.src->Xri.Imm.imm32)) {
+//..                *p++ = 0x83;
+//..                p    = doAMode_M(p, fake(subopc_imm), i->Xin.Alu32M.dst);
+//..                *p++ = 0xFF & i->Xin.Alu32M.src->Xri.Imm.imm32;
+//..                goto done;
+//..             } else {
+//..                *p++ = 0x81;
+//..                p    = doAMode_M(p, fake(subopc_imm), i->Xin.Alu32M.dst);
+//..                p    = emit32(p, i->Xin.Alu32M.src->Xri.Imm.imm32);
+//..                goto done;
+//..             }
+//..          default: 
+//..             goto bad;
+//..       }
+//..       break;
+//.. 
+//..    case Xin_Sh32:
+//..       opc_cl = opc_imm = subopc = 0;
+//..       switch (i->Xin.Sh32.op) {
+//..          case Xsh_SHR: opc_cl = 0xD3; opc_imm = 0xC1; subopc = 5; break;
+//..          case Xsh_SAR: opc_cl = 0xD3; opc_imm = 0xC1; subopc = 7; break;
+//..          case Xsh_SHL: opc_cl = 0xD3; opc_imm = 0xC1; subopc = 4; break;
+//..          default: goto bad;
+//..       }
+//..       if (i->Xin.Sh32.src == 0) {
+//..          *p++ = opc_cl;
+//..          switch (i->Xin.Sh32.dst->tag) {
+//..             case Xrm_Reg:
+//..                p = doAMode_R(p, fake(subopc), 
+//..                                 i->Xin.Sh32.dst->Xrm.Reg.reg);
+//..                goto done;
+//..             default:
+//..                goto bad;
+//..          }
+//..       } else {
+//..          *p++ = opc_imm;
+//..          switch (i->Xin.Sh32.dst->tag) {
+//..             case Xrm_Reg:
+//..                p = doAMode_R(p, fake(subopc), 
+//..                                 i->Xin.Sh32.dst->Xrm.Reg.reg);
+//..                *p++ = (UChar)(i->Xin.Sh32.src);
+//..                goto done;
+//..             default:
+//..                goto bad;
+//..          }
+//..       }
+//..       break;
+//.. 
+//..    case Xin_Test32:
+//..       if (i->Xin.Test32.src->tag == Xri_Imm
+//..           && i->Xin.Test32.dst->tag == Xrm_Reg) {
+//..          /* testl $imm32, %reg */
+//..          *p++ = 0xF7;
+//..          p = doAMode_R(p, fake(0), i->Xin.Test32.dst->Xrm.Reg.reg);
+//..          p = emit32(p, i->Xin.Test32.src->Xri.Imm.imm32);
+//..          goto done;
+//..       }
+//..       break;
+//.. 
+//..    case Xin_Unary32:
+//..       if (i->Xin.Unary32.op == Xun_NOT) {
+//..          *p++ = 0xF7;
+//..          if (i->Xin.Unary32.dst->tag == Xrm_Reg) {
+//..             p = doAMode_R(p, fake(2), i->Xin.Unary32.dst->Xrm.Reg.reg);
+//..             goto done;
+//..          } else {
+//..             goto bad;
+//..          }
+//..       }
+//..       if (i->Xin.Unary32.op == Xun_NEG) {
+//..          *p++ = 0xF7;
+//..          if (i->Xin.Unary32.dst->tag == Xrm_Reg) {
+//..             p = doAMode_R(p, fake(3), i->Xin.Unary32.dst->Xrm.Reg.reg);
+//..             goto done;
+//..          } else {
+//..             goto bad;
+//..          }
+//..       }
+//..       break;
+//.. 
+//..    case Xin_MulL:
+//..       subopc = i->Xin.MulL.syned ? 5 : 4;
+//..       if (i->Xin.MulL.ssz == Xss_32) {
+//..          *p++ = 0xF7;
+//..          switch (i->Xin.MulL.src->tag)  {
+//..             case Xrm_Mem:
+//..                p = doAMode_M(p, fake(subopc),
+//..                                 i->Xin.MulL.src->Xrm.Mem.am);
+//..                goto done;
+//..             case Xrm_Reg:
+//..                p = doAMode_R(p, fake(subopc), 
+//..                                 i->Xin.MulL.src->Xrm.Reg.reg);
+//..                goto done;
+//..             default:
+//..                goto bad;
+//..          }
+//..       }
+//..       break;
+//.. 
+//..    case Xin_Div:
+//..       subopc = i->Xin.Div.syned ? 7 : 6;
+//..       if (i->Xin.Div.ssz == Xss_32) {
+//..          *p++ = 0xF7;
+//..          switch (i->Xin.Div.src->tag)  {
+//..             case Xrm_Mem:
+//..                p = doAMode_M(p, fake(subopc),
+//..                                 i->Xin.Div.src->Xrm.Mem.am);
+//..                goto done;
+//..             case Xrm_Reg:
+//..                p = doAMode_R(p, fake(subopc), 
+//..                                 i->Xin.Div.src->Xrm.Reg.reg);
+//..                goto done;
+//..             default:
+//..                goto bad;
+//..          }
+//..       }
+//..       break;
+//.. 
+//..    case Xin_Sh3232:
+//..       vassert(i->Xin.Sh3232.op == Xsh_SHL || i->Xin.Sh3232.op == Xsh_SHR);
+//..       if (i->Xin.Sh3232.amt == 0) {
+//..          /* shldl/shrdl by %cl */
+//..          *p++ = 0x0F;
+//..          if (i->Xin.Sh3232.op == Xsh_SHL) {
+//..             *p++ = 0xA5;
+//..          } else {
+//..             *p++ = 0xAD;
+//..          }
+//..          p = doAMode_R(p, i->Xin.Sh3232.src, i->Xin.Sh3232.dst);
+//..          goto done;
+//..       }
+//..       break;
+//.. 
+//..    case Xin_Push:
+//..       switch (i->Xin.Push.src->tag) {
+//..          case Xrmi_Mem: 
+//..             *p++ = 0xFF;
+//..             p = doAMode_M(p, fake(6), i->Xin.Push.src->Xrmi.Mem.am);
+//..             goto done;
+//..          case Xrmi_Imm:
+//..             *p++ = 0x68;
+//..             p = emit32(p, i->Xin.Push.src->Xrmi.Imm.imm32);
+//..             goto done;
+//..          case Xrmi_Reg:
+//..             *p++ = 0x50 + iregNo(i->Xin.Push.src->Xrmi.Reg.reg);
+//..             goto done;
+//..         default: 
+//..             goto bad;
+//..       }
+//.. 
+//..    case Xin_Call:
+//..       /* See detailed comment for Xin_Call in getRegUsage_X86Instr above
+//..          for explanation of this. */
+//..       switch (i->Xin.Call.regparms) {
+//..          case 0: irno = iregNo(hregX86_EAX()); break;
+//..          case 1: irno = iregNo(hregX86_EDX()); break;
+//..          case 2: irno = iregNo(hregX86_ECX()); break;
+//..          case 3: irno = iregNo(hregX86_EDI()); break;
+//..          default: vpanic(" emit_X86Instr:call:regparms");
+//..       }
+//..       /* jump over the following two insns if the condition does not
+//..          hold */
+//..       if (i->Xin.Call.cond != Xcc_ALWAYS) {
+//..          *p++ = 0x70 + (0xF & (i->Xin.Call.cond ^ 1));
+//..          *p++ = 0x07; /* 7 bytes in the next two insns */
+//..       }
+//..       /* movl $target, %tmp */
+//..       *p++ = 0xB8 + irno; 
+//..       p = emit32(p, i->Xin.Call.target);
+//..       /* call *%tmp */
+//..       *p++ = 0xFF;
+//..       *p++ = 0xD0 + irno;
+//..       goto done;
+//.. 
+//..    case Xin_Goto:
+//..       /* Use ptmp for backpatching conditional jumps. */
+//..       ptmp = NULL;
+//.. 
+//..       /* First off, if this is conditional, create a conditional
+//..    jump over the rest of it. */
+//..       if (i->Xin.Goto.cond != Xcc_ALWAYS) {
+//..          /* jmp fwds if !condition */
+//..          *p++ = 0x70 + (i->Xin.Goto.cond ^ 1);
+//..          ptmp = p; /* fill in this bit later */
+//..          *p++ = 0; /* # of bytes to jump over; don't know how many yet. */
+//..       }
+//.. 
+//..       /* If a non-boring, set %ebp (the guest state pointer)
+//..          appropriately. */
+//..       /* movl $magic_number, %ebp */
+//..       switch (i->Xin.Goto.jk) {
+//..          case Ijk_ClientReq: 
+//..             *p++ = 0xBD;
+//..             p = emit32(p, VEX_TRC_JMP_CLIENTREQ); break;
+//..          case Ijk_Syscall: 
+//..             *p++ = 0xBD;
+//..             p = emit32(p, VEX_TRC_JMP_SYSCALL); break;
+//..          case Ijk_Yield: 
+//..             *p++ = 0xBD;
+//..             p = emit32(p, VEX_TRC_JMP_YIELD); break;
+//..          case Ijk_EmWarn:
+//..             *p++ = 0xBD;
+//..             p = emit32(p, VEX_TRC_JMP_EMWARN); break;
+//..          case Ijk_MapFail:
+//..             *p++ = 0xBD;
+//..             p = emit32(p, VEX_TRC_JMP_MAPFAIL); break;
+//..          case Ijk_NoDecode:
+//..             *p++ = 0xBD;
+//..             p = emit32(p, VEX_TRC_JMP_NODECODE); break;
+//..          case Ijk_Ret:
+//..    case Ijk_Call:
+//..          case Ijk_Boring:
+//..             break;
+//..          default: 
+//..             ppIRJumpKind(i->Xin.Goto.jk);
+//..             vpanic("emit_X86Instr.Xin_Goto: unknown jump kind");
+//..       }
+//.. 
+//..       /* Get the destination address into %eax */
+//..       if (i->Xin.Goto.dst->tag == Xri_Imm) {
+//..          /* movl $immediate, %eax ; ret */
+//..          *p++ = 0xB8;
+//..          p = emit32(p, i->Xin.Goto.dst->Xri.Imm.imm32);
+//..       } else {
+//..          vassert(i->Xin.Goto.dst->tag == Xri_Reg);
+//..          /* movl %reg, %eax ; ret */
+//..          if (i->Xin.Goto.dst->Xri.Reg.reg != hregX86_EAX()) {
+//..             *p++ = 0x89;
+//..             p = doAMode_R(p, i->Xin.Goto.dst->Xri.Reg.reg, hregX86_EAX());
+//..          }
+//..       }
+//.. 
+//..       /* ret */
+//..       *p++ = 0xC3;
+//.. 
+//..       /* Fix up the conditional jump, if there was one. */
+//..       if (i->Xin.Goto.cond != Xcc_ALWAYS) {
+//..          Int delta = p - ptmp;
+//..    vassert(delta > 0 && delta < 20);
+//..          *ptmp = (UChar)(delta-1);
+//..       }
+//..       goto done;
+//.. 
+//..    case Xin_CMov32:
+//..       vassert(i->Xin.CMov32.cond != Xcc_ALWAYS);
+//.. #if 0
+//..       /* This generates cmov, which is illegal on P54/P55. */
+//..       *p++ = 0x0F;
+//..       *p++ = 0x40 + i->Xin.CMov32.cond;
+//..       if (i->Xin.CMov32.src->tag == Xrm_Reg) {
+//..          p = doAMode_R(p, i->Xin.CMov32.dst, i->Xin.CMov32.src->Xrm.Reg.reg);
+//..          goto done;
+//..       }
+//..       if (i->Xin.CMov32.src->tag == Xrm_Mem) {
+//..          p = doAMode_M(p, i->Xin.CMov32.dst, i->Xin.CMov32.src->Xrm.Mem.am);
+//..          goto done;
+//..       }
+//.. #else
+//..       /* P5 friendly version: conditional jump over an unconditional
+//..          move. */
+//..       /* jmp fwds if !condition */
+//..       *p++ = 0x70 + (i->Xin.CMov32.cond ^ 1);
+//..       *p++ = 0; /* # of bytes in the next bit, which we don't know yet */
+//..       ptmp = p;
+//.. 
+//..       switch (i->Xin.CMov32.src->tag) {
+//..          case Xrm_Reg:
+//..             /* Big sigh.  This is movl E -> G ... */
+//..             *p++ = 0x89;
+//..             p = doAMode_R(p, i->Xin.CMov32.src->Xrm.Reg.reg,
+//..                              i->Xin.CMov32.dst);
+//..                              
+//..             break;
+//..          case Xrm_Mem:
+//..             /* ... whereas this is movl G -> E.  That's why the args
+//..                to doAMode_R appear to be the wrong way round in the
+//..                Xrm_Reg case. */
+//..             *p++ = 0x8B;
+//..             p = doAMode_M(p, i->Xin.CMov32.dst, 
+//..                              i->Xin.CMov32.src->Xrm.Mem.am);
+//..             break;
+//..          default:
+//..             goto bad;
+//..       }
+//..       /* Fill in the jump offset. */
+//..       *(ptmp-1) = p - ptmp;
+//..       goto done;
+//.. #endif
+//..       break;
+//.. 
+//..    case Xin_LoadEX:
+//..       if (i->Xin.LoadEX.szSmall == 1 && !i->Xin.LoadEX.syned) {
+//..          /* movzbl */
+//..          *p++ = 0x0F;
+//..          *p++ = 0xB6;
+//..          p = doAMode_M(p, i->Xin.LoadEX.dst, i->Xin.LoadEX.src); 
+//..          goto done;
+//..       }
+//..       if (i->Xin.LoadEX.szSmall == 2 && !i->Xin.LoadEX.syned) {
+//..          /* movzwl */
+//..          *p++ = 0x0F;
+//..          *p++ = 0xB7;
+//..          p = doAMode_M(p, i->Xin.LoadEX.dst, i->Xin.LoadEX.src); 
+//..          goto done;
+//..       }
+//..       break;
+//.. 
+//..    case Xin_Set32:
+//..       /* Make the destination register be 1 or 0, depending on whether
+//..          the relevant condition holds.  We have to dodge and weave
+//..          when the destination is %esi or %edi as we cannot directly
+//..          emit the native 'setb %reg' for those.  Further complication:
+//..          the top 24 bits of the destination should be forced to zero,
+//..          but doing 'xor %r,%r' kills the flag(s) we are about to read.
+//..          Sigh.  So start off my moving $0 into the dest. */
+//.. 
+//..       /* Do we need to swap in %eax? */
+//..       if (iregNo(i->Xin.Set32.dst) >= 4) {
+//..          /* xchg %eax, %dst */
+//..          *p++ = 0x90 + iregNo(i->Xin.Set32.dst);
+//..          /* movl $0, %eax */
+//..          *p++ = 0xB8 + iregNo(hregX86_EAX());
+//..          p = emit32(p, 0);
+//..          /* setb lo8(%eax) */
+//..          *p++ = 0x0F; 
+//..          *p++ = 0x90 + (UChar)(i->Xin.Set32.cond);
+//..          p = doAMode_R(p, fake(0), hregX86_EAX());
+//..          /* xchg %eax, %dst */
+//..          *p++ = 0x90 + iregNo(i->Xin.Set32.dst);
+//..       } else {
+//..          /* movl $0, %dst */
+//..          *p++ = 0xB8 + iregNo(i->Xin.Set32.dst);
+//..          p = emit32(p, 0);
+//..          /* setb lo8(%dst) */
+//..          *p++ = 0x0F; 
+//..          *p++ = 0x90 + (UChar)(i->Xin.Set32.cond);
+//..          p = doAMode_R(p, fake(0), i->Xin.Set32.dst);
+//..       }
+//..       goto done;
+//.. 
+//..    case Xin_Bsfr32:
+//..       *p++ = 0x0F;
+//..       if (i->Xin.Bsfr32.isFwds) {
+//..          *p++ = 0xBC;
+//..       } else {
+//..          *p++ = 0xBD;
+//..       }
+//..       p = doAMode_R(p, i->Xin.Bsfr32.dst, i->Xin.Bsfr32.src);
+//..       goto done;
+//.. 
+//..    case Xin_MFence:
+//..       /* see comment in hdefs.h re this insn */
+//..       if (0) vex_printf("EMIT FENCE\n");
+//..       switch (i->Xin.MFence.subarch) {
+//..          case VexSubArchX86_sse0:
+//..             vassert(0); /* awaiting test case */
+//..             /* lock addl $0,0(%esp) */
+//..             *p++ = 0xF0; *p++ = 0x83; *p++ = 0x44; 
+//..             *p++ = 0x24; *p++ = 0x00; *p++ = 0x00;
+//..             goto done;
+//..          case VexSubArchX86_sse1:
+//..             /* sfence */
+//..             *p++ = 0x0F; *p++ = 0xAE; *p++ = 0xF8;
+//..             /* lock addl $0,0(%esp) */
+//..             *p++ = 0xF0; *p++ = 0x83; *p++ = 0x44; 
+//..             *p++ = 0x24; *p++ = 0x00; *p++ = 0x00;
+//..             goto done;
+//..          case VexSubArchX86_sse2:
+//..             /* mfence */
+//..             *p++ = 0x0F; *p++ = 0xAE; *p++ = 0xF0;
+//..             goto done;
+//..          default: 
+//..             vpanic("emit_X86Instr:mfence:subarch");
+//..       }
+//..       break;
+//.. 
+//..    case Xin_Store:
+//..       if (i->Xin.Store.sz == 2) {
+//..          /* This case, at least, is simple, given that we can
+//..             reference the low 16 bits of any integer register. */
+//..          *p++ = 0x66;
+//..          *p++ = 0x89;
+//..          p = doAMode_M(p, i->Xin.Store.src, i->Xin.Store.dst);
+//..          goto done;
+//..       }
+//.. 
+//..       if (i->Xin.Store.sz == 1) {
+//..          /* We have to do complex dodging and weaving if src is not
+//..             the low 8 bits of %eax/%ebx/%ecx/%edx. */
+//..          if (iregNo(i->Xin.Store.src) < 4) {
+//..             /* we're OK, can do it directly */
+//..             *p++ = 0x88;
+//..             p = doAMode_M(p, i->Xin.Store.src, i->Xin.Store.dst);
+//..            goto done;
+//..          } else {
+//..             /* Bleh.  This means the source is %edi or %esi.  Since
+//..                the address mode can only mention three registers, at
+//..                least one of %eax/%ebx/%ecx/%edx must be available to
+//..                temporarily swap the source into, so the store can
+//..                happen.  So we have to look at the regs mentioned
+//..                in the amode. */
+//..             HReg swap = INVALID_HREG;
+//..             HReg  eax = hregX86_EAX(), ebx = hregX86_EBX(), 
+//..                   ecx = hregX86_ECX(), edx = hregX86_EDX();
+//..             Bool a_ok = True, b_ok = True, c_ok = True, d_ok = True;
+//..             HRegUsage u;
+//..             Int j;
+//..             initHRegUsage(&u);
+//..             addRegUsage_X86AMode(&u,  i->Xin.Store.dst);
+//..             for (j = 0; j < u.n_used; j++) {
+//..                HReg r = u.hreg[j];
+//..                if (r == eax) a_ok = False;
+//..                if (r == ebx) b_ok = False;
+//..                if (r == ecx) c_ok = False;
+//..                if (r == edx) d_ok = False;
+//..             }
+//..             if (a_ok) swap = eax;
+//..             if (b_ok) swap = ebx;
+//..             if (c_ok) swap = ecx;
+//..             if (d_ok) swap = edx;
+//..             vassert(swap != INVALID_HREG);
+//..             /* xchgl %source, %swap. Could do better if swap is %eax. */
+//..             *p++ = 0x87;
+//..             p = doAMode_R(p, i->Xin.Store.src, swap);
+//..             /* movb lo8{%swap}, (dst) */
+//..             *p++ = 0x88;
+//..             p = doAMode_M(p, swap, i->Xin.Store.dst);
+//..             /* xchgl %source, %swap. Could do better if swap is %eax. */
+//..             *p++ = 0x87;
+//..             p = doAMode_R(p, i->Xin.Store.src, swap);
+//..             goto done;
+//..          }
+//..       } /* if (i->Xin.Store.sz == 1) */
+//..       break;
+//.. 
+//..    case Xin_FpUnary:
+//..       /* gop %src, %dst
+//..          --> ffree %st7 ; fld %st(src) ; fop %st(0) ; fstp %st(1+dst)
+//..       */
+//..       p = do_ffree_st7(p);
+//..       p = do_fld_st(p, 0+hregNumber(i->Xin.FpUnary.src));
+//..       p = do_fop1_st(p, i->Xin.FpUnary.op);
+//..       p = do_fstp_st(p, 1+hregNumber(i->Xin.FpUnary.dst));
+//..       goto done;
+//.. 
+//..    case Xin_FpBinary:
+//..       if (i->Xin.FpBinary.op == Xfp_YL2X
+//..           || i->Xin.FpBinary.op == Xfp_YL2XP1) {
+//..          /* Have to do this specially. */
+//..          /* ffree %st7 ; fld %st(srcL) ; 
+//..             ffree %st7 ; fld %st(srcR+1) ; fyl2x{p1} ; fstp(1+dst) */
+//..          p = do_ffree_st7(p);
+//..          p = do_fld_st(p, 0+hregNumber(i->Xin.FpBinary.srcL));
+//..          p = do_ffree_st7(p);
+//..          p = do_fld_st(p, 1+hregNumber(i->Xin.FpBinary.srcR));
+//..          *p++ = 0xD9; 
+//..          *p++ = i->Xin.FpBinary.op==Xfp_YL2X ? 0xF1 : 0xF9;
+//..          p = do_fstp_st(p, 1+hregNumber(i->Xin.FpBinary.dst));
+//..          goto done;
+//..       }
+//..       if (i->Xin.FpBinary.op == Xfp_ATAN) {
+//..          /* Have to do this specially. */
+//..          /* ffree %st7 ; fld %st(srcL) ; 
+//..             ffree %st7 ; fld %st(srcR+1) ; fpatan ; fstp(1+dst) */
+//..          p = do_ffree_st7(p);
+//..          p = do_fld_st(p, 0+hregNumber(i->Xin.FpBinary.srcL));
+//..          p = do_ffree_st7(p);
+//..          p = do_fld_st(p, 1+hregNumber(i->Xin.FpBinary.srcR));
+//..          *p++ = 0xD9; *p++ = 0xF3;
+//..          p = do_fstp_st(p, 1+hregNumber(i->Xin.FpBinary.dst));
+//..          goto done;
+//..       }
+//..       if (i->Xin.FpBinary.op == Xfp_PREM
+//..           || i->Xin.FpBinary.op == Xfp_PREM1
+//..           || i->Xin.FpBinary.op == Xfp_SCALE) {
+//..          /* Have to do this specially. */
+//..          /* ffree %st7 ; fld %st(srcR) ; 
+//..             ffree %st7 ; fld %st(srcL+1) ; fprem/fprem1/fscale ; fstp(2+dst) ; 
+//..             fincstp ; ffree %st7 */
+//..          p = do_ffree_st7(p);
+//..          p = do_fld_st(p, 0+hregNumber(i->Xin.FpBinary.srcR));
+//..          p = do_ffree_st7(p);
+//..          p = do_fld_st(p, 1+hregNumber(i->Xin.FpBinary.srcL));
+//..          *p++ = 0xD9;
+//..          switch (i->Xin.FpBinary.op) {
+//..             case Xfp_PREM: *p++ = 0xF8; break;
+//..             case Xfp_PREM1: *p++ = 0xF5; break;
+//..             case Xfp_SCALE: *p++ =  0xFD; break;
+//..             default: vpanic("emitX86Instr(FpBinary,PREM/PREM1/SCALE)");
+//..          }
+//..          p = do_fstp_st(p, 2+hregNumber(i->Xin.FpBinary.dst));
+//..          *p++ = 0xD9; *p++ = 0xF7;
+//..          p = do_ffree_st7(p);
+//..          goto done;
+//..       }
+//..       /* General case */
+//..       /* gop %srcL, %srcR, %dst
+//..          --> ffree %st7 ; fld %st(srcL) ; fop %st(1+srcR) ; fstp %st(1+dst)
+//..       */
+//..       p = do_ffree_st7(p);
+//..       p = do_fld_st(p, 0+hregNumber(i->Xin.FpBinary.srcL));
+//..       p = do_fop2_st(p, i->Xin.FpBinary.op, 
+//..                         1+hregNumber(i->Xin.FpBinary.srcR));
+//..       p = do_fstp_st(p, 1+hregNumber(i->Xin.FpBinary.dst));
+//..       goto done;
+//.. 
+//..    case Xin_FpLdSt:
+//..       vassert(i->Xin.FpLdSt.sz == 4 || i->Xin.FpLdSt.sz == 8);
+//..       if (i->Xin.FpLdSt.isLoad) {
+//..          /* Load from memory into %fakeN.  
+//..             --> ffree %st(7) ; fld{s/l} amode ; fstp st(N+1) 
+//..          */
+//..          p = do_ffree_st7(p);
+//..          *p++ = i->Xin.FpLdSt.sz==4 ? 0xD9 : 0xDD;
+//..    p = doAMode_M(p, fake(0)/*subopcode*/, i->Xin.FpLdSt.addr);
+//..          p = do_fstp_st(p, 1+hregNumber(i->Xin.FpLdSt.reg));
+//..          goto done;
+//..       } else {
+//..          /* Store from %fakeN into memory.
+//..             --> ffree %st(7) ; fld st(N) ; fstp{l|s} amode
+//..    */
+//..          p = do_ffree_st7(p);
+//..          p = do_fld_st(p, 0+hregNumber(i->Xin.FpLdSt.reg));
+//..          *p++ = i->Xin.FpLdSt.sz==4 ? 0xD9 : 0xDD;
+//..          p = doAMode_M(p, fake(3)/*subopcode*/, i->Xin.FpLdSt.addr);
+//..          goto done;
+//..       }
+//..       break;
+//.. 
+//..    case Xin_FpLdStI:
+//..       if (i->Xin.FpLdStI.isLoad) {
+//..          /* Load from memory into %fakeN, converting from an int.  
+//..             --> ffree %st(7) ; fild{w/l/ll} amode ; fstp st(N+1) 
+//..          */
+//..          switch (i->Xin.FpLdStI.sz) {
+//..             case 8:  opc = 0xDF; subopc_imm = 5; break;
+//..             case 4:  opc = 0xDB; subopc_imm = 0; break;
+//..             case 2:  vassert(0); opc = 0xDF; subopc_imm = 0; break;
+//..             default: vpanic("emitX86Instr(Xin_FpLdStI-load)");
+//..          }
+//..          p = do_ffree_st7(p);
+//..          *p++ = opc;
+//..          p = doAMode_M(p, fake(subopc_imm)/*subopcode*/, i->Xin.FpLdStI.addr);
+//..          p = do_fstp_st(p, 1+hregNumber(i->Xin.FpLdStI.reg));
+//..          goto done;
+//..       } else {
+//..          /* Store from %fakeN into memory, converting to an int.
+//..             --> ffree %st(7) ; fld st(N) ; fistp{w/l/ll} amode
+//..    */
+//..          switch (i->Xin.FpLdStI.sz) {
+//..             case 8:  opc = 0xDF; subopc_imm = 7; break;
+//..             case 4:  opc = 0xDB; subopc_imm = 3; break;
+//..             case 2:  opc = 0xDF; subopc_imm = 3; break;
+//..             default: vpanic("emitX86Instr(Xin_FpLdStI-store)");
+//..          }
+//..          p = do_ffree_st7(p);
+//..          p = do_fld_st(p, 0+hregNumber(i->Xin.FpLdStI.reg));
+//..          *p++ = opc;
+//..          p = doAMode_M(p, fake(subopc_imm)/*subopcode*/, i->Xin.FpLdStI.addr);
+//..          goto done;
+//..       }
+//..       break;
+//.. 
+//..    case Xin_Fp64to32:
+//..       /* ffree %st7 ; fld %st(src) */
+//..       p = do_ffree_st7(p);
+//..       p = do_fld_st(p, 0+fregNo(i->Xin.Fp64to32.src));
+//..       /* subl $4, %esp */
+//..       *p++ = 0x83; *p++ = 0xEC; *p++ = 0x04;
+//..       /* fstps (%esp) */
+//..       *p++ = 0xD9; *p++ = 0x1C; *p++ = 0x24;
+//..       /* flds (%esp) */
+//..       *p++ = 0xD9; *p++ = 0x04; *p++ = 0x24;
+//..       /* addl $4, %esp */
+//..       *p++ = 0x83; *p++ = 0xC4; *p++ = 0x04;
+//..       /* fstp %st(1+dst) */
+//..       p = do_fstp_st(p, 1+fregNo(i->Xin.Fp64to32.dst));
+//..       goto done;
+//.. 
+//..    case Xin_FpCMov:
+//..       /* jmp fwds if !condition */
+//..       *p++ = 0x70 + (i->Xin.FpCMov.cond ^ 1);
+//..       *p++ = 0; /* # of bytes in the next bit, which we don't know yet */
+//..       ptmp = p;
+//.. 
+//..       /* ffree %st7 ; fld %st(src) ; fstp %st(1+dst) */
+//..       p = do_ffree_st7(p);
+//..       p = do_fld_st(p, 0+fregNo(i->Xin.FpCMov.src));
+//..       p = do_fstp_st(p, 1+fregNo(i->Xin.FpCMov.dst));
+//.. 
+//..       /* Fill in the jump offset. */
+//..       *(ptmp-1) = p - ptmp;
+//..       goto done;
+//.. 
+//..    case Xin_FpLdStCW:
+//..       if (i->Xin.FpLdStCW.isLoad) {
+//..          *p++ = 0xD9;
+//..          p = doAMode_M(p, fake(5)/*subopcode*/, i->Xin.FpLdStCW.addr);
+//..       } else {
+//..          vassert(0);
+//..       }
+//..       goto done;
+//.. 
+//..    case Xin_FpStSW_AX:
+//..       /* note, this emits fnstsw %ax, not fstsw %ax */
+//..       *p++ = 0xDF;
+//..       *p++ = 0xE0;
+//..       goto done;
+//.. 
+//..    case Xin_FpCmp:
+//..       /* gcmp %fL, %fR, %dst
+//..          -> ffree %st7; fpush %fL ; fucomp %(fR+1) ; 
+//..             fnstsw %ax ; movl %eax, %dst 
+//..       */
+//..       /* ffree %st7 */
+//..       p = do_ffree_st7(p);
+//..       /* fpush %fL */
+//..       p = do_fld_st(p, 0+fregNo(i->Xin.FpCmp.srcL));
+//..       /* fucomp %(fR+1) */
+//..       *p++ = 0xDD;
+//..       *p++ = 0xE8 + (7 & (1+fregNo(i->Xin.FpCmp.srcR)));
+//..       /* fnstsw %ax */
+//..       *p++ = 0xDF;
+//..       *p++ = 0xE0;
+//..       /*  movl %eax, %dst */
+//..       *p++ = 0x89;
+//..       p = doAMode_R(p, hregX86_EAX(), i->Xin.FpCmp.dst);
+//..       goto done;
+//.. 
+//..    case Xin_SseConst: {
+//..       UShort con = i->Xin.SseConst.con;
+//..       p = push_word_from_tags(p, (con >> 12) & 0xF);
+//..       p = push_word_from_tags(p, (con >> 8) & 0xF);
+//..       p = push_word_from_tags(p, (con >> 4) & 0xF);
+//..       p = push_word_from_tags(p, con & 0xF);
+//..       /* movl (%esp), %xmm-dst */
+//..       *p++ = 0x0F;
+//..       *p++ = 0x10;
+//..       *p++ = 0x04 + 8 * (7 & vregNo(i->Xin.SseConst.dst));
+//..       *p++ = 0x24;
+//..       /* addl $16, %esp */
+//..       *p++ = 0x83;
+//..       *p++ = 0xC4;
+//..       *p++ = 0x10;
+//..       goto done;
+//..    }
+//.. 
+//..    case Xin_SseLdSt:
+//..       *p++ = 0x0F; 
+//..       *p++ = i->Xin.SseLdSt.isLoad ? 0x10 : 0x11;
+//..       p = doAMode_M(p, fake(vregNo(i->Xin.SseLdSt.reg)), i->Xin.SseLdSt.addr);
+//..       goto done;
+//.. 
+//..    case Xin_SseLdzLO:
+//..       vassert(i->Xin.SseLdzLO.sz == 4 || i->Xin.SseLdzLO.sz == 8);
+//..       /* movs[sd] amode, %xmm-dst */
+//..       *p++ = i->Xin.SseLdzLO.sz==4 ? 0xF3 : 0xF2;
+//..       *p++ = 0x0F; 
+//..       *p++ = 0x10; 
+//..       p = doAMode_M(p, fake(vregNo(i->Xin.SseLdzLO.reg)), 
+//..                        i->Xin.SseLdzLO.addr);
+//..       goto done;
+//.. 
+//..    case Xin_Sse32Fx4:
+//..       xtra = 0;
+//..       *p++ = 0x0F;
+//..       switch (i->Xin.Sse32Fx4.op) {
+//..          case Xsse_ADDF:   *p++ = 0x58; break;
+//..          case Xsse_DIVF:   *p++ = 0x5E; break;
+//..          case Xsse_MAXF:   *p++ = 0x5F; break;
+//..          case Xsse_MINF:   *p++ = 0x5D; break;
+//..          case Xsse_MULF:   *p++ = 0x59; break;
+//..          case Xsse_RCPF:   *p++ = 0x53; break;
+//..          case Xsse_RSQRTF: *p++ = 0x52; break;
+//..          case Xsse_SQRTF:  *p++ = 0x51; break;
+//..          case Xsse_SUBF:   *p++ = 0x5C; break;
+//..          case Xsse_CMPEQF: *p++ = 0xC2; xtra = 0x100; break;
+//..          case Xsse_CMPLTF: *p++ = 0xC2; xtra = 0x101; break;
+//..          case Xsse_CMPLEF: *p++ = 0xC2; xtra = 0x102; break;
+//..          default: goto bad;
+//..       }
+//..       p = doAMode_R(p, fake(vregNo(i->Xin.Sse32Fx4.dst)),
+//..                        fake(vregNo(i->Xin.Sse32Fx4.src)) );
+//..       if (xtra & 0x100)
+//..          *p++ = (UChar)(xtra & 0xFF);
+//..       goto done;
+//.. 
+//..    case Xin_Sse64Fx2:
+//..       xtra = 0;
+//..       *p++ = 0x66;
+//..       *p++ = 0x0F;
+//..       switch (i->Xin.Sse64Fx2.op) {
+//..          case Xsse_ADDF:   *p++ = 0x58; break;
+//..          case Xsse_DIVF:   *p++ = 0x5E; break;
+//..          case Xsse_MAXF:   *p++ = 0x5F; break;
+//..          case Xsse_MINF:   *p++ = 0x5D; break;
+//..          case Xsse_MULF:   *p++ = 0x59; break;
+//..          case Xsse_RCPF:   *p++ = 0x53; break;
+//..          case Xsse_RSQRTF: *p++ = 0x52; break;
+//..          case Xsse_SQRTF:  *p++ = 0x51; break;
+//..          case Xsse_SUBF:   *p++ = 0x5C; break;
+//..          case Xsse_CMPEQF: *p++ = 0xC2; xtra = 0x100; break;
+//..          case Xsse_CMPLTF: *p++ = 0xC2; xtra = 0x101; break;
+//..          case Xsse_CMPLEF: *p++ = 0xC2; xtra = 0x102; break;
+//..          default: goto bad;
+//..       }
+//..       p = doAMode_R(p, fake(vregNo(i->Xin.Sse64Fx2.dst)),
+//..                        fake(vregNo(i->Xin.Sse64Fx2.src)) );
+//..       if (xtra & 0x100)
+//..          *p++ = (UChar)(xtra & 0xFF);
+//..       goto done;
+//.. 
+//..    case Xin_Sse32FLo:
+//..       xtra = 0;
+//..       *p++ = 0xF3;
+//..       *p++ = 0x0F;
+//..       switch (i->Xin.Sse32FLo.op) {
+//..          case Xsse_ADDF:   *p++ = 0x58; break;
+//..          case Xsse_DIVF:   *p++ = 0x5E; break;
+//..          case Xsse_MAXF:   *p++ = 0x5F; break;
+//..          case Xsse_MINF:   *p++ = 0x5D; break;
+//..          case Xsse_MULF:   *p++ = 0x59; break;
+//..          case Xsse_RCPF:   *p++ = 0x53; break;
+//..          case Xsse_RSQRTF: *p++ = 0x52; break;
+//..          case Xsse_SQRTF:  *p++ = 0x51; break;
+//..          case Xsse_SUBF:   *p++ = 0x5C; break;
+//..          case Xsse_CMPEQF: *p++ = 0xC2; xtra = 0x100; break;
+//..          case Xsse_CMPLTF: *p++ = 0xC2; xtra = 0x101; break;
+//..          case Xsse_CMPLEF: *p++ = 0xC2; xtra = 0x102; break;
+//..          default: goto bad;
+//..       }
+//..       p = doAMode_R(p, fake(vregNo(i->Xin.Sse32FLo.dst)),
+//..                        fake(vregNo(i->Xin.Sse32FLo.src)) );
+//..       if (xtra & 0x100)
+//..          *p++ = (UChar)(xtra & 0xFF);
+//..       goto done;
+//.. 
+//..    case Xin_Sse64FLo:
+//..       xtra = 0;
+//..       *p++ = 0xF2;
+//..       *p++ = 0x0F;
+//..       switch (i->Xin.Sse64FLo.op) {
+//..          case Xsse_ADDF:   *p++ = 0x58; break;
+//..          case Xsse_DIVF:   *p++ = 0x5E; break;
+//..          case Xsse_MAXF:   *p++ = 0x5F; break;
+//..          case Xsse_MINF:   *p++ = 0x5D; break;
+//..          case Xsse_MULF:   *p++ = 0x59; break;
+//..          case Xsse_RCPF:   *p++ = 0x53; break;
+//..          case Xsse_RSQRTF: *p++ = 0x52; break;
+//..          case Xsse_SQRTF:  *p++ = 0x51; break;
+//..          case Xsse_SUBF:   *p++ = 0x5C; break;
+//..          case Xsse_CMPEQF: *p++ = 0xC2; xtra = 0x100; break;
+//..          case Xsse_CMPLTF: *p++ = 0xC2; xtra = 0x101; break;
+//..          case Xsse_CMPLEF: *p++ = 0xC2; xtra = 0x102; break;
+//..          default: goto bad;
+//..       }
+//..       p = doAMode_R(p, fake(vregNo(i->Xin.Sse64FLo.dst)),
+//..                        fake(vregNo(i->Xin.Sse64FLo.src)) );
+//..       if (xtra & 0x100)
+//..          *p++ = (UChar)(xtra & 0xFF);
+//..       goto done;
+//.. 
+//..    case Xin_SseReRg:
+//.. #     define XX(_n) *p++ = (_n)
+//..       switch (i->Xin.SseReRg.op) {
+//..          case Xsse_MOV:     /*movups*/ XX(0x0F); XX(0x10); break;
+//..          case Xsse_OR:                 XX(0x0F); XX(0x56); break;
+//..          case Xsse_XOR:                XX(0x0F); XX(0x57); break;
+//..          case Xsse_AND:                XX(0x0F); XX(0x54); break;
+//..          case Xsse_PACKSSD:  XX(0x66); XX(0x0F); XX(0x6B); break;
+//..          case Xsse_PACKSSW:  XX(0x66); XX(0x0F); XX(0x63); break;
+//..          case Xsse_PACKUSW:  XX(0x66); XX(0x0F); XX(0x67); break;
+//..          case Xsse_ADD8:     XX(0x66); XX(0x0F); XX(0xFC); break;
+//..          case Xsse_ADD16:    XX(0x66); XX(0x0F); XX(0xFD); break;
+//..          case Xsse_ADD32:    XX(0x66); XX(0x0F); XX(0xFE); break;
+//..          case Xsse_ADD64:    XX(0x66); XX(0x0F); XX(0xD4); break;
+//..          case Xsse_QADD8S:   XX(0x66); XX(0x0F); XX(0xEC); break;
+//..          case Xsse_QADD16S:  XX(0x66); XX(0x0F); XX(0xED); break;
+//..          case Xsse_QADD8U:   XX(0x66); XX(0x0F); XX(0xDC); break;
+//..          case Xsse_QADD16U:  XX(0x66); XX(0x0F); XX(0xDD); break;
+//..          case Xsse_AVG8U:    XX(0x66); XX(0x0F); XX(0xE0); break;
+//..          case Xsse_AVG16U:   XX(0x66); XX(0x0F); XX(0xE3); break;
+//..          case Xsse_CMPEQ8:   XX(0x66); XX(0x0F); XX(0x74); break;
+//..          case Xsse_CMPEQ16:  XX(0x66); XX(0x0F); XX(0x75); break;
+//..          case Xsse_CMPEQ32:  XX(0x66); XX(0x0F); XX(0x76); break;
+//..          case Xsse_CMPGT8S:  XX(0x66); XX(0x0F); XX(0x64); break;
+//..          case Xsse_CMPGT16S: XX(0x66); XX(0x0F); XX(0x65); break;
+//..          case Xsse_CMPGT32S: XX(0x66); XX(0x0F); XX(0x66); break;
+//..          case Xsse_MAX16S:   XX(0x66); XX(0x0F); XX(0xEE); break;
+//..          case Xsse_MAX8U:    XX(0x66); XX(0x0F); XX(0xDE); break;
+//..          case Xsse_MIN16S:   XX(0x66); XX(0x0F); XX(0xEA); break;
+//..          case Xsse_MIN8U:    XX(0x66); XX(0x0F); XX(0xDA); break;
+//..          case Xsse_MULHI16U: XX(0x66); XX(0x0F); XX(0xE4); break;
+//..          case Xsse_MULHI16S: XX(0x66); XX(0x0F); XX(0xE5); break;
+//..          case Xsse_MUL16:    XX(0x66); XX(0x0F); XX(0xD5); break;
+//..          case Xsse_SHL16:    XX(0x66); XX(0x0F); XX(0xF1); break;
+//..          case Xsse_SHL32:    XX(0x66); XX(0x0F); XX(0xF2); break;
+//..          case Xsse_SHL64:    XX(0x66); XX(0x0F); XX(0xF3); break;
+//..          case Xsse_SAR16:    XX(0x66); XX(0x0F); XX(0xE1); break;
+//..          case Xsse_SAR32:    XX(0x66); XX(0x0F); XX(0xE2); break;
+//..          case Xsse_SHR16:    XX(0x66); XX(0x0F); XX(0xD1); break;
+//..          case Xsse_SHR32:    XX(0x66); XX(0x0F); XX(0xD2); break;
+//..          case Xsse_SHR64:    XX(0x66); XX(0x0F); XX(0xD3); break;
+//..          case Xsse_SUB8:     XX(0x66); XX(0x0F); XX(0xF8); break;
+//..          case Xsse_SUB16:    XX(0x66); XX(0x0F); XX(0xF9); break;
+//..          case Xsse_SUB32:    XX(0x66); XX(0x0F); XX(0xFA); break;
+//..          case Xsse_SUB64:    XX(0x66); XX(0x0F); XX(0xFB); break;
+//..          case Xsse_QSUB8S:   XX(0x66); XX(0x0F); XX(0xE8); break;
+//..          case Xsse_QSUB16S:  XX(0x66); XX(0x0F); XX(0xE9); break;
+//..          case Xsse_QSUB8U:   XX(0x66); XX(0x0F); XX(0xD8); break;
+//..          case Xsse_QSUB16U:  XX(0x66); XX(0x0F); XX(0xD9); break;
+//..          case Xsse_UNPCKHB:  XX(0x66); XX(0x0F); XX(0x68); break;
+//..          case Xsse_UNPCKHW:  XX(0x66); XX(0x0F); XX(0x69); break;
+//..          case Xsse_UNPCKHD:  XX(0x66); XX(0x0F); XX(0x6A); break;
+//..          case Xsse_UNPCKHQ:  XX(0x66); XX(0x0F); XX(0x6D); break;
+//..          case Xsse_UNPCKLB:  XX(0x66); XX(0x0F); XX(0x60); break;
+//..          case Xsse_UNPCKLW:  XX(0x66); XX(0x0F); XX(0x61); break;
+//..          case Xsse_UNPCKLD:  XX(0x66); XX(0x0F); XX(0x62); break;
+//..          case Xsse_UNPCKLQ:  XX(0x66); XX(0x0F); XX(0x6C); break;
+//..          default: goto bad;
+//..       }
+//..       p = doAMode_R(p, fake(vregNo(i->Xin.SseReRg.dst)),
+//..                        fake(vregNo(i->Xin.SseReRg.src)) );
+//.. #     undef XX
+//..       goto done;
+//.. 
+//..    case Xin_SseCMov:
+//..       /* jmp fwds if !condition */
+//..       *p++ = 0x70 + (i->Xin.SseCMov.cond ^ 1);
+//..       *p++ = 0; /* # of bytes in the next bit, which we don't know yet */
+//..       ptmp = p;
+//.. 
+//..       /* movaps %src, %dst */
+//..       *p++ = 0x0F; 
+//..       *p++ = 0x28; 
+//..       p = doAMode_R(p, fake(vregNo(i->Xin.SseCMov.dst)),
+//..                        fake(vregNo(i->Xin.SseCMov.src)) );
+//.. 
+//..       /* Fill in the jump offset. */
+//..       *(ptmp-1) = p - ptmp;
+//..       goto done;
+//.. 
+//..    case Xin_SseShuf:
+//..       *p++ = 0x66; 
+//..       *p++ = 0x0F; 
+//..       *p++ = 0x70; 
+//..       p = doAMode_R(p, fake(vregNo(i->Xin.SseShuf.dst)),
+//..                        fake(vregNo(i->Xin.SseShuf.src)) );
+//..       *p++ = (UChar)(i->Xin.SseShuf.order);
+//..       goto done;
+
+   default: 
+      goto bad;
+   }
+
+  bad:
+   ppPPC32Instr(i);
+   vpanic("emit_PPC32Instr");
+   /*NOTREACHED*/
+   
+  goto done;  // CAB: Rem to remove - Just reducing compiler warnings.
+  done:
+   vassert(p - &buf[0] <= 32);
+   return p - &buf[0];
+
+#  undef fake
+}
+
+/*---------------------------------------------------------------*/
+/*--- end                                  host-ppc32/hdefs.c ---*/
+/*---------------------------------------------------------------*/
diff --git a/VEX/priv/host-ppc32/hdefs.h b/VEX/priv/host-ppc32/hdefs.h
new file mode 100644 (file)
index 0000000..a1b879d
--- /dev/null
@@ -0,0 +1,720 @@
+
+/*---------------------------------------------------------------*/
+/*---                                                         ---*/
+/*--- This file (host-ppc32/hdefs.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) 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.
+*/
+
+#ifndef __LIBVEX_HOST_PPC32_HDEFS_H
+#define __LIBVEX_HOST_PPC32_HDEFS_H
+
+
+/* --------- Registers. --------- */
+
+/* The usual HReg abstraction.  There are 32 real int regs,
+   32 real float regs, and 0 real vector regs. 
+*/
+
+extern void ppHRegPPC32 ( HReg );
+
+extern HReg hregPPC32_GPR0 ( void );
+extern HReg hregPPC32_GPR1 ( void );
+extern HReg hregPPC32_GPR2 ( void );
+extern HReg hregPPC32_GPR3 ( void );
+extern HReg hregPPC32_GPR4 ( void );
+extern HReg hregPPC32_GPR5 ( void );
+extern HReg hregPPC32_GPR6 ( void );
+extern HReg hregPPC32_GPR7 ( void );
+extern HReg hregPPC32_GPR8 ( void );
+extern HReg hregPPC32_GPR9 ( void );
+extern HReg hregPPC32_GPR10 ( void );
+extern HReg hregPPC32_GPR11 ( void );
+extern HReg hregPPC32_GPR12 ( void );
+extern HReg hregPPC32_GPR13 ( void );
+extern HReg hregPPC32_GPR14 ( void );
+extern HReg hregPPC32_GPR15 ( void );
+extern HReg hregPPC32_GPR16 ( void );
+extern HReg hregPPC32_GPR17 ( void );
+extern HReg hregPPC32_GPR18 ( void );
+extern HReg hregPPC32_GPR19 ( void );
+extern HReg hregPPC32_GPR20 ( void );
+extern HReg hregPPC32_GPR21 ( void );
+extern HReg hregPPC32_GPR22 ( void );
+extern HReg hregPPC32_GPR23 ( void );
+extern HReg hregPPC32_GPR24 ( void );
+extern HReg hregPPC32_GPR25 ( void );
+extern HReg hregPPC32_GPR26 ( void );
+extern HReg hregPPC32_GPR27 ( void );
+extern HReg hregPPC32_GPR28 ( void );
+extern HReg hregPPC32_GPR29 ( void );
+extern HReg hregPPC32_GPR30 ( void );
+extern HReg hregPPC32_GPR31 ( void );
+
+extern HReg hregPPC32_FPR0 ( void );
+extern HReg hregPPC32_FPR1 ( void );
+extern HReg hregPPC32_FPR2 ( void );
+extern HReg hregPPC32_FPR3 ( void );
+extern HReg hregPPC32_FPR4 ( void );
+extern HReg hregPPC32_FPR5 ( void );
+extern HReg hregPPC32_FPR6 ( void );
+extern HReg hregPPC32_FPR7 ( void );
+extern HReg hregPPC32_FPR8 ( void );
+extern HReg hregPPC32_FPR9 ( void );
+extern HReg hregPPC32_FPR10 ( void );
+extern HReg hregPPC32_FPR11 ( void );
+extern HReg hregPPC32_FPR12 ( void );
+extern HReg hregPPC32_FPR13 ( void );
+extern HReg hregPPC32_FPR14 ( void );
+extern HReg hregPPC32_FPR15 ( void );
+extern HReg hregPPC32_FPR16 ( void );
+extern HReg hregPPC32_FPR17 ( void );
+extern HReg hregPPC32_FPR18 ( void );
+extern HReg hregPPC32_FPR19 ( void );
+extern HReg hregPPC32_FPR20 ( void );
+extern HReg hregPPC32_FPR21 ( void );
+extern HReg hregPPC32_FPR22 ( void );
+extern HReg hregPPC32_FPR23 ( void );
+extern HReg hregPPC32_FPR24 ( void );
+extern HReg hregPPC32_FPR25 ( void );
+extern HReg hregPPC32_FPR26 ( void );
+extern HReg hregPPC32_FPR27 ( void );
+extern HReg hregPPC32_FPR28 ( void );
+extern HReg hregPPC32_FPR29 ( void );
+extern HReg hregPPC32_FPR30 ( void );
+extern HReg hregPPC32_FPR31 ( void );
+
+
+
+//.. /* --------- Condition codes, Intel encoding. --------- */
+//.. 
+//.. typedef
+//..    enum {
+//..       Xcc_O      = 0,  /* overflow           */
+//..       Xcc_NO     = 1,  /* no overflow        */
+//.. 
+//..       Xcc_B      = 2,  /* below              */
+//..       Xcc_NB     = 3,  /* not below          */
+//.. 
+//..       Xcc_Z      = 4,  /* zero               */
+//..       Xcc_NZ     = 5,  /* not zero           */
+//.. 
+//..       Xcc_BE     = 6,  /* below or equal     */
+//..       Xcc_NBE    = 7,  /* not below or equal */
+//.. 
+//..       Xcc_S      = 8,  /* negative           */
+//..       Xcc_NS     = 9,  /* not negative       */
+//.. 
+//..       Xcc_P      = 10, /* parity even        */
+//..       Xcc_NP     = 11, /* not parity even    */
+//.. 
+//..       Xcc_L      = 12, /* jump less          */
+//..       Xcc_NL     = 13, /* not less           */
+//.. 
+//..       Xcc_LE     = 14, /* less or equal      */
+//..       Xcc_NLE    = 15, /* not less or equal  */
+//.. 
+//..       Xcc_ALWAYS = 16  /* the usual hack     */
+//..    }
+//..    X86CondCode;
+//.. 
+//.. extern HChar* showX86CondCode ( X86CondCode );
+
+
+/* --------- Memory address expressions (amodes). --------- */
+
+typedef
+   enum {
+     Pam_IR,        /* Immediate + Reg */
+     Pam_RR         /* Reg1 + Reg2     */
+   }
+   PPC32AModeTag;
+
+typedef
+   struct {
+      PPC32AModeTag tag;
+      union {
+         struct {
+            HReg base;
+            UInt index;
+         } IR;
+         struct {
+            HReg base;
+            HReg index;
+         } RR;
+      } Pam;
+   }
+   PPC32AMode;
+
+extern PPC32AMode* PPC32AMode_IR ( UInt, HReg );
+extern PPC32AMode* PPC32AMode_RR ( HReg, HReg );
+
+extern PPC32AMode* dopyPPC32AMode ( PPC32AMode* );
+
+extern void ppPPC32AMode ( PPC32AMode* );
+
+
+/* --------- Operand, which can be reg, immediate or memory. --------- */
+
+typedef 
+   enum {
+      Prmi_Imm,
+      Prmi_Reg,
+      Prmi_Mem
+   }
+   PPC32RMITag;
+
+typedef
+   struct {
+      PPC32RMITag tag;
+      union {
+         struct {
+            UInt imm32;
+         } Imm;
+         struct {
+            HReg reg;
+         } Reg;
+         struct {
+            PPC32AMode* am;
+         } Mem;
+      }
+      Prmi;
+   }
+   PPC32RMI;
+
+extern PPC32RMI* PPC32RMI_Imm ( UInt );
+extern PPC32RMI* PPC32RMI_Reg ( HReg );
+extern PPC32RMI* PPC32RMI_Mem ( PPC32AMode* );
+
+extern void ppPPC32RMI ( PPC32RMI* );
+
+
+/* --------- Operand, which can be reg or immediate only. --------- */
+
+typedef 
+   enum {
+      Pri_Imm,
+      Pri_Reg
+   }
+   PPC32RITag;
+
+typedef
+   struct {
+      PPC32RITag tag;
+      union {
+         struct {
+            UInt imm32;
+         } Imm;
+         struct {
+            HReg reg;
+         } Reg;
+      }
+      Pri;
+   }
+   PPC32RI;
+
+extern PPC32RI* PPC32RI_Imm ( UInt );
+extern PPC32RI* PPC32RI_Reg ( HReg );
+
+extern void ppPPC32RI ( PPC32RI* );
+
+
+/* --------- Operand, which can be reg or memory only. --------- */
+
+typedef 
+   enum {
+      Prm_Reg,
+      Prm_Mem
+   }
+   PPC32RMTag;
+
+typedef
+   struct {
+      PPC32RMTag tag;
+      union {
+         struct {
+            HReg reg;
+         } Reg;
+         struct {
+            PPC32AMode* am;
+         } Mem;
+      }
+      Prm;
+   }
+   PPC32RM;
+
+extern PPC32RM* PPC32RM_Reg ( HReg );
+extern PPC32RM* PPC32RM_Mem ( PPC32AMode* );
+
+extern void ppPPC32RM ( PPC32RM* );
+
+
+//.. /* --------- Instructions. --------- */
+//.. 
+//.. /* --------- */
+//.. typedef
+//..    enum {
+//..       Xss_16,
+//..       Xss_32
+//..    }
+//..    X86ScalarSz;
+//.. 
+//.. extern HChar* showX86ScalarSz ( X86ScalarSz );
+//.. 
+//.. 
+//.. /* --------- */
+//.. typedef
+//..    enum {
+//..       Xun_NEG,
+//..       Xun_NOT
+//..    }
+//..    X86UnaryOp;
+//.. 
+//.. extern HChar* showX86UnaryOp ( X86UnaryOp );
+//.. 
+//.. 
+//.. /* --------- */
+//.. typedef 
+//..    enum {
+//..       Xalu_INVALID,
+//..       Xalu_MOV,
+//..       Xalu_CMP,
+//..       Xalu_ADD, Xalu_SUB, Xalu_ADC, Xalu_SBB, 
+//..       Xalu_AND, Xalu_OR, Xalu_XOR,
+//..       Xalu_MUL
+//..    }
+//..    X86AluOp;
+//.. 
+//.. extern HChar* showX86AluOp ( X86AluOp );
+//.. 
+//.. 
+//.. /* --------- */
+//.. typedef
+//..    enum {
+//..       Xsh_INVALID,
+//..       Xsh_SHL, Xsh_SHR, Xsh_SAR, 
+//..       Xsh_ROL, Xsh_ROR
+//..    }
+//..    X86ShiftOp;
+//.. 
+//.. extern HChar* showX86ShiftOp ( X86ShiftOp );
+//.. 
+//.. 
+//.. /* --------- */
+//.. typedef
+//..    enum {
+//..       Xfp_INVALID,
+//..       /* Binary */
+//..       Xfp_ADD, Xfp_SUB, Xfp_MUL, Xfp_DIV, 
+//..       Xfp_SCALE, Xfp_ATAN, Xfp_YL2X, Xfp_YL2XP1, Xfp_PREM, Xfp_PREM1,
+//..       /* Unary */
+//..       Xfp_SQRT, Xfp_ABS, Xfp_NEG, Xfp_MOV, Xfp_SIN, Xfp_COS, Xfp_TAN,
+//..       Xfp_ROUND, Xfp_2XM1
+//..    }
+//..    X86FpOp;
+//.. 
+//.. extern HChar* showX86FpOp ( X86FpOp );
+//.. 
+//.. 
+//.. /* --------- */
+//.. typedef
+//..    enum {
+//..       Xsse_INVALID,
+//..       /* mov */
+//..       Xsse_MOV,
+//..       /* Floating point binary */
+//..       Xsse_ADDF, Xsse_SUBF, Xsse_MULF, Xsse_DIVF,
+//..       Xsse_MAXF, Xsse_MINF,
+//..       Xsse_CMPEQF, Xsse_CMPLTF, Xsse_CMPLEF, Xsse_CMPUNF,
+//..       /* Floating point unary */
+//..       Xsse_RCPF, Xsse_RSQRTF, Xsse_SQRTF, 
+//..       /* Bitwise */
+//..       Xsse_AND, Xsse_OR, Xsse_XOR, Xsse_ANDN,
+//..       /* Integer binary */
+//..       Xsse_ADD8,   Xsse_ADD16,   Xsse_ADD32,   Xsse_ADD64,
+//..       Xsse_QADD8U, Xsse_QADD16U,
+//..       Xsse_QADD8S, Xsse_QADD16S,
+//..       Xsse_SUB8,   Xsse_SUB16,   Xsse_SUB32,   Xsse_SUB64,
+//..       Xsse_QSUB8U, Xsse_QSUB16U,
+//..       Xsse_QSUB8S, Xsse_QSUB16S,
+//..       Xsse_MUL16,
+//..       Xsse_MULHI16U,
+//..       Xsse_MULHI16S,
+//..       Xsse_AVG8U, Xsse_AVG16U,
+//..       Xsse_MAX16S,
+//..       Xsse_MAX8U,
+//..       Xsse_MIN16S,
+//..       Xsse_MIN8U,
+//..       Xsse_CMPEQ8,  Xsse_CMPEQ16,  Xsse_CMPEQ32,
+//..       Xsse_CMPGT8S, Xsse_CMPGT16S, Xsse_CMPGT32S,
+//..       Xsse_SHL16, Xsse_SHL32, Xsse_SHL64,
+//..       Xsse_SHR16, Xsse_SHR32, Xsse_SHR64,
+//..       Xsse_SAR16, Xsse_SAR32, 
+//..       Xsse_PACKSSD, Xsse_PACKSSW, Xsse_PACKUSW,
+//..       Xsse_UNPCKHB, Xsse_UNPCKHW, Xsse_UNPCKHD, Xsse_UNPCKHQ,
+//..       Xsse_UNPCKLB, Xsse_UNPCKLW, Xsse_UNPCKLD, Xsse_UNPCKLQ
+//..    }
+//..    X86SseOp;
+//.. 
+//.. extern HChar* showX86SseOp ( X86SseOp );
+
+
+/* --------- */
+typedef
+   enum {
+      Pin_Nada,    /* nix */
+//..       Xin_Alu32R,    /* 32-bit mov/arith/logical, dst=REG */
+//..       Xin_Alu32M,    /* 32-bit mov/arith/logical, dst=MEM */
+//..       Xin_Sh32,      /* 32-bit shift/rotate, dst=REG or MEM */
+//..       Xin_Test32,    /* 32-bit test (AND, set flags, discard result) */
+//..       Xin_Unary32,   /* 32-bit not and neg */
+//..       Xin_MulL,      /* widening multiply */
+//..       Xin_Div,       /* div and mod */
+//..       Xin_Sh3232,    /* shldl or shrdl */
+//..       Xin_Push,      /* push (32-bit?) value on stack */
+//..       Xin_Call,      /* call to address in register */
+//..       Xin_Goto,      /* conditional/unconditional jmp to dst */
+//..       Xin_CMov32,    /* conditional move */
+//..       Xin_LoadEX,    /* mov{s,z}{b,w}l from mem to reg */
+//..       Xin_Store,     /* store 16/8 bit value in memory */
+//..       Xin_Set32,     /* convert condition code to 32-bit value */
+//..       Xin_Bsfr32,    /* 32-bit bsf/bsr */
+//..       Xin_MFence,    /* mem fence (not just sse2, but sse0 and 1 too) */
+//.. 
+//..       Xin_FpUnary,   /* FP fake unary op */
+//..       Xin_FpBinary,  /* FP fake binary op */
+//..       Xin_FpLdSt,    /* FP fake load/store */
+//..       Xin_FpLdStI,   /* FP fake load/store, converting to/from Int */
+//..       Xin_Fp64to32,  /* FP round IEEE754 double to IEEE754 single */
+//..       Xin_FpCMov,    /* FP fake floating point conditional move */
+//..       Xin_FpLdStCW,  /* fldcw / fstcw */
+//..       Xin_FpStSW_AX, /* fstsw %ax */
+//..       Xin_FpCmp,     /* FP compare, generating a C320 value into int reg */
+//.. 
+//..       Xin_SseConst,  /* Generate restricted SSE literal */
+//..       Xin_SseLdSt,   /* SSE load/store, no alignment constraints */
+//..       Xin_SseLdzLO,  /* SSE load low 32/64 bits, zero remainder of reg */
+//..       Xin_Sse32Fx4,  /* SSE binary, 32Fx4 */
+//..       Xin_Sse32FLo,  /* SSE binary, 32F in lowest lane only */
+//..       Xin_Sse64Fx2,  /* SSE binary, 64Fx2 */
+//..       Xin_Sse64FLo,  /* SSE binary, 64F in lowest lane only */
+//..       Xin_SseReRg,   /* SSE binary general reg-reg, Re, Rg */
+//..       Xin_SseCMov,   /* SSE conditional move */
+//..       Xin_SseShuf    /* SSE2 shuffle (pshufd) */
+   }
+   PPC32InstrTag;
+
+/* Destinations are on the RIGHT (second operand) */
+
+typedef
+   struct {
+      PPC32InstrTag tag;
+//..       union {
+//..          struct {
+//..             X86AluOp op;
+//..             X86RMI*  src;
+//..             HReg     dst;
+//..          } Alu32R;
+//..          struct {
+//..             X86AluOp  op;
+//..             X86RI*    src;
+//..             X86AMode* dst;
+//..          } Alu32M;
+//..          struct {
+//..             X86ShiftOp op;
+//..             UInt       src;  /* shift amount, or 0 means %cl */
+//..             X86RM*     dst;
+//..          } Sh32;
+//..          struct {
+//..             X86RI* src;
+//..             X86RM* dst;
+//..          } Test32;
+//..          /* Not and Neg */
+//..          struct {
+//..             X86UnaryOp op;
+//..             X86RM*     dst;
+//..          } Unary32;
+//..          /* DX:AX = AX *s/u r/m16,  or EDX:EAX = EAX *s/u r/m32 */
+//..          struct {
+//..             Bool        syned;
+//..             X86ScalarSz ssz;
+//..             X86RM*      src;
+//..          } MulL;
+//..          /* x86 div/idiv instruction.  Modifies EDX and EAX and reads src. */
+//..          struct {
+//..             Bool        syned;
+//..             X86ScalarSz ssz;
+//..             X86RM*      src;
+//..          } Div;
+//..          /* shld/shrd.  op may only be Xsh_SHL or Xsh_SHR */
+//..          struct {
+//..             X86ShiftOp op;
+//..             UInt       amt;   /* shift amount, or 0 means %cl */
+//..             HReg       src;
+//..             HReg       dst;
+//..          } Sh3232;
+//..          struct {
+//..             X86RMI* src;
+//..          } Push;
+//..          /* Pseudo-insn.  Call target (an absolute address), on given
+//..             condition (which could be Xcc_ALWAYS). */
+//..          struct {
+//..             X86CondCode cond;
+//..             Addr32      target;
+//..             Int         regparms; /* 0 .. 3 */
+//..          } Call;
+//..          /* Pseudo-insn.  Goto dst, on given condition (which could be
+//..             Xcc_ALWAYS).  Note importantly that if the jump is 
+//..             conditional (not Xcc_ALWAYS) the jump kind *must* be
+//..             Ijk_Boring.  Ie non-Boring conditional jumps are
+//..             not allowed. */
+//..          struct {
+//..             IRJumpKind  jk;
+//..             X86CondCode cond;
+//..             X86RI*      dst;
+//..          } Goto;
+//..          /* Mov src to dst on the given condition, which may not
+//..             be the bogus Xcc_ALWAYS. */
+//..          struct {
+//..             X86CondCode cond;
+//..             X86RM*      src;
+//..             HReg        dst;
+//..          } CMov32;
+//..          /* Sign/Zero extending loads.  Dst size is always 32 bits. */
+//..          struct {
+//..             UChar     szSmall;
+//..             Bool      syned;
+//..             X86AMode* src;
+//..             HReg      dst;
+//..          } LoadEX;
+//..          /* 16/8 bit stores, which are troublesome (particularly
+//..             8-bit) */
+//..          struct {
+//..             UChar     sz; /* only 1 or 2 */
+//..             HReg      src;
+//..             X86AMode* dst;
+//..          } Store;
+//..          /* Convert a x86 condition code to a 32-bit value (0 or 1). */
+//..          struct {
+//..             X86CondCode cond;
+//..             HReg        dst;
+//..          } Set32;
+//..          /* 32-bit bsf or bsr. */
+//..          struct {
+//..             Bool isFwds;
+//..             HReg src;
+//..             HReg dst;
+//..          } Bsfr32;
+//..          /* Mem fence (not just sse2, but sse0 and 1 too).  In short,
+//..             an insn which flushes all preceding loads and stores as
+//..             much as possible before continuing.  On SSE2 we emit a
+//..             real "mfence", on SSE1 "sfence ; lock addl $0,0(%esp)" and
+//..             on SSE0 "lock addl $0,0(%esp)".  This insn therefore
+//..             carries the subarch so the assembler knows what to
+//..             emit. */
+//..          struct {
+//..             VexSubArch subarch;
+//..          } MFence;
+//.. 
+//..          /* X86 Floating point (fake 3-operand, "flat reg file" insns) */
+//..          struct {
+//..             X86FpOp op;
+//..             HReg    src;
+//..             HReg    dst;
+//..          } FpUnary;
+//..          struct {
+//..             X86FpOp op;
+//..             HReg    srcL;
+//..             HReg    srcR;
+//..             HReg    dst;
+//..          } FpBinary;
+//..          struct {
+//..             Bool      isLoad;
+//..             UChar     sz; /* only 4 (IEEE single) or 8 (IEEE double) */
+//..             HReg      reg;
+//..             X86AMode* addr;
+//..          } FpLdSt;
+//..          /* Move 64-bit float to/from memory, converting to/from
+//..             signed int on the way.  Note the conversions will observe
+//..             the host FPU rounding mode currently in force. */
+//..          struct {
+//..             Bool      isLoad;
+//..             UChar     sz; /* only 2, 4 or 8 */
+//..             HReg      reg;
+//..             X86AMode* addr;
+//..          } FpLdStI;
+//..          /* By observing the current FPU rounding mode, round (etc)
+//..             src into dst given that dst should be interpreted as an
+//..             IEEE754 32-bit (float) type. */
+//..          struct {
+//..             HReg src;
+//..             HReg dst;
+//..          } Fp64to32;
+//..          /* Mov src to dst on the given condition, which may not
+//..             be the bogus Xcc_ALWAYS. */
+//..          struct {
+//..             X86CondCode cond;
+//..             HReg        src;
+//..             HReg        dst;
+//..          } FpCMov;
+//..          /* Load/store the FPU's 16-bit control word (fldcw/fstcw) */
+//..          struct {
+//..             Bool      isLoad;
+//..             X86AMode* addr;
+//..          }
+//..          FpLdStCW;
+//..          /* fstsw %ax */
+//..          struct {
+//..             /* no fields */
+//..          }
+//..          FpStSW_AX;
+//..          /* Do a compare, generating the C320 bits into the dst. */
+//..          struct {
+//..             HReg    srcL;
+//..             HReg    srcR;
+//..             HReg    dst;
+//..          } FpCmp;
+//.. 
+//..          /* Simplistic SSE[123] */
+//..          struct {
+//..             UShort  con;
+//..             HReg    dst;
+//..          } SseConst;
+//..          struct {
+//..             Bool      isLoad;
+//..             HReg      reg;
+//..             X86AMode* addr;
+//..          } SseLdSt;
+//..          struct {
+//..             Int       sz; /* 4 or 8 only */
+//..             HReg      reg;
+//..             X86AMode* addr;
+//..          } SseLdzLO;
+//..          struct {
+//..             X86SseOp op;
+//..             HReg     src;
+//..             HReg     dst;
+//..          } Sse32Fx4;
+//..          struct {
+//..             X86SseOp op;
+//..             HReg     src;
+//..             HReg     dst;
+//..          } Sse32FLo;
+//..          struct {
+//..             X86SseOp op;
+//..             HReg     src;
+//..             HReg     dst;
+//..          } Sse64Fx2;
+//..          struct {
+//..             X86SseOp op;
+//..             HReg     src;
+//..             HReg     dst;
+//..          } Sse64FLo;
+//..          struct {
+//..             X86SseOp op;
+//..             HReg     src;
+//..             HReg     dst;
+//..          } SseReRg;
+//..          /* Mov src to dst on the given condition, which may not
+//..             be the bogus Xcc_ALWAYS. */
+//..          struct {
+//..             X86CondCode cond;
+//..             HReg        src;
+//..             HReg        dst;
+//..          } SseCMov;
+//..          struct {
+//..             Int    order; /* 0 <= order <= 0xFF */
+//..             HReg   src;
+//..             HReg   dst;
+//..          } SseShuf;
+//.. 
+//..       } Xin;
+   }
+   PPC32Instr;
+
+//.. extern X86Instr* X86Instr_Alu32R    ( X86AluOp, X86RMI*, HReg );
+//.. extern X86Instr* X86Instr_Alu32M    ( X86AluOp, X86RI*,  X86AMode* );
+//.. extern X86Instr* X86Instr_Unary32   ( X86UnaryOp op, X86RM* dst );
+//.. extern X86Instr* X86Instr_Sh32      ( X86ShiftOp, UInt, X86RM* );
+//.. extern X86Instr* X86Instr_Test32    ( X86RI* src, X86RM* dst );
+//.. extern X86Instr* X86Instr_MulL      ( Bool syned, X86ScalarSz, X86RM* );
+//.. extern X86Instr* X86Instr_Div       ( Bool syned, X86ScalarSz, X86RM* );
+//.. extern X86Instr* X86Instr_Sh3232    ( X86ShiftOp, UInt amt, HReg src, HReg dst );
+//.. extern X86Instr* X86Instr_Push      ( X86RMI* );
+//.. extern X86Instr* X86Instr_Call      ( X86CondCode, Addr32, Int );
+//.. extern X86Instr* X86Instr_Goto      ( IRJumpKind, X86CondCode cond, X86RI* dst );
+//.. extern X86Instr* X86Instr_CMov32    ( X86CondCode, X86RM* src, HReg dst );
+//.. extern X86Instr* X86Instr_LoadEX    ( UChar szSmall, Bool syned,
+//..                                       X86AMode* src, HReg dst );
+//.. extern X86Instr* X86Instr_Store     ( UChar sz, HReg src, X86AMode* dst );
+//.. extern X86Instr* X86Instr_Set32     ( X86CondCode cond, HReg dst );
+//.. extern X86Instr* X86Instr_Bsfr32    ( Bool isFwds, HReg src, HReg dst );
+//.. extern X86Instr* X86Instr_MFence    ( VexSubArch );
+//.. 
+//.. extern X86Instr* X86Instr_FpUnary   ( X86FpOp op, HReg src, HReg dst );
+//.. extern X86Instr* X86Instr_FpBinary  ( X86FpOp op, HReg srcL, HReg srcR, HReg dst );
+//.. extern X86Instr* X86Instr_FpLdSt    ( Bool isLoad, UChar sz, HReg reg, X86AMode* );
+//.. extern X86Instr* X86Instr_FpLdStI   ( Bool isLoad, UChar sz, HReg reg, X86AMode* );
+//.. extern X86Instr* X86Instr_Fp64to32  ( HReg src, HReg dst );
+//.. extern X86Instr* X86Instr_FpCMov    ( X86CondCode, HReg src, HReg dst );
+//.. extern X86Instr* X86Instr_FpLdStCW  ( Bool isLoad, X86AMode* );
+//.. extern X86Instr* X86Instr_FpStSW_AX ( void );
+//.. extern X86Instr* X86Instr_FpCmp     ( HReg srcL, HReg srcR, HReg dst );
+//.. 
+//.. extern X86Instr* X86Instr_SseConst  ( UShort con, HReg dst );
+//.. extern X86Instr* X86Instr_SseLdSt   ( Bool isLoad, HReg, X86AMode* );
+//.. extern X86Instr* X86Instr_SseLdzLO  ( Int sz, HReg, X86AMode* );
+//.. extern X86Instr* X86Instr_Sse32Fx4  ( X86SseOp, HReg, HReg );
+//.. extern X86Instr* X86Instr_Sse32FLo  ( X86SseOp, HReg, HReg );
+//.. extern X86Instr* X86Instr_Sse64Fx2  ( X86SseOp, HReg, HReg );
+//.. extern X86Instr* X86Instr_Sse64FLo  ( X86SseOp, HReg, HReg );
+//.. extern X86Instr* X86Instr_SseReRg   ( X86SseOp, HReg, HReg );
+//.. extern X86Instr* X86Instr_SseCMov   ( X86CondCode, HReg src, HReg dst );
+//.. extern X86Instr* X86Instr_SseShuf   ( Int order, HReg src, HReg dst );
+
+
+extern void ppPPC32Instr ( PPC32Instr* );
+
+/* Some functions that insulate the register allocator from details
+   of the underlying instruction set. */
+extern void         getRegUsage_PPC32Instr ( HRegUsage*, PPC32Instr* );
+extern void         mapRegs_PPC32Instr     ( HRegRemap*, PPC32Instr* );
+extern Bool         isMove_PPC32Instr      ( PPC32Instr*, HReg*, HReg* );
+extern Int          emit_PPC32Instr        ( UChar* buf, Int nbuf, PPC32Instr* );
+extern PPC32Instr*  genSpill_PPC32         ( HReg rreg, Int offset );
+extern PPC32Instr*  genReload_PPC32        ( HReg rreg, Int offset );
+extern void         getAllocableRegs_PPC32 ( Int*, HReg** );
+extern HInstrArray* iselBB_PPC32           ( IRBB*, VexSubArch );
+
+#endif /* ndef __LIBVEX_HOST_PPC32_HDEFS_H */
+
+/*---------------------------------------------------------------*/
+/*--- end                                  host-ppc32/hdefs.h ---*/
+/*---------------------------------------------------------------*/
diff --git a/VEX/priv/host-ppc32/isel.c b/VEX/priv/host-ppc32/isel.c
new file mode 100644 (file)
index 0000000..30c6d36
--- /dev/null
@@ -0,0 +1,3474 @@
+
+/*---------------------------------------------------------------*/
+/*---                                                         ---*/
+/*--- This file (host-ppc32/isel.c) 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) 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.
+*/
+
+#include "libvex_basictypes.h"
+#include "libvex_ir.h"
+#include "libvex.h"
+
+//.. #include "ir/irmatch.h"
+#include "main/vex_util.h"
+#include "main/vex_globals.h"
+#include "host-generic/h_generic_regs.h"
+//.. #include "host-generic/h_generic_simd64.h"
+#include "host-ppc32/hdefs.h"
+//.. 
+//.. 
+//.. /*---------------------------------------------------------*/
+//.. /*--- x87 control word stuff                            ---*/
+//.. /*---------------------------------------------------------*/
+//.. 
+//.. /* Vex-generated code expects to run with the FPU set as follows: all
+//..    exceptions masked, round-to-nearest, precision = 53 bits.  This
+//..    corresponds to a FPU control word value of 0x027F.
+//.. 
+//..    Similarly the SSE control word (%mxcsr) should be 0x1F80.
+//.. 
+//..    %fpucw and %mxcsr should have these values on entry to
+//..    Vex-generated code, and should those values should be
+//..    unchanged at exit.
+//.. */
+//.. 
+//.. #define DEFAULT_FPUCW 0x027F
+//.. 
+//.. /* debugging only, do not use */
+//.. /* define DEFAULT_FPUCW 0x037F */
+//.. 
+//.. 
+//.. /*---------------------------------------------------------*/
+//.. /*--- misc helpers                                      ---*/
+//.. /*---------------------------------------------------------*/
+//.. 
+//.. /* These are duplicated in guest-x86/toIR.c */
+//.. 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* mkU64 ( ULong i )
+//.. {
+//..    return IRExpr_Const(IRConst_U64(i));
+//.. }
+//.. 
+//.. static IRExpr* mkU32 ( UInt i )
+//.. {
+//..    return IRExpr_Const(IRConst_U32(i));
+//.. }
+//.. 
+//.. static IRExpr* bind ( Int binder )
+//.. {
+//..    return IRExpr_Binder(binder);
+//.. }
+
+/*---------------------------------------------------------*/
+/*--- ISelEnv                                           ---*/
+/*---------------------------------------------------------*/
+
+/* This carries around:
+
+   - A mapping from IRTemp to IRType, giving the type of any IRTemp we
+     might encounter.  This is computed before insn selection starts,
+     and does not change.
+
+   - A mapping from IRTemp to HReg.  This tells the insn selector
+     which virtual register(s) are associated with each IRTemp
+      temporary.  This is computed before insn selection starts, and
+      does not change.  We expect this mapping to map precisely the
+      same set of IRTemps as the type mapping does.
+         - vregmap   holds the primary register for the IRTemp.
+         - vregmapHI is only used for 64-bit integer-typed
+              IRTemps.  It holds the identity of a second
+              32-bit virtual HReg, which holds the high half
+              of the value.
+    - The code array, that is, the insns selected so far.
+    - A counter, for generating new virtual registers.
+    - The host subarchitecture we are selecting insns for.  
+      This is set at the start and does not change.
+    Note, this is all host-independent.  (JRS 20050201: well, kinda
+   ... not completely.  Compare with ISelEnv for amd64.)
+*/
+typedef
+   struct {
+      IRTypeEnv*   type_env;
+      HReg*        vregmap;
+      HReg*        vregmapHI;
+      Int          n_vregmap;
+      HInstrArray* code;
+      Int          vreg_ctr;
+      VexSubArch   subarch;
+   }
+   ISelEnv;
+#if 0
+static HReg lookupIRTemp ( ISelEnv* env, IRTemp tmp )
+{
+   vassert(tmp >= 0);
+   vassert(tmp < env->n_vregmap);
+   return env->vregmap[tmp];
+}
+#endif
+//.. static void lookupIRTemp64 ( HReg* vrHI, HReg* vrLO, ISelEnv* env, IRTemp tmp )
+//.. {
+//..    vassert(tmp >= 0);
+//..    vassert(tmp < env->n_vregmap);
+//..    vassert(env->vregmapHI[tmp] != INVALID_HREG);
+//..    *vrLO = env->vregmap[tmp];
+//..    *vrHI = env->vregmapHI[tmp];
+//.. }
+//.. 
+//.. static void addInstr ( ISelEnv* env, X86Instr* instr )
+//.. {
+//..    addHInstr(env->code, instr);
+//..    if (vex_traceflags & VEX_TRACE_VCODE) {
+//..       ppX86Instr(instr);
+//..       vex_printf("\n");
+//..    }
+//.. }
+//.. 
+//.. static HReg newVRegI ( ISelEnv* env )
+//.. {
+//..    HReg reg = mkHReg(env->vreg_ctr, HRcInt32, True/*virtual reg*/);
+//..    env->vreg_ctr++;
+//..    return reg;
+//.. }
+//.. 
+//.. static HReg newVRegF ( ISelEnv* env )
+//.. {
+//..    HReg reg = mkHReg(env->vreg_ctr, HRcFlt64, True/*virtual reg*/);
+//..    env->vreg_ctr++;
+//..    return reg;
+//.. }
+//.. 
+//.. static HReg newVRegV ( ISelEnv* env )
+//.. {
+//..    HReg reg = mkHReg(env->vreg_ctr, HRcVec128, True/*virtual reg*/);
+//..    env->vreg_ctr++;
+//..    return reg;
+//.. }
+//.. 
+//.. 
+//.. /*---------------------------------------------------------*/
+//.. /*--- ISEL: Forward declarations                        ---*/
+//.. /*---------------------------------------------------------*/
+//.. 
+//.. /* These are organised as iselXXX and iselXXX_wrk pairs.  The
+//..    iselXXX_wrk do the real work, but are not to be called directly.
+//..    For each XXX, iselXXX calls its iselXXX_wrk counterpart, then
+//..    checks that all returned registers are virtual.  You should not
+//..    call the _wrk version directly.
+//.. */
+//.. static X86RMI*     iselIntExpr_RMI_wrk ( ISelEnv* env, IRExpr* e );
+//.. static X86RMI*     iselIntExpr_RMI     ( ISelEnv* env, IRExpr* e );
+//.. 
+//.. static X86RI*      iselIntExpr_RI_wrk ( ISelEnv* env, IRExpr* e );
+//.. static X86RI*      iselIntExpr_RI     ( ISelEnv* env, IRExpr* e );
+//.. 
+//.. static X86RM*      iselIntExpr_RM_wrk ( ISelEnv* env, IRExpr* e );
+//.. static X86RM*      iselIntExpr_RM     ( ISelEnv* env, IRExpr* e );
+//.. 
+//.. static HReg        iselIntExpr_R_wrk ( ISelEnv* env, IRExpr* e );
+//.. static HReg        iselIntExpr_R     ( ISelEnv* env, IRExpr* e );
+//.. 
+//.. static X86AMode*   iselIntExpr_AMode_wrk ( ISelEnv* env, IRExpr* e );
+//.. static X86AMode*   iselIntExpr_AMode     ( ISelEnv* env, IRExpr* e );
+//.. 
+//.. static void        iselInt64Expr_wrk ( HReg* rHi, HReg* rLo, 
+//..                                        ISelEnv* env, IRExpr* e );
+//.. static void        iselInt64Expr     ( HReg* rHi, HReg* rLo, 
+//..                                        ISelEnv* env, IRExpr* e );
+//.. 
+//.. static X86CondCode iselCondCode_wrk ( ISelEnv* env, IRExpr* e );
+//.. static X86CondCode iselCondCode     ( ISelEnv* env, IRExpr* e );
+//.. 
+//.. static HReg        iselDblExpr_wrk ( ISelEnv* env, IRExpr* e );
+//.. static HReg        iselDblExpr     ( ISelEnv* env, IRExpr* e );
+//.. 
+//.. static HReg        iselFltExpr_wrk ( ISelEnv* env, IRExpr* e );
+//.. static HReg        iselFltExpr     ( ISelEnv* env, IRExpr* e );
+//.. 
+//.. static HReg        iselVecExpr_wrk ( ISelEnv* env, IRExpr* e );
+//.. static HReg        iselVecExpr     ( ISelEnv* env, IRExpr* e );
+//.. 
+//.. 
+//.. /*---------------------------------------------------------*/
+//.. /*--- ISEL: Misc helpers                                ---*/
+//.. /*---------------------------------------------------------*/
+//.. 
+//.. /* Is this a 32-bit zero expression? */
+//.. 
+//.. static Bool isZero32 ( IRExpr* e )
+//.. {
+//..    return e->tag == Iex_Const
+//..           && e->Iex.Const.con->tag == Ico_U32
+//..           && e->Iex.Const.con->Ico.U32 == 0;
+//.. }
+//.. 
+//.. /* Make a int reg-reg move. */
+//.. 
+//.. static X86Instr* mk_iMOVsd_RR ( HReg src, HReg dst )
+//.. {
+//..    vassert(hregClass(src) == HRcInt32);
+//..    vassert(hregClass(dst) == HRcInt32);
+//..    return X86Instr_Alu32R(Xalu_MOV, X86RMI_Reg(src), dst);
+//.. }
+//.. 
+//.. 
+//.. /* Make a vector reg-reg move. */
+//.. 
+//.. static X86Instr* mk_vMOVsd_RR ( HReg src, HReg dst )
+//.. {
+//..    vassert(hregClass(src) == HRcVec128);
+//..    vassert(hregClass(dst) == HRcVec128);
+//..    return X86Instr_SseReRg(Xsse_MOV, src, dst);
+//.. }
+//.. 
+//.. /* Advance/retreat %esp by n. */
+//.. 
+//.. static void add_to_esp ( ISelEnv* env, Int n )
+//.. {
+//..    vassert(n > 0 && n < 256 && (n%4) == 0);
+//..    addInstr(env, 
+//..             X86Instr_Alu32R(Xalu_ADD, X86RMI_Imm(n), hregX86_ESP()));
+//.. }
+//.. 
+//.. static void sub_from_esp ( ISelEnv* env, Int n )
+//.. {
+//..    vassert(n > 0 && n < 256 && (n%4) == 0);
+//..    addInstr(env, 
+//..             X86Instr_Alu32R(Xalu_SUB, X86RMI_Imm(n), hregX86_ESP()));
+//.. }
+//.. 
+//.. 
+//.. /* Given an amode, return one which references 4 bytes further
+//..    along. */
+//.. 
+//.. static X86AMode* advance4 ( X86AMode* am )
+//.. {
+//..    X86AMode* am4 = dopyX86AMode(am);
+//..    switch (am4->tag) {
+//..       case Xam_IRRS:
+//..          am4->Xam.IRRS.imm += 4; break;
+//..       case Xam_IR:
+//..          am4->Xam.IR.imm += 4; break;
+//..       default:
+//..          vpanic("advance4(x86,host)");
+//..    }
+//..    return am4;
+//.. }
+//.. 
+//.. 
+//.. /* Push an arg onto the host stack, in preparation for a call to a
+//..    helper function of some kind.  Returns the number of 32-bit words
+//..    pushed. */
+//.. 
+//.. static Int pushArg ( ISelEnv* env, IRExpr* arg )
+//.. {
+//..    IRType arg_ty = typeOfIRExpr(env->type_env, arg);
+//..    if (arg_ty == Ity_I32) {
+//..       addInstr(env, X86Instr_Push(iselIntExpr_RMI(env, arg)));
+//..       return 1;
+//..    } else 
+//..    if (arg_ty == Ity_I64) {
+//..       HReg rHi, rLo;
+//..       iselInt64Expr(&rHi, &rLo, env, arg);
+//..       addInstr(env, X86Instr_Push(X86RMI_Reg(rHi)));
+//..       addInstr(env, X86Instr_Push(X86RMI_Reg(rLo)));
+//..       return 2;
+//..    }
+//..    ppIRExpr(arg);
+//..    vpanic("pushArg(x86): can't handle arg of this type");
+//.. }
+//.. 
+//.. 
+//.. /* Complete the call to a helper function, by calling the 
+//..    helper and clearing the args off the stack. */
+//.. 
+//.. static 
+//.. void callHelperAndClearArgs ( ISelEnv* env, X86CondCode cc, 
+//..                               IRCallee* cee, Int n_arg_ws )
+//.. {
+//..    /* Complication.  Need to decide which reg to use as the fn address
+//..       pointer, in a way that doesn't trash regparm-passed
+//..       parameters. */
+//..    vassert(sizeof(void*) == 4);
+//.. 
+//..    addInstr(env, X86Instr_Call( cc, (UInt)cee->addr, cee->regparms));
+//..    if (n_arg_ws > 0)
+//..       add_to_esp(env, 4*n_arg_ws);
+//.. }
+//.. 
+//.. 
+//.. /* Used only in doHelperCall.  See big comment in doHelperCall re
+//..    handling of regparm args.  This function figures out whether
+//..    evaluation of an expression might require use of a fixed register.
+//..    If in doubt return True (safe but suboptimal).  
+//.. */
+//.. static
+//.. Bool mightRequireFixedRegs ( IRExpr* e )
+//.. {
+//..    switch (e->tag) {
+//..       case Iex_Tmp: case Iex_Const: case Iex_Get: 
+//..          return False;
+//..       default:
+//..          return True;
+//..    }
+//.. }
+//.. 
+//.. 
+//.. /* Do a complete function call.  guard is a Ity_Bit expression
+//..    indicating whether or not the call happens.  If guard==NULL, the
+//..    call is unconditional. */
+//.. 
+//.. static
+//.. void doHelperCall ( ISelEnv* env, 
+//..                     Bool passBBP, 
+//..                     IRExpr* guard, IRCallee* cee, IRExpr** args )
+//.. {
+//..    X86CondCode cc;
+//..    HReg        argregs[3];
+//..    HReg        tmpregs[3];
+//..    Bool        danger;
+//..    Int         not_done_yet, n_args, n_arg_ws, stack_limit, 
+//..                i, argreg, argregX;
+//.. 
+//..    /* Marshal args for a call, do the call, and clear the stack.
+//..       Complexities to consider:
+//.. 
+//..       * if passBBP is True, %ebp (the baseblock pointer) is to be
+//..         passed as the first arg.
+//.. 
+//..       * If the callee claims regparmness of 1, 2 or 3, we must pass the
+//..         first 1, 2 or 3 args in registers (EAX, EDX, and ECX
+//..         respectively).  To keep things relatively simple, only args of
+//..         type I32 may be passed as regparms -- just bomb out if anything
+//..         else turns up.  Clearly this depends on the front ends not
+//..         trying to pass any other types as regparms.  
+//..    */
+//.. 
+//..    /* 16 Nov 2004: the regparm handling is complicated by the
+//..       following problem.
+//.. 
+//..       Consider a call two a function with two regparm parameters:
+//..       f(e1,e2).  We need to compute e1 into %eax and e2 into %edx.
+//..       Suppose code is first generated to compute e1 into %eax.  Then,
+//..       code is generated to compute e2 into %edx.  Unfortunately, if
+//..       the latter code sequence uses %eax, it will trash the value of
+//..       e1 computed by the former sequence.  This could happen if (for
+//..       example) e2 itself involved a function call.  In the code below,
+//..       args are evaluated right-to-left, not left-to-right, but the
+//..       principle and the problem are the same.
+//.. 
+//..       One solution is to compute all regparm-bound args into vregs
+//..       first, and once they are all done, move them to the relevant
+//..       real regs.  This always gives correct code, but it also gives
+//..       a bunch of vreg-to-rreg moves which are usually redundant but 
+//..       are hard for the register allocator to get rid of.
+//.. 
+//..       A compromise is to first examine all regparm'd argument 
+//..       expressions.  If they are all so simple that it is clear 
+//..       they will be evaluated without use of any fixed registers,
+//..       use the old compute-directly-to-fixed-target scheme.  If not,
+//..       be safe and use the via-vregs scheme.
+//.. 
+//..       Note this requires being able to examine an expression and
+//..       determine whether or not evaluation of it might use a fixed
+//..       register.  That requires knowledge of how the rest of this
+//..       insn selector works.  Currently just the following 3 are 
+//..       regarded as safe -- hopefully they cover the majority of
+//..       arguments in practice: IRExpr_Tmp IRExpr_Const IRExpr_Get.
+//..    */
+//..    vassert(cee->regparms >= 0 && cee->regparms <= 3);
+//.. 
+//..    n_args = n_arg_ws = 0;
+//..    while (args[n_args]) n_args++;
+//.. 
+//..    not_done_yet = n_args;
+//..    if (passBBP)
+//..       not_done_yet++;
+//.. 
+//..    stack_limit = cee->regparms;
+//..    if (cee->regparms > 0 && passBBP) stack_limit--;
+//.. 
+//..    /* ------ BEGIN marshall all arguments ------ */
+//.. 
+//..    /* Push (R to L) the stack-passed args, [n_args-1 .. stack_limit] */
+//..    for (i = n_args-1; i >= stack_limit; i--) {
+//..       n_arg_ws += pushArg(env, args[i]);
+//..       not_done_yet--;
+//..    }
+//.. 
+//..    /* args [stack_limit-1 .. 0] and possibly %ebp are to be passed in
+//..       registers. */
+//.. 
+//..    if (cee->regparms > 0) {
+//.. 
+//..       /* ------ BEGIN deal with regparms ------ */
+//.. 
+//..       /* deal with regparms, not forgetting %ebp if needed. */
+//..       argregs[0] = hregX86_EAX();
+//..       argregs[1] = hregX86_EDX();
+//..       argregs[2] = hregX86_ECX();
+//..       tmpregs[0] = tmpregs[1] = tmpregs[2] = INVALID_HREG;
+//.. 
+//..       argreg = cee->regparms;
+//.. 
+//..       /* In keeping with big comment above, detect potential danger
+//..          and use the via-vregs scheme if needed. */
+//..       danger = False;
+//..       for (i = stack_limit-1; i >= 0; i--) {
+//..          if (mightRequireFixedRegs(args[i])) {
+//..             danger = True;
+//..             break;
+//..          }
+//..       }
+//.. 
+//..       if (danger) {
+//.. 
+//..          /* Move via temporaries */
+//..          argregX = argreg;
+//..          for (i = stack_limit-1; i >= 0; i--) {
+//.. 
+//..             if (0) {
+//..                vex_printf("x86 host: register param is complex: ");
+//..                ppIRExpr(args[i]);
+//..                vex_printf("\n");
+//..             }
+//.. 
+//..             argreg--;
+//..             vassert(argreg >= 0);
+//..             vassert(typeOfIRExpr(env->type_env, args[i]) == Ity_I32);
+//..             tmpregs[argreg] = iselIntExpr_R(env, args[i]);
+//..             not_done_yet--;
+//..          }
+//..          for (i = stack_limit-1; i >= 0; i--) {
+//..             argregX--;
+//..             vassert(argregX >= 0);
+//..             addInstr( env, mk_iMOVsd_RR( tmpregs[argregX], argregs[argregX] ) );
+//..          }
+//.. 
+//..       } else {
+//..          /* It's safe to compute all regparm args directly into their
+//..             target registers. */
+//..          for (i = stack_limit-1; i >= 0; i--) {
+//..             argreg--;
+//..             vassert(argreg >= 0);
+//..             vassert(typeOfIRExpr(env->type_env, args[i]) == Ity_I32);
+//..             addInstr(env, X86Instr_Alu32R(Xalu_MOV, 
+//..                                           iselIntExpr_RMI(env, args[i]),
+//..                                           argregs[argreg]));
+//..             not_done_yet--;
+//..          }
+//.. 
+//..       }
+//.. 
+//..       /* Not forgetting %ebp if needed. */
+//..       if (passBBP) {
+//..          vassert(argreg == 1);
+//..          addInstr(env, mk_iMOVsd_RR( hregX86_EBP(), argregs[0]));
+//..          not_done_yet--;
+//..       }
+//.. 
+//..       /* ------ END deal with regparms ------ */
+//.. 
+//..    } else {
+//.. 
+//..       /* No regparms.  Heave %ebp on the stack if needed. */
+//..       if (passBBP) {
+//..          addInstr(env, X86Instr_Push(X86RMI_Reg(hregX86_EBP())));
+//..          n_arg_ws++;
+//..          not_done_yet--;
+//..       }
+//.. 
+//..    }
+//.. 
+//..    vassert(not_done_yet == 0);
+//.. 
+//..    /* ------ END marshall all arguments ------ */
+//.. 
+//..    /* Now we can compute the condition.  We can't do it earlier
+//..       because the argument computations could trash the condition
+//..       codes.  Be a bit clever to handle the common case where the
+//..       guard is 1:Bit. */
+//..    cc = Xcc_ALWAYS;
+//..    if (guard) {
+//..       if (guard->tag == Iex_Const 
+//..           && guard->Iex.Const.con->tag == Ico_U1
+//..           && guard->Iex.Const.con->Ico.U1 == True) {
+//..          /* unconditional -- do nothing */
+//..       } else {
+//..          cc = iselCondCode( env, guard );
+//..       }
+//..    }
+//.. 
+//..    /* call the helper, and get the args off the stack afterwards. */
+//..    callHelperAndClearArgs( env, cc, cee, n_arg_ws );
+//.. }
+//.. 
+//.. 
+//.. /* Given a guest-state array descriptor, an index expression and a
+//..    bias, generate an X86AMode holding the relevant guest state
+//..    offset. */
+//.. 
+//.. static
+//.. X86AMode* genGuestArrayOffset ( ISelEnv* env, IRArray* descr, 
+//..                                 IRExpr* off, Int bias )
+//.. {
+//..    HReg tmp, roff;
+//..    Int  elemSz = sizeofIRType(descr->elemTy);
+//..    Int  nElems = descr->nElems;
+//.. 
+//..    /* throw out any cases not generated by an x86 front end.  In
+//..       theory there might be a day where we need to handle them -- if
+//..       we ever run non-x86-guest on x86 host. */
+//.. 
+//..    if (nElems != 8 || (elemSz != 1 && elemSz != 8))
+//..       vpanic("genGuestArrayOffset(x86 host)");
+//.. 
+//..    /* Compute off into a reg, %off.  Then return:
+//.. 
+//..          movl %off, %tmp
+//..          addl $bias, %tmp  (if bias != 0)
+//..          andl %tmp, 7
+//..          ... base(%ebp, %tmp, shift) ...
+//..    */
+//..    tmp  = newVRegI(env);
+//..    roff = iselIntExpr_R(env, off);
+//..    addInstr(env, mk_iMOVsd_RR(roff, tmp));
+//..    if (bias != 0) {
+//..       addInstr(env, 
+//..                X86Instr_Alu32R(Xalu_ADD, X86RMI_Imm(bias), tmp));
+//..    }
+//..    addInstr(env, 
+//..             X86Instr_Alu32R(Xalu_AND, X86RMI_Imm(7), tmp));
+//..    vassert(elemSz == 1 || elemSz == 8);
+//..    return
+//..       X86AMode_IRRS( descr->base, hregX86_EBP(), tmp,
+//..                                   elemSz==8 ? 3 : 0);
+//.. }
+//.. 
+//.. 
+//.. /* Mess with the FPU's rounding mode: set to the default rounding mode
+//..    (DEFAULT_FPUCW). */
+//.. static 
+//.. void set_FPU_rounding_default ( ISelEnv* env )
+//.. {
+//..    /* pushl $DEFAULT_FPUCW
+//..       fldcw 0(%esp)
+//..       addl $4, %esp 
+//..    */
+//..    X86AMode* zero_esp = X86AMode_IR(0, hregX86_ESP());
+//..    addInstr(env, X86Instr_Push(X86RMI_Imm(DEFAULT_FPUCW)));
+//..    addInstr(env, X86Instr_FpLdStCW(True/*load*/, zero_esp));
+//..    add_to_esp(env, 4);
+//.. }
+//.. 
+//.. 
+//.. /* Mess with the FPU's rounding mode: 'mode' is an I32-typed
+//..    expression denoting a value in the range 0 .. 3, indicating a round
+//..    mode encoded as per type IRRoundingMode.  Set the x87 FPU to have
+//..    the same rounding.
+//.. */
+//.. static
+//.. void set_FPU_rounding_mode ( ISelEnv* env, IRExpr* mode )
+//.. {
+//..    HReg rrm  = iselIntExpr_R(env, mode);
+//..    HReg rrm2 = newVRegI(env);
+//..    X86AMode* zero_esp = X86AMode_IR(0, hregX86_ESP());
+//.. 
+//..    /* movl  %rrm, %rrm2
+//..       andl  $3, %rrm2   -- shouldn't be needed; paranoia
+//..       shll  $10, %rrm2
+//..       orl   $DEFAULT_FPUCW, %rrm2
+//..       pushl %rrm2
+//..       fldcw 0(%esp)
+//..       addl  $4, %esp
+//..    */
+//..    addInstr(env, mk_iMOVsd_RR(rrm, rrm2));
+//..    addInstr(env, X86Instr_Alu32R(Xalu_AND, X86RMI_Imm(3), rrm2));
+//..    addInstr(env, X86Instr_Sh32(Xsh_SHL, 10, X86RM_Reg(rrm2)));
+//..    addInstr(env, X86Instr_Alu32R(Xalu_OR, X86RMI_Imm(DEFAULT_FPUCW), rrm2));
+//..    addInstr(env, X86Instr_Push(X86RMI_Reg(rrm2)));
+//..    addInstr(env, X86Instr_FpLdStCW(True/*load*/, zero_esp));
+//..    add_to_esp(env, 4);
+//.. }
+//.. 
+//.. 
+//.. /* Generate !src into a new vector register, and be sure that the code
+//..    is SSE1 compatible.  Amazing that Intel doesn't offer a less crappy
+//..    way to do this. 
+//.. */
+//.. static HReg do_sse_Not128 ( ISelEnv* env, HReg src )
+//.. {
+//..    HReg dst = newVRegV(env);
+//..    /* Set dst to zero.  Not strictly necessary, but the idea of doing
+//..       a FP comparison on whatever junk happens to be floating around
+//..       in it is just too scary. */
+//..    addInstr(env, X86Instr_SseReRg(Xsse_XOR, dst, dst));
+//..    /* And now make it all 1s ... */
+//..    addInstr(env, X86Instr_Sse32Fx4(Xsse_CMPEQF, dst, dst));
+//..    /* Finally, xor 'src' into it. */
+//..    addInstr(env, X86Instr_SseReRg(Xsse_XOR, src, dst));
+//..    return dst;
+//.. }
+//.. 
+//.. 
+//.. /* Round an x87 FPU value to 53-bit-mantissa precision, to be used
+//..    after most non-simple FPU operations (simple = +, -, *, / and
+//..    sqrt).
+//.. 
+//..    This could be done a lot more efficiently if needed, by loading
+//..    zero and adding it to the value to be rounded (fldz ; faddp?).
+//.. */
+//.. static void roundToF64 ( ISelEnv* env, HReg reg )
+//.. {
+//..    X86AMode* zero_esp = X86AMode_IR(0, hregX86_ESP());
+//..    sub_from_esp(env, 8);
+//..    addInstr(env, X86Instr_FpLdSt(False/*store*/, 8, reg, zero_esp));
+//..    addInstr(env, X86Instr_FpLdSt(True/*load*/, 8, reg, zero_esp));
+//..    add_to_esp(env, 8);
+//.. }
+//.. 
+//.. 
+//.. /*---------------------------------------------------------*/
+//.. /*--- ISEL: Integer expressions (32/16/8 bit)           ---*/
+//.. /*---------------------------------------------------------*/
+//.. 
+//.. /* Select insns for an integer-typed expression, and add them to the
+//..    code list.  Return a reg holding the result.  This reg will be a
+//..    virtual register.  THE RETURNED REG MUST NOT BE MODIFIED.  If you
+//..    want to modify it, ask for a new vreg, copy it in there, and modify
+//..    the copy.  The register allocator will do its best to map both
+//..    vregs to the same real register, so the copies will often disappear
+//..    later in the game.
+//.. 
+//..    This should handle expressions of 32, 16 and 8-bit type.  All
+//..    results are returned in a 32-bit register.  For 16- and 8-bit
+//..    expressions, the upper 16/24 bits are arbitrary, so you should mask
+//..    or sign extend partial values if necessary.
+//.. */
+//.. 
+//.. static HReg iselIntExpr_R ( ISelEnv* env, IRExpr* e )
+//.. {
+//..    HReg r = iselIntExpr_R_wrk(env, e);
+//..    /* sanity checks ... */
+//.. #  if 0
+//..    vex_printf("\n"); ppIRExpr(e); vex_printf("\n");
+//.. #  endif
+//..    vassert(hregClass(r) == HRcInt32);
+//..    vassert(hregIsVirtual(r));
+//..    return r;
+//.. }
+//.. 
+//.. /* DO NOT CALL THIS DIRECTLY ! */
+//.. static HReg iselIntExpr_R_wrk ( ISelEnv* env, IRExpr* e )
+//.. {
+//..    MatchInfo mi;
+//..    DECLARE_PATTERN(p_32to1_then_1Uto8);
+//.. 
+//..    IRType ty = typeOfIRExpr(env->type_env,e);
+//..    vassert(ty == Ity_I32 || Ity_I16 || Ity_I8);
+//.. 
+//..    switch (e->tag) {
+//.. 
+//..    /* --------- TEMP --------- */
+//..    case Iex_Tmp: {
+//..       return lookupIRTemp(env, e->Iex.Tmp.tmp);
+//..    }
+//.. 
+//..    /* --------- LOAD --------- */
+//..    case Iex_LDle: {
+//..       HReg dst = newVRegI(env);
+//..       X86AMode* amode = iselIntExpr_AMode ( env, e->Iex.LDle.addr );
+//..       if (ty == Ity_I32) {
+//..          addInstr(env, X86Instr_Alu32R(Xalu_MOV,
+//..                                        X86RMI_Mem(amode), dst) );
+//..          return dst;
+//..       }
+//..       if (ty == Ity_I16) {
+//..          addInstr(env, X86Instr_LoadEX(2,False,amode,dst));
+//..          return dst;
+//..       }
+//..       if (ty == Ity_I8) {
+//..          addInstr(env, X86Instr_LoadEX(1,False,amode,dst));
+//..          return dst;
+//..       }
+//..       break;
+//..    }
+//.. 
+//..    /* --------- BINARY OP --------- */
+//..    case Iex_Binop: {
+//..       X86AluOp   aluOp;
+//..       X86ShiftOp shOp;
+//.. 
+//..       /* Pattern: Sub32(0,x) */
+//..       if (e->Iex.Binop.op == Iop_Sub32 && isZero32(e->Iex.Binop.arg1)) {
+//..          HReg dst = newVRegI(env);
+//..          HReg reg = iselIntExpr_R(env, e->Iex.Binop.arg2);
+//..          addInstr(env, mk_iMOVsd_RR(reg,dst));
+//..          addInstr(env, X86Instr_Unary32(Xun_NEG,X86RM_Reg(dst)));
+//..          return dst;
+//..       }
+//.. 
+//..       /* Is it an addition or logical style op? */
+//..       switch (e->Iex.Binop.op) {
+//..          case Iop_Add8: case Iop_Add16: case Iop_Add32:
+//..             aluOp = Xalu_ADD; break;
+//..          case Iop_Sub8: case Iop_Sub16: case Iop_Sub32: 
+//..             aluOp = Xalu_SUB; break;
+//..          case Iop_And8: case Iop_And16: case Iop_And32: 
+//..             aluOp = Xalu_AND; break;
+//..          case Iop_Or8: case Iop_Or16: case Iop_Or32:  
+//..             aluOp = Xalu_OR; break;
+//..          case Iop_Xor8: case Iop_Xor16: case Iop_Xor32: 
+//..             aluOp = Xalu_XOR; break;
+//..          case Iop_Mul16: case Iop_Mul32: 
+//..             aluOp = Xalu_MUL; break;
+//..          default:
+//..             aluOp = Xalu_INVALID; break;
+//..       }
+//..       /* For commutative ops we assume any literal
+//..          values are on the second operand. */
+//..       if (aluOp != Xalu_INVALID) {
+//..          HReg dst    = newVRegI(env);
+//..          HReg reg    = iselIntExpr_R(env, e->Iex.Binop.arg1);
+//..          X86RMI* rmi = iselIntExpr_RMI(env, e->Iex.Binop.arg2);
+//..          addInstr(env, mk_iMOVsd_RR(reg,dst));
+//..          addInstr(env, X86Instr_Alu32R(aluOp, rmi, dst));
+//..          return dst;
+//..       }
+//..       /* Could do better here; forcing the first arg into a reg
+//..          isn't always clever.
+//..          -- t70 = Xor32(And32(Xor32(LDle:I32(Add32(t41,0xFFFFFFA0:I32)),
+//..                         LDle:I32(Add32(t41,0xFFFFFFA4:I32))),LDle:I32(Add32(
+//..                         t41,0xFFFFFFA8:I32))),LDle:I32(Add32(t41,0xFFFFFFA0:I32)))
+//..             movl 0xFFFFFFA0(%vr41),%vr107
+//..             movl 0xFFFFFFA4(%vr41),%vr108
+//..             movl %vr107,%vr106
+//..             xorl %vr108,%vr106
+//..             movl 0xFFFFFFA8(%vr41),%vr109
+//..             movl %vr106,%vr105
+//..             andl %vr109,%vr105
+//..             movl 0xFFFFFFA0(%vr41),%vr110
+//..             movl %vr105,%vr104
+//..             xorl %vr110,%vr104
+//..             movl %vr104,%vr70
+//..       */
+//.. 
+//..       /* Perhaps a shift op? */
+//..       switch (e->Iex.Binop.op) {
+//..          case Iop_Shl32: case Iop_Shl16: case Iop_Shl8:
+//..             shOp = Xsh_SHL; break;
+//..          case Iop_Shr32: case Iop_Shr16: case Iop_Shr8: 
+//..             shOp = Xsh_SHR; break;
+//..          case Iop_Sar32: case Iop_Sar16: case Iop_Sar8: 
+//..             shOp = Xsh_SAR; break;
+//..          default:
+//..             shOp = Xsh_INVALID; break;
+//..       }
+//..       if (shOp != Xsh_INVALID) {
+//..          HReg dst = newVRegI(env);
+//.. 
+//..          /* regL = the value to be shifted */
+//..          HReg regL   = iselIntExpr_R(env, e->Iex.Binop.arg1);
+//..          addInstr(env, mk_iMOVsd_RR(regL,dst));
+//.. 
+//..          /* Do any necessary widening for 16/8 bit operands */
+//..          switch (e->Iex.Binop.op) {
+//..             case Iop_Shr8:
+//..                addInstr(env, X86Instr_Alu32R(
+//..                                 Xalu_AND, X86RMI_Imm(0xFF), dst));
+//..                break;
+//..             case Iop_Shr16:
+//..                addInstr(env, X86Instr_Alu32R(
+//..                                 Xalu_AND, X86RMI_Imm(0xFFFF), dst));
+//..                break;
+//..             case Iop_Sar8:
+//..                addInstr(env, X86Instr_Sh32(Xsh_SHL, 24, X86RM_Reg(dst)));
+//..                addInstr(env, X86Instr_Sh32(Xsh_SAR, 24, X86RM_Reg(dst)));
+//..                break;
+//..             case Iop_Sar16:
+//..                addInstr(env, X86Instr_Sh32(Xsh_SHL, 16, X86RM_Reg(dst)));
+//..                addInstr(env, X86Instr_Sh32(Xsh_SAR, 16, X86RM_Reg(dst)));
+//..                break;
+//..             default: break;
+//..          }
+//.. 
+//..          /* Now consider the shift amount.  If it's a literal, we
+//..             can do a much better job than the general case. */
+//..          if (e->Iex.Binop.arg2->tag == Iex_Const) {
+//..             /* assert that the IR is well-typed */
+//..             Int nshift;
+//..             vassert(e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U8);
+//..             nshift = e->Iex.Binop.arg2->Iex.Const.con->Ico.U8;
+//..       vassert(nshift >= 0);
+//..       if (nshift > 0)
+//..                /* Can't allow nshift==0 since that means %cl */
+//..                addInstr(env, X86Instr_Sh32(
+//..                                 shOp, 
+//..                                 nshift,
+//..                                 X86RM_Reg(dst)));
+//..          } else {
+//..             /* General case; we have to force the amount into %cl. */
+//..             HReg regR = iselIntExpr_R(env, e->Iex.Binop.arg2);
+//..             addInstr(env, mk_iMOVsd_RR(regR,hregX86_ECX()));
+//..             addInstr(env, X86Instr_Sh32(shOp, 0/* %cl */, X86RM_Reg(dst)));
+//..          }
+//..          return dst;
+//..       }
+//.. 
+//..       /* Handle misc other ops. */
+//..       if (e->Iex.Binop.op == Iop_8HLto16) {
+//..          HReg hi8  = newVRegI(env);
+//..          HReg lo8  = newVRegI(env);
+//..          HReg hi8s = iselIntExpr_R(env, e->Iex.Binop.arg1);
+//..          HReg lo8s = iselIntExpr_R(env, e->Iex.Binop.arg2);
+//..          addInstr(env, mk_iMOVsd_RR(hi8s, hi8));
+//..          addInstr(env, mk_iMOVsd_RR(lo8s, lo8));
+//..          addInstr(env, X86Instr_Sh32(Xsh_SHL, 8, X86RM_Reg(hi8)));
+//..          addInstr(env, X86Instr_Alu32R(Xalu_AND, X86RMI_Imm(0xFF), lo8));
+//..          addInstr(env, X86Instr_Alu32R(Xalu_OR, X86RMI_Reg(lo8), hi8));
+//..          return hi8;
+//..       }
+//.. 
+//..       if (e->Iex.Binop.op == Iop_16HLto32) {
+//..          HReg hi16  = newVRegI(env);
+//..          HReg lo16  = newVRegI(env);
+//..          HReg hi16s = iselIntExpr_R(env, e->Iex.Binop.arg1);
+//..          HReg lo16s = iselIntExpr_R(env, e->Iex.Binop.arg2);
+//..          addInstr(env, mk_iMOVsd_RR(hi16s, hi16));
+//..          addInstr(env, mk_iMOVsd_RR(lo16s, lo16));
+//..          addInstr(env, X86Instr_Sh32(Xsh_SHL, 16, X86RM_Reg(hi16)));
+//..          addInstr(env, X86Instr_Alu32R(Xalu_AND, X86RMI_Imm(0xFFFF), lo16));
+//..          addInstr(env, X86Instr_Alu32R(Xalu_OR, X86RMI_Reg(lo16), hi16));
+//..          return hi16;
+//..       }
+//.. 
+//..       if (e->Iex.Binop.op == Iop_MullS16 || e->Iex.Binop.op == Iop_MullS8
+//..           || e->Iex.Binop.op == Iop_MullU16 || e->Iex.Binop.op == Iop_MullU8) {
+//..          HReg a16   = newVRegI(env);
+//..          HReg b16   = newVRegI(env);
+//..          HReg a16s  = iselIntExpr_R(env, e->Iex.Binop.arg1);
+//..          HReg b16s  = iselIntExpr_R(env, e->Iex.Binop.arg2);
+//..          Int  shift = (e->Iex.Binop.op == Iop_MullS8 
+//..                        || e->Iex.Binop.op == Iop_MullU8)
+//..                          ? 24 : 16;
+//..          X86ShiftOp shr_op = (e->Iex.Binop.op == Iop_MullS8 
+//..                               || e->Iex.Binop.op == Iop_MullS16)
+//..                                 ? Xsh_SAR : Xsh_SHR;
+//.. 
+//..          addInstr(env, mk_iMOVsd_RR(a16s, a16));
+//..          addInstr(env, mk_iMOVsd_RR(b16s, b16));
+//..          addInstr(env, X86Instr_Sh32(Xsh_SHL, shift, X86RM_Reg(a16)));
+//..          addInstr(env, X86Instr_Sh32(Xsh_SHL, shift, X86RM_Reg(b16)));
+//..          addInstr(env, X86Instr_Sh32(shr_op,  shift, X86RM_Reg(a16)));
+//..          addInstr(env, X86Instr_Sh32(shr_op,  shift, X86RM_Reg(b16)));
+//..          addInstr(env, X86Instr_Alu32R(Xalu_MUL, X86RMI_Reg(a16), b16));
+//..          return b16;
+//..       }
+//.. 
+//..       if (e->Iex.Binop.op == Iop_CmpF64) {
+//..          HReg fL = iselDblExpr(env, e->Iex.Binop.arg1);
+//..          HReg fR = iselDblExpr(env, e->Iex.Binop.arg2);
+//..          HReg dst = newVRegI(env);
+//..          addInstr(env, X86Instr_FpCmp(fL,fR,dst));
+//..          /* shift this right 8 bits so as to conform to CmpF64
+//..             definition. */
+//..          addInstr(env, X86Instr_Sh32(Xsh_SHR, 8, X86RM_Reg(dst)));
+//..          return dst;
+//..       }
+//.. 
+//..       if (e->Iex.Binop.op == Iop_F64toI32 || e->Iex.Binop.op == Iop_F64toI16) {
+//..          Int  sz  = e->Iex.Binop.op == Iop_F64toI16 ? 2 : 4;
+//..          HReg rf  = iselDblExpr(env, e->Iex.Binop.arg2);
+//..          HReg dst = newVRegI(env);
+//.. 
+//..          /* Used several times ... */
+//..          X86AMode* zero_esp = X86AMode_IR(0, hregX86_ESP());
+//.. 
+//..    /* rf now holds the value to be converted, and rrm holds the
+//..       rounding mode value, encoded as per the IRRoundingMode
+//..       enum.  The first thing to do is set the FPU's rounding
+//..       mode accordingly. */
+//.. 
+//..          /* Create a space for the format conversion. */
+//..          /* subl $4, %esp */
+//..          sub_from_esp(env, 4);
+//.. 
+//..    /* Set host rounding mode */
+//..    set_FPU_rounding_mode( env, e->Iex.Binop.arg1 );
+//.. 
+//..          /* gistw/l %rf, 0(%esp) */
+//..          addInstr(env, X86Instr_FpLdStI(False/*store*/, sz, rf, zero_esp));
+//.. 
+//..          if (sz == 2) {
+//..             /* movzwl 0(%esp), %dst */
+//..             addInstr(env, X86Instr_LoadEX(2,False,zero_esp,dst));
+//..          } else {
+//..             /* movl 0(%esp), %dst */
+//..             vassert(sz == 4);
+//..             addInstr(env, X86Instr_Alu32R(
+//..                              Xalu_MOV, X86RMI_Mem(zero_esp), dst));
+//..          }
+//.. 
+//..    /* Restore default FPU rounding. */
+//..          set_FPU_rounding_default( env );
+//.. 
+//..          /* addl $4, %esp */
+//..    add_to_esp(env, 4);
+//..          return dst;
+//..       }
+//.. 
+//..       /* C3210 flags following FPU partial remainder (fprem), both
+//..          IEEE compliant (PREM1) and non-IEEE compliant (PREM). */
+//..       if (e->Iex.Binop.op == Iop_PRemC3210F64
+//..           || e->Iex.Binop.op == Iop_PRem1C3210F64) {
+//..          HReg junk = newVRegF(env);
+//..          HReg dst  = newVRegI(env);
+//..          HReg srcL = iselDblExpr(env, e->Iex.Binop.arg1);
+//..          HReg srcR = iselDblExpr(env, e->Iex.Binop.arg2);
+//..          addInstr(env, X86Instr_FpBinary(
+//..                            e->Iex.Binop.op==Iop_PRemC3210F64 
+//..                               ? Xfp_PREM : Xfp_PREM1,
+//..                            srcL,srcR,junk
+//..                  ));
+//..          /* The previous pseudo-insn will have left the FPU's C3210
+//..             flags set correctly.  So bag them. */
+//..          addInstr(env, X86Instr_FpStSW_AX());
+//..          addInstr(env, mk_iMOVsd_RR(hregX86_EAX(), dst));
+//..    addInstr(env, X86Instr_Alu32R(Xalu_AND, X86RMI_Imm(0x4700), dst));
+//..          return dst;
+//..       }
+//.. 
+//..       break;
+//..    }
+//.. 
+//..    /* --------- UNARY OP --------- */
+//..    case Iex_Unop: {
+//..       /* 1Uto8(32to1(expr32)) */
+//..       DEFINE_PATTERN(p_32to1_then_1Uto8,
+//..                      unop(Iop_1Uto8,unop(Iop_32to1,bind(0))));
+//..       if (matchIRExpr(&mi,p_32to1_then_1Uto8,e)) {
+//..          IRExpr* expr32 = mi.bindee[0];
+//..          HReg dst = newVRegI(env);
+//..          HReg src = iselIntExpr_R(env, expr32);
+//..          addInstr(env, mk_iMOVsd_RR(src,dst) );
+//..          addInstr(env, X86Instr_Alu32R(Xalu_AND,
+//..                                        X86RMI_Imm(1), dst));
+//..          return dst;
+//..       }
+//.. 
+//..       /* 16Uto32(LDle(expr32)) */
+//..       {
+//..          DECLARE_PATTERN(p_LDle16_then_16Uto32);
+//..          DEFINE_PATTERN(p_LDle16_then_16Uto32,
+//..             unop(Iop_16Uto32,IRExpr_LDle(Ity_I16,bind(0))) );
+//..          if (matchIRExpr(&mi,p_LDle16_then_16Uto32,e)) {
+//..             HReg dst = newVRegI(env);
+//..             X86AMode* amode = iselIntExpr_AMode ( env, mi.bindee[0] );
+//..             addInstr(env, X86Instr_LoadEX(2,False,amode,dst));
+//..             return dst;
+//..          }
+//..       }
+//.. 
+//..       switch (e->Iex.Unop.op) {
+//..          case Iop_8Uto16:
+//..          case Iop_8Uto32:
+//..          case Iop_16Uto32: {
+//..             HReg dst = newVRegI(env);
+//..             HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
+//..             UInt mask = e->Iex.Unop.op==Iop_16Uto32 ? 0xFFFF : 0xFF;
+//..             addInstr(env, mk_iMOVsd_RR(src,dst) );
+//..             addInstr(env, X86Instr_Alu32R(Xalu_AND,
+//..                                           X86RMI_Imm(mask), dst));
+//..             return dst;
+//..          }
+//..          case Iop_8Sto16:
+//..          case Iop_8Sto32:
+//..          case Iop_16Sto32: {
+//..             HReg dst = newVRegI(env);
+//..             HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
+//..             UInt amt = e->Iex.Unop.op==Iop_16Sto32 ? 16 : 24;
+//..             addInstr(env, mk_iMOVsd_RR(src,dst) );
+//..             addInstr(env, X86Instr_Sh32(Xsh_SHL, amt, X86RM_Reg(dst)));
+//..             addInstr(env, X86Instr_Sh32(Xsh_SAR, amt, X86RM_Reg(dst)));
+//..             return dst;
+//..          }
+//..    case Iop_Not8:
+//..    case Iop_Not16:
+//..          case Iop_Not32: {
+//..             HReg dst = newVRegI(env);
+//..             HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
+//..             addInstr(env, mk_iMOVsd_RR(src,dst) );
+//..             addInstr(env, X86Instr_Unary32(Xun_NOT,X86RM_Reg(dst)));
+//..             return dst;
+//..          }
+//..          case Iop_64HIto32: {
+//..             HReg rHi, rLo;
+//..             iselInt64Expr(&rHi,&rLo, env, e->Iex.Unop.arg);
+//..             return rHi; /* and abandon rLo .. poor wee thing :-) */
+//..          }
+//..          case Iop_64to32: {
+//..             HReg rHi, rLo;
+//..             iselInt64Expr(&rHi,&rLo, env, e->Iex.Unop.arg);
+//..             return rLo; /* similar stupid comment to the above ... */
+//..          }
+//..          case Iop_16HIto8:
+//..          case Iop_32HIto16: {
+//..             HReg dst  = newVRegI(env);
+//..             HReg src  = iselIntExpr_R(env, e->Iex.Unop.arg);
+//..             Int shift = e->Iex.Unop.op == Iop_16HIto8 ? 8 : 16;
+//..             addInstr(env, mk_iMOVsd_RR(src,dst) );
+//..             addInstr(env, X86Instr_Sh32(Xsh_SHR, shift, X86RM_Reg(dst)));
+//..             return dst;
+//..          }
+//..          case Iop_1Uto32:
+//..          case Iop_1Uto8: {
+//..             HReg dst         = newVRegI(env);
+//..             X86CondCode cond = iselCondCode(env, e->Iex.Unop.arg);
+//..             addInstr(env, X86Instr_Set32(cond,dst));
+//..             return dst;
+//..          }
+//..          case Iop_1Sto8:
+//..          case Iop_1Sto16:
+//..          case Iop_1Sto32: {
+//..             /* could do better than this, but for now ... */
+//..             HReg dst         = newVRegI(env);
+//..             X86CondCode cond = iselCondCode(env, e->Iex.Unop.arg);
+//..             addInstr(env, X86Instr_Set32(cond,dst));
+//..             addInstr(env, X86Instr_Sh32(Xsh_SHL, 31, X86RM_Reg(dst)));
+//..             addInstr(env, X86Instr_Sh32(Xsh_SAR, 31, X86RM_Reg(dst)));
+//..             return dst;
+//..          }
+//..          case Iop_Ctz32: {
+//..             /* Count trailing zeroes, implemented by x86 'bsfl' */
+//..             HReg dst = newVRegI(env);
+//..             HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
+//..             addInstr(env, X86Instr_Bsfr32(True,src,dst));
+//..             return dst;
+//..          }
+//..          case Iop_Clz32: {
+//..             /* Count leading zeroes.  Do 'bsrl' to establish the index
+//..                of the highest set bit, and subtract that value from
+//..                31. */
+//..             HReg tmp = newVRegI(env);
+//..             HReg dst = newVRegI(env);
+//..             HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
+//..             addInstr(env, X86Instr_Bsfr32(False,src,tmp));
+//..             addInstr(env, X86Instr_Alu32R(Xalu_MOV, 
+//..                                           X86RMI_Imm(31), dst));
+//..             addInstr(env, X86Instr_Alu32R(Xalu_SUB,
+//..                                           X86RMI_Reg(tmp), dst));
+//..             return dst;
+//..          }
+//.. 
+//..          case Iop_128to32: {
+//..             HReg      dst  = newVRegI(env);
+//..             HReg      vec  = iselVecExpr(env, e->Iex.Unop.arg);
+//..             X86AMode* esp0 = X86AMode_IR(0, hregX86_ESP());
+//..             sub_from_esp(env, 16);
+//..             addInstr(env, X86Instr_SseLdSt(False/*store*/, vec, esp0));
+//..             addInstr(env, X86Instr_Alu32R( Xalu_MOV, X86RMI_Mem(esp0), dst ));
+//..             add_to_esp(env, 16);
+//..             return dst;
+//..          }
+//.. 
+//..          case Iop_16to8:
+//..          case Iop_32to8:
+//..          case Iop_32to16:
+//..             /* These are no-ops. */
+//..             return iselIntExpr_R(env, e->Iex.Unop.arg);
+//.. 
+//..          default: 
+//..             break;
+//..       }
+//..       break;
+//..    }
+//.. 
+//..    /* --------- GET --------- */
+//..    case Iex_Get: {
+//..       if (ty == Ity_I32) {
+//..          HReg dst = newVRegI(env);
+//..          addInstr(env, X86Instr_Alu32R(
+//..                           Xalu_MOV, 
+//..                           X86RMI_Mem(X86AMode_IR(e->Iex.Get.offset,
+//..                                                  hregX86_EBP())),
+//..                           dst));
+//..          return dst;
+//..       }
+//..       if (ty == Ity_I8 || ty == Ity_I16) {
+//..          HReg dst = newVRegI(env);
+//..          addInstr(env, X86Instr_LoadEX(
+//..                           ty==Ity_I8 ? 1 : 2,
+//..                           False,
+//..                           X86AMode_IR(e->Iex.Get.offset,hregX86_EBP()),
+//..                           dst));
+//..          return dst;
+//..       }
+//..       break;
+//..    }
+//.. 
+//..    case Iex_GetI: {
+//..       X86AMode* am 
+//..          = genGuestArrayOffset(
+//..               env, e->Iex.GetI.descr, 
+//..                    e->Iex.GetI.ix, e->Iex.GetI.bias );
+//..       HReg dst = newVRegI(env);
+//..       if (ty == Ity_I8) {
+//..          addInstr(env, X86Instr_LoadEX( 1, False, am, dst ));
+//..          return dst;
+//..       }
+//..       break;
+//..    }
+//.. 
+//..    /* --------- CCALL --------- */
+//..    case Iex_CCall: {
+//..       HReg    dst = newVRegI(env);
+//..       vassert(ty == Ity_I32);
+//.. 
+//..       /* be very restrictive for now.  Only 32/64-bit ints allowed
+//..          for args, and 32 bits for return type. */
+//..       if (e->Iex.CCall.retty != Ity_I32)
+//..          goto irreducible;
+//.. 
+//..       /* Marshal args, do the call, clear stack. */
+//..       doHelperCall( env, False, NULL, e->Iex.CCall.cee, e->Iex.CCall.args );
+//.. 
+//..       addInstr(env, mk_iMOVsd_RR(hregX86_EAX(), dst));
+//..       return dst;
+//..    }
+//.. 
+//..    /* --------- LITERAL --------- */
+//..    /* 32/16/8-bit literals */
+//..    case Iex_Const: {
+//..       X86RMI* rmi = iselIntExpr_RMI ( env, e );
+//..       HReg    r   = newVRegI(env);
+//..       addInstr(env, X86Instr_Alu32R(Xalu_MOV, rmi, r));
+//..       return r;
+//..    }
+//.. 
+//..    /* --------- MULTIPLEX --------- */
+//..    case Iex_Mux0X: {
+//..      if ((ty == Ity_I32 || ty == Ity_I16 || ty == Ity_I8)
+//..          && typeOfIRExpr(env->type_env,e->Iex.Mux0X.cond) == Ity_I8) {
+//..         HReg r8;
+//..         HReg rX   = iselIntExpr_R(env, e->Iex.Mux0X.exprX);
+//..         X86RM* r0 = iselIntExpr_RM(env, e->Iex.Mux0X.expr0);
+//..         HReg dst = newVRegI(env);
+//..         addInstr(env, mk_iMOVsd_RR(rX,dst));
+//..         r8 = iselIntExpr_R(env, e->Iex.Mux0X.cond);
+//..         addInstr(env, X86Instr_Test32(X86RI_Imm(0xFF), X86RM_Reg(r8)));
+//..         addInstr(env, X86Instr_CMov32(Xcc_Z,r0,dst));
+//..         return dst;
+//..       }
+//..       break;
+//..    }
+//.. 
+//..    default: 
+//..    break;
+//..    } /* switch (e->tag) */
+//.. 
+//..    /* We get here if no pattern matched. */
+//..   irreducible:
+//..    ppIRExpr(e);
+//..    vpanic("iselIntExpr_R: cannot reduce tree");
+//.. }
+//.. 
+//.. 
+//.. /*---------------------------------------------------------*/
+//.. /*--- ISEL: Integer expression auxiliaries              ---*/
+//.. /*---------------------------------------------------------*/
+//.. 
+//.. /* --------------------- AMODEs --------------------- */
+//.. 
+//.. /* Return an AMode which computes the value of the specified
+//..    expression, possibly also adding insns to the code list as a
+//..    result.  The expression may only be a 32-bit one.
+//.. */
+//.. 
+//.. static Bool sane_AMode ( X86AMode* am )
+//.. {
+//..    switch (am->tag) {
+//..       case Xam_IR:
+//..          return hregClass(am->Xam.IR.reg) == HRcInt32
+//..                 && (hregIsVirtual(am->Xam.IR.reg)
+//..                     || am->Xam.IR.reg == hregX86_EBP());
+//..       case Xam_IRRS:
+//..          return hregClass(am->Xam.IRRS.base) == HRcInt32
+//..                 && hregIsVirtual(am->Xam.IRRS.base)
+//..                 && hregClass(am->Xam.IRRS.index) == HRcInt32
+//..                 && hregIsVirtual(am->Xam.IRRS.index);
+//..       default:
+//..         vpanic("sane_AMode: unknown x86 amode tag");
+//..    }
+//.. }
+//.. 
+//.. static X86AMode* iselIntExpr_AMode ( ISelEnv* env, IRExpr* e )
+//.. {
+//..    X86AMode* am = iselIntExpr_AMode_wrk(env, e);
+//..    vassert(sane_AMode(am));
+//..    return am;
+//.. }
+//.. 
+//.. /* DO NOT CALL THIS DIRECTLY ! */
+//.. static X86AMode* iselIntExpr_AMode_wrk ( ISelEnv* env, IRExpr* e )
+//.. {
+//..    IRType ty = typeOfIRExpr(env->type_env,e);
+//..    vassert(ty == Ity_I32);
+//.. 
+//..    /* Add32(expr1, Shl32(expr2, imm)) */
+//..    if (e->tag == Iex_Binop
+//..        && e->Iex.Binop.op == Iop_Add32
+//..        && e->Iex.Binop.arg2->tag == Iex_Binop
+//..        && e->Iex.Binop.arg2->Iex.Binop.op == Iop_Shl32
+//..        && e->Iex.Binop.arg2->Iex.Binop.arg2->tag == Iex_Const
+//..        && e->Iex.Binop.arg2->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U8) {
+//..       UInt shift = e->Iex.Binop.arg2->Iex.Binop.arg2->Iex.Const.con->Ico.U8;
+//..       if (shift == 1 || shift == 2 || shift == 3) {
+//..          HReg r1 = iselIntExpr_R(env, e->Iex.Binop.arg1);
+//..          HReg r2 = iselIntExpr_R(env, e->Iex.Binop.arg2->Iex.Binop.arg1 );
+//..          return X86AMode_IRRS(0, r1, r2, shift);
+//..       }
+//..    }
+//.. 
+//..    /* Add32(expr,i) */
+//..    if (e->tag == Iex_Binop 
+//..        && e->Iex.Binop.op == Iop_Add32
+//..        && e->Iex.Binop.arg2->tag == Iex_Const
+//..        && e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U32) {
+//..       HReg r1 = iselIntExpr_R(env,  e->Iex.Binop.arg1);
+//..       return X86AMode_IR(e->Iex.Binop.arg2->Iex.Const.con->Ico.U32, r1);
+//..    }
+//.. 
+//..    /* Doesn't match anything in particular.  Generate it into
+//..       a register and use that. */
+//..    {
+//..       HReg r1 = iselIntExpr_R(env, e);
+//..       return X86AMode_IR(0, r1);
+//..    }
+//.. }
+//.. 
+//.. 
+//.. /* --------------------- RMIs --------------------- */
+//.. 
+//.. /* Similarly, calculate an expression into an X86RMI operand.  As with
+//..    iselIntExpr_R, the expression can have type 32, 16 or 8 bits.  */
+//.. 
+//.. static X86RMI* iselIntExpr_RMI ( ISelEnv* env, IRExpr* e )
+//.. {
+//..    X86RMI* rmi = iselIntExpr_RMI_wrk(env, e);
+//..    /* sanity checks ... */
+//..    switch (rmi->tag) {
+//..       case Xrmi_Imm:
+//..          return rmi;
+//..       case Xrmi_Reg:
+//..          vassert(hregClass(rmi->Xrmi.Reg.reg) == HRcInt32);
+//..          vassert(hregIsVirtual(rmi->Xrmi.Reg.reg));
+//..          return rmi;
+//..       case Xrmi_Mem:
+//..          vassert(sane_AMode(rmi->Xrmi.Mem.am));
+//..          return rmi;
+//..       default:
+//..          vpanic("iselIntExpr_RMI: unknown x86 RMI tag");
+//..    }
+//.. }
+//.. 
+//.. /* DO NOT CALL THIS DIRECTLY ! */
+//.. static X86RMI* iselIntExpr_RMI_wrk ( ISelEnv* env, IRExpr* e )
+//.. {
+//..    IRType ty = typeOfIRExpr(env->type_env,e);
+//..    vassert(ty == Ity_I32 || ty == Ity_I16 || ty == Ity_I8);
+//.. 
+//..    /* special case: immediate */
+//..    if (e->tag == Iex_Const) {
+//..       UInt u;
+//..       switch (e->Iex.Const.con->tag) {
+//..          case Ico_U32: u = e->Iex.Const.con->Ico.U32; break;
+//..          case Ico_U16: u = 0xFFFF & (e->Iex.Const.con->Ico.U16); break;
+//..          case Ico_U8:  u = 0xFF   & (e->Iex.Const.con->Ico.U8); break;
+//..          default: vpanic("iselIntExpr_RMI.Iex_Const(x86h)");
+//..       }
+//..       return X86RMI_Imm(u);
+//..    }
+//.. 
+//..    /* special case: 32-bit GET */
+//..    if (e->tag == Iex_Get && ty == Ity_I32) {
+//..       return X86RMI_Mem(X86AMode_IR(e->Iex.Get.offset,
+//..                                     hregX86_EBP()));
+//..    }
+//.. 
+//..    /* special case: load from memory */
+//.. 
+//..    /* default case: calculate into a register and return that */
+//..    {
+//..       HReg r = iselIntExpr_R ( env, e );
+//..       return X86RMI_Reg(r);
+//..    }
+//.. }
+//.. 
+//.. 
+//.. /* --------------------- RIs --------------------- */
+//.. 
+//.. /* Calculate an expression into an X86RI operand.  As with
+//..    iselIntExpr_R, the expression can have type 32, 16 or 8 bits. */
+//.. 
+//.. static X86RI* iselIntExpr_RI ( ISelEnv* env, IRExpr* e )
+//.. {
+//..    X86RI* ri = iselIntExpr_RI_wrk(env, e);
+//..    /* sanity checks ... */
+//..    switch (ri->tag) {
+//..       case Xri_Imm:
+//..          return ri;
+//..       case Xrmi_Reg:
+//..          vassert(hregClass(ri->Xri.Reg.reg) == HRcInt32);
+//..          vassert(hregIsVirtual(ri->Xri.Reg.reg));
+//..          return ri;
+//..       default:
+//..          vpanic("iselIntExpr_RI: unknown x86 RI tag");
+//..    }
+//.. }
+//.. 
+//.. /* DO NOT CALL THIS DIRECTLY ! */
+//.. static X86RI* iselIntExpr_RI_wrk ( ISelEnv* env, IRExpr* e )
+//.. {
+//..    IRType ty = typeOfIRExpr(env->type_env,e);
+//..    vassert(ty == Ity_I32 || ty == Ity_I16 || ty == Ity_I8);
+//.. 
+//..    /* special case: immediate */
+//..    if (e->tag == Iex_Const) {
+//..       UInt u;
+//..       switch (e->Iex.Const.con->tag) {
+//..          case Ico_U32: u = e->Iex.Const.con->Ico.U32; break;
+//..          case Ico_U16: u = 0xFFFF & (e->Iex.Const.con->Ico.U16); break;
+//..          case Ico_U8:  u = 0xFF   & (e->Iex.Const.con->Ico.U8); break;
+//..          default: vpanic("iselIntExpr_RMI.Iex_Const(x86h)");
+//..       }
+//..       return X86RI_Imm(u);
+//..    }
+//.. 
+//..    /* default case: calculate into a register and return that */
+//..    {
+//..       HReg r = iselIntExpr_R ( env, e );
+//..       return X86RI_Reg(r);
+//..    }
+//.. }
+//.. 
+//.. 
+//.. /* --------------------- RMs --------------------- */
+//.. 
+//.. /* Similarly, calculate an expression into an X86RM operand.  As with
+//..    iselIntExpr_R, the expression can have type 32, 16 or 8 bits.  */
+//.. 
+//.. static X86RM* iselIntExpr_RM ( ISelEnv* env, IRExpr* e )
+//.. {
+//..    X86RM* rm = iselIntExpr_RM_wrk(env, e);
+//..    /* sanity checks ... */
+//..    switch (rm->tag) {
+//..       case Xrm_Reg:
+//..          vassert(hregClass(rm->Xrm.Reg.reg) == HRcInt32);
+//..          vassert(hregIsVirtual(rm->Xrm.Reg.reg));
+//..          return rm;
+//..       case Xrm_Mem:
+//..          vassert(sane_AMode(rm->Xrm.Mem.am));
+//..          return rm;
+//..       default:
+//..          vpanic("iselIntExpr_RM: unknown x86 RM tag");
+//..    }
+//.. }
+//.. 
+//.. /* DO NOT CALL THIS DIRECTLY ! */
+//.. static X86RM* iselIntExpr_RM_wrk ( ISelEnv* env, IRExpr* e )
+//.. {
+//..    IRType ty = typeOfIRExpr(env->type_env,e);
+//..    vassert(ty == Ity_I32 || ty == Ity_I16 || ty == Ity_I8);
+//.. 
+//..    /* special case: 32-bit GET */
+//..    if (e->tag == Iex_Get && ty == Ity_I32) {
+//..       return X86RM_Mem(X86AMode_IR(e->Iex.Get.offset,
+//..                                    hregX86_EBP()));
+//..    }
+//.. 
+//..    /* special case: load from memory */
+//.. 
+//..    /* default case: calculate into a register and return that */
+//..    {
+//..       HReg r = iselIntExpr_R ( env, e );
+//..       return X86RM_Reg(r);
+//..    }
+//.. }
+//.. 
+//.. 
+//.. /* --------------------- CONDCODE --------------------- */
+//.. 
+//.. /* Generate code to evaluated a bit-typed expression, returning the
+//..    condition code which would correspond when the expression would
+//..    notionally have returned 1. */
+//.. 
+//.. static X86CondCode iselCondCode ( ISelEnv* env, IRExpr* e )
+//.. {
+//..    /* Uh, there's nothing we can sanity check here, unfortunately. */
+//..    return iselCondCode_wrk(env,e);
+//.. }
+//.. 
+//.. /* DO NOT CALL THIS DIRECTLY ! */
+//.. static X86CondCode iselCondCode_wrk ( ISelEnv* env, IRExpr* e )
+//.. {
+//..    MatchInfo mi;
+//..    DECLARE_PATTERN(p_32to1);
+//..    DECLARE_PATTERN(p_1Uto32_then_32to1);
+//..    DECLARE_PATTERN(p_1Sto32_then_32to1);
+//.. 
+//..    vassert(e);
+//..    vassert(typeOfIRExpr(env->type_env,e) == Ity_I1);
+//.. 
+//..    /* Constant 1:Bit */
+//..    if (e->tag == Iex_Const && e->Iex.Const.con->Ico.U1 == True) {
+//..       HReg r;
+//..       vassert(e->Iex.Const.con->tag == Ico_U1);
+//..       r = newVRegI(env);
+//..       addInstr(env, X86Instr_Alu32R(Xalu_MOV,X86RMI_Imm(0),r));
+//..       addInstr(env, X86Instr_Alu32R(Xalu_XOR,X86RMI_Reg(r),r));
+//..       return Xcc_Z;
+//..    }
+//.. 
+//..    /* Not1(...) */
+//..    if (e->tag == Iex_Unop && e->Iex.Unop.op == Iop_Not1) {
+//..       /* Generate code for the arg, and negate the test condition */
+//..       return 1 ^ iselCondCode(env, e->Iex.Unop.arg);
+//..    }
+//.. 
+//..    /* 32to1(1Uto32(expr1)) -- the casts are pointless, ignore them */
+//..    DEFINE_PATTERN(p_1Uto32_then_32to1,
+//..                   unop(Iop_32to1,unop(Iop_1Uto32,bind(0))));
+//..    if (matchIRExpr(&mi,p_1Uto32_then_32to1,e)) {
+//..       IRExpr* expr1 = mi.bindee[0];
+//..       return iselCondCode(env, expr1);
+//..    }
+//.. 
+//..    /* 32to1(1Sto32(expr1)) -- the casts are pointless, ignore them */
+//..    DEFINE_PATTERN(p_1Sto32_then_32to1,
+//..                   unop(Iop_32to1,unop(Iop_1Sto32,bind(0))));
+//..    if (matchIRExpr(&mi,p_1Sto32_then_32to1,e)) {
+//..       IRExpr* expr1 = mi.bindee[0];
+//..       return iselCondCode(env, expr1);
+//..    }
+//.. 
+//..    /* pattern: 32to1(expr32) */
+//..    DEFINE_PATTERN(p_32to1, 
+//..       unop(Iop_32to1,bind(0))
+//..    );
+//..    if (matchIRExpr(&mi,p_32to1,e)) {
+//..       X86RM* rm = iselIntExpr_RM(env, mi.bindee[0]);
+//..       addInstr(env, X86Instr_Test32(X86RI_Imm(1),rm));
+//..       return Xcc_NZ;
+//..    }
+//.. 
+//..    /* CmpEQ8 / CmpNE8 */
+//..    if (e->tag == Iex_Binop 
+//..        && (e->Iex.Binop.op == Iop_CmpEQ8
+//..            || e->Iex.Binop.op == Iop_CmpNE8)) {
+//..       HReg    r1   = iselIntExpr_R(env, e->Iex.Binop.arg1);
+//..       X86RMI* rmi2 = iselIntExpr_RMI(env, e->Iex.Binop.arg2);
+//..       HReg    r    = newVRegI(env);
+//..       addInstr(env, mk_iMOVsd_RR(r1,r));
+//..       addInstr(env, X86Instr_Alu32R(Xalu_XOR,rmi2,r));
+//..       addInstr(env, X86Instr_Alu32R(Xalu_AND,X86RMI_Imm(0xFF),r));
+//..       switch (e->Iex.Binop.op) {
+//..          case Iop_CmpEQ8:  return Xcc_Z;
+//..          case Iop_CmpNE8:  return Xcc_NZ;
+//..          default: vpanic("iselCondCode(x86): CmpXX8");
+//..       }
+//..    }
+//.. 
+//..    /* CmpEQ16 / CmpNE16 */
+//..    if (e->tag == Iex_Binop 
+//..        && (e->Iex.Binop.op == Iop_CmpEQ16
+//..            || e->Iex.Binop.op == Iop_CmpNE16)) {
+//..       HReg    r1   = iselIntExpr_R(env, e->Iex.Binop.arg1);
+//..       X86RMI* rmi2 = iselIntExpr_RMI(env, e->Iex.Binop.arg2);
+//..       HReg    r    = newVRegI(env);
+//..       addInstr(env, mk_iMOVsd_RR(r1,r));
+//..       addInstr(env, X86Instr_Alu32R(Xalu_XOR,rmi2,r));
+//..       addInstr(env, X86Instr_Alu32R(Xalu_AND,X86RMI_Imm(0xFFFF),r));
+//..       switch (e->Iex.Binop.op) {
+//..          case Iop_CmpEQ16:  return Xcc_Z;
+//..          case Iop_CmpNE16:  return Xcc_NZ;
+//..          default: vpanic("iselCondCode(x86): CmpXX16");
+//..       }
+//..    }
+//.. 
+//..    /* CmpNE32(1Sto32(b), 0) ==> b */
+//..    {
+//..       DECLARE_PATTERN(p_CmpNE32_1Sto32);
+//..       DEFINE_PATTERN(
+//..          p_CmpNE32_1Sto32,
+//..          binop(Iop_CmpNE32, unop(Iop_1Sto32,bind(0)), mkU32(0)));
+//..       if (matchIRExpr(&mi, p_CmpNE32_1Sto32, e)) {
+//..          return iselCondCode(env, mi.bindee[0]);
+//..       }
+//..    }
+//.. 
+//..    /* Cmp*32*(x,y) */
+//..    if (e->tag == Iex_Binop 
+//..        && (e->Iex.Binop.op == Iop_CmpEQ32
+//..            || e->Iex.Binop.op == Iop_CmpNE32
+//..            || e->Iex.Binop.op == Iop_CmpLT32S
+//..            || e->Iex.Binop.op == Iop_CmpLT32U
+//..            || e->Iex.Binop.op == Iop_CmpLE32S
+//..            || e->Iex.Binop.op == Iop_CmpLE32U)) {
+//..       HReg    r1   = iselIntExpr_R(env, e->Iex.Binop.arg1);
+//..       X86RMI* rmi2 = iselIntExpr_RMI(env, e->Iex.Binop.arg2);
+//..       addInstr(env, X86Instr_Alu32R(Xalu_CMP,rmi2,r1));
+//..       switch (e->Iex.Binop.op) {
+//..          case Iop_CmpEQ32:  return Xcc_Z;
+//..          case Iop_CmpNE32:  return Xcc_NZ;
+//..          case Iop_CmpLT32S: return Xcc_L;
+//..          case Iop_CmpLT32U: return Xcc_B;
+//..          case Iop_CmpLE32S: return Xcc_LE;
+//..          case Iop_CmpLE32U: return Xcc_BE;
+//..          default: vpanic("iselCondCode(x86): CmpXX32");
+//..       }
+//..    }
+//.. 
+//..    /* CmpNE64(1Sto64(b), 0) ==> b */
+//..    {
+//..       DECLARE_PATTERN(p_CmpNE64_1Sto64);
+//..       DEFINE_PATTERN(
+//..          p_CmpNE64_1Sto64,
+//..          binop(Iop_CmpNE64, unop(Iop_1Sto64,bind(0)), mkU64(0)));
+//..       if (matchIRExpr(&mi, p_CmpNE64_1Sto64, e)) {
+//..          return iselCondCode(env, mi.bindee[0]);
+//..       }
+//..    }
+//.. 
+//..    /* CmpNE64(x, 0) */
+//..    {
+//..       DECLARE_PATTERN(p_CmpNE64_x_zero);
+//..       DEFINE_PATTERN(
+//..          p_CmpNE64_x_zero,
+//..          binop(Iop_CmpNE64, bind(0), mkU64(0)) );
+//..       if (matchIRExpr(&mi, p_CmpNE64_x_zero, e)) {
+//..          HReg hi, lo;
+//..          IRExpr* x   = mi.bindee[0];
+//..          HReg    tmp = newVRegI(env);
+//..          iselInt64Expr( &hi, &lo, env, x );
+//..          addInstr(env, mk_iMOVsd_RR(hi, tmp));
+//..          addInstr(env, X86Instr_Alu32R(Xalu_OR,X86RMI_Reg(lo), tmp));
+//..          return Xcc_NZ;
+//..       }
+//..    }
+//.. 
+//..    /* CmpNE64 */
+//..    if (e->tag == Iex_Binop 
+//..        && e->Iex.Binop.op == Iop_CmpNE64) {
+//..       HReg hi1, hi2, lo1, lo2;
+//..       HReg tHi = newVRegI(env);
+//..       HReg tLo = newVRegI(env);
+//..       iselInt64Expr( &hi1, &lo1, env, e->Iex.Binop.arg1 );
+//..       iselInt64Expr( &hi2, &lo2, env, e->Iex.Binop.arg2 );
+//..       addInstr(env, mk_iMOVsd_RR(hi1, tHi));
+//..       addInstr(env, X86Instr_Alu32R(Xalu_XOR,X86RMI_Reg(hi2), tHi));
+//..       addInstr(env, mk_iMOVsd_RR(lo1, tLo));
+//..       addInstr(env, X86Instr_Alu32R(Xalu_XOR,X86RMI_Reg(lo2), tLo));
+//..       addInstr(env, X86Instr_Alu32R(Xalu_OR,X86RMI_Reg(tHi), tLo));
+//..       switch (e->Iex.Binop.op) {
+//..          case Iop_CmpNE64:  return Xcc_NZ;
+//..          default: vpanic("iselCondCode(x86): CmpXX64");
+//..       }
+//..    }
+//.. 
+//..    /* var */
+//..    if (e->tag == Iex_Tmp) {
+//..       HReg r32 = lookupIRTemp(env, e->Iex.Tmp.tmp);
+//..       HReg dst = newVRegI(env);
+//..       addInstr(env, mk_iMOVsd_RR(r32,dst));
+//..       addInstr(env, X86Instr_Alu32R(Xalu_AND,X86RMI_Imm(1),dst));
+//..       return Xcc_NZ;
+//..    }
+//.. 
+//..    ppIRExpr(e);
+//..    vpanic("iselCondCode");
+//.. }
+//.. 
+//.. 
+//.. /*---------------------------------------------------------*/
+//.. /*--- ISEL: Integer expressions (64 bit)                ---*/
+//.. /*---------------------------------------------------------*/
+//.. 
+//.. /* Compute a 64-bit value into a register pair, which is returned as
+//..    the first two parameters.  As with iselIntExpr_R, these may be
+//..    either real or virtual regs; in any case they must not be changed
+//..    by subsequent code emitted by the caller.  */
+//.. 
+//.. static void iselInt64Expr ( HReg* rHi, HReg* rLo, ISelEnv* env, IRExpr* e )
+//.. {
+//..    iselInt64Expr_wrk(rHi, rLo, env, e);
+//.. #  if 0
+//..    vex_printf("\n"); ppIRExpr(e); vex_printf("\n");
+//.. #  endif
+//..    vassert(hregClass(*rHi) == HRcInt32);
+//..    vassert(hregIsVirtual(*rHi));
+//..    vassert(hregClass(*rLo) == HRcInt32);
+//..    vassert(hregIsVirtual(*rLo));
+//.. }
+//.. 
+//.. /* DO NOT CALL THIS DIRECTLY ! */
+//.. static void iselInt64Expr_wrk ( HReg* rHi, HReg* rLo, ISelEnv* env, IRExpr* e )
+//.. {
+//..    HWord fn = 0; /* helper fn for most SIMD64 stuff */
+//..    vassert(e);
+//..    vassert(typeOfIRExpr(env->type_env,e) == Ity_I64);
+//.. 
+//..    /* 64-bit literal */
+//..    if (e->tag == Iex_Const) {
+//..       ULong w64 = e->Iex.Const.con->Ico.U64;
+//..       UInt  wHi = ((UInt)(w64 >> 32)) & 0xFFFFFFFF;
+//..       UInt  wLo = ((UInt)w64) & 0xFFFFFFFF;
+//..       HReg  tLo = newVRegI(env);
+//..       HReg  tHi = newVRegI(env);
+//..       vassert(e->Iex.Const.con->tag == Ico_U64);
+//..       addInstr(env, X86Instr_Alu32R(Xalu_MOV, X86RMI_Imm(wHi), tHi));
+//..       addInstr(env, X86Instr_Alu32R(Xalu_MOV, X86RMI_Imm(wLo), tLo));
+//..       *rHi = tHi;
+//..       *rLo = tLo;
+//..       return;
+//..    }
+//.. 
+//..    /* read 64-bit IRTemp */
+//..    if (e->tag == Iex_Tmp) {
+//..       lookupIRTemp64( rHi, rLo, env, e->Iex.Tmp.tmp);
+//..       return;
+//..    }
+//.. 
+//..    /* 64-bit load */
+//..    if (e->tag == Iex_LDle) {
+//..       HReg     tLo, tHi;
+//..       X86AMode *am0, *am4;
+//..       vassert(e->Iex.LDle.ty == Ity_I64);
+//..       tLo = newVRegI(env);
+//..       tHi = newVRegI(env);
+//..       am0 = iselIntExpr_AMode(env, e->Iex.LDle.addr);
+//..       am4 = advance4(am0);
+//..       addInstr(env, X86Instr_Alu32R( Xalu_MOV, X86RMI_Mem(am0), tLo ));
+//..       addInstr(env, X86Instr_Alu32R( Xalu_MOV, X86RMI_Mem(am4), tHi ));
+//..       *rHi = tHi;
+//..       *rLo = tLo;
+//..       return;
+//..    }
+//.. 
+//..    /* 64-bit GET */
+//..    if (e->tag == Iex_Get) {
+//..       X86AMode* am  = X86AMode_IR(e->Iex.Get.offset, hregX86_EBP());
+//..       X86AMode* am4 = advance4(am);
+//..       HReg tLo = newVRegI(env);
+//..       HReg tHi = newVRegI(env);
+//..       addInstr(env, X86Instr_Alu32R( Xalu_MOV, X86RMI_Mem(am), tLo ));
+//..       addInstr(env, X86Instr_Alu32R( Xalu_MOV, X86RMI_Mem(am4), tHi ));
+//..       *rHi = tHi;
+//..       *rLo = tLo;
+//..       return;
+//..    }
+//.. 
+//..    /* 64-bit GETI */
+//..    if (e->tag == Iex_GetI) {
+//..       X86AMode* am 
+//..          = genGuestArrayOffset( env, e->Iex.GetI.descr, 
+//..                                      e->Iex.GetI.ix, e->Iex.GetI.bias );
+//..       X86AMode* am4 = advance4(am);
+//..       HReg tLo = newVRegI(env);
+//..       HReg tHi = newVRegI(env);
+//..       addInstr(env, X86Instr_Alu32R( Xalu_MOV, X86RMI_Mem(am), tLo ));
+//..       addInstr(env, X86Instr_Alu32R( Xalu_MOV, X86RMI_Mem(am4), tHi ));
+//..       *rHi = tHi;
+//..       *rLo = tLo;
+//..       return;
+//..    }
+//.. 
+//..    /* 64-bit Mux0X */
+//..    if (e->tag == Iex_Mux0X) {
+//..       HReg e0Lo, e0Hi, eXLo, eXHi, r8;
+//..       HReg tLo = newVRegI(env);
+//..       HReg tHi = newVRegI(env);
+//..       iselInt64Expr(&e0Hi, &e0Lo, env, e->Iex.Mux0X.expr0);
+//..       iselInt64Expr(&eXHi, &eXLo, env, e->Iex.Mux0X.exprX);
+//..       addInstr(env, mk_iMOVsd_RR(eXHi, tHi));
+//..       addInstr(env, mk_iMOVsd_RR(eXLo, tLo));
+//..       r8 = iselIntExpr_R(env, e->Iex.Mux0X.cond);
+//..       addInstr(env, X86Instr_Test32(X86RI_Imm(0xFF), X86RM_Reg(r8)));
+//..       /* This assumes the first cmov32 doesn't trash the condition
+//..          codes, so they are still available for the second cmov32 */
+//..       addInstr(env, X86Instr_CMov32(Xcc_Z,X86RM_Reg(e0Hi),tHi));
+//..       addInstr(env, X86Instr_CMov32(Xcc_Z,X86RM_Reg(e0Lo),tLo));
+//..       *rHi = tHi;
+//..       *rLo = tLo;
+//..       return;
+//..    }
+//.. 
+//..    /* --------- BINARY ops --------- */
+//..    if (e->tag == Iex_Binop) {
+//..       switch (e->Iex.Binop.op) {
+//..          /* 32 x 32 -> 64 multiply */
+//..          case Iop_MullU32:
+//..          case Iop_MullS32: {
+//..             /* get one operand into %eax, and the other into a R/M.
+//..                Need to make an educated guess about which is better in
+//..                which. */
+//..             HReg   tLo    = newVRegI(env);
+//..             HReg   tHi    = newVRegI(env);
+//..             Bool   syned  = e->Iex.Binop.op == Iop_MullS32;
+//..             X86RM* rmLeft = iselIntExpr_RM(env, e->Iex.Binop.arg1);
+//..             HReg   rRight = iselIntExpr_R(env, e->Iex.Binop.arg2);
+//..             addInstr(env, mk_iMOVsd_RR(rRight, hregX86_EAX()));
+//..             addInstr(env, X86Instr_MulL(syned, Xss_32, rmLeft));
+//..             /* Result is now in EDX:EAX.  Tell the caller. */
+//..             addInstr(env, mk_iMOVsd_RR(hregX86_EDX(), tHi));
+//..             addInstr(env, mk_iMOVsd_RR(hregX86_EAX(), tLo));
+//..             *rHi = tHi;
+//..             *rLo = tLo;
+//..             return;
+//..          }
+//.. 
+//..          /* 64 x 32 -> (32(rem),32(div)) division */
+//..          case Iop_DivModU64to32:
+//..          case Iop_DivModS64to32: {
+//..             /* Get the 64-bit operand into edx:eax, and the other into
+//..                any old R/M. */
+//..             HReg sHi, sLo;
+//..             HReg   tLo     = newVRegI(env);
+//..             HReg   tHi     = newVRegI(env);
+//..             Bool   syned   = e->Iex.Binop.op == Iop_DivModS64to32;
+//..             X86RM* rmRight = iselIntExpr_RM(env, e->Iex.Binop.arg2);
+//..             iselInt64Expr(&sHi,&sLo, env, e->Iex.Binop.arg1);
+//..             addInstr(env, mk_iMOVsd_RR(sHi, hregX86_EDX()));
+//..             addInstr(env, mk_iMOVsd_RR(sLo, hregX86_EAX()));
+//..             addInstr(env, X86Instr_Div(syned, Xss_32, rmRight));
+//..             addInstr(env, mk_iMOVsd_RR(hregX86_EDX(), tHi));
+//..             addInstr(env, mk_iMOVsd_RR(hregX86_EAX(), tLo));
+//..             *rHi = tHi;
+//..             *rLo = tLo;
+//..             return;
+//..          }
+//.. 
+//..          /* Or64/And64/Xor64 */
+//..          case Iop_Or64:
+//..          case Iop_And64:
+//..          case Iop_Xor64: {
+//..             HReg xLo, xHi, yLo, yHi;
+//..             HReg tLo = newVRegI(env);
+//..             HReg tHi = newVRegI(env);
+//..             X86AluOp op = e->Iex.Binop.op==Iop_Or64 ? Xalu_OR
+//..                           : e->Iex.Binop.op==Iop_And64 ? Xalu_AND
+//..                           : Xalu_XOR;
+//..             iselInt64Expr(&xHi, &xLo, env, e->Iex.Binop.arg1);
+//..             addInstr(env, mk_iMOVsd_RR(xHi, tHi));
+//..             addInstr(env, mk_iMOVsd_RR(xLo, tLo));
+//..             iselInt64Expr(&yHi, &yLo, env, e->Iex.Binop.arg2);
+//..             addInstr(env, X86Instr_Alu32R(op, X86RMI_Reg(yHi), tHi));
+//..             addInstr(env, X86Instr_Alu32R(op, X86RMI_Reg(yLo), tLo));
+//..             *rHi = tHi;
+//..             *rLo = tLo;
+//..             return;
+//..          }
+//.. 
+//..          /* Add64/Sub64 */
+//..          case Iop_Add64:
+//..          case Iop_Sub64: {
+//..             HReg xLo, xHi, yLo, yHi;
+//..             HReg tLo = newVRegI(env);
+//..             HReg tHi = newVRegI(env);
+//..             iselInt64Expr(&xHi, &xLo, env, e->Iex.Binop.arg1);
+//..             addInstr(env, mk_iMOVsd_RR(xHi, tHi));
+//..             addInstr(env, mk_iMOVsd_RR(xLo, tLo));
+//..             iselInt64Expr(&yHi, &yLo, env, e->Iex.Binop.arg2);
+//..             if (e->Iex.Binop.op==Iop_Add64) {
+//..                addInstr(env, X86Instr_Alu32R(Xalu_ADD, X86RMI_Reg(yLo), tLo));
+//..                addInstr(env, X86Instr_Alu32R(Xalu_ADC, X86RMI_Reg(yHi), tHi));
+//..             } else {
+//..                addInstr(env, X86Instr_Alu32R(Xalu_SUB, X86RMI_Reg(yLo), tLo));
+//..                addInstr(env, X86Instr_Alu32R(Xalu_SBB, X86RMI_Reg(yHi), tHi));
+//..             }
+//..             *rHi = tHi;
+//..             *rLo = tLo;
+//..             return;
+//..          }
+//.. 
+//..          /* 32HLto64(e1,e2) */
+//..          case Iop_32HLto64:
+//..             *rHi = iselIntExpr_R(env, e->Iex.Binop.arg1);
+//..             *rLo = iselIntExpr_R(env, e->Iex.Binop.arg2);
+//..             return;
+//.. 
+//..          /* 64-bit shifts */
+//..          case Iop_Shl64: {
+//..             /* We use the same ingenious scheme as gcc.  Put the value
+//..                to be shifted into %hi:%lo, and the shift amount into
+//..                %cl.  Then (dsts on right, a la ATT syntax):
+//..  
+//..                shldl %cl, %lo, %hi   -- make %hi be right for the
+//..                                      -- shift amt %cl % 32
+//..                shll  %cl, %lo        -- make %lo be right for the
+//..                                      -- shift amt %cl % 32
+//.. 
+//..                Now, if (shift amount % 64) is in the range 32 .. 63,
+//..                we have to do a fixup, which puts the result low half
+//..                into the result high half, and zeroes the low half:
+//.. 
+//..                testl $32, %ecx
+//.. 
+//..                cmovnz %lo, %hi
+//..                movl $0, %tmp         -- sigh; need yet another reg
+//..                cmovnz %tmp, %lo 
+//..             */
+//..             HReg rAmt, sHi, sLo, tHi, tLo, tTemp;
+//..             tLo = newVRegI(env);
+//..             tHi = newVRegI(env);
+//..             tTemp = newVRegI(env);
+//..             rAmt = iselIntExpr_R(env, e->Iex.Binop.arg2);
+//..             iselInt64Expr(&sHi,&sLo, env, e->Iex.Binop.arg1);
+//..             addInstr(env, mk_iMOVsd_RR(rAmt, hregX86_ECX()));
+//..             addInstr(env, mk_iMOVsd_RR(sHi, tHi));
+//..             addInstr(env, mk_iMOVsd_RR(sLo, tLo));
+//..             /* Ok.  Now shift amt is in %ecx, and value is in tHi/tLo
+//..                and those regs are legitimately modifiable. */
+//..             addInstr(env, X86Instr_Sh3232(Xsh_SHL, 0/*%cl*/, tLo, tHi));
+//..             addInstr(env, X86Instr_Sh32(Xsh_SHL, 0/*%cl*/, X86RM_Reg(tLo)));
+//..             addInstr(env, X86Instr_Test32(X86RI_Imm(32), 
+//..                           X86RM_Reg(hregX86_ECX())));
+//..             addInstr(env, X86Instr_CMov32(Xcc_NZ, X86RM_Reg(tLo), tHi));
+//..             addInstr(env, X86Instr_Alu32R(Xalu_MOV, X86RMI_Imm(0), tTemp));
+//..             addInstr(env, X86Instr_CMov32(Xcc_NZ, X86RM_Reg(tTemp), tLo));
+//..             *rHi = tHi;
+//..             *rLo = tLo;
+//..             return;
+//..          }
+//.. 
+//..          case Iop_Shr64: {
+//..             /* We use the same ingenious scheme as gcc.  Put the value
+//..                to be shifted into %hi:%lo, and the shift amount into
+//..                %cl.  Then:
+//..  
+//..                shrdl %cl, %hi, %lo   -- make %lo be right for the
+//..                                      -- shift amt %cl % 32
+//..                shrl  %cl, %hi        -- make %hi be right for the
+//..                                      -- shift amt %cl % 32
+//.. 
+//..                Now, if (shift amount % 64) is in the range 32 .. 63,
+//..                we have to do a fixup, which puts the result high half
+//..                into the result low half, and zeroes the high half:
+//.. 
+//..                testl $32, %ecx
+//.. 
+//..                cmovnz %hi, %lo
+//..                movl $0, %tmp         -- sigh; need yet another reg
+//..                cmovnz %tmp, %hi
+//..             */
+//..             HReg rAmt, sHi, sLo, tHi, tLo, tTemp;
+//..             tLo = newVRegI(env);
+//..             tHi = newVRegI(env);
+//..             tTemp = newVRegI(env);
+//..             rAmt = iselIntExpr_R(env, e->Iex.Binop.arg2);
+//..             iselInt64Expr(&sHi,&sLo, env, e->Iex.Binop.arg1);
+//..             addInstr(env, mk_iMOVsd_RR(rAmt, hregX86_ECX()));
+//..             addInstr(env, mk_iMOVsd_RR(sHi, tHi));
+//..             addInstr(env, mk_iMOVsd_RR(sLo, tLo));
+//..             /* Ok.  Now shift amt is in %ecx, and value is in tHi/tLo
+//..                and those regs are legitimately modifiable. */
+//..             addInstr(env, X86Instr_Sh3232(Xsh_SHR, 0/*%cl*/, tHi, tLo));
+//..             addInstr(env, X86Instr_Sh32(Xsh_SHR, 0/*%cl*/, X86RM_Reg(tHi)));
+//..             addInstr(env, X86Instr_Test32(X86RI_Imm(32), 
+//..                           X86RM_Reg(hregX86_ECX())));
+//..             addInstr(env, X86Instr_CMov32(Xcc_NZ, X86RM_Reg(tHi), tLo));
+//..             addInstr(env, X86Instr_Alu32R(Xalu_MOV, X86RMI_Imm(0), tTemp));
+//..             addInstr(env, X86Instr_CMov32(Xcc_NZ, X86RM_Reg(tTemp), tHi));
+//..             *rHi = tHi;
+//..             *rLo = tLo;
+//..             return;
+//..          }
+//.. 
+//..          /* F64 -> I64 */
+//..          /* Sigh, this is an almost exact copy of the F64 -> I32/I16
+//..             case.  Unfortunately I see no easy way to avoid the
+//..             duplication. */
+//..          case Iop_F64toI64: {
+//..             HReg rf  = iselDblExpr(env, e->Iex.Binop.arg2);
+//..             HReg tLo = newVRegI(env);
+//..             HReg tHi = newVRegI(env);
+//.. 
+//..             /* Used several times ... */
+//..             /* Careful ... this sharing is only safe because
+//..          zero_esp/four_esp do not hold any registers which the
+//..          register allocator could attempt to swizzle later. */
+//..             X86AMode* zero_esp = X86AMode_IR(0, hregX86_ESP());
+//..             X86AMode* four_esp = X86AMode_IR(4, hregX86_ESP());
+//.. 
+//..             /* rf now holds the value to be converted, and rrm holds
+//..                the rounding mode value, encoded as per the
+//..                IRRoundingMode enum.  The first thing to do is set the
+//..                FPU's rounding mode accordingly. */
+//.. 
+//..             /* Create a space for the format conversion. */
+//..             /* subl $8, %esp */
+//..             sub_from_esp(env, 8);
+//.. 
+//..             /* Set host rounding mode */
+//..             set_FPU_rounding_mode( env, e->Iex.Binop.arg1 );
+//.. 
+//..             /* gistll %rf, 0(%esp) */
+//..             addInstr(env, X86Instr_FpLdStI(False/*store*/, 8, rf, zero_esp));
+//.. 
+//..             /* movl 0(%esp), %dstLo */
+//..             /* movl 4(%esp), %dstHi */
+//..             addInstr(env, X86Instr_Alu32R(
+//..                              Xalu_MOV, X86RMI_Mem(zero_esp), tLo));
+//..             addInstr(env, X86Instr_Alu32R(
+//..                              Xalu_MOV, X86RMI_Mem(four_esp), tHi));
+//.. 
+//..             /* Restore default FPU rounding. */
+//..             set_FPU_rounding_default( env );
+//.. 
+//..             /* addl $8, %esp */
+//..             add_to_esp(env, 8);
+//.. 
+//..             *rHi = tHi;
+//..             *rLo = tLo;
+//..             return;
+//..          }
+//.. 
+//..          case Iop_Add8x8:
+//..             fn = (HWord)h_generic_calc_Add8x8; goto binnish;
+//..          case Iop_Add16x4:
+//..             fn = (HWord)h_generic_calc_Add16x4; goto binnish;
+//..          case Iop_Add32x2:
+//..             fn = (HWord)h_generic_calc_Add32x2; goto binnish;
+//.. 
+//..          case Iop_Avg8Ux8:
+//..             fn = (HWord)h_generic_calc_Avg8Ux8; goto binnish;
+//..          case Iop_Avg16Ux4:
+//..             fn = (HWord)h_generic_calc_Avg16Ux4; goto binnish;
+//.. 
+//..          case Iop_CmpEQ8x8:
+//..             fn = (HWord)h_generic_calc_CmpEQ8x8; goto binnish;
+//..          case Iop_CmpEQ16x4:
+//..             fn = (HWord)h_generic_calc_CmpEQ16x4; goto binnish;
+//..          case Iop_CmpEQ32x2:
+//..             fn = (HWord)h_generic_calc_CmpEQ32x2; goto binnish;
+//.. 
+//..          case Iop_CmpGT8Sx8:
+//..             fn = (HWord)h_generic_calc_CmpGT8Sx8; goto binnish;
+//..          case Iop_CmpGT16Sx4:
+//..             fn = (HWord)h_generic_calc_CmpGT16Sx4; goto binnish;
+//..          case Iop_CmpGT32Sx2:
+//..             fn = (HWord)h_generic_calc_CmpGT32Sx2; goto binnish;
+//.. 
+//..          case Iop_InterleaveHI8x8:
+//..             fn = (HWord)h_generic_calc_InterleaveHI8x8; goto binnish;
+//..          case Iop_InterleaveLO8x8:
+//..             fn = (HWord)h_generic_calc_InterleaveLO8x8; goto binnish;
+//..          case Iop_InterleaveHI16x4:
+//..             fn = (HWord)h_generic_calc_InterleaveHI16x4; goto binnish;
+//..          case Iop_InterleaveLO16x4:
+//..             fn = (HWord)h_generic_calc_InterleaveLO16x4; goto binnish;
+//..          case Iop_InterleaveHI32x2:
+//..             fn = (HWord)h_generic_calc_InterleaveHI32x2; goto binnish;
+//..          case Iop_InterleaveLO32x2:
+//..             fn = (HWord)h_generic_calc_InterleaveLO32x2; goto binnish;
+//.. 
+//..          case Iop_Max8Ux8:
+//..             fn = (HWord)h_generic_calc_Max8Ux8; goto binnish;
+//..          case Iop_Max16Sx4:
+//..             fn = (HWord)h_generic_calc_Max16Sx4; goto binnish;
+//..          case Iop_Min8Ux8:
+//..             fn = (HWord)h_generic_calc_Min8Ux8; goto binnish;
+//..          case Iop_Min16Sx4:
+//..             fn = (HWord)h_generic_calc_Min16Sx4; goto binnish;
+//.. 
+//..          case Iop_Mul16x4:
+//..             fn = (HWord)h_generic_calc_Mul16x4; goto binnish;
+//..          case Iop_MulHi16Sx4:
+//..             fn = (HWord)h_generic_calc_MulHi16Sx4; goto binnish;
+//..          case Iop_MulHi16Ux4:
+//..             fn = (HWord)h_generic_calc_MulHi16Ux4; goto binnish;
+//.. 
+//..          case Iop_QAdd8Sx8:
+//..             fn = (HWord)h_generic_calc_QAdd8Sx8; goto binnish;
+//..          case Iop_QAdd16Sx4:
+//..             fn = (HWord)h_generic_calc_QAdd16Sx4; goto binnish;
+//..          case Iop_QAdd8Ux8:
+//..             fn = (HWord)h_generic_calc_QAdd8Ux8; goto binnish;
+//..          case Iop_QAdd16Ux4:
+//..             fn = (HWord)h_generic_calc_QAdd16Ux4; goto binnish;
+//.. 
+//..          case Iop_QNarrow32Sx2:
+//..             fn = (HWord)h_generic_calc_QNarrow32Sx2; goto binnish;
+//..          case Iop_QNarrow16Sx4:
+//..             fn = (HWord)h_generic_calc_QNarrow16Sx4; goto binnish;
+//..          case Iop_QNarrow16Ux4:
+//..             fn = (HWord)h_generic_calc_QNarrow16Ux4; goto binnish;
+//.. 
+//..          case Iop_QSub8Sx8:
+//..             fn = (HWord)h_generic_calc_QSub8Sx8; goto binnish;
+//..          case Iop_QSub16Sx4:
+//..             fn = (HWord)h_generic_calc_QSub16Sx4; goto binnish;
+//..          case Iop_QSub8Ux8:
+//..             fn = (HWord)h_generic_calc_QSub8Ux8; goto binnish;
+//..          case Iop_QSub16Ux4:
+//..             fn = (HWord)h_generic_calc_QSub16Ux4; goto binnish;
+//.. 
+//..          case Iop_Sub8x8:
+//..             fn = (HWord)h_generic_calc_Sub8x8; goto binnish;
+//..          case Iop_Sub16x4:
+//..             fn = (HWord)h_generic_calc_Sub16x4; goto binnish;
+//..          case Iop_Sub32x2:
+//..             fn = (HWord)h_generic_calc_Sub32x2; goto binnish;
+//.. 
+//..          binnish: {
+//..             /* Note: the following assumes all helpers are of
+//..                signature 
+//..                   ULong fn ( ULong, ULong ), and they are
+//..                not marked as regparm functions. 
+//..             */
+//..             HReg xLo, xHi, yLo, yHi;
+//..             HReg tLo = newVRegI(env);
+//..             HReg tHi = newVRegI(env);
+//..             iselInt64Expr(&yHi, &yLo, env, e->Iex.Binop.arg2);
+//..             addInstr(env, X86Instr_Push(X86RMI_Reg(yHi)));
+//..             addInstr(env, X86Instr_Push(X86RMI_Reg(yLo)));
+//..             iselInt64Expr(&xHi, &xLo, env, e->Iex.Binop.arg1);
+//..             addInstr(env, X86Instr_Push(X86RMI_Reg(xHi)));
+//..             addInstr(env, X86Instr_Push(X86RMI_Reg(xLo)));
+//..             addInstr(env, X86Instr_Call( Xcc_ALWAYS, (UInt)fn, 0 ));
+//..             add_to_esp(env, 4*4);
+//..             addInstr(env, mk_iMOVsd_RR(hregX86_EDX(), tHi));
+//..             addInstr(env, mk_iMOVsd_RR(hregX86_EAX(), tLo));
+//..             *rHi = tHi;
+//..             *rLo = tLo;
+//..             return;
+//..          }
+//.. 
+//..          case Iop_ShlN32x2:
+//..             fn = (HWord)h_generic_calc_ShlN32x2; goto shifty;
+//..          case Iop_ShlN16x4:
+//..             fn = (HWord)h_generic_calc_ShlN16x4; goto shifty;
+//..          case Iop_ShrN32x2:
+//..             fn = (HWord)h_generic_calc_ShrN32x2; goto shifty;
+//..          case Iop_ShrN16x4:
+//..             fn = (HWord)h_generic_calc_ShrN16x4; goto shifty;
+//..          case Iop_SarN32x2:
+//..             fn = (HWord)h_generic_calc_SarN32x2; goto shifty;
+//..          case Iop_SarN16x4:
+//..             fn = (HWord)h_generic_calc_SarN16x4; goto shifty;
+//..          shifty: {
+//..             /* Note: the following assumes all helpers are of
+//..                signature 
+//..                   ULong fn ( ULong, UInt ), and they are
+//..                not marked as regparm functions. 
+//..             */
+//..             HReg xLo, xHi;
+//..             HReg tLo = newVRegI(env);
+//..             HReg tHi = newVRegI(env);
+//..             X86RMI* y = iselIntExpr_RMI(env, e->Iex.Binop.arg2);
+//..             addInstr(env, X86Instr_Push(y));
+//..             iselInt64Expr(&xHi, &xLo, env, e->Iex.Binop.arg1);
+//..             addInstr(env, X86Instr_Push(X86RMI_Reg(xHi)));
+//..             addInstr(env, X86Instr_Push(X86RMI_Reg(xLo)));
+//..             addInstr(env, X86Instr_Call( Xcc_ALWAYS, (UInt)fn, 0 ));
+//..             add_to_esp(env, 3*4);
+//..             addInstr(env, mk_iMOVsd_RR(hregX86_EDX(), tHi));
+//..             addInstr(env, mk_iMOVsd_RR(hregX86_EAX(), tLo));
+//..             *rHi = tHi;
+//..             *rLo = tLo;
+//..             return;
+//..          }
+//.. 
+//..          default: 
+//..             break;
+//..       }
+//..    } /* if (e->tag == Iex_Binop) */
+//.. 
+//.. 
+//..    /* --------- UNARY ops --------- */
+//..    if (e->tag == Iex_Unop) {
+//..       switch (e->Iex.Unop.op) {
+//.. 
+//..          /* 32Sto64(e) */
+//..          case Iop_32Sto64: {
+//..             HReg tLo = newVRegI(env);
+//..             HReg tHi = newVRegI(env);
+//..             HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
+//..             addInstr(env, mk_iMOVsd_RR(src,tHi));
+//..             addInstr(env, mk_iMOVsd_RR(src,tLo));
+//..             addInstr(env, X86Instr_Sh32(Xsh_SAR, 31, X86RM_Reg(tHi)));
+//..             *rHi = tHi;
+//..             *rLo = tLo;
+//..             return;
+//..          }
+//.. 
+//..          /* 32Uto64(e) */
+//..          case Iop_32Uto64: {
+//..             HReg tLo = newVRegI(env);
+//..             HReg tHi = newVRegI(env);
+//..             HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
+//..             addInstr(env, mk_iMOVsd_RR(src,tLo));
+//..             addInstr(env, X86Instr_Alu32R(Xalu_MOV, X86RMI_Imm(0), tHi));
+//..             *rHi = tHi;
+//..             *rLo = tLo;
+//..             return;
+//..          }
+//.. 
+//..          /* 128{HI}to64 */
+//..          case Iop_128HIto64:
+//..          case Iop_128to64: {
+//..             Int  off = e->Iex.Unop.op==Iop_128HIto64 ? 8 : 0;
+//..             HReg tLo = newVRegI(env);
+//..             HReg tHi = newVRegI(env);
+//..             HReg vec = iselVecExpr(env, e->Iex.Unop.arg);
+//..             X86AMode* esp0  = X86AMode_IR(0,     hregX86_ESP());
+//..             X86AMode* espLO = X86AMode_IR(off,   hregX86_ESP());
+//..             X86AMode* espHI = X86AMode_IR(off+4, hregX86_ESP());
+//..             sub_from_esp(env, 16);
+//..             addInstr(env, X86Instr_SseLdSt(False/*store*/, vec, esp0));
+//..             addInstr(env, X86Instr_Alu32R( Xalu_MOV, 
+//..                                            X86RMI_Mem(espLO), tLo ));
+//..             addInstr(env, X86Instr_Alu32R( Xalu_MOV, 
+//..                                            X86RMI_Mem(espHI), tHi ));
+//..             add_to_esp(env, 16);
+//..             *rHi = tHi;
+//..             *rLo = tLo;
+//..             return;
+//..          }
+//.. 
+//..          /* could do better than this, but for now ... */
+//..          case Iop_1Sto64: {
+//..             HReg tLo = newVRegI(env);
+//..             HReg tHi = newVRegI(env);
+//..             X86CondCode cond = iselCondCode(env, e->Iex.Unop.arg);
+//..             addInstr(env, X86Instr_Set32(cond,tLo));
+//..             addInstr(env, X86Instr_Sh32(Xsh_SHL, 31, X86RM_Reg(tLo)));
+//..             addInstr(env, X86Instr_Sh32(Xsh_SAR, 31, X86RM_Reg(tLo)));
+//..             addInstr(env, mk_iMOVsd_RR(tLo, tHi));
+//..             *rHi = tHi;
+//..             *rLo = tLo;
+//..             return;
+//..          }
+//.. 
+//..          /* Not64(e) */
+//..          case Iop_Not64: {
+//..             HReg tLo = newVRegI(env);
+//..             HReg tHi = newVRegI(env);
+//..             HReg sHi, sLo;
+//..             iselInt64Expr(&sHi, &sLo, env, e->Iex.Unop.arg);
+//..             addInstr(env, mk_iMOVsd_RR(sHi, tHi));
+//..             addInstr(env, mk_iMOVsd_RR(sLo, tLo));
+//..             addInstr(env, X86Instr_Unary32(Xun_NOT,X86RM_Reg(tHi)));
+//..             addInstr(env, X86Instr_Unary32(Xun_NOT,X86RM_Reg(tLo)));
+//..             *rHi = tHi;
+//..             *rLo = tLo;
+//..             return;
+//..          }
+//.. 
+//..          /* ReinterpF64asI64(e) */
+//..          /* Given an IEEE754 double, produce an I64 with the same bit
+//..             pattern. */
+//..          case Iop_ReinterpF64asI64: {
+//..             HReg rf   = iselDblExpr(env, e->Iex.Unop.arg);
+//..             HReg tLo  = newVRegI(env);
+//..             HReg tHi  = newVRegI(env);
+//..             X86AMode* zero_esp = X86AMode_IR(0, hregX86_ESP());
+//..             X86AMode* four_esp = X86AMode_IR(4, hregX86_ESP());
+//..             /* paranoia */
+//..             set_FPU_rounding_default(env);
+//..             /* subl $8, %esp */
+//..             sub_from_esp(env, 8);
+//..             /* gstD %rf, 0(%esp) */
+//..             addInstr(env,
+//..                      X86Instr_FpLdSt(False/*store*/, 8, rf, zero_esp));
+//..             /* movl 0(%esp), %tLo */
+//..             addInstr(env, 
+//..                      X86Instr_Alu32R(Xalu_MOV, X86RMI_Mem(zero_esp), tLo));
+//..             /* movl 4(%esp), %tHi */
+//..             addInstr(env, 
+//..                      X86Instr_Alu32R(Xalu_MOV, X86RMI_Mem(four_esp), tHi));
+//..             /* addl $8, %esp */
+//..             add_to_esp(env, 8);
+//..             *rHi = tHi;
+//..             *rLo = tLo;
+//..             return;
+//..          }
+//.. 
+//..          case Iop_CmpNEZ32x2:
+//..             fn = (HWord)h_generic_calc_CmpNEZ32x2; goto unish;
+//..          case Iop_CmpNEZ16x4:
+//..             fn = (HWord)h_generic_calc_CmpNEZ16x4; goto unish;
+//..          case Iop_CmpNEZ8x8:
+//..             fn = (HWord)h_generic_calc_CmpNEZ8x8; goto unish;
+//..          unish: {
+//..             /* Note: the following assumes all helpers are of
+//..                signature 
+//..                   ULong fn ( ULong ), and they are
+//..                not marked as regparm functions. 
+//..             */
+//..             HReg xLo, xHi;
+//..             HReg tLo = newVRegI(env);
+//..             HReg tHi = newVRegI(env);
+//..             iselInt64Expr(&xHi, &xLo, env, e->Iex.Unop.arg);
+//..             addInstr(env, X86Instr_Push(X86RMI_Reg(xHi)));
+//..             addInstr(env, X86Instr_Push(X86RMI_Reg(xLo)));
+//..             addInstr(env, X86Instr_Call( Xcc_ALWAYS, (UInt)fn, 0 ));
+//..             add_to_esp(env, 2*4);
+//..             addInstr(env, mk_iMOVsd_RR(hregX86_EDX(), tHi));
+//..             addInstr(env, mk_iMOVsd_RR(hregX86_EAX(), tLo));
+//..             *rHi = tHi;
+//..             *rLo = tLo;
+//..             return;
+//..          }
+//.. 
+//..          default: 
+//..             break;
+//..       }
+//..    } /* if (e->tag == Iex_Unop) */
+//.. 
+//.. 
+//..    /* --------- CCALL --------- */
+//..    if (e->tag == Iex_CCall) {
+//..       HReg tLo = newVRegI(env);
+//..       HReg tHi = newVRegI(env);
+//.. 
+//..       /* Marshal args, do the call, clear stack. */
+//..       doHelperCall( env, False, NULL, e->Iex.CCall.cee, e->Iex.CCall.args );
+//.. 
+//..       addInstr(env, mk_iMOVsd_RR(hregX86_EDX(), tHi));
+//..       addInstr(env, mk_iMOVsd_RR(hregX86_EAX(), tLo));
+//..       *rHi = tHi;
+//..       *rLo = tLo;
+//..       return;
+//..    }
+//.. 
+//..    ppIRExpr(e);
+//..    vpanic("iselInt64Expr");
+//.. }
+//.. 
+//.. 
+//.. /*---------------------------------------------------------*/
+//.. /*--- ISEL: Floating point expressions (32 bit)         ---*/
+//.. /*---------------------------------------------------------*/
+//.. 
+//.. /* Nothing interesting here; really just wrappers for
+//..    64-bit stuff. */
+//.. 
+//.. static HReg iselFltExpr ( ISelEnv* env, IRExpr* e )
+//.. {
+//..    HReg r = iselFltExpr_wrk( env, e );
+//.. #  if 0
+//..    vex_printf("\n"); ppIRExpr(e); vex_printf("\n");
+//.. #  endif
+//..    vassert(hregClass(r) == HRcFlt64); /* yes, really Flt64 */
+//..    vassert(hregIsVirtual(r));
+//..    return r;
+//.. }
+//.. 
+//.. /* DO NOT CALL THIS DIRECTLY */
+//.. static HReg iselFltExpr_wrk ( ISelEnv* env, IRExpr* e )
+//.. {
+//..    IRType ty = typeOfIRExpr(env->type_env,e);
+//..    vassert(ty == Ity_F32);
+//.. 
+//..    if (e->tag == Iex_Tmp) {
+//..       return lookupIRTemp(env, e->Iex.Tmp.tmp);
+//..    }
+//.. 
+//..    if (e->tag == Iex_LDle) {
+//..       X86AMode* am;
+//..       HReg res = newVRegF(env);
+//..       vassert(e->Iex.LDle.ty == Ity_F32);
+//..       am = iselIntExpr_AMode(env, e->Iex.LDle.addr);
+//..       addInstr(env, X86Instr_FpLdSt(True/*load*/, 4, res, am));
+//..       return res;
+//..    }
+//.. 
+//..    if (e->tag == Iex_Binop
+//..        && e->Iex.Binop.op == Iop_F64toF32) {
+//..       /* Although the result is still held in a standard FPU register,
+//..          we need to round it to reflect the loss of accuracy/range
+//..          entailed in casting it to a 32-bit float. */
+//..       HReg dst = newVRegF(env);
+//..       HReg src = iselDblExpr(env, e->Iex.Binop.arg2);
+//..       set_FPU_rounding_mode( env, e->Iex.Binop.arg1 );
+//..       addInstr(env, X86Instr_Fp64to32(src,dst));
+//..       set_FPU_rounding_default( env );
+//..       return dst;
+//..    }
+//.. 
+//..    if (e->tag == Iex_Get) {
+//..       X86AMode* am = X86AMode_IR( e->Iex.Get.offset,
+//..                                   hregX86_EBP() );
+//..       HReg res = newVRegF(env);
+//..       addInstr(env, X86Instr_FpLdSt( True/*load*/, 4, res, am ));
+//..       return res;
+//..    }
+//.. 
+//..    if (e->tag == Iex_Unop
+//..        && e->Iex.Unop.op == Iop_ReinterpI32asF32) {
+//..        /* Given an I32, produce an IEEE754 float with the same bit
+//..           pattern. */
+//..       HReg    dst = newVRegF(env);
+//..       X86RMI* rmi = iselIntExpr_RMI(env, e->Iex.Unop.arg);
+//..       /* paranoia */
+//..       addInstr(env, X86Instr_Push(rmi));
+//..       addInstr(env, X86Instr_FpLdSt(
+//..                        True/*load*/, 4, dst, 
+//..                        X86AMode_IR(0, hregX86_ESP())));
+//..       add_to_esp(env, 4);
+//..       return dst;
+//..    }
+//.. 
+//..    ppIRExpr(e);
+//..    vpanic("iselFltExpr_wrk");
+//.. }
+//.. 
+//.. 
+//.. /*---------------------------------------------------------*/
+//.. /*--- ISEL: Floating point expressions (64 bit)         ---*/
+//.. /*---------------------------------------------------------*/
+//.. 
+//.. /* Compute a 64-bit floating point value into a register, the identity
+//..    of which is returned.  As with iselIntExpr_R, the reg may be either
+//..    real or virtual; in any case it must not be changed by subsequent
+//..    code emitted by the caller.  */
+//.. 
+//.. /* IEEE 754 formats.  From http://www.freesoft.org/CIE/RFC/1832/32.htm:
+//.. 
+//..     Type                  S (1 bit)   E (11 bits)   F (52 bits)
+//..     ----                  ---------   -----------   -----------
+//..     signalling NaN        u           2047 (max)    .0uuuuu---u
+//..                                                     (with at least
+//..                                                      one 1 bit)
+//..     quiet NaN             u           2047 (max)    .1uuuuu---u
+//.. 
+//..     negative infinity     1           2047 (max)    .000000---0
+//.. 
+//..     positive infinity     0           2047 (max)    .000000---0
+//.. 
+//..     negative zero         1           0             .000000---0
+//.. 
+//..     positive zero         0           0             .000000---0
+//.. */
+//.. 
+//.. static HReg iselDblExpr ( ISelEnv* env, IRExpr* e )
+//.. {
+//..    HReg r = iselDblExpr_wrk( env, e );
+//.. #  if 0
+//..    vex_printf("\n"); ppIRExpr(e); vex_printf("\n");
+//.. #  endif
+//..    vassert(hregClass(r) == HRcFlt64);
+//..    vassert(hregIsVirtual(r));
+//..    return r;
+//.. }
+//.. 
+//.. /* DO NOT CALL THIS DIRECTLY */
+//.. static HReg iselDblExpr_wrk ( ISelEnv* env, IRExpr* e )
+//.. {
+//..    IRType ty = typeOfIRExpr(env->type_env,e);
+//..    vassert(e);
+//..    vassert(ty == Ity_F64);
+//.. 
+//..    if (e->tag == Iex_Tmp) {
+//..       return lookupIRTemp(env, e->Iex.Tmp.tmp);
+//..    }
+//.. 
+//..    if (e->tag == Iex_Const) {
+//..       union { UInt u32x2[2]; ULong u64; Double f64; } u;
+//..       HReg freg = newVRegF(env);
+//..       vassert(sizeof(u) == 8);
+//..       vassert(sizeof(u.u64) == 8);
+//..       vassert(sizeof(u.f64) == 8);
+//..       vassert(sizeof(u.u32x2) == 8);
+//.. 
+//..       if (e->Iex.Const.con->tag == Ico_F64) {
+//..          u.f64 = e->Iex.Const.con->Ico.F64;
+//..       }
+//..       else if (e->Iex.Const.con->tag == Ico_F64i) {
+//..          u.u64 = e->Iex.Const.con->Ico.F64i;
+//..       }
+//..       else
+//..          vpanic("iselDblExpr(x86): const");
+//.. 
+//..       addInstr(env, X86Instr_Push(X86RMI_Imm(u.u32x2[1])));
+//..       addInstr(env, X86Instr_Push(X86RMI_Imm(u.u32x2[0])));
+//..       addInstr(env, X86Instr_FpLdSt(True/*load*/, 8, freg, 
+//..                                     X86AMode_IR(0, hregX86_ESP())));
+//..       add_to_esp(env, 8);
+//..       return freg;
+//..    }
+//.. 
+//..    if (e->tag == Iex_LDle) {
+//..       X86AMode* am;
+//..       HReg res = newVRegF(env);
+//..       vassert(e->Iex.LDle.ty == Ity_F64);
+//..       am = iselIntExpr_AMode(env, e->Iex.LDle.addr);
+//..       addInstr(env, X86Instr_FpLdSt(True/*load*/, 8, res, am));
+//..       return res;
+//..    }
+//.. 
+//..    if (e->tag == Iex_Get) {
+//..       X86AMode* am = X86AMode_IR( e->Iex.Get.offset,
+//..                                   hregX86_EBP() );
+//..       HReg res = newVRegF(env);
+//..       addInstr(env, X86Instr_FpLdSt( True/*load*/, 8, res, am ));
+//..       return res;
+//..    }
+//.. 
+//..    if (e->tag == Iex_GetI) {
+//..       X86AMode* am 
+//..          = genGuestArrayOffset(
+//..               env, e->Iex.GetI.descr, 
+//..                    e->Iex.GetI.ix, e->Iex.GetI.bias );
+//..       HReg res = newVRegF(env);
+//..       addInstr(env, X86Instr_FpLdSt( True/*load*/, 8, res, am ));
+//..       return res;
+//..    }
+//.. 
+//..    if (e->tag == Iex_Binop) {
+//..       X86FpOp fpop = Xfp_INVALID;
+//..       switch (e->Iex.Binop.op) {
+//..          case Iop_AddF64:    fpop = Xfp_ADD; break;
+//..          case Iop_SubF64:    fpop = Xfp_SUB; break;
+//..          case Iop_MulF64:    fpop = Xfp_MUL; break;
+//..          case Iop_DivF64:    fpop = Xfp_DIV; break;
+//..          case Iop_ScaleF64:  fpop = Xfp_SCALE; break;
+//..          case Iop_AtanF64:   fpop = Xfp_ATAN; break;
+//..          case Iop_Yl2xF64:   fpop = Xfp_YL2X; break;
+//..          case Iop_Yl2xp1F64: fpop = Xfp_YL2XP1; break;
+//..          case Iop_PRemF64:   fpop = Xfp_PREM; break;
+//..          case Iop_PRem1F64:  fpop = Xfp_PREM1; break;
+//..          default: break;
+//..       }
+//..       if (fpop != Xfp_INVALID) {
+//..          HReg res  = newVRegF(env);
+//..          HReg srcL = iselDblExpr(env, e->Iex.Binop.arg1);
+//..          HReg srcR = iselDblExpr(env, e->Iex.Binop.arg2);
+//..          addInstr(env, X86Instr_FpBinary(fpop,srcL,srcR,res));
+//..    if (fpop != Xfp_ADD && fpop != Xfp_SUB 
+//..        && fpop != Xfp_MUL && fpop != Xfp_DIV)
+//..             roundToF64(env, res);
+//..          return res;
+//..       }
+//..    }
+//.. 
+//..    if (e->tag == Iex_Binop && e->Iex.Binop.op == Iop_RoundF64) {
+//..       HReg rf  = iselDblExpr(env, e->Iex.Binop.arg2);
+//..       HReg dst = newVRegF(env);
+//.. 
+//..       /* rf now holds the value to be rounded.  The first thing to do
+//..          is set the FPU's rounding mode accordingly. */
+//.. 
+//..       /* Set host rounding mode */
+//..       set_FPU_rounding_mode( env, e->Iex.Binop.arg1 );
+//.. 
+//..       /* grndint %rf, %dst */
+//..       addInstr(env, X86Instr_FpUnary(Xfp_ROUND, rf, dst));
+//.. 
+//..       /* Restore default FPU rounding. */
+//..       set_FPU_rounding_default( env );
+//.. 
+//..       return dst;
+//..    }
+//.. 
+//..    if (e->tag == Iex_Binop && e->Iex.Binop.op == Iop_I64toF64) {
+//..       HReg dst = newVRegF(env);
+//..       HReg rHi,rLo;
+//..       iselInt64Expr( &rHi, &rLo, env, e->Iex.Binop.arg2);
+//..       addInstr(env, X86Instr_Push(X86RMI_Reg(rHi)));
+//..       addInstr(env, X86Instr_Push(X86RMI_Reg(rLo)));
+//.. 
+//..       /* Set host rounding mode */
+//..       set_FPU_rounding_mode( env, e->Iex.Binop.arg1 );
+//.. 
+//..       addInstr(env, X86Instr_FpLdStI(
+//..                        True/*load*/, 8, dst, 
+//..                        X86AMode_IR(0, hregX86_ESP())));
+//.. 
+//..       /* Restore default FPU rounding. */
+//..       set_FPU_rounding_default( env );
+//.. 
+//..       add_to_esp(env, 8);
+//..       return dst;
+//..    }
+//.. 
+//..    if (e->tag == Iex_Unop) {
+//..       X86FpOp fpop = Xfp_INVALID;
+//..       switch (e->Iex.Unop.op) {
+//..          case Iop_NegF64:  fpop = Xfp_NEG; break;
+//..          case Iop_AbsF64:  fpop = Xfp_ABS; break;
+//..          case Iop_SqrtF64: fpop = Xfp_SQRT; break;
+//..          case Iop_SinF64:  fpop = Xfp_SIN; break;
+//..          case Iop_CosF64:  fpop = Xfp_COS; break;
+//..          case Iop_TanF64:  fpop = Xfp_TAN; break;
+//..          case Iop_2xm1F64: fpop = Xfp_2XM1; break;
+//..          default: break;
+//..       }
+//..       if (fpop != Xfp_INVALID) {
+//..          HReg res = newVRegF(env);
+//..          HReg src = iselDblExpr(env, e->Iex.Unop.arg);
+//..          addInstr(env, X86Instr_FpUnary(fpop,src,res));
+//..    if (fpop != Xfp_SQRT
+//..              && fpop != Xfp_NEG && fpop != Xfp_ABS)
+//..             roundToF64(env, res);
+//..          return res;
+//..       }
+//..    }
+//.. 
+//..    if (e->tag == Iex_Unop) {
+//..       switch (e->Iex.Unop.op) {
+//..          case Iop_I32toF64: {
+//..             HReg dst = newVRegF(env);
+//..             HReg ri  = iselIntExpr_R(env, e->Iex.Unop.arg);
+//..             addInstr(env, X86Instr_Push(X86RMI_Reg(ri)));
+//..             set_FPU_rounding_default(env);
+//..             addInstr(env, X86Instr_FpLdStI(
+//..                              True/*load*/, 4, dst, 
+//..                              X86AMode_IR(0, hregX86_ESP())));
+//..       add_to_esp(env, 4);
+//..             return dst;
+//..          }
+//..          case Iop_ReinterpI64asF64: {
+//..             /* Given an I64, produce an IEEE754 double with the same
+//..                bit pattern. */
+//..             HReg dst = newVRegF(env);
+//..             HReg rHi, rLo;
+//..       iselInt64Expr( &rHi, &rLo, env, e->Iex.Unop.arg);
+//..             /* paranoia */
+//..             set_FPU_rounding_default(env);
+//..             addInstr(env, X86Instr_Push(X86RMI_Reg(rHi)));
+//..             addInstr(env, X86Instr_Push(X86RMI_Reg(rLo)));
+//..             addInstr(env, X86Instr_FpLdSt(
+//..                              True/*load*/, 8, dst, 
+//..                              X86AMode_IR(0, hregX86_ESP())));
+//..       add_to_esp(env, 8);
+//..             return dst;
+//..    }
+//..          case Iop_F32toF64: {
+//..             /* this is a no-op */
+//..             HReg res = iselFltExpr(env, e->Iex.Unop.arg);
+//..             return res;
+//..    }
+//..          default: 
+//..             break;
+//..       }
+//..    }
+//.. 
+//..    /* --------- MULTIPLEX --------- */
+//..    if (e->tag == Iex_Mux0X) {
+//..      if (ty == Ity_F64
+//..          && typeOfIRExpr(env->type_env,e->Iex.Mux0X.cond) == Ity_I8) {
+//..         HReg r8  = iselIntExpr_R(env, e->Iex.Mux0X.cond);
+//..         HReg rX  = iselDblExpr(env, e->Iex.Mux0X.exprX);
+//..         HReg r0  = iselDblExpr(env, e->Iex.Mux0X.expr0);
+//..         HReg dst = newVRegF(env);
+//..         addInstr(env, X86Instr_FpUnary(Xfp_MOV,rX,dst));
+//..         addInstr(env, X86Instr_Test32(X86RI_Imm(0xFF), X86RM_Reg(r8)));
+//..         addInstr(env, X86Instr_FpCMov(Xcc_Z,r0,dst));
+//..         return dst;
+//..       }
+//..    }
+//.. 
+//..    ppIRExpr(e);
+//..    vpanic("iselDblExpr_wrk");
+//.. }
+//.. 
+//.. 
+//.. /*---------------------------------------------------------*/
+//.. /*--- ISEL: SIMD (Vector) expressions, 128 bit.         ---*/
+//.. /*---------------------------------------------------------*/
+//.. 
+//.. static HReg iselVecExpr ( ISelEnv* env, IRExpr* e )
+//.. {
+//..    HReg r = iselVecExpr_wrk( env, e );
+//.. #  if 0
+//..    vex_printf("\n"); ppIRExpr(e); vex_printf("\n");
+//.. #  endif
+//..    vassert(hregClass(r) == HRcVec128);
+//..    vassert(hregIsVirtual(r));
+//..    return r;
+//.. }
+//.. 
+//.. 
+//.. /* DO NOT CALL THIS DIRECTLY */
+//.. static HReg iselVecExpr_wrk ( ISelEnv* env, IRExpr* e )
+//.. {
+//.. 
+/*
+//.. #  define REQUIRE_SSE1                                  \
+//..       do { if (env->subarch == VexSubArchX86_sse0)      \
+//..               goto vec_fail;                            \
+//..       } while (0)
+//.. 
+//.. #  define REQUIRE_SSE2                                  \
+//..       do { if (env->subarch == VexSubArchX86_sse0       \
+//..                || env->subarch == VexSubArchX86_sse1)   \
+//..               goto vec_fail;                            \
+//..       } while (0)
+*/
+//..    Bool     arg1isEReg = False;
+//..    X86SseOp op = Xsse_INVALID;
+//..    IRType   ty = typeOfIRExpr(env->type_env,e);
+//..    vassert(e);
+//..    vassert(ty == Ity_V128);
+//.. 
+//..    REQUIRE_SSE1;
+//.. 
+//..    if (e->tag == Iex_Tmp) {
+//..       return lookupIRTemp(env, e->Iex.Tmp.tmp);
+//..    }
+//.. 
+//..    if (e->tag == Iex_Get) {
+//..       HReg dst = newVRegV(env);
+//..       addInstr(env, X86Instr_SseLdSt(
+//..                        True/*load*/, 
+//..                        dst,
+//..                        X86AMode_IR(e->Iex.Get.offset, hregX86_EBP())
+//..                     )
+//..               );
+//..       return dst;
+//..    }
+//.. 
+//..    if (e->tag == Iex_LDle) {
+//..       HReg      dst = newVRegV(env);
+//..       X86AMode* am  = iselIntExpr_AMode(env, e->Iex.LDle.addr);
+//..       addInstr(env, X86Instr_SseLdSt( True/*load*/, dst, am ));
+//..       return dst;
+//..    }
+//.. 
+//..    if (e->tag == Iex_Const) {
+//..       HReg dst = newVRegV(env);
+//..       vassert(e->Iex.Const.con->tag == Ico_V128);
+//..       addInstr(env, X86Instr_SseConst(e->Iex.Const.con->Ico.V128, dst));
+//..       return dst;
+//..    }
+//.. 
+//..    if (e->tag == Iex_Unop) {
+//..    switch (e->Iex.Unop.op) {
+//.. 
+//..       case Iop_Not128: {
+//..          HReg arg = iselVecExpr(env, e->Iex.Unop.arg);
+//..          return do_sse_Not128(env, arg);
+//..       }
+//.. 
+//..       case Iop_CmpNEZ64x2: {
+//..          /* We can use SSE2 instructions for this. */
+//..          /* Ideally, we want to do a 64Ix2 comparison against zero of
+//..             the operand.  Problem is no such insn exists.  Solution
+//..             therefore is to do a 32Ix4 comparison instead, and bitwise-
+//..             negate (NOT) the result.  Let a,b,c,d be 32-bit lanes, and 
+//..             let the not'd result of this initial comparison be a:b:c:d.
+//..             What we need to compute is (a|b):(a|b):(c|d):(c|d).  So, use
+//..             pshufd to create a value b:a:d:c, and OR that with a:b:c:d,
+//..             giving the required result.
+//.. 
+//..             The required selection sequence is 2,3,0,1, which
+//..             according to Intel's documentation means the pshufd
+//..             literal value is 0xB1, that is, 
+//..             (2 << 6) | (3 << 4) | (0 << 2) | (1 << 0) 
+//..          */
+//..          HReg arg  = iselVecExpr(env, e->Iex.Unop.arg);
+//..          HReg tmp  = newVRegV(env);
+//..          HReg dst  = newVRegV(env);
+//..          REQUIRE_SSE2;
+//..          addInstr(env, X86Instr_SseReRg(Xsse_XOR, tmp, tmp));
+//..          addInstr(env, X86Instr_SseReRg(Xsse_CMPEQ32, arg, tmp));
+//..          tmp = do_sse_Not128(env, tmp);
+//..          addInstr(env, X86Instr_SseShuf(0xB1, tmp, dst));
+//..          addInstr(env, X86Instr_SseReRg(Xsse_OR, tmp, dst));
+//..          return dst;
+//..       }
+//.. 
+//..       case Iop_CmpNEZ32x4: {
+//..          /* Sigh, we have to generate lousy code since this has to
+//..             work on SSE1 hosts */
+//..          /* basically, the idea is: for each lane:
+//..                movl lane, %r ; negl %r   (now CF = lane==0 ? 0 : 1)
+//..                sbbl %r, %r               (now %r = 1Sto32(CF))
+//..                movl %r, lane
+//..          */
+//..          Int       i;
+//..          X86AMode* am;
+//..          X86AMode* esp0 = X86AMode_IR(0, hregX86_ESP());
+//..          HReg      arg  = iselVecExpr(env, e->Iex.Unop.arg);
+//..          HReg      dst  = newVRegV(env);
+//..          HReg      r32  = newVRegI(env);
+//..          sub_from_esp(env, 16);
+//..          addInstr(env, X86Instr_SseLdSt(False/*store*/, arg, esp0));
+//..          for (i = 0; i < 4; i++) {
+//..             am = X86AMode_IR(i*4, hregX86_ESP());
+//..             addInstr(env, X86Instr_Alu32R(Xalu_MOV, X86RMI_Mem(am), r32));
+//..             addInstr(env, X86Instr_Unary32(Xun_NEG, X86RM_Reg(r32)));
+//..             addInstr(env, X86Instr_Alu32R(Xalu_SBB, X86RMI_Reg(r32), r32));
+//..             addInstr(env, X86Instr_Alu32M(Xalu_MOV, X86RI_Reg(r32), am));
+//..          }
+//..          addInstr(env, X86Instr_SseLdSt(True/*load*/, dst, esp0));
+//..          add_to_esp(env, 16);
+//..          return dst;
+//..       }
+//.. 
+//..       case Iop_CmpNEZ8x16:
+//..       case Iop_CmpNEZ16x8: {
+//..          /* We can use SSE2 instructions for this. */
+//..          HReg arg;
+//..          HReg vec0 = newVRegV(env);
+//..          HReg vec1 = newVRegV(env);
+//..          HReg dst  = newVRegV(env);
+//..          X86SseOp cmpOp 
+//..             = e->Iex.Unop.op==Iop_CmpNEZ16x8 ? Xsse_CMPEQ16
+//..                                              : Xsse_CMPEQ8;
+//..          REQUIRE_SSE2;
+//..          addInstr(env, X86Instr_SseReRg(Xsse_XOR, vec0, vec0));
+//..          addInstr(env, mk_vMOVsd_RR(vec0, vec1));
+//..          addInstr(env, X86Instr_Sse32Fx4(Xsse_CMPEQF, vec1, vec1));
+//..          /* defer arg computation to here so as to give CMPEQF as long
+//..             as possible to complete */
+//..          arg = iselVecExpr(env, e->Iex.Unop.arg);
+//..          /* vec0 is all 0s; vec1 is all 1s */
+//..          addInstr(env, mk_vMOVsd_RR(arg, dst));
+//..          /* 16x8 or 8x16 comparison == */
+//..          addInstr(env, X86Instr_SseReRg(cmpOp, vec0, dst));
+//..          /* invert result */
+//..          addInstr(env, X86Instr_SseReRg(Xsse_XOR, vec1, dst));
+//..          return dst;
+//..       }
+//.. 
+//..       case Iop_Recip32Fx4: op = Xsse_RCPF;   goto do_32Fx4_unary;
+//..       case Iop_RSqrt32Fx4: op = Xsse_RSQRTF; goto do_32Fx4_unary;
+//..       case Iop_Sqrt32Fx4:  op = Xsse_SQRTF;  goto do_32Fx4_unary;
+//..       do_32Fx4_unary:
+//..       {
+//..          HReg arg = iselVecExpr(env, e->Iex.Unop.arg);
+//..          HReg dst = newVRegV(env);
+//..          addInstr(env, X86Instr_Sse32Fx4(op, arg, dst));
+//..          return dst;
+//..       }
+//.. 
+//..       case Iop_Recip64Fx2: op = Xsse_RCPF;   goto do_64Fx2_unary;
+//..       case Iop_RSqrt64Fx2: op = Xsse_RSQRTF; goto do_64Fx2_unary;
+//..       case Iop_Sqrt64Fx2:  op = Xsse_SQRTF;  goto do_64Fx2_unary;
+//..       do_64Fx2_unary:
+//..       {
+//..          HReg arg = iselVecExpr(env, e->Iex.Unop.arg);
+//..          HReg dst = newVRegV(env);
+//..          REQUIRE_SSE2;
+//..          addInstr(env, X86Instr_Sse64Fx2(op, arg, dst));
+//..          return dst;
+//..       }
+//.. 
+//..       case Iop_Recip32F0x4: op = Xsse_RCPF;   goto do_32F0x4_unary;
+//..       case Iop_RSqrt32F0x4: op = Xsse_RSQRTF; goto do_32F0x4_unary;
+//..       case Iop_Sqrt32F0x4:  op = Xsse_SQRTF;  goto do_32F0x4_unary;
+//..       do_32F0x4_unary:
+//..       {
+//..          /* A bit subtle.  We have to copy the arg to the result
+//..             register first, because actually doing the SSE scalar insn
+//..             leaves the upper 3/4 of the destination register
+//..             unchanged.  Whereas the required semantics of these
+//..             primops is that the upper 3/4 is simply copied in from the
+//..             argument. */
+//..          HReg arg = iselVecExpr(env, e->Iex.Unop.arg);
+//..          HReg dst = newVRegV(env);
+//..          addInstr(env, mk_vMOVsd_RR(arg, dst));
+//..          addInstr(env, X86Instr_Sse32FLo(op, arg, dst));
+//..          return dst;
+//..       }
+//.. 
+//..       case Iop_Recip64F0x2: op = Xsse_RCPF;   goto do_64F0x2_unary;
+//..       case Iop_RSqrt64F0x2: op = Xsse_RSQRTF; goto do_64F0x2_unary;
+//..       case Iop_Sqrt64F0x2:  op = Xsse_SQRTF;  goto do_64F0x2_unary;
+//..       do_64F0x2_unary:
+//..       {
+//..          /* A bit subtle.  We have to copy the arg to the result
+//..             register first, because actually doing the SSE scalar insn
+//..             leaves the upper half of the destination register
+//..             unchanged.  Whereas the required semantics of these
+//..             primops is that the upper half is simply copied in from the
+//..             argument. */
+//..          HReg arg = iselVecExpr(env, e->Iex.Unop.arg);
+//..          HReg dst = newVRegV(env);
+//..          REQUIRE_SSE2;
+//..          addInstr(env, mk_vMOVsd_RR(arg, dst));
+//..          addInstr(env, X86Instr_Sse64FLo(op, arg, dst));
+//..          return dst;
+//..       }
+//.. 
+//..       case Iop_32Uto128: {
+//..          HReg      dst  = newVRegV(env);
+//..          X86AMode* esp0 = X86AMode_IR(0, hregX86_ESP());
+//..          X86RMI*   rmi  = iselIntExpr_RMI(env, e->Iex.Unop.arg);
+//..          addInstr(env, X86Instr_Push(rmi));
+//..    addInstr(env, X86Instr_SseLdzLO(4, dst, esp0));
+//..          add_to_esp(env, 4);
+//..          return dst;
+//..       }
+//.. 
+//..       case Iop_64Uto128: {
+//..          HReg      rHi, rLo;
+//..          HReg      dst  = newVRegV(env);
+//..          X86AMode* esp0 = X86AMode_IR(0, hregX86_ESP());
+//..          iselInt64Expr(&rHi, &rLo, env, e->Iex.Unop.arg);
+//..          addInstr(env, X86Instr_Push(X86RMI_Reg(rHi)));
+//..          addInstr(env, X86Instr_Push(X86RMI_Reg(rLo)));
+//..    addInstr(env, X86Instr_SseLdzLO(8, dst, esp0));
+//..          add_to_esp(env, 8);
+//..          return dst;
+//..       }
+//.. 
+//..       default:
+//..          break;
+//..    } /* switch (e->Iex.Unop.op) */
+//..    } /* if (e->tag == Iex_Unop) */
+//.. 
+//..    if (e->tag == Iex_Binop) {
+//..    switch (e->Iex.Binop.op) {
+//.. 
+//..       case Iop_Set128lo32: {
+//..          HReg dst = newVRegV(env);
+//..          HReg srcV = iselVecExpr(env, e->Iex.Binop.arg1);
+//..          HReg srcI = iselIntExpr_R(env, e->Iex.Binop.arg2);
+//..          X86AMode* esp0 = X86AMode_IR(0, hregX86_ESP());
+//..          sub_from_esp(env, 16);
+//..          addInstr(env, X86Instr_SseLdSt(False/*store*/, srcV, esp0));
+//..          addInstr(env, X86Instr_Alu32M(Xalu_MOV, X86RI_Reg(srcI), esp0));
+//..          addInstr(env, X86Instr_SseLdSt(True/*load*/, dst, esp0));
+//..          add_to_esp(env, 16);
+//..          return dst;
+//..       }
+//.. 
+//..       case Iop_Set128lo64: {
+//..          HReg dst = newVRegV(env);
+//..          HReg srcV = iselVecExpr(env, e->Iex.Binop.arg1);
+//..          HReg srcIhi, srcIlo;
+//..          X86AMode* esp0 = X86AMode_IR(0, hregX86_ESP());
+//..          X86AMode* esp4 = advance4(esp0);
+//..          iselInt64Expr(&srcIhi, &srcIlo, env, e->Iex.Binop.arg2);
+//..          sub_from_esp(env, 16);
+//..          addInstr(env, X86Instr_SseLdSt(False/*store*/, srcV, esp0));
+//..          addInstr(env, X86Instr_Alu32M(Xalu_MOV, X86RI_Reg(srcIlo), esp0));
+//..          addInstr(env, X86Instr_Alu32M(Xalu_MOV, X86RI_Reg(srcIhi), esp4));
+//..          addInstr(env, X86Instr_SseLdSt(True/*load*/, dst, esp0));
+//..          add_to_esp(env, 16);
+//..          return dst;
+//..       }
+//.. 
+//..       case Iop_64HLto128: {
+//..          HReg r3, r2, r1, r0;
+//..          X86AMode* esp0  = X86AMode_IR(0, hregX86_ESP());
+//..          X86AMode* esp4  = advance4(esp0);
+//..          X86AMode* esp8  = advance4(esp4);
+//..          X86AMode* esp12 = advance4(esp8);
+//..          HReg dst = newVRegV(env);
+//..    /* do this via the stack (easy, convenient, etc) */
+//..          sub_from_esp(env, 16);
+//..          /* Do the less significant 64 bits */
+//..          iselInt64Expr(&r1, &r0, env, e->Iex.Binop.arg2);
+//..          addInstr(env, X86Instr_Alu32M(Xalu_MOV, X86RI_Reg(r0), esp0));
+//..          addInstr(env, X86Instr_Alu32M(Xalu_MOV, X86RI_Reg(r1), esp4));
+//..          /* Do the more significant 64 bits */
+//..          iselInt64Expr(&r3, &r2, env, e->Iex.Binop.arg1);
+//..          addInstr(env, X86Instr_Alu32M(Xalu_MOV, X86RI_Reg(r2), esp8));
+//..          addInstr(env, X86Instr_Alu32M(Xalu_MOV, X86RI_Reg(r3), esp12));
+//..    /* Fetch result back from stack. */
+//..          addInstr(env, X86Instr_SseLdSt(True/*load*/, dst, esp0));
+//..          add_to_esp(env, 16);
+//..          return dst;
+//..       }
+//.. 
+//..       case Iop_CmpEQ32Fx4: op = Xsse_CMPEQF; goto do_32Fx4;
+//..       case Iop_CmpLT32Fx4: op = Xsse_CMPLTF; goto do_32Fx4;
+//..       case Iop_CmpLE32Fx4: op = Xsse_CMPLEF; goto do_32Fx4;
+//..       case Iop_Add32Fx4:   op = Xsse_ADDF;   goto do_32Fx4;
+//..       case Iop_Div32Fx4:   op = Xsse_DIVF;   goto do_32Fx4;
+//..       case Iop_Max32Fx4:   op = Xsse_MAXF;   goto do_32Fx4;
+//..       case Iop_Min32Fx4:   op = Xsse_MINF;   goto do_32Fx4;
+//..       case Iop_Mul32Fx4:   op = Xsse_MULF;   goto do_32Fx4;
+//..       case Iop_Sub32Fx4:   op = Xsse_SUBF;   goto do_32Fx4;
+//..       do_32Fx4:
+//..       {
+//..          HReg argL = iselVecExpr(env, e->Iex.Binop.arg1);
+//..          HReg argR = iselVecExpr(env, e->Iex.Binop.arg2);
+//..          HReg dst = newVRegV(env);
+//..          addInstr(env, mk_vMOVsd_RR(argL, dst));
+//..          addInstr(env, X86Instr_Sse32Fx4(op, argR, dst));
+//..          return dst;
+//..       }
+//.. 
+//..       case Iop_CmpEQ64Fx2: op = Xsse_CMPEQF; goto do_64Fx2;
+//..       case Iop_CmpLT64Fx2: op = Xsse_CMPLTF; goto do_64Fx2;
+//..       case Iop_CmpLE64Fx2: op = Xsse_CMPLEF; goto do_64Fx2;
+//..       case Iop_Add64Fx2:   op = Xsse_ADDF;   goto do_64Fx2;
+//..       case Iop_Div64Fx2:   op = Xsse_DIVF;   goto do_64Fx2;
+//..       case Iop_Max64Fx2:   op = Xsse_MAXF;   goto do_64Fx2;
+//..       case Iop_Min64Fx2:   op = Xsse_MINF;   goto do_64Fx2;
+//..       case Iop_Mul64Fx2:   op = Xsse_MULF;   goto do_64Fx2;
+//..       case Iop_Sub64Fx2:   op = Xsse_SUBF;   goto do_64Fx2;
+//..       do_64Fx2:
+//..       {
+//..          HReg argL = iselVecExpr(env, e->Iex.Binop.arg1);
+//..          HReg argR = iselVecExpr(env, e->Iex.Binop.arg2);
+//..          HReg dst = newVRegV(env);
+//..          REQUIRE_SSE2;
+//..          addInstr(env, mk_vMOVsd_RR(argL, dst));
+//..          addInstr(env, X86Instr_Sse64Fx2(op, argR, dst));
+//..          return dst;
+//..       }
+//.. 
+//..       case Iop_CmpEQ32F0x4: op = Xsse_CMPEQF; goto do_32F0x4;
+//..       case Iop_CmpLT32F0x4: op = Xsse_CMPLTF; goto do_32F0x4;
+//..       case Iop_CmpLE32F0x4: op = Xsse_CMPLEF; goto do_32F0x4;
+//..       case Iop_Add32F0x4:   op = Xsse_ADDF;   goto do_32F0x4;
+//..       case Iop_Div32F0x4:   op = Xsse_DIVF;   goto do_32F0x4;
+//..       case Iop_Max32F0x4:   op = Xsse_MAXF;   goto do_32F0x4;
+//..       case Iop_Min32F0x4:   op = Xsse_MINF;   goto do_32F0x4;
+//..       case Iop_Mul32F0x4:   op = Xsse_MULF;   goto do_32F0x4;
+//..       case Iop_Sub32F0x4:   op = Xsse_SUBF;   goto do_32F0x4;
+//..       do_32F0x4: {
+//..          HReg argL = iselVecExpr(env, e->Iex.Binop.arg1);
+//..          HReg argR = iselVecExpr(env, e->Iex.Binop.arg2);
+//..          HReg dst = newVRegV(env);
+//..          addInstr(env, mk_vMOVsd_RR(argL, dst));
+//..          addInstr(env, X86Instr_Sse32FLo(op, argR, dst));
+//..          return dst;
+//..       }
+//.. 
+//..       case Iop_CmpEQ64F0x2: op = Xsse_CMPEQF; goto do_64F0x2;
+//..       case Iop_CmpLT64F0x2: op = Xsse_CMPLTF; goto do_64F0x2;
+//..       case Iop_CmpLE64F0x2: op = Xsse_CMPLEF; goto do_64F0x2;
+//..       case Iop_Add64F0x2:   op = Xsse_ADDF;   goto do_64F0x2;
+//..       case Iop_Div64F0x2:   op = Xsse_DIVF;   goto do_64F0x2;
+//..       case Iop_Max64F0x2:   op = Xsse_MAXF;   goto do_64F0x2;
+//..       case Iop_Min64F0x2:   op = Xsse_MINF;   goto do_64F0x2;
+//..       case Iop_Mul64F0x2:   op = Xsse_MULF;   goto do_64F0x2;
+//..       case Iop_Sub64F0x2:   op = Xsse_SUBF;   goto do_64F0x2;
+//..       do_64F0x2: {
+//..          HReg argL = iselVecExpr(env, e->Iex.Binop.arg1);
+//..          HReg argR = iselVecExpr(env, e->Iex.Binop.arg2);
+//..          HReg dst = newVRegV(env);
+//..          REQUIRE_SSE2;
+//..          addInstr(env, mk_vMOVsd_RR(argL, dst));
+//..          addInstr(env, X86Instr_Sse64FLo(op, argR, dst));
+//..          return dst;
+//..       }
+//.. 
+//..       case Iop_QNarrow32Sx4: 
+//..          op = Xsse_PACKSSD; arg1isEReg = True; goto do_SseReRg;
+//..       case Iop_QNarrow16Sx8: 
+//..          op = Xsse_PACKSSW; arg1isEReg = True; goto do_SseReRg;
+//..       case Iop_QNarrow16Ux8: 
+//..          op = Xsse_PACKUSW; arg1isEReg = True; goto do_SseReRg;
+//.. 
+//..       case Iop_InterleaveHI8x16: 
+//..          op = Xsse_UNPCKHB; arg1isEReg = True; goto do_SseReRg;
+//..       case Iop_InterleaveHI16x8: 
+//..          op = Xsse_UNPCKHW; arg1isEReg = True; goto do_SseReRg;
+//..       case Iop_InterleaveHI32x4: 
+//..          op = Xsse_UNPCKHD; arg1isEReg = True; goto do_SseReRg;
+//..       case Iop_InterleaveHI64x2: 
+//..          op = Xsse_UNPCKHQ; arg1isEReg = True; goto do_SseReRg;
+//.. 
+//..       case Iop_InterleaveLO8x16: 
+//..          op = Xsse_UNPCKLB; arg1isEReg = True; goto do_SseReRg;
+//..       case Iop_InterleaveLO16x8: 
+//..          op = Xsse_UNPCKLW; arg1isEReg = True; goto do_SseReRg;
+//..       case Iop_InterleaveLO32x4: 
+//..          op = Xsse_UNPCKLD; arg1isEReg = True; goto do_SseReRg;
+//..       case Iop_InterleaveLO64x2: 
+//..          op = Xsse_UNPCKLQ; arg1isEReg = True; goto do_SseReRg;
+//.. 
+//..       case Iop_And128:     op = Xsse_AND;      goto do_SseReRg;
+//..       case Iop_Or128:      op = Xsse_OR;       goto do_SseReRg;
+//..       case Iop_Xor128:     op = Xsse_XOR;      goto do_SseReRg;
+//..       case Iop_Add8x16:    op = Xsse_ADD8;     goto do_SseReRg;
+//..       case Iop_Add16x8:    op = Xsse_ADD16;    goto do_SseReRg;
+//..       case Iop_Add32x4:    op = Xsse_ADD32;    goto do_SseReRg;
+//..       case Iop_Add64x2:    op = Xsse_ADD64;    goto do_SseReRg;
+//..       case Iop_QAdd8Sx16:  op = Xsse_QADD8S;   goto do_SseReRg;
+//..       case Iop_QAdd16Sx8:  op = Xsse_QADD16S;  goto do_SseReRg;
+//..       case Iop_QAdd8Ux16:  op = Xsse_QADD8U;   goto do_SseReRg;
+//..       case Iop_QAdd16Ux8:  op = Xsse_QADD16U;  goto do_SseReRg;
+//..       case Iop_Avg8Ux16:   op = Xsse_AVG8U;    goto do_SseReRg;
+//..       case Iop_Avg16Ux8:   op = Xsse_AVG16U;   goto do_SseReRg;
+//..       case Iop_CmpEQ8x16:  op = Xsse_CMPEQ8;   goto do_SseReRg;
+//..       case Iop_CmpEQ16x8:  op = Xsse_CMPEQ16;  goto do_SseReRg;
+//..       case Iop_CmpEQ32x4:  op = Xsse_CMPEQ32;  goto do_SseReRg;
+//..       case Iop_CmpGT8Sx16: op = Xsse_CMPGT8S;  goto do_SseReRg;
+//..       case Iop_CmpGT16Sx8: op = Xsse_CMPGT16S; goto do_SseReRg;
+//..       case Iop_CmpGT32Sx4: op = Xsse_CMPGT32S; goto do_SseReRg;
+//..       case Iop_Max16Sx8:   op = Xsse_MAX16S;   goto do_SseReRg;
+//..       case Iop_Max8Ux16:   op = Xsse_MAX8U;    goto do_SseReRg;
+//..       case Iop_Min16Sx8:   op = Xsse_MIN16S;   goto do_SseReRg;
+//..       case Iop_Min8Ux16:   op = Xsse_MIN8U;    goto do_SseReRg;
+//..       case Iop_MulHi16Ux8: op = Xsse_MULHI16U; goto do_SseReRg;
+//..       case Iop_MulHi16Sx8: op = Xsse_MULHI16S; goto do_SseReRg;
+//..       case Iop_Mul16x8:    op = Xsse_MUL16;    goto do_SseReRg;
+//..       case Iop_Sub8x16:    op = Xsse_SUB8;     goto do_SseReRg;
+//..       case Iop_Sub16x8:    op = Xsse_SUB16;    goto do_SseReRg;
+//..       case Iop_Sub32x4:    op = Xsse_SUB32;    goto do_SseReRg;
+//..       case Iop_Sub64x2:    op = Xsse_SUB64;    goto do_SseReRg;
+//..       case Iop_QSub8Sx16:  op = Xsse_QSUB8S;   goto do_SseReRg;
+//..       case Iop_QSub16Sx8:  op = Xsse_QSUB16S;  goto do_SseReRg;
+//..       case Iop_QSub8Ux16:  op = Xsse_QSUB8U;   goto do_SseReRg;
+//..       case Iop_QSub16Ux8:  op = Xsse_QSUB16U;  goto do_SseReRg;
+//..       do_SseReRg: {
+//..          HReg arg1 = iselVecExpr(env, e->Iex.Binop.arg1);
+//..          HReg arg2 = iselVecExpr(env, e->Iex.Binop.arg2);
+//..          HReg dst = newVRegV(env);
+//..          if (op != Xsse_OR && op != Xsse_AND && op != Xsse_XOR)
+//..             REQUIRE_SSE2;
+//..          if (arg1isEReg) {
+//..             addInstr(env, mk_vMOVsd_RR(arg2, dst));
+//..             addInstr(env, X86Instr_SseReRg(op, arg1, dst));
+//..          } else {
+//..             addInstr(env, mk_vMOVsd_RR(arg1, dst));
+//..             addInstr(env, X86Instr_SseReRg(op, arg2, dst));
+//..          }
+//..          return dst;
+//..       }
+//.. 
+//..       case Iop_ShlN16x8: op = Xsse_SHL16; goto do_SseShift;
+//..       case Iop_ShlN32x4: op = Xsse_SHL32; goto do_SseShift;
+//..       case Iop_ShlN64x2: op = Xsse_SHL64; goto do_SseShift;
+//..       case Iop_SarN16x8: op = Xsse_SAR16; goto do_SseShift;
+//..       case Iop_SarN32x4: op = Xsse_SAR32; goto do_SseShift;
+//..       case Iop_ShrN16x8: op = Xsse_SHR16; goto do_SseShift;
+//..       case Iop_ShrN32x4: op = Xsse_SHR32; goto do_SseShift;
+//..       case Iop_ShrN64x2: op = Xsse_SHR64; goto do_SseShift;
+//..       do_SseShift: {
+//..          HReg      greg = iselVecExpr(env, e->Iex.Binop.arg1);
+//..          X86RMI*   rmi  = iselIntExpr_RMI(env, e->Iex.Binop.arg2);
+//..          X86AMode* esp0 = X86AMode_IR(0, hregX86_ESP());
+//..          HReg      ereg = newVRegV(env);
+//..          HReg      dst  = newVRegV(env);
+//..          REQUIRE_SSE2;
+//..          addInstr(env, X86Instr_Push(X86RMI_Imm(0)));
+//..          addInstr(env, X86Instr_Push(X86RMI_Imm(0)));
+//..          addInstr(env, X86Instr_Push(X86RMI_Imm(0)));
+//..          addInstr(env, X86Instr_Push(rmi));
+//..          addInstr(env, X86Instr_SseLdSt(True/*load*/, ereg, esp0));
+//..    addInstr(env, mk_vMOVsd_RR(greg, dst));
+//..          addInstr(env, X86Instr_SseReRg(op, ereg, dst));
+//..          add_to_esp(env, 16);
+//..          return dst;
+//..       }
+//.. 
+//..       default:
+//..          break;
+//..    } /* switch (e->Iex.Binop.op) */
+//..    } /* if (e->tag == Iex_Binop) */
+//.. 
+//..    if (e->tag == Iex_Mux0X) {
+//..       HReg r8  = iselIntExpr_R(env, e->Iex.Mux0X.cond);
+//..       HReg rX  = iselVecExpr(env, e->Iex.Mux0X.exprX);
+//..       HReg r0  = iselVecExpr(env, e->Iex.Mux0X.expr0);
+//..       HReg dst = newVRegV(env);
+//..       addInstr(env, mk_vMOVsd_RR(rX,dst));
+//..       addInstr(env, X86Instr_Test32(X86RI_Imm(0xFF), X86RM_Reg(r8)));
+//..       addInstr(env, X86Instr_SseCMov(Xcc_Z,r0,dst));
+//..       return dst;
+//..    }
+//.. 
+//..    vec_fail:
+//..    vex_printf("iselVecExpr (subarch = %s): can't reduce\n",
+//..               LibVEX_ppVexSubArch(env->subarch));
+//..    ppIRExpr(e);
+//..    vpanic("iselVecExpr_wrk");
+//.. 
+//.. #  undef REQUIRE_SSE1
+//.. #  undef REQUIRE_SSE2
+//.. }
+
+
+/*---------------------------------------------------------*/
+/*--- ISEL: Statements                                  ---*/
+/*---------------------------------------------------------*/
+
+static void iselStmt ( ISelEnv* env, IRStmt* stmt )
+{
+   if (vex_traceflags & VEX_TRACE_VCODE) {
+      vex_printf("\n-- ");
+      ppIRStmt(stmt);
+      vex_printf("\n");
+   }
+
+   switch (stmt->tag) {
+
+//..    /* --------- STORE --------- */
+//..    case Ist_STle: {
+//..       X86AMode* am;
+//..       IRType tya = typeOfIRExpr(env->type_env, stmt->Ist.STle.addr);
+//..       IRType tyd = typeOfIRExpr(env->type_env, stmt->Ist.STle.data);
+//..       vassert(tya == Ity_I32);
+//..       am = iselIntExpr_AMode(env, stmt->Ist.STle.addr);
+//..       if (tyd == Ity_I32) {
+//..          X86RI* ri = iselIntExpr_RI(env, stmt->Ist.STle.data);
+//..          addInstr(env, X86Instr_Alu32M(Xalu_MOV,ri,am));
+//..          return;
+//..       }
+//..       if (tyd == Ity_I8 || tyd == Ity_I16) {
+//..          HReg r = iselIntExpr_R(env, stmt->Ist.STle.data);
+//..          addInstr(env, X86Instr_Store(tyd==Ity_I8 ? 1 : 2,
+//..                                       r,am));
+//..          return;
+//..       }
+//..       if (tyd == Ity_F64) {
+//..          HReg r = iselDblExpr(env, stmt->Ist.STle.data);
+//..          addInstr(env, X86Instr_FpLdSt(False/*store*/, 8, r, am));
+//..          return;
+//..       }
+//..       if (tyd == Ity_F32) {
+//..          HReg r = iselFltExpr(env, stmt->Ist.STle.data);
+//..          addInstr(env, X86Instr_FpLdSt(False/*store*/, 4, r, am));
+//..          return;
+//..       }
+//..       if (tyd == Ity_I64) {
+//..          HReg vHi, vLo, rA;
+//..          iselInt64Expr(&vHi, &vLo, env, stmt->Ist.STle.data);
+//..          rA = iselIntExpr_R(env, stmt->Ist.STle.addr);
+//..          addInstr(env, X86Instr_Alu32M(
+//..                           Xalu_MOV, X86RI_Reg(vLo), X86AMode_IR(0, rA)));
+//..          addInstr(env, X86Instr_Alu32M(
+//..                           Xalu_MOV, X86RI_Reg(vHi), X86AMode_IR(4, rA)));
+//..          return;
+//..       }
+//..       if (tyd == Ity_V128) {
+//..          HReg r = iselVecExpr(env, stmt->Ist.STle.data);
+//..          addInstr(env, X86Instr_SseLdSt(False/*store*/, r, am));
+//..          return;
+//..       }
+//..       break;
+//..    }
+//.. 
+//..    /* --------- PUT --------- */
+//..    case Ist_Put: {
+//..       IRType ty = typeOfIRExpr(env->type_env, stmt->Ist.Put.data);
+//..       if (ty == Ity_I32) {
+//..          /* We're going to write to memory, so compute the RHS into an
+//..             X86RI. */
+//..          X86RI* ri = iselIntExpr_RI(env, stmt->Ist.Put.data);
+//..          addInstr(env,
+//..                   X86Instr_Alu32M(
+//..                      Xalu_MOV,
+//..                      ri,
+//..                      X86AMode_IR(stmt->Ist.Put.offset,hregX86_EBP())
+//..                  ));
+//..          return;
+//..       }
+//..       if (ty == Ity_I8 || ty == Ity_I16) {
+//..          HReg r = iselIntExpr_R(env, stmt->Ist.Put.data);
+//..          addInstr(env, X86Instr_Store(
+//..                           ty==Ity_I8 ? 1 : 2,
+//..                           r,
+//..                           X86AMode_IR(stmt->Ist.Put.offset,
+//..                                       hregX86_EBP())));
+//..          return;
+//..       }
+//..       if (ty == Ity_I64) {
+//..          HReg vHi, vLo;
+//..          X86AMode* am  = X86AMode_IR(stmt->Ist.Put.offset, hregX86_EBP());
+//..          X86AMode* am4 = advance4(am);
+//..          iselInt64Expr(&vHi, &vLo, env, stmt->Ist.Put.data);
+//..          addInstr(env, X86Instr_Alu32M( Xalu_MOV, X86RI_Reg(vLo), am ));
+//..          addInstr(env, X86Instr_Alu32M( Xalu_MOV, X86RI_Reg(vHi), am4 ));
+//..          return;
+//..       }
+//..       if (ty == Ity_V128) {
+//..          HReg      vec = iselVecExpr(env, stmt->Ist.Put.data);
+//..          X86AMode* am  = X86AMode_IR(stmt->Ist.Put.offset, hregX86_EBP());
+//..          addInstr(env, X86Instr_SseLdSt(False/*store*/, vec, am));
+//..          return;
+//..       }
+//..       if (ty == Ity_F32) {
+//..          HReg f32 = iselFltExpr(env, stmt->Ist.Put.data);
+//..          X86AMode* am  = X86AMode_IR(stmt->Ist.Put.offset, hregX86_EBP());
+//..          set_FPU_rounding_default(env); /* paranoia */
+//..          addInstr(env, X86Instr_FpLdSt( False/*store*/, 4, f32, am ));
+//..          return;
+//..       }
+//..       if (ty == Ity_F64) {
+//..          HReg f64 = iselDblExpr(env, stmt->Ist.Put.data);
+//..          X86AMode* am  = X86AMode_IR(stmt->Ist.Put.offset, hregX86_EBP());
+//..          set_FPU_rounding_default(env); /* paranoia */
+//..          addInstr(env, X86Instr_FpLdSt( False/*store*/, 8, f64, am ));
+//..          return;
+//..       }
+//..       break;
+//..    }
+//.. 
+//..    /* --------- Indexed PUT --------- */
+//..    case Ist_PutI: {
+//..       X86AMode* am 
+//..          = genGuestArrayOffset(
+//..               env, stmt->Ist.PutI.descr, 
+//..                    stmt->Ist.PutI.ix, stmt->Ist.PutI.bias );
+//.. 
+//..       IRType ty = typeOfIRExpr(env->type_env, stmt->Ist.PutI.data);
+//..       if (ty == Ity_F64) {
+//..          HReg val = iselDblExpr(env, stmt->Ist.PutI.data);
+//..          addInstr(env, X86Instr_FpLdSt( False/*store*/, 8, val, am ));
+//..          return;
+//..       }
+//..       if (ty == Ity_I8) {
+//..          HReg r = iselIntExpr_R(env, stmt->Ist.PutI.data);
+//..          addInstr(env, X86Instr_Store( 1, r, am ));
+//..          return;
+//..       }
+//..       if (ty == Ity_I64) {
+//..          HReg rHi, rLo;
+//..          X86AMode* am4 = advance4(am);
+//..          iselInt64Expr(&rHi, &rLo, env, stmt->Ist.PutI.data);
+//..          addInstr(env, X86Instr_Alu32M( Xalu_MOV, X86RI_Reg(rLo), am ));
+//..          addInstr(env, X86Instr_Alu32M( Xalu_MOV, X86RI_Reg(rHi), am4 ));
+//..          return;
+//..       }
+//..       break;
+//..    }
+//.. 
+//..    /* --------- TMP --------- */
+//..    case Ist_Tmp: {
+//..       IRTemp tmp = stmt->Ist.Tmp.tmp;
+//..       IRType ty = typeOfIRTemp(env->type_env, tmp);
+//..       if (ty == Ity_I32 || ty == Ity_I16 || ty == Ity_I8) {
+//..          X86RMI* rmi = iselIntExpr_RMI(env, stmt->Ist.Tmp.data);
+//..          HReg dst = lookupIRTemp(env, tmp);
+//..          addInstr(env, X86Instr_Alu32R(Xalu_MOV,rmi,dst));
+//..          return;
+//..       }
+//..       if (ty == Ity_I64) {
+//..          HReg rHi, rLo, dstHi, dstLo;
+//..          iselInt64Expr(&rHi,&rLo, env, stmt->Ist.Tmp.data);
+//..          lookupIRTemp64( &dstHi, &dstLo, env, tmp);
+//..          addInstr(env, mk_iMOVsd_RR(rHi,dstHi) );
+//..          addInstr(env, mk_iMOVsd_RR(rLo,dstLo) );
+//..          return;
+//..       }
+//..       if (ty == Ity_I1) {
+//..          X86CondCode cond = iselCondCode(env, stmt->Ist.Tmp.data);
+//..          HReg dst = lookupIRTemp(env, tmp);
+//..          addInstr(env, X86Instr_Set32(cond, dst));
+//..          return;
+//..       }
+//..       if (ty == Ity_F64) {
+//..          HReg dst = lookupIRTemp(env, tmp);
+//..          HReg src = iselDblExpr(env, stmt->Ist.Tmp.data);
+//..          addInstr(env, X86Instr_FpUnary(Xfp_MOV,src,dst));
+//..          return;
+//..       }
+//..       if (ty == Ity_F32) {
+//..          HReg dst = lookupIRTemp(env, tmp);
+//..          HReg src = iselFltExpr(env, stmt->Ist.Tmp.data);
+//..          addInstr(env, X86Instr_FpUnary(Xfp_MOV,src,dst));
+//..          return;
+//..       }
+//..       if (ty == Ity_V128) {
+//..          HReg dst = lookupIRTemp(env, tmp);
+//..          HReg src = iselVecExpr(env, stmt->Ist.Tmp.data);
+//..          addInstr(env, mk_vMOVsd_RR(src,dst));
+//..          return;
+//..       }
+//..       break;
+//..    }
+//.. 
+//..    /* --------- Call to DIRTY helper --------- */
+//..    case Ist_Dirty: {
+//..       IRType   retty;
+//..       IRDirty* d = stmt->Ist.Dirty.details;
+//..       Bool     passBBP = False;
+//.. 
+//..       if (d->nFxState == 0)
+//..          vassert(!d->needsBBP);
+//..       passBBP = d->nFxState > 0 && d->needsBBP;
+//.. 
+//..       /* Marshal args, do the call, clear stack. */
+//..       doHelperCall( env, passBBP, d->guard, d->cee, d->args );
+//.. 
+//..       /* Now figure out what to do with the returned value, if any. */
+//..       if (d->tmp == IRTemp_INVALID)
+//..          /* No return value.  Nothing to do. */
+//..          return;
+//.. 
+//..       retty = typeOfIRTemp(env->type_env, d->tmp);
+//..       if (retty == Ity_I64) {
+//..          HReg dstHi, dstLo;
+//..          /* The returned value is in %edx:%eax.  Park it in the
+//..             register-pair associated with tmp. */
+//..          lookupIRTemp64( &dstHi, &dstLo, env, d->tmp);
+//..          addInstr(env, mk_iMOVsd_RR(hregX86_EDX(),dstHi) );
+//..          addInstr(env, mk_iMOVsd_RR(hregX86_EAX(),dstLo) );
+//..          return;
+//..       }
+//..       if (retty == Ity_I32 || retty == Ity_I16 || retty == Ity_I8) {
+//..          /* The returned value is in %eax.  Park it in the register
+//..             associated with tmp. */
+//..          HReg dst = lookupIRTemp(env, d->tmp);
+//..          addInstr(env, mk_iMOVsd_RR(hregX86_EAX(),dst) );
+//..          return;
+//..       }
+//..       break;
+//..    }
+//.. 
+//..    /* --------- MEM FENCE --------- */
+//..    case Ist_MFence:
+//..       addInstr(env, X86Instr_MFence(env->subarch));
+//..       return;
+//.. 
+//..    /* --------- EXIT --------- */
+//..    case Ist_Exit: {
+//..       X86RI*      dst;
+//..       X86CondCode cc;
+//..       if (stmt->Ist.Exit.dst->tag != Ico_U32)
+//..          vpanic("isel_x86: Ist_Exit: dst is not a 32-bit value");
+//..       dst = iselIntExpr_RI(env, IRExpr_Const(stmt->Ist.Exit.dst));
+//..       cc  = iselCondCode(env,stmt->Ist.Exit.guard);
+//..       addInstr(env, X86Instr_Goto(stmt->Ist.Exit.jk, cc, dst));
+//..       return;
+//..    }
+
+   default: break;
+   }
+   ppIRStmt(stmt);
+   vpanic("iselStmt");
+}
+
+/*---------------------------------------------------------*/
+/*--- ISEL: Basic block terminators (Nexts)             ---*/
+/*---------------------------------------------------------*/
+
+static void iselNext ( ISelEnv* env, IRExpr* next, IRJumpKind jk )
+{ vassert(0);
+//..    X86RI* ri;
+//..    if (vex_traceflags & VEX_TRACE_VCODE) {
+//..       vex_printf("\n-- goto {");
+//..       ppIRJumpKind(jk);
+//..       vex_printf("} ");
+//..       ppIRExpr(next);
+//..       vex_printf("\n");
+//..    }
+//..    ri = iselIntExpr_RI(env, next);
+//..    addInstr(env, X86Instr_Goto(jk, Xcc_ALWAYS,ri));
+}
+
+
+/*---------------------------------------------------------*/
+/*--- Insn selector top-level                           ---*/
+/*---------------------------------------------------------*/
+
+/* Translate an entire BB to x86 code. */
+
+HInstrArray* iselBB_PPC32 ( IRBB* bb, VexSubArch subarch_host )
+{
+   Int     i, j;
+   HReg    hreg, hregHI;
+
+   /* sanity ... */
+   vassert(subarch_host == VexSubArchPPC32_noAV
+           || subarch_host == VexSubArchPPC32_AV);
+
+   /* Make up an initial environment to use. */
+   ISelEnv* env = LibVEX_Alloc(sizeof(ISelEnv));
+   env->vreg_ctr = 0;
+
+   /* Set up output code array. */
+   env->code = newHInstrArray();
+
+   /* Copy BB's type env. */
+   env->type_env = bb->tyenv;
+
+   /* Make up an IRTemp -> virtual HReg mapping.  This doesn't
+      change as we go along. */
+   env->n_vregmap = bb->tyenv->types_used;
+   env->vregmap   = LibVEX_Alloc(env->n_vregmap * sizeof(HReg));
+   env->vregmapHI = LibVEX_Alloc(env->n_vregmap * sizeof(HReg));
+
+   /* and finally ... */
+   env->subarch = subarch_host;
+
+   /* For each IR temporary, allocate a suitably-kinded virtual
+      register. */
+   j = 0;
+   for (i = 0; i < env->n_vregmap; i++) {
+      hregHI = hreg = INVALID_HREG;
+      switch (bb->tyenv->types[i]) {
+         case Ity_I1:
+         case Ity_I8:
+         case Ity_I16:
+         case Ity_I32:  hreg   = mkHReg(j++, HRcInt32, True); break;
+         case Ity_I64:  hreg   = mkHReg(j++, HRcInt32, True);
+                        hregHI = mkHReg(j++, HRcInt32, True); break;
+         case Ity_F32:
+         case Ity_F64:  hreg   = mkHReg(j++, HRcFlt64, True); break;
+         case Ity_V128: hreg   = mkHReg(j++, HRcVec128, True); break;
+         default: ppIRType(bb->tyenv->types[i]);
+                  vpanic("iselBB(ppc32): IRTemp type");
+      }
+      env->vregmap[i]   = hreg;
+      env->vregmapHI[i] = hregHI;
+   }
+   env->vreg_ctr = j;
+
+   /* Ok, finally we can iterate over the statements. */
+   for (i = 0; i < bb->stmts_used; i++)
+      if (bb->stmts[i])
+         iselStmt(env,bb->stmts[i]);
+
+   iselNext(env,bb->next,bb->jumpkind);
+
+   /* record the number of vregs we used. */
+   env->code->n_vregs = env->vreg_ctr;
+   return env->code;
+}
+
+
+/*---------------------------------------------------------------*/
+/*--- end                                   host-ppc32/isel.c ---*/
+/*---------------------------------------------------------------*/