blob: 71135b9a3ead093b7be3365852f7848ea66190ea [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); }
sewardj76ac4762014-06-20 08:30:21 +0000125HReg hregARM64_Q19 ( void ) { return mkHReg(19, HRcVec128, False); }
126HReg hregARM64_Q20 ( void ) { return mkHReg(20, HRcVec128, False); }
sewardjbbcf1882014-01-12 12:49:10 +0000127//ZZ HReg hregARM_Q11 ( void ) { return mkHReg(11, HRcVec128, False); }
128//ZZ HReg hregARM_Q12 ( void ) { return mkHReg(12, HRcVec128, False); }
129//ZZ HReg hregARM_Q13 ( void ) { return mkHReg(13, HRcVec128, False); }
130//ZZ HReg hregARM_Q14 ( void ) { return mkHReg(14, HRcVec128, False); }
131//ZZ HReg hregARM_Q15 ( void ) { return mkHReg(15, HRcVec128, False); }
132
133void getAllocableRegs_ARM64 ( Int* nregs, HReg** arr )
134{
135 Int i = 0;
sewardj76ac4762014-06-20 08:30:21 +0000136 *nregs = 26;
sewardjbbcf1882014-01-12 12:49:10 +0000137 *arr = LibVEX_Alloc(*nregs * sizeof(HReg));
138
139 // callee saves ones (22 to 28) are listed first, since we prefer
140 // them if they're available
141 (*arr)[i++] = hregARM64_X22();
142 (*arr)[i++] = hregARM64_X23();
143 (*arr)[i++] = hregARM64_X24();
144 (*arr)[i++] = hregARM64_X25();
145 (*arr)[i++] = hregARM64_X26();
146 (*arr)[i++] = hregARM64_X27();
147 (*arr)[i++] = hregARM64_X28();
148
149 (*arr)[i++] = hregARM64_X0();
150 (*arr)[i++] = hregARM64_X1();
151 (*arr)[i++] = hregARM64_X2();
152 (*arr)[i++] = hregARM64_X3();
153 (*arr)[i++] = hregARM64_X4();
154 (*arr)[i++] = hregARM64_X5();
155 (*arr)[i++] = hregARM64_X6();
156 (*arr)[i++] = hregARM64_X7();
157 // X8 .. who knows.
158 // X9 is a chaining/spill temporary, not available to regalloc.
159
160 // Do we really need all these?
161 //(*arr)[i++] = hregARM64_X10();
162 //(*arr)[i++] = hregARM64_X11();
163 //(*arr)[i++] = hregARM64_X12();
164 //(*arr)[i++] = hregARM64_X13();
165 //(*arr)[i++] = hregARM64_X14();
166 //(*arr)[i++] = hregARM64_X15();
167 // X21 is the guest state pointer, not available to regalloc.
168
169 // vector regs. Unfortunately not callee-saved.
170 (*arr)[i++] = hregARM64_Q16();
171 (*arr)[i++] = hregARM64_Q17();
172 (*arr)[i++] = hregARM64_Q18();
sewardj76ac4762014-06-20 08:30:21 +0000173 (*arr)[i++] = hregARM64_Q19();
174 (*arr)[i++] = hregARM64_Q20();
sewardjbbcf1882014-01-12 12:49:10 +0000175
176 // F64 regs, all of which are callee-saved
177 (*arr)[i++] = hregARM64_D8();
178 (*arr)[i++] = hregARM64_D9();
179 (*arr)[i++] = hregARM64_D10();
180 (*arr)[i++] = hregARM64_D11();
181 (*arr)[i++] = hregARM64_D12();
182 (*arr)[i++] = hregARM64_D13();
183
184 // unavail: x21 as GSP
185 // x9 is used as a spill/reload/chaining/call temporary
186 // x8 is unassigned
187 // x30 as LR
188 // x31 because dealing with the SP-vs-ZR overloading is too
189 // confusing, and we don't need to do so, so let's just avoid
190 // the problem
191 //
192 // Currently, we have 15 allocatable integer registers:
193 // 0 1 2 3 4 5 6 7 22 23 24 25 26 27 28
194 //
195 // Hence for the allocatable integer registers we have:
196 //
197 // callee-saved: 22 23 24 25 26 27 28
198 // caller-saved: 0 1 2 3 4 5 6 7
199 //
200 // If the set of available registers changes or if the e/r status
201 // changes, be sure to re-check/sync the definition of
202 // getHRegUsage for ARMInstr_Call too.
203 vassert(i == *nregs);
204}
205
206
sewardjbbcf1882014-01-12 12:49:10 +0000207/* --------- Condition codes, ARM64 encoding. --------- */
208
209static const HChar* showARM64CondCode ( ARM64CondCode cond ) {
210 switch (cond) {
211 case ARM64cc_EQ: return "eq";
212 case ARM64cc_NE: return "ne";
213 case ARM64cc_CS: return "cs";
214 case ARM64cc_CC: return "cc";
215 case ARM64cc_MI: return "mi";
216 case ARM64cc_PL: return "pl";
217 case ARM64cc_VS: return "vs";
218 case ARM64cc_VC: return "vc";
219 case ARM64cc_HI: return "hi";
220 case ARM64cc_LS: return "ls";
221 case ARM64cc_GE: return "ge";
222 case ARM64cc_LT: return "lt";
223 case ARM64cc_GT: return "gt";
224 case ARM64cc_LE: return "le";
225 case ARM64cc_AL: return "al"; // default
226 case ARM64cc_NV: return "nv";
227 default: vpanic("showARM64CondCode");
228 }
229}
230
231
232/* --------- Memory address expressions (amodes). --------- */
233
234ARM64AMode* ARM64AMode_RI9 ( HReg reg, Int simm9 ) {
235 ARM64AMode* am = LibVEX_Alloc(sizeof(ARM64AMode));
236 am->tag = ARM64am_RI9;
237 am->ARM64am.RI9.reg = reg;
238 am->ARM64am.RI9.simm9 = simm9;
239 vassert(-256 <= simm9 && simm9 <= 255);
240 return am;
241}
242
243ARM64AMode* ARM64AMode_RI12 ( HReg reg, Int uimm12, UChar szB ) {
244 ARM64AMode* am = LibVEX_Alloc(sizeof(ARM64AMode));
245 am->tag = ARM64am_RI12;
246 am->ARM64am.RI12.reg = reg;
247 am->ARM64am.RI12.uimm12 = uimm12;
248 am->ARM64am.RI12.szB = szB;
249 vassert(uimm12 >= 0 && uimm12 <= 4095);
250 switch (szB) {
251 case 1: case 2: case 4: case 8: break;
252 default: vassert(0);
253 }
254 return am;
255}
256
257ARM64AMode* ARM64AMode_RR ( HReg base, HReg index ) {
258 ARM64AMode* am = LibVEX_Alloc(sizeof(ARM64AMode));
259 am->tag = ARM64am_RR;
260 am->ARM64am.RR.base = base;
261 am->ARM64am.RR.index = index;
262 return am;
263}
264
265static void ppARM64AMode ( ARM64AMode* am ) {
266 switch (am->tag) {
267 case ARM64am_RI9:
268 vex_printf("%d(", am->ARM64am.RI9.simm9);
269 ppHRegARM64(am->ARM64am.RI9.reg);
270 vex_printf(")");
271 break;
272 case ARM64am_RI12:
273 vex_printf("%u(", (UInt)am->ARM64am.RI12.szB
274 * (UInt)am->ARM64am.RI12.uimm12);
275 ppHRegARM64(am->ARM64am.RI12.reg);
276 vex_printf(")");
277 break;
278 case ARM64am_RR:
279 vex_printf("(");
280 ppHRegARM64(am->ARM64am.RR.base);
281 vex_printf(",");
282 ppHRegARM64(am->ARM64am.RR.index);
283 vex_printf(")");
284 break;
285 default:
286 vassert(0);
287 }
288}
289
290static void addRegUsage_ARM64AMode ( HRegUsage* u, ARM64AMode* am ) {
291 switch (am->tag) {
292 case ARM64am_RI9:
293 addHRegUse(u, HRmRead, am->ARM64am.RI9.reg);
294 return;
295 case ARM64am_RI12:
296 addHRegUse(u, HRmRead, am->ARM64am.RI12.reg);
297 return;
298 case ARM64am_RR:
299 addHRegUse(u, HRmRead, am->ARM64am.RR.base);
300 addHRegUse(u, HRmRead, am->ARM64am.RR.index);
301 return;
302 default:
303 vpanic("addRegUsage_ARM64Amode");
304 }
305}
306
307static void mapRegs_ARM64AMode ( HRegRemap* m, ARM64AMode* am ) {
308 switch (am->tag) {
309 case ARM64am_RI9:
310 am->ARM64am.RI9.reg = lookupHRegRemap(m, am->ARM64am.RI9.reg);
311 return;
312 case ARM64am_RI12:
313 am->ARM64am.RI12.reg = lookupHRegRemap(m, am->ARM64am.RI12.reg);
314 return;
315 case ARM64am_RR:
316 am->ARM64am.RR.base = lookupHRegRemap(m, am->ARM64am.RR.base);
317 am->ARM64am.RR.index = lookupHRegRemap(m, am->ARM64am.RR.index);
318 return;
319 default:
320 vpanic("mapRegs_ARM64Amode");
321 }
322}
323
324
325//ZZ /* --------- Mem AModes: Addressing Mode 2 --------- */
326//ZZ
327//ZZ ARMAMode2* ARMAMode2_RI ( HReg reg, Int simm9 ) {
328//ZZ ARMAMode2* am = LibVEX_Alloc(sizeof(ARMAMode2));
329//ZZ am->tag = ARMam2_RI;
330//ZZ am->ARMam2.RI.reg = reg;
331//ZZ am->ARMam2.RI.simm9 = simm9;
332//ZZ vassert(-255 <= simm9 && simm9 <= 255);
333//ZZ return am;
334//ZZ }
335//ZZ ARMAMode2* ARMAMode2_RR ( HReg base, HReg index ) {
336//ZZ ARMAMode2* am = LibVEX_Alloc(sizeof(ARMAMode2));
337//ZZ am->tag = ARMam2_RR;
338//ZZ am->ARMam2.RR.base = base;
339//ZZ am->ARMam2.RR.index = index;
340//ZZ return am;
341//ZZ }
342//ZZ
343//ZZ void ppARMAMode2 ( ARMAMode2* am ) {
344//ZZ switch (am->tag) {
345//ZZ case ARMam2_RI:
346//ZZ vex_printf("%d(", am->ARMam2.RI.simm9);
347//ZZ ppHRegARM(am->ARMam2.RI.reg);
348//ZZ vex_printf(")");
349//ZZ break;
350//ZZ case ARMam2_RR:
351//ZZ vex_printf("(");
352//ZZ ppHRegARM(am->ARMam2.RR.base);
353//ZZ vex_printf(",");
354//ZZ ppHRegARM(am->ARMam2.RR.index);
355//ZZ vex_printf(")");
356//ZZ break;
357//ZZ default:
358//ZZ vassert(0);
359//ZZ }
360//ZZ }
361//ZZ
362//ZZ static void addRegUsage_ARMAMode2 ( HRegUsage* u, ARMAMode2* am ) {
363//ZZ switch (am->tag) {
364//ZZ case ARMam2_RI:
365//ZZ addHRegUse(u, HRmRead, am->ARMam2.RI.reg);
366//ZZ return;
367//ZZ case ARMam2_RR:
368//ZZ // addHRegUse(u, HRmRead, am->ARMam2.RR.base);
369//ZZ // addHRegUse(u, HRmRead, am->ARMam2.RR.index);
370//ZZ // return;
371//ZZ default:
372//ZZ vpanic("addRegUsage_ARMAmode2");
373//ZZ }
374//ZZ }
375//ZZ
376//ZZ static void mapRegs_ARMAMode2 ( HRegRemap* m, ARMAMode2* am ) {
377//ZZ switch (am->tag) {
378//ZZ case ARMam2_RI:
379//ZZ am->ARMam2.RI.reg = lookupHRegRemap(m, am->ARMam2.RI.reg);
380//ZZ return;
381//ZZ case ARMam2_RR:
382//ZZ //am->ARMam2.RR.base =lookupHRegRemap(m, am->ARMam2.RR.base);
383//ZZ //am->ARMam2.RR.index = lookupHRegRemap(m, am->ARMam2.RR.index);
384//ZZ //return;
385//ZZ default:
386//ZZ vpanic("mapRegs_ARMAmode2");
387//ZZ }
388//ZZ }
389//ZZ
390//ZZ
391//ZZ /* --------- Mem AModes: Addressing Mode VFP --------- */
392//ZZ
393//ZZ ARMAModeV* mkARMAModeV ( HReg reg, Int simm11 ) {
394//ZZ ARMAModeV* am = LibVEX_Alloc(sizeof(ARMAModeV));
395//ZZ vassert(simm11 >= -1020 && simm11 <= 1020);
396//ZZ vassert(0 == (simm11 & 3));
397//ZZ am->reg = reg;
398//ZZ am->simm11 = simm11;
399//ZZ return am;
400//ZZ }
401//ZZ
402//ZZ void ppARMAModeV ( ARMAModeV* am ) {
403//ZZ vex_printf("%d(", am->simm11);
404//ZZ ppHRegARM(am->reg);
405//ZZ vex_printf(")");
406//ZZ }
407//ZZ
408//ZZ static void addRegUsage_ARMAModeV ( HRegUsage* u, ARMAModeV* am ) {
409//ZZ addHRegUse(u, HRmRead, am->reg);
410//ZZ }
411//ZZ
412//ZZ static void mapRegs_ARMAModeV ( HRegRemap* m, ARMAModeV* am ) {
413//ZZ am->reg = lookupHRegRemap(m, am->reg);
414//ZZ }
415//ZZ
416//ZZ
417//ZZ /* --------- Mem AModes: Addressing Mode Neon ------- */
418//ZZ
419//ZZ ARMAModeN *mkARMAModeN_RR ( HReg rN, HReg rM ) {
420//ZZ ARMAModeN* am = LibVEX_Alloc(sizeof(ARMAModeN));
421//ZZ am->tag = ARMamN_RR;
422//ZZ am->ARMamN.RR.rN = rN;
423//ZZ am->ARMamN.RR.rM = rM;
424//ZZ return am;
425//ZZ }
426//ZZ
427//ZZ ARMAModeN *mkARMAModeN_R ( HReg rN ) {
428//ZZ ARMAModeN* am = LibVEX_Alloc(sizeof(ARMAModeN));
429//ZZ am->tag = ARMamN_R;
430//ZZ am->ARMamN.R.rN = rN;
431//ZZ return am;
432//ZZ }
433//ZZ
434//ZZ static void addRegUsage_ARMAModeN ( HRegUsage* u, ARMAModeN* am ) {
435//ZZ if (am->tag == ARMamN_R) {
436//ZZ addHRegUse(u, HRmRead, am->ARMamN.R.rN);
437//ZZ } else {
438//ZZ addHRegUse(u, HRmRead, am->ARMamN.RR.rN);
439//ZZ addHRegUse(u, HRmRead, am->ARMamN.RR.rM);
440//ZZ }
441//ZZ }
442//ZZ
443//ZZ static void mapRegs_ARMAModeN ( HRegRemap* m, ARMAModeN* am ) {
444//ZZ if (am->tag == ARMamN_R) {
445//ZZ am->ARMamN.R.rN = lookupHRegRemap(m, am->ARMamN.R.rN);
446//ZZ } else {
447//ZZ am->ARMamN.RR.rN = lookupHRegRemap(m, am->ARMamN.RR.rN);
448//ZZ am->ARMamN.RR.rM = lookupHRegRemap(m, am->ARMamN.RR.rM);
449//ZZ }
450//ZZ }
451//ZZ
452//ZZ void ppARMAModeN ( ARMAModeN* am ) {
453//ZZ vex_printf("[");
454//ZZ if (am->tag == ARMamN_R) {
455//ZZ ppHRegARM(am->ARMamN.R.rN);
456//ZZ } else {
457//ZZ ppHRegARM(am->ARMamN.RR.rN);
458//ZZ }
459//ZZ vex_printf("]");
460//ZZ if (am->tag == ARMamN_RR) {
461//ZZ vex_printf(", ");
462//ZZ ppHRegARM(am->ARMamN.RR.rM);
463//ZZ }
464//ZZ }
465
466
467/* --------- Reg or uimm12<<{0,12} operands --------- */
468
469ARM64RIA* ARM64RIA_I12 ( UShort imm12, UChar shift ) {
470 ARM64RIA* riA = LibVEX_Alloc(sizeof(ARM64RIA));
471 riA->tag = ARM64riA_I12;
472 riA->ARM64riA.I12.imm12 = imm12;
473 riA->ARM64riA.I12.shift = shift;
474 vassert(imm12 < 4096);
475 vassert(shift == 0 || shift == 12);
476 return riA;
477}
478ARM64RIA* ARM64RIA_R ( HReg reg ) {
479 ARM64RIA* riA = LibVEX_Alloc(sizeof(ARM64RIA));
480 riA->tag = ARM64riA_R;
481 riA->ARM64riA.R.reg = reg;
482 return riA;
483}
484
485static void ppARM64RIA ( ARM64RIA* riA ) {
486 switch (riA->tag) {
487 case ARM64riA_I12:
488 vex_printf("#%u",(UInt)(riA->ARM64riA.I12.imm12
489 << riA->ARM64riA.I12.shift));
490 break;
491 case ARM64riA_R:
492 ppHRegARM64(riA->ARM64riA.R.reg);
493 break;
494 default:
495 vassert(0);
496 }
497}
498
499static void addRegUsage_ARM64RIA ( HRegUsage* u, ARM64RIA* riA ) {
500 switch (riA->tag) {
501 case ARM64riA_I12:
502 return;
503 case ARM64riA_R:
504 addHRegUse(u, HRmRead, riA->ARM64riA.R.reg);
505 return;
506 default:
507 vpanic("addRegUsage_ARM64RIA");
508 }
509}
510
511static void mapRegs_ARM64RIA ( HRegRemap* m, ARM64RIA* riA ) {
512 switch (riA->tag) {
513 case ARM64riA_I12:
514 return;
515 case ARM64riA_R:
516 riA->ARM64riA.R.reg = lookupHRegRemap(m, riA->ARM64riA.R.reg);
517 return;
518 default:
519 vpanic("mapRegs_ARM64RIA");
520 }
521}
522
523
524/* --------- Reg or "bitfield" (logic immediate) operands --------- */
525
526ARM64RIL* ARM64RIL_I13 ( UChar bitN, UChar immR, UChar immS ) {
527 ARM64RIL* riL = LibVEX_Alloc(sizeof(ARM64RIL));
528 riL->tag = ARM64riL_I13;
529 riL->ARM64riL.I13.bitN = bitN;
530 riL->ARM64riL.I13.immR = immR;
531 riL->ARM64riL.I13.immS = immS;
532 vassert(bitN < 2);
533 vassert(immR < 64);
534 vassert(immS < 64);
535 return riL;
536}
537ARM64RIL* ARM64RIL_R ( HReg reg ) {
538 ARM64RIL* riL = LibVEX_Alloc(sizeof(ARM64RIL));
539 riL->tag = ARM64riL_R;
540 riL->ARM64riL.R.reg = reg;
541 return riL;
542}
543
544static void ppARM64RIL ( ARM64RIL* riL ) {
545 switch (riL->tag) {
546 case ARM64riL_I13:
547 vex_printf("#nrs(%u,%u,%u)",
548 (UInt)riL->ARM64riL.I13.bitN,
549 (UInt)riL->ARM64riL.I13.immR,
550 (UInt)riL->ARM64riL.I13.immS);
551 break;
552 case ARM64riL_R:
553 ppHRegARM64(riL->ARM64riL.R.reg);
554 break;
555 default:
556 vassert(0);
557 }
558}
559
560static void addRegUsage_ARM64RIL ( HRegUsage* u, ARM64RIL* riL ) {
561 switch (riL->tag) {
562 case ARM64riL_I13:
563 return;
564 case ARM64riL_R:
565 addHRegUse(u, HRmRead, riL->ARM64riL.R.reg);
566 return;
567 default:
568 vpanic("addRegUsage_ARM64RIL");
569 }
570}
571
572static void mapRegs_ARM64RIL ( HRegRemap* m, ARM64RIL* riL ) {
573 switch (riL->tag) {
574 case ARM64riL_I13:
575 return;
576 case ARM64riL_R:
577 riL->ARM64riL.R.reg = lookupHRegRemap(m, riL->ARM64riL.R.reg);
578 return;
579 default:
580 vpanic("mapRegs_ARM64RIL");
581 }
582}
583
584
585/* --------------- Reg or uimm6 operands --------------- */
586
587ARM64RI6* ARM64RI6_I6 ( UInt imm6 ) {
588 ARM64RI6* ri6 = LibVEX_Alloc(sizeof(ARM64RI6));
589 ri6->tag = ARM64ri6_I6;
590 ri6->ARM64ri6.I6.imm6 = imm6;
591 vassert(imm6 > 0 && imm6 < 64);
592 return ri6;
593}
594ARM64RI6* ARM64RI6_R ( HReg reg ) {
595 ARM64RI6* ri6 = LibVEX_Alloc(sizeof(ARM64RI6));
596 ri6->tag = ARM64ri6_R;
597 ri6->ARM64ri6.R.reg = reg;
598 return ri6;
599}
600
601static void ppARM64RI6 ( ARM64RI6* ri6 ) {
602 switch (ri6->tag) {
603 case ARM64ri6_I6:
604 vex_printf("#%u", ri6->ARM64ri6.I6.imm6);
605 break;
606 case ARM64ri6_R:
607 ppHRegARM64(ri6->ARM64ri6.R.reg);
608 break;
609 default:
610 vassert(0);
611 }
612}
613
614static void addRegUsage_ARM64RI6 ( HRegUsage* u, ARM64RI6* ri6 ) {
615 switch (ri6->tag) {
616 case ARM64ri6_I6:
617 return;
618 case ARM64ri6_R:
619 addHRegUse(u, HRmRead, ri6->ARM64ri6.R.reg);
620 return;
621 default:
622 vpanic("addRegUsage_ARM64RI6");
623 }
624}
625
626static void mapRegs_ARM64RI6 ( HRegRemap* m, ARM64RI6* ri6 ) {
627 switch (ri6->tag) {
628 case ARM64ri6_I6:
629 return;
630 case ARM64ri6_R:
631 ri6->ARM64ri6.R.reg = lookupHRegRemap(m, ri6->ARM64ri6.R.reg);
632 return;
633 default:
634 vpanic("mapRegs_ARM64RI6");
635 }
636}
637
638
639//ZZ /* -------- Neon Immediate operatnd --------- */
640//ZZ
641//ZZ ARMNImm* ARMNImm_TI ( UInt type, UInt imm8 ) {
642//ZZ ARMNImm* i = LibVEX_Alloc(sizeof(ARMNImm));
643//ZZ i->type = type;
644//ZZ i->imm8 = imm8;
645//ZZ return i;
646//ZZ }
647//ZZ
648//ZZ ULong ARMNImm_to_Imm64 ( ARMNImm* imm ) {
649//ZZ int i, j;
650//ZZ ULong y, x = imm->imm8;
651//ZZ switch (imm->type) {
652//ZZ case 3:
653//ZZ x = x << 8; /* fallthrough */
654//ZZ case 2:
655//ZZ x = x << 8; /* fallthrough */
656//ZZ case 1:
657//ZZ x = x << 8; /* fallthrough */
658//ZZ case 0:
659//ZZ return (x << 32) | x;
660//ZZ case 5:
661//ZZ case 6:
662//ZZ if (imm->type == 5)
663//ZZ x = x << 8;
664//ZZ else
665//ZZ x = (x << 8) | x;
666//ZZ /* fallthrough */
667//ZZ case 4:
668//ZZ x = (x << 16) | x;
669//ZZ return (x << 32) | x;
670//ZZ case 8:
671//ZZ x = (x << 8) | 0xFF;
672//ZZ /* fallthrough */
673//ZZ case 7:
674//ZZ x = (x << 8) | 0xFF;
675//ZZ return (x << 32) | x;
676//ZZ case 9:
677//ZZ x = 0;
678//ZZ for (i = 7; i >= 0; i--) {
679//ZZ y = ((ULong)imm->imm8 >> i) & 1;
680//ZZ for (j = 0; j < 8; j++) {
681//ZZ x = (x << 1) | y;
682//ZZ }
683//ZZ }
684//ZZ return x;
685//ZZ case 10:
686//ZZ x |= (x & 0x80) << 5;
687//ZZ x |= (~x & 0x40) << 5;
688//ZZ x &= 0x187F; /* 0001 1000 0111 1111 */
689//ZZ x |= (x & 0x40) << 4;
690//ZZ x |= (x & 0x40) << 3;
691//ZZ x |= (x & 0x40) << 2;
692//ZZ x |= (x & 0x40) << 1;
693//ZZ x = x << 19;
694//ZZ x = (x << 32) | x;
695//ZZ return x;
696//ZZ default:
697//ZZ vpanic("ARMNImm_to_Imm64");
698//ZZ }
699//ZZ }
700//ZZ
701//ZZ ARMNImm* Imm64_to_ARMNImm ( ULong x ) {
702//ZZ ARMNImm tmp;
703//ZZ if ((x & 0xFFFFFFFF) == (x >> 32)) {
704//ZZ if ((x & 0xFFFFFF00) == 0)
705//ZZ return ARMNImm_TI(0, x & 0xFF);
706//ZZ if ((x & 0xFFFF00FF) == 0)
707//ZZ return ARMNImm_TI(1, (x >> 8) & 0xFF);
708//ZZ if ((x & 0xFF00FFFF) == 0)
709//ZZ return ARMNImm_TI(2, (x >> 16) & 0xFF);
710//ZZ if ((x & 0x00FFFFFF) == 0)
711//ZZ return ARMNImm_TI(3, (x >> 24) & 0xFF);
712//ZZ if ((x & 0xFFFF00FF) == 0xFF)
713//ZZ return ARMNImm_TI(7, (x >> 8) & 0xFF);
714//ZZ if ((x & 0xFF00FFFF) == 0xFFFF)
715//ZZ return ARMNImm_TI(8, (x >> 16) & 0xFF);
716//ZZ if ((x & 0xFFFF) == ((x >> 16) & 0xFFFF)) {
717//ZZ if ((x & 0xFF00) == 0)
718//ZZ return ARMNImm_TI(4, x & 0xFF);
719//ZZ if ((x & 0x00FF) == 0)
720//ZZ return ARMNImm_TI(5, (x >> 8) & 0xFF);
721//ZZ if ((x & 0xFF) == ((x >> 8) & 0xFF))
722//ZZ return ARMNImm_TI(6, x & 0xFF);
723//ZZ }
724//ZZ if ((x & 0x7FFFF) == 0) {
725//ZZ tmp.type = 10;
726//ZZ tmp.imm8 = ((x >> 19) & 0x7F) | ((x >> 24) & 0x80);
727//ZZ if (ARMNImm_to_Imm64(&tmp) == x)
728//ZZ return ARMNImm_TI(tmp.type, tmp.imm8);
729//ZZ }
730//ZZ } else {
731//ZZ /* This can only be type 9. */
732//ZZ tmp.imm8 = (((x >> 56) & 1) << 7)
733//ZZ | (((x >> 48) & 1) << 6)
734//ZZ | (((x >> 40) & 1) << 5)
735//ZZ | (((x >> 32) & 1) << 4)
736//ZZ | (((x >> 24) & 1) << 3)
737//ZZ | (((x >> 16) & 1) << 2)
738//ZZ | (((x >> 8) & 1) << 1)
739//ZZ | (((x >> 0) & 1) << 0);
740//ZZ tmp.type = 9;
741//ZZ if (ARMNImm_to_Imm64 (&tmp) == x)
742//ZZ return ARMNImm_TI(tmp.type, tmp.imm8);
743//ZZ }
744//ZZ return NULL;
745//ZZ }
746//ZZ
747//ZZ void ppARMNImm (ARMNImm* i) {
748//ZZ ULong x = ARMNImm_to_Imm64(i);
749//ZZ vex_printf("0x%llX%llX", x, x);
750//ZZ }
751//ZZ
752//ZZ /* -- Register or scalar operand --- */
753//ZZ
754//ZZ ARMNRS* mkARMNRS(ARMNRS_tag tag, HReg reg, UInt index)
755//ZZ {
756//ZZ ARMNRS *p = LibVEX_Alloc(sizeof(ARMNRS));
757//ZZ p->tag = tag;
758//ZZ p->reg = reg;
759//ZZ p->index = index;
760//ZZ return p;
761//ZZ }
762//ZZ
763//ZZ void ppARMNRS(ARMNRS *p)
764//ZZ {
765//ZZ ppHRegARM(p->reg);
766//ZZ if (p->tag == ARMNRS_Scalar) {
767//ZZ vex_printf("[%d]", p->index);
768//ZZ }
769//ZZ }
770
771/* --------- Instructions. --------- */
772
773static const HChar* showARM64LogicOp ( ARM64LogicOp op ) {
774 switch (op) {
775 case ARM64lo_AND: return "and";
776 case ARM64lo_OR: return "orr";
777 case ARM64lo_XOR: return "eor";
778 default: vpanic("showARM64LogicOp");
779 }
780}
781
782static const HChar* showARM64ShiftOp ( ARM64ShiftOp op ) {
783 switch (op) {
784 case ARM64sh_SHL: return "lsl";
785 case ARM64sh_SHR: return "lsr";
786 case ARM64sh_SAR: return "asr";
787 default: vpanic("showARM64ShiftOp");
788 }
789}
790
791static const HChar* showARM64UnaryOp ( ARM64UnaryOp op ) {
792 switch (op) {
793 case ARM64un_NEG: return "neg";
794 case ARM64un_NOT: return "not";
795 case ARM64un_CLZ: return "clz";
796 default: vpanic("showARM64UnaryOp");
797 }
798}
799
800static const HChar* showARM64MulOp ( ARM64MulOp op ) {
801 switch (op) {
802 case ARM64mul_PLAIN: return "mul ";
803 case ARM64mul_ZX: return "umulh";
804 case ARM64mul_SX: return "smulh";
805 default: vpanic("showARM64MulOp");
806 }
807}
808
809static void characteriseARM64CvtOp ( /*OUT*/HChar* syn,
810 /*OUT*/UInt* fszB, /*OUT*/UInt* iszB,
811 ARM64CvtOp op ) {
812 switch (op) {
813 case ARM64cvt_F32_I32S:
814 *syn = 's'; *fszB = 4; *iszB = 4; break;
815 case ARM64cvt_F64_I32S:
816 *syn = 's'; *fszB = 8; *iszB = 4; break;
817 case ARM64cvt_F32_I64S:
818 *syn = 's'; *fszB = 4; *iszB = 8; break;
819 case ARM64cvt_F64_I64S:
820 *syn = 's'; *fszB = 8; *iszB = 8; break;
821 case ARM64cvt_F32_I32U:
822 *syn = 'u'; *fszB = 4; *iszB = 4; break;
823 case ARM64cvt_F64_I32U:
824 *syn = 'u'; *fszB = 8; *iszB = 4; break;
825 case ARM64cvt_F32_I64U:
826 *syn = 'u'; *fszB = 4; *iszB = 8; break;
827 case ARM64cvt_F64_I64U:
828 *syn = 'u'; *fszB = 8; *iszB = 8; break;
829 default:
830 vpanic("characteriseARM64CvtOp");
831 }
832}
833
834static const HChar* showARM64FpBinOp ( ARM64FpBinOp op ) {
835 switch (op) {
836 case ARM64fpb_ADD: return "add";
837 case ARM64fpb_SUB: return "sub";
838 case ARM64fpb_MUL: return "mul";
839 case ARM64fpb_DIV: return "div";
840 default: vpanic("showARM64FpBinOp");
841 }
842}
843
844static const HChar* showARM64FpUnaryOp ( ARM64FpUnaryOp op ) {
845 switch (op) {
846 case ARM64fpu_NEG: return "neg ";
847 case ARM64fpu_ABS: return "abs ";
848 case ARM64fpu_SQRT: return "sqrt ";
849 case ARM64fpu_RINT: return "rinti";
850 default: vpanic("showARM64FpUnaryOp");
851 }
852}
853
sewardj606c4ba2014-01-26 19:11:14 +0000854static void showARM64VecBinOp(/*OUT*/const HChar** nm,
855 /*OUT*/const HChar** ar, ARM64VecBinOp op ) {
856 switch (op) {
sewardj12972182014-08-04 08:09:47 +0000857 case ARM64vecb_ADD64x2: *nm = "add "; *ar = "2d"; return;
858 case ARM64vecb_ADD32x4: *nm = "add "; *ar = "4s"; return;
859 case ARM64vecb_ADD16x8: *nm = "add "; *ar = "8h"; return;
860 case ARM64vecb_ADD8x16: *nm = "add "; *ar = "16b"; return;
861 case ARM64vecb_SUB64x2: *nm = "sub "; *ar = "2d"; return;
862 case ARM64vecb_SUB32x4: *nm = "sub "; *ar = "4s"; return;
863 case ARM64vecb_SUB16x8: *nm = "sub "; *ar = "8h"; return;
864 case ARM64vecb_SUB8x16: *nm = "sub "; *ar = "16b"; return;
865 case ARM64vecb_MUL32x4: *nm = "mul "; *ar = "4s"; return;
866 case ARM64vecb_MUL16x8: *nm = "mul "; *ar = "8h"; return;
867 case ARM64vecb_MUL8x16: *nm = "mul "; *ar = "16b"; return;
868 case ARM64vecb_FADD64x2: *nm = "fadd "; *ar = "2d"; return;
869 case ARM64vecb_FSUB64x2: *nm = "fsub "; *ar = "2d"; return;
870 case ARM64vecb_FMUL64x2: *nm = "fmul "; *ar = "2d"; return;
871 case ARM64vecb_FDIV64x2: *nm = "fdiv "; *ar = "2d"; return;
872 case ARM64vecb_FADD32x4: *nm = "fadd "; *ar = "4s"; return;
873 case ARM64vecb_FSUB32x4: *nm = "fsub "; *ar = "4s"; return;
874 case ARM64vecb_FMUL32x4: *nm = "fmul "; *ar = "4s"; return;
875 case ARM64vecb_FDIV32x4: *nm = "fdiv "; *ar = "4s"; return;
876 case ARM64vecb_UMAX32x4: *nm = "umax "; *ar = "4s"; return;
877 case ARM64vecb_UMAX16x8: *nm = "umax "; *ar = "8h"; return;
878 case ARM64vecb_UMAX8x16: *nm = "umax "; *ar = "16b"; return;
879 case ARM64vecb_UMIN32x4: *nm = "umin "; *ar = "4s"; return;
880 case ARM64vecb_UMIN16x8: *nm = "umin "; *ar = "8h"; return;
881 case ARM64vecb_UMIN8x16: *nm = "umin "; *ar = "16b"; return;
882 case ARM64vecb_SMAX32x4: *nm = "smax "; *ar = "4s"; return;
883 case ARM64vecb_SMAX16x8: *nm = "smax "; *ar = "8h"; return;
884 case ARM64vecb_SMAX8x16: *nm = "smax "; *ar = "16b"; return;
885 case ARM64vecb_SMIN32x4: *nm = "smin "; *ar = "4s"; return;
886 case ARM64vecb_SMIN16x8: *nm = "smin "; *ar = "8h"; return;
887 case ARM64vecb_SMIN8x16: *nm = "smin "; *ar = "16b"; return;
888 case ARM64vecb_AND: *nm = "and "; *ar = "16b"; return;
889 case ARM64vecb_ORR: *nm = "orr "; *ar = "16b"; return;
890 case ARM64vecb_XOR: *nm = "eor "; *ar = "16b"; return;
891 case ARM64vecb_CMEQ64x2: *nm = "cmeq "; *ar = "2d"; return;
892 case ARM64vecb_CMEQ32x4: *nm = "cmeq "; *ar = "4s"; return;
893 case ARM64vecb_CMEQ16x8: *nm = "cmeq "; *ar = "8h"; return;
894 case ARM64vecb_CMEQ8x16: *nm = "cmeq "; *ar = "16b"; return;
895 case ARM64vecb_CMHI64x2: *nm = "cmhi "; *ar = "2d"; return;
896 case ARM64vecb_CMHI32x4: *nm = "cmhi "; *ar = "4s"; return;
897 case ARM64vecb_CMHI16x8: *nm = "cmhi "; *ar = "8h"; return;
898 case ARM64vecb_CMHI8x16: *nm = "cmhi "; *ar = "16b"; return;
899 case ARM64vecb_CMGT64x2: *nm = "cmgt "; *ar = "2d"; return;
900 case ARM64vecb_CMGT32x4: *nm = "cmgt "; *ar = "4s"; return;
901 case ARM64vecb_CMGT16x8: *nm = "cmgt "; *ar = "8h"; return;
902 case ARM64vecb_CMGT8x16: *nm = "cmgt "; *ar = "16b"; return;
903 case ARM64vecb_FCMEQ64x2: *nm = "fcmeq "; *ar = "2d"; return;
904 case ARM64vecb_FCMEQ32x4: *nm = "fcmeq "; *ar = "4s"; return;
905 case ARM64vecb_FCMGE64x2: *nm = "fcmge "; *ar = "2d"; return;
906 case ARM64vecb_FCMGE32x4: *nm = "fcmge "; *ar = "4s"; return;
907 case ARM64vecb_FCMGT64x2: *nm = "fcmgt "; *ar = "2d"; return;
908 case ARM64vecb_FCMGT32x4: *nm = "fcmgt "; *ar = "4s"; return;
909 case ARM64vecb_TBL1: *nm = "tbl "; *ar = "16b"; return;
910 case ARM64vecb_UZP164x2: *nm = "uzp1 "; *ar = "2d"; return;
911 case ARM64vecb_UZP132x4: *nm = "uzp1 "; *ar = "4s"; return;
912 case ARM64vecb_UZP116x8: *nm = "uzp1 "; *ar = "8h"; return;
913 case ARM64vecb_UZP18x16: *nm = "uzp1 "; *ar = "16b"; return;
914 case ARM64vecb_UZP264x2: *nm = "uzp2 "; *ar = "2d"; return;
915 case ARM64vecb_UZP232x4: *nm = "uzp2 "; *ar = "4s"; return;
916 case ARM64vecb_UZP216x8: *nm = "uzp2 "; *ar = "8h"; return;
917 case ARM64vecb_UZP28x16: *nm = "uzp2 "; *ar = "16b"; return;
918 case ARM64vecb_ZIP132x4: *nm = "zip1 "; *ar = "4s"; return;
919 case ARM64vecb_ZIP116x8: *nm = "zip1 "; *ar = "8h"; return;
920 case ARM64vecb_ZIP18x16: *nm = "zip1 "; *ar = "16b"; return;
921 case ARM64vecb_ZIP232x4: *nm = "zip2 "; *ar = "4s"; return;
922 case ARM64vecb_ZIP216x8: *nm = "zip2 "; *ar = "8h"; return;
923 case ARM64vecb_ZIP28x16: *nm = "zip2 "; *ar = "16b"; return;
924 case ARM64vecb_PMUL8x16: *nm = "pmul "; *ar = "16b"; return;
925 case ARM64vecb_PMULL8x8: *nm = "pmull "; *ar = "8hbb"; return;
926 case ARM64vecb_UMULL2DSS: *nm = "umull "; *ar = "2dss"; return;
927 case ARM64vecb_UMULL4SHH: *nm = "umull "; *ar = "4shh"; return;
928 case ARM64vecb_UMULL8HBB: *nm = "umull "; *ar = "8hbb"; return;
929 case ARM64vecb_SMULL2DSS: *nm = "smull "; *ar = "2dss"; return;
930 case ARM64vecb_SMULL4SHH: *nm = "smull "; *ar = "4shh"; return;
931 case ARM64vecb_SMULL8HBB: *nm = "smull "; *ar = "8hbb"; return;
932 case ARM64vecb_SQADD64x2: *nm = "sqadd "; *ar = "2d"; return;
933 case ARM64vecb_SQADD32x4: *nm = "sqadd "; *ar = "4s"; return;
934 case ARM64vecb_SQADD16x8: *nm = "sqadd "; *ar = "8h"; return;
935 case ARM64vecb_SQADD8x16: *nm = "sqadd "; *ar = "16b"; return;
936 case ARM64vecb_UQADD64x2: *nm = "uqadd "; *ar = "2d"; return;
937 case ARM64vecb_UQADD32x4: *nm = "uqadd "; *ar = "4s"; return;
938 case ARM64vecb_UQADD16x8: *nm = "uqadd "; *ar = "8h"; return;
939 case ARM64vecb_UQADD8x16: *nm = "uqadd "; *ar = "16b"; return;
940 case ARM64vecb_SQSUB64x2: *nm = "sqsub "; *ar = "2d"; return;
941 case ARM64vecb_SQSUB32x4: *nm = "sqsub "; *ar = "4s"; return;
942 case ARM64vecb_SQSUB16x8: *nm = "sqsub "; *ar = "8h"; return;
943 case ARM64vecb_SQSUB8x16: *nm = "sqsub "; *ar = "16b"; return;
944 case ARM64vecb_UQSUB64x2: *nm = "uqsub "; *ar = "2d"; return;
945 case ARM64vecb_UQSUB32x4: *nm = "uqsub "; *ar = "4s"; return;
946 case ARM64vecb_UQSUB16x8: *nm = "uqsub "; *ar = "8h"; return;
947 case ARM64vecb_UQSUB8x16: *nm = "uqsub "; *ar = "16b"; return;
948 case ARM64vecb_SQDMULL2DSS: *nm = "sqdmull"; *ar = "2dss"; return;
949 case ARM64vecb_SQDMULL4SHH: *nm = "sqdmull"; *ar = "4shh"; return;
950 case ARM64vecb_SQDMULH32x4: *nm = "sqdmulh"; *ar = "4s"; return;
951 case ARM64vecb_SQDMULH16x8: *nm = "sqdmulh"; *ar = "8h"; return;
952 case ARM64vecb_SQRDMULH32x4: *nm = "sqrdmulh"; *ar = "4s"; return;
953 case ARM64vecb_SQRDMULH16x8: *nm = "sqrdmulh"; *ar = "8h"; return;
954 case ARM64vecb_SQSHL64x2: *nm = "sqshl "; *ar = "2d"; return;
955 case ARM64vecb_SQSHL32x4: *nm = "sqshl "; *ar = "4s"; return;
956 case ARM64vecb_SQSHL16x8: *nm = "sqshl "; *ar = "8h"; return;
957 case ARM64vecb_SQSHL8x16: *nm = "sqshl "; *ar = "16b"; return;
958 case ARM64vecb_UQSHL64x2: *nm = "uqshl "; *ar = "2d"; return;
959 case ARM64vecb_UQSHL32x4: *nm = "uqshl "; *ar = "4s"; return;
960 case ARM64vecb_UQSHL16x8: *nm = "uqshl "; *ar = "8h"; return;
961 case ARM64vecb_UQSHL8x16: *nm = "uqshl "; *ar = "16b"; return;
962 case ARM64vecb_SQRSHL64x2: *nm = "sqrshl"; *ar = "2d"; return;
963 case ARM64vecb_SQRSHL32x4: *nm = "sqrshl"; *ar = "4s"; return;
964 case ARM64vecb_SQRSHL16x8: *nm = "sqrshl"; *ar = "8h"; return;
965 case ARM64vecb_SQRSHL8x16: *nm = "sqrshl"; *ar = "16b"; return;
966 case ARM64vecb_UQRSHL64x2: *nm = "uqrshl"; *ar = "2d"; return;
967 case ARM64vecb_UQRSHL32x4: *nm = "uqrshl"; *ar = "4s"; return;
968 case ARM64vecb_UQRSHL16x8: *nm = "uqrshl"; *ar = "8h"; return;
969 case ARM64vecb_UQRSHL8x16: *nm = "uqrshl"; *ar = "16b"; return;
sewardj606c4ba2014-01-26 19:11:14 +0000970 default: vpanic("showARM64VecBinOp");
971 }
972}
973
sewardjfab09142014-02-10 10:28:13 +0000974static void showARM64VecUnaryOp(/*OUT*/const HChar** nm,
975 /*OUT*/const HChar** ar, ARM64VecUnaryOp op )
976{
977 switch (op) {
sewardje520bb32014-02-17 11:00:53 +0000978 case ARM64vecu_FNEG64x2: *nm = "fneg "; *ar = "2d"; return;
sewardjfab09142014-02-10 10:28:13 +0000979 case ARM64vecu_FNEG32x4: *nm = "fneg "; *ar = "4s"; return;
980 case ARM64vecu_FABS64x2: *nm = "fabs "; *ar = "2d"; return;
981 case ARM64vecu_FABS32x4: *nm = "fabs "; *ar = "4s"; return;
sewardje520bb32014-02-17 11:00:53 +0000982 case ARM64vecu_NOT: *nm = "not "; *ar = "all"; return;
sewardj2b6fd5e2014-06-19 14:21:37 +0000983 case ARM64vecu_ABS64x2: *nm = "abs "; *ar = "2d"; return;
984 case ARM64vecu_ABS32x4: *nm = "abs "; *ar = "4s"; return;
985 case ARM64vecu_ABS16x8: *nm = "abs "; *ar = "8h"; return;
986 case ARM64vecu_ABS8x16: *nm = "abs "; *ar = "16b"; return;
987 case ARM64vecu_CLS32x4: *nm = "cls "; *ar = "4s"; return;
988 case ARM64vecu_CLS16x8: *nm = "cls "; *ar = "8h"; return;
989 case ARM64vecu_CLS8x16: *nm = "cls "; *ar = "16b"; return;
990 case ARM64vecu_CLZ32x4: *nm = "clz "; *ar = "4s"; return;
991 case ARM64vecu_CLZ16x8: *nm = "clz "; *ar = "8h"; return;
992 case ARM64vecu_CLZ8x16: *nm = "clz "; *ar = "16b"; return;
993 case ARM64vecu_CNT8x16: *nm = "cnt "; *ar = "16b"; return;
sewardj715d1622014-06-26 12:39:05 +0000994 case ARM64vecu_RBIT: *nm = "rbit "; *ar = "16b"; return;
995 case ARM64vecu_REV1616B: *nm = "rev16"; *ar = "16b"; return;
sewardjdf9d6d52014-06-27 10:43:22 +0000996 case ARM64vecu_REV3216B: *nm = "rev32"; *ar = "16b"; return;
997 case ARM64vecu_REV328H: *nm = "rev32"; *ar = "8h"; return;
998 case ARM64vecu_REV6416B: *nm = "rev64"; *ar = "16b"; return;
999 case ARM64vecu_REV648H: *nm = "rev64"; *ar = "8h"; return;
1000 case ARM64vecu_REV644S: *nm = "rev64"; *ar = "4s"; return;
sewardje520bb32014-02-17 11:00:53 +00001001 default: vpanic("showARM64VecUnaryOp");
1002 }
1003}
1004
1005static void showARM64VecShiftOp(/*OUT*/const HChar** nm,
1006 /*OUT*/const HChar** ar,
1007 ARM64VecShiftOp op )
1008{
1009 switch (op) {
sewardjecedd982014-08-11 14:02:47 +00001010 case ARM64vecsh_USHR64x2: *nm = "ushr "; *ar = "2d"; return;
1011 case ARM64vecsh_USHR32x4: *nm = "ushr "; *ar = "4s"; return;
1012 case ARM64vecsh_USHR16x8: *nm = "ushr "; *ar = "8h"; return;
1013 case ARM64vecsh_USHR8x16: *nm = "ushr "; *ar = "16b"; return;
1014 case ARM64vecsh_SSHR64x2: *nm = "sshr "; *ar = "2d"; return;
1015 case ARM64vecsh_SSHR32x4: *nm = "sshr "; *ar = "4s"; return;
1016 case ARM64vecsh_SSHR16x8: *nm = "sshr "; *ar = "8h"; return;
1017 case ARM64vecsh_SSHR8x16: *nm = "sshr "; *ar = "16b"; return;
1018 case ARM64vecsh_SHL64x2: *nm = "shl "; *ar = "2d"; return;
1019 case ARM64vecsh_SHL32x4: *nm = "shl "; *ar = "4s"; return;
1020 case ARM64vecsh_SHL16x8: *nm = "shl "; *ar = "8h"; return;
1021 case ARM64vecsh_SHL8x16: *nm = "shl "; *ar = "16b"; return;
1022 case ARM64vecsh_SQSHRN2SD: *nm = "sqshrn"; *ar = "2sd"; return;
1023 case ARM64vecsh_SQSHRN4HS: *nm = "sqshrn"; *ar = "4hs"; return;
1024 case ARM64vecsh_SQSHRN8BH: *nm = "sqshrn"; *ar = "8bh"; return;
1025 case ARM64vecsh_UQSHRN2SD: *nm = "uqshrn"; *ar = "2sd"; return;
1026 case ARM64vecsh_UQSHRN4HS: *nm = "uqshrn"; *ar = "4hs"; return;
1027 case ARM64vecsh_UQSHRN8BH: *nm = "uqshrn"; *ar = "8bh"; return;
1028 case ARM64vecsh_SQSHRUN2SD: *nm = "sqshrun"; *ar = "2sd"; return;
1029 case ARM64vecsh_SQSHRUN4HS: *nm = "sqshrun"; *ar = "4hs"; return;
1030 case ARM64vecsh_SQSHRUN8BH: *nm = "sqshrun"; *ar = "8bh"; return;
1031 case ARM64vecsh_SQRSHRN2SD: *nm = "sqrshrn"; *ar = "2sd"; return;
1032 case ARM64vecsh_SQRSHRN4HS: *nm = "sqrshrn"; *ar = "4hs"; return;
1033 case ARM64vecsh_SQRSHRN8BH: *nm = "sqrshrn"; *ar = "8bh"; return;
1034 case ARM64vecsh_UQRSHRN2SD: *nm = "uqrshrn"; *ar = "2sd"; return;
1035 case ARM64vecsh_UQRSHRN4HS: *nm = "uqrshrn"; *ar = "4hs"; return;
1036 case ARM64vecsh_UQRSHRN8BH: *nm = "uqrshrn"; *ar = "8bh"; return;
1037 case ARM64vecsh_SQRSHRUN2SD: *nm = "sqrshrun"; *ar = "2sd"; return;
1038 case ARM64vecsh_SQRSHRUN4HS: *nm = "sqrshrun"; *ar = "4hs"; return;
1039 case ARM64vecsh_SQRSHRUN8BH: *nm = "sqrshrun"; *ar = "8bh"; return;
sewardja97dddf2014-08-14 22:26:52 +00001040 case ARM64vecsh_UQSHL64x2: *nm = "uqshl "; *ar = "2d"; return;
1041 case ARM64vecsh_UQSHL32x4: *nm = "uqshl "; *ar = "4s"; return;
1042 case ARM64vecsh_UQSHL16x8: *nm = "uqshl "; *ar = "8h"; return;
1043 case ARM64vecsh_UQSHL8x16: *nm = "uqshl "; *ar = "16b"; return;
1044 case ARM64vecsh_SQSHL64x2: *nm = "sqshl "; *ar = "2d"; return;
1045 case ARM64vecsh_SQSHL32x4: *nm = "sqshl "; *ar = "4s"; return;
1046 case ARM64vecsh_SQSHL16x8: *nm = "sqshl "; *ar = "8h"; return;
1047 case ARM64vecsh_SQSHL8x16: *nm = "sqshl "; *ar = "16b"; return;
1048 case ARM64vecsh_SQSHLU64x2: *nm = "sqshlu"; *ar = "2d"; return;
1049 case ARM64vecsh_SQSHLU32x4: *nm = "sqshlu"; *ar = "4s"; return;
1050 case ARM64vecsh_SQSHLU16x8: *nm = "sqshlu"; *ar = "8h"; return;
1051 case ARM64vecsh_SQSHLU8x16: *nm = "sqshlu"; *ar = "16b"; return;
sewardjecedd982014-08-11 14:02:47 +00001052 default: vpanic("showARM64VecShiftOp");
1053 }
1054}
1055
1056static const HChar* showARM64VecNarrowOp(ARM64VecNarrowOp op) {
1057 switch (op) {
1058 case ARM64vecna_XTN: return "xtn ";
1059 case ARM64vecna_SQXTN: return "sqxtn ";
1060 case ARM64vecna_UQXTN: return "uqxtn ";
1061 case ARM64vecna_SQXTUN: return "sqxtun";
1062 default: vpanic("showARM64VecNarrowOp");
sewardjfab09142014-02-10 10:28:13 +00001063 }
1064}
1065
sewardjbbcf1882014-01-12 12:49:10 +00001066//ZZ const HChar* showARMNeonBinOp ( ARMNeonBinOp op ) {
1067//ZZ switch (op) {
1068//ZZ case ARMneon_VAND: return "vand";
1069//ZZ case ARMneon_VORR: return "vorr";
1070//ZZ case ARMneon_VXOR: return "veor";
1071//ZZ case ARMneon_VADD: return "vadd";
1072//ZZ case ARMneon_VRHADDS: return "vrhadd";
1073//ZZ case ARMneon_VRHADDU: return "vrhadd";
1074//ZZ case ARMneon_VADDFP: return "vadd";
1075//ZZ case ARMneon_VPADDFP: return "vpadd";
1076//ZZ case ARMneon_VABDFP: return "vabd";
1077//ZZ case ARMneon_VSUB: return "vsub";
1078//ZZ case ARMneon_VSUBFP: return "vsub";
1079//ZZ case ARMneon_VMINU: return "vmin";
1080//ZZ case ARMneon_VMINS: return "vmin";
1081//ZZ case ARMneon_VMINF: return "vmin";
1082//ZZ case ARMneon_VMAXU: return "vmax";
1083//ZZ case ARMneon_VMAXS: return "vmax";
1084//ZZ case ARMneon_VMAXF: return "vmax";
1085//ZZ case ARMneon_VQADDU: return "vqadd";
1086//ZZ case ARMneon_VQADDS: return "vqadd";
1087//ZZ case ARMneon_VQSUBU: return "vqsub";
1088//ZZ case ARMneon_VQSUBS: return "vqsub";
1089//ZZ case ARMneon_VCGTU: return "vcgt";
1090//ZZ case ARMneon_VCGTS: return "vcgt";
1091//ZZ case ARMneon_VCGTF: return "vcgt";
1092//ZZ case ARMneon_VCGEF: return "vcgt";
1093//ZZ case ARMneon_VCGEU: return "vcge";
1094//ZZ case ARMneon_VCGES: return "vcge";
1095//ZZ case ARMneon_VCEQ: return "vceq";
1096//ZZ case ARMneon_VCEQF: return "vceq";
1097//ZZ case ARMneon_VPADD: return "vpadd";
1098//ZZ case ARMneon_VPMINU: return "vpmin";
1099//ZZ case ARMneon_VPMINS: return "vpmin";
1100//ZZ case ARMneon_VPMINF: return "vpmin";
1101//ZZ case ARMneon_VPMAXU: return "vpmax";
1102//ZZ case ARMneon_VPMAXS: return "vpmax";
1103//ZZ case ARMneon_VPMAXF: return "vpmax";
1104//ZZ case ARMneon_VEXT: return "vext";
1105//ZZ case ARMneon_VMUL: return "vmuli";
1106//ZZ case ARMneon_VMULLU: return "vmull";
1107//ZZ case ARMneon_VMULLS: return "vmull";
1108//ZZ case ARMneon_VMULP: return "vmul";
1109//ZZ case ARMneon_VMULFP: return "vmul";
1110//ZZ case ARMneon_VMULLP: return "vmul";
1111//ZZ case ARMneon_VQDMULH: return "vqdmulh";
1112//ZZ case ARMneon_VQRDMULH: return "vqrdmulh";
1113//ZZ case ARMneon_VQDMULL: return "vqdmull";
1114//ZZ case ARMneon_VTBL: return "vtbl";
1115//ZZ case ARMneon_VRECPS: return "vrecps";
1116//ZZ case ARMneon_VRSQRTS: return "vrecps";
1117//ZZ /* ... */
1118//ZZ default: vpanic("showARMNeonBinOp");
1119//ZZ }
1120//ZZ }
1121//ZZ
1122//ZZ const HChar* showARMNeonBinOpDataType ( ARMNeonBinOp op ) {
1123//ZZ switch (op) {
1124//ZZ case ARMneon_VAND:
1125//ZZ case ARMneon_VORR:
1126//ZZ case ARMneon_VXOR:
1127//ZZ return "";
1128//ZZ case ARMneon_VADD:
1129//ZZ case ARMneon_VSUB:
1130//ZZ case ARMneon_VEXT:
1131//ZZ case ARMneon_VMUL:
1132//ZZ case ARMneon_VPADD:
1133//ZZ case ARMneon_VTBL:
1134//ZZ case ARMneon_VCEQ:
1135//ZZ return ".i";
1136//ZZ case ARMneon_VRHADDU:
1137//ZZ case ARMneon_VMINU:
1138//ZZ case ARMneon_VMAXU:
1139//ZZ case ARMneon_VQADDU:
1140//ZZ case ARMneon_VQSUBU:
1141//ZZ case ARMneon_VCGTU:
1142//ZZ case ARMneon_VCGEU:
1143//ZZ case ARMneon_VMULLU:
1144//ZZ case ARMneon_VPMINU:
1145//ZZ case ARMneon_VPMAXU:
1146//ZZ return ".u";
1147//ZZ case ARMneon_VRHADDS:
1148//ZZ case ARMneon_VMINS:
1149//ZZ case ARMneon_VMAXS:
1150//ZZ case ARMneon_VQADDS:
1151//ZZ case ARMneon_VQSUBS:
1152//ZZ case ARMneon_VCGTS:
1153//ZZ case ARMneon_VCGES:
1154//ZZ case ARMneon_VQDMULL:
1155//ZZ case ARMneon_VMULLS:
1156//ZZ case ARMneon_VPMINS:
1157//ZZ case ARMneon_VPMAXS:
1158//ZZ case ARMneon_VQDMULH:
1159//ZZ case ARMneon_VQRDMULH:
1160//ZZ return ".s";
1161//ZZ case ARMneon_VMULP:
1162//ZZ case ARMneon_VMULLP:
1163//ZZ return ".p";
1164//ZZ case ARMneon_VADDFP:
1165//ZZ case ARMneon_VABDFP:
1166//ZZ case ARMneon_VPADDFP:
1167//ZZ case ARMneon_VSUBFP:
1168//ZZ case ARMneon_VMULFP:
1169//ZZ case ARMneon_VMINF:
1170//ZZ case ARMneon_VMAXF:
1171//ZZ case ARMneon_VPMINF:
1172//ZZ case ARMneon_VPMAXF:
1173//ZZ case ARMneon_VCGTF:
1174//ZZ case ARMneon_VCGEF:
1175//ZZ case ARMneon_VCEQF:
1176//ZZ case ARMneon_VRECPS:
1177//ZZ case ARMneon_VRSQRTS:
1178//ZZ return ".f";
1179//ZZ /* ... */
1180//ZZ default: vpanic("showARMNeonBinOpDataType");
1181//ZZ }
1182//ZZ }
1183//ZZ
1184//ZZ const HChar* showARMNeonUnOp ( ARMNeonUnOp op ) {
1185//ZZ switch (op) {
1186//ZZ case ARMneon_COPY: return "vmov";
1187//ZZ case ARMneon_COPYLS: return "vmov";
1188//ZZ case ARMneon_COPYLU: return "vmov";
1189//ZZ case ARMneon_COPYN: return "vmov";
1190//ZZ case ARMneon_COPYQNSS: return "vqmovn";
1191//ZZ case ARMneon_COPYQNUS: return "vqmovun";
1192//ZZ case ARMneon_COPYQNUU: return "vqmovn";
1193//ZZ case ARMneon_NOT: return "vmvn";
1194//ZZ case ARMneon_EQZ: return "vceq";
1195//ZZ case ARMneon_CNT: return "vcnt";
1196//ZZ case ARMneon_CLS: return "vcls";
1197//ZZ case ARMneon_CLZ: return "vclz";
1198//ZZ case ARMneon_DUP: return "vdup";
1199//ZZ case ARMneon_PADDLS: return "vpaddl";
1200//ZZ case ARMneon_PADDLU: return "vpaddl";
1201//ZZ case ARMneon_VQSHLNSS: return "vqshl";
1202//ZZ case ARMneon_VQSHLNUU: return "vqshl";
1203//ZZ case ARMneon_VQSHLNUS: return "vqshlu";
1204//ZZ case ARMneon_REV16: return "vrev16";
1205//ZZ case ARMneon_REV32: return "vrev32";
1206//ZZ case ARMneon_REV64: return "vrev64";
1207//ZZ case ARMneon_VCVTFtoU: return "vcvt";
1208//ZZ case ARMneon_VCVTFtoS: return "vcvt";
1209//ZZ case ARMneon_VCVTUtoF: return "vcvt";
1210//ZZ case ARMneon_VCVTStoF: return "vcvt";
1211//ZZ case ARMneon_VCVTFtoFixedU: return "vcvt";
1212//ZZ case ARMneon_VCVTFtoFixedS: return "vcvt";
1213//ZZ case ARMneon_VCVTFixedUtoF: return "vcvt";
1214//ZZ case ARMneon_VCVTFixedStoF: return "vcvt";
1215//ZZ case ARMneon_VCVTF32toF16: return "vcvt";
1216//ZZ case ARMneon_VCVTF16toF32: return "vcvt";
1217//ZZ case ARMneon_VRECIP: return "vrecip";
1218//ZZ case ARMneon_VRECIPF: return "vrecipf";
1219//ZZ case ARMneon_VNEGF: return "vneg";
1220//ZZ case ARMneon_ABS: return "vabs";
1221//ZZ case ARMneon_VABSFP: return "vabsfp";
1222//ZZ case ARMneon_VRSQRTEFP: return "vrsqrtefp";
1223//ZZ case ARMneon_VRSQRTE: return "vrsqrte";
1224//ZZ /* ... */
1225//ZZ default: vpanic("showARMNeonUnOp");
1226//ZZ }
1227//ZZ }
1228//ZZ
1229//ZZ const HChar* showARMNeonUnOpDataType ( ARMNeonUnOp op ) {
1230//ZZ switch (op) {
1231//ZZ case ARMneon_COPY:
1232//ZZ case ARMneon_NOT:
1233//ZZ return "";
1234//ZZ case ARMneon_COPYN:
1235//ZZ case ARMneon_EQZ:
1236//ZZ case ARMneon_CNT:
1237//ZZ case ARMneon_DUP:
1238//ZZ case ARMneon_REV16:
1239//ZZ case ARMneon_REV32:
1240//ZZ case ARMneon_REV64:
1241//ZZ return ".i";
1242//ZZ case ARMneon_COPYLU:
1243//ZZ case ARMneon_PADDLU:
1244//ZZ case ARMneon_COPYQNUU:
1245//ZZ case ARMneon_VQSHLNUU:
1246//ZZ case ARMneon_VRECIP:
1247//ZZ case ARMneon_VRSQRTE:
1248//ZZ return ".u";
1249//ZZ case ARMneon_CLS:
1250//ZZ case ARMneon_CLZ:
1251//ZZ case ARMneon_COPYLS:
1252//ZZ case ARMneon_PADDLS:
1253//ZZ case ARMneon_COPYQNSS:
1254//ZZ case ARMneon_COPYQNUS:
1255//ZZ case ARMneon_VQSHLNSS:
1256//ZZ case ARMneon_VQSHLNUS:
1257//ZZ case ARMneon_ABS:
1258//ZZ return ".s";
1259//ZZ case ARMneon_VRECIPF:
1260//ZZ case ARMneon_VNEGF:
1261//ZZ case ARMneon_VABSFP:
1262//ZZ case ARMneon_VRSQRTEFP:
1263//ZZ return ".f";
1264//ZZ case ARMneon_VCVTFtoU: return ".u32.f32";
1265//ZZ case ARMneon_VCVTFtoS: return ".s32.f32";
1266//ZZ case ARMneon_VCVTUtoF: return ".f32.u32";
1267//ZZ case ARMneon_VCVTStoF: return ".f32.s32";
1268//ZZ case ARMneon_VCVTF16toF32: return ".f32.f16";
1269//ZZ case ARMneon_VCVTF32toF16: return ".f16.f32";
1270//ZZ case ARMneon_VCVTFtoFixedU: return ".u32.f32";
1271//ZZ case ARMneon_VCVTFtoFixedS: return ".s32.f32";
1272//ZZ case ARMneon_VCVTFixedUtoF: return ".f32.u32";
1273//ZZ case ARMneon_VCVTFixedStoF: return ".f32.s32";
1274//ZZ /* ... */
1275//ZZ default: vpanic("showARMNeonUnOpDataType");
1276//ZZ }
1277//ZZ }
1278//ZZ
1279//ZZ const HChar* showARMNeonUnOpS ( ARMNeonUnOpS op ) {
1280//ZZ switch (op) {
1281//ZZ case ARMneon_SETELEM: return "vmov";
1282//ZZ case ARMneon_GETELEMU: return "vmov";
1283//ZZ case ARMneon_GETELEMS: return "vmov";
1284//ZZ case ARMneon_VDUP: return "vdup";
1285//ZZ /* ... */
1286//ZZ default: vpanic("showARMNeonUnarySOp");
1287//ZZ }
1288//ZZ }
1289//ZZ
1290//ZZ const HChar* showARMNeonUnOpSDataType ( ARMNeonUnOpS op ) {
1291//ZZ switch (op) {
1292//ZZ case ARMneon_SETELEM:
1293//ZZ case ARMneon_VDUP:
1294//ZZ return ".i";
1295//ZZ case ARMneon_GETELEMS:
1296//ZZ return ".s";
1297//ZZ case ARMneon_GETELEMU:
1298//ZZ return ".u";
1299//ZZ /* ... */
1300//ZZ default: vpanic("showARMNeonUnarySOp");
1301//ZZ }
1302//ZZ }
1303//ZZ
1304//ZZ const HChar* showARMNeonShiftOp ( ARMNeonShiftOp op ) {
1305//ZZ switch (op) {
1306//ZZ case ARMneon_VSHL: return "vshl";
1307//ZZ case ARMneon_VSAL: return "vshl";
1308//ZZ case ARMneon_VQSHL: return "vqshl";
1309//ZZ case ARMneon_VQSAL: return "vqshl";
1310//ZZ /* ... */
1311//ZZ default: vpanic("showARMNeonShiftOp");
1312//ZZ }
1313//ZZ }
1314//ZZ
1315//ZZ const HChar* showARMNeonShiftOpDataType ( ARMNeonShiftOp op ) {
1316//ZZ switch (op) {
1317//ZZ case ARMneon_VSHL:
1318//ZZ case ARMneon_VQSHL:
1319//ZZ return ".u";
1320//ZZ case ARMneon_VSAL:
1321//ZZ case ARMneon_VQSAL:
1322//ZZ return ".s";
1323//ZZ /* ... */
1324//ZZ default: vpanic("showARMNeonShiftOpDataType");
1325//ZZ }
1326//ZZ }
1327//ZZ
1328//ZZ const HChar* showARMNeonDualOp ( ARMNeonDualOp op ) {
1329//ZZ switch (op) {
1330//ZZ case ARMneon_TRN: return "vtrn";
1331//ZZ case ARMneon_ZIP: return "vzip";
1332//ZZ case ARMneon_UZP: return "vuzp";
1333//ZZ /* ... */
1334//ZZ default: vpanic("showARMNeonDualOp");
1335//ZZ }
1336//ZZ }
1337//ZZ
1338//ZZ const HChar* showARMNeonDualOpDataType ( ARMNeonDualOp op ) {
1339//ZZ switch (op) {
1340//ZZ case ARMneon_TRN:
1341//ZZ case ARMneon_ZIP:
1342//ZZ case ARMneon_UZP:
1343//ZZ return "i";
1344//ZZ /* ... */
1345//ZZ default: vpanic("showARMNeonDualOp");
1346//ZZ }
1347//ZZ }
1348//ZZ
1349//ZZ static const HChar* showARMNeonDataSize_wrk ( UInt size )
1350//ZZ {
1351//ZZ switch (size) {
1352//ZZ case 0: return "8";
1353//ZZ case 1: return "16";
1354//ZZ case 2: return "32";
1355//ZZ case 3: return "64";
1356//ZZ default: vpanic("showARMNeonDataSize");
1357//ZZ }
1358//ZZ }
1359//ZZ
1360//ZZ static const HChar* showARMNeonDataSize ( ARMInstr* i )
1361//ZZ {
1362//ZZ switch (i->tag) {
1363//ZZ case ARMin_NBinary:
1364//ZZ if (i->ARMin.NBinary.op == ARMneon_VEXT)
1365//ZZ return "8";
1366//ZZ if (i->ARMin.NBinary.op == ARMneon_VAND ||
1367//ZZ i->ARMin.NBinary.op == ARMneon_VORR ||
1368//ZZ i->ARMin.NBinary.op == ARMneon_VXOR)
1369//ZZ return "";
1370//ZZ return showARMNeonDataSize_wrk(i->ARMin.NBinary.size);
1371//ZZ case ARMin_NUnary:
1372//ZZ if (i->ARMin.NUnary.op == ARMneon_COPY ||
1373//ZZ i->ARMin.NUnary.op == ARMneon_NOT ||
1374//ZZ i->ARMin.NUnary.op == ARMneon_VCVTF32toF16||
1375//ZZ i->ARMin.NUnary.op == ARMneon_VCVTF16toF32||
1376//ZZ i->ARMin.NUnary.op == ARMneon_VCVTFtoFixedS ||
1377//ZZ i->ARMin.NUnary.op == ARMneon_VCVTFtoFixedU ||
1378//ZZ i->ARMin.NUnary.op == ARMneon_VCVTFixedStoF ||
1379//ZZ i->ARMin.NUnary.op == ARMneon_VCVTFixedUtoF ||
1380//ZZ i->ARMin.NUnary.op == ARMneon_VCVTFtoS ||
1381//ZZ i->ARMin.NUnary.op == ARMneon_VCVTFtoU ||
1382//ZZ i->ARMin.NUnary.op == ARMneon_VCVTStoF ||
1383//ZZ i->ARMin.NUnary.op == ARMneon_VCVTUtoF)
1384//ZZ return "";
1385//ZZ if (i->ARMin.NUnary.op == ARMneon_VQSHLNSS ||
1386//ZZ i->ARMin.NUnary.op == ARMneon_VQSHLNUU ||
1387//ZZ i->ARMin.NUnary.op == ARMneon_VQSHLNUS) {
1388//ZZ UInt size;
1389//ZZ size = i->ARMin.NUnary.size;
1390//ZZ if (size & 0x40)
1391//ZZ return "64";
1392//ZZ if (size & 0x20)
1393//ZZ return "32";
1394//ZZ if (size & 0x10)
1395//ZZ return "16";
1396//ZZ if (size & 0x08)
1397//ZZ return "8";
1398//ZZ vpanic("showARMNeonDataSize");
1399//ZZ }
1400//ZZ return showARMNeonDataSize_wrk(i->ARMin.NUnary.size);
1401//ZZ case ARMin_NUnaryS:
1402//ZZ if (i->ARMin.NUnaryS.op == ARMneon_VDUP) {
1403//ZZ int size;
1404//ZZ size = i->ARMin.NUnaryS.size;
1405//ZZ if ((size & 1) == 1)
1406//ZZ return "8";
1407//ZZ if ((size & 3) == 2)
1408//ZZ return "16";
1409//ZZ if ((size & 7) == 4)
1410//ZZ return "32";
1411//ZZ vpanic("showARMNeonDataSize");
1412//ZZ }
1413//ZZ return showARMNeonDataSize_wrk(i->ARMin.NUnaryS.size);
1414//ZZ case ARMin_NShift:
1415//ZZ return showARMNeonDataSize_wrk(i->ARMin.NShift.size);
1416//ZZ case ARMin_NDual:
1417//ZZ return showARMNeonDataSize_wrk(i->ARMin.NDual.size);
1418//ZZ default:
1419//ZZ vpanic("showARMNeonDataSize");
1420//ZZ }
1421//ZZ }
1422
1423ARM64Instr* ARM64Instr_Arith ( HReg dst,
1424 HReg argL, ARM64RIA* argR, Bool isAdd ) {
1425 ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
1426 i->tag = ARM64in_Arith;
1427 i->ARM64in.Arith.dst = dst;
1428 i->ARM64in.Arith.argL = argL;
1429 i->ARM64in.Arith.argR = argR;
1430 i->ARM64in.Arith.isAdd = isAdd;
1431 return i;
1432}
1433ARM64Instr* ARM64Instr_Cmp ( HReg argL, ARM64RIA* argR, Bool is64 ) {
1434 ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
1435 i->tag = ARM64in_Cmp;
1436 i->ARM64in.Cmp.argL = argL;
1437 i->ARM64in.Cmp.argR = argR;
1438 i->ARM64in.Cmp.is64 = is64;
1439 return i;
1440}
1441ARM64Instr* ARM64Instr_Logic ( HReg dst,
1442 HReg argL, ARM64RIL* argR, ARM64LogicOp op ) {
1443 ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
1444 i->tag = ARM64in_Logic;
1445 i->ARM64in.Logic.dst = dst;
1446 i->ARM64in.Logic.argL = argL;
1447 i->ARM64in.Logic.argR = argR;
1448 i->ARM64in.Logic.op = op;
1449 return i;
1450}
1451ARM64Instr* ARM64Instr_Test ( HReg argL, ARM64RIL* argR ) {
1452 ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
1453 i->tag = ARM64in_Test;
1454 i->ARM64in.Test.argL = argL;
1455 i->ARM64in.Test.argR = argR;
1456 return i;
1457}
1458ARM64Instr* ARM64Instr_Shift ( HReg dst,
1459 HReg argL, ARM64RI6* argR, ARM64ShiftOp op ) {
1460 ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
1461 i->tag = ARM64in_Shift;
1462 i->ARM64in.Shift.dst = dst;
1463 i->ARM64in.Shift.argL = argL;
1464 i->ARM64in.Shift.argR = argR;
1465 i->ARM64in.Shift.op = op;
1466 return i;
1467}
1468ARM64Instr* ARM64Instr_Unary ( HReg dst, HReg src, ARM64UnaryOp op ) {
1469 ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
1470 i->tag = ARM64in_Unary;
1471 i->ARM64in.Unary.dst = dst;
1472 i->ARM64in.Unary.src = src;
1473 i->ARM64in.Unary.op = op;
1474 return i;
1475}
1476ARM64Instr* ARM64Instr_MovI ( HReg dst, HReg src ) {
1477 ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
1478 i->tag = ARM64in_MovI;
1479 i->ARM64in.MovI.dst = dst;
1480 i->ARM64in.MovI.src = src;
1481 vassert(hregClass(src) == HRcInt64);
1482 vassert(hregClass(dst) == HRcInt64);
1483 return i;
1484}
1485ARM64Instr* ARM64Instr_Imm64 ( HReg dst, ULong imm64 ) {
1486 ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
1487 i->tag = ARM64in_Imm64;
1488 i->ARM64in.Imm64.dst = dst;
1489 i->ARM64in.Imm64.imm64 = imm64;
1490 return i;
1491}
1492ARM64Instr* ARM64Instr_LdSt64 ( Bool isLoad, HReg rD, ARM64AMode* amode ) {
1493 ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
1494 i->tag = ARM64in_LdSt64;
1495 i->ARM64in.LdSt64.isLoad = isLoad;
1496 i->ARM64in.LdSt64.rD = rD;
1497 i->ARM64in.LdSt64.amode = amode;
1498 return i;
1499}
1500ARM64Instr* ARM64Instr_LdSt32 ( Bool isLoad, HReg rD, ARM64AMode* amode ) {
1501 ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
1502 i->tag = ARM64in_LdSt32;
1503 i->ARM64in.LdSt32.isLoad = isLoad;
1504 i->ARM64in.LdSt32.rD = rD;
1505 i->ARM64in.LdSt32.amode = amode;
1506 return i;
1507}
1508ARM64Instr* ARM64Instr_LdSt16 ( Bool isLoad, HReg rD, ARM64AMode* amode ) {
1509 ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
1510 i->tag = ARM64in_LdSt16;
1511 i->ARM64in.LdSt16.isLoad = isLoad;
1512 i->ARM64in.LdSt16.rD = rD;
1513 i->ARM64in.LdSt16.amode = amode;
1514 return i;
1515}
1516ARM64Instr* ARM64Instr_LdSt8 ( Bool isLoad, HReg rD, ARM64AMode* amode ) {
1517 ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
1518 i->tag = ARM64in_LdSt8;
1519 i->ARM64in.LdSt8.isLoad = isLoad;
1520 i->ARM64in.LdSt8.rD = rD;
1521 i->ARM64in.LdSt8.amode = amode;
1522 return i;
1523}
1524ARM64Instr* ARM64Instr_XDirect ( Addr64 dstGA, ARM64AMode* amPC,
1525 ARM64CondCode cond, Bool toFastEP ) {
1526 ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
1527 i->tag = ARM64in_XDirect;
1528 i->ARM64in.XDirect.dstGA = dstGA;
1529 i->ARM64in.XDirect.amPC = amPC;
1530 i->ARM64in.XDirect.cond = cond;
1531 i->ARM64in.XDirect.toFastEP = toFastEP;
1532 return i;
1533}
1534ARM64Instr* ARM64Instr_XIndir ( HReg dstGA, ARM64AMode* amPC,
1535 ARM64CondCode cond ) {
1536 ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
1537 i->tag = ARM64in_XIndir;
1538 i->ARM64in.XIndir.dstGA = dstGA;
1539 i->ARM64in.XIndir.amPC = amPC;
1540 i->ARM64in.XIndir.cond = cond;
1541 return i;
1542}
1543ARM64Instr* ARM64Instr_XAssisted ( HReg dstGA, ARM64AMode* amPC,
1544 ARM64CondCode cond, IRJumpKind jk ) {
1545 ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
1546 i->tag = ARM64in_XAssisted;
1547 i->ARM64in.XAssisted.dstGA = dstGA;
1548 i->ARM64in.XAssisted.amPC = amPC;
1549 i->ARM64in.XAssisted.cond = cond;
1550 i->ARM64in.XAssisted.jk = jk;
1551 return i;
1552}
1553ARM64Instr* ARM64Instr_CSel ( HReg dst, HReg argL, HReg argR,
1554 ARM64CondCode cond ) {
1555 ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
1556 i->tag = ARM64in_CSel;
1557 i->ARM64in.CSel.dst = dst;
1558 i->ARM64in.CSel.argL = argL;
1559 i->ARM64in.CSel.argR = argR;
1560 i->ARM64in.CSel.cond = cond;
1561 return i;
1562}
1563ARM64Instr* ARM64Instr_Call ( ARM64CondCode cond, HWord target, Int nArgRegs,
1564 RetLoc rloc ) {
1565 ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
1566 i->tag = ARM64in_Call;
1567 i->ARM64in.Call.cond = cond;
1568 i->ARM64in.Call.target = target;
1569 i->ARM64in.Call.nArgRegs = nArgRegs;
1570 i->ARM64in.Call.rloc = rloc;
1571 vassert(is_sane_RetLoc(rloc));
1572 return i;
1573}
1574extern ARM64Instr* ARM64Instr_AddToSP ( Int simm ) {
1575 ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
1576 i->tag = ARM64in_AddToSP;
1577 i->ARM64in.AddToSP.simm = simm;
1578 vassert(-4096 < simm && simm < 4096);
1579 vassert(0 == (simm & 0xF));
1580 return i;
1581}
1582extern ARM64Instr* ARM64Instr_FromSP ( HReg dst ) {
1583 ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
1584 i->tag = ARM64in_FromSP;
1585 i->ARM64in.FromSP.dst = dst;
1586 return i;
1587}
1588ARM64Instr* ARM64Instr_Mul ( HReg dst, HReg argL, HReg argR,
1589 ARM64MulOp op ) {
1590 ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
1591 i->tag = ARM64in_Mul;
1592 i->ARM64in.Mul.dst = dst;
1593 i->ARM64in.Mul.argL = argL;
1594 i->ARM64in.Mul.argR = argR;
1595 i->ARM64in.Mul.op = op;
1596 return i;
1597}
sewardj7d009132014-02-20 17:43:38 +00001598ARM64Instr* ARM64Instr_LdrEX ( Int szB ) {
1599 ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
1600 i->tag = ARM64in_LdrEX;
1601 i->ARM64in.LdrEX.szB = szB;
1602 vassert(szB == 8 || szB == 4 || szB == 2 || szB == 1);
1603 return i;
1604}
1605ARM64Instr* ARM64Instr_StrEX ( Int szB ) {
1606 ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
1607 i->tag = ARM64in_StrEX;
1608 i->ARM64in.StrEX.szB = szB;
1609 vassert(szB == 8 || szB == 4 || szB == 2 || szB == 1);
1610 return i;
1611}
1612ARM64Instr* ARM64Instr_MFence ( void ) {
1613 ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
1614 i->tag = ARM64in_MFence;
1615 return i;
1616}
1617//ZZ ARM64Instr* ARM64Instr_CLREX( void ) {
1618//ZZ ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
1619//ZZ i->tag = ARM64in_CLREX;
sewardjbbcf1882014-01-12 12:49:10 +00001620//ZZ return i;
1621//ZZ }
1622ARM64Instr* ARM64Instr_VLdStS ( Bool isLoad, HReg sD, HReg rN, UInt uimm12 ) {
1623 ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
1624 i->tag = ARM64in_VLdStS;
1625 i->ARM64in.VLdStS.isLoad = isLoad;
1626 i->ARM64in.VLdStS.sD = sD;
1627 i->ARM64in.VLdStS.rN = rN;
1628 i->ARM64in.VLdStS.uimm12 = uimm12;
1629 vassert(uimm12 < 16384 && 0 == (uimm12 & 3));
1630 return i;
1631}
1632ARM64Instr* ARM64Instr_VLdStD ( Bool isLoad, HReg dD, HReg rN, UInt uimm12 ) {
1633 ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
1634 i->tag = ARM64in_VLdStD;
1635 i->ARM64in.VLdStD.isLoad = isLoad;
1636 i->ARM64in.VLdStD.dD = dD;
1637 i->ARM64in.VLdStD.rN = rN;
1638 i->ARM64in.VLdStD.uimm12 = uimm12;
1639 vassert(uimm12 < 32768 && 0 == (uimm12 & 7));
1640 return i;
1641}
1642ARM64Instr* ARM64Instr_VLdStQ ( Bool isLoad, HReg rQ, HReg rN ) {
1643 ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
1644 i->tag = ARM64in_VLdStQ;
1645 i->ARM64in.VLdStQ.isLoad = isLoad;
1646 i->ARM64in.VLdStQ.rQ = rQ;
1647 i->ARM64in.VLdStQ.rN = rN;
1648 return i;
1649}
1650ARM64Instr* ARM64Instr_VCvtI2F ( ARM64CvtOp how, HReg rD, HReg rS ) {
1651 ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
1652 i->tag = ARM64in_VCvtI2F;
1653 i->ARM64in.VCvtI2F.how = how;
1654 i->ARM64in.VCvtI2F.rD = rD;
1655 i->ARM64in.VCvtI2F.rS = rS;
1656 return i;
1657}
1658ARM64Instr* ARM64Instr_VCvtF2I ( ARM64CvtOp how, HReg rD, HReg rS,
1659 UChar armRM ) {
1660 ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
1661 i->tag = ARM64in_VCvtF2I;
1662 i->ARM64in.VCvtF2I.how = how;
1663 i->ARM64in.VCvtF2I.rD = rD;
1664 i->ARM64in.VCvtF2I.rS = rS;
1665 i->ARM64in.VCvtF2I.armRM = armRM;
1666 vassert(armRM <= 3);
1667 return i;
1668}
1669ARM64Instr* ARM64Instr_VCvtSD ( Bool sToD, HReg dst, HReg src ) {
1670 ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
1671 i->tag = ARM64in_VCvtSD;
1672 i->ARM64in.VCvtSD.sToD = sToD;
1673 i->ARM64in.VCvtSD.dst = dst;
1674 i->ARM64in.VCvtSD.src = src;
1675 return i;
1676}
1677ARM64Instr* ARM64Instr_VUnaryD ( ARM64FpUnaryOp op, HReg dst, HReg src ) {
1678 ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
1679 i->tag = ARM64in_VUnaryD;
1680 i->ARM64in.VUnaryD.op = op;
1681 i->ARM64in.VUnaryD.dst = dst;
1682 i->ARM64in.VUnaryD.src = src;
1683 return i;
1684}
1685ARM64Instr* ARM64Instr_VUnaryS ( ARM64FpUnaryOp op, HReg dst, HReg src ) {
1686 ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
1687 i->tag = ARM64in_VUnaryS;
1688 i->ARM64in.VUnaryS.op = op;
1689 i->ARM64in.VUnaryS.dst = dst;
1690 i->ARM64in.VUnaryS.src = src;
1691 return i;
1692}
1693ARM64Instr* ARM64Instr_VBinD ( ARM64FpBinOp op,
1694 HReg dst, HReg argL, HReg argR ) {
1695 ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
1696 i->tag = ARM64in_VBinD;
1697 i->ARM64in.VBinD.op = op;
1698 i->ARM64in.VBinD.dst = dst;
1699 i->ARM64in.VBinD.argL = argL;
1700 i->ARM64in.VBinD.argR = argR;
1701 return i;
1702}
1703ARM64Instr* ARM64Instr_VBinS ( ARM64FpBinOp op,
1704 HReg dst, HReg argL, HReg argR ) {
1705 ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
1706 i->tag = ARM64in_VBinS;
1707 i->ARM64in.VBinS.op = op;
1708 i->ARM64in.VBinS.dst = dst;
1709 i->ARM64in.VBinS.argL = argL;
1710 i->ARM64in.VBinS.argR = argR;
1711 return i;
1712}
1713ARM64Instr* ARM64Instr_VCmpD ( HReg argL, HReg argR ) {
1714 ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
1715 i->tag = ARM64in_VCmpD;
1716 i->ARM64in.VCmpD.argL = argL;
1717 i->ARM64in.VCmpD.argR = argR;
1718 return i;
1719}
1720ARM64Instr* ARM64Instr_VCmpS ( HReg argL, HReg argR ) {
1721 ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
1722 i->tag = ARM64in_VCmpS;
1723 i->ARM64in.VCmpS.argL = argL;
1724 i->ARM64in.VCmpS.argR = argR;
1725 return i;
1726}
1727ARM64Instr* ARM64Instr_FPCR ( Bool toFPCR, HReg iReg ) {
1728 ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
1729 i->tag = ARM64in_FPCR;
1730 i->ARM64in.FPCR.toFPCR = toFPCR;
1731 i->ARM64in.FPCR.iReg = iReg;
1732 return i;
1733}
sewardj12972182014-08-04 08:09:47 +00001734ARM64Instr* ARM64Instr_FPSR ( Bool toFPSR, HReg iReg ) {
1735 ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
1736 i->tag = ARM64in_FPSR;
1737 i->ARM64in.FPSR.toFPSR = toFPSR;
1738 i->ARM64in.FPSR.iReg = iReg;
1739 return i;
1740}
sewardj606c4ba2014-01-26 19:11:14 +00001741ARM64Instr* ARM64Instr_VBinV ( ARM64VecBinOp op,
1742 HReg dst, HReg argL, HReg argR ) {
1743 ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
1744 i->tag = ARM64in_VBinV;
1745 i->ARM64in.VBinV.op = op;
1746 i->ARM64in.VBinV.dst = dst;
1747 i->ARM64in.VBinV.argL = argL;
1748 i->ARM64in.VBinV.argR = argR;
1749 return i;
1750}
sewardjfab09142014-02-10 10:28:13 +00001751ARM64Instr* ARM64Instr_VUnaryV ( ARM64VecUnaryOp op, HReg dst, HReg arg ) {
1752 ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
1753 i->tag = ARM64in_VUnaryV;
1754 i->ARM64in.VUnaryV.op = op;
1755 i->ARM64in.VUnaryV.dst = dst;
1756 i->ARM64in.VUnaryV.arg = arg;
1757 return i;
1758}
sewardjecedd982014-08-11 14:02:47 +00001759ARM64Instr* ARM64Instr_VNarrowV ( ARM64VecNarrowOp op,
1760 UInt dszBlg2, HReg dst, HReg src ) {
sewardj606c4ba2014-01-26 19:11:14 +00001761 ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
1762 i->tag = ARM64in_VNarrowV;
sewardjecedd982014-08-11 14:02:47 +00001763 i->ARM64in.VNarrowV.op = op;
sewardj606c4ba2014-01-26 19:11:14 +00001764 i->ARM64in.VNarrowV.dszBlg2 = dszBlg2;
1765 i->ARM64in.VNarrowV.dst = dst;
1766 i->ARM64in.VNarrowV.src = src;
1767 vassert(dszBlg2 == 0 || dszBlg2 == 1 || dszBlg2 == 2);
1768 return i;
1769}
sewardje520bb32014-02-17 11:00:53 +00001770ARM64Instr* ARM64Instr_VShiftImmV ( ARM64VecShiftOp op,
1771 HReg dst, HReg src, UInt amt ) {
1772 ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
1773 i->tag = ARM64in_VShiftImmV;
1774 i->ARM64in.VShiftImmV.op = op;
1775 i->ARM64in.VShiftImmV.dst = dst;
1776 i->ARM64in.VShiftImmV.src = src;
1777 i->ARM64in.VShiftImmV.amt = amt;
sewardja97dddf2014-08-14 22:26:52 +00001778 UInt minSh = 0;
sewardje520bb32014-02-17 11:00:53 +00001779 UInt maxSh = 0;
1780 switch (op) {
sewardja97dddf2014-08-14 22:26:52 +00001781 /* For right shifts, the allowed shift amounts are 1 .. lane_size.
1782 For left shifts, the allowed shift amounts are 0 .. lane_size-1.
1783 */
sewardje520bb32014-02-17 11:00:53 +00001784 case ARM64vecsh_USHR64x2: case ARM64vecsh_SSHR64x2:
sewardja97dddf2014-08-14 22:26:52 +00001785 case ARM64vecsh_UQSHRN2SD: case ARM64vecsh_SQSHRN2SD:
sewardjecedd982014-08-11 14:02:47 +00001786 case ARM64vecsh_SQSHRUN2SD:
1787 case ARM64vecsh_UQRSHRN2SD: case ARM64vecsh_SQRSHRN2SD:
1788 case ARM64vecsh_SQRSHRUN2SD:
sewardja97dddf2014-08-14 22:26:52 +00001789 minSh = 1; maxSh = 64; break;
1790 case ARM64vecsh_SHL64x2:
1791 case ARM64vecsh_UQSHL64x2: case ARM64vecsh_SQSHL64x2:
1792 case ARM64vecsh_SQSHLU64x2:
1793 minSh = 0; maxSh = 63; break;
1794 case ARM64vecsh_USHR32x4: case ARM64vecsh_SSHR32x4:
1795 case ARM64vecsh_UQSHRN4HS: case ARM64vecsh_SQSHRN4HS:
sewardjecedd982014-08-11 14:02:47 +00001796 case ARM64vecsh_SQSHRUN4HS:
1797 case ARM64vecsh_UQRSHRN4HS: case ARM64vecsh_SQRSHRN4HS:
1798 case ARM64vecsh_SQRSHRUN4HS:
sewardja97dddf2014-08-14 22:26:52 +00001799 minSh = 1; maxSh = 32; break;
1800 case ARM64vecsh_SHL32x4:
1801 case ARM64vecsh_UQSHL32x4: case ARM64vecsh_SQSHL32x4:
1802 case ARM64vecsh_SQSHLU32x4:
1803 minSh = 0; maxSh = 31; break;
1804 case ARM64vecsh_USHR16x8: case ARM64vecsh_SSHR16x8:
1805 case ARM64vecsh_UQSHRN8BH: case ARM64vecsh_SQSHRN8BH:
sewardjecedd982014-08-11 14:02:47 +00001806 case ARM64vecsh_SQSHRUN8BH:
1807 case ARM64vecsh_UQRSHRN8BH: case ARM64vecsh_SQRSHRN8BH:
1808 case ARM64vecsh_SQRSHRUN8BH:
sewardja97dddf2014-08-14 22:26:52 +00001809 minSh = 1; maxSh = 16; break;
1810 case ARM64vecsh_SHL16x8:
1811 case ARM64vecsh_UQSHL16x8: case ARM64vecsh_SQSHL16x8:
1812 case ARM64vecsh_SQSHLU16x8:
1813 minSh = 0; maxSh = 15; break;
1814 case ARM64vecsh_USHR8x16: case ARM64vecsh_SSHR8x16:
1815 minSh = 1; maxSh = 8; break;
1816 case ARM64vecsh_SHL8x16:
1817 case ARM64vecsh_UQSHL8x16: case ARM64vecsh_SQSHL8x16:
1818 case ARM64vecsh_SQSHLU8x16:
1819 minSh = 0; maxSh = 7; break;
sewardje520bb32014-02-17 11:00:53 +00001820 default:
1821 vassert(0);
1822 }
1823 vassert(maxSh > 0);
sewardja97dddf2014-08-14 22:26:52 +00001824 vassert(amt >= minSh && amt <= maxSh);
sewardje520bb32014-02-17 11:00:53 +00001825 return i;
1826}
sewardjab33a7a2014-06-19 22:20:47 +00001827ARM64Instr* ARM64Instr_VExtV ( HReg dst, HReg srcLo, HReg srcHi, UInt amtB ) {
1828 ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
1829 i->tag = ARM64in_VExtV;
1830 i->ARM64in.VExtV.dst = dst;
1831 i->ARM64in.VExtV.srcLo = srcLo;
1832 i->ARM64in.VExtV.srcHi = srcHi;
1833 i->ARM64in.VExtV.amtB = amtB;
1834 vassert(amtB >= 1 && amtB <= 15);
1835 return i;
1836}
sewardjbbcf1882014-01-12 12:49:10 +00001837//ZZ ARMInstr* ARMInstr_VAluS ( ARMVfpOp op, HReg dst, HReg argL, HReg argR ) {
1838//ZZ ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
1839//ZZ i->tag = ARMin_VAluS;
1840//ZZ i->ARMin.VAluS.op = op;
1841//ZZ i->ARMin.VAluS.dst = dst;
1842//ZZ i->ARMin.VAluS.argL = argL;
1843//ZZ i->ARMin.VAluS.argR = argR;
1844//ZZ return i;
1845//ZZ }
1846//ZZ ARMInstr* ARMInstr_VCMovD ( ARMCondCode cond, HReg dst, HReg src ) {
1847//ZZ ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
1848//ZZ i->tag = ARMin_VCMovD;
1849//ZZ i->ARMin.VCMovD.cond = cond;
1850//ZZ i->ARMin.VCMovD.dst = dst;
1851//ZZ i->ARMin.VCMovD.src = src;
1852//ZZ vassert(cond != ARMcc_AL);
1853//ZZ return i;
1854//ZZ }
1855//ZZ ARMInstr* ARMInstr_VCMovS ( ARMCondCode cond, HReg dst, HReg src ) {
1856//ZZ ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
1857//ZZ i->tag = ARMin_VCMovS;
1858//ZZ i->ARMin.VCMovS.cond = cond;
1859//ZZ i->ARMin.VCMovS.dst = dst;
1860//ZZ i->ARMin.VCMovS.src = src;
1861//ZZ vassert(cond != ARMcc_AL);
1862//ZZ return i;
1863//ZZ }
1864//ZZ ARMInstr* ARMInstr_VXferD ( Bool toD, HReg dD, HReg rHi, HReg rLo ) {
1865//ZZ ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
1866//ZZ i->tag = ARMin_VXferD;
1867//ZZ i->ARMin.VXferD.toD = toD;
1868//ZZ i->ARMin.VXferD.dD = dD;
1869//ZZ i->ARMin.VXferD.rHi = rHi;
1870//ZZ i->ARMin.VXferD.rLo = rLo;
1871//ZZ return i;
1872//ZZ }
1873//ZZ ARMInstr* ARMInstr_VXferS ( Bool toS, HReg fD, HReg rLo ) {
1874//ZZ ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
1875//ZZ i->tag = ARMin_VXferS;
1876//ZZ i->ARMin.VXferS.toS = toS;
1877//ZZ i->ARMin.VXferS.fD = fD;
1878//ZZ i->ARMin.VXferS.rLo = rLo;
1879//ZZ return i;
1880//ZZ }
1881//ZZ ARMInstr* ARMInstr_VCvtID ( Bool iToD, Bool syned,
1882//ZZ HReg dst, HReg src ) {
1883//ZZ ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
1884//ZZ i->tag = ARMin_VCvtID;
1885//ZZ i->ARMin.VCvtID.iToD = iToD;
1886//ZZ i->ARMin.VCvtID.syned = syned;
1887//ZZ i->ARMin.VCvtID.dst = dst;
1888//ZZ i->ARMin.VCvtID.src = src;
1889//ZZ return i;
1890//ZZ }
sewardjbbcf1882014-01-12 12:49:10 +00001891//ZZ ARMInstr* ARMInstr_NLdStD ( Bool isLoad, HReg dD, ARMAModeN *amode ) {
1892//ZZ ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
1893//ZZ i->tag = ARMin_NLdStD;
1894//ZZ i->ARMin.NLdStD.isLoad = isLoad;
1895//ZZ i->ARMin.NLdStD.dD = dD;
1896//ZZ i->ARMin.NLdStD.amode = amode;
1897//ZZ return i;
1898//ZZ }
1899//ZZ
1900//ZZ ARMInstr* ARMInstr_NUnary ( ARMNeonUnOp op, HReg dQ, HReg nQ,
1901//ZZ UInt size, Bool Q ) {
1902//ZZ ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
1903//ZZ i->tag = ARMin_NUnary;
1904//ZZ i->ARMin.NUnary.op = op;
1905//ZZ i->ARMin.NUnary.src = nQ;
1906//ZZ i->ARMin.NUnary.dst = dQ;
1907//ZZ i->ARMin.NUnary.size = size;
1908//ZZ i->ARMin.NUnary.Q = Q;
1909//ZZ return i;
1910//ZZ }
1911//ZZ
1912//ZZ ARMInstr* ARMInstr_NUnaryS ( ARMNeonUnOpS op, ARMNRS* dst, ARMNRS* src,
1913//ZZ UInt size, Bool Q ) {
1914//ZZ ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
1915//ZZ i->tag = ARMin_NUnaryS;
1916//ZZ i->ARMin.NUnaryS.op = op;
1917//ZZ i->ARMin.NUnaryS.src = src;
1918//ZZ i->ARMin.NUnaryS.dst = dst;
1919//ZZ i->ARMin.NUnaryS.size = size;
1920//ZZ i->ARMin.NUnaryS.Q = Q;
1921//ZZ return i;
1922//ZZ }
1923//ZZ
1924//ZZ ARMInstr* ARMInstr_NDual ( ARMNeonDualOp op, HReg nQ, HReg mQ,
1925//ZZ UInt size, Bool Q ) {
1926//ZZ ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
1927//ZZ i->tag = ARMin_NDual;
1928//ZZ i->ARMin.NDual.op = op;
1929//ZZ i->ARMin.NDual.arg1 = nQ;
1930//ZZ i->ARMin.NDual.arg2 = mQ;
1931//ZZ i->ARMin.NDual.size = size;
1932//ZZ i->ARMin.NDual.Q = Q;
1933//ZZ return i;
1934//ZZ }
1935//ZZ
1936//ZZ ARMInstr* ARMInstr_NBinary ( ARMNeonBinOp op,
1937//ZZ HReg dst, HReg argL, HReg argR,
1938//ZZ UInt size, Bool Q ) {
1939//ZZ ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
1940//ZZ i->tag = ARMin_NBinary;
1941//ZZ i->ARMin.NBinary.op = op;
1942//ZZ i->ARMin.NBinary.argL = argL;
1943//ZZ i->ARMin.NBinary.argR = argR;
1944//ZZ i->ARMin.NBinary.dst = dst;
1945//ZZ i->ARMin.NBinary.size = size;
1946//ZZ i->ARMin.NBinary.Q = Q;
1947//ZZ return i;
1948//ZZ }
1949
1950ARM64Instr* ARM64Instr_VImmQ (HReg rQ, UShort imm) {
1951 ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
1952 i->tag = ARM64in_VImmQ;
1953 i->ARM64in.VImmQ.rQ = rQ;
1954 i->ARM64in.VImmQ.imm = imm;
1955 return i;
1956}
1957ARM64Instr* ARM64Instr_VDfromX ( HReg rD, HReg rX ) {
1958 ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
1959 i->tag = ARM64in_VDfromX;
1960 i->ARM64in.VDfromX.rD = rD;
1961 i->ARM64in.VDfromX.rX = rX;
1962 return i;
1963}
sewardj12972182014-08-04 08:09:47 +00001964ARM64Instr* ARM64Instr_VQfromX ( HReg rQ, HReg rXlo ) {
1965 ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
1966 i->tag = ARM64in_VQfromX;
1967 i->ARM64in.VQfromX.rQ = rQ;
1968 i->ARM64in.VQfromX.rXlo = rXlo;
1969 return i;
1970}
sewardjbbcf1882014-01-12 12:49:10 +00001971ARM64Instr* ARM64Instr_VQfromXX ( HReg rQ, HReg rXhi, HReg rXlo ) {
1972 ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
1973 i->tag = ARM64in_VQfromXX;
1974 i->ARM64in.VQfromXX.rQ = rQ;
1975 i->ARM64in.VQfromXX.rXhi = rXhi;
1976 i->ARM64in.VQfromXX.rXlo = rXlo;
1977 return i;
1978}
1979ARM64Instr* ARM64Instr_VXfromQ ( HReg rX, HReg rQ, UInt laneNo ) {
1980 ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
1981 i->tag = ARM64in_VXfromQ;
1982 i->ARM64in.VXfromQ.rX = rX;
1983 i->ARM64in.VXfromQ.rQ = rQ;
1984 i->ARM64in.VXfromQ.laneNo = laneNo;
1985 vassert(laneNo <= 1);
1986 return i;
1987}
sewardj85fbb022014-06-12 13:16:01 +00001988ARM64Instr* ARM64Instr_VXfromDorS ( HReg rX, HReg rDorS, Bool fromD ) {
1989 ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
1990 i->tag = ARM64in_VXfromDorS;
1991 i->ARM64in.VXfromDorS.rX = rX;
1992 i->ARM64in.VXfromDorS.rDorS = rDorS;
1993 i->ARM64in.VXfromDorS.fromD = fromD;
1994 return i;
1995}
sewardjbbcf1882014-01-12 12:49:10 +00001996ARM64Instr* ARM64Instr_VMov ( UInt szB, HReg dst, HReg src ) {
1997 ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
1998 i->tag = ARM64in_VMov;
1999 i->ARM64in.VMov.szB = szB;
2000 i->ARM64in.VMov.dst = dst;
2001 i->ARM64in.VMov.src = src;
2002 switch (szB) {
2003 case 16:
2004 vassert(hregClass(src) == HRcVec128);
2005 vassert(hregClass(dst) == HRcVec128);
2006 break;
2007 case 8:
2008 vassert(hregClass(src) == HRcFlt64);
2009 vassert(hregClass(dst) == HRcFlt64);
2010 break;
2011 default:
2012 vpanic("ARM64Instr_VMov");
2013 }
2014 return i;
2015}
2016
2017//ZZ ARMInstr* ARMInstr_NCMovQ ( ARMCondCode cond, HReg dst, HReg src ) {
2018//ZZ ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
2019//ZZ i->tag = ARMin_NCMovQ;
2020//ZZ i->ARMin.NCMovQ.cond = cond;
2021//ZZ i->ARMin.NCMovQ.dst = dst;
2022//ZZ i->ARMin.NCMovQ.src = src;
2023//ZZ vassert(cond != ARMcc_AL);
2024//ZZ return i;
2025//ZZ }
2026//ZZ
2027//ZZ ARMInstr* ARMInstr_NShift ( ARMNeonShiftOp op,
2028//ZZ HReg dst, HReg argL, HReg argR,
2029//ZZ UInt size, Bool Q ) {
2030//ZZ ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
2031//ZZ i->tag = ARMin_NShift;
2032//ZZ i->ARMin.NShift.op = op;
2033//ZZ i->ARMin.NShift.argL = argL;
2034//ZZ i->ARMin.NShift.argR = argR;
2035//ZZ i->ARMin.NShift.dst = dst;
2036//ZZ i->ARMin.NShift.size = size;
2037//ZZ i->ARMin.NShift.Q = Q;
2038//ZZ return i;
2039//ZZ }
2040//ZZ
2041//ZZ ARMInstr* ARMInstr_NShl64 ( HReg dst, HReg src, UInt amt )
2042//ZZ {
2043//ZZ ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
2044//ZZ i->tag = ARMin_NShl64;
2045//ZZ i->ARMin.NShl64.dst = dst;
2046//ZZ i->ARMin.NShl64.src = src;
2047//ZZ i->ARMin.NShl64.amt = amt;
2048//ZZ vassert(amt >= 1 && amt <= 63);
2049//ZZ return i;
2050//ZZ }
2051//ZZ
2052//ZZ /* Helper copy-pasted from isel.c */
2053//ZZ static Bool fitsIn8x4 ( UInt* u8, UInt* u4, UInt u )
2054//ZZ {
2055//ZZ UInt i;
2056//ZZ for (i = 0; i < 16; i++) {
2057//ZZ if (0 == (u & 0xFFFFFF00)) {
2058//ZZ *u8 = u;
2059//ZZ *u4 = i;
2060//ZZ return True;
2061//ZZ }
2062//ZZ u = ROR32(u, 30);
2063//ZZ }
2064//ZZ vassert(i == 16);
2065//ZZ return False;
2066//ZZ }
2067//ZZ
2068//ZZ ARMInstr* ARMInstr_Add32 ( HReg rD, HReg rN, UInt imm32 ) {
2069//ZZ UInt u8, u4;
2070//ZZ ARMInstr *i = LibVEX_Alloc(sizeof(ARMInstr));
2071//ZZ /* Try to generate single ADD if possible */
2072//ZZ if (fitsIn8x4(&u8, &u4, imm32)) {
2073//ZZ i->tag = ARMin_Alu;
2074//ZZ i->ARMin.Alu.op = ARMalu_ADD;
2075//ZZ i->ARMin.Alu.dst = rD;
2076//ZZ i->ARMin.Alu.argL = rN;
2077//ZZ i->ARMin.Alu.argR = ARMRI84_I84(u8, u4);
2078//ZZ } else {
2079//ZZ i->tag = ARMin_Add32;
2080//ZZ i->ARMin.Add32.rD = rD;
2081//ZZ i->ARMin.Add32.rN = rN;
2082//ZZ i->ARMin.Add32.imm32 = imm32;
2083//ZZ }
2084//ZZ return i;
2085//ZZ }
2086
2087ARM64Instr* ARM64Instr_EvCheck ( ARM64AMode* amCounter,
2088 ARM64AMode* amFailAddr ) {
2089 ARM64Instr* i = LibVEX_Alloc(sizeof(ARM64Instr));
2090 i->tag = ARM64in_EvCheck;
2091 i->ARM64in.EvCheck.amCounter = amCounter;
2092 i->ARM64in.EvCheck.amFailAddr = amFailAddr;
2093 return i;
2094}
2095
2096//ZZ ARMInstr* ARMInstr_ProfInc ( void ) {
2097//ZZ ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
2098//ZZ i->tag = ARMin_ProfInc;
2099//ZZ return i;
2100//ZZ }
2101
2102/* ... */
2103
2104void ppARM64Instr ( ARM64Instr* i ) {
2105 switch (i->tag) {
2106 case ARM64in_Arith:
2107 vex_printf("%s ", i->ARM64in.Arith.isAdd ? "add" : "sub");
2108 ppHRegARM64(i->ARM64in.Arith.dst);
2109 vex_printf(", ");
2110 ppHRegARM64(i->ARM64in.Arith.argL);
2111 vex_printf(", ");
2112 ppARM64RIA(i->ARM64in.Arith.argR);
2113 return;
2114 case ARM64in_Cmp:
2115 vex_printf("cmp%s ", i->ARM64in.Cmp.is64 ? " " : "(w)" );
2116 ppHRegARM64(i->ARM64in.Cmp.argL);
2117 vex_printf(", ");
2118 ppARM64RIA(i->ARM64in.Cmp.argR);
2119 return;
2120 case ARM64in_Logic:
2121 vex_printf("%s ", showARM64LogicOp(i->ARM64in.Logic.op));
2122 ppHRegARM64(i->ARM64in.Logic.dst);
2123 vex_printf(", ");
2124 ppHRegARM64(i->ARM64in.Logic.argL);
2125 vex_printf(", ");
2126 ppARM64RIL(i->ARM64in.Logic.argR);
2127 return;
2128 case ARM64in_Test:
2129 vex_printf("tst ");
2130 ppHRegARM64(i->ARM64in.Test.argL);
2131 vex_printf(", ");
2132 ppARM64RIL(i->ARM64in.Test.argR);
2133 return;
2134 case ARM64in_Shift:
2135 vex_printf("%s ", showARM64ShiftOp(i->ARM64in.Shift.op));
2136 ppHRegARM64(i->ARM64in.Shift.dst);
2137 vex_printf(", ");
2138 ppHRegARM64(i->ARM64in.Shift.argL);
2139 vex_printf(", ");
2140 ppARM64RI6(i->ARM64in.Shift.argR);
2141 return;
2142 case ARM64in_Unary:
2143 vex_printf("%s ", showARM64UnaryOp(i->ARM64in.Unary.op));
2144 ppHRegARM64(i->ARM64in.Unary.dst);
2145 vex_printf(", ");
2146 ppHRegARM64(i->ARM64in.Unary.src);
2147 return;
2148 case ARM64in_MovI:
2149 vex_printf("mov ");
2150 ppHRegARM64(i->ARM64in.MovI.dst);
2151 vex_printf(", ");
2152 ppHRegARM64(i->ARM64in.MovI.src);
2153 return;
2154 case ARM64in_Imm64:
2155 vex_printf("imm64 ");
2156 ppHRegARM64(i->ARM64in.Imm64.dst);
2157 vex_printf(", 0x%llx", i->ARM64in.Imm64.imm64);
2158 return;
2159 case ARM64in_LdSt64:
2160 if (i->ARM64in.LdSt64.isLoad) {
2161 vex_printf("ldr ");
2162 ppHRegARM64(i->ARM64in.LdSt64.rD);
2163 vex_printf(", ");
2164 ppARM64AMode(i->ARM64in.LdSt64.amode);
2165 } else {
2166 vex_printf("str ");
2167 ppARM64AMode(i->ARM64in.LdSt64.amode);
2168 vex_printf(", ");
2169 ppHRegARM64(i->ARM64in.LdSt64.rD);
2170 }
2171 return;
2172 case ARM64in_LdSt32:
2173 if (i->ARM64in.LdSt32.isLoad) {
2174 vex_printf("ldruw ");
2175 ppHRegARM64(i->ARM64in.LdSt32.rD);
2176 vex_printf(", ");
2177 ppARM64AMode(i->ARM64in.LdSt32.amode);
2178 } else {
2179 vex_printf("strw ");
2180 ppARM64AMode(i->ARM64in.LdSt32.amode);
2181 vex_printf(", ");
2182 ppHRegARM64(i->ARM64in.LdSt32.rD);
2183 }
2184 return;
2185 case ARM64in_LdSt16:
2186 if (i->ARM64in.LdSt16.isLoad) {
2187 vex_printf("ldruh ");
2188 ppHRegARM64(i->ARM64in.LdSt16.rD);
2189 vex_printf(", ");
2190 ppARM64AMode(i->ARM64in.LdSt16.amode);
2191 } else {
2192 vex_printf("strh ");
2193 ppARM64AMode(i->ARM64in.LdSt16.amode);
2194 vex_printf(", ");
2195 ppHRegARM64(i->ARM64in.LdSt16.rD);
2196 }
2197 return;
2198 case ARM64in_LdSt8:
2199 if (i->ARM64in.LdSt8.isLoad) {
2200 vex_printf("ldrub ");
2201 ppHRegARM64(i->ARM64in.LdSt8.rD);
2202 vex_printf(", ");
2203 ppARM64AMode(i->ARM64in.LdSt8.amode);
2204 } else {
2205 vex_printf("strb ");
2206 ppARM64AMode(i->ARM64in.LdSt8.amode);
2207 vex_printf(", ");
2208 ppHRegARM64(i->ARM64in.LdSt8.rD);
2209 }
2210 return;
2211 case ARM64in_XDirect:
2212 vex_printf("(xDirect) ");
2213 vex_printf("if (%%pstate.%s) { ",
2214 showARM64CondCode(i->ARM64in.XDirect.cond));
2215 vex_printf("imm64 x9,0x%llx; ", i->ARM64in.XDirect.dstGA);
2216 vex_printf("str x9,");
2217 ppARM64AMode(i->ARM64in.XDirect.amPC);
2218 vex_printf("; imm64-exactly4 x9,$disp_cp_chain_me_to_%sEP; ",
2219 i->ARM64in.XDirect.toFastEP ? "fast" : "slow");
2220 vex_printf("blr x9 }");
2221 return;
2222 case ARM64in_XIndir:
2223 vex_printf("(xIndir) ");
2224 vex_printf("if (%%pstate.%s) { ",
2225 showARM64CondCode(i->ARM64in.XIndir.cond));
2226 vex_printf("str ");
2227 ppHRegARM64(i->ARM64in.XIndir.dstGA);
2228 vex_printf(",");
2229 ppARM64AMode(i->ARM64in.XIndir.amPC);
2230 vex_printf("; imm64 x9,$disp_cp_xindir; ");
2231 vex_printf("br x9 }");
2232 return;
2233 case ARM64in_XAssisted:
2234 vex_printf("(xAssisted) ");
2235 vex_printf("if (%%pstate.%s) { ",
2236 showARM64CondCode(i->ARM64in.XAssisted.cond));
2237 vex_printf("str ");
2238 ppHRegARM64(i->ARM64in.XAssisted.dstGA);
2239 vex_printf(",");
2240 ppARM64AMode(i->ARM64in.XAssisted.amPC);
2241 vex_printf("; movw x21,$IRJumpKind_to_TRCVAL(%d); ",
2242 (Int)i->ARM64in.XAssisted.jk);
2243 vex_printf("imm64 x9,$disp_cp_xassisted; ");
2244 vex_printf("br x9 }");
2245 return;
2246 case ARM64in_CSel:
2247 vex_printf("csel ");
2248 ppHRegARM64(i->ARM64in.CSel.dst);
2249 vex_printf(", ");
2250 ppHRegARM64(i->ARM64in.CSel.argL);
2251 vex_printf(", ");
2252 ppHRegARM64(i->ARM64in.CSel.argR);
2253 vex_printf(", %s", showARM64CondCode(i->ARM64in.CSel.cond));
2254 return;
2255 case ARM64in_Call:
2256 vex_printf("call%s ",
2257 i->ARM64in.Call.cond==ARM64cc_AL
2258 ? " " : showARM64CondCode(i->ARM64in.Call.cond));
2259 vex_printf("0x%lx [nArgRegs=%d, ",
2260 i->ARM64in.Call.target, i->ARM64in.Call.nArgRegs);
2261 ppRetLoc(i->ARM64in.Call.rloc);
2262 vex_printf("]");
2263 return;
2264 case ARM64in_AddToSP: {
2265 Int simm = i->ARM64in.AddToSP.simm;
2266 vex_printf("%s xsp, xsp, #%d", simm < 0 ? "sub" : "add",
2267 simm < 0 ? -simm : simm);
2268 return;
2269 }
2270 case ARM64in_FromSP:
2271 vex_printf("mov ");
2272 ppHRegARM64(i->ARM64in.FromSP.dst);
2273 vex_printf(", xsp");
2274 return;
2275 case ARM64in_Mul:
2276 vex_printf("%s ", showARM64MulOp(i->ARM64in.Mul.op));
2277 ppHRegARM64(i->ARM64in.Mul.dst);
2278 vex_printf(", ");
2279 ppHRegARM64(i->ARM64in.Mul.argL);
2280 vex_printf(", ");
2281 ppHRegARM64(i->ARM64in.Mul.argR);
2282 return;
sewardj7d009132014-02-20 17:43:38 +00002283
2284 case ARM64in_LdrEX: {
2285 const HChar* sz = " ";
2286 switch (i->ARM64in.LdrEX.szB) {
2287 case 1: sz = "b"; break;
2288 case 2: sz = "h"; break;
2289 case 4: case 8: break;
2290 default: vassert(0);
2291 }
2292 vex_printf("ldxr%s %c2, [x4]",
2293 sz, i->ARM64in.LdrEX.szB == 8 ? 'x' : 'w');
2294 return;
2295 }
2296 case ARM64in_StrEX: {
2297 const HChar* sz = " ";
2298 switch (i->ARM64in.StrEX.szB) {
2299 case 1: sz = "b"; break;
2300 case 2: sz = "h"; break;
2301 case 4: case 8: break;
2302 default: vassert(0);
2303 }
2304 vex_printf("stxr%s w0, %c2, [x4]",
2305 sz, i->ARM64in.StrEX.szB == 8 ? 'x' : 'w');
2306 return;
2307 }
2308 case ARM64in_MFence:
2309 vex_printf("(mfence) dsb sy; dmb sy; isb");
2310 return;
2311//ZZ case ARM64in_CLREX:
2312//ZZ vex_printf("clrex");
sewardjbbcf1882014-01-12 12:49:10 +00002313//ZZ return;
sewardjbbcf1882014-01-12 12:49:10 +00002314 case ARM64in_VLdStS:
2315 if (i->ARM64in.VLdStS.isLoad) {
2316 vex_printf("ldr ");
2317 ppHRegARM64asSreg(i->ARM64in.VLdStS.sD);
2318 vex_printf(", %u(", i->ARM64in.VLdStS.uimm12);
2319 ppHRegARM64(i->ARM64in.VLdStS.rN);
2320 vex_printf(")");
2321 } else {
2322 vex_printf("str ");
2323 vex_printf("%u(", i->ARM64in.VLdStS.uimm12);
2324 ppHRegARM64(i->ARM64in.VLdStS.rN);
2325 vex_printf("), ");
2326 ppHRegARM64asSreg(i->ARM64in.VLdStS.sD);
2327 }
2328 return;
2329 case ARM64in_VLdStD:
2330 if (i->ARM64in.VLdStD.isLoad) {
2331 vex_printf("ldr ");
2332 ppHRegARM64(i->ARM64in.VLdStD.dD);
2333 vex_printf(", %u(", i->ARM64in.VLdStD.uimm12);
2334 ppHRegARM64(i->ARM64in.VLdStD.rN);
2335 vex_printf(")");
2336 } else {
2337 vex_printf("str ");
2338 vex_printf("%u(", i->ARM64in.VLdStD.uimm12);
2339 ppHRegARM64(i->ARM64in.VLdStD.rN);
2340 vex_printf("), ");
2341 ppHRegARM64(i->ARM64in.VLdStD.dD);
2342 }
2343 return;
2344 case ARM64in_VLdStQ:
2345 if (i->ARM64in.VLdStQ.isLoad)
2346 vex_printf("ld1.2d {");
2347 else
2348 vex_printf("st1.2d {");
2349 ppHRegARM64(i->ARM64in.VLdStQ.rQ);
2350 vex_printf("}, [");
2351 ppHRegARM64(i->ARM64in.VLdStQ.rN);
2352 vex_printf("]");
2353 return;
2354 case ARM64in_VCvtI2F: {
2355 HChar syn = '?';
2356 UInt fszB = 0;
2357 UInt iszB = 0;
2358 characteriseARM64CvtOp(&syn, &fszB, &iszB, i->ARM64in.VCvtI2F.how);
2359 vex_printf("%ccvtf ", syn);
2360 ppHRegARM64(i->ARM64in.VCvtI2F.rD);
2361 vex_printf("(%c-reg), ", fszB == 4 ? 'S' : 'D');
2362 ppHRegARM64(i->ARM64in.VCvtI2F.rS);
2363 vex_printf("(%c-reg)", iszB == 4 ? 'W' : 'X');
2364 return;
2365 }
2366 case ARM64in_VCvtF2I: {
2367 HChar syn = '?';
2368 UInt fszB = 0;
2369 UInt iszB = 0;
2370 HChar rmo = '?';
2371 characteriseARM64CvtOp(&syn, &fszB, &iszB, i->ARM64in.VCvtF2I.how);
2372 UChar armRM = i->ARM64in.VCvtF2I.armRM;
2373 if (armRM < 4) rmo = "npmz"[armRM];
2374 vex_printf("fcvt%c%c ", rmo, syn);
2375 ppHRegARM64(i->ARM64in.VCvtF2I.rD);
2376 vex_printf("(%c-reg), ", iszB == 4 ? 'W' : 'X');
2377 ppHRegARM64(i->ARM64in.VCvtF2I.rS);
2378 vex_printf("(%c-reg)", fszB == 4 ? 'S' : 'D');
2379 return;
2380 }
2381 case ARM64in_VCvtSD:
2382 vex_printf("fcvt%s ", i->ARM64in.VCvtSD.sToD ? "s2d" : "d2s");
2383 if (i->ARM64in.VCvtSD.sToD) {
2384 ppHRegARM64(i->ARM64in.VCvtSD.dst);
2385 vex_printf(", ");
2386 ppHRegARM64asSreg(i->ARM64in.VCvtSD.src);
2387 } else {
2388 ppHRegARM64asSreg(i->ARM64in.VCvtSD.dst);
2389 vex_printf(", ");
2390 ppHRegARM64(i->ARM64in.VCvtSD.src);
2391 }
2392 return;
2393 case ARM64in_VUnaryD:
2394 vex_printf("f%s ", showARM64FpUnaryOp(i->ARM64in.VUnaryD.op));
2395 ppHRegARM64(i->ARM64in.VUnaryD.dst);
2396 vex_printf(", ");
2397 ppHRegARM64(i->ARM64in.VUnaryD.src);
2398 return;
2399 case ARM64in_VUnaryS:
2400 vex_printf("f%s ", showARM64FpUnaryOp(i->ARM64in.VUnaryS.op));
2401 ppHRegARM64asSreg(i->ARM64in.VUnaryS.dst);
2402 vex_printf(", ");
2403 ppHRegARM64asSreg(i->ARM64in.VUnaryS.src);
2404 return;
2405 case ARM64in_VBinD:
2406 vex_printf("f%s ", showARM64FpBinOp(i->ARM64in.VBinD.op));
2407 ppHRegARM64(i->ARM64in.VBinD.dst);
2408 vex_printf(", ");
2409 ppHRegARM64(i->ARM64in.VBinD.argL);
2410 vex_printf(", ");
2411 ppHRegARM64(i->ARM64in.VBinD.argR);
2412 return;
2413 case ARM64in_VBinS:
2414 vex_printf("f%s ", showARM64FpBinOp(i->ARM64in.VBinS.op));
2415 ppHRegARM64asSreg(i->ARM64in.VBinS.dst);
2416 vex_printf(", ");
2417 ppHRegARM64asSreg(i->ARM64in.VBinS.argL);
2418 vex_printf(", ");
2419 ppHRegARM64asSreg(i->ARM64in.VBinS.argR);
2420 return;
2421 case ARM64in_VCmpD:
2422 vex_printf("fcmp ");
2423 ppHRegARM64(i->ARM64in.VCmpD.argL);
2424 vex_printf(", ");
2425 ppHRegARM64(i->ARM64in.VCmpD.argR);
2426 return;
2427 case ARM64in_VCmpS:
2428 vex_printf("fcmp ");
2429 ppHRegARM64asSreg(i->ARM64in.VCmpS.argL);
2430 vex_printf(", ");
2431 ppHRegARM64asSreg(i->ARM64in.VCmpS.argR);
2432 return;
2433 case ARM64in_FPCR:
2434 if (i->ARM64in.FPCR.toFPCR) {
2435 vex_printf("msr fpcr, ");
2436 ppHRegARM64(i->ARM64in.FPCR.iReg);
2437 } else {
2438 vex_printf("mrs ");
2439 ppHRegARM64(i->ARM64in.FPCR.iReg);
2440 vex_printf(", fpcr");
2441 }
2442 return;
sewardj12972182014-08-04 08:09:47 +00002443 case ARM64in_FPSR:
2444 if (i->ARM64in.FPSR.toFPSR) {
2445 vex_printf("msr fpsr, ");
2446 ppHRegARM64(i->ARM64in.FPSR.iReg);
2447 } else {
2448 vex_printf("mrs ");
2449 ppHRegARM64(i->ARM64in.FPSR.iReg);
2450 vex_printf(", fpsr");
2451 }
2452 return;
sewardj606c4ba2014-01-26 19:11:14 +00002453 case ARM64in_VBinV: {
2454 const HChar* nm = "??";
2455 const HChar* ar = "??";
2456 showARM64VecBinOp(&nm, &ar, i->ARM64in.VBinV.op);
sewardj12972182014-08-04 08:09:47 +00002457 vex_printf("%s ", nm);
sewardj606c4ba2014-01-26 19:11:14 +00002458 ppHRegARM64(i->ARM64in.VBinV.dst);
2459 vex_printf(".%s, ", ar);
2460 ppHRegARM64(i->ARM64in.VBinV.argL);
2461 vex_printf(".%s, ", ar);
2462 ppHRegARM64(i->ARM64in.VBinV.argR);
2463 vex_printf(".%s", ar);
2464 return;
2465 }
sewardjfab09142014-02-10 10:28:13 +00002466 case ARM64in_VUnaryV: {
2467 const HChar* nm = "??";
2468 const HChar* ar = "??";
2469 showARM64VecUnaryOp(&nm, &ar, i->ARM64in.VUnaryV.op);
2470 vex_printf("%s ", nm);
2471 ppHRegARM64(i->ARM64in.VUnaryV.dst);
2472 vex_printf(".%s, ", ar);
2473 ppHRegARM64(i->ARM64in.VUnaryV.arg);
2474 vex_printf(".%s", ar);
2475 return;
2476 }
sewardj606c4ba2014-01-26 19:11:14 +00002477 case ARM64in_VNarrowV: {
2478 UInt dszBlg2 = i->ARM64in.VNarrowV.dszBlg2;
2479 const HChar* darr[3] = { "8b", "4h", "2s" };
2480 const HChar* sarr[3] = { "8h", "4s", "2d" };
sewardjecedd982014-08-11 14:02:47 +00002481 const HChar* nm = showARM64VecNarrowOp(i->ARM64in.VNarrowV.op);
2482 vex_printf("%s ", nm);
sewardj606c4ba2014-01-26 19:11:14 +00002483 ppHRegARM64(i->ARM64in.VNarrowV.dst);
2484 vex_printf(".%s, ", dszBlg2 < 3 ? darr[dszBlg2] : "??");
2485 ppHRegARM64(i->ARM64in.VNarrowV.src);
2486 vex_printf(".%s", dszBlg2 < 3 ? sarr[dszBlg2] : "??");
2487 return;
2488 }
sewardje520bb32014-02-17 11:00:53 +00002489 case ARM64in_VShiftImmV: {
2490 const HChar* nm = "??";
2491 const HChar* ar = "??";
2492 showARM64VecShiftOp(&nm, &ar, i->ARM64in.VShiftImmV.op);
2493 vex_printf("%s ", nm);
2494 ppHRegARM64(i->ARM64in.VShiftImmV.dst);
2495 vex_printf(".%s, ", ar);
2496 ppHRegARM64(i->ARM64in.VShiftImmV.src);
2497 vex_printf(".%s, #%u", ar, i->ARM64in.VShiftImmV.amt);
2498 return;
2499 }
sewardjab33a7a2014-06-19 22:20:47 +00002500 case ARM64in_VExtV: {
2501 vex_printf("ext ");
2502 ppHRegARM64(i->ARM64in.VExtV.dst);
2503 vex_printf(".16b, ");
2504 ppHRegARM64(i->ARM64in.VExtV.srcLo);
2505 vex_printf(".16b, ");
2506 ppHRegARM64(i->ARM64in.VExtV.srcHi);
2507 vex_printf(".16b, #%u", i->ARM64in.VExtV.amtB);
2508 return;
2509 }
sewardjbbcf1882014-01-12 12:49:10 +00002510//ZZ case ARMin_VAluS:
2511//ZZ vex_printf("f%-3ss ", showARMVfpOp(i->ARMin.VAluS.op));
2512//ZZ ppHRegARM(i->ARMin.VAluS.dst);
2513//ZZ vex_printf(", ");
2514//ZZ ppHRegARM(i->ARMin.VAluS.argL);
2515//ZZ vex_printf(", ");
2516//ZZ ppHRegARM(i->ARMin.VAluS.argR);
2517//ZZ return;
2518//ZZ case ARMin_VCMovD:
2519//ZZ vex_printf("fcpyd%s ", showARMCondCode(i->ARMin.VCMovD.cond));
2520//ZZ ppHRegARM(i->ARMin.VCMovD.dst);
2521//ZZ vex_printf(", ");
2522//ZZ ppHRegARM(i->ARMin.VCMovD.src);
2523//ZZ return;
2524//ZZ case ARMin_VCMovS:
2525//ZZ vex_printf("fcpys%s ", showARMCondCode(i->ARMin.VCMovS.cond));
2526//ZZ ppHRegARM(i->ARMin.VCMovS.dst);
2527//ZZ vex_printf(", ");
2528//ZZ ppHRegARM(i->ARMin.VCMovS.src);
2529//ZZ return;
2530//ZZ case ARMin_VXferD:
2531//ZZ vex_printf("vmov ");
2532//ZZ if (i->ARMin.VXferD.toD) {
2533//ZZ ppHRegARM(i->ARMin.VXferD.dD);
2534//ZZ vex_printf(", ");
2535//ZZ ppHRegARM(i->ARMin.VXferD.rLo);
2536//ZZ vex_printf(", ");
2537//ZZ ppHRegARM(i->ARMin.VXferD.rHi);
2538//ZZ } else {
2539//ZZ ppHRegARM(i->ARMin.VXferD.rLo);
2540//ZZ vex_printf(", ");
2541//ZZ ppHRegARM(i->ARMin.VXferD.rHi);
2542//ZZ vex_printf(", ");
2543//ZZ ppHRegARM(i->ARMin.VXferD.dD);
2544//ZZ }
2545//ZZ return;
2546//ZZ case ARMin_VXferS:
2547//ZZ vex_printf("vmov ");
2548//ZZ if (i->ARMin.VXferS.toS) {
2549//ZZ ppHRegARM(i->ARMin.VXferS.fD);
2550//ZZ vex_printf(", ");
2551//ZZ ppHRegARM(i->ARMin.VXferS.rLo);
2552//ZZ } else {
2553//ZZ ppHRegARM(i->ARMin.VXferS.rLo);
2554//ZZ vex_printf(", ");
2555//ZZ ppHRegARM(i->ARMin.VXferS.fD);
2556//ZZ }
2557//ZZ return;
2558//ZZ case ARMin_VCvtID: {
2559//ZZ const HChar* nm = "?";
2560//ZZ if (i->ARMin.VCvtID.iToD) {
2561//ZZ nm = i->ARMin.VCvtID.syned ? "fsitod" : "fuitod";
2562//ZZ } else {
2563//ZZ nm = i->ARMin.VCvtID.syned ? "ftosid" : "ftouid";
2564//ZZ }
2565//ZZ vex_printf("%s ", nm);
2566//ZZ ppHRegARM(i->ARMin.VCvtID.dst);
2567//ZZ vex_printf(", ");
2568//ZZ ppHRegARM(i->ARMin.VCvtID.src);
2569//ZZ return;
2570//ZZ }
sewardjbbcf1882014-01-12 12:49:10 +00002571//ZZ case ARMin_NLdStD:
2572//ZZ if (i->ARMin.NLdStD.isLoad)
2573//ZZ vex_printf("vld1.32 {");
2574//ZZ else
2575//ZZ vex_printf("vst1.32 {");
2576//ZZ ppHRegARM(i->ARMin.NLdStD.dD);
2577//ZZ vex_printf("} ");
2578//ZZ ppARMAModeN(i->ARMin.NLdStD.amode);
2579//ZZ return;
2580//ZZ case ARMin_NUnary:
2581//ZZ vex_printf("%s%s%s ",
2582//ZZ showARMNeonUnOp(i->ARMin.NUnary.op),
2583//ZZ showARMNeonUnOpDataType(i->ARMin.NUnary.op),
2584//ZZ showARMNeonDataSize(i));
2585//ZZ ppHRegARM(i->ARMin.NUnary.dst);
2586//ZZ vex_printf(", ");
2587//ZZ ppHRegARM(i->ARMin.NUnary.src);
2588//ZZ if (i->ARMin.NUnary.op == ARMneon_EQZ)
2589//ZZ vex_printf(", #0");
2590//ZZ if (i->ARMin.NUnary.op == ARMneon_VCVTFtoFixedS ||
2591//ZZ i->ARMin.NUnary.op == ARMneon_VCVTFtoFixedU ||
2592//ZZ i->ARMin.NUnary.op == ARMneon_VCVTFixedStoF ||
2593//ZZ i->ARMin.NUnary.op == ARMneon_VCVTFixedUtoF) {
2594//ZZ vex_printf(", #%d", i->ARMin.NUnary.size);
2595//ZZ }
2596//ZZ if (i->ARMin.NUnary.op == ARMneon_VQSHLNSS ||
2597//ZZ i->ARMin.NUnary.op == ARMneon_VQSHLNUU ||
2598//ZZ i->ARMin.NUnary.op == ARMneon_VQSHLNUS) {
2599//ZZ UInt size;
2600//ZZ size = i->ARMin.NUnary.size;
2601//ZZ if (size & 0x40) {
2602//ZZ vex_printf(", #%d", size - 64);
2603//ZZ } else if (size & 0x20) {
2604//ZZ vex_printf(", #%d", size - 32);
2605//ZZ } else if (size & 0x10) {
2606//ZZ vex_printf(", #%d", size - 16);
2607//ZZ } else if (size & 0x08) {
2608//ZZ vex_printf(", #%d", size - 8);
2609//ZZ }
2610//ZZ }
2611//ZZ return;
2612//ZZ case ARMin_NUnaryS:
2613//ZZ vex_printf("%s%s%s ",
2614//ZZ showARMNeonUnOpS(i->ARMin.NUnaryS.op),
2615//ZZ showARMNeonUnOpSDataType(i->ARMin.NUnaryS.op),
2616//ZZ showARMNeonDataSize(i));
2617//ZZ ppARMNRS(i->ARMin.NUnaryS.dst);
2618//ZZ vex_printf(", ");
2619//ZZ ppARMNRS(i->ARMin.NUnaryS.src);
2620//ZZ return;
2621//ZZ case ARMin_NShift:
2622//ZZ vex_printf("%s%s%s ",
2623//ZZ showARMNeonShiftOp(i->ARMin.NShift.op),
2624//ZZ showARMNeonShiftOpDataType(i->ARMin.NShift.op),
2625//ZZ showARMNeonDataSize(i));
2626//ZZ ppHRegARM(i->ARMin.NShift.dst);
2627//ZZ vex_printf(", ");
2628//ZZ ppHRegARM(i->ARMin.NShift.argL);
2629//ZZ vex_printf(", ");
2630//ZZ ppHRegARM(i->ARMin.NShift.argR);
2631//ZZ return;
2632//ZZ case ARMin_NShl64:
2633//ZZ vex_printf("vshl.i64 ");
2634//ZZ ppHRegARM(i->ARMin.NShl64.dst);
2635//ZZ vex_printf(", ");
2636//ZZ ppHRegARM(i->ARMin.NShl64.src);
2637//ZZ vex_printf(", #%u", i->ARMin.NShl64.amt);
2638//ZZ return;
2639//ZZ case ARMin_NDual:
2640//ZZ vex_printf("%s%s%s ",
2641//ZZ showARMNeonDualOp(i->ARMin.NDual.op),
2642//ZZ showARMNeonDualOpDataType(i->ARMin.NDual.op),
2643//ZZ showARMNeonDataSize(i));
2644//ZZ ppHRegARM(i->ARMin.NDual.arg1);
2645//ZZ vex_printf(", ");
2646//ZZ ppHRegARM(i->ARMin.NDual.arg2);
2647//ZZ return;
2648//ZZ case ARMin_NBinary:
2649//ZZ vex_printf("%s%s%s",
2650//ZZ showARMNeonBinOp(i->ARMin.NBinary.op),
2651//ZZ showARMNeonBinOpDataType(i->ARMin.NBinary.op),
2652//ZZ showARMNeonDataSize(i));
2653//ZZ vex_printf(" ");
2654//ZZ ppHRegARM(i->ARMin.NBinary.dst);
2655//ZZ vex_printf(", ");
2656//ZZ ppHRegARM(i->ARMin.NBinary.argL);
2657//ZZ vex_printf(", ");
2658//ZZ ppHRegARM(i->ARMin.NBinary.argR);
2659//ZZ return;
2660 case ARM64in_VImmQ:
2661 vex_printf("qimm ");
2662 ppHRegARM64(i->ARM64in.VImmQ.rQ);
2663 vex_printf(", Bits16toBytes16(0x%x)", (UInt)i->ARM64in.VImmQ.imm);
2664 return;
2665 case ARM64in_VDfromX:
2666 vex_printf("fmov ");
2667 ppHRegARM64(i->ARM64in.VDfromX.rD);
2668 vex_printf(", ");
2669 ppHRegARM64(i->ARM64in.VDfromX.rX);
2670 return;
sewardj12972182014-08-04 08:09:47 +00002671 case ARM64in_VQfromX:
2672 vex_printf("fmov ");
2673 ppHRegARM64(i->ARM64in.VQfromX.rQ);
2674 vex_printf(".d[0], ");
2675 ppHRegARM64(i->ARM64in.VQfromX.rXlo);
2676 return;
sewardjbbcf1882014-01-12 12:49:10 +00002677 case ARM64in_VQfromXX:
2678 vex_printf("qFromXX ");
2679 ppHRegARM64(i->ARM64in.VQfromXX.rQ);
2680 vex_printf(", ");
2681 ppHRegARM64(i->ARM64in.VQfromXX.rXhi);
2682 vex_printf(", ");
2683 ppHRegARM64(i->ARM64in.VQfromXX.rXlo);
2684 return;
2685 case ARM64in_VXfromQ:
sewardj85fbb022014-06-12 13:16:01 +00002686 vex_printf("fmov ");
sewardjbbcf1882014-01-12 12:49:10 +00002687 ppHRegARM64(i->ARM64in.VXfromQ.rX);
2688 vex_printf(", ");
2689 ppHRegARM64(i->ARM64in.VXfromQ.rQ);
2690 vex_printf(".d[%u]", i->ARM64in.VXfromQ.laneNo);
2691 return;
sewardj85fbb022014-06-12 13:16:01 +00002692 case ARM64in_VXfromDorS:
2693 vex_printf("fmov ");
2694 ppHRegARM64(i->ARM64in.VXfromDorS.rX);
2695 vex_printf("(%c-reg), ", i->ARM64in.VXfromDorS.fromD ? 'X':'W');
2696 ppHRegARM64(i->ARM64in.VXfromDorS.rDorS);
2697 vex_printf("(%c-reg)", i->ARM64in.VXfromDorS.fromD ? 'D' : 'S');
2698 return;
sewardjbbcf1882014-01-12 12:49:10 +00002699 case ARM64in_VMov: {
2700 UChar aux = '?';
2701 switch (i->ARM64in.VMov.szB) {
2702 case 16: aux = 'q'; break;
2703 case 8: aux = 'd'; break;
2704 case 4: aux = 's'; break;
2705 default: break;
2706 }
2707 vex_printf("mov(%c) ", aux);
2708 ppHRegARM64(i->ARM64in.VMov.dst);
2709 vex_printf(", ");
2710 ppHRegARM64(i->ARM64in.VMov.src);
2711 return;
2712 }
2713//ZZ case ARMin_NCMovQ:
2714//ZZ vex_printf("vmov%s ", showARMCondCode(i->ARMin.NCMovQ.cond));
2715//ZZ ppHRegARM(i->ARMin.NCMovQ.dst);
2716//ZZ vex_printf(", ");
2717//ZZ ppHRegARM(i->ARMin.NCMovQ.src);
2718//ZZ return;
2719//ZZ case ARMin_Add32:
2720//ZZ vex_printf("add32 ");
2721//ZZ ppHRegARM(i->ARMin.Add32.rD);
2722//ZZ vex_printf(", ");
2723//ZZ ppHRegARM(i->ARMin.Add32.rN);
2724//ZZ vex_printf(", ");
2725//ZZ vex_printf("%d", i->ARMin.Add32.imm32);
2726//ZZ return;
2727 case ARM64in_EvCheck:
2728 vex_printf("(evCheck) ldr w9,");
2729 ppARM64AMode(i->ARM64in.EvCheck.amCounter);
2730 vex_printf("; subs w9,w9,$1; str w9,");
2731 ppARM64AMode(i->ARM64in.EvCheck.amCounter);
2732 vex_printf("; bpl nofail; ldr x9,");
2733 ppARM64AMode(i->ARM64in.EvCheck.amFailAddr);
2734 vex_printf("; br x9; nofail:");
2735 return;
2736//ZZ case ARMin_ProfInc:
2737//ZZ vex_printf("(profInc) movw r12,LO16($NotKnownYet); "
2738//ZZ "movw r12,HI16($NotKnownYet); "
2739//ZZ "ldr r11,[r12]; "
2740//ZZ "adds r11,r11,$1; "
2741//ZZ "str r11,[r12]; "
2742//ZZ "ldr r11,[r12+4]; "
2743//ZZ "adc r11,r11,$0; "
2744//ZZ "str r11,[r12+4]");
2745//ZZ return;
2746 default:
2747 vex_printf("ppARM64Instr: unhandled case (tag %d)", (Int)i->tag);
2748 vpanic("ppARM64Instr(1)");
2749 return;
2750 }
2751}
2752
2753
2754/* --------- Helpers for register allocation. --------- */
2755
2756void getRegUsage_ARM64Instr ( HRegUsage* u, ARM64Instr* i, Bool mode64 )
2757{
2758 vassert(mode64 == True);
2759 initHRegUsage(u);
2760 switch (i->tag) {
2761 case ARM64in_Arith:
2762 addHRegUse(u, HRmWrite, i->ARM64in.Arith.dst);
2763 addHRegUse(u, HRmRead, i->ARM64in.Arith.argL);
2764 addRegUsage_ARM64RIA(u, i->ARM64in.Arith.argR);
2765 return;
2766 case ARM64in_Cmp:
2767 addHRegUse(u, HRmRead, i->ARM64in.Cmp.argL);
2768 addRegUsage_ARM64RIA(u, i->ARM64in.Cmp.argR);
2769 return;
2770 case ARM64in_Logic:
2771 addHRegUse(u, HRmWrite, i->ARM64in.Logic.dst);
2772 addHRegUse(u, HRmRead, i->ARM64in.Logic.argL);
2773 addRegUsage_ARM64RIL(u, i->ARM64in.Logic.argR);
2774 return;
2775 case ARM64in_Test:
2776 addHRegUse(u, HRmRead, i->ARM64in.Test.argL);
2777 addRegUsage_ARM64RIL(u, i->ARM64in.Test.argR);
2778 return;
2779 case ARM64in_Shift:
2780 addHRegUse(u, HRmWrite, i->ARM64in.Shift.dst);
2781 addHRegUse(u, HRmRead, i->ARM64in.Shift.argL);
2782 addRegUsage_ARM64RI6(u, i->ARM64in.Shift.argR);
2783 return;
2784 case ARM64in_Unary:
2785 addHRegUse(u, HRmWrite, i->ARM64in.Unary.dst);
2786 addHRegUse(u, HRmRead, i->ARM64in.Unary.src);
2787 return;
2788 case ARM64in_MovI:
2789 addHRegUse(u, HRmWrite, i->ARM64in.MovI.dst);
2790 addHRegUse(u, HRmRead, i->ARM64in.MovI.src);
2791 return;
2792 case ARM64in_Imm64:
2793 addHRegUse(u, HRmWrite, i->ARM64in.Imm64.dst);
2794 return;
2795 case ARM64in_LdSt64:
2796 addRegUsage_ARM64AMode(u, i->ARM64in.LdSt64.amode);
2797 if (i->ARM64in.LdSt64.isLoad) {
2798 addHRegUse(u, HRmWrite, i->ARM64in.LdSt64.rD);
2799 } else {
2800 addHRegUse(u, HRmRead, i->ARM64in.LdSt64.rD);
2801 }
2802 return;
2803 case ARM64in_LdSt32:
2804 addRegUsage_ARM64AMode(u, i->ARM64in.LdSt32.amode);
2805 if (i->ARM64in.LdSt32.isLoad) {
2806 addHRegUse(u, HRmWrite, i->ARM64in.LdSt32.rD);
2807 } else {
2808 addHRegUse(u, HRmRead, i->ARM64in.LdSt32.rD);
2809 }
2810 return;
2811 case ARM64in_LdSt16:
2812 addRegUsage_ARM64AMode(u, i->ARM64in.LdSt16.amode);
2813 if (i->ARM64in.LdSt16.isLoad) {
2814 addHRegUse(u, HRmWrite, i->ARM64in.LdSt16.rD);
2815 } else {
2816 addHRegUse(u, HRmRead, i->ARM64in.LdSt16.rD);
2817 }
2818 return;
2819 case ARM64in_LdSt8:
2820 addRegUsage_ARM64AMode(u, i->ARM64in.LdSt8.amode);
2821 if (i->ARM64in.LdSt8.isLoad) {
2822 addHRegUse(u, HRmWrite, i->ARM64in.LdSt8.rD);
2823 } else {
2824 addHRegUse(u, HRmRead, i->ARM64in.LdSt8.rD);
2825 }
2826 return;
2827 /* XDirect/XIndir/XAssisted are also a bit subtle. They
2828 conditionally exit the block. Hence we only need to list (1)
2829 the registers that they read, and (2) the registers that they
2830 write in the case where the block is not exited. (2) is
2831 empty, hence only (1) is relevant here. */
2832 case ARM64in_XDirect:
2833 addRegUsage_ARM64AMode(u, i->ARM64in.XDirect.amPC);
2834 return;
2835 case ARM64in_XIndir:
2836 addHRegUse(u, HRmRead, i->ARM64in.XIndir.dstGA);
2837 addRegUsage_ARM64AMode(u, i->ARM64in.XIndir.amPC);
2838 return;
2839 case ARM64in_XAssisted:
2840 addHRegUse(u, HRmRead, i->ARM64in.XAssisted.dstGA);
2841 addRegUsage_ARM64AMode(u, i->ARM64in.XAssisted.amPC);
2842 return;
2843 case ARM64in_CSel:
2844 addHRegUse(u, HRmWrite, i->ARM64in.CSel.dst);
2845 addHRegUse(u, HRmRead, i->ARM64in.CSel.argL);
2846 addHRegUse(u, HRmRead, i->ARM64in.CSel.argR);
2847 return;
2848 case ARM64in_Call:
2849 /* logic and comments copied/modified from x86 back end */
2850 /* This is a bit subtle. */
2851 /* First off, claim it trashes all the caller-saved regs
2852 which fall within the register allocator's jurisdiction.
sewardj76ac4762014-06-20 08:30:21 +00002853 These I believe to be x0 to x7 and the 128-bit vector
2854 registers in use, q16 .. q20. */
sewardjbbcf1882014-01-12 12:49:10 +00002855 addHRegUse(u, HRmWrite, hregARM64_X0());
2856 addHRegUse(u, HRmWrite, hregARM64_X1());
2857 addHRegUse(u, HRmWrite, hregARM64_X2());
2858 addHRegUse(u, HRmWrite, hregARM64_X3());
2859 addHRegUse(u, HRmWrite, hregARM64_X4());
2860 addHRegUse(u, HRmWrite, hregARM64_X5());
2861 addHRegUse(u, HRmWrite, hregARM64_X6());
2862 addHRegUse(u, HRmWrite, hregARM64_X7());
2863 addHRegUse(u, HRmWrite, hregARM64_Q16());
2864 addHRegUse(u, HRmWrite, hregARM64_Q17());
2865 addHRegUse(u, HRmWrite, hregARM64_Q18());
sewardj76ac4762014-06-20 08:30:21 +00002866 addHRegUse(u, HRmWrite, hregARM64_Q19());
2867 addHRegUse(u, HRmWrite, hregARM64_Q20());
sewardjbbcf1882014-01-12 12:49:10 +00002868 /* Now we have to state any parameter-carrying registers
2869 which might be read. This depends on nArgRegs. */
2870 switch (i->ARM64in.Call.nArgRegs) {
2871 case 8: addHRegUse(u, HRmRead, hregARM64_X7()); /*fallthru*/
2872 case 7: addHRegUse(u, HRmRead, hregARM64_X6()); /*fallthru*/
2873 case 6: addHRegUse(u, HRmRead, hregARM64_X5()); /*fallthru*/
2874 case 5: addHRegUse(u, HRmRead, hregARM64_X4()); /*fallthru*/
2875 case 4: addHRegUse(u, HRmRead, hregARM64_X3()); /*fallthru*/
2876 case 3: addHRegUse(u, HRmRead, hregARM64_X2()); /*fallthru*/
2877 case 2: addHRegUse(u, HRmRead, hregARM64_X1()); /*fallthru*/
2878 case 1: addHRegUse(u, HRmRead, hregARM64_X0()); break;
2879 case 0: break;
2880 default: vpanic("getRegUsage_ARM64:Call:regparms");
2881 }
2882 /* Finally, there is the issue that the insn trashes a
2883 register because the literal target address has to be
2884 loaded into a register. However, we reserve x9 for that
2885 purpose so there's no further complexity here. Stating x9
2886 as trashed is pointless since it's not under the control
2887 of the allocator, but what the hell. */
2888 addHRegUse(u, HRmWrite, hregARM64_X9());
2889 return;
2890 case ARM64in_AddToSP:
2891 /* Only changes SP, but regalloc doesn't control that, hence
2892 we don't care. */
2893 return;
2894 case ARM64in_FromSP:
2895 addHRegUse(u, HRmWrite, i->ARM64in.FromSP.dst);
2896 return;
2897 case ARM64in_Mul:
2898 addHRegUse(u, HRmWrite, i->ARM64in.Mul.dst);
2899 addHRegUse(u, HRmRead, i->ARM64in.Mul.argL);
2900 addHRegUse(u, HRmRead, i->ARM64in.Mul.argR);
2901 return;
sewardj7d009132014-02-20 17:43:38 +00002902 case ARM64in_LdrEX:
2903 addHRegUse(u, HRmRead, hregARM64_X4());
2904 addHRegUse(u, HRmWrite, hregARM64_X2());
2905 return;
2906 case ARM64in_StrEX:
2907 addHRegUse(u, HRmRead, hregARM64_X4());
2908 addHRegUse(u, HRmWrite, hregARM64_X0());
2909 addHRegUse(u, HRmRead, hregARM64_X2());
2910 return;
2911 case ARM64in_MFence:
2912 return;
2913//ZZ case ARMin_CLREX:
sewardjbbcf1882014-01-12 12:49:10 +00002914//ZZ return;
2915 case ARM64in_VLdStS:
2916 addHRegUse(u, HRmRead, i->ARM64in.VLdStS.rN);
2917 if (i->ARM64in.VLdStS.isLoad) {
2918 addHRegUse(u, HRmWrite, i->ARM64in.VLdStS.sD);
2919 } else {
2920 addHRegUse(u, HRmRead, i->ARM64in.VLdStS.sD);
2921 }
2922 return;
2923 case ARM64in_VLdStD:
2924 addHRegUse(u, HRmRead, i->ARM64in.VLdStD.rN);
2925 if (i->ARM64in.VLdStD.isLoad) {
2926 addHRegUse(u, HRmWrite, i->ARM64in.VLdStD.dD);
2927 } else {
2928 addHRegUse(u, HRmRead, i->ARM64in.VLdStD.dD);
2929 }
2930 return;
2931 case ARM64in_VLdStQ:
2932 addHRegUse(u, HRmRead, i->ARM64in.VLdStQ.rN);
2933 if (i->ARM64in.VLdStQ.isLoad)
2934 addHRegUse(u, HRmWrite, i->ARM64in.VLdStQ.rQ);
2935 else
2936 addHRegUse(u, HRmRead, i->ARM64in.VLdStQ.rQ);
2937 return;
2938 case ARM64in_VCvtI2F:
2939 addHRegUse(u, HRmRead, i->ARM64in.VCvtI2F.rS);
2940 addHRegUse(u, HRmWrite, i->ARM64in.VCvtI2F.rD);
2941 return;
2942 case ARM64in_VCvtF2I:
2943 addHRegUse(u, HRmRead, i->ARM64in.VCvtF2I.rS);
2944 addHRegUse(u, HRmWrite, i->ARM64in.VCvtF2I.rD);
2945 return;
2946 case ARM64in_VCvtSD:
2947 addHRegUse(u, HRmWrite, i->ARM64in.VCvtSD.dst);
2948 addHRegUse(u, HRmRead, i->ARM64in.VCvtSD.src);
2949 return;
2950 case ARM64in_VUnaryD:
2951 addHRegUse(u, HRmWrite, i->ARM64in.VUnaryD.dst);
2952 addHRegUse(u, HRmRead, i->ARM64in.VUnaryD.src);
2953 return;
2954 case ARM64in_VUnaryS:
2955 addHRegUse(u, HRmWrite, i->ARM64in.VUnaryS.dst);
2956 addHRegUse(u, HRmRead, i->ARM64in.VUnaryS.src);
2957 return;
2958 case ARM64in_VBinD:
2959 addHRegUse(u, HRmWrite, i->ARM64in.VBinD.dst);
2960 addHRegUse(u, HRmRead, i->ARM64in.VBinD.argL);
2961 addHRegUse(u, HRmRead, i->ARM64in.VBinD.argR);
2962 return;
2963 case ARM64in_VBinS:
2964 addHRegUse(u, HRmWrite, i->ARM64in.VBinS.dst);
2965 addHRegUse(u, HRmRead, i->ARM64in.VBinS.argL);
2966 addHRegUse(u, HRmRead, i->ARM64in.VBinS.argR);
2967 return;
2968 case ARM64in_VCmpD:
2969 addHRegUse(u, HRmRead, i->ARM64in.VCmpD.argL);
2970 addHRegUse(u, HRmRead, i->ARM64in.VCmpD.argR);
2971 return;
2972 case ARM64in_VCmpS:
2973 addHRegUse(u, HRmRead, i->ARM64in.VCmpS.argL);
2974 addHRegUse(u, HRmRead, i->ARM64in.VCmpS.argR);
2975 return;
2976 case ARM64in_FPCR:
2977 if (i->ARM64in.FPCR.toFPCR)
2978 addHRegUse(u, HRmRead, i->ARM64in.FPCR.iReg);
2979 else
2980 addHRegUse(u, HRmWrite, i->ARM64in.FPCR.iReg);
2981 return;
sewardj12972182014-08-04 08:09:47 +00002982 case ARM64in_FPSR:
2983 if (i->ARM64in.FPSR.toFPSR)
2984 addHRegUse(u, HRmRead, i->ARM64in.FPSR.iReg);
2985 else
2986 addHRegUse(u, HRmWrite, i->ARM64in.FPSR.iReg);
2987 return;
sewardj606c4ba2014-01-26 19:11:14 +00002988 case ARM64in_VBinV:
2989 addHRegUse(u, HRmWrite, i->ARM64in.VBinV.dst);
2990 addHRegUse(u, HRmRead, i->ARM64in.VBinV.argL);
2991 addHRegUse(u, HRmRead, i->ARM64in.VBinV.argR);
2992 return;
sewardjfab09142014-02-10 10:28:13 +00002993 case ARM64in_VUnaryV:
2994 addHRegUse(u, HRmWrite, i->ARM64in.VUnaryV.dst);
2995 addHRegUse(u, HRmRead, i->ARM64in.VUnaryV.arg);
2996 return;
sewardj606c4ba2014-01-26 19:11:14 +00002997 case ARM64in_VNarrowV:
2998 addHRegUse(u, HRmWrite, i->ARM64in.VNarrowV.dst);
2999 addHRegUse(u, HRmRead, i->ARM64in.VNarrowV.src);
3000 return;
sewardje520bb32014-02-17 11:00:53 +00003001 case ARM64in_VShiftImmV:
3002 addHRegUse(u, HRmWrite, i->ARM64in.VShiftImmV.dst);
3003 addHRegUse(u, HRmRead, i->ARM64in.VShiftImmV.src);
3004 return;
sewardjab33a7a2014-06-19 22:20:47 +00003005 case ARM64in_VExtV:
3006 addHRegUse(u, HRmWrite, i->ARM64in.VExtV.dst);
3007 addHRegUse(u, HRmRead, i->ARM64in.VExtV.srcLo);
3008 addHRegUse(u, HRmRead, i->ARM64in.VExtV.srcHi);
sewardjbbcf1882014-01-12 12:49:10 +00003009//ZZ case ARMin_VAluS:
3010//ZZ addHRegUse(u, HRmWrite, i->ARMin.VAluS.dst);
3011//ZZ addHRegUse(u, HRmRead, i->ARMin.VAluS.argL);
3012//ZZ addHRegUse(u, HRmRead, i->ARMin.VAluS.argR);
3013//ZZ return;
3014//ZZ case ARMin_VUnaryS:
3015//ZZ addHRegUse(u, HRmWrite, i->ARMin.VUnaryS.dst);
3016//ZZ addHRegUse(u, HRmRead, i->ARMin.VUnaryS.src);
3017//ZZ return;
3018//ZZ case ARMin_VCMovD:
3019//ZZ addHRegUse(u, HRmWrite, i->ARMin.VCMovD.dst);
3020//ZZ addHRegUse(u, HRmRead, i->ARMin.VCMovD.dst);
3021//ZZ addHRegUse(u, HRmRead, i->ARMin.VCMovD.src);
3022//ZZ return;
3023//ZZ case ARMin_VCMovS:
3024//ZZ addHRegUse(u, HRmWrite, i->ARMin.VCMovS.dst);
3025//ZZ addHRegUse(u, HRmRead, i->ARMin.VCMovS.dst);
3026//ZZ addHRegUse(u, HRmRead, i->ARMin.VCMovS.src);
3027//ZZ return;
3028//ZZ case ARMin_VXferD:
3029//ZZ if (i->ARMin.VXferD.toD) {
3030//ZZ addHRegUse(u, HRmWrite, i->ARMin.VXferD.dD);
3031//ZZ addHRegUse(u, HRmRead, i->ARMin.VXferD.rHi);
3032//ZZ addHRegUse(u, HRmRead, i->ARMin.VXferD.rLo);
3033//ZZ } else {
3034//ZZ addHRegUse(u, HRmRead, i->ARMin.VXferD.dD);
3035//ZZ addHRegUse(u, HRmWrite, i->ARMin.VXferD.rHi);
3036//ZZ addHRegUse(u, HRmWrite, i->ARMin.VXferD.rLo);
3037//ZZ }
3038//ZZ return;
3039//ZZ case ARMin_VXferS:
3040//ZZ if (i->ARMin.VXferS.toS) {
3041//ZZ addHRegUse(u, HRmWrite, i->ARMin.VXferS.fD);
3042//ZZ addHRegUse(u, HRmRead, i->ARMin.VXferS.rLo);
3043//ZZ } else {
3044//ZZ addHRegUse(u, HRmRead, i->ARMin.VXferS.fD);
3045//ZZ addHRegUse(u, HRmWrite, i->ARMin.VXferS.rLo);
3046//ZZ }
3047//ZZ return;
3048//ZZ case ARMin_VCvtID:
3049//ZZ addHRegUse(u, HRmWrite, i->ARMin.VCvtID.dst);
3050//ZZ addHRegUse(u, HRmRead, i->ARMin.VCvtID.src);
3051//ZZ return;
sewardjbbcf1882014-01-12 12:49:10 +00003052//ZZ case ARMin_NLdStD:
3053//ZZ if (i->ARMin.NLdStD.isLoad)
3054//ZZ addHRegUse(u, HRmWrite, i->ARMin.NLdStD.dD);
3055//ZZ else
3056//ZZ addHRegUse(u, HRmRead, i->ARMin.NLdStD.dD);
3057//ZZ addRegUsage_ARMAModeN(u, i->ARMin.NLdStD.amode);
3058//ZZ return;
3059//ZZ case ARMin_NUnary:
3060//ZZ addHRegUse(u, HRmWrite, i->ARMin.NUnary.dst);
3061//ZZ addHRegUse(u, HRmRead, i->ARMin.NUnary.src);
3062//ZZ return;
3063//ZZ case ARMin_NUnaryS:
3064//ZZ addHRegUse(u, HRmWrite, i->ARMin.NUnaryS.dst->reg);
3065//ZZ addHRegUse(u, HRmRead, i->ARMin.NUnaryS.src->reg);
3066//ZZ return;
3067//ZZ case ARMin_NShift:
3068//ZZ addHRegUse(u, HRmWrite, i->ARMin.NShift.dst);
3069//ZZ addHRegUse(u, HRmRead, i->ARMin.NShift.argL);
3070//ZZ addHRegUse(u, HRmRead, i->ARMin.NShift.argR);
3071//ZZ return;
3072//ZZ case ARMin_NShl64:
3073//ZZ addHRegUse(u, HRmWrite, i->ARMin.NShl64.dst);
3074//ZZ addHRegUse(u, HRmRead, i->ARMin.NShl64.src);
3075//ZZ return;
3076//ZZ case ARMin_NDual:
3077//ZZ addHRegUse(u, HRmWrite, i->ARMin.NDual.arg1);
3078//ZZ addHRegUse(u, HRmWrite, i->ARMin.NDual.arg2);
3079//ZZ addHRegUse(u, HRmRead, i->ARMin.NDual.arg1);
3080//ZZ addHRegUse(u, HRmRead, i->ARMin.NDual.arg2);
3081//ZZ return;
3082 case ARM64in_VImmQ:
3083 addHRegUse(u, HRmWrite, i->ARM64in.VImmQ.rQ);
3084 return;
3085 case ARM64in_VDfromX:
3086 addHRegUse(u, HRmWrite, i->ARM64in.VDfromX.rD);
3087 addHRegUse(u, HRmRead, i->ARM64in.VDfromX.rX);
3088 return;
sewardj12972182014-08-04 08:09:47 +00003089 case ARM64in_VQfromX:
3090 addHRegUse(u, HRmWrite, i->ARM64in.VQfromX.rQ);
3091 addHRegUse(u, HRmRead, i->ARM64in.VQfromX.rXlo);
3092 return;
sewardjbbcf1882014-01-12 12:49:10 +00003093 case ARM64in_VQfromXX:
3094 addHRegUse(u, HRmWrite, i->ARM64in.VQfromXX.rQ);
3095 addHRegUse(u, HRmRead, i->ARM64in.VQfromXX.rXhi);
3096 addHRegUse(u, HRmRead, i->ARM64in.VQfromXX.rXlo);
3097 return;
3098 case ARM64in_VXfromQ:
3099 addHRegUse(u, HRmWrite, i->ARM64in.VXfromQ.rX);
3100 addHRegUse(u, HRmRead, i->ARM64in.VXfromQ.rQ);
3101 return;
sewardj85fbb022014-06-12 13:16:01 +00003102 case ARM64in_VXfromDorS:
3103 addHRegUse(u, HRmWrite, i->ARM64in.VXfromDorS.rX);
3104 addHRegUse(u, HRmRead, i->ARM64in.VXfromDorS.rDorS);
3105 return;
sewardjbbcf1882014-01-12 12:49:10 +00003106 case ARM64in_VMov:
3107 addHRegUse(u, HRmWrite, i->ARM64in.VMov.dst);
3108 addHRegUse(u, HRmRead, i->ARM64in.VMov.src);
3109 return;
3110//ZZ case ARMin_NBinary:
3111//ZZ addHRegUse(u, HRmWrite, i->ARMin.NBinary.dst);
3112//ZZ /* TODO: sometimes dst is also being read! */
3113//ZZ // XXX fix this
3114//ZZ addHRegUse(u, HRmRead, i->ARMin.NBinary.argL);
3115//ZZ addHRegUse(u, HRmRead, i->ARMin.NBinary.argR);
3116//ZZ return;
3117//ZZ case ARMin_NCMovQ:
3118//ZZ addHRegUse(u, HRmWrite, i->ARMin.NCMovQ.dst);
3119//ZZ addHRegUse(u, HRmRead, i->ARMin.NCMovQ.dst);
3120//ZZ addHRegUse(u, HRmRead, i->ARMin.NCMovQ.src);
3121//ZZ return;
3122//ZZ case ARMin_Add32:
3123//ZZ addHRegUse(u, HRmWrite, i->ARMin.Add32.rD);
3124//ZZ addHRegUse(u, HRmRead, i->ARMin.Add32.rN);
3125//ZZ return;
3126 case ARM64in_EvCheck:
3127 /* We expect both amodes only to mention x21, so this is in
3128 fact pointless, since x21 isn't allocatable, but
3129 anyway.. */
3130 addRegUsage_ARM64AMode(u, i->ARM64in.EvCheck.amCounter);
3131 addRegUsage_ARM64AMode(u, i->ARM64in.EvCheck.amFailAddr);
3132 addHRegUse(u, HRmWrite, hregARM64_X9()); /* also unavail to RA */
3133 return;
3134//ZZ case ARMin_ProfInc:
3135//ZZ addHRegUse(u, HRmWrite, hregARM_R12());
3136//ZZ addHRegUse(u, HRmWrite, hregARM_R11());
3137//ZZ return;
3138 default:
3139 ppARM64Instr(i);
3140 vpanic("getRegUsage_ARM64Instr");
3141 }
3142}
3143
3144
3145void mapRegs_ARM64Instr ( HRegRemap* m, ARM64Instr* i, Bool mode64 )
3146{
3147 vassert(mode64 == True);
3148 switch (i->tag) {
3149 case ARM64in_Arith:
3150 i->ARM64in.Arith.dst = lookupHRegRemap(m, i->ARM64in.Arith.dst);
3151 i->ARM64in.Arith.argL = lookupHRegRemap(m, i->ARM64in.Arith.argL);
3152 mapRegs_ARM64RIA(m, i->ARM64in.Arith.argR);
3153 return;
3154 case ARM64in_Cmp:
3155 i->ARM64in.Cmp.argL = lookupHRegRemap(m, i->ARM64in.Cmp.argL);
3156 mapRegs_ARM64RIA(m, i->ARM64in.Cmp.argR);
3157 return;
3158 case ARM64in_Logic:
3159 i->ARM64in.Logic.dst = lookupHRegRemap(m, i->ARM64in.Logic.dst);
3160 i->ARM64in.Logic.argL = lookupHRegRemap(m, i->ARM64in.Logic.argL);
3161 mapRegs_ARM64RIL(m, i->ARM64in.Logic.argR);
3162 return;
3163 case ARM64in_Test:
3164 i->ARM64in.Test.argL = lookupHRegRemap(m, i->ARM64in.Test.argL);
3165 mapRegs_ARM64RIL(m, i->ARM64in.Logic.argR);
3166 return;
3167 case ARM64in_Shift:
3168 i->ARM64in.Shift.dst = lookupHRegRemap(m, i->ARM64in.Shift.dst);
3169 i->ARM64in.Shift.argL = lookupHRegRemap(m, i->ARM64in.Shift.argL);
3170 mapRegs_ARM64RI6(m, i->ARM64in.Shift.argR);
3171 return;
3172 case ARM64in_Unary:
3173 i->ARM64in.Unary.dst = lookupHRegRemap(m, i->ARM64in.Unary.dst);
3174 i->ARM64in.Unary.src = lookupHRegRemap(m, i->ARM64in.Unary.src);
3175 return;
3176 case ARM64in_MovI:
3177 i->ARM64in.MovI.dst = lookupHRegRemap(m, i->ARM64in.MovI.dst);
3178 i->ARM64in.MovI.src = lookupHRegRemap(m, i->ARM64in.MovI.src);
3179 return;
3180 case ARM64in_Imm64:
3181 i->ARM64in.Imm64.dst = lookupHRegRemap(m, i->ARM64in.Imm64.dst);
3182 return;
3183 case ARM64in_LdSt64:
3184 i->ARM64in.LdSt64.rD = lookupHRegRemap(m, i->ARM64in.LdSt64.rD);
3185 mapRegs_ARM64AMode(m, i->ARM64in.LdSt64.amode);
3186 return;
3187 case ARM64in_LdSt32:
3188 i->ARM64in.LdSt32.rD = lookupHRegRemap(m, i->ARM64in.LdSt32.rD);
3189 mapRegs_ARM64AMode(m, i->ARM64in.LdSt32.amode);
3190 return;
3191 case ARM64in_LdSt16:
3192 i->ARM64in.LdSt16.rD = lookupHRegRemap(m, i->ARM64in.LdSt16.rD);
3193 mapRegs_ARM64AMode(m, i->ARM64in.LdSt16.amode);
3194 return;
3195 case ARM64in_LdSt8:
3196 i->ARM64in.LdSt8.rD = lookupHRegRemap(m, i->ARM64in.LdSt8.rD);
3197 mapRegs_ARM64AMode(m, i->ARM64in.LdSt8.amode);
3198 return;
3199 case ARM64in_XDirect:
3200 mapRegs_ARM64AMode(m, i->ARM64in.XDirect.amPC);
3201 return;
3202 case ARM64in_XIndir:
3203 i->ARM64in.XIndir.dstGA
3204 = lookupHRegRemap(m, i->ARM64in.XIndir.dstGA);
3205 mapRegs_ARM64AMode(m, i->ARM64in.XIndir.amPC);
3206 return;
3207 case ARM64in_XAssisted:
3208 i->ARM64in.XAssisted.dstGA
3209 = lookupHRegRemap(m, i->ARM64in.XAssisted.dstGA);
3210 mapRegs_ARM64AMode(m, i->ARM64in.XAssisted.amPC);
3211 return;
3212 case ARM64in_CSel:
3213 i->ARM64in.CSel.dst = lookupHRegRemap(m, i->ARM64in.CSel.dst);
3214 i->ARM64in.CSel.argL = lookupHRegRemap(m, i->ARM64in.CSel.argL);
3215 i->ARM64in.CSel.argR = lookupHRegRemap(m, i->ARM64in.CSel.argR);
3216 return;
3217 case ARM64in_Call:
3218 return;
3219 case ARM64in_AddToSP:
3220 return;
3221 case ARM64in_FromSP:
3222 i->ARM64in.FromSP.dst = lookupHRegRemap(m, i->ARM64in.FromSP.dst);
3223 return;
3224 case ARM64in_Mul:
3225 i->ARM64in.Mul.dst = lookupHRegRemap(m, i->ARM64in.Mul.dst);
3226 i->ARM64in.Mul.argL = lookupHRegRemap(m, i->ARM64in.Mul.argL);
3227 i->ARM64in.Mul.argR = lookupHRegRemap(m, i->ARM64in.Mul.argR);
3228 break;
sewardj7d009132014-02-20 17:43:38 +00003229 case ARM64in_LdrEX:
3230 return;
3231 case ARM64in_StrEX:
3232 return;
3233 case ARM64in_MFence:
3234 return;
3235//ZZ case ARMin_CLREX:
sewardjbbcf1882014-01-12 12:49:10 +00003236//ZZ return;
3237 case ARM64in_VLdStS:
3238 i->ARM64in.VLdStS.sD = lookupHRegRemap(m, i->ARM64in.VLdStS.sD);
3239 i->ARM64in.VLdStS.rN = lookupHRegRemap(m, i->ARM64in.VLdStS.rN);
3240 return;
3241 case ARM64in_VLdStD:
3242 i->ARM64in.VLdStD.dD = lookupHRegRemap(m, i->ARM64in.VLdStD.dD);
3243 i->ARM64in.VLdStD.rN = lookupHRegRemap(m, i->ARM64in.VLdStD.rN);
3244 return;
3245 case ARM64in_VLdStQ:
3246 i->ARM64in.VLdStQ.rQ = lookupHRegRemap(m, i->ARM64in.VLdStQ.rQ);
3247 i->ARM64in.VLdStQ.rN = lookupHRegRemap(m, i->ARM64in.VLdStQ.rN);
3248 return;
3249 case ARM64in_VCvtI2F:
3250 i->ARM64in.VCvtI2F.rS = lookupHRegRemap(m, i->ARM64in.VCvtI2F.rS);
3251 i->ARM64in.VCvtI2F.rD = lookupHRegRemap(m, i->ARM64in.VCvtI2F.rD);
3252 return;
3253 case ARM64in_VCvtF2I:
3254 i->ARM64in.VCvtF2I.rS = lookupHRegRemap(m, i->ARM64in.VCvtF2I.rS);
3255 i->ARM64in.VCvtF2I.rD = lookupHRegRemap(m, i->ARM64in.VCvtF2I.rD);
3256 return;
3257 case ARM64in_VCvtSD:
3258 i->ARM64in.VCvtSD.dst = lookupHRegRemap(m, i->ARM64in.VCvtSD.dst);
3259 i->ARM64in.VCvtSD.src = lookupHRegRemap(m, i->ARM64in.VCvtSD.src);
3260 return;
3261 case ARM64in_VUnaryD:
3262 i->ARM64in.VUnaryD.dst = lookupHRegRemap(m, i->ARM64in.VUnaryD.dst);
3263 i->ARM64in.VUnaryD.src = lookupHRegRemap(m, i->ARM64in.VUnaryD.src);
3264 return;
3265 case ARM64in_VUnaryS:
3266 i->ARM64in.VUnaryS.dst = lookupHRegRemap(m, i->ARM64in.VUnaryS.dst);
3267 i->ARM64in.VUnaryS.src = lookupHRegRemap(m, i->ARM64in.VUnaryS.src);
3268 return;
3269 case ARM64in_VBinD:
3270 i->ARM64in.VBinD.dst = lookupHRegRemap(m, i->ARM64in.VBinD.dst);
3271 i->ARM64in.VBinD.argL = lookupHRegRemap(m, i->ARM64in.VBinD.argL);
3272 i->ARM64in.VBinD.argR = lookupHRegRemap(m, i->ARM64in.VBinD.argR);
3273 return;
3274 case ARM64in_VBinS:
3275 i->ARM64in.VBinS.dst = lookupHRegRemap(m, i->ARM64in.VBinS.dst);
3276 i->ARM64in.VBinS.argL = lookupHRegRemap(m, i->ARM64in.VBinS.argL);
3277 i->ARM64in.VBinS.argR = lookupHRegRemap(m, i->ARM64in.VBinS.argR);
3278 return;
3279 case ARM64in_VCmpD:
3280 i->ARM64in.VCmpD.argL = lookupHRegRemap(m, i->ARM64in.VCmpD.argL);
3281 i->ARM64in.VCmpD.argR = lookupHRegRemap(m, i->ARM64in.VCmpD.argR);
3282 return;
3283 case ARM64in_VCmpS:
3284 i->ARM64in.VCmpS.argL = lookupHRegRemap(m, i->ARM64in.VCmpS.argL);
3285 i->ARM64in.VCmpS.argR = lookupHRegRemap(m, i->ARM64in.VCmpS.argR);
3286 return;
3287 case ARM64in_FPCR:
3288 i->ARM64in.FPCR.iReg = lookupHRegRemap(m, i->ARM64in.FPCR.iReg);
3289 return;
sewardj12972182014-08-04 08:09:47 +00003290 case ARM64in_FPSR:
3291 i->ARM64in.FPSR.iReg = lookupHRegRemap(m, i->ARM64in.FPSR.iReg);
3292 return;
sewardj606c4ba2014-01-26 19:11:14 +00003293 case ARM64in_VBinV:
3294 i->ARM64in.VBinV.dst = lookupHRegRemap(m, i->ARM64in.VBinV.dst);
3295 i->ARM64in.VBinV.argL = lookupHRegRemap(m, i->ARM64in.VBinV.argL);
3296 i->ARM64in.VBinV.argR = lookupHRegRemap(m, i->ARM64in.VBinV.argR);
3297 return;
sewardjfab09142014-02-10 10:28:13 +00003298 case ARM64in_VUnaryV:
3299 i->ARM64in.VUnaryV.dst = lookupHRegRemap(m, i->ARM64in.VUnaryV.dst);
3300 i->ARM64in.VUnaryV.arg = lookupHRegRemap(m, i->ARM64in.VUnaryV.arg);
3301 return;
sewardj606c4ba2014-01-26 19:11:14 +00003302 case ARM64in_VNarrowV:
3303 i->ARM64in.VNarrowV.dst = lookupHRegRemap(m, i->ARM64in.VNarrowV.dst);
3304 i->ARM64in.VNarrowV.src = lookupHRegRemap(m, i->ARM64in.VNarrowV.src);
3305 return;
sewardje520bb32014-02-17 11:00:53 +00003306 case ARM64in_VShiftImmV:
3307 i->ARM64in.VShiftImmV.dst
3308 = lookupHRegRemap(m, i->ARM64in.VShiftImmV.dst);
3309 i->ARM64in.VShiftImmV.src
3310 = lookupHRegRemap(m, i->ARM64in.VShiftImmV.src);
3311 return;
sewardjab33a7a2014-06-19 22:20:47 +00003312 case ARM64in_VExtV:
3313 i->ARM64in.VExtV.dst = lookupHRegRemap(m, i->ARM64in.VExtV.dst);
3314 i->ARM64in.VExtV.srcLo = lookupHRegRemap(m, i->ARM64in.VExtV.srcLo);
3315 i->ARM64in.VExtV.srcHi = lookupHRegRemap(m, i->ARM64in.VExtV.srcHi);
3316 return;
3317
sewardjbbcf1882014-01-12 12:49:10 +00003318//ZZ case ARMin_VAluS:
3319//ZZ i->ARMin.VAluS.dst = lookupHRegRemap(m, i->ARMin.VAluS.dst);
3320//ZZ i->ARMin.VAluS.argL = lookupHRegRemap(m, i->ARMin.VAluS.argL);
3321//ZZ i->ARMin.VAluS.argR = lookupHRegRemap(m, i->ARMin.VAluS.argR);
3322//ZZ return;
3323//ZZ case ARMin_VCMovD:
3324//ZZ i->ARMin.VCMovD.dst = lookupHRegRemap(m, i->ARMin.VCMovD.dst);
3325//ZZ i->ARMin.VCMovD.src = lookupHRegRemap(m, i->ARMin.VCMovD.src);
3326//ZZ return;
3327//ZZ case ARMin_VCMovS:
3328//ZZ i->ARMin.VCMovS.dst = lookupHRegRemap(m, i->ARMin.VCMovS.dst);
3329//ZZ i->ARMin.VCMovS.src = lookupHRegRemap(m, i->ARMin.VCMovS.src);
3330//ZZ return;
3331//ZZ case ARMin_VXferD:
3332//ZZ i->ARMin.VXferD.dD = lookupHRegRemap(m, i->ARMin.VXferD.dD);
3333//ZZ i->ARMin.VXferD.rHi = lookupHRegRemap(m, i->ARMin.VXferD.rHi);
3334//ZZ i->ARMin.VXferD.rLo = lookupHRegRemap(m, i->ARMin.VXferD.rLo);
3335//ZZ return;
3336//ZZ case ARMin_VXferS:
3337//ZZ i->ARMin.VXferS.fD = lookupHRegRemap(m, i->ARMin.VXferS.fD);
3338//ZZ i->ARMin.VXferS.rLo = lookupHRegRemap(m, i->ARMin.VXferS.rLo);
3339//ZZ return;
3340//ZZ case ARMin_VCvtID:
3341//ZZ i->ARMin.VCvtID.dst = lookupHRegRemap(m, i->ARMin.VCvtID.dst);
3342//ZZ i->ARMin.VCvtID.src = lookupHRegRemap(m, i->ARMin.VCvtID.src);
3343//ZZ return;
sewardjbbcf1882014-01-12 12:49:10 +00003344//ZZ case ARMin_NLdStD:
3345//ZZ i->ARMin.NLdStD.dD = lookupHRegRemap(m, i->ARMin.NLdStD.dD);
3346//ZZ mapRegs_ARMAModeN(m, i->ARMin.NLdStD.amode);
3347//ZZ return;
3348//ZZ case ARMin_NUnary:
3349//ZZ i->ARMin.NUnary.src = lookupHRegRemap(m, i->ARMin.NUnary.src);
3350//ZZ i->ARMin.NUnary.dst = lookupHRegRemap(m, i->ARMin.NUnary.dst);
3351//ZZ return;
3352//ZZ case ARMin_NUnaryS:
3353//ZZ i->ARMin.NUnaryS.src->reg
3354//ZZ = lookupHRegRemap(m, i->ARMin.NUnaryS.src->reg);
3355//ZZ i->ARMin.NUnaryS.dst->reg
3356//ZZ = lookupHRegRemap(m, i->ARMin.NUnaryS.dst->reg);
3357//ZZ return;
3358//ZZ case ARMin_NShift:
3359//ZZ i->ARMin.NShift.dst = lookupHRegRemap(m, i->ARMin.NShift.dst);
3360//ZZ i->ARMin.NShift.argL = lookupHRegRemap(m, i->ARMin.NShift.argL);
3361//ZZ i->ARMin.NShift.argR = lookupHRegRemap(m, i->ARMin.NShift.argR);
3362//ZZ return;
3363//ZZ case ARMin_NShl64:
3364//ZZ i->ARMin.NShl64.dst = lookupHRegRemap(m, i->ARMin.NShl64.dst);
3365//ZZ i->ARMin.NShl64.src = lookupHRegRemap(m, i->ARMin.NShl64.src);
3366//ZZ return;
3367//ZZ case ARMin_NDual:
3368//ZZ i->ARMin.NDual.arg1 = lookupHRegRemap(m, i->ARMin.NDual.arg1);
3369//ZZ i->ARMin.NDual.arg2 = lookupHRegRemap(m, i->ARMin.NDual.arg2);
3370//ZZ return;
3371 case ARM64in_VImmQ:
3372 i->ARM64in.VImmQ.rQ = lookupHRegRemap(m, i->ARM64in.VImmQ.rQ);
3373 return;
3374 case ARM64in_VDfromX:
3375 i->ARM64in.VDfromX.rD
3376 = lookupHRegRemap(m, i->ARM64in.VDfromX.rD);
3377 i->ARM64in.VDfromX.rX
3378 = lookupHRegRemap(m, i->ARM64in.VDfromX.rX);
3379 return;
sewardj12972182014-08-04 08:09:47 +00003380 case ARM64in_VQfromX:
3381 i->ARM64in.VQfromX.rQ
3382 = lookupHRegRemap(m, i->ARM64in.VQfromX.rQ);
3383 i->ARM64in.VQfromX.rXlo
3384 = lookupHRegRemap(m, i->ARM64in.VQfromX.rXlo);
3385 return;
sewardjbbcf1882014-01-12 12:49:10 +00003386 case ARM64in_VQfromXX:
3387 i->ARM64in.VQfromXX.rQ
3388 = lookupHRegRemap(m, i->ARM64in.VQfromXX.rQ);
3389 i->ARM64in.VQfromXX.rXhi
3390 = lookupHRegRemap(m, i->ARM64in.VQfromXX.rXhi);
3391 i->ARM64in.VQfromXX.rXlo
3392 = lookupHRegRemap(m, i->ARM64in.VQfromXX.rXlo);
3393 return;
3394 case ARM64in_VXfromQ:
3395 i->ARM64in.VXfromQ.rX
3396 = lookupHRegRemap(m, i->ARM64in.VXfromQ.rX);
3397 i->ARM64in.VXfromQ.rQ
3398 = lookupHRegRemap(m, i->ARM64in.VXfromQ.rQ);
3399 return;
sewardj85fbb022014-06-12 13:16:01 +00003400 case ARM64in_VXfromDorS:
3401 i->ARM64in.VXfromDorS.rX
3402 = lookupHRegRemap(m, i->ARM64in.VXfromDorS.rX);
3403 i->ARM64in.VXfromDorS.rDorS
3404 = lookupHRegRemap(m, i->ARM64in.VXfromDorS.rDorS);
3405 return;
sewardjbbcf1882014-01-12 12:49:10 +00003406 case ARM64in_VMov:
3407 i->ARM64in.VMov.dst = lookupHRegRemap(m, i->ARM64in.VMov.dst);
3408 i->ARM64in.VMov.src = lookupHRegRemap(m, i->ARM64in.VMov.src);
3409 return;
3410
3411//ZZ case ARMin_NBinary:
3412//ZZ i->ARMin.NBinary.argL = lookupHRegRemap(m, i->ARMin.NBinary.argL);
3413//ZZ i->ARMin.NBinary.argR = lookupHRegRemap(m, i->ARMin.NBinary.argR);
3414//ZZ i->ARMin.NBinary.dst = lookupHRegRemap(m, i->ARMin.NBinary.dst);
3415//ZZ return;
3416//ZZ case ARMin_NCMovQ:
3417//ZZ i->ARMin.NCMovQ.dst = lookupHRegRemap(m, i->ARMin.NCMovQ.dst);
3418//ZZ i->ARMin.NCMovQ.src = lookupHRegRemap(m, i->ARMin.NCMovQ.src);
3419//ZZ return;
3420//ZZ case ARMin_Add32:
3421//ZZ i->ARMin.Add32.rD = lookupHRegRemap(m, i->ARMin.Add32.rD);
3422//ZZ i->ARMin.Add32.rN = lookupHRegRemap(m, i->ARMin.Add32.rN);
3423//ZZ return;
3424 case ARM64in_EvCheck:
3425 /* We expect both amodes only to mention x21, so this is in
3426 fact pointless, since x21 isn't allocatable, but
3427 anyway.. */
3428 mapRegs_ARM64AMode(m, i->ARM64in.EvCheck.amCounter);
3429 mapRegs_ARM64AMode(m, i->ARM64in.EvCheck.amFailAddr);
3430 return;
3431//ZZ case ARMin_ProfInc:
3432//ZZ /* hardwires r11 and r12 -- nothing to modify. */
3433//ZZ return;
3434 default:
3435 ppARM64Instr(i);
3436 vpanic("mapRegs_ARM64Instr");
3437 }
3438}
3439
3440/* Figure out if i represents a reg-reg move, and if so assign the
3441 source and destination to *src and *dst. If in doubt say No. Used
3442 by the register allocator to do move coalescing.
3443*/
3444Bool isMove_ARM64Instr ( ARM64Instr* i, HReg* src, HReg* dst )
3445{
3446 switch (i->tag) {
3447 case ARM64in_MovI:
3448 *src = i->ARM64in.MovI.src;
3449 *dst = i->ARM64in.MovI.dst;
3450 return True;
3451 case ARM64in_VMov:
3452 *src = i->ARM64in.VMov.src;
3453 *dst = i->ARM64in.VMov.dst;
3454 return True;
3455 default:
3456 break;
3457 }
3458
3459 return False;
3460}
3461
3462
3463/* Generate arm spill/reload instructions under the direction of the
3464 register allocator. Note it's critical these don't write the
3465 condition codes. */
3466
3467void genSpill_ARM64 ( /*OUT*/HInstr** i1, /*OUT*/HInstr** i2,
3468 HReg rreg, Int offsetB, Bool mode64 )
3469{
3470 HRegClass rclass;
3471 vassert(offsetB >= 0);
3472 vassert(!hregIsVirtual(rreg));
3473 vassert(mode64 == True);
3474 *i1 = *i2 = NULL;
3475 rclass = hregClass(rreg);
3476 switch (rclass) {
3477 case HRcInt64:
3478 vassert(0 == (offsetB & 7));
3479 offsetB >>= 3;
3480 vassert(offsetB < 4096);
3481 *i1 = ARM64Instr_LdSt64(
3482 False/*!isLoad*/,
3483 rreg,
3484 ARM64AMode_RI12(hregARM64_X21(), offsetB, 8)
3485 );
3486 return;
3487 case HRcFlt64:
3488 vassert(0 == (offsetB & 7));
3489 vassert(offsetB >= 0 && offsetB < 32768);
3490 *i1 = ARM64Instr_VLdStD(False/*!isLoad*/,
3491 rreg, hregARM64_X21(), offsetB);
3492 return;
3493 case HRcVec128: {
3494 HReg x21 = hregARM64_X21(); // baseblock
3495 HReg x9 = hregARM64_X9(); // spill temporary
3496 vassert(0 == (offsetB & 15)); // check sane alignment
3497 vassert(offsetB < 4096);
3498 *i1 = ARM64Instr_Arith(x9, x21, ARM64RIA_I12(offsetB, 0), True);
3499 *i2 = ARM64Instr_VLdStQ(False/*!isLoad*/, rreg, x9);
3500 return;
3501 }
3502 default:
3503 ppHRegClass(rclass);
3504 vpanic("genSpill_ARM: unimplemented regclass");
3505 }
3506}
3507
3508void genReload_ARM64 ( /*OUT*/HInstr** i1, /*OUT*/HInstr** i2,
3509 HReg rreg, Int offsetB, Bool mode64 )
3510{
3511 HRegClass rclass;
3512 vassert(offsetB >= 0);
3513 vassert(!hregIsVirtual(rreg));
3514 vassert(mode64 == True);
3515 *i1 = *i2 = NULL;
3516 rclass = hregClass(rreg);
3517 switch (rclass) {
3518 case HRcInt64:
3519 vassert(0 == (offsetB & 7));
3520 offsetB >>= 3;
3521 vassert(offsetB < 4096);
3522 *i1 = ARM64Instr_LdSt64(
3523 True/*isLoad*/,
3524 rreg,
3525 ARM64AMode_RI12(hregARM64_X21(), offsetB, 8)
3526 );
3527 return;
3528 case HRcFlt64:
3529 vassert(0 == (offsetB & 7));
3530 vassert(offsetB >= 0 && offsetB < 32768);
3531 *i1 = ARM64Instr_VLdStD(True/*isLoad*/,
3532 rreg, hregARM64_X21(), offsetB);
3533 return;
3534 case HRcVec128: {
3535 HReg x21 = hregARM64_X21(); // baseblock
3536 HReg x9 = hregARM64_X9(); // spill temporary
3537 vassert(0 == (offsetB & 15)); // check sane alignment
3538 vassert(offsetB < 4096);
3539 *i1 = ARM64Instr_Arith(x9, x21, ARM64RIA_I12(offsetB, 0), True);
3540 *i2 = ARM64Instr_VLdStQ(True/*isLoad*/, rreg, x9);
3541 return;
3542 }
3543 default:
3544 ppHRegClass(rclass);
3545 vpanic("genReload_ARM: unimplemented regclass");
3546 }
3547}
3548
3549
3550//ZZ /* Emit an instruction into buf and return the number of bytes used.
3551//ZZ Note that buf is not the insn's final place, and therefore it is
3552//ZZ imperative to emit position-independent code. */
3553
3554static inline UChar iregNo ( HReg r )
3555{
3556 UInt n;
3557 vassert(hregClass(r) == HRcInt64);
3558 vassert(!hregIsVirtual(r));
3559 n = hregNumber(r);
3560 vassert(n <= 30);
3561 return toUChar(n);
3562}
3563
3564static inline UChar dregNo ( HReg r )
3565{
3566 UInt n;
3567 vassert(hregClass(r) == HRcFlt64);
3568 vassert(!hregIsVirtual(r));
3569 n = hregNumber(r);
3570 vassert(n <= 31);
3571 return toUChar(n);
3572}
3573
3574static inline UChar qregNo ( HReg r )
3575{
3576 UInt n;
3577 vassert(hregClass(r) == HRcVec128);
3578 vassert(!hregIsVirtual(r));
3579 n = hregNumber(r);
3580 vassert(n <= 31);
3581 return toUChar(n);
3582}
3583
3584#define BITS4(zzb3,zzb2,zzb1,zzb0) \
3585 (((zzb3) << 3) | ((zzb2) << 2) | ((zzb1) << 1) | (zzb0))
3586
3587#define X00 BITS4(0,0, 0,0)
3588#define X01 BITS4(0,0, 0,1)
3589#define X10 BITS4(0,0, 1,0)
3590#define X11 BITS4(0,0, 1,1)
3591
3592#define X000 BITS4(0, 0,0,0)
3593#define X001 BITS4(0, 0,0,1)
3594#define X010 BITS4(0, 0,1,0)
3595#define X011 BITS4(0, 0,1,1)
3596#define X100 BITS4(0, 1,0,0)
3597#define X101 BITS4(0, 1,0,1)
3598#define X110 BITS4(0, 1,1,0)
3599#define X111 BITS4(0, 1,1,1)
3600
sewardjbbcf1882014-01-12 12:49:10 +00003601#define X0000 BITS4(0,0,0,0)
3602#define X0001 BITS4(0,0,0,1)
3603#define X0010 BITS4(0,0,1,0)
3604#define X0011 BITS4(0,0,1,1)
3605
sewardj606c4ba2014-01-26 19:11:14 +00003606#define BITS8(zzb7,zzb6,zzb5,zzb4,zzb3,zzb2,zzb1,zzb0) \
3607 ((BITS4(zzb7,zzb6,zzb5,zzb4) << 4) | BITS4(zzb3,zzb2,zzb1,zzb0))
3608
sewardjbbcf1882014-01-12 12:49:10 +00003609#define X00000 BITS8(0,0,0, 0,0,0,0,0)
sewardj606c4ba2014-01-26 19:11:14 +00003610#define X00001 BITS8(0,0,0, 0,0,0,0,1)
sewardj85fbb022014-06-12 13:16:01 +00003611#define X00110 BITS8(0,0,0, 0,0,1,1,0)
sewardjbbcf1882014-01-12 12:49:10 +00003612#define X00111 BITS8(0,0,0, 0,0,1,1,1)
3613#define X01000 BITS8(0,0,0, 0,1,0,0,0)
3614#define X10000 BITS8(0,0,0, 1,0,0,0,0)
3615#define X11000 BITS8(0,0,0, 1,1,0,0,0)
3616#define X11110 BITS8(0,0,0, 1,1,1,1,0)
3617#define X11111 BITS8(0,0,0, 1,1,1,1,1)
3618
3619#define X000000 BITS8(0,0, 0,0,0,0,0,0)
sewardje520bb32014-02-17 11:00:53 +00003620#define X000001 BITS8(0,0, 0,0,0,0,0,1)
sewardjdf9d6d52014-06-27 10:43:22 +00003621#define X000010 BITS8(0,0, 0,0,0,0,1,0)
sewardja5a6b752014-06-30 07:33:56 +00003622#define X000011 BITS8(0,0, 0,0,0,0,1,1)
sewardjbbcf1882014-01-12 12:49:10 +00003623#define X000100 BITS8(0,0, 0,0,0,1,0,0)
sewardjd96daf62014-06-15 08:17:35 +00003624#define X000110 BITS8(0,0, 0,0,0,1,1,0)
sewardjecde6972014-02-05 11:01:19 +00003625#define X000111 BITS8(0,0, 0,0,0,1,1,1)
sewardjbbcf1882014-01-12 12:49:10 +00003626#define X001000 BITS8(0,0, 0,0,1,0,0,0)
3627#define X001001 BITS8(0,0, 0,0,1,0,0,1)
3628#define X001010 BITS8(0,0, 0,0,1,0,1,0)
sewardja5a6b752014-06-30 07:33:56 +00003629#define X001011 BITS8(0,0, 0,0,1,0,1,1)
sewardj92d0ae32014-04-03 13:48:54 +00003630#define X001101 BITS8(0,0, 0,0,1,1,0,1)
sewardjd96daf62014-06-15 08:17:35 +00003631#define X001110 BITS8(0,0, 0,0,1,1,1,0)
sewardjbbcf1882014-01-12 12:49:10 +00003632#define X001111 BITS8(0,0, 0,0,1,1,1,1)
3633#define X010000 BITS8(0,0, 0,1,0,0,0,0)
3634#define X010001 BITS8(0,0, 0,1,0,0,0,1)
sewardj2b6fd5e2014-06-19 14:21:37 +00003635#define X010010 BITS8(0,0, 0,1,0,0,1,0)
sewardj12972182014-08-04 08:09:47 +00003636#define X010011 BITS8(0,0, 0,1,0,0,1,1)
sewardj32d86752014-03-02 12:47:18 +00003637#define X010101 BITS8(0,0, 0,1,0,1,0,1)
sewardje520bb32014-02-17 11:00:53 +00003638#define X010110 BITS8(0,0, 0,1,0,1,1,0)
sewardj12972182014-08-04 08:09:47 +00003639#define X010111 BITS8(0,0, 0,1,0,1,1,1)
sewardjecde6972014-02-05 11:01:19 +00003640#define X011001 BITS8(0,0, 0,1,1,0,0,1)
sewardjbbcf1882014-01-12 12:49:10 +00003641#define X011010 BITS8(0,0, 0,1,1,0,1,0)
sewardjecde6972014-02-05 11:01:19 +00003642#define X011011 BITS8(0,0, 0,1,1,0,1,1)
sewardja97dddf2014-08-14 22:26:52 +00003643#define X011101 BITS8(0,0, 0,1,1,1,0,1)
sewardje520bb32014-02-17 11:00:53 +00003644#define X011110 BITS8(0,0, 0,1,1,1,1,0)
sewardjbbcf1882014-01-12 12:49:10 +00003645#define X011111 BITS8(0,0, 0,1,1,1,1,1)
sewardj606c4ba2014-01-26 19:11:14 +00003646#define X100001 BITS8(0,0, 1,0,0,0,0,1)
sewardje520bb32014-02-17 11:00:53 +00003647#define X100011 BITS8(0,0, 1,0,0,0,1,1)
sewardjbbcf1882014-01-12 12:49:10 +00003648#define X100100 BITS8(0,0, 1,0,0,1,0,0)
3649#define X100101 BITS8(0,0, 1,0,0,1,0,1)
3650#define X100110 BITS8(0,0, 1,0,0,1,1,0)
sewardjf5b08912014-02-06 12:57:58 +00003651#define X100111 BITS8(0,0, 1,0,0,1,1,1)
sewardj54ffa1d2014-07-22 09:27:49 +00003652#define X101101 BITS8(0,0, 1,0,1,1,0,1)
sewardj25523c42014-06-15 19:36:29 +00003653#define X101110 BITS8(0,0, 1,0,1,1,1,0)
sewardjbbcf1882014-01-12 12:49:10 +00003654#define X110000 BITS8(0,0, 1,1,0,0,0,0)
3655#define X110001 BITS8(0,0, 1,1,0,0,0,1)
sewardj51d012a2014-07-21 09:19:50 +00003656#define X110100 BITS8(0,0, 1,1,0,1,0,0)
sewardj606c4ba2014-01-26 19:11:14 +00003657#define X110101 BITS8(0,0, 1,1,0,1,0,1)
3658#define X110111 BITS8(0,0, 1,1,0,1,1,1)
sewardjbbcf1882014-01-12 12:49:10 +00003659#define X111000 BITS8(0,0, 1,1,1,0,0,0)
3660#define X111001 BITS8(0,0, 1,1,1,0,0,1)
3661#define X111101 BITS8(0,0, 1,1,1,1,0,1)
sewardjfab09142014-02-10 10:28:13 +00003662#define X111110 BITS8(0,0, 1,1,1,1,1,0)
sewardj606c4ba2014-01-26 19:11:14 +00003663#define X111111 BITS8(0,0, 1,1,1,1,1,1)
sewardjbbcf1882014-01-12 12:49:10 +00003664
sewardj93013432014-04-27 12:02:12 +00003665#define X0001000 BITS8(0, 0,0,0,1,0,0,0)
sewardj1eaaec22014-03-07 22:52:19 +00003666#define X0010000 BITS8(0, 0,0,1,0,0,0,0)
sewardj32d86752014-03-02 12:47:18 +00003667#define X0100000 BITS8(0, 0,1,0,0,0,0,0)
sewardje520bb32014-02-17 11:00:53 +00003668#define X1000000 BITS8(0, 1,0,0,0,0,0,0)
3669
sewardjbbcf1882014-01-12 12:49:10 +00003670#define X00100000 BITS8(0,0,1,0,0,0,0,0)
3671#define X00100001 BITS8(0,0,1,0,0,0,0,1)
3672#define X00100010 BITS8(0,0,1,0,0,0,1,0)
3673#define X00100011 BITS8(0,0,1,0,0,0,1,1)
3674#define X01010000 BITS8(0,1,0,1,0,0,0,0)
3675#define X01010001 BITS8(0,1,0,1,0,0,0,1)
3676#define X01010100 BITS8(0,1,0,1,0,1,0,0)
3677#define X01011000 BITS8(0,1,0,1,1,0,0,0)
3678#define X01100000 BITS8(0,1,1,0,0,0,0,0)
3679#define X01100001 BITS8(0,1,1,0,0,0,0,1)
3680#define X01100010 BITS8(0,1,1,0,0,0,1,0)
3681#define X01100011 BITS8(0,1,1,0,0,0,1,1)
3682#define X01110000 BITS8(0,1,1,1,0,0,0,0)
sewardj606c4ba2014-01-26 19:11:14 +00003683#define X01110001 BITS8(0,1,1,1,0,0,0,1)
sewardjd96daf62014-06-15 08:17:35 +00003684#define X01110010 BITS8(0,1,1,1,0,0,1,0)
sewardj606c4ba2014-01-26 19:11:14 +00003685#define X01110011 BITS8(0,1,1,1,0,0,1,1)
sewardjd96daf62014-06-15 08:17:35 +00003686#define X01110100 BITS8(0,1,1,1,0,1,0,0)
sewardj606c4ba2014-01-26 19:11:14 +00003687#define X01110101 BITS8(0,1,1,1,0,1,0,1)
sewardjd96daf62014-06-15 08:17:35 +00003688#define X01110110 BITS8(0,1,1,1,0,1,1,0)
sewardj606c4ba2014-01-26 19:11:14 +00003689#define X01110111 BITS8(0,1,1,1,0,1,1,1)
sewardjbbcf1882014-01-12 12:49:10 +00003690#define X11000001 BITS8(1,1,0,0,0,0,0,1)
3691#define X11000011 BITS8(1,1,0,0,0,0,1,1)
3692#define X11010100 BITS8(1,1,0,1,0,1,0,0)
3693#define X11010110 BITS8(1,1,0,1,0,1,1,0)
3694#define X11011000 BITS8(1,1,0,1,1,0,0,0)
3695#define X11011010 BITS8(1,1,0,1,1,0,1,0)
3696#define X11011110 BITS8(1,1,0,1,1,1,1,0)
3697#define X11110001 BITS8(1,1,1,1,0,0,0,1)
3698#define X11110011 BITS8(1,1,1,1,0,0,1,1)
3699
3700
3701/* --- 4 fields --- */
3702
3703static inline UInt X_8_19_1_4 ( UInt f1, UInt f2, UInt f3, UInt f4 ) {
3704 vassert(8+19+1+4 == 32);
3705 vassert(f1 < (1<<8));
3706 vassert(f2 < (1<<19));
3707 vassert(f3 < (1<<1));
3708 vassert(f4 < (1<<4));
3709 UInt w = 0;
3710 w = (w << 8) | f1;
3711 w = (w << 19) | f2;
3712 w = (w << 1) | f3;
3713 w = (w << 4) | f4;
3714 return w;
3715}
3716
3717/* --- 5 fields --- */
3718
3719static inline UInt X_3_6_2_16_5 ( UInt f1, UInt f2,
3720 UInt f3, UInt f4, UInt f5 ) {
3721 vassert(3+6+2+16+5 == 32);
3722 vassert(f1 < (1<<3));
3723 vassert(f2 < (1<<6));
3724 vassert(f3 < (1<<2));
3725 vassert(f4 < (1<<16));
3726 vassert(f5 < (1<<5));
3727 UInt w = 0;
3728 w = (w << 3) | f1;
3729 w = (w << 6) | f2;
3730 w = (w << 2) | f3;
3731 w = (w << 16) | f4;
3732 w = (w << 5) | f5;
3733 return w;
3734}
3735
3736/* --- 6 fields --- */
3737
3738static inline UInt X_2_6_2_12_5_5 ( UInt f1, UInt f2, UInt f3,
3739 UInt f4, UInt f5, UInt f6 ) {
3740 vassert(2+6+2+12+5+5 == 32);
3741 vassert(f1 < (1<<2));
3742 vassert(f2 < (1<<6));
3743 vassert(f3 < (1<<2));
3744 vassert(f4 < (1<<12));
3745 vassert(f5 < (1<<5));
3746 vassert(f6 < (1<<5));
3747 UInt w = 0;
3748 w = (w << 2) | f1;
3749 w = (w << 6) | f2;
3750 w = (w << 2) | f3;
3751 w = (w << 12) | f4;
3752 w = (w << 5) | f5;
3753 w = (w << 5) | f6;
3754 return w;
3755}
3756
3757static inline UInt X_3_8_5_6_5_5 ( UInt f1, UInt f2, UInt f3,
3758 UInt f4, UInt f5, UInt f6 ) {
3759 vassert(3+8+5+6+5+5 == 32);
3760 vassert(f1 < (1<<3));
3761 vassert(f2 < (1<<8));
3762 vassert(f3 < (1<<5));
3763 vassert(f4 < (1<<6));
3764 vassert(f5 < (1<<5));
3765 vassert(f6 < (1<<5));
3766 UInt w = 0;
3767 w = (w << 3) | f1;
3768 w = (w << 8) | f2;
3769 w = (w << 5) | f3;
3770 w = (w << 6) | f4;
3771 w = (w << 5) | f5;
3772 w = (w << 5) | f6;
3773 return w;
3774}
3775
3776static inline UInt X_3_5_8_6_5_5 ( UInt f1, UInt f2, UInt f3,
3777 UInt f4, UInt f5, UInt f6 ) {
3778 vassert(3+8+5+6+5+5 == 32);
3779 vassert(f1 < (1<<3));
3780 vassert(f2 < (1<<5));
3781 vassert(f3 < (1<<8));
3782 vassert(f4 < (1<<6));
3783 vassert(f5 < (1<<5));
3784 vassert(f6 < (1<<5));
3785 UInt w = 0;
3786 w = (w << 3) | f1;
3787 w = (w << 5) | f2;
3788 w = (w << 8) | f3;
3789 w = (w << 6) | f4;
3790 w = (w << 5) | f5;
3791 w = (w << 5) | f6;
3792 return w;
3793}
3794
sewardje520bb32014-02-17 11:00:53 +00003795static inline UInt X_3_6_7_6_5_5 ( UInt f1, UInt f2, UInt f3,
3796 UInt f4, UInt f5, UInt f6 ) {
3797 vassert(3+6+7+6+5+5 == 32);
3798 vassert(f1 < (1<<3));
3799 vassert(f2 < (1<<6));
3800 vassert(f3 < (1<<7));
3801 vassert(f4 < (1<<6));
3802 vassert(f5 < (1<<5));
3803 vassert(f6 < (1<<5));
3804 UInt w = 0;
3805 w = (w << 3) | f1;
3806 w = (w << 6) | f2;
3807 w = (w << 7) | f3;
3808 w = (w << 6) | f4;
3809 w = (w << 5) | f5;
3810 w = (w << 5) | f6;
3811 return w;
3812}
3813
sewardjbbcf1882014-01-12 12:49:10 +00003814/* --- 7 fields --- */
3815
3816static inline UInt X_2_6_3_9_2_5_5 ( UInt f1, UInt f2, UInt f3,
3817 UInt f4, UInt f5, UInt f6, UInt f7 ) {
3818 vassert(2+6+3+9+2+5+5 == 32);
3819 vassert(f1 < (1<<2));
3820 vassert(f2 < (1<<6));
3821 vassert(f3 < (1<<3));
3822 vassert(f4 < (1<<9));
3823 vassert(f5 < (1<<2));
3824 vassert(f6 < (1<<5));
3825 vassert(f7 < (1<<5));
3826 UInt w = 0;
3827 w = (w << 2) | f1;
3828 w = (w << 6) | f2;
3829 w = (w << 3) | f3;
3830 w = (w << 9) | f4;
3831 w = (w << 2) | f5;
3832 w = (w << 5) | f6;
3833 w = (w << 5) | f7;
3834 return w;
3835}
3836
3837static inline UInt X_3_6_1_6_6_5_5 ( UInt f1, UInt f2, UInt f3,
3838 UInt f4, UInt f5, UInt f6, UInt f7 ) {
3839 vassert(3+6+1+6+6+5+5 == 32);
3840 vassert(f1 < (1<<3));
3841 vassert(f2 < (1<<6));
3842 vassert(f3 < (1<<1));
3843 vassert(f4 < (1<<6));
3844 vassert(f5 < (1<<6));
3845 vassert(f6 < (1<<5));
3846 vassert(f7 < (1<<5));
3847 UInt w = 0;
3848 w = (w << 3) | f1;
3849 w = (w << 6) | f2;
3850 w = (w << 1) | f3;
3851 w = (w << 6) | f4;
3852 w = (w << 6) | f5;
3853 w = (w << 5) | f6;
3854 w = (w << 5) | f7;
3855 return w;
3856}
3857
3858
3859//ZZ #define X0000 BITS4(0,0,0,0)
3860//ZZ #define X0001 BITS4(0,0,0,1)
3861//ZZ #define X0010 BITS4(0,0,1,0)
3862//ZZ #define X0011 BITS4(0,0,1,1)
3863//ZZ #define X0100 BITS4(0,1,0,0)
3864//ZZ #define X0101 BITS4(0,1,0,1)
3865//ZZ #define X0110 BITS4(0,1,1,0)
3866//ZZ #define X0111 BITS4(0,1,1,1)
3867//ZZ #define X1000 BITS4(1,0,0,0)
3868//ZZ #define X1001 BITS4(1,0,0,1)
3869//ZZ #define X1010 BITS4(1,0,1,0)
3870//ZZ #define X1011 BITS4(1,0,1,1)
3871//ZZ #define X1100 BITS4(1,1,0,0)
3872//ZZ #define X1101 BITS4(1,1,0,1)
3873//ZZ #define X1110 BITS4(1,1,1,0)
3874//ZZ #define X1111 BITS4(1,1,1,1)
3875/*
3876#define XXXXX___(zzx7,zzx6,zzx5,zzx4,zzx3) \
3877 ((((zzx7) & 0xF) << 28) | (((zzx6) & 0xF) << 24) | \
3878 (((zzx5) & 0xF) << 20) | (((zzx4) & 0xF) << 16) | \
3879 (((zzx3) & 0xF) << 12))
3880
3881#define XXXXXX__(zzx7,zzx6,zzx5,zzx4,zzx3,zzx2) \
3882 ((((zzx7) & 0xF) << 28) | (((zzx6) & 0xF) << 24) | \
3883 (((zzx5) & 0xF) << 20) | (((zzx4) & 0xF) << 16) | \
3884 (((zzx3) & 0xF) << 12) | (((zzx2) & 0xF) << 8))
3885
3886#define XXXXX__X(zzx7,zzx6,zzx5,zzx4,zzx3,zzx0) \
3887 ((((zzx7) & 0xF) << 28) | (((zzx6) & 0xF) << 24) | \
3888 (((zzx5) & 0xF) << 20) | (((zzx4) & 0xF) << 16) | \
3889 (((zzx3) & 0xF) << 12) | (((zzx0) & 0xF) << 0))
3890
3891#define XXX___XX(zzx7,zzx6,zzx5,zzx1,zzx0) \
3892 ((((zzx7) & 0xF) << 28) | (((zzx6) & 0xF) << 24) | \
3893 (((zzx5) & 0xF) << 20) | (((zzx1) & 0xF) << 4) | \
3894 (((zzx0) & 0xF) << 0))
3895
3896#define XXXXXXXX(zzx7,zzx6,zzx5,zzx4,zzx3,zzx2,zzx1,zzx0) \
3897 ((((zzx7) & 0xF) << 28) | (((zzx6) & 0xF) << 24) | \
3898 (((zzx5) & 0xF) << 20) | (((zzx4) & 0xF) << 16) | \
3899 (((zzx3) & 0xF) << 12) | (((zzx2) & 0xF) << 8) | \
3900 (((zzx1) & 0xF) << 4) | (((zzx0) & 0xF) << 0))
3901
3902#define XX______(zzx7,zzx6) \
3903 ((((zzx7) & 0xF) << 28) | (((zzx6) & 0xF) << 24))
3904*/
3905//ZZ /* Generate a skeletal insn that involves an a RI84 shifter operand.
3906//ZZ Returns a word which is all zeroes apart from bits 25 and 11..0,
3907//ZZ since it is those that encode the shifter operand (at least to the
3908//ZZ extent that we care about it.) */
3909//ZZ static UInt skeletal_RI84 ( ARMRI84* ri )
3910//ZZ {
3911//ZZ UInt instr;
3912//ZZ if (ri->tag == ARMri84_I84) {
3913//ZZ vassert(0 == (ri->ARMri84.I84.imm4 & ~0x0F));
3914//ZZ vassert(0 == (ri->ARMri84.I84.imm8 & ~0xFF));
3915//ZZ instr = 1 << 25;
3916//ZZ instr |= (ri->ARMri84.I84.imm4 << 8);
3917//ZZ instr |= ri->ARMri84.I84.imm8;
3918//ZZ } else {
3919//ZZ instr = 0 << 25;
3920//ZZ instr |= iregNo(ri->ARMri84.R.reg);
3921//ZZ }
3922//ZZ return instr;
3923//ZZ }
3924//ZZ
3925//ZZ /* Ditto for RI5. Resulting word is zeroes apart from bit 4 and bits
3926//ZZ 11..7. */
3927//ZZ static UInt skeletal_RI5 ( ARMRI5* ri )
3928//ZZ {
3929//ZZ UInt instr;
3930//ZZ if (ri->tag == ARMri5_I5) {
3931//ZZ UInt imm5 = ri->ARMri5.I5.imm5;
3932//ZZ vassert(imm5 >= 1 && imm5 <= 31);
3933//ZZ instr = 0 << 4;
3934//ZZ instr |= imm5 << 7;
3935//ZZ } else {
3936//ZZ instr = 1 << 4;
3937//ZZ instr |= iregNo(ri->ARMri5.R.reg) << 8;
3938//ZZ }
3939//ZZ return instr;
3940//ZZ }
3941
3942
3943/* Get an immediate into a register, using only that register. */
3944static UInt* imm64_to_iregNo ( UInt* p, Int xD, ULong imm64 )
3945{
3946 if (imm64 == 0) {
3947 // This has to be special-cased, since the logic below
3948 // will leave the register unchanged in this case.
3949 // MOVZ xD, #0, LSL #0
3950 *p++ = X_3_6_2_16_5(X110, X100101, X00, 0/*imm16*/, xD);
3951 return p;
3952 }
3953
3954 // There must be at least one non-zero halfword. Find the
3955 // lowest nonzero such, and use MOVZ to install it and zero
3956 // out the rest of the register.
3957 UShort h[4];
3958 h[3] = (UShort)((imm64 >> 48) & 0xFFFF);
3959 h[2] = (UShort)((imm64 >> 32) & 0xFFFF);
3960 h[1] = (UShort)((imm64 >> 16) & 0xFFFF);
3961 h[0] = (UShort)((imm64 >> 0) & 0xFFFF);
3962
3963 UInt i;
3964 for (i = 0; i < 4; i++) {
3965 if (h[i] != 0)
3966 break;
3967 }
3968 vassert(i < 4);
3969
3970 // MOVZ xD, h[i], LSL (16*i)
3971 *p++ = X_3_6_2_16_5(X110, X100101, i, h[i], xD);
3972
3973 // Work on upwards through h[i], using MOVK to stuff in any
3974 // remaining nonzero elements.
3975 i++;
3976 for (; i < 4; i++) {
3977 if (h[i] == 0)
3978 continue;
3979 // MOVK xD, h[i], LSL (16*i)
3980 *p++ = X_3_6_2_16_5(X111, X100101, i, h[i], xD);
3981 }
3982
3983 return p;
3984}
3985
3986/* Get an immediate into a register, using only that register, and
3987 generating exactly 4 instructions, regardless of the value of the
3988 immediate. This is used when generating sections of code that need
3989 to be patched later, so as to guarantee a specific size. */
3990static UInt* imm64_to_iregNo_EXACTLY4 ( UInt* p, Int xD, ULong imm64 )
3991{
3992 UShort h[4];
3993 h[3] = (UShort)((imm64 >> 48) & 0xFFFF);
3994 h[2] = (UShort)((imm64 >> 32) & 0xFFFF);
3995 h[1] = (UShort)((imm64 >> 16) & 0xFFFF);
3996 h[0] = (UShort)((imm64 >> 0) & 0xFFFF);
3997 // Work on upwards through h[i], using MOVK to stuff in the
3998 // remaining elements.
3999 UInt i;
4000 for (i = 0; i < 4; i++) {
4001 if (i == 0) {
4002 // MOVZ xD, h[0], LSL (16*0)
4003 *p++ = X_3_6_2_16_5(X110, X100101, i, h[i], xD);
4004 } else {
4005 // MOVK xD, h[i], LSL (16*i)
4006 *p++ = X_3_6_2_16_5(X111, X100101, i, h[i], xD);
4007 }
4008 }
4009 return p;
4010}
4011
4012/* Check whether p points at a 4-insn sequence cooked up by
4013 imm64_to_iregNo_EXACTLY4(). */
4014static Bool is_imm64_to_iregNo_EXACTLY4 ( UInt* p, Int xD, ULong imm64 )
4015{
4016 UShort h[4];
4017 h[3] = (UShort)((imm64 >> 48) & 0xFFFF);
4018 h[2] = (UShort)((imm64 >> 32) & 0xFFFF);
4019 h[1] = (UShort)((imm64 >> 16) & 0xFFFF);
4020 h[0] = (UShort)((imm64 >> 0) & 0xFFFF);
4021 // Work on upwards through h[i], using MOVK to stuff in the
4022 // remaining elements.
4023 UInt i;
4024 for (i = 0; i < 4; i++) {
4025 UInt expected;
4026 if (i == 0) {
4027 // MOVZ xD, h[0], LSL (16*0)
4028 expected = X_3_6_2_16_5(X110, X100101, i, h[i], xD);
4029 } else {
4030 // MOVK xD, h[i], LSL (16*i)
4031 expected = X_3_6_2_16_5(X111, X100101, i, h[i], xD);
4032 }
4033 if (p[i] != expected)
4034 return False;
4035 }
4036 return True;
4037}
4038
4039
4040/* Generate a 8 bit store or 8-to-64 unsigned widening load from/to
4041 rD, using the given amode for the address. */
4042static UInt* do_load_or_store8 ( UInt* p,
4043 Bool isLoad, UInt wD, ARM64AMode* am )
4044{
4045 vassert(wD <= 30);
4046 if (am->tag == ARM64am_RI9) {
4047 /* STURB Wd, [Xn|SP + simm9]: 00 111000 000 simm9 00 n d
4048 LDURB Wd, [Xn|SP + simm9]: 00 111000 010 simm9 00 n d
4049 */
4050 Int simm9 = am->ARM64am.RI9.simm9;
4051 vassert(-256 <= simm9 && simm9 <= 255);
4052 UInt instr = X_2_6_3_9_2_5_5(X00, X111000, isLoad ? X010 : X000,
4053 simm9 & 0x1FF, X00,
4054 iregNo(am->ARM64am.RI9.reg), wD);
4055 *p++ = instr;
4056 return p;
4057 }
4058 if (am->tag == ARM64am_RI12) {
4059 /* STRB Wd, [Xn|SP + uimm12 * 1]: 00 111 001 00 imm12 n d
4060 LDRB Wd, [Xn|SP + uimm12 * 1]: 00 111 001 01 imm12 n d
4061 */
4062 UInt uimm12 = am->ARM64am.RI12.uimm12;
4063 UInt scale = am->ARM64am.RI12.szB;
4064 vassert(scale == 1); /* failure of this is serious. Do not ignore. */
4065 UInt xN = iregNo(am->ARM64am.RI12.reg);
4066 vassert(xN <= 30);
4067 UInt instr = X_2_6_2_12_5_5(X00, X111001, isLoad ? X01 : X00,
4068 uimm12, xN, wD);
4069 *p++ = instr;
4070 return p;
4071 }
4072 if (am->tag == ARM64am_RR) {
4073 /* STRB Xd, [Xn|SP, Xm]: 00 111 000 001 m 011 0 10 n d
4074 LDRB Xd, [Xn|SP, Xm]: 00 111 000 011 m 011 0 10 n d
4075 */
4076 UInt xN = iregNo(am->ARM64am.RR.base);
4077 UInt xM = iregNo(am->ARM64am.RR.index);
4078 vassert(xN <= 30);
4079 UInt instr = X_3_8_5_6_5_5(X001, isLoad ? X11000011 : X11000001,
4080 xM, X011010, xN, wD);
4081 *p++ = instr;
4082 return p;
4083 }
4084 vpanic("do_load_or_store8");
4085 vassert(0);
4086}
4087
4088
4089/* Generate a 16 bit store or 16-to-64 unsigned widening load from/to
4090 rD, using the given amode for the address. */
4091static UInt* do_load_or_store16 ( UInt* p,
4092 Bool isLoad, UInt wD, ARM64AMode* am )
4093{
4094 vassert(wD <= 30);
4095 if (am->tag == ARM64am_RI9) {
4096 /* STURH Wd, [Xn|SP + simm9]: 01 111000 000 simm9 00 n d
4097 LDURH Wd, [Xn|SP + simm9]: 01 111000 010 simm9 00 n d
4098 */
4099 Int simm9 = am->ARM64am.RI9.simm9;
4100 vassert(-256 <= simm9 && simm9 <= 255);
4101 UInt instr = X_2_6_3_9_2_5_5(X01, X111000, isLoad ? X010 : X000,
4102 simm9 & 0x1FF, X00,
4103 iregNo(am->ARM64am.RI9.reg), wD);
4104 *p++ = instr;
4105 return p;
4106 }
4107 if (am->tag == ARM64am_RI12) {
4108 /* STRH Wd, [Xn|SP + uimm12 * 2]: 01 111 001 00 imm12 n d
4109 LDRH Wd, [Xn|SP + uimm12 * 2]: 01 111 001 01 imm12 n d
4110 */
4111 UInt uimm12 = am->ARM64am.RI12.uimm12;
4112 UInt scale = am->ARM64am.RI12.szB;
4113 vassert(scale == 2); /* failure of this is serious. Do not ignore. */
4114 UInt xN = iregNo(am->ARM64am.RI12.reg);
4115 vassert(xN <= 30);
4116 UInt instr = X_2_6_2_12_5_5(X01, X111001, isLoad ? X01 : X00,
4117 uimm12, xN, wD);
4118 *p++ = instr;
4119 return p;
4120 }
4121 if (am->tag == ARM64am_RR) {
4122 /* STRH Xd, [Xn|SP, Xm]: 01 111 000 001 m 011 0 10 n d
4123 LDRH Xd, [Xn|SP, Xm]: 01 111 000 011 m 011 0 10 n d
4124 */
4125 UInt xN = iregNo(am->ARM64am.RR.base);
4126 UInt xM = iregNo(am->ARM64am.RR.index);
4127 vassert(xN <= 30);
4128 UInt instr = X_3_8_5_6_5_5(X011, isLoad ? X11000011 : X11000001,
4129 xM, X011010, xN, wD);
4130 *p++ = instr;
4131 return p;
4132 }
4133 vpanic("do_load_or_store16");
4134 vassert(0);
4135}
4136
4137
4138/* Generate a 32 bit store or 32-to-64 unsigned widening load from/to
4139 rD, using the given amode for the address. */
4140static UInt* do_load_or_store32 ( UInt* p,
4141 Bool isLoad, UInt wD, ARM64AMode* am )
4142{
4143 vassert(wD <= 30);
4144 if (am->tag == ARM64am_RI9) {
4145 /* STUR Wd, [Xn|SP + simm9]: 10 111000 000 simm9 00 n d
4146 LDUR Wd, [Xn|SP + simm9]: 10 111000 010 simm9 00 n d
4147 */
4148 Int simm9 = am->ARM64am.RI9.simm9;
4149 vassert(-256 <= simm9 && simm9 <= 255);
4150 UInt instr = X_2_6_3_9_2_5_5(X10, X111000, isLoad ? X010 : X000,
4151 simm9 & 0x1FF, X00,
4152 iregNo(am->ARM64am.RI9.reg), wD);
4153 *p++ = instr;
4154 return p;
4155 }
4156 if (am->tag == ARM64am_RI12) {
4157 /* STR Wd, [Xn|SP + uimm12 * 4]: 10 111 001 00 imm12 n d
4158 LDR Wd, [Xn|SP + uimm12 * 4]: 10 111 001 01 imm12 n d
4159 */
4160 UInt uimm12 = am->ARM64am.RI12.uimm12;
4161 UInt scale = am->ARM64am.RI12.szB;
4162 vassert(scale == 4); /* failure of this is serious. Do not ignore. */
4163 UInt xN = iregNo(am->ARM64am.RI12.reg);
4164 vassert(xN <= 30);
4165 UInt instr = X_2_6_2_12_5_5(X10, X111001, isLoad ? X01 : X00,
4166 uimm12, xN, wD);
4167 *p++ = instr;
4168 return p;
4169 }
4170 if (am->tag == ARM64am_RR) {
4171 /* STR Wd, [Xn|SP, Xm]: 10 111 000 001 m 011 0 10 n d
4172 LDR Wd, [Xn|SP, Xm]: 10 111 000 011 m 011 0 10 n d
4173 */
4174 UInt xN = iregNo(am->ARM64am.RR.base);
4175 UInt xM = iregNo(am->ARM64am.RR.index);
4176 vassert(xN <= 30);
4177 UInt instr = X_3_8_5_6_5_5(X101, isLoad ? X11000011 : X11000001,
4178 xM, X011010, xN, wD);
4179 *p++ = instr;
4180 return p;
4181 }
4182 vpanic("do_load_or_store32");
4183 vassert(0);
4184}
4185
4186
4187/* Generate a 64 bit load or store to/from xD, using the given amode
4188 for the address. */
4189static UInt* do_load_or_store64 ( UInt* p,
4190 Bool isLoad, UInt xD, ARM64AMode* am )
4191{
4192 /* In all these cases, Rn can't be 31 since that means SP. */
4193 vassert(xD <= 30);
4194 if (am->tag == ARM64am_RI9) {
4195 /* STUR Xd, [Xn|SP + simm9]: 11 111000 000 simm9 00 n d
4196 LDUR Xd, [Xn|SP + simm9]: 11 111000 010 simm9 00 n d
4197 */
4198 Int simm9 = am->ARM64am.RI9.simm9;
4199 vassert(-256 <= simm9 && simm9 <= 255);
4200 UInt xN = iregNo(am->ARM64am.RI9.reg);
4201 vassert(xN <= 30);
4202 UInt instr = X_2_6_3_9_2_5_5(X11, X111000, isLoad ? X010 : X000,
4203 simm9 & 0x1FF, X00, xN, xD);
4204 *p++ = instr;
4205 return p;
4206 }
4207 if (am->tag == ARM64am_RI12) {
4208 /* STR Xd, [Xn|SP + uimm12 * 8]: 11 111 001 00 imm12 n d
4209 LDR Xd, [Xn|SP + uimm12 * 8]: 11 111 001 01 imm12 n d
4210 */
4211 UInt uimm12 = am->ARM64am.RI12.uimm12;
4212 UInt scale = am->ARM64am.RI12.szB;
4213 vassert(scale == 8); /* failure of this is serious. Do not ignore. */
4214 UInt xN = iregNo(am->ARM64am.RI12.reg);
4215 vassert(xN <= 30);
4216 UInt instr = X_2_6_2_12_5_5(X11, X111001, isLoad ? X01 : X00,
4217 uimm12, xN, xD);
4218 *p++ = instr;
4219 return p;
4220 }
4221 if (am->tag == ARM64am_RR) {
4222 /* STR Xd, [Xn|SP, Xm]: 11 111 000 001 m 011 0 10 n d
4223 LDR Xd, [Xn|SP, Xm]: 11 111 000 011 m 011 0 10 n d
4224 */
4225 UInt xN = iregNo(am->ARM64am.RR.base);
4226 UInt xM = iregNo(am->ARM64am.RR.index);
4227 vassert(xN <= 30);
4228 UInt instr = X_3_8_5_6_5_5(X111, isLoad ? X11000011 : X11000001,
4229 xM, X011010, xN, xD);
4230 *p++ = instr;
4231 return p;
4232 }
4233 vpanic("do_load_or_store64");
4234 vassert(0);
4235}
4236
4237
4238/* Emit an instruction into buf and return the number of bytes used.
4239 Note that buf is not the insn's final place, and therefore it is
4240 imperative to emit position-independent code. If the emitted
4241 instruction was a profiler inc, set *is_profInc to True, else
4242 leave it unchanged. */
4243
4244Int emit_ARM64Instr ( /*MB_MOD*/Bool* is_profInc,
4245 UChar* buf, Int nbuf, ARM64Instr* i,
sewardj9b769162014-07-24 12:42:03 +00004246 Bool mode64, VexEndness endness_host,
sewardjbbcf1882014-01-12 12:49:10 +00004247 void* disp_cp_chain_me_to_slowEP,
4248 void* disp_cp_chain_me_to_fastEP,
4249 void* disp_cp_xindir,
4250 void* disp_cp_xassisted )
4251{
4252 UInt* p = (UInt*)buf;
4253 vassert(nbuf >= 32);
4254 vassert(mode64 == True);
4255 vassert(0 == (((HWord)buf) & 3));
4256
4257 switch (i->tag) {
4258 case ARM64in_Arith: {
4259 UInt rD = iregNo(i->ARM64in.Arith.dst);
4260 UInt rN = iregNo(i->ARM64in.Arith.argL);
4261 ARM64RIA* argR = i->ARM64in.Arith.argR;
4262 switch (argR->tag) {
4263 case ARM64riA_I12:
4264 *p++ = X_2_6_2_12_5_5(
4265 i->ARM64in.Arith.isAdd ? X10 : X11,
4266 X010001,
4267 argR->ARM64riA.I12.shift == 12 ? X01 : X00,
4268 argR->ARM64riA.I12.imm12, rN, rD
4269 );
4270 break;
4271 case ARM64riA_R: {
4272 UInt rM = iregNo(i->ARM64in.Arith.argR->ARM64riA.R.reg);
4273 *p++ = X_3_8_5_6_5_5(
4274 i->ARM64in.Arith.isAdd ? X100 : X110,
4275 X01011000, rM, X000000, rN, rD
4276 );
4277 break;
4278 }
4279 default:
4280 goto bad;
4281 }
4282 goto done;
4283 }
4284 case ARM64in_Cmp: {
4285 UInt rD = 31; /* XZR, we are going to dump the result */
4286 UInt rN = iregNo(i->ARM64in.Cmp.argL);
4287 ARM64RIA* argR = i->ARM64in.Cmp.argR;
4288 Bool is64 = i->ARM64in.Cmp.is64;
4289 switch (argR->tag) {
4290 case ARM64riA_I12:
4291 /* 1 11 10001 sh imm12 Rn Rd = SUBS Xd, Xn, #imm */
4292 /* 0 11 10001 sh imm12 Rn Rd = SUBS Wd, Wn, #imm */
4293 *p++ = X_2_6_2_12_5_5(
4294 is64 ? X11 : X01, X110001,
4295 argR->ARM64riA.I12.shift == 12 ? X01 : X00,
4296 argR->ARM64riA.I12.imm12, rN, rD);
4297 break;
4298 case ARM64riA_R: {
4299 /* 1 11 01011 00 0 Rm 000000 Rn Rd = SUBS Xd, Xn, Xm */
4300 /* 0 11 01011 00 0 Rm 000000 Rn Rd = SUBS Wd, Wn, Wm */
4301 UInt rM = iregNo(i->ARM64in.Cmp.argR->ARM64riA.R.reg);
4302 *p++ = X_3_8_5_6_5_5(is64 ? X111 : X011,
4303 X01011000, rM, X000000, rN, rD);
4304 break;
4305 }
4306 default:
4307 goto bad;
4308 }
4309 goto done;
4310 }
4311 case ARM64in_Logic: {
4312 UInt rD = iregNo(i->ARM64in.Logic.dst);
4313 UInt rN = iregNo(i->ARM64in.Logic.argL);
4314 ARM64RIL* argR = i->ARM64in.Logic.argR;
4315 UInt opc = 0; /* invalid */
4316 vassert(rD < 31);
4317 vassert(rN < 31);
4318 switch (i->ARM64in.Logic.op) {
4319 case ARM64lo_OR: opc = X101; break;
4320 case ARM64lo_AND: opc = X100; break;
4321 case ARM64lo_XOR: opc = X110; break;
4322 default: break;
4323 }
4324 vassert(opc != 0);
4325 switch (argR->tag) {
4326 case ARM64riL_I13: {
4327 /* 1 01 100100 N immR immS Rn Rd = ORR <Xd|Sp>, Xn, #imm */
4328 /* 1 00 100100 N immR immS Rn Rd = AND <Xd|Sp>, Xn, #imm */
4329 /* 1 10 100100 N immR immS Rn Rd = EOR <Xd|Sp>, Xn, #imm */
4330 *p++ = X_3_6_1_6_6_5_5(
4331 opc, X100100, argR->ARM64riL.I13.bitN,
4332 argR->ARM64riL.I13.immR, argR->ARM64riL.I13.immS,
4333 rN, rD
4334 );
4335 break;
4336 }
4337 case ARM64riL_R: {
4338 /* 1 01 01010 00 0 m 000000 n d = ORR Xd, Xn, Xm */
4339 /* 1 00 01010 00 0 m 000000 n d = AND Xd, Xn, Xm */
4340 /* 1 10 01010 00 0 m 000000 n d = EOR Xd, Xn, Xm */
4341 UInt rM = iregNo(argR->ARM64riL.R.reg);
4342 vassert(rM < 31);
4343 *p++ = X_3_8_5_6_5_5(opc, X01010000, rM, X000000, rN, rD);
4344 break;
4345 }
4346 default:
4347 goto bad;
4348 }
4349 goto done;
4350 }
4351 case ARM64in_Test: {
4352 UInt rD = 31; /* XZR, we are going to dump the result */
4353 UInt rN = iregNo(i->ARM64in.Test.argL);
4354 ARM64RIL* argR = i->ARM64in.Test.argR;
4355 switch (argR->tag) {
4356 case ARM64riL_I13: {
4357 /* 1 11 100100 N immR immS Rn Rd = ANDS Xd, Xn, #imm */
4358 *p++ = X_3_6_1_6_6_5_5(
4359 X111, X100100, argR->ARM64riL.I13.bitN,
4360 argR->ARM64riL.I13.immR, argR->ARM64riL.I13.immS,
4361 rN, rD
4362 );
4363 break;
4364 }
4365 default:
4366 goto bad;
4367 }
4368 goto done;
4369 }
4370 case ARM64in_Shift: {
4371 UInt rD = iregNo(i->ARM64in.Shift.dst);
4372 UInt rN = iregNo(i->ARM64in.Shift.argL);
4373 ARM64RI6* argR = i->ARM64in.Shift.argR;
4374 vassert(rD < 31);
4375 vassert(rN < 31);
4376 switch (argR->tag) {
4377 case ARM64ri6_I6: {
4378 /* 110 1001101 (63-sh) (64-sh) nn dd LSL Xd, Xn, sh */
4379 /* 110 1001101 sh 63 nn dd LSR Xd, Xn, sh */
4380 /* 100 1001101 sh 63 nn dd ASR Xd, Xn, sh */
4381 UInt sh = argR->ARM64ri6.I6.imm6;
4382 vassert(sh > 0 && sh < 64);
4383 switch (i->ARM64in.Shift.op) {
4384 case ARM64sh_SHL:
4385 *p++ = X_3_6_1_6_6_5_5(X110, X100110,
4386 1, 64-sh, 63-sh, rN, rD);
4387 break;
4388 case ARM64sh_SHR:
4389 *p++ = X_3_6_1_6_6_5_5(X110, X100110, 1, sh, 63, rN, rD);
4390 break;
4391 case ARM64sh_SAR:
4392 *p++ = X_3_6_1_6_6_5_5(X100, X100110, 1, sh, 63, rN, rD);
4393 break;
4394 default:
4395 vassert(0);
4396 }
4397 break;
4398 }
4399 case ARM64ri6_R: {
4400 /* 100 1101 0110 mm 001000 nn dd LSL Xd, Xn, Xm */
4401 /* 100 1101 0110 mm 001001 nn dd LSR Xd, Xn, Xm */
4402 /* 100 1101 0110 mm 001010 nn dd ASR Xd, Xn, Xm */
4403 UInt rM = iregNo(argR->ARM64ri6.R.reg);
4404 vassert(rM < 31);
4405 UInt subOpc = 0;
4406 switch (i->ARM64in.Shift.op) {
4407 case ARM64sh_SHL: subOpc = X001000; break;
4408 case ARM64sh_SHR: subOpc = X001001; break;
4409 case ARM64sh_SAR: subOpc = X001010; break;
4410 default: vassert(0);
4411 }
4412 *p++ = X_3_8_5_6_5_5(X100, X11010110, rM, subOpc, rN, rD);
4413 break;
4414 }
4415 default:
4416 vassert(0);
4417 }
4418 goto done;
4419 }
4420 case ARM64in_Unary: {
4421 UInt rDst = iregNo(i->ARM64in.Unary.dst);
4422 UInt rSrc = iregNo(i->ARM64in.Unary.src);
4423 switch (i->ARM64in.Unary.op) {
4424 case ARM64un_CLZ:
4425 /* 1 10 1101 0110 00000 00010 0 nn dd CLZ Xd, Xn */
4426 /* 1 10 1101 0110 00000 00010 1 nn dd CLS Xd, Xn (unimp) */
4427 *p++ = X_3_8_5_6_5_5(X110,
4428 X11010110, X00000, X000100, rSrc, rDst);
4429 goto done;
4430 case ARM64un_NEG:
4431 /* 1 10 01011 000 m 000000 11111 d NEG Xd,Xm */
4432 /* 0 10 01011 000 m 000000 11111 d NEG Wd,Wm (unimp) */
4433 *p++ = X_3_8_5_6_5_5(X110,
4434 X01011000, rSrc, X000000, X11111, rDst);
4435 goto done;
4436 case ARM64un_NOT: {
4437 /* 1 01 01010 00 1 m 000000 11111 d MVN Xd,Xm */
4438 *p++ = X_3_8_5_6_5_5(X101,
4439 X01010001, rSrc, X000000, X11111, rDst);
4440 goto done;
4441 }
4442 default:
4443 break;
4444 }
4445 goto bad;
4446 }
4447 case ARM64in_MovI: {
4448 /* We generate the "preferred form", ORR Xd, XZR, Xm
4449 101 01010 00 0 m 000000 11111 d
4450 */
4451 UInt instr = 0xAA0003E0;
4452 UInt d = iregNo(i->ARM64in.MovI.dst);
4453 UInt m = iregNo(i->ARM64in.MovI.src);
4454 *p++ = instr | ((m & 31) << 16) | ((d & 31) << 0);
4455 goto done;
4456 }
4457 case ARM64in_Imm64: {
4458 p = imm64_to_iregNo( p, iregNo(i->ARM64in.Imm64.dst),
4459 i->ARM64in.Imm64.imm64 );
4460 goto done;
4461 }
4462 case ARM64in_LdSt64: {
4463 p = do_load_or_store64( p, i->ARM64in.LdSt64.isLoad,
4464 iregNo(i->ARM64in.LdSt64.rD),
4465 i->ARM64in.LdSt64.amode );
4466 goto done;
4467 }
4468 case ARM64in_LdSt32: {
4469 p = do_load_or_store32( p, i->ARM64in.LdSt32.isLoad,
4470 iregNo(i->ARM64in.LdSt32.rD),
4471 i->ARM64in.LdSt32.amode );
4472 goto done;
4473 }
4474 case ARM64in_LdSt16: {
4475 p = do_load_or_store16( p, i->ARM64in.LdSt16.isLoad,
4476 iregNo(i->ARM64in.LdSt16.rD),
4477 i->ARM64in.LdSt16.amode );
4478 goto done;
4479 }
4480 case ARM64in_LdSt8: {
4481 p = do_load_or_store8( p, i->ARM64in.LdSt8.isLoad,
4482 iregNo(i->ARM64in.LdSt8.rD),
4483 i->ARM64in.LdSt8.amode );
4484 goto done;
4485 }
4486//ZZ case ARMin_LdSt32:
4487//ZZ case ARMin_LdSt8U: {
4488//ZZ UInt bL, bB;
4489//ZZ HReg rD;
4490//ZZ ARMAMode1* am;
4491//ZZ ARMCondCode cc;
4492//ZZ if (i->tag == ARMin_LdSt32) {
4493//ZZ bB = 0;
4494//ZZ bL = i->ARMin.LdSt32.isLoad ? 1 : 0;
4495//ZZ am = i->ARMin.LdSt32.amode;
4496//ZZ rD = i->ARMin.LdSt32.rD;
4497//ZZ cc = i->ARMin.LdSt32.cc;
4498//ZZ } else {
4499//ZZ bB = 1;
4500//ZZ bL = i->ARMin.LdSt8U.isLoad ? 1 : 0;
4501//ZZ am = i->ARMin.LdSt8U.amode;
4502//ZZ rD = i->ARMin.LdSt8U.rD;
4503//ZZ cc = i->ARMin.LdSt8U.cc;
4504//ZZ }
4505//ZZ vassert(cc != ARMcc_NV);
4506//ZZ if (am->tag == ARMam1_RI) {
4507//ZZ Int simm12;
4508//ZZ UInt instr, bP;
4509//ZZ if (am->ARMam1.RI.simm13 < 0) {
4510//ZZ bP = 0;
4511//ZZ simm12 = -am->ARMam1.RI.simm13;
4512//ZZ } else {
4513//ZZ bP = 1;
4514//ZZ simm12 = am->ARMam1.RI.simm13;
4515//ZZ }
4516//ZZ vassert(simm12 >= 0 && simm12 <= 4095);
4517//ZZ instr = XXXXX___(cc,X0101,BITS4(bP,bB,0,bL),
4518//ZZ iregNo(am->ARMam1.RI.reg),
4519//ZZ iregNo(rD));
4520//ZZ instr |= simm12;
4521//ZZ *p++ = instr;
4522//ZZ goto done;
4523//ZZ } else {
4524//ZZ // RR case
4525//ZZ goto bad;
4526//ZZ }
4527//ZZ }
4528//ZZ case ARMin_LdSt16: {
4529//ZZ HReg rD = i->ARMin.LdSt16.rD;
4530//ZZ UInt bS = i->ARMin.LdSt16.signedLoad ? 1 : 0;
4531//ZZ UInt bL = i->ARMin.LdSt16.isLoad ? 1 : 0;
4532//ZZ ARMAMode2* am = i->ARMin.LdSt16.amode;
4533//ZZ ARMCondCode cc = i->ARMin.LdSt16.cc;
4534//ZZ vassert(cc != ARMcc_NV);
4535//ZZ if (am->tag == ARMam2_RI) {
4536//ZZ HReg rN = am->ARMam2.RI.reg;
4537//ZZ Int simm8;
4538//ZZ UInt bP, imm8hi, imm8lo, instr;
4539//ZZ if (am->ARMam2.RI.simm9 < 0) {
4540//ZZ bP = 0;
4541//ZZ simm8 = -am->ARMam2.RI.simm9;
4542//ZZ } else {
4543//ZZ bP = 1;
4544//ZZ simm8 = am->ARMam2.RI.simm9;
4545//ZZ }
4546//ZZ vassert(simm8 >= 0 && simm8 <= 255);
4547//ZZ imm8hi = (simm8 >> 4) & 0xF;
4548//ZZ imm8lo = simm8 & 0xF;
4549//ZZ vassert(!(bL == 0 && bS == 1)); // "! signed store"
4550//ZZ /**/ if (bL == 0 && bS == 0) {
4551//ZZ // strh
4552//ZZ instr = XXXXXXXX(cc,X0001, BITS4(bP,1,0,0), iregNo(rN),
4553//ZZ iregNo(rD), imm8hi, X1011, imm8lo);
4554//ZZ *p++ = instr;
4555//ZZ goto done;
4556//ZZ }
4557//ZZ else if (bL == 1 && bS == 0) {
4558//ZZ // ldrh
4559//ZZ instr = XXXXXXXX(cc,X0001, BITS4(bP,1,0,1), iregNo(rN),
4560//ZZ iregNo(rD), imm8hi, X1011, imm8lo);
4561//ZZ *p++ = instr;
4562//ZZ goto done;
4563//ZZ }
4564//ZZ else if (bL == 1 && bS == 1) {
4565//ZZ // ldrsh
4566//ZZ instr = XXXXXXXX(cc,X0001, BITS4(bP,1,0,1), iregNo(rN),
4567//ZZ iregNo(rD), imm8hi, X1111, imm8lo);
4568//ZZ *p++ = instr;
4569//ZZ goto done;
4570//ZZ }
4571//ZZ else vassert(0); // ill-constructed insn
4572//ZZ } else {
4573//ZZ // RR case
4574//ZZ goto bad;
4575//ZZ }
4576//ZZ }
4577//ZZ case ARMin_Ld8S: {
4578//ZZ HReg rD = i->ARMin.Ld8S.rD;
4579//ZZ ARMAMode2* am = i->ARMin.Ld8S.amode;
4580//ZZ ARMCondCode cc = i->ARMin.Ld8S.cc;
4581//ZZ vassert(cc != ARMcc_NV);
4582//ZZ if (am->tag == ARMam2_RI) {
4583//ZZ HReg rN = am->ARMam2.RI.reg;
4584//ZZ Int simm8;
4585//ZZ UInt bP, imm8hi, imm8lo, instr;
4586//ZZ if (am->ARMam2.RI.simm9 < 0) {
4587//ZZ bP = 0;
4588//ZZ simm8 = -am->ARMam2.RI.simm9;
4589//ZZ } else {
4590//ZZ bP = 1;
4591//ZZ simm8 = am->ARMam2.RI.simm9;
4592//ZZ }
4593//ZZ vassert(simm8 >= 0 && simm8 <= 255);
4594//ZZ imm8hi = (simm8 >> 4) & 0xF;
4595//ZZ imm8lo = simm8 & 0xF;
4596//ZZ // ldrsb
4597//ZZ instr = XXXXXXXX(cc,X0001, BITS4(bP,1,0,1), iregNo(rN),
4598//ZZ iregNo(rD), imm8hi, X1101, imm8lo);
4599//ZZ *p++ = instr;
4600//ZZ goto done;
4601//ZZ } else {
4602//ZZ // RR case
4603//ZZ goto bad;
4604//ZZ }
4605//ZZ }
4606
4607 case ARM64in_XDirect: {
4608 /* NB: what goes on here has to be very closely coordinated
4609 with chainXDirect_ARM64 and unchainXDirect_ARM64 below. */
4610 /* We're generating chain-me requests here, so we need to be
4611 sure this is actually allowed -- no-redir translations
4612 can't use chain-me's. Hence: */
4613 vassert(disp_cp_chain_me_to_slowEP != NULL);
4614 vassert(disp_cp_chain_me_to_fastEP != NULL);
4615
4616 /* Use ptmp for backpatching conditional jumps. */
4617 UInt* ptmp = NULL;
4618
4619 /* First off, if this is conditional, create a conditional
4620 jump over the rest of it. Or at least, leave a space for
4621 it that we will shortly fill in. */
4622 if (i->ARM64in.XDirect.cond != ARM64cc_AL) {
4623 vassert(i->ARM64in.XDirect.cond != ARM64cc_NV);
4624 ptmp = p;
4625 *p++ = 0;
4626 }
4627
4628 /* Update the guest PC. */
4629 /* imm64 x9, dstGA */
4630 /* str x9, amPC */
4631 p = imm64_to_iregNo(p, /*x*/9, i->ARM64in.XDirect.dstGA);
4632 p = do_load_or_store64(p, False/*!isLoad*/,
4633 /*x*/9, i->ARM64in.XDirect.amPC);
4634
4635 /* --- FIRST PATCHABLE BYTE follows --- */
4636 /* VG_(disp_cp_chain_me_to_{slowEP,fastEP}) (where we're
4637 calling to) backs up the return address, so as to find the
4638 address of the first patchable byte. So: don't change the
4639 number of instructions (5) below. */
4640 /* movw x9, VG_(disp_cp_chain_me_to_{slowEP,fastEP})[15:0] */
4641 /* movk x9, VG_(disp_cp_chain_me_to_{slowEP,fastEP})[31:15], lsl 16 */
4642 /* movk x9, VG_(disp_cp_chain_me_to_{slowEP,fastEP})[47:32], lsl 32 */
4643 /* movk x9, VG_(disp_cp_chain_me_to_{slowEP,fastEP})[63:48], lsl 48 */
4644 /* blr x9 */
4645 void* disp_cp_chain_me
4646 = i->ARM64in.XDirect.toFastEP ? disp_cp_chain_me_to_fastEP
4647 : disp_cp_chain_me_to_slowEP;
4648 p = imm64_to_iregNo_EXACTLY4(p, /*x*/9,
4649 Ptr_to_ULong(disp_cp_chain_me));
4650 *p++ = 0xD63F0120;
4651 /* --- END of PATCHABLE BYTES --- */
4652
4653 /* Fix up the conditional jump, if there was one. */
4654 if (i->ARM64in.XDirect.cond != ARM64cc_AL) {
4655 Int delta = (UChar*)p - (UChar*)ptmp; /* must be signed */
4656 vassert(delta > 0 && delta < 40);
4657 vassert((delta & 3) == 0);
4658 UInt notCond = 1 ^ (UInt)i->ARM64in.XDirect.cond;
4659 vassert(notCond <= 13); /* Neither AL nor NV */
4660 vassert(ptmp != NULL);
4661 delta = delta >> 2;
4662 *ptmp = X_8_19_1_4(X01010100, delta & ((1<<19)-1), 0, notCond);
4663 }
4664 goto done;
4665 }
4666
4667 case ARM64in_XIndir: {
4668 // XIndir is more or less the same as XAssisted, except
4669 // we don't have a trc value to hand back, so there's no
4670 // write to r21
4671 /* Use ptmp for backpatching conditional jumps. */
4672 //UInt* ptmp = NULL;
4673
4674 /* First off, if this is conditional, create a conditional
4675 jump over the rest of it. Or at least, leave a space for
4676 it that we will shortly fill in. */
4677 if (i->ARM64in.XIndir.cond != ARM64cc_AL) {
4678 vassert(0); //ATC
4679//ZZ vassert(i->ARMin.XIndir.cond != ARMcc_NV);
4680//ZZ ptmp = p;
4681//ZZ *p++ = 0;
4682 }
4683
4684 /* Update the guest PC. */
4685 /* str r-dstGA, amPC */
4686 p = do_load_or_store64(p, False/*!isLoad*/,
4687 iregNo(i->ARM64in.XIndir.dstGA),
4688 i->ARM64in.XIndir.amPC);
4689
4690 /* imm64 x9, VG_(disp_cp_xindir) */
4691 /* br x9 */
4692 p = imm64_to_iregNo(p, /*x*/9, Ptr_to_ULong(disp_cp_xindir));
4693 *p++ = 0xD61F0120; /* br x9 */
4694
4695 /* Fix up the conditional jump, if there was one. */
4696 if (i->ARM64in.XIndir.cond != ARM64cc_AL) {
4697 vassert(0); //ATC
4698//ZZ Int delta = (UChar*)p - (UChar*)ptmp; /* must be signed */
4699//ZZ vassert(delta > 0 && delta < 40);
4700//ZZ vassert((delta & 3) == 0);
4701//ZZ UInt notCond = 1 ^ (UInt)i->ARMin.XIndir.cond;
4702//ZZ vassert(notCond <= 13); /* Neither AL nor NV */
4703//ZZ delta = (delta >> 2) - 2;
4704//ZZ *ptmp = XX______(notCond, X1010) | (delta & 0xFFFFFF);
4705 }
4706 goto done;
4707 }
4708
4709 case ARM64in_XAssisted: {
4710 /* Use ptmp for backpatching conditional jumps. */
4711 UInt* ptmp = NULL;
4712
4713 /* First off, if this is conditional, create a conditional
4714 jump over the rest of it. Or at least, leave a space for
4715 it that we will shortly fill in. I think this can only
4716 ever happen when VEX is driven by the switchbacker. */
4717 if (i->ARM64in.XAssisted.cond != ARM64cc_AL) {
4718 vassert(i->ARM64in.XDirect.cond != ARM64cc_NV);
4719 ptmp = p;
4720 *p++ = 0;
4721 }
4722
4723 /* Update the guest PC. */
4724 /* str r-dstGA, amPC */
4725 p = do_load_or_store64(p, False/*!isLoad*/,
4726 iregNo(i->ARM64in.XAssisted.dstGA),
4727 i->ARM64in.XAssisted.amPC);
4728
4729 /* movw r21, $magic_number */
4730 UInt trcval = 0;
4731 switch (i->ARM64in.XAssisted.jk) {
4732 case Ijk_ClientReq: trcval = VEX_TRC_JMP_CLIENTREQ; break;
4733 case Ijk_Sys_syscall: trcval = VEX_TRC_JMP_SYS_SYSCALL; break;
4734 //case Ijk_Sys_int128: trcval = VEX_TRC_JMP_SYS_INT128; break;
4735 //case Ijk_Yield: trcval = VEX_TRC_JMP_YIELD; break;
4736 //case Ijk_EmWarn: trcval = VEX_TRC_JMP_EMWARN; break;
4737 //case Ijk_MapFail: trcval = VEX_TRC_JMP_MAPFAIL; break;
4738 case Ijk_NoDecode: trcval = VEX_TRC_JMP_NODECODE; break;
sewardj05f5e012014-05-04 10:52:11 +00004739 case Ijk_InvalICache: trcval = VEX_TRC_JMP_INVALICACHE; break;
sewardj65902992014-05-03 21:20:56 +00004740 case Ijk_FlushDCache: trcval = VEX_TRC_JMP_FLUSHDCACHE; break;
sewardj99c1f812014-03-09 09:41:56 +00004741 case Ijk_NoRedir: trcval = VEX_TRC_JMP_NOREDIR; break;
sewardjbbcf1882014-01-12 12:49:10 +00004742 //case Ijk_SigTRAP: trcval = VEX_TRC_JMP_SIGTRAP; break;
4743 //case Ijk_SigSEGV: trcval = VEX_TRC_JMP_SIGSEGV; break;
4744 case Ijk_Boring: trcval = VEX_TRC_JMP_BORING; break;
4745 /* We don't expect to see the following being assisted. */
4746 //case Ijk_Ret:
4747 //case Ijk_Call:
4748 /* fallthrough */
4749 default:
4750 ppIRJumpKind(i->ARM64in.XAssisted.jk);
4751 vpanic("emit_ARM64Instr.ARM64in_XAssisted: "
4752 "unexpected jump kind");
4753 }
4754 vassert(trcval != 0);
4755 p = imm64_to_iregNo(p, /*x*/21, (ULong)trcval);
4756
4757 /* imm64 x9, VG_(disp_cp_xassisted) */
4758 /* br x9 */
4759 p = imm64_to_iregNo(p, /*x*/9, Ptr_to_ULong(disp_cp_xassisted));
4760 *p++ = 0xD61F0120; /* br x9 */
4761
4762 /* Fix up the conditional jump, if there was one. */
4763 if (i->ARM64in.XAssisted.cond != ARM64cc_AL) {
4764 Int delta = (UChar*)p - (UChar*)ptmp; /* must be signed */
4765 vassert(delta > 0 && delta < 40);
4766 vassert((delta & 3) == 0);
4767 UInt notCond = 1 ^ (UInt)i->ARM64in.XDirect.cond;
4768 vassert(notCond <= 13); /* Neither AL nor NV */
4769 vassert(ptmp != NULL);
4770 delta = delta >> 2;
4771 *ptmp = X_8_19_1_4(X01010100, delta & ((1<<19)-1), 0, notCond);
4772 }
4773 goto done;
4774 }
4775
4776 case ARM64in_CSel: {
4777 /* 100 1101 0100 mm cond 00 nn dd = CSEL Xd, Xn, Xm, cond */
4778 UInt dd = iregNo(i->ARM64in.CSel.dst);
4779 UInt nn = iregNo(i->ARM64in.CSel.argL);
4780 UInt mm = iregNo(i->ARM64in.CSel.argR);
4781 UInt cond = (UInt)i->ARM64in.CSel.cond;
4782 vassert(dd < 31 && nn < 31 && mm < 31 && cond < 16);
4783 *p++ = X_3_8_5_6_5_5(X100, X11010100, mm, cond << 2, nn, dd);
4784 goto done;
4785 }
4786
4787 case ARM64in_Call: {
4788 /* We'll use x9 as a scratch register to put the target
4789 address in. */
4790 if (i->ARM64in.Call.cond != ARM64cc_AL
4791 && i->ARM64in.Call.rloc.pri != RLPri_None) {
4792 /* The call might not happen (it isn't unconditional) and
4793 it returns a result. In this case we will need to
4794 generate a control flow diamond to put 0x555..555 in
4795 the return register(s) in the case where the call
4796 doesn't happen. If this ever becomes necessary, maybe
4797 copy code from the 32-bit ARM equivalent. Until that
4798 day, just give up. */
4799 goto bad;
4800 }
4801
4802 UInt* ptmp = NULL;
4803 if (i->ARM64in.Call.cond != ARM64cc_AL) {
4804 /* Create a hole to put a conditional branch in. We'll
4805 patch it once we know the branch length. */
4806 ptmp = p;
4807 *p++ = 0;
4808 }
4809
4810 // x9 = &target
4811 p = imm64_to_iregNo( (UInt*)p,
4812 /*x*/9, (ULong)i->ARM64in.Call.target );
4813 // blr x9
4814 *p++ = 0xD63F0120;
4815
4816 // Patch the hole if necessary
4817 if (i->ARM64in.Call.cond != ARM64cc_AL) {
4818 ULong dist = (ULong)(p - ptmp);
4819 /* imm64_to_iregNo produces between 1 and 4 insns, and
4820 then there's the BLR itself. Hence: */
4821 vassert(dist >= 2 && dist <= 5);
4822 vassert(ptmp != NULL);
4823 // 01010100 simm19 0 cond = B.cond (here + simm19 << 2)
4824 *ptmp = X_8_19_1_4(X01010100, dist, 0,
4825 1 ^ (UInt)i->ARM64in.Call.cond);
4826 } else {
4827 vassert(ptmp == NULL);
4828 }
4829
4830 goto done;
4831 }
4832
4833 case ARM64in_AddToSP: {
4834 /* 10,0 10001 00 imm12 11111 11111 ADD xsp, xsp, #imm12
4835 11,0 10001 00 imm12 11111 11111 SUB xsp, xsp, #imm12
4836 */
4837 Int simm12 = i->ARM64in.AddToSP.simm;
4838 vassert(-4096 < simm12 && simm12 < 4096);
4839 vassert(0 == (simm12 & 0xF));
4840 if (simm12 >= 0) {
4841 *p++ = X_2_6_2_12_5_5(X10, X010001, X00, simm12, X11111, X11111);
4842 } else {
4843 *p++ = X_2_6_2_12_5_5(X11, X010001, X00, -simm12, X11111, X11111);
4844 }
4845 goto done;
4846 }
4847
4848 case ARM64in_FromSP: {
4849 /* 10,0 10001 00 0..(12)..0 11111 dd MOV Xd, xsp */
4850 UInt dd = iregNo(i->ARM64in.FromSP.dst);
4851 vassert(dd < 31);
4852 *p++ = X_2_6_2_12_5_5(X10, X010001, X00, 0, X11111, dd);
4853 goto done;
4854 }
4855
4856 case ARM64in_Mul: {
4857 /* 100 11011 110 mm 011111 nn dd UMULH Xd, Xn,Xm
4858 100 11011 010 mm 011111 nn dd SMULH Xd, Xn,Xm
4859 100 11011 000 mm 011111 nn dd MUL Xd, Xn,Xm
4860 */
4861 UInt dd = iregNo(i->ARM64in.Mul.dst);
4862 UInt nn = iregNo(i->ARM64in.Mul.argL);
4863 UInt mm = iregNo(i->ARM64in.Mul.argR);
4864 vassert(dd < 31 && nn < 31 && mm < 31);
4865 switch (i->ARM64in.Mul.op) {
4866 case ARM64mul_ZX:
4867 *p++ = X_3_8_5_6_5_5(X100, X11011110, mm, X011111, nn, dd);
4868 goto done;
sewardj7fce7cc2014-05-07 09:41:40 +00004869 case ARM64mul_SX:
4870 *p++ = X_3_8_5_6_5_5(X100, X11011010, mm, X011111, nn, dd);
4871 goto done;
sewardjbbcf1882014-01-12 12:49:10 +00004872 case ARM64mul_PLAIN:
4873 *p++ = X_3_8_5_6_5_5(X100, X11011000, mm, X011111, nn, dd);
4874 goto done;
4875 default:
4876 vassert(0);
4877 }
4878 goto bad;
4879 }
sewardj7d009132014-02-20 17:43:38 +00004880 case ARM64in_LdrEX: {
4881 /* 085F7C82 ldxrb w2, [x4]
4882 485F7C82 ldxrh w2, [x4]
4883 885F7C82 ldxr w2, [x4]
4884 C85F7C82 ldxr x2, [x4]
4885 */
4886 switch (i->ARM64in.LdrEX.szB) {
4887 case 1: *p++ = 0x085F7C82; goto done;
4888 case 2: *p++ = 0x485F7C82; goto done;
4889 case 4: *p++ = 0x885F7C82; goto done;
4890 case 8: *p++ = 0xC85F7C82; goto done;
4891 default: break;
4892 }
4893 goto bad;
4894 }
4895 case ARM64in_StrEX: {
4896 /* 08007C82 stxrb w0, w2, [x4]
4897 48007C82 stxrh w0, w2, [x4]
4898 88007C82 stxr w0, w2, [x4]
4899 C8007C82 stxr w0, x2, [x4]
4900 */
4901 switch (i->ARM64in.StrEX.szB) {
4902 case 1: *p++ = 0x08007C82; goto done;
4903 case 2: *p++ = 0x48007C82; goto done;
4904 case 4: *p++ = 0x88007C82; goto done;
4905 case 8: *p++ = 0xC8007C82; goto done;
4906 default: break;
4907 }
4908 goto bad;
4909 }
4910 case ARM64in_MFence: {
4911 *p++ = 0xD5033F9F; /* DSB sy */
4912 *p++ = 0xD5033FBF; /* DMB sy */
4913 *p++ = 0xD5033FDF; /* ISB */
4914 goto done;
4915 }
4916 //case ARM64in_CLREX: {
4917 // //ATC, but believed to be correct
4918 // goto bad;
4919 // *p++ = 0xD5033F5F; /* clrex */
4920 // goto done;
4921 //}
sewardjbbcf1882014-01-12 12:49:10 +00004922 case ARM64in_VLdStS: {
4923 /* 10 111101 01 imm12 n t LDR St, [Xn|SP, #imm12 * 4]
4924 10 111101 00 imm12 n t STR St, [Xn|SP, #imm12 * 4]
4925 */
4926 UInt sD = dregNo(i->ARM64in.VLdStS.sD);
4927 UInt rN = iregNo(i->ARM64in.VLdStS.rN);
4928 UInt uimm12 = i->ARM64in.VLdStS.uimm12;
4929 Bool isLD = i->ARM64in.VLdStS.isLoad;
4930 vassert(uimm12 < 16384 && 0 == (uimm12 & 3));
4931 uimm12 >>= 2;
4932 vassert(uimm12 < (1<<12));
4933 vassert(sD < 32);
4934 vassert(rN < 31);
4935 *p++ = X_2_6_2_12_5_5(X10, X111101, isLD ? X01 : X00,
4936 uimm12, rN, sD);
4937 goto done;
4938 }
4939 case ARM64in_VLdStD: {
4940 /* 11 111101 01 imm12 n t LDR Dt, [Xn|SP, #imm12 * 8]
4941 11 111101 00 imm12 n t STR Dt, [Xn|SP, #imm12 * 8]
4942 */
4943 UInt dD = dregNo(i->ARM64in.VLdStD.dD);
4944 UInt rN = iregNo(i->ARM64in.VLdStD.rN);
4945 UInt uimm12 = i->ARM64in.VLdStD.uimm12;
4946 Bool isLD = i->ARM64in.VLdStD.isLoad;
4947 vassert(uimm12 < 32768 && 0 == (uimm12 & 7));
4948 uimm12 >>= 3;
4949 vassert(uimm12 < (1<<12));
4950 vassert(dD < 32);
4951 vassert(rN < 31);
4952 *p++ = X_2_6_2_12_5_5(X11, X111101, isLD ? X01 : X00,
4953 uimm12, rN, dD);
4954 goto done;
4955 }
4956 case ARM64in_VLdStQ: {
4957 /* 0100 1100 0000 0000 0111 11 rN rQ st1 {vQ.2d}, [<rN|SP>]
4958 0100 1100 0100 0000 0111 11 rN rQ ld1 {vQ.2d}, [<rN|SP>]
4959 */
4960 UInt rQ = qregNo(i->ARM64in.VLdStQ.rQ);
4961 UInt rN = iregNo(i->ARM64in.VLdStQ.rN);
4962 vassert(rQ < 32);
4963 vassert(rN < 31);
4964 if (i->ARM64in.VLdStQ.isLoad) {
4965 *p++ = 0x4C407C00 | (rN << 5) | rQ;
4966 } else {
4967 *p++ = 0x4C007C00 | (rN << 5) | rQ;
4968 }
4969 goto done;
4970 }
4971 case ARM64in_VCvtI2F: {
4972 /* 31 28 23 21 20 18 15 9 4
4973 000 11110 00 1 00 010 000000 n d SCVTF Sd, Wn
4974 000 11110 01 1 00 010 000000 n d SCVTF Dd, Wn
sewardj606c4ba2014-01-26 19:11:14 +00004975 100 11110 00 1 00 010 000000 n d SCVTF Sd, Xn
sewardjbbcf1882014-01-12 12:49:10 +00004976 100 11110 01 1 00 010 000000 n d SCVTF Dd, Xn
4977 000 11110 00 1 00 011 000000 n d UCVTF Sd, Wn
4978 000 11110 01 1 00 011 000000 n d UCVTF Dd, Wn
4979 100 11110 00 1 00 011 000000 n d UCVTF Sd, Xn
4980 100 11110 01 1 00 011 000000 n d UCVTF Dd, Xn
4981 */
4982 UInt rN = iregNo(i->ARM64in.VCvtI2F.rS);
4983 UInt rD = dregNo(i->ARM64in.VCvtI2F.rD);
4984 ARM64CvtOp how = i->ARM64in.VCvtI2F.how;
4985 /* Just handle cases as they show up. */
4986 switch (how) {
4987 case ARM64cvt_F32_I32S: /* SCVTF Sd, Wn */
4988 *p++ = X_3_5_8_6_5_5(X000, X11110, X00100010, X000000, rN, rD);
4989 break;
4990 case ARM64cvt_F64_I32S: /* SCVTF Dd, Wn */
4991 *p++ = X_3_5_8_6_5_5(X000, X11110, X01100010, X000000, rN, rD);
4992 break;
4993 case ARM64cvt_F32_I64S: /* SCVTF Sd, Xn */
4994 *p++ = X_3_5_8_6_5_5(X100, X11110, X00100010, X000000, rN, rD);
4995 break;
4996 case ARM64cvt_F64_I64S: /* SCVTF Dd, Xn */
4997 *p++ = X_3_5_8_6_5_5(X100, X11110, X01100010, X000000, rN, rD);
4998 break;
sewardj1eaaec22014-03-07 22:52:19 +00004999 case ARM64cvt_F32_I32U: /* UCVTF Sd, Wn */
5000 *p++ = X_3_5_8_6_5_5(X000, X11110, X00100011, X000000, rN, rD);
5001 break;
sewardjbbcf1882014-01-12 12:49:10 +00005002 case ARM64cvt_F64_I32U: /* UCVTF Dd, Wn */
5003 *p++ = X_3_5_8_6_5_5(X000, X11110, X01100011, X000000, rN, rD);
5004 break;
5005 case ARM64cvt_F32_I64U: /* UCVTF Sd, Xn */
5006 *p++ = X_3_5_8_6_5_5(X100, X11110, X00100011, X000000, rN, rD);
5007 break;
5008 case ARM64cvt_F64_I64U: /* UCVTF Dd, Xn */
5009 *p++ = X_3_5_8_6_5_5(X100, X11110, X01100011, X000000, rN, rD);
5010 break;
5011 default:
5012 goto bad; //ATC
5013 }
5014 goto done;
5015 }
5016 case ARM64in_VCvtF2I: {
5017 /* 30 23 20 18 15 9 4
5018 sf 00,11110,0x 1 00 000,000000 n d FCVTNS Rd, Fn (round to
5019 sf 00,11110,0x 1 00 001,000000 n d FCVTNU Rd, Fn nearest)
5020 ---------------- 01 -------------- FCVTP-------- (round to +inf)
5021 ---------------- 10 -------------- FCVTM-------- (round to -inf)
5022 ---------------- 11 -------------- FCVTZ-------- (round to zero)
5023
5024 Rd is Xd when sf==1, Wd when sf==0
5025 Fn is Dn when x==1, Sn when x==0
5026 20:19 carry the rounding mode, using the same encoding as FPCR
5027 */
5028 UInt rD = iregNo(i->ARM64in.VCvtF2I.rD);
5029 UInt rN = dregNo(i->ARM64in.VCvtF2I.rS);
5030 ARM64CvtOp how = i->ARM64in.VCvtF2I.how;
5031 UChar armRM = i->ARM64in.VCvtF2I.armRM;
5032 /* Just handle cases as they show up. */
5033 switch (how) {
5034 case ARM64cvt_F64_I32S: /* FCVTxS Wd, Dn */
5035 *p++ = X_3_5_8_6_5_5(X000, X11110, X01100000 | (armRM << 3),
5036 X000000, rN, rD);
5037 break;
5038 case ARM64cvt_F64_I32U: /* FCVTxU Wd, Dn */
5039 *p++ = X_3_5_8_6_5_5(X000, X11110, X01100001 | (armRM << 3),
5040 X000000, rN, rD);
5041 break;
5042 case ARM64cvt_F64_I64S: /* FCVTxS Xd, Dn */
5043 *p++ = X_3_5_8_6_5_5(X100, X11110, X01100000 | (armRM << 3),
5044 X000000, rN, rD);
5045 break;
5046 case ARM64cvt_F64_I64U: /* FCVTxU Xd, Dn */
5047 *p++ = X_3_5_8_6_5_5(X100, X11110, X01100001 | (armRM << 3),
5048 X000000, rN, rD);
5049 break;
sewardjbbcf1882014-01-12 12:49:10 +00005050 case ARM64cvt_F32_I32S: /* FCVTxS Wd, Sn */
5051 *p++ = X_3_5_8_6_5_5(X000, X11110, X00100000 | (armRM << 3),
5052 X000000, rN, rD);
5053 break;
sewardj1eaaec22014-03-07 22:52:19 +00005054 case ARM64cvt_F32_I32U: /* FCVTxU Wd, Sn */
5055 *p++ = X_3_5_8_6_5_5(X000, X11110, X00100001 | (armRM << 3),
5056 X000000, rN, rD);
5057 break;
5058 case ARM64cvt_F32_I64S: /* FCVTxS Xd, Sn */
5059 *p++ = X_3_5_8_6_5_5(X100, X11110, X00100000 | (armRM << 3),
5060 X000000, rN, rD);
5061 break;
sewardjbbcf1882014-01-12 12:49:10 +00005062 case ARM64cvt_F32_I64U: /* FCVTxU Xd, Sn */
5063 *p++ = X_3_5_8_6_5_5(X100, X11110, X00100001 | (armRM << 3),
5064 X000000, rN, rD);
5065 break;
5066 default:
5067 goto bad; //ATC
5068 }
5069 goto done;
5070 }
5071 case ARM64in_VCvtSD: {
5072 /* 31 23 21 16 14 9 4
5073 000,11110, 00 10001 0,1 10000 n d FCVT Dd, Sn (S->D)
5074 ---------- 01 ----- 0,0 --------- FCVT Sd, Dn (D->S)
5075 Rounding, when dst is smaller than src, is per the FPCR.
5076 */
5077 UInt dd = dregNo(i->ARM64in.VCvtSD.dst);
5078 UInt nn = dregNo(i->ARM64in.VCvtSD.src);
5079 if (i->ARM64in.VCvtSD.sToD) {
5080 *p++ = X_3_5_8_6_5_5(X000, X11110, X00100010, X110000, nn, dd);
5081 } else {
5082 *p++ = X_3_5_8_6_5_5(X000, X11110, X01100010, X010000, nn, dd);
5083 }
5084 goto done;
5085 }
sewardjbbcf1882014-01-12 12:49:10 +00005086 case ARM64in_VUnaryD: {
5087 /* 31 23 21 16 14 9 4
5088 000,11110 01 1,0000 0,0 10000 n d FMOV Dd, Dn (not handled)
5089 ------------------- 0,1 --------- FABS ------
5090 ------------------- 1,0 --------- FNEG ------
5091 ------------------- 1,1 --------- FQSRT -----
5092 */
5093 UInt dD = dregNo(i->ARM64in.VUnaryD.dst);
5094 UInt dN = dregNo(i->ARM64in.VUnaryD.src);
5095 UInt b16 = 2; /* impossible */
5096 UInt b15 = 2; /* impossible */
5097 switch (i->ARM64in.VUnaryD.op) {
5098 case ARM64fpu_NEG: b16 = 1; b15 = 0; break;
5099 case ARM64fpu_SQRT: b16 = 1; b15 = 1; break;
5100 case ARM64fpu_ABS: b16 = 0; b15 = 1; break;
5101 default: break;
5102 }
5103 if (b16 < 2 && b15 < 2) {
5104 *p++ = X_3_8_5_6_5_5(X000, X11110011, (X0000 << 1) | b16,
5105 (b15 << 5) | X10000, dN, dD);
5106 goto done;
5107 }
5108 /*
5109 000, 11110 01 1,001 11,1 10000 n d FRINTI Dd, Dm (round per FPCR)
5110 */
5111 if (i->ARM64in.VUnaryD.op == ARM64fpu_RINT) {
5112 *p++ = X_3_8_5_6_5_5(X000, X11110011, X00111, X110000, dN, dD);
5113 goto done;
5114 }
5115 goto bad;
5116 }
5117 case ARM64in_VUnaryS: {
5118 /* 31 23 21 16 14 9 4
5119 000,11110 00 1,0000 0,0 10000 n d FMOV Sd, Sn (not handled)
5120 ------------------- 0,1 --------- FABS ------
5121 ------------------- 1,0 --------- FNEG ------
5122 ------------------- 1,1 --------- FQSRT -----
5123 */
5124 UInt sD = dregNo(i->ARM64in.VUnaryS.dst);
5125 UInt sN = dregNo(i->ARM64in.VUnaryS.src);
5126 UInt b16 = 2; /* impossible */
5127 UInt b15 = 2; /* impossible */
5128 switch (i->ARM64in.VUnaryS.op) {
5129 case ARM64fpu_NEG: b16 = 1; b15 = 0; break;
5130 case ARM64fpu_SQRT: b16 = 1; b15 = 1; break;
5131 case ARM64fpu_ABS: b16 = 0; b15 = 1; break;
5132 default: break;
5133 }
5134 if (b16 < 2 && b15 < 2) {
5135 *p++ = X_3_8_5_6_5_5(X000, X11110001, (X0000 << 1) | b16,
5136 (b15 << 5) | X10000, sN, sD);
5137 goto done;
5138 }
5139 /*
5140 000, 11110 00 1,001 11,1 10000 n d FRINTI Sd, Sm (round per FPCR)
5141 */
5142 if (i->ARM64in.VUnaryS.op == ARM64fpu_RINT) {
5143 *p++ = X_3_8_5_6_5_5(X000, X11110001, X00111, X110000, sN, sD);
5144 goto done;
5145 }
5146 goto bad;
5147 }
5148 case ARM64in_VBinD: {
5149 /* 31 23 20 15 11 9 4
5150 ---------------- 0000 ------ FMUL --------
5151 000 11110 011 m 0001 10 n d FDIV Dd,Dn,Dm
5152 ---------------- 0010 ------ FADD --------
5153 ---------------- 0011 ------ FSUB --------
5154 */
5155 UInt dD = dregNo(i->ARM64in.VBinD.dst);
5156 UInt dN = dregNo(i->ARM64in.VBinD.argL);
5157 UInt dM = dregNo(i->ARM64in.VBinD.argR);
5158 UInt b1512 = 16; /* impossible */
5159 switch (i->ARM64in.VBinD.op) {
5160 case ARM64fpb_DIV: b1512 = X0001; break;
5161 case ARM64fpb_MUL: b1512 = X0000; break;
5162 case ARM64fpb_SUB: b1512 = X0011; break;
5163 case ARM64fpb_ADD: b1512 = X0010; break;
5164 default: goto bad;
5165 }
5166 vassert(b1512 < 16);
5167 *p++
5168 = X_3_8_5_6_5_5(X000, X11110011, dM, (b1512 << 2) | X10, dN, dD);
5169 goto done;
5170 }
5171 case ARM64in_VBinS: {
5172 /* 31 23 20 15 11 9 4
5173 ---------------- 0000 ------ FMUL --------
5174 000 11110 001 m 0001 10 n d FDIV Dd,Dn,Dm
5175 ---------------- 0010 ------ FADD --------
5176 ---------------- 0011 ------ FSUB --------
5177 */
5178 UInt sD = dregNo(i->ARM64in.VBinS.dst);
5179 UInt sN = dregNo(i->ARM64in.VBinS.argL);
5180 UInt sM = dregNo(i->ARM64in.VBinS.argR);
5181 UInt b1512 = 16; /* impossible */
5182 switch (i->ARM64in.VBinS.op) {
5183 case ARM64fpb_DIV: b1512 = X0001; break;
5184 case ARM64fpb_MUL: b1512 = X0000; break;
5185 case ARM64fpb_SUB: b1512 = X0011; break;
5186 case ARM64fpb_ADD: b1512 = X0010; break;
5187 default: goto bad;
5188 }
5189 vassert(b1512 < 16);
5190 *p++
5191 = X_3_8_5_6_5_5(X000, X11110001, sM, (b1512 << 2) | X10, sN, sD);
5192 goto done;
5193 }
5194 case ARM64in_VCmpD: {
5195 /* 000 11110 01 1 m 00 1000 n 00 000 FCMP Dn, Dm */
5196 UInt dN = dregNo(i->ARM64in.VCmpD.argL);
5197 UInt dM = dregNo(i->ARM64in.VCmpD.argR);
5198 *p++ = X_3_8_5_6_5_5(X000, X11110011, dM, X001000, dN, X00000);
5199 goto done;
5200 }
5201 case ARM64in_VCmpS: {
5202 /* 000 11110 00 1 m 00 1000 n 00 000 FCMP Sn, Sm */
5203 UInt sN = dregNo(i->ARM64in.VCmpS.argL);
5204 UInt sM = dregNo(i->ARM64in.VCmpS.argR);
5205 *p++ = X_3_8_5_6_5_5(X000, X11110001, sM, X001000, sN, X00000);
5206 goto done;
5207 }
sewardj606c4ba2014-01-26 19:11:14 +00005208 case ARM64in_FPCR: {
5209 Bool toFPCR = i->ARM64in.FPCR.toFPCR;
5210 UInt iReg = iregNo(i->ARM64in.FPCR.iReg);
5211 if (toFPCR) {
5212 /* 0xD51B44 000 Rt MSR fpcr, rT */
5213 *p++ = 0xD51B4400 | (iReg & 0x1F);
5214 goto done;
5215 }
5216 goto bad; // FPCR -> iReg case currently ATC
5217 }
sewardj12972182014-08-04 08:09:47 +00005218 case ARM64in_FPSR: {
5219 Bool toFPSR = i->ARM64in.FPSR.toFPSR;
5220 UInt iReg = iregNo(i->ARM64in.FPSR.iReg);
5221 if (toFPSR) {
5222 /* 0xD51B44 001 Rt MSR fpsr, rT */
5223 *p++ = 0xD51B4420 | (iReg & 0x1F);
5224 } else {
5225 /* 0xD53B44 001 Rt MRS rT, fpsr */
5226 *p++ = 0xD53B4420 | (iReg & 0x1F);
5227 }
5228 goto done;
5229 }
sewardj606c4ba2014-01-26 19:11:14 +00005230 case ARM64in_VBinV: {
5231 /* 31 23 20 15 9 4
sewardj93013432014-04-27 12:02:12 +00005232 010 01110 11 1 m 100001 n d ADD Vd.2d, Vn.2d, Vm.2d
5233 010 01110 10 1 m 100001 n d ADD Vd.4s, Vn.4s, Vm.4s
5234 010 01110 01 1 m 100001 n d ADD Vd.8h, Vn.8h, Vm.8h
sewardj92d0ae32014-04-03 13:48:54 +00005235 010 01110 00 1 m 100001 n d ADD Vd.16b, Vn.16b, Vm.16b
sewardjf5b08912014-02-06 12:57:58 +00005236
sewardj93013432014-04-27 12:02:12 +00005237 011 01110 11 1 m 100001 n d SUB Vd.2d, Vn.2d, Vm.2d
5238 011 01110 10 1 m 100001 n d SUB Vd.4s, Vn.4s, Vm.4s
5239 011 01110 01 1 m 100001 n d SUB Vd.8h, Vn.8h, Vm.8h
sewardj92d0ae32014-04-03 13:48:54 +00005240 011 01110 00 1 m 100001 n d SUB Vd.16b, Vn.16b, Vm.16b
sewardjf5b08912014-02-06 12:57:58 +00005241
sewardj93013432014-04-27 12:02:12 +00005242 010 01110 10 1 m 100111 n d MUL Vd.4s, Vn.4s, Vm.4s
5243 010 01110 01 1 m 100111 n d MUL Vd.8h, Vn.8h, Vm.8h
5244 010 01110 00 1 m 100111 n d MUL Vd.16b, Vn.16b, Vm.16b
sewardjf5b08912014-02-06 12:57:58 +00005245
sewardj606c4ba2014-01-26 19:11:14 +00005246 010 01110 01 1 m 110101 n d FADD Vd.2d, Vn.2d, Vm.2d
sewardjecde6972014-02-05 11:01:19 +00005247 010 01110 00 1 m 110101 n d FADD Vd.4s, Vn.4s, Vm.4s
sewardj606c4ba2014-01-26 19:11:14 +00005248 010 01110 11 1 m 110101 n d FSUB Vd.2d, Vn.2d, Vm.2d
sewardjecde6972014-02-05 11:01:19 +00005249 010 01110 10 1 m 110101 n d FSUB Vd.4s, Vn.4s, Vm.4s
sewardjf5b08912014-02-06 12:57:58 +00005250
sewardj606c4ba2014-01-26 19:11:14 +00005251 011 01110 01 1 m 110111 n d FMUL Vd.2d, Vn.2d, Vm.2d
sewardjecde6972014-02-05 11:01:19 +00005252 011 01110 00 1 m 110111 n d FMUL Vd.4s, Vn.4s, Vm.4s
sewardj606c4ba2014-01-26 19:11:14 +00005253 011 01110 01 1 m 111111 n d FDIV Vd.2d, Vn.2d, Vm.2d
sewardjecde6972014-02-05 11:01:19 +00005254 011 01110 00 1 m 111111 n d FDIV Vd.4s, Vn.4s, Vm.4s
sewardjf5b08912014-02-06 12:57:58 +00005255
sewardjfab09142014-02-10 10:28:13 +00005256 011 01110 10 1 m 011001 n d UMAX Vd.4s, Vn.4s, Vm.4s
5257 011 01110 01 1 m 011001 n d UMAX Vd.8h, Vn.8h, Vm.8h
5258 011 01110 00 1 m 011001 n d UMAX Vd.16b, Vn.16b, Vm.16b
5259
5260 011 01110 10 1 m 011011 n d UMIN Vd.4s, Vn.4s, Vm.4s
5261 011 01110 01 1 m 011011 n d UMIN Vd.8h, Vn.8h, Vm.8h
5262 011 01110 00 1 m 011011 n d UMIN Vd.16b, Vn.16b, Vm.16b
sewardjf5b08912014-02-06 12:57:58 +00005263
sewardj9b1cf5e2014-03-01 11:16:57 +00005264 010 01110 10 1 m 011001 n d SMAX Vd.4s, Vn.4s, Vm.4s
5265 010 01110 01 1 m 011001 n d SMAX Vd.8h, Vn.8h, Vm.8h
5266 010 01110 00 1 m 011001 n d SMAX Vd.16b, Vn.16b, Vm.16b
sewardjfab09142014-02-10 10:28:13 +00005267
sewardj9b1cf5e2014-03-01 11:16:57 +00005268 010 01110 10 1 m 011011 n d SMIN Vd.4s, Vn.4s, Vm.4s
5269 010 01110 01 1 m 011011 n d SMIN Vd.8h, Vn.8h, Vm.8h
5270 010 01110 00 1 m 011011 n d SMIN Vd.16b, Vn.16b, Vm.16b
sewardjf5b08912014-02-06 12:57:58 +00005271
sewardjecde6972014-02-05 11:01:19 +00005272 010 01110 00 1 m 000111 n d AND Vd, Vn, Vm
5273 010 01110 10 1 m 000111 n d ORR Vd, Vn, Vm
sewardje520bb32014-02-17 11:00:53 +00005274 011 01110 00 1 m 000111 n d EOR Vd, Vn, Vm
5275
sewardj505a27d2014-03-10 10:40:48 +00005276 011 01110 11 1 m 100011 n d CMEQ Vd.2d, Vn.2d, Vm.2d
5277 011 01110 10 1 m 100011 n d CMEQ Vd.4s, Vn.4s, Vm.4s
5278 011 01110 01 1 m 100011 n d CMEQ Vd.8h, Vn.8h, Vm.8h
5279 011 01110 00 1 m 100011 n d CMEQ Vd.16b, Vn.16b, Vm.16b
5280
sewardj93013432014-04-27 12:02:12 +00005281 011 01110 11 1 m 001101 n d CMHI Vd.2d, Vn.2d, Vm.2d
5282 011 01110 10 1 m 001101 n d CMHI Vd.4s, Vn.4s, Vm.4s
5283 011 01110 01 1 m 001101 n d CMHI Vd.8h, Vn.8h, Vm.8h
5284 011 01110 00 1 m 001101 n d CMHI Vd.16b, Vn.16b, Vm.16b
5285
5286 010 01110 11 1 m 001101 n d CMGT Vd.2d, Vn.2d, Vm.2d
5287 010 01110 10 1 m 001101 n d CMGT Vd.4s, Vn.4s, Vm.4s
5288 010 01110 01 1 m 001101 n d CMGT Vd.8h, Vn.8h, Vm.8h
5289 010 01110 00 1 m 001101 n d CMGT Vd.16b, Vn.16b, Vm.16b
sewardj2bd1ffe2014-03-27 18:59:00 +00005290
5291 010 01110 01 1 m 111001 n d FCMEQ Vd.2d, Vn.2d, Vm.2d
5292 010 01110 00 1 m 111001 n d FCMEQ Vd.4s, Vn.4s, Vm.4s
5293
5294 011 01110 01 1 m 111001 n d FCMGE Vd.2d, Vn.2d, Vm.2d
5295 011 01110 00 1 m 111001 n d FCMGE Vd.4s, Vn.4s, Vm.4s
5296
5297 011 01110 11 1 m 111001 n d FCMGT Vd.2d, Vn.2d, Vm.2d
5298 011 01110 10 1 m 111001 n d FCMGT Vd.4s, Vn.4s, Vm.4s
sewardj92d0ae32014-04-03 13:48:54 +00005299
5300 010 01110 00 0 m 000000 n d TBL Vd.16b, {Vn.16b}, Vm.16b
5301
sewardjd96daf62014-06-15 08:17:35 +00005302 010 01110 11 0 m 000110 n d UZP1 Vd.2d, Vn.2d, Vm.2d
5303 010 01110 10 0 m 000110 n d UZP1 Vd.4s, Vn.4s, Vm.4s
5304 010 01110 01 0 m 000110 n d UZP1 Vd.8h, Vn.8h, Vm.8h
5305 010 01110 00 0 m 000110 n d UZP1 Vd.16b, Vn.16b, Vm.16b
5306
5307 010 01110 11 0 m 010110 n d UZP2 Vd.2d, Vn.2d, Vm.2d
5308 010 01110 10 0 m 010110 n d UZP2 Vd.4s, Vn.4s, Vm.4s
5309 010 01110 01 0 m 010110 n d UZP2 Vd.8h, Vn.8h, Vm.8h
5310 010 01110 00 0 m 010110 n d UZP2 Vd.16b, Vn.16b, Vm.16b
5311
5312 010 01110 10 0 m 001110 n d ZIP1 Vd.4s, Vn.4s, Vm.4s
5313 010 01110 01 0 m 001110 n d ZIP1 Vd.8h, Vn.8h, Vm.8h
5314 010 01110 10 0 m 001110 n d ZIP1 Vd.16b, Vn.16b, Vm.16b
5315
5316 010 01110 10 0 m 011110 n d ZIP2 Vd.4s, Vn.4s, Vm.4s
5317 010 01110 01 0 m 011110 n d ZIP2 Vd.8h, Vn.8h, Vm.8h
5318 010 01110 10 0 m 011110 n d ZIP2 Vd.16b, Vn.16b, Vm.16b
sewardj168c8bd2014-06-25 13:05:23 +00005319
5320 011 01110 00 1 m 100111 n d PMUL Vd.16b, Vn.16b, Vm.16b
sewardj31b5a952014-06-26 07:41:14 +00005321
5322 000 01110 00 1 m 111000 n d PMULL Vd.8h, Vn.8b, Vm.8b
sewardj6f312d02014-06-28 12:21:37 +00005323
5324 001 01110 10 1 m 110000 n d UMULL Vd.2d, Vn.2s, Vm.2s
5325 001 01110 01 1 m 110000 n d UMULL Vd.4s, Vn.4h, Vm.4h
5326 001 01110 00 1 m 110000 n d UMULL Vd.8h, Vn.8b, Vm.8b
5327
5328 000 01110 10 1 m 110000 n d SMULL Vd.2d, Vn.2s, Vm.2s
5329 000 01110 01 1 m 110000 n d SMULL Vd.4s, Vn.4h, Vm.4h
5330 000 01110 00 1 m 110000 n d SMULL Vd.8h, Vn.8b, Vm.8b
sewardja5a6b752014-06-30 07:33:56 +00005331
5332 010 01110 11 1 m 000011 n d SQADD Vd.2d, Vn.2d, Vm.2d
5333 010 01110 10 1 m 000011 n d SQADD Vd.4s, Vn.4s, Vm.4s
5334 010 01110 01 1 m 000011 n d SQADD Vd.8h, Vn.8h, Vm.8h
5335 010 01110 00 1 m 000011 n d SQADD Vd.16b, Vn.16b, Vm.16b
5336
5337 011 01110 11 1 m 000011 n d UQADD Vd.2d, Vn.2d, Vm.2d
5338 011 01110 10 1 m 000011 n d UQADD Vd.4s, Vn.4s, Vm.4s
5339 011 01110 01 1 m 000011 n d UQADD Vd.8h, Vn.8h, Vm.8h
5340 011 01110 00 1 m 000011 n d UQADD Vd.16b, Vn.16b, Vm.16b
5341
5342 010 01110 11 1 m 001011 n d SQSUB Vd.2d, Vn.2d, Vm.2d
5343 010 01110 10 1 m 001011 n d SQSUB Vd.4s, Vn.4s, Vm.4s
5344 010 01110 01 1 m 001011 n d SQSUB Vd.8h, Vn.8h, Vm.8h
5345 010 01110 00 1 m 001011 n d SQSUB Vd.16b, Vn.16b, Vm.16b
5346
5347 011 01110 11 1 m 001011 n d UQSUB Vd.2d, Vn.2d, Vm.2d
5348 011 01110 10 1 m 001011 n d UQSUB Vd.4s, Vn.4s, Vm.4s
5349 011 01110 01 1 m 001011 n d UQSUB Vd.8h, Vn.8h, Vm.8h
5350 011 01110 00 1 m 001011 n d UQSUB Vd.16b, Vn.16b, Vm.16b
sewardj51d012a2014-07-21 09:19:50 +00005351
5352 000 01110 10 1 m 110100 n d SQDMULL Vd.2d, Vn.2s, Vm.2s
5353 000 01110 01 1 m 110100 n d SQDMULL Vd.4s, Vn.4h, Vm.4h
sewardj54ffa1d2014-07-22 09:27:49 +00005354
5355 010 01110 10 1 m 101101 n d SQDMULH Vd.4s, Vn.4s, Vm.4s
5356 010 01110 01 1 m 101101 n d SQDMULH Vd.8h, Vn.8h, Vm.8h
5357 011 01110 10 1 m 101101 n d SQRDMULH Vd.4s, Vn.4s, Vm.4s
5358 011 01110 10 1 m 101101 n d SQRDMULH Vd.8h, Vn.8h, Vm.8h
sewardj12972182014-08-04 08:09:47 +00005359
5360 010 01110 sz 1 m 010011 n d SQSHL@sz Vd, Vn, Vm
5361 010 01110 sz 1 m 010111 n d SQRSHL@sz Vd, Vn, Vm
5362 011 01110 sz 1 m 010011 n d UQSHL@sz Vd, Vn, Vm
5363 011 01110 sz 1 m 010111 n d URQSHL@sz Vd, Vn, Vm
sewardj606c4ba2014-01-26 19:11:14 +00005364 */
5365 UInt vD = qregNo(i->ARM64in.VBinV.dst);
5366 UInt vN = qregNo(i->ARM64in.VBinV.argL);
5367 UInt vM = qregNo(i->ARM64in.VBinV.argR);
5368 switch (i->ARM64in.VBinV.op) {
5369 case ARM64vecb_ADD64x2:
5370 *p++ = X_3_8_5_6_5_5(X010, X01110111, vM, X100001, vN, vD);
5371 break;
sewardjf5b08912014-02-06 12:57:58 +00005372 case ARM64vecb_ADD32x4:
5373 *p++ = X_3_8_5_6_5_5(X010, X01110101, vM, X100001, vN, vD);
5374 break;
5375 case ARM64vecb_ADD16x8:
5376 *p++ = X_3_8_5_6_5_5(X010, X01110011, vM, X100001, vN, vD);
5377 break;
sewardj92d0ae32014-04-03 13:48:54 +00005378 case ARM64vecb_ADD8x16:
5379 *p++ = X_3_8_5_6_5_5(X010, X01110001, vM, X100001, vN, vD);
5380 break;
sewardj606c4ba2014-01-26 19:11:14 +00005381 case ARM64vecb_SUB64x2:
5382 *p++ = X_3_8_5_6_5_5(X011, X01110111, vM, X100001, vN, vD);
5383 break;
5384 case ARM64vecb_SUB32x4:
5385 *p++ = X_3_8_5_6_5_5(X011, X01110101, vM, X100001, vN, vD);
5386 break;
5387 case ARM64vecb_SUB16x8:
5388 *p++ = X_3_8_5_6_5_5(X011, X01110011, vM, X100001, vN, vD);
5389 break;
sewardj92d0ae32014-04-03 13:48:54 +00005390 case ARM64vecb_SUB8x16:
5391 *p++ = X_3_8_5_6_5_5(X011, X01110001, vM, X100001, vN, vD);
5392 break;
sewardjf5b08912014-02-06 12:57:58 +00005393 case ARM64vecb_MUL32x4:
5394 *p++ = X_3_8_5_6_5_5(X010, X01110101, vM, X100111, vN, vD);
5395 break;
5396 case ARM64vecb_MUL16x8:
5397 *p++ = X_3_8_5_6_5_5(X010, X01110011, vM, X100111, vN, vD);
5398 break;
sewardj93013432014-04-27 12:02:12 +00005399 case ARM64vecb_MUL8x16:
5400 *p++ = X_3_8_5_6_5_5(X010, X01110001, vM, X100111, vN, vD);
5401 break;
sewardj606c4ba2014-01-26 19:11:14 +00005402 case ARM64vecb_FADD64x2:
5403 *p++ = X_3_8_5_6_5_5(X010, X01110011, vM, X110101, vN, vD);
5404 break;
sewardjecde6972014-02-05 11:01:19 +00005405 case ARM64vecb_FADD32x4:
5406 *p++ = X_3_8_5_6_5_5(X010, X01110001, vM, X110101, vN, vD);
5407 break;
sewardj606c4ba2014-01-26 19:11:14 +00005408 case ARM64vecb_FSUB64x2:
5409 *p++ = X_3_8_5_6_5_5(X010, X01110111, vM, X110101, vN, vD);
5410 break;
sewardjecde6972014-02-05 11:01:19 +00005411 case ARM64vecb_FSUB32x4:
5412 *p++ = X_3_8_5_6_5_5(X010, X01110101, vM, X110101, vN, vD);
5413 break;
sewardj606c4ba2014-01-26 19:11:14 +00005414 case ARM64vecb_FMUL64x2:
5415 *p++ = X_3_8_5_6_5_5(X011, X01110011, vM, X110111, vN, vD);
5416 break;
sewardjecde6972014-02-05 11:01:19 +00005417 case ARM64vecb_FMUL32x4:
5418 *p++ = X_3_8_5_6_5_5(X011, X01110001, vM, X110111, vN, vD);
5419 break;
sewardj606c4ba2014-01-26 19:11:14 +00005420 case ARM64vecb_FDIV64x2:
5421 *p++ = X_3_8_5_6_5_5(X011, X01110011, vM, X111111, vN, vD);
5422 break;
sewardjecde6972014-02-05 11:01:19 +00005423 case ARM64vecb_FDIV32x4:
5424 *p++ = X_3_8_5_6_5_5(X011, X01110001, vM, X111111, vN, vD);
5425 break;
sewardjf5b08912014-02-06 12:57:58 +00005426
sewardjecde6972014-02-05 11:01:19 +00005427 case ARM64vecb_UMAX32x4:
5428 *p++ = X_3_8_5_6_5_5(X011, X01110101, vM, X011001, vN, vD);
5429 break;
5430 case ARM64vecb_UMAX16x8:
5431 *p++ = X_3_8_5_6_5_5(X011, X01110011, vM, X011001, vN, vD);
5432 break;
sewardjfab09142014-02-10 10:28:13 +00005433 case ARM64vecb_UMAX8x16:
5434 *p++ = X_3_8_5_6_5_5(X011, X01110001, vM, X011001, vN, vD);
5435 break;
5436
sewardjecde6972014-02-05 11:01:19 +00005437 case ARM64vecb_UMIN32x4:
5438 *p++ = X_3_8_5_6_5_5(X011, X01110101, vM, X011011, vN, vD);
5439 break;
5440 case ARM64vecb_UMIN16x8:
5441 *p++ = X_3_8_5_6_5_5(X011, X01110011, vM, X011011, vN, vD);
5442 break;
sewardjfab09142014-02-10 10:28:13 +00005443 case ARM64vecb_UMIN8x16:
5444 *p++ = X_3_8_5_6_5_5(X011, X01110001, vM, X011011, vN, vD);
5445 break;
sewardjf5b08912014-02-06 12:57:58 +00005446
5447 case ARM64vecb_SMAX32x4:
5448 *p++ = X_3_8_5_6_5_5(X010, X01110101, vM, X011001, vN, vD);
5449 break;
5450 case ARM64vecb_SMAX16x8:
5451 *p++ = X_3_8_5_6_5_5(X010, X01110011, vM, X011001, vN, vD);
5452 break;
sewardj9b1cf5e2014-03-01 11:16:57 +00005453 case ARM64vecb_SMAX8x16:
5454 *p++ = X_3_8_5_6_5_5(X010, X01110001, vM, X011001, vN, vD);
5455 break;
sewardjfab09142014-02-10 10:28:13 +00005456
sewardjf5b08912014-02-06 12:57:58 +00005457 case ARM64vecb_SMIN32x4:
5458 *p++ = X_3_8_5_6_5_5(X010, X01110101, vM, X011011, vN, vD);
5459 break;
5460 case ARM64vecb_SMIN16x8:
5461 *p++ = X_3_8_5_6_5_5(X010, X01110011, vM, X011011, vN, vD);
5462 break;
sewardj9b1cf5e2014-03-01 11:16:57 +00005463 case ARM64vecb_SMIN8x16:
5464 *p++ = X_3_8_5_6_5_5(X010, X01110001, vM, X011011, vN, vD);
5465 break;
sewardjf5b08912014-02-06 12:57:58 +00005466
sewardjecde6972014-02-05 11:01:19 +00005467 case ARM64vecb_AND:
5468 *p++ = X_3_8_5_6_5_5(X010, X01110001, vM, X000111, vN, vD);
5469 break;
sewardje520bb32014-02-17 11:00:53 +00005470 case ARM64vecb_ORR:
5471 *p++ = X_3_8_5_6_5_5(X010, X01110101, vM, X000111, vN, vD);
5472 break;
5473 case ARM64vecb_XOR:
5474 *p++ = X_3_8_5_6_5_5(X011, X01110001, vM, X000111, vN, vD);
5475 break;
5476
5477 case ARM64vecb_CMEQ64x2:
5478 *p++ = X_3_8_5_6_5_5(X011, X01110111, vM, X100011, vN, vD);
5479 break;
sewardj505a27d2014-03-10 10:40:48 +00005480 case ARM64vecb_CMEQ32x4:
5481 *p++ = X_3_8_5_6_5_5(X011, X01110101, vM, X100011, vN, vD);
5482 break;
5483 case ARM64vecb_CMEQ16x8:
5484 *p++ = X_3_8_5_6_5_5(X011, X01110011, vM, X100011, vN, vD);
5485 break;
5486 case ARM64vecb_CMEQ8x16:
5487 *p++ = X_3_8_5_6_5_5(X011, X01110001, vM, X100011, vN, vD);
5488 break;
sewardje520bb32014-02-17 11:00:53 +00005489
sewardj93013432014-04-27 12:02:12 +00005490 case ARM64vecb_CMHI64x2:
5491 *p++ = X_3_8_5_6_5_5(X011, X01110111, vM, X001101, vN, vD);
5492 break;
5493 case ARM64vecb_CMHI32x4:
5494 *p++ = X_3_8_5_6_5_5(X011, X01110101, vM, X001101, vN, vD);
5495 break;
5496 case ARM64vecb_CMHI16x8:
5497 *p++ = X_3_8_5_6_5_5(X011, X01110011, vM, X001101, vN, vD);
5498 break;
5499 case ARM64vecb_CMHI8x16:
5500 *p++ = X_3_8_5_6_5_5(X011, X01110001, vM, X001101, vN, vD);
5501 break;
5502
5503 case ARM64vecb_CMGT64x2:
5504 *p++ = X_3_8_5_6_5_5(X010, X01110111, vM, X001101, vN, vD);
5505 break;
5506 case ARM64vecb_CMGT32x4:
5507 *p++ = X_3_8_5_6_5_5(X010, X01110101, vM, X001101, vN, vD);
5508 break;
5509 case ARM64vecb_CMGT16x8:
5510 *p++ = X_3_8_5_6_5_5(X010, X01110011, vM, X001101, vN, vD);
5511 break;
5512 case ARM64vecb_CMGT8x16:
5513 *p++ = X_3_8_5_6_5_5(X010, X01110001, vM, X001101, vN, vD);
5514 break;
5515
sewardj2bd1ffe2014-03-27 18:59:00 +00005516 case ARM64vecb_FCMEQ64x2:
5517 *p++ = X_3_8_5_6_5_5(X010, X01110011, vM, X111001, vN, vD);
5518 break;
5519 case ARM64vecb_FCMEQ32x4:
5520 *p++ = X_3_8_5_6_5_5(X010, X01110001, vM, X111001, vN, vD);
5521 break;
5522
5523 case ARM64vecb_FCMGE64x2:
5524 *p++ = X_3_8_5_6_5_5(X011, X01110011, vM, X111001, vN, vD);
5525 break;
5526 case ARM64vecb_FCMGE32x4:
5527 *p++ = X_3_8_5_6_5_5(X011, X01110001, vM, X111001, vN, vD);
5528 break;
5529
5530 case ARM64vecb_FCMGT64x2:
5531 *p++ = X_3_8_5_6_5_5(X011, X01110111, vM, X111001, vN, vD);
5532 break;
5533 case ARM64vecb_FCMGT32x4:
5534 *p++ = X_3_8_5_6_5_5(X011, X01110101, vM, X111001, vN, vD);
5535 break;
sewardj92d0ae32014-04-03 13:48:54 +00005536
5537 case ARM64vecb_TBL1:
sewardjd96daf62014-06-15 08:17:35 +00005538 *p++ = X_3_8_5_6_5_5(X010, X01110000, vM, X000000, vN, vD);
5539 break;
5540
5541 case ARM64vecb_UZP164x2:
5542 *p++ = X_3_8_5_6_5_5(X010, X01110110, vM, X000110, vN, vD);
5543 break;
5544 case ARM64vecb_UZP132x4:
5545 *p++ = X_3_8_5_6_5_5(X010, X01110100, vM, X000110, vN, vD);
5546 break;
5547 case ARM64vecb_UZP116x8:
5548 *p++ = X_3_8_5_6_5_5(X010, X01110010, vM, X000110, vN, vD);
5549 break;
5550 case ARM64vecb_UZP18x16:
5551 *p++ = X_3_8_5_6_5_5(X010, X01110000, vM, X000110, vN, vD);
5552 break;
5553
5554 case ARM64vecb_UZP264x2:
5555 *p++ = X_3_8_5_6_5_5(X010, X01110110, vM, X010110, vN, vD);
5556 break;
5557 case ARM64vecb_UZP232x4:
5558 *p++ = X_3_8_5_6_5_5(X010, X01110100, vM, X010110, vN, vD);
5559 break;
5560 case ARM64vecb_UZP216x8:
5561 *p++ = X_3_8_5_6_5_5(X010, X01110010, vM, X010110, vN, vD);
5562 break;
5563 case ARM64vecb_UZP28x16:
5564 *p++ = X_3_8_5_6_5_5(X010, X01110000, vM, X010110, vN, vD);
5565 break;
5566
5567 case ARM64vecb_ZIP132x4:
5568 *p++ = X_3_8_5_6_5_5(X010, X01110100, vM, X001110, vN, vD);
5569 break;
5570 case ARM64vecb_ZIP116x8:
5571 *p++ = X_3_8_5_6_5_5(X010, X01110010, vM, X001110, vN, vD);
5572 break;
5573 case ARM64vecb_ZIP18x16:
5574 *p++ = X_3_8_5_6_5_5(X010, X01110000, vM, X001110, vN, vD);
5575 break;
5576
5577 case ARM64vecb_ZIP232x4:
5578 *p++ = X_3_8_5_6_5_5(X010, X01110100, vM, X011110, vN, vD);
5579 break;
5580 case ARM64vecb_ZIP216x8:
5581 *p++ = X_3_8_5_6_5_5(X010, X01110010, vM, X011110, vN, vD);
5582 break;
5583 case ARM64vecb_ZIP28x16:
5584 *p++ = X_3_8_5_6_5_5(X010, X01110000, vM, X011110, vN, vD);
sewardj92d0ae32014-04-03 13:48:54 +00005585 break;
5586
sewardj168c8bd2014-06-25 13:05:23 +00005587 case ARM64vecb_PMUL8x16:
5588 *p++ = X_3_8_5_6_5_5(X011, X01110001, vM, X100111, vN, vD);
5589 break;
5590
sewardj31b5a952014-06-26 07:41:14 +00005591 case ARM64vecb_PMULL8x8:
5592 *p++ = X_3_8_5_6_5_5(X000, X01110001, vM, X111000, vN, vD);
5593 break;
5594
sewardj6f312d02014-06-28 12:21:37 +00005595 case ARM64vecb_UMULL2DSS:
5596 *p++ = X_3_8_5_6_5_5(X001, X01110101, vM, X110000, vN, vD);
5597 break;
5598 case ARM64vecb_UMULL4SHH:
5599 *p++ = X_3_8_5_6_5_5(X001, X01110011, vM, X110000, vN, vD);
5600 break;
5601 case ARM64vecb_UMULL8HBB:
5602 *p++ = X_3_8_5_6_5_5(X001, X01110001, vM, X110000, vN, vD);
5603 break;
5604
5605 case ARM64vecb_SMULL2DSS:
5606 *p++ = X_3_8_5_6_5_5(X000, X01110101, vM, X110000, vN, vD);
5607 break;
5608 case ARM64vecb_SMULL4SHH:
5609 *p++ = X_3_8_5_6_5_5(X000, X01110011, vM, X110000, vN, vD);
5610 break;
5611 case ARM64vecb_SMULL8HBB:
5612 *p++ = X_3_8_5_6_5_5(X000, X01110001, vM, X110000, vN, vD);
5613 break;
5614
sewardja5a6b752014-06-30 07:33:56 +00005615 case ARM64vecb_SQADD64x2:
5616 *p++ = X_3_8_5_6_5_5(X010, X01110111, vM, X000011, vN, vD);
5617 break;
5618 case ARM64vecb_SQADD32x4:
5619 *p++ = X_3_8_5_6_5_5(X010, X01110101, vM, X000011, vN, vD);
5620 break;
5621 case ARM64vecb_SQADD16x8:
5622 *p++ = X_3_8_5_6_5_5(X010, X01110011, vM, X000011, vN, vD);
5623 break;
5624 case ARM64vecb_SQADD8x16:
5625 *p++ = X_3_8_5_6_5_5(X010, X01110001, vM, X000011, vN, vD);
5626 break;
5627
5628 case ARM64vecb_UQADD64x2:
5629 *p++ = X_3_8_5_6_5_5(X011, X01110111, vM, X000011, vN, vD);
5630 break;
5631 case ARM64vecb_UQADD32x4:
5632 *p++ = X_3_8_5_6_5_5(X011, X01110101, vM, X000011, vN, vD);
5633 break;
5634 case ARM64vecb_UQADD16x8:
5635 *p++ = X_3_8_5_6_5_5(X011, X01110011, vM, X000011, vN, vD);
5636 break;
5637 case ARM64vecb_UQADD8x16:
5638 *p++ = X_3_8_5_6_5_5(X011, X01110001, vM, X000011, vN, vD);
5639 break;
5640
5641 case ARM64vecb_SQSUB64x2:
5642 *p++ = X_3_8_5_6_5_5(X010, X01110111, vM, X001011, vN, vD);
5643 break;
5644 case ARM64vecb_SQSUB32x4:
5645 *p++ = X_3_8_5_6_5_5(X010, X01110101, vM, X001011, vN, vD);
5646 break;
5647 case ARM64vecb_SQSUB16x8:
5648 *p++ = X_3_8_5_6_5_5(X010, X01110011, vM, X001011, vN, vD);
5649 break;
5650 case ARM64vecb_SQSUB8x16:
5651 *p++ = X_3_8_5_6_5_5(X010, X01110001, vM, X001011, vN, vD);
5652 break;
5653
5654 case ARM64vecb_UQSUB64x2:
5655 *p++ = X_3_8_5_6_5_5(X011, X01110111, vM, X001011, vN, vD);
5656 break;
5657 case ARM64vecb_UQSUB32x4:
5658 *p++ = X_3_8_5_6_5_5(X011, X01110101, vM, X001011, vN, vD);
5659 break;
5660 case ARM64vecb_UQSUB16x8:
5661 *p++ = X_3_8_5_6_5_5(X011, X01110011, vM, X001011, vN, vD);
5662 break;
5663 case ARM64vecb_UQSUB8x16:
5664 *p++ = X_3_8_5_6_5_5(X011, X01110001, vM, X001011, vN, vD);
5665 break;
5666
sewardj51d012a2014-07-21 09:19:50 +00005667 case ARM64vecb_SQDMULL2DSS:
5668 *p++ = X_3_8_5_6_5_5(X000, X01110101, vM, X110100, vN, vD);
5669 break;
5670 case ARM64vecb_SQDMULL4SHH:
5671 *p++ = X_3_8_5_6_5_5(X000, X01110011, vM, X110100, vN, vD);
5672 break;
5673
sewardj54ffa1d2014-07-22 09:27:49 +00005674 case ARM64vecb_SQDMULH32x4:
5675 *p++ = X_3_8_5_6_5_5(X010, X01110101, vM, X101101, vN, vD);
5676 break;
5677 case ARM64vecb_SQDMULH16x8:
5678 *p++ = X_3_8_5_6_5_5(X010, X01110011, vM, X101101, vN, vD);
5679 break;
5680 case ARM64vecb_SQRDMULH32x4:
5681 *p++ = X_3_8_5_6_5_5(X011, X01110101, vM, X101101, vN, vD);
5682 break;
5683 case ARM64vecb_SQRDMULH16x8:
5684 *p++ = X_3_8_5_6_5_5(X011, X01110011, vM, X101101, vN, vD);
5685 break;
5686
sewardj12972182014-08-04 08:09:47 +00005687 case ARM64vecb_SQSHL64x2:
5688 *p++ = X_3_8_5_6_5_5(X010, X01110111, vM, X010011, vN, vD);
5689 break;
5690 case ARM64vecb_SQSHL32x4:
5691 *p++ = X_3_8_5_6_5_5(X010, X01110101, vM, X010011, vN, vD);
5692 break;
5693 case ARM64vecb_SQSHL16x8:
5694 *p++ = X_3_8_5_6_5_5(X010, X01110011, vM, X010011, vN, vD);
5695 break;
5696 case ARM64vecb_SQSHL8x16:
5697 *p++ = X_3_8_5_6_5_5(X010, X01110001, vM, X010011, vN, vD);
5698 break;
5699
5700 case ARM64vecb_SQRSHL64x2:
5701 *p++ = X_3_8_5_6_5_5(X010, X01110111, vM, X010111, vN, vD);
5702 break;
5703 case ARM64vecb_SQRSHL32x4:
5704 *p++ = X_3_8_5_6_5_5(X010, X01110101, vM, X010111, vN, vD);
5705 break;
5706 case ARM64vecb_SQRSHL16x8:
5707 *p++ = X_3_8_5_6_5_5(X010, X01110011, vM, X010111, vN, vD);
5708 break;
5709 case ARM64vecb_SQRSHL8x16:
5710 *p++ = X_3_8_5_6_5_5(X010, X01110001, vM, X010111, vN, vD);
5711 break;
5712
5713 case ARM64vecb_UQSHL64x2:
5714 *p++ = X_3_8_5_6_5_5(X011, X01110111, vM, X010011, vN, vD);
5715 break;
5716 case ARM64vecb_UQSHL32x4:
5717 *p++ = X_3_8_5_6_5_5(X011, X01110101, vM, X010011, vN, vD);
5718 break;
5719 case ARM64vecb_UQSHL16x8:
5720 *p++ = X_3_8_5_6_5_5(X011, X01110011, vM, X010011, vN, vD);
5721 break;
5722 case ARM64vecb_UQSHL8x16:
5723 *p++ = X_3_8_5_6_5_5(X011, X01110001, vM, X010011, vN, vD);
5724 break;
5725
5726 case ARM64vecb_UQRSHL64x2:
5727 *p++ = X_3_8_5_6_5_5(X011, X01110111, vM, X010111, vN, vD);
5728 break;
5729 case ARM64vecb_UQRSHL32x4:
5730 *p++ = X_3_8_5_6_5_5(X011, X01110101, vM, X010111, vN, vD);
5731 break;
5732 case ARM64vecb_UQRSHL16x8:
5733 *p++ = X_3_8_5_6_5_5(X011, X01110011, vM, X010111, vN, vD);
5734 break;
5735 case ARM64vecb_UQRSHL8x16:
5736 *p++ = X_3_8_5_6_5_5(X011, X01110001, vM, X010111, vN, vD);
5737 break;
5738
sewardj606c4ba2014-01-26 19:11:14 +00005739 default:
5740 goto bad;
5741 }
5742 goto done;
5743 }
sewardjfab09142014-02-10 10:28:13 +00005744 case ARM64in_VUnaryV: {
5745 /* 31 23 20 15 9 4
sewardje520bb32014-02-17 11:00:53 +00005746 010 01110 11 1 00000 111110 n d FABS Vd.2d, Vn.2d
5747 010 01110 10 1 00000 111110 n d FABS Vd.4s, Vn.4s
5748 011 01110 11 1 00000 111110 n d FNEG Vd.2d, Vn.2d
5749 011 01110 10 1 00000 111110 n d FNEG Vd.4s, Vn.4s
5750 011 01110 00 1 00000 010110 n d NOT Vd.16b, Vn.16b
sewardj25523c42014-06-15 19:36:29 +00005751
5752 010 01110 11 1 00000 101110 n d ABS Vd.2d, Vn.2d
5753 010 01110 10 1 00000 101110 n d ABS Vd.4s, Vn.4s
5754 010 01110 01 1 00000 101110 n d ABS Vd.8h, Vn.8h
5755 010 01110 00 1 00000 101110 n d ABS Vd.16b, Vn.16b
sewardj2b6fd5e2014-06-19 14:21:37 +00005756
5757 010 01110 10 1 00000 010010 n d CLS Vd.4s, Vn.4s
5758 010 01110 01 1 00000 010010 n d CLS Vd.8h, Vn.8h
5759 010 01110 00 1 00000 010010 n d CLS Vd.16b, Vn.16b
5760
5761 011 01110 10 1 00000 010010 n d CLZ Vd.4s, Vn.4s
5762 011 01110 01 1 00000 010010 n d CLZ Vd.8h, Vn.8h
5763 011 01110 00 1 00000 010010 n d CLZ Vd.16b, Vn.16b
5764
5765 010 01110 00 1 00000 010110 n d CNT Vd.16b, Vn.16b
sewardj715d1622014-06-26 12:39:05 +00005766
5767 011 01110 01 1 00000 010110 n d RBIT Vd.16b, Vn.16b
sewardj715d1622014-06-26 12:39:05 +00005768 010 01110 00 1 00000 000110 n d REV16 Vd.16b, Vn.16b
sewardjdf9d6d52014-06-27 10:43:22 +00005769 011 01110 00 1 00000 000010 n d REV32 Vd.16b, Vn.16b
5770 011 01110 01 1 00000 000010 n d REV32 Vd.8h, Vn.8h
5771
5772 010 01110 00 1 00000 000010 n d REV64 Vd.16b, Vn.16b
5773 010 01110 01 1 00000 000010 n d REV64 Vd.8h, Vn.8h
5774 010 01110 10 1 00000 000010 n d REV64 Vd.4s, Vn.4s
sewardjfab09142014-02-10 10:28:13 +00005775 */
5776 UInt vD = qregNo(i->ARM64in.VUnaryV.dst);
5777 UInt vN = qregNo(i->ARM64in.VUnaryV.arg);
5778 switch (i->ARM64in.VUnaryV.op) {
sewardje520bb32014-02-17 11:00:53 +00005779 case ARM64vecu_FABS64x2:
5780 *p++ = X_3_8_5_6_5_5(X010, X01110111, X00000, X111110, vN, vD);
5781 break;
sewardj2bd1ffe2014-03-27 18:59:00 +00005782 case ARM64vecu_FABS32x4:
5783 *p++ = X_3_8_5_6_5_5(X010, X01110101, X00000, X111110, vN, vD);
5784 break;
sewardjfab09142014-02-10 10:28:13 +00005785 case ARM64vecu_FNEG64x2:
5786 *p++ = X_3_8_5_6_5_5(X011, X01110111, X00000, X111110, vN, vD);
5787 break;
sewardj950ca7a2014-04-03 23:03:32 +00005788 case ARM64vecu_FNEG32x4:
5789 *p++ = X_3_8_5_6_5_5(X011, X01110101, X00000, X111110, vN, vD);
5790 break;
sewardje520bb32014-02-17 11:00:53 +00005791 case ARM64vecu_NOT:
5792 *p++ = X_3_8_5_6_5_5(X011, X01110001, X00000, X010110, vN, vD);
5793 break;
sewardj25523c42014-06-15 19:36:29 +00005794 case ARM64vecu_ABS64x2:
5795 *p++ = X_3_8_5_6_5_5(X010, X01110111, X00000, X101110, vN, vD);
5796 break;
5797 case ARM64vecu_ABS32x4:
5798 *p++ = X_3_8_5_6_5_5(X010, X01110101, X00000, X101110, vN, vD);
5799 break;
5800 case ARM64vecu_ABS16x8:
5801 *p++ = X_3_8_5_6_5_5(X010, X01110011, X00000, X101110, vN, vD);
5802 break;
5803 case ARM64vecu_ABS8x16:
5804 *p++ = X_3_8_5_6_5_5(X010, X01110001, X00000, X101110, vN, vD);
5805 break;
sewardj2b6fd5e2014-06-19 14:21:37 +00005806 case ARM64vecu_CLS32x4:
5807 *p++ = X_3_8_5_6_5_5(X010, X01110101, X00000, X010010, vN, vD);
5808 break;
5809 case ARM64vecu_CLS16x8:
5810 *p++ = X_3_8_5_6_5_5(X010, X01110011, X00000, X010010, vN, vD);
5811 break;
5812 case ARM64vecu_CLS8x16:
5813 *p++ = X_3_8_5_6_5_5(X010, X01110001, X00000, X010010, vN, vD);
5814 break;
5815 case ARM64vecu_CLZ32x4:
5816 *p++ = X_3_8_5_6_5_5(X011, X01110101, X00000, X010010, vN, vD);
5817 break;
5818 case ARM64vecu_CLZ16x8:
5819 *p++ = X_3_8_5_6_5_5(X011, X01110011, X00000, X010010, vN, vD);
5820 break;
5821 case ARM64vecu_CLZ8x16:
5822 *p++ = X_3_8_5_6_5_5(X011, X01110001, X00000, X010010, vN, vD);
5823 break;
5824 case ARM64vecu_CNT8x16:
5825 *p++ = X_3_8_5_6_5_5(X010, X01110001, X00000, X010110, vN, vD);
5826 break;
sewardj715d1622014-06-26 12:39:05 +00005827 case ARM64vecu_RBIT:
5828 *p++ = X_3_8_5_6_5_5(X011, X01110011, X00000, X010110, vN, vD);
5829 break;
5830 case ARM64vecu_REV1616B:
5831 *p++ = X_3_8_5_6_5_5(X010, X01110001, X00000, X000110, vN, vD);
5832 break;
sewardjdf9d6d52014-06-27 10:43:22 +00005833 case ARM64vecu_REV3216B:
5834 *p++ = X_3_8_5_6_5_5(X011, X01110001, X00000, X000010, vN, vD);
5835 break;
5836 case ARM64vecu_REV328H:
5837 *p++ = X_3_8_5_6_5_5(X011, X01110011, X00000, X000010, vN, vD);
5838 break;
5839 case ARM64vecu_REV6416B:
5840 *p++ = X_3_8_5_6_5_5(X010, X01110001, X00000, X000010, vN, vD);
5841 break;
5842 case ARM64vecu_REV648H:
5843 *p++ = X_3_8_5_6_5_5(X010, X01110011, X00000, X000010, vN, vD);
5844 break;
5845 case ARM64vecu_REV644S:
5846 *p++ = X_3_8_5_6_5_5(X010, X01110101, X00000, X000010, vN, vD);
5847 break;
sewardjfab09142014-02-10 10:28:13 +00005848 default:
5849 goto bad;
5850 }
5851 goto done;
5852 }
sewardj606c4ba2014-01-26 19:11:14 +00005853 case ARM64in_VNarrowV: {
5854 /* 31 23 21 15 9 4
5855 000 01110 00 1,00001 001010 n d XTN Vd.8b, Vn.8h
5856 000 01110 01 1,00001 001010 n d XTN Vd.4h, Vn.4s
5857 000 01110 10 1,00001 001010 n d XTN Vd.2s, Vn.2d
sewardjecedd982014-08-11 14:02:47 +00005858
5859 001 01110 00 1,00001 001010 n d SQXTUN Vd.8b, Vn.8h
5860 001 01110 01 1,00001 001010 n d SQXTUN Vd.4h, Vn.4s
5861 001 01110 10 1,00001 001010 n d SQXTUN Vd.2s, Vn.2d
5862
5863 000 01110 00 1,00001 010010 n d SQXTN Vd.8b, Vn.8h
5864 000 01110 01 1,00001 010010 n d SQXTN Vd.4h, Vn.4s
5865 000 01110 10 1,00001 010010 n d SQXTN Vd.2s, Vn.2d
5866
5867 001 01110 00 1,00001 010010 n d UQXTN Vd.8b, Vn.8h
5868 001 01110 01 1,00001 010010 n d UQXTN Vd.4h, Vn.4s
5869 001 01110 10 1,00001 010010 n d UQXTN Vd.2s, Vn.2d
sewardj606c4ba2014-01-26 19:11:14 +00005870 */
5871 UInt vD = qregNo(i->ARM64in.VNarrowV.dst);
5872 UInt vN = qregNo(i->ARM64in.VNarrowV.src);
5873 UInt dszBlg2 = i->ARM64in.VNarrowV.dszBlg2;
5874 vassert(dszBlg2 >= 0 && dszBlg2 <= 2);
sewardjecedd982014-08-11 14:02:47 +00005875 switch (i->ARM64in.VNarrowV.op) {
5876 case ARM64vecna_XTN:
5877 *p++ = X_3_8_5_6_5_5(X000, X01110001 | (dszBlg2 << 1),
5878 X00001, X001010, vN, vD);
5879 goto done;
5880 case ARM64vecna_SQXTUN:
5881 *p++ = X_3_8_5_6_5_5(X001, X01110001 | (dszBlg2 << 1),
5882 X00001, X001010, vN, vD);
5883 goto done;
5884 case ARM64vecna_SQXTN:
5885 *p++ = X_3_8_5_6_5_5(X000, X01110001 | (dszBlg2 << 1),
5886 X00001, X010010, vN, vD);
5887 goto done;
5888 case ARM64vecna_UQXTN:
5889 *p++ = X_3_8_5_6_5_5(X001, X01110001 | (dszBlg2 << 1),
5890 X00001, X010010, vN, vD);
5891 goto done;
5892 default:
5893 break;
5894 }
5895 goto bad;
sewardj606c4ba2014-01-26 19:11:14 +00005896 }
sewardje520bb32014-02-17 11:00:53 +00005897 case ARM64in_VShiftImmV: {
5898 /*
sewardjecedd982014-08-11 14:02:47 +00005899 011 011110 immh immb 000001 n d USHR Vd.T, Vn.T, #sh
5900 010 011110 immh immb 000001 n d SSHR Vd.T, Vn.T, #sh
5901
5902 001 011110 immh immb 100101 n d UQSHRN ,,#sh
5903 000 011110 immh immb 100101 n d SQSHRN ,,#sh
5904 001 011110 immh immb 100001 n d SQSHRUN ,,#sh
5905
5906 001 011110 immh immb 100111 n d UQRSHRN ,,#sh
5907 000 011110 immh immb 100111 n d SQRSHRN ,,#sh
5908 001 011110 immh immb 100011 n d SQRSHRUN ,,#sh
sewardja97dddf2014-08-14 22:26:52 +00005909
sewardje520bb32014-02-17 11:00:53 +00005910 where immh:immb
5911 = case T of
sewardjecedd982014-08-11 14:02:47 +00005912 2d | sh in 1..64 -> let xxxxxx = 64-sh in 1xxx:xxx
5913 4s | sh in 1..32 -> let xxxxx = 32-sh in 01xx:xxx
5914 8h | sh in 1..16 -> let xxxx = 16-sh in 001x:xxx
5915 16b | sh in 1..8 -> let xxx = 8-sh in 0001:xxx
sewardj32d86752014-03-02 12:47:18 +00005916
sewardja97dddf2014-08-14 22:26:52 +00005917 010 011110 immh immb 010101 n d SHL Vd.T, Vn.T, #sh
5918
5919 011 011110 immh immb 011101 n d UQSHL Vd.T, Vn.T, #sh
5920 010 011110 immh immb 011101 n d SQSHL Vd.T, Vn.T, #sh
5921 011 011110 immh immb 011001 n d SQSHLU Vd.T, Vn.T, #sh
5922
sewardj32d86752014-03-02 12:47:18 +00005923 where immh:immb
5924 = case T of
sewardjecedd982014-08-11 14:02:47 +00005925 2d | sh in 0..63 -> let xxxxxx = sh in 1xxx:xxx
5926 4s | sh in 0..31 -> let xxxxx = sh in 01xx:xxx
5927 8h | sh in 0..15 -> let xxxx = sh in 001x:xxx
5928 16b | sh in 0..7 -> let xxx = sh in 0001:xxx
sewardje520bb32014-02-17 11:00:53 +00005929 */
sewardjecedd982014-08-11 14:02:47 +00005930 UInt vD = qregNo(i->ARM64in.VShiftImmV.dst);
5931 UInt vN = qregNo(i->ARM64in.VShiftImmV.src);
5932 UInt sh = i->ARM64in.VShiftImmV.amt;
5933 UInt tmpl = 0; /* invalid */
5934
5935 const UInt tmpl_USHR
5936 = X_3_6_7_6_5_5(X011, X011110, 0, X000001, vN, vD);
5937 const UInt tmpl_SSHR
5938 = X_3_6_7_6_5_5(X010, X011110, 0, X000001, vN, vD);
5939
5940 const UInt tmpl_UQSHRN
5941 = X_3_6_7_6_5_5(X001, X011110, 0, X100101, vN, vD);
5942 const UInt tmpl_SQSHRN
5943 = X_3_6_7_6_5_5(X000, X011110, 0, X100101, vN, vD);
5944 const UInt tmpl_SQSHRUN
5945 = X_3_6_7_6_5_5(X001, X011110, 0, X100001, vN, vD);
5946
5947 const UInt tmpl_UQRSHRN
5948 = X_3_6_7_6_5_5(X001, X011110, 0, X100111, vN, vD);
5949 const UInt tmpl_SQRSHRN
5950 = X_3_6_7_6_5_5(X000, X011110, 0, X100111, vN, vD);
5951 const UInt tmpl_SQRSHRUN
5952 = X_3_6_7_6_5_5(X001, X011110, 0, X100011, vN, vD);
5953
5954 const UInt tmpl_SHL
5955 = X_3_6_7_6_5_5(X010, X011110, 0, X010101, vN, vD);
5956
sewardja97dddf2014-08-14 22:26:52 +00005957 const UInt tmpl_UQSHL
5958 = X_3_6_7_6_5_5(X011, X011110, 0, X011101, vN, vD);
5959 const UInt tmpl_SQSHL
5960 = X_3_6_7_6_5_5(X010, X011110, 0, X011101, vN, vD);
5961 const UInt tmpl_SQSHLU
5962 = X_3_6_7_6_5_5(X011, X011110, 0, X011001, vN, vD);
5963
sewardjecedd982014-08-11 14:02:47 +00005964 switch (i->ARM64in.VShiftImmV.op) {
5965 case ARM64vecsh_SSHR64x2: tmpl = tmpl_SSHR; goto right64x2;
5966 case ARM64vecsh_USHR64x2: tmpl = tmpl_USHR; goto right64x2;
5967 case ARM64vecsh_SHL64x2: tmpl = tmpl_SHL; goto left64x2;
sewardja97dddf2014-08-14 22:26:52 +00005968 case ARM64vecsh_UQSHL64x2: tmpl = tmpl_UQSHL; goto left64x2;
5969 case ARM64vecsh_SQSHL64x2: tmpl = tmpl_SQSHL; goto left64x2;
5970 case ARM64vecsh_SQSHLU64x2: tmpl = tmpl_SQSHLU; goto left64x2;
sewardjecedd982014-08-11 14:02:47 +00005971 case ARM64vecsh_SSHR32x4: tmpl = tmpl_SSHR; goto right32x4;
5972 case ARM64vecsh_USHR32x4: tmpl = tmpl_USHR; goto right32x4;
5973 case ARM64vecsh_UQSHRN2SD: tmpl = tmpl_UQSHRN; goto right32x4;
5974 case ARM64vecsh_SQSHRN2SD: tmpl = tmpl_SQSHRN; goto right32x4;
5975 case ARM64vecsh_SQSHRUN2SD: tmpl = tmpl_SQSHRUN; goto right32x4;
5976 case ARM64vecsh_UQRSHRN2SD: tmpl = tmpl_UQRSHRN; goto right32x4;
5977 case ARM64vecsh_SQRSHRN2SD: tmpl = tmpl_SQRSHRN; goto right32x4;
5978 case ARM64vecsh_SQRSHRUN2SD: tmpl = tmpl_SQRSHRUN; goto right32x4;
5979 case ARM64vecsh_SHL32x4: tmpl = tmpl_SHL; goto left32x4;
sewardja97dddf2014-08-14 22:26:52 +00005980 case ARM64vecsh_UQSHL32x4: tmpl = tmpl_UQSHL; goto left32x4;
5981 case ARM64vecsh_SQSHL32x4: tmpl = tmpl_SQSHL; goto left32x4;
5982 case ARM64vecsh_SQSHLU32x4: tmpl = tmpl_SQSHLU; goto left32x4;
sewardjecedd982014-08-11 14:02:47 +00005983 case ARM64vecsh_SSHR16x8: tmpl = tmpl_SSHR; goto right16x8;
5984 case ARM64vecsh_USHR16x8: tmpl = tmpl_USHR; goto right16x8;
5985 case ARM64vecsh_UQSHRN4HS: tmpl = tmpl_UQSHRN; goto right16x8;
5986 case ARM64vecsh_SQSHRN4HS: tmpl = tmpl_SQSHRN; goto right16x8;
5987 case ARM64vecsh_SQSHRUN4HS: tmpl = tmpl_SQSHRUN; goto right16x8;
5988 case ARM64vecsh_UQRSHRN4HS: tmpl = tmpl_UQRSHRN; goto right16x8;
5989 case ARM64vecsh_SQRSHRN4HS: tmpl = tmpl_SQRSHRN; goto right16x8;
5990 case ARM64vecsh_SQRSHRUN4HS: tmpl = tmpl_SQRSHRUN; goto right16x8;
5991 case ARM64vecsh_SHL16x8: tmpl = tmpl_SHL; goto left16x8;
sewardja97dddf2014-08-14 22:26:52 +00005992 case ARM64vecsh_UQSHL16x8: tmpl = tmpl_UQSHL; goto left16x8;
5993 case ARM64vecsh_SQSHL16x8: tmpl = tmpl_SQSHL; goto left16x8;
5994 case ARM64vecsh_SQSHLU16x8: tmpl = tmpl_SQSHLU; goto left16x8;
sewardjecedd982014-08-11 14:02:47 +00005995 case ARM64vecsh_SSHR8x16: tmpl = tmpl_SSHR; goto right8x16;
5996 case ARM64vecsh_USHR8x16: tmpl = tmpl_USHR; goto right8x16;
5997 case ARM64vecsh_UQSHRN8BH: tmpl = tmpl_UQSHRN; goto right8x16;
5998 case ARM64vecsh_SQSHRN8BH: tmpl = tmpl_SQSHRN; goto right8x16;
5999 case ARM64vecsh_SQSHRUN8BH: tmpl = tmpl_SQSHRUN; goto right8x16;
6000 case ARM64vecsh_UQRSHRN8BH: tmpl = tmpl_UQRSHRN; goto right8x16;
6001 case ARM64vecsh_SQRSHRN8BH: tmpl = tmpl_SQRSHRN; goto right8x16;
6002 case ARM64vecsh_SQRSHRUN8BH: tmpl = tmpl_SQRSHRUN; goto right8x16;
6003 case ARM64vecsh_SHL8x16: tmpl = tmpl_SHL; goto left8x16;
sewardja97dddf2014-08-14 22:26:52 +00006004 case ARM64vecsh_UQSHL8x16: tmpl = tmpl_UQSHL; goto left8x16;
6005 case ARM64vecsh_SQSHL8x16: tmpl = tmpl_SQSHL; goto left8x16;
6006 case ARM64vecsh_SQSHLU8x16: tmpl = tmpl_SQSHLU; goto left8x16;
sewardjecedd982014-08-11 14:02:47 +00006007
6008 default: break;
6009
6010 right64x2:
sewardje520bb32014-02-17 11:00:53 +00006011 if (sh >= 1 && sh <= 63) {
sewardjecedd982014-08-11 14:02:47 +00006012 *p++ = tmpl | X_3_6_7_6_5_5(0,0, X1000000 | (64-sh), 0,0,0);
sewardje520bb32014-02-17 11:00:53 +00006013 goto done;
6014 }
6015 break;
sewardjecedd982014-08-11 14:02:47 +00006016 right32x4:
6017 if (sh >= 1 && sh <= 32) {
6018 *p++ = tmpl | X_3_6_7_6_5_5(0,0, X0100000 | (32-sh), 0,0,0);
6019 goto done;
6020 }
6021 break;
6022 right16x8:
6023 if (sh >= 1 && sh <= 16) {
6024 *p++ = tmpl | X_3_6_7_6_5_5(0,0, X0010000 | (16-sh), 0,0,0);
6025 goto done;
6026 }
6027 break;
6028 right8x16:
6029 if (sh >= 1 && sh <= 8) {
6030 *p++ = tmpl | X_3_6_7_6_5_5(0,0, X0001000 | (8-sh), 0,0,0);
6031 goto done;
6032 }
6033 break;
6034
6035 left64x2:
sewardja97dddf2014-08-14 22:26:52 +00006036 if (sh >= 0 && sh <= 63) {
sewardjecedd982014-08-11 14:02:47 +00006037 *p++ = tmpl | X_3_6_7_6_5_5(0,0, X1000000 | sh, 0,0,0);
sewardj93013432014-04-27 12:02:12 +00006038 goto done;
6039 }
6040 break;
sewardjecedd982014-08-11 14:02:47 +00006041 left32x4:
sewardja97dddf2014-08-14 22:26:52 +00006042 if (sh >= 0 && sh <= 31) {
sewardjecedd982014-08-11 14:02:47 +00006043 *p++ = tmpl | X_3_6_7_6_5_5(0,0, X0100000 | sh, 0,0,0);
sewardj93013432014-04-27 12:02:12 +00006044 goto done;
6045 }
6046 break;
sewardjecedd982014-08-11 14:02:47 +00006047 left16x8:
sewardja97dddf2014-08-14 22:26:52 +00006048 if (sh >= 0 && sh <= 15) {
sewardjecedd982014-08-11 14:02:47 +00006049 *p++ = tmpl | X_3_6_7_6_5_5(0,0, X0010000 | sh, 0,0,0);
sewardj1eaaec22014-03-07 22:52:19 +00006050 goto done;
6051 }
6052 break;
sewardjecedd982014-08-11 14:02:47 +00006053 left8x16:
sewardja97dddf2014-08-14 22:26:52 +00006054 if (sh >= 0 && sh <= 7) {
sewardjecedd982014-08-11 14:02:47 +00006055 *p++ = tmpl | X_3_6_7_6_5_5(0,0, X0001000 | sh, 0,0,0);
sewardj93013432014-04-27 12:02:12 +00006056 goto done;
6057 }
6058 break;
sewardje520bb32014-02-17 11:00:53 +00006059 }
6060 goto bad;
6061 }
sewardjab33a7a2014-06-19 22:20:47 +00006062 case ARM64in_VExtV: {
6063 /*
6064 011 01110 000 m 0 imm4 0 n d EXT Vd.16b, Vn.16b, Vm.16b, #imm4
6065 where imm4 = the shift amount, in bytes,
6066 Vn is low operand, Vm is high operand
6067 */
6068 UInt vD = qregNo(i->ARM64in.VExtV.dst);
6069 UInt vN = qregNo(i->ARM64in.VExtV.srcLo);
6070 UInt vM = qregNo(i->ARM64in.VExtV.srcHi);
6071 UInt imm4 = i->ARM64in.VExtV.amtB;
6072 vassert(imm4 >= 1 && imm4 <= 15);
6073 *p++ = X_3_8_5_6_5_5(X011, X01110000, vM,
6074 X000000 | (imm4 << 1), vN, vD);
6075 goto done;
6076 }
sewardjbbcf1882014-01-12 12:49:10 +00006077//ZZ case ARMin_VAluS: {
6078//ZZ UInt dN = fregNo(i->ARMin.VAluS.argL);
6079//ZZ UInt dD = fregNo(i->ARMin.VAluS.dst);
6080//ZZ UInt dM = fregNo(i->ARMin.VAluS.argR);
6081//ZZ UInt bN = dN & 1;
6082//ZZ UInt bD = dD & 1;
6083//ZZ UInt bM = dM & 1;
6084//ZZ UInt pqrs = X1111; /* undefined */
6085//ZZ switch (i->ARMin.VAluS.op) {
6086//ZZ case ARMvfp_ADD: pqrs = X0110; break;
6087//ZZ case ARMvfp_SUB: pqrs = X0111; break;
6088//ZZ case ARMvfp_MUL: pqrs = X0100; break;
6089//ZZ case ARMvfp_DIV: pqrs = X1000; break;
6090//ZZ default: goto bad;
6091//ZZ }
6092//ZZ vassert(pqrs != X1111);
6093//ZZ UInt bP = (pqrs >> 3) & 1;
6094//ZZ UInt bQ = (pqrs >> 2) & 1;
6095//ZZ UInt bR = (pqrs >> 1) & 1;
6096//ZZ UInt bS = (pqrs >> 0) & 1;
6097//ZZ UInt insn = XXXXXXXX(0xE, X1110, BITS4(bP,bD,bQ,bR),
6098//ZZ (dN >> 1), (dD >> 1),
6099//ZZ X1010, BITS4(bN,bS,bM,0), (dM >> 1));
6100//ZZ *p++ = insn;
6101//ZZ goto done;
6102//ZZ }
6103//ZZ case ARMin_VUnaryS: {
6104//ZZ UInt fD = fregNo(i->ARMin.VUnaryS.dst);
6105//ZZ UInt fM = fregNo(i->ARMin.VUnaryS.src);
6106//ZZ UInt insn = 0;
6107//ZZ switch (i->ARMin.VUnaryS.op) {
6108//ZZ case ARMvfpu_COPY:
6109//ZZ insn = XXXXXXXX(0xE, X1110, BITS4(1,(fD & 1),1,1), X0000,
6110//ZZ (fD >> 1), X1010, BITS4(0,1,(fM & 1),0),
6111//ZZ (fM >> 1));
6112//ZZ break;
6113//ZZ case ARMvfpu_ABS:
6114//ZZ insn = XXXXXXXX(0xE, X1110, BITS4(1,(fD & 1),1,1), X0000,
6115//ZZ (fD >> 1), X1010, BITS4(1,1,(fM & 1),0),
6116//ZZ (fM >> 1));
6117//ZZ break;
6118//ZZ case ARMvfpu_NEG:
6119//ZZ insn = XXXXXXXX(0xE, X1110, BITS4(1,(fD & 1),1,1), X0001,
6120//ZZ (fD >> 1), X1010, BITS4(0,1,(fM & 1),0),
6121//ZZ (fM >> 1));
6122//ZZ break;
6123//ZZ case ARMvfpu_SQRT:
6124//ZZ insn = XXXXXXXX(0xE, X1110, BITS4(1,(fD & 1),1,1), X0001,
6125//ZZ (fD >> 1), X1010, BITS4(1,1,(fM & 1),0),
6126//ZZ (fM >> 1));
6127//ZZ break;
6128//ZZ default:
6129//ZZ goto bad;
6130//ZZ }
6131//ZZ *p++ = insn;
6132//ZZ goto done;
6133//ZZ }
6134//ZZ case ARMin_VCMovD: {
6135//ZZ UInt cc = (UInt)i->ARMin.VCMovD.cond;
6136//ZZ UInt dD = dregNo(i->ARMin.VCMovD.dst);
6137//ZZ UInt dM = dregNo(i->ARMin.VCMovD.src);
6138//ZZ vassert(cc < 16 && cc != ARMcc_AL);
6139//ZZ UInt insn = XXXXXXXX(cc, X1110,X1011,X0000,dD,X1011,X0100,dM);
6140//ZZ *p++ = insn;
6141//ZZ goto done;
6142//ZZ }
6143//ZZ case ARMin_VCMovS: {
6144//ZZ UInt cc = (UInt)i->ARMin.VCMovS.cond;
6145//ZZ UInt fD = fregNo(i->ARMin.VCMovS.dst);
6146//ZZ UInt fM = fregNo(i->ARMin.VCMovS.src);
6147//ZZ vassert(cc < 16 && cc != ARMcc_AL);
6148//ZZ UInt insn = XXXXXXXX(cc, X1110, BITS4(1,(fD & 1),1,1),
6149//ZZ X0000,(fD >> 1),X1010,
6150//ZZ BITS4(0,1,(fM & 1),0), (fM >> 1));
6151//ZZ *p++ = insn;
6152//ZZ goto done;
6153//ZZ }
6154//ZZ case ARMin_VXferD: {
6155//ZZ UInt dD = dregNo(i->ARMin.VXferD.dD);
6156//ZZ UInt rHi = iregNo(i->ARMin.VXferD.rHi);
6157//ZZ UInt rLo = iregNo(i->ARMin.VXferD.rLo);
6158//ZZ /* vmov dD, rLo, rHi is
6159//ZZ E C 4 rHi rLo B (0,0,dD[4],1) dD[3:0]
6160//ZZ vmov rLo, rHi, dD is
6161//ZZ E C 5 rHi rLo B (0,0,dD[4],1) dD[3:0]
6162//ZZ */
6163//ZZ UInt insn
6164//ZZ = XXXXXXXX(0xE, 0xC, i->ARMin.VXferD.toD ? 4 : 5,
6165//ZZ rHi, rLo, 0xB,
6166//ZZ BITS4(0,0, ((dD >> 4) & 1), 1), (dD & 0xF));
6167//ZZ *p++ = insn;
6168//ZZ goto done;
6169//ZZ }
6170//ZZ case ARMin_VXferS: {
6171//ZZ UInt fD = fregNo(i->ARMin.VXferS.fD);
6172//ZZ UInt rLo = iregNo(i->ARMin.VXferS.rLo);
6173//ZZ /* vmov fD, rLo is
6174//ZZ E E 0 fD[4:1] rLo A (fD[0],0,0,1) 0
6175//ZZ vmov rLo, fD is
6176//ZZ E E 1 fD[4:1] rLo A (fD[0],0,0,1) 0
6177//ZZ */
6178//ZZ UInt insn
6179//ZZ = XXXXXXXX(0xE, 0xE, i->ARMin.VXferS.toS ? 0 : 1,
6180//ZZ (fD >> 1) & 0xF, rLo, 0xA,
6181//ZZ BITS4((fD & 1),0,0,1), 0);
6182//ZZ *p++ = insn;
6183//ZZ goto done;
6184//ZZ }
6185//ZZ case ARMin_VCvtID: {
6186//ZZ Bool iToD = i->ARMin.VCvtID.iToD;
6187//ZZ Bool syned = i->ARMin.VCvtID.syned;
6188//ZZ if (iToD && syned) {
6189//ZZ // FSITOD: I32S-in-freg to F64-in-dreg
6190//ZZ UInt regF = fregNo(i->ARMin.VCvtID.src);
6191//ZZ UInt regD = dregNo(i->ARMin.VCvtID.dst);
6192//ZZ UInt insn = XXXXXXXX(0xE, X1110, X1011, X1000, regD,
6193//ZZ X1011, BITS4(1,1,(regF & 1),0),
6194//ZZ (regF >> 1) & 0xF);
6195//ZZ *p++ = insn;
6196//ZZ goto done;
6197//ZZ }
6198//ZZ if (iToD && (!syned)) {
6199//ZZ // FUITOD: I32U-in-freg to F64-in-dreg
6200//ZZ UInt regF = fregNo(i->ARMin.VCvtID.src);
6201//ZZ UInt regD = dregNo(i->ARMin.VCvtID.dst);
6202//ZZ UInt insn = XXXXXXXX(0xE, X1110, X1011, X1000, regD,
6203//ZZ X1011, BITS4(0,1,(regF & 1),0),
6204//ZZ (regF >> 1) & 0xF);
6205//ZZ *p++ = insn;
6206//ZZ goto done;
6207//ZZ }
6208//ZZ if ((!iToD) && syned) {
6209//ZZ // FTOSID: F64-in-dreg to I32S-in-freg
6210//ZZ UInt regD = dregNo(i->ARMin.VCvtID.src);
6211//ZZ UInt regF = fregNo(i->ARMin.VCvtID.dst);
6212//ZZ UInt insn = XXXXXXXX(0xE, X1110, BITS4(1,(regF & 1),1,1),
6213//ZZ X1101, (regF >> 1) & 0xF,
6214//ZZ X1011, X0100, regD);
6215//ZZ *p++ = insn;
6216//ZZ goto done;
6217//ZZ }
6218//ZZ if ((!iToD) && (!syned)) {
6219//ZZ // FTOUID: F64-in-dreg to I32U-in-freg
6220//ZZ UInt regD = dregNo(i->ARMin.VCvtID.src);
6221//ZZ UInt regF = fregNo(i->ARMin.VCvtID.dst);
6222//ZZ UInt insn = XXXXXXXX(0xE, X1110, BITS4(1,(regF & 1),1,1),
6223//ZZ X1100, (regF >> 1) & 0xF,
6224//ZZ X1011, X0100, regD);
6225//ZZ *p++ = insn;
6226//ZZ goto done;
6227//ZZ }
6228//ZZ /*UNREACHED*/
6229//ZZ vassert(0);
6230//ZZ }
sewardjbbcf1882014-01-12 12:49:10 +00006231//ZZ case ARMin_NLdStD: {
6232//ZZ UInt regD = dregNo(i->ARMin.NLdStD.dD);
6233//ZZ UInt regN, regM;
6234//ZZ UInt D = regD >> 4;
6235//ZZ UInt bL = i->ARMin.NLdStD.isLoad ? 1 : 0;
6236//ZZ UInt insn;
6237//ZZ vassert(hregClass(i->ARMin.NLdStD.dD) == HRcFlt64);
6238//ZZ regD &= 0xF;
6239//ZZ if (i->ARMin.NLdStD.amode->tag == ARMamN_RR) {
6240//ZZ regN = iregNo(i->ARMin.NLdStD.amode->ARMamN.RR.rN);
6241//ZZ regM = iregNo(i->ARMin.NLdStD.amode->ARMamN.RR.rM);
6242//ZZ } else {
6243//ZZ regN = iregNo(i->ARMin.NLdStD.amode->ARMamN.R.rN);
6244//ZZ regM = 15;
6245//ZZ }
6246//ZZ insn = XXXXXXXX(0xF, X0100, BITS4(0, D, bL, 0),
6247//ZZ regN, regD, X0111, X1000, regM);
6248//ZZ *p++ = insn;
6249//ZZ goto done;
6250//ZZ }
6251//ZZ case ARMin_NUnaryS: {
6252//ZZ UInt Q = i->ARMin.NUnaryS.Q ? 1 : 0;
6253//ZZ UInt regD, D;
6254//ZZ UInt regM, M;
6255//ZZ UInt size = i->ARMin.NUnaryS.size;
6256//ZZ UInt insn;
6257//ZZ UInt opc, opc1, opc2;
6258//ZZ switch (i->ARMin.NUnaryS.op) {
6259//ZZ case ARMneon_VDUP:
6260//ZZ if (i->ARMin.NUnaryS.size >= 16)
6261//ZZ goto bad;
6262//ZZ if (i->ARMin.NUnaryS.dst->tag != ARMNRS_Reg)
6263//ZZ goto bad;
6264//ZZ if (i->ARMin.NUnaryS.src->tag != ARMNRS_Scalar)
6265//ZZ goto bad;
6266//ZZ regD = (hregClass(i->ARMin.NUnaryS.dst->reg) == HRcVec128)
6267//ZZ ? (qregNo(i->ARMin.NUnaryS.dst->reg) << 1)
6268//ZZ : dregNo(i->ARMin.NUnaryS.dst->reg);
6269//ZZ regM = (hregClass(i->ARMin.NUnaryS.src->reg) == HRcVec128)
6270//ZZ ? (qregNo(i->ARMin.NUnaryS.src->reg) << 1)
6271//ZZ : dregNo(i->ARMin.NUnaryS.src->reg);
6272//ZZ D = regD >> 4;
6273//ZZ M = regM >> 4;
6274//ZZ regD &= 0xf;
6275//ZZ regM &= 0xf;
6276//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(1,D,1,1),
6277//ZZ (i->ARMin.NUnaryS.size & 0xf), regD,
6278//ZZ X1100, BITS4(0,Q,M,0), regM);
6279//ZZ *p++ = insn;
6280//ZZ goto done;
6281//ZZ case ARMneon_SETELEM:
6282//ZZ regD = Q ? (qregNo(i->ARMin.NUnaryS.dst->reg) << 1) :
6283//ZZ dregNo(i->ARMin.NUnaryS.dst->reg);
6284//ZZ regM = iregNo(i->ARMin.NUnaryS.src->reg);
6285//ZZ M = regM >> 4;
6286//ZZ D = regD >> 4;
6287//ZZ regM &= 0xF;
6288//ZZ regD &= 0xF;
6289//ZZ if (i->ARMin.NUnaryS.dst->tag != ARMNRS_Scalar)
6290//ZZ goto bad;
6291//ZZ switch (size) {
6292//ZZ case 0:
6293//ZZ if (i->ARMin.NUnaryS.dst->index > 7)
6294//ZZ goto bad;
6295//ZZ opc = X1000 | i->ARMin.NUnaryS.dst->index;
6296//ZZ break;
6297//ZZ case 1:
6298//ZZ if (i->ARMin.NUnaryS.dst->index > 3)
6299//ZZ goto bad;
6300//ZZ opc = X0001 | (i->ARMin.NUnaryS.dst->index << 1);
6301//ZZ break;
6302//ZZ case 2:
6303//ZZ if (i->ARMin.NUnaryS.dst->index > 1)
6304//ZZ goto bad;
6305//ZZ opc = X0000 | (i->ARMin.NUnaryS.dst->index << 2);
6306//ZZ break;
6307//ZZ default:
6308//ZZ goto bad;
6309//ZZ }
6310//ZZ opc1 = (opc >> 2) & 3;
6311//ZZ opc2 = opc & 3;
6312//ZZ insn = XXXXXXXX(0xE, X1110, BITS4(0,(opc1 >> 1),(opc1 & 1),0),
6313//ZZ regD, regM, X1011,
6314//ZZ BITS4(D,(opc2 >> 1),(opc2 & 1),1), X0000);
6315//ZZ *p++ = insn;
6316//ZZ goto done;
6317//ZZ case ARMneon_GETELEMU:
6318//ZZ regM = Q ? (qregNo(i->ARMin.NUnaryS.src->reg) << 1) :
6319//ZZ dregNo(i->ARMin.NUnaryS.src->reg);
6320//ZZ regD = iregNo(i->ARMin.NUnaryS.dst->reg);
6321//ZZ M = regM >> 4;
6322//ZZ D = regD >> 4;
6323//ZZ regM &= 0xF;
6324//ZZ regD &= 0xF;
6325//ZZ if (i->ARMin.NUnaryS.src->tag != ARMNRS_Scalar)
6326//ZZ goto bad;
6327//ZZ switch (size) {
6328//ZZ case 0:
6329//ZZ if (Q && i->ARMin.NUnaryS.src->index > 7) {
6330//ZZ regM++;
6331//ZZ i->ARMin.NUnaryS.src->index -= 8;
6332//ZZ }
6333//ZZ if (i->ARMin.NUnaryS.src->index > 7)
6334//ZZ goto bad;
6335//ZZ opc = X1000 | i->ARMin.NUnaryS.src->index;
6336//ZZ break;
6337//ZZ case 1:
6338//ZZ if (Q && i->ARMin.NUnaryS.src->index > 3) {
6339//ZZ regM++;
6340//ZZ i->ARMin.NUnaryS.src->index -= 4;
6341//ZZ }
6342//ZZ if (i->ARMin.NUnaryS.src->index > 3)
6343//ZZ goto bad;
6344//ZZ opc = X0001 | (i->ARMin.NUnaryS.src->index << 1);
6345//ZZ break;
6346//ZZ case 2:
6347//ZZ goto bad;
6348//ZZ default:
6349//ZZ goto bad;
6350//ZZ }
6351//ZZ opc1 = (opc >> 2) & 3;
6352//ZZ opc2 = opc & 3;
6353//ZZ insn = XXXXXXXX(0xE, X1110, BITS4(1,(opc1 >> 1),(opc1 & 1),1),
6354//ZZ regM, regD, X1011,
6355//ZZ BITS4(M,(opc2 >> 1),(opc2 & 1),1), X0000);
6356//ZZ *p++ = insn;
6357//ZZ goto done;
6358//ZZ case ARMneon_GETELEMS:
6359//ZZ regM = Q ? (qregNo(i->ARMin.NUnaryS.src->reg) << 1) :
6360//ZZ dregNo(i->ARMin.NUnaryS.src->reg);
6361//ZZ regD = iregNo(i->ARMin.NUnaryS.dst->reg);
6362//ZZ M = regM >> 4;
6363//ZZ D = regD >> 4;
6364//ZZ regM &= 0xF;
6365//ZZ regD &= 0xF;
6366//ZZ if (i->ARMin.NUnaryS.src->tag != ARMNRS_Scalar)
6367//ZZ goto bad;
6368//ZZ switch (size) {
6369//ZZ case 0:
6370//ZZ if (Q && i->ARMin.NUnaryS.src->index > 7) {
6371//ZZ regM++;
6372//ZZ i->ARMin.NUnaryS.src->index -= 8;
6373//ZZ }
6374//ZZ if (i->ARMin.NUnaryS.src->index > 7)
6375//ZZ goto bad;
6376//ZZ opc = X1000 | i->ARMin.NUnaryS.src->index;
6377//ZZ break;
6378//ZZ case 1:
6379//ZZ if (Q && i->ARMin.NUnaryS.src->index > 3) {
6380//ZZ regM++;
6381//ZZ i->ARMin.NUnaryS.src->index -= 4;
6382//ZZ }
6383//ZZ if (i->ARMin.NUnaryS.src->index > 3)
6384//ZZ goto bad;
6385//ZZ opc = X0001 | (i->ARMin.NUnaryS.src->index << 1);
6386//ZZ break;
6387//ZZ case 2:
6388//ZZ if (Q && i->ARMin.NUnaryS.src->index > 1) {
6389//ZZ regM++;
6390//ZZ i->ARMin.NUnaryS.src->index -= 2;
6391//ZZ }
6392//ZZ if (i->ARMin.NUnaryS.src->index > 1)
6393//ZZ goto bad;
6394//ZZ opc = X0000 | (i->ARMin.NUnaryS.src->index << 2);
6395//ZZ break;
6396//ZZ default:
6397//ZZ goto bad;
6398//ZZ }
6399//ZZ opc1 = (opc >> 2) & 3;
6400//ZZ opc2 = opc & 3;
6401//ZZ insn = XXXXXXXX(0xE, X1110, BITS4(0,(opc1 >> 1),(opc1 & 1),1),
6402//ZZ regM, regD, X1011,
6403//ZZ BITS4(M,(opc2 >> 1),(opc2 & 1),1), X0000);
6404//ZZ *p++ = insn;
6405//ZZ goto done;
6406//ZZ default:
6407//ZZ goto bad;
6408//ZZ }
6409//ZZ }
6410//ZZ case ARMin_NUnary: {
6411//ZZ UInt Q = i->ARMin.NUnary.Q ? 1 : 0;
6412//ZZ UInt regD = (hregClass(i->ARMin.NUnary.dst) == HRcVec128)
6413//ZZ ? (qregNo(i->ARMin.NUnary.dst) << 1)
6414//ZZ : dregNo(i->ARMin.NUnary.dst);
6415//ZZ UInt regM, M;
6416//ZZ UInt D = regD >> 4;
6417//ZZ UInt sz1 = i->ARMin.NUnary.size >> 1;
6418//ZZ UInt sz2 = i->ARMin.NUnary.size & 1;
6419//ZZ UInt sz = i->ARMin.NUnary.size;
6420//ZZ UInt insn;
6421//ZZ UInt F = 0; /* TODO: floating point EQZ ??? */
6422//ZZ if (i->ARMin.NUnary.op != ARMneon_DUP) {
6423//ZZ regM = (hregClass(i->ARMin.NUnary.src) == HRcVec128)
6424//ZZ ? (qregNo(i->ARMin.NUnary.src) << 1)
6425//ZZ : dregNo(i->ARMin.NUnary.src);
6426//ZZ M = regM >> 4;
6427//ZZ } else {
6428//ZZ regM = iregNo(i->ARMin.NUnary.src);
6429//ZZ M = regM >> 4;
6430//ZZ }
6431//ZZ regD &= 0xF;
6432//ZZ regM &= 0xF;
6433//ZZ switch (i->ARMin.NUnary.op) {
6434//ZZ case ARMneon_COPY: /* VMOV reg, reg */
6435//ZZ insn = XXXXXXXX(0xF, X0010, BITS4(0,D,1,0), regM, regD, X0001,
6436//ZZ BITS4(M,Q,M,1), regM);
6437//ZZ break;
6438//ZZ case ARMneon_COPYN: /* VMOVN regD, regQ */
6439//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(1,D,1,1), BITS4(sz1,sz2,1,0),
6440//ZZ regD, X0010, BITS4(0,0,M,0), regM);
6441//ZZ break;
6442//ZZ case ARMneon_COPYQNSS: /* VQMOVN regD, regQ */
6443//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(1,D,1,1), BITS4(sz1,sz2,1,0),
6444//ZZ regD, X0010, BITS4(1,0,M,0), regM);
6445//ZZ break;
6446//ZZ case ARMneon_COPYQNUS: /* VQMOVUN regD, regQ */
6447//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(1,D,1,1), BITS4(sz1,sz2,1,0),
6448//ZZ regD, X0010, BITS4(0,1,M,0), regM);
6449//ZZ break;
6450//ZZ case ARMneon_COPYQNUU: /* VQMOVN regD, regQ */
6451//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(1,D,1,1), BITS4(sz1,sz2,1,0),
6452//ZZ regD, X0010, BITS4(1,1,M,0), regM);
6453//ZZ break;
6454//ZZ case ARMneon_COPYLS: /* VMOVL regQ, regD */
6455//ZZ if (sz >= 3)
6456//ZZ goto bad;
6457//ZZ insn = XXXXXXXX(0xF, X0010,
6458//ZZ BITS4(1,D,(sz == 2) ? 1 : 0,(sz == 1) ? 1 : 0),
6459//ZZ BITS4((sz == 0) ? 1 : 0,0,0,0),
6460//ZZ regD, X1010, BITS4(0,0,M,1), regM);
6461//ZZ break;
6462//ZZ case ARMneon_COPYLU: /* VMOVL regQ, regD */
6463//ZZ if (sz >= 3)
6464//ZZ goto bad;
6465//ZZ insn = XXXXXXXX(0xF, X0011,
6466//ZZ BITS4(1,D,(sz == 2) ? 1 : 0,(sz == 1) ? 1 : 0),
6467//ZZ BITS4((sz == 0) ? 1 : 0,0,0,0),
6468//ZZ regD, X1010, BITS4(0,0,M,1), regM);
6469//ZZ break;
6470//ZZ case ARMneon_NOT: /* VMVN reg, reg*/
6471//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(1,D,1,1), X0000, regD, X0101,
6472//ZZ BITS4(1,Q,M,0), regM);
6473//ZZ break;
6474//ZZ case ARMneon_EQZ:
6475//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(1,D,1,1), BITS4(sz1,sz2,0,1),
6476//ZZ regD, BITS4(0,F,0,1), BITS4(0,Q,M,0), regM);
6477//ZZ break;
6478//ZZ case ARMneon_CNT:
6479//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(1,D,1,1), X0000, regD, X0101,
6480//ZZ BITS4(0,Q,M,0), regM);
6481//ZZ break;
6482//ZZ case ARMneon_CLZ:
6483//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(1,D,1,1), BITS4(sz1,sz2,0,0),
6484//ZZ regD, X0100, BITS4(1,Q,M,0), regM);
6485//ZZ break;
6486//ZZ case ARMneon_CLS:
6487//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(1,D,1,1), BITS4(sz1,sz2,0,0),
6488//ZZ regD, X0100, BITS4(0,Q,M,0), regM);
6489//ZZ break;
6490//ZZ case ARMneon_ABS:
6491//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(1,D,1,1), BITS4(sz1,sz2,0,1),
6492//ZZ regD, X0011, BITS4(0,Q,M,0), regM);
6493//ZZ break;
6494//ZZ case ARMneon_DUP:
6495//ZZ sz1 = i->ARMin.NUnary.size == 0 ? 1 : 0;
6496//ZZ sz2 = i->ARMin.NUnary.size == 1 ? 1 : 0;
6497//ZZ vassert(sz1 + sz2 < 2);
6498//ZZ insn = XXXXXXXX(0xE, X1110, BITS4(1, sz1, Q, 0), regD, regM,
6499//ZZ X1011, BITS4(D,0,sz2,1), X0000);
6500//ZZ break;
6501//ZZ case ARMneon_REV16:
6502//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(1,D,1,1), BITS4(sz1,sz2,0,0),
6503//ZZ regD, BITS4(0,0,0,1), BITS4(0,Q,M,0), regM);
6504//ZZ break;
6505//ZZ case ARMneon_REV32:
6506//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(1,D,1,1), BITS4(sz1,sz2,0,0),
6507//ZZ regD, BITS4(0,0,0,0), BITS4(1,Q,M,0), regM);
6508//ZZ break;
6509//ZZ case ARMneon_REV64:
6510//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(1,D,1,1), BITS4(sz1,sz2,0,0),
6511//ZZ regD, BITS4(0,0,0,0), BITS4(0,Q,M,0), regM);
6512//ZZ break;
6513//ZZ case ARMneon_PADDLU:
6514//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(1,D,1,1), BITS4(sz1,sz2,0,0),
6515//ZZ regD, X0010, BITS4(1,Q,M,0), regM);
6516//ZZ break;
6517//ZZ case ARMneon_PADDLS:
6518//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(1,D,1,1), BITS4(sz1,sz2,0,0),
6519//ZZ regD, X0010, BITS4(0,Q,M,0), regM);
6520//ZZ break;
6521//ZZ case ARMneon_VQSHLNUU:
6522//ZZ insn = XXXXXXXX(0xF, X0011,
6523//ZZ (1 << 3) | (D << 2) | ((sz >> 4) & 3),
6524//ZZ sz & 0xf, regD, X0111,
6525//ZZ BITS4(sz >> 6,Q,M,1), regM);
6526//ZZ break;
6527//ZZ case ARMneon_VQSHLNSS:
6528//ZZ insn = XXXXXXXX(0xF, X0010,
6529//ZZ (1 << 3) | (D << 2) | ((sz >> 4) & 3),
6530//ZZ sz & 0xf, regD, X0111,
6531//ZZ BITS4(sz >> 6,Q,M,1), regM);
6532//ZZ break;
6533//ZZ case ARMneon_VQSHLNUS:
6534//ZZ insn = XXXXXXXX(0xF, X0011,
6535//ZZ (1 << 3) | (D << 2) | ((sz >> 4) & 3),
6536//ZZ sz & 0xf, regD, X0110,
6537//ZZ BITS4(sz >> 6,Q,M,1), regM);
6538//ZZ break;
6539//ZZ case ARMneon_VCVTFtoS:
6540//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(1,D,1,1), X1011, regD, X0111,
6541//ZZ BITS4(0,Q,M,0), regM);
6542//ZZ break;
6543//ZZ case ARMneon_VCVTFtoU:
6544//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(1,D,1,1), X1011, regD, X0111,
6545//ZZ BITS4(1,Q,M,0), regM);
6546//ZZ break;
6547//ZZ case ARMneon_VCVTStoF:
6548//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(1,D,1,1), X1011, regD, X0110,
6549//ZZ BITS4(0,Q,M,0), regM);
6550//ZZ break;
6551//ZZ case ARMneon_VCVTUtoF:
6552//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(1,D,1,1), X1011, regD, X0110,
6553//ZZ BITS4(1,Q,M,0), regM);
6554//ZZ break;
6555//ZZ case ARMneon_VCVTFtoFixedU:
6556//ZZ sz1 = (sz >> 5) & 1;
6557//ZZ sz2 = (sz >> 4) & 1;
6558//ZZ sz &= 0xf;
6559//ZZ insn = XXXXXXXX(0xF, X0011,
6560//ZZ BITS4(1,D,sz1,sz2), sz, regD, X1111,
6561//ZZ BITS4(0,Q,M,1), regM);
6562//ZZ break;
6563//ZZ case ARMneon_VCVTFtoFixedS:
6564//ZZ sz1 = (sz >> 5) & 1;
6565//ZZ sz2 = (sz >> 4) & 1;
6566//ZZ sz &= 0xf;
6567//ZZ insn = XXXXXXXX(0xF, X0010,
6568//ZZ BITS4(1,D,sz1,sz2), sz, regD, X1111,
6569//ZZ BITS4(0,Q,M,1), regM);
6570//ZZ break;
6571//ZZ case ARMneon_VCVTFixedUtoF:
6572//ZZ sz1 = (sz >> 5) & 1;
6573//ZZ sz2 = (sz >> 4) & 1;
6574//ZZ sz &= 0xf;
6575//ZZ insn = XXXXXXXX(0xF, X0011,
6576//ZZ BITS4(1,D,sz1,sz2), sz, regD, X1110,
6577//ZZ BITS4(0,Q,M,1), regM);
6578//ZZ break;
6579//ZZ case ARMneon_VCVTFixedStoF:
6580//ZZ sz1 = (sz >> 5) & 1;
6581//ZZ sz2 = (sz >> 4) & 1;
6582//ZZ sz &= 0xf;
6583//ZZ insn = XXXXXXXX(0xF, X0010,
6584//ZZ BITS4(1,D,sz1,sz2), sz, regD, X1110,
6585//ZZ BITS4(0,Q,M,1), regM);
6586//ZZ break;
6587//ZZ case ARMneon_VCVTF32toF16:
6588//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(1,D,1,1), X0110, regD, X0110,
6589//ZZ BITS4(0,0,M,0), regM);
6590//ZZ break;
6591//ZZ case ARMneon_VCVTF16toF32:
6592//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(1,D,1,1), X0110, regD, X0111,
6593//ZZ BITS4(0,0,M,0), regM);
6594//ZZ break;
6595//ZZ case ARMneon_VRECIP:
6596//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(1,D,1,1), X1011, regD, X0100,
6597//ZZ BITS4(0,Q,M,0), regM);
6598//ZZ break;
6599//ZZ case ARMneon_VRECIPF:
6600//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(1,D,1,1), X1011, regD, X0101,
6601//ZZ BITS4(0,Q,M,0), regM);
6602//ZZ break;
6603//ZZ case ARMneon_VABSFP:
6604//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(1,D,1,1), X1001, regD, X0111,
6605//ZZ BITS4(0,Q,M,0), regM);
6606//ZZ break;
6607//ZZ case ARMneon_VRSQRTEFP:
6608//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(1,D,1,1), X1011, regD, X0101,
6609//ZZ BITS4(1,Q,M,0), regM);
6610//ZZ break;
6611//ZZ case ARMneon_VRSQRTE:
6612//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(1,D,1,1), X1011, regD, X0100,
6613//ZZ BITS4(1,Q,M,0), regM);
6614//ZZ break;
6615//ZZ case ARMneon_VNEGF:
6616//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(1,D,1,1), X1001, regD, X0111,
6617//ZZ BITS4(1,Q,M,0), regM);
6618//ZZ break;
6619//ZZ
6620//ZZ default:
6621//ZZ goto bad;
6622//ZZ }
6623//ZZ *p++ = insn;
6624//ZZ goto done;
6625//ZZ }
6626//ZZ case ARMin_NDual: {
6627//ZZ UInt Q = i->ARMin.NDual.Q ? 1 : 0;
6628//ZZ UInt regD = (hregClass(i->ARMin.NDual.arg1) == HRcVec128)
6629//ZZ ? (qregNo(i->ARMin.NDual.arg1) << 1)
6630//ZZ : dregNo(i->ARMin.NDual.arg1);
6631//ZZ UInt regM = (hregClass(i->ARMin.NDual.arg2) == HRcVec128)
6632//ZZ ? (qregNo(i->ARMin.NDual.arg2) << 1)
6633//ZZ : dregNo(i->ARMin.NDual.arg2);
6634//ZZ UInt D = regD >> 4;
6635//ZZ UInt M = regM >> 4;
6636//ZZ UInt sz1 = i->ARMin.NDual.size >> 1;
6637//ZZ UInt sz2 = i->ARMin.NDual.size & 1;
6638//ZZ UInt insn;
6639//ZZ regD &= 0xF;
6640//ZZ regM &= 0xF;
6641//ZZ switch (i->ARMin.NDual.op) {
6642//ZZ case ARMneon_TRN: /* VTRN reg, reg */
6643//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(1,D,1,1), BITS4(sz1,sz2,1,0),
6644//ZZ regD, X0000, BITS4(1,Q,M,0), regM);
6645//ZZ break;
6646//ZZ case ARMneon_ZIP: /* VZIP reg, reg */
6647//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(1,D,1,1), BITS4(sz1,sz2,1,0),
6648//ZZ regD, X0001, BITS4(1,Q,M,0), regM);
6649//ZZ break;
6650//ZZ case ARMneon_UZP: /* VUZP reg, reg */
6651//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(1,D,1,1), BITS4(sz1,sz2,1,0),
6652//ZZ regD, X0001, BITS4(0,Q,M,0), regM);
6653//ZZ break;
6654//ZZ default:
6655//ZZ goto bad;
6656//ZZ }
6657//ZZ *p++ = insn;
6658//ZZ goto done;
6659//ZZ }
6660//ZZ case ARMin_NBinary: {
6661//ZZ UInt Q = i->ARMin.NBinary.Q ? 1 : 0;
6662//ZZ UInt regD = (hregClass(i->ARMin.NBinary.dst) == HRcVec128)
6663//ZZ ? (qregNo(i->ARMin.NBinary.dst) << 1)
6664//ZZ : dregNo(i->ARMin.NBinary.dst);
6665//ZZ UInt regN = (hregClass(i->ARMin.NBinary.argL) == HRcVec128)
6666//ZZ ? (qregNo(i->ARMin.NBinary.argL) << 1)
6667//ZZ : dregNo(i->ARMin.NBinary.argL);
6668//ZZ UInt regM = (hregClass(i->ARMin.NBinary.argR) == HRcVec128)
6669//ZZ ? (qregNo(i->ARMin.NBinary.argR) << 1)
6670//ZZ : dregNo(i->ARMin.NBinary.argR);
6671//ZZ UInt sz1 = i->ARMin.NBinary.size >> 1;
6672//ZZ UInt sz2 = i->ARMin.NBinary.size & 1;
6673//ZZ UInt D = regD >> 4;
6674//ZZ UInt N = regN >> 4;
6675//ZZ UInt M = regM >> 4;
6676//ZZ UInt insn;
6677//ZZ regD &= 0xF;
6678//ZZ regM &= 0xF;
6679//ZZ regN &= 0xF;
6680//ZZ switch (i->ARMin.NBinary.op) {
6681//ZZ case ARMneon_VAND: /* VAND reg, reg, reg */
6682//ZZ insn = XXXXXXXX(0xF, X0010, BITS4(0,D,0,0), regN, regD, X0001,
6683//ZZ BITS4(N,Q,M,1), regM);
6684//ZZ break;
6685//ZZ case ARMneon_VORR: /* VORR reg, reg, reg*/
6686//ZZ insn = XXXXXXXX(0xF, X0010, BITS4(0,D,1,0), regN, regD, X0001,
6687//ZZ BITS4(N,Q,M,1), regM);
6688//ZZ break;
6689//ZZ case ARMneon_VXOR: /* VEOR reg, reg, reg */
6690//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(0,D,0,0), regN, regD, X0001,
6691//ZZ BITS4(N,Q,M,1), regM);
6692//ZZ break;
6693//ZZ case ARMneon_VADD: /* VADD reg, reg, reg */
6694//ZZ insn = XXXXXXXX(0xF, X0010, BITS4(0,D,sz1,sz2), regN, regD,
6695//ZZ X1000, BITS4(N,Q,M,0), regM);
6696//ZZ break;
6697//ZZ case ARMneon_VSUB: /* VSUB reg, reg, reg */
6698//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(0,D,sz1,sz2), regN, regD,
6699//ZZ X1000, BITS4(N,Q,M,0), regM);
6700//ZZ break;
6701//ZZ case ARMneon_VMINU: /* VMIN.Uxx reg, reg, reg */
6702//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(0,D,sz1,sz2), regN, regD,
6703//ZZ X0110, BITS4(N,Q,M,1), regM);
6704//ZZ break;
6705//ZZ case ARMneon_VMINS: /* VMIN.Sxx reg, reg, reg */
6706//ZZ insn = XXXXXXXX(0xF, X0010, BITS4(0,D,sz1,sz2), regN, regD,
6707//ZZ X0110, BITS4(N,Q,M,1), regM);
6708//ZZ break;
6709//ZZ case ARMneon_VMAXU: /* VMAX.Uxx reg, reg, reg */
6710//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(0,D,sz1,sz2), regN, regD,
6711//ZZ X0110, BITS4(N,Q,M,0), regM);
6712//ZZ break;
6713//ZZ case ARMneon_VMAXS: /* VMAX.Sxx reg, reg, reg */
6714//ZZ insn = XXXXXXXX(0xF, X0010, BITS4(0,D,sz1,sz2), regN, regD,
6715//ZZ X0110, BITS4(N,Q,M,0), regM);
6716//ZZ break;
6717//ZZ case ARMneon_VRHADDS: /* VRHADD.Sxx reg, reg, reg */
6718//ZZ insn = XXXXXXXX(0xF, X0010, BITS4(0,D,sz1,sz2), regN, regD,
6719//ZZ X0001, BITS4(N,Q,M,0), regM);
6720//ZZ break;
6721//ZZ case ARMneon_VRHADDU: /* VRHADD.Uxx reg, reg, reg */
6722//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(0,D,sz1,sz2), regN, regD,
6723//ZZ X0001, BITS4(N,Q,M,0), regM);
6724//ZZ break;
6725//ZZ case ARMneon_VQADDU: /* VQADD unsigned reg, reg, reg */
6726//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(0,D,sz1,sz2), regN, regD,
6727//ZZ X0000, BITS4(N,Q,M,1), regM);
6728//ZZ break;
6729//ZZ case ARMneon_VQADDS: /* VQADD signed reg, reg, reg */
6730//ZZ insn = XXXXXXXX(0xF, X0010, BITS4(0,D,sz1,sz2), regN, regD,
6731//ZZ X0000, BITS4(N,Q,M,1), regM);
6732//ZZ break;
6733//ZZ case ARMneon_VQSUBU: /* VQSUB unsigned reg, reg, reg */
6734//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(0,D,sz1,sz2), regN, regD,
6735//ZZ X0010, BITS4(N,Q,M,1), regM);
6736//ZZ break;
6737//ZZ case ARMneon_VQSUBS: /* VQSUB signed reg, reg, reg */
6738//ZZ insn = XXXXXXXX(0xF, X0010, BITS4(0,D,sz1,sz2), regN, regD,
6739//ZZ X0010, BITS4(N,Q,M,1), regM);
6740//ZZ break;
6741//ZZ case ARMneon_VCGTU: /* VCGT unsigned reg, reg, reg */
6742//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(0,D,sz1,sz2), regN, regD,
6743//ZZ X0011, BITS4(N,Q,M,0), regM);
6744//ZZ break;
6745//ZZ case ARMneon_VCGTS: /* VCGT signed reg, reg, reg */
6746//ZZ insn = XXXXXXXX(0xF, X0010, BITS4(0,D,sz1,sz2), regN, regD,
6747//ZZ X0011, BITS4(N,Q,M,0), regM);
6748//ZZ break;
6749//ZZ case ARMneon_VCGEU: /* VCGE unsigned reg, reg, reg */
6750//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(0,D,sz1,sz2), regN, regD,
6751//ZZ X0011, BITS4(N,Q,M,1), regM);
6752//ZZ break;
6753//ZZ case ARMneon_VCGES: /* VCGE signed reg, reg, reg */
6754//ZZ insn = XXXXXXXX(0xF, X0010, BITS4(0,D,sz1,sz2), regN, regD,
6755//ZZ X0011, BITS4(N,Q,M,1), regM);
6756//ZZ break;
6757//ZZ case ARMneon_VCEQ: /* VCEQ reg, reg, reg */
6758//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(0,D,sz1,sz2), regN, regD,
6759//ZZ X1000, BITS4(N,Q,M,1), regM);
6760//ZZ break;
6761//ZZ case ARMneon_VEXT: /* VEXT.8 reg, reg, #imm4*/
6762//ZZ if (i->ARMin.NBinary.size >= 16)
6763//ZZ goto bad;
6764//ZZ insn = XXXXXXXX(0xF, X0010, BITS4(1,D,1,1), regN, regD,
6765//ZZ i->ARMin.NBinary.size & 0xf, BITS4(N,Q,M,0),
6766//ZZ regM);
6767//ZZ break;
6768//ZZ case ARMneon_VMUL:
6769//ZZ insn = XXXXXXXX(0xF, X0010, BITS4(0,D,sz1,sz2), regN, regD,
6770//ZZ X1001, BITS4(N,Q,M,1), regM);
6771//ZZ break;
6772//ZZ case ARMneon_VMULLU:
6773//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(1,D,sz1,sz2), regN, regD,
6774//ZZ X1100, BITS4(N,0,M,0), regM);
6775//ZZ break;
6776//ZZ case ARMneon_VMULLS:
6777//ZZ insn = XXXXXXXX(0xF, X0010, BITS4(1,D,sz1,sz2), regN, regD,
6778//ZZ X1100, BITS4(N,0,M,0), regM);
6779//ZZ break;
6780//ZZ case ARMneon_VMULP:
6781//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(0,D,sz1,sz2), regN, regD,
6782//ZZ X1001, BITS4(N,Q,M,1), regM);
6783//ZZ break;
6784//ZZ case ARMneon_VMULFP:
6785//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(0,D,0,0), regN, regD,
6786//ZZ X1101, BITS4(N,Q,M,1), regM);
6787//ZZ break;
6788//ZZ case ARMneon_VMULLP:
6789//ZZ insn = XXXXXXXX(0xF, X0010, BITS4(1,D,sz1,sz2), regN, regD,
6790//ZZ X1110, BITS4(N,0,M,0), regM);
6791//ZZ break;
6792//ZZ case ARMneon_VQDMULH:
6793//ZZ insn = XXXXXXXX(0xF, X0010, BITS4(0,D,sz1,sz2), regN, regD,
6794//ZZ X1011, BITS4(N,Q,M,0), regM);
6795//ZZ break;
6796//ZZ case ARMneon_VQRDMULH:
6797//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(0,D,sz1,sz2), regN, regD,
6798//ZZ X1011, BITS4(N,Q,M,0), regM);
6799//ZZ break;
6800//ZZ case ARMneon_VQDMULL:
6801//ZZ insn = XXXXXXXX(0xF, X0010, BITS4(1,D,sz1,sz2), regN, regD,
6802//ZZ X1101, BITS4(N,0,M,0), regM);
6803//ZZ break;
6804//ZZ case ARMneon_VTBL:
6805//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(1,D,1,1), regN, regD,
6806//ZZ X1000, BITS4(N,0,M,0), regM);
6807//ZZ break;
6808//ZZ case ARMneon_VPADD:
6809//ZZ insn = XXXXXXXX(0xF, X0010, BITS4(0,D,sz1,sz2), regN, regD,
6810//ZZ X1011, BITS4(N,Q,M,1), regM);
6811//ZZ break;
6812//ZZ case ARMneon_VPADDFP:
6813//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(0,D,0,0), regN, regD,
6814//ZZ X1101, BITS4(N,Q,M,0), regM);
6815//ZZ break;
6816//ZZ case ARMneon_VPMINU:
6817//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(0,D,sz1,sz2), regN, regD,
6818//ZZ X1010, BITS4(N,Q,M,1), regM);
6819//ZZ break;
6820//ZZ case ARMneon_VPMINS:
6821//ZZ insn = XXXXXXXX(0xF, X0010, BITS4(0,D,sz1,sz2), regN, regD,
6822//ZZ X1010, BITS4(N,Q,M,1), regM);
6823//ZZ break;
6824//ZZ case ARMneon_VPMAXU:
6825//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(0,D,sz1,sz2), regN, regD,
6826//ZZ X1010, BITS4(N,Q,M,0), regM);
6827//ZZ break;
6828//ZZ case ARMneon_VPMAXS:
6829//ZZ insn = XXXXXXXX(0xF, X0010, BITS4(0,D,sz1,sz2), regN, regD,
6830//ZZ X1010, BITS4(N,Q,M,0), regM);
6831//ZZ break;
6832//ZZ case ARMneon_VADDFP: /* VADD reg, reg, reg */
6833//ZZ insn = XXXXXXXX(0xF, X0010, BITS4(0,D,0,0), regN, regD,
6834//ZZ X1101, BITS4(N,Q,M,0), regM);
6835//ZZ break;
6836//ZZ case ARMneon_VSUBFP: /* VADD reg, reg, reg */
6837//ZZ insn = XXXXXXXX(0xF, X0010, BITS4(0,D,1,0), regN, regD,
6838//ZZ X1101, BITS4(N,Q,M,0), regM);
6839//ZZ break;
6840//ZZ case ARMneon_VABDFP: /* VABD reg, reg, reg */
6841//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(0,D,1,0), regN, regD,
6842//ZZ X1101, BITS4(N,Q,M,0), regM);
6843//ZZ break;
6844//ZZ case ARMneon_VMINF:
6845//ZZ insn = XXXXXXXX(0xF, X0010, BITS4(0,D,1,0), regN, regD,
6846//ZZ X1111, BITS4(N,Q,M,0), regM);
6847//ZZ break;
6848//ZZ case ARMneon_VMAXF:
6849//ZZ insn = XXXXXXXX(0xF, X0010, BITS4(0,D,0,0), regN, regD,
6850//ZZ X1111, BITS4(N,Q,M,0), regM);
6851//ZZ break;
6852//ZZ case ARMneon_VPMINF:
6853//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(0,D,1,0), regN, regD,
6854//ZZ X1111, BITS4(N,Q,M,0), regM);
6855//ZZ break;
6856//ZZ case ARMneon_VPMAXF:
6857//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(0,D,0,0), regN, regD,
6858//ZZ X1111, BITS4(N,Q,M,0), regM);
6859//ZZ break;
6860//ZZ case ARMneon_VRECPS:
6861//ZZ insn = XXXXXXXX(0xF, X0010, BITS4(0,D,0,0), regN, regD, X1111,
6862//ZZ BITS4(N,Q,M,1), regM);
6863//ZZ break;
6864//ZZ case ARMneon_VCGTF:
6865//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(0,D,1,0), regN, regD, X1110,
6866//ZZ BITS4(N,Q,M,0), regM);
6867//ZZ break;
6868//ZZ case ARMneon_VCGEF:
6869//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(0,D,0,0), regN, regD, X1110,
6870//ZZ BITS4(N,Q,M,0), regM);
6871//ZZ break;
6872//ZZ case ARMneon_VCEQF:
6873//ZZ insn = XXXXXXXX(0xF, X0010, BITS4(0,D,0,0), regN, regD, X1110,
6874//ZZ BITS4(N,Q,M,0), regM);
6875//ZZ break;
6876//ZZ case ARMneon_VRSQRTS:
6877//ZZ insn = XXXXXXXX(0xF, X0010, BITS4(0,D,1,0), regN, regD, X1111,
6878//ZZ BITS4(N,Q,M,1), regM);
6879//ZZ break;
6880//ZZ default:
6881//ZZ goto bad;
6882//ZZ }
6883//ZZ *p++ = insn;
6884//ZZ goto done;
6885//ZZ }
6886//ZZ case ARMin_NShift: {
6887//ZZ UInt Q = i->ARMin.NShift.Q ? 1 : 0;
6888//ZZ UInt regD = (hregClass(i->ARMin.NShift.dst) == HRcVec128)
6889//ZZ ? (qregNo(i->ARMin.NShift.dst) << 1)
6890//ZZ : dregNo(i->ARMin.NShift.dst);
6891//ZZ UInt regM = (hregClass(i->ARMin.NShift.argL) == HRcVec128)
6892//ZZ ? (qregNo(i->ARMin.NShift.argL) << 1)
6893//ZZ : dregNo(i->ARMin.NShift.argL);
6894//ZZ UInt regN = (hregClass(i->ARMin.NShift.argR) == HRcVec128)
6895//ZZ ? (qregNo(i->ARMin.NShift.argR) << 1)
6896//ZZ : dregNo(i->ARMin.NShift.argR);
6897//ZZ UInt sz1 = i->ARMin.NShift.size >> 1;
6898//ZZ UInt sz2 = i->ARMin.NShift.size & 1;
6899//ZZ UInt D = regD >> 4;
6900//ZZ UInt N = regN >> 4;
6901//ZZ UInt M = regM >> 4;
6902//ZZ UInt insn;
6903//ZZ regD &= 0xF;
6904//ZZ regM &= 0xF;
6905//ZZ regN &= 0xF;
6906//ZZ switch (i->ARMin.NShift.op) {
6907//ZZ case ARMneon_VSHL:
6908//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(0,D,sz1,sz2), regN, regD,
6909//ZZ X0100, BITS4(N,Q,M,0), regM);
6910//ZZ break;
6911//ZZ case ARMneon_VSAL:
6912//ZZ insn = XXXXXXXX(0xF, X0010, BITS4(0,D,sz1,sz2), regN, regD,
6913//ZZ X0100, BITS4(N,Q,M,0), regM);
6914//ZZ break;
6915//ZZ case ARMneon_VQSHL:
6916//ZZ insn = XXXXXXXX(0xF, X0011, BITS4(0,D,sz1,sz2), regN, regD,
6917//ZZ X0100, BITS4(N,Q,M,1), regM);
6918//ZZ break;
6919//ZZ case ARMneon_VQSAL:
6920//ZZ insn = XXXXXXXX(0xF, X0010, BITS4(0,D,sz1,sz2), regN, regD,
6921//ZZ X0100, BITS4(N,Q,M,1), regM);
6922//ZZ break;
6923//ZZ default:
6924//ZZ goto bad;
6925//ZZ }
6926//ZZ *p++ = insn;
6927//ZZ goto done;
6928//ZZ }
6929//ZZ case ARMin_NShl64: {
6930//ZZ HReg regDreg = i->ARMin.NShl64.dst;
6931//ZZ HReg regMreg = i->ARMin.NShl64.src;
6932//ZZ UInt amt = i->ARMin.NShl64.amt;
6933//ZZ vassert(amt >= 1 && amt <= 63);
6934//ZZ vassert(hregClass(regDreg) == HRcFlt64);
6935//ZZ vassert(hregClass(regMreg) == HRcFlt64);
6936//ZZ UInt regD = dregNo(regDreg);
6937//ZZ UInt regM = dregNo(regMreg);
6938//ZZ UInt D = (regD >> 4) & 1;
6939//ZZ UInt Vd = regD & 0xF;
6940//ZZ UInt L = 1;
6941//ZZ UInt Q = 0; /* always 64-bit */
6942//ZZ UInt M = (regM >> 4) & 1;
6943//ZZ UInt Vm = regM & 0xF;
6944//ZZ UInt insn = XXXXXXXX(X1111,X0010, BITS4(1,D,(amt>>5)&1,(amt>>4)&1),
6945//ZZ amt & 0xF, Vd, X0101, BITS4(L,Q,M,1), Vm);
6946//ZZ *p++ = insn;
6947//ZZ goto done;
6948//ZZ }
6949 case ARM64in_VImmQ: {
6950 UInt rQ = qregNo(i->ARM64in.VImmQ.rQ);
6951 UShort imm = i->ARM64in.VImmQ.imm;
sewardjecde6972014-02-05 11:01:19 +00006952 if (imm == 0x0000) {
sewardjbbcf1882014-01-12 12:49:10 +00006953 /* movi rQ.4s, #0x0 == 0x4F 0x00 0x04 000 rQ */
6954 vassert(rQ < 32);
6955 *p++ = 0x4F000400 | rQ;
6956 goto done;
6957 }
sewardjfab09142014-02-10 10:28:13 +00006958 if (imm == 0x0001) {
6959 /* movi rD, #0xFF == 0x2F 0x00 0xE4 001 rD */
6960 vassert(rQ < 32);
6961 *p++ = 0x2F00E420 | rQ;
6962 goto done;
6963 }
sewardjecde6972014-02-05 11:01:19 +00006964 if (imm == 0x0003) {
6965 /* movi rD, #0xFFFF == 0x2F 0x00 0xE4 011 rD */
6966 vassert(rQ < 32);
6967 *p++ = 0x2F00E460 | rQ;
6968 goto done;
6969 }
6970 if (imm == 0x000F) {
6971 /* movi rD, #0xFFFFFFFF == 0x2F 0x00 0xE5 111 rD */
6972 vassert(rQ < 32);
6973 *p++ = 0x2F00E5E0 | rQ;
6974 goto done;
6975 }
sewardj9b1cf5e2014-03-01 11:16:57 +00006976 if (imm == 0x00FF) {
6977 /* movi rD, #0xFFFFFFFFFFFFFFFF == 0x2F 0x07 0xE7 111 rD */
6978 vassert(rQ < 32);
6979 *p++ = 0x2F07E7E0 | rQ;
6980 goto done;
6981 }
sewardj8e91fd42014-07-11 12:05:47 +00006982 if (imm == 0xFFFF) {
6983 /* mvni rQ.4s, #0x0 == 0x6F 0x00 0x04 000 rQ */
6984 vassert(rQ < 32);
6985 *p++ = 0x6F000400 | rQ;
6986 goto done;
6987 }
sewardjecde6972014-02-05 11:01:19 +00006988 goto bad; /* no other handled cases right now */
sewardjbbcf1882014-01-12 12:49:10 +00006989 }
6990
6991 case ARM64in_VDfromX: {
6992 /* INS Vd.D[0], rX
6993 0100 1110 0000 1000 0001 11 nn dd INS Vd.D[0], Xn
6994 This isn't wonderful, in the sense that the upper half of
6995 the vector register stays unchanged and thus the insn is
6996 data dependent on its output register. */
6997 UInt dd = dregNo(i->ARM64in.VDfromX.rD);
6998 UInt xx = iregNo(i->ARM64in.VDfromX.rX);
6999 vassert(xx < 31);
7000 *p++ = 0x4E081C00 | X_2_6_2_12_5_5(0,0,0,0,xx,dd);
7001 goto done;
7002 }
7003
sewardj12972182014-08-04 08:09:47 +00007004 case ARM64in_VQfromX: {
7005 /* FMOV D, X
7006 1001 1110 0110 0111 0000 00 nn dd FMOV Vd.D[0], Xn
7007 I think this zeroes out the top half of the destination, which
7008 is what we need. TODO: can we do VDfromX and VQfromXX better? */
7009 UInt dd = qregNo(i->ARM64in.VQfromX.rQ);
7010 UInt xx = iregNo(i->ARM64in.VQfromX.rXlo);
7011 vassert(xx < 31);
7012 *p++ = 0x9E670000 | X_2_6_2_12_5_5(0,0,0,0,xx,dd);
7013 goto done;
7014 }
7015
sewardjbbcf1882014-01-12 12:49:10 +00007016 case ARM64in_VQfromXX: {
7017 /* What we really generate is a two insn sequence:
7018 INS Vd.D[0], Xlo; INS Vd.D[1], Xhi
7019 0100 1110 0000 1000 0001 11 nn dd INS Vd.D[0], Xn
7020 0100 1110 0001 1000 0001 11 nn dd INS Vd.D[1], Xn
7021 */
7022 UInt qq = qregNo(i->ARM64in.VQfromXX.rQ);
7023 UInt xhi = iregNo(i->ARM64in.VQfromXX.rXhi);
7024 UInt xlo = iregNo(i->ARM64in.VQfromXX.rXlo);
7025 vassert(xhi < 31 && xlo < 31);
7026 *p++ = 0x4E081C00 | X_2_6_2_12_5_5(0,0,0,0,xlo,qq);
7027 *p++ = 0x4E181C00 | X_2_6_2_12_5_5(0,0,0,0,xhi,qq);
7028 goto done;
7029 }
7030
7031 case ARM64in_VXfromQ: {
7032 /* 010 0111 0000 01000 001111 nn dd UMOV Xd, Vn.D[0]
7033 010 0111 0000 11000 001111 nn dd UMOV Xd, Vn.D[1]
7034 */
7035 UInt dd = iregNo(i->ARM64in.VXfromQ.rX);
7036 UInt nn = qregNo(i->ARM64in.VXfromQ.rQ);
7037 UInt laneNo = i->ARM64in.VXfromQ.laneNo;
7038 vassert(dd < 31);
7039 vassert(laneNo < 2);
7040 *p++ = X_3_8_5_6_5_5(X010, X01110000,
7041 laneNo == 1 ? X11000 : X01000, X001111, nn, dd);
7042 goto done;
7043 }
7044
sewardj85fbb022014-06-12 13:16:01 +00007045 case ARM64in_VXfromDorS: {
7046 /* 000 11110001 00110 000000 n d FMOV Wd, Sn
7047 100 11110011 00110 000000 n d FMOV Xd, Dn
7048 */
7049 UInt dd = iregNo(i->ARM64in.VXfromDorS.rX);
7050 UInt nn = dregNo(i->ARM64in.VXfromDorS.rDorS);
7051 Bool fromD = i->ARM64in.VXfromDorS.fromD;
7052 vassert(dd < 31);
7053 *p++ = X_3_8_5_6_5_5(fromD ? X100 : X000,
7054 fromD ? X11110011 : X11110001,
7055 X00110, X000000, nn, dd);
7056 goto done;
7057 }
7058
sewardjbbcf1882014-01-12 12:49:10 +00007059 case ARM64in_VMov: {
7060 /* 000 11110 00 10000 00 10000 n d FMOV Sd, Sn
7061 000 11110 01 10000 00 10000 n d FMOV Dd, Dn
7062 010 01110 10 1 n 0 00111 n d MOV Vd.16b, Vn.16b
7063 */
7064 HReg rD = i->ARM64in.VMov.dst;
7065 HReg rN = i->ARM64in.VMov.src;
7066 switch (i->ARM64in.VMov.szB) {
sewardja97dddf2014-08-14 22:26:52 +00007067 case 16: {
7068 UInt dd = qregNo(rD);
7069 UInt nn = qregNo(rN);
7070 *p++ = X_3_8_5_6_5_5(X010, X01110101, nn, X000111, nn, dd);
7071 goto done;
7072 }
sewardjbbcf1882014-01-12 12:49:10 +00007073 case 8: {
7074 UInt dd = dregNo(rD);
7075 UInt nn = dregNo(rN);
7076 *p++ = X_3_8_5_6_5_5(X000, X11110011, X00000, X010000, nn, dd);
7077 goto done;
7078 }
7079 default:
7080 break;
7081 }
7082 goto bad;
7083 }
7084//ZZ case ARMin_NeonImm: {
7085//ZZ UInt Q = (hregClass(i->ARMin.NeonImm.dst) == HRcVec128) ? 1 : 0;
7086//ZZ UInt regD = Q ? (qregNo(i->ARMin.NeonImm.dst) << 1) :
7087//ZZ dregNo(i->ARMin.NeonImm.dst);
7088//ZZ UInt D = regD >> 4;
7089//ZZ UInt imm = i->ARMin.NeonImm.imm->imm8;
7090//ZZ UInt tp = i->ARMin.NeonImm.imm->type;
7091//ZZ UInt j = imm >> 7;
7092//ZZ UInt imm3 = (imm >> 4) & 0x7;
7093//ZZ UInt imm4 = imm & 0xF;
7094//ZZ UInt cmode, op;
7095//ZZ UInt insn;
7096//ZZ regD &= 0xF;
7097//ZZ if (tp == 9)
7098//ZZ op = 1;
7099//ZZ else
7100//ZZ op = 0;
7101//ZZ switch (tp) {
7102//ZZ case 0:
7103//ZZ case 1:
7104//ZZ case 2:
7105//ZZ case 3:
7106//ZZ case 4:
7107//ZZ case 5:
7108//ZZ cmode = tp << 1;
7109//ZZ break;
7110//ZZ case 9:
7111//ZZ case 6:
7112//ZZ cmode = 14;
7113//ZZ break;
7114//ZZ case 7:
7115//ZZ cmode = 12;
7116//ZZ break;
7117//ZZ case 8:
7118//ZZ cmode = 13;
7119//ZZ break;
7120//ZZ case 10:
7121//ZZ cmode = 15;
7122//ZZ break;
7123//ZZ default:
7124//ZZ vpanic("ARMin_NeonImm");
7125//ZZ
7126//ZZ }
7127//ZZ insn = XXXXXXXX(0xF, BITS4(0,0,1,j), BITS4(1,D,0,0), imm3, regD,
7128//ZZ cmode, BITS4(0,Q,op,1), imm4);
7129//ZZ *p++ = insn;
7130//ZZ goto done;
7131//ZZ }
7132//ZZ case ARMin_NCMovQ: {
7133//ZZ UInt cc = (UInt)i->ARMin.NCMovQ.cond;
7134//ZZ UInt qM = qregNo(i->ARMin.NCMovQ.src) << 1;
7135//ZZ UInt qD = qregNo(i->ARMin.NCMovQ.dst) << 1;
7136//ZZ UInt vM = qM & 0xF;
7137//ZZ UInt vD = qD & 0xF;
7138//ZZ UInt M = (qM >> 4) & 1;
7139//ZZ UInt D = (qD >> 4) & 1;
7140//ZZ vassert(cc < 16 && cc != ARMcc_AL && cc != ARMcc_NV);
7141//ZZ /* b!cc here+8: !cc A00 0000 */
7142//ZZ UInt insn = XXXXXXXX(cc ^ 1, 0xA, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0);
7143//ZZ *p++ = insn;
7144//ZZ /* vmov qD, qM */
7145//ZZ insn = XXXXXXXX(0xF, 0x2, BITS4(0,D,1,0),
7146//ZZ vM, vD, BITS4(0,0,0,1), BITS4(M,1,M,1), vM);
7147//ZZ *p++ = insn;
7148//ZZ goto done;
7149//ZZ }
7150//ZZ case ARMin_Add32: {
7151//ZZ UInt regD = iregNo(i->ARMin.Add32.rD);
7152//ZZ UInt regN = iregNo(i->ARMin.Add32.rN);
7153//ZZ UInt imm32 = i->ARMin.Add32.imm32;
7154//ZZ vassert(regD != regN);
7155//ZZ /* MOV regD, imm32 */
7156//ZZ p = imm32_to_iregNo((UInt *)p, regD, imm32);
7157//ZZ /* ADD regD, regN, regD */
7158//ZZ UInt insn = XXXXXXXX(0xE, 0, X1000, regN, regD, 0, 0, regD);
7159//ZZ *p++ = insn;
7160//ZZ goto done;
7161//ZZ }
7162
7163 case ARM64in_EvCheck: {
7164 /* The sequence is fixed (canned) except for the two amodes
7165 supplied by the insn. These don't change the length, though.
7166 We generate:
7167 ldr w9, [x21 + #8] 8 == offsetof(host_EvC_COUNTER)
7168 subs w9, w9, #1
7169 str w9, [x21 + #8] 8 == offsetof(host_EvC_COUNTER)
7170 bpl nofail
7171 ldr x9, [x21 + #0] 0 == offsetof(host_EvC_FAILADDR)
7172 br x9
7173 nofail:
7174 */
7175 UInt* p0 = p;
7176 p = do_load_or_store32(p, True/*isLoad*/, /*w*/9,
7177 i->ARM64in.EvCheck.amCounter);
7178 *p++ = 0x71000529; /* subs w9, w9, #1 */
7179 p = do_load_or_store32(p, False/*!isLoad*/, /*w*/9,
7180 i->ARM64in.EvCheck.amCounter);
7181 *p++ = 0x54000065; /* bpl nofail */
7182 p = do_load_or_store64(p, True/*isLoad*/, /*x*/9,
7183 i->ARM64in.EvCheck.amFailAddr);
7184 *p++ = 0xD61F0120; /* br x9 */
7185 /* nofail: */
7186
7187 /* Crosscheck */
sewardj9b769162014-07-24 12:42:03 +00007188 vassert(evCheckSzB_ARM64(endness_host) == (UChar*)p - (UChar*)p0);
sewardjbbcf1882014-01-12 12:49:10 +00007189 goto done;
7190 }
7191
7192//ZZ case ARMin_ProfInc: {
7193//ZZ /* We generate:
7194//ZZ (ctrP is unknown now, so use 0x65556555 in the
7195//ZZ expectation that a later call to LibVEX_patchProfCtr
7196//ZZ will be used to fill in the immediate fields once the
7197//ZZ right value is known.)
7198//ZZ movw r12, lo16(0x65556555)
7199//ZZ movt r12, lo16(0x65556555)
7200//ZZ ldr r11, [r12]
7201//ZZ adds r11, r11, #1
7202//ZZ str r11, [r12]
7203//ZZ ldr r11, [r12+4]
7204//ZZ adc r11, r11, #0
7205//ZZ str r11, [r12+4]
7206//ZZ */
7207//ZZ p = imm32_to_iregNo_EXACTLY2(p, /*r*/12, 0x65556555);
7208//ZZ *p++ = 0xE59CB000;
7209//ZZ *p++ = 0xE29BB001;
7210//ZZ *p++ = 0xE58CB000;
7211//ZZ *p++ = 0xE59CB004;
7212//ZZ *p++ = 0xE2ABB000;
7213//ZZ *p++ = 0xE58CB004;
7214//ZZ /* Tell the caller .. */
7215//ZZ vassert(!(*is_profInc));
7216//ZZ *is_profInc = True;
7217//ZZ goto done;
7218//ZZ }
7219
7220 /* ... */
7221 default:
7222 goto bad;
7223 }
7224
7225 bad:
7226 ppARM64Instr(i);
7227 vpanic("emit_ARM64Instr");
7228 /*NOTREACHED*/
7229
7230 done:
7231 vassert(((UChar*)p) - &buf[0] <= 36);
7232 return ((UChar*)p) - &buf[0];
7233}
7234
7235
7236/* How big is an event check? See case for ARM64in_EvCheck in
7237 emit_ARM64Instr just above. That crosschecks what this returns, so
7238 we can tell if we're inconsistent. */
sewardj9b769162014-07-24 12:42:03 +00007239Int evCheckSzB_ARM64 ( VexEndness endness_host )
sewardjbbcf1882014-01-12 12:49:10 +00007240{
7241 return 24;
7242}
7243
7244
7245/* NB: what goes on here has to be very closely coordinated with the
7246 emitInstr case for XDirect, above. */
sewardj9b769162014-07-24 12:42:03 +00007247VexInvalRange chainXDirect_ARM64 ( VexEndness endness_host,
7248 void* place_to_chain,
sewardjbbcf1882014-01-12 12:49:10 +00007249 void* disp_cp_chain_me_EXPECTED,
7250 void* place_to_jump_to )
7251{
sewardj9b769162014-07-24 12:42:03 +00007252 vassert(endness_host == VexEndnessLE);
7253
sewardjbbcf1882014-01-12 12:49:10 +00007254 /* What we're expecting to see is:
7255 movw x9, disp_cp_chain_me_to_EXPECTED[15:0]
7256 movk x9, disp_cp_chain_me_to_EXPECTED[31:15], lsl 16
7257 movk x9, disp_cp_chain_me_to_EXPECTED[47:32], lsl 32
7258 movk x9, disp_cp_chain_me_to_EXPECTED[63:48], lsl 48
7259 blr x9
7260 viz
7261 <16 bytes generated by imm64_to_iregNo_EXACTLY4>
7262 D6 3F 01 20
7263 */
7264 UInt* p = (UInt*)place_to_chain;
7265 vassert(0 == (3 & (HWord)p));
7266 vassert(is_imm64_to_iregNo_EXACTLY4(
7267 p, /*x*/9, Ptr_to_ULong(disp_cp_chain_me_EXPECTED)));
7268 vassert(p[4] == 0xD63F0120);
sewardjc6acaa42014-02-19 17:42:59 +00007269
sewardjbbcf1882014-01-12 12:49:10 +00007270 /* And what we want to change it to is:
7271 movw x9, place_to_jump_to[15:0]
7272 movk x9, place_to_jump_to[31:15], lsl 16
7273 movk x9, place_to_jump_to[47:32], lsl 32
7274 movk x9, place_to_jump_to[63:48], lsl 48
7275 br x9
7276 viz
7277 <16 bytes generated by imm64_to_iregNo_EXACTLY4>
7278 D6 1F 01 20
7279
7280 The replacement has the same length as the original.
7281 */
sewardjbbcf1882014-01-12 12:49:10 +00007282 (void)imm64_to_iregNo_EXACTLY4(
7283 p, /*x*/9, Ptr_to_ULong(place_to_jump_to));
7284 p[4] = 0xD61F0120;
7285
7286 VexInvalRange vir = {(HWord)p, 20};
7287 return vir;
7288}
7289
7290
sewardjc6acaa42014-02-19 17:42:59 +00007291/* NB: what goes on here has to be very closely coordinated with the
7292 emitInstr case for XDirect, above. */
sewardj9b769162014-07-24 12:42:03 +00007293VexInvalRange unchainXDirect_ARM64 ( VexEndness endness_host,
7294 void* place_to_unchain,
sewardjc6acaa42014-02-19 17:42:59 +00007295 void* place_to_jump_to_EXPECTED,
7296 void* disp_cp_chain_me )
7297{
sewardj9b769162014-07-24 12:42:03 +00007298 vassert(endness_host == VexEndnessLE);
7299
sewardjc6acaa42014-02-19 17:42:59 +00007300 /* What we're expecting to see is:
7301 movw x9, place_to_jump_to_EXPECTED[15:0]
7302 movk x9, place_to_jump_to_EXPECTED[31:15], lsl 16
7303 movk x9, place_to_jump_to_EXPECTED[47:32], lsl 32
7304 movk x9, place_to_jump_to_EXPECTED[63:48], lsl 48
7305 br x9
7306 viz
7307 <16 bytes generated by imm64_to_iregNo_EXACTLY4>
7308 D6 1F 01 20
7309 */
7310 UInt* p = (UInt*)place_to_unchain;
7311 vassert(0 == (3 & (HWord)p));
7312 vassert(is_imm64_to_iregNo_EXACTLY4(
7313 p, /*x*/9, Ptr_to_ULong(place_to_jump_to_EXPECTED)));
7314 vassert(p[4] == 0xD61F0120);
7315
7316 /* And what we want to change it to is:
7317 movw x9, disp_cp_chain_me_to[15:0]
7318 movk x9, disp_cp_chain_me_to[31:15], lsl 16
7319 movk x9, disp_cp_chain_me_to[47:32], lsl 32
7320 movk x9, disp_cp_chain_me_to[63:48], lsl 48
7321 blr x9
7322 viz
7323 <16 bytes generated by imm64_to_iregNo_EXACTLY4>
7324 D6 3F 01 20
7325 */
7326 (void)imm64_to_iregNo_EXACTLY4(
7327 p, /*x*/9, Ptr_to_ULong(disp_cp_chain_me));
7328 p[4] = 0xD63F0120;
7329
7330 VexInvalRange vir = {(HWord)p, 20};
7331 return vir;
7332}
7333
7334
sewardjbbcf1882014-01-12 12:49:10 +00007335//ZZ /* Patch the counter address into a profile inc point, as previously
7336//ZZ created by the ARMin_ProfInc case for emit_ARMInstr. */
sewardj9b769162014-07-24 12:42:03 +00007337//ZZ VexInvalRange patchProfInc_ARM ( VexEndness endness_host,
7338//ZZ void* place_to_patch,
sewardjbbcf1882014-01-12 12:49:10 +00007339//ZZ ULong* location_of_counter )
7340//ZZ {
7341//ZZ vassert(sizeof(ULong*) == 4);
7342//ZZ UInt* p = (UInt*)place_to_patch;
7343//ZZ vassert(0 == (3 & (HWord)p));
7344//ZZ vassert(is_imm32_to_iregNo_EXACTLY2(p, /*r*/12, 0x65556555));
7345//ZZ vassert(p[2] == 0xE59CB000);
7346//ZZ vassert(p[3] == 0xE29BB001);
7347//ZZ vassert(p[4] == 0xE58CB000);
7348//ZZ vassert(p[5] == 0xE59CB004);
7349//ZZ vassert(p[6] == 0xE2ABB000);
7350//ZZ vassert(p[7] == 0xE58CB004);
7351//ZZ imm32_to_iregNo_EXACTLY2(p, /*r*/12,
7352//ZZ (UInt)Ptr_to_ULong(location_of_counter));
7353//ZZ VexInvalRange vir = {(HWord)p, 8};
7354//ZZ return vir;
7355//ZZ }
7356//ZZ
7357//ZZ
7358//ZZ #undef BITS4
7359//ZZ #undef X0000
7360//ZZ #undef X0001
7361//ZZ #undef X0010
7362//ZZ #undef X0011
7363//ZZ #undef X0100
7364//ZZ #undef X0101
7365//ZZ #undef X0110
7366//ZZ #undef X0111
7367//ZZ #undef X1000
7368//ZZ #undef X1001
7369//ZZ #undef X1010
7370//ZZ #undef X1011
7371//ZZ #undef X1100
7372//ZZ #undef X1101
7373//ZZ #undef X1110
7374//ZZ #undef X1111
7375//ZZ #undef XXXXX___
7376//ZZ #undef XXXXXX__
7377//ZZ #undef XXX___XX
7378//ZZ #undef XXXXX__X
7379//ZZ #undef XXXXXXXX
7380//ZZ #undef XX______
7381
7382/*---------------------------------------------------------------*/
7383/*--- end host_arm64_defs.c ---*/
7384/*---------------------------------------------------------------*/