blob: cc7c832f37fa4eae822e2ff674ffab51dbc895a5 [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
sewardj785952d2015-08-21 11:29:16 +000010 Copyright (C) 2013-2015 OpenWorks
sewardjbbcf1882014-01-12 12:49:10 +000011 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
sewardjbbcf1882014-01-12 12:49:10 +000039
40/* --------- Registers. --------- */
41
42/* The usual HReg abstraction. We use the following classes only:
43 X regs (64 bit int)
44 D regs (64 bit float, also used for 32 bit float)
45 Q regs (128 bit vector)
46*/
47
sewardja5b50222015-03-26 07:18:32 +000048const RRegUniverse* getRRegUniverse_ARM64 ( void )
sewardjbbcf1882014-01-12 12:49:10 +000049{
sewardja5b50222015-03-26 07:18:32 +000050 /* The real-register universe is a big constant, so we just want to
51 initialise it once. */
52 static RRegUniverse rRegUniverse_ARM64;
53 static Bool rRegUniverse_ARM64_initted = False;
sewardjbbcf1882014-01-12 12:49:10 +000054
sewardja5b50222015-03-26 07:18:32 +000055 /* Handy shorthand, nothing more */
56 RRegUniverse* ru = &rRegUniverse_ARM64;
sewardjbbcf1882014-01-12 12:49:10 +000057
sewardja5b50222015-03-26 07:18:32 +000058 /* This isn't thread-safe. Sigh. */
59 if (LIKELY(rRegUniverse_ARM64_initted))
60 return ru;
61
62 RRegUniverse__init(ru);
63
64 /* Add the registers. The initial segment of this array must be
65 those available for allocation by reg-alloc, and those that
66 follow are not available for allocation. */
67
68 ru->regs[ru->size++] = hregARM64_X22();
69 ru->regs[ru->size++] = hregARM64_X23();
70 ru->regs[ru->size++] = hregARM64_X24();
71 ru->regs[ru->size++] = hregARM64_X25();
72 ru->regs[ru->size++] = hregARM64_X26();
73 ru->regs[ru->size++] = hregARM64_X27();
74 ru->regs[ru->size++] = hregARM64_X28();
75
76 ru->regs[ru->size++] = hregARM64_X0();
77 ru->regs[ru->size++] = hregARM64_X1();
78 ru->regs[ru->size++] = hregARM64_X2();
79 ru->regs[ru->size++] = hregARM64_X3();
80 ru->regs[ru->size++] = hregARM64_X4();
81 ru->regs[ru->size++] = hregARM64_X5();
82 ru->regs[ru->size++] = hregARM64_X6();
83 ru->regs[ru->size++] = hregARM64_X7();
sewardj0ad37a92014-08-29 21:58:03 +000084 // X8 is used as a ProfInc temporary, not available to regalloc.
sewardjbbcf1882014-01-12 12:49:10 +000085 // X9 is a chaining/spill temporary, not available to regalloc.
86
87 // Do we really need all these?
sewardja5b50222015-03-26 07:18:32 +000088 //ru->regs[ru->size++] = hregARM64_X10();
89 //ru->regs[ru->size++] = hregARM64_X11();
90 //ru->regs[ru->size++] = hregARM64_X12();
91 //ru->regs[ru->size++] = hregARM64_X13();
92 //ru->regs[ru->size++] = hregARM64_X14();
93 //ru->regs[ru->size++] = hregARM64_X15();
sewardjbbcf1882014-01-12 12:49:10 +000094 // X21 is the guest state pointer, not available to regalloc.
95
96 // vector regs. Unfortunately not callee-saved.
sewardja5b50222015-03-26 07:18:32 +000097 ru->regs[ru->size++] = hregARM64_Q16();
98 ru->regs[ru->size++] = hregARM64_Q17();
99 ru->regs[ru->size++] = hregARM64_Q18();
100 ru->regs[ru->size++] = hregARM64_Q19();
101 ru->regs[ru->size++] = hregARM64_Q20();
sewardjbbcf1882014-01-12 12:49:10 +0000102
103 // F64 regs, all of which are callee-saved
sewardja5b50222015-03-26 07:18:32 +0000104 ru->regs[ru->size++] = hregARM64_D8();
105 ru->regs[ru->size++] = hregARM64_D9();
106 ru->regs[ru->size++] = hregARM64_D10();
107 ru->regs[ru->size++] = hregARM64_D11();
108 ru->regs[ru->size++] = hregARM64_D12();
109 ru->regs[ru->size++] = hregARM64_D13();
110
111 ru->allocable = ru->size;
112 /* And other regs, not available to the allocator. */
sewardjbbcf1882014-01-12 12:49:10 +0000113
114 // unavail: x21 as GSP
sewardj0ad37a92014-08-29 21:58:03 +0000115 // x8 is used as a ProfInc temporary
sewardjbbcf1882014-01-12 12:49:10 +0000116 // x9 is used as a spill/reload/chaining/call temporary
sewardjbbcf1882014-01-12 12:49:10 +0000117 // x30 as LR
118 // x31 because dealing with the SP-vs-ZR overloading is too
119 // confusing, and we don't need to do so, so let's just avoid
120 // the problem
121 //
122 // Currently, we have 15 allocatable integer registers:
123 // 0 1 2 3 4 5 6 7 22 23 24 25 26 27 28
124 //
125 // Hence for the allocatable integer registers we have:
126 //
127 // callee-saved: 22 23 24 25 26 27 28
128 // caller-saved: 0 1 2 3 4 5 6 7
129 //
130 // If the set of available registers changes or if the e/r status
131 // changes, be sure to re-check/sync the definition of
sewardj0ad37a92014-08-29 21:58:03 +0000132 // getRegUsage for ARM64Instr_Call too.
sewardja5b50222015-03-26 07:18:32 +0000133
134 ru->regs[ru->size++] = hregARM64_X8();
135 ru->regs[ru->size++] = hregARM64_X9();
136 ru->regs[ru->size++] = hregARM64_X21();
137
138 rRegUniverse_ARM64_initted = True;
139
140 RRegUniverse__check_is_sane(ru);
141 return ru;
142}
143
144
145void ppHRegARM64 ( HReg reg ) {
146 Int r;
147 /* Be generic for all virtual regs. */
148 if (hregIsVirtual(reg)) {
149 ppHReg(reg);
150 return;
151 }
152 /* But specific for real regs. */
153 switch (hregClass(reg)) {
154 case HRcInt64:
155 r = hregEncoding(reg);
156 vassert(r >= 0 && r < 31);
157 vex_printf("x%d", r);
158 return;
159 case HRcFlt64:
160 r = hregEncoding(reg);
161 vassert(r >= 0 && r < 32);
162 vex_printf("d%d", r);
163 return;
164 case HRcVec128:
165 r = hregEncoding(reg);
166 vassert(r >= 0 && r < 32);
167 vex_printf("q%d", r);
168 return;
169 default:
170 vpanic("ppHRegARM64");
171 }
172}
173
174static void ppHRegARM64asSreg ( HReg reg ) {
175 ppHRegARM64(reg);
176 vex_printf("(S-reg)");
sewardjbbcf1882014-01-12 12:49:10 +0000177}
178
sewardj400d6b92015-03-30 09:01:51 +0000179static void ppHRegARM64asHreg ( HReg reg ) {
180 ppHRegARM64(reg);
181 vex_printf("(H-reg)");
182}
183
sewardjbbcf1882014-01-12 12:49:10 +0000184
sewardjbbcf1882014-01-12 12:49:10 +0000185/* --------- Condition codes, ARM64 encoding. --------- */
186
187static const HChar* showARM64CondCode ( ARM64CondCode cond ) {
188 switch (cond) {
189 case ARM64cc_EQ: return "eq";
190 case ARM64cc_NE: return "ne";
191 case ARM64cc_CS: return "cs";
192 case ARM64cc_CC: return "cc";
193 case ARM64cc_MI: return "mi";
194 case ARM64cc_PL: return "pl";
195 case ARM64cc_VS: return "vs";
196 case ARM64cc_VC: return "vc";
197 case ARM64cc_HI: return "hi";
198 case ARM64cc_LS: return "ls";
199 case ARM64cc_GE: return "ge";
200 case ARM64cc_LT: return "lt";
201 case ARM64cc_GT: return "gt";
202 case ARM64cc_LE: return "le";
203 case ARM64cc_AL: return "al"; // default
204 case ARM64cc_NV: return "nv";
205 default: vpanic("showARM64CondCode");
206 }
207}
208
209
210/* --------- Memory address expressions (amodes). --------- */
211
212ARM64AMode* ARM64AMode_RI9 ( HReg reg, Int simm9 ) {
floriand8e3eca2015-03-13 12:46:49 +0000213 ARM64AMode* am = LibVEX_Alloc_inline(sizeof(ARM64AMode));
sewardjbbcf1882014-01-12 12:49:10 +0000214 am->tag = ARM64am_RI9;
215 am->ARM64am.RI9.reg = reg;
216 am->ARM64am.RI9.simm9 = simm9;
217 vassert(-256 <= simm9 && simm9 <= 255);
218 return am;
219}
220
221ARM64AMode* ARM64AMode_RI12 ( HReg reg, Int uimm12, UChar szB ) {
floriand8e3eca2015-03-13 12:46:49 +0000222 ARM64AMode* am = LibVEX_Alloc_inline(sizeof(ARM64AMode));
sewardjbbcf1882014-01-12 12:49:10 +0000223 am->tag = ARM64am_RI12;
224 am->ARM64am.RI12.reg = reg;
225 am->ARM64am.RI12.uimm12 = uimm12;
226 am->ARM64am.RI12.szB = szB;
227 vassert(uimm12 >= 0 && uimm12 <= 4095);
228 switch (szB) {
229 case 1: case 2: case 4: case 8: break;
230 default: vassert(0);
231 }
232 return am;
233}
234
235ARM64AMode* ARM64AMode_RR ( HReg base, HReg index ) {
floriand8e3eca2015-03-13 12:46:49 +0000236 ARM64AMode* am = LibVEX_Alloc_inline(sizeof(ARM64AMode));
sewardjbbcf1882014-01-12 12:49:10 +0000237 am->tag = ARM64am_RR;
238 am->ARM64am.RR.base = base;
239 am->ARM64am.RR.index = index;
240 return am;
241}
242
243static void ppARM64AMode ( ARM64AMode* am ) {
244 switch (am->tag) {
245 case ARM64am_RI9:
246 vex_printf("%d(", am->ARM64am.RI9.simm9);
247 ppHRegARM64(am->ARM64am.RI9.reg);
248 vex_printf(")");
249 break;
250 case ARM64am_RI12:
251 vex_printf("%u(", (UInt)am->ARM64am.RI12.szB
252 * (UInt)am->ARM64am.RI12.uimm12);
253 ppHRegARM64(am->ARM64am.RI12.reg);
254 vex_printf(")");
255 break;
256 case ARM64am_RR:
257 vex_printf("(");
258 ppHRegARM64(am->ARM64am.RR.base);
259 vex_printf(",");
260 ppHRegARM64(am->ARM64am.RR.index);
261 vex_printf(")");
262 break;
263 default:
264 vassert(0);
265 }
266}
267
268static void addRegUsage_ARM64AMode ( HRegUsage* u, ARM64AMode* am ) {
269 switch (am->tag) {
270 case ARM64am_RI9:
271 addHRegUse(u, HRmRead, am->ARM64am.RI9.reg);
272 return;
273 case ARM64am_RI12:
274 addHRegUse(u, HRmRead, am->ARM64am.RI12.reg);
275 return;
276 case ARM64am_RR:
277 addHRegUse(u, HRmRead, am->ARM64am.RR.base);
278 addHRegUse(u, HRmRead, am->ARM64am.RR.index);
279 return;
280 default:
281 vpanic("addRegUsage_ARM64Amode");
282 }
283}
284
285static void mapRegs_ARM64AMode ( HRegRemap* m, ARM64AMode* am ) {
286 switch (am->tag) {
287 case ARM64am_RI9:
288 am->ARM64am.RI9.reg = lookupHRegRemap(m, am->ARM64am.RI9.reg);
289 return;
290 case ARM64am_RI12:
291 am->ARM64am.RI12.reg = lookupHRegRemap(m, am->ARM64am.RI12.reg);
292 return;
293 case ARM64am_RR:
294 am->ARM64am.RR.base = lookupHRegRemap(m, am->ARM64am.RR.base);
295 am->ARM64am.RR.index = lookupHRegRemap(m, am->ARM64am.RR.index);
296 return;
297 default:
298 vpanic("mapRegs_ARM64Amode");
299 }
300}
301
302
sewardjbbcf1882014-01-12 12:49:10 +0000303/* --------- Reg or uimm12<<{0,12} operands --------- */
304
305ARM64RIA* ARM64RIA_I12 ( UShort imm12, UChar shift ) {
floriand8e3eca2015-03-13 12:46:49 +0000306 ARM64RIA* riA = LibVEX_Alloc_inline(sizeof(ARM64RIA));
sewardjbbcf1882014-01-12 12:49:10 +0000307 riA->tag = ARM64riA_I12;
308 riA->ARM64riA.I12.imm12 = imm12;
309 riA->ARM64riA.I12.shift = shift;
310 vassert(imm12 < 4096);
311 vassert(shift == 0 || shift == 12);
312 return riA;
313}
314ARM64RIA* ARM64RIA_R ( HReg reg ) {
floriand8e3eca2015-03-13 12:46:49 +0000315 ARM64RIA* riA = LibVEX_Alloc_inline(sizeof(ARM64RIA));
sewardjbbcf1882014-01-12 12:49:10 +0000316 riA->tag = ARM64riA_R;
317 riA->ARM64riA.R.reg = reg;
318 return riA;
319}
320
321static void ppARM64RIA ( ARM64RIA* riA ) {
322 switch (riA->tag) {
323 case ARM64riA_I12:
324 vex_printf("#%u",(UInt)(riA->ARM64riA.I12.imm12
325 << riA->ARM64riA.I12.shift));
326 break;
327 case ARM64riA_R:
328 ppHRegARM64(riA->ARM64riA.R.reg);
329 break;
330 default:
331 vassert(0);
332 }
333}
334
335static void addRegUsage_ARM64RIA ( HRegUsage* u, ARM64RIA* riA ) {
336 switch (riA->tag) {
337 case ARM64riA_I12:
338 return;
339 case ARM64riA_R:
340 addHRegUse(u, HRmRead, riA->ARM64riA.R.reg);
341 return;
342 default:
343 vpanic("addRegUsage_ARM64RIA");
344 }
345}
346
347static void mapRegs_ARM64RIA ( HRegRemap* m, ARM64RIA* riA ) {
348 switch (riA->tag) {
349 case ARM64riA_I12:
350 return;
351 case ARM64riA_R:
352 riA->ARM64riA.R.reg = lookupHRegRemap(m, riA->ARM64riA.R.reg);
353 return;
354 default:
355 vpanic("mapRegs_ARM64RIA");
356 }
357}
358
359
360/* --------- Reg or "bitfield" (logic immediate) operands --------- */
361
362ARM64RIL* ARM64RIL_I13 ( UChar bitN, UChar immR, UChar immS ) {
floriand8e3eca2015-03-13 12:46:49 +0000363 ARM64RIL* riL = LibVEX_Alloc_inline(sizeof(ARM64RIL));
sewardjbbcf1882014-01-12 12:49:10 +0000364 riL->tag = ARM64riL_I13;
365 riL->ARM64riL.I13.bitN = bitN;
366 riL->ARM64riL.I13.immR = immR;
367 riL->ARM64riL.I13.immS = immS;
368 vassert(bitN < 2);
369 vassert(immR < 64);
370 vassert(immS < 64);
371 return riL;
372}
373ARM64RIL* ARM64RIL_R ( HReg reg ) {
floriand8e3eca2015-03-13 12:46:49 +0000374 ARM64RIL* riL = LibVEX_Alloc_inline(sizeof(ARM64RIL));
sewardjbbcf1882014-01-12 12:49:10 +0000375 riL->tag = ARM64riL_R;
376 riL->ARM64riL.R.reg = reg;
377 return riL;
378}
379
380static void ppARM64RIL ( ARM64RIL* riL ) {
381 switch (riL->tag) {
382 case ARM64riL_I13:
383 vex_printf("#nrs(%u,%u,%u)",
384 (UInt)riL->ARM64riL.I13.bitN,
385 (UInt)riL->ARM64riL.I13.immR,
386 (UInt)riL->ARM64riL.I13.immS);
387 break;
388 case ARM64riL_R:
389 ppHRegARM64(riL->ARM64riL.R.reg);
390 break;
391 default:
392 vassert(0);
393 }
394}
395
396static void addRegUsage_ARM64RIL ( HRegUsage* u, ARM64RIL* riL ) {
397 switch (riL->tag) {
398 case ARM64riL_I13:
399 return;
400 case ARM64riL_R:
401 addHRegUse(u, HRmRead, riL->ARM64riL.R.reg);
402 return;
403 default:
404 vpanic("addRegUsage_ARM64RIL");
405 }
406}
407
408static void mapRegs_ARM64RIL ( HRegRemap* m, ARM64RIL* riL ) {
409 switch (riL->tag) {
410 case ARM64riL_I13:
411 return;
412 case ARM64riL_R:
413 riL->ARM64riL.R.reg = lookupHRegRemap(m, riL->ARM64riL.R.reg);
414 return;
415 default:
416 vpanic("mapRegs_ARM64RIL");
417 }
418}
419
420
421/* --------------- Reg or uimm6 operands --------------- */
422
423ARM64RI6* ARM64RI6_I6 ( UInt imm6 ) {
floriand8e3eca2015-03-13 12:46:49 +0000424 ARM64RI6* ri6 = LibVEX_Alloc_inline(sizeof(ARM64RI6));
sewardjbbcf1882014-01-12 12:49:10 +0000425 ri6->tag = ARM64ri6_I6;
426 ri6->ARM64ri6.I6.imm6 = imm6;
427 vassert(imm6 > 0 && imm6 < 64);
428 return ri6;
429}
430ARM64RI6* ARM64RI6_R ( HReg reg ) {
floriand8e3eca2015-03-13 12:46:49 +0000431 ARM64RI6* ri6 = LibVEX_Alloc_inline(sizeof(ARM64RI6));
sewardjbbcf1882014-01-12 12:49:10 +0000432 ri6->tag = ARM64ri6_R;
433 ri6->ARM64ri6.R.reg = reg;
434 return ri6;
435}
436
437static void ppARM64RI6 ( ARM64RI6* ri6 ) {
438 switch (ri6->tag) {
439 case ARM64ri6_I6:
440 vex_printf("#%u", ri6->ARM64ri6.I6.imm6);
441 break;
442 case ARM64ri6_R:
443 ppHRegARM64(ri6->ARM64ri6.R.reg);
444 break;
445 default:
446 vassert(0);
447 }
448}
449
450static void addRegUsage_ARM64RI6 ( HRegUsage* u, ARM64RI6* ri6 ) {
451 switch (ri6->tag) {
452 case ARM64ri6_I6:
453 return;
454 case ARM64ri6_R:
455 addHRegUse(u, HRmRead, ri6->ARM64ri6.R.reg);
456 return;
457 default:
458 vpanic("addRegUsage_ARM64RI6");
459 }
460}
461
462static void mapRegs_ARM64RI6 ( HRegRemap* m, ARM64RI6* ri6 ) {
463 switch (ri6->tag) {
464 case ARM64ri6_I6:
465 return;
466 case ARM64ri6_R:
467 ri6->ARM64ri6.R.reg = lookupHRegRemap(m, ri6->ARM64ri6.R.reg);
468 return;
469 default:
470 vpanic("mapRegs_ARM64RI6");
471 }
472}
473
474
sewardjbbcf1882014-01-12 12:49:10 +0000475/* --------- Instructions. --------- */
476
477static const HChar* showARM64LogicOp ( ARM64LogicOp op ) {
478 switch (op) {
479 case ARM64lo_AND: return "and";
480 case ARM64lo_OR: return "orr";
481 case ARM64lo_XOR: return "eor";
482 default: vpanic("showARM64LogicOp");
483 }
484}
485
486static const HChar* showARM64ShiftOp ( ARM64ShiftOp op ) {
487 switch (op) {
488 case ARM64sh_SHL: return "lsl";
489 case ARM64sh_SHR: return "lsr";
490 case ARM64sh_SAR: return "asr";
491 default: vpanic("showARM64ShiftOp");
492 }
493}
494
495static const HChar* showARM64UnaryOp ( ARM64UnaryOp op ) {
496 switch (op) {
497 case ARM64un_NEG: return "neg";
498 case ARM64un_NOT: return "not";
499 case ARM64un_CLZ: return "clz";
500 default: vpanic("showARM64UnaryOp");
501 }
502}
503
504static const HChar* showARM64MulOp ( ARM64MulOp op ) {
505 switch (op) {
506 case ARM64mul_PLAIN: return "mul ";
507 case ARM64mul_ZX: return "umulh";
508 case ARM64mul_SX: return "smulh";
509 default: vpanic("showARM64MulOp");
510 }
511}
512
513static void characteriseARM64CvtOp ( /*OUT*/HChar* syn,
514 /*OUT*/UInt* fszB, /*OUT*/UInt* iszB,
515 ARM64CvtOp op ) {
516 switch (op) {
517 case ARM64cvt_F32_I32S:
518 *syn = 's'; *fszB = 4; *iszB = 4; break;
519 case ARM64cvt_F64_I32S:
520 *syn = 's'; *fszB = 8; *iszB = 4; break;
521 case ARM64cvt_F32_I64S:
522 *syn = 's'; *fszB = 4; *iszB = 8; break;
523 case ARM64cvt_F64_I64S:
524 *syn = 's'; *fszB = 8; *iszB = 8; break;
525 case ARM64cvt_F32_I32U:
526 *syn = 'u'; *fszB = 4; *iszB = 4; break;
527 case ARM64cvt_F64_I32U:
528 *syn = 'u'; *fszB = 8; *iszB = 4; break;
529 case ARM64cvt_F32_I64U:
530 *syn = 'u'; *fszB = 4; *iszB = 8; break;
531 case ARM64cvt_F64_I64U:
532 *syn = 'u'; *fszB = 8; *iszB = 8; break;
533 default:
534 vpanic("characteriseARM64CvtOp");
535 }
536}
537
538static const HChar* showARM64FpBinOp ( ARM64FpBinOp op ) {
539 switch (op) {
540 case ARM64fpb_ADD: return "add";
541 case ARM64fpb_SUB: return "sub";
542 case ARM64fpb_MUL: return "mul";
543 case ARM64fpb_DIV: return "div";
544 default: vpanic("showARM64FpBinOp");
545 }
546}
547
548static const HChar* showARM64FpUnaryOp ( ARM64FpUnaryOp op ) {
549 switch (op) {
sewardj89cefe42015-02-24 12:21:01 +0000550 case ARM64fpu_NEG: return "neg ";
551 case ARM64fpu_ABS: return "abs ";
552 case ARM64fpu_SQRT: return "sqrt ";
553 case ARM64fpu_RINT: return "rinti";
554 case ARM64fpu_RECPX: return "recpx";
sewardjbbcf1882014-01-12 12:49:10 +0000555 default: vpanic("showARM64FpUnaryOp");
556 }
557}
558
sewardj606c4ba2014-01-26 19:11:14 +0000559static void showARM64VecBinOp(/*OUT*/const HChar** nm,
560 /*OUT*/const HChar** ar, ARM64VecBinOp op ) {
561 switch (op) {
sewardj12972182014-08-04 08:09:47 +0000562 case ARM64vecb_ADD64x2: *nm = "add "; *ar = "2d"; return;
563 case ARM64vecb_ADD32x4: *nm = "add "; *ar = "4s"; return;
564 case ARM64vecb_ADD16x8: *nm = "add "; *ar = "8h"; return;
565 case ARM64vecb_ADD8x16: *nm = "add "; *ar = "16b"; return;
566 case ARM64vecb_SUB64x2: *nm = "sub "; *ar = "2d"; return;
567 case ARM64vecb_SUB32x4: *nm = "sub "; *ar = "4s"; return;
568 case ARM64vecb_SUB16x8: *nm = "sub "; *ar = "8h"; return;
569 case ARM64vecb_SUB8x16: *nm = "sub "; *ar = "16b"; return;
570 case ARM64vecb_MUL32x4: *nm = "mul "; *ar = "4s"; return;
571 case ARM64vecb_MUL16x8: *nm = "mul "; *ar = "8h"; return;
572 case ARM64vecb_MUL8x16: *nm = "mul "; *ar = "16b"; return;
573 case ARM64vecb_FADD64x2: *nm = "fadd "; *ar = "2d"; return;
574 case ARM64vecb_FSUB64x2: *nm = "fsub "; *ar = "2d"; return;
575 case ARM64vecb_FMUL64x2: *nm = "fmul "; *ar = "2d"; return;
576 case ARM64vecb_FDIV64x2: *nm = "fdiv "; *ar = "2d"; return;
577 case ARM64vecb_FADD32x4: *nm = "fadd "; *ar = "4s"; return;
578 case ARM64vecb_FSUB32x4: *nm = "fsub "; *ar = "4s"; return;
579 case ARM64vecb_FMUL32x4: *nm = "fmul "; *ar = "4s"; return;
580 case ARM64vecb_FDIV32x4: *nm = "fdiv "; *ar = "4s"; return;
sewardj76927e62014-11-17 11:21:21 +0000581 case ARM64vecb_FMAX64x2: *nm = "fmax "; *ar = "2d"; return;
582 case ARM64vecb_FMAX32x4: *nm = "fmax "; *ar = "4s"; return;
583 case ARM64vecb_FMIN64x2: *nm = "fmin "; *ar = "2d"; return;
584 case ARM64vecb_FMIN32x4: *nm = "fmin "; *ar = "4s"; return;
sewardj12972182014-08-04 08:09:47 +0000585 case ARM64vecb_UMAX32x4: *nm = "umax "; *ar = "4s"; return;
586 case ARM64vecb_UMAX16x8: *nm = "umax "; *ar = "8h"; return;
587 case ARM64vecb_UMAX8x16: *nm = "umax "; *ar = "16b"; return;
588 case ARM64vecb_UMIN32x4: *nm = "umin "; *ar = "4s"; return;
589 case ARM64vecb_UMIN16x8: *nm = "umin "; *ar = "8h"; return;
590 case ARM64vecb_UMIN8x16: *nm = "umin "; *ar = "16b"; return;
591 case ARM64vecb_SMAX32x4: *nm = "smax "; *ar = "4s"; return;
592 case ARM64vecb_SMAX16x8: *nm = "smax "; *ar = "8h"; return;
593 case ARM64vecb_SMAX8x16: *nm = "smax "; *ar = "16b"; return;
594 case ARM64vecb_SMIN32x4: *nm = "smin "; *ar = "4s"; return;
595 case ARM64vecb_SMIN16x8: *nm = "smin "; *ar = "8h"; return;
596 case ARM64vecb_SMIN8x16: *nm = "smin "; *ar = "16b"; return;
597 case ARM64vecb_AND: *nm = "and "; *ar = "16b"; return;
598 case ARM64vecb_ORR: *nm = "orr "; *ar = "16b"; return;
599 case ARM64vecb_XOR: *nm = "eor "; *ar = "16b"; return;
600 case ARM64vecb_CMEQ64x2: *nm = "cmeq "; *ar = "2d"; return;
601 case ARM64vecb_CMEQ32x4: *nm = "cmeq "; *ar = "4s"; return;
602 case ARM64vecb_CMEQ16x8: *nm = "cmeq "; *ar = "8h"; return;
603 case ARM64vecb_CMEQ8x16: *nm = "cmeq "; *ar = "16b"; return;
604 case ARM64vecb_CMHI64x2: *nm = "cmhi "; *ar = "2d"; return;
605 case ARM64vecb_CMHI32x4: *nm = "cmhi "; *ar = "4s"; return;
606 case ARM64vecb_CMHI16x8: *nm = "cmhi "; *ar = "8h"; return;
607 case ARM64vecb_CMHI8x16: *nm = "cmhi "; *ar = "16b"; return;
608 case ARM64vecb_CMGT64x2: *nm = "cmgt "; *ar = "2d"; return;
609 case ARM64vecb_CMGT32x4: *nm = "cmgt "; *ar = "4s"; return;
610 case ARM64vecb_CMGT16x8: *nm = "cmgt "; *ar = "8h"; return;
611 case ARM64vecb_CMGT8x16: *nm = "cmgt "; *ar = "16b"; return;
612 case ARM64vecb_FCMEQ64x2: *nm = "fcmeq "; *ar = "2d"; return;
613 case ARM64vecb_FCMEQ32x4: *nm = "fcmeq "; *ar = "4s"; return;
614 case ARM64vecb_FCMGE64x2: *nm = "fcmge "; *ar = "2d"; return;
615 case ARM64vecb_FCMGE32x4: *nm = "fcmge "; *ar = "4s"; return;
616 case ARM64vecb_FCMGT64x2: *nm = "fcmgt "; *ar = "2d"; return;
617 case ARM64vecb_FCMGT32x4: *nm = "fcmgt "; *ar = "4s"; return;
618 case ARM64vecb_TBL1: *nm = "tbl "; *ar = "16b"; return;
619 case ARM64vecb_UZP164x2: *nm = "uzp1 "; *ar = "2d"; return;
620 case ARM64vecb_UZP132x4: *nm = "uzp1 "; *ar = "4s"; return;
621 case ARM64vecb_UZP116x8: *nm = "uzp1 "; *ar = "8h"; return;
622 case ARM64vecb_UZP18x16: *nm = "uzp1 "; *ar = "16b"; return;
623 case ARM64vecb_UZP264x2: *nm = "uzp2 "; *ar = "2d"; return;
624 case ARM64vecb_UZP232x4: *nm = "uzp2 "; *ar = "4s"; return;
625 case ARM64vecb_UZP216x8: *nm = "uzp2 "; *ar = "8h"; return;
626 case ARM64vecb_UZP28x16: *nm = "uzp2 "; *ar = "16b"; return;
627 case ARM64vecb_ZIP132x4: *nm = "zip1 "; *ar = "4s"; return;
628 case ARM64vecb_ZIP116x8: *nm = "zip1 "; *ar = "8h"; return;
629 case ARM64vecb_ZIP18x16: *nm = "zip1 "; *ar = "16b"; return;
630 case ARM64vecb_ZIP232x4: *nm = "zip2 "; *ar = "4s"; return;
631 case ARM64vecb_ZIP216x8: *nm = "zip2 "; *ar = "8h"; return;
632 case ARM64vecb_ZIP28x16: *nm = "zip2 "; *ar = "16b"; return;
633 case ARM64vecb_PMUL8x16: *nm = "pmul "; *ar = "16b"; return;
634 case ARM64vecb_PMULL8x8: *nm = "pmull "; *ar = "8hbb"; return;
635 case ARM64vecb_UMULL2DSS: *nm = "umull "; *ar = "2dss"; return;
636 case ARM64vecb_UMULL4SHH: *nm = "umull "; *ar = "4shh"; return;
637 case ARM64vecb_UMULL8HBB: *nm = "umull "; *ar = "8hbb"; return;
638 case ARM64vecb_SMULL2DSS: *nm = "smull "; *ar = "2dss"; return;
639 case ARM64vecb_SMULL4SHH: *nm = "smull "; *ar = "4shh"; return;
640 case ARM64vecb_SMULL8HBB: *nm = "smull "; *ar = "8hbb"; return;
641 case ARM64vecb_SQADD64x2: *nm = "sqadd "; *ar = "2d"; return;
642 case ARM64vecb_SQADD32x4: *nm = "sqadd "; *ar = "4s"; return;
643 case ARM64vecb_SQADD16x8: *nm = "sqadd "; *ar = "8h"; return;
644 case ARM64vecb_SQADD8x16: *nm = "sqadd "; *ar = "16b"; return;
645 case ARM64vecb_UQADD64x2: *nm = "uqadd "; *ar = "2d"; return;
646 case ARM64vecb_UQADD32x4: *nm = "uqadd "; *ar = "4s"; return;
647 case ARM64vecb_UQADD16x8: *nm = "uqadd "; *ar = "8h"; return;
648 case ARM64vecb_UQADD8x16: *nm = "uqadd "; *ar = "16b"; return;
649 case ARM64vecb_SQSUB64x2: *nm = "sqsub "; *ar = "2d"; return;
650 case ARM64vecb_SQSUB32x4: *nm = "sqsub "; *ar = "4s"; return;
651 case ARM64vecb_SQSUB16x8: *nm = "sqsub "; *ar = "8h"; return;
652 case ARM64vecb_SQSUB8x16: *nm = "sqsub "; *ar = "16b"; return;
653 case ARM64vecb_UQSUB64x2: *nm = "uqsub "; *ar = "2d"; return;
654 case ARM64vecb_UQSUB32x4: *nm = "uqsub "; *ar = "4s"; return;
655 case ARM64vecb_UQSUB16x8: *nm = "uqsub "; *ar = "8h"; return;
656 case ARM64vecb_UQSUB8x16: *nm = "uqsub "; *ar = "16b"; return;
657 case ARM64vecb_SQDMULL2DSS: *nm = "sqdmull"; *ar = "2dss"; return;
658 case ARM64vecb_SQDMULL4SHH: *nm = "sqdmull"; *ar = "4shh"; return;
659 case ARM64vecb_SQDMULH32x4: *nm = "sqdmulh"; *ar = "4s"; return;
660 case ARM64vecb_SQDMULH16x8: *nm = "sqdmulh"; *ar = "8h"; return;
661 case ARM64vecb_SQRDMULH32x4: *nm = "sqrdmulh"; *ar = "4s"; return;
662 case ARM64vecb_SQRDMULH16x8: *nm = "sqrdmulh"; *ar = "8h"; return;
663 case ARM64vecb_SQSHL64x2: *nm = "sqshl "; *ar = "2d"; return;
664 case ARM64vecb_SQSHL32x4: *nm = "sqshl "; *ar = "4s"; return;
665 case ARM64vecb_SQSHL16x8: *nm = "sqshl "; *ar = "8h"; return;
666 case ARM64vecb_SQSHL8x16: *nm = "sqshl "; *ar = "16b"; return;
667 case ARM64vecb_UQSHL64x2: *nm = "uqshl "; *ar = "2d"; return;
668 case ARM64vecb_UQSHL32x4: *nm = "uqshl "; *ar = "4s"; return;
669 case ARM64vecb_UQSHL16x8: *nm = "uqshl "; *ar = "8h"; return;
670 case ARM64vecb_UQSHL8x16: *nm = "uqshl "; *ar = "16b"; return;
671 case ARM64vecb_SQRSHL64x2: *nm = "sqrshl"; *ar = "2d"; return;
672 case ARM64vecb_SQRSHL32x4: *nm = "sqrshl"; *ar = "4s"; return;
673 case ARM64vecb_SQRSHL16x8: *nm = "sqrshl"; *ar = "8h"; return;
674 case ARM64vecb_SQRSHL8x16: *nm = "sqrshl"; *ar = "16b"; return;
675 case ARM64vecb_UQRSHL64x2: *nm = "uqrshl"; *ar = "2d"; return;
676 case ARM64vecb_UQRSHL32x4: *nm = "uqrshl"; *ar = "4s"; return;
677 case ARM64vecb_UQRSHL16x8: *nm = "uqrshl"; *ar = "8h"; return;
678 case ARM64vecb_UQRSHL8x16: *nm = "uqrshl"; *ar = "16b"; return;
sewardj89cefe42015-02-24 12:21:01 +0000679 case ARM64vecb_SSHL64x2: *nm = "sshl "; *ar = "2d"; return;
680 case ARM64vecb_SSHL32x4: *nm = "sshl "; *ar = "4s"; return;
681 case ARM64vecb_SSHL16x8: *nm = "sshl "; *ar = "8h"; return;
682 case ARM64vecb_SSHL8x16: *nm = "sshl "; *ar = "16b"; return;
683 case ARM64vecb_USHL64x2: *nm = "ushl "; *ar = "2d"; return;
684 case ARM64vecb_USHL32x4: *nm = "ushl "; *ar = "4s"; return;
685 case ARM64vecb_USHL16x8: *nm = "ushl "; *ar = "8h"; return;
686 case ARM64vecb_USHL8x16: *nm = "ushl "; *ar = "16b"; return;
687 case ARM64vecb_SRSHL64x2: *nm = "srshl "; *ar = "2d"; return;
688 case ARM64vecb_SRSHL32x4: *nm = "srshl "; *ar = "4s"; return;
689 case ARM64vecb_SRSHL16x8: *nm = "srshl "; *ar = "8h"; return;
690 case ARM64vecb_SRSHL8x16: *nm = "srshl "; *ar = "16b"; return;
691 case ARM64vecb_URSHL64x2: *nm = "urshl "; *ar = "2d"; return;
692 case ARM64vecb_URSHL32x4: *nm = "urshl "; *ar = "4s"; return;
693 case ARM64vecb_URSHL16x8: *nm = "urshl "; *ar = "8h"; return;
694 case ARM64vecb_URSHL8x16: *nm = "urshl "; *ar = "16b"; return;
695 case ARM64vecb_FRECPS64x2: *nm = "frecps"; *ar = "2d"; return;
696 case ARM64vecb_FRECPS32x4: *nm = "frecps"; *ar = "4s"; return;
697 case ARM64vecb_FRSQRTS64x2: *nm = "frsqrts"; *ar = "2d"; return;
698 case ARM64vecb_FRSQRTS32x4: *nm = "frsqrts"; *ar = "4s"; return;
sewardj606c4ba2014-01-26 19:11:14 +0000699 default: vpanic("showARM64VecBinOp");
700 }
701}
702
sewardjf7003bc2014-08-18 12:28:02 +0000703static void showARM64VecModifyOp(/*OUT*/const HChar** nm,
704 /*OUT*/const HChar** ar,
705 ARM64VecModifyOp op ) {
706 switch (op) {
707 case ARM64vecmo_SUQADD64x2: *nm = "suqadd"; *ar = "2d"; return;
708 case ARM64vecmo_SUQADD32x4: *nm = "suqadd"; *ar = "4s"; return;
709 case ARM64vecmo_SUQADD16x8: *nm = "suqadd"; *ar = "8h"; return;
710 case ARM64vecmo_SUQADD8x16: *nm = "suqadd"; *ar = "16b"; return;
711 case ARM64vecmo_USQADD64x2: *nm = "usqadd"; *ar = "2d"; return;
712 case ARM64vecmo_USQADD32x4: *nm = "usqadd"; *ar = "4s"; return;
713 case ARM64vecmo_USQADD16x8: *nm = "usqadd"; *ar = "8h"; return;
714 case ARM64vecmo_USQADD8x16: *nm = "usqadd"; *ar = "16b"; return;
715 default: vpanic("showARM64VecModifyOp");
716 }
717}
718
sewardjfab09142014-02-10 10:28:13 +0000719static void showARM64VecUnaryOp(/*OUT*/const HChar** nm,
720 /*OUT*/const HChar** ar, ARM64VecUnaryOp op )
721{
722 switch (op) {
sewardjfc261d92014-08-24 20:36:14 +0000723 case ARM64vecu_FNEG64x2: *nm = "fneg "; *ar = "2d"; return;
724 case ARM64vecu_FNEG32x4: *nm = "fneg "; *ar = "4s"; return;
725 case ARM64vecu_FABS64x2: *nm = "fabs "; *ar = "2d"; return;
726 case ARM64vecu_FABS32x4: *nm = "fabs "; *ar = "4s"; return;
727 case ARM64vecu_NOT: *nm = "not "; *ar = "all"; return;
728 case ARM64vecu_ABS64x2: *nm = "abs "; *ar = "2d"; return;
729 case ARM64vecu_ABS32x4: *nm = "abs "; *ar = "4s"; return;
730 case ARM64vecu_ABS16x8: *nm = "abs "; *ar = "8h"; return;
731 case ARM64vecu_ABS8x16: *nm = "abs "; *ar = "16b"; return;
732 case ARM64vecu_CLS32x4: *nm = "cls "; *ar = "4s"; return;
733 case ARM64vecu_CLS16x8: *nm = "cls "; *ar = "8h"; return;
734 case ARM64vecu_CLS8x16: *nm = "cls "; *ar = "16b"; return;
735 case ARM64vecu_CLZ32x4: *nm = "clz "; *ar = "4s"; return;
736 case ARM64vecu_CLZ16x8: *nm = "clz "; *ar = "8h"; return;
737 case ARM64vecu_CLZ8x16: *nm = "clz "; *ar = "16b"; return;
738 case ARM64vecu_CNT8x16: *nm = "cnt "; *ar = "16b"; return;
739 case ARM64vecu_RBIT: *nm = "rbit "; *ar = "16b"; return;
740 case ARM64vecu_REV1616B: *nm = "rev16"; *ar = "16b"; return;
741 case ARM64vecu_REV3216B: *nm = "rev32"; *ar = "16b"; return;
742 case ARM64vecu_REV328H: *nm = "rev32"; *ar = "8h"; return;
743 case ARM64vecu_REV6416B: *nm = "rev64"; *ar = "16b"; return;
744 case ARM64vecu_REV648H: *nm = "rev64"; *ar = "8h"; return;
745 case ARM64vecu_REV644S: *nm = "rev64"; *ar = "4s"; return;
746 case ARM64vecu_URECPE32x4: *nm = "urecpe"; *ar = "4s"; return;
747 case ARM64vecu_URSQRTE32x4: *nm = "ursqrte"; *ar = "4s"; return;
sewardj89cefe42015-02-24 12:21:01 +0000748 case ARM64vecu_FRECPE64x2: *nm = "frecpe"; *ar = "2d"; return;
749 case ARM64vecu_FRECPE32x4: *nm = "frecpe"; *ar = "4s"; return;
750 case ARM64vecu_FRSQRTE64x2: *nm = "frsqrte"; *ar = "2d"; return;
751 case ARM64vecu_FRSQRTE32x4: *nm = "frsqrte"; *ar = "4s"; return;
sewardj4b21c3d2015-04-06 19:34:03 +0000752 case ARM64vecu_FSQRT64x2: *nm = "fsqrt"; *ar = "2d"; return;
753 case ARM64vecu_FSQRT32x4: *nm = "fsqrt"; *ar = "4s"; return;
sewardje520bb32014-02-17 11:00:53 +0000754 default: vpanic("showARM64VecUnaryOp");
755 }
756}
757
sewardja6b61f02014-08-17 18:32:14 +0000758static void showARM64VecShiftImmOp(/*OUT*/const HChar** nm,
759 /*OUT*/const HChar** ar,
760 ARM64VecShiftImmOp op )
sewardje520bb32014-02-17 11:00:53 +0000761{
762 switch (op) {
sewardja6b61f02014-08-17 18:32:14 +0000763 case ARM64vecshi_USHR64x2: *nm = "ushr "; *ar = "2d"; return;
764 case ARM64vecshi_USHR32x4: *nm = "ushr "; *ar = "4s"; return;
765 case ARM64vecshi_USHR16x8: *nm = "ushr "; *ar = "8h"; return;
766 case ARM64vecshi_USHR8x16: *nm = "ushr "; *ar = "16b"; return;
767 case ARM64vecshi_SSHR64x2: *nm = "sshr "; *ar = "2d"; return;
768 case ARM64vecshi_SSHR32x4: *nm = "sshr "; *ar = "4s"; return;
769 case ARM64vecshi_SSHR16x8: *nm = "sshr "; *ar = "8h"; return;
770 case ARM64vecshi_SSHR8x16: *nm = "sshr "; *ar = "16b"; return;
771 case ARM64vecshi_SHL64x2: *nm = "shl "; *ar = "2d"; return;
772 case ARM64vecshi_SHL32x4: *nm = "shl "; *ar = "4s"; return;
773 case ARM64vecshi_SHL16x8: *nm = "shl "; *ar = "8h"; return;
774 case ARM64vecshi_SHL8x16: *nm = "shl "; *ar = "16b"; return;
775 case ARM64vecshi_SQSHRN2SD: *nm = "sqshrn"; *ar = "2sd"; return;
776 case ARM64vecshi_SQSHRN4HS: *nm = "sqshrn"; *ar = "4hs"; return;
777 case ARM64vecshi_SQSHRN8BH: *nm = "sqshrn"; *ar = "8bh"; return;
778 case ARM64vecshi_UQSHRN2SD: *nm = "uqshrn"; *ar = "2sd"; return;
779 case ARM64vecshi_UQSHRN4HS: *nm = "uqshrn"; *ar = "4hs"; return;
780 case ARM64vecshi_UQSHRN8BH: *nm = "uqshrn"; *ar = "8bh"; return;
781 case ARM64vecshi_SQSHRUN2SD: *nm = "sqshrun"; *ar = "2sd"; return;
782 case ARM64vecshi_SQSHRUN4HS: *nm = "sqshrun"; *ar = "4hs"; return;
783 case ARM64vecshi_SQSHRUN8BH: *nm = "sqshrun"; *ar = "8bh"; return;
784 case ARM64vecshi_SQRSHRN2SD: *nm = "sqrshrn"; *ar = "2sd"; return;
785 case ARM64vecshi_SQRSHRN4HS: *nm = "sqrshrn"; *ar = "4hs"; return;
786 case ARM64vecshi_SQRSHRN8BH: *nm = "sqrshrn"; *ar = "8bh"; return;
787 case ARM64vecshi_UQRSHRN2SD: *nm = "uqrshrn"; *ar = "2sd"; return;
788 case ARM64vecshi_UQRSHRN4HS: *nm = "uqrshrn"; *ar = "4hs"; return;
789 case ARM64vecshi_UQRSHRN8BH: *nm = "uqrshrn"; *ar = "8bh"; return;
790 case ARM64vecshi_SQRSHRUN2SD: *nm = "sqrshrun"; *ar = "2sd"; return;
791 case ARM64vecshi_SQRSHRUN4HS: *nm = "sqrshrun"; *ar = "4hs"; return;
792 case ARM64vecshi_SQRSHRUN8BH: *nm = "sqrshrun"; *ar = "8bh"; return;
793 case ARM64vecshi_UQSHL64x2: *nm = "uqshl "; *ar = "2d"; return;
794 case ARM64vecshi_UQSHL32x4: *nm = "uqshl "; *ar = "4s"; return;
795 case ARM64vecshi_UQSHL16x8: *nm = "uqshl "; *ar = "8h"; return;
796 case ARM64vecshi_UQSHL8x16: *nm = "uqshl "; *ar = "16b"; return;
797 case ARM64vecshi_SQSHL64x2: *nm = "sqshl "; *ar = "2d"; return;
798 case ARM64vecshi_SQSHL32x4: *nm = "sqshl "; *ar = "4s"; return;
799 case ARM64vecshi_SQSHL16x8: *nm = "sqshl "; *ar = "8h"; return;
800 case ARM64vecshi_SQSHL8x16: *nm = "sqshl "; *ar = "16b"; return;
801 case ARM64vecshi_SQSHLU64x2: *nm = "sqshlu"; *ar = "2d"; return;
802 case ARM64vecshi_SQSHLU32x4: *nm = "sqshlu"; *ar = "4s"; return;
803 case ARM64vecshi_SQSHLU16x8: *nm = "sqshlu"; *ar = "8h"; return;
804 case ARM64vecshi_SQSHLU8x16: *nm = "sqshlu"; *ar = "16b"; return;
805 default: vpanic("showARM64VecShiftImmOp");
sewardjecedd982014-08-11 14:02:47 +0000806 }
807}
808
809static const HChar* showARM64VecNarrowOp(ARM64VecNarrowOp op) {
810 switch (op) {
811 case ARM64vecna_XTN: return "xtn ";
812 case ARM64vecna_SQXTN: return "sqxtn ";
813 case ARM64vecna_UQXTN: return "uqxtn ";
814 case ARM64vecna_SQXTUN: return "sqxtun";
815 default: vpanic("showARM64VecNarrowOp");
sewardjfab09142014-02-10 10:28:13 +0000816 }
817}
818
sewardjbbcf1882014-01-12 12:49:10 +0000819ARM64Instr* ARM64Instr_Arith ( HReg dst,
820 HReg argL, ARM64RIA* argR, Bool isAdd ) {
floriand8e3eca2015-03-13 12:46:49 +0000821 ARM64Instr* i = LibVEX_Alloc_inline(sizeof(ARM64Instr));
sewardjbbcf1882014-01-12 12:49:10 +0000822 i->tag = ARM64in_Arith;
823 i->ARM64in.Arith.dst = dst;
824 i->ARM64in.Arith.argL = argL;
825 i->ARM64in.Arith.argR = argR;
826 i->ARM64in.Arith.isAdd = isAdd;
827 return i;
828}
829ARM64Instr* ARM64Instr_Cmp ( HReg argL, ARM64RIA* argR, Bool is64 ) {
floriand8e3eca2015-03-13 12:46:49 +0000830 ARM64Instr* i = LibVEX_Alloc_inline(sizeof(ARM64Instr));
sewardjbbcf1882014-01-12 12:49:10 +0000831 i->tag = ARM64in_Cmp;
832 i->ARM64in.Cmp.argL = argL;
833 i->ARM64in.Cmp.argR = argR;
834 i->ARM64in.Cmp.is64 = is64;
835 return i;
836}
837ARM64Instr* ARM64Instr_Logic ( HReg dst,
838 HReg argL, ARM64RIL* argR, ARM64LogicOp op ) {
floriand8e3eca2015-03-13 12:46:49 +0000839 ARM64Instr* i = LibVEX_Alloc_inline(sizeof(ARM64Instr));
sewardjbbcf1882014-01-12 12:49:10 +0000840 i->tag = ARM64in_Logic;
841 i->ARM64in.Logic.dst = dst;
842 i->ARM64in.Logic.argL = argL;
843 i->ARM64in.Logic.argR = argR;
844 i->ARM64in.Logic.op = op;
845 return i;
846}
847ARM64Instr* ARM64Instr_Test ( HReg argL, ARM64RIL* argR ) {
floriand8e3eca2015-03-13 12:46:49 +0000848 ARM64Instr* i = LibVEX_Alloc_inline(sizeof(ARM64Instr));
sewardjbbcf1882014-01-12 12:49:10 +0000849 i->tag = ARM64in_Test;
850 i->ARM64in.Test.argL = argL;
851 i->ARM64in.Test.argR = argR;
852 return i;
853}
854ARM64Instr* ARM64Instr_Shift ( HReg dst,
855 HReg argL, ARM64RI6* argR, ARM64ShiftOp op ) {
floriand8e3eca2015-03-13 12:46:49 +0000856 ARM64Instr* i = LibVEX_Alloc_inline(sizeof(ARM64Instr));
sewardjbbcf1882014-01-12 12:49:10 +0000857 i->tag = ARM64in_Shift;
858 i->ARM64in.Shift.dst = dst;
859 i->ARM64in.Shift.argL = argL;
860 i->ARM64in.Shift.argR = argR;
861 i->ARM64in.Shift.op = op;
862 return i;
863}
864ARM64Instr* ARM64Instr_Unary ( HReg dst, HReg src, ARM64UnaryOp op ) {
floriand8e3eca2015-03-13 12:46:49 +0000865 ARM64Instr* i = LibVEX_Alloc_inline(sizeof(ARM64Instr));
sewardjbbcf1882014-01-12 12:49:10 +0000866 i->tag = ARM64in_Unary;
867 i->ARM64in.Unary.dst = dst;
868 i->ARM64in.Unary.src = src;
869 i->ARM64in.Unary.op = op;
870 return i;
871}
872ARM64Instr* ARM64Instr_MovI ( HReg dst, HReg src ) {
floriand8e3eca2015-03-13 12:46:49 +0000873 ARM64Instr* i = LibVEX_Alloc_inline(sizeof(ARM64Instr));
sewardjbbcf1882014-01-12 12:49:10 +0000874 i->tag = ARM64in_MovI;
875 i->ARM64in.MovI.dst = dst;
876 i->ARM64in.MovI.src = src;
877 vassert(hregClass(src) == HRcInt64);
878 vassert(hregClass(dst) == HRcInt64);
879 return i;
880}
881ARM64Instr* ARM64Instr_Imm64 ( HReg dst, ULong imm64 ) {
floriand8e3eca2015-03-13 12:46:49 +0000882 ARM64Instr* i = LibVEX_Alloc_inline(sizeof(ARM64Instr));
sewardjbbcf1882014-01-12 12:49:10 +0000883 i->tag = ARM64in_Imm64;
884 i->ARM64in.Imm64.dst = dst;
885 i->ARM64in.Imm64.imm64 = imm64;
886 return i;
887}
888ARM64Instr* ARM64Instr_LdSt64 ( Bool isLoad, HReg rD, ARM64AMode* amode ) {
floriand8e3eca2015-03-13 12:46:49 +0000889 ARM64Instr* i = LibVEX_Alloc_inline(sizeof(ARM64Instr));
sewardjbbcf1882014-01-12 12:49:10 +0000890 i->tag = ARM64in_LdSt64;
891 i->ARM64in.LdSt64.isLoad = isLoad;
892 i->ARM64in.LdSt64.rD = rD;
893 i->ARM64in.LdSt64.amode = amode;
894 return i;
895}
896ARM64Instr* ARM64Instr_LdSt32 ( Bool isLoad, HReg rD, ARM64AMode* amode ) {
floriand8e3eca2015-03-13 12:46:49 +0000897 ARM64Instr* i = LibVEX_Alloc_inline(sizeof(ARM64Instr));
sewardjbbcf1882014-01-12 12:49:10 +0000898 i->tag = ARM64in_LdSt32;
899 i->ARM64in.LdSt32.isLoad = isLoad;
900 i->ARM64in.LdSt32.rD = rD;
901 i->ARM64in.LdSt32.amode = amode;
902 return i;
903}
904ARM64Instr* ARM64Instr_LdSt16 ( Bool isLoad, HReg rD, ARM64AMode* amode ) {
floriand8e3eca2015-03-13 12:46:49 +0000905 ARM64Instr* i = LibVEX_Alloc_inline(sizeof(ARM64Instr));
sewardjbbcf1882014-01-12 12:49:10 +0000906 i->tag = ARM64in_LdSt16;
907 i->ARM64in.LdSt16.isLoad = isLoad;
908 i->ARM64in.LdSt16.rD = rD;
909 i->ARM64in.LdSt16.amode = amode;
910 return i;
911}
912ARM64Instr* ARM64Instr_LdSt8 ( Bool isLoad, HReg rD, ARM64AMode* amode ) {
floriand8e3eca2015-03-13 12:46:49 +0000913 ARM64Instr* i = LibVEX_Alloc_inline(sizeof(ARM64Instr));
sewardjbbcf1882014-01-12 12:49:10 +0000914 i->tag = ARM64in_LdSt8;
915 i->ARM64in.LdSt8.isLoad = isLoad;
916 i->ARM64in.LdSt8.rD = rD;
917 i->ARM64in.LdSt8.amode = amode;
918 return i;
919}
920ARM64Instr* ARM64Instr_XDirect ( Addr64 dstGA, ARM64AMode* amPC,
921 ARM64CondCode cond, Bool toFastEP ) {
floriand8e3eca2015-03-13 12:46:49 +0000922 ARM64Instr* i = LibVEX_Alloc_inline(sizeof(ARM64Instr));
sewardjbbcf1882014-01-12 12:49:10 +0000923 i->tag = ARM64in_XDirect;
924 i->ARM64in.XDirect.dstGA = dstGA;
925 i->ARM64in.XDirect.amPC = amPC;
926 i->ARM64in.XDirect.cond = cond;
927 i->ARM64in.XDirect.toFastEP = toFastEP;
928 return i;
929}
930ARM64Instr* ARM64Instr_XIndir ( HReg dstGA, ARM64AMode* amPC,
931 ARM64CondCode cond ) {
floriand8e3eca2015-03-13 12:46:49 +0000932 ARM64Instr* i = LibVEX_Alloc_inline(sizeof(ARM64Instr));
sewardjbbcf1882014-01-12 12:49:10 +0000933 i->tag = ARM64in_XIndir;
934 i->ARM64in.XIndir.dstGA = dstGA;
935 i->ARM64in.XIndir.amPC = amPC;
936 i->ARM64in.XIndir.cond = cond;
937 return i;
938}
939ARM64Instr* ARM64Instr_XAssisted ( HReg dstGA, ARM64AMode* amPC,
940 ARM64CondCode cond, IRJumpKind jk ) {
floriand8e3eca2015-03-13 12:46:49 +0000941 ARM64Instr* i = LibVEX_Alloc_inline(sizeof(ARM64Instr));
sewardjbbcf1882014-01-12 12:49:10 +0000942 i->tag = ARM64in_XAssisted;
943 i->ARM64in.XAssisted.dstGA = dstGA;
944 i->ARM64in.XAssisted.amPC = amPC;
945 i->ARM64in.XAssisted.cond = cond;
946 i->ARM64in.XAssisted.jk = jk;
947 return i;
948}
949ARM64Instr* ARM64Instr_CSel ( HReg dst, HReg argL, HReg argR,
950 ARM64CondCode cond ) {
floriand8e3eca2015-03-13 12:46:49 +0000951 ARM64Instr* i = LibVEX_Alloc_inline(sizeof(ARM64Instr));
sewardjbbcf1882014-01-12 12:49:10 +0000952 i->tag = ARM64in_CSel;
953 i->ARM64in.CSel.dst = dst;
954 i->ARM64in.CSel.argL = argL;
955 i->ARM64in.CSel.argR = argR;
956 i->ARM64in.CSel.cond = cond;
957 return i;
958}
florian93a09742015-01-07 20:14:48 +0000959ARM64Instr* ARM64Instr_Call ( ARM64CondCode cond, Addr64 target, Int nArgRegs,
sewardjbbcf1882014-01-12 12:49:10 +0000960 RetLoc rloc ) {
floriand8e3eca2015-03-13 12:46:49 +0000961 ARM64Instr* i = LibVEX_Alloc_inline(sizeof(ARM64Instr));
sewardjbbcf1882014-01-12 12:49:10 +0000962 i->tag = ARM64in_Call;
963 i->ARM64in.Call.cond = cond;
964 i->ARM64in.Call.target = target;
965 i->ARM64in.Call.nArgRegs = nArgRegs;
966 i->ARM64in.Call.rloc = rloc;
967 vassert(is_sane_RetLoc(rloc));
968 return i;
969}
970extern ARM64Instr* ARM64Instr_AddToSP ( Int simm ) {
floriand8e3eca2015-03-13 12:46:49 +0000971 ARM64Instr* i = LibVEX_Alloc_inline(sizeof(ARM64Instr));
sewardjbbcf1882014-01-12 12:49:10 +0000972 i->tag = ARM64in_AddToSP;
973 i->ARM64in.AddToSP.simm = simm;
974 vassert(-4096 < simm && simm < 4096);
975 vassert(0 == (simm & 0xF));
976 return i;
977}
978extern ARM64Instr* ARM64Instr_FromSP ( HReg dst ) {
floriand8e3eca2015-03-13 12:46:49 +0000979 ARM64Instr* i = LibVEX_Alloc_inline(sizeof(ARM64Instr));
sewardjbbcf1882014-01-12 12:49:10 +0000980 i->tag = ARM64in_FromSP;
981 i->ARM64in.FromSP.dst = dst;
982 return i;
983}
984ARM64Instr* ARM64Instr_Mul ( HReg dst, HReg argL, HReg argR,
985 ARM64MulOp op ) {
floriand8e3eca2015-03-13 12:46:49 +0000986 ARM64Instr* i = LibVEX_Alloc_inline(sizeof(ARM64Instr));
sewardjbbcf1882014-01-12 12:49:10 +0000987 i->tag = ARM64in_Mul;
988 i->ARM64in.Mul.dst = dst;
989 i->ARM64in.Mul.argL = argL;
990 i->ARM64in.Mul.argR = argR;
991 i->ARM64in.Mul.op = op;
992 return i;
993}
sewardj7d009132014-02-20 17:43:38 +0000994ARM64Instr* ARM64Instr_LdrEX ( Int szB ) {
floriand8e3eca2015-03-13 12:46:49 +0000995 ARM64Instr* i = LibVEX_Alloc_inline(sizeof(ARM64Instr));
sewardj7d009132014-02-20 17:43:38 +0000996 i->tag = ARM64in_LdrEX;
997 i->ARM64in.LdrEX.szB = szB;
998 vassert(szB == 8 || szB == 4 || szB == 2 || szB == 1);
999 return i;
1000}
1001ARM64Instr* ARM64Instr_StrEX ( Int szB ) {
floriand8e3eca2015-03-13 12:46:49 +00001002 ARM64Instr* i = LibVEX_Alloc_inline(sizeof(ARM64Instr));
sewardj7d009132014-02-20 17:43:38 +00001003 i->tag = ARM64in_StrEX;
1004 i->ARM64in.StrEX.szB = szB;
1005 vassert(szB == 8 || szB == 4 || szB == 2 || szB == 1);
1006 return i;
1007}
1008ARM64Instr* ARM64Instr_MFence ( void ) {
floriand8e3eca2015-03-13 12:46:49 +00001009 ARM64Instr* i = LibVEX_Alloc_inline(sizeof(ARM64Instr));
sewardj7d009132014-02-20 17:43:38 +00001010 i->tag = ARM64in_MFence;
1011 return i;
1012}
Elliott Hughesa0664b92017-04-18 17:46:52 -07001013ARM64Instr* ARM64Instr_ClrEX ( void ) {
1014 ARM64Instr* i = LibVEX_Alloc_inline(sizeof(ARM64Instr));
1015 i->tag = ARM64in_ClrEX;
1016 return i;
1017}
sewardj400d6b92015-03-30 09:01:51 +00001018ARM64Instr* ARM64Instr_VLdStH ( Bool isLoad, HReg sD, HReg rN, UInt uimm12 ) {
1019 ARM64Instr* i = LibVEX_Alloc_inline(sizeof(ARM64Instr));
1020 i->tag = ARM64in_VLdStH;
1021 i->ARM64in.VLdStH.isLoad = isLoad;
1022 i->ARM64in.VLdStH.hD = sD;
1023 i->ARM64in.VLdStH.rN = rN;
1024 i->ARM64in.VLdStH.uimm12 = uimm12;
1025 vassert(uimm12 < 8192 && 0 == (uimm12 & 1));
1026 return i;
1027}
sewardjbbcf1882014-01-12 12:49:10 +00001028ARM64Instr* ARM64Instr_VLdStS ( Bool isLoad, HReg sD, HReg rN, UInt uimm12 ) {
floriand8e3eca2015-03-13 12:46:49 +00001029 ARM64Instr* i = LibVEX_Alloc_inline(sizeof(ARM64Instr));
sewardj400d6b92015-03-30 09:01:51 +00001030 i->tag = ARM64in_VLdStS;
sewardjbbcf1882014-01-12 12:49:10 +00001031 i->ARM64in.VLdStS.isLoad = isLoad;
1032 i->ARM64in.VLdStS.sD = sD;
1033 i->ARM64in.VLdStS.rN = rN;
1034 i->ARM64in.VLdStS.uimm12 = uimm12;
1035 vassert(uimm12 < 16384 && 0 == (uimm12 & 3));
1036 return i;
1037}
1038ARM64Instr* ARM64Instr_VLdStD ( Bool isLoad, HReg dD, HReg rN, UInt uimm12 ) {
floriand8e3eca2015-03-13 12:46:49 +00001039 ARM64Instr* i = LibVEX_Alloc_inline(sizeof(ARM64Instr));
sewardj400d6b92015-03-30 09:01:51 +00001040 i->tag = ARM64in_VLdStD;
sewardjbbcf1882014-01-12 12:49:10 +00001041 i->ARM64in.VLdStD.isLoad = isLoad;
1042 i->ARM64in.VLdStD.dD = dD;
1043 i->ARM64in.VLdStD.rN = rN;
1044 i->ARM64in.VLdStD.uimm12 = uimm12;
1045 vassert(uimm12 < 32768 && 0 == (uimm12 & 7));
1046 return i;
1047}
1048ARM64Instr* ARM64Instr_VLdStQ ( Bool isLoad, HReg rQ, HReg rN ) {
floriand8e3eca2015-03-13 12:46:49 +00001049 ARM64Instr* i = LibVEX_Alloc_inline(sizeof(ARM64Instr));
sewardjbbcf1882014-01-12 12:49:10 +00001050 i->tag = ARM64in_VLdStQ;
1051 i->ARM64in.VLdStQ.isLoad = isLoad;
1052 i->ARM64in.VLdStQ.rQ = rQ;
1053 i->ARM64in.VLdStQ.rN = rN;
1054 return i;
1055}
1056ARM64Instr* ARM64Instr_VCvtI2F ( ARM64CvtOp how, HReg rD, HReg rS ) {
floriand8e3eca2015-03-13 12:46:49 +00001057 ARM64Instr* i = LibVEX_Alloc_inline(sizeof(ARM64Instr));
sewardjbbcf1882014-01-12 12:49:10 +00001058 i->tag = ARM64in_VCvtI2F;
1059 i->ARM64in.VCvtI2F.how = how;
1060 i->ARM64in.VCvtI2F.rD = rD;
1061 i->ARM64in.VCvtI2F.rS = rS;
1062 return i;
1063}
1064ARM64Instr* ARM64Instr_VCvtF2I ( ARM64CvtOp how, HReg rD, HReg rS,
1065 UChar armRM ) {
floriand8e3eca2015-03-13 12:46:49 +00001066 ARM64Instr* i = LibVEX_Alloc_inline(sizeof(ARM64Instr));
sewardjbbcf1882014-01-12 12:49:10 +00001067 i->tag = ARM64in_VCvtF2I;
1068 i->ARM64in.VCvtF2I.how = how;
1069 i->ARM64in.VCvtF2I.rD = rD;
1070 i->ARM64in.VCvtF2I.rS = rS;
1071 i->ARM64in.VCvtF2I.armRM = armRM;
1072 vassert(armRM <= 3);
1073 return i;
1074}
1075ARM64Instr* ARM64Instr_VCvtSD ( Bool sToD, HReg dst, HReg src ) {
floriand8e3eca2015-03-13 12:46:49 +00001076 ARM64Instr* i = LibVEX_Alloc_inline(sizeof(ARM64Instr));
sewardj400d6b92015-03-30 09:01:51 +00001077 i->tag = ARM64in_VCvtSD;
sewardjbbcf1882014-01-12 12:49:10 +00001078 i->ARM64in.VCvtSD.sToD = sToD;
1079 i->ARM64in.VCvtSD.dst = dst;
1080 i->ARM64in.VCvtSD.src = src;
1081 return i;
1082}
sewardj400d6b92015-03-30 09:01:51 +00001083ARM64Instr* ARM64Instr_VCvtHS ( Bool hToS, HReg dst, HReg src ) {
1084 ARM64Instr* i = LibVEX_Alloc_inline(sizeof(ARM64Instr));
1085 i->tag = ARM64in_VCvtHS;
1086 i->ARM64in.VCvtHS.hToS = hToS;
1087 i->ARM64in.VCvtHS.dst = dst;
1088 i->ARM64in.VCvtHS.src = src;
1089 return i;
1090}
1091ARM64Instr* ARM64Instr_VCvtHD ( Bool hToD, HReg dst, HReg src ) {
1092 ARM64Instr* i = LibVEX_Alloc_inline(sizeof(ARM64Instr));
1093 i->tag = ARM64in_VCvtHD;
1094 i->ARM64in.VCvtHD.hToD = hToD;
1095 i->ARM64in.VCvtHD.dst = dst;
1096 i->ARM64in.VCvtHD.src = src;
1097 return i;
1098}
sewardjbbcf1882014-01-12 12:49:10 +00001099ARM64Instr* ARM64Instr_VUnaryD ( ARM64FpUnaryOp op, HReg dst, HReg src ) {
floriand8e3eca2015-03-13 12:46:49 +00001100 ARM64Instr* i = LibVEX_Alloc_inline(sizeof(ARM64Instr));
sewardjbbcf1882014-01-12 12:49:10 +00001101 i->tag = ARM64in_VUnaryD;
1102 i->ARM64in.VUnaryD.op = op;
1103 i->ARM64in.VUnaryD.dst = dst;
1104 i->ARM64in.VUnaryD.src = src;
1105 return i;
1106}
1107ARM64Instr* ARM64Instr_VUnaryS ( ARM64FpUnaryOp op, HReg dst, HReg src ) {
floriand8e3eca2015-03-13 12:46:49 +00001108 ARM64Instr* i = LibVEX_Alloc_inline(sizeof(ARM64Instr));
sewardjbbcf1882014-01-12 12:49:10 +00001109 i->tag = ARM64in_VUnaryS;
1110 i->ARM64in.VUnaryS.op = op;
1111 i->ARM64in.VUnaryS.dst = dst;
1112 i->ARM64in.VUnaryS.src = src;
1113 return i;
1114}
1115ARM64Instr* ARM64Instr_VBinD ( ARM64FpBinOp op,
1116 HReg dst, HReg argL, HReg argR ) {
floriand8e3eca2015-03-13 12:46:49 +00001117 ARM64Instr* i = LibVEX_Alloc_inline(sizeof(ARM64Instr));
sewardjbbcf1882014-01-12 12:49:10 +00001118 i->tag = ARM64in_VBinD;
1119 i->ARM64in.VBinD.op = op;
1120 i->ARM64in.VBinD.dst = dst;
1121 i->ARM64in.VBinD.argL = argL;
1122 i->ARM64in.VBinD.argR = argR;
1123 return i;
1124}
1125ARM64Instr* ARM64Instr_VBinS ( ARM64FpBinOp op,
1126 HReg dst, HReg argL, HReg argR ) {
floriand8e3eca2015-03-13 12:46:49 +00001127 ARM64Instr* i = LibVEX_Alloc_inline(sizeof(ARM64Instr));
sewardjbbcf1882014-01-12 12:49:10 +00001128 i->tag = ARM64in_VBinS;
1129 i->ARM64in.VBinS.op = op;
1130 i->ARM64in.VBinS.dst = dst;
1131 i->ARM64in.VBinS.argL = argL;
1132 i->ARM64in.VBinS.argR = argR;
1133 return i;
1134}
1135ARM64Instr* ARM64Instr_VCmpD ( HReg argL, HReg argR ) {
floriand8e3eca2015-03-13 12:46:49 +00001136 ARM64Instr* i = LibVEX_Alloc_inline(sizeof(ARM64Instr));
sewardjbbcf1882014-01-12 12:49:10 +00001137 i->tag = ARM64in_VCmpD;
1138 i->ARM64in.VCmpD.argL = argL;
1139 i->ARM64in.VCmpD.argR = argR;
1140 return i;
1141}
1142ARM64Instr* ARM64Instr_VCmpS ( HReg argL, HReg argR ) {
floriand8e3eca2015-03-13 12:46:49 +00001143 ARM64Instr* i = LibVEX_Alloc_inline(sizeof(ARM64Instr));
sewardjbbcf1882014-01-12 12:49:10 +00001144 i->tag = ARM64in_VCmpS;
1145 i->ARM64in.VCmpS.argL = argL;
1146 i->ARM64in.VCmpS.argR = argR;
1147 return i;
1148}
sewardje23ec112014-11-15 16:07:14 +00001149ARM64Instr* ARM64Instr_VFCSel ( HReg dst, HReg argL, HReg argR,
1150 ARM64CondCode cond, Bool isD ) {
floriand8e3eca2015-03-13 12:46:49 +00001151 ARM64Instr* i = LibVEX_Alloc_inline(sizeof(ARM64Instr));
sewardje23ec112014-11-15 16:07:14 +00001152 i->tag = ARM64in_VFCSel;
1153 i->ARM64in.VFCSel.dst = dst;
1154 i->ARM64in.VFCSel.argL = argL;
1155 i->ARM64in.VFCSel.argR = argR;
1156 i->ARM64in.VFCSel.cond = cond;
1157 i->ARM64in.VFCSel.isD = isD;
1158 return i;
1159}
sewardjbbcf1882014-01-12 12:49:10 +00001160ARM64Instr* ARM64Instr_FPCR ( Bool toFPCR, HReg iReg ) {
floriand8e3eca2015-03-13 12:46:49 +00001161 ARM64Instr* i = LibVEX_Alloc_inline(sizeof(ARM64Instr));
sewardjbbcf1882014-01-12 12:49:10 +00001162 i->tag = ARM64in_FPCR;
1163 i->ARM64in.FPCR.toFPCR = toFPCR;
1164 i->ARM64in.FPCR.iReg = iReg;
1165 return i;
1166}
sewardj12972182014-08-04 08:09:47 +00001167ARM64Instr* ARM64Instr_FPSR ( Bool toFPSR, HReg iReg ) {
floriand8e3eca2015-03-13 12:46:49 +00001168 ARM64Instr* i = LibVEX_Alloc_inline(sizeof(ARM64Instr));
sewardj12972182014-08-04 08:09:47 +00001169 i->tag = ARM64in_FPSR;
1170 i->ARM64in.FPSR.toFPSR = toFPSR;
1171 i->ARM64in.FPSR.iReg = iReg;
1172 return i;
1173}
sewardj606c4ba2014-01-26 19:11:14 +00001174ARM64Instr* ARM64Instr_VBinV ( ARM64VecBinOp op,
1175 HReg dst, HReg argL, HReg argR ) {
floriand8e3eca2015-03-13 12:46:49 +00001176 ARM64Instr* i = LibVEX_Alloc_inline(sizeof(ARM64Instr));
sewardj606c4ba2014-01-26 19:11:14 +00001177 i->tag = ARM64in_VBinV;
1178 i->ARM64in.VBinV.op = op;
1179 i->ARM64in.VBinV.dst = dst;
1180 i->ARM64in.VBinV.argL = argL;
1181 i->ARM64in.VBinV.argR = argR;
1182 return i;
1183}
sewardjf7003bc2014-08-18 12:28:02 +00001184ARM64Instr* ARM64Instr_VModifyV ( ARM64VecModifyOp op, HReg mod, HReg arg ) {
floriand8e3eca2015-03-13 12:46:49 +00001185 ARM64Instr* i = LibVEX_Alloc_inline(sizeof(ARM64Instr));
sewardjf7003bc2014-08-18 12:28:02 +00001186 i->tag = ARM64in_VModifyV;
1187 i->ARM64in.VModifyV.op = op;
1188 i->ARM64in.VModifyV.mod = mod;
1189 i->ARM64in.VModifyV.arg = arg;
1190 return i;
1191}
sewardjfab09142014-02-10 10:28:13 +00001192ARM64Instr* ARM64Instr_VUnaryV ( ARM64VecUnaryOp op, HReg dst, HReg arg ) {
floriand8e3eca2015-03-13 12:46:49 +00001193 ARM64Instr* i = LibVEX_Alloc_inline(sizeof(ARM64Instr));
sewardjfab09142014-02-10 10:28:13 +00001194 i->tag = ARM64in_VUnaryV;
1195 i->ARM64in.VUnaryV.op = op;
1196 i->ARM64in.VUnaryV.dst = dst;
1197 i->ARM64in.VUnaryV.arg = arg;
1198 return i;
1199}
sewardjecedd982014-08-11 14:02:47 +00001200ARM64Instr* ARM64Instr_VNarrowV ( ARM64VecNarrowOp op,
1201 UInt dszBlg2, HReg dst, HReg src ) {
floriand8e3eca2015-03-13 12:46:49 +00001202 ARM64Instr* i = LibVEX_Alloc_inline(sizeof(ARM64Instr));
sewardj606c4ba2014-01-26 19:11:14 +00001203 i->tag = ARM64in_VNarrowV;
sewardjecedd982014-08-11 14:02:47 +00001204 i->ARM64in.VNarrowV.op = op;
sewardj606c4ba2014-01-26 19:11:14 +00001205 i->ARM64in.VNarrowV.dszBlg2 = dszBlg2;
1206 i->ARM64in.VNarrowV.dst = dst;
1207 i->ARM64in.VNarrowV.src = src;
1208 vassert(dszBlg2 == 0 || dszBlg2 == 1 || dszBlg2 == 2);
1209 return i;
1210}
sewardja6b61f02014-08-17 18:32:14 +00001211ARM64Instr* ARM64Instr_VShiftImmV ( ARM64VecShiftImmOp op,
sewardje520bb32014-02-17 11:00:53 +00001212 HReg dst, HReg src, UInt amt ) {
floriand8e3eca2015-03-13 12:46:49 +00001213 ARM64Instr* i = LibVEX_Alloc_inline(sizeof(ARM64Instr));
sewardje520bb32014-02-17 11:00:53 +00001214 i->tag = ARM64in_VShiftImmV;
1215 i->ARM64in.VShiftImmV.op = op;
1216 i->ARM64in.VShiftImmV.dst = dst;
1217 i->ARM64in.VShiftImmV.src = src;
1218 i->ARM64in.VShiftImmV.amt = amt;
sewardja97dddf2014-08-14 22:26:52 +00001219 UInt minSh = 0;
sewardje520bb32014-02-17 11:00:53 +00001220 UInt maxSh = 0;
1221 switch (op) {
sewardja97dddf2014-08-14 22:26:52 +00001222 /* For right shifts, the allowed shift amounts are 1 .. lane_size.
1223 For left shifts, the allowed shift amounts are 0 .. lane_size-1.
1224 */
sewardja6b61f02014-08-17 18:32:14 +00001225 case ARM64vecshi_USHR64x2: case ARM64vecshi_SSHR64x2:
1226 case ARM64vecshi_UQSHRN2SD: case ARM64vecshi_SQSHRN2SD:
1227 case ARM64vecshi_SQSHRUN2SD:
1228 case ARM64vecshi_UQRSHRN2SD: case ARM64vecshi_SQRSHRN2SD:
1229 case ARM64vecshi_SQRSHRUN2SD:
sewardja97dddf2014-08-14 22:26:52 +00001230 minSh = 1; maxSh = 64; break;
sewardja6b61f02014-08-17 18:32:14 +00001231 case ARM64vecshi_SHL64x2:
1232 case ARM64vecshi_UQSHL64x2: case ARM64vecshi_SQSHL64x2:
1233 case ARM64vecshi_SQSHLU64x2:
sewardja97dddf2014-08-14 22:26:52 +00001234 minSh = 0; maxSh = 63; break;
sewardja6b61f02014-08-17 18:32:14 +00001235 case ARM64vecshi_USHR32x4: case ARM64vecshi_SSHR32x4:
1236 case ARM64vecshi_UQSHRN4HS: case ARM64vecshi_SQSHRN4HS:
1237 case ARM64vecshi_SQSHRUN4HS:
1238 case ARM64vecshi_UQRSHRN4HS: case ARM64vecshi_SQRSHRN4HS:
1239 case ARM64vecshi_SQRSHRUN4HS:
sewardja97dddf2014-08-14 22:26:52 +00001240 minSh = 1; maxSh = 32; break;
sewardja6b61f02014-08-17 18:32:14 +00001241 case ARM64vecshi_SHL32x4:
1242 case ARM64vecshi_UQSHL32x4: case ARM64vecshi_SQSHL32x4:
1243 case ARM64vecshi_SQSHLU32x4:
sewardja97dddf2014-08-14 22:26:52 +00001244 minSh = 0; maxSh = 31; break;
sewardja6b61f02014-08-17 18:32:14 +00001245 case ARM64vecshi_USHR16x8: case ARM64vecshi_SSHR16x8:
1246 case ARM64vecshi_UQSHRN8BH: case ARM64vecshi_SQSHRN8BH:
1247 case ARM64vecshi_SQSHRUN8BH:
1248 case ARM64vecshi_UQRSHRN8BH: case ARM64vecshi_SQRSHRN8BH:
1249 case ARM64vecshi_SQRSHRUN8BH:
sewardja97dddf2014-08-14 22:26:52 +00001250 minSh = 1; maxSh = 16; break;
sewardja6b61f02014-08-17 18:32:14 +00001251 case ARM64vecshi_SHL16x8:
1252 case ARM64vecshi_UQSHL16x8: case ARM64vecshi_SQSHL16x8:
1253 case ARM64vecshi_SQSHLU16x8:
sewardja97dddf2014-08-14 22:26:52 +00001254 minSh = 0; maxSh = 15; break;
sewardja6b61f02014-08-17 18:32:14 +00001255 case ARM64vecshi_USHR8x16: case ARM64vecshi_SSHR8x16:
sewardja97dddf2014-08-14 22:26:52 +00001256 minSh = 1; maxSh = 8; break;
sewardja6b61f02014-08-17 18:32:14 +00001257 case ARM64vecshi_SHL8x16:
1258 case ARM64vecshi_UQSHL8x16: case ARM64vecshi_SQSHL8x16:
1259 case ARM64vecshi_SQSHLU8x16:
sewardja97dddf2014-08-14 22:26:52 +00001260 minSh = 0; maxSh = 7; break;
sewardje520bb32014-02-17 11:00:53 +00001261 default:
1262 vassert(0);
1263 }
1264 vassert(maxSh > 0);
sewardja97dddf2014-08-14 22:26:52 +00001265 vassert(amt >= minSh && amt <= maxSh);
sewardje520bb32014-02-17 11:00:53 +00001266 return i;
1267}
sewardjab33a7a2014-06-19 22:20:47 +00001268ARM64Instr* ARM64Instr_VExtV ( HReg dst, HReg srcLo, HReg srcHi, UInt amtB ) {
floriand8e3eca2015-03-13 12:46:49 +00001269 ARM64Instr* i = LibVEX_Alloc_inline(sizeof(ARM64Instr));
sewardjab33a7a2014-06-19 22:20:47 +00001270 i->tag = ARM64in_VExtV;
1271 i->ARM64in.VExtV.dst = dst;
1272 i->ARM64in.VExtV.srcLo = srcLo;
1273 i->ARM64in.VExtV.srcHi = srcHi;
1274 i->ARM64in.VExtV.amtB = amtB;
1275 vassert(amtB >= 1 && amtB <= 15);
1276 return i;
1277}
sewardjbbcf1882014-01-12 12:49:10 +00001278ARM64Instr* ARM64Instr_VImmQ (HReg rQ, UShort imm) {
floriand8e3eca2015-03-13 12:46:49 +00001279 ARM64Instr* i = LibVEX_Alloc_inline(sizeof(ARM64Instr));
sewardjbbcf1882014-01-12 12:49:10 +00001280 i->tag = ARM64in_VImmQ;
1281 i->ARM64in.VImmQ.rQ = rQ;
1282 i->ARM64in.VImmQ.imm = imm;
sewardj208a7762014-10-22 13:52:51 +00001283 /* Check that this is something that can actually be emitted. */
1284 switch (imm) {
1285 case 0x0000: case 0x0001: case 0x0003:
1286 case 0x000F: case 0x003F: case 0x00FF: case 0xFFFF:
1287 break;
1288 default:
1289 vassert(0);
1290 }
sewardjbbcf1882014-01-12 12:49:10 +00001291 return i;
1292}
1293ARM64Instr* ARM64Instr_VDfromX ( HReg rD, HReg rX ) {
floriand8e3eca2015-03-13 12:46:49 +00001294 ARM64Instr* i = LibVEX_Alloc_inline(sizeof(ARM64Instr));
sewardjbbcf1882014-01-12 12:49:10 +00001295 i->tag = ARM64in_VDfromX;
1296 i->ARM64in.VDfromX.rD = rD;
1297 i->ARM64in.VDfromX.rX = rX;
1298 return i;
1299}
sewardj12972182014-08-04 08:09:47 +00001300ARM64Instr* ARM64Instr_VQfromX ( HReg rQ, HReg rXlo ) {
floriand8e3eca2015-03-13 12:46:49 +00001301 ARM64Instr* i = LibVEX_Alloc_inline(sizeof(ARM64Instr));
sewardj12972182014-08-04 08:09:47 +00001302 i->tag = ARM64in_VQfromX;
1303 i->ARM64in.VQfromX.rQ = rQ;
1304 i->ARM64in.VQfromX.rXlo = rXlo;
1305 return i;
1306}
sewardjbbcf1882014-01-12 12:49:10 +00001307ARM64Instr* ARM64Instr_VQfromXX ( HReg rQ, HReg rXhi, HReg rXlo ) {
floriand8e3eca2015-03-13 12:46:49 +00001308 ARM64Instr* i = LibVEX_Alloc_inline(sizeof(ARM64Instr));
sewardjbbcf1882014-01-12 12:49:10 +00001309 i->tag = ARM64in_VQfromXX;
1310 i->ARM64in.VQfromXX.rQ = rQ;
1311 i->ARM64in.VQfromXX.rXhi = rXhi;
1312 i->ARM64in.VQfromXX.rXlo = rXlo;
1313 return i;
1314}
1315ARM64Instr* ARM64Instr_VXfromQ ( HReg rX, HReg rQ, UInt laneNo ) {
floriand8e3eca2015-03-13 12:46:49 +00001316 ARM64Instr* i = LibVEX_Alloc_inline(sizeof(ARM64Instr));
sewardjbbcf1882014-01-12 12:49:10 +00001317 i->tag = ARM64in_VXfromQ;
1318 i->ARM64in.VXfromQ.rX = rX;
1319 i->ARM64in.VXfromQ.rQ = rQ;
1320 i->ARM64in.VXfromQ.laneNo = laneNo;
1321 vassert(laneNo <= 1);
1322 return i;
1323}
sewardj85fbb022014-06-12 13:16:01 +00001324ARM64Instr* ARM64Instr_VXfromDorS ( HReg rX, HReg rDorS, Bool fromD ) {
floriand8e3eca2015-03-13 12:46:49 +00001325 ARM64Instr* i = LibVEX_Alloc_inline(sizeof(ARM64Instr));
sewardj85fbb022014-06-12 13:16:01 +00001326 i->tag = ARM64in_VXfromDorS;
1327 i->ARM64in.VXfromDorS.rX = rX;
1328 i->ARM64in.VXfromDorS.rDorS = rDorS;
1329 i->ARM64in.VXfromDorS.fromD = fromD;
1330 return i;
1331}
sewardjbbcf1882014-01-12 12:49:10 +00001332ARM64Instr* ARM64Instr_VMov ( UInt szB, HReg dst, HReg src ) {
floriand8e3eca2015-03-13 12:46:49 +00001333 ARM64Instr* i = LibVEX_Alloc_inline(sizeof(ARM64Instr));
sewardjbbcf1882014-01-12 12:49:10 +00001334 i->tag = ARM64in_VMov;
1335 i->ARM64in.VMov.szB = szB;
1336 i->ARM64in.VMov.dst = dst;
1337 i->ARM64in.VMov.src = src;
1338 switch (szB) {
1339 case 16:
1340 vassert(hregClass(src) == HRcVec128);
1341 vassert(hregClass(dst) == HRcVec128);
1342 break;
1343 case 8:
1344 vassert(hregClass(src) == HRcFlt64);
1345 vassert(hregClass(dst) == HRcFlt64);
1346 break;
1347 default:
1348 vpanic("ARM64Instr_VMov");
1349 }
1350 return i;
1351}
sewardjbbcf1882014-01-12 12:49:10 +00001352ARM64Instr* ARM64Instr_EvCheck ( ARM64AMode* amCounter,
1353 ARM64AMode* amFailAddr ) {
floriand8e3eca2015-03-13 12:46:49 +00001354 ARM64Instr* i = LibVEX_Alloc_inline(sizeof(ARM64Instr));
sewardjbbcf1882014-01-12 12:49:10 +00001355 i->tag = ARM64in_EvCheck;
1356 i->ARM64in.EvCheck.amCounter = amCounter;
1357 i->ARM64in.EvCheck.amFailAddr = amFailAddr;
1358 return i;
1359}
sewardj0ad37a92014-08-29 21:58:03 +00001360ARM64Instr* ARM64Instr_ProfInc ( void ) {
floriand8e3eca2015-03-13 12:46:49 +00001361 ARM64Instr* i = LibVEX_Alloc_inline(sizeof(ARM64Instr));
sewardj0ad37a92014-08-29 21:58:03 +00001362 i->tag = ARM64in_ProfInc;
1363 return i;
1364}
sewardjbbcf1882014-01-12 12:49:10 +00001365
sewardjbbcf1882014-01-12 12:49:10 +00001366/* ... */
1367
floriand8c64e02014-10-08 08:54:44 +00001368void ppARM64Instr ( const ARM64Instr* i ) {
sewardjbbcf1882014-01-12 12:49:10 +00001369 switch (i->tag) {
1370 case ARM64in_Arith:
1371 vex_printf("%s ", i->ARM64in.Arith.isAdd ? "add" : "sub");
1372 ppHRegARM64(i->ARM64in.Arith.dst);
1373 vex_printf(", ");
1374 ppHRegARM64(i->ARM64in.Arith.argL);
1375 vex_printf(", ");
1376 ppARM64RIA(i->ARM64in.Arith.argR);
1377 return;
1378 case ARM64in_Cmp:
1379 vex_printf("cmp%s ", i->ARM64in.Cmp.is64 ? " " : "(w)" );
1380 ppHRegARM64(i->ARM64in.Cmp.argL);
1381 vex_printf(", ");
1382 ppARM64RIA(i->ARM64in.Cmp.argR);
1383 return;
1384 case ARM64in_Logic:
1385 vex_printf("%s ", showARM64LogicOp(i->ARM64in.Logic.op));
1386 ppHRegARM64(i->ARM64in.Logic.dst);
1387 vex_printf(", ");
1388 ppHRegARM64(i->ARM64in.Logic.argL);
1389 vex_printf(", ");
1390 ppARM64RIL(i->ARM64in.Logic.argR);
1391 return;
1392 case ARM64in_Test:
1393 vex_printf("tst ");
1394 ppHRegARM64(i->ARM64in.Test.argL);
1395 vex_printf(", ");
1396 ppARM64RIL(i->ARM64in.Test.argR);
1397 return;
1398 case ARM64in_Shift:
1399 vex_printf("%s ", showARM64ShiftOp(i->ARM64in.Shift.op));
1400 ppHRegARM64(i->ARM64in.Shift.dst);
1401 vex_printf(", ");
1402 ppHRegARM64(i->ARM64in.Shift.argL);
1403 vex_printf(", ");
1404 ppARM64RI6(i->ARM64in.Shift.argR);
1405 return;
1406 case ARM64in_Unary:
1407 vex_printf("%s ", showARM64UnaryOp(i->ARM64in.Unary.op));
1408 ppHRegARM64(i->ARM64in.Unary.dst);
1409 vex_printf(", ");
1410 ppHRegARM64(i->ARM64in.Unary.src);
1411 return;
1412 case ARM64in_MovI:
1413 vex_printf("mov ");
1414 ppHRegARM64(i->ARM64in.MovI.dst);
1415 vex_printf(", ");
1416 ppHRegARM64(i->ARM64in.MovI.src);
1417 return;
1418 case ARM64in_Imm64:
1419 vex_printf("imm64 ");
1420 ppHRegARM64(i->ARM64in.Imm64.dst);
1421 vex_printf(", 0x%llx", i->ARM64in.Imm64.imm64);
1422 return;
1423 case ARM64in_LdSt64:
1424 if (i->ARM64in.LdSt64.isLoad) {
1425 vex_printf("ldr ");
1426 ppHRegARM64(i->ARM64in.LdSt64.rD);
1427 vex_printf(", ");
1428 ppARM64AMode(i->ARM64in.LdSt64.amode);
1429 } else {
1430 vex_printf("str ");
1431 ppARM64AMode(i->ARM64in.LdSt64.amode);
1432 vex_printf(", ");
1433 ppHRegARM64(i->ARM64in.LdSt64.rD);
1434 }
1435 return;
1436 case ARM64in_LdSt32:
1437 if (i->ARM64in.LdSt32.isLoad) {
1438 vex_printf("ldruw ");
1439 ppHRegARM64(i->ARM64in.LdSt32.rD);
1440 vex_printf(", ");
1441 ppARM64AMode(i->ARM64in.LdSt32.amode);
1442 } else {
1443 vex_printf("strw ");
1444 ppARM64AMode(i->ARM64in.LdSt32.amode);
1445 vex_printf(", ");
1446 ppHRegARM64(i->ARM64in.LdSt32.rD);
1447 }
1448 return;
1449 case ARM64in_LdSt16:
1450 if (i->ARM64in.LdSt16.isLoad) {
1451 vex_printf("ldruh ");
1452 ppHRegARM64(i->ARM64in.LdSt16.rD);
1453 vex_printf(", ");
1454 ppARM64AMode(i->ARM64in.LdSt16.amode);
1455 } else {
1456 vex_printf("strh ");
1457 ppARM64AMode(i->ARM64in.LdSt16.amode);
1458 vex_printf(", ");
1459 ppHRegARM64(i->ARM64in.LdSt16.rD);
1460 }
1461 return;
1462 case ARM64in_LdSt8:
1463 if (i->ARM64in.LdSt8.isLoad) {
1464 vex_printf("ldrub ");
1465 ppHRegARM64(i->ARM64in.LdSt8.rD);
1466 vex_printf(", ");
1467 ppARM64AMode(i->ARM64in.LdSt8.amode);
1468 } else {
1469 vex_printf("strb ");
1470 ppARM64AMode(i->ARM64in.LdSt8.amode);
1471 vex_printf(", ");
1472 ppHRegARM64(i->ARM64in.LdSt8.rD);
1473 }
1474 return;
1475 case ARM64in_XDirect:
1476 vex_printf("(xDirect) ");
1477 vex_printf("if (%%pstate.%s) { ",
1478 showARM64CondCode(i->ARM64in.XDirect.cond));
1479 vex_printf("imm64 x9,0x%llx; ", i->ARM64in.XDirect.dstGA);
1480 vex_printf("str x9,");
1481 ppARM64AMode(i->ARM64in.XDirect.amPC);
1482 vex_printf("; imm64-exactly4 x9,$disp_cp_chain_me_to_%sEP; ",
1483 i->ARM64in.XDirect.toFastEP ? "fast" : "slow");
1484 vex_printf("blr x9 }");
1485 return;
1486 case ARM64in_XIndir:
1487 vex_printf("(xIndir) ");
1488 vex_printf("if (%%pstate.%s) { ",
1489 showARM64CondCode(i->ARM64in.XIndir.cond));
1490 vex_printf("str ");
1491 ppHRegARM64(i->ARM64in.XIndir.dstGA);
1492 vex_printf(",");
1493 ppARM64AMode(i->ARM64in.XIndir.amPC);
1494 vex_printf("; imm64 x9,$disp_cp_xindir; ");
1495 vex_printf("br x9 }");
1496 return;
1497 case ARM64in_XAssisted:
1498 vex_printf("(xAssisted) ");
1499 vex_printf("if (%%pstate.%s) { ",
1500 showARM64CondCode(i->ARM64in.XAssisted.cond));
1501 vex_printf("str ");
1502 ppHRegARM64(i->ARM64in.XAssisted.dstGA);
1503 vex_printf(",");
1504 ppARM64AMode(i->ARM64in.XAssisted.amPC);
1505 vex_printf("; movw x21,$IRJumpKind_to_TRCVAL(%d); ",
1506 (Int)i->ARM64in.XAssisted.jk);
1507 vex_printf("imm64 x9,$disp_cp_xassisted; ");
1508 vex_printf("br x9 }");
1509 return;
1510 case ARM64in_CSel:
1511 vex_printf("csel ");
1512 ppHRegARM64(i->ARM64in.CSel.dst);
1513 vex_printf(", ");
1514 ppHRegARM64(i->ARM64in.CSel.argL);
1515 vex_printf(", ");
1516 ppHRegARM64(i->ARM64in.CSel.argR);
1517 vex_printf(", %s", showARM64CondCode(i->ARM64in.CSel.cond));
1518 return;
1519 case ARM64in_Call:
1520 vex_printf("call%s ",
1521 i->ARM64in.Call.cond==ARM64cc_AL
1522 ? " " : showARM64CondCode(i->ARM64in.Call.cond));
florian93a09742015-01-07 20:14:48 +00001523 vex_printf("0x%llx [nArgRegs=%d, ",
sewardjbbcf1882014-01-12 12:49:10 +00001524 i->ARM64in.Call.target, i->ARM64in.Call.nArgRegs);
1525 ppRetLoc(i->ARM64in.Call.rloc);
1526 vex_printf("]");
1527 return;
1528 case ARM64in_AddToSP: {
1529 Int simm = i->ARM64in.AddToSP.simm;
1530 vex_printf("%s xsp, xsp, #%d", simm < 0 ? "sub" : "add",
1531 simm < 0 ? -simm : simm);
1532 return;
1533 }
1534 case ARM64in_FromSP:
1535 vex_printf("mov ");
1536 ppHRegARM64(i->ARM64in.FromSP.dst);
1537 vex_printf(", xsp");
1538 return;
1539 case ARM64in_Mul:
1540 vex_printf("%s ", showARM64MulOp(i->ARM64in.Mul.op));
1541 ppHRegARM64(i->ARM64in.Mul.dst);
1542 vex_printf(", ");
1543 ppHRegARM64(i->ARM64in.Mul.argL);
1544 vex_printf(", ");
1545 ppHRegARM64(i->ARM64in.Mul.argR);
1546 return;
sewardj7d009132014-02-20 17:43:38 +00001547
1548 case ARM64in_LdrEX: {
1549 const HChar* sz = " ";
1550 switch (i->ARM64in.LdrEX.szB) {
1551 case 1: sz = "b"; break;
1552 case 2: sz = "h"; break;
1553 case 4: case 8: break;
1554 default: vassert(0);
1555 }
1556 vex_printf("ldxr%s %c2, [x4]",
1557 sz, i->ARM64in.LdrEX.szB == 8 ? 'x' : 'w');
1558 return;
1559 }
1560 case ARM64in_StrEX: {
1561 const HChar* sz = " ";
1562 switch (i->ARM64in.StrEX.szB) {
1563 case 1: sz = "b"; break;
1564 case 2: sz = "h"; break;
1565 case 4: case 8: break;
1566 default: vassert(0);
1567 }
1568 vex_printf("stxr%s w0, %c2, [x4]",
1569 sz, i->ARM64in.StrEX.szB == 8 ? 'x' : 'w');
1570 return;
1571 }
1572 case ARM64in_MFence:
1573 vex_printf("(mfence) dsb sy; dmb sy; isb");
1574 return;
Elliott Hughesa0664b92017-04-18 17:46:52 -07001575 case ARM64in_ClrEX:
1576 vex_printf("clrex #15");
1577 return;
sewardj400d6b92015-03-30 09:01:51 +00001578 case ARM64in_VLdStH:
1579 if (i->ARM64in.VLdStH.isLoad) {
1580 vex_printf("ldr ");
1581 ppHRegARM64asHreg(i->ARM64in.VLdStH.hD);
1582 vex_printf(", %u(", i->ARM64in.VLdStH.uimm12);
1583 ppHRegARM64(i->ARM64in.VLdStH.rN);
1584 vex_printf(")");
1585 } else {
1586 vex_printf("str ");
1587 vex_printf("%u(", i->ARM64in.VLdStH.uimm12);
1588 ppHRegARM64(i->ARM64in.VLdStH.rN);
1589 vex_printf("), ");
1590 ppHRegARM64asHreg(i->ARM64in.VLdStH.hD);
1591 }
1592 return;
sewardjbbcf1882014-01-12 12:49:10 +00001593 case ARM64in_VLdStS:
1594 if (i->ARM64in.VLdStS.isLoad) {
1595 vex_printf("ldr ");
1596 ppHRegARM64asSreg(i->ARM64in.VLdStS.sD);
1597 vex_printf(", %u(", i->ARM64in.VLdStS.uimm12);
1598 ppHRegARM64(i->ARM64in.VLdStS.rN);
1599 vex_printf(")");
1600 } else {
1601 vex_printf("str ");
1602 vex_printf("%u(", i->ARM64in.VLdStS.uimm12);
1603 ppHRegARM64(i->ARM64in.VLdStS.rN);
1604 vex_printf("), ");
1605 ppHRegARM64asSreg(i->ARM64in.VLdStS.sD);
1606 }
1607 return;
1608 case ARM64in_VLdStD:
1609 if (i->ARM64in.VLdStD.isLoad) {
1610 vex_printf("ldr ");
1611 ppHRegARM64(i->ARM64in.VLdStD.dD);
1612 vex_printf(", %u(", i->ARM64in.VLdStD.uimm12);
1613 ppHRegARM64(i->ARM64in.VLdStD.rN);
1614 vex_printf(")");
1615 } else {
1616 vex_printf("str ");
1617 vex_printf("%u(", i->ARM64in.VLdStD.uimm12);
1618 ppHRegARM64(i->ARM64in.VLdStD.rN);
1619 vex_printf("), ");
1620 ppHRegARM64(i->ARM64in.VLdStD.dD);
1621 }
1622 return;
1623 case ARM64in_VLdStQ:
1624 if (i->ARM64in.VLdStQ.isLoad)
1625 vex_printf("ld1.2d {");
1626 else
1627 vex_printf("st1.2d {");
1628 ppHRegARM64(i->ARM64in.VLdStQ.rQ);
1629 vex_printf("}, [");
1630 ppHRegARM64(i->ARM64in.VLdStQ.rN);
1631 vex_printf("]");
1632 return;
1633 case ARM64in_VCvtI2F: {
1634 HChar syn = '?';
1635 UInt fszB = 0;
1636 UInt iszB = 0;
1637 characteriseARM64CvtOp(&syn, &fszB, &iszB, i->ARM64in.VCvtI2F.how);
1638 vex_printf("%ccvtf ", syn);
1639 ppHRegARM64(i->ARM64in.VCvtI2F.rD);
1640 vex_printf("(%c-reg), ", fszB == 4 ? 'S' : 'D');
1641 ppHRegARM64(i->ARM64in.VCvtI2F.rS);
1642 vex_printf("(%c-reg)", iszB == 4 ? 'W' : 'X');
1643 return;
1644 }
1645 case ARM64in_VCvtF2I: {
1646 HChar syn = '?';
1647 UInt fszB = 0;
1648 UInt iszB = 0;
1649 HChar rmo = '?';
1650 characteriseARM64CvtOp(&syn, &fszB, &iszB, i->ARM64in.VCvtF2I.how);
1651 UChar armRM = i->ARM64in.VCvtF2I.armRM;
1652 if (armRM < 4) rmo = "npmz"[armRM];
1653 vex_printf("fcvt%c%c ", rmo, syn);
1654 ppHRegARM64(i->ARM64in.VCvtF2I.rD);
1655 vex_printf("(%c-reg), ", iszB == 4 ? 'W' : 'X');
1656 ppHRegARM64(i->ARM64in.VCvtF2I.rS);
1657 vex_printf("(%c-reg)", fszB == 4 ? 'S' : 'D');
1658 return;
1659 }
1660 case ARM64in_VCvtSD:
1661 vex_printf("fcvt%s ", i->ARM64in.VCvtSD.sToD ? "s2d" : "d2s");
1662 if (i->ARM64in.VCvtSD.sToD) {
1663 ppHRegARM64(i->ARM64in.VCvtSD.dst);
1664 vex_printf(", ");
1665 ppHRegARM64asSreg(i->ARM64in.VCvtSD.src);
1666 } else {
1667 ppHRegARM64asSreg(i->ARM64in.VCvtSD.dst);
1668 vex_printf(", ");
1669 ppHRegARM64(i->ARM64in.VCvtSD.src);
1670 }
1671 return;
sewardj400d6b92015-03-30 09:01:51 +00001672 case ARM64in_VCvtHS:
1673 vex_printf("fcvt%s ", i->ARM64in.VCvtHS.hToS ? "h2s" : "s2h");
1674 if (i->ARM64in.VCvtHS.hToS) {
1675 ppHRegARM64asSreg(i->ARM64in.VCvtHS.dst);
1676 vex_printf(", ");
1677 ppHRegARM64asHreg(i->ARM64in.VCvtHS.src);
1678 } else {
1679 ppHRegARM64asHreg(i->ARM64in.VCvtHS.dst);
1680 vex_printf(", ");
1681 ppHRegARM64asSreg(i->ARM64in.VCvtHS.src);
1682 }
1683 return;
1684 case ARM64in_VCvtHD:
1685 vex_printf("fcvt%s ", i->ARM64in.VCvtHD.hToD ? "h2d" : "d2h");
1686 if (i->ARM64in.VCvtHD.hToD) {
1687 ppHRegARM64(i->ARM64in.VCvtHD.dst);
1688 vex_printf(", ");
1689 ppHRegARM64asHreg(i->ARM64in.VCvtHD.src);
1690 } else {
1691 ppHRegARM64asHreg(i->ARM64in.VCvtHD.dst);
1692 vex_printf(", ");
1693 ppHRegARM64(i->ARM64in.VCvtHD.src);
1694 }
1695 return;
sewardjbbcf1882014-01-12 12:49:10 +00001696 case ARM64in_VUnaryD:
1697 vex_printf("f%s ", showARM64FpUnaryOp(i->ARM64in.VUnaryD.op));
1698 ppHRegARM64(i->ARM64in.VUnaryD.dst);
1699 vex_printf(", ");
1700 ppHRegARM64(i->ARM64in.VUnaryD.src);
1701 return;
1702 case ARM64in_VUnaryS:
1703 vex_printf("f%s ", showARM64FpUnaryOp(i->ARM64in.VUnaryS.op));
1704 ppHRegARM64asSreg(i->ARM64in.VUnaryS.dst);
1705 vex_printf(", ");
1706 ppHRegARM64asSreg(i->ARM64in.VUnaryS.src);
1707 return;
1708 case ARM64in_VBinD:
1709 vex_printf("f%s ", showARM64FpBinOp(i->ARM64in.VBinD.op));
1710 ppHRegARM64(i->ARM64in.VBinD.dst);
1711 vex_printf(", ");
1712 ppHRegARM64(i->ARM64in.VBinD.argL);
1713 vex_printf(", ");
1714 ppHRegARM64(i->ARM64in.VBinD.argR);
1715 return;
1716 case ARM64in_VBinS:
1717 vex_printf("f%s ", showARM64FpBinOp(i->ARM64in.VBinS.op));
1718 ppHRegARM64asSreg(i->ARM64in.VBinS.dst);
1719 vex_printf(", ");
1720 ppHRegARM64asSreg(i->ARM64in.VBinS.argL);
1721 vex_printf(", ");
1722 ppHRegARM64asSreg(i->ARM64in.VBinS.argR);
1723 return;
1724 case ARM64in_VCmpD:
1725 vex_printf("fcmp ");
1726 ppHRegARM64(i->ARM64in.VCmpD.argL);
1727 vex_printf(", ");
1728 ppHRegARM64(i->ARM64in.VCmpD.argR);
1729 return;
1730 case ARM64in_VCmpS:
1731 vex_printf("fcmp ");
1732 ppHRegARM64asSreg(i->ARM64in.VCmpS.argL);
1733 vex_printf(", ");
1734 ppHRegARM64asSreg(i->ARM64in.VCmpS.argR);
1735 return;
sewardje23ec112014-11-15 16:07:14 +00001736 case ARM64in_VFCSel: {
1737 void (*ppHRegARM64fp)(HReg)
1738 = (i->ARM64in.VFCSel.isD ? ppHRegARM64 : ppHRegARM64asSreg);
1739 vex_printf("fcsel ");
1740 ppHRegARM64fp(i->ARM64in.VFCSel.dst);
1741 vex_printf(", ");
1742 ppHRegARM64fp(i->ARM64in.VFCSel.argL);
1743 vex_printf(", ");
1744 ppHRegARM64fp(i->ARM64in.VFCSel.argR);
1745 vex_printf(", %s", showARM64CondCode(i->ARM64in.VFCSel.cond));
1746 return;
1747 }
sewardjbbcf1882014-01-12 12:49:10 +00001748 case ARM64in_FPCR:
1749 if (i->ARM64in.FPCR.toFPCR) {
1750 vex_printf("msr fpcr, ");
1751 ppHRegARM64(i->ARM64in.FPCR.iReg);
1752 } else {
1753 vex_printf("mrs ");
1754 ppHRegARM64(i->ARM64in.FPCR.iReg);
1755 vex_printf(", fpcr");
1756 }
1757 return;
sewardj12972182014-08-04 08:09:47 +00001758 case ARM64in_FPSR:
1759 if (i->ARM64in.FPSR.toFPSR) {
1760 vex_printf("msr fpsr, ");
1761 ppHRegARM64(i->ARM64in.FPSR.iReg);
1762 } else {
1763 vex_printf("mrs ");
1764 ppHRegARM64(i->ARM64in.FPSR.iReg);
1765 vex_printf(", fpsr");
1766 }
1767 return;
sewardj606c4ba2014-01-26 19:11:14 +00001768 case ARM64in_VBinV: {
1769 const HChar* nm = "??";
1770 const HChar* ar = "??";
1771 showARM64VecBinOp(&nm, &ar, i->ARM64in.VBinV.op);
sewardj12972182014-08-04 08:09:47 +00001772 vex_printf("%s ", nm);
sewardj606c4ba2014-01-26 19:11:14 +00001773 ppHRegARM64(i->ARM64in.VBinV.dst);
1774 vex_printf(".%s, ", ar);
1775 ppHRegARM64(i->ARM64in.VBinV.argL);
1776 vex_printf(".%s, ", ar);
1777 ppHRegARM64(i->ARM64in.VBinV.argR);
1778 vex_printf(".%s", ar);
1779 return;
1780 }
sewardjf7003bc2014-08-18 12:28:02 +00001781 case ARM64in_VModifyV: {
1782 const HChar* nm = "??";
1783 const HChar* ar = "??";
1784 showARM64VecModifyOp(&nm, &ar, i->ARM64in.VModifyV.op);
1785 vex_printf("%s ", nm);
1786 ppHRegARM64(i->ARM64in.VModifyV.mod);
1787 vex_printf(".%s, ", ar);
1788 ppHRegARM64(i->ARM64in.VModifyV.arg);
1789 vex_printf(".%s", ar);
1790 return;
1791 }
sewardjfab09142014-02-10 10:28:13 +00001792 case ARM64in_VUnaryV: {
1793 const HChar* nm = "??";
1794 const HChar* ar = "??";
1795 showARM64VecUnaryOp(&nm, &ar, i->ARM64in.VUnaryV.op);
1796 vex_printf("%s ", nm);
1797 ppHRegARM64(i->ARM64in.VUnaryV.dst);
1798 vex_printf(".%s, ", ar);
1799 ppHRegARM64(i->ARM64in.VUnaryV.arg);
1800 vex_printf(".%s", ar);
1801 return;
1802 }
sewardj606c4ba2014-01-26 19:11:14 +00001803 case ARM64in_VNarrowV: {
1804 UInt dszBlg2 = i->ARM64in.VNarrowV.dszBlg2;
1805 const HChar* darr[3] = { "8b", "4h", "2s" };
1806 const HChar* sarr[3] = { "8h", "4s", "2d" };
sewardjecedd982014-08-11 14:02:47 +00001807 const HChar* nm = showARM64VecNarrowOp(i->ARM64in.VNarrowV.op);
1808 vex_printf("%s ", nm);
sewardj606c4ba2014-01-26 19:11:14 +00001809 ppHRegARM64(i->ARM64in.VNarrowV.dst);
1810 vex_printf(".%s, ", dszBlg2 < 3 ? darr[dszBlg2] : "??");
1811 ppHRegARM64(i->ARM64in.VNarrowV.src);
1812 vex_printf(".%s", dszBlg2 < 3 ? sarr[dszBlg2] : "??");
1813 return;
1814 }
sewardje520bb32014-02-17 11:00:53 +00001815 case ARM64in_VShiftImmV: {
1816 const HChar* nm = "??";
1817 const HChar* ar = "??";
sewardja6b61f02014-08-17 18:32:14 +00001818 showARM64VecShiftImmOp(&nm, &ar, i->ARM64in.VShiftImmV.op);
sewardje520bb32014-02-17 11:00:53 +00001819 vex_printf("%s ", nm);
1820 ppHRegARM64(i->ARM64in.VShiftImmV.dst);
1821 vex_printf(".%s, ", ar);
1822 ppHRegARM64(i->ARM64in.VShiftImmV.src);
1823 vex_printf(".%s, #%u", ar, i->ARM64in.VShiftImmV.amt);
1824 return;
1825 }
sewardjab33a7a2014-06-19 22:20:47 +00001826 case ARM64in_VExtV: {
1827 vex_printf("ext ");
1828 ppHRegARM64(i->ARM64in.VExtV.dst);
1829 vex_printf(".16b, ");
1830 ppHRegARM64(i->ARM64in.VExtV.srcLo);
1831 vex_printf(".16b, ");
1832 ppHRegARM64(i->ARM64in.VExtV.srcHi);
1833 vex_printf(".16b, #%u", i->ARM64in.VExtV.amtB);
1834 return;
1835 }
sewardjbbcf1882014-01-12 12:49:10 +00001836 case ARM64in_VImmQ:
1837 vex_printf("qimm ");
1838 ppHRegARM64(i->ARM64in.VImmQ.rQ);
1839 vex_printf(", Bits16toBytes16(0x%x)", (UInt)i->ARM64in.VImmQ.imm);
1840 return;
1841 case ARM64in_VDfromX:
1842 vex_printf("fmov ");
1843 ppHRegARM64(i->ARM64in.VDfromX.rD);
1844 vex_printf(", ");
1845 ppHRegARM64(i->ARM64in.VDfromX.rX);
1846 return;
sewardj12972182014-08-04 08:09:47 +00001847 case ARM64in_VQfromX:
1848 vex_printf("fmov ");
1849 ppHRegARM64(i->ARM64in.VQfromX.rQ);
1850 vex_printf(".d[0], ");
1851 ppHRegARM64(i->ARM64in.VQfromX.rXlo);
1852 return;
sewardjbbcf1882014-01-12 12:49:10 +00001853 case ARM64in_VQfromXX:
1854 vex_printf("qFromXX ");
1855 ppHRegARM64(i->ARM64in.VQfromXX.rQ);
1856 vex_printf(", ");
1857 ppHRegARM64(i->ARM64in.VQfromXX.rXhi);
1858 vex_printf(", ");
1859 ppHRegARM64(i->ARM64in.VQfromXX.rXlo);
1860 return;
1861 case ARM64in_VXfromQ:
sewardj85fbb022014-06-12 13:16:01 +00001862 vex_printf("fmov ");
sewardjbbcf1882014-01-12 12:49:10 +00001863 ppHRegARM64(i->ARM64in.VXfromQ.rX);
1864 vex_printf(", ");
1865 ppHRegARM64(i->ARM64in.VXfromQ.rQ);
1866 vex_printf(".d[%u]", i->ARM64in.VXfromQ.laneNo);
1867 return;
sewardj85fbb022014-06-12 13:16:01 +00001868 case ARM64in_VXfromDorS:
1869 vex_printf("fmov ");
1870 ppHRegARM64(i->ARM64in.VXfromDorS.rX);
1871 vex_printf("(%c-reg), ", i->ARM64in.VXfromDorS.fromD ? 'X':'W');
1872 ppHRegARM64(i->ARM64in.VXfromDorS.rDorS);
1873 vex_printf("(%c-reg)", i->ARM64in.VXfromDorS.fromD ? 'D' : 'S');
1874 return;
sewardjbbcf1882014-01-12 12:49:10 +00001875 case ARM64in_VMov: {
1876 UChar aux = '?';
1877 switch (i->ARM64in.VMov.szB) {
1878 case 16: aux = 'q'; break;
1879 case 8: aux = 'd'; break;
1880 case 4: aux = 's'; break;
1881 default: break;
1882 }
1883 vex_printf("mov(%c) ", aux);
1884 ppHRegARM64(i->ARM64in.VMov.dst);
1885 vex_printf(", ");
1886 ppHRegARM64(i->ARM64in.VMov.src);
1887 return;
sewardj0ad37a92014-08-29 21:58:03 +00001888 }
sewardjbbcf1882014-01-12 12:49:10 +00001889 case ARM64in_EvCheck:
1890 vex_printf("(evCheck) ldr w9,");
1891 ppARM64AMode(i->ARM64in.EvCheck.amCounter);
1892 vex_printf("; subs w9,w9,$1; str w9,");
1893 ppARM64AMode(i->ARM64in.EvCheck.amCounter);
1894 vex_printf("; bpl nofail; ldr x9,");
1895 ppARM64AMode(i->ARM64in.EvCheck.amFailAddr);
1896 vex_printf("; br x9; nofail:");
1897 return;
sewardj0ad37a92014-08-29 21:58:03 +00001898 case ARM64in_ProfInc:
1899 vex_printf("(profInc) imm64-fixed4 x9,$NotKnownYet; "
1900 "ldr x8,[x9]; add x8,x8,#1, str x8,[x9]");
1901 return;
sewardjbbcf1882014-01-12 12:49:10 +00001902 default:
1903 vex_printf("ppARM64Instr: unhandled case (tag %d)", (Int)i->tag);
1904 vpanic("ppARM64Instr(1)");
1905 return;
1906 }
1907}
1908
1909
1910/* --------- Helpers for register allocation. --------- */
1911
floriand8c64e02014-10-08 08:54:44 +00001912void getRegUsage_ARM64Instr ( HRegUsage* u, const ARM64Instr* i, Bool mode64 )
sewardjbbcf1882014-01-12 12:49:10 +00001913{
1914 vassert(mode64 == True);
1915 initHRegUsage(u);
1916 switch (i->tag) {
1917 case ARM64in_Arith:
1918 addHRegUse(u, HRmWrite, i->ARM64in.Arith.dst);
1919 addHRegUse(u, HRmRead, i->ARM64in.Arith.argL);
1920 addRegUsage_ARM64RIA(u, i->ARM64in.Arith.argR);
1921 return;
1922 case ARM64in_Cmp:
1923 addHRegUse(u, HRmRead, i->ARM64in.Cmp.argL);
1924 addRegUsage_ARM64RIA(u, i->ARM64in.Cmp.argR);
1925 return;
1926 case ARM64in_Logic:
1927 addHRegUse(u, HRmWrite, i->ARM64in.Logic.dst);
1928 addHRegUse(u, HRmRead, i->ARM64in.Logic.argL);
1929 addRegUsage_ARM64RIL(u, i->ARM64in.Logic.argR);
1930 return;
1931 case ARM64in_Test:
1932 addHRegUse(u, HRmRead, i->ARM64in.Test.argL);
1933 addRegUsage_ARM64RIL(u, i->ARM64in.Test.argR);
1934 return;
1935 case ARM64in_Shift:
1936 addHRegUse(u, HRmWrite, i->ARM64in.Shift.dst);
1937 addHRegUse(u, HRmRead, i->ARM64in.Shift.argL);
1938 addRegUsage_ARM64RI6(u, i->ARM64in.Shift.argR);
1939 return;
1940 case ARM64in_Unary:
1941 addHRegUse(u, HRmWrite, i->ARM64in.Unary.dst);
1942 addHRegUse(u, HRmRead, i->ARM64in.Unary.src);
1943 return;
1944 case ARM64in_MovI:
1945 addHRegUse(u, HRmWrite, i->ARM64in.MovI.dst);
1946 addHRegUse(u, HRmRead, i->ARM64in.MovI.src);
1947 return;
1948 case ARM64in_Imm64:
1949 addHRegUse(u, HRmWrite, i->ARM64in.Imm64.dst);
1950 return;
1951 case ARM64in_LdSt64:
1952 addRegUsage_ARM64AMode(u, i->ARM64in.LdSt64.amode);
1953 if (i->ARM64in.LdSt64.isLoad) {
1954 addHRegUse(u, HRmWrite, i->ARM64in.LdSt64.rD);
1955 } else {
1956 addHRegUse(u, HRmRead, i->ARM64in.LdSt64.rD);
1957 }
1958 return;
1959 case ARM64in_LdSt32:
1960 addRegUsage_ARM64AMode(u, i->ARM64in.LdSt32.amode);
1961 if (i->ARM64in.LdSt32.isLoad) {
1962 addHRegUse(u, HRmWrite, i->ARM64in.LdSt32.rD);
1963 } else {
1964 addHRegUse(u, HRmRead, i->ARM64in.LdSt32.rD);
1965 }
1966 return;
1967 case ARM64in_LdSt16:
1968 addRegUsage_ARM64AMode(u, i->ARM64in.LdSt16.amode);
1969 if (i->ARM64in.LdSt16.isLoad) {
1970 addHRegUse(u, HRmWrite, i->ARM64in.LdSt16.rD);
1971 } else {
1972 addHRegUse(u, HRmRead, i->ARM64in.LdSt16.rD);
1973 }
1974 return;
1975 case ARM64in_LdSt8:
1976 addRegUsage_ARM64AMode(u, i->ARM64in.LdSt8.amode);
1977 if (i->ARM64in.LdSt8.isLoad) {
1978 addHRegUse(u, HRmWrite, i->ARM64in.LdSt8.rD);
1979 } else {
1980 addHRegUse(u, HRmRead, i->ARM64in.LdSt8.rD);
1981 }
1982 return;
1983 /* XDirect/XIndir/XAssisted are also a bit subtle. They
1984 conditionally exit the block. Hence we only need to list (1)
1985 the registers that they read, and (2) the registers that they
1986 write in the case where the block is not exited. (2) is
1987 empty, hence only (1) is relevant here. */
1988 case ARM64in_XDirect:
1989 addRegUsage_ARM64AMode(u, i->ARM64in.XDirect.amPC);
1990 return;
1991 case ARM64in_XIndir:
1992 addHRegUse(u, HRmRead, i->ARM64in.XIndir.dstGA);
1993 addRegUsage_ARM64AMode(u, i->ARM64in.XIndir.amPC);
1994 return;
1995 case ARM64in_XAssisted:
1996 addHRegUse(u, HRmRead, i->ARM64in.XAssisted.dstGA);
1997 addRegUsage_ARM64AMode(u, i->ARM64in.XAssisted.amPC);
1998 return;
1999 case ARM64in_CSel:
2000 addHRegUse(u, HRmWrite, i->ARM64in.CSel.dst);
2001 addHRegUse(u, HRmRead, i->ARM64in.CSel.argL);
2002 addHRegUse(u, HRmRead, i->ARM64in.CSel.argR);
2003 return;
2004 case ARM64in_Call:
2005 /* logic and comments copied/modified from x86 back end */
2006 /* This is a bit subtle. */
2007 /* First off, claim it trashes all the caller-saved regs
2008 which fall within the register allocator's jurisdiction.
sewardj76ac4762014-06-20 08:30:21 +00002009 These I believe to be x0 to x7 and the 128-bit vector
2010 registers in use, q16 .. q20. */
sewardjbbcf1882014-01-12 12:49:10 +00002011 addHRegUse(u, HRmWrite, hregARM64_X0());
2012 addHRegUse(u, HRmWrite, hregARM64_X1());
2013 addHRegUse(u, HRmWrite, hregARM64_X2());
2014 addHRegUse(u, HRmWrite, hregARM64_X3());
2015 addHRegUse(u, HRmWrite, hregARM64_X4());
2016 addHRegUse(u, HRmWrite, hregARM64_X5());
2017 addHRegUse(u, HRmWrite, hregARM64_X6());
2018 addHRegUse(u, HRmWrite, hregARM64_X7());
2019 addHRegUse(u, HRmWrite, hregARM64_Q16());
2020 addHRegUse(u, HRmWrite, hregARM64_Q17());
2021 addHRegUse(u, HRmWrite, hregARM64_Q18());
sewardj76ac4762014-06-20 08:30:21 +00002022 addHRegUse(u, HRmWrite, hregARM64_Q19());
2023 addHRegUse(u, HRmWrite, hregARM64_Q20());
sewardjbbcf1882014-01-12 12:49:10 +00002024 /* Now we have to state any parameter-carrying registers
2025 which might be read. This depends on nArgRegs. */
2026 switch (i->ARM64in.Call.nArgRegs) {
2027 case 8: addHRegUse(u, HRmRead, hregARM64_X7()); /*fallthru*/
2028 case 7: addHRegUse(u, HRmRead, hregARM64_X6()); /*fallthru*/
2029 case 6: addHRegUse(u, HRmRead, hregARM64_X5()); /*fallthru*/
2030 case 5: addHRegUse(u, HRmRead, hregARM64_X4()); /*fallthru*/
2031 case 4: addHRegUse(u, HRmRead, hregARM64_X3()); /*fallthru*/
2032 case 3: addHRegUse(u, HRmRead, hregARM64_X2()); /*fallthru*/
2033 case 2: addHRegUse(u, HRmRead, hregARM64_X1()); /*fallthru*/
2034 case 1: addHRegUse(u, HRmRead, hregARM64_X0()); break;
2035 case 0: break;
2036 default: vpanic("getRegUsage_ARM64:Call:regparms");
2037 }
2038 /* Finally, there is the issue that the insn trashes a
2039 register because the literal target address has to be
2040 loaded into a register. However, we reserve x9 for that
2041 purpose so there's no further complexity here. Stating x9
2042 as trashed is pointless since it's not under the control
2043 of the allocator, but what the hell. */
2044 addHRegUse(u, HRmWrite, hregARM64_X9());
2045 return;
2046 case ARM64in_AddToSP:
2047 /* Only changes SP, but regalloc doesn't control that, hence
2048 we don't care. */
2049 return;
2050 case ARM64in_FromSP:
2051 addHRegUse(u, HRmWrite, i->ARM64in.FromSP.dst);
2052 return;
2053 case ARM64in_Mul:
2054 addHRegUse(u, HRmWrite, i->ARM64in.Mul.dst);
2055 addHRegUse(u, HRmRead, i->ARM64in.Mul.argL);
2056 addHRegUse(u, HRmRead, i->ARM64in.Mul.argR);
2057 return;
sewardj7d009132014-02-20 17:43:38 +00002058 case ARM64in_LdrEX:
2059 addHRegUse(u, HRmRead, hregARM64_X4());
2060 addHRegUse(u, HRmWrite, hregARM64_X2());
2061 return;
2062 case ARM64in_StrEX:
2063 addHRegUse(u, HRmRead, hregARM64_X4());
2064 addHRegUse(u, HRmWrite, hregARM64_X0());
2065 addHRegUse(u, HRmRead, hregARM64_X2());
2066 return;
2067 case ARM64in_MFence:
2068 return;
Elliott Hughesa0664b92017-04-18 17:46:52 -07002069 case ARM64in_ClrEX:
2070 return;
sewardj400d6b92015-03-30 09:01:51 +00002071 case ARM64in_VLdStH:
2072 addHRegUse(u, HRmRead, i->ARM64in.VLdStH.rN);
2073 if (i->ARM64in.VLdStH.isLoad) {
2074 addHRegUse(u, HRmWrite, i->ARM64in.VLdStH.hD);
2075 } else {
2076 addHRegUse(u, HRmRead, i->ARM64in.VLdStH.hD);
2077 }
2078 return;
sewardjbbcf1882014-01-12 12:49:10 +00002079 case ARM64in_VLdStS:
2080 addHRegUse(u, HRmRead, i->ARM64in.VLdStS.rN);
2081 if (i->ARM64in.VLdStS.isLoad) {
2082 addHRegUse(u, HRmWrite, i->ARM64in.VLdStS.sD);
2083 } else {
2084 addHRegUse(u, HRmRead, i->ARM64in.VLdStS.sD);
2085 }
2086 return;
2087 case ARM64in_VLdStD:
2088 addHRegUse(u, HRmRead, i->ARM64in.VLdStD.rN);
2089 if (i->ARM64in.VLdStD.isLoad) {
2090 addHRegUse(u, HRmWrite, i->ARM64in.VLdStD.dD);
2091 } else {
2092 addHRegUse(u, HRmRead, i->ARM64in.VLdStD.dD);
2093 }
2094 return;
2095 case ARM64in_VLdStQ:
2096 addHRegUse(u, HRmRead, i->ARM64in.VLdStQ.rN);
2097 if (i->ARM64in.VLdStQ.isLoad)
2098 addHRegUse(u, HRmWrite, i->ARM64in.VLdStQ.rQ);
2099 else
2100 addHRegUse(u, HRmRead, i->ARM64in.VLdStQ.rQ);
2101 return;
2102 case ARM64in_VCvtI2F:
2103 addHRegUse(u, HRmRead, i->ARM64in.VCvtI2F.rS);
2104 addHRegUse(u, HRmWrite, i->ARM64in.VCvtI2F.rD);
2105 return;
2106 case ARM64in_VCvtF2I:
2107 addHRegUse(u, HRmRead, i->ARM64in.VCvtF2I.rS);
2108 addHRegUse(u, HRmWrite, i->ARM64in.VCvtF2I.rD);
2109 return;
2110 case ARM64in_VCvtSD:
2111 addHRegUse(u, HRmWrite, i->ARM64in.VCvtSD.dst);
2112 addHRegUse(u, HRmRead, i->ARM64in.VCvtSD.src);
2113 return;
sewardj400d6b92015-03-30 09:01:51 +00002114 case ARM64in_VCvtHS:
2115 addHRegUse(u, HRmWrite, i->ARM64in.VCvtHS.dst);
2116 addHRegUse(u, HRmRead, i->ARM64in.VCvtHS.src);
2117 return;
2118 case ARM64in_VCvtHD:
2119 addHRegUse(u, HRmWrite, i->ARM64in.VCvtHD.dst);
2120 addHRegUse(u, HRmRead, i->ARM64in.VCvtHD.src);
2121 return;
sewardjbbcf1882014-01-12 12:49:10 +00002122 case ARM64in_VUnaryD:
2123 addHRegUse(u, HRmWrite, i->ARM64in.VUnaryD.dst);
2124 addHRegUse(u, HRmRead, i->ARM64in.VUnaryD.src);
2125 return;
2126 case ARM64in_VUnaryS:
2127 addHRegUse(u, HRmWrite, i->ARM64in.VUnaryS.dst);
2128 addHRegUse(u, HRmRead, i->ARM64in.VUnaryS.src);
2129 return;
2130 case ARM64in_VBinD:
2131 addHRegUse(u, HRmWrite, i->ARM64in.VBinD.dst);
2132 addHRegUse(u, HRmRead, i->ARM64in.VBinD.argL);
2133 addHRegUse(u, HRmRead, i->ARM64in.VBinD.argR);
2134 return;
2135 case ARM64in_VBinS:
2136 addHRegUse(u, HRmWrite, i->ARM64in.VBinS.dst);
2137 addHRegUse(u, HRmRead, i->ARM64in.VBinS.argL);
2138 addHRegUse(u, HRmRead, i->ARM64in.VBinS.argR);
2139 return;
2140 case ARM64in_VCmpD:
2141 addHRegUse(u, HRmRead, i->ARM64in.VCmpD.argL);
2142 addHRegUse(u, HRmRead, i->ARM64in.VCmpD.argR);
2143 return;
2144 case ARM64in_VCmpS:
2145 addHRegUse(u, HRmRead, i->ARM64in.VCmpS.argL);
2146 addHRegUse(u, HRmRead, i->ARM64in.VCmpS.argR);
2147 return;
sewardje23ec112014-11-15 16:07:14 +00002148 case ARM64in_VFCSel:
2149 addHRegUse(u, HRmRead, i->ARM64in.VFCSel.argL);
2150 addHRegUse(u, HRmRead, i->ARM64in.VFCSel.argR);
2151 addHRegUse(u, HRmWrite, i->ARM64in.VFCSel.dst);
2152 return;
sewardjbbcf1882014-01-12 12:49:10 +00002153 case ARM64in_FPCR:
2154 if (i->ARM64in.FPCR.toFPCR)
2155 addHRegUse(u, HRmRead, i->ARM64in.FPCR.iReg);
2156 else
2157 addHRegUse(u, HRmWrite, i->ARM64in.FPCR.iReg);
2158 return;
sewardj12972182014-08-04 08:09:47 +00002159 case ARM64in_FPSR:
2160 if (i->ARM64in.FPSR.toFPSR)
2161 addHRegUse(u, HRmRead, i->ARM64in.FPSR.iReg);
2162 else
2163 addHRegUse(u, HRmWrite, i->ARM64in.FPSR.iReg);
2164 return;
sewardj606c4ba2014-01-26 19:11:14 +00002165 case ARM64in_VBinV:
2166 addHRegUse(u, HRmWrite, i->ARM64in.VBinV.dst);
2167 addHRegUse(u, HRmRead, i->ARM64in.VBinV.argL);
2168 addHRegUse(u, HRmRead, i->ARM64in.VBinV.argR);
2169 return;
sewardjf7003bc2014-08-18 12:28:02 +00002170 case ARM64in_VModifyV:
2171 addHRegUse(u, HRmWrite, i->ARM64in.VModifyV.mod);
2172 addHRegUse(u, HRmRead, i->ARM64in.VModifyV.mod);
2173 addHRegUse(u, HRmRead, i->ARM64in.VModifyV.arg);
2174 return;
sewardjfab09142014-02-10 10:28:13 +00002175 case ARM64in_VUnaryV:
2176 addHRegUse(u, HRmWrite, i->ARM64in.VUnaryV.dst);
2177 addHRegUse(u, HRmRead, i->ARM64in.VUnaryV.arg);
2178 return;
sewardj606c4ba2014-01-26 19:11:14 +00002179 case ARM64in_VNarrowV:
2180 addHRegUse(u, HRmWrite, i->ARM64in.VNarrowV.dst);
2181 addHRegUse(u, HRmRead, i->ARM64in.VNarrowV.src);
2182 return;
sewardje520bb32014-02-17 11:00:53 +00002183 case ARM64in_VShiftImmV:
2184 addHRegUse(u, HRmWrite, i->ARM64in.VShiftImmV.dst);
2185 addHRegUse(u, HRmRead, i->ARM64in.VShiftImmV.src);
2186 return;
sewardjab33a7a2014-06-19 22:20:47 +00002187 case ARM64in_VExtV:
2188 addHRegUse(u, HRmWrite, i->ARM64in.VExtV.dst);
2189 addHRegUse(u, HRmRead, i->ARM64in.VExtV.srcLo);
2190 addHRegUse(u, HRmRead, i->ARM64in.VExtV.srcHi);
florian57628412014-09-02 14:54:39 +00002191 return;
sewardjbbcf1882014-01-12 12:49:10 +00002192 case ARM64in_VImmQ:
2193 addHRegUse(u, HRmWrite, i->ARM64in.VImmQ.rQ);
2194 return;
2195 case ARM64in_VDfromX:
2196 addHRegUse(u, HRmWrite, i->ARM64in.VDfromX.rD);
2197 addHRegUse(u, HRmRead, i->ARM64in.VDfromX.rX);
2198 return;
sewardj12972182014-08-04 08:09:47 +00002199 case ARM64in_VQfromX:
2200 addHRegUse(u, HRmWrite, i->ARM64in.VQfromX.rQ);
2201 addHRegUse(u, HRmRead, i->ARM64in.VQfromX.rXlo);
2202 return;
sewardjbbcf1882014-01-12 12:49:10 +00002203 case ARM64in_VQfromXX:
2204 addHRegUse(u, HRmWrite, i->ARM64in.VQfromXX.rQ);
2205 addHRegUse(u, HRmRead, i->ARM64in.VQfromXX.rXhi);
2206 addHRegUse(u, HRmRead, i->ARM64in.VQfromXX.rXlo);
2207 return;
2208 case ARM64in_VXfromQ:
2209 addHRegUse(u, HRmWrite, i->ARM64in.VXfromQ.rX);
2210 addHRegUse(u, HRmRead, i->ARM64in.VXfromQ.rQ);
2211 return;
sewardj85fbb022014-06-12 13:16:01 +00002212 case ARM64in_VXfromDorS:
2213 addHRegUse(u, HRmWrite, i->ARM64in.VXfromDorS.rX);
2214 addHRegUse(u, HRmRead, i->ARM64in.VXfromDorS.rDorS);
2215 return;
sewardjbbcf1882014-01-12 12:49:10 +00002216 case ARM64in_VMov:
2217 addHRegUse(u, HRmWrite, i->ARM64in.VMov.dst);
2218 addHRegUse(u, HRmRead, i->ARM64in.VMov.src);
2219 return;
sewardjbbcf1882014-01-12 12:49:10 +00002220 case ARM64in_EvCheck:
2221 /* We expect both amodes only to mention x21, so this is in
2222 fact pointless, since x21 isn't allocatable, but
2223 anyway.. */
2224 addRegUsage_ARM64AMode(u, i->ARM64in.EvCheck.amCounter);
2225 addRegUsage_ARM64AMode(u, i->ARM64in.EvCheck.amFailAddr);
2226 addHRegUse(u, HRmWrite, hregARM64_X9()); /* also unavail to RA */
2227 return;
sewardj0ad37a92014-08-29 21:58:03 +00002228 case ARM64in_ProfInc:
2229 /* Again, pointless to actually state these since neither
2230 is available to RA. */
2231 addHRegUse(u, HRmWrite, hregARM64_X9()); /* unavail to RA */
2232 addHRegUse(u, HRmWrite, hregARM64_X8()); /* unavail to RA */
2233 return;
sewardjbbcf1882014-01-12 12:49:10 +00002234 default:
2235 ppARM64Instr(i);
2236 vpanic("getRegUsage_ARM64Instr");
2237 }
2238}
2239
2240
2241void mapRegs_ARM64Instr ( HRegRemap* m, ARM64Instr* i, Bool mode64 )
2242{
2243 vassert(mode64 == True);
2244 switch (i->tag) {
2245 case ARM64in_Arith:
2246 i->ARM64in.Arith.dst = lookupHRegRemap(m, i->ARM64in.Arith.dst);
2247 i->ARM64in.Arith.argL = lookupHRegRemap(m, i->ARM64in.Arith.argL);
2248 mapRegs_ARM64RIA(m, i->ARM64in.Arith.argR);
2249 return;
2250 case ARM64in_Cmp:
2251 i->ARM64in.Cmp.argL = lookupHRegRemap(m, i->ARM64in.Cmp.argL);
2252 mapRegs_ARM64RIA(m, i->ARM64in.Cmp.argR);
2253 return;
2254 case ARM64in_Logic:
2255 i->ARM64in.Logic.dst = lookupHRegRemap(m, i->ARM64in.Logic.dst);
2256 i->ARM64in.Logic.argL = lookupHRegRemap(m, i->ARM64in.Logic.argL);
2257 mapRegs_ARM64RIL(m, i->ARM64in.Logic.argR);
2258 return;
2259 case ARM64in_Test:
2260 i->ARM64in.Test.argL = lookupHRegRemap(m, i->ARM64in.Test.argL);
2261 mapRegs_ARM64RIL(m, i->ARM64in.Logic.argR);
2262 return;
2263 case ARM64in_Shift:
2264 i->ARM64in.Shift.dst = lookupHRegRemap(m, i->ARM64in.Shift.dst);
2265 i->ARM64in.Shift.argL = lookupHRegRemap(m, i->ARM64in.Shift.argL);
2266 mapRegs_ARM64RI6(m, i->ARM64in.Shift.argR);
2267 return;
2268 case ARM64in_Unary:
2269 i->ARM64in.Unary.dst = lookupHRegRemap(m, i->ARM64in.Unary.dst);
2270 i->ARM64in.Unary.src = lookupHRegRemap(m, i->ARM64in.Unary.src);
2271 return;
2272 case ARM64in_MovI:
2273 i->ARM64in.MovI.dst = lookupHRegRemap(m, i->ARM64in.MovI.dst);
2274 i->ARM64in.MovI.src = lookupHRegRemap(m, i->ARM64in.MovI.src);
2275 return;
2276 case ARM64in_Imm64:
2277 i->ARM64in.Imm64.dst = lookupHRegRemap(m, i->ARM64in.Imm64.dst);
2278 return;
2279 case ARM64in_LdSt64:
2280 i->ARM64in.LdSt64.rD = lookupHRegRemap(m, i->ARM64in.LdSt64.rD);
2281 mapRegs_ARM64AMode(m, i->ARM64in.LdSt64.amode);
2282 return;
2283 case ARM64in_LdSt32:
2284 i->ARM64in.LdSt32.rD = lookupHRegRemap(m, i->ARM64in.LdSt32.rD);
2285 mapRegs_ARM64AMode(m, i->ARM64in.LdSt32.amode);
2286 return;
2287 case ARM64in_LdSt16:
2288 i->ARM64in.LdSt16.rD = lookupHRegRemap(m, i->ARM64in.LdSt16.rD);
2289 mapRegs_ARM64AMode(m, i->ARM64in.LdSt16.amode);
2290 return;
2291 case ARM64in_LdSt8:
2292 i->ARM64in.LdSt8.rD = lookupHRegRemap(m, i->ARM64in.LdSt8.rD);
2293 mapRegs_ARM64AMode(m, i->ARM64in.LdSt8.amode);
2294 return;
2295 case ARM64in_XDirect:
2296 mapRegs_ARM64AMode(m, i->ARM64in.XDirect.amPC);
2297 return;
2298 case ARM64in_XIndir:
2299 i->ARM64in.XIndir.dstGA
2300 = lookupHRegRemap(m, i->ARM64in.XIndir.dstGA);
2301 mapRegs_ARM64AMode(m, i->ARM64in.XIndir.amPC);
2302 return;
2303 case ARM64in_XAssisted:
2304 i->ARM64in.XAssisted.dstGA
2305 = lookupHRegRemap(m, i->ARM64in.XAssisted.dstGA);
2306 mapRegs_ARM64AMode(m, i->ARM64in.XAssisted.amPC);
2307 return;
2308 case ARM64in_CSel:
2309 i->ARM64in.CSel.dst = lookupHRegRemap(m, i->ARM64in.CSel.dst);
2310 i->ARM64in.CSel.argL = lookupHRegRemap(m, i->ARM64in.CSel.argL);
2311 i->ARM64in.CSel.argR = lookupHRegRemap(m, i->ARM64in.CSel.argR);
2312 return;
2313 case ARM64in_Call:
2314 return;
2315 case ARM64in_AddToSP:
2316 return;
2317 case ARM64in_FromSP:
2318 i->ARM64in.FromSP.dst = lookupHRegRemap(m, i->ARM64in.FromSP.dst);
2319 return;
2320 case ARM64in_Mul:
2321 i->ARM64in.Mul.dst = lookupHRegRemap(m, i->ARM64in.Mul.dst);
2322 i->ARM64in.Mul.argL = lookupHRegRemap(m, i->ARM64in.Mul.argL);
2323 i->ARM64in.Mul.argR = lookupHRegRemap(m, i->ARM64in.Mul.argR);
2324 break;
sewardj7d009132014-02-20 17:43:38 +00002325 case ARM64in_LdrEX:
2326 return;
2327 case ARM64in_StrEX:
2328 return;
2329 case ARM64in_MFence:
2330 return;
Elliott Hughesa0664b92017-04-18 17:46:52 -07002331 case ARM64in_ClrEX:
2332 return;
sewardj400d6b92015-03-30 09:01:51 +00002333 case ARM64in_VLdStH:
2334 i->ARM64in.VLdStH.hD = lookupHRegRemap(m, i->ARM64in.VLdStH.hD);
2335 i->ARM64in.VLdStH.rN = lookupHRegRemap(m, i->ARM64in.VLdStH.rN);
2336 return;
sewardjbbcf1882014-01-12 12:49:10 +00002337 case ARM64in_VLdStS:
2338 i->ARM64in.VLdStS.sD = lookupHRegRemap(m, i->ARM64in.VLdStS.sD);
2339 i->ARM64in.VLdStS.rN = lookupHRegRemap(m, i->ARM64in.VLdStS.rN);
2340 return;
2341 case ARM64in_VLdStD:
2342 i->ARM64in.VLdStD.dD = lookupHRegRemap(m, i->ARM64in.VLdStD.dD);
2343 i->ARM64in.VLdStD.rN = lookupHRegRemap(m, i->ARM64in.VLdStD.rN);
2344 return;
2345 case ARM64in_VLdStQ:
2346 i->ARM64in.VLdStQ.rQ = lookupHRegRemap(m, i->ARM64in.VLdStQ.rQ);
2347 i->ARM64in.VLdStQ.rN = lookupHRegRemap(m, i->ARM64in.VLdStQ.rN);
2348 return;
2349 case ARM64in_VCvtI2F:
2350 i->ARM64in.VCvtI2F.rS = lookupHRegRemap(m, i->ARM64in.VCvtI2F.rS);
2351 i->ARM64in.VCvtI2F.rD = lookupHRegRemap(m, i->ARM64in.VCvtI2F.rD);
2352 return;
2353 case ARM64in_VCvtF2I:
2354 i->ARM64in.VCvtF2I.rS = lookupHRegRemap(m, i->ARM64in.VCvtF2I.rS);
2355 i->ARM64in.VCvtF2I.rD = lookupHRegRemap(m, i->ARM64in.VCvtF2I.rD);
2356 return;
2357 case ARM64in_VCvtSD:
2358 i->ARM64in.VCvtSD.dst = lookupHRegRemap(m, i->ARM64in.VCvtSD.dst);
2359 i->ARM64in.VCvtSD.src = lookupHRegRemap(m, i->ARM64in.VCvtSD.src);
2360 return;
sewardj400d6b92015-03-30 09:01:51 +00002361 case ARM64in_VCvtHS:
2362 i->ARM64in.VCvtHS.dst = lookupHRegRemap(m, i->ARM64in.VCvtHS.dst);
2363 i->ARM64in.VCvtHS.src = lookupHRegRemap(m, i->ARM64in.VCvtHS.src);
2364 return;
2365 case ARM64in_VCvtHD:
2366 i->ARM64in.VCvtHD.dst = lookupHRegRemap(m, i->ARM64in.VCvtHD.dst);
2367 i->ARM64in.VCvtHD.src = lookupHRegRemap(m, i->ARM64in.VCvtHD.src);
2368 return;
sewardjbbcf1882014-01-12 12:49:10 +00002369 case ARM64in_VUnaryD:
2370 i->ARM64in.VUnaryD.dst = lookupHRegRemap(m, i->ARM64in.VUnaryD.dst);
2371 i->ARM64in.VUnaryD.src = lookupHRegRemap(m, i->ARM64in.VUnaryD.src);
2372 return;
2373 case ARM64in_VUnaryS:
2374 i->ARM64in.VUnaryS.dst = lookupHRegRemap(m, i->ARM64in.VUnaryS.dst);
2375 i->ARM64in.VUnaryS.src = lookupHRegRemap(m, i->ARM64in.VUnaryS.src);
2376 return;
2377 case ARM64in_VBinD:
2378 i->ARM64in.VBinD.dst = lookupHRegRemap(m, i->ARM64in.VBinD.dst);
2379 i->ARM64in.VBinD.argL = lookupHRegRemap(m, i->ARM64in.VBinD.argL);
2380 i->ARM64in.VBinD.argR = lookupHRegRemap(m, i->ARM64in.VBinD.argR);
2381 return;
2382 case ARM64in_VBinS:
2383 i->ARM64in.VBinS.dst = lookupHRegRemap(m, i->ARM64in.VBinS.dst);
2384 i->ARM64in.VBinS.argL = lookupHRegRemap(m, i->ARM64in.VBinS.argL);
2385 i->ARM64in.VBinS.argR = lookupHRegRemap(m, i->ARM64in.VBinS.argR);
2386 return;
2387 case ARM64in_VCmpD:
2388 i->ARM64in.VCmpD.argL = lookupHRegRemap(m, i->ARM64in.VCmpD.argL);
2389 i->ARM64in.VCmpD.argR = lookupHRegRemap(m, i->ARM64in.VCmpD.argR);
2390 return;
2391 case ARM64in_VCmpS:
2392 i->ARM64in.VCmpS.argL = lookupHRegRemap(m, i->ARM64in.VCmpS.argL);
2393 i->ARM64in.VCmpS.argR = lookupHRegRemap(m, i->ARM64in.VCmpS.argR);
2394 return;
sewardje23ec112014-11-15 16:07:14 +00002395 case ARM64in_VFCSel:
2396 i->ARM64in.VFCSel.argL = lookupHRegRemap(m, i->ARM64in.VFCSel.argL);
2397 i->ARM64in.VFCSel.argR = lookupHRegRemap(m, i->ARM64in.VFCSel.argR);
2398 i->ARM64in.VFCSel.dst = lookupHRegRemap(m, i->ARM64in.VFCSel.dst);
2399 return;
sewardjbbcf1882014-01-12 12:49:10 +00002400 case ARM64in_FPCR:
2401 i->ARM64in.FPCR.iReg = lookupHRegRemap(m, i->ARM64in.FPCR.iReg);
2402 return;
sewardj12972182014-08-04 08:09:47 +00002403 case ARM64in_FPSR:
2404 i->ARM64in.FPSR.iReg = lookupHRegRemap(m, i->ARM64in.FPSR.iReg);
2405 return;
sewardj606c4ba2014-01-26 19:11:14 +00002406 case ARM64in_VBinV:
2407 i->ARM64in.VBinV.dst = lookupHRegRemap(m, i->ARM64in.VBinV.dst);
2408 i->ARM64in.VBinV.argL = lookupHRegRemap(m, i->ARM64in.VBinV.argL);
2409 i->ARM64in.VBinV.argR = lookupHRegRemap(m, i->ARM64in.VBinV.argR);
2410 return;
sewardjf7003bc2014-08-18 12:28:02 +00002411 case ARM64in_VModifyV:
2412 i->ARM64in.VModifyV.mod = lookupHRegRemap(m, i->ARM64in.VModifyV.mod);
2413 i->ARM64in.VModifyV.arg = lookupHRegRemap(m, i->ARM64in.VModifyV.arg);
2414 return;
sewardjfab09142014-02-10 10:28:13 +00002415 case ARM64in_VUnaryV:
2416 i->ARM64in.VUnaryV.dst = lookupHRegRemap(m, i->ARM64in.VUnaryV.dst);
2417 i->ARM64in.VUnaryV.arg = lookupHRegRemap(m, i->ARM64in.VUnaryV.arg);
2418 return;
sewardj606c4ba2014-01-26 19:11:14 +00002419 case ARM64in_VNarrowV:
2420 i->ARM64in.VNarrowV.dst = lookupHRegRemap(m, i->ARM64in.VNarrowV.dst);
2421 i->ARM64in.VNarrowV.src = lookupHRegRemap(m, i->ARM64in.VNarrowV.src);
2422 return;
sewardje520bb32014-02-17 11:00:53 +00002423 case ARM64in_VShiftImmV:
2424 i->ARM64in.VShiftImmV.dst
2425 = lookupHRegRemap(m, i->ARM64in.VShiftImmV.dst);
2426 i->ARM64in.VShiftImmV.src
2427 = lookupHRegRemap(m, i->ARM64in.VShiftImmV.src);
2428 return;
sewardjab33a7a2014-06-19 22:20:47 +00002429 case ARM64in_VExtV:
2430 i->ARM64in.VExtV.dst = lookupHRegRemap(m, i->ARM64in.VExtV.dst);
2431 i->ARM64in.VExtV.srcLo = lookupHRegRemap(m, i->ARM64in.VExtV.srcLo);
2432 i->ARM64in.VExtV.srcHi = lookupHRegRemap(m, i->ARM64in.VExtV.srcHi);
2433 return;
sewardjbbcf1882014-01-12 12:49:10 +00002434 case ARM64in_VImmQ:
2435 i->ARM64in.VImmQ.rQ = lookupHRegRemap(m, i->ARM64in.VImmQ.rQ);
2436 return;
2437 case ARM64in_VDfromX:
2438 i->ARM64in.VDfromX.rD
2439 = lookupHRegRemap(m, i->ARM64in.VDfromX.rD);
2440 i->ARM64in.VDfromX.rX
2441 = lookupHRegRemap(m, i->ARM64in.VDfromX.rX);
2442 return;
sewardj12972182014-08-04 08:09:47 +00002443 case ARM64in_VQfromX:
2444 i->ARM64in.VQfromX.rQ
2445 = lookupHRegRemap(m, i->ARM64in.VQfromX.rQ);
2446 i->ARM64in.VQfromX.rXlo
2447 = lookupHRegRemap(m, i->ARM64in.VQfromX.rXlo);
2448 return;
sewardjbbcf1882014-01-12 12:49:10 +00002449 case ARM64in_VQfromXX:
2450 i->ARM64in.VQfromXX.rQ
2451 = lookupHRegRemap(m, i->ARM64in.VQfromXX.rQ);
2452 i->ARM64in.VQfromXX.rXhi
2453 = lookupHRegRemap(m, i->ARM64in.VQfromXX.rXhi);
2454 i->ARM64in.VQfromXX.rXlo
2455 = lookupHRegRemap(m, i->ARM64in.VQfromXX.rXlo);
2456 return;
2457 case ARM64in_VXfromQ:
2458 i->ARM64in.VXfromQ.rX
2459 = lookupHRegRemap(m, i->ARM64in.VXfromQ.rX);
2460 i->ARM64in.VXfromQ.rQ
2461 = lookupHRegRemap(m, i->ARM64in.VXfromQ.rQ);
2462 return;
sewardj85fbb022014-06-12 13:16:01 +00002463 case ARM64in_VXfromDorS:
2464 i->ARM64in.VXfromDorS.rX
2465 = lookupHRegRemap(m, i->ARM64in.VXfromDorS.rX);
2466 i->ARM64in.VXfromDorS.rDorS
2467 = lookupHRegRemap(m, i->ARM64in.VXfromDorS.rDorS);
2468 return;
sewardjbbcf1882014-01-12 12:49:10 +00002469 case ARM64in_VMov:
2470 i->ARM64in.VMov.dst = lookupHRegRemap(m, i->ARM64in.VMov.dst);
2471 i->ARM64in.VMov.src = lookupHRegRemap(m, i->ARM64in.VMov.src);
2472 return;
sewardjbbcf1882014-01-12 12:49:10 +00002473 case ARM64in_EvCheck:
2474 /* We expect both amodes only to mention x21, so this is in
2475 fact pointless, since x21 isn't allocatable, but
2476 anyway.. */
2477 mapRegs_ARM64AMode(m, i->ARM64in.EvCheck.amCounter);
2478 mapRegs_ARM64AMode(m, i->ARM64in.EvCheck.amFailAddr);
2479 return;
sewardj0ad37a92014-08-29 21:58:03 +00002480 case ARM64in_ProfInc:
2481 /* hardwires x8 and x9 -- nothing to modify. */
2482 return;
sewardjbbcf1882014-01-12 12:49:10 +00002483 default:
2484 ppARM64Instr(i);
2485 vpanic("mapRegs_ARM64Instr");
2486 }
2487}
2488
2489/* Figure out if i represents a reg-reg move, and if so assign the
2490 source and destination to *src and *dst. If in doubt say No. Used
2491 by the register allocator to do move coalescing.
2492*/
floriand8c64e02014-10-08 08:54:44 +00002493Bool isMove_ARM64Instr ( const ARM64Instr* i, HReg* src, HReg* dst )
sewardjbbcf1882014-01-12 12:49:10 +00002494{
2495 switch (i->tag) {
2496 case ARM64in_MovI:
2497 *src = i->ARM64in.MovI.src;
2498 *dst = i->ARM64in.MovI.dst;
2499 return True;
2500 case ARM64in_VMov:
2501 *src = i->ARM64in.VMov.src;
2502 *dst = i->ARM64in.VMov.dst;
2503 return True;
2504 default:
2505 break;
2506 }
2507
2508 return False;
2509}
2510
2511
2512/* Generate arm spill/reload instructions under the direction of the
2513 register allocator. Note it's critical these don't write the
2514 condition codes. */
2515
2516void genSpill_ARM64 ( /*OUT*/HInstr** i1, /*OUT*/HInstr** i2,
2517 HReg rreg, Int offsetB, Bool mode64 )
2518{
2519 HRegClass rclass;
2520 vassert(offsetB >= 0);
2521 vassert(!hregIsVirtual(rreg));
2522 vassert(mode64 == True);
2523 *i1 = *i2 = NULL;
2524 rclass = hregClass(rreg);
2525 switch (rclass) {
2526 case HRcInt64:
2527 vassert(0 == (offsetB & 7));
2528 offsetB >>= 3;
2529 vassert(offsetB < 4096);
2530 *i1 = ARM64Instr_LdSt64(
2531 False/*!isLoad*/,
2532 rreg,
2533 ARM64AMode_RI12(hregARM64_X21(), offsetB, 8)
2534 );
2535 return;
2536 case HRcFlt64:
2537 vassert(0 == (offsetB & 7));
2538 vassert(offsetB >= 0 && offsetB < 32768);
2539 *i1 = ARM64Instr_VLdStD(False/*!isLoad*/,
2540 rreg, hregARM64_X21(), offsetB);
2541 return;
2542 case HRcVec128: {
2543 HReg x21 = hregARM64_X21(); // baseblock
2544 HReg x9 = hregARM64_X9(); // spill temporary
2545 vassert(0 == (offsetB & 15)); // check sane alignment
2546 vassert(offsetB < 4096);
2547 *i1 = ARM64Instr_Arith(x9, x21, ARM64RIA_I12(offsetB, 0), True);
2548 *i2 = ARM64Instr_VLdStQ(False/*!isLoad*/, rreg, x9);
2549 return;
2550 }
2551 default:
2552 ppHRegClass(rclass);
2553 vpanic("genSpill_ARM: unimplemented regclass");
2554 }
2555}
2556
2557void genReload_ARM64 ( /*OUT*/HInstr** i1, /*OUT*/HInstr** i2,
2558 HReg rreg, Int offsetB, Bool mode64 )
2559{
2560 HRegClass rclass;
2561 vassert(offsetB >= 0);
2562 vassert(!hregIsVirtual(rreg));
2563 vassert(mode64 == True);
2564 *i1 = *i2 = NULL;
2565 rclass = hregClass(rreg);
2566 switch (rclass) {
2567 case HRcInt64:
2568 vassert(0 == (offsetB & 7));
2569 offsetB >>= 3;
2570 vassert(offsetB < 4096);
2571 *i1 = ARM64Instr_LdSt64(
2572 True/*isLoad*/,
2573 rreg,
2574 ARM64AMode_RI12(hregARM64_X21(), offsetB, 8)
2575 );
2576 return;
2577 case HRcFlt64:
2578 vassert(0 == (offsetB & 7));
2579 vassert(offsetB >= 0 && offsetB < 32768);
2580 *i1 = ARM64Instr_VLdStD(True/*isLoad*/,
2581 rreg, hregARM64_X21(), offsetB);
2582 return;
2583 case HRcVec128: {
2584 HReg x21 = hregARM64_X21(); // baseblock
2585 HReg x9 = hregARM64_X9(); // spill temporary
2586 vassert(0 == (offsetB & 15)); // check sane alignment
2587 vassert(offsetB < 4096);
2588 *i1 = ARM64Instr_Arith(x9, x21, ARM64RIA_I12(offsetB, 0), True);
2589 *i2 = ARM64Instr_VLdStQ(True/*isLoad*/, rreg, x9);
2590 return;
2591 }
2592 default:
2593 ppHRegClass(rclass);
2594 vpanic("genReload_ARM: unimplemented regclass");
2595 }
2596}
2597
2598
sewardja5b50222015-03-26 07:18:32 +00002599/* Emit an instruction into buf and return the number of bytes used.
2600 Note that buf is not the insn's final place, and therefore it is
2601 imperative to emit position-independent code. */
sewardjbbcf1882014-01-12 12:49:10 +00002602
sewardja5b50222015-03-26 07:18:32 +00002603static inline UInt iregEnc ( HReg r )
sewardjbbcf1882014-01-12 12:49:10 +00002604{
2605 UInt n;
2606 vassert(hregClass(r) == HRcInt64);
2607 vassert(!hregIsVirtual(r));
sewardja5b50222015-03-26 07:18:32 +00002608 n = hregEncoding(r);
sewardjbbcf1882014-01-12 12:49:10 +00002609 vassert(n <= 30);
sewardja5b50222015-03-26 07:18:32 +00002610 return n;
sewardjbbcf1882014-01-12 12:49:10 +00002611}
2612
sewardja5b50222015-03-26 07:18:32 +00002613static inline UInt dregEnc ( HReg r )
sewardjbbcf1882014-01-12 12:49:10 +00002614{
2615 UInt n;
2616 vassert(hregClass(r) == HRcFlt64);
2617 vassert(!hregIsVirtual(r));
sewardja5b50222015-03-26 07:18:32 +00002618 n = hregEncoding(r);
sewardjbbcf1882014-01-12 12:49:10 +00002619 vassert(n <= 31);
sewardja5b50222015-03-26 07:18:32 +00002620 return n;
sewardjbbcf1882014-01-12 12:49:10 +00002621}
2622
sewardja5b50222015-03-26 07:18:32 +00002623static inline UInt qregEnc ( HReg r )
sewardjbbcf1882014-01-12 12:49:10 +00002624{
2625 UInt n;
2626 vassert(hregClass(r) == HRcVec128);
2627 vassert(!hregIsVirtual(r));
sewardja5b50222015-03-26 07:18:32 +00002628 n = hregEncoding(r);
sewardjbbcf1882014-01-12 12:49:10 +00002629 vassert(n <= 31);
sewardja5b50222015-03-26 07:18:32 +00002630 return n;
sewardjbbcf1882014-01-12 12:49:10 +00002631}
2632
2633#define BITS4(zzb3,zzb2,zzb1,zzb0) \
2634 (((zzb3) << 3) | ((zzb2) << 2) | ((zzb1) << 1) | (zzb0))
2635
2636#define X00 BITS4(0,0, 0,0)
2637#define X01 BITS4(0,0, 0,1)
2638#define X10 BITS4(0,0, 1,0)
2639#define X11 BITS4(0,0, 1,1)
2640
2641#define X000 BITS4(0, 0,0,0)
2642#define X001 BITS4(0, 0,0,1)
2643#define X010 BITS4(0, 0,1,0)
2644#define X011 BITS4(0, 0,1,1)
2645#define X100 BITS4(0, 1,0,0)
2646#define X101 BITS4(0, 1,0,1)
2647#define X110 BITS4(0, 1,1,0)
2648#define X111 BITS4(0, 1,1,1)
2649
sewardjbbcf1882014-01-12 12:49:10 +00002650#define X0000 BITS4(0,0,0,0)
2651#define X0001 BITS4(0,0,0,1)
2652#define X0010 BITS4(0,0,1,0)
2653#define X0011 BITS4(0,0,1,1)
2654
sewardj606c4ba2014-01-26 19:11:14 +00002655#define BITS8(zzb7,zzb6,zzb5,zzb4,zzb3,zzb2,zzb1,zzb0) \
2656 ((BITS4(zzb7,zzb6,zzb5,zzb4) << 4) | BITS4(zzb3,zzb2,zzb1,zzb0))
2657
sewardjbbcf1882014-01-12 12:49:10 +00002658#define X00000 BITS8(0,0,0, 0,0,0,0,0)
sewardj606c4ba2014-01-26 19:11:14 +00002659#define X00001 BITS8(0,0,0, 0,0,0,0,1)
sewardj85fbb022014-06-12 13:16:01 +00002660#define X00110 BITS8(0,0,0, 0,0,1,1,0)
sewardjbbcf1882014-01-12 12:49:10 +00002661#define X00111 BITS8(0,0,0, 0,0,1,1,1)
2662#define X01000 BITS8(0,0,0, 0,1,0,0,0)
2663#define X10000 BITS8(0,0,0, 1,0,0,0,0)
2664#define X11000 BITS8(0,0,0, 1,1,0,0,0)
2665#define X11110 BITS8(0,0,0, 1,1,1,1,0)
2666#define X11111 BITS8(0,0,0, 1,1,1,1,1)
2667
2668#define X000000 BITS8(0,0, 0,0,0,0,0,0)
sewardje520bb32014-02-17 11:00:53 +00002669#define X000001 BITS8(0,0, 0,0,0,0,0,1)
sewardjdf9d6d52014-06-27 10:43:22 +00002670#define X000010 BITS8(0,0, 0,0,0,0,1,0)
sewardja5a6b752014-06-30 07:33:56 +00002671#define X000011 BITS8(0,0, 0,0,0,0,1,1)
sewardjbbcf1882014-01-12 12:49:10 +00002672#define X000100 BITS8(0,0, 0,0,0,1,0,0)
sewardjd96daf62014-06-15 08:17:35 +00002673#define X000110 BITS8(0,0, 0,0,0,1,1,0)
sewardjecde6972014-02-05 11:01:19 +00002674#define X000111 BITS8(0,0, 0,0,0,1,1,1)
sewardjbbcf1882014-01-12 12:49:10 +00002675#define X001000 BITS8(0,0, 0,0,1,0,0,0)
2676#define X001001 BITS8(0,0, 0,0,1,0,0,1)
2677#define X001010 BITS8(0,0, 0,0,1,0,1,0)
sewardja5a6b752014-06-30 07:33:56 +00002678#define X001011 BITS8(0,0, 0,0,1,0,1,1)
sewardj92d0ae32014-04-03 13:48:54 +00002679#define X001101 BITS8(0,0, 0,0,1,1,0,1)
sewardjd96daf62014-06-15 08:17:35 +00002680#define X001110 BITS8(0,0, 0,0,1,1,1,0)
sewardjbbcf1882014-01-12 12:49:10 +00002681#define X001111 BITS8(0,0, 0,0,1,1,1,1)
2682#define X010000 BITS8(0,0, 0,1,0,0,0,0)
2683#define X010001 BITS8(0,0, 0,1,0,0,0,1)
sewardj2b6fd5e2014-06-19 14:21:37 +00002684#define X010010 BITS8(0,0, 0,1,0,0,1,0)
sewardj12972182014-08-04 08:09:47 +00002685#define X010011 BITS8(0,0, 0,1,0,0,1,1)
sewardj32d86752014-03-02 12:47:18 +00002686#define X010101 BITS8(0,0, 0,1,0,1,0,1)
sewardje520bb32014-02-17 11:00:53 +00002687#define X010110 BITS8(0,0, 0,1,0,1,1,0)
sewardj12972182014-08-04 08:09:47 +00002688#define X010111 BITS8(0,0, 0,1,0,1,1,1)
sewardjecde6972014-02-05 11:01:19 +00002689#define X011001 BITS8(0,0, 0,1,1,0,0,1)
sewardjbbcf1882014-01-12 12:49:10 +00002690#define X011010 BITS8(0,0, 0,1,1,0,1,0)
sewardjecde6972014-02-05 11:01:19 +00002691#define X011011 BITS8(0,0, 0,1,1,0,1,1)
sewardja97dddf2014-08-14 22:26:52 +00002692#define X011101 BITS8(0,0, 0,1,1,1,0,1)
sewardje520bb32014-02-17 11:00:53 +00002693#define X011110 BITS8(0,0, 0,1,1,1,1,0)
sewardjbbcf1882014-01-12 12:49:10 +00002694#define X011111 BITS8(0,0, 0,1,1,1,1,1)
sewardj606c4ba2014-01-26 19:11:14 +00002695#define X100001 BITS8(0,0, 1,0,0,0,0,1)
sewardje520bb32014-02-17 11:00:53 +00002696#define X100011 BITS8(0,0, 1,0,0,0,1,1)
sewardjbbcf1882014-01-12 12:49:10 +00002697#define X100100 BITS8(0,0, 1,0,0,1,0,0)
2698#define X100101 BITS8(0,0, 1,0,0,1,0,1)
2699#define X100110 BITS8(0,0, 1,0,0,1,1,0)
sewardjf5b08912014-02-06 12:57:58 +00002700#define X100111 BITS8(0,0, 1,0,0,1,1,1)
sewardj54ffa1d2014-07-22 09:27:49 +00002701#define X101101 BITS8(0,0, 1,0,1,1,0,1)
sewardj25523c42014-06-15 19:36:29 +00002702#define X101110 BITS8(0,0, 1,0,1,1,1,0)
sewardjbbcf1882014-01-12 12:49:10 +00002703#define X110000 BITS8(0,0, 1,1,0,0,0,0)
2704#define X110001 BITS8(0,0, 1,1,0,0,0,1)
sewardjfc261d92014-08-24 20:36:14 +00002705#define X110010 BITS8(0,0, 1,1,0,0,1,0)
sewardj51d012a2014-07-21 09:19:50 +00002706#define X110100 BITS8(0,0, 1,1,0,1,0,0)
sewardj606c4ba2014-01-26 19:11:14 +00002707#define X110101 BITS8(0,0, 1,1,0,1,0,1)
sewardj89cefe42015-02-24 12:21:01 +00002708#define X110110 BITS8(0,0, 1,1,0,1,1,0)
sewardj606c4ba2014-01-26 19:11:14 +00002709#define X110111 BITS8(0,0, 1,1,0,1,1,1)
sewardjbbcf1882014-01-12 12:49:10 +00002710#define X111000 BITS8(0,0, 1,1,1,0,0,0)
2711#define X111001 BITS8(0,0, 1,1,1,0,0,1)
2712#define X111101 BITS8(0,0, 1,1,1,1,0,1)
sewardjfab09142014-02-10 10:28:13 +00002713#define X111110 BITS8(0,0, 1,1,1,1,1,0)
sewardj606c4ba2014-01-26 19:11:14 +00002714#define X111111 BITS8(0,0, 1,1,1,1,1,1)
sewardjbbcf1882014-01-12 12:49:10 +00002715
sewardj93013432014-04-27 12:02:12 +00002716#define X0001000 BITS8(0, 0,0,0,1,0,0,0)
sewardj1eaaec22014-03-07 22:52:19 +00002717#define X0010000 BITS8(0, 0,0,1,0,0,0,0)
sewardj32d86752014-03-02 12:47:18 +00002718#define X0100000 BITS8(0, 0,1,0,0,0,0,0)
sewardje520bb32014-02-17 11:00:53 +00002719#define X1000000 BITS8(0, 1,0,0,0,0,0,0)
2720
sewardjbbcf1882014-01-12 12:49:10 +00002721#define X00100000 BITS8(0,0,1,0,0,0,0,0)
2722#define X00100001 BITS8(0,0,1,0,0,0,0,1)
2723#define X00100010 BITS8(0,0,1,0,0,0,1,0)
2724#define X00100011 BITS8(0,0,1,0,0,0,1,1)
2725#define X01010000 BITS8(0,1,0,1,0,0,0,0)
2726#define X01010001 BITS8(0,1,0,1,0,0,0,1)
2727#define X01010100 BITS8(0,1,0,1,0,1,0,0)
2728#define X01011000 BITS8(0,1,0,1,1,0,0,0)
2729#define X01100000 BITS8(0,1,1,0,0,0,0,0)
2730#define X01100001 BITS8(0,1,1,0,0,0,0,1)
2731#define X01100010 BITS8(0,1,1,0,0,0,1,0)
2732#define X01100011 BITS8(0,1,1,0,0,0,1,1)
2733#define X01110000 BITS8(0,1,1,1,0,0,0,0)
sewardj606c4ba2014-01-26 19:11:14 +00002734#define X01110001 BITS8(0,1,1,1,0,0,0,1)
sewardjd96daf62014-06-15 08:17:35 +00002735#define X01110010 BITS8(0,1,1,1,0,0,1,0)
sewardj606c4ba2014-01-26 19:11:14 +00002736#define X01110011 BITS8(0,1,1,1,0,0,1,1)
sewardjd96daf62014-06-15 08:17:35 +00002737#define X01110100 BITS8(0,1,1,1,0,1,0,0)
sewardj606c4ba2014-01-26 19:11:14 +00002738#define X01110101 BITS8(0,1,1,1,0,1,0,1)
sewardjd96daf62014-06-15 08:17:35 +00002739#define X01110110 BITS8(0,1,1,1,0,1,1,0)
sewardj606c4ba2014-01-26 19:11:14 +00002740#define X01110111 BITS8(0,1,1,1,0,1,1,1)
sewardjbbcf1882014-01-12 12:49:10 +00002741#define X11000001 BITS8(1,1,0,0,0,0,0,1)
2742#define X11000011 BITS8(1,1,0,0,0,0,1,1)
2743#define X11010100 BITS8(1,1,0,1,0,1,0,0)
2744#define X11010110 BITS8(1,1,0,1,0,1,1,0)
2745#define X11011000 BITS8(1,1,0,1,1,0,0,0)
2746#define X11011010 BITS8(1,1,0,1,1,0,1,0)
2747#define X11011110 BITS8(1,1,0,1,1,1,1,0)
sewardj400d6b92015-03-30 09:01:51 +00002748#define X11100010 BITS8(1,1,1,0,0,0,1,0)
sewardjbbcf1882014-01-12 12:49:10 +00002749#define X11110001 BITS8(1,1,1,1,0,0,0,1)
2750#define X11110011 BITS8(1,1,1,1,0,0,1,1)
sewardj89cefe42015-02-24 12:21:01 +00002751#define X11110101 BITS8(1,1,1,1,0,1,0,1)
2752#define X11110111 BITS8(1,1,1,1,0,1,1,1)
sewardjbbcf1882014-01-12 12:49:10 +00002753
2754
2755/* --- 4 fields --- */
2756
2757static inline UInt X_8_19_1_4 ( UInt f1, UInt f2, UInt f3, UInt f4 ) {
2758 vassert(8+19+1+4 == 32);
2759 vassert(f1 < (1<<8));
2760 vassert(f2 < (1<<19));
2761 vassert(f3 < (1<<1));
2762 vassert(f4 < (1<<4));
2763 UInt w = 0;
2764 w = (w << 8) | f1;
2765 w = (w << 19) | f2;
2766 w = (w << 1) | f3;
2767 w = (w << 4) | f4;
2768 return w;
2769}
2770
2771/* --- 5 fields --- */
2772
2773static inline UInt X_3_6_2_16_5 ( UInt f1, UInt f2,
2774 UInt f3, UInt f4, UInt f5 ) {
2775 vassert(3+6+2+16+5 == 32);
2776 vassert(f1 < (1<<3));
2777 vassert(f2 < (1<<6));
2778 vassert(f3 < (1<<2));
2779 vassert(f4 < (1<<16));
2780 vassert(f5 < (1<<5));
2781 UInt w = 0;
2782 w = (w << 3) | f1;
2783 w = (w << 6) | f2;
2784 w = (w << 2) | f3;
2785 w = (w << 16) | f4;
2786 w = (w << 5) | f5;
2787 return w;
2788}
2789
2790/* --- 6 fields --- */
2791
2792static inline UInt X_2_6_2_12_5_5 ( UInt f1, UInt f2, UInt f3,
2793 UInt f4, UInt f5, UInt f6 ) {
2794 vassert(2+6+2+12+5+5 == 32);
2795 vassert(f1 < (1<<2));
2796 vassert(f2 < (1<<6));
2797 vassert(f3 < (1<<2));
2798 vassert(f4 < (1<<12));
2799 vassert(f5 < (1<<5));
2800 vassert(f6 < (1<<5));
2801 UInt w = 0;
2802 w = (w << 2) | f1;
2803 w = (w << 6) | f2;
2804 w = (w << 2) | f3;
2805 w = (w << 12) | f4;
2806 w = (w << 5) | f5;
2807 w = (w << 5) | f6;
2808 return w;
2809}
2810
2811static inline UInt X_3_8_5_6_5_5 ( UInt f1, UInt f2, UInt f3,
2812 UInt f4, UInt f5, UInt f6 ) {
2813 vassert(3+8+5+6+5+5 == 32);
2814 vassert(f1 < (1<<3));
2815 vassert(f2 < (1<<8));
2816 vassert(f3 < (1<<5));
2817 vassert(f4 < (1<<6));
2818 vassert(f5 < (1<<5));
2819 vassert(f6 < (1<<5));
2820 UInt w = 0;
2821 w = (w << 3) | f1;
2822 w = (w << 8) | f2;
2823 w = (w << 5) | f3;
2824 w = (w << 6) | f4;
2825 w = (w << 5) | f5;
2826 w = (w << 5) | f6;
2827 return w;
2828}
2829
2830static inline UInt X_3_5_8_6_5_5 ( UInt f1, UInt f2, UInt f3,
2831 UInt f4, UInt f5, UInt f6 ) {
2832 vassert(3+8+5+6+5+5 == 32);
2833 vassert(f1 < (1<<3));
2834 vassert(f2 < (1<<5));
2835 vassert(f3 < (1<<8));
2836 vassert(f4 < (1<<6));
2837 vassert(f5 < (1<<5));
2838 vassert(f6 < (1<<5));
2839 UInt w = 0;
2840 w = (w << 3) | f1;
2841 w = (w << 5) | f2;
2842 w = (w << 8) | f3;
2843 w = (w << 6) | f4;
2844 w = (w << 5) | f5;
2845 w = (w << 5) | f6;
2846 return w;
2847}
2848
sewardje520bb32014-02-17 11:00:53 +00002849static inline UInt X_3_6_7_6_5_5 ( UInt f1, UInt f2, UInt f3,
2850 UInt f4, UInt f5, UInt f6 ) {
2851 vassert(3+6+7+6+5+5 == 32);
2852 vassert(f1 < (1<<3));
2853 vassert(f2 < (1<<6));
2854 vassert(f3 < (1<<7));
2855 vassert(f4 < (1<<6));
2856 vassert(f5 < (1<<5));
2857 vassert(f6 < (1<<5));
2858 UInt w = 0;
2859 w = (w << 3) | f1;
2860 w = (w << 6) | f2;
2861 w = (w << 7) | f3;
2862 w = (w << 6) | f4;
2863 w = (w << 5) | f5;
2864 w = (w << 5) | f6;
2865 return w;
2866}
2867
sewardjbbcf1882014-01-12 12:49:10 +00002868/* --- 7 fields --- */
2869
2870static inline UInt X_2_6_3_9_2_5_5 ( UInt f1, UInt f2, UInt f3,
2871 UInt f4, UInt f5, UInt f6, UInt f7 ) {
2872 vassert(2+6+3+9+2+5+5 == 32);
2873 vassert(f1 < (1<<2));
2874 vassert(f2 < (1<<6));
2875 vassert(f3 < (1<<3));
2876 vassert(f4 < (1<<9));
2877 vassert(f5 < (1<<2));
2878 vassert(f6 < (1<<5));
2879 vassert(f7 < (1<<5));
2880 UInt w = 0;
2881 w = (w << 2) | f1;
2882 w = (w << 6) | f2;
2883 w = (w << 3) | f3;
2884 w = (w << 9) | f4;
2885 w = (w << 2) | f5;
2886 w = (w << 5) | f6;
2887 w = (w << 5) | f7;
2888 return w;
2889}
2890
2891static inline UInt X_3_6_1_6_6_5_5 ( UInt f1, UInt f2, UInt f3,
2892 UInt f4, UInt f5, UInt f6, UInt f7 ) {
2893 vassert(3+6+1+6+6+5+5 == 32);
2894 vassert(f1 < (1<<3));
2895 vassert(f2 < (1<<6));
2896 vassert(f3 < (1<<1));
2897 vassert(f4 < (1<<6));
2898 vassert(f5 < (1<<6));
2899 vassert(f6 < (1<<5));
2900 vassert(f7 < (1<<5));
2901 UInt w = 0;
2902 w = (w << 3) | f1;
2903 w = (w << 6) | f2;
2904 w = (w << 1) | f3;
2905 w = (w << 6) | f4;
2906 w = (w << 6) | f5;
2907 w = (w << 5) | f6;
2908 w = (w << 5) | f7;
2909 return w;
2910}
2911
2912
2913//ZZ #define X0000 BITS4(0,0,0,0)
2914//ZZ #define X0001 BITS4(0,0,0,1)
2915//ZZ #define X0010 BITS4(0,0,1,0)
2916//ZZ #define X0011 BITS4(0,0,1,1)
2917//ZZ #define X0100 BITS4(0,1,0,0)
2918//ZZ #define X0101 BITS4(0,1,0,1)
2919//ZZ #define X0110 BITS4(0,1,1,0)
2920//ZZ #define X0111 BITS4(0,1,1,1)
2921//ZZ #define X1000 BITS4(1,0,0,0)
2922//ZZ #define X1001 BITS4(1,0,0,1)
2923//ZZ #define X1010 BITS4(1,0,1,0)
2924//ZZ #define X1011 BITS4(1,0,1,1)
2925//ZZ #define X1100 BITS4(1,1,0,0)
2926//ZZ #define X1101 BITS4(1,1,0,1)
2927//ZZ #define X1110 BITS4(1,1,1,0)
2928//ZZ #define X1111 BITS4(1,1,1,1)
2929/*
2930#define XXXXX___(zzx7,zzx6,zzx5,zzx4,zzx3) \
2931 ((((zzx7) & 0xF) << 28) | (((zzx6) & 0xF) << 24) | \
2932 (((zzx5) & 0xF) << 20) | (((zzx4) & 0xF) << 16) | \
2933 (((zzx3) & 0xF) << 12))
2934
2935#define XXXXXX__(zzx7,zzx6,zzx5,zzx4,zzx3,zzx2) \
2936 ((((zzx7) & 0xF) << 28) | (((zzx6) & 0xF) << 24) | \
2937 (((zzx5) & 0xF) << 20) | (((zzx4) & 0xF) << 16) | \
2938 (((zzx3) & 0xF) << 12) | (((zzx2) & 0xF) << 8))
2939
2940#define XXXXX__X(zzx7,zzx6,zzx5,zzx4,zzx3,zzx0) \
2941 ((((zzx7) & 0xF) << 28) | (((zzx6) & 0xF) << 24) | \
2942 (((zzx5) & 0xF) << 20) | (((zzx4) & 0xF) << 16) | \
2943 (((zzx3) & 0xF) << 12) | (((zzx0) & 0xF) << 0))
2944
2945#define XXX___XX(zzx7,zzx6,zzx5,zzx1,zzx0) \
2946 ((((zzx7) & 0xF) << 28) | (((zzx6) & 0xF) << 24) | \
2947 (((zzx5) & 0xF) << 20) | (((zzx1) & 0xF) << 4) | \
2948 (((zzx0) & 0xF) << 0))
2949
2950#define XXXXXXXX(zzx7,zzx6,zzx5,zzx4,zzx3,zzx2,zzx1,zzx0) \
2951 ((((zzx7) & 0xF) << 28) | (((zzx6) & 0xF) << 24) | \
2952 (((zzx5) & 0xF) << 20) | (((zzx4) & 0xF) << 16) | \
2953 (((zzx3) & 0xF) << 12) | (((zzx2) & 0xF) << 8) | \
2954 (((zzx1) & 0xF) << 4) | (((zzx0) & 0xF) << 0))
2955
2956#define XX______(zzx7,zzx6) \
2957 ((((zzx7) & 0xF) << 28) | (((zzx6) & 0xF) << 24))
2958*/
sewardjbbcf1882014-01-12 12:49:10 +00002959
2960
2961/* Get an immediate into a register, using only that register. */
sewardja5b50222015-03-26 07:18:32 +00002962static UInt* imm64_to_ireg ( UInt* p, Int xD, ULong imm64 )
sewardjbbcf1882014-01-12 12:49:10 +00002963{
2964 if (imm64 == 0) {
2965 // This has to be special-cased, since the logic below
2966 // will leave the register unchanged in this case.
2967 // MOVZ xD, #0, LSL #0
2968 *p++ = X_3_6_2_16_5(X110, X100101, X00, 0/*imm16*/, xD);
2969 return p;
2970 }
2971
2972 // There must be at least one non-zero halfword. Find the
2973 // lowest nonzero such, and use MOVZ to install it and zero
2974 // out the rest of the register.
2975 UShort h[4];
2976 h[3] = (UShort)((imm64 >> 48) & 0xFFFF);
2977 h[2] = (UShort)((imm64 >> 32) & 0xFFFF);
2978 h[1] = (UShort)((imm64 >> 16) & 0xFFFF);
2979 h[0] = (UShort)((imm64 >> 0) & 0xFFFF);
2980
2981 UInt i;
2982 for (i = 0; i < 4; i++) {
2983 if (h[i] != 0)
2984 break;
2985 }
2986 vassert(i < 4);
2987
2988 // MOVZ xD, h[i], LSL (16*i)
2989 *p++ = X_3_6_2_16_5(X110, X100101, i, h[i], xD);
2990
2991 // Work on upwards through h[i], using MOVK to stuff in any
2992 // remaining nonzero elements.
2993 i++;
2994 for (; i < 4; i++) {
2995 if (h[i] == 0)
2996 continue;
2997 // MOVK xD, h[i], LSL (16*i)
2998 *p++ = X_3_6_2_16_5(X111, X100101, i, h[i], xD);
2999 }
3000
3001 return p;
3002}
3003
3004/* Get an immediate into a register, using only that register, and
3005 generating exactly 4 instructions, regardless of the value of the
3006 immediate. This is used when generating sections of code that need
3007 to be patched later, so as to guarantee a specific size. */
sewardja5b50222015-03-26 07:18:32 +00003008static UInt* imm64_to_ireg_EXACTLY4 ( UInt* p, Int xD, ULong imm64 )
sewardjbbcf1882014-01-12 12:49:10 +00003009{
3010 UShort h[4];
3011 h[3] = (UShort)((imm64 >> 48) & 0xFFFF);
3012 h[2] = (UShort)((imm64 >> 32) & 0xFFFF);
3013 h[1] = (UShort)((imm64 >> 16) & 0xFFFF);
3014 h[0] = (UShort)((imm64 >> 0) & 0xFFFF);
3015 // Work on upwards through h[i], using MOVK to stuff in the
3016 // remaining elements.
3017 UInt i;
3018 for (i = 0; i < 4; i++) {
3019 if (i == 0) {
3020 // MOVZ xD, h[0], LSL (16*0)
3021 *p++ = X_3_6_2_16_5(X110, X100101, i, h[i], xD);
3022 } else {
3023 // MOVK xD, h[i], LSL (16*i)
3024 *p++ = X_3_6_2_16_5(X111, X100101, i, h[i], xD);
3025 }
3026 }
3027 return p;
3028}
3029
3030/* Check whether p points at a 4-insn sequence cooked up by
sewardja5b50222015-03-26 07:18:32 +00003031 imm64_to_ireg_EXACTLY4(). */
3032static Bool is_imm64_to_ireg_EXACTLY4 ( UInt* p, Int xD, ULong imm64 )
sewardjbbcf1882014-01-12 12:49:10 +00003033{
3034 UShort h[4];
3035 h[3] = (UShort)((imm64 >> 48) & 0xFFFF);
3036 h[2] = (UShort)((imm64 >> 32) & 0xFFFF);
3037 h[1] = (UShort)((imm64 >> 16) & 0xFFFF);
3038 h[0] = (UShort)((imm64 >> 0) & 0xFFFF);
3039 // Work on upwards through h[i], using MOVK to stuff in the
3040 // remaining elements.
3041 UInt i;
3042 for (i = 0; i < 4; i++) {
3043 UInt expected;
3044 if (i == 0) {
3045 // MOVZ xD, h[0], LSL (16*0)
3046 expected = X_3_6_2_16_5(X110, X100101, i, h[i], xD);
3047 } else {
3048 // MOVK xD, h[i], LSL (16*i)
3049 expected = X_3_6_2_16_5(X111, X100101, i, h[i], xD);
3050 }
3051 if (p[i] != expected)
3052 return False;
3053 }
3054 return True;
3055}
3056
3057
3058/* Generate a 8 bit store or 8-to-64 unsigned widening load from/to
3059 rD, using the given amode for the address. */
3060static UInt* do_load_or_store8 ( UInt* p,
3061 Bool isLoad, UInt wD, ARM64AMode* am )
3062{
3063 vassert(wD <= 30);
3064 if (am->tag == ARM64am_RI9) {
3065 /* STURB Wd, [Xn|SP + simm9]: 00 111000 000 simm9 00 n d
3066 LDURB Wd, [Xn|SP + simm9]: 00 111000 010 simm9 00 n d
3067 */
3068 Int simm9 = am->ARM64am.RI9.simm9;
3069 vassert(-256 <= simm9 && simm9 <= 255);
3070 UInt instr = X_2_6_3_9_2_5_5(X00, X111000, isLoad ? X010 : X000,
3071 simm9 & 0x1FF, X00,
sewardja5b50222015-03-26 07:18:32 +00003072 iregEnc(am->ARM64am.RI9.reg), wD);
sewardjbbcf1882014-01-12 12:49:10 +00003073 *p++ = instr;
3074 return p;
3075 }
3076 if (am->tag == ARM64am_RI12) {
3077 /* STRB Wd, [Xn|SP + uimm12 * 1]: 00 111 001 00 imm12 n d
3078 LDRB Wd, [Xn|SP + uimm12 * 1]: 00 111 001 01 imm12 n d
3079 */
3080 UInt uimm12 = am->ARM64am.RI12.uimm12;
3081 UInt scale = am->ARM64am.RI12.szB;
3082 vassert(scale == 1); /* failure of this is serious. Do not ignore. */
sewardja5b50222015-03-26 07:18:32 +00003083 UInt xN = iregEnc(am->ARM64am.RI12.reg);
sewardjbbcf1882014-01-12 12:49:10 +00003084 vassert(xN <= 30);
3085 UInt instr = X_2_6_2_12_5_5(X00, X111001, isLoad ? X01 : X00,
3086 uimm12, xN, wD);
3087 *p++ = instr;
3088 return p;
3089 }
3090 if (am->tag == ARM64am_RR) {
3091 /* STRB Xd, [Xn|SP, Xm]: 00 111 000 001 m 011 0 10 n d
3092 LDRB Xd, [Xn|SP, Xm]: 00 111 000 011 m 011 0 10 n d
3093 */
sewardja5b50222015-03-26 07:18:32 +00003094 UInt xN = iregEnc(am->ARM64am.RR.base);
3095 UInt xM = iregEnc(am->ARM64am.RR.index);
sewardjbbcf1882014-01-12 12:49:10 +00003096 vassert(xN <= 30);
3097 UInt instr = X_3_8_5_6_5_5(X001, isLoad ? X11000011 : X11000001,
3098 xM, X011010, xN, wD);
3099 *p++ = instr;
3100 return p;
3101 }
3102 vpanic("do_load_or_store8");
3103 vassert(0);
3104}
3105
3106
3107/* Generate a 16 bit store or 16-to-64 unsigned widening load from/to
3108 rD, using the given amode for the address. */
3109static UInt* do_load_or_store16 ( UInt* p,
3110 Bool isLoad, UInt wD, ARM64AMode* am )
3111{
3112 vassert(wD <= 30);
3113 if (am->tag == ARM64am_RI9) {
3114 /* STURH Wd, [Xn|SP + simm9]: 01 111000 000 simm9 00 n d
3115 LDURH Wd, [Xn|SP + simm9]: 01 111000 010 simm9 00 n d
3116 */
3117 Int simm9 = am->ARM64am.RI9.simm9;
3118 vassert(-256 <= simm9 && simm9 <= 255);
3119 UInt instr = X_2_6_3_9_2_5_5(X01, X111000, isLoad ? X010 : X000,
3120 simm9 & 0x1FF, X00,
sewardja5b50222015-03-26 07:18:32 +00003121 iregEnc(am->ARM64am.RI9.reg), wD);
sewardjbbcf1882014-01-12 12:49:10 +00003122 *p++ = instr;
3123 return p;
3124 }
3125 if (am->tag == ARM64am_RI12) {
3126 /* STRH Wd, [Xn|SP + uimm12 * 2]: 01 111 001 00 imm12 n d
3127 LDRH Wd, [Xn|SP + uimm12 * 2]: 01 111 001 01 imm12 n d
3128 */
3129 UInt uimm12 = am->ARM64am.RI12.uimm12;
3130 UInt scale = am->ARM64am.RI12.szB;
3131 vassert(scale == 2); /* failure of this is serious. Do not ignore. */
sewardja5b50222015-03-26 07:18:32 +00003132 UInt xN = iregEnc(am->ARM64am.RI12.reg);
sewardjbbcf1882014-01-12 12:49:10 +00003133 vassert(xN <= 30);
3134 UInt instr = X_2_6_2_12_5_5(X01, X111001, isLoad ? X01 : X00,
3135 uimm12, xN, wD);
3136 *p++ = instr;
3137 return p;
3138 }
3139 if (am->tag == ARM64am_RR) {
3140 /* STRH Xd, [Xn|SP, Xm]: 01 111 000 001 m 011 0 10 n d
3141 LDRH Xd, [Xn|SP, Xm]: 01 111 000 011 m 011 0 10 n d
3142 */
sewardja5b50222015-03-26 07:18:32 +00003143 UInt xN = iregEnc(am->ARM64am.RR.base);
3144 UInt xM = iregEnc(am->ARM64am.RR.index);
sewardjbbcf1882014-01-12 12:49:10 +00003145 vassert(xN <= 30);
3146 UInt instr = X_3_8_5_6_5_5(X011, isLoad ? X11000011 : X11000001,
3147 xM, X011010, xN, wD);
3148 *p++ = instr;
3149 return p;
3150 }
3151 vpanic("do_load_or_store16");
3152 vassert(0);
3153}
3154
3155
3156/* Generate a 32 bit store or 32-to-64 unsigned widening load from/to
3157 rD, using the given amode for the address. */
3158static UInt* do_load_or_store32 ( UInt* p,
3159 Bool isLoad, UInt wD, ARM64AMode* am )
3160{
3161 vassert(wD <= 30);
3162 if (am->tag == ARM64am_RI9) {
3163 /* STUR Wd, [Xn|SP + simm9]: 10 111000 000 simm9 00 n d
3164 LDUR Wd, [Xn|SP + simm9]: 10 111000 010 simm9 00 n d
3165 */
3166 Int simm9 = am->ARM64am.RI9.simm9;
3167 vassert(-256 <= simm9 && simm9 <= 255);
3168 UInt instr = X_2_6_3_9_2_5_5(X10, X111000, isLoad ? X010 : X000,
3169 simm9 & 0x1FF, X00,
sewardja5b50222015-03-26 07:18:32 +00003170 iregEnc(am->ARM64am.RI9.reg), wD);
sewardjbbcf1882014-01-12 12:49:10 +00003171 *p++ = instr;
3172 return p;
3173 }
3174 if (am->tag == ARM64am_RI12) {
3175 /* STR Wd, [Xn|SP + uimm12 * 4]: 10 111 001 00 imm12 n d
3176 LDR Wd, [Xn|SP + uimm12 * 4]: 10 111 001 01 imm12 n d
3177 */
3178 UInt uimm12 = am->ARM64am.RI12.uimm12;
3179 UInt scale = am->ARM64am.RI12.szB;
3180 vassert(scale == 4); /* failure of this is serious. Do not ignore. */
sewardja5b50222015-03-26 07:18:32 +00003181 UInt xN = iregEnc(am->ARM64am.RI12.reg);
sewardjbbcf1882014-01-12 12:49:10 +00003182 vassert(xN <= 30);
3183 UInt instr = X_2_6_2_12_5_5(X10, X111001, isLoad ? X01 : X00,
3184 uimm12, xN, wD);
3185 *p++ = instr;
3186 return p;
3187 }
3188 if (am->tag == ARM64am_RR) {
3189 /* STR Wd, [Xn|SP, Xm]: 10 111 000 001 m 011 0 10 n d
3190 LDR Wd, [Xn|SP, Xm]: 10 111 000 011 m 011 0 10 n d
3191 */
sewardja5b50222015-03-26 07:18:32 +00003192 UInt xN = iregEnc(am->ARM64am.RR.base);
3193 UInt xM = iregEnc(am->ARM64am.RR.index);
sewardjbbcf1882014-01-12 12:49:10 +00003194 vassert(xN <= 30);
3195 UInt instr = X_3_8_5_6_5_5(X101, isLoad ? X11000011 : X11000001,
3196 xM, X011010, xN, wD);
3197 *p++ = instr;
3198 return p;
3199 }
3200 vpanic("do_load_or_store32");
3201 vassert(0);
3202}
3203
3204
3205/* Generate a 64 bit load or store to/from xD, using the given amode
3206 for the address. */
3207static UInt* do_load_or_store64 ( UInt* p,
3208 Bool isLoad, UInt xD, ARM64AMode* am )
3209{
3210 /* In all these cases, Rn can't be 31 since that means SP. */
3211 vassert(xD <= 30);
3212 if (am->tag == ARM64am_RI9) {
3213 /* STUR Xd, [Xn|SP + simm9]: 11 111000 000 simm9 00 n d
3214 LDUR Xd, [Xn|SP + simm9]: 11 111000 010 simm9 00 n d
3215 */
3216 Int simm9 = am->ARM64am.RI9.simm9;
3217 vassert(-256 <= simm9 && simm9 <= 255);
sewardja5b50222015-03-26 07:18:32 +00003218 UInt xN = iregEnc(am->ARM64am.RI9.reg);
sewardjbbcf1882014-01-12 12:49:10 +00003219 vassert(xN <= 30);
3220 UInt instr = X_2_6_3_9_2_5_5(X11, X111000, isLoad ? X010 : X000,
3221 simm9 & 0x1FF, X00, xN, xD);
3222 *p++ = instr;
3223 return p;
3224 }
3225 if (am->tag == ARM64am_RI12) {
3226 /* STR Xd, [Xn|SP + uimm12 * 8]: 11 111 001 00 imm12 n d
3227 LDR Xd, [Xn|SP + uimm12 * 8]: 11 111 001 01 imm12 n d
3228 */
3229 UInt uimm12 = am->ARM64am.RI12.uimm12;
3230 UInt scale = am->ARM64am.RI12.szB;
3231 vassert(scale == 8); /* failure of this is serious. Do not ignore. */
sewardja5b50222015-03-26 07:18:32 +00003232 UInt xN = iregEnc(am->ARM64am.RI12.reg);
sewardjbbcf1882014-01-12 12:49:10 +00003233 vassert(xN <= 30);
3234 UInt instr = X_2_6_2_12_5_5(X11, X111001, isLoad ? X01 : X00,
3235 uimm12, xN, xD);
3236 *p++ = instr;
3237 return p;
3238 }
3239 if (am->tag == ARM64am_RR) {
3240 /* STR Xd, [Xn|SP, Xm]: 11 111 000 001 m 011 0 10 n d
3241 LDR Xd, [Xn|SP, Xm]: 11 111 000 011 m 011 0 10 n d
3242 */
sewardja5b50222015-03-26 07:18:32 +00003243 UInt xN = iregEnc(am->ARM64am.RR.base);
3244 UInt xM = iregEnc(am->ARM64am.RR.index);
sewardjbbcf1882014-01-12 12:49:10 +00003245 vassert(xN <= 30);
3246 UInt instr = X_3_8_5_6_5_5(X111, isLoad ? X11000011 : X11000001,
3247 xM, X011010, xN, xD);
3248 *p++ = instr;
3249 return p;
3250 }
3251 vpanic("do_load_or_store64");
3252 vassert(0);
3253}
3254
3255
3256/* Emit an instruction into buf and return the number of bytes used.
3257 Note that buf is not the insn's final place, and therefore it is
3258 imperative to emit position-independent code. If the emitted
3259 instruction was a profiler inc, set *is_profInc to True, else
3260 leave it unchanged. */
3261
3262Int emit_ARM64Instr ( /*MB_MOD*/Bool* is_profInc,
floriand8c64e02014-10-08 08:54:44 +00003263 UChar* buf, Int nbuf, const ARM64Instr* i,
sewardj9b769162014-07-24 12:42:03 +00003264 Bool mode64, VexEndness endness_host,
florian8462d112014-09-24 15:18:09 +00003265 const void* disp_cp_chain_me_to_slowEP,
3266 const void* disp_cp_chain_me_to_fastEP,
3267 const void* disp_cp_xindir,
3268 const void* disp_cp_xassisted )
sewardjbbcf1882014-01-12 12:49:10 +00003269{
3270 UInt* p = (UInt*)buf;
3271 vassert(nbuf >= 32);
3272 vassert(mode64 == True);
3273 vassert(0 == (((HWord)buf) & 3));
3274
3275 switch (i->tag) {
3276 case ARM64in_Arith: {
sewardja5b50222015-03-26 07:18:32 +00003277 UInt rD = iregEnc(i->ARM64in.Arith.dst);
3278 UInt rN = iregEnc(i->ARM64in.Arith.argL);
sewardjbbcf1882014-01-12 12:49:10 +00003279 ARM64RIA* argR = i->ARM64in.Arith.argR;
3280 switch (argR->tag) {
3281 case ARM64riA_I12:
3282 *p++ = X_2_6_2_12_5_5(
3283 i->ARM64in.Arith.isAdd ? X10 : X11,
3284 X010001,
3285 argR->ARM64riA.I12.shift == 12 ? X01 : X00,
3286 argR->ARM64riA.I12.imm12, rN, rD
3287 );
3288 break;
3289 case ARM64riA_R: {
sewardja5b50222015-03-26 07:18:32 +00003290 UInt rM = iregEnc(i->ARM64in.Arith.argR->ARM64riA.R.reg);
sewardjbbcf1882014-01-12 12:49:10 +00003291 *p++ = X_3_8_5_6_5_5(
3292 i->ARM64in.Arith.isAdd ? X100 : X110,
3293 X01011000, rM, X000000, rN, rD
3294 );
3295 break;
3296 }
3297 default:
3298 goto bad;
3299 }
3300 goto done;
3301 }
3302 case ARM64in_Cmp: {
3303 UInt rD = 31; /* XZR, we are going to dump the result */
sewardja5b50222015-03-26 07:18:32 +00003304 UInt rN = iregEnc(i->ARM64in.Cmp.argL);
sewardjbbcf1882014-01-12 12:49:10 +00003305 ARM64RIA* argR = i->ARM64in.Cmp.argR;
3306 Bool is64 = i->ARM64in.Cmp.is64;
3307 switch (argR->tag) {
3308 case ARM64riA_I12:
3309 /* 1 11 10001 sh imm12 Rn Rd = SUBS Xd, Xn, #imm */
3310 /* 0 11 10001 sh imm12 Rn Rd = SUBS Wd, Wn, #imm */
3311 *p++ = X_2_6_2_12_5_5(
3312 is64 ? X11 : X01, X110001,
3313 argR->ARM64riA.I12.shift == 12 ? X01 : X00,
3314 argR->ARM64riA.I12.imm12, rN, rD);
3315 break;
3316 case ARM64riA_R: {
3317 /* 1 11 01011 00 0 Rm 000000 Rn Rd = SUBS Xd, Xn, Xm */
3318 /* 0 11 01011 00 0 Rm 000000 Rn Rd = SUBS Wd, Wn, Wm */
sewardja5b50222015-03-26 07:18:32 +00003319 UInt rM = iregEnc(i->ARM64in.Cmp.argR->ARM64riA.R.reg);
sewardjbbcf1882014-01-12 12:49:10 +00003320 *p++ = X_3_8_5_6_5_5(is64 ? X111 : X011,
3321 X01011000, rM, X000000, rN, rD);
3322 break;
3323 }
3324 default:
3325 goto bad;
3326 }
3327 goto done;
3328 }
3329 case ARM64in_Logic: {
sewardja5b50222015-03-26 07:18:32 +00003330 UInt rD = iregEnc(i->ARM64in.Logic.dst);
3331 UInt rN = iregEnc(i->ARM64in.Logic.argL);
sewardjbbcf1882014-01-12 12:49:10 +00003332 ARM64RIL* argR = i->ARM64in.Logic.argR;
3333 UInt opc = 0; /* invalid */
3334 vassert(rD < 31);
3335 vassert(rN < 31);
3336 switch (i->ARM64in.Logic.op) {
3337 case ARM64lo_OR: opc = X101; break;
3338 case ARM64lo_AND: opc = X100; break;
3339 case ARM64lo_XOR: opc = X110; break;
3340 default: break;
3341 }
3342 vassert(opc != 0);
3343 switch (argR->tag) {
3344 case ARM64riL_I13: {
3345 /* 1 01 100100 N immR immS Rn Rd = ORR <Xd|Sp>, Xn, #imm */
3346 /* 1 00 100100 N immR immS Rn Rd = AND <Xd|Sp>, Xn, #imm */
3347 /* 1 10 100100 N immR immS Rn Rd = EOR <Xd|Sp>, Xn, #imm */
3348 *p++ = X_3_6_1_6_6_5_5(
3349 opc, X100100, argR->ARM64riL.I13.bitN,
3350 argR->ARM64riL.I13.immR, argR->ARM64riL.I13.immS,
3351 rN, rD
3352 );
3353 break;
3354 }
3355 case ARM64riL_R: {
3356 /* 1 01 01010 00 0 m 000000 n d = ORR Xd, Xn, Xm */
3357 /* 1 00 01010 00 0 m 000000 n d = AND Xd, Xn, Xm */
3358 /* 1 10 01010 00 0 m 000000 n d = EOR Xd, Xn, Xm */
sewardja5b50222015-03-26 07:18:32 +00003359 UInt rM = iregEnc(argR->ARM64riL.R.reg);
sewardjbbcf1882014-01-12 12:49:10 +00003360 vassert(rM < 31);
3361 *p++ = X_3_8_5_6_5_5(opc, X01010000, rM, X000000, rN, rD);
3362 break;
3363 }
3364 default:
3365 goto bad;
3366 }
3367 goto done;
3368 }
3369 case ARM64in_Test: {
3370 UInt rD = 31; /* XZR, we are going to dump the result */
sewardja5b50222015-03-26 07:18:32 +00003371 UInt rN = iregEnc(i->ARM64in.Test.argL);
sewardjbbcf1882014-01-12 12:49:10 +00003372 ARM64RIL* argR = i->ARM64in.Test.argR;
3373 switch (argR->tag) {
3374 case ARM64riL_I13: {
3375 /* 1 11 100100 N immR immS Rn Rd = ANDS Xd, Xn, #imm */
3376 *p++ = X_3_6_1_6_6_5_5(
3377 X111, X100100, argR->ARM64riL.I13.bitN,
3378 argR->ARM64riL.I13.immR, argR->ARM64riL.I13.immS,
3379 rN, rD
3380 );
3381 break;
3382 }
3383 default:
3384 goto bad;
3385 }
3386 goto done;
3387 }
3388 case ARM64in_Shift: {
sewardja5b50222015-03-26 07:18:32 +00003389 UInt rD = iregEnc(i->ARM64in.Shift.dst);
3390 UInt rN = iregEnc(i->ARM64in.Shift.argL);
sewardjbbcf1882014-01-12 12:49:10 +00003391 ARM64RI6* argR = i->ARM64in.Shift.argR;
3392 vassert(rD < 31);
3393 vassert(rN < 31);
3394 switch (argR->tag) {
3395 case ARM64ri6_I6: {
3396 /* 110 1001101 (63-sh) (64-sh) nn dd LSL Xd, Xn, sh */
3397 /* 110 1001101 sh 63 nn dd LSR Xd, Xn, sh */
3398 /* 100 1001101 sh 63 nn dd ASR Xd, Xn, sh */
3399 UInt sh = argR->ARM64ri6.I6.imm6;
3400 vassert(sh > 0 && sh < 64);
3401 switch (i->ARM64in.Shift.op) {
3402 case ARM64sh_SHL:
3403 *p++ = X_3_6_1_6_6_5_5(X110, X100110,
3404 1, 64-sh, 63-sh, rN, rD);
3405 break;
3406 case ARM64sh_SHR:
3407 *p++ = X_3_6_1_6_6_5_5(X110, X100110, 1, sh, 63, rN, rD);
3408 break;
3409 case ARM64sh_SAR:
3410 *p++ = X_3_6_1_6_6_5_5(X100, X100110, 1, sh, 63, rN, rD);
3411 break;
3412 default:
3413 vassert(0);
3414 }
3415 break;
3416 }
3417 case ARM64ri6_R: {
3418 /* 100 1101 0110 mm 001000 nn dd LSL Xd, Xn, Xm */
3419 /* 100 1101 0110 mm 001001 nn dd LSR Xd, Xn, Xm */
3420 /* 100 1101 0110 mm 001010 nn dd ASR Xd, Xn, Xm */
sewardja5b50222015-03-26 07:18:32 +00003421 UInt rM = iregEnc(argR->ARM64ri6.R.reg);
sewardjbbcf1882014-01-12 12:49:10 +00003422 vassert(rM < 31);
3423 UInt subOpc = 0;
3424 switch (i->ARM64in.Shift.op) {
3425 case ARM64sh_SHL: subOpc = X001000; break;
3426 case ARM64sh_SHR: subOpc = X001001; break;
3427 case ARM64sh_SAR: subOpc = X001010; break;
3428 default: vassert(0);
3429 }
3430 *p++ = X_3_8_5_6_5_5(X100, X11010110, rM, subOpc, rN, rD);
3431 break;
3432 }
3433 default:
3434 vassert(0);
3435 }
3436 goto done;
3437 }
3438 case ARM64in_Unary: {
sewardja5b50222015-03-26 07:18:32 +00003439 UInt rDst = iregEnc(i->ARM64in.Unary.dst);
3440 UInt rSrc = iregEnc(i->ARM64in.Unary.src);
sewardjbbcf1882014-01-12 12:49:10 +00003441 switch (i->ARM64in.Unary.op) {
3442 case ARM64un_CLZ:
3443 /* 1 10 1101 0110 00000 00010 0 nn dd CLZ Xd, Xn */
3444 /* 1 10 1101 0110 00000 00010 1 nn dd CLS Xd, Xn (unimp) */
3445 *p++ = X_3_8_5_6_5_5(X110,
3446 X11010110, X00000, X000100, rSrc, rDst);
3447 goto done;
3448 case ARM64un_NEG:
3449 /* 1 10 01011 000 m 000000 11111 d NEG Xd,Xm */
3450 /* 0 10 01011 000 m 000000 11111 d NEG Wd,Wm (unimp) */
3451 *p++ = X_3_8_5_6_5_5(X110,
3452 X01011000, rSrc, X000000, X11111, rDst);
3453 goto done;
3454 case ARM64un_NOT: {
3455 /* 1 01 01010 00 1 m 000000 11111 d MVN Xd,Xm */
3456 *p++ = X_3_8_5_6_5_5(X101,
3457 X01010001, rSrc, X000000, X11111, rDst);
3458 goto done;
3459 }
3460 default:
3461 break;
3462 }
3463 goto bad;
3464 }
3465 case ARM64in_MovI: {
3466 /* We generate the "preferred form", ORR Xd, XZR, Xm
3467 101 01010 00 0 m 000000 11111 d
3468 */
3469 UInt instr = 0xAA0003E0;
sewardja5b50222015-03-26 07:18:32 +00003470 UInt d = iregEnc(i->ARM64in.MovI.dst);
3471 UInt m = iregEnc(i->ARM64in.MovI.src);
sewardjbbcf1882014-01-12 12:49:10 +00003472 *p++ = instr | ((m & 31) << 16) | ((d & 31) << 0);
3473 goto done;
3474 }
3475 case ARM64in_Imm64: {
sewardja5b50222015-03-26 07:18:32 +00003476 p = imm64_to_ireg( p, iregEnc(i->ARM64in.Imm64.dst),
3477 i->ARM64in.Imm64.imm64 );
sewardjbbcf1882014-01-12 12:49:10 +00003478 goto done;
3479 }
3480 case ARM64in_LdSt64: {
3481 p = do_load_or_store64( p, i->ARM64in.LdSt64.isLoad,
sewardja5b50222015-03-26 07:18:32 +00003482 iregEnc(i->ARM64in.LdSt64.rD),
sewardjbbcf1882014-01-12 12:49:10 +00003483 i->ARM64in.LdSt64.amode );
3484 goto done;
3485 }
3486 case ARM64in_LdSt32: {
3487 p = do_load_or_store32( p, i->ARM64in.LdSt32.isLoad,
sewardja5b50222015-03-26 07:18:32 +00003488 iregEnc(i->ARM64in.LdSt32.rD),
sewardjbbcf1882014-01-12 12:49:10 +00003489 i->ARM64in.LdSt32.amode );
3490 goto done;
3491 }
3492 case ARM64in_LdSt16: {
3493 p = do_load_or_store16( p, i->ARM64in.LdSt16.isLoad,
sewardja5b50222015-03-26 07:18:32 +00003494 iregEnc(i->ARM64in.LdSt16.rD),
sewardjbbcf1882014-01-12 12:49:10 +00003495 i->ARM64in.LdSt16.amode );
3496 goto done;
3497 }
3498 case ARM64in_LdSt8: {
3499 p = do_load_or_store8( p, i->ARM64in.LdSt8.isLoad,
sewardja5b50222015-03-26 07:18:32 +00003500 iregEnc(i->ARM64in.LdSt8.rD),
sewardjbbcf1882014-01-12 12:49:10 +00003501 i->ARM64in.LdSt8.amode );
3502 goto done;
3503 }
sewardjbbcf1882014-01-12 12:49:10 +00003504
3505 case ARM64in_XDirect: {
3506 /* NB: what goes on here has to be very closely coordinated
3507 with chainXDirect_ARM64 and unchainXDirect_ARM64 below. */
3508 /* We're generating chain-me requests here, so we need to be
3509 sure this is actually allowed -- no-redir translations
3510 can't use chain-me's. Hence: */
3511 vassert(disp_cp_chain_me_to_slowEP != NULL);
3512 vassert(disp_cp_chain_me_to_fastEP != NULL);
3513
3514 /* Use ptmp for backpatching conditional jumps. */
3515 UInt* ptmp = NULL;
3516
3517 /* First off, if this is conditional, create a conditional
3518 jump over the rest of it. Or at least, leave a space for
3519 it that we will shortly fill in. */
3520 if (i->ARM64in.XDirect.cond != ARM64cc_AL) {
3521 vassert(i->ARM64in.XDirect.cond != ARM64cc_NV);
3522 ptmp = p;
3523 *p++ = 0;
3524 }
3525
3526 /* Update the guest PC. */
3527 /* imm64 x9, dstGA */
3528 /* str x9, amPC */
sewardja5b50222015-03-26 07:18:32 +00003529 p = imm64_to_ireg(p, /*x*/9, i->ARM64in.XDirect.dstGA);
sewardjbbcf1882014-01-12 12:49:10 +00003530 p = do_load_or_store64(p, False/*!isLoad*/,
3531 /*x*/9, i->ARM64in.XDirect.amPC);
3532
3533 /* --- FIRST PATCHABLE BYTE follows --- */
3534 /* VG_(disp_cp_chain_me_to_{slowEP,fastEP}) (where we're
3535 calling to) backs up the return address, so as to find the
3536 address of the first patchable byte. So: don't change the
3537 number of instructions (5) below. */
3538 /* movw x9, VG_(disp_cp_chain_me_to_{slowEP,fastEP})[15:0] */
3539 /* movk x9, VG_(disp_cp_chain_me_to_{slowEP,fastEP})[31:15], lsl 16 */
3540 /* movk x9, VG_(disp_cp_chain_me_to_{slowEP,fastEP})[47:32], lsl 32 */
3541 /* movk x9, VG_(disp_cp_chain_me_to_{slowEP,fastEP})[63:48], lsl 48 */
3542 /* blr x9 */
florian8462d112014-09-24 15:18:09 +00003543 const void* disp_cp_chain_me
sewardjbbcf1882014-01-12 12:49:10 +00003544 = i->ARM64in.XDirect.toFastEP ? disp_cp_chain_me_to_fastEP
3545 : disp_cp_chain_me_to_slowEP;
sewardja5b50222015-03-26 07:18:32 +00003546 p = imm64_to_ireg_EXACTLY4(p, /*x*/9, (Addr)disp_cp_chain_me);
sewardjbbcf1882014-01-12 12:49:10 +00003547 *p++ = 0xD63F0120;
3548 /* --- END of PATCHABLE BYTES --- */
3549
3550 /* Fix up the conditional jump, if there was one. */
3551 if (i->ARM64in.XDirect.cond != ARM64cc_AL) {
3552 Int delta = (UChar*)p - (UChar*)ptmp; /* must be signed */
3553 vassert(delta > 0 && delta < 40);
3554 vassert((delta & 3) == 0);
3555 UInt notCond = 1 ^ (UInt)i->ARM64in.XDirect.cond;
3556 vassert(notCond <= 13); /* Neither AL nor NV */
3557 vassert(ptmp != NULL);
3558 delta = delta >> 2;
3559 *ptmp = X_8_19_1_4(X01010100, delta & ((1<<19)-1), 0, notCond);
3560 }
3561 goto done;
3562 }
3563
3564 case ARM64in_XIndir: {
3565 // XIndir is more or less the same as XAssisted, except
3566 // we don't have a trc value to hand back, so there's no
3567 // write to r21
3568 /* Use ptmp for backpatching conditional jumps. */
3569 //UInt* ptmp = NULL;
3570
3571 /* First off, if this is conditional, create a conditional
3572 jump over the rest of it. Or at least, leave a space for
3573 it that we will shortly fill in. */
3574 if (i->ARM64in.XIndir.cond != ARM64cc_AL) {
3575 vassert(0); //ATC
3576//ZZ vassert(i->ARMin.XIndir.cond != ARMcc_NV);
3577//ZZ ptmp = p;
3578//ZZ *p++ = 0;
3579 }
3580
3581 /* Update the guest PC. */
3582 /* str r-dstGA, amPC */
3583 p = do_load_or_store64(p, False/*!isLoad*/,
sewardja5b50222015-03-26 07:18:32 +00003584 iregEnc(i->ARM64in.XIndir.dstGA),
sewardjbbcf1882014-01-12 12:49:10 +00003585 i->ARM64in.XIndir.amPC);
3586
3587 /* imm64 x9, VG_(disp_cp_xindir) */
3588 /* br x9 */
sewardja5b50222015-03-26 07:18:32 +00003589 p = imm64_to_ireg(p, /*x*/9, (Addr)disp_cp_xindir);
sewardjbbcf1882014-01-12 12:49:10 +00003590 *p++ = 0xD61F0120; /* br x9 */
3591
3592 /* Fix up the conditional jump, if there was one. */
3593 if (i->ARM64in.XIndir.cond != ARM64cc_AL) {
3594 vassert(0); //ATC
3595//ZZ Int delta = (UChar*)p - (UChar*)ptmp; /* must be signed */
3596//ZZ vassert(delta > 0 && delta < 40);
3597//ZZ vassert((delta & 3) == 0);
3598//ZZ UInt notCond = 1 ^ (UInt)i->ARMin.XIndir.cond;
3599//ZZ vassert(notCond <= 13); /* Neither AL nor NV */
3600//ZZ delta = (delta >> 2) - 2;
3601//ZZ *ptmp = XX______(notCond, X1010) | (delta & 0xFFFFFF);
3602 }
3603 goto done;
3604 }
3605
3606 case ARM64in_XAssisted: {
3607 /* Use ptmp for backpatching conditional jumps. */
3608 UInt* ptmp = NULL;
3609
3610 /* First off, if this is conditional, create a conditional
3611 jump over the rest of it. Or at least, leave a space for
3612 it that we will shortly fill in. I think this can only
3613 ever happen when VEX is driven by the switchbacker. */
3614 if (i->ARM64in.XAssisted.cond != ARM64cc_AL) {
3615 vassert(i->ARM64in.XDirect.cond != ARM64cc_NV);
3616 ptmp = p;
3617 *p++ = 0;
3618 }
3619
3620 /* Update the guest PC. */
3621 /* str r-dstGA, amPC */
3622 p = do_load_or_store64(p, False/*!isLoad*/,
sewardja5b50222015-03-26 07:18:32 +00003623 iregEnc(i->ARM64in.XAssisted.dstGA),
sewardjbbcf1882014-01-12 12:49:10 +00003624 i->ARM64in.XAssisted.amPC);
3625
3626 /* movw r21, $magic_number */
3627 UInt trcval = 0;
3628 switch (i->ARM64in.XAssisted.jk) {
3629 case Ijk_ClientReq: trcval = VEX_TRC_JMP_CLIENTREQ; break;
3630 case Ijk_Sys_syscall: trcval = VEX_TRC_JMP_SYS_SYSCALL; break;
3631 //case Ijk_Sys_int128: trcval = VEX_TRC_JMP_SYS_INT128; break;
sewardje3115c12015-08-18 19:55:16 +00003632 case Ijk_Yield: trcval = VEX_TRC_JMP_YIELD; break;
sewardjbbcf1882014-01-12 12:49:10 +00003633 //case Ijk_EmWarn: trcval = VEX_TRC_JMP_EMWARN; break;
3634 //case Ijk_MapFail: trcval = VEX_TRC_JMP_MAPFAIL; break;
3635 case Ijk_NoDecode: trcval = VEX_TRC_JMP_NODECODE; break;
sewardj05f5e012014-05-04 10:52:11 +00003636 case Ijk_InvalICache: trcval = VEX_TRC_JMP_INVALICACHE; break;
sewardj65902992014-05-03 21:20:56 +00003637 case Ijk_FlushDCache: trcval = VEX_TRC_JMP_FLUSHDCACHE; break;
sewardj99c1f812014-03-09 09:41:56 +00003638 case Ijk_NoRedir: trcval = VEX_TRC_JMP_NOREDIR; break;
sewardj39b51682014-11-25 12:17:53 +00003639 case Ijk_SigTRAP: trcval = VEX_TRC_JMP_SIGTRAP; break;
sewardjbbcf1882014-01-12 12:49:10 +00003640 //case Ijk_SigSEGV: trcval = VEX_TRC_JMP_SIGSEGV; break;
3641 case Ijk_Boring: trcval = VEX_TRC_JMP_BORING; break;
3642 /* We don't expect to see the following being assisted. */
3643 //case Ijk_Ret:
3644 //case Ijk_Call:
3645 /* fallthrough */
3646 default:
3647 ppIRJumpKind(i->ARM64in.XAssisted.jk);
3648 vpanic("emit_ARM64Instr.ARM64in_XAssisted: "
3649 "unexpected jump kind");
3650 }
3651 vassert(trcval != 0);
sewardja5b50222015-03-26 07:18:32 +00003652 p = imm64_to_ireg(p, /*x*/21, (ULong)trcval);
sewardjbbcf1882014-01-12 12:49:10 +00003653
3654 /* imm64 x9, VG_(disp_cp_xassisted) */
3655 /* br x9 */
sewardja5b50222015-03-26 07:18:32 +00003656 p = imm64_to_ireg(p, /*x*/9, (Addr)disp_cp_xassisted);
sewardjbbcf1882014-01-12 12:49:10 +00003657 *p++ = 0xD61F0120; /* br x9 */
3658
3659 /* Fix up the conditional jump, if there was one. */
3660 if (i->ARM64in.XAssisted.cond != ARM64cc_AL) {
3661 Int delta = (UChar*)p - (UChar*)ptmp; /* must be signed */
3662 vassert(delta > 0 && delta < 40);
3663 vassert((delta & 3) == 0);
3664 UInt notCond = 1 ^ (UInt)i->ARM64in.XDirect.cond;
3665 vassert(notCond <= 13); /* Neither AL nor NV */
3666 vassert(ptmp != NULL);
3667 delta = delta >> 2;
3668 *ptmp = X_8_19_1_4(X01010100, delta & ((1<<19)-1), 0, notCond);
3669 }
3670 goto done;
3671 }
3672
3673 case ARM64in_CSel: {
3674 /* 100 1101 0100 mm cond 00 nn dd = CSEL Xd, Xn, Xm, cond */
sewardja5b50222015-03-26 07:18:32 +00003675 UInt dd = iregEnc(i->ARM64in.CSel.dst);
3676 UInt nn = iregEnc(i->ARM64in.CSel.argL);
3677 UInt mm = iregEnc(i->ARM64in.CSel.argR);
sewardjbbcf1882014-01-12 12:49:10 +00003678 UInt cond = (UInt)i->ARM64in.CSel.cond;
3679 vassert(dd < 31 && nn < 31 && mm < 31 && cond < 16);
3680 *p++ = X_3_8_5_6_5_5(X100, X11010100, mm, cond << 2, nn, dd);
3681 goto done;
3682 }
3683
3684 case ARM64in_Call: {
3685 /* We'll use x9 as a scratch register to put the target
3686 address in. */
3687 if (i->ARM64in.Call.cond != ARM64cc_AL
3688 && i->ARM64in.Call.rloc.pri != RLPri_None) {
3689 /* The call might not happen (it isn't unconditional) and
3690 it returns a result. In this case we will need to
3691 generate a control flow diamond to put 0x555..555 in
3692 the return register(s) in the case where the call
3693 doesn't happen. If this ever becomes necessary, maybe
3694 copy code from the 32-bit ARM equivalent. Until that
3695 day, just give up. */
3696 goto bad;
3697 }
3698
3699 UInt* ptmp = NULL;
3700 if (i->ARM64in.Call.cond != ARM64cc_AL) {
3701 /* Create a hole to put a conditional branch in. We'll
3702 patch it once we know the branch length. */
3703 ptmp = p;
3704 *p++ = 0;
3705 }
3706
3707 // x9 = &target
sewardja5b50222015-03-26 07:18:32 +00003708 p = imm64_to_ireg( (UInt*)p, /*x*/9, (ULong)i->ARM64in.Call.target );
sewardjbbcf1882014-01-12 12:49:10 +00003709 // blr x9
3710 *p++ = 0xD63F0120;
3711
3712 // Patch the hole if necessary
3713 if (i->ARM64in.Call.cond != ARM64cc_AL) {
3714 ULong dist = (ULong)(p - ptmp);
sewardja5b50222015-03-26 07:18:32 +00003715 /* imm64_to_ireg produces between 1 and 4 insns, and
sewardjbbcf1882014-01-12 12:49:10 +00003716 then there's the BLR itself. Hence: */
3717 vassert(dist >= 2 && dist <= 5);
3718 vassert(ptmp != NULL);
3719 // 01010100 simm19 0 cond = B.cond (here + simm19 << 2)
3720 *ptmp = X_8_19_1_4(X01010100, dist, 0,
3721 1 ^ (UInt)i->ARM64in.Call.cond);
3722 } else {
3723 vassert(ptmp == NULL);
3724 }
3725
3726 goto done;
3727 }
3728
3729 case ARM64in_AddToSP: {
3730 /* 10,0 10001 00 imm12 11111 11111 ADD xsp, xsp, #imm12
3731 11,0 10001 00 imm12 11111 11111 SUB xsp, xsp, #imm12
3732 */
3733 Int simm12 = i->ARM64in.AddToSP.simm;
3734 vassert(-4096 < simm12 && simm12 < 4096);
3735 vassert(0 == (simm12 & 0xF));
3736 if (simm12 >= 0) {
3737 *p++ = X_2_6_2_12_5_5(X10, X010001, X00, simm12, X11111, X11111);
3738 } else {
3739 *p++ = X_2_6_2_12_5_5(X11, X010001, X00, -simm12, X11111, X11111);
3740 }
3741 goto done;
3742 }
3743
3744 case ARM64in_FromSP: {
3745 /* 10,0 10001 00 0..(12)..0 11111 dd MOV Xd, xsp */
sewardja5b50222015-03-26 07:18:32 +00003746 UInt dd = iregEnc(i->ARM64in.FromSP.dst);
sewardjbbcf1882014-01-12 12:49:10 +00003747 vassert(dd < 31);
3748 *p++ = X_2_6_2_12_5_5(X10, X010001, X00, 0, X11111, dd);
3749 goto done;
3750 }
3751
3752 case ARM64in_Mul: {
3753 /* 100 11011 110 mm 011111 nn dd UMULH Xd, Xn,Xm
3754 100 11011 010 mm 011111 nn dd SMULH Xd, Xn,Xm
3755 100 11011 000 mm 011111 nn dd MUL Xd, Xn,Xm
3756 */
sewardja5b50222015-03-26 07:18:32 +00003757 UInt dd = iregEnc(i->ARM64in.Mul.dst);
3758 UInt nn = iregEnc(i->ARM64in.Mul.argL);
3759 UInt mm = iregEnc(i->ARM64in.Mul.argR);
sewardjbbcf1882014-01-12 12:49:10 +00003760 vassert(dd < 31 && nn < 31 && mm < 31);
3761 switch (i->ARM64in.Mul.op) {
3762 case ARM64mul_ZX:
3763 *p++ = X_3_8_5_6_5_5(X100, X11011110, mm, X011111, nn, dd);
3764 goto done;
sewardj7fce7cc2014-05-07 09:41:40 +00003765 case ARM64mul_SX:
3766 *p++ = X_3_8_5_6_5_5(X100, X11011010, mm, X011111, nn, dd);
3767 goto done;
sewardjbbcf1882014-01-12 12:49:10 +00003768 case ARM64mul_PLAIN:
3769 *p++ = X_3_8_5_6_5_5(X100, X11011000, mm, X011111, nn, dd);
3770 goto done;
3771 default:
3772 vassert(0);
3773 }
3774 goto bad;
3775 }
sewardj7d009132014-02-20 17:43:38 +00003776 case ARM64in_LdrEX: {
3777 /* 085F7C82 ldxrb w2, [x4]
3778 485F7C82 ldxrh w2, [x4]
3779 885F7C82 ldxr w2, [x4]
3780 C85F7C82 ldxr x2, [x4]
3781 */
3782 switch (i->ARM64in.LdrEX.szB) {
3783 case 1: *p++ = 0x085F7C82; goto done;
3784 case 2: *p++ = 0x485F7C82; goto done;
3785 case 4: *p++ = 0x885F7C82; goto done;
3786 case 8: *p++ = 0xC85F7C82; goto done;
3787 default: break;
3788 }
3789 goto bad;
3790 }
3791 case ARM64in_StrEX: {
3792 /* 08007C82 stxrb w0, w2, [x4]
3793 48007C82 stxrh w0, w2, [x4]
3794 88007C82 stxr w0, w2, [x4]
3795 C8007C82 stxr w0, x2, [x4]
3796 */
3797 switch (i->ARM64in.StrEX.szB) {
3798 case 1: *p++ = 0x08007C82; goto done;
3799 case 2: *p++ = 0x48007C82; goto done;
3800 case 4: *p++ = 0x88007C82; goto done;
3801 case 8: *p++ = 0xC8007C82; goto done;
3802 default: break;
3803 }
3804 goto bad;
3805 }
3806 case ARM64in_MFence: {
3807 *p++ = 0xD5033F9F; /* DSB sy */
3808 *p++ = 0xD5033FBF; /* DMB sy */
3809 *p++ = 0xD5033FDF; /* ISB */
3810 goto done;
3811 }
Elliott Hughesa0664b92017-04-18 17:46:52 -07003812 case ARM64in_ClrEX: {
3813 *p++ = 0xD5033F5F; /* clrex #15 */
3814 goto done;
3815 }
sewardj400d6b92015-03-30 09:01:51 +00003816 case ARM64in_VLdStH: {
3817 /* 01 111101 01 imm12 n t LDR Ht, [Xn|SP, #imm12 * 2]
3818 01 111101 00 imm12 n t STR Ht, [Xn|SP, #imm12 * 2]
3819 */
3820 UInt hD = dregEnc(i->ARM64in.VLdStH.hD);
3821 UInt rN = iregEnc(i->ARM64in.VLdStH.rN);
3822 UInt uimm12 = i->ARM64in.VLdStH.uimm12;
3823 Bool isLD = i->ARM64in.VLdStH.isLoad;
3824 vassert(uimm12 < 8192 && 0 == (uimm12 & 1));
3825 uimm12 >>= 1;
3826 vassert(uimm12 < (1<<12));
3827 vassert(hD < 32);
3828 vassert(rN < 31);
3829 *p++ = X_2_6_2_12_5_5(X01, X111101, isLD ? X01 : X00,
3830 uimm12, rN, hD);
3831 goto done;
3832 }
sewardjbbcf1882014-01-12 12:49:10 +00003833 case ARM64in_VLdStS: {
3834 /* 10 111101 01 imm12 n t LDR St, [Xn|SP, #imm12 * 4]
3835 10 111101 00 imm12 n t STR St, [Xn|SP, #imm12 * 4]
3836 */
sewardja5b50222015-03-26 07:18:32 +00003837 UInt sD = dregEnc(i->ARM64in.VLdStS.sD);
3838 UInt rN = iregEnc(i->ARM64in.VLdStS.rN);
sewardjbbcf1882014-01-12 12:49:10 +00003839 UInt uimm12 = i->ARM64in.VLdStS.uimm12;
3840 Bool isLD = i->ARM64in.VLdStS.isLoad;
3841 vassert(uimm12 < 16384 && 0 == (uimm12 & 3));
3842 uimm12 >>= 2;
3843 vassert(uimm12 < (1<<12));
3844 vassert(sD < 32);
3845 vassert(rN < 31);
3846 *p++ = X_2_6_2_12_5_5(X10, X111101, isLD ? X01 : X00,
3847 uimm12, rN, sD);
3848 goto done;
3849 }
3850 case ARM64in_VLdStD: {
3851 /* 11 111101 01 imm12 n t LDR Dt, [Xn|SP, #imm12 * 8]
3852 11 111101 00 imm12 n t STR Dt, [Xn|SP, #imm12 * 8]
3853 */
sewardja5b50222015-03-26 07:18:32 +00003854 UInt dD = dregEnc(i->ARM64in.VLdStD.dD);
3855 UInt rN = iregEnc(i->ARM64in.VLdStD.rN);
sewardjbbcf1882014-01-12 12:49:10 +00003856 UInt uimm12 = i->ARM64in.VLdStD.uimm12;
3857 Bool isLD = i->ARM64in.VLdStD.isLoad;
3858 vassert(uimm12 < 32768 && 0 == (uimm12 & 7));
3859 uimm12 >>= 3;
3860 vassert(uimm12 < (1<<12));
3861 vassert(dD < 32);
3862 vassert(rN < 31);
3863 *p++ = X_2_6_2_12_5_5(X11, X111101, isLD ? X01 : X00,
3864 uimm12, rN, dD);
3865 goto done;
3866 }
3867 case ARM64in_VLdStQ: {
3868 /* 0100 1100 0000 0000 0111 11 rN rQ st1 {vQ.2d}, [<rN|SP>]
3869 0100 1100 0100 0000 0111 11 rN rQ ld1 {vQ.2d}, [<rN|SP>]
3870 */
sewardja5b50222015-03-26 07:18:32 +00003871 UInt rQ = qregEnc(i->ARM64in.VLdStQ.rQ);
3872 UInt rN = iregEnc(i->ARM64in.VLdStQ.rN);
sewardjbbcf1882014-01-12 12:49:10 +00003873 vassert(rQ < 32);
3874 vassert(rN < 31);
3875 if (i->ARM64in.VLdStQ.isLoad) {
3876 *p++ = 0x4C407C00 | (rN << 5) | rQ;
3877 } else {
3878 *p++ = 0x4C007C00 | (rN << 5) | rQ;
3879 }
3880 goto done;
3881 }
3882 case ARM64in_VCvtI2F: {
3883 /* 31 28 23 21 20 18 15 9 4
3884 000 11110 00 1 00 010 000000 n d SCVTF Sd, Wn
3885 000 11110 01 1 00 010 000000 n d SCVTF Dd, Wn
sewardj606c4ba2014-01-26 19:11:14 +00003886 100 11110 00 1 00 010 000000 n d SCVTF Sd, Xn
sewardjbbcf1882014-01-12 12:49:10 +00003887 100 11110 01 1 00 010 000000 n d SCVTF Dd, Xn
3888 000 11110 00 1 00 011 000000 n d UCVTF Sd, Wn
3889 000 11110 01 1 00 011 000000 n d UCVTF Dd, Wn
3890 100 11110 00 1 00 011 000000 n d UCVTF Sd, Xn
3891 100 11110 01 1 00 011 000000 n d UCVTF Dd, Xn
3892 */
sewardja5b50222015-03-26 07:18:32 +00003893 UInt rN = iregEnc(i->ARM64in.VCvtI2F.rS);
3894 UInt rD = dregEnc(i->ARM64in.VCvtI2F.rD);
sewardjbbcf1882014-01-12 12:49:10 +00003895 ARM64CvtOp how = i->ARM64in.VCvtI2F.how;
3896 /* Just handle cases as they show up. */
3897 switch (how) {
3898 case ARM64cvt_F32_I32S: /* SCVTF Sd, Wn */
3899 *p++ = X_3_5_8_6_5_5(X000, X11110, X00100010, X000000, rN, rD);
3900 break;
3901 case ARM64cvt_F64_I32S: /* SCVTF Dd, Wn */
3902 *p++ = X_3_5_8_6_5_5(X000, X11110, X01100010, X000000, rN, rD);
3903 break;
3904 case ARM64cvt_F32_I64S: /* SCVTF Sd, Xn */
3905 *p++ = X_3_5_8_6_5_5(X100, X11110, X00100010, X000000, rN, rD);
3906 break;
3907 case ARM64cvt_F64_I64S: /* SCVTF Dd, Xn */
3908 *p++ = X_3_5_8_6_5_5(X100, X11110, X01100010, X000000, rN, rD);
3909 break;
sewardj1eaaec22014-03-07 22:52:19 +00003910 case ARM64cvt_F32_I32U: /* UCVTF Sd, Wn */
3911 *p++ = X_3_5_8_6_5_5(X000, X11110, X00100011, X000000, rN, rD);
3912 break;
sewardjbbcf1882014-01-12 12:49:10 +00003913 case ARM64cvt_F64_I32U: /* UCVTF Dd, Wn */
3914 *p++ = X_3_5_8_6_5_5(X000, X11110, X01100011, X000000, rN, rD);
3915 break;
3916 case ARM64cvt_F32_I64U: /* UCVTF Sd, Xn */
3917 *p++ = X_3_5_8_6_5_5(X100, X11110, X00100011, X000000, rN, rD);
3918 break;
3919 case ARM64cvt_F64_I64U: /* UCVTF Dd, Xn */
3920 *p++ = X_3_5_8_6_5_5(X100, X11110, X01100011, X000000, rN, rD);
3921 break;
3922 default:
3923 goto bad; //ATC
3924 }
3925 goto done;
3926 }
3927 case ARM64in_VCvtF2I: {
3928 /* 30 23 20 18 15 9 4
3929 sf 00,11110,0x 1 00 000,000000 n d FCVTNS Rd, Fn (round to
3930 sf 00,11110,0x 1 00 001,000000 n d FCVTNU Rd, Fn nearest)
3931 ---------------- 01 -------------- FCVTP-------- (round to +inf)
3932 ---------------- 10 -------------- FCVTM-------- (round to -inf)
3933 ---------------- 11 -------------- FCVTZ-------- (round to zero)
3934
3935 Rd is Xd when sf==1, Wd when sf==0
3936 Fn is Dn when x==1, Sn when x==0
3937 20:19 carry the rounding mode, using the same encoding as FPCR
3938 */
sewardja5b50222015-03-26 07:18:32 +00003939 UInt rD = iregEnc(i->ARM64in.VCvtF2I.rD);
3940 UInt rN = dregEnc(i->ARM64in.VCvtF2I.rS);
sewardjbbcf1882014-01-12 12:49:10 +00003941 ARM64CvtOp how = i->ARM64in.VCvtF2I.how;
3942 UChar armRM = i->ARM64in.VCvtF2I.armRM;
3943 /* Just handle cases as they show up. */
3944 switch (how) {
3945 case ARM64cvt_F64_I32S: /* FCVTxS Wd, Dn */
3946 *p++ = X_3_5_8_6_5_5(X000, X11110, X01100000 | (armRM << 3),
3947 X000000, rN, rD);
3948 break;
3949 case ARM64cvt_F64_I32U: /* FCVTxU Wd, Dn */
3950 *p++ = X_3_5_8_6_5_5(X000, X11110, X01100001 | (armRM << 3),
3951 X000000, rN, rD);
3952 break;
3953 case ARM64cvt_F64_I64S: /* FCVTxS Xd, Dn */
3954 *p++ = X_3_5_8_6_5_5(X100, X11110, X01100000 | (armRM << 3),
3955 X000000, rN, rD);
3956 break;
3957 case ARM64cvt_F64_I64U: /* FCVTxU Xd, Dn */
3958 *p++ = X_3_5_8_6_5_5(X100, X11110, X01100001 | (armRM << 3),
3959 X000000, rN, rD);
3960 break;
sewardjbbcf1882014-01-12 12:49:10 +00003961 case ARM64cvt_F32_I32S: /* FCVTxS Wd, Sn */
3962 *p++ = X_3_5_8_6_5_5(X000, X11110, X00100000 | (armRM << 3),
3963 X000000, rN, rD);
3964 break;
sewardj1eaaec22014-03-07 22:52:19 +00003965 case ARM64cvt_F32_I32U: /* FCVTxU Wd, Sn */
3966 *p++ = X_3_5_8_6_5_5(X000, X11110, X00100001 | (armRM << 3),
3967 X000000, rN, rD);
3968 break;
3969 case ARM64cvt_F32_I64S: /* FCVTxS Xd, Sn */
3970 *p++ = X_3_5_8_6_5_5(X100, X11110, X00100000 | (armRM << 3),
3971 X000000, rN, rD);
3972 break;
sewardjbbcf1882014-01-12 12:49:10 +00003973 case ARM64cvt_F32_I64U: /* FCVTxU Xd, Sn */
3974 *p++ = X_3_5_8_6_5_5(X100, X11110, X00100001 | (armRM << 3),
3975 X000000, rN, rD);
3976 break;
3977 default:
3978 goto bad; //ATC
3979 }
3980 goto done;
3981 }
3982 case ARM64in_VCvtSD: {
sewardj400d6b92015-03-30 09:01:51 +00003983 /* 31 23 21 16 14 9 4
sewardjbbcf1882014-01-12 12:49:10 +00003984 000,11110, 00 10001 0,1 10000 n d FCVT Dd, Sn (S->D)
3985 ---------- 01 ----- 0,0 --------- FCVT Sd, Dn (D->S)
3986 Rounding, when dst is smaller than src, is per the FPCR.
3987 */
sewardja5b50222015-03-26 07:18:32 +00003988 UInt dd = dregEnc(i->ARM64in.VCvtSD.dst);
3989 UInt nn = dregEnc(i->ARM64in.VCvtSD.src);
sewardjbbcf1882014-01-12 12:49:10 +00003990 if (i->ARM64in.VCvtSD.sToD) {
3991 *p++ = X_3_5_8_6_5_5(X000, X11110, X00100010, X110000, nn, dd);
3992 } else {
3993 *p++ = X_3_5_8_6_5_5(X000, X11110, X01100010, X010000, nn, dd);
3994 }
3995 goto done;
3996 }
sewardj400d6b92015-03-30 09:01:51 +00003997 case ARM64in_VCvtHS: {
3998 /* 31 23 21 16 14 9 4
3999 000,11110, 11 10001 0,0 10000 n d FCVT Sd, Hn (H->S)
4000 ---------- 00 ----- 1,1 --------- FCVT Hd, Sn (S->H)
4001 Rounding, when dst is smaller than src, is per the FPCR.
4002 */
4003 UInt dd = dregEnc(i->ARM64in.VCvtHS.dst);
4004 UInt nn = dregEnc(i->ARM64in.VCvtHS.src);
4005 if (i->ARM64in.VCvtHS.hToS) {
4006 *p++ = X_3_5_8_6_5_5(X000, X11110, X11100010, X010000, nn, dd);
4007 } else {
4008 *p++ = X_3_5_8_6_5_5(X000, X11110, X00100011, X110000, nn, dd);
4009 }
4010 goto done;
4011 }
4012 case ARM64in_VCvtHD: {
4013 /* 31 23 21 16 14 9 4
4014 000,11110, 11 10001 0,1 10000 n d FCVT Dd, Hn (H->D)
4015 ---------- 01 ----- 1,1 --------- FCVT Hd, Dn (D->H)
4016 Rounding, when dst is smaller than src, is per the FPCR.
4017 */
4018 UInt dd = dregEnc(i->ARM64in.VCvtHD.dst);
4019 UInt nn = dregEnc(i->ARM64in.VCvtHD.src);
4020 if (i->ARM64in.VCvtHD.hToD) {
4021 *p++ = X_3_5_8_6_5_5(X000, X11110, X11100010, X110000, nn, dd);
4022 } else {
4023 *p++ = X_3_5_8_6_5_5(X000, X11110, X01100011, X110000, nn, dd);
4024 }
4025 goto done;
4026 }
sewardjbbcf1882014-01-12 12:49:10 +00004027 case ARM64in_VUnaryD: {
4028 /* 31 23 21 16 14 9 4
4029 000,11110 01 1,0000 0,0 10000 n d FMOV Dd, Dn (not handled)
4030 ------------------- 0,1 --------- FABS ------
4031 ------------------- 1,0 --------- FNEG ------
sewardj89cefe42015-02-24 12:21:01 +00004032 ------------------- 1,1 --------- FSQRT -----
sewardjbbcf1882014-01-12 12:49:10 +00004033 */
sewardja5b50222015-03-26 07:18:32 +00004034 UInt dD = dregEnc(i->ARM64in.VUnaryD.dst);
4035 UInt dN = dregEnc(i->ARM64in.VUnaryD.src);
sewardjbbcf1882014-01-12 12:49:10 +00004036 UInt b16 = 2; /* impossible */
4037 UInt b15 = 2; /* impossible */
4038 switch (i->ARM64in.VUnaryD.op) {
4039 case ARM64fpu_NEG: b16 = 1; b15 = 0; break;
4040 case ARM64fpu_SQRT: b16 = 1; b15 = 1; break;
4041 case ARM64fpu_ABS: b16 = 0; b15 = 1; break;
4042 default: break;
4043 }
4044 if (b16 < 2 && b15 < 2) {
4045 *p++ = X_3_8_5_6_5_5(X000, X11110011, (X0000 << 1) | b16,
4046 (b15 << 5) | X10000, dN, dD);
4047 goto done;
4048 }
4049 /*
4050 000, 11110 01 1,001 11,1 10000 n d FRINTI Dd, Dm (round per FPCR)
4051 */
4052 if (i->ARM64in.VUnaryD.op == ARM64fpu_RINT) {
4053 *p++ = X_3_8_5_6_5_5(X000, X11110011, X00111, X110000, dN, dD);
4054 goto done;
4055 }
sewardj89cefe42015-02-24 12:21:01 +00004056 /*
4057 010, 11110 11 1,0000 1,1111 10 n d FRECPX Dd, Dm
4058 */
4059 if (i->ARM64in.VUnaryD.op == ARM64fpu_RECPX) {
4060 *p++ = X_3_8_5_6_5_5(X010, X11110111, X00001, X111110, dN, dD);
4061 goto done;
4062 }
sewardjbbcf1882014-01-12 12:49:10 +00004063 goto bad;
4064 }
4065 case ARM64in_VUnaryS: {
4066 /* 31 23 21 16 14 9 4
4067 000,11110 00 1,0000 0,0 10000 n d FMOV Sd, Sn (not handled)
4068 ------------------- 0,1 --------- FABS ------
4069 ------------------- 1,0 --------- FNEG ------
sewardj89cefe42015-02-24 12:21:01 +00004070 ------------------- 1,1 --------- FSQRT -----
sewardjbbcf1882014-01-12 12:49:10 +00004071 */
sewardja5b50222015-03-26 07:18:32 +00004072 UInt sD = dregEnc(i->ARM64in.VUnaryS.dst);
4073 UInt sN = dregEnc(i->ARM64in.VUnaryS.src);
sewardjbbcf1882014-01-12 12:49:10 +00004074 UInt b16 = 2; /* impossible */
4075 UInt b15 = 2; /* impossible */
4076 switch (i->ARM64in.VUnaryS.op) {
4077 case ARM64fpu_NEG: b16 = 1; b15 = 0; break;
4078 case ARM64fpu_SQRT: b16 = 1; b15 = 1; break;
4079 case ARM64fpu_ABS: b16 = 0; b15 = 1; break;
4080 default: break;
4081 }
4082 if (b16 < 2 && b15 < 2) {
4083 *p++ = X_3_8_5_6_5_5(X000, X11110001, (X0000 << 1) | b16,
4084 (b15 << 5) | X10000, sN, sD);
4085 goto done;
4086 }
4087 /*
4088 000, 11110 00 1,001 11,1 10000 n d FRINTI Sd, Sm (round per FPCR)
4089 */
4090 if (i->ARM64in.VUnaryS.op == ARM64fpu_RINT) {
4091 *p++ = X_3_8_5_6_5_5(X000, X11110001, X00111, X110000, sN, sD);
4092 goto done;
4093 }
sewardj89cefe42015-02-24 12:21:01 +00004094 /*
4095 010, 11110 10 1,0000 1,1111 10 n d FRECPX Sd, Sm
4096 */
4097 if (i->ARM64in.VUnaryS.op == ARM64fpu_RECPX) {
4098 *p++ = X_3_8_5_6_5_5(X010, X11110101, X00001, X111110, sN, sD);
4099 goto done;
4100 }
sewardjbbcf1882014-01-12 12:49:10 +00004101 goto bad;
4102 }
4103 case ARM64in_VBinD: {
4104 /* 31 23 20 15 11 9 4
4105 ---------------- 0000 ------ FMUL --------
4106 000 11110 011 m 0001 10 n d FDIV Dd,Dn,Dm
4107 ---------------- 0010 ------ FADD --------
4108 ---------------- 0011 ------ FSUB --------
4109 */
sewardja5b50222015-03-26 07:18:32 +00004110 UInt dD = dregEnc(i->ARM64in.VBinD.dst);
4111 UInt dN = dregEnc(i->ARM64in.VBinD.argL);
4112 UInt dM = dregEnc(i->ARM64in.VBinD.argR);
sewardjbbcf1882014-01-12 12:49:10 +00004113 UInt b1512 = 16; /* impossible */
4114 switch (i->ARM64in.VBinD.op) {
4115 case ARM64fpb_DIV: b1512 = X0001; break;
4116 case ARM64fpb_MUL: b1512 = X0000; break;
4117 case ARM64fpb_SUB: b1512 = X0011; break;
4118 case ARM64fpb_ADD: b1512 = X0010; break;
4119 default: goto bad;
4120 }
4121 vassert(b1512 < 16);
4122 *p++
4123 = X_3_8_5_6_5_5(X000, X11110011, dM, (b1512 << 2) | X10, dN, dD);
4124 goto done;
4125 }
4126 case ARM64in_VBinS: {
4127 /* 31 23 20 15 11 9 4
4128 ---------------- 0000 ------ FMUL --------
4129 000 11110 001 m 0001 10 n d FDIV Dd,Dn,Dm
4130 ---------------- 0010 ------ FADD --------
4131 ---------------- 0011 ------ FSUB --------
4132 */
sewardja5b50222015-03-26 07:18:32 +00004133 UInt sD = dregEnc(i->ARM64in.VBinS.dst);
4134 UInt sN = dregEnc(i->ARM64in.VBinS.argL);
4135 UInt sM = dregEnc(i->ARM64in.VBinS.argR);
sewardjbbcf1882014-01-12 12:49:10 +00004136 UInt b1512 = 16; /* impossible */
4137 switch (i->ARM64in.VBinS.op) {
4138 case ARM64fpb_DIV: b1512 = X0001; break;
4139 case ARM64fpb_MUL: b1512 = X0000; break;
4140 case ARM64fpb_SUB: b1512 = X0011; break;
4141 case ARM64fpb_ADD: b1512 = X0010; break;
4142 default: goto bad;
4143 }
4144 vassert(b1512 < 16);
4145 *p++
4146 = X_3_8_5_6_5_5(X000, X11110001, sM, (b1512 << 2) | X10, sN, sD);
4147 goto done;
4148 }
4149 case ARM64in_VCmpD: {
4150 /* 000 11110 01 1 m 00 1000 n 00 000 FCMP Dn, Dm */
sewardja5b50222015-03-26 07:18:32 +00004151 UInt dN = dregEnc(i->ARM64in.VCmpD.argL);
4152 UInt dM = dregEnc(i->ARM64in.VCmpD.argR);
sewardjbbcf1882014-01-12 12:49:10 +00004153 *p++ = X_3_8_5_6_5_5(X000, X11110011, dM, X001000, dN, X00000);
4154 goto done;
4155 }
4156 case ARM64in_VCmpS: {
4157 /* 000 11110 00 1 m 00 1000 n 00 000 FCMP Sn, Sm */
sewardja5b50222015-03-26 07:18:32 +00004158 UInt sN = dregEnc(i->ARM64in.VCmpS.argL);
4159 UInt sM = dregEnc(i->ARM64in.VCmpS.argR);
sewardjbbcf1882014-01-12 12:49:10 +00004160 *p++ = X_3_8_5_6_5_5(X000, X11110001, sM, X001000, sN, X00000);
4161 goto done;
4162 }
sewardje23ec112014-11-15 16:07:14 +00004163 case ARM64in_VFCSel: {
4164 /* 31 23 21 20 15 11 9 5
4165 000 11110 00 1 m cond 11 n d FCSEL Sd,Sn,Sm,cond
4166 000 11110 01 1 m cond 11 n d FCSEL Dd,Dn,Dm,cond
4167 */
4168 Bool isD = i->ARM64in.VFCSel.isD;
sewardja5b50222015-03-26 07:18:32 +00004169 UInt dd = dregEnc(i->ARM64in.VFCSel.dst);
4170 UInt nn = dregEnc(i->ARM64in.VFCSel.argL);
4171 UInt mm = dregEnc(i->ARM64in.VFCSel.argR);
sewardje23ec112014-11-15 16:07:14 +00004172 UInt cond = (UInt)i->ARM64in.VFCSel.cond;
4173 vassert(cond < 16);
4174 *p++ = X_3_8_5_6_5_5(X000, isD ? X11110011 : X11110001,
4175 mm, (cond << 2) | X000011, nn, dd);
4176 goto done;
4177 }
sewardj606c4ba2014-01-26 19:11:14 +00004178 case ARM64in_FPCR: {
4179 Bool toFPCR = i->ARM64in.FPCR.toFPCR;
sewardja5b50222015-03-26 07:18:32 +00004180 UInt iReg = iregEnc(i->ARM64in.FPCR.iReg);
sewardj606c4ba2014-01-26 19:11:14 +00004181 if (toFPCR) {
4182 /* 0xD51B44 000 Rt MSR fpcr, rT */
4183 *p++ = 0xD51B4400 | (iReg & 0x1F);
4184 goto done;
4185 }
4186 goto bad; // FPCR -> iReg case currently ATC
4187 }
sewardj12972182014-08-04 08:09:47 +00004188 case ARM64in_FPSR: {
4189 Bool toFPSR = i->ARM64in.FPSR.toFPSR;
sewardja5b50222015-03-26 07:18:32 +00004190 UInt iReg = iregEnc(i->ARM64in.FPSR.iReg);
sewardj12972182014-08-04 08:09:47 +00004191 if (toFPSR) {
4192 /* 0xD51B44 001 Rt MSR fpsr, rT */
4193 *p++ = 0xD51B4420 | (iReg & 0x1F);
4194 } else {
4195 /* 0xD53B44 001 Rt MRS rT, fpsr */
4196 *p++ = 0xD53B4420 | (iReg & 0x1F);
4197 }
4198 goto done;
4199 }
sewardj606c4ba2014-01-26 19:11:14 +00004200 case ARM64in_VBinV: {
4201 /* 31 23 20 15 9 4
sewardj93013432014-04-27 12:02:12 +00004202 010 01110 11 1 m 100001 n d ADD Vd.2d, Vn.2d, Vm.2d
4203 010 01110 10 1 m 100001 n d ADD Vd.4s, Vn.4s, Vm.4s
4204 010 01110 01 1 m 100001 n d ADD Vd.8h, Vn.8h, Vm.8h
sewardj92d0ae32014-04-03 13:48:54 +00004205 010 01110 00 1 m 100001 n d ADD Vd.16b, Vn.16b, Vm.16b
sewardjf5b08912014-02-06 12:57:58 +00004206
sewardj93013432014-04-27 12:02:12 +00004207 011 01110 11 1 m 100001 n d SUB Vd.2d, Vn.2d, Vm.2d
4208 011 01110 10 1 m 100001 n d SUB Vd.4s, Vn.4s, Vm.4s
4209 011 01110 01 1 m 100001 n d SUB Vd.8h, Vn.8h, Vm.8h
sewardj92d0ae32014-04-03 13:48:54 +00004210 011 01110 00 1 m 100001 n d SUB Vd.16b, Vn.16b, Vm.16b
sewardjf5b08912014-02-06 12:57:58 +00004211
sewardj93013432014-04-27 12:02:12 +00004212 010 01110 10 1 m 100111 n d MUL Vd.4s, Vn.4s, Vm.4s
4213 010 01110 01 1 m 100111 n d MUL Vd.8h, Vn.8h, Vm.8h
4214 010 01110 00 1 m 100111 n d MUL Vd.16b, Vn.16b, Vm.16b
sewardjf5b08912014-02-06 12:57:58 +00004215
sewardj606c4ba2014-01-26 19:11:14 +00004216 010 01110 01 1 m 110101 n d FADD Vd.2d, Vn.2d, Vm.2d
sewardjecde6972014-02-05 11:01:19 +00004217 010 01110 00 1 m 110101 n d FADD Vd.4s, Vn.4s, Vm.4s
sewardj606c4ba2014-01-26 19:11:14 +00004218 010 01110 11 1 m 110101 n d FSUB Vd.2d, Vn.2d, Vm.2d
sewardjecde6972014-02-05 11:01:19 +00004219 010 01110 10 1 m 110101 n d FSUB Vd.4s, Vn.4s, Vm.4s
sewardjf5b08912014-02-06 12:57:58 +00004220
sewardj606c4ba2014-01-26 19:11:14 +00004221 011 01110 01 1 m 110111 n d FMUL Vd.2d, Vn.2d, Vm.2d
sewardjecde6972014-02-05 11:01:19 +00004222 011 01110 00 1 m 110111 n d FMUL Vd.4s, Vn.4s, Vm.4s
sewardj606c4ba2014-01-26 19:11:14 +00004223 011 01110 01 1 m 111111 n d FDIV Vd.2d, Vn.2d, Vm.2d
sewardjecde6972014-02-05 11:01:19 +00004224 011 01110 00 1 m 111111 n d FDIV Vd.4s, Vn.4s, Vm.4s
sewardjf5b08912014-02-06 12:57:58 +00004225
sewardj76927e62014-11-17 11:21:21 +00004226 010 01110 01 1 m 111101 n d FMAX Vd.2d, Vn.2d, Vm.2d
4227 010 01110 00 1 m 111101 n d FMAX Vd.4s, Vn.4s, Vm.4s
4228 010 01110 11 1 m 111101 n d FMIN Vd.2d, Vn.2d, Vm.2d
4229 010 01110 10 1 m 111101 n d FMIN Vd.4s, Vn.4s, Vm.4s
4230
sewardjfab09142014-02-10 10:28:13 +00004231 011 01110 10 1 m 011001 n d UMAX Vd.4s, Vn.4s, Vm.4s
4232 011 01110 01 1 m 011001 n d UMAX Vd.8h, Vn.8h, Vm.8h
4233 011 01110 00 1 m 011001 n d UMAX Vd.16b, Vn.16b, Vm.16b
4234
4235 011 01110 10 1 m 011011 n d UMIN Vd.4s, Vn.4s, Vm.4s
4236 011 01110 01 1 m 011011 n d UMIN Vd.8h, Vn.8h, Vm.8h
4237 011 01110 00 1 m 011011 n d UMIN Vd.16b, Vn.16b, Vm.16b
sewardjf5b08912014-02-06 12:57:58 +00004238
sewardj9b1cf5e2014-03-01 11:16:57 +00004239 010 01110 10 1 m 011001 n d SMAX Vd.4s, Vn.4s, Vm.4s
4240 010 01110 01 1 m 011001 n d SMAX Vd.8h, Vn.8h, Vm.8h
4241 010 01110 00 1 m 011001 n d SMAX Vd.16b, Vn.16b, Vm.16b
sewardjfab09142014-02-10 10:28:13 +00004242
sewardj9b1cf5e2014-03-01 11:16:57 +00004243 010 01110 10 1 m 011011 n d SMIN Vd.4s, Vn.4s, Vm.4s
4244 010 01110 01 1 m 011011 n d SMIN Vd.8h, Vn.8h, Vm.8h
4245 010 01110 00 1 m 011011 n d SMIN Vd.16b, Vn.16b, Vm.16b
sewardjf5b08912014-02-06 12:57:58 +00004246
sewardjecde6972014-02-05 11:01:19 +00004247 010 01110 00 1 m 000111 n d AND Vd, Vn, Vm
4248 010 01110 10 1 m 000111 n d ORR Vd, Vn, Vm
sewardje520bb32014-02-17 11:00:53 +00004249 011 01110 00 1 m 000111 n d EOR Vd, Vn, Vm
4250
sewardj505a27d2014-03-10 10:40:48 +00004251 011 01110 11 1 m 100011 n d CMEQ Vd.2d, Vn.2d, Vm.2d
4252 011 01110 10 1 m 100011 n d CMEQ Vd.4s, Vn.4s, Vm.4s
4253 011 01110 01 1 m 100011 n d CMEQ Vd.8h, Vn.8h, Vm.8h
4254 011 01110 00 1 m 100011 n d CMEQ Vd.16b, Vn.16b, Vm.16b
4255
sewardj93013432014-04-27 12:02:12 +00004256 011 01110 11 1 m 001101 n d CMHI Vd.2d, Vn.2d, Vm.2d
4257 011 01110 10 1 m 001101 n d CMHI Vd.4s, Vn.4s, Vm.4s
4258 011 01110 01 1 m 001101 n d CMHI Vd.8h, Vn.8h, Vm.8h
4259 011 01110 00 1 m 001101 n d CMHI Vd.16b, Vn.16b, Vm.16b
4260
4261 010 01110 11 1 m 001101 n d CMGT Vd.2d, Vn.2d, Vm.2d
4262 010 01110 10 1 m 001101 n d CMGT Vd.4s, Vn.4s, Vm.4s
4263 010 01110 01 1 m 001101 n d CMGT Vd.8h, Vn.8h, Vm.8h
4264 010 01110 00 1 m 001101 n d CMGT Vd.16b, Vn.16b, Vm.16b
sewardj2bd1ffe2014-03-27 18:59:00 +00004265
4266 010 01110 01 1 m 111001 n d FCMEQ Vd.2d, Vn.2d, Vm.2d
4267 010 01110 00 1 m 111001 n d FCMEQ Vd.4s, Vn.4s, Vm.4s
4268
4269 011 01110 01 1 m 111001 n d FCMGE Vd.2d, Vn.2d, Vm.2d
4270 011 01110 00 1 m 111001 n d FCMGE Vd.4s, Vn.4s, Vm.4s
4271
4272 011 01110 11 1 m 111001 n d FCMGT Vd.2d, Vn.2d, Vm.2d
4273 011 01110 10 1 m 111001 n d FCMGT Vd.4s, Vn.4s, Vm.4s
sewardj92d0ae32014-04-03 13:48:54 +00004274
4275 010 01110 00 0 m 000000 n d TBL Vd.16b, {Vn.16b}, Vm.16b
4276
sewardjd96daf62014-06-15 08:17:35 +00004277 010 01110 11 0 m 000110 n d UZP1 Vd.2d, Vn.2d, Vm.2d
4278 010 01110 10 0 m 000110 n d UZP1 Vd.4s, Vn.4s, Vm.4s
4279 010 01110 01 0 m 000110 n d UZP1 Vd.8h, Vn.8h, Vm.8h
4280 010 01110 00 0 m 000110 n d UZP1 Vd.16b, Vn.16b, Vm.16b
4281
4282 010 01110 11 0 m 010110 n d UZP2 Vd.2d, Vn.2d, Vm.2d
4283 010 01110 10 0 m 010110 n d UZP2 Vd.4s, Vn.4s, Vm.4s
4284 010 01110 01 0 m 010110 n d UZP2 Vd.8h, Vn.8h, Vm.8h
4285 010 01110 00 0 m 010110 n d UZP2 Vd.16b, Vn.16b, Vm.16b
4286
4287 010 01110 10 0 m 001110 n d ZIP1 Vd.4s, Vn.4s, Vm.4s
4288 010 01110 01 0 m 001110 n d ZIP1 Vd.8h, Vn.8h, Vm.8h
4289 010 01110 10 0 m 001110 n d ZIP1 Vd.16b, Vn.16b, Vm.16b
4290
4291 010 01110 10 0 m 011110 n d ZIP2 Vd.4s, Vn.4s, Vm.4s
4292 010 01110 01 0 m 011110 n d ZIP2 Vd.8h, Vn.8h, Vm.8h
4293 010 01110 10 0 m 011110 n d ZIP2 Vd.16b, Vn.16b, Vm.16b
sewardj168c8bd2014-06-25 13:05:23 +00004294
4295 011 01110 00 1 m 100111 n d PMUL Vd.16b, Vn.16b, Vm.16b
sewardj31b5a952014-06-26 07:41:14 +00004296
4297 000 01110 00 1 m 111000 n d PMULL Vd.8h, Vn.8b, Vm.8b
sewardj6f312d02014-06-28 12:21:37 +00004298
4299 001 01110 10 1 m 110000 n d UMULL Vd.2d, Vn.2s, Vm.2s
4300 001 01110 01 1 m 110000 n d UMULL Vd.4s, Vn.4h, Vm.4h
4301 001 01110 00 1 m 110000 n d UMULL Vd.8h, Vn.8b, Vm.8b
4302
4303 000 01110 10 1 m 110000 n d SMULL Vd.2d, Vn.2s, Vm.2s
4304 000 01110 01 1 m 110000 n d SMULL Vd.4s, Vn.4h, Vm.4h
4305 000 01110 00 1 m 110000 n d SMULL Vd.8h, Vn.8b, Vm.8b
sewardja5a6b752014-06-30 07:33:56 +00004306
4307 010 01110 11 1 m 000011 n d SQADD Vd.2d, Vn.2d, Vm.2d
4308 010 01110 10 1 m 000011 n d SQADD Vd.4s, Vn.4s, Vm.4s
4309 010 01110 01 1 m 000011 n d SQADD Vd.8h, Vn.8h, Vm.8h
4310 010 01110 00 1 m 000011 n d SQADD Vd.16b, Vn.16b, Vm.16b
4311
4312 011 01110 11 1 m 000011 n d UQADD Vd.2d, Vn.2d, Vm.2d
4313 011 01110 10 1 m 000011 n d UQADD Vd.4s, Vn.4s, Vm.4s
4314 011 01110 01 1 m 000011 n d UQADD Vd.8h, Vn.8h, Vm.8h
4315 011 01110 00 1 m 000011 n d UQADD Vd.16b, Vn.16b, Vm.16b
4316
4317 010 01110 11 1 m 001011 n d SQSUB Vd.2d, Vn.2d, Vm.2d
4318 010 01110 10 1 m 001011 n d SQSUB Vd.4s, Vn.4s, Vm.4s
4319 010 01110 01 1 m 001011 n d SQSUB Vd.8h, Vn.8h, Vm.8h
4320 010 01110 00 1 m 001011 n d SQSUB Vd.16b, Vn.16b, Vm.16b
4321
4322 011 01110 11 1 m 001011 n d UQSUB Vd.2d, Vn.2d, Vm.2d
4323 011 01110 10 1 m 001011 n d UQSUB Vd.4s, Vn.4s, Vm.4s
4324 011 01110 01 1 m 001011 n d UQSUB Vd.8h, Vn.8h, Vm.8h
4325 011 01110 00 1 m 001011 n d UQSUB Vd.16b, Vn.16b, Vm.16b
sewardj51d012a2014-07-21 09:19:50 +00004326
4327 000 01110 10 1 m 110100 n d SQDMULL Vd.2d, Vn.2s, Vm.2s
4328 000 01110 01 1 m 110100 n d SQDMULL Vd.4s, Vn.4h, Vm.4h
sewardj54ffa1d2014-07-22 09:27:49 +00004329
4330 010 01110 10 1 m 101101 n d SQDMULH Vd.4s, Vn.4s, Vm.4s
4331 010 01110 01 1 m 101101 n d SQDMULH Vd.8h, Vn.8h, Vm.8h
4332 011 01110 10 1 m 101101 n d SQRDMULH Vd.4s, Vn.4s, Vm.4s
4333 011 01110 10 1 m 101101 n d SQRDMULH Vd.8h, Vn.8h, Vm.8h
sewardj12972182014-08-04 08:09:47 +00004334
4335 010 01110 sz 1 m 010011 n d SQSHL@sz Vd, Vn, Vm
4336 010 01110 sz 1 m 010111 n d SQRSHL@sz Vd, Vn, Vm
4337 011 01110 sz 1 m 010011 n d UQSHL@sz Vd, Vn, Vm
4338 011 01110 sz 1 m 010111 n d URQSHL@sz Vd, Vn, Vm
sewardja6b61f02014-08-17 18:32:14 +00004339
4340 010 01110 sz 1 m 010001 n d SSHL@sz Vd, Vn, Vm
4341 010 01110 sz 1 m 010101 n d SRSHL@sz Vd, Vn, Vm
4342 011 01110 sz 1 m 010001 n d USHL@sz Vd, Vn, Vm
4343 011 01110 sz 1 m 010101 n d URSHL@sz Vd, Vn, Vm
sewardj89cefe42015-02-24 12:21:01 +00004344
4345 010 01110 01 1 m 111111 n d FRECPS Vd.2d, Vn.2d, Vm.2d
4346 010 01110 00 1 m 111111 n d FRECPS Vd.4s, Vn.4s, Vm.4s
4347 010 01110 11 1 m 111111 n d FRSQRTS Vd.2d, Vn.2d, Vm.2d
4348 010 01110 10 1 m 111111 n d FRSQRTS Vd.4s, Vn.4s, Vm.4s
sewardj606c4ba2014-01-26 19:11:14 +00004349 */
sewardja5b50222015-03-26 07:18:32 +00004350 UInt vD = qregEnc(i->ARM64in.VBinV.dst);
4351 UInt vN = qregEnc(i->ARM64in.VBinV.argL);
4352 UInt vM = qregEnc(i->ARM64in.VBinV.argR);
sewardj606c4ba2014-01-26 19:11:14 +00004353 switch (i->ARM64in.VBinV.op) {
4354 case ARM64vecb_ADD64x2:
4355 *p++ = X_3_8_5_6_5_5(X010, X01110111, vM, X100001, vN, vD);
4356 break;
sewardjf5b08912014-02-06 12:57:58 +00004357 case ARM64vecb_ADD32x4:
4358 *p++ = X_3_8_5_6_5_5(X010, X01110101, vM, X100001, vN, vD);
4359 break;
4360 case ARM64vecb_ADD16x8:
4361 *p++ = X_3_8_5_6_5_5(X010, X01110011, vM, X100001, vN, vD);
4362 break;
sewardj92d0ae32014-04-03 13:48:54 +00004363 case ARM64vecb_ADD8x16:
4364 *p++ = X_3_8_5_6_5_5(X010, X01110001, vM, X100001, vN, vD);
4365 break;
sewardj606c4ba2014-01-26 19:11:14 +00004366 case ARM64vecb_SUB64x2:
4367 *p++ = X_3_8_5_6_5_5(X011, X01110111, vM, X100001, vN, vD);
4368 break;
4369 case ARM64vecb_SUB32x4:
4370 *p++ = X_3_8_5_6_5_5(X011, X01110101, vM, X100001, vN, vD);
4371 break;
4372 case ARM64vecb_SUB16x8:
4373 *p++ = X_3_8_5_6_5_5(X011, X01110011, vM, X100001, vN, vD);
4374 break;
sewardj92d0ae32014-04-03 13:48:54 +00004375 case ARM64vecb_SUB8x16:
4376 *p++ = X_3_8_5_6_5_5(X011, X01110001, vM, X100001, vN, vD);
4377 break;
sewardjf5b08912014-02-06 12:57:58 +00004378 case ARM64vecb_MUL32x4:
4379 *p++ = X_3_8_5_6_5_5(X010, X01110101, vM, X100111, vN, vD);
4380 break;
4381 case ARM64vecb_MUL16x8:
4382 *p++ = X_3_8_5_6_5_5(X010, X01110011, vM, X100111, vN, vD);
4383 break;
sewardj93013432014-04-27 12:02:12 +00004384 case ARM64vecb_MUL8x16:
4385 *p++ = X_3_8_5_6_5_5(X010, X01110001, vM, X100111, vN, vD);
4386 break;
sewardj606c4ba2014-01-26 19:11:14 +00004387 case ARM64vecb_FADD64x2:
4388 *p++ = X_3_8_5_6_5_5(X010, X01110011, vM, X110101, vN, vD);
4389 break;
sewardjecde6972014-02-05 11:01:19 +00004390 case ARM64vecb_FADD32x4:
4391 *p++ = X_3_8_5_6_5_5(X010, X01110001, vM, X110101, vN, vD);
4392 break;
sewardj606c4ba2014-01-26 19:11:14 +00004393 case ARM64vecb_FSUB64x2:
4394 *p++ = X_3_8_5_6_5_5(X010, X01110111, vM, X110101, vN, vD);
4395 break;
sewardjecde6972014-02-05 11:01:19 +00004396 case ARM64vecb_FSUB32x4:
4397 *p++ = X_3_8_5_6_5_5(X010, X01110101, vM, X110101, vN, vD);
4398 break;
sewardj606c4ba2014-01-26 19:11:14 +00004399 case ARM64vecb_FMUL64x2:
4400 *p++ = X_3_8_5_6_5_5(X011, X01110011, vM, X110111, vN, vD);
4401 break;
sewardjecde6972014-02-05 11:01:19 +00004402 case ARM64vecb_FMUL32x4:
4403 *p++ = X_3_8_5_6_5_5(X011, X01110001, vM, X110111, vN, vD);
4404 break;
sewardj606c4ba2014-01-26 19:11:14 +00004405 case ARM64vecb_FDIV64x2:
4406 *p++ = X_3_8_5_6_5_5(X011, X01110011, vM, X111111, vN, vD);
4407 break;
sewardjecde6972014-02-05 11:01:19 +00004408 case ARM64vecb_FDIV32x4:
4409 *p++ = X_3_8_5_6_5_5(X011, X01110001, vM, X111111, vN, vD);
4410 break;
sewardjf5b08912014-02-06 12:57:58 +00004411
sewardj76927e62014-11-17 11:21:21 +00004412 case ARM64vecb_FMAX64x2:
4413 *p++ = X_3_8_5_6_5_5(X010, X01110011, vM, X111101, vN, vD);
4414 break;
4415 case ARM64vecb_FMAX32x4:
4416 *p++ = X_3_8_5_6_5_5(X010, X01110001, vM, X111101, vN, vD);
4417 break;
4418 case ARM64vecb_FMIN64x2:
4419 *p++ = X_3_8_5_6_5_5(X010, X01110111, vM, X111101, vN, vD);
4420 break;
4421 case ARM64vecb_FMIN32x4:
4422 *p++ = X_3_8_5_6_5_5(X010, X01110101, vM, X111101, vN, vD);
4423 break;
4424
sewardjecde6972014-02-05 11:01:19 +00004425 case ARM64vecb_UMAX32x4:
4426 *p++ = X_3_8_5_6_5_5(X011, X01110101, vM, X011001, vN, vD);
4427 break;
4428 case ARM64vecb_UMAX16x8:
4429 *p++ = X_3_8_5_6_5_5(X011, X01110011, vM, X011001, vN, vD);
4430 break;
sewardjfab09142014-02-10 10:28:13 +00004431 case ARM64vecb_UMAX8x16:
4432 *p++ = X_3_8_5_6_5_5(X011, X01110001, vM, X011001, vN, vD);
4433 break;
4434
sewardjecde6972014-02-05 11:01:19 +00004435 case ARM64vecb_UMIN32x4:
4436 *p++ = X_3_8_5_6_5_5(X011, X01110101, vM, X011011, vN, vD);
4437 break;
4438 case ARM64vecb_UMIN16x8:
4439 *p++ = X_3_8_5_6_5_5(X011, X01110011, vM, X011011, vN, vD);
4440 break;
sewardjfab09142014-02-10 10:28:13 +00004441 case ARM64vecb_UMIN8x16:
4442 *p++ = X_3_8_5_6_5_5(X011, X01110001, vM, X011011, vN, vD);
4443 break;
sewardjf5b08912014-02-06 12:57:58 +00004444
4445 case ARM64vecb_SMAX32x4:
4446 *p++ = X_3_8_5_6_5_5(X010, X01110101, vM, X011001, vN, vD);
4447 break;
4448 case ARM64vecb_SMAX16x8:
4449 *p++ = X_3_8_5_6_5_5(X010, X01110011, vM, X011001, vN, vD);
4450 break;
sewardj9b1cf5e2014-03-01 11:16:57 +00004451 case ARM64vecb_SMAX8x16:
4452 *p++ = X_3_8_5_6_5_5(X010, X01110001, vM, X011001, vN, vD);
4453 break;
sewardjfab09142014-02-10 10:28:13 +00004454
sewardjf5b08912014-02-06 12:57:58 +00004455 case ARM64vecb_SMIN32x4:
4456 *p++ = X_3_8_5_6_5_5(X010, X01110101, vM, X011011, vN, vD);
4457 break;
4458 case ARM64vecb_SMIN16x8:
4459 *p++ = X_3_8_5_6_5_5(X010, X01110011, vM, X011011, vN, vD);
4460 break;
sewardj9b1cf5e2014-03-01 11:16:57 +00004461 case ARM64vecb_SMIN8x16:
4462 *p++ = X_3_8_5_6_5_5(X010, X01110001, vM, X011011, vN, vD);
4463 break;
sewardjf5b08912014-02-06 12:57:58 +00004464
sewardjecde6972014-02-05 11:01:19 +00004465 case ARM64vecb_AND:
4466 *p++ = X_3_8_5_6_5_5(X010, X01110001, vM, X000111, vN, vD);
4467 break;
sewardje520bb32014-02-17 11:00:53 +00004468 case ARM64vecb_ORR:
4469 *p++ = X_3_8_5_6_5_5(X010, X01110101, vM, X000111, vN, vD);
4470 break;
4471 case ARM64vecb_XOR:
4472 *p++ = X_3_8_5_6_5_5(X011, X01110001, vM, X000111, vN, vD);
4473 break;
4474
4475 case ARM64vecb_CMEQ64x2:
4476 *p++ = X_3_8_5_6_5_5(X011, X01110111, vM, X100011, vN, vD);
4477 break;
sewardj505a27d2014-03-10 10:40:48 +00004478 case ARM64vecb_CMEQ32x4:
4479 *p++ = X_3_8_5_6_5_5(X011, X01110101, vM, X100011, vN, vD);
4480 break;
4481 case ARM64vecb_CMEQ16x8:
4482 *p++ = X_3_8_5_6_5_5(X011, X01110011, vM, X100011, vN, vD);
4483 break;
4484 case ARM64vecb_CMEQ8x16:
4485 *p++ = X_3_8_5_6_5_5(X011, X01110001, vM, X100011, vN, vD);
4486 break;
sewardje520bb32014-02-17 11:00:53 +00004487
sewardj93013432014-04-27 12:02:12 +00004488 case ARM64vecb_CMHI64x2:
4489 *p++ = X_3_8_5_6_5_5(X011, X01110111, vM, X001101, vN, vD);
4490 break;
4491 case ARM64vecb_CMHI32x4:
4492 *p++ = X_3_8_5_6_5_5(X011, X01110101, vM, X001101, vN, vD);
4493 break;
4494 case ARM64vecb_CMHI16x8:
4495 *p++ = X_3_8_5_6_5_5(X011, X01110011, vM, X001101, vN, vD);
4496 break;
4497 case ARM64vecb_CMHI8x16:
4498 *p++ = X_3_8_5_6_5_5(X011, X01110001, vM, X001101, vN, vD);
4499 break;
4500
4501 case ARM64vecb_CMGT64x2:
4502 *p++ = X_3_8_5_6_5_5(X010, X01110111, vM, X001101, vN, vD);
4503 break;
4504 case ARM64vecb_CMGT32x4:
4505 *p++ = X_3_8_5_6_5_5(X010, X01110101, vM, X001101, vN, vD);
4506 break;
4507 case ARM64vecb_CMGT16x8:
4508 *p++ = X_3_8_5_6_5_5(X010, X01110011, vM, X001101, vN, vD);
4509 break;
4510 case ARM64vecb_CMGT8x16:
4511 *p++ = X_3_8_5_6_5_5(X010, X01110001, vM, X001101, vN, vD);
4512 break;
4513
sewardj2bd1ffe2014-03-27 18:59:00 +00004514 case ARM64vecb_FCMEQ64x2:
4515 *p++ = X_3_8_5_6_5_5(X010, X01110011, vM, X111001, vN, vD);
4516 break;
4517 case ARM64vecb_FCMEQ32x4:
4518 *p++ = X_3_8_5_6_5_5(X010, X01110001, vM, X111001, vN, vD);
4519 break;
4520
4521 case ARM64vecb_FCMGE64x2:
4522 *p++ = X_3_8_5_6_5_5(X011, X01110011, vM, X111001, vN, vD);
4523 break;
4524 case ARM64vecb_FCMGE32x4:
4525 *p++ = X_3_8_5_6_5_5(X011, X01110001, vM, X111001, vN, vD);
4526 break;
4527
4528 case ARM64vecb_FCMGT64x2:
4529 *p++ = X_3_8_5_6_5_5(X011, X01110111, vM, X111001, vN, vD);
4530 break;
4531 case ARM64vecb_FCMGT32x4:
4532 *p++ = X_3_8_5_6_5_5(X011, X01110101, vM, X111001, vN, vD);
4533 break;
sewardj92d0ae32014-04-03 13:48:54 +00004534
4535 case ARM64vecb_TBL1:
sewardjd96daf62014-06-15 08:17:35 +00004536 *p++ = X_3_8_5_6_5_5(X010, X01110000, vM, X000000, vN, vD);
4537 break;
4538
4539 case ARM64vecb_UZP164x2:
4540 *p++ = X_3_8_5_6_5_5(X010, X01110110, vM, X000110, vN, vD);
4541 break;
4542 case ARM64vecb_UZP132x4:
4543 *p++ = X_3_8_5_6_5_5(X010, X01110100, vM, X000110, vN, vD);
4544 break;
4545 case ARM64vecb_UZP116x8:
4546 *p++ = X_3_8_5_6_5_5(X010, X01110010, vM, X000110, vN, vD);
4547 break;
4548 case ARM64vecb_UZP18x16:
4549 *p++ = X_3_8_5_6_5_5(X010, X01110000, vM, X000110, vN, vD);
4550 break;
4551
4552 case ARM64vecb_UZP264x2:
4553 *p++ = X_3_8_5_6_5_5(X010, X01110110, vM, X010110, vN, vD);
4554 break;
4555 case ARM64vecb_UZP232x4:
4556 *p++ = X_3_8_5_6_5_5(X010, X01110100, vM, X010110, vN, vD);
4557 break;
4558 case ARM64vecb_UZP216x8:
4559 *p++ = X_3_8_5_6_5_5(X010, X01110010, vM, X010110, vN, vD);
4560 break;
4561 case ARM64vecb_UZP28x16:
4562 *p++ = X_3_8_5_6_5_5(X010, X01110000, vM, X010110, vN, vD);
4563 break;
4564
4565 case ARM64vecb_ZIP132x4:
4566 *p++ = X_3_8_5_6_5_5(X010, X01110100, vM, X001110, vN, vD);
4567 break;
4568 case ARM64vecb_ZIP116x8:
4569 *p++ = X_3_8_5_6_5_5(X010, X01110010, vM, X001110, vN, vD);
4570 break;
4571 case ARM64vecb_ZIP18x16:
4572 *p++ = X_3_8_5_6_5_5(X010, X01110000, vM, X001110, vN, vD);
4573 break;
4574
4575 case ARM64vecb_ZIP232x4:
4576 *p++ = X_3_8_5_6_5_5(X010, X01110100, vM, X011110, vN, vD);
4577 break;
4578 case ARM64vecb_ZIP216x8:
4579 *p++ = X_3_8_5_6_5_5(X010, X01110010, vM, X011110, vN, vD);
4580 break;
4581 case ARM64vecb_ZIP28x16:
4582 *p++ = X_3_8_5_6_5_5(X010, X01110000, vM, X011110, vN, vD);
sewardj92d0ae32014-04-03 13:48:54 +00004583 break;
4584
sewardj168c8bd2014-06-25 13:05:23 +00004585 case ARM64vecb_PMUL8x16:
4586 *p++ = X_3_8_5_6_5_5(X011, X01110001, vM, X100111, vN, vD);
4587 break;
4588
sewardj31b5a952014-06-26 07:41:14 +00004589 case ARM64vecb_PMULL8x8:
4590 *p++ = X_3_8_5_6_5_5(X000, X01110001, vM, X111000, vN, vD);
4591 break;
4592
sewardj6f312d02014-06-28 12:21:37 +00004593 case ARM64vecb_UMULL2DSS:
4594 *p++ = X_3_8_5_6_5_5(X001, X01110101, vM, X110000, vN, vD);
4595 break;
4596 case ARM64vecb_UMULL4SHH:
4597 *p++ = X_3_8_5_6_5_5(X001, X01110011, vM, X110000, vN, vD);
4598 break;
4599 case ARM64vecb_UMULL8HBB:
4600 *p++ = X_3_8_5_6_5_5(X001, X01110001, vM, X110000, vN, vD);
4601 break;
4602
4603 case ARM64vecb_SMULL2DSS:
4604 *p++ = X_3_8_5_6_5_5(X000, X01110101, vM, X110000, vN, vD);
4605 break;
4606 case ARM64vecb_SMULL4SHH:
4607 *p++ = X_3_8_5_6_5_5(X000, X01110011, vM, X110000, vN, vD);
4608 break;
4609 case ARM64vecb_SMULL8HBB:
4610 *p++ = X_3_8_5_6_5_5(X000, X01110001, vM, X110000, vN, vD);
4611 break;
4612
sewardja5a6b752014-06-30 07:33:56 +00004613 case ARM64vecb_SQADD64x2:
4614 *p++ = X_3_8_5_6_5_5(X010, X01110111, vM, X000011, vN, vD);
4615 break;
4616 case ARM64vecb_SQADD32x4:
4617 *p++ = X_3_8_5_6_5_5(X010, X01110101, vM, X000011, vN, vD);
4618 break;
4619 case ARM64vecb_SQADD16x8:
4620 *p++ = X_3_8_5_6_5_5(X010, X01110011, vM, X000011, vN, vD);
4621 break;
4622 case ARM64vecb_SQADD8x16:
4623 *p++ = X_3_8_5_6_5_5(X010, X01110001, vM, X000011, vN, vD);
4624 break;
4625
4626 case ARM64vecb_UQADD64x2:
4627 *p++ = X_3_8_5_6_5_5(X011, X01110111, vM, X000011, vN, vD);
4628 break;
4629 case ARM64vecb_UQADD32x4:
4630 *p++ = X_3_8_5_6_5_5(X011, X01110101, vM, X000011, vN, vD);
4631 break;
4632 case ARM64vecb_UQADD16x8:
4633 *p++ = X_3_8_5_6_5_5(X011, X01110011, vM, X000011, vN, vD);
4634 break;
4635 case ARM64vecb_UQADD8x16:
4636 *p++ = X_3_8_5_6_5_5(X011, X01110001, vM, X000011, vN, vD);
4637 break;
4638
4639 case ARM64vecb_SQSUB64x2:
4640 *p++ = X_3_8_5_6_5_5(X010, X01110111, vM, X001011, vN, vD);
4641 break;
4642 case ARM64vecb_SQSUB32x4:
4643 *p++ = X_3_8_5_6_5_5(X010, X01110101, vM, X001011, vN, vD);
4644 break;
4645 case ARM64vecb_SQSUB16x8:
4646 *p++ = X_3_8_5_6_5_5(X010, X01110011, vM, X001011, vN, vD);
4647 break;
4648 case ARM64vecb_SQSUB8x16:
4649 *p++ = X_3_8_5_6_5_5(X010, X01110001, vM, X001011, vN, vD);
4650 break;
4651
4652 case ARM64vecb_UQSUB64x2:
4653 *p++ = X_3_8_5_6_5_5(X011, X01110111, vM, X001011, vN, vD);
4654 break;
4655 case ARM64vecb_UQSUB32x4:
4656 *p++ = X_3_8_5_6_5_5(X011, X01110101, vM, X001011, vN, vD);
4657 break;
4658 case ARM64vecb_UQSUB16x8:
4659 *p++ = X_3_8_5_6_5_5(X011, X01110011, vM, X001011, vN, vD);
4660 break;
4661 case ARM64vecb_UQSUB8x16:
4662 *p++ = X_3_8_5_6_5_5(X011, X01110001, vM, X001011, vN, vD);
4663 break;
4664
sewardj51d012a2014-07-21 09:19:50 +00004665 case ARM64vecb_SQDMULL2DSS:
4666 *p++ = X_3_8_5_6_5_5(X000, X01110101, vM, X110100, vN, vD);
4667 break;
4668 case ARM64vecb_SQDMULL4SHH:
4669 *p++ = X_3_8_5_6_5_5(X000, X01110011, vM, X110100, vN, vD);
4670 break;
4671
sewardj54ffa1d2014-07-22 09:27:49 +00004672 case ARM64vecb_SQDMULH32x4:
4673 *p++ = X_3_8_5_6_5_5(X010, X01110101, vM, X101101, vN, vD);
4674 break;
4675 case ARM64vecb_SQDMULH16x8:
4676 *p++ = X_3_8_5_6_5_5(X010, X01110011, vM, X101101, vN, vD);
4677 break;
4678 case ARM64vecb_SQRDMULH32x4:
4679 *p++ = X_3_8_5_6_5_5(X011, X01110101, vM, X101101, vN, vD);
4680 break;
4681 case ARM64vecb_SQRDMULH16x8:
4682 *p++ = X_3_8_5_6_5_5(X011, X01110011, vM, X101101, vN, vD);
4683 break;
4684
sewardj12972182014-08-04 08:09:47 +00004685 case ARM64vecb_SQSHL64x2:
4686 *p++ = X_3_8_5_6_5_5(X010, X01110111, vM, X010011, vN, vD);
4687 break;
4688 case ARM64vecb_SQSHL32x4:
4689 *p++ = X_3_8_5_6_5_5(X010, X01110101, vM, X010011, vN, vD);
4690 break;
4691 case ARM64vecb_SQSHL16x8:
4692 *p++ = X_3_8_5_6_5_5(X010, X01110011, vM, X010011, vN, vD);
4693 break;
4694 case ARM64vecb_SQSHL8x16:
4695 *p++ = X_3_8_5_6_5_5(X010, X01110001, vM, X010011, vN, vD);
4696 break;
4697
4698 case ARM64vecb_SQRSHL64x2:
4699 *p++ = X_3_8_5_6_5_5(X010, X01110111, vM, X010111, vN, vD);
4700 break;
4701 case ARM64vecb_SQRSHL32x4:
4702 *p++ = X_3_8_5_6_5_5(X010, X01110101, vM, X010111, vN, vD);
4703 break;
4704 case ARM64vecb_SQRSHL16x8:
4705 *p++ = X_3_8_5_6_5_5(X010, X01110011, vM, X010111, vN, vD);
4706 break;
4707 case ARM64vecb_SQRSHL8x16:
4708 *p++ = X_3_8_5_6_5_5(X010, X01110001, vM, X010111, vN, vD);
4709 break;
4710
4711 case ARM64vecb_UQSHL64x2:
4712 *p++ = X_3_8_5_6_5_5(X011, X01110111, vM, X010011, vN, vD);
4713 break;
4714 case ARM64vecb_UQSHL32x4:
4715 *p++ = X_3_8_5_6_5_5(X011, X01110101, vM, X010011, vN, vD);
4716 break;
4717 case ARM64vecb_UQSHL16x8:
4718 *p++ = X_3_8_5_6_5_5(X011, X01110011, vM, X010011, vN, vD);
4719 break;
4720 case ARM64vecb_UQSHL8x16:
4721 *p++ = X_3_8_5_6_5_5(X011, X01110001, vM, X010011, vN, vD);
4722 break;
4723
4724 case ARM64vecb_UQRSHL64x2:
4725 *p++ = X_3_8_5_6_5_5(X011, X01110111, vM, X010111, vN, vD);
4726 break;
4727 case ARM64vecb_UQRSHL32x4:
4728 *p++ = X_3_8_5_6_5_5(X011, X01110101, vM, X010111, vN, vD);
4729 break;
4730 case ARM64vecb_UQRSHL16x8:
4731 *p++ = X_3_8_5_6_5_5(X011, X01110011, vM, X010111, vN, vD);
4732 break;
4733 case ARM64vecb_UQRSHL8x16:
4734 *p++ = X_3_8_5_6_5_5(X011, X01110001, vM, X010111, vN, vD);
4735 break;
4736
sewardja6b61f02014-08-17 18:32:14 +00004737 case ARM64vecb_SSHL64x2:
4738 *p++ = X_3_8_5_6_5_5(X010, X01110111, vM, X010001, vN, vD);
4739 break;
4740 case ARM64vecb_SSHL32x4:
4741 *p++ = X_3_8_5_6_5_5(X010, X01110101, vM, X010001, vN, vD);
4742 break;
4743 case ARM64vecb_SSHL16x8:
4744 *p++ = X_3_8_5_6_5_5(X010, X01110011, vM, X010001, vN, vD);
4745 break;
4746 case ARM64vecb_SSHL8x16:
4747 *p++ = X_3_8_5_6_5_5(X010, X01110001, vM, X010001, vN, vD);
4748 break;
4749
4750 case ARM64vecb_SRSHL64x2:
4751 *p++ = X_3_8_5_6_5_5(X010, X01110111, vM, X010101, vN, vD);
4752 break;
4753 case ARM64vecb_SRSHL32x4:
4754 *p++ = X_3_8_5_6_5_5(X010, X01110101, vM, X010101, vN, vD);
4755 break;
4756 case ARM64vecb_SRSHL16x8:
4757 *p++ = X_3_8_5_6_5_5(X010, X01110011, vM, X010101, vN, vD);
4758 break;
4759 case ARM64vecb_SRSHL8x16:
4760 *p++ = X_3_8_5_6_5_5(X010, X01110001, vM, X010101, vN, vD);
4761 break;
4762
4763 case ARM64vecb_USHL64x2:
4764 *p++ = X_3_8_5_6_5_5(X011, X01110111, vM, X010001, vN, vD);
4765 break;
4766 case ARM64vecb_USHL32x4:
4767 *p++ = X_3_8_5_6_5_5(X011, X01110101, vM, X010001, vN, vD);
4768 break;
4769 case ARM64vecb_USHL16x8:
4770 *p++ = X_3_8_5_6_5_5(X011, X01110011, vM, X010001, vN, vD);
4771 break;
4772 case ARM64vecb_USHL8x16:
4773 *p++ = X_3_8_5_6_5_5(X011, X01110001, vM, X010001, vN, vD);
4774 break;
4775
4776 case ARM64vecb_URSHL64x2:
4777 *p++ = X_3_8_5_6_5_5(X011, X01110111, vM, X010101, vN, vD);
4778 break;
4779 case ARM64vecb_URSHL32x4:
4780 *p++ = X_3_8_5_6_5_5(X011, X01110101, vM, X010101, vN, vD);
4781 break;
4782 case ARM64vecb_URSHL16x8:
4783 *p++ = X_3_8_5_6_5_5(X011, X01110011, vM, X010101, vN, vD);
4784 break;
4785 case ARM64vecb_URSHL8x16:
4786 *p++ = X_3_8_5_6_5_5(X011, X01110001, vM, X010101, vN, vD);
4787 break;
4788
sewardj89cefe42015-02-24 12:21:01 +00004789 case ARM64vecb_FRECPS64x2:
4790 *p++ = X_3_8_5_6_5_5(X010, X01110011, vM, X111111, vN, vD);
4791 break;
4792 case ARM64vecb_FRECPS32x4:
4793 *p++ = X_3_8_5_6_5_5(X010, X01110001, vM, X111111, vN, vD);
4794 break;
4795 case ARM64vecb_FRSQRTS64x2:
4796 *p++ = X_3_8_5_6_5_5(X010, X01110111, vM, X111111, vN, vD);
4797 break;
4798 case ARM64vecb_FRSQRTS32x4:
4799 *p++ = X_3_8_5_6_5_5(X010, X01110101, vM, X111111, vN, vD);
4800 break;
4801
sewardj606c4ba2014-01-26 19:11:14 +00004802 default:
4803 goto bad;
4804 }
4805 goto done;
4806 }
sewardjf7003bc2014-08-18 12:28:02 +00004807 case ARM64in_VModifyV: {
4808 /* 31 23 20 15 9 4
4809 010 01110 sz 1 00000 001110 n d SUQADD@sz Vd, Vn
4810 011 01110 sz 1 00000 001110 n d USQADD@sz Vd, Vn
4811 */
sewardja5b50222015-03-26 07:18:32 +00004812 UInt vD = qregEnc(i->ARM64in.VModifyV.mod);
4813 UInt vN = qregEnc(i->ARM64in.VModifyV.arg);
sewardjf7003bc2014-08-18 12:28:02 +00004814 switch (i->ARM64in.VModifyV.op) {
4815 case ARM64vecmo_SUQADD64x2:
4816 *p++ = X_3_8_5_6_5_5(X010, X01110111, X00000, X001110, vN, vD);
4817 break;
4818 case ARM64vecmo_SUQADD32x4:
4819 *p++ = X_3_8_5_6_5_5(X010, X01110101, X00000, X001110, vN, vD);
4820 break;
4821 case ARM64vecmo_SUQADD16x8:
4822 *p++ = X_3_8_5_6_5_5(X010, X01110011, X00000, X001110, vN, vD);
4823 break;
4824 case ARM64vecmo_SUQADD8x16:
4825 *p++ = X_3_8_5_6_5_5(X010, X01110001, X00000, X001110, vN, vD);
4826 break;
4827 case ARM64vecmo_USQADD64x2:
4828 *p++ = X_3_8_5_6_5_5(X011, X01110111, X00000, X001110, vN, vD);
4829 break;
4830 case ARM64vecmo_USQADD32x4:
4831 *p++ = X_3_8_5_6_5_5(X011, X01110101, X00000, X001110, vN, vD);
4832 break;
4833 case ARM64vecmo_USQADD16x8:
4834 *p++ = X_3_8_5_6_5_5(X011, X01110011, X00000, X001110, vN, vD);
4835 break;
4836 case ARM64vecmo_USQADD8x16:
4837 *p++ = X_3_8_5_6_5_5(X011, X01110001, X00000, X001110, vN, vD);
4838 break;
4839 default:
4840 goto bad;
4841 }
4842 goto done;
4843 }
sewardjfab09142014-02-10 10:28:13 +00004844 case ARM64in_VUnaryV: {
4845 /* 31 23 20 15 9 4
sewardje520bb32014-02-17 11:00:53 +00004846 010 01110 11 1 00000 111110 n d FABS Vd.2d, Vn.2d
4847 010 01110 10 1 00000 111110 n d FABS Vd.4s, Vn.4s
4848 011 01110 11 1 00000 111110 n d FNEG Vd.2d, Vn.2d
4849 011 01110 10 1 00000 111110 n d FNEG Vd.4s, Vn.4s
4850 011 01110 00 1 00000 010110 n d NOT Vd.16b, Vn.16b
sewardj25523c42014-06-15 19:36:29 +00004851
4852 010 01110 11 1 00000 101110 n d ABS Vd.2d, Vn.2d
4853 010 01110 10 1 00000 101110 n d ABS Vd.4s, Vn.4s
4854 010 01110 01 1 00000 101110 n d ABS Vd.8h, Vn.8h
4855 010 01110 00 1 00000 101110 n d ABS Vd.16b, Vn.16b
sewardj2b6fd5e2014-06-19 14:21:37 +00004856
4857 010 01110 10 1 00000 010010 n d CLS Vd.4s, Vn.4s
4858 010 01110 01 1 00000 010010 n d CLS Vd.8h, Vn.8h
4859 010 01110 00 1 00000 010010 n d CLS Vd.16b, Vn.16b
4860
4861 011 01110 10 1 00000 010010 n d CLZ Vd.4s, Vn.4s
4862 011 01110 01 1 00000 010010 n d CLZ Vd.8h, Vn.8h
4863 011 01110 00 1 00000 010010 n d CLZ Vd.16b, Vn.16b
4864
4865 010 01110 00 1 00000 010110 n d CNT Vd.16b, Vn.16b
sewardj715d1622014-06-26 12:39:05 +00004866
4867 011 01110 01 1 00000 010110 n d RBIT Vd.16b, Vn.16b
sewardj715d1622014-06-26 12:39:05 +00004868 010 01110 00 1 00000 000110 n d REV16 Vd.16b, Vn.16b
sewardjdf9d6d52014-06-27 10:43:22 +00004869 011 01110 00 1 00000 000010 n d REV32 Vd.16b, Vn.16b
4870 011 01110 01 1 00000 000010 n d REV32 Vd.8h, Vn.8h
4871
4872 010 01110 00 1 00000 000010 n d REV64 Vd.16b, Vn.16b
4873 010 01110 01 1 00000 000010 n d REV64 Vd.8h, Vn.8h
4874 010 01110 10 1 00000 000010 n d REV64 Vd.4s, Vn.4s
sewardjfc261d92014-08-24 20:36:14 +00004875
4876 010 01110 10 1 00001 110010 n d URECPE Vd.4s, Vn.4s
4877 011 01110 10 1 00001 110010 n d URSQRTE Vd.4s, Vn.4s
sewardj89cefe42015-02-24 12:21:01 +00004878
4879 010 01110 11 1 00001 110110 n d FRECPE Vd.2d, Vn.2d
4880 010 01110 10 1 00001 110110 n d FRECPE Vd.4s, Vn.4s
4881
4882 011 01110 11 1 00001 110110 n d FRECPE Vd.2d, Vn.2d
4883 011 01110 10 1 00001 110110 n d FRECPE Vd.4s, Vn.4s
sewardj4b21c3d2015-04-06 19:34:03 +00004884
4885 011 01110 11 1 00001 111110 n d FSQRT Vd.2d, Vn.2d
4886 011 01110 10 1 00001 111110 n d FSQRT Vd.4s, Vn.4s
sewardjfab09142014-02-10 10:28:13 +00004887 */
sewardja5b50222015-03-26 07:18:32 +00004888 UInt vD = qregEnc(i->ARM64in.VUnaryV.dst);
4889 UInt vN = qregEnc(i->ARM64in.VUnaryV.arg);
sewardjfab09142014-02-10 10:28:13 +00004890 switch (i->ARM64in.VUnaryV.op) {
sewardje520bb32014-02-17 11:00:53 +00004891 case ARM64vecu_FABS64x2:
4892 *p++ = X_3_8_5_6_5_5(X010, X01110111, X00000, X111110, vN, vD);
4893 break;
sewardj2bd1ffe2014-03-27 18:59:00 +00004894 case ARM64vecu_FABS32x4:
4895 *p++ = X_3_8_5_6_5_5(X010, X01110101, X00000, X111110, vN, vD);
4896 break;
sewardjfab09142014-02-10 10:28:13 +00004897 case ARM64vecu_FNEG64x2:
4898 *p++ = X_3_8_5_6_5_5(X011, X01110111, X00000, X111110, vN, vD);
4899 break;
sewardj950ca7a2014-04-03 23:03:32 +00004900 case ARM64vecu_FNEG32x4:
4901 *p++ = X_3_8_5_6_5_5(X011, X01110101, X00000, X111110, vN, vD);
4902 break;
sewardje520bb32014-02-17 11:00:53 +00004903 case ARM64vecu_NOT:
4904 *p++ = X_3_8_5_6_5_5(X011, X01110001, X00000, X010110, vN, vD);
4905 break;
sewardj25523c42014-06-15 19:36:29 +00004906 case ARM64vecu_ABS64x2:
4907 *p++ = X_3_8_5_6_5_5(X010, X01110111, X00000, X101110, vN, vD);
4908 break;
4909 case ARM64vecu_ABS32x4:
4910 *p++ = X_3_8_5_6_5_5(X010, X01110101, X00000, X101110, vN, vD);
4911 break;
4912 case ARM64vecu_ABS16x8:
4913 *p++ = X_3_8_5_6_5_5(X010, X01110011, X00000, X101110, vN, vD);
4914 break;
4915 case ARM64vecu_ABS8x16:
4916 *p++ = X_3_8_5_6_5_5(X010, X01110001, X00000, X101110, vN, vD);
4917 break;
sewardj2b6fd5e2014-06-19 14:21:37 +00004918 case ARM64vecu_CLS32x4:
4919 *p++ = X_3_8_5_6_5_5(X010, X01110101, X00000, X010010, vN, vD);
4920 break;
4921 case ARM64vecu_CLS16x8:
4922 *p++ = X_3_8_5_6_5_5(X010, X01110011, X00000, X010010, vN, vD);
4923 break;
4924 case ARM64vecu_CLS8x16:
4925 *p++ = X_3_8_5_6_5_5(X010, X01110001, X00000, X010010, vN, vD);
4926 break;
4927 case ARM64vecu_CLZ32x4:
4928 *p++ = X_3_8_5_6_5_5(X011, X01110101, X00000, X010010, vN, vD);
4929 break;
4930 case ARM64vecu_CLZ16x8:
4931 *p++ = X_3_8_5_6_5_5(X011, X01110011, X00000, X010010, vN, vD);
4932 break;
4933 case ARM64vecu_CLZ8x16:
4934 *p++ = X_3_8_5_6_5_5(X011, X01110001, X00000, X010010, vN, vD);
4935 break;
4936 case ARM64vecu_CNT8x16:
4937 *p++ = X_3_8_5_6_5_5(X010, X01110001, X00000, X010110, vN, vD);
4938 break;
sewardj715d1622014-06-26 12:39:05 +00004939 case ARM64vecu_RBIT:
4940 *p++ = X_3_8_5_6_5_5(X011, X01110011, X00000, X010110, vN, vD);
4941 break;
4942 case ARM64vecu_REV1616B:
4943 *p++ = X_3_8_5_6_5_5(X010, X01110001, X00000, X000110, vN, vD);
4944 break;
sewardjdf9d6d52014-06-27 10:43:22 +00004945 case ARM64vecu_REV3216B:
4946 *p++ = X_3_8_5_6_5_5(X011, X01110001, X00000, X000010, vN, vD);
4947 break;
4948 case ARM64vecu_REV328H:
4949 *p++ = X_3_8_5_6_5_5(X011, X01110011, X00000, X000010, vN, vD);
4950 break;
4951 case ARM64vecu_REV6416B:
4952 *p++ = X_3_8_5_6_5_5(X010, X01110001, X00000, X000010, vN, vD);
4953 break;
4954 case ARM64vecu_REV648H:
4955 *p++ = X_3_8_5_6_5_5(X010, X01110011, X00000, X000010, vN, vD);
4956 break;
4957 case ARM64vecu_REV644S:
4958 *p++ = X_3_8_5_6_5_5(X010, X01110101, X00000, X000010, vN, vD);
4959 break;
sewardjfc261d92014-08-24 20:36:14 +00004960 case ARM64vecu_URECPE32x4:
4961 *p++ = X_3_8_5_6_5_5(X010, X01110101, X00001, X110010, vN, vD);
4962 break;
4963 case ARM64vecu_URSQRTE32x4:
4964 *p++ = X_3_8_5_6_5_5(X011, X01110101, X00001, X110010, vN, vD);
4965 break;
sewardj89cefe42015-02-24 12:21:01 +00004966 case ARM64vecu_FRECPE64x2:
4967 *p++ = X_3_8_5_6_5_5(X010, X01110111, X00001, X110110, vN, vD);
4968 break;
4969 case ARM64vecu_FRECPE32x4:
4970 *p++ = X_3_8_5_6_5_5(X010, X01110101, X00001, X110110, vN, vD);
4971 break;
4972 case ARM64vecu_FRSQRTE64x2:
4973 *p++ = X_3_8_5_6_5_5(X011, X01110111, X00001, X110110, vN, vD);
4974 break;
4975 case ARM64vecu_FRSQRTE32x4:
4976 *p++ = X_3_8_5_6_5_5(X011, X01110101, X00001, X110110, vN, vD);
4977 break;
sewardj4b21c3d2015-04-06 19:34:03 +00004978 case ARM64vecu_FSQRT64x2:
4979 *p++ = X_3_8_5_6_5_5(X011, X01110111, X00001, X111110, vN, vD);
4980 break;
4981 case ARM64vecu_FSQRT32x4:
4982 *p++ = X_3_8_5_6_5_5(X011, X01110101, X00001, X111110, vN, vD);
4983 break;
sewardjfab09142014-02-10 10:28:13 +00004984 default:
4985 goto bad;
4986 }
4987 goto done;
4988 }
sewardj606c4ba2014-01-26 19:11:14 +00004989 case ARM64in_VNarrowV: {
4990 /* 31 23 21 15 9 4
4991 000 01110 00 1,00001 001010 n d XTN Vd.8b, Vn.8h
4992 000 01110 01 1,00001 001010 n d XTN Vd.4h, Vn.4s
4993 000 01110 10 1,00001 001010 n d XTN Vd.2s, Vn.2d
sewardjecedd982014-08-11 14:02:47 +00004994
4995 001 01110 00 1,00001 001010 n d SQXTUN Vd.8b, Vn.8h
4996 001 01110 01 1,00001 001010 n d SQXTUN Vd.4h, Vn.4s
4997 001 01110 10 1,00001 001010 n d SQXTUN Vd.2s, Vn.2d
4998
4999 000 01110 00 1,00001 010010 n d SQXTN Vd.8b, Vn.8h
5000 000 01110 01 1,00001 010010 n d SQXTN Vd.4h, Vn.4s
5001 000 01110 10 1,00001 010010 n d SQXTN Vd.2s, Vn.2d
5002
5003 001 01110 00 1,00001 010010 n d UQXTN Vd.8b, Vn.8h
5004 001 01110 01 1,00001 010010 n d UQXTN Vd.4h, Vn.4s
5005 001 01110 10 1,00001 010010 n d UQXTN Vd.2s, Vn.2d
sewardj606c4ba2014-01-26 19:11:14 +00005006 */
sewardja5b50222015-03-26 07:18:32 +00005007 UInt vD = qregEnc(i->ARM64in.VNarrowV.dst);
5008 UInt vN = qregEnc(i->ARM64in.VNarrowV.src);
sewardj606c4ba2014-01-26 19:11:14 +00005009 UInt dszBlg2 = i->ARM64in.VNarrowV.dszBlg2;
5010 vassert(dszBlg2 >= 0 && dszBlg2 <= 2);
sewardjecedd982014-08-11 14:02:47 +00005011 switch (i->ARM64in.VNarrowV.op) {
5012 case ARM64vecna_XTN:
5013 *p++ = X_3_8_5_6_5_5(X000, X01110001 | (dszBlg2 << 1),
5014 X00001, X001010, vN, vD);
5015 goto done;
5016 case ARM64vecna_SQXTUN:
5017 *p++ = X_3_8_5_6_5_5(X001, X01110001 | (dszBlg2 << 1),
5018 X00001, X001010, vN, vD);
5019 goto done;
5020 case ARM64vecna_SQXTN:
5021 *p++ = X_3_8_5_6_5_5(X000, X01110001 | (dszBlg2 << 1),
5022 X00001, X010010, vN, vD);
5023 goto done;
5024 case ARM64vecna_UQXTN:
5025 *p++ = X_3_8_5_6_5_5(X001, X01110001 | (dszBlg2 << 1),
5026 X00001, X010010, vN, vD);
5027 goto done;
5028 default:
5029 break;
5030 }
5031 goto bad;
sewardj606c4ba2014-01-26 19:11:14 +00005032 }
sewardje520bb32014-02-17 11:00:53 +00005033 case ARM64in_VShiftImmV: {
5034 /*
sewardjecedd982014-08-11 14:02:47 +00005035 011 011110 immh immb 000001 n d USHR Vd.T, Vn.T, #sh
5036 010 011110 immh immb 000001 n d SSHR Vd.T, Vn.T, #sh
5037
5038 001 011110 immh immb 100101 n d UQSHRN ,,#sh
5039 000 011110 immh immb 100101 n d SQSHRN ,,#sh
5040 001 011110 immh immb 100001 n d SQSHRUN ,,#sh
5041
5042 001 011110 immh immb 100111 n d UQRSHRN ,,#sh
5043 000 011110 immh immb 100111 n d SQRSHRN ,,#sh
5044 001 011110 immh immb 100011 n d SQRSHRUN ,,#sh
sewardja97dddf2014-08-14 22:26:52 +00005045
sewardje520bb32014-02-17 11:00:53 +00005046 where immh:immb
5047 = case T of
sewardjecedd982014-08-11 14:02:47 +00005048 2d | sh in 1..64 -> let xxxxxx = 64-sh in 1xxx:xxx
5049 4s | sh in 1..32 -> let xxxxx = 32-sh in 01xx:xxx
5050 8h | sh in 1..16 -> let xxxx = 16-sh in 001x:xxx
5051 16b | sh in 1..8 -> let xxx = 8-sh in 0001:xxx
sewardj32d86752014-03-02 12:47:18 +00005052
sewardja97dddf2014-08-14 22:26:52 +00005053 010 011110 immh immb 010101 n d SHL Vd.T, Vn.T, #sh
5054
5055 011 011110 immh immb 011101 n d UQSHL Vd.T, Vn.T, #sh
5056 010 011110 immh immb 011101 n d SQSHL Vd.T, Vn.T, #sh
5057 011 011110 immh immb 011001 n d SQSHLU Vd.T, Vn.T, #sh
5058
sewardj32d86752014-03-02 12:47:18 +00005059 where immh:immb
5060 = case T of
sewardjecedd982014-08-11 14:02:47 +00005061 2d | sh in 0..63 -> let xxxxxx = sh in 1xxx:xxx
5062 4s | sh in 0..31 -> let xxxxx = sh in 01xx:xxx
5063 8h | sh in 0..15 -> let xxxx = sh in 001x:xxx
5064 16b | sh in 0..7 -> let xxx = sh in 0001:xxx
sewardje520bb32014-02-17 11:00:53 +00005065 */
sewardja5b50222015-03-26 07:18:32 +00005066 UInt vD = qregEnc(i->ARM64in.VShiftImmV.dst);
5067 UInt vN = qregEnc(i->ARM64in.VShiftImmV.src);
sewardjecedd982014-08-11 14:02:47 +00005068 UInt sh = i->ARM64in.VShiftImmV.amt;
5069 UInt tmpl = 0; /* invalid */
5070
5071 const UInt tmpl_USHR
5072 = X_3_6_7_6_5_5(X011, X011110, 0, X000001, vN, vD);
5073 const UInt tmpl_SSHR
5074 = X_3_6_7_6_5_5(X010, X011110, 0, X000001, vN, vD);
5075
5076 const UInt tmpl_UQSHRN
5077 = X_3_6_7_6_5_5(X001, X011110, 0, X100101, vN, vD);
5078 const UInt tmpl_SQSHRN
5079 = X_3_6_7_6_5_5(X000, X011110, 0, X100101, vN, vD);
5080 const UInt tmpl_SQSHRUN
5081 = X_3_6_7_6_5_5(X001, X011110, 0, X100001, vN, vD);
5082
5083 const UInt tmpl_UQRSHRN
5084 = X_3_6_7_6_5_5(X001, X011110, 0, X100111, vN, vD);
5085 const UInt tmpl_SQRSHRN
5086 = X_3_6_7_6_5_5(X000, X011110, 0, X100111, vN, vD);
5087 const UInt tmpl_SQRSHRUN
5088 = X_3_6_7_6_5_5(X001, X011110, 0, X100011, vN, vD);
5089
5090 const UInt tmpl_SHL
5091 = X_3_6_7_6_5_5(X010, X011110, 0, X010101, vN, vD);
5092
sewardja97dddf2014-08-14 22:26:52 +00005093 const UInt tmpl_UQSHL
5094 = X_3_6_7_6_5_5(X011, X011110, 0, X011101, vN, vD);
5095 const UInt tmpl_SQSHL
5096 = X_3_6_7_6_5_5(X010, X011110, 0, X011101, vN, vD);
5097 const UInt tmpl_SQSHLU
5098 = X_3_6_7_6_5_5(X011, X011110, 0, X011001, vN, vD);
5099
sewardjecedd982014-08-11 14:02:47 +00005100 switch (i->ARM64in.VShiftImmV.op) {
sewardja6b61f02014-08-17 18:32:14 +00005101 case ARM64vecshi_SSHR64x2: tmpl = tmpl_SSHR; goto right64x2;
5102 case ARM64vecshi_USHR64x2: tmpl = tmpl_USHR; goto right64x2;
5103 case ARM64vecshi_SHL64x2: tmpl = tmpl_SHL; goto left64x2;
5104 case ARM64vecshi_UQSHL64x2: tmpl = tmpl_UQSHL; goto left64x2;
5105 case ARM64vecshi_SQSHL64x2: tmpl = tmpl_SQSHL; goto left64x2;
5106 case ARM64vecshi_SQSHLU64x2: tmpl = tmpl_SQSHLU; goto left64x2;
5107 case ARM64vecshi_SSHR32x4: tmpl = tmpl_SSHR; goto right32x4;
5108 case ARM64vecshi_USHR32x4: tmpl = tmpl_USHR; goto right32x4;
5109 case ARM64vecshi_UQSHRN2SD: tmpl = tmpl_UQSHRN; goto right32x4;
5110 case ARM64vecshi_SQSHRN2SD: tmpl = tmpl_SQSHRN; goto right32x4;
5111 case ARM64vecshi_SQSHRUN2SD: tmpl = tmpl_SQSHRUN; goto right32x4;
5112 case ARM64vecshi_UQRSHRN2SD: tmpl = tmpl_UQRSHRN; goto right32x4;
5113 case ARM64vecshi_SQRSHRN2SD: tmpl = tmpl_SQRSHRN; goto right32x4;
5114 case ARM64vecshi_SQRSHRUN2SD: tmpl = tmpl_SQRSHRUN; goto right32x4;
5115 case ARM64vecshi_SHL32x4: tmpl = tmpl_SHL; goto left32x4;
5116 case ARM64vecshi_UQSHL32x4: tmpl = tmpl_UQSHL; goto left32x4;
5117 case ARM64vecshi_SQSHL32x4: tmpl = tmpl_SQSHL; goto left32x4;
5118 case ARM64vecshi_SQSHLU32x4: tmpl = tmpl_SQSHLU; goto left32x4;
5119 case ARM64vecshi_SSHR16x8: tmpl = tmpl_SSHR; goto right16x8;
5120 case ARM64vecshi_USHR16x8: tmpl = tmpl_USHR; goto right16x8;
5121 case ARM64vecshi_UQSHRN4HS: tmpl = tmpl_UQSHRN; goto right16x8;
5122 case ARM64vecshi_SQSHRN4HS: tmpl = tmpl_SQSHRN; goto right16x8;
5123 case ARM64vecshi_SQSHRUN4HS: tmpl = tmpl_SQSHRUN; goto right16x8;
5124 case ARM64vecshi_UQRSHRN4HS: tmpl = tmpl_UQRSHRN; goto right16x8;
5125 case ARM64vecshi_SQRSHRN4HS: tmpl = tmpl_SQRSHRN; goto right16x8;
5126 case ARM64vecshi_SQRSHRUN4HS: tmpl = tmpl_SQRSHRUN; goto right16x8;
5127 case ARM64vecshi_SHL16x8: tmpl = tmpl_SHL; goto left16x8;
5128 case ARM64vecshi_UQSHL16x8: tmpl = tmpl_UQSHL; goto left16x8;
5129 case ARM64vecshi_SQSHL16x8: tmpl = tmpl_SQSHL; goto left16x8;
5130 case ARM64vecshi_SQSHLU16x8: tmpl = tmpl_SQSHLU; goto left16x8;
5131 case ARM64vecshi_SSHR8x16: tmpl = tmpl_SSHR; goto right8x16;
5132 case ARM64vecshi_USHR8x16: tmpl = tmpl_USHR; goto right8x16;
5133 case ARM64vecshi_UQSHRN8BH: tmpl = tmpl_UQSHRN; goto right8x16;
5134 case ARM64vecshi_SQSHRN8BH: tmpl = tmpl_SQSHRN; goto right8x16;
5135 case ARM64vecshi_SQSHRUN8BH: tmpl = tmpl_SQSHRUN; goto right8x16;
5136 case ARM64vecshi_UQRSHRN8BH: tmpl = tmpl_UQRSHRN; goto right8x16;
5137 case ARM64vecshi_SQRSHRN8BH: tmpl = tmpl_SQRSHRN; goto right8x16;
5138 case ARM64vecshi_SQRSHRUN8BH: tmpl = tmpl_SQRSHRUN; goto right8x16;
5139 case ARM64vecshi_SHL8x16: tmpl = tmpl_SHL; goto left8x16;
5140 case ARM64vecshi_UQSHL8x16: tmpl = tmpl_UQSHL; goto left8x16;
5141 case ARM64vecshi_SQSHL8x16: tmpl = tmpl_SQSHL; goto left8x16;
5142 case ARM64vecshi_SQSHLU8x16: tmpl = tmpl_SQSHLU; goto left8x16;
sewardjecedd982014-08-11 14:02:47 +00005143
5144 default: break;
5145
5146 right64x2:
sewardje520bb32014-02-17 11:00:53 +00005147 if (sh >= 1 && sh <= 63) {
sewardjecedd982014-08-11 14:02:47 +00005148 *p++ = tmpl | X_3_6_7_6_5_5(0,0, X1000000 | (64-sh), 0,0,0);
sewardje520bb32014-02-17 11:00:53 +00005149 goto done;
5150 }
5151 break;
sewardjecedd982014-08-11 14:02:47 +00005152 right32x4:
5153 if (sh >= 1 && sh <= 32) {
5154 *p++ = tmpl | X_3_6_7_6_5_5(0,0, X0100000 | (32-sh), 0,0,0);
5155 goto done;
5156 }
5157 break;
5158 right16x8:
5159 if (sh >= 1 && sh <= 16) {
5160 *p++ = tmpl | X_3_6_7_6_5_5(0,0, X0010000 | (16-sh), 0,0,0);
5161 goto done;
5162 }
5163 break;
5164 right8x16:
5165 if (sh >= 1 && sh <= 8) {
5166 *p++ = tmpl | X_3_6_7_6_5_5(0,0, X0001000 | (8-sh), 0,0,0);
5167 goto done;
5168 }
5169 break;
5170
5171 left64x2:
sewardja97dddf2014-08-14 22:26:52 +00005172 if (sh >= 0 && sh <= 63) {
sewardjecedd982014-08-11 14:02:47 +00005173 *p++ = tmpl | X_3_6_7_6_5_5(0,0, X1000000 | sh, 0,0,0);
sewardj93013432014-04-27 12:02:12 +00005174 goto done;
5175 }
5176 break;
sewardjecedd982014-08-11 14:02:47 +00005177 left32x4:
sewardja97dddf2014-08-14 22:26:52 +00005178 if (sh >= 0 && sh <= 31) {
sewardjecedd982014-08-11 14:02:47 +00005179 *p++ = tmpl | X_3_6_7_6_5_5(0,0, X0100000 | sh, 0,0,0);
sewardj93013432014-04-27 12:02:12 +00005180 goto done;
5181 }
5182 break;
sewardjecedd982014-08-11 14:02:47 +00005183 left16x8:
sewardja97dddf2014-08-14 22:26:52 +00005184 if (sh >= 0 && sh <= 15) {
sewardjecedd982014-08-11 14:02:47 +00005185 *p++ = tmpl | X_3_6_7_6_5_5(0,0, X0010000 | sh, 0,0,0);
sewardj1eaaec22014-03-07 22:52:19 +00005186 goto done;
5187 }
5188 break;
sewardjecedd982014-08-11 14:02:47 +00005189 left8x16:
sewardja97dddf2014-08-14 22:26:52 +00005190 if (sh >= 0 && sh <= 7) {
sewardjecedd982014-08-11 14:02:47 +00005191 *p++ = tmpl | X_3_6_7_6_5_5(0,0, X0001000 | sh, 0,0,0);
sewardj93013432014-04-27 12:02:12 +00005192 goto done;
5193 }
5194 break;
sewardje520bb32014-02-17 11:00:53 +00005195 }
5196 goto bad;
5197 }
sewardjab33a7a2014-06-19 22:20:47 +00005198 case ARM64in_VExtV: {
5199 /*
5200 011 01110 000 m 0 imm4 0 n d EXT Vd.16b, Vn.16b, Vm.16b, #imm4
5201 where imm4 = the shift amount, in bytes,
5202 Vn is low operand, Vm is high operand
5203 */
sewardja5b50222015-03-26 07:18:32 +00005204 UInt vD = qregEnc(i->ARM64in.VExtV.dst);
5205 UInt vN = qregEnc(i->ARM64in.VExtV.srcLo);
5206 UInt vM = qregEnc(i->ARM64in.VExtV.srcHi);
sewardjab33a7a2014-06-19 22:20:47 +00005207 UInt imm4 = i->ARM64in.VExtV.amtB;
5208 vassert(imm4 >= 1 && imm4 <= 15);
5209 *p++ = X_3_8_5_6_5_5(X011, X01110000, vM,
5210 X000000 | (imm4 << 1), vN, vD);
5211 goto done;
5212 }
sewardjbbcf1882014-01-12 12:49:10 +00005213 case ARM64in_VImmQ: {
sewardja5b50222015-03-26 07:18:32 +00005214 UInt rQ = qregEnc(i->ARM64in.VImmQ.rQ);
sewardjbbcf1882014-01-12 12:49:10 +00005215 UShort imm = i->ARM64in.VImmQ.imm;
sewardj208a7762014-10-22 13:52:51 +00005216 vassert(rQ < 32);
5217 switch (imm) {
5218 case 0x0000:
5219 // movi rQ.4s, #0x0 == 0x4F 0x00 0x04 000 rQ
5220 *p++ = 0x4F000400 | rQ;
5221 goto done;
5222 case 0x0001:
5223 // movi rQ, #0xFF == 0x2F 0x00 0xE4 001 rQ
5224 *p++ = 0x2F00E420 | rQ;
5225 goto done;
5226 case 0x0003:
5227 // movi rQ, #0xFFFF == 0x2F 0x00 0xE4 011 rQ
5228 *p++ = 0x2F00E460 | rQ;
5229 goto done;
5230 case 0x000F:
5231 // movi rQ, #0xFFFFFFFF == 0x2F 0x00 0xE5 111 rQ
5232 *p++ = 0x2F00E5E0 | rQ;
5233 goto done;
5234 case 0x003F:
5235 // movi rQ, #0xFFFFFFFFFFFF == 0x2F 0x01 0xE7 111 rQ
5236 *p++ = 0x2F01E7E0 | rQ;
5237 goto done;
5238 case 0x00FF:
5239 // movi rQ, #0xFFFFFFFFFFFFFFFF == 0x2F 0x07 0xE7 111 rQ
5240 *p++ = 0x2F07E7E0 | rQ;
5241 goto done;
5242 case 0xFFFF:
5243 // mvni rQ.4s, #0x0 == 0x6F 0x00 0x04 000 rQ
5244 *p++ = 0x6F000400 | rQ;
5245 goto done;
5246 default:
5247 break;
sewardj8e91fd42014-07-11 12:05:47 +00005248 }
sewardjecde6972014-02-05 11:01:19 +00005249 goto bad; /* no other handled cases right now */
sewardjbbcf1882014-01-12 12:49:10 +00005250 }
5251
5252 case ARM64in_VDfromX: {
5253 /* INS Vd.D[0], rX
5254 0100 1110 0000 1000 0001 11 nn dd INS Vd.D[0], Xn
5255 This isn't wonderful, in the sense that the upper half of
5256 the vector register stays unchanged and thus the insn is
5257 data dependent on its output register. */
sewardja5b50222015-03-26 07:18:32 +00005258 UInt dd = dregEnc(i->ARM64in.VDfromX.rD);
5259 UInt xx = iregEnc(i->ARM64in.VDfromX.rX);
sewardjbbcf1882014-01-12 12:49:10 +00005260 vassert(xx < 31);
5261 *p++ = 0x4E081C00 | X_2_6_2_12_5_5(0,0,0,0,xx,dd);
5262 goto done;
5263 }
5264
sewardj12972182014-08-04 08:09:47 +00005265 case ARM64in_VQfromX: {
5266 /* FMOV D, X
5267 1001 1110 0110 0111 0000 00 nn dd FMOV Vd.D[0], Xn
5268 I think this zeroes out the top half of the destination, which
5269 is what we need. TODO: can we do VDfromX and VQfromXX better? */
sewardja5b50222015-03-26 07:18:32 +00005270 UInt dd = qregEnc(i->ARM64in.VQfromX.rQ);
5271 UInt xx = iregEnc(i->ARM64in.VQfromX.rXlo);
sewardj12972182014-08-04 08:09:47 +00005272 vassert(xx < 31);
5273 *p++ = 0x9E670000 | X_2_6_2_12_5_5(0,0,0,0,xx,dd);
5274 goto done;
5275 }
5276
sewardjbbcf1882014-01-12 12:49:10 +00005277 case ARM64in_VQfromXX: {
5278 /* What we really generate is a two insn sequence:
5279 INS Vd.D[0], Xlo; INS Vd.D[1], Xhi
5280 0100 1110 0000 1000 0001 11 nn dd INS Vd.D[0], Xn
5281 0100 1110 0001 1000 0001 11 nn dd INS Vd.D[1], Xn
5282 */
sewardja5b50222015-03-26 07:18:32 +00005283 UInt qq = qregEnc(i->ARM64in.VQfromXX.rQ);
5284 UInt xhi = iregEnc(i->ARM64in.VQfromXX.rXhi);
5285 UInt xlo = iregEnc(i->ARM64in.VQfromXX.rXlo);
sewardjbbcf1882014-01-12 12:49:10 +00005286 vassert(xhi < 31 && xlo < 31);
5287 *p++ = 0x4E081C00 | X_2_6_2_12_5_5(0,0,0,0,xlo,qq);
5288 *p++ = 0x4E181C00 | X_2_6_2_12_5_5(0,0,0,0,xhi,qq);
5289 goto done;
5290 }
5291
5292 case ARM64in_VXfromQ: {
5293 /* 010 0111 0000 01000 001111 nn dd UMOV Xd, Vn.D[0]
5294 010 0111 0000 11000 001111 nn dd UMOV Xd, Vn.D[1]
5295 */
sewardja5b50222015-03-26 07:18:32 +00005296 UInt dd = iregEnc(i->ARM64in.VXfromQ.rX);
5297 UInt nn = qregEnc(i->ARM64in.VXfromQ.rQ);
sewardjbbcf1882014-01-12 12:49:10 +00005298 UInt laneNo = i->ARM64in.VXfromQ.laneNo;
5299 vassert(dd < 31);
5300 vassert(laneNo < 2);
5301 *p++ = X_3_8_5_6_5_5(X010, X01110000,
5302 laneNo == 1 ? X11000 : X01000, X001111, nn, dd);
5303 goto done;
5304 }
5305
sewardj85fbb022014-06-12 13:16:01 +00005306 case ARM64in_VXfromDorS: {
5307 /* 000 11110001 00110 000000 n d FMOV Wd, Sn
5308 100 11110011 00110 000000 n d FMOV Xd, Dn
5309 */
sewardja5b50222015-03-26 07:18:32 +00005310 UInt dd = iregEnc(i->ARM64in.VXfromDorS.rX);
5311 UInt nn = dregEnc(i->ARM64in.VXfromDorS.rDorS);
sewardj85fbb022014-06-12 13:16:01 +00005312 Bool fromD = i->ARM64in.VXfromDorS.fromD;
5313 vassert(dd < 31);
5314 *p++ = X_3_8_5_6_5_5(fromD ? X100 : X000,
5315 fromD ? X11110011 : X11110001,
5316 X00110, X000000, nn, dd);
5317 goto done;
5318 }
5319
sewardjbbcf1882014-01-12 12:49:10 +00005320 case ARM64in_VMov: {
5321 /* 000 11110 00 10000 00 10000 n d FMOV Sd, Sn
5322 000 11110 01 10000 00 10000 n d FMOV Dd, Dn
5323 010 01110 10 1 n 0 00111 n d MOV Vd.16b, Vn.16b
5324 */
5325 HReg rD = i->ARM64in.VMov.dst;
5326 HReg rN = i->ARM64in.VMov.src;
5327 switch (i->ARM64in.VMov.szB) {
sewardja97dddf2014-08-14 22:26:52 +00005328 case 16: {
sewardja5b50222015-03-26 07:18:32 +00005329 UInt dd = qregEnc(rD);
5330 UInt nn = qregEnc(rN);
sewardja97dddf2014-08-14 22:26:52 +00005331 *p++ = X_3_8_5_6_5_5(X010, X01110101, nn, X000111, nn, dd);
5332 goto done;
5333 }
sewardjbbcf1882014-01-12 12:49:10 +00005334 case 8: {
sewardja5b50222015-03-26 07:18:32 +00005335 UInt dd = dregEnc(rD);
5336 UInt nn = dregEnc(rN);
sewardjbbcf1882014-01-12 12:49:10 +00005337 *p++ = X_3_8_5_6_5_5(X000, X11110011, X00000, X010000, nn, dd);
5338 goto done;
5339 }
5340 default:
5341 break;
5342 }
5343 goto bad;
5344 }
sewardjbbcf1882014-01-12 12:49:10 +00005345
5346 case ARM64in_EvCheck: {
5347 /* The sequence is fixed (canned) except for the two amodes
5348 supplied by the insn. These don't change the length, though.
5349 We generate:
5350 ldr w9, [x21 + #8] 8 == offsetof(host_EvC_COUNTER)
5351 subs w9, w9, #1
5352 str w9, [x21 + #8] 8 == offsetof(host_EvC_COUNTER)
5353 bpl nofail
5354 ldr x9, [x21 + #0] 0 == offsetof(host_EvC_FAILADDR)
5355 br x9
5356 nofail:
5357 */
5358 UInt* p0 = p;
5359 p = do_load_or_store32(p, True/*isLoad*/, /*w*/9,
5360 i->ARM64in.EvCheck.amCounter);
5361 *p++ = 0x71000529; /* subs w9, w9, #1 */
5362 p = do_load_or_store32(p, False/*!isLoad*/, /*w*/9,
5363 i->ARM64in.EvCheck.amCounter);
5364 *p++ = 0x54000065; /* bpl nofail */
5365 p = do_load_or_store64(p, True/*isLoad*/, /*x*/9,
5366 i->ARM64in.EvCheck.amFailAddr);
5367 *p++ = 0xD61F0120; /* br x9 */
5368 /* nofail: */
5369
5370 /* Crosscheck */
florian7ce2cc82015-01-10 16:10:58 +00005371 vassert(evCheckSzB_ARM64() == (UChar*)p - (UChar*)p0);
sewardjbbcf1882014-01-12 12:49:10 +00005372 goto done;
5373 }
5374
sewardj0ad37a92014-08-29 21:58:03 +00005375 case ARM64in_ProfInc: {
5376 /* We generate:
5377 (ctrP is unknown now, so use 0x6555'7555'8555'9566 in the
5378 expectation that a later call to LibVEX_patchProfCtr
5379 will be used to fill in the immediate fields once the
5380 right value is known.)
5381 imm64-exactly4 x9, 0x6555'7555'8555'9566
5382 ldr x8, [x9]
5383 add x8, x8, #1
5384 str x8, [x9]
5385 */
sewardja5b50222015-03-26 07:18:32 +00005386 p = imm64_to_ireg_EXACTLY4(p, /*x*/9, 0x6555755585559566ULL);
sewardj0ad37a92014-08-29 21:58:03 +00005387 *p++ = 0xF9400128;
5388 *p++ = 0x91000508;
5389 *p++ = 0xF9000128;
5390 /* Tell the caller .. */
5391 vassert(!(*is_profInc));
5392 *is_profInc = True;
5393 goto done;
5394 }
sewardjbbcf1882014-01-12 12:49:10 +00005395
5396 /* ... */
5397 default:
5398 goto bad;
5399 }
5400
5401 bad:
5402 ppARM64Instr(i);
5403 vpanic("emit_ARM64Instr");
5404 /*NOTREACHED*/
5405
5406 done:
5407 vassert(((UChar*)p) - &buf[0] <= 36);
5408 return ((UChar*)p) - &buf[0];
5409}
5410
5411
5412/* How big is an event check? See case for ARM64in_EvCheck in
5413 emit_ARM64Instr just above. That crosschecks what this returns, so
5414 we can tell if we're inconsistent. */
florian7ce2cc82015-01-10 16:10:58 +00005415Int evCheckSzB_ARM64 (void)
sewardjbbcf1882014-01-12 12:49:10 +00005416{
5417 return 24;
5418}
5419
5420
5421/* NB: what goes on here has to be very closely coordinated with the
5422 emitInstr case for XDirect, above. */
sewardj9b769162014-07-24 12:42:03 +00005423VexInvalRange chainXDirect_ARM64 ( VexEndness endness_host,
5424 void* place_to_chain,
florian7d6f81d2014-09-22 21:43:37 +00005425 const void* disp_cp_chain_me_EXPECTED,
5426 const void* place_to_jump_to )
sewardjbbcf1882014-01-12 12:49:10 +00005427{
sewardj9b769162014-07-24 12:42:03 +00005428 vassert(endness_host == VexEndnessLE);
5429
sewardjbbcf1882014-01-12 12:49:10 +00005430 /* What we're expecting to see is:
5431 movw x9, disp_cp_chain_me_to_EXPECTED[15:0]
5432 movk x9, disp_cp_chain_me_to_EXPECTED[31:15], lsl 16
5433 movk x9, disp_cp_chain_me_to_EXPECTED[47:32], lsl 32
5434 movk x9, disp_cp_chain_me_to_EXPECTED[63:48], lsl 48
5435 blr x9
5436 viz
sewardja5b50222015-03-26 07:18:32 +00005437 <16 bytes generated by imm64_to_ireg_EXACTLY4>
sewardjbbcf1882014-01-12 12:49:10 +00005438 D6 3F 01 20
5439 */
5440 UInt* p = (UInt*)place_to_chain;
5441 vassert(0 == (3 & (HWord)p));
sewardja5b50222015-03-26 07:18:32 +00005442 vassert(is_imm64_to_ireg_EXACTLY4(
5443 p, /*x*/9, (Addr)disp_cp_chain_me_EXPECTED));
sewardjbbcf1882014-01-12 12:49:10 +00005444 vassert(p[4] == 0xD63F0120);
sewardjc6acaa42014-02-19 17:42:59 +00005445
sewardjbbcf1882014-01-12 12:49:10 +00005446 /* And what we want to change it to is:
5447 movw x9, place_to_jump_to[15:0]
5448 movk x9, place_to_jump_to[31:15], lsl 16
5449 movk x9, place_to_jump_to[47:32], lsl 32
5450 movk x9, place_to_jump_to[63:48], lsl 48
5451 br x9
5452 viz
sewardja5b50222015-03-26 07:18:32 +00005453 <16 bytes generated by imm64_to_ireg_EXACTLY4>
sewardjbbcf1882014-01-12 12:49:10 +00005454 D6 1F 01 20
5455
5456 The replacement has the same length as the original.
5457 */
sewardja5b50222015-03-26 07:18:32 +00005458 (void)imm64_to_ireg_EXACTLY4(p, /*x*/9, (Addr)place_to_jump_to);
sewardjbbcf1882014-01-12 12:49:10 +00005459 p[4] = 0xD61F0120;
5460
5461 VexInvalRange vir = {(HWord)p, 20};
5462 return vir;
5463}
5464
5465
sewardjc6acaa42014-02-19 17:42:59 +00005466/* NB: what goes on here has to be very closely coordinated with the
5467 emitInstr case for XDirect, above. */
sewardj9b769162014-07-24 12:42:03 +00005468VexInvalRange unchainXDirect_ARM64 ( VexEndness endness_host,
5469 void* place_to_unchain,
florian7d6f81d2014-09-22 21:43:37 +00005470 const void* place_to_jump_to_EXPECTED,
5471 const void* disp_cp_chain_me )
sewardjc6acaa42014-02-19 17:42:59 +00005472{
sewardj9b769162014-07-24 12:42:03 +00005473 vassert(endness_host == VexEndnessLE);
5474
sewardjc6acaa42014-02-19 17:42:59 +00005475 /* What we're expecting to see is:
5476 movw x9, place_to_jump_to_EXPECTED[15:0]
5477 movk x9, place_to_jump_to_EXPECTED[31:15], lsl 16
5478 movk x9, place_to_jump_to_EXPECTED[47:32], lsl 32
5479 movk x9, place_to_jump_to_EXPECTED[63:48], lsl 48
5480 br x9
5481 viz
sewardja5b50222015-03-26 07:18:32 +00005482 <16 bytes generated by imm64_to_ireg_EXACTLY4>
sewardjc6acaa42014-02-19 17:42:59 +00005483 D6 1F 01 20
5484 */
5485 UInt* p = (UInt*)place_to_unchain;
5486 vassert(0 == (3 & (HWord)p));
sewardja5b50222015-03-26 07:18:32 +00005487 vassert(is_imm64_to_ireg_EXACTLY4(
florian93a09742015-01-07 20:14:48 +00005488 p, /*x*/9, (Addr)place_to_jump_to_EXPECTED));
sewardjc6acaa42014-02-19 17:42:59 +00005489 vassert(p[4] == 0xD61F0120);
5490
5491 /* And what we want to change it to is:
5492 movw x9, disp_cp_chain_me_to[15:0]
5493 movk x9, disp_cp_chain_me_to[31:15], lsl 16
5494 movk x9, disp_cp_chain_me_to[47:32], lsl 32
5495 movk x9, disp_cp_chain_me_to[63:48], lsl 48
5496 blr x9
5497 viz
sewardja5b50222015-03-26 07:18:32 +00005498 <16 bytes generated by imm64_to_ireg_EXACTLY4>
sewardjc6acaa42014-02-19 17:42:59 +00005499 D6 3F 01 20
5500 */
sewardja5b50222015-03-26 07:18:32 +00005501 (void)imm64_to_ireg_EXACTLY4(p, /*x*/9, (Addr)disp_cp_chain_me);
sewardjc6acaa42014-02-19 17:42:59 +00005502 p[4] = 0xD63F0120;
5503
5504 VexInvalRange vir = {(HWord)p, 20};
5505 return vir;
5506}
5507
5508
sewardj0ad37a92014-08-29 21:58:03 +00005509/* Patch the counter address into a profile inc point, as previously
5510 created by the ARM64in_ProfInc case for emit_ARM64Instr. */
5511VexInvalRange patchProfInc_ARM64 ( VexEndness endness_host,
5512 void* place_to_patch,
florian7d6f81d2014-09-22 21:43:37 +00005513 const ULong* location_of_counter )
sewardj0ad37a92014-08-29 21:58:03 +00005514{
5515 vassert(sizeof(ULong*) == 8);
5516 vassert(endness_host == VexEndnessLE);
5517 UInt* p = (UInt*)place_to_patch;
5518 vassert(0 == (3 & (HWord)p));
sewardja5b50222015-03-26 07:18:32 +00005519 vassert(is_imm64_to_ireg_EXACTLY4(p, /*x*/9, 0x6555755585559566ULL));
sewardj0ad37a92014-08-29 21:58:03 +00005520 vassert(p[4] == 0xF9400128);
5521 vassert(p[5] == 0x91000508);
5522 vassert(p[6] == 0xF9000128);
sewardja5b50222015-03-26 07:18:32 +00005523 imm64_to_ireg_EXACTLY4(p, /*x*/9, (Addr)location_of_counter);
sewardj0ad37a92014-08-29 21:58:03 +00005524 VexInvalRange vir = {(HWord)p, 4*4};
5525 return vir;
5526}
sewardjbbcf1882014-01-12 12:49:10 +00005527
5528/*---------------------------------------------------------------*/
5529/*--- end host_arm64_defs.c ---*/
5530/*---------------------------------------------------------------*/