1ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
3ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- begin                                 host_amd64_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
10663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Copyright (C) 2004-2012 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_amd64_defs.h"
43ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
44ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
45ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------- Registers. --------- */
46ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
47ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid ppHRegAMD64 ( HReg reg )
48ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
49ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int r;
50ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   static HChar* ireg64_names[16]
51ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     = { "%rax", "%rcx", "%rdx", "%rbx", "%rsp", "%rbp", "%rsi", "%rdi",
52ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         "%r8",  "%r9",  "%r10", "%r11", "%r12", "%r13", "%r14", "%r15" };
53ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Be generic for all virtual regs. */
54ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (hregIsVirtual(reg)) {
55ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ppHReg(reg);
56ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return;
57ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
58ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* But specific for real regs. */
59ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (hregClass(reg)) {
60ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case HRcInt64:
61ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         r = hregNumber(reg);
62ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(r >= 0 && r < 16);
63ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("%s", ireg64_names[r]);
64ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
65ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case HRcFlt64:
66ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         r = hregNumber(reg);
67ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(r >= 0 && r < 6);
68ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("%%fake%d", r);
69ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
70ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case HRcVec128:
71ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         r = hregNumber(reg);
72ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(r >= 0 && r < 16);
73ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("%%xmm%d", r);
74ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
75ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
76ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("ppHRegAMD64");
77ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
78ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
79ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
80ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void ppHRegAMD64_lo32 ( HReg reg )
81ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
82ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int r;
83ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   static HChar* ireg32_names[16]
84ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     = { "%eax",  "%ecx",  "%edx",  "%ebx",  "%esp",  "%ebp",  "%esi",  "%edi",
85ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         "%r8d",  "%r9d",  "%r10d", "%r11d", "%r12d", "%r13d", "%r14d", "%r15d" };
86ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Be generic for all virtual regs. */
87ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (hregIsVirtual(reg)) {
88ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ppHReg(reg);
89ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("d");
90ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return;
91ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
92ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* But specific for real regs. */
93ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (hregClass(reg)) {
94ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case HRcInt64:
95ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         r = hregNumber(reg);
96ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(r >= 0 && r < 16);
97ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("%s", ireg32_names[r]);
98ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
99ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("ppHRegAMD64_lo32: invalid regclass");
101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownHReg hregAMD64_RAX ( void ) { return mkHReg( 0, HRcInt64, False); }
105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownHReg hregAMD64_RCX ( void ) { return mkHReg( 1, HRcInt64, False); }
106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownHReg hregAMD64_RDX ( void ) { return mkHReg( 2, HRcInt64, False); }
107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownHReg hregAMD64_RBX ( void ) { return mkHReg( 3, HRcInt64, False); }
108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownHReg hregAMD64_RSP ( void ) { return mkHReg( 4, HRcInt64, False); }
109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownHReg hregAMD64_RBP ( void ) { return mkHReg( 5, HRcInt64, False); }
110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownHReg hregAMD64_RSI ( void ) { return mkHReg( 6, HRcInt64, False); }
111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownHReg hregAMD64_RDI ( void ) { return mkHReg( 7, HRcInt64, False); }
112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownHReg hregAMD64_R8  ( void ) { return mkHReg( 8, HRcInt64, False); }
113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownHReg hregAMD64_R9  ( void ) { return mkHReg( 9, HRcInt64, False); }
114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownHReg hregAMD64_R10 ( void ) { return mkHReg(10, HRcInt64, False); }
115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownHReg hregAMD64_R11 ( void ) { return mkHReg(11, HRcInt64, False); }
116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownHReg hregAMD64_R12 ( void ) { return mkHReg(12, HRcInt64, False); }
117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownHReg hregAMD64_R13 ( void ) { return mkHReg(13, HRcInt64, False); }
118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownHReg hregAMD64_R14 ( void ) { return mkHReg(14, HRcInt64, False); }
119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownHReg hregAMD64_R15 ( void ) { return mkHReg(15, HRcInt64, False); }
120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownHReg hregAMD64_XMM0  ( void ) { return mkHReg( 0, HRcVec128, False); }
122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownHReg hregAMD64_XMM1  ( void ) { return mkHReg( 1, HRcVec128, False); }
123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownHReg hregAMD64_XMM3  ( void ) { return mkHReg( 3, HRcVec128, False); }
124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownHReg hregAMD64_XMM4  ( void ) { return mkHReg( 4, HRcVec128, False); }
125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownHReg hregAMD64_XMM5  ( void ) { return mkHReg( 5, HRcVec128, False); }
126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownHReg hregAMD64_XMM6  ( void ) { return mkHReg( 6, HRcVec128, False); }
127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownHReg hregAMD64_XMM7  ( void ) { return mkHReg( 7, HRcVec128, False); }
128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownHReg hregAMD64_XMM8  ( void ) { return mkHReg( 8, HRcVec128, False); }
129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownHReg hregAMD64_XMM9  ( void ) { return mkHReg( 9, HRcVec128, False); }
130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownHReg hregAMD64_XMM10 ( void ) { return mkHReg(10, HRcVec128, False); }
131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownHReg hregAMD64_XMM11 ( void ) { return mkHReg(11, HRcVec128, False); }
132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownHReg hregAMD64_XMM12 ( void ) { return mkHReg(12, HRcVec128, False); }
133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid getAllocableRegs_AMD64 ( Int* nregs, HReg** arr )
136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if 0
138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *nregs = 6;
139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *arr = LibVEX_Alloc(*nregs * sizeof(HReg));
140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (*arr)[ 0] = hregAMD64_RSI();
141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (*arr)[ 1] = hregAMD64_RDI();
142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (*arr)[ 2] = hregAMD64_RBX();
143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (*arr)[ 3] = hregAMD64_XMM7();
145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (*arr)[ 4] = hregAMD64_XMM8();
146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (*arr)[ 5] = hregAMD64_XMM9();
147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if 1
149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *nregs = 20;
150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *arr = LibVEX_Alloc(*nregs * sizeof(HReg));
151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (*arr)[ 0] = hregAMD64_RSI();
152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (*arr)[ 1] = hregAMD64_RDI();
153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (*arr)[ 2] = hregAMD64_R8();
154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (*arr)[ 3] = hregAMD64_R9();
155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (*arr)[ 4] = hregAMD64_R12();
156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (*arr)[ 5] = hregAMD64_R13();
157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (*arr)[ 6] = hregAMD64_R14();
158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (*arr)[ 7] = hregAMD64_R15();
159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (*arr)[ 8] = hregAMD64_RBX();
160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (*arr)[ 9] = hregAMD64_XMM3();
162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (*arr)[10] = hregAMD64_XMM4();
163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (*arr)[11] = hregAMD64_XMM5();
164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (*arr)[12] = hregAMD64_XMM6();
165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (*arr)[13] = hregAMD64_XMM7();
166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (*arr)[14] = hregAMD64_XMM8();
167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (*arr)[15] = hregAMD64_XMM9();
168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (*arr)[16] = hregAMD64_XMM10();
169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (*arr)[17] = hregAMD64_XMM11();
170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (*arr)[18] = hregAMD64_XMM12();
171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (*arr)[19] = hregAMD64_R10();
172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------- Condition codes, Intel encoding. --------- */
177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownHChar* showAMD64CondCode ( AMD64CondCode cond )
179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (cond) {
181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Acc_O:      return "o";
182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Acc_NO:     return "no";
183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Acc_B:      return "b";
184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Acc_NB:     return "nb";
185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Acc_Z:      return "z";
186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Acc_NZ:     return "nz";
187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Acc_BE:     return "be";
188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Acc_NBE:    return "nbe";
189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Acc_S:      return "s";
190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Acc_NS:     return "ns";
191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Acc_P:      return "p";
192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Acc_NP:     return "np";
193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Acc_L:      return "l";
194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Acc_NL:     return "nl";
195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Acc_LE:     return "le";
196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Acc_NLE:    return "nle";
197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Acc_ALWAYS: return "ALWAYS";
198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default: vpanic("ppAMD64CondCode");
199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------- AMD64AMode: memory address expressions. --------- */
204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownAMD64AMode* AMD64AMode_IR ( UInt imm32, HReg reg ) {
206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   AMD64AMode* am = LibVEX_Alloc(sizeof(AMD64AMode));
207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   am->tag        = Aam_IR;
208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   am->Aam.IR.imm = imm32;
209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   am->Aam.IR.reg = reg;
210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return am;
211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownAMD64AMode* AMD64AMode_IRRS ( UInt imm32, HReg base, HReg indEx, Int shift ) {
213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   AMD64AMode* am = LibVEX_Alloc(sizeof(AMD64AMode));
214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   am->tag = Aam_IRRS;
215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   am->Aam.IRRS.imm   = imm32;
216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   am->Aam.IRRS.base  = base;
217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   am->Aam.IRRS.index = indEx;
218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   am->Aam.IRRS.shift = shift;
219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(shift >= 0 && shift <= 3);
220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return am;
221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid ppAMD64AMode ( AMD64AMode* am ) {
224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (am->tag) {
225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Aam_IR:
226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (am->Aam.IR.imm == 0)
227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf("(");
228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else
229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf("0x%x(", am->Aam.IR.imm);
230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppHRegAMD64(am->Aam.IR.reg);
231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf(")");
232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Aam_IRRS:
234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("0x%x(", am->Aam.IRRS.imm);
235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppHRegAMD64(am->Aam.IRRS.base);
236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf(",");
237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppHRegAMD64(am->Aam.IRRS.index);
238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf(",%d)", 1 << am->Aam.IRRS.shift);
239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("ppAMD64AMode");
242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void addRegUsage_AMD64AMode ( HRegUsage* u, AMD64AMode* am ) {
246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (am->tag) {
247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Aam_IR:
248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmRead, am->Aam.IR.reg);
249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Aam_IRRS:
251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmRead, am->Aam.IRRS.base);
252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmRead, am->Aam.IRRS.index);
253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("addRegUsage_AMD64AMode");
256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void mapRegs_AMD64AMode ( HRegRemap* m, AMD64AMode* am ) {
260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (am->tag) {
261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Aam_IR:
262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         am->Aam.IR.reg = lookupHRegRemap(m, am->Aam.IR.reg);
263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Aam_IRRS:
265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         am->Aam.IRRS.base = lookupHRegRemap(m, am->Aam.IRRS.base);
266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         am->Aam.IRRS.index = lookupHRegRemap(m, am->Aam.IRRS.index);
267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("mapRegs_AMD64AMode");
270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------- Operand, which can be reg, immediate or memory. --------- */
274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownAMD64RMI* AMD64RMI_Imm ( UInt imm32 ) {
276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   AMD64RMI* op       = LibVEX_Alloc(sizeof(AMD64RMI));
277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   op->tag            = Armi_Imm;
278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   op->Armi.Imm.imm32 = imm32;
279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return op;
280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownAMD64RMI* AMD64RMI_Reg ( HReg reg ) {
282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   AMD64RMI* op     = LibVEX_Alloc(sizeof(AMD64RMI));
283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   op->tag          = Armi_Reg;
284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   op->Armi.Reg.reg = reg;
285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return op;
286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownAMD64RMI* AMD64RMI_Mem ( AMD64AMode* am ) {
288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   AMD64RMI* op    = LibVEX_Alloc(sizeof(AMD64RMI));
289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   op->tag         = Armi_Mem;
290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   op->Armi.Mem.am = am;
291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return op;
292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
294b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic void ppAMD64RMI_wrk ( AMD64RMI* op, Bool lo32 ) {
295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (op->tag) {
296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Armi_Imm:
297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("$0x%x", op->Armi.Imm.imm32);
298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
299b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Armi_Reg:
300b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         if (lo32)
301b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            ppHRegAMD64_lo32(op->Armi.Reg.reg);
302b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         else
303b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            ppHRegAMD64(op->Armi.Reg.reg);
304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Armi_Mem:
306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppAMD64AMode(op->Armi.Mem.am);
307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     default:
309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("ppAMD64RMI");
310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
312b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovvoid ppAMD64RMI ( AMD64RMI* op ) {
313b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   ppAMD64RMI_wrk(op, False/*!lo32*/);
314b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
315b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovvoid ppAMD64RMI_lo32 ( AMD64RMI* op ) {
316b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   ppAMD64RMI_wrk(op, True/*lo32*/);
317b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* An AMD64RMI can only be used in a "read" context (what would it mean
320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   to write or modify a literal?) and so we enumerate its registers
321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   accordingly. */
322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void addRegUsage_AMD64RMI ( HRegUsage* u, AMD64RMI* op ) {
323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (op->tag) {
324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Armi_Imm:
325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Armi_Reg:
327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmRead, op->Armi.Reg.reg);
328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Armi_Mem:
330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addRegUsage_AMD64AMode(u, op->Armi.Mem.am);
331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("addRegUsage_AMD64RMI");
334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void mapRegs_AMD64RMI ( HRegRemap* m, AMD64RMI* op ) {
338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (op->tag) {
339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Armi_Imm:
340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Armi_Reg:
342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         op->Armi.Reg.reg = lookupHRegRemap(m, op->Armi.Reg.reg);
343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Armi_Mem:
345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapRegs_AMD64AMode(m, op->Armi.Mem.am);
346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("mapRegs_AMD64RMI");
349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------- Operand, which can be reg or immediate only. --------- */
354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownAMD64RI* AMD64RI_Imm ( UInt imm32 ) {
356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   AMD64RI* op       = LibVEX_Alloc(sizeof(AMD64RI));
357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   op->tag           = Ari_Imm;
358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   op->Ari.Imm.imm32 = imm32;
359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return op;
360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownAMD64RI* AMD64RI_Reg ( HReg reg ) {
362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   AMD64RI* op     = LibVEX_Alloc(sizeof(AMD64RI));
363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   op->tag         = Ari_Reg;
364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   op->Ari.Reg.reg = reg;
365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return op;
366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid ppAMD64RI ( AMD64RI* op ) {
369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (op->tag) {
370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ari_Imm:
371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("$0x%x", op->Ari.Imm.imm32);
372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ari_Reg:
374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppHRegAMD64(op->Ari.Reg.reg);
375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     default:
377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("ppAMD64RI");
378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* An AMD64RI can only be used in a "read" context (what would it mean
382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   to write or modify a literal?) and so we enumerate its registers
383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   accordingly. */
384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void addRegUsage_AMD64RI ( HRegUsage* u, AMD64RI* op ) {
385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (op->tag) {
386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ari_Imm:
387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ari_Reg:
389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmRead, op->Ari.Reg.reg);
390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("addRegUsage_AMD64RI");
393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void mapRegs_AMD64RI ( HRegRemap* m, AMD64RI* op ) {
397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (op->tag) {
398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ari_Imm:
399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ari_Reg:
401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         op->Ari.Reg.reg = lookupHRegRemap(m, op->Ari.Reg.reg);
402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("mapRegs_AMD64RI");
405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------- Operand, which can be reg or memory only. --------- */
410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownAMD64RM* AMD64RM_Reg ( HReg reg ) {
412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   AMD64RM* op       = LibVEX_Alloc(sizeof(AMD64RM));
413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   op->tag         = Arm_Reg;
414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   op->Arm.Reg.reg = reg;
415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return op;
416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownAMD64RM* AMD64RM_Mem ( AMD64AMode* am ) {
418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   AMD64RM* op    = LibVEX_Alloc(sizeof(AMD64RM));
419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   op->tag        = Arm_Mem;
420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   op->Arm.Mem.am = am;
421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return op;
422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid ppAMD64RM ( AMD64RM* op ) {
425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (op->tag) {
426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Arm_Mem:
427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppAMD64AMode(op->Arm.Mem.am);
428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Arm_Reg:
430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppHRegAMD64(op->Arm.Reg.reg);
431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     default:
433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("ppAMD64RM");
434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Because an AMD64RM can be both a source or destination operand, we
438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   have to supply a mode -- pertaining to the operand as a whole --
439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   indicating how it's being used. */
440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void addRegUsage_AMD64RM ( HRegUsage* u, AMD64RM* op, HRegMode mode ) {
441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (op->tag) {
442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Arm_Mem:
443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Memory is read, written or modified.  So we just want to
444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            know the regs read by the amode. */
445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addRegUsage_AMD64AMode(u, op->Arm.Mem.am);
446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Arm_Reg:
448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* reg is read, written or modified.  Add it in the
449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            appropriate way. */
450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, mode, op->Arm.Reg.reg);
451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     default:
453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("addRegUsage_AMD64RM");
454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void mapRegs_AMD64RM ( HRegRemap* m, AMD64RM* op )
458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (op->tag) {
460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Arm_Mem:
461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapRegs_AMD64AMode(m, op->Arm.Mem.am);
462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Arm_Reg:
464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         op->Arm.Reg.reg = lookupHRegRemap(m, op->Arm.Reg.reg);
465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     default:
467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("mapRegs_AMD64RM");
468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------- Instructions. --------- */
473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HChar* showAMD64ScalarSz ( Int sz ) {
475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (sz) {
476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 2: return "w";
477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 4: return "l";
478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 8: return "q";
479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default: vpanic("showAMD64ScalarSz");
480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownHChar* showAMD64UnaryOp ( AMD64UnaryOp op ) {
484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (op) {
485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Aun_NOT: return "not";
486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Aun_NEG: return "neg";
487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default: vpanic("showAMD64UnaryOp");
488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownHChar* showAMD64AluOp ( AMD64AluOp op ) {
492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (op) {
493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Aalu_MOV:  return "mov";
494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Aalu_CMP:  return "cmp";
495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Aalu_ADD:  return "add";
496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Aalu_SUB:  return "sub";
497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Aalu_ADC:  return "adc";
498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Aalu_SBB:  return "sbb";
499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Aalu_AND:  return "and";
500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Aalu_OR:   return "or";
501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Aalu_XOR:  return "xor";
502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Aalu_MUL:  return "imul";
503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default: vpanic("showAMD64AluOp");
504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownHChar* showAMD64ShiftOp ( AMD64ShiftOp op ) {
508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (op) {
509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ash_SHL: return "shl";
510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ash_SHR: return "shr";
511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ash_SAR: return "sar";
512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default: vpanic("showAMD64ShiftOp");
513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownHChar* showA87FpOp ( A87FpOp op ) {
517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (op) {
518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Afp_SCALE:  return "scale";
519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Afp_ATAN:   return "atan";
520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Afp_YL2X:   return "yl2x";
521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Afp_YL2XP1: return "yl2xp1";
522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Afp_PREM:   return "prem";
523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Afp_PREM1:  return "prem1";
524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Afp_SQRT:   return "sqrt";
525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Afp_SIN:    return "sin";
526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Afp_COS:    return "cos";
527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Afp_TAN:    return "tan";
528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Afp_ROUND:  return "round";
529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Afp_2XM1:   return "2xm1";
530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default: vpanic("showA87FpOp");
531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownHChar* showAMD64SseOp ( AMD64SseOp op ) {
535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (op) {
536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Asse_MOV:      return "movups";
537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Asse_ADDF:     return "add";
538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Asse_SUBF:     return "sub";
539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Asse_MULF:     return "mul";
540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Asse_DIVF:     return "div";
541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Asse_MAXF:     return "max";
542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Asse_MINF:     return "min";
543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Asse_CMPEQF:   return "cmpFeq";
544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Asse_CMPLTF:   return "cmpFlt";
545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Asse_CMPLEF:   return "cmpFle";
546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Asse_CMPUNF:   return "cmpFun";
547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Asse_RCPF:     return "rcp";
548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Asse_RSQRTF:   return "rsqrt";
549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Asse_SQRTF:    return "sqrt";
550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Asse_AND:      return "and";
551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Asse_OR:       return "or";
552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Asse_XOR:      return "xor";
553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Asse_ANDN:     return "andn";
554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Asse_ADD8:     return "paddb";
555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Asse_ADD16:    return "paddw";
556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Asse_ADD32:    return "paddd";
557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Asse_ADD64:    return "paddq";
558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Asse_QADD8U:   return "paddusb";
559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Asse_QADD16U:  return "paddusw";
560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Asse_QADD8S:   return "paddsb";
561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Asse_QADD16S:  return "paddsw";
562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Asse_SUB8:     return "psubb";
563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Asse_SUB16:    return "psubw";
564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Asse_SUB32:    return "psubd";
565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Asse_SUB64:    return "psubq";
566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Asse_QSUB8U:   return "psubusb";
567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Asse_QSUB16U:  return "psubusw";
568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Asse_QSUB8S:   return "psubsb";
569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Asse_QSUB16S:  return "psubsw";
570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Asse_MUL16:    return "pmullw";
571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Asse_MULHI16U: return "pmulhuw";
572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Asse_MULHI16S: return "pmulhw";
573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Asse_AVG8U:    return "pavgb";
574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Asse_AVG16U:   return "pavgw";
575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Asse_MAX16S:   return "pmaxw";
576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Asse_MAX8U:    return "pmaxub";
577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Asse_MIN16S:   return "pminw";
578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Asse_MIN8U:    return "pminub";
579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Asse_CMPEQ8:   return "pcmpeqb";
580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Asse_CMPEQ16:  return "pcmpeqw";
581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Asse_CMPEQ32:  return "pcmpeqd";
582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Asse_CMPGT8S:  return "pcmpgtb";
583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Asse_CMPGT16S: return "pcmpgtw";
584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Asse_CMPGT32S: return "pcmpgtd";
585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Asse_SHL16:    return "psllw";
586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Asse_SHL32:    return "pslld";
587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Asse_SHL64:    return "psllq";
588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Asse_SHR16:    return "psrlw";
589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Asse_SHR32:    return "psrld";
590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Asse_SHR64:    return "psrlq";
591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Asse_SAR16:    return "psraw";
592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Asse_SAR32:    return "psrad";
593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Asse_PACKSSD:  return "packssdw";
594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Asse_PACKSSW:  return "packsswb";
595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Asse_PACKUSW:  return "packuswb";
596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Asse_UNPCKHB:  return "punpckhb";
597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Asse_UNPCKHW:  return "punpckhw";
598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Asse_UNPCKHD:  return "punpckhd";
599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Asse_UNPCKHQ:  return "punpckhq";
600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Asse_UNPCKLB:  return "punpcklb";
601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Asse_UNPCKLW:  return "punpcklw";
602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Asse_UNPCKLD:  return "punpckld";
603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Asse_UNPCKLQ:  return "punpcklq";
604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default: vpanic("showAMD64SseOp");
605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownAMD64Instr* AMD64Instr_Imm64 ( ULong imm64, HReg dst ) {
609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   AMD64Instr* i      = LibVEX_Alloc(sizeof(AMD64Instr));
610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->tag             = Ain_Imm64;
611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Ain.Imm64.imm64 = imm64;
612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Ain.Imm64.dst   = dst;
613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return i;
614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownAMD64Instr* AMD64Instr_Alu64R ( AMD64AluOp op, AMD64RMI* src, HReg dst ) {
616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   AMD64Instr* i     = LibVEX_Alloc(sizeof(AMD64Instr));
617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->tag            = Ain_Alu64R;
618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Ain.Alu64R.op  = op;
619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Ain.Alu64R.src = src;
620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Ain.Alu64R.dst = dst;
621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return i;
622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownAMD64Instr* AMD64Instr_Alu64M ( AMD64AluOp op, AMD64RI* src, AMD64AMode* dst ) {
624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   AMD64Instr* i     = LibVEX_Alloc(sizeof(AMD64Instr));
625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->tag            = Ain_Alu64M;
626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Ain.Alu64M.op  = op;
627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Ain.Alu64M.src = src;
628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Ain.Alu64M.dst = dst;
629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(op != Aalu_MUL);
630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return i;
631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownAMD64Instr* AMD64Instr_Sh64 ( AMD64ShiftOp op, UInt src, HReg dst ) {
633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   AMD64Instr* i   = LibVEX_Alloc(sizeof(AMD64Instr));
634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->tag          = Ain_Sh64;
635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Ain.Sh64.op  = op;
636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Ain.Sh64.src = src;
637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Ain.Sh64.dst = dst;
638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return i;
639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownAMD64Instr* AMD64Instr_Test64 ( UInt imm32, HReg dst ) {
641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   AMD64Instr* i       = LibVEX_Alloc(sizeof(AMD64Instr));
642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->tag              = Ain_Test64;
643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Ain.Test64.imm32 = imm32;
644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Ain.Test64.dst   = dst;
645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return i;
646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownAMD64Instr* AMD64Instr_Unary64 ( AMD64UnaryOp op, HReg dst ) {
648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   AMD64Instr* i      = LibVEX_Alloc(sizeof(AMD64Instr));
649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->tag             = Ain_Unary64;
650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Ain.Unary64.op  = op;
651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Ain.Unary64.dst = dst;
652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return i;
653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownAMD64Instr* AMD64Instr_Lea64 ( AMD64AMode* am, HReg dst ) {
655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   AMD64Instr* i      = LibVEX_Alloc(sizeof(AMD64Instr));
656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->tag             = Ain_Lea64;
657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Ain.Lea64.am    = am;
658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Ain.Lea64.dst   = dst;
659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return i;
660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
661b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy StepanovAMD64Instr* AMD64Instr_Alu32R ( AMD64AluOp op, AMD64RMI* src, HReg dst ) {
662b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   AMD64Instr* i     = LibVEX_Alloc(sizeof(AMD64Instr));
663b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   i->tag            = Ain_Alu32R;
664b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   i->Ain.Alu32R.op  = op;
665b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   i->Ain.Alu32R.src = src;
666b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   i->Ain.Alu32R.dst = dst;
667b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   switch (op) {
668b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Aalu_ADD: case Aalu_SUB: case Aalu_CMP:
669b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Aalu_AND: case Aalu_OR:  case Aalu_XOR: break;
670b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      default: vassert(0);
671b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
672b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return i;
673b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownAMD64Instr* AMD64Instr_MulL ( Bool syned, AMD64RM* src ) {
675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   AMD64Instr* i     = LibVEX_Alloc(sizeof(AMD64Instr));
676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->tag            = Ain_MulL;
677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Ain.MulL.syned = syned;
678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Ain.MulL.src   = src;
679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return i;
680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownAMD64Instr* AMD64Instr_Div ( Bool syned, Int sz, AMD64RM* src ) {
682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   AMD64Instr* i     = LibVEX_Alloc(sizeof(AMD64Instr));
683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->tag            = Ain_Div;
684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Ain.Div.syned  = syned;
685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Ain.Div.sz     = sz;
686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Ain.Div.src    = src;
687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(sz == 4 || sz == 8);
688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return i;
689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownAMD64Instr* AMD64Instr_Push( AMD64RMI* src ) {
691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   AMD64Instr* i   = LibVEX_Alloc(sizeof(AMD64Instr));
692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->tag          = Ain_Push;
693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Ain.Push.src = src;
694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return i;
695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownAMD64Instr* AMD64Instr_Call ( AMD64CondCode cond, Addr64 target, Int regparms ) {
697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   AMD64Instr* i        = LibVEX_Alloc(sizeof(AMD64Instr));
698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->tag               = Ain_Call;
699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Ain.Call.cond     = cond;
700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Ain.Call.target   = target;
701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Ain.Call.regparms = regparms;
702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(regparms >= 0 && regparms <= 6);
703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return i;
704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
705663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
706663860b1408516d02ebfcb3a9999a134e6cfb223Ben ChengAMD64Instr* AMD64Instr_XDirect ( Addr64 dstGA, AMD64AMode* amRIP,
707663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                 AMD64CondCode cond, Bool toFastEP ) {
708663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   AMD64Instr* i           = LibVEX_Alloc(sizeof(AMD64Instr));
709663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   i->tag                  = Ain_XDirect;
710663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   i->Ain.XDirect.dstGA    = dstGA;
711663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   i->Ain.XDirect.amRIP    = amRIP;
712663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   i->Ain.XDirect.cond     = cond;
713663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   i->Ain.XDirect.toFastEP = toFastEP;
714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return i;
715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
716663860b1408516d02ebfcb3a9999a134e6cfb223Ben ChengAMD64Instr* AMD64Instr_XIndir ( HReg dstGA, AMD64AMode* amRIP,
717663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                AMD64CondCode cond ) {
718663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   AMD64Instr* i       = LibVEX_Alloc(sizeof(AMD64Instr));
719663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   i->tag              = Ain_XIndir;
720663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   i->Ain.XIndir.dstGA = dstGA;
721663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   i->Ain.XIndir.amRIP = amRIP;
722663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   i->Ain.XIndir.cond  = cond;
723663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return i;
724663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
725663860b1408516d02ebfcb3a9999a134e6cfb223Ben ChengAMD64Instr* AMD64Instr_XAssisted ( HReg dstGA, AMD64AMode* amRIP,
726663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                   AMD64CondCode cond, IRJumpKind jk ) {
727663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   AMD64Instr* i          = LibVEX_Alloc(sizeof(AMD64Instr));
728663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   i->tag                 = Ain_XAssisted;
729663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   i->Ain.XAssisted.dstGA = dstGA;
730663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   i->Ain.XAssisted.amRIP = amRIP;
731663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   i->Ain.XAssisted.cond  = cond;
732663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   i->Ain.XAssisted.jk    = jk;
733663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return i;
734663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
735663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownAMD64Instr* AMD64Instr_CMov64 ( AMD64CondCode cond, AMD64RM* src, HReg dst ) {
737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   AMD64Instr* i      = LibVEX_Alloc(sizeof(AMD64Instr));
738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->tag             = Ain_CMov64;
739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Ain.CMov64.cond = cond;
740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Ain.CMov64.src  = src;
741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Ain.CMov64.dst  = dst;
742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(cond != Acc_ALWAYS);
743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return i;
744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownAMD64Instr* AMD64Instr_MovxLQ ( Bool syned, HReg src, HReg dst ) {
746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   AMD64Instr* i       = LibVEX_Alloc(sizeof(AMD64Instr));
747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->tag              = Ain_MovxLQ;
748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Ain.MovxLQ.syned = syned;
749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Ain.MovxLQ.src   = src;
750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Ain.MovxLQ.dst   = dst;
751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return i;
752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownAMD64Instr* AMD64Instr_LoadEX ( UChar szSmall, Bool syned,
754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                AMD64AMode* src, HReg dst ) {
755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   AMD64Instr* i         = LibVEX_Alloc(sizeof(AMD64Instr));
756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->tag                = Ain_LoadEX;
757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Ain.LoadEX.szSmall = szSmall;
758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Ain.LoadEX.syned   = syned;
759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Ain.LoadEX.src     = src;
760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Ain.LoadEX.dst     = dst;
761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(szSmall == 1 || szSmall == 2 || szSmall == 4);
762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return i;
763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownAMD64Instr* AMD64Instr_Store ( UChar sz, HReg src, AMD64AMode* dst ) {
765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   AMD64Instr* i    = LibVEX_Alloc(sizeof(AMD64Instr));
766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->tag           = Ain_Store;
767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Ain.Store.sz  = sz;
768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Ain.Store.src = src;
769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Ain.Store.dst = dst;
770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(sz == 1 || sz == 2 || sz == 4);
771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return i;
772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownAMD64Instr* AMD64Instr_Set64 ( AMD64CondCode cond, HReg dst ) {
774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   AMD64Instr* i     = LibVEX_Alloc(sizeof(AMD64Instr));
775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->tag            = Ain_Set64;
776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Ain.Set64.cond = cond;
777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Ain.Set64.dst  = dst;
778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return i;
779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownAMD64Instr* AMD64Instr_Bsfr64 ( Bool isFwds, HReg src, HReg dst ) {
781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   AMD64Instr* i        = LibVEX_Alloc(sizeof(AMD64Instr));
782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->tag               = Ain_Bsfr64;
783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Ain.Bsfr64.isFwds = isFwds;
784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Ain.Bsfr64.src    = src;
785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Ain.Bsfr64.dst    = dst;
786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return i;
787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownAMD64Instr* AMD64Instr_MFence ( void ) {
789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   AMD64Instr* i = LibVEX_Alloc(sizeof(AMD64Instr));
790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->tag        = Ain_MFence;
791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return i;
792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownAMD64Instr* AMD64Instr_ACAS ( AMD64AMode* addr, UChar sz ) {
794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   AMD64Instr* i    = LibVEX_Alloc(sizeof(AMD64Instr));
795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->tag           = Ain_ACAS;
796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Ain.ACAS.addr = addr;
797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Ain.ACAS.sz   = sz;
798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(sz == 8 || sz == 4 || sz == 2 || sz == 1);
799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return i;
800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownAMD64Instr* AMD64Instr_DACAS ( AMD64AMode* addr, UChar sz ) {
802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   AMD64Instr* i     = LibVEX_Alloc(sizeof(AMD64Instr));
803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->tag            = Ain_DACAS;
804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Ain.DACAS.addr = addr;
805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Ain.DACAS.sz   = sz;
806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(sz == 8 || sz == 4);
807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return i;
808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownAMD64Instr* AMD64Instr_A87Free ( Int nregs )
811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   AMD64Instr* i        = LibVEX_Alloc(sizeof(AMD64Instr));
813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->tag               = Ain_A87Free;
814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Ain.A87Free.nregs = nregs;
815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(nregs >= 1 && nregs <= 7);
816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return i;
817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownAMD64Instr* AMD64Instr_A87PushPop ( AMD64AMode* addr, Bool isPush, UChar szB )
819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   AMD64Instr* i            = LibVEX_Alloc(sizeof(AMD64Instr));
821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->tag                   = Ain_A87PushPop;
822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Ain.A87PushPop.addr   = addr;
823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Ain.A87PushPop.isPush = isPush;
824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Ain.A87PushPop.szB    = szB;
825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(szB == 8 || szB == 4);
826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return i;
827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownAMD64Instr* AMD64Instr_A87FpOp ( A87FpOp op )
829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   AMD64Instr* i     = LibVEX_Alloc(sizeof(AMD64Instr));
831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->tag            = Ain_A87FpOp;
832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Ain.A87FpOp.op = op;
833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return i;
834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownAMD64Instr* AMD64Instr_A87LdCW ( AMD64AMode* addr )
836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   AMD64Instr* i       = LibVEX_Alloc(sizeof(AMD64Instr));
838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->tag              = Ain_A87LdCW;
839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Ain.A87LdCW.addr = addr;
840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return i;
841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownAMD64Instr* AMD64Instr_A87StSW ( AMD64AMode* addr )
843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   AMD64Instr* i       = LibVEX_Alloc(sizeof(AMD64Instr));
845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->tag              = Ain_A87StSW;
846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Ain.A87StSW.addr = addr;
847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return i;
848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownAMD64Instr* AMD64Instr_LdMXCSR ( AMD64AMode* addr ) {
850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   AMD64Instr* i         = LibVEX_Alloc(sizeof(AMD64Instr));
851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->tag                = Ain_LdMXCSR;
852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Ain.LdMXCSR.addr   = addr;
853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return i;
854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownAMD64Instr* AMD64Instr_SseUComIS ( Int sz, HReg srcL, HReg srcR, HReg dst ) {
856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   AMD64Instr* i         = LibVEX_Alloc(sizeof(AMD64Instr));
857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->tag                = Ain_SseUComIS;
858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Ain.SseUComIS.sz   = toUChar(sz);
859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Ain.SseUComIS.srcL = srcL;
860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Ain.SseUComIS.srcR = srcR;
861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Ain.SseUComIS.dst  = dst;
862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(sz == 4 || sz == 8);
863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return i;
864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownAMD64Instr* AMD64Instr_SseSI2SF ( Int szS, Int szD, HReg src, HReg dst ) {
866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   AMD64Instr* i       = LibVEX_Alloc(sizeof(AMD64Instr));
867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->tag              = Ain_SseSI2SF;
868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Ain.SseSI2SF.szS = toUChar(szS);
869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Ain.SseSI2SF.szD = toUChar(szD);
870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Ain.SseSI2SF.src = src;
871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Ain.SseSI2SF.dst = dst;
872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(szS == 4 || szS == 8);
873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(szD == 4 || szD == 8);
874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return i;
875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownAMD64Instr* AMD64Instr_SseSF2SI ( Int szS, Int szD, HReg src, HReg dst ) {
877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   AMD64Instr* i       = LibVEX_Alloc(sizeof(AMD64Instr));
878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->tag              = Ain_SseSF2SI;
879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Ain.SseSF2SI.szS = toUChar(szS);
880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Ain.SseSF2SI.szD = toUChar(szD);
881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Ain.SseSF2SI.src = src;
882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Ain.SseSF2SI.dst = dst;
883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(szS == 4 || szS == 8);
884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(szD == 4 || szD == 8);
885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return i;
886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownAMD64Instr* AMD64Instr_SseSDSS   ( Bool from64, HReg src, HReg dst )
888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   AMD64Instr* i         = LibVEX_Alloc(sizeof(AMD64Instr));
890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->tag                = Ain_SseSDSS;
891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Ain.SseSDSS.from64 = from64;
892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Ain.SseSDSS.src    = src;
893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Ain.SseSDSS.dst    = dst;
894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return i;
895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownAMD64Instr* AMD64Instr_SseLdSt ( Bool isLoad, Int sz,
897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 HReg reg, AMD64AMode* addr ) {
898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   AMD64Instr* i         = LibVEX_Alloc(sizeof(AMD64Instr));
899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->tag                = Ain_SseLdSt;
900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Ain.SseLdSt.isLoad = isLoad;
901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Ain.SseLdSt.sz     = toUChar(sz);
902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Ain.SseLdSt.reg    = reg;
903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Ain.SseLdSt.addr   = addr;
904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(sz == 4 || sz == 8 || sz == 16);
905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return i;
906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownAMD64Instr* AMD64Instr_SseLdzLO  ( Int sz, HReg reg, AMD64AMode* addr )
908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   AMD64Instr* i         = LibVEX_Alloc(sizeof(AMD64Instr));
910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->tag                = Ain_SseLdzLO;
911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Ain.SseLdzLO.sz    = sz;
912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Ain.SseLdzLO.reg   = reg;
913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Ain.SseLdzLO.addr  = addr;
914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(sz == 4 || sz == 8);
915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return i;
916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownAMD64Instr* AMD64Instr_Sse32Fx4 ( AMD64SseOp op, HReg src, HReg dst ) {
918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   AMD64Instr* i       = LibVEX_Alloc(sizeof(AMD64Instr));
919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->tag              = Ain_Sse32Fx4;
920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Ain.Sse32Fx4.op  = op;
921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Ain.Sse32Fx4.src = src;
922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Ain.Sse32Fx4.dst = dst;
923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(op != Asse_MOV);
924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return i;
925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownAMD64Instr* AMD64Instr_Sse32FLo ( AMD64SseOp op, HReg src, HReg dst ) {
927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   AMD64Instr* i       = LibVEX_Alloc(sizeof(AMD64Instr));
928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->tag              = Ain_Sse32FLo;
929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Ain.Sse32FLo.op  = op;
930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Ain.Sse32FLo.src = src;
931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Ain.Sse32FLo.dst = dst;
932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(op != Asse_MOV);
933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return i;
934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownAMD64Instr* AMD64Instr_Sse64Fx2 ( AMD64SseOp op, HReg src, HReg dst ) {
936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   AMD64Instr* i       = LibVEX_Alloc(sizeof(AMD64Instr));
937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->tag              = Ain_Sse64Fx2;
938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Ain.Sse64Fx2.op  = op;
939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Ain.Sse64Fx2.src = src;
940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Ain.Sse64Fx2.dst = dst;
941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(op != Asse_MOV);
942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return i;
943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownAMD64Instr* AMD64Instr_Sse64FLo ( AMD64SseOp op, HReg src, HReg dst ) {
945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   AMD64Instr* i       = LibVEX_Alloc(sizeof(AMD64Instr));
946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->tag              = Ain_Sse64FLo;
947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Ain.Sse64FLo.op  = op;
948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Ain.Sse64FLo.src = src;
949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Ain.Sse64FLo.dst = dst;
950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(op != Asse_MOV);
951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return i;
952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownAMD64Instr* AMD64Instr_SseReRg ( AMD64SseOp op, HReg re, HReg rg ) {
954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   AMD64Instr* i      = LibVEX_Alloc(sizeof(AMD64Instr));
955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->tag             = Ain_SseReRg;
956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Ain.SseReRg.op  = op;
957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Ain.SseReRg.src = re;
958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Ain.SseReRg.dst = rg;
959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return i;
960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownAMD64Instr* AMD64Instr_SseCMov ( AMD64CondCode cond, HReg src, HReg dst ) {
962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   AMD64Instr* i       = LibVEX_Alloc(sizeof(AMD64Instr));
963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->tag              = Ain_SseCMov;
964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Ain.SseCMov.cond = cond;
965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Ain.SseCMov.src  = src;
966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Ain.SseCMov.dst  = dst;
967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(cond != Acc_ALWAYS);
968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return i;
969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownAMD64Instr* AMD64Instr_SseShuf ( Int order, HReg src, HReg dst ) {
971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   AMD64Instr* i        = LibVEX_Alloc(sizeof(AMD64Instr));
972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->tag               = Ain_SseShuf;
973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Ain.SseShuf.order = order;
974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Ain.SseShuf.src   = src;
975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->Ain.SseShuf.dst   = dst;
976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(order >= 0 && order <= 0xFF);
977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return i;
978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
979663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu AMD64Instr* AMD64Instr_AvxLdSt ( Bool isLoad,
980663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu                                  HReg reg, AMD64AMode* addr ) {
981663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu    AMD64Instr* i         = LibVEX_Alloc(sizeof(AMD64Instr));
982663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu    i->tag                = Ain_AvxLdSt;
983663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu    i->Ain.AvxLdSt.isLoad = isLoad;
984663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu    i->Ain.AvxLdSt.reg    = reg;
985663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu    i->Ain.AvxLdSt.addr   = addr;
986663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu    return i;
987663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu }
988663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu AMD64Instr* AMD64Instr_AvxReRg ( AMD64SseOp op, HReg re, HReg rg ) {
989663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu    AMD64Instr* i      = LibVEX_Alloc(sizeof(AMD64Instr));
990663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu    i->tag             = Ain_AvxReRg;
991663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu    i->Ain.AvxReRg.op  = op;
992663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu    i->Ain.AvxReRg.src = re;
993663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu    i->Ain.AvxReRg.dst = rg;
994663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu    return i;
995663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu }
996663860b1408516d02ebfcb3a9999a134e6cfb223Ben ChengAMD64Instr* AMD64Instr_EvCheck ( AMD64AMode* amCounter,
997663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                 AMD64AMode* amFailAddr ) {
998663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   AMD64Instr* i             = LibVEX_Alloc(sizeof(AMD64Instr));
999663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   i->tag                    = Ain_EvCheck;
1000663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   i->Ain.EvCheck.amCounter  = amCounter;
1001663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   i->Ain.EvCheck.amFailAddr = amFailAddr;
1002663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return i;
1003663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
1004663860b1408516d02ebfcb3a9999a134e6cfb223Ben ChengAMD64Instr* AMD64Instr_ProfInc ( void ) {
1005663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   AMD64Instr* i = LibVEX_Alloc(sizeof(AMD64Instr));
1006663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   i->tag        = Ain_ProfInc;
1007663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return i;
1008663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
1009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid ppAMD64Instr ( AMD64Instr* i, Bool mode64 )
1011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(mode64 == True);
1013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (i->tag) {
1014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_Imm64:
1015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("movabsq $0x%llx,", i->Ain.Imm64.imm64);
1016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppHRegAMD64(i->Ain.Imm64.dst);
1017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_Alu64R:
1019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("%sq ", showAMD64AluOp(i->Ain.Alu64R.op));
1020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppAMD64RMI(i->Ain.Alu64R.src);
1021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf(",");
1022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppHRegAMD64(i->Ain.Alu64R.dst);
1023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_Alu64M:
1025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("%sq ", showAMD64AluOp(i->Ain.Alu64M.op));
1026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppAMD64RI(i->Ain.Alu64M.src);
1027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf(",");
1028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppAMD64AMode(i->Ain.Alu64M.dst);
1029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_Sh64:
1031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("%sq ", showAMD64ShiftOp(i->Ain.Sh64.op));
1032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (i->Ain.Sh64.src == 0)
1033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf("%%cl,");
1034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else
1035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf("$%d,", (Int)i->Ain.Sh64.src);
1036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppHRegAMD64(i->Ain.Sh64.dst);
1037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_Test64:
1039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("testq $%d,", (Int)i->Ain.Test64.imm32);
1040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppHRegAMD64(i->Ain.Test64.dst);
1041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_Unary64:
1043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("%sq ", showAMD64UnaryOp(i->Ain.Unary64.op));
1044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppHRegAMD64(i->Ain.Unary64.dst);
1045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_Lea64:
1047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("leaq ");
1048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppAMD64AMode(i->Ain.Lea64.am);
1049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf(",");
1050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppHRegAMD64(i->Ain.Lea64.dst);
1051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1052b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Ain_Alu32R:
1053b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         vex_printf("%sl ", showAMD64AluOp(i->Ain.Alu32R.op));
1054b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         ppAMD64RMI_lo32(i->Ain.Alu32R.src);
1055b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         vex_printf(",");
1056b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         ppHRegAMD64_lo32(i->Ain.Alu32R.dst);
1057b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return;
1058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_MulL:
1059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("%cmulq ", i->Ain.MulL.syned ? 's' : 'u');
1060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppAMD64RM(i->Ain.MulL.src);
1061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_Div:
1063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("%cdiv%s ",
1064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    i->Ain.Div.syned ? 's' : 'u',
1065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    showAMD64ScalarSz(i->Ain.Div.sz));
1066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppAMD64RM(i->Ain.Div.src);
1067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_Push:
1069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("pushq ");
1070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppAMD64RMI(i->Ain.Push.src);
1071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_Call:
1073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("call%s[%d] ",
1074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    i->Ain.Call.cond==Acc_ALWAYS
1075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       ? "" : showAMD64CondCode(i->Ain.Call.cond),
1076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    i->Ain.Call.regparms );
1077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("0x%llx", i->Ain.Call.target);
1078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
1079663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1080663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Ain_XDirect:
1081663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vex_printf("(xDirect) ");
1082663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vex_printf("if (%%rflags.%s) { ",
1083663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    showAMD64CondCode(i->Ain.XDirect.cond));
1084663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vex_printf("movabsq $0x%llx,%%r11; ", i->Ain.XDirect.dstGA);
1085663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vex_printf("movq %%r11,");
1086663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         ppAMD64AMode(i->Ain.XDirect.amRIP);
1087663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vex_printf("; ");
1088663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vex_printf("movabsq $disp_cp_chain_me_to_%sEP,%%r11; call *%%r11 }",
1089663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    i->Ain.XDirect.toFastEP ? "fast" : "slow");
1090663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return;
1091663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Ain_XIndir:
1092663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vex_printf("(xIndir) ");
1093663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vex_printf("if (%%rflags.%s) { ",
1094663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    showAMD64CondCode(i->Ain.XIndir.cond));
1095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("movq ");
1096663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         ppHRegAMD64(i->Ain.XIndir.dstGA);
1097663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vex_printf(",");
1098663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         ppAMD64AMode(i->Ain.XIndir.amRIP);
1099663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vex_printf("; movabsq $disp_indir,%%r11; jmp *%%r11 }");
1100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1101663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Ain_XAssisted:
1102663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vex_printf("(xAssisted) ");
1103663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vex_printf("if (%%rflags.%s) { ",
1104663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    showAMD64CondCode(i->Ain.XAssisted.cond));
1105663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vex_printf("movq ");
1106663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         ppHRegAMD64(i->Ain.XAssisted.dstGA);
1107663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vex_printf(",");
1108663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         ppAMD64AMode(i->Ain.XAssisted.amRIP);
1109663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vex_printf("; movl $IRJumpKind_to_TRCVAL(%d),%%rbp",
1110663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    (Int)i->Ain.XAssisted.jk);
1111663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vex_printf("; movabsq $disp_assisted,%%r11; jmp *%%r11 }");
1112663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return;
1113663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_CMov64:
1115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("cmov%s ", showAMD64CondCode(i->Ain.CMov64.cond));
1116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppAMD64RM(i->Ain.CMov64.src);
1117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf(",");
1118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppHRegAMD64(i->Ain.CMov64.dst);
1119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_MovxLQ:
1121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("mov%clq ", i->Ain.MovxLQ.syned ? 's' : 'z');
1122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppHRegAMD64_lo32(i->Ain.MovxLQ.src);
1123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf(",");
1124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppHRegAMD64(i->Ain.MovxLQ.dst);
1125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_LoadEX:
1127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (i->Ain.LoadEX.szSmall==4 && !i->Ain.LoadEX.syned) {
1128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf("movl ");
1129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ppAMD64AMode(i->Ain.LoadEX.src);
1130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf(",");
1131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ppHRegAMD64_lo32(i->Ain.LoadEX.dst);
1132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
1133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf("mov%c%cq ",
1134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       i->Ain.LoadEX.syned ? 's' : 'z',
1135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       i->Ain.LoadEX.szSmall==1
1136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          ? 'b'
1137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          : (i->Ain.LoadEX.szSmall==2 ? 'w' : 'l'));
1138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ppAMD64AMode(i->Ain.LoadEX.src);
1139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf(",");
1140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ppHRegAMD64(i->Ain.LoadEX.dst);
1141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_Store:
1144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("mov%c ", i->Ain.Store.sz==1 ? 'b'
1145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              : (i->Ain.Store.sz==2 ? 'w' : 'l'));
1146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppHRegAMD64(i->Ain.Store.src);
1147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf(",");
1148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppAMD64AMode(i->Ain.Store.dst);
1149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_Set64:
1151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("setq%s ", showAMD64CondCode(i->Ain.Set64.cond));
1152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppHRegAMD64(i->Ain.Set64.dst);
1153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_Bsfr64:
1155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("bs%cq ", i->Ain.Bsfr64.isFwds ? 'f' : 'r');
1156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppHRegAMD64(i->Ain.Bsfr64.src);
1157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf(",");
1158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppHRegAMD64(i->Ain.Bsfr64.dst);
1159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_MFence:
1161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("mfence" );
1162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_ACAS:
1164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("lock cmpxchg%c ",
1165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     i->Ain.ACAS.sz==1 ? 'b' : i->Ain.ACAS.sz==2 ? 'w'
1166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     : i->Ain.ACAS.sz==4 ? 'l' : 'q' );
1167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("{%%rax->%%rbx},");
1168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppAMD64AMode(i->Ain.ACAS.addr);
1169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_DACAS:
1171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("lock cmpxchg%db {%%rdx:%%rax->%%rcx:%%rbx},",
1172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    (Int)(2 * i->Ain.DACAS.sz));
1173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppAMD64AMode(i->Ain.DACAS.addr);
1174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_A87Free:
1176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("ffree %%st(7..%d)", 8 - i->Ain.A87Free.nregs );
1177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
1178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_A87PushPop:
1179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf(i->Ain.A87PushPop.isPush ? "fld%c " : "fstp%c ",
1180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    i->Ain.A87PushPop.szB == 4 ? 's' : 'l');
1181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppAMD64AMode(i->Ain.A87PushPop.addr);
1182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
1183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_A87FpOp:
1184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("f%s", showA87FpOp(i->Ain.A87FpOp.op));
1185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
1186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_A87LdCW:
1187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("fldcw ");
1188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppAMD64AMode(i->Ain.A87LdCW.addr);
1189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
1190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_A87StSW:
1191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("fstsw ");
1192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppAMD64AMode(i->Ain.A87StSW.addr);
1193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
1194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_LdMXCSR:
1195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("ldmxcsr ");
1196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppAMD64AMode(i->Ain.LdMXCSR.addr);
1197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
1198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_SseUComIS:
1199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("ucomis%s ", i->Ain.SseUComIS.sz==4 ? "s" : "d");
1200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppHRegAMD64(i->Ain.SseUComIS.srcL);
1201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf(",");
1202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppHRegAMD64(i->Ain.SseUComIS.srcR);
1203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf(" ; pushfq ; popq ");
1204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppHRegAMD64(i->Ain.SseUComIS.dst);
1205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
1206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_SseSI2SF:
1207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("cvtsi2s%s ", i->Ain.SseSI2SF.szD==4 ? "s" : "d");
1208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         (i->Ain.SseSI2SF.szS==4 ? ppHRegAMD64_lo32 : ppHRegAMD64)
1209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            (i->Ain.SseSI2SF.src);
1210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf(",");
1211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppHRegAMD64(i->Ain.SseSI2SF.dst);
1212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
1213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_SseSF2SI:
1214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("cvts%s2si ", i->Ain.SseSF2SI.szS==4 ? "s" : "d");
1215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppHRegAMD64(i->Ain.SseSF2SI.src);
1216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf(",");
1217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         (i->Ain.SseSF2SI.szD==4 ? ppHRegAMD64_lo32 : ppHRegAMD64)
1218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            (i->Ain.SseSF2SI.dst);
1219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
1220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_SseSDSS:
1221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf(i->Ain.SseSDSS.from64 ? "cvtsd2ss " : "cvtss2sd ");
1222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppHRegAMD64(i->Ain.SseSDSS.src);
1223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf(",");
1224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppHRegAMD64(i->Ain.SseSDSS.dst);
1225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
1226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_SseLdSt:
1227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch (i->Ain.SseLdSt.sz) {
1228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 4:  vex_printf("movss "); break;
1229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 8:  vex_printf("movsd "); break;
1230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 16: vex_printf("movups "); break;
1231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default: vassert(0);
1232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (i->Ain.SseLdSt.isLoad) {
1234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ppAMD64AMode(i->Ain.SseLdSt.addr);
1235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf(",");
1236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ppHRegAMD64(i->Ain.SseLdSt.reg);
1237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
1238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ppHRegAMD64(i->Ain.SseLdSt.reg);
1239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf(",");
1240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ppAMD64AMode(i->Ain.SseLdSt.addr);
1241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_SseLdzLO:
1244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("movs%s ", i->Ain.SseLdzLO.sz==4 ? "s" : "d");
1245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppAMD64AMode(i->Ain.SseLdzLO.addr);
1246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf(",");
1247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppHRegAMD64(i->Ain.SseLdzLO.reg);
1248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_Sse32Fx4:
1250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("%sps ", showAMD64SseOp(i->Ain.Sse32Fx4.op));
1251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppHRegAMD64(i->Ain.Sse32Fx4.src);
1252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf(",");
1253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppHRegAMD64(i->Ain.Sse32Fx4.dst);
1254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_Sse32FLo:
1256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("%sss ", showAMD64SseOp(i->Ain.Sse32FLo.op));
1257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppHRegAMD64(i->Ain.Sse32FLo.src);
1258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf(",");
1259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppHRegAMD64(i->Ain.Sse32FLo.dst);
1260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_Sse64Fx2:
1262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("%spd ", showAMD64SseOp(i->Ain.Sse64Fx2.op));
1263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppHRegAMD64(i->Ain.Sse64Fx2.src);
1264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf(",");
1265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppHRegAMD64(i->Ain.Sse64Fx2.dst);
1266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_Sse64FLo:
1268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("%ssd ", showAMD64SseOp(i->Ain.Sse64FLo.op));
1269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppHRegAMD64(i->Ain.Sse64FLo.src);
1270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf(",");
1271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppHRegAMD64(i->Ain.Sse64FLo.dst);
1272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_SseReRg:
1274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("%s ", showAMD64SseOp(i->Ain.SseReRg.op));
1275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppHRegAMD64(i->Ain.SseReRg.src);
1276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf(",");
1277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppHRegAMD64(i->Ain.SseReRg.dst);
1278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_SseCMov:
1280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("cmov%s ", showAMD64CondCode(i->Ain.SseCMov.cond));
1281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppHRegAMD64(i->Ain.SseCMov.src);
1282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf(",");
1283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppHRegAMD64(i->Ain.SseCMov.dst);
1284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_SseShuf:
1286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("pshufd $0x%x,", i->Ain.SseShuf.order);
1287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppHRegAMD64(i->Ain.SseShuf.src);
1288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf(",");
1289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppHRegAMD64(i->Ain.SseShuf.dst);
1290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1291663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      //uu case Ain_AvxLdSt:
1292663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      //uu    vex_printf("vmovups ");
1293663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      //uu    if (i->Ain.AvxLdSt.isLoad) {
1294663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      //uu       ppAMD64AMode(i->Ain.AvxLdSt.addr);
1295663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      //uu       vex_printf(",");
1296663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      //uu       ppHRegAMD64(i->Ain.AvxLdSt.reg);
1297663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      //uu    } else {
1298663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      //uu       ppHRegAMD64(i->Ain.AvxLdSt.reg);
1299663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      //uu       vex_printf(",");
1300663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      //uu       ppAMD64AMode(i->Ain.AvxLdSt.addr);
1301663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      //uu    }
1302663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      //uu    return;
1303663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      //uu case Ain_AvxReRg:
1304663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      //uu    vex_printf("v%s ", showAMD64SseOp(i->Ain.SseReRg.op));
1305663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      //uu    ppHRegAMD64(i->Ain.AvxReRg.src);
1306663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      //uu    vex_printf(",");
1307663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      //uu    ppHRegAMD64(i->Ain.AvxReRg.dst);
1308663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      //uu    return;
1309663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Ain_EvCheck:
1310663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vex_printf("(evCheck) decl ");
1311663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         ppAMD64AMode(i->Ain.EvCheck.amCounter);
1312663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vex_printf("; jns nofail; jmp *");
1313663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         ppAMD64AMode(i->Ain.EvCheck.amFailAddr);
1314663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vex_printf("; nofail:");
1315663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return;
1316663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Ain_ProfInc:
1317663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vex_printf("(profInc) movabsq $NotKnownYet, %%r11; incq (%%r11)");
1318663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return;
1319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
1320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("ppAMD64Instr");
1321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------- Helpers for register allocation. --------- */
1325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid getRegUsage_AMD64Instr ( HRegUsage* u, AMD64Instr* i, Bool mode64 )
1327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool unary;
1329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(mode64 == True);
1330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   initHRegUsage(u);
1331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (i->tag) {
1332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_Imm64:
1333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmWrite, i->Ain.Imm64.dst);
1334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_Alu64R:
1336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addRegUsage_AMD64RMI(u, i->Ain.Alu64R.src);
1337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (i->Ain.Alu64R.op == Aalu_MOV) {
1338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addHRegUse(u, HRmWrite, i->Ain.Alu64R.dst);
1339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return;
1340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (i->Ain.Alu64R.op == Aalu_CMP) {
1342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addHRegUse(u, HRmRead, i->Ain.Alu64R.dst);
1343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return;
1344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmModify, i->Ain.Alu64R.dst);
1346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_Alu64M:
1348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addRegUsage_AMD64RI(u, i->Ain.Alu64M.src);
1349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addRegUsage_AMD64AMode(u, i->Ain.Alu64M.dst);
1350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_Sh64:
1352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmModify, i->Ain.Sh64.dst);
1353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (i->Ain.Sh64.src == 0)
1354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addHRegUse(u, HRmRead, hregAMD64_RCX());
1355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_Test64:
1357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmRead, i->Ain.Test64.dst);
1358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_Unary64:
1360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmModify, i->Ain.Unary64.dst);
1361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_Lea64:
1363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addRegUsage_AMD64AMode(u, i->Ain.Lea64.am);
1364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmWrite, i->Ain.Lea64.dst);
1365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1366b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Ain_Alu32R:
1367b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         vassert(i->Ain.Alu32R.op != Aalu_MOV);
1368b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         addRegUsage_AMD64RMI(u, i->Ain.Alu32R.src);
1369b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         if (i->Ain.Alu32R.op == Aalu_CMP) {
1370b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            addHRegUse(u, HRmRead, i->Ain.Alu32R.dst);
1371b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            return;
1372b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         }
1373b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         addHRegUse(u, HRmModify, i->Ain.Alu32R.dst);
1374b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return;
1375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_MulL:
1376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addRegUsage_AMD64RM(u, i->Ain.MulL.src, HRmRead);
1377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmModify, hregAMD64_RAX());
1378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmWrite, hregAMD64_RDX());
1379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_Div:
1381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addRegUsage_AMD64RM(u, i->Ain.Div.src, HRmRead);
1382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmModify, hregAMD64_RAX());
1383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmModify, hregAMD64_RDX());
1384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_Push:
1386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addRegUsage_AMD64RMI(u, i->Ain.Push.src);
1387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmModify, hregAMD64_RSP());
1388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_Call:
1390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* This is a bit subtle. */
1391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* First off, claim it trashes all the caller-saved regs
1392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            which fall within the register allocator's jurisdiction.
1393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            These I believe to be: rax rcx rdx rsi rdi r8 r9 r10 r11
1394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            and all the xmm registers.
1395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         */
1396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmWrite, hregAMD64_RAX());
1397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmWrite, hregAMD64_RCX());
1398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmWrite, hregAMD64_RDX());
1399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmWrite, hregAMD64_RSI());
1400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmWrite, hregAMD64_RDI());
1401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmWrite, hregAMD64_R8());
1402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmWrite, hregAMD64_R9());
1403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmWrite, hregAMD64_R10());
1404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmWrite, hregAMD64_R11());
1405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmWrite, hregAMD64_XMM0());
1406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmWrite, hregAMD64_XMM1());
1407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmWrite, hregAMD64_XMM3());
1408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmWrite, hregAMD64_XMM4());
1409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmWrite, hregAMD64_XMM5());
1410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmWrite, hregAMD64_XMM6());
1411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmWrite, hregAMD64_XMM7());
1412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmWrite, hregAMD64_XMM8());
1413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmWrite, hregAMD64_XMM9());
1414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmWrite, hregAMD64_XMM10());
1415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmWrite, hregAMD64_XMM11());
1416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmWrite, hregAMD64_XMM12());
1417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Now we have to state any parameter-carrying registers
1419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            which might be read.  This depends on the regparmness. */
1420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch (i->Ain.Call.regparms) {
1421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 6: addHRegUse(u, HRmRead, hregAMD64_R9());  /*fallthru*/
1422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 5: addHRegUse(u, HRmRead, hregAMD64_R8());  /*fallthru*/
1423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 4: addHRegUse(u, HRmRead, hregAMD64_RCX()); /*fallthru*/
1424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 3: addHRegUse(u, HRmRead, hregAMD64_RDX()); /*fallthru*/
1425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 2: addHRegUse(u, HRmRead, hregAMD64_RSI()); /*fallthru*/
1426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 1: addHRegUse(u, HRmRead, hregAMD64_RDI()); break;
1427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0: break;
1428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default: vpanic("getRegUsage_AMD64Instr:Call:regparms");
1429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Finally, there is the issue that the insn trashes a
1431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            register because the literal target address has to be
1432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            loaded into a register.  Fortunately, r11 is stated in the
1433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ABI as a scratch register, and so seems a suitable victim.  */
1434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmWrite, hregAMD64_R11());
1435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Upshot of this is that the assembler really must use r11,
1436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            and no other, as a destination temporary. */
1437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1438663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* XDirect/XIndir/XAssisted are also a bit subtle.  They
1439663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         conditionally exit the block.  Hence we only need to list (1)
1440663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         the registers that they read, and (2) the registers that they
1441663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         write in the case where the block is not exited.  (2) is
1442663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         empty, hence only (1) is relevant here. */
1443663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Ain_XDirect:
1444663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* Don't bother to mention the write to %r11, since it is not
1445663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            available to the allocator. */
1446663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addRegUsage_AMD64AMode(u, i->Ain.XDirect.amRIP);
1447663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return;
1448663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Ain_XIndir:
1449663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* Ditto re %r11 */
1450663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addHRegUse(u, HRmRead, i->Ain.XIndir.dstGA);
1451663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addRegUsage_AMD64AMode(u, i->Ain.XIndir.amRIP);
1452663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return;
1453663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Ain_XAssisted:
1454663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* Ditto re %r11 and %rbp (the baseblock ptr) */
1455663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addHRegUse(u, HRmRead, i->Ain.XAssisted.dstGA);
1456663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addRegUsage_AMD64AMode(u, i->Ain.XAssisted.amRIP);
1457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_CMov64:
1459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addRegUsage_AMD64RM(u, i->Ain.CMov64.src, HRmRead);
1460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmModify, i->Ain.CMov64.dst);
1461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_MovxLQ:
1463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmRead,  i->Ain.MovxLQ.src);
1464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmWrite, i->Ain.MovxLQ.dst);
1465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_LoadEX:
1467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addRegUsage_AMD64AMode(u, i->Ain.LoadEX.src);
1468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmWrite, i->Ain.LoadEX.dst);
1469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_Store:
1471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmRead, i->Ain.Store.src);
1472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addRegUsage_AMD64AMode(u, i->Ain.Store.dst);
1473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_Set64:
1475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmWrite, i->Ain.Set64.dst);
1476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_Bsfr64:
1478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmRead, i->Ain.Bsfr64.src);
1479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmWrite, i->Ain.Bsfr64.dst);
1480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_MFence:
1482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_ACAS:
1484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addRegUsage_AMD64AMode(u, i->Ain.ACAS.addr);
1485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmRead, hregAMD64_RBX());
1486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmModify, hregAMD64_RAX());
1487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_DACAS:
1489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addRegUsage_AMD64AMode(u, i->Ain.DACAS.addr);
1490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmRead, hregAMD64_RCX());
1491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmRead, hregAMD64_RBX());
1492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmModify, hregAMD64_RDX());
1493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmModify, hregAMD64_RAX());
1494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_A87Free:
1496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_A87PushPop:
1498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addRegUsage_AMD64AMode(u, i->Ain.A87PushPop.addr);
1499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_A87FpOp:
1501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_A87LdCW:
1503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addRegUsage_AMD64AMode(u, i->Ain.A87LdCW.addr);
1504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_A87StSW:
1506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addRegUsage_AMD64AMode(u, i->Ain.A87StSW.addr);
1507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_LdMXCSR:
1509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addRegUsage_AMD64AMode(u, i->Ain.LdMXCSR.addr);
1510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_SseUComIS:
1512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmRead,  i->Ain.SseUComIS.srcL);
1513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmRead,  i->Ain.SseUComIS.srcR);
1514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmWrite, i->Ain.SseUComIS.dst);
1515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_SseSI2SF:
1517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmRead,  i->Ain.SseSI2SF.src);
1518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmWrite, i->Ain.SseSI2SF.dst);
1519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_SseSF2SI:
1521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmRead,  i->Ain.SseSF2SI.src);
1522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmWrite, i->Ain.SseSF2SI.dst);
1523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_SseSDSS:
1525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmRead,  i->Ain.SseSDSS.src);
1526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmWrite, i->Ain.SseSDSS.dst);
1527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_SseLdSt:
1529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addRegUsage_AMD64AMode(u, i->Ain.SseLdSt.addr);
1530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, i->Ain.SseLdSt.isLoad ? HRmWrite : HRmRead,
1531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       i->Ain.SseLdSt.reg);
1532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_SseLdzLO:
1534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addRegUsage_AMD64AMode(u, i->Ain.SseLdzLO.addr);
1535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmWrite, i->Ain.SseLdzLO.reg);
1536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_Sse32Fx4:
1538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(i->Ain.Sse32Fx4.op != Asse_MOV);
1539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         unary = toBool( i->Ain.Sse32Fx4.op == Asse_RCPF
1540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         || i->Ain.Sse32Fx4.op == Asse_RSQRTF
1541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         || i->Ain.Sse32Fx4.op == Asse_SQRTF );
1542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmRead, i->Ain.Sse32Fx4.src);
1543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, unary ? HRmWrite : HRmModify,
1544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       i->Ain.Sse32Fx4.dst);
1545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_Sse32FLo:
1547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(i->Ain.Sse32FLo.op != Asse_MOV);
1548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         unary = toBool( i->Ain.Sse32FLo.op == Asse_RCPF
1549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         || i->Ain.Sse32FLo.op == Asse_RSQRTF
1550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         || i->Ain.Sse32FLo.op == Asse_SQRTF );
1551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmRead, i->Ain.Sse32FLo.src);
1552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, unary ? HRmWrite : HRmModify,
1553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       i->Ain.Sse32FLo.dst);
1554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_Sse64Fx2:
1556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(i->Ain.Sse64Fx2.op != Asse_MOV);
1557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         unary = toBool( i->Ain.Sse64Fx2.op == Asse_RCPF
1558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         || i->Ain.Sse64Fx2.op == Asse_RSQRTF
1559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         || i->Ain.Sse64Fx2.op == Asse_SQRTF );
1560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmRead, i->Ain.Sse64Fx2.src);
1561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, unary ? HRmWrite : HRmModify,
1562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       i->Ain.Sse64Fx2.dst);
1563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_Sse64FLo:
1565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(i->Ain.Sse64FLo.op != Asse_MOV);
1566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         unary = toBool( i->Ain.Sse64FLo.op == Asse_RCPF
1567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         || i->Ain.Sse64FLo.op == Asse_RSQRTF
1568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         || i->Ain.Sse64FLo.op == Asse_SQRTF );
1569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmRead, i->Ain.Sse64FLo.src);
1570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, unary ? HRmWrite : HRmModify,
1571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       i->Ain.Sse64FLo.dst);
1572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_SseReRg:
1574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if ( (i->Ain.SseReRg.op == Asse_XOR
1575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               || i->Ain.SseReRg.op == Asse_CMPEQ32)
1576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              && i->Ain.SseReRg.src == i->Ain.SseReRg.dst) {
1577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* reg-alloc needs to understand 'xor r,r' and 'cmpeqd
1578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               r,r' as a write of a value to r, and independent of any
1579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               previous value in r */
1580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* (as opposed to a rite of passage :-) */
1581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addHRegUse(u, HRmWrite, i->Ain.SseReRg.dst);
1582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
1583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addHRegUse(u, HRmRead, i->Ain.SseReRg.src);
1584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addHRegUse(u, i->Ain.SseReRg.op == Asse_MOV
1585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             ? HRmWrite : HRmModify,
1586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          i->Ain.SseReRg.dst);
1587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_SseCMov:
1590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmRead,   i->Ain.SseCMov.src);
1591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmModify, i->Ain.SseCMov.dst);
1592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_SseShuf:
1594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmRead,  i->Ain.SseShuf.src);
1595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addHRegUse(u, HRmWrite, i->Ain.SseShuf.dst);
1596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1597663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      //uu case Ain_AvxLdSt:
1598663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      //uu addRegUsage_AMD64AMode(u, i->Ain.AvxLdSt.addr);
1599663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      //uu addHRegUse(u, i->Ain.AvxLdSt.isLoad ? HRmWrite : HRmRead,
1600663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      //uu               i->Ain.AvxLdSt.reg);
1601663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      //uu return;
1602663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      //uu case Ain_AvxReRg:
1603663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      //uu    if ( (i->Ain.AvxReRg.op == Asse_XOR
1604663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      //uu          || i->Ain.AvxReRg.op == Asse_CMPEQ32)
1605663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      //uu         && i->Ain.AvxReRg.src == i->Ain.AvxReRg.dst) {
1606663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      //uu       /* See comments on the case for Ain_SseReRg. */
1607663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      //uu       addHRegUse(u, HRmWrite, i->Ain.AvxReRg.dst);
1608663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      //uu    } else {
1609663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      //uu       addHRegUse(u, HRmRead, i->Ain.AvxReRg.src);
1610663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      //uu       addHRegUse(u, i->Ain.AvxReRg.op == Asse_MOV
1611663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      //uu                        ? HRmWrite : HRmModify,
1612663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      //uu                     i->Ain.AvxReRg.dst);
1613663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      //uu    }
1614663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      //uu    return;
1615663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Ain_EvCheck:
1616663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* We expect both amodes only to mention %rbp, so this is in
1617663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            fact pointless, since %rbp isn't allocatable, but anyway.. */
1618663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addRegUsage_AMD64AMode(u, i->Ain.EvCheck.amCounter);
1619663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addRegUsage_AMD64AMode(u, i->Ain.EvCheck.amFailAddr);
1620663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return;
1621663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Ain_ProfInc:
1622663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addHRegUse(u, HRmWrite, hregAMD64_R11());
1623663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return;
1624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
1625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppAMD64Instr(i, mode64);
1626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("getRegUsage_AMD64Instr");
1627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* local helper */
1631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic inline void mapReg(HRegRemap* m, HReg* r)
1632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *r = lookupHRegRemap(m, *r);
1634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid mapRegs_AMD64Instr ( HRegRemap* m, AMD64Instr* i, Bool mode64 )
1637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(mode64 == True);
1639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (i->tag) {
1640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_Imm64:
1641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapReg(m, &i->Ain.Imm64.dst);
1642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_Alu64R:
1644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapRegs_AMD64RMI(m, i->Ain.Alu64R.src);
1645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapReg(m, &i->Ain.Alu64R.dst);
1646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_Alu64M:
1648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapRegs_AMD64RI(m, i->Ain.Alu64M.src);
1649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapRegs_AMD64AMode(m, i->Ain.Alu64M.dst);
1650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_Sh64:
1652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapReg(m, &i->Ain.Sh64.dst);
1653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_Test64:
1655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapReg(m, &i->Ain.Test64.dst);
1656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_Unary64:
1658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapReg(m, &i->Ain.Unary64.dst);
1659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_Lea64:
1661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapRegs_AMD64AMode(m, i->Ain.Lea64.am);
1662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapReg(m, &i->Ain.Lea64.dst);
1663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1664b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Ain_Alu32R:
1665b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         mapRegs_AMD64RMI(m, i->Ain.Alu32R.src);
1666b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         mapReg(m, &i->Ain.Alu32R.dst);
1667b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return;
1668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_MulL:
1669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapRegs_AMD64RM(m, i->Ain.MulL.src);
1670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_Div:
1672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapRegs_AMD64RM(m, i->Ain.Div.src);
1673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_Push:
1675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapRegs_AMD64RMI(m, i->Ain.Push.src);
1676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_Call:
1678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1679663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Ain_XDirect:
1680663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         mapRegs_AMD64AMode(m, i->Ain.XDirect.amRIP);
1681663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return;
1682663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Ain_XIndir:
1683663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         mapReg(m, &i->Ain.XIndir.dstGA);
1684663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         mapRegs_AMD64AMode(m, i->Ain.XIndir.amRIP);
1685663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return;
1686663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Ain_XAssisted:
1687663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         mapReg(m, &i->Ain.XAssisted.dstGA);
1688663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         mapRegs_AMD64AMode(m, i->Ain.XAssisted.amRIP);
1689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_CMov64:
1691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapRegs_AMD64RM(m, i->Ain.CMov64.src);
1692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapReg(m, &i->Ain.CMov64.dst);
1693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_MovxLQ:
1695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapReg(m, &i->Ain.MovxLQ.src);
1696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapReg(m, &i->Ain.MovxLQ.dst);
1697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_LoadEX:
1699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapRegs_AMD64AMode(m, i->Ain.LoadEX.src);
1700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapReg(m, &i->Ain.LoadEX.dst);
1701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_Store:
1703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapReg(m, &i->Ain.Store.src);
1704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapRegs_AMD64AMode(m, i->Ain.Store.dst);
1705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_Set64:
1707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapReg(m, &i->Ain.Set64.dst);
1708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_Bsfr64:
1710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapReg(m, &i->Ain.Bsfr64.src);
1711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapReg(m, &i->Ain.Bsfr64.dst);
1712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_MFence:
1714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_ACAS:
1716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapRegs_AMD64AMode(m, i->Ain.ACAS.addr);
1717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_DACAS:
1719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapRegs_AMD64AMode(m, i->Ain.DACAS.addr);
1720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_A87Free:
1722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_A87PushPop:
1724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapRegs_AMD64AMode(m, i->Ain.A87PushPop.addr);
1725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_A87FpOp:
1727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_A87LdCW:
1729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapRegs_AMD64AMode(m, i->Ain.A87LdCW.addr);
1730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_A87StSW:
1732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapRegs_AMD64AMode(m, i->Ain.A87StSW.addr);
1733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_LdMXCSR:
1735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapRegs_AMD64AMode(m, i->Ain.LdMXCSR.addr);
1736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_SseUComIS:
1738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapReg(m, &i->Ain.SseUComIS.srcL);
1739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapReg(m, &i->Ain.SseUComIS.srcR);
1740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapReg(m, &i->Ain.SseUComIS.dst);
1741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_SseSI2SF:
1743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapReg(m, &i->Ain.SseSI2SF.src);
1744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapReg(m, &i->Ain.SseSI2SF.dst);
1745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_SseSF2SI:
1747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapReg(m, &i->Ain.SseSF2SI.src);
1748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapReg(m, &i->Ain.SseSF2SI.dst);
1749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_SseSDSS:
1751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapReg(m, &i->Ain.SseSDSS.src);
1752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapReg(m, &i->Ain.SseSDSS.dst);
1753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_SseLdSt:
1755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapReg(m, &i->Ain.SseLdSt.reg);
1756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapRegs_AMD64AMode(m, i->Ain.SseLdSt.addr);
1757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
1758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_SseLdzLO:
1759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapReg(m, &i->Ain.SseLdzLO.reg);
1760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapRegs_AMD64AMode(m, i->Ain.SseLdzLO.addr);
1761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
1762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_Sse32Fx4:
1763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapReg(m, &i->Ain.Sse32Fx4.src);
1764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapReg(m, &i->Ain.Sse32Fx4.dst);
1765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_Sse32FLo:
1767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapReg(m, &i->Ain.Sse32FLo.src);
1768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapReg(m, &i->Ain.Sse32FLo.dst);
1769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_Sse64Fx2:
1771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapReg(m, &i->Ain.Sse64Fx2.src);
1772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapReg(m, &i->Ain.Sse64Fx2.dst);
1773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_Sse64FLo:
1775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapReg(m, &i->Ain.Sse64FLo.src);
1776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapReg(m, &i->Ain.Sse64FLo.dst);
1777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_SseReRg:
1779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapReg(m, &i->Ain.SseReRg.src);
1780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapReg(m, &i->Ain.SseReRg.dst);
1781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_SseCMov:
1783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapReg(m, &i->Ain.SseCMov.src);
1784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapReg(m, &i->Ain.SseCMov.dst);
1785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ain_SseShuf:
1787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapReg(m, &i->Ain.SseShuf.src);
1788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mapReg(m, &i->Ain.SseShuf.dst);
1789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1790663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      //uu case Ain_AvxLdSt:
1791663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      //uu    mapReg(m, &i->Ain.AvxLdSt.reg);
1792663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      //uu    mapRegs_AMD64AMode(m, i->Ain.AvxLdSt.addr);
1793663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      //uu    break;
1794663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      //uu case Ain_AvxReRg:
1795663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      //uu    mapReg(m, &i->Ain.AvxReRg.src);
1796663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      //uu    mapReg(m, &i->Ain.AvxReRg.dst);
1797663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      //uu    return;
1798663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Ain_EvCheck:
1799663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* We expect both amodes only to mention %rbp, so this is in
1800663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            fact pointless, since %rbp isn't allocatable, but anyway.. */
1801663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         mapRegs_AMD64AMode(m, i->Ain.EvCheck.amCounter);
1802663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         mapRegs_AMD64AMode(m, i->Ain.EvCheck.amFailAddr);
1803663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return;
1804663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Ain_ProfInc:
1805663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* hardwires r11 -- nothing to modify. */
1806663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return;
1807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
1808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppAMD64Instr(i, mode64);
1809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("mapRegs_AMD64Instr");
1810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Figure out if i represents a reg-reg move, and if so assign the
1814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   source and destination to *src and *dst.  If in doubt say No.  Used
1815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   by the register allocator to do move coalescing.
1816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
1817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool isMove_AMD64Instr ( AMD64Instr* i, HReg* src, HReg* dst )
1818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1819663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   switch (i->tag) {
1820663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Ain_Alu64R:
1821663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* Moves between integer regs */
1822663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (i->Ain.Alu64R.op != Aalu_MOV)
1823663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            return False;
1824663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (i->Ain.Alu64R.src->tag != Armi_Reg)
1825663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            return False;
1826663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *src = i->Ain.Alu64R.src->Armi.Reg.reg;
1827663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *dst = i->Ain.Alu64R.dst;
1828663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return True;
1829663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Ain_SseReRg:
1830663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* Moves between SSE regs */
1831663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (i->Ain.SseReRg.op != Asse_MOV)
1832663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            return False;
1833663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *src = i->Ain.SseReRg.src;
1834663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *dst = i->Ain.SseReRg.dst;
1835663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return True;
1836663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      //uu case Ain_AvxReRg:
1837663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      //uu    /* Moves between AVX regs */
1838663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      //uu    if (i->Ain.AvxReRg.op != Asse_MOV)
1839663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      //uu       return False;
1840663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      //uu    *src = i->Ain.AvxReRg.src;
1841663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      //uu    *dst = i->Ain.AvxReRg.dst;
1842663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      //uu    return True;
1843663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      default:
1844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
1845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1846663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /*NOTREACHED*/
1847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Generate amd64 spill/reload instructions under the direction of the
1851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   register allocator.  Note it's critical these don't write the
1852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   condition codes. */
1853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid genSpill_AMD64 ( /*OUT*/HInstr** i1, /*OUT*/HInstr** i2,
1855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      HReg rreg, Int offsetB, Bool mode64 )
1856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   AMD64AMode* am;
1858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(offsetB >= 0);
1859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(!hregIsVirtual(rreg));
1860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(mode64 == True);
1861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *i1 = *i2 = NULL;
1862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   am = AMD64AMode_IR(offsetB, hregAMD64_RBP());
1863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (hregClass(rreg)) {
1864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case HRcInt64:
1865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *i1 = AMD64Instr_Alu64M ( Aalu_MOV, AMD64RI_Reg(rreg), am );
1866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case HRcVec128:
1868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *i1 = AMD64Instr_SseLdSt ( False/*store*/, 16, rreg, am );
1869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
1871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppHRegClass(hregClass(rreg));
1872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("genSpill_AMD64: unimplemented regclass");
1873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid genReload_AMD64 ( /*OUT*/HInstr** i1, /*OUT*/HInstr** i2,
1877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       HReg rreg, Int offsetB, Bool mode64 )
1878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   AMD64AMode* am;
1880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(offsetB >= 0);
1881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(!hregIsVirtual(rreg));
1882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(mode64 == True);
1883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *i1 = *i2 = NULL;
1884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   am = AMD64AMode_IR(offsetB, hregAMD64_RBP());
1885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (hregClass(rreg)) {
1886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case HRcInt64:
1887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *i1 = AMD64Instr_Alu64R ( Aalu_MOV, AMD64RMI_Mem(am), rreg );
1888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case HRcVec128:
1890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *i1 = AMD64Instr_SseLdSt ( True/*load*/, 16, rreg, am );
1891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
1892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
1893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppHRegClass(hregClass(rreg));
1894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("genReload_AMD64: unimplemented regclass");
1895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------- The amd64 assembler (bleh.) --------- */
1900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Produce the low three bits of an integer register number. */
1902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UChar iregBits210 ( HReg r )
1903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt n;
1905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(hregClass(r) == HRcInt64);
1906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(!hregIsVirtual(r));
1907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   n = hregNumber(r);
1908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(n <= 15);
1909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return toUChar(n & 7);
1910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Produce bit 3 of an integer register number. */
1913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UChar iregBit3 ( HReg r )
1914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt n;
1916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(hregClass(r) == HRcInt64);
1917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(!hregIsVirtual(r));
1918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   n = hregNumber(r);
1919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(n <= 15);
1920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return toUChar((n >> 3) & 1);
1921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Produce a complete 4-bit integer register number. */
1924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UChar iregBits3210 ( HReg r )
1925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt n;
1927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(hregClass(r) == HRcInt64);
1928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(!hregIsVirtual(r));
1929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   n = hregNumber(r);
1930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(n <= 15);
1931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return toUChar(n);
1932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Given an xmm (128bit V-class) register number, produce the
1935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   equivalent numbered register in 64-bit I-class.  This is a bit of
1936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   fakery which facilitates using functions that work on integer
1937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   register numbers to be used when assembling SSE instructions
1938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   too. */
1939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UInt vreg2ireg ( HReg r )
1940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt n;
1942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(hregClass(r) == HRcVec128);
1943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(!hregIsVirtual(r));
1944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   n = hregNumber(r);
1945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(n <= 15);
1946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return mkHReg(n, HRcInt64, False);
1947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1949663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu /* Ditto for ymm regs. */
1950663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu static UInt dvreg2ireg ( HReg r )
1951663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu {
1952663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu    UInt n;
1953663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu    vassert(hregClass(r) == HRcVec256);
1954663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu    vassert(!hregIsVirtual(r));
1955663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu    n = hregNumber(r);
1956663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu    vassert(n <= 15);
1957663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu    return mkHReg(n, HRcInt64, False);
1958663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu }
1959663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UChar mkModRegRM ( UChar mod, UChar reg, UChar regmem )
1961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return toUChar( ((mod & 3) << 6)
1963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   | ((reg & 7) << 3)
1964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   | (regmem & 7) );
1965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UChar mkSIB ( Int shift, Int regindex, Int regbase )
1968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return toUChar( ((shift & 3) << 6)
1970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   | ((regindex & 7) << 3)
1971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   | (regbase & 7) );
1972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UChar* emit32 ( UChar* p, UInt w32 )
1975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *p++ = toUChar((w32)       & 0x000000FF);
1977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *p++ = toUChar((w32 >>  8) & 0x000000FF);
1978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *p++ = toUChar((w32 >> 16) & 0x000000FF);
1979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *p++ = toUChar((w32 >> 24) & 0x000000FF);
1980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return p;
1981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UChar* emit64 ( UChar* p, ULong w64 )
1984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   p = emit32(p, toUInt(w64         & 0xFFFFFFFF));
1986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   p = emit32(p, toUInt((w64 >> 32) & 0xFFFFFFFF));
1987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return p;
1988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Does a sign-extend of the lowest 8 bits give
1991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the original number? */
1992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool fits8bits ( UInt w32 )
1993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int i32 = (Int)w32;
1995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return toBool(i32 == ((i32 << 24) >> 24));
1996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Can the lower 32 bits be signedly widened to produce the whole
1998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   64-bit value?  In other words, are the top 33 bits either all 0 or
1999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   all 1 ? */
2000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool fitsIn32Bits ( ULong x )
2001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Long y0 = (Long)x;
2003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Long y1 = y0;
2004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   y1 <<= 32;
2005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   y1 >>=/*s*/ 32;
2006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return toBool(x == y1);
2007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Forming mod-reg-rm bytes and scale-index-base bytes.
2011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     greg,  0(ereg)    |  ereg is not any of: RSP RBP R12 R13
2013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       =  00 greg ereg
2014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     greg,  d8(ereg)   |  ereg is neither of: RSP R12
2016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       =  01 greg ereg, d8
2017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     greg,  d32(ereg)  |  ereg is neither of: RSP R12
2019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       =  10 greg ereg, d32
2020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     greg,  d8(ereg)   |  ereg is either: RSP R12
2022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       =  01 greg 100, 0x24, d8
2023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       (lowest bit of rex distinguishes R12/RSP)
2024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     greg,  d32(ereg)  |  ereg is either: RSP R12
2026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       =  10 greg 100, 0x24, d32
2027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       (lowest bit of rex distinguishes R12/RSP)
2028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     -----------------------------------------------
2030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     greg,  d8(base,index,scale)
2032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               |  index != RSP
2033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               =  01 greg 100, scale index base, d8
2034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     greg,  d32(base,index,scale)
2036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               |  index != RSP
2037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               =  10 greg 100, scale index base, d32
2038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
2039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UChar* doAMode_M ( UChar* p, HReg greg, AMD64AMode* am )
2040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (am->tag == Aam_IR) {
2042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (am->Aam.IR.imm == 0
2043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && am->Aam.IR.reg != hregAMD64_RSP()
2044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && am->Aam.IR.reg != hregAMD64_RBP()
2045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && am->Aam.IR.reg != hregAMD64_R12()
2046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && am->Aam.IR.reg != hregAMD64_R13()
2047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ) {
2048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = mkModRegRM(0, iregBits210(greg),
2049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              iregBits210(am->Aam.IR.reg));
2050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return p;
2051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (fits8bits(am->Aam.IR.imm)
2053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && am->Aam.IR.reg != hregAMD64_RSP()
2054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && am->Aam.IR.reg != hregAMD64_R12()
2055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ) {
2056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = mkModRegRM(1, iregBits210(greg),
2057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              iregBits210(am->Aam.IR.reg));
2058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = toUChar(am->Aam.IR.imm & 0xFF);
2059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return p;
2060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (am->Aam.IR.reg != hregAMD64_RSP()
2062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && am->Aam.IR.reg != hregAMD64_R12()
2063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ) {
2064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = mkModRegRM(2, iregBits210(greg),
2065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              iregBits210(am->Aam.IR.reg));
2066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         p = emit32(p, am->Aam.IR.imm);
2067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return p;
2068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if ((am->Aam.IR.reg == hregAMD64_RSP()
2070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || am->Aam.IR.reg == hregAMD64_R12())
2071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && fits8bits(am->Aam.IR.imm)) {
2072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 	 *p++ = mkModRegRM(1, iregBits210(greg), 4);
2073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = 0x24;
2074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = toUChar(am->Aam.IR.imm & 0xFF);
2075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return p;
2076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (/* (am->Aam.IR.reg == hregAMD64_RSP()
2078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	     || wait for test case for RSP case */
2079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          am->Aam.IR.reg == hregAMD64_R12()) {
2080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 	 *p++ = mkModRegRM(2, iregBits210(greg), 4);
2081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = 0x24;
2082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         p = emit32(p, am->Aam.IR.imm);
2083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return p;
2084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ppAMD64AMode(am);
2086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vpanic("doAMode_M: can't emit amode IR");
2087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /*NOTREACHED*/
2088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (am->tag == Aam_IRRS) {
2090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (fits8bits(am->Aam.IRRS.imm)
2091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && am->Aam.IRRS.index != hregAMD64_RSP()) {
2092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = mkModRegRM(1, iregBits210(greg), 4);
2093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = mkSIB(am->Aam.IRRS.shift, am->Aam.IRRS.index,
2094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                          am->Aam.IRRS.base);
2095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = toUChar(am->Aam.IRRS.imm & 0xFF);
2096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return p;
2097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (am->Aam.IRRS.index != hregAMD64_RSP()) {
2099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = mkModRegRM(2, iregBits210(greg), 4);
2100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = mkSIB(am->Aam.IRRS.shift, am->Aam.IRRS.index,
2101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                          am->Aam.IRRS.base);
2102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         p = emit32(p, am->Aam.IRRS.imm);
2103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return p;
2104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ppAMD64AMode(am);
2106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vpanic("doAMode_M: can't emit amode IRRS");
2107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /*NOTREACHED*/
2108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vpanic("doAMode_M: unknown amode");
2110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /*NOTREACHED*/
2111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Emit a mod-reg-rm byte when the rm bit denotes a reg. */
2115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UChar* doAMode_R ( UChar* p, HReg greg, HReg ereg )
2116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *p++ = mkModRegRM(3, iregBits210(greg), iregBits210(ereg));
2118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return p;
2119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Clear the W bit on a REX byte, thereby changing the operand size
2123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   back to whatever that instruction's default operand size is. */
2124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic inline UChar clearWBit ( UChar rex )
2125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return toUChar(rex & ~(1<<3));
2127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Make up a REX byte, with W=1 (size=64), for a (greg,amode) pair. */
2131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UChar rexAMode_M ( HReg greg, AMD64AMode* am )
2132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (am->tag == Aam_IR) {
2134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UChar W = 1;  /* we want 64-bit mode */
2135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UChar R = iregBit3(greg);
2136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UChar X = 0; /* not relevant */
2137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UChar B = iregBit3(am->Aam.IR.reg);
2138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return toUChar(0x40 + ((W << 3) | (R << 2) | (X << 1) | (B << 0)));
2139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (am->tag == Aam_IRRS) {
2141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UChar W = 1;  /* we want 64-bit mode */
2142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UChar R = iregBit3(greg);
2143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UChar X = iregBit3(am->Aam.IRRS.index);
2144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UChar B = iregBit3(am->Aam.IRRS.base);
2145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return toUChar(0x40 + ((W << 3) | (R << 2) | (X << 1) | (B << 0)));
2146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(0);
2148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return 0; /*NOTREACHED*/
2149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Make up a REX byte, with W=1 (size=64), for a (greg,ereg) pair. */
2152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UChar rexAMode_R ( HReg greg, HReg ereg )
2153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar W = 1;  /* we want 64-bit mode */
2155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar R = iregBit3(greg);
2156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar X = 0; /* not relevant */
2157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar B = iregBit3(ereg);
2158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return toUChar(0x40 + ((W << 3) | (R << 2) | (X << 1) | (B << 0)));
2159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2162663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu /* May 2012: this VEX prefix stuff is currently unused, but has
2163663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu    verified correct (I reckon).  Certainly it has been known to
2164663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu    produce correct VEX prefixes during testing. */
2165663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu
2166663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu /* Assemble a 2 or 3 byte VEX prefix from parts.  rexR, rexX, rexB and
2167663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu    notVvvvv need to be not-ed before packing.  mmmmm, rexW, L and pp go
2168663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu    in verbatim.  There's no range checking on the bits. */
2169663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu static UInt packVexPrefix ( UInt rexR, UInt rexX, UInt rexB,
2170663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu                             UInt mmmmm, UInt rexW, UInt notVvvv,
2171663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu                             UInt L, UInt pp )
2172663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu {
2173663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu    UChar byte0 = 0;
2174663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu    UChar byte1 = 0;
2175663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu    UChar byte2 = 0;
2176663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu    if (rexX == 0 && rexB == 0 && mmmmm == 1 && rexW == 0) {
2177663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu       /* 2 byte encoding is possible. */
2178663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu       byte0 = 0xC5;
2179663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu       byte1 = ((rexR ^ 1) << 7) | ((notVvvv ^ 0xF) << 3)
2180663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu               | (L << 2) | pp;
2181663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu    } else {
2182663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu       /* 3 byte encoding is needed. */
2183663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu       byte0 = 0xC4;
2184663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu       byte1 = ((rexR ^ 1) << 7) | ((rexX ^ 1) << 6)
2185663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu               | ((rexB ^ 1) << 5) | mmmmm;
2186663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu       byte2 = (rexW << 7) | ((notVvvv ^ 0xF) << 3) | (L << 2) | pp;
2187663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu    }
2188663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu    return (((UInt)byte2) << 16) | (((UInt)byte1) << 8) | ((UInt)byte0);
2189663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu }
2190663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu
2191663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu /* Make up a VEX prefix for a (greg,amode) pair.  First byte in bits
2192663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu    7:0 of result, second in 15:8, third (for a 3 byte prefix) in
2193663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu    23:16.  Has m-mmmm set to indicate a prefix of 0F, pp set to
2194663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu    indicate no SIMD prefix, W=0 (ignore), L=1 (size=256), and
2195663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu    vvvv=1111 (unused 3rd reg). */
2196663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu static UInt vexAMode_M ( HReg greg, AMD64AMode* am )
2197663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu {
2198663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu    UChar L       = 1; /* size = 256 */
2199663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu    UChar pp      = 0; /* no SIMD prefix */
2200663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu    UChar mmmmm   = 1; /* 0F */
2201663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu    UChar notVvvv = 0; /* unused */
2202663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu    UChar rexW    = 0;
2203663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu    UChar rexR    = 0;
2204663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu    UChar rexX    = 0;
2205663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu    UChar rexB    = 0;
2206663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu    /* Same logic as in rexAMode_M. */
2207663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu    if (am->tag == Aam_IR) {
2208663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu       rexR = iregBit3(greg);
2209663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu       rexX = 0; /* not relevant */
2210663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu       rexB = iregBit3(am->Aam.IR.reg);
2211663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu    }
2212663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu    else if (am->tag == Aam_IRRS) {
2213663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu       rexR = iregBit3(greg);
2214663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu       rexX = iregBit3(am->Aam.IRRS.index);
2215663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu       rexB = iregBit3(am->Aam.IRRS.base);
2216663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu    } else {
2217663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu       vassert(0);
2218663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu    }
2219663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu    return packVexPrefix( rexR, rexX, rexB, mmmmm, rexW, notVvvv, L, pp );
2220663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu }
2221663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu
2222663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu static UChar* emitVexPrefix ( UChar* p, UInt vex )
2223663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu {
2224663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu    switch (vex & 0xFF) {
2225663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu       case 0xC5:
2226663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu          *p++ = 0xC5;
2227663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu          *p++ = (vex >> 8) & 0xFF;
2228663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu          vassert(0 == (vex >> 16));
2229663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu          break;
2230663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu       case 0xC4:
2231663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu          *p++ = 0xC4;
2232663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu          *p++ = (vex >> 8) & 0xFF;
2233663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu          *p++ = (vex >> 16) & 0xFF;
2234663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu          vassert(0 == (vex >> 24));
2235663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu          break;
2236663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu       default:
2237663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu          vassert(0);
2238663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu    }
2239663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu    return p;
2240663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//uu }
2241663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2242663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Emit ffree %st(N) */
2244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UChar* do_ffree_st ( UChar* p, Int n )
2245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(n >= 0 && n <= 7);
2247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *p++ = 0xDD;
2248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *p++ = toUChar(0xC0 + n);
2249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return p;
2250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Emit an instruction into buf and return the number of bytes used.
2253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Note that buf is not the insn's final place, and therefore it is
2254663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   imperative to emit position-independent code.  If the emitted
2255663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   instruction was a profiler inc, set *is_profInc to True, else
2256663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   leave it unchanged. */
2257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2258663860b1408516d02ebfcb3a9999a134e6cfb223Ben ChengInt emit_AMD64Instr ( /*MB_MOD*/Bool* is_profInc,
2259663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      UChar* buf, Int nbuf, AMD64Instr* i,
2260b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                      Bool mode64,
2261663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      void* disp_cp_chain_me_to_slowEP,
2262663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      void* disp_cp_chain_me_to_fastEP,
2263663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      void* disp_cp_xindir,
2264663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      void* disp_cp_xassisted )
2265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt /*irno,*/ opc, opc_rr, subopc_imm, opc_imma, opc_cl, opc_imm, subopc;
2267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt   xtra;
2268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt   reg;
2269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar  rex;
2270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar* p = &buf[0];
2271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar* ptmp;
2272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int    j;
2273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(nbuf >= 32);
2274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(mode64 == True);
2275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Wrap an integer as a int register, for use assembling
2277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      GrpN insns, in which the greg field is used as a sub-opcode
2278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      and does not really contain a register. */
2279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define fake(_n) mkHReg((_n), HRcInt64, False)
2280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* vex_printf("asm  "); ppAMD64Instr(i, mode64); vex_printf("\n"); */
2282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (i->tag) {
2284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Ain_Imm64:
2286b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (i->Ain.Imm64.imm64 <= 0xFFFFFULL) {
2287b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         /* Use the short form (load into 32 bit reg, + default
2288b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            widening rule) for constants under 1 million.  We could
2289b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            use this form for the range 0 to 0x7FFFFFFF inclusive, but
2290b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            limit it to a smaller range for verifiability purposes. */
2291b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         if (1 & iregBit3(i->Ain.Imm64.dst))
2292b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            *p++ = 0x41;
2293b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         *p++ = 0xB8 + iregBits210(i->Ain.Imm64.dst);
2294b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         p = emit32(p, (UInt)i->Ain.Imm64.imm64);
2295b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      } else {
2296b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         *p++ = toUChar(0x48 + (1 & iregBit3(i->Ain.Imm64.dst)));
2297b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         *p++ = toUChar(0xB8 + iregBits210(i->Ain.Imm64.dst));
2298b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         p = emit64(p, i->Ain.Imm64.imm64);
2299b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
2300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto done;
2301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Ain_Alu64R:
2303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Deal specially with MOV */
2304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (i->Ain.Alu64R.op == Aalu_MOV) {
2305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch (i->Ain.Alu64R.src->tag) {
2306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Armi_Imm:
2307b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               if (0 == (i->Ain.Alu64R.src->Armi.Imm.imm32 & ~0xFFFFF)) {
2308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  /* Actually we could use this form for constants in
2309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     the range 0 through 0x7FFFFFFF inclusive, but
2310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     limit it to a small range for verifiability
2311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     purposes. */
2312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  /* Generate "movl $imm32, 32-bit-register" and let
2313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     the default zero-extend rule cause the upper half
2314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     of the dst to be zeroed out too.  This saves 1
2315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     and sometimes 2 bytes compared to the more
2316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     obvious encoding in the 'else' branch. */
2317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  if (1 & iregBit3(i->Ain.Alu64R.dst))
2318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     *p++ = 0x41;
2319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  *p++ = 0xB8 + iregBits210(i->Ain.Alu64R.dst);
2320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  p = emit32(p, i->Ain.Alu64R.src->Armi.Imm.imm32);
2321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               } else {
2322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  *p++ = toUChar(0x48 + (1 & iregBit3(i->Ain.Alu64R.dst)));
2323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  *p++ = 0xC7;
2324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  *p++ = toUChar(0xC0 + iregBits210(i->Ain.Alu64R.dst));
2325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  p = emit32(p, i->Ain.Alu64R.src->Armi.Imm.imm32);
2326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
2327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               goto done;
2328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Armi_Reg:
2329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               *p++ = rexAMode_R( i->Ain.Alu64R.src->Armi.Reg.reg,
2330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  i->Ain.Alu64R.dst );
2331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               *p++ = 0x89;
2332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               p = doAMode_R(p, i->Ain.Alu64R.src->Armi.Reg.reg,
2333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                i->Ain.Alu64R.dst);
2334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               goto done;
2335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Armi_Mem:
2336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               *p++ = rexAMode_M(i->Ain.Alu64R.dst,
2337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 i->Ain.Alu64R.src->Armi.Mem.am);
2338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               *p++ = 0x8B;
2339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               p = doAMode_M(p, i->Ain.Alu64R.dst,
2340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                i->Ain.Alu64R.src->Armi.Mem.am);
2341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               goto done;
2342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default:
2343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               goto bad;
2344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
2345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* MUL */
2347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (i->Ain.Alu64R.op == Aalu_MUL) {
2348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch (i->Ain.Alu64R.src->tag) {
2349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Armi_Reg:
2350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               *p++ = rexAMode_R( i->Ain.Alu64R.dst,
2351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  i->Ain.Alu64R.src->Armi.Reg.reg);
2352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               *p++ = 0x0F;
2353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               *p++ = 0xAF;
2354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               p = doAMode_R(p, i->Ain.Alu64R.dst,
2355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                i->Ain.Alu64R.src->Armi.Reg.reg);
2356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               goto done;
2357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Armi_Mem:
2358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               *p++ = rexAMode_M(i->Ain.Alu64R.dst,
2359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 i->Ain.Alu64R.src->Armi.Mem.am);
2360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               *p++ = 0x0F;
2361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               *p++ = 0xAF;
2362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               p = doAMode_M(p, i->Ain.Alu64R.dst,
2363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                i->Ain.Alu64R.src->Armi.Mem.am);
2364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               goto done;
2365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Armi_Imm:
2366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (fits8bits(i->Ain.Alu64R.src->Armi.Imm.imm32)) {
2367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  *p++ = rexAMode_R(i->Ain.Alu64R.dst, i->Ain.Alu64R.dst);
2368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  *p++ = 0x6B;
2369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  p = doAMode_R(p, i->Ain.Alu64R.dst, i->Ain.Alu64R.dst);
2370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  *p++ = toUChar(0xFF & i->Ain.Alu64R.src->Armi.Imm.imm32);
2371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               } else {
2372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  *p++ = rexAMode_R(i->Ain.Alu64R.dst, i->Ain.Alu64R.dst);
2373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  *p++ = 0x69;
2374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  p = doAMode_R(p, i->Ain.Alu64R.dst, i->Ain.Alu64R.dst);
2375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  p = emit32(p, i->Ain.Alu64R.src->Armi.Imm.imm32);
2376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
2377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               goto done;
2378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default:
2379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               goto bad;
2380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
2381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ADD/SUB/ADC/SBB/AND/OR/XOR/CMP */
2383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      opc = opc_rr = subopc_imm = opc_imma = 0;
2384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (i->Ain.Alu64R.op) {
2385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Aalu_ADC: opc = 0x13; opc_rr = 0x11;
2386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        subopc_imm = 2; opc_imma = 0x15; break;
2387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Aalu_ADD: opc = 0x03; opc_rr = 0x01;
2388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        subopc_imm = 0; opc_imma = 0x05; break;
2389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Aalu_SUB: opc = 0x2B; opc_rr = 0x29;
2390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        subopc_imm = 5; opc_imma = 0x2D; break;
2391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Aalu_SBB: opc = 0x1B; opc_rr = 0x19;
2392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        subopc_imm = 3; opc_imma = 0x1D; break;
2393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Aalu_AND: opc = 0x23; opc_rr = 0x21;
2394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        subopc_imm = 4; opc_imma = 0x25; break;
2395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Aalu_XOR: opc = 0x33; opc_rr = 0x31;
2396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        subopc_imm = 6; opc_imma = 0x35; break;
2397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Aalu_OR:  opc = 0x0B; opc_rr = 0x09;
2398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        subopc_imm = 1; opc_imma = 0x0D; break;
2399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Aalu_CMP: opc = 0x3B; opc_rr = 0x39;
2400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        subopc_imm = 7; opc_imma = 0x3D; break;
2401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default: goto bad;
2402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (i->Ain.Alu64R.src->tag) {
2404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Armi_Imm:
2405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (i->Ain.Alu64R.dst == hregAMD64_RAX()
2406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                && !fits8bits(i->Ain.Alu64R.src->Armi.Imm.imm32)) {
2407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               goto bad; /* FIXME: awaiting test case */
2408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               *p++ = toUChar(opc_imma);
2409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               p = emit32(p, i->Ain.Alu64R.src->Armi.Imm.imm32);
2410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else
2411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (fits8bits(i->Ain.Alu64R.src->Armi.Imm.imm32)) {
2412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               *p++ = rexAMode_R( fake(0), i->Ain.Alu64R.dst );
2413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               *p++ = 0x83;
2414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               p    = doAMode_R(p, fake(subopc_imm), i->Ain.Alu64R.dst);
2415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               *p++ = toUChar(0xFF & i->Ain.Alu64R.src->Armi.Imm.imm32);
2416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
2417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               *p++ = rexAMode_R( fake(0), i->Ain.Alu64R.dst);
2418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               *p++ = 0x81;
2419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               p    = doAMode_R(p, fake(subopc_imm), i->Ain.Alu64R.dst);
2420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               p    = emit32(p, i->Ain.Alu64R.src->Armi.Imm.imm32);
2421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
2422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto done;
2423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Armi_Reg:
2424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *p++ = rexAMode_R( i->Ain.Alu64R.src->Armi.Reg.reg,
2425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               i->Ain.Alu64R.dst);
2426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *p++ = toUChar(opc_rr);
2427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            p = doAMode_R(p, i->Ain.Alu64R.src->Armi.Reg.reg,
2428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             i->Ain.Alu64R.dst);
2429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto done;
2430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Armi_Mem:
2431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *p++ = rexAMode_M( i->Ain.Alu64R.dst,
2432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               i->Ain.Alu64R.src->Armi.Mem.am);
2433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *p++ = toUChar(opc);
2434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            p = doAMode_M(p, i->Ain.Alu64R.dst,
2435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             i->Ain.Alu64R.src->Armi.Mem.am);
2436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto done;
2437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:
2438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto bad;
2439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
2441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Ain_Alu64M:
2443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Deal specially with MOV */
2444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (i->Ain.Alu64M.op == Aalu_MOV) {
2445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch (i->Ain.Alu64M.src->tag) {
2446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Ari_Reg:
2447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               *p++ = rexAMode_M(i->Ain.Alu64M.src->Ari.Reg.reg,
2448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 i->Ain.Alu64M.dst);
2449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               *p++ = 0x89;
2450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               p = doAMode_M(p, i->Ain.Alu64M.src->Ari.Reg.reg,
2451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                i->Ain.Alu64M.dst);
2452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               goto done;
2453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Ari_Imm:
2454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               *p++ = rexAMode_M(fake(0), i->Ain.Alu64M.dst);
2455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               *p++ = 0xC7;
2456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               p = doAMode_M(p, fake(0), i->Ain.Alu64M.dst);
2457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               p = emit32(p, i->Ain.Alu64M.src->Ari.Imm.imm32);
2458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               goto done;
2459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default:
2460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               goto bad;
2461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
2462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
2464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Ain_Sh64:
2466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      opc_cl = opc_imm = subopc = 0;
2467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (i->Ain.Sh64.op) {
2468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ash_SHR: opc_cl = 0xD3; opc_imm = 0xC1; subopc = 5; break;
2469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ash_SAR: opc_cl = 0xD3; opc_imm = 0xC1; subopc = 7; break;
2470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ash_SHL: opc_cl = 0xD3; opc_imm = 0xC1; subopc = 4; break;
2471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default: goto bad;
2472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (i->Ain.Sh64.src == 0) {
2474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = rexAMode_R(fake(0), i->Ain.Sh64.dst);
2475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = toUChar(opc_cl);
2476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         p = doAMode_R(p, fake(subopc), i->Ain.Sh64.dst);
2477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto done;
2478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
2479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = rexAMode_R(fake(0), i->Ain.Sh64.dst);
2480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = toUChar(opc_imm);
2481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         p = doAMode_R(p, fake(subopc), i->Ain.Sh64.dst);
2482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = (UChar)(i->Ain.Sh64.src);
2483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto done;
2484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
2486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Ain_Test64:
2488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* testq sign-extend($imm32), %reg */
2489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = rexAMode_R(fake(0), i->Ain.Test64.dst);
2490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = 0xF7;
2491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      p = doAMode_R(p, fake(0), i->Ain.Test64.dst);
2492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      p = emit32(p, i->Ain.Test64.imm32);
2493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto done;
2494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Ain_Unary64:
2496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (i->Ain.Unary64.op == Aun_NOT) {
2497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = rexAMode_R(fake(0), i->Ain.Unary64.dst);
2498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = 0xF7;
2499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         p = doAMode_R(p, fake(2), i->Ain.Unary64.dst);
2500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto done;
2501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (i->Ain.Unary64.op == Aun_NEG) {
2503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = rexAMode_R(fake(0), i->Ain.Unary64.dst);
2504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = 0xF7;
2505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         p = doAMode_R(p, fake(3), i->Ain.Unary64.dst);
2506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto done;
2507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
2509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Ain_Lea64:
2511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = rexAMode_M(i->Ain.Lea64.dst, i->Ain.Lea64.am);
2512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = 0x8D;
2513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      p = doAMode_M(p, i->Ain.Lea64.dst, i->Ain.Lea64.am);
2514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto done;
2515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2516b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case Ain_Alu32R:
2517b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* ADD/SUB/AND/OR/XOR/CMP */
2518b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      opc = opc_rr = subopc_imm = opc_imma = 0;
2519b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      switch (i->Ain.Alu32R.op) {
2520b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case Aalu_ADD: opc = 0x03; opc_rr = 0x01;
2521b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                        subopc_imm = 0; opc_imma = 0x05; break;
2522b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case Aalu_SUB: opc = 0x2B; opc_rr = 0x29;
2523b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                        subopc_imm = 5; opc_imma = 0x2D; break;
2524b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case Aalu_AND: opc = 0x23; opc_rr = 0x21;
2525b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                        subopc_imm = 4; opc_imma = 0x25; break;
2526b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case Aalu_XOR: opc = 0x33; opc_rr = 0x31;
2527b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                        subopc_imm = 6; opc_imma = 0x35; break;
2528b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case Aalu_OR:  opc = 0x0B; opc_rr = 0x09;
2529b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                        subopc_imm = 1; opc_imma = 0x0D; break;
2530b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case Aalu_CMP: opc = 0x3B; opc_rr = 0x39;
2531b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                        subopc_imm = 7; opc_imma = 0x3D; break;
2532b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         default: goto bad;
2533b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
2534b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      switch (i->Ain.Alu32R.src->tag) {
2535b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case Armi_Imm:
2536b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            if (i->Ain.Alu32R.dst == hregAMD64_RAX()
2537b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                && !fits8bits(i->Ain.Alu32R.src->Armi.Imm.imm32)) {
2538b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               goto bad; /* FIXME: awaiting test case */
2539b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               *p++ = toUChar(opc_imma);
2540b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               p = emit32(p, i->Ain.Alu32R.src->Armi.Imm.imm32);
2541b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            } else
2542b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            if (fits8bits(i->Ain.Alu32R.src->Armi.Imm.imm32)) {
2543b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               rex  = clearWBit( rexAMode_R( fake(0), i->Ain.Alu32R.dst ) );
2544b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               if (rex != 0x40) *p++ = rex;
2545b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               *p++ = 0x83;
2546b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               p    = doAMode_R(p, fake(subopc_imm), i->Ain.Alu32R.dst);
2547b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               *p++ = toUChar(0xFF & i->Ain.Alu32R.src->Armi.Imm.imm32);
2548b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            } else {
2549b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               rex  = clearWBit( rexAMode_R( fake(0), i->Ain.Alu32R.dst) );
2550b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               if (rex != 0x40) *p++ = rex;
2551b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               *p++ = 0x81;
2552b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               p    = doAMode_R(p, fake(subopc_imm), i->Ain.Alu32R.dst);
2553b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               p    = emit32(p, i->Ain.Alu32R.src->Armi.Imm.imm32);
2554b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            }
2555b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            goto done;
2556b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case Armi_Reg:
2557b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            rex  = clearWBit(
2558b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                   rexAMode_R( i->Ain.Alu32R.src->Armi.Reg.reg,
2559b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                               i->Ain.Alu32R.dst) );
2560b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            if (rex != 0x40) *p++ = rex;
2561b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            *p++ = toUChar(opc_rr);
2562b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            p = doAMode_R(p, i->Ain.Alu32R.src->Armi.Reg.reg,
2563b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                             i->Ain.Alu32R.dst);
2564b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            goto done;
2565b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case Armi_Mem:
2566b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            rex  = clearWBit(
2567b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                   rexAMode_M( i->Ain.Alu32R.dst,
2568b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                               i->Ain.Alu32R.src->Armi.Mem.am) );
2569b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            if (rex != 0x40) *p++ = rex;
2570b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            *p++ = toUChar(opc);
2571b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            p = doAMode_M(p, i->Ain.Alu32R.dst,
2572b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                             i->Ain.Alu32R.src->Armi.Mem.am);
2573b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            goto done;
2574b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         default:
2575b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            goto bad;
2576b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
2577b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      break;
2578b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
2579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Ain_MulL:
2580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      subopc = i->Ain.MulL.syned ? 5 : 4;
2581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (i->Ain.MulL.src->tag)  {
2582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Arm_Mem:
2583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *p++ = rexAMode_M( fake(0),
2584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               i->Ain.MulL.src->Arm.Mem.am);
2585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *p++ = 0xF7;
2586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            p = doAMode_M(p, fake(subopc),
2587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             i->Ain.MulL.src->Arm.Mem.am);
2588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto done;
2589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Arm_Reg:
2590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *p++ = rexAMode_R(fake(0),
2591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              i->Ain.MulL.src->Arm.Reg.reg);
2592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *p++ = 0xF7;
2593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            p = doAMode_R(p, fake(subopc),
2594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             i->Ain.MulL.src->Arm.Reg.reg);
2595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto done;
2596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:
2597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto bad;
2598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
2600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Ain_Div:
2602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      subopc = i->Ain.Div.syned ? 7 : 6;
2603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (i->Ain.Div.sz == 4) {
2604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch (i->Ain.Div.src->tag)  {
2605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Arm_Mem:
2606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               goto bad;
2607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /*FIXME*/
2608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               *p++ = 0xF7;
2609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               p = doAMode_M(p, fake(subopc),
2610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                i->Ain.Div.src->Arm.Mem.am);
2611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               goto done;
2612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Arm_Reg:
2613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               *p++ = clearWBit(
2614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      rexAMode_R( fake(0), i->Ain.Div.src->Arm.Reg.reg));
2615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               *p++ = 0xF7;
2616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               p = doAMode_R(p, fake(subopc),
2617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                i->Ain.Div.src->Arm.Reg.reg);
2618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               goto done;
2619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default:
2620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               goto bad;
2621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
2622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (i->Ain.Div.sz == 8) {
2624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch (i->Ain.Div.src->tag)  {
2625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Arm_Mem:
2626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               *p++ = rexAMode_M( fake(0),
2627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  i->Ain.Div.src->Arm.Mem.am);
2628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               *p++ = 0xF7;
2629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               p = doAMode_M(p, fake(subopc),
2630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                i->Ain.Div.src->Arm.Mem.am);
2631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               goto done;
2632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Arm_Reg:
2633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               *p++ = rexAMode_R( fake(0),
2634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  i->Ain.Div.src->Arm.Reg.reg);
2635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               *p++ = 0xF7;
2636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               p = doAMode_R(p, fake(subopc),
2637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                i->Ain.Div.src->Arm.Reg.reg);
2638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               goto done;
2639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default:
2640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               goto bad;
2641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
2642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
2644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Ain_Push:
2646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (i->Ain.Push.src->tag) {
2647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Armi_Mem:
2648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *p++ = clearWBit(
2649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   rexAMode_M(fake(0), i->Ain.Push.src->Armi.Mem.am));
2650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *p++ = 0xFF;
2651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            p = doAMode_M(p, fake(6), i->Ain.Push.src->Armi.Mem.am);
2652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto done;
2653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Armi_Imm:
2654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *p++ = 0x68;
2655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            p = emit32(p, i->Ain.Push.src->Armi.Imm.imm32);
2656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto done;
2657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Armi_Reg:
2658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *p++ = toUChar(0x40 + (1 & iregBit3(i->Ain.Push.src->Armi.Reg.reg)));
2659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *p++ = toUChar(0x50 + iregBits210(i->Ain.Push.src->Armi.Reg.reg));
2660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto done;
2661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        default:
2662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto bad;
2663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Ain_Call: {
2666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* As per detailed comment for Ain_Call in
2667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         getRegUsage_AMD64Instr above, %r11 is used as an address
2668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         temporary. */
2669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* jump over the following two insns if the condition does not
2670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         hold */
2671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Bool shortImm = fitsIn32Bits(i->Ain.Call.target);
2672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (i->Ain.Call.cond != Acc_ALWAYS) {
2673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = toUChar(0x70 + (0xF & (i->Ain.Call.cond ^ 1)));
2674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = shortImm ? 10 : 13;
2675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* 10 or 13 bytes in the next two insns */
2676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (shortImm) {
2678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* 7 bytes: movl sign-extend(imm32), %r11 */
2679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = 0x49;
2680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = 0xC7;
2681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = 0xC3;
2682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         p = emit32(p, (UInt)i->Ain.Call.target);
2683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
2684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* 10 bytes: movabsq $target, %r11 */
2685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = 0x49;
2686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = 0xBB;
2687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         p = emit64(p, i->Ain.Call.target);
2688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* 3 bytes: call *%r11 */
2690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = 0x41;
2691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = 0xFF;
2692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = 0xD3;
2693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto done;
2694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2696663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case Ain_XDirect: {
2697663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* NB: what goes on here has to be very closely coordinated with the
2698663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         chainXDirect_AMD64 and unchainXDirect_AMD64 below. */
2699663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* We're generating chain-me requests here, so we need to be
2700663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         sure this is actually allowed -- no-redir translations can't
2701663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         use chain-me's.  Hence: */
2702663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      vassert(disp_cp_chain_me_to_slowEP != NULL);
2703663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      vassert(disp_cp_chain_me_to_fastEP != NULL);
2704663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2705663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      HReg r11 = hregAMD64_R11();
2706b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
2707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Use ptmp for backpatching conditional jumps. */
2708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ptmp = NULL;
2709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* First off, if this is conditional, create a conditional
2711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         jump over the rest of it. */
2712663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (i->Ain.XDirect.cond != Acc_ALWAYS) {
2713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* jmp fwds if !condition */
2714663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *p++ = toUChar(0x70 + (0xF & (i->Ain.XDirect.cond ^ 1)));
2715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ptmp = p; /* fill in this bit later */
2716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = 0; /* # of bytes to jump over; don't know how many yet. */
2717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2719663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Update the guest RIP. */
2720663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (fitsIn32Bits(i->Ain.XDirect.dstGA)) {
2721663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* use a shorter encoding */
2722663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* movl sign-extend(dstGA), %r11 */
2723663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *p++ = 0x49;
2724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = 0xC7;
2725663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *p++ = 0xC3;
2726663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         p = emit32(p, (UInt)i->Ain.XDirect.dstGA);
2727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
2728663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* movabsq $dstGA, %r11 */
2729663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *p++ = 0x49;
2730663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *p++ = 0xBB;
2731663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         p = emit64(p, i->Ain.XDirect.dstGA);
2732663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
2733663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2734663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* movq %r11, amRIP */
2735663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      *p++ = rexAMode_M(r11, i->Ain.XDirect.amRIP);
2736663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      *p++ = 0x89;
2737663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      p = doAMode_M(p, r11, i->Ain.XDirect.amRIP);
2738663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2739663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* --- FIRST PATCHABLE BYTE follows --- */
2740663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* VG_(disp_cp_chain_me_to_{slowEP,fastEP}) (where we're calling
2741663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         to) backs up the return address, so as to find the address of
2742663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         the first patchable byte.  So: don't change the length of the
2743663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         two instructions below. */
2744663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* movabsq $disp_cp_chain_me_to_{slow,fast}EP,%r11; */
2745663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      *p++ = 0x49;
2746663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      *p++ = 0xBB;
2747663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      void* disp_cp_chain_me
2748663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               = i->Ain.XDirect.toFastEP ? disp_cp_chain_me_to_fastEP
2749663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                         : disp_cp_chain_me_to_slowEP;
2750663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      p = emit64(p, Ptr_to_ULong(disp_cp_chain_me));
2751663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* call *%r11 */
2752663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      *p++ = 0x41;
2753663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      *p++ = 0xFF;
2754663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      *p++ = 0xD3;
2755663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* --- END of PATCHABLE BYTES --- */
2756663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2757663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Fix up the conditional jump, if there was one. */
2758663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (i->Ain.XDirect.cond != Acc_ALWAYS) {
2759663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Int delta = p - ptmp;
2760663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vassert(delta > 0 && delta < 40);
2761663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *ptmp = toUChar(delta-1);
2762663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
2763663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      goto done;
2764663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
2765663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2766663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case Ain_XIndir: {
2767663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* We're generating transfers that could lead indirectly to a
2768663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         chain-me, so we need to be sure this is actually allowed --
2769663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         no-redir translations are not allowed to reach normal
2770663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         translations without going through the scheduler.  That means
2771663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         no XDirects or XIndirs out from no-redir translations.
2772663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Hence: */
2773663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      vassert(disp_cp_xindir != NULL);
2774663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2775663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Use ptmp for backpatching conditional jumps. */
2776663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      ptmp = NULL;
2777663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2778663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* First off, if this is conditional, create a conditional
2779663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         jump over the rest of it. */
2780663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (i->Ain.XIndir.cond != Acc_ALWAYS) {
2781663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* jmp fwds if !condition */
2782663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *p++ = toUChar(0x70 + (0xF & (i->Ain.XIndir.cond ^ 1)));
2783663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         ptmp = p; /* fill in this bit later */
2784663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *p++ = 0; /* # of bytes to jump over; don't know how many yet. */
2785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2787663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* movq dstGA(a reg), amRIP -- copied from Alu64M MOV case */
2788663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      *p++ = rexAMode_M(i->Ain.XIndir.dstGA, i->Ain.XIndir.amRIP);
2789663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      *p++ = 0x89;
2790663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      p = doAMode_M(p, i->Ain.XIndir.dstGA, i->Ain.XIndir.amRIP);
2791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2792663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* get $disp_cp_xindir into %r11 */
2793663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (fitsIn32Bits(Ptr_to_ULong(disp_cp_xindir))) {
2794663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* use a shorter encoding */
2795663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* movl sign-extend(disp_cp_xindir), %r11 */
2796663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *p++ = 0x49;
2797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = 0xC7;
2798663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *p++ = 0xC3;
2799663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         p = emit32(p, (UInt)Ptr_to_ULong(disp_cp_xindir));
2800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
2801663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* movabsq $disp_cp_xindir, %r11 */
2802663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *p++ = 0x49;
2803663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *p++ = 0xBB;
2804663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         p = emit64(p, Ptr_to_ULong(disp_cp_xindir));
2805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2806663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2807663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* jmp *%r11 */
2808663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      *p++ = 0x41;
2809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = 0xFF;
2810663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      *p++ = 0xE3;
2811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Fix up the conditional jump, if there was one. */
2813663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (i->Ain.XIndir.cond != Acc_ALWAYS) {
2814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Int delta = p - ptmp;
2815663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vassert(delta > 0 && delta < 40);
2816663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *ptmp = toUChar(delta-1);
2817663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
2818663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      goto done;
2819663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
2820663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2821663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case Ain_XAssisted: {
2822663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Use ptmp for backpatching conditional jumps. */
2823663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      ptmp = NULL;
2824663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2825663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* First off, if this is conditional, create a conditional
2826663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         jump over the rest of it. */
2827663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (i->Ain.XAssisted.cond != Acc_ALWAYS) {
2828663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* jmp fwds if !condition */
2829663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *p++ = toUChar(0x70 + (0xF & (i->Ain.XAssisted.cond ^ 1)));
2830663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         ptmp = p; /* fill in this bit later */
2831663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *p++ = 0; /* # of bytes to jump over; don't know how many yet. */
2832663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
2833663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2834663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* movq dstGA(a reg), amRIP -- copied from Alu64M MOV case */
2835663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      *p++ = rexAMode_M(i->Ain.XAssisted.dstGA, i->Ain.XAssisted.amRIP);
2836663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      *p++ = 0x89;
2837663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      p = doAMode_M(p, i->Ain.XAssisted.dstGA, i->Ain.XAssisted.amRIP);
2838663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* movl $magic_number, %ebp.  Since these numbers are all small positive
2839663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         integers, we can get away with "movl $N, %ebp" rather than
2840663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         the longer "movq $N, %rbp". */
2841663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      UInt trcval = 0;
2842663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      switch (i->Ain.XAssisted.jk) {
2843663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Ijk_ClientReq:   trcval = VEX_TRC_JMP_CLIENTREQ;   break;
2844663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Ijk_Sys_syscall: trcval = VEX_TRC_JMP_SYS_SYSCALL; break;
2845663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Ijk_Sys_int32:   trcval = VEX_TRC_JMP_SYS_INT32;   break;
2846663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Ijk_Yield:       trcval = VEX_TRC_JMP_YIELD;       break;
2847663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Ijk_EmWarn:      trcval = VEX_TRC_JMP_EMWARN;      break;
2848663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Ijk_MapFail:     trcval = VEX_TRC_JMP_MAPFAIL;     break;
2849663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Ijk_NoDecode:    trcval = VEX_TRC_JMP_NODECODE;    break;
2850663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Ijk_TInval:      trcval = VEX_TRC_JMP_TINVAL;      break;
2851663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Ijk_NoRedir:     trcval = VEX_TRC_JMP_NOREDIR;     break;
2852663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Ijk_SigTRAP:     trcval = VEX_TRC_JMP_SIGTRAP;     break;
2853663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Ijk_SigSEGV:     trcval = VEX_TRC_JMP_SIGSEGV;     break;
2854663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Ijk_Boring:      trcval = VEX_TRC_JMP_BORING;      break;
2855663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* We don't expect to see the following being assisted. */
2856663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Ijk_Ret:
2857663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Ijk_Call:
2858663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* fallthrough */
2859663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         default:
2860663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            ppIRJumpKind(i->Ain.XAssisted.jk);
2861663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            vpanic("emit_AMD64Instr.Ain_XAssisted: unexpected jump kind");
2862663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
2863663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      vassert(trcval != 0);
2864663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      *p++ = 0xBD;
2865663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      p = emit32(p, trcval);
2866663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* movabsq $disp_assisted, %r11 */
2867663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      *p++ = 0x49;
2868663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      *p++ = 0xBB;
2869663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      p = emit64(p, Ptr_to_ULong(disp_cp_xassisted));
2870663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* jmp *%r11 */
2871663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      *p++ = 0x41;
2872663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      *p++ = 0xFF;
2873663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      *p++ = 0xE3;
2874663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2875663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Fix up the conditional jump, if there was one. */
2876663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (i->Ain.XAssisted.cond != Acc_ALWAYS) {
2877663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Int delta = p - ptmp;
2878663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vassert(delta > 0 && delta < 40);
2879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *ptmp = toUChar(delta-1);
2880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto done;
2882b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
2883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Ain_CMov64:
2885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(i->Ain.CMov64.cond != Acc_ALWAYS);
2886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (i->Ain.CMov64.src->tag == Arm_Reg) {
2887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = rexAMode_R(i->Ain.CMov64.dst, i->Ain.CMov64.src->Arm.Reg.reg);
2888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = 0x0F;
2889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = toUChar(0x40 + (0xF & i->Ain.CMov64.cond));
2890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         p = doAMode_R(p, i->Ain.CMov64.dst, i->Ain.CMov64.src->Arm.Reg.reg);
2891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto done;
2892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (i->Ain.CMov64.src->tag == Arm_Mem) {
2894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = rexAMode_M(i->Ain.CMov64.dst, i->Ain.CMov64.src->Arm.Mem.am);
2895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = 0x0F;
2896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = toUChar(0x40 + (0xF & i->Ain.CMov64.cond));
2897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         p = doAMode_M(p, i->Ain.CMov64.dst, i->Ain.CMov64.src->Arm.Mem.am);
2898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto done;
2899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
2901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Ain_MovxLQ:
2903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* No, _don't_ ask me why the sense of the args has to be
2904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         different in the S vs Z case.  I don't know. */
2905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (i->Ain.MovxLQ.syned) {
2906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Need REX.W = 1 here, but rexAMode_R does that for us. */
2907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = rexAMode_R(i->Ain.MovxLQ.dst, i->Ain.MovxLQ.src);
2908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = 0x63;
2909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         p = doAMode_R(p, i->Ain.MovxLQ.dst, i->Ain.MovxLQ.src);
2910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
2911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Produce a 32-bit reg-reg move, since the implicit
2912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            zero-extend does what we want. */
2913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = clearWBit (
2914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   rexAMode_R(i->Ain.MovxLQ.src, i->Ain.MovxLQ.dst));
2915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = 0x89;
2916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         p = doAMode_R(p, i->Ain.MovxLQ.src, i->Ain.MovxLQ.dst);
2917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto done;
2919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Ain_LoadEX:
2921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (i->Ain.LoadEX.szSmall == 1 && !i->Ain.LoadEX.syned) {
2922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* movzbq */
2923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = rexAMode_M(i->Ain.LoadEX.dst, i->Ain.LoadEX.src);
2924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = 0x0F;
2925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = 0xB6;
2926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         p = doAMode_M(p, i->Ain.LoadEX.dst, i->Ain.LoadEX.src);
2927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto done;
2928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (i->Ain.LoadEX.szSmall == 2 && !i->Ain.LoadEX.syned) {
2930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* movzwq */
2931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = rexAMode_M(i->Ain.LoadEX.dst, i->Ain.LoadEX.src);
2932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = 0x0F;
2933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = 0xB7;
2934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         p = doAMode_M(p, i->Ain.LoadEX.dst, i->Ain.LoadEX.src);
2935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto done;
2936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (i->Ain.LoadEX.szSmall == 4 && !i->Ain.LoadEX.syned) {
2938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* movzlq */
2939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* This isn't really an existing AMD64 instruction per se.
2940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Rather, we have to do a 32-bit load.  Because a 32-bit
2941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            write implicitly clears the upper 32 bits of the target
2942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            register, we get what we want. */
2943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = clearWBit(
2944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                rexAMode_M(i->Ain.LoadEX.dst, i->Ain.LoadEX.src));
2945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = 0x8B;
2946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         p = doAMode_M(p, i->Ain.LoadEX.dst, i->Ain.LoadEX.src);
2947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto done;
2948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
2950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Ain_Set64:
2952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Make the destination register be 1 or 0, depending on whether
2953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         the relevant condition holds.  Complication: the top 56 bits
2954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         of the destination should be forced to zero, but doing 'xorq
2955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         %r,%r' kills the flag(s) we are about to read.  Sigh.  So
2956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         start off my moving $0 into the dest. */
2957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      reg = iregBits3210(i->Ain.Set64.dst);
2958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(reg < 16);
2959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* movq $0, %dst */
2961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = toUChar(reg >= 8 ? 0x49 : 0x48);
2962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = 0xC7;
2963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = toUChar(0xC0 + (reg & 7));
2964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      p = emit32(p, 0);
2965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* setb lo8(%dst) */
2967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* note, 8-bit register rex trickyness.  Be careful here. */
2968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = toUChar(reg >= 8 ? 0x41 : 0x40);
2969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = 0x0F;
2970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = toUChar(0x90 + (0x0F & i->Ain.Set64.cond));
2971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = toUChar(0xC0 + (reg & 7));
2972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto done;
2973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Ain_Bsfr64:
2975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = rexAMode_R(i->Ain.Bsfr64.dst, i->Ain.Bsfr64.src);
2976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = 0x0F;
2977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (i->Ain.Bsfr64.isFwds) {
2978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = 0xBC;
2979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
2980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = 0xBD;
2981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      p = doAMode_R(p, i->Ain.Bsfr64.dst, i->Ain.Bsfr64.src);
2983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto done;
2984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Ain_MFence:
2986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* mfence */
2987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = 0x0F; *p++ = 0xAE; *p++ = 0xF0;
2988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto done;
2989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Ain_ACAS:
2991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* lock */
2992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = 0xF0;
2993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (i->Ain.ACAS.sz == 2) *p++ = 0x66;
2994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* cmpxchg{b,w,l,q} %rbx,mem.  Expected-value in %rax, new value
2995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         in %rbx.  The new-value register is hardwired to be %rbx
2996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         since dealing with byte integer registers is too much hassle,
2997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         so we force the register operand to %rbx (could equally be
2998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         %rcx or %rdx). */
2999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      rex = rexAMode_M( hregAMD64_RBX(), i->Ain.ACAS.addr );
3000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (i->Ain.ACAS.sz != 8)
3001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         rex = clearWBit(rex);
3002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = rex; /* this can emit 0x40, which is pointless. oh well. */
3004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = 0x0F;
3005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (i->Ain.ACAS.sz == 1) *p++ = 0xB0; else *p++ = 0xB1;
3006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      p = doAMode_M(p, hregAMD64_RBX(), i->Ain.ACAS.addr);
3007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto done;
3008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Ain_DACAS:
3010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* lock */
3011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = 0xF0;
3012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* cmpxchg{8,16}b m{64,128}.  Expected-value in %rdx:%rax, new
3013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         value in %rcx:%rbx.  All 4 regs are hardwired in the ISA, so
3014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         aren't encoded in the insn. */
3015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      rex = rexAMode_M( fake(1), i->Ain.ACAS.addr );
3016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (i->Ain.ACAS.sz != 8)
3017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         rex = clearWBit(rex);
3018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = rex;
3019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = 0x0F;
3020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = 0xC7;
3021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      p = doAMode_M(p, fake(1), i->Ain.DACAS.addr);
3022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto done;
3023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Ain_A87Free:
3025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(i->Ain.A87Free.nregs > 0 && i->Ain.A87Free.nregs <= 7);
3026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (j = 0; j < i->Ain.A87Free.nregs; j++) {
3027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         p = do_ffree_st(p, 7-j);
3028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto done;
3030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Ain_A87PushPop:
3032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(i->Ain.A87PushPop.szB == 8 || i->Ain.A87PushPop.szB == 4);
3033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (i->Ain.A87PushPop.isPush) {
3034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Load from memory into %st(0): flds/fldl amode */
3035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = clearWBit(
3036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   rexAMode_M(fake(0), i->Ain.A87PushPop.addr) );
3037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = i->Ain.A87PushPop.szB == 4 ? 0xD9 : 0xDD;
3038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 p = doAMode_M(p, fake(0)/*subopcode*/, i->Ain.A87PushPop.addr);
3039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
3040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Dump %st(0) to memory: fstps/fstpl amode */
3041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = clearWBit(
3042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   rexAMode_M(fake(3), i->Ain.A87PushPop.addr) );
3043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = i->Ain.A87PushPop.szB == 4 ? 0xD9 : 0xDD;
3044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         p = doAMode_M(p, fake(3)/*subopcode*/, i->Ain.A87PushPop.addr);
3045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto done;
3046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto done;
3048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Ain_A87FpOp:
3050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (i->Ain.A87FpOp.op) {
3051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Afp_SQRT:   *p++ = 0xD9; *p++ = 0xFA; break;
3052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Afp_SIN:    *p++ = 0xD9; *p++ = 0xFE; break;
3053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Afp_COS:    *p++ = 0xD9; *p++ = 0xFF; break;
3054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Afp_TAN:    *p++ = 0xD9; *p++ = 0xF2; break;
3055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Afp_ROUND:  *p++ = 0xD9; *p++ = 0xFC; break;
3056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Afp_2XM1:   *p++ = 0xD9; *p++ = 0xF0; break;
3057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Afp_SCALE:  *p++ = 0xD9; *p++ = 0xFD; break;
3058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Afp_ATAN:   *p++ = 0xD9; *p++ = 0xF3; break;
3059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Afp_YL2X:   *p++ = 0xD9; *p++ = 0xF1; break;
3060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Afp_YL2XP1: *p++ = 0xD9; *p++ = 0xF9; break;
3061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Afp_PREM:   *p++ = 0xD9; *p++ = 0xF8; break;
3062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Afp_PREM1:  *p++ = 0xD9; *p++ = 0xF5; break;
3063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default: goto bad;
3064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto done;
3066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Ain_A87LdCW:
3068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = clearWBit(
3069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                rexAMode_M(fake(5), i->Ain.A87LdCW.addr) );
3070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = 0xD9;
3071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      p = doAMode_M(p, fake(5)/*subopcode*/, i->Ain.A87LdCW.addr);
3072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto done;
3073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Ain_A87StSW:
3075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = clearWBit(
3076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                rexAMode_M(fake(7), i->Ain.A87StSW.addr) );
3077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = 0xDD;
3078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      p = doAMode_M(p, fake(7)/*subopcode*/, i->Ain.A87StSW.addr);
3079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto done;
3080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Ain_Store:
3082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (i->Ain.Store.sz == 2) {
3083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* This just goes to show the crazyness of the instruction
3084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            set encoding.  We have to insert two prefix bytes, but be
3085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            careful to avoid a conflict in what the size should be, by
3086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ensuring that REX.W = 0. */
3087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = 0x66; /* override to 16-bits */
3088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 *p++ = clearWBit( rexAMode_M( i->Ain.Store.src, i->Ain.Store.dst) );
3089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = 0x89;
3090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         p = doAMode_M(p, i->Ain.Store.src, i->Ain.Store.dst);
3091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto done;
3092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (i->Ain.Store.sz == 4) {
3094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 *p++ = clearWBit( rexAMode_M( i->Ain.Store.src, i->Ain.Store.dst) );
3095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = 0x89;
3096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         p = doAMode_M(p, i->Ain.Store.src, i->Ain.Store.dst);
3097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto done;
3098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (i->Ain.Store.sz == 1) {
3100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* This is one place where it would be wrong to skip emitting
3101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            a rex byte of 0x40, since the mere presence of rex changes
3102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            the meaning of the byte register access.  Be careful. */
3103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 *p++ = clearWBit( rexAMode_M( i->Ain.Store.src, i->Ain.Store.dst) );
3104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = 0x88;
3105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         p = doAMode_M(p, i->Ain.Store.src, i->Ain.Store.dst);
3106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto done;
3107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
3109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Ain_LdMXCSR:
3111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = clearWBit(rexAMode_M( fake(0), i->Ain.LdMXCSR.addr));
3112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = 0x0F;
3113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = 0xAE;
3114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      p = doAMode_M(p, fake(2)/*subopcode*/, i->Ain.LdMXCSR.addr);
3115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto done;
3116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Ain_SseUComIS:
3118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ucomi[sd] %srcL, %srcR ;  pushfq ; popq %dst */
3119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ucomi[sd] %srcL, %srcR */
3120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (i->Ain.SseUComIS.sz == 8) {
3121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = 0x66;
3122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
3123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto bad;
3124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(i->Ain.SseUComIS.sz == 4);
3125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = clearWBit (
3127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             rexAMode_R( vreg2ireg(i->Ain.SseUComIS.srcL),
3128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         vreg2ireg(i->Ain.SseUComIS.srcR) ));
3129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = 0x0F;
3130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = 0x2E;
3131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      p = doAMode_R(p, vreg2ireg(i->Ain.SseUComIS.srcL),
3132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       vreg2ireg(i->Ain.SseUComIS.srcR) );
3133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* pushfq */
3134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = 0x9C;
3135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* popq %dst */
3136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = toUChar(0x40 + (1 & iregBit3(i->Ain.SseUComIS.dst)));
3137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = toUChar(0x58 + iregBits210(i->Ain.SseUComIS.dst));
3138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto done;
3139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Ain_SseSI2SF:
3141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* cvssi2s[sd] %src, %dst */
3142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      rex = rexAMode_R( vreg2ireg(i->Ain.SseSI2SF.dst),
3143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        i->Ain.SseSI2SF.src );
3144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = toUChar(i->Ain.SseSI2SF.szD==4 ? 0xF3 : 0xF2);
3145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = toUChar(i->Ain.SseSI2SF.szS==4 ? clearWBit(rex) : rex);
3146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = 0x0F;
3147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = 0x2A;
3148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      p = doAMode_R( p, vreg2ireg(i->Ain.SseSI2SF.dst),
3149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        i->Ain.SseSI2SF.src );
3150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto done;
3151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Ain_SseSF2SI:
3153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* cvss[sd]2si %src, %dst */
3154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      rex = rexAMode_R( i->Ain.SseSF2SI.dst,
3155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        vreg2ireg(i->Ain.SseSF2SI.src) );
3156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = toUChar(i->Ain.SseSF2SI.szS==4 ? 0xF3 : 0xF2);
3157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = toUChar(i->Ain.SseSF2SI.szD==4 ? clearWBit(rex) : rex);
3158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = 0x0F;
3159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = 0x2D;
3160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      p = doAMode_R( p, i->Ain.SseSF2SI.dst,
3161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        vreg2ireg(i->Ain.SseSF2SI.src) );
3162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto done;
3163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Ain_SseSDSS:
3165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* cvtsd2ss/cvtss2sd %src, %dst */
3166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = toUChar(i->Ain.SseSDSS.from64 ? 0xF2 : 0xF3);
3167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = clearWBit(
3168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              rexAMode_R( vreg2ireg(i->Ain.SseSDSS.dst),
3169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          vreg2ireg(i->Ain.SseSDSS.src) ));
3170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = 0x0F;
3171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = 0x5A;
3172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      p = doAMode_R( p, vreg2ireg(i->Ain.SseSDSS.dst),
3173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        vreg2ireg(i->Ain.SseSDSS.src) );
3174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto done;
3175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Ain_SseLdSt:
3177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (i->Ain.SseLdSt.sz == 8) {
3178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = 0xF2;
3179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else
3180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (i->Ain.SseLdSt.sz == 4) {
3181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = 0xF3;
3182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else
3183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (i->Ain.SseLdSt.sz != 16) {
3184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(0);
3185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = clearWBit(
3187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             rexAMode_M( vreg2ireg(i->Ain.SseLdSt.reg), i->Ain.SseLdSt.addr));
3188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = 0x0F;
3189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = toUChar(i->Ain.SseLdSt.isLoad ? 0x10 : 0x11);
3190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      p = doAMode_M(p, vreg2ireg(i->Ain.SseLdSt.reg), i->Ain.SseLdSt.addr);
3191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto done;
3192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Ain_SseLdzLO:
3194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(i->Ain.SseLdzLO.sz == 4 || i->Ain.SseLdzLO.sz == 8);
3195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* movs[sd] amode, %xmm-dst */
3196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = toUChar(i->Ain.SseLdzLO.sz==4 ? 0xF3 : 0xF2);
3197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = clearWBit(
3198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             rexAMode_M(vreg2ireg(i->Ain.SseLdzLO.reg),
3199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        i->Ain.SseLdzLO.addr));
3200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = 0x0F;
3201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = 0x10;
3202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      p = doAMode_M(p, vreg2ireg(i->Ain.SseLdzLO.reg),
3203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       i->Ain.SseLdzLO.addr);
3204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto done;
3205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Ain_Sse32Fx4:
3207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      xtra = 0;
3208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = clearWBit(
3209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             rexAMode_R( vreg2ireg(i->Ain.Sse32Fx4.dst),
3210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         vreg2ireg(i->Ain.Sse32Fx4.src) ));
3211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = 0x0F;
3212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (i->Ain.Sse32Fx4.op) {
3213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_ADDF:   *p++ = 0x58; break;
3214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_DIVF:   *p++ = 0x5E; break;
3215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_MAXF:   *p++ = 0x5F; break;
3216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_MINF:   *p++ = 0x5D; break;
3217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_MULF:   *p++ = 0x59; break;
3218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_RCPF:   *p++ = 0x53; break;
3219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_RSQRTF: *p++ = 0x52; break;
3220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_SQRTF:  *p++ = 0x51; break;
3221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_SUBF:   *p++ = 0x5C; break;
3222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_CMPEQF: *p++ = 0xC2; xtra = 0x100; break;
3223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_CMPLTF: *p++ = 0xC2; xtra = 0x101; break;
3224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_CMPLEF: *p++ = 0xC2; xtra = 0x102; break;
3225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_CMPUNF: *p++ = 0xC2; xtra = 0x103; break;
3226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default: goto bad;
3227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      p = doAMode_R(p, vreg2ireg(i->Ain.Sse32Fx4.dst),
3229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       vreg2ireg(i->Ain.Sse32Fx4.src) );
3230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (xtra & 0x100)
3231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = toUChar(xtra & 0xFF);
3232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto done;
3233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Ain_Sse64Fx2:
3235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      xtra = 0;
3236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = 0x66;
3237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = clearWBit(
3238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             rexAMode_R( vreg2ireg(i->Ain.Sse64Fx2.dst),
3239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         vreg2ireg(i->Ain.Sse64Fx2.src) ));
3240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = 0x0F;
3241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (i->Ain.Sse64Fx2.op) {
3242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_ADDF:   *p++ = 0x58; break;
3243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_DIVF:   *p++ = 0x5E; break;
3244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_MAXF:   *p++ = 0x5F; break;
3245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_MINF:   *p++ = 0x5D; break;
3246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_MULF:   *p++ = 0x59; break;
3247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_SQRTF:  *p++ = 0x51; break;
3248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_SUBF:   *p++ = 0x5C; break;
3249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_CMPEQF: *p++ = 0xC2; xtra = 0x100; break;
3250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_CMPLTF: *p++ = 0xC2; xtra = 0x101; break;
3251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_CMPLEF: *p++ = 0xC2; xtra = 0x102; break;
3252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_CMPUNF: *p++ = 0xC2; xtra = 0x103; break;
3253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default: goto bad;
3254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      p = doAMode_R(p, vreg2ireg(i->Ain.Sse64Fx2.dst),
3256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       vreg2ireg(i->Ain.Sse64Fx2.src) );
3257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (xtra & 0x100)
3258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = toUChar(xtra & 0xFF);
3259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto done;
3260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Ain_Sse32FLo:
3262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      xtra = 0;
3263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = 0xF3;
3264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = clearWBit(
3265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             rexAMode_R( vreg2ireg(i->Ain.Sse32FLo.dst),
3266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         vreg2ireg(i->Ain.Sse32FLo.src) ));
3267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = 0x0F;
3268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (i->Ain.Sse32FLo.op) {
3269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_ADDF:   *p++ = 0x58; break;
3270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_DIVF:   *p++ = 0x5E; break;
3271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_MAXF:   *p++ = 0x5F; break;
3272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_MINF:   *p++ = 0x5D; break;
3273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_MULF:   *p++ = 0x59; break;
3274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_RCPF:   *p++ = 0x53; break;
3275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_RSQRTF: *p++ = 0x52; break;
3276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_SQRTF:  *p++ = 0x51; break;
3277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_SUBF:   *p++ = 0x5C; break;
3278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_CMPEQF: *p++ = 0xC2; xtra = 0x100; break;
3279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_CMPLTF: *p++ = 0xC2; xtra = 0x101; break;
3280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_CMPLEF: *p++ = 0xC2; xtra = 0x102; break;
3281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_CMPUNF: *p++ = 0xC2; xtra = 0x103; break;
3282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default: goto bad;
3283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      p = doAMode_R(p, vreg2ireg(i->Ain.Sse32FLo.dst),
3285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       vreg2ireg(i->Ain.Sse32FLo.src) );
3286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (xtra & 0x100)
3287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = toUChar(xtra & 0xFF);
3288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto done;
3289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Ain_Sse64FLo:
3291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      xtra = 0;
3292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = 0xF2;
3293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = clearWBit(
3294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             rexAMode_R( vreg2ireg(i->Ain.Sse64FLo.dst),
3295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         vreg2ireg(i->Ain.Sse64FLo.src) ));
3296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = 0x0F;
3297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (i->Ain.Sse64FLo.op) {
3298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_ADDF:   *p++ = 0x58; break;
3299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_DIVF:   *p++ = 0x5E; break;
3300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_MAXF:   *p++ = 0x5F; break;
3301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_MINF:   *p++ = 0x5D; break;
3302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_MULF:   *p++ = 0x59; break;
3303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_SQRTF:  *p++ = 0x51; break;
3304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_SUBF:   *p++ = 0x5C; break;
3305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_CMPEQF: *p++ = 0xC2; xtra = 0x100; break;
3306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_CMPLTF: *p++ = 0xC2; xtra = 0x101; break;
3307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_CMPLEF: *p++ = 0xC2; xtra = 0x102; break;
3308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_CMPUNF: *p++ = 0xC2; xtra = 0x103; break;
3309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default: goto bad;
3310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      p = doAMode_R(p, vreg2ireg(i->Ain.Sse64FLo.dst),
3312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       vreg2ireg(i->Ain.Sse64FLo.src) );
3313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (xtra & 0x100)
3314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *p++ = toUChar(xtra & 0xFF);
3315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto done;
3316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Ain_SseReRg:
3318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#     define XX(_n) *p++ = (_n)
3319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      rex = clearWBit(
3321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            rexAMode_R( vreg2ireg(i->Ain.SseReRg.dst),
3322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        vreg2ireg(i->Ain.SseReRg.src) ));
3323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (i->Ain.SseReRg.op) {
3325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_MOV:     /*movups*/ XX(rex); XX(0x0F); XX(0x10); break;
3326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_OR:                 XX(rex); XX(0x0F); XX(0x56); break;
3327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_XOR:                XX(rex); XX(0x0F); XX(0x57); break;
3328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_AND:                XX(rex); XX(0x0F); XX(0x54); break;
3329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_ANDN:               XX(rex); XX(0x0F); XX(0x55); break;
3330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_PACKSSD:  XX(0x66); XX(rex); XX(0x0F); XX(0x6B); break;
3331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_PACKSSW:  XX(0x66); XX(rex); XX(0x0F); XX(0x63); break;
3332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_PACKUSW:  XX(0x66); XX(rex); XX(0x0F); XX(0x67); break;
3333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_ADD8:     XX(0x66); XX(rex); XX(0x0F); XX(0xFC); break;
3334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_ADD16:    XX(0x66); XX(rex); XX(0x0F); XX(0xFD); break;
3335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_ADD32:    XX(0x66); XX(rex); XX(0x0F); XX(0xFE); break;
3336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_ADD64:    XX(0x66); XX(rex); XX(0x0F); XX(0xD4); break;
3337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_QADD8S:   XX(0x66); XX(rex); XX(0x0F); XX(0xEC); break;
3338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_QADD16S:  XX(0x66); XX(rex); XX(0x0F); XX(0xED); break;
3339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_QADD8U:   XX(0x66); XX(rex); XX(0x0F); XX(0xDC); break;
3340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_QADD16U:  XX(0x66); XX(rex); XX(0x0F); XX(0xDD); break;
3341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_AVG8U:    XX(0x66); XX(rex); XX(0x0F); XX(0xE0); break;
3342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_AVG16U:   XX(0x66); XX(rex); XX(0x0F); XX(0xE3); break;
3343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_CMPEQ8:   XX(0x66); XX(rex); XX(0x0F); XX(0x74); break;
3344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_CMPEQ16:  XX(0x66); XX(rex); XX(0x0F); XX(0x75); break;
3345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_CMPEQ32:  XX(0x66); XX(rex); XX(0x0F); XX(0x76); break;
3346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_CMPGT8S:  XX(0x66); XX(rex); XX(0x0F); XX(0x64); break;
3347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_CMPGT16S: XX(0x66); XX(rex); XX(0x0F); XX(0x65); break;
3348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_CMPGT32S: XX(0x66); XX(rex); XX(0x0F); XX(0x66); break;
3349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_MAX16S:   XX(0x66); XX(rex); XX(0x0F); XX(0xEE); break;
3350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_MAX8U:    XX(0x66); XX(rex); XX(0x0F); XX(0xDE); break;
3351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_MIN16S:   XX(0x66); XX(rex); XX(0x0F); XX(0xEA); break;
3352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_MIN8U:    XX(0x66); XX(rex); XX(0x0F); XX(0xDA); break;
3353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_MULHI16U: XX(0x66); XX(rex); XX(0x0F); XX(0xE4); break;
3354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_MULHI16S: XX(0x66); XX(rex); XX(0x0F); XX(0xE5); break;
3355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_MUL16:    XX(0x66); XX(rex); XX(0x0F); XX(0xD5); break;
3356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_SHL16:    XX(0x66); XX(rex); XX(0x0F); XX(0xF1); break;
3357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_SHL32:    XX(0x66); XX(rex); XX(0x0F); XX(0xF2); break;
3358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_SHL64:    XX(0x66); XX(rex); XX(0x0F); XX(0xF3); break;
3359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_SAR16:    XX(0x66); XX(rex); XX(0x0F); XX(0xE1); break;
3360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_SAR32:    XX(0x66); XX(rex); XX(0x0F); XX(0xE2); break;
3361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_SHR16:    XX(0x66); XX(rex); XX(0x0F); XX(0xD1); break;
3362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_SHR32:    XX(0x66); XX(rex); XX(0x0F); XX(0xD2); break;
3363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_SHR64:    XX(0x66); XX(rex); XX(0x0F); XX(0xD3); break;
3364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_SUB8:     XX(0x66); XX(rex); XX(0x0F); XX(0xF8); break;
3365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_SUB16:    XX(0x66); XX(rex); XX(0x0F); XX(0xF9); break;
3366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_SUB32:    XX(0x66); XX(rex); XX(0x0F); XX(0xFA); break;
3367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_SUB64:    XX(0x66); XX(rex); XX(0x0F); XX(0xFB); break;
3368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_QSUB8S:   XX(0x66); XX(rex); XX(0x0F); XX(0xE8); break;
3369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_QSUB16S:  XX(0x66); XX(rex); XX(0x0F); XX(0xE9); break;
3370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_QSUB8U:   XX(0x66); XX(rex); XX(0x0F); XX(0xD8); break;
3371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_QSUB16U:  XX(0x66); XX(rex); XX(0x0F); XX(0xD9); break;
3372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_UNPCKHB:  XX(0x66); XX(rex); XX(0x0F); XX(0x68); break;
3373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_UNPCKHW:  XX(0x66); XX(rex); XX(0x0F); XX(0x69); break;
3374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_UNPCKHD:  XX(0x66); XX(rex); XX(0x0F); XX(0x6A); break;
3375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_UNPCKHQ:  XX(0x66); XX(rex); XX(0x0F); XX(0x6D); break;
3376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_UNPCKLB:  XX(0x66); XX(rex); XX(0x0F); XX(0x60); break;
3377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_UNPCKLW:  XX(0x66); XX(rex); XX(0x0F); XX(0x61); break;
3378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_UNPCKLD:  XX(0x66); XX(rex); XX(0x0F); XX(0x62); break;
3379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Asse_UNPCKLQ:  XX(0x66); XX(rex); XX(0x0F); XX(0x6C); break;
3380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default: goto bad;
3381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      p = doAMode_R(p, vreg2ireg(i->Ain.SseReRg.dst),
3383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       vreg2ireg(i->Ain.SseReRg.src) );
3384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#     undef XX
3385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto done;
3386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Ain_SseCMov:
3388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* jmp fwds if !condition */
3389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = toUChar(0x70 + (i->Ain.SseCMov.cond ^ 1));
3390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = 0; /* # of bytes in the next bit, which we don't know yet */
3391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ptmp = p;
3392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* movaps %src, %dst */
3394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = clearWBit(
3395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             rexAMode_R( vreg2ireg(i->Ain.SseCMov.dst),
3396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         vreg2ireg(i->Ain.SseCMov.src) ));
3397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = 0x0F;
3398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = 0x28;
3399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      p = doAMode_R(p, vreg2ireg(i->Ain.SseCMov.dst),
3400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       vreg2ireg(i->Ain.SseCMov.src) );
3401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Fill in the jump offset. */
3403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *(ptmp-1) = toUChar(p - ptmp);
3404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto done;
3405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Ain_SseShuf:
3407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = 0x66;
3408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = clearWBit(
3409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             rexAMode_R( vreg2ireg(i->Ain.SseShuf.dst),
3410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         vreg2ireg(i->Ain.SseShuf.src) ));
3411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = 0x0F;
3412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = 0x70;
3413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      p = doAMode_R(p, vreg2ireg(i->Ain.SseShuf.dst),
3414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       vreg2ireg(i->Ain.SseShuf.src) );
3415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *p++ = (UChar)(i->Ain.SseShuf.order);
3416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto done;
3417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3418663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   //uu case Ain_AvxLdSt: {
3419663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   //uu    UInt vex = vexAMode_M( dvreg2ireg(i->Ain.AvxLdSt.reg),
3420663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   //uu                           i->Ain.AvxLdSt.addr );
3421663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   //uu    p = emitVexPrefix(p, vex);
3422663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   //uu    *p++ = toUChar(i->Ain.AvxLdSt.isLoad ? 0x10 : 0x11);
3423663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   //uu    p = doAMode_M(p, dvreg2ireg(i->Ain.AvxLdSt.reg), i->Ain.AvxLdSt.addr);
3424663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   //uu      goto done;
3425663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   //uu }
3426663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3427663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case Ain_EvCheck: {
3428663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* We generate:
3429663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            (3 bytes)  decl 8(%rbp)    8 == offsetof(host_EvC_COUNTER)
3430663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            (2 bytes)  jns  nofail     expected taken
3431663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            (3 bytes)  jmp* 0(%rbp)    0 == offsetof(host_EvC_FAILADDR)
3432663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            nofail:
3433663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      */
3434663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* This is heavily asserted re instruction lengths.  It needs to
3435663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         be.  If we get given unexpected forms of .amCounter or
3436663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         .amFailAddr -- basically, anything that's not of the form
3437663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         uimm7(%rbp) -- they are likely to fail. */
3438663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Note also that after the decl we must be very careful not to
3439663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         read the carry flag, else we get a partial flags stall.
3440663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         js/jns avoids that, though. */
3441663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      UChar* p0 = p;
3442663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* ---  decl 8(%rbp) --- */
3443663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Need to compute the REX byte for the decl in order to prove
3444663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         that we don't need it, since this is a 32-bit inc and all
3445663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         registers involved in the amode are < r8.  "fake(1)" because
3446663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         there's no register in this encoding; instead the register
3447663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         field is used as a sub opcode.  The encoding for "decl r/m32"
3448663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         is FF /1, hence the fake(1). */
3449663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      rex = clearWBit(rexAMode_M(fake(1), i->Ain.EvCheck.amCounter));
3450663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (rex != 0x40) goto bad; /* We don't expect to need the REX byte. */
3451663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      *p++ = 0xFF;
3452663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      p = doAMode_M(p, fake(1), i->Ain.EvCheck.amCounter);
3453663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      vassert(p - p0 == 3);
3454663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* --- jns nofail --- */
3455663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      *p++ = 0x79;
3456663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      *p++ = 0x03; /* need to check this 0x03 after the next insn */
3457663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      vassert(p - p0 == 5);
3458663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* --- jmp* 0(%rbp) --- */
3459663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Once again, verify we don't need REX.  The encoding is FF /4.
3460663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         We don't need REX.W since by default FF /4 in 64-bit mode
3461663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         implies a 64 bit load. */
3462663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      rex = clearWBit(rexAMode_M(fake(4), i->Ain.EvCheck.amFailAddr));
3463663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (rex != 0x40) goto bad;
3464663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      *p++ = 0xFF;
3465663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      p = doAMode_M(p, fake(4), i->Ain.EvCheck.amFailAddr);
3466663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      vassert(p - p0 == 8); /* also ensures that 0x03 offset above is ok */
3467663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* And crosscheck .. */
3468663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      vassert(evCheckSzB_AMD64() == 8);
3469663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      goto done;
3470663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
3471663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3472663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case Ain_ProfInc: {
3473663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* We generate   movabsq $0, %r11
3474663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                       incq (%r11)
3475663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         in the expectation that a later call to LibVEX_patchProfCtr
3476663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         will be used to fill in the immediate field once the right
3477663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         value is known.
3478663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         49 BB 00 00 00 00 00 00 00 00
3479663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         49 FF 03
3480663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      */
3481663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      *p++ = 0x49; *p++ = 0xBB;
3482663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      *p++ = 0x00; *p++ = 0x00; *p++ = 0x00; *p++ = 0x00;
3483663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      *p++ = 0x00; *p++ = 0x00; *p++ = 0x00; *p++ = 0x00;
3484663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      *p++ = 0x49; *p++ = 0xFF; *p++ = 0x03;
3485663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Tell the caller .. */
3486663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      vassert(!(*is_profInc));
3487663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      *is_profInc = True;
3488663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      goto done;
3489663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
3490663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:
3492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto bad;
3493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  bad:
3496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ppAMD64Instr(i, mode64);
3497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vpanic("emit_AMD64Instr");
3498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /*NOTREACHED*/
3499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  done:
3501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(p - &buf[0] <= 32);
3502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return p - &buf[0];
3503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  undef fake
3505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3507663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3508663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* How big is an event check?  See case for Ain_EvCheck in
3509663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   emit_AMD64Instr just above.  That crosschecks what this returns, so
3510663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   we can tell if we're inconsistent. */
3511663860b1408516d02ebfcb3a9999a134e6cfb223Ben ChengInt evCheckSzB_AMD64 ( void )
3512663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
3513663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return 8;
3514663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
3515663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3516663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3517663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* NB: what goes on here has to be very closely coordinated with the
3518663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   emitInstr case for XDirect, above. */
3519663860b1408516d02ebfcb3a9999a134e6cfb223Ben ChengVexInvalRange chainXDirect_AMD64 ( void* place_to_chain,
3520663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                   void* disp_cp_chain_me_EXPECTED,
3521663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                   void* place_to_jump_to )
3522663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
3523663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* What we're expecting to see is:
3524663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        movabsq $disp_cp_chain_me_EXPECTED, %r11
3525663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        call *%r11
3526663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      viz
3527663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        49 BB <8 bytes value == disp_cp_chain_me_EXPECTED>
3528663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        41 FF D3
3529663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   */
3530663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar* p = (UChar*)place_to_chain;
3531663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(p[0] == 0x49);
3532663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(p[1] == 0xBB);
3533663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(*(ULong*)(&p[2]) == Ptr_to_ULong(disp_cp_chain_me_EXPECTED));
3534663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(p[10] == 0x41);
3535663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(p[11] == 0xFF);
3536663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(p[12] == 0xD3);
3537663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* And what we want to change it to is either:
3538663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        (general case):
3539663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          movabsq $place_to_jump_to, %r11
3540663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          jmpq *%r11
3541663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        viz
3542663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          49 BB <8 bytes value == place_to_jump_to>
3543663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          41 FF E3
3544663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        So it's the same length (convenient, huh) and we don't
3545663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        need to change all the bits.
3546663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      ---OR---
3547663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        in the case where the displacement falls within 32 bits
3548663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          jmpq disp32   where disp32 is relative to the next insn
3549663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          ud2; ud2; ud2; ud2
3550663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        viz
3551663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          E9 <4 bytes == disp32>
3552663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          0F 0B 0F 0B 0F 0B 0F 0B
3553663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3554663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      In both cases the replacement has the same length as the original.
3555663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      To remain sane & verifiable,
3556663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      (1) limit the displacement for the short form to
3557663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          (say) +/- one billion, so as to avoid wraparound
3558663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          off-by-ones
3559663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      (2) even if the short form is applicable, once every (say)
3560663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          1024 times use the long form anyway, so as to maintain
3561663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          verifiability
3562663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   */
3563663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* This is the delta we need to put into a JMP d32 insn.  It's
3564663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      relative to the start of the next insn, hence the -5.  */
3565663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Long delta   = (Long)((UChar*)place_to_jump_to - (UChar*)p) - (Long)5;
3566663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Bool shortOK = delta >= -1000*1000*1000 && delta < 1000*1000*1000;
3567663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3568663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   static UInt shortCTR = 0; /* DO NOT MAKE NON-STATIC */
3569663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (shortOK) {
3570663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      shortCTR++; // thread safety bleh
3571663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (0 == (shortCTR & 0x3FF)) {
3572663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         shortOK = False;
3573663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (0)
3574663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            vex_printf("QQQ chainXDirect_AMD64: shortCTR = %u, "
3575663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                       "using long jmp\n", shortCTR);
3576663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
3577663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
3578663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3579663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* And make the modifications. */
3580663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (shortOK) {
3581663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      p[0]  = 0xE9;
3582663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      p[1]  = (delta >> 0) & 0xFF;
3583663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      p[2]  = (delta >> 8) & 0xFF;
3584663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      p[3]  = (delta >> 16) & 0xFF;
3585663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      p[4]  = (delta >> 24) & 0xFF;
3586663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      p[5]  = 0x0F; p[6]  = 0x0B;
3587663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      p[7]  = 0x0F; p[8]  = 0x0B;
3588663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      p[9]  = 0x0F; p[10] = 0x0B;
3589663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      p[11] = 0x0F; p[12] = 0x0B;
3590663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* sanity check on the delta -- top 32 are all 0 or all 1 */
3591663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      delta >>= 32;
3592663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      vassert(delta == 0LL || delta == -1LL);
3593663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } else {
3594663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Minimal modifications from the starting sequence. */
3595663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      *(ULong*)(&p[2]) = Ptr_to_ULong(place_to_jump_to);
3596663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      p[12] = 0xE3;
3597663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
3598663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   VexInvalRange vir = {0, 0};
3599663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return vir;
3600663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
3601663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3602663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3603663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* NB: what goes on here has to be very closely coordinated with the
3604663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   emitInstr case for XDirect, above. */
3605663860b1408516d02ebfcb3a9999a134e6cfb223Ben ChengVexInvalRange unchainXDirect_AMD64 ( void* place_to_unchain,
3606663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                     void* place_to_jump_to_EXPECTED,
3607663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                     void* disp_cp_chain_me )
3608663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
3609663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* What we're expecting to see is either:
3610663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        (general case)
3611663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          movabsq $place_to_jump_to_EXPECTED, %r11
3612663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          jmpq *%r11
3613663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        viz
3614663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          49 BB <8 bytes value == place_to_jump_to_EXPECTED>
3615663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          41 FF E3
3616663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      ---OR---
3617663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        in the case where the displacement falls within 32 bits
3618663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          jmpq d32
3619663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          ud2; ud2; ud2; ud2
3620663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        viz
3621663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          E9 <4 bytes == disp32>
3622663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          0F 0B 0F 0B 0F 0B 0F 0B
3623663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   */
3624663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar* p     = (UChar*)place_to_unchain;
3625663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Bool   valid = False;
3626663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (p[0] == 0x49 && p[1] == 0xBB
3627663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng       && *(ULong*)(&p[2]) == Ptr_to_ULong(place_to_jump_to_EXPECTED)
3628663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng       && p[10] == 0x41 && p[11] == 0xFF && p[12] == 0xE3) {
3629663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* it's the long form */
3630663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      valid = True;
3631663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
3632663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   else
3633663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (p[0] == 0xE9
3634663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng       && p[5]  == 0x0F && p[6]  == 0x0B
3635663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng       && p[7]  == 0x0F && p[8]  == 0x0B
3636663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng       && p[9]  == 0x0F && p[10] == 0x0B
3637663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng       && p[11] == 0x0F && p[12] == 0x0B) {
3638663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* It's the short form.  Check the offset is right. */
3639663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      Int  s32 = *(Int*)(&p[1]);
3640663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      Long s64 = (Long)s32;
3641663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if ((UChar*)p + 5 + s64 == (UChar*)place_to_jump_to_EXPECTED) {
3642663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         valid = True;
3643663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (0)
3644663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            vex_printf("QQQ unchainXDirect_AMD64: found short form\n");
3645663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
3646663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
3647663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(valid);
3648663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* And what we want to change it to is:
3649663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        movabsq $disp_cp_chain_me, %r11
3650663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        call *%r11
3651663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      viz
3652663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        49 BB <8 bytes value == disp_cp_chain_me>
3653663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        41 FF D3
3654663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      So it's the same length (convenient, huh).
3655663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   */
3656663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   p[0] = 0x49;
3657663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   p[1] = 0xBB;
3658663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   *(ULong*)(&p[2]) = Ptr_to_ULong(disp_cp_chain_me);
3659663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   p[10] = 0x41;
3660663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   p[11] = 0xFF;
3661663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   p[12] = 0xD3;
3662663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   VexInvalRange vir = {0, 0};
3663663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return vir;
3664663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
3665663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3666663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3667663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* Patch the counter address into a profile inc point, as previously
3668663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   created by the Ain_ProfInc case for emit_AMD64Instr. */
3669663860b1408516d02ebfcb3a9999a134e6cfb223Ben ChengVexInvalRange patchProfInc_AMD64 ( void*  place_to_patch,
3670663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                   ULong* location_of_counter )
3671663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
3672663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(sizeof(ULong*) == 8);
3673663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UChar* p = (UChar*)place_to_patch;
3674663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(p[0] == 0x49);
3675663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(p[1] == 0xBB);
3676663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(p[2] == 0x00);
3677663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(p[3] == 0x00);
3678663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(p[4] == 0x00);
3679663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(p[5] == 0x00);
3680663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(p[6] == 0x00);
3681663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(p[7] == 0x00);
3682663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(p[8] == 0x00);
3683663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(p[9] == 0x00);
3684663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(p[10] == 0x49);
3685663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(p[11] == 0xFF);
3686663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(p[12] == 0x03);
3687663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   ULong imm64 = (ULong)Ptr_to_ULong(location_of_counter);
3688663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   p[2] = imm64 & 0xFF; imm64 >>= 8;
3689663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   p[3] = imm64 & 0xFF; imm64 >>= 8;
3690663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   p[4] = imm64 & 0xFF; imm64 >>= 8;
3691663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   p[5] = imm64 & 0xFF; imm64 >>= 8;
3692663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   p[6] = imm64 & 0xFF; imm64 >>= 8;
3693663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   p[7] = imm64 & 0xFF; imm64 >>= 8;
3694663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   p[8] = imm64 & 0xFF; imm64 >>= 8;
3695663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   p[9] = imm64 & 0xFF; imm64 >>= 8;
3696663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   VexInvalRange vir = {0, 0};
3697663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return vir;
3698663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
3699663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3700663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
3702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- end                                   host_amd64_defs.c ---*/
3703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
3704