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