blob: f662ec4a5907b30cdb40fc53b13e4977a706f775 [file] [log] [blame]
sewardja3e98302005-02-01 15:55:05 +00001
2/*---------------------------------------------------------------*/
3/*--- ---*/
4/*--- This file (host-amd64/hdefs.c) is ---*/
5/*--- Copyright (c) 2005 OpenWorks LLP. All rights reserved. ---*/
6/*--- ---*/
7/*---------------------------------------------------------------*/
8
9/*
10 This file is part of LibVEX, a library for dynamic binary
11 instrumentation and translation.
12
13 Copyright (C) 2004-2005 OpenWorks, LLP.
14
15 This program is free software; you can redistribute it and/or modify
16 it under the terms of the GNU General Public License as published by
17 the Free Software Foundation; Version 2 dated June 1991 of the
18 license.
19
20 This program is distributed in the hope that it will be useful,
21 but WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or liability
23 for damages. See the GNU General Public License for more details.
24
25 Neither the names of the U.S. Department of Energy nor the
26 University of California nor the names of its contributors may be
27 used to endorse or promote products derived from this software
28 without prior written permission.
29
30 You should have received a copy of the GNU General Public License
31 along with this program; if not, write to the Free Software
32 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
33 USA.
34*/
35
36#include "libvex_basictypes.h"
37#include "libvex.h"
38#include "libvex_trc_values.h"
39
sewardjc33671d2005-02-01 20:30:00 +000040#include "main/vex_util.h"
41#include "host-generic/h_generic_regs.h"
42#include "host-amd64/hdefs.h"
43
44
45/* --------- Registers. --------- */
46
47void ppHRegAMD64 ( HReg reg )
sewardj614b3fb2005-02-02 02:16:03 +000048{
49 Int r;
50 static HChar* ireg64_names[16]
51 = { "%rax", "%rcx", "%rdx", "%rbx", "%rsp", "%rbp", "%rsi", "%rdi",
52 "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15" };
53 /* Be generic for all virtual regs. */
54 if (hregIsVirtual(reg)) {
55 ppHReg(reg);
56 return;
57 }
58 /* But specific for real regs. */
59 switch (hregClass(reg)) {
60 case HRcInt64:
61 r = hregNumber(reg);
62 vassert(r >= 0 && r < 16);
63 vex_printf("%s", ireg64_names[r]);
64 return;
65 case HRcFlt64:
66 r = hregNumber(reg);
67 vassert(r >= 0 && r < 6);
68 vex_printf("%%fake%d", r);
69 return;
70 case HRcVec128:
71 r = hregNumber(reg);
72 vassert(r >= 0 && r < 16);
73 vex_printf("%%xmm%d", r);
74 return;
75 default:
76 vpanic("ppHRegAMD64");
77 }
sewardjc33671d2005-02-01 20:30:00 +000078}
79
sewardj549e0642005-02-05 12:00:14 +000080static void ppHRegAMD64_lo32 ( HReg reg )
81{
82 Int r;
83 static HChar* ireg32_names[16]
84 = { "%eax", "%ecx", "%edx", "%ebx", "%esp", "%ebp", "%esi", "%edi",
85 "%r8d", "%r9d", "%r10d", "%r11d", "%r12d", "%r13d", "%r14d", "%r15d" };
86 /* Be generic for all virtual regs. */
87 if (hregIsVirtual(reg)) {
88 ppHReg(reg);
89 vex_printf("d");
90 return;
91 }
92 /* But specific for real regs. */
93 switch (hregClass(reg)) {
94 case HRcInt64:
95 r = hregNumber(reg);
96 vassert(r >= 0 && r < 16);
97 vex_printf("%s", ireg32_names[r]);
98 return;
99 default:
100 vpanic("ppHRegAMD64_lo32: invalid regclass");
101 }
102}
103
sewardjf67eadf2005-02-03 03:53:52 +0000104HReg hregAMD64_RAX ( void ) { return mkHReg( 0, HRcInt64, False); }
105HReg hregAMD64_RCX ( void ) { return mkHReg( 1, HRcInt64, False); }
106HReg hregAMD64_RDX ( void ) { return mkHReg( 2, HRcInt64, False); }
107HReg hregAMD64_RBX ( void ) { return mkHReg( 3, HRcInt64, False); }
108HReg hregAMD64_RSP ( void ) { return mkHReg( 4, HRcInt64, False); }
109HReg hregAMD64_RBP ( void ) { return mkHReg( 5, HRcInt64, False); }
110HReg hregAMD64_RSI ( void ) { return mkHReg( 6, HRcInt64, False); }
111HReg hregAMD64_RDI ( void ) { return mkHReg( 7, HRcInt64, False); }
112HReg hregAMD64_R8 ( void ) { return mkHReg( 8, HRcInt64, False); }
113HReg hregAMD64_R9 ( void ) { return mkHReg( 9, HRcInt64, False); }
114HReg hregAMD64_R10 ( void ) { return mkHReg(10, HRcInt64, False); }
115HReg hregAMD64_R11 ( void ) { return mkHReg(11, HRcInt64, False); }
116HReg hregAMD64_R12 ( void ) { return mkHReg(12, HRcInt64, False); }
117HReg hregAMD64_R13 ( void ) { return mkHReg(13, HRcInt64, False); }
118HReg hregAMD64_R14 ( void ) { return mkHReg(14, HRcInt64, False); }
119HReg hregAMD64_R15 ( void ) { return mkHReg(15, HRcInt64, False); }
120
sewardj614b3fb2005-02-02 02:16:03 +0000121//.. HReg hregAMD64_FAKE0 ( void ) { return mkHReg(0, HRcFlt64, False); }
122//.. HReg hregAMD64_FAKE1 ( void ) { return mkHReg(1, HRcFlt64, False); }
123//.. HReg hregAMD64_FAKE2 ( void ) { return mkHReg(2, HRcFlt64, False); }
124//.. HReg hregAMD64_FAKE3 ( void ) { return mkHReg(3, HRcFlt64, False); }
125//.. HReg hregAMD64_FAKE4 ( void ) { return mkHReg(4, HRcFlt64, False); }
126//.. HReg hregAMD64_FAKE5 ( void ) { return mkHReg(5, HRcFlt64, False); }
sewardja3e98302005-02-01 15:55:05 +0000127//..
sewardjf67eadf2005-02-03 03:53:52 +0000128HReg hregAMD64_XMM0 ( void ) { return mkHReg( 0, HRcVec128, False); }
129HReg hregAMD64_XMM1 ( void ) { return mkHReg( 1, HRcVec128, False); }
130HReg hregAMD64_XMM2 ( void ) { return mkHReg( 2, HRcVec128, False); }
131HReg hregAMD64_XMM3 ( void ) { return mkHReg( 3, HRcVec128, False); }
132HReg hregAMD64_XMM4 ( void ) { return mkHReg( 4, HRcVec128, False); }
133HReg hregAMD64_XMM5 ( void ) { return mkHReg( 5, HRcVec128, False); }
134HReg hregAMD64_XMM6 ( void ) { return mkHReg( 6, HRcVec128, False); }
135HReg hregAMD64_XMM7 ( void ) { return mkHReg( 7, HRcVec128, False); }
136HReg hregAMD64_XMM8 ( void ) { return mkHReg( 8, HRcVec128, False); }
137HReg hregAMD64_XMM9 ( void ) { return mkHReg( 9, HRcVec128, False); }
138HReg hregAMD64_XMM10 ( void ) { return mkHReg(10, HRcVec128, False); }
139HReg hregAMD64_XMM11 ( void ) { return mkHReg(11, HRcVec128, False); }
140HReg hregAMD64_XMM12 ( void ) { return mkHReg(12, HRcVec128, False); }
141HReg hregAMD64_XMM13 ( void ) { return mkHReg(13, HRcVec128, False); }
142HReg hregAMD64_XMM14 ( void ) { return mkHReg(14, HRcVec128, False); }
143HReg hregAMD64_XMM15 ( void ) { return mkHReg(15, HRcVec128, False); }
sewardjc33671d2005-02-01 20:30:00 +0000144
145
146void getAllocableRegs_AMD64 ( Int* nregs, HReg** arr )
sewardjf67eadf2005-02-03 03:53:52 +0000147{
148 *nregs = 30;
149 *arr = LibVEX_Alloc(*nregs * sizeof(HReg));
sewardj1b8d58e2005-02-05 14:34:18 +0000150#if 1
sewardjf67eadf2005-02-03 03:53:52 +0000151 (*arr)[ 0] = hregAMD64_RAX();
152 (*arr)[ 1] = hregAMD64_RBX();
153 (*arr)[ 2] = hregAMD64_RCX();
154 (*arr)[ 3] = hregAMD64_RDX();
155 (*arr)[ 4] = hregAMD64_RSI();
156 (*arr)[ 5] = hregAMD64_RDI();
157 (*arr)[ 6] = hregAMD64_R8();
158 (*arr)[ 7] = hregAMD64_R9();
159 (*arr)[ 8] = hregAMD64_R10();
160 (*arr)[ 9] = hregAMD64_R11();
161 (*arr)[10] = hregAMD64_R12();
162 (*arr)[11] = hregAMD64_R13();
163 (*arr)[12] = hregAMD64_R14();
164 (*arr)[13] = hregAMD64_R15();
sewardj1b8d58e2005-02-05 14:34:18 +0000165#else
166 /* For testing the assembler */
167 (*arr)[ 0] = hregAMD64_RDI();
168 (*arr)[ 1] = hregAMD64_R8();
169 (*arr)[ 2] = hregAMD64_RSI();
170 (*arr)[ 3] = hregAMD64_R9();
171 (*arr)[ 4] = hregAMD64_RAX();
172 (*arr)[ 5] = hregAMD64_RBX();
173 (*arr)[ 6] = hregAMD64_RCX();
174 (*arr)[ 7] = hregAMD64_RDX();
175 (*arr)[ 8] = hregAMD64_R10();
176 (*arr)[ 9] = hregAMD64_R11();
177 (*arr)[10] = hregAMD64_R12();
178 (*arr)[11] = hregAMD64_R13();
179 (*arr)[12] = hregAMD64_R14();
180 (*arr)[13] = hregAMD64_R15();
181#endif
sewardjf67eadf2005-02-03 03:53:52 +0000182 // (*arr)[6] = hregAMD64_FAKE0();
183 //(*arr)[7] = hregAMD64_FAKE1();
184 //(*arr)[8] = hregAMD64_FAKE2();
185 //(*arr)[9] = hregAMD64_FAKE3();
186 //(*arr)[10] = hregAMD64_FAKE4();
187 //(*arr)[11] = hregAMD64_FAKE5();
188 (*arr)[14] = hregAMD64_XMM0();
189 (*arr)[15] = hregAMD64_XMM1();
190 (*arr)[16] = hregAMD64_XMM2();
191 (*arr)[17] = hregAMD64_XMM3();
192 (*arr)[18] = hregAMD64_XMM4();
193 (*arr)[19] = hregAMD64_XMM5();
194 (*arr)[20] = hregAMD64_XMM6();
195 (*arr)[21] = hregAMD64_XMM7();
196 (*arr)[22] = hregAMD64_XMM8();
197 (*arr)[23] = hregAMD64_XMM9();
198 (*arr)[24] = hregAMD64_XMM10();
199 (*arr)[25] = hregAMD64_XMM11();
200 (*arr)[26] = hregAMD64_XMM12();
201 (*arr)[27] = hregAMD64_XMM13();
202 (*arr)[28] = hregAMD64_XMM14();
203 (*arr)[29] = hregAMD64_XMM15();
sewardjc33671d2005-02-01 20:30:00 +0000204}
205
206
sewardjf67eadf2005-02-03 03:53:52 +0000207/* --------- Condition codes, Intel encoding. --------- */
208
209HChar* showAMD64CondCode ( AMD64CondCode cond )
210{
211 switch (cond) {
212 case Acc_O: return "o";
213 case Acc_NO: return "no";
214 case Acc_B: return "b";
215 case Acc_NB: return "nb";
216 case Acc_Z: return "z";
217 case Acc_NZ: return "nz";
218 case Acc_BE: return "be";
219 case Acc_NBE: return "nbe";
220 case Acc_S: return "s";
221 case Acc_NS: return "ns";
222 case Acc_P: return "p";
223 case Acc_NP: return "np";
224 case Acc_L: return "l";
225 case Acc_NL: return "nl";
226 case Acc_LE: return "le";
227 case Acc_NLE: return "nle";
228 case Acc_ALWAYS: return "ALWAYS";
229 default: vpanic("ppAMD64CondCode");
230 }
231}
sewardj614b3fb2005-02-02 02:16:03 +0000232
233
234/* --------- AMD64AMode: memory address expressions. --------- */
235
236AMD64AMode* AMD64AMode_IR ( UInt imm32, HReg reg ) {
237 AMD64AMode* am = LibVEX_Alloc(sizeof(AMD64AMode));
238 am->tag = Aam_IR;
239 am->Aam.IR.imm = imm32;
240 am->Aam.IR.reg = reg;
241 return am;
242}
243AMD64AMode* AMD64AMode_IRRS ( UInt imm32, HReg base, HReg indEx, Int shift ) {
244 AMD64AMode* am = LibVEX_Alloc(sizeof(AMD64AMode));
245 am->tag = Aam_IRRS;
246 am->Aam.IRRS.imm = imm32;
247 am->Aam.IRRS.base = base;
248 am->Aam.IRRS.index = indEx;
249 am->Aam.IRRS.shift = shift;
250 vassert(shift >= 0 && shift <= 3);
251 return am;
252}
253
254//.. AMD64AMode* dopyAMD64AMode ( AMD64AMode* am ) {
sewardja3e98302005-02-01 15:55:05 +0000255//.. switch (am->tag) {
256//.. case Xam_IR:
sewardj614b3fb2005-02-02 02:16:03 +0000257//.. return AMD64AMode_IR( am->Xam.IR.imm, am->Xam.IR.reg );
sewardja3e98302005-02-01 15:55:05 +0000258//.. case Xam_IRRS:
sewardj614b3fb2005-02-02 02:16:03 +0000259//.. return AMD64AMode_IRRS( am->Xam.IRRS.imm, am->Xam.IRRS.base,
sewardja3e98302005-02-01 15:55:05 +0000260//.. am->Xam.IRRS.index, am->Xam.IRRS.shift );
261//.. default:
sewardj614b3fb2005-02-02 02:16:03 +0000262//.. vpanic("dopyAMD64AMode");
sewardja3e98302005-02-01 15:55:05 +0000263//.. }
264//.. }
sewardj614b3fb2005-02-02 02:16:03 +0000265
266void ppAMD64AMode ( AMD64AMode* am ) {
267 switch (am->tag) {
268 case Aam_IR:
269 if (am->Aam.IR.imm == 0)
270 vex_printf("(");
271 else
272 vex_printf("0x%x(", am->Aam.IR.imm);
273 ppHRegAMD64(am->Aam.IR.reg);
274 vex_printf(")");
275 return;
276 case Aam_IRRS:
277 vex_printf("0x%x(", am->Aam.IRRS.imm);
278 ppHRegAMD64(am->Aam.IRRS.base);
279 vex_printf(",");
280 ppHRegAMD64(am->Aam.IRRS.index);
281 vex_printf(",%d)", 1 << am->Aam.IRRS.shift);
282 return;
283 default:
284 vpanic("ppAMD64AMode");
285 }
286}
287
sewardjf67eadf2005-02-03 03:53:52 +0000288static void addRegUsage_AMD64AMode ( HRegUsage* u, AMD64AMode* am ) {
289 switch (am->tag) {
290 case Aam_IR:
291 addHRegUse(u, HRmRead, am->Aam.IR.reg);
292 return;
293 case Aam_IRRS:
294 addHRegUse(u, HRmRead, am->Aam.IRRS.base);
295 addHRegUse(u, HRmRead, am->Aam.IRRS.index);
296 return;
297 default:
298 vpanic("addRegUsage_AMD64AMode");
299 }
300}
301
302static void mapRegs_AMD64AMode ( HRegRemap* m, AMD64AMode* am ) {
303 switch (am->tag) {
304 case Aam_IR:
305 am->Aam.IR.reg = lookupHRegRemap(m, am->Aam.IR.reg);
306 return;
307 case Aam_IRRS:
308 am->Aam.IRRS.base = lookupHRegRemap(m, am->Aam.IRRS.base);
309 am->Aam.IRRS.index = lookupHRegRemap(m, am->Aam.IRRS.index);
310 return;
311 default:
312 vpanic("mapRegs_AMD64AMode");
313 }
314}
sewardj614b3fb2005-02-02 02:16:03 +0000315
316/* --------- Operand, which can be reg, immediate or memory. --------- */
317
318AMD64RMI* AMD64RMI_Imm ( UInt imm32 ) {
319 AMD64RMI* op = LibVEX_Alloc(sizeof(AMD64RMI));
320 op->tag = Armi_Imm;
321 op->Armi.Imm.imm32 = imm32;
322 return op;
323}
sewardj8258a8c2005-02-02 03:11:24 +0000324AMD64RMI* AMD64RMI_Reg ( HReg reg ) {
325 AMD64RMI* op = LibVEX_Alloc(sizeof(AMD64RMI));
326 op->tag = Armi_Reg;
327 op->Armi.Reg.reg = reg;
328 return op;
329}
sewardj614b3fb2005-02-02 02:16:03 +0000330AMD64RMI* AMD64RMI_Mem ( AMD64AMode* am ) {
331 AMD64RMI* op = LibVEX_Alloc(sizeof(AMD64RMI));
332 op->tag = Armi_Mem;
333 op->Armi.Mem.am = am;
334 return op;
335}
336
337void ppAMD64RMI ( AMD64RMI* op ) {
338 switch (op->tag) {
339 case Armi_Imm:
340 vex_printf("$0x%x", op->Armi.Imm.imm32);
341 return;
342 case Armi_Reg:
343 ppHRegAMD64(op->Armi.Reg.reg);
344 return;
345 case Armi_Mem:
346 ppAMD64AMode(op->Armi.Mem.am);
347 return;
348 default:
349 vpanic("ppAMD64RMI");
350 }
351}
352
sewardjf67eadf2005-02-03 03:53:52 +0000353/* An AMD64RMI can only be used in a "read" context (what would it mean
354 to write or modify a literal?) and so we enumerate its registers
355 accordingly. */
356static void addRegUsage_AMD64RMI ( HRegUsage* u, AMD64RMI* op ) {
357 switch (op->tag) {
358 case Armi_Imm:
359 return;
360 case Armi_Reg:
361 addHRegUse(u, HRmRead, op->Armi.Reg.reg);
362 return;
363 case Armi_Mem:
364 addRegUsage_AMD64AMode(u, op->Armi.Mem.am);
365 return;
366 default:
367 vpanic("addRegUsage_AMD64RMI");
368 }
369}
370
371static void mapRegs_AMD64RMI ( HRegRemap* m, AMD64RMI* op ) {
372 switch (op->tag) {
373 case Armi_Imm:
374 return;
375 case Armi_Reg:
376 op->Armi.Reg.reg = lookupHRegRemap(m, op->Armi.Reg.reg);
377 return;
378 case Armi_Mem:
379 mapRegs_AMD64AMode(m, op->Armi.Mem.am);
380 return;
381 default:
382 vpanic("mapRegs_AMD64RMI");
383 }
384}
385
386
387/* --------- Operand, which can be reg or immediate only. --------- */
388
389AMD64RI* AMD64RI_Imm ( UInt imm32 ) {
390 AMD64RI* op = LibVEX_Alloc(sizeof(AMD64RI));
391 op->tag = Ari_Imm;
392 op->Ari.Imm.imm32 = imm32;
393 return op;
394}
395AMD64RI* AMD64RI_Reg ( HReg reg ) {
396 AMD64RI* op = LibVEX_Alloc(sizeof(AMD64RI));
397 op->tag = Ari_Reg;
398 op->Ari.Reg.reg = reg;
399 return op;
400}
401
402void ppAMD64RI ( AMD64RI* op ) {
403 switch (op->tag) {
404 case Ari_Imm:
405 vex_printf("$0x%x", op->Ari.Imm.imm32);
406 return;
407 case Ari_Reg:
408 ppHRegAMD64(op->Ari.Reg.reg);
409 return;
410 default:
411 vpanic("ppAMD64RI");
412 }
413}
414
415/* An AMD64RI can only be used in a "read" context (what would it mean
416 to write or modify a literal?) and so we enumerate its registers
417 accordingly. */
418static void addRegUsage_AMD64RI ( HRegUsage* u, AMD64RI* op ) {
419 switch (op->tag) {
420 case Ari_Imm:
421 return;
422 case Ari_Reg:
423 addHRegUse(u, HRmRead, op->Ari.Reg.reg);
424 return;
425 default:
426 vpanic("addRegUsage_AMD64RI");
427 }
428}
429
430static void mapRegs_AMD64RI ( HRegRemap* m, AMD64RI* op ) {
431 switch (op->tag) {
432 case Ari_Imm:
433 return;
434 case Ari_Reg:
435 op->Ari.Reg.reg = lookupHRegRemap(m, op->Ari.Reg.reg);
436 return;
437 default:
438 vpanic("mapRegs_AMD64RI");
439 }
440}
sewardj8258a8c2005-02-02 03:11:24 +0000441
442
443/* --------- Operand, which can be reg or memory only. --------- */
444
445AMD64RM* AMD64RM_Reg ( HReg reg ) {
446 AMD64RM* op = LibVEX_Alloc(sizeof(AMD64RM));
447 op->tag = Arm_Reg;
448 op->Arm.Reg.reg = reg;
449 return op;
450}
sewardj05b3b6a2005-02-04 01:44:33 +0000451AMD64RM* AMD64RM_Mem ( AMD64AMode* am ) {
452 AMD64RM* op = LibVEX_Alloc(sizeof(AMD64RM));
453 op->tag = Arm_Mem;
454 op->Arm.Mem.am = am;
455 return op;
456}
sewardj8258a8c2005-02-02 03:11:24 +0000457
458void ppAMD64RM ( AMD64RM* op ) {
459 switch (op->tag) {
460 case Arm_Mem:
461 ppAMD64AMode(op->Arm.Mem.am);
462 return;
463 case Arm_Reg:
464 ppHRegAMD64(op->Arm.Reg.reg);
465 return;
466 default:
467 vpanic("ppAMD64RM");
468 }
469}
470
sewardjf67eadf2005-02-03 03:53:52 +0000471/* Because an AMD64RM can be both a source or destination operand, we
472 have to supply a mode -- pertaining to the operand as a whole --
473 indicating how it's being used. */
474static void addRegUsage_AMD64RM ( HRegUsage* u, AMD64RM* op, HRegMode mode ) {
475 switch (op->tag) {
476 case Arm_Mem:
477 /* Memory is read, written or modified. So we just want to
478 know the regs read by the amode. */
479 addRegUsage_AMD64AMode(u, op->Arm.Mem.am);
480 return;
481 case Arm_Reg:
482 /* reg is read, written or modified. Add it in the
483 appropriate way. */
484 addHRegUse(u, mode, op->Arm.Reg.reg);
485 return;
486 default:
487 vpanic("addRegUsage_AMD64RM");
488 }
489}
490
491static void mapRegs_AMD64RM ( HRegRemap* m, AMD64RM* op )
492{
493 switch (op->tag) {
494 case Arm_Mem:
495 mapRegs_AMD64AMode(m, op->Arm.Mem.am);
496 return;
497 case Arm_Reg:
498 op->Arm.Reg.reg = lookupHRegRemap(m, op->Arm.Reg.reg);
499 return;
500 default:
501 vpanic("mapRegs_AMD64RM");
502 }
503}
504
505
sewardja3e98302005-02-01 15:55:05 +0000506//.. /* --------- Instructions. --------- */
507//..
sewardj614b3fb2005-02-02 02:16:03 +0000508//.. HChar* showAMD64ScalarSz ( AMD64ScalarSz sz ) {
sewardja3e98302005-02-01 15:55:05 +0000509//.. switch (sz) {
510//.. case Xss_16: return "w";
511//.. case Xss_32: return "l";
sewardj614b3fb2005-02-02 02:16:03 +0000512//.. default: vpanic("showAMD64ScalarSz");
sewardja3e98302005-02-01 15:55:05 +0000513//.. }
514//.. }
515//..
sewardj614b3fb2005-02-02 02:16:03 +0000516//.. HChar* showAMD64UnaryOp ( AMD64UnaryOp op ) {
sewardja3e98302005-02-01 15:55:05 +0000517//.. switch (op) {
518//.. case Xun_NOT: return "not";
519//.. case Xun_NEG: return "neg";
sewardj614b3fb2005-02-02 02:16:03 +0000520//.. default: vpanic("showAMD64UnaryOp");
sewardja3e98302005-02-01 15:55:05 +0000521//.. }
522//.. }
sewardj614b3fb2005-02-02 02:16:03 +0000523
524HChar* showAMD64AluOp ( AMD64AluOp op ) {
525 switch (op) {
526 case Aalu_MOV: return "mov";
527 case Aalu_CMP: return "cmp";
528 case Aalu_ADD: return "add";
529 case Aalu_SUB: return "sub";
530 case Aalu_ADC: return "adc";
531 case Aalu_SBB: return "sbb";
532 case Aalu_AND: return "and";
533 case Aalu_OR: return "or";
534 case Aalu_XOR: return "xor";
535 case Aalu_MUL: return "mul";
536 default: vpanic("showAMD64AluOp");
537 }
538}
539
sewardj8258a8c2005-02-02 03:11:24 +0000540HChar* showAMD64ShiftOp ( AMD64ShiftOp op ) {
541 switch (op) {
542 case Ash_SHL: return "shl";
543 case Ash_SHR: return "shr";
544 case Ash_SAR: return "sar";
545 default: vpanic("showAMD64ShiftOp");
546 }
547}
548
sewardj614b3fb2005-02-02 02:16:03 +0000549//.. HChar* showAMD64FpOp ( AMD64FpOp op ) {
sewardja3e98302005-02-01 15:55:05 +0000550//.. switch (op) {
551//.. case Xfp_ADD: return "add";
552//.. case Xfp_SUB: return "sub";
553//.. case Xfp_MUL: return "mul";
554//.. case Xfp_DIV: return "div";
555//.. case Xfp_SCALE: return "scale";
556//.. case Xfp_ATAN: return "atan";
557//.. case Xfp_YL2X: return "yl2x";
558//.. case Xfp_YL2XP1: return "yl2xp1";
559//.. case Xfp_PREM: return "prem";
560//.. case Xfp_PREM1: return "prem1";
561//.. case Xfp_SQRT: return "sqrt";
562//.. case Xfp_ABS: return "abs";
563//.. case Xfp_NEG: return "chs";
564//.. case Xfp_MOV: return "mov";
565//.. case Xfp_SIN: return "sin";
566//.. case Xfp_COS: return "cos";
567//.. case Xfp_TAN: return "tan";
568//.. case Xfp_ROUND: return "round";
569//.. case Xfp_2XM1: return "2xm1";
sewardj614b3fb2005-02-02 02:16:03 +0000570//.. default: vpanic("showAMD64FpOp");
sewardja3e98302005-02-01 15:55:05 +0000571//.. }
572//.. }
573//..
sewardj614b3fb2005-02-02 02:16:03 +0000574//.. HChar* showAMD64SseOp ( AMD64SseOp op ) {
sewardja3e98302005-02-01 15:55:05 +0000575//.. switch (op) {
576//.. case Xsse_MOV: return "mov(?!)";
577//.. case Xsse_ADDF: return "add";
578//.. case Xsse_SUBF: return "sub";
579//.. case Xsse_MULF: return "mul";
580//.. case Xsse_DIVF: return "div";
581//.. case Xsse_MAXF: return "max";
582//.. case Xsse_MINF: return "min";
583//.. case Xsse_CMPEQF: return "cmpFeq";
584//.. case Xsse_CMPLTF: return "cmpFlt";
585//.. case Xsse_CMPLEF: return "cmpFle";
586//.. case Xsse_CMPUNF: return "cmpFun";
587//.. case Xsse_RCPF: return "rcp";
588//.. case Xsse_RSQRTF: return "rsqrt";
589//.. case Xsse_SQRTF: return "sqrt";
590//.. case Xsse_AND: return "and";
591//.. case Xsse_OR: return "or";
592//.. case Xsse_XOR: return "xor";
593//.. case Xsse_ANDN: return "andn";
594//.. case Xsse_ADD8: return "paddb";
595//.. case Xsse_ADD16: return "paddw";
596//.. case Xsse_ADD32: return "paddd";
597//.. case Xsse_ADD64: return "paddq";
598//.. case Xsse_QADD8U: return "paddusb";
599//.. case Xsse_QADD16U: return "paddusw";
600//.. case Xsse_QADD8S: return "paddsb";
601//.. case Xsse_QADD16S: return "paddsw";
602//.. case Xsse_SUB8: return "psubb";
603//.. case Xsse_SUB16: return "psubw";
604//.. case Xsse_SUB32: return "psubd";
605//.. case Xsse_SUB64: return "psubq";
606//.. case Xsse_QSUB8U: return "psubusb";
607//.. case Xsse_QSUB16U: return "psubusw";
608//.. case Xsse_QSUB8S: return "psubsb";
609//.. case Xsse_QSUB16S: return "psubsw";
610//.. case Xsse_MUL16: return "pmullw";
611//.. case Xsse_MULHI16U: return "pmulhuw";
612//.. case Xsse_MULHI16S: return "pmulhw";
613//.. case Xsse_AVG8U: return "pavgb";
614//.. case Xsse_AVG16U: return "pavgw";
615//.. case Xsse_MAX16S: return "pmaxw";
616//.. case Xsse_MAX8U: return "pmaxub";
617//.. case Xsse_MIN16S: return "pminw";
618//.. case Xsse_MIN8U: return "pminub";
619//.. case Xsse_CMPEQ8: return "pcmpeqb";
620//.. case Xsse_CMPEQ16: return "pcmpeqw";
621//.. case Xsse_CMPEQ32: return "pcmpeqd";
622//.. case Xsse_CMPGT8S: return "pcmpgtb";
623//.. case Xsse_CMPGT16S: return "pcmpgtw";
624//.. case Xsse_CMPGT32S: return "pcmpgtd";
625//.. case Xsse_SHL16: return "psllw";
626//.. case Xsse_SHL32: return "pslld";
627//.. case Xsse_SHL64: return "psllq";
628//.. case Xsse_SHR16: return "psrlw";
629//.. case Xsse_SHR32: return "psrld";
630//.. case Xsse_SHR64: return "psrlq";
631//.. case Xsse_SAR16: return "psraw";
632//.. case Xsse_SAR32: return "psrad";
633//.. case Xsse_PACKSSD: return "packssdw";
634//.. case Xsse_PACKSSW: return "packsswb";
635//.. case Xsse_PACKUSW: return "packuswb";
636//.. case Xsse_UNPCKHB: return "punpckhb";
637//.. case Xsse_UNPCKHW: return "punpckhw";
638//.. case Xsse_UNPCKHD: return "punpckhd";
639//.. case Xsse_UNPCKHQ: return "punpckhq";
640//.. case Xsse_UNPCKLB: return "punpcklb";
641//.. case Xsse_UNPCKLW: return "punpcklw";
642//.. case Xsse_UNPCKLD: return "punpckld";
643//.. case Xsse_UNPCKLQ: return "punpcklq";
sewardj614b3fb2005-02-02 02:16:03 +0000644//.. default: vpanic("showAMD64SseOp");
sewardja3e98302005-02-01 15:55:05 +0000645//.. }
646//.. }
sewardj614b3fb2005-02-02 02:16:03 +0000647
sewardj813ce9e2005-02-04 21:16:48 +0000648AMD64Instr* AMD64Instr_Imm64 ( ULong imm64, HReg dst ) {
649 AMD64Instr* i = LibVEX_Alloc(sizeof(AMD64Instr));
650 i->tag = Ain_Imm64;
651 i->Ain.Imm64.imm64 = imm64;
652 i->Ain.Imm64.dst = dst;
653 return i;
654}
sewardj614b3fb2005-02-02 02:16:03 +0000655AMD64Instr* AMD64Instr_Alu64R ( AMD64AluOp op, AMD64RMI* src, HReg dst ) {
656 AMD64Instr* i = LibVEX_Alloc(sizeof(AMD64Instr));
657 i->tag = Ain_Alu64R;
658 i->Ain.Alu64R.op = op;
659 i->Ain.Alu64R.src = src;
660 i->Ain.Alu64R.dst = dst;
661 return i;
662}
sewardjf67eadf2005-02-03 03:53:52 +0000663AMD64Instr* AMD64Instr_Alu64M ( AMD64AluOp op, AMD64RI* src, AMD64AMode* dst ) {
664 AMD64Instr* i = LibVEX_Alloc(sizeof(AMD64Instr));
665 i->tag = Ain_Alu64M;
666 i->Ain.Alu64M.op = op;
667 i->Ain.Alu64M.src = src;
668 i->Ain.Alu64M.dst = dst;
669 vassert(op != Aalu_MUL);
670 return i;
671}
sewardj8258a8c2005-02-02 03:11:24 +0000672AMD64Instr* AMD64Instr_Sh64 ( AMD64ShiftOp op, UInt src, AMD64RM* dst ) {
673 AMD64Instr* i = LibVEX_Alloc(sizeof(AMD64Instr));
674 i->tag = Ain_Sh64;
675 i->Ain.Sh64.op = op;
676 i->Ain.Sh64.src = src;
677 i->Ain.Sh64.dst = dst;
678 return i;
679}
sewardj05b3b6a2005-02-04 01:44:33 +0000680AMD64Instr* AMD64Instr_Test64 ( AMD64RI* src, AMD64RM* dst ) {
681 AMD64Instr* i = LibVEX_Alloc(sizeof(AMD64Instr));
682 i->tag = Ain_Test64;
683 i->Ain.Test64.src = src;
684 i->Ain.Test64.dst = dst;
685 return i;
686}
sewardj614b3fb2005-02-02 02:16:03 +0000687//.. AMD64Instr* AMD64Instr_Unary32 ( AMD64UnaryOp op, AMD64RM* dst ) {
688//.. AMD64Instr* i = LibVEX_Alloc(sizeof(AMD64Instr));
sewardja3e98302005-02-01 15:55:05 +0000689//.. i->tag = Xin_Unary32;
690//.. i->Xin.Unary32.op = op;
691//.. i->Xin.Unary32.dst = dst;
692//.. return i;
693//.. }
sewardj614b3fb2005-02-02 02:16:03 +0000694//.. AMD64Instr* AMD64Instr_MulL ( Bool syned, AMD64ScalarSz ssz , AMD64RM* src ) {
695//.. AMD64Instr* i = LibVEX_Alloc(sizeof(AMD64Instr));
sewardja3e98302005-02-01 15:55:05 +0000696//.. i->tag = Xin_MulL;
697//.. i->Xin.MulL.syned = syned;
698//.. i->Xin.MulL.ssz = ssz;
699//.. i->Xin.MulL.src = src;
700//.. return i;
701//.. }
sewardj614b3fb2005-02-02 02:16:03 +0000702//.. AMD64Instr* AMD64Instr_Div ( Bool syned, AMD64ScalarSz ssz, AMD64RM* src ) {
703//.. AMD64Instr* i = LibVEX_Alloc(sizeof(AMD64Instr));
sewardja3e98302005-02-01 15:55:05 +0000704//.. i->tag = Xin_Div;
705//.. i->Xin.Div.syned = syned;
706//.. i->Xin.Div.ssz = ssz;
707//.. i->Xin.Div.src = src;
708//.. return i;
709//.. }
sewardj614b3fb2005-02-02 02:16:03 +0000710//.. AMD64Instr* AMD64Instr_Sh3232 ( AMD64ShiftOp op, UInt amt, HReg src, HReg dst ) {
711//.. AMD64Instr* i = LibVEX_Alloc(sizeof(AMD64Instr));
sewardja3e98302005-02-01 15:55:05 +0000712//.. i->tag = Xin_Sh3232;
713//.. i->Xin.Sh3232.op = op;
714//.. i->Xin.Sh3232.amt = amt;
715//.. i->Xin.Sh3232.src = src;
716//.. i->Xin.Sh3232.dst = dst;
717//.. vassert(op == Xsh_SHL || op == Xsh_SHR);
718//.. return i;
719//.. }
sewardj614b3fb2005-02-02 02:16:03 +0000720//.. AMD64Instr* AMD64Instr_Push( AMD64RMI* src ) {
721//.. AMD64Instr* i = LibVEX_Alloc(sizeof(AMD64Instr));
sewardja3e98302005-02-01 15:55:05 +0000722//.. i->tag = Xin_Push;
723//.. i->Xin.Push.src = src;
724//.. return i;
725//.. }
sewardj05b3b6a2005-02-04 01:44:33 +0000726AMD64Instr* AMD64Instr_Call ( AMD64CondCode cond, Addr64 target, Int regparms ) {
727 AMD64Instr* i = LibVEX_Alloc(sizeof(AMD64Instr));
728 i->tag = Ain_Call;
729 i->Ain.Call.cond = cond;
730 i->Ain.Call.target = target;
731 i->Ain.Call.regparms = regparms;
732 vassert(regparms >= 0 && regparms <= 6);
733 return i;
734}
sewardjf67eadf2005-02-03 03:53:52 +0000735AMD64Instr* AMD64Instr_Goto ( IRJumpKind jk, AMD64CondCode cond, AMD64RI* dst ) {
736 AMD64Instr* i = LibVEX_Alloc(sizeof(AMD64Instr));
737 i->tag = Ain_Goto;
738 i->Ain.Goto.cond = cond;
739 i->Ain.Goto.dst = dst;
740 i->Ain.Goto.jk = jk;
741 return i;
742}
sewardj05b3b6a2005-02-04 01:44:33 +0000743AMD64Instr* AMD64Instr_CMov64 ( AMD64CondCode cond, AMD64RM* src, HReg dst ) {
744 AMD64Instr* i = LibVEX_Alloc(sizeof(AMD64Instr));
745 i->tag = Ain_CMov64;
746 i->Ain.CMov64.cond = cond;
747 i->Ain.CMov64.src = src;
748 i->Ain.CMov64.dst = dst;
749 vassert(cond != Acc_ALWAYS);
750 return i;
751}
sewardjf67eadf2005-02-03 03:53:52 +0000752AMD64Instr* AMD64Instr_MovZLQ ( HReg src, HReg dst ) {
753 AMD64Instr* i = LibVEX_Alloc(sizeof(AMD64Instr));
754 i->tag = Ain_MovZLQ;
755 i->Ain.MovZLQ.src = src;
756 i->Ain.MovZLQ.dst = dst;
757 return i;
758}
sewardj8258a8c2005-02-02 03:11:24 +0000759AMD64Instr* AMD64Instr_LoadEX ( UChar szSmall, Bool syned,
760 AMD64AMode* src, HReg dst ) {
761 AMD64Instr* i = LibVEX_Alloc(sizeof(AMD64Instr));
762 i->tag = Ain_LoadEX;
763 i->Ain.LoadEX.szSmall = szSmall;
764 i->Ain.LoadEX.syned = syned;
765 i->Ain.LoadEX.src = src;
766 i->Ain.LoadEX.dst = dst;
767 vassert(szSmall == 1 || szSmall == 2 || szSmall == 4);
768 return i;
769}
sewardjf67eadf2005-02-03 03:53:52 +0000770AMD64Instr* AMD64Instr_Store ( UChar sz, HReg src, AMD64AMode* dst ) {
771 AMD64Instr* i = LibVEX_Alloc(sizeof(AMD64Instr));
772 i->tag = Ain_Store;
773 i->Ain.Store.sz = sz;
774 i->Ain.Store.src = src;
775 i->Ain.Store.dst = dst;
776 vassert(sz == 1 || sz == 2 || sz == 4);
777 return i;
778}
sewardj614b3fb2005-02-02 02:16:03 +0000779//.. AMD64Instr* AMD64Instr_Set32 ( AMD64CondCode cond, HReg dst ) {
780//.. AMD64Instr* i = LibVEX_Alloc(sizeof(AMD64Instr));
sewardja3e98302005-02-01 15:55:05 +0000781//.. i->tag = Xin_Set32;
782//.. i->Xin.Set32.cond = cond;
783//.. i->Xin.Set32.dst = dst;
784//.. return i;
785//.. }
sewardj614b3fb2005-02-02 02:16:03 +0000786//.. AMD64Instr* AMD64Instr_Bsfr32 ( Bool isFwds, HReg src, HReg dst ) {
787//.. AMD64Instr* i = LibVEX_Alloc(sizeof(AMD64Instr));
sewardja3e98302005-02-01 15:55:05 +0000788//.. i->tag = Xin_Bsfr32;
789//.. i->Xin.Bsfr32.isFwds = isFwds;
790//.. i->Xin.Bsfr32.src = src;
791//.. i->Xin.Bsfr32.dst = dst;
792//.. return i;
793//.. }
sewardj614b3fb2005-02-02 02:16:03 +0000794//.. AMD64Instr* AMD64Instr_MFence ( VexSubArch subarch )
sewardja3e98302005-02-01 15:55:05 +0000795//.. {
sewardj614b3fb2005-02-02 02:16:03 +0000796//.. AMD64Instr* i = LibVEX_Alloc(sizeof(AMD64Instr));
sewardja3e98302005-02-01 15:55:05 +0000797//.. i->tag = Xin_MFence;
798//.. i->Xin.MFence.subarch = subarch;
sewardj614b3fb2005-02-02 02:16:03 +0000799//.. vassert(subarch == VexSubArchAMD64_sse0
800//.. || subarch == VexSubArchAMD64_sse1
801//.. || subarch == VexSubArchAMD64_sse2);
sewardja3e98302005-02-01 15:55:05 +0000802//.. return i;
803//.. }
804//..
sewardj614b3fb2005-02-02 02:16:03 +0000805//.. AMD64Instr* AMD64Instr_FpUnary ( AMD64FpOp op, HReg src, HReg dst ) {
806//.. AMD64Instr* i = LibVEX_Alloc(sizeof(AMD64Instr));
sewardja3e98302005-02-01 15:55:05 +0000807//.. i->tag = Xin_FpUnary;
808//.. i->Xin.FpUnary.op = op;
809//.. i->Xin.FpUnary.src = src;
810//.. i->Xin.FpUnary.dst = dst;
811//.. return i;
812//.. }
sewardj614b3fb2005-02-02 02:16:03 +0000813//.. AMD64Instr* AMD64Instr_FpBinary ( AMD64FpOp op, HReg srcL, HReg srcR, HReg dst ) {
814//.. AMD64Instr* i = LibVEX_Alloc(sizeof(AMD64Instr));
sewardja3e98302005-02-01 15:55:05 +0000815//.. i->tag = Xin_FpBinary;
816//.. i->Xin.FpBinary.op = op;
817//.. i->Xin.FpBinary.srcL = srcL;
818//.. i->Xin.FpBinary.srcR = srcR;
819//.. i->Xin.FpBinary.dst = dst;
820//.. return i;
821//.. }
sewardj614b3fb2005-02-02 02:16:03 +0000822//.. AMD64Instr* AMD64Instr_FpLdSt ( Bool isLoad, UChar sz, HReg reg, AMD64AMode* addr ) {
823//.. AMD64Instr* i = LibVEX_Alloc(sizeof(AMD64Instr));
sewardja3e98302005-02-01 15:55:05 +0000824//.. i->tag = Xin_FpLdSt;
825//.. i->Xin.FpLdSt.isLoad = isLoad;
826//.. i->Xin.FpLdSt.sz = sz;
827//.. i->Xin.FpLdSt.reg = reg;
828//.. i->Xin.FpLdSt.addr = addr;
829//.. vassert(sz == 4 || sz == 8);
830//.. return i;
831//.. }
sewardj614b3fb2005-02-02 02:16:03 +0000832//.. AMD64Instr* AMD64Instr_FpLdStI ( Bool isLoad, UChar sz,
833//.. HReg reg, AMD64AMode* addr ) {
834//.. AMD64Instr* i = LibVEX_Alloc(sizeof(AMD64Instr));
sewardja3e98302005-02-01 15:55:05 +0000835//.. i->tag = Xin_FpLdStI;
836//.. i->Xin.FpLdStI.isLoad = isLoad;
837//.. i->Xin.FpLdStI.sz = sz;
838//.. i->Xin.FpLdStI.reg = reg;
839//.. i->Xin.FpLdStI.addr = addr;
840//.. vassert(sz == 2 || sz == 4 || sz == 8);
841//.. return i;
842//.. }
sewardj614b3fb2005-02-02 02:16:03 +0000843//.. AMD64Instr* AMD64Instr_Fp64to32 ( HReg src, HReg dst ) {
844//.. AMD64Instr* i = LibVEX_Alloc(sizeof(AMD64Instr));
sewardja3e98302005-02-01 15:55:05 +0000845//.. i->tag = Xin_Fp64to32;
846//.. i->Xin.Fp64to32.src = src;
847//.. i->Xin.Fp64to32.dst = dst;
848//.. return i;
849//.. }
sewardj614b3fb2005-02-02 02:16:03 +0000850//.. AMD64Instr* AMD64Instr_FpCMov ( AMD64CondCode cond, HReg src, HReg dst ) {
851//.. AMD64Instr* i = LibVEX_Alloc(sizeof(AMD64Instr));
sewardja3e98302005-02-01 15:55:05 +0000852//.. i->tag = Xin_FpCMov;
853//.. i->Xin.FpCMov.cond = cond;
854//.. i->Xin.FpCMov.src = src;
855//.. i->Xin.FpCMov.dst = dst;
856//.. vassert(cond != Xcc_ALWAYS);
857//.. return i;
858//.. }
sewardj614b3fb2005-02-02 02:16:03 +0000859//.. AMD64Instr* AMD64Instr_FpLdStCW ( Bool isLoad, AMD64AMode* addr ) {
860//.. AMD64Instr* i = LibVEX_Alloc(sizeof(AMD64Instr));
sewardja3e98302005-02-01 15:55:05 +0000861//.. i->tag = Xin_FpLdStCW;
862//.. i->Xin.FpLdStCW.isLoad = isLoad;
863//.. i->Xin.FpLdStCW.addr = addr;
864//.. return i;
865//.. }
sewardj614b3fb2005-02-02 02:16:03 +0000866//.. AMD64Instr* AMD64Instr_FpStSW_AX ( void ) {
867//.. AMD64Instr* i = LibVEX_Alloc(sizeof(AMD64Instr));
sewardja3e98302005-02-01 15:55:05 +0000868//.. i->tag = Xin_FpStSW_AX;
869//.. return i;
870//.. }
sewardj614b3fb2005-02-02 02:16:03 +0000871//.. AMD64Instr* AMD64Instr_FpCmp ( HReg srcL, HReg srcR, HReg dst ) {
872//.. AMD64Instr* i = LibVEX_Alloc(sizeof(AMD64Instr));
sewardja3e98302005-02-01 15:55:05 +0000873//.. i->tag = Xin_FpCmp;
874//.. i->Xin.FpCmp.srcL = srcL;
875//.. i->Xin.FpCmp.srcR = srcR;
876//.. i->Xin.FpCmp.dst = dst;
877//.. return i;
878//.. }
879//..
sewardj614b3fb2005-02-02 02:16:03 +0000880//.. AMD64Instr* AMD64Instr_SseConst ( UShort con, HReg dst ) {
881//.. AMD64Instr* i = LibVEX_Alloc(sizeof(AMD64Instr));
sewardja3e98302005-02-01 15:55:05 +0000882//.. i->tag = Xin_SseConst;
883//.. i->Xin.SseConst.con = con;
884//.. i->Xin.SseConst.dst = dst;
885//.. vassert(hregClass(dst) == HRcVec128);
886//.. return i;
887//.. }
sewardj614b3fb2005-02-02 02:16:03 +0000888//.. AMD64Instr* AMD64Instr_SseLdSt ( Bool isLoad, HReg reg, AMD64AMode* addr ) {
889//.. AMD64Instr* i = LibVEX_Alloc(sizeof(AMD64Instr));
sewardja3e98302005-02-01 15:55:05 +0000890//.. i->tag = Xin_SseLdSt;
891//.. i->Xin.SseLdSt.isLoad = isLoad;
892//.. i->Xin.SseLdSt.reg = reg;
893//.. i->Xin.SseLdSt.addr = addr;
894//.. return i;
895//.. }
sewardj614b3fb2005-02-02 02:16:03 +0000896//.. AMD64Instr* AMD64Instr_SseLdzLO ( Int sz, HReg reg, AMD64AMode* addr )
sewardja3e98302005-02-01 15:55:05 +0000897//.. {
sewardj614b3fb2005-02-02 02:16:03 +0000898//.. AMD64Instr* i = LibVEX_Alloc(sizeof(AMD64Instr));
sewardja3e98302005-02-01 15:55:05 +0000899//.. i->tag = Xin_SseLdzLO;
900//.. i->Xin.SseLdzLO.sz = sz;
901//.. i->Xin.SseLdzLO.reg = reg;
902//.. i->Xin.SseLdzLO.addr = addr;
903//.. vassert(sz == 4 || sz == 8);
904//.. return i;
905//.. }
sewardj614b3fb2005-02-02 02:16:03 +0000906//.. AMD64Instr* AMD64Instr_Sse32Fx4 ( AMD64SseOp op, HReg src, HReg dst ) {
907//.. AMD64Instr* i = LibVEX_Alloc(sizeof(AMD64Instr));
sewardja3e98302005-02-01 15:55:05 +0000908//.. i->tag = Xin_Sse32Fx4;
909//.. i->Xin.Sse32Fx4.op = op;
910//.. i->Xin.Sse32Fx4.src = src;
911//.. i->Xin.Sse32Fx4.dst = dst;
912//.. vassert(op != Xsse_MOV);
913//.. return i;
914//.. }
sewardj614b3fb2005-02-02 02:16:03 +0000915//.. AMD64Instr* AMD64Instr_Sse32FLo ( AMD64SseOp op, HReg src, HReg dst ) {
916//.. AMD64Instr* i = LibVEX_Alloc(sizeof(AMD64Instr));
sewardja3e98302005-02-01 15:55:05 +0000917//.. i->tag = Xin_Sse32FLo;
918//.. i->Xin.Sse32FLo.op = op;
919//.. i->Xin.Sse32FLo.src = src;
920//.. i->Xin.Sse32FLo.dst = dst;
921//.. vassert(op != Xsse_MOV);
922//.. return i;
923//.. }
sewardj614b3fb2005-02-02 02:16:03 +0000924//.. AMD64Instr* AMD64Instr_Sse64Fx2 ( AMD64SseOp op, HReg src, HReg dst ) {
925//.. AMD64Instr* i = LibVEX_Alloc(sizeof(AMD64Instr));
sewardja3e98302005-02-01 15:55:05 +0000926//.. i->tag = Xin_Sse64Fx2;
927//.. i->Xin.Sse64Fx2.op = op;
928//.. i->Xin.Sse64Fx2.src = src;
929//.. i->Xin.Sse64Fx2.dst = dst;
930//.. vassert(op != Xsse_MOV);
931//.. return i;
932//.. }
sewardj614b3fb2005-02-02 02:16:03 +0000933//.. AMD64Instr* AMD64Instr_Sse64FLo ( AMD64SseOp op, HReg src, HReg dst ) {
934//.. AMD64Instr* i = LibVEX_Alloc(sizeof(AMD64Instr));
sewardja3e98302005-02-01 15:55:05 +0000935//.. i->tag = Xin_Sse64FLo;
936//.. i->Xin.Sse64FLo.op = op;
937//.. i->Xin.Sse64FLo.src = src;
938//.. i->Xin.Sse64FLo.dst = dst;
939//.. vassert(op != Xsse_MOV);
940//.. return i;
941//.. }
sewardj614b3fb2005-02-02 02:16:03 +0000942//.. AMD64Instr* AMD64Instr_SseReRg ( AMD64SseOp op, HReg re, HReg rg ) {
943//.. AMD64Instr* i = LibVEX_Alloc(sizeof(AMD64Instr));
sewardja3e98302005-02-01 15:55:05 +0000944//.. i->tag = Xin_SseReRg;
945//.. i->Xin.SseReRg.op = op;
946//.. i->Xin.SseReRg.src = re;
947//.. i->Xin.SseReRg.dst = rg;
948//.. return i;
949//.. }
sewardj614b3fb2005-02-02 02:16:03 +0000950//.. AMD64Instr* AMD64Instr_SseCMov ( AMD64CondCode cond, HReg src, HReg dst ) {
951//.. AMD64Instr* i = LibVEX_Alloc(sizeof(AMD64Instr));
sewardja3e98302005-02-01 15:55:05 +0000952//.. i->tag = Xin_SseCMov;
953//.. i->Xin.SseCMov.cond = cond;
954//.. i->Xin.SseCMov.src = src;
955//.. i->Xin.SseCMov.dst = dst;
956//.. vassert(cond != Xcc_ALWAYS);
957//.. return i;
958//.. }
sewardj614b3fb2005-02-02 02:16:03 +0000959//.. AMD64Instr* AMD64Instr_SseShuf ( Int order, HReg src, HReg dst ) {
960//.. AMD64Instr* i = LibVEX_Alloc(sizeof(AMD64Instr));
sewardja3e98302005-02-01 15:55:05 +0000961//.. i->tag = Xin_SseShuf;
962//.. i->Xin.SseShuf.order = order;
963//.. i->Xin.SseShuf.src = src;
964//.. i->Xin.SseShuf.dst = dst;
965//.. vassert(order >= 0 && order <= 0xFF);
966//.. return i;
967//.. }
sewardjc33671d2005-02-01 20:30:00 +0000968
969void ppAMD64Instr ( AMD64Instr* i )
970{
971 switch (i->tag) {
sewardj813ce9e2005-02-04 21:16:48 +0000972 case Ain_Imm64:
sewardj1b8d58e2005-02-05 14:34:18 +0000973 vex_printf("movabsq $0x%llx,", i->Ain.Imm64.imm64);
sewardj813ce9e2005-02-04 21:16:48 +0000974 ppHRegAMD64(i->Ain.Imm64.dst);
975 return;
sewardj614b3fb2005-02-02 02:16:03 +0000976 case Ain_Alu64R:
977 vex_printf("%sq ", showAMD64AluOp(i->Ain.Alu64R.op));
978 ppAMD64RMI(i->Ain.Alu64R.src);
979 vex_printf(",");
980 ppHRegAMD64(i->Ain.Alu64R.dst);
981 return;
sewardjf67eadf2005-02-03 03:53:52 +0000982 case Ain_Alu64M:
983 vex_printf("%sq ", showAMD64AluOp(i->Ain.Alu64M.op));
984 ppAMD64RI(i->Ain.Alu64M.src);
985 vex_printf(",");
986 ppAMD64AMode(i->Ain.Alu64M.dst);
987 return;
sewardj8258a8c2005-02-02 03:11:24 +0000988 case Ain_Sh64:
sewardj1b8d58e2005-02-05 14:34:18 +0000989 vex_printf("%sq ", showAMD64ShiftOp(i->Ain.Sh64.op));
sewardj8258a8c2005-02-02 03:11:24 +0000990 if (i->Ain.Sh64.src == 0)
991 vex_printf("%%cl,");
992 else
993 vex_printf("$%d,", i->Ain.Sh64.src);
994 ppAMD64RM(i->Ain.Sh64.dst);
995 return;
sewardj05b3b6a2005-02-04 01:44:33 +0000996 case Ain_Test64:
997 vex_printf("testq ");
998 ppAMD64RI(i->Ain.Test64.src);
999 vex_printf(",");
1000 ppAMD64RM(i->Ain.Test64.dst);
1001 return;
sewardja3e98302005-02-01 15:55:05 +00001002//.. case Xin_Unary32:
sewardj614b3fb2005-02-02 02:16:03 +00001003//.. vex_printf("%sl ", showAMD64UnaryOp(i->Xin.Unary32.op));
1004//.. ppAMD64RM(i->Xin.Unary32.dst);
sewardja3e98302005-02-01 15:55:05 +00001005//.. return;
1006//.. case Xin_MulL:
1007//.. vex_printf("%cmul%s ",
1008//.. i->Xin.MulL.syned ? 's' : 'u',
sewardj614b3fb2005-02-02 02:16:03 +00001009//.. showAMD64ScalarSz(i->Xin.MulL.ssz));
1010//.. ppAMD64RM(i->Xin.MulL.src);
sewardja3e98302005-02-01 15:55:05 +00001011//.. return;
1012//.. case Xin_Div:
1013//.. vex_printf("%cdiv%s ",
1014//.. i->Xin.Div.syned ? 's' : 'u',
sewardj614b3fb2005-02-02 02:16:03 +00001015//.. showAMD64ScalarSz(i->Xin.Div.ssz));
1016//.. ppAMD64RM(i->Xin.Div.src);
sewardja3e98302005-02-01 15:55:05 +00001017//.. return;
1018//.. case Xin_Sh3232:
sewardj614b3fb2005-02-02 02:16:03 +00001019//.. vex_printf("%sdl ", showAMD64ShiftOp(i->Xin.Sh3232.op));
sewardja3e98302005-02-01 15:55:05 +00001020//.. if (i->Xin.Sh3232.amt == 0)
1021//.. vex_printf(" %%cl,");
1022//.. else
1023//.. vex_printf(" $%d,", i->Xin.Sh3232.amt);
sewardj614b3fb2005-02-02 02:16:03 +00001024//.. ppHRegAMD64(i->Xin.Sh3232.src);
sewardja3e98302005-02-01 15:55:05 +00001025//.. vex_printf(",");
sewardj614b3fb2005-02-02 02:16:03 +00001026//.. ppHRegAMD64(i->Xin.Sh3232.dst);
sewardja3e98302005-02-01 15:55:05 +00001027//.. return;
1028//.. case Xin_Push:
1029//.. vex_printf("pushl ");
sewardj614b3fb2005-02-02 02:16:03 +00001030//.. ppAMD64RMI(i->Xin.Push.src);
sewardja3e98302005-02-01 15:55:05 +00001031//.. return;
sewardj05b3b6a2005-02-04 01:44:33 +00001032 case Ain_Call:
1033 vex_printf("call%s[%d] ",
1034 i->Ain.Call.cond==Acc_ALWAYS
1035 ? "" : showAMD64CondCode(i->Ain.Call.cond),
1036 i->Ain.Call.regparms );
1037 vex_printf("0x%llx", i->Ain.Call.target);
1038 break;
sewardjf67eadf2005-02-03 03:53:52 +00001039 case Ain_Goto:
1040 if (i->Ain.Goto.cond != Acc_ALWAYS) {
1041 vex_printf("if (%%rflags.%s) { ",
1042 showAMD64CondCode(i->Ain.Goto.cond));
1043 }
1044 if (i->Ain.Goto.jk != Ijk_Boring) {
1045 vex_printf("movl $");
1046 ppIRJumpKind(i->Ain.Goto.jk);
sewardjc2bcb6f2005-02-07 00:17:12 +00001047 vex_printf(",%%ebp ; ");
sewardjf67eadf2005-02-03 03:53:52 +00001048 }
sewardj1b8d58e2005-02-05 14:34:18 +00001049 vex_printf("movq ");
sewardjf67eadf2005-02-03 03:53:52 +00001050 ppAMD64RI(i->Ain.Goto.dst);
1051 vex_printf(",%%rax ; ret");
1052 if (i->Ain.Goto.cond != Acc_ALWAYS) {
1053 vex_printf(" }");
1054 }
1055 return;
sewardj05b3b6a2005-02-04 01:44:33 +00001056 case Ain_CMov64:
1057 vex_printf("cmov%s ", showAMD64CondCode(i->Ain.CMov64.cond));
1058 ppAMD64RM(i->Ain.CMov64.src);
1059 vex_printf(",");
1060 ppHRegAMD64(i->Ain.CMov64.dst);
1061 return;
sewardjf67eadf2005-02-03 03:53:52 +00001062 case Ain_MovZLQ:
sewardj549e0642005-02-05 12:00:14 +00001063 vex_printf("movl{zlq} ");
1064 ppHRegAMD64_lo32(i->Ain.MovZLQ.src);
sewardjf67eadf2005-02-03 03:53:52 +00001065 vex_printf(",");
sewardj549e0642005-02-05 12:00:14 +00001066 ppHRegAMD64_lo32(i->Ain.MovZLQ.dst);
sewardjf67eadf2005-02-03 03:53:52 +00001067 return;
sewardj8258a8c2005-02-02 03:11:24 +00001068 case Ain_LoadEX:
sewardj549e0642005-02-05 12:00:14 +00001069 if (i->Ain.LoadEX.szSmall==4 && !i->Ain.LoadEX.syned) {
1070 vex_printf("movl ");
1071 ppAMD64AMode(i->Ain.LoadEX.src);
1072 vex_printf(",");
1073 ppHRegAMD64_lo32(i->Ain.LoadEX.dst);
1074 } else {
1075 vex_printf("mov%c%cq ",
1076 i->Ain.LoadEX.syned ? 's' : 'z',
1077 i->Ain.LoadEX.szSmall==1
1078 ? 'b'
1079 : (i->Ain.LoadEX.szSmall==2 ? 'w' : 'l'));
1080 ppAMD64AMode(i->Ain.LoadEX.src);
1081 vex_printf(",");
1082 ppHRegAMD64(i->Ain.LoadEX.dst);
1083 }
sewardj8258a8c2005-02-02 03:11:24 +00001084 return;
sewardj05b3b6a2005-02-04 01:44:33 +00001085 case Ain_Store:
1086 vex_printf("mov%c ", i->Ain.Store.sz==1 ? 'b'
1087 : (i->Ain.Store.sz==2 ? 'w' : 'l'));
1088 ppHRegAMD64(i->Ain.Store.src);
1089 vex_printf(",");
1090 ppAMD64AMode(i->Ain.Store.dst);
1091 return;
sewardja3e98302005-02-01 15:55:05 +00001092//.. case Xin_Set32:
sewardj614b3fb2005-02-02 02:16:03 +00001093//.. vex_printf("setl%s ", showAMD64CondCode(i->Xin.Set32.cond));
1094//.. ppHRegAMD64(i->Xin.Set32.dst);
sewardja3e98302005-02-01 15:55:05 +00001095//.. return;
1096//.. case Xin_Bsfr32:
1097//.. vex_printf("bs%cl ", i->Xin.Bsfr32.isFwds ? 'f' : 'r');
sewardj614b3fb2005-02-02 02:16:03 +00001098//.. ppHRegAMD64(i->Xin.Bsfr32.src);
sewardja3e98302005-02-01 15:55:05 +00001099//.. vex_printf(",");
sewardj614b3fb2005-02-02 02:16:03 +00001100//.. ppHRegAMD64(i->Xin.Bsfr32.dst);
sewardja3e98302005-02-01 15:55:05 +00001101//.. return;
1102//.. case Xin_MFence:
1103//.. vex_printf("mfence(%s)",
1104//.. LibVEX_ppVexSubArch(i->Xin.MFence.subarch));
1105//.. return;
1106//.. case Xin_FpUnary:
sewardj614b3fb2005-02-02 02:16:03 +00001107//.. vex_printf("g%sD ", showAMD64FpOp(i->Xin.FpUnary.op));
1108//.. ppHRegAMD64(i->Xin.FpUnary.src);
sewardja3e98302005-02-01 15:55:05 +00001109//.. vex_printf(",");
sewardj614b3fb2005-02-02 02:16:03 +00001110//.. ppHRegAMD64(i->Xin.FpUnary.dst);
sewardja3e98302005-02-01 15:55:05 +00001111//.. break;
1112//.. case Xin_FpBinary:
sewardj614b3fb2005-02-02 02:16:03 +00001113//.. vex_printf("g%sD ", showAMD64FpOp(i->Xin.FpBinary.op));
1114//.. ppHRegAMD64(i->Xin.FpBinary.srcL);
sewardja3e98302005-02-01 15:55:05 +00001115//.. vex_printf(",");
sewardj614b3fb2005-02-02 02:16:03 +00001116//.. ppHRegAMD64(i->Xin.FpBinary.srcR);
sewardja3e98302005-02-01 15:55:05 +00001117//.. vex_printf(",");
sewardj614b3fb2005-02-02 02:16:03 +00001118//.. ppHRegAMD64(i->Xin.FpBinary.dst);
sewardja3e98302005-02-01 15:55:05 +00001119//.. break;
1120//.. case Xin_FpLdSt:
1121//.. if (i->Xin.FpLdSt.isLoad) {
1122//.. vex_printf("gld%c " , i->Xin.FpLdSt.sz==8 ? 'D' : 'F');
sewardj614b3fb2005-02-02 02:16:03 +00001123//.. ppAMD64AMode(i->Xin.FpLdSt.addr);
sewardja3e98302005-02-01 15:55:05 +00001124//.. vex_printf(", ");
sewardj614b3fb2005-02-02 02:16:03 +00001125//.. ppHRegAMD64(i->Xin.FpLdSt.reg);
sewardja3e98302005-02-01 15:55:05 +00001126//.. } else {
1127//.. vex_printf("gst%c " , i->Xin.FpLdSt.sz==8 ? 'D' : 'F');
sewardj614b3fb2005-02-02 02:16:03 +00001128//.. ppHRegAMD64(i->Xin.FpLdSt.reg);
sewardja3e98302005-02-01 15:55:05 +00001129//.. vex_printf(", ");
sewardj614b3fb2005-02-02 02:16:03 +00001130//.. ppAMD64AMode(i->Xin.FpLdSt.addr);
sewardja3e98302005-02-01 15:55:05 +00001131//.. }
1132//.. return;
1133//.. case Xin_FpLdStI:
1134//.. if (i->Xin.FpLdStI.isLoad) {
1135//.. vex_printf("gild%s ", i->Xin.FpLdStI.sz==8 ? "ll" :
1136//.. i->Xin.FpLdStI.sz==4 ? "l" : "w");
sewardj614b3fb2005-02-02 02:16:03 +00001137//.. ppAMD64AMode(i->Xin.FpLdStI.addr);
sewardja3e98302005-02-01 15:55:05 +00001138//.. vex_printf(", ");
sewardj614b3fb2005-02-02 02:16:03 +00001139//.. ppHRegAMD64(i->Xin.FpLdStI.reg);
sewardja3e98302005-02-01 15:55:05 +00001140//.. } else {
1141//.. vex_printf("gist%s ", i->Xin.FpLdStI.sz==8 ? "ll" :
1142//.. i->Xin.FpLdStI.sz==4 ? "l" : "w");
sewardj614b3fb2005-02-02 02:16:03 +00001143//.. ppHRegAMD64(i->Xin.FpLdStI.reg);
sewardja3e98302005-02-01 15:55:05 +00001144//.. vex_printf(", ");
sewardj614b3fb2005-02-02 02:16:03 +00001145//.. ppAMD64AMode(i->Xin.FpLdStI.addr);
sewardja3e98302005-02-01 15:55:05 +00001146//.. }
1147//.. return;
1148//.. case Xin_Fp64to32:
1149//.. vex_printf("gdtof ");
sewardj614b3fb2005-02-02 02:16:03 +00001150//.. ppHRegAMD64(i->Xin.Fp64to32.src);
sewardja3e98302005-02-01 15:55:05 +00001151//.. vex_printf(",");
sewardj614b3fb2005-02-02 02:16:03 +00001152//.. ppHRegAMD64(i->Xin.Fp64to32.dst);
sewardja3e98302005-02-01 15:55:05 +00001153//.. return;
1154//.. case Xin_FpCMov:
sewardj614b3fb2005-02-02 02:16:03 +00001155//.. vex_printf("gcmov%s ", showAMD64CondCode(i->Xin.FpCMov.cond));
1156//.. ppHRegAMD64(i->Xin.FpCMov.src);
sewardja3e98302005-02-01 15:55:05 +00001157//.. vex_printf(",");
sewardj614b3fb2005-02-02 02:16:03 +00001158//.. ppHRegAMD64(i->Xin.FpCMov.dst);
sewardja3e98302005-02-01 15:55:05 +00001159//.. return;
1160//.. case Xin_FpLdStCW:
1161//.. vex_printf(i->Xin.FpLdStCW.isLoad ? "fldcw " : "fstcw ");
sewardj614b3fb2005-02-02 02:16:03 +00001162//.. ppAMD64AMode(i->Xin.FpLdStCW.addr);
sewardja3e98302005-02-01 15:55:05 +00001163//.. return;
1164//.. case Xin_FpStSW_AX:
1165//.. vex_printf("fstsw %%ax");
1166//.. return;
1167//.. case Xin_FpCmp:
1168//.. vex_printf("gcmp ");
sewardj614b3fb2005-02-02 02:16:03 +00001169//.. ppHRegAMD64(i->Xin.FpCmp.srcL);
sewardja3e98302005-02-01 15:55:05 +00001170//.. vex_printf(",");
sewardj614b3fb2005-02-02 02:16:03 +00001171//.. ppHRegAMD64(i->Xin.FpCmp.srcR);
sewardja3e98302005-02-01 15:55:05 +00001172//.. vex_printf(",");
sewardj614b3fb2005-02-02 02:16:03 +00001173//.. ppHRegAMD64(i->Xin.FpCmp.dst);
sewardja3e98302005-02-01 15:55:05 +00001174//.. break;
1175//.. case Xin_SseConst:
1176//.. vex_printf("const $0x%04x,", (Int)i->Xin.SseConst.con);
sewardj614b3fb2005-02-02 02:16:03 +00001177//.. ppHRegAMD64(i->Xin.SseConst.dst);
sewardja3e98302005-02-01 15:55:05 +00001178//.. break;
1179//.. case Xin_SseLdSt:
1180//.. vex_printf("movups ");
1181//.. if (i->Xin.SseLdSt.isLoad) {
sewardj614b3fb2005-02-02 02:16:03 +00001182//.. ppAMD64AMode(i->Xin.SseLdSt.addr);
sewardja3e98302005-02-01 15:55:05 +00001183//.. vex_printf(",");
sewardj614b3fb2005-02-02 02:16:03 +00001184//.. ppHRegAMD64(i->Xin.SseLdSt.reg);
sewardja3e98302005-02-01 15:55:05 +00001185//.. } else {
sewardj614b3fb2005-02-02 02:16:03 +00001186//.. ppHRegAMD64(i->Xin.SseLdSt.reg);
sewardja3e98302005-02-01 15:55:05 +00001187//.. vex_printf(",");
sewardj614b3fb2005-02-02 02:16:03 +00001188//.. ppAMD64AMode(i->Xin.SseLdSt.addr);
sewardja3e98302005-02-01 15:55:05 +00001189//.. }
1190//.. return;
1191//.. case Xin_SseLdzLO:
1192//.. vex_printf("movs%s ", i->Xin.SseLdzLO.sz==4 ? "s" : "d");
sewardj614b3fb2005-02-02 02:16:03 +00001193//.. ppAMD64AMode(i->Xin.SseLdzLO.addr);
sewardja3e98302005-02-01 15:55:05 +00001194//.. vex_printf(",");
sewardj614b3fb2005-02-02 02:16:03 +00001195//.. ppHRegAMD64(i->Xin.SseLdzLO.reg);
sewardja3e98302005-02-01 15:55:05 +00001196//.. return;
1197//.. case Xin_Sse32Fx4:
sewardj614b3fb2005-02-02 02:16:03 +00001198//.. vex_printf("%sps ", showAMD64SseOp(i->Xin.Sse32Fx4.op));
1199//.. ppHRegAMD64(i->Xin.Sse32Fx4.src);
sewardja3e98302005-02-01 15:55:05 +00001200//.. vex_printf(",");
sewardj614b3fb2005-02-02 02:16:03 +00001201//.. ppHRegAMD64(i->Xin.Sse32Fx4.dst);
sewardja3e98302005-02-01 15:55:05 +00001202//.. return;
1203//.. case Xin_Sse32FLo:
sewardj614b3fb2005-02-02 02:16:03 +00001204//.. vex_printf("%sss ", showAMD64SseOp(i->Xin.Sse32FLo.op));
1205//.. ppHRegAMD64(i->Xin.Sse32FLo.src);
sewardja3e98302005-02-01 15:55:05 +00001206//.. vex_printf(",");
sewardj614b3fb2005-02-02 02:16:03 +00001207//.. ppHRegAMD64(i->Xin.Sse32FLo.dst);
sewardja3e98302005-02-01 15:55:05 +00001208//.. return;
1209//.. case Xin_Sse64Fx2:
sewardj614b3fb2005-02-02 02:16:03 +00001210//.. vex_printf("%spd ", showAMD64SseOp(i->Xin.Sse64Fx2.op));
1211//.. ppHRegAMD64(i->Xin.Sse64Fx2.src);
sewardja3e98302005-02-01 15:55:05 +00001212//.. vex_printf(",");
sewardj614b3fb2005-02-02 02:16:03 +00001213//.. ppHRegAMD64(i->Xin.Sse64Fx2.dst);
sewardja3e98302005-02-01 15:55:05 +00001214//.. return;
1215//.. case Xin_Sse64FLo:
sewardj614b3fb2005-02-02 02:16:03 +00001216//.. vex_printf("%ssd ", showAMD64SseOp(i->Xin.Sse64FLo.op));
1217//.. ppHRegAMD64(i->Xin.Sse64FLo.src);
sewardja3e98302005-02-01 15:55:05 +00001218//.. vex_printf(",");
sewardj614b3fb2005-02-02 02:16:03 +00001219//.. ppHRegAMD64(i->Xin.Sse64FLo.dst);
sewardja3e98302005-02-01 15:55:05 +00001220//.. return;
1221//.. case Xin_SseReRg:
sewardj614b3fb2005-02-02 02:16:03 +00001222//.. vex_printf("%s ", showAMD64SseOp(i->Xin.SseReRg.op));
1223//.. ppHRegAMD64(i->Xin.SseReRg.src);
sewardja3e98302005-02-01 15:55:05 +00001224//.. vex_printf(",");
sewardj614b3fb2005-02-02 02:16:03 +00001225//.. ppHRegAMD64(i->Xin.SseReRg.dst);
sewardja3e98302005-02-01 15:55:05 +00001226//.. return;
1227//.. case Xin_SseCMov:
sewardj614b3fb2005-02-02 02:16:03 +00001228//.. vex_printf("cmov%s ", showAMD64CondCode(i->Xin.SseCMov.cond));
1229//.. ppHRegAMD64(i->Xin.SseCMov.src);
sewardja3e98302005-02-01 15:55:05 +00001230//.. vex_printf(",");
sewardj614b3fb2005-02-02 02:16:03 +00001231//.. ppHRegAMD64(i->Xin.SseCMov.dst);
sewardja3e98302005-02-01 15:55:05 +00001232//.. return;
1233//.. case Xin_SseShuf:
1234//.. vex_printf("pshufd $0x%x,", i->Xin.SseShuf.order);
sewardj614b3fb2005-02-02 02:16:03 +00001235//.. ppHRegAMD64(i->Xin.SseShuf.src);
sewardja3e98302005-02-01 15:55:05 +00001236//.. vex_printf(",");
sewardj614b3fb2005-02-02 02:16:03 +00001237//.. ppHRegAMD64(i->Xin.SseShuf.dst);
sewardja3e98302005-02-01 15:55:05 +00001238//.. return;
sewardjc33671d2005-02-01 20:30:00 +00001239
1240 default:
1241 vpanic("ppAMD64Instr");
1242 }
1243}
1244
1245/* --------- Helpers for register allocation. --------- */
1246
1247void getRegUsage_AMD64Instr ( HRegUsage* u, AMD64Instr* i )
1248{
1249 // Bool unary;
1250 initHRegUsage(u);
1251 switch (i->tag) {
sewardj813ce9e2005-02-04 21:16:48 +00001252 case Ain_Imm64:
1253 addHRegUse(u, HRmWrite, i->Ain.Imm64.dst);
1254 return;
sewardjf67eadf2005-02-03 03:53:52 +00001255 case Ain_Alu64R:
1256 addRegUsage_AMD64RMI(u, i->Ain.Alu64R.src);
1257 if (i->Ain.Alu64R.op == Aalu_MOV) {
1258 addHRegUse(u, HRmWrite, i->Ain.Alu64R.dst);
1259 return;
1260 }
1261 if (i->Ain.Alu64R.op == Aalu_CMP) {
1262 addHRegUse(u, HRmRead, i->Ain.Alu64R.dst);
1263 return;
1264 }
1265 addHRegUse(u, HRmModify, i->Ain.Alu64R.dst);
1266 return;
1267 case Ain_Alu64M:
1268 addRegUsage_AMD64RI(u, i->Ain.Alu64M.src);
1269 addRegUsage_AMD64AMode(u, i->Ain.Alu64M.dst);
1270 return;
1271 case Ain_Sh64:
1272 addRegUsage_AMD64RM(u, i->Ain.Sh64.dst, HRmModify);
1273 if (i->Ain.Sh64.src == 0)
1274 addHRegUse(u, HRmRead, hregAMD64_RCX());
1275 return;
sewardj05b3b6a2005-02-04 01:44:33 +00001276 case Ain_Test64:
1277 addRegUsage_AMD64RI(u, i->Ain.Test64.src);
1278 addRegUsage_AMD64RM(u, i->Ain.Test64.dst, HRmRead);
1279 return;
sewardja3e98302005-02-01 15:55:05 +00001280//.. case Xin_Unary32:
sewardj614b3fb2005-02-02 02:16:03 +00001281//.. addRegUsage_AMD64RM(u, i->Xin.Unary32.dst, HRmModify);
sewardja3e98302005-02-01 15:55:05 +00001282//.. return;
1283//.. case Xin_MulL:
sewardj614b3fb2005-02-02 02:16:03 +00001284//.. addRegUsage_AMD64RM(u, i->Xin.MulL.src, HRmRead);
1285//.. addHRegUse(u, HRmModify, hregAMD64_EAX());
1286//.. addHRegUse(u, HRmWrite, hregAMD64_EDX());
sewardja3e98302005-02-01 15:55:05 +00001287//.. return;
1288//.. case Xin_Div:
sewardj614b3fb2005-02-02 02:16:03 +00001289//.. addRegUsage_AMD64RM(u, i->Xin.Div.src, HRmRead);
1290//.. addHRegUse(u, HRmModify, hregAMD64_EAX());
1291//.. addHRegUse(u, HRmModify, hregAMD64_EDX());
sewardja3e98302005-02-01 15:55:05 +00001292//.. return;
1293//.. case Xin_Sh3232:
1294//.. addHRegUse(u, HRmRead, i->Xin.Sh3232.src);
1295//.. addHRegUse(u, HRmModify, i->Xin.Sh3232.dst);
1296//.. if (i->Xin.Sh3232.amt == 0)
sewardj614b3fb2005-02-02 02:16:03 +00001297//.. addHRegUse(u, HRmRead, hregAMD64_ECX());
sewardja3e98302005-02-01 15:55:05 +00001298//.. return;
1299//.. case Xin_Push:
sewardj614b3fb2005-02-02 02:16:03 +00001300//.. addRegUsage_AMD64RMI(u, i->Xin.Push.src);
1301//.. addHRegUse(u, HRmModify, hregAMD64_ESP());
sewardja3e98302005-02-01 15:55:05 +00001302//.. return;
sewardj05b3b6a2005-02-04 01:44:33 +00001303 case Ain_Call:
1304 /* This is a bit subtle. */
1305 /* First off, claim it trashes all the caller-saved regs
1306 which fall within the register allocator's jurisdiction.
1307 These I believe to be: rax rcx rdx rsi rdi r8 r9 r10 r11
1308 */
1309 addHRegUse(u, HRmWrite, hregAMD64_RAX());
1310 addHRegUse(u, HRmWrite, hregAMD64_RCX());
1311 addHRegUse(u, HRmWrite, hregAMD64_RDX());
1312 addHRegUse(u, HRmWrite, hregAMD64_RSI());
1313 addHRegUse(u, HRmWrite, hregAMD64_RDI());
1314 addHRegUse(u, HRmWrite, hregAMD64_R8());
1315 addHRegUse(u, HRmWrite, hregAMD64_R9());
1316 addHRegUse(u, HRmWrite, hregAMD64_R10());
1317 addHRegUse(u, HRmWrite, hregAMD64_R11());
1318
1319 /* Now we have to state any parameter-carrying registers
1320 which might be read. This depends on the regparmness. */
1321 switch (i->Ain.Call.regparms) {
1322 case 6: addHRegUse(u, HRmRead, hregAMD64_R9()); /*fallthru*/
1323 case 5: addHRegUse(u, HRmRead, hregAMD64_R8()); /*fallthru*/
1324 case 4: addHRegUse(u, HRmRead, hregAMD64_RCX()); /*fallthru*/
1325 case 3: addHRegUse(u, HRmRead, hregAMD64_RDX()); /*fallthru*/
1326 case 2: addHRegUse(u, HRmRead, hregAMD64_RSI()); /*fallthru*/
1327 case 1: addHRegUse(u, HRmRead, hregAMD64_RDI()); break;
1328 case 0: break;
1329 default: vpanic("getRegUsage_AMD64Instr:Call:regparms");
1330 }
1331 /* Finally, there is the issue that the insn trashes a
1332 register because the literal target address has to be
1333 loaded into a register. Fortunately, r11 is stated in the
1334 ABI as a scratch register, and so seems a suitable victim. */
1335 addHRegUse(u, HRmWrite, hregAMD64_R11());
1336 /* Upshot of this is that the assembler really must use r11,
1337 and no other, as a destination temporary. */
1338 return;
sewardjf67eadf2005-02-03 03:53:52 +00001339 case Ain_Goto:
1340 addRegUsage_AMD64RI(u, i->Ain.Goto.dst);
1341 addHRegUse(u, HRmWrite, hregAMD64_RAX());
1342 if (i->Ain.Goto.jk != Ijk_Boring)
1343 addHRegUse(u, HRmWrite, hregAMD64_RBP());
1344 return;
sewardj05b3b6a2005-02-04 01:44:33 +00001345 case Ain_CMov64:
1346 addRegUsage_AMD64RM(u, i->Ain.CMov64.src, HRmRead);
1347 addHRegUse(u, HRmModify, i->Ain.CMov64.dst);
1348 return;
sewardjf67eadf2005-02-03 03:53:52 +00001349 case Ain_MovZLQ:
1350 addHRegUse(u, HRmRead, i->Ain.MovZLQ.src);
1351 addHRegUse(u, HRmWrite, i->Ain.MovZLQ.dst);
1352 return;
1353 case Ain_LoadEX:
1354 addRegUsage_AMD64AMode(u, i->Ain.LoadEX.src);
1355 addHRegUse(u, HRmWrite, i->Ain.LoadEX.dst);
1356 return;
sewardj05b3b6a2005-02-04 01:44:33 +00001357 case Ain_Store:
1358 addHRegUse(u, HRmRead, i->Ain.Store.src);
1359 addRegUsage_AMD64AMode(u, i->Ain.Store.dst);
1360 return;
sewardja3e98302005-02-01 15:55:05 +00001361//.. case Xin_Set32:
1362//.. addHRegUse(u, HRmWrite, i->Xin.Set32.dst);
1363//.. return;
1364//.. case Xin_Bsfr32:
1365//.. addHRegUse(u, HRmRead, i->Xin.Bsfr32.src);
1366//.. addHRegUse(u, HRmWrite, i->Xin.Bsfr32.dst);
1367//.. return;
1368//.. case Xin_MFence:
1369//.. return;
1370//.. case Xin_FpUnary:
1371//.. addHRegUse(u, HRmRead, i->Xin.FpUnary.src);
1372//.. addHRegUse(u, HRmWrite, i->Xin.FpUnary.dst);
1373//.. return;
1374//.. case Xin_FpBinary:
1375//.. addHRegUse(u, HRmRead, i->Xin.FpBinary.srcL);
1376//.. addHRegUse(u, HRmRead, i->Xin.FpBinary.srcR);
1377//.. addHRegUse(u, HRmWrite, i->Xin.FpBinary.dst);
1378//.. return;
1379//.. case Xin_FpLdSt:
sewardj614b3fb2005-02-02 02:16:03 +00001380//.. addRegUsage_AMD64AMode(u, i->Xin.FpLdSt.addr);
sewardja3e98302005-02-01 15:55:05 +00001381//.. addHRegUse(u, i->Xin.FpLdSt.isLoad ? HRmWrite : HRmRead,
1382//.. i->Xin.FpLdSt.reg);
1383//.. return;
1384//.. case Xin_FpLdStI:
sewardj614b3fb2005-02-02 02:16:03 +00001385//.. addRegUsage_AMD64AMode(u, i->Xin.FpLdStI.addr);
sewardja3e98302005-02-01 15:55:05 +00001386//.. addHRegUse(u, i->Xin.FpLdStI.isLoad ? HRmWrite : HRmRead,
1387//.. i->Xin.FpLdStI.reg);
1388//.. return;
1389//.. case Xin_Fp64to32:
1390//.. addHRegUse(u, HRmRead, i->Xin.Fp64to32.src);
1391//.. addHRegUse(u, HRmWrite, i->Xin.Fp64to32.dst);
1392//.. return;
1393//.. case Xin_FpCMov:
1394//.. addHRegUse(u, HRmRead, i->Xin.FpCMov.src);
1395//.. addHRegUse(u, HRmModify, i->Xin.FpCMov.dst);
1396//.. return;
1397//.. case Xin_FpLdStCW:
sewardj614b3fb2005-02-02 02:16:03 +00001398//.. addRegUsage_AMD64AMode(u, i->Xin.FpLdStCW.addr);
sewardja3e98302005-02-01 15:55:05 +00001399//.. return;
1400//.. case Xin_FpStSW_AX:
sewardj614b3fb2005-02-02 02:16:03 +00001401//.. addHRegUse(u, HRmWrite, hregAMD64_EAX());
sewardja3e98302005-02-01 15:55:05 +00001402//.. return;
1403//.. case Xin_FpCmp:
1404//.. addHRegUse(u, HRmRead, i->Xin.FpCmp.srcL);
1405//.. addHRegUse(u, HRmRead, i->Xin.FpCmp.srcR);
1406//.. addHRegUse(u, HRmWrite, i->Xin.FpCmp.dst);
sewardj614b3fb2005-02-02 02:16:03 +00001407//.. addHRegUse(u, HRmWrite, hregAMD64_EAX());
sewardja3e98302005-02-01 15:55:05 +00001408//.. return;
1409//.. case Xin_SseLdSt:
sewardj614b3fb2005-02-02 02:16:03 +00001410//.. addRegUsage_AMD64AMode(u, i->Xin.SseLdSt.addr);
sewardja3e98302005-02-01 15:55:05 +00001411//.. addHRegUse(u, i->Xin.SseLdSt.isLoad ? HRmWrite : HRmRead,
1412//.. i->Xin.SseLdSt.reg);
1413//.. return;
1414//.. case Xin_SseLdzLO:
sewardj614b3fb2005-02-02 02:16:03 +00001415//.. addRegUsage_AMD64AMode(u, i->Xin.SseLdzLO.addr);
sewardja3e98302005-02-01 15:55:05 +00001416//.. addHRegUse(u, HRmWrite, i->Xin.SseLdzLO.reg);
1417//.. return;
1418//.. case Xin_SseConst:
1419//.. addHRegUse(u, HRmWrite, i->Xin.SseConst.dst);
1420//.. return;
1421//.. case Xin_Sse32Fx4:
1422//.. vassert(i->Xin.Sse32Fx4.op != Xsse_MOV);
1423//.. unary = i->Xin.Sse32Fx4.op == Xsse_RCPF
1424//.. || i->Xin.Sse32Fx4.op == Xsse_RSQRTF
1425//.. || i->Xin.Sse32Fx4.op == Xsse_SQRTF;
1426//.. addHRegUse(u, HRmRead, i->Xin.Sse32Fx4.src);
1427//.. addHRegUse(u, unary ? HRmWrite : HRmModify,
1428//.. i->Xin.Sse32Fx4.dst);
1429//.. return;
1430//.. case Xin_Sse32FLo:
1431//.. vassert(i->Xin.Sse32FLo.op != Xsse_MOV);
1432//.. unary = i->Xin.Sse32FLo.op == Xsse_RCPF
1433//.. || i->Xin.Sse32FLo.op == Xsse_RSQRTF
1434//.. || i->Xin.Sse32FLo.op == Xsse_SQRTF;
1435//.. addHRegUse(u, HRmRead, i->Xin.Sse32FLo.src);
1436//.. addHRegUse(u, unary ? HRmWrite : HRmModify,
1437//.. i->Xin.Sse32FLo.dst);
1438//.. return;
1439//.. case Xin_Sse64Fx2:
1440//.. vassert(i->Xin.Sse64Fx2.op != Xsse_MOV);
1441//.. unary = i->Xin.Sse64Fx2.op == Xsse_RCPF
1442//.. || i->Xin.Sse64Fx2.op == Xsse_RSQRTF
1443//.. || i->Xin.Sse64Fx2.op == Xsse_SQRTF;
1444//.. addHRegUse(u, HRmRead, i->Xin.Sse64Fx2.src);
1445//.. addHRegUse(u, unary ? HRmWrite : HRmModify,
1446//.. i->Xin.Sse64Fx2.dst);
1447//.. return;
1448//.. case Xin_Sse64FLo:
1449//.. vassert(i->Xin.Sse64FLo.op != Xsse_MOV);
1450//.. unary = i->Xin.Sse64FLo.op == Xsse_RCPF
1451//.. || i->Xin.Sse64FLo.op == Xsse_RSQRTF
1452//.. || i->Xin.Sse64FLo.op == Xsse_SQRTF;
1453//.. addHRegUse(u, HRmRead, i->Xin.Sse64FLo.src);
1454//.. addHRegUse(u, unary ? HRmWrite : HRmModify,
1455//.. i->Xin.Sse64FLo.dst);
1456//.. return;
1457//.. case Xin_SseReRg:
1458//.. if (i->Xin.SseReRg.op == Xsse_XOR
1459//.. && i->Xin.SseReRg.src == i->Xin.SseReRg.dst) {
1460//.. /* reg-alloc needs to understand 'xor r,r' as a write of r */
1461//.. /* (as opposed to a rite of passage :-) */
1462//.. addHRegUse(u, HRmWrite, i->Xin.SseReRg.dst);
1463//.. } else {
1464//.. addHRegUse(u, HRmRead, i->Xin.SseReRg.src);
1465//.. addHRegUse(u, i->Xin.SseReRg.op == Xsse_MOV
1466//.. ? HRmWrite : HRmModify,
1467//.. i->Xin.SseReRg.dst);
1468//.. }
1469//.. return;
1470//.. case Xin_SseCMov:
1471//.. addHRegUse(u, HRmRead, i->Xin.SseCMov.src);
1472//.. addHRegUse(u, HRmModify, i->Xin.SseCMov.dst);
1473//.. return;
1474//.. case Xin_SseShuf:
1475//.. addHRegUse(u, HRmRead, i->Xin.SseShuf.src);
1476//.. addHRegUse(u, HRmWrite, i->Xin.SseShuf.dst);
1477//.. return;
sewardjc33671d2005-02-01 20:30:00 +00001478 default:
1479 ppAMD64Instr(i);
1480 vpanic("getRegUsage_AMD64Instr");
1481 }
1482}
sewardjf67eadf2005-02-03 03:53:52 +00001483
1484/* local helper */
1485static void mapReg(HRegRemap* m, HReg* r)
1486{
1487 *r = lookupHRegRemap(m, *r);
1488}
sewardjc33671d2005-02-01 20:30:00 +00001489
1490void mapRegs_AMD64Instr ( HRegRemap* m, AMD64Instr* i )
1491{
1492 switch (i->tag) {
sewardj813ce9e2005-02-04 21:16:48 +00001493 case Ain_Imm64:
1494 mapReg(m, &i->Ain.Imm64.dst);
1495 return;
sewardjf67eadf2005-02-03 03:53:52 +00001496 case Ain_Alu64R:
1497 mapRegs_AMD64RMI(m, i->Ain.Alu64R.src);
1498 mapReg(m, &i->Ain.Alu64R.dst);
1499 return;
1500 case Ain_Alu64M:
1501 mapRegs_AMD64RI(m, i->Ain.Alu64M.src);
1502 mapRegs_AMD64AMode(m, i->Ain.Alu64M.dst);
1503 return;
1504 case Ain_Sh64:
1505 mapRegs_AMD64RM(m, i->Ain.Sh64.dst);
1506 return;
sewardj05b3b6a2005-02-04 01:44:33 +00001507 case Ain_Test64:
1508 mapRegs_AMD64RI(m, i->Ain.Test64.src);
1509 mapRegs_AMD64RM(m, i->Ain.Test64.dst);
1510 return;
sewardja3e98302005-02-01 15:55:05 +00001511//.. case Xin_Unary32:
sewardj614b3fb2005-02-02 02:16:03 +00001512//.. mapRegs_AMD64RM(m, i->Xin.Unary32.dst);
sewardja3e98302005-02-01 15:55:05 +00001513//.. return;
1514//.. case Xin_MulL:
sewardj614b3fb2005-02-02 02:16:03 +00001515//.. mapRegs_AMD64RM(m, i->Xin.MulL.src);
sewardja3e98302005-02-01 15:55:05 +00001516//.. return;
1517//.. case Xin_Div:
sewardj614b3fb2005-02-02 02:16:03 +00001518//.. mapRegs_AMD64RM(m, i->Xin.Div.src);
sewardja3e98302005-02-01 15:55:05 +00001519//.. return;
1520//.. case Xin_Sh3232:
1521//.. mapReg(m, &i->Xin.Sh3232.src);
1522//.. mapReg(m, &i->Xin.Sh3232.dst);
1523//.. return;
1524//.. case Xin_Push:
sewardj614b3fb2005-02-02 02:16:03 +00001525//.. mapRegs_AMD64RMI(m, i->Xin.Push.src);
sewardja3e98302005-02-01 15:55:05 +00001526//.. return;
sewardj05b3b6a2005-02-04 01:44:33 +00001527 case Ain_Call:
1528 return;
sewardjf67eadf2005-02-03 03:53:52 +00001529 case Ain_Goto:
1530 mapRegs_AMD64RI(m, i->Ain.Goto.dst);
1531 return;
sewardj05b3b6a2005-02-04 01:44:33 +00001532 case Ain_CMov64:
1533 mapRegs_AMD64RM(m, i->Ain.CMov64.src);
1534 mapReg(m, &i->Ain.CMov64.dst);
1535 return;
sewardjf67eadf2005-02-03 03:53:52 +00001536 case Ain_MovZLQ:
1537 mapReg(m, &i->Ain.MovZLQ.src);
1538 mapReg(m, &i->Ain.MovZLQ.dst);
1539 return;
1540 case Ain_LoadEX:
1541 mapRegs_AMD64AMode(m, i->Ain.LoadEX.src);
1542 mapReg(m, &i->Ain.LoadEX.dst);
1543 return;
sewardj05b3b6a2005-02-04 01:44:33 +00001544 case Ain_Store:
1545 mapReg(m, &i->Ain.Store.src);
1546 mapRegs_AMD64AMode(m, i->Ain.Store.dst);
1547 return;
sewardja3e98302005-02-01 15:55:05 +00001548//.. case Xin_Set32:
1549//.. mapReg(m, &i->Xin.Set32.dst);
1550//.. return;
1551//.. case Xin_Bsfr32:
1552//.. mapReg(m, &i->Xin.Bsfr32.src);
1553//.. mapReg(m, &i->Xin.Bsfr32.dst);
1554//.. return;
1555//.. case Xin_MFence:
1556//.. return;
1557//.. case Xin_FpUnary:
1558//.. mapReg(m, &i->Xin.FpUnary.src);
1559//.. mapReg(m, &i->Xin.FpUnary.dst);
1560//.. return;
1561//.. case Xin_FpBinary:
1562//.. mapReg(m, &i->Xin.FpBinary.srcL);
1563//.. mapReg(m, &i->Xin.FpBinary.srcR);
1564//.. mapReg(m, &i->Xin.FpBinary.dst);
1565//.. return;
1566//.. case Xin_FpLdSt:
sewardj614b3fb2005-02-02 02:16:03 +00001567//.. mapRegs_AMD64AMode(m, i->Xin.FpLdSt.addr);
sewardja3e98302005-02-01 15:55:05 +00001568//.. mapReg(m, &i->Xin.FpLdSt.reg);
1569//.. return;
1570//.. case Xin_FpLdStI:
sewardj614b3fb2005-02-02 02:16:03 +00001571//.. mapRegs_AMD64AMode(m, i->Xin.FpLdStI.addr);
sewardja3e98302005-02-01 15:55:05 +00001572//.. mapReg(m, &i->Xin.FpLdStI.reg);
1573//.. return;
1574//.. case Xin_Fp64to32:
1575//.. mapReg(m, &i->Xin.Fp64to32.src);
1576//.. mapReg(m, &i->Xin.Fp64to32.dst);
1577//.. return;
1578//.. case Xin_FpCMov:
1579//.. mapReg(m, &i->Xin.FpCMov.src);
1580//.. mapReg(m, &i->Xin.FpCMov.dst);
1581//.. return;
1582//.. case Xin_FpLdStCW:
sewardj614b3fb2005-02-02 02:16:03 +00001583//.. mapRegs_AMD64AMode(m, i->Xin.FpLdStCW.addr);
sewardja3e98302005-02-01 15:55:05 +00001584//.. return;
1585//.. case Xin_FpStSW_AX:
1586//.. return;
1587//.. case Xin_FpCmp:
1588//.. mapReg(m, &i->Xin.FpCmp.srcL);
1589//.. mapReg(m, &i->Xin.FpCmp.srcR);
1590//.. mapReg(m, &i->Xin.FpCmp.dst);
1591//.. return;
1592//.. case Xin_SseConst:
1593//.. mapReg(m, &i->Xin.SseConst.dst);
1594//.. return;
1595//.. case Xin_SseLdSt:
1596//.. mapReg(m, &i->Xin.SseLdSt.reg);
sewardj614b3fb2005-02-02 02:16:03 +00001597//.. mapRegs_AMD64AMode(m, i->Xin.SseLdSt.addr);
sewardja3e98302005-02-01 15:55:05 +00001598//.. break;
1599//.. case Xin_SseLdzLO:
1600//.. mapReg(m, &i->Xin.SseLdzLO.reg);
sewardj614b3fb2005-02-02 02:16:03 +00001601//.. mapRegs_AMD64AMode(m, i->Xin.SseLdzLO.addr);
sewardja3e98302005-02-01 15:55:05 +00001602//.. break;
1603//.. case Xin_Sse32Fx4:
1604//.. mapReg(m, &i->Xin.Sse32Fx4.src);
1605//.. mapReg(m, &i->Xin.Sse32Fx4.dst);
1606//.. return;
1607//.. case Xin_Sse32FLo:
1608//.. mapReg(m, &i->Xin.Sse32FLo.src);
1609//.. mapReg(m, &i->Xin.Sse32FLo.dst);
1610//.. return;
1611//.. case Xin_Sse64Fx2:
1612//.. mapReg(m, &i->Xin.Sse64Fx2.src);
1613//.. mapReg(m, &i->Xin.Sse64Fx2.dst);
1614//.. return;
1615//.. case Xin_Sse64FLo:
1616//.. mapReg(m, &i->Xin.Sse64FLo.src);
1617//.. mapReg(m, &i->Xin.Sse64FLo.dst);
1618//.. return;
1619//.. case Xin_SseReRg:
1620//.. mapReg(m, &i->Xin.SseReRg.src);
1621//.. mapReg(m, &i->Xin.SseReRg.dst);
1622//.. return;
1623//.. case Xin_SseCMov:
1624//.. mapReg(m, &i->Xin.SseCMov.src);
1625//.. mapReg(m, &i->Xin.SseCMov.dst);
1626//.. return;
1627//.. case Xin_SseShuf:
1628//.. mapReg(m, &i->Xin.SseShuf.src);
1629//.. mapReg(m, &i->Xin.SseShuf.dst);
1630//.. return;
sewardjc33671d2005-02-01 20:30:00 +00001631 default:
1632 ppAMD64Instr(i);
1633 vpanic("mapRegs_AMD64Instr");
1634 }
1635}
1636
1637/* Figure out if i represents a reg-reg move, and if so assign the
1638 source and destination to *src and *dst. If in doubt say No. Used
1639 by the register allocator to do move coalescing.
1640*/
1641Bool isMove_AMD64Instr ( AMD64Instr* i, HReg* src, HReg* dst )
1642{
sewardjf67eadf2005-02-03 03:53:52 +00001643 /* Moves between integer regs */
1644 if (i->tag == Ain_Alu64R) {
1645 if (i->Ain.Alu64R.op != Aalu_MOV)
1646 return False;
1647 if (i->Ain.Alu64R.src->tag != Armi_Reg)
1648 return False;
1649 *src = i->Ain.Alu64R.src->Armi.Reg.reg;
1650 *dst = i->Ain.Alu64R.dst;
1651 return True;
1652 }
sewardja3e98302005-02-01 15:55:05 +00001653//.. /* Moves between FP regs */
1654//.. if (i->tag == Xin_FpUnary) {
1655//.. if (i->Xin.FpUnary.op != Xfp_MOV)
1656//.. return False;
1657//.. *src = i->Xin.FpUnary.src;
1658//.. *dst = i->Xin.FpUnary.dst;
1659//.. return True;
1660//.. }
1661//.. if (i->tag == Xin_SseReRg) {
1662//.. if (i->Xin.SseReRg.op != Xsse_MOV)
1663//.. return False;
1664//.. *src = i->Xin.SseReRg.src;
1665//.. *dst = i->Xin.SseReRg.dst;
1666//.. return True;
1667//.. }
sewardjc33671d2005-02-01 20:30:00 +00001668 return False;
1669}
1670
1671
1672/* Generate amd64 spill/reload instructions under the direction of the
1673 register allocator. Note it's critical these don't write the
1674 condition codes. */
1675
1676AMD64Instr* genSpill_AMD64 ( HReg rreg, Int offsetB )
1677{vassert(0);
sewardj614b3fb2005-02-02 02:16:03 +00001678//.. AMD64AMode* am;
sewardja3e98302005-02-01 15:55:05 +00001679//.. vassert(offsetB >= 0);
1680//.. vassert(!hregIsVirtual(rreg));
sewardj614b3fb2005-02-02 02:16:03 +00001681//.. am = AMD64AMode_IR(offsetB, hregAMD64_EBP());
sewardja3e98302005-02-01 15:55:05 +00001682//..
1683//.. switch (hregClass(rreg)) {
1684//.. case HRcInt32:
sewardj614b3fb2005-02-02 02:16:03 +00001685//.. return AMD64Instr_Alu32M ( Xalu_MOV, AMD64RI_Reg(rreg), am );
sewardja3e98302005-02-01 15:55:05 +00001686//.. case HRcFlt64:
sewardj614b3fb2005-02-02 02:16:03 +00001687//.. return AMD64Instr_FpLdSt ( False/*store*/, 8, rreg, am );
sewardja3e98302005-02-01 15:55:05 +00001688//.. case HRcVec128:
sewardj614b3fb2005-02-02 02:16:03 +00001689//.. return AMD64Instr_SseLdSt ( False/*store*/, rreg, am );
sewardja3e98302005-02-01 15:55:05 +00001690//.. default:
1691//.. ppHRegClass(hregClass(rreg));
sewardj614b3fb2005-02-02 02:16:03 +00001692//.. vpanic("genSpill_AMD64: unimplemented regclass");
sewardja3e98302005-02-01 15:55:05 +00001693//.. }
sewardjc33671d2005-02-01 20:30:00 +00001694}
1695
1696AMD64Instr* genReload_AMD64 ( HReg rreg, Int offsetB )
1697{vassert(0);
sewardj614b3fb2005-02-02 02:16:03 +00001698//.. AMD64AMode* am;
sewardja3e98302005-02-01 15:55:05 +00001699//.. vassert(offsetB >= 0);
1700//.. vassert(!hregIsVirtual(rreg));
sewardj614b3fb2005-02-02 02:16:03 +00001701//.. am = AMD64AMode_IR(offsetB, hregAMD64_EBP());
sewardja3e98302005-02-01 15:55:05 +00001702//.. switch (hregClass(rreg)) {
1703//.. case HRcInt32:
sewardj614b3fb2005-02-02 02:16:03 +00001704//.. return AMD64Instr_Alu32R ( Xalu_MOV, AMD64RMI_Mem(am), rreg );
sewardja3e98302005-02-01 15:55:05 +00001705//.. case HRcFlt64:
sewardj614b3fb2005-02-02 02:16:03 +00001706//.. return AMD64Instr_FpLdSt ( True/*load*/, 8, rreg, am );
sewardja3e98302005-02-01 15:55:05 +00001707//.. case HRcVec128:
sewardj614b3fb2005-02-02 02:16:03 +00001708//.. return AMD64Instr_SseLdSt ( True/*load*/, rreg, am );
sewardja3e98302005-02-01 15:55:05 +00001709//.. default:
1710//.. ppHRegClass(hregClass(rreg));
sewardj614b3fb2005-02-02 02:16:03 +00001711//.. vpanic("genReload_AMD64: unimplemented regclass");
sewardja3e98302005-02-01 15:55:05 +00001712//.. }
sewardjc33671d2005-02-01 20:30:00 +00001713}
1714
1715
sewardj813ce9e2005-02-04 21:16:48 +00001716/* --------- The amd64 assembler (bleh.) --------- */
1717
1718/* Produce the low three bits of an integer register number. */
1719static UInt iregNo ( HReg r )
1720{
1721 UInt n;
1722 vassert(hregClass(r) == HRcInt64);
1723 vassert(!hregIsVirtual(r));
1724 n = hregNumber(r);
1725 vassert(n <= 15);
1726 return n & 7;
1727}
1728
1729/* Produce bit 3 of an integer register number. */
1730static UInt iregBit3 ( HReg r )
1731{
1732 UInt n;
1733 vassert(hregClass(r) == HRcInt64);
1734 vassert(!hregIsVirtual(r));
1735 n = hregNumber(r);
1736 vassert(n <= 15);
1737 return (n >> 3) & 1;
1738}
1739
1740
sewardja3e98302005-02-01 15:55:05 +00001741//.. static UInt fregNo ( HReg r )
1742//.. {
1743//.. UInt n;
1744//.. vassert(hregClass(r) == HRcFlt64);
1745//.. vassert(!hregIsVirtual(r));
1746//.. n = hregNumber(r);
1747//.. vassert(n <= 5);
1748//.. return n;
1749//.. }
1750//..
1751//.. static UInt vregNo ( HReg r )
1752//.. {
1753//.. UInt n;
1754//.. vassert(hregClass(r) == HRcVec128);
1755//.. vassert(!hregIsVirtual(r));
1756//.. n = hregNumber(r);
1757//.. vassert(n <= 7);
1758//.. return n;
1759//.. }
sewardj813ce9e2005-02-04 21:16:48 +00001760
1761static UChar mkModRegRM ( UChar mod, UChar reg, UChar regmem )
1762{
1763 return ((mod & 3) << 6) | ((reg & 7) << 3) | (regmem & 7);
1764}
1765
1766static UChar mkSIB ( Int shift, Int regindex, Int regbase )
1767{
1768 return ((shift & 3) << 6) | ((regindex & 7) << 3) | (regbase & 7);
1769}
1770
1771static UChar* emit32 ( UChar* p, UInt w32 )
1772{
1773 *p++ = (w32) & 0x000000FF;
1774 *p++ = (w32 >> 8) & 0x000000FF;
1775 *p++ = (w32 >> 16) & 0x000000FF;
1776 *p++ = (w32 >> 24) & 0x000000FF;
1777 return p;
1778}
1779
sewardj1b8d58e2005-02-05 14:34:18 +00001780static UChar* emit64 ( UChar* p, ULong w64 )
1781{
1782 p = emit32(p, (UInt)(w64 & 0xFFFFFFFF));
1783 p = emit32(p, (UInt)((w64 >> 32) & 0xFFFFFFFF));
1784 return p;
1785}
1786
sewardj813ce9e2005-02-04 21:16:48 +00001787/* Does a sign-extend of the lowest 8 bits give
1788 the original number? */
1789static Bool fits8bits ( UInt w32 )
1790{
1791 Int i32 = (Int)w32;
1792 return i32 == ((i32 << 24) >> 24);
1793}
1794
1795
1796/* Forming mod-reg-rm bytes and scale-index-base bytes.
1797
1798 greg, 0(ereg) | ereg != RSP && ereg != RBP
1799 = 00 greg ereg
1800
1801 greg, d8(ereg) | ereg != RSP
1802 = 01 greg ereg, d8
1803
1804 greg, d32(ereg) | ereg != RSP
1805 = 10 greg ereg, d32
1806
1807 greg, d8(%rsp) = 01 greg 100, 0x24, d8
1808
1809 -----------------------------------------------
1810
1811 greg, d8(base,index,scale)
1812 | index != RSP
1813 = 01 greg 100, scale index base, d8
1814
1815 greg, d32(base,index,scale)
1816 | index != RSP
1817 = 10 greg 100, scale index base, d32
1818*/
1819static UChar* doAMode_M ( UChar* p, HReg greg, AMD64AMode* am )
1820{
1821 if (am->tag == Aam_IR) {
1822 if (am->Aam.IR.imm == 0
1823 && am->Aam.IR.reg != hregAMD64_RSP()
1824 && am->Aam.IR.reg != hregAMD64_RBP() ) {
1825 *p++ = mkModRegRM(0, iregNo(greg), iregNo(am->Aam.IR.reg));
1826 return p;
1827 }
1828 if (fits8bits(am->Aam.IR.imm)
1829 && am->Aam.IR.reg != hregAMD64_RSP()) {
1830 *p++ = mkModRegRM(1, iregNo(greg), iregNo(am->Aam.IR.reg));
1831 *p++ = am->Aam.IR.imm & 0xFF;
1832 return p;
1833 }
1834 if (am->Aam.IR.reg != hregAMD64_RSP()) {
1835 *p++ = mkModRegRM(2, iregNo(greg), iregNo(am->Aam.IR.reg));
1836 p = emit32(p, am->Aam.IR.imm);
1837 return p;
1838 }
1839 if (am->Aam.IR.reg == hregAMD64_RSP()
1840 && fits8bits(am->Aam.IR.imm)) {
1841 *p++ = mkModRegRM(1, iregNo(greg), 4);
1842 *p++ = 0x24;
1843 *p++ = am->Aam.IR.imm & 0xFF;
1844 return p;
1845 }
1846 ppAMD64AMode(am);
1847 vpanic("doAMode_M: can't emit amode IR");
1848 /*NOTREACHED*/
1849 }
1850 if (am->tag == Aam_IRRS) {
1851 if (fits8bits(am->Aam.IRRS.imm)
1852 && am->Aam.IRRS.index != hregAMD64_RSP()) {
1853 *p++ = mkModRegRM(1, iregNo(greg), 4);
1854 *p++ = mkSIB(am->Aam.IRRS.shift, am->Aam.IRRS.index,
1855 am->Aam.IRRS.base);
1856 *p++ = am->Aam.IRRS.imm & 0xFF;
1857 return p;
1858 }
1859 if (am->Aam.IRRS.index != hregAMD64_RSP()) {
1860 *p++ = mkModRegRM(2, iregNo(greg), 4);
1861 *p++ = mkSIB(am->Aam.IRRS.shift, am->Aam.IRRS.index,
1862 am->Aam.IRRS.base);
1863 p = emit32(p, am->Aam.IRRS.imm);
1864 return p;
1865 }
1866 ppAMD64AMode(am);
1867 vpanic("doAMode_M: can't emit amode IRRS");
1868 /*NOTREACHED*/
1869 }
1870 vpanic("doAMode_M: unknown amode");
1871 /*NOTREACHED*/
1872}
1873
1874
1875/* Emit a mod-reg-rm byte when the rm bit denotes a reg. */
1876static UChar* doAMode_R ( UChar* p, HReg greg, HReg ereg )
1877{
1878 *p++ = mkModRegRM(3, iregNo(greg), iregNo(ereg));
1879 return p;
1880}
1881
1882
sewardj549e0642005-02-05 12:00:14 +00001883/* Clear the W bit on a REX byte, thereby changing the operand size
1884 back to whatever that instruction's default operand size is. */
1885static inline UChar clearWBit ( UChar rex )
1886{
1887 return rex & ~(1<<3);
1888}
1889
1890
1891/* Make up a REX byte, with W=1 (size=64), for a (greg,amode) pair. */
1892static UChar rexAMode_M ( HReg greg, AMD64AMode* am )
sewardj813ce9e2005-02-04 21:16:48 +00001893{
1894 if (am->tag == Aam_IR) {
1895 UChar W = 1; /* we want 64-bit mode */
sewardj549e0642005-02-05 12:00:14 +00001896 UChar R = iregBit3(greg);
sewardj813ce9e2005-02-04 21:16:48 +00001897 UChar X = 0; /* not relevant */
sewardj549e0642005-02-05 12:00:14 +00001898 UChar B = iregBit3(am->Aam.IR.reg);
sewardj813ce9e2005-02-04 21:16:48 +00001899 return 0x40 + ((W << 3) | (R << 2) | (X << 1) | (B << 0));
1900 }
1901 if (am->tag == Aam_IRRS) {
1902 UChar W = 1; /* we want 64-bit mode */
sewardj549e0642005-02-05 12:00:14 +00001903 UChar R = iregBit3(greg);
1904 UChar X = iregBit3(am->Aam.IRRS.index);
1905 UChar B = iregBit3(am->Aam.IRRS.base);
sewardj813ce9e2005-02-04 21:16:48 +00001906 return 0x40 + ((W << 3) | (R << 2) | (X << 1) | (B << 0));
1907 }
1908 vassert(0);
1909}
1910
sewardj549e0642005-02-05 12:00:14 +00001911/* Make up a REX byte, with W=1 (size=64), for a (greg,ereg) pair. */
1912static UChar rexAMode_R ( HReg greg, HReg ereg )
1913{
1914 UChar W = 1; /* we want 64-bit mode */
1915 UChar R = iregBit3(greg);
1916 UChar X = 0; /* not relevant */
1917 UChar B = iregBit3(ereg);
1918 return 0x40 + ((W << 3) | (R << 2) | (X << 1) | (B << 0));
1919}
1920
sewardj813ce9e2005-02-04 21:16:48 +00001921
sewardja3e98302005-02-01 15:55:05 +00001922//.. /* Emit ffree %st(7) */
1923//.. static UChar* do_ffree_st7 ( UChar* p )
1924//.. {
1925//.. *p++ = 0xDD;
1926//.. *p++ = 0xC7;
1927//.. return p;
1928//.. }
1929//..
1930//.. /* Emit fstp %st(i), 1 <= i <= 7 */
1931//.. static UChar* do_fstp_st ( UChar* p, Int i )
1932//.. {
1933//.. vassert(1 <= i && i <= 7);
1934//.. *p++ = 0xDD;
1935//.. *p++ = 0xD8+i;
1936//.. return p;
1937//.. }
1938//..
1939//.. /* Emit fld %st(i), 0 <= i <= 6 */
1940//.. static UChar* do_fld_st ( UChar* p, Int i )
1941//.. {
1942//.. vassert(0 <= i && i <= 6);
1943//.. *p++ = 0xD9;
1944//.. *p++ = 0xC0+i;
1945//.. return p;
1946//.. }
1947//..
1948//.. /* Emit f<op> %st(0) */
sewardj614b3fb2005-02-02 02:16:03 +00001949//.. static UChar* do_fop1_st ( UChar* p, AMD64FpOp op )
sewardja3e98302005-02-01 15:55:05 +00001950//.. {
1951//.. switch (op) {
1952//.. case Xfp_NEG: *p++ = 0xD9; *p++ = 0xE0; break;
1953//.. case Xfp_ABS: *p++ = 0xD9; *p++ = 0xE1; break;
1954//.. case Xfp_SQRT: *p++ = 0xD9; *p++ = 0xFA; break;
1955//.. case Xfp_ROUND: *p++ = 0xD9; *p++ = 0xFC; break;
1956//.. case Xfp_SIN: *p++ = 0xD9; *p++ = 0xFE; break;
1957//.. case Xfp_COS: *p++ = 0xD9; *p++ = 0xFF; break;
1958//.. case Xfp_2XM1: *p++ = 0xD9; *p++ = 0xF0; break;
1959//.. case Xfp_MOV: break;
1960//.. case Xfp_TAN: p = do_ffree_st7(p); /* since fptan pushes 1.0 */
1961//.. *p++ = 0xD9; *p++ = 0xF2; /* fptan */
1962//.. *p++ = 0xD9; *p++ = 0xF7; /* fincstp */
1963//.. break;
1964//.. default: vpanic("do_fop1_st: unknown op");
1965//.. }
1966//.. return p;
1967//.. }
1968//..
1969//.. /* Emit f<op> %st(i), 1 <= i <= 5 */
sewardj614b3fb2005-02-02 02:16:03 +00001970//.. static UChar* do_fop2_st ( UChar* p, AMD64FpOp op, Int i )
sewardja3e98302005-02-01 15:55:05 +00001971//.. {
1972//.. # define fake(_n) mkHReg((_n), HRcInt32, False)
1973//.. Int subopc;
1974//.. switch (op) {
1975//.. case Xfp_ADD: subopc = 0; break;
1976//.. case Xfp_SUB: subopc = 4; break;
1977//.. case Xfp_MUL: subopc = 1; break;
1978//.. case Xfp_DIV: subopc = 6; break;
1979//.. default: vpanic("do_fop2_st: unknown op");
1980//.. }
1981//.. *p++ = 0xD8;
1982//.. p = doAMode_R(p, fake(subopc), fake(i));
1983//.. return p;
1984//.. # undef fake
1985//.. }
1986//..
1987//.. /* Push a 32-bit word on the stack. The word depends on tags[3:0];
1988//.. each byte is either 0x00 or 0xFF depending on the corresponding bit in tags[].
1989//.. */
1990//.. static UChar* push_word_from_tags ( UChar* p, UShort tags )
1991//.. {
1992//.. UInt w;
1993//.. vassert(0 == (tags & ~0xF));
1994//.. if (tags == 0) {
1995//.. /* pushl $0x00000000 */
1996//.. *p++ = 0x6A;
1997//.. *p++ = 0x00;
1998//.. }
1999//.. else
2000//.. /* pushl $0xFFFFFFFF */
2001//.. if (tags == 0xF) {
2002//.. *p++ = 0x6A;
2003//.. *p++ = 0xFF;
2004//.. } else {
2005//.. vassert(0); /* awaiting test case */
2006//.. w = 0;
2007//.. if (tags & 1) w |= 0x000000FF;
2008//.. if (tags & 2) w |= 0x0000FF00;
2009//.. if (tags & 4) w |= 0x00FF0000;
2010//.. if (tags & 8) w |= 0xFF000000;
2011//.. *p++ = 0x68;
2012//.. p = emit32(p, w);
2013//.. }
2014//.. return p;
2015//.. }
sewardjc33671d2005-02-01 20:30:00 +00002016
2017/* Emit an instruction into buf and return the number of bytes used.
2018 Note that buf is not the insn's final place, and therefore it is
2019 imperative to emit position-independent code. */
2020
2021Int emit_AMD64Instr ( UChar* buf, Int nbuf, AMD64Instr* i )
2022{
sewardjc2bcb6f2005-02-07 00:17:12 +00002023 UInt /*irno,*/ opc, opc_rr, subopc_imm, opc_imma, opc_cl, opc_imm, subopc;
sewardja3e98302005-02-01 15:55:05 +00002024//..
2025//.. UInt xtra;
sewardjc33671d2005-02-01 20:30:00 +00002026 UChar* p = &buf[0];
sewardj549e0642005-02-05 12:00:14 +00002027 UChar* ptmp;
2028 vassert(nbuf >= 32);
2029
2030 /* Wrap an integer as a int register, for use assembling
2031 GrpN insns, in which the greg field is used as a sub-opcode
2032 and does not really contain a register. */
2033# define fake(_n) mkHReg((_n), HRcInt64, False)
2034
sewardj614b3fb2005-02-02 02:16:03 +00002035//.. /* vex_printf("asm ");ppAMD64Instr(i); vex_printf("\n"); */
sewardjc33671d2005-02-01 20:30:00 +00002036
2037 switch (i->tag) {
2038
sewardj1b8d58e2005-02-05 14:34:18 +00002039 case Ain_Imm64:
2040 *p++ = 0x48 + (1 & iregBit3(i->Ain.Imm64.dst));
2041 *p++ = 0xB8 + iregNo(i->Ain.Imm64.dst);
2042 p = emit64(p, i->Ain.Imm64.imm64);
2043 goto done;
2044
sewardj813ce9e2005-02-04 21:16:48 +00002045 case Ain_Alu64R:
2046 /* Deal specially with MOV */
2047 if (i->Ain.Alu64R.op == Aalu_MOV) {
2048 switch (i->Ain.Alu64R.src->tag) {
2049 case Armi_Imm:
sewardj1b8d58e2005-02-05 14:34:18 +00002050 *p++ = 0x48 + (1 & iregBit3(i->Ain.Alu64R.dst));
2051 *p++ = 0xC7;
2052 *p++ = 0xC0 + iregNo(i->Ain.Alu64R.dst);
sewardj813ce9e2005-02-04 21:16:48 +00002053 p = emit32(p, i->Ain.Alu64R.src->Armi.Imm.imm32);
2054 goto done;
2055 case Armi_Reg:
sewardj1b8d58e2005-02-05 14:34:18 +00002056 *p++ = rexAMode_R( i->Ain.Alu64R.src->Armi.Reg.reg,
2057 i->Ain.Alu64R.dst );
sewardj813ce9e2005-02-04 21:16:48 +00002058 *p++ = 0x89;
2059 p = doAMode_R(p, i->Ain.Alu64R.src->Armi.Reg.reg,
2060 i->Ain.Alu64R.dst);
2061 goto done;
2062 case Armi_Mem:
sewardj549e0642005-02-05 12:00:14 +00002063 *p++ = rexAMode_M(i->Ain.Alu64R.dst,
sewardj813ce9e2005-02-04 21:16:48 +00002064 i->Ain.Alu64R.src->Armi.Mem.am);
2065 *p++ = 0x8B;
2066 p = doAMode_M(p, i->Ain.Alu64R.dst,
2067 i->Ain.Alu64R.src->Armi.Mem.am);
2068 goto done;
2069 default:
2070 goto bad;
2071 }
2072 }
sewardja3e98302005-02-01 15:55:05 +00002073//.. /* MUL */
2074//.. if (i->Xin.Alu32R.op == Xalu_MUL) {
2075//.. switch (i->Xin.Alu32R.src->tag) {
2076//.. case Xrmi_Reg:
2077//.. *p++ = 0x0F;
2078//.. *p++ = 0xAF;
2079//.. p = doAMode_R(p, i->Xin.Alu32R.dst,
2080//.. i->Xin.Alu32R.src->Xrmi.Reg.reg);
2081//.. goto done;
2082//.. case Xrmi_Mem:
2083//.. *p++ = 0x0F;
2084//.. *p++ = 0xAF;
2085//.. p = doAMode_M(p, i->Xin.Alu32R.dst,
2086//.. i->Xin.Alu32R.src->Xrmi.Mem.am);
2087//.. goto done;
2088//.. case Xrmi_Imm:
2089//.. if (fits8bits(i->Xin.Alu32R.src->Xrmi.Imm.imm32)) {
2090//.. *p++ = 0x6B;
2091//.. p = doAMode_R(p, i->Xin.Alu32R.dst, i->Xin.Alu32R.dst);
2092//.. *p++ = 0xFF & i->Xin.Alu32R.src->Xrmi.Imm.imm32;
2093//.. } else {
2094//.. *p++ = 0x69;
2095//.. p = doAMode_R(p, i->Xin.Alu32R.dst, i->Xin.Alu32R.dst);
2096//.. p = emit32(p, i->Xin.Alu32R.src->Xrmi.Imm.imm32);
2097//.. }
2098//.. goto done;
2099//.. default:
2100//.. goto bad;
2101//.. }
2102//.. }
sewardj549e0642005-02-05 12:00:14 +00002103 /* ADD/SUB/ADC/SBB/AND/OR/XOR/CMP */
2104 opc = opc_rr = subopc_imm = opc_imma = 0;
2105 switch (i->Ain.Alu64R.op) {
2106 case Aalu_ADC: opc = 0x13; opc_rr = 0x11;
2107 subopc_imm = 2; opc_imma = 0x15; break;
2108 case Aalu_ADD: opc = 0x03; opc_rr = 0x01;
2109 subopc_imm = 0; opc_imma = 0x05; break;
2110 case Aalu_SUB: opc = 0x2B; opc_rr = 0x29;
2111 subopc_imm = 5; opc_imma = 0x2D; break;
2112 case Aalu_SBB: opc = 0x1B; opc_rr = 0x19;
2113 subopc_imm = 3; opc_imma = 0x1D; break;
2114 case Aalu_AND: opc = 0x23; opc_rr = 0x21;
2115 subopc_imm = 4; opc_imma = 0x25; break;
2116 case Aalu_XOR: opc = 0x33; opc_rr = 0x31;
2117 subopc_imm = 6; opc_imma = 0x35; break;
2118 case Aalu_OR: opc = 0x0B; opc_rr = 0x09;
2119 subopc_imm = 1; opc_imma = 0x0D; break;
2120 case Aalu_CMP: opc = 0x3B; opc_rr = 0x39;
2121 subopc_imm = 7; opc_imma = 0x3D; break;
2122 default: goto bad;
2123 }
2124 switch (i->Ain.Alu64R.src->tag) {
2125 case Armi_Imm:
2126 if (i->Ain.Alu64R.dst == hregAMD64_RAX()
2127 && !fits8bits(i->Ain.Alu64R.src->Armi.Imm.imm32)) {
2128vassert(0);
2129 *p++ = opc_imma;
2130 p = emit32(p, i->Ain.Alu64R.src->Armi.Imm.imm32);
2131 } else
2132 if (fits8bits(i->Ain.Alu64R.src->Armi.Imm.imm32)) {
2133 *p++ = rexAMode_R( fake(0), i->Ain.Alu64R.dst );
2134 *p++ = 0x83;
2135 p = doAMode_R(p, fake(subopc_imm), i->Ain.Alu64R.dst);
2136 *p++ = 0xFF & i->Ain.Alu64R.src->Armi.Imm.imm32;
2137 } else {
sewardj1b8d58e2005-02-05 14:34:18 +00002138 *p++ = rexAMode_R( fake(0), i->Ain.Alu64R.dst);
sewardj549e0642005-02-05 12:00:14 +00002139 *p++ = 0x81;
2140 p = doAMode_R(p, fake(subopc_imm), i->Ain.Alu64R.dst);
2141 p = emit32(p, i->Ain.Alu64R.src->Armi.Imm.imm32);
2142 }
2143 goto done;
2144 case Armi_Reg:
2145 *p++ = rexAMode_R( i->Ain.Alu64R.src->Armi.Reg.reg,
2146 i->Ain.Alu64R.dst);
2147 *p++ = opc_rr;
2148 p = doAMode_R(p, i->Ain.Alu64R.src->Armi.Reg.reg,
2149 i->Ain.Alu64R.dst);
2150 goto done;
2151 case Armi_Mem:
sewardj31191072005-02-05 18:24:47 +00002152 *p++ = rexAMode_M( i->Ain.Alu64R.dst,
2153 i->Ain.Alu64R.src->Armi.Mem.am);
sewardj549e0642005-02-05 12:00:14 +00002154 *p++ = opc;
2155 p = doAMode_M(p, i->Ain.Alu64R.dst,
2156 i->Ain.Alu64R.src->Armi.Mem.am);
2157 goto done;
2158 default:
2159 goto bad;
2160 }
sewardj813ce9e2005-02-04 21:16:48 +00002161 break;
2162
sewardj549e0642005-02-05 12:00:14 +00002163 case Ain_Alu64M:
2164 /* Deal specially with MOV */
2165 if (i->Ain.Alu64M.op == Aalu_MOV) {
2166 switch (i->Ain.Alu64M.src->tag) {
2167 case Ari_Reg:
2168 *p++ = rexAMode_M(i->Ain.Alu64M.src->Ari.Reg.reg,
2169 i->Ain.Alu64M.dst);
2170 *p++ = 0x89;
2171 p = doAMode_M(p, i->Ain.Alu64M.src->Ari.Reg.reg,
2172 i->Ain.Alu64M.dst);
2173 goto done;
2174 case Ari_Imm:
2175 *p++ = rexAMode_M(fake(0), i->Ain.Alu64M.dst);
2176 *p++ = 0xC7;
2177 p = doAMode_M(p, fake(0), i->Ain.Alu64M.dst);
2178 p = emit32(p, i->Ain.Alu64M.src->Ari.Imm.imm32);
2179 goto done;
2180 default:
2181 goto bad;
2182 }
2183 }
sewardja3e98302005-02-01 15:55:05 +00002184//.. /* ADD/SUB/ADC/SBB/AND/OR/XOR/CMP. MUL is not
2185//.. allowed here. */
2186//.. opc = subopc_imm = opc_imma = 0;
2187//.. switch (i->Xin.Alu32M.op) {
2188//.. case Xalu_ADD: opc = 0x01; subopc_imm = 0; break;
2189//.. case Xalu_SUB: opc = 0x29; subopc_imm = 5; break;
2190//.. default: goto bad;
2191//.. }
2192//.. switch (i->Xin.Alu32M.src->tag) {
2193//.. case Xri_Reg:
2194//.. *p++ = opc;
2195//.. p = doAMode_M(p, i->Xin.Alu32M.src->Xri.Reg.reg,
2196//.. i->Xin.Alu32M.dst);
2197//.. goto done;
2198//.. case Xri_Imm:
2199//.. if (fits8bits(i->Xin.Alu32M.src->Xri.Imm.imm32)) {
2200//.. *p++ = 0x83;
2201//.. p = doAMode_M(p, fake(subopc_imm), i->Xin.Alu32M.dst);
2202//.. *p++ = 0xFF & i->Xin.Alu32M.src->Xri.Imm.imm32;
2203//.. goto done;
2204//.. } else {
2205//.. *p++ = 0x81;
2206//.. p = doAMode_M(p, fake(subopc_imm), i->Xin.Alu32M.dst);
2207//.. p = emit32(p, i->Xin.Alu32M.src->Xri.Imm.imm32);
2208//.. goto done;
2209//.. }
2210//.. default:
2211//.. goto bad;
2212//.. }
sewardj549e0642005-02-05 12:00:14 +00002213 break;
2214
sewardj1b8d58e2005-02-05 14:34:18 +00002215 case Ain_Sh64:
2216 opc_cl = opc_imm = subopc = 0;
2217 switch (i->Ain.Sh64.op) {
2218 case Ash_SHR: opc_cl = 0xD3; opc_imm = 0xC1; subopc = 5; break;
2219 case Ash_SAR: opc_cl = 0xD3; opc_imm = 0xC1; subopc = 7; break;
2220 case Ash_SHL: opc_cl = 0xD3; opc_imm = 0xC1; subopc = 4; break;
2221 default: goto bad;
2222 }
2223 if (i->Ain.Sh64.src == 0) {
2224vassert(0);
2225 *p++ = opc_cl;
2226 switch (i->Ain.Sh64.dst->tag) {
2227 case Arm_Reg:
2228 p = doAMode_R(p, fake(subopc),
2229 i->Ain.Sh64.dst->Arm.Reg.reg);
2230 goto done;
2231 default:
2232 goto bad;
2233 }
2234 } else {
2235 *p++ = rexAMode_R(fake(0), i->Ain.Sh64.dst->Arm.Reg.reg);
2236 *p++ = opc_imm;
2237 switch (i->Ain.Sh64.dst->tag) {
2238 case Arm_Reg:
2239 p = doAMode_R(p, fake(subopc),
2240 i->Ain.Sh64.dst->Arm.Reg.reg);
2241 *p++ = (UChar)(i->Ain.Sh64.src);
2242 goto done;
2243 default:
2244 goto bad;
2245 }
2246 }
2247 break;
2248
2249 case Ain_Test64:
2250 if (i->Ain.Test64.src->tag == Ari_Imm
2251 && i->Ain.Test64.dst->tag == Arm_Reg) {
2252 /* testq sign-extend($imm32), %reg */
2253 *p++ = rexAMode_R(fake(0), i->Ain.Test64.dst->Arm.Reg.reg);
2254 *p++ = 0xF7;
2255 p = doAMode_R(p, fake(0), i->Ain.Test64.dst->Arm.Reg.reg);
2256 p = emit32(p, i->Ain.Test64.src->Ari.Imm.imm32);
2257 goto done;
2258 }
2259 break;
2260
sewardja3e98302005-02-01 15:55:05 +00002261//.. case Xin_Unary32:
2262//.. if (i->Xin.Unary32.op == Xun_NOT) {
2263//.. *p++ = 0xF7;
2264//.. if (i->Xin.Unary32.dst->tag == Xrm_Reg) {
2265//.. p = doAMode_R(p, fake(2), i->Xin.Unary32.dst->Xrm.Reg.reg);
2266//.. goto done;
2267//.. } else {
2268//.. goto bad;
2269//.. }
2270//.. }
2271//.. if (i->Xin.Unary32.op == Xun_NEG) {
2272//.. *p++ = 0xF7;
2273//.. if (i->Xin.Unary32.dst->tag == Xrm_Reg) {
2274//.. p = doAMode_R(p, fake(3), i->Xin.Unary32.dst->Xrm.Reg.reg);
2275//.. goto done;
2276//.. } else {
2277//.. goto bad;
2278//.. }
2279//.. }
2280//.. break;
2281//..
2282//.. case Xin_MulL:
2283//.. subopc = i->Xin.MulL.syned ? 5 : 4;
2284//.. if (i->Xin.MulL.ssz == Xss_32) {
2285//.. *p++ = 0xF7;
2286//.. switch (i->Xin.MulL.src->tag) {
2287//.. case Xrm_Mem:
2288//.. p = doAMode_M(p, fake(subopc),
2289//.. i->Xin.MulL.src->Xrm.Mem.am);
2290//.. goto done;
2291//.. case Xrm_Reg:
2292//.. p = doAMode_R(p, fake(subopc),
2293//.. i->Xin.MulL.src->Xrm.Reg.reg);
2294//.. goto done;
2295//.. default:
2296//.. goto bad;
2297//.. }
2298//.. }
2299//.. break;
2300//..
2301//.. case Xin_Div:
2302//.. subopc = i->Xin.Div.syned ? 7 : 6;
2303//.. if (i->Xin.Div.ssz == Xss_32) {
2304//.. *p++ = 0xF7;
2305//.. switch (i->Xin.Div.src->tag) {
2306//.. case Xrm_Mem:
2307//.. p = doAMode_M(p, fake(subopc),
2308//.. i->Xin.Div.src->Xrm.Mem.am);
2309//.. goto done;
2310//.. case Xrm_Reg:
2311//.. p = doAMode_R(p, fake(subopc),
2312//.. i->Xin.Div.src->Xrm.Reg.reg);
2313//.. goto done;
2314//.. default:
2315//.. goto bad;
2316//.. }
2317//.. }
2318//.. break;
2319//..
2320//.. case Xin_Sh3232:
2321//.. vassert(i->Xin.Sh3232.op == Xsh_SHL || i->Xin.Sh3232.op == Xsh_SHR);
2322//.. if (i->Xin.Sh3232.amt == 0) {
2323//.. /* shldl/shrdl by %cl */
2324//.. *p++ = 0x0F;
2325//.. if (i->Xin.Sh3232.op == Xsh_SHL) {
2326//.. *p++ = 0xA5;
2327//.. } else {
2328//.. *p++ = 0xAD;
2329//.. }
2330//.. p = doAMode_R(p, i->Xin.Sh3232.src, i->Xin.Sh3232.dst);
2331//.. goto done;
2332//.. }
2333//.. break;
2334//..
2335//.. case Xin_Push:
2336//.. switch (i->Xin.Push.src->tag) {
2337//.. case Xrmi_Mem:
2338//.. *p++ = 0xFF;
2339//.. p = doAMode_M(p, fake(6), i->Xin.Push.src->Xrmi.Mem.am);
2340//.. goto done;
2341//.. case Xrmi_Imm:
2342//.. *p++ = 0x68;
2343//.. p = emit32(p, i->Xin.Push.src->Xrmi.Imm.imm32);
2344//.. goto done;
2345//.. case Xrmi_Reg:
2346//.. *p++ = 0x50 + iregNo(i->Xin.Push.src->Xrmi.Reg.reg);
2347//.. goto done;
2348//.. default:
2349//.. goto bad;
2350//.. }
sewardj1b8d58e2005-02-05 14:34:18 +00002351
2352 case Ain_Call:
2353 /* As per detailed comment for Ain_Call in
2354 getRegUsage_AMD64Instr above, %r11 is used as an address
2355 temporary. */
2356 /* jump over the following two insns if the condition does not
2357 hold */
2358 if (i->Ain.Call.cond != Acc_ALWAYS) {
2359 *p++ = 0x70 + (0xF & (i->Ain.Call.cond ^ 1));
2360 *p++ = 13; /* 13 bytes in the next two insns */
2361 }
2362 /* movabsq $target, %r11 */
2363 *p++ = 0x49;
2364 *p++ = 0xBB;
2365 p = emit64(p, i->Ain.Call.target);
2366 /* call *%r11 */
2367 *p++ = 0x41;
2368 *p++ = 0xFF;
2369 *p++ = 0xD3;
2370 goto done;
sewardj549e0642005-02-05 12:00:14 +00002371
2372 case Ain_Goto:
sewardj549e0642005-02-05 12:00:14 +00002373 /* Use ptmp for backpatching conditional jumps. */
2374 ptmp = NULL;
2375
2376 /* First off, if this is conditional, create a conditional
2377 jump over the rest of it. */
2378 if (i->Ain.Goto.cond != Acc_ALWAYS) {
2379 /* jmp fwds if !condition */
2380 *p++ = 0x70 + (i->Ain.Goto.cond ^ 1);
2381 ptmp = p; /* fill in this bit later */
2382 *p++ = 0; /* # of bytes to jump over; don't know how many yet. */
2383 }
2384
2385 /* If a non-boring, set %rbp (the guest state pointer)
sewardj1b8d58e2005-02-05 14:34:18 +00002386 appropriately. Since these numbers are all small positive
2387 integers, we can get away with "movl $N, %ebp" rather than
2388 the longer "movq $N, %rbp". */
2389 /* movl $magic_number, %ebp */
sewardj549e0642005-02-05 12:00:14 +00002390 switch (i->Ain.Goto.jk) {
2391 case Ijk_ClientReq:
2392 *p++ = 0xBD;
2393 p = emit32(p, VEX_TRC_JMP_CLIENTREQ); break;
2394 case Ijk_Syscall:
2395 *p++ = 0xBD;
2396 p = emit32(p, VEX_TRC_JMP_SYSCALL); break;
2397 case Ijk_Yield:
2398 *p++ = 0xBD;
2399 p = emit32(p, VEX_TRC_JMP_YIELD); break;
2400 case Ijk_EmWarn:
2401 *p++ = 0xBD;
2402 p = emit32(p, VEX_TRC_JMP_EMWARN); break;
2403 case Ijk_MapFail:
2404 *p++ = 0xBD;
2405 p = emit32(p, VEX_TRC_JMP_MAPFAIL); break;
2406 case Ijk_NoDecode:
2407 *p++ = 0xBD;
2408 p = emit32(p, VEX_TRC_JMP_NODECODE); break;
2409 case Ijk_Ret:
2410 case Ijk_Call:
2411 case Ijk_Boring:
2412 break;
2413 default:
2414 ppIRJumpKind(i->Ain.Goto.jk);
2415 vpanic("emit_AMD64Instr.Ain_Goto: unknown jump kind");
2416 }
2417
2418 /* Get the destination address into %rax */
2419 if (i->Ain.Goto.dst->tag == Ari_Imm) {
sewardjc2bcb6f2005-02-07 00:17:12 +00002420 /* movl sign-ext($immediate), %rax ; ret */
2421 *p++ = 0x48;
2422 *p++ = 0xC7;
2423 *p++ = 0xC0;
sewardj549e0642005-02-05 12:00:14 +00002424 p = emit32(p, i->Ain.Goto.dst->Ari.Imm.imm32);
2425 } else {
2426 vassert(i->Ain.Goto.dst->tag == Ari_Reg);
sewardj1b8d58e2005-02-05 14:34:18 +00002427 /* movq %reg, %rax ; ret */
sewardj549e0642005-02-05 12:00:14 +00002428 if (i->Ain.Goto.dst->Ari.Reg.reg != hregAMD64_RAX()) {
sewardj1b8d58e2005-02-05 14:34:18 +00002429 *p++ = rexAMode_R(i->Ain.Goto.dst->Ari.Reg.reg, hregAMD64_RAX());
sewardj549e0642005-02-05 12:00:14 +00002430 *p++ = 0x89;
2431 p = doAMode_R(p, i->Ain.Goto.dst->Ari.Reg.reg, hregAMD64_RAX());
2432 }
2433 }
2434
2435 /* ret */
2436 *p++ = 0xC3;
2437
2438 /* Fix up the conditional jump, if there was one. */
2439 if (i->Ain.Goto.cond != Acc_ALWAYS) {
2440 Int delta = p - ptmp;
2441 vassert(delta > 0 && delta < 20);
2442 *ptmp = (UChar)(delta-1);
2443 }
2444 goto done;
2445
sewardj1b8d58e2005-02-05 14:34:18 +00002446 case Ain_CMov64:
2447 vassert(i->Ain.CMov64.cond != Acc_ALWAYS);
2448 if (i->Ain.CMov64.src->tag == Arm_Reg) {
2449 *p++ = rexAMode_R(i->Ain.CMov64.dst, i->Ain.CMov64.src->Arm.Reg.reg);
2450 *p++ = 0x0F;
2451 *p++ = 0x40 + (0xF & i->Ain.CMov64.cond);
2452 p = doAMode_R(p, i->Ain.CMov64.dst, i->Ain.CMov64.src->Arm.Reg.reg);
2453 goto done;
2454 }
2455 if (i->Ain.CMov64.src->tag == Arm_Mem) {
2456vassert(0);
2457 *p++ = rexAMode_M(i->Ain.CMov64.dst, i->Ain.CMov64.src->Arm.Mem.am);
2458 *p++ = 0x0F;
2459 *p++ = 0x40 + (0xF & i->Ain.CMov64.cond);
2460 p = doAMode_M(p, i->Ain.CMov64.dst, i->Ain.CMov64.src->Arm.Mem.am);
2461 goto done;
2462 }
2463 break;
sewardj549e0642005-02-05 12:00:14 +00002464
2465 case Ain_MovZLQ:
2466 /* Produce a 32-bit reg-reg move, since the implicit zero-extend
2467 does what we want. */
2468 *p++ = clearWBit (
2469 rexAMode_R(i->Ain.MovZLQ.src, i->Ain.MovZLQ.dst));
2470 *p++ = 0x89;
2471 p = doAMode_R(p, i->Ain.MovZLQ.src, i->Ain.MovZLQ.dst);
2472 goto done;
2473
2474 case Ain_LoadEX:
sewardj1b8d58e2005-02-05 14:34:18 +00002475 if (i->Ain.LoadEX.szSmall == 1 && !i->Ain.LoadEX.syned) {
2476 /* movzbq */
2477 *p++ = rexAMode_M(i->Ain.LoadEX.dst, i->Ain.LoadEX.src);
2478 *p++ = 0x0F;
2479 *p++ = 0xB6;
2480 p = doAMode_M(p, i->Ain.LoadEX.dst, i->Ain.LoadEX.src);
2481 goto done;
2482 }
2483 if (i->Ain.LoadEX.szSmall == 2 && !i->Ain.LoadEX.syned) {
2484 /* movzwq */
2485 *p++ = rexAMode_M(i->Ain.LoadEX.dst, i->Ain.LoadEX.src);
2486 *p++ = 0x0F;
2487 *p++ = 0xB7;
2488 p = doAMode_M(p, i->Ain.LoadEX.dst, i->Ain.LoadEX.src);
2489 goto done;
2490 }
sewardj549e0642005-02-05 12:00:14 +00002491 if (i->Ain.LoadEX.szSmall == 4 && !i->Ain.LoadEX.syned) {
2492 /* movzlq */
sewardj1b8d58e2005-02-05 14:34:18 +00002493 /* This isn't really an existing AMD64 instruction per se.
sewardj549e0642005-02-05 12:00:14 +00002494 Rather, we have to do a 32-bit load. Because a 32-bit
2495 write implicitly clears the upper 32 bits of the target
2496 register, we get what we want. */
2497 *p++ = clearWBit(
2498 rexAMode_M(i->Ain.LoadEX.dst, i->Ain.LoadEX.src));
2499 *p++ = 0x8B;
2500 p = doAMode_M(p, i->Ain.LoadEX.dst, i->Ain.LoadEX.src);
2501 goto done;
2502 }
2503 break;
2504
sewardja3e98302005-02-01 15:55:05 +00002505//.. case Xin_Set32:
2506//.. /* Make the destination register be 1 or 0, depending on whether
2507//.. the relevant condition holds. We have to dodge and weave
2508//.. when the destination is %esi or %edi as we cannot directly
2509//.. emit the native 'setb %reg' for those. Further complication:
2510//.. the top 24 bits of the destination should be forced to zero,
2511//.. but doing 'xor %r,%r' kills the flag(s) we are about to read.
2512//.. Sigh. So start off my moving $0 into the dest. */
2513//..
2514//.. /* Do we need to swap in %eax? */
2515//.. if (iregNo(i->Xin.Set32.dst) >= 4) {
2516//.. /* xchg %eax, %dst */
2517//.. *p++ = 0x90 + iregNo(i->Xin.Set32.dst);
2518//.. /* movl $0, %eax */
sewardj614b3fb2005-02-02 02:16:03 +00002519//.. *p++ = 0xB8 + iregNo(hregAMD64_EAX());
sewardja3e98302005-02-01 15:55:05 +00002520//.. p = emit32(p, 0);
2521//.. /* setb lo8(%eax) */
2522//.. *p++ = 0x0F;
2523//.. *p++ = 0x90 + (UChar)(i->Xin.Set32.cond);
sewardj614b3fb2005-02-02 02:16:03 +00002524//.. p = doAMode_R(p, fake(0), hregAMD64_EAX());
sewardja3e98302005-02-01 15:55:05 +00002525//.. /* xchg %eax, %dst */
2526//.. *p++ = 0x90 + iregNo(i->Xin.Set32.dst);
2527//.. } else {
2528//.. /* movl $0, %dst */
2529//.. *p++ = 0xB8 + iregNo(i->Xin.Set32.dst);
2530//.. p = emit32(p, 0);
2531//.. /* setb lo8(%dst) */
2532//.. *p++ = 0x0F;
2533//.. *p++ = 0x90 + (UChar)(i->Xin.Set32.cond);
2534//.. p = doAMode_R(p, fake(0), i->Xin.Set32.dst);
2535//.. }
2536//.. goto done;
2537//..
2538//.. case Xin_Bsfr32:
2539//.. *p++ = 0x0F;
2540//.. if (i->Xin.Bsfr32.isFwds) {
2541//.. *p++ = 0xBC;
2542//.. } else {
2543//.. *p++ = 0xBD;
2544//.. }
2545//.. p = doAMode_R(p, i->Xin.Bsfr32.dst, i->Xin.Bsfr32.src);
2546//.. goto done;
2547//..
2548//.. case Xin_MFence:
2549//.. /* see comment in hdefs.h re this insn */
2550//.. if (0) vex_printf("EMIT FENCE\n");
2551//.. switch (i->Xin.MFence.subarch) {
sewardj614b3fb2005-02-02 02:16:03 +00002552//.. case VexSubArchAMD64_sse0:
sewardja3e98302005-02-01 15:55:05 +00002553//.. vassert(0); /* awaiting test case */
2554//.. /* lock addl $0,0(%esp) */
2555//.. *p++ = 0xF0; *p++ = 0x83; *p++ = 0x44;
2556//.. *p++ = 0x24; *p++ = 0x00; *p++ = 0x00;
2557//.. goto done;
sewardj614b3fb2005-02-02 02:16:03 +00002558//.. case VexSubArchAMD64_sse1:
sewardja3e98302005-02-01 15:55:05 +00002559//.. /* sfence */
2560//.. *p++ = 0x0F; *p++ = 0xAE; *p++ = 0xF8;
2561//.. /* lock addl $0,0(%esp) */
2562//.. *p++ = 0xF0; *p++ = 0x83; *p++ = 0x44;
2563//.. *p++ = 0x24; *p++ = 0x00; *p++ = 0x00;
2564//.. goto done;
sewardj614b3fb2005-02-02 02:16:03 +00002565//.. case VexSubArchAMD64_sse2:
sewardja3e98302005-02-01 15:55:05 +00002566//.. /* mfence */
2567//.. *p++ = 0x0F; *p++ = 0xAE; *p++ = 0xF0;
2568//.. goto done;
2569//.. default:
sewardj614b3fb2005-02-02 02:16:03 +00002570//.. vpanic("emit_AMD64Instr:mfence:subarch");
sewardja3e98302005-02-01 15:55:05 +00002571//.. }
2572//.. break;
sewardj1b8d58e2005-02-05 14:34:18 +00002573
2574 case Ain_Store:
2575 if (i->Ain.Store.sz == 2) {
2576 /* This just goes to show the crazyness of the instruction
2577 set encoding. We have to insert two prefix bytes, but be
2578 careful to avoid a conflict in what the size should be, by
2579 ensuring that REX.W = 0. */
2580 *p++ = 0x66; /* override to 16-bits */
2581 *p++ = clearWBit( rexAMode_M( i->Ain.Store.src, i->Ain.Store.dst) );
2582 *p++ = 0x89;
2583 p = doAMode_M(p, i->Ain.Store.src, i->Ain.Store.dst);
2584 goto done;
2585 }
2586 if (i->Ain.Store.sz == 4) {
2587 *p++ = clearWBit( rexAMode_M( i->Ain.Store.src, i->Ain.Store.dst) );
2588 *p++ = 0x89;
2589 p = doAMode_M(p, i->Ain.Store.src, i->Ain.Store.dst);
2590 goto done;
2591 }
sewardja3e98302005-02-01 15:55:05 +00002592//..
2593//.. if (i->Xin.Store.sz == 1) {
2594//.. /* We have to do complex dodging and weaving if src is not
2595//.. the low 8 bits of %eax/%ebx/%ecx/%edx. */
2596//.. if (iregNo(i->Xin.Store.src) < 4) {
2597//.. /* we're OK, can do it directly */
2598//.. *p++ = 0x88;
2599//.. p = doAMode_M(p, i->Xin.Store.src, i->Xin.Store.dst);
2600//.. goto done;
2601//.. } else {
2602//.. /* Bleh. This means the source is %edi or %esi. Since
2603//.. the address mode can only mention three registers, at
2604//.. least one of %eax/%ebx/%ecx/%edx must be available to
2605//.. temporarily swap the source into, so the store can
2606//.. happen. So we have to look at the regs mentioned
2607//.. in the amode. */
2608//.. HReg swap = INVALID_HREG;
sewardj614b3fb2005-02-02 02:16:03 +00002609//.. HReg eax = hregAMD64_EAX(), ebx = hregAMD64_EBX(),
2610//.. ecx = hregAMD64_ECX(), edx = hregAMD64_EDX();
sewardja3e98302005-02-01 15:55:05 +00002611//.. Bool a_ok = True, b_ok = True, c_ok = True, d_ok = True;
2612//.. HRegUsage u;
2613//.. Int j;
2614//.. initHRegUsage(&u);
sewardj614b3fb2005-02-02 02:16:03 +00002615//.. addRegUsage_AMD64AMode(&u, i->Xin.Store.dst);
sewardja3e98302005-02-01 15:55:05 +00002616//.. for (j = 0; j < u.n_used; j++) {
2617//.. HReg r = u.hreg[j];
2618//.. if (r == eax) a_ok = False;
2619//.. if (r == ebx) b_ok = False;
2620//.. if (r == ecx) c_ok = False;
2621//.. if (r == edx) d_ok = False;
2622//.. }
2623//.. if (a_ok) swap = eax;
2624//.. if (b_ok) swap = ebx;
2625//.. if (c_ok) swap = ecx;
2626//.. if (d_ok) swap = edx;
2627//.. vassert(swap != INVALID_HREG);
2628//.. /* xchgl %source, %swap. Could do better if swap is %eax. */
2629//.. *p++ = 0x87;
2630//.. p = doAMode_R(p, i->Xin.Store.src, swap);
2631//.. /* movb lo8{%swap}, (dst) */
2632//.. *p++ = 0x88;
2633//.. p = doAMode_M(p, swap, i->Xin.Store.dst);
2634//.. /* xchgl %source, %swap. Could do better if swap is %eax. */
2635//.. *p++ = 0x87;
2636//.. p = doAMode_R(p, i->Xin.Store.src, swap);
2637//.. goto done;
2638//.. }
2639//.. } /* if (i->Xin.Store.sz == 1) */
sewardj1b8d58e2005-02-05 14:34:18 +00002640 break;
2641
sewardja3e98302005-02-01 15:55:05 +00002642//.. case Xin_FpUnary:
2643//.. /* gop %src, %dst
2644//.. --> ffree %st7 ; fld %st(src) ; fop %st(0) ; fstp %st(1+dst)
2645//.. */
2646//.. p = do_ffree_st7(p);
2647//.. p = do_fld_st(p, 0+hregNumber(i->Xin.FpUnary.src));
2648//.. p = do_fop1_st(p, i->Xin.FpUnary.op);
2649//.. p = do_fstp_st(p, 1+hregNumber(i->Xin.FpUnary.dst));
2650//.. goto done;
2651//..
2652//.. case Xin_FpBinary:
2653//.. if (i->Xin.FpBinary.op == Xfp_YL2X
2654//.. || i->Xin.FpBinary.op == Xfp_YL2XP1) {
2655//.. /* Have to do this specially. */
2656//.. /* ffree %st7 ; fld %st(srcL) ;
2657//.. ffree %st7 ; fld %st(srcR+1) ; fyl2x{p1} ; fstp(1+dst) */
2658//.. p = do_ffree_st7(p);
2659//.. p = do_fld_st(p, 0+hregNumber(i->Xin.FpBinary.srcL));
2660//.. p = do_ffree_st7(p);
2661//.. p = do_fld_st(p, 1+hregNumber(i->Xin.FpBinary.srcR));
2662//.. *p++ = 0xD9;
2663//.. *p++ = i->Xin.FpBinary.op==Xfp_YL2X ? 0xF1 : 0xF9;
2664//.. p = do_fstp_st(p, 1+hregNumber(i->Xin.FpBinary.dst));
2665//.. goto done;
2666//.. }
2667//.. if (i->Xin.FpBinary.op == Xfp_ATAN) {
2668//.. /* Have to do this specially. */
2669//.. /* ffree %st7 ; fld %st(srcL) ;
2670//.. ffree %st7 ; fld %st(srcR+1) ; fpatan ; fstp(1+dst) */
2671//.. p = do_ffree_st7(p);
2672//.. p = do_fld_st(p, 0+hregNumber(i->Xin.FpBinary.srcL));
2673//.. p = do_ffree_st7(p);
2674//.. p = do_fld_st(p, 1+hregNumber(i->Xin.FpBinary.srcR));
2675//.. *p++ = 0xD9; *p++ = 0xF3;
2676//.. p = do_fstp_st(p, 1+hregNumber(i->Xin.FpBinary.dst));
2677//.. goto done;
2678//.. }
2679//.. if (i->Xin.FpBinary.op == Xfp_PREM
2680//.. || i->Xin.FpBinary.op == Xfp_PREM1
2681//.. || i->Xin.FpBinary.op == Xfp_SCALE) {
2682//.. /* Have to do this specially. */
2683//.. /* ffree %st7 ; fld %st(srcR) ;
2684//.. ffree %st7 ; fld %st(srcL+1) ; fprem/fprem1/fscale ; fstp(2+dst) ;
2685//.. fincstp ; ffree %st7 */
2686//.. p = do_ffree_st7(p);
2687//.. p = do_fld_st(p, 0+hregNumber(i->Xin.FpBinary.srcR));
2688//.. p = do_ffree_st7(p);
2689//.. p = do_fld_st(p, 1+hregNumber(i->Xin.FpBinary.srcL));
2690//.. *p++ = 0xD9;
2691//.. switch (i->Xin.FpBinary.op) {
2692//.. case Xfp_PREM: *p++ = 0xF8; break;
2693//.. case Xfp_PREM1: *p++ = 0xF5; break;
2694//.. case Xfp_SCALE: *p++ = 0xFD; break;
sewardj614b3fb2005-02-02 02:16:03 +00002695//.. default: vpanic("emitAMD64Instr(FpBinary,PREM/PREM1/SCALE)");
sewardja3e98302005-02-01 15:55:05 +00002696//.. }
2697//.. p = do_fstp_st(p, 2+hregNumber(i->Xin.FpBinary.dst));
2698//.. *p++ = 0xD9; *p++ = 0xF7;
2699//.. p = do_ffree_st7(p);
2700//.. goto done;
2701//.. }
2702//.. /* General case */
2703//.. /* gop %srcL, %srcR, %dst
2704//.. --> ffree %st7 ; fld %st(srcL) ; fop %st(1+srcR) ; fstp %st(1+dst)
2705//.. */
2706//.. p = do_ffree_st7(p);
2707//.. p = do_fld_st(p, 0+hregNumber(i->Xin.FpBinary.srcL));
2708//.. p = do_fop2_st(p, i->Xin.FpBinary.op,
2709//.. 1+hregNumber(i->Xin.FpBinary.srcR));
2710//.. p = do_fstp_st(p, 1+hregNumber(i->Xin.FpBinary.dst));
2711//.. goto done;
2712//..
2713//.. case Xin_FpLdSt:
2714//.. vassert(i->Xin.FpLdSt.sz == 4 || i->Xin.FpLdSt.sz == 8);
2715//.. if (i->Xin.FpLdSt.isLoad) {
2716//.. /* Load from memory into %fakeN.
2717//.. --> ffree %st(7) ; fld{s/l} amode ; fstp st(N+1)
2718//.. */
2719//.. p = do_ffree_st7(p);
2720//.. *p++ = i->Xin.FpLdSt.sz==4 ? 0xD9 : 0xDD;
2721//.. p = doAMode_M(p, fake(0)/*subopcode*/, i->Xin.FpLdSt.addr);
2722//.. p = do_fstp_st(p, 1+hregNumber(i->Xin.FpLdSt.reg));
2723//.. goto done;
2724//.. } else {
2725//.. /* Store from %fakeN into memory.
2726//.. --> ffree %st(7) ; fld st(N) ; fstp{l|s} amode
2727//.. */
2728//.. p = do_ffree_st7(p);
2729//.. p = do_fld_st(p, 0+hregNumber(i->Xin.FpLdSt.reg));
2730//.. *p++ = i->Xin.FpLdSt.sz==4 ? 0xD9 : 0xDD;
2731//.. p = doAMode_M(p, fake(3)/*subopcode*/, i->Xin.FpLdSt.addr);
2732//.. goto done;
2733//.. }
2734//.. break;
2735//..
2736//.. case Xin_FpLdStI:
2737//.. if (i->Xin.FpLdStI.isLoad) {
2738//.. /* Load from memory into %fakeN, converting from an int.
2739//.. --> ffree %st(7) ; fild{w/l/ll} amode ; fstp st(N+1)
2740//.. */
2741//.. switch (i->Xin.FpLdStI.sz) {
2742//.. case 8: opc = 0xDF; subopc_imm = 5; break;
2743//.. case 4: opc = 0xDB; subopc_imm = 0; break;
2744//.. case 2: vassert(0); opc = 0xDF; subopc_imm = 0; break;
sewardj614b3fb2005-02-02 02:16:03 +00002745//.. default: vpanic("emitAMD64Instr(Xin_FpLdStI-load)");
sewardja3e98302005-02-01 15:55:05 +00002746//.. }
2747//.. p = do_ffree_st7(p);
2748//.. *p++ = opc;
2749//.. p = doAMode_M(p, fake(subopc_imm)/*subopcode*/, i->Xin.FpLdStI.addr);
2750//.. p = do_fstp_st(p, 1+hregNumber(i->Xin.FpLdStI.reg));
2751//.. goto done;
2752//.. } else {
2753//.. /* Store from %fakeN into memory, converting to an int.
2754//.. --> ffree %st(7) ; fld st(N) ; fistp{w/l/ll} amode
2755//.. */
2756//.. switch (i->Xin.FpLdStI.sz) {
2757//.. case 8: opc = 0xDF; subopc_imm = 7; break;
2758//.. case 4: opc = 0xDB; subopc_imm = 3; break;
2759//.. case 2: opc = 0xDF; subopc_imm = 3; break;
sewardj614b3fb2005-02-02 02:16:03 +00002760//.. default: vpanic("emitAMD64Instr(Xin_FpLdStI-store)");
sewardja3e98302005-02-01 15:55:05 +00002761//.. }
2762//.. p = do_ffree_st7(p);
2763//.. p = do_fld_st(p, 0+hregNumber(i->Xin.FpLdStI.reg));
2764//.. *p++ = opc;
2765//.. p = doAMode_M(p, fake(subopc_imm)/*subopcode*/, i->Xin.FpLdStI.addr);
2766//.. goto done;
2767//.. }
2768//.. break;
2769//..
2770//.. case Xin_Fp64to32:
2771//.. /* ffree %st7 ; fld %st(src) */
2772//.. p = do_ffree_st7(p);
2773//.. p = do_fld_st(p, 0+fregNo(i->Xin.Fp64to32.src));
2774//.. /* subl $4, %esp */
2775//.. *p++ = 0x83; *p++ = 0xEC; *p++ = 0x04;
2776//.. /* fstps (%esp) */
2777//.. *p++ = 0xD9; *p++ = 0x1C; *p++ = 0x24;
2778//.. /* flds (%esp) */
2779//.. *p++ = 0xD9; *p++ = 0x04; *p++ = 0x24;
2780//.. /* addl $4, %esp */
2781//.. *p++ = 0x83; *p++ = 0xC4; *p++ = 0x04;
2782//.. /* fstp %st(1+dst) */
2783//.. p = do_fstp_st(p, 1+fregNo(i->Xin.Fp64to32.dst));
2784//.. goto done;
2785//..
2786//.. case Xin_FpCMov:
2787//.. /* jmp fwds if !condition */
2788//.. *p++ = 0x70 + (i->Xin.FpCMov.cond ^ 1);
2789//.. *p++ = 0; /* # of bytes in the next bit, which we don't know yet */
2790//.. ptmp = p;
2791//..
2792//.. /* ffree %st7 ; fld %st(src) ; fstp %st(1+dst) */
2793//.. p = do_ffree_st7(p);
2794//.. p = do_fld_st(p, 0+fregNo(i->Xin.FpCMov.src));
2795//.. p = do_fstp_st(p, 1+fregNo(i->Xin.FpCMov.dst));
2796//..
2797//.. /* Fill in the jump offset. */
2798//.. *(ptmp-1) = p - ptmp;
2799//.. goto done;
2800//..
2801//.. case Xin_FpLdStCW:
2802//.. if (i->Xin.FpLdStCW.isLoad) {
2803//.. *p++ = 0xD9;
2804//.. p = doAMode_M(p, fake(5)/*subopcode*/, i->Xin.FpLdStCW.addr);
2805//.. } else {
2806//.. vassert(0);
2807//.. }
2808//.. goto done;
2809//..
2810//.. case Xin_FpStSW_AX:
2811//.. /* note, this emits fnstsw %ax, not fstsw %ax */
2812//.. *p++ = 0xDF;
2813//.. *p++ = 0xE0;
2814//.. goto done;
2815//..
2816//.. case Xin_FpCmp:
2817//.. /* gcmp %fL, %fR, %dst
2818//.. -> ffree %st7; fpush %fL ; fucomp %(fR+1) ;
2819//.. fnstsw %ax ; movl %eax, %dst
2820//.. */
2821//.. /* ffree %st7 */
2822//.. p = do_ffree_st7(p);
2823//.. /* fpush %fL */
2824//.. p = do_fld_st(p, 0+fregNo(i->Xin.FpCmp.srcL));
2825//.. /* fucomp %(fR+1) */
2826//.. *p++ = 0xDD;
2827//.. *p++ = 0xE8 + (7 & (1+fregNo(i->Xin.FpCmp.srcR)));
2828//.. /* fnstsw %ax */
2829//.. *p++ = 0xDF;
2830//.. *p++ = 0xE0;
2831//.. /* movl %eax, %dst */
2832//.. *p++ = 0x89;
sewardj614b3fb2005-02-02 02:16:03 +00002833//.. p = doAMode_R(p, hregAMD64_EAX(), i->Xin.FpCmp.dst);
sewardja3e98302005-02-01 15:55:05 +00002834//.. goto done;
2835//..
2836//.. case Xin_SseConst: {
2837//.. UShort con = i->Xin.SseConst.con;
2838//.. p = push_word_from_tags(p, (con >> 12) & 0xF);
2839//.. p = push_word_from_tags(p, (con >> 8) & 0xF);
2840//.. p = push_word_from_tags(p, (con >> 4) & 0xF);
2841//.. p = push_word_from_tags(p, con & 0xF);
2842//.. /* movl (%esp), %xmm-dst */
2843//.. *p++ = 0x0F;
2844//.. *p++ = 0x10;
2845//.. *p++ = 0x04 + 8 * (7 & vregNo(i->Xin.SseConst.dst));
2846//.. *p++ = 0x24;
2847//.. /* addl $16, %esp */
2848//.. *p++ = 0x83;
2849//.. *p++ = 0xC4;
2850//.. *p++ = 0x10;
2851//.. goto done;
2852//.. }
2853//..
2854//.. case Xin_SseLdSt:
2855//.. *p++ = 0x0F;
2856//.. *p++ = i->Xin.SseLdSt.isLoad ? 0x10 : 0x11;
2857//.. p = doAMode_M(p, fake(vregNo(i->Xin.SseLdSt.reg)), i->Xin.SseLdSt.addr);
2858//.. goto done;
2859//..
2860//.. case Xin_SseLdzLO:
2861//.. vassert(i->Xin.SseLdzLO.sz == 4 || i->Xin.SseLdzLO.sz == 8);
2862//.. /* movs[sd] amode, %xmm-dst */
2863//.. *p++ = i->Xin.SseLdzLO.sz==4 ? 0xF3 : 0xF2;
2864//.. *p++ = 0x0F;
2865//.. *p++ = 0x10;
2866//.. p = doAMode_M(p, fake(vregNo(i->Xin.SseLdzLO.reg)),
2867//.. i->Xin.SseLdzLO.addr);
2868//.. goto done;
2869//..
2870//.. case Xin_Sse32Fx4:
2871//.. xtra = 0;
2872//.. *p++ = 0x0F;
2873//.. switch (i->Xin.Sse32Fx4.op) {
2874//.. case Xsse_ADDF: *p++ = 0x58; break;
2875//.. case Xsse_DIVF: *p++ = 0x5E; break;
2876//.. case Xsse_MAXF: *p++ = 0x5F; break;
2877//.. case Xsse_MINF: *p++ = 0x5D; break;
2878//.. case Xsse_MULF: *p++ = 0x59; break;
2879//.. case Xsse_RCPF: *p++ = 0x53; break;
2880//.. case Xsse_RSQRTF: *p++ = 0x52; break;
2881//.. case Xsse_SQRTF: *p++ = 0x51; break;
2882//.. case Xsse_SUBF: *p++ = 0x5C; break;
2883//.. case Xsse_CMPEQF: *p++ = 0xC2; xtra = 0x100; break;
2884//.. case Xsse_CMPLTF: *p++ = 0xC2; xtra = 0x101; break;
2885//.. case Xsse_CMPLEF: *p++ = 0xC2; xtra = 0x102; break;
2886//.. default: goto bad;
2887//.. }
2888//.. p = doAMode_R(p, fake(vregNo(i->Xin.Sse32Fx4.dst)),
2889//.. fake(vregNo(i->Xin.Sse32Fx4.src)) );
2890//.. if (xtra & 0x100)
2891//.. *p++ = (UChar)(xtra & 0xFF);
2892//.. goto done;
2893//..
2894//.. case Xin_Sse64Fx2:
2895//.. xtra = 0;
2896//.. *p++ = 0x66;
2897//.. *p++ = 0x0F;
2898//.. switch (i->Xin.Sse64Fx2.op) {
2899//.. case Xsse_ADDF: *p++ = 0x58; break;
2900//.. case Xsse_DIVF: *p++ = 0x5E; break;
2901//.. case Xsse_MAXF: *p++ = 0x5F; break;
2902//.. case Xsse_MINF: *p++ = 0x5D; break;
2903//.. case Xsse_MULF: *p++ = 0x59; break;
2904//.. case Xsse_RCPF: *p++ = 0x53; break;
2905//.. case Xsse_RSQRTF: *p++ = 0x52; break;
2906//.. case Xsse_SQRTF: *p++ = 0x51; break;
2907//.. case Xsse_SUBF: *p++ = 0x5C; break;
2908//.. case Xsse_CMPEQF: *p++ = 0xC2; xtra = 0x100; break;
2909//.. case Xsse_CMPLTF: *p++ = 0xC2; xtra = 0x101; break;
2910//.. case Xsse_CMPLEF: *p++ = 0xC2; xtra = 0x102; break;
2911//.. default: goto bad;
2912//.. }
2913//.. p = doAMode_R(p, fake(vregNo(i->Xin.Sse64Fx2.dst)),
2914//.. fake(vregNo(i->Xin.Sse64Fx2.src)) );
2915//.. if (xtra & 0x100)
2916//.. *p++ = (UChar)(xtra & 0xFF);
2917//.. goto done;
2918//..
2919//.. case Xin_Sse32FLo:
2920//.. xtra = 0;
2921//.. *p++ = 0xF3;
2922//.. *p++ = 0x0F;
2923//.. switch (i->Xin.Sse32FLo.op) {
2924//.. case Xsse_ADDF: *p++ = 0x58; break;
2925//.. case Xsse_DIVF: *p++ = 0x5E; break;
2926//.. case Xsse_MAXF: *p++ = 0x5F; break;
2927//.. case Xsse_MINF: *p++ = 0x5D; break;
2928//.. case Xsse_MULF: *p++ = 0x59; break;
2929//.. case Xsse_RCPF: *p++ = 0x53; break;
2930//.. case Xsse_RSQRTF: *p++ = 0x52; break;
2931//.. case Xsse_SQRTF: *p++ = 0x51; break;
2932//.. case Xsse_SUBF: *p++ = 0x5C; break;
2933//.. case Xsse_CMPEQF: *p++ = 0xC2; xtra = 0x100; break;
2934//.. case Xsse_CMPLTF: *p++ = 0xC2; xtra = 0x101; break;
2935//.. case Xsse_CMPLEF: *p++ = 0xC2; xtra = 0x102; break;
2936//.. default: goto bad;
2937//.. }
2938//.. p = doAMode_R(p, fake(vregNo(i->Xin.Sse32FLo.dst)),
2939//.. fake(vregNo(i->Xin.Sse32FLo.src)) );
2940//.. if (xtra & 0x100)
2941//.. *p++ = (UChar)(xtra & 0xFF);
2942//.. goto done;
2943//..
2944//.. case Xin_Sse64FLo:
2945//.. xtra = 0;
2946//.. *p++ = 0xF2;
2947//.. *p++ = 0x0F;
2948//.. switch (i->Xin.Sse64FLo.op) {
2949//.. case Xsse_ADDF: *p++ = 0x58; break;
2950//.. case Xsse_DIVF: *p++ = 0x5E; break;
2951//.. case Xsse_MAXF: *p++ = 0x5F; break;
2952//.. case Xsse_MINF: *p++ = 0x5D; break;
2953//.. case Xsse_MULF: *p++ = 0x59; break;
2954//.. case Xsse_RCPF: *p++ = 0x53; break;
2955//.. case Xsse_RSQRTF: *p++ = 0x52; break;
2956//.. case Xsse_SQRTF: *p++ = 0x51; break;
2957//.. case Xsse_SUBF: *p++ = 0x5C; break;
2958//.. case Xsse_CMPEQF: *p++ = 0xC2; xtra = 0x100; break;
2959//.. case Xsse_CMPLTF: *p++ = 0xC2; xtra = 0x101; break;
2960//.. case Xsse_CMPLEF: *p++ = 0xC2; xtra = 0x102; break;
2961//.. default: goto bad;
2962//.. }
2963//.. p = doAMode_R(p, fake(vregNo(i->Xin.Sse64FLo.dst)),
2964//.. fake(vregNo(i->Xin.Sse64FLo.src)) );
2965//.. if (xtra & 0x100)
2966//.. *p++ = (UChar)(xtra & 0xFF);
2967//.. goto done;
2968//..
2969//.. case Xin_SseReRg:
2970//.. # define XX(_n) *p++ = (_n)
2971//.. switch (i->Xin.SseReRg.op) {
2972//.. case Xsse_MOV: /*movups*/ XX(0x0F); XX(0x10); break;
2973//.. case Xsse_OR: XX(0x0F); XX(0x56); break;
2974//.. case Xsse_XOR: XX(0x0F); XX(0x57); break;
2975//.. case Xsse_AND: XX(0x0F); XX(0x54); break;
2976//.. case Xsse_PACKSSD: XX(0x66); XX(0x0F); XX(0x6B); break;
2977//.. case Xsse_PACKSSW: XX(0x66); XX(0x0F); XX(0x63); break;
2978//.. case Xsse_PACKUSW: XX(0x66); XX(0x0F); XX(0x67); break;
2979//.. case Xsse_ADD8: XX(0x66); XX(0x0F); XX(0xFC); break;
2980//.. case Xsse_ADD16: XX(0x66); XX(0x0F); XX(0xFD); break;
2981//.. case Xsse_ADD32: XX(0x66); XX(0x0F); XX(0xFE); break;
2982//.. case Xsse_ADD64: XX(0x66); XX(0x0F); XX(0xD4); break;
2983//.. case Xsse_QADD8S: XX(0x66); XX(0x0F); XX(0xEC); break;
2984//.. case Xsse_QADD16S: XX(0x66); XX(0x0F); XX(0xED); break;
2985//.. case Xsse_QADD8U: XX(0x66); XX(0x0F); XX(0xDC); break;
2986//.. case Xsse_QADD16U: XX(0x66); XX(0x0F); XX(0xDD); break;
2987//.. case Xsse_AVG8U: XX(0x66); XX(0x0F); XX(0xE0); break;
2988//.. case Xsse_AVG16U: XX(0x66); XX(0x0F); XX(0xE3); break;
2989//.. case Xsse_CMPEQ8: XX(0x66); XX(0x0F); XX(0x74); break;
2990//.. case Xsse_CMPEQ16: XX(0x66); XX(0x0F); XX(0x75); break;
2991//.. case Xsse_CMPEQ32: XX(0x66); XX(0x0F); XX(0x76); break;
2992//.. case Xsse_CMPGT8S: XX(0x66); XX(0x0F); XX(0x64); break;
2993//.. case Xsse_CMPGT16S: XX(0x66); XX(0x0F); XX(0x65); break;
2994//.. case Xsse_CMPGT32S: XX(0x66); XX(0x0F); XX(0x66); break;
2995//.. case Xsse_MAX16S: XX(0x66); XX(0x0F); XX(0xEE); break;
2996//.. case Xsse_MAX8U: XX(0x66); XX(0x0F); XX(0xDE); break;
2997//.. case Xsse_MIN16S: XX(0x66); XX(0x0F); XX(0xEA); break;
2998//.. case Xsse_MIN8U: XX(0x66); XX(0x0F); XX(0xDA); break;
2999//.. case Xsse_MULHI16U: XX(0x66); XX(0x0F); XX(0xE4); break;
3000//.. case Xsse_MULHI16S: XX(0x66); XX(0x0F); XX(0xE5); break;
3001//.. case Xsse_MUL16: XX(0x66); XX(0x0F); XX(0xD5); break;
3002//.. case Xsse_SHL16: XX(0x66); XX(0x0F); XX(0xF1); break;
3003//.. case Xsse_SHL32: XX(0x66); XX(0x0F); XX(0xF2); break;
3004//.. case Xsse_SHL64: XX(0x66); XX(0x0F); XX(0xF3); break;
3005//.. case Xsse_SAR16: XX(0x66); XX(0x0F); XX(0xE1); break;
3006//.. case Xsse_SAR32: XX(0x66); XX(0x0F); XX(0xE2); break;
3007//.. case Xsse_SHR16: XX(0x66); XX(0x0F); XX(0xD1); break;
3008//.. case Xsse_SHR32: XX(0x66); XX(0x0F); XX(0xD2); break;
3009//.. case Xsse_SHR64: XX(0x66); XX(0x0F); XX(0xD3); break;
3010//.. case Xsse_SUB8: XX(0x66); XX(0x0F); XX(0xF8); break;
3011//.. case Xsse_SUB16: XX(0x66); XX(0x0F); XX(0xF9); break;
3012//.. case Xsse_SUB32: XX(0x66); XX(0x0F); XX(0xFA); break;
3013//.. case Xsse_SUB64: XX(0x66); XX(0x0F); XX(0xFB); break;
3014//.. case Xsse_QSUB8S: XX(0x66); XX(0x0F); XX(0xE8); break;
3015//.. case Xsse_QSUB16S: XX(0x66); XX(0x0F); XX(0xE9); break;
3016//.. case Xsse_QSUB8U: XX(0x66); XX(0x0F); XX(0xD8); break;
3017//.. case Xsse_QSUB16U: XX(0x66); XX(0x0F); XX(0xD9); break;
3018//.. case Xsse_UNPCKHB: XX(0x66); XX(0x0F); XX(0x68); break;
3019//.. case Xsse_UNPCKHW: XX(0x66); XX(0x0F); XX(0x69); break;
3020//.. case Xsse_UNPCKHD: XX(0x66); XX(0x0F); XX(0x6A); break;
3021//.. case Xsse_UNPCKHQ: XX(0x66); XX(0x0F); XX(0x6D); break;
3022//.. case Xsse_UNPCKLB: XX(0x66); XX(0x0F); XX(0x60); break;
3023//.. case Xsse_UNPCKLW: XX(0x66); XX(0x0F); XX(0x61); break;
3024//.. case Xsse_UNPCKLD: XX(0x66); XX(0x0F); XX(0x62); break;
3025//.. case Xsse_UNPCKLQ: XX(0x66); XX(0x0F); XX(0x6C); break;
3026//.. default: goto bad;
3027//.. }
3028//.. p = doAMode_R(p, fake(vregNo(i->Xin.SseReRg.dst)),
3029//.. fake(vregNo(i->Xin.SseReRg.src)) );
3030//.. # undef XX
3031//.. goto done;
3032//..
3033//.. case Xin_SseCMov:
3034//.. /* jmp fwds if !condition */
3035//.. *p++ = 0x70 + (i->Xin.SseCMov.cond ^ 1);
3036//.. *p++ = 0; /* # of bytes in the next bit, which we don't know yet */
3037//.. ptmp = p;
3038//..
3039//.. /* movaps %src, %dst */
3040//.. *p++ = 0x0F;
3041//.. *p++ = 0x28;
3042//.. p = doAMode_R(p, fake(vregNo(i->Xin.SseCMov.dst)),
3043//.. fake(vregNo(i->Xin.SseCMov.src)) );
3044//..
3045//.. /* Fill in the jump offset. */
3046//.. *(ptmp-1) = p - ptmp;
3047//.. goto done;
3048//..
3049//.. case Xin_SseShuf:
3050//.. *p++ = 0x66;
3051//.. *p++ = 0x0F;
3052//.. *p++ = 0x70;
3053//.. p = doAMode_R(p, fake(vregNo(i->Xin.SseShuf.dst)),
3054//.. fake(vregNo(i->Xin.SseShuf.src)) );
3055//.. *p++ = (UChar)(i->Xin.SseShuf.order);
3056//.. goto done;
3057//..
sewardjc33671d2005-02-01 20:30:00 +00003058 default:
3059 goto bad;
3060 }
3061
3062 bad:
3063 ppAMD64Instr(i);
3064 vpanic("emit_AMD64Instr");
3065 /*NOTREACHED*/
3066
sewardj813ce9e2005-02-04 21:16:48 +00003067 done:
sewardjc33671d2005-02-01 20:30:00 +00003068 vassert(p - &buf[0] <= 32);
3069 return p - &buf[0];
3070
3071# undef fake
3072}
sewardja3e98302005-02-01 15:55:05 +00003073
3074/*---------------------------------------------------------------*/
3075/*--- end host-amd64/hdefs.c ---*/
3076/*---------------------------------------------------------------*/