blob: 122a9f9c40d02870b181f8e2767003891dcac8b8 [file] [log] [blame]
cerion82edbb32004-12-16 14:06:34 +00001
2/*---------------------------------------------------------------*/
sewardj752f9062010-05-03 21:38:49 +00003/*--- begin host_arm_defs.c ---*/
cerion82edbb32004-12-16 14:06:34 +00004/*---------------------------------------------------------------*/
5
6/*
sewardj752f9062010-05-03 21:38:49 +00007 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
cerion82edbb32004-12-16 14:06:34 +00009
sewardj752f9062010-05-03 21:38:49 +000010 Copyright (C) 2004-2010 OpenWorks LLP
11 info@open-works.net
sewardj64733c42010-10-12 10:10:46 +000012
13 NEON support is
14 Copyright (C) 2010-2010 Samsung Electronics
15 contributed by Dmitry Zhurikhin <zhur@ispras.ru>
16 and Kirill Batuzov <batuzovk@ispras.ru>
cerion82edbb32004-12-16 14:06:34 +000017
sewardj752f9062010-05-03 21:38:49 +000018 This program is free software; you can redistribute it and/or
19 modify it under the terms of the GNU General Public License as
20 published by the Free Software Foundation; either version 2 of the
21 License, or (at your option) any later version.
cerion82edbb32004-12-16 14:06:34 +000022
sewardj752f9062010-05-03 21:38:49 +000023 This program is distributed in the hope that it will be useful, but
24 WITHOUT ANY WARRANTY; without even the implied warranty of
25 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
26 General Public License for more details.
27
28 You should have received a copy of the GNU General Public License
29 along with this program; if not, write to the Free Software
30 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
sewardj7bd6ffe2005-08-03 16:07:36 +000031 02110-1301, USA.
32
sewardj752f9062010-05-03 21:38:49 +000033 The GNU General Public License is contained in the file COPYING.
cerion82edbb32004-12-16 14:06:34 +000034*/
35
36#include "libvex_basictypes.h"
37#include "libvex.h"
38#include "libvex_trc_values.h"
39
sewardjcef7d3e2009-07-02 12:21:59 +000040#include "main_util.h"
41#include "host_generic_regs.h"
42#include "host_arm_defs.h"
cerion82edbb32004-12-16 14:06:34 +000043
sewardj6c60b322010-08-22 12:48:28 +000044UInt arm_hwcaps = 0;
cerion82edbb32004-12-16 14:06:34 +000045
46
47/* --------- Registers. --------- */
48
cerioncee30312004-12-17 20:30:21 +000049/* The usual HReg abstraction.
50 There are 16 general purpose regs.
cerion82edbb32004-12-16 14:06:34 +000051*/
52
cerion82edbb32004-12-16 14:06:34 +000053void ppHRegARM ( HReg reg ) {
54 Int r;
cerion82edbb32004-12-16 14:06:34 +000055 /* Be generic for all virtual regs. */
56 if (hregIsVirtual(reg)) {
57 ppHReg(reg);
58 return;
59 }
60 /* But specific for real regs. */
61 switch (hregClass(reg)) {
62 case HRcInt32:
63 r = hregNumber(reg);
64 vassert(r >= 0 && r < 16);
sewardj6c299f32009-12-31 18:00:12 +000065 vex_printf("r%d", r);
66 return;
67 case HRcFlt64:
68 r = hregNumber(reg);
sewardj6c60b322010-08-22 12:48:28 +000069 vassert(r >= 0 && r < 32);
sewardj6c299f32009-12-31 18:00:12 +000070 vex_printf("d%d", r);
71 return;
72 case HRcFlt32:
73 r = hregNumber(reg);
74 vassert(r >= 0 && r < 32);
75 vex_printf("s%d", r);
cerion82edbb32004-12-16 14:06:34 +000076 return;
sewardj6c60b322010-08-22 12:48:28 +000077 case HRcVec128:
78 r = hregNumber(reg);
79 vassert(r >= 0 && r < 16);
80 vex_printf("q%d", r);
81 return;
cerion82edbb32004-12-16 14:06:34 +000082 default:
83 vpanic("ppHRegARM");
84 }
85}
86
sewardj6c299f32009-12-31 18:00:12 +000087HReg hregARM_R0 ( void ) { return mkHReg(0, HRcInt32, False); }
88HReg hregARM_R1 ( void ) { return mkHReg(1, HRcInt32, False); }
89HReg hregARM_R2 ( void ) { return mkHReg(2, HRcInt32, False); }
90HReg hregARM_R3 ( void ) { return mkHReg(3, HRcInt32, False); }
91HReg hregARM_R4 ( void ) { return mkHReg(4, HRcInt32, False); }
92HReg hregARM_R5 ( void ) { return mkHReg(5, HRcInt32, False); }
93HReg hregARM_R6 ( void ) { return mkHReg(6, HRcInt32, False); }
94HReg hregARM_R7 ( void ) { return mkHReg(7, HRcInt32, False); }
95HReg hregARM_R8 ( void ) { return mkHReg(8, HRcInt32, False); }
96HReg hregARM_R9 ( void ) { return mkHReg(9, HRcInt32, False); }
cerion82edbb32004-12-16 14:06:34 +000097HReg hregARM_R10 ( void ) { return mkHReg(10, HRcInt32, False); }
98HReg hregARM_R11 ( void ) { return mkHReg(11, HRcInt32, False); }
99HReg hregARM_R12 ( void ) { return mkHReg(12, HRcInt32, False); }
100HReg hregARM_R13 ( void ) { return mkHReg(13, HRcInt32, False); }
101HReg hregARM_R14 ( void ) { return mkHReg(14, HRcInt32, False); }
102HReg hregARM_R15 ( void ) { return mkHReg(15, HRcInt32, False); }
sewardj6c299f32009-12-31 18:00:12 +0000103HReg hregARM_D8 ( void ) { return mkHReg(8, HRcFlt64, False); }
104HReg hregARM_D9 ( void ) { return mkHReg(9, HRcFlt64, False); }
105HReg hregARM_D10 ( void ) { return mkHReg(10, HRcFlt64, False); }
106HReg hregARM_D11 ( void ) { return mkHReg(11, HRcFlt64, False); }
107HReg hregARM_D12 ( void ) { return mkHReg(12, HRcFlt64, False); }
108HReg hregARM_S26 ( void ) { return mkHReg(26, HRcFlt32, False); }
109HReg hregARM_S27 ( void ) { return mkHReg(27, HRcFlt32, False); }
110HReg hregARM_S28 ( void ) { return mkHReg(28, HRcFlt32, False); }
111HReg hregARM_S29 ( void ) { return mkHReg(29, HRcFlt32, False); }
112HReg hregARM_S30 ( void ) { return mkHReg(30, HRcFlt32, False); }
sewardj6c60b322010-08-22 12:48:28 +0000113HReg hregARM_Q8 ( void ) { return mkHReg(8, HRcVec128, False); }
114HReg hregARM_Q9 ( void ) { return mkHReg(9, HRcVec128, False); }
115HReg hregARM_Q10 ( void ) { return mkHReg(10, HRcVec128, False); }
116HReg hregARM_Q11 ( void ) { return mkHReg(11, HRcVec128, False); }
117HReg hregARM_Q12 ( void ) { return mkHReg(12, HRcVec128, False); }
118HReg hregARM_Q13 ( void ) { return mkHReg(13, HRcVec128, False); }
119HReg hregARM_Q14 ( void ) { return mkHReg(14, HRcVec128, False); }
120HReg hregARM_Q15 ( void ) { return mkHReg(15, HRcVec128, False); }
cerion82edbb32004-12-16 14:06:34 +0000121
sewardj6c299f32009-12-31 18:00:12 +0000122void getAllocableRegs_ARM ( Int* nregs, HReg** arr )
123{
124 Int i = 0;
sewardjef9ef372010-08-31 09:32:40 +0000125 *nregs = 26;
cerion82edbb32004-12-16 14:06:34 +0000126 *arr = LibVEX_Alloc(*nregs * sizeof(HReg));
sewardj6c299f32009-12-31 18:00:12 +0000127 // callee saves ones are listed first, since we prefer them
128 // if they're available
129 (*arr)[i++] = hregARM_R4();
130 (*arr)[i++] = hregARM_R5();
131 (*arr)[i++] = hregARM_R6();
132 (*arr)[i++] = hregARM_R7();
133 (*arr)[i++] = hregARM_R10();
134 (*arr)[i++] = hregARM_R11();
135 // otherwise we'll have to slum it out with caller-saves ones
136 (*arr)[i++] = hregARM_R0();
137 (*arr)[i++] = hregARM_R1();
138 (*arr)[i++] = hregARM_R2();
139 (*arr)[i++] = hregARM_R3();
140 (*arr)[i++] = hregARM_R9();
141 // FP hreegisters. Note: these are all callee-save. Yay!
142 // Hence we don't need to mention them as trashed in
143 // getHRegUsage for ARMInstr_Call.
144 (*arr)[i++] = hregARM_D8();
145 (*arr)[i++] = hregARM_D9();
146 (*arr)[i++] = hregARM_D10();
147 (*arr)[i++] = hregARM_D11();
148 (*arr)[i++] = hregARM_D12();
149 (*arr)[i++] = hregARM_S26();
150 (*arr)[i++] = hregARM_S27();
151 (*arr)[i++] = hregARM_S28();
152 (*arr)[i++] = hregARM_S29();
153 (*arr)[i++] = hregARM_S30();
sewardj6c60b322010-08-22 12:48:28 +0000154
155 (*arr)[i++] = hregARM_Q8();
156 (*arr)[i++] = hregARM_Q9();
157 (*arr)[i++] = hregARM_Q10();
158 (*arr)[i++] = hregARM_Q11();
159 (*arr)[i++] = hregARM_Q12();
sewardjef9ef372010-08-31 09:32:40 +0000160
161 //(*arr)[i++] = hregARM_Q13();
162 //(*arr)[i++] = hregARM_Q14();
163 //(*arr)[i++] = hregARM_Q15();
sewardj6c60b322010-08-22 12:48:28 +0000164
sewardj6c299f32009-12-31 18:00:12 +0000165 // unavail: r8 as GSP
sewardje30973c2010-09-01 10:25:51 +0000166 // r12 is used as a spill/reload temporary
sewardj6c299f32009-12-31 18:00:12 +0000167 // r13 as SP
168 // r14 as LR
169 // r15 as PC
170 //
171 // All in all, we have 11 allocatable integer registers:
sewardje30973c2010-09-01 10:25:51 +0000172 // 0 1 2 3 4 5 6 7 9 10 11, with r8 dedicated as GSP
173 // and r12 dedicated as a spill temporary.
174 // 13 14 and 15 are not under the allocator's control.
sewardj6c299f32009-12-31 18:00:12 +0000175 //
176 // Hence for the allocatable registers we have:
177 //
178 // callee-saved: 4 5 6 7 (8) 9 10 11
179 // caller-saved: 0 1 2 3
180 // Note 9 is ambiguous: the base EABI does not give an e/r-saved
181 // designation for it, but the Linux instantiation of the ABI
182 // specifies it as callee-saved.
183 //
184 // If the set of available registers changes or if the e/r status
185 // changes, be sure to re-check/sync the definition of
186 // getHRegUsage for ARMInstr_Call too.
187 vassert(i == *nregs);
cerion82edbb32004-12-16 14:06:34 +0000188}
189
190
191
192/* --------- Condition codes, ARM encoding. --------- */
193
194HChar* showARMCondCode ( ARMCondCode cond ) {
195 switch (cond) {
sewardj6c299f32009-12-31 18:00:12 +0000196 case ARMcc_EQ: return "eq";
197 case ARMcc_NE: return "ne";
198 case ARMcc_HS: return "hs";
199 case ARMcc_LO: return "lo";
200 case ARMcc_MI: return "mi";
201 case ARMcc_PL: return "pl";
202 case ARMcc_VS: return "vs";
203 case ARMcc_VC: return "vc";
204 case ARMcc_HI: return "hi";
205 case ARMcc_LS: return "ls";
206 case ARMcc_GE: return "ge";
207 case ARMcc_LT: return "lt";
208 case ARMcc_GT: return "gt";
209 case ARMcc_LE: return "le";
210 case ARMcc_AL: return "al"; // default
211 case ARMcc_NV: return "nv";
cerion82edbb32004-12-16 14:06:34 +0000212 default: vpanic("showARMCondCode");
213 }
214}
215
216
sewardj6c299f32009-12-31 18:00:12 +0000217/* --------- Mem AModes: Addressing Mode 1 --------- */
cerioncee30312004-12-17 20:30:21 +0000218
sewardj6c299f32009-12-31 18:00:12 +0000219ARMAMode1* ARMAMode1_RI ( HReg reg, Int simm13 ) {
220 ARMAMode1* am = LibVEX_Alloc(sizeof(ARMAMode1));
221 am->tag = ARMam1_RI;
222 am->ARMam1.RI.reg = reg;
223 am->ARMam1.RI.simm13 = simm13;
224 vassert(-4095 <= simm13 && simm13 <= 4095);
225 return am;
cerion82edbb32004-12-16 14:06:34 +0000226}
sewardj6c299f32009-12-31 18:00:12 +0000227ARMAMode1* ARMAMode1_RRS ( HReg base, HReg index, UInt shift ) {
228 ARMAMode1* am = LibVEX_Alloc(sizeof(ARMAMode1));
229 am->tag = ARMam1_RRS;
230 am->ARMam1.RRS.base = base;
231 am->ARMam1.RRS.index = index;
232 am->ARMam1.RRS.shift = shift;
233 vassert(0 <= shift && shift <= 3);
234 return am;
cerion82edbb32004-12-16 14:06:34 +0000235}
236
237void ppARMAMode1 ( ARMAMode1* am ) {
238 switch (am->tag) {
sewardj6c299f32009-12-31 18:00:12 +0000239 case ARMam1_RI:
240 vex_printf("%d(", am->ARMam1.RI.simm13);
241 ppHRegARM(am->ARMam1.RI.reg);
242 vex_printf(")");
243 break;
244 case ARMam1_RRS:
245 vex_printf("(");
246 ppHRegARM(am->ARMam1.RRS.base);
247 vex_printf(",");
248 ppHRegARM(am->ARMam1.RRS.index);
249 vex_printf(",%u)", am->ARMam1.RRS.shift);
250 break;
251 default:
252 vassert(0);
cerion82edbb32004-12-16 14:06:34 +0000253 }
254}
255
cerion82edbb32004-12-16 14:06:34 +0000256static void addRegUsage_ARMAMode1 ( HRegUsage* u, ARMAMode1* am ) {
cerion82edbb32004-12-16 14:06:34 +0000257 switch (am->tag) {
sewardj6c299f32009-12-31 18:00:12 +0000258 case ARMam1_RI:
259 addHRegUse(u, HRmRead, am->ARMam1.RI.reg);
260 return;
261 case ARMam1_RRS:
262 // addHRegUse(u, HRmRead, am->ARMam1.RRS.base);
263 // addHRegUse(u, HRmRead, am->ARMam1.RRS.index);
264 // return;
265 default:
266 vpanic("addRegUsage_ARMAmode1");
cerion82edbb32004-12-16 14:06:34 +0000267 }
268}
269
sewardj6c299f32009-12-31 18:00:12 +0000270static void mapRegs_ARMAMode1 ( HRegRemap* m, ARMAMode1* am ) {
271 switch (am->tag) {
272 case ARMam1_RI:
273 am->ARMam1.RI.reg = lookupHRegRemap(m, am->ARMam1.RI.reg);
274 return;
275 case ARMam1_RRS:
276 //am->ARMam1.RR.base =lookupHRegRemap(m, am->ARMam1.RR.base);
277 //am->ARMam1.RR.index = lookupHRegRemap(m, am->ARMam1.RR.index);
278 //return;
279 default:
280 vpanic("mapRegs_ARMAmode1");
281 }
282}
283
284
285/* --------- Mem AModes: Addressing Mode 2 --------- */
286
287ARMAMode2* ARMAMode2_RI ( HReg reg, Int simm9 ) {
288 ARMAMode2* am = LibVEX_Alloc(sizeof(ARMAMode2));
289 am->tag = ARMam2_RI;
290 am->ARMam2.RI.reg = reg;
291 am->ARMam2.RI.simm9 = simm9;
292 vassert(-255 <= simm9 && simm9 <= 255);
293 return am;
294}
295ARMAMode2* ARMAMode2_RR ( HReg base, HReg index ) {
296 ARMAMode2* am = LibVEX_Alloc(sizeof(ARMAMode2));
297 am->tag = ARMam2_RR;
298 am->ARMam2.RR.base = base;
299 am->ARMam2.RR.index = index;
300 return am;
301}
302
cerion82edbb32004-12-16 14:06:34 +0000303void ppARMAMode2 ( ARMAMode2* am ) {
304 switch (am->tag) {
sewardj6c299f32009-12-31 18:00:12 +0000305 case ARMam2_RI:
306 vex_printf("%d(", am->ARMam2.RI.simm9);
307 ppHRegARM(am->ARMam2.RI.reg);
308 vex_printf(")");
309 break;
310 case ARMam2_RR:
311 vex_printf("(");
312 ppHRegARM(am->ARMam2.RR.base);
313 vex_printf(",");
314 ppHRegARM(am->ARMam2.RR.index);
315 vex_printf(")");
316 break;
317 default:
318 vassert(0);
cerion82edbb32004-12-16 14:06:34 +0000319 }
320}
321
sewardj6c299f32009-12-31 18:00:12 +0000322static void addRegUsage_ARMAMode2 ( HRegUsage* u, ARMAMode2* am ) {
cerion82edbb32004-12-16 14:06:34 +0000323 switch (am->tag) {
sewardj6c299f32009-12-31 18:00:12 +0000324 case ARMam2_RI:
325 addHRegUse(u, HRmRead, am->ARMam2.RI.reg);
326 return;
327 case ARMam2_RR:
328 // addHRegUse(u, HRmRead, am->ARMam2.RR.base);
329 // addHRegUse(u, HRmRead, am->ARMam2.RR.index);
330 // return;
331 default:
332 vpanic("addRegUsage_ARMAmode2");
cerion82edbb32004-12-16 14:06:34 +0000333 }
334}
335
cerion82edbb32004-12-16 14:06:34 +0000336static void mapRegs_ARMAMode2 ( HRegRemap* m, ARMAMode2* am ) {
sewardj6c299f32009-12-31 18:00:12 +0000337 switch (am->tag) {
338 case ARMam2_RI:
339 am->ARMam2.RI.reg = lookupHRegRemap(m, am->ARMam2.RI.reg);
340 return;
341 case ARMam2_RR:
342 //am->ARMam2.RR.base =lookupHRegRemap(m, am->ARMam2.RR.base);
343 //am->ARMam2.RR.index = lookupHRegRemap(m, am->ARMam2.RR.index);
344 //return;
345 default:
346 vpanic("mapRegs_ARMAmode2");
347 }
cerion82edbb32004-12-16 14:06:34 +0000348}
349
350
sewardj6c299f32009-12-31 18:00:12 +0000351/* --------- Mem AModes: Addressing Mode VFP --------- */
352
353ARMAModeV* mkARMAModeV ( HReg reg, Int simm11 ) {
354 ARMAModeV* am = LibVEX_Alloc(sizeof(ARMAModeV));
355 vassert(simm11 >= -1020 && simm11 <= 1020);
356 vassert(0 == (simm11 & 3));
357 am->reg = reg;
358 am->simm11 = simm11;
359 return am;
360}
361
362void ppARMAModeV ( ARMAModeV* am ) {
363 vex_printf("%d(", am->simm11);
364 ppHRegARM(am->reg);
365 vex_printf(")");
366}
367
368static void addRegUsage_ARMAModeV ( HRegUsage* u, ARMAModeV* am ) {
369 addHRegUse(u, HRmRead, am->reg);
370}
371
372static void mapRegs_ARMAModeV ( HRegRemap* m, ARMAModeV* am ) {
373 am->reg = lookupHRegRemap(m, am->reg);
374}
375
376
sewardj6c60b322010-08-22 12:48:28 +0000377/* --------- Mem AModes: Addressing Mode Neon ------- */
378
379ARMAModeN *mkARMAModeN_RR ( HReg rN, HReg rM ) {
380 ARMAModeN* am = LibVEX_Alloc(sizeof(ARMAModeN));
381 am->tag = ARMamN_RR;
382 am->ARMamN.RR.rN = rN;
383 am->ARMamN.RR.rM = rM;
384 return am;
385}
386
387ARMAModeN *mkARMAModeN_R ( HReg rN ) {
388 ARMAModeN* am = LibVEX_Alloc(sizeof(ARMAModeN));
389 am->tag = ARMamN_R;
390 am->ARMamN.R.rN = rN;
391 return am;
392}
393
394static void addRegUsage_ARMAModeN ( HRegUsage* u, ARMAModeN* am ) {
395 if (am->tag == ARMamN_R) {
396 addHRegUse(u, HRmRead, am->ARMamN.R.rN);
397 } else {
398 addHRegUse(u, HRmRead, am->ARMamN.RR.rN);
399 addHRegUse(u, HRmRead, am->ARMamN.RR.rM);
400 }
401}
402
403static void mapRegs_ARMAModeN ( HRegRemap* m, ARMAModeN* am ) {
404 if (am->tag == ARMamN_R) {
405 am->ARMamN.R.rN = lookupHRegRemap(m, am->ARMamN.R.rN);
406 } else {
407 am->ARMamN.RR.rN = lookupHRegRemap(m, am->ARMamN.RR.rN);
408 am->ARMamN.RR.rM = lookupHRegRemap(m, am->ARMamN.RR.rM);
409 }
410}
411
412void ppARMAModeN ( ARMAModeN* am ) {
413 vex_printf("[");
414 if (am->tag == ARMamN_R) {
415 ppHRegARM(am->ARMamN.R.rN);
416 } else {
417 ppHRegARM(am->ARMamN.RR.rN);
418 }
419 vex_printf("]");
420 if (am->tag == ARMamN_RR) {
421 vex_printf(", ");
422 ppHRegARM(am->ARMamN.RR.rM);
423 }
424}
425
426
sewardj6c299f32009-12-31 18:00:12 +0000427/* --------- Reg or imm-8x4 operands --------- */
428
429static UInt ROR32 ( UInt x, UInt sh ) {
430 vassert(sh >= 0 && sh < 32);
431 if (sh == 0)
432 return x;
433 else
434 return (x << (32-sh)) | (x >> sh);
435}
436
437ARMRI84* ARMRI84_I84 ( UShort imm8, UShort imm4 ) {
438 ARMRI84* ri84 = LibVEX_Alloc(sizeof(ARMRI84));
439 ri84->tag = ARMri84_I84;
440 ri84->ARMri84.I84.imm8 = imm8;
441 ri84->ARMri84.I84.imm4 = imm4;
442 vassert(imm8 >= 0 && imm8 <= 255);
443 vassert(imm4 >= 0 && imm4 <= 15);
444 return ri84;
445}
446ARMRI84* ARMRI84_R ( HReg reg ) {
447 ARMRI84* ri84 = LibVEX_Alloc(sizeof(ARMRI84));
448 ri84->tag = ARMri84_R;
449 ri84->ARMri84.R.reg = reg;
450 return ri84;
451}
452
453void ppARMRI84 ( ARMRI84* ri84 ) {
454 switch (ri84->tag) {
455 case ARMri84_I84:
456 vex_printf("0x%x", ROR32(ri84->ARMri84.I84.imm8,
457 2 * ri84->ARMri84.I84.imm4));
458 break;
459 case ARMri84_R:
460 ppHRegARM(ri84->ARMri84.R.reg);
461 break;
462 default:
463 vassert(0);
464 }
465}
466
467static void addRegUsage_ARMRI84 ( HRegUsage* u, ARMRI84* ri84 ) {
468 switch (ri84->tag) {
469 case ARMri84_I84:
470 return;
471 case ARMri84_R:
472 addHRegUse(u, HRmRead, ri84->ARMri84.R.reg);
473 return;
474 default:
475 vpanic("addRegUsage_ARMRI84");
476 }
477}
478
479static void mapRegs_ARMRI84 ( HRegRemap* m, ARMRI84* ri84 ) {
480 switch (ri84->tag) {
481 case ARMri84_I84:
482 return;
483 case ARMri84_R:
484 ri84->ARMri84.R.reg = lookupHRegRemap(m, ri84->ARMri84.R.reg);
485 return;
486 default:
487 vpanic("mapRegs_ARMRI84");
488 }
489}
490
491
492/* --------- Reg or imm5 operands --------- */
493
494ARMRI5* ARMRI5_I5 ( UInt imm5 ) {
495 ARMRI5* ri5 = LibVEX_Alloc(sizeof(ARMRI5));
496 ri5->tag = ARMri5_I5;
497 ri5->ARMri5.I5.imm5 = imm5;
498 vassert(imm5 > 0 && imm5 <= 31); // zero is not allowed
499 return ri5;
500}
501ARMRI5* ARMRI5_R ( HReg reg ) {
502 ARMRI5* ri5 = LibVEX_Alloc(sizeof(ARMRI5));
503 ri5->tag = ARMri5_R;
504 ri5->ARMri5.R.reg = reg;
505 return ri5;
506}
507
508void ppARMRI5 ( ARMRI5* ri5 ) {
509 switch (ri5->tag) {
510 case ARMri5_I5:
511 vex_printf("%u", ri5->ARMri5.I5.imm5);
512 break;
513 case ARMri5_R:
514 ppHRegARM(ri5->ARMri5.R.reg);
515 break;
516 default:
517 vassert(0);
518 }
519}
520
521static void addRegUsage_ARMRI5 ( HRegUsage* u, ARMRI5* ri5 ) {
522 switch (ri5->tag) {
523 case ARMri5_I5:
524 return;
525 case ARMri5_R:
526 addHRegUse(u, HRmRead, ri5->ARMri5.R.reg);
527 return;
528 default:
529 vpanic("addRegUsage_ARMRI5");
530 }
531}
532
533static void mapRegs_ARMRI5 ( HRegRemap* m, ARMRI5* ri5 ) {
534 switch (ri5->tag) {
535 case ARMri5_I5:
536 return;
537 case ARMri5_R:
538 ri5->ARMri5.R.reg = lookupHRegRemap(m, ri5->ARMri5.R.reg);
539 return;
540 default:
541 vpanic("mapRegs_ARMRI5");
542 }
543}
cerion82edbb32004-12-16 14:06:34 +0000544
sewardj6c60b322010-08-22 12:48:28 +0000545/* -------- Neon Immediate operatnd --------- */
546
547ARMNImm* ARMNImm_TI ( UInt type, UInt imm8 ) {
548 ARMNImm* i = LibVEX_Alloc(sizeof(ARMNImm));
549 i->type = type;
550 i->imm8 = imm8;
551 return i;
552}
553
554ULong ARMNImm_to_Imm64 ( ARMNImm* imm ) {
555 int i, j;
556 ULong y, x = imm->imm8;
557 switch (imm->type) {
558 case 3:
559 x = x << 8;
560 case 2:
561 x = x << 8;
562 case 1:
563 x = x << 8;
564 case 0:
565 return (x << 32) | x;
566 case 5:
567 case 6:
568 if (imm->type == 5)
569 x = x << 8;
570 else
571 x = (x << 8) | x;
572 case 4:
573 x = (x << 16) | x;
574 return (x << 32) | x;
575 case 8:
576 x = (x << 8) | 0xFF;
577 case 7:
578 x = (x << 8) | 0xFF;
579 return (x << 32) | x;
580 case 9:
581 x = 0;
582 for (i = 7; i >= 0; i--) {
583 y = ((ULong)imm->imm8 >> i) & 1;
584 for (j = 0; j < 8; j++) {
585 x = (x << 1) | y;
586 }
587 }
588 return x;
589 case 10:
590 x |= (x & 0x80) << 5;
591 x |= ~(x & 0x40) << 5;
592 x &= 0x187F; /* 0001 1000 0111 1111 */
593 x |= (x & 0x40) << 4;
594 x |= (x & 0x40) << 3;
595 x |= (x & 0x40) << 2;
596 x |= (x & 0x40) << 1;
597 x = x << 19;
598 x = (x << 32) | x;
599 return x;
600 default:
601 vpanic("ARMNImm_to_Imm64");
602 }
603}
604
605ARMNImm* Imm64_to_ARMNImm ( ULong x ) {
606 ARMNImm tmp;
607 if ((x & 0xFFFFFFFF) == (x >> 32)) {
608 if ((x & 0xFFFFFF00) == 0)
609 return ARMNImm_TI(0, x & 0xFF);
610 if ((x & 0xFFFF00FF) == 0)
611 return ARMNImm_TI(1, (x >> 8) & 0xFF);
612 if ((x & 0xFF00FFFF) == 0)
613 return ARMNImm_TI(2, (x >> 16) & 0xFF);
614 if ((x & 0x00FFFFFF) == 0)
615 return ARMNImm_TI(3, (x >> 24) & 0xFF);
616 if ((x & 0xFFFF00FF) == 0xFF)
617 return ARMNImm_TI(7, (x >> 8) & 0xFF);
618 if ((x & 0xFF00FFFF) == 0xFFFF)
619 return ARMNImm_TI(8, (x >> 16) & 0xFF);
620 if ((x & 0xFFFF) == ((x >> 16) & 0xFFFF)) {
621 if ((x & 0xFF00) == 0)
622 return ARMNImm_TI(4, x & 0xFF);
623 if ((x & 0x00FF) == 0)
624 return ARMNImm_TI(5, (x >> 8) & 0xFF);
625 if ((x & 0xFF) == ((x >> 8) & 0xFF))
626 return ARMNImm_TI(6, x & 0xFF);
627 }
628 if ((x & 0x7FFFF) == 0) {
629 tmp.type = 10;
630 tmp.imm8 = ((x >> 19) & 0x7F) | ((x >> 24) & 0x80);
631 if (ARMNImm_to_Imm64(&tmp) == x)
632 return ARMNImm_TI(tmp.type, tmp.imm8);
633 }
634 } else {
635 /* This can only be type 9. */
636 tmp.imm8 = (((x >> 56) & 1) << 7)
637 | (((x >> 48) & 1) << 6)
638 | (((x >> 40) & 1) << 5)
639 | (((x >> 32) & 1) << 4)
640 | (((x >> 24) & 1) << 3)
641 | (((x >> 16) & 1) << 2)
642 | (((x >> 8) & 1) << 1)
643 | (((x >> 0) & 1) << 0);
644 tmp.type = 9;
645 if (ARMNImm_to_Imm64 (&tmp) == x)
646 return ARMNImm_TI(tmp.type, tmp.imm8);
647 }
648 return NULL;
649}
650
651void ppARMNImm (ARMNImm* i) {
652 ULong x = ARMNImm_to_Imm64(i);
653 vex_printf("0x%llX%llX", x, x);
654}
655
656/* -- Register or scalar operand --- */
657
658ARMNRS* mkARMNRS(ARMNRS_tag tag, HReg reg, UInt index)
659{
660 ARMNRS *p = LibVEX_Alloc(sizeof(ARMNRS));
661 p->tag = tag;
662 p->reg = reg;
663 p->index = index;
664 return p;
665}
666
667void ppARMNRS(ARMNRS *p)
668{
669 ppHRegARM(p->reg);
670 if (p->tag == ARMNRS_Scalar) {
671 vex_printf("[%d]", p->index);
672 }
673}
cerion82edbb32004-12-16 14:06:34 +0000674
675/* --------- Instructions. --------- */
676
677HChar* showARMAluOp ( ARMAluOp op ) {
sewardj6c299f32009-12-31 18:00:12 +0000678 switch (op) {
679 case ARMalu_ADD: return "add";
680 case ARMalu_ADDS: return "adds";
681 case ARMalu_ADC: return "adc";
682 case ARMalu_SUB: return "sub";
683 case ARMalu_SUBS: return "subs";
684 case ARMalu_SBC: return "sbc";
685 case ARMalu_AND: return "and";
686 case ARMalu_BIC: return "bic";
687 case ARMalu_OR: return "orr";
688 case ARMalu_XOR: return "xor";
689 default: vpanic("showARMAluOp");
690 }
cerion82edbb32004-12-16 14:06:34 +0000691}
692
sewardj6c299f32009-12-31 18:00:12 +0000693HChar* showARMShiftOp ( ARMShiftOp op ) {
694 switch (op) {
695 case ARMsh_SHL: return "shl";
696 case ARMsh_SHR: return "shr";
697 case ARMsh_SAR: return "sar";
698 default: vpanic("showARMShiftOp");
699 }
cerion82edbb32004-12-16 14:06:34 +0000700}
701
sewardj6c299f32009-12-31 18:00:12 +0000702HChar* showARMUnaryOp ( ARMUnaryOp op ) {
703 switch (op) {
704 case ARMun_NEG: return "neg";
705 case ARMun_NOT: return "not";
706 case ARMun_CLZ: return "clz";
707 default: vpanic("showARMUnaryOp");
708 }
cerion82edbb32004-12-16 14:06:34 +0000709}
710
sewardj6c299f32009-12-31 18:00:12 +0000711HChar* showARMMulOp ( ARMMulOp op ) {
712 switch (op) {
713 case ARMmul_PLAIN: return "mul";
714 case ARMmul_ZX: return "umull";
715 case ARMmul_SX: return "smull";
716 default: vpanic("showARMMulOp");
717 }
cerion82edbb32004-12-16 14:06:34 +0000718}
719
sewardj6c299f32009-12-31 18:00:12 +0000720HChar* showARMVfpOp ( ARMVfpOp op ) {
721 switch (op) {
722 case ARMvfp_ADD: return "add";
723 case ARMvfp_SUB: return "sub";
724 case ARMvfp_MUL: return "mul";
725 case ARMvfp_DIV: return "div";
726 default: vpanic("showARMVfpOp");
727 }
cerion82edbb32004-12-16 14:06:34 +0000728}
729
sewardj6c299f32009-12-31 18:00:12 +0000730HChar* showARMVfpUnaryOp ( ARMVfpUnaryOp op ) {
731 switch (op) {
732 case ARMvfpu_COPY: return "cpy";
733 case ARMvfpu_NEG: return "neg";
734 case ARMvfpu_ABS: return "abs";
735 case ARMvfpu_SQRT: return "sqrt";
736 default: vpanic("showARMVfpUnaryOp");
737 }
cerion82edbb32004-12-16 14:06:34 +0000738}
739
sewardj6c60b322010-08-22 12:48:28 +0000740HChar* showARMNeonBinOp ( ARMNeonBinOp op ) {
741 switch (op) {
742 case ARMneon_VAND: return "vand";
743 case ARMneon_VORR: return "vorr";
744 case ARMneon_VXOR: return "veor";
745 case ARMneon_VADD: return "vadd";
746 case ARMneon_VRHADDS: return "vrhadd";
747 case ARMneon_VRHADDU: return "vrhadd";
748 case ARMneon_VADDFP: return "vadd";
749 case ARMneon_VPADDFP: return "vpadd";
750 case ARMneon_VABDFP: return "vabd";
751 case ARMneon_VSUB: return "vsub";
752 case ARMneon_VSUBFP: return "vsub";
753 case ARMneon_VMINU: return "vmin";
754 case ARMneon_VMINS: return "vmin";
755 case ARMneon_VMINF: return "vmin";
756 case ARMneon_VMAXU: return "vmax";
757 case ARMneon_VMAXS: return "vmax";
758 case ARMneon_VMAXF: return "vmax";
759 case ARMneon_VQADDU: return "vqadd";
760 case ARMneon_VQADDS: return "vqadd";
761 case ARMneon_VQSUBU: return "vqsub";
762 case ARMneon_VQSUBS: return "vqsub";
763 case ARMneon_VCGTU: return "vcgt";
764 case ARMneon_VCGTS: return "vcgt";
765 case ARMneon_VCGTF: return "vcgt";
766 case ARMneon_VCGEF: return "vcgt";
767 case ARMneon_VCGEU: return "vcge";
768 case ARMneon_VCGES: return "vcge";
769 case ARMneon_VCEQ: return "vceq";
770 case ARMneon_VCEQF: return "vceq";
771 case ARMneon_VPADD: return "vpadd";
772 case ARMneon_VPMINU: return "vpmin";
773 case ARMneon_VPMINS: return "vpmin";
774 case ARMneon_VPMINF: return "vpmin";
775 case ARMneon_VPMAXU: return "vpmax";
776 case ARMneon_VPMAXS: return "vpmax";
777 case ARMneon_VPMAXF: return "vpmax";
778 case ARMneon_VEXT: return "vext";
779 case ARMneon_VMUL: return "vmuli";
780 case ARMneon_VMULLU: return "vmull";
781 case ARMneon_VMULLS: return "vmull";
782 case ARMneon_VMULP: return "vmul";
783 case ARMneon_VMULFP: return "vmul";
784 case ARMneon_VMULLP: return "vmul";
785 case ARMneon_VQDMULH: return "vqdmulh";
786 case ARMneon_VQRDMULH: return "vqrdmulh";
787 case ARMneon_VQDMULL: return "vqdmull";
788 case ARMneon_VTBL: return "vtbl";
sewardj6aa87a62010-10-06 20:34:53 +0000789 case ARMneon_VRECPS: return "vrecps";
790 case ARMneon_VRSQRTS: return "vrecps";
sewardj6c60b322010-08-22 12:48:28 +0000791 /* ... */
792 default: vpanic("showARMNeonBinOp");
793 }
794}
795
796HChar* showARMNeonBinOpDataType ( ARMNeonBinOp op ) {
797 switch (op) {
798 case ARMneon_VAND:
799 case ARMneon_VORR:
800 case ARMneon_VXOR:
801 return "";
802 case ARMneon_VADD:
803 case ARMneon_VSUB:
804 case ARMneon_VEXT:
805 case ARMneon_VMUL:
sewardj6c60b322010-08-22 12:48:28 +0000806 case ARMneon_VPADD:
807 case ARMneon_VTBL:
808 case ARMneon_VCEQ:
809 return ".i";
810 case ARMneon_VRHADDU:
811 case ARMneon_VMINU:
812 case ARMneon_VMAXU:
813 case ARMneon_VQADDU:
814 case ARMneon_VQSUBU:
815 case ARMneon_VCGTU:
816 case ARMneon_VCGEU:
817 case ARMneon_VMULLU:
818 case ARMneon_VPMINU:
819 case ARMneon_VPMAXU:
sewardj6c60b322010-08-22 12:48:28 +0000820 return ".u";
821 case ARMneon_VRHADDS:
822 case ARMneon_VMINS:
823 case ARMneon_VMAXS:
824 case ARMneon_VQADDS:
825 case ARMneon_VQSUBS:
826 case ARMneon_VCGTS:
827 case ARMneon_VCGES:
828 case ARMneon_VQDMULL:
829 case ARMneon_VMULLS:
830 case ARMneon_VPMINS:
831 case ARMneon_VPMAXS:
832 case ARMneon_VQDMULH:
833 case ARMneon_VQRDMULH:
834 return ".s";
835 case ARMneon_VMULP:
836 case ARMneon_VMULLP:
837 return ".p";
838 case ARMneon_VADDFP:
839 case ARMneon_VABDFP:
840 case ARMneon_VPADDFP:
841 case ARMneon_VSUBFP:
842 case ARMneon_VMULFP:
843 case ARMneon_VMINF:
844 case ARMneon_VMAXF:
sewardj6c60b322010-08-22 12:48:28 +0000845 case ARMneon_VPMINF:
846 case ARMneon_VPMAXF:
847 case ARMneon_VCGTF:
848 case ARMneon_VCGEF:
849 case ARMneon_VCEQF:
sewardj6aa87a62010-10-06 20:34:53 +0000850 case ARMneon_VRECPS:
851 case ARMneon_VRSQRTS:
sewardj6c60b322010-08-22 12:48:28 +0000852 return ".f";
853 /* ... */
854 default: vpanic("showARMNeonBinOpDataType");
855 }
856}
857
858HChar* showARMNeonUnOp ( ARMNeonUnOp op ) {
859 switch (op) {
860 case ARMneon_COPY: return "vmov";
861 case ARMneon_COPYLS: return "vmov";
862 case ARMneon_COPYLU: return "vmov";
863 case ARMneon_COPYN: return "vmov";
864 case ARMneon_COPYQNSS: return "vqmovn";
865 case ARMneon_COPYQNUS: return "vqmovun";
866 case ARMneon_COPYQNUU: return "vqmovn";
867 case ARMneon_NOT: return "vmvn";
868 case ARMneon_EQZ: return "vceq";
869 case ARMneon_CNT: return "vcnt";
870 case ARMneon_CLS: return "vcls";
871 case ARMneon_CLZ: return "vclz";
872 case ARMneon_DUP: return "vdup";
873 case ARMneon_PADDLS: return "vpaddl";
874 case ARMneon_PADDLU: return "vpaddl";
875 case ARMneon_VQSHLNSS: return "vqshl";
876 case ARMneon_VQSHLNUU: return "vqshl";
877 case ARMneon_VQSHLNUS: return "vqshlu";
878 case ARMneon_REV16: return "vrev16";
879 case ARMneon_REV32: return "vrev32";
880 case ARMneon_REV64: return "vrev64";
881 case ARMneon_VCVTFtoU: return "vcvt";
882 case ARMneon_VCVTFtoS: return "vcvt";
883 case ARMneon_VCVTUtoF: return "vcvt";
884 case ARMneon_VCVTStoF: return "vcvt";
885 case ARMneon_VCVTFtoFixedU: return "vcvt";
886 case ARMneon_VCVTFtoFixedS: return "vcvt";
887 case ARMneon_VCVTFixedUtoF: return "vcvt";
888 case ARMneon_VCVTFixedStoF: return "vcvt";
889 case ARMneon_VCVTF32toF16: return "vcvt";
890 case ARMneon_VCVTF16toF32: return "vcvt";
891 case ARMneon_VRECIP: return "vrecip";
892 case ARMneon_VRECIPF: return "vrecipf";
sewardj6c60b322010-08-22 12:48:28 +0000893 case ARMneon_VNEGF: return "vneg";
sewardj6c60b322010-08-22 12:48:28 +0000894 case ARMneon_ABS: return "vabs";
sewardj6aa87a62010-10-06 20:34:53 +0000895 case ARMneon_VABSFP: return "vabsfp";
896 case ARMneon_VRSQRTEFP: return "vrsqrtefp";
897 case ARMneon_VRSQRTE: return "vrsqrte";
sewardj6c60b322010-08-22 12:48:28 +0000898 /* ... */
899 default: vpanic("showARMNeonUnOp");
900 }
901}
902
903HChar* showARMNeonUnOpDataType ( ARMNeonUnOp op ) {
904 switch (op) {
905 case ARMneon_COPY:
906 case ARMneon_NOT:
907 return "";
908 case ARMneon_COPYN:
909 case ARMneon_EQZ:
910 case ARMneon_CNT:
911 case ARMneon_DUP:
912 case ARMneon_REV16:
913 case ARMneon_REV32:
914 case ARMneon_REV64:
915 return ".i";
916 case ARMneon_COPYLU:
917 case ARMneon_PADDLU:
918 case ARMneon_COPYQNUU:
919 case ARMneon_VQSHLNUU:
920 case ARMneon_VRECIP:
sewardj6aa87a62010-10-06 20:34:53 +0000921 case ARMneon_VRSQRTE:
sewardj6c60b322010-08-22 12:48:28 +0000922 return ".u";
923 case ARMneon_CLS:
924 case ARMneon_CLZ:
925 case ARMneon_COPYLS:
926 case ARMneon_PADDLS:
927 case ARMneon_COPYQNSS:
928 case ARMneon_COPYQNUS:
929 case ARMneon_VQSHLNSS:
930 case ARMneon_VQSHLNUS:
931 case ARMneon_ABS:
932 return ".s";
933 case ARMneon_VRECIPF:
sewardj6c60b322010-08-22 12:48:28 +0000934 case ARMneon_VNEGF:
sewardj6aa87a62010-10-06 20:34:53 +0000935 case ARMneon_VABSFP:
936 case ARMneon_VRSQRTEFP:
sewardj6c60b322010-08-22 12:48:28 +0000937 return ".f";
938 case ARMneon_VCVTFtoU: return ".u32.f32";
939 case ARMneon_VCVTFtoS: return ".s32.f32";
940 case ARMneon_VCVTUtoF: return ".f32.u32";
941 case ARMneon_VCVTStoF: return ".f32.s32";
942 case ARMneon_VCVTF16toF32: return ".f32.f16";
943 case ARMneon_VCVTF32toF16: return ".f16.f32";
944 case ARMneon_VCVTFtoFixedU: return ".u32.f32";
945 case ARMneon_VCVTFtoFixedS: return ".s32.f32";
946 case ARMneon_VCVTFixedUtoF: return ".f32.u32";
947 case ARMneon_VCVTFixedStoF: return ".f32.s32";
948 /* ... */
949 default: vpanic("showARMNeonUnOpDataType");
950 }
951}
952
953HChar* showARMNeonUnOpS ( ARMNeonUnOpS op ) {
954 switch (op) {
955 case ARMneon_SETELEM: return "vmov";
956 case ARMneon_GETELEMU: return "vmov";
957 case ARMneon_GETELEMS: return "vmov";
958 case ARMneon_VDUP: return "vdup";
959 /* ... */
960 default: vpanic("showARMNeonUnarySOp");
961 }
962}
963
964HChar* showARMNeonUnOpSDataType ( ARMNeonUnOpS op ) {
965 switch (op) {
966 case ARMneon_SETELEM:
967 case ARMneon_VDUP:
968 return ".i";
969 case ARMneon_GETELEMS:
970 return ".s";
971 case ARMneon_GETELEMU:
972 return ".u";
973 /* ... */
974 default: vpanic("showARMNeonUnarySOp");
975 }
976}
977
978HChar* showARMNeonShiftOp ( ARMNeonShiftOp op ) {
979 switch (op) {
980 case ARMneon_VSHL: return "vshl";
981 case ARMneon_VSAL: return "vshl";
982 case ARMneon_VQSHL: return "vqshl";
983 case ARMneon_VQSAL: return "vqshl";
984 /* ... */
985 default: vpanic("showARMNeonShiftOp");
986 }
987}
988
989HChar* showARMNeonShiftOpDataType ( ARMNeonShiftOp op ) {
990 switch (op) {
991 case ARMneon_VSHL:
992 case ARMneon_VQSHL:
993 return ".u";
994 case ARMneon_VSAL:
995 case ARMneon_VQSAL:
996 return ".s";
997 /* ... */
998 default: vpanic("showARMNeonShiftOpDataType");
999 }
1000}
1001
1002HChar* showARMNeonDualOp ( ARMNeonDualOp op ) {
1003 switch (op) {
1004 case ARMneon_TRN: return "vtrn";
1005 case ARMneon_ZIP: return "vzip";
1006 case ARMneon_UZP: return "vuzp";
1007 /* ... */
1008 default: vpanic("showARMNeonDualOp");
1009 }
1010}
1011
1012HChar* showARMNeonDualOpDataType ( ARMNeonDualOp op ) {
1013 switch (op) {
1014 case ARMneon_TRN:
1015 case ARMneon_ZIP:
1016 case ARMneon_UZP:
1017 return "i";
1018 /* ... */
1019 default: vpanic("showARMNeonDualOp");
1020 }
1021}
1022
1023static HChar* showARMNeonDataSize_wrk ( UInt size )
1024{
1025 switch (size) {
1026 case 0: return "8";
1027 case 1: return "16";
1028 case 2: return "32";
1029 case 3: return "64";
1030 default: vpanic("showARMNeonDataSize");
1031 }
1032}
1033
1034static HChar* showARMNeonDataSize ( ARMInstr* i )
1035{
1036 switch (i->tag) {
1037 case ARMin_NBinary:
1038 if (i->ARMin.NBinary.op == ARMneon_VEXT)
1039 return "8";
1040 if (i->ARMin.NBinary.op == ARMneon_VAND ||
1041 i->ARMin.NBinary.op == ARMneon_VORR ||
1042 i->ARMin.NBinary.op == ARMneon_VXOR)
1043 return "";
1044 return showARMNeonDataSize_wrk(i->ARMin.NBinary.size);
1045 case ARMin_NUnary:
1046 if (i->ARMin.NUnary.op == ARMneon_COPY ||
1047 i->ARMin.NUnary.op == ARMneon_NOT ||
1048 i->ARMin.NUnary.op == ARMneon_VCVTF32toF16||
1049 i->ARMin.NUnary.op == ARMneon_VCVTF16toF32||
1050 i->ARMin.NUnary.op == ARMneon_VCVTFtoFixedS ||
1051 i->ARMin.NUnary.op == ARMneon_VCVTFtoFixedU ||
1052 i->ARMin.NUnary.op == ARMneon_VCVTFixedStoF ||
1053 i->ARMin.NUnary.op == ARMneon_VCVTFixedUtoF ||
1054 i->ARMin.NUnary.op == ARMneon_VCVTFtoS ||
1055 i->ARMin.NUnary.op == ARMneon_VCVTFtoU ||
1056 i->ARMin.NUnary.op == ARMneon_VCVTStoF ||
1057 i->ARMin.NUnary.op == ARMneon_VCVTUtoF)
1058 return "";
1059 if (i->ARMin.NUnary.op == ARMneon_VQSHLNSS ||
1060 i->ARMin.NUnary.op == ARMneon_VQSHLNUU ||
1061 i->ARMin.NUnary.op == ARMneon_VQSHLNUS) {
1062 UInt size;
1063 size = i->ARMin.NUnary.size;
1064 if (size & 0x40)
1065 return "64";
1066 if (size & 0x20)
1067 return "32";
1068 if (size & 0x10)
1069 return "16";
1070 if (size & 0x08)
1071 return "8";
1072 vpanic("showARMNeonDataSize");
1073 }
1074 return showARMNeonDataSize_wrk(i->ARMin.NUnary.size);
1075 case ARMin_NUnaryS:
1076 if (i->ARMin.NUnaryS.op == ARMneon_VDUP) {
1077 int size;
1078 size = i->ARMin.NUnaryS.size;
1079 if ((size & 1) == 1)
1080 return "8";
1081 if ((size & 3) == 2)
1082 return "16";
1083 if ((size & 7) == 4)
1084 return "32";
1085 vpanic("showARMNeonDataSize");
1086 }
1087 return showARMNeonDataSize_wrk(i->ARMin.NUnaryS.size);
1088 case ARMin_NShift:
1089 return showARMNeonDataSize_wrk(i->ARMin.NShift.size);
1090 case ARMin_NDual:
1091 return showARMNeonDataSize_wrk(i->ARMin.NDual.size);
1092 default:
1093 vpanic("showARMNeonDataSize");
1094 }
1095}
1096
sewardj6c299f32009-12-31 18:00:12 +00001097ARMInstr* ARMInstr_Alu ( ARMAluOp op,
1098 HReg dst, HReg argL, ARMRI84* argR ) {
1099 ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
1100 i->tag = ARMin_Alu;
1101 i->ARMin.Alu.op = op;
1102 i->ARMin.Alu.dst = dst;
1103 i->ARMin.Alu.argL = argL;
1104 i->ARMin.Alu.argR = argR;
1105 return i;
cerion82edbb32004-12-16 14:06:34 +00001106}
sewardj6c299f32009-12-31 18:00:12 +00001107ARMInstr* ARMInstr_Shift ( ARMShiftOp op,
1108 HReg dst, HReg argL, ARMRI5* argR ) {
1109 ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
1110 i->tag = ARMin_Shift;
1111 i->ARMin.Shift.op = op;
1112 i->ARMin.Shift.dst = dst;
1113 i->ARMin.Shift.argL = argL;
1114 i->ARMin.Shift.argR = argR;
1115 return i;
cerion82edbb32004-12-16 14:06:34 +00001116}
sewardj6c299f32009-12-31 18:00:12 +00001117ARMInstr* ARMInstr_Unary ( ARMUnaryOp op, HReg dst, HReg src ) {
1118 ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
1119 i->tag = ARMin_Unary;
1120 i->ARMin.Unary.op = op;
1121 i->ARMin.Unary.dst = dst;
1122 i->ARMin.Unary.src = src;
1123 return i;
cerion82edbb32004-12-16 14:06:34 +00001124}
sewardj6c299f32009-12-31 18:00:12 +00001125ARMInstr* ARMInstr_CmpOrTst ( Bool isCmp, HReg argL, ARMRI84* argR ) {
1126 ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
1127 i->tag = ARMin_CmpOrTst;
1128 i->ARMin.CmpOrTst.isCmp = isCmp;
1129 i->ARMin.CmpOrTst.argL = argL;
1130 i->ARMin.CmpOrTst.argR = argR;
1131 return i;
cerion82edbb32004-12-16 14:06:34 +00001132}
sewardj6c299f32009-12-31 18:00:12 +00001133ARMInstr* ARMInstr_Mov ( HReg dst, ARMRI84* src ) {
1134 ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
1135 i->tag = ARMin_Mov;
1136 i->ARMin.Mov.dst = dst;
1137 i->ARMin.Mov.src = src;
1138 return i;
cerion82edbb32004-12-16 14:06:34 +00001139}
sewardj6c299f32009-12-31 18:00:12 +00001140ARMInstr* ARMInstr_Imm32 ( HReg dst, UInt imm32 ) {
1141 ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
1142 i->tag = ARMin_Imm32;
1143 i->ARMin.Imm32.dst = dst;
1144 i->ARMin.Imm32.imm32 = imm32;
1145 return i;
cerion82edbb32004-12-16 14:06:34 +00001146}
sewardj6c299f32009-12-31 18:00:12 +00001147ARMInstr* ARMInstr_LdSt32 ( Bool isLoad, HReg rD, ARMAMode1* amode ) {
1148 ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
1149 i->tag = ARMin_LdSt32;
1150 i->ARMin.LdSt32.isLoad = isLoad;
1151 i->ARMin.LdSt32.rD = rD;
1152 i->ARMin.LdSt32.amode = amode;
1153 return i;
cerion82edbb32004-12-16 14:06:34 +00001154}
sewardj6c299f32009-12-31 18:00:12 +00001155ARMInstr* ARMInstr_LdSt16 ( Bool isLoad, Bool signedLoad,
1156 HReg rD, ARMAMode2* amode ) {
1157 ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
1158 i->tag = ARMin_LdSt16;
1159 i->ARMin.LdSt16.isLoad = isLoad;
1160 i->ARMin.LdSt16.signedLoad = signedLoad;
1161 i->ARMin.LdSt16.rD = rD;
1162 i->ARMin.LdSt16.amode = amode;
1163 return i;
cerion82edbb32004-12-16 14:06:34 +00001164}
sewardj6c299f32009-12-31 18:00:12 +00001165ARMInstr* ARMInstr_LdSt8U ( Bool isLoad, HReg rD, ARMAMode1* amode ) {
1166 ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
1167 i->tag = ARMin_LdSt8U;
1168 i->ARMin.LdSt8U.isLoad = isLoad;
1169 i->ARMin.LdSt8U.rD = rD;
1170 i->ARMin.LdSt8U.amode = amode;
1171 return i;
cerion82edbb32004-12-16 14:06:34 +00001172}
sewardj6c299f32009-12-31 18:00:12 +00001173//extern ARMInstr* ARMInstr_Ld8S ( HReg, ARMAMode2* );
1174ARMInstr* ARMInstr_Goto ( IRJumpKind jk, ARMCondCode cond, HReg gnext ) {
1175 ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
1176 i->tag = ARMin_Goto;
1177 i->ARMin.Goto.jk = jk;
1178 i->ARMin.Goto.cond = cond;
1179 i->ARMin.Goto.gnext = gnext;
1180 return i;
1181}
1182ARMInstr* ARMInstr_CMov ( ARMCondCode cond, HReg dst, ARMRI84* src ) {
1183 ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
1184 i->tag = ARMin_CMov;
1185 i->ARMin.CMov.cond = cond;
1186 i->ARMin.CMov.dst = dst;
1187 i->ARMin.CMov.src = src;
1188 vassert(cond != ARMcc_AL);
1189 return i;
1190}
1191ARMInstr* ARMInstr_Call ( ARMCondCode cond, HWord target, Int nArgRegs ) {
1192 ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
1193 i->tag = ARMin_Call;
1194 i->ARMin.Call.cond = cond;
1195 i->ARMin.Call.target = target;
1196 i->ARMin.Call.nArgRegs = nArgRegs;
1197 return i;
1198}
1199ARMInstr* ARMInstr_Mul ( ARMMulOp op ) {
1200 ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
1201 i->tag = ARMin_Mul;
1202 i->ARMin.Mul.op = op;
1203 return i;
1204}
1205ARMInstr* ARMInstr_LdrEX ( Int szB ) {
1206 ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
1207 i->tag = ARMin_LdrEX;
1208 i->ARMin.LdrEX.szB = szB;
1209 vassert(szB == 4 || szB == 1);
1210 return i;
1211}
1212ARMInstr* ARMInstr_StrEX ( Int szB ) {
1213 ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
1214 i->tag = ARMin_StrEX;
1215 i->ARMin.StrEX.szB = szB;
1216 vassert(szB == 4 || szB == 1);
1217 return i;
1218}
1219ARMInstr* ARMInstr_VLdStD ( Bool isLoad, HReg dD, ARMAModeV* am ) {
1220 ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
1221 i->tag = ARMin_VLdStD;
1222 i->ARMin.VLdStD.isLoad = isLoad;
1223 i->ARMin.VLdStD.dD = dD;
1224 i->ARMin.VLdStD.amode = am;
1225 return i;
1226}
1227ARMInstr* ARMInstr_VLdStS ( Bool isLoad, HReg fD, ARMAModeV* am ) {
1228 ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
1229 i->tag = ARMin_VLdStS;
1230 i->ARMin.VLdStS.isLoad = isLoad;
1231 i->ARMin.VLdStS.fD = fD;
1232 i->ARMin.VLdStS.amode = am;
1233 return i;
1234}
1235ARMInstr* ARMInstr_VAluD ( ARMVfpOp op, HReg dst, HReg argL, HReg argR ) {
1236 ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
1237 i->tag = ARMin_VAluD;
1238 i->ARMin.VAluD.op = op;
1239 i->ARMin.VAluD.dst = dst;
1240 i->ARMin.VAluD.argL = argL;
1241 i->ARMin.VAluD.argR = argR;
1242 return i;
1243}
1244ARMInstr* ARMInstr_VAluS ( ARMVfpOp op, HReg dst, HReg argL, HReg argR ) {
1245 ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
1246 i->tag = ARMin_VAluS;
1247 i->ARMin.VAluS.op = op;
1248 i->ARMin.VAluS.dst = dst;
1249 i->ARMin.VAluS.argL = argL;
1250 i->ARMin.VAluS.argR = argR;
1251 return i;
1252}
1253ARMInstr* ARMInstr_VUnaryD ( ARMVfpUnaryOp op, HReg dst, HReg src ) {
1254 ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
1255 i->tag = ARMin_VUnaryD;
1256 i->ARMin.VUnaryD.op = op;
1257 i->ARMin.VUnaryD.dst = dst;
1258 i->ARMin.VUnaryD.src = src;
1259 return i;
1260}
1261ARMInstr* ARMInstr_VUnaryS ( ARMVfpUnaryOp op, HReg dst, HReg src ) {
1262 ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
1263 i->tag = ARMin_VUnaryS;
1264 i->ARMin.VUnaryS.op = op;
1265 i->ARMin.VUnaryS.dst = dst;
1266 i->ARMin.VUnaryS.src = src;
1267 return i;
1268}
1269ARMInstr* ARMInstr_VCmpD ( HReg argL, HReg argR ) {
1270 ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
1271 i->tag = ARMin_VCmpD;
1272 i->ARMin.VCmpD.argL = argL;
1273 i->ARMin.VCmpD.argR = argR;
1274 return i;
1275}
1276ARMInstr* ARMInstr_VCMovD ( ARMCondCode cond, HReg dst, HReg src ) {
1277 ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
1278 i->tag = ARMin_VCMovD;
1279 i->ARMin.VCMovD.cond = cond;
1280 i->ARMin.VCMovD.dst = dst;
1281 i->ARMin.VCMovD.src = src;
1282 vassert(cond != ARMcc_AL);
1283 return i;
1284}
1285ARMInstr* ARMInstr_VCMovS ( ARMCondCode cond, HReg dst, HReg src ) {
1286 ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
1287 i->tag = ARMin_VCMovS;
1288 i->ARMin.VCMovS.cond = cond;
1289 i->ARMin.VCMovS.dst = dst;
1290 i->ARMin.VCMovS.src = src;
1291 vassert(cond != ARMcc_AL);
1292 return i;
1293}
1294ARMInstr* ARMInstr_VCvtSD ( Bool sToD, HReg dst, HReg src ) {
1295 ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
1296 i->tag = ARMin_VCvtSD;
1297 i->ARMin.VCvtSD.sToD = sToD;
1298 i->ARMin.VCvtSD.dst = dst;
1299 i->ARMin.VCvtSD.src = src;
1300 return i;
1301}
1302ARMInstr* ARMInstr_VXferD ( Bool toD, HReg dD, HReg rHi, HReg rLo ) {
1303 ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
1304 i->tag = ARMin_VXferD;
1305 i->ARMin.VXferD.toD = toD;
1306 i->ARMin.VXferD.dD = dD;
1307 i->ARMin.VXferD.rHi = rHi;
1308 i->ARMin.VXferD.rLo = rLo;
1309 return i;
1310}
1311ARMInstr* ARMInstr_VXferS ( Bool toS, HReg fD, HReg rLo ) {
1312 ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
1313 i->tag = ARMin_VXferS;
1314 i->ARMin.VXferS.toS = toS;
1315 i->ARMin.VXferS.fD = fD;
1316 i->ARMin.VXferS.rLo = rLo;
1317 return i;
1318}
1319ARMInstr* ARMInstr_VCvtID ( Bool iToD, Bool syned,
1320 HReg dst, HReg src ) {
1321 ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
1322 i->tag = ARMin_VCvtID;
1323 i->ARMin.VCvtID.iToD = iToD;
1324 i->ARMin.VCvtID.syned = syned;
1325 i->ARMin.VCvtID.dst = dst;
1326 i->ARMin.VCvtID.src = src;
1327 return i;
1328}
1329ARMInstr* ARMInstr_FPSCR ( Bool toFPSCR, HReg iReg ) {
1330 ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
1331 i->tag = ARMin_FPSCR;
1332 i->ARMin.FPSCR.toFPSCR = toFPSCR;
1333 i->ARMin.FPSCR.iReg = iReg;
1334 return i;
1335}
sewardj412098c2010-05-04 08:48:43 +00001336ARMInstr* ARMInstr_MFence ( void ) {
1337 ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
1338 i->tag = ARMin_MFence;
1339 return i;
1340}
cerion82edbb32004-12-16 14:06:34 +00001341
sewardj6c60b322010-08-22 12:48:28 +00001342ARMInstr* ARMInstr_NLdStQ ( Bool isLoad, HReg dQ, ARMAModeN *amode ) {
1343 ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
1344 i->tag = ARMin_NLdStQ;
1345 i->ARMin.NLdStQ.isLoad = isLoad;
1346 i->ARMin.NLdStQ.dQ = dQ;
1347 i->ARMin.NLdStQ.amode = amode;
1348 return i;
1349}
1350
1351ARMInstr* ARMInstr_NLdStD ( Bool isLoad, HReg dD, ARMAModeN *amode ) {
1352 ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
1353 i->tag = ARMin_NLdStD;
1354 i->ARMin.NLdStD.isLoad = isLoad;
1355 i->ARMin.NLdStD.dD = dD;
1356 i->ARMin.NLdStD.amode = amode;
1357 return i;
1358}
1359
1360ARMInstr* ARMInstr_NUnary ( ARMNeonUnOp op, HReg dQ, HReg nQ,
1361 UInt size, Bool Q ) {
1362 ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
1363 i->tag = ARMin_NUnary;
1364 i->ARMin.NUnary.op = op;
1365 i->ARMin.NUnary.src = nQ;
1366 i->ARMin.NUnary.dst = dQ;
1367 i->ARMin.NUnary.size = size;
1368 i->ARMin.NUnary.Q = Q;
1369 return i;
1370}
1371
1372ARMInstr* ARMInstr_NUnaryS ( ARMNeonUnOp op, ARMNRS* dst, ARMNRS* src,
1373 UInt size, Bool Q ) {
1374 ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
1375 i->tag = ARMin_NUnaryS;
1376 i->ARMin.NUnaryS.op = op;
1377 i->ARMin.NUnaryS.src = src;
1378 i->ARMin.NUnaryS.dst = dst;
1379 i->ARMin.NUnaryS.size = size;
1380 i->ARMin.NUnaryS.Q = Q;
1381 return i;
1382}
1383
1384ARMInstr* ARMInstr_NDual ( ARMNeonDualOp op, HReg nQ, HReg mQ,
1385 UInt size, Bool Q ) {
1386 ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
1387 i->tag = ARMin_NDual;
1388 i->ARMin.NDual.op = op;
1389 i->ARMin.NDual.arg1 = nQ;
1390 i->ARMin.NDual.arg2 = mQ;
1391 i->ARMin.NDual.size = size;
1392 i->ARMin.NDual.Q = Q;
1393 return i;
1394}
1395
1396ARMInstr* ARMInstr_NBinary ( ARMNeonBinOp op,
1397 HReg dst, HReg argL, HReg argR,
1398 UInt size, Bool Q ) {
1399 ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
1400 i->tag = ARMin_NBinary;
1401 i->ARMin.NBinary.op = op;
1402 i->ARMin.NBinary.argL = argL;
1403 i->ARMin.NBinary.argR = argR;
1404 i->ARMin.NBinary.dst = dst;
1405 i->ARMin.NBinary.size = size;
1406 i->ARMin.NBinary.Q = Q;
1407 return i;
1408}
1409
1410ARMInstr* ARMInstr_NeonImm (HReg dst, ARMNImm* imm ) {
1411 ARMInstr *i = LibVEX_Alloc(sizeof(ARMInstr));
1412 i->tag = ARMin_NeonImm;
1413 i->ARMin.NeonImm.dst = dst;
1414 i->ARMin.NeonImm.imm = imm;
1415 return i;
1416}
1417
1418ARMInstr* ARMInstr_NCMovQ ( ARMCondCode cond, HReg dst, HReg src ) {
1419 ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
1420 i->tag = ARMin_NCMovQ;
1421 i->ARMin.NCMovQ.cond = cond;
1422 i->ARMin.NCMovQ.dst = dst;
1423 i->ARMin.NCMovQ.src = src;
1424 vassert(cond != ARMcc_AL);
1425 return i;
1426}
1427
1428ARMInstr* ARMInstr_NShift ( ARMNeonShiftOp op,
1429 HReg dst, HReg argL, HReg argR,
1430 UInt size, Bool Q ) {
1431 ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
1432 i->tag = ARMin_NShift;
1433 i->ARMin.NShift.op = op;
1434 i->ARMin.NShift.argL = argL;
1435 i->ARMin.NShift.argR = argR;
1436 i->ARMin.NShift.dst = dst;
1437 i->ARMin.NShift.size = size;
1438 i->ARMin.NShift.Q = Q;
1439 return i;
1440}
1441
1442/* Helper copy-pasted from isel.c */
1443static Bool fitsIn8x4 ( UInt* u8, UInt* u4, UInt u )
1444{
1445 UInt i;
1446 for (i = 0; i < 16; i++) {
1447 if (0 == (u & 0xFFFFFF00)) {
1448 *u8 = u;
1449 *u4 = i;
1450 return True;
1451 }
1452 u = ROR32(u, 30);
1453 }
1454 vassert(i == 16);
1455 return False;
1456}
1457
1458ARMInstr* ARMInstr_Add32 ( HReg rD, HReg rN, UInt imm32 ) {
1459 UInt u8, u4;
1460 ARMInstr *i = LibVEX_Alloc(sizeof(ARMInstr));
1461 /* Try to generate single ADD if possible */
1462 if (fitsIn8x4(&u8, &u4, imm32)) {
1463 i->tag = ARMin_Alu;
1464 i->ARMin.Alu.op = ARMalu_ADD;
1465 i->ARMin.Alu.dst = rD;
1466 i->ARMin.Alu.argL = rN;
1467 i->ARMin.Alu.argR = ARMRI84_I84(u8, u4);
1468 } else {
1469 i->tag = ARMin_Add32;
1470 i->ARMin.Add32.rD = rD;
1471 i->ARMin.Add32.rN = rN;
1472 i->ARMin.Add32.imm32 = imm32;
1473 }
1474 return i;
1475}
1476
1477/* ... */
1478
cerion82edbb32004-12-16 14:06:34 +00001479void ppARMInstr ( ARMInstr* i ) {
sewardj6c299f32009-12-31 18:00:12 +00001480 switch (i->tag) {
1481 case ARMin_Alu:
1482 vex_printf("%-4s ", showARMAluOp(i->ARMin.Alu.op));
1483 ppHRegARM(i->ARMin.Alu.dst);
1484 vex_printf(", ");
1485 ppHRegARM(i->ARMin.Alu.argL);
1486 vex_printf(", ");
1487 ppARMRI84(i->ARMin.Alu.argR);
1488 return;
1489 case ARMin_Shift:
1490 vex_printf("%s ", showARMShiftOp(i->ARMin.Shift.op));
1491 ppHRegARM(i->ARMin.Shift.dst);
1492 vex_printf(", ");
1493 ppHRegARM(i->ARMin.Shift.argL);
1494 vex_printf(", ");
1495 ppARMRI5(i->ARMin.Shift.argR);
1496 return;
1497 case ARMin_Unary:
1498 vex_printf("%s ", showARMUnaryOp(i->ARMin.Unary.op));
1499 ppHRegARM(i->ARMin.Unary.dst);
1500 vex_printf(", ");
1501 ppHRegARM(i->ARMin.Unary.src);
1502 return;
1503 case ARMin_CmpOrTst:
1504 vex_printf("%s ", i->ARMin.CmpOrTst.isCmp ? "cmp" : "tst");
1505 ppHRegARM(i->ARMin.CmpOrTst.argL);
1506 vex_printf(", ");
1507 ppARMRI84(i->ARMin.CmpOrTst.argR);
1508 return;
1509 case ARMin_Mov:
1510 vex_printf("mov ");
1511 ppHRegARM(i->ARMin.Mov.dst);
1512 vex_printf(", ");
1513 ppARMRI84(i->ARMin.Mov.src);
1514 return;
1515 case ARMin_Imm32:
1516 vex_printf("imm ");
1517 ppHRegARM(i->ARMin.Imm32.dst);
1518 vex_printf(", 0x%x", i->ARMin.Imm32.imm32);
1519 return;
1520 case ARMin_LdSt32:
1521 if (i->ARMin.LdSt32.isLoad) {
1522 vex_printf("ldr ");
1523 ppHRegARM(i->ARMin.LdSt32.rD);
1524 vex_printf(", ");
1525 ppARMAMode1(i->ARMin.LdSt32.amode);
1526 } else {
1527 vex_printf("str ");
1528 ppARMAMode1(i->ARMin.LdSt32.amode);
1529 vex_printf(", ");
1530 ppHRegARM(i->ARMin.LdSt32.rD);
1531 }
1532 return;
1533 case ARMin_LdSt16:
1534 if (i->ARMin.LdSt16.isLoad) {
1535 vex_printf("%s", i->ARMin.LdSt16.signedLoad
1536 ? "ldrsh " : "ldrh " );
1537 ppHRegARM(i->ARMin.LdSt16.rD);
1538 vex_printf(", ");
1539 ppARMAMode2(i->ARMin.LdSt16.amode);
1540 } else {
1541 vex_printf("strh ");
1542 ppARMAMode2(i->ARMin.LdSt16.amode);
1543 vex_printf(", ");
1544 ppHRegARM(i->ARMin.LdSt16.rD);
1545 }
1546 return;
1547 case ARMin_LdSt8U:
1548 if (i->ARMin.LdSt8U.isLoad) {
1549 vex_printf("ldrb ");
1550 ppHRegARM(i->ARMin.LdSt8U.rD);
1551 vex_printf(", ");
1552 ppARMAMode1(i->ARMin.LdSt8U.amode);
1553 } else {
1554 vex_printf("strb ");
1555 ppARMAMode1(i->ARMin.LdSt8U.amode);
1556 vex_printf(", ");
1557 ppHRegARM(i->ARMin.LdSt8U.rD);
1558 }
1559 return;
1560 case ARMin_Ld8S:
1561 goto unhandled;
1562 case ARMin_Goto:
1563 if (i->ARMin.Goto.cond != ARMcc_AL) {
1564 vex_printf("if (%%cpsr.%s) { ",
1565 showARMCondCode(i->ARMin.Goto.cond));
1566 } else {
1567 vex_printf("if (1) { ");
1568 }
1569 if (i->ARMin.Goto.jk != Ijk_Boring
1570 && i->ARMin.Goto.jk != Ijk_Call
1571 && i->ARMin.Goto.jk != Ijk_Ret) {
1572 vex_printf("mov r8, $");
1573 ppIRJumpKind(i->ARMin.Goto.jk);
1574 vex_printf(" ; ");
1575 }
1576 vex_printf("mov r0, ");
1577 ppHRegARM(i->ARMin.Goto.gnext);
1578 vex_printf(" ; bx r14");
1579 if (i->ARMin.Goto.cond != ARMcc_AL) {
1580 vex_printf(" }");
1581 } else {
1582 vex_printf(" }");
1583 }
1584 return;
1585 case ARMin_CMov:
1586 vex_printf("mov%s ", showARMCondCode(i->ARMin.CMov.cond));
1587 ppHRegARM(i->ARMin.CMov.dst);
1588 vex_printf(", ");
1589 ppARMRI84(i->ARMin.CMov.src);
1590 return;
1591 case ARMin_Call:
1592 vex_printf("call%s ",
1593 i->ARMin.Call.cond==ARMcc_AL
1594 ? "" : showARMCondCode(i->ARMin.Call.cond));
1595 vex_printf("0x%lx [nArgRegs=%d]",
1596 i->ARMin.Call.target, i->ARMin.Call.nArgRegs);
1597 return;
1598 case ARMin_Mul:
1599 vex_printf("%-5s ", showARMMulOp(i->ARMin.Mul.op));
1600 if (i->ARMin.Mul.op == ARMmul_PLAIN) {
1601 vex_printf("r0, r2, r3");
1602 } else {
1603 vex_printf("r1:r0, r2, r3");
1604 }
1605 return;
1606 case ARMin_LdrEX:
1607 vex_printf("ldrex%s ", i->ARMin.LdrEX.szB == 1 ? "b"
1608 : i->ARMin.LdrEX.szB == 2 ? "h" : "");
1609 vex_printf("r0, [r1]");
1610 return;
1611 case ARMin_StrEX:
1612 vex_printf("strex%s ", i->ARMin.StrEX.szB == 1 ? "b"
1613 : i->ARMin.StrEX.szB == 2 ? "h" : "");
1614 vex_printf("r0, r1, [r2]");
1615 return;
1616 case ARMin_VLdStD:
1617 if (i->ARMin.VLdStD.isLoad) {
1618 vex_printf("fldd ");
1619 ppHRegARM(i->ARMin.VLdStD.dD);
1620 vex_printf(", ");
1621 ppARMAModeV(i->ARMin.VLdStD.amode);
1622 } else {
1623 vex_printf("fstd ");
1624 ppARMAModeV(i->ARMin.VLdStD.amode);
1625 vex_printf(", ");
1626 ppHRegARM(i->ARMin.VLdStD.dD);
1627 }
1628 return;
1629 case ARMin_VLdStS:
1630 if (i->ARMin.VLdStS.isLoad) {
1631 vex_printf("flds ");
1632 ppHRegARM(i->ARMin.VLdStS.fD);
1633 vex_printf(", ");
1634 ppARMAModeV(i->ARMin.VLdStS.amode);
1635 } else {
1636 vex_printf("fsts ");
1637 ppARMAModeV(i->ARMin.VLdStS.amode);
1638 vex_printf(", ");
1639 ppHRegARM(i->ARMin.VLdStS.fD);
1640 }
1641 return;
1642 case ARMin_VAluD:
1643 vex_printf("f%-3sd ", showARMVfpOp(i->ARMin.VAluD.op));
1644 ppHRegARM(i->ARMin.VAluD.dst);
1645 vex_printf(", ");
1646 ppHRegARM(i->ARMin.VAluD.argL);
1647 vex_printf(", ");
1648 ppHRegARM(i->ARMin.VAluD.argR);
1649 return;
1650 case ARMin_VAluS:
1651 vex_printf("f%-3ss ", showARMVfpOp(i->ARMin.VAluS.op));
1652 ppHRegARM(i->ARMin.VAluS.dst);
1653 vex_printf(", ");
1654 ppHRegARM(i->ARMin.VAluS.argL);
1655 vex_printf(", ");
1656 ppHRegARM(i->ARMin.VAluS.argR);
1657 return;
1658 case ARMin_VUnaryD:
1659 vex_printf("f%-3sd ", showARMVfpUnaryOp(i->ARMin.VUnaryD.op));
1660 ppHRegARM(i->ARMin.VUnaryD.dst);
1661 vex_printf(", ");
1662 ppHRegARM(i->ARMin.VUnaryD.src);
1663 return;
1664 case ARMin_VUnaryS:
1665 vex_printf("f%-3ss ", showARMVfpUnaryOp(i->ARMin.VUnaryS.op));
1666 ppHRegARM(i->ARMin.VUnaryS.dst);
1667 vex_printf(", ");
1668 ppHRegARM(i->ARMin.VUnaryS.src);
1669 return;
1670 case ARMin_VCmpD:
1671 vex_printf("fcmpd ");
1672 ppHRegARM(i->ARMin.VCmpD.argL);
1673 vex_printf(", ");
1674 ppHRegARM(i->ARMin.VCmpD.argR);
1675 vex_printf(" ; fmstat");
1676 return;
1677 case ARMin_VCMovD:
1678 vex_printf("fcpyd%s ", showARMCondCode(i->ARMin.VCMovD.cond));
1679 ppHRegARM(i->ARMin.VCMovD.dst);
1680 vex_printf(", ");
1681 ppHRegARM(i->ARMin.VCMovD.src);
1682 return;
1683 case ARMin_VCMovS:
1684 vex_printf("fcpys%s ", showARMCondCode(i->ARMin.VCMovS.cond));
1685 ppHRegARM(i->ARMin.VCMovS.dst);
1686 vex_printf(", ");
1687 ppHRegARM(i->ARMin.VCMovS.src);
1688 return;
1689 case ARMin_VCvtSD:
1690 vex_printf("fcvt%s ", i->ARMin.VCvtSD.sToD ? "ds" : "sd");
1691 ppHRegARM(i->ARMin.VCvtSD.dst);
1692 vex_printf(", ");
1693 ppHRegARM(i->ARMin.VCvtSD.src);
1694 return;
1695 case ARMin_VXferD:
1696 vex_printf("vmov ");
1697 if (i->ARMin.VXferD.toD) {
1698 ppHRegARM(i->ARMin.VXferD.dD);
1699 vex_printf(", ");
1700 ppHRegARM(i->ARMin.VXferD.rLo);
1701 vex_printf(", ");
1702 ppHRegARM(i->ARMin.VXferD.rHi);
1703 } else {
1704 ppHRegARM(i->ARMin.VXferD.rLo);
1705 vex_printf(", ");
1706 ppHRegARM(i->ARMin.VXferD.rHi);
1707 vex_printf(", ");
1708 ppHRegARM(i->ARMin.VXferD.dD);
1709 }
1710 return;
1711 case ARMin_VXferS:
1712 vex_printf("vmov ");
1713 if (i->ARMin.VXferS.toS) {
1714 ppHRegARM(i->ARMin.VXferS.fD);
1715 vex_printf(", ");
1716 ppHRegARM(i->ARMin.VXferS.rLo);
1717 } else {
1718 ppHRegARM(i->ARMin.VXferS.rLo);
1719 vex_printf(", ");
1720 ppHRegARM(i->ARMin.VXferS.fD);
1721 }
1722 return;
1723 case ARMin_VCvtID: {
1724 HChar* nm = "?";
1725 if (i->ARMin.VCvtID.iToD) {
1726 nm = i->ARMin.VCvtID.syned ? "fsitod" : "fuitod";
1727 } else {
1728 nm = i->ARMin.VCvtID.syned ? "ftosid" : "ftouid";
1729 }
1730 vex_printf("%s ", nm);
1731 ppHRegARM(i->ARMin.VCvtID.dst);
1732 vex_printf(", ");
1733 ppHRegARM(i->ARMin.VCvtID.src);
1734 return;
1735 }
1736 case ARMin_FPSCR:
1737 if (i->ARMin.FPSCR.toFPSCR) {
1738 vex_printf("fmxr fpscr, ");
1739 ppHRegARM(i->ARMin.FPSCR.iReg);
1740 } else {
1741 vex_printf("fmrx ");
1742 ppHRegARM(i->ARMin.FPSCR.iReg);
1743 vex_printf(", fpscr");
1744 }
1745 return;
sewardj412098c2010-05-04 08:48:43 +00001746 case ARMin_MFence:
1747 vex_printf("mfence (mcr 15,0,r0,c7,c10,4; 15,0,r0,c7,c10,5; "
1748 "15,0,r0,c7,c5,4)");
1749 return;
sewardj6c60b322010-08-22 12:48:28 +00001750 case ARMin_NLdStQ:
1751 if (i->ARMin.NLdStQ.isLoad)
1752 vex_printf("vld1.32 {");
1753 else
1754 vex_printf("vst1.32 {");
1755 ppHRegARM(i->ARMin.NLdStQ.dQ);
1756 vex_printf("} ");
1757 ppARMAModeN(i->ARMin.NLdStQ.amode);
1758 return;
1759 case ARMin_NLdStD:
1760 if (i->ARMin.NLdStD.isLoad)
1761 vex_printf("vld1.32 {");
1762 else
1763 vex_printf("vst1.32 {");
1764 ppHRegARM(i->ARMin.NLdStD.dD);
1765 vex_printf("} ");
1766 ppARMAModeN(i->ARMin.NLdStD.amode);
1767 return;
1768 case ARMin_NUnary:
1769 vex_printf("%s%s%s ",
1770 showARMNeonUnOp(i->ARMin.NUnary.op),
1771 showARMNeonUnOpDataType(i->ARMin.NUnary.op),
1772 showARMNeonDataSize(i));
1773 ppHRegARM(i->ARMin.NUnary.dst);
1774 vex_printf(", ");
1775 ppHRegARM(i->ARMin.NUnary.src);
1776 if (i->ARMin.NUnary.op == ARMneon_EQZ)
1777 vex_printf(", #0");
1778 if (i->ARMin.NUnary.op == ARMneon_VCVTFtoFixedS ||
1779 i->ARMin.NUnary.op == ARMneon_VCVTFtoFixedU ||
1780 i->ARMin.NUnary.op == ARMneon_VCVTFixedStoF ||
1781 i->ARMin.NUnary.op == ARMneon_VCVTFixedUtoF) {
1782 vex_printf(", #%d", i->ARMin.NUnary.size);
1783 }
1784 if (i->ARMin.NUnary.op == ARMneon_VQSHLNSS ||
1785 i->ARMin.NUnary.op == ARMneon_VQSHLNUU ||
1786 i->ARMin.NUnary.op == ARMneon_VQSHLNUS) {
1787 UInt size;
1788 size = i->ARMin.NUnary.size;
1789 if (size & 0x40) {
1790 vex_printf(", #%d", size - 64);
1791 } else if (size & 0x20) {
1792 vex_printf(", #%d", size - 32);
1793 } else if (size & 0x10) {
1794 vex_printf(", #%d", size - 16);
1795 } else if (size & 0x08) {
1796 vex_printf(", #%d", size - 8);
1797 }
1798 }
1799 return;
1800 case ARMin_NUnaryS:
1801 vex_printf("%s%s%s ",
1802 showARMNeonUnOpS(i->ARMin.NUnary.op),
1803 showARMNeonUnOpSDataType(i->ARMin.NUnary.op),
1804 showARMNeonDataSize(i));
1805 ppARMNRS(i->ARMin.NUnaryS.dst);
1806 vex_printf(", ");
1807 ppARMNRS(i->ARMin.NUnaryS.src);
1808 return;
1809 case ARMin_NShift:
1810 vex_printf("%s%s%s ",
1811 showARMNeonShiftOp(i->ARMin.NShift.op),
1812 showARMNeonShiftOpDataType(i->ARMin.NShift.op),
1813 showARMNeonDataSize(i));
1814 ppHRegARM(i->ARMin.NShift.dst);
1815 vex_printf(", ");
1816 ppHRegARM(i->ARMin.NShift.argL);
1817 vex_printf(", ");
1818 ppHRegARM(i->ARMin.NShift.argR);
1819 return;
1820 case ARMin_NDual:
1821 vex_printf("%s%s%s ",
1822 showARMNeonDualOp(i->ARMin.NDual.op),
1823 showARMNeonDualOpDataType(i->ARMin.NDual.op),
1824 showARMNeonDataSize(i));
1825 ppHRegARM(i->ARMin.NDual.arg1);
1826 vex_printf(", ");
1827 ppHRegARM(i->ARMin.NDual.arg2);
1828 return;
1829 case ARMin_NBinary:
1830 vex_printf("%s%s%s",
1831 showARMNeonBinOp(i->ARMin.NBinary.op),
1832 showARMNeonBinOpDataType(i->ARMin.NBinary.op),
1833 showARMNeonDataSize(i));
1834 vex_printf(" ");
1835 ppHRegARM(i->ARMin.NBinary.dst);
1836 vex_printf(", ");
1837 ppHRegARM(i->ARMin.NBinary.argL);
1838 vex_printf(", ");
1839 ppHRegARM(i->ARMin.NBinary.argR);
1840 return;
1841 case ARMin_NeonImm:
1842 vex_printf("vmov ");
1843 ppHRegARM(i->ARMin.NeonImm.dst);
1844 vex_printf(", ");
1845 ppARMNImm(i->ARMin.NeonImm.imm);
1846 return;
1847 case ARMin_NCMovQ:
1848 vex_printf("vmov%s ", showARMCondCode(i->ARMin.NCMovQ.cond));
1849 ppHRegARM(i->ARMin.NCMovQ.dst);
1850 vex_printf(", ");
1851 ppHRegARM(i->ARMin.NCMovQ.src);
1852 return;
1853 case ARMin_Add32:
1854 vex_printf("add32 ");
1855 ppHRegARM(i->ARMin.Add32.rD);
1856 vex_printf(", ");
1857 ppHRegARM(i->ARMin.Add32.rN);
1858 vex_printf(", ");
1859 vex_printf("%d", i->ARMin.Add32.imm32);
1860 return;
1861 default:
sewardj6c299f32009-12-31 18:00:12 +00001862 unhandled:
1863 vex_printf("ppARMInstr: unhandled case (tag %d)", (Int)i->tag);
1864 vpanic("ppARMInstr(1)");
1865 return;
sewardj6c299f32009-12-31 18:00:12 +00001866 }
cerion82edbb32004-12-16 14:06:34 +00001867}
1868
1869
cerion82edbb32004-12-16 14:06:34 +00001870/* --------- Helpers for register allocation. --------- */
1871
sewardj6c299f32009-12-31 18:00:12 +00001872void getRegUsage_ARMInstr ( HRegUsage* u, ARMInstr* i, Bool mode64 )
1873{
1874 vassert(mode64 == False);
1875 initHRegUsage(u);
1876 switch (i->tag) {
1877 case ARMin_Alu:
1878 addHRegUse(u, HRmWrite, i->ARMin.Alu.dst);
1879 addHRegUse(u, HRmRead, i->ARMin.Alu.argL);
1880 addRegUsage_ARMRI84(u, i->ARMin.Alu.argR);
1881 return;
1882 case ARMin_Shift:
1883 addHRegUse(u, HRmWrite, i->ARMin.Shift.dst);
1884 addHRegUse(u, HRmRead, i->ARMin.Shift.argL);
1885 addRegUsage_ARMRI5(u, i->ARMin.Shift.argR);
1886 return;
1887 case ARMin_Unary:
1888 addHRegUse(u, HRmWrite, i->ARMin.Unary.dst);
1889 addHRegUse(u, HRmRead, i->ARMin.Unary.src);
1890 return;
1891 case ARMin_CmpOrTst:
1892 addHRegUse(u, HRmRead, i->ARMin.CmpOrTst.argL);
1893 addRegUsage_ARMRI84(u, i->ARMin.CmpOrTst.argR);
1894 return;
1895 case ARMin_Mov:
1896 addHRegUse(u, HRmWrite, i->ARMin.Mov.dst);
1897 addRegUsage_ARMRI84(u, i->ARMin.Mov.src);
1898 return;
1899 case ARMin_Imm32:
1900 addHRegUse(u, HRmWrite, i->ARMin.Imm32.dst);
1901 return;
1902 case ARMin_LdSt32:
1903 addRegUsage_ARMAMode1(u, i->ARMin.LdSt32.amode);
1904 if (i->ARMin.LdSt32.isLoad) {
1905 addHRegUse(u, HRmWrite, i->ARMin.LdSt32.rD);
1906 } else {
1907 addHRegUse(u, HRmRead, i->ARMin.LdSt32.rD);
1908 }
1909 return;
1910 case ARMin_LdSt16:
1911 addRegUsage_ARMAMode2(u, i->ARMin.LdSt16.amode);
1912 if (i->ARMin.LdSt16.isLoad) {
1913 addHRegUse(u, HRmWrite, i->ARMin.LdSt16.rD);
1914 } else {
1915 addHRegUse(u, HRmRead, i->ARMin.LdSt16.rD);
1916 }
1917 return;
1918 case ARMin_LdSt8U:
1919 addRegUsage_ARMAMode1(u, i->ARMin.LdSt8U.amode);
1920 if (i->ARMin.LdSt8U.isLoad) {
1921 addHRegUse(u, HRmWrite, i->ARMin.LdSt8U.rD);
1922 } else {
1923 addHRegUse(u, HRmRead, i->ARMin.LdSt8U.rD);
1924 }
1925 return;
1926 case ARMin_Ld8S:
1927 goto unhandled;
1928 case ARMin_Goto:
1929 /* reads the reg holding the next guest addr */
1930 addHRegUse(u, HRmRead, i->ARMin.Goto.gnext);
1931 /* writes it to the standard integer return register */
1932 addHRegUse(u, HRmWrite, hregARM_R0());
1933 /* possibly messes with the baseblock pointer */
1934 if (i->ARMin.Goto.jk != Ijk_Boring
1935 && i->ARMin.Goto.jk != Ijk_Call
1936 && i->ARMin.Goto.jk != Ijk_Ret)
1937 /* note, this is irrelevant since r8 is not actually
1938 available to the allocator. But still .. */
1939 addHRegUse(u, HRmWrite, hregARM_R8());
1940 return;
1941 case ARMin_CMov:
1942 addHRegUse(u, HRmWrite, i->ARMin.CMov.dst);
1943 addHRegUse(u, HRmRead, i->ARMin.CMov.dst);
1944 addRegUsage_ARMRI84(u, i->ARMin.CMov.src);
1945 return;
1946 case ARMin_Call:
1947 /* logic and comments copied/modified from x86 back end */
1948 /* This is a bit subtle. */
1949 /* First off, claim it trashes all the caller-saved regs
1950 which fall within the register allocator's jurisdiction.
1951 These I believe to be r0,1,2,3. If it turns out that r9
1952 is also caller-saved, then we'll have to add that here
1953 too. */
1954 addHRegUse(u, HRmWrite, hregARM_R0());
1955 addHRegUse(u, HRmWrite, hregARM_R1());
1956 addHRegUse(u, HRmWrite, hregARM_R2());
1957 addHRegUse(u, HRmWrite, hregARM_R3());
1958 /* Now we have to state any parameter-carrying registers
1959 which might be read. This depends on nArgRegs. */
1960 switch (i->ARMin.Call.nArgRegs) {
1961 case 4: addHRegUse(u, HRmRead, hregARM_R3()); /*fallthru*/
1962 case 3: addHRegUse(u, HRmRead, hregARM_R2()); /*fallthru*/
1963 case 2: addHRegUse(u, HRmRead, hregARM_R1()); /*fallthru*/
1964 case 1: addHRegUse(u, HRmRead, hregARM_R0()); break;
1965 case 0: break;
1966 default: vpanic("getRegUsage_ARM:Call:regparms");
1967 }
1968 /* Finally, there is the issue that the insn trashes a
1969 register because the literal target address has to be
1970 loaded into a register. Fortunately, for the nArgRegs=
1971 0/1/2/3 case, we can use r0, r1, r2 or r3 respectively, so
1972 this does not cause any further damage. For the
1973 nArgRegs=4 case, we'll have to choose another register
1974 arbitrarily since all the caller saved regs are used for
1975 parameters, and so we might as well choose r11.
1976 */
1977 if (i->ARMin.Call.nArgRegs == 4)
1978 addHRegUse(u, HRmWrite, hregARM_R11());
1979 /* Upshot of this is that the assembler really must observe
1980 the here-stated convention of which register to use as an
1981 address temporary, depending on nArgRegs: 0==r0,
1982 1==r1, 2==r2, 3==r3, 4==r11 */
1983 return;
1984 case ARMin_Mul:
1985 addHRegUse(u, HRmRead, hregARM_R2());
1986 addHRegUse(u, HRmRead, hregARM_R3());
1987 addHRegUse(u, HRmWrite, hregARM_R0());
1988 if (i->ARMin.Mul.op != ARMmul_PLAIN)
1989 addHRegUse(u, HRmWrite, hregARM_R1());
1990 return;
1991 case ARMin_LdrEX:
1992 addHRegUse(u, HRmWrite, hregARM_R0());
1993 addHRegUse(u, HRmRead, hregARM_R1());
1994 return;
1995 case ARMin_StrEX:
1996 addHRegUse(u, HRmWrite, hregARM_R0());
1997 addHRegUse(u, HRmRead, hregARM_R1());
1998 addHRegUse(u, HRmRead, hregARM_R2());
1999 return;
2000 case ARMin_VLdStD:
2001 addRegUsage_ARMAModeV(u, i->ARMin.VLdStD.amode);
2002 if (i->ARMin.VLdStD.isLoad) {
2003 addHRegUse(u, HRmWrite, i->ARMin.VLdStD.dD);
2004 } else {
2005 addHRegUse(u, HRmRead, i->ARMin.VLdStD.dD);
2006 }
2007 return;
2008 case ARMin_VLdStS:
2009 addRegUsage_ARMAModeV(u, i->ARMin.VLdStS.amode);
2010 if (i->ARMin.VLdStS.isLoad) {
2011 addHRegUse(u, HRmWrite, i->ARMin.VLdStS.fD);
2012 } else {
2013 addHRegUse(u, HRmRead, i->ARMin.VLdStS.fD);
2014 }
2015 return;
2016 case ARMin_VAluD:
2017 addHRegUse(u, HRmWrite, i->ARMin.VAluD.dst);
2018 addHRegUse(u, HRmRead, i->ARMin.VAluD.argL);
2019 addHRegUse(u, HRmRead, i->ARMin.VAluD.argR);
2020 return;
2021 case ARMin_VAluS:
2022 addHRegUse(u, HRmWrite, i->ARMin.VAluS.dst);
2023 addHRegUse(u, HRmRead, i->ARMin.VAluS.argL);
2024 addHRegUse(u, HRmRead, i->ARMin.VAluS.argR);
2025 return;
2026 case ARMin_VUnaryD:
2027 addHRegUse(u, HRmWrite, i->ARMin.VUnaryD.dst);
2028 addHRegUse(u, HRmRead, i->ARMin.VUnaryD.src);
2029 return;
2030 case ARMin_VUnaryS:
2031 addHRegUse(u, HRmWrite, i->ARMin.VUnaryS.dst);
2032 addHRegUse(u, HRmRead, i->ARMin.VUnaryS.src);
2033 return;
2034 case ARMin_VCmpD:
2035 addHRegUse(u, HRmRead, i->ARMin.VCmpD.argL);
2036 addHRegUse(u, HRmRead, i->ARMin.VCmpD.argR);
2037 return;
2038 case ARMin_VCMovD:
2039 addHRegUse(u, HRmWrite, i->ARMin.VCMovD.dst);
2040 addHRegUse(u, HRmRead, i->ARMin.VCMovD.dst);
2041 addHRegUse(u, HRmRead, i->ARMin.VCMovD.src);
2042 return;
2043 case ARMin_VCMovS:
2044 addHRegUse(u, HRmWrite, i->ARMin.VCMovS.dst);
2045 addHRegUse(u, HRmRead, i->ARMin.VCMovS.dst);
2046 addHRegUse(u, HRmRead, i->ARMin.VCMovS.src);
2047 return;
2048 case ARMin_VCvtSD:
2049 addHRegUse(u, HRmWrite, i->ARMin.VCvtSD.dst);
2050 addHRegUse(u, HRmRead, i->ARMin.VCvtSD.src);
2051 return;
2052 case ARMin_VXferD:
2053 if (i->ARMin.VXferD.toD) {
2054 addHRegUse(u, HRmWrite, i->ARMin.VXferD.dD);
2055 addHRegUse(u, HRmRead, i->ARMin.VXferD.rHi);
2056 addHRegUse(u, HRmRead, i->ARMin.VXferD.rLo);
2057 } else {
2058 addHRegUse(u, HRmRead, i->ARMin.VXferD.dD);
2059 addHRegUse(u, HRmWrite, i->ARMin.VXferD.rHi);
2060 addHRegUse(u, HRmWrite, i->ARMin.VXferD.rLo);
2061 }
2062 return;
2063 case ARMin_VXferS:
2064 if (i->ARMin.VXferS.toS) {
2065 addHRegUse(u, HRmWrite, i->ARMin.VXferS.fD);
2066 addHRegUse(u, HRmRead, i->ARMin.VXferS.rLo);
2067 } else {
2068 addHRegUse(u, HRmRead, i->ARMin.VXferS.fD);
2069 addHRegUse(u, HRmWrite, i->ARMin.VXferS.rLo);
2070 }
2071 return;
2072 case ARMin_VCvtID:
2073 addHRegUse(u, HRmWrite, i->ARMin.VCvtID.dst);
2074 addHRegUse(u, HRmRead, i->ARMin.VCvtID.src);
2075 return;
2076 case ARMin_FPSCR:
2077 if (i->ARMin.FPSCR.toFPSCR)
2078 addHRegUse(u, HRmRead, i->ARMin.FPSCR.iReg);
2079 else
2080 addHRegUse(u, HRmWrite, i->ARMin.FPSCR.iReg);
2081 return;
sewardj412098c2010-05-04 08:48:43 +00002082 case ARMin_MFence:
2083 return;
sewardj6c60b322010-08-22 12:48:28 +00002084 case ARMin_NLdStQ:
2085 if (i->ARMin.NLdStQ.isLoad)
2086 addHRegUse(u, HRmWrite, i->ARMin.NLdStQ.dQ);
2087 else
2088 addHRegUse(u, HRmRead, i->ARMin.NLdStQ.dQ);
2089 addRegUsage_ARMAModeN(u, i->ARMin.NLdStQ.amode);
2090 return;
2091 case ARMin_NLdStD:
2092 if (i->ARMin.NLdStD.isLoad)
2093 addHRegUse(u, HRmWrite, i->ARMin.NLdStD.dD);
2094 else
2095 addHRegUse(u, HRmRead, i->ARMin.NLdStD.dD);
2096 addRegUsage_ARMAModeN(u, i->ARMin.NLdStD.amode);
2097 return;
2098 case ARMin_NUnary:
2099 addHRegUse(u, HRmWrite, i->ARMin.NUnary.dst);
2100 addHRegUse(u, HRmRead, i->ARMin.NUnary.src);
2101 return;
2102 case ARMin_NUnaryS:
2103 addHRegUse(u, HRmWrite, i->ARMin.NUnaryS.dst->reg);
2104 addHRegUse(u, HRmRead, i->ARMin.NUnaryS.src->reg);
2105 return;
2106 case ARMin_NShift:
2107 addHRegUse(u, HRmWrite, i->ARMin.NShift.dst);
2108 addHRegUse(u, HRmRead, i->ARMin.NShift.argL);
2109 addHRegUse(u, HRmRead, i->ARMin.NShift.argR);
2110 return;
2111 case ARMin_NDual:
2112 addHRegUse(u, HRmWrite, i->ARMin.NDual.arg1);
2113 addHRegUse(u, HRmWrite, i->ARMin.NDual.arg2);
2114 addHRegUse(u, HRmRead, i->ARMin.NDual.arg1);
2115 addHRegUse(u, HRmRead, i->ARMin.NDual.arg2);
2116 return;
2117 case ARMin_NBinary:
2118 addHRegUse(u, HRmWrite, i->ARMin.NBinary.dst);
2119 /* TODO: sometimes dst is also being read! */
2120 // XXX fix this
2121 addHRegUse(u, HRmRead, i->ARMin.NBinary.argL);
2122 addHRegUse(u, HRmRead, i->ARMin.NBinary.argR);
2123 return;
2124 case ARMin_NeonImm:
2125 addHRegUse(u, HRmWrite, i->ARMin.NeonImm.dst);
2126 return;
2127 case ARMin_NCMovQ:
2128 addHRegUse(u, HRmWrite, i->ARMin.NCMovQ.dst);
2129 addHRegUse(u, HRmRead, i->ARMin.NCMovQ.dst);
2130 addHRegUse(u, HRmRead, i->ARMin.NCMovQ.src);
2131 return;
2132 case ARMin_Add32:
2133 addHRegUse(u, HRmWrite, i->ARMin.Add32.rD);
2134 addHRegUse(u, HRmRead, i->ARMin.Add32.rN);
2135 return;
sewardj6c299f32009-12-31 18:00:12 +00002136 unhandled:
2137 default:
2138 ppARMInstr(i);
2139 vpanic("getRegUsage_ARMInstr");
2140 }
cerion82edbb32004-12-16 14:06:34 +00002141}
2142
2143
sewardj6c299f32009-12-31 18:00:12 +00002144void mapRegs_ARMInstr ( HRegRemap* m, ARMInstr* i, Bool mode64 )
2145{
2146 vassert(mode64 == False);
2147 switch (i->tag) {
2148 case ARMin_Alu:
2149 i->ARMin.Alu.dst = lookupHRegRemap(m, i->ARMin.Alu.dst);
2150 i->ARMin.Alu.argL = lookupHRegRemap(m, i->ARMin.Alu.argL);
2151 mapRegs_ARMRI84(m, i->ARMin.Alu.argR);
2152 return;
2153 case ARMin_Shift:
2154 i->ARMin.Shift.dst = lookupHRegRemap(m, i->ARMin.Shift.dst);
2155 i->ARMin.Shift.argL = lookupHRegRemap(m, i->ARMin.Shift.argL);
2156 mapRegs_ARMRI5(m, i->ARMin.Shift.argR);
2157 return;
2158 case ARMin_Unary:
2159 i->ARMin.Unary.dst = lookupHRegRemap(m, i->ARMin.Unary.dst);
2160 i->ARMin.Unary.src = lookupHRegRemap(m, i->ARMin.Unary.src);
2161 return;
2162 case ARMin_CmpOrTst:
2163 i->ARMin.CmpOrTst.argL = lookupHRegRemap(m, i->ARMin.CmpOrTst.argL);
2164 mapRegs_ARMRI84(m, i->ARMin.CmpOrTst.argR);
2165 return;
2166 case ARMin_Mov:
2167 i->ARMin.Mov.dst = lookupHRegRemap(m, i->ARMin.Mov.dst);
2168 mapRegs_ARMRI84(m, i->ARMin.Mov.src);
2169 return;
2170 case ARMin_Imm32:
2171 i->ARMin.Imm32.dst = lookupHRegRemap(m, i->ARMin.Imm32.dst);
2172 return;
2173 case ARMin_LdSt32:
2174 i->ARMin.LdSt32.rD = lookupHRegRemap(m, i->ARMin.LdSt32.rD);
2175 mapRegs_ARMAMode1(m, i->ARMin.LdSt32.amode);
2176 return;
2177 case ARMin_LdSt16:
2178 i->ARMin.LdSt16.rD = lookupHRegRemap(m, i->ARMin.LdSt16.rD);
2179 mapRegs_ARMAMode2(m, i->ARMin.LdSt16.amode);
2180 return;
2181 case ARMin_LdSt8U:
2182 i->ARMin.LdSt8U.rD = lookupHRegRemap(m, i->ARMin.LdSt8U.rD);
2183 mapRegs_ARMAMode1(m, i->ARMin.LdSt8U.amode);
2184 return;
2185 case ARMin_Ld8S:
2186 goto unhandled;
2187 case ARMin_Goto:
2188 i->ARMin.Goto.gnext = lookupHRegRemap(m, i->ARMin.Goto.gnext);
2189 return;
2190 case ARMin_CMov:
2191 i->ARMin.CMov.dst = lookupHRegRemap(m, i->ARMin.CMov.dst);
2192 mapRegs_ARMRI84(m, i->ARMin.CMov.src);
2193 return;
2194 case ARMin_Call:
2195 return;
2196 case ARMin_Mul:
2197 return;
2198 case ARMin_LdrEX:
2199 return;
2200 case ARMin_StrEX:
2201 return;
2202 case ARMin_VLdStD:
2203 i->ARMin.VLdStD.dD = lookupHRegRemap(m, i->ARMin.VLdStD.dD);
2204 mapRegs_ARMAModeV(m, i->ARMin.VLdStD.amode);
2205 return;
2206 case ARMin_VLdStS:
2207 i->ARMin.VLdStS.fD = lookupHRegRemap(m, i->ARMin.VLdStS.fD);
2208 mapRegs_ARMAModeV(m, i->ARMin.VLdStS.amode);
2209 return;
2210 case ARMin_VAluD:
2211 i->ARMin.VAluD.dst = lookupHRegRemap(m, i->ARMin.VAluD.dst);
2212 i->ARMin.VAluD.argL = lookupHRegRemap(m, i->ARMin.VAluD.argL);
2213 i->ARMin.VAluD.argR = lookupHRegRemap(m, i->ARMin.VAluD.argR);
2214 return;
2215 case ARMin_VAluS:
2216 i->ARMin.VAluS.dst = lookupHRegRemap(m, i->ARMin.VAluS.dst);
2217 i->ARMin.VAluS.argL = lookupHRegRemap(m, i->ARMin.VAluS.argL);
2218 i->ARMin.VAluS.argR = lookupHRegRemap(m, i->ARMin.VAluS.argR);
2219 return;
2220 case ARMin_VUnaryD:
2221 i->ARMin.VUnaryD.dst = lookupHRegRemap(m, i->ARMin.VUnaryD.dst);
2222 i->ARMin.VUnaryD.src = lookupHRegRemap(m, i->ARMin.VUnaryD.src);
2223 return;
2224 case ARMin_VUnaryS:
2225 i->ARMin.VUnaryS.dst = lookupHRegRemap(m, i->ARMin.VUnaryS.dst);
2226 i->ARMin.VUnaryS.src = lookupHRegRemap(m, i->ARMin.VUnaryS.src);
2227 return;
2228 case ARMin_VCmpD:
2229 i->ARMin.VCmpD.argL = lookupHRegRemap(m, i->ARMin.VCmpD.argL);
2230 i->ARMin.VCmpD.argR = lookupHRegRemap(m, i->ARMin.VCmpD.argR);
2231 return;
2232 case ARMin_VCMovD:
2233 i->ARMin.VCMovD.dst = lookupHRegRemap(m, i->ARMin.VCMovD.dst);
2234 i->ARMin.VCMovD.src = lookupHRegRemap(m, i->ARMin.VCMovD.src);
2235 return;
2236 case ARMin_VCMovS:
2237 i->ARMin.VCMovS.dst = lookupHRegRemap(m, i->ARMin.VCMovS.dst);
2238 i->ARMin.VCMovS.src = lookupHRegRemap(m, i->ARMin.VCMovS.src);
2239 return;
2240 case ARMin_VCvtSD:
2241 i->ARMin.VCvtSD.dst = lookupHRegRemap(m, i->ARMin.VCvtSD.dst);
2242 i->ARMin.VCvtSD.src = lookupHRegRemap(m, i->ARMin.VCvtSD.src);
2243 return;
2244 case ARMin_VXferD:
2245 i->ARMin.VXferD.dD = lookupHRegRemap(m, i->ARMin.VXferD.dD);
2246 i->ARMin.VXferD.rHi = lookupHRegRemap(m, i->ARMin.VXferD.rHi);
2247 i->ARMin.VXferD.rLo = lookupHRegRemap(m, i->ARMin.VXferD.rLo);
2248 return;
2249 case ARMin_VXferS:
2250 i->ARMin.VXferS.fD = lookupHRegRemap(m, i->ARMin.VXferS.fD);
2251 i->ARMin.VXferS.rLo = lookupHRegRemap(m, i->ARMin.VXferS.rLo);
2252 return;
2253 case ARMin_VCvtID:
2254 i->ARMin.VCvtID.dst = lookupHRegRemap(m, i->ARMin.VCvtID.dst);
2255 i->ARMin.VCvtID.src = lookupHRegRemap(m, i->ARMin.VCvtID.src);
2256 return;
2257 case ARMin_FPSCR:
2258 i->ARMin.FPSCR.iReg = lookupHRegRemap(m, i->ARMin.FPSCR.iReg);
2259 return;
sewardj412098c2010-05-04 08:48:43 +00002260 case ARMin_MFence:
2261 return;
sewardj6c60b322010-08-22 12:48:28 +00002262 case ARMin_NLdStQ:
2263 i->ARMin.NLdStQ.dQ = lookupHRegRemap(m, i->ARMin.NLdStQ.dQ);
2264 mapRegs_ARMAModeN(m, i->ARMin.NLdStQ.amode);
2265 return;
2266 case ARMin_NLdStD:
2267 i->ARMin.NLdStD.dD = lookupHRegRemap(m, i->ARMin.NLdStD.dD);
2268 mapRegs_ARMAModeN(m, i->ARMin.NLdStD.amode);
2269 return;
2270 case ARMin_NUnary:
2271 i->ARMin.NUnary.src = lookupHRegRemap(m, i->ARMin.NUnary.src);
2272 i->ARMin.NUnary.dst = lookupHRegRemap(m, i->ARMin.NUnary.dst);
2273 return;
2274 case ARMin_NUnaryS:
2275 i->ARMin.NUnaryS.src->reg
2276 = lookupHRegRemap(m, i->ARMin.NUnaryS.src->reg);
2277 i->ARMin.NUnaryS.dst->reg
2278 = lookupHRegRemap(m, i->ARMin.NUnaryS.dst->reg);
2279 return;
2280 case ARMin_NShift:
2281 i->ARMin.NShift.dst = lookupHRegRemap(m, i->ARMin.NShift.dst);
2282 i->ARMin.NShift.argL = lookupHRegRemap(m, i->ARMin.NShift.argL);
2283 i->ARMin.NShift.argR = lookupHRegRemap(m, i->ARMin.NShift.argR);
2284 return;
2285 case ARMin_NDual:
2286 i->ARMin.NDual.arg1 = lookupHRegRemap(m, i->ARMin.NDual.arg1);
2287 i->ARMin.NDual.arg2 = lookupHRegRemap(m, i->ARMin.NDual.arg2);
2288 return;
2289 case ARMin_NBinary:
2290 i->ARMin.NBinary.argL = lookupHRegRemap(m, i->ARMin.NBinary.argL);
2291 i->ARMin.NBinary.argR = lookupHRegRemap(m, i->ARMin.NBinary.argR);
2292 i->ARMin.NBinary.dst = lookupHRegRemap(m, i->ARMin.NBinary.dst);
2293 return;
2294 case ARMin_NeonImm:
2295 i->ARMin.NeonImm.dst = lookupHRegRemap(m, i->ARMin.NeonImm.dst);
2296 return;
2297 case ARMin_NCMovQ:
2298 i->ARMin.NCMovQ.dst = lookupHRegRemap(m, i->ARMin.NCMovQ.dst);
2299 i->ARMin.NCMovQ.src = lookupHRegRemap(m, i->ARMin.NCMovQ.src);
2300 return;
2301 case ARMin_Add32:
2302 i->ARMin.Add32.rD = lookupHRegRemap(m, i->ARMin.Add32.rD);
2303 i->ARMin.Add32.rN = lookupHRegRemap(m, i->ARMin.Add32.rN);
sewardj6c299f32009-12-31 18:00:12 +00002304 unhandled:
2305 default:
2306 ppARMInstr(i);
2307 vpanic("mapRegs_ARMInstr");
2308 }
cerion82edbb32004-12-16 14:06:34 +00002309}
2310
2311/* Figure out if i represents a reg-reg move, and if so assign the
2312 source and destination to *src and *dst. If in doubt say No. Used
2313 by the register allocator to do move coalescing.
2314*/
sewardj6c299f32009-12-31 18:00:12 +00002315Bool isMove_ARMInstr ( ARMInstr* i, HReg* src, HReg* dst )
2316{
2317 /* Moves between integer regs */
2318 switch (i->tag) {
2319 case ARMin_Mov:
2320 if (i->ARMin.Mov.src->tag == ARMri84_R) {
2321 *src = i->ARMin.Mov.src->ARMri84.R.reg;
2322 *dst = i->ARMin.Mov.dst;
2323 return True;
2324 }
2325 break;
2326 case ARMin_VUnaryD:
2327 if (i->ARMin.VUnaryD.op == ARMvfpu_COPY) {
2328 *src = i->ARMin.VUnaryD.src;
2329 *dst = i->ARMin.VUnaryD.dst;
2330 return True;
2331 }
2332 break;
2333 case ARMin_VUnaryS:
2334 if (i->ARMin.VUnaryS.op == ARMvfpu_COPY) {
2335 *src = i->ARMin.VUnaryS.src;
2336 *dst = i->ARMin.VUnaryS.dst;
2337 return True;
2338 }
2339 break;
2340 default:
2341 break;
2342 }
2343
2344 // todo: float, vector moves
2345 return False;
cerion82edbb32004-12-16 14:06:34 +00002346}
2347
2348
sewardj6c299f32009-12-31 18:00:12 +00002349/* Generate arm spill/reload instructions under the direction of the
cerion82edbb32004-12-16 14:06:34 +00002350 register allocator. Note it's critical these don't write the
2351 condition codes. */
2352
sewardj6c299f32009-12-31 18:00:12 +00002353void genSpill_ARM ( /*OUT*/HInstr** i1, /*OUT*/HInstr** i2,
2354 HReg rreg, Int offsetB, Bool mode64 )
2355{
2356 HRegClass rclass;
cerion82edbb32004-12-16 14:06:34 +00002357 vassert(offsetB >= 0);
2358 vassert(!hregIsVirtual(rreg));
sewardj6c299f32009-12-31 18:00:12 +00002359 vassert(mode64 == False);
2360 *i1 = *i2 = NULL;
2361 rclass = hregClass(rreg);
2362 switch (rclass) {
2363 case HRcInt32:
2364 vassert(offsetB <= 4095);
2365 *i1 = ARMInstr_LdSt32( False/*!isLoad*/,
2366 rreg,
2367 ARMAMode1_RI(hregARM_R8(), offsetB) );
2368 return;
2369 case HRcFlt32:
2370 case HRcFlt64: {
2371 HReg r8 = hregARM_R8(); /* baseblock */
2372 HReg r12 = hregARM_R12(); /* spill temp */
2373 HReg base = r8;
2374 vassert(0 == (offsetB & 3));
2375 if (offsetB >= 1024) {
sewardje30973c2010-09-01 10:25:51 +00002376 Int offsetKB = offsetB / 1024;
2377 /* r12 = r8 + (1024 * offsetKB) */
sewardj6c299f32009-12-31 18:00:12 +00002378 *i1 = ARMInstr_Alu(ARMalu_ADD, r12, r8,
sewardje30973c2010-09-01 10:25:51 +00002379 ARMRI84_I84(offsetKB, 11));
2380 offsetB -= (1024 * offsetKB);
sewardj6c299f32009-12-31 18:00:12 +00002381 base = r12;
2382 }
2383 vassert(offsetB <= 1020);
2384 if (rclass == HRcFlt32) {
2385 *i2 = ARMInstr_VLdStS( False/*!isLoad*/,
2386 rreg,
2387 mkARMAModeV(base, offsetB) );
2388 } else {
2389 *i2 = ARMInstr_VLdStD( False/*!isLoad*/,
2390 rreg,
2391 mkARMAModeV(base, offsetB) );
2392 }
2393 return;
2394 }
sewardj6c60b322010-08-22 12:48:28 +00002395 case HRcVec128: {
2396 HReg r8 = hregARM_R8();
2397 HReg r12 = hregARM_R12();
2398 *i1 = ARMInstr_Add32(r12, r8, offsetB);
2399 *i2 = ARMInstr_NLdStQ(False, rreg, mkARMAModeN_R(r12));
2400 return;
2401 }
2402 default:
sewardj6c299f32009-12-31 18:00:12 +00002403 ppHRegClass(rclass);
2404 vpanic("genSpill_ARM: unimplemented regclass");
cerion82edbb32004-12-16 14:06:34 +00002405 }
2406}
2407
sewardj6c299f32009-12-31 18:00:12 +00002408void genReload_ARM ( /*OUT*/HInstr** i1, /*OUT*/HInstr** i2,
2409 HReg rreg, Int offsetB, Bool mode64 )
2410{
2411 HRegClass rclass;
cerion82edbb32004-12-16 14:06:34 +00002412 vassert(offsetB >= 0);
2413 vassert(!hregIsVirtual(rreg));
sewardj6c299f32009-12-31 18:00:12 +00002414 vassert(mode64 == False);
2415 *i1 = *i2 = NULL;
2416 rclass = hregClass(rreg);
2417 switch (rclass) {
2418 case HRcInt32:
2419 vassert(offsetB <= 4095);
2420 *i1 = ARMInstr_LdSt32( True/*isLoad*/,
2421 rreg,
2422 ARMAMode1_RI(hregARM_R8(), offsetB) );
2423 return;
2424 case HRcFlt32:
2425 case HRcFlt64: {
2426 HReg r8 = hregARM_R8(); /* baseblock */
2427 HReg r12 = hregARM_R12(); /* spill temp */
2428 HReg base = r8;
2429 vassert(0 == (offsetB & 3));
2430 if (offsetB >= 1024) {
sewardje30973c2010-09-01 10:25:51 +00002431 Int offsetKB = offsetB / 1024;
2432 /* r12 = r8 + (1024 * offsetKB) */
sewardj6c299f32009-12-31 18:00:12 +00002433 *i1 = ARMInstr_Alu(ARMalu_ADD, r12, r8,
sewardje30973c2010-09-01 10:25:51 +00002434 ARMRI84_I84(offsetKB, 11));
2435 offsetB -= (1024 * offsetKB);
sewardj6c299f32009-12-31 18:00:12 +00002436 base = r12;
2437 }
2438 vassert(offsetB <= 1020);
2439 if (rclass == HRcFlt32) {
2440 *i2 = ARMInstr_VLdStS( True/*isLoad*/,
2441 rreg,
2442 mkARMAModeV(base, offsetB) );
2443 } else {
2444 *i2 = ARMInstr_VLdStD( True/*isLoad*/,
2445 rreg,
2446 mkARMAModeV(base, offsetB) );
2447 }
2448 return;
2449 }
sewardj6c60b322010-08-22 12:48:28 +00002450 case HRcVec128: {
2451 HReg r8 = hregARM_R8();
2452 HReg r12 = hregARM_R12();
2453 *i1 = ARMInstr_Add32(r12, r8, offsetB);
2454 *i2 = ARMInstr_NLdStQ(True, rreg, mkARMAModeN_R(r12));
2455 return;
2456 }
2457 default:
sewardj6c299f32009-12-31 18:00:12 +00002458 ppHRegClass(rclass);
2459 vpanic("genReload_ARM: unimplemented regclass");
cerion82edbb32004-12-16 14:06:34 +00002460 }
2461}
2462
2463
2464/* Emit an instruction into buf and return the number of bytes used.
2465 Note that buf is not the insn's final place, and therefore it is
2466 imperative to emit position-independent code. */
2467
sewardj6c299f32009-12-31 18:00:12 +00002468static inline UChar iregNo ( HReg r )
2469{
2470 UInt n;
2471 vassert(hregClass(r) == HRcInt32);
2472 vassert(!hregIsVirtual(r));
2473 n = hregNumber(r);
2474 vassert(n <= 15);
2475 return toUChar(n);
cerion82edbb32004-12-16 14:06:34 +00002476}
2477
sewardj6c299f32009-12-31 18:00:12 +00002478static inline UChar dregNo ( HReg r )
2479{
2480 UInt n;
sewardj6c60b322010-08-22 12:48:28 +00002481 if (hregClass(r) != HRcFlt64)
2482 ppHRegClass(hregClass(r));
sewardj6c299f32009-12-31 18:00:12 +00002483 vassert(hregClass(r) == HRcFlt64);
2484 vassert(!hregIsVirtual(r));
2485 n = hregNumber(r);
sewardj6c60b322010-08-22 12:48:28 +00002486 vassert(n <= 31);
sewardj6c299f32009-12-31 18:00:12 +00002487 return toUChar(n);
2488}
2489
2490static inline UChar fregNo ( HReg r )
2491{
2492 UInt n;
2493 vassert(hregClass(r) == HRcFlt32);
2494 vassert(!hregIsVirtual(r));
2495 n = hregNumber(r);
2496 vassert(n <= 31);
2497 return toUChar(n);
2498}
2499
sewardj6c60b322010-08-22 12:48:28 +00002500static inline UChar qregNo ( HReg r )
2501{
2502 UInt n;
2503 vassert(hregClass(r) == HRcVec128);
2504 vassert(!hregIsVirtual(r));
2505 n = hregNumber(r);
2506 vassert(n <= 15);
2507 return toUChar(n);
2508}
2509
sewardj6c299f32009-12-31 18:00:12 +00002510#define BITS4(zzb3,zzb2,zzb1,zzb0) \
2511 (((zzb3) << 3) | ((zzb2) << 2) | ((zzb1) << 1) | (zzb0))
2512#define X0000 BITS4(0,0,0,0)
2513#define X0001 BITS4(0,0,0,1)
2514#define X0010 BITS4(0,0,1,0)
2515#define X0011 BITS4(0,0,1,1)
2516#define X0100 BITS4(0,1,0,0)
2517#define X0101 BITS4(0,1,0,1)
2518#define X0110 BITS4(0,1,1,0)
2519#define X0111 BITS4(0,1,1,1)
2520#define X1000 BITS4(1,0,0,0)
2521#define X1001 BITS4(1,0,0,1)
2522#define X1010 BITS4(1,0,1,0)
2523#define X1011 BITS4(1,0,1,1)
2524#define X1100 BITS4(1,1,0,0)
2525#define X1101 BITS4(1,1,0,1)
2526#define X1110 BITS4(1,1,1,0)
2527#define X1111 BITS4(1,1,1,1)
2528
2529#define XXXXX___(zzx7,zzx6,zzx5,zzx4,zzx3) \
2530 ((((zzx7) & 0xF) << 28) | (((zzx6) & 0xF) << 24) | \
2531 (((zzx5) & 0xF) << 20) | (((zzx4) & 0xF) << 16) | \
2532 (((zzx3) & 0xF) << 12))
2533
2534#define XXXXXX__(zzx7,zzx6,zzx5,zzx4,zzx3,zzx2) \
2535 ((((zzx7) & 0xF) << 28) | (((zzx6) & 0xF) << 24) | \
2536 (((zzx5) & 0xF) << 20) | (((zzx4) & 0xF) << 16) | \
2537 (((zzx3) & 0xF) << 12) | (((zzx2) & 0xF) << 8))
2538
2539#define XXXXX__X(zzx7,zzx6,zzx5,zzx4,zzx3,zzx0) \
2540 ((((zzx7) & 0xF) << 28) | (((zzx6) & 0xF) << 24) | \
2541 (((zzx5) & 0xF) << 20) | (((zzx4) & 0xF) << 16) | \
2542 (((zzx3) & 0xF) << 12) | (((zzx0) & 0xF) << 0))
2543
2544#define XXX___XX(zzx7,zzx6,zzx5,zzx1,zzx0) \
2545 ((((zzx7) & 0xF) << 28) | (((zzx6) & 0xF) << 24) | \
2546 (((zzx5) & 0xF) << 20) | (((zzx1) & 0xF) << 4) | \
2547 (((zzx0) & 0xF) << 0))
2548
2549#define XXXXXXXX(zzx7,zzx6,zzx5,zzx4,zzx3,zzx2,zzx1,zzx0) \
2550 ((((zzx7) & 0xF) << 28) | (((zzx6) & 0xF) << 24) | \
2551 (((zzx5) & 0xF) << 20) | (((zzx4) & 0xF) << 16) | \
2552 (((zzx3) & 0xF) << 12) | (((zzx2) & 0xF) << 8) | \
2553 (((zzx1) & 0xF) << 4) | (((zzx0) & 0xF) << 0))
2554
2555/* Generate a skeletal insn that involves an a RI84 shifter operand.
2556 Returns a word which is all zeroes apart from bits 25 and 11..0,
2557 since it is those that encode the shifter operand (at least to the
2558 extent that we care about it.) */
2559static UInt skeletal_RI84 ( ARMRI84* ri )
2560{
2561 UInt instr;
2562 if (ri->tag == ARMri84_I84) {
2563 vassert(0 == (ri->ARMri84.I84.imm4 & ~0x0F));
2564 vassert(0 == (ri->ARMri84.I84.imm8 & ~0xFF));
2565 instr = 1 << 25;
2566 instr |= (ri->ARMri84.I84.imm4 << 8);
2567 instr |= ri->ARMri84.I84.imm8;
2568 } else {
2569 instr = 0 << 25;
2570 instr |= iregNo(ri->ARMri84.R.reg);
2571 }
2572 return instr;
2573}
2574
2575/* Ditto for RI5. Resulting word is zeroes apart from bit 4 and bits
2576 11..7. */
2577static UInt skeletal_RI5 ( ARMRI5* ri )
2578{
2579 UInt instr;
2580 if (ri->tag == ARMri5_I5) {
2581 UInt imm5 = ri->ARMri5.I5.imm5;
2582 vassert(imm5 >= 1 && imm5 <= 31);
2583 instr = 0 << 4;
2584 instr |= imm5 << 7;
2585 } else {
2586 instr = 1 << 4;
2587 instr |= iregNo(ri->ARMri5.R.reg) << 8;
2588 }
2589 return instr;
2590}
2591
2592
2593/* Get an immediate into a register, using only that
2594 register. (very lame..) */
2595static UInt* imm32_to_iregNo ( UInt* p, Int rD, UInt imm32 )
2596{
2597 UInt instr;
2598 vassert(rD >= 0 && rD <= 14); // r15 not good to mess with!
2599#if 0
2600 if (0 == (imm32 & ~0xFF)) {
2601 /* mov with a immediate shifter operand of (0, imm32) (??) */
2602 instr = XXXXXX__(X1110,X0011,X1010,X0000,rD,X0000);
2603 instr |= imm32;
2604 *p++ = instr;
2605 } else {
2606 // this is very bad; causes Dcache pollution
2607 // ldr rD, [pc]
2608 instr = XXXXX___(X1110,X0101,X1001,X1111,rD);
2609 *p++ = instr;
2610 // b .+8
2611 instr = 0xEA000000;
2612 *p++ = instr;
2613 // .word imm32
2614 *p++ = imm32;
2615 }
2616#else
sewardj6c60b322010-08-22 12:48:28 +00002617 if (VEX_ARM_ARCHLEVEL(arm_hwcaps) > 6) {
2618 /* Generate movw rD, #low16. Then, if the high 16 are
2619 nonzero, generate movt rD, #high16. */
2620 UInt lo16 = imm32 & 0xFFFF;
2621 UInt hi16 = (imm32 >> 16) & 0xFFFF;
2622 instr = XXXXXXXX(0xE, 0x3, 0x0, (lo16 >> 12) & 0xF, rD,
2623 (lo16 >> 8) & 0xF, (lo16 >> 4) & 0xF,
2624 lo16 & 0xF);
sewardj6c299f32009-12-31 18:00:12 +00002625 *p++ = instr;
sewardj6c60b322010-08-22 12:48:28 +00002626 if (hi16 != 0) {
2627 instr = XXXXXXXX(0xE, 0x3, 0x4, (hi16 >> 12) & 0xF, rD,
2628 (hi16 >> 8) & 0xF, (hi16 >> 4) & 0xF,
2629 hi16 & 0xF);
2630 *p++ = instr;
2631 }
2632 } else {
2633 UInt imm, rot;
2634 UInt op = X1010;
2635 UInt rN = 0;
2636 if ((imm32 & 0xFF) || (imm32 == 0)) {
2637 imm = imm32 & 0xFF;
2638 rot = 0;
2639 instr = XXXXXXXX(0xE, 0x3, op, rN, rD, rot, imm >> 4, imm & 0xF);
2640 *p++ = instr;
2641 op = X1000;
2642 rN = rD;
2643 }
2644 if (imm32 & 0xFF000000) {
2645 imm = (imm32 >> 24) & 0xFF;
2646 rot = 4;
2647 instr = XXXXXXXX(0xE, 0x3, op, rN, rD, rot, imm >> 4, imm & 0xF);
2648 *p++ = instr;
2649 op = X1000;
2650 rN = rD;
2651 }
2652 if (imm32 & 0xFF0000) {
2653 imm = (imm32 >> 16) & 0xFF;
2654 rot = 8;
2655 instr = XXXXXXXX(0xE, 0x3, op, rN, rD, rot, imm >> 4, imm & 0xF);
2656 *p++ = instr;
2657 op = X1000;
2658 rN = rD;
2659 }
2660 if (imm32 & 0xFF00) {
2661 imm = (imm32 >> 8) & 0xFF;
2662 rot = 12;
2663 instr = XXXXXXXX(0xE, 0x3, op, rN, rD, rot, imm >> 4, imm & 0xF);
2664 *p++ = instr;
2665 op = X1000;
2666 rN = rD;
2667 }
sewardj6c299f32009-12-31 18:00:12 +00002668 }
2669#endif
2670 return p;
2671}
2672
2673
2674Int emit_ARMInstr ( UChar* buf, Int nbuf, ARMInstr* i,
2675 Bool mode64, void* dispatch )
2676{
2677 UInt* p = (UInt*)buf;
2678 vassert(nbuf >= 32);
2679 vassert(mode64 == False);
2680 vassert(0 == (((HWord)buf) & 3));
2681 /* since we branch to lr(r13) to get back to dispatch: */
2682 vassert(dispatch == NULL);
2683
2684 switch (i->tag) {
2685 case ARMin_Alu: {
2686 UInt instr, subopc;
2687 UInt rD = iregNo(i->ARMin.Alu.dst);
2688 UInt rN = iregNo(i->ARMin.Alu.argL);
2689 ARMRI84* argR = i->ARMin.Alu.argR;
2690 switch (i->ARMin.Alu.op) {
2691 case ARMalu_ADDS: /* fallthru */
2692 case ARMalu_ADD: subopc = X0100; break;
2693 case ARMalu_ADC: subopc = X0101; break;
2694 case ARMalu_SUBS: /* fallthru */
2695 case ARMalu_SUB: subopc = X0010; break;
2696 case ARMalu_SBC: subopc = X0110; break;
2697 case ARMalu_AND: subopc = X0000; break;
2698 case ARMalu_BIC: subopc = X1110; break;
2699 case ARMalu_OR: subopc = X1100; break;
2700 case ARMalu_XOR: subopc = X0001; break;
2701 default: goto bad;
2702 }
2703 instr = skeletal_RI84(argR);
2704 instr |= XXXXX___(X1110, (1 & (subopc >> 3)),
2705 (subopc << 1) & 0xF, rN, rD);
sewardj6c60b322010-08-22 12:48:28 +00002706 if (i->ARMin.Alu.op == ARMalu_ADDS
2707 || i->ARMin.Alu.op == ARMalu_SUBS) {
sewardj6c299f32009-12-31 18:00:12 +00002708 instr |= 1<<20; /* set the S bit */
2709 }
2710 *p++ = instr;
2711 goto done;
2712 }
2713 case ARMin_Shift: {
2714 UInt instr, subopc;
2715 HReg rD = iregNo(i->ARMin.Shift.dst);
2716 HReg rM = iregNo(i->ARMin.Shift.argL);
2717 ARMRI5* argR = i->ARMin.Shift.argR;
2718 switch (i->ARMin.Shift.op) {
2719 case ARMsh_SHL: subopc = X0000; break;
2720 case ARMsh_SHR: subopc = X0001; break;
2721 case ARMsh_SAR: subopc = X0010; break;
2722 default: goto bad;
2723 }
2724 instr = skeletal_RI5(argR);
2725 instr |= XXXXX__X(X1110,X0001,X1010,X0000,rD, /* _ _ */ rM);
2726 instr |= (subopc & 3) << 5;
2727 *p++ = instr;
2728 goto done;
2729 }
2730 case ARMin_Unary: {
2731 UInt instr;
2732 HReg rDst = iregNo(i->ARMin.Unary.dst);
2733 HReg rSrc = iregNo(i->ARMin.Unary.src);
2734 switch (i->ARMin.Unary.op) {
2735 case ARMun_CLZ:
2736 instr = XXXXXXXX(X1110,X0001,X0110,X1111,
2737 rDst,X1111,X0001,rSrc);
2738 *p++ = instr;
2739 goto done;
2740 case ARMun_NEG: /* RSB rD,rS,#0 */
2741 instr = XXXXX___(X1110,0x2,0x6,rSrc,rDst);
2742 *p++ = instr;
2743 goto done;
2744 case ARMun_NOT: {
2745 UInt subopc = X1111; /* MVN */
2746 instr = rSrc;
2747 instr |= XXXXX___(X1110, (1 & (subopc >> 3)),
2748 (subopc << 1) & 0xF, 0, rDst);
2749 *p++ = instr;
2750 goto done;
2751 }
2752 default:
2753 break;
2754 }
2755 goto bad;
2756 }
2757 case ARMin_CmpOrTst: {
2758 UInt instr = skeletal_RI84(i->ARMin.CmpOrTst.argR);
2759 UInt subopc = i->ARMin.CmpOrTst.isCmp ? X1010 : X1000;
2760 UInt SBZ = 0;
2761 instr |= XXXXX___(X1110, (1 & (subopc >> 3)),
2762 ((subopc << 1) & 0xF) | 1,
2763 i->ARMin.CmpOrTst.argL, SBZ );
2764 *p++ = instr;
2765 goto done;
2766 }
2767 case ARMin_Mov: {
2768 UInt instr = skeletal_RI84(i->ARMin.Mov.src);
2769 UInt subopc = X1101; /* MOV */
2770 UInt SBZ = 0;
2771 instr |= XXXXX___(X1110, (1 & (subopc >> 3)),
2772 (subopc << 1) & 0xF, SBZ, i->ARMin.Mov.dst);
2773 *p++ = instr;
2774 goto done;
2775 }
2776 case ARMin_Imm32: {
2777 p = imm32_to_iregNo( (UInt*)p, iregNo(i->ARMin.Imm32.dst),
2778 i->ARMin.Imm32.imm32 );
2779 goto done;
2780 }
2781 case ARMin_LdSt32:
2782 case ARMin_LdSt8U: {
2783 UInt bL, bB;
2784 HReg rD;
2785 ARMAMode1* am;
2786 if (i->tag == ARMin_LdSt32) {
2787 bB = 0;
2788 bL = i->ARMin.LdSt32.isLoad ? 1 : 0;
2789 am = i->ARMin.LdSt32.amode;
2790 rD = i->ARMin.LdSt32.rD;
2791 } else {
2792 bB = 1;
2793 bL = i->ARMin.LdSt8U.isLoad ? 1 : 0;
2794 am = i->ARMin.LdSt8U.amode;
2795 rD = i->ARMin.LdSt8U.rD;
2796 }
2797 if (am->tag == ARMam1_RI) {
2798 Int simm12;
2799 UInt instr, bP;
2800 if (am->ARMam1.RI.simm13 < 0) {
2801 bP = 0;
2802 simm12 = -am->ARMam1.RI.simm13;
2803 } else {
2804 bP = 1;
2805 simm12 = am->ARMam1.RI.simm13;
2806 }
2807 vassert(simm12 >= 0 && simm12 <= 4095);
2808 instr = XXXXX___(X1110,X0101,BITS4(bP,bB,0,bL),
2809 iregNo(am->ARMam1.RI.reg),
2810 iregNo(rD));
2811 instr |= simm12;
2812 *p++ = instr;
2813 goto done;
2814 } else {
2815 // RR case
2816 goto bad;
2817 }
2818 }
2819 case ARMin_LdSt16: {
2820 HReg rD = i->ARMin.LdSt16.rD;
2821 UInt bS = i->ARMin.LdSt16.signedLoad ? 1 : 0;
2822 UInt bL = i->ARMin.LdSt16.isLoad ? 1 : 0;
2823 ARMAMode2* am = i->ARMin.LdSt16.amode;
2824 if (am->tag == ARMam2_RI) {
2825 HReg rN = am->ARMam2.RI.reg;
2826 Int simm8;
2827 UInt bP, imm8hi, imm8lo, instr;
2828 if (am->ARMam2.RI.simm9 < 0) {
2829 bP = 0;
2830 simm8 = -am->ARMam2.RI.simm9;
2831 } else {
2832 bP = 1;
2833 simm8 = am->ARMam2.RI.simm9;
2834 }
2835 vassert(simm8 >= 0 && simm8 <= 255);
2836 imm8hi = (simm8 >> 4) & 0xF;
2837 imm8lo = simm8 & 0xF;
2838 vassert(!(bL == 0 && bS == 1)); // "! signed store"
2839 /**/ if (bL == 0 && bS == 0) {
2840 // strh
2841 instr = XXXXXXXX(X1110,X0001, BITS4(bP,1,0,0), iregNo(rN),
2842 iregNo(rD), imm8hi, X1011, imm8lo);
2843 *p++ = instr;
2844 goto done;
2845 }
2846 else if (bL == 1 && bS == 0) {
2847 // ldrh
2848 instr = XXXXXXXX(X1110,X0001, BITS4(bP,1,0,1), iregNo(rN),
2849 iregNo(rD), imm8hi, X1011, imm8lo);
2850 *p++ = instr;
2851 goto done;
2852 }
2853 else if (bL == 1 && bS == 1) {
2854 goto bad;
2855 }
2856 else vassert(0); // ill-constructed insn
2857 } else {
2858 // RR case
2859 goto bad;
2860 }
2861 }
2862 case ARMin_Ld8S:
2863 goto bad;
2864 case ARMin_Goto: {
2865 UInt instr;
2866 IRJumpKind jk = i->ARMin.Goto.jk;
2867 ARMCondCode cond = i->ARMin.Goto.cond;
2868 UInt rnext = iregNo(i->ARMin.Goto.gnext);
2869 Int trc = -1;
2870 switch (jk) {
2871 case Ijk_Ret: case Ijk_Call: case Ijk_Boring:
2872 break; /* no need to set GST in these common cases */
2873 case Ijk_ClientReq:
2874 trc = VEX_TRC_JMP_CLIENTREQ; break;
2875 case Ijk_Sys_int128:
2876 case Ijk_Sys_int129:
2877 case Ijk_Sys_int130:
2878 case Ijk_Yield:
2879 case Ijk_EmWarn:
2880 case Ijk_MapFail:
2881 goto unhandled_jk;
2882 case Ijk_NoDecode:
2883 trc = VEX_TRC_JMP_NODECODE; break;
2884 case Ijk_TInval:
2885 trc = VEX_TRC_JMP_TINVAL; break;
2886 case Ijk_NoRedir:
2887 trc = VEX_TRC_JMP_NOREDIR; break;
2888 case Ijk_Sys_sysenter:
2889 case Ijk_SigTRAP:
2890 case Ijk_SigSEGV:
2891 goto unhandled_jk;
2892 case Ijk_Sys_syscall:
2893 trc = VEX_TRC_JMP_SYS_SYSCALL; break;
2894 unhandled_jk:
2895 default:
2896 goto bad;
2897 }
2898 if (trc != -1) {
2899 // mov{cond} r8, #trc
2900 vassert(trc >= 0 && trc <= 255);
2901 instr = (cond << 28) | 0x03A08000 | (0xFF & (UInt)trc);
2902 *p++ = instr;
2903 }
2904 // mov{cond} r0, rnext
2905 if (rnext != 0) {
2906 instr = (cond << 28) | 0x01A00000 | rnext;
2907 *p++ = instr;
2908 }
2909 // bx{cond} r14
2910 instr =(cond << 28) | 0x012FFF1E;
2911 *p++ = instr;
2912 goto done;
2913 }
2914 case ARMin_CMov: {
2915 UInt instr = skeletal_RI84(i->ARMin.CMov.src);
2916 UInt subopc = X1101; /* MOV */
2917 UInt SBZ = 0;
2918 instr |= XXXXX___(i->ARMin.CMov.cond, (1 & (subopc >> 3)),
2919 (subopc << 1) & 0xF, SBZ, i->ARMin.CMov.dst);
2920 *p++ = instr;
2921 goto done;
2922 }
2923 case ARMin_Call: {
2924 UInt instr;
2925 /* Decide on a scratch reg used to hold to the call address.
2926 This has to be done as per the comments in getRegUsage. */
2927 Int scratchNo;
2928 switch (i->ARMin.Call.nArgRegs) {
2929 case 0: scratchNo = 0; break;
2930 case 1: scratchNo = 1; break;
2931 case 2: scratchNo = 2; break;
2932 case 3: scratchNo = 3; break;
2933 case 4: scratchNo = 11; break;
2934 default: vassert(0);
2935 }
2936 // r"scratchNo" = &target
2937 p = imm32_to_iregNo( (UInt*)p,
2938 scratchNo, (UInt)i->ARMin.Call.target );
2939 // blx{cond} r"scratchNo"
2940 instr = XXX___XX(i->ARMin.Call.cond, X0001, X0010, /*___*/
2941 X0011, scratchNo);
2942 instr |= 0xFFF << 8; // stick in the SBOnes
2943 *p++ = instr;
2944 goto done;
2945 }
2946 case ARMin_Mul: {
2947 /* E0000392 mul r0, r2, r3
2948 E0810392 umull r0(LO), r1(HI), r2, r3
2949 E0C10392 smull r0(LO), r1(HI), r2, r3
2950 */
2951 switch (i->ARMin.Mul.op) {
2952 case ARMmul_PLAIN: *p++ = 0xE0000392; goto done;
2953 case ARMmul_ZX: *p++ = 0xE0810392; goto done;
2954 case ARMmul_SX: *p++ = 0xE0C10392; goto done;
2955 default: vassert(0);
2956 }
2957 goto bad;
2958 }
2959 case ARMin_LdrEX: {
2960 /* E1910F9F ldrex r0, [r1]
2961 E1F10F9F ldrexh r0, [r1]
2962 E1D10F9F ldrexb r0, [r1]
2963 */
2964 switch (i->ARMin.LdrEX.szB) {
2965 case 4: *p++ = 0xE1910F9F; goto done;
2966 //case 2: *p++ = 0xE1F10F9F; goto done;
2967 case 1: *p++ = 0xE1D10F9F; goto done;
2968 default: break;
2969 }
2970 goto bad;
2971 }
2972 case ARMin_StrEX: {
2973 /* E1820F91 strex r0, r1, [r2]
2974 E1E20F91 strexh r0, r1, [r2]
2975 E1C20F91 strexb r0, r1, [r2]
2976 */
2977 switch (i->ARMin.StrEX.szB) {
2978 case 4: *p++ = 0xE1820F91; goto done;
2979 //case 2: *p++ = 0xE1E20F91; goto done;
2980 case 1: *p++ = 0xE1C20F91; goto done;
2981 default: break;
2982 }
2983 goto bad;
2984 }
2985 case ARMin_VLdStD: {
2986 UInt dD = dregNo(i->ARMin.VLdStD.dD);
2987 UInt rN = iregNo(i->ARMin.VLdStD.amode->reg);
2988 Int simm11 = i->ARMin.VLdStD.amode->simm11;
2989 UInt off8 = simm11 >= 0 ? simm11 : ((UInt)(-simm11));
2990 UInt bU = simm11 >= 0 ? 1 : 0;
2991 UInt bL = i->ARMin.VLdStD.isLoad ? 1 : 0;
2992 UInt insn;
2993 vassert(0 == (off8 & 3));
2994 off8 >>= 2;
2995 vassert(0 == (off8 & 0xFFFFFF00));
2996 insn = XXXXXX__(0xE,X1101,BITS4(bU,0,0,bL),rN,dD,X1011);
2997 insn |= off8;
2998 *p++ = insn;
2999 goto done;
3000 }
3001 case ARMin_VLdStS: {
3002 UInt fD = fregNo(i->ARMin.VLdStS.fD);
3003 UInt rN = iregNo(i->ARMin.VLdStS.amode->reg);
3004 Int simm11 = i->ARMin.VLdStS.amode->simm11;
3005 UInt off8 = simm11 >= 0 ? simm11 : ((UInt)(-simm11));
3006 UInt bU = simm11 >= 0 ? 1 : 0;
3007 UInt bL = i->ARMin.VLdStS.isLoad ? 1 : 0;
3008 UInt bD = fD & 1;
3009 UInt insn;
3010 vassert(0 == (off8 & 3));
3011 off8 >>= 2;
3012 vassert(0 == (off8 & 0xFFFFFF00));
3013 insn = XXXXXX__(0xE,X1101,BITS4(bU,bD,0,bL),rN, (fD >> 1), X1010);
3014 insn |= off8;
3015 *p++ = insn;
3016 goto done;
3017 }
3018 case ARMin_VAluD: {
3019 UInt dN = dregNo(i->ARMin.VAluD.argL);
3020 UInt dD = dregNo(i->ARMin.VAluD.dst);
3021 UInt dM = dregNo(i->ARMin.VAluD.argR);
3022 UInt pqrs = X1111; /* undefined */
3023 switch (i->ARMin.VAluD.op) {
3024 case ARMvfp_ADD: pqrs = X0110; break;
3025 case ARMvfp_SUB: pqrs = X0111; break;
3026 case ARMvfp_MUL: pqrs = X0100; break;
3027 case ARMvfp_DIV: pqrs = X1000; break;
3028 default: goto bad;
3029 }
3030 vassert(pqrs != X1111);
3031 UInt bP = (pqrs >> 3) & 1;
3032 UInt bQ = (pqrs >> 2) & 1;
3033 UInt bR = (pqrs >> 1) & 1;
3034 UInt bS = (pqrs >> 0) & 1;
3035 UInt insn = XXXXXXXX(0xE, X1110, BITS4(bP,0,bQ,bR), dN, dD,
3036 X1011, BITS4(0,bS,0,0), dM);
3037 *p++ = insn;
3038 goto done;
3039 }
3040 case ARMin_VAluS: {
3041 UInt dN = fregNo(i->ARMin.VAluS.argL);
3042 UInt dD = fregNo(i->ARMin.VAluS.dst);
3043 UInt dM = fregNo(i->ARMin.VAluS.argR);
3044 UInt bN = dN & 1;
3045 UInt bD = dD & 1;
3046 UInt bM = dM & 1;
3047 UInt pqrs = X1111; /* undefined */
3048 switch (i->ARMin.VAluS.op) {
3049 case ARMvfp_ADD: pqrs = X0110; break;
3050 case ARMvfp_SUB: pqrs = X0111; break;
3051 case ARMvfp_MUL: pqrs = X0100; break;
3052 case ARMvfp_DIV: pqrs = X1000; break;
3053 default: goto bad;
3054 }
3055 vassert(pqrs != X1111);
3056 UInt bP = (pqrs >> 3) & 1;
3057 UInt bQ = (pqrs >> 2) & 1;
3058 UInt bR = (pqrs >> 1) & 1;
3059 UInt bS = (pqrs >> 0) & 1;
3060 UInt insn = XXXXXXXX(0xE, X1110, BITS4(bP,bD,bQ,bR),
3061 (dN >> 1), (dD >> 1),
3062 X1010, BITS4(bN,bS,bM,0), (dM >> 1));
3063 *p++ = insn;
3064 goto done;
3065 }
3066 case ARMin_VUnaryD: {
3067 UInt dD = dregNo(i->ARMin.VUnaryD.dst);
3068 UInt dM = dregNo(i->ARMin.VUnaryD.src);
3069 UInt insn = 0;
3070 switch (i->ARMin.VUnaryD.op) {
3071 case ARMvfpu_COPY:
3072 insn = XXXXXXXX(0xE, X1110,X1011,X0000,dD,X1011,X0100,dM);
3073 break;
3074 case ARMvfpu_ABS:
3075 insn = XXXXXXXX(0xE, X1110,X1011,X0000,dD,X1011,X1100,dM);
3076 break;
3077 case ARMvfpu_NEG:
3078 insn = XXXXXXXX(0xE, X1110,X1011,X0001,dD,X1011,X0100,dM);
3079 break;
3080 case ARMvfpu_SQRT:
3081 insn = XXXXXXXX(0xE, X1110,X1011,X0001,dD,X1011,X1100,dM);
3082 break;
3083 default:
3084 goto bad;
3085 }
3086 *p++ = insn;
3087 goto done;
3088 }
3089 case ARMin_VUnaryS: {
3090 UInt fD = fregNo(i->ARMin.VUnaryS.dst);
3091 UInt fM = fregNo(i->ARMin.VUnaryS.src);
3092 UInt insn = 0;
3093 switch (i->ARMin.VUnaryS.op) {
3094 case ARMvfpu_COPY:
3095 insn = XXXXXXXX(0xE, X1110, BITS4(1,(fD & 1),1,1), X0000,
3096 (fD >> 1), X1010, BITS4(0,1,(fM & 1),0),
3097 (fM >> 1));
3098 break;
3099 case ARMvfpu_ABS:
3100 insn = XXXXXXXX(0xE, X1110, BITS4(1,(fD & 1),1,1), X0000,
3101 (fD >> 1), X1010, BITS4(1,1,(fM & 1),0),
3102 (fM >> 1));
3103 break;
3104 case ARMvfpu_NEG:
3105 insn = XXXXXXXX(0xE, X1110, BITS4(1,(fD & 1),1,1), X0001,
3106 (fD >> 1), X1010, BITS4(0,1,(fM & 1),0),
3107 (fM >> 1));
3108 break;
3109 case ARMvfpu_SQRT:
3110 insn = XXXXXXXX(0xE, X1110, BITS4(1,(fD & 1),1,1), X0001,
3111 (fD >> 1), X1010, BITS4(1,1,(fM & 1),0),
3112 (fM >> 1));
3113 break;
3114 default:
3115 goto bad;
3116 }
3117 *p++ = insn;
3118 goto done;
3119 }
3120 case ARMin_VCmpD: {
3121 UInt dD = dregNo(i->ARMin.VCmpD.argL);
3122 UInt dM = dregNo(i->ARMin.VCmpD.argR);
3123 UInt insn = XXXXXXXX(0xE, X1110, X1011, X0100, dD, X1011, X0100, dM);
3124 *p++ = insn; /* FCMPD dD, dM */
3125 *p++ = 0xEEF1FA10; /* FMSTAT */
3126 goto done;
3127 }
3128 case ARMin_VCMovD: {
3129 UInt cc = (UInt)i->ARMin.VCMovD.cond;
3130 UInt dD = dregNo(i->ARMin.VCMovD.dst);
3131 UInt dM = dregNo(i->ARMin.VCMovD.src);
3132 vassert(cc < 16 && cc != ARMcc_AL);
3133 UInt insn = XXXXXXXX(cc, X1110,X1011,X0000,dD,X1011,X0100,dM);
3134 *p++ = insn;
3135 goto done;
3136 }
3137 case ARMin_VCMovS: {
3138 UInt cc = (UInt)i->ARMin.VCMovS.cond;
3139 UInt fD = fregNo(i->ARMin.VCMovS.dst);
3140 UInt fM = fregNo(i->ARMin.VCMovS.src);
3141 vassert(cc < 16 && cc != ARMcc_AL);
3142 UInt insn = XXXXXXXX(cc, X1110, BITS4(1,(fD & 1),1,1),
3143 X0000,(fD >> 1),X1010,
3144 BITS4(0,1,(fM & 1),0), (fM >> 1));
3145 *p++ = insn;
3146 goto done;
3147 }
3148 case ARMin_VCvtSD: {
3149 if (i->ARMin.VCvtSD.sToD) {
3150 UInt dD = dregNo(i->ARMin.VCvtSD.dst);
3151 UInt fM = fregNo(i->ARMin.VCvtSD.src);
3152 UInt insn = XXXXXXXX(0xE, X1110, X1011, X0111, dD, X1010,
3153 BITS4(1,1, (fM & 1), 0),
3154 (fM >> 1));
3155 *p++ = insn;
3156 goto done;
3157 } else {
3158 UInt fD = fregNo(i->ARMin.VCvtSD.dst);
3159 UInt dM = dregNo(i->ARMin.VCvtSD.src);
3160 UInt insn = XXXXXXXX(0xE, X1110, BITS4(1,(fD & 1),1,1),
3161 X0111, (fD >> 1),
3162 X1011, X1100, dM);
3163 *p++ = insn;
3164 goto done;
3165 }
3166 goto bad;
3167 }
3168 case ARMin_VXferD: {
3169 UInt dD = dregNo(i->ARMin.VXferD.dD);
3170 UInt rHi = iregNo(i->ARMin.VXferD.rHi);
3171 UInt rLo = iregNo(i->ARMin.VXferD.rLo);
3172 /* vmov dD, rLo, rHi is
3173 E C 4 rHi rLo B (0,0,dD[4],1) dD[3:0]
3174 vmov rLo, rHi, dD is
3175 E C 5 rHi rLo B (0,0,dD[4],1) dD[3:0]
3176 */
3177 UInt insn
3178 = XXXXXXXX(0xE, 0xC, i->ARMin.VXferD.toD ? 4 : 5,
3179 rHi, rLo, 0xB,
3180 BITS4(0,0, ((dD >> 4) & 1), 1), (dD & 0xF));
3181 *p++ = insn;
3182 goto done;
3183 }
3184 case ARMin_VXferS: {
3185 UInt fD = fregNo(i->ARMin.VXferS.fD);
3186 UInt rLo = iregNo(i->ARMin.VXferS.rLo);
3187 /* vmov fD, rLo is
3188 E E 0 fD[4:1] rLo A (fD[0],0,0,1) 0
3189 vmov rLo, fD is
3190 E E 1 fD[4:1] rLo A (fD[0],0,0,1) 0
3191 */
3192 UInt insn
3193 = XXXXXXXX(0xE, 0xE, i->ARMin.VXferS.toS ? 0 : 1,
3194 (fD >> 1) & 0xF, rLo, 0xA,
3195 BITS4((fD & 1),0,0,1), 0);
3196 *p++ = insn;
3197 goto done;
3198 }
3199 case ARMin_VCvtID: {
3200 Bool iToD = i->ARMin.VCvtID.iToD;
3201 Bool syned = i->ARMin.VCvtID.syned;
3202 if (iToD && syned) {
3203 // FSITOD: I32S-in-freg to F64-in-dreg
3204 UInt regF = fregNo(i->ARMin.VCvtID.src);
3205 UInt regD = dregNo(i->ARMin.VCvtID.dst);
3206 UInt insn = XXXXXXXX(0xE, X1110, X1011, X1000, regD,
3207 X1011, BITS4(1,1,(regF & 1),0),
3208 (regF >> 1) & 0xF);
3209 *p++ = insn;
3210 goto done;
3211 }
3212 if (iToD && (!syned)) {
3213 // FUITOD: I32U-in-freg to F64-in-dreg
3214 UInt regF = fregNo(i->ARMin.VCvtID.src);
3215 UInt regD = dregNo(i->ARMin.VCvtID.dst);
3216 UInt insn = XXXXXXXX(0xE, X1110, X1011, X1000, regD,
3217 X1011, BITS4(0,1,(regF & 1),0),
3218 (regF >> 1) & 0xF);
3219 *p++ = insn;
3220 goto done;
3221 }
3222 if ((!iToD) && syned) {
3223 // FTOSID: F64-in-dreg to I32S-in-freg
3224 UInt regD = dregNo(i->ARMin.VCvtID.src);
3225 UInt regF = fregNo(i->ARMin.VCvtID.dst);
3226 UInt insn = XXXXXXXX(0xE, X1110, BITS4(1,(regF & 1),1,1),
3227 X1101, (regF >> 1) & 0xF,
3228 X1011, X0100, regD);
3229 *p++ = insn;
3230 goto done;
3231 }
3232 if ((!iToD) && (!syned)) {
3233 // FTOUID: F64-in-dreg to I32U-in-freg
3234 UInt regD = dregNo(i->ARMin.VCvtID.src);
3235 UInt regF = fregNo(i->ARMin.VCvtID.dst);
3236 UInt insn = XXXXXXXX(0xE, X1110, BITS4(1,(regF & 1),1,1),
3237 X1100, (regF >> 1) & 0xF,
3238 X1011, X0100, regD);
3239 *p++ = insn;
3240 goto done;
3241 }
3242 /*UNREACHED*/
3243 vassert(0);
3244 }
3245 case ARMin_FPSCR: {
3246 Bool toFPSCR = i->ARMin.FPSCR.toFPSCR;
3247 HReg iReg = iregNo(i->ARMin.FPSCR.iReg);
3248 if (toFPSCR) {
3249 /* fmxr fpscr, iReg is EEE1 iReg A10 */
3250 *p++ = 0xEEE10A10 | ((iReg & 0xF) << 12);
3251 goto done;
3252 }
3253 goto bad; // FPSCR -> iReg case currently ATC
3254 }
sewardj412098c2010-05-04 08:48:43 +00003255 case ARMin_MFence: {
3256 *p++ = 0xEE070F9A; /* mcr 15,0,r0,c7,c10,4 (DSB) */
3257 *p++ = 0xEE070FBA; /* mcr 15,0,r0,c7,c10,5 (DMB) */
3258 *p++ = 0xEE070F95; /* mcr 15,0,r0,c7,c5,4 (ISB) */
3259 goto done;
3260 }
sewardj6c60b322010-08-22 12:48:28 +00003261 case ARMin_NLdStQ: {
3262 UInt regD = qregNo(i->ARMin.NLdStQ.dQ) << 1;
3263 UInt regN, regM;
3264 UInt D = regD >> 4;
3265 UInt bL = i->ARMin.NLdStQ.isLoad ? 1 : 0;
3266 UInt insn;
3267 vassert(hregClass(i->ARMin.NLdStQ.dQ) == HRcVec128);
3268 regD &= 0xF;
3269 if (i->ARMin.NLdStQ.amode->tag == ARMamN_RR) {
3270 regN = iregNo(i->ARMin.NLdStQ.amode->ARMamN.RR.rN);
3271 regM = iregNo(i->ARMin.NLdStQ.amode->ARMamN.RR.rM);
3272 } else {
3273 regN = iregNo(i->ARMin.NLdStQ.amode->ARMamN.R.rN);
3274 regM = 15;
3275 }
3276 insn = XXXXXXXX(0xF, X0100, BITS4(0, D, bL, 0),
3277 regN, regD, X1010, X1000, regM);
3278 *p++ = insn;
3279 goto done;
3280 }
3281 case ARMin_NLdStD: {
3282 UInt regD = dregNo(i->ARMin.NLdStD.dD);
3283 UInt regN, regM;
3284 UInt D = regD >> 4;
3285 UInt bL = i->ARMin.NLdStD.isLoad ? 1 : 0;
3286 UInt insn;
3287 vassert(hregClass(i->ARMin.NLdStD.dD) == HRcFlt64);
3288 regD &= 0xF;
3289 if (i->ARMin.NLdStD.amode->tag == ARMamN_RR) {
3290 regN = iregNo(i->ARMin.NLdStD.amode->ARMamN.RR.rN);
3291 regM = iregNo(i->ARMin.NLdStD.amode->ARMamN.RR.rM);
3292 } else {
3293 regN = iregNo(i->ARMin.NLdStD.amode->ARMamN.R.rN);
3294 regM = 15;
3295 }
3296 insn = XXXXXXXX(0xF, X0100, BITS4(0, D, bL, 0),
3297 regN, regD, X0111, X1000, regM);
3298 *p++ = insn;
3299 goto done;
3300 }
3301 case ARMin_NUnaryS: {
3302 UInt Q = i->ARMin.NUnaryS.Q ? 1 : 0;
3303 UInt regD, D;
3304 UInt regM, M;
3305 UInt size = i->ARMin.NUnaryS.size;
3306 UInt insn;
3307 UInt opc, opc1, opc2;
3308 switch (i->ARMin.NUnaryS.op) {
sewardj6aa87a62010-10-06 20:34:53 +00003309 case ARMneon_VDUP:
sewardj6c60b322010-08-22 12:48:28 +00003310 if (i->ARMin.NUnaryS.size >= 16)
3311 goto bad;
3312 if (i->ARMin.NUnaryS.dst->tag != ARMNRS_Reg)
3313 goto bad;
3314 if (i->ARMin.NUnaryS.src->tag != ARMNRS_Scalar)
3315 goto bad;
3316 regD = (hregClass(i->ARMin.NUnaryS.dst->reg) == HRcVec128)
3317 ? (qregNo(i->ARMin.NUnaryS.dst->reg) << 1)
3318 : dregNo(i->ARMin.NUnaryS.dst->reg);
3319 regM = (hregClass(i->ARMin.NUnaryS.src->reg) == HRcVec128)
3320 ? (qregNo(i->ARMin.NUnaryS.src->reg) << 1)
3321 : dregNo(i->ARMin.NUnaryS.src->reg);
3322 D = regD >> 4;
3323 M = regM >> 4;
3324 regD &= 0xf;
3325 regM &= 0xf;
3326 insn = XXXXXXXX(0xF, X0011, BITS4(1,D,1,1),
3327 (i->ARMin.NUnaryS.size & 0xf), regD,
3328 X1100, BITS4(0,Q,M,0), regM);
3329 *p++ = insn;
sewardj6aa87a62010-10-06 20:34:53 +00003330 goto done;
sewardj6c60b322010-08-22 12:48:28 +00003331 case ARMneon_SETELEM:
3332 regD = Q ? (qregNo(i->ARMin.NUnaryS.dst->reg) << 1) :
3333 dregNo(i->ARMin.NUnaryS.dst->reg);
3334 regM = iregNo(i->ARMin.NUnaryS.src->reg);
3335 M = regM >> 4;
3336 D = regD >> 4;
3337 regM &= 0xF;
3338 regD &= 0xF;
3339 if (i->ARMin.NUnaryS.dst->tag != ARMNRS_Scalar)
3340 goto bad;
3341 switch (size) {
3342 case 0:
3343 if (i->ARMin.NUnaryS.dst->index > 7)
3344 goto bad;
3345 opc = X1000 | i->ARMin.NUnaryS.dst->index;
3346 break;
3347 case 1:
3348 if (i->ARMin.NUnaryS.dst->index > 3)
3349 goto bad;
3350 opc = X0001 | (i->ARMin.NUnaryS.dst->index << 1);
3351 break;
3352 case 2:
3353 if (i->ARMin.NUnaryS.dst->index > 1)
3354 goto bad;
3355 opc = X0000 | (i->ARMin.NUnaryS.dst->index << 2);
3356 break;
3357 default:
3358 goto bad;
3359 }
3360 opc1 = (opc >> 2) & 3;
3361 opc2 = opc & 3;
3362 insn = XXXXXXXX(0xE, X1110, BITS4(0,(opc1 >> 1),(opc1 & 1),0),
3363 regD, regM, X1011,
3364 BITS4(D,(opc2 >> 1),(opc2 & 1),1), X0000);
3365 *p++ = insn;
3366 goto done;
3367 case ARMneon_GETELEMU:
3368 regM = Q ? (qregNo(i->ARMin.NUnaryS.src->reg) << 1) :
3369 dregNo(i->ARMin.NUnaryS.src->reg);
3370 regD = iregNo(i->ARMin.NUnaryS.dst->reg);
3371 M = regM >> 4;
3372 D = regD >> 4;
3373 regM &= 0xF;
3374 regD &= 0xF;
3375 if (i->ARMin.NUnaryS.src->tag != ARMNRS_Scalar)
3376 goto bad;
3377 switch (size) {
3378 case 0:
3379 if (Q && i->ARMin.NUnaryS.src->index > 7) {
3380 regM++;
3381 i->ARMin.NUnaryS.src->index -= 8;
3382 }
3383 if (i->ARMin.NUnaryS.src->index > 7)
3384 goto bad;
3385 opc = X1000 | i->ARMin.NUnaryS.src->index;
3386 break;
3387 case 1:
3388 if (Q && i->ARMin.NUnaryS.src->index > 3) {
3389 regM++;
3390 i->ARMin.NUnaryS.src->index -= 4;
3391 }
3392 if (i->ARMin.NUnaryS.src->index > 3)
3393 goto bad;
3394 opc = X0001 | (i->ARMin.NUnaryS.src->index << 1);
3395 break;
3396 case 2:
3397 goto bad;
3398 default:
3399 goto bad;
3400 }
3401 opc1 = (opc >> 2) & 3;
3402 opc2 = opc & 3;
3403 insn = XXXXXXXX(0xE, X1110, BITS4(1,(opc1 >> 1),(opc1 & 1),1),
3404 regM, regD, X1011,
3405 BITS4(M,(opc2 >> 1),(opc2 & 1),1), X0000);
3406 *p++ = insn;
3407 goto done;
3408 case ARMneon_GETELEMS:
3409 regM = Q ? (qregNo(i->ARMin.NUnaryS.src->reg) << 1) :
3410 dregNo(i->ARMin.NUnaryS.src->reg);
3411 regD = iregNo(i->ARMin.NUnaryS.dst->reg);
3412 M = regM >> 4;
3413 D = regD >> 4;
3414 regM &= 0xF;
3415 regD &= 0xF;
3416 if (i->ARMin.NUnaryS.src->tag != ARMNRS_Scalar)
3417 goto bad;
3418 switch (size) {
3419 case 0:
3420 if (Q && i->ARMin.NUnaryS.src->index > 7) {
3421 regM++;
3422 i->ARMin.NUnaryS.src->index -= 8;
3423 }
3424 if (i->ARMin.NUnaryS.src->index > 7)
3425 goto bad;
3426 opc = X1000 | i->ARMin.NUnaryS.src->index;
3427 break;
3428 case 1:
3429 if (Q && i->ARMin.NUnaryS.src->index > 3) {
3430 regM++;
3431 i->ARMin.NUnaryS.src->index -= 4;
3432 }
3433 if (i->ARMin.NUnaryS.src->index > 3)
3434 goto bad;
3435 opc = X0001 | (i->ARMin.NUnaryS.src->index << 1);
3436 break;
3437 case 2:
3438 if (Q && i->ARMin.NUnaryS.src->index > 1) {
3439 regM++;
3440 i->ARMin.NUnaryS.src->index -= 2;
3441 }
3442 if (i->ARMin.NUnaryS.src->index > 1)
3443 goto bad;
3444 opc = X0000 | (i->ARMin.NUnaryS.src->index << 2);
3445 break;
3446 default:
3447 goto bad;
3448 }
3449 opc1 = (opc >> 2) & 3;
3450 opc2 = opc & 3;
3451 insn = XXXXXXXX(0xE, X1110, BITS4(0,(opc1 >> 1),(opc1 & 1),1),
3452 regM, regD, X1011,
3453 BITS4(M,(opc2 >> 1),(opc2 & 1),1), X0000);
3454 *p++ = insn;
3455 goto done;
3456 default:
3457 goto bad;
3458 }
3459 }
3460 case ARMin_NUnary: {
3461 UInt Q = i->ARMin.NUnary.Q ? 1 : 0;
3462 UInt regD = (hregClass(i->ARMin.NUnary.dst) == HRcVec128)
3463 ? (qregNo(i->ARMin.NUnary.dst) << 1)
3464 : dregNo(i->ARMin.NUnary.dst);
3465 UInt regM, M;
3466 UInt D = regD >> 4;
3467 UInt sz1 = i->ARMin.NUnary.size >> 1;
3468 UInt sz2 = i->ARMin.NUnary.size & 1;
3469 UInt sz = i->ARMin.NUnary.size;
3470 UInt insn;
3471 UInt F = 0; /* TODO: floating point EQZ ??? */
3472 if (i->ARMin.NUnary.op != ARMneon_DUP) {
3473 regM = (hregClass(i->ARMin.NUnary.src) == HRcVec128)
3474 ? (qregNo(i->ARMin.NUnary.src) << 1)
3475 : dregNo(i->ARMin.NUnary.src);
3476 M = regM >> 4;
3477 } else {
3478 regM = iregNo(i->ARMin.NUnary.src);
3479 M = regM >> 4;
3480 }
3481 regD &= 0xF;
3482 regM &= 0xF;
3483 switch (i->ARMin.NUnary.op) {
3484 case ARMneon_COPY: /* VMOV reg, reg */
3485 insn = XXXXXXXX(0xF, X0010, BITS4(0,D,1,0), regM, regD, X0001,
3486 BITS4(M,Q,M,1), regM);
3487 break;
3488 case ARMneon_COPYN: /* VMOVN regD, regQ */
3489 insn = XXXXXXXX(0xF, X0011, BITS4(1,D,1,1), BITS4(sz1,sz2,1,0),
3490 regD, X0010, BITS4(0,0,M,0), regM);
3491 break;
3492 case ARMneon_COPYQNSS: /* VQMOVN regD, regQ */
3493 insn = XXXXXXXX(0xF, X0011, BITS4(1,D,1,1), BITS4(sz1,sz2,1,0),
3494 regD, X0010, BITS4(1,0,M,0), regM);
3495 break;
3496 case ARMneon_COPYQNUS: /* VQMOVUN regD, regQ */
3497 insn = XXXXXXXX(0xF, X0011, BITS4(1,D,1,1), BITS4(sz1,sz2,1,0),
3498 regD, X0010, BITS4(0,1,M,0), regM);
3499 break;
3500 case ARMneon_COPYQNUU: /* VQMOVN regD, regQ */
3501 insn = XXXXXXXX(0xF, X0011, BITS4(1,D,1,1), BITS4(sz1,sz2,1,0),
3502 regD, X0010, BITS4(1,1,M,0), regM);
3503 break;
3504 case ARMneon_COPYLS: /* VMOVL regQ, regD */
3505 if (sz >= 3)
3506 goto bad;
3507 insn = XXXXXXXX(0xF, X0010,
3508 BITS4(1,D,(sz == 2) ? 1 : 0,(sz == 1) ? 1 : 0),
3509 BITS4((sz == 0) ? 1 : 0,0,0,0),
3510 regD, X1010, BITS4(0,0,M,1), regM);
3511 break;
3512 case ARMneon_COPYLU: /* VMOVL regQ, regD */
3513 if (sz >= 3)
3514 goto bad;
3515 insn = XXXXXXXX(0xF, X0011,
3516 BITS4(1,D,(sz == 2) ? 1 : 0,(sz == 1) ? 1 : 0),
3517 BITS4((sz == 0) ? 1 : 0,0,0,0),
3518 regD, X1010, BITS4(0,0,M,1), regM);
3519 break;
3520 case ARMneon_NOT: /* VMVN reg, reg*/
3521 insn = XXXXXXXX(0xF, X0011, BITS4(1,D,1,1), X0000, regD, X0101,
3522 BITS4(1,Q,M,0), regM);
3523 break;
3524 case ARMneon_EQZ:
3525 insn = XXXXXXXX(0xF, X0011, BITS4(1,D,1,1), BITS4(sz1,sz2,0,1),
3526 regD, BITS4(0,F,0,1), BITS4(0,Q,M,0), regM);
3527 break;
3528 case ARMneon_CNT:
3529 insn = XXXXXXXX(0xF, X0011, BITS4(1,D,1,1), X0000, regD, X0101,
3530 BITS4(0,Q,M,0), regM);
3531 break;
3532 case ARMneon_CLZ:
3533 insn = XXXXXXXX(0xF, X0011, BITS4(1,D,1,1), BITS4(sz1,sz2,0,0),
3534 regD, X0100, BITS4(1,Q,M,0), regM);
3535 break;
3536 case ARMneon_CLS:
3537 insn = XXXXXXXX(0xF, X0011, BITS4(1,D,1,1), BITS4(sz1,sz2,0,0),
3538 regD, X0100, BITS4(0,Q,M,0), regM);
3539 break;
3540 case ARMneon_ABS:
3541 insn = XXXXXXXX(0xF, X0011, BITS4(1,D,1,1), BITS4(sz1,sz2,0,1),
3542 regD, X0011, BITS4(0,Q,M,0), regM);
3543 break;
3544 case ARMneon_DUP:
3545 sz1 = i->ARMin.NUnary.size == 0 ? 1 : 0;
3546 sz2 = i->ARMin.NUnary.size == 1 ? 1 : 0;
3547 vassert(sz1 + sz2 < 2);
3548 insn = XXXXXXXX(0xE, X1110, BITS4(1, sz1, Q, 0), regD, regM,
3549 X1011, BITS4(D,0,sz2,1), X0000);
3550 break;
3551 case ARMneon_REV16:
3552 insn = XXXXXXXX(0xF, X0011, BITS4(1,D,1,1), BITS4(sz1,sz2,0,0),
3553 regD, BITS4(0,0,0,1), BITS4(0,Q,M,0), regM);
3554 break;
3555 case ARMneon_REV32:
3556 insn = XXXXXXXX(0xF, X0011, BITS4(1,D,1,1), BITS4(sz1,sz2,0,0),
3557 regD, BITS4(0,0,0,0), BITS4(1,Q,M,0), regM);
3558 break;
3559 case ARMneon_REV64:
3560 insn = XXXXXXXX(0xF, X0011, BITS4(1,D,1,1), BITS4(sz1,sz2,0,0),
3561 regD, BITS4(0,0,0,0), BITS4(0,Q,M,0), regM);
3562 break;
3563 case ARMneon_PADDLU:
3564 insn = XXXXXXXX(0xF, X0011, BITS4(1,D,1,1), BITS4(sz1,sz2,0,0),
3565 regD, X0010, BITS4(1,Q,M,0), regM);
3566 break;
3567 case ARMneon_PADDLS:
3568 insn = XXXXXXXX(0xF, X0011, BITS4(1,D,1,1), BITS4(sz1,sz2,0,0),
3569 regD, X0010, BITS4(0,Q,M,0), regM);
3570 break;
3571 case ARMneon_VQSHLNUU:
3572 insn = XXXXXXXX(0xF, X0011,
3573 (1 << 3) | (D << 2) | ((sz >> 4) & 3),
3574 sz & 0xf, regD, X0111,
3575 BITS4(sz >> 6,Q,M,1), regM);
3576 break;
3577 case ARMneon_VQSHLNSS:
3578 insn = XXXXXXXX(0xF, X0010,
3579 (1 << 3) | (D << 2) | ((sz >> 4) & 3),
3580 sz & 0xf, regD, X0111,
3581 BITS4(sz >> 6,Q,M,1), regM);
3582 break;
3583 case ARMneon_VQSHLNUS:
3584 insn = XXXXXXXX(0xF, X0011,
3585 (1 << 3) | (D << 2) | ((sz >> 4) & 3),
3586 sz & 0xf, regD, X0110,
3587 BITS4(sz >> 6,Q,M,1), regM);
3588 break;
3589 case ARMneon_VCVTFtoS:
3590 insn = XXXXXXXX(0xF, X0011, BITS4(1,D,1,1), X1011, regD, X0111,
3591 BITS4(0,Q,M,0), regM);
3592 break;
3593 case ARMneon_VCVTFtoU:
3594 insn = XXXXXXXX(0xF, X0011, BITS4(1,D,1,1), X1011, regD, X0111,
3595 BITS4(1,Q,M,0), regM);
3596 break;
3597 case ARMneon_VCVTStoF:
3598 insn = XXXXXXXX(0xF, X0011, BITS4(1,D,1,1), X1011, regD, X0110,
3599 BITS4(0,Q,M,0), regM);
3600 break;
3601 case ARMneon_VCVTUtoF:
3602 insn = XXXXXXXX(0xF, X0011, BITS4(1,D,1,1), X1011, regD, X0110,
3603 BITS4(1,Q,M,0), regM);
3604 break;
3605 case ARMneon_VCVTFtoFixedU:
3606 sz1 = (sz >> 5) & 1;
3607 sz2 = (sz >> 4) & 1;
3608 sz &= 0xf;
3609 insn = XXXXXXXX(0xF, X0011,
3610 BITS4(1,D,sz1,sz2), sz, regD, X1111,
3611 BITS4(0,Q,M,1), regM);
3612 break;
3613 case ARMneon_VCVTFtoFixedS:
3614 sz1 = (sz >> 5) & 1;
3615 sz2 = (sz >> 4) & 1;
3616 sz &= 0xf;
3617 insn = XXXXXXXX(0xF, X0010,
3618 BITS4(1,D,sz1,sz2), sz, regD, X1111,
3619 BITS4(0,Q,M,1), regM);
3620 break;
3621 case ARMneon_VCVTFixedUtoF:
3622 sz1 = (sz >> 5) & 1;
3623 sz2 = (sz >> 4) & 1;
3624 sz &= 0xf;
3625 insn = XXXXXXXX(0xF, X0011,
3626 BITS4(1,D,sz1,sz2), sz, regD, X1110,
3627 BITS4(0,Q,M,1), regM);
3628 break;
3629 case ARMneon_VCVTFixedStoF:
3630 sz1 = (sz >> 5) & 1;
3631 sz2 = (sz >> 4) & 1;
3632 sz &= 0xf;
3633 insn = XXXXXXXX(0xF, X0010,
3634 BITS4(1,D,sz1,sz2), sz, regD, X1110,
3635 BITS4(0,Q,M,1), regM);
3636 break;
3637 case ARMneon_VCVTF32toF16:
3638 insn = XXXXXXXX(0xF, X0011, BITS4(1,D,1,1), X0110, regD, X0110,
3639 BITS4(0,0,M,0), regM);
3640 break;
3641 case ARMneon_VCVTF16toF32:
3642 insn = XXXXXXXX(0xF, X0011, BITS4(1,D,1,1), X0110, regD, X0111,
3643 BITS4(0,0,M,0), regM);
3644 break;
3645 case ARMneon_VRECIP:
3646 insn = XXXXXXXX(0xF, X0011, BITS4(1,D,1,1), X1011, regD, X0100,
3647 BITS4(0,Q,M,0), regM);
3648 break;
3649 case ARMneon_VRECIPF:
3650 insn = XXXXXXXX(0xF, X0011, BITS4(1,D,1,1), X1011, regD, X0101,
3651 BITS4(0,Q,M,0), regM);
3652 break;
3653 case ARMneon_VABSFP:
3654 insn = XXXXXXXX(0xF, X0011, BITS4(1,D,1,1), X1001, regD, X0111,
3655 BITS4(0,Q,M,0), regM);
3656 break;
3657 case ARMneon_VRSQRTEFP:
3658 insn = XXXXXXXX(0xF, X0011, BITS4(1,D,1,1), X1011, regD, X0101,
3659 BITS4(1,Q,M,0), regM);
3660 break;
3661 case ARMneon_VRSQRTE:
3662 insn = XXXXXXXX(0xF, X0011, BITS4(1,D,1,1), X1011, regD, X0100,
3663 BITS4(1,Q,M,0), regM);
3664 break;
3665 case ARMneon_VNEGF:
3666 insn = XXXXXXXX(0xF, X0011, BITS4(1,D,1,1), X1001, regD, X0111,
3667 BITS4(1,Q,M,0), regM);
3668 break;
sewardj6aa87a62010-10-06 20:34:53 +00003669
sewardj6c60b322010-08-22 12:48:28 +00003670 default:
3671 goto bad;
3672 }
3673 *p++ = insn;
3674 goto done;
3675 }
3676 case ARMin_NDual: {
3677 UInt Q = i->ARMin.NDual.Q ? 1 : 0;
3678 UInt regD = (hregClass(i->ARMin.NDual.arg1) == HRcVec128)
3679 ? (qregNo(i->ARMin.NDual.arg1) << 1)
3680 : dregNo(i->ARMin.NDual.arg1);
3681 UInt regM = (hregClass(i->ARMin.NDual.arg2) == HRcVec128)
3682 ? (qregNo(i->ARMin.NDual.arg2) << 1)
3683 : dregNo(i->ARMin.NDual.arg2);
3684 UInt D = regD >> 4;
3685 UInt M = regM >> 4;
3686 UInt sz1 = i->ARMin.NDual.size >> 1;
3687 UInt sz2 = i->ARMin.NDual.size & 1;
3688 UInt insn;
3689 regD &= 0xF;
3690 regM &= 0xF;
3691 switch (i->ARMin.NDual.op) {
3692 case ARMneon_TRN: /* VTRN reg, reg */
3693 insn = XXXXXXXX(0xF, X0011, BITS4(1,D,1,1), BITS4(sz1,sz2,1,0),
3694 regD, X0000, BITS4(1,Q,M,0), regM);
3695 break;
3696 case ARMneon_ZIP: /* VZIP reg, reg */
3697 insn = XXXXXXXX(0xF, X0011, BITS4(1,D,1,1), BITS4(sz1,sz2,1,0),
3698 regD, X0001, BITS4(1,Q,M,0), regM);
3699 break;
3700 case ARMneon_UZP: /* VUZP reg, reg */
3701 insn = XXXXXXXX(0xF, X0011, BITS4(1,D,1,1), BITS4(sz1,sz2,1,0),
3702 regD, X0001, BITS4(0,Q,M,0), regM);
3703 break;
3704 default:
3705 goto bad;
3706 }
3707 *p++ = insn;
3708 goto done;
3709 }
3710 case ARMin_NBinary: {
3711 UInt Q = i->ARMin.NBinary.Q ? 1 : 0;
3712 UInt regD = (hregClass(i->ARMin.NBinary.dst) == HRcVec128)
3713 ? (qregNo(i->ARMin.NBinary.dst) << 1)
3714 : dregNo(i->ARMin.NBinary.dst);
3715 UInt regN = (hregClass(i->ARMin.NBinary.argL) == HRcVec128)
3716 ? (qregNo(i->ARMin.NBinary.argL) << 1)
3717 : dregNo(i->ARMin.NBinary.argL);
3718 UInt regM = (hregClass(i->ARMin.NBinary.argR) == HRcVec128)
3719 ? (qregNo(i->ARMin.NBinary.argR) << 1)
3720 : dregNo(i->ARMin.NBinary.argR);
3721 UInt sz1 = i->ARMin.NBinary.size >> 1;
3722 UInt sz2 = i->ARMin.NBinary.size & 1;
3723 UInt D = regD >> 4;
3724 UInt N = regN >> 4;
3725 UInt M = regM >> 4;
3726 UInt insn;
3727 regD &= 0xF;
3728 regM &= 0xF;
3729 regN &= 0xF;
3730 switch (i->ARMin.NBinary.op) {
3731 case ARMneon_VAND: /* VAND reg, reg, reg */
3732 insn = XXXXXXXX(0xF, X0010, BITS4(0,D,0,0), regN, regD, X0001,
3733 BITS4(N,Q,M,1), regM);
3734 break;
3735 case ARMneon_VORR: /* VORR reg, reg, reg*/
3736 insn = XXXXXXXX(0xF, X0010, BITS4(0,D,1,0), regN, regD, X0001,
3737 BITS4(N,Q,M,1), regM);
3738 break;
3739 case ARMneon_VXOR: /* VEOR reg, reg, reg */
3740 insn = XXXXXXXX(0xF, X0011, BITS4(0,D,0,0), regN, regD, X0001,
3741 BITS4(N,Q,M,1), regM);
3742 break;
3743 case ARMneon_VADD: /* VADD reg, reg, reg */
3744 insn = XXXXXXXX(0xF, X0010, BITS4(0,D,sz1,sz2), regN, regD,
3745 X1000, BITS4(N,Q,M,0), regM);
3746 break;
3747 case ARMneon_VSUB: /* VSUB reg, reg, reg */
3748 insn = XXXXXXXX(0xF, X0011, BITS4(0,D,sz1,sz2), regN, regD,
3749 X1000, BITS4(N,Q,M,0), regM);
3750 break;
3751 case ARMneon_VMINU: /* VMIN.Uxx reg, reg, reg */
3752 insn = XXXXXXXX(0xF, X0011, BITS4(0,D,sz1,sz2), regN, regD,
3753 X0110, BITS4(N,Q,M,1), regM);
3754 break;
3755 case ARMneon_VMINS: /* VMIN.Sxx reg, reg, reg */
3756 insn = XXXXXXXX(0xF, X0010, BITS4(0,D,sz1,sz2), regN, regD,
3757 X0110, BITS4(N,Q,M,1), regM);
3758 break;
3759 case ARMneon_VMAXU: /* VMAX.Uxx reg, reg, reg */
3760 insn = XXXXXXXX(0xF, X0011, BITS4(0,D,sz1,sz2), regN, regD,
3761 X0110, BITS4(N,Q,M,0), regM);
3762 break;
3763 case ARMneon_VMAXS: /* VMAX.Sxx reg, reg, reg */
3764 insn = XXXXXXXX(0xF, X0010, BITS4(0,D,sz1,sz2), regN, regD,
3765 X0110, BITS4(N,Q,M,0), regM);
3766 break;
3767 case ARMneon_VRHADDS: /* VRHADD.Sxx reg, reg, reg */
3768 insn = XXXXXXXX(0xF, X0010, BITS4(0,D,sz1,sz2), regN, regD,
3769 X0001, BITS4(N,Q,M,0), regM);
3770 break;
3771 case ARMneon_VRHADDU: /* VRHADD.Uxx reg, reg, reg */
3772 insn = XXXXXXXX(0xF, X0011, BITS4(0,D,sz1,sz2), regN, regD,
3773 X0001, BITS4(N,Q,M,0), regM);
3774 break;
3775 case ARMneon_VQADDU: /* VQADD unsigned reg, reg, reg */
3776 insn = XXXXXXXX(0xF, X0011, BITS4(0,D,sz1,sz2), regN, regD,
3777 X0000, BITS4(N,Q,M,1), regM);
3778 break;
3779 case ARMneon_VQADDS: /* VQADD signed reg, reg, reg */
3780 insn = XXXXXXXX(0xF, X0010, BITS4(0,D,sz1,sz2), regN, regD,
3781 X0000, BITS4(N,Q,M,1), regM);
3782 break;
3783 case ARMneon_VQSUBU: /* VQSUB unsigned reg, reg, reg */
3784 insn = XXXXXXXX(0xF, X0011, BITS4(0,D,sz1,sz2), regN, regD,
3785 X0010, BITS4(N,Q,M,1), regM);
3786 break;
3787 case ARMneon_VQSUBS: /* VQSUB signed reg, reg, reg */
3788 insn = XXXXXXXX(0xF, X0010, BITS4(0,D,sz1,sz2), regN, regD,
3789 X0010, BITS4(N,Q,M,1), regM);
3790 break;
3791 case ARMneon_VCGTU: /* VCGT unsigned reg, reg, reg */
3792 insn = XXXXXXXX(0xF, X0011, BITS4(0,D,sz1,sz2), regN, regD,
3793 X0011, BITS4(N,Q,M,0), regM);
3794 break;
3795 case ARMneon_VCGTS: /* VCGT signed reg, reg, reg */
3796 insn = XXXXXXXX(0xF, X0010, BITS4(0,D,sz1,sz2), regN, regD,
3797 X0011, BITS4(N,Q,M,0), regM);
3798 break;
3799 case ARMneon_VCGEU: /* VCGE unsigned reg, reg, reg */
3800 insn = XXXXXXXX(0xF, X0011, BITS4(0,D,sz1,sz2), regN, regD,
3801 X0011, BITS4(N,Q,M,1), regM);
3802 break;
3803 case ARMneon_VCGES: /* VCGE signed reg, reg, reg */
3804 insn = XXXXXXXX(0xF, X0010, BITS4(0,D,sz1,sz2), regN, regD,
3805 X0011, BITS4(N,Q,M,1), regM);
3806 break;
3807 case ARMneon_VCEQ: /* VCEQ reg, reg, reg */
3808 insn = XXXXXXXX(0xF, X0011, BITS4(0,D,sz1,sz2), regN, regD,
3809 X1000, BITS4(N,Q,M,1), regM);
3810 break;
3811 case ARMneon_VEXT: /* VEXT.8 reg, reg, #imm4*/
3812 if (i->ARMin.NBinary.size >= 16)
3813 goto bad;
3814 insn = XXXXXXXX(0xF, X0010, BITS4(1,D,1,1), regN, regD,
3815 i->ARMin.NBinary.size & 0xf, BITS4(N,Q,M,0),
3816 regM);
3817 break;
3818 case ARMneon_VMUL:
3819 insn = XXXXXXXX(0xF, X0010, BITS4(0,D,sz1,sz2), regN, regD,
3820 X1001, BITS4(N,Q,M,1), regM);
3821 break;
3822 case ARMneon_VMULLU:
3823 insn = XXXXXXXX(0xF, X0011, BITS4(1,D,sz1,sz2), regN, regD,
3824 X1100, BITS4(N,0,M,0), regM);
3825 break;
3826 case ARMneon_VMULLS:
3827 insn = XXXXXXXX(0xF, X0010, BITS4(1,D,sz1,sz2), regN, regD,
3828 X1100, BITS4(N,0,M,0), regM);
3829 break;
3830 case ARMneon_VMULP:
3831 insn = XXXXXXXX(0xF, X0011, BITS4(0,D,sz1,sz2), regN, regD,
3832 X1001, BITS4(N,Q,M,1), regM);
3833 break;
3834 case ARMneon_VMULFP:
3835 insn = XXXXXXXX(0xF, X0011, BITS4(0,D,0,0), regN, regD,
3836 X1101, BITS4(N,Q,M,1), regM);
3837 break;
3838 case ARMneon_VMULLP:
3839 insn = XXXXXXXX(0xF, X0010, BITS4(1,D,sz1,sz2), regN, regD,
3840 X1110, BITS4(N,0,M,0), regM);
3841 break;
3842 case ARMneon_VQDMULH:
3843 insn = XXXXXXXX(0xF, X0010, BITS4(0,D,sz1,sz2), regN, regD,
3844 X1011, BITS4(N,Q,M,0), regM);
3845 break;
3846 case ARMneon_VQRDMULH:
3847 insn = XXXXXXXX(0xF, X0011, BITS4(0,D,sz1,sz2), regN, regD,
3848 X1011, BITS4(N,Q,M,0), regM);
3849 break;
3850 case ARMneon_VQDMULL:
3851 insn = XXXXXXXX(0xF, X0010, BITS4(1,D,sz1,sz2), regN, regD,
3852 X1101, BITS4(N,0,M,0), regM);
3853 break;
3854 case ARMneon_VTBL:
3855 insn = XXXXXXXX(0xF, X0011, BITS4(1,D,1,1), regN, regD,
3856 X1000, BITS4(N,0,M,0), regM);
3857 break;
3858 case ARMneon_VPADD:
3859 insn = XXXXXXXX(0xF, X0010, BITS4(0,D,sz1,sz2), regN, regD,
3860 X1011, BITS4(N,Q,M,1), regM);
3861 break;
3862 case ARMneon_VPADDFP:
3863 insn = XXXXXXXX(0xF, X0011, BITS4(0,D,0,0), regN, regD,
3864 X1101, BITS4(N,Q,M,0), regM);
3865 break;
3866 case ARMneon_VPMINU:
3867 insn = XXXXXXXX(0xF, X0011, BITS4(0,D,sz1,sz2), regN, regD,
3868 X1010, BITS4(N,Q,M,1), regM);
3869 break;
3870 case ARMneon_VPMINS:
3871 insn = XXXXXXXX(0xF, X0010, BITS4(0,D,sz1,sz2), regN, regD,
3872 X1010, BITS4(N,Q,M,1), regM);
3873 break;
3874 case ARMneon_VPMAXU:
3875 insn = XXXXXXXX(0xF, X0011, BITS4(0,D,sz1,sz2), regN, regD,
3876 X1010, BITS4(N,Q,M,0), regM);
3877 break;
3878 case ARMneon_VPMAXS:
3879 insn = XXXXXXXX(0xF, X0010, BITS4(0,D,sz1,sz2), regN, regD,
3880 X1010, BITS4(N,Q,M,0), regM);
3881 break;
3882 case ARMneon_VADDFP: /* VADD reg, reg, reg */
3883 insn = XXXXXXXX(0xF, X0010, BITS4(0,D,0,0), regN, regD,
3884 X1101, BITS4(N,Q,M,0), regM);
3885 break;
3886 case ARMneon_VSUBFP: /* VADD reg, reg, reg */
3887 insn = XXXXXXXX(0xF, X0010, BITS4(0,D,1,0), regN, regD,
3888 X1101, BITS4(N,Q,M,0), regM);
3889 break;
3890 case ARMneon_VABDFP: /* VABD reg, reg, reg */
3891 insn = XXXXXXXX(0xF, X0011, BITS4(0,D,1,0), regN, regD,
3892 X1101, BITS4(N,Q,M,0), regM);
3893 break;
3894 case ARMneon_VMINF:
3895 insn = XXXXXXXX(0xF, X0010, BITS4(0,D,1,0), regN, regD,
3896 X1111, BITS4(N,Q,M,0), regM);
3897 break;
3898 case ARMneon_VMAXF:
3899 insn = XXXXXXXX(0xF, X0010, BITS4(0,D,0,0), regN, regD,
3900 X1111, BITS4(N,Q,M,0), regM);
3901 break;
3902 case ARMneon_VPMINF:
3903 insn = XXXXXXXX(0xF, X0011, BITS4(0,D,1,0), regN, regD,
3904 X1111, BITS4(N,Q,M,0), regM);
3905 break;
3906 case ARMneon_VPMAXF:
3907 insn = XXXXXXXX(0xF, X0011, BITS4(0,D,0,0), regN, regD,
3908 X1111, BITS4(N,Q,M,0), regM);
3909 break;
3910 case ARMneon_VRECPS:
3911 insn = XXXXXXXX(0xF, X0010, BITS4(0,D,0,0), regN, regD, X1111,
3912 BITS4(N,Q,M,1), regM);
3913 break;
3914 case ARMneon_VCGTF:
3915 insn = XXXXXXXX(0xF, X0011, BITS4(0,D,1,0), regN, regD, X1110,
3916 BITS4(N,Q,M,0), regM);
3917 break;
3918 case ARMneon_VCGEF:
3919 insn = XXXXXXXX(0xF, X0011, BITS4(0,D,0,0), regN, regD, X1110,
3920 BITS4(N,Q,M,0), regM);
3921 break;
3922 case ARMneon_VCEQF:
3923 insn = XXXXXXXX(0xF, X0010, BITS4(0,D,0,0), regN, regD, X1110,
3924 BITS4(N,Q,M,0), regM);
3925 break;
3926 case ARMneon_VRSQRTS:
3927 insn = XXXXXXXX(0xF, X0010, BITS4(0,D,1,0), regN, regD, X1111,
3928 BITS4(N,Q,M,1), regM);
3929 break;
3930 default:
3931 goto bad;
3932 }
3933 *p++ = insn;
3934 goto done;
3935 }
3936 case ARMin_NShift: {
3937 UInt Q = i->ARMin.NShift.Q ? 1 : 0;
3938 UInt regD = (hregClass(i->ARMin.NShift.dst) == HRcVec128)
3939 ? (qregNo(i->ARMin.NShift.dst) << 1)
3940 : dregNo(i->ARMin.NShift.dst);
3941 UInt regM = (hregClass(i->ARMin.NShift.argL) == HRcVec128)
3942 ? (qregNo(i->ARMin.NShift.argL) << 1)
3943 : dregNo(i->ARMin.NShift.argL);
3944 UInt regN = (hregClass(i->ARMin.NShift.argR) == HRcVec128)
3945 ? (qregNo(i->ARMin.NShift.argR) << 1)
3946 : dregNo(i->ARMin.NShift.argR);
3947 UInt sz1 = i->ARMin.NShift.size >> 1;
3948 UInt sz2 = i->ARMin.NShift.size & 1;
3949 UInt D = regD >> 4;
3950 UInt N = regN >> 4;
3951 UInt M = regM >> 4;
3952 UInt insn;
3953 regD &= 0xF;
3954 regM &= 0xF;
3955 regN &= 0xF;
3956 switch (i->ARMin.NShift.op) {
3957 case ARMneon_VSHL:
3958 insn = XXXXXXXX(0xF, X0011, BITS4(0,D,sz1,sz2), regN, regD,
3959 X0100, BITS4(N,Q,M,0), regM);
3960 break;
3961 case ARMneon_VSAL:
3962 insn = XXXXXXXX(0xF, X0010, BITS4(0,D,sz1,sz2), regN, regD,
3963 X0100, BITS4(N,Q,M,0), regM);
3964 break;
3965 case ARMneon_VQSHL:
3966 insn = XXXXXXXX(0xF, X0011, BITS4(0,D,sz1,sz2), regN, regD,
3967 X0100, BITS4(N,Q,M,1), regM);
3968 break;
3969 case ARMneon_VQSAL:
3970 insn = XXXXXXXX(0xF, X0010, BITS4(0,D,sz1,sz2), regN, regD,
3971 X0100, BITS4(N,Q,M,1), regM);
3972 break;
3973 default:
3974 goto bad;
3975 }
3976 *p++ = insn;
3977 goto done;
3978 }
3979 case ARMin_NeonImm: {
3980 UInt Q = (hregClass(i->ARMin.NeonImm.dst) == HRcVec128) ? 1 : 0;
3981 UInt regD = Q ? (qregNo(i->ARMin.NeonImm.dst) << 1) :
3982 dregNo(i->ARMin.NeonImm.dst);
3983 UInt D = regD >> 4;
3984 UInt imm = i->ARMin.NeonImm.imm->imm8;
3985 UInt tp = i->ARMin.NeonImm.imm->type;
3986 UInt j = imm >> 7;
3987 UInt imm3 = (imm >> 4) & 0x7;
3988 UInt imm4 = imm & 0xF;
3989 UInt cmode, op;
3990 UInt insn;
3991 regD &= 0xF;
3992 if (tp == 9)
3993 op = 1;
3994 else
3995 op = 0;
3996 switch (tp) {
3997 case 0:
3998 case 1:
3999 case 2:
4000 case 3:
4001 case 4:
4002 case 5:
4003 cmode = tp << 1;
4004 break;
4005 case 9:
4006 case 6:
4007 cmode = 14;
4008 break;
4009 case 7:
4010 cmode = 12;
4011 break;
4012 case 8:
4013 cmode = 13;
4014 break;
4015 case 10:
4016 cmode = 15;
4017 break;
4018 default:
4019 vpanic("ARMin_NeonImm");
4020
4021 }
4022 insn = XXXXXXXX(0xF, BITS4(0,0,1,j), BITS4(1,D,0,0), imm3, regD,
4023 cmode, BITS4(0,Q,op,1), imm4);
4024 *p++ = insn;
4025 goto done;
4026 }
4027 case ARMin_NCMovQ: {
4028 UInt cc = (UInt)i->ARMin.NCMovQ.cond;
4029 UInt qM = qregNo(i->ARMin.NCMovQ.src) << 1;
4030 UInt qD = qregNo(i->ARMin.NCMovQ.dst) << 1;
4031 UInt vM = qM & 0xF;
4032 UInt vD = qD & 0xF;
4033 UInt M = (qM >> 4) & 1;
4034 UInt D = (qD >> 4) & 1;
4035 vassert(cc < 16 && cc != ARMcc_AL && cc != ARMcc_NV);
4036 /* b!cc here+8: !cc A00 0000 */
4037 UInt insn = XXXXXXXX(cc ^ 1, 0xA, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0);
4038 *p++ = insn;
4039 /* vmov qD, qM */
4040 insn = XXXXXXXX(0xF, 0x2, BITS4(0,D,1,0),
4041 vM, vD, BITS4(0,0,0,1), BITS4(M,1,M,1), vM);
4042 *p++ = insn;
4043 goto done;
4044 }
4045 case ARMin_Add32: {
4046 UInt regD = iregNo(i->ARMin.Add32.rD);
4047 UInt regN = iregNo(i->ARMin.Add32.rN);
4048 UInt imm32 = i->ARMin.Add32.imm32;
4049 vassert(regD != regN);
4050 /* MOV regD, imm32 */
4051 p = imm32_to_iregNo((UInt *)p, regD, imm32);
4052 /* ADD regD, regN, regD */
4053 UInt insn = XXXXXXXX(0xE, 0, X1000, regN, regD, 0, 0, regD);
4054 *p++ = insn;
4055 goto done;
4056 }
4057 /* ... */
sewardj6c299f32009-12-31 18:00:12 +00004058 default:
4059 goto bad;
4060 }
4061
4062 bad:
4063 ppARMInstr(i);
4064 vpanic("emit_ARMInstr");
4065 /*NOTREACHED*/
sewardj6c60b322010-08-22 12:48:28 +00004066
sewardj6c299f32009-12-31 18:00:12 +00004067 done:
4068 vassert(((UChar*)p) - &buf[0] <= 32);
4069 return ((UChar*)p) - &buf[0];
4070}
4071
4072#undef BITS4
4073#undef X0000
4074#undef X0001
4075#undef X0010
4076#undef X0011
4077#undef X0100
4078#undef X0101
4079#undef X0110
4080#undef X0111
4081#undef X1000
4082#undef X1001
4083#undef X1010
4084#undef X1011
4085#undef X1100
4086#undef X1101
4087#undef X1110
4088#undef X1111
4089#undef XXXXX___
4090#undef XXXXXX__
4091#undef XXX___XX
4092#undef XXXXX__X
4093#undef XXXXXXXX
cerion82edbb32004-12-16 14:06:34 +00004094
4095/*---------------------------------------------------------------*/
sewardjcef7d3e2009-07-02 12:21:59 +00004096/*--- end host_arm_defs.c ---*/
cerion82edbb32004-12-16 14:06:34 +00004097/*---------------------------------------------------------------*/