blob: 8aa27e62524820754bdd8e3d9b2798e538a4564c [file] [log] [blame]
sewardjbbcf1882014-01-12 12:49:10 +00001
2/*---------------------------------------------------------------*/
3/*--- begin host_arm64_defs.c ---*/
4/*---------------------------------------------------------------*/
5
6/*
7 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
9
10 Copyright (C) 2013-2013 OpenWorks
11 info@open-works.net
12
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
26 02110-1301, USA.
27
28 The GNU General Public License is contained in the file COPYING.
29*/
30
31#include "libvex_basictypes.h"
32#include "libvex.h"
33#include "libvex_trc_values.h"
34
35#include "main_util.h"
36#include "host_generic_regs.h"
37#include "host_arm64_defs.h"
38
39//ZZ UInt arm_hwcaps = 0;
40
41
42/* --------- Registers. --------- */
43
44/* The usual HReg abstraction. We use the following classes only:
45 X regs (64 bit int)
46 D regs (64 bit float, also used for 32 bit float)
47 Q regs (128 bit vector)
48*/
49
50void ppHRegARM64 ( HReg reg ) {
51 Int r;
52 /* Be generic for all virtual regs. */
53 if (hregIsVirtual(reg)) {
54 ppHReg(reg);
55 return;
56 }
57 /* But specific for real regs. */
58 switch (hregClass(reg)) {
59 case HRcInt64:
60 r = hregNumber(reg);
61 vassert(r >= 0 && r < 31);
62 vex_printf("x%d", r);
63 return;
64 case HRcFlt64:
65 r = hregNumber(reg);
66 vassert(r >= 0 && r < 32);
67 vex_printf("d%d", r);
68 return;
69 case HRcVec128:
70 r = hregNumber(reg);
71 vassert(r >= 0 && r < 32);
72 vex_printf("q%d", r);
73 return;
74 default:
75 vpanic("ppHRegARM64");
76 }
77}
78
79static void ppHRegARM64asSreg ( HReg reg ) {
80 ppHRegARM64(reg);
81 vex_printf("(S-reg)");
82}
83
84HReg hregARM64_X0 ( void ) { return mkHReg(0, HRcInt64, False); }
85HReg hregARM64_X1 ( void ) { return mkHReg(1, HRcInt64, False); }
86HReg hregARM64_X2 ( void ) { return mkHReg(2, HRcInt64, False); }
87HReg hregARM64_X3 ( void ) { return mkHReg(3, HRcInt64, False); }
88HReg hregARM64_X4 ( void ) { return mkHReg(4, HRcInt64, False); }
89HReg hregARM64_X5 ( void ) { return mkHReg(5, HRcInt64, False); }
90HReg hregARM64_X6 ( void ) { return mkHReg(6, HRcInt64, False); }
91HReg hregARM64_X7 ( void ) { return mkHReg(7, HRcInt64, False); }
92//ZZ HReg hregARM_R8 ( void ) { return mkHReg(8, HRcInt32, False); }
93HReg hregARM64_X9 ( void ) { return mkHReg(9, HRcInt64, False); }
94HReg hregARM64_X10 ( void ) { return mkHReg(10, HRcInt64, False); }
95HReg hregARM64_X11 ( void ) { return mkHReg(11, HRcInt64, False); }
96HReg hregARM64_X12 ( void ) { return mkHReg(12, HRcInt64, False); }
97HReg hregARM64_X13 ( void ) { return mkHReg(13, HRcInt64, False); }
98HReg hregARM64_X14 ( void ) { return mkHReg(14, HRcInt64, False); }
99HReg hregARM64_X15 ( void ) { return mkHReg(15, HRcInt64, False); }
100HReg hregARM64_X21 ( void ) { return mkHReg(21, HRcInt64, False); }
101HReg hregARM64_X22 ( void ) { return mkHReg(22, HRcInt64, False); }
102HReg hregARM64_X23 ( void ) { return mkHReg(23, HRcInt64, False); }
103HReg hregARM64_X24 ( void ) { return mkHReg(24, HRcInt64, False); }
104HReg hregARM64_X25 ( void ) { return mkHReg(25, HRcInt64, False); }
105HReg hregARM64_X26 ( void ) { return mkHReg(26, HRcInt64, False); }
106HReg hregARM64_X27 ( void ) { return mkHReg(27, HRcInt64, False); }
107HReg hregARM64_X28 ( void ) { return mkHReg(28, HRcInt64, False); }
108
109// Should really use D8 .. D15 for class F64, since they are callee
110// save
111HReg hregARM64_D8 ( void ) { return mkHReg(8, HRcFlt64, False); }
112HReg hregARM64_D9 ( void ) { return mkHReg(9, HRcFlt64, False); }
113HReg hregARM64_D10 ( void ) { return mkHReg(10, HRcFlt64, False); }
114HReg hregARM64_D11 ( void ) { return mkHReg(11, HRcFlt64, False); }
115HReg hregARM64_D12 ( void ) { return mkHReg(12, HRcFlt64, False); }
116HReg hregARM64_D13 ( void ) { return mkHReg(13, HRcFlt64, False); }
117//ZZ HReg hregARM_S26 ( void ) { return mkHReg(26, HRcFlt32, False); }
118//ZZ HReg hregARM_S27 ( void ) { return mkHReg(27, HRcFlt32, False); }
119//ZZ HReg hregARM_S28 ( void ) { return mkHReg(28, HRcFlt32, False); }
120//ZZ HReg hregARM_S29 ( void ) { return mkHReg(29, HRcFlt32, False); }
121//ZZ HReg hregARM_S30 ( void ) { return mkHReg(30, HRcFlt32, False); }
122HReg hregARM64_Q16 ( void ) { return mkHReg(16, HRcVec128, False); }
123HReg hregARM64_Q17 ( void ) { return mkHReg(17, HRcVec128, False); }
124HReg hregARM64_Q18 ( void ) { return mkHReg(18, HRcVec128, False); }
125//ZZ HReg hregARM_Q11 ( void ) { return mkHReg(11, HRcVec128, False); }
126//ZZ HReg hregARM_Q12 ( void ) { return mkHReg(12, HRcVec128, False); }
127//ZZ HReg hregARM_Q13 ( void ) { return mkHReg(13, HRcVec128, False); }
128//ZZ HReg hregARM_Q14 ( void ) { return mkHReg(14, HRcVec128, False); }
129//ZZ HReg hregARM_Q15 ( void ) { return mkHReg(15, HRcVec128, False); }
130
131void getAllocableRegs_ARM64 ( Int* nregs, HReg** arr )
132{
133 Int i = 0;
134 *nregs = 24;
135 *arr = LibVEX_Alloc(*nregs * sizeof(HReg));
136
137 // callee saves ones (22 to 28) are listed first, since we prefer
138 // them if they're available
139 (*arr)[i++] = hregARM64_X22();
140 (*arr)[i++] = hregARM64_X23();
141 (*arr)[i++] = hregARM64_X24();
142 (*arr)[i++] = hregARM64_X25();
143 (*arr)[i++] = hregARM64_X26();
144 (*arr)[i++] = hregARM64_X27();
145 (*arr)[i++] = hregARM64_X28();
146
147 (*arr)[i++] = hregARM64_X0();
148 (*arr)[i++] = hregARM64_X1();
149 (*arr)[i++] = hregARM64_X2();
150 (*arr)[i++] = hregARM64_X3();
151 (*arr)[i++] = hregARM64_X4();
152 (*arr)[i++] = hregARM64_X5();
153 (*arr)[i++] = hregARM64_X6();
154 (*arr)[i++] = hregARM64_X7();
155 // X8 .. who knows.
156 // X9 is a chaining/spill temporary, not available to regalloc.
157
158 // Do we really need all these?
159 //(*arr)[i++] = hregARM64_X10();
160 //(*arr)[i++] = hregARM64_X11();
161 //(*arr)[i++] = hregARM64_X12();
162 //(*arr)[i++] = hregARM64_X13();
163 //(*arr)[i++] = hregARM64_X14();
164 //(*arr)[i++] = hregARM64_X15();
165 // X21 is the guest state pointer, not available to regalloc.
166
167 // vector regs. Unfortunately not callee-saved.
168 (*arr)[i++] = hregARM64_Q16();
169 (*arr)[i++] = hregARM64_Q17();
170 (*arr)[i++] = hregARM64_Q18();
171
172 // F64 regs, all of which are callee-saved
173 (*arr)[i++] = hregARM64_D8();
174 (*arr)[i++] = hregARM64_D9();
175 (*arr)[i++] = hregARM64_D10();
176 (*arr)[i++] = hregARM64_D11();
177 (*arr)[i++] = hregARM64_D12();
178 (*arr)[i++] = hregARM64_D13();
179
180 // unavail: x21 as GSP
181 // x9 is used as a spill/reload/chaining/call temporary
182 // x8 is unassigned
183 // x30 as LR
184 // x31 because dealing with the SP-vs-ZR overloading is too
185 // confusing, and we don't need to do so, so let's just avoid
186 // the problem
187 //
188 // Currently, we have 15 allocatable integer registers:
189 // 0 1 2 3 4 5 6 7 22 23 24 25 26 27 28
190 //
191 // Hence for the allocatable integer registers we have:
192 //
193 // callee-saved: 22 23 24 25 26 27 28
194 // caller-saved: 0 1 2 3 4 5 6 7
195 //
196 // If the set of available registers changes or if the e/r status
197 // changes, be sure to re-check/sync the definition of
198 // getHRegUsage for ARMInstr_Call too.
199 vassert(i == *nregs);
200}
201
202
sewardjbbcf1882014-01-12 12:49:10 +0000203/* --------- Condition codes, ARM64 encoding. --------- */
204
205static const HChar* showARM64CondCode ( ARM64CondCode cond ) {
206 switch (cond) {
207 case ARM64cc_EQ: return "eq";
208 case ARM64cc_NE: return "ne";
209 case ARM64cc_CS: return "cs";
210 case ARM64cc_CC: return "cc";
211 case ARM64cc_MI: return "mi";
212 case ARM64cc_PL: return "pl";
213 case ARM64cc_VS: return "vs";
214 case ARM64cc_VC: return "vc";
215 case ARM64cc_HI: return "hi";
216 case ARM64cc_LS: return "ls";
217 case ARM64cc_GE: return "ge";
218 case ARM64cc_LT: return "lt";
219 case ARM64cc_GT: return "gt";
220 case ARM64cc_LE: return "le";
221 case ARM64cc_AL: return "al"; // default
222 case ARM64cc_NV: return "nv";
223 default: vpanic("showARM64CondCode");
224 }
225}
226
227
228/* --------- Memory address expressions (amodes). --------- */
229
230ARM64AMode* ARM64AMode_RI9 ( HReg reg, Int simm9 ) {
231 ARM64AMode* am = LibVEX_Alloc(sizeof(ARM64AMode));
232 am->tag = ARM64am_RI9;
233 am->ARM64am.RI9.reg = reg;
234 am->ARM64am.RI9.simm9 = simm9;
235 vassert(-256 <= simm9 && simm9 <= 255);
236 return am;
237}
238
239ARM64AMode* ARM64AMode_RI12 ( HReg reg, Int uimm12, UChar szB ) {
240 ARM64AMode* am = LibVEX_Alloc(sizeof(ARM64AMode));
241 am->tag = ARM64am_RI12;
242 am->ARM64am.RI12.reg = reg;
243 am->ARM64am.RI12.uimm12 = uimm12;
244 am->ARM64am.RI12.szB = szB;
245 vassert(uimm12 >= 0 && uimm12 <= 4095);
246 switch (szB) {
247 case 1: case 2: case 4: case 8: break;
248 default: vassert(0);
249 }
250 return am;
251}
252
253ARM64AMode* ARM64AMode_RR ( HReg base, HReg index ) {
254 ARM64AMode* am = LibVEX_Alloc(sizeof(ARM64AMode));
255 am->tag = ARM64am_RR;
256 am->ARM64am.RR.base = base;
257 am->ARM64am.RR.index = index;
258 return am;
259}
260
261static void ppARM64AMode ( ARM64AMode* am ) {
262 switch (am->tag) {
263 case ARM64am_RI9:
264 vex_printf("%d(", am->ARM64am.RI9.simm9);
265 ppHRegARM64(am->ARM64am.RI9.reg);
266 vex_printf(")");
267 break;
268 case ARM64am_RI12:
269 vex_printf("%u(", (UInt)am->ARM64am.RI12.szB
270 * (UInt)am->ARM64am.RI12.uimm12);
271 ppHRegARM64(am->ARM64am.RI12.reg);
272 vex_printf(")");
273 break;
274 case ARM64am_RR:
275 vex_printf("(");
276 ppHRegARM64(am->ARM64am.RR.base);
277 vex_printf(",");
278 ppHRegARM64(am->ARM64am.RR.index);
279 vex_printf(")");
280 break;
281 default:
282 vassert(0);
283 }
284}
285
286static void addRegUsage_ARM64AMode ( HRegUsage* u, ARM64AMode* am ) {
287 switch (am->tag) {
288 case ARM64am_RI9:
289 addHRegUse(u, HRmRead, am->ARM64am.RI9.reg);
290 return;
291 case ARM64am_RI12:
292 addHRegUse(u, HRmRead, am->ARM64am.RI12.reg);
293 return;
294 case ARM64am_RR:
295 addHRegUse(u, HRmRead, am->ARM64am.RR.base);
296 addHRegUse(u, HRmRead, am->ARM64am.RR.index);
297 return;
298 default:
299 vpanic("addRegUsage_ARM64Amode");
300 }
301}
302
303static void mapRegs_ARM64AMode ( HRegRemap* m, ARM64AMode* am ) {
304 switch (am->tag) {
305 case ARM64am_RI9:
306 am->ARM64am.RI9.reg = lookupHRegRemap(m, am->ARM64am.RI9.reg);
307 return;
308 case ARM64am_RI12:
309 am->ARM64am.RI12.reg = lookupHRegRemap(m, am->ARM64am.RI12.reg);
310 return;
311 case ARM64am_RR:
312 am->ARM64am.RR.base = lookupHRegRemap(m, am->ARM64am.RR.base);
313 am->ARM64am.RR.index = lookupHRegRemap(m, am->ARM64am.RR.index);
314 return;
315 default:
316 vpanic("mapRegs_ARM64Amode");
317 }
318}
319
320
321//ZZ /* --------- Mem AModes: Addressing Mode 2 --------- */
322//ZZ
323//ZZ ARMAMode2* ARMAMode2_RI ( HReg reg, Int simm9 ) {
324//ZZ ARMAMode2* am = LibVEX_Alloc(sizeof(ARMAMode2));
325//ZZ am->tag = ARMam2_RI;
326//ZZ am->ARMam2.RI.reg = reg;
327//ZZ am->ARMam2.RI.simm9 = simm9;
328//ZZ vassert(-255 <= simm9 && simm9 <= 255);
329//ZZ return am;
330//ZZ }
331//ZZ ARMAMode2* ARMAMode2_RR ( HReg base, HReg index ) {
332//ZZ ARMAMode2* am = LibVEX_Alloc(sizeof(ARMAMode2));
333//ZZ am->tag = ARMam2_RR;
334//ZZ am->ARMam2.RR.base = base;
335//ZZ am->ARMam2.RR.index = index;
336//ZZ return am;
337//ZZ }
338//ZZ
339//ZZ void ppARMAMode2 ( ARMAMode2* am ) {
340//ZZ switch (am->tag) {
341//ZZ case ARMam2_RI:
342//ZZ vex_printf("%d(", am->ARMam2.RI.simm9);
343//ZZ ppHRegARM(am->ARMam2.RI.reg);
344//ZZ vex_printf(")");
345//ZZ break;
346//ZZ case ARMam2_RR:
347//ZZ vex_printf("(");
348//ZZ ppHRegARM(am->ARMam2.RR.base);
349//ZZ vex_printf(",");
350//ZZ ppHRegARM(am->ARMam2.RR.index);
351//ZZ vex_printf(")");
352//ZZ break;
353//ZZ default:
354//ZZ vassert(0);
355//ZZ }
356//ZZ }
357//ZZ
358//ZZ static void addRegUsage_ARMAMode2 ( HRegUsage* u, ARMAMode2* am ) {
359//ZZ switch (am->tag) {
360//ZZ case ARMam2_RI:
361//ZZ addHRegUse(u, HRmRead, am->ARMam2.RI.reg);
362//ZZ return;
363//ZZ case ARMam2_RR:
364//ZZ // addHRegUse(u, HRmRead, am->ARMam2.RR.base);
365//ZZ // addHRegUse(u, HRmRead, am->ARMam2.RR.index);
366//ZZ // return;
367//ZZ default:
368//ZZ vpanic("addRegUsage_ARMAmode2");
369//ZZ }
370//ZZ }
371//ZZ
372//ZZ static void mapRegs_ARMAMode2 ( HRegRemap* m, ARMAMode2* am ) {
373//ZZ switch (am->tag) {
374//ZZ case ARMam2_RI:
375//ZZ am->ARMam2.RI.reg = lookupHRegRemap(m, am->ARMam2.RI.reg);
376//ZZ return;
377//ZZ case ARMam2_RR:
378//ZZ //am->ARMam2.RR.base =lookupHRegRemap(m, am->ARMam2.RR.base);
379//ZZ //am->ARMam2.RR.index = lookupHRegRemap(m, am->ARMam2.RR.index);
380//ZZ //return;
381//ZZ default:
382//ZZ vpanic("mapRegs_ARMAmode2");
383//ZZ }
384//ZZ }
385//ZZ
386//ZZ
387//ZZ /* --------- Mem AModes: Addressing Mode VFP --------- */
388//ZZ
389//ZZ ARMAModeV* mkARMAModeV ( HReg reg, Int simm11 ) {
390//ZZ ARMAModeV* am = LibVEX_Alloc(sizeof(ARMAModeV));
391//ZZ vassert(simm11 >= -1020 && simm11 <= 1020);
392//ZZ vassert(0 == (simm11 & 3));
393//ZZ am->reg = reg;
394//ZZ am->simm11 = simm11;
395//ZZ return am;
396//ZZ }
397//ZZ
398//ZZ void ppARMAModeV ( ARMAModeV* am ) {
399//ZZ vex_printf("%d(", am->simm11);
400//ZZ ppHRegARM(am->reg);
401//ZZ vex_printf(")");
402//ZZ }
403//ZZ
404//ZZ static void addRegUsage_ARMAModeV ( HRegUsage* u, ARMAModeV* am ) {
405//ZZ addHRegUse(u, HRmRead, am->reg);
406//ZZ }
407//ZZ
408//ZZ static void mapRegs_ARMAModeV ( HRegRemap* m, ARMAModeV* am ) {
409//ZZ am->reg = lookupHRegRemap(m, am->reg);
410//ZZ }
411//ZZ
412//ZZ
413//ZZ /* --------- Mem AModes: Addressing Mode Neon ------- */
414//ZZ
415//ZZ ARMAModeN *mkARMAModeN_RR ( HReg rN, HReg rM ) {
416//ZZ ARMAModeN* am = LibVEX_Alloc(sizeof(ARMAModeN));
417//ZZ am->tag = ARMamN_RR;
418//ZZ am->ARMamN.RR.rN = rN;
419//ZZ am->ARMamN.RR.rM = rM;
420//ZZ return am;
421//ZZ }
422//ZZ
423//ZZ ARMAModeN *mkARMAModeN_R ( HReg rN ) {
424//ZZ ARMAModeN* am = LibVEX_Alloc(sizeof(ARMAModeN));
425//ZZ am->tag = ARMamN_R;
426//ZZ am->ARMamN.R.rN = rN;
427//ZZ return am;
428//ZZ }
429//ZZ
430//ZZ static void addRegUsage_ARMAModeN ( HRegUsage* u, ARMAModeN* am ) {
431//ZZ if (am->tag == ARMamN_R) {
432//ZZ addHRegUse(u, HRmRead, am->ARMamN.R.rN);
433//ZZ } else {
434//ZZ addHRegUse(u, HRmRead, am->ARMamN.RR.rN);
435//ZZ addHRegUse(u, HRmRead, am->ARMamN.RR.rM);
436//ZZ }
437//ZZ }
438//ZZ
439//ZZ static void mapRegs_ARMAModeN ( HRegRemap* m, ARMAModeN* am ) {
440//ZZ if (am->tag == ARMamN_R) {
441//ZZ am->ARMamN.R.rN = lookupHRegRemap(m, am->ARMamN.R.rN);
442//ZZ } else {
443//ZZ am->ARMamN.RR.rN = lookupHRegRemap(m, am->ARMamN.RR.rN);
444//ZZ am->ARMamN.RR.rM = lookupHRegRemap(m, am->ARMamN.RR.rM);
445//ZZ }
446//ZZ }
447//ZZ
448//ZZ void ppARMAModeN ( ARMAModeN* am ) {
449//ZZ vex_printf("[");
450//ZZ if (am->tag == ARMamN_R) {
451//ZZ ppHRegARM(am->ARMamN.R.rN);
452//ZZ } else {
453//ZZ ppHRegARM(am->ARMamN.RR.rN);
454//ZZ }
455//ZZ vex_printf("]");
456//ZZ if (am->tag == ARMamN_RR) {
457//ZZ vex_printf(", ");
458//ZZ ppHRegARM(am->ARMamN.RR.rM);
459//ZZ }
460//ZZ }
461
462
463/* --------- Reg or uimm12<<{0,12} operands --------- */
464
465ARM64RIA* ARM64RIA_I12 ( UShort imm12, UChar shift ) {
466 ARM64RIA* riA = LibVEX_Alloc(sizeof(ARM64RIA));
467 riA->tag = ARM64riA_I12;
468 riA->ARM64riA.I12.imm12 = imm12;
469 riA->ARM64riA.I12.shift = shift;
470 vassert(imm12 < 4096);
471 vassert(shift == 0 || shift == 12);
472 return riA;
473}
474ARM64RIA* ARM64RIA_R ( HReg reg ) {
475 ARM64RIA* riA = LibVEX_Alloc(sizeof(ARM64RIA));
476 riA->tag = ARM64riA_R;
477 riA->ARM64riA.R.reg = reg;
478 return riA;
479}
480
481static void ppARM64RIA ( ARM64RIA* riA ) {
482 switch (riA->tag) {
483 case ARM64riA_I12:
484 vex_printf("#%u",(UInt)(riA->ARM64riA.I12.imm12
485 << riA->ARM64riA.I12.shift));
486 break;
487 case ARM64riA_R:
488 ppHRegARM64(riA->ARM64riA.R.reg);
489 break;
490 default:
491 vassert(0);
492 }
493}
494
495static void addRegUsage_ARM64RIA ( HRegUsage* u, ARM64RIA* riA ) {
496 switch (riA->tag) {
497 case ARM64riA_I12:
498 return;
499 case ARM64riA_R:
500 addHRegUse(u, HRmRead, riA->ARM64riA.R.reg);
501 return;
502 default:
503 vpanic("addRegUsage_ARM64RIA");
504 }
505}
506
507static void mapRegs_ARM64RIA ( HRegRemap* m, ARM64RIA* riA ) {
508 switch (riA->tag) {
509 case ARM64riA_I12:
510 return;
511 case ARM64riA_R:
512 riA->ARM64riA.R.reg = lookupHRegRemap(m, riA->ARM64riA.R.reg);
513 return;
514 default:
515 vpanic("mapRegs_ARM64RIA");
516 }
517}
518
519
520/* --------- Reg or "bitfield" (logic immediate) operands --------- */
521
522ARM64RIL* ARM64RIL_I13 ( UChar bitN, UChar immR, UChar immS ) {
523 ARM64RIL* riL = LibVEX_Alloc(sizeof(ARM64RIL));
524 riL->tag = ARM64riL_I13;
525 riL->ARM64riL.I13.bitN = bitN;
526 riL->ARM64riL.I13.immR = immR;
527 riL->ARM64riL.I13.immS = immS;
528 vassert(bitN < 2);
529 vassert(immR < 64);
530 vassert(immS < 64);
531 return riL;
532}
533ARM64RIL* ARM64RIL_R ( HReg reg ) {
534 ARM64RIL* riL = LibVEX_Alloc(sizeof(ARM64RIL));
535 riL->tag = ARM64riL_R;
536 riL->ARM64riL.R.reg = reg;
537 return riL;
538}
539
540static void ppARM64RIL ( ARM64RIL* riL ) {
541 switch (riL->tag) {
542 case ARM64riL_I13:
543 vex_printf("#nrs(%u,%u,%u)",
544 (UInt)riL->ARM64riL.I13.bitN,
545 (UInt)riL->ARM64riL.I13.immR,
546 (UInt)riL->ARM64riL.I13.immS);
547 break;
548 case ARM64riL_R:
549 ppHRegARM64(riL->ARM64riL.R.reg);
550 break;
551 default:
552 vassert(0);
553 }
554}
555
556static void addRegUsage_ARM64RIL ( HRegUsage* u, ARM64RIL* riL ) {
557 switch (riL->tag) {
558 case ARM64riL_I13:
559 return;
560 case ARM64riL_R:
561 addHRegUse(u, HRmRead, riL->ARM64riL.R.reg);
562 return;
563 default:
564 vpanic("addRegUsage_ARM64RIL");
565 }
566}
567
568static void mapRegs_ARM64RIL ( HRegRemap* m, ARM64RIL* riL ) {
569 switch (riL->tag) {
570 case ARM64riL_I13:
571 return;
572 case ARM64riL_R:
573 riL->ARM64riL.R.reg = lookupHRegRemap(m, riL->ARM64riL.R.reg);
574 return;
575 default:
576 vpanic("mapRegs_ARM64RIL");
577 }
578}
579
580
581/* --------------- Reg or uimm6 operands --------------- */
582
583ARM64RI6* ARM64RI6_I6 ( UInt imm6 ) {
584 ARM64RI6* ri6 = LibVEX_Alloc(sizeof(ARM64RI6));
585 ri6->tag = ARM64ri6_I6;
586 ri6->ARM64ri6.I6.imm6 = imm6;
587 vassert(imm6 > 0 && imm6 < 64);
588 return ri6;
589}
590ARM64RI6* ARM64RI6_R ( HReg reg ) {
591 ARM64RI6* ri6 = LibVEX_Alloc(sizeof(ARM64RI6));
592 ri6->tag = ARM64ri6_R;
593 ri6->ARM64ri6.R.reg = reg;
594 return ri6;
595}
596
597static void ppARM64RI6 ( ARM64RI6* ri6 ) {
598 switch (ri6->tag) {
599 case ARM64ri6_I6:
600 vex_printf("#%u", ri6->ARM64ri6.I6.imm6);
601 break;
602 case ARM64ri6_R:
603 ppHRegARM64(ri6->ARM64ri6.R.reg);
604 break;
605 default:
606 vassert(0);
607 }
608}
609
610static void addRegUsage_ARM64RI6 ( HRegUsage* u, ARM64RI6* ri6 ) {
611 switch (ri6->tag) {
612 case ARM64ri6_I6:
613 return;
614 case ARM64ri6_R:
615 addHRegUse(u, HRmRead, ri6->ARM64ri6.R.reg);
616 return;
617 default:
618 vpanic("addRegUsage_ARM64RI6");
619 }
620}
621
622static void mapRegs_ARM64RI6 ( HRegRemap* m, ARM64RI6* ri6 ) {
623 switch (ri6->tag) {
624 case ARM64ri6_I6:
625 return;
626 case ARM64ri6_R:
627 ri6->ARM64ri6.R.reg = lookupHRegRemap(m, ri6->ARM64ri6.R.reg);
628 return;
629 default:
630 vpanic("mapRegs_ARM64RI6");
631 }
632}
633
634
635//ZZ /* -------- Neon Immediate operatnd --------- */
636//ZZ
637//ZZ ARMNImm* ARMNImm_TI ( UInt type, UInt imm8 ) {
638//ZZ ARMNImm* i = LibVEX_Alloc(sizeof(ARMNImm));
639//ZZ i->type = type;
640//ZZ i->imm8 = imm8;
641//ZZ return i;
642//ZZ }
643//ZZ
644//ZZ ULong ARMNImm_to_Imm64 ( ARMNImm* imm ) {
645//ZZ int i, j;
646//ZZ ULong y, x = imm->imm8;
647//ZZ switch (imm->type) {
648//ZZ case 3:
649//ZZ x = x << 8; /* fallthrough */
650//ZZ case 2:
651//ZZ x = x << 8; /* fallthrough */
652//ZZ case 1:
653//ZZ x = x << 8; /* fallthrough */
654//ZZ case 0:
655//ZZ return (x << 32) | x;
656//ZZ case 5:
657//ZZ case 6:
658//ZZ if (imm->type == 5)
659//ZZ x = x << 8;
660//ZZ else
661//ZZ x = (x << 8) | x;
662//ZZ /* fallthrough */
663//ZZ case 4:
664//ZZ x = (x << 16) | x;
665//ZZ return (x << 32) | x;
666//ZZ case 8:
667//ZZ x = (x << 8) | 0xFF;
668//ZZ /* fallthrough */
669//ZZ case 7:
670//ZZ x = (x << 8) | 0xFF;
671//ZZ return (x << 32) | x;
672//ZZ case 9:
673//ZZ x = 0;
674//ZZ for (i = 7; i >= 0; i--) {
675//ZZ y = ((ULong)imm->imm8 >> i) & 1;
676//ZZ for (j = 0; j < 8; j++) {
677//ZZ x = (x << 1) | y;
678//ZZ }
679//ZZ }
680//ZZ return x;
681//ZZ case 10:
682//ZZ x |= (x & 0x80) << 5;
683//ZZ x |= (~x & 0x40) << 5;
684//ZZ x &= 0x187F; /* 0001 1000 0111 1111 */
685//ZZ x |= (x & 0x40) << 4;
686//ZZ x |= (x & 0x40) << 3;
687//ZZ x |= (x & 0x40) << 2;
688//ZZ x |= (x & 0x40) << 1;
689//ZZ x = x << 19;
690//ZZ x = (x << 32) | x;
691//ZZ return x;
692//ZZ default:
693//ZZ vpanic("ARMNImm_to_Imm64");
694//ZZ }
695//ZZ }
696//ZZ
697//ZZ ARMNImm* Imm64_to_ARMNImm ( ULong x ) {
698//ZZ ARMNImm tmp;
699//ZZ if ((x & 0xFFFFFFFF) == (x >> 32)) {
700//ZZ if ((x & 0xFFFFFF00) == 0)
701//ZZ return ARMNImm_TI(0, x & 0xFF);
702//ZZ if ((x & 0xFFFF00FF) == 0)
703//ZZ return ARMNImm_TI(1, (x >> 8) & 0xFF);
704//ZZ if ((x & 0xFF00FFFF) == 0)
705//ZZ return ARMNImm_TI(2, (x >> 16) & 0xFF);
706//ZZ if ((x & 0x00FFFFFF) == 0)
707//ZZ return ARMNImm_TI(3, (x >> 24) & 0xFF);
708//ZZ if ((x & 0xFFFF00FF) == 0xFF)
709//ZZ return ARMNImm_TI(7, (x >> 8) & 0xFF);
710//ZZ if ((x & 0xFF00FFFF) == 0xFFFF)
711//ZZ return ARMNImm_TI(8, (x >> 16) & 0xFF);
712//ZZ if ((x & 0xFFFF) == ((x >> 16) & 0xFFFF)) {
713//ZZ if ((x & 0xFF00) == 0)
714//ZZ return ARMNImm_TI(4, x & 0xFF);
715//ZZ if ((x & 0x00FF) == 0)
716//ZZ return ARMNImm_TI(5, (x >> 8) & 0xFF);
717//ZZ if ((x & 0xFF) == ((x >> 8) & 0xFF))
718//ZZ return ARMNImm_TI(6, x & 0xFF);
719//ZZ }
720//ZZ if ((x & 0x7FFFF) == 0) {
721//ZZ tmp.type = 10;
722//ZZ tmp.imm8 = ((x >> 19) & 0x7F) | ((x >> 24) & 0x80);
723//ZZ if (ARMNImm_to_Imm64(&tmp) == x)
724//ZZ return ARMNImm_TI(tmp.type, tmp.imm8);
725//ZZ }
726//ZZ } else {
727//ZZ /* This can only be type 9. */
728//ZZ tmp.imm8 = (((x >> 56) & 1) << 7)
729//ZZ | (((x >> 48) & 1) << 6)
730//ZZ | (((x >> 40) & 1) << 5)
731//ZZ | (((x >> 32) & 1) << 4)
732//ZZ | (((x >> 24) & 1) << 3)
733//ZZ | (((x >> 16) & 1) << 2)
734//ZZ | (((x >> 8) & 1) << 1)
735//ZZ | (((x >> 0) & 1) << 0);
736//ZZ tmp.type = 9;
737//ZZ if (ARMNImm_to_Imm64 (&tmp) == x)
738//ZZ return ARMNImm_TI(tmp.type, tmp.imm8);
739//ZZ }
740//ZZ return NULL;
741//ZZ }
742//ZZ
743//ZZ void ppARMNImm (ARMNImm* i) {
744//ZZ ULong x = ARMNImm_to_Imm64(i);
745//ZZ vex_printf("0x%llX%llX", x, x);
746//ZZ }
747//ZZ
748//ZZ /* -- Register or scalar operand --- */
749//ZZ
750//ZZ ARMNRS* mkARMNRS(ARMNRS_tag tag, HReg reg, UInt index)
751//ZZ {
752//ZZ ARMNRS *p = LibVEX_Alloc(sizeof(ARMNRS));
753//ZZ p->tag = tag;
754//ZZ p->reg = reg;
755//ZZ p->index = index;
756//ZZ return p;
757//ZZ }
758//ZZ
759//ZZ void ppARMNRS(ARMNRS *p)
760//ZZ {
761//ZZ ppHRegARM(p->reg);
762//ZZ if (p->tag == ARMNRS_Scalar) {
763//ZZ vex_printf("[%d]", p->index);
764//ZZ }
765//ZZ }
766
767/* --------- Instructions. --------- */
768
769static const HChar* showARM64LogicOp ( ARM64LogicOp op ) {
770 switch (op) {
771 case ARM64lo_AND: return "and";
772 case ARM64lo_OR: return "orr";
773 case ARM64lo_XOR: return "eor";
774 default: vpanic("showARM64LogicOp");
775 }
776}
777
778static const HChar* showARM64ShiftOp ( ARM64ShiftOp op ) {
779 switch (op) {
780 case ARM64sh_SHL: return "lsl";
781 case ARM64sh_SHR: return "lsr";
782 case ARM64sh_SAR: return "asr";
783 default: vpanic("showARM64ShiftOp");
784 }
785}
786
787static const HChar* showARM64UnaryOp ( ARM64UnaryOp op ) {
788 switch (op) {
789 case ARM64un_NEG: return "neg";
790 case ARM64un_NOT: return "not";
791 case ARM64un_CLZ: return "clz";
792 default: vpanic("showARM64UnaryOp");
793 }
794}
795
796static const HChar* showARM64MulOp ( ARM64MulOp op ) {
797 switch (op) {
798 case ARM64mul_PLAIN: return "mul ";
799 case ARM64mul_ZX: return "umulh";
800 case ARM64mul_SX: return "smulh";
801 default: vpanic("showARM64MulOp");
802 }
803}
804
805static void characteriseARM64CvtOp ( /*OUT*/HChar* syn,
806 /*OUT*/UInt* fszB, /*OUT*/UInt* iszB,
807 ARM64CvtOp op ) {
808 switch (op) {
809 case ARM64cvt_F32_I32S:
810 *syn = 's'; *fszB = 4; *iszB = 4; break;
811 case ARM64cvt_F64_I32S:
812 *syn = 's'; *fszB = 8; *iszB = 4; break;
813 case ARM64cvt_F32_I64S:
814 *syn = 's'; *fszB = 4; *iszB = 8; break;
815 case ARM64cvt_F64_I64S:
816 *syn = 's'; *fszB = 8; *iszB = 8; break;
817 case ARM64cvt_F32_I32U:
818 *syn = 'u'; *fszB = 4; *iszB = 4; break;
819 case ARM64cvt_F64_I32U:
820 *syn = 'u'; *fszB = 8; *iszB = 4; break;
821 case ARM64cvt_F32_I64U:
822 *syn = 'u'; *fszB = 4; *iszB = 8; break;
823 case ARM64cvt_F64_I64U:
824 *syn = 'u'; *fszB = 8; *iszB = 8; break;
825 default:
826 vpanic("characteriseARM64CvtOp");
827 }
828}
829
830static const HChar* showARM64FpBinOp ( ARM64FpBinOp op ) {
831 switch (op) {
832 case ARM64fpb_ADD: return "add";
833 case ARM64fpb_SUB: return "sub";
834 case ARM64fpb_MUL: return "mul";
835 case ARM64fpb_DIV: return "div";
836 default: vpanic("showARM64FpBinOp");
837 }
838}
839
840static const HChar* showARM64FpUnaryOp ( ARM64FpUnaryOp op ) {
841 switch (op) {
842 case ARM64fpu_NEG: return "neg ";
843 case ARM64fpu_ABS: return "abs ";
844 case ARM64fpu_SQRT: return "sqrt ";
845 case ARM64fpu_RINT: return "rinti";
846 default: vpanic("showARM64FpUnaryOp");
847 }
848}
849
sewardj606c4ba2014-01-26 19:11:14 +0000850static void showARM64VecBinOp(/*OUT*/const HChar** nm,
851 /*OUT*/const HChar** ar, ARM64VecBinOp op ) {
852 switch (op) {
sewardj93013432014-04-27 12:02:12 +0000853 case ARM64vecb_ADD64x2: *nm = "add "; *ar = "2d"; return;
854 case ARM64vecb_ADD32x4: *nm = "add "; *ar = "4s"; return;
855 case ARM64vecb_ADD16x8: *nm = "add "; *ar = "8h"; return;
856 case ARM64vecb_ADD8x16: *nm = "add "; *ar = "16b"; return;
857 case ARM64vecb_SUB64x2: *nm = "sub "; *ar = "2d"; return;
858 case ARM64vecb_SUB32x4: *nm = "sub "; *ar = "4s"; return;
859 case ARM64vecb_SUB16x8: *nm = "sub "; *ar = "8h"; return;
860 case ARM64vecb_SUB8x16: *nm = "sub "; *ar = "16b"; return;
861 case ARM64vecb_MUL32x4: *nm = "mul "; *ar = "4s"; return;
862 case ARM64vecb_MUL16x8: *nm = "mul "; *ar = "8h"; return;
863 case ARM64vecb_MUL8x16: *nm = "mul "; *ar = "16b"; return;
864 case ARM64vecb_FADD64x2: *nm = "fadd"; *ar = "2d"; return;
865 case ARM64vecb_FSUB64x2: *nm = "fsub"; *ar = "2d"; return;
866 case ARM64vecb_FMUL64x2: *nm = "fmul"; *ar = "2d"; return;
867 case ARM64vecb_FDIV64x2: *nm = "fdiv"; *ar = "2d"; return;
868 case ARM64vecb_FADD32x4: *nm = "fadd"; *ar = "4s"; return;
869 case ARM64vecb_FSUB32x4: *nm = "fsub"; *ar = "4s"; return;
870 case ARM64vecb_FMUL32x4: *nm = "fmul"; *ar = "4s"; return;
871 case ARM64vecb_FDIV32x4: *nm = "fdiv"; *ar = "4s"; return;
872 case ARM64vecb_UMAX32x4: *nm = "umax"; *ar = "4s"; return;
873 case ARM64vecb_UMAX16x8: *nm = "umax"; *ar = "8h"; return;
874 case ARM64vecb_UMAX8x16: *nm = "umax"; *ar = "16b"; return;
875 case ARM64vecb_UMIN32x4: *nm = "umin"; *ar = "4s"; return;
876 case ARM64vecb_UMIN16x8: *nm = "umin"; *ar = "8h"; return;
877 case ARM64vecb_UMIN8x16: *nm = "umin"; *ar = "16b"; return;
878 case ARM64vecb_SMAX32x4: *nm = "smax"; *ar = "4s"; return;
879 case ARM64vecb_SMAX16x8: *nm = "smax"; *ar = "8h"; return;
880 case ARM64vecb_SMAX8x16: *nm = "smax"; *ar = "16b"; return;
881 case ARM64vecb_SMIN32x4: *nm = "smin"; *ar = "4s"; return;
882 case ARM64vecb_SMIN16x8: *nm = "smin"; *ar = "8h"; return;
883 case ARM64vecb_SMIN8x16: *nm = "smin"; *ar = "16b"; return;
884 case ARM64vecb_AND: *nm = "and "; *ar = "all"; return;
885 case ARM64vecb_ORR: *nm = "orr "; *ar = "all"; return;
886 case ARM64vecb_XOR: *nm = "eor "; *ar = "all"; return;
887 case ARM64vecb_CMEQ64x2: *nm = "cmeq"; *ar = "2d"; return;
888 case ARM64vecb_CMEQ32x4: *nm = "cmeq"; *ar = "4s"; return;
889 case ARM64vecb_CMEQ16x8: *nm = "cmeq"; *ar = "8h"; return;
890 case ARM64vecb_CMEQ8x16: *nm = "cmeq"; *ar = "16b"; return;
891 case ARM64vecb_CMHI64x2: *nm = "cmhi"; *ar = "2d"; return;
892 case ARM64vecb_CMHI32x4: *nm = "cmhi"; *ar = "4s"; return;
893 case ARM64vecb_CMHI16x8: *nm = "cmhi"; *ar = "8h"; return;
894 case ARM64vecb_CMHI8x16: *nm = "cmhi"; *ar = "16b"; return;
895 case ARM64vecb_CMGT64x2: *nm = "cmgt"; *ar = "2d"; return;
896 case ARM64vecb_CMGT32x4: *nm = "cmgt"; *ar = "4s"; return;
897 case ARM64vecb_CMGT16x8: *nm = "cmgt"; *ar = "8h"; return;
898 case ARM64vecb_CMGT8x16: *nm = "cmgt"; *ar = "16b"; return;
sewardj2bd1ffe2014-03-27 18:59:00 +0000899 case ARM64vecb_FCMEQ64x2: *nm = "fcmeq"; *ar = "2d"; return;
900 case ARM64vecb_FCMEQ32x4: *nm = "fcmeq"; *ar = "4s"; return;
901 case ARM64vecb_FCMGE64x2: *nm = "fcmge"; *ar = "2d"; return;
902 case ARM64vecb_FCMGE32x4: *nm = "fcmge"; *ar = "4s"; return;
903 case ARM64vecb_FCMGT64x2: *nm = "fcmgt"; *ar = "2d"; return;
904 case ARM64vecb_FCMGT32x4: *nm = "fcmgt"; *ar = "4s"; return;
sewardj93013432014-04-27 12:02:12 +0000905 case ARM64vecb_TBL1: *nm = "tbl "; *ar = "16b"; return;
sewardj606c4ba2014-01-26 19:11:14 +0000906 default: vpanic("showARM64VecBinOp");
907 }
908}
909
sewardjfab09142014-02-10 10:28:13 +0000910static void showARM64VecUnaryOp(/*OUT*/const HChar** nm,
911 /*OUT*/const HChar** ar, ARM64VecUnaryOp op )
912{
913 switch (op) {
sewardje520bb32014-02-17 11:00:53 +0000914 case ARM64vecu_FNEG64x2: *nm = "fneg "; *ar = "2d"; return;
sewardjfab09142014-02-10 10:28:13 +0000915 case ARM64vecu_FNEG32x4: *nm = "fneg "; *ar = "4s"; return;
916 case ARM64vecu_FABS64x2: *nm = "fabs "; *ar = "2d"; return;
917 case ARM64vecu_FABS32x4: *nm = "fabs "; *ar = "4s"; return;
sewardje520bb32014-02-17 11:00:53 +0000918 case ARM64vecu_NOT: *nm = "not "; *ar = "all"; return;
919 default: vpanic("showARM64VecUnaryOp");
920 }
921}
922
923static void showARM64VecShiftOp(/*OUT*/const HChar** nm,
924 /*OUT*/const HChar** ar,
925 ARM64VecShiftOp op )
926{
927 switch (op) {
928 case ARM64vecsh_USHR64x2: *nm = "ushr "; *ar = "2d"; return;
sewardj93013432014-04-27 12:02:12 +0000929 case ARM64vecsh_USHR32x4: *nm = "ushr "; *ar = "4s"; return;
sewardj1eaaec22014-03-07 22:52:19 +0000930 case ARM64vecsh_USHR16x8: *nm = "ushr "; *ar = "8h"; return;
sewardj93013432014-04-27 12:02:12 +0000931 case ARM64vecsh_USHR8x16: *nm = "ushr "; *ar = "16b"; return;
sewardje520bb32014-02-17 11:00:53 +0000932 case ARM64vecsh_SSHR64x2: *nm = "sshr "; *ar = "2d"; return;
sewardj93013432014-04-27 12:02:12 +0000933 case ARM64vecsh_SSHR32x4: *nm = "sshr "; *ar = "4s"; return;
934 case ARM64vecsh_SSHR16x8: *nm = "sshr "; *ar = "8h"; return;
935 case ARM64vecsh_SSHR8x16: *nm = "sshr "; *ar = "16b"; return;
936 case ARM64vecsh_SHL64x2: *nm = "shl "; *ar = "2d"; return;
sewardj32d86752014-03-02 12:47:18 +0000937 case ARM64vecsh_SHL32x4: *nm = "shl "; *ar = "4s"; return;
sewardj93013432014-04-27 12:02:12 +0000938 case ARM64vecsh_SHL16x8: *nm = "shl "; *ar = "8h"; return;
939 case ARM64vecsh_SHL8x16: *nm = "shl "; *ar = "16b"; return;
sewardje520bb32014-02-17 11:00:53 +0000940 default: vpanic("showARM64VecShiftImmOp");
sewardjfab09142014-02-10 10:28:13 +0000941 }
942}
943
sewardjbbcf1882014-01-12 12:49:10 +0000944//ZZ const HChar* showARMNeonBinOp ( ARMNeonBinOp op ) {
945//ZZ switch (op) {
946//ZZ case ARMneon_VAND: return "vand";
947//ZZ case ARMneon_VORR: return "vorr";
948//ZZ case ARMneon_VXOR: return "veor";
949//ZZ case ARMneon_VADD: return "vadd";
950//ZZ case ARMneon_VRHADDS: return "vrhadd";
951//ZZ case ARMneon_VRHADDU: return "vrhadd";
952//ZZ case ARMneon_VADDFP: return "vadd";
953//ZZ case ARMneon_VPADDFP: return "vpadd";
954//ZZ case ARMneon_VABDFP: return "vabd";
955//ZZ case ARMneon_VSUB: return "vsub";
956//ZZ case ARMneon_VSUBFP: return "vsub";
957//ZZ case ARMneon_VMINU: return "vmin";
958//ZZ case ARMneon_VMINS: return "vmin";
959//ZZ case ARMneon_VMINF: return "vmin";
960//ZZ case ARMneon_VMAXU: return "vmax";
961//ZZ case ARMneon_VMAXS: return "vmax";
962//ZZ case ARMneon_VMAXF: return "vmax";
963//ZZ case ARMneon_VQADDU: return "vqadd";
964//ZZ case ARMneon_VQADDS: return "vqadd";
965//ZZ case ARMneon_VQSUBU: return "vqsub";
966//ZZ case ARMneon_VQSUBS: return "vqsub";
967//ZZ case ARMneon_VCGTU: return "vcgt";
968//ZZ case ARMneon_VCGTS: return "vcgt";
969//ZZ case ARMneon_VCGTF: return "vcgt";
970//ZZ case ARMneon_VCGEF: return "vcgt";
971//ZZ case ARMneon_VCGEU: return "vcge";
972//ZZ case ARMneon_VCGES: return "vcge";
973//ZZ case ARMneon_VCEQ: return "vceq";
974//ZZ case ARMneon_VCEQF: return "vceq";
975//ZZ case ARMneon_VPADD: return "vpadd";
976//ZZ case ARMneon_VPMINU: return "vpmin";
977//ZZ case ARMneon_VPMINS: return "vpmin";
978//ZZ case ARMneon_VPMINF: return "vpmin";
979//ZZ case ARMneon_VPMAXU: return "vpmax";
980//ZZ case ARMneon_VPMAXS: return "vpmax";
981//ZZ case ARMneon_VPMAXF: return "vpmax";
982//ZZ case ARMneon_VEXT: return "vext";
983//ZZ case ARMneon_VMUL: return "vmuli";
984//ZZ case ARMneon_VMULLU: return "vmull";
985//ZZ case ARMneon_VMULLS: return "vmull";
986//ZZ case ARMneon_VMULP: return "vmul";
987//ZZ case ARMneon_VMULFP: return "vmul";
988//ZZ case ARMneon_VMULLP: return "vmul";
989//ZZ case ARMneon_VQDMULH: return "vqdmulh";
990//ZZ case ARMneon_VQRDMULH: return "vqrdmulh";
991//ZZ case ARMneon_VQDMULL: return "vqdmull";
992//ZZ case ARMneon_VTBL: return "vtbl";
993//ZZ case ARMneon_VRECPS: return "vrecps";
994//ZZ case ARMneon_VRSQRTS: return "vrecps";
995//ZZ /* ... */
996//ZZ default: vpanic("showARMNeonBinOp");
997//ZZ }
998//ZZ }
999//ZZ
1000//ZZ const HChar* showARMNeonBinOpDataType ( ARMNeonBinOp op ) {
1001//ZZ switch (op) {
1002//ZZ case ARMneon_VAND:
1003//ZZ case ARMneon_VORR:
1004//ZZ case ARMneon_VXOR:
1005//ZZ return "";
1006//ZZ case ARMneon_VADD:
1007//ZZ case ARMneon_VSUB:
1008//ZZ case ARMneon_VEXT:
1009//ZZ case ARMneon_VMUL:
1010//ZZ case ARMneon_VPADD:
1011//ZZ case ARMneon_VTBL:
1012//ZZ case ARMneon_VCEQ:
1013//ZZ return ".i";
1014//ZZ case ARMneon_VRHADDU:
1015//ZZ case ARMneon_VMINU:
1016//ZZ case ARMneon_VMAXU:
1017//ZZ case ARMneon_VQADDU:
1018//ZZ case ARMneon_VQSUBU:
1019//ZZ case ARMneon_VCGTU:
1020//ZZ case ARMneon_VCGEU:
1021//ZZ case ARMneon_VMULLU:
1022//ZZ case ARMneon_VPMINU:
1023//ZZ case ARMneon_VPMAXU:
1024//ZZ return ".u";
1025//ZZ case ARMneon_VRHADDS:
1026//ZZ case ARMneon_VMINS:
1027//ZZ case ARMneon_VMAXS:
1028//ZZ case ARMneon_VQADDS:
1029//ZZ case ARMneon_VQSUBS:
1030//ZZ case ARMneon_VCGTS:
1031//ZZ case ARMneon_VCGES:
1032//ZZ case ARMneon_VQDMULL:
1033//ZZ case ARMneon_VMULLS:
1034//ZZ case ARMneon_VPMINS:
1035//ZZ case ARMneon_VPMAXS:
1036//ZZ case ARMneon_VQDMULH:
1037//ZZ case ARMneon_VQRDMULH:
1038//ZZ return ".s";
1039//ZZ case ARMneon_VMULP:
1040//ZZ case ARMneon_VMULLP:
1041//ZZ return ".p";
1042//ZZ case ARMneon_VADDFP:
1043//ZZ case ARMneon_VABDFP:
1044//ZZ case ARMneon_VPADDFP:
1045//ZZ case ARMneon_VSUBFP:
1046//ZZ case ARMneon_VMULFP:
1047//ZZ case ARMneon_VMINF:
1048//ZZ case ARMneon_VMAXF:
1049//ZZ case ARMneon_VPMINF:
1050//ZZ case ARMneon_VPMAXF:
1051//ZZ case ARMneon_VCGTF:
1052//ZZ case ARMneon_VCGEF:
1053//ZZ case ARMneon_VCEQF:
1054//ZZ case ARMneon_VRECPS:
1055//ZZ case ARMneon_VRSQRTS:
1056//ZZ return ".f";
1057//ZZ /* ... */
1058//ZZ default: vpanic("showARMNeonBinOpDataType");
1059//ZZ }
1060//ZZ }
1061//ZZ
1062//ZZ const HChar* showARMNeonUnOp ( ARMNeonUnOp op ) {
1063//ZZ switch (op) {
1064//ZZ case ARMneon_COPY: return "vmov";
1065//ZZ case ARMneon_COPYLS: return "vmov";
1066//ZZ case ARMneon_COPYLU: return "vmov";
1067//ZZ case ARMneon_COPYN: return "vmov";
1068//ZZ case ARMneon_COPYQNSS: return "vqmovn";
1069//ZZ case ARMneon_COPYQNUS: return "vqmovun";
1070//ZZ case ARMneon_COPYQNUU: return "vqmovn";
1071//ZZ case ARMneon_NOT: return "vmvn";
1072//ZZ case ARMneon_EQZ: return "vceq";
1073//ZZ case ARMneon_CNT: return "vcnt";
1074//ZZ case ARMneon_CLS: return "vcls";
1075//ZZ case ARMneon_CLZ: return "vclz";
1076//ZZ case ARMneon_DUP: return "vdup";
1077//ZZ case ARMneon_PADDLS: return "vpaddl";
1078//ZZ case ARMneon_PADDLU: return "vpaddl";
1079//ZZ case ARMneon_VQSHLNSS: return "vqshl";
1080//ZZ case ARMneon_VQSHLNUU: return "vqshl";
1081//ZZ case ARMneon_VQSHLNUS: return "vqshlu";
1082//ZZ case ARMneon_REV16: return "vrev16";
1083//ZZ case ARMneon_REV32: return "vrev32";
1084//ZZ case ARMneon_REV64: return "vrev64";
1085//ZZ case ARMneon_VCVTFtoU: return "vcvt";
1086//ZZ case ARMneon_VCVTFtoS: return "vcvt";
1087//ZZ case ARMneon_VCVTUtoF: return "vcvt";
1088//ZZ case ARMneon_VCVTStoF: return "vcvt";
1089//ZZ case ARMneon_VCVTFtoFixedU: return "vcvt";
1090//ZZ case ARMneon_VCVTFtoFixedS: return "vcvt";
1091//ZZ case ARMneon_VCVTFixedUtoF: return "vcvt";
1092//ZZ case ARMneon_VCVTFixedStoF: return "vcvt";
1093//ZZ case ARMneon_VCVTF32toF16: return "vcvt";
1094//ZZ case ARMneon_VCVTF16toF32: return "vcvt";
1095//ZZ case ARMneon_VRECIP: return "vrecip";
1096//ZZ case ARMneon_VRECIPF: return "vrecipf";
1097//ZZ case ARMneon_VNEGF: return "vneg";
1098//ZZ case ARMneon_ABS: return "vabs";
1099//ZZ case ARMneon_VABSFP: return "vabsfp";
1100//ZZ case ARMneon_VRSQRTEFP: return "vrsqrtefp";
1101//ZZ case ARMneon_VRSQRTE: return "vrsqrte";
1102//ZZ /* ... */
1103//ZZ default: vpanic("showARMNeonUnOp");
1104//ZZ }
1105//ZZ }
1106//ZZ
1107//ZZ const HChar* showARMNeonUnOpDataType ( ARMNeonUnOp op ) {
1108//ZZ switch (op) {
1109//ZZ case ARMneon_COPY:
1110//ZZ case ARMneon_NOT:
1111//ZZ return "";
1112//ZZ case ARMneon_COPYN:
1113//ZZ case ARMneon_EQZ:
1114//ZZ case ARMneon_CNT:
1115//ZZ case ARMneon_DUP:
1116//ZZ case ARMneon_REV16:
1117//ZZ case ARMneon_REV32:
1118//ZZ case ARMneon_REV64:
1119//ZZ return ".i";
1120//ZZ case ARMneon_COPYLU:
1121//ZZ case ARMneon_PADDLU:
1122//ZZ case ARMneon_COPYQNUU:
1123//ZZ case ARMneon_VQSHLNUU:
1124//ZZ case ARMneon_VRECIP:
1125//ZZ case ARMneon_VRSQRTE:
1126//ZZ return ".u";
1127//ZZ case ARMneon_CLS:
1128//ZZ case ARMneon_CLZ:
1129//ZZ case ARMneon_COPYLS:
1130//ZZ case ARMneon_PADDLS:
1131//ZZ case ARMneon_COPYQNSS:
1132//ZZ case ARMneon_COPYQNUS:
1133//ZZ case ARMneon_VQSHLNSS:
1134//ZZ case ARMneon_VQSHLNUS:
1135//ZZ case ARMneon_ABS:
1136//ZZ return ".s";
1137//ZZ case ARMneon_VRECIPF:
1138//ZZ case ARMneon_VNEGF:
1139//ZZ case ARMneon_VABSFP:
1140//ZZ case ARMneon_VRSQRTEFP:
1141//ZZ return ".f";
1142//ZZ case ARMneon_VCVTFtoU: return ".u32.f32";
1143//ZZ case ARMneon_VCVTFtoS: return ".s32.f32";
1144//ZZ case ARMneon_VCVTUtoF: return ".f32.u32";
1145//ZZ case ARMneon_VCVTStoF: return ".f32.s32";
1146//ZZ case ARMneon_VCVTF16toF32: return ".f32.f16";
1147//ZZ case ARMneon_VCVTF32toF16: return ".f16.f32";
1148//ZZ case ARMneon_VCVTFtoFixedU: return ".u32.f32";
1149//ZZ case ARMneon_VCVTFtoFixedS: return ".s32.f32";
1150//ZZ case ARMneon_VCVTFixedUtoF: return ".f32.u32";
1151//ZZ case ARMneon_VCVTFixedStoF: return ".f32.s32";
1152//ZZ /* ... */
1153//ZZ default: vpanic("showARMNeonUnOpDataType");
1154//ZZ }
1155//ZZ }
1156//ZZ
1157//ZZ const HChar* showARMNeonUnOpS ( ARMNeonUnOpS op ) {
1158//ZZ switch (op) {
1159//ZZ case ARMneon_SETELEM: return "vmov";
1160//ZZ case ARMneon_GETELEMU: return "vmov";
1161//ZZ case ARMneon_GETELEMS: return "vmov";
1162//ZZ case ARMneon_VDUP: return "vdup";
1163//ZZ /* ... */
1164//ZZ default: vpanic("showARMNeonUnarySOp");
1165//ZZ }
1166//ZZ }
1167//ZZ
1168//ZZ const HChar* showARMNeonUnOpSDataType ( ARMNeonUnOpS op ) {
1169//ZZ switch (op) {
1170//ZZ case ARMneon_SETELEM:
1171//ZZ case ARMneon_VDUP:
1172//ZZ return ".i";
1173//ZZ case ARMneon_GETELEMS:
1174//ZZ return ".s";
1175//ZZ case ARMneon_GETELEMU:
1176//ZZ return ".u";
1177//ZZ /* ... */
1178//ZZ default: vpanic("showARMNeonUnarySOp");
1179//ZZ }
1180//ZZ }
1181//ZZ
1182//ZZ const HChar* showARMNeonShiftOp ( ARMNeonShiftOp op ) {
1183//ZZ switch (op) {
1184//ZZ case ARMneon_VSHL: return "vshl";
1185//ZZ case ARMneon_VSAL: return "vshl";
1186//ZZ case ARMneon_VQSHL: return "vqshl";
1187//ZZ case ARMneon_VQSAL: return "vqshl";
1188//ZZ /* ... */
1189//ZZ default: vpanic("showARMNeonShiftOp");
1190//ZZ }
1191//ZZ }
1192//ZZ
1193//ZZ const HChar* showARMNeonShiftOpDataType ( ARMNeonShiftOp op ) {
1194//ZZ switch (op) {
1195//ZZ case ARMneon_VSHL:
1196//ZZ case ARMneon_VQSHL:
1197//ZZ return ".u";
1198//ZZ case ARMneon_VSAL:
1199//ZZ case ARMneon_VQSAL:
1200//ZZ return ".s";
1201//ZZ /* ... */
1202//ZZ default: vpanic("showARMNeonShiftOpDataType");
1203//ZZ }
1204//ZZ }
1205//ZZ
1206//ZZ const HChar* showARMNeonDualOp ( ARMNeonDualOp op ) {
1207//ZZ switch (op) {
1208//ZZ case ARMneon_TRN: return "vtrn";
1209//ZZ case ARMneon_ZIP: return "vzip";
1210//ZZ case ARMneon_UZP: return "vuzp";
1211//ZZ /* ... */
1212//ZZ default: vpanic("showARMNeonDualOp");
1213//ZZ }
1214//ZZ }
1215//ZZ
1216//ZZ const HChar* showARMNeonDualOpDataType ( ARMNeonDualOp op ) {
1217//ZZ switch (op) {
1218//ZZ case ARMneon_TRN:
1219//ZZ case ARMneon_ZIP:
1220//ZZ case ARMneon_UZP:
1221//ZZ return "i";
1222//ZZ /* ... */
1223//ZZ default: vpanic("showARMNeonDualOp");
1224//ZZ }
1225//ZZ }
1226//ZZ
1227//ZZ static const HChar* showARMNeonDataSize_wrk ( UInt size )
1228//ZZ {
1229//ZZ switch (size) {
1230//ZZ case 0: return "8";
1231//ZZ case 1: return "16";
1232//ZZ case 2: return "32";
1233//ZZ case 3: return "64";
1234//ZZ default: vpanic("showARMNeonDataSize");
1235//ZZ }
1236//ZZ }
1237//ZZ
1238//ZZ static const HChar* showARMNeonDataSize ( ARMInstr* i )
1239//ZZ {
1240//ZZ switch (i->tag) {
1241//ZZ case ARMin_NBinary:
1242//ZZ if (i->ARMin.NBinary.op == ARMneon_VEXT)
1243//ZZ return "8";
1244//ZZ if (i->ARMin.NBinary.op == ARMneon_VAND ||
1245//ZZ i->ARMin.NBinary.op == ARMneon_VORR ||
1246//ZZ i->ARMin.NBinary.op == ARMneon_VXOR)
1247//ZZ return "";
1248//ZZ return showARMNeonDataSize_wrk(i->ARMin.NBinary.size);
1249//ZZ case ARMin_NUnary:
1250//ZZ if (i->ARMin.NUnary.op == ARMneon_COPY ||
1251//ZZ i->ARMin.NUnary.op == ARMneon_NOT ||
1252//ZZ i->ARMin.NUnary.op == ARMneon_VCVTF32toF16||
1253//ZZ i->ARMin.NUnary.op == ARMneon_VCVTF16toF32||
1254//ZZ i->ARMin.NUnary.op == ARMneon_VCVTFtoFixedS ||
1255//ZZ i->ARMin.NUnary.op == ARMneon_VCVTFtoFixedU ||
1256//ZZ i->ARMin.NUnary.op == ARMneon_VCVTFixedStoF ||
1257//ZZ i->ARMin.NUnary.op == ARMneon_VCVTFixedUtoF ||
1258//ZZ i->ARMin.NUnary.op == ARMneon_VCVTFtoS ||
1259//ZZ i->ARMin.NUnary.op == ARMneon_VCVTFtoU ||
1260//ZZ i->ARMin.NUnary.op == ARMneon_VCVTStoF ||
1261//ZZ i->ARMin.NUnary.op == ARMneon_VCVTUtoF)
1262//ZZ return "";
1263//ZZ if (i->ARMin.NUnary.op == ARMneon_VQSHLNSS ||
1264//ZZ i->ARMin.NUnary.op == ARMneon_VQSHLNUU ||
1265//ZZ i->ARMin.NUnary.op == ARMneon_VQSHLNUS) {
1266//ZZ UInt size;
1267//ZZ size = i->ARMin.NUnary.size;
1268//ZZ if (size & 0x40)
1269//ZZ return "64";
1270//ZZ if (size & 0x20)
1271//ZZ return "32";
1272//ZZ if (size & 0x10)
1273//ZZ return "16";
1274//ZZ if (size & 0x08)
1275//ZZ return "8";
1276//ZZ vpanic("showARMNeonDataSize");
1277//ZZ }
1278//ZZ return showARMNeonDataSize_wrk(i->ARMin.NUnary.size);
1279//ZZ case ARMin_NUnaryS:
1280//ZZ if (i->ARMin.NUnaryS.op == ARMneon_VDUP) {
1281//ZZ int size;
1282//ZZ size = i->ARMin.NUnaryS.size;
1283//ZZ if ((size & 1) == 1)
1284//ZZ return "8";
1285//ZZ if ((size & 3) == 2)
1286//ZZ return "16";
1287//ZZ if ((size & 7) == 4)
1288//ZZ return "32";
1289//ZZ vpanic("showARMNeonDataSize");
1290//ZZ }
1291//ZZ return showARMNeonDataSize_wrk(i->ARMin.NUnaryS.size);
1292//ZZ case ARMin_NShift:
1293//ZZ return showARMNeonDataSize_wrk(i->ARMin.NShift.size);
1294//ZZ case ARMin_NDual:
1295//ZZ return showARMNeonDataSize_wrk(i->ARMin.NDual.size);
1296//ZZ default:
1297//ZZ vpanic("showARMNeonDataSize");
1298//ZZ }
1299//ZZ }
1300
1301ARM64Instr* ARM64Instr_Arith ( HReg dst,
1302 HReg argL, ARM64RIA* argR, Bool isAdd ) {
1303 ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
1304 i->tag = ARM64in_Arith;
1305 i->ARM64in.Arith.dst = dst;
1306 i->ARM64in.Arith.argL = argL;
1307 i->ARM64in.Arith.argR = argR;
1308 i->ARM64in.Arith.isAdd = isAdd;
1309 return i;
1310}
1311ARM64Instr* ARM64Instr_Cmp ( HReg argL, ARM64RIA* argR, Bool is64 ) {
1312 ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
1313 i->tag = ARM64in_Cmp;
1314 i->ARM64in.Cmp.argL = argL;
1315 i->ARM64in.Cmp.argR = argR;
1316 i->ARM64in.Cmp.is64 = is64;
1317 return i;
1318}
1319ARM64Instr* ARM64Instr_Logic ( HReg dst,
1320 HReg argL, ARM64RIL* argR, ARM64LogicOp op ) {
1321 ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
1322 i->tag = ARM64in_Logic;
1323 i->ARM64in.Logic.dst = dst;
1324 i->ARM64in.Logic.argL = argL;
1325 i->ARM64in.Logic.argR = argR;
1326 i->ARM64in.Logic.op = op;
1327 return i;
1328}
1329ARM64Instr* ARM64Instr_Test ( HReg argL, ARM64RIL* argR ) {
1330 ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
1331 i->tag = ARM64in_Test;
1332 i->ARM64in.Test.argL = argL;
1333 i->ARM64in.Test.argR = argR;
1334 return i;
1335}
1336ARM64Instr* ARM64Instr_Shift ( HReg dst,
1337 HReg argL, ARM64RI6* argR, ARM64ShiftOp op ) {
1338 ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
1339 i->tag = ARM64in_Shift;
1340 i->ARM64in.Shift.dst = dst;
1341 i->ARM64in.Shift.argL = argL;
1342 i->ARM64in.Shift.argR = argR;
1343 i->ARM64in.Shift.op = op;
1344 return i;
1345}
1346ARM64Instr* ARM64Instr_Unary ( HReg dst, HReg src, ARM64UnaryOp op ) {
1347 ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
1348 i->tag = ARM64in_Unary;
1349 i->ARM64in.Unary.dst = dst;
1350 i->ARM64in.Unary.src = src;
1351 i->ARM64in.Unary.op = op;
1352 return i;
1353}
1354ARM64Instr* ARM64Instr_MovI ( HReg dst, HReg src ) {
1355 ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
1356 i->tag = ARM64in_MovI;
1357 i->ARM64in.MovI.dst = dst;
1358 i->ARM64in.MovI.src = src;
1359 vassert(hregClass(src) == HRcInt64);
1360 vassert(hregClass(dst) == HRcInt64);
1361 return i;
1362}
1363ARM64Instr* ARM64Instr_Imm64 ( HReg dst, ULong imm64 ) {
1364 ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
1365 i->tag = ARM64in_Imm64;
1366 i->ARM64in.Imm64.dst = dst;
1367 i->ARM64in.Imm64.imm64 = imm64;
1368 return i;
1369}
1370ARM64Instr* ARM64Instr_LdSt64 ( Bool isLoad, HReg rD, ARM64AMode* amode ) {
1371 ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
1372 i->tag = ARM64in_LdSt64;
1373 i->ARM64in.LdSt64.isLoad = isLoad;
1374 i->ARM64in.LdSt64.rD = rD;
1375 i->ARM64in.LdSt64.amode = amode;
1376 return i;
1377}
1378ARM64Instr* ARM64Instr_LdSt32 ( Bool isLoad, HReg rD, ARM64AMode* amode ) {
1379 ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
1380 i->tag = ARM64in_LdSt32;
1381 i->ARM64in.LdSt32.isLoad = isLoad;
1382 i->ARM64in.LdSt32.rD = rD;
1383 i->ARM64in.LdSt32.amode = amode;
1384 return i;
1385}
1386ARM64Instr* ARM64Instr_LdSt16 ( Bool isLoad, HReg rD, ARM64AMode* amode ) {
1387 ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
1388 i->tag = ARM64in_LdSt16;
1389 i->ARM64in.LdSt16.isLoad = isLoad;
1390 i->ARM64in.LdSt16.rD = rD;
1391 i->ARM64in.LdSt16.amode = amode;
1392 return i;
1393}
1394ARM64Instr* ARM64Instr_LdSt8 ( Bool isLoad, HReg rD, ARM64AMode* amode ) {
1395 ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
1396 i->tag = ARM64in_LdSt8;
1397 i->ARM64in.LdSt8.isLoad = isLoad;
1398 i->ARM64in.LdSt8.rD = rD;
1399 i->ARM64in.LdSt8.amode = amode;
1400 return i;
1401}
1402ARM64Instr* ARM64Instr_XDirect ( Addr64 dstGA, ARM64AMode* amPC,
1403 ARM64CondCode cond, Bool toFastEP ) {
1404 ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
1405 i->tag = ARM64in_XDirect;
1406 i->ARM64in.XDirect.dstGA = dstGA;
1407 i->ARM64in.XDirect.amPC = amPC;
1408 i->ARM64in.XDirect.cond = cond;
1409 i->ARM64in.XDirect.toFastEP = toFastEP;
1410 return i;
1411}
1412ARM64Instr* ARM64Instr_XIndir ( HReg dstGA, ARM64AMode* amPC,
1413 ARM64CondCode cond ) {
1414 ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
1415 i->tag = ARM64in_XIndir;
1416 i->ARM64in.XIndir.dstGA = dstGA;
1417 i->ARM64in.XIndir.amPC = amPC;
1418 i->ARM64in.XIndir.cond = cond;
1419 return i;
1420}
1421ARM64Instr* ARM64Instr_XAssisted ( HReg dstGA, ARM64AMode* amPC,
1422 ARM64CondCode cond, IRJumpKind jk ) {
1423 ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
1424 i->tag = ARM64in_XAssisted;
1425 i->ARM64in.XAssisted.dstGA = dstGA;
1426 i->ARM64in.XAssisted.amPC = amPC;
1427 i->ARM64in.XAssisted.cond = cond;
1428 i->ARM64in.XAssisted.jk = jk;
1429 return i;
1430}
1431ARM64Instr* ARM64Instr_CSel ( HReg dst, HReg argL, HReg argR,
1432 ARM64CondCode cond ) {
1433 ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
1434 i->tag = ARM64in_CSel;
1435 i->ARM64in.CSel.dst = dst;
1436 i->ARM64in.CSel.argL = argL;
1437 i->ARM64in.CSel.argR = argR;
1438 i->ARM64in.CSel.cond = cond;
1439 return i;
1440}
1441ARM64Instr* ARM64Instr_Call ( ARM64CondCode cond, HWord target, Int nArgRegs,
1442 RetLoc rloc ) {
1443 ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
1444 i->tag = ARM64in_Call;
1445 i->ARM64in.Call.cond = cond;
1446 i->ARM64in.Call.target = target;
1447 i->ARM64in.Call.nArgRegs = nArgRegs;
1448 i->ARM64in.Call.rloc = rloc;
1449 vassert(is_sane_RetLoc(rloc));
1450 return i;
1451}
1452extern ARM64Instr* ARM64Instr_AddToSP ( Int simm ) {
1453 ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
1454 i->tag = ARM64in_AddToSP;
1455 i->ARM64in.AddToSP.simm = simm;
1456 vassert(-4096 < simm && simm < 4096);
1457 vassert(0 == (simm & 0xF));
1458 return i;
1459}
1460extern ARM64Instr* ARM64Instr_FromSP ( HReg dst ) {
1461 ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
1462 i->tag = ARM64in_FromSP;
1463 i->ARM64in.FromSP.dst = dst;
1464 return i;
1465}
1466ARM64Instr* ARM64Instr_Mul ( HReg dst, HReg argL, HReg argR,
1467 ARM64MulOp op ) {
1468 ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
1469 i->tag = ARM64in_Mul;
1470 i->ARM64in.Mul.dst = dst;
1471 i->ARM64in.Mul.argL = argL;
1472 i->ARM64in.Mul.argR = argR;
1473 i->ARM64in.Mul.op = op;
1474 return i;
1475}
sewardj7d009132014-02-20 17:43:38 +00001476ARM64Instr* ARM64Instr_LdrEX ( Int szB ) {
1477 ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
1478 i->tag = ARM64in_LdrEX;
1479 i->ARM64in.LdrEX.szB = szB;
1480 vassert(szB == 8 || szB == 4 || szB == 2 || szB == 1);
1481 return i;
1482}
1483ARM64Instr* ARM64Instr_StrEX ( Int szB ) {
1484 ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
1485 i->tag = ARM64in_StrEX;
1486 i->ARM64in.StrEX.szB = szB;
1487 vassert(szB == 8 || szB == 4 || szB == 2 || szB == 1);
1488 return i;
1489}
1490ARM64Instr* ARM64Instr_MFence ( void ) {
1491 ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
1492 i->tag = ARM64in_MFence;
1493 return i;
1494}
1495//ZZ ARM64Instr* ARM64Instr_CLREX( void ) {
1496//ZZ ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
1497//ZZ i->tag = ARM64in_CLREX;
sewardjbbcf1882014-01-12 12:49:10 +00001498//ZZ return i;
1499//ZZ }
1500ARM64Instr* ARM64Instr_VLdStS ( Bool isLoad, HReg sD, HReg rN, UInt uimm12 ) {
1501 ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
1502 i->tag = ARM64in_VLdStS;
1503 i->ARM64in.VLdStS.isLoad = isLoad;
1504 i->ARM64in.VLdStS.sD = sD;
1505 i->ARM64in.VLdStS.rN = rN;
1506 i->ARM64in.VLdStS.uimm12 = uimm12;
1507 vassert(uimm12 < 16384 && 0 == (uimm12 & 3));
1508 return i;
1509}
1510ARM64Instr* ARM64Instr_VLdStD ( Bool isLoad, HReg dD, HReg rN, UInt uimm12 ) {
1511 ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
1512 i->tag = ARM64in_VLdStD;
1513 i->ARM64in.VLdStD.isLoad = isLoad;
1514 i->ARM64in.VLdStD.dD = dD;
1515 i->ARM64in.VLdStD.rN = rN;
1516 i->ARM64in.VLdStD.uimm12 = uimm12;
1517 vassert(uimm12 < 32768 && 0 == (uimm12 & 7));
1518 return i;
1519}
1520ARM64Instr* ARM64Instr_VLdStQ ( Bool isLoad, HReg rQ, HReg rN ) {
1521 ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
1522 i->tag = ARM64in_VLdStQ;
1523 i->ARM64in.VLdStQ.isLoad = isLoad;
1524 i->ARM64in.VLdStQ.rQ = rQ;
1525 i->ARM64in.VLdStQ.rN = rN;
1526 return i;
1527}
1528ARM64Instr* ARM64Instr_VCvtI2F ( ARM64CvtOp how, HReg rD, HReg rS ) {
1529 ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
1530 i->tag = ARM64in_VCvtI2F;
1531 i->ARM64in.VCvtI2F.how = how;
1532 i->ARM64in.VCvtI2F.rD = rD;
1533 i->ARM64in.VCvtI2F.rS = rS;
1534 return i;
1535}
1536ARM64Instr* ARM64Instr_VCvtF2I ( ARM64CvtOp how, HReg rD, HReg rS,
1537 UChar armRM ) {
1538 ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
1539 i->tag = ARM64in_VCvtF2I;
1540 i->ARM64in.VCvtF2I.how = how;
1541 i->ARM64in.VCvtF2I.rD = rD;
1542 i->ARM64in.VCvtF2I.rS = rS;
1543 i->ARM64in.VCvtF2I.armRM = armRM;
1544 vassert(armRM <= 3);
1545 return i;
1546}
1547ARM64Instr* ARM64Instr_VCvtSD ( Bool sToD, HReg dst, HReg src ) {
1548 ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
1549 i->tag = ARM64in_VCvtSD;
1550 i->ARM64in.VCvtSD.sToD = sToD;
1551 i->ARM64in.VCvtSD.dst = dst;
1552 i->ARM64in.VCvtSD.src = src;
1553 return i;
1554}
1555ARM64Instr* ARM64Instr_VUnaryD ( ARM64FpUnaryOp op, HReg dst, HReg src ) {
1556 ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
1557 i->tag = ARM64in_VUnaryD;
1558 i->ARM64in.VUnaryD.op = op;
1559 i->ARM64in.VUnaryD.dst = dst;
1560 i->ARM64in.VUnaryD.src = src;
1561 return i;
1562}
1563ARM64Instr* ARM64Instr_VUnaryS ( ARM64FpUnaryOp op, HReg dst, HReg src ) {
1564 ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
1565 i->tag = ARM64in_VUnaryS;
1566 i->ARM64in.VUnaryS.op = op;
1567 i->ARM64in.VUnaryS.dst = dst;
1568 i->ARM64in.VUnaryS.src = src;
1569 return i;
1570}
1571ARM64Instr* ARM64Instr_VBinD ( ARM64FpBinOp op,
1572 HReg dst, HReg argL, HReg argR ) {
1573 ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
1574 i->tag = ARM64in_VBinD;
1575 i->ARM64in.VBinD.op = op;
1576 i->ARM64in.VBinD.dst = dst;
1577 i->ARM64in.VBinD.argL = argL;
1578 i->ARM64in.VBinD.argR = argR;
1579 return i;
1580}
1581ARM64Instr* ARM64Instr_VBinS ( ARM64FpBinOp op,
1582 HReg dst, HReg argL, HReg argR ) {
1583 ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
1584 i->tag = ARM64in_VBinS;
1585 i->ARM64in.VBinS.op = op;
1586 i->ARM64in.VBinS.dst = dst;
1587 i->ARM64in.VBinS.argL = argL;
1588 i->ARM64in.VBinS.argR = argR;
1589 return i;
1590}
1591ARM64Instr* ARM64Instr_VCmpD ( HReg argL, HReg argR ) {
1592 ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
1593 i->tag = ARM64in_VCmpD;
1594 i->ARM64in.VCmpD.argL = argL;
1595 i->ARM64in.VCmpD.argR = argR;
1596 return i;
1597}
1598ARM64Instr* ARM64Instr_VCmpS ( HReg argL, HReg argR ) {
1599 ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
1600 i->tag = ARM64in_VCmpS;
1601 i->ARM64in.VCmpS.argL = argL;
1602 i->ARM64in.VCmpS.argR = argR;
1603 return i;
1604}
1605ARM64Instr* ARM64Instr_FPCR ( Bool toFPCR, HReg iReg ) {
1606 ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
1607 i->tag = ARM64in_FPCR;
1608 i->ARM64in.FPCR.toFPCR = toFPCR;
1609 i->ARM64in.FPCR.iReg = iReg;
1610 return i;
1611}
sewardj606c4ba2014-01-26 19:11:14 +00001612ARM64Instr* ARM64Instr_VBinV ( ARM64VecBinOp op,
1613 HReg dst, HReg argL, HReg argR ) {
1614 ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
1615 i->tag = ARM64in_VBinV;
1616 i->ARM64in.VBinV.op = op;
1617 i->ARM64in.VBinV.dst = dst;
1618 i->ARM64in.VBinV.argL = argL;
1619 i->ARM64in.VBinV.argR = argR;
1620 return i;
1621}
sewardjfab09142014-02-10 10:28:13 +00001622ARM64Instr* ARM64Instr_VUnaryV ( ARM64VecUnaryOp op, HReg dst, HReg arg ) {
1623 ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
1624 i->tag = ARM64in_VUnaryV;
1625 i->ARM64in.VUnaryV.op = op;
1626 i->ARM64in.VUnaryV.dst = dst;
1627 i->ARM64in.VUnaryV.arg = arg;
1628 return i;
1629}
sewardj606c4ba2014-01-26 19:11:14 +00001630ARM64Instr* ARM64Instr_VNarrowV ( UInt dszBlg2, HReg dst, HReg src ) {
1631 ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
1632 i->tag = ARM64in_VNarrowV;
1633 i->ARM64in.VNarrowV.dszBlg2 = dszBlg2;
1634 i->ARM64in.VNarrowV.dst = dst;
1635 i->ARM64in.VNarrowV.src = src;
1636 vassert(dszBlg2 == 0 || dszBlg2 == 1 || dszBlg2 == 2);
1637 return i;
1638}
sewardje520bb32014-02-17 11:00:53 +00001639ARM64Instr* ARM64Instr_VShiftImmV ( ARM64VecShiftOp op,
1640 HReg dst, HReg src, UInt amt ) {
1641 ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
1642 i->tag = ARM64in_VShiftImmV;
1643 i->ARM64in.VShiftImmV.op = op;
1644 i->ARM64in.VShiftImmV.dst = dst;
1645 i->ARM64in.VShiftImmV.src = src;
1646 i->ARM64in.VShiftImmV.amt = amt;
1647 UInt maxSh = 0;
1648 switch (op) {
1649 case ARM64vecsh_USHR64x2: case ARM64vecsh_SSHR64x2:
sewardj93013432014-04-27 12:02:12 +00001650 case ARM64vecsh_SHL64x2:
sewardje520bb32014-02-17 11:00:53 +00001651 maxSh = 63; break;
sewardj93013432014-04-27 12:02:12 +00001652 case ARM64vecsh_USHR32x4: case ARM64vecsh_SSHR32x4:
sewardj32d86752014-03-02 12:47:18 +00001653 case ARM64vecsh_SHL32x4:
1654 maxSh = 31; break;
sewardj93013432014-04-27 12:02:12 +00001655 case ARM64vecsh_USHR16x8: case ARM64vecsh_SSHR16x8:
1656 case ARM64vecsh_SHL16x8:
sewardj1eaaec22014-03-07 22:52:19 +00001657 maxSh = 15; break;
sewardj93013432014-04-27 12:02:12 +00001658 case ARM64vecsh_USHR8x16: case ARM64vecsh_SSHR8x16:
1659 case ARM64vecsh_SHL8x16:
1660 maxSh = 7; break;
sewardje520bb32014-02-17 11:00:53 +00001661 default:
1662 vassert(0);
1663 }
1664 vassert(maxSh > 0);
1665 vassert(amt > 0 && amt <= maxSh);
1666 return i;
1667}
sewardjbbcf1882014-01-12 12:49:10 +00001668//ZZ ARMInstr* ARMInstr_VAluS ( ARMVfpOp op, HReg dst, HReg argL, HReg argR ) {
1669//ZZ ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
1670//ZZ i->tag = ARMin_VAluS;
1671//ZZ i->ARMin.VAluS.op = op;
1672//ZZ i->ARMin.VAluS.dst = dst;
1673//ZZ i->ARMin.VAluS.argL = argL;
1674//ZZ i->ARMin.VAluS.argR = argR;
1675//ZZ return i;
1676//ZZ }
1677//ZZ ARMInstr* ARMInstr_VCMovD ( ARMCondCode cond, HReg dst, HReg src ) {
1678//ZZ ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
1679//ZZ i->tag = ARMin_VCMovD;
1680//ZZ i->ARMin.VCMovD.cond = cond;
1681//ZZ i->ARMin.VCMovD.dst = dst;
1682//ZZ i->ARMin.VCMovD.src = src;
1683//ZZ vassert(cond != ARMcc_AL);
1684//ZZ return i;
1685//ZZ }
1686//ZZ ARMInstr* ARMInstr_VCMovS ( ARMCondCode cond, HReg dst, HReg src ) {
1687//ZZ ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
1688//ZZ i->tag = ARMin_VCMovS;
1689//ZZ i->ARMin.VCMovS.cond = cond;
1690//ZZ i->ARMin.VCMovS.dst = dst;
1691//ZZ i->ARMin.VCMovS.src = src;
1692//ZZ vassert(cond != ARMcc_AL);
1693//ZZ return i;
1694//ZZ }
1695//ZZ ARMInstr* ARMInstr_VXferD ( Bool toD, HReg dD, HReg rHi, HReg rLo ) {
1696//ZZ ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
1697//ZZ i->tag = ARMin_VXferD;
1698//ZZ i->ARMin.VXferD.toD = toD;
1699//ZZ i->ARMin.VXferD.dD = dD;
1700//ZZ i->ARMin.VXferD.rHi = rHi;
1701//ZZ i->ARMin.VXferD.rLo = rLo;
1702//ZZ return i;
1703//ZZ }
1704//ZZ ARMInstr* ARMInstr_VXferS ( Bool toS, HReg fD, HReg rLo ) {
1705//ZZ ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
1706//ZZ i->tag = ARMin_VXferS;
1707//ZZ i->ARMin.VXferS.toS = toS;
1708//ZZ i->ARMin.VXferS.fD = fD;
1709//ZZ i->ARMin.VXferS.rLo = rLo;
1710//ZZ return i;
1711//ZZ }
1712//ZZ ARMInstr* ARMInstr_VCvtID ( Bool iToD, Bool syned,
1713//ZZ HReg dst, HReg src ) {
1714//ZZ ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
1715//ZZ i->tag = ARMin_VCvtID;
1716//ZZ i->ARMin.VCvtID.iToD = iToD;
1717//ZZ i->ARMin.VCvtID.syned = syned;
1718//ZZ i->ARMin.VCvtID.dst = dst;
1719//ZZ i->ARMin.VCvtID.src = src;
1720//ZZ return i;
1721//ZZ }
sewardjbbcf1882014-01-12 12:49:10 +00001722//ZZ ARMInstr* ARMInstr_NLdStD ( Bool isLoad, HReg dD, ARMAModeN *amode ) {
1723//ZZ ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
1724//ZZ i->tag = ARMin_NLdStD;
1725//ZZ i->ARMin.NLdStD.isLoad = isLoad;
1726//ZZ i->ARMin.NLdStD.dD = dD;
1727//ZZ i->ARMin.NLdStD.amode = amode;
1728//ZZ return i;
1729//ZZ }
1730//ZZ
1731//ZZ ARMInstr* ARMInstr_NUnary ( ARMNeonUnOp op, HReg dQ, HReg nQ,
1732//ZZ UInt size, Bool Q ) {
1733//ZZ ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
1734//ZZ i->tag = ARMin_NUnary;
1735//ZZ i->ARMin.NUnary.op = op;
1736//ZZ i->ARMin.NUnary.src = nQ;
1737//ZZ i->ARMin.NUnary.dst = dQ;
1738//ZZ i->ARMin.NUnary.size = size;
1739//ZZ i->ARMin.NUnary.Q = Q;
1740//ZZ return i;
1741//ZZ }
1742//ZZ
1743//ZZ ARMInstr* ARMInstr_NUnaryS ( ARMNeonUnOpS op, ARMNRS* dst, ARMNRS* src,
1744//ZZ UInt size, Bool Q ) {
1745//ZZ ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
1746//ZZ i->tag = ARMin_NUnaryS;
1747//ZZ i->ARMin.NUnaryS.op = op;
1748//ZZ i->ARMin.NUnaryS.src = src;
1749//ZZ i->ARMin.NUnaryS.dst = dst;
1750//ZZ i->ARMin.NUnaryS.size = size;
1751//ZZ i->ARMin.NUnaryS.Q = Q;
1752//ZZ return i;
1753//ZZ }
1754//ZZ
1755//ZZ ARMInstr* ARMInstr_NDual ( ARMNeonDualOp op, HReg nQ, HReg mQ,
1756//ZZ UInt size, Bool Q ) {
1757//ZZ ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
1758//ZZ i->tag = ARMin_NDual;
1759//ZZ i->ARMin.NDual.op = op;
1760//ZZ i->ARMin.NDual.arg1 = nQ;
1761//ZZ i->ARMin.NDual.arg2 = mQ;
1762//ZZ i->ARMin.NDual.size = size;
1763//ZZ i->ARMin.NDual.Q = Q;
1764//ZZ return i;
1765//ZZ }
1766//ZZ
1767//ZZ ARMInstr* ARMInstr_NBinary ( ARMNeonBinOp op,
1768//ZZ HReg dst, HReg argL, HReg argR,
1769//ZZ UInt size, Bool Q ) {
1770//ZZ ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
1771//ZZ i->tag = ARMin_NBinary;
1772//ZZ i->ARMin.NBinary.op = op;
1773//ZZ i->ARMin.NBinary.argL = argL;
1774//ZZ i->ARMin.NBinary.argR = argR;
1775//ZZ i->ARMin.NBinary.dst = dst;
1776//ZZ i->ARMin.NBinary.size = size;
1777//ZZ i->ARMin.NBinary.Q = Q;
1778//ZZ return i;
1779//ZZ }
1780
1781ARM64Instr* ARM64Instr_VImmQ (HReg rQ, UShort imm) {
1782 ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
1783 i->tag = ARM64in_VImmQ;
1784 i->ARM64in.VImmQ.rQ = rQ;
1785 i->ARM64in.VImmQ.imm = imm;
1786 return i;
1787}
1788ARM64Instr* ARM64Instr_VDfromX ( HReg rD, HReg rX ) {
1789 ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
1790 i->tag = ARM64in_VDfromX;
1791 i->ARM64in.VDfromX.rD = rD;
1792 i->ARM64in.VDfromX.rX = rX;
1793 return i;
1794}
1795ARM64Instr* ARM64Instr_VQfromXX ( HReg rQ, HReg rXhi, HReg rXlo ) {
1796 ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
1797 i->tag = ARM64in_VQfromXX;
1798 i->ARM64in.VQfromXX.rQ = rQ;
1799 i->ARM64in.VQfromXX.rXhi = rXhi;
1800 i->ARM64in.VQfromXX.rXlo = rXlo;
1801 return i;
1802}
1803ARM64Instr* ARM64Instr_VXfromQ ( HReg rX, HReg rQ, UInt laneNo ) {
1804 ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
1805 i->tag = ARM64in_VXfromQ;
1806 i->ARM64in.VXfromQ.rX = rX;
1807 i->ARM64in.VXfromQ.rQ = rQ;
1808 i->ARM64in.VXfromQ.laneNo = laneNo;
1809 vassert(laneNo <= 1);
1810 return i;
1811}
1812ARM64Instr* ARM64Instr_VMov ( UInt szB, HReg dst, HReg src ) {
1813 ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
1814 i->tag = ARM64in_VMov;
1815 i->ARM64in.VMov.szB = szB;
1816 i->ARM64in.VMov.dst = dst;
1817 i->ARM64in.VMov.src = src;
1818 switch (szB) {
1819 case 16:
1820 vassert(hregClass(src) == HRcVec128);
1821 vassert(hregClass(dst) == HRcVec128);
1822 break;
1823 case 8:
1824 vassert(hregClass(src) == HRcFlt64);
1825 vassert(hregClass(dst) == HRcFlt64);
1826 break;
1827 default:
1828 vpanic("ARM64Instr_VMov");
1829 }
1830 return i;
1831}
1832
1833//ZZ ARMInstr* ARMInstr_NCMovQ ( ARMCondCode cond, HReg dst, HReg src ) {
1834//ZZ ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
1835//ZZ i->tag = ARMin_NCMovQ;
1836//ZZ i->ARMin.NCMovQ.cond = cond;
1837//ZZ i->ARMin.NCMovQ.dst = dst;
1838//ZZ i->ARMin.NCMovQ.src = src;
1839//ZZ vassert(cond != ARMcc_AL);
1840//ZZ return i;
1841//ZZ }
1842//ZZ
1843//ZZ ARMInstr* ARMInstr_NShift ( ARMNeonShiftOp op,
1844//ZZ HReg dst, HReg argL, HReg argR,
1845//ZZ UInt size, Bool Q ) {
1846//ZZ ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
1847//ZZ i->tag = ARMin_NShift;
1848//ZZ i->ARMin.NShift.op = op;
1849//ZZ i->ARMin.NShift.argL = argL;
1850//ZZ i->ARMin.NShift.argR = argR;
1851//ZZ i->ARMin.NShift.dst = dst;
1852//ZZ i->ARMin.NShift.size = size;
1853//ZZ i->ARMin.NShift.Q = Q;
1854//ZZ return i;
1855//ZZ }
1856//ZZ
1857//ZZ ARMInstr* ARMInstr_NShl64 ( HReg dst, HReg src, UInt amt )
1858//ZZ {
1859//ZZ ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
1860//ZZ i->tag = ARMin_NShl64;
1861//ZZ i->ARMin.NShl64.dst = dst;
1862//ZZ i->ARMin.NShl64.src = src;
1863//ZZ i->ARMin.NShl64.amt = amt;
1864//ZZ vassert(amt >= 1 && amt <= 63);
1865//ZZ return i;
1866//ZZ }
1867//ZZ
1868//ZZ /* Helper copy-pasted from isel.c */
1869//ZZ static Bool fitsIn8x4 ( UInt* u8, UInt* u4, UInt u )
1870//ZZ {
1871//ZZ UInt i;
1872//ZZ for (i = 0; i < 16; i++) {
1873//ZZ if (0 == (u & 0xFFFFFF00)) {
1874//ZZ *u8 = u;
1875//ZZ *u4 = i;
1876//ZZ return True;
1877//ZZ }
1878//ZZ u = ROR32(u, 30);
1879//ZZ }
1880//ZZ vassert(i == 16);
1881//ZZ return False;
1882//ZZ }
1883//ZZ
1884//ZZ ARMInstr* ARMInstr_Add32 ( HReg rD, HReg rN, UInt imm32 ) {
1885//ZZ UInt u8, u4;
1886//ZZ ARMInstr *i = LibVEX_Alloc(sizeof(ARMInstr));
1887//ZZ /* Try to generate single ADD if possible */
1888//ZZ if (fitsIn8x4(&u8, &u4, imm32)) {
1889//ZZ i->tag = ARMin_Alu;
1890//ZZ i->ARMin.Alu.op = ARMalu_ADD;
1891//ZZ i->ARMin.Alu.dst = rD;
1892//ZZ i->ARMin.Alu.argL = rN;
1893//ZZ i->ARMin.Alu.argR = ARMRI84_I84(u8, u4);
1894//ZZ } else {
1895//ZZ i->tag = ARMin_Add32;
1896//ZZ i->ARMin.Add32.rD = rD;
1897//ZZ i->ARMin.Add32.rN = rN;
1898//ZZ i->ARMin.Add32.imm32 = imm32;
1899//ZZ }
1900//ZZ return i;
1901//ZZ }
1902
1903ARM64Instr* ARM64Instr_EvCheck ( ARM64AMode* amCounter,
1904 ARM64AMode* amFailAddr ) {
1905 ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
1906 i->tag = ARM64in_EvCheck;
1907 i->ARM64in.EvCheck.amCounter = amCounter;
1908 i->ARM64in.EvCheck.amFailAddr = amFailAddr;
1909 return i;
1910}
1911
1912//ZZ ARMInstr* ARMInstr_ProfInc ( void ) {
1913//ZZ ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
1914//ZZ i->tag = ARMin_ProfInc;
1915//ZZ return i;
1916//ZZ }
1917
1918/* ... */
1919
1920void ppARM64Instr ( ARM64Instr* i ) {
1921 switch (i->tag) {
1922 case ARM64in_Arith:
1923 vex_printf("%s ", i->ARM64in.Arith.isAdd ? "add" : "sub");
1924 ppHRegARM64(i->ARM64in.Arith.dst);
1925 vex_printf(", ");
1926 ppHRegARM64(i->ARM64in.Arith.argL);
1927 vex_printf(", ");
1928 ppARM64RIA(i->ARM64in.Arith.argR);
1929 return;
1930 case ARM64in_Cmp:
1931 vex_printf("cmp%s ", i->ARM64in.Cmp.is64 ? " " : "(w)" );
1932 ppHRegARM64(i->ARM64in.Cmp.argL);
1933 vex_printf(", ");
1934 ppARM64RIA(i->ARM64in.Cmp.argR);
1935 return;
1936 case ARM64in_Logic:
1937 vex_printf("%s ", showARM64LogicOp(i->ARM64in.Logic.op));
1938 ppHRegARM64(i->ARM64in.Logic.dst);
1939 vex_printf(", ");
1940 ppHRegARM64(i->ARM64in.Logic.argL);
1941 vex_printf(", ");
1942 ppARM64RIL(i->ARM64in.Logic.argR);
1943 return;
1944 case ARM64in_Test:
1945 vex_printf("tst ");
1946 ppHRegARM64(i->ARM64in.Test.argL);
1947 vex_printf(", ");
1948 ppARM64RIL(i->ARM64in.Test.argR);
1949 return;
1950 case ARM64in_Shift:
1951 vex_printf("%s ", showARM64ShiftOp(i->ARM64in.Shift.op));
1952 ppHRegARM64(i->ARM64in.Shift.dst);
1953 vex_printf(", ");
1954 ppHRegARM64(i->ARM64in.Shift.argL);
1955 vex_printf(", ");
1956 ppARM64RI6(i->ARM64in.Shift.argR);
1957 return;
1958 case ARM64in_Unary:
1959 vex_printf("%s ", showARM64UnaryOp(i->ARM64in.Unary.op));
1960 ppHRegARM64(i->ARM64in.Unary.dst);
1961 vex_printf(", ");
1962 ppHRegARM64(i->ARM64in.Unary.src);
1963 return;
1964 case ARM64in_MovI:
1965 vex_printf("mov ");
1966 ppHRegARM64(i->ARM64in.MovI.dst);
1967 vex_printf(", ");
1968 ppHRegARM64(i->ARM64in.MovI.src);
1969 return;
1970 case ARM64in_Imm64:
1971 vex_printf("imm64 ");
1972 ppHRegARM64(i->ARM64in.Imm64.dst);
1973 vex_printf(", 0x%llx", i->ARM64in.Imm64.imm64);
1974 return;
1975 case ARM64in_LdSt64:
1976 if (i->ARM64in.LdSt64.isLoad) {
1977 vex_printf("ldr ");
1978 ppHRegARM64(i->ARM64in.LdSt64.rD);
1979 vex_printf(", ");
1980 ppARM64AMode(i->ARM64in.LdSt64.amode);
1981 } else {
1982 vex_printf("str ");
1983 ppARM64AMode(i->ARM64in.LdSt64.amode);
1984 vex_printf(", ");
1985 ppHRegARM64(i->ARM64in.LdSt64.rD);
1986 }
1987 return;
1988 case ARM64in_LdSt32:
1989 if (i->ARM64in.LdSt32.isLoad) {
1990 vex_printf("ldruw ");
1991 ppHRegARM64(i->ARM64in.LdSt32.rD);
1992 vex_printf(", ");
1993 ppARM64AMode(i->ARM64in.LdSt32.amode);
1994 } else {
1995 vex_printf("strw ");
1996 ppARM64AMode(i->ARM64in.LdSt32.amode);
1997 vex_printf(", ");
1998 ppHRegARM64(i->ARM64in.LdSt32.rD);
1999 }
2000 return;
2001 case ARM64in_LdSt16:
2002 if (i->ARM64in.LdSt16.isLoad) {
2003 vex_printf("ldruh ");
2004 ppHRegARM64(i->ARM64in.LdSt16.rD);
2005 vex_printf(", ");
2006 ppARM64AMode(i->ARM64in.LdSt16.amode);
2007 } else {
2008 vex_printf("strh ");
2009 ppARM64AMode(i->ARM64in.LdSt16.amode);
2010 vex_printf(", ");
2011 ppHRegARM64(i->ARM64in.LdSt16.rD);
2012 }
2013 return;
2014 case ARM64in_LdSt8:
2015 if (i->ARM64in.LdSt8.isLoad) {
2016 vex_printf("ldrub ");
2017 ppHRegARM64(i->ARM64in.LdSt8.rD);
2018 vex_printf(", ");
2019 ppARM64AMode(i->ARM64in.LdSt8.amode);
2020 } else {
2021 vex_printf("strb ");
2022 ppARM64AMode(i->ARM64in.LdSt8.amode);
2023 vex_printf(", ");
2024 ppHRegARM64(i->ARM64in.LdSt8.rD);
2025 }
2026 return;
2027 case ARM64in_XDirect:
2028 vex_printf("(xDirect) ");
2029 vex_printf("if (%%pstate.%s) { ",
2030 showARM64CondCode(i->ARM64in.XDirect.cond));
2031 vex_printf("imm64 x9,0x%llx; ", i->ARM64in.XDirect.dstGA);
2032 vex_printf("str x9,");
2033 ppARM64AMode(i->ARM64in.XDirect.amPC);
2034 vex_printf("; imm64-exactly4 x9,$disp_cp_chain_me_to_%sEP; ",
2035 i->ARM64in.XDirect.toFastEP ? "fast" : "slow");
2036 vex_printf("blr x9 }");
2037 return;
2038 case ARM64in_XIndir:
2039 vex_printf("(xIndir) ");
2040 vex_printf("if (%%pstate.%s) { ",
2041 showARM64CondCode(i->ARM64in.XIndir.cond));
2042 vex_printf("str ");
2043 ppHRegARM64(i->ARM64in.XIndir.dstGA);
2044 vex_printf(",");
2045 ppARM64AMode(i->ARM64in.XIndir.amPC);
2046 vex_printf("; imm64 x9,$disp_cp_xindir; ");
2047 vex_printf("br x9 }");
2048 return;
2049 case ARM64in_XAssisted:
2050 vex_printf("(xAssisted) ");
2051 vex_printf("if (%%pstate.%s) { ",
2052 showARM64CondCode(i->ARM64in.XAssisted.cond));
2053 vex_printf("str ");
2054 ppHRegARM64(i->ARM64in.XAssisted.dstGA);
2055 vex_printf(",");
2056 ppARM64AMode(i->ARM64in.XAssisted.amPC);
2057 vex_printf("; movw x21,$IRJumpKind_to_TRCVAL(%d); ",
2058 (Int)i->ARM64in.XAssisted.jk);
2059 vex_printf("imm64 x9,$disp_cp_xassisted; ");
2060 vex_printf("br x9 }");
2061 return;
2062 case ARM64in_CSel:
2063 vex_printf("csel ");
2064 ppHRegARM64(i->ARM64in.CSel.dst);
2065 vex_printf(", ");
2066 ppHRegARM64(i->ARM64in.CSel.argL);
2067 vex_printf(", ");
2068 ppHRegARM64(i->ARM64in.CSel.argR);
2069 vex_printf(", %s", showARM64CondCode(i->ARM64in.CSel.cond));
2070 return;
2071 case ARM64in_Call:
2072 vex_printf("call%s ",
2073 i->ARM64in.Call.cond==ARM64cc_AL
2074 ? " " : showARM64CondCode(i->ARM64in.Call.cond));
2075 vex_printf("0x%lx [nArgRegs=%d, ",
2076 i->ARM64in.Call.target, i->ARM64in.Call.nArgRegs);
2077 ppRetLoc(i->ARM64in.Call.rloc);
2078 vex_printf("]");
2079 return;
2080 case ARM64in_AddToSP: {
2081 Int simm = i->ARM64in.AddToSP.simm;
2082 vex_printf("%s xsp, xsp, #%d", simm < 0 ? "sub" : "add",
2083 simm < 0 ? -simm : simm);
2084 return;
2085 }
2086 case ARM64in_FromSP:
2087 vex_printf("mov ");
2088 ppHRegARM64(i->ARM64in.FromSP.dst);
2089 vex_printf(", xsp");
2090 return;
2091 case ARM64in_Mul:
2092 vex_printf("%s ", showARM64MulOp(i->ARM64in.Mul.op));
2093 ppHRegARM64(i->ARM64in.Mul.dst);
2094 vex_printf(", ");
2095 ppHRegARM64(i->ARM64in.Mul.argL);
2096 vex_printf(", ");
2097 ppHRegARM64(i->ARM64in.Mul.argR);
2098 return;
sewardj7d009132014-02-20 17:43:38 +00002099
2100 case ARM64in_LdrEX: {
2101 const HChar* sz = " ";
2102 switch (i->ARM64in.LdrEX.szB) {
2103 case 1: sz = "b"; break;
2104 case 2: sz = "h"; break;
2105 case 4: case 8: break;
2106 default: vassert(0);
2107 }
2108 vex_printf("ldxr%s %c2, [x4]",
2109 sz, i->ARM64in.LdrEX.szB == 8 ? 'x' : 'w');
2110 return;
2111 }
2112 case ARM64in_StrEX: {
2113 const HChar* sz = " ";
2114 switch (i->ARM64in.StrEX.szB) {
2115 case 1: sz = "b"; break;
2116 case 2: sz = "h"; break;
2117 case 4: case 8: break;
2118 default: vassert(0);
2119 }
2120 vex_printf("stxr%s w0, %c2, [x4]",
2121 sz, i->ARM64in.StrEX.szB == 8 ? 'x' : 'w');
2122 return;
2123 }
2124 case ARM64in_MFence:
2125 vex_printf("(mfence) dsb sy; dmb sy; isb");
2126 return;
2127//ZZ case ARM64in_CLREX:
2128//ZZ vex_printf("clrex");
sewardjbbcf1882014-01-12 12:49:10 +00002129//ZZ return;
sewardjbbcf1882014-01-12 12:49:10 +00002130 case ARM64in_VLdStS:
2131 if (i->ARM64in.VLdStS.isLoad) {
2132 vex_printf("ldr ");
2133 ppHRegARM64asSreg(i->ARM64in.VLdStS.sD);
2134 vex_printf(", %u(", i->ARM64in.VLdStS.uimm12);
2135 ppHRegARM64(i->ARM64in.VLdStS.rN);
2136 vex_printf(")");
2137 } else {
2138 vex_printf("str ");
2139 vex_printf("%u(", i->ARM64in.VLdStS.uimm12);
2140 ppHRegARM64(i->ARM64in.VLdStS.rN);
2141 vex_printf("), ");
2142 ppHRegARM64asSreg(i->ARM64in.VLdStS.sD);
2143 }
2144 return;
2145 case ARM64in_VLdStD:
2146 if (i->ARM64in.VLdStD.isLoad) {
2147 vex_printf("ldr ");
2148 ppHRegARM64(i->ARM64in.VLdStD.dD);
2149 vex_printf(", %u(", i->ARM64in.VLdStD.uimm12);
2150 ppHRegARM64(i->ARM64in.VLdStD.rN);
2151 vex_printf(")");
2152 } else {
2153 vex_printf("str ");
2154 vex_printf("%u(", i->ARM64in.VLdStD.uimm12);
2155 ppHRegARM64(i->ARM64in.VLdStD.rN);
2156 vex_printf("), ");
2157 ppHRegARM64(i->ARM64in.VLdStD.dD);
2158 }
2159 return;
2160 case ARM64in_VLdStQ:
2161 if (i->ARM64in.VLdStQ.isLoad)
2162 vex_printf("ld1.2d {");
2163 else
2164 vex_printf("st1.2d {");
2165 ppHRegARM64(i->ARM64in.VLdStQ.rQ);
2166 vex_printf("}, [");
2167 ppHRegARM64(i->ARM64in.VLdStQ.rN);
2168 vex_printf("]");
2169 return;
2170 case ARM64in_VCvtI2F: {
2171 HChar syn = '?';
2172 UInt fszB = 0;
2173 UInt iszB = 0;
2174 characteriseARM64CvtOp(&syn, &fszB, &iszB, i->ARM64in.VCvtI2F.how);
2175 vex_printf("%ccvtf ", syn);
2176 ppHRegARM64(i->ARM64in.VCvtI2F.rD);
2177 vex_printf("(%c-reg), ", fszB == 4 ? 'S' : 'D');
2178 ppHRegARM64(i->ARM64in.VCvtI2F.rS);
2179 vex_printf("(%c-reg)", iszB == 4 ? 'W' : 'X');
2180 return;
2181 }
2182 case ARM64in_VCvtF2I: {
2183 HChar syn = '?';
2184 UInt fszB = 0;
2185 UInt iszB = 0;
2186 HChar rmo = '?';
2187 characteriseARM64CvtOp(&syn, &fszB, &iszB, i->ARM64in.VCvtF2I.how);
2188 UChar armRM = i->ARM64in.VCvtF2I.armRM;
2189 if (armRM < 4) rmo = "npmz"[armRM];
2190 vex_printf("fcvt%c%c ", rmo, syn);
2191 ppHRegARM64(i->ARM64in.VCvtF2I.rD);
2192 vex_printf("(%c-reg), ", iszB == 4 ? 'W' : 'X');
2193 ppHRegARM64(i->ARM64in.VCvtF2I.rS);
2194 vex_printf("(%c-reg)", fszB == 4 ? 'S' : 'D');
2195 return;
2196 }
2197 case ARM64in_VCvtSD:
2198 vex_printf("fcvt%s ", i->ARM64in.VCvtSD.sToD ? "s2d" : "d2s");
2199 if (i->ARM64in.VCvtSD.sToD) {
2200 ppHRegARM64(i->ARM64in.VCvtSD.dst);
2201 vex_printf(", ");
2202 ppHRegARM64asSreg(i->ARM64in.VCvtSD.src);
2203 } else {
2204 ppHRegARM64asSreg(i->ARM64in.VCvtSD.dst);
2205 vex_printf(", ");
2206 ppHRegARM64(i->ARM64in.VCvtSD.src);
2207 }
2208 return;
2209 case ARM64in_VUnaryD:
2210 vex_printf("f%s ", showARM64FpUnaryOp(i->ARM64in.VUnaryD.op));
2211 ppHRegARM64(i->ARM64in.VUnaryD.dst);
2212 vex_printf(", ");
2213 ppHRegARM64(i->ARM64in.VUnaryD.src);
2214 return;
2215 case ARM64in_VUnaryS:
2216 vex_printf("f%s ", showARM64FpUnaryOp(i->ARM64in.VUnaryS.op));
2217 ppHRegARM64asSreg(i->ARM64in.VUnaryS.dst);
2218 vex_printf(", ");
2219 ppHRegARM64asSreg(i->ARM64in.VUnaryS.src);
2220 return;
2221 case ARM64in_VBinD:
2222 vex_printf("f%s ", showARM64FpBinOp(i->ARM64in.VBinD.op));
2223 ppHRegARM64(i->ARM64in.VBinD.dst);
2224 vex_printf(", ");
2225 ppHRegARM64(i->ARM64in.VBinD.argL);
2226 vex_printf(", ");
2227 ppHRegARM64(i->ARM64in.VBinD.argR);
2228 return;
2229 case ARM64in_VBinS:
2230 vex_printf("f%s ", showARM64FpBinOp(i->ARM64in.VBinS.op));
2231 ppHRegARM64asSreg(i->ARM64in.VBinS.dst);
2232 vex_printf(", ");
2233 ppHRegARM64asSreg(i->ARM64in.VBinS.argL);
2234 vex_printf(", ");
2235 ppHRegARM64asSreg(i->ARM64in.VBinS.argR);
2236 return;
2237 case ARM64in_VCmpD:
2238 vex_printf("fcmp ");
2239 ppHRegARM64(i->ARM64in.VCmpD.argL);
2240 vex_printf(", ");
2241 ppHRegARM64(i->ARM64in.VCmpD.argR);
2242 return;
2243 case ARM64in_VCmpS:
2244 vex_printf("fcmp ");
2245 ppHRegARM64asSreg(i->ARM64in.VCmpS.argL);
2246 vex_printf(", ");
2247 ppHRegARM64asSreg(i->ARM64in.VCmpS.argR);
2248 return;
2249 case ARM64in_FPCR:
2250 if (i->ARM64in.FPCR.toFPCR) {
2251 vex_printf("msr fpcr, ");
2252 ppHRegARM64(i->ARM64in.FPCR.iReg);
2253 } else {
2254 vex_printf("mrs ");
2255 ppHRegARM64(i->ARM64in.FPCR.iReg);
2256 vex_printf(", fpcr");
2257 }
2258 return;
sewardj606c4ba2014-01-26 19:11:14 +00002259 case ARM64in_VBinV: {
2260 const HChar* nm = "??";
2261 const HChar* ar = "??";
2262 showARM64VecBinOp(&nm, &ar, i->ARM64in.VBinV.op);
2263 vex_printf("%s ", nm);
2264 ppHRegARM64(i->ARM64in.VBinV.dst);
2265 vex_printf(".%s, ", ar);
2266 ppHRegARM64(i->ARM64in.VBinV.argL);
2267 vex_printf(".%s, ", ar);
2268 ppHRegARM64(i->ARM64in.VBinV.argR);
2269 vex_printf(".%s", ar);
2270 return;
2271 }
sewardjfab09142014-02-10 10:28:13 +00002272 case ARM64in_VUnaryV: {
2273 const HChar* nm = "??";
2274 const HChar* ar = "??";
2275 showARM64VecUnaryOp(&nm, &ar, i->ARM64in.VUnaryV.op);
2276 vex_printf("%s ", nm);
2277 ppHRegARM64(i->ARM64in.VUnaryV.dst);
2278 vex_printf(".%s, ", ar);
2279 ppHRegARM64(i->ARM64in.VUnaryV.arg);
2280 vex_printf(".%s", ar);
2281 return;
2282 }
sewardj606c4ba2014-01-26 19:11:14 +00002283 case ARM64in_VNarrowV: {
2284 UInt dszBlg2 = i->ARM64in.VNarrowV.dszBlg2;
2285 const HChar* darr[3] = { "8b", "4h", "2s" };
2286 const HChar* sarr[3] = { "8h", "4s", "2d" };
2287 vex_printf("xtn ");
2288 ppHRegARM64(i->ARM64in.VNarrowV.dst);
2289 vex_printf(".%s, ", dszBlg2 < 3 ? darr[dszBlg2] : "??");
2290 ppHRegARM64(i->ARM64in.VNarrowV.src);
2291 vex_printf(".%s", dszBlg2 < 3 ? sarr[dszBlg2] : "??");
2292 return;
2293 }
sewardje520bb32014-02-17 11:00:53 +00002294 case ARM64in_VShiftImmV: {
2295 const HChar* nm = "??";
2296 const HChar* ar = "??";
2297 showARM64VecShiftOp(&nm, &ar, i->ARM64in.VShiftImmV.op);
2298 vex_printf("%s ", nm);
2299 ppHRegARM64(i->ARM64in.VShiftImmV.dst);
2300 vex_printf(".%s, ", ar);
2301 ppHRegARM64(i->ARM64in.VShiftImmV.src);
2302 vex_printf(".%s, #%u", ar, i->ARM64in.VShiftImmV.amt);
2303 return;
2304 }
sewardjbbcf1882014-01-12 12:49:10 +00002305//ZZ case ARMin_VAluS:
2306//ZZ vex_printf("f%-3ss ", showARMVfpOp(i->ARMin.VAluS.op));
2307//ZZ ppHRegARM(i->ARMin.VAluS.dst);
2308//ZZ vex_printf(", ");
2309//ZZ ppHRegARM(i->ARMin.VAluS.argL);
2310//ZZ vex_printf(", ");
2311//ZZ ppHRegARM(i->ARMin.VAluS.argR);
2312//ZZ return;
2313//ZZ case ARMin_VCMovD:
2314//ZZ vex_printf("fcpyd%s ", showARMCondCode(i->ARMin.VCMovD.cond));
2315//ZZ ppHRegARM(i->ARMin.VCMovD.dst);
2316//ZZ vex_printf(", ");
2317//ZZ ppHRegARM(i->ARMin.VCMovD.src);
2318//ZZ return;
2319//ZZ case ARMin_VCMovS:
2320//ZZ vex_printf("fcpys%s ", showARMCondCode(i->ARMin.VCMovS.cond));
2321//ZZ ppHRegARM(i->ARMin.VCMovS.dst);
2322//ZZ vex_printf(", ");
2323//ZZ ppHRegARM(i->ARMin.VCMovS.src);
2324//ZZ return;
2325//ZZ case ARMin_VXferD:
2326//ZZ vex_printf("vmov ");
2327//ZZ if (i->ARMin.VXferD.toD) {
2328//ZZ ppHRegARM(i->ARMin.VXferD.dD);
2329//ZZ vex_printf(", ");
2330//ZZ ppHRegARM(i->ARMin.VXferD.rLo);
2331//ZZ vex_printf(", ");
2332//ZZ ppHRegARM(i->ARMin.VXferD.rHi);
2333//ZZ } else {
2334//ZZ ppHRegARM(i->ARMin.VXferD.rLo);
2335//ZZ vex_printf(", ");
2336//ZZ ppHRegARM(i->ARMin.VXferD.rHi);
2337//ZZ vex_printf(", ");
2338//ZZ ppHRegARM(i->ARMin.VXferD.dD);
2339//ZZ }
2340//ZZ return;
2341//ZZ case ARMin_VXferS:
2342//ZZ vex_printf("vmov ");
2343//ZZ if (i->ARMin.VXferS.toS) {
2344//ZZ ppHRegARM(i->ARMin.VXferS.fD);
2345//ZZ vex_printf(", ");
2346//ZZ ppHRegARM(i->ARMin.VXferS.rLo);
2347//ZZ } else {
2348//ZZ ppHRegARM(i->ARMin.VXferS.rLo);
2349//ZZ vex_printf(", ");
2350//ZZ ppHRegARM(i->ARMin.VXferS.fD);
2351//ZZ }
2352//ZZ return;
2353//ZZ case ARMin_VCvtID: {
2354//ZZ const HChar* nm = "?";
2355//ZZ if (i->ARMin.VCvtID.iToD) {
2356//ZZ nm = i->ARMin.VCvtID.syned ? "fsitod" : "fuitod";
2357//ZZ } else {
2358//ZZ nm = i->ARMin.VCvtID.syned ? "ftosid" : "ftouid";
2359//ZZ }
2360//ZZ vex_printf("%s ", nm);
2361//ZZ ppHRegARM(i->ARMin.VCvtID.dst);
2362//ZZ vex_printf(", ");
2363//ZZ ppHRegARM(i->ARMin.VCvtID.src);
2364//ZZ return;
2365//ZZ }
sewardjbbcf1882014-01-12 12:49:10 +00002366//ZZ case ARMin_NLdStD:
2367//ZZ if (i->ARMin.NLdStD.isLoad)
2368//ZZ vex_printf("vld1.32 {");
2369//ZZ else
2370//ZZ vex_printf("vst1.32 {");
2371//ZZ ppHRegARM(i->ARMin.NLdStD.dD);
2372//ZZ vex_printf("} ");
2373//ZZ ppARMAModeN(i->ARMin.NLdStD.amode);
2374//ZZ return;
2375//ZZ case ARMin_NUnary:
2376//ZZ vex_printf("%s%s%s ",
2377//ZZ showARMNeonUnOp(i->ARMin.NUnary.op),
2378//ZZ showARMNeonUnOpDataType(i->ARMin.NUnary.op),
2379//ZZ showARMNeonDataSize(i));
2380//ZZ ppHRegARM(i->ARMin.NUnary.dst);
2381//ZZ vex_printf(", ");
2382//ZZ ppHRegARM(i->ARMin.NUnary.src);
2383//ZZ if (i->ARMin.NUnary.op == ARMneon_EQZ)
2384//ZZ vex_printf(", #0");
2385//ZZ if (i->ARMin.NUnary.op == ARMneon_VCVTFtoFixedS ||
2386//ZZ i->ARMin.NUnary.op == ARMneon_VCVTFtoFixedU ||
2387//ZZ i->ARMin.NUnary.op == ARMneon_VCVTFixedStoF ||
2388//ZZ i->ARMin.NUnary.op == ARMneon_VCVTFixedUtoF) {
2389//ZZ vex_printf(", #%d", i->ARMin.NUnary.size);
2390//ZZ }
2391//ZZ if (i->ARMin.NUnary.op == ARMneon_VQSHLNSS ||
2392//ZZ i->ARMin.NUnary.op == ARMneon_VQSHLNUU ||
2393//ZZ i->ARMin.NUnary.op == ARMneon_VQSHLNUS) {
2394//ZZ UInt size;
2395//ZZ size = i->ARMin.NUnary.size;
2396//ZZ if (size & 0x40) {
2397//ZZ vex_printf(", #%d", size - 64);
2398//ZZ } else if (size & 0x20) {
2399//ZZ vex_printf(", #%d", size - 32);
2400//ZZ } else if (size & 0x10) {
2401//ZZ vex_printf(", #%d", size - 16);
2402//ZZ } else if (size & 0x08) {
2403//ZZ vex_printf(", #%d", size - 8);
2404//ZZ }
2405//ZZ }
2406//ZZ return;
2407//ZZ case ARMin_NUnaryS:
2408//ZZ vex_printf("%s%s%s ",
2409//ZZ showARMNeonUnOpS(i->ARMin.NUnaryS.op),
2410//ZZ showARMNeonUnOpSDataType(i->ARMin.NUnaryS.op),
2411//ZZ showARMNeonDataSize(i));
2412//ZZ ppARMNRS(i->ARMin.NUnaryS.dst);
2413//ZZ vex_printf(", ");
2414//ZZ ppARMNRS(i->ARMin.NUnaryS.src);
2415//ZZ return;
2416//ZZ case ARMin_NShift:
2417//ZZ vex_printf("%s%s%s ",
2418//ZZ showARMNeonShiftOp(i->ARMin.NShift.op),
2419//ZZ showARMNeonShiftOpDataType(i->ARMin.NShift.op),
2420//ZZ showARMNeonDataSize(i));
2421//ZZ ppHRegARM(i->ARMin.NShift.dst);
2422//ZZ vex_printf(", ");
2423//ZZ ppHRegARM(i->ARMin.NShift.argL);
2424//ZZ vex_printf(", ");
2425//ZZ ppHRegARM(i->ARMin.NShift.argR);
2426//ZZ return;
2427//ZZ case ARMin_NShl64:
2428//ZZ vex_printf("vshl.i64 ");
2429//ZZ ppHRegARM(i->ARMin.NShl64.dst);
2430//ZZ vex_printf(", ");
2431//ZZ ppHRegARM(i->ARMin.NShl64.src);
2432//ZZ vex_printf(", #%u", i->ARMin.NShl64.amt);
2433//ZZ return;
2434//ZZ case ARMin_NDual:
2435//ZZ vex_printf("%s%s%s ",
2436//ZZ showARMNeonDualOp(i->ARMin.NDual.op),
2437//ZZ showARMNeonDualOpDataType(i->ARMin.NDual.op),
2438//ZZ showARMNeonDataSize(i));
2439//ZZ ppHRegARM(i->ARMin.NDual.arg1);
2440//ZZ vex_printf(", ");
2441//ZZ ppHRegARM(i->ARMin.NDual.arg2);
2442//ZZ return;
2443//ZZ case ARMin_NBinary:
2444//ZZ vex_printf("%s%s%s",
2445//ZZ showARMNeonBinOp(i->ARMin.NBinary.op),
2446//ZZ showARMNeonBinOpDataType(i->ARMin.NBinary.op),
2447//ZZ showARMNeonDataSize(i));
2448//ZZ vex_printf(" ");
2449//ZZ ppHRegARM(i->ARMin.NBinary.dst);
2450//ZZ vex_printf(", ");
2451//ZZ ppHRegARM(i->ARMin.NBinary.argL);
2452//ZZ vex_printf(", ");
2453//ZZ ppHRegARM(i->ARMin.NBinary.argR);
2454//ZZ return;
2455 case ARM64in_VImmQ:
2456 vex_printf("qimm ");
2457 ppHRegARM64(i->ARM64in.VImmQ.rQ);
2458 vex_printf(", Bits16toBytes16(0x%x)", (UInt)i->ARM64in.VImmQ.imm);
2459 return;
2460 case ARM64in_VDfromX:
2461 vex_printf("fmov ");
2462 ppHRegARM64(i->ARM64in.VDfromX.rD);
2463 vex_printf(", ");
2464 ppHRegARM64(i->ARM64in.VDfromX.rX);
2465 return;
2466 case ARM64in_VQfromXX:
2467 vex_printf("qFromXX ");
2468 ppHRegARM64(i->ARM64in.VQfromXX.rQ);
2469 vex_printf(", ");
2470 ppHRegARM64(i->ARM64in.VQfromXX.rXhi);
2471 vex_printf(", ");
2472 ppHRegARM64(i->ARM64in.VQfromXX.rXlo);
2473 return;
2474 case ARM64in_VXfromQ:
2475 vex_printf("mov ");
2476 ppHRegARM64(i->ARM64in.VXfromQ.rX);
2477 vex_printf(", ");
2478 ppHRegARM64(i->ARM64in.VXfromQ.rQ);
2479 vex_printf(".d[%u]", i->ARM64in.VXfromQ.laneNo);
2480 return;
2481 case ARM64in_VMov: {
2482 UChar aux = '?';
2483 switch (i->ARM64in.VMov.szB) {
2484 case 16: aux = 'q'; break;
2485 case 8: aux = 'd'; break;
2486 case 4: aux = 's'; break;
2487 default: break;
2488 }
2489 vex_printf("mov(%c) ", aux);
2490 ppHRegARM64(i->ARM64in.VMov.dst);
2491 vex_printf(", ");
2492 ppHRegARM64(i->ARM64in.VMov.src);
2493 return;
2494 }
2495//ZZ case ARMin_NCMovQ:
2496//ZZ vex_printf("vmov%s ", showARMCondCode(i->ARMin.NCMovQ.cond));
2497//ZZ ppHRegARM(i->ARMin.NCMovQ.dst);
2498//ZZ vex_printf(", ");
2499//ZZ ppHRegARM(i->ARMin.NCMovQ.src);
2500//ZZ return;
2501//ZZ case ARMin_Add32:
2502//ZZ vex_printf("add32 ");
2503//ZZ ppHRegARM(i->ARMin.Add32.rD);
2504//ZZ vex_printf(", ");
2505//ZZ ppHRegARM(i->ARMin.Add32.rN);
2506//ZZ vex_printf(", ");
2507//ZZ vex_printf("%d", i->ARMin.Add32.imm32);
2508//ZZ return;
2509 case ARM64in_EvCheck:
2510 vex_printf("(evCheck) ldr w9,");
2511 ppARM64AMode(i->ARM64in.EvCheck.amCounter);
2512 vex_printf("; subs w9,w9,$1; str w9,");
2513 ppARM64AMode(i->ARM64in.EvCheck.amCounter);
2514 vex_printf("; bpl nofail; ldr x9,");
2515 ppARM64AMode(i->ARM64in.EvCheck.amFailAddr);
2516 vex_printf("; br x9; nofail:");
2517 return;
2518//ZZ case ARMin_ProfInc:
2519//ZZ vex_printf("(profInc) movw r12,LO16($NotKnownYet); "
2520//ZZ "movw r12,HI16($NotKnownYet); "
2521//ZZ "ldr r11,[r12]; "
2522//ZZ "adds r11,r11,$1; "
2523//ZZ "str r11,[r12]; "
2524//ZZ "ldr r11,[r12+4]; "
2525//ZZ "adc r11,r11,$0; "
2526//ZZ "str r11,[r12+4]");
2527//ZZ return;
2528 default:
2529 vex_printf("ppARM64Instr: unhandled case (tag %d)", (Int)i->tag);
2530 vpanic("ppARM64Instr(1)");
2531 return;
2532 }
2533}
2534
2535
2536/* --------- Helpers for register allocation. --------- */
2537
2538void getRegUsage_ARM64Instr ( HRegUsage* u, ARM64Instr* i, Bool mode64 )
2539{
2540 vassert(mode64 == True);
2541 initHRegUsage(u);
2542 switch (i->tag) {
2543 case ARM64in_Arith:
2544 addHRegUse(u, HRmWrite, i->ARM64in.Arith.dst);
2545 addHRegUse(u, HRmRead, i->ARM64in.Arith.argL);
2546 addRegUsage_ARM64RIA(u, i->ARM64in.Arith.argR);
2547 return;
2548 case ARM64in_Cmp:
2549 addHRegUse(u, HRmRead, i->ARM64in.Cmp.argL);
2550 addRegUsage_ARM64RIA(u, i->ARM64in.Cmp.argR);
2551 return;
2552 case ARM64in_Logic:
2553 addHRegUse(u, HRmWrite, i->ARM64in.Logic.dst);
2554 addHRegUse(u, HRmRead, i->ARM64in.Logic.argL);
2555 addRegUsage_ARM64RIL(u, i->ARM64in.Logic.argR);
2556 return;
2557 case ARM64in_Test:
2558 addHRegUse(u, HRmRead, i->ARM64in.Test.argL);
2559 addRegUsage_ARM64RIL(u, i->ARM64in.Test.argR);
2560 return;
2561 case ARM64in_Shift:
2562 addHRegUse(u, HRmWrite, i->ARM64in.Shift.dst);
2563 addHRegUse(u, HRmRead, i->ARM64in.Shift.argL);
2564 addRegUsage_ARM64RI6(u, i->ARM64in.Shift.argR);
2565 return;
2566 case ARM64in_Unary:
2567 addHRegUse(u, HRmWrite, i->ARM64in.Unary.dst);
2568 addHRegUse(u, HRmRead, i->ARM64in.Unary.src);
2569 return;
2570 case ARM64in_MovI:
2571 addHRegUse(u, HRmWrite, i->ARM64in.MovI.dst);
2572 addHRegUse(u, HRmRead, i->ARM64in.MovI.src);
2573 return;
2574 case ARM64in_Imm64:
2575 addHRegUse(u, HRmWrite, i->ARM64in.Imm64.dst);
2576 return;
2577 case ARM64in_LdSt64:
2578 addRegUsage_ARM64AMode(u, i->ARM64in.LdSt64.amode);
2579 if (i->ARM64in.LdSt64.isLoad) {
2580 addHRegUse(u, HRmWrite, i->ARM64in.LdSt64.rD);
2581 } else {
2582 addHRegUse(u, HRmRead, i->ARM64in.LdSt64.rD);
2583 }
2584 return;
2585 case ARM64in_LdSt32:
2586 addRegUsage_ARM64AMode(u, i->ARM64in.LdSt32.amode);
2587 if (i->ARM64in.LdSt32.isLoad) {
2588 addHRegUse(u, HRmWrite, i->ARM64in.LdSt32.rD);
2589 } else {
2590 addHRegUse(u, HRmRead, i->ARM64in.LdSt32.rD);
2591 }
2592 return;
2593 case ARM64in_LdSt16:
2594 addRegUsage_ARM64AMode(u, i->ARM64in.LdSt16.amode);
2595 if (i->ARM64in.LdSt16.isLoad) {
2596 addHRegUse(u, HRmWrite, i->ARM64in.LdSt16.rD);
2597 } else {
2598 addHRegUse(u, HRmRead, i->ARM64in.LdSt16.rD);
2599 }
2600 return;
2601 case ARM64in_LdSt8:
2602 addRegUsage_ARM64AMode(u, i->ARM64in.LdSt8.amode);
2603 if (i->ARM64in.LdSt8.isLoad) {
2604 addHRegUse(u, HRmWrite, i->ARM64in.LdSt8.rD);
2605 } else {
2606 addHRegUse(u, HRmRead, i->ARM64in.LdSt8.rD);
2607 }
2608 return;
2609 /* XDirect/XIndir/XAssisted are also a bit subtle. They
2610 conditionally exit the block. Hence we only need to list (1)
2611 the registers that they read, and (2) the registers that they
2612 write in the case where the block is not exited. (2) is
2613 empty, hence only (1) is relevant here. */
2614 case ARM64in_XDirect:
2615 addRegUsage_ARM64AMode(u, i->ARM64in.XDirect.amPC);
2616 return;
2617 case ARM64in_XIndir:
2618 addHRegUse(u, HRmRead, i->ARM64in.XIndir.dstGA);
2619 addRegUsage_ARM64AMode(u, i->ARM64in.XIndir.amPC);
2620 return;
2621 case ARM64in_XAssisted:
2622 addHRegUse(u, HRmRead, i->ARM64in.XAssisted.dstGA);
2623 addRegUsage_ARM64AMode(u, i->ARM64in.XAssisted.amPC);
2624 return;
2625 case ARM64in_CSel:
2626 addHRegUse(u, HRmWrite, i->ARM64in.CSel.dst);
2627 addHRegUse(u, HRmRead, i->ARM64in.CSel.argL);
2628 addHRegUse(u, HRmRead, i->ARM64in.CSel.argR);
2629 return;
2630 case ARM64in_Call:
2631 /* logic and comments copied/modified from x86 back end */
2632 /* This is a bit subtle. */
2633 /* First off, claim it trashes all the caller-saved regs
2634 which fall within the register allocator's jurisdiction.
2635 These I believe to be x0 to x7. Also need to be
2636 careful about vector regs. */
2637 addHRegUse(u, HRmWrite, hregARM64_X0());
2638 addHRegUse(u, HRmWrite, hregARM64_X1());
2639 addHRegUse(u, HRmWrite, hregARM64_X2());
2640 addHRegUse(u, HRmWrite, hregARM64_X3());
2641 addHRegUse(u, HRmWrite, hregARM64_X4());
2642 addHRegUse(u, HRmWrite, hregARM64_X5());
2643 addHRegUse(u, HRmWrite, hregARM64_X6());
2644 addHRegUse(u, HRmWrite, hregARM64_X7());
2645 addHRegUse(u, HRmWrite, hregARM64_Q16());
2646 addHRegUse(u, HRmWrite, hregARM64_Q17());
2647 addHRegUse(u, HRmWrite, hregARM64_Q18());
2648 /* Now we have to state any parameter-carrying registers
2649 which might be read. This depends on nArgRegs. */
2650 switch (i->ARM64in.Call.nArgRegs) {
2651 case 8: addHRegUse(u, HRmRead, hregARM64_X7()); /*fallthru*/
2652 case 7: addHRegUse(u, HRmRead, hregARM64_X6()); /*fallthru*/
2653 case 6: addHRegUse(u, HRmRead, hregARM64_X5()); /*fallthru*/
2654 case 5: addHRegUse(u, HRmRead, hregARM64_X4()); /*fallthru*/
2655 case 4: addHRegUse(u, HRmRead, hregARM64_X3()); /*fallthru*/
2656 case 3: addHRegUse(u, HRmRead, hregARM64_X2()); /*fallthru*/
2657 case 2: addHRegUse(u, HRmRead, hregARM64_X1()); /*fallthru*/
2658 case 1: addHRegUse(u, HRmRead, hregARM64_X0()); break;
2659 case 0: break;
2660 default: vpanic("getRegUsage_ARM64:Call:regparms");
2661 }
2662 /* Finally, there is the issue that the insn trashes a
2663 register because the literal target address has to be
2664 loaded into a register. However, we reserve x9 for that
2665 purpose so there's no further complexity here. Stating x9
2666 as trashed is pointless since it's not under the control
2667 of the allocator, but what the hell. */
2668 addHRegUse(u, HRmWrite, hregARM64_X9());
2669 return;
2670 case ARM64in_AddToSP:
2671 /* Only changes SP, but regalloc doesn't control that, hence
2672 we don't care. */
2673 return;
2674 case ARM64in_FromSP:
2675 addHRegUse(u, HRmWrite, i->ARM64in.FromSP.dst);
2676 return;
2677 case ARM64in_Mul:
2678 addHRegUse(u, HRmWrite, i->ARM64in.Mul.dst);
2679 addHRegUse(u, HRmRead, i->ARM64in.Mul.argL);
2680 addHRegUse(u, HRmRead, i->ARM64in.Mul.argR);
2681 return;
sewardj7d009132014-02-20 17:43:38 +00002682 case ARM64in_LdrEX:
2683 addHRegUse(u, HRmRead, hregARM64_X4());
2684 addHRegUse(u, HRmWrite, hregARM64_X2());
2685 return;
2686 case ARM64in_StrEX:
2687 addHRegUse(u, HRmRead, hregARM64_X4());
2688 addHRegUse(u, HRmWrite, hregARM64_X0());
2689 addHRegUse(u, HRmRead, hregARM64_X2());
2690 return;
2691 case ARM64in_MFence:
2692 return;
2693//ZZ case ARMin_CLREX:
sewardjbbcf1882014-01-12 12:49:10 +00002694//ZZ return;
2695 case ARM64in_VLdStS:
2696 addHRegUse(u, HRmRead, i->ARM64in.VLdStS.rN);
2697 if (i->ARM64in.VLdStS.isLoad) {
2698 addHRegUse(u, HRmWrite, i->ARM64in.VLdStS.sD);
2699 } else {
2700 addHRegUse(u, HRmRead, i->ARM64in.VLdStS.sD);
2701 }
2702 return;
2703 case ARM64in_VLdStD:
2704 addHRegUse(u, HRmRead, i->ARM64in.VLdStD.rN);
2705 if (i->ARM64in.VLdStD.isLoad) {
2706 addHRegUse(u, HRmWrite, i->ARM64in.VLdStD.dD);
2707 } else {
2708 addHRegUse(u, HRmRead, i->ARM64in.VLdStD.dD);
2709 }
2710 return;
2711 case ARM64in_VLdStQ:
2712 addHRegUse(u, HRmRead, i->ARM64in.VLdStQ.rN);
2713 if (i->ARM64in.VLdStQ.isLoad)
2714 addHRegUse(u, HRmWrite, i->ARM64in.VLdStQ.rQ);
2715 else
2716 addHRegUse(u, HRmRead, i->ARM64in.VLdStQ.rQ);
2717 return;
2718 case ARM64in_VCvtI2F:
2719 addHRegUse(u, HRmRead, i->ARM64in.VCvtI2F.rS);
2720 addHRegUse(u, HRmWrite, i->ARM64in.VCvtI2F.rD);
2721 return;
2722 case ARM64in_VCvtF2I:
2723 addHRegUse(u, HRmRead, i->ARM64in.VCvtF2I.rS);
2724 addHRegUse(u, HRmWrite, i->ARM64in.VCvtF2I.rD);
2725 return;
2726 case ARM64in_VCvtSD:
2727 addHRegUse(u, HRmWrite, i->ARM64in.VCvtSD.dst);
2728 addHRegUse(u, HRmRead, i->ARM64in.VCvtSD.src);
2729 return;
2730 case ARM64in_VUnaryD:
2731 addHRegUse(u, HRmWrite, i->ARM64in.VUnaryD.dst);
2732 addHRegUse(u, HRmRead, i->ARM64in.VUnaryD.src);
2733 return;
2734 case ARM64in_VUnaryS:
2735 addHRegUse(u, HRmWrite, i->ARM64in.VUnaryS.dst);
2736 addHRegUse(u, HRmRead, i->ARM64in.VUnaryS.src);
2737 return;
2738 case ARM64in_VBinD:
2739 addHRegUse(u, HRmWrite, i->ARM64in.VBinD.dst);
2740 addHRegUse(u, HRmRead, i->ARM64in.VBinD.argL);
2741 addHRegUse(u, HRmRead, i->ARM64in.VBinD.argR);
2742 return;
2743 case ARM64in_VBinS:
2744 addHRegUse(u, HRmWrite, i->ARM64in.VBinS.dst);
2745 addHRegUse(u, HRmRead, i->ARM64in.VBinS.argL);
2746 addHRegUse(u, HRmRead, i->ARM64in.VBinS.argR);
2747 return;
2748 case ARM64in_VCmpD:
2749 addHRegUse(u, HRmRead, i->ARM64in.VCmpD.argL);
2750 addHRegUse(u, HRmRead, i->ARM64in.VCmpD.argR);
2751 return;
2752 case ARM64in_VCmpS:
2753 addHRegUse(u, HRmRead, i->ARM64in.VCmpS.argL);
2754 addHRegUse(u, HRmRead, i->ARM64in.VCmpS.argR);
2755 return;
2756 case ARM64in_FPCR:
2757 if (i->ARM64in.FPCR.toFPCR)
2758 addHRegUse(u, HRmRead, i->ARM64in.FPCR.iReg);
2759 else
2760 addHRegUse(u, HRmWrite, i->ARM64in.FPCR.iReg);
2761 return;
sewardj606c4ba2014-01-26 19:11:14 +00002762 case ARM64in_VBinV:
2763 addHRegUse(u, HRmWrite, i->ARM64in.VBinV.dst);
2764 addHRegUse(u, HRmRead, i->ARM64in.VBinV.argL);
2765 addHRegUse(u, HRmRead, i->ARM64in.VBinV.argR);
2766 return;
sewardjfab09142014-02-10 10:28:13 +00002767 case ARM64in_VUnaryV:
2768 addHRegUse(u, HRmWrite, i->ARM64in.VUnaryV.dst);
2769 addHRegUse(u, HRmRead, i->ARM64in.VUnaryV.arg);
2770 return;
sewardj606c4ba2014-01-26 19:11:14 +00002771 case ARM64in_VNarrowV:
2772 addHRegUse(u, HRmWrite, i->ARM64in.VNarrowV.dst);
2773 addHRegUse(u, HRmRead, i->ARM64in.VNarrowV.src);
2774 return;
sewardje520bb32014-02-17 11:00:53 +00002775 case ARM64in_VShiftImmV:
2776 addHRegUse(u, HRmWrite, i->ARM64in.VShiftImmV.dst);
2777 addHRegUse(u, HRmRead, i->ARM64in.VShiftImmV.src);
2778 return;
sewardjbbcf1882014-01-12 12:49:10 +00002779//ZZ case ARMin_VAluS:
2780//ZZ addHRegUse(u, HRmWrite, i->ARMin.VAluS.dst);
2781//ZZ addHRegUse(u, HRmRead, i->ARMin.VAluS.argL);
2782//ZZ addHRegUse(u, HRmRead, i->ARMin.VAluS.argR);
2783//ZZ return;
2784//ZZ case ARMin_VUnaryS:
2785//ZZ addHRegUse(u, HRmWrite, i->ARMin.VUnaryS.dst);
2786//ZZ addHRegUse(u, HRmRead, i->ARMin.VUnaryS.src);
2787//ZZ return;
2788//ZZ case ARMin_VCMovD:
2789//ZZ addHRegUse(u, HRmWrite, i->ARMin.VCMovD.dst);
2790//ZZ addHRegUse(u, HRmRead, i->ARMin.VCMovD.dst);
2791//ZZ addHRegUse(u, HRmRead, i->ARMin.VCMovD.src);
2792//ZZ return;
2793//ZZ case ARMin_VCMovS:
2794//ZZ addHRegUse(u, HRmWrite, i->ARMin.VCMovS.dst);
2795//ZZ addHRegUse(u, HRmRead, i->ARMin.VCMovS.dst);
2796//ZZ addHRegUse(u, HRmRead, i->ARMin.VCMovS.src);
2797//ZZ return;
2798//ZZ case ARMin_VXferD:
2799//ZZ if (i->ARMin.VXferD.toD) {
2800//ZZ addHRegUse(u, HRmWrite, i->ARMin.VXferD.dD);
2801//ZZ addHRegUse(u, HRmRead, i->ARMin.VXferD.rHi);
2802//ZZ addHRegUse(u, HRmRead, i->ARMin.VXferD.rLo);
2803//ZZ } else {
2804//ZZ addHRegUse(u, HRmRead, i->ARMin.VXferD.dD);
2805//ZZ addHRegUse(u, HRmWrite, i->ARMin.VXferD.rHi);
2806//ZZ addHRegUse(u, HRmWrite, i->ARMin.VXferD.rLo);
2807//ZZ }
2808//ZZ return;
2809//ZZ case ARMin_VXferS:
2810//ZZ if (i->ARMin.VXferS.toS) {
2811//ZZ addHRegUse(u, HRmWrite, i->ARMin.VXferS.fD);
2812//ZZ addHRegUse(u, HRmRead, i->ARMin.VXferS.rLo);
2813//ZZ } else {
2814//ZZ addHRegUse(u, HRmRead, i->ARMin.VXferS.fD);
2815//ZZ addHRegUse(u, HRmWrite, i->ARMin.VXferS.rLo);
2816//ZZ }
2817//ZZ return;
2818//ZZ case ARMin_VCvtID:
2819//ZZ addHRegUse(u, HRmWrite, i->ARMin.VCvtID.dst);
2820//ZZ addHRegUse(u, HRmRead, i->ARMin.VCvtID.src);
2821//ZZ return;
sewardjbbcf1882014-01-12 12:49:10 +00002822//ZZ case ARMin_NLdStD:
2823//ZZ if (i->ARMin.NLdStD.isLoad)
2824//ZZ addHRegUse(u, HRmWrite, i->ARMin.NLdStD.dD);
2825//ZZ else
2826//ZZ addHRegUse(u, HRmRead, i->ARMin.NLdStD.dD);
2827//ZZ addRegUsage_ARMAModeN(u, i->ARMin.NLdStD.amode);
2828//ZZ return;
2829//ZZ case ARMin_NUnary:
2830//ZZ addHRegUse(u, HRmWrite, i->ARMin.NUnary.dst);
2831//ZZ addHRegUse(u, HRmRead, i->ARMin.NUnary.src);
2832//ZZ return;
2833//ZZ case ARMin_NUnaryS:
2834//ZZ addHRegUse(u, HRmWrite, i->ARMin.NUnaryS.dst->reg);
2835//ZZ addHRegUse(u, HRmRead, i->ARMin.NUnaryS.src->reg);
2836//ZZ return;
2837//ZZ case ARMin_NShift:
2838//ZZ addHRegUse(u, HRmWrite, i->ARMin.NShift.dst);
2839//ZZ addHRegUse(u, HRmRead, i->ARMin.NShift.argL);
2840//ZZ addHRegUse(u, HRmRead, i->ARMin.NShift.argR);
2841//ZZ return;
2842//ZZ case ARMin_NShl64:
2843//ZZ addHRegUse(u, HRmWrite, i->ARMin.NShl64.dst);
2844//ZZ addHRegUse(u, HRmRead, i->ARMin.NShl64.src);
2845//ZZ return;
2846//ZZ case ARMin_NDual:
2847//ZZ addHRegUse(u, HRmWrite, i->ARMin.NDual.arg1);
2848//ZZ addHRegUse(u, HRmWrite, i->ARMin.NDual.arg2);
2849//ZZ addHRegUse(u, HRmRead, i->ARMin.NDual.arg1);
2850//ZZ addHRegUse(u, HRmRead, i->ARMin.NDual.arg2);
2851//ZZ return;
2852 case ARM64in_VImmQ:
2853 addHRegUse(u, HRmWrite, i->ARM64in.VImmQ.rQ);
2854 return;
2855 case ARM64in_VDfromX:
2856 addHRegUse(u, HRmWrite, i->ARM64in.VDfromX.rD);
2857 addHRegUse(u, HRmRead, i->ARM64in.VDfromX.rX);
2858 return;
2859 case ARM64in_VQfromXX:
2860 addHRegUse(u, HRmWrite, i->ARM64in.VQfromXX.rQ);
2861 addHRegUse(u, HRmRead, i->ARM64in.VQfromXX.rXhi);
2862 addHRegUse(u, HRmRead, i->ARM64in.VQfromXX.rXlo);
2863 return;
2864 case ARM64in_VXfromQ:
2865 addHRegUse(u, HRmWrite, i->ARM64in.VXfromQ.rX);
2866 addHRegUse(u, HRmRead, i->ARM64in.VXfromQ.rQ);
2867 return;
2868 case ARM64in_VMov:
2869 addHRegUse(u, HRmWrite, i->ARM64in.VMov.dst);
2870 addHRegUse(u, HRmRead, i->ARM64in.VMov.src);
2871 return;
2872//ZZ case ARMin_NBinary:
2873//ZZ addHRegUse(u, HRmWrite, i->ARMin.NBinary.dst);
2874//ZZ /* TODO: sometimes dst is also being read! */
2875//ZZ // XXX fix this
2876//ZZ addHRegUse(u, HRmRead, i->ARMin.NBinary.argL);
2877//ZZ addHRegUse(u, HRmRead, i->ARMin.NBinary.argR);
2878//ZZ return;
2879//ZZ case ARMin_NCMovQ:
2880//ZZ addHRegUse(u, HRmWrite, i->ARMin.NCMovQ.dst);
2881//ZZ addHRegUse(u, HRmRead, i->ARMin.NCMovQ.dst);
2882//ZZ addHRegUse(u, HRmRead, i->ARMin.NCMovQ.src);
2883//ZZ return;
2884//ZZ case ARMin_Add32:
2885//ZZ addHRegUse(u, HRmWrite, i->ARMin.Add32.rD);
2886//ZZ addHRegUse(u, HRmRead, i->ARMin.Add32.rN);
2887//ZZ return;
2888 case ARM64in_EvCheck:
2889 /* We expect both amodes only to mention x21, so this is in
2890 fact pointless, since x21 isn't allocatable, but
2891 anyway.. */
2892 addRegUsage_ARM64AMode(u, i->ARM64in.EvCheck.amCounter);
2893 addRegUsage_ARM64AMode(u, i->ARM64in.EvCheck.amFailAddr);
2894 addHRegUse(u, HRmWrite, hregARM64_X9()); /* also unavail to RA */
2895 return;
2896//ZZ case ARMin_ProfInc:
2897//ZZ addHRegUse(u, HRmWrite, hregARM_R12());
2898//ZZ addHRegUse(u, HRmWrite, hregARM_R11());
2899//ZZ return;
2900 default:
2901 ppARM64Instr(i);
2902 vpanic("getRegUsage_ARM64Instr");
2903 }
2904}
2905
2906
2907void mapRegs_ARM64Instr ( HRegRemap* m, ARM64Instr* i, Bool mode64 )
2908{
2909 vassert(mode64 == True);
2910 switch (i->tag) {
2911 case ARM64in_Arith:
2912 i->ARM64in.Arith.dst = lookupHRegRemap(m, i->ARM64in.Arith.dst);
2913 i->ARM64in.Arith.argL = lookupHRegRemap(m, i->ARM64in.Arith.argL);
2914 mapRegs_ARM64RIA(m, i->ARM64in.Arith.argR);
2915 return;
2916 case ARM64in_Cmp:
2917 i->ARM64in.Cmp.argL = lookupHRegRemap(m, i->ARM64in.Cmp.argL);
2918 mapRegs_ARM64RIA(m, i->ARM64in.Cmp.argR);
2919 return;
2920 case ARM64in_Logic:
2921 i->ARM64in.Logic.dst = lookupHRegRemap(m, i->ARM64in.Logic.dst);
2922 i->ARM64in.Logic.argL = lookupHRegRemap(m, i->ARM64in.Logic.argL);
2923 mapRegs_ARM64RIL(m, i->ARM64in.Logic.argR);
2924 return;
2925 case ARM64in_Test:
2926 i->ARM64in.Test.argL = lookupHRegRemap(m, i->ARM64in.Test.argL);
2927 mapRegs_ARM64RIL(m, i->ARM64in.Logic.argR);
2928 return;
2929 case ARM64in_Shift:
2930 i->ARM64in.Shift.dst = lookupHRegRemap(m, i->ARM64in.Shift.dst);
2931 i->ARM64in.Shift.argL = lookupHRegRemap(m, i->ARM64in.Shift.argL);
2932 mapRegs_ARM64RI6(m, i->ARM64in.Shift.argR);
2933 return;
2934 case ARM64in_Unary:
2935 i->ARM64in.Unary.dst = lookupHRegRemap(m, i->ARM64in.Unary.dst);
2936 i->ARM64in.Unary.src = lookupHRegRemap(m, i->ARM64in.Unary.src);
2937 return;
2938 case ARM64in_MovI:
2939 i->ARM64in.MovI.dst = lookupHRegRemap(m, i->ARM64in.MovI.dst);
2940 i->ARM64in.MovI.src = lookupHRegRemap(m, i->ARM64in.MovI.src);
2941 return;
2942 case ARM64in_Imm64:
2943 i->ARM64in.Imm64.dst = lookupHRegRemap(m, i->ARM64in.Imm64.dst);
2944 return;
2945 case ARM64in_LdSt64:
2946 i->ARM64in.LdSt64.rD = lookupHRegRemap(m, i->ARM64in.LdSt64.rD);
2947 mapRegs_ARM64AMode(m, i->ARM64in.LdSt64.amode);
2948 return;
2949 case ARM64in_LdSt32:
2950 i->ARM64in.LdSt32.rD = lookupHRegRemap(m, i->ARM64in.LdSt32.rD);
2951 mapRegs_ARM64AMode(m, i->ARM64in.LdSt32.amode);
2952 return;
2953 case ARM64in_LdSt16:
2954 i->ARM64in.LdSt16.rD = lookupHRegRemap(m, i->ARM64in.LdSt16.rD);
2955 mapRegs_ARM64AMode(m, i->ARM64in.LdSt16.amode);
2956 return;
2957 case ARM64in_LdSt8:
2958 i->ARM64in.LdSt8.rD = lookupHRegRemap(m, i->ARM64in.LdSt8.rD);
2959 mapRegs_ARM64AMode(m, i->ARM64in.LdSt8.amode);
2960 return;
2961 case ARM64in_XDirect:
2962 mapRegs_ARM64AMode(m, i->ARM64in.XDirect.amPC);
2963 return;
2964 case ARM64in_XIndir:
2965 i->ARM64in.XIndir.dstGA
2966 = lookupHRegRemap(m, i->ARM64in.XIndir.dstGA);
2967 mapRegs_ARM64AMode(m, i->ARM64in.XIndir.amPC);
2968 return;
2969 case ARM64in_XAssisted:
2970 i->ARM64in.XAssisted.dstGA
2971 = lookupHRegRemap(m, i->ARM64in.XAssisted.dstGA);
2972 mapRegs_ARM64AMode(m, i->ARM64in.XAssisted.amPC);
2973 return;
2974 case ARM64in_CSel:
2975 i->ARM64in.CSel.dst = lookupHRegRemap(m, i->ARM64in.CSel.dst);
2976 i->ARM64in.CSel.argL = lookupHRegRemap(m, i->ARM64in.CSel.argL);
2977 i->ARM64in.CSel.argR = lookupHRegRemap(m, i->ARM64in.CSel.argR);
2978 return;
2979 case ARM64in_Call:
2980 return;
2981 case ARM64in_AddToSP:
2982 return;
2983 case ARM64in_FromSP:
2984 i->ARM64in.FromSP.dst = lookupHRegRemap(m, i->ARM64in.FromSP.dst);
2985 return;
2986 case ARM64in_Mul:
2987 i->ARM64in.Mul.dst = lookupHRegRemap(m, i->ARM64in.Mul.dst);
2988 i->ARM64in.Mul.argL = lookupHRegRemap(m, i->ARM64in.Mul.argL);
2989 i->ARM64in.Mul.argR = lookupHRegRemap(m, i->ARM64in.Mul.argR);
2990 break;
sewardj7d009132014-02-20 17:43:38 +00002991 case ARM64in_LdrEX:
2992 return;
2993 case ARM64in_StrEX:
2994 return;
2995 case ARM64in_MFence:
2996 return;
2997//ZZ case ARMin_CLREX:
sewardjbbcf1882014-01-12 12:49:10 +00002998//ZZ return;
2999 case ARM64in_VLdStS:
3000 i->ARM64in.VLdStS.sD = lookupHRegRemap(m, i->ARM64in.VLdStS.sD);
3001 i->ARM64in.VLdStS.rN = lookupHRegRemap(m, i->ARM64in.VLdStS.rN);
3002 return;
3003 case ARM64in_VLdStD:
3004 i->ARM64in.VLdStD.dD = lookupHRegRemap(m, i->ARM64in.VLdStD.dD);
3005 i->ARM64in.VLdStD.rN = lookupHRegRemap(m, i->ARM64in.VLdStD.rN);
3006 return;
3007 case ARM64in_VLdStQ:
3008 i->ARM64in.VLdStQ.rQ = lookupHRegRemap(m, i->ARM64in.VLdStQ.rQ);
3009 i->ARM64in.VLdStQ.rN = lookupHRegRemap(m, i->ARM64in.VLdStQ.rN);
3010 return;
3011 case ARM64in_VCvtI2F:
3012 i->ARM64in.VCvtI2F.rS = lookupHRegRemap(m, i->ARM64in.VCvtI2F.rS);
3013 i->ARM64in.VCvtI2F.rD = lookupHRegRemap(m, i->ARM64in.VCvtI2F.rD);
3014 return;
3015 case ARM64in_VCvtF2I:
3016 i->ARM64in.VCvtF2I.rS = lookupHRegRemap(m, i->ARM64in.VCvtF2I.rS);
3017 i->ARM64in.VCvtF2I.rD = lookupHRegRemap(m, i->ARM64in.VCvtF2I.rD);
3018 return;
3019 case ARM64in_VCvtSD:
3020 i->ARM64in.VCvtSD.dst = lookupHRegRemap(m, i->ARM64in.VCvtSD.dst);
3021 i->ARM64in.VCvtSD.src = lookupHRegRemap(m, i->ARM64in.VCvtSD.src);
3022 return;
3023 case ARM64in_VUnaryD:
3024 i->ARM64in.VUnaryD.dst = lookupHRegRemap(m, i->ARM64in.VUnaryD.dst);
3025 i->ARM64in.VUnaryD.src = lookupHRegRemap(m, i->ARM64in.VUnaryD.src);
3026 return;
3027 case ARM64in_VUnaryS:
3028 i->ARM64in.VUnaryS.dst = lookupHRegRemap(m, i->ARM64in.VUnaryS.dst);
3029 i->ARM64in.VUnaryS.src = lookupHRegRemap(m, i->ARM64in.VUnaryS.src);
3030 return;
3031 case ARM64in_VBinD:
3032 i->ARM64in.VBinD.dst = lookupHRegRemap(m, i->ARM64in.VBinD.dst);
3033 i->ARM64in.VBinD.argL = lookupHRegRemap(m, i->ARM64in.VBinD.argL);
3034 i->ARM64in.VBinD.argR = lookupHRegRemap(m, i->ARM64in.VBinD.argR);
3035 return;
3036 case ARM64in_VBinS:
3037 i->ARM64in.VBinS.dst = lookupHRegRemap(m, i->ARM64in.VBinS.dst);
3038 i->ARM64in.VBinS.argL = lookupHRegRemap(m, i->ARM64in.VBinS.argL);
3039 i->ARM64in.VBinS.argR = lookupHRegRemap(m, i->ARM64in.VBinS.argR);
3040 return;
3041 case ARM64in_VCmpD:
3042 i->ARM64in.VCmpD.argL = lookupHRegRemap(m, i->ARM64in.VCmpD.argL);
3043 i->ARM64in.VCmpD.argR = lookupHRegRemap(m, i->ARM64in.VCmpD.argR);
3044 return;
3045 case ARM64in_VCmpS:
3046 i->ARM64in.VCmpS.argL = lookupHRegRemap(m, i->ARM64in.VCmpS.argL);
3047 i->ARM64in.VCmpS.argR = lookupHRegRemap(m, i->ARM64in.VCmpS.argR);
3048 return;
3049 case ARM64in_FPCR:
3050 i->ARM64in.FPCR.iReg = lookupHRegRemap(m, i->ARM64in.FPCR.iReg);
3051 return;
sewardj606c4ba2014-01-26 19:11:14 +00003052 case ARM64in_VBinV:
3053 i->ARM64in.VBinV.dst = lookupHRegRemap(m, i->ARM64in.VBinV.dst);
3054 i->ARM64in.VBinV.argL = lookupHRegRemap(m, i->ARM64in.VBinV.argL);
3055 i->ARM64in.VBinV.argR = lookupHRegRemap(m, i->ARM64in.VBinV.argR);
3056 return;
sewardjfab09142014-02-10 10:28:13 +00003057 case ARM64in_VUnaryV:
3058 i->ARM64in.VUnaryV.dst = lookupHRegRemap(m, i->ARM64in.VUnaryV.dst);
3059 i->ARM64in.VUnaryV.arg = lookupHRegRemap(m, i->ARM64in.VUnaryV.arg);
3060 return;
sewardj606c4ba2014-01-26 19:11:14 +00003061 case ARM64in_VNarrowV:
3062 i->ARM64in.VNarrowV.dst = lookupHRegRemap(m, i->ARM64in.VNarrowV.dst);
3063 i->ARM64in.VNarrowV.src = lookupHRegRemap(m, i->ARM64in.VNarrowV.src);
3064 return;
sewardje520bb32014-02-17 11:00:53 +00003065 case ARM64in_VShiftImmV:
3066 i->ARM64in.VShiftImmV.dst
3067 = lookupHRegRemap(m, i->ARM64in.VShiftImmV.dst);
3068 i->ARM64in.VShiftImmV.src
3069 = lookupHRegRemap(m, i->ARM64in.VShiftImmV.src);
3070 return;
sewardjbbcf1882014-01-12 12:49:10 +00003071//ZZ case ARMin_VAluS:
3072//ZZ i->ARMin.VAluS.dst = lookupHRegRemap(m, i->ARMin.VAluS.dst);
3073//ZZ i->ARMin.VAluS.argL = lookupHRegRemap(m, i->ARMin.VAluS.argL);
3074//ZZ i->ARMin.VAluS.argR = lookupHRegRemap(m, i->ARMin.VAluS.argR);
3075//ZZ return;
3076//ZZ case ARMin_VCMovD:
3077//ZZ i->ARMin.VCMovD.dst = lookupHRegRemap(m, i->ARMin.VCMovD.dst);
3078//ZZ i->ARMin.VCMovD.src = lookupHRegRemap(m, i->ARMin.VCMovD.src);
3079//ZZ return;
3080//ZZ case ARMin_VCMovS:
3081//ZZ i->ARMin.VCMovS.dst = lookupHRegRemap(m, i->ARMin.VCMovS.dst);
3082//ZZ i->ARMin.VCMovS.src = lookupHRegRemap(m, i->ARMin.VCMovS.src);
3083//ZZ return;
3084//ZZ case ARMin_VXferD:
3085//ZZ i->ARMin.VXferD.dD = lookupHRegRemap(m, i->ARMin.VXferD.dD);
3086//ZZ i->ARMin.VXferD.rHi = lookupHRegRemap(m, i->ARMin.VXferD.rHi);
3087//ZZ i->ARMin.VXferD.rLo = lookupHRegRemap(m, i->ARMin.VXferD.rLo);
3088//ZZ return;
3089//ZZ case ARMin_VXferS:
3090//ZZ i->ARMin.VXferS.fD = lookupHRegRemap(m, i->ARMin.VXferS.fD);
3091//ZZ i->ARMin.VXferS.rLo = lookupHRegRemap(m, i->ARMin.VXferS.rLo);
3092//ZZ return;
3093//ZZ case ARMin_VCvtID:
3094//ZZ i->ARMin.VCvtID.dst = lookupHRegRemap(m, i->ARMin.VCvtID.dst);
3095//ZZ i->ARMin.VCvtID.src = lookupHRegRemap(m, i->ARMin.VCvtID.src);
3096//ZZ return;
sewardjbbcf1882014-01-12 12:49:10 +00003097//ZZ case ARMin_NLdStD:
3098//ZZ i->ARMin.NLdStD.dD = lookupHRegRemap(m, i->ARMin.NLdStD.dD);
3099//ZZ mapRegs_ARMAModeN(m, i->ARMin.NLdStD.amode);
3100//ZZ return;
3101//ZZ case ARMin_NUnary:
3102//ZZ i->ARMin.NUnary.src = lookupHRegRemap(m, i->ARMin.NUnary.src);
3103//ZZ i->ARMin.NUnary.dst = lookupHRegRemap(m, i->ARMin.NUnary.dst);
3104//ZZ return;
3105//ZZ case ARMin_NUnaryS:
3106//ZZ i->ARMin.NUnaryS.src->reg
3107//ZZ = lookupHRegRemap(m, i->ARMin.NUnaryS.src->reg);
3108//ZZ i->ARMin.NUnaryS.dst->reg
3109//ZZ = lookupHRegRemap(m, i->ARMin.NUnaryS.dst->reg);
3110//ZZ return;
3111//ZZ case ARMin_NShift:
3112//ZZ i->ARMin.NShift.dst = lookupHRegRemap(m, i->ARMin.NShift.dst);
3113//ZZ i->ARMin.NShift.argL = lookupHRegRemap(m, i->ARMin.NShift.argL);
3114//ZZ i->ARMin.NShift.argR = lookupHRegRemap(m, i->ARMin.NShift.argR);
3115//ZZ return;
3116//ZZ case ARMin_NShl64:
3117//ZZ i->ARMin.NShl64.dst = lookupHRegRemap(m, i->ARMin.NShl64.dst);
3118//ZZ i->ARMin.NShl64.src = lookupHRegRemap(m, i->ARMin.NShl64.src);
3119//ZZ return;
3120//ZZ case ARMin_NDual:
3121//ZZ i->ARMin.NDual.arg1 = lookupHRegRemap(m, i->ARMin.NDual.arg1);
3122//ZZ i->ARMin.NDual.arg2 = lookupHRegRemap(m, i->ARMin.NDual.arg2);
3123//ZZ return;
3124 case ARM64in_VImmQ:
3125 i->ARM64in.VImmQ.rQ = lookupHRegRemap(m, i->ARM64in.VImmQ.rQ);
3126 return;
3127 case ARM64in_VDfromX:
3128 i->ARM64in.VDfromX.rD
3129 = lookupHRegRemap(m, i->ARM64in.VDfromX.rD);
3130 i->ARM64in.VDfromX.rX
3131 = lookupHRegRemap(m, i->ARM64in.VDfromX.rX);
3132 return;
3133 case ARM64in_VQfromXX:
3134 i->ARM64in.VQfromXX.rQ
3135 = lookupHRegRemap(m, i->ARM64in.VQfromXX.rQ);
3136 i->ARM64in.VQfromXX.rXhi
3137 = lookupHRegRemap(m, i->ARM64in.VQfromXX.rXhi);
3138 i->ARM64in.VQfromXX.rXlo
3139 = lookupHRegRemap(m, i->ARM64in.VQfromXX.rXlo);
3140 return;
3141 case ARM64in_VXfromQ:
3142 i->ARM64in.VXfromQ.rX
3143 = lookupHRegRemap(m, i->ARM64in.VXfromQ.rX);
3144 i->ARM64in.VXfromQ.rQ
3145 = lookupHRegRemap(m, i->ARM64in.VXfromQ.rQ);
3146 return;
3147 case ARM64in_VMov:
3148 i->ARM64in.VMov.dst = lookupHRegRemap(m, i->ARM64in.VMov.dst);
3149 i->ARM64in.VMov.src = lookupHRegRemap(m, i->ARM64in.VMov.src);
3150 return;
3151
3152//ZZ case ARMin_NBinary:
3153//ZZ i->ARMin.NBinary.argL = lookupHRegRemap(m, i->ARMin.NBinary.argL);
3154//ZZ i->ARMin.NBinary.argR = lookupHRegRemap(m, i->ARMin.NBinary.argR);
3155//ZZ i->ARMin.NBinary.dst = lookupHRegRemap(m, i->ARMin.NBinary.dst);
3156//ZZ return;
3157//ZZ case ARMin_NCMovQ:
3158//ZZ i->ARMin.NCMovQ.dst = lookupHRegRemap(m, i->ARMin.NCMovQ.dst);
3159//ZZ i->ARMin.NCMovQ.src = lookupHRegRemap(m, i->ARMin.NCMovQ.src);
3160//ZZ return;
3161//ZZ case ARMin_Add32:
3162//ZZ i->ARMin.Add32.rD = lookupHRegRemap(m, i->ARMin.Add32.rD);
3163//ZZ i->ARMin.Add32.rN = lookupHRegRemap(m, i->ARMin.Add32.rN);
3164//ZZ return;
3165 case ARM64in_EvCheck:
3166 /* We expect both amodes only to mention x21, so this is in
3167 fact pointless, since x21 isn't allocatable, but
3168 anyway.. */
3169 mapRegs_ARM64AMode(m, i->ARM64in.EvCheck.amCounter);
3170 mapRegs_ARM64AMode(m, i->ARM64in.EvCheck.amFailAddr);
3171 return;
3172//ZZ case ARMin_ProfInc:
3173//ZZ /* hardwires r11 and r12 -- nothing to modify. */
3174//ZZ return;
3175 default:
3176 ppARM64Instr(i);
3177 vpanic("mapRegs_ARM64Instr");
3178 }
3179}
3180
3181/* Figure out if i represents a reg-reg move, and if so assign the
3182 source and destination to *src and *dst. If in doubt say No. Used
3183 by the register allocator to do move coalescing.
3184*/
3185Bool isMove_ARM64Instr ( ARM64Instr* i, HReg* src, HReg* dst )
3186{
3187 switch (i->tag) {
3188 case ARM64in_MovI:
3189 *src = i->ARM64in.MovI.src;
3190 *dst = i->ARM64in.MovI.dst;
3191 return True;
3192 case ARM64in_VMov:
3193 *src = i->ARM64in.VMov.src;
3194 *dst = i->ARM64in.VMov.dst;
3195 return True;
3196 default:
3197 break;
3198 }
3199
3200 return False;
3201}
3202
3203
3204/* Generate arm spill/reload instructions under the direction of the
3205 register allocator. Note it's critical these don't write the
3206 condition codes. */
3207
3208void genSpill_ARM64 ( /*OUT*/HInstr** i1, /*OUT*/HInstr** i2,
3209 HReg rreg, Int offsetB, Bool mode64 )
3210{
3211 HRegClass rclass;
3212 vassert(offsetB >= 0);
3213 vassert(!hregIsVirtual(rreg));
3214 vassert(mode64 == True);
3215 *i1 = *i2 = NULL;
3216 rclass = hregClass(rreg);
3217 switch (rclass) {
3218 case HRcInt64:
3219 vassert(0 == (offsetB & 7));
3220 offsetB >>= 3;
3221 vassert(offsetB < 4096);
3222 *i1 = ARM64Instr_LdSt64(
3223 False/*!isLoad*/,
3224 rreg,
3225 ARM64AMode_RI12(hregARM64_X21(), offsetB, 8)
3226 );
3227 return;
3228 case HRcFlt64:
3229 vassert(0 == (offsetB & 7));
3230 vassert(offsetB >= 0 && offsetB < 32768);
3231 *i1 = ARM64Instr_VLdStD(False/*!isLoad*/,
3232 rreg, hregARM64_X21(), offsetB);
3233 return;
3234 case HRcVec128: {
3235 HReg x21 = hregARM64_X21(); // baseblock
3236 HReg x9 = hregARM64_X9(); // spill temporary
3237 vassert(0 == (offsetB & 15)); // check sane alignment
3238 vassert(offsetB < 4096);
3239 *i1 = ARM64Instr_Arith(x9, x21, ARM64RIA_I12(offsetB, 0), True);
3240 *i2 = ARM64Instr_VLdStQ(False/*!isLoad*/, rreg, x9);
3241 return;
3242 }
3243 default:
3244 ppHRegClass(rclass);
3245 vpanic("genSpill_ARM: unimplemented regclass");
3246 }
3247}
3248
3249void genReload_ARM64 ( /*OUT*/HInstr** i1, /*OUT*/HInstr** i2,
3250 HReg rreg, Int offsetB, Bool mode64 )
3251{
3252 HRegClass rclass;
3253 vassert(offsetB >= 0);
3254 vassert(!hregIsVirtual(rreg));
3255 vassert(mode64 == True);
3256 *i1 = *i2 = NULL;
3257 rclass = hregClass(rreg);
3258 switch (rclass) {
3259 case HRcInt64:
3260 vassert(0 == (offsetB & 7));
3261 offsetB >>= 3;
3262 vassert(offsetB < 4096);
3263 *i1 = ARM64Instr_LdSt64(
3264 True/*isLoad*/,
3265 rreg,
3266 ARM64AMode_RI12(hregARM64_X21(), offsetB, 8)
3267 );
3268 return;
3269 case HRcFlt64:
3270 vassert(0 == (offsetB & 7));
3271 vassert(offsetB >= 0 && offsetB < 32768);
3272 *i1 = ARM64Instr_VLdStD(True/*isLoad*/,
3273 rreg, hregARM64_X21(), offsetB);
3274 return;
3275 case HRcVec128: {
3276 HReg x21 = hregARM64_X21(); // baseblock
3277 HReg x9 = hregARM64_X9(); // spill temporary
3278 vassert(0 == (offsetB & 15)); // check sane alignment
3279 vassert(offsetB < 4096);
3280 *i1 = ARM64Instr_Arith(x9, x21, ARM64RIA_I12(offsetB, 0), True);
3281 *i2 = ARM64Instr_VLdStQ(True/*isLoad*/, rreg, x9);
3282 return;
3283 }
3284 default:
3285 ppHRegClass(rclass);
3286 vpanic("genReload_ARM: unimplemented regclass");
3287 }
3288}
3289
3290
3291//ZZ /* Emit an instruction into buf and return the number of bytes used.
3292//ZZ Note that buf is not the insn's final place, and therefore it is
3293//ZZ imperative to emit position-independent code. */
3294
3295static inline UChar iregNo ( HReg r )
3296{
3297 UInt n;
3298 vassert(hregClass(r) == HRcInt64);
3299 vassert(!hregIsVirtual(r));
3300 n = hregNumber(r);
3301 vassert(n <= 30);
3302 return toUChar(n);
3303}
3304
3305static inline UChar dregNo ( HReg r )
3306{
3307 UInt n;
3308 vassert(hregClass(r) == HRcFlt64);
3309 vassert(!hregIsVirtual(r));
3310 n = hregNumber(r);
3311 vassert(n <= 31);
3312 return toUChar(n);
3313}
3314
3315static inline UChar qregNo ( HReg r )
3316{
3317 UInt n;
3318 vassert(hregClass(r) == HRcVec128);
3319 vassert(!hregIsVirtual(r));
3320 n = hregNumber(r);
3321 vassert(n <= 31);
3322 return toUChar(n);
3323}
3324
3325#define BITS4(zzb3,zzb2,zzb1,zzb0) \
3326 (((zzb3) << 3) | ((zzb2) << 2) | ((zzb1) << 1) | (zzb0))
3327
3328#define X00 BITS4(0,0, 0,0)
3329#define X01 BITS4(0,0, 0,1)
3330#define X10 BITS4(0,0, 1,0)
3331#define X11 BITS4(0,0, 1,1)
3332
3333#define X000 BITS4(0, 0,0,0)
3334#define X001 BITS4(0, 0,0,1)
3335#define X010 BITS4(0, 0,1,0)
3336#define X011 BITS4(0, 0,1,1)
3337#define X100 BITS4(0, 1,0,0)
3338#define X101 BITS4(0, 1,0,1)
3339#define X110 BITS4(0, 1,1,0)
3340#define X111 BITS4(0, 1,1,1)
3341
sewardjbbcf1882014-01-12 12:49:10 +00003342#define X0000 BITS4(0,0,0,0)
3343#define X0001 BITS4(0,0,0,1)
3344#define X0010 BITS4(0,0,1,0)
3345#define X0011 BITS4(0,0,1,1)
3346
sewardj606c4ba2014-01-26 19:11:14 +00003347#define BITS8(zzb7,zzb6,zzb5,zzb4,zzb3,zzb2,zzb1,zzb0) \
3348 ((BITS4(zzb7,zzb6,zzb5,zzb4) << 4) | BITS4(zzb3,zzb2,zzb1,zzb0))
3349
sewardjbbcf1882014-01-12 12:49:10 +00003350#define X00000 BITS8(0,0,0, 0,0,0,0,0)
sewardj606c4ba2014-01-26 19:11:14 +00003351#define X00001 BITS8(0,0,0, 0,0,0,0,1)
sewardjbbcf1882014-01-12 12:49:10 +00003352#define X00111 BITS8(0,0,0, 0,0,1,1,1)
3353#define X01000 BITS8(0,0,0, 0,1,0,0,0)
3354#define X10000 BITS8(0,0,0, 1,0,0,0,0)
3355#define X11000 BITS8(0,0,0, 1,1,0,0,0)
3356#define X11110 BITS8(0,0,0, 1,1,1,1,0)
3357#define X11111 BITS8(0,0,0, 1,1,1,1,1)
3358
3359#define X000000 BITS8(0,0, 0,0,0,0,0,0)
sewardje520bb32014-02-17 11:00:53 +00003360#define X000001 BITS8(0,0, 0,0,0,0,0,1)
sewardjbbcf1882014-01-12 12:49:10 +00003361#define X000100 BITS8(0,0, 0,0,0,1,0,0)
sewardjecde6972014-02-05 11:01:19 +00003362#define X000111 BITS8(0,0, 0,0,0,1,1,1)
sewardjbbcf1882014-01-12 12:49:10 +00003363#define X001000 BITS8(0,0, 0,0,1,0,0,0)
3364#define X001001 BITS8(0,0, 0,0,1,0,0,1)
3365#define X001010 BITS8(0,0, 0,0,1,0,1,0)
sewardj92d0ae32014-04-03 13:48:54 +00003366#define X001101 BITS8(0,0, 0,0,1,1,0,1)
sewardjbbcf1882014-01-12 12:49:10 +00003367#define X001111 BITS8(0,0, 0,0,1,1,1,1)
3368#define X010000 BITS8(0,0, 0,1,0,0,0,0)
3369#define X010001 BITS8(0,0, 0,1,0,0,0,1)
sewardj32d86752014-03-02 12:47:18 +00003370#define X010101 BITS8(0,0, 0,1,0,1,0,1)
sewardje520bb32014-02-17 11:00:53 +00003371#define X010110 BITS8(0,0, 0,1,0,1,1,0)
sewardjecde6972014-02-05 11:01:19 +00003372#define X011001 BITS8(0,0, 0,1,1,0,0,1)
sewardjbbcf1882014-01-12 12:49:10 +00003373#define X011010 BITS8(0,0, 0,1,1,0,1,0)
sewardjecde6972014-02-05 11:01:19 +00003374#define X011011 BITS8(0,0, 0,1,1,0,1,1)
sewardje520bb32014-02-17 11:00:53 +00003375#define X011110 BITS8(0,0, 0,1,1,1,1,0)
sewardjbbcf1882014-01-12 12:49:10 +00003376#define X011111 BITS8(0,0, 0,1,1,1,1,1)
sewardj606c4ba2014-01-26 19:11:14 +00003377#define X100001 BITS8(0,0, 1,0,0,0,0,1)
sewardje520bb32014-02-17 11:00:53 +00003378#define X100011 BITS8(0,0, 1,0,0,0,1,1)
sewardjbbcf1882014-01-12 12:49:10 +00003379#define X100100 BITS8(0,0, 1,0,0,1,0,0)
3380#define X100101 BITS8(0,0, 1,0,0,1,0,1)
3381#define X100110 BITS8(0,0, 1,0,0,1,1,0)
sewardjf5b08912014-02-06 12:57:58 +00003382#define X100111 BITS8(0,0, 1,0,0,1,1,1)
sewardjbbcf1882014-01-12 12:49:10 +00003383#define X110000 BITS8(0,0, 1,1,0,0,0,0)
3384#define X110001 BITS8(0,0, 1,1,0,0,0,1)
sewardj606c4ba2014-01-26 19:11:14 +00003385#define X110101 BITS8(0,0, 1,1,0,1,0,1)
3386#define X110111 BITS8(0,0, 1,1,0,1,1,1)
sewardjbbcf1882014-01-12 12:49:10 +00003387#define X111000 BITS8(0,0, 1,1,1,0,0,0)
3388#define X111001 BITS8(0,0, 1,1,1,0,0,1)
3389#define X111101 BITS8(0,0, 1,1,1,1,0,1)
sewardjfab09142014-02-10 10:28:13 +00003390#define X111110 BITS8(0,0, 1,1,1,1,1,0)
sewardj606c4ba2014-01-26 19:11:14 +00003391#define X111111 BITS8(0,0, 1,1,1,1,1,1)
sewardjbbcf1882014-01-12 12:49:10 +00003392
sewardj93013432014-04-27 12:02:12 +00003393#define X0001000 BITS8(0, 0,0,0,1,0,0,0)
sewardj1eaaec22014-03-07 22:52:19 +00003394#define X0010000 BITS8(0, 0,0,1,0,0,0,0)
sewardj32d86752014-03-02 12:47:18 +00003395#define X0100000 BITS8(0, 0,1,0,0,0,0,0)
sewardje520bb32014-02-17 11:00:53 +00003396#define X1000000 BITS8(0, 1,0,0,0,0,0,0)
3397
sewardjbbcf1882014-01-12 12:49:10 +00003398#define X00100000 BITS8(0,0,1,0,0,0,0,0)
3399#define X00100001 BITS8(0,0,1,0,0,0,0,1)
3400#define X00100010 BITS8(0,0,1,0,0,0,1,0)
3401#define X00100011 BITS8(0,0,1,0,0,0,1,1)
3402#define X01010000 BITS8(0,1,0,1,0,0,0,0)
3403#define X01010001 BITS8(0,1,0,1,0,0,0,1)
3404#define X01010100 BITS8(0,1,0,1,0,1,0,0)
3405#define X01011000 BITS8(0,1,0,1,1,0,0,0)
3406#define X01100000 BITS8(0,1,1,0,0,0,0,0)
3407#define X01100001 BITS8(0,1,1,0,0,0,0,1)
3408#define X01100010 BITS8(0,1,1,0,0,0,1,0)
3409#define X01100011 BITS8(0,1,1,0,0,0,1,1)
3410#define X01110000 BITS8(0,1,1,1,0,0,0,0)
sewardj606c4ba2014-01-26 19:11:14 +00003411#define X01110001 BITS8(0,1,1,1,0,0,0,1)
3412#define X01110011 BITS8(0,1,1,1,0,0,1,1)
3413#define X01110101 BITS8(0,1,1,1,0,1,0,1)
3414#define X01110111 BITS8(0,1,1,1,0,1,1,1)
sewardjbbcf1882014-01-12 12:49:10 +00003415#define X11000001 BITS8(1,1,0,0,0,0,0,1)
3416#define X11000011 BITS8(1,1,0,0,0,0,1,1)
3417#define X11010100 BITS8(1,1,0,1,0,1,0,0)
3418#define X11010110 BITS8(1,1,0,1,0,1,1,0)
3419#define X11011000 BITS8(1,1,0,1,1,0,0,0)
3420#define X11011010 BITS8(1,1,0,1,1,0,1,0)
3421#define X11011110 BITS8(1,1,0,1,1,1,1,0)
3422#define X11110001 BITS8(1,1,1,1,0,0,0,1)
3423#define X11110011 BITS8(1,1,1,1,0,0,1,1)
3424
3425
3426/* --- 4 fields --- */
3427
3428static inline UInt X_8_19_1_4 ( UInt f1, UInt f2, UInt f3, UInt f4 ) {
3429 vassert(8+19+1+4 == 32);
3430 vassert(f1 < (1<<8));
3431 vassert(f2 < (1<<19));
3432 vassert(f3 < (1<<1));
3433 vassert(f4 < (1<<4));
3434 UInt w = 0;
3435 w = (w << 8) | f1;
3436 w = (w << 19) | f2;
3437 w = (w << 1) | f3;
3438 w = (w << 4) | f4;
3439 return w;
3440}
3441
3442/* --- 5 fields --- */
3443
3444static inline UInt X_3_6_2_16_5 ( UInt f1, UInt f2,
3445 UInt f3, UInt f4, UInt f5 ) {
3446 vassert(3+6+2+16+5 == 32);
3447 vassert(f1 < (1<<3));
3448 vassert(f2 < (1<<6));
3449 vassert(f3 < (1<<2));
3450 vassert(f4 < (1<<16));
3451 vassert(f5 < (1<<5));
3452 UInt w = 0;
3453 w = (w << 3) | f1;
3454 w = (w << 6) | f2;
3455 w = (w << 2) | f3;
3456 w = (w << 16) | f4;
3457 w = (w << 5) | f5;
3458 return w;
3459}
3460
3461/* --- 6 fields --- */
3462
3463static inline UInt X_2_6_2_12_5_5 ( UInt f1, UInt f2, UInt f3,
3464 UInt f4, UInt f5, UInt f6 ) {
3465 vassert(2+6+2+12+5+5 == 32);
3466 vassert(f1 < (1<<2));
3467 vassert(f2 < (1<<6));
3468 vassert(f3 < (1<<2));
3469 vassert(f4 < (1<<12));
3470 vassert(f5 < (1<<5));
3471 vassert(f6 < (1<<5));
3472 UInt w = 0;
3473 w = (w << 2) | f1;
3474 w = (w << 6) | f2;
3475 w = (w << 2) | f3;
3476 w = (w << 12) | f4;
3477 w = (w << 5) | f5;
3478 w = (w << 5) | f6;
3479 return w;
3480}
3481
3482static inline UInt X_3_8_5_6_5_5 ( UInt f1, UInt f2, UInt f3,
3483 UInt f4, UInt f5, UInt f6 ) {
3484 vassert(3+8+5+6+5+5 == 32);
3485 vassert(f1 < (1<<3));
3486 vassert(f2 < (1<<8));
3487 vassert(f3 < (1<<5));
3488 vassert(f4 < (1<<6));
3489 vassert(f5 < (1<<5));
3490 vassert(f6 < (1<<5));
3491 UInt w = 0;
3492 w = (w << 3) | f1;
3493 w = (w << 8) | f2;
3494 w = (w << 5) | f3;
3495 w = (w << 6) | f4;
3496 w = (w << 5) | f5;
3497 w = (w << 5) | f6;
3498 return w;
3499}
3500
3501static inline UInt X_3_5_8_6_5_5 ( UInt f1, UInt f2, UInt f3,
3502 UInt f4, UInt f5, UInt f6 ) {
3503 vassert(3+8+5+6+5+5 == 32);
3504 vassert(f1 < (1<<3));
3505 vassert(f2 < (1<<5));
3506 vassert(f3 < (1<<8));
3507 vassert(f4 < (1<<6));
3508 vassert(f5 < (1<<5));
3509 vassert(f6 < (1<<5));
3510 UInt w = 0;
3511 w = (w << 3) | f1;
3512 w = (w << 5) | f2;
3513 w = (w << 8) | f3;
3514 w = (w << 6) | f4;
3515 w = (w << 5) | f5;
3516 w = (w << 5) | f6;
3517 return w;
3518}
3519
sewardje520bb32014-02-17 11:00:53 +00003520static inline UInt X_3_6_7_6_5_5 ( UInt f1, UInt f2, UInt f3,
3521 UInt f4, UInt f5, UInt f6 ) {
3522 vassert(3+6+7+6+5+5 == 32);
3523 vassert(f1 < (1<<3));
3524 vassert(f2 < (1<<6));
3525 vassert(f3 < (1<<7));
3526 vassert(f4 < (1<<6));
3527 vassert(f5 < (1<<5));
3528 vassert(f6 < (1<<5));
3529 UInt w = 0;
3530 w = (w << 3) | f1;
3531 w = (w << 6) | f2;
3532 w = (w << 7) | f3;
3533 w = (w << 6) | f4;
3534 w = (w << 5) | f5;
3535 w = (w << 5) | f6;
3536 return w;
3537}
3538
sewardjbbcf1882014-01-12 12:49:10 +00003539/* --- 7 fields --- */
3540
3541static inline UInt X_2_6_3_9_2_5_5 ( UInt f1, UInt f2, UInt f3,
3542 UInt f4, UInt f5, UInt f6, UInt f7 ) {
3543 vassert(2+6+3+9+2+5+5 == 32);
3544 vassert(f1 < (1<<2));
3545 vassert(f2 < (1<<6));
3546 vassert(f3 < (1<<3));
3547 vassert(f4 < (1<<9));
3548 vassert(f5 < (1<<2));
3549 vassert(f6 < (1<<5));
3550 vassert(f7 < (1<<5));
3551 UInt w = 0;
3552 w = (w << 2) | f1;
3553 w = (w << 6) | f2;
3554 w = (w << 3) | f3;
3555 w = (w << 9) | f4;
3556 w = (w << 2) | f5;
3557 w = (w << 5) | f6;
3558 w = (w << 5) | f7;
3559 return w;
3560}
3561
3562static inline UInt X_3_6_1_6_6_5_5 ( UInt f1, UInt f2, UInt f3,
3563 UInt f4, UInt f5, UInt f6, UInt f7 ) {
3564 vassert(3+6+1+6+6+5+5 == 32);
3565 vassert(f1 < (1<<3));
3566 vassert(f2 < (1<<6));
3567 vassert(f3 < (1<<1));
3568 vassert(f4 < (1<<6));
3569 vassert(f5 < (1<<6));
3570 vassert(f6 < (1<<5));
3571 vassert(f7 < (1<<5));
3572 UInt w = 0;
3573 w = (w << 3) | f1;
3574 w = (w << 6) | f2;
3575 w = (w << 1) | f3;
3576 w = (w << 6) | f4;
3577 w = (w << 6) | f5;
3578 w = (w << 5) | f6;
3579 w = (w << 5) | f7;
3580 return w;
3581}
3582
3583
3584//ZZ #define X0000 BITS4(0,0,0,0)
3585//ZZ #define X0001 BITS4(0,0,0,1)
3586//ZZ #define X0010 BITS4(0,0,1,0)
3587//ZZ #define X0011 BITS4(0,0,1,1)
3588//ZZ #define X0100 BITS4(0,1,0,0)
3589//ZZ #define X0101 BITS4(0,1,0,1)
3590//ZZ #define X0110 BITS4(0,1,1,0)
3591//ZZ #define X0111 BITS4(0,1,1,1)
3592//ZZ #define X1000 BITS4(1,0,0,0)
3593//ZZ #define X1001 BITS4(1,0,0,1)
3594//ZZ #define X1010 BITS4(1,0,1,0)
3595//ZZ #define X1011 BITS4(1,0,1,1)
3596//ZZ #define X1100 BITS4(1,1,0,0)
3597//ZZ #define X1101 BITS4(1,1,0,1)
3598//ZZ #define X1110 BITS4(1,1,1,0)
3599//ZZ #define X1111 BITS4(1,1,1,1)
3600/*
3601#define XXXXX___(zzx7,zzx6,zzx5,zzx4,zzx3) \
3602 ((((zzx7) & 0xF) << 28) | (((zzx6) & 0xF) << 24) | \
3603 (((zzx5) & 0xF) << 20) | (((zzx4) & 0xF) << 16) | \
3604 (((zzx3) & 0xF) << 12))
3605
3606#define XXXXXX__(zzx7,zzx6,zzx5,zzx4,zzx3,zzx2) \
3607 ((((zzx7) & 0xF) << 28) | (((zzx6) & 0xF) << 24) | \
3608 (((zzx5) & 0xF) << 20) | (((zzx4) & 0xF) << 16) | \
3609 (((zzx3) & 0xF) << 12) | (((zzx2) & 0xF) << 8))
3610
3611#define XXXXX__X(zzx7,zzx6,zzx5,zzx4,zzx3,zzx0) \
3612 ((((zzx7) & 0xF) << 28) | (((zzx6) & 0xF) << 24) | \
3613 (((zzx5) & 0xF) << 20) | (((zzx4) & 0xF) << 16) | \
3614 (((zzx3) & 0xF) << 12) | (((zzx0) & 0xF) << 0))
3615
3616#define XXX___XX(zzx7,zzx6,zzx5,zzx1,zzx0) \
3617 ((((zzx7) & 0xF) << 28) | (((zzx6) & 0xF) << 24) | \
3618 (((zzx5) & 0xF) << 20) | (((zzx1) & 0xF) << 4) | \
3619 (((zzx0) & 0xF) << 0))
3620
3621#define XXXXXXXX(zzx7,zzx6,zzx5,zzx4,zzx3,zzx2,zzx1,zzx0) \
3622 ((((zzx7) & 0xF) << 28) | (((zzx6) & 0xF) << 24) | \
3623 (((zzx5) & 0xF) << 20) | (((zzx4) & 0xF) << 16) | \
3624 (((zzx3) & 0xF) << 12) | (((zzx2) & 0xF) << 8) | \
3625 (((zzx1) & 0xF) << 4) | (((zzx0) & 0xF) << 0))
3626
3627#define XX______(zzx7,zzx6) \
3628 ((((zzx7) & 0xF) << 28) | (((zzx6) & 0xF) << 24))
3629*/
3630//ZZ /* Generate a skeletal insn that involves an a RI84 shifter operand.
3631//ZZ Returns a word which is all zeroes apart from bits 25 and 11..0,
3632//ZZ since it is those that encode the shifter operand (at least to the
3633//ZZ extent that we care about it.) */
3634//ZZ static UInt skeletal_RI84 ( ARMRI84* ri )
3635//ZZ {
3636//ZZ UInt instr;
3637//ZZ if (ri->tag == ARMri84_I84) {
3638//ZZ vassert(0 == (ri->ARMri84.I84.imm4 & ~0x0F));
3639//ZZ vassert(0 == (ri->ARMri84.I84.imm8 & ~0xFF));
3640//ZZ instr = 1 << 25;
3641//ZZ instr |= (ri->ARMri84.I84.imm4 << 8);
3642//ZZ instr |= ri->ARMri84.I84.imm8;
3643//ZZ } else {
3644//ZZ instr = 0 << 25;
3645//ZZ instr |= iregNo(ri->ARMri84.R.reg);
3646//ZZ }
3647//ZZ return instr;
3648//ZZ }
3649//ZZ
3650//ZZ /* Ditto for RI5. Resulting word is zeroes apart from bit 4 and bits
3651//ZZ 11..7. */
3652//ZZ static UInt skeletal_RI5 ( ARMRI5* ri )
3653//ZZ {
3654//ZZ UInt instr;
3655//ZZ if (ri->tag == ARMri5_I5) {
3656//ZZ UInt imm5 = ri->ARMri5.I5.imm5;
3657//ZZ vassert(imm5 >= 1 && imm5 <= 31);
3658//ZZ instr = 0 << 4;
3659//ZZ instr |= imm5 << 7;
3660//ZZ } else {
3661//ZZ instr = 1 << 4;
3662//ZZ instr |= iregNo(ri->ARMri5.R.reg) << 8;
3663//ZZ }
3664//ZZ return instr;
3665//ZZ }
3666
3667
3668/* Get an immediate into a register, using only that register. */
3669static UInt* imm64_to_iregNo ( UInt* p, Int xD, ULong imm64 )
3670{
3671 if (imm64 == 0) {
3672 // This has to be special-cased, since the logic below
3673 // will leave the register unchanged in this case.
3674 // MOVZ xD, #0, LSL #0
3675 *p++ = X_3_6_2_16_5(X110, X100101, X00, 0/*imm16*/, xD);
3676 return p;
3677 }
3678
3679 // There must be at least one non-zero halfword. Find the
3680 // lowest nonzero such, and use MOVZ to install it and zero
3681 // out the rest of the register.
3682 UShort h[4];
3683 h[3] = (UShort)((imm64 >> 48) & 0xFFFF);
3684 h[2] = (UShort)((imm64 >> 32) & 0xFFFF);
3685 h[1] = (UShort)((imm64 >> 16) & 0xFFFF);
3686 h[0] = (UShort)((imm64 >> 0) & 0xFFFF);
3687
3688 UInt i;
3689 for (i = 0; i < 4; i++) {
3690 if (h[i] != 0)
3691 break;
3692 }
3693 vassert(i < 4);
3694
3695 // MOVZ xD, h[i], LSL (16*i)
3696 *p++ = X_3_6_2_16_5(X110, X100101, i, h[i], xD);
3697
3698 // Work on upwards through h[i], using MOVK to stuff in any
3699 // remaining nonzero elements.
3700 i++;
3701 for (; i < 4; i++) {
3702 if (h[i] == 0)
3703 continue;
3704 // MOVK xD, h[i], LSL (16*i)
3705 *p++ = X_3_6_2_16_5(X111, X100101, i, h[i], xD);
3706 }
3707
3708 return p;
3709}
3710
3711/* Get an immediate into a register, using only that register, and
3712 generating exactly 4 instructions, regardless of the value of the
3713 immediate. This is used when generating sections of code that need
3714 to be patched later, so as to guarantee a specific size. */
3715static UInt* imm64_to_iregNo_EXACTLY4 ( UInt* p, Int xD, ULong imm64 )
3716{
3717 UShort h[4];
3718 h[3] = (UShort)((imm64 >> 48) & 0xFFFF);
3719 h[2] = (UShort)((imm64 >> 32) & 0xFFFF);
3720 h[1] = (UShort)((imm64 >> 16) & 0xFFFF);
3721 h[0] = (UShort)((imm64 >> 0) & 0xFFFF);
3722 // Work on upwards through h[i], using MOVK to stuff in the
3723 // remaining elements.
3724 UInt i;
3725 for (i = 0; i < 4; i++) {
3726 if (i == 0) {
3727 // MOVZ xD, h[0], LSL (16*0)
3728 *p++ = X_3_6_2_16_5(X110, X100101, i, h[i], xD);
3729 } else {
3730 // MOVK xD, h[i], LSL (16*i)
3731 *p++ = X_3_6_2_16_5(X111, X100101, i, h[i], xD);
3732 }
3733 }
3734 return p;
3735}
3736
3737/* Check whether p points at a 4-insn sequence cooked up by
3738 imm64_to_iregNo_EXACTLY4(). */
3739static Bool is_imm64_to_iregNo_EXACTLY4 ( UInt* p, Int xD, ULong imm64 )
3740{
3741 UShort h[4];
3742 h[3] = (UShort)((imm64 >> 48) & 0xFFFF);
3743 h[2] = (UShort)((imm64 >> 32) & 0xFFFF);
3744 h[1] = (UShort)((imm64 >> 16) & 0xFFFF);
3745 h[0] = (UShort)((imm64 >> 0) & 0xFFFF);
3746 // Work on upwards through h[i], using MOVK to stuff in the
3747 // remaining elements.
3748 UInt i;
3749 for (i = 0; i < 4; i++) {
3750 UInt expected;
3751 if (i == 0) {
3752 // MOVZ xD, h[0], LSL (16*0)
3753 expected = X_3_6_2_16_5(X110, X100101, i, h[i], xD);
3754 } else {
3755 // MOVK xD, h[i], LSL (16*i)
3756 expected = X_3_6_2_16_5(X111, X100101, i, h[i], xD);
3757 }
3758 if (p[i] != expected)
3759 return False;
3760 }
3761 return True;
3762}
3763
3764
3765/* Generate a 8 bit store or 8-to-64 unsigned widening load from/to
3766 rD, using the given amode for the address. */
3767static UInt* do_load_or_store8 ( UInt* p,
3768 Bool isLoad, UInt wD, ARM64AMode* am )
3769{
3770 vassert(wD <= 30);
3771 if (am->tag == ARM64am_RI9) {
3772 /* STURB Wd, [Xn|SP + simm9]: 00 111000 000 simm9 00 n d
3773 LDURB Wd, [Xn|SP + simm9]: 00 111000 010 simm9 00 n d
3774 */
3775 Int simm9 = am->ARM64am.RI9.simm9;
3776 vassert(-256 <= simm9 && simm9 <= 255);
3777 UInt instr = X_2_6_3_9_2_5_5(X00, X111000, isLoad ? X010 : X000,
3778 simm9 & 0x1FF, X00,
3779 iregNo(am->ARM64am.RI9.reg), wD);
3780 *p++ = instr;
3781 return p;
3782 }
3783 if (am->tag == ARM64am_RI12) {
3784 /* STRB Wd, [Xn|SP + uimm12 * 1]: 00 111 001 00 imm12 n d
3785 LDRB Wd, [Xn|SP + uimm12 * 1]: 00 111 001 01 imm12 n d
3786 */
3787 UInt uimm12 = am->ARM64am.RI12.uimm12;
3788 UInt scale = am->ARM64am.RI12.szB;
3789 vassert(scale == 1); /* failure of this is serious. Do not ignore. */
3790 UInt xN = iregNo(am->ARM64am.RI12.reg);
3791 vassert(xN <= 30);
3792 UInt instr = X_2_6_2_12_5_5(X00, X111001, isLoad ? X01 : X00,
3793 uimm12, xN, wD);
3794 *p++ = instr;
3795 return p;
3796 }
3797 if (am->tag == ARM64am_RR) {
3798 /* STRB Xd, [Xn|SP, Xm]: 00 111 000 001 m 011 0 10 n d
3799 LDRB Xd, [Xn|SP, Xm]: 00 111 000 011 m 011 0 10 n d
3800 */
3801 UInt xN = iregNo(am->ARM64am.RR.base);
3802 UInt xM = iregNo(am->ARM64am.RR.index);
3803 vassert(xN <= 30);
3804 UInt instr = X_3_8_5_6_5_5(X001, isLoad ? X11000011 : X11000001,
3805 xM, X011010, xN, wD);
3806 *p++ = instr;
3807 return p;
3808 }
3809 vpanic("do_load_or_store8");
3810 vassert(0);
3811}
3812
3813
3814/* Generate a 16 bit store or 16-to-64 unsigned widening load from/to
3815 rD, using the given amode for the address. */
3816static UInt* do_load_or_store16 ( UInt* p,
3817 Bool isLoad, UInt wD, ARM64AMode* am )
3818{
3819 vassert(wD <= 30);
3820 if (am->tag == ARM64am_RI9) {
3821 /* STURH Wd, [Xn|SP + simm9]: 01 111000 000 simm9 00 n d
3822 LDURH Wd, [Xn|SP + simm9]: 01 111000 010 simm9 00 n d
3823 */
3824 Int simm9 = am->ARM64am.RI9.simm9;
3825 vassert(-256 <= simm9 && simm9 <= 255);
3826 UInt instr = X_2_6_3_9_2_5_5(X01, X111000, isLoad ? X010 : X000,
3827 simm9 & 0x1FF, X00,
3828 iregNo(am->ARM64am.RI9.reg), wD);
3829 *p++ = instr;
3830 return p;
3831 }
3832 if (am->tag == ARM64am_RI12) {
3833 /* STRH Wd, [Xn|SP + uimm12 * 2]: 01 111 001 00 imm12 n d
3834 LDRH Wd, [Xn|SP + uimm12 * 2]: 01 111 001 01 imm12 n d
3835 */
3836 UInt uimm12 = am->ARM64am.RI12.uimm12;
3837 UInt scale = am->ARM64am.RI12.szB;
3838 vassert(scale == 2); /* failure of this is serious. Do not ignore. */
3839 UInt xN = iregNo(am->ARM64am.RI12.reg);
3840 vassert(xN <= 30);
3841 UInt instr = X_2_6_2_12_5_5(X01, X111001, isLoad ? X01 : X00,
3842 uimm12, xN, wD);
3843 *p++ = instr;
3844 return p;
3845 }
3846 if (am->tag == ARM64am_RR) {
3847 /* STRH Xd, [Xn|SP, Xm]: 01 111 000 001 m 011 0 10 n d
3848 LDRH Xd, [Xn|SP, Xm]: 01 111 000 011 m 011 0 10 n d
3849 */
3850 UInt xN = iregNo(am->ARM64am.RR.base);
3851 UInt xM = iregNo(am->ARM64am.RR.index);
3852 vassert(xN <= 30);
3853 UInt instr = X_3_8_5_6_5_5(X011, isLoad ? X11000011 : X11000001,
3854 xM, X011010, xN, wD);
3855 *p++ = instr;
3856 return p;
3857 }
3858 vpanic("do_load_or_store16");
3859 vassert(0);
3860}
3861
3862
3863/* Generate a 32 bit store or 32-to-64 unsigned widening load from/to
3864 rD, using the given amode for the address. */
3865static UInt* do_load_or_store32 ( UInt* p,
3866 Bool isLoad, UInt wD, ARM64AMode* am )
3867{
3868 vassert(wD <= 30);
3869 if (am->tag == ARM64am_RI9) {
3870 /* STUR Wd, [Xn|SP + simm9]: 10 111000 000 simm9 00 n d
3871 LDUR Wd, [Xn|SP + simm9]: 10 111000 010 simm9 00 n d
3872 */
3873 Int simm9 = am->ARM64am.RI9.simm9;
3874 vassert(-256 <= simm9 && simm9 <= 255);
3875 UInt instr = X_2_6_3_9_2_5_5(X10, X111000, isLoad ? X010 : X000,
3876 simm9 & 0x1FF, X00,
3877 iregNo(am->ARM64am.RI9.reg), wD);
3878 *p++ = instr;
3879 return p;
3880 }
3881 if (am->tag == ARM64am_RI12) {
3882 /* STR Wd, [Xn|SP + uimm12 * 4]: 10 111 001 00 imm12 n d
3883 LDR Wd, [Xn|SP + uimm12 * 4]: 10 111 001 01 imm12 n d
3884 */
3885 UInt uimm12 = am->ARM64am.RI12.uimm12;
3886 UInt scale = am->ARM64am.RI12.szB;
3887 vassert(scale == 4); /* failure of this is serious. Do not ignore. */
3888 UInt xN = iregNo(am->ARM64am.RI12.reg);
3889 vassert(xN <= 30);
3890 UInt instr = X_2_6_2_12_5_5(X10, X111001, isLoad ? X01 : X00,
3891 uimm12, xN, wD);
3892 *p++ = instr;
3893 return p;
3894 }
3895 if (am->tag == ARM64am_RR) {
3896 /* STR Wd, [Xn|SP, Xm]: 10 111 000 001 m 011 0 10 n d
3897 LDR Wd, [Xn|SP, Xm]: 10 111 000 011 m 011 0 10 n d
3898 */
3899 UInt xN = iregNo(am->ARM64am.RR.base);
3900 UInt xM = iregNo(am->ARM64am.RR.index);
3901 vassert(xN <= 30);
3902 UInt instr = X_3_8_5_6_5_5(X101, isLoad ? X11000011 : X11000001,
3903 xM, X011010, xN, wD);
3904 *p++ = instr;
3905 return p;
3906 }
3907 vpanic("do_load_or_store32");
3908 vassert(0);
3909}
3910
3911
3912/* Generate a 64 bit load or store to/from xD, using the given amode
3913 for the address. */
3914static UInt* do_load_or_store64 ( UInt* p,
3915 Bool isLoad, UInt xD, ARM64AMode* am )
3916{
3917 /* In all these cases, Rn can't be 31 since that means SP. */
3918 vassert(xD <= 30);
3919 if (am->tag == ARM64am_RI9) {
3920 /* STUR Xd, [Xn|SP + simm9]: 11 111000 000 simm9 00 n d
3921 LDUR Xd, [Xn|SP + simm9]: 11 111000 010 simm9 00 n d
3922 */
3923 Int simm9 = am->ARM64am.RI9.simm9;
3924 vassert(-256 <= simm9 && simm9 <= 255);
3925 UInt xN = iregNo(am->ARM64am.RI9.reg);
3926 vassert(xN <= 30);
3927 UInt instr = X_2_6_3_9_2_5_5(X11, X111000, isLoad ? X010 : X000,
3928 simm9 & 0x1FF, X00, xN, xD);
3929 *p++ = instr;
3930 return p;
3931 }
3932 if (am->tag == ARM64am_RI12) {
3933 /* STR Xd, [Xn|SP + uimm12 * 8]: 11 111 001 00 imm12 n d
3934 LDR Xd, [Xn|SP + uimm12 * 8]: 11 111 001 01 imm12 n d
3935 */
3936 UInt uimm12 = am->ARM64am.RI12.uimm12;
3937 UInt scale = am->ARM64am.RI12.szB;
3938 vassert(scale == 8); /* failure of this is serious. Do not ignore. */
3939 UInt xN = iregNo(am->ARM64am.RI12.reg);
3940 vassert(xN <= 30);
3941 UInt instr = X_2_6_2_12_5_5(X11, X111001, isLoad ? X01 : X00,
3942 uimm12, xN, xD);
3943 *p++ = instr;
3944 return p;
3945 }
3946 if (am->tag == ARM64am_RR) {
3947 /* STR Xd, [Xn|SP, Xm]: 11 111 000 001 m 011 0 10 n d
3948 LDR Xd, [Xn|SP, Xm]: 11 111 000 011 m 011 0 10 n d
3949 */
3950 UInt xN = iregNo(am->ARM64am.RR.base);
3951 UInt xM = iregNo(am->ARM64am.RR.index);
3952 vassert(xN <= 30);
3953 UInt instr = X_3_8_5_6_5_5(X111, isLoad ? X11000011 : X11000001,
3954 xM, X011010, xN, xD);
3955 *p++ = instr;
3956 return p;
3957 }
3958 vpanic("do_load_or_store64");
3959 vassert(0);
3960}
3961
3962
3963/* Emit an instruction into buf and return the number of bytes used.
3964 Note that buf is not the insn's final place, and therefore it is
3965 imperative to emit position-independent code. If the emitted
3966 instruction was a profiler inc, set *is_profInc to True, else
3967 leave it unchanged. */
3968
3969Int emit_ARM64Instr ( /*MB_MOD*/Bool* is_profInc,
3970 UChar* buf, Int nbuf, ARM64Instr* i,
3971 Bool mode64,
3972 void* disp_cp_chain_me_to_slowEP,
3973 void* disp_cp_chain_me_to_fastEP,
3974 void* disp_cp_xindir,
3975 void* disp_cp_xassisted )
3976{
3977 UInt* p = (UInt*)buf;
3978 vassert(nbuf >= 32);
3979 vassert(mode64 == True);
3980 vassert(0 == (((HWord)buf) & 3));
3981
3982 switch (i->tag) {
3983 case ARM64in_Arith: {
3984 UInt rD = iregNo(i->ARM64in.Arith.dst);
3985 UInt rN = iregNo(i->ARM64in.Arith.argL);
3986 ARM64RIA* argR = i->ARM64in.Arith.argR;
3987 switch (argR->tag) {
3988 case ARM64riA_I12:
3989 *p++ = X_2_6_2_12_5_5(
3990 i->ARM64in.Arith.isAdd ? X10 : X11,
3991 X010001,
3992 argR->ARM64riA.I12.shift == 12 ? X01 : X00,
3993 argR->ARM64riA.I12.imm12, rN, rD
3994 );
3995 break;
3996 case ARM64riA_R: {
3997 UInt rM = iregNo(i->ARM64in.Arith.argR->ARM64riA.R.reg);
3998 *p++ = X_3_8_5_6_5_5(
3999 i->ARM64in.Arith.isAdd ? X100 : X110,
4000 X01011000, rM, X000000, rN, rD
4001 );
4002 break;
4003 }
4004 default:
4005 goto bad;
4006 }
4007 goto done;
4008 }
4009 case ARM64in_Cmp: {
4010 UInt rD = 31; /* XZR, we are going to dump the result */
4011 UInt rN = iregNo(i->ARM64in.Cmp.argL);
4012 ARM64RIA* argR = i->ARM64in.Cmp.argR;
4013 Bool is64 = i->ARM64in.Cmp.is64;
4014 switch (argR->tag) {
4015 case ARM64riA_I12:
4016 /* 1 11 10001 sh imm12 Rn Rd = SUBS Xd, Xn, #imm */
4017 /* 0 11 10001 sh imm12 Rn Rd = SUBS Wd, Wn, #imm */
4018 *p++ = X_2_6_2_12_5_5(
4019 is64 ? X11 : X01, X110001,
4020 argR->ARM64riA.I12.shift == 12 ? X01 : X00,
4021 argR->ARM64riA.I12.imm12, rN, rD);
4022 break;
4023 case ARM64riA_R: {
4024 /* 1 11 01011 00 0 Rm 000000 Rn Rd = SUBS Xd, Xn, Xm */
4025 /* 0 11 01011 00 0 Rm 000000 Rn Rd = SUBS Wd, Wn, Wm */
4026 UInt rM = iregNo(i->ARM64in.Cmp.argR->ARM64riA.R.reg);
4027 *p++ = X_3_8_5_6_5_5(is64 ? X111 : X011,
4028 X01011000, rM, X000000, rN, rD);
4029 break;
4030 }
4031 default:
4032 goto bad;
4033 }
4034 goto done;
4035 }
4036 case ARM64in_Logic: {
4037 UInt rD = iregNo(i->ARM64in.Logic.dst);
4038 UInt rN = iregNo(i->ARM64in.Logic.argL);
4039 ARM64RIL* argR = i->ARM64in.Logic.argR;
4040 UInt opc = 0; /* invalid */
4041 vassert(rD < 31);
4042 vassert(rN < 31);
4043 switch (i->ARM64in.Logic.op) {
4044 case ARM64lo_OR: opc = X101; break;
4045 case ARM64lo_AND: opc = X100; break;
4046 case ARM64lo_XOR: opc = X110; break;
4047 default: break;
4048 }
4049 vassert(opc != 0);
4050 switch (argR->tag) {
4051 case ARM64riL_I13: {
4052 /* 1 01 100100 N immR immS Rn Rd = ORR <Xd|Sp>, Xn, #imm */
4053 /* 1 00 100100 N immR immS Rn Rd = AND <Xd|Sp>, Xn, #imm */
4054 /* 1 10 100100 N immR immS Rn Rd = EOR <Xd|Sp>, Xn, #imm */
4055 *p++ = X_3_6_1_6_6_5_5(
4056 opc, X100100, argR->ARM64riL.I13.bitN,
4057 argR->ARM64riL.I13.immR, argR->ARM64riL.I13.immS,
4058 rN, rD
4059 );
4060 break;
4061 }
4062 case ARM64riL_R: {
4063 /* 1 01 01010 00 0 m 000000 n d = ORR Xd, Xn, Xm */
4064 /* 1 00 01010 00 0 m 000000 n d = AND Xd, Xn, Xm */
4065 /* 1 10 01010 00 0 m 000000 n d = EOR Xd, Xn, Xm */
4066 UInt rM = iregNo(argR->ARM64riL.R.reg);
4067 vassert(rM < 31);
4068 *p++ = X_3_8_5_6_5_5(opc, X01010000, rM, X000000, rN, rD);
4069 break;
4070 }
4071 default:
4072 goto bad;
4073 }
4074 goto done;
4075 }
4076 case ARM64in_Test: {
4077 UInt rD = 31; /* XZR, we are going to dump the result */
4078 UInt rN = iregNo(i->ARM64in.Test.argL);
4079 ARM64RIL* argR = i->ARM64in.Test.argR;
4080 switch (argR->tag) {
4081 case ARM64riL_I13: {
4082 /* 1 11 100100 N immR immS Rn Rd = ANDS Xd, Xn, #imm */
4083 *p++ = X_3_6_1_6_6_5_5(
4084 X111, X100100, argR->ARM64riL.I13.bitN,
4085 argR->ARM64riL.I13.immR, argR->ARM64riL.I13.immS,
4086 rN, rD
4087 );
4088 break;
4089 }
4090 default:
4091 goto bad;
4092 }
4093 goto done;
4094 }
4095 case ARM64in_Shift: {
4096 UInt rD = iregNo(i->ARM64in.Shift.dst);
4097 UInt rN = iregNo(i->ARM64in.Shift.argL);
4098 ARM64RI6* argR = i->ARM64in.Shift.argR;
4099 vassert(rD < 31);
4100 vassert(rN < 31);
4101 switch (argR->tag) {
4102 case ARM64ri6_I6: {
4103 /* 110 1001101 (63-sh) (64-sh) nn dd LSL Xd, Xn, sh */
4104 /* 110 1001101 sh 63 nn dd LSR Xd, Xn, sh */
4105 /* 100 1001101 sh 63 nn dd ASR Xd, Xn, sh */
4106 UInt sh = argR->ARM64ri6.I6.imm6;
4107 vassert(sh > 0 && sh < 64);
4108 switch (i->ARM64in.Shift.op) {
4109 case ARM64sh_SHL:
4110 *p++ = X_3_6_1_6_6_5_5(X110, X100110,
4111 1, 64-sh, 63-sh, rN, rD);
4112 break;
4113 case ARM64sh_SHR:
4114 *p++ = X_3_6_1_6_6_5_5(X110, X100110, 1, sh, 63, rN, rD);
4115 break;
4116 case ARM64sh_SAR:
4117 *p++ = X_3_6_1_6_6_5_5(X100, X100110, 1, sh, 63, rN, rD);
4118 break;
4119 default:
4120 vassert(0);
4121 }
4122 break;
4123 }
4124 case ARM64ri6_R: {
4125 /* 100 1101 0110 mm 001000 nn dd LSL Xd, Xn, Xm */
4126 /* 100 1101 0110 mm 001001 nn dd LSR Xd, Xn, Xm */
4127 /* 100 1101 0110 mm 001010 nn dd ASR Xd, Xn, Xm */
4128 UInt rM = iregNo(argR->ARM64ri6.R.reg);
4129 vassert(rM < 31);
4130 UInt subOpc = 0;
4131 switch (i->ARM64in.Shift.op) {
4132 case ARM64sh_SHL: subOpc = X001000; break;
4133 case ARM64sh_SHR: subOpc = X001001; break;
4134 case ARM64sh_SAR: subOpc = X001010; break;
4135 default: vassert(0);
4136 }
4137 *p++ = X_3_8_5_6_5_5(X100, X11010110, rM, subOpc, rN, rD);
4138 break;
4139 }
4140 default:
4141 vassert(0);
4142 }
4143 goto done;
4144 }
4145 case ARM64in_Unary: {
4146 UInt rDst = iregNo(i->ARM64in.Unary.dst);
4147 UInt rSrc = iregNo(i->ARM64in.Unary.src);
4148 switch (i->ARM64in.Unary.op) {
4149 case ARM64un_CLZ:
4150 /* 1 10 1101 0110 00000 00010 0 nn dd CLZ Xd, Xn */
4151 /* 1 10 1101 0110 00000 00010 1 nn dd CLS Xd, Xn (unimp) */
4152 *p++ = X_3_8_5_6_5_5(X110,
4153 X11010110, X00000, X000100, rSrc, rDst);
4154 goto done;
4155 case ARM64un_NEG:
4156 /* 1 10 01011 000 m 000000 11111 d NEG Xd,Xm */
4157 /* 0 10 01011 000 m 000000 11111 d NEG Wd,Wm (unimp) */
4158 *p++ = X_3_8_5_6_5_5(X110,
4159 X01011000, rSrc, X000000, X11111, rDst);
4160 goto done;
4161 case ARM64un_NOT: {
4162 /* 1 01 01010 00 1 m 000000 11111 d MVN Xd,Xm */
4163 *p++ = X_3_8_5_6_5_5(X101,
4164 X01010001, rSrc, X000000, X11111, rDst);
4165 goto done;
4166 }
4167 default:
4168 break;
4169 }
4170 goto bad;
4171 }
4172 case ARM64in_MovI: {
4173 /* We generate the "preferred form", ORR Xd, XZR, Xm
4174 101 01010 00 0 m 000000 11111 d
4175 */
4176 UInt instr = 0xAA0003E0;
4177 UInt d = iregNo(i->ARM64in.MovI.dst);
4178 UInt m = iregNo(i->ARM64in.MovI.src);
4179 *p++ = instr | ((m & 31) << 16) | ((d & 31) << 0);
4180 goto done;
4181 }
4182 case ARM64in_Imm64: {
4183 p = imm64_to_iregNo( p, iregNo(i->ARM64in.Imm64.dst),
4184 i->ARM64in.Imm64.imm64 );
4185 goto done;
4186 }
4187 case ARM64in_LdSt64: {
4188 p = do_load_or_store64( p, i->ARM64in.LdSt64.isLoad,
4189 iregNo(i->ARM64in.LdSt64.rD),
4190 i->ARM64in.LdSt64.amode );
4191 goto done;
4192 }
4193 case ARM64in_LdSt32: {
4194 p = do_load_or_store32( p, i->ARM64in.LdSt32.isLoad,
4195 iregNo(i->ARM64in.LdSt32.rD),
4196 i->ARM64in.LdSt32.amode );
4197 goto done;
4198 }
4199 case ARM64in_LdSt16: {
4200 p = do_load_or_store16( p, i->ARM64in.LdSt16.isLoad,
4201 iregNo(i->ARM64in.LdSt16.rD),
4202 i->ARM64in.LdSt16.amode );
4203 goto done;
4204 }
4205 case ARM64in_LdSt8: {
4206 p = do_load_or_store8( p, i->ARM64in.LdSt8.isLoad,
4207 iregNo(i->ARM64in.LdSt8.rD),
4208 i->ARM64in.LdSt8.amode );
4209 goto done;
4210 }
4211//ZZ case ARMin_LdSt32:
4212//ZZ case ARMin_LdSt8U: {
4213//ZZ UInt bL, bB;
4214//ZZ HReg rD;
4215//ZZ ARMAMode1* am;
4216//ZZ ARMCondCode cc;
4217//ZZ if (i->tag == ARMin_LdSt32) {
4218//ZZ bB = 0;
4219//ZZ bL = i->ARMin.LdSt32.isLoad ? 1 : 0;
4220//ZZ am = i->ARMin.LdSt32.amode;
4221//ZZ rD = i->ARMin.LdSt32.rD;
4222//ZZ cc = i->ARMin.LdSt32.cc;
4223//ZZ } else {
4224//ZZ bB = 1;
4225//ZZ bL = i->ARMin.LdSt8U.isLoad ? 1 : 0;
4226//ZZ am = i->ARMin.LdSt8U.amode;
4227//ZZ rD = i->ARMin.LdSt8U.rD;
4228//ZZ cc = i->ARMin.LdSt8U.cc;
4229//ZZ }
4230//ZZ vassert(cc != ARMcc_NV);
4231//ZZ if (am->tag == ARMam1_RI) {
4232//ZZ Int simm12;
4233//ZZ UInt instr, bP;
4234//ZZ if (am->ARMam1.RI.simm13 < 0) {
4235//ZZ bP = 0;
4236//ZZ simm12 = -am->ARMam1.RI.simm13;
4237//ZZ } else {
4238//ZZ bP = 1;
4239//ZZ simm12 = am->ARMam1.RI.simm13;
4240//ZZ }
4241//ZZ vassert(simm12 >= 0 && simm12 <= 4095);
4242//ZZ instr = XXXXX___(cc,X0101,BITS4(bP,bB,0,bL),
4243//ZZ iregNo(am->ARMam1.RI.reg),
4244//ZZ iregNo(rD));
4245//ZZ instr |= simm12;
4246//ZZ *p++ = instr;
4247//ZZ goto done;
4248//ZZ } else {
4249//ZZ // RR case
4250//ZZ goto bad;
4251//ZZ }
4252//ZZ }
4253//ZZ case ARMin_LdSt16: {
4254//ZZ HReg rD = i->ARMin.LdSt16.rD;
4255//ZZ UInt bS = i->ARMin.LdSt16.signedLoad ? 1 : 0;
4256//ZZ UInt bL = i->ARMin.LdSt16.isLoad ? 1 : 0;
4257//ZZ ARMAMode2* am = i->ARMin.LdSt16.amode;
4258//ZZ ARMCondCode cc = i->ARMin.LdSt16.cc;
4259//ZZ vassert(cc != ARMcc_NV);
4260//ZZ if (am->tag == ARMam2_RI) {
4261//ZZ HReg rN = am->ARMam2.RI.reg;
4262//ZZ Int simm8;
4263//ZZ UInt bP, imm8hi, imm8lo, instr;
4264//ZZ if (am->ARMam2.RI.simm9 < 0) {
4265//ZZ bP = 0;
4266//ZZ simm8 = -am->ARMam2.RI.simm9;
4267//ZZ } else {
4268//ZZ bP = 1;
4269//ZZ simm8 = am->ARMam2.RI.simm9;
4270//ZZ }
4271//ZZ vassert(simm8 >= 0 && simm8 <= 255);
4272//ZZ imm8hi = (simm8 >> 4) & 0xF;
4273//ZZ imm8lo = simm8 & 0xF;
4274//ZZ vassert(!(bL == 0 && bS == 1)); // "! signed store"
4275//ZZ /**/ if (bL == 0 && bS == 0) {
4276//ZZ // strh
4277//ZZ instr = XXXXXXXX(cc,X0001, BITS4(bP,1,0,0), iregNo(rN),
4278//ZZ iregNo(rD), imm8hi, X1011, imm8lo);
4279//ZZ *p++ = instr;
4280//ZZ goto done;
4281//ZZ }
4282//ZZ else if (bL == 1 && bS == 0) {
4283//ZZ // ldrh
4284//ZZ instr = XXXXXXXX(cc,X0001, BITS4(bP,1,0,1), iregNo(rN),
4285//ZZ iregNo(rD), imm8hi, X1011, imm8lo);
4286//ZZ *p++ = instr;
4287//ZZ goto done;
4288//ZZ }
4289//ZZ else if (bL == 1 && bS == 1) {
4290//ZZ // ldrsh
4291//ZZ instr = XXXXXXXX(cc,X0001, BITS4(bP,1,0,1), iregNo(rN),
4292//ZZ iregNo(rD), imm8hi, X1111, imm8lo);
4293//ZZ *p++ = instr;
4294//ZZ goto done;
4295//ZZ }
4296//ZZ else vassert(0); // ill-constructed insn
4297//ZZ } else {
4298//ZZ // RR case
4299//ZZ goto bad;
4300//ZZ }
4301//ZZ }
4302//ZZ case ARMin_Ld8S: {
4303//ZZ HReg rD = i->ARMin.Ld8S.rD;
4304//ZZ ARMAMode2* am = i->ARMin.Ld8S.amode;
4305//ZZ ARMCondCode cc = i->ARMin.Ld8S.cc;
4306//ZZ vassert(cc != ARMcc_NV);
4307//ZZ if (am->tag == ARMam2_RI) {
4308//ZZ HReg rN = am->ARMam2.RI.reg;
4309//ZZ Int simm8;
4310//ZZ UInt bP, imm8hi, imm8lo, instr;
4311//ZZ if (am->ARMam2.RI.simm9 < 0) {
4312//ZZ bP = 0;
4313//ZZ simm8 = -am->ARMam2.RI.simm9;
4314//ZZ } else {
4315//ZZ bP = 1;
4316//ZZ simm8 = am->ARMam2.RI.simm9;
4317//ZZ }
4318//ZZ vassert(simm8 >= 0 && simm8 <= 255);
4319//ZZ imm8hi = (simm8 >> 4) & 0xF;
4320//ZZ imm8lo = simm8 & 0xF;
4321//ZZ // ldrsb
4322//ZZ instr = XXXXXXXX(cc,X0001, BITS4(bP,1,0,1), iregNo(rN),
4323//ZZ iregNo(rD), imm8hi, X1101, imm8lo);
4324//ZZ *p++ = instr;
4325//ZZ goto done;
4326//ZZ } else {
4327//ZZ // RR case
4328//ZZ goto bad;
4329//ZZ }
4330//ZZ }
4331
4332 case ARM64in_XDirect: {
4333 /* NB: what goes on here has to be very closely coordinated
4334 with chainXDirect_ARM64 and unchainXDirect_ARM64 below. */
4335 /* We're generating chain-me requests here, so we need to be
4336 sure this is actually allowed -- no-redir translations
4337 can't use chain-me's. Hence: */
4338 vassert(disp_cp_chain_me_to_slowEP != NULL);
4339 vassert(disp_cp_chain_me_to_fastEP != NULL);
4340
4341 /* Use ptmp for backpatching conditional jumps. */
4342 UInt* ptmp = NULL;
4343
4344 /* First off, if this is conditional, create a conditional
4345 jump over the rest of it. Or at least, leave a space for
4346 it that we will shortly fill in. */
4347 if (i->ARM64in.XDirect.cond != ARM64cc_AL) {
4348 vassert(i->ARM64in.XDirect.cond != ARM64cc_NV);
4349 ptmp = p;
4350 *p++ = 0;
4351 }
4352
4353 /* Update the guest PC. */
4354 /* imm64 x9, dstGA */
4355 /* str x9, amPC */
4356 p = imm64_to_iregNo(p, /*x*/9, i->ARM64in.XDirect.dstGA);
4357 p = do_load_or_store64(p, False/*!isLoad*/,
4358 /*x*/9, i->ARM64in.XDirect.amPC);
4359
4360 /* --- FIRST PATCHABLE BYTE follows --- */
4361 /* VG_(disp_cp_chain_me_to_{slowEP,fastEP}) (where we're
4362 calling to) backs up the return address, so as to find the
4363 address of the first patchable byte. So: don't change the
4364 number of instructions (5) below. */
4365 /* movw x9, VG_(disp_cp_chain_me_to_{slowEP,fastEP})[15:0] */
4366 /* movk x9, VG_(disp_cp_chain_me_to_{slowEP,fastEP})[31:15], lsl 16 */
4367 /* movk x9, VG_(disp_cp_chain_me_to_{slowEP,fastEP})[47:32], lsl 32 */
4368 /* movk x9, VG_(disp_cp_chain_me_to_{slowEP,fastEP})[63:48], lsl 48 */
4369 /* blr x9 */
4370 void* disp_cp_chain_me
4371 = i->ARM64in.XDirect.toFastEP ? disp_cp_chain_me_to_fastEP
4372 : disp_cp_chain_me_to_slowEP;
4373 p = imm64_to_iregNo_EXACTLY4(p, /*x*/9,
4374 Ptr_to_ULong(disp_cp_chain_me));
4375 *p++ = 0xD63F0120;
4376 /* --- END of PATCHABLE BYTES --- */
4377
4378 /* Fix up the conditional jump, if there was one. */
4379 if (i->ARM64in.XDirect.cond != ARM64cc_AL) {
4380 Int delta = (UChar*)p - (UChar*)ptmp; /* must be signed */
4381 vassert(delta > 0 && delta < 40);
4382 vassert((delta & 3) == 0);
4383 UInt notCond = 1 ^ (UInt)i->ARM64in.XDirect.cond;
4384 vassert(notCond <= 13); /* Neither AL nor NV */
4385 vassert(ptmp != NULL);
4386 delta = delta >> 2;
4387 *ptmp = X_8_19_1_4(X01010100, delta & ((1<<19)-1), 0, notCond);
4388 }
4389 goto done;
4390 }
4391
4392 case ARM64in_XIndir: {
4393 // XIndir is more or less the same as XAssisted, except
4394 // we don't have a trc value to hand back, so there's no
4395 // write to r21
4396 /* Use ptmp for backpatching conditional jumps. */
4397 //UInt* ptmp = NULL;
4398
4399 /* First off, if this is conditional, create a conditional
4400 jump over the rest of it. Or at least, leave a space for
4401 it that we will shortly fill in. */
4402 if (i->ARM64in.XIndir.cond != ARM64cc_AL) {
4403 vassert(0); //ATC
4404//ZZ vassert(i->ARMin.XIndir.cond != ARMcc_NV);
4405//ZZ ptmp = p;
4406//ZZ *p++ = 0;
4407 }
4408
4409 /* Update the guest PC. */
4410 /* str r-dstGA, amPC */
4411 p = do_load_or_store64(p, False/*!isLoad*/,
4412 iregNo(i->ARM64in.XIndir.dstGA),
4413 i->ARM64in.XIndir.amPC);
4414
4415 /* imm64 x9, VG_(disp_cp_xindir) */
4416 /* br x9 */
4417 p = imm64_to_iregNo(p, /*x*/9, Ptr_to_ULong(disp_cp_xindir));
4418 *p++ = 0xD61F0120; /* br x9 */
4419
4420 /* Fix up the conditional jump, if there was one. */
4421 if (i->ARM64in.XIndir.cond != ARM64cc_AL) {
4422 vassert(0); //ATC
4423//ZZ Int delta = (UChar*)p - (UChar*)ptmp; /* must be signed */
4424//ZZ vassert(delta > 0 && delta < 40);
4425//ZZ vassert((delta & 3) == 0);
4426//ZZ UInt notCond = 1 ^ (UInt)i->ARMin.XIndir.cond;
4427//ZZ vassert(notCond <= 13); /* Neither AL nor NV */
4428//ZZ delta = (delta >> 2) - 2;
4429//ZZ *ptmp = XX______(notCond, X1010) | (delta & 0xFFFFFF);
4430 }
4431 goto done;
4432 }
4433
4434 case ARM64in_XAssisted: {
4435 /* Use ptmp for backpatching conditional jumps. */
4436 UInt* ptmp = NULL;
4437
4438 /* First off, if this is conditional, create a conditional
4439 jump over the rest of it. Or at least, leave a space for
4440 it that we will shortly fill in. I think this can only
4441 ever happen when VEX is driven by the switchbacker. */
4442 if (i->ARM64in.XAssisted.cond != ARM64cc_AL) {
4443 vassert(i->ARM64in.XDirect.cond != ARM64cc_NV);
4444 ptmp = p;
4445 *p++ = 0;
4446 }
4447
4448 /* Update the guest PC. */
4449 /* str r-dstGA, amPC */
4450 p = do_load_or_store64(p, False/*!isLoad*/,
4451 iregNo(i->ARM64in.XAssisted.dstGA),
4452 i->ARM64in.XAssisted.amPC);
4453
4454 /* movw r21, $magic_number */
4455 UInt trcval = 0;
4456 switch (i->ARM64in.XAssisted.jk) {
4457 case Ijk_ClientReq: trcval = VEX_TRC_JMP_CLIENTREQ; break;
4458 case Ijk_Sys_syscall: trcval = VEX_TRC_JMP_SYS_SYSCALL; break;
4459 //case Ijk_Sys_int128: trcval = VEX_TRC_JMP_SYS_INT128; break;
4460 //case Ijk_Yield: trcval = VEX_TRC_JMP_YIELD; break;
4461 //case Ijk_EmWarn: trcval = VEX_TRC_JMP_EMWARN; break;
4462 //case Ijk_MapFail: trcval = VEX_TRC_JMP_MAPFAIL; break;
4463 case Ijk_NoDecode: trcval = VEX_TRC_JMP_NODECODE; break;
sewardj05f5e012014-05-04 10:52:11 +00004464 case Ijk_InvalICache: trcval = VEX_TRC_JMP_INVALICACHE; break;
sewardj65902992014-05-03 21:20:56 +00004465 case Ijk_FlushDCache: trcval = VEX_TRC_JMP_FLUSHDCACHE; break;
sewardj99c1f812014-03-09 09:41:56 +00004466 case Ijk_NoRedir: trcval = VEX_TRC_JMP_NOREDIR; break;
sewardjbbcf1882014-01-12 12:49:10 +00004467 //case Ijk_SigTRAP: trcval = VEX_TRC_JMP_SIGTRAP; break;
4468 //case Ijk_SigSEGV: trcval = VEX_TRC_JMP_SIGSEGV; break;
4469 case Ijk_Boring: trcval = VEX_TRC_JMP_BORING; break;
4470 /* We don't expect to see the following being assisted. */
4471 //case Ijk_Ret:
4472 //case Ijk_Call:
4473 /* fallthrough */
4474 default:
4475 ppIRJumpKind(i->ARM64in.XAssisted.jk);
4476 vpanic("emit_ARM64Instr.ARM64in_XAssisted: "
4477 "unexpected jump kind");
4478 }
4479 vassert(trcval != 0);
4480 p = imm64_to_iregNo(p, /*x*/21, (ULong)trcval);
4481
4482 /* imm64 x9, VG_(disp_cp_xassisted) */
4483 /* br x9 */
4484 p = imm64_to_iregNo(p, /*x*/9, Ptr_to_ULong(disp_cp_xassisted));
4485 *p++ = 0xD61F0120; /* br x9 */
4486
4487 /* Fix up the conditional jump, if there was one. */
4488 if (i->ARM64in.XAssisted.cond != ARM64cc_AL) {
4489 Int delta = (UChar*)p - (UChar*)ptmp; /* must be signed */
4490 vassert(delta > 0 && delta < 40);
4491 vassert((delta & 3) == 0);
4492 UInt notCond = 1 ^ (UInt)i->ARM64in.XDirect.cond;
4493 vassert(notCond <= 13); /* Neither AL nor NV */
4494 vassert(ptmp != NULL);
4495 delta = delta >> 2;
4496 *ptmp = X_8_19_1_4(X01010100, delta & ((1<<19)-1), 0, notCond);
4497 }
4498 goto done;
4499 }
4500
4501 case ARM64in_CSel: {
4502 /* 100 1101 0100 mm cond 00 nn dd = CSEL Xd, Xn, Xm, cond */
4503 UInt dd = iregNo(i->ARM64in.CSel.dst);
4504 UInt nn = iregNo(i->ARM64in.CSel.argL);
4505 UInt mm = iregNo(i->ARM64in.CSel.argR);
4506 UInt cond = (UInt)i->ARM64in.CSel.cond;
4507 vassert(dd < 31 && nn < 31 && mm < 31 && cond < 16);
4508 *p++ = X_3_8_5_6_5_5(X100, X11010100, mm, cond << 2, nn, dd);
4509 goto done;
4510 }
4511
4512 case ARM64in_Call: {
4513 /* We'll use x9 as a scratch register to put the target
4514 address in. */
4515 if (i->ARM64in.Call.cond != ARM64cc_AL
4516 && i->ARM64in.Call.rloc.pri != RLPri_None) {
4517 /* The call might not happen (it isn't unconditional) and
4518 it returns a result. In this case we will need to
4519 generate a control flow diamond to put 0x555..555 in
4520 the return register(s) in the case where the call
4521 doesn't happen. If this ever becomes necessary, maybe
4522 copy code from the 32-bit ARM equivalent. Until that
4523 day, just give up. */
4524 goto bad;
4525 }
4526
4527 UInt* ptmp = NULL;
4528 if (i->ARM64in.Call.cond != ARM64cc_AL) {
4529 /* Create a hole to put a conditional branch in. We'll
4530 patch it once we know the branch length. */
4531 ptmp = p;
4532 *p++ = 0;
4533 }
4534
4535 // x9 = &target
4536 p = imm64_to_iregNo( (UInt*)p,
4537 /*x*/9, (ULong)i->ARM64in.Call.target );
4538 // blr x9
4539 *p++ = 0xD63F0120;
4540
4541 // Patch the hole if necessary
4542 if (i->ARM64in.Call.cond != ARM64cc_AL) {
4543 ULong dist = (ULong)(p - ptmp);
4544 /* imm64_to_iregNo produces between 1 and 4 insns, and
4545 then there's the BLR itself. Hence: */
4546 vassert(dist >= 2 && dist <= 5);
4547 vassert(ptmp != NULL);
4548 // 01010100 simm19 0 cond = B.cond (here + simm19 << 2)
4549 *ptmp = X_8_19_1_4(X01010100, dist, 0,
4550 1 ^ (UInt)i->ARM64in.Call.cond);
4551 } else {
4552 vassert(ptmp == NULL);
4553 }
4554
4555 goto done;
4556 }
4557
4558 case ARM64in_AddToSP: {
4559 /* 10,0 10001 00 imm12 11111 11111 ADD xsp, xsp, #imm12
4560 11,0 10001 00 imm12 11111 11111 SUB xsp, xsp, #imm12
4561 */
4562 Int simm12 = i->ARM64in.AddToSP.simm;
4563 vassert(-4096 < simm12 && simm12 < 4096);
4564 vassert(0 == (simm12 & 0xF));
4565 if (simm12 >= 0) {
4566 *p++ = X_2_6_2_12_5_5(X10, X010001, X00, simm12, X11111, X11111);
4567 } else {
4568 *p++ = X_2_6_2_12_5_5(X11, X010001, X00, -simm12, X11111, X11111);
4569 }
4570 goto done;
4571 }
4572
4573 case ARM64in_FromSP: {
4574 /* 10,0 10001 00 0..(12)..0 11111 dd MOV Xd, xsp */
4575 UInt dd = iregNo(i->ARM64in.FromSP.dst);
4576 vassert(dd < 31);
4577 *p++ = X_2_6_2_12_5_5(X10, X010001, X00, 0, X11111, dd);
4578 goto done;
4579 }
4580
4581 case ARM64in_Mul: {
4582 /* 100 11011 110 mm 011111 nn dd UMULH Xd, Xn,Xm
4583 100 11011 010 mm 011111 nn dd SMULH Xd, Xn,Xm
4584 100 11011 000 mm 011111 nn dd MUL Xd, Xn,Xm
4585 */
4586 UInt dd = iregNo(i->ARM64in.Mul.dst);
4587 UInt nn = iregNo(i->ARM64in.Mul.argL);
4588 UInt mm = iregNo(i->ARM64in.Mul.argR);
4589 vassert(dd < 31 && nn < 31 && mm < 31);
4590 switch (i->ARM64in.Mul.op) {
4591 case ARM64mul_ZX:
4592 *p++ = X_3_8_5_6_5_5(X100, X11011110, mm, X011111, nn, dd);
4593 goto done;
4594 //case ARM64mul_SX:
4595 // *p++ = X_3_8_5_6_5_5(X100, X11011010, mm, X011111, nn, dd);
4596 // goto done;
4597 case ARM64mul_PLAIN:
4598 *p++ = X_3_8_5_6_5_5(X100, X11011000, mm, X011111, nn, dd);
4599 goto done;
4600 default:
4601 vassert(0);
4602 }
4603 goto bad;
4604 }
sewardj7d009132014-02-20 17:43:38 +00004605 case ARM64in_LdrEX: {
4606 /* 085F7C82 ldxrb w2, [x4]
4607 485F7C82 ldxrh w2, [x4]
4608 885F7C82 ldxr w2, [x4]
4609 C85F7C82 ldxr x2, [x4]
4610 */
4611 switch (i->ARM64in.LdrEX.szB) {
4612 case 1: *p++ = 0x085F7C82; goto done;
4613 case 2: *p++ = 0x485F7C82; goto done;
4614 case 4: *p++ = 0x885F7C82; goto done;
4615 case 8: *p++ = 0xC85F7C82; goto done;
4616 default: break;
4617 }
4618 goto bad;
4619 }
4620 case ARM64in_StrEX: {
4621 /* 08007C82 stxrb w0, w2, [x4]
4622 48007C82 stxrh w0, w2, [x4]
4623 88007C82 stxr w0, w2, [x4]
4624 C8007C82 stxr w0, x2, [x4]
4625 */
4626 switch (i->ARM64in.StrEX.szB) {
4627 case 1: *p++ = 0x08007C82; goto done;
4628 case 2: *p++ = 0x48007C82; goto done;
4629 case 4: *p++ = 0x88007C82; goto done;
4630 case 8: *p++ = 0xC8007C82; goto done;
4631 default: break;
4632 }
4633 goto bad;
4634 }
4635 case ARM64in_MFence: {
4636 *p++ = 0xD5033F9F; /* DSB sy */
4637 *p++ = 0xD5033FBF; /* DMB sy */
4638 *p++ = 0xD5033FDF; /* ISB */
4639 goto done;
4640 }
4641 //case ARM64in_CLREX: {
4642 // //ATC, but believed to be correct
4643 // goto bad;
4644 // *p++ = 0xD5033F5F; /* clrex */
4645 // goto done;
4646 //}
sewardjbbcf1882014-01-12 12:49:10 +00004647 case ARM64in_VLdStS: {
4648 /* 10 111101 01 imm12 n t LDR St, [Xn|SP, #imm12 * 4]
4649 10 111101 00 imm12 n t STR St, [Xn|SP, #imm12 * 4]
4650 */
4651 UInt sD = dregNo(i->ARM64in.VLdStS.sD);
4652 UInt rN = iregNo(i->ARM64in.VLdStS.rN);
4653 UInt uimm12 = i->ARM64in.VLdStS.uimm12;
4654 Bool isLD = i->ARM64in.VLdStS.isLoad;
4655 vassert(uimm12 < 16384 && 0 == (uimm12 & 3));
4656 uimm12 >>= 2;
4657 vassert(uimm12 < (1<<12));
4658 vassert(sD < 32);
4659 vassert(rN < 31);
4660 *p++ = X_2_6_2_12_5_5(X10, X111101, isLD ? X01 : X00,
4661 uimm12, rN, sD);
4662 goto done;
4663 }
4664 case ARM64in_VLdStD: {
4665 /* 11 111101 01 imm12 n t LDR Dt, [Xn|SP, #imm12 * 8]
4666 11 111101 00 imm12 n t STR Dt, [Xn|SP, #imm12 * 8]
4667 */
4668 UInt dD = dregNo(i->ARM64in.VLdStD.dD);
4669 UInt rN = iregNo(i->ARM64in.VLdStD.rN);
4670 UInt uimm12 = i->ARM64in.VLdStD.uimm12;
4671 Bool isLD = i->ARM64in.VLdStD.isLoad;
4672 vassert(uimm12 < 32768 && 0 == (uimm12 & 7));
4673 uimm12 >>= 3;
4674 vassert(uimm12 < (1<<12));
4675 vassert(dD < 32);
4676 vassert(rN < 31);
4677 *p++ = X_2_6_2_12_5_5(X11, X111101, isLD ? X01 : X00,
4678 uimm12, rN, dD);
4679 goto done;
4680 }
4681 case ARM64in_VLdStQ: {
4682 /* 0100 1100 0000 0000 0111 11 rN rQ st1 {vQ.2d}, [<rN|SP>]
4683 0100 1100 0100 0000 0111 11 rN rQ ld1 {vQ.2d}, [<rN|SP>]
4684 */
4685 UInt rQ = qregNo(i->ARM64in.VLdStQ.rQ);
4686 UInt rN = iregNo(i->ARM64in.VLdStQ.rN);
4687 vassert(rQ < 32);
4688 vassert(rN < 31);
4689 if (i->ARM64in.VLdStQ.isLoad) {
4690 *p++ = 0x4C407C00 | (rN << 5) | rQ;
4691 } else {
4692 *p++ = 0x4C007C00 | (rN << 5) | rQ;
4693 }
4694 goto done;
4695 }
4696 case ARM64in_VCvtI2F: {
4697 /* 31 28 23 21 20 18 15 9 4
4698 000 11110 00 1 00 010 000000 n d SCVTF Sd, Wn
4699 000 11110 01 1 00 010 000000 n d SCVTF Dd, Wn
sewardj606c4ba2014-01-26 19:11:14 +00004700 100 11110 00 1 00 010 000000 n d SCVTF Sd, Xn
sewardjbbcf1882014-01-12 12:49:10 +00004701 100 11110 01 1 00 010 000000 n d SCVTF Dd, Xn
4702 000 11110 00 1 00 011 000000 n d UCVTF Sd, Wn
4703 000 11110 01 1 00 011 000000 n d UCVTF Dd, Wn
4704 100 11110 00 1 00 011 000000 n d UCVTF Sd, Xn
4705 100 11110 01 1 00 011 000000 n d UCVTF Dd, Xn
4706 */
4707 UInt rN = iregNo(i->ARM64in.VCvtI2F.rS);
4708 UInt rD = dregNo(i->ARM64in.VCvtI2F.rD);
4709 ARM64CvtOp how = i->ARM64in.VCvtI2F.how;
4710 /* Just handle cases as they show up. */
4711 switch (how) {
4712 case ARM64cvt_F32_I32S: /* SCVTF Sd, Wn */
4713 *p++ = X_3_5_8_6_5_5(X000, X11110, X00100010, X000000, rN, rD);
4714 break;
4715 case ARM64cvt_F64_I32S: /* SCVTF Dd, Wn */
4716 *p++ = X_3_5_8_6_5_5(X000, X11110, X01100010, X000000, rN, rD);
4717 break;
4718 case ARM64cvt_F32_I64S: /* SCVTF Sd, Xn */
4719 *p++ = X_3_5_8_6_5_5(X100, X11110, X00100010, X000000, rN, rD);
4720 break;
4721 case ARM64cvt_F64_I64S: /* SCVTF Dd, Xn */
4722 *p++ = X_3_5_8_6_5_5(X100, X11110, X01100010, X000000, rN, rD);
4723 break;
sewardj1eaaec22014-03-07 22:52:19 +00004724 case ARM64cvt_F32_I32U: /* UCVTF Sd, Wn */
4725 *p++ = X_3_5_8_6_5_5(X000, X11110, X00100011, X000000, rN, rD);
4726 break;
sewardjbbcf1882014-01-12 12:49:10 +00004727 case ARM64cvt_F64_I32U: /* UCVTF Dd, Wn */
4728 *p++ = X_3_5_8_6_5_5(X000, X11110, X01100011, X000000, rN, rD);
4729 break;
4730 case ARM64cvt_F32_I64U: /* UCVTF Sd, Xn */
4731 *p++ = X_3_5_8_6_5_5(X100, X11110, X00100011, X000000, rN, rD);
4732 break;
4733 case ARM64cvt_F64_I64U: /* UCVTF Dd, Xn */
4734 *p++ = X_3_5_8_6_5_5(X100, X11110, X01100011, X000000, rN, rD);
4735 break;
4736 default:
4737 goto bad; //ATC
4738 }
4739 goto done;
4740 }
4741 case ARM64in_VCvtF2I: {
4742 /* 30 23 20 18 15 9 4
4743 sf 00,11110,0x 1 00 000,000000 n d FCVTNS Rd, Fn (round to
4744 sf 00,11110,0x 1 00 001,000000 n d FCVTNU Rd, Fn nearest)
4745 ---------------- 01 -------------- FCVTP-------- (round to +inf)
4746 ---------------- 10 -------------- FCVTM-------- (round to -inf)
4747 ---------------- 11 -------------- FCVTZ-------- (round to zero)
4748
4749 Rd is Xd when sf==1, Wd when sf==0
4750 Fn is Dn when x==1, Sn when x==0
4751 20:19 carry the rounding mode, using the same encoding as FPCR
4752 */
4753 UInt rD = iregNo(i->ARM64in.VCvtF2I.rD);
4754 UInt rN = dregNo(i->ARM64in.VCvtF2I.rS);
4755 ARM64CvtOp how = i->ARM64in.VCvtF2I.how;
4756 UChar armRM = i->ARM64in.VCvtF2I.armRM;
4757 /* Just handle cases as they show up. */
4758 switch (how) {
4759 case ARM64cvt_F64_I32S: /* FCVTxS Wd, Dn */
4760 *p++ = X_3_5_8_6_5_5(X000, X11110, X01100000 | (armRM << 3),
4761 X000000, rN, rD);
4762 break;
4763 case ARM64cvt_F64_I32U: /* FCVTxU Wd, Dn */
4764 *p++ = X_3_5_8_6_5_5(X000, X11110, X01100001 | (armRM << 3),
4765 X000000, rN, rD);
4766 break;
4767 case ARM64cvt_F64_I64S: /* FCVTxS Xd, Dn */
4768 *p++ = X_3_5_8_6_5_5(X100, X11110, X01100000 | (armRM << 3),
4769 X000000, rN, rD);
4770 break;
4771 case ARM64cvt_F64_I64U: /* FCVTxU Xd, Dn */
4772 *p++ = X_3_5_8_6_5_5(X100, X11110, X01100001 | (armRM << 3),
4773 X000000, rN, rD);
4774 break;
sewardjbbcf1882014-01-12 12:49:10 +00004775 case ARM64cvt_F32_I32S: /* FCVTxS Wd, Sn */
4776 *p++ = X_3_5_8_6_5_5(X000, X11110, X00100000 | (armRM << 3),
4777 X000000, rN, rD);
4778 break;
sewardj1eaaec22014-03-07 22:52:19 +00004779 case ARM64cvt_F32_I32U: /* FCVTxU Wd, Sn */
4780 *p++ = X_3_5_8_6_5_5(X000, X11110, X00100001 | (armRM << 3),
4781 X000000, rN, rD);
4782 break;
4783 case ARM64cvt_F32_I64S: /* FCVTxS Xd, Sn */
4784 *p++ = X_3_5_8_6_5_5(X100, X11110, X00100000 | (armRM << 3),
4785 X000000, rN, rD);
4786 break;
sewardjbbcf1882014-01-12 12:49:10 +00004787 case ARM64cvt_F32_I64U: /* FCVTxU Xd, Sn */
4788 *p++ = X_3_5_8_6_5_5(X100, X11110, X00100001 | (armRM << 3),
4789 X000000, rN, rD);
4790 break;
4791 default:
4792 goto bad; //ATC
4793 }
4794 goto done;
4795 }
4796 case ARM64in_VCvtSD: {
4797 /* 31 23 21 16 14 9 4
4798 000,11110, 00 10001 0,1 10000 n d FCVT Dd, Sn (S->D)
4799 ---------- 01 ----- 0,0 --------- FCVT Sd, Dn (D->S)
4800 Rounding, when dst is smaller than src, is per the FPCR.
4801 */
4802 UInt dd = dregNo(i->ARM64in.VCvtSD.dst);
4803 UInt nn = dregNo(i->ARM64in.VCvtSD.src);
4804 if (i->ARM64in.VCvtSD.sToD) {
4805 *p++ = X_3_5_8_6_5_5(X000, X11110, X00100010, X110000, nn, dd);
4806 } else {
4807 *p++ = X_3_5_8_6_5_5(X000, X11110, X01100010, X010000, nn, dd);
4808 }
4809 goto done;
4810 }
sewardjbbcf1882014-01-12 12:49:10 +00004811 case ARM64in_VUnaryD: {
4812 /* 31 23 21 16 14 9 4
4813 000,11110 01 1,0000 0,0 10000 n d FMOV Dd, Dn (not handled)
4814 ------------------- 0,1 --------- FABS ------
4815 ------------------- 1,0 --------- FNEG ------
4816 ------------------- 1,1 --------- FQSRT -----
4817 */
4818 UInt dD = dregNo(i->ARM64in.VUnaryD.dst);
4819 UInt dN = dregNo(i->ARM64in.VUnaryD.src);
4820 UInt b16 = 2; /* impossible */
4821 UInt b15 = 2; /* impossible */
4822 switch (i->ARM64in.VUnaryD.op) {
4823 case ARM64fpu_NEG: b16 = 1; b15 = 0; break;
4824 case ARM64fpu_SQRT: b16 = 1; b15 = 1; break;
4825 case ARM64fpu_ABS: b16 = 0; b15 = 1; break;
4826 default: break;
4827 }
4828 if (b16 < 2 && b15 < 2) {
4829 *p++ = X_3_8_5_6_5_5(X000, X11110011, (X0000 << 1) | b16,
4830 (b15 << 5) | X10000, dN, dD);
4831 goto done;
4832 }
4833 /*
4834 000, 11110 01 1,001 11,1 10000 n d FRINTI Dd, Dm (round per FPCR)
4835 */
4836 if (i->ARM64in.VUnaryD.op == ARM64fpu_RINT) {
4837 *p++ = X_3_8_5_6_5_5(X000, X11110011, X00111, X110000, dN, dD);
4838 goto done;
4839 }
4840 goto bad;
4841 }
4842 case ARM64in_VUnaryS: {
4843 /* 31 23 21 16 14 9 4
4844 000,11110 00 1,0000 0,0 10000 n d FMOV Sd, Sn (not handled)
4845 ------------------- 0,1 --------- FABS ------
4846 ------------------- 1,0 --------- FNEG ------
4847 ------------------- 1,1 --------- FQSRT -----
4848 */
4849 UInt sD = dregNo(i->ARM64in.VUnaryS.dst);
4850 UInt sN = dregNo(i->ARM64in.VUnaryS.src);
4851 UInt b16 = 2; /* impossible */
4852 UInt b15 = 2; /* impossible */
4853 switch (i->ARM64in.VUnaryS.op) {
4854 case ARM64fpu_NEG: b16 = 1; b15 = 0; break;
4855 case ARM64fpu_SQRT: b16 = 1; b15 = 1; break;
4856 case ARM64fpu_ABS: b16 = 0; b15 = 1; break;
4857 default: break;
4858 }
4859 if (b16 < 2 && b15 < 2) {
4860 *p++ = X_3_8_5_6_5_5(X000, X11110001, (X0000 << 1) | b16,
4861 (b15 << 5) | X10000, sN, sD);
4862 goto done;
4863 }
4864 /*
4865 000, 11110 00 1,001 11,1 10000 n d FRINTI Sd, Sm (round per FPCR)
4866 */
4867 if (i->ARM64in.VUnaryS.op == ARM64fpu_RINT) {
4868 *p++ = X_3_8_5_6_5_5(X000, X11110001, X00111, X110000, sN, sD);
4869 goto done;
4870 }
4871 goto bad;
4872 }
4873 case ARM64in_VBinD: {
4874 /* 31 23 20 15 11 9 4
4875 ---------------- 0000 ------ FMUL --------
4876 000 11110 011 m 0001 10 n d FDIV Dd,Dn,Dm
4877 ---------------- 0010 ------ FADD --------
4878 ---------------- 0011 ------ FSUB --------
4879 */
4880 UInt dD = dregNo(i->ARM64in.VBinD.dst);
4881 UInt dN = dregNo(i->ARM64in.VBinD.argL);
4882 UInt dM = dregNo(i->ARM64in.VBinD.argR);
4883 UInt b1512 = 16; /* impossible */
4884 switch (i->ARM64in.VBinD.op) {
4885 case ARM64fpb_DIV: b1512 = X0001; break;
4886 case ARM64fpb_MUL: b1512 = X0000; break;
4887 case ARM64fpb_SUB: b1512 = X0011; break;
4888 case ARM64fpb_ADD: b1512 = X0010; break;
4889 default: goto bad;
4890 }
4891 vassert(b1512 < 16);
4892 *p++
4893 = X_3_8_5_6_5_5(X000, X11110011, dM, (b1512 << 2) | X10, dN, dD);
4894 goto done;
4895 }
4896 case ARM64in_VBinS: {
4897 /* 31 23 20 15 11 9 4
4898 ---------------- 0000 ------ FMUL --------
4899 000 11110 001 m 0001 10 n d FDIV Dd,Dn,Dm
4900 ---------------- 0010 ------ FADD --------
4901 ---------------- 0011 ------ FSUB --------
4902 */
4903 UInt sD = dregNo(i->ARM64in.VBinS.dst);
4904 UInt sN = dregNo(i->ARM64in.VBinS.argL);
4905 UInt sM = dregNo(i->ARM64in.VBinS.argR);
4906 UInt b1512 = 16; /* impossible */
4907 switch (i->ARM64in.VBinS.op) {
4908 case ARM64fpb_DIV: b1512 = X0001; break;
4909 case ARM64fpb_MUL: b1512 = X0000; break;
4910 case ARM64fpb_SUB: b1512 = X0011; break;
4911 case ARM64fpb_ADD: b1512 = X0010; break;
4912 default: goto bad;
4913 }
4914 vassert(b1512 < 16);
4915 *p++
4916 = X_3_8_5_6_5_5(X000, X11110001, sM, (b1512 << 2) | X10, sN, sD);
4917 goto done;
4918 }
4919 case ARM64in_VCmpD: {
4920 /* 000 11110 01 1 m 00 1000 n 00 000 FCMP Dn, Dm */
4921 UInt dN = dregNo(i->ARM64in.VCmpD.argL);
4922 UInt dM = dregNo(i->ARM64in.VCmpD.argR);
4923 *p++ = X_3_8_5_6_5_5(X000, X11110011, dM, X001000, dN, X00000);
4924 goto done;
4925 }
4926 case ARM64in_VCmpS: {
4927 /* 000 11110 00 1 m 00 1000 n 00 000 FCMP Sn, Sm */
4928 UInt sN = dregNo(i->ARM64in.VCmpS.argL);
4929 UInt sM = dregNo(i->ARM64in.VCmpS.argR);
4930 *p++ = X_3_8_5_6_5_5(X000, X11110001, sM, X001000, sN, X00000);
4931 goto done;
4932 }
sewardj606c4ba2014-01-26 19:11:14 +00004933 case ARM64in_FPCR: {
4934 Bool toFPCR = i->ARM64in.FPCR.toFPCR;
4935 UInt iReg = iregNo(i->ARM64in.FPCR.iReg);
4936 if (toFPCR) {
4937 /* 0xD51B44 000 Rt MSR fpcr, rT */
4938 *p++ = 0xD51B4400 | (iReg & 0x1F);
4939 goto done;
4940 }
4941 goto bad; // FPCR -> iReg case currently ATC
4942 }
4943 case ARM64in_VBinV: {
4944 /* 31 23 20 15 9 4
sewardj93013432014-04-27 12:02:12 +00004945 010 01110 11 1 m 100001 n d ADD Vd.2d, Vn.2d, Vm.2d
4946 010 01110 10 1 m 100001 n d ADD Vd.4s, Vn.4s, Vm.4s
4947 010 01110 01 1 m 100001 n d ADD Vd.8h, Vn.8h, Vm.8h
sewardj92d0ae32014-04-03 13:48:54 +00004948 010 01110 00 1 m 100001 n d ADD Vd.16b, Vn.16b, Vm.16b
sewardjf5b08912014-02-06 12:57:58 +00004949
sewardj93013432014-04-27 12:02:12 +00004950 011 01110 11 1 m 100001 n d SUB Vd.2d, Vn.2d, Vm.2d
4951 011 01110 10 1 m 100001 n d SUB Vd.4s, Vn.4s, Vm.4s
4952 011 01110 01 1 m 100001 n d SUB Vd.8h, Vn.8h, Vm.8h
sewardj92d0ae32014-04-03 13:48:54 +00004953 011 01110 00 1 m 100001 n d SUB Vd.16b, Vn.16b, Vm.16b
sewardjf5b08912014-02-06 12:57:58 +00004954
sewardj93013432014-04-27 12:02:12 +00004955 010 01110 10 1 m 100111 n d MUL Vd.4s, Vn.4s, Vm.4s
4956 010 01110 01 1 m 100111 n d MUL Vd.8h, Vn.8h, Vm.8h
4957 010 01110 00 1 m 100111 n d MUL Vd.16b, Vn.16b, Vm.16b
sewardjf5b08912014-02-06 12:57:58 +00004958
sewardj606c4ba2014-01-26 19:11:14 +00004959 010 01110 01 1 m 110101 n d FADD Vd.2d, Vn.2d, Vm.2d
sewardjecde6972014-02-05 11:01:19 +00004960 010 01110 00 1 m 110101 n d FADD Vd.4s, Vn.4s, Vm.4s
sewardj606c4ba2014-01-26 19:11:14 +00004961 010 01110 11 1 m 110101 n d FSUB Vd.2d, Vn.2d, Vm.2d
sewardjecde6972014-02-05 11:01:19 +00004962 010 01110 10 1 m 110101 n d FSUB Vd.4s, Vn.4s, Vm.4s
sewardjf5b08912014-02-06 12:57:58 +00004963
sewardj606c4ba2014-01-26 19:11:14 +00004964 011 01110 01 1 m 110111 n d FMUL Vd.2d, Vn.2d, Vm.2d
sewardjecde6972014-02-05 11:01:19 +00004965 011 01110 00 1 m 110111 n d FMUL Vd.4s, Vn.4s, Vm.4s
sewardj606c4ba2014-01-26 19:11:14 +00004966 011 01110 01 1 m 111111 n d FDIV Vd.2d, Vn.2d, Vm.2d
sewardjecde6972014-02-05 11:01:19 +00004967 011 01110 00 1 m 111111 n d FDIV Vd.4s, Vn.4s, Vm.4s
sewardjf5b08912014-02-06 12:57:58 +00004968
sewardjfab09142014-02-10 10:28:13 +00004969 011 01110 10 1 m 011001 n d UMAX Vd.4s, Vn.4s, Vm.4s
4970 011 01110 01 1 m 011001 n d UMAX Vd.8h, Vn.8h, Vm.8h
4971 011 01110 00 1 m 011001 n d UMAX Vd.16b, Vn.16b, Vm.16b
4972
4973 011 01110 10 1 m 011011 n d UMIN Vd.4s, Vn.4s, Vm.4s
4974 011 01110 01 1 m 011011 n d UMIN Vd.8h, Vn.8h, Vm.8h
4975 011 01110 00 1 m 011011 n d UMIN Vd.16b, Vn.16b, Vm.16b
sewardjf5b08912014-02-06 12:57:58 +00004976
sewardj9b1cf5e2014-03-01 11:16:57 +00004977 010 01110 10 1 m 011001 n d SMAX Vd.4s, Vn.4s, Vm.4s
4978 010 01110 01 1 m 011001 n d SMAX Vd.8h, Vn.8h, Vm.8h
4979 010 01110 00 1 m 011001 n d SMAX Vd.16b, Vn.16b, Vm.16b
sewardjfab09142014-02-10 10:28:13 +00004980
sewardj9b1cf5e2014-03-01 11:16:57 +00004981 010 01110 10 1 m 011011 n d SMIN Vd.4s, Vn.4s, Vm.4s
4982 010 01110 01 1 m 011011 n d SMIN Vd.8h, Vn.8h, Vm.8h
4983 010 01110 00 1 m 011011 n d SMIN Vd.16b, Vn.16b, Vm.16b
sewardjf5b08912014-02-06 12:57:58 +00004984
sewardjecde6972014-02-05 11:01:19 +00004985 010 01110 00 1 m 000111 n d AND Vd, Vn, Vm
4986 010 01110 10 1 m 000111 n d ORR Vd, Vn, Vm
sewardje520bb32014-02-17 11:00:53 +00004987 011 01110 00 1 m 000111 n d EOR Vd, Vn, Vm
4988
sewardj505a27d2014-03-10 10:40:48 +00004989 011 01110 11 1 m 100011 n d CMEQ Vd.2d, Vn.2d, Vm.2d
4990 011 01110 10 1 m 100011 n d CMEQ Vd.4s, Vn.4s, Vm.4s
4991 011 01110 01 1 m 100011 n d CMEQ Vd.8h, Vn.8h, Vm.8h
4992 011 01110 00 1 m 100011 n d CMEQ Vd.16b, Vn.16b, Vm.16b
4993
sewardj93013432014-04-27 12:02:12 +00004994 011 01110 11 1 m 001101 n d CMHI Vd.2d, Vn.2d, Vm.2d
4995 011 01110 10 1 m 001101 n d CMHI Vd.4s, Vn.4s, Vm.4s
4996 011 01110 01 1 m 001101 n d CMHI Vd.8h, Vn.8h, Vm.8h
4997 011 01110 00 1 m 001101 n d CMHI Vd.16b, Vn.16b, Vm.16b
4998
4999 010 01110 11 1 m 001101 n d CMGT Vd.2d, Vn.2d, Vm.2d
5000 010 01110 10 1 m 001101 n d CMGT Vd.4s, Vn.4s, Vm.4s
5001 010 01110 01 1 m 001101 n d CMGT Vd.8h, Vn.8h, Vm.8h
5002 010 01110 00 1 m 001101 n d CMGT Vd.16b, Vn.16b, Vm.16b
sewardj2bd1ffe2014-03-27 18:59:00 +00005003
5004 010 01110 01 1 m 111001 n d FCMEQ Vd.2d, Vn.2d, Vm.2d
5005 010 01110 00 1 m 111001 n d FCMEQ Vd.4s, Vn.4s, Vm.4s
5006
5007 011 01110 01 1 m 111001 n d FCMGE Vd.2d, Vn.2d, Vm.2d
5008 011 01110 00 1 m 111001 n d FCMGE Vd.4s, Vn.4s, Vm.4s
5009
5010 011 01110 11 1 m 111001 n d FCMGT Vd.2d, Vn.2d, Vm.2d
5011 011 01110 10 1 m 111001 n d FCMGT Vd.4s, Vn.4s, Vm.4s
sewardj92d0ae32014-04-03 13:48:54 +00005012
5013 010 01110 00 0 m 000000 n d TBL Vd.16b, {Vn.16b}, Vm.16b
5014
sewardj606c4ba2014-01-26 19:11:14 +00005015 */
5016 UInt vD = qregNo(i->ARM64in.VBinV.dst);
5017 UInt vN = qregNo(i->ARM64in.VBinV.argL);
5018 UInt vM = qregNo(i->ARM64in.VBinV.argR);
5019 switch (i->ARM64in.VBinV.op) {
5020 case ARM64vecb_ADD64x2:
5021 *p++ = X_3_8_5_6_5_5(X010, X01110111, vM, X100001, vN, vD);
5022 break;
sewardjf5b08912014-02-06 12:57:58 +00005023 case ARM64vecb_ADD32x4:
5024 *p++ = X_3_8_5_6_5_5(X010, X01110101, vM, X100001, vN, vD);
5025 break;
5026 case ARM64vecb_ADD16x8:
5027 *p++ = X_3_8_5_6_5_5(X010, X01110011, vM, X100001, vN, vD);
5028 break;
sewardj92d0ae32014-04-03 13:48:54 +00005029 case ARM64vecb_ADD8x16:
5030 *p++ = X_3_8_5_6_5_5(X010, X01110001, vM, X100001, vN, vD);
5031 break;
sewardj606c4ba2014-01-26 19:11:14 +00005032 case ARM64vecb_SUB64x2:
5033 *p++ = X_3_8_5_6_5_5(X011, X01110111, vM, X100001, vN, vD);
5034 break;
5035 case ARM64vecb_SUB32x4:
5036 *p++ = X_3_8_5_6_5_5(X011, X01110101, vM, X100001, vN, vD);
5037 break;
5038 case ARM64vecb_SUB16x8:
5039 *p++ = X_3_8_5_6_5_5(X011, X01110011, vM, X100001, vN, vD);
5040 break;
sewardj92d0ae32014-04-03 13:48:54 +00005041 case ARM64vecb_SUB8x16:
5042 *p++ = X_3_8_5_6_5_5(X011, X01110001, vM, X100001, vN, vD);
5043 break;
sewardjf5b08912014-02-06 12:57:58 +00005044 case ARM64vecb_MUL32x4:
5045 *p++ = X_3_8_5_6_5_5(X010, X01110101, vM, X100111, vN, vD);
5046 break;
5047 case ARM64vecb_MUL16x8:
5048 *p++ = X_3_8_5_6_5_5(X010, X01110011, vM, X100111, vN, vD);
5049 break;
sewardj93013432014-04-27 12:02:12 +00005050 case ARM64vecb_MUL8x16:
5051 *p++ = X_3_8_5_6_5_5(X010, X01110001, vM, X100111, vN, vD);
5052 break;
sewardj606c4ba2014-01-26 19:11:14 +00005053 case ARM64vecb_FADD64x2:
5054 *p++ = X_3_8_5_6_5_5(X010, X01110011, vM, X110101, vN, vD);
5055 break;
sewardjecde6972014-02-05 11:01:19 +00005056 case ARM64vecb_FADD32x4:
5057 *p++ = X_3_8_5_6_5_5(X010, X01110001, vM, X110101, vN, vD);
5058 break;
sewardj606c4ba2014-01-26 19:11:14 +00005059 case ARM64vecb_FSUB64x2:
5060 *p++ = X_3_8_5_6_5_5(X010, X01110111, vM, X110101, vN, vD);
5061 break;
sewardjecde6972014-02-05 11:01:19 +00005062 case ARM64vecb_FSUB32x4:
5063 *p++ = X_3_8_5_6_5_5(X010, X01110101, vM, X110101, vN, vD);
5064 break;
sewardj606c4ba2014-01-26 19:11:14 +00005065 case ARM64vecb_FMUL64x2:
5066 *p++ = X_3_8_5_6_5_5(X011, X01110011, vM, X110111, vN, vD);
5067 break;
sewardjecde6972014-02-05 11:01:19 +00005068 case ARM64vecb_FMUL32x4:
5069 *p++ = X_3_8_5_6_5_5(X011, X01110001, vM, X110111, vN, vD);
5070 break;
sewardj606c4ba2014-01-26 19:11:14 +00005071 case ARM64vecb_FDIV64x2:
5072 *p++ = X_3_8_5_6_5_5(X011, X01110011, vM, X111111, vN, vD);
5073 break;
sewardjecde6972014-02-05 11:01:19 +00005074 case ARM64vecb_FDIV32x4:
5075 *p++ = X_3_8_5_6_5_5(X011, X01110001, vM, X111111, vN, vD);
5076 break;
sewardjf5b08912014-02-06 12:57:58 +00005077
sewardjecde6972014-02-05 11:01:19 +00005078 case ARM64vecb_UMAX32x4:
5079 *p++ = X_3_8_5_6_5_5(X011, X01110101, vM, X011001, vN, vD);
5080 break;
5081 case ARM64vecb_UMAX16x8:
5082 *p++ = X_3_8_5_6_5_5(X011, X01110011, vM, X011001, vN, vD);
5083 break;
sewardjfab09142014-02-10 10:28:13 +00005084 case ARM64vecb_UMAX8x16:
5085 *p++ = X_3_8_5_6_5_5(X011, X01110001, vM, X011001, vN, vD);
5086 break;
5087
sewardjecde6972014-02-05 11:01:19 +00005088 case ARM64vecb_UMIN32x4:
5089 *p++ = X_3_8_5_6_5_5(X011, X01110101, vM, X011011, vN, vD);
5090 break;
5091 case ARM64vecb_UMIN16x8:
5092 *p++ = X_3_8_5_6_5_5(X011, X01110011, vM, X011011, vN, vD);
5093 break;
sewardjfab09142014-02-10 10:28:13 +00005094 case ARM64vecb_UMIN8x16:
5095 *p++ = X_3_8_5_6_5_5(X011, X01110001, vM, X011011, vN, vD);
5096 break;
sewardjf5b08912014-02-06 12:57:58 +00005097
5098 case ARM64vecb_SMAX32x4:
5099 *p++ = X_3_8_5_6_5_5(X010, X01110101, vM, X011001, vN, vD);
5100 break;
5101 case ARM64vecb_SMAX16x8:
5102 *p++ = X_3_8_5_6_5_5(X010, X01110011, vM, X011001, vN, vD);
5103 break;
sewardj9b1cf5e2014-03-01 11:16:57 +00005104 case ARM64vecb_SMAX8x16:
5105 *p++ = X_3_8_5_6_5_5(X010, X01110001, vM, X011001, vN, vD);
5106 break;
sewardjfab09142014-02-10 10:28:13 +00005107
sewardjf5b08912014-02-06 12:57:58 +00005108 case ARM64vecb_SMIN32x4:
5109 *p++ = X_3_8_5_6_5_5(X010, X01110101, vM, X011011, vN, vD);
5110 break;
5111 case ARM64vecb_SMIN16x8:
5112 *p++ = X_3_8_5_6_5_5(X010, X01110011, vM, X011011, vN, vD);
5113 break;
sewardj9b1cf5e2014-03-01 11:16:57 +00005114 case ARM64vecb_SMIN8x16:
5115 *p++ = X_3_8_5_6_5_5(X010, X01110001, vM, X011011, vN, vD);
5116 break;
sewardjf5b08912014-02-06 12:57:58 +00005117
sewardjecde6972014-02-05 11:01:19 +00005118 case ARM64vecb_AND:
5119 *p++ = X_3_8_5_6_5_5(X010, X01110001, vM, X000111, vN, vD);
5120 break;
sewardje520bb32014-02-17 11:00:53 +00005121 case ARM64vecb_ORR:
5122 *p++ = X_3_8_5_6_5_5(X010, X01110101, vM, X000111, vN, vD);
5123 break;
5124 case ARM64vecb_XOR:
5125 *p++ = X_3_8_5_6_5_5(X011, X01110001, vM, X000111, vN, vD);
5126 break;
5127
5128 case ARM64vecb_CMEQ64x2:
5129 *p++ = X_3_8_5_6_5_5(X011, X01110111, vM, X100011, vN, vD);
5130 break;
sewardj505a27d2014-03-10 10:40:48 +00005131 case ARM64vecb_CMEQ32x4:
5132 *p++ = X_3_8_5_6_5_5(X011, X01110101, vM, X100011, vN, vD);
5133 break;
5134 case ARM64vecb_CMEQ16x8:
5135 *p++ = X_3_8_5_6_5_5(X011, X01110011, vM, X100011, vN, vD);
5136 break;
5137 case ARM64vecb_CMEQ8x16:
5138 *p++ = X_3_8_5_6_5_5(X011, X01110001, vM, X100011, vN, vD);
5139 break;
sewardje520bb32014-02-17 11:00:53 +00005140
sewardj93013432014-04-27 12:02:12 +00005141 case ARM64vecb_CMHI64x2:
5142 *p++ = X_3_8_5_6_5_5(X011, X01110111, vM, X001101, vN, vD);
5143 break;
5144 case ARM64vecb_CMHI32x4:
5145 *p++ = X_3_8_5_6_5_5(X011, X01110101, vM, X001101, vN, vD);
5146 break;
5147 case ARM64vecb_CMHI16x8:
5148 *p++ = X_3_8_5_6_5_5(X011, X01110011, vM, X001101, vN, vD);
5149 break;
5150 case ARM64vecb_CMHI8x16:
5151 *p++ = X_3_8_5_6_5_5(X011, X01110001, vM, X001101, vN, vD);
5152 break;
5153
5154 case ARM64vecb_CMGT64x2:
5155 *p++ = X_3_8_5_6_5_5(X010, X01110111, vM, X001101, vN, vD);
5156 break;
5157 case ARM64vecb_CMGT32x4:
5158 *p++ = X_3_8_5_6_5_5(X010, X01110101, vM, X001101, vN, vD);
5159 break;
5160 case ARM64vecb_CMGT16x8:
5161 *p++ = X_3_8_5_6_5_5(X010, X01110011, vM, X001101, vN, vD);
5162 break;
5163 case ARM64vecb_CMGT8x16:
5164 *p++ = X_3_8_5_6_5_5(X010, X01110001, vM, X001101, vN, vD);
5165 break;
5166
sewardj2bd1ffe2014-03-27 18:59:00 +00005167 case ARM64vecb_FCMEQ64x2:
5168 *p++ = X_3_8_5_6_5_5(X010, X01110011, vM, X111001, vN, vD);
5169 break;
5170 case ARM64vecb_FCMEQ32x4:
5171 *p++ = X_3_8_5_6_5_5(X010, X01110001, vM, X111001, vN, vD);
5172 break;
5173
5174 case ARM64vecb_FCMGE64x2:
5175 *p++ = X_3_8_5_6_5_5(X011, X01110011, vM, X111001, vN, vD);
5176 break;
5177 case ARM64vecb_FCMGE32x4:
5178 *p++ = X_3_8_5_6_5_5(X011, X01110001, vM, X111001, vN, vD);
5179 break;
5180
5181 case ARM64vecb_FCMGT64x2:
5182 *p++ = X_3_8_5_6_5_5(X011, X01110111, vM, X111001, vN, vD);
5183 break;
5184 case ARM64vecb_FCMGT32x4:
5185 *p++ = X_3_8_5_6_5_5(X011, X01110101, vM, X111001, vN, vD);
5186 break;
sewardj92d0ae32014-04-03 13:48:54 +00005187
5188 case ARM64vecb_TBL1:
5189 *p++ = X_3_8_5_6_5_5(X010, X01110000, vM, X000000, vN, vD);
5190 break;
5191
sewardj606c4ba2014-01-26 19:11:14 +00005192 default:
5193 goto bad;
5194 }
5195 goto done;
5196 }
sewardjfab09142014-02-10 10:28:13 +00005197 case ARM64in_VUnaryV: {
5198 /* 31 23 20 15 9 4
sewardje520bb32014-02-17 11:00:53 +00005199 010 01110 11 1 00000 111110 n d FABS Vd.2d, Vn.2d
5200 010 01110 10 1 00000 111110 n d FABS Vd.4s, Vn.4s
5201 011 01110 11 1 00000 111110 n d FNEG Vd.2d, Vn.2d
5202 011 01110 10 1 00000 111110 n d FNEG Vd.4s, Vn.4s
5203 011 01110 00 1 00000 010110 n d NOT Vd.16b, Vn.16b
sewardjfab09142014-02-10 10:28:13 +00005204 */
5205 UInt vD = qregNo(i->ARM64in.VUnaryV.dst);
5206 UInt vN = qregNo(i->ARM64in.VUnaryV.arg);
5207 switch (i->ARM64in.VUnaryV.op) {
sewardje520bb32014-02-17 11:00:53 +00005208 case ARM64vecu_FABS64x2:
5209 *p++ = X_3_8_5_6_5_5(X010, X01110111, X00000, X111110, vN, vD);
5210 break;
sewardj2bd1ffe2014-03-27 18:59:00 +00005211 case ARM64vecu_FABS32x4:
5212 *p++ = X_3_8_5_6_5_5(X010, X01110101, X00000, X111110, vN, vD);
5213 break;
sewardjfab09142014-02-10 10:28:13 +00005214 case ARM64vecu_FNEG64x2:
5215 *p++ = X_3_8_5_6_5_5(X011, X01110111, X00000, X111110, vN, vD);
5216 break;
sewardj950ca7a2014-04-03 23:03:32 +00005217 case ARM64vecu_FNEG32x4:
5218 *p++ = X_3_8_5_6_5_5(X011, X01110101, X00000, X111110, vN, vD);
5219 break;
sewardje520bb32014-02-17 11:00:53 +00005220 case ARM64vecu_NOT:
5221 *p++ = X_3_8_5_6_5_5(X011, X01110001, X00000, X010110, vN, vD);
5222 break;
sewardjfab09142014-02-10 10:28:13 +00005223 default:
5224 goto bad;
5225 }
5226 goto done;
5227 }
sewardj606c4ba2014-01-26 19:11:14 +00005228 case ARM64in_VNarrowV: {
5229 /* 31 23 21 15 9 4
5230 000 01110 00 1,00001 001010 n d XTN Vd.8b, Vn.8h
5231 000 01110 01 1,00001 001010 n d XTN Vd.4h, Vn.4s
5232 000 01110 10 1,00001 001010 n d XTN Vd.2s, Vn.2d
5233 */
5234 UInt vD = qregNo(i->ARM64in.VNarrowV.dst);
5235 UInt vN = qregNo(i->ARM64in.VNarrowV.src);
5236 UInt dszBlg2 = i->ARM64in.VNarrowV.dszBlg2;
5237 vassert(dszBlg2 >= 0 && dszBlg2 <= 2);
5238 *p++ = X_3_8_5_6_5_5(X000, X01110001 | (dszBlg2 << 1),
5239 X00001, X001010, vN, vD);
5240 goto done;
5241 }
sewardje520bb32014-02-17 11:00:53 +00005242 case ARM64in_VShiftImmV: {
5243 /*
5244 0q1 011110 immh immb 000001 n d USHR Vd.T, Vn.T, #sh
5245 0q0 011110 immh immb 000001 n d SSHR Vd.T, Vn.T, #sh
5246 where immh:immb
5247 = case T of
5248 2d | sh in 1..63 -> let xxxxxx = 64-sh in 1xxx:xxx
5249 4s | sh in 1..31 -> let xxxxx = 32-sh in 01xx:xxx
5250 8h | sh in 1..15 -> let xxxx = 16-sh in 001x:xxx
5251 16b | sh in 1..7 -> let xxx = 8-sh in 0001:xxx
sewardj32d86752014-03-02 12:47:18 +00005252
5253 0q0 011110 immh immb 010101 n d SHL Vd.T, Vn.T, #sh
5254 where immh:immb
5255 = case T of
5256 2d | sh in 1..63 -> let xxxxxx = sh in 1xxx:xxx
5257 4s | sh in 1..31 -> let xxxxx = sh in 01xx:xxx
5258 8h | sh in 1..15 -> let xxxx = sh in 001x:xxx
5259 16b | sh in 1..7 -> let xxx = sh in 0001:xxx
sewardje520bb32014-02-17 11:00:53 +00005260 */
5261 UInt vD = qregNo(i->ARM64in.VShiftImmV.dst);
5262 UInt vN = qregNo(i->ARM64in.VShiftImmV.src);
5263 UInt sh = i->ARM64in.VShiftImmV.amt;
5264 ARM64VecShiftOp op = i->ARM64in.VShiftImmV.op;
5265 Bool syned = False;
5266 switch (op) {
sewardj93013432014-04-27 12:02:12 +00005267 /* 64x2 cases */
sewardje520bb32014-02-17 11:00:53 +00005268 case ARM64vecsh_SSHR64x2: syned = True;
5269 case ARM64vecsh_USHR64x2: /* fallthrough */
5270 if (sh >= 1 && sh <= 63) {
5271 UInt xxxxxx = 64-sh;
5272 *p++ = X_3_6_7_6_5_5(syned ? X010 : X011, X011110,
5273 X1000000 | xxxxxx, X000001, vN, vD);
5274 goto done;
5275 }
5276 break;
sewardj93013432014-04-27 12:02:12 +00005277 case ARM64vecsh_SHL64x2:
5278 if (sh >= 1 && sh <= 63) {
5279 UInt xxxxxx = sh;
5280 *p++ = X_3_6_7_6_5_5(X010, X011110,
5281 X1000000 | xxxxxx, X010101, vN, vD);
5282 goto done;
5283 }
5284 break;
5285 /* 32x4 cases */
5286 case ARM64vecsh_SSHR32x4: syned = True;
5287 case ARM64vecsh_USHR32x4: /* fallthrough */
5288 if (sh >= 1 && sh <= 31) {
5289 UInt xxxxx = 32-sh;
5290 *p++ = X_3_6_7_6_5_5(syned ? X010 : X011, X011110,
5291 X0100000 | xxxxx, X000001, vN, vD);
5292 goto done;
5293 }
5294 break;
sewardj32d86752014-03-02 12:47:18 +00005295 case ARM64vecsh_SHL32x4:
5296 if (sh >= 1 && sh <= 31) {
5297 UInt xxxxx = sh;
5298 *p++ = X_3_6_7_6_5_5(X010, X011110,
5299 X0100000 | xxxxx, X010101, vN, vD);
5300 goto done;
5301 }
5302 break;
sewardj93013432014-04-27 12:02:12 +00005303 /* 16x8 cases */
5304 case ARM64vecsh_SSHR16x8: syned = True;
sewardj1eaaec22014-03-07 22:52:19 +00005305 case ARM64vecsh_USHR16x8: /* fallthrough */
5306 if (sh >= 1 && sh <= 15) {
5307 UInt xxxx = 16-sh;
5308 *p++ = X_3_6_7_6_5_5(syned ? X010 : X011, X011110,
5309 X0010000 | xxxx, X000001, vN, vD);
5310 goto done;
5311 }
5312 break;
sewardj93013432014-04-27 12:02:12 +00005313 case ARM64vecsh_SHL16x8:
5314 if (sh >= 1 && sh <= 15) {
5315 UInt xxxx = sh;
5316 *p++ = X_3_6_7_6_5_5(X010, X011110,
5317 X0010000 | xxxx, X010101, vN, vD);
5318 goto done;
5319 }
5320 break;
5321
5322
5323 /* 8x16 cases */
5324 case ARM64vecsh_SSHR8x16: syned = True;
5325 case ARM64vecsh_USHR8x16: /* fallthrough */
5326 if (sh >= 1 && sh <= 7) {
5327 UInt xxx = 8-sh;
5328 *p++ = X_3_6_7_6_5_5(syned ? X010 : X011, X011110,
5329 X0001000 | xxx, X000001, vN, vD);
5330 goto done;
5331 }
5332 break;
5333 case ARM64vecsh_SHL8x16:
5334 if (sh >= 1 && sh <= 7) {
5335 UInt xxx = sh;
5336 *p++ = X_3_6_7_6_5_5(X010, X011110,
5337 X0001000 | xxx, X010101, vN, vD);
5338 goto done;
5339 }
5340 break;
5341
sewardje520bb32014-02-17 11:00:53 +00005342 default:
5343 break;
5344 }
5345 goto bad;
5346 }
sewardjbbcf1882014-01-12 12:49:10 +00005347//ZZ case ARMin_VAluS: {
5348//ZZ UInt dN = fregNo(i->ARMin.VAluS.argL);
5349//ZZ UInt dD = fregNo(i->ARMin.VAluS.dst);
5350//ZZ UInt dM = fregNo(i->ARMin.VAluS.argR);
5351//ZZ UInt bN = dN & 1;
5352//ZZ UInt bD = dD & 1;
5353//ZZ UInt bM = dM & 1;
5354//ZZ UInt pqrs = X1111; /* undefined */
5355//ZZ switch (i->ARMin.VAluS.op) {
5356//ZZ case ARMvfp_ADD: pqrs = X0110; break;
5357//ZZ case ARMvfp_SUB: pqrs = X0111; break;
5358//ZZ case ARMvfp_MUL: pqrs = X0100; break;
5359//ZZ case ARMvfp_DIV: pqrs = X1000; break;
5360//ZZ default: goto bad;
5361//ZZ }
5362//ZZ vassert(pqrs != X1111);
5363//ZZ UInt bP = (pqrs >> 3) & 1;
5364//ZZ UInt bQ = (pqrs >> 2) & 1;
5365//ZZ UInt bR = (pqrs >> 1) & 1;
5366//ZZ UInt bS = (pqrs >> 0) & 1;
5367//ZZ UInt insn = XXXXXXXX(0xE, X1110, BITS4(bP,bD,bQ,bR),
5368//ZZ (dN >> 1), (dD >> 1),
5369//ZZ X1010, BITS4(bN,bS,bM,0), (dM >> 1));
5370//ZZ *p++ = insn;
5371//ZZ goto done;
5372//ZZ }
5373//ZZ case ARMin_VUnaryS: {
5374//ZZ UInt fD = fregNo(i->ARMin.VUnaryS.dst);
5375//ZZ UInt fM = fregNo(i->ARMin.VUnaryS.src);
5376//ZZ UInt insn = 0;
5377//ZZ switch (i->ARMin.VUnaryS.op) {
5378//ZZ case ARMvfpu_COPY:
5379//ZZ insn = XXXXXXXX(0xE, X1110, BITS4(1,(fD & 1),1,1), X0000,
5380//ZZ (fD >> 1), X1010, BITS4(0,1,(fM & 1),0),
5381//ZZ (fM >> 1));
5382//ZZ break;
5383//ZZ case ARMvfpu_ABS:
5384//ZZ insn = XXXXXXXX(0xE, X1110, BITS4(1,(fD & 1),1,1), X0000,
5385//ZZ (fD >> 1), X1010, BITS4(1,1,(fM & 1),0),
5386//ZZ (fM >> 1));
5387//ZZ break;
5388//ZZ case ARMvfpu_NEG:
5389//ZZ insn = XXXXXXXX(0xE, X1110, BITS4(1,(fD & 1),1,1), X0001,
5390//ZZ (fD >> 1), X1010, BITS4(0,1,(fM & 1),0),
5391//ZZ (fM >> 1));
5392//ZZ break;
5393//ZZ case ARMvfpu_SQRT:
5394//ZZ insn = XXXXXXXX(0xE, X1110, BITS4(1,(fD & 1),1,1), X0001,
5395//ZZ (fD >> 1), X1010, BITS4(1,1,(fM & 1),0),
5396//ZZ (fM >> 1));
5397//ZZ break;
5398//ZZ default:
5399//ZZ goto bad;
5400//ZZ }
5401//ZZ *p++ = insn;
5402//ZZ goto done;
5403//ZZ }
5404//ZZ case ARMin_VCMovD: {
5405//ZZ UInt cc = (UInt)i->ARMin.VCMovD.cond;
5406//ZZ UInt dD = dregNo(i->ARMin.VCMovD.dst);
5407//ZZ UInt dM = dregNo(i->ARMin.VCMovD.src);
5408//ZZ vassert(cc < 16 && cc != ARMcc_AL);
5409//ZZ UInt insn = XXXXXXXX(cc, X1110,X1011,X0000,dD,X1011,X0100,dM);
5410//ZZ *p++ = insn;
5411//ZZ goto done;
5412//ZZ }
5413//ZZ case ARMin_VCMovS: {
5414//ZZ UInt cc = (UInt)i->ARMin.VCMovS.cond;
5415//ZZ UInt fD = fregNo(i->ARMin.VCMovS.dst);
5416//ZZ UInt fM = fregNo(i->ARMin.VCMovS.src);
5417//ZZ vassert(cc < 16 && cc != ARMcc_AL);
5418//ZZ UInt insn = XXXXXXXX(cc, X1110, BITS4(1,(fD & 1),1,1),
5419//ZZ X0000,(fD >> 1),X1010,
5420//ZZ BITS4(0,1,(fM & 1),0), (fM >> 1));
5421//ZZ *p++ = insn;
5422//ZZ goto done;
5423//ZZ }
5424//ZZ case ARMin_VXferD: {
5425//ZZ UInt dD = dregNo(i->ARMin.VXferD.dD);
5426//ZZ UInt rHi = iregNo(i->ARMin.VXferD.rHi);
5427//ZZ UInt rLo = iregNo(i->ARMin.VXferD.rLo);
5428//ZZ /* vmov dD, rLo, rHi is
5429//ZZ E C 4 rHi rLo B (0,0,dD[4],1) dD[3:0]
5430//ZZ vmov rLo, rHi, dD is
5431//ZZ E C 5 rHi rLo B (0,0,dD[4],1) dD[3:0]
5432//ZZ */
5433//ZZ UInt insn
5434//ZZ = XXXXXXXX(0xE, 0xC, i->ARMin.VXferD.toD ? 4 : 5,
5435//ZZ rHi, rLo, 0xB,
5436//ZZ BITS4(0,0, ((dD >> 4) & 1), 1), (dD & 0xF));
5437//ZZ *p++ = insn;
5438//ZZ goto done;
5439//ZZ }
5440//ZZ case ARMin_VXferS: {
5441//ZZ UInt fD = fregNo(i->ARMin.VXferS.fD);
5442//ZZ UInt rLo = iregNo(i->ARMin.VXferS.rLo);
5443//ZZ /* vmov fD, rLo is
5444//ZZ E E 0 fD[4:1] rLo A (fD[0],0,0,1) 0
5445//ZZ vmov rLo, fD is
5446//ZZ E E 1 fD[4:1] rLo A (fD[0],0,0,1) 0
5447//ZZ */
5448//ZZ UInt insn
5449//ZZ = XXXXXXXX(0xE, 0xE, i->ARMin.VXferS.toS ? 0 : 1,
5450//ZZ (fD >> 1) & 0xF, rLo, 0xA,
5451//ZZ BITS4((fD & 1),0,0,1), 0);
5452//ZZ *p++ = insn;
5453//ZZ goto done;
5454//ZZ }
5455//ZZ case ARMin_VCvtID: {
5456//ZZ Bool iToD = i->ARMin.VCvtID.iToD;
5457//ZZ Bool syned = i->ARMin.VCvtID.syned;
5458//ZZ if (iToD && syned) {
5459//ZZ // FSITOD: I32S-in-freg to F64-in-dreg
5460//ZZ UInt regF = fregNo(i->ARMin.VCvtID.src);
5461//ZZ UInt regD = dregNo(i->ARMin.VCvtID.dst);
5462//ZZ UInt insn = XXXXXXXX(0xE, X1110, X1011, X1000, regD,
5463//ZZ X1011, BITS4(1,1,(regF & 1),0),
5464//ZZ (regF >> 1) & 0xF);
5465//ZZ *p++ = insn;
5466//ZZ goto done;
5467//ZZ }
5468//ZZ if (iToD && (!syned)) {
5469//ZZ // FUITOD: I32U-in-freg to F64-in-dreg
5470//ZZ UInt regF = fregNo(i->ARMin.VCvtID.src);
5471//ZZ UInt regD = dregNo(i->ARMin.VCvtID.dst);
5472//ZZ UInt insn = XXXXXXXX(0xE, X1110, X1011, X1000, regD,
5473//ZZ X1011, BITS4(0,1,(regF & 1),0),
5474//ZZ (regF >> 1) & 0xF);
5475//ZZ *p++ = insn;
5476//ZZ goto done;
5477//ZZ }
5478//ZZ if ((!iToD) && syned) {
5479//ZZ // FTOSID: F64-in-dreg to I32S-in-freg
5480//ZZ UInt regD = dregNo(i->ARMin.VCvtID.src);
5481//ZZ UInt regF = fregNo(i->ARMin.VCvtID.dst);
5482//ZZ UInt insn = XXXXXXXX(0xE, X1110, BITS4(1,(regF & 1),1,1),
5483//ZZ X1101, (regF >> 1) & 0xF,
5484//ZZ X1011, X0100, regD);
5485//ZZ *p++ = insn;
5486//ZZ goto done;
5487//ZZ }
5488//ZZ if ((!iToD) && (!syned)) {
5489//ZZ // FTOUID: F64-in-dreg to I32U-in-freg
5490//ZZ UInt regD = dregNo(i->ARMin.VCvtID.src);
5491//ZZ UInt regF = fregNo(i->ARMin.VCvtID.dst);
5492//ZZ UInt insn = XXXXXXXX(0xE, X1110, BITS4(1,(regF & 1),1,1),
5493//ZZ X1100, (regF >> 1) & 0xF,
5494//ZZ X1011, X0100, regD);
5495//ZZ *p++ = insn;
5496//ZZ goto done;
5497//ZZ }
5498//ZZ /*UNREACHED*/
5499//ZZ vassert(0);
5500//ZZ }
sewardjbbcf1882014-01-12 12:49:10 +00005501//ZZ case ARMin_NLdStD: {
5502//ZZ UInt regD = dregNo(i->ARMin.NLdStD.dD);
5503//ZZ UInt regN, regM;
5504//ZZ UInt D = regD >> 4;
5505//ZZ UInt bL = i->ARMin.NLdStD.isLoad ? 1 : 0;
5506//ZZ UInt insn;
5507//ZZ vassert(hregClass(i->ARMin.NLdStD.dD) == HRcFlt64);
5508//ZZ regD &= 0xF;
5509//ZZ if (i->ARMin.NLdStD.amode->tag == ARMamN_RR) {
5510//ZZ regN = iregNo(i->ARMin.NLdStD.amode->ARMamN.RR.rN);
5511//ZZ regM = iregNo(i->ARMin.NLdStD.amode->ARMamN.RR.rM);
5512//ZZ } else {
5513//ZZ regN = iregNo(i->ARMin.NLdStD.amode->ARMamN.R.rN);
5514//ZZ regM = 15;
5515//ZZ }
5516//ZZ insn = XXXXXXXX(0xF, X0100, BITS4(0, D, bL, 0),
5517//ZZ regN, regD, X0111, X1000, regM);
5518//ZZ *p++ = insn;
5519//ZZ goto done;
5520//ZZ }
5521//ZZ case ARMin_NUnaryS: {
5522//ZZ UInt Q = i->ARMin.NUnaryS.Q ? 1 : 0;
5523//ZZ UInt regD, D;
5524//ZZ UInt regM, M;
5525//ZZ UInt size = i->ARMin.NUnaryS.size;
5526//ZZ UInt insn;
5527//ZZ UInt opc, opc1, opc2;
5528//ZZ switch (i->ARMin.NUnaryS.op) {
5529//ZZ case ARMneon_VDUP:
5530//ZZ if (i->ARMin.NUnaryS.size >= 16)
5531//ZZ goto bad;
5532//ZZ if (i->ARMin.NUnaryS.dst->tag != ARMNRS_Reg)
5533//ZZ goto bad;
5534//ZZ if (i->ARMin.NUnaryS.src->tag != ARMNRS_Scalar)
5535//ZZ goto bad;
5536//ZZ regD = (hregClass(i->ARMin.NUnaryS.dst->reg) == HRcVec128)
5537//ZZ ? (qregNo(i->ARMin.NUnaryS.dst->reg) << 1)
5538//ZZ : dregNo(i->ARMin.NUnaryS.dst->reg);
5539//ZZ regM = (hregClass(i->ARMin.NUnaryS.src->reg) == HRcVec128)
5540//ZZ ? (qregNo(i->ARMin.NUnaryS.src->reg) << 1)
5541//ZZ : dregNo(i->ARMin.NUnaryS.src->reg);
5542//ZZ D = regD >> 4;
5543//ZZ M = regM >> 4;
5544//ZZ regD &= 0xf;
5545//ZZ regM &= 0xf;
5546//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(1,D,1,1),
5547//ZZ (i->ARMin.NUnaryS.size & 0xf), regD,
5548//ZZ X1100, BITS4(0,Q,M,0), regM);
5549//ZZ *p++ = insn;
5550//ZZ goto done;
5551//ZZ case ARMneon_SETELEM:
5552//ZZ regD = Q ? (qregNo(i->ARMin.NUnaryS.dst->reg) << 1) :
5553//ZZ dregNo(i->ARMin.NUnaryS.dst->reg);
5554//ZZ regM = iregNo(i->ARMin.NUnaryS.src->reg);
5555//ZZ M = regM >> 4;
5556//ZZ D = regD >> 4;
5557//ZZ regM &= 0xF;
5558//ZZ regD &= 0xF;
5559//ZZ if (i->ARMin.NUnaryS.dst->tag != ARMNRS_Scalar)
5560//ZZ goto bad;
5561//ZZ switch (size) {
5562//ZZ case 0:
5563//ZZ if (i->ARMin.NUnaryS.dst->index > 7)
5564//ZZ goto bad;
5565//ZZ opc = X1000 | i->ARMin.NUnaryS.dst->index;
5566//ZZ break;
5567//ZZ case 1:
5568//ZZ if (i->ARMin.NUnaryS.dst->index > 3)
5569//ZZ goto bad;
5570//ZZ opc = X0001 | (i->ARMin.NUnaryS.dst->index << 1);
5571//ZZ break;
5572//ZZ case 2:
5573//ZZ if (i->ARMin.NUnaryS.dst->index > 1)
5574//ZZ goto bad;
5575//ZZ opc = X0000 | (i->ARMin.NUnaryS.dst->index << 2);
5576//ZZ break;
5577//ZZ default:
5578//ZZ goto bad;
5579//ZZ }
5580//ZZ opc1 = (opc >> 2) & 3;
5581//ZZ opc2 = opc & 3;
5582//ZZ insn = XXXXXXXX(0xE, X1110, BITS4(0,(opc1 >> 1),(opc1 & 1),0),
5583//ZZ regD, regM, X1011,
5584//ZZ BITS4(D,(opc2 >> 1),(opc2 & 1),1), X0000);
5585//ZZ *p++ = insn;
5586//ZZ goto done;
5587//ZZ case ARMneon_GETELEMU:
5588//ZZ regM = Q ? (qregNo(i->ARMin.NUnaryS.src->reg) << 1) :
5589//ZZ dregNo(i->ARMin.NUnaryS.src->reg);
5590//ZZ regD = iregNo(i->ARMin.NUnaryS.dst->reg);
5591//ZZ M = regM >> 4;
5592//ZZ D = regD >> 4;
5593//ZZ regM &= 0xF;
5594//ZZ regD &= 0xF;
5595//ZZ if (i->ARMin.NUnaryS.src->tag != ARMNRS_Scalar)
5596//ZZ goto bad;
5597//ZZ switch (size) {
5598//ZZ case 0:
5599//ZZ if (Q && i->ARMin.NUnaryS.src->index > 7) {
5600//ZZ regM++;
5601//ZZ i->ARMin.NUnaryS.src->index -= 8;
5602//ZZ }
5603//ZZ if (i->ARMin.NUnaryS.src->index > 7)
5604//ZZ goto bad;
5605//ZZ opc = X1000 | i->ARMin.NUnaryS.src->index;
5606//ZZ break;
5607//ZZ case 1:
5608//ZZ if (Q && i->ARMin.NUnaryS.src->index > 3) {
5609//ZZ regM++;
5610//ZZ i->ARMin.NUnaryS.src->index -= 4;
5611//ZZ }
5612//ZZ if (i->ARMin.NUnaryS.src->index > 3)
5613//ZZ goto bad;
5614//ZZ opc = X0001 | (i->ARMin.NUnaryS.src->index << 1);
5615//ZZ break;
5616//ZZ case 2:
5617//ZZ goto bad;
5618//ZZ default:
5619//ZZ goto bad;
5620//ZZ }
5621//ZZ opc1 = (opc >> 2) & 3;
5622//ZZ opc2 = opc & 3;
5623//ZZ insn = XXXXXXXX(0xE, X1110, BITS4(1,(opc1 >> 1),(opc1 & 1),1),
5624//ZZ regM, regD, X1011,
5625//ZZ BITS4(M,(opc2 >> 1),(opc2 & 1),1), X0000);
5626//ZZ *p++ = insn;
5627//ZZ goto done;
5628//ZZ case ARMneon_GETELEMS:
5629//ZZ regM = Q ? (qregNo(i->ARMin.NUnaryS.src->reg) << 1) :
5630//ZZ dregNo(i->ARMin.NUnaryS.src->reg);
5631//ZZ regD = iregNo(i->ARMin.NUnaryS.dst->reg);
5632//ZZ M = regM >> 4;
5633//ZZ D = regD >> 4;
5634//ZZ regM &= 0xF;
5635//ZZ regD &= 0xF;
5636//ZZ if (i->ARMin.NUnaryS.src->tag != ARMNRS_Scalar)
5637//ZZ goto bad;
5638//ZZ switch (size) {
5639//ZZ case 0:
5640//ZZ if (Q && i->ARMin.NUnaryS.src->index > 7) {
5641//ZZ regM++;
5642//ZZ i->ARMin.NUnaryS.src->index -= 8;
5643//ZZ }
5644//ZZ if (i->ARMin.NUnaryS.src->index > 7)
5645//ZZ goto bad;
5646//ZZ opc = X1000 | i->ARMin.NUnaryS.src->index;
5647//ZZ break;
5648//ZZ case 1:
5649//ZZ if (Q && i->ARMin.NUnaryS.src->index > 3) {
5650//ZZ regM++;
5651//ZZ i->ARMin.NUnaryS.src->index -= 4;
5652//ZZ }
5653//ZZ if (i->ARMin.NUnaryS.src->index > 3)
5654//ZZ goto bad;
5655//ZZ opc = X0001 | (i->ARMin.NUnaryS.src->index << 1);
5656//ZZ break;
5657//ZZ case 2:
5658//ZZ if (Q && i->ARMin.NUnaryS.src->index > 1) {
5659//ZZ regM++;
5660//ZZ i->ARMin.NUnaryS.src->index -= 2;
5661//ZZ }
5662//ZZ if (i->ARMin.NUnaryS.src->index > 1)
5663//ZZ goto bad;
5664//ZZ opc = X0000 | (i->ARMin.NUnaryS.src->index << 2);
5665//ZZ break;
5666//ZZ default:
5667//ZZ goto bad;
5668//ZZ }
5669//ZZ opc1 = (opc >> 2) & 3;
5670//ZZ opc2 = opc & 3;
5671//ZZ insn = XXXXXXXX(0xE, X1110, BITS4(0,(opc1 >> 1),(opc1 & 1),1),
5672//ZZ regM, regD, X1011,
5673//ZZ BITS4(M,(opc2 >> 1),(opc2 & 1),1), X0000);
5674//ZZ *p++ = insn;
5675//ZZ goto done;
5676//ZZ default:
5677//ZZ goto bad;
5678//ZZ }
5679//ZZ }
5680//ZZ case ARMin_NUnary: {
5681//ZZ UInt Q = i->ARMin.NUnary.Q ? 1 : 0;
5682//ZZ UInt regD = (hregClass(i->ARMin.NUnary.dst) == HRcVec128)
5683//ZZ ? (qregNo(i->ARMin.NUnary.dst) << 1)
5684//ZZ : dregNo(i->ARMin.NUnary.dst);
5685//ZZ UInt regM, M;
5686//ZZ UInt D = regD >> 4;
5687//ZZ UInt sz1 = i->ARMin.NUnary.size >> 1;
5688//ZZ UInt sz2 = i->ARMin.NUnary.size & 1;
5689//ZZ UInt sz = i->ARMin.NUnary.size;
5690//ZZ UInt insn;
5691//ZZ UInt F = 0; /* TODO: floating point EQZ ??? */
5692//ZZ if (i->ARMin.NUnary.op != ARMneon_DUP) {
5693//ZZ regM = (hregClass(i->ARMin.NUnary.src) == HRcVec128)
5694//ZZ ? (qregNo(i->ARMin.NUnary.src) << 1)
5695//ZZ : dregNo(i->ARMin.NUnary.src);
5696//ZZ M = regM >> 4;
5697//ZZ } else {
5698//ZZ regM = iregNo(i->ARMin.NUnary.src);
5699//ZZ M = regM >> 4;
5700//ZZ }
5701//ZZ regD &= 0xF;
5702//ZZ regM &= 0xF;
5703//ZZ switch (i->ARMin.NUnary.op) {
5704//ZZ case ARMneon_COPY: /* VMOV reg, reg */
5705//ZZ insn = XXXXXXXX(0xF, X0010, BITS4(0,D,1,0), regM, regD, X0001,
5706//ZZ BITS4(M,Q,M,1), regM);
5707//ZZ break;
5708//ZZ case ARMneon_COPYN: /* VMOVN regD, regQ */
5709//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(1,D,1,1), BITS4(sz1,sz2,1,0),
5710//ZZ regD, X0010, BITS4(0,0,M,0), regM);
5711//ZZ break;
5712//ZZ case ARMneon_COPYQNSS: /* VQMOVN regD, regQ */
5713//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(1,D,1,1), BITS4(sz1,sz2,1,0),
5714//ZZ regD, X0010, BITS4(1,0,M,0), regM);
5715//ZZ break;
5716//ZZ case ARMneon_COPYQNUS: /* VQMOVUN regD, regQ */
5717//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(1,D,1,1), BITS4(sz1,sz2,1,0),
5718//ZZ regD, X0010, BITS4(0,1,M,0), regM);
5719//ZZ break;
5720//ZZ case ARMneon_COPYQNUU: /* VQMOVN regD, regQ */
5721//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(1,D,1,1), BITS4(sz1,sz2,1,0),
5722//ZZ regD, X0010, BITS4(1,1,M,0), regM);
5723//ZZ break;
5724//ZZ case ARMneon_COPYLS: /* VMOVL regQ, regD */
5725//ZZ if (sz >= 3)
5726//ZZ goto bad;
5727//ZZ insn = XXXXXXXX(0xF, X0010,
5728//ZZ BITS4(1,D,(sz == 2) ? 1 : 0,(sz == 1) ? 1 : 0),
5729//ZZ BITS4((sz == 0) ? 1 : 0,0,0,0),
5730//ZZ regD, X1010, BITS4(0,0,M,1), regM);
5731//ZZ break;
5732//ZZ case ARMneon_COPYLU: /* VMOVL regQ, regD */
5733//ZZ if (sz >= 3)
5734//ZZ goto bad;
5735//ZZ insn = XXXXXXXX(0xF, X0011,
5736//ZZ BITS4(1,D,(sz == 2) ? 1 : 0,(sz == 1) ? 1 : 0),
5737//ZZ BITS4((sz == 0) ? 1 : 0,0,0,0),
5738//ZZ regD, X1010, BITS4(0,0,M,1), regM);
5739//ZZ break;
5740//ZZ case ARMneon_NOT: /* VMVN reg, reg*/
5741//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(1,D,1,1), X0000, regD, X0101,
5742//ZZ BITS4(1,Q,M,0), regM);
5743//ZZ break;
5744//ZZ case ARMneon_EQZ:
5745//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(1,D,1,1), BITS4(sz1,sz2,0,1),
5746//ZZ regD, BITS4(0,F,0,1), BITS4(0,Q,M,0), regM);
5747//ZZ break;
5748//ZZ case ARMneon_CNT:
5749//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(1,D,1,1), X0000, regD, X0101,
5750//ZZ BITS4(0,Q,M,0), regM);
5751//ZZ break;
5752//ZZ case ARMneon_CLZ:
5753//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(1,D,1,1), BITS4(sz1,sz2,0,0),
5754//ZZ regD, X0100, BITS4(1,Q,M,0), regM);
5755//ZZ break;
5756//ZZ case ARMneon_CLS:
5757//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(1,D,1,1), BITS4(sz1,sz2,0,0),
5758//ZZ regD, X0100, BITS4(0,Q,M,0), regM);
5759//ZZ break;
5760//ZZ case ARMneon_ABS:
5761//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(1,D,1,1), BITS4(sz1,sz2,0,1),
5762//ZZ regD, X0011, BITS4(0,Q,M,0), regM);
5763//ZZ break;
5764//ZZ case ARMneon_DUP:
5765//ZZ sz1 = i->ARMin.NUnary.size == 0 ? 1 : 0;
5766//ZZ sz2 = i->ARMin.NUnary.size == 1 ? 1 : 0;
5767//ZZ vassert(sz1 + sz2 < 2);
5768//ZZ insn = XXXXXXXX(0xE, X1110, BITS4(1, sz1, Q, 0), regD, regM,
5769//ZZ X1011, BITS4(D,0,sz2,1), X0000);
5770//ZZ break;
5771//ZZ case ARMneon_REV16:
5772//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(1,D,1,1), BITS4(sz1,sz2,0,0),
5773//ZZ regD, BITS4(0,0,0,1), BITS4(0,Q,M,0), regM);
5774//ZZ break;
5775//ZZ case ARMneon_REV32:
5776//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(1,D,1,1), BITS4(sz1,sz2,0,0),
5777//ZZ regD, BITS4(0,0,0,0), BITS4(1,Q,M,0), regM);
5778//ZZ break;
5779//ZZ case ARMneon_REV64:
5780//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(1,D,1,1), BITS4(sz1,sz2,0,0),
5781//ZZ regD, BITS4(0,0,0,0), BITS4(0,Q,M,0), regM);
5782//ZZ break;
5783//ZZ case ARMneon_PADDLU:
5784//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(1,D,1,1), BITS4(sz1,sz2,0,0),
5785//ZZ regD, X0010, BITS4(1,Q,M,0), regM);
5786//ZZ break;
5787//ZZ case ARMneon_PADDLS:
5788//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(1,D,1,1), BITS4(sz1,sz2,0,0),
5789//ZZ regD, X0010, BITS4(0,Q,M,0), regM);
5790//ZZ break;
5791//ZZ case ARMneon_VQSHLNUU:
5792//ZZ insn = XXXXXXXX(0xF, X0011,
5793//ZZ (1 << 3) | (D << 2) | ((sz >> 4) & 3),
5794//ZZ sz & 0xf, regD, X0111,
5795//ZZ BITS4(sz >> 6,Q,M,1), regM);
5796//ZZ break;
5797//ZZ case ARMneon_VQSHLNSS:
5798//ZZ insn = XXXXXXXX(0xF, X0010,
5799//ZZ (1 << 3) | (D << 2) | ((sz >> 4) & 3),
5800//ZZ sz & 0xf, regD, X0111,
5801//ZZ BITS4(sz >> 6,Q,M,1), regM);
5802//ZZ break;
5803//ZZ case ARMneon_VQSHLNUS:
5804//ZZ insn = XXXXXXXX(0xF, X0011,
5805//ZZ (1 << 3) | (D << 2) | ((sz >> 4) & 3),
5806//ZZ sz & 0xf, regD, X0110,
5807//ZZ BITS4(sz >> 6,Q,M,1), regM);
5808//ZZ break;
5809//ZZ case ARMneon_VCVTFtoS:
5810//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(1,D,1,1), X1011, regD, X0111,
5811//ZZ BITS4(0,Q,M,0), regM);
5812//ZZ break;
5813//ZZ case ARMneon_VCVTFtoU:
5814//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(1,D,1,1), X1011, regD, X0111,
5815//ZZ BITS4(1,Q,M,0), regM);
5816//ZZ break;
5817//ZZ case ARMneon_VCVTStoF:
5818//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(1,D,1,1), X1011, regD, X0110,
5819//ZZ BITS4(0,Q,M,0), regM);
5820//ZZ break;
5821//ZZ case ARMneon_VCVTUtoF:
5822//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(1,D,1,1), X1011, regD, X0110,
5823//ZZ BITS4(1,Q,M,0), regM);
5824//ZZ break;
5825//ZZ case ARMneon_VCVTFtoFixedU:
5826//ZZ sz1 = (sz >> 5) & 1;
5827//ZZ sz2 = (sz >> 4) & 1;
5828//ZZ sz &= 0xf;
5829//ZZ insn = XXXXXXXX(0xF, X0011,
5830//ZZ BITS4(1,D,sz1,sz2), sz, regD, X1111,
5831//ZZ BITS4(0,Q,M,1), regM);
5832//ZZ break;
5833//ZZ case ARMneon_VCVTFtoFixedS:
5834//ZZ sz1 = (sz >> 5) & 1;
5835//ZZ sz2 = (sz >> 4) & 1;
5836//ZZ sz &= 0xf;
5837//ZZ insn = XXXXXXXX(0xF, X0010,
5838//ZZ BITS4(1,D,sz1,sz2), sz, regD, X1111,
5839//ZZ BITS4(0,Q,M,1), regM);
5840//ZZ break;
5841//ZZ case ARMneon_VCVTFixedUtoF:
5842//ZZ sz1 = (sz >> 5) & 1;
5843//ZZ sz2 = (sz >> 4) & 1;
5844//ZZ sz &= 0xf;
5845//ZZ insn = XXXXXXXX(0xF, X0011,
5846//ZZ BITS4(1,D,sz1,sz2), sz, regD, X1110,
5847//ZZ BITS4(0,Q,M,1), regM);
5848//ZZ break;
5849//ZZ case ARMneon_VCVTFixedStoF:
5850//ZZ sz1 = (sz >> 5) & 1;
5851//ZZ sz2 = (sz >> 4) & 1;
5852//ZZ sz &= 0xf;
5853//ZZ insn = XXXXXXXX(0xF, X0010,
5854//ZZ BITS4(1,D,sz1,sz2), sz, regD, X1110,
5855//ZZ BITS4(0,Q,M,1), regM);
5856//ZZ break;
5857//ZZ case ARMneon_VCVTF32toF16:
5858//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(1,D,1,1), X0110, regD, X0110,
5859//ZZ BITS4(0,0,M,0), regM);
5860//ZZ break;
5861//ZZ case ARMneon_VCVTF16toF32:
5862//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(1,D,1,1), X0110, regD, X0111,
5863//ZZ BITS4(0,0,M,0), regM);
5864//ZZ break;
5865//ZZ case ARMneon_VRECIP:
5866//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(1,D,1,1), X1011, regD, X0100,
5867//ZZ BITS4(0,Q,M,0), regM);
5868//ZZ break;
5869//ZZ case ARMneon_VRECIPF:
5870//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(1,D,1,1), X1011, regD, X0101,
5871//ZZ BITS4(0,Q,M,0), regM);
5872//ZZ break;
5873//ZZ case ARMneon_VABSFP:
5874//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(1,D,1,1), X1001, regD, X0111,
5875//ZZ BITS4(0,Q,M,0), regM);
5876//ZZ break;
5877//ZZ case ARMneon_VRSQRTEFP:
5878//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(1,D,1,1), X1011, regD, X0101,
5879//ZZ BITS4(1,Q,M,0), regM);
5880//ZZ break;
5881//ZZ case ARMneon_VRSQRTE:
5882//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(1,D,1,1), X1011, regD, X0100,
5883//ZZ BITS4(1,Q,M,0), regM);
5884//ZZ break;
5885//ZZ case ARMneon_VNEGF:
5886//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(1,D,1,1), X1001, regD, X0111,
5887//ZZ BITS4(1,Q,M,0), regM);
5888//ZZ break;
5889//ZZ
5890//ZZ default:
5891//ZZ goto bad;
5892//ZZ }
5893//ZZ *p++ = insn;
5894//ZZ goto done;
5895//ZZ }
5896//ZZ case ARMin_NDual: {
5897//ZZ UInt Q = i->ARMin.NDual.Q ? 1 : 0;
5898//ZZ UInt regD = (hregClass(i->ARMin.NDual.arg1) == HRcVec128)
5899//ZZ ? (qregNo(i->ARMin.NDual.arg1) << 1)
5900//ZZ : dregNo(i->ARMin.NDual.arg1);
5901//ZZ UInt regM = (hregClass(i->ARMin.NDual.arg2) == HRcVec128)
5902//ZZ ? (qregNo(i->ARMin.NDual.arg2) << 1)
5903//ZZ : dregNo(i->ARMin.NDual.arg2);
5904//ZZ UInt D = regD >> 4;
5905//ZZ UInt M = regM >> 4;
5906//ZZ UInt sz1 = i->ARMin.NDual.size >> 1;
5907//ZZ UInt sz2 = i->ARMin.NDual.size & 1;
5908//ZZ UInt insn;
5909//ZZ regD &= 0xF;
5910//ZZ regM &= 0xF;
5911//ZZ switch (i->ARMin.NDual.op) {
5912//ZZ case ARMneon_TRN: /* VTRN reg, reg */
5913//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(1,D,1,1), BITS4(sz1,sz2,1,0),
5914//ZZ regD, X0000, BITS4(1,Q,M,0), regM);
5915//ZZ break;
5916//ZZ case ARMneon_ZIP: /* VZIP reg, reg */
5917//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(1,D,1,1), BITS4(sz1,sz2,1,0),
5918//ZZ regD, X0001, BITS4(1,Q,M,0), regM);
5919//ZZ break;
5920//ZZ case ARMneon_UZP: /* VUZP reg, reg */
5921//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(1,D,1,1), BITS4(sz1,sz2,1,0),
5922//ZZ regD, X0001, BITS4(0,Q,M,0), regM);
5923//ZZ break;
5924//ZZ default:
5925//ZZ goto bad;
5926//ZZ }
5927//ZZ *p++ = insn;
5928//ZZ goto done;
5929//ZZ }
5930//ZZ case ARMin_NBinary: {
5931//ZZ UInt Q = i->ARMin.NBinary.Q ? 1 : 0;
5932//ZZ UInt regD = (hregClass(i->ARMin.NBinary.dst) == HRcVec128)
5933//ZZ ? (qregNo(i->ARMin.NBinary.dst) << 1)
5934//ZZ : dregNo(i->ARMin.NBinary.dst);
5935//ZZ UInt regN = (hregClass(i->ARMin.NBinary.argL) == HRcVec128)
5936//ZZ ? (qregNo(i->ARMin.NBinary.argL) << 1)
5937//ZZ : dregNo(i->ARMin.NBinary.argL);
5938//ZZ UInt regM = (hregClass(i->ARMin.NBinary.argR) == HRcVec128)
5939//ZZ ? (qregNo(i->ARMin.NBinary.argR) << 1)
5940//ZZ : dregNo(i->ARMin.NBinary.argR);
5941//ZZ UInt sz1 = i->ARMin.NBinary.size >> 1;
5942//ZZ UInt sz2 = i->ARMin.NBinary.size & 1;
5943//ZZ UInt D = regD >> 4;
5944//ZZ UInt N = regN >> 4;
5945//ZZ UInt M = regM >> 4;
5946//ZZ UInt insn;
5947//ZZ regD &= 0xF;
5948//ZZ regM &= 0xF;
5949//ZZ regN &= 0xF;
5950//ZZ switch (i->ARMin.NBinary.op) {
5951//ZZ case ARMneon_VAND: /* VAND reg, reg, reg */
5952//ZZ insn = XXXXXXXX(0xF, X0010, BITS4(0,D,0,0), regN, regD, X0001,
5953//ZZ BITS4(N,Q,M,1), regM);
5954//ZZ break;
5955//ZZ case ARMneon_VORR: /* VORR reg, reg, reg*/
5956//ZZ insn = XXXXXXXX(0xF, X0010, BITS4(0,D,1,0), regN, regD, X0001,
5957//ZZ BITS4(N,Q,M,1), regM);
5958//ZZ break;
5959//ZZ case ARMneon_VXOR: /* VEOR reg, reg, reg */
5960//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(0,D,0,0), regN, regD, X0001,
5961//ZZ BITS4(N,Q,M,1), regM);
5962//ZZ break;
5963//ZZ case ARMneon_VADD: /* VADD reg, reg, reg */
5964//ZZ insn = XXXXXXXX(0xF, X0010, BITS4(0,D,sz1,sz2), regN, regD,
5965//ZZ X1000, BITS4(N,Q,M,0), regM);
5966//ZZ break;
5967//ZZ case ARMneon_VSUB: /* VSUB reg, reg, reg */
5968//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(0,D,sz1,sz2), regN, regD,
5969//ZZ X1000, BITS4(N,Q,M,0), regM);
5970//ZZ break;
5971//ZZ case ARMneon_VMINU: /* VMIN.Uxx reg, reg, reg */
5972//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(0,D,sz1,sz2), regN, regD,
5973//ZZ X0110, BITS4(N,Q,M,1), regM);
5974//ZZ break;
5975//ZZ case ARMneon_VMINS: /* VMIN.Sxx reg, reg, reg */
5976//ZZ insn = XXXXXXXX(0xF, X0010, BITS4(0,D,sz1,sz2), regN, regD,
5977//ZZ X0110, BITS4(N,Q,M,1), regM);
5978//ZZ break;
5979//ZZ case ARMneon_VMAXU: /* VMAX.Uxx reg, reg, reg */
5980//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(0,D,sz1,sz2), regN, regD,
5981//ZZ X0110, BITS4(N,Q,M,0), regM);
5982//ZZ break;
5983//ZZ case ARMneon_VMAXS: /* VMAX.Sxx reg, reg, reg */
5984//ZZ insn = XXXXXXXX(0xF, X0010, BITS4(0,D,sz1,sz2), regN, regD,
5985//ZZ X0110, BITS4(N,Q,M,0), regM);
5986//ZZ break;
5987//ZZ case ARMneon_VRHADDS: /* VRHADD.Sxx reg, reg, reg */
5988//ZZ insn = XXXXXXXX(0xF, X0010, BITS4(0,D,sz1,sz2), regN, regD,
5989//ZZ X0001, BITS4(N,Q,M,0), regM);
5990//ZZ break;
5991//ZZ case ARMneon_VRHADDU: /* VRHADD.Uxx reg, reg, reg */
5992//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(0,D,sz1,sz2), regN, regD,
5993//ZZ X0001, BITS4(N,Q,M,0), regM);
5994//ZZ break;
5995//ZZ case ARMneon_VQADDU: /* VQADD unsigned reg, reg, reg */
5996//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(0,D,sz1,sz2), regN, regD,
5997//ZZ X0000, BITS4(N,Q,M,1), regM);
5998//ZZ break;
5999//ZZ case ARMneon_VQADDS: /* VQADD signed reg, reg, reg */
6000//ZZ insn = XXXXXXXX(0xF, X0010, BITS4(0,D,sz1,sz2), regN, regD,
6001//ZZ X0000, BITS4(N,Q,M,1), regM);
6002//ZZ break;
6003//ZZ case ARMneon_VQSUBU: /* VQSUB unsigned reg, reg, reg */
6004//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(0,D,sz1,sz2), regN, regD,
6005//ZZ X0010, BITS4(N,Q,M,1), regM);
6006//ZZ break;
6007//ZZ case ARMneon_VQSUBS: /* VQSUB signed reg, reg, reg */
6008//ZZ insn = XXXXXXXX(0xF, X0010, BITS4(0,D,sz1,sz2), regN, regD,
6009//ZZ X0010, BITS4(N,Q,M,1), regM);
6010//ZZ break;
6011//ZZ case ARMneon_VCGTU: /* VCGT unsigned reg, reg, reg */
6012//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(0,D,sz1,sz2), regN, regD,
6013//ZZ X0011, BITS4(N,Q,M,0), regM);
6014//ZZ break;
6015//ZZ case ARMneon_VCGTS: /* VCGT signed reg, reg, reg */
6016//ZZ insn = XXXXXXXX(0xF, X0010, BITS4(0,D,sz1,sz2), regN, regD,
6017//ZZ X0011, BITS4(N,Q,M,0), regM);
6018//ZZ break;
6019//ZZ case ARMneon_VCGEU: /* VCGE unsigned reg, reg, reg */
6020//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(0,D,sz1,sz2), regN, regD,
6021//ZZ X0011, BITS4(N,Q,M,1), regM);
6022//ZZ break;
6023//ZZ case ARMneon_VCGES: /* VCGE signed reg, reg, reg */
6024//ZZ insn = XXXXXXXX(0xF, X0010, BITS4(0,D,sz1,sz2), regN, regD,
6025//ZZ X0011, BITS4(N,Q,M,1), regM);
6026//ZZ break;
6027//ZZ case ARMneon_VCEQ: /* VCEQ reg, reg, reg */
6028//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(0,D,sz1,sz2), regN, regD,
6029//ZZ X1000, BITS4(N,Q,M,1), regM);
6030//ZZ break;
6031//ZZ case ARMneon_VEXT: /* VEXT.8 reg, reg, #imm4*/
6032//ZZ if (i->ARMin.NBinary.size >= 16)
6033//ZZ goto bad;
6034//ZZ insn = XXXXXXXX(0xF, X0010, BITS4(1,D,1,1), regN, regD,
6035//ZZ i->ARMin.NBinary.size & 0xf, BITS4(N,Q,M,0),
6036//ZZ regM);
6037//ZZ break;
6038//ZZ case ARMneon_VMUL:
6039//ZZ insn = XXXXXXXX(0xF, X0010, BITS4(0,D,sz1,sz2), regN, regD,
6040//ZZ X1001, BITS4(N,Q,M,1), regM);
6041//ZZ break;
6042//ZZ case ARMneon_VMULLU:
6043//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(1,D,sz1,sz2), regN, regD,
6044//ZZ X1100, BITS4(N,0,M,0), regM);
6045//ZZ break;
6046//ZZ case ARMneon_VMULLS:
6047//ZZ insn = XXXXXXXX(0xF, X0010, BITS4(1,D,sz1,sz2), regN, regD,
6048//ZZ X1100, BITS4(N,0,M,0), regM);
6049//ZZ break;
6050//ZZ case ARMneon_VMULP:
6051//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(0,D,sz1,sz2), regN, regD,
6052//ZZ X1001, BITS4(N,Q,M,1), regM);
6053//ZZ break;
6054//ZZ case ARMneon_VMULFP:
6055//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(0,D,0,0), regN, regD,
6056//ZZ X1101, BITS4(N,Q,M,1), regM);
6057//ZZ break;
6058//ZZ case ARMneon_VMULLP:
6059//ZZ insn = XXXXXXXX(0xF, X0010, BITS4(1,D,sz1,sz2), regN, regD,
6060//ZZ X1110, BITS4(N,0,M,0), regM);
6061//ZZ break;
6062//ZZ case ARMneon_VQDMULH:
6063//ZZ insn = XXXXXXXX(0xF, X0010, BITS4(0,D,sz1,sz2), regN, regD,
6064//ZZ X1011, BITS4(N,Q,M,0), regM);
6065//ZZ break;
6066//ZZ case ARMneon_VQRDMULH:
6067//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(0,D,sz1,sz2), regN, regD,
6068//ZZ X1011, BITS4(N,Q,M,0), regM);
6069//ZZ break;
6070//ZZ case ARMneon_VQDMULL:
6071//ZZ insn = XXXXXXXX(0xF, X0010, BITS4(1,D,sz1,sz2), regN, regD,
6072//ZZ X1101, BITS4(N,0,M,0), regM);
6073//ZZ break;
6074//ZZ case ARMneon_VTBL:
6075//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(1,D,1,1), regN, regD,
6076//ZZ X1000, BITS4(N,0,M,0), regM);
6077//ZZ break;
6078//ZZ case ARMneon_VPADD:
6079//ZZ insn = XXXXXXXX(0xF, X0010, BITS4(0,D,sz1,sz2), regN, regD,
6080//ZZ X1011, BITS4(N,Q,M,1), regM);
6081//ZZ break;
6082//ZZ case ARMneon_VPADDFP:
6083//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(0,D,0,0), regN, regD,
6084//ZZ X1101, BITS4(N,Q,M,0), regM);
6085//ZZ break;
6086//ZZ case ARMneon_VPMINU:
6087//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(0,D,sz1,sz2), regN, regD,
6088//ZZ X1010, BITS4(N,Q,M,1), regM);
6089//ZZ break;
6090//ZZ case ARMneon_VPMINS:
6091//ZZ insn = XXXXXXXX(0xF, X0010, BITS4(0,D,sz1,sz2), regN, regD,
6092//ZZ X1010, BITS4(N,Q,M,1), regM);
6093//ZZ break;
6094//ZZ case ARMneon_VPMAXU:
6095//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(0,D,sz1,sz2), regN, regD,
6096//ZZ X1010, BITS4(N,Q,M,0), regM);
6097//ZZ break;
6098//ZZ case ARMneon_VPMAXS:
6099//ZZ insn = XXXXXXXX(0xF, X0010, BITS4(0,D,sz1,sz2), regN, regD,
6100//ZZ X1010, BITS4(N,Q,M,0), regM);
6101//ZZ break;
6102//ZZ case ARMneon_VADDFP: /* VADD reg, reg, reg */
6103//ZZ insn = XXXXXXXX(0xF, X0010, BITS4(0,D,0,0), regN, regD,
6104//ZZ X1101, BITS4(N,Q,M,0), regM);
6105//ZZ break;
6106//ZZ case ARMneon_VSUBFP: /* VADD reg, reg, reg */
6107//ZZ insn = XXXXXXXX(0xF, X0010, BITS4(0,D,1,0), regN, regD,
6108//ZZ X1101, BITS4(N,Q,M,0), regM);
6109//ZZ break;
6110//ZZ case ARMneon_VABDFP: /* VABD reg, reg, reg */
6111//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(0,D,1,0), regN, regD,
6112//ZZ X1101, BITS4(N,Q,M,0), regM);
6113//ZZ break;
6114//ZZ case ARMneon_VMINF:
6115//ZZ insn = XXXXXXXX(0xF, X0010, BITS4(0,D,1,0), regN, regD,
6116//ZZ X1111, BITS4(N,Q,M,0), regM);
6117//ZZ break;
6118//ZZ case ARMneon_VMAXF:
6119//ZZ insn = XXXXXXXX(0xF, X0010, BITS4(0,D,0,0), regN, regD,
6120//ZZ X1111, BITS4(N,Q,M,0), regM);
6121//ZZ break;
6122//ZZ case ARMneon_VPMINF:
6123//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(0,D,1,0), regN, regD,
6124//ZZ X1111, BITS4(N,Q,M,0), regM);
6125//ZZ break;
6126//ZZ case ARMneon_VPMAXF:
6127//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(0,D,0,0), regN, regD,
6128//ZZ X1111, BITS4(N,Q,M,0), regM);
6129//ZZ break;
6130//ZZ case ARMneon_VRECPS:
6131//ZZ insn = XXXXXXXX(0xF, X0010, BITS4(0,D,0,0), regN, regD, X1111,
6132//ZZ BITS4(N,Q,M,1), regM);
6133//ZZ break;
6134//ZZ case ARMneon_VCGTF:
6135//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(0,D,1,0), regN, regD, X1110,
6136//ZZ BITS4(N,Q,M,0), regM);
6137//ZZ break;
6138//ZZ case ARMneon_VCGEF:
6139//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(0,D,0,0), regN, regD, X1110,
6140//ZZ BITS4(N,Q,M,0), regM);
6141//ZZ break;
6142//ZZ case ARMneon_VCEQF:
6143//ZZ insn = XXXXXXXX(0xF, X0010, BITS4(0,D,0,0), regN, regD, X1110,
6144//ZZ BITS4(N,Q,M,0), regM);
6145//ZZ break;
6146//ZZ case ARMneon_VRSQRTS:
6147//ZZ insn = XXXXXXXX(0xF, X0010, BITS4(0,D,1,0), regN, regD, X1111,
6148//ZZ BITS4(N,Q,M,1), regM);
6149//ZZ break;
6150//ZZ default:
6151//ZZ goto bad;
6152//ZZ }
6153//ZZ *p++ = insn;
6154//ZZ goto done;
6155//ZZ }
6156//ZZ case ARMin_NShift: {
6157//ZZ UInt Q = i->ARMin.NShift.Q ? 1 : 0;
6158//ZZ UInt regD = (hregClass(i->ARMin.NShift.dst) == HRcVec128)
6159//ZZ ? (qregNo(i->ARMin.NShift.dst) << 1)
6160//ZZ : dregNo(i->ARMin.NShift.dst);
6161//ZZ UInt regM = (hregClass(i->ARMin.NShift.argL) == HRcVec128)
6162//ZZ ? (qregNo(i->ARMin.NShift.argL) << 1)
6163//ZZ : dregNo(i->ARMin.NShift.argL);
6164//ZZ UInt regN = (hregClass(i->ARMin.NShift.argR) == HRcVec128)
6165//ZZ ? (qregNo(i->ARMin.NShift.argR) << 1)
6166//ZZ : dregNo(i->ARMin.NShift.argR);
6167//ZZ UInt sz1 = i->ARMin.NShift.size >> 1;
6168//ZZ UInt sz2 = i->ARMin.NShift.size & 1;
6169//ZZ UInt D = regD >> 4;
6170//ZZ UInt N = regN >> 4;
6171//ZZ UInt M = regM >> 4;
6172//ZZ UInt insn;
6173//ZZ regD &= 0xF;
6174//ZZ regM &= 0xF;
6175//ZZ regN &= 0xF;
6176//ZZ switch (i->ARMin.NShift.op) {
6177//ZZ case ARMneon_VSHL:
6178//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(0,D,sz1,sz2), regN, regD,
6179//ZZ X0100, BITS4(N,Q,M,0), regM);
6180//ZZ break;
6181//ZZ case ARMneon_VSAL:
6182//ZZ insn = XXXXXXXX(0xF, X0010, BITS4(0,D,sz1,sz2), regN, regD,
6183//ZZ X0100, BITS4(N,Q,M,0), regM);
6184//ZZ break;
6185//ZZ case ARMneon_VQSHL:
6186//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(0,D,sz1,sz2), regN, regD,
6187//ZZ X0100, BITS4(N,Q,M,1), regM);
6188//ZZ break;
6189//ZZ case ARMneon_VQSAL:
6190//ZZ insn = XXXXXXXX(0xF, X0010, BITS4(0,D,sz1,sz2), regN, regD,
6191//ZZ X0100, BITS4(N,Q,M,1), regM);
6192//ZZ break;
6193//ZZ default:
6194//ZZ goto bad;
6195//ZZ }
6196//ZZ *p++ = insn;
6197//ZZ goto done;
6198//ZZ }
6199//ZZ case ARMin_NShl64: {
6200//ZZ HReg regDreg = i->ARMin.NShl64.dst;
6201//ZZ HReg regMreg = i->ARMin.NShl64.src;
6202//ZZ UInt amt = i->ARMin.NShl64.amt;
6203//ZZ vassert(amt >= 1 && amt <= 63);
6204//ZZ vassert(hregClass(regDreg) == HRcFlt64);
6205//ZZ vassert(hregClass(regMreg) == HRcFlt64);
6206//ZZ UInt regD = dregNo(regDreg);
6207//ZZ UInt regM = dregNo(regMreg);
6208//ZZ UInt D = (regD >> 4) & 1;
6209//ZZ UInt Vd = regD & 0xF;
6210//ZZ UInt L = 1;
6211//ZZ UInt Q = 0; /* always 64-bit */
6212//ZZ UInt M = (regM >> 4) & 1;
6213//ZZ UInt Vm = regM & 0xF;
6214//ZZ UInt insn = XXXXXXXX(X1111,X0010, BITS4(1,D,(amt>>5)&1,(amt>>4)&1),
6215//ZZ amt & 0xF, Vd, X0101, BITS4(L,Q,M,1), Vm);
6216//ZZ *p++ = insn;
6217//ZZ goto done;
6218//ZZ }
6219 case ARM64in_VImmQ: {
6220 UInt rQ = qregNo(i->ARM64in.VImmQ.rQ);
6221 UShort imm = i->ARM64in.VImmQ.imm;
sewardjecde6972014-02-05 11:01:19 +00006222 if (imm == 0x0000) {
sewardjbbcf1882014-01-12 12:49:10 +00006223 /* movi rQ.4s, #0x0 == 0x4F 0x00 0x04 000 rQ */
6224 vassert(rQ < 32);
6225 *p++ = 0x4F000400 | rQ;
6226 goto done;
6227 }
sewardjfab09142014-02-10 10:28:13 +00006228 if (imm == 0x0001) {
6229 /* movi rD, #0xFF == 0x2F 0x00 0xE4 001 rD */
6230 vassert(rQ < 32);
6231 *p++ = 0x2F00E420 | rQ;
6232 goto done;
6233 }
sewardjecde6972014-02-05 11:01:19 +00006234 if (imm == 0x0003) {
6235 /* movi rD, #0xFFFF == 0x2F 0x00 0xE4 011 rD */
6236 vassert(rQ < 32);
6237 *p++ = 0x2F00E460 | rQ;
6238 goto done;
6239 }
6240 if (imm == 0x000F) {
6241 /* movi rD, #0xFFFFFFFF == 0x2F 0x00 0xE5 111 rD */
6242 vassert(rQ < 32);
6243 *p++ = 0x2F00E5E0 | rQ;
6244 goto done;
6245 }
sewardj9b1cf5e2014-03-01 11:16:57 +00006246 if (imm == 0x00FF) {
6247 /* movi rD, #0xFFFFFFFFFFFFFFFF == 0x2F 0x07 0xE7 111 rD */
6248 vassert(rQ < 32);
6249 *p++ = 0x2F07E7E0 | rQ;
6250 goto done;
6251 }
sewardjecde6972014-02-05 11:01:19 +00006252 goto bad; /* no other handled cases right now */
sewardjbbcf1882014-01-12 12:49:10 +00006253 }
6254
6255 case ARM64in_VDfromX: {
6256 /* INS Vd.D[0], rX
6257 0100 1110 0000 1000 0001 11 nn dd INS Vd.D[0], Xn
6258 This isn't wonderful, in the sense that the upper half of
6259 the vector register stays unchanged and thus the insn is
6260 data dependent on its output register. */
6261 UInt dd = dregNo(i->ARM64in.VDfromX.rD);
6262 UInt xx = iregNo(i->ARM64in.VDfromX.rX);
6263 vassert(xx < 31);
6264 *p++ = 0x4E081C00 | X_2_6_2_12_5_5(0,0,0,0,xx,dd);
6265 goto done;
6266 }
6267
6268 case ARM64in_VQfromXX: {
6269 /* What we really generate is a two insn sequence:
6270 INS Vd.D[0], Xlo; INS Vd.D[1], Xhi
6271 0100 1110 0000 1000 0001 11 nn dd INS Vd.D[0], Xn
6272 0100 1110 0001 1000 0001 11 nn dd INS Vd.D[1], Xn
6273 */
6274 UInt qq = qregNo(i->ARM64in.VQfromXX.rQ);
6275 UInt xhi = iregNo(i->ARM64in.VQfromXX.rXhi);
6276 UInt xlo = iregNo(i->ARM64in.VQfromXX.rXlo);
6277 vassert(xhi < 31 && xlo < 31);
6278 *p++ = 0x4E081C00 | X_2_6_2_12_5_5(0,0,0,0,xlo,qq);
6279 *p++ = 0x4E181C00 | X_2_6_2_12_5_5(0,0,0,0,xhi,qq);
6280 goto done;
6281 }
6282
6283 case ARM64in_VXfromQ: {
6284 /* 010 0111 0000 01000 001111 nn dd UMOV Xd, Vn.D[0]
6285 010 0111 0000 11000 001111 nn dd UMOV Xd, Vn.D[1]
6286 */
6287 UInt dd = iregNo(i->ARM64in.VXfromQ.rX);
6288 UInt nn = qregNo(i->ARM64in.VXfromQ.rQ);
6289 UInt laneNo = i->ARM64in.VXfromQ.laneNo;
6290 vassert(dd < 31);
6291 vassert(laneNo < 2);
6292 *p++ = X_3_8_5_6_5_5(X010, X01110000,
6293 laneNo == 1 ? X11000 : X01000, X001111, nn, dd);
6294 goto done;
6295 }
6296
6297 case ARM64in_VMov: {
6298 /* 000 11110 00 10000 00 10000 n d FMOV Sd, Sn
6299 000 11110 01 10000 00 10000 n d FMOV Dd, Dn
6300 010 01110 10 1 n 0 00111 n d MOV Vd.16b, Vn.16b
6301 */
6302 HReg rD = i->ARM64in.VMov.dst;
6303 HReg rN = i->ARM64in.VMov.src;
6304 switch (i->ARM64in.VMov.szB) {
6305 case 8: {
6306 UInt dd = dregNo(rD);
6307 UInt nn = dregNo(rN);
6308 *p++ = X_3_8_5_6_5_5(X000, X11110011, X00000, X010000, nn, dd);
6309 goto done;
6310 }
6311 default:
6312 break;
6313 }
6314 goto bad;
6315 }
6316//ZZ case ARMin_NeonImm: {
6317//ZZ UInt Q = (hregClass(i->ARMin.NeonImm.dst) == HRcVec128) ? 1 : 0;
6318//ZZ UInt regD = Q ? (qregNo(i->ARMin.NeonImm.dst) << 1) :
6319//ZZ dregNo(i->ARMin.NeonImm.dst);
6320//ZZ UInt D = regD >> 4;
6321//ZZ UInt imm = i->ARMin.NeonImm.imm->imm8;
6322//ZZ UInt tp = i->ARMin.NeonImm.imm->type;
6323//ZZ UInt j = imm >> 7;
6324//ZZ UInt imm3 = (imm >> 4) & 0x7;
6325//ZZ UInt imm4 = imm & 0xF;
6326//ZZ UInt cmode, op;
6327//ZZ UInt insn;
6328//ZZ regD &= 0xF;
6329//ZZ if (tp == 9)
6330//ZZ op = 1;
6331//ZZ else
6332//ZZ op = 0;
6333//ZZ switch (tp) {
6334//ZZ case 0:
6335//ZZ case 1:
6336//ZZ case 2:
6337//ZZ case 3:
6338//ZZ case 4:
6339//ZZ case 5:
6340//ZZ cmode = tp << 1;
6341//ZZ break;
6342//ZZ case 9:
6343//ZZ case 6:
6344//ZZ cmode = 14;
6345//ZZ break;
6346//ZZ case 7:
6347//ZZ cmode = 12;
6348//ZZ break;
6349//ZZ case 8:
6350//ZZ cmode = 13;
6351//ZZ break;
6352//ZZ case 10:
6353//ZZ cmode = 15;
6354//ZZ break;
6355//ZZ default:
6356//ZZ vpanic("ARMin_NeonImm");
6357//ZZ
6358//ZZ }
6359//ZZ insn = XXXXXXXX(0xF, BITS4(0,0,1,j), BITS4(1,D,0,0), imm3, regD,
6360//ZZ cmode, BITS4(0,Q,op,1), imm4);
6361//ZZ *p++ = insn;
6362//ZZ goto done;
6363//ZZ }
6364//ZZ case ARMin_NCMovQ: {
6365//ZZ UInt cc = (UInt)i->ARMin.NCMovQ.cond;
6366//ZZ UInt qM = qregNo(i->ARMin.NCMovQ.src) << 1;
6367//ZZ UInt qD = qregNo(i->ARMin.NCMovQ.dst) << 1;
6368//ZZ UInt vM = qM & 0xF;
6369//ZZ UInt vD = qD & 0xF;
6370//ZZ UInt M = (qM >> 4) & 1;
6371//ZZ UInt D = (qD >> 4) & 1;
6372//ZZ vassert(cc < 16 && cc != ARMcc_AL && cc != ARMcc_NV);
6373//ZZ /* b!cc here+8: !cc A00 0000 */
6374//ZZ UInt insn = XXXXXXXX(cc ^ 1, 0xA, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0);
6375//ZZ *p++ = insn;
6376//ZZ /* vmov qD, qM */
6377//ZZ insn = XXXXXXXX(0xF, 0x2, BITS4(0,D,1,0),
6378//ZZ vM, vD, BITS4(0,0,0,1), BITS4(M,1,M,1), vM);
6379//ZZ *p++ = insn;
6380//ZZ goto done;
6381//ZZ }
6382//ZZ case ARMin_Add32: {
6383//ZZ UInt regD = iregNo(i->ARMin.Add32.rD);
6384//ZZ UInt regN = iregNo(i->ARMin.Add32.rN);
6385//ZZ UInt imm32 = i->ARMin.Add32.imm32;
6386//ZZ vassert(regD != regN);
6387//ZZ /* MOV regD, imm32 */
6388//ZZ p = imm32_to_iregNo((UInt *)p, regD, imm32);
6389//ZZ /* ADD regD, regN, regD */
6390//ZZ UInt insn = XXXXXXXX(0xE, 0, X1000, regN, regD, 0, 0, regD);
6391//ZZ *p++ = insn;
6392//ZZ goto done;
6393//ZZ }
6394
6395 case ARM64in_EvCheck: {
6396 /* The sequence is fixed (canned) except for the two amodes
6397 supplied by the insn. These don't change the length, though.
6398 We generate:
6399 ldr w9, [x21 + #8] 8 == offsetof(host_EvC_COUNTER)
6400 subs w9, w9, #1
6401 str w9, [x21 + #8] 8 == offsetof(host_EvC_COUNTER)
6402 bpl nofail
6403 ldr x9, [x21 + #0] 0 == offsetof(host_EvC_FAILADDR)
6404 br x9
6405 nofail:
6406 */
6407 UInt* p0 = p;
6408 p = do_load_or_store32(p, True/*isLoad*/, /*w*/9,
6409 i->ARM64in.EvCheck.amCounter);
6410 *p++ = 0x71000529; /* subs w9, w9, #1 */
6411 p = do_load_or_store32(p, False/*!isLoad*/, /*w*/9,
6412 i->ARM64in.EvCheck.amCounter);
6413 *p++ = 0x54000065; /* bpl nofail */
6414 p = do_load_or_store64(p, True/*isLoad*/, /*x*/9,
6415 i->ARM64in.EvCheck.amFailAddr);
6416 *p++ = 0xD61F0120; /* br x9 */
6417 /* nofail: */
6418
6419 /* Crosscheck */
6420 vassert(evCheckSzB_ARM64() == (UChar*)p - (UChar*)p0);
6421 goto done;
6422 }
6423
6424//ZZ case ARMin_ProfInc: {
6425//ZZ /* We generate:
6426//ZZ (ctrP is unknown now, so use 0x65556555 in the
6427//ZZ expectation that a later call to LibVEX_patchProfCtr
6428//ZZ will be used to fill in the immediate fields once the
6429//ZZ right value is known.)
6430//ZZ movw r12, lo16(0x65556555)
6431//ZZ movt r12, lo16(0x65556555)
6432//ZZ ldr r11, [r12]
6433//ZZ adds r11, r11, #1
6434//ZZ str r11, [r12]
6435//ZZ ldr r11, [r12+4]
6436//ZZ adc r11, r11, #0
6437//ZZ str r11, [r12+4]
6438//ZZ */
6439//ZZ p = imm32_to_iregNo_EXACTLY2(p, /*r*/12, 0x65556555);
6440//ZZ *p++ = 0xE59CB000;
6441//ZZ *p++ = 0xE29BB001;
6442//ZZ *p++ = 0xE58CB000;
6443//ZZ *p++ = 0xE59CB004;
6444//ZZ *p++ = 0xE2ABB000;
6445//ZZ *p++ = 0xE58CB004;
6446//ZZ /* Tell the caller .. */
6447//ZZ vassert(!(*is_profInc));
6448//ZZ *is_profInc = True;
6449//ZZ goto done;
6450//ZZ }
6451
6452 /* ... */
6453 default:
6454 goto bad;
6455 }
6456
6457 bad:
6458 ppARM64Instr(i);
6459 vpanic("emit_ARM64Instr");
6460 /*NOTREACHED*/
6461
6462 done:
6463 vassert(((UChar*)p) - &buf[0] <= 36);
6464 return ((UChar*)p) - &buf[0];
6465}
6466
6467
6468/* How big is an event check? See case for ARM64in_EvCheck in
6469 emit_ARM64Instr just above. That crosschecks what this returns, so
6470 we can tell if we're inconsistent. */
6471Int evCheckSzB_ARM64 ( void )
6472{
6473 return 24;
6474}
6475
6476
6477/* NB: what goes on here has to be very closely coordinated with the
6478 emitInstr case for XDirect, above. */
6479VexInvalRange chainXDirect_ARM64 ( void* place_to_chain,
6480 void* disp_cp_chain_me_EXPECTED,
6481 void* place_to_jump_to )
6482{
6483 /* What we're expecting to see is:
6484 movw x9, disp_cp_chain_me_to_EXPECTED[15:0]
6485 movk x9, disp_cp_chain_me_to_EXPECTED[31:15], lsl 16
6486 movk x9, disp_cp_chain_me_to_EXPECTED[47:32], lsl 32
6487 movk x9, disp_cp_chain_me_to_EXPECTED[63:48], lsl 48
6488 blr x9
6489 viz
6490 <16 bytes generated by imm64_to_iregNo_EXACTLY4>
6491 D6 3F 01 20
6492 */
6493 UInt* p = (UInt*)place_to_chain;
6494 vassert(0 == (3 & (HWord)p));
6495 vassert(is_imm64_to_iregNo_EXACTLY4(
6496 p, /*x*/9, Ptr_to_ULong(disp_cp_chain_me_EXPECTED)));
6497 vassert(p[4] == 0xD63F0120);
sewardjc6acaa42014-02-19 17:42:59 +00006498
sewardjbbcf1882014-01-12 12:49:10 +00006499 /* And what we want to change it to is:
6500 movw x9, place_to_jump_to[15:0]
6501 movk x9, place_to_jump_to[31:15], lsl 16
6502 movk x9, place_to_jump_to[47:32], lsl 32
6503 movk x9, place_to_jump_to[63:48], lsl 48
6504 br x9
6505 viz
6506 <16 bytes generated by imm64_to_iregNo_EXACTLY4>
6507 D6 1F 01 20
6508
6509 The replacement has the same length as the original.
6510 */
sewardjbbcf1882014-01-12 12:49:10 +00006511 (void)imm64_to_iregNo_EXACTLY4(
6512 p, /*x*/9, Ptr_to_ULong(place_to_jump_to));
6513 p[4] = 0xD61F0120;
6514
6515 VexInvalRange vir = {(HWord)p, 20};
6516 return vir;
6517}
6518
6519
sewardjc6acaa42014-02-19 17:42:59 +00006520/* NB: what goes on here has to be very closely coordinated with the
6521 emitInstr case for XDirect, above. */
6522VexInvalRange unchainXDirect_ARM64 ( void* place_to_unchain,
6523 void* place_to_jump_to_EXPECTED,
6524 void* disp_cp_chain_me )
6525{
6526 /* What we're expecting to see is:
6527 movw x9, place_to_jump_to_EXPECTED[15:0]
6528 movk x9, place_to_jump_to_EXPECTED[31:15], lsl 16
6529 movk x9, place_to_jump_to_EXPECTED[47:32], lsl 32
6530 movk x9, place_to_jump_to_EXPECTED[63:48], lsl 48
6531 br x9
6532 viz
6533 <16 bytes generated by imm64_to_iregNo_EXACTLY4>
6534 D6 1F 01 20
6535 */
6536 UInt* p = (UInt*)place_to_unchain;
6537 vassert(0 == (3 & (HWord)p));
6538 vassert(is_imm64_to_iregNo_EXACTLY4(
6539 p, /*x*/9, Ptr_to_ULong(place_to_jump_to_EXPECTED)));
6540 vassert(p[4] == 0xD61F0120);
6541
6542 /* And what we want to change it to is:
6543 movw x9, disp_cp_chain_me_to[15:0]
6544 movk x9, disp_cp_chain_me_to[31:15], lsl 16
6545 movk x9, disp_cp_chain_me_to[47:32], lsl 32
6546 movk x9, disp_cp_chain_me_to[63:48], lsl 48
6547 blr x9
6548 viz
6549 <16 bytes generated by imm64_to_iregNo_EXACTLY4>
6550 D6 3F 01 20
6551 */
6552 (void)imm64_to_iregNo_EXACTLY4(
6553 p, /*x*/9, Ptr_to_ULong(disp_cp_chain_me));
6554 p[4] = 0xD63F0120;
6555
6556 VexInvalRange vir = {(HWord)p, 20};
6557 return vir;
6558}
6559
6560
sewardjbbcf1882014-01-12 12:49:10 +00006561//ZZ /* Patch the counter address into a profile inc point, as previously
6562//ZZ created by the ARMin_ProfInc case for emit_ARMInstr. */
6563//ZZ VexInvalRange patchProfInc_ARM ( void* place_to_patch,
6564//ZZ ULong* location_of_counter )
6565//ZZ {
6566//ZZ vassert(sizeof(ULong*) == 4);
6567//ZZ UInt* p = (UInt*)place_to_patch;
6568//ZZ vassert(0 == (3 & (HWord)p));
6569//ZZ vassert(is_imm32_to_iregNo_EXACTLY2(p, /*r*/12, 0x65556555));
6570//ZZ vassert(p[2] == 0xE59CB000);
6571//ZZ vassert(p[3] == 0xE29BB001);
6572//ZZ vassert(p[4] == 0xE58CB000);
6573//ZZ vassert(p[5] == 0xE59CB004);
6574//ZZ vassert(p[6] == 0xE2ABB000);
6575//ZZ vassert(p[7] == 0xE58CB004);
6576//ZZ imm32_to_iregNo_EXACTLY2(p, /*r*/12,
6577//ZZ (UInt)Ptr_to_ULong(location_of_counter));
6578//ZZ VexInvalRange vir = {(HWord)p, 8};
6579//ZZ return vir;
6580//ZZ }
6581//ZZ
6582//ZZ
6583//ZZ #undef BITS4
6584//ZZ #undef X0000
6585//ZZ #undef X0001
6586//ZZ #undef X0010
6587//ZZ #undef X0011
6588//ZZ #undef X0100
6589//ZZ #undef X0101
6590//ZZ #undef X0110
6591//ZZ #undef X0111
6592//ZZ #undef X1000
6593//ZZ #undef X1001
6594//ZZ #undef X1010
6595//ZZ #undef X1011
6596//ZZ #undef X1100
6597//ZZ #undef X1101
6598//ZZ #undef X1110
6599//ZZ #undef X1111
6600//ZZ #undef XXXXX___
6601//ZZ #undef XXXXXX__
6602//ZZ #undef XXX___XX
6603//ZZ #undef XXXXX__X
6604//ZZ #undef XXXXXXXX
6605//ZZ #undef XX______
6606
6607/*---------------------------------------------------------------*/
6608/*--- end host_arm64_defs.c ---*/
6609/*---------------------------------------------------------------*/