1a3e9830f0ab418d41a9c8484216b563d438cf2dcsewardj
2a3e9830f0ab418d41a9c8484216b563d438cf2dcsewardj/*---------------------------------------------------------------*/
3752f90673ebbb6b2f55fc5e46606dea371313713sewardj/*--- begin                                 host_amd64_defs.c ---*/
4a3e9830f0ab418d41a9c8484216b563d438cf2dcsewardj/*---------------------------------------------------------------*/
5a3e9830f0ab418d41a9c8484216b563d438cf2dcsewardj
6a3e9830f0ab418d41a9c8484216b563d438cf2dcsewardj/*
7752f90673ebbb6b2f55fc5e46606dea371313713sewardj   This file is part of Valgrind, a dynamic binary instrumentation
8752f90673ebbb6b2f55fc5e46606dea371313713sewardj   framework.
9a3e9830f0ab418d41a9c8484216b563d438cf2dcsewardj
10ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes   Copyright (C) 2004-2017 OpenWorks LLP
11752f90673ebbb6b2f55fc5e46606dea371313713sewardj      info@open-works.net
127bd6ffe203f3aa9e7b25f7eae40a9b9cf48710cfsewardj
13752f90673ebbb6b2f55fc5e46606dea371313713sewardj   This program is free software; you can redistribute it and/or
14752f90673ebbb6b2f55fc5e46606dea371313713sewardj   modify it under the terms of the GNU General Public License as
15752f90673ebbb6b2f55fc5e46606dea371313713sewardj   published by the Free Software Foundation; either version 2 of the
16752f90673ebbb6b2f55fc5e46606dea371313713sewardj   License, or (at your option) any later version.
177bd6ffe203f3aa9e7b25f7eae40a9b9cf48710cfsewardj
18752f90673ebbb6b2f55fc5e46606dea371313713sewardj   This program is distributed in the hope that it will be useful, but
19752f90673ebbb6b2f55fc5e46606dea371313713sewardj   WITHOUT ANY WARRANTY; without even the implied warranty of
20752f90673ebbb6b2f55fc5e46606dea371313713sewardj   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21752f90673ebbb6b2f55fc5e46606dea371313713sewardj   General Public License for more details.
227bd6ffe203f3aa9e7b25f7eae40a9b9cf48710cfsewardj
23752f90673ebbb6b2f55fc5e46606dea371313713sewardj   You should have received a copy of the GNU General Public License
24752f90673ebbb6b2f55fc5e46606dea371313713sewardj   along with this program; if not, write to the Free Software
25752f90673ebbb6b2f55fc5e46606dea371313713sewardj   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
26752f90673ebbb6b2f55fc5e46606dea371313713sewardj   02110-1301, USA.
277bd6ffe203f3aa9e7b25f7eae40a9b9cf48710cfsewardj
28752f90673ebbb6b2f55fc5e46606dea371313713sewardj   The GNU General Public License is contained in the file COPYING.
29a3e9830f0ab418d41a9c8484216b563d438cf2dcsewardj
30a3e9830f0ab418d41a9c8484216b563d438cf2dcsewardj   Neither the names of the U.S. Department of Energy nor the
31a3e9830f0ab418d41a9c8484216b563d438cf2dcsewardj   University of California nor the names of its contributors may be
32a3e9830f0ab418d41a9c8484216b563d438cf2dcsewardj   used to endorse or promote products derived from this software
33a3e9830f0ab418d41a9c8484216b563d438cf2dcsewardj   without prior written permission.
34a3e9830f0ab418d41a9c8484216b563d438cf2dcsewardj*/
35a3e9830f0ab418d41a9c8484216b563d438cf2dcsewardj
36a3e9830f0ab418d41a9c8484216b563d438cf2dcsewardj#include "libvex_basictypes.h"
37a3e9830f0ab418d41a9c8484216b563d438cf2dcsewardj#include "libvex.h"
38a3e9830f0ab418d41a9c8484216b563d438cf2dcsewardj#include "libvex_trc_values.h"
39a3e9830f0ab418d41a9c8484216b563d438cf2dcsewardj
40cef7d3e3df4796e35b4521158d9dc058f034aa87sewardj#include "main_util.h"
41cef7d3e3df4796e35b4521158d9dc058f034aa87sewardj#include "host_generic_regs.h"
42cef7d3e3df4796e35b4521158d9dc058f034aa87sewardj#include "host_amd64_defs.h"
43c33671d7b0e21edb1d1015e4cbccbc6ca139e6d8sewardj
44c33671d7b0e21edb1d1015e4cbccbc6ca139e6d8sewardj
45c33671d7b0e21edb1d1015e4cbccbc6ca139e6d8sewardj/* --------- Registers. --------- */
46c33671d7b0e21edb1d1015e4cbccbc6ca139e6d8sewardj
47a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardjconst RRegUniverse* getRRegUniverse_AMD64 ( void )
48a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj{
49a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj   /* The real-register universe is a big constant, so we just want to
50a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj      initialise it once. */
51a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj   static RRegUniverse rRegUniverse_AMD64;
52a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj   static Bool         rRegUniverse_AMD64_initted = False;
53a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj
54a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj   /* Handy shorthand, nothing more */
55a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj   RRegUniverse* ru = &rRegUniverse_AMD64;
56a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj
57a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj   /* This isn't thread-safe.  Sigh. */
58a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj   if (LIKELY(rRegUniverse_AMD64_initted))
59a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj      return ru;
60a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj
61a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj   RRegUniverse__init(ru);
62a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj
63a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj   /* Add the registers.  The initial segment of this array must be
64a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj      those available for allocation by reg-alloc, and those that
65a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj      follow are not available for allocation. */
66a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj   ru->regs[ru->size++] = hregAMD64_RSI();
67a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj   ru->regs[ru->size++] = hregAMD64_RDI();
68a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj   ru->regs[ru->size++] = hregAMD64_R8();
69a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj   ru->regs[ru->size++] = hregAMD64_R9();
70a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj   ru->regs[ru->size++] = hregAMD64_R12();
71a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj   ru->regs[ru->size++] = hregAMD64_R13();
72a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj   ru->regs[ru->size++] = hregAMD64_R14();
73a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj   ru->regs[ru->size++] = hregAMD64_R15();
74a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj   ru->regs[ru->size++] = hregAMD64_RBX();
75a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj   ru->regs[ru->size++] = hregAMD64_XMM3();
76a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj   ru->regs[ru->size++] = hregAMD64_XMM4();
77a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj   ru->regs[ru->size++] = hregAMD64_XMM5();
78a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj   ru->regs[ru->size++] = hregAMD64_XMM6();
79a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj   ru->regs[ru->size++] = hregAMD64_XMM7();
80a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj   ru->regs[ru->size++] = hregAMD64_XMM8();
81a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj   ru->regs[ru->size++] = hregAMD64_XMM9();
82a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj   ru->regs[ru->size++] = hregAMD64_XMM10();
83a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj   ru->regs[ru->size++] = hregAMD64_XMM11();
84a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj   ru->regs[ru->size++] = hregAMD64_XMM12();
85a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj   ru->regs[ru->size++] = hregAMD64_R10();
86a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj   ru->allocable = ru->size;
87a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj   /* And other regs, not available to the allocator. */
88a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj   ru->regs[ru->size++] = hregAMD64_RAX();
89a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj   ru->regs[ru->size++] = hregAMD64_RCX();
90a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj   ru->regs[ru->size++] = hregAMD64_RDX();
91a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj   ru->regs[ru->size++] = hregAMD64_RSP();
92a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj   ru->regs[ru->size++] = hregAMD64_RBP();
93a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj   ru->regs[ru->size++] = hregAMD64_R11();
94a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj   ru->regs[ru->size++] = hregAMD64_XMM0();
95a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj   ru->regs[ru->size++] = hregAMD64_XMM1();
96a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj
97a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj   rRegUniverse_AMD64_initted = True;
98a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj
99a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj   RRegUniverse__check_is_sane(ru);
100a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj   return ru;
101a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj}
102a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj
103a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj
104c33671d7b0e21edb1d1015e4cbccbc6ca139e6d8sewardjvoid ppHRegAMD64 ( HReg reg )
105614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj{
106614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj   Int r;
10755085f8680acc89d727e321f3b34cae1a8c4093aflorian   static const HChar* ireg64_names[16]
108614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj     = { "%rax", "%rcx", "%rdx", "%rbx", "%rsp", "%rbp", "%rsi", "%rdi",
109614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj         "%r8",  "%r9",  "%r10", "%r11", "%r12", "%r13", "%r14", "%r15" };
110614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj   /* Be generic for all virtual regs. */
111614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj   if (hregIsVirtual(reg)) {
112614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj      ppHReg(reg);
113614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj      return;
114614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj   }
115614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj   /* But specific for real regs. */
116614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj   switch (hregClass(reg)) {
117614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj      case HRcInt64:
118a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj         r = hregEncoding(reg);
119614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj         vassert(r >= 0 && r < 16);
120614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj         vex_printf("%s", ireg64_names[r]);
121614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj         return;
122614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj      case HRcVec128:
123a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj         r = hregEncoding(reg);
124614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj         vassert(r >= 0 && r < 16);
125614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj         vex_printf("%%xmm%d", r);
126614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj         return;
127614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj      default:
128614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj         vpanic("ppHRegAMD64");
129614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj   }
130c33671d7b0e21edb1d1015e4cbccbc6ca139e6d8sewardj}
131c33671d7b0e21edb1d1015e4cbccbc6ca139e6d8sewardj
132549e06463d433ee6351b72dc9107f22ce4305250sewardjstatic void ppHRegAMD64_lo32 ( HReg reg )
133549e06463d433ee6351b72dc9107f22ce4305250sewardj{
134549e06463d433ee6351b72dc9107f22ce4305250sewardj   Int r;
13555085f8680acc89d727e321f3b34cae1a8c4093aflorian   static const HChar* ireg32_names[16]
136a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj     = { "%eax", "%ecx", "%edx",  "%ebx",  "%esp",  "%ebp",  "%esi",  "%edi",
137a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj         "%r8d", "%r9d", "%r10d", "%r11d", "%r12d", "%r13d", "%r14d", "%r15d" };
138549e06463d433ee6351b72dc9107f22ce4305250sewardj   /* Be generic for all virtual regs. */
139549e06463d433ee6351b72dc9107f22ce4305250sewardj   if (hregIsVirtual(reg)) {
140549e06463d433ee6351b72dc9107f22ce4305250sewardj      ppHReg(reg);
141549e06463d433ee6351b72dc9107f22ce4305250sewardj      vex_printf("d");
142549e06463d433ee6351b72dc9107f22ce4305250sewardj      return;
143549e06463d433ee6351b72dc9107f22ce4305250sewardj   }
144549e06463d433ee6351b72dc9107f22ce4305250sewardj   /* But specific for real regs. */
145549e06463d433ee6351b72dc9107f22ce4305250sewardj   switch (hregClass(reg)) {
146549e06463d433ee6351b72dc9107f22ce4305250sewardj      case HRcInt64:
147a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj         r = hregEncoding(reg);
148549e06463d433ee6351b72dc9107f22ce4305250sewardj         vassert(r >= 0 && r < 16);
149549e06463d433ee6351b72dc9107f22ce4305250sewardj         vex_printf("%s", ireg32_names[r]);
150549e06463d433ee6351b72dc9107f22ce4305250sewardj         return;
151549e06463d433ee6351b72dc9107f22ce4305250sewardj      default:
152549e06463d433ee6351b72dc9107f22ce4305250sewardj         vpanic("ppHRegAMD64_lo32: invalid regclass");
153549e06463d433ee6351b72dc9107f22ce4305250sewardj   }
154549e06463d433ee6351b72dc9107f22ce4305250sewardj}
155549e06463d433ee6351b72dc9107f22ce4305250sewardj
156c33671d7b0e21edb1d1015e4cbccbc6ca139e6d8sewardj
157f67eadf04f5150178e589060f03381300d28e540sewardj/* --------- Condition codes, Intel encoding. --------- */
158f67eadf04f5150178e589060f03381300d28e540sewardj
15955085f8680acc89d727e321f3b34cae1a8c4093aflorianconst HChar* showAMD64CondCode ( AMD64CondCode cond )
160f67eadf04f5150178e589060f03381300d28e540sewardj{
161f67eadf04f5150178e589060f03381300d28e540sewardj   switch (cond) {
162f67eadf04f5150178e589060f03381300d28e540sewardj      case Acc_O:      return "o";
163f67eadf04f5150178e589060f03381300d28e540sewardj      case Acc_NO:     return "no";
164f67eadf04f5150178e589060f03381300d28e540sewardj      case Acc_B:      return "b";
165f67eadf04f5150178e589060f03381300d28e540sewardj      case Acc_NB:     return "nb";
166f67eadf04f5150178e589060f03381300d28e540sewardj      case Acc_Z:      return "z";
167f67eadf04f5150178e589060f03381300d28e540sewardj      case Acc_NZ:     return "nz";
168f67eadf04f5150178e589060f03381300d28e540sewardj      case Acc_BE:     return "be";
169f67eadf04f5150178e589060f03381300d28e540sewardj      case Acc_NBE:    return "nbe";
170f67eadf04f5150178e589060f03381300d28e540sewardj      case Acc_S:      return "s";
171f67eadf04f5150178e589060f03381300d28e540sewardj      case Acc_NS:     return "ns";
172f67eadf04f5150178e589060f03381300d28e540sewardj      case Acc_P:      return "p";
173f67eadf04f5150178e589060f03381300d28e540sewardj      case Acc_NP:     return "np";
174f67eadf04f5150178e589060f03381300d28e540sewardj      case Acc_L:      return "l";
175f67eadf04f5150178e589060f03381300d28e540sewardj      case Acc_NL:     return "nl";
176f67eadf04f5150178e589060f03381300d28e540sewardj      case Acc_LE:     return "le";
177f67eadf04f5150178e589060f03381300d28e540sewardj      case Acc_NLE:    return "nle";
178f67eadf04f5150178e589060f03381300d28e540sewardj      case Acc_ALWAYS: return "ALWAYS";
179f67eadf04f5150178e589060f03381300d28e540sewardj      default: vpanic("ppAMD64CondCode");
180f67eadf04f5150178e589060f03381300d28e540sewardj   }
181f67eadf04f5150178e589060f03381300d28e540sewardj}
182614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj
183614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj
184614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj/* --------- AMD64AMode: memory address expressions. --------- */
185614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj
186614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardjAMD64AMode* AMD64AMode_IR ( UInt imm32, HReg reg ) {
187d8e3ecaede8eccf5bc7be2a55d99a188a07b0a34florian   AMD64AMode* am = LibVEX_Alloc_inline(sizeof(AMD64AMode));
188614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj   am->tag        = Aam_IR;
189614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj   am->Aam.IR.imm = imm32;
190614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj   am->Aam.IR.reg = reg;
191614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj   return am;
192614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj}
193614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardjAMD64AMode* AMD64AMode_IRRS ( UInt imm32, HReg base, HReg indEx, Int shift ) {
194d8e3ecaede8eccf5bc7be2a55d99a188a07b0a34florian   AMD64AMode* am = LibVEX_Alloc_inline(sizeof(AMD64AMode));
195614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj   am->tag = Aam_IRRS;
196614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj   am->Aam.IRRS.imm   = imm32;
197614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj   am->Aam.IRRS.base  = base;
198614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj   am->Aam.IRRS.index = indEx;
199614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj   am->Aam.IRRS.shift = shift;
200614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj   vassert(shift >= 0 && shift <= 3);
201614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj   return am;
202614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj}
203614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj
204614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardjvoid ppAMD64AMode ( AMD64AMode* am ) {
205614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj   switch (am->tag) {
206614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj      case Aam_IR:
207614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj         if (am->Aam.IR.imm == 0)
208614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj            vex_printf("(");
209614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj         else
210614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj            vex_printf("0x%x(", am->Aam.IR.imm);
211614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj         ppHRegAMD64(am->Aam.IR.reg);
212614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj         vex_printf(")");
213614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj         return;
214614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj      case Aam_IRRS:
215614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj         vex_printf("0x%x(", am->Aam.IRRS.imm);
216614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj         ppHRegAMD64(am->Aam.IRRS.base);
217614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj         vex_printf(",");
218614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj         ppHRegAMD64(am->Aam.IRRS.index);
219614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj         vex_printf(",%d)", 1 << am->Aam.IRRS.shift);
220614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj         return;
221614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj      default:
222614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj         vpanic("ppAMD64AMode");
223614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj   }
224614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj}
225614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj
226f67eadf04f5150178e589060f03381300d28e540sewardjstatic void addRegUsage_AMD64AMode ( HRegUsage* u, AMD64AMode* am ) {
227f67eadf04f5150178e589060f03381300d28e540sewardj   switch (am->tag) {
228f67eadf04f5150178e589060f03381300d28e540sewardj      case Aam_IR:
229f67eadf04f5150178e589060f03381300d28e540sewardj         addHRegUse(u, HRmRead, am->Aam.IR.reg);
230f67eadf04f5150178e589060f03381300d28e540sewardj         return;
231f67eadf04f5150178e589060f03381300d28e540sewardj      case Aam_IRRS:
232f67eadf04f5150178e589060f03381300d28e540sewardj         addHRegUse(u, HRmRead, am->Aam.IRRS.base);
233f67eadf04f5150178e589060f03381300d28e540sewardj         addHRegUse(u, HRmRead, am->Aam.IRRS.index);
234f67eadf04f5150178e589060f03381300d28e540sewardj         return;
235f67eadf04f5150178e589060f03381300d28e540sewardj      default:
236f67eadf04f5150178e589060f03381300d28e540sewardj         vpanic("addRegUsage_AMD64AMode");
237f67eadf04f5150178e589060f03381300d28e540sewardj   }
238f67eadf04f5150178e589060f03381300d28e540sewardj}
239f67eadf04f5150178e589060f03381300d28e540sewardj
240f67eadf04f5150178e589060f03381300d28e540sewardjstatic void mapRegs_AMD64AMode ( HRegRemap* m, AMD64AMode* am ) {
241f67eadf04f5150178e589060f03381300d28e540sewardj   switch (am->tag) {
242f67eadf04f5150178e589060f03381300d28e540sewardj      case Aam_IR:
243f67eadf04f5150178e589060f03381300d28e540sewardj         am->Aam.IR.reg = lookupHRegRemap(m, am->Aam.IR.reg);
244f67eadf04f5150178e589060f03381300d28e540sewardj         return;
245f67eadf04f5150178e589060f03381300d28e540sewardj      case Aam_IRRS:
246f67eadf04f5150178e589060f03381300d28e540sewardj         am->Aam.IRRS.base = lookupHRegRemap(m, am->Aam.IRRS.base);
247f67eadf04f5150178e589060f03381300d28e540sewardj         am->Aam.IRRS.index = lookupHRegRemap(m, am->Aam.IRRS.index);
248f67eadf04f5150178e589060f03381300d28e540sewardj         return;
249f67eadf04f5150178e589060f03381300d28e540sewardj      default:
250f67eadf04f5150178e589060f03381300d28e540sewardj         vpanic("mapRegs_AMD64AMode");
251f67eadf04f5150178e589060f03381300d28e540sewardj   }
252f67eadf04f5150178e589060f03381300d28e540sewardj}
253614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj
254614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj/* --------- Operand, which can be reg, immediate or memory. --------- */
255614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj
256614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardjAMD64RMI* AMD64RMI_Imm ( UInt imm32 ) {
257d8e3ecaede8eccf5bc7be2a55d99a188a07b0a34florian   AMD64RMI* op       = LibVEX_Alloc_inline(sizeof(AMD64RMI));
258614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj   op->tag            = Armi_Imm;
259614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj   op->Armi.Imm.imm32 = imm32;
260614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj   return op;
261614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj}
2628258a8c9f2e0ba23e79e322102fa6d0c354436f1sewardjAMD64RMI* AMD64RMI_Reg ( HReg reg ) {
263d8e3ecaede8eccf5bc7be2a55d99a188a07b0a34florian   AMD64RMI* op     = LibVEX_Alloc_inline(sizeof(AMD64RMI));
2648258a8c9f2e0ba23e79e322102fa6d0c354436f1sewardj   op->tag          = Armi_Reg;
2658258a8c9f2e0ba23e79e322102fa6d0c354436f1sewardj   op->Armi.Reg.reg = reg;
2668258a8c9f2e0ba23e79e322102fa6d0c354436f1sewardj   return op;
2678258a8c9f2e0ba23e79e322102fa6d0c354436f1sewardj}
268614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardjAMD64RMI* AMD64RMI_Mem ( AMD64AMode* am ) {
269d8e3ecaede8eccf5bc7be2a55d99a188a07b0a34florian   AMD64RMI* op    = LibVEX_Alloc_inline(sizeof(AMD64RMI));
270614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj   op->tag         = Armi_Mem;
271614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj   op->Armi.Mem.am = am;
272614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj   return op;
273614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj}
274614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj
2759cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardjstatic void ppAMD64RMI_wrk ( AMD64RMI* op, Bool lo32 ) {
276614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj   switch (op->tag) {
277614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj      case Armi_Imm:
278614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj         vex_printf("$0x%x", op->Armi.Imm.imm32);
279614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj         return;
2809cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj      case Armi_Reg:
2819cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj         if (lo32)
2829cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj            ppHRegAMD64_lo32(op->Armi.Reg.reg);
2839cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj         else
2849cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj            ppHRegAMD64(op->Armi.Reg.reg);
285614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj         return;
286614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj      case Armi_Mem:
287614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj         ppAMD64AMode(op->Armi.Mem.am);
288614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj         return;
289614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj     default:
290614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj         vpanic("ppAMD64RMI");
291614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj   }
292614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj}
2939cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardjvoid ppAMD64RMI ( AMD64RMI* op ) {
2949cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj   ppAMD64RMI_wrk(op, False/*!lo32*/);
2959cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj}
2969cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardjvoid ppAMD64RMI_lo32 ( AMD64RMI* op ) {
2979cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj   ppAMD64RMI_wrk(op, True/*lo32*/);
2989cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj}
299614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj
300f67eadf04f5150178e589060f03381300d28e540sewardj/* An AMD64RMI can only be used in a "read" context (what would it mean
301f67eadf04f5150178e589060f03381300d28e540sewardj   to write or modify a literal?) and so we enumerate its registers
302f67eadf04f5150178e589060f03381300d28e540sewardj   accordingly. */
303f67eadf04f5150178e589060f03381300d28e540sewardjstatic void addRegUsage_AMD64RMI ( HRegUsage* u, AMD64RMI* op ) {
304f67eadf04f5150178e589060f03381300d28e540sewardj   switch (op->tag) {
305f67eadf04f5150178e589060f03381300d28e540sewardj      case Armi_Imm:
306f67eadf04f5150178e589060f03381300d28e540sewardj         return;
307f67eadf04f5150178e589060f03381300d28e540sewardj      case Armi_Reg:
308f67eadf04f5150178e589060f03381300d28e540sewardj         addHRegUse(u, HRmRead, op->Armi.Reg.reg);
309f67eadf04f5150178e589060f03381300d28e540sewardj         return;
310f67eadf04f5150178e589060f03381300d28e540sewardj      case Armi_Mem:
311f67eadf04f5150178e589060f03381300d28e540sewardj         addRegUsage_AMD64AMode(u, op->Armi.Mem.am);
312f67eadf04f5150178e589060f03381300d28e540sewardj         return;
313f67eadf04f5150178e589060f03381300d28e540sewardj      default:
314f67eadf04f5150178e589060f03381300d28e540sewardj         vpanic("addRegUsage_AMD64RMI");
315f67eadf04f5150178e589060f03381300d28e540sewardj   }
316f67eadf04f5150178e589060f03381300d28e540sewardj}
317f67eadf04f5150178e589060f03381300d28e540sewardj
318f67eadf04f5150178e589060f03381300d28e540sewardjstatic void mapRegs_AMD64RMI ( HRegRemap* m, AMD64RMI* op ) {
319f67eadf04f5150178e589060f03381300d28e540sewardj   switch (op->tag) {
320f67eadf04f5150178e589060f03381300d28e540sewardj      case Armi_Imm:
321f67eadf04f5150178e589060f03381300d28e540sewardj         return;
322f67eadf04f5150178e589060f03381300d28e540sewardj      case Armi_Reg:
323f67eadf04f5150178e589060f03381300d28e540sewardj         op->Armi.Reg.reg = lookupHRegRemap(m, op->Armi.Reg.reg);
324f67eadf04f5150178e589060f03381300d28e540sewardj         return;
325f67eadf04f5150178e589060f03381300d28e540sewardj      case Armi_Mem:
326f67eadf04f5150178e589060f03381300d28e540sewardj         mapRegs_AMD64AMode(m, op->Armi.Mem.am);
327f67eadf04f5150178e589060f03381300d28e540sewardj         return;
328f67eadf04f5150178e589060f03381300d28e540sewardj      default:
329f67eadf04f5150178e589060f03381300d28e540sewardj         vpanic("mapRegs_AMD64RMI");
330f67eadf04f5150178e589060f03381300d28e540sewardj   }
331f67eadf04f5150178e589060f03381300d28e540sewardj}
332f67eadf04f5150178e589060f03381300d28e540sewardj
333f67eadf04f5150178e589060f03381300d28e540sewardj
334f67eadf04f5150178e589060f03381300d28e540sewardj/* --------- Operand, which can be reg or immediate only. --------- */
335f67eadf04f5150178e589060f03381300d28e540sewardj
336f67eadf04f5150178e589060f03381300d28e540sewardjAMD64RI* AMD64RI_Imm ( UInt imm32 ) {
337d8e3ecaede8eccf5bc7be2a55d99a188a07b0a34florian   AMD64RI* op       = LibVEX_Alloc_inline(sizeof(AMD64RI));
338f67eadf04f5150178e589060f03381300d28e540sewardj   op->tag           = Ari_Imm;
339f67eadf04f5150178e589060f03381300d28e540sewardj   op->Ari.Imm.imm32 = imm32;
340f67eadf04f5150178e589060f03381300d28e540sewardj   return op;
341f67eadf04f5150178e589060f03381300d28e540sewardj}
342f67eadf04f5150178e589060f03381300d28e540sewardjAMD64RI* AMD64RI_Reg ( HReg reg ) {
343d8e3ecaede8eccf5bc7be2a55d99a188a07b0a34florian   AMD64RI* op     = LibVEX_Alloc_inline(sizeof(AMD64RI));
344f67eadf04f5150178e589060f03381300d28e540sewardj   op->tag         = Ari_Reg;
345f67eadf04f5150178e589060f03381300d28e540sewardj   op->Ari.Reg.reg = reg;
346f67eadf04f5150178e589060f03381300d28e540sewardj   return op;
347f67eadf04f5150178e589060f03381300d28e540sewardj}
348f67eadf04f5150178e589060f03381300d28e540sewardj
349f67eadf04f5150178e589060f03381300d28e540sewardjvoid ppAMD64RI ( AMD64RI* op ) {
350f67eadf04f5150178e589060f03381300d28e540sewardj   switch (op->tag) {
351f67eadf04f5150178e589060f03381300d28e540sewardj      case Ari_Imm:
352f67eadf04f5150178e589060f03381300d28e540sewardj         vex_printf("$0x%x", op->Ari.Imm.imm32);
353f67eadf04f5150178e589060f03381300d28e540sewardj         return;
354f67eadf04f5150178e589060f03381300d28e540sewardj      case Ari_Reg:
355f67eadf04f5150178e589060f03381300d28e540sewardj         ppHRegAMD64(op->Ari.Reg.reg);
356f67eadf04f5150178e589060f03381300d28e540sewardj         return;
357f67eadf04f5150178e589060f03381300d28e540sewardj     default:
358f67eadf04f5150178e589060f03381300d28e540sewardj         vpanic("ppAMD64RI");
359f67eadf04f5150178e589060f03381300d28e540sewardj   }
360f67eadf04f5150178e589060f03381300d28e540sewardj}
361f67eadf04f5150178e589060f03381300d28e540sewardj
362f67eadf04f5150178e589060f03381300d28e540sewardj/* An AMD64RI can only be used in a "read" context (what would it mean
363f67eadf04f5150178e589060f03381300d28e540sewardj   to write or modify a literal?) and so we enumerate its registers
364f67eadf04f5150178e589060f03381300d28e540sewardj   accordingly. */
365f67eadf04f5150178e589060f03381300d28e540sewardjstatic void addRegUsage_AMD64RI ( HRegUsage* u, AMD64RI* op ) {
366f67eadf04f5150178e589060f03381300d28e540sewardj   switch (op->tag) {
367f67eadf04f5150178e589060f03381300d28e540sewardj      case Ari_Imm:
368f67eadf04f5150178e589060f03381300d28e540sewardj         return;
369f67eadf04f5150178e589060f03381300d28e540sewardj      case Ari_Reg:
370f67eadf04f5150178e589060f03381300d28e540sewardj         addHRegUse(u, HRmRead, op->Ari.Reg.reg);
371f67eadf04f5150178e589060f03381300d28e540sewardj         return;
372f67eadf04f5150178e589060f03381300d28e540sewardj      default:
373f67eadf04f5150178e589060f03381300d28e540sewardj         vpanic("addRegUsage_AMD64RI");
374f67eadf04f5150178e589060f03381300d28e540sewardj   }
375f67eadf04f5150178e589060f03381300d28e540sewardj}
376f67eadf04f5150178e589060f03381300d28e540sewardj
377f67eadf04f5150178e589060f03381300d28e540sewardjstatic void mapRegs_AMD64RI ( HRegRemap* m, AMD64RI* op ) {
378f67eadf04f5150178e589060f03381300d28e540sewardj   switch (op->tag) {
379f67eadf04f5150178e589060f03381300d28e540sewardj      case Ari_Imm:
380f67eadf04f5150178e589060f03381300d28e540sewardj         return;
381f67eadf04f5150178e589060f03381300d28e540sewardj      case Ari_Reg:
382f67eadf04f5150178e589060f03381300d28e540sewardj         op->Ari.Reg.reg = lookupHRegRemap(m, op->Ari.Reg.reg);
383f67eadf04f5150178e589060f03381300d28e540sewardj         return;
384f67eadf04f5150178e589060f03381300d28e540sewardj      default:
385f67eadf04f5150178e589060f03381300d28e540sewardj         vpanic("mapRegs_AMD64RI");
386f67eadf04f5150178e589060f03381300d28e540sewardj   }
387f67eadf04f5150178e589060f03381300d28e540sewardj}
3888258a8c9f2e0ba23e79e322102fa6d0c354436f1sewardj
3898258a8c9f2e0ba23e79e322102fa6d0c354436f1sewardj
3908258a8c9f2e0ba23e79e322102fa6d0c354436f1sewardj/* --------- Operand, which can be reg or memory only. --------- */
3918258a8c9f2e0ba23e79e322102fa6d0c354436f1sewardj
3928258a8c9f2e0ba23e79e322102fa6d0c354436f1sewardjAMD64RM* AMD64RM_Reg ( HReg reg ) {
393d8e3ecaede8eccf5bc7be2a55d99a188a07b0a34florian   AMD64RM* op       = LibVEX_Alloc_inline(sizeof(AMD64RM));
3948258a8c9f2e0ba23e79e322102fa6d0c354436f1sewardj   op->tag         = Arm_Reg;
3958258a8c9f2e0ba23e79e322102fa6d0c354436f1sewardj   op->Arm.Reg.reg = reg;
3968258a8c9f2e0ba23e79e322102fa6d0c354436f1sewardj   return op;
3978258a8c9f2e0ba23e79e322102fa6d0c354436f1sewardj}
39805b3b6a0474ba57b4dbd15ac26d857197cdc87fcsewardjAMD64RM* AMD64RM_Mem ( AMD64AMode* am ) {
399d8e3ecaede8eccf5bc7be2a55d99a188a07b0a34florian   AMD64RM* op    = LibVEX_Alloc_inline(sizeof(AMD64RM));
40005b3b6a0474ba57b4dbd15ac26d857197cdc87fcsewardj   op->tag        = Arm_Mem;
40105b3b6a0474ba57b4dbd15ac26d857197cdc87fcsewardj   op->Arm.Mem.am = am;
40205b3b6a0474ba57b4dbd15ac26d857197cdc87fcsewardj   return op;
40305b3b6a0474ba57b4dbd15ac26d857197cdc87fcsewardj}
4048258a8c9f2e0ba23e79e322102fa6d0c354436f1sewardj
4058258a8c9f2e0ba23e79e322102fa6d0c354436f1sewardjvoid ppAMD64RM ( AMD64RM* op ) {
4068258a8c9f2e0ba23e79e322102fa6d0c354436f1sewardj   switch (op->tag) {
4078258a8c9f2e0ba23e79e322102fa6d0c354436f1sewardj      case Arm_Mem:
4088258a8c9f2e0ba23e79e322102fa6d0c354436f1sewardj         ppAMD64AMode(op->Arm.Mem.am);
4098258a8c9f2e0ba23e79e322102fa6d0c354436f1sewardj         return;
4108258a8c9f2e0ba23e79e322102fa6d0c354436f1sewardj      case Arm_Reg:
4118258a8c9f2e0ba23e79e322102fa6d0c354436f1sewardj         ppHRegAMD64(op->Arm.Reg.reg);
4128258a8c9f2e0ba23e79e322102fa6d0c354436f1sewardj         return;
4138258a8c9f2e0ba23e79e322102fa6d0c354436f1sewardj     default:
4148258a8c9f2e0ba23e79e322102fa6d0c354436f1sewardj         vpanic("ppAMD64RM");
4158258a8c9f2e0ba23e79e322102fa6d0c354436f1sewardj   }
4168258a8c9f2e0ba23e79e322102fa6d0c354436f1sewardj}
4178258a8c9f2e0ba23e79e322102fa6d0c354436f1sewardj
418f67eadf04f5150178e589060f03381300d28e540sewardj/* Because an AMD64RM can be both a source or destination operand, we
419f67eadf04f5150178e589060f03381300d28e540sewardj   have to supply a mode -- pertaining to the operand as a whole --
420f67eadf04f5150178e589060f03381300d28e540sewardj   indicating how it's being used. */
421f67eadf04f5150178e589060f03381300d28e540sewardjstatic void addRegUsage_AMD64RM ( HRegUsage* u, AMD64RM* op, HRegMode mode ) {
422f67eadf04f5150178e589060f03381300d28e540sewardj   switch (op->tag) {
423f67eadf04f5150178e589060f03381300d28e540sewardj      case Arm_Mem:
424f67eadf04f5150178e589060f03381300d28e540sewardj         /* Memory is read, written or modified.  So we just want to
425f67eadf04f5150178e589060f03381300d28e540sewardj            know the regs read by the amode. */
426f67eadf04f5150178e589060f03381300d28e540sewardj         addRegUsage_AMD64AMode(u, op->Arm.Mem.am);
427f67eadf04f5150178e589060f03381300d28e540sewardj         return;
428f67eadf04f5150178e589060f03381300d28e540sewardj      case Arm_Reg:
429f67eadf04f5150178e589060f03381300d28e540sewardj         /* reg is read, written or modified.  Add it in the
430f67eadf04f5150178e589060f03381300d28e540sewardj            appropriate way. */
431f67eadf04f5150178e589060f03381300d28e540sewardj         addHRegUse(u, mode, op->Arm.Reg.reg);
432f67eadf04f5150178e589060f03381300d28e540sewardj         return;
433f67eadf04f5150178e589060f03381300d28e540sewardj     default:
434f67eadf04f5150178e589060f03381300d28e540sewardj         vpanic("addRegUsage_AMD64RM");
435f67eadf04f5150178e589060f03381300d28e540sewardj   }
436f67eadf04f5150178e589060f03381300d28e540sewardj}
437f67eadf04f5150178e589060f03381300d28e540sewardj
438f67eadf04f5150178e589060f03381300d28e540sewardjstatic void mapRegs_AMD64RM ( HRegRemap* m, AMD64RM* op )
439f67eadf04f5150178e589060f03381300d28e540sewardj{
440f67eadf04f5150178e589060f03381300d28e540sewardj   switch (op->tag) {
441f67eadf04f5150178e589060f03381300d28e540sewardj      case Arm_Mem:
442f67eadf04f5150178e589060f03381300d28e540sewardj         mapRegs_AMD64AMode(m, op->Arm.Mem.am);
443f67eadf04f5150178e589060f03381300d28e540sewardj         return;
444f67eadf04f5150178e589060f03381300d28e540sewardj      case Arm_Reg:
445f67eadf04f5150178e589060f03381300d28e540sewardj         op->Arm.Reg.reg = lookupHRegRemap(m, op->Arm.Reg.reg);
446f67eadf04f5150178e589060f03381300d28e540sewardj         return;
447f67eadf04f5150178e589060f03381300d28e540sewardj     default:
448f67eadf04f5150178e589060f03381300d28e540sewardj         vpanic("mapRegs_AMD64RM");
449f67eadf04f5150178e589060f03381300d28e540sewardj   }
450f67eadf04f5150178e589060f03381300d28e540sewardj}
451f67eadf04f5150178e589060f03381300d28e540sewardj
452f67eadf04f5150178e589060f03381300d28e540sewardj
4539b96767debeeb1f78378f0e7e295fe6762c64002sewardj/* --------- Instructions. --------- */
4549b96767debeeb1f78378f0e7e295fe6762c64002sewardj
45555085f8680acc89d727e321f3b34cae1a8c4093aflorianstatic const HChar* showAMD64ScalarSz ( Int sz ) {
4569b96767debeeb1f78378f0e7e295fe6762c64002sewardj   switch (sz) {
4579b96767debeeb1f78378f0e7e295fe6762c64002sewardj      case 2: return "w";
4589b96767debeeb1f78378f0e7e295fe6762c64002sewardj      case 4: return "l";
4599b96767debeeb1f78378f0e7e295fe6762c64002sewardj      case 8: return "q";
4609b96767debeeb1f78378f0e7e295fe6762c64002sewardj      default: vpanic("showAMD64ScalarSz");
4619b96767debeeb1f78378f0e7e295fe6762c64002sewardj   }
4629b96767debeeb1f78378f0e7e295fe6762c64002sewardj}
4639b96767debeeb1f78378f0e7e295fe6762c64002sewardj
46455085f8680acc89d727e321f3b34cae1a8c4093aflorianconst HChar* showAMD64UnaryOp ( AMD64UnaryOp op ) {
465d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj   switch (op) {
466d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj      case Aun_NOT: return "not";
467d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj      case Aun_NEG: return "neg";
468d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj      default: vpanic("showAMD64UnaryOp");
469d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj   }
470d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj}
471614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj
47255085f8680acc89d727e321f3b34cae1a8c4093aflorianconst HChar* showAMD64AluOp ( AMD64AluOp op ) {
473614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj   switch (op) {
474614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj      case Aalu_MOV:  return "mov";
475614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj      case Aalu_CMP:  return "cmp";
476614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj      case Aalu_ADD:  return "add";
477614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj      case Aalu_SUB:  return "sub";
478614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj      case Aalu_ADC:  return "adc";
479614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj      case Aalu_SBB:  return "sbb";
480614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj      case Aalu_AND:  return "and";
481614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj      case Aalu_OR:   return "or";
482614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj      case Aalu_XOR:  return "xor";
4837de0d3c800437fbd82c59d57d156f4823d67609fsewardj      case Aalu_MUL:  return "imul";
484614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj      default: vpanic("showAMD64AluOp");
485614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj   }
486614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj}
487614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj
48855085f8680acc89d727e321f3b34cae1a8c4093aflorianconst HChar* showAMD64ShiftOp ( AMD64ShiftOp op ) {
4898258a8c9f2e0ba23e79e322102fa6d0c354436f1sewardj   switch (op) {
4908258a8c9f2e0ba23e79e322102fa6d0c354436f1sewardj      case Ash_SHL: return "shl";
4918258a8c9f2e0ba23e79e322102fa6d0c354436f1sewardj      case Ash_SHR: return "shr";
4928258a8c9f2e0ba23e79e322102fa6d0c354436f1sewardj      case Ash_SAR: return "sar";
4938258a8c9f2e0ba23e79e322102fa6d0c354436f1sewardj      default: vpanic("showAMD64ShiftOp");
4948258a8c9f2e0ba23e79e322102fa6d0c354436f1sewardj   }
4958258a8c9f2e0ba23e79e322102fa6d0c354436f1sewardj}
4968258a8c9f2e0ba23e79e322102fa6d0c354436f1sewardj
49755085f8680acc89d727e321f3b34cae1a8c4093aflorianconst HChar* showA87FpOp ( A87FpOp op ) {
49825a858136df4cbea0055c20aa7035d25fd40ee89sewardj   switch (op) {
49925a858136df4cbea0055c20aa7035d25fd40ee89sewardj      case Afp_SCALE:  return "scale";
50025a858136df4cbea0055c20aa7035d25fd40ee89sewardj      case Afp_ATAN:   return "atan";
50125a858136df4cbea0055c20aa7035d25fd40ee89sewardj      case Afp_YL2X:   return "yl2x";
5025e205372f0023f11eb756ee38de40a065b0681c1sewardj      case Afp_YL2XP1: return "yl2xp1";
503f4c803b0947e7534809589cba8007851d78c7a2esewardj      case Afp_PREM:   return "prem";
5044970e4e219cb92ef15de742d102c537ea33d5430sewardj      case Afp_PREM1:  return "prem1";
50525a858136df4cbea0055c20aa7035d25fd40ee89sewardj      case Afp_SQRT:   return "sqrt";
50625a858136df4cbea0055c20aa7035d25fd40ee89sewardj      case Afp_SIN:    return "sin";
50725a858136df4cbea0055c20aa7035d25fd40ee89sewardj      case Afp_COS:    return "cos";
5085e205372f0023f11eb756ee38de40a065b0681c1sewardj      case Afp_TAN:    return "tan";
50925a858136df4cbea0055c20aa7035d25fd40ee89sewardj      case Afp_ROUND:  return "round";
51025a858136df4cbea0055c20aa7035d25fd40ee89sewardj      case Afp_2XM1:   return "2xm1";
51125a858136df4cbea0055c20aa7035d25fd40ee89sewardj      default: vpanic("showA87FpOp");
51225a858136df4cbea0055c20aa7035d25fd40ee89sewardj   }
51325a858136df4cbea0055c20aa7035d25fd40ee89sewardj}
5141001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj
51555085f8680acc89d727e321f3b34cae1a8c4093aflorianconst HChar* showAMD64SseOp ( AMD64SseOp op ) {
5161001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj   switch (op) {
5171830386e7b10430c0c3630123a82d8bcf0a071e7sewardj      case Asse_MOV:      return "movups";
5181001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj      case Asse_ADDF:     return "add";
5191001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj      case Asse_SUBF:     return "sub";
5201001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj      case Asse_MULF:     return "mul";
5211001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj      case Asse_DIVF:     return "div";
5221a01e65f9993d97095c2af463e98674a091834casewardj      case Asse_MAXF:     return "max";
5231a01e65f9993d97095c2af463e98674a091834casewardj      case Asse_MINF:     return "min";
5248d965316c72c2392f670dcdfa127547ec77c7e56sewardj      case Asse_CMPEQF:   return "cmpFeq";
5258d965316c72c2392f670dcdfa127547ec77c7e56sewardj      case Asse_CMPLTF:   return "cmpFlt";
5268d965316c72c2392f670dcdfa127547ec77c7e56sewardj      case Asse_CMPLEF:   return "cmpFle";
5278d965316c72c2392f670dcdfa127547ec77c7e56sewardj      case Asse_CMPUNF:   return "cmpFun";
528a7ba8c47f30998a518cda7e38b4082a9e5c6892esewardj      case Asse_RCPF:     return "rcp";
529a7ba8c47f30998a518cda7e38b4082a9e5c6892esewardj      case Asse_RSQRTF:   return "rsqrt";
5301830386e7b10430c0c3630123a82d8bcf0a071e7sewardj      case Asse_SQRTF:    return "sqrt";
5311001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj      case Asse_AND:      return "and";
5321001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj      case Asse_OR:       return "or";
5331001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj      case Asse_XOR:      return "xor";
5341001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj      case Asse_ANDN:     return "andn";
535976285992e00e9b3656f08d0e08e62e65ec6a29fsewardj      case Asse_ADD8:     return "paddb";
536976285992e00e9b3656f08d0e08e62e65ec6a29fsewardj      case Asse_ADD16:    return "paddw";
537976285992e00e9b3656f08d0e08e62e65ec6a29fsewardj      case Asse_ADD32:    return "paddd";
53809717341a0c364814e35bf405e61399d0e45fa7csewardj      case Asse_ADD64:    return "paddq";
5395992bd07a3237cae1c22f6c93c43730e6447350csewardj      case Asse_QADD8U:   return "paddusb";
5405992bd07a3237cae1c22f6c93c43730e6447350csewardj      case Asse_QADD16U:  return "paddusw";
5415992bd07a3237cae1c22f6c93c43730e6447350csewardj      case Asse_QADD8S:   return "paddsb";
5425992bd07a3237cae1c22f6c93c43730e6447350csewardj      case Asse_QADD16S:  return "paddsw";
543976285992e00e9b3656f08d0e08e62e65ec6a29fsewardj      case Asse_SUB8:     return "psubb";
544976285992e00e9b3656f08d0e08e62e65ec6a29fsewardj      case Asse_SUB16:    return "psubw";
545976285992e00e9b3656f08d0e08e62e65ec6a29fsewardj      case Asse_SUB32:    return "psubd";
54609717341a0c364814e35bf405e61399d0e45fa7csewardj      case Asse_SUB64:    return "psubq";
547976285992e00e9b3656f08d0e08e62e65ec6a29fsewardj      case Asse_QSUB8U:   return "psubusb";
548976285992e00e9b3656f08d0e08e62e65ec6a29fsewardj      case Asse_QSUB16U:  return "psubusw";
549976285992e00e9b3656f08d0e08e62e65ec6a29fsewardj      case Asse_QSUB8S:   return "psubsb";
550976285992e00e9b3656f08d0e08e62e65ec6a29fsewardj      case Asse_QSUB16S:  return "psubsw";
551adffcef004712e8afc6a7d87b30ef90e4685df40sewardj      case Asse_MUL16:    return "pmullw";
552adffcef004712e8afc6a7d87b30ef90e4685df40sewardj      case Asse_MULHI16U: return "pmulhuw";
553adffcef004712e8afc6a7d87b30ef90e4685df40sewardj      case Asse_MULHI16S: return "pmulhw";
5545992bd07a3237cae1c22f6c93c43730e6447350csewardj      case Asse_AVG8U:    return "pavgb";
5555992bd07a3237cae1c22f6c93c43730e6447350csewardj      case Asse_AVG16U:   return "pavgw";
556adffcef004712e8afc6a7d87b30ef90e4685df40sewardj      case Asse_MAX16S:   return "pmaxw";
557adffcef004712e8afc6a7d87b30ef90e4685df40sewardj      case Asse_MAX8U:    return "pmaxub";
558adffcef004712e8afc6a7d87b30ef90e4685df40sewardj      case Asse_MIN16S:   return "pminw";
559adffcef004712e8afc6a7d87b30ef90e4685df40sewardj      case Asse_MIN8U:    return "pminub";
5605992bd07a3237cae1c22f6c93c43730e6447350csewardj      case Asse_CMPEQ8:   return "pcmpeqb";
5615992bd07a3237cae1c22f6c93c43730e6447350csewardj      case Asse_CMPEQ16:  return "pcmpeqw";
56209717341a0c364814e35bf405e61399d0e45fa7csewardj      case Asse_CMPEQ32:  return "pcmpeqd";
5635992bd07a3237cae1c22f6c93c43730e6447350csewardj      case Asse_CMPGT8S:  return "pcmpgtb";
5645992bd07a3237cae1c22f6c93c43730e6447350csewardj      case Asse_CMPGT16S: return "pcmpgtw";
5655992bd07a3237cae1c22f6c93c43730e6447350csewardj      case Asse_CMPGT32S: return "pcmpgtd";
566adffcef004712e8afc6a7d87b30ef90e4685df40sewardj      case Asse_SHL16:    return "psllw";
567adffcef004712e8afc6a7d87b30ef90e4685df40sewardj      case Asse_SHL32:    return "pslld";
568adffcef004712e8afc6a7d87b30ef90e4685df40sewardj      case Asse_SHL64:    return "psllq";
569adffcef004712e8afc6a7d87b30ef90e4685df40sewardj      case Asse_SHR16:    return "psrlw";
570adffcef004712e8afc6a7d87b30ef90e4685df40sewardj      case Asse_SHR32:    return "psrld";
57109717341a0c364814e35bf405e61399d0e45fa7csewardj      case Asse_SHR64:    return "psrlq";
572adffcef004712e8afc6a7d87b30ef90e4685df40sewardj      case Asse_SAR16:    return "psraw";
573adffcef004712e8afc6a7d87b30ef90e4685df40sewardj      case Asse_SAR32:    return "psrad";
574976285992e00e9b3656f08d0e08e62e65ec6a29fsewardj      case Asse_PACKSSD:  return "packssdw";
575976285992e00e9b3656f08d0e08e62e65ec6a29fsewardj      case Asse_PACKSSW:  return "packsswb";
576976285992e00e9b3656f08d0e08e62e65ec6a29fsewardj      case Asse_PACKUSW:  return "packuswb";
577976285992e00e9b3656f08d0e08e62e65ec6a29fsewardj      case Asse_UNPCKHB:  return "punpckhb";
578976285992e00e9b3656f08d0e08e62e65ec6a29fsewardj      case Asse_UNPCKHW:  return "punpckhw";
579976285992e00e9b3656f08d0e08e62e65ec6a29fsewardj      case Asse_UNPCKHD:  return "punpckhd";
580976285992e00e9b3656f08d0e08e62e65ec6a29fsewardj      case Asse_UNPCKHQ:  return "punpckhq";
581976285992e00e9b3656f08d0e08e62e65ec6a29fsewardj      case Asse_UNPCKLB:  return "punpcklb";
582976285992e00e9b3656f08d0e08e62e65ec6a29fsewardj      case Asse_UNPCKLW:  return "punpcklw";
583976285992e00e9b3656f08d0e08e62e65ec6a29fsewardj      case Asse_UNPCKLD:  return "punpckld";
584976285992e00e9b3656f08d0e08e62e65ec6a29fsewardj      case Asse_UNPCKLQ:  return "punpcklq";
5851001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj      default: vpanic("showAMD64SseOp");
5861001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj   }
5871001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj}
588614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj
589813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardjAMD64Instr* AMD64Instr_Imm64 ( ULong imm64, HReg dst ) {
590d8e3ecaede8eccf5bc7be2a55d99a188a07b0a34florian   AMD64Instr* i      = LibVEX_Alloc_inline(sizeof(AMD64Instr));
591813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj   i->tag             = Ain_Imm64;
592813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj   i->Ain.Imm64.imm64 = imm64;
593813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj   i->Ain.Imm64.dst   = dst;
594813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj   return i;
595813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj}
596614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardjAMD64Instr* AMD64Instr_Alu64R ( AMD64AluOp op, AMD64RMI* src, HReg dst ) {
597d8e3ecaede8eccf5bc7be2a55d99a188a07b0a34florian   AMD64Instr* i     = LibVEX_Alloc_inline(sizeof(AMD64Instr));
598614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj   i->tag            = Ain_Alu64R;
599614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj   i->Ain.Alu64R.op  = op;
600614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj   i->Ain.Alu64R.src = src;
601614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj   i->Ain.Alu64R.dst = dst;
602614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj   return i;
603614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj}
604f67eadf04f5150178e589060f03381300d28e540sewardjAMD64Instr* AMD64Instr_Alu64M ( AMD64AluOp op, AMD64RI* src, AMD64AMode* dst ) {
605d8e3ecaede8eccf5bc7be2a55d99a188a07b0a34florian   AMD64Instr* i     = LibVEX_Alloc_inline(sizeof(AMD64Instr));
606f67eadf04f5150178e589060f03381300d28e540sewardj   i->tag            = Ain_Alu64M;
607f67eadf04f5150178e589060f03381300d28e540sewardj   i->Ain.Alu64M.op  = op;
608f67eadf04f5150178e589060f03381300d28e540sewardj   i->Ain.Alu64M.src = src;
609f67eadf04f5150178e589060f03381300d28e540sewardj   i->Ain.Alu64M.dst = dst;
610f67eadf04f5150178e589060f03381300d28e540sewardj   vassert(op != Aalu_MUL);
611f67eadf04f5150178e589060f03381300d28e540sewardj   return i;
612f67eadf04f5150178e589060f03381300d28e540sewardj}
613501a339ba08d28f30eb96d17b3f5bbe996ca6a4dsewardjAMD64Instr* AMD64Instr_Sh64 ( AMD64ShiftOp op, UInt src, HReg dst ) {
614d8e3ecaede8eccf5bc7be2a55d99a188a07b0a34florian   AMD64Instr* i   = LibVEX_Alloc_inline(sizeof(AMD64Instr));
6158258a8c9f2e0ba23e79e322102fa6d0c354436f1sewardj   i->tag          = Ain_Sh64;
6168258a8c9f2e0ba23e79e322102fa6d0c354436f1sewardj   i->Ain.Sh64.op  = op;
6178258a8c9f2e0ba23e79e322102fa6d0c354436f1sewardj   i->Ain.Sh64.src = src;
6188258a8c9f2e0ba23e79e322102fa6d0c354436f1sewardj   i->Ain.Sh64.dst = dst;
6198258a8c9f2e0ba23e79e322102fa6d0c354436f1sewardj   return i;
6208258a8c9f2e0ba23e79e322102fa6d0c354436f1sewardj}
621501a339ba08d28f30eb96d17b3f5bbe996ca6a4dsewardjAMD64Instr* AMD64Instr_Test64 ( UInt imm32, HReg dst ) {
622d8e3ecaede8eccf5bc7be2a55d99a188a07b0a34florian   AMD64Instr* i       = LibVEX_Alloc_inline(sizeof(AMD64Instr));
623501a339ba08d28f30eb96d17b3f5bbe996ca6a4dsewardj   i->tag              = Ain_Test64;
624501a339ba08d28f30eb96d17b3f5bbe996ca6a4dsewardj   i->Ain.Test64.imm32 = imm32;
625501a339ba08d28f30eb96d17b3f5bbe996ca6a4dsewardj   i->Ain.Test64.dst   = dst;
62605b3b6a0474ba57b4dbd15ac26d857197cdc87fcsewardj   return i;
62705b3b6a0474ba57b4dbd15ac26d857197cdc87fcsewardj}
628501a339ba08d28f30eb96d17b3f5bbe996ca6a4dsewardjAMD64Instr* AMD64Instr_Unary64 ( AMD64UnaryOp op, HReg dst ) {
629d8e3ecaede8eccf5bc7be2a55d99a188a07b0a34florian   AMD64Instr* i      = LibVEX_Alloc_inline(sizeof(AMD64Instr));
630d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj   i->tag             = Ain_Unary64;
631d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj   i->Ain.Unary64.op  = op;
632d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj   i->Ain.Unary64.dst = dst;
633d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj   return i;
634d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj}
6356ce1a23b27d1729da9d705abd15b2007dce8daecsewardjAMD64Instr* AMD64Instr_Lea64 ( AMD64AMode* am, HReg dst ) {
636d8e3ecaede8eccf5bc7be2a55d99a188a07b0a34florian   AMD64Instr* i      = LibVEX_Alloc_inline(sizeof(AMD64Instr));
6376ce1a23b27d1729da9d705abd15b2007dce8daecsewardj   i->tag             = Ain_Lea64;
6386ce1a23b27d1729da9d705abd15b2007dce8daecsewardj   i->Ain.Lea64.am    = am;
6396ce1a23b27d1729da9d705abd15b2007dce8daecsewardj   i->Ain.Lea64.dst   = dst;
6406ce1a23b27d1729da9d705abd15b2007dce8daecsewardj   return i;
6416ce1a23b27d1729da9d705abd15b2007dce8daecsewardj}
6429cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardjAMD64Instr* AMD64Instr_Alu32R ( AMD64AluOp op, AMD64RMI* src, HReg dst ) {
643d8e3ecaede8eccf5bc7be2a55d99a188a07b0a34florian   AMD64Instr* i     = LibVEX_Alloc_inline(sizeof(AMD64Instr));
6449cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj   i->tag            = Ain_Alu32R;
6459cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj   i->Ain.Alu32R.op  = op;
6469cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj   i->Ain.Alu32R.src = src;
6479cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj   i->Ain.Alu32R.dst = dst;
6489cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj   switch (op) {
6499cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj      case Aalu_ADD: case Aalu_SUB: case Aalu_CMP:
6509cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj      case Aalu_AND: case Aalu_OR:  case Aalu_XOR: break;
6519cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj      default: vassert(0);
6529cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj   }
6539cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj   return i;
6549cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj}
655501a339ba08d28f30eb96d17b3f5bbe996ca6a4dsewardjAMD64Instr* AMD64Instr_MulL ( Bool syned, AMD64RM* src ) {
656d8e3ecaede8eccf5bc7be2a55d99a188a07b0a34florian   AMD64Instr* i     = LibVEX_Alloc_inline(sizeof(AMD64Instr));
6579b96767debeeb1f78378f0e7e295fe6762c64002sewardj   i->tag            = Ain_MulL;
6589b96767debeeb1f78378f0e7e295fe6762c64002sewardj   i->Ain.MulL.syned = syned;
6599b96767debeeb1f78378f0e7e295fe6762c64002sewardj   i->Ain.MulL.src   = src;
6609b96767debeeb1f78378f0e7e295fe6762c64002sewardj   return i;
6619b96767debeeb1f78378f0e7e295fe6762c64002sewardj}
6627de0d3c800437fbd82c59d57d156f4823d67609fsewardjAMD64Instr* AMD64Instr_Div ( Bool syned, Int sz, AMD64RM* src ) {
663d8e3ecaede8eccf5bc7be2a55d99a188a07b0a34florian   AMD64Instr* i     = LibVEX_Alloc_inline(sizeof(AMD64Instr));
6647de0d3c800437fbd82c59d57d156f4823d67609fsewardj   i->tag            = Ain_Div;
6657de0d3c800437fbd82c59d57d156f4823d67609fsewardj   i->Ain.Div.syned  = syned;
6667de0d3c800437fbd82c59d57d156f4823d67609fsewardj   i->Ain.Div.sz     = sz;
6677de0d3c800437fbd82c59d57d156f4823d67609fsewardj   i->Ain.Div.src    = src;
6687de0d3c800437fbd82c59d57d156f4823d67609fsewardj   vassert(sz == 4 || sz == 8);
6697de0d3c800437fbd82c59d57d156f4823d67609fsewardj   return i;
6707de0d3c800437fbd82c59d57d156f4823d67609fsewardj}
6711001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardjAMD64Instr* AMD64Instr_Push( AMD64RMI* src ) {
672d8e3ecaede8eccf5bc7be2a55d99a188a07b0a34florian   AMD64Instr* i   = LibVEX_Alloc_inline(sizeof(AMD64Instr));
6731001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj   i->tag          = Ain_Push;
6741001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj   i->Ain.Push.src = src;
6751001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj   return i;
6761001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj}
677cfe046e178666280b87da998b1b52ecda03ecd89sewardjAMD64Instr* AMD64Instr_Call ( AMD64CondCode cond, Addr64 target, Int regparms,
678cfe046e178666280b87da998b1b52ecda03ecd89sewardj                              RetLoc rloc ) {
679d8e3ecaede8eccf5bc7be2a55d99a188a07b0a34florian   AMD64Instr* i        = LibVEX_Alloc_inline(sizeof(AMD64Instr));
68005b3b6a0474ba57b4dbd15ac26d857197cdc87fcsewardj   i->tag               = Ain_Call;
68105b3b6a0474ba57b4dbd15ac26d857197cdc87fcsewardj   i->Ain.Call.cond     = cond;
68205b3b6a0474ba57b4dbd15ac26d857197cdc87fcsewardj   i->Ain.Call.target   = target;
68305b3b6a0474ba57b4dbd15ac26d857197cdc87fcsewardj   i->Ain.Call.regparms = regparms;
684cfe046e178666280b87da998b1b52ecda03ecd89sewardj   i->Ain.Call.rloc     = rloc;
68505b3b6a0474ba57b4dbd15ac26d857197cdc87fcsewardj   vassert(regparms >= 0 && regparms <= 6);
68674142b8c8d5d3b3db17d744f5d5fb80f548bcf74sewardj   vassert(is_sane_RetLoc(rloc));
68705b3b6a0474ba57b4dbd15ac26d857197cdc87fcsewardj   return i;
68805b3b6a0474ba57b4dbd15ac26d857197cdc87fcsewardj}
689c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj
690c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardjAMD64Instr* AMD64Instr_XDirect ( Addr64 dstGA, AMD64AMode* amRIP,
691c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj                                 AMD64CondCode cond, Bool toFastEP ) {
692d8e3ecaede8eccf5bc7be2a55d99a188a07b0a34florian   AMD64Instr* i           = LibVEX_Alloc_inline(sizeof(AMD64Instr));
693c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   i->tag                  = Ain_XDirect;
694c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   i->Ain.XDirect.dstGA    = dstGA;
695c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   i->Ain.XDirect.amRIP    = amRIP;
696c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   i->Ain.XDirect.cond     = cond;
697c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   i->Ain.XDirect.toFastEP = toFastEP;
698c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   return i;
699c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj}
700c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardjAMD64Instr* AMD64Instr_XIndir ( HReg dstGA, AMD64AMode* amRIP,
701c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj                                AMD64CondCode cond ) {
702d8e3ecaede8eccf5bc7be2a55d99a188a07b0a34florian   AMD64Instr* i       = LibVEX_Alloc_inline(sizeof(AMD64Instr));
703c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   i->tag              = Ain_XIndir;
704c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   i->Ain.XIndir.dstGA = dstGA;
705c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   i->Ain.XIndir.amRIP = amRIP;
706c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   i->Ain.XIndir.cond  = cond;
707c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   return i;
708c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj}
709c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardjAMD64Instr* AMD64Instr_XAssisted ( HReg dstGA, AMD64AMode* amRIP,
710c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj                                   AMD64CondCode cond, IRJumpKind jk ) {
711d8e3ecaede8eccf5bc7be2a55d99a188a07b0a34florian   AMD64Instr* i          = LibVEX_Alloc_inline(sizeof(AMD64Instr));
712c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   i->tag                 = Ain_XAssisted;
713c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   i->Ain.XAssisted.dstGA = dstGA;
714c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   i->Ain.XAssisted.amRIP = amRIP;
715c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   i->Ain.XAssisted.cond  = cond;
716c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   i->Ain.XAssisted.jk    = jk;
717f67eadf04f5150178e589060f03381300d28e540sewardj   return i;
718f67eadf04f5150178e589060f03381300d28e540sewardj}
719c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj
720e357c67787b7429f85a030ee5fbedf33173b5656sewardjAMD64Instr* AMD64Instr_CMov64 ( AMD64CondCode cond, HReg src, HReg dst ) {
721d8e3ecaede8eccf5bc7be2a55d99a188a07b0a34florian   AMD64Instr* i      = LibVEX_Alloc_inline(sizeof(AMD64Instr));
72205b3b6a0474ba57b4dbd15ac26d857197cdc87fcsewardj   i->tag             = Ain_CMov64;
72305b3b6a0474ba57b4dbd15ac26d857197cdc87fcsewardj   i->Ain.CMov64.cond = cond;
72405b3b6a0474ba57b4dbd15ac26d857197cdc87fcsewardj   i->Ain.CMov64.src  = src;
72505b3b6a0474ba57b4dbd15ac26d857197cdc87fcsewardj   i->Ain.CMov64.dst  = dst;
72605b3b6a0474ba57b4dbd15ac26d857197cdc87fcsewardj   vassert(cond != Acc_ALWAYS);
72705b3b6a0474ba57b4dbd15ac26d857197cdc87fcsewardj   return i;
72805b3b6a0474ba57b4dbd15ac26d857197cdc87fcsewardj}
729bdea5508b371d394c81b91464fa8df767010d4dasewardjAMD64Instr* AMD64Instr_CLoad ( AMD64CondCode cond, UChar szB,
730bdea5508b371d394c81b91464fa8df767010d4dasewardj                               AMD64AMode* addr, HReg dst ) {
731d8e3ecaede8eccf5bc7be2a55d99a188a07b0a34florian   AMD64Instr* i     = LibVEX_Alloc_inline(sizeof(AMD64Instr));
732bdea5508b371d394c81b91464fa8df767010d4dasewardj   i->tag            = Ain_CLoad;
733bdea5508b371d394c81b91464fa8df767010d4dasewardj   i->Ain.CLoad.cond = cond;
734bdea5508b371d394c81b91464fa8df767010d4dasewardj   i->Ain.CLoad.szB  = szB;
735bdea5508b371d394c81b91464fa8df767010d4dasewardj   i->Ain.CLoad.addr = addr;
736bdea5508b371d394c81b91464fa8df767010d4dasewardj   i->Ain.CLoad.dst  = dst;
7376f1ec58d9806064dea0000e4b543aacded9b11easewardj   vassert(cond != Acc_ALWAYS && (szB == 4 || szB == 8));
7386f1ec58d9806064dea0000e4b543aacded9b11easewardj   return i;
7396f1ec58d9806064dea0000e4b543aacded9b11easewardj}
7406f1ec58d9806064dea0000e4b543aacded9b11easewardjAMD64Instr* AMD64Instr_CStore ( AMD64CondCode cond, UChar szB,
7416f1ec58d9806064dea0000e4b543aacded9b11easewardj                                HReg src, AMD64AMode* addr ) {
742d8e3ecaede8eccf5bc7be2a55d99a188a07b0a34florian   AMD64Instr* i      = LibVEX_Alloc_inline(sizeof(AMD64Instr));
7436f1ec58d9806064dea0000e4b543aacded9b11easewardj   i->tag             = Ain_CStore;
7446f1ec58d9806064dea0000e4b543aacded9b11easewardj   i->Ain.CStore.cond = cond;
7456f1ec58d9806064dea0000e4b543aacded9b11easewardj   i->Ain.CStore.szB  = szB;
7466f1ec58d9806064dea0000e4b543aacded9b11easewardj   i->Ain.CStore.src  = src;
7476f1ec58d9806064dea0000e4b543aacded9b11easewardj   i->Ain.CStore.addr = addr;
7486f1ec58d9806064dea0000e4b543aacded9b11easewardj   vassert(cond != Acc_ALWAYS && (szB == 4 || szB == 8));
749bdea5508b371d394c81b91464fa8df767010d4dasewardj   return i;
750bdea5508b371d394c81b91464fa8df767010d4dasewardj}
751ca257bc572147c1a9c7d9a2e81237125a35ff25dsewardjAMD64Instr* AMD64Instr_MovxLQ ( Bool syned, HReg src, HReg dst ) {
752d8e3ecaede8eccf5bc7be2a55d99a188a07b0a34florian   AMD64Instr* i       = LibVEX_Alloc_inline(sizeof(AMD64Instr));
753ca257bc572147c1a9c7d9a2e81237125a35ff25dsewardj   i->tag              = Ain_MovxLQ;
754ca257bc572147c1a9c7d9a2e81237125a35ff25dsewardj   i->Ain.MovxLQ.syned = syned;
755ca257bc572147c1a9c7d9a2e81237125a35ff25dsewardj   i->Ain.MovxLQ.src   = src;
756ca257bc572147c1a9c7d9a2e81237125a35ff25dsewardj   i->Ain.MovxLQ.dst   = dst;
757f67eadf04f5150178e589060f03381300d28e540sewardj   return i;
758f67eadf04f5150178e589060f03381300d28e540sewardj}
7598258a8c9f2e0ba23e79e322102fa6d0c354436f1sewardjAMD64Instr* AMD64Instr_LoadEX ( UChar szSmall, Bool syned,
7608258a8c9f2e0ba23e79e322102fa6d0c354436f1sewardj                                AMD64AMode* src, HReg dst ) {
761d8e3ecaede8eccf5bc7be2a55d99a188a07b0a34florian   AMD64Instr* i         = LibVEX_Alloc_inline(sizeof(AMD64Instr));
7628258a8c9f2e0ba23e79e322102fa6d0c354436f1sewardj   i->tag                = Ain_LoadEX;
7638258a8c9f2e0ba23e79e322102fa6d0c354436f1sewardj   i->Ain.LoadEX.szSmall = szSmall;
7648258a8c9f2e0ba23e79e322102fa6d0c354436f1sewardj   i->Ain.LoadEX.syned   = syned;
7658258a8c9f2e0ba23e79e322102fa6d0c354436f1sewardj   i->Ain.LoadEX.src     = src;
7668258a8c9f2e0ba23e79e322102fa6d0c354436f1sewardj   i->Ain.LoadEX.dst     = dst;
7678258a8c9f2e0ba23e79e322102fa6d0c354436f1sewardj   vassert(szSmall == 1 || szSmall == 2 || szSmall == 4);
7688258a8c9f2e0ba23e79e322102fa6d0c354436f1sewardj   return i;
7698258a8c9f2e0ba23e79e322102fa6d0c354436f1sewardj}
770f67eadf04f5150178e589060f03381300d28e540sewardjAMD64Instr* AMD64Instr_Store ( UChar sz, HReg src, AMD64AMode* dst ) {
771d8e3ecaede8eccf5bc7be2a55d99a188a07b0a34florian   AMD64Instr* i    = LibVEX_Alloc_inline(sizeof(AMD64Instr));
772f67eadf04f5150178e589060f03381300d28e540sewardj   i->tag           = Ain_Store;
773f67eadf04f5150178e589060f03381300d28e540sewardj   i->Ain.Store.sz  = sz;
774f67eadf04f5150178e589060f03381300d28e540sewardj   i->Ain.Store.src = src;
775f67eadf04f5150178e589060f03381300d28e540sewardj   i->Ain.Store.dst = dst;
776f67eadf04f5150178e589060f03381300d28e540sewardj   vassert(sz == 1 || sz == 2 || sz == 4);
777f67eadf04f5150178e589060f03381300d28e540sewardj   return i;
778f67eadf04f5150178e589060f03381300d28e540sewardj}
779a5bd0aff6eda3e7c312f51ae6bc742ea62b5d404sewardjAMD64Instr* AMD64Instr_Set64 ( AMD64CondCode cond, HReg dst ) {
780d8e3ecaede8eccf5bc7be2a55d99a188a07b0a34florian   AMD64Instr* i     = LibVEX_Alloc_inline(sizeof(AMD64Instr));
781a5bd0aff6eda3e7c312f51ae6bc742ea62b5d404sewardj   i->tag            = Ain_Set64;
782a5bd0aff6eda3e7c312f51ae6bc742ea62b5d404sewardj   i->Ain.Set64.cond = cond;
783a5bd0aff6eda3e7c312f51ae6bc742ea62b5d404sewardj   i->Ain.Set64.dst  = dst;
784a5bd0aff6eda3e7c312f51ae6bc742ea62b5d404sewardj   return i;
785a5bd0aff6eda3e7c312f51ae6bc742ea62b5d404sewardj}
786f53b7359a342e7d79090615169c6583a1a75fbcesewardjAMD64Instr* AMD64Instr_Bsfr64 ( Bool isFwds, HReg src, HReg dst ) {
787d8e3ecaede8eccf5bc7be2a55d99a188a07b0a34florian   AMD64Instr* i        = LibVEX_Alloc_inline(sizeof(AMD64Instr));
788f53b7359a342e7d79090615169c6583a1a75fbcesewardj   i->tag               = Ain_Bsfr64;
789f53b7359a342e7d79090615169c6583a1a75fbcesewardj   i->Ain.Bsfr64.isFwds = isFwds;
790f53b7359a342e7d79090615169c6583a1a75fbcesewardj   i->Ain.Bsfr64.src    = src;
791f53b7359a342e7d79090615169c6583a1a75fbcesewardj   i->Ain.Bsfr64.dst    = dst;
792f53b7359a342e7d79090615169c6583a1a75fbcesewardj   return i;
793f53b7359a342e7d79090615169c6583a1a75fbcesewardj}
794e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardjAMD64Instr* AMD64Instr_MFence ( void ) {
795d8e3ecaede8eccf5bc7be2a55d99a188a07b0a34florian   AMD64Instr* i = LibVEX_Alloc_inline(sizeof(AMD64Instr));
79625a858136df4cbea0055c20aa7035d25fd40ee89sewardj   i->tag        = Ain_MFence;
79725a858136df4cbea0055c20aa7035d25fd40ee89sewardj   return i;
79825a858136df4cbea0055c20aa7035d25fd40ee89sewardj}
799e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardjAMD64Instr* AMD64Instr_ACAS ( AMD64AMode* addr, UChar sz ) {
800d8e3ecaede8eccf5bc7be2a55d99a188a07b0a34florian   AMD64Instr* i    = LibVEX_Alloc_inline(sizeof(AMD64Instr));
801e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj   i->tag           = Ain_ACAS;
802e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj   i->Ain.ACAS.addr = addr;
803e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj   i->Ain.ACAS.sz   = sz;
804e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj   vassert(sz == 8 || sz == 4 || sz == 2 || sz == 1);
805e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj   return i;
806e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj}
807e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardjAMD64Instr* AMD64Instr_DACAS ( AMD64AMode* addr, UChar sz ) {
808d8e3ecaede8eccf5bc7be2a55d99a188a07b0a34florian   AMD64Instr* i     = LibVEX_Alloc_inline(sizeof(AMD64Instr));
809e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj   i->tag            = Ain_DACAS;
810e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj   i->Ain.DACAS.addr = addr;
811e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj   i->Ain.DACAS.sz   = sz;
812e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj   vassert(sz == 8 || sz == 4);
813e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj   return i;
814e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj}
815e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj
81625a858136df4cbea0055c20aa7035d25fd40ee89sewardjAMD64Instr* AMD64Instr_A87Free ( Int nregs )
81725a858136df4cbea0055c20aa7035d25fd40ee89sewardj{
818d8e3ecaede8eccf5bc7be2a55d99a188a07b0a34florian   AMD64Instr* i        = LibVEX_Alloc_inline(sizeof(AMD64Instr));
81925a858136df4cbea0055c20aa7035d25fd40ee89sewardj   i->tag               = Ain_A87Free;
82025a858136df4cbea0055c20aa7035d25fd40ee89sewardj   i->Ain.A87Free.nregs = nregs;
82125a858136df4cbea0055c20aa7035d25fd40ee89sewardj   vassert(nregs >= 1 && nregs <= 7);
82225a858136df4cbea0055c20aa7035d25fd40ee89sewardj   return i;
82325a858136df4cbea0055c20aa7035d25fd40ee89sewardj}
824d15b597a8a006b3fe136cbf6cdf5b46ed532a4d8sewardjAMD64Instr* AMD64Instr_A87PushPop ( AMD64AMode* addr, Bool isPush, UChar szB )
82525a858136df4cbea0055c20aa7035d25fd40ee89sewardj{
826d8e3ecaede8eccf5bc7be2a55d99a188a07b0a34florian   AMD64Instr* i            = LibVEX_Alloc_inline(sizeof(AMD64Instr));
82725a858136df4cbea0055c20aa7035d25fd40ee89sewardj   i->tag                   = Ain_A87PushPop;
82825a858136df4cbea0055c20aa7035d25fd40ee89sewardj   i->Ain.A87PushPop.addr   = addr;
82925a858136df4cbea0055c20aa7035d25fd40ee89sewardj   i->Ain.A87PushPop.isPush = isPush;
830d15b597a8a006b3fe136cbf6cdf5b46ed532a4d8sewardj   i->Ain.A87PushPop.szB    = szB;
831d15b597a8a006b3fe136cbf6cdf5b46ed532a4d8sewardj   vassert(szB == 8 || szB == 4);
83225a858136df4cbea0055c20aa7035d25fd40ee89sewardj   return i;
83325a858136df4cbea0055c20aa7035d25fd40ee89sewardj}
83425a858136df4cbea0055c20aa7035d25fd40ee89sewardjAMD64Instr* AMD64Instr_A87FpOp ( A87FpOp op )
83525a858136df4cbea0055c20aa7035d25fd40ee89sewardj{
836d8e3ecaede8eccf5bc7be2a55d99a188a07b0a34florian   AMD64Instr* i     = LibVEX_Alloc_inline(sizeof(AMD64Instr));
83725a858136df4cbea0055c20aa7035d25fd40ee89sewardj   i->tag            = Ain_A87FpOp;
83825a858136df4cbea0055c20aa7035d25fd40ee89sewardj   i->Ain.A87FpOp.op = op;
83925a858136df4cbea0055c20aa7035d25fd40ee89sewardj   return i;
84025a858136df4cbea0055c20aa7035d25fd40ee89sewardj}
84125a858136df4cbea0055c20aa7035d25fd40ee89sewardjAMD64Instr* AMD64Instr_A87LdCW ( AMD64AMode* addr )
84225a858136df4cbea0055c20aa7035d25fd40ee89sewardj{
843d8e3ecaede8eccf5bc7be2a55d99a188a07b0a34florian   AMD64Instr* i       = LibVEX_Alloc_inline(sizeof(AMD64Instr));
84425a858136df4cbea0055c20aa7035d25fd40ee89sewardj   i->tag              = Ain_A87LdCW;
84525a858136df4cbea0055c20aa7035d25fd40ee89sewardj   i->Ain.A87LdCW.addr = addr;
846d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj   return i;
847d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj}
848f4c803b0947e7534809589cba8007851d78c7a2esewardjAMD64Instr* AMD64Instr_A87StSW ( AMD64AMode* addr )
849f4c803b0947e7534809589cba8007851d78c7a2esewardj{
850d8e3ecaede8eccf5bc7be2a55d99a188a07b0a34florian   AMD64Instr* i       = LibVEX_Alloc_inline(sizeof(AMD64Instr));
851f4c803b0947e7534809589cba8007851d78c7a2esewardj   i->tag              = Ain_A87StSW;
852f4c803b0947e7534809589cba8007851d78c7a2esewardj   i->Ain.A87StSW.addr = addr;
853f4c803b0947e7534809589cba8007851d78c7a2esewardj   return i;
854f4c803b0947e7534809589cba8007851d78c7a2esewardj}
8551a01e65f9993d97095c2af463e98674a091834casewardjAMD64Instr* AMD64Instr_LdMXCSR ( AMD64AMode* addr ) {
856d8e3ecaede8eccf5bc7be2a55d99a188a07b0a34florian   AMD64Instr* i         = LibVEX_Alloc_inline(sizeof(AMD64Instr));
8571a01e65f9993d97095c2af463e98674a091834casewardj   i->tag                = Ain_LdMXCSR;
8581a01e65f9993d97095c2af463e98674a091834casewardj   i->Ain.LdMXCSR.addr   = addr;
8591a01e65f9993d97095c2af463e98674a091834casewardj   return i;
8601a01e65f9993d97095c2af463e98674a091834casewardj}
8611830386e7b10430c0c3630123a82d8bcf0a071e7sewardjAMD64Instr* AMD64Instr_SseUComIS ( Int sz, HReg srcL, HReg srcR, HReg dst ) {
862d8e3ecaede8eccf5bc7be2a55d99a188a07b0a34florian   AMD64Instr* i         = LibVEX_Alloc_inline(sizeof(AMD64Instr));
8631830386e7b10430c0c3630123a82d8bcf0a071e7sewardj   i->tag                = Ain_SseUComIS;
86403ccf858efa285d793061359c04fdd0055cd9d31sewardj   i->Ain.SseUComIS.sz   = toUChar(sz);
8651830386e7b10430c0c3630123a82d8bcf0a071e7sewardj   i->Ain.SseUComIS.srcL = srcL;
8661830386e7b10430c0c3630123a82d8bcf0a071e7sewardj   i->Ain.SseUComIS.srcR = srcR;
8671830386e7b10430c0c3630123a82d8bcf0a071e7sewardj   i->Ain.SseUComIS.dst  = dst;
8681830386e7b10430c0c3630123a82d8bcf0a071e7sewardj   vassert(sz == 4 || sz == 8);
8691830386e7b10430c0c3630123a82d8bcf0a071e7sewardj   return i;
8701830386e7b10430c0c3630123a82d8bcf0a071e7sewardj}
8711a01e65f9993d97095c2af463e98674a091834casewardjAMD64Instr* AMD64Instr_SseSI2SF ( Int szS, Int szD, HReg src, HReg dst ) {
872d8e3ecaede8eccf5bc7be2a55d99a188a07b0a34florian   AMD64Instr* i       = LibVEX_Alloc_inline(sizeof(AMD64Instr));
8731a01e65f9993d97095c2af463e98674a091834casewardj   i->tag              = Ain_SseSI2SF;
87403ccf858efa285d793061359c04fdd0055cd9d31sewardj   i->Ain.SseSI2SF.szS = toUChar(szS);
87503ccf858efa285d793061359c04fdd0055cd9d31sewardj   i->Ain.SseSI2SF.szD = toUChar(szD);
8761a01e65f9993d97095c2af463e98674a091834casewardj   i->Ain.SseSI2SF.src = src;
8771a01e65f9993d97095c2af463e98674a091834casewardj   i->Ain.SseSI2SF.dst = dst;
8781a01e65f9993d97095c2af463e98674a091834casewardj   vassert(szS == 4 || szS == 8);
8791a01e65f9993d97095c2af463e98674a091834casewardj   vassert(szD == 4 || szD == 8);
8801a01e65f9993d97095c2af463e98674a091834casewardj   return i;
8811a01e65f9993d97095c2af463e98674a091834casewardj}
8821a01e65f9993d97095c2af463e98674a091834casewardjAMD64Instr* AMD64Instr_SseSF2SI ( Int szS, Int szD, HReg src, HReg dst ) {
883d8e3ecaede8eccf5bc7be2a55d99a188a07b0a34florian   AMD64Instr* i       = LibVEX_Alloc_inline(sizeof(AMD64Instr));
8841a01e65f9993d97095c2af463e98674a091834casewardj   i->tag              = Ain_SseSF2SI;
88503ccf858efa285d793061359c04fdd0055cd9d31sewardj   i->Ain.SseSF2SI.szS = toUChar(szS);
88603ccf858efa285d793061359c04fdd0055cd9d31sewardj   i->Ain.SseSF2SI.szD = toUChar(szD);
8871a01e65f9993d97095c2af463e98674a091834casewardj   i->Ain.SseSF2SI.src = src;
8881a01e65f9993d97095c2af463e98674a091834casewardj   i->Ain.SseSF2SI.dst = dst;
8891a01e65f9993d97095c2af463e98674a091834casewardj   vassert(szS == 4 || szS == 8);
8901a01e65f9993d97095c2af463e98674a091834casewardj   vassert(szD == 4 || szD == 8);
8911a01e65f9993d97095c2af463e98674a091834casewardj   return i;
8921a01e65f9993d97095c2af463e98674a091834casewardj}
8938d965316c72c2392f670dcdfa127547ec77c7e56sewardjAMD64Instr* AMD64Instr_SseSDSS   ( Bool from64, HReg src, HReg dst )
8948d965316c72c2392f670dcdfa127547ec77c7e56sewardj{
895d8e3ecaede8eccf5bc7be2a55d99a188a07b0a34florian   AMD64Instr* i         = LibVEX_Alloc_inline(sizeof(AMD64Instr));
8968d965316c72c2392f670dcdfa127547ec77c7e56sewardj   i->tag                = Ain_SseSDSS;
8978d965316c72c2392f670dcdfa127547ec77c7e56sewardj   i->Ain.SseSDSS.from64 = from64;
8988d965316c72c2392f670dcdfa127547ec77c7e56sewardj   i->Ain.SseSDSS.src    = src;
8998d965316c72c2392f670dcdfa127547ec77c7e56sewardj   i->Ain.SseSDSS.dst    = dst;
9008d965316c72c2392f670dcdfa127547ec77c7e56sewardj   return i;
9018d965316c72c2392f670dcdfa127547ec77c7e56sewardj}
9021830386e7b10430c0c3630123a82d8bcf0a071e7sewardjAMD64Instr* AMD64Instr_SseLdSt ( Bool isLoad, Int sz,
9031830386e7b10430c0c3630123a82d8bcf0a071e7sewardj                                 HReg reg, AMD64AMode* addr ) {
904d8e3ecaede8eccf5bc7be2a55d99a188a07b0a34florian   AMD64Instr* i         = LibVEX_Alloc_inline(sizeof(AMD64Instr));
9051001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj   i->tag                = Ain_SseLdSt;
9061001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj   i->Ain.SseLdSt.isLoad = isLoad;
90703ccf858efa285d793061359c04fdd0055cd9d31sewardj   i->Ain.SseLdSt.sz     = toUChar(sz);
9081001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj   i->Ain.SseLdSt.reg    = reg;
9091001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj   i->Ain.SseLdSt.addr   = addr;
9101830386e7b10430c0c3630123a82d8bcf0a071e7sewardj   vassert(sz == 4 || sz == 8 || sz == 16);
9111001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj   return i;
9121001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj}
91370dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardjAMD64Instr* AMD64Instr_SseCStore ( AMD64CondCode cond,
91470dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj                                   HReg src, AMD64AMode* addr )
91570dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj{
91670dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   AMD64Instr* i         = LibVEX_Alloc_inline(sizeof(AMD64Instr));
91770dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   i->tag                = Ain_SseCStore;
91870dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   i->Ain.SseCStore.cond = cond;
91970dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   i->Ain.SseCStore.src  = src;
92070dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   i->Ain.SseCStore.addr = addr;
92170dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   vassert(cond != Acc_ALWAYS);
92270dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   return i;
92370dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj}
92470dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardjAMD64Instr* AMD64Instr_SseCLoad ( AMD64CondCode cond,
92570dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj                                  AMD64AMode* addr, HReg dst )
92670dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj{
92770dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   AMD64Instr* i        = LibVEX_Alloc_inline(sizeof(AMD64Instr));
92870dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   i->tag               = Ain_SseCLoad;
92970dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   i->Ain.SseCLoad.cond = cond;
93070dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   i->Ain.SseCLoad.addr = addr;
93170dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   i->Ain.SseCLoad.dst  = dst;
93270dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   vassert(cond != Acc_ALWAYS);
93370dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   return i;
93470dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj}
9351001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardjAMD64Instr* AMD64Instr_SseLdzLO  ( Int sz, HReg reg, AMD64AMode* addr )
9361001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj{
937d8e3ecaede8eccf5bc7be2a55d99a188a07b0a34florian   AMD64Instr* i         = LibVEX_Alloc_inline(sizeof(AMD64Instr));
9381001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj   i->tag                = Ain_SseLdzLO;
9391001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj   i->Ain.SseLdzLO.sz    = sz;
9401001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj   i->Ain.SseLdzLO.reg   = reg;
9411001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj   i->Ain.SseLdzLO.addr  = addr;
9421001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj   vassert(sz == 4 || sz == 8);
9431001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj   return i;
9441001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj}
9458d965316c72c2392f670dcdfa127547ec77c7e56sewardjAMD64Instr* AMD64Instr_Sse32Fx4 ( AMD64SseOp op, HReg src, HReg dst ) {
946d8e3ecaede8eccf5bc7be2a55d99a188a07b0a34florian   AMD64Instr* i       = LibVEX_Alloc_inline(sizeof(AMD64Instr));
9478d965316c72c2392f670dcdfa127547ec77c7e56sewardj   i->tag              = Ain_Sse32Fx4;
9488d965316c72c2392f670dcdfa127547ec77c7e56sewardj   i->Ain.Sse32Fx4.op  = op;
9498d965316c72c2392f670dcdfa127547ec77c7e56sewardj   i->Ain.Sse32Fx4.src = src;
9508d965316c72c2392f670dcdfa127547ec77c7e56sewardj   i->Ain.Sse32Fx4.dst = dst;
9518d965316c72c2392f670dcdfa127547ec77c7e56sewardj   vassert(op != Asse_MOV);
9528d965316c72c2392f670dcdfa127547ec77c7e56sewardj   return i;
9538d965316c72c2392f670dcdfa127547ec77c7e56sewardj}
9548d965316c72c2392f670dcdfa127547ec77c7e56sewardjAMD64Instr* AMD64Instr_Sse32FLo ( AMD64SseOp op, HReg src, HReg dst ) {
955d8e3ecaede8eccf5bc7be2a55d99a188a07b0a34florian   AMD64Instr* i       = LibVEX_Alloc_inline(sizeof(AMD64Instr));
9568d965316c72c2392f670dcdfa127547ec77c7e56sewardj   i->tag              = Ain_Sse32FLo;
9578d965316c72c2392f670dcdfa127547ec77c7e56sewardj   i->Ain.Sse32FLo.op  = op;
9588d965316c72c2392f670dcdfa127547ec77c7e56sewardj   i->Ain.Sse32FLo.src = src;
9598d965316c72c2392f670dcdfa127547ec77c7e56sewardj   i->Ain.Sse32FLo.dst = dst;
9608d965316c72c2392f670dcdfa127547ec77c7e56sewardj   vassert(op != Asse_MOV);
9618d965316c72c2392f670dcdfa127547ec77c7e56sewardj   return i;
9628d965316c72c2392f670dcdfa127547ec77c7e56sewardj}
9634c328cf28ebd12977fbf837c44a614c5aac660f3sewardjAMD64Instr* AMD64Instr_Sse64Fx2 ( AMD64SseOp op, HReg src, HReg dst ) {
964d8e3ecaede8eccf5bc7be2a55d99a188a07b0a34florian   AMD64Instr* i       = LibVEX_Alloc_inline(sizeof(AMD64Instr));
9654c328cf28ebd12977fbf837c44a614c5aac660f3sewardj   i->tag              = Ain_Sse64Fx2;
9664c328cf28ebd12977fbf837c44a614c5aac660f3sewardj   i->Ain.Sse64Fx2.op  = op;
9674c328cf28ebd12977fbf837c44a614c5aac660f3sewardj   i->Ain.Sse64Fx2.src = src;
9684c328cf28ebd12977fbf837c44a614c5aac660f3sewardj   i->Ain.Sse64Fx2.dst = dst;
9694c328cf28ebd12977fbf837c44a614c5aac660f3sewardj   vassert(op != Asse_MOV);
9704c328cf28ebd12977fbf837c44a614c5aac660f3sewardj   return i;
9714c328cf28ebd12977fbf837c44a614c5aac660f3sewardj}
9721001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardjAMD64Instr* AMD64Instr_Sse64FLo ( AMD64SseOp op, HReg src, HReg dst ) {
973d8e3ecaede8eccf5bc7be2a55d99a188a07b0a34florian   AMD64Instr* i       = LibVEX_Alloc_inline(sizeof(AMD64Instr));
9741001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj   i->tag              = Ain_Sse64FLo;
9751001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj   i->Ain.Sse64FLo.op  = op;
9761001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj   i->Ain.Sse64FLo.src = src;
9771001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj   i->Ain.Sse64FLo.dst = dst;
9781001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj   vassert(op != Asse_MOV);
9791001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj   return i;
9801001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj}
9811001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardjAMD64Instr* AMD64Instr_SseReRg ( AMD64SseOp op, HReg re, HReg rg ) {
982d8e3ecaede8eccf5bc7be2a55d99a188a07b0a34florian   AMD64Instr* i      = LibVEX_Alloc_inline(sizeof(AMD64Instr));
9831001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj   i->tag             = Ain_SseReRg;
9841001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj   i->Ain.SseReRg.op  = op;
9851001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj   i->Ain.SseReRg.src = re;
9861001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj   i->Ain.SseReRg.dst = rg;
9871001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj   return i;
9881001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj}
9898d965316c72c2392f670dcdfa127547ec77c7e56sewardjAMD64Instr* AMD64Instr_SseCMov ( AMD64CondCode cond, HReg src, HReg dst ) {
990d8e3ecaede8eccf5bc7be2a55d99a188a07b0a34florian   AMD64Instr* i       = LibVEX_Alloc_inline(sizeof(AMD64Instr));
9918d965316c72c2392f670dcdfa127547ec77c7e56sewardj   i->tag              = Ain_SseCMov;
9928d965316c72c2392f670dcdfa127547ec77c7e56sewardj   i->Ain.SseCMov.cond = cond;
9938d965316c72c2392f670dcdfa127547ec77c7e56sewardj   i->Ain.SseCMov.src  = src;
9948d965316c72c2392f670dcdfa127547ec77c7e56sewardj   i->Ain.SseCMov.dst  = dst;
9958d965316c72c2392f670dcdfa127547ec77c7e56sewardj   vassert(cond != Acc_ALWAYS);
9968d965316c72c2392f670dcdfa127547ec77c7e56sewardj   return i;
9978d965316c72c2392f670dcdfa127547ec77c7e56sewardj}
99809717341a0c364814e35bf405e61399d0e45fa7csewardjAMD64Instr* AMD64Instr_SseShuf ( Int order, HReg src, HReg dst ) {
999d8e3ecaede8eccf5bc7be2a55d99a188a07b0a34florian   AMD64Instr* i        = LibVEX_Alloc_inline(sizeof(AMD64Instr));
100009717341a0c364814e35bf405e61399d0e45fa7csewardj   i->tag               = Ain_SseShuf;
100109717341a0c364814e35bf405e61399d0e45fa7csewardj   i->Ain.SseShuf.order = order;
100209717341a0c364814e35bf405e61399d0e45fa7csewardj   i->Ain.SseShuf.src   = src;
100309717341a0c364814e35bf405e61399d0e45fa7csewardj   i->Ain.SseShuf.dst   = dst;
100409717341a0c364814e35bf405e61399d0e45fa7csewardj   vassert(order >= 0 && order <= 0xFF);
100509717341a0c364814e35bf405e61399d0e45fa7csewardj   return i;
100609717341a0c364814e35bf405e61399d0e45fa7csewardj}
10073616a2ec4af166a3917810e4fdbe910ed80bd278sewardj//uu AMD64Instr* AMD64Instr_AvxLdSt ( Bool isLoad,
10083616a2ec4af166a3917810e4fdbe910ed80bd278sewardj//uu                                  HReg reg, AMD64AMode* addr ) {
1009d8e3ecaede8eccf5bc7be2a55d99a188a07b0a34florian//uu    AMD64Instr* i         = LibVEX_Alloc_inline(sizeof(AMD64Instr));
10103616a2ec4af166a3917810e4fdbe910ed80bd278sewardj//uu    i->tag                = Ain_AvxLdSt;
10113616a2ec4af166a3917810e4fdbe910ed80bd278sewardj//uu    i->Ain.AvxLdSt.isLoad = isLoad;
10123616a2ec4af166a3917810e4fdbe910ed80bd278sewardj//uu    i->Ain.AvxLdSt.reg    = reg;
10133616a2ec4af166a3917810e4fdbe910ed80bd278sewardj//uu    i->Ain.AvxLdSt.addr   = addr;
10143616a2ec4af166a3917810e4fdbe910ed80bd278sewardj//uu    return i;
10153616a2ec4af166a3917810e4fdbe910ed80bd278sewardj//uu }
10163616a2ec4af166a3917810e4fdbe910ed80bd278sewardj//uu AMD64Instr* AMD64Instr_AvxReRg ( AMD64SseOp op, HReg re, HReg rg ) {
1017d8e3ecaede8eccf5bc7be2a55d99a188a07b0a34florian//uu    AMD64Instr* i      = LibVEX_Alloc_inline(sizeof(AMD64Instr));
10183616a2ec4af166a3917810e4fdbe910ed80bd278sewardj//uu    i->tag             = Ain_AvxReRg;
10193616a2ec4af166a3917810e4fdbe910ed80bd278sewardj//uu    i->Ain.AvxReRg.op  = op;
10203616a2ec4af166a3917810e4fdbe910ed80bd278sewardj//uu    i->Ain.AvxReRg.src = re;
10213616a2ec4af166a3917810e4fdbe910ed80bd278sewardj//uu    i->Ain.AvxReRg.dst = rg;
10223616a2ec4af166a3917810e4fdbe910ed80bd278sewardj//uu    return i;
10233616a2ec4af166a3917810e4fdbe910ed80bd278sewardj//uu }
1024c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardjAMD64Instr* AMD64Instr_EvCheck ( AMD64AMode* amCounter,
1025c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj                                 AMD64AMode* amFailAddr ) {
1026d8e3ecaede8eccf5bc7be2a55d99a188a07b0a34florian   AMD64Instr* i             = LibVEX_Alloc_inline(sizeof(AMD64Instr));
1027c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   i->tag                    = Ain_EvCheck;
1028c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   i->Ain.EvCheck.amCounter  = amCounter;
1029c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   i->Ain.EvCheck.amFailAddr = amFailAddr;
1030c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   return i;
1031c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj}
1032c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardjAMD64Instr* AMD64Instr_ProfInc ( void ) {
1033d8e3ecaede8eccf5bc7be2a55d99a188a07b0a34florian   AMD64Instr* i = LibVEX_Alloc_inline(sizeof(AMD64Instr));
1034c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   i->tag        = Ain_ProfInc;
1035c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   return i;
1036c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj}
1037c33671d7b0e21edb1d1015e4cbccbc6ca139e6d8sewardj
1038d8c64e082224b2e688abdef9219cc76fd82b373bflorianvoid ppAMD64Instr ( const AMD64Instr* i, Bool mode64 )
1039c33671d7b0e21edb1d1015e4cbccbc6ca139e6d8sewardj{
104092b643609c5fa432b11fc726c2706ae3f3296eb4cerion   vassert(mode64 == True);
1041c33671d7b0e21edb1d1015e4cbccbc6ca139e6d8sewardj   switch (i->tag) {
1042813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj      case Ain_Imm64:
10431b8d58eb046ad31fbb058d65855b604886d3d177sewardj         vex_printf("movabsq $0x%llx,", i->Ain.Imm64.imm64);
1044813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj         ppHRegAMD64(i->Ain.Imm64.dst);
1045813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj         return;
1046614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj      case Ain_Alu64R:
1047614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj         vex_printf("%sq ", showAMD64AluOp(i->Ain.Alu64R.op));
1048614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj         ppAMD64RMI(i->Ain.Alu64R.src);
1049614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj         vex_printf(",");
1050614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj         ppHRegAMD64(i->Ain.Alu64R.dst);
1051614b3fb2b4b226c487bf7f4c85c719c31527bc89sewardj         return;
1052f67eadf04f5150178e589060f03381300d28e540sewardj      case Ain_Alu64M:
1053f67eadf04f5150178e589060f03381300d28e540sewardj         vex_printf("%sq ", showAMD64AluOp(i->Ain.Alu64M.op));
1054f67eadf04f5150178e589060f03381300d28e540sewardj         ppAMD64RI(i->Ain.Alu64M.src);
1055f67eadf04f5150178e589060f03381300d28e540sewardj         vex_printf(",");
1056f67eadf04f5150178e589060f03381300d28e540sewardj         ppAMD64AMode(i->Ain.Alu64M.dst);
1057f67eadf04f5150178e589060f03381300d28e540sewardj         return;
10588258a8c9f2e0ba23e79e322102fa6d0c354436f1sewardj      case Ain_Sh64:
10591b8d58eb046ad31fbb058d65855b604886d3d177sewardj         vex_printf("%sq ", showAMD64ShiftOp(i->Ain.Sh64.op));
10608258a8c9f2e0ba23e79e322102fa6d0c354436f1sewardj         if (i->Ain.Sh64.src == 0)
10618258a8c9f2e0ba23e79e322102fa6d0c354436f1sewardj            vex_printf("%%cl,");
10628258a8c9f2e0ba23e79e322102fa6d0c354436f1sewardj         else
106303ccf858efa285d793061359c04fdd0055cd9d31sewardj            vex_printf("$%d,", (Int)i->Ain.Sh64.src);
1064501a339ba08d28f30eb96d17b3f5bbe996ca6a4dsewardj         ppHRegAMD64(i->Ain.Sh64.dst);
10658258a8c9f2e0ba23e79e322102fa6d0c354436f1sewardj         return;
106605b3b6a0474ba57b4dbd15ac26d857197cdc87fcsewardj      case Ain_Test64:
1067501a339ba08d28f30eb96d17b3f5bbe996ca6a4dsewardj         vex_printf("testq $%d,", (Int)i->Ain.Test64.imm32);
1068501a339ba08d28f30eb96d17b3f5bbe996ca6a4dsewardj         ppHRegAMD64(i->Ain.Test64.dst);
106905b3b6a0474ba57b4dbd15ac26d857197cdc87fcsewardj         return;
1070d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj      case Ain_Unary64:
1071b522077275a57df04305eec3ec1ef3fab9801197sewardj         vex_printf("%sq ", showAMD64UnaryOp(i->Ain.Unary64.op));
1072501a339ba08d28f30eb96d17b3f5bbe996ca6a4dsewardj         ppHRegAMD64(i->Ain.Unary64.dst);
1073d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj         return;
10746ce1a23b27d1729da9d705abd15b2007dce8daecsewardj      case Ain_Lea64:
10756ce1a23b27d1729da9d705abd15b2007dce8daecsewardj         vex_printf("leaq ");
10766ce1a23b27d1729da9d705abd15b2007dce8daecsewardj         ppAMD64AMode(i->Ain.Lea64.am);
10776ce1a23b27d1729da9d705abd15b2007dce8daecsewardj         vex_printf(",");
10786ce1a23b27d1729da9d705abd15b2007dce8daecsewardj         ppHRegAMD64(i->Ain.Lea64.dst);
10796ce1a23b27d1729da9d705abd15b2007dce8daecsewardj         return;
10809cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj      case Ain_Alu32R:
10819cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj         vex_printf("%sl ", showAMD64AluOp(i->Ain.Alu32R.op));
10829cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj         ppAMD64RMI_lo32(i->Ain.Alu32R.src);
10839cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj         vex_printf(",");
10849cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj         ppHRegAMD64_lo32(i->Ain.Alu32R.dst);
10859cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj         return;
10869b96767debeeb1f78378f0e7e295fe6762c64002sewardj      case Ain_MulL:
1087501a339ba08d28f30eb96d17b3f5bbe996ca6a4dsewardj         vex_printf("%cmulq ", i->Ain.MulL.syned ? 's' : 'u');
10889b96767debeeb1f78378f0e7e295fe6762c64002sewardj         ppAMD64RM(i->Ain.MulL.src);
10899b96767debeeb1f78378f0e7e295fe6762c64002sewardj         return;
10907de0d3c800437fbd82c59d57d156f4823d67609fsewardj      case Ain_Div:
10917de0d3c800437fbd82c59d57d156f4823d67609fsewardj         vex_printf("%cdiv%s ",
10927de0d3c800437fbd82c59d57d156f4823d67609fsewardj                    i->Ain.Div.syned ? 's' : 'u',
10937de0d3c800437fbd82c59d57d156f4823d67609fsewardj                    showAMD64ScalarSz(i->Ain.Div.sz));
10947de0d3c800437fbd82c59d57d156f4823d67609fsewardj         ppAMD64RM(i->Ain.Div.src);
10957de0d3c800437fbd82c59d57d156f4823d67609fsewardj         return;
10961001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj      case Ain_Push:
10971001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj         vex_printf("pushq ");
10981001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj         ppAMD64RMI(i->Ain.Push.src);
10991001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj         return;
110005b3b6a0474ba57b4dbd15ac26d857197cdc87fcsewardj      case Ain_Call:
1101cfe046e178666280b87da998b1b52ecda03ecd89sewardj         vex_printf("call%s[%d,",
110205b3b6a0474ba57b4dbd15ac26d857197cdc87fcsewardj                    i->Ain.Call.cond==Acc_ALWAYS
110305b3b6a0474ba57b4dbd15ac26d857197cdc87fcsewardj                       ? "" : showAMD64CondCode(i->Ain.Call.cond),
110405b3b6a0474ba57b4dbd15ac26d857197cdc87fcsewardj                    i->Ain.Call.regparms );
1105cfe046e178666280b87da998b1b52ecda03ecd89sewardj         ppRetLoc(i->Ain.Call.rloc);
1106cfe046e178666280b87da998b1b52ecda03ecd89sewardj         vex_printf("] 0x%llx", i->Ain.Call.target);
110705b3b6a0474ba57b4dbd15ac26d857197cdc87fcsewardj         break;
1108c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj
1109c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      case Ain_XDirect:
1110c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         vex_printf("(xDirect) ");
1111c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         vex_printf("if (%%rflags.%s) { ",
1112c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj                    showAMD64CondCode(i->Ain.XDirect.cond));
1113c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         vex_printf("movabsq $0x%llx,%%r11; ", i->Ain.XDirect.dstGA);
1114c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         vex_printf("movq %%r11,");
1115c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         ppAMD64AMode(i->Ain.XDirect.amRIP);
1116c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         vex_printf("; ");
1117c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         vex_printf("movabsq $disp_cp_chain_me_to_%sEP,%%r11; call *%%r11 }",
1118c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj                    i->Ain.XDirect.toFastEP ? "fast" : "slow");
1119c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         return;
1120c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      case Ain_XIndir:
1121c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         vex_printf("(xIndir) ");
1122c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         vex_printf("if (%%rflags.%s) { ",
1123c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj                    showAMD64CondCode(i->Ain.XIndir.cond));
11241b8d58eb046ad31fbb058d65855b604886d3d177sewardj         vex_printf("movq ");
1125c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         ppHRegAMD64(i->Ain.XIndir.dstGA);
1126c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         vex_printf(",");
1127c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         ppAMD64AMode(i->Ain.XIndir.amRIP);
1128c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         vex_printf("; movabsq $disp_indir,%%r11; jmp *%%r11 }");
1129c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         return;
1130c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      case Ain_XAssisted:
1131c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         vex_printf("(xAssisted) ");
1132c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         vex_printf("if (%%rflags.%s) { ",
1133c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj                    showAMD64CondCode(i->Ain.XAssisted.cond));
1134c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         vex_printf("movq ");
1135c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         ppHRegAMD64(i->Ain.XAssisted.dstGA);
1136c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         vex_printf(",");
1137c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         ppAMD64AMode(i->Ain.XAssisted.amRIP);
1138c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         vex_printf("; movl $IRJumpKind_to_TRCVAL(%d),%%rbp",
1139c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj                    (Int)i->Ain.XAssisted.jk);
1140c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         vex_printf("; movabsq $disp_assisted,%%r11; jmp *%%r11 }");
1141f67eadf04f5150178e589060f03381300d28e540sewardj         return;
1142c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj
114305b3b6a0474ba57b4dbd15ac26d857197cdc87fcsewardj      case Ain_CMov64:
114405b3b6a0474ba57b4dbd15ac26d857197cdc87fcsewardj         vex_printf("cmov%s ", showAMD64CondCode(i->Ain.CMov64.cond));
1145e357c67787b7429f85a030ee5fbedf33173b5656sewardj         ppHRegAMD64(i->Ain.CMov64.src);
114605b3b6a0474ba57b4dbd15ac26d857197cdc87fcsewardj         vex_printf(",");
114705b3b6a0474ba57b4dbd15ac26d857197cdc87fcsewardj         ppHRegAMD64(i->Ain.CMov64.dst);
114805b3b6a0474ba57b4dbd15ac26d857197cdc87fcsewardj         return;
1149bdea5508b371d394c81b91464fa8df767010d4dasewardj      case Ain_CLoad:
1150bdea5508b371d394c81b91464fa8df767010d4dasewardj         vex_printf("if (%%rflags.%s) { ",
1151bdea5508b371d394c81b91464fa8df767010d4dasewardj                    showAMD64CondCode(i->Ain.CLoad.cond));
11526f1ec58d9806064dea0000e4b543aacded9b11easewardj         vex_printf("mov%c ", i->Ain.CLoad.szB == 4 ? 'l' : 'q');
1153bdea5508b371d394c81b91464fa8df767010d4dasewardj         ppAMD64AMode(i->Ain.CLoad.addr);
11546f1ec58d9806064dea0000e4b543aacded9b11easewardj         vex_printf(", ");
1155bdea5508b371d394c81b91464fa8df767010d4dasewardj         (i->Ain.CLoad.szB == 4 ? ppHRegAMD64_lo32 : ppHRegAMD64)
1156bdea5508b371d394c81b91464fa8df767010d4dasewardj            (i->Ain.CLoad.dst);
1157bdea5508b371d394c81b91464fa8df767010d4dasewardj         vex_printf(" }");
1158bdea5508b371d394c81b91464fa8df767010d4dasewardj         return;
11596f1ec58d9806064dea0000e4b543aacded9b11easewardj      case Ain_CStore:
11606f1ec58d9806064dea0000e4b543aacded9b11easewardj         vex_printf("if (%%rflags.%s) { ",
11616f1ec58d9806064dea0000e4b543aacded9b11easewardj                    showAMD64CondCode(i->Ain.CStore.cond));
11626f1ec58d9806064dea0000e4b543aacded9b11easewardj         vex_printf("mov%c ", i->Ain.CStore.szB == 4 ? 'l' : 'q');
11636f1ec58d9806064dea0000e4b543aacded9b11easewardj         (i->Ain.CStore.szB == 4 ? ppHRegAMD64_lo32 : ppHRegAMD64)
11646f1ec58d9806064dea0000e4b543aacded9b11easewardj            (i->Ain.CStore.src);
11656f1ec58d9806064dea0000e4b543aacded9b11easewardj         vex_printf(", ");
11666f1ec58d9806064dea0000e4b543aacded9b11easewardj         ppAMD64AMode(i->Ain.CStore.addr);
11676f1ec58d9806064dea0000e4b543aacded9b11easewardj         vex_printf(" }");
11686f1ec58d9806064dea0000e4b543aacded9b11easewardj         return;
11696f1ec58d9806064dea0000e4b543aacded9b11easewardj
1170ca257bc572147c1a9c7d9a2e81237125a35ff25dsewardj      case Ain_MovxLQ:
1171ca257bc572147c1a9c7d9a2e81237125a35ff25dsewardj         vex_printf("mov%clq ", i->Ain.MovxLQ.syned ? 's' : 'z');
1172ca257bc572147c1a9c7d9a2e81237125a35ff25dsewardj         ppHRegAMD64_lo32(i->Ain.MovxLQ.src);
1173f67eadf04f5150178e589060f03381300d28e540sewardj         vex_printf(",");
1174ca257bc572147c1a9c7d9a2e81237125a35ff25dsewardj         ppHRegAMD64(i->Ain.MovxLQ.dst);
1175f67eadf04f5150178e589060f03381300d28e540sewardj         return;
11768258a8c9f2e0ba23e79e322102fa6d0c354436f1sewardj      case Ain_LoadEX:
1177549e06463d433ee6351b72dc9107f22ce4305250sewardj         if (i->Ain.LoadEX.szSmall==4 && !i->Ain.LoadEX.syned) {
1178549e06463d433ee6351b72dc9107f22ce4305250sewardj            vex_printf("movl ");
1179549e06463d433ee6351b72dc9107f22ce4305250sewardj            ppAMD64AMode(i->Ain.LoadEX.src);
1180549e06463d433ee6351b72dc9107f22ce4305250sewardj            vex_printf(",");
1181549e06463d433ee6351b72dc9107f22ce4305250sewardj            ppHRegAMD64_lo32(i->Ain.LoadEX.dst);
1182549e06463d433ee6351b72dc9107f22ce4305250sewardj         } else {
1183549e06463d433ee6351b72dc9107f22ce4305250sewardj            vex_printf("mov%c%cq ",
1184549e06463d433ee6351b72dc9107f22ce4305250sewardj                       i->Ain.LoadEX.syned ? 's' : 'z',
1185549e06463d433ee6351b72dc9107f22ce4305250sewardj                       i->Ain.LoadEX.szSmall==1
1186549e06463d433ee6351b72dc9107f22ce4305250sewardj                          ? 'b'
1187549e06463d433ee6351b72dc9107f22ce4305250sewardj                          : (i->Ain.LoadEX.szSmall==2 ? 'w' : 'l'));
1188549e06463d433ee6351b72dc9107f22ce4305250sewardj            ppAMD64AMode(i->Ain.LoadEX.src);
1189549e06463d433ee6351b72dc9107f22ce4305250sewardj            vex_printf(",");
1190549e06463d433ee6351b72dc9107f22ce4305250sewardj            ppHRegAMD64(i->Ain.LoadEX.dst);
1191549e06463d433ee6351b72dc9107f22ce4305250sewardj         }
11928258a8c9f2e0ba23e79e322102fa6d0c354436f1sewardj         return;
119305b3b6a0474ba57b4dbd15ac26d857197cdc87fcsewardj      case Ain_Store:
119405b3b6a0474ba57b4dbd15ac26d857197cdc87fcsewardj         vex_printf("mov%c ", i->Ain.Store.sz==1 ? 'b'
119505b3b6a0474ba57b4dbd15ac26d857197cdc87fcsewardj                              : (i->Ain.Store.sz==2 ? 'w' : 'l'));
119605b3b6a0474ba57b4dbd15ac26d857197cdc87fcsewardj         ppHRegAMD64(i->Ain.Store.src);
119705b3b6a0474ba57b4dbd15ac26d857197cdc87fcsewardj         vex_printf(",");
119805b3b6a0474ba57b4dbd15ac26d857197cdc87fcsewardj         ppAMD64AMode(i->Ain.Store.dst);
119905b3b6a0474ba57b4dbd15ac26d857197cdc87fcsewardj         return;
1200a5bd0aff6eda3e7c312f51ae6bc742ea62b5d404sewardj      case Ain_Set64:
1201a5bd0aff6eda3e7c312f51ae6bc742ea62b5d404sewardj         vex_printf("setq%s ", showAMD64CondCode(i->Ain.Set64.cond));
1202a5bd0aff6eda3e7c312f51ae6bc742ea62b5d404sewardj         ppHRegAMD64(i->Ain.Set64.dst);
1203a5bd0aff6eda3e7c312f51ae6bc742ea62b5d404sewardj         return;
1204f53b7359a342e7d79090615169c6583a1a75fbcesewardj      case Ain_Bsfr64:
1205f53b7359a342e7d79090615169c6583a1a75fbcesewardj         vex_printf("bs%cq ", i->Ain.Bsfr64.isFwds ? 'f' : 'r');
1206f53b7359a342e7d79090615169c6583a1a75fbcesewardj         ppHRegAMD64(i->Ain.Bsfr64.src);
1207f53b7359a342e7d79090615169c6583a1a75fbcesewardj         vex_printf(",");
1208f53b7359a342e7d79090615169c6583a1a75fbcesewardj         ppHRegAMD64(i->Ain.Bsfr64.dst);
1209f53b7359a342e7d79090615169c6583a1a75fbcesewardj         return;
1210d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj      case Ain_MFence:
1211d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj         vex_printf("mfence" );
1212d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj         return;
1213e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj      case Ain_ACAS:
1214e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         vex_printf("lock cmpxchg%c ",
1215e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj                     i->Ain.ACAS.sz==1 ? 'b' : i->Ain.ACAS.sz==2 ? 'w'
1216e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj                     : i->Ain.ACAS.sz==4 ? 'l' : 'q' );
1217e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         vex_printf("{%%rax->%%rbx},");
1218e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         ppAMD64AMode(i->Ain.ACAS.addr);
1219e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         return;
1220e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj      case Ain_DACAS:
1221e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         vex_printf("lock cmpxchg%db {%%rdx:%%rax->%%rcx:%%rbx},",
1222e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj                    (Int)(2 * i->Ain.DACAS.sz));
1223e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         ppAMD64AMode(i->Ain.DACAS.addr);
1224e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         return;
122525a858136df4cbea0055c20aa7035d25fd40ee89sewardj      case Ain_A87Free:
1226f4c803b0947e7534809589cba8007851d78c7a2esewardj         vex_printf("ffree %%st(7..%d)", 8 - i->Ain.A87Free.nregs );
122725a858136df4cbea0055c20aa7035d25fd40ee89sewardj         break;
122825a858136df4cbea0055c20aa7035d25fd40ee89sewardj      case Ain_A87PushPop:
1229d15b597a8a006b3fe136cbf6cdf5b46ed532a4d8sewardj         vex_printf(i->Ain.A87PushPop.isPush ? "fld%c " : "fstp%c ",
1230d15b597a8a006b3fe136cbf6cdf5b46ed532a4d8sewardj                    i->Ain.A87PushPop.szB == 4 ? 's' : 'l');
123125a858136df4cbea0055c20aa7035d25fd40ee89sewardj         ppAMD64AMode(i->Ain.A87PushPop.addr);
123225a858136df4cbea0055c20aa7035d25fd40ee89sewardj         break;
123325a858136df4cbea0055c20aa7035d25fd40ee89sewardj      case Ain_A87FpOp:
1234f4c803b0947e7534809589cba8007851d78c7a2esewardj         vex_printf("f%s", showA87FpOp(i->Ain.A87FpOp.op));
123525a858136df4cbea0055c20aa7035d25fd40ee89sewardj         break;
123625a858136df4cbea0055c20aa7035d25fd40ee89sewardj      case Ain_A87LdCW:
123725a858136df4cbea0055c20aa7035d25fd40ee89sewardj         vex_printf("fldcw ");
123825a858136df4cbea0055c20aa7035d25fd40ee89sewardj         ppAMD64AMode(i->Ain.A87LdCW.addr);
123925a858136df4cbea0055c20aa7035d25fd40ee89sewardj         break;
1240f4c803b0947e7534809589cba8007851d78c7a2esewardj      case Ain_A87StSW:
1241f4c803b0947e7534809589cba8007851d78c7a2esewardj         vex_printf("fstsw ");
1242f4c803b0947e7534809589cba8007851d78c7a2esewardj         ppAMD64AMode(i->Ain.A87StSW.addr);
1243f4c803b0947e7534809589cba8007851d78c7a2esewardj         break;
12441a01e65f9993d97095c2af463e98674a091834casewardj      case Ain_LdMXCSR:
12451a01e65f9993d97095c2af463e98674a091834casewardj         vex_printf("ldmxcsr ");
12461a01e65f9993d97095c2af463e98674a091834casewardj         ppAMD64AMode(i->Ain.LdMXCSR.addr);
12471a01e65f9993d97095c2af463e98674a091834casewardj         break;
12481830386e7b10430c0c3630123a82d8bcf0a071e7sewardj      case Ain_SseUComIS:
12491830386e7b10430c0c3630123a82d8bcf0a071e7sewardj         vex_printf("ucomis%s ", i->Ain.SseUComIS.sz==4 ? "s" : "d");
12501830386e7b10430c0c3630123a82d8bcf0a071e7sewardj         ppHRegAMD64(i->Ain.SseUComIS.srcL);
12511830386e7b10430c0c3630123a82d8bcf0a071e7sewardj         vex_printf(",");
12521830386e7b10430c0c3630123a82d8bcf0a071e7sewardj         ppHRegAMD64(i->Ain.SseUComIS.srcR);
12531830386e7b10430c0c3630123a82d8bcf0a071e7sewardj         vex_printf(" ; pushfq ; popq ");
12541830386e7b10430c0c3630123a82d8bcf0a071e7sewardj         ppHRegAMD64(i->Ain.SseUComIS.dst);
12551830386e7b10430c0c3630123a82d8bcf0a071e7sewardj         break;
12561a01e65f9993d97095c2af463e98674a091834casewardj      case Ain_SseSI2SF:
12571a01e65f9993d97095c2af463e98674a091834casewardj         vex_printf("cvtsi2s%s ", i->Ain.SseSI2SF.szD==4 ? "s" : "d");
12581a01e65f9993d97095c2af463e98674a091834casewardj         (i->Ain.SseSI2SF.szS==4 ? ppHRegAMD64_lo32 : ppHRegAMD64)
12591a01e65f9993d97095c2af463e98674a091834casewardj            (i->Ain.SseSI2SF.src);
12601a01e65f9993d97095c2af463e98674a091834casewardj         vex_printf(",");
12611a01e65f9993d97095c2af463e98674a091834casewardj         ppHRegAMD64(i->Ain.SseSI2SF.dst);
12621a01e65f9993d97095c2af463e98674a091834casewardj         break;
12631a01e65f9993d97095c2af463e98674a091834casewardj      case Ain_SseSF2SI:
12641a01e65f9993d97095c2af463e98674a091834casewardj         vex_printf("cvts%s2si ", i->Ain.SseSF2SI.szS==4 ? "s" : "d");
12651a01e65f9993d97095c2af463e98674a091834casewardj         ppHRegAMD64(i->Ain.SseSF2SI.src);
12661a01e65f9993d97095c2af463e98674a091834casewardj         vex_printf(",");
12671a01e65f9993d97095c2af463e98674a091834casewardj         (i->Ain.SseSF2SI.szD==4 ? ppHRegAMD64_lo32 : ppHRegAMD64)
12681a01e65f9993d97095c2af463e98674a091834casewardj            (i->Ain.SseSF2SI.dst);
12691a01e65f9993d97095c2af463e98674a091834casewardj         break;
12708d965316c72c2392f670dcdfa127547ec77c7e56sewardj      case Ain_SseSDSS:
12718d965316c72c2392f670dcdfa127547ec77c7e56sewardj         vex_printf(i->Ain.SseSDSS.from64 ? "cvtsd2ss " : "cvtss2sd ");
12728d965316c72c2392f670dcdfa127547ec77c7e56sewardj         ppHRegAMD64(i->Ain.SseSDSS.src);
12738d965316c72c2392f670dcdfa127547ec77c7e56sewardj         vex_printf(",");
12748d965316c72c2392f670dcdfa127547ec77c7e56sewardj         ppHRegAMD64(i->Ain.SseSDSS.dst);
12758d965316c72c2392f670dcdfa127547ec77c7e56sewardj         break;
12761001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj      case Ain_SseLdSt:
12771830386e7b10430c0c3630123a82d8bcf0a071e7sewardj         switch (i->Ain.SseLdSt.sz) {
12781830386e7b10430c0c3630123a82d8bcf0a071e7sewardj            case 4:  vex_printf("movss "); break;
12791830386e7b10430c0c3630123a82d8bcf0a071e7sewardj            case 8:  vex_printf("movsd "); break;
12801830386e7b10430c0c3630123a82d8bcf0a071e7sewardj            case 16: vex_printf("movups "); break;
12811830386e7b10430c0c3630123a82d8bcf0a071e7sewardj            default: vassert(0);
12821830386e7b10430c0c3630123a82d8bcf0a071e7sewardj         }
12831001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj         if (i->Ain.SseLdSt.isLoad) {
12841001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj            ppAMD64AMode(i->Ain.SseLdSt.addr);
12851001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj            vex_printf(",");
12861001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj            ppHRegAMD64(i->Ain.SseLdSt.reg);
12871001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj         } else {
12881001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj            ppHRegAMD64(i->Ain.SseLdSt.reg);
12891001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj            vex_printf(",");
12901001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj            ppAMD64AMode(i->Ain.SseLdSt.addr);
12911001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj         }
12921001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj         return;
129370dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj      case Ain_SseCStore:
129470dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj         vex_printf("if (%%rflags.%s) { ",
129570dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj                    showAMD64CondCode(i->Ain.SseCStore.cond));
129670dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj         vex_printf("movups ");
129770dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj         ppHRegAMD64(i->Ain.SseCStore.src);
129870dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj         vex_printf(", ");
129970dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj         ppAMD64AMode(i->Ain.SseCStore.addr);
130070dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj         vex_printf(" }");
130170dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj         return;
130270dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj      case Ain_SseCLoad:
130370dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj         vex_printf("if (%%rflags.%s) { ",
130470dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj                    showAMD64CondCode(i->Ain.SseCLoad.cond));
130570dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj         vex_printf("movups ");
130670dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj         ppAMD64AMode(i->Ain.SseCLoad.addr);
130770dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj         vex_printf(", ");
130870dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj         ppHRegAMD64(i->Ain.SseCLoad.dst);
130970dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj         vex_printf(" }");
131070dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj         return;
13111001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj      case Ain_SseLdzLO:
13121001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj         vex_printf("movs%s ", i->Ain.SseLdzLO.sz==4 ? "s" : "d");
13131001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj         ppAMD64AMode(i->Ain.SseLdzLO.addr);
13141001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj         vex_printf(",");
13151001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj         ppHRegAMD64(i->Ain.SseLdzLO.reg);
13161001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj         return;
13178d965316c72c2392f670dcdfa127547ec77c7e56sewardj      case Ain_Sse32Fx4:
13188d965316c72c2392f670dcdfa127547ec77c7e56sewardj         vex_printf("%sps ", showAMD64SseOp(i->Ain.Sse32Fx4.op));
13198d965316c72c2392f670dcdfa127547ec77c7e56sewardj         ppHRegAMD64(i->Ain.Sse32Fx4.src);
13208d965316c72c2392f670dcdfa127547ec77c7e56sewardj         vex_printf(",");
13218d965316c72c2392f670dcdfa127547ec77c7e56sewardj         ppHRegAMD64(i->Ain.Sse32Fx4.dst);
13228d965316c72c2392f670dcdfa127547ec77c7e56sewardj         return;
13238d965316c72c2392f670dcdfa127547ec77c7e56sewardj      case Ain_Sse32FLo:
13248d965316c72c2392f670dcdfa127547ec77c7e56sewardj         vex_printf("%sss ", showAMD64SseOp(i->Ain.Sse32FLo.op));
13258d965316c72c2392f670dcdfa127547ec77c7e56sewardj         ppHRegAMD64(i->Ain.Sse32FLo.src);
13268d965316c72c2392f670dcdfa127547ec77c7e56sewardj         vex_printf(",");
13278d965316c72c2392f670dcdfa127547ec77c7e56sewardj         ppHRegAMD64(i->Ain.Sse32FLo.dst);
13288d965316c72c2392f670dcdfa127547ec77c7e56sewardj         return;
13294c328cf28ebd12977fbf837c44a614c5aac660f3sewardj      case Ain_Sse64Fx2:
13304c328cf28ebd12977fbf837c44a614c5aac660f3sewardj         vex_printf("%spd ", showAMD64SseOp(i->Ain.Sse64Fx2.op));
13314c328cf28ebd12977fbf837c44a614c5aac660f3sewardj         ppHRegAMD64(i->Ain.Sse64Fx2.src);
13324c328cf28ebd12977fbf837c44a614c5aac660f3sewardj         vex_printf(",");
13334c328cf28ebd12977fbf837c44a614c5aac660f3sewardj         ppHRegAMD64(i->Ain.Sse64Fx2.dst);
13344c328cf28ebd12977fbf837c44a614c5aac660f3sewardj         return;
13351001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj      case Ain_Sse64FLo:
13361001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj         vex_printf("%ssd ", showAMD64SseOp(i->Ain.Sse64FLo.op));
13371001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj         ppHRegAMD64(i->Ain.Sse64FLo.src);
13381001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj         vex_printf(",");
13391001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj         ppHRegAMD64(i->Ain.Sse64FLo.dst);
13401001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj         return;
13411001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj      case Ain_SseReRg:
13421001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj         vex_printf("%s ", showAMD64SseOp(i->Ain.SseReRg.op));
13431001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj         ppHRegAMD64(i->Ain.SseReRg.src);
13441001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj         vex_printf(",");
13451001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj         ppHRegAMD64(i->Ain.SseReRg.dst);
13461001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj         return;
13478d965316c72c2392f670dcdfa127547ec77c7e56sewardj      case Ain_SseCMov:
13488d965316c72c2392f670dcdfa127547ec77c7e56sewardj         vex_printf("cmov%s ", showAMD64CondCode(i->Ain.SseCMov.cond));
13498d965316c72c2392f670dcdfa127547ec77c7e56sewardj         ppHRegAMD64(i->Ain.SseCMov.src);
13508d965316c72c2392f670dcdfa127547ec77c7e56sewardj         vex_printf(",");
13518d965316c72c2392f670dcdfa127547ec77c7e56sewardj         ppHRegAMD64(i->Ain.SseCMov.dst);
13528d965316c72c2392f670dcdfa127547ec77c7e56sewardj         return;
135309717341a0c364814e35bf405e61399d0e45fa7csewardj      case Ain_SseShuf:
1354b173774421d015736c2316b5e6e998e7de545a5cflorian         vex_printf("pshufd $0x%x,", (UInt)i->Ain.SseShuf.order);
135509717341a0c364814e35bf405e61399d0e45fa7csewardj         ppHRegAMD64(i->Ain.SseShuf.src);
135609717341a0c364814e35bf405e61399d0e45fa7csewardj         vex_printf(",");
135709717341a0c364814e35bf405e61399d0e45fa7csewardj         ppHRegAMD64(i->Ain.SseShuf.dst);
135809717341a0c364814e35bf405e61399d0e45fa7csewardj         return;
13593616a2ec4af166a3917810e4fdbe910ed80bd278sewardj      //uu case Ain_AvxLdSt:
13603616a2ec4af166a3917810e4fdbe910ed80bd278sewardj      //uu    vex_printf("vmovups ");
13613616a2ec4af166a3917810e4fdbe910ed80bd278sewardj      //uu    if (i->Ain.AvxLdSt.isLoad) {
13623616a2ec4af166a3917810e4fdbe910ed80bd278sewardj      //uu       ppAMD64AMode(i->Ain.AvxLdSt.addr);
13633616a2ec4af166a3917810e4fdbe910ed80bd278sewardj      //uu       vex_printf(",");
13643616a2ec4af166a3917810e4fdbe910ed80bd278sewardj      //uu       ppHRegAMD64(i->Ain.AvxLdSt.reg);
13653616a2ec4af166a3917810e4fdbe910ed80bd278sewardj      //uu    } else {
13663616a2ec4af166a3917810e4fdbe910ed80bd278sewardj      //uu       ppHRegAMD64(i->Ain.AvxLdSt.reg);
13673616a2ec4af166a3917810e4fdbe910ed80bd278sewardj      //uu       vex_printf(",");
13683616a2ec4af166a3917810e4fdbe910ed80bd278sewardj      //uu       ppAMD64AMode(i->Ain.AvxLdSt.addr);
13693616a2ec4af166a3917810e4fdbe910ed80bd278sewardj      //uu    }
13703616a2ec4af166a3917810e4fdbe910ed80bd278sewardj      //uu    return;
13713616a2ec4af166a3917810e4fdbe910ed80bd278sewardj      //uu case Ain_AvxReRg:
13723616a2ec4af166a3917810e4fdbe910ed80bd278sewardj      //uu    vex_printf("v%s ", showAMD64SseOp(i->Ain.SseReRg.op));
13733616a2ec4af166a3917810e4fdbe910ed80bd278sewardj      //uu    ppHRegAMD64(i->Ain.AvxReRg.src);
13743616a2ec4af166a3917810e4fdbe910ed80bd278sewardj      //uu    vex_printf(",");
13753616a2ec4af166a3917810e4fdbe910ed80bd278sewardj      //uu    ppHRegAMD64(i->Ain.AvxReRg.dst);
13763616a2ec4af166a3917810e4fdbe910ed80bd278sewardj      //uu    return;
1377c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      case Ain_EvCheck:
1378c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         vex_printf("(evCheck) decl ");
1379c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         ppAMD64AMode(i->Ain.EvCheck.amCounter);
1380c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         vex_printf("; jns nofail; jmp *");
1381c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         ppAMD64AMode(i->Ain.EvCheck.amFailAddr);
1382c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         vex_printf("; nofail:");
1383c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         return;
1384c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      case Ain_ProfInc:
1385c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         vex_printf("(profInc) movabsq $NotKnownYet, %%r11; incq (%%r11)");
1386c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         return;
1387c33671d7b0e21edb1d1015e4cbccbc6ca139e6d8sewardj      default:
1388c33671d7b0e21edb1d1015e4cbccbc6ca139e6d8sewardj         vpanic("ppAMD64Instr");
1389c33671d7b0e21edb1d1015e4cbccbc6ca139e6d8sewardj   }
1390c33671d7b0e21edb1d1015e4cbccbc6ca139e6d8sewardj}
1391c33671d7b0e21edb1d1015e4cbccbc6ca139e6d8sewardj
1392c33671d7b0e21edb1d1015e4cbccbc6ca139e6d8sewardj/* --------- Helpers for register allocation. --------- */
1393c33671d7b0e21edb1d1015e4cbccbc6ca139e6d8sewardj
1394d8c64e082224b2e688abdef9219cc76fd82b373bflorianvoid getRegUsage_AMD64Instr ( HRegUsage* u, const AMD64Instr* i, Bool mode64 )
1395c33671d7b0e21edb1d1015e4cbccbc6ca139e6d8sewardj{
13961001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj   Bool unary;
139792b643609c5fa432b11fc726c2706ae3f3296eb4cerion   vassert(mode64 == True);
1398c33671d7b0e21edb1d1015e4cbccbc6ca139e6d8sewardj   initHRegUsage(u);
1399c33671d7b0e21edb1d1015e4cbccbc6ca139e6d8sewardj   switch (i->tag) {
1400813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj      case Ain_Imm64:
1401813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj         addHRegUse(u, HRmWrite, i->Ain.Imm64.dst);
1402813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj         return;
1403f67eadf04f5150178e589060f03381300d28e540sewardj      case Ain_Alu64R:
1404f67eadf04f5150178e589060f03381300d28e540sewardj         addRegUsage_AMD64RMI(u, i->Ain.Alu64R.src);
1405f67eadf04f5150178e589060f03381300d28e540sewardj         if (i->Ain.Alu64R.op == Aalu_MOV) {
1406f67eadf04f5150178e589060f03381300d28e540sewardj            addHRegUse(u, HRmWrite, i->Ain.Alu64R.dst);
1407f67eadf04f5150178e589060f03381300d28e540sewardj            return;
1408f67eadf04f5150178e589060f03381300d28e540sewardj         }
1409f67eadf04f5150178e589060f03381300d28e540sewardj         if (i->Ain.Alu64R.op == Aalu_CMP) {
1410f67eadf04f5150178e589060f03381300d28e540sewardj            addHRegUse(u, HRmRead, i->Ain.Alu64R.dst);
1411f67eadf04f5150178e589060f03381300d28e540sewardj            return;
1412f67eadf04f5150178e589060f03381300d28e540sewardj         }
1413f67eadf04f5150178e589060f03381300d28e540sewardj         addHRegUse(u, HRmModify, i->Ain.Alu64R.dst);
1414f67eadf04f5150178e589060f03381300d28e540sewardj         return;
1415f67eadf04f5150178e589060f03381300d28e540sewardj      case Ain_Alu64M:
1416f67eadf04f5150178e589060f03381300d28e540sewardj         addRegUsage_AMD64RI(u, i->Ain.Alu64M.src);
1417f67eadf04f5150178e589060f03381300d28e540sewardj         addRegUsage_AMD64AMode(u, i->Ain.Alu64M.dst);
1418f67eadf04f5150178e589060f03381300d28e540sewardj         return;
1419f67eadf04f5150178e589060f03381300d28e540sewardj      case Ain_Sh64:
1420501a339ba08d28f30eb96d17b3f5bbe996ca6a4dsewardj         addHRegUse(u, HRmModify, i->Ain.Sh64.dst);
1421f67eadf04f5150178e589060f03381300d28e540sewardj         if (i->Ain.Sh64.src == 0)
1422f67eadf04f5150178e589060f03381300d28e540sewardj            addHRegUse(u, HRmRead, hregAMD64_RCX());
1423f67eadf04f5150178e589060f03381300d28e540sewardj         return;
142405b3b6a0474ba57b4dbd15ac26d857197cdc87fcsewardj      case Ain_Test64:
1425501a339ba08d28f30eb96d17b3f5bbe996ca6a4dsewardj         addHRegUse(u, HRmRead, i->Ain.Test64.dst);
142605b3b6a0474ba57b4dbd15ac26d857197cdc87fcsewardj         return;
1427d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj      case Ain_Unary64:
1428501a339ba08d28f30eb96d17b3f5bbe996ca6a4dsewardj         addHRegUse(u, HRmModify, i->Ain.Unary64.dst);
1429d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj         return;
14306ce1a23b27d1729da9d705abd15b2007dce8daecsewardj      case Ain_Lea64:
14316ce1a23b27d1729da9d705abd15b2007dce8daecsewardj         addRegUsage_AMD64AMode(u, i->Ain.Lea64.am);
14326ce1a23b27d1729da9d705abd15b2007dce8daecsewardj         addHRegUse(u, HRmWrite, i->Ain.Lea64.dst);
14336ce1a23b27d1729da9d705abd15b2007dce8daecsewardj         return;
14349cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj      case Ain_Alu32R:
14359cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj         vassert(i->Ain.Alu32R.op != Aalu_MOV);
14369cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj         addRegUsage_AMD64RMI(u, i->Ain.Alu32R.src);
14379cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj         if (i->Ain.Alu32R.op == Aalu_CMP) {
14389cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj            addHRegUse(u, HRmRead, i->Ain.Alu32R.dst);
14399cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj            return;
14409cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj         }
14419cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj         addHRegUse(u, HRmModify, i->Ain.Alu32R.dst);
14429cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj         return;
14439b96767debeeb1f78378f0e7e295fe6762c64002sewardj      case Ain_MulL:
14449b96767debeeb1f78378f0e7e295fe6762c64002sewardj         addRegUsage_AMD64RM(u, i->Ain.MulL.src, HRmRead);
14459b96767debeeb1f78378f0e7e295fe6762c64002sewardj         addHRegUse(u, HRmModify, hregAMD64_RAX());
14469b96767debeeb1f78378f0e7e295fe6762c64002sewardj         addHRegUse(u, HRmWrite, hregAMD64_RDX());
14479b96767debeeb1f78378f0e7e295fe6762c64002sewardj         return;
14487de0d3c800437fbd82c59d57d156f4823d67609fsewardj      case Ain_Div:
14497de0d3c800437fbd82c59d57d156f4823d67609fsewardj         addRegUsage_AMD64RM(u, i->Ain.Div.src, HRmRead);
14507de0d3c800437fbd82c59d57d156f4823d67609fsewardj         addHRegUse(u, HRmModify, hregAMD64_RAX());
14517de0d3c800437fbd82c59d57d156f4823d67609fsewardj         addHRegUse(u, HRmModify, hregAMD64_RDX());
14527de0d3c800437fbd82c59d57d156f4823d67609fsewardj         return;
14531001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj      case Ain_Push:
14541001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj         addRegUsage_AMD64RMI(u, i->Ain.Push.src);
14551001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj         addHRegUse(u, HRmModify, hregAMD64_RSP());
14561001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj         return;
145705b3b6a0474ba57b4dbd15ac26d857197cdc87fcsewardj      case Ain_Call:
145805b3b6a0474ba57b4dbd15ac26d857197cdc87fcsewardj         /* This is a bit subtle. */
145905b3b6a0474ba57b4dbd15ac26d857197cdc87fcsewardj         /* First off, claim it trashes all the caller-saved regs
146005b3b6a0474ba57b4dbd15ac26d857197cdc87fcsewardj            which fall within the register allocator's jurisdiction.
146105b3b6a0474ba57b4dbd15ac26d857197cdc87fcsewardj            These I believe to be: rax rcx rdx rsi rdi r8 r9 r10 r11
14623616a2ec4af166a3917810e4fdbe910ed80bd278sewardj            and all the xmm registers.
146305b3b6a0474ba57b4dbd15ac26d857197cdc87fcsewardj         */
146405b3b6a0474ba57b4dbd15ac26d857197cdc87fcsewardj         addHRegUse(u, HRmWrite, hregAMD64_RAX());
146505b3b6a0474ba57b4dbd15ac26d857197cdc87fcsewardj         addHRegUse(u, HRmWrite, hregAMD64_RCX());
146605b3b6a0474ba57b4dbd15ac26d857197cdc87fcsewardj         addHRegUse(u, HRmWrite, hregAMD64_RDX());
146705b3b6a0474ba57b4dbd15ac26d857197cdc87fcsewardj         addHRegUse(u, HRmWrite, hregAMD64_RSI());
146805b3b6a0474ba57b4dbd15ac26d857197cdc87fcsewardj         addHRegUse(u, HRmWrite, hregAMD64_RDI());
146905b3b6a0474ba57b4dbd15ac26d857197cdc87fcsewardj         addHRegUse(u, HRmWrite, hregAMD64_R8());
147005b3b6a0474ba57b4dbd15ac26d857197cdc87fcsewardj         addHRegUse(u, HRmWrite, hregAMD64_R9());
147105b3b6a0474ba57b4dbd15ac26d857197cdc87fcsewardj         addHRegUse(u, HRmWrite, hregAMD64_R10());
147205b3b6a0474ba57b4dbd15ac26d857197cdc87fcsewardj         addHRegUse(u, HRmWrite, hregAMD64_R11());
14731001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj         addHRegUse(u, HRmWrite, hregAMD64_XMM0());
14741001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj         addHRegUse(u, HRmWrite, hregAMD64_XMM1());
14751001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj         addHRegUse(u, HRmWrite, hregAMD64_XMM3());
14761001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj         addHRegUse(u, HRmWrite, hregAMD64_XMM4());
14771001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj         addHRegUse(u, HRmWrite, hregAMD64_XMM5());
14781001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj         addHRegUse(u, HRmWrite, hregAMD64_XMM6());
14791001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj         addHRegUse(u, HRmWrite, hregAMD64_XMM7());
14801001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj         addHRegUse(u, HRmWrite, hregAMD64_XMM8());
14811001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj         addHRegUse(u, HRmWrite, hregAMD64_XMM9());
14821001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj         addHRegUse(u, HRmWrite, hregAMD64_XMM10());
14831001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj         addHRegUse(u, HRmWrite, hregAMD64_XMM11());
14841001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj         addHRegUse(u, HRmWrite, hregAMD64_XMM12());
148505b3b6a0474ba57b4dbd15ac26d857197cdc87fcsewardj
148605b3b6a0474ba57b4dbd15ac26d857197cdc87fcsewardj         /* Now we have to state any parameter-carrying registers
148705b3b6a0474ba57b4dbd15ac26d857197cdc87fcsewardj            which might be read.  This depends on the regparmness. */
148805b3b6a0474ba57b4dbd15ac26d857197cdc87fcsewardj         switch (i->Ain.Call.regparms) {
148905b3b6a0474ba57b4dbd15ac26d857197cdc87fcsewardj            case 6: addHRegUse(u, HRmRead, hregAMD64_R9());  /*fallthru*/
149005b3b6a0474ba57b4dbd15ac26d857197cdc87fcsewardj            case 5: addHRegUse(u, HRmRead, hregAMD64_R8());  /*fallthru*/
149105b3b6a0474ba57b4dbd15ac26d857197cdc87fcsewardj            case 4: addHRegUse(u, HRmRead, hregAMD64_RCX()); /*fallthru*/
149205b3b6a0474ba57b4dbd15ac26d857197cdc87fcsewardj            case 3: addHRegUse(u, HRmRead, hregAMD64_RDX()); /*fallthru*/
149305b3b6a0474ba57b4dbd15ac26d857197cdc87fcsewardj            case 2: addHRegUse(u, HRmRead, hregAMD64_RSI()); /*fallthru*/
149405b3b6a0474ba57b4dbd15ac26d857197cdc87fcsewardj            case 1: addHRegUse(u, HRmRead, hregAMD64_RDI()); break;
149505b3b6a0474ba57b4dbd15ac26d857197cdc87fcsewardj            case 0: break;
149605b3b6a0474ba57b4dbd15ac26d857197cdc87fcsewardj            default: vpanic("getRegUsage_AMD64Instr:Call:regparms");
149705b3b6a0474ba57b4dbd15ac26d857197cdc87fcsewardj         }
149805b3b6a0474ba57b4dbd15ac26d857197cdc87fcsewardj         /* Finally, there is the issue that the insn trashes a
149905b3b6a0474ba57b4dbd15ac26d857197cdc87fcsewardj            register because the literal target address has to be
150005b3b6a0474ba57b4dbd15ac26d857197cdc87fcsewardj            loaded into a register.  Fortunately, r11 is stated in the
150105b3b6a0474ba57b4dbd15ac26d857197cdc87fcsewardj            ABI as a scratch register, and so seems a suitable victim.  */
150205b3b6a0474ba57b4dbd15ac26d857197cdc87fcsewardj         addHRegUse(u, HRmWrite, hregAMD64_R11());
150305b3b6a0474ba57b4dbd15ac26d857197cdc87fcsewardj         /* Upshot of this is that the assembler really must use r11,
150405b3b6a0474ba57b4dbd15ac26d857197cdc87fcsewardj            and no other, as a destination temporary. */
150505b3b6a0474ba57b4dbd15ac26d857197cdc87fcsewardj         return;
1506c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      /* XDirect/XIndir/XAssisted are also a bit subtle.  They
1507c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         conditionally exit the block.  Hence we only need to list (1)
1508c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         the registers that they read, and (2) the registers that they
1509c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         write in the case where the block is not exited.  (2) is
1510c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         empty, hence only (1) is relevant here. */
1511c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      case Ain_XDirect:
1512c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         /* Don't bother to mention the write to %r11, since it is not
1513c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj            available to the allocator. */
1514c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         addRegUsage_AMD64AMode(u, i->Ain.XDirect.amRIP);
1515c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         return;
1516c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      case Ain_XIndir:
1517c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         /* Ditto re %r11 */
1518c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         addHRegUse(u, HRmRead, i->Ain.XIndir.dstGA);
1519c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         addRegUsage_AMD64AMode(u, i->Ain.XIndir.amRIP);
1520c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         return;
1521c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      case Ain_XAssisted:
1522c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         /* Ditto re %r11 and %rbp (the baseblock ptr) */
1523c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         addHRegUse(u, HRmRead, i->Ain.XAssisted.dstGA);
1524c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         addRegUsage_AMD64AMode(u, i->Ain.XAssisted.amRIP);
1525f67eadf04f5150178e589060f03381300d28e540sewardj         return;
152605b3b6a0474ba57b4dbd15ac26d857197cdc87fcsewardj      case Ain_CMov64:
1527e357c67787b7429f85a030ee5fbedf33173b5656sewardj         addHRegUse(u, HRmRead,   i->Ain.CMov64.src);
152805b3b6a0474ba57b4dbd15ac26d857197cdc87fcsewardj         addHRegUse(u, HRmModify, i->Ain.CMov64.dst);
152905b3b6a0474ba57b4dbd15ac26d857197cdc87fcsewardj         return;
1530bdea5508b371d394c81b91464fa8df767010d4dasewardj      case Ain_CLoad:
1531bdea5508b371d394c81b91464fa8df767010d4dasewardj         addRegUsage_AMD64AMode(u, i->Ain.CLoad.addr);
1532bdea5508b371d394c81b91464fa8df767010d4dasewardj         addHRegUse(u, HRmModify, i->Ain.CLoad.dst);
1533bdea5508b371d394c81b91464fa8df767010d4dasewardj         return;
15346f1ec58d9806064dea0000e4b543aacded9b11easewardj      case Ain_CStore:
15356f1ec58d9806064dea0000e4b543aacded9b11easewardj         addRegUsage_AMD64AMode(u, i->Ain.CStore.addr);
15366f1ec58d9806064dea0000e4b543aacded9b11easewardj         addHRegUse(u, HRmRead, i->Ain.CStore.src);
15376f1ec58d9806064dea0000e4b543aacded9b11easewardj         return;
1538ca257bc572147c1a9c7d9a2e81237125a35ff25dsewardj      case Ain_MovxLQ:
1539ca257bc572147c1a9c7d9a2e81237125a35ff25dsewardj         addHRegUse(u, HRmRead,  i->Ain.MovxLQ.src);
1540ca257bc572147c1a9c7d9a2e81237125a35ff25dsewardj         addHRegUse(u, HRmWrite, i->Ain.MovxLQ.dst);
1541f67eadf04f5150178e589060f03381300d28e540sewardj         return;
1542f67eadf04f5150178e589060f03381300d28e540sewardj      case Ain_LoadEX:
1543f67eadf04f5150178e589060f03381300d28e540sewardj         addRegUsage_AMD64AMode(u, i->Ain.LoadEX.src);
1544f67eadf04f5150178e589060f03381300d28e540sewardj         addHRegUse(u, HRmWrite, i->Ain.LoadEX.dst);
1545f67eadf04f5150178e589060f03381300d28e540sewardj         return;
154605b3b6a0474ba57b4dbd15ac26d857197cdc87fcsewardj      case Ain_Store:
154705b3b6a0474ba57b4dbd15ac26d857197cdc87fcsewardj         addHRegUse(u, HRmRead, i->Ain.Store.src);
154805b3b6a0474ba57b4dbd15ac26d857197cdc87fcsewardj         addRegUsage_AMD64AMode(u, i->Ain.Store.dst);
154905b3b6a0474ba57b4dbd15ac26d857197cdc87fcsewardj         return;
1550a5bd0aff6eda3e7c312f51ae6bc742ea62b5d404sewardj      case Ain_Set64:
1551a5bd0aff6eda3e7c312f51ae6bc742ea62b5d404sewardj         addHRegUse(u, HRmWrite, i->Ain.Set64.dst);
1552a5bd0aff6eda3e7c312f51ae6bc742ea62b5d404sewardj         return;
1553f53b7359a342e7d79090615169c6583a1a75fbcesewardj      case Ain_Bsfr64:
1554f53b7359a342e7d79090615169c6583a1a75fbcesewardj         addHRegUse(u, HRmRead, i->Ain.Bsfr64.src);
1555f53b7359a342e7d79090615169c6583a1a75fbcesewardj         addHRegUse(u, HRmWrite, i->Ain.Bsfr64.dst);
1556f53b7359a342e7d79090615169c6583a1a75fbcesewardj         return;
1557d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj      case Ain_MFence:
1558d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj         return;
1559e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj      case Ain_ACAS:
1560e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         addRegUsage_AMD64AMode(u, i->Ain.ACAS.addr);
1561e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         addHRegUse(u, HRmRead, hregAMD64_RBX());
1562e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         addHRegUse(u, HRmModify, hregAMD64_RAX());
1563e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         return;
1564e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj      case Ain_DACAS:
1565e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         addRegUsage_AMD64AMode(u, i->Ain.DACAS.addr);
1566e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         addHRegUse(u, HRmRead, hregAMD64_RCX());
1567e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         addHRegUse(u, HRmRead, hregAMD64_RBX());
1568e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         addHRegUse(u, HRmModify, hregAMD64_RDX());
1569e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         addHRegUse(u, HRmModify, hregAMD64_RAX());
1570e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         return;
157125a858136df4cbea0055c20aa7035d25fd40ee89sewardj      case Ain_A87Free:
157225a858136df4cbea0055c20aa7035d25fd40ee89sewardj         return;
157325a858136df4cbea0055c20aa7035d25fd40ee89sewardj      case Ain_A87PushPop:
157425a858136df4cbea0055c20aa7035d25fd40ee89sewardj         addRegUsage_AMD64AMode(u, i->Ain.A87PushPop.addr);
157525a858136df4cbea0055c20aa7035d25fd40ee89sewardj         return;
157625a858136df4cbea0055c20aa7035d25fd40ee89sewardj      case Ain_A87FpOp:
157725a858136df4cbea0055c20aa7035d25fd40ee89sewardj         return;
157825a858136df4cbea0055c20aa7035d25fd40ee89sewardj      case Ain_A87LdCW:
157925a858136df4cbea0055c20aa7035d25fd40ee89sewardj         addRegUsage_AMD64AMode(u, i->Ain.A87LdCW.addr);
158025a858136df4cbea0055c20aa7035d25fd40ee89sewardj         return;
1581f4c803b0947e7534809589cba8007851d78c7a2esewardj      case Ain_A87StSW:
1582f4c803b0947e7534809589cba8007851d78c7a2esewardj         addRegUsage_AMD64AMode(u, i->Ain.A87StSW.addr);
1583f4c803b0947e7534809589cba8007851d78c7a2esewardj         return;
15841a01e65f9993d97095c2af463e98674a091834casewardj      case Ain_LdMXCSR:
15851a01e65f9993d97095c2af463e98674a091834casewardj         addRegUsage_AMD64AMode(u, i->Ain.LdMXCSR.addr);
15861a01e65f9993d97095c2af463e98674a091834casewardj         return;
15871830386e7b10430c0c3630123a82d8bcf0a071e7sewardj      case Ain_SseUComIS:
15881830386e7b10430c0c3630123a82d8bcf0a071e7sewardj         addHRegUse(u, HRmRead,  i->Ain.SseUComIS.srcL);
15891830386e7b10430c0c3630123a82d8bcf0a071e7sewardj         addHRegUse(u, HRmRead,  i->Ain.SseUComIS.srcR);
15901830386e7b10430c0c3630123a82d8bcf0a071e7sewardj         addHRegUse(u, HRmWrite, i->Ain.SseUComIS.dst);
15911830386e7b10430c0c3630123a82d8bcf0a071e7sewardj         return;
15921a01e65f9993d97095c2af463e98674a091834casewardj      case Ain_SseSI2SF:
15931a01e65f9993d97095c2af463e98674a091834casewardj         addHRegUse(u, HRmRead,  i->Ain.SseSI2SF.src);
15941a01e65f9993d97095c2af463e98674a091834casewardj         addHRegUse(u, HRmWrite, i->Ain.SseSI2SF.dst);
15951a01e65f9993d97095c2af463e98674a091834casewardj         return;
15961a01e65f9993d97095c2af463e98674a091834casewardj      case Ain_SseSF2SI:
15971a01e65f9993d97095c2af463e98674a091834casewardj         addHRegUse(u, HRmRead,  i->Ain.SseSF2SI.src);
15981a01e65f9993d97095c2af463e98674a091834casewardj         addHRegUse(u, HRmWrite, i->Ain.SseSF2SI.dst);
15991a01e65f9993d97095c2af463e98674a091834casewardj         return;
16008d965316c72c2392f670dcdfa127547ec77c7e56sewardj      case Ain_SseSDSS:
16018d965316c72c2392f670dcdfa127547ec77c7e56sewardj         addHRegUse(u, HRmRead,  i->Ain.SseSDSS.src);
16028d965316c72c2392f670dcdfa127547ec77c7e56sewardj         addHRegUse(u, HRmWrite, i->Ain.SseSDSS.dst);
16038d965316c72c2392f670dcdfa127547ec77c7e56sewardj         return;
16041001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj      case Ain_SseLdSt:
16051001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj         addRegUsage_AMD64AMode(u, i->Ain.SseLdSt.addr);
16061001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj         addHRegUse(u, i->Ain.SseLdSt.isLoad ? HRmWrite : HRmRead,
16071001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj                       i->Ain.SseLdSt.reg);
16081001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj         return;
160970dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj      case Ain_SseCStore:
161070dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj         addRegUsage_AMD64AMode(u, i->Ain.SseCStore.addr);
161170dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj         addHRegUse(u, HRmRead, i->Ain.SseCStore.src);
161270dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj         return;
161370dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj      case Ain_SseCLoad:
161470dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj         addRegUsage_AMD64AMode(u, i->Ain.SseCLoad.addr);
161570dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj         addHRegUse(u, HRmModify, i->Ain.SseCLoad.dst);
161670dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj         return;
16171001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj      case Ain_SseLdzLO:
16181001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj         addRegUsage_AMD64AMode(u, i->Ain.SseLdzLO.addr);
16191001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj         addHRegUse(u, HRmWrite, i->Ain.SseLdzLO.reg);
16201001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj         return;
16218d965316c72c2392f670dcdfa127547ec77c7e56sewardj      case Ain_Sse32Fx4:
16228d965316c72c2392f670dcdfa127547ec77c7e56sewardj         vassert(i->Ain.Sse32Fx4.op != Asse_MOV);
162303ccf858efa285d793061359c04fdd0055cd9d31sewardj         unary = toBool( i->Ain.Sse32Fx4.op == Asse_RCPF
162403ccf858efa285d793061359c04fdd0055cd9d31sewardj                         || i->Ain.Sse32Fx4.op == Asse_RSQRTF
162503ccf858efa285d793061359c04fdd0055cd9d31sewardj                         || i->Ain.Sse32Fx4.op == Asse_SQRTF );
16268d965316c72c2392f670dcdfa127547ec77c7e56sewardj         addHRegUse(u, HRmRead, i->Ain.Sse32Fx4.src);
16278d965316c72c2392f670dcdfa127547ec77c7e56sewardj         addHRegUse(u, unary ? HRmWrite : HRmModify,
16288d965316c72c2392f670dcdfa127547ec77c7e56sewardj                       i->Ain.Sse32Fx4.dst);
16298d965316c72c2392f670dcdfa127547ec77c7e56sewardj         return;
16308d965316c72c2392f670dcdfa127547ec77c7e56sewardj      case Ain_Sse32FLo:
16318d965316c72c2392f670dcdfa127547ec77c7e56sewardj         vassert(i->Ain.Sse32FLo.op != Asse_MOV);
163203ccf858efa285d793061359c04fdd0055cd9d31sewardj         unary = toBool( i->Ain.Sse32FLo.op == Asse_RCPF
163303ccf858efa285d793061359c04fdd0055cd9d31sewardj                         || i->Ain.Sse32FLo.op == Asse_RSQRTF
163403ccf858efa285d793061359c04fdd0055cd9d31sewardj                         || i->Ain.Sse32FLo.op == Asse_SQRTF );
16358d965316c72c2392f670dcdfa127547ec77c7e56sewardj         addHRegUse(u, HRmRead, i->Ain.Sse32FLo.src);
16368d965316c72c2392f670dcdfa127547ec77c7e56sewardj         addHRegUse(u, unary ? HRmWrite : HRmModify,
16378d965316c72c2392f670dcdfa127547ec77c7e56sewardj                       i->Ain.Sse32FLo.dst);
16388d965316c72c2392f670dcdfa127547ec77c7e56sewardj         return;
16394c328cf28ebd12977fbf837c44a614c5aac660f3sewardj      case Ain_Sse64Fx2:
16404c328cf28ebd12977fbf837c44a614c5aac660f3sewardj         vassert(i->Ain.Sse64Fx2.op != Asse_MOV);
1641ca673ab9a76f5697f7ce086ff564bf26f4fa28besewardj         unary = toBool( i->Ain.Sse64Fx2.op == Asse_RCPF
1642ca673ab9a76f5697f7ce086ff564bf26f4fa28besewardj                         || i->Ain.Sse64Fx2.op == Asse_RSQRTF
1643ca673ab9a76f5697f7ce086ff564bf26f4fa28besewardj                         || i->Ain.Sse64Fx2.op == Asse_SQRTF );
16444c328cf28ebd12977fbf837c44a614c5aac660f3sewardj         addHRegUse(u, HRmRead, i->Ain.Sse64Fx2.src);
16454c328cf28ebd12977fbf837c44a614c5aac660f3sewardj         addHRegUse(u, unary ? HRmWrite : HRmModify,
16464c328cf28ebd12977fbf837c44a614c5aac660f3sewardj                       i->Ain.Sse64Fx2.dst);
16474c328cf28ebd12977fbf837c44a614c5aac660f3sewardj         return;
16481001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj      case Ain_Sse64FLo:
16491001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj         vassert(i->Ain.Sse64FLo.op != Asse_MOV);
165003ccf858efa285d793061359c04fdd0055cd9d31sewardj         unary = toBool( i->Ain.Sse64FLo.op == Asse_RCPF
165103ccf858efa285d793061359c04fdd0055cd9d31sewardj                         || i->Ain.Sse64FLo.op == Asse_RSQRTF
165203ccf858efa285d793061359c04fdd0055cd9d31sewardj                         || i->Ain.Sse64FLo.op == Asse_SQRTF );
16531001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj         addHRegUse(u, HRmRead, i->Ain.Sse64FLo.src);
16541001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj         addHRegUse(u, unary ? HRmWrite : HRmModify,
16551001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj                       i->Ain.Sse64FLo.dst);
16561001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj         return;
16571001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj      case Ain_SseReRg:
1658ac5304450fb867b10fce90f1c1774a153dc9576asewardj         if ( (i->Ain.SseReRg.op == Asse_XOR
1659ac5304450fb867b10fce90f1c1774a153dc9576asewardj               || i->Ain.SseReRg.op == Asse_CMPEQ32)
166079efdc6ea93db174395af845d4e21a4a7ad600ccflorian              && sameHReg(i->Ain.SseReRg.src, i->Ain.SseReRg.dst)) {
1661ac5304450fb867b10fce90f1c1774a153dc9576asewardj            /* reg-alloc needs to understand 'xor r,r' and 'cmpeqd
1662ac5304450fb867b10fce90f1c1774a153dc9576asewardj               r,r' as a write of a value to r, and independent of any
1663ac5304450fb867b10fce90f1c1774a153dc9576asewardj               previous value in r */
16641001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj            /* (as opposed to a rite of passage :-) */
16651001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj            addHRegUse(u, HRmWrite, i->Ain.SseReRg.dst);
16661001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj         } else {
16671001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj            addHRegUse(u, HRmRead, i->Ain.SseReRg.src);
16681001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj            addHRegUse(u, i->Ain.SseReRg.op == Asse_MOV
16691001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj                             ? HRmWrite : HRmModify,
16701001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj                          i->Ain.SseReRg.dst);
16711001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj         }
16721001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj         return;
16738d965316c72c2392f670dcdfa127547ec77c7e56sewardj      case Ain_SseCMov:
16748d965316c72c2392f670dcdfa127547ec77c7e56sewardj         addHRegUse(u, HRmRead,   i->Ain.SseCMov.src);
16758d965316c72c2392f670dcdfa127547ec77c7e56sewardj         addHRegUse(u, HRmModify, i->Ain.SseCMov.dst);
16768d965316c72c2392f670dcdfa127547ec77c7e56sewardj         return;
167709717341a0c364814e35bf405e61399d0e45fa7csewardj      case Ain_SseShuf:
167809717341a0c364814e35bf405e61399d0e45fa7csewardj         addHRegUse(u, HRmRead,  i->Ain.SseShuf.src);
167909717341a0c364814e35bf405e61399d0e45fa7csewardj         addHRegUse(u, HRmWrite, i->Ain.SseShuf.dst);
168009717341a0c364814e35bf405e61399d0e45fa7csewardj         return;
16813616a2ec4af166a3917810e4fdbe910ed80bd278sewardj      //uu case Ain_AvxLdSt:
16823616a2ec4af166a3917810e4fdbe910ed80bd278sewardj      //uu addRegUsage_AMD64AMode(u, i->Ain.AvxLdSt.addr);
16833616a2ec4af166a3917810e4fdbe910ed80bd278sewardj      //uu addHRegUse(u, i->Ain.AvxLdSt.isLoad ? HRmWrite : HRmRead,
16843616a2ec4af166a3917810e4fdbe910ed80bd278sewardj      //uu               i->Ain.AvxLdSt.reg);
16853616a2ec4af166a3917810e4fdbe910ed80bd278sewardj      //uu return;
16863616a2ec4af166a3917810e4fdbe910ed80bd278sewardj      //uu case Ain_AvxReRg:
16873616a2ec4af166a3917810e4fdbe910ed80bd278sewardj      //uu    if ( (i->Ain.AvxReRg.op == Asse_XOR
16883616a2ec4af166a3917810e4fdbe910ed80bd278sewardj      //uu          || i->Ain.AvxReRg.op == Asse_CMPEQ32)
16893616a2ec4af166a3917810e4fdbe910ed80bd278sewardj      //uu         && i->Ain.AvxReRg.src == i->Ain.AvxReRg.dst) {
16903616a2ec4af166a3917810e4fdbe910ed80bd278sewardj      //uu       /* See comments on the case for Ain_SseReRg. */
16913616a2ec4af166a3917810e4fdbe910ed80bd278sewardj      //uu       addHRegUse(u, HRmWrite, i->Ain.AvxReRg.dst);
16923616a2ec4af166a3917810e4fdbe910ed80bd278sewardj      //uu    } else {
16933616a2ec4af166a3917810e4fdbe910ed80bd278sewardj      //uu       addHRegUse(u, HRmRead, i->Ain.AvxReRg.src);
16943616a2ec4af166a3917810e4fdbe910ed80bd278sewardj      //uu       addHRegUse(u, i->Ain.AvxReRg.op == Asse_MOV
16953616a2ec4af166a3917810e4fdbe910ed80bd278sewardj      //uu                        ? HRmWrite : HRmModify,
16963616a2ec4af166a3917810e4fdbe910ed80bd278sewardj      //uu                     i->Ain.AvxReRg.dst);
16973616a2ec4af166a3917810e4fdbe910ed80bd278sewardj      //uu    }
16983616a2ec4af166a3917810e4fdbe910ed80bd278sewardj      //uu    return;
1699c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      case Ain_EvCheck:
1700c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         /* We expect both amodes only to mention %rbp, so this is in
1701c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj            fact pointless, since %rbp isn't allocatable, but anyway.. */
1702c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         addRegUsage_AMD64AMode(u, i->Ain.EvCheck.amCounter);
1703c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         addRegUsage_AMD64AMode(u, i->Ain.EvCheck.amFailAddr);
1704c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         return;
1705c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      case Ain_ProfInc:
1706c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         addHRegUse(u, HRmWrite, hregAMD64_R11());
1707c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         return;
1708c33671d7b0e21edb1d1015e4cbccbc6ca139e6d8sewardj      default:
170992b643609c5fa432b11fc726c2706ae3f3296eb4cerion         ppAMD64Instr(i, mode64);
1710c33671d7b0e21edb1d1015e4cbccbc6ca139e6d8sewardj         vpanic("getRegUsage_AMD64Instr");
1711c33671d7b0e21edb1d1015e4cbccbc6ca139e6d8sewardj   }
1712c33671d7b0e21edb1d1015e4cbccbc6ca139e6d8sewardj}
1713f67eadf04f5150178e589060f03381300d28e540sewardj
1714f67eadf04f5150178e589060f03381300d28e540sewardj/* local helper */
171525a858136df4cbea0055c20aa7035d25fd40ee89sewardjstatic inline void mapReg(HRegRemap* m, HReg* r)
1716f67eadf04f5150178e589060f03381300d28e540sewardj{
1717f67eadf04f5150178e589060f03381300d28e540sewardj   *r = lookupHRegRemap(m, *r);
1718f67eadf04f5150178e589060f03381300d28e540sewardj}
1719c33671d7b0e21edb1d1015e4cbccbc6ca139e6d8sewardj
172092b643609c5fa432b11fc726c2706ae3f3296eb4cerionvoid mapRegs_AMD64Instr ( HRegRemap* m, AMD64Instr* i, Bool mode64 )
1721c33671d7b0e21edb1d1015e4cbccbc6ca139e6d8sewardj{
172292b643609c5fa432b11fc726c2706ae3f3296eb4cerion   vassert(mode64 == True);
1723c33671d7b0e21edb1d1015e4cbccbc6ca139e6d8sewardj   switch (i->tag) {
1724813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj      case Ain_Imm64:
1725813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj         mapReg(m, &i->Ain.Imm64.dst);
1726813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj         return;
1727f67eadf04f5150178e589060f03381300d28e540sewardj      case Ain_Alu64R:
1728f67eadf04f5150178e589060f03381300d28e540sewardj         mapRegs_AMD64RMI(m, i->Ain.Alu64R.src);
1729f67eadf04f5150178e589060f03381300d28e540sewardj         mapReg(m, &i->Ain.Alu64R.dst);
1730f67eadf04f5150178e589060f03381300d28e540sewardj         return;
1731f67eadf04f5150178e589060f03381300d28e540sewardj      case Ain_Alu64M:
1732f67eadf04f5150178e589060f03381300d28e540sewardj         mapRegs_AMD64RI(m, i->Ain.Alu64M.src);
1733f67eadf04f5150178e589060f03381300d28e540sewardj         mapRegs_AMD64AMode(m, i->Ain.Alu64M.dst);
1734f67eadf04f5150178e589060f03381300d28e540sewardj         return;
1735f67eadf04f5150178e589060f03381300d28e540sewardj      case Ain_Sh64:
1736501a339ba08d28f30eb96d17b3f5bbe996ca6a4dsewardj         mapReg(m, &i->Ain.Sh64.dst);
1737f67eadf04f5150178e589060f03381300d28e540sewardj         return;
173805b3b6a0474ba57b4dbd15ac26d857197cdc87fcsewardj      case Ain_Test64:
1739501a339ba08d28f30eb96d17b3f5bbe996ca6a4dsewardj         mapReg(m, &i->Ain.Test64.dst);
174005b3b6a0474ba57b4dbd15ac26d857197cdc87fcsewardj         return;
1741d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj      case Ain_Unary64:
1742501a339ba08d28f30eb96d17b3f5bbe996ca6a4dsewardj         mapReg(m, &i->Ain.Unary64.dst);
1743d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj         return;
17446ce1a23b27d1729da9d705abd15b2007dce8daecsewardj      case Ain_Lea64:
17456ce1a23b27d1729da9d705abd15b2007dce8daecsewardj         mapRegs_AMD64AMode(m, i->Ain.Lea64.am);
17466ce1a23b27d1729da9d705abd15b2007dce8daecsewardj         mapReg(m, &i->Ain.Lea64.dst);
17476ce1a23b27d1729da9d705abd15b2007dce8daecsewardj         return;
17489cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj      case Ain_Alu32R:
17499cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj         mapRegs_AMD64RMI(m, i->Ain.Alu32R.src);
17509cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj         mapReg(m, &i->Ain.Alu32R.dst);
17519cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj         return;
17529b96767debeeb1f78378f0e7e295fe6762c64002sewardj      case Ain_MulL:
17539b96767debeeb1f78378f0e7e295fe6762c64002sewardj         mapRegs_AMD64RM(m, i->Ain.MulL.src);
17549b96767debeeb1f78378f0e7e295fe6762c64002sewardj         return;
17557de0d3c800437fbd82c59d57d156f4823d67609fsewardj      case Ain_Div:
17567de0d3c800437fbd82c59d57d156f4823d67609fsewardj         mapRegs_AMD64RM(m, i->Ain.Div.src);
17577de0d3c800437fbd82c59d57d156f4823d67609fsewardj         return;
17581001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj      case Ain_Push:
17591001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj         mapRegs_AMD64RMI(m, i->Ain.Push.src);
17601001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj         return;
176105b3b6a0474ba57b4dbd15ac26d857197cdc87fcsewardj      case Ain_Call:
176205b3b6a0474ba57b4dbd15ac26d857197cdc87fcsewardj         return;
1763c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      case Ain_XDirect:
1764c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         mapRegs_AMD64AMode(m, i->Ain.XDirect.amRIP);
1765c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         return;
1766c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      case Ain_XIndir:
1767c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         mapReg(m, &i->Ain.XIndir.dstGA);
1768c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         mapRegs_AMD64AMode(m, i->Ain.XIndir.amRIP);
1769c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         return;
1770c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      case Ain_XAssisted:
1771c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         mapReg(m, &i->Ain.XAssisted.dstGA);
1772c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         mapRegs_AMD64AMode(m, i->Ain.XAssisted.amRIP);
1773f67eadf04f5150178e589060f03381300d28e540sewardj         return;
177405b3b6a0474ba57b4dbd15ac26d857197cdc87fcsewardj      case Ain_CMov64:
1775e357c67787b7429f85a030ee5fbedf33173b5656sewardj         mapReg(m, &i->Ain.CMov64.src);
177605b3b6a0474ba57b4dbd15ac26d857197cdc87fcsewardj         mapReg(m, &i->Ain.CMov64.dst);
177705b3b6a0474ba57b4dbd15ac26d857197cdc87fcsewardj         return;
1778bdea5508b371d394c81b91464fa8df767010d4dasewardj      case Ain_CLoad:
1779bdea5508b371d394c81b91464fa8df767010d4dasewardj         mapRegs_AMD64AMode(m, i->Ain.CLoad.addr);
1780bdea5508b371d394c81b91464fa8df767010d4dasewardj         mapReg(m, &i->Ain.CLoad.dst);
1781bdea5508b371d394c81b91464fa8df767010d4dasewardj         return;
17826f1ec58d9806064dea0000e4b543aacded9b11easewardj      case Ain_CStore:
17836f1ec58d9806064dea0000e4b543aacded9b11easewardj         mapRegs_AMD64AMode(m, i->Ain.CStore.addr);
17846f1ec58d9806064dea0000e4b543aacded9b11easewardj         mapReg(m, &i->Ain.CStore.src);
17856f1ec58d9806064dea0000e4b543aacded9b11easewardj         return;
1786ca257bc572147c1a9c7d9a2e81237125a35ff25dsewardj      case Ain_MovxLQ:
1787ca257bc572147c1a9c7d9a2e81237125a35ff25dsewardj         mapReg(m, &i->Ain.MovxLQ.src);
1788ca257bc572147c1a9c7d9a2e81237125a35ff25dsewardj         mapReg(m, &i->Ain.MovxLQ.dst);
1789f67eadf04f5150178e589060f03381300d28e540sewardj         return;
1790f67eadf04f5150178e589060f03381300d28e540sewardj      case Ain_LoadEX:
1791f67eadf04f5150178e589060f03381300d28e540sewardj         mapRegs_AMD64AMode(m, i->Ain.LoadEX.src);
1792f67eadf04f5150178e589060f03381300d28e540sewardj         mapReg(m, &i->Ain.LoadEX.dst);
1793f67eadf04f5150178e589060f03381300d28e540sewardj         return;
179405b3b6a0474ba57b4dbd15ac26d857197cdc87fcsewardj      case Ain_Store:
179505b3b6a0474ba57b4dbd15ac26d857197cdc87fcsewardj         mapReg(m, &i->Ain.Store.src);
179605b3b6a0474ba57b4dbd15ac26d857197cdc87fcsewardj         mapRegs_AMD64AMode(m, i->Ain.Store.dst);
179705b3b6a0474ba57b4dbd15ac26d857197cdc87fcsewardj         return;
1798a5bd0aff6eda3e7c312f51ae6bc742ea62b5d404sewardj      case Ain_Set64:
1799a5bd0aff6eda3e7c312f51ae6bc742ea62b5d404sewardj         mapReg(m, &i->Ain.Set64.dst);
1800a5bd0aff6eda3e7c312f51ae6bc742ea62b5d404sewardj         return;
1801f53b7359a342e7d79090615169c6583a1a75fbcesewardj      case Ain_Bsfr64:
1802f53b7359a342e7d79090615169c6583a1a75fbcesewardj         mapReg(m, &i->Ain.Bsfr64.src);
1803f53b7359a342e7d79090615169c6583a1a75fbcesewardj         mapReg(m, &i->Ain.Bsfr64.dst);
1804f53b7359a342e7d79090615169c6583a1a75fbcesewardj         return;
1805d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj      case Ain_MFence:
1806d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj         return;
1807e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj      case Ain_ACAS:
1808e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         mapRegs_AMD64AMode(m, i->Ain.ACAS.addr);
1809e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         return;
1810e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj      case Ain_DACAS:
1811e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         mapRegs_AMD64AMode(m, i->Ain.DACAS.addr);
1812e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         return;
181325a858136df4cbea0055c20aa7035d25fd40ee89sewardj      case Ain_A87Free:
181425a858136df4cbea0055c20aa7035d25fd40ee89sewardj         return;
181525a858136df4cbea0055c20aa7035d25fd40ee89sewardj      case Ain_A87PushPop:
181625a858136df4cbea0055c20aa7035d25fd40ee89sewardj         mapRegs_AMD64AMode(m, i->Ain.A87PushPop.addr);
181725a858136df4cbea0055c20aa7035d25fd40ee89sewardj         return;
181825a858136df4cbea0055c20aa7035d25fd40ee89sewardj      case Ain_A87FpOp:
181925a858136df4cbea0055c20aa7035d25fd40ee89sewardj         return;
182025a858136df4cbea0055c20aa7035d25fd40ee89sewardj      case Ain_A87LdCW:
182125a858136df4cbea0055c20aa7035d25fd40ee89sewardj         mapRegs_AMD64AMode(m, i->Ain.A87LdCW.addr);
182225a858136df4cbea0055c20aa7035d25fd40ee89sewardj         return;
1823f4c803b0947e7534809589cba8007851d78c7a2esewardj      case Ain_A87StSW:
1824f4c803b0947e7534809589cba8007851d78c7a2esewardj         mapRegs_AMD64AMode(m, i->Ain.A87StSW.addr);
1825f4c803b0947e7534809589cba8007851d78c7a2esewardj         return;
18261a01e65f9993d97095c2af463e98674a091834casewardj      case Ain_LdMXCSR:
18271a01e65f9993d97095c2af463e98674a091834casewardj         mapRegs_AMD64AMode(m, i->Ain.LdMXCSR.addr);
18281a01e65f9993d97095c2af463e98674a091834casewardj         return;
18291830386e7b10430c0c3630123a82d8bcf0a071e7sewardj      case Ain_SseUComIS:
18301830386e7b10430c0c3630123a82d8bcf0a071e7sewardj         mapReg(m, &i->Ain.SseUComIS.srcL);
18311830386e7b10430c0c3630123a82d8bcf0a071e7sewardj         mapReg(m, &i->Ain.SseUComIS.srcR);
18321830386e7b10430c0c3630123a82d8bcf0a071e7sewardj         mapReg(m, &i->Ain.SseUComIS.dst);
18331830386e7b10430c0c3630123a82d8bcf0a071e7sewardj         return;
18341a01e65f9993d97095c2af463e98674a091834casewardj      case Ain_SseSI2SF:
18351a01e65f9993d97095c2af463e98674a091834casewardj         mapReg(m, &i->Ain.SseSI2SF.src);
18361a01e65f9993d97095c2af463e98674a091834casewardj         mapReg(m, &i->Ain.SseSI2SF.dst);
18371a01e65f9993d97095c2af463e98674a091834casewardj         return;
18381a01e65f9993d97095c2af463e98674a091834casewardj      case Ain_SseSF2SI:
18391a01e65f9993d97095c2af463e98674a091834casewardj         mapReg(m, &i->Ain.SseSF2SI.src);
18401a01e65f9993d97095c2af463e98674a091834casewardj         mapReg(m, &i->Ain.SseSF2SI.dst);
18411a01e65f9993d97095c2af463e98674a091834casewardj         return;
18428d965316c72c2392f670dcdfa127547ec77c7e56sewardj      case Ain_SseSDSS:
18438d965316c72c2392f670dcdfa127547ec77c7e56sewardj         mapReg(m, &i->Ain.SseSDSS.src);
18448d965316c72c2392f670dcdfa127547ec77c7e56sewardj         mapReg(m, &i->Ain.SseSDSS.dst);
18458d965316c72c2392f670dcdfa127547ec77c7e56sewardj         return;
18461001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj      case Ain_SseLdSt:
18471001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj         mapReg(m, &i->Ain.SseLdSt.reg);
18481001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj         mapRegs_AMD64AMode(m, i->Ain.SseLdSt.addr);
18491001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj         break;
185070dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj      case Ain_SseCStore:
185170dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj         mapRegs_AMD64AMode(m, i->Ain.SseCStore.addr);
185270dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj         mapReg(m, &i->Ain.SseCStore.src);
185370dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj         return;
185470dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj      case Ain_SseCLoad:
185570dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj         mapRegs_AMD64AMode(m, i->Ain.SseCLoad.addr);
185670dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj         mapReg(m, &i->Ain.SseCLoad.dst);
185770dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj         return;
18581001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj      case Ain_SseLdzLO:
18591001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj         mapReg(m, &i->Ain.SseLdzLO.reg);
18601001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj         mapRegs_AMD64AMode(m, i->Ain.SseLdzLO.addr);
18611001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj         break;
18628d965316c72c2392f670dcdfa127547ec77c7e56sewardj      case Ain_Sse32Fx4:
18638d965316c72c2392f670dcdfa127547ec77c7e56sewardj         mapReg(m, &i->Ain.Sse32Fx4.src);
18648d965316c72c2392f670dcdfa127547ec77c7e56sewardj         mapReg(m, &i->Ain.Sse32Fx4.dst);
18658d965316c72c2392f670dcdfa127547ec77c7e56sewardj         return;
18668d965316c72c2392f670dcdfa127547ec77c7e56sewardj      case Ain_Sse32FLo:
18678d965316c72c2392f670dcdfa127547ec77c7e56sewardj         mapReg(m, &i->Ain.Sse32FLo.src);
18688d965316c72c2392f670dcdfa127547ec77c7e56sewardj         mapReg(m, &i->Ain.Sse32FLo.dst);
18698d965316c72c2392f670dcdfa127547ec77c7e56sewardj         return;
18704c328cf28ebd12977fbf837c44a614c5aac660f3sewardj      case Ain_Sse64Fx2:
18714c328cf28ebd12977fbf837c44a614c5aac660f3sewardj         mapReg(m, &i->Ain.Sse64Fx2.src);
18724c328cf28ebd12977fbf837c44a614c5aac660f3sewardj         mapReg(m, &i->Ain.Sse64Fx2.dst);
18734c328cf28ebd12977fbf837c44a614c5aac660f3sewardj         return;
18741001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj      case Ain_Sse64FLo:
18751001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj         mapReg(m, &i->Ain.Sse64FLo.src);
18761001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj         mapReg(m, &i->Ain.Sse64FLo.dst);
18771001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj         return;
18781001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj      case Ain_SseReRg:
18791001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj         mapReg(m, &i->Ain.SseReRg.src);
18801001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj         mapReg(m, &i->Ain.SseReRg.dst);
18811001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj         return;
18828d965316c72c2392f670dcdfa127547ec77c7e56sewardj      case Ain_SseCMov:
18838d965316c72c2392f670dcdfa127547ec77c7e56sewardj         mapReg(m, &i->Ain.SseCMov.src);
18848d965316c72c2392f670dcdfa127547ec77c7e56sewardj         mapReg(m, &i->Ain.SseCMov.dst);
18858d965316c72c2392f670dcdfa127547ec77c7e56sewardj         return;
188609717341a0c364814e35bf405e61399d0e45fa7csewardj      case Ain_SseShuf:
188709717341a0c364814e35bf405e61399d0e45fa7csewardj         mapReg(m, &i->Ain.SseShuf.src);
188809717341a0c364814e35bf405e61399d0e45fa7csewardj         mapReg(m, &i->Ain.SseShuf.dst);
188909717341a0c364814e35bf405e61399d0e45fa7csewardj         return;
18903616a2ec4af166a3917810e4fdbe910ed80bd278sewardj      //uu case Ain_AvxLdSt:
18913616a2ec4af166a3917810e4fdbe910ed80bd278sewardj      //uu    mapReg(m, &i->Ain.AvxLdSt.reg);
18923616a2ec4af166a3917810e4fdbe910ed80bd278sewardj      //uu    mapRegs_AMD64AMode(m, i->Ain.AvxLdSt.addr);
18933616a2ec4af166a3917810e4fdbe910ed80bd278sewardj      //uu    break;
18943616a2ec4af166a3917810e4fdbe910ed80bd278sewardj      //uu case Ain_AvxReRg:
18953616a2ec4af166a3917810e4fdbe910ed80bd278sewardj      //uu    mapReg(m, &i->Ain.AvxReRg.src);
18963616a2ec4af166a3917810e4fdbe910ed80bd278sewardj      //uu    mapReg(m, &i->Ain.AvxReRg.dst);
18973616a2ec4af166a3917810e4fdbe910ed80bd278sewardj      //uu    return;
1898c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      case Ain_EvCheck:
1899c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         /* We expect both amodes only to mention %rbp, so this is in
1900c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj            fact pointless, since %rbp isn't allocatable, but anyway.. */
1901c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         mapRegs_AMD64AMode(m, i->Ain.EvCheck.amCounter);
1902c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         mapRegs_AMD64AMode(m, i->Ain.EvCheck.amFailAddr);
1903c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         return;
1904c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      case Ain_ProfInc:
1905c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         /* hardwires r11 -- nothing to modify. */
1906c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         return;
1907c33671d7b0e21edb1d1015e4cbccbc6ca139e6d8sewardj      default:
190892b643609c5fa432b11fc726c2706ae3f3296eb4cerion         ppAMD64Instr(i, mode64);
1909c33671d7b0e21edb1d1015e4cbccbc6ca139e6d8sewardj         vpanic("mapRegs_AMD64Instr");
1910c33671d7b0e21edb1d1015e4cbccbc6ca139e6d8sewardj   }
1911c33671d7b0e21edb1d1015e4cbccbc6ca139e6d8sewardj}
1912c33671d7b0e21edb1d1015e4cbccbc6ca139e6d8sewardj
1913c33671d7b0e21edb1d1015e4cbccbc6ca139e6d8sewardj/* Figure out if i represents a reg-reg move, and if so assign the
1914c33671d7b0e21edb1d1015e4cbccbc6ca139e6d8sewardj   source and destination to *src and *dst.  If in doubt say No.  Used
1915c33671d7b0e21edb1d1015e4cbccbc6ca139e6d8sewardj   by the register allocator to do move coalescing.
1916c33671d7b0e21edb1d1015e4cbccbc6ca139e6d8sewardj*/
1917d8c64e082224b2e688abdef9219cc76fd82b373bflorianBool isMove_AMD64Instr ( const AMD64Instr* i, HReg* src, HReg* dst )
1918c33671d7b0e21edb1d1015e4cbccbc6ca139e6d8sewardj{
1919c4530ae9079b0c3f8d4e8df35073613d718cadecsewardj   switch (i->tag) {
1920c4530ae9079b0c3f8d4e8df35073613d718cadecsewardj      case Ain_Alu64R:
1921c4530ae9079b0c3f8d4e8df35073613d718cadecsewardj         /* Moves between integer regs */
1922c4530ae9079b0c3f8d4e8df35073613d718cadecsewardj         if (i->Ain.Alu64R.op != Aalu_MOV)
1923c4530ae9079b0c3f8d4e8df35073613d718cadecsewardj            return False;
1924c4530ae9079b0c3f8d4e8df35073613d718cadecsewardj         if (i->Ain.Alu64R.src->tag != Armi_Reg)
1925c4530ae9079b0c3f8d4e8df35073613d718cadecsewardj            return False;
1926c4530ae9079b0c3f8d4e8df35073613d718cadecsewardj         *src = i->Ain.Alu64R.src->Armi.Reg.reg;
1927c4530ae9079b0c3f8d4e8df35073613d718cadecsewardj         *dst = i->Ain.Alu64R.dst;
1928c4530ae9079b0c3f8d4e8df35073613d718cadecsewardj         return True;
1929c4530ae9079b0c3f8d4e8df35073613d718cadecsewardj      case Ain_SseReRg:
1930c4530ae9079b0c3f8d4e8df35073613d718cadecsewardj         /* Moves between SSE regs */
1931c4530ae9079b0c3f8d4e8df35073613d718cadecsewardj         if (i->Ain.SseReRg.op != Asse_MOV)
1932c4530ae9079b0c3f8d4e8df35073613d718cadecsewardj            return False;
1933c4530ae9079b0c3f8d4e8df35073613d718cadecsewardj         *src = i->Ain.SseReRg.src;
1934c4530ae9079b0c3f8d4e8df35073613d718cadecsewardj         *dst = i->Ain.SseReRg.dst;
1935c4530ae9079b0c3f8d4e8df35073613d718cadecsewardj         return True;
19363616a2ec4af166a3917810e4fdbe910ed80bd278sewardj      //uu case Ain_AvxReRg:
19373616a2ec4af166a3917810e4fdbe910ed80bd278sewardj      //uu    /* Moves between AVX regs */
19383616a2ec4af166a3917810e4fdbe910ed80bd278sewardj      //uu    if (i->Ain.AvxReRg.op != Asse_MOV)
19393616a2ec4af166a3917810e4fdbe910ed80bd278sewardj      //uu       return False;
19403616a2ec4af166a3917810e4fdbe910ed80bd278sewardj      //uu    *src = i->Ain.AvxReRg.src;
19413616a2ec4af166a3917810e4fdbe910ed80bd278sewardj      //uu    *dst = i->Ain.AvxReRg.dst;
19423616a2ec4af166a3917810e4fdbe910ed80bd278sewardj      //uu    return True;
1943c4530ae9079b0c3f8d4e8df35073613d718cadecsewardj      default:
19441830386e7b10430c0c3630123a82d8bcf0a071e7sewardj         return False;
19451830386e7b10430c0c3630123a82d8bcf0a071e7sewardj   }
1946c4530ae9079b0c3f8d4e8df35073613d718cadecsewardj   /*NOTREACHED*/
1947c33671d7b0e21edb1d1015e4cbccbc6ca139e6d8sewardj}
1948c33671d7b0e21edb1d1015e4cbccbc6ca139e6d8sewardj
1949c33671d7b0e21edb1d1015e4cbccbc6ca139e6d8sewardj
1950c33671d7b0e21edb1d1015e4cbccbc6ca139e6d8sewardj/* Generate amd64 spill/reload instructions under the direction of the
1951c33671d7b0e21edb1d1015e4cbccbc6ca139e6d8sewardj   register allocator.  Note it's critical these don't write the
1952c33671d7b0e21edb1d1015e4cbccbc6ca139e6d8sewardj   condition codes. */
1953c33671d7b0e21edb1d1015e4cbccbc6ca139e6d8sewardj
19542a1ed8e417440976e0c8059715ee0c87d3e2f5ccsewardjvoid genSpill_AMD64 ( /*OUT*/HInstr** i1, /*OUT*/HInstr** i2,
19552a1ed8e417440976e0c8059715ee0c87d3e2f5ccsewardj                      HReg rreg, Int offsetB, Bool mode64 )
1956d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj{
1957d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj   AMD64AMode* am;
1958d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj   vassert(offsetB >= 0);
1959d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj   vassert(!hregIsVirtual(rreg));
196092b643609c5fa432b11fc726c2706ae3f3296eb4cerion   vassert(mode64 == True);
19612a1ed8e417440976e0c8059715ee0c87d3e2f5ccsewardj   *i1 = *i2 = NULL;
1962d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj   am = AMD64AMode_IR(offsetB, hregAMD64_RBP());
1963d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj   switch (hregClass(rreg)) {
1964d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj      case HRcInt64:
19652a1ed8e417440976e0c8059715ee0c87d3e2f5ccsewardj         *i1 = AMD64Instr_Alu64M ( Aalu_MOV, AMD64RI_Reg(rreg), am );
19662a1ed8e417440976e0c8059715ee0c87d3e2f5ccsewardj         return;
19671001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj      case HRcVec128:
19682a1ed8e417440976e0c8059715ee0c87d3e2f5ccsewardj         *i1 = AMD64Instr_SseLdSt ( False/*store*/, 16, rreg, am );
19692a1ed8e417440976e0c8059715ee0c87d3e2f5ccsewardj         return;
1970d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj      default:
1971d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj         ppHRegClass(hregClass(rreg));
1972d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj         vpanic("genSpill_AMD64: unimplemented regclass");
1973d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj   }
1974c33671d7b0e21edb1d1015e4cbccbc6ca139e6d8sewardj}
1975c33671d7b0e21edb1d1015e4cbccbc6ca139e6d8sewardj
19762a1ed8e417440976e0c8059715ee0c87d3e2f5ccsewardjvoid genReload_AMD64 ( /*OUT*/HInstr** i1, /*OUT*/HInstr** i2,
19772a1ed8e417440976e0c8059715ee0c87d3e2f5ccsewardj                       HReg rreg, Int offsetB, Bool mode64 )
1978d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj{
1979d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj   AMD64AMode* am;
1980d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj   vassert(offsetB >= 0);
1981d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj   vassert(!hregIsVirtual(rreg));
198292b643609c5fa432b11fc726c2706ae3f3296eb4cerion   vassert(mode64 == True);
19832a1ed8e417440976e0c8059715ee0c87d3e2f5ccsewardj   *i1 = *i2 = NULL;
1984d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj   am = AMD64AMode_IR(offsetB, hregAMD64_RBP());
1985d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj   switch (hregClass(rreg)) {
1986d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj      case HRcInt64:
19872a1ed8e417440976e0c8059715ee0c87d3e2f5ccsewardj         *i1 = AMD64Instr_Alu64R ( Aalu_MOV, AMD64RMI_Mem(am), rreg );
19882a1ed8e417440976e0c8059715ee0c87d3e2f5ccsewardj         return;
19891001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj      case HRcVec128:
19902a1ed8e417440976e0c8059715ee0c87d3e2f5ccsewardj         *i1 = AMD64Instr_SseLdSt ( True/*load*/, 16, rreg, am );
19912a1ed8e417440976e0c8059715ee0c87d3e2f5ccsewardj         return;
1992d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj      default:
1993d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj         ppHRegClass(hregClass(rreg));
1994d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj         vpanic("genReload_AMD64: unimplemented regclass");
1995d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj   }
1996c33671d7b0e21edb1d1015e4cbccbc6ca139e6d8sewardj}
1997c33671d7b0e21edb1d1015e4cbccbc6ca139e6d8sewardj
1998ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott HughesAMD64Instr* directReload_AMD64( AMD64Instr* i, HReg vreg, Short spill_off )
1999ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes{
2000ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes   vassert(spill_off >= 0 && spill_off < 10000); /* let's say */
2001ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes
2002ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes   /* Deal with form: src=RMI_Reg, dst=Reg where src == vreg
2003ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes      Convert to: src=RMI_Mem, dst=Reg
2004ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes   */
2005ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes   if (i->tag == Ain_Alu64R
2006ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes       && (i->Ain.Alu64R.op == Aalu_MOV || i->Ain.Alu64R.op == Aalu_OR
2007ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes           || i->Ain.Alu64R.op == Aalu_XOR)
2008ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes       && i->Ain.Alu64R.src->tag == Armi_Reg
2009ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes       && sameHReg(i->Ain.Alu64R.src->Armi.Reg.reg, vreg)) {
2010ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes      vassert(! sameHReg(i->Ain.Alu64R.dst, vreg));
2011ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes      return AMD64Instr_Alu64R(
2012ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes                i->Ain.Alu64R.op,
2013ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes                AMD64RMI_Mem( AMD64AMode_IR( spill_off, hregAMD64_RBP())),
2014ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes                i->Ain.Alu64R.dst
2015ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes             );
2016ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes   }
2017ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes
2018ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes   /* Deal with form: src=RMI_Imm, dst=Reg where dst == vreg
2019ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes      Convert to: src=RI_Imm, dst=Mem
2020ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes   */
2021ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes   if (i->tag == Ain_Alu64R
2022ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes       && (i->Ain.Alu64R.op == Aalu_CMP)
2023ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes       && i->Ain.Alu64R.src->tag == Armi_Imm
2024ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes       && sameHReg(i->Ain.Alu64R.dst, vreg)) {
2025ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes      return AMD64Instr_Alu64M(
2026ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes                i->Ain.Alu64R.op,
2027ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes                AMD64RI_Imm( i->Ain.Alu64R.src->Armi.Imm.imm32 ),
2028ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes                AMD64AMode_IR( spill_off, hregAMD64_RBP())
2029ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes             );
2030ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes   }
2031ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes
2032ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes   return NULL;
2033ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes}
2034ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes
2035c33671d7b0e21edb1d1015e4cbccbc6ca139e6d8sewardj
2036813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj/* --------- The amd64 assembler (bleh.) --------- */
2037813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj
2038813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj/* Produce the low three bits of an integer register number. */
2039a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardjinline static UInt iregEnc210 ( HReg r )
2040813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj{
2041813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj   UInt n;
2042813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj   vassert(hregClass(r) == HRcInt64);
2043813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj   vassert(!hregIsVirtual(r));
2044a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj   n = hregEncoding(r);
2045813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj   vassert(n <= 15);
2046a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj   return n & 7;
2047813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj}
2048813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj
2049813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj/* Produce bit 3 of an integer register number. */
2050a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardjinline static UInt iregEnc3 ( HReg r )
2051813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj{
2052813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj   UInt n;
2053813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj   vassert(hregClass(r) == HRcInt64);
2054813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj   vassert(!hregIsVirtual(r));
2055a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj   n = hregEncoding(r);
2056813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj   vassert(n <= 15);
2057a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj   return (n >> 3) & 1;
2058813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj}
2059813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj
2060dc2ca89b181aa0429f7c62aed4f94cfb415ec02esewardj/* Produce a complete 4-bit integer register number. */
2061a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardjinline static UInt iregEnc3210 ( HReg r )
2062dc2ca89b181aa0429f7c62aed4f94cfb415ec02esewardj{
2063dc2ca89b181aa0429f7c62aed4f94cfb415ec02esewardj   UInt n;
2064dc2ca89b181aa0429f7c62aed4f94cfb415ec02esewardj   vassert(hregClass(r) == HRcInt64);
2065dc2ca89b181aa0429f7c62aed4f94cfb415ec02esewardj   vassert(!hregIsVirtual(r));
2066a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj   n = hregEncoding(r);
2067dc2ca89b181aa0429f7c62aed4f94cfb415ec02esewardj   vassert(n <= 15);
2068a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj   return n;
2069dc2ca89b181aa0429f7c62aed4f94cfb415ec02esewardj}
2070dc2ca89b181aa0429f7c62aed4f94cfb415ec02esewardj
2071a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj/* Produce a complete 4-bit integer register number. */
2072a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardjinline static UInt vregEnc3210 ( HReg r )
20731001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj{
20741001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj   UInt n;
20751001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj   vassert(hregClass(r) == HRcVec128);
20761001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj   vassert(!hregIsVirtual(r));
2077a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj   n = hregEncoding(r);
20781001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj   vassert(n <= 15);
2079a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj   return n;
20801001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj}
2081813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj
2082a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardjinline static UChar mkModRegRM ( UInt mod, UInt reg, UInt regmem )
2083813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj{
2084b5e7ced3600c90faa2ebf9dbbdc0e0e6cda7bfc7sewardj   vassert(mod < 4);
2085b5e7ced3600c90faa2ebf9dbbdc0e0e6cda7bfc7sewardj   vassert((reg|regmem) < 8);
2086a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj   return (UChar)( ((mod & 3) << 6) | ((reg & 7) << 3) | (regmem & 7) );
2087813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj}
2088813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj
2089a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardjinline static UChar mkSIB ( UInt shift, UInt regindex, UInt regbase )
2090813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj{
2091b5e7ced3600c90faa2ebf9dbbdc0e0e6cda7bfc7sewardj   vassert(shift < 4);
2092b5e7ced3600c90faa2ebf9dbbdc0e0e6cda7bfc7sewardj   vassert((regindex|regbase) < 8);
2093a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj   return (UChar)( ((shift & 3) << 6) | ((regindex & 7) << 3) | (regbase & 7) );
2094813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj}
2095813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj
2096813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardjstatic UChar* emit32 ( UChar* p, UInt w32 )
2097813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj{
209803ccf858efa285d793061359c04fdd0055cd9d31sewardj   *p++ = toUChar((w32)       & 0x000000FF);
209903ccf858efa285d793061359c04fdd0055cd9d31sewardj   *p++ = toUChar((w32 >>  8) & 0x000000FF);
210003ccf858efa285d793061359c04fdd0055cd9d31sewardj   *p++ = toUChar((w32 >> 16) & 0x000000FF);
210103ccf858efa285d793061359c04fdd0055cd9d31sewardj   *p++ = toUChar((w32 >> 24) & 0x000000FF);
2102813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj   return p;
2103813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj}
2104813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj
21051b8d58eb046ad31fbb058d65855b604886d3d177sewardjstatic UChar* emit64 ( UChar* p, ULong w64 )
21061b8d58eb046ad31fbb058d65855b604886d3d177sewardj{
210703ccf858efa285d793061359c04fdd0055cd9d31sewardj   p = emit32(p, toUInt(w64         & 0xFFFFFFFF));
210803ccf858efa285d793061359c04fdd0055cd9d31sewardj   p = emit32(p, toUInt((w64 >> 32) & 0xFFFFFFFF));
21091b8d58eb046ad31fbb058d65855b604886d3d177sewardj   return p;
21101b8d58eb046ad31fbb058d65855b604886d3d177sewardj}
21111b8d58eb046ad31fbb058d65855b604886d3d177sewardj
2112813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj/* Does a sign-extend of the lowest 8 bits give
2113813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj   the original number? */
2114813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardjstatic Bool fits8bits ( UInt w32 )
2115813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj{
2116813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj   Int i32 = (Int)w32;
2117108e03fcb0a4ef42164235b1988aa540aa1e5298florian   return toBool(i32 == ((Int)(w32 << 24) >> 24));
2118813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj}
21194d77a9c73b332df0f5c7c36c2d8d72c7f22b735dsewardj/* Can the lower 32 bits be signedly widened to produce the whole
21204d77a9c73b332df0f5c7c36c2d8d72c7f22b735dsewardj   64-bit value?  In other words, are the top 33 bits either all 0 or
21214d77a9c73b332df0f5c7c36c2d8d72c7f22b735dsewardj   all 1 ? */
21224d77a9c73b332df0f5c7c36c2d8d72c7f22b735dsewardjstatic Bool fitsIn32Bits ( ULong x )
21234d77a9c73b332df0f5c7c36c2d8d72c7f22b735dsewardj{
2124108e03fcb0a4ef42164235b1988aa540aa1e5298florian   Long y1;
2125108e03fcb0a4ef42164235b1988aa540aa1e5298florian   y1 = x << 32;
21264d77a9c73b332df0f5c7c36c2d8d72c7f22b735dsewardj   y1 >>=/*s*/ 32;
21274d77a9c73b332df0f5c7c36c2d8d72c7f22b735dsewardj   return toBool(x == y1);
21284d77a9c73b332df0f5c7c36c2d8d72c7f22b735dsewardj}
2129813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj
2130813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj
2131813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj/* Forming mod-reg-rm bytes and scale-index-base bytes.
2132813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj
2133e95b04a535c72c948cf135f802fbdca5d3b23f76sewardj     greg,  0(ereg)    |  ereg is not any of: RSP RBP R12 R13
2134813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj                       =  00 greg ereg
2135813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj
2136e95b04a535c72c948cf135f802fbdca5d3b23f76sewardj     greg,  d8(ereg)   |  ereg is neither of: RSP R12
2137813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj                       =  01 greg ereg, d8
2138813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj
2139e95b04a535c72c948cf135f802fbdca5d3b23f76sewardj     greg,  d32(ereg)  |  ereg is neither of: RSP R12
2140813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj                       =  10 greg ereg, d32
2141813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj
2142e95b04a535c72c948cf135f802fbdca5d3b23f76sewardj     greg,  d8(ereg)   |  ereg is either: RSP R12
2143e95b04a535c72c948cf135f802fbdca5d3b23f76sewardj                       =  01 greg 100, 0x24, d8
2144e95b04a535c72c948cf135f802fbdca5d3b23f76sewardj                       (lowest bit of rex distinguishes R12/RSP)
2145e95b04a535c72c948cf135f802fbdca5d3b23f76sewardj
21467de0d3c800437fbd82c59d57d156f4823d67609fsewardj     greg,  d32(ereg)  |  ereg is either: RSP R12
21477de0d3c800437fbd82c59d57d156f4823d67609fsewardj                       =  10 greg 100, 0x24, d32
21487de0d3c800437fbd82c59d57d156f4823d67609fsewardj                       (lowest bit of rex distinguishes R12/RSP)
2149813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj
2150813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj     -----------------------------------------------
2151813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj
2152813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj     greg,  d8(base,index,scale)
2153813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj               |  index != RSP
2154813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj               =  01 greg 100, scale index base, d8
2155813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj
2156813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj     greg,  d32(base,index,scale)
2157813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj               |  index != RSP
2158813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj               =  10 greg 100, scale index base, d32
2159813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj*/
2160a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardjstatic UChar* doAMode_M__wrk ( UChar* p, UInt gregEnc3210, AMD64AMode* am )
2161813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj{
2162a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj   UInt gregEnc210 = gregEnc3210 & 7;
2163813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj   if (am->tag == Aam_IR) {
2164813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj      if (am->Aam.IR.imm == 0
216579efdc6ea93db174395af845d4e21a4a7ad600ccflorian          && ! sameHReg(am->Aam.IR.reg, hregAMD64_RSP())
216679efdc6ea93db174395af845d4e21a4a7ad600ccflorian          && ! sameHReg(am->Aam.IR.reg, hregAMD64_RBP())
216779efdc6ea93db174395af845d4e21a4a7ad600ccflorian          && ! sameHReg(am->Aam.IR.reg, hregAMD64_R12())
216879efdc6ea93db174395af845d4e21a4a7ad600ccflorian          && ! sameHReg(am->Aam.IR.reg, hregAMD64_R13())
2169e95b04a535c72c948cf135f802fbdca5d3b23f76sewardj         ) {
2170a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj         *p++ = mkModRegRM(0, gregEnc210, iregEnc210(am->Aam.IR.reg));
2171813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj         return p;
2172813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj      }
2173813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj      if (fits8bits(am->Aam.IR.imm)
217479efdc6ea93db174395af845d4e21a4a7ad600ccflorian          && ! sameHReg(am->Aam.IR.reg, hregAMD64_RSP())
217579efdc6ea93db174395af845d4e21a4a7ad600ccflorian          && ! sameHReg(am->Aam.IR.reg, hregAMD64_R12())
2176e95b04a535c72c948cf135f802fbdca5d3b23f76sewardj         ) {
2177a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj         *p++ = mkModRegRM(1, gregEnc210, iregEnc210(am->Aam.IR.reg));
217803ccf858efa285d793061359c04fdd0055cd9d31sewardj         *p++ = toUChar(am->Aam.IR.imm & 0xFF);
2179813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj         return p;
2180813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj      }
218179efdc6ea93db174395af845d4e21a4a7ad600ccflorian      if (! sameHReg(am->Aam.IR.reg, hregAMD64_RSP())
218279efdc6ea93db174395af845d4e21a4a7ad600ccflorian          && ! sameHReg(am->Aam.IR.reg, hregAMD64_R12())
2183e95b04a535c72c948cf135f802fbdca5d3b23f76sewardj         ) {
2184a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj         *p++ = mkModRegRM(2, gregEnc210, iregEnc210(am->Aam.IR.reg));
2185813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj         p = emit32(p, am->Aam.IR.imm);
2186813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj         return p;
2187813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj      }
218879efdc6ea93db174395af845d4e21a4a7ad600ccflorian      if ((sameHReg(am->Aam.IR.reg, hregAMD64_RSP())
218979efdc6ea93db174395af845d4e21a4a7ad600ccflorian           || sameHReg(am->Aam.IR.reg, hregAMD64_R12()))
2190813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj          && fits8bits(am->Aam.IR.imm)) {
2191a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj 	 *p++ = mkModRegRM(1, gregEnc210, 4);
2192813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj         *p++ = 0x24;
219303ccf858efa285d793061359c04fdd0055cd9d31sewardj         *p++ = toUChar(am->Aam.IR.imm & 0xFF);
2194813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj         return p;
2195813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj      }
219679efdc6ea93db174395af845d4e21a4a7ad600ccflorian      if (/* (sameHReg(am->Aam.IR.reg, hregAMD64_RSP())
2197a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj	      || wait for test case for RSP case */
219879efdc6ea93db174395af845d4e21a4a7ad600ccflorian          sameHReg(am->Aam.IR.reg, hregAMD64_R12())) {
2199a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj 	 *p++ = mkModRegRM(2, gregEnc210, 4);
22007de0d3c800437fbd82c59d57d156f4823d67609fsewardj         *p++ = 0x24;
22017de0d3c800437fbd82c59d57d156f4823d67609fsewardj         p = emit32(p, am->Aam.IR.imm);
22027de0d3c800437fbd82c59d57d156f4823d67609fsewardj         return p;
22037de0d3c800437fbd82c59d57d156f4823d67609fsewardj      }
2204813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj      ppAMD64AMode(am);
2205813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj      vpanic("doAMode_M: can't emit amode IR");
2206813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj      /*NOTREACHED*/
2207813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj   }
2208813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj   if (am->tag == Aam_IRRS) {
2209813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj      if (fits8bits(am->Aam.IRRS.imm)
221079efdc6ea93db174395af845d4e21a4a7ad600ccflorian          && ! sameHReg(am->Aam.IRRS.index, hregAMD64_RSP())) {
2211a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj         *p++ = mkModRegRM(1, gregEnc210, 4);
2212a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj         *p++ = mkSIB(am->Aam.IRRS.shift, iregEnc210(am->Aam.IRRS.index),
2213a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj                                          iregEnc210(am->Aam.IRRS.base));
221403ccf858efa285d793061359c04fdd0055cd9d31sewardj         *p++ = toUChar(am->Aam.IRRS.imm & 0xFF);
2215813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj         return p;
2216813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj      }
221779efdc6ea93db174395af845d4e21a4a7ad600ccflorian      if (! sameHReg(am->Aam.IRRS.index, hregAMD64_RSP())) {
2218a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj         *p++ = mkModRegRM(2, gregEnc210, 4);
2219a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj         *p++ = mkSIB(am->Aam.IRRS.shift, iregEnc210(am->Aam.IRRS.index),
2220a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj                                          iregEnc210(am->Aam.IRRS.base));
2221813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj         p = emit32(p, am->Aam.IRRS.imm);
2222813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj         return p;
2223813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj      }
2224813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj      ppAMD64AMode(am);
2225813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj      vpanic("doAMode_M: can't emit amode IRRS");
2226813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj      /*NOTREACHED*/
2227813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj   }
2228813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj   vpanic("doAMode_M: unknown amode");
2229813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj   /*NOTREACHED*/
2230813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj}
2231813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj
2232a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardjstatic UChar* doAMode_M ( UChar* p, HReg greg, AMD64AMode* am )
2233a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj{
2234a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj   return doAMode_M__wrk(p, iregEnc3210(greg), am);
2235a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj}
2236a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj
2237a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardjstatic UChar* doAMode_M_enc ( UChar* p, UInt gregEnc3210, AMD64AMode* am )
2238a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj{
2239a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj   vassert(gregEnc3210 < 16);
2240a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj   return doAMode_M__wrk(p, gregEnc3210, am);
2241a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj}
2242a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj
2243813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj
2244813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj/* Emit a mod-reg-rm byte when the rm bit denotes a reg. */
2245a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardjinline
2246a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardjstatic UChar* doAMode_R__wrk ( UChar* p, UInt gregEnc3210, UInt eregEnc3210 )
2247813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj{
2248a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj   *p++ = mkModRegRM(3, gregEnc3210 & 7, eregEnc3210 & 7);
2249813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj   return p;
2250813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj}
2251813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj
2252a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardjstatic UChar* doAMode_R ( UChar* p, HReg greg, HReg ereg )
2253a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj{
2254a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj   return doAMode_R__wrk(p, iregEnc3210(greg), iregEnc3210(ereg));
2255a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj}
2256a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj
2257a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardjstatic UChar* doAMode_R_enc_reg ( UChar* p, UInt gregEnc3210, HReg ereg )
2258a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj{
2259a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj   vassert(gregEnc3210 < 16);
2260a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj   return doAMode_R__wrk(p, gregEnc3210, iregEnc3210(ereg));
2261a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj}
2262a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj
2263a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardjstatic UChar* doAMode_R_reg_enc ( UChar* p, HReg greg, UInt eregEnc3210 )
2264a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj{
2265a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj   vassert(eregEnc3210 < 16);
2266a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj   return doAMode_R__wrk(p, iregEnc3210(greg), eregEnc3210);
2267a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj}
2268a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj
2269a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardjstatic UChar* doAMode_R_enc_enc ( UChar* p, UInt gregEnc3210, UInt eregEnc3210 )
2270a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj{
2271a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj   vassert( (gregEnc3210|eregEnc3210) < 16);
2272a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj   return doAMode_R__wrk(p, gregEnc3210, eregEnc3210);
2273a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj}
2274a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj
2275813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj
2276549e06463d433ee6351b72dc9107f22ce4305250sewardj/* Clear the W bit on a REX byte, thereby changing the operand size
2277549e06463d433ee6351b72dc9107f22ce4305250sewardj   back to whatever that instruction's default operand size is. */
2278549e06463d433ee6351b72dc9107f22ce4305250sewardjstatic inline UChar clearWBit ( UChar rex )
2279549e06463d433ee6351b72dc9107f22ce4305250sewardj{
2280a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj   return rex & ~(1<<3);
2281549e06463d433ee6351b72dc9107f22ce4305250sewardj}
2282549e06463d433ee6351b72dc9107f22ce4305250sewardj
2283549e06463d433ee6351b72dc9107f22ce4305250sewardj
2284549e06463d433ee6351b72dc9107f22ce4305250sewardj/* Make up a REX byte, with W=1 (size=64), for a (greg,amode) pair. */
2285a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardjinline static UChar rexAMode_M__wrk ( UInt gregEnc3210, AMD64AMode* am )
2286813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj{
2287813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj   if (am->tag == Aam_IR) {
2288813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj      UChar W = 1;  /* we want 64-bit mode */
2289a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj      UChar R = (gregEnc3210 >> 3) & 1;
2290813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj      UChar X = 0; /* not relevant */
2291a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj      UChar B = iregEnc3(am->Aam.IR.reg);
2292a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj      return 0x40 + ((W << 3) | (R << 2) | (X << 1) | (B << 0));
2293813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj   }
2294813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj   if (am->tag == Aam_IRRS) {
2295813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj      UChar W = 1;  /* we want 64-bit mode */
2296a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj      UChar R = (gregEnc3210 >> 3) & 1;
2297a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj      UChar X = iregEnc3(am->Aam.IRRS.index);
2298a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj      UChar B = iregEnc3(am->Aam.IRRS.base);
2299a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj      return 0x40 + ((W << 3) | (R << 2) | (X << 1) | (B << 0));
2300813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj   }
2301813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj   vassert(0);
230203ccf858efa285d793061359c04fdd0055cd9d31sewardj   return 0; /*NOTREACHED*/
2303813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj}
2304813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj
2305a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardjstatic UChar rexAMode_M ( HReg greg, AMD64AMode* am )
2306a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj{
2307a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj   return rexAMode_M__wrk(iregEnc3210(greg), am);
2308a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj}
2309a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj
2310a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardjstatic UChar rexAMode_M_enc ( UInt gregEnc3210, AMD64AMode* am )
2311a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj{
2312a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj   vassert(gregEnc3210 < 16);
2313a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj   return rexAMode_M__wrk(gregEnc3210, am);
2314a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj}
2315a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj
2316a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj
2317549e06463d433ee6351b72dc9107f22ce4305250sewardj/* Make up a REX byte, with W=1 (size=64), for a (greg,ereg) pair. */
2318a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardjinline static UChar rexAMode_R__wrk ( UInt gregEnc3210, UInt eregEnc3210 )
2319549e06463d433ee6351b72dc9107f22ce4305250sewardj{
2320549e06463d433ee6351b72dc9107f22ce4305250sewardj   UChar W = 1;  /* we want 64-bit mode */
2321a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj   UChar R = (gregEnc3210 >> 3) & 1;
2322549e06463d433ee6351b72dc9107f22ce4305250sewardj   UChar X = 0; /* not relevant */
2323a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj   UChar B = (eregEnc3210 >> 3) & 1;
2324a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj   return 0x40 + ((W << 3) | (R << 2) | (X << 1) | (B << 0));
2325a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj}
2326a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj
2327a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardjstatic UChar rexAMode_R ( HReg greg, HReg ereg )
2328a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj{
2329a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj   return rexAMode_R__wrk(iregEnc3210(greg), iregEnc3210(ereg));
2330a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj}
2331a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj
2332a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardjstatic UChar rexAMode_R_enc_reg ( UInt gregEnc3210, HReg ereg )
2333a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj{
2334a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj   vassert(gregEnc3210 < 16);
2335a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj   return rexAMode_R__wrk(gregEnc3210, iregEnc3210(ereg));
2336a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj}
2337a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj
2338a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardjstatic UChar rexAMode_R_reg_enc ( HReg greg, UInt eregEnc3210 )
2339a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj{
2340a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj   vassert(eregEnc3210 < 16);
2341a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj   return rexAMode_R__wrk(iregEnc3210(greg), eregEnc3210);
2342a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj}
2343a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj
2344a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardjstatic UChar rexAMode_R_enc_enc ( UInt gregEnc3210, UInt eregEnc3210 )
2345a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj{
2346a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj   vassert((gregEnc3210|eregEnc3210) < 16);
2347a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj   return rexAMode_R__wrk(gregEnc3210, eregEnc3210);
2348549e06463d433ee6351b72dc9107f22ce4305250sewardj}
2349549e06463d433ee6351b72dc9107f22ce4305250sewardj
2350813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj
23513616a2ec4af166a3917810e4fdbe910ed80bd278sewardj//uu /* May 2012: this VEX prefix stuff is currently unused, but has
23523616a2ec4af166a3917810e4fdbe910ed80bd278sewardj//uu    verified correct (I reckon).  Certainly it has been known to
23533616a2ec4af166a3917810e4fdbe910ed80bd278sewardj//uu    produce correct VEX prefixes during testing. */
23543616a2ec4af166a3917810e4fdbe910ed80bd278sewardj//uu
23553616a2ec4af166a3917810e4fdbe910ed80bd278sewardj//uu /* Assemble a 2 or 3 byte VEX prefix from parts.  rexR, rexX, rexB and
23563616a2ec4af166a3917810e4fdbe910ed80bd278sewardj//uu    notVvvvv need to be not-ed before packing.  mmmmm, rexW, L and pp go
23573616a2ec4af166a3917810e4fdbe910ed80bd278sewardj//uu    in verbatim.  There's no range checking on the bits. */
23583616a2ec4af166a3917810e4fdbe910ed80bd278sewardj//uu static UInt packVexPrefix ( UInt rexR, UInt rexX, UInt rexB,
23593616a2ec4af166a3917810e4fdbe910ed80bd278sewardj//uu                             UInt mmmmm, UInt rexW, UInt notVvvv,
23603616a2ec4af166a3917810e4fdbe910ed80bd278sewardj//uu                             UInt L, UInt pp )
23613616a2ec4af166a3917810e4fdbe910ed80bd278sewardj//uu {
23623616a2ec4af166a3917810e4fdbe910ed80bd278sewardj//uu    UChar byte0 = 0;
23633616a2ec4af166a3917810e4fdbe910ed80bd278sewardj//uu    UChar byte1 = 0;
23643616a2ec4af166a3917810e4fdbe910ed80bd278sewardj//uu    UChar byte2 = 0;
23653616a2ec4af166a3917810e4fdbe910ed80bd278sewardj//uu    if (rexX == 0 && rexB == 0 && mmmmm == 1 && rexW == 0) {
23663616a2ec4af166a3917810e4fdbe910ed80bd278sewardj//uu       /* 2 byte encoding is possible. */
23673616a2ec4af166a3917810e4fdbe910ed80bd278sewardj//uu       byte0 = 0xC5;
23683616a2ec4af166a3917810e4fdbe910ed80bd278sewardj//uu       byte1 = ((rexR ^ 1) << 7) | ((notVvvv ^ 0xF) << 3)
23693616a2ec4af166a3917810e4fdbe910ed80bd278sewardj//uu               | (L << 2) | pp;
23703616a2ec4af166a3917810e4fdbe910ed80bd278sewardj//uu    } else {
23713616a2ec4af166a3917810e4fdbe910ed80bd278sewardj//uu       /* 3 byte encoding is needed. */
23723616a2ec4af166a3917810e4fdbe910ed80bd278sewardj//uu       byte0 = 0xC4;
23733616a2ec4af166a3917810e4fdbe910ed80bd278sewardj//uu       byte1 = ((rexR ^ 1) << 7) | ((rexX ^ 1) << 6)
23743616a2ec4af166a3917810e4fdbe910ed80bd278sewardj//uu               | ((rexB ^ 1) << 5) | mmmmm;
23753616a2ec4af166a3917810e4fdbe910ed80bd278sewardj//uu       byte2 = (rexW << 7) | ((notVvvv ^ 0xF) << 3) | (L << 2) | pp;
23763616a2ec4af166a3917810e4fdbe910ed80bd278sewardj//uu    }
23773616a2ec4af166a3917810e4fdbe910ed80bd278sewardj//uu    return (((UInt)byte2) << 16) | (((UInt)byte1) << 8) | ((UInt)byte0);
23783616a2ec4af166a3917810e4fdbe910ed80bd278sewardj//uu }
23793616a2ec4af166a3917810e4fdbe910ed80bd278sewardj//uu
23803616a2ec4af166a3917810e4fdbe910ed80bd278sewardj//uu /* Make up a VEX prefix for a (greg,amode) pair.  First byte in bits
23813616a2ec4af166a3917810e4fdbe910ed80bd278sewardj//uu    7:0 of result, second in 15:8, third (for a 3 byte prefix) in
23823616a2ec4af166a3917810e4fdbe910ed80bd278sewardj//uu    23:16.  Has m-mmmm set to indicate a prefix of 0F, pp set to
23833616a2ec4af166a3917810e4fdbe910ed80bd278sewardj//uu    indicate no SIMD prefix, W=0 (ignore), L=1 (size=256), and
23843616a2ec4af166a3917810e4fdbe910ed80bd278sewardj//uu    vvvv=1111 (unused 3rd reg). */
23853616a2ec4af166a3917810e4fdbe910ed80bd278sewardj//uu static UInt vexAMode_M ( HReg greg, AMD64AMode* am )
23863616a2ec4af166a3917810e4fdbe910ed80bd278sewardj//uu {
23873616a2ec4af166a3917810e4fdbe910ed80bd278sewardj//uu    UChar L       = 1; /* size = 256 */
23883616a2ec4af166a3917810e4fdbe910ed80bd278sewardj//uu    UChar pp      = 0; /* no SIMD prefix */
23893616a2ec4af166a3917810e4fdbe910ed80bd278sewardj//uu    UChar mmmmm   = 1; /* 0F */
23903616a2ec4af166a3917810e4fdbe910ed80bd278sewardj//uu    UChar notVvvv = 0; /* unused */
23913616a2ec4af166a3917810e4fdbe910ed80bd278sewardj//uu    UChar rexW    = 0;
23923616a2ec4af166a3917810e4fdbe910ed80bd278sewardj//uu    UChar rexR    = 0;
23933616a2ec4af166a3917810e4fdbe910ed80bd278sewardj//uu    UChar rexX    = 0;
23943616a2ec4af166a3917810e4fdbe910ed80bd278sewardj//uu    UChar rexB    = 0;
23953616a2ec4af166a3917810e4fdbe910ed80bd278sewardj//uu    /* Same logic as in rexAMode_M. */
23963616a2ec4af166a3917810e4fdbe910ed80bd278sewardj//uu    if (am->tag == Aam_IR) {
2397a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj//uu       rexR = iregEnc3(greg);
23983616a2ec4af166a3917810e4fdbe910ed80bd278sewardj//uu       rexX = 0; /* not relevant */
2399a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj//uu       rexB = iregEnc3(am->Aam.IR.reg);
24003616a2ec4af166a3917810e4fdbe910ed80bd278sewardj//uu    }
24013616a2ec4af166a3917810e4fdbe910ed80bd278sewardj//uu    else if (am->tag == Aam_IRRS) {
2402a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj//uu       rexR = iregEnc3(greg);
2403a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj//uu       rexX = iregEnc3(am->Aam.IRRS.index);
2404a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj//uu       rexB = iregEnc3(am->Aam.IRRS.base);
24053616a2ec4af166a3917810e4fdbe910ed80bd278sewardj//uu    } else {
24063616a2ec4af166a3917810e4fdbe910ed80bd278sewardj//uu       vassert(0);
24073616a2ec4af166a3917810e4fdbe910ed80bd278sewardj//uu    }
24083616a2ec4af166a3917810e4fdbe910ed80bd278sewardj//uu    return packVexPrefix( rexR, rexX, rexB, mmmmm, rexW, notVvvv, L, pp );
24093616a2ec4af166a3917810e4fdbe910ed80bd278sewardj//uu }
24103616a2ec4af166a3917810e4fdbe910ed80bd278sewardj//uu
24113616a2ec4af166a3917810e4fdbe910ed80bd278sewardj//uu static UChar* emitVexPrefix ( UChar* p, UInt vex )
24123616a2ec4af166a3917810e4fdbe910ed80bd278sewardj//uu {
24133616a2ec4af166a3917810e4fdbe910ed80bd278sewardj//uu    switch (vex & 0xFF) {
24143616a2ec4af166a3917810e4fdbe910ed80bd278sewardj//uu       case 0xC5:
24153616a2ec4af166a3917810e4fdbe910ed80bd278sewardj//uu          *p++ = 0xC5;
24163616a2ec4af166a3917810e4fdbe910ed80bd278sewardj//uu          *p++ = (vex >> 8) & 0xFF;
24173616a2ec4af166a3917810e4fdbe910ed80bd278sewardj//uu          vassert(0 == (vex >> 16));
24183616a2ec4af166a3917810e4fdbe910ed80bd278sewardj//uu          break;
24193616a2ec4af166a3917810e4fdbe910ed80bd278sewardj//uu       case 0xC4:
24203616a2ec4af166a3917810e4fdbe910ed80bd278sewardj//uu          *p++ = 0xC4;
24213616a2ec4af166a3917810e4fdbe910ed80bd278sewardj//uu          *p++ = (vex >> 8) & 0xFF;
24223616a2ec4af166a3917810e4fdbe910ed80bd278sewardj//uu          *p++ = (vex >> 16) & 0xFF;
24233616a2ec4af166a3917810e4fdbe910ed80bd278sewardj//uu          vassert(0 == (vex >> 24));
24243616a2ec4af166a3917810e4fdbe910ed80bd278sewardj//uu          break;
24253616a2ec4af166a3917810e4fdbe910ed80bd278sewardj//uu       default:
24263616a2ec4af166a3917810e4fdbe910ed80bd278sewardj//uu          vassert(0);
24273616a2ec4af166a3917810e4fdbe910ed80bd278sewardj//uu    }
24283616a2ec4af166a3917810e4fdbe910ed80bd278sewardj//uu    return p;
24293616a2ec4af166a3917810e4fdbe910ed80bd278sewardj//uu }
2430c4530ae9079b0c3f8d4e8df35073613d718cadecsewardj
2431c4530ae9079b0c3f8d4e8df35073613d718cadecsewardj
243225a858136df4cbea0055c20aa7035d25fd40ee89sewardj/* Emit ffree %st(N) */
243325a858136df4cbea0055c20aa7035d25fd40ee89sewardjstatic UChar* do_ffree_st ( UChar* p, Int n )
243425a858136df4cbea0055c20aa7035d25fd40ee89sewardj{
243525a858136df4cbea0055c20aa7035d25fd40ee89sewardj   vassert(n >= 0 && n <= 7);
243625a858136df4cbea0055c20aa7035d25fd40ee89sewardj   *p++ = 0xDD;
243725a858136df4cbea0055c20aa7035d25fd40ee89sewardj   *p++ = toUChar(0xC0 + n);
243825a858136df4cbea0055c20aa7035d25fd40ee89sewardj   return p;
243925a858136df4cbea0055c20aa7035d25fd40ee89sewardj}
244025a858136df4cbea0055c20aa7035d25fd40ee89sewardj
2441c33671d7b0e21edb1d1015e4cbccbc6ca139e6d8sewardj/* Emit an instruction into buf and return the number of bytes used.
2442c33671d7b0e21edb1d1015e4cbccbc6ca139e6d8sewardj   Note that buf is not the insn's final place, and therefore it is
2443c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   imperative to emit position-independent code.  If the emitted
2444c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   instruction was a profiler inc, set *is_profInc to True, else
2445c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   leave it unchanged. */
2446c33671d7b0e21edb1d1015e4cbccbc6ca139e6d8sewardj
2447c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardjInt emit_AMD64Instr ( /*MB_MOD*/Bool* is_profInc,
2448d8c64e082224b2e688abdef9219cc76fd82b373bflorian                      UChar* buf, Int nbuf, const AMD64Instr* i,
24499b76916dcc1628e133d57db001563429c6e3a590sewardj                      Bool mode64, VexEndness endness_host,
24508462d113e3efeacceb304222dada8d85f748295aflorian                      const void* disp_cp_chain_me_to_slowEP,
24518462d113e3efeacceb304222dada8d85f748295aflorian                      const void* disp_cp_chain_me_to_fastEP,
24528462d113e3efeacceb304222dada8d85f748295aflorian                      const void* disp_cp_xindir,
24538462d113e3efeacceb304222dada8d85f748295aflorian                      const void* disp_cp_xassisted )
2454c33671d7b0e21edb1d1015e4cbccbc6ca139e6d8sewardj{
2455c2bcb6f78b7fc9066befa79aeaee57f82a087545sewardj   UInt /*irno,*/ opc, opc_rr, subopc_imm, opc_imma, opc_cl, opc_imm, subopc;
24561001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj   UInt   xtra;
2457a5bd0aff6eda3e7c312f51ae6bc742ea62b5d404sewardj   UInt   reg;
24581001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj   UChar  rex;
2459c33671d7b0e21edb1d1015e4cbccbc6ca139e6d8sewardj   UChar* p = &buf[0];
2460549e06463d433ee6351b72dc9107f22ce4305250sewardj   UChar* ptmp;
246125a858136df4cbea0055c20aa7035d25fd40ee89sewardj   Int    j;
246270dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   vassert(nbuf >= 64);
246392b643609c5fa432b11fc726c2706ae3f3296eb4cerion   vassert(mode64 == True);
2464549e06463d433ee6351b72dc9107f22ce4305250sewardj
246592b643609c5fa432b11fc726c2706ae3f3296eb4cerion   /* vex_printf("asm  "); ppAMD64Instr(i, mode64); vex_printf("\n"); */
2466c33671d7b0e21edb1d1015e4cbccbc6ca139e6d8sewardj
2467c33671d7b0e21edb1d1015e4cbccbc6ca139e6d8sewardj   switch (i->tag) {
2468c33671d7b0e21edb1d1015e4cbccbc6ca139e6d8sewardj
24691b8d58eb046ad31fbb058d65855b604886d3d177sewardj   case Ain_Imm64:
24707cf5bd04544e5288102d0b911a8910533d0a2161sewardj      if (i->Ain.Imm64.imm64 <= 0xFFFFFULL) {
24717cf5bd04544e5288102d0b911a8910533d0a2161sewardj         /* Use the short form (load into 32 bit reg, + default
24727cf5bd04544e5288102d0b911a8910533d0a2161sewardj            widening rule) for constants under 1 million.  We could
24737cf5bd04544e5288102d0b911a8910533d0a2161sewardj            use this form for the range 0 to 0x7FFFFFFF inclusive, but
24747cf5bd04544e5288102d0b911a8910533d0a2161sewardj            limit it to a smaller range for verifiability purposes. */
2475a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj         if (1 & iregEnc3(i->Ain.Imm64.dst))
24767cf5bd04544e5288102d0b911a8910533d0a2161sewardj            *p++ = 0x41;
2477a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj         *p++ = 0xB8 + iregEnc210(i->Ain.Imm64.dst);
24787cf5bd04544e5288102d0b911a8910533d0a2161sewardj         p = emit32(p, (UInt)i->Ain.Imm64.imm64);
24797cf5bd04544e5288102d0b911a8910533d0a2161sewardj      } else {
2480a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj         *p++ = toUChar(0x48 + (1 & iregEnc3(i->Ain.Imm64.dst)));
2481a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj         *p++ = toUChar(0xB8 + iregEnc210(i->Ain.Imm64.dst));
24827cf5bd04544e5288102d0b911a8910533d0a2161sewardj         p = emit64(p, i->Ain.Imm64.imm64);
24837cf5bd04544e5288102d0b911a8910533d0a2161sewardj      }
24841b8d58eb046ad31fbb058d65855b604886d3d177sewardj      goto done;
24851b8d58eb046ad31fbb058d65855b604886d3d177sewardj
2486813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj   case Ain_Alu64R:
2487813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj      /* Deal specially with MOV */
2488813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj      if (i->Ain.Alu64R.op == Aalu_MOV) {
2489813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj         switch (i->Ain.Alu64R.src->tag) {
2490813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj            case Armi_Imm:
24917cf5bd04544e5288102d0b911a8910533d0a2161sewardj               if (0 == (i->Ain.Alu64R.src->Armi.Imm.imm32 & ~0xFFFFF)) {
249295e154cd4155e22c25e4ed0554d42773cb0e0650sewardj                  /* Actually we could use this form for constants in
249395e154cd4155e22c25e4ed0554d42773cb0e0650sewardj                     the range 0 through 0x7FFFFFFF inclusive, but
249495e154cd4155e22c25e4ed0554d42773cb0e0650sewardj                     limit it to a small range for verifiability
249595e154cd4155e22c25e4ed0554d42773cb0e0650sewardj                     purposes. */
249695e154cd4155e22c25e4ed0554d42773cb0e0650sewardj                  /* Generate "movl $imm32, 32-bit-register" and let
249795e154cd4155e22c25e4ed0554d42773cb0e0650sewardj                     the default zero-extend rule cause the upper half
249895e154cd4155e22c25e4ed0554d42773cb0e0650sewardj                     of the dst to be zeroed out too.  This saves 1
249995e154cd4155e22c25e4ed0554d42773cb0e0650sewardj                     and sometimes 2 bytes compared to the more
250095e154cd4155e22c25e4ed0554d42773cb0e0650sewardj                     obvious encoding in the 'else' branch. */
2501a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj                  if (1 & iregEnc3(i->Ain.Alu64R.dst))
250295e154cd4155e22c25e4ed0554d42773cb0e0650sewardj                     *p++ = 0x41;
2503a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj                  *p++ = 0xB8 + iregEnc210(i->Ain.Alu64R.dst);
250495e154cd4155e22c25e4ed0554d42773cb0e0650sewardj                  p = emit32(p, i->Ain.Alu64R.src->Armi.Imm.imm32);
250595e154cd4155e22c25e4ed0554d42773cb0e0650sewardj               } else {
2506a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj                  *p++ = toUChar(0x48 + (1 & iregEnc3(i->Ain.Alu64R.dst)));
250795e154cd4155e22c25e4ed0554d42773cb0e0650sewardj                  *p++ = 0xC7;
2508a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj                  *p++ = toUChar(0xC0 + iregEnc210(i->Ain.Alu64R.dst));
250995e154cd4155e22c25e4ed0554d42773cb0e0650sewardj                  p = emit32(p, i->Ain.Alu64R.src->Armi.Imm.imm32);
251095e154cd4155e22c25e4ed0554d42773cb0e0650sewardj               }
2511813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj               goto done;
2512813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj            case Armi_Reg:
25131b8d58eb046ad31fbb058d65855b604886d3d177sewardj               *p++ = rexAMode_R( i->Ain.Alu64R.src->Armi.Reg.reg,
25141b8d58eb046ad31fbb058d65855b604886d3d177sewardj                                  i->Ain.Alu64R.dst );
2515813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj               *p++ = 0x89;
2516813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj               p = doAMode_R(p, i->Ain.Alu64R.src->Armi.Reg.reg,
2517813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj                                i->Ain.Alu64R.dst);
2518813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj               goto done;
2519813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj            case Armi_Mem:
2520549e06463d433ee6351b72dc9107f22ce4305250sewardj               *p++ = rexAMode_M(i->Ain.Alu64R.dst,
2521813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj                                 i->Ain.Alu64R.src->Armi.Mem.am);
2522813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj               *p++ = 0x8B;
2523813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj               p = doAMode_M(p, i->Ain.Alu64R.dst,
2524813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj                                i->Ain.Alu64R.src->Armi.Mem.am);
2525813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj               goto done;
2526813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj            default:
2527813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj               goto bad;
2528813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj         }
2529813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj      }
2530d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj      /* MUL */
2531d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj      if (i->Ain.Alu64R.op == Aalu_MUL) {
2532d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj         switch (i->Ain.Alu64R.src->tag) {
25337de0d3c800437fbd82c59d57d156f4823d67609fsewardj            case Armi_Reg:
25347de0d3c800437fbd82c59d57d156f4823d67609fsewardj               *p++ = rexAMode_R( i->Ain.Alu64R.dst,
25357de0d3c800437fbd82c59d57d156f4823d67609fsewardj                                  i->Ain.Alu64R.src->Armi.Reg.reg);
25367de0d3c800437fbd82c59d57d156f4823d67609fsewardj               *p++ = 0x0F;
25377de0d3c800437fbd82c59d57d156f4823d67609fsewardj               *p++ = 0xAF;
25387de0d3c800437fbd82c59d57d156f4823d67609fsewardj               p = doAMode_R(p, i->Ain.Alu64R.dst,
25397de0d3c800437fbd82c59d57d156f4823d67609fsewardj                                i->Ain.Alu64R.src->Armi.Reg.reg);
25407de0d3c800437fbd82c59d57d156f4823d67609fsewardj               goto done;
2541d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj            case Armi_Mem:
2542d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj               *p++ = rexAMode_M(i->Ain.Alu64R.dst,
2543d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj                                 i->Ain.Alu64R.src->Armi.Mem.am);
2544d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj               *p++ = 0x0F;
2545d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj               *p++ = 0xAF;
2546d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj               p = doAMode_M(p, i->Ain.Alu64R.dst,
2547d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj                                i->Ain.Alu64R.src->Armi.Mem.am);
2548d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj               goto done;
25497de0d3c800437fbd82c59d57d156f4823d67609fsewardj            case Armi_Imm:
25507de0d3c800437fbd82c59d57d156f4823d67609fsewardj               if (fits8bits(i->Ain.Alu64R.src->Armi.Imm.imm32)) {
25517de0d3c800437fbd82c59d57d156f4823d67609fsewardj                  *p++ = rexAMode_R(i->Ain.Alu64R.dst, i->Ain.Alu64R.dst);
25527de0d3c800437fbd82c59d57d156f4823d67609fsewardj                  *p++ = 0x6B;
25537de0d3c800437fbd82c59d57d156f4823d67609fsewardj                  p = doAMode_R(p, i->Ain.Alu64R.dst, i->Ain.Alu64R.dst);
255403ccf858efa285d793061359c04fdd0055cd9d31sewardj                  *p++ = toUChar(0xFF & i->Ain.Alu64R.src->Armi.Imm.imm32);
25557de0d3c800437fbd82c59d57d156f4823d67609fsewardj               } else {
25567de0d3c800437fbd82c59d57d156f4823d67609fsewardj                  *p++ = rexAMode_R(i->Ain.Alu64R.dst, i->Ain.Alu64R.dst);
25577de0d3c800437fbd82c59d57d156f4823d67609fsewardj                  *p++ = 0x69;
25587de0d3c800437fbd82c59d57d156f4823d67609fsewardj                  p = doAMode_R(p, i->Ain.Alu64R.dst, i->Ain.Alu64R.dst);
25597de0d3c800437fbd82c59d57d156f4823d67609fsewardj                  p = emit32(p, i->Ain.Alu64R.src->Armi.Imm.imm32);
25607de0d3c800437fbd82c59d57d156f4823d67609fsewardj               }
25617de0d3c800437fbd82c59d57d156f4823d67609fsewardj               goto done;
2562d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj            default:
2563d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj               goto bad;
2564d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj         }
2565d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj      }
2566549e06463d433ee6351b72dc9107f22ce4305250sewardj      /* ADD/SUB/ADC/SBB/AND/OR/XOR/CMP */
2567549e06463d433ee6351b72dc9107f22ce4305250sewardj      opc = opc_rr = subopc_imm = opc_imma = 0;
2568549e06463d433ee6351b72dc9107f22ce4305250sewardj      switch (i->Ain.Alu64R.op) {
2569549e06463d433ee6351b72dc9107f22ce4305250sewardj         case Aalu_ADC: opc = 0x13; opc_rr = 0x11;
2570549e06463d433ee6351b72dc9107f22ce4305250sewardj                        subopc_imm = 2; opc_imma = 0x15; break;
2571549e06463d433ee6351b72dc9107f22ce4305250sewardj         case Aalu_ADD: opc = 0x03; opc_rr = 0x01;
2572549e06463d433ee6351b72dc9107f22ce4305250sewardj                        subopc_imm = 0; opc_imma = 0x05; break;
2573549e06463d433ee6351b72dc9107f22ce4305250sewardj         case Aalu_SUB: opc = 0x2B; opc_rr = 0x29;
2574549e06463d433ee6351b72dc9107f22ce4305250sewardj                        subopc_imm = 5; opc_imma = 0x2D; break;
2575549e06463d433ee6351b72dc9107f22ce4305250sewardj         case Aalu_SBB: opc = 0x1B; opc_rr = 0x19;
2576549e06463d433ee6351b72dc9107f22ce4305250sewardj                        subopc_imm = 3; opc_imma = 0x1D; break;
2577549e06463d433ee6351b72dc9107f22ce4305250sewardj         case Aalu_AND: opc = 0x23; opc_rr = 0x21;
2578549e06463d433ee6351b72dc9107f22ce4305250sewardj                        subopc_imm = 4; opc_imma = 0x25; break;
2579549e06463d433ee6351b72dc9107f22ce4305250sewardj         case Aalu_XOR: opc = 0x33; opc_rr = 0x31;
2580549e06463d433ee6351b72dc9107f22ce4305250sewardj                        subopc_imm = 6; opc_imma = 0x35; break;
2581549e06463d433ee6351b72dc9107f22ce4305250sewardj         case Aalu_OR:  opc = 0x0B; opc_rr = 0x09;
2582549e06463d433ee6351b72dc9107f22ce4305250sewardj                        subopc_imm = 1; opc_imma = 0x0D; break;
2583549e06463d433ee6351b72dc9107f22ce4305250sewardj         case Aalu_CMP: opc = 0x3B; opc_rr = 0x39;
2584549e06463d433ee6351b72dc9107f22ce4305250sewardj                        subopc_imm = 7; opc_imma = 0x3D; break;
2585549e06463d433ee6351b72dc9107f22ce4305250sewardj         default: goto bad;
2586549e06463d433ee6351b72dc9107f22ce4305250sewardj      }
2587549e06463d433ee6351b72dc9107f22ce4305250sewardj      switch (i->Ain.Alu64R.src->tag) {
2588549e06463d433ee6351b72dc9107f22ce4305250sewardj         case Armi_Imm:
258979efdc6ea93db174395af845d4e21a4a7ad600ccflorian            if (sameHReg(i->Ain.Alu64R.dst, hregAMD64_RAX())
2590549e06463d433ee6351b72dc9107f22ce4305250sewardj                && !fits8bits(i->Ain.Alu64R.src->Armi.Imm.imm32)) {
25911830386e7b10430c0c3630123a82d8bcf0a071e7sewardj               goto bad; /* FIXME: awaiting test case */
259203ccf858efa285d793061359c04fdd0055cd9d31sewardj               *p++ = toUChar(opc_imma);
2593549e06463d433ee6351b72dc9107f22ce4305250sewardj               p = emit32(p, i->Ain.Alu64R.src->Armi.Imm.imm32);
2594549e06463d433ee6351b72dc9107f22ce4305250sewardj            } else
2595549e06463d433ee6351b72dc9107f22ce4305250sewardj            if (fits8bits(i->Ain.Alu64R.src->Armi.Imm.imm32)) {
2596a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj               *p++ = rexAMode_R_enc_reg( 0, i->Ain.Alu64R.dst );
2597549e06463d433ee6351b72dc9107f22ce4305250sewardj               *p++ = 0x83;
2598a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj               p    = doAMode_R_enc_reg(p, subopc_imm, i->Ain.Alu64R.dst);
259903ccf858efa285d793061359c04fdd0055cd9d31sewardj               *p++ = toUChar(0xFF & i->Ain.Alu64R.src->Armi.Imm.imm32);
2600549e06463d433ee6351b72dc9107f22ce4305250sewardj            } else {
2601a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj               *p++ = rexAMode_R_enc_reg( 0, i->Ain.Alu64R.dst);
2602549e06463d433ee6351b72dc9107f22ce4305250sewardj               *p++ = 0x81;
2603a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj               p    = doAMode_R_enc_reg(p, subopc_imm, i->Ain.Alu64R.dst);
2604549e06463d433ee6351b72dc9107f22ce4305250sewardj               p    = emit32(p, i->Ain.Alu64R.src->Armi.Imm.imm32);
2605549e06463d433ee6351b72dc9107f22ce4305250sewardj            }
2606549e06463d433ee6351b72dc9107f22ce4305250sewardj            goto done;
2607549e06463d433ee6351b72dc9107f22ce4305250sewardj         case Armi_Reg:
2608549e06463d433ee6351b72dc9107f22ce4305250sewardj            *p++ = rexAMode_R( i->Ain.Alu64R.src->Armi.Reg.reg,
2609549e06463d433ee6351b72dc9107f22ce4305250sewardj                               i->Ain.Alu64R.dst);
261003ccf858efa285d793061359c04fdd0055cd9d31sewardj            *p++ = toUChar(opc_rr);
2611549e06463d433ee6351b72dc9107f22ce4305250sewardj            p = doAMode_R(p, i->Ain.Alu64R.src->Armi.Reg.reg,
2612549e06463d433ee6351b72dc9107f22ce4305250sewardj                             i->Ain.Alu64R.dst);
2613549e06463d433ee6351b72dc9107f22ce4305250sewardj            goto done;
2614549e06463d433ee6351b72dc9107f22ce4305250sewardj         case Armi_Mem:
261531191074d1de762d8fbed3590ec08f2894ab1d8bsewardj            *p++ = rexAMode_M( i->Ain.Alu64R.dst,
261631191074d1de762d8fbed3590ec08f2894ab1d8bsewardj                               i->Ain.Alu64R.src->Armi.Mem.am);
261703ccf858efa285d793061359c04fdd0055cd9d31sewardj            *p++ = toUChar(opc);
2618549e06463d433ee6351b72dc9107f22ce4305250sewardj            p = doAMode_M(p, i->Ain.Alu64R.dst,
2619549e06463d433ee6351b72dc9107f22ce4305250sewardj                             i->Ain.Alu64R.src->Armi.Mem.am);
2620549e06463d433ee6351b72dc9107f22ce4305250sewardj            goto done;
2621549e06463d433ee6351b72dc9107f22ce4305250sewardj         default:
2622549e06463d433ee6351b72dc9107f22ce4305250sewardj            goto bad;
2623549e06463d433ee6351b72dc9107f22ce4305250sewardj      }
2624813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj      break;
2625813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj
2626549e06463d433ee6351b72dc9107f22ce4305250sewardj   case Ain_Alu64M:
2627549e06463d433ee6351b72dc9107f22ce4305250sewardj      /* Deal specially with MOV */
2628549e06463d433ee6351b72dc9107f22ce4305250sewardj      if (i->Ain.Alu64M.op == Aalu_MOV) {
2629549e06463d433ee6351b72dc9107f22ce4305250sewardj         switch (i->Ain.Alu64M.src->tag) {
2630549e06463d433ee6351b72dc9107f22ce4305250sewardj            case Ari_Reg:
2631549e06463d433ee6351b72dc9107f22ce4305250sewardj               *p++ = rexAMode_M(i->Ain.Alu64M.src->Ari.Reg.reg,
2632549e06463d433ee6351b72dc9107f22ce4305250sewardj                                 i->Ain.Alu64M.dst);
2633549e06463d433ee6351b72dc9107f22ce4305250sewardj               *p++ = 0x89;
2634549e06463d433ee6351b72dc9107f22ce4305250sewardj               p = doAMode_M(p, i->Ain.Alu64M.src->Ari.Reg.reg,
2635549e06463d433ee6351b72dc9107f22ce4305250sewardj                                i->Ain.Alu64M.dst);
2636549e06463d433ee6351b72dc9107f22ce4305250sewardj               goto done;
2637549e06463d433ee6351b72dc9107f22ce4305250sewardj            case Ari_Imm:
2638a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj               *p++ = rexAMode_M_enc(0, i->Ain.Alu64M.dst);
2639549e06463d433ee6351b72dc9107f22ce4305250sewardj               *p++ = 0xC7;
2640a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj               p = doAMode_M_enc(p, 0, i->Ain.Alu64M.dst);
2641549e06463d433ee6351b72dc9107f22ce4305250sewardj               p = emit32(p, i->Ain.Alu64M.src->Ari.Imm.imm32);
2642549e06463d433ee6351b72dc9107f22ce4305250sewardj               goto done;
2643549e06463d433ee6351b72dc9107f22ce4305250sewardj            default:
2644549e06463d433ee6351b72dc9107f22ce4305250sewardj               goto bad;
2645549e06463d433ee6351b72dc9107f22ce4305250sewardj         }
2646549e06463d433ee6351b72dc9107f22ce4305250sewardj      }
2647ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes      /* ADD/SUB/ADC/SBB/AND/OR/XOR/CMP.  MUL is not
2648ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes         allowed here. (This is derived from the x86 version of same). */
2649ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes      opc = subopc_imm = opc_imma = 0;
2650ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes      switch (i->Ain.Alu64M.op) {
2651ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes         case Aalu_CMP: opc = 0x39; subopc_imm = 7; break;
2652ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes         default: goto bad;
2653ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes      }
2654ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes      switch (i->Ain.Alu64M.src->tag) {
2655ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes         /*
2656ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes         case Xri_Reg:
2657ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes            *p++ = toUChar(opc);
2658ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes            p = doAMode_M(p, i->Xin.Alu32M.src->Xri.Reg.reg,
2659ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes                             i->Xin.Alu32M.dst);
2660ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes            goto done;
2661ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes         */
2662ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes         case Ari_Imm:
2663ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes            if (fits8bits(i->Ain.Alu64M.src->Ari.Imm.imm32)) {
2664ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes               *p++ = rexAMode_M_enc(subopc_imm, i->Ain.Alu64M.dst);
2665ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes               *p++ = 0x83;
2666ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes               p    = doAMode_M_enc(p, subopc_imm, i->Ain.Alu64M.dst);
2667ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes               *p++ = toUChar(0xFF & i->Ain.Alu64M.src->Ari.Imm.imm32);
2668ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes               goto done;
2669ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes            } else {
2670ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes               *p++ = rexAMode_M_enc(subopc_imm, i->Ain.Alu64M.dst);
2671ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes               *p++ = 0x81;
2672ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes               p    = doAMode_M_enc(p, subopc_imm, i->Ain.Alu64M.dst);
2673ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes               p    = emit32(p, i->Ain.Alu64M.src->Ari.Imm.imm32);
2674ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes               goto done;
2675ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes            }
2676ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes         default:
2677ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes            goto bad;
2678ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes      }
2679ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes
2680549e06463d433ee6351b72dc9107f22ce4305250sewardj      break;
2681549e06463d433ee6351b72dc9107f22ce4305250sewardj
26821b8d58eb046ad31fbb058d65855b604886d3d177sewardj   case Ain_Sh64:
26831b8d58eb046ad31fbb058d65855b604886d3d177sewardj      opc_cl = opc_imm = subopc = 0;
26841b8d58eb046ad31fbb058d65855b604886d3d177sewardj      switch (i->Ain.Sh64.op) {
26851b8d58eb046ad31fbb058d65855b604886d3d177sewardj         case Ash_SHR: opc_cl = 0xD3; opc_imm = 0xC1; subopc = 5; break;
26861b8d58eb046ad31fbb058d65855b604886d3d177sewardj         case Ash_SAR: opc_cl = 0xD3; opc_imm = 0xC1; subopc = 7; break;
26871b8d58eb046ad31fbb058d65855b604886d3d177sewardj         case Ash_SHL: opc_cl = 0xD3; opc_imm = 0xC1; subopc = 4; break;
26881b8d58eb046ad31fbb058d65855b604886d3d177sewardj         default: goto bad;
26891b8d58eb046ad31fbb058d65855b604886d3d177sewardj      }
26901b8d58eb046ad31fbb058d65855b604886d3d177sewardj      if (i->Ain.Sh64.src == 0) {
2691a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj         *p++ = rexAMode_R_enc_reg(0, i->Ain.Sh64.dst);
269203ccf858efa285d793061359c04fdd0055cd9d31sewardj         *p++ = toUChar(opc_cl);
2693a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj         p = doAMode_R_enc_reg(p, subopc, i->Ain.Sh64.dst);
2694501a339ba08d28f30eb96d17b3f5bbe996ca6a4dsewardj         goto done;
26951b8d58eb046ad31fbb058d65855b604886d3d177sewardj      } else {
2696a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj         *p++ = rexAMode_R_enc_reg(0, i->Ain.Sh64.dst);
269703ccf858efa285d793061359c04fdd0055cd9d31sewardj         *p++ = toUChar(opc_imm);
2698a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj         p = doAMode_R_enc_reg(p, subopc, i->Ain.Sh64.dst);
2699501a339ba08d28f30eb96d17b3f5bbe996ca6a4dsewardj         *p++ = (UChar)(i->Ain.Sh64.src);
2700501a339ba08d28f30eb96d17b3f5bbe996ca6a4dsewardj         goto done;
27011b8d58eb046ad31fbb058d65855b604886d3d177sewardj      }
27021b8d58eb046ad31fbb058d65855b604886d3d177sewardj      break;
27031b8d58eb046ad31fbb058d65855b604886d3d177sewardj
27041b8d58eb046ad31fbb058d65855b604886d3d177sewardj   case Ain_Test64:
2705501a339ba08d28f30eb96d17b3f5bbe996ca6a4dsewardj      /* testq sign-extend($imm32), %reg */
2706a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj      *p++ = rexAMode_R_enc_reg(0, i->Ain.Test64.dst);
2707501a339ba08d28f30eb96d17b3f5bbe996ca6a4dsewardj      *p++ = 0xF7;
2708a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj      p = doAMode_R_enc_reg(p, 0, i->Ain.Test64.dst);
2709501a339ba08d28f30eb96d17b3f5bbe996ca6a4dsewardj      p = emit32(p, i->Ain.Test64.imm32);
2710501a339ba08d28f30eb96d17b3f5bbe996ca6a4dsewardj      goto done;
27111b8d58eb046ad31fbb058d65855b604886d3d177sewardj
2712d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj   case Ain_Unary64:
2713d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj      if (i->Ain.Unary64.op == Aun_NOT) {
2714a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj         *p++ = rexAMode_R_enc_reg(0, i->Ain.Unary64.dst);
2715501a339ba08d28f30eb96d17b3f5bbe996ca6a4dsewardj         *p++ = 0xF7;
2716a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj         p = doAMode_R_enc_reg(p, 2, i->Ain.Unary64.dst);
2717501a339ba08d28f30eb96d17b3f5bbe996ca6a4dsewardj         goto done;
2718d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj      }
2719b522077275a57df04305eec3ec1ef3fab9801197sewardj      if (i->Ain.Unary64.op == Aun_NEG) {
2720a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj         *p++ = rexAMode_R_enc_reg(0, i->Ain.Unary64.dst);
2721501a339ba08d28f30eb96d17b3f5bbe996ca6a4dsewardj         *p++ = 0xF7;
2722a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj         p = doAMode_R_enc_reg(p, 3, i->Ain.Unary64.dst);
2723501a339ba08d28f30eb96d17b3f5bbe996ca6a4dsewardj         goto done;
2724b522077275a57df04305eec3ec1ef3fab9801197sewardj      }
2725d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj      break;
27269b96767debeeb1f78378f0e7e295fe6762c64002sewardj
27276ce1a23b27d1729da9d705abd15b2007dce8daecsewardj   case Ain_Lea64:
27286ce1a23b27d1729da9d705abd15b2007dce8daecsewardj      *p++ = rexAMode_M(i->Ain.Lea64.dst, i->Ain.Lea64.am);
27296ce1a23b27d1729da9d705abd15b2007dce8daecsewardj      *p++ = 0x8D;
27306ce1a23b27d1729da9d705abd15b2007dce8daecsewardj      p = doAMode_M(p, i->Ain.Lea64.dst, i->Ain.Lea64.am);
27316ce1a23b27d1729da9d705abd15b2007dce8daecsewardj      goto done;
27326ce1a23b27d1729da9d705abd15b2007dce8daecsewardj
27339cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj   case Ain_Alu32R:
27349cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj      /* ADD/SUB/AND/OR/XOR/CMP */
27359cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj      opc = opc_rr = subopc_imm = opc_imma = 0;
27369cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj      switch (i->Ain.Alu32R.op) {
27379cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj         case Aalu_ADD: opc = 0x03; opc_rr = 0x01;
27389cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj                        subopc_imm = 0; opc_imma = 0x05; break;
27399cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj         case Aalu_SUB: opc = 0x2B; opc_rr = 0x29;
27409cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj                        subopc_imm = 5; opc_imma = 0x2D; break;
27419cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj         case Aalu_AND: opc = 0x23; opc_rr = 0x21;
27429cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj                        subopc_imm = 4; opc_imma = 0x25; break;
27439cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj         case Aalu_XOR: opc = 0x33; opc_rr = 0x31;
27449cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj                        subopc_imm = 6; opc_imma = 0x35; break;
27459cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj         case Aalu_OR:  opc = 0x0B; opc_rr = 0x09;
27469cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj                        subopc_imm = 1; opc_imma = 0x0D; break;
27479cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj         case Aalu_CMP: opc = 0x3B; opc_rr = 0x39;
27489cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj                        subopc_imm = 7; opc_imma = 0x3D; break;
27499cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj         default: goto bad;
27509cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj      }
27519cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj      switch (i->Ain.Alu32R.src->tag) {
27529cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj         case Armi_Imm:
275379efdc6ea93db174395af845d4e21a4a7ad600ccflorian            if (sameHReg(i->Ain.Alu32R.dst, hregAMD64_RAX())
27549cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj                && !fits8bits(i->Ain.Alu32R.src->Armi.Imm.imm32)) {
27559cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj               goto bad; /* FIXME: awaiting test case */
27569cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj               *p++ = toUChar(opc_imma);
27579cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj               p = emit32(p, i->Ain.Alu32R.src->Armi.Imm.imm32);
27589cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj            } else
27599cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj            if (fits8bits(i->Ain.Alu32R.src->Armi.Imm.imm32)) {
2760a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj               rex  = clearWBit( rexAMode_R_enc_reg( 0, i->Ain.Alu32R.dst ) );
27619cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj               if (rex != 0x40) *p++ = rex;
27629cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj               *p++ = 0x83;
2763a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj               p    = doAMode_R_enc_reg(p, subopc_imm, i->Ain.Alu32R.dst);
27649cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj               *p++ = toUChar(0xFF & i->Ain.Alu32R.src->Armi.Imm.imm32);
27659cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj            } else {
2766a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj               rex  = clearWBit( rexAMode_R_enc_reg( 0, i->Ain.Alu32R.dst) );
27679cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj               if (rex != 0x40) *p++ = rex;
27689cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj               *p++ = 0x81;
2769a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj               p    = doAMode_R_enc_reg(p, subopc_imm, i->Ain.Alu32R.dst);
27709cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj               p    = emit32(p, i->Ain.Alu32R.src->Armi.Imm.imm32);
27719cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj            }
27729cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj            goto done;
27739cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj         case Armi_Reg:
27749cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj            rex  = clearWBit(
27759cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj                   rexAMode_R( i->Ain.Alu32R.src->Armi.Reg.reg,
27769cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj                               i->Ain.Alu32R.dst) );
27779cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj            if (rex != 0x40) *p++ = rex;
27789cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj            *p++ = toUChar(opc_rr);
27799cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj            p = doAMode_R(p, i->Ain.Alu32R.src->Armi.Reg.reg,
27809cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj                             i->Ain.Alu32R.dst);
27819cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj            goto done;
27829cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj         case Armi_Mem:
27839cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj            rex  = clearWBit(
27849cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj                   rexAMode_M( i->Ain.Alu32R.dst,
27859cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj                               i->Ain.Alu32R.src->Armi.Mem.am) );
27869cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj            if (rex != 0x40) *p++ = rex;
27879cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj            *p++ = toUChar(opc);
27889cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj            p = doAMode_M(p, i->Ain.Alu32R.dst,
27899cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj                             i->Ain.Alu32R.src->Armi.Mem.am);
27909cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj            goto done;
27919cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj         default:
27929cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj            goto bad;
27939cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj      }
27949cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj      break;
27959cc2bbf8496403cf998aec6152c086cd66b8bcdfsewardj
27969b96767debeeb1f78378f0e7e295fe6762c64002sewardj   case Ain_MulL:
27979b96767debeeb1f78378f0e7e295fe6762c64002sewardj      subopc = i->Ain.MulL.syned ? 5 : 4;
2798501a339ba08d28f30eb96d17b3f5bbe996ca6a4dsewardj      switch (i->Ain.MulL.src->tag)  {
2799501a339ba08d28f30eb96d17b3f5bbe996ca6a4dsewardj         case Arm_Mem:
2800a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj            *p++ = rexAMode_M_enc(0, i->Ain.MulL.src->Arm.Mem.am);
2801501a339ba08d28f30eb96d17b3f5bbe996ca6a4dsewardj            *p++ = 0xF7;
2802a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj            p = doAMode_M_enc(p, subopc, i->Ain.MulL.src->Arm.Mem.am);
2803501a339ba08d28f30eb96d17b3f5bbe996ca6a4dsewardj            goto done;
2804501a339ba08d28f30eb96d17b3f5bbe996ca6a4dsewardj         case Arm_Reg:
2805a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj            *p++ = rexAMode_R_enc_reg(0, i->Ain.MulL.src->Arm.Reg.reg);
2806501a339ba08d28f30eb96d17b3f5bbe996ca6a4dsewardj            *p++ = 0xF7;
2807a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj            p = doAMode_R_enc_reg(p, subopc, i->Ain.MulL.src->Arm.Reg.reg);
2808501a339ba08d28f30eb96d17b3f5bbe996ca6a4dsewardj            goto done;
2809501a339ba08d28f30eb96d17b3f5bbe996ca6a4dsewardj         default:
2810501a339ba08d28f30eb96d17b3f5bbe996ca6a4dsewardj            goto bad;
28119b96767debeeb1f78378f0e7e295fe6762c64002sewardj      }
28129b96767debeeb1f78378f0e7e295fe6762c64002sewardj      break;
28139b96767debeeb1f78378f0e7e295fe6762c64002sewardj
28147de0d3c800437fbd82c59d57d156f4823d67609fsewardj   case Ain_Div:
28157de0d3c800437fbd82c59d57d156f4823d67609fsewardj      subopc = i->Ain.Div.syned ? 7 : 6;
28167de0d3c800437fbd82c59d57d156f4823d67609fsewardj      if (i->Ain.Div.sz == 4) {
28177de0d3c800437fbd82c59d57d156f4823d67609fsewardj         switch (i->Ain.Div.src->tag)  {
28187de0d3c800437fbd82c59d57d156f4823d67609fsewardj            case Arm_Mem:
2819a6b93d109a1d3b18e1ffaf3c1721216e79aaadc7sewardj               goto bad;
2820a6b93d109a1d3b18e1ffaf3c1721216e79aaadc7sewardj               /*FIXME*/
28217de0d3c800437fbd82c59d57d156f4823d67609fsewardj               *p++ = 0xF7;
2822a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj               p = doAMode_M_enc(p, subopc, i->Ain.Div.src->Arm.Mem.am);
28237de0d3c800437fbd82c59d57d156f4823d67609fsewardj               goto done;
28247de0d3c800437fbd82c59d57d156f4823d67609fsewardj            case Arm_Reg:
28257de0d3c800437fbd82c59d57d156f4823d67609fsewardj               *p++ = clearWBit(
2826a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj                      rexAMode_R_enc_reg(0, i->Ain.Div.src->Arm.Reg.reg));
28277de0d3c800437fbd82c59d57d156f4823d67609fsewardj               *p++ = 0xF7;
2828a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj               p = doAMode_R_enc_reg(p, subopc, i->Ain.Div.src->Arm.Reg.reg);
28297de0d3c800437fbd82c59d57d156f4823d67609fsewardj               goto done;
28307de0d3c800437fbd82c59d57d156f4823d67609fsewardj            default:
28317de0d3c800437fbd82c59d57d156f4823d67609fsewardj               goto bad;
28327de0d3c800437fbd82c59d57d156f4823d67609fsewardj         }
28337de0d3c800437fbd82c59d57d156f4823d67609fsewardj      }
2834a6b93d109a1d3b18e1ffaf3c1721216e79aaadc7sewardj      if (i->Ain.Div.sz == 8) {
2835a6b93d109a1d3b18e1ffaf3c1721216e79aaadc7sewardj         switch (i->Ain.Div.src->tag)  {
2836a6b93d109a1d3b18e1ffaf3c1721216e79aaadc7sewardj            case Arm_Mem:
2837a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj               *p++ = rexAMode_M_enc(0, i->Ain.Div.src->Arm.Mem.am);
2838a6b93d109a1d3b18e1ffaf3c1721216e79aaadc7sewardj               *p++ = 0xF7;
2839a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj               p = doAMode_M_enc(p, subopc, i->Ain.Div.src->Arm.Mem.am);
2840a6b93d109a1d3b18e1ffaf3c1721216e79aaadc7sewardj               goto done;
2841a6b93d109a1d3b18e1ffaf3c1721216e79aaadc7sewardj            case Arm_Reg:
2842a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj               *p++ = rexAMode_R_enc_reg(0, i->Ain.Div.src->Arm.Reg.reg);
2843a6b93d109a1d3b18e1ffaf3c1721216e79aaadc7sewardj               *p++ = 0xF7;
2844a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj               p = doAMode_R_enc_reg(p, subopc, i->Ain.Div.src->Arm.Reg.reg);
2845a6b93d109a1d3b18e1ffaf3c1721216e79aaadc7sewardj               goto done;
2846a6b93d109a1d3b18e1ffaf3c1721216e79aaadc7sewardj            default:
2847a6b93d109a1d3b18e1ffaf3c1721216e79aaadc7sewardj               goto bad;
2848a6b93d109a1d3b18e1ffaf3c1721216e79aaadc7sewardj         }
2849a6b93d109a1d3b18e1ffaf3c1721216e79aaadc7sewardj      }
28507de0d3c800437fbd82c59d57d156f4823d67609fsewardj      break;
28517de0d3c800437fbd82c59d57d156f4823d67609fsewardj
28521001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj   case Ain_Push:
28531001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj      switch (i->Ain.Push.src->tag) {
28541001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj         case Armi_Mem:
28551001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj            *p++ = clearWBit(
2856a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj                   rexAMode_M_enc(0, i->Ain.Push.src->Armi.Mem.am));
28571001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj            *p++ = 0xFF;
2858a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj            p = doAMode_M_enc(p, 6, i->Ain.Push.src->Armi.Mem.am);
28591001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj            goto done;
28601a01e65f9993d97095c2af463e98674a091834casewardj         case Armi_Imm:
28611a01e65f9993d97095c2af463e98674a091834casewardj            *p++ = 0x68;
28621a01e65f9993d97095c2af463e98674a091834casewardj            p = emit32(p, i->Ain.Push.src->Armi.Imm.imm32);
28631a01e65f9993d97095c2af463e98674a091834casewardj            goto done;
28641a01e65f9993d97095c2af463e98674a091834casewardj         case Armi_Reg:
2865a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj            *p++ = toUChar(0x40 + (1 & iregEnc3(i->Ain.Push.src->Armi.Reg.reg)));
2866a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj            *p++ = toUChar(0x50 + iregEnc210(i->Ain.Push.src->Armi.Reg.reg));
28671a01e65f9993d97095c2af463e98674a091834casewardj            goto done;
28681001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj        default:
28691001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj            goto bad;
28701001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj      }
28711b8d58eb046ad31fbb058d65855b604886d3d177sewardj
28724d77a9c73b332df0f5c7c36c2d8d72c7f22b735dsewardj   case Ain_Call: {
2873bdea5508b371d394c81b91464fa8df767010d4dasewardj      /* As per detailed comment for Ain_Call in getRegUsage_AMD64Instr
2874bdea5508b371d394c81b91464fa8df767010d4dasewardj         above, %r11 is used as an address temporary. */
2875bdea5508b371d394c81b91464fa8df767010d4dasewardj      /* If we don't need to do any fixup actions in the case that the
2876bdea5508b371d394c81b91464fa8df767010d4dasewardj         call doesn't happen, just do the simple thing and emit
2877bdea5508b371d394c81b91464fa8df767010d4dasewardj         straight-line code.  This is usually the case. */
2878bdea5508b371d394c81b91464fa8df767010d4dasewardj      if (i->Ain.Call.cond == Acc_ALWAYS/*call always happens*/
2879bdea5508b371d394c81b91464fa8df767010d4dasewardj          || i->Ain.Call.rloc.pri == RLPri_None/*no fixup action*/) {
2880bdea5508b371d394c81b91464fa8df767010d4dasewardj         /* jump over the following two insns if the condition does
2881bdea5508b371d394c81b91464fa8df767010d4dasewardj            not hold */
2882bdea5508b371d394c81b91464fa8df767010d4dasewardj         Bool shortImm = fitsIn32Bits(i->Ain.Call.target);
2883bdea5508b371d394c81b91464fa8df767010d4dasewardj         if (i->Ain.Call.cond != Acc_ALWAYS) {
2884bdea5508b371d394c81b91464fa8df767010d4dasewardj            *p++ = toUChar(0x70 + (0xF & (i->Ain.Call.cond ^ 1)));
2885bdea5508b371d394c81b91464fa8df767010d4dasewardj            *p++ = shortImm ? 10 : 13;
2886bdea5508b371d394c81b91464fa8df767010d4dasewardj            /* 10 or 13 bytes in the next two insns */
2887bdea5508b371d394c81b91464fa8df767010d4dasewardj         }
2888bdea5508b371d394c81b91464fa8df767010d4dasewardj         if (shortImm) {
2889bdea5508b371d394c81b91464fa8df767010d4dasewardj            /* 7 bytes: movl sign-extend(imm32), %r11 */
2890bdea5508b371d394c81b91464fa8df767010d4dasewardj            *p++ = 0x49;
2891bdea5508b371d394c81b91464fa8df767010d4dasewardj            *p++ = 0xC7;
2892bdea5508b371d394c81b91464fa8df767010d4dasewardj            *p++ = 0xC3;
2893bdea5508b371d394c81b91464fa8df767010d4dasewardj            p = emit32(p, (UInt)i->Ain.Call.target);
2894bdea5508b371d394c81b91464fa8df767010d4dasewardj         } else {
2895bdea5508b371d394c81b91464fa8df767010d4dasewardj            /* 10 bytes: movabsq $target, %r11 */
2896bdea5508b371d394c81b91464fa8df767010d4dasewardj            *p++ = 0x49;
2897bdea5508b371d394c81b91464fa8df767010d4dasewardj            *p++ = 0xBB;
2898bdea5508b371d394c81b91464fa8df767010d4dasewardj            p = emit64(p, i->Ain.Call.target);
2899bdea5508b371d394c81b91464fa8df767010d4dasewardj         }
2900bdea5508b371d394c81b91464fa8df767010d4dasewardj         /* 3 bytes: call *%r11 */
2901bdea5508b371d394c81b91464fa8df767010d4dasewardj         *p++ = 0x41;
2902bdea5508b371d394c81b91464fa8df767010d4dasewardj         *p++ = 0xFF;
2903bdea5508b371d394c81b91464fa8df767010d4dasewardj         *p++ = 0xD3;
29044d77a9c73b332df0f5c7c36c2d8d72c7f22b735dsewardj      } else {
2905bdea5508b371d394c81b91464fa8df767010d4dasewardj         Int delta;
2906bdea5508b371d394c81b91464fa8df767010d4dasewardj         /* Complex case.  We have to generate an if-then-else diamond. */
2907bdea5508b371d394c81b91464fa8df767010d4dasewardj         // before:
2908bdea5508b371d394c81b91464fa8df767010d4dasewardj         //   j{!cond} else:
2909bdea5508b371d394c81b91464fa8df767010d4dasewardj         //   movabsq $target, %r11
2910bdea5508b371d394c81b91464fa8df767010d4dasewardj         //   call* %r11
2911bdea5508b371d394c81b91464fa8df767010d4dasewardj         // preElse:
2912bdea5508b371d394c81b91464fa8df767010d4dasewardj         //   jmp after:
2913bdea5508b371d394c81b91464fa8df767010d4dasewardj         // else:
2914bdea5508b371d394c81b91464fa8df767010d4dasewardj         //   movabsq $0x5555555555555555, %rax  // possibly
2915bdea5508b371d394c81b91464fa8df767010d4dasewardj         //   movq %rax, %rdx                    // possibly
2916bdea5508b371d394c81b91464fa8df767010d4dasewardj         // after:
2917bdea5508b371d394c81b91464fa8df767010d4dasewardj
2918bdea5508b371d394c81b91464fa8df767010d4dasewardj         // before:
2919bdea5508b371d394c81b91464fa8df767010d4dasewardj         UChar* pBefore = p;
2920bdea5508b371d394c81b91464fa8df767010d4dasewardj
2921bdea5508b371d394c81b91464fa8df767010d4dasewardj         //   j{!cond} else:
2922bdea5508b371d394c81b91464fa8df767010d4dasewardj         *p++ = toUChar(0x70 + (0xF & (i->Ain.Call.cond ^ 1)));
2923bdea5508b371d394c81b91464fa8df767010d4dasewardj         *p++ = 0; /* # of bytes to jump over; don't know how many yet. */
2924bdea5508b371d394c81b91464fa8df767010d4dasewardj
2925bdea5508b371d394c81b91464fa8df767010d4dasewardj         //   movabsq $target, %r11
29264d77a9c73b332df0f5c7c36c2d8d72c7f22b735dsewardj         *p++ = 0x49;
29274d77a9c73b332df0f5c7c36c2d8d72c7f22b735dsewardj         *p++ = 0xBB;
29284d77a9c73b332df0f5c7c36c2d8d72c7f22b735dsewardj         p = emit64(p, i->Ain.Call.target);
2929bdea5508b371d394c81b91464fa8df767010d4dasewardj
2930bdea5508b371d394c81b91464fa8df767010d4dasewardj         //   call* %r11
2931bdea5508b371d394c81b91464fa8df767010d4dasewardj         *p++ = 0x41;
2932bdea5508b371d394c81b91464fa8df767010d4dasewardj         *p++ = 0xFF;
2933bdea5508b371d394c81b91464fa8df767010d4dasewardj         *p++ = 0xD3;
2934bdea5508b371d394c81b91464fa8df767010d4dasewardj
2935bdea5508b371d394c81b91464fa8df767010d4dasewardj         // preElse:
2936bdea5508b371d394c81b91464fa8df767010d4dasewardj         UChar* pPreElse = p;
2937bdea5508b371d394c81b91464fa8df767010d4dasewardj
2938bdea5508b371d394c81b91464fa8df767010d4dasewardj         //   jmp after:
2939bdea5508b371d394c81b91464fa8df767010d4dasewardj         *p++ = 0xEB;
2940bdea5508b371d394c81b91464fa8df767010d4dasewardj         *p++ = 0; /* # of bytes to jump over; don't know how many yet. */
2941bdea5508b371d394c81b91464fa8df767010d4dasewardj
2942bdea5508b371d394c81b91464fa8df767010d4dasewardj         // else:
2943bdea5508b371d394c81b91464fa8df767010d4dasewardj         UChar* pElse = p;
2944bdea5508b371d394c81b91464fa8df767010d4dasewardj
2945bdea5508b371d394c81b91464fa8df767010d4dasewardj         /* Do the 'else' actions */
2946bdea5508b371d394c81b91464fa8df767010d4dasewardj         switch (i->Ain.Call.rloc.pri) {
2947bdea5508b371d394c81b91464fa8df767010d4dasewardj            case RLPri_Int:
2948bdea5508b371d394c81b91464fa8df767010d4dasewardj               // movabsq $0x5555555555555555, %rax
2949bdea5508b371d394c81b91464fa8df767010d4dasewardj               *p++ = 0x48; *p++ = 0xB8; p = emit64(p, 0x5555555555555555ULL);
2950bdea5508b371d394c81b91464fa8df767010d4dasewardj               break;
2951bdea5508b371d394c81b91464fa8df767010d4dasewardj            case RLPri_2Int:
295270dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj               goto bad; //ATC
2953bdea5508b371d394c81b91464fa8df767010d4dasewardj               // movabsq $0x5555555555555555, %rax
2954bdea5508b371d394c81b91464fa8df767010d4dasewardj               *p++ = 0x48; *p++ = 0xB8; p = emit64(p, 0x5555555555555555ULL);
2955bdea5508b371d394c81b91464fa8df767010d4dasewardj               // movq %rax, %rdx
2956bdea5508b371d394c81b91464fa8df767010d4dasewardj               *p++ = 0x48; *p++ = 0x89; *p++ = 0xC2;
295770dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj               break;
295870dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj            case RLPri_V128SpRel:
295970dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj               if (i->Ain.Call.rloc.spOff == 0) {
296070dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj                  // We could accept any |spOff| here, but that's more
296170dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj                  // hassle and the only value we're ever going to get
296270dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj                  // is zero (I believe.)  Hence take the easy path :)
296370dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj                  // We need a scag register -- r11 can be it.
296470dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj                  // movabsq $0x5555555555555555, %r11
296570dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj                  *p++ = 0x49; *p++ = 0xBB;
296670dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj                  p = emit64(p, 0x5555555555555555ULL);
296770dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj                  // movq %r11, 0(%rsp)
296870dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj                  *p++ = 0x4C; *p++ = 0x89; *p++ = 0x1C; *p++ = 0x24;
296970dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj                  // movq %r11, 8(%rsp)
297070dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj                  *p++ = 0x4C; *p++ = 0x89; *p++ = 0x5C; *p++ = 0x24;
297170dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj                  *p++ = 0x08;
297270dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj                  break;
297370dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj               }
297470dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj               goto bad; //ATC for all other spOff values
297570dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj            case RLPri_V256SpRel:
297670dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj               goto bad; //ATC
2977bdea5508b371d394c81b91464fa8df767010d4dasewardj            case RLPri_None: case RLPri_INVALID: default:
297870dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj               vassert(0); // should never get here
2979bdea5508b371d394c81b91464fa8df767010d4dasewardj         }
2980bdea5508b371d394c81b91464fa8df767010d4dasewardj
2981bdea5508b371d394c81b91464fa8df767010d4dasewardj         // after:
2982bdea5508b371d394c81b91464fa8df767010d4dasewardj         UChar* pAfter = p;
2983bdea5508b371d394c81b91464fa8df767010d4dasewardj
2984bdea5508b371d394c81b91464fa8df767010d4dasewardj         // Fix up the branch offsets.  The +2s in the offset
2985bdea5508b371d394c81b91464fa8df767010d4dasewardj         // calculations are there because x86 requires conditional
2986bdea5508b371d394c81b91464fa8df767010d4dasewardj         // branches to have their offset stated relative to the
2987bdea5508b371d394c81b91464fa8df767010d4dasewardj         // instruction immediately following the branch insn.  And in
2988bdea5508b371d394c81b91464fa8df767010d4dasewardj         // both cases the branch insns are 2 bytes long.
2989bdea5508b371d394c81b91464fa8df767010d4dasewardj
2990bdea5508b371d394c81b91464fa8df767010d4dasewardj         // First, the "j{!cond} else:" at pBefore.
2991bdea5508b371d394c81b91464fa8df767010d4dasewardj         delta = (Int)(Long)(pElse - (pBefore + 2));
2992bdea5508b371d394c81b91464fa8df767010d4dasewardj         vassert(delta >= 0 && delta < 100/*arbitrary*/);
2993bdea5508b371d394c81b91464fa8df767010d4dasewardj         *(pBefore+1) = (UChar)delta;
2994bdea5508b371d394c81b91464fa8df767010d4dasewardj
2995bdea5508b371d394c81b91464fa8df767010d4dasewardj         // And secondly, the "jmp after:" at pPreElse.
2996bdea5508b371d394c81b91464fa8df767010d4dasewardj         delta = (Int)(Long)(pAfter - (pPreElse + 2));
2997bdea5508b371d394c81b91464fa8df767010d4dasewardj         vassert(delta >= 0 && delta < 100/*arbitrary*/);
2998bdea5508b371d394c81b91464fa8df767010d4dasewardj         *(pPreElse+1) = (UChar)delta;
29991b8d58eb046ad31fbb058d65855b604886d3d177sewardj      }
30001b8d58eb046ad31fbb058d65855b604886d3d177sewardj      goto done;
30014d77a9c73b332df0f5c7c36c2d8d72c7f22b735dsewardj   }
3002549e06463d433ee6351b72dc9107f22ce4305250sewardj
3003c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   case Ain_XDirect: {
3004c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      /* NB: what goes on here has to be very closely coordinated with the
3005c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         chainXDirect_AMD64 and unchainXDirect_AMD64 below. */
3006c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      /* We're generating chain-me requests here, so we need to be
3007c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         sure this is actually allowed -- no-redir translations can't
3008c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         use chain-me's.  Hence: */
3009c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      vassert(disp_cp_chain_me_to_slowEP != NULL);
3010c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      vassert(disp_cp_chain_me_to_fastEP != NULL);
3011c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj
3012c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      HReg r11 = hregAMD64_R11();
3013010ac5400c3294a8c0991fac7b382578e5b91b1csewardj
3014549e06463d433ee6351b72dc9107f22ce4305250sewardj      /* Use ptmp for backpatching conditional jumps. */
3015549e06463d433ee6351b72dc9107f22ce4305250sewardj      ptmp = NULL;
3016549e06463d433ee6351b72dc9107f22ce4305250sewardj
3017549e06463d433ee6351b72dc9107f22ce4305250sewardj      /* First off, if this is conditional, create a conditional
3018549e06463d433ee6351b72dc9107f22ce4305250sewardj         jump over the rest of it. */
3019c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      if (i->Ain.XDirect.cond != Acc_ALWAYS) {
3020549e06463d433ee6351b72dc9107f22ce4305250sewardj         /* jmp fwds if !condition */
3021c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         *p++ = toUChar(0x70 + (0xF & (i->Ain.XDirect.cond ^ 1)));
3022549e06463d433ee6351b72dc9107f22ce4305250sewardj         ptmp = p; /* fill in this bit later */
3023549e06463d433ee6351b72dc9107f22ce4305250sewardj         *p++ = 0; /* # of bytes to jump over; don't know how many yet. */
3024549e06463d433ee6351b72dc9107f22ce4305250sewardj      }
3025549e06463d433ee6351b72dc9107f22ce4305250sewardj
3026c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      /* Update the guest RIP. */
30273e8ba60decf63c6c349ccfe509733c81aee8c6b8sewardj      if (fitsIn32Bits(i->Ain.XDirect.dstGA)) {
30283e8ba60decf63c6c349ccfe509733c81aee8c6b8sewardj         /* use a shorter encoding */
30293e8ba60decf63c6c349ccfe509733c81aee8c6b8sewardj         /* movl sign-extend(dstGA), %r11 */
30303e8ba60decf63c6c349ccfe509733c81aee8c6b8sewardj         *p++ = 0x49;
30313e8ba60decf63c6c349ccfe509733c81aee8c6b8sewardj         *p++ = 0xC7;
30323e8ba60decf63c6c349ccfe509733c81aee8c6b8sewardj         *p++ = 0xC3;
30333e8ba60decf63c6c349ccfe509733c81aee8c6b8sewardj         p = emit32(p, (UInt)i->Ain.XDirect.dstGA);
30343e8ba60decf63c6c349ccfe509733c81aee8c6b8sewardj      } else {
30353e8ba60decf63c6c349ccfe509733c81aee8c6b8sewardj         /* movabsq $dstGA, %r11 */
30363e8ba60decf63c6c349ccfe509733c81aee8c6b8sewardj         *p++ = 0x49;
30373e8ba60decf63c6c349ccfe509733c81aee8c6b8sewardj         *p++ = 0xBB;
30383e8ba60decf63c6c349ccfe509733c81aee8c6b8sewardj         p = emit64(p, i->Ain.XDirect.dstGA);
30393e8ba60decf63c6c349ccfe509733c81aee8c6b8sewardj      }
30403e8ba60decf63c6c349ccfe509733c81aee8c6b8sewardj
3041c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      /* movq %r11, amRIP */
3042c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      *p++ = rexAMode_M(r11, i->Ain.XDirect.amRIP);
3043c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      *p++ = 0x89;
3044c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      p = doAMode_M(p, r11, i->Ain.XDirect.amRIP);
3045c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj
3046c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      /* --- FIRST PATCHABLE BYTE follows --- */
3047c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      /* VG_(disp_cp_chain_me_to_{slowEP,fastEP}) (where we're calling
3048c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         to) backs up the return address, so as to find the address of
3049c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         the first patchable byte.  So: don't change the length of the
3050c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         two instructions below. */
3051c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      /* movabsq $disp_cp_chain_me_to_{slow,fast}EP,%r11; */
3052c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      *p++ = 0x49;
3053c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      *p++ = 0xBB;
30548462d113e3efeacceb304222dada8d85f748295aflorian      const void* disp_cp_chain_me
3055c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj               = i->Ain.XDirect.toFastEP ? disp_cp_chain_me_to_fastEP
3056c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj                                         : disp_cp_chain_me_to_slowEP;
305793a09742b0de3d61718882c2d999f64be402564dflorian      p = emit64(p, (Addr)disp_cp_chain_me);
3058c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      /* call *%r11 */
3059c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      *p++ = 0x41;
3060c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      *p++ = 0xFF;
3061c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      *p++ = 0xD3;
3062c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      /* --- END of PATCHABLE BYTES --- */
3063c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj
3064c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      /* Fix up the conditional jump, if there was one. */
3065c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      if (i->Ain.XDirect.cond != Acc_ALWAYS) {
3066c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         Int delta = p - ptmp;
3067c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         vassert(delta > 0 && delta < 40);
3068c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         *ptmp = toUChar(delta-1);
3069549e06463d433ee6351b72dc9107f22ce4305250sewardj      }
3070c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      goto done;
3071c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   }
3072549e06463d433ee6351b72dc9107f22ce4305250sewardj
3073c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   case Ain_XIndir: {
3074c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      /* We're generating transfers that could lead indirectly to a
3075c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         chain-me, so we need to be sure this is actually allowed --
3076c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         no-redir translations are not allowed to reach normal
3077c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         translations without going through the scheduler.  That means
3078c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         no XDirects or XIndirs out from no-redir translations.
3079c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         Hence: */
3080c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      vassert(disp_cp_xindir != NULL);
3081c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj
3082c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      /* Use ptmp for backpatching conditional jumps. */
3083c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      ptmp = NULL;
3084c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj
3085c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      /* First off, if this is conditional, create a conditional
3086c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         jump over the rest of it. */
3087c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      if (i->Ain.XIndir.cond != Acc_ALWAYS) {
3088c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         /* jmp fwds if !condition */
3089c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         *p++ = toUChar(0x70 + (0xF & (i->Ain.XIndir.cond ^ 1)));
3090c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         ptmp = p; /* fill in this bit later */
3091c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         *p++ = 0; /* # of bytes to jump over; don't know how many yet. */
3092549e06463d433ee6351b72dc9107f22ce4305250sewardj      }
3093549e06463d433ee6351b72dc9107f22ce4305250sewardj
3094c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      /* movq dstGA(a reg), amRIP -- copied from Alu64M MOV case */
3095c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      *p++ = rexAMode_M(i->Ain.XIndir.dstGA, i->Ain.XIndir.amRIP);
3096c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      *p++ = 0x89;
3097c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      p = doAMode_M(p, i->Ain.XIndir.dstGA, i->Ain.XIndir.amRIP);
30983e8ba60decf63c6c349ccfe509733c81aee8c6b8sewardj
30993e8ba60decf63c6c349ccfe509733c81aee8c6b8sewardj      /* get $disp_cp_xindir into %r11 */
310093a09742b0de3d61718882c2d999f64be402564dflorian      if (fitsIn32Bits((Addr)disp_cp_xindir)) {
31013e8ba60decf63c6c349ccfe509733c81aee8c6b8sewardj         /* use a shorter encoding */
31023e8ba60decf63c6c349ccfe509733c81aee8c6b8sewardj         /* movl sign-extend(disp_cp_xindir), %r11 */
31033e8ba60decf63c6c349ccfe509733c81aee8c6b8sewardj         *p++ = 0x49;
31043e8ba60decf63c6c349ccfe509733c81aee8c6b8sewardj         *p++ = 0xC7;
31053e8ba60decf63c6c349ccfe509733c81aee8c6b8sewardj         *p++ = 0xC3;
310693a09742b0de3d61718882c2d999f64be402564dflorian         p = emit32(p, (UInt)(Addr)disp_cp_xindir);
31073e8ba60decf63c6c349ccfe509733c81aee8c6b8sewardj      } else {
31083e8ba60decf63c6c349ccfe509733c81aee8c6b8sewardj         /* movabsq $disp_cp_xindir, %r11 */
31093e8ba60decf63c6c349ccfe509733c81aee8c6b8sewardj         *p++ = 0x49;
31103e8ba60decf63c6c349ccfe509733c81aee8c6b8sewardj         *p++ = 0xBB;
311193a09742b0de3d61718882c2d999f64be402564dflorian         p = emit64(p, (Addr)disp_cp_xindir);
31123e8ba60decf63c6c349ccfe509733c81aee8c6b8sewardj      }
31133e8ba60decf63c6c349ccfe509733c81aee8c6b8sewardj
3114c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      /* jmp *%r11 */
3115c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      *p++ = 0x41;
3116c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      *p++ = 0xFF;
3117c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      *p++ = 0xE3;
31180528bb5bd879eed0e8fa7e2bc9bc8debea00bf5fsewardj
3119c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      /* Fix up the conditional jump, if there was one. */
3120c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      if (i->Ain.XIndir.cond != Acc_ALWAYS) {
3121c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         Int delta = p - ptmp;
3122c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         vassert(delta > 0 && delta < 40);
3123c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         *ptmp = toUChar(delta-1);
3124c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      }
3125c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      goto done;
3126c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   }
3127c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj
3128c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   case Ain_XAssisted: {
3129c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      /* Use ptmp for backpatching conditional jumps. */
3130c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      ptmp = NULL;
3131c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj
3132c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      /* First off, if this is conditional, create a conditional
3133c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         jump over the rest of it. */
3134c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      if (i->Ain.XAssisted.cond != Acc_ALWAYS) {
3135c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         /* jmp fwds if !condition */
3136c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         *p++ = toUChar(0x70 + (0xF & (i->Ain.XAssisted.cond ^ 1)));
3137c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         ptmp = p; /* fill in this bit later */
3138c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         *p++ = 0; /* # of bytes to jump over; don't know how many yet. */
31394d77a9c73b332df0f5c7c36c2d8d72c7f22b735dsewardj      }
3140c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj
3141c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      /* movq dstGA(a reg), amRIP -- copied from Alu64M MOV case */
3142c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      *p++ = rexAMode_M(i->Ain.XAssisted.dstGA, i->Ain.XAssisted.amRIP);
3143c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      *p++ = 0x89;
3144c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      p = doAMode_M(p, i->Ain.XAssisted.dstGA, i->Ain.XAssisted.amRIP);
3145c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      /* movl $magic_number, %ebp.  Since these numbers are all small positive
3146c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         integers, we can get away with "movl $N, %ebp" rather than
3147c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         the longer "movq $N, %rbp". */
3148c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      UInt trcval = 0;
3149c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      switch (i->Ain.XAssisted.jk) {
3150c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         case Ijk_ClientReq:   trcval = VEX_TRC_JMP_CLIENTREQ;   break;
3151c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         case Ijk_Sys_syscall: trcval = VEX_TRC_JMP_SYS_SYSCALL; break;
3152c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         case Ijk_Sys_int32:   trcval = VEX_TRC_JMP_SYS_INT32;   break;
31533e5d82d003f0746010e22c7cfc4a25b34c9641f1sewardj         case Ijk_Sys_int210:  trcval = VEX_TRC_JMP_SYS_INT210;  break;
3154c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         case Ijk_Yield:       trcval = VEX_TRC_JMP_YIELD;       break;
3155c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         case Ijk_EmWarn:      trcval = VEX_TRC_JMP_EMWARN;      break;
3156c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         case Ijk_MapFail:     trcval = VEX_TRC_JMP_MAPFAIL;     break;
3157c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         case Ijk_NoDecode:    trcval = VEX_TRC_JMP_NODECODE;    break;
315805f5e0172384dd2983fb16fbb7deebd74d71cd35sewardj         case Ijk_InvalICache: trcval = VEX_TRC_JMP_INVALICACHE; break;
3159c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         case Ijk_NoRedir:     trcval = VEX_TRC_JMP_NOREDIR;     break;
3160c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         case Ijk_SigTRAP:     trcval = VEX_TRC_JMP_SIGTRAP;     break;
3161c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         case Ijk_SigSEGV:     trcval = VEX_TRC_JMP_SIGSEGV;     break;
3162c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         case Ijk_Boring:      trcval = VEX_TRC_JMP_BORING;      break;
3163c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         /* We don't expect to see the following being assisted. */
3164c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         case Ijk_Ret:
3165c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         case Ijk_Call:
3166c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         /* fallthrough */
3167c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         default:
3168c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj            ppIRJumpKind(i->Ain.XAssisted.jk);
3169c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj            vpanic("emit_AMD64Instr.Ain_XAssisted: unexpected jump kind");
3170c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      }
3171c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      vassert(trcval != 0);
3172c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      *p++ = 0xBD;
3173c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      p = emit32(p, trcval);
3174c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      /* movabsq $disp_assisted, %r11 */
3175c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      *p++ = 0x49;
3176c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      *p++ = 0xBB;
317793a09742b0de3d61718882c2d999f64be402564dflorian      p = emit64(p, (Addr)disp_cp_xassisted);
3178c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      /* jmp *%r11 */
3179c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      *p++ = 0x41;
31800528bb5bd879eed0e8fa7e2bc9bc8debea00bf5fsewardj      *p++ = 0xFF;
3181c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      *p++ = 0xE3;
3182549e06463d433ee6351b72dc9107f22ce4305250sewardj
3183549e06463d433ee6351b72dc9107f22ce4305250sewardj      /* Fix up the conditional jump, if there was one. */
3184c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      if (i->Ain.XAssisted.cond != Acc_ALWAYS) {
3185549e06463d433ee6351b72dc9107f22ce4305250sewardj         Int delta = p - ptmp;
3186c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         vassert(delta > 0 && delta < 40);
318703ccf858efa285d793061359c04fdd0055cd9d31sewardj         *ptmp = toUChar(delta-1);
3188549e06463d433ee6351b72dc9107f22ce4305250sewardj      }
3189549e06463d433ee6351b72dc9107f22ce4305250sewardj      goto done;
3190010ac5400c3294a8c0991fac7b382578e5b91b1csewardj   }
3191549e06463d433ee6351b72dc9107f22ce4305250sewardj
31921b8d58eb046ad31fbb058d65855b604886d3d177sewardj   case Ain_CMov64:
31931b8d58eb046ad31fbb058d65855b604886d3d177sewardj      vassert(i->Ain.CMov64.cond != Acc_ALWAYS);
3194e357c67787b7429f85a030ee5fbedf33173b5656sewardj      *p++ = rexAMode_R(i->Ain.CMov64.dst, i->Ain.CMov64.src);
3195e357c67787b7429f85a030ee5fbedf33173b5656sewardj      *p++ = 0x0F;
3196e357c67787b7429f85a030ee5fbedf33173b5656sewardj      *p++ = toUChar(0x40 + (0xF & i->Ain.CMov64.cond));
3197e357c67787b7429f85a030ee5fbedf33173b5656sewardj      p = doAMode_R(p, i->Ain.CMov64.dst, i->Ain.CMov64.src);
3198e357c67787b7429f85a030ee5fbedf33173b5656sewardj      goto done;
3199549e06463d433ee6351b72dc9107f22ce4305250sewardj
3200bdea5508b371d394c81b91464fa8df767010d4dasewardj   case Ain_CLoad: {
3201bdea5508b371d394c81b91464fa8df767010d4dasewardj      vassert(i->Ain.CLoad.cond != Acc_ALWAYS);
3202bdea5508b371d394c81b91464fa8df767010d4dasewardj
3203bdea5508b371d394c81b91464fa8df767010d4dasewardj      /* Only 32- or 64-bit variants are allowed. */
3204bdea5508b371d394c81b91464fa8df767010d4dasewardj      vassert(i->Ain.CLoad.szB == 4 || i->Ain.CLoad.szB == 8);
3205bdea5508b371d394c81b91464fa8df767010d4dasewardj
3206bdea5508b371d394c81b91464fa8df767010d4dasewardj      /* Use ptmp for backpatching conditional jumps. */
3207bdea5508b371d394c81b91464fa8df767010d4dasewardj      ptmp = NULL;
3208bdea5508b371d394c81b91464fa8df767010d4dasewardj
3209bdea5508b371d394c81b91464fa8df767010d4dasewardj      /* jmp fwds if !condition */
3210bdea5508b371d394c81b91464fa8df767010d4dasewardj      *p++ = toUChar(0x70 + (0xF & (i->Ain.CLoad.cond ^ 1)));
3211bdea5508b371d394c81b91464fa8df767010d4dasewardj      ptmp = p; /* fill in this bit later */
3212bdea5508b371d394c81b91464fa8df767010d4dasewardj      *p++ = 0; /* # of bytes to jump over; don't know how many yet. */
3213bdea5508b371d394c81b91464fa8df767010d4dasewardj
3214bdea5508b371d394c81b91464fa8df767010d4dasewardj      /* Now the load.  Either a normal 64 bit load or a normal 32 bit
3215bdea5508b371d394c81b91464fa8df767010d4dasewardj         load, which, by the default zero-extension rule, zeroes out
3216bdea5508b371d394c81b91464fa8df767010d4dasewardj         the upper half of the destination, as required. */
3217bdea5508b371d394c81b91464fa8df767010d4dasewardj      rex = rexAMode_M(i->Ain.CLoad.dst, i->Ain.CLoad.addr);
3218bdea5508b371d394c81b91464fa8df767010d4dasewardj      *p++ = i->Ain.CLoad.szB == 4 ? clearWBit(rex) : rex;
3219bdea5508b371d394c81b91464fa8df767010d4dasewardj      *p++ = 0x8B;
3220bdea5508b371d394c81b91464fa8df767010d4dasewardj      p = doAMode_M(p, i->Ain.CLoad.dst, i->Ain.CLoad.addr);
3221bdea5508b371d394c81b91464fa8df767010d4dasewardj
3222bdea5508b371d394c81b91464fa8df767010d4dasewardj      /* Fix up the conditional branch */
3223bdea5508b371d394c81b91464fa8df767010d4dasewardj      Int delta = p - ptmp;
3224bdea5508b371d394c81b91464fa8df767010d4dasewardj      vassert(delta > 0 && delta < 40);
3225bdea5508b371d394c81b91464fa8df767010d4dasewardj      *ptmp = toUChar(delta-1);
3226bdea5508b371d394c81b91464fa8df767010d4dasewardj      goto done;
3227bdea5508b371d394c81b91464fa8df767010d4dasewardj   }
3228bdea5508b371d394c81b91464fa8df767010d4dasewardj
32296f1ec58d9806064dea0000e4b543aacded9b11easewardj   case Ain_CStore: {
323070dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj      /* AFAICS this is identical to Ain_CLoad except that the opcode
32316f1ec58d9806064dea0000e4b543aacded9b11easewardj         is 0x89 instead of 0x8B. */
32326f1ec58d9806064dea0000e4b543aacded9b11easewardj      vassert(i->Ain.CStore.cond != Acc_ALWAYS);
32336f1ec58d9806064dea0000e4b543aacded9b11easewardj
32346f1ec58d9806064dea0000e4b543aacded9b11easewardj      /* Only 32- or 64-bit variants are allowed. */
32356f1ec58d9806064dea0000e4b543aacded9b11easewardj      vassert(i->Ain.CStore.szB == 4 || i->Ain.CStore.szB == 8);
32366f1ec58d9806064dea0000e4b543aacded9b11easewardj
32376f1ec58d9806064dea0000e4b543aacded9b11easewardj      /* Use ptmp for backpatching conditional jumps. */
32386f1ec58d9806064dea0000e4b543aacded9b11easewardj      ptmp = NULL;
32396f1ec58d9806064dea0000e4b543aacded9b11easewardj
32406f1ec58d9806064dea0000e4b543aacded9b11easewardj      /* jmp fwds if !condition */
32416f1ec58d9806064dea0000e4b543aacded9b11easewardj      *p++ = toUChar(0x70 + (0xF & (i->Ain.CStore.cond ^ 1)));
32426f1ec58d9806064dea0000e4b543aacded9b11easewardj      ptmp = p; /* fill in this bit later */
32436f1ec58d9806064dea0000e4b543aacded9b11easewardj      *p++ = 0; /* # of bytes to jump over; don't know how many yet. */
32446f1ec58d9806064dea0000e4b543aacded9b11easewardj
32456f1ec58d9806064dea0000e4b543aacded9b11easewardj      /* Now the store. */
32466f1ec58d9806064dea0000e4b543aacded9b11easewardj      rex = rexAMode_M(i->Ain.CStore.src, i->Ain.CStore.addr);
32476f1ec58d9806064dea0000e4b543aacded9b11easewardj      *p++ = i->Ain.CStore.szB == 4 ? clearWBit(rex) : rex;
32486f1ec58d9806064dea0000e4b543aacded9b11easewardj      *p++ = 0x89;
32496f1ec58d9806064dea0000e4b543aacded9b11easewardj      p = doAMode_M(p, i->Ain.CStore.src, i->Ain.CStore.addr);
32506f1ec58d9806064dea0000e4b543aacded9b11easewardj
32516f1ec58d9806064dea0000e4b543aacded9b11easewardj      /* Fix up the conditional branch */
32526f1ec58d9806064dea0000e4b543aacded9b11easewardj      Int delta = p - ptmp;
32536f1ec58d9806064dea0000e4b543aacded9b11easewardj      vassert(delta > 0 && delta < 40);
32546f1ec58d9806064dea0000e4b543aacded9b11easewardj      *ptmp = toUChar(delta-1);
32556f1ec58d9806064dea0000e4b543aacded9b11easewardj      goto done;
32566f1ec58d9806064dea0000e4b543aacded9b11easewardj   }
32576f1ec58d9806064dea0000e4b543aacded9b11easewardj
3258ca257bc572147c1a9c7d9a2e81237125a35ff25dsewardj   case Ain_MovxLQ:
3259ca257bc572147c1a9c7d9a2e81237125a35ff25dsewardj      /* No, _don't_ ask me why the sense of the args has to be
3260ca257bc572147c1a9c7d9a2e81237125a35ff25dsewardj         different in the S vs Z case.  I don't know. */
3261ca257bc572147c1a9c7d9a2e81237125a35ff25dsewardj      if (i->Ain.MovxLQ.syned) {
3262ca257bc572147c1a9c7d9a2e81237125a35ff25dsewardj         /* Need REX.W = 1 here, but rexAMode_R does that for us. */
3263ca257bc572147c1a9c7d9a2e81237125a35ff25dsewardj         *p++ = rexAMode_R(i->Ain.MovxLQ.dst, i->Ain.MovxLQ.src);
3264ca257bc572147c1a9c7d9a2e81237125a35ff25dsewardj         *p++ = 0x63;
3265ca257bc572147c1a9c7d9a2e81237125a35ff25dsewardj         p = doAMode_R(p, i->Ain.MovxLQ.dst, i->Ain.MovxLQ.src);
3266ca257bc572147c1a9c7d9a2e81237125a35ff25dsewardj      } else {
3267ca257bc572147c1a9c7d9a2e81237125a35ff25dsewardj         /* Produce a 32-bit reg-reg move, since the implicit
3268ca257bc572147c1a9c7d9a2e81237125a35ff25dsewardj            zero-extend does what we want. */
3269ca257bc572147c1a9c7d9a2e81237125a35ff25dsewardj         *p++ = clearWBit (
3270ca257bc572147c1a9c7d9a2e81237125a35ff25dsewardj                   rexAMode_R(i->Ain.MovxLQ.src, i->Ain.MovxLQ.dst));
3271ca257bc572147c1a9c7d9a2e81237125a35ff25dsewardj         *p++ = 0x89;
3272ca257bc572147c1a9c7d9a2e81237125a35ff25dsewardj         p = doAMode_R(p, i->Ain.MovxLQ.src, i->Ain.MovxLQ.dst);
3273ca257bc572147c1a9c7d9a2e81237125a35ff25dsewardj      }
3274549e06463d433ee6351b72dc9107f22ce4305250sewardj      goto done;
3275549e06463d433ee6351b72dc9107f22ce4305250sewardj
3276549e06463d433ee6351b72dc9107f22ce4305250sewardj   case Ain_LoadEX:
32771b8d58eb046ad31fbb058d65855b604886d3d177sewardj      if (i->Ain.LoadEX.szSmall == 1 && !i->Ain.LoadEX.syned) {
32781b8d58eb046ad31fbb058d65855b604886d3d177sewardj         /* movzbq */
32791b8d58eb046ad31fbb058d65855b604886d3d177sewardj         *p++ = rexAMode_M(i->Ain.LoadEX.dst, i->Ain.LoadEX.src);
32801b8d58eb046ad31fbb058d65855b604886d3d177sewardj         *p++ = 0x0F;
32811b8d58eb046ad31fbb058d65855b604886d3d177sewardj         *p++ = 0xB6;
32821b8d58eb046ad31fbb058d65855b604886d3d177sewardj         p = doAMode_M(p, i->Ain.LoadEX.dst, i->Ain.LoadEX.src);
32831b8d58eb046ad31fbb058d65855b604886d3d177sewardj         goto done;
32841b8d58eb046ad31fbb058d65855b604886d3d177sewardj      }
32851b8d58eb046ad31fbb058d65855b604886d3d177sewardj      if (i->Ain.LoadEX.szSmall == 2 && !i->Ain.LoadEX.syned) {
32861b8d58eb046ad31fbb058d65855b604886d3d177sewardj         /* movzwq */
32871b8d58eb046ad31fbb058d65855b604886d3d177sewardj         *p++ = rexAMode_M(i->Ain.LoadEX.dst, i->Ain.LoadEX.src);
32881b8d58eb046ad31fbb058d65855b604886d3d177sewardj         *p++ = 0x0F;
32891b8d58eb046ad31fbb058d65855b604886d3d177sewardj         *p++ = 0xB7;
32901b8d58eb046ad31fbb058d65855b604886d3d177sewardj         p = doAMode_M(p, i->Ain.LoadEX.dst, i->Ain.LoadEX.src);
32911b8d58eb046ad31fbb058d65855b604886d3d177sewardj         goto done;
32921b8d58eb046ad31fbb058d65855b604886d3d177sewardj      }
3293549e06463d433ee6351b72dc9107f22ce4305250sewardj      if (i->Ain.LoadEX.szSmall == 4 && !i->Ain.LoadEX.syned) {
3294549e06463d433ee6351b72dc9107f22ce4305250sewardj         /* movzlq */
32951b8d58eb046ad31fbb058d65855b604886d3d177sewardj         /* This isn't really an existing AMD64 instruction per se.
3296549e06463d433ee6351b72dc9107f22ce4305250sewardj            Rather, we have to do a 32-bit load.  Because a 32-bit
3297549e06463d433ee6351b72dc9107f22ce4305250sewardj            write implicitly clears the upper 32 bits of the target
3298549e06463d433ee6351b72dc9107f22ce4305250sewardj            register, we get what we want. */
3299549e06463d433ee6351b72dc9107f22ce4305250sewardj         *p++ = clearWBit(
3300549e06463d433ee6351b72dc9107f22ce4305250sewardj                rexAMode_M(i->Ain.LoadEX.dst, i->Ain.LoadEX.src));
3301549e06463d433ee6351b72dc9107f22ce4305250sewardj         *p++ = 0x8B;
3302549e06463d433ee6351b72dc9107f22ce4305250sewardj         p = doAMode_M(p, i->Ain.LoadEX.dst, i->Ain.LoadEX.src);
3303549e06463d433ee6351b72dc9107f22ce4305250sewardj         goto done;
3304549e06463d433ee6351b72dc9107f22ce4305250sewardj      }
3305549e06463d433ee6351b72dc9107f22ce4305250sewardj      break;
3306549e06463d433ee6351b72dc9107f22ce4305250sewardj
3307a5bd0aff6eda3e7c312f51ae6bc742ea62b5d404sewardj   case Ain_Set64:
3308a5bd0aff6eda3e7c312f51ae6bc742ea62b5d404sewardj      /* Make the destination register be 1 or 0, depending on whether
3309a5bd0aff6eda3e7c312f51ae6bc742ea62b5d404sewardj         the relevant condition holds.  Complication: the top 56 bits
3310a5bd0aff6eda3e7c312f51ae6bc742ea62b5d404sewardj         of the destination should be forced to zero, but doing 'xorq
3311a5bd0aff6eda3e7c312f51ae6bc742ea62b5d404sewardj         %r,%r' kills the flag(s) we are about to read.  Sigh.  So
3312a5bd0aff6eda3e7c312f51ae6bc742ea62b5d404sewardj         start off my moving $0 into the dest. */
3313a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj      reg = iregEnc3210(i->Ain.Set64.dst);
3314a5bd0aff6eda3e7c312f51ae6bc742ea62b5d404sewardj      vassert(reg < 16);
3315a5bd0aff6eda3e7c312f51ae6bc742ea62b5d404sewardj
3316a5bd0aff6eda3e7c312f51ae6bc742ea62b5d404sewardj      /* movq $0, %dst */
3317a5bd0aff6eda3e7c312f51ae6bc742ea62b5d404sewardj      *p++ = toUChar(reg >= 8 ? 0x49 : 0x48);
3318a5bd0aff6eda3e7c312f51ae6bc742ea62b5d404sewardj      *p++ = 0xC7;
3319a5bd0aff6eda3e7c312f51ae6bc742ea62b5d404sewardj      *p++ = toUChar(0xC0 + (reg & 7));
3320a5bd0aff6eda3e7c312f51ae6bc742ea62b5d404sewardj      p = emit32(p, 0);
3321a5bd0aff6eda3e7c312f51ae6bc742ea62b5d404sewardj
3322a5bd0aff6eda3e7c312f51ae6bc742ea62b5d404sewardj      /* setb lo8(%dst) */
3323a5bd0aff6eda3e7c312f51ae6bc742ea62b5d404sewardj      /* note, 8-bit register rex trickyness.  Be careful here. */
3324a5bd0aff6eda3e7c312f51ae6bc742ea62b5d404sewardj      *p++ = toUChar(reg >= 8 ? 0x41 : 0x40);
3325a5bd0aff6eda3e7c312f51ae6bc742ea62b5d404sewardj      *p++ = 0x0F;
3326a5bd0aff6eda3e7c312f51ae6bc742ea62b5d404sewardj      *p++ = toUChar(0x90 + (0x0F & i->Ain.Set64.cond));
3327a5bd0aff6eda3e7c312f51ae6bc742ea62b5d404sewardj      *p++ = toUChar(0xC0 + (reg & 7));
3328a5bd0aff6eda3e7c312f51ae6bc742ea62b5d404sewardj      goto done;
3329a5bd0aff6eda3e7c312f51ae6bc742ea62b5d404sewardj
3330f53b7359a342e7d79090615169c6583a1a75fbcesewardj   case Ain_Bsfr64:
3331f53b7359a342e7d79090615169c6583a1a75fbcesewardj      *p++ = rexAMode_R(i->Ain.Bsfr64.dst, i->Ain.Bsfr64.src);
3332f53b7359a342e7d79090615169c6583a1a75fbcesewardj      *p++ = 0x0F;
3333f53b7359a342e7d79090615169c6583a1a75fbcesewardj      if (i->Ain.Bsfr64.isFwds) {
3334f53b7359a342e7d79090615169c6583a1a75fbcesewardj         *p++ = 0xBC;
3335f53b7359a342e7d79090615169c6583a1a75fbcesewardj      } else {
3336f53b7359a342e7d79090615169c6583a1a75fbcesewardj         *p++ = 0xBD;
3337f53b7359a342e7d79090615169c6583a1a75fbcesewardj      }
3338f53b7359a342e7d79090615169c6583a1a75fbcesewardj      p = doAMode_R(p, i->Ain.Bsfr64.dst, i->Ain.Bsfr64.src);
3339f53b7359a342e7d79090615169c6583a1a75fbcesewardj      goto done;
3340d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj
3341d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj   case Ain_MFence:
3342d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj      /* mfence */
3343d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj      *p++ = 0x0F; *p++ = 0xAE; *p++ = 0xF0;
3344d0a12df66280288ed336f61b4b9a0c769b2ecef8sewardj      goto done;
33451b8d58eb046ad31fbb058d65855b604886d3d177sewardj
3346e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj   case Ain_ACAS:
3347e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj      /* lock */
3348e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj      *p++ = 0xF0;
3349e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj      if (i->Ain.ACAS.sz == 2) *p++ = 0x66;
3350e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj      /* cmpxchg{b,w,l,q} %rbx,mem.  Expected-value in %rax, new value
3351e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         in %rbx.  The new-value register is hardwired to be %rbx
3352e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         since dealing with byte integer registers is too much hassle,
3353e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         so we force the register operand to %rbx (could equally be
3354e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         %rcx or %rdx). */
3355e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj      rex = rexAMode_M( hregAMD64_RBX(), i->Ain.ACAS.addr );
3356e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj      if (i->Ain.ACAS.sz != 8)
3357e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         rex = clearWBit(rex);
3358e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj
3359e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj      *p++ = rex; /* this can emit 0x40, which is pointless. oh well. */
3360e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj      *p++ = 0x0F;
3361e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj      if (i->Ain.ACAS.sz == 1) *p++ = 0xB0; else *p++ = 0xB1;
3362e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj      p = doAMode_M(p, hregAMD64_RBX(), i->Ain.ACAS.addr);
3363e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj      goto done;
3364e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj
3365e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj   case Ain_DACAS:
3366e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj      /* lock */
3367e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj      *p++ = 0xF0;
3368e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj      /* cmpxchg{8,16}b m{64,128}.  Expected-value in %rdx:%rax, new
3369e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         value in %rcx:%rbx.  All 4 regs are hardwired in the ISA, so
3370e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         aren't encoded in the insn. */
3371a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj      rex = rexAMode_M_enc(1, i->Ain.ACAS.addr );
3372e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj      if (i->Ain.ACAS.sz != 8)
3373e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         rex = clearWBit(rex);
3374e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj      *p++ = rex;
3375e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj      *p++ = 0x0F;
3376e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj      *p++ = 0xC7;
3377a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj      p = doAMode_M_enc(p, 1, i->Ain.DACAS.addr);
3378e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj      goto done;
3379e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj
338025a858136df4cbea0055c20aa7035d25fd40ee89sewardj   case Ain_A87Free:
338125a858136df4cbea0055c20aa7035d25fd40ee89sewardj      vassert(i->Ain.A87Free.nregs > 0 && i->Ain.A87Free.nregs <= 7);
338225a858136df4cbea0055c20aa7035d25fd40ee89sewardj      for (j = 0; j < i->Ain.A87Free.nregs; j++) {
338325a858136df4cbea0055c20aa7035d25fd40ee89sewardj         p = do_ffree_st(p, 7-j);
338425a858136df4cbea0055c20aa7035d25fd40ee89sewardj      }
338525a858136df4cbea0055c20aa7035d25fd40ee89sewardj      goto done;
338625a858136df4cbea0055c20aa7035d25fd40ee89sewardj
338725a858136df4cbea0055c20aa7035d25fd40ee89sewardj   case Ain_A87PushPop:
3388d15b597a8a006b3fe136cbf6cdf5b46ed532a4d8sewardj      vassert(i->Ain.A87PushPop.szB == 8 || i->Ain.A87PushPop.szB == 4);
338925a858136df4cbea0055c20aa7035d25fd40ee89sewardj      if (i->Ain.A87PushPop.isPush) {
3390d15b597a8a006b3fe136cbf6cdf5b46ed532a4d8sewardj         /* Load from memory into %st(0): flds/fldl amode */
339125a858136df4cbea0055c20aa7035d25fd40ee89sewardj         *p++ = clearWBit(
3392a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj                   rexAMode_M_enc(0, i->Ain.A87PushPop.addr) );
3393d15b597a8a006b3fe136cbf6cdf5b46ed532a4d8sewardj         *p++ = i->Ain.A87PushPop.szB == 4 ? 0xD9 : 0xDD;
3394a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj	 p = doAMode_M_enc(p, 0/*subopcode*/, i->Ain.A87PushPop.addr);
339525a858136df4cbea0055c20aa7035d25fd40ee89sewardj      } else {
3396d15b597a8a006b3fe136cbf6cdf5b46ed532a4d8sewardj         /* Dump %st(0) to memory: fstps/fstpl amode */
339725a858136df4cbea0055c20aa7035d25fd40ee89sewardj         *p++ = clearWBit(
3398a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj                   rexAMode_M_enc(3, i->Ain.A87PushPop.addr) );
3399d15b597a8a006b3fe136cbf6cdf5b46ed532a4d8sewardj         *p++ = i->Ain.A87PushPop.szB == 4 ? 0xD9 : 0xDD;
3400a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj         p = doAMode_M_enc(p, 3/*subopcode*/, i->Ain.A87PushPop.addr);
340125a858136df4cbea0055c20aa7035d25fd40ee89sewardj         goto done;
340225a858136df4cbea0055c20aa7035d25fd40ee89sewardj      }
340325a858136df4cbea0055c20aa7035d25fd40ee89sewardj      goto done;
340425a858136df4cbea0055c20aa7035d25fd40ee89sewardj
340525a858136df4cbea0055c20aa7035d25fd40ee89sewardj   case Ain_A87FpOp:
340625a858136df4cbea0055c20aa7035d25fd40ee89sewardj      switch (i->Ain.A87FpOp.op) {
34075e205372f0023f11eb756ee38de40a065b0681c1sewardj         case Afp_SQRT:   *p++ = 0xD9; *p++ = 0xFA; break;
34085e205372f0023f11eb756ee38de40a065b0681c1sewardj         case Afp_SIN:    *p++ = 0xD9; *p++ = 0xFE; break;
34095e205372f0023f11eb756ee38de40a065b0681c1sewardj         case Afp_COS:    *p++ = 0xD9; *p++ = 0xFF; break;
34105e205372f0023f11eb756ee38de40a065b0681c1sewardj         case Afp_ROUND:  *p++ = 0xD9; *p++ = 0xFC; break;
34115e205372f0023f11eb756ee38de40a065b0681c1sewardj         case Afp_2XM1:   *p++ = 0xD9; *p++ = 0xF0; break;
34125e205372f0023f11eb756ee38de40a065b0681c1sewardj         case Afp_SCALE:  *p++ = 0xD9; *p++ = 0xFD; break;
34135e205372f0023f11eb756ee38de40a065b0681c1sewardj         case Afp_ATAN:   *p++ = 0xD9; *p++ = 0xF3; break;
34145e205372f0023f11eb756ee38de40a065b0681c1sewardj         case Afp_YL2X:   *p++ = 0xD9; *p++ = 0xF1; break;
34155e205372f0023f11eb756ee38de40a065b0681c1sewardj         case Afp_YL2XP1: *p++ = 0xD9; *p++ = 0xF9; break;
3416f4c803b0947e7534809589cba8007851d78c7a2esewardj         case Afp_PREM:   *p++ = 0xD9; *p++ = 0xF8; break;
34174970e4e219cb92ef15de742d102c537ea33d5430sewardj         case Afp_PREM1:  *p++ = 0xD9; *p++ = 0xF5; break;
3418e9c51c9287ce703a0740e610d5bdd2ea8429fb6dsewardj         case Afp_TAN:
3419e9c51c9287ce703a0740e610d5bdd2ea8429fb6dsewardj            /* fptan pushes 1.0 on the FP stack, except when the
3420e9c51c9287ce703a0740e610d5bdd2ea8429fb6dsewardj               argument is out of range.  Hence we have to do the
3421e9c51c9287ce703a0740e610d5bdd2ea8429fb6dsewardj               instruction, then inspect C2 to see if there is an out
3422e9c51c9287ce703a0740e610d5bdd2ea8429fb6dsewardj               of range condition.  If there is, we skip the fincstp
3423e9c51c9287ce703a0740e610d5bdd2ea8429fb6dsewardj               that is used by the in-range case to get rid of this
3424e9c51c9287ce703a0740e610d5bdd2ea8429fb6dsewardj               extra 1.0 value. */
3425e9c51c9287ce703a0740e610d5bdd2ea8429fb6dsewardj            *p++ = 0xD9; *p++ = 0xF2; // fptan
3426e9c51c9287ce703a0740e610d5bdd2ea8429fb6dsewardj            *p++ = 0x50;              // pushq %rax
3427e9c51c9287ce703a0740e610d5bdd2ea8429fb6dsewardj            *p++ = 0xDF; *p++ = 0xE0; // fnstsw %ax
3428e9c51c9287ce703a0740e610d5bdd2ea8429fb6dsewardj            *p++ = 0x66; *p++ = 0xA9;
3429e9c51c9287ce703a0740e610d5bdd2ea8429fb6dsewardj            *p++ = 0x00; *p++ = 0x04; // testw $0x400,%ax
3430e9c51c9287ce703a0740e610d5bdd2ea8429fb6dsewardj            *p++ = 0x75; *p++ = 0x02; // jnz after_fincstp
3431e9c51c9287ce703a0740e610d5bdd2ea8429fb6dsewardj            *p++ = 0xD9; *p++ = 0xF7; // fincstp
3432e9c51c9287ce703a0740e610d5bdd2ea8429fb6dsewardj            *p++ = 0x58;              // after_fincstp: popq %rax
3433e9c51c9287ce703a0740e610d5bdd2ea8429fb6dsewardj            break;
3434e9c51c9287ce703a0740e610d5bdd2ea8429fb6dsewardj         default:
3435e9c51c9287ce703a0740e610d5bdd2ea8429fb6dsewardj            goto bad;
343625a858136df4cbea0055c20aa7035d25fd40ee89sewardj      }
343725a858136df4cbea0055c20aa7035d25fd40ee89sewardj      goto done;
343825a858136df4cbea0055c20aa7035d25fd40ee89sewardj
343925a858136df4cbea0055c20aa7035d25fd40ee89sewardj   case Ain_A87LdCW:
344025a858136df4cbea0055c20aa7035d25fd40ee89sewardj      *p++ = clearWBit(
3441a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj                rexAMode_M_enc(5, i->Ain.A87LdCW.addr) );
344225a858136df4cbea0055c20aa7035d25fd40ee89sewardj      *p++ = 0xD9;
3443a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj      p = doAMode_M_enc(p, 5/*subopcode*/, i->Ain.A87LdCW.addr);
344425a858136df4cbea0055c20aa7035d25fd40ee89sewardj      goto done;
344525a858136df4cbea0055c20aa7035d25fd40ee89sewardj
3446f4c803b0947e7534809589cba8007851d78c7a2esewardj   case Ain_A87StSW:
3447f4c803b0947e7534809589cba8007851d78c7a2esewardj      *p++ = clearWBit(
3448a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj                rexAMode_M_enc(7, i->Ain.A87StSW.addr) );
3449f4c803b0947e7534809589cba8007851d78c7a2esewardj      *p++ = 0xDD;
3450a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj      p = doAMode_M_enc(p, 7/*subopcode*/, i->Ain.A87StSW.addr);
3451f4c803b0947e7534809589cba8007851d78c7a2esewardj      goto done;
3452f4c803b0947e7534809589cba8007851d78c7a2esewardj
34531b8d58eb046ad31fbb058d65855b604886d3d177sewardj   case Ain_Store:
34541b8d58eb046ad31fbb058d65855b604886d3d177sewardj      if (i->Ain.Store.sz == 2) {
34551b8d58eb046ad31fbb058d65855b604886d3d177sewardj         /* This just goes to show the crazyness of the instruction
34561b8d58eb046ad31fbb058d65855b604886d3d177sewardj            set encoding.  We have to insert two prefix bytes, but be
34571b8d58eb046ad31fbb058d65855b604886d3d177sewardj            careful to avoid a conflict in what the size should be, by
34581b8d58eb046ad31fbb058d65855b604886d3d177sewardj            ensuring that REX.W = 0. */
34591b8d58eb046ad31fbb058d65855b604886d3d177sewardj         *p++ = 0x66; /* override to 16-bits */
34601b8d58eb046ad31fbb058d65855b604886d3d177sewardj	 *p++ = clearWBit( rexAMode_M( i->Ain.Store.src, i->Ain.Store.dst) );
34611b8d58eb046ad31fbb058d65855b604886d3d177sewardj         *p++ = 0x89;
34621b8d58eb046ad31fbb058d65855b604886d3d177sewardj         p = doAMode_M(p, i->Ain.Store.src, i->Ain.Store.dst);
34631b8d58eb046ad31fbb058d65855b604886d3d177sewardj         goto done;
34641b8d58eb046ad31fbb058d65855b604886d3d177sewardj      }
34651b8d58eb046ad31fbb058d65855b604886d3d177sewardj      if (i->Ain.Store.sz == 4) {
34661b8d58eb046ad31fbb058d65855b604886d3d177sewardj	 *p++ = clearWBit( rexAMode_M( i->Ain.Store.src, i->Ain.Store.dst) );
34671b8d58eb046ad31fbb058d65855b604886d3d177sewardj         *p++ = 0x89;
34681b8d58eb046ad31fbb058d65855b604886d3d177sewardj         p = doAMode_M(p, i->Ain.Store.src, i->Ain.Store.dst);
34691b8d58eb046ad31fbb058d65855b604886d3d177sewardj         goto done;
34701b8d58eb046ad31fbb058d65855b604886d3d177sewardj      }
3471e1698951a3a6431c2421f1eb42f3d246226917basewardj      if (i->Ain.Store.sz == 1) {
3472a890367704a21066b655cf8a1136e1846b326f52sewardj         /* This is one place where it would be wrong to skip emitting
3473a890367704a21066b655cf8a1136e1846b326f52sewardj            a rex byte of 0x40, since the mere presence of rex changes
3474a890367704a21066b655cf8a1136e1846b326f52sewardj            the meaning of the byte register access.  Be careful. */
3475e1698951a3a6431c2421f1eb42f3d246226917basewardj	 *p++ = clearWBit( rexAMode_M( i->Ain.Store.src, i->Ain.Store.dst) );
3476e1698951a3a6431c2421f1eb42f3d246226917basewardj         *p++ = 0x88;
3477e1698951a3a6431c2421f1eb42f3d246226917basewardj         p = doAMode_M(p, i->Ain.Store.src, i->Ain.Store.dst);
3478e1698951a3a6431c2421f1eb42f3d246226917basewardj         goto done;
3479e1698951a3a6431c2421f1eb42f3d246226917basewardj      }
34801b8d58eb046ad31fbb058d65855b604886d3d177sewardj      break;
34811b8d58eb046ad31fbb058d65855b604886d3d177sewardj
34821a01e65f9993d97095c2af463e98674a091834casewardj   case Ain_LdMXCSR:
3483a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj      *p++ = clearWBit(rexAMode_M_enc(0, i->Ain.LdMXCSR.addr));
34841a01e65f9993d97095c2af463e98674a091834casewardj      *p++ = 0x0F;
34851a01e65f9993d97095c2af463e98674a091834casewardj      *p++ = 0xAE;
3486a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj      p = doAMode_M_enc(p, 2/*subopcode*/, i->Ain.LdMXCSR.addr);
34871a01e65f9993d97095c2af463e98674a091834casewardj      goto done;
34881a01e65f9993d97095c2af463e98674a091834casewardj
34891830386e7b10430c0c3630123a82d8bcf0a071e7sewardj   case Ain_SseUComIS:
34901830386e7b10430c0c3630123a82d8bcf0a071e7sewardj      /* ucomi[sd] %srcL, %srcR ;  pushfq ; popq %dst */
34911830386e7b10430c0c3630123a82d8bcf0a071e7sewardj      /* ucomi[sd] %srcL, %srcR */
34921830386e7b10430c0c3630123a82d8bcf0a071e7sewardj      if (i->Ain.SseUComIS.sz == 8) {
34931830386e7b10430c0c3630123a82d8bcf0a071e7sewardj         *p++ = 0x66;
34941830386e7b10430c0c3630123a82d8bcf0a071e7sewardj      } else {
34951830386e7b10430c0c3630123a82d8bcf0a071e7sewardj         goto bad;
34961830386e7b10430c0c3630123a82d8bcf0a071e7sewardj         vassert(i->Ain.SseUComIS.sz == 4);
34971830386e7b10430c0c3630123a82d8bcf0a071e7sewardj      }
34981830386e7b10430c0c3630123a82d8bcf0a071e7sewardj      *p++ = clearWBit (
3499a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj             rexAMode_R_enc_enc( vregEnc3210(i->Ain.SseUComIS.srcL),
3500a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj                                 vregEnc3210(i->Ain.SseUComIS.srcR) ));
35011830386e7b10430c0c3630123a82d8bcf0a071e7sewardj      *p++ = 0x0F;
35021830386e7b10430c0c3630123a82d8bcf0a071e7sewardj      *p++ = 0x2E;
3503a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj      p = doAMode_R_enc_enc(p, vregEnc3210(i->Ain.SseUComIS.srcL),
3504a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj                               vregEnc3210(i->Ain.SseUComIS.srcR) );
35051830386e7b10430c0c3630123a82d8bcf0a071e7sewardj      /* pushfq */
35061830386e7b10430c0c3630123a82d8bcf0a071e7sewardj      *p++ = 0x9C;
35071830386e7b10430c0c3630123a82d8bcf0a071e7sewardj      /* popq %dst */
3508a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj      *p++ = toUChar(0x40 + (1 & iregEnc3(i->Ain.SseUComIS.dst)));
3509a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj      *p++ = toUChar(0x58 + iregEnc210(i->Ain.SseUComIS.dst));
35101830386e7b10430c0c3630123a82d8bcf0a071e7sewardj      goto done;
35111830386e7b10430c0c3630123a82d8bcf0a071e7sewardj
35121a01e65f9993d97095c2af463e98674a091834casewardj   case Ain_SseSI2SF:
35131a01e65f9993d97095c2af463e98674a091834casewardj      /* cvssi2s[sd] %src, %dst */
3514a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj      rex = rexAMode_R_enc_reg( vregEnc3210(i->Ain.SseSI2SF.dst),
3515a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj                                i->Ain.SseSI2SF.src );
351603ccf858efa285d793061359c04fdd0055cd9d31sewardj      *p++ = toUChar(i->Ain.SseSI2SF.szD==4 ? 0xF3 : 0xF2);
351703ccf858efa285d793061359c04fdd0055cd9d31sewardj      *p++ = toUChar(i->Ain.SseSI2SF.szS==4 ? clearWBit(rex) : rex);
35181a01e65f9993d97095c2af463e98674a091834casewardj      *p++ = 0x0F;
35191a01e65f9993d97095c2af463e98674a091834casewardj      *p++ = 0x2A;
3520a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj      p = doAMode_R_enc_reg( p, vregEnc3210(i->Ain.SseSI2SF.dst),
3521a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj                                i->Ain.SseSI2SF.src );
35221a01e65f9993d97095c2af463e98674a091834casewardj      goto done;
35231a01e65f9993d97095c2af463e98674a091834casewardj
35241a01e65f9993d97095c2af463e98674a091834casewardj   case Ain_SseSF2SI:
35251a01e65f9993d97095c2af463e98674a091834casewardj      /* cvss[sd]2si %src, %dst */
3526a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj      rex = rexAMode_R_reg_enc( i->Ain.SseSF2SI.dst,
3527a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj                                vregEnc3210(i->Ain.SseSF2SI.src) );
352803ccf858efa285d793061359c04fdd0055cd9d31sewardj      *p++ = toUChar(i->Ain.SseSF2SI.szS==4 ? 0xF3 : 0xF2);
352903ccf858efa285d793061359c04fdd0055cd9d31sewardj      *p++ = toUChar(i->Ain.SseSF2SI.szD==4 ? clearWBit(rex) : rex);
35301a01e65f9993d97095c2af463e98674a091834casewardj      *p++ = 0x0F;
35311a01e65f9993d97095c2af463e98674a091834casewardj      *p++ = 0x2D;
3532a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj      p = doAMode_R_reg_enc( p, i->Ain.SseSF2SI.dst,
3533a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj                                vregEnc3210(i->Ain.SseSF2SI.src) );
35341a01e65f9993d97095c2af463e98674a091834casewardj      goto done;
35351a01e65f9993d97095c2af463e98674a091834casewardj
35368d965316c72c2392f670dcdfa127547ec77c7e56sewardj   case Ain_SseSDSS:
35378d965316c72c2392f670dcdfa127547ec77c7e56sewardj      /* cvtsd2ss/cvtss2sd %src, %dst */
353803ccf858efa285d793061359c04fdd0055cd9d31sewardj      *p++ = toUChar(i->Ain.SseSDSS.from64 ? 0xF2 : 0xF3);
35398d965316c72c2392f670dcdfa127547ec77c7e56sewardj      *p++ = clearWBit(
3540a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj              rexAMode_R_enc_enc( vregEnc3210(i->Ain.SseSDSS.dst),
3541a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj                                  vregEnc3210(i->Ain.SseSDSS.src) ));
35428d965316c72c2392f670dcdfa127547ec77c7e56sewardj      *p++ = 0x0F;
35438d965316c72c2392f670dcdfa127547ec77c7e56sewardj      *p++ = 0x5A;
3544a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj      p = doAMode_R_enc_enc( p, vregEnc3210(i->Ain.SseSDSS.dst),
3545a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj                                vregEnc3210(i->Ain.SseSDSS.src) );
35468d965316c72c2392f670dcdfa127547ec77c7e56sewardj      goto done;
35478d965316c72c2392f670dcdfa127547ec77c7e56sewardj
35481001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj   case Ain_SseLdSt:
35491830386e7b10430c0c3630123a82d8bcf0a071e7sewardj      if (i->Ain.SseLdSt.sz == 8) {
35501830386e7b10430c0c3630123a82d8bcf0a071e7sewardj         *p++ = 0xF2;
35511830386e7b10430c0c3630123a82d8bcf0a071e7sewardj      } else
35521830386e7b10430c0c3630123a82d8bcf0a071e7sewardj      if (i->Ain.SseLdSt.sz == 4) {
35531830386e7b10430c0c3630123a82d8bcf0a071e7sewardj         *p++ = 0xF3;
35541830386e7b10430c0c3630123a82d8bcf0a071e7sewardj      } else
35551830386e7b10430c0c3630123a82d8bcf0a071e7sewardj      if (i->Ain.SseLdSt.sz != 16) {
35561830386e7b10430c0c3630123a82d8bcf0a071e7sewardj         vassert(0);
35571830386e7b10430c0c3630123a82d8bcf0a071e7sewardj      }
35581001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj      *p++ = clearWBit(
3559a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj             rexAMode_M_enc(vregEnc3210(i->Ain.SseLdSt.reg),
3560a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj                            i->Ain.SseLdSt.addr));
35611001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj      *p++ = 0x0F;
356203ccf858efa285d793061359c04fdd0055cd9d31sewardj      *p++ = toUChar(i->Ain.SseLdSt.isLoad ? 0x10 : 0x11);
3563a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj      p = doAMode_M_enc(p, vregEnc3210(i->Ain.SseLdSt.reg),
3564a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj                           i->Ain.SseLdSt.addr);
35651001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj      goto done;
35661001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj
356770dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   case Ain_SseCStore: {
356870dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj      vassert(i->Ain.SseCStore.cond != Acc_ALWAYS);
356970dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj
357070dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj      /* Use ptmp for backpatching conditional jumps. */
357170dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj      ptmp = NULL;
357270dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj
357370dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj      /* jmp fwds if !condition */
357470dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj      *p++ = toUChar(0x70 + (0xF & (i->Ain.SseCStore.cond ^ 1)));
357570dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj      ptmp = p; /* fill in this bit later */
357670dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj      *p++ = 0; /* # of bytes to jump over; don't know how many yet. */
357770dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj
357870dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj      /* Now the store. */
357970dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj      *p++ = clearWBit(
358070dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj             rexAMode_M_enc(vregEnc3210(i->Ain.SseCStore.src),
358170dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj                            i->Ain.SseCStore.addr));
358270dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj      *p++ = 0x0F;
358370dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj      *p++ = toUChar(0x11);
358470dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj      p = doAMode_M_enc(p, vregEnc3210(i->Ain.SseCStore.src),
358570dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj                           i->Ain.SseCStore.addr);
358670dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj
358770dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj      /* Fix up the conditional branch */
358870dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj      Int delta = p - ptmp;
358970dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj      vassert(delta > 0 && delta < 40);
359070dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj      *ptmp = toUChar(delta-1);
359170dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj      goto done;
359270dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   }
359370dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj
359470dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   case Ain_SseCLoad: {
359570dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj      vassert(i->Ain.SseCLoad.cond != Acc_ALWAYS);
359670dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj
359770dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj      /* Use ptmp for backpatching conditional jumps. */
359870dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj      ptmp = NULL;
359970dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj
360070dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj      /* jmp fwds if !condition */
360170dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj      *p++ = toUChar(0x70 + (0xF & (i->Ain.SseCLoad.cond ^ 1)));
360270dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj      ptmp = p; /* fill in this bit later */
360370dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj      *p++ = 0; /* # of bytes to jump over; don't know how many yet. */
360470dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj
360570dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj      /* Now the load. */
360670dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj      *p++ = clearWBit(
360770dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj             rexAMode_M_enc(vregEnc3210(i->Ain.SseCLoad.dst),
360870dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj                            i->Ain.SseCLoad.addr));
360970dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj      *p++ = 0x0F;
361070dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj      *p++ = toUChar(0x10);
361170dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj      p = doAMode_M_enc(p, vregEnc3210(i->Ain.SseCLoad.dst),
361270dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj                           i->Ain.SseCLoad.addr);
361370dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj
361470dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj      /* Fix up the conditional branch */
361570dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj      Int delta = p - ptmp;
361670dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj      vassert(delta > 0 && delta < 40);
361770dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj      *ptmp = toUChar(delta-1);
361870dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj      goto done;
361970dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   }
362070dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj
36211001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj   case Ain_SseLdzLO:
36221001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj      vassert(i->Ain.SseLdzLO.sz == 4 || i->Ain.SseLdzLO.sz == 8);
36231001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj      /* movs[sd] amode, %xmm-dst */
362403ccf858efa285d793061359c04fdd0055cd9d31sewardj      *p++ = toUChar(i->Ain.SseLdzLO.sz==4 ? 0xF3 : 0xF2);
36251001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj      *p++ = clearWBit(
3626a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj             rexAMode_M_enc(vregEnc3210(i->Ain.SseLdzLO.reg),
3627a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj                            i->Ain.SseLdzLO.addr));
36281001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj      *p++ = 0x0F;
36291001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj      *p++ = 0x10;
3630a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj      p = doAMode_M_enc(p, vregEnc3210(i->Ain.SseLdzLO.reg),
3631a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj                           i->Ain.SseLdzLO.addr);
36321001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj      goto done;
36331001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj
36348d965316c72c2392f670dcdfa127547ec77c7e56sewardj   case Ain_Sse32Fx4:
36358d965316c72c2392f670dcdfa127547ec77c7e56sewardj      xtra = 0;
36368d965316c72c2392f670dcdfa127547ec77c7e56sewardj      *p++ = clearWBit(
3637a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj             rexAMode_R_enc_enc( vregEnc3210(i->Ain.Sse32Fx4.dst),
3638a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj                                 vregEnc3210(i->Ain.Sse32Fx4.src) ));
36398d965316c72c2392f670dcdfa127547ec77c7e56sewardj      *p++ = 0x0F;
36408d965316c72c2392f670dcdfa127547ec77c7e56sewardj      switch (i->Ain.Sse32Fx4.op) {
3641432f8b63f5f06d0b86daf3b360a722aaf2f3344fsewardj         case Asse_ADDF:   *p++ = 0x58; break;
3642432f8b63f5f06d0b86daf3b360a722aaf2f3344fsewardj         case Asse_DIVF:   *p++ = 0x5E; break;
3643432f8b63f5f06d0b86daf3b360a722aaf2f3344fsewardj         case Asse_MAXF:   *p++ = 0x5F; break;
3644432f8b63f5f06d0b86daf3b360a722aaf2f3344fsewardj         case Asse_MINF:   *p++ = 0x5D; break;
3645432f8b63f5f06d0b86daf3b360a722aaf2f3344fsewardj         case Asse_MULF:   *p++ = 0x59; break;
3646a7ba8c47f30998a518cda7e38b4082a9e5c6892esewardj         case Asse_RCPF:   *p++ = 0x53; break;
3647a7ba8c47f30998a518cda7e38b4082a9e5c6892esewardj         case Asse_RSQRTF: *p++ = 0x52; break;
3648a7ba8c47f30998a518cda7e38b4082a9e5c6892esewardj         case Asse_SQRTF:  *p++ = 0x51; break;
3649432f8b63f5f06d0b86daf3b360a722aaf2f3344fsewardj         case Asse_SUBF:   *p++ = 0x5C; break;
36508d965316c72c2392f670dcdfa127547ec77c7e56sewardj         case Asse_CMPEQF: *p++ = 0xC2; xtra = 0x100; break;
3651432f8b63f5f06d0b86daf3b360a722aaf2f3344fsewardj         case Asse_CMPLTF: *p++ = 0xC2; xtra = 0x101; break;
3652432f8b63f5f06d0b86daf3b360a722aaf2f3344fsewardj         case Asse_CMPLEF: *p++ = 0xC2; xtra = 0x102; break;
3653b928263af5cbbf25ae6da4be3ab5b7f3ee3bb79bsewardj         case Asse_CMPUNF: *p++ = 0xC2; xtra = 0x103; break;
36548d965316c72c2392f670dcdfa127547ec77c7e56sewardj         default: goto bad;
36558d965316c72c2392f670dcdfa127547ec77c7e56sewardj      }
3656a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj      p = doAMode_R_enc_enc(p, vregEnc3210(i->Ain.Sse32Fx4.dst),
3657a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj                               vregEnc3210(i->Ain.Sse32Fx4.src) );
36588d965316c72c2392f670dcdfa127547ec77c7e56sewardj      if (xtra & 0x100)
365903ccf858efa285d793061359c04fdd0055cd9d31sewardj         *p++ = toUChar(xtra & 0xFF);
36608d965316c72c2392f670dcdfa127547ec77c7e56sewardj      goto done;
36618d965316c72c2392f670dcdfa127547ec77c7e56sewardj
36624c328cf28ebd12977fbf837c44a614c5aac660f3sewardj   case Ain_Sse64Fx2:
36634c328cf28ebd12977fbf837c44a614c5aac660f3sewardj      xtra = 0;
36644c328cf28ebd12977fbf837c44a614c5aac660f3sewardj      *p++ = 0x66;
36654c328cf28ebd12977fbf837c44a614c5aac660f3sewardj      *p++ = clearWBit(
3666a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj             rexAMode_R_enc_enc( vregEnc3210(i->Ain.Sse64Fx2.dst),
3667a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj                                 vregEnc3210(i->Ain.Sse64Fx2.src) ));
36684c328cf28ebd12977fbf837c44a614c5aac660f3sewardj      *p++ = 0x0F;
36694c328cf28ebd12977fbf837c44a614c5aac660f3sewardj      switch (i->Ain.Sse64Fx2.op) {
36704c328cf28ebd12977fbf837c44a614c5aac660f3sewardj         case Asse_ADDF:   *p++ = 0x58; break;
36715992bd07a3237cae1c22f6c93c43730e6447350csewardj         case Asse_DIVF:   *p++ = 0x5E; break;
36725992bd07a3237cae1c22f6c93c43730e6447350csewardj         case Asse_MAXF:   *p++ = 0x5F; break;
36735992bd07a3237cae1c22f6c93c43730e6447350csewardj         case Asse_MINF:   *p++ = 0x5D; break;
36744c328cf28ebd12977fbf837c44a614c5aac660f3sewardj         case Asse_MULF:   *p++ = 0x59; break;
3675976285992e00e9b3656f08d0e08e62e65ec6a29fsewardj         case Asse_SQRTF:  *p++ = 0x51; break;
36764c328cf28ebd12977fbf837c44a614c5aac660f3sewardj         case Asse_SUBF:   *p++ = 0x5C; break;
3677976285992e00e9b3656f08d0e08e62e65ec6a29fsewardj         case Asse_CMPEQF: *p++ = 0xC2; xtra = 0x100; break;
3678976285992e00e9b3656f08d0e08e62e65ec6a29fsewardj         case Asse_CMPLTF: *p++ = 0xC2; xtra = 0x101; break;
3679976285992e00e9b3656f08d0e08e62e65ec6a29fsewardj         case Asse_CMPLEF: *p++ = 0xC2; xtra = 0x102; break;
3680b928263af5cbbf25ae6da4be3ab5b7f3ee3bb79bsewardj         case Asse_CMPUNF: *p++ = 0xC2; xtra = 0x103; break;
36814c328cf28ebd12977fbf837c44a614c5aac660f3sewardj         default: goto bad;
36824c328cf28ebd12977fbf837c44a614c5aac660f3sewardj      }
3683a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj      p = doAMode_R_enc_enc(p, vregEnc3210(i->Ain.Sse64Fx2.dst),
3684a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj                               vregEnc3210(i->Ain.Sse64Fx2.src) );
36854c328cf28ebd12977fbf837c44a614c5aac660f3sewardj      if (xtra & 0x100)
3686ca673ab9a76f5697f7ce086ff564bf26f4fa28besewardj         *p++ = toUChar(xtra & 0xFF);
36874c328cf28ebd12977fbf837c44a614c5aac660f3sewardj      goto done;
36888d965316c72c2392f670dcdfa127547ec77c7e56sewardj
36898d965316c72c2392f670dcdfa127547ec77c7e56sewardj   case Ain_Sse32FLo:
36908d965316c72c2392f670dcdfa127547ec77c7e56sewardj      xtra = 0;
36918d965316c72c2392f670dcdfa127547ec77c7e56sewardj      *p++ = 0xF3;
36928d965316c72c2392f670dcdfa127547ec77c7e56sewardj      *p++ = clearWBit(
3693a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj             rexAMode_R_enc_enc( vregEnc3210(i->Ain.Sse32FLo.dst),
3694a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj                                 vregEnc3210(i->Ain.Sse32FLo.src) ));
36958d965316c72c2392f670dcdfa127547ec77c7e56sewardj      *p++ = 0x0F;
36968d965316c72c2392f670dcdfa127547ec77c7e56sewardj      switch (i->Ain.Sse32FLo.op) {
36978d965316c72c2392f670dcdfa127547ec77c7e56sewardj         case Asse_ADDF:   *p++ = 0x58; break;
3698c49ce233511cddeaf1fed6931e9a5d8a0cbcf279sewardj         case Asse_DIVF:   *p++ = 0x5E; break;
369937d52574c28a12a0e1930f1a703db573a4aa3e44sewardj         case Asse_MAXF:   *p++ = 0x5F; break;
370037d52574c28a12a0e1930f1a703db573a4aa3e44sewardj         case Asse_MINF:   *p++ = 0x5D; break;
37018d965316c72c2392f670dcdfa127547ec77c7e56sewardj         case Asse_MULF:   *p++ = 0x59; break;
3702a7ba8c47f30998a518cda7e38b4082a9e5c6892esewardj         case Asse_RCPF:   *p++ = 0x53; break;
3703a7ba8c47f30998a518cda7e38b4082a9e5c6892esewardj         case Asse_RSQRTF: *p++ = 0x52; break;
3704a7ba8c47f30998a518cda7e38b4082a9e5c6892esewardj         case Asse_SQRTF:  *p++ = 0x51; break;
37058d965316c72c2392f670dcdfa127547ec77c7e56sewardj         case Asse_SUBF:   *p++ = 0x5C; break;
3706432f8b63f5f06d0b86daf3b360a722aaf2f3344fsewardj         case Asse_CMPEQF: *p++ = 0xC2; xtra = 0x100; break;
37073aba9eb1a223f2cbb21500ec8854f745c9eb11absewardj         case Asse_CMPLTF: *p++ = 0xC2; xtra = 0x101; break;
37084c328cf28ebd12977fbf837c44a614c5aac660f3sewardj         case Asse_CMPLEF: *p++ = 0xC2; xtra = 0x102; break;
3709b928263af5cbbf25ae6da4be3ab5b7f3ee3bb79bsewardj         case Asse_CMPUNF: *p++ = 0xC2; xtra = 0x103; break;
37108d965316c72c2392f670dcdfa127547ec77c7e56sewardj         default: goto bad;
37118d965316c72c2392f670dcdfa127547ec77c7e56sewardj      }
3712a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj      p = doAMode_R_enc_enc(p, vregEnc3210(i->Ain.Sse32FLo.dst),
3713a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj                               vregEnc3210(i->Ain.Sse32FLo.src) );
37148d965316c72c2392f670dcdfa127547ec77c7e56sewardj      if (xtra & 0x100)
371503ccf858efa285d793061359c04fdd0055cd9d31sewardj         *p++ = toUChar(xtra & 0xFF);
37168d965316c72c2392f670dcdfa127547ec77c7e56sewardj      goto done;
37171001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj
37181001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj   case Ain_Sse64FLo:
37191001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj      xtra = 0;
37201001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj      *p++ = 0xF2;
37211001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj      *p++ = clearWBit(
3722a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj             rexAMode_R_enc_enc( vregEnc3210(i->Ain.Sse64FLo.dst),
3723a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj                                 vregEnc3210(i->Ain.Sse64FLo.src) ));
37241001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj      *p++ = 0x0F;
37251001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj      switch (i->Ain.Sse64FLo.op) {
37261001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj         case Asse_ADDF:   *p++ = 0x58; break;
37271001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj         case Asse_DIVF:   *p++ = 0x5E; break;
37281a01e65f9993d97095c2af463e98674a091834casewardj         case Asse_MAXF:   *p++ = 0x5F; break;
3729c49ce233511cddeaf1fed6931e9a5d8a0cbcf279sewardj         case Asse_MINF:   *p++ = 0x5D; break;
37301001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj         case Asse_MULF:   *p++ = 0x59; break;
37311830386e7b10430c0c3630123a82d8bcf0a071e7sewardj         case Asse_SQRTF:  *p++ = 0x51; break;
37321001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj         case Asse_SUBF:   *p++ = 0x5C; break;
3733137015d7434c75ff70954d347bd61432efba3532sewardj         case Asse_CMPEQF: *p++ = 0xC2; xtra = 0x100; break;
37348d965316c72c2392f670dcdfa127547ec77c7e56sewardj         case Asse_CMPLTF: *p++ = 0xC2; xtra = 0x101; break;
3735137015d7434c75ff70954d347bd61432efba3532sewardj         case Asse_CMPLEF: *p++ = 0xC2; xtra = 0x102; break;
3736b928263af5cbbf25ae6da4be3ab5b7f3ee3bb79bsewardj         case Asse_CMPUNF: *p++ = 0xC2; xtra = 0x103; break;
37371001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj         default: goto bad;
37381001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj      }
3739a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj      p = doAMode_R_enc_enc(p, vregEnc3210(i->Ain.Sse64FLo.dst),
3740a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj                               vregEnc3210(i->Ain.Sse64FLo.src) );
37411001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj      if (xtra & 0x100)
374203ccf858efa285d793061359c04fdd0055cd9d31sewardj         *p++ = toUChar(xtra & 0xFF);
37431001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj      goto done;
37441001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj
37451001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj   case Ain_SseReRg:
37461001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj#     define XX(_n) *p++ = (_n)
37471001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj
37481001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj      rex = clearWBit(
3749a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj            rexAMode_R_enc_enc( vregEnc3210(i->Ain.SseReRg.dst),
3750a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj                                vregEnc3210(i->Ain.SseReRg.src) ));
37511001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj
37521001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj      switch (i->Ain.SseReRg.op) {
37531001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj         case Asse_MOV:     /*movups*/ XX(rex); XX(0x0F); XX(0x10); break;
37548d965316c72c2392f670dcdfa127547ec77c7e56sewardj         case Asse_OR:                 XX(rex); XX(0x0F); XX(0x56); break;
37559da16977406ea569541209807c7dcf8cb936a8dcsewardj         case Asse_XOR:                XX(rex); XX(0x0F); XX(0x57); break;
37561a01e65f9993d97095c2af463e98674a091834casewardj         case Asse_AND:                XX(rex); XX(0x0F); XX(0x54); break;
3757137015d7434c75ff70954d347bd61432efba3532sewardj         case Asse_ANDN:               XX(rex); XX(0x0F); XX(0x55); break;
3758976285992e00e9b3656f08d0e08e62e65ec6a29fsewardj         case Asse_PACKSSD:  XX(0x66); XX(rex); XX(0x0F); XX(0x6B); break;
3759976285992e00e9b3656f08d0e08e62e65ec6a29fsewardj         case Asse_PACKSSW:  XX(0x66); XX(rex); XX(0x0F); XX(0x63); break;
3760976285992e00e9b3656f08d0e08e62e65ec6a29fsewardj         case Asse_PACKUSW:  XX(0x66); XX(rex); XX(0x0F); XX(0x67); break;
3761976285992e00e9b3656f08d0e08e62e65ec6a29fsewardj         case Asse_ADD8:     XX(0x66); XX(rex); XX(0x0F); XX(0xFC); break;
37625992bd07a3237cae1c22f6c93c43730e6447350csewardj         case Asse_ADD16:    XX(0x66); XX(rex); XX(0x0F); XX(0xFD); break;
3763976285992e00e9b3656f08d0e08e62e65ec6a29fsewardj         case Asse_ADD32:    XX(0x66); XX(rex); XX(0x0F); XX(0xFE); break;
376409717341a0c364814e35bf405e61399d0e45fa7csewardj         case Asse_ADD64:    XX(0x66); XX(rex); XX(0x0F); XX(0xD4); break;
37655992bd07a3237cae1c22f6c93c43730e6447350csewardj         case Asse_QADD8S:   XX(0x66); XX(rex); XX(0x0F); XX(0xEC); break;
37665992bd07a3237cae1c22f6c93c43730e6447350csewardj         case Asse_QADD16S:  XX(0x66); XX(rex); XX(0x0F); XX(0xED); break;
37675992bd07a3237cae1c22f6c93c43730e6447350csewardj         case Asse_QADD8U:   XX(0x66); XX(rex); XX(0x0F); XX(0xDC); break;
37685992bd07a3237cae1c22f6c93c43730e6447350csewardj         case Asse_QADD16U:  XX(0x66); XX(rex); XX(0x0F); XX(0xDD); break;
37695992bd07a3237cae1c22f6c93c43730e6447350csewardj         case Asse_AVG8U:    XX(0x66); XX(rex); XX(0x0F); XX(0xE0); break;
37705992bd07a3237cae1c22f6c93c43730e6447350csewardj         case Asse_AVG16U:   XX(0x66); XX(rex); XX(0x0F); XX(0xE3); break;
37715992bd07a3237cae1c22f6c93c43730e6447350csewardj         case Asse_CMPEQ8:   XX(0x66); XX(rex); XX(0x0F); XX(0x74); break;
37725992bd07a3237cae1c22f6c93c43730e6447350csewardj         case Asse_CMPEQ16:  XX(0x66); XX(rex); XX(0x0F); XX(0x75); break;
377309717341a0c364814e35bf405e61399d0e45fa7csewardj         case Asse_CMPEQ32:  XX(0x66); XX(rex); XX(0x0F); XX(0x76); break;
37745992bd07a3237cae1c22f6c93c43730e6447350csewardj         case Asse_CMPGT8S:  XX(0x66); XX(rex); XX(0x0F); XX(0x64); break;
37755992bd07a3237cae1c22f6c93c43730e6447350csewardj         case Asse_CMPGT16S: XX(0x66); XX(rex); XX(0x0F); XX(0x65); break;
37765992bd07a3237cae1c22f6c93c43730e6447350csewardj         case Asse_CMPGT32S: XX(0x66); XX(rex); XX(0x0F); XX(0x66); break;
3777adffcef004712e8afc6a7d87b30ef90e4685df40sewardj         case Asse_MAX16S:   XX(0x66); XX(rex); XX(0x0F); XX(0xEE); break;
3778adffcef004712e8afc6a7d87b30ef90e4685df40sewardj         case Asse_MAX8U:    XX(0x66); XX(rex); XX(0x0F); XX(0xDE); break;
3779adffcef004712e8afc6a7d87b30ef90e4685df40sewardj         case Asse_MIN16S:   XX(0x66); XX(rex); XX(0x0F); XX(0xEA); break;
3780adffcef004712e8afc6a7d87b30ef90e4685df40sewardj         case Asse_MIN8U:    XX(0x66); XX(rex); XX(0x0F); XX(0xDA); break;
3781adffcef004712e8afc6a7d87b30ef90e4685df40sewardj         case Asse_MULHI16U: XX(0x66); XX(rex); XX(0x0F); XX(0xE4); break;
3782adffcef004712e8afc6a7d87b30ef90e4685df40sewardj         case Asse_MULHI16S: XX(0x66); XX(rex); XX(0x0F); XX(0xE5); break;
3783adffcef004712e8afc6a7d87b30ef90e4685df40sewardj         case Asse_MUL16:    XX(0x66); XX(rex); XX(0x0F); XX(0xD5); break;
3784adffcef004712e8afc6a7d87b30ef90e4685df40sewardj         case Asse_SHL16:    XX(0x66); XX(rex); XX(0x0F); XX(0xF1); break;
3785adffcef004712e8afc6a7d87b30ef90e4685df40sewardj         case Asse_SHL32:    XX(0x66); XX(rex); XX(0x0F); XX(0xF2); break;
3786adffcef004712e8afc6a7d87b30ef90e4685df40sewardj         case Asse_SHL64:    XX(0x66); XX(rex); XX(0x0F); XX(0xF3); break;
3787adffcef004712e8afc6a7d87b30ef90e4685df40sewardj         case Asse_SAR16:    XX(0x66); XX(rex); XX(0x0F); XX(0xE1); break;
3788adffcef004712e8afc6a7d87b30ef90e4685df40sewardj         case Asse_SAR32:    XX(0x66); XX(rex); XX(0x0F); XX(0xE2); break;
3789adffcef004712e8afc6a7d87b30ef90e4685df40sewardj         case Asse_SHR16:    XX(0x66); XX(rex); XX(0x0F); XX(0xD1); break;
3790adffcef004712e8afc6a7d87b30ef90e4685df40sewardj         case Asse_SHR32:    XX(0x66); XX(rex); XX(0x0F); XX(0xD2); break;
379109717341a0c364814e35bf405e61399d0e45fa7csewardj         case Asse_SHR64:    XX(0x66); XX(rex); XX(0x0F); XX(0xD3); break;
3792976285992e00e9b3656f08d0e08e62e65ec6a29fsewardj         case Asse_SUB8:     XX(0x66); XX(rex); XX(0x0F); XX(0xF8); break;
3793976285992e00e9b3656f08d0e08e62e65ec6a29fsewardj         case Asse_SUB16:    XX(0x66); XX(rex); XX(0x0F); XX(0xF9); break;
3794976285992e00e9b3656f08d0e08e62e65ec6a29fsewardj         case Asse_SUB32:    XX(0x66); XX(rex); XX(0x0F); XX(0xFA); break;
379509717341a0c364814e35bf405e61399d0e45fa7csewardj         case Asse_SUB64:    XX(0x66); XX(rex); XX(0x0F); XX(0xFB); break;
3796976285992e00e9b3656f08d0e08e62e65ec6a29fsewardj         case Asse_QSUB8S:   XX(0x66); XX(rex); XX(0x0F); XX(0xE8); break;
3797976285992e00e9b3656f08d0e08e62e65ec6a29fsewardj         case Asse_QSUB16S:  XX(0x66); XX(rex); XX(0x0F); XX(0xE9); break;
3798976285992e00e9b3656f08d0e08e62e65ec6a29fsewardj         case Asse_QSUB8U:   XX(0x66); XX(rex); XX(0x0F); XX(0xD8); break;
3799976285992e00e9b3656f08d0e08e62e65ec6a29fsewardj         case Asse_QSUB16U:  XX(0x66); XX(rex); XX(0x0F); XX(0xD9); break;
3800976285992e00e9b3656f08d0e08e62e65ec6a29fsewardj         case Asse_UNPCKHB:  XX(0x66); XX(rex); XX(0x0F); XX(0x68); break;
3801976285992e00e9b3656f08d0e08e62e65ec6a29fsewardj         case Asse_UNPCKHW:  XX(0x66); XX(rex); XX(0x0F); XX(0x69); break;
3802976285992e00e9b3656f08d0e08e62e65ec6a29fsewardj         case Asse_UNPCKHD:  XX(0x66); XX(rex); XX(0x0F); XX(0x6A); break;
3803976285992e00e9b3656f08d0e08e62e65ec6a29fsewardj         case Asse_UNPCKHQ:  XX(0x66); XX(rex); XX(0x0F); XX(0x6D); break;
3804976285992e00e9b3656f08d0e08e62e65ec6a29fsewardj         case Asse_UNPCKLB:  XX(0x66); XX(rex); XX(0x0F); XX(0x60); break;
3805976285992e00e9b3656f08d0e08e62e65ec6a29fsewardj         case Asse_UNPCKLW:  XX(0x66); XX(rex); XX(0x0F); XX(0x61); break;
3806976285992e00e9b3656f08d0e08e62e65ec6a29fsewardj         case Asse_UNPCKLD:  XX(0x66); XX(rex); XX(0x0F); XX(0x62); break;
3807976285992e00e9b3656f08d0e08e62e65ec6a29fsewardj         case Asse_UNPCKLQ:  XX(0x66); XX(rex); XX(0x0F); XX(0x6C); break;
38081001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj         default: goto bad;
38091001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj      }
3810a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj      p = doAMode_R_enc_enc(p, vregEnc3210(i->Ain.SseReRg.dst),
3811a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj                               vregEnc3210(i->Ain.SseReRg.src) );
38121001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj#     undef XX
38131001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj      goto done;
38141001dc4dbf8f684e2afeaaea169e37a7ddeb5934sewardj
38158d965316c72c2392f670dcdfa127547ec77c7e56sewardj   case Ain_SseCMov:
38168d965316c72c2392f670dcdfa127547ec77c7e56sewardj      /* jmp fwds if !condition */
381703ccf858efa285d793061359c04fdd0055cd9d31sewardj      *p++ = toUChar(0x70 + (i->Ain.SseCMov.cond ^ 1));
38188d965316c72c2392f670dcdfa127547ec77c7e56sewardj      *p++ = 0; /* # of bytes in the next bit, which we don't know yet */
38198d965316c72c2392f670dcdfa127547ec77c7e56sewardj      ptmp = p;
38208d965316c72c2392f670dcdfa127547ec77c7e56sewardj
38218d965316c72c2392f670dcdfa127547ec77c7e56sewardj      /* movaps %src, %dst */
38228d965316c72c2392f670dcdfa127547ec77c7e56sewardj      *p++ = clearWBit(
3823a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj             rexAMode_R_enc_enc( vregEnc3210(i->Ain.SseCMov.dst),
3824a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj                                 vregEnc3210(i->Ain.SseCMov.src) ));
38258d965316c72c2392f670dcdfa127547ec77c7e56sewardj      *p++ = 0x0F;
38268d965316c72c2392f670dcdfa127547ec77c7e56sewardj      *p++ = 0x28;
3827a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj      p = doAMode_R_enc_enc(p, vregEnc3210(i->Ain.SseCMov.dst),
3828a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj                               vregEnc3210(i->Ain.SseCMov.src) );
38298d965316c72c2392f670dcdfa127547ec77c7e56sewardj
38308d965316c72c2392f670dcdfa127547ec77c7e56sewardj      /* Fill in the jump offset. */
383103ccf858efa285d793061359c04fdd0055cd9d31sewardj      *(ptmp-1) = toUChar(p - ptmp);
38328d965316c72c2392f670dcdfa127547ec77c7e56sewardj      goto done;
38338d965316c72c2392f670dcdfa127547ec77c7e56sewardj
383409717341a0c364814e35bf405e61399d0e45fa7csewardj   case Ain_SseShuf:
383509717341a0c364814e35bf405e61399d0e45fa7csewardj      *p++ = 0x66;
383609717341a0c364814e35bf405e61399d0e45fa7csewardj      *p++ = clearWBit(
3837a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj             rexAMode_R_enc_enc( vregEnc3210(i->Ain.SseShuf.dst),
3838a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj                                 vregEnc3210(i->Ain.SseShuf.src) ));
383909717341a0c364814e35bf405e61399d0e45fa7csewardj      *p++ = 0x0F;
384009717341a0c364814e35bf405e61399d0e45fa7csewardj      *p++ = 0x70;
3841a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj      p = doAMode_R_enc_enc(p, vregEnc3210(i->Ain.SseShuf.dst),
3842a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj                               vregEnc3210(i->Ain.SseShuf.src) );
384309717341a0c364814e35bf405e61399d0e45fa7csewardj      *p++ = (UChar)(i->Ain.SseShuf.order);
384409717341a0c364814e35bf405e61399d0e45fa7csewardj      goto done;
384509717341a0c364814e35bf405e61399d0e45fa7csewardj
38463616a2ec4af166a3917810e4fdbe910ed80bd278sewardj   //uu case Ain_AvxLdSt: {
38473616a2ec4af166a3917810e4fdbe910ed80bd278sewardj   //uu    UInt vex = vexAMode_M( dvreg2ireg(i->Ain.AvxLdSt.reg),
38483616a2ec4af166a3917810e4fdbe910ed80bd278sewardj   //uu                           i->Ain.AvxLdSt.addr );
38493616a2ec4af166a3917810e4fdbe910ed80bd278sewardj   //uu    p = emitVexPrefix(p, vex);
38503616a2ec4af166a3917810e4fdbe910ed80bd278sewardj   //uu    *p++ = toUChar(i->Ain.AvxLdSt.isLoad ? 0x10 : 0x11);
38513616a2ec4af166a3917810e4fdbe910ed80bd278sewardj   //uu    p = doAMode_M(p, dvreg2ireg(i->Ain.AvxLdSt.reg), i->Ain.AvxLdSt.addr);
38523616a2ec4af166a3917810e4fdbe910ed80bd278sewardj   //uu      goto done;
38533616a2ec4af166a3917810e4fdbe910ed80bd278sewardj   //uu }
3854c4530ae9079b0c3f8d4e8df35073613d718cadecsewardj
3855c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   case Ain_EvCheck: {
3856c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      /* We generate:
3857c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj            (3 bytes)  decl 8(%rbp)    8 == offsetof(host_EvC_COUNTER)
3858c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj            (2 bytes)  jns  nofail     expected taken
3859c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj            (3 bytes)  jmp* 0(%rbp)    0 == offsetof(host_EvC_FAILADDR)
3860c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj            nofail:
3861c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      */
3862c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      /* This is heavily asserted re instruction lengths.  It needs to
3863c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         be.  If we get given unexpected forms of .amCounter or
3864c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         .amFailAddr -- basically, anything that's not of the form
3865c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         uimm7(%rbp) -- they are likely to fail. */
3866c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      /* Note also that after the decl we must be very careful not to
3867c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         read the carry flag, else we get a partial flags stall.
3868c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         js/jns avoids that, though. */
3869c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      UChar* p0 = p;
3870c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      /* ---  decl 8(%rbp) --- */
3871c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      /* Need to compute the REX byte for the decl in order to prove
3872c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         that we don't need it, since this is a 32-bit inc and all
3873a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj         registers involved in the amode are < r8.  "1" because
3874c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         there's no register in this encoding; instead the register
3875c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         field is used as a sub opcode.  The encoding for "decl r/m32"
3876a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj         is FF /1, hence the "1". */
3877a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj      rex = clearWBit(rexAMode_M_enc(1, i->Ain.EvCheck.amCounter));
3878c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      if (rex != 0x40) goto bad; /* We don't expect to need the REX byte. */
3879c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      *p++ = 0xFF;
3880a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj      p = doAMode_M_enc(p, 1, i->Ain.EvCheck.amCounter);
3881c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      vassert(p - p0 == 3);
3882c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      /* --- jns nofail --- */
3883c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      *p++ = 0x79;
3884c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      *p++ = 0x03; /* need to check this 0x03 after the next insn */
3885c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      vassert(p - p0 == 5);
3886c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      /* --- jmp* 0(%rbp) --- */
3887c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      /* Once again, verify we don't need REX.  The encoding is FF /4.
3888c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         We don't need REX.W since by default FF /4 in 64-bit mode
3889c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         implies a 64 bit load. */
3890a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj      rex = clearWBit(rexAMode_M_enc(4, i->Ain.EvCheck.amFailAddr));
3891c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      if (rex != 0x40) goto bad;
3892c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      *p++ = 0xFF;
3893a5b502299bfc9d97f4c2c9f61cdc1a0a65e1da61sewardj      p = doAMode_M_enc(p, 4, i->Ain.EvCheck.amFailAddr);
3894c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      vassert(p - p0 == 8); /* also ensures that 0x03 offset above is ok */
3895c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      /* And crosscheck .. */
38967ce2cc883c5b36586babec833838951ecf9f2a76florian      vassert(evCheckSzB_AMD64() == 8);
3897c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      goto done;
3898c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   }
3899c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj
3900c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   case Ain_ProfInc: {
3901c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      /* We generate   movabsq $0, %r11
3902c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj                       incq (%r11)
3903c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         in the expectation that a later call to LibVEX_patchProfCtr
3904c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         will be used to fill in the immediate field once the right
3905c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         value is known.
3906c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         49 BB 00 00 00 00 00 00 00 00
3907c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         49 FF 03
3908c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      */
3909c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      *p++ = 0x49; *p++ = 0xBB;
3910c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      *p++ = 0x00; *p++ = 0x00; *p++ = 0x00; *p++ = 0x00;
3911c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      *p++ = 0x00; *p++ = 0x00; *p++ = 0x00; *p++ = 0x00;
3912c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      *p++ = 0x49; *p++ = 0xFF; *p++ = 0x03;
3913c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      /* Tell the caller .. */
3914c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      vassert(!(*is_profInc));
3915c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      *is_profInc = True;
3916c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      goto done;
3917c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   }
3918c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj
3919c33671d7b0e21edb1d1015e4cbccbc6ca139e6d8sewardj   default:
3920c33671d7b0e21edb1d1015e4cbccbc6ca139e6d8sewardj      goto bad;
3921c33671d7b0e21edb1d1015e4cbccbc6ca139e6d8sewardj   }
3922c33671d7b0e21edb1d1015e4cbccbc6ca139e6d8sewardj
3923c33671d7b0e21edb1d1015e4cbccbc6ca139e6d8sewardj  bad:
392492b643609c5fa432b11fc726c2706ae3f3296eb4cerion   ppAMD64Instr(i, mode64);
3925c33671d7b0e21edb1d1015e4cbccbc6ca139e6d8sewardj   vpanic("emit_AMD64Instr");
3926c33671d7b0e21edb1d1015e4cbccbc6ca139e6d8sewardj   /*NOTREACHED*/
3927c33671d7b0e21edb1d1015e4cbccbc6ca139e6d8sewardj
3928813ce9e974ad75c2f69f570e6dbc087b5b3b1706sewardj  done:
392970dbeb0232ebafbf0977549b1c72ff53c8ef9863sewardj   vassert(p - &buf[0] <= 64);
3930c33671d7b0e21edb1d1015e4cbccbc6ca139e6d8sewardj   return p - &buf[0];
3931c33671d7b0e21edb1d1015e4cbccbc6ca139e6d8sewardj}
3932a3e9830f0ab418d41a9c8484216b563d438cf2dcsewardj
3933c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj
3934c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj/* How big is an event check?  See case for Ain_EvCheck in
3935c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   emit_AMD64Instr just above.  That crosschecks what this returns, so
3936c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   we can tell if we're inconsistent. */
39377ce2cc883c5b36586babec833838951ecf9f2a76florianInt evCheckSzB_AMD64 (void)
3938c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj{
3939c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   return 8;
3940c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj}
3941c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj
3942c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj
3943c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj/* NB: what goes on here has to be very closely coordinated with the
3944c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   emitInstr case for XDirect, above. */
39459b76916dcc1628e133d57db001563429c6e3a590sewardjVexInvalRange chainXDirect_AMD64 ( VexEndness endness_host,
39469b76916dcc1628e133d57db001563429c6e3a590sewardj                                   void* place_to_chain,
39477d6f81de12e6d8deb3e119ab318f361d97a10a65florian                                   const void* disp_cp_chain_me_EXPECTED,
39487d6f81de12e6d8deb3e119ab318f361d97a10a65florian                                   const void* place_to_jump_to )
3949c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj{
39509b76916dcc1628e133d57db001563429c6e3a590sewardj   vassert(endness_host == VexEndnessLE);
39519b76916dcc1628e133d57db001563429c6e3a590sewardj
3952c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   /* What we're expecting to see is:
3953c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj        movabsq $disp_cp_chain_me_EXPECTED, %r11
3954c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj        call *%r11
3955c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      viz
3956c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj        49 BB <8 bytes value == disp_cp_chain_me_EXPECTED>
3957c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj        41 FF D3
3958c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   */
3959c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   UChar* p = (UChar*)place_to_chain;
3960c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   vassert(p[0] == 0x49);
3961c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   vassert(p[1] == 0xBB);
396248729060949c3c8e2cfdd9aae20df000dac279c0sewardj   vassert(read_misaligned_ULong_LE(&p[2]) == (Addr)disp_cp_chain_me_EXPECTED);
3963c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   vassert(p[10] == 0x41);
3964c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   vassert(p[11] == 0xFF);
3965c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   vassert(p[12] == 0xD3);
3966c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   /* And what we want to change it to is either:
3967c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj        (general case):
3968c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj          movabsq $place_to_jump_to, %r11
3969c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj          jmpq *%r11
3970c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj        viz
3971c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj          49 BB <8 bytes value == place_to_jump_to>
3972c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj          41 FF E3
3973c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj        So it's the same length (convenient, huh) and we don't
3974c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj        need to change all the bits.
3975c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      ---OR---
3976c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj        in the case where the displacement falls within 32 bits
3977c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj          jmpq disp32   where disp32 is relative to the next insn
3978c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj          ud2; ud2; ud2; ud2
3979c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj        viz
3980c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj          E9 <4 bytes == disp32>
3981c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj          0F 0B 0F 0B 0F 0B 0F 0B
3982c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj
3983c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      In both cases the replacement has the same length as the original.
3984c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      To remain sane & verifiable,
3985c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      (1) limit the displacement for the short form to
3986c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj          (say) +/- one billion, so as to avoid wraparound
3987c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj          off-by-ones
3988c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      (2) even if the short form is applicable, once every (say)
3989c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj          1024 times use the long form anyway, so as to maintain
3990c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj          verifiability
3991c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   */
3992c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   /* This is the delta we need to put into a JMP d32 insn.  It's
3993c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      relative to the start of the next insn, hence the -5.  */
39947d6f81de12e6d8deb3e119ab318f361d97a10a65florian   Long delta   = (Long)((const UChar *)place_to_jump_to - (const UChar*)p) - 5;
3995c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   Bool shortOK = delta >= -1000*1000*1000 && delta < 1000*1000*1000;
3996c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj
3997c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   static UInt shortCTR = 0; /* DO NOT MAKE NON-STATIC */
3998c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   if (shortOK) {
3999c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      shortCTR++; // thread safety bleh
4000c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      if (0 == (shortCTR & 0x3FF)) {
4001c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         shortOK = False;
4002c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         if (0)
4003c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj            vex_printf("QQQ chainXDirect_AMD64: shortCTR = %u, "
4004c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj                       "using long jmp\n", shortCTR);
4005c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      }
4006c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   }
4007c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj
4008c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   /* And make the modifications. */
4009c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   if (shortOK) {
4010c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      p[0]  = 0xE9;
401148729060949c3c8e2cfdd9aae20df000dac279c0sewardj      write_misaligned_UInt_LE(&p[1], (UInt)(Int)delta);
4012c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      p[5]  = 0x0F; p[6]  = 0x0B;
4013c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      p[7]  = 0x0F; p[8]  = 0x0B;
4014c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      p[9]  = 0x0F; p[10] = 0x0B;
4015c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      p[11] = 0x0F; p[12] = 0x0B;
4016c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      /* sanity check on the delta -- top 32 are all 0 or all 1 */
4017c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      delta >>= 32;
4018c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      vassert(delta == 0LL || delta == -1LL);
4019c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   } else {
4020c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      /* Minimal modifications from the starting sequence. */
402148729060949c3c8e2cfdd9aae20df000dac279c0sewardj      write_misaligned_ULong_LE(&p[2], (ULong)(Addr)place_to_jump_to);
4022c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      p[12] = 0xE3;
4023c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   }
40245ea257be80e49474f724426939d4c398c8bfab1bflorian   VexInvalRange vir = { (HWord)place_to_chain, 13 };
4025c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   return vir;
4026c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj}
4027c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj
4028c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj
4029c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj/* NB: what goes on here has to be very closely coordinated with the
4030c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   emitInstr case for XDirect, above. */
40319b76916dcc1628e133d57db001563429c6e3a590sewardjVexInvalRange unchainXDirect_AMD64 ( VexEndness endness_host,
40329b76916dcc1628e133d57db001563429c6e3a590sewardj                                     void* place_to_unchain,
40337d6f81de12e6d8deb3e119ab318f361d97a10a65florian                                     const void* place_to_jump_to_EXPECTED,
40347d6f81de12e6d8deb3e119ab318f361d97a10a65florian                                     const void* disp_cp_chain_me )
4035c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj{
40369b76916dcc1628e133d57db001563429c6e3a590sewardj   vassert(endness_host == VexEndnessLE);
40379b76916dcc1628e133d57db001563429c6e3a590sewardj
4038c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   /* What we're expecting to see is either:
4039c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj        (general case)
4040c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj          movabsq $place_to_jump_to_EXPECTED, %r11
4041c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj          jmpq *%r11
4042c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj        viz
4043c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj          49 BB <8 bytes value == place_to_jump_to_EXPECTED>
4044c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj          41 FF E3
4045c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      ---OR---
4046c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj        in the case where the displacement falls within 32 bits
4047c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj          jmpq d32
4048c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj          ud2; ud2; ud2; ud2
4049c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj        viz
4050c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj          E9 <4 bytes == disp32>
4051c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj          0F 0B 0F 0B 0F 0B 0F 0B
4052c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   */
4053c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   UChar* p     = (UChar*)place_to_unchain;
4054c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   Bool   valid = False;
4055c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   if (p[0] == 0x49 && p[1] == 0xBB
405648729060949c3c8e2cfdd9aae20df000dac279c0sewardj       && read_misaligned_ULong_LE(&p[2])
405748729060949c3c8e2cfdd9aae20df000dac279c0sewardj          == (ULong)(Addr)place_to_jump_to_EXPECTED
4058c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj       && p[10] == 0x41 && p[11] == 0xFF && p[12] == 0xE3) {
4059c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      /* it's the long form */
4060c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      valid = True;
4061c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   }
4062c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   else
4063c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   if (p[0] == 0xE9
4064c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj       && p[5]  == 0x0F && p[6]  == 0x0B
4065c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj       && p[7]  == 0x0F && p[8]  == 0x0B
4066c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj       && p[9]  == 0x0F && p[10] == 0x0B
4067c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj       && p[11] == 0x0F && p[12] == 0x0B) {
4068c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      /* It's the short form.  Check the offset is right. */
406948729060949c3c8e2cfdd9aae20df000dac279c0sewardj      Int  s32 = (Int)read_misaligned_UInt_LE(&p[1]);
4070c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      Long s64 = (Long)s32;
40717d6f81de12e6d8deb3e119ab318f361d97a10a65florian      if ((UChar*)p + 5 + s64 == place_to_jump_to_EXPECTED) {
4072c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         valid = True;
4073c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj         if (0)
4074c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj            vex_printf("QQQ unchainXDirect_AMD64: found short form\n");
4075c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      }
4076c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   }
4077c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   vassert(valid);
4078c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   /* And what we want to change it to is:
4079c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj        movabsq $disp_cp_chain_me, %r11
4080c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj        call *%r11
4081c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      viz
4082c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj        49 BB <8 bytes value == disp_cp_chain_me>
4083c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj        41 FF D3
4084c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj      So it's the same length (convenient, huh).
4085c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   */
4086c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   p[0] = 0x49;
4087c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   p[1] = 0xBB;
408848729060949c3c8e2cfdd9aae20df000dac279c0sewardj   write_misaligned_ULong_LE(&p[2], (ULong)(Addr)disp_cp_chain_me);
4089c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   p[10] = 0x41;
4090c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   p[11] = 0xFF;
4091c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   p[12] = 0xD3;
40925ea257be80e49474f724426939d4c398c8bfab1bflorian   VexInvalRange vir = { (HWord)place_to_unchain, 13 };
4093c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   return vir;
4094c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj}
4095c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj
4096c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj
4097c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj/* Patch the counter address into a profile inc point, as previously
4098c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   created by the Ain_ProfInc case for emit_AMD64Instr. */
40999b76916dcc1628e133d57db001563429c6e3a590sewardjVexInvalRange patchProfInc_AMD64 ( VexEndness endness_host,
41009b76916dcc1628e133d57db001563429c6e3a590sewardj                                   void*  place_to_patch,
41017d6f81de12e6d8deb3e119ab318f361d97a10a65florian                                   const ULong* location_of_counter )
4102c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj{
41039b76916dcc1628e133d57db001563429c6e3a590sewardj   vassert(endness_host == VexEndnessLE);
4104c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   vassert(sizeof(ULong*) == 8);
4105c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   UChar* p = (UChar*)place_to_patch;
4106c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   vassert(p[0] == 0x49);
4107c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   vassert(p[1] == 0xBB);
4108c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   vassert(p[2] == 0x00);
4109c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   vassert(p[3] == 0x00);
4110c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   vassert(p[4] == 0x00);
4111c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   vassert(p[5] == 0x00);
4112c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   vassert(p[6] == 0x00);
4113c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   vassert(p[7] == 0x00);
4114c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   vassert(p[8] == 0x00);
4115c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   vassert(p[9] == 0x00);
4116c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   vassert(p[10] == 0x49);
4117c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   vassert(p[11] == 0xFF);
4118c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   vassert(p[12] == 0x03);
411993a09742b0de3d61718882c2d999f64be402564dflorian   ULong imm64 = (ULong)(Addr)location_of_counter;
4120c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   p[2] = imm64 & 0xFF; imm64 >>= 8;
4121c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   p[3] = imm64 & 0xFF; imm64 >>= 8;
4122c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   p[4] = imm64 & 0xFF; imm64 >>= 8;
4123c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   p[5] = imm64 & 0xFF; imm64 >>= 8;
4124c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   p[6] = imm64 & 0xFF; imm64 >>= 8;
4125c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   p[7] = imm64 & 0xFF; imm64 >>= 8;
4126c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   p[8] = imm64 & 0xFF; imm64 >>= 8;
4127c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   p[9] = imm64 & 0xFF; imm64 >>= 8;
41285ea257be80e49474f724426939d4c398c8bfab1bflorian   VexInvalRange vir = { (HWord)place_to_patch, 13 };
4129c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   return vir;
4130c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj}
4131c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj
4132c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj
4133a3e9830f0ab418d41a9c8484216b563d438cf2dcsewardj/*---------------------------------------------------------------*/
4134cef7d3e3df4796e35b4521158d9dc058f034aa87sewardj/*--- end                                   host_amd64_defs.c ---*/
4135a3e9830f0ab418d41a9c8484216b563d438cf2dcsewardj/*---------------------------------------------------------------*/
4136