1ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
3ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- begin                                   host_x86_defs.c ---*/
4ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
5ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
7ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This file is part of Valgrind, a dynamic binary instrumentation
8ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   framework.
9ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Copyright (C) 2004-2011 OpenWorks LLP
11ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      info@open-works.net
12ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This program is free software; you can redistribute it and/or
14ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   modify it under the terms of the GNU General Public License as
15ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   published by the Free Software Foundation; either version 2 of the
16ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   License, or (at your option) any later version.
17ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This program is distributed in the hope that it will be useful, but
19ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   WITHOUT ANY WARRANTY; without even the implied warranty of
20ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   General Public License for more details.
22ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
23ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   You should have received a copy of the GNU General Public License
24ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   along with this program; if not, write to the Free Software
25ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
26ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   02110-1301, USA.
27ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
28ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   The GNU General Public License is contained in the file COPYING.
29ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
30ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Neither the names of the U.S. Department of Energy nor the
31ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   University of California nor the names of its contributors may be
32ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   used to endorse or promote products derived from this software
33ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   without prior written permission.
34ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
35ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
36ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "libvex_basictypes.h"
37ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "libvex.h"
38ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "libvex_trc_values.h"
39ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
40ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "main_util.h"
41ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "host_generic_regs.h"
42ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "host_x86_defs.h"
43ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
44ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
45ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------- Registers. --------- */
46ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
47ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid ppHRegX86 ( HReg reg )
48ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
49ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int r;
50ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   static HChar* ireg32_names[8]
51ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     = { "%eax", "%ecx", "%edx", "%ebx", "%esp", "%ebp", "%esi", "%edi" };
52ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Be generic for all virtual regs. */
53ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (hregIsVirtual(reg)) {
54ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ppHReg(reg);
55ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return;
56ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
57ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* But specific for real regs. */
58ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (hregClass(reg)) {
59ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case HRcInt32:
60ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         r = hregNumber(reg);
61ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(r >= 0 && r < 8);
62ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("%s", ireg32_names[r]);
63ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
64ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case HRcFlt64:
65ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         r = hregNumber(reg);
66ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(r >= 0 && r < 6);
67ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("%%fake%d", r);
68ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
69ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case HRcVec128:
70ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         r = hregNumber(reg);
71ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(r >= 0 && r < 8);
72ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("%%xmm%d", r);
73ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
74ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
75ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("ppHRegX86");
76ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
77ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
78ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
79ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownHReg hregX86_EAX ( void ) { return mkHReg(0, HRcInt32, False); }
80ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownHReg hregX86_ECX ( void ) { return mkHReg(1, HRcInt32, False); }
81ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownHReg hregX86_EDX ( void ) { return mkHReg(2, HRcInt32, False); }
82ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownHReg hregX86_EBX ( void ) { return mkHReg(3, HRcInt32, False); }
83ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownHReg hregX86_ESP ( void ) { return mkHReg(4, HRcInt32, False); }
84ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownHReg hregX86_EBP ( void ) { return mkHReg(5, HRcInt32, False); }
85ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownHReg hregX86_ESI ( void ) { return mkHReg(6, HRcInt32, False); }
86ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownHReg hregX86_EDI ( void ) { return mkHReg(7, HRcInt32, False); }
87ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
88ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownHReg hregX86_FAKE0 ( void ) { return mkHReg(0, HRcFlt64, False); }
89ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownHReg hregX86_FAKE1 ( void ) { return mkHReg(1, HRcFlt64, False); }
90ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownHReg hregX86_FAKE2 ( void ) { return mkHReg(2, HRcFlt64, False); }
91ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownHReg hregX86_FAKE3 ( void ) { return mkHReg(3, HRcFlt64, False); }
92ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownHReg hregX86_FAKE4 ( void ) { return mkHReg(4, HRcFlt64, False); }
93ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownHReg hregX86_FAKE5 ( void ) { return mkHReg(5, HRcFlt64, False); }
94ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
95ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownHReg hregX86_XMM0 ( void ) { return mkHReg(0, HRcVec128, False); }
96ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownHReg hregX86_XMM1 ( void ) { return mkHReg(1, HRcVec128, False); }
97ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownHReg hregX86_XMM2 ( void ) { return mkHReg(2, HRcVec128, False); }
98ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownHReg hregX86_XMM3 ( void ) { return mkHReg(3, HRcVec128, False); }
99ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownHReg hregX86_XMM4 ( void ) { return mkHReg(4, HRcVec128, False); }
100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownHReg hregX86_XMM5 ( void ) { return mkHReg(5, HRcVec128, False); }
101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownHReg hregX86_XMM6 ( void ) { return mkHReg(6, HRcVec128, False); }
102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownHReg hregX86_XMM7 ( void ) { return mkHReg(7, HRcVec128, False); }
103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid getAllocableRegs_X86 ( Int* nregs, HReg** arr )
106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *nregs = 20;
108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *arr = LibVEX_Alloc(*nregs * sizeof(HReg));
109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (*arr)[0] = hregX86_EAX();
110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (*arr)[1] = hregX86_EBX();
111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (*arr)[2] = hregX86_ECX();
112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (*arr)[3] = hregX86_EDX();
113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (*arr)[4] = hregX86_ESI();
114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (*arr)[5] = hregX86_EDI();
115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (*arr)[6] = hregX86_FAKE0();
116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (*arr)[7] = hregX86_FAKE1();
117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (*arr)[8] = hregX86_FAKE2();
118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (*arr)[9] = hregX86_FAKE3();
119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (*arr)[10] = hregX86_FAKE4();
120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (*arr)[11] = hregX86_FAKE5();
121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (*arr)[12] = hregX86_XMM0();
122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (*arr)[13] = hregX86_XMM1();
123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (*arr)[14] = hregX86_XMM2();
124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (*arr)[15] = hregX86_XMM3();
125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (*arr)[16] = hregX86_XMM4();
126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (*arr)[17] = hregX86_XMM5();
127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (*arr)[18] = hregX86_XMM6();
128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (*arr)[19] = hregX86_XMM7();
129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------- Condition codes, Intel encoding. --------- */
133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownHChar* showX86CondCode ( X86CondCode cond )
135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (cond) {
137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xcc_O:      return "o";
138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xcc_NO:     return "no";
139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xcc_B:      return "b";
140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xcc_NB:     return "nb";
141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xcc_Z:      return "z";
142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xcc_NZ:     return "nz";
143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xcc_BE:     return "be";
144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xcc_NBE:    return "nbe";
145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xcc_S:      return "s";
146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xcc_NS:     return "ns";
147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xcc_P:      return "p";
148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xcc_NP:     return "np";
149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xcc_L:      return "l";
150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xcc_NL:     return "nl";
151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xcc_LE:     return "le";
152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xcc_NLE:    return "nle";
153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xcc_ALWAYS: return "ALWAYS";
154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default: vpanic("ppX86CondCode");
155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------- X86AMode: memory address expressions. --------- */
160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownX86AMode* X86AMode_IR ( UInt imm32, HReg reg ) {
162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   X86AMode* am = LibVEX_Alloc(sizeof(X86AMode));
163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   am->tag = Xam_IR;
164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   am->Xam.IR.imm = imm32;
165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   am->Xam.IR.reg = reg;
166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return am;
167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownX86AMode* X86AMode_IRRS ( UInt imm32, HReg base, HReg indEx, Int shift ) {
169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   X86AMode* am = LibVEX_Alloc(sizeof(X86AMode));
170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   am->tag = Xam_IRRS;
171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   am->Xam.IRRS.imm = imm32;
172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   am->Xam.IRRS.base = base;
173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   am->Xam.IRRS.index = indEx;
174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   am->Xam.IRRS.shift = shift;
175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(shift >= 0 && shift <= 3);
176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return am;
177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownX86AMode* dopyX86AMode ( X86AMode* am ) {
180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (am->tag) {
181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xam_IR:
182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return X86AMode_IR( am->Xam.IR.imm, am->Xam.IR.reg );
183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xam_IRRS:
184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return X86AMode_IRRS( am->Xam.IRRS.imm, am->Xam.IRRS.base,
185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               am->Xam.IRRS.index, am->Xam.IRRS.shift );
186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("dopyX86AMode");
188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid ppX86AMode ( X86AMode* am ) {
192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (am->tag) {
193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xam_IR:
194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (am->Xam.IR.imm == 0)
195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf("(");
196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else
197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf("0x%x(", am->Xam.IR.imm);
198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppHRegX86(am->Xam.IR.reg);
199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf(")");
200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xam_IRRS:
202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("0x%x(", am->Xam.IRRS.imm);
203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppHRegX86(am->Xam.IRRS.base);
204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf(",");
205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppHRegX86(am->Xam.IRRS.index);
206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf(",%d)", 1 << am->Xam.IRRS.shift);
207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("ppX86AMode");
210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void addRegUsage_X86AMode ( HRegUsage* u, X86AMode* am ) {
214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (am->tag) {
215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xam_IR:
216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmRead, am->Xam.IR.reg);
217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xam_IRRS:
219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmRead, am->Xam.IRRS.base);
220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmRead, am->Xam.IRRS.index);
221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("addRegUsage_X86AMode");
224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void mapRegs_X86AMode ( HRegRemap* m, X86AMode* am ) {
228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (am->tag) {
229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xam_IR:
230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         am->Xam.IR.reg = lookupHRegRemap(m, am->Xam.IR.reg);
231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xam_IRRS:
233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         am->Xam.IRRS.base = lookupHRegRemap(m, am->Xam.IRRS.base);
234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         am->Xam.IRRS.index = lookupHRegRemap(m, am->Xam.IRRS.index);
235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("mapRegs_X86AMode");
238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------- Operand, which can be reg, immediate or memory. --------- */
242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownX86RMI* X86RMI_Imm ( UInt imm32 ) {
244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   X86RMI* op         = LibVEX_Alloc(sizeof(X86RMI));
245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   op->tag            = Xrmi_Imm;
246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   op->Xrmi.Imm.imm32 = imm32;
247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return op;
248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownX86RMI* X86RMI_Reg ( HReg reg ) {
250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   X86RMI* op       = LibVEX_Alloc(sizeof(X86RMI));
251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   op->tag          = Xrmi_Reg;
252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   op->Xrmi.Reg.reg = reg;
253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return op;
254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownX86RMI* X86RMI_Mem ( X86AMode* am ) {
256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   X86RMI* op      = LibVEX_Alloc(sizeof(X86RMI));
257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   op->tag         = Xrmi_Mem;
258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   op->Xrmi.Mem.am = am;
259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return op;
260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid ppX86RMI ( X86RMI* op ) {
263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (op->tag) {
264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xrmi_Imm:
265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("$0x%x", op->Xrmi.Imm.imm32);
266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xrmi_Reg:
268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppHRegX86(op->Xrmi.Reg.reg);
269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xrmi_Mem:
271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppX86AMode(op->Xrmi.Mem.am);
272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     default:
274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("ppX86RMI");
275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* An X86RMI can only be used in a "read" context (what would it mean
279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   to write or modify a literal?) and so we enumerate its registers
280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   accordingly. */
281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void addRegUsage_X86RMI ( HRegUsage* u, X86RMI* op ) {
282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (op->tag) {
283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xrmi_Imm:
284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xrmi_Reg:
286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmRead, op->Xrmi.Reg.reg);
287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xrmi_Mem:
289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addRegUsage_X86AMode(u, op->Xrmi.Mem.am);
290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("addRegUsage_X86RMI");
293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void mapRegs_X86RMI ( HRegRemap* m, X86RMI* op ) {
297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (op->tag) {
298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xrmi_Imm:
299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xrmi_Reg:
301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         op->Xrmi.Reg.reg = lookupHRegRemap(m, op->Xrmi.Reg.reg);
302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xrmi_Mem:
304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapRegs_X86AMode(m, op->Xrmi.Mem.am);
305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("mapRegs_X86RMI");
308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------- Operand, which can be reg or immediate only. --------- */
313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownX86RI* X86RI_Imm ( UInt imm32 ) {
315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   X86RI* op         = LibVEX_Alloc(sizeof(X86RI));
316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   op->tag           = Xri_Imm;
317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   op->Xri.Imm.imm32 = imm32;
318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return op;
319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownX86RI* X86RI_Reg ( HReg reg ) {
321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   X86RI* op       = LibVEX_Alloc(sizeof(X86RI));
322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   op->tag         = Xri_Reg;
323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   op->Xri.Reg.reg = reg;
324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return op;
325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid ppX86RI ( X86RI* op ) {
328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (op->tag) {
329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xri_Imm:
330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("$0x%x", op->Xri.Imm.imm32);
331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xri_Reg:
333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppHRegX86(op->Xri.Reg.reg);
334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     default:
336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("ppX86RI");
337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* An X86RI can only be used in a "read" context (what would it mean
341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   to write or modify a literal?) and so we enumerate its registers
342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   accordingly. */
343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void addRegUsage_X86RI ( HRegUsage* u, X86RI* op ) {
344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (op->tag) {
345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xri_Imm:
346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xri_Reg:
348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmRead, op->Xri.Reg.reg);
349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("addRegUsage_X86RI");
352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void mapRegs_X86RI ( HRegRemap* m, X86RI* op ) {
356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (op->tag) {
357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xri_Imm:
358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xri_Reg:
360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         op->Xri.Reg.reg = lookupHRegRemap(m, op->Xri.Reg.reg);
361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("mapRegs_X86RI");
364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------- Operand, which can be reg or memory only. --------- */
369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownX86RM* X86RM_Reg ( HReg reg ) {
371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   X86RM* op       = LibVEX_Alloc(sizeof(X86RM));
372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   op->tag         = Xrm_Reg;
373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   op->Xrm.Reg.reg = reg;
374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return op;
375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownX86RM* X86RM_Mem ( X86AMode* am ) {
377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   X86RM* op      = LibVEX_Alloc(sizeof(X86RM));
378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   op->tag        = Xrm_Mem;
379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   op->Xrm.Mem.am = am;
380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return op;
381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid ppX86RM ( X86RM* op ) {
384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (op->tag) {
385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xrm_Mem:
386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppX86AMode(op->Xrm.Mem.am);
387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xrm_Reg:
389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppHRegX86(op->Xrm.Reg.reg);
390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     default:
392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("ppX86RM");
393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Because an X86RM can be both a source or destination operand, we
397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   have to supply a mode -- pertaining to the operand as a whole --
398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   indicating how it's being used. */
399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void addRegUsage_X86RM ( HRegUsage* u, X86RM* op, HRegMode mode ) {
400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (op->tag) {
401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xrm_Mem:
402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Memory is read, written or modified.  So we just want to
403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            know the regs read by the amode. */
404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addRegUsage_X86AMode(u, op->Xrm.Mem.am);
405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xrm_Reg:
407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* reg is read, written or modified.  Add it in the
408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            appropriate way. */
409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, mode, op->Xrm.Reg.reg);
410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     default:
412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("addRegUsage_X86RM");
413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void mapRegs_X86RM ( HRegRemap* m, X86RM* op )
417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (op->tag) {
419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xrm_Mem:
420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapRegs_X86AMode(m, op->Xrm.Mem.am);
421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xrm_Reg:
423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         op->Xrm.Reg.reg = lookupHRegRemap(m, op->Xrm.Reg.reg);
424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     default:
426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("mapRegs_X86RM");
427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------- Instructions. --------- */
432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownHChar* showX86UnaryOp ( X86UnaryOp op ) {
434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (op) {
435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xun_NOT: return "not";
436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xun_NEG: return "neg";
437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default: vpanic("showX86UnaryOp");
438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownHChar* showX86AluOp ( X86AluOp op ) {
442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (op) {
443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xalu_MOV:  return "mov";
444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xalu_CMP:  return "cmp";
445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xalu_ADD:  return "add";
446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xalu_SUB:  return "sub";
447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xalu_ADC:  return "adc";
448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xalu_SBB:  return "sbb";
449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xalu_AND:  return "and";
450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xalu_OR:   return "or";
451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xalu_XOR:  return "xor";
452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xalu_MUL:  return "mul";
453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default: vpanic("showX86AluOp");
454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownHChar* showX86ShiftOp ( X86ShiftOp op ) {
458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (op) {
459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xsh_SHL: return "shl";
460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xsh_SHR: return "shr";
461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xsh_SAR: return "sar";
462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default: vpanic("showX86ShiftOp");
463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownHChar* showX86FpOp ( X86FpOp op ) {
467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (op) {
468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xfp_ADD:    return "add";
469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xfp_SUB:    return "sub";
470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xfp_MUL:    return "mul";
471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xfp_DIV:    return "div";
472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xfp_SCALE:  return "scale";
473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xfp_ATAN:   return "atan";
474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xfp_YL2X:   return "yl2x";
475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xfp_YL2XP1: return "yl2xp1";
476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xfp_PREM:   return "prem";
477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xfp_PREM1:  return "prem1";
478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xfp_SQRT:   return "sqrt";
479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xfp_ABS:    return "abs";
480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xfp_NEG:    return "chs";
481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xfp_MOV:    return "mov";
482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xfp_SIN:    return "sin";
483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xfp_COS:    return "cos";
484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xfp_TAN:    return "tan";
485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xfp_ROUND:  return "round";
486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xfp_2XM1:   return "2xm1";
487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default: vpanic("showX86FpOp");
488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownHChar* showX86SseOp ( X86SseOp op ) {
492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (op) {
493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xsse_MOV:      return "mov(?!)";
494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xsse_ADDF:     return "add";
495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xsse_SUBF:     return "sub";
496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xsse_MULF:     return "mul";
497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xsse_DIVF:     return "div";
498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xsse_MAXF:     return "max";
499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xsse_MINF:     return "min";
500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xsse_CMPEQF:   return "cmpFeq";
501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xsse_CMPLTF:   return "cmpFlt";
502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xsse_CMPLEF:   return "cmpFle";
503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xsse_CMPUNF:   return "cmpFun";
504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xsse_RCPF:     return "rcp";
505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xsse_RSQRTF:   return "rsqrt";
506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xsse_SQRTF:    return "sqrt";
507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xsse_AND:      return "and";
508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xsse_OR:       return "or";
509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xsse_XOR:      return "xor";
510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xsse_ANDN:     return "andn";
511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xsse_ADD8:     return "paddb";
512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xsse_ADD16:    return "paddw";
513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xsse_ADD32:    return "paddd";
514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xsse_ADD64:    return "paddq";
515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xsse_QADD8U:   return "paddusb";
516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xsse_QADD16U:  return "paddusw";
517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xsse_QADD8S:   return "paddsb";
518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xsse_QADD16S:  return "paddsw";
519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xsse_SUB8:     return "psubb";
520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xsse_SUB16:    return "psubw";
521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xsse_SUB32:    return "psubd";
522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xsse_SUB64:    return "psubq";
523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xsse_QSUB8U:   return "psubusb";
524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xsse_QSUB16U:  return "psubusw";
525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xsse_QSUB8S:   return "psubsb";
526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xsse_QSUB16S:  return "psubsw";
527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xsse_MUL16:    return "pmullw";
528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xsse_MULHI16U: return "pmulhuw";
529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xsse_MULHI16S: return "pmulhw";
530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xsse_AVG8U:    return "pavgb";
531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xsse_AVG16U:   return "pavgw";
532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xsse_MAX16S:   return "pmaxw";
533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xsse_MAX8U:    return "pmaxub";
534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xsse_MIN16S:   return "pminw";
535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xsse_MIN8U:    return "pminub";
536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xsse_CMPEQ8:   return "pcmpeqb";
537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xsse_CMPEQ16:  return "pcmpeqw";
538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xsse_CMPEQ32:  return "pcmpeqd";
539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xsse_CMPGT8S:  return "pcmpgtb";
540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xsse_CMPGT16S: return "pcmpgtw";
541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xsse_CMPGT32S: return "pcmpgtd";
542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xsse_SHL16:    return "psllw";
543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xsse_SHL32:    return "pslld";
544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xsse_SHL64:    return "psllq";
545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xsse_SHR16:    return "psrlw";
546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xsse_SHR32:    return "psrld";
547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xsse_SHR64:    return "psrlq";
548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xsse_SAR16:    return "psraw";
549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xsse_SAR32:    return "psrad";
550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xsse_PACKSSD:  return "packssdw";
551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xsse_PACKSSW:  return "packsswb";
552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xsse_PACKUSW:  return "packuswb";
553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xsse_UNPCKHB:  return "punpckhb";
554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xsse_UNPCKHW:  return "punpckhw";
555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xsse_UNPCKHD:  return "punpckhd";
556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xsse_UNPCKHQ:  return "punpckhq";
557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xsse_UNPCKLB:  return "punpcklb";
558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xsse_UNPCKLW:  return "punpcklw";
559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xsse_UNPCKLD:  return "punpckld";
560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xsse_UNPCKLQ:  return "punpcklq";
561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default: vpanic("showX86SseOp");
562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownX86Instr* X86Instr_Alu32R ( X86AluOp op, X86RMI* src, HReg dst ) {
566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   X86Instr* i       = LibVEX_Alloc(sizeof(X86Instr));
567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->tag            = Xin_Alu32R;
568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.Alu32R.op  = op;
569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.Alu32R.src = src;
570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.Alu32R.dst = dst;
571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return i;
572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownX86Instr* X86Instr_Alu32M ( X86AluOp op, X86RI* src, X86AMode* dst ) {
574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   X86Instr* i       = LibVEX_Alloc(sizeof(X86Instr));
575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->tag            = Xin_Alu32M;
576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.Alu32M.op  = op;
577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.Alu32M.src = src;
578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.Alu32M.dst = dst;
579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(op != Xalu_MUL);
580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return i;
581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownX86Instr* X86Instr_Sh32 ( X86ShiftOp op, UInt src, HReg dst ) {
583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   X86Instr* i     = LibVEX_Alloc(sizeof(X86Instr));
584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->tag          = Xin_Sh32;
585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.Sh32.op  = op;
586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.Sh32.src = src;
587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.Sh32.dst = dst;
588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return i;
589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownX86Instr* X86Instr_Test32 ( UInt imm32, X86RM* dst ) {
591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   X86Instr* i         = LibVEX_Alloc(sizeof(X86Instr));
592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->tag              = Xin_Test32;
593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.Test32.imm32 = imm32;
594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.Test32.dst   = dst;
595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return i;
596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownX86Instr* X86Instr_Unary32 ( X86UnaryOp op, HReg dst ) {
598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   X86Instr* i        = LibVEX_Alloc(sizeof(X86Instr));
599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->tag             = Xin_Unary32;
600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.Unary32.op  = op;
601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.Unary32.dst = dst;
602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return i;
603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownX86Instr* X86Instr_Lea32 ( X86AMode* am, HReg dst ) {
605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   X86Instr* i        = LibVEX_Alloc(sizeof(X86Instr));
606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->tag             = Xin_Lea32;
607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.Lea32.am    = am;
608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.Lea32.dst   = dst;
609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return i;
610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownX86Instr* X86Instr_MulL ( Bool syned, X86RM* src ) {
612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   X86Instr* i        = LibVEX_Alloc(sizeof(X86Instr));
613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->tag             = Xin_MulL;
614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.MulL.syned  = syned;
615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.MulL.src    = src;
616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return i;
617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownX86Instr* X86Instr_Div ( Bool syned, X86RM* src ) {
619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   X86Instr* i      = LibVEX_Alloc(sizeof(X86Instr));
620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->tag           = Xin_Div;
621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.Div.syned = syned;
622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.Div.src   = src;
623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return i;
624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownX86Instr* X86Instr_Sh3232  ( X86ShiftOp op, UInt amt, HReg src, HReg dst ) {
626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   X86Instr* i       = LibVEX_Alloc(sizeof(X86Instr));
627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->tag            = Xin_Sh3232;
628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.Sh3232.op  = op;
629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.Sh3232.amt = amt;
630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.Sh3232.src = src;
631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.Sh3232.dst = dst;
632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(op == Xsh_SHL || op == Xsh_SHR);
633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return i;
634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownX86Instr* X86Instr_Push( X86RMI* src ) {
636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   X86Instr* i     = LibVEX_Alloc(sizeof(X86Instr));
637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->tag          = Xin_Push;
638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.Push.src = src;
639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return i;
640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownX86Instr* X86Instr_Call ( X86CondCode cond, Addr32 target, Int regparms ) {
642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   X86Instr* i          = LibVEX_Alloc(sizeof(X86Instr));
643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->tag               = Xin_Call;
644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.Call.cond     = cond;
645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.Call.target   = target;
646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.Call.regparms = regparms;
647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(regparms >= 0 && regparms <= 3);
648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return i;
649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownX86Instr* X86Instr_Goto ( IRJumpKind jk, X86CondCode cond, X86RI* dst ) {
651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   X86Instr* i      = LibVEX_Alloc(sizeof(X86Instr));
652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->tag           = Xin_Goto;
653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.Goto.cond = cond;
654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.Goto.dst  = dst;
655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.Goto.jk   = jk;
656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return i;
657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownX86Instr* X86Instr_CMov32  ( X86CondCode cond, X86RM* src, HReg dst ) {
659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   X86Instr* i        = LibVEX_Alloc(sizeof(X86Instr));
660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->tag             = Xin_CMov32;
661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.CMov32.cond = cond;
662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.CMov32.src  = src;
663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.CMov32.dst  = dst;
664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(cond != Xcc_ALWAYS);
665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return i;
666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownX86Instr* X86Instr_LoadEX ( UChar szSmall, Bool syned,
668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            X86AMode* src, HReg dst ) {
669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   X86Instr* i           = LibVEX_Alloc(sizeof(X86Instr));
670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->tag                = Xin_LoadEX;
671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.LoadEX.szSmall = szSmall;
672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.LoadEX.syned   = syned;
673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.LoadEX.src     = src;
674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.LoadEX.dst     = dst;
675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(szSmall == 1 || szSmall == 2);
676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return i;
677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownX86Instr* X86Instr_Store ( UChar sz, HReg src, X86AMode* dst ) {
679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   X86Instr* i      = LibVEX_Alloc(sizeof(X86Instr));
680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->tag           = Xin_Store;
681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.Store.sz  = sz;
682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.Store.src = src;
683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.Store.dst = dst;
684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(sz == 1 || sz == 2);
685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return i;
686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownX86Instr* X86Instr_Set32 ( X86CondCode cond, HReg dst ) {
688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   X86Instr* i       = LibVEX_Alloc(sizeof(X86Instr));
689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->tag            = Xin_Set32;
690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.Set32.cond = cond;
691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.Set32.dst  = dst;
692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return i;
693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownX86Instr* X86Instr_Bsfr32 ( Bool isFwds, HReg src, HReg dst ) {
695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   X86Instr* i          = LibVEX_Alloc(sizeof(X86Instr));
696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->tag               = Xin_Bsfr32;
697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.Bsfr32.isFwds = isFwds;
698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.Bsfr32.src    = src;
699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.Bsfr32.dst    = dst;
700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return i;
701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownX86Instr* X86Instr_MFence ( UInt hwcaps ) {
703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   X86Instr* i          = LibVEX_Alloc(sizeof(X86Instr));
704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->tag               = Xin_MFence;
705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.MFence.hwcaps = hwcaps;
706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(0 == (hwcaps & ~(VEX_HWCAPS_X86_SSE1
707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            |VEX_HWCAPS_X86_SSE2
708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            |VEX_HWCAPS_X86_SSE3
709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            |VEX_HWCAPS_X86_LZCNT)));
710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return i;
711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownX86Instr* X86Instr_ACAS ( X86AMode* addr, UChar sz ) {
713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   X86Instr* i      = LibVEX_Alloc(sizeof(X86Instr));
714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->tag           = Xin_ACAS;
715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.ACAS.addr = addr;
716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.ACAS.sz   = sz;
717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(sz == 4 || sz == 2 || sz == 1);
718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return i;
719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownX86Instr* X86Instr_DACAS ( X86AMode* addr ) {
721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   X86Instr* i       = LibVEX_Alloc(sizeof(X86Instr));
722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->tag            = Xin_DACAS;
723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.DACAS.addr = addr;
724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return i;
725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownX86Instr* X86Instr_FpUnary ( X86FpOp op, HReg src, HReg dst ) {
728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   X86Instr* i        = LibVEX_Alloc(sizeof(X86Instr));
729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->tag             = Xin_FpUnary;
730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.FpUnary.op  = op;
731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.FpUnary.src = src;
732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.FpUnary.dst = dst;
733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return i;
734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownX86Instr* X86Instr_FpBinary ( X86FpOp op, HReg srcL, HReg srcR, HReg dst ) {
736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   X86Instr* i          = LibVEX_Alloc(sizeof(X86Instr));
737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->tag               = Xin_FpBinary;
738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.FpBinary.op   = op;
739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.FpBinary.srcL = srcL;
740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.FpBinary.srcR = srcR;
741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.FpBinary.dst  = dst;
742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return i;
743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownX86Instr* X86Instr_FpLdSt ( Bool isLoad, UChar sz, HReg reg, X86AMode* addr ) {
745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   X86Instr* i          = LibVEX_Alloc(sizeof(X86Instr));
746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->tag               = Xin_FpLdSt;
747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.FpLdSt.isLoad = isLoad;
748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.FpLdSt.sz     = sz;
749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.FpLdSt.reg    = reg;
750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.FpLdSt.addr   = addr;
751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(sz == 4 || sz == 8 || sz == 10);
752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return i;
753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownX86Instr* X86Instr_FpLdStI ( Bool isLoad, UChar sz,
755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             HReg reg, X86AMode* addr ) {
756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   X86Instr* i           = LibVEX_Alloc(sizeof(X86Instr));
757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->tag                = Xin_FpLdStI;
758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.FpLdStI.isLoad = isLoad;
759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.FpLdStI.sz     = sz;
760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.FpLdStI.reg    = reg;
761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.FpLdStI.addr   = addr;
762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(sz == 2 || sz == 4 || sz == 8);
763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return i;
764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownX86Instr* X86Instr_Fp64to32 ( HReg src, HReg dst ) {
766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   X86Instr* i         = LibVEX_Alloc(sizeof(X86Instr));
767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->tag              = Xin_Fp64to32;
768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.Fp64to32.src = src;
769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.Fp64to32.dst = dst;
770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return i;
771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownX86Instr* X86Instr_FpCMov ( X86CondCode cond, HReg src, HReg dst ) {
773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   X86Instr* i        = LibVEX_Alloc(sizeof(X86Instr));
774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->tag             = Xin_FpCMov;
775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.FpCMov.cond = cond;
776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.FpCMov.src  = src;
777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.FpCMov.dst  = dst;
778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(cond != Xcc_ALWAYS);
779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return i;
780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownX86Instr* X86Instr_FpLdCW ( X86AMode* addr ) {
782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   X86Instr* i          = LibVEX_Alloc(sizeof(X86Instr));
783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->tag               = Xin_FpLdCW;
784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.FpLdCW.addr   = addr;
785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return i;
786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownX86Instr* X86Instr_FpStSW_AX ( void ) {
788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   X86Instr* i = LibVEX_Alloc(sizeof(X86Instr));
789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->tag      = Xin_FpStSW_AX;
790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return i;
791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownX86Instr* X86Instr_FpCmp ( HReg srcL, HReg srcR, HReg dst ) {
793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   X86Instr* i       = LibVEX_Alloc(sizeof(X86Instr));
794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->tag            = Xin_FpCmp;
795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.FpCmp.srcL = srcL;
796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.FpCmp.srcR = srcR;
797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.FpCmp.dst  = dst;
798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return i;
799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownX86Instr* X86Instr_SseConst ( UShort con, HReg dst ) {
802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   X86Instr* i            = LibVEX_Alloc(sizeof(X86Instr));
803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->tag                 = Xin_SseConst;
804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.SseConst.con    = con;
805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.SseConst.dst    = dst;
806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(hregClass(dst) == HRcVec128);
807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return i;
808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownX86Instr* X86Instr_SseLdSt ( Bool isLoad, HReg reg, X86AMode* addr ) {
810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   X86Instr* i           = LibVEX_Alloc(sizeof(X86Instr));
811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->tag                = Xin_SseLdSt;
812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.SseLdSt.isLoad = isLoad;
813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.SseLdSt.reg    = reg;
814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.SseLdSt.addr   = addr;
815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return i;
816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownX86Instr* X86Instr_SseLdzLO  ( Int sz, HReg reg, X86AMode* addr )
818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   X86Instr* i           = LibVEX_Alloc(sizeof(X86Instr));
820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->tag                = Xin_SseLdzLO;
821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.SseLdzLO.sz    = toUChar(sz);
822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.SseLdzLO.reg   = reg;
823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.SseLdzLO.addr  = addr;
824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(sz == 4 || sz == 8);
825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return i;
826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownX86Instr* X86Instr_Sse32Fx4 ( X86SseOp op, HReg src, HReg dst ) {
828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   X86Instr* i         = LibVEX_Alloc(sizeof(X86Instr));
829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->tag              = Xin_Sse32Fx4;
830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.Sse32Fx4.op  = op;
831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.Sse32Fx4.src = src;
832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.Sse32Fx4.dst = dst;
833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(op != Xsse_MOV);
834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return i;
835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownX86Instr* X86Instr_Sse32FLo ( X86SseOp op, HReg src, HReg dst ) {
837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   X86Instr* i         = LibVEX_Alloc(sizeof(X86Instr));
838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->tag              = Xin_Sse32FLo;
839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.Sse32FLo.op  = op;
840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.Sse32FLo.src = src;
841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.Sse32FLo.dst = dst;
842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(op != Xsse_MOV);
843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return i;
844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownX86Instr* X86Instr_Sse64Fx2 ( X86SseOp op, HReg src, HReg dst ) {
846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   X86Instr* i         = LibVEX_Alloc(sizeof(X86Instr));
847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->tag              = Xin_Sse64Fx2;
848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.Sse64Fx2.op  = op;
849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.Sse64Fx2.src = src;
850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.Sse64Fx2.dst = dst;
851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(op != Xsse_MOV);
852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return i;
853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownX86Instr* X86Instr_Sse64FLo ( X86SseOp op, HReg src, HReg dst ) {
855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   X86Instr* i         = LibVEX_Alloc(sizeof(X86Instr));
856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->tag              = Xin_Sse64FLo;
857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.Sse64FLo.op  = op;
858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.Sse64FLo.src = src;
859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.Sse64FLo.dst = dst;
860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(op != Xsse_MOV);
861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return i;
862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownX86Instr* X86Instr_SseReRg ( X86SseOp op, HReg re, HReg rg ) {
864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   X86Instr* i        = LibVEX_Alloc(sizeof(X86Instr));
865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->tag             = Xin_SseReRg;
866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.SseReRg.op  = op;
867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.SseReRg.src = re;
868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.SseReRg.dst = rg;
869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return i;
870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownX86Instr* X86Instr_SseCMov ( X86CondCode cond, HReg src, HReg dst ) {
872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   X86Instr* i         = LibVEX_Alloc(sizeof(X86Instr));
873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->tag              = Xin_SseCMov;
874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.SseCMov.cond = cond;
875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.SseCMov.src  = src;
876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.SseCMov.dst  = dst;
877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(cond != Xcc_ALWAYS);
878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return i;
879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownX86Instr* X86Instr_SseShuf ( Int order, HReg src, HReg dst ) {
881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   X86Instr* i          = LibVEX_Alloc(sizeof(X86Instr));
882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->tag               = Xin_SseShuf;
883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.SseShuf.order = order;
884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.SseShuf.src   = src;
885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Xin.SseShuf.dst   = dst;
886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(order >= 0 && order <= 0xFF);
887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return i;
888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid ppX86Instr ( X86Instr* i, Bool mode64 ) {
891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(mode64 == False);
892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (i->tag) {
893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_Alu32R:
894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("%sl ", showX86AluOp(i->Xin.Alu32R.op));
895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppX86RMI(i->Xin.Alu32R.src);
896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf(",");
897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppHRegX86(i->Xin.Alu32R.dst);
898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_Alu32M:
900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("%sl ", showX86AluOp(i->Xin.Alu32M.op));
901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppX86RI(i->Xin.Alu32M.src);
902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf(",");
903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppX86AMode(i->Xin.Alu32M.dst);
904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_Sh32:
906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("%sl ", showX86ShiftOp(i->Xin.Sh32.op));
907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (i->Xin.Sh32.src == 0)
908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           vex_printf("%%cl,");
909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else
910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf("$%d,", (Int)i->Xin.Sh32.src);
911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppHRegX86(i->Xin.Sh32.dst);
912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_Test32:
914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("testl $%d,", (Int)i->Xin.Test32.imm32);
915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppX86RM(i->Xin.Test32.dst);
916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_Unary32:
918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("%sl ", showX86UnaryOp(i->Xin.Unary32.op));
919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppHRegX86(i->Xin.Unary32.dst);
920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_Lea32:
922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("leal ");
923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppX86AMode(i->Xin.Lea32.am);
924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf(",");
925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppHRegX86(i->Xin.Lea32.dst);
926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_MulL:
928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("%cmull ", i->Xin.MulL.syned ? 's' : 'u');
929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppX86RM(i->Xin.MulL.src);
930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_Div:
932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("%cdivl ", i->Xin.Div.syned ? 's' : 'u');
933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppX86RM(i->Xin.Div.src);
934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_Sh3232:
936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("%sdl ", showX86ShiftOp(i->Xin.Sh3232.op));
937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (i->Xin.Sh3232.amt == 0)
938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           vex_printf(" %%cl,");
939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else
940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf(" $%d,", (Int)i->Xin.Sh3232.amt);
941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppHRegX86(i->Xin.Sh3232.src);
942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf(",");
943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppHRegX86(i->Xin.Sh3232.dst);
944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_Push:
946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("pushl ");
947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppX86RMI(i->Xin.Push.src);
948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_Call:
950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("call%s[%d] ",
951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    i->Xin.Call.cond==Xcc_ALWAYS
952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       ? "" : showX86CondCode(i->Xin.Call.cond),
953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    i->Xin.Call.regparms);
954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("0x%x", i->Xin.Call.target);
955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_Goto:
957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (i->Xin.Goto.cond != Xcc_ALWAYS) {
958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf("if (%%eflags.%s) { ",
959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       showX86CondCode(i->Xin.Goto.cond));
960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 }
961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (i->Xin.Goto.jk != Ijk_Boring
962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             && i->Xin.Goto.jk != Ijk_Call
963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             && i->Xin.Goto.jk != Ijk_Ret) {
964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf("movl $");
965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ppIRJumpKind(i->Xin.Goto.jk);
966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf(",%%ebp ; ");
967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("movl ");
969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppX86RI(i->Xin.Goto.dst);
970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf(",%%eax ; movl $dispatcher_addr,%%edx ; jmp *%%edx");
971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (i->Xin.Goto.cond != Xcc_ALWAYS) {
972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf(" }");
973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 }
974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_CMov32:
976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("cmov%s ", showX86CondCode(i->Xin.CMov32.cond));
977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppX86RM(i->Xin.CMov32.src);
978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf(",");
979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppHRegX86(i->Xin.CMov32.dst);
980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_LoadEX:
982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("mov%c%cl ",
983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    i->Xin.LoadEX.syned ? 's' : 'z',
984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    i->Xin.LoadEX.szSmall==1 ? 'b' : 'w');
985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppX86AMode(i->Xin.LoadEX.src);
986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf(",");
987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppHRegX86(i->Xin.LoadEX.dst);
988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_Store:
990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("mov%c ", i->Xin.Store.sz==1 ? 'b' : 'w');
991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppHRegX86(i->Xin.Store.src);
992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf(",");
993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppX86AMode(i->Xin.Store.dst);
994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_Set32:
996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("setl%s ", showX86CondCode(i->Xin.Set32.cond));
997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppHRegX86(i->Xin.Set32.dst);
998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_Bsfr32:
1000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("bs%cl ", i->Xin.Bsfr32.isFwds ? 'f' : 'r');
1001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppHRegX86(i->Xin.Bsfr32.src);
1002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf(",");
1003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppHRegX86(i->Xin.Bsfr32.dst);
1004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_MFence:
1006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("mfence(%s)",
1007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    LibVEX_ppVexHwCaps(VexArchX86,i->Xin.MFence.hwcaps));
1008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_ACAS:
1010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("lock cmpxchg%c ",
1011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     i->Xin.ACAS.sz==1 ? 'b'
1012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       : i->Xin.ACAS.sz==2 ? 'w' : 'l');
1013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("{%%eax->%%ebx},");
1014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppX86AMode(i->Xin.ACAS.addr);
1015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_DACAS:
1017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("lock cmpxchg8b {%%edx:%%eax->%%ecx:%%ebx},");
1018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppX86AMode(i->Xin.DACAS.addr);
1019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_FpUnary:
1021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("g%sD ", showX86FpOp(i->Xin.FpUnary.op));
1022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppHRegX86(i->Xin.FpUnary.src);
1023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf(",");
1024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppHRegX86(i->Xin.FpUnary.dst);
1025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
1026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_FpBinary:
1027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("g%sD ", showX86FpOp(i->Xin.FpBinary.op));
1028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppHRegX86(i->Xin.FpBinary.srcL);
1029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf(",");
1030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppHRegX86(i->Xin.FpBinary.srcR);
1031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf(",");
1032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppHRegX86(i->Xin.FpBinary.dst);
1033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
1034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_FpLdSt:
1035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (i->Xin.FpLdSt.isLoad) {
1036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf("gld%c " ,  i->Xin.FpLdSt.sz==10 ? 'T'
1037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   : (i->Xin.FpLdSt.sz==8 ? 'D' : 'F'));
1038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ppX86AMode(i->Xin.FpLdSt.addr);
1039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf(", ");
1040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ppHRegX86(i->Xin.FpLdSt.reg);
1041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
1042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf("gst%c " , i->Xin.FpLdSt.sz==10 ? 'T'
1043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  : (i->Xin.FpLdSt.sz==8 ? 'D' : 'F'));
1044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ppHRegX86(i->Xin.FpLdSt.reg);
1045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf(", ");
1046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ppX86AMode(i->Xin.FpLdSt.addr);
1047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_FpLdStI:
1050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (i->Xin.FpLdStI.isLoad) {
1051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf("gild%s ", i->Xin.FpLdStI.sz==8 ? "ll" :
1052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  i->Xin.FpLdStI.sz==4 ? "l" : "w");
1053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ppX86AMode(i->Xin.FpLdStI.addr);
1054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf(", ");
1055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ppHRegX86(i->Xin.FpLdStI.reg);
1056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
1057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf("gist%s ", i->Xin.FpLdStI.sz==8 ? "ll" :
1058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  i->Xin.FpLdStI.sz==4 ? "l" : "w");
1059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ppHRegX86(i->Xin.FpLdStI.reg);
1060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf(", ");
1061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ppX86AMode(i->Xin.FpLdStI.addr);
1062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_Fp64to32:
1065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("gdtof ");
1066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppHRegX86(i->Xin.Fp64to32.src);
1067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf(",");
1068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppHRegX86(i->Xin.Fp64to32.dst);
1069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_FpCMov:
1071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("gcmov%s ", showX86CondCode(i->Xin.FpCMov.cond));
1072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppHRegX86(i->Xin.FpCMov.src);
1073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf(",");
1074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppHRegX86(i->Xin.FpCMov.dst);
1075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_FpLdCW:
1077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("fldcw ");
1078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppX86AMode(i->Xin.FpLdCW.addr);
1079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_FpStSW_AX:
1081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("fstsw %%ax");
1082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_FpCmp:
1084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("gcmp ");
1085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppHRegX86(i->Xin.FpCmp.srcL);
1086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf(",");
1087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppHRegX86(i->Xin.FpCmp.srcR);
1088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf(",");
1089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppHRegX86(i->Xin.FpCmp.dst);
1090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
1091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_SseConst:
1092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("const $0x%04x,", (Int)i->Xin.SseConst.con);
1093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppHRegX86(i->Xin.SseConst.dst);
1094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
1095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_SseLdSt:
1096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("movups ");
1097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (i->Xin.SseLdSt.isLoad) {
1098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ppX86AMode(i->Xin.SseLdSt.addr);
1099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf(",");
1100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ppHRegX86(i->Xin.SseLdSt.reg);
1101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
1102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ppHRegX86(i->Xin.SseLdSt.reg);
1103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf(",");
1104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ppX86AMode(i->Xin.SseLdSt.addr);
1105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_SseLdzLO:
1108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("movs%s ", i->Xin.SseLdzLO.sz==4 ? "s" : "d");
1109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppX86AMode(i->Xin.SseLdzLO.addr);
1110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf(",");
1111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppHRegX86(i->Xin.SseLdzLO.reg);
1112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_Sse32Fx4:
1114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("%sps ", showX86SseOp(i->Xin.Sse32Fx4.op));
1115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppHRegX86(i->Xin.Sse32Fx4.src);
1116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf(",");
1117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppHRegX86(i->Xin.Sse32Fx4.dst);
1118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_Sse32FLo:
1120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("%sss ", showX86SseOp(i->Xin.Sse32FLo.op));
1121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppHRegX86(i->Xin.Sse32FLo.src);
1122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf(",");
1123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppHRegX86(i->Xin.Sse32FLo.dst);
1124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_Sse64Fx2:
1126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("%spd ", showX86SseOp(i->Xin.Sse64Fx2.op));
1127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppHRegX86(i->Xin.Sse64Fx2.src);
1128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf(",");
1129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppHRegX86(i->Xin.Sse64Fx2.dst);
1130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_Sse64FLo:
1132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("%ssd ", showX86SseOp(i->Xin.Sse64FLo.op));
1133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppHRegX86(i->Xin.Sse64FLo.src);
1134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf(",");
1135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppHRegX86(i->Xin.Sse64FLo.dst);
1136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_SseReRg:
1138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("%s ", showX86SseOp(i->Xin.SseReRg.op));
1139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppHRegX86(i->Xin.SseReRg.src);
1140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf(",");
1141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppHRegX86(i->Xin.SseReRg.dst);
1142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_SseCMov:
1144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("cmov%s ", showX86CondCode(i->Xin.SseCMov.cond));
1145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppHRegX86(i->Xin.SseCMov.src);
1146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf(",");
1147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppHRegX86(i->Xin.SseCMov.dst);
1148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_SseShuf:
1150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("pshufd $0x%x,", i->Xin.SseShuf.order);
1151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppHRegX86(i->Xin.SseShuf.src);
1152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf(",");
1153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppHRegX86(i->Xin.SseShuf.dst);
1154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
1157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("ppX86Instr");
1158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------- Helpers for register allocation. --------- */
1162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid getRegUsage_X86Instr (HRegUsage* u, X86Instr* i, Bool mode64)
1164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool unary;
1166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(mode64 == False);
1167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   initHRegUsage(u);
1168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (i->tag) {
1169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_Alu32R:
1170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addRegUsage_X86RMI(u, i->Xin.Alu32R.src);
1171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (i->Xin.Alu32R.op == Xalu_MOV) {
1172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addHRegUse(u, HRmWrite, i->Xin.Alu32R.dst);
1173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return;
1174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (i->Xin.Alu32R.op == Xalu_CMP) {
1176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addHRegUse(u, HRmRead, i->Xin.Alu32R.dst);
1177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return;
1178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmModify, i->Xin.Alu32R.dst);
1180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_Alu32M:
1182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addRegUsage_X86RI(u, i->Xin.Alu32M.src);
1183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addRegUsage_X86AMode(u, i->Xin.Alu32M.dst);
1184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_Sh32:
1186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmModify, i->Xin.Sh32.dst);
1187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (i->Xin.Sh32.src == 0)
1188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addHRegUse(u, HRmRead, hregX86_ECX());
1189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_Test32:
1191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addRegUsage_X86RM(u, i->Xin.Test32.dst, HRmRead);
1192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_Unary32:
1194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmModify, i->Xin.Unary32.dst);
1195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_Lea32:
1197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addRegUsage_X86AMode(u, i->Xin.Lea32.am);
1198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmWrite, i->Xin.Lea32.dst);
1199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_MulL:
1201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addRegUsage_X86RM(u, i->Xin.MulL.src, HRmRead);
1202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmModify, hregX86_EAX());
1203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmWrite, hregX86_EDX());
1204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_Div:
1206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addRegUsage_X86RM(u, i->Xin.Div.src, HRmRead);
1207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmModify, hregX86_EAX());
1208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmModify, hregX86_EDX());
1209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_Sh3232:
1211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmRead, i->Xin.Sh3232.src);
1212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmModify, i->Xin.Sh3232.dst);
1213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (i->Xin.Sh3232.amt == 0)
1214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addHRegUse(u, HRmRead, hregX86_ECX());
1215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_Push:
1217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addRegUsage_X86RMI(u, i->Xin.Push.src);
1218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmModify, hregX86_ESP());
1219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_Call:
1221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* This is a bit subtle. */
1222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* First off, claim it trashes all the caller-saved regs
1223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            which fall within the register allocator's jurisdiction.
1224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            These I believe to be %eax %ecx %edx and all the xmm
1225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            registers. */
1226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmWrite, hregX86_EAX());
1227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmWrite, hregX86_ECX());
1228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmWrite, hregX86_EDX());
1229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmWrite, hregX86_XMM0());
1230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmWrite, hregX86_XMM1());
1231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmWrite, hregX86_XMM2());
1232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmWrite, hregX86_XMM3());
1233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmWrite, hregX86_XMM4());
1234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmWrite, hregX86_XMM5());
1235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmWrite, hregX86_XMM6());
1236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmWrite, hregX86_XMM7());
1237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Now we have to state any parameter-carrying registers
1238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            which might be read.  This depends on the regparmness. */
1239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch (i->Xin.Call.regparms) {
1240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 3: addHRegUse(u, HRmRead, hregX86_ECX()); /*fallthru*/
1241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 2: addHRegUse(u, HRmRead, hregX86_EDX()); /*fallthru*/
1242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 1: addHRegUse(u, HRmRead, hregX86_EAX()); break;
1243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0: break;
1244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default: vpanic("getRegUsage_X86Instr:Call:regparms");
1245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Finally, there is the issue that the insn trashes a
1247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            register because the literal target address has to be
1248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            loaded into a register.  Fortunately, for the 0/1/2
1249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            regparm case, we can use EAX, EDX and ECX respectively, so
1250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            this does not cause any further damage.  For the 3-regparm
1251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case, we'll have to choose another register arbitrarily --
1252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            since A, D and C are used for parameters -- and so we might
1253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            as well choose EDI. */
1254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (i->Xin.Call.regparms == 3)
1255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addHRegUse(u, HRmWrite, hregX86_EDI());
1256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Upshot of this is that the assembler really must observe
1257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            the here-stated convention of which register to use as an
1258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            address temporary, depending on the regparmness: 0==EAX,
1259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            1==EDX, 2==ECX, 3==EDI. */
1260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_Goto:
1262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addRegUsage_X86RI(u, i->Xin.Goto.dst);
1263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmWrite, hregX86_EAX()); /* used for next guest addr */
1264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmWrite, hregX86_EDX()); /* used for dispatcher addr */
1265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (i->Xin.Goto.jk != Ijk_Boring
1266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             && i->Xin.Goto.jk != Ijk_Call
1267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             && i->Xin.Goto.jk != Ijk_Ret)
1268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* note, this is irrelevant since ebp is not actually
1269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               available to the allocator.  But still .. */
1270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addHRegUse(u, HRmWrite, hregX86_EBP());
1271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_CMov32:
1273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addRegUsage_X86RM(u, i->Xin.CMov32.src, HRmRead);
1274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmModify, i->Xin.CMov32.dst);
1275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_LoadEX:
1277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addRegUsage_X86AMode(u, i->Xin.LoadEX.src);
1278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmWrite, i->Xin.LoadEX.dst);
1279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_Store:
1281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmRead, i->Xin.Store.src);
1282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addRegUsage_X86AMode(u, i->Xin.Store.dst);
1283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_Set32:
1285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmWrite, i->Xin.Set32.dst);
1286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_Bsfr32:
1288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmRead, i->Xin.Bsfr32.src);
1289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmWrite, i->Xin.Bsfr32.dst);
1290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_MFence:
1292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_ACAS:
1294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addRegUsage_X86AMode(u, i->Xin.ACAS.addr);
1295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmRead, hregX86_EBX());
1296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmModify, hregX86_EAX());
1297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_DACAS:
1299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addRegUsage_X86AMode(u, i->Xin.DACAS.addr);
1300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmRead, hregX86_ECX());
1301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmRead, hregX86_EBX());
1302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmModify, hregX86_EDX());
1303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmModify, hregX86_EAX());
1304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_FpUnary:
1306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmRead, i->Xin.FpUnary.src);
1307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmWrite, i->Xin.FpUnary.dst);
1308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_FpBinary:
1310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmRead, i->Xin.FpBinary.srcL);
1311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmRead, i->Xin.FpBinary.srcR);
1312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmWrite, i->Xin.FpBinary.dst);
1313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_FpLdSt:
1315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addRegUsage_X86AMode(u, i->Xin.FpLdSt.addr);
1316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, i->Xin.FpLdSt.isLoad ? HRmWrite : HRmRead,
1317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       i->Xin.FpLdSt.reg);
1318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_FpLdStI:
1320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addRegUsage_X86AMode(u, i->Xin.FpLdStI.addr);
1321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, i->Xin.FpLdStI.isLoad ? HRmWrite : HRmRead,
1322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       i->Xin.FpLdStI.reg);
1323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_Fp64to32:
1325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmRead,  i->Xin.Fp64to32.src);
1326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmWrite, i->Xin.Fp64to32.dst);
1327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_FpCMov:
1329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmRead,   i->Xin.FpCMov.src);
1330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmModify, i->Xin.FpCMov.dst);
1331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_FpLdCW:
1333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addRegUsage_X86AMode(u, i->Xin.FpLdCW.addr);
1334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_FpStSW_AX:
1336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmWrite, hregX86_EAX());
1337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_FpCmp:
1339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmRead, i->Xin.FpCmp.srcL);
1340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmRead, i->Xin.FpCmp.srcR);
1341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmWrite, i->Xin.FpCmp.dst);
1342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmWrite, hregX86_EAX());
1343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_SseLdSt:
1345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addRegUsage_X86AMode(u, i->Xin.SseLdSt.addr);
1346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, i->Xin.SseLdSt.isLoad ? HRmWrite : HRmRead,
1347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       i->Xin.SseLdSt.reg);
1348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_SseLdzLO:
1350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addRegUsage_X86AMode(u, i->Xin.SseLdzLO.addr);
1351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmWrite, i->Xin.SseLdzLO.reg);
1352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_SseConst:
1354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmWrite, i->Xin.SseConst.dst);
1355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_Sse32Fx4:
1357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(i->Xin.Sse32Fx4.op != Xsse_MOV);
1358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         unary = toBool( i->Xin.Sse32Fx4.op == Xsse_RCPF
1359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         || i->Xin.Sse32Fx4.op == Xsse_RSQRTF
1360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         || i->Xin.Sse32Fx4.op == Xsse_SQRTF );
1361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmRead, i->Xin.Sse32Fx4.src);
1362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, unary ? HRmWrite : HRmModify,
1363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       i->Xin.Sse32Fx4.dst);
1364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_Sse32FLo:
1366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(i->Xin.Sse32FLo.op != Xsse_MOV);
1367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         unary = toBool( i->Xin.Sse32FLo.op == Xsse_RCPF
1368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         || i->Xin.Sse32FLo.op == Xsse_RSQRTF
1369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         || i->Xin.Sse32FLo.op == Xsse_SQRTF );
1370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmRead, i->Xin.Sse32FLo.src);
1371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, unary ? HRmWrite : HRmModify,
1372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       i->Xin.Sse32FLo.dst);
1373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_Sse64Fx2:
1375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(i->Xin.Sse64Fx2.op != Xsse_MOV);
1376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         unary = toBool( i->Xin.Sse64Fx2.op == Xsse_RCPF
1377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         || i->Xin.Sse64Fx2.op == Xsse_RSQRTF
1378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         || i->Xin.Sse64Fx2.op == Xsse_SQRTF );
1379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmRead, i->Xin.Sse64Fx2.src);
1380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, unary ? HRmWrite : HRmModify,
1381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       i->Xin.Sse64Fx2.dst);
1382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_Sse64FLo:
1384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(i->Xin.Sse64FLo.op != Xsse_MOV);
1385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         unary = toBool( i->Xin.Sse64FLo.op == Xsse_RCPF
1386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         || i->Xin.Sse64FLo.op == Xsse_RSQRTF
1387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         || i->Xin.Sse64FLo.op == Xsse_SQRTF );
1388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmRead, i->Xin.Sse64FLo.src);
1389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, unary ? HRmWrite : HRmModify,
1390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       i->Xin.Sse64FLo.dst);
1391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_SseReRg:
1393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (i->Xin.SseReRg.op == Xsse_XOR
1394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             && i->Xin.SseReRg.src == i->Xin.SseReRg.dst) {
1395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* reg-alloc needs to understand 'xor r,r' as a write of r */
1396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* (as opposed to a rite of passage :-) */
1397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addHRegUse(u, HRmWrite, i->Xin.SseReRg.dst);
1398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
1399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addHRegUse(u, HRmRead, i->Xin.SseReRg.src);
1400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addHRegUse(u, i->Xin.SseReRg.op == Xsse_MOV
1401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             ? HRmWrite : HRmModify,
1402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          i->Xin.SseReRg.dst);
1403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_SseCMov:
1406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmRead,   i->Xin.SseCMov.src);
1407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmModify, i->Xin.SseCMov.dst);
1408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_SseShuf:
1410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmRead,  i->Xin.SseShuf.src);
1411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmWrite, i->Xin.SseShuf.dst);
1412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
1414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppX86Instr(i, False);
1415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("getRegUsage_X86Instr");
1416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* local helper */
1420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void mapReg( HRegRemap* m, HReg* r )
1421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *r = lookupHRegRemap(m, *r);
1423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid mapRegs_X86Instr ( HRegRemap* m, X86Instr* i, Bool mode64 )
1426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(mode64 == False);
1428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (i->tag) {
1429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_Alu32R:
1430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapRegs_X86RMI(m, i->Xin.Alu32R.src);
1431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapReg(m, &i->Xin.Alu32R.dst);
1432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_Alu32M:
1434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapRegs_X86RI(m, i->Xin.Alu32M.src);
1435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapRegs_X86AMode(m, i->Xin.Alu32M.dst);
1436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_Sh32:
1438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapReg(m, &i->Xin.Sh32.dst);
1439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_Test32:
1441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapRegs_X86RM(m, i->Xin.Test32.dst);
1442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_Unary32:
1444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapReg(m, &i->Xin.Unary32.dst);
1445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_Lea32:
1447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapRegs_X86AMode(m, i->Xin.Lea32.am);
1448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapReg(m, &i->Xin.Lea32.dst);
1449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_MulL:
1451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapRegs_X86RM(m, i->Xin.MulL.src);
1452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_Div:
1454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapRegs_X86RM(m, i->Xin.Div.src);
1455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_Sh3232:
1457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapReg(m, &i->Xin.Sh3232.src);
1458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapReg(m, &i->Xin.Sh3232.dst);
1459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_Push:
1461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapRegs_X86RMI(m, i->Xin.Push.src);
1462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_Call:
1464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_Goto:
1466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapRegs_X86RI(m, i->Xin.Goto.dst);
1467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_CMov32:
1469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapRegs_X86RM(m, i->Xin.CMov32.src);
1470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapReg(m, &i->Xin.CMov32.dst);
1471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_LoadEX:
1473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapRegs_X86AMode(m, i->Xin.LoadEX.src);
1474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapReg(m, &i->Xin.LoadEX.dst);
1475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_Store:
1477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapReg(m, &i->Xin.Store.src);
1478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapRegs_X86AMode(m, i->Xin.Store.dst);
1479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_Set32:
1481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapReg(m, &i->Xin.Set32.dst);
1482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_Bsfr32:
1484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapReg(m, &i->Xin.Bsfr32.src);
1485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapReg(m, &i->Xin.Bsfr32.dst);
1486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_MFence:
1488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_ACAS:
1490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapRegs_X86AMode(m, i->Xin.ACAS.addr);
1491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_DACAS:
1493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapRegs_X86AMode(m, i->Xin.DACAS.addr);
1494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_FpUnary:
1496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapReg(m, &i->Xin.FpUnary.src);
1497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapReg(m, &i->Xin.FpUnary.dst);
1498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_FpBinary:
1500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapReg(m, &i->Xin.FpBinary.srcL);
1501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapReg(m, &i->Xin.FpBinary.srcR);
1502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapReg(m, &i->Xin.FpBinary.dst);
1503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_FpLdSt:
1505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapRegs_X86AMode(m, i->Xin.FpLdSt.addr);
1506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapReg(m, &i->Xin.FpLdSt.reg);
1507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_FpLdStI:
1509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapRegs_X86AMode(m, i->Xin.FpLdStI.addr);
1510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapReg(m, &i->Xin.FpLdStI.reg);
1511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_Fp64to32:
1513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapReg(m, &i->Xin.Fp64to32.src);
1514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapReg(m, &i->Xin.Fp64to32.dst);
1515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_FpCMov:
1517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapReg(m, &i->Xin.FpCMov.src);
1518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapReg(m, &i->Xin.FpCMov.dst);
1519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_FpLdCW:
1521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapRegs_X86AMode(m, i->Xin.FpLdCW.addr);
1522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_FpStSW_AX:
1524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_FpCmp:
1526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapReg(m, &i->Xin.FpCmp.srcL);
1527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapReg(m, &i->Xin.FpCmp.srcR);
1528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapReg(m, &i->Xin.FpCmp.dst);
1529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_SseConst:
1531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapReg(m, &i->Xin.SseConst.dst);
1532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_SseLdSt:
1534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapReg(m, &i->Xin.SseLdSt.reg);
1535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapRegs_X86AMode(m, i->Xin.SseLdSt.addr);
1536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
1537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_SseLdzLO:
1538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapReg(m, &i->Xin.SseLdzLO.reg);
1539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapRegs_X86AMode(m, i->Xin.SseLdzLO.addr);
1540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
1541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_Sse32Fx4:
1542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapReg(m, &i->Xin.Sse32Fx4.src);
1543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapReg(m, &i->Xin.Sse32Fx4.dst);
1544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_Sse32FLo:
1546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapReg(m, &i->Xin.Sse32FLo.src);
1547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapReg(m, &i->Xin.Sse32FLo.dst);
1548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_Sse64Fx2:
1550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapReg(m, &i->Xin.Sse64Fx2.src);
1551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapReg(m, &i->Xin.Sse64Fx2.dst);
1552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_Sse64FLo:
1554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapReg(m, &i->Xin.Sse64FLo.src);
1555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapReg(m, &i->Xin.Sse64FLo.dst);
1556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_SseReRg:
1558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapReg(m, &i->Xin.SseReRg.src);
1559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapReg(m, &i->Xin.SseReRg.dst);
1560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_SseCMov:
1562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapReg(m, &i->Xin.SseCMov.src);
1563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapReg(m, &i->Xin.SseCMov.dst);
1564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xin_SseShuf:
1566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapReg(m, &i->Xin.SseShuf.src);
1567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapReg(m, &i->Xin.SseShuf.dst);
1568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
1570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppX86Instr(i, mode64);
1571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("mapRegs_X86Instr");
1572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Figure out if i represents a reg-reg move, and if so assign the
1576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   source and destination to *src and *dst.  If in doubt say No.  Used
1577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   by the register allocator to do move coalescing.
1578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
1579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool isMove_X86Instr ( X86Instr* i, HReg* src, HReg* dst )
1580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Moves between integer regs */
1582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (i->tag == Xin_Alu32R) {
1583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (i->Xin.Alu32R.op != Xalu_MOV)
1584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
1585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (i->Xin.Alu32R.src->tag != Xrmi_Reg)
1586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
1587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *src = i->Xin.Alu32R.src->Xrmi.Reg.reg;
1588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *dst = i->Xin.Alu32R.dst;
1589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return True;
1590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Moves between FP regs */
1592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (i->tag == Xin_FpUnary) {
1593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (i->Xin.FpUnary.op != Xfp_MOV)
1594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
1595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *src = i->Xin.FpUnary.src;
1596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *dst = i->Xin.FpUnary.dst;
1597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return True;
1598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (i->tag == Xin_SseReRg) {
1600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (i->Xin.SseReRg.op != Xsse_MOV)
1601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
1602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *src = i->Xin.SseReRg.src;
1603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *dst = i->Xin.SseReRg.dst;
1604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return True;
1605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return False;
1607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Generate x86 spill/reload instructions under the direction of the
1611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   register allocator.  Note it's critical these don't write the
1612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   condition codes. */
1613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid genSpill_X86 ( /*OUT*/HInstr** i1, /*OUT*/HInstr** i2,
1615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    HReg rreg, Int offsetB, Bool mode64 )
1616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   X86AMode* am;
1618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(offsetB >= 0);
1619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(!hregIsVirtual(rreg));
1620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(mode64 == False);
1621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *i1 = *i2 = NULL;
1622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   am = X86AMode_IR(offsetB, hregX86_EBP());
1623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (hregClass(rreg)) {
1624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case HRcInt32:
1625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *i1 = X86Instr_Alu32M ( Xalu_MOV, X86RI_Reg(rreg), am );
1626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case HRcFlt64:
1628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *i1 = X86Instr_FpLdSt ( False/*store*/, 10, rreg, am );
1629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case HRcVec128:
1631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *i1 = X86Instr_SseLdSt ( False/*store*/, rreg, am );
1632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
1634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppHRegClass(hregClass(rreg));
1635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("genSpill_X86: unimplemented regclass");
1636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid genReload_X86 ( /*OUT*/HInstr** i1, /*OUT*/HInstr** i2,
1640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     HReg rreg, Int offsetB, Bool mode64 )
1641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   X86AMode* am;
1643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(offsetB >= 0);
1644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(!hregIsVirtual(rreg));
1645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(mode64 == False);
1646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *i1 = *i2 = NULL;
1647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   am = X86AMode_IR(offsetB, hregX86_EBP());
1648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (hregClass(rreg)) {
1649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case HRcInt32:
1650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *i1 = X86Instr_Alu32R ( Xalu_MOV, X86RMI_Mem(am), rreg );
1651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case HRcFlt64:
1653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *i1 = X86Instr_FpLdSt ( True/*load*/, 10, rreg, am );
1654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case HRcVec128:
1656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *i1 = X86Instr_SseLdSt ( True/*load*/, rreg, am );
1657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
1659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppHRegClass(hregClass(rreg));
1660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("genReload_X86: unimplemented regclass");
1661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* The given instruction reads the specified vreg exactly once, and
1665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   that vreg is currently located at the given spill offset.  If
1666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   possible, return a variant of the instruction to one which instead
1667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   references the spill slot directly. */
1668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownX86Instr* directReload_X86( X86Instr* i, HReg vreg, Short spill_off )
1670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(spill_off >= 0 && spill_off < 10000); /* let's say */
1672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Deal with form: src=RMI_Reg, dst=Reg where src == vreg
1674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Convert to: src=RMI_Mem, dst=Reg
1675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
1676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (i->tag == Xin_Alu32R
1677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && (i->Xin.Alu32R.op == Xalu_MOV || i->Xin.Alu32R.op == Xalu_OR
1678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || i->Xin.Alu32R.op == Xalu_XOR)
1679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && i->Xin.Alu32R.src->tag == Xrmi_Reg
1680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && i->Xin.Alu32R.src->Xrmi.Reg.reg == vreg) {
1681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(i->Xin.Alu32R.dst != vreg);
1682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return X86Instr_Alu32R(
1683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                i->Xin.Alu32R.op,
1684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                X86RMI_Mem( X86AMode_IR( spill_off, hregX86_EBP())),
1685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                i->Xin.Alu32R.dst
1686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             );
1687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Deal with form: src=RMI_Imm, dst=Reg where dst == vreg
1690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Convert to: src=RI_Imm, dst=Mem
1691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
1692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (i->tag == Xin_Alu32R
1693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && (i->Xin.Alu32R.op == Xalu_CMP)
1694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && i->Xin.Alu32R.src->tag == Xrmi_Imm
1695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && i->Xin.Alu32R.dst == vreg) {
1696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return X86Instr_Alu32M(
1697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                i->Xin.Alu32R.op,
1698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		X86RI_Imm( i->Xin.Alu32R.src->Xrmi.Imm.imm32 ),
1699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                X86AMode_IR( spill_off, hregX86_EBP())
1700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             );
1701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Deal with form: Push(RMI_Reg)
1704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Convert to: Push(RMI_Mem)
1705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
1706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (i->tag == Xin_Push
1707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && i->Xin.Push.src->tag == Xrmi_Reg
1708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && i->Xin.Push.src->Xrmi.Reg.reg == vreg) {
1709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return X86Instr_Push(
1710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                X86RMI_Mem( X86AMode_IR( spill_off, hregX86_EBP()))
1711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             );
1712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Deal with form: CMov32(src=RM_Reg, dst) where vreg == src
1715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Convert to CMov32(RM_Mem, dst) */
1716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (i->tag == Xin_CMov32
1717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && i->Xin.CMov32.src->tag == Xrm_Reg
1718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && i->Xin.CMov32.src->Xrm.Reg.reg == vreg) {
1719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(i->Xin.CMov32.dst != vreg);
1720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return X86Instr_CMov32(
1721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                i->Xin.CMov32.cond,
1722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                X86RM_Mem( X86AMode_IR( spill_off, hregX86_EBP() )),
1723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                i->Xin.CMov32.dst
1724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             );
1725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Deal with form: Test32(imm,RM_Reg vreg) -> Test32(imm,amode) */
1728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (i->tag == Xin_Test32
1729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && i->Xin.Test32.dst->tag == Xrm_Reg
1730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && i->Xin.Test32.dst->Xrm.Reg.reg == vreg) {
1731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return X86Instr_Test32(
1732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                i->Xin.Test32.imm32,
1733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                X86RM_Mem( X86AMode_IR( spill_off, hregX86_EBP() ) )
1734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             );
1735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return NULL;
1738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------- The x86 assembler (bleh.) --------- */
1742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UChar iregNo ( HReg r )
1744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt n;
1746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(hregClass(r) == HRcInt32);
1747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(!hregIsVirtual(r));
1748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   n = hregNumber(r);
1749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(n <= 7);
1750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return toUChar(n);
1751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UInt fregNo ( HReg r )
1754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt n;
1756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(hregClass(r) == HRcFlt64);
1757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(!hregIsVirtual(r));
1758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   n = hregNumber(r);
1759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(n <= 5);
1760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return n;
1761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UInt vregNo ( HReg r )
1764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt n;
1766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(hregClass(r) == HRcVec128);
1767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(!hregIsVirtual(r));
1768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   n = hregNumber(r);
1769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(n <= 7);
1770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return n;
1771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UChar mkModRegRM ( UChar mod, UChar reg, UChar regmem )
1774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return toUChar( ((mod & 3) << 6)
1776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   | ((reg & 7) << 3)
1777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   | (regmem & 7) );
1778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UChar mkSIB ( Int shift, Int regindex, Int regbase )
1781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return toUChar( ((shift & 3) << 6)
1783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   | ((regindex & 7) << 3)
1784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   | (regbase & 7) );
1785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UChar* emit32 ( UChar* p, UInt w32 )
1788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *p++ = toUChar( w32        & 0x000000FF);
1790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *p++ = toUChar((w32 >>  8) & 0x000000FF);
1791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *p++ = toUChar((w32 >> 16) & 0x000000FF);
1792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *p++ = toUChar((w32 >> 24) & 0x000000FF);
1793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return p;
1794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Does a sign-extend of the lowest 8 bits give
1797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the original number? */
1798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool fits8bits ( UInt w32 )
1799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int i32 = (Int)w32;
1801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return toBool(i32 == ((i32 << 24) >> 24));
1802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Forming mod-reg-rm bytes and scale-index-base bytes.
1806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     greg,  0(ereg)    |  ereg != ESP && ereg != EBP
1808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       =  00 greg ereg
1809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     greg,  d8(ereg)   |  ereg != ESP
1811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       =  01 greg ereg, d8
1812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     greg,  d32(ereg)  |  ereg != ESP
1814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       =  10 greg ereg, d32
1815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     greg,  d8(%esp)   =  01 greg 100, 0x24, d8
1817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     -----------------------------------------------
1819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     greg,  d8(base,index,scale)
1821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               |  index != ESP
1822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               =  01 greg 100, scale index base, d8
1823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     greg,  d32(base,index,scale)
1825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               |  index != ESP
1826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               =  10 greg 100, scale index base, d32
1827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
1828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UChar* doAMode_M ( UChar* p, HReg greg, X86AMode* am )
1829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (am->tag == Xam_IR) {
1831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (am->Xam.IR.imm == 0
1832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && am->Xam.IR.reg != hregX86_ESP()
1833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && am->Xam.IR.reg != hregX86_EBP() ) {
1834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = mkModRegRM(0, iregNo(greg), iregNo(am->Xam.IR.reg));
1835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return p;
1836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (fits8bits(am->Xam.IR.imm)
1838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && am->Xam.IR.reg != hregX86_ESP()) {
1839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = mkModRegRM(1, iregNo(greg), iregNo(am->Xam.IR.reg));
1840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = toUChar(am->Xam.IR.imm & 0xFF);
1841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return p;
1842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (am->Xam.IR.reg != hregX86_ESP()) {
1844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = mkModRegRM(2, iregNo(greg), iregNo(am->Xam.IR.reg));
1845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         p = emit32(p, am->Xam.IR.imm);
1846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return p;
1847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (am->Xam.IR.reg == hregX86_ESP()
1849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && fits8bits(am->Xam.IR.imm)) {
1850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 	 *p++ = mkModRegRM(1, iregNo(greg), 4);
1851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = 0x24;
1852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = toUChar(am->Xam.IR.imm & 0xFF);
1853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return p;
1854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ppX86AMode(am);
1856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vpanic("doAMode_M: can't emit amode IR");
1857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /*NOTREACHED*/
1858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (am->tag == Xam_IRRS) {
1860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (fits8bits(am->Xam.IRRS.imm)
1861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && am->Xam.IRRS.index != hregX86_ESP()) {
1862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = mkModRegRM(1, iregNo(greg), 4);
1863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = mkSIB(am->Xam.IRRS.shift, am->Xam.IRRS.index,
1864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                          am->Xam.IRRS.base);
1865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = toUChar(am->Xam.IRRS.imm & 0xFF);
1866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return p;
1867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (am->Xam.IRRS.index != hregX86_ESP()) {
1869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = mkModRegRM(2, iregNo(greg), 4);
1870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = mkSIB(am->Xam.IRRS.shift, am->Xam.IRRS.index,
1871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                          am->Xam.IRRS.base);
1872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         p = emit32(p, am->Xam.IRRS.imm);
1873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return p;
1874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ppX86AMode(am);
1876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vpanic("doAMode_M: can't emit amode IRRS");
1877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /*NOTREACHED*/
1878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vpanic("doAMode_M: unknown amode");
1880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /*NOTREACHED*/
1881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Emit a mod-reg-rm byte when the rm bit denotes a reg. */
1885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UChar* doAMode_R ( UChar* p, HReg greg, HReg ereg )
1886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *p++ = mkModRegRM(3, iregNo(greg), iregNo(ereg));
1888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return p;
1889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Emit ffree %st(7) */
1893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UChar* do_ffree_st7 ( UChar* p )
1894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *p++ = 0xDD;
1896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *p++ = 0xC7;
1897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return p;
1898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Emit fstp %st(i), 1 <= i <= 7 */
1901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UChar* do_fstp_st ( UChar* p, Int i )
1902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(1 <= i && i <= 7);
1904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *p++ = 0xDD;
1905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *p++ = toUChar(0xD8+i);
1906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return p;
1907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Emit fld %st(i), 0 <= i <= 6 */
1910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UChar* do_fld_st ( UChar* p, Int i )
1911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(0 <= i && i <= 6);
1913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *p++ = 0xD9;
1914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *p++ = toUChar(0xC0+i);
1915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return p;
1916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Emit f<op> %st(0) */
1919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UChar* do_fop1_st ( UChar* p, X86FpOp op )
1920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (op) {
1922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xfp_NEG:    *p++ = 0xD9; *p++ = 0xE0; break;
1923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xfp_ABS:    *p++ = 0xD9; *p++ = 0xE1; break;
1924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xfp_SQRT:   *p++ = 0xD9; *p++ = 0xFA; break;
1925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xfp_ROUND:  *p++ = 0xD9; *p++ = 0xFC; break;
1926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xfp_SIN:    *p++ = 0xD9; *p++ = 0xFE; break;
1927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xfp_COS:    *p++ = 0xD9; *p++ = 0xFF; break;
1928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xfp_2XM1:   *p++ = 0xD9; *p++ = 0xF0; break;
1929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xfp_MOV:    break;
1930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xfp_TAN:    p = do_ffree_st7(p); /* since fptan pushes 1.0 */
1931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       *p++ = 0xD9; *p++ = 0xF2; /* fptan */
1932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       *p++ = 0xD9; *p++ = 0xF7; /* fincstp */
1933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       break;
1934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default: vpanic("do_fop1_st: unknown op");
1935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return p;
1937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Emit f<op> %st(i), 1 <= i <= 5 */
1940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UChar* do_fop2_st ( UChar* p, X86FpOp op, Int i )
1941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define fake(_n) mkHReg((_n), HRcInt32, False)
1943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int subopc;
1944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (op) {
1945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xfp_ADD: subopc = 0; break;
1946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xfp_SUB: subopc = 4; break;
1947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xfp_MUL: subopc = 1; break;
1948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xfp_DIV: subopc = 6; break;
1949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default: vpanic("do_fop2_st: unknown op");
1950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *p++ = 0xD8;
1952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   p    = doAMode_R(p, fake(subopc), fake(i));
1953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return p;
1954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  undef fake
1955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Push a 32-bit word on the stack.  The word depends on tags[3:0];
1958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browneach byte is either 0x00 or 0xFF depending on the corresponding bit in tags[].
1959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
1960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UChar* push_word_from_tags ( UChar* p, UShort tags )
1961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt w;
1963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(0 == (tags & ~0xF));
1964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (tags == 0) {
1965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* pushl $0x00000000 */
1966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = 0x6A;
1967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = 0x00;
1968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else
1970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* pushl $0xFFFFFFFF */
1971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (tags == 0xF) {
1972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = 0x6A;
1973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = 0xFF;
1974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
1975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(0); /* awaiting test case */
1976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      w = 0;
1977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (tags & 1) w |= 0x000000FF;
1978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (tags & 2) w |= 0x0000FF00;
1979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (tags & 4) w |= 0x00FF0000;
1980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (tags & 8) w |= 0xFF000000;
1981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = 0x68;
1982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      p = emit32(p, w);
1983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return p;
1985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Emit an instruction into buf and return the number of bytes used.
1988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Note that buf is not the insn's final place, and therefore it is
1989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   imperative to emit position-independent code. */
1990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownInt emit_X86Instr ( UChar* buf, Int nbuf, X86Instr* i,
1992b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                    Bool mode64,
1993b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                    void* dispatch_unassisted,
1994b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                    void* dispatch_assisted )
1995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt irno, opc, opc_rr, subopc_imm, opc_imma, opc_cl, opc_imm, subopc;
1997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt   xtra;
1999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar* p = &buf[0];
2000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar* ptmp;
2001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(nbuf >= 32);
2002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(mode64 == False);
2003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Wrap an integer as a int register, for use assembling
2005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      GrpN insns, in which the greg field is used as a sub-opcode
2006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      and does not really contain a register. */
2007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define fake(_n) mkHReg((_n), HRcInt32, False)
2008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* vex_printf("asm  ");ppX86Instr(i, mode64); vex_printf("\n"); */
2010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (i->tag) {
2012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Xin_Alu32R:
2014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Deal specially with MOV */
2015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (i->Xin.Alu32R.op == Xalu_MOV) {
2016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch (i->Xin.Alu32R.src->tag) {
2017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Xrmi_Imm:
2018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               *p++ = toUChar(0xB8 + iregNo(i->Xin.Alu32R.dst));
2019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               p = emit32(p, i->Xin.Alu32R.src->Xrmi.Imm.imm32);
2020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               goto done;
2021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Xrmi_Reg:
2022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               *p++ = 0x89;
2023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               p = doAMode_R(p, i->Xin.Alu32R.src->Xrmi.Reg.reg,
2024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                i->Xin.Alu32R.dst);
2025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               goto done;
2026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Xrmi_Mem:
2027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               *p++ = 0x8B;
2028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               p = doAMode_M(p, i->Xin.Alu32R.dst,
2029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                i->Xin.Alu32R.src->Xrmi.Mem.am);
2030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               goto done;
2031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default:
2032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               goto bad;
2033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
2034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* MUL */
2036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (i->Xin.Alu32R.op == Xalu_MUL) {
2037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch (i->Xin.Alu32R.src->tag) {
2038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Xrmi_Reg:
2039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               *p++ = 0x0F;
2040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               *p++ = 0xAF;
2041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               p = doAMode_R(p, i->Xin.Alu32R.dst,
2042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                i->Xin.Alu32R.src->Xrmi.Reg.reg);
2043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               goto done;
2044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Xrmi_Mem:
2045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               *p++ = 0x0F;
2046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               *p++ = 0xAF;
2047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               p = doAMode_M(p, i->Xin.Alu32R.dst,
2048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                i->Xin.Alu32R.src->Xrmi.Mem.am);
2049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               goto done;
2050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Xrmi_Imm:
2051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (fits8bits(i->Xin.Alu32R.src->Xrmi.Imm.imm32)) {
2052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  *p++ = 0x6B;
2053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  p = doAMode_R(p, i->Xin.Alu32R.dst, i->Xin.Alu32R.dst);
2054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  *p++ = toUChar(0xFF & i->Xin.Alu32R.src->Xrmi.Imm.imm32);
2055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               } else {
2056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  *p++ = 0x69;
2057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  p = doAMode_R(p, i->Xin.Alu32R.dst, i->Xin.Alu32R.dst);
2058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  p = emit32(p, i->Xin.Alu32R.src->Xrmi.Imm.imm32);
2059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
2060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               goto done;
2061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default:
2062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               goto bad;
2063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
2064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ADD/SUB/ADC/SBB/AND/OR/XOR/CMP */
2066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      opc = opc_rr = subopc_imm = opc_imma = 0;
2067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (i->Xin.Alu32R.op) {
2068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xalu_ADC: opc = 0x13; opc_rr = 0x11;
2069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        subopc_imm = 2; opc_imma = 0x15; break;
2070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xalu_ADD: opc = 0x03; opc_rr = 0x01;
2071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        subopc_imm = 0; opc_imma = 0x05; break;
2072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xalu_SUB: opc = 0x2B; opc_rr = 0x29;
2073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        subopc_imm = 5; opc_imma = 0x2D; break;
2074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xalu_SBB: opc = 0x1B; opc_rr = 0x19;
2075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        subopc_imm = 3; opc_imma = 0x1D; break;
2076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xalu_AND: opc = 0x23; opc_rr = 0x21;
2077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        subopc_imm = 4; opc_imma = 0x25; break;
2078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xalu_XOR: opc = 0x33; opc_rr = 0x31;
2079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        subopc_imm = 6; opc_imma = 0x35; break;
2080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xalu_OR:  opc = 0x0B; opc_rr = 0x09;
2081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        subopc_imm = 1; opc_imma = 0x0D; break;
2082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xalu_CMP: opc = 0x3B; opc_rr = 0x39;
2083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        subopc_imm = 7; opc_imma = 0x3D; break;
2084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default: goto bad;
2085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (i->Xin.Alu32R.src->tag) {
2087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xrmi_Imm:
2088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (i->Xin.Alu32R.dst == hregX86_EAX()
2089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                && !fits8bits(i->Xin.Alu32R.src->Xrmi.Imm.imm32)) {
2090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               *p++ = toUChar(opc_imma);
2091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               p = emit32(p, i->Xin.Alu32R.src->Xrmi.Imm.imm32);
2092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else
2093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (fits8bits(i->Xin.Alu32R.src->Xrmi.Imm.imm32)) {
2094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               *p++ = 0x83;
2095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               p    = doAMode_R(p, fake(subopc_imm), i->Xin.Alu32R.dst);
2096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               *p++ = toUChar(0xFF & i->Xin.Alu32R.src->Xrmi.Imm.imm32);
2097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
2098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               *p++ = 0x81;
2099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               p    = doAMode_R(p, fake(subopc_imm), i->Xin.Alu32R.dst);
2100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               p    = emit32(p, i->Xin.Alu32R.src->Xrmi.Imm.imm32);
2101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
2102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto done;
2103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xrmi_Reg:
2104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *p++ = toUChar(opc_rr);
2105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            p = doAMode_R(p, i->Xin.Alu32R.src->Xrmi.Reg.reg,
2106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             i->Xin.Alu32R.dst);
2107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto done;
2108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xrmi_Mem:
2109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *p++ = toUChar(opc);
2110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            p = doAMode_M(p, i->Xin.Alu32R.dst,
2111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             i->Xin.Alu32R.src->Xrmi.Mem.am);
2112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto done;
2113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:
2114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto bad;
2115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
2117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Xin_Alu32M:
2119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Deal specially with MOV */
2120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (i->Xin.Alu32M.op == Xalu_MOV) {
2121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch (i->Xin.Alu32M.src->tag) {
2122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Xri_Reg:
2123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               *p++ = 0x89;
2124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               p = doAMode_M(p, i->Xin.Alu32M.src->Xri.Reg.reg,
2125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                i->Xin.Alu32M.dst);
2126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               goto done;
2127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Xri_Imm:
2128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               *p++ = 0xC7;
2129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               p = doAMode_M(p, fake(0), i->Xin.Alu32M.dst);
2130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               p = emit32(p, i->Xin.Alu32M.src->Xri.Imm.imm32);
2131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               goto done;
2132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default:
2133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               goto bad;
2134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
2135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ADD/SUB/ADC/SBB/AND/OR/XOR/CMP.  MUL is not
2137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         allowed here. */
2138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      opc = subopc_imm = opc_imma = 0;
2139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (i->Xin.Alu32M.op) {
2140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xalu_ADD: opc = 0x01; subopc_imm = 0; break;
2141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xalu_SUB: opc = 0x29; subopc_imm = 5; break;
2142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xalu_CMP: opc = 0x39; subopc_imm = 7; break;
2143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default: goto bad;
2144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (i->Xin.Alu32M.src->tag) {
2146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xri_Reg:
2147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *p++ = toUChar(opc);
2148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            p = doAMode_M(p, i->Xin.Alu32M.src->Xri.Reg.reg,
2149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             i->Xin.Alu32M.dst);
2150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto done;
2151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xri_Imm:
2152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (fits8bits(i->Xin.Alu32M.src->Xri.Imm.imm32)) {
2153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               *p++ = 0x83;
2154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               p    = doAMode_M(p, fake(subopc_imm), i->Xin.Alu32M.dst);
2155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               *p++ = toUChar(0xFF & i->Xin.Alu32M.src->Xri.Imm.imm32);
2156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               goto done;
2157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
2158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               *p++ = 0x81;
2159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               p    = doAMode_M(p, fake(subopc_imm), i->Xin.Alu32M.dst);
2160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               p    = emit32(p, i->Xin.Alu32M.src->Xri.Imm.imm32);
2161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               goto done;
2162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
2163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:
2164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto bad;
2165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
2167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Xin_Sh32:
2169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      opc_cl = opc_imm = subopc = 0;
2170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (i->Xin.Sh32.op) {
2171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsh_SHR: opc_cl = 0xD3; opc_imm = 0xC1; subopc = 5; break;
2172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsh_SAR: opc_cl = 0xD3; opc_imm = 0xC1; subopc = 7; break;
2173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsh_SHL: opc_cl = 0xD3; opc_imm = 0xC1; subopc = 4; break;
2174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default: goto bad;
2175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (i->Xin.Sh32.src == 0) {
2177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = toUChar(opc_cl);
2178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         p = doAMode_R(p, fake(subopc), i->Xin.Sh32.dst);
2179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
2180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = toUChar(opc_imm);
2181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         p = doAMode_R(p, fake(subopc), i->Xin.Sh32.dst);
2182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = (UChar)(i->Xin.Sh32.src);
2183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto done;
2185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Xin_Test32:
2187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (i->Xin.Test32.dst->tag == Xrm_Reg) {
2188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* testl $imm32, %reg */
2189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = 0xF7;
2190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         p = doAMode_R(p, fake(0), i->Xin.Test32.dst->Xrm.Reg.reg);
2191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         p = emit32(p, i->Xin.Test32.imm32);
2192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto done;
2193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
2194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* testl $imm32, amode */
2195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = 0xF7;
2196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         p = doAMode_M(p, fake(0), i->Xin.Test32.dst->Xrm.Mem.am);
2197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         p = emit32(p, i->Xin.Test32.imm32);
2198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto done;
2199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Xin_Unary32:
2202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (i->Xin.Unary32.op == Xun_NOT) {
2203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = 0xF7;
2204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         p = doAMode_R(p, fake(2), i->Xin.Unary32.dst);
2205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto done;
2206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (i->Xin.Unary32.op == Xun_NEG) {
2208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = 0xF7;
2209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         p = doAMode_R(p, fake(3), i->Xin.Unary32.dst);
2210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto done;
2211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
2213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Xin_Lea32:
2215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = 0x8D;
2216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      p = doAMode_M(p, i->Xin.Lea32.dst, i->Xin.Lea32.am);
2217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto done;
2218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Xin_MulL:
2220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      subopc = i->Xin.MulL.syned ? 5 : 4;
2221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = 0xF7;
2222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (i->Xin.MulL.src->tag)  {
2223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xrm_Mem:
2224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            p = doAMode_M(p, fake(subopc),
2225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             i->Xin.MulL.src->Xrm.Mem.am);
2226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto done;
2227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xrm_Reg:
2228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            p = doAMode_R(p, fake(subopc),
2229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             i->Xin.MulL.src->Xrm.Reg.reg);
2230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto done;
2231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:
2232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto bad;
2233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
2235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Xin_Div:
2237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      subopc = i->Xin.Div.syned ? 7 : 6;
2238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = 0xF7;
2239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (i->Xin.Div.src->tag)  {
2240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xrm_Mem:
2241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            p = doAMode_M(p, fake(subopc),
2242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             i->Xin.Div.src->Xrm.Mem.am);
2243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto done;
2244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xrm_Reg:
2245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            p = doAMode_R(p, fake(subopc),
2246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             i->Xin.Div.src->Xrm.Reg.reg);
2247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto done;
2248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:
2249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto bad;
2250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
2252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Xin_Sh3232:
2254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(i->Xin.Sh3232.op == Xsh_SHL || i->Xin.Sh3232.op == Xsh_SHR);
2255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (i->Xin.Sh3232.amt == 0) {
2256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* shldl/shrdl by %cl */
2257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = 0x0F;
2258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (i->Xin.Sh3232.op == Xsh_SHL) {
2259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *p++ = 0xA5;
2260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
2261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *p++ = 0xAD;
2262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
2263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         p = doAMode_R(p, i->Xin.Sh3232.src, i->Xin.Sh3232.dst);
2264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto done;
2265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
2267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Xin_Push:
2269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (i->Xin.Push.src->tag) {
2270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xrmi_Mem:
2271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *p++ = 0xFF;
2272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            p = doAMode_M(p, fake(6), i->Xin.Push.src->Xrmi.Mem.am);
2273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto done;
2274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xrmi_Imm:
2275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *p++ = 0x68;
2276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            p = emit32(p, i->Xin.Push.src->Xrmi.Imm.imm32);
2277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto done;
2278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xrmi_Reg:
2279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *p++ = toUChar(0x50 + iregNo(i->Xin.Push.src->Xrmi.Reg.reg));
2280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto done;
2281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        default:
2282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto bad;
2283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Xin_Call:
2286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* See detailed comment for Xin_Call in getRegUsage_X86Instr above
2287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for explanation of this. */
2288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (i->Xin.Call.regparms) {
2289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 0: irno = iregNo(hregX86_EAX()); break;
2290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 1: irno = iregNo(hregX86_EDX()); break;
2291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 2: irno = iregNo(hregX86_ECX()); break;
2292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 3: irno = iregNo(hregX86_EDI()); break;
2293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default: vpanic(" emit_X86Instr:call:regparms");
2294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* jump over the following two insns if the condition does not
2296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         hold */
2297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (i->Xin.Call.cond != Xcc_ALWAYS) {
2298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = toUChar(0x70 + (0xF & (i->Xin.Call.cond ^ 1)));
2299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = 0x07; /* 7 bytes in the next two insns */
2300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* movl $target, %tmp */
2302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = toUChar(0xB8 + irno);
2303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      p = emit32(p, i->Xin.Call.target);
2304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* call *%tmp */
2305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = 0xFF;
2306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = toUChar(0xD0 + irno);
2307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto done;
2308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2309b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case Xin_Goto: {
2310b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      void* dispatch_to_use = NULL;
2311b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      vassert(dispatch_unassisted != NULL);
2312b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      vassert(dispatch_assisted != NULL);
2313b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
2314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Use ptmp for backpatching conditional jumps. */
2315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ptmp = NULL;
2316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* First off, if this is conditional, create a conditional
2318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 jump over the rest of it. */
2319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (i->Xin.Goto.cond != Xcc_ALWAYS) {
2320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* jmp fwds if !condition */
2321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = toUChar(0x70 + (0xF & (i->Xin.Goto.cond ^ 1)));
2322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ptmp = p; /* fill in this bit later */
2323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = 0; /* # of bytes to jump over; don't know how many yet. */
2324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* If a non-boring, set %ebp (the guest state pointer)
2327b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         appropriately.  Also, decide which dispatcher we need to
2328b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         use. */
2329b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      dispatch_to_use = dispatch_assisted;
2330b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
2331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* movl $magic_number, %ebp */
2332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (i->Xin.Goto.jk) {
2333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ijk_ClientReq:
2334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *p++ = 0xBD;
2335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            p = emit32(p, VEX_TRC_JMP_CLIENTREQ); break;
2336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ijk_Sys_int128:
2337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *p++ = 0xBD;
2338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            p = emit32(p, VEX_TRC_JMP_SYS_INT128); break;
2339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ijk_Sys_int129:
2340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *p++ = 0xBD;
2341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            p = emit32(p, VEX_TRC_JMP_SYS_INT129); break;
2342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ijk_Sys_int130:
2343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *p++ = 0xBD;
2344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            p = emit32(p, VEX_TRC_JMP_SYS_INT130); break;
2345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ijk_Yield:
2346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *p++ = 0xBD;
2347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            p = emit32(p, VEX_TRC_JMP_YIELD); break;
2348f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov         case Ijk_YieldNoRedir:
2349f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov            *p++ = 0xBD;
2350f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov            p = emit32(p, VEX_TRC_JMP_YIELD_NOREDIR); break;
2351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ijk_EmWarn:
2352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *p++ = 0xBD;
2353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            p = emit32(p, VEX_TRC_JMP_EMWARN); break;
2354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ijk_MapFail:
2355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *p++ = 0xBD;
2356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            p = emit32(p, VEX_TRC_JMP_MAPFAIL); break;
2357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ijk_NoDecode:
2358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *p++ = 0xBD;
2359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            p = emit32(p, VEX_TRC_JMP_NODECODE); break;
2360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ijk_TInval:
2361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *p++ = 0xBD;
2362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            p = emit32(p, VEX_TRC_JMP_TINVAL); break;
2363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ijk_NoRedir:
2364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *p++ = 0xBD;
2365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            p = emit32(p, VEX_TRC_JMP_NOREDIR); break;
2366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ijk_Sys_sysenter:
2367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *p++ = 0xBD;
2368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            p = emit32(p, VEX_TRC_JMP_SYS_SYSENTER); break;
2369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ijk_SigTRAP:
2370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *p++ = 0xBD;
2371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            p = emit32(p, VEX_TRC_JMP_SIGTRAP); break;
2372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ijk_SigSEGV:
2373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *p++ = 0xBD;
2374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            p = emit32(p, VEX_TRC_JMP_SIGSEGV); break;
2375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ijk_Ret:
2376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 case Ijk_Call:
2377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ijk_Boring:
2378b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            dispatch_to_use = dispatch_unassisted;
2379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
2380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:
2381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ppIRJumpKind(i->Xin.Goto.jk);
2382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vpanic("emit_X86Instr.Xin_Goto: unknown jump kind");
2383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Get the destination address into %eax */
2386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (i->Xin.Goto.dst->tag == Xri_Imm) {
2387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* movl $immediate, %eax */
2388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = 0xB8;
2389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         p = emit32(p, i->Xin.Goto.dst->Xri.Imm.imm32);
2390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
2391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(i->Xin.Goto.dst->tag == Xri_Reg);
2392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* movl %reg, %eax */
2393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (i->Xin.Goto.dst->Xri.Reg.reg != hregX86_EAX()) {
2394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *p++ = 0x89;
2395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            p = doAMode_R(p, i->Xin.Goto.dst->Xri.Reg.reg, hregX86_EAX());
2396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
2397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Get the dispatcher address into %edx.  This has to happen
2400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         after the load of %eax since %edx might be carrying the value
2401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         destined for %eax immediately prior to this Xin_Goto. */
2402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(sizeof(UInt) == sizeof(void*));
2403b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      vassert(dispatch_to_use != NULL);
2404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* movl $imm32, %edx */
2405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = 0xBA;
2406b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      p = emit32(p, (UInt)Ptr_to_ULong(dispatch_to_use));
2407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* jmp *%edx */
2409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = 0xFF;
2410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = 0xE2;
2411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Fix up the conditional jump, if there was one. */
2413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (i->Xin.Goto.cond != Xcc_ALWAYS) {
2414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Int delta = p - ptmp;
2415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 vassert(delta > 0 && delta < 20);
2416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *ptmp = toUChar(delta-1);
2417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto done;
2419b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
2420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Xin_CMov32:
2422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(i->Xin.CMov32.cond != Xcc_ALWAYS);
2423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* This generates cmov, which is illegal on P54/P55. */
2425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /*
2426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = 0x0F;
2427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = toUChar(0x40 + (0xF & i->Xin.CMov32.cond));
2428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (i->Xin.CMov32.src->tag == Xrm_Reg) {
2429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         p = doAMode_R(p, i->Xin.CMov32.dst, i->Xin.CMov32.src->Xrm.Reg.reg);
2430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto done;
2431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (i->Xin.CMov32.src->tag == Xrm_Mem) {
2433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         p = doAMode_M(p, i->Xin.CMov32.dst, i->Xin.CMov32.src->Xrm.Mem.am);
2434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto done;
2435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      */
2437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Alternative version which works on any x86 variant. */
2439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* jmp fwds if !condition */
2440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = toUChar(0x70 + (i->Xin.CMov32.cond ^ 1));
2441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = 0; /* # of bytes in the next bit, which we don't know yet */
2442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ptmp = p;
2443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (i->Xin.CMov32.src->tag) {
2445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xrm_Reg:
2446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Big sigh.  This is movl E -> G ... */
2447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *p++ = 0x89;
2448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            p = doAMode_R(p, i->Xin.CMov32.src->Xrm.Reg.reg,
2449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             i->Xin.CMov32.dst);
2450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
2452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xrm_Mem:
2453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* ... whereas this is movl G -> E.  That's why the args
2454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               to doAMode_R appear to be the wrong way round in the
2455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               Xrm_Reg case. */
2456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *p++ = 0x8B;
2457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            p = doAMode_M(p, i->Xin.CMov32.dst,
2458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             i->Xin.CMov32.src->Xrm.Mem.am);
2459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
2460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:
2461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto bad;
2462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Fill in the jump offset. */
2464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *(ptmp-1) = toUChar(p - ptmp);
2465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto done;
2466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
2468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Xin_LoadEX:
2470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (i->Xin.LoadEX.szSmall == 1 && !i->Xin.LoadEX.syned) {
2471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* movzbl */
2472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = 0x0F;
2473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = 0xB6;
2474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         p = doAMode_M(p, i->Xin.LoadEX.dst, i->Xin.LoadEX.src);
2475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto done;
2476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (i->Xin.LoadEX.szSmall == 2 && !i->Xin.LoadEX.syned) {
2478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* movzwl */
2479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = 0x0F;
2480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = 0xB7;
2481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         p = doAMode_M(p, i->Xin.LoadEX.dst, i->Xin.LoadEX.src);
2482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto done;
2483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (i->Xin.LoadEX.szSmall == 1 && i->Xin.LoadEX.syned) {
2485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* movsbl */
2486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = 0x0F;
2487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = 0xBE;
2488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         p = doAMode_M(p, i->Xin.LoadEX.dst, i->Xin.LoadEX.src);
2489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto done;
2490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
2492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Xin_Set32:
2494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Make the destination register be 1 or 0, depending on whether
2495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         the relevant condition holds.  We have to dodge and weave
2496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         when the destination is %esi or %edi as we cannot directly
2497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         emit the native 'setb %reg' for those.  Further complication:
2498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         the top 24 bits of the destination should be forced to zero,
2499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         but doing 'xor %r,%r' kills the flag(s) we are about to read.
2500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Sigh.  So start off my moving $0 into the dest. */
2501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Do we need to swap in %eax? */
2503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (iregNo(i->Xin.Set32.dst) >= 4) {
2504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* xchg %eax, %dst */
2505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = toUChar(0x90 + iregNo(i->Xin.Set32.dst));
2506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* movl $0, %eax */
2507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ =toUChar(0xB8 + iregNo(hregX86_EAX()));
2508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         p = emit32(p, 0);
2509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* setb lo8(%eax) */
2510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = 0x0F;
2511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = toUChar(0x90 + (0xF & i->Xin.Set32.cond));
2512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         p = doAMode_R(p, fake(0), hregX86_EAX());
2513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* xchg %eax, %dst */
2514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = toUChar(0x90 + iregNo(i->Xin.Set32.dst));
2515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
2516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* movl $0, %dst */
2517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = toUChar(0xB8 + iregNo(i->Xin.Set32.dst));
2518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         p = emit32(p, 0);
2519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* setb lo8(%dst) */
2520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = 0x0F;
2521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = toUChar(0x90 + (0xF & i->Xin.Set32.cond));
2522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         p = doAMode_R(p, fake(0), i->Xin.Set32.dst);
2523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto done;
2525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Xin_Bsfr32:
2527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = 0x0F;
2528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (i->Xin.Bsfr32.isFwds) {
2529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = 0xBC;
2530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
2531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = 0xBD;
2532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      p = doAMode_R(p, i->Xin.Bsfr32.dst, i->Xin.Bsfr32.src);
2534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto done;
2535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Xin_MFence:
2537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* see comment in hdefs.h re this insn */
2538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (0) vex_printf("EMIT FENCE\n");
2539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (i->Xin.MFence.hwcaps & (VEX_HWCAPS_X86_SSE3
2540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  |VEX_HWCAPS_X86_SSE2)) {
2541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* mfence */
2542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = 0x0F; *p++ = 0xAE; *p++ = 0xF0;
2543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto done;
2544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (i->Xin.MFence.hwcaps & VEX_HWCAPS_X86_SSE1) {
2546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* sfence */
2547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = 0x0F; *p++ = 0xAE; *p++ = 0xF8;
2548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* lock addl $0,0(%esp) */
2549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = 0xF0; *p++ = 0x83; *p++ = 0x44;
2550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = 0x24; *p++ = 0x00; *p++ = 0x00;
2551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto done;
2552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (i->Xin.MFence.hwcaps == 0/*baseline, no SSE*/) {
2554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* lock addl $0,0(%esp) */
2555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = 0xF0; *p++ = 0x83; *p++ = 0x44;
2556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = 0x24; *p++ = 0x00; *p++ = 0x00;
2557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto done;
2558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vpanic("emit_X86Instr:mfence:hwcaps");
2560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /*NOTREACHED*/
2561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
2562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Xin_ACAS:
2564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* lock */
2565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = 0xF0;
2566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* cmpxchg{b,w,l} %ebx,mem.  Expected-value in %eax, new value
2567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         in %ebx.  The new-value register is hardwired to be %ebx
2568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         since letting it be any integer register gives the problem
2569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         that %sil and %dil are unaddressible on x86 and hence we
2570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         would have to resort to the same kind of trickery as with
2571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         byte-sized Xin.Store, just below.  Given that this isn't
2572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         performance critical, it is simpler just to force the
2573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         register operand to %ebx (could equally be %ecx or %edx).
2574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         (Although %ebx is more consistent with cmpxchg8b.) */
2575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (i->Xin.ACAS.sz == 2) *p++ = 0x66;
2576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = 0x0F;
2577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (i->Xin.ACAS.sz == 1) *p++ = 0xB0; else *p++ = 0xB1;
2578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      p = doAMode_M(p, hregX86_EBX(), i->Xin.ACAS.addr);
2579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto done;
2580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Xin_DACAS:
2582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* lock */
2583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = 0xF0;
2584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* cmpxchg8b m64.  Expected-value in %edx:%eax, new value
2585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         in %ecx:%ebx.  All 4 regs are hardwired in the ISA, so
2586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         aren't encoded in the insn. */
2587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = 0x0F;
2588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = 0xC7;
2589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      p = doAMode_M(p, fake(1), i->Xin.DACAS.addr);
2590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto done;
2591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Xin_Store:
2593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (i->Xin.Store.sz == 2) {
2594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* This case, at least, is simple, given that we can
2595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            reference the low 16 bits of any integer register. */
2596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = 0x66;
2597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = 0x89;
2598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         p = doAMode_M(p, i->Xin.Store.src, i->Xin.Store.dst);
2599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto done;
2600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (i->Xin.Store.sz == 1) {
2603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* We have to do complex dodging and weaving if src is not
2604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            the low 8 bits of %eax/%ebx/%ecx/%edx. */
2605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (iregNo(i->Xin.Store.src) < 4) {
2606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* we're OK, can do it directly */
2607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *p++ = 0x88;
2608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            p = doAMode_M(p, i->Xin.Store.src, i->Xin.Store.dst);
2609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           goto done;
2610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
2611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Bleh.  This means the source is %edi or %esi.  Since
2612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               the address mode can only mention three registers, at
2613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               least one of %eax/%ebx/%ecx/%edx must be available to
2614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               temporarily swap the source into, so the store can
2615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               happen.  So we have to look at the regs mentioned
2616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               in the amode. */
2617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg swap = INVALID_HREG;
2618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg  eax = hregX86_EAX(), ebx = hregX86_EBX(),
2619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  ecx = hregX86_ECX(), edx = hregX86_EDX();
2620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Bool a_ok = True, b_ok = True, c_ok = True, d_ok = True;
2621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HRegUsage u;
2622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Int j;
2623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            initHRegUsage(&u);
2624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addRegUsage_X86AMode(&u,  i->Xin.Store.dst);
2625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            for (j = 0; j < u.n_used; j++) {
2626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               HReg r = u.hreg[j];
2627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (r == eax) a_ok = False;
2628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (r == ebx) b_ok = False;
2629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (r == ecx) c_ok = False;
2630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (r == edx) d_ok = False;
2631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
2632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (a_ok) swap = eax;
2633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (b_ok) swap = ebx;
2634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (c_ok) swap = ecx;
2635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (d_ok) swap = edx;
2636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(swap != INVALID_HREG);
2637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* xchgl %source, %swap. Could do better if swap is %eax. */
2638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *p++ = 0x87;
2639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            p = doAMode_R(p, i->Xin.Store.src, swap);
2640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* movb lo8{%swap}, (dst) */
2641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *p++ = 0x88;
2642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            p = doAMode_M(p, swap, i->Xin.Store.dst);
2643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* xchgl %source, %swap. Could do better if swap is %eax. */
2644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *p++ = 0x87;
2645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            p = doAMode_R(p, i->Xin.Store.src, swap);
2646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto done;
2647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
2648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } /* if (i->Xin.Store.sz == 1) */
2649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
2650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Xin_FpUnary:
2652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* gop %src, %dst
2653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         --> ffree %st7 ; fld %st(src) ; fop %st(0) ; fstp %st(1+dst)
2654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      */
2655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      p = do_ffree_st7(p);
2656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      p = do_fld_st(p, 0+hregNumber(i->Xin.FpUnary.src));
2657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      p = do_fop1_st(p, i->Xin.FpUnary.op);
2658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      p = do_fstp_st(p, 1+hregNumber(i->Xin.FpUnary.dst));
2659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto done;
2660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Xin_FpBinary:
2662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (i->Xin.FpBinary.op == Xfp_YL2X
2663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          || i->Xin.FpBinary.op == Xfp_YL2XP1) {
2664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Have to do this specially. */
2665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* ffree %st7 ; fld %st(srcL) ;
2666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ffree %st7 ; fld %st(srcR+1) ; fyl2x{p1} ; fstp(1+dst) */
2667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         p = do_ffree_st7(p);
2668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         p = do_fld_st(p, 0+hregNumber(i->Xin.FpBinary.srcL));
2669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         p = do_ffree_st7(p);
2670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         p = do_fld_st(p, 1+hregNumber(i->Xin.FpBinary.srcR));
2671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = 0xD9;
2672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = toUChar(i->Xin.FpBinary.op==Xfp_YL2X ? 0xF1 : 0xF9);
2673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         p = do_fstp_st(p, 1+hregNumber(i->Xin.FpBinary.dst));
2674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto done;
2675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (i->Xin.FpBinary.op == Xfp_ATAN) {
2677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Have to do this specially. */
2678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* ffree %st7 ; fld %st(srcL) ;
2679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ffree %st7 ; fld %st(srcR+1) ; fpatan ; fstp(1+dst) */
2680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         p = do_ffree_st7(p);
2681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         p = do_fld_st(p, 0+hregNumber(i->Xin.FpBinary.srcL));
2682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         p = do_ffree_st7(p);
2683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         p = do_fld_st(p, 1+hregNumber(i->Xin.FpBinary.srcR));
2684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = 0xD9; *p++ = 0xF3;
2685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         p = do_fstp_st(p, 1+hregNumber(i->Xin.FpBinary.dst));
2686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto done;
2687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (i->Xin.FpBinary.op == Xfp_PREM
2689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          || i->Xin.FpBinary.op == Xfp_PREM1
2690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          || i->Xin.FpBinary.op == Xfp_SCALE) {
2691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Have to do this specially. */
2692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* ffree %st7 ; fld %st(srcR) ;
2693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ffree %st7 ; fld %st(srcL+1) ; fprem/fprem1/fscale ; fstp(2+dst) ;
2694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fincstp ; ffree %st7 */
2695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         p = do_ffree_st7(p);
2696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         p = do_fld_st(p, 0+hregNumber(i->Xin.FpBinary.srcR));
2697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         p = do_ffree_st7(p);
2698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         p = do_fld_st(p, 1+hregNumber(i->Xin.FpBinary.srcL));
2699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = 0xD9;
2700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch (i->Xin.FpBinary.op) {
2701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Xfp_PREM: *p++ = 0xF8; break;
2702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Xfp_PREM1: *p++ = 0xF5; break;
2703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Xfp_SCALE: *p++ =  0xFD; break;
2704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default: vpanic("emitX86Instr(FpBinary,PREM/PREM1/SCALE)");
2705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
2706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         p = do_fstp_st(p, 2+hregNumber(i->Xin.FpBinary.dst));
2707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = 0xD9; *p++ = 0xF7;
2708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         p = do_ffree_st7(p);
2709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto done;
2710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* General case */
2712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* gop %srcL, %srcR, %dst
2713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         --> ffree %st7 ; fld %st(srcL) ; fop %st(1+srcR) ; fstp %st(1+dst)
2714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      */
2715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      p = do_ffree_st7(p);
2716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      p = do_fld_st(p, 0+hregNumber(i->Xin.FpBinary.srcL));
2717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      p = do_fop2_st(p, i->Xin.FpBinary.op,
2718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        1+hregNumber(i->Xin.FpBinary.srcR));
2719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      p = do_fstp_st(p, 1+hregNumber(i->Xin.FpBinary.dst));
2720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto done;
2721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Xin_FpLdSt:
2723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (i->Xin.FpLdSt.isLoad) {
2724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Load from memory into %fakeN.
2725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            --> ffree %st(7) ; fld{s/l/t} amode ; fstp st(N+1)
2726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         */
2727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         p = do_ffree_st7(p);
2728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch (i->Xin.FpLdSt.sz) {
2729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 4:
2730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               *p++ = 0xD9;
2731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               p = doAMode_M(p, fake(0)/*subopcode*/, i->Xin.FpLdSt.addr);
2732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
2733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 8:
2734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               *p++ = 0xDD;
2735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               p = doAMode_M(p, fake(0)/*subopcode*/, i->Xin.FpLdSt.addr);
2736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
2737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 10:
2738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               *p++ = 0xDB;
2739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               p = doAMode_M(p, fake(5)/*subopcode*/, i->Xin.FpLdSt.addr);
2740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
2741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default:
2742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vpanic("emitX86Instr(FpLdSt,load)");
2743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
2744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         p = do_fstp_st(p, 1+hregNumber(i->Xin.FpLdSt.reg));
2745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto done;
2746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
2747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Store from %fakeN into memory.
2748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            --> ffree %st(7) ; fld st(N) ; fstp{l|s} amode
2749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 */
2750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         p = do_ffree_st7(p);
2751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         p = do_fld_st(p, 0+hregNumber(i->Xin.FpLdSt.reg));
2752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch (i->Xin.FpLdSt.sz) {
2753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 4:
2754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               *p++ = 0xD9;
2755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               p = doAMode_M(p, fake(3)/*subopcode*/, i->Xin.FpLdSt.addr);
2756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
2757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 8:
2758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               *p++ = 0xDD;
2759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               p = doAMode_M(p, fake(3)/*subopcode*/, i->Xin.FpLdSt.addr);
2760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
2761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 10:
2762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               *p++ = 0xDB;
2763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               p = doAMode_M(p, fake(7)/*subopcode*/, i->Xin.FpLdSt.addr);
2764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
2765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default:
2766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vpanic("emitX86Instr(FpLdSt,store)");
2767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
2768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto done;
2769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
2771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Xin_FpLdStI:
2773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (i->Xin.FpLdStI.isLoad) {
2774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Load from memory into %fakeN, converting from an int.
2775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            --> ffree %st(7) ; fild{w/l/ll} amode ; fstp st(N+1)
2776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         */
2777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch (i->Xin.FpLdStI.sz) {
2778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 8:  opc = 0xDF; subopc_imm = 5; break;
2779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 4:  opc = 0xDB; subopc_imm = 0; break;
2780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 2:  vassert(0); opc = 0xDF; subopc_imm = 0; break;
2781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default: vpanic("emitX86Instr(Xin_FpLdStI-load)");
2782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
2783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         p = do_ffree_st7(p);
2784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = toUChar(opc);
2785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         p = doAMode_M(p, fake(subopc_imm)/*subopcode*/, i->Xin.FpLdStI.addr);
2786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         p = do_fstp_st(p, 1+hregNumber(i->Xin.FpLdStI.reg));
2787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto done;
2788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
2789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Store from %fakeN into memory, converting to an int.
2790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            --> ffree %st(7) ; fld st(N) ; fistp{w/l/ll} amode
2791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 */
2792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch (i->Xin.FpLdStI.sz) {
2793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 8:  opc = 0xDF; subopc_imm = 7; break;
2794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 4:  opc = 0xDB; subopc_imm = 3; break;
2795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 2:  opc = 0xDF; subopc_imm = 3; break;
2796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default: vpanic("emitX86Instr(Xin_FpLdStI-store)");
2797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
2798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         p = do_ffree_st7(p);
2799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         p = do_fld_st(p, 0+hregNumber(i->Xin.FpLdStI.reg));
2800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = toUChar(opc);
2801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         p = doAMode_M(p, fake(subopc_imm)/*subopcode*/, i->Xin.FpLdStI.addr);
2802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto done;
2803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
2805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Xin_Fp64to32:
2807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ffree %st7 ; fld %st(src) */
2808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      p = do_ffree_st7(p);
2809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      p = do_fld_st(p, 0+fregNo(i->Xin.Fp64to32.src));
2810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* subl $4, %esp */
2811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = 0x83; *p++ = 0xEC; *p++ = 0x04;
2812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* fstps (%esp) */
2813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = 0xD9; *p++ = 0x1C; *p++ = 0x24;
2814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* flds (%esp) */
2815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = 0xD9; *p++ = 0x04; *p++ = 0x24;
2816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* addl $4, %esp */
2817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = 0x83; *p++ = 0xC4; *p++ = 0x04;
2818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* fstp %st(1+dst) */
2819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      p = do_fstp_st(p, 1+fregNo(i->Xin.Fp64to32.dst));
2820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto done;
2821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Xin_FpCMov:
2823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* jmp fwds if !condition */
2824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = toUChar(0x70 + (i->Xin.FpCMov.cond ^ 1));
2825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = 0; /* # of bytes in the next bit, which we don't know yet */
2826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ptmp = p;
2827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ffree %st7 ; fld %st(src) ; fstp %st(1+dst) */
2829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      p = do_ffree_st7(p);
2830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      p = do_fld_st(p, 0+fregNo(i->Xin.FpCMov.src));
2831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      p = do_fstp_st(p, 1+fregNo(i->Xin.FpCMov.dst));
2832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Fill in the jump offset. */
2834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *(ptmp-1) = toUChar(p - ptmp);
2835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto done;
2836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Xin_FpLdCW:
2838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = 0xD9;
2839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      p = doAMode_M(p, fake(5)/*subopcode*/, i->Xin.FpLdCW.addr);
2840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto done;
2841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Xin_FpStSW_AX:
2843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* note, this emits fnstsw %ax, not fstsw %ax */
2844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = 0xDF;
2845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = 0xE0;
2846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto done;
2847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Xin_FpCmp:
2849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* gcmp %fL, %fR, %dst
2850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         -> ffree %st7; fpush %fL ; fucomp %(fR+1) ;
2851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fnstsw %ax ; movl %eax, %dst
2852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      */
2853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ffree %st7 */
2854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      p = do_ffree_st7(p);
2855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* fpush %fL */
2856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      p = do_fld_st(p, 0+fregNo(i->Xin.FpCmp.srcL));
2857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* fucomp %(fR+1) */
2858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = 0xDD;
2859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = toUChar(0xE8 + (7 & (1+fregNo(i->Xin.FpCmp.srcR))));
2860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* fnstsw %ax */
2861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = 0xDF;
2862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = 0xE0;
2863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /*  movl %eax, %dst */
2864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = 0x89;
2865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      p = doAMode_R(p, hregX86_EAX(), i->Xin.FpCmp.dst);
2866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto done;
2867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Xin_SseConst: {
2869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UShort con = i->Xin.SseConst.con;
2870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      p = push_word_from_tags(p, toUShort((con >> 12) & 0xF));
2871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      p = push_word_from_tags(p, toUShort((con >> 8) & 0xF));
2872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      p = push_word_from_tags(p, toUShort((con >> 4) & 0xF));
2873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      p = push_word_from_tags(p, toUShort(con & 0xF));
2874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* movl (%esp), %xmm-dst */
2875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = 0x0F;
2876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = 0x10;
2877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = toUChar(0x04 + 8 * (7 & vregNo(i->Xin.SseConst.dst)));
2878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = 0x24;
2879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* addl $16, %esp */
2880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = 0x83;
2881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = 0xC4;
2882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = 0x10;
2883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto done;
2884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Xin_SseLdSt:
2887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = 0x0F;
2888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = toUChar(i->Xin.SseLdSt.isLoad ? 0x10 : 0x11);
2889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      p = doAMode_M(p, fake(vregNo(i->Xin.SseLdSt.reg)), i->Xin.SseLdSt.addr);
2890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto done;
2891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Xin_SseLdzLO:
2893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(i->Xin.SseLdzLO.sz == 4 || i->Xin.SseLdzLO.sz == 8);
2894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* movs[sd] amode, %xmm-dst */
2895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = toUChar(i->Xin.SseLdzLO.sz==4 ? 0xF3 : 0xF2);
2896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = 0x0F;
2897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = 0x10;
2898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      p = doAMode_M(p, fake(vregNo(i->Xin.SseLdzLO.reg)),
2899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       i->Xin.SseLdzLO.addr);
2900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto done;
2901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Xin_Sse32Fx4:
2903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      xtra = 0;
2904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = 0x0F;
2905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (i->Xin.Sse32Fx4.op) {
2906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_ADDF:   *p++ = 0x58; break;
2907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_DIVF:   *p++ = 0x5E; break;
2908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_MAXF:   *p++ = 0x5F; break;
2909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_MINF:   *p++ = 0x5D; break;
2910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_MULF:   *p++ = 0x59; break;
2911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_RCPF:   *p++ = 0x53; break;
2912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_RSQRTF: *p++ = 0x52; break;
2913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_SQRTF:  *p++ = 0x51; break;
2914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_SUBF:   *p++ = 0x5C; break;
2915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_CMPEQF: *p++ = 0xC2; xtra = 0x100; break;
2916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_CMPLTF: *p++ = 0xC2; xtra = 0x101; break;
2917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_CMPLEF: *p++ = 0xC2; xtra = 0x102; break;
2918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_CMPUNF: *p++ = 0xC2; xtra = 0x103; break;
2919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default: goto bad;
2920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      p = doAMode_R(p, fake(vregNo(i->Xin.Sse32Fx4.dst)),
2922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       fake(vregNo(i->Xin.Sse32Fx4.src)) );
2923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (xtra & 0x100)
2924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = toUChar(xtra & 0xFF);
2925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto done;
2926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Xin_Sse64Fx2:
2928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      xtra = 0;
2929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = 0x66;
2930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = 0x0F;
2931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (i->Xin.Sse64Fx2.op) {
2932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_ADDF:   *p++ = 0x58; break;
2933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_DIVF:   *p++ = 0x5E; break;
2934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_MAXF:   *p++ = 0x5F; break;
2935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_MINF:   *p++ = 0x5D; break;
2936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_MULF:   *p++ = 0x59; break;
2937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_RCPF:   *p++ = 0x53; break;
2938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_RSQRTF: *p++ = 0x52; break;
2939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_SQRTF:  *p++ = 0x51; break;
2940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_SUBF:   *p++ = 0x5C; break;
2941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_CMPEQF: *p++ = 0xC2; xtra = 0x100; break;
2942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_CMPLTF: *p++ = 0xC2; xtra = 0x101; break;
2943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_CMPLEF: *p++ = 0xC2; xtra = 0x102; break;
2944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_CMPUNF: *p++ = 0xC2; xtra = 0x103; break;
2945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default: goto bad;
2946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      p = doAMode_R(p, fake(vregNo(i->Xin.Sse64Fx2.dst)),
2948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       fake(vregNo(i->Xin.Sse64Fx2.src)) );
2949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (xtra & 0x100)
2950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = toUChar(xtra & 0xFF);
2951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto done;
2952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Xin_Sse32FLo:
2954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      xtra = 0;
2955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = 0xF3;
2956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = 0x0F;
2957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (i->Xin.Sse32FLo.op) {
2958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_ADDF:   *p++ = 0x58; break;
2959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_DIVF:   *p++ = 0x5E; break;
2960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_MAXF:   *p++ = 0x5F; break;
2961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_MINF:   *p++ = 0x5D; break;
2962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_MULF:   *p++ = 0x59; break;
2963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_RCPF:   *p++ = 0x53; break;
2964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_RSQRTF: *p++ = 0x52; break;
2965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_SQRTF:  *p++ = 0x51; break;
2966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_SUBF:   *p++ = 0x5C; break;
2967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_CMPEQF: *p++ = 0xC2; xtra = 0x100; break;
2968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_CMPLTF: *p++ = 0xC2; xtra = 0x101; break;
2969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_CMPLEF: *p++ = 0xC2; xtra = 0x102; break;
2970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_CMPUNF: *p++ = 0xC2; xtra = 0x103; break;
2971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default: goto bad;
2972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      p = doAMode_R(p, fake(vregNo(i->Xin.Sse32FLo.dst)),
2974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       fake(vregNo(i->Xin.Sse32FLo.src)) );
2975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (xtra & 0x100)
2976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = toUChar(xtra & 0xFF);
2977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto done;
2978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Xin_Sse64FLo:
2980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      xtra = 0;
2981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = 0xF2;
2982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = 0x0F;
2983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (i->Xin.Sse64FLo.op) {
2984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_ADDF:   *p++ = 0x58; break;
2985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_DIVF:   *p++ = 0x5E; break;
2986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_MAXF:   *p++ = 0x5F; break;
2987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_MINF:   *p++ = 0x5D; break;
2988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_MULF:   *p++ = 0x59; break;
2989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_RCPF:   *p++ = 0x53; break;
2990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_RSQRTF: *p++ = 0x52; break;
2991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_SQRTF:  *p++ = 0x51; break;
2992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_SUBF:   *p++ = 0x5C; break;
2993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_CMPEQF: *p++ = 0xC2; xtra = 0x100; break;
2994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_CMPLTF: *p++ = 0xC2; xtra = 0x101; break;
2995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_CMPLEF: *p++ = 0xC2; xtra = 0x102; break;
2996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_CMPUNF: *p++ = 0xC2; xtra = 0x103; break;
2997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default: goto bad;
2998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      p = doAMode_R(p, fake(vregNo(i->Xin.Sse64FLo.dst)),
3000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       fake(vregNo(i->Xin.Sse64FLo.src)) );
3001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (xtra & 0x100)
3002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = toUChar(xtra & 0xFF);
3003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto done;
3004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Xin_SseReRg:
3006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#     define XX(_n) *p++ = (_n)
3007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (i->Xin.SseReRg.op) {
3008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_MOV:     /*movups*/ XX(0x0F); XX(0x10); break;
3009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_OR:                 XX(0x0F); XX(0x56); break;
3010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_XOR:                XX(0x0F); XX(0x57); break;
3011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_AND:                XX(0x0F); XX(0x54); break;
3012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_PACKSSD:  XX(0x66); XX(0x0F); XX(0x6B); break;
3013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_PACKSSW:  XX(0x66); XX(0x0F); XX(0x63); break;
3014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_PACKUSW:  XX(0x66); XX(0x0F); XX(0x67); break;
3015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_ADD8:     XX(0x66); XX(0x0F); XX(0xFC); break;
3016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_ADD16:    XX(0x66); XX(0x0F); XX(0xFD); break;
3017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_ADD32:    XX(0x66); XX(0x0F); XX(0xFE); break;
3018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_ADD64:    XX(0x66); XX(0x0F); XX(0xD4); break;
3019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_QADD8S:   XX(0x66); XX(0x0F); XX(0xEC); break;
3020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_QADD16S:  XX(0x66); XX(0x0F); XX(0xED); break;
3021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_QADD8U:   XX(0x66); XX(0x0F); XX(0xDC); break;
3022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_QADD16U:  XX(0x66); XX(0x0F); XX(0xDD); break;
3023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_AVG8U:    XX(0x66); XX(0x0F); XX(0xE0); break;
3024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_AVG16U:   XX(0x66); XX(0x0F); XX(0xE3); break;
3025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_CMPEQ8:   XX(0x66); XX(0x0F); XX(0x74); break;
3026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_CMPEQ16:  XX(0x66); XX(0x0F); XX(0x75); break;
3027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_CMPEQ32:  XX(0x66); XX(0x0F); XX(0x76); break;
3028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_CMPGT8S:  XX(0x66); XX(0x0F); XX(0x64); break;
3029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_CMPGT16S: XX(0x66); XX(0x0F); XX(0x65); break;
3030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_CMPGT32S: XX(0x66); XX(0x0F); XX(0x66); break;
3031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_MAX16S:   XX(0x66); XX(0x0F); XX(0xEE); break;
3032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_MAX8U:    XX(0x66); XX(0x0F); XX(0xDE); break;
3033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_MIN16S:   XX(0x66); XX(0x0F); XX(0xEA); break;
3034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_MIN8U:    XX(0x66); XX(0x0F); XX(0xDA); break;
3035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_MULHI16U: XX(0x66); XX(0x0F); XX(0xE4); break;
3036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_MULHI16S: XX(0x66); XX(0x0F); XX(0xE5); break;
3037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_MUL16:    XX(0x66); XX(0x0F); XX(0xD5); break;
3038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_SHL16:    XX(0x66); XX(0x0F); XX(0xF1); break;
3039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_SHL32:    XX(0x66); XX(0x0F); XX(0xF2); break;
3040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_SHL64:    XX(0x66); XX(0x0F); XX(0xF3); break;
3041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_SAR16:    XX(0x66); XX(0x0F); XX(0xE1); break;
3042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_SAR32:    XX(0x66); XX(0x0F); XX(0xE2); break;
3043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_SHR16:    XX(0x66); XX(0x0F); XX(0xD1); break;
3044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_SHR32:    XX(0x66); XX(0x0F); XX(0xD2); break;
3045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_SHR64:    XX(0x66); XX(0x0F); XX(0xD3); break;
3046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_SUB8:     XX(0x66); XX(0x0F); XX(0xF8); break;
3047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_SUB16:    XX(0x66); XX(0x0F); XX(0xF9); break;
3048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_SUB32:    XX(0x66); XX(0x0F); XX(0xFA); break;
3049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_SUB64:    XX(0x66); XX(0x0F); XX(0xFB); break;
3050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_QSUB8S:   XX(0x66); XX(0x0F); XX(0xE8); break;
3051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_QSUB16S:  XX(0x66); XX(0x0F); XX(0xE9); break;
3052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_QSUB8U:   XX(0x66); XX(0x0F); XX(0xD8); break;
3053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_QSUB16U:  XX(0x66); XX(0x0F); XX(0xD9); break;
3054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_UNPCKHB:  XX(0x66); XX(0x0F); XX(0x68); break;
3055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_UNPCKHW:  XX(0x66); XX(0x0F); XX(0x69); break;
3056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_UNPCKHD:  XX(0x66); XX(0x0F); XX(0x6A); break;
3057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_UNPCKHQ:  XX(0x66); XX(0x0F); XX(0x6D); break;
3058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_UNPCKLB:  XX(0x66); XX(0x0F); XX(0x60); break;
3059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_UNPCKLW:  XX(0x66); XX(0x0F); XX(0x61); break;
3060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_UNPCKLD:  XX(0x66); XX(0x0F); XX(0x62); break;
3061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Xsse_UNPCKLQ:  XX(0x66); XX(0x0F); XX(0x6C); break;
3062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default: goto bad;
3063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      p = doAMode_R(p, fake(vregNo(i->Xin.SseReRg.dst)),
3065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       fake(vregNo(i->Xin.SseReRg.src)) );
3066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#     undef XX
3067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto done;
3068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Xin_SseCMov:
3070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* jmp fwds if !condition */
3071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = toUChar(0x70 + (i->Xin.SseCMov.cond ^ 1));
3072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = 0; /* # of bytes in the next bit, which we don't know yet */
3073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ptmp = p;
3074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* movaps %src, %dst */
3076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = 0x0F;
3077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = 0x28;
3078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      p = doAMode_R(p, fake(vregNo(i->Xin.SseCMov.dst)),
3079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       fake(vregNo(i->Xin.SseCMov.src)) );
3080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Fill in the jump offset. */
3082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *(ptmp-1) = toUChar(p - ptmp);
3083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto done;
3084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Xin_SseShuf:
3086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = 0x66;
3087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = 0x0F;
3088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = 0x70;
3089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      p = doAMode_R(p, fake(vregNo(i->Xin.SseShuf.dst)),
3090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       fake(vregNo(i->Xin.SseShuf.src)) );
3091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = (UChar)(i->Xin.SseShuf.order);
3092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto done;
3093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:
3095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto bad;
3096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  bad:
3099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ppX86Instr(i, mode64);
3100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vpanic("emit_X86Instr");
3101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /*NOTREACHED*/
3102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  done:
3104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(p - &buf[0] <= 32);
3105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return p - &buf[0];
3106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  undef fake
3108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
3111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- end                                     host_x86_defs.c ---*/
3112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
3113