--- /dev/null
+
+/*---------------------------------------------------------------*/
+/*--- ---*/
+/*--- 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 ---*/
+/*---------------------------------------------------------------*/
--- /dev/null
+
+/*---------------------------------------------------------------*/
+/*--- ---*/
+/*--- 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 ---*/
+/*---------------------------------------------------------------*/