]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/valgrind/src/valgrind-3.6.0-svn/VEX/priv/host_arm_defs.c
7fb7f98ae11963889d8fcae1104255c6d975d35d
[l4.git] / l4 / pkg / valgrind / src / valgrind-3.6.0-svn / VEX / priv / host_arm_defs.c
1
2 /*---------------------------------------------------------------*/
3 /*--- begin                                   host_arm_defs.c ---*/
4 /*---------------------------------------------------------------*/
5
6 /*
7    This file is part of Valgrind, a dynamic binary instrumentation
8    framework.
9
10    Copyright (C) 2004-2010 OpenWorks LLP
11       info@open-works.net
12
13    This program is free software; you can redistribute it and/or
14    modify it under the terms of the GNU General Public License as
15    published by the Free Software Foundation; either version 2 of the
16    License, or (at your option) any later version.
17
18    This program is distributed in the hope that it will be useful, but
19    WITHOUT ANY WARRANTY; without even the implied warranty of
20    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21    General Public License for more details.
22
23    You should have received a copy of the GNU General Public License
24    along with this program; if not, write to the Free Software
25    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
26    02110-1301, USA.
27
28    The GNU General Public License is contained in the file COPYING.
29 */
30
31 #include "libvex_basictypes.h"
32 #include "libvex.h"
33 #include "libvex_trc_values.h"
34
35 #include "main_util.h"
36 #include "host_generic_regs.h"
37 #include "host_arm_defs.h"
38
39
40
41 /* --------- Registers. --------- */
42
43 /* The usual HReg abstraction.
44    There are 16 general purpose regs.
45 */
46
47 void ppHRegARM ( HReg reg )  {
48    Int r;
49    /* Be generic for all virtual regs. */
50    if (hregIsVirtual(reg)) {
51       ppHReg(reg);
52       return;
53    }
54    /* But specific for real regs. */
55    switch (hregClass(reg)) {
56       case HRcInt32:
57          r = hregNumber(reg);
58          vassert(r >= 0 && r < 16);
59          vex_printf("r%d", r);
60          return;
61       case HRcFlt64:
62          r = hregNumber(reg);
63          vassert(r >= 0 && r < 16);
64          vex_printf("d%d", r);
65          return;
66       case HRcFlt32:
67          r = hregNumber(reg);
68          vassert(r >= 0 && r < 32);
69          vex_printf("s%d", r);
70          return;
71       default:
72          vpanic("ppHRegARM");
73    }
74 }
75
76 HReg hregARM_R0  ( void ) { return mkHReg(0,  HRcInt32, False); }
77 HReg hregARM_R1  ( void ) { return mkHReg(1,  HRcInt32, False); }
78 HReg hregARM_R2  ( void ) { return mkHReg(2,  HRcInt32, False); }
79 HReg hregARM_R3  ( void ) { return mkHReg(3,  HRcInt32, False); }
80 HReg hregARM_R4  ( void ) { return mkHReg(4,  HRcInt32, False); }
81 HReg hregARM_R5  ( void ) { return mkHReg(5,  HRcInt32, False); }
82 HReg hregARM_R6  ( void ) { return mkHReg(6,  HRcInt32, False); }
83 HReg hregARM_R7  ( void ) { return mkHReg(7,  HRcInt32, False); }
84 HReg hregARM_R8  ( void ) { return mkHReg(8,  HRcInt32, False); }
85 HReg hregARM_R9  ( void ) { return mkHReg(9,  HRcInt32, False); }
86 HReg hregARM_R10 ( void ) { return mkHReg(10, HRcInt32, False); }
87 HReg hregARM_R11 ( void ) { return mkHReg(11, HRcInt32, False); }
88 HReg hregARM_R12 ( void ) { return mkHReg(12, HRcInt32, False); }
89 HReg hregARM_R13 ( void ) { return mkHReg(13, HRcInt32, False); }
90 HReg hregARM_R14 ( void ) { return mkHReg(14, HRcInt32, False); }
91 HReg hregARM_R15 ( void ) { return mkHReg(15, HRcInt32, False); }
92 HReg hregARM_D8  ( void ) { return mkHReg(8,  HRcFlt64, False); }
93 HReg hregARM_D9  ( void ) { return mkHReg(9,  HRcFlt64, False); }
94 HReg hregARM_D10 ( void ) { return mkHReg(10, HRcFlt64, False); }
95 HReg hregARM_D11 ( void ) { return mkHReg(11, HRcFlt64, False); }
96 HReg hregARM_D12 ( void ) { return mkHReg(12, HRcFlt64, False); }
97 HReg hregARM_S26 ( void ) { return mkHReg(26, HRcFlt32, False); }
98 HReg hregARM_S27 ( void ) { return mkHReg(27, HRcFlt32, False); }
99 HReg hregARM_S28 ( void ) { return mkHReg(28, HRcFlt32, False); }
100 HReg hregARM_S29 ( void ) { return mkHReg(29, HRcFlt32, False); }
101 HReg hregARM_S30 ( void ) { return mkHReg(30, HRcFlt32, False); }
102
103 void getAllocableRegs_ARM ( Int* nregs, HReg** arr )
104 {
105    Int i = 0;
106    *nregs = 21;
107    *arr = LibVEX_Alloc(*nregs * sizeof(HReg));
108    // callee saves ones are listed first, since we prefer them
109    // if they're available
110    (*arr)[i++] = hregARM_R4();
111    (*arr)[i++] = hregARM_R5();
112    (*arr)[i++] = hregARM_R6();
113    (*arr)[i++] = hregARM_R7();
114    (*arr)[i++] = hregARM_R10();
115    (*arr)[i++] = hregARM_R11();
116    // otherwise we'll have to slum it out with caller-saves ones
117    (*arr)[i++] = hregARM_R0();
118    (*arr)[i++] = hregARM_R1();
119    (*arr)[i++] = hregARM_R2();
120    (*arr)[i++] = hregARM_R3();
121    (*arr)[i++] = hregARM_R9();
122    // FP hreegisters.  Note: these are all callee-save.  Yay!
123    // Hence we don't need to mention them as trashed in
124    // getHRegUsage for ARMInstr_Call.
125    (*arr)[i++] = hregARM_D8();
126    (*arr)[i++] = hregARM_D9();
127    (*arr)[i++] = hregARM_D10();
128    (*arr)[i++] = hregARM_D11();
129    (*arr)[i++] = hregARM_D12();
130    (*arr)[i++] = hregARM_S26();
131    (*arr)[i++] = hregARM_S27();
132    (*arr)[i++] = hregARM_S28();
133    (*arr)[i++] = hregARM_S29();
134    (*arr)[i++] = hregARM_S30();
135    // unavail: r8 as GSP
136    // r12 'cos we're not sure what it's for
137    // r13 as SP
138    // r14 as LR
139    // r15 as PC
140    //
141    // All in all, we have 11 allocatable integer registers:
142    // 0 1 2 3 4 5 6 7 9 10 11 plus r8 dedicated as GSP.
143    // 12 13 14 and 15 are not under the allocator's control.
144    //
145    // Hence for the allocatable registers we have:
146    //
147    // callee-saved: 4 5 6 7 (8) 9 10 11
148    // caller-saved: 0 1 2 3
149    // Note 9 is ambiguous: the base EABI does not give an e/r-saved
150    // designation for it, but the Linux instantiation of the ABI
151    // specifies it as callee-saved.
152    //
153    // If the set of available registers changes or if the e/r status
154    // changes, be sure to re-check/sync the definition of
155    // getHRegUsage for ARMInstr_Call too.
156    vassert(i == *nregs);
157 }
158
159
160
161 /* --------- Condition codes, ARM encoding. --------- */
162
163 HChar* showARMCondCode ( ARMCondCode cond ) {
164    switch (cond) {
165        case ARMcc_EQ:  return "eq";
166        case ARMcc_NE:  return "ne";
167        case ARMcc_HS:  return "hs";
168        case ARMcc_LO:  return "lo";
169        case ARMcc_MI:  return "mi";
170        case ARMcc_PL:  return "pl";
171        case ARMcc_VS:  return "vs";
172        case ARMcc_VC:  return "vc";
173        case ARMcc_HI:  return "hi";
174        case ARMcc_LS:  return "ls";
175        case ARMcc_GE:  return "ge";
176        case ARMcc_LT:  return "lt";
177        case ARMcc_GT:  return "gt";
178        case ARMcc_LE:  return "le";
179        case ARMcc_AL:  return "al"; // default
180        case ARMcc_NV:  return "nv";
181        default: vpanic("showARMCondCode");
182    }
183 }
184
185
186 /* --------- Mem AModes: Addressing Mode 1 --------- */
187
188 ARMAMode1* ARMAMode1_RI  ( HReg reg, Int simm13 ) {
189    ARMAMode1* am        = LibVEX_Alloc(sizeof(ARMAMode1));
190    am->tag              = ARMam1_RI;
191    am->ARMam1.RI.reg    = reg;
192    am->ARMam1.RI.simm13 = simm13;
193    vassert(-4095 <= simm13 && simm13 <= 4095);
194    return am;
195 }
196 ARMAMode1* ARMAMode1_RRS ( HReg base, HReg index, UInt shift ) {
197    ARMAMode1* am        = LibVEX_Alloc(sizeof(ARMAMode1));
198    am->tag              = ARMam1_RRS;
199    am->ARMam1.RRS.base  = base;
200    am->ARMam1.RRS.index = index;
201    am->ARMam1.RRS.shift = shift;
202    vassert(0 <= shift && shift <= 3);
203    return am;
204 }
205
206 void ppARMAMode1 ( ARMAMode1* am ) {
207    switch (am->tag) {
208       case ARMam1_RI:
209          vex_printf("%d(", am->ARMam1.RI.simm13);
210          ppHRegARM(am->ARMam1.RI.reg);
211          vex_printf(")");
212          break;
213       case ARMam1_RRS:
214          vex_printf("(");
215          ppHRegARM(am->ARMam1.RRS.base);
216          vex_printf(",");
217          ppHRegARM(am->ARMam1.RRS.index);
218          vex_printf(",%u)", am->ARMam1.RRS.shift);
219          break;
220       default:
221          vassert(0);
222    }
223 }
224
225 static void addRegUsage_ARMAMode1 ( HRegUsage* u, ARMAMode1* am ) {
226    switch (am->tag) {
227       case ARMam1_RI:
228          addHRegUse(u, HRmRead, am->ARMam1.RI.reg);
229          return;
230       case ARMam1_RRS:
231          //    addHRegUse(u, HRmRead, am->ARMam1.RRS.base);
232          //    addHRegUse(u, HRmRead, am->ARMam1.RRS.index);
233          //   return;
234       default:
235          vpanic("addRegUsage_ARMAmode1");
236    }
237 }
238
239 static void mapRegs_ARMAMode1 ( HRegRemap* m, ARMAMode1* am ) {
240    switch (am->tag) {
241       case ARMam1_RI:
242          am->ARMam1.RI.reg = lookupHRegRemap(m, am->ARMam1.RI.reg);
243          return;
244       case ARMam1_RRS:
245          //am->ARMam1.RR.base =lookupHRegRemap(m, am->ARMam1.RR.base);
246          //am->ARMam1.RR.index = lookupHRegRemap(m, am->ARMam1.RR.index);
247          //return;
248       default:
249          vpanic("mapRegs_ARMAmode1");
250    }
251 }
252
253
254 /* --------- Mem AModes: Addressing Mode 2 --------- */
255
256 ARMAMode2* ARMAMode2_RI ( HReg reg, Int simm9 ) {
257    ARMAMode2* am       = LibVEX_Alloc(sizeof(ARMAMode2));
258    am->tag             = ARMam2_RI;
259    am->ARMam2.RI.reg   = reg;
260    am->ARMam2.RI.simm9 = simm9;
261    vassert(-255 <= simm9 && simm9 <= 255);
262    return am;
263 }
264 ARMAMode2* ARMAMode2_RR ( HReg base, HReg index ) {
265    ARMAMode2* am       = LibVEX_Alloc(sizeof(ARMAMode2));
266    am->tag             = ARMam2_RR;
267    am->ARMam2.RR.base  = base;
268    am->ARMam2.RR.index = index;
269    return am;
270 }
271
272 void ppARMAMode2 ( ARMAMode2* am ) {
273    switch (am->tag) {
274       case ARMam2_RI:
275          vex_printf("%d(", am->ARMam2.RI.simm9);
276          ppHRegARM(am->ARMam2.RI.reg);
277          vex_printf(")");
278          break;
279       case ARMam2_RR:
280          vex_printf("(");
281          ppHRegARM(am->ARMam2.RR.base);
282          vex_printf(",");
283          ppHRegARM(am->ARMam2.RR.index);
284          vex_printf(")");
285          break;
286       default:
287          vassert(0);
288    }
289 }
290
291 static void addRegUsage_ARMAMode2 ( HRegUsage* u, ARMAMode2* am ) {
292    switch (am->tag) {
293       case ARMam2_RI:
294          addHRegUse(u, HRmRead, am->ARMam2.RI.reg);
295          return;
296       case ARMam2_RR:
297          //    addHRegUse(u, HRmRead, am->ARMam2.RR.base);
298          //    addHRegUse(u, HRmRead, am->ARMam2.RR.index);
299          //   return;
300       default:
301          vpanic("addRegUsage_ARMAmode2");
302    }
303 }
304
305 static void mapRegs_ARMAMode2 ( HRegRemap* m, ARMAMode2* am ) {
306    switch (am->tag) {
307       case ARMam2_RI:
308          am->ARMam2.RI.reg = lookupHRegRemap(m, am->ARMam2.RI.reg);
309          return;
310       case ARMam2_RR:
311          //am->ARMam2.RR.base =lookupHRegRemap(m, am->ARMam2.RR.base);
312          //am->ARMam2.RR.index = lookupHRegRemap(m, am->ARMam2.RR.index);
313          //return;
314       default:
315          vpanic("mapRegs_ARMAmode2");
316    }
317 }
318
319
320 /* --------- Mem AModes: Addressing Mode VFP --------- */
321
322 ARMAModeV* mkARMAModeV ( HReg reg, Int simm11 ) {
323    ARMAModeV* am = LibVEX_Alloc(sizeof(ARMAModeV));
324    vassert(simm11 >= -1020 && simm11 <= 1020);
325    vassert(0 == (simm11 & 3));
326    am->reg    = reg;
327    am->simm11 = simm11;
328    return am;
329 }
330
331 void ppARMAModeV ( ARMAModeV* am ) {
332    vex_printf("%d(", am->simm11);
333    ppHRegARM(am->reg);
334    vex_printf(")");
335 }
336
337 static void addRegUsage_ARMAModeV ( HRegUsage* u, ARMAModeV* am ) {
338    addHRegUse(u, HRmRead, am->reg);
339 }
340
341 static void mapRegs_ARMAModeV ( HRegRemap* m, ARMAModeV* am ) {
342    am->reg = lookupHRegRemap(m, am->reg);
343 }
344
345
346 /* --------- Reg or imm-8x4 operands --------- */
347
348 static UInt ROR32 ( UInt x, UInt sh ) {
349    vassert(sh >= 0 && sh < 32);
350    if (sh == 0)
351       return x;
352    else
353       return (x << (32-sh)) | (x >> sh);
354 }
355
356 ARMRI84* ARMRI84_I84 ( UShort imm8, UShort imm4 ) {
357    ARMRI84* ri84          = LibVEX_Alloc(sizeof(ARMRI84));
358    ri84->tag              = ARMri84_I84;
359    ri84->ARMri84.I84.imm8 = imm8;
360    ri84->ARMri84.I84.imm4 = imm4;
361    vassert(imm8 >= 0 && imm8 <= 255);
362    vassert(imm4 >= 0 && imm4 <= 15);
363    return ri84;
364 }
365 ARMRI84* ARMRI84_R ( HReg reg ) {
366    ARMRI84* ri84       = LibVEX_Alloc(sizeof(ARMRI84));
367    ri84->tag           = ARMri84_R;
368    ri84->ARMri84.R.reg = reg;
369    return ri84;
370 }
371
372 void ppARMRI84 ( ARMRI84* ri84 ) {
373    switch (ri84->tag) {
374       case ARMri84_I84:
375          vex_printf("0x%x", ROR32(ri84->ARMri84.I84.imm8,
376                                   2 * ri84->ARMri84.I84.imm4));
377          break;
378       case ARMri84_R:
379          ppHRegARM(ri84->ARMri84.R.reg);
380          break;
381       default:
382          vassert(0);
383    }
384 }
385
386 static void addRegUsage_ARMRI84 ( HRegUsage* u, ARMRI84* ri84 ) {
387    switch (ri84->tag) {
388       case ARMri84_I84:
389          return;
390       case ARMri84_R:
391          addHRegUse(u, HRmRead, ri84->ARMri84.R.reg);
392          return;
393       default:
394          vpanic("addRegUsage_ARMRI84");
395    }
396 }
397
398 static void mapRegs_ARMRI84 ( HRegRemap* m, ARMRI84* ri84 ) {
399    switch (ri84->tag) {
400       case ARMri84_I84:
401          return;
402       case ARMri84_R:
403          ri84->ARMri84.R.reg = lookupHRegRemap(m, ri84->ARMri84.R.reg);
404          return;
405       default:
406          vpanic("mapRegs_ARMRI84");
407    }
408 }
409
410
411 /* --------- Reg or imm5 operands --------- */
412
413 ARMRI5* ARMRI5_I5 ( UInt imm5 ) {
414    ARMRI5* ri5         = LibVEX_Alloc(sizeof(ARMRI5));
415    ri5->tag            = ARMri5_I5;
416    ri5->ARMri5.I5.imm5 = imm5;
417    vassert(imm5 > 0 && imm5 <= 31); // zero is not allowed
418    return ri5;
419 }
420 ARMRI5* ARMRI5_R ( HReg reg ) {
421    ARMRI5* ri5       = LibVEX_Alloc(sizeof(ARMRI5));
422    ri5->tag          = ARMri5_R;
423    ri5->ARMri5.R.reg = reg;
424    return ri5;
425 }
426
427 void ppARMRI5 ( ARMRI5* ri5 ) {
428    switch (ri5->tag) {
429       case ARMri5_I5:
430          vex_printf("%u", ri5->ARMri5.I5.imm5);
431          break;
432       case ARMri5_R:
433          ppHRegARM(ri5->ARMri5.R.reg);
434          break;
435       default:
436          vassert(0);
437    }
438 }
439
440 static void addRegUsage_ARMRI5 ( HRegUsage* u, ARMRI5* ri5 ) {
441    switch (ri5->tag) {
442       case ARMri5_I5:
443          return;
444       case ARMri5_R:
445          addHRegUse(u, HRmRead, ri5->ARMri5.R.reg);
446          return;
447       default:
448          vpanic("addRegUsage_ARMRI5");
449    }
450 }
451
452 static void mapRegs_ARMRI5 ( HRegRemap* m, ARMRI5* ri5 ) {
453    switch (ri5->tag) {
454       case ARMri5_I5:
455          return;
456       case ARMri5_R:
457          ri5->ARMri5.R.reg = lookupHRegRemap(m, ri5->ARMri5.R.reg);
458          return;
459       default:
460          vpanic("mapRegs_ARMRI5");
461    }
462 }
463
464
465 /* --------- Instructions. --------- */
466
467 HChar* showARMAluOp ( ARMAluOp op ) {
468    switch (op) {
469       case ARMalu_ADD:  return "add";
470       case ARMalu_ADDS: return "adds";
471       case ARMalu_ADC:  return "adc";
472       case ARMalu_SUB:  return "sub";
473       case ARMalu_SUBS: return "subs";
474       case ARMalu_SBC:  return "sbc";
475       case ARMalu_AND:  return "and";
476       case ARMalu_BIC:  return "bic";
477       case ARMalu_OR:   return "orr";
478       case ARMalu_XOR:  return "xor";
479       default: vpanic("showARMAluOp");
480    }
481 }
482
483 HChar* showARMShiftOp ( ARMShiftOp op ) {
484    switch (op) {
485       case ARMsh_SHL: return "shl";
486       case ARMsh_SHR: return "shr";
487       case ARMsh_SAR: return "sar";
488       default: vpanic("showARMShiftOp");
489    }
490 }
491
492 HChar* showARMUnaryOp ( ARMUnaryOp op ) {
493    switch (op) {
494       case ARMun_NEG: return "neg";
495       case ARMun_NOT: return "not";
496       case ARMun_CLZ: return "clz";
497       default: vpanic("showARMUnaryOp");
498    }
499 }
500
501 HChar* showARMMulOp ( ARMMulOp op ) {
502    switch (op) {
503       case ARMmul_PLAIN: return "mul";
504       case ARMmul_ZX:    return "umull";
505       case ARMmul_SX:    return "smull";
506       default: vpanic("showARMMulOp");
507    }
508 }
509
510 HChar* showARMVfpOp ( ARMVfpOp op ) {
511    switch (op) {
512       case ARMvfp_ADD: return "add";
513       case ARMvfp_SUB: return "sub";
514       case ARMvfp_MUL: return "mul";
515       case ARMvfp_DIV: return "div";
516       default: vpanic("showARMVfpOp");
517    }
518 }
519
520 HChar* showARMVfpUnaryOp ( ARMVfpUnaryOp op ) {
521    switch (op) {
522       case ARMvfpu_COPY: return "cpy";
523       case ARMvfpu_NEG:  return "neg";
524       case ARMvfpu_ABS:  return "abs";
525       case ARMvfpu_SQRT: return "sqrt";
526       default: vpanic("showARMVfpUnaryOp");
527    }
528 }
529
530 ARMInstr* ARMInstr_Alu ( ARMAluOp op,
531                          HReg dst, HReg argL, ARMRI84* argR ) {
532    ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
533    i->tag            = ARMin_Alu;
534    i->ARMin.Alu.op   = op;
535    i->ARMin.Alu.dst  = dst;
536    i->ARMin.Alu.argL = argL;
537    i->ARMin.Alu.argR = argR;
538    return i;
539 }
540 ARMInstr* ARMInstr_Shift  ( ARMShiftOp op,
541                             HReg dst, HReg argL, ARMRI5* argR ) {
542    ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
543    i->tag              = ARMin_Shift;
544    i->ARMin.Shift.op   = op;
545    i->ARMin.Shift.dst  = dst;
546    i->ARMin.Shift.argL = argL;
547    i->ARMin.Shift.argR = argR;
548    return i;
549 }
550 ARMInstr* ARMInstr_Unary ( ARMUnaryOp op, HReg dst, HReg src ) {
551    ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
552    i->tag             = ARMin_Unary;
553    i->ARMin.Unary.op  = op;
554    i->ARMin.Unary.dst = dst;
555    i->ARMin.Unary.src = src;
556    return i;
557 }
558 ARMInstr* ARMInstr_CmpOrTst ( Bool isCmp, HReg argL, ARMRI84* argR ) {
559    ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
560    i->tag                  = ARMin_CmpOrTst;
561    i->ARMin.CmpOrTst.isCmp = isCmp;
562    i->ARMin.CmpOrTst.argL  = argL;
563    i->ARMin.CmpOrTst.argR  = argR;
564    return i;
565 }
566 ARMInstr* ARMInstr_Mov ( HReg dst, ARMRI84* src ) {
567    ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
568    i->tag           = ARMin_Mov;
569    i->ARMin.Mov.dst = dst;
570    i->ARMin.Mov.src = src;
571    return i;
572 }
573 ARMInstr* ARMInstr_Imm32  ( HReg dst, UInt imm32 ) {
574    ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
575    i->tag               = ARMin_Imm32;
576    i->ARMin.Imm32.dst   = dst;
577    i->ARMin.Imm32.imm32 = imm32;
578    return i;
579 }
580 ARMInstr* ARMInstr_LdSt32 ( Bool isLoad, HReg rD, ARMAMode1* amode ) {
581    ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
582    i->tag                 = ARMin_LdSt32;
583    i->ARMin.LdSt32.isLoad = isLoad;
584    i->ARMin.LdSt32.rD     = rD;
585    i->ARMin.LdSt32.amode  = amode;
586    return i;
587 }
588 ARMInstr* ARMInstr_LdSt16 ( Bool isLoad, Bool signedLoad,
589                             HReg rD, ARMAMode2* amode ) {
590    ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
591    i->tag                     = ARMin_LdSt16;
592    i->ARMin.LdSt16.isLoad     = isLoad;
593    i->ARMin.LdSt16.signedLoad = signedLoad;
594    i->ARMin.LdSt16.rD         = rD;
595    i->ARMin.LdSt16.amode      = amode;
596    return i;
597 }
598 ARMInstr* ARMInstr_LdSt8U ( Bool isLoad, HReg rD, ARMAMode1* amode ) {
599    ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
600    i->tag                 = ARMin_LdSt8U;
601    i->ARMin.LdSt8U.isLoad = isLoad;
602    i->ARMin.LdSt8U.rD     = rD;
603    i->ARMin.LdSt8U.amode  = amode;
604    return i;
605 }
606 //extern ARMInstr* ARMInstr_Ld8S   ( HReg, ARMAMode2* );
607 ARMInstr* ARMInstr_Goto ( IRJumpKind jk, ARMCondCode cond, HReg gnext ) {
608    ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
609    i->tag              = ARMin_Goto;
610    i->ARMin.Goto.jk    = jk;
611    i->ARMin.Goto.cond  = cond;
612    i->ARMin.Goto.gnext = gnext;
613    return i;
614 }
615 ARMInstr* ARMInstr_CMov ( ARMCondCode cond, HReg dst, ARMRI84* src ) {
616    ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
617    i->tag             = ARMin_CMov;
618    i->ARMin.CMov.cond = cond;
619    i->ARMin.CMov.dst  = dst;
620    i->ARMin.CMov.src  = src;
621    vassert(cond != ARMcc_AL);
622    return i;
623 }
624 ARMInstr* ARMInstr_Call ( ARMCondCode cond, HWord target, Int nArgRegs ) {
625    ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
626    i->tag                 = ARMin_Call;
627    i->ARMin.Call.cond     = cond;
628    i->ARMin.Call.target   = target;
629    i->ARMin.Call.nArgRegs = nArgRegs;
630    return i;
631 }
632 ARMInstr* ARMInstr_Mul ( ARMMulOp op ) {
633    ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
634    i->tag          = ARMin_Mul;
635    i->ARMin.Mul.op = op;
636    return i;
637 }
638 ARMInstr* ARMInstr_LdrEX ( Int szB ) {
639    ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
640    i->tag             = ARMin_LdrEX;
641    i->ARMin.LdrEX.szB = szB;
642    vassert(szB == 4 || szB == 1);
643    return i;
644 }
645 ARMInstr* ARMInstr_StrEX ( Int szB ) {
646    ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
647    i->tag             = ARMin_StrEX;
648    i->ARMin.StrEX.szB = szB;
649    vassert(szB == 4 || szB == 1);
650    return i;
651 }
652 ARMInstr* ARMInstr_VLdStD ( Bool isLoad, HReg dD, ARMAModeV* am ) {
653    ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
654    i->tag                 = ARMin_VLdStD;
655    i->ARMin.VLdStD.isLoad = isLoad;
656    i->ARMin.VLdStD.dD     = dD;
657    i->ARMin.VLdStD.amode  = am;
658    return i;
659 }
660 ARMInstr* ARMInstr_VLdStS ( Bool isLoad, HReg fD, ARMAModeV* am ) {
661    ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
662    i->tag                 = ARMin_VLdStS;
663    i->ARMin.VLdStS.isLoad = isLoad;
664    i->ARMin.VLdStS.fD     = fD;
665    i->ARMin.VLdStS.amode  = am;
666    return i;
667 }
668 ARMInstr* ARMInstr_VAluD ( ARMVfpOp op, HReg dst, HReg argL, HReg argR ) {
669    ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
670    i->tag              = ARMin_VAluD;
671    i->ARMin.VAluD.op   = op;
672    i->ARMin.VAluD.dst  = dst;
673    i->ARMin.VAluD.argL = argL;
674    i->ARMin.VAluD.argR = argR;
675    return i;
676 }
677 ARMInstr* ARMInstr_VAluS ( ARMVfpOp op, HReg dst, HReg argL, HReg argR ) {
678    ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
679    i->tag              = ARMin_VAluS;
680    i->ARMin.VAluS.op   = op;
681    i->ARMin.VAluS.dst  = dst;
682    i->ARMin.VAluS.argL = argL;
683    i->ARMin.VAluS.argR = argR;
684    return i;
685 }
686 ARMInstr* ARMInstr_VUnaryD ( ARMVfpUnaryOp op, HReg dst, HReg src ) {
687    ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
688    i->tag               = ARMin_VUnaryD;
689    i->ARMin.VUnaryD.op  = op;
690    i->ARMin.VUnaryD.dst = dst;
691    i->ARMin.VUnaryD.src = src;
692    return i;
693 }
694 ARMInstr* ARMInstr_VUnaryS ( ARMVfpUnaryOp op, HReg dst, HReg src ) {
695    ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
696    i->tag               = ARMin_VUnaryS;
697    i->ARMin.VUnaryS.op  = op;
698    i->ARMin.VUnaryS.dst = dst;
699    i->ARMin.VUnaryS.src = src;
700    return i;
701 }
702 ARMInstr* ARMInstr_VCmpD ( HReg argL, HReg argR ) {
703    ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
704    i->tag              = ARMin_VCmpD;
705    i->ARMin.VCmpD.argL = argL;
706    i->ARMin.VCmpD.argR = argR;
707    return i;
708 }
709 ARMInstr* ARMInstr_VCMovD ( ARMCondCode cond, HReg dst, HReg src ) {
710    ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
711    i->tag               = ARMin_VCMovD;
712    i->ARMin.VCMovD.cond = cond;
713    i->ARMin.VCMovD.dst  = dst;
714    i->ARMin.VCMovD.src  = src;
715    vassert(cond != ARMcc_AL);
716    return i;
717 }
718 ARMInstr* ARMInstr_VCMovS ( ARMCondCode cond, HReg dst, HReg src ) {
719    ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
720    i->tag               = ARMin_VCMovS;
721    i->ARMin.VCMovS.cond = cond;
722    i->ARMin.VCMovS.dst  = dst;
723    i->ARMin.VCMovS.src  = src;
724    vassert(cond != ARMcc_AL);
725    return i;
726 }
727 ARMInstr* ARMInstr_VCvtSD ( Bool sToD, HReg dst, HReg src ) {
728    ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
729    i->tag               = ARMin_VCvtSD;
730    i->ARMin.VCvtSD.sToD = sToD;
731    i->ARMin.VCvtSD.dst  = dst;
732    i->ARMin.VCvtSD.src  = src;
733    return i;
734 }
735 ARMInstr* ARMInstr_VXferD ( Bool toD, HReg dD, HReg rHi, HReg rLo ) {
736    ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
737    i->tag              = ARMin_VXferD;
738    i->ARMin.VXferD.toD = toD;
739    i->ARMin.VXferD.dD  = dD;
740    i->ARMin.VXferD.rHi = rHi;
741    i->ARMin.VXferD.rLo = rLo;
742    return i;
743 }
744 ARMInstr* ARMInstr_VXferS ( Bool toS, HReg fD, HReg rLo ) {
745    ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
746    i->tag              = ARMin_VXferS;
747    i->ARMin.VXferS.toS = toS;
748    i->ARMin.VXferS.fD  = fD;
749    i->ARMin.VXferS.rLo = rLo;
750    return i;
751 }
752 ARMInstr* ARMInstr_VCvtID ( Bool iToD, Bool syned,
753                             HReg dst, HReg src ) {
754    ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
755    i->tag                = ARMin_VCvtID;
756    i->ARMin.VCvtID.iToD  = iToD;
757    i->ARMin.VCvtID.syned = syned;
758    i->ARMin.VCvtID.dst   = dst;
759    i->ARMin.VCvtID.src   = src;
760    return i;
761 }
762 ARMInstr* ARMInstr_FPSCR ( Bool toFPSCR, HReg iReg ) {
763    ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
764    i->tag                 = ARMin_FPSCR;
765    i->ARMin.FPSCR.toFPSCR = toFPSCR;
766    i->ARMin.FPSCR.iReg    = iReg;
767    return i;
768 }
769 ARMInstr* ARMInstr_MFence ( void ) {
770    ARMInstr* i = LibVEX_Alloc(sizeof(ARMInstr));
771    i->tag      = ARMin_MFence;
772    return i;
773 }
774
775 void ppARMInstr ( ARMInstr* i ) {
776    switch (i->tag) {
777       case ARMin_Alu:
778          vex_printf("%-4s  ", showARMAluOp(i->ARMin.Alu.op));
779          ppHRegARM(i->ARMin.Alu.dst);
780          vex_printf(", ");
781          ppHRegARM(i->ARMin.Alu.argL);
782          vex_printf(", ");
783          ppARMRI84(i->ARMin.Alu.argR);
784          return;
785       case ARMin_Shift:
786          vex_printf("%s   ", showARMShiftOp(i->ARMin.Shift.op));
787          ppHRegARM(i->ARMin.Shift.dst);
788          vex_printf(", ");
789          ppHRegARM(i->ARMin.Shift.argL);
790          vex_printf(", ");
791          ppARMRI5(i->ARMin.Shift.argR);
792          return;
793       case ARMin_Unary:
794          vex_printf("%s   ", showARMUnaryOp(i->ARMin.Unary.op));
795          ppHRegARM(i->ARMin.Unary.dst);
796          vex_printf(", ");
797          ppHRegARM(i->ARMin.Unary.src);
798          return;
799       case ARMin_CmpOrTst:
800          vex_printf("%s   ", i->ARMin.CmpOrTst.isCmp ? "cmp" : "tst");
801          ppHRegARM(i->ARMin.CmpOrTst.argL);
802          vex_printf(", ");
803          ppARMRI84(i->ARMin.CmpOrTst.argR);
804          return;
805       case ARMin_Mov:
806          vex_printf("mov   ");
807          ppHRegARM(i->ARMin.Mov.dst);
808          vex_printf(", ");
809          ppARMRI84(i->ARMin.Mov.src);
810          return;
811       case ARMin_Imm32:
812          vex_printf("imm   ");
813          ppHRegARM(i->ARMin.Imm32.dst);
814          vex_printf(", 0x%x", i->ARMin.Imm32.imm32);
815          return;
816       case ARMin_LdSt32:
817          if (i->ARMin.LdSt32.isLoad) {
818             vex_printf("ldr   ");
819             ppHRegARM(i->ARMin.LdSt32.rD);
820             vex_printf(", ");
821             ppARMAMode1(i->ARMin.LdSt32.amode);
822          } else {
823             vex_printf("str   ");
824             ppARMAMode1(i->ARMin.LdSt32.amode);
825             vex_printf(", ");
826             ppHRegARM(i->ARMin.LdSt32.rD);
827          }
828          return;
829       case ARMin_LdSt16:
830          if (i->ARMin.LdSt16.isLoad) {
831             vex_printf("%s", i->ARMin.LdSt16.signedLoad 
832                                 ? "ldrsh " : "ldrh  " );
833             ppHRegARM(i->ARMin.LdSt16.rD);
834             vex_printf(", ");
835             ppARMAMode2(i->ARMin.LdSt16.amode);
836          } else {
837             vex_printf("strh  ");
838             ppARMAMode2(i->ARMin.LdSt16.amode);
839             vex_printf(", ");
840             ppHRegARM(i->ARMin.LdSt16.rD);
841          }
842          return;
843       case ARMin_LdSt8U:
844          if (i->ARMin.LdSt8U.isLoad) {
845             vex_printf("ldrb  ");
846             ppHRegARM(i->ARMin.LdSt8U.rD);
847             vex_printf(", ");
848             ppARMAMode1(i->ARMin.LdSt8U.amode);
849          } else {
850             vex_printf("strb  ");
851             ppARMAMode1(i->ARMin.LdSt8U.amode);
852             vex_printf(", ");
853             ppHRegARM(i->ARMin.LdSt8U.rD);
854          }
855          return;
856       case ARMin_Ld8S:
857          goto unhandled;
858       case ARMin_Goto:
859          if (i->ARMin.Goto.cond != ARMcc_AL) {
860             vex_printf("if (%%cpsr.%s) { ",
861                        showARMCondCode(i->ARMin.Goto.cond));
862          } else {
863             vex_printf("if (1) { ");
864          }
865          if (i->ARMin.Goto.jk != Ijk_Boring
866              && i->ARMin.Goto.jk != Ijk_Call
867              && i->ARMin.Goto.jk != Ijk_Ret) {
868             vex_printf("mov r8, $");
869             ppIRJumpKind(i->ARMin.Goto.jk);
870             vex_printf(" ; ");
871          }
872          vex_printf("mov r0, ");
873          ppHRegARM(i->ARMin.Goto.gnext);
874          vex_printf(" ; bx r14");
875          if (i->ARMin.Goto.cond != ARMcc_AL) {
876             vex_printf(" }");
877          } else {
878             vex_printf(" }");
879          }
880          return;
881       case ARMin_CMov:
882          vex_printf("mov%s ", showARMCondCode(i->ARMin.CMov.cond));
883          ppHRegARM(i->ARMin.CMov.dst);
884          vex_printf(", ");
885          ppARMRI84(i->ARMin.CMov.src);
886          return;
887       case ARMin_Call:
888          vex_printf("call%s  ",
889                     i->ARMin.Call.cond==ARMcc_AL
890                        ? "" : showARMCondCode(i->ARMin.Call.cond));
891          vex_printf("0x%lx [nArgRegs=%d]",
892                     i->ARMin.Call.target, i->ARMin.Call.nArgRegs);
893          return;
894       case ARMin_Mul:
895          vex_printf("%-5s ", showARMMulOp(i->ARMin.Mul.op));
896          if (i->ARMin.Mul.op == ARMmul_PLAIN) {
897             vex_printf("r0, r2, r3");
898          } else {
899             vex_printf("r1:r0, r2, r3");
900          }
901          return;
902       case ARMin_LdrEX:
903          vex_printf("ldrex%s ", i->ARMin.LdrEX.szB == 1 ? "b"
904                                 : i->ARMin.LdrEX.szB == 2 ? "h" : "");
905          vex_printf("r0, [r1]");
906          return;
907       case ARMin_StrEX:
908          vex_printf("strex%s ", i->ARMin.StrEX.szB == 1 ? "b"
909                                 : i->ARMin.StrEX.szB == 2 ? "h" : "");
910          vex_printf("r0, r1, [r2]");
911          return;
912       case ARMin_VLdStD:
913          if (i->ARMin.VLdStD.isLoad) {
914             vex_printf("fldd  ");
915             ppHRegARM(i->ARMin.VLdStD.dD);
916             vex_printf(", ");
917             ppARMAModeV(i->ARMin.VLdStD.amode);
918          } else {
919             vex_printf("fstd  ");
920             ppARMAModeV(i->ARMin.VLdStD.amode);
921             vex_printf(", ");
922             ppHRegARM(i->ARMin.VLdStD.dD);
923          }
924          return;
925       case ARMin_VLdStS:
926          if (i->ARMin.VLdStS.isLoad) {
927             vex_printf("flds  ");
928             ppHRegARM(i->ARMin.VLdStS.fD);
929             vex_printf(", ");
930             ppARMAModeV(i->ARMin.VLdStS.amode);
931          } else {
932             vex_printf("fsts  ");
933             ppARMAModeV(i->ARMin.VLdStS.amode);
934             vex_printf(", ");
935             ppHRegARM(i->ARMin.VLdStS.fD);
936          }
937          return;
938       case ARMin_VAluD:
939          vex_printf("f%-3sd ", showARMVfpOp(i->ARMin.VAluD.op));
940          ppHRegARM(i->ARMin.VAluD.dst);
941          vex_printf(", ");
942          ppHRegARM(i->ARMin.VAluD.argL);
943          vex_printf(", ");
944          ppHRegARM(i->ARMin.VAluD.argR);
945          return;
946       case ARMin_VAluS:
947          vex_printf("f%-3ss ", showARMVfpOp(i->ARMin.VAluS.op));
948          ppHRegARM(i->ARMin.VAluS.dst);
949          vex_printf(", ");
950          ppHRegARM(i->ARMin.VAluS.argL);
951          vex_printf(", ");
952          ppHRegARM(i->ARMin.VAluS.argR);
953          return;
954       case ARMin_VUnaryD:
955          vex_printf("f%-3sd ", showARMVfpUnaryOp(i->ARMin.VUnaryD.op));
956          ppHRegARM(i->ARMin.VUnaryD.dst);
957          vex_printf(", ");
958          ppHRegARM(i->ARMin.VUnaryD.src);
959          return;
960       case ARMin_VUnaryS:
961          vex_printf("f%-3ss ", showARMVfpUnaryOp(i->ARMin.VUnaryS.op));
962          ppHRegARM(i->ARMin.VUnaryS.dst);
963          vex_printf(", ");
964          ppHRegARM(i->ARMin.VUnaryS.src);
965          return;
966       case ARMin_VCmpD:
967          vex_printf("fcmpd ");
968          ppHRegARM(i->ARMin.VCmpD.argL);
969          vex_printf(", ");
970          ppHRegARM(i->ARMin.VCmpD.argR);
971          vex_printf(" ; fmstat");
972          return;
973       case ARMin_VCMovD:
974          vex_printf("fcpyd%s ", showARMCondCode(i->ARMin.VCMovD.cond));
975          ppHRegARM(i->ARMin.VCMovD.dst);
976          vex_printf(", ");
977          ppHRegARM(i->ARMin.VCMovD.src);
978          return;
979       case ARMin_VCMovS:
980          vex_printf("fcpys%s ", showARMCondCode(i->ARMin.VCMovS.cond));
981          ppHRegARM(i->ARMin.VCMovS.dst);
982          vex_printf(", ");
983          ppHRegARM(i->ARMin.VCMovS.src);
984          return;
985       case ARMin_VCvtSD:
986          vex_printf("fcvt%s ", i->ARMin.VCvtSD.sToD ? "ds" : "sd");
987          ppHRegARM(i->ARMin.VCvtSD.dst);
988          vex_printf(", ");
989          ppHRegARM(i->ARMin.VCvtSD.src);
990          return;
991       case ARMin_VXferD:
992          vex_printf("vmov  ");
993          if (i->ARMin.VXferD.toD) {
994             ppHRegARM(i->ARMin.VXferD.dD);
995             vex_printf(", ");
996             ppHRegARM(i->ARMin.VXferD.rLo);
997             vex_printf(", ");
998             ppHRegARM(i->ARMin.VXferD.rHi);
999          } else {
1000             ppHRegARM(i->ARMin.VXferD.rLo);
1001             vex_printf(", ");
1002             ppHRegARM(i->ARMin.VXferD.rHi);
1003             vex_printf(", ");
1004             ppHRegARM(i->ARMin.VXferD.dD);
1005          }
1006          return;
1007       case ARMin_VXferS:
1008          vex_printf("vmov  ");
1009          if (i->ARMin.VXferS.toS) {
1010             ppHRegARM(i->ARMin.VXferS.fD);
1011             vex_printf(", ");
1012             ppHRegARM(i->ARMin.VXferS.rLo);
1013          } else {
1014             ppHRegARM(i->ARMin.VXferS.rLo);
1015             vex_printf(", ");
1016             ppHRegARM(i->ARMin.VXferS.fD);
1017          }
1018          return;
1019       case ARMin_VCvtID: {
1020          HChar* nm = "?";
1021          if (i->ARMin.VCvtID.iToD) {
1022             nm = i->ARMin.VCvtID.syned ? "fsitod" : "fuitod";
1023          } else {
1024             nm = i->ARMin.VCvtID.syned ? "ftosid" : "ftouid";
1025          }
1026          vex_printf("%s ", nm);
1027          ppHRegARM(i->ARMin.VCvtID.dst);
1028          vex_printf(", ");
1029          ppHRegARM(i->ARMin.VCvtID.src);
1030          return;
1031       }
1032       case ARMin_FPSCR:
1033          if (i->ARMin.FPSCR.toFPSCR) {
1034             vex_printf("fmxr  fpscr, ");
1035             ppHRegARM(i->ARMin.FPSCR.iReg);
1036          } else {
1037             vex_printf("fmrx  ");
1038             ppHRegARM(i->ARMin.FPSCR.iReg);
1039             vex_printf(", fpscr");
1040          }
1041          return;
1042       case ARMin_MFence:
1043          vex_printf("mfence (mcr 15,0,r0,c7,c10,4; 15,0,r0,c7,c10,5; "
1044                     "15,0,r0,c7,c5,4)");
1045          return;
1046
1047       unhandled:
1048          vex_printf("ppARMInstr: unhandled case (tag %d)", (Int)i->tag);
1049          vpanic("ppARMInstr(1)");
1050          return;
1051       default:
1052          vpanic("ppARMInstr(2)");
1053    }
1054 }
1055
1056
1057 /* --------- Helpers for register allocation. --------- */
1058
1059 void getRegUsage_ARMInstr ( HRegUsage* u, ARMInstr* i, Bool mode64 )
1060 {
1061    vassert(mode64 == False);
1062    initHRegUsage(u);
1063    switch (i->tag) {
1064       case ARMin_Alu:
1065          addHRegUse(u, HRmWrite, i->ARMin.Alu.dst);
1066          addHRegUse(u, HRmRead, i->ARMin.Alu.argL);
1067          addRegUsage_ARMRI84(u, i->ARMin.Alu.argR);
1068          return;
1069       case ARMin_Shift:
1070          addHRegUse(u, HRmWrite, i->ARMin.Shift.dst);
1071          addHRegUse(u, HRmRead, i->ARMin.Shift.argL);
1072          addRegUsage_ARMRI5(u, i->ARMin.Shift.argR);
1073          return;
1074       case ARMin_Unary:
1075          addHRegUse(u, HRmWrite, i->ARMin.Unary.dst);
1076          addHRegUse(u, HRmRead, i->ARMin.Unary.src);
1077          return;
1078       case ARMin_CmpOrTst:
1079          addHRegUse(u, HRmRead, i->ARMin.CmpOrTst.argL);
1080          addRegUsage_ARMRI84(u, i->ARMin.CmpOrTst.argR);
1081          return;
1082       case ARMin_Mov:
1083          addHRegUse(u, HRmWrite, i->ARMin.Mov.dst);
1084          addRegUsage_ARMRI84(u, i->ARMin.Mov.src);
1085          return;
1086       case ARMin_Imm32:
1087          addHRegUse(u, HRmWrite, i->ARMin.Imm32.dst);
1088          return;
1089       case ARMin_LdSt32:
1090          addRegUsage_ARMAMode1(u, i->ARMin.LdSt32.amode);
1091          if (i->ARMin.LdSt32.isLoad) {
1092             addHRegUse(u, HRmWrite, i->ARMin.LdSt32.rD);
1093          } else {
1094             addHRegUse(u, HRmRead, i->ARMin.LdSt32.rD);
1095          }
1096          return;
1097       case ARMin_LdSt16:
1098          addRegUsage_ARMAMode2(u, i->ARMin.LdSt16.amode);
1099          if (i->ARMin.LdSt16.isLoad) {
1100             addHRegUse(u, HRmWrite, i->ARMin.LdSt16.rD);
1101          } else {
1102             addHRegUse(u, HRmRead, i->ARMin.LdSt16.rD);
1103          }
1104          return;
1105       case ARMin_LdSt8U:
1106          addRegUsage_ARMAMode1(u, i->ARMin.LdSt8U.amode);
1107          if (i->ARMin.LdSt8U.isLoad) {
1108             addHRegUse(u, HRmWrite, i->ARMin.LdSt8U.rD);
1109          } else {
1110             addHRegUse(u, HRmRead, i->ARMin.LdSt8U.rD);
1111          }
1112          return;
1113       case ARMin_Ld8S:
1114          goto unhandled;
1115       case ARMin_Goto:
1116          /* reads the reg holding the next guest addr */
1117          addHRegUse(u, HRmRead, i->ARMin.Goto.gnext);
1118          /* writes it to the standard integer return register */
1119          addHRegUse(u, HRmWrite, hregARM_R0());
1120          /* possibly messes with the baseblock pointer */
1121          if (i->ARMin.Goto.jk != Ijk_Boring
1122              && i->ARMin.Goto.jk != Ijk_Call
1123              && i->ARMin.Goto.jk != Ijk_Ret)
1124             /* note, this is irrelevant since r8 is not actually
1125                available to the allocator.  But still .. */
1126             addHRegUse(u, HRmWrite, hregARM_R8());
1127          return;
1128       case ARMin_CMov:
1129          addHRegUse(u, HRmWrite, i->ARMin.CMov.dst);
1130          addHRegUse(u, HRmRead,  i->ARMin.CMov.dst);
1131          addRegUsage_ARMRI84(u, i->ARMin.CMov.src);
1132          return;
1133       case ARMin_Call:
1134          /* logic and comments copied/modified from x86 back end */
1135          /* This is a bit subtle. */
1136          /* First off, claim it trashes all the caller-saved regs
1137             which fall within the register allocator's jurisdiction.
1138             These I believe to be r0,1,2,3.  If it turns out that r9
1139             is also caller-saved, then we'll have to add that here
1140             too. */
1141          addHRegUse(u, HRmWrite, hregARM_R0());
1142          addHRegUse(u, HRmWrite, hregARM_R1());
1143          addHRegUse(u, HRmWrite, hregARM_R2());
1144          addHRegUse(u, HRmWrite, hregARM_R3());
1145          /* Now we have to state any parameter-carrying registers
1146             which might be read.  This depends on nArgRegs. */
1147          switch (i->ARMin.Call.nArgRegs) {
1148             case 4: addHRegUse(u, HRmRead, hregARM_R3()); /*fallthru*/
1149             case 3: addHRegUse(u, HRmRead, hregARM_R2()); /*fallthru*/
1150             case 2: addHRegUse(u, HRmRead, hregARM_R1()); /*fallthru*/
1151             case 1: addHRegUse(u, HRmRead, hregARM_R0()); break;
1152             case 0: break;
1153             default: vpanic("getRegUsage_ARM:Call:regparms");
1154          }
1155          /* Finally, there is the issue that the insn trashes a
1156             register because the literal target address has to be
1157             loaded into a register.  Fortunately, for the nArgRegs=
1158             0/1/2/3 case, we can use r0, r1, r2 or r3 respectively, so
1159             this does not cause any further damage.  For the
1160             nArgRegs=4 case, we'll have to choose another register
1161             arbitrarily since all the caller saved regs are used for
1162             parameters, and so we might as well choose r11.
1163             */
1164          if (i->ARMin.Call.nArgRegs == 4)
1165             addHRegUse(u, HRmWrite, hregARM_R11());
1166          /* Upshot of this is that the assembler really must observe
1167             the here-stated convention of which register to use as an
1168             address temporary, depending on nArgRegs: 0==r0,
1169             1==r1, 2==r2, 3==r3, 4==r11 */
1170          return;
1171       case ARMin_Mul:
1172          addHRegUse(u, HRmRead, hregARM_R2());
1173          addHRegUse(u, HRmRead, hregARM_R3());
1174          addHRegUse(u, HRmWrite, hregARM_R0());
1175          if (i->ARMin.Mul.op != ARMmul_PLAIN)
1176             addHRegUse(u, HRmWrite, hregARM_R1());
1177          return;
1178       case ARMin_LdrEX:
1179          addHRegUse(u, HRmWrite, hregARM_R0());
1180          addHRegUse(u, HRmRead, hregARM_R1());
1181          return;
1182       case ARMin_StrEX:
1183          addHRegUse(u, HRmWrite, hregARM_R0());
1184          addHRegUse(u, HRmRead, hregARM_R1());
1185          addHRegUse(u, HRmRead, hregARM_R2());
1186          return;
1187       case ARMin_VLdStD:
1188          addRegUsage_ARMAModeV(u, i->ARMin.VLdStD.amode);
1189          if (i->ARMin.VLdStD.isLoad) {
1190             addHRegUse(u, HRmWrite, i->ARMin.VLdStD.dD);
1191          } else {
1192             addHRegUse(u, HRmRead, i->ARMin.VLdStD.dD);
1193          }
1194          return;
1195       case ARMin_VLdStS:
1196          addRegUsage_ARMAModeV(u, i->ARMin.VLdStS.amode);
1197          if (i->ARMin.VLdStS.isLoad) {
1198             addHRegUse(u, HRmWrite, i->ARMin.VLdStS.fD);
1199          } else {
1200             addHRegUse(u, HRmRead, i->ARMin.VLdStS.fD);
1201          }
1202          return;
1203       case ARMin_VAluD:
1204          addHRegUse(u, HRmWrite, i->ARMin.VAluD.dst);
1205          addHRegUse(u, HRmRead, i->ARMin.VAluD.argL);
1206          addHRegUse(u, HRmRead, i->ARMin.VAluD.argR);
1207          return;
1208       case ARMin_VAluS:
1209          addHRegUse(u, HRmWrite, i->ARMin.VAluS.dst);
1210          addHRegUse(u, HRmRead, i->ARMin.VAluS.argL);
1211          addHRegUse(u, HRmRead, i->ARMin.VAluS.argR);
1212          return;
1213       case ARMin_VUnaryD:
1214          addHRegUse(u, HRmWrite, i->ARMin.VUnaryD.dst);
1215          addHRegUse(u, HRmRead, i->ARMin.VUnaryD.src);
1216          return;
1217       case ARMin_VUnaryS:
1218          addHRegUse(u, HRmWrite, i->ARMin.VUnaryS.dst);
1219          addHRegUse(u, HRmRead, i->ARMin.VUnaryS.src);
1220          return;
1221       case ARMin_VCmpD:
1222          addHRegUse(u, HRmRead, i->ARMin.VCmpD.argL);
1223          addHRegUse(u, HRmRead, i->ARMin.VCmpD.argR);
1224          return;
1225       case ARMin_VCMovD:
1226          addHRegUse(u, HRmWrite, i->ARMin.VCMovD.dst);
1227          addHRegUse(u, HRmRead,  i->ARMin.VCMovD.dst);
1228          addHRegUse(u, HRmRead,  i->ARMin.VCMovD.src);
1229          return;
1230       case ARMin_VCMovS:
1231          addHRegUse(u, HRmWrite, i->ARMin.VCMovS.dst);
1232          addHRegUse(u, HRmRead,  i->ARMin.VCMovS.dst);
1233          addHRegUse(u, HRmRead,  i->ARMin.VCMovS.src);
1234          return;
1235       case ARMin_VCvtSD:
1236          addHRegUse(u, HRmWrite, i->ARMin.VCvtSD.dst);
1237          addHRegUse(u, HRmRead,  i->ARMin.VCvtSD.src);
1238          return;
1239       case ARMin_VXferD:
1240          if (i->ARMin.VXferD.toD) {
1241             addHRegUse(u, HRmWrite, i->ARMin.VXferD.dD);
1242             addHRegUse(u, HRmRead,  i->ARMin.VXferD.rHi);
1243             addHRegUse(u, HRmRead,  i->ARMin.VXferD.rLo);
1244          } else {
1245             addHRegUse(u, HRmRead,  i->ARMin.VXferD.dD);
1246             addHRegUse(u, HRmWrite, i->ARMin.VXferD.rHi);
1247             addHRegUse(u, HRmWrite, i->ARMin.VXferD.rLo);
1248          }
1249          return;
1250       case ARMin_VXferS:
1251          if (i->ARMin.VXferS.toS) {
1252             addHRegUse(u, HRmWrite, i->ARMin.VXferS.fD);
1253             addHRegUse(u, HRmRead,  i->ARMin.VXferS.rLo);
1254          } else {
1255             addHRegUse(u, HRmRead,  i->ARMin.VXferS.fD);
1256             addHRegUse(u, HRmWrite, i->ARMin.VXferS.rLo);
1257          }
1258          return;
1259       case ARMin_VCvtID:
1260          addHRegUse(u, HRmWrite, i->ARMin.VCvtID.dst);
1261          addHRegUse(u, HRmRead,  i->ARMin.VCvtID.src);
1262          return;
1263       case ARMin_FPSCR:
1264          if (i->ARMin.FPSCR.toFPSCR)
1265             addHRegUse(u, HRmRead, i->ARMin.FPSCR.iReg);
1266          else
1267             addHRegUse(u, HRmWrite, i->ARMin.FPSCR.iReg);
1268          return;
1269       case ARMin_MFence:
1270          return;
1271       unhandled:
1272       default:
1273          ppARMInstr(i);
1274          vpanic("getRegUsage_ARMInstr");
1275    }
1276 }
1277
1278
1279 void mapRegs_ARMInstr ( HRegRemap* m, ARMInstr* i, Bool mode64 )
1280 {
1281    vassert(mode64 == False);
1282    switch (i->tag) {
1283       case ARMin_Alu:
1284          i->ARMin.Alu.dst = lookupHRegRemap(m, i->ARMin.Alu.dst);
1285          i->ARMin.Alu.argL = lookupHRegRemap(m, i->ARMin.Alu.argL);
1286          mapRegs_ARMRI84(m, i->ARMin.Alu.argR);
1287          return;
1288       case ARMin_Shift:
1289          i->ARMin.Shift.dst = lookupHRegRemap(m, i->ARMin.Shift.dst);
1290          i->ARMin.Shift.argL = lookupHRegRemap(m, i->ARMin.Shift.argL);
1291          mapRegs_ARMRI5(m, i->ARMin.Shift.argR);
1292          return;
1293       case ARMin_Unary:
1294          i->ARMin.Unary.dst = lookupHRegRemap(m, i->ARMin.Unary.dst);
1295          i->ARMin.Unary.src = lookupHRegRemap(m, i->ARMin.Unary.src);
1296          return;
1297       case ARMin_CmpOrTst:
1298          i->ARMin.CmpOrTst.argL = lookupHRegRemap(m, i->ARMin.CmpOrTst.argL);
1299          mapRegs_ARMRI84(m, i->ARMin.CmpOrTst.argR);
1300          return;
1301       case ARMin_Mov:
1302          i->ARMin.Mov.dst = lookupHRegRemap(m, i->ARMin.Mov.dst);
1303          mapRegs_ARMRI84(m, i->ARMin.Mov.src);
1304          return;
1305       case ARMin_Imm32:
1306          i->ARMin.Imm32.dst = lookupHRegRemap(m, i->ARMin.Imm32.dst);
1307          return;
1308       case ARMin_LdSt32:
1309          i->ARMin.LdSt32.rD = lookupHRegRemap(m, i->ARMin.LdSt32.rD);
1310          mapRegs_ARMAMode1(m, i->ARMin.LdSt32.amode);
1311          return;
1312       case ARMin_LdSt16:
1313          i->ARMin.LdSt16.rD = lookupHRegRemap(m, i->ARMin.LdSt16.rD);
1314          mapRegs_ARMAMode2(m, i->ARMin.LdSt16.amode);
1315          return;
1316       case ARMin_LdSt8U:
1317          i->ARMin.LdSt8U.rD = lookupHRegRemap(m, i->ARMin.LdSt8U.rD);
1318          mapRegs_ARMAMode1(m, i->ARMin.LdSt8U.amode);
1319          return;
1320       case ARMin_Ld8S:
1321          goto unhandled;
1322       case ARMin_Goto:
1323          i->ARMin.Goto.gnext = lookupHRegRemap(m, i->ARMin.Goto.gnext);
1324          return;
1325       case ARMin_CMov:
1326          i->ARMin.CMov.dst = lookupHRegRemap(m, i->ARMin.CMov.dst);
1327          mapRegs_ARMRI84(m, i->ARMin.CMov.src);
1328          return;
1329       case ARMin_Call:
1330          return;
1331       case ARMin_Mul:
1332          return;
1333       case ARMin_LdrEX:
1334          return;
1335       case ARMin_StrEX:
1336          return;
1337       case ARMin_VLdStD:
1338          i->ARMin.VLdStD.dD = lookupHRegRemap(m, i->ARMin.VLdStD.dD);
1339          mapRegs_ARMAModeV(m, i->ARMin.VLdStD.amode);
1340          return;
1341       case ARMin_VLdStS:
1342          i->ARMin.VLdStS.fD = lookupHRegRemap(m, i->ARMin.VLdStS.fD);
1343          mapRegs_ARMAModeV(m, i->ARMin.VLdStS.amode);
1344          return;
1345       case ARMin_VAluD:
1346          i->ARMin.VAluD.dst  = lookupHRegRemap(m, i->ARMin.VAluD.dst);
1347          i->ARMin.VAluD.argL = lookupHRegRemap(m, i->ARMin.VAluD.argL);
1348          i->ARMin.VAluD.argR = lookupHRegRemap(m, i->ARMin.VAluD.argR);
1349          return;
1350       case ARMin_VAluS:
1351          i->ARMin.VAluS.dst  = lookupHRegRemap(m, i->ARMin.VAluS.dst);
1352          i->ARMin.VAluS.argL = lookupHRegRemap(m, i->ARMin.VAluS.argL);
1353          i->ARMin.VAluS.argR = lookupHRegRemap(m, i->ARMin.VAluS.argR);
1354          return;
1355       case ARMin_VUnaryD:
1356          i->ARMin.VUnaryD.dst = lookupHRegRemap(m, i->ARMin.VUnaryD.dst);
1357          i->ARMin.VUnaryD.src = lookupHRegRemap(m, i->ARMin.VUnaryD.src);
1358          return;
1359       case ARMin_VUnaryS:
1360          i->ARMin.VUnaryS.dst = lookupHRegRemap(m, i->ARMin.VUnaryS.dst);
1361          i->ARMin.VUnaryS.src = lookupHRegRemap(m, i->ARMin.VUnaryS.src);
1362          return;
1363       case ARMin_VCmpD:
1364          i->ARMin.VCmpD.argL = lookupHRegRemap(m, i->ARMin.VCmpD.argL);
1365          i->ARMin.VCmpD.argR = lookupHRegRemap(m, i->ARMin.VCmpD.argR);
1366          return;
1367       case ARMin_VCMovD:
1368          i->ARMin.VCMovD.dst = lookupHRegRemap(m, i->ARMin.VCMovD.dst);
1369          i->ARMin.VCMovD.src = lookupHRegRemap(m, i->ARMin.VCMovD.src);
1370          return;
1371       case ARMin_VCMovS:
1372          i->ARMin.VCMovS.dst = lookupHRegRemap(m, i->ARMin.VCMovS.dst);
1373          i->ARMin.VCMovS.src = lookupHRegRemap(m, i->ARMin.VCMovS.src);
1374          return;
1375       case ARMin_VCvtSD:
1376          i->ARMin.VCvtSD.dst = lookupHRegRemap(m, i->ARMin.VCvtSD.dst);
1377          i->ARMin.VCvtSD.src = lookupHRegRemap(m, i->ARMin.VCvtSD.src);
1378          return;
1379       case ARMin_VXferD:
1380          i->ARMin.VXferD.dD  = lookupHRegRemap(m, i->ARMin.VXferD.dD);
1381          i->ARMin.VXferD.rHi = lookupHRegRemap(m, i->ARMin.VXferD.rHi);
1382          i->ARMin.VXferD.rLo = lookupHRegRemap(m, i->ARMin.VXferD.rLo);
1383          return;
1384       case ARMin_VXferS:
1385          i->ARMin.VXferS.fD  = lookupHRegRemap(m, i->ARMin.VXferS.fD);
1386          i->ARMin.VXferS.rLo = lookupHRegRemap(m, i->ARMin.VXferS.rLo);
1387          return;
1388       case ARMin_VCvtID:
1389          i->ARMin.VCvtID.dst = lookupHRegRemap(m, i->ARMin.VCvtID.dst);
1390          i->ARMin.VCvtID.src = lookupHRegRemap(m, i->ARMin.VCvtID.src);
1391          return;
1392       case ARMin_FPSCR:
1393          i->ARMin.FPSCR.iReg = lookupHRegRemap(m, i->ARMin.FPSCR.iReg);
1394          return;
1395       case ARMin_MFence:
1396          return;
1397       unhandled:
1398       default:
1399          ppARMInstr(i);
1400          vpanic("mapRegs_ARMInstr");
1401    }
1402 }
1403
1404 /* Figure out if i represents a reg-reg move, and if so assign the
1405    source and destination to *src and *dst.  If in doubt say No.  Used
1406    by the register allocator to do move coalescing. 
1407 */
1408 Bool isMove_ARMInstr ( ARMInstr* i, HReg* src, HReg* dst )
1409 {
1410    /* Moves between integer regs */
1411    switch (i->tag) {
1412       case ARMin_Mov:
1413          if (i->ARMin.Mov.src->tag == ARMri84_R) {
1414             *src = i->ARMin.Mov.src->ARMri84.R.reg;
1415             *dst = i->ARMin.Mov.dst;
1416             return True;
1417          }
1418          break;
1419       case ARMin_VUnaryD:
1420          if (i->ARMin.VUnaryD.op == ARMvfpu_COPY) {
1421             *src = i->ARMin.VUnaryD.src;
1422             *dst = i->ARMin.VUnaryD.dst;
1423             return True;
1424          }
1425          break;
1426       case ARMin_VUnaryS:
1427          if (i->ARMin.VUnaryS.op == ARMvfpu_COPY) {
1428             *src = i->ARMin.VUnaryS.src;
1429             *dst = i->ARMin.VUnaryS.dst;
1430             return True;
1431          }
1432          break;
1433       default:
1434          break;
1435    }
1436
1437    // todo: float, vector moves
1438    return False;
1439 }
1440
1441
1442 /* Generate arm spill/reload instructions under the direction of the
1443    register allocator.  Note it's critical these don't write the
1444    condition codes. */
1445
1446 void genSpill_ARM ( /*OUT*/HInstr** i1, /*OUT*/HInstr** i2,
1447                     HReg rreg, Int offsetB, Bool mode64 )
1448 {
1449    HRegClass rclass;
1450    vassert(offsetB >= 0);
1451    vassert(!hregIsVirtual(rreg));
1452    vassert(mode64 == False);
1453    *i1 = *i2 = NULL;
1454    rclass = hregClass(rreg);
1455    switch (rclass) {
1456       case HRcInt32:
1457          vassert(offsetB <= 4095);
1458          *i1 = ARMInstr_LdSt32( False/*!isLoad*/, 
1459                                 rreg, 
1460                                 ARMAMode1_RI(hregARM_R8(), offsetB) );
1461          return;
1462       case HRcFlt32:
1463       case HRcFlt64: {
1464          HReg r8   = hregARM_R8();  /* baseblock */
1465          HReg r12  = hregARM_R12(); /* spill temp */
1466          HReg base = r8;
1467          vassert(0 == (offsetB & 3));
1468          if (offsetB >= 1024) {
1469             *i1 = ARMInstr_Alu(ARMalu_ADD, r12, r8,
1470                                ARMRI84_I84(1,11)); /* 1024 */
1471             offsetB -= 1024;
1472             base = r12;
1473          }
1474          vassert(offsetB <= 1020);
1475          if (rclass == HRcFlt32) {
1476             *i2 = ARMInstr_VLdStS( False/*!isLoad*/,
1477                                    rreg,
1478                                    mkARMAModeV(base, offsetB) );
1479          } else {
1480             *i2 = ARMInstr_VLdStD( False/*!isLoad*/,
1481                                    rreg,
1482                                    mkARMAModeV(base, offsetB) );
1483          }
1484          return;
1485       }
1486       default: 
1487          ppHRegClass(rclass);
1488          vpanic("genSpill_ARM: unimplemented regclass");
1489    }
1490 }
1491
1492 void genReload_ARM ( /*OUT*/HInstr** i1, /*OUT*/HInstr** i2,
1493                      HReg rreg, Int offsetB, Bool mode64 )
1494 {
1495    HRegClass rclass;
1496    vassert(offsetB >= 0);
1497    vassert(!hregIsVirtual(rreg));
1498    vassert(mode64 == False);
1499    *i1 = *i2 = NULL;
1500    rclass = hregClass(rreg);
1501    switch (rclass) {
1502       case HRcInt32:
1503          vassert(offsetB <= 4095);
1504          *i1 = ARMInstr_LdSt32( True/*isLoad*/, 
1505                                 rreg, 
1506                                 ARMAMode1_RI(hregARM_R8(), offsetB) );
1507          return;
1508       case HRcFlt32:
1509       case HRcFlt64: {
1510          HReg r8   = hregARM_R8();  /* baseblock */
1511          HReg r12  = hregARM_R12(); /* spill temp */
1512          HReg base = r8;
1513          vassert(0 == (offsetB & 3));
1514          if (offsetB >= 1024) {
1515             *i1 = ARMInstr_Alu(ARMalu_ADD, r12, r8,
1516                                ARMRI84_I84(1,11)); /* 1024 */
1517             offsetB -= 1024;
1518             base = r12;
1519          }
1520          vassert(offsetB <= 1020);
1521          if (rclass == HRcFlt32) {
1522             *i2 = ARMInstr_VLdStS( True/*isLoad*/,
1523                                    rreg,
1524                                    mkARMAModeV(base, offsetB) );
1525          } else {
1526             *i2 = ARMInstr_VLdStD( True/*isLoad*/,
1527                                    rreg,
1528                                    mkARMAModeV(base, offsetB) );
1529          }
1530          return;
1531       }
1532       default: 
1533          ppHRegClass(rclass);
1534          vpanic("genReload_ARM: unimplemented regclass");
1535    }
1536 }
1537
1538
1539 /* Emit an instruction into buf and return the number of bytes used.
1540    Note that buf is not the insn's final place, and therefore it is
1541    imperative to emit position-independent code. */
1542
1543 static inline UChar iregNo ( HReg r )
1544 {
1545    UInt n;
1546    vassert(hregClass(r) == HRcInt32);
1547    vassert(!hregIsVirtual(r));
1548    n = hregNumber(r);
1549    vassert(n <= 15);
1550    return toUChar(n);
1551 }
1552
1553 static inline UChar dregNo ( HReg r )
1554 {
1555    UInt n;
1556    vassert(hregClass(r) == HRcFlt64);
1557    vassert(!hregIsVirtual(r));
1558    n = hregNumber(r);
1559    vassert(n <= 15);
1560    return toUChar(n);
1561 }
1562
1563 static inline UChar fregNo ( HReg r )
1564 {
1565    UInt n;
1566    vassert(hregClass(r) == HRcFlt32);
1567    vassert(!hregIsVirtual(r));
1568    n = hregNumber(r);
1569    vassert(n <= 31);
1570    return toUChar(n);
1571 }
1572
1573 #define BITS4(zzb3,zzb2,zzb1,zzb0) \
1574    (((zzb3) << 3) | ((zzb2) << 2) | ((zzb1) << 1) | (zzb0))
1575 #define X0000  BITS4(0,0,0,0)
1576 #define X0001  BITS4(0,0,0,1)
1577 #define X0010  BITS4(0,0,1,0)
1578 #define X0011  BITS4(0,0,1,1)
1579 #define X0100  BITS4(0,1,0,0)
1580 #define X0101  BITS4(0,1,0,1)
1581 #define X0110  BITS4(0,1,1,0)
1582 #define X0111  BITS4(0,1,1,1)
1583 #define X1000  BITS4(1,0,0,0)
1584 #define X1001  BITS4(1,0,0,1)
1585 #define X1010  BITS4(1,0,1,0)
1586 #define X1011  BITS4(1,0,1,1)
1587 #define X1100  BITS4(1,1,0,0)
1588 #define X1101  BITS4(1,1,0,1)
1589 #define X1110  BITS4(1,1,1,0)
1590 #define X1111  BITS4(1,1,1,1)
1591
1592 #define XXXXX___(zzx7,zzx6,zzx5,zzx4,zzx3) \
1593    ((((zzx7) & 0xF) << 28) | (((zzx6) & 0xF) << 24) |  \
1594     (((zzx5) & 0xF) << 20) | (((zzx4) & 0xF) << 16) |  \
1595     (((zzx3) & 0xF) << 12))
1596
1597 #define XXXXXX__(zzx7,zzx6,zzx5,zzx4,zzx3,zzx2)        \
1598    ((((zzx7) & 0xF) << 28) | (((zzx6) & 0xF) << 24) |  \
1599     (((zzx5) & 0xF) << 20) | (((zzx4) & 0xF) << 16) |  \
1600     (((zzx3) & 0xF) << 12) | (((zzx2) & 0xF) <<  8))
1601
1602 #define XXXXX__X(zzx7,zzx6,zzx5,zzx4,zzx3,zzx0)        \
1603    ((((zzx7) & 0xF) << 28) | (((zzx6) & 0xF) << 24) |  \
1604     (((zzx5) & 0xF) << 20) | (((zzx4) & 0xF) << 16) |  \
1605     (((zzx3) & 0xF) << 12) | (((zzx0) & 0xF) <<  0))
1606
1607 #define XXX___XX(zzx7,zzx6,zzx5,zzx1,zzx0) \
1608   ((((zzx7) & 0xF) << 28) | (((zzx6) & 0xF) << 24) | \
1609    (((zzx5) & 0xF) << 20) | (((zzx1) & 0xF) << 4) | \
1610    (((zzx0) & 0xF) << 0))
1611
1612 #define XXXXXXXX(zzx7,zzx6,zzx5,zzx4,zzx3,zzx2,zzx1,zzx0)  \
1613    ((((zzx7) & 0xF) << 28) | (((zzx6) & 0xF) << 24) |  \
1614     (((zzx5) & 0xF) << 20) | (((zzx4) & 0xF) << 16) |  \
1615     (((zzx3) & 0xF) << 12) | (((zzx2) & 0xF) <<  8) |  \
1616     (((zzx1) & 0xF) <<  4) | (((zzx0) & 0xF) <<  0))
1617
1618 /* Generate a skeletal insn that involves an a RI84 shifter operand.
1619    Returns a word which is all zeroes apart from bits 25 and 11..0,
1620    since it is those that encode the shifter operand (at least to the
1621    extent that we care about it.) */
1622 static UInt skeletal_RI84 ( ARMRI84* ri )
1623 {
1624    UInt instr;
1625    if (ri->tag == ARMri84_I84) {
1626       vassert(0 == (ri->ARMri84.I84.imm4 & ~0x0F));
1627       vassert(0 == (ri->ARMri84.I84.imm8 & ~0xFF));
1628       instr = 1 << 25;
1629       instr |= (ri->ARMri84.I84.imm4 << 8);
1630       instr |= ri->ARMri84.I84.imm8;
1631    } else {
1632       instr = 0 << 25;
1633       instr |= iregNo(ri->ARMri84.R.reg);
1634    }
1635    return instr;
1636 }
1637
1638 /* Ditto for RI5.  Resulting word is zeroes apart from bit 4 and bits
1639    11..7. */
1640 static UInt skeletal_RI5 ( ARMRI5* ri )
1641 {
1642    UInt instr;
1643    if (ri->tag == ARMri5_I5) {
1644       UInt imm5 = ri->ARMri5.I5.imm5;
1645       vassert(imm5 >= 1 && imm5 <= 31);
1646       instr = 0 << 4;
1647       instr |= imm5 << 7;
1648    } else {
1649       instr = 1 << 4;
1650       instr |= iregNo(ri->ARMri5.R.reg) << 8;
1651    }
1652    return instr;
1653 }
1654
1655
1656 /* Get an immediate into a register, using only that 
1657    register.  (very lame..) */
1658 static UInt* imm32_to_iregNo ( UInt* p, Int rD, UInt imm32 )
1659 {
1660    UInt instr;
1661    vassert(rD >= 0 && rD <= 14); // r15 not good to mess with!
1662 #if 0
1663    if (0 == (imm32 & ~0xFF)) {
1664       /* mov with a immediate shifter operand of (0, imm32) (??) */
1665       instr = XXXXXX__(X1110,X0011,X1010,X0000,rD,X0000);
1666       instr |= imm32;
1667       *p++ = instr;
1668    } else {
1669       // this is very bad; causes Dcache pollution
1670       // ldr  rD, [pc]
1671       instr = XXXXX___(X1110,X0101,X1001,X1111,rD);
1672       *p++ = instr;
1673       // b .+8
1674       instr = 0xEA000000;
1675       *p++ = instr;
1676       // .word imm32
1677       *p++ = imm32;
1678    }
1679 #else
1680    /* Generate movw rD, #low16.  Then, if the high 16 are
1681       nonzero, generate movt rD, #high16. */
1682    UInt lo16 = imm32 & 0xFFFF;
1683    UInt hi16 = (imm32 >> 16) & 0xFFFF;
1684    instr = XXXXXXXX(0xE, 0x3, 0x0, (lo16 >> 12) & 0xF, rD,
1685                     (lo16 >> 8) & 0xF, (lo16 >> 4) & 0xF,
1686                     lo16 & 0xF);
1687    *p++ = instr;
1688    if (hi16 != 0) {
1689       instr = XXXXXXXX(0xE, 0x3, 0x4, (hi16 >> 12) & 0xF, rD,
1690                        (hi16 >> 8) & 0xF, (hi16 >> 4) & 0xF,
1691                        hi16 & 0xF);
1692       *p++ = instr;
1693    }
1694 #endif
1695    return p;
1696 }
1697
1698
1699 Int emit_ARMInstr ( UChar* buf, Int nbuf, ARMInstr* i,
1700                     Bool mode64, void* dispatch ) 
1701 {
1702    UInt* p = (UInt*)buf;
1703    vassert(nbuf >= 32);
1704    vassert(mode64 == False);
1705    vassert(0 == (((HWord)buf) & 3));
1706    /* since we branch to lr(r13) to get back to dispatch: */
1707    vassert(dispatch == NULL);
1708
1709    switch (i->tag) {
1710       case ARMin_Alu: {
1711          UInt     instr, subopc;
1712          UInt     rD   = iregNo(i->ARMin.Alu.dst);
1713          UInt     rN   = iregNo(i->ARMin.Alu.argL);
1714          ARMRI84* argR = i->ARMin.Alu.argR;
1715          switch (i->ARMin.Alu.op) {
1716             case ARMalu_ADDS: /* fallthru */
1717             case ARMalu_ADD:  subopc = X0100; break;
1718             case ARMalu_ADC:  subopc = X0101; break;
1719             case ARMalu_SUBS: /* fallthru */
1720             case ARMalu_SUB:  subopc = X0010; break;
1721             case ARMalu_SBC:  subopc = X0110; break;
1722             case ARMalu_AND:  subopc = X0000; break;
1723             case ARMalu_BIC:  subopc = X1110; break;
1724             case ARMalu_OR:   subopc = X1100; break;
1725             case ARMalu_XOR:  subopc = X0001; break;
1726             default: goto bad;
1727          }
1728          instr = skeletal_RI84(argR);
1729          instr |= XXXXX___(X1110, (1 & (subopc >> 3)),
1730                            (subopc << 1) & 0xF, rN, rD);
1731          if (i->ARMin.Alu.op == ARMalu_ADDS || i->ARMin.Alu.op == ARMalu_SUBS) {
1732             instr |= 1<<20;  /* set the S bit */
1733          }
1734          *p++ = instr;
1735          goto done;
1736       }
1737       case ARMin_Shift: {
1738          UInt    instr, subopc;
1739          HReg    rD   = iregNo(i->ARMin.Shift.dst);
1740          HReg    rM   = iregNo(i->ARMin.Shift.argL);
1741          ARMRI5* argR = i->ARMin.Shift.argR;
1742          switch (i->ARMin.Shift.op) {
1743             case ARMsh_SHL: subopc = X0000; break;
1744             case ARMsh_SHR: subopc = X0001; break;
1745             case ARMsh_SAR: subopc = X0010; break;
1746             default: goto bad;
1747          }
1748          instr = skeletal_RI5(argR);
1749          instr |= XXXXX__X(X1110,X0001,X1010,X0000,rD, /* _ _ */ rM);
1750          instr |= (subopc & 3) << 5;
1751          *p++ = instr;
1752          goto done;
1753       }
1754       case ARMin_Unary: {
1755          UInt instr;
1756          HReg rDst = iregNo(i->ARMin.Unary.dst);
1757          HReg rSrc = iregNo(i->ARMin.Unary.src);
1758          switch (i->ARMin.Unary.op) {
1759             case ARMun_CLZ:
1760                instr = XXXXXXXX(X1110,X0001,X0110,X1111,
1761                                 rDst,X1111,X0001,rSrc);
1762                *p++ = instr;
1763                goto done;
1764             case ARMun_NEG: /* RSB rD,rS,#0 */
1765                instr = XXXXX___(X1110,0x2,0x6,rSrc,rDst);
1766                *p++ = instr;
1767                goto done;
1768             case ARMun_NOT: {
1769                UInt subopc = X1111; /* MVN */
1770                instr = rSrc;
1771                instr |= XXXXX___(X1110, (1 & (subopc >> 3)),
1772                                  (subopc << 1) & 0xF, 0, rDst);
1773                *p++ = instr;
1774                goto done;
1775             }
1776             default:
1777                break;
1778          }
1779          goto bad;
1780       }
1781       case ARMin_CmpOrTst: {
1782          UInt instr  = skeletal_RI84(i->ARMin.CmpOrTst.argR);
1783          UInt subopc = i->ARMin.CmpOrTst.isCmp ? X1010 : X1000;
1784          UInt SBZ    = 0;
1785          instr |= XXXXX___(X1110, (1 & (subopc >> 3)),
1786                            ((subopc << 1) & 0xF) | 1,
1787                            i->ARMin.CmpOrTst.argL, SBZ );
1788          *p++ = instr;
1789          goto done;
1790       }
1791       case ARMin_Mov: {
1792          UInt instr  = skeletal_RI84(i->ARMin.Mov.src);
1793          UInt subopc = X1101; /* MOV */
1794          UInt SBZ    = 0;
1795          instr |= XXXXX___(X1110, (1 & (subopc >> 3)),
1796                            (subopc << 1) & 0xF, SBZ, i->ARMin.Mov.dst);
1797          *p++ = instr;
1798          goto done;
1799       }
1800       case ARMin_Imm32: {
1801          p = imm32_to_iregNo( (UInt*)p, iregNo(i->ARMin.Imm32.dst),
1802                                         i->ARMin.Imm32.imm32 );
1803          goto done;
1804       }
1805       case ARMin_LdSt32:
1806       case ARMin_LdSt8U: {
1807          UInt       bL, bB;
1808          HReg       rD;
1809          ARMAMode1* am;
1810          if (i->tag == ARMin_LdSt32) {
1811             bB = 0;
1812             bL = i->ARMin.LdSt32.isLoad ? 1 : 0;
1813             am = i->ARMin.LdSt32.amode;
1814             rD = i->ARMin.LdSt32.rD;
1815          } else {
1816             bB = 1;
1817             bL = i->ARMin.LdSt8U.isLoad ? 1 : 0;
1818             am = i->ARMin.LdSt8U.amode;
1819             rD = i->ARMin.LdSt8U.rD;
1820          }
1821          if (am->tag == ARMam1_RI) {
1822             Int  simm12;
1823             UInt instr, bP;
1824             if (am->ARMam1.RI.simm13 < 0) {
1825                bP = 0;
1826                simm12 = -am->ARMam1.RI.simm13;
1827             } else {
1828                bP = 1;
1829                simm12 = am->ARMam1.RI.simm13;
1830             }
1831             vassert(simm12 >= 0 && simm12 <= 4095);
1832             instr = XXXXX___(X1110,X0101,BITS4(bP,bB,0,bL),
1833                              iregNo(am->ARMam1.RI.reg),
1834                              iregNo(rD));
1835             instr |= simm12;
1836             *p++ = instr;
1837             goto done;
1838          } else {
1839             // RR case
1840             goto bad;
1841          }
1842       }
1843       case ARMin_LdSt16: {
1844          HReg       rD = i->ARMin.LdSt16.rD;
1845          UInt       bS = i->ARMin.LdSt16.signedLoad ? 1 : 0;
1846          UInt       bL = i->ARMin.LdSt16.isLoad ? 1 : 0;
1847          ARMAMode2* am = i->ARMin.LdSt16.amode;
1848          if (am->tag == ARMam2_RI) {
1849             HReg rN = am->ARMam2.RI.reg;
1850             Int  simm8;
1851             UInt bP, imm8hi, imm8lo, instr;
1852             if (am->ARMam2.RI.simm9 < 0) {
1853                bP = 0;
1854                simm8 = -am->ARMam2.RI.simm9;
1855             } else {
1856                bP = 1;
1857                simm8 = am->ARMam2.RI.simm9;
1858             }
1859             vassert(simm8 >= 0 && simm8 <= 255);
1860             imm8hi = (simm8 >> 4) & 0xF;
1861             imm8lo = simm8 & 0xF;
1862             vassert(!(bL == 0 && bS == 1)); // "! signed store"
1863             /**/ if (bL == 0 && bS == 0) {
1864                // strh
1865                instr = XXXXXXXX(X1110,X0001, BITS4(bP,1,0,0), iregNo(rN),
1866                                 iregNo(rD), imm8hi, X1011, imm8lo);
1867                *p++ = instr;
1868                goto done;
1869             }
1870             else if (bL == 1 && bS == 0) {
1871                // ldrh
1872                instr = XXXXXXXX(X1110,X0001, BITS4(bP,1,0,1), iregNo(rN),
1873                                 iregNo(rD), imm8hi, X1011, imm8lo);
1874                *p++ = instr;
1875                goto done;
1876             }
1877             else if (bL == 1 && bS == 1) {
1878                goto bad;
1879             }
1880             else vassert(0); // ill-constructed insn
1881          } else {
1882             // RR case
1883             goto bad;
1884          }
1885       }
1886       case ARMin_Ld8S:
1887          goto bad;
1888       case ARMin_Goto: {
1889          UInt        instr;
1890          IRJumpKind  jk    = i->ARMin.Goto.jk;
1891          ARMCondCode cond  = i->ARMin.Goto.cond;
1892          UInt        rnext = iregNo(i->ARMin.Goto.gnext);
1893          Int         trc   = -1;
1894          switch (jk) {
1895             case Ijk_Ret: case Ijk_Call: case Ijk_Boring:
1896                break; /* no need to set GST in these common cases */
1897             case Ijk_ClientReq:
1898                trc = VEX_TRC_JMP_CLIENTREQ; break;
1899             case Ijk_Sys_int128:
1900             case Ijk_Sys_int129:
1901             case Ijk_Sys_int130:
1902             case Ijk_Yield:
1903             case Ijk_EmWarn:
1904             case Ijk_MapFail:
1905                goto unhandled_jk;
1906             case Ijk_NoDecode:
1907                trc = VEX_TRC_JMP_NODECODE; break;
1908             case Ijk_TInval:
1909                trc = VEX_TRC_JMP_TINVAL; break;
1910             case Ijk_NoRedir:
1911                trc = VEX_TRC_JMP_NOREDIR; break;
1912             case Ijk_Sys_sysenter:
1913             case Ijk_SigTRAP:
1914             case Ijk_SigSEGV:
1915                goto unhandled_jk;
1916             case Ijk_Sys_syscall:
1917                trc = VEX_TRC_JMP_SYS_SYSCALL; break;
1918             unhandled_jk:
1919             default:
1920                goto bad;
1921          }
1922          if (trc != -1) {
1923             // mov{cond} r8, #trc
1924             vassert(trc >= 0 && trc <= 255);
1925             instr = (cond << 28) | 0x03A08000 | (0xFF & (UInt)trc);
1926             *p++ = instr;
1927          }
1928          // mov{cond} r0, rnext
1929          if (rnext != 0) {
1930             instr = (cond << 28) | 0x01A00000 | rnext;
1931             *p++ = instr;
1932          }
1933          // bx{cond} r14
1934          instr =(cond << 28) | 0x012FFF1E;
1935          *p++ = instr;
1936          goto done;
1937       }
1938       case ARMin_CMov: {
1939          UInt instr  = skeletal_RI84(i->ARMin.CMov.src);
1940          UInt subopc = X1101; /* MOV */
1941          UInt SBZ    = 0;
1942          instr |= XXXXX___(i->ARMin.CMov.cond, (1 & (subopc >> 3)),
1943                            (subopc << 1) & 0xF, SBZ, i->ARMin.CMov.dst);
1944          *p++ = instr;
1945          goto done;
1946       }
1947       case ARMin_Call: {
1948          UInt instr;
1949          /* Decide on a scratch reg used to hold to the call address.
1950             This has to be done as per the comments in getRegUsage. */
1951          Int scratchNo;
1952          switch (i->ARMin.Call.nArgRegs) {
1953             case 0:  scratchNo = 0;  break;
1954             case 1:  scratchNo = 1;  break;
1955             case 2:  scratchNo = 2;  break;
1956             case 3:  scratchNo = 3;  break;
1957             case 4:  scratchNo = 11; break;
1958             default: vassert(0);
1959          }
1960          // r"scratchNo" = &target
1961          p = imm32_to_iregNo( (UInt*)p,
1962                               scratchNo, (UInt)i->ARMin.Call.target );
1963          // blx{cond} r"scratchNo"
1964          instr = XXX___XX(i->ARMin.Call.cond, X0001, X0010, /*___*/
1965                           X0011, scratchNo);
1966          instr |= 0xFFF << 8; // stick in the SBOnes
1967          *p++ = instr;
1968          goto done;
1969       }
1970       case ARMin_Mul: {
1971          /* E0000392   mul     r0, r2, r3
1972             E0810392   umull   r0(LO), r1(HI), r2, r3
1973             E0C10392   smull   r0(LO), r1(HI), r2, r3
1974          */
1975          switch (i->ARMin.Mul.op) {
1976             case ARMmul_PLAIN: *p++ = 0xE0000392; goto done;
1977             case ARMmul_ZX:    *p++ = 0xE0810392; goto done;
1978             case ARMmul_SX:    *p++ = 0xE0C10392; goto done;
1979             default: vassert(0);
1980          }
1981          goto bad;
1982       }
1983       case ARMin_LdrEX: {
1984          /* E1910F9F   ldrex    r0, [r1]
1985             E1F10F9F   ldrexh   r0, [r1]
1986             E1D10F9F   ldrexb   r0, [r1]
1987          */
1988          switch (i->ARMin.LdrEX.szB) {
1989             case 4: *p++ = 0xE1910F9F; goto done;
1990             //case 2: *p++ = 0xE1F10F9F; goto done;
1991             case 1: *p++ = 0xE1D10F9F; goto done;
1992             default: break;
1993          }
1994          goto bad;
1995       }
1996       case ARMin_StrEX: {
1997          /* E1820F91   strex   r0, r1, [r2]
1998             E1E20F91   strexh  r0, r1, [r2]
1999             E1C20F91   strexb  r0, r1, [r2]
2000          */
2001          switch (i->ARMin.StrEX.szB) {
2002             case 4: *p++ = 0xE1820F91; goto done;
2003             //case 2: *p++ = 0xE1E20F91; goto done;
2004             case 1: *p++ = 0xE1C20F91; goto done;
2005             default: break;
2006          }
2007          goto bad;
2008       }
2009       case ARMin_VLdStD: {
2010          UInt dD     = dregNo(i->ARMin.VLdStD.dD);
2011          UInt rN     = iregNo(i->ARMin.VLdStD.amode->reg);
2012          Int  simm11 = i->ARMin.VLdStD.amode->simm11;
2013          UInt off8   = simm11 >= 0 ? simm11 : ((UInt)(-simm11));
2014          UInt bU     = simm11 >= 0 ? 1 : 0;
2015          UInt bL     = i->ARMin.VLdStD.isLoad ? 1 : 0;
2016          UInt insn;
2017          vassert(0 == (off8 & 3));
2018          off8 >>= 2;
2019          vassert(0 == (off8 & 0xFFFFFF00));
2020          insn = XXXXXX__(0xE,X1101,BITS4(bU,0,0,bL),rN,dD,X1011);
2021          insn |= off8;
2022          *p++ = insn;
2023          goto done;
2024       }
2025       case ARMin_VLdStS: {
2026          UInt fD     = fregNo(i->ARMin.VLdStS.fD);
2027          UInt rN     = iregNo(i->ARMin.VLdStS.amode->reg);
2028          Int  simm11 = i->ARMin.VLdStS.amode->simm11;
2029          UInt off8   = simm11 >= 0 ? simm11 : ((UInt)(-simm11));
2030          UInt bU     = simm11 >= 0 ? 1 : 0;
2031          UInt bL     = i->ARMin.VLdStS.isLoad ? 1 : 0;
2032          UInt bD     = fD & 1;
2033          UInt insn;
2034          vassert(0 == (off8 & 3));
2035          off8 >>= 2;
2036          vassert(0 == (off8 & 0xFFFFFF00));
2037          insn = XXXXXX__(0xE,X1101,BITS4(bU,bD,0,bL),rN, (fD >> 1), X1010);
2038          insn |= off8;
2039          *p++ = insn;
2040          goto done;
2041       }
2042       case ARMin_VAluD: {
2043          UInt dN = dregNo(i->ARMin.VAluD.argL);
2044          UInt dD = dregNo(i->ARMin.VAluD.dst);
2045          UInt dM = dregNo(i->ARMin.VAluD.argR);
2046          UInt pqrs = X1111; /* undefined */
2047          switch (i->ARMin.VAluD.op) {
2048             case ARMvfp_ADD: pqrs = X0110; break;
2049             case ARMvfp_SUB: pqrs = X0111; break;
2050             case ARMvfp_MUL: pqrs = X0100; break;
2051             case ARMvfp_DIV: pqrs = X1000; break;
2052             default: goto bad;
2053          }
2054          vassert(pqrs != X1111);
2055          UInt bP  = (pqrs >> 3) & 1;
2056          UInt bQ  = (pqrs >> 2) & 1;
2057          UInt bR  = (pqrs >> 1) & 1;
2058          UInt bS  = (pqrs >> 0) & 1;
2059          UInt insn = XXXXXXXX(0xE, X1110, BITS4(bP,0,bQ,bR), dN, dD,
2060                               X1011, BITS4(0,bS,0,0), dM);
2061          *p++ = insn;
2062          goto done;
2063       }
2064       case ARMin_VAluS: {
2065          UInt dN = fregNo(i->ARMin.VAluS.argL);
2066          UInt dD = fregNo(i->ARMin.VAluS.dst);
2067          UInt dM = fregNo(i->ARMin.VAluS.argR);
2068          UInt bN = dN & 1;
2069          UInt bD = dD & 1;
2070          UInt bM = dM & 1;
2071          UInt pqrs = X1111; /* undefined */
2072          switch (i->ARMin.VAluS.op) {
2073             case ARMvfp_ADD: pqrs = X0110; break;
2074             case ARMvfp_SUB: pqrs = X0111; break;
2075             case ARMvfp_MUL: pqrs = X0100; break;
2076             case ARMvfp_DIV: pqrs = X1000; break;
2077             default: goto bad;
2078          }
2079          vassert(pqrs != X1111);
2080          UInt bP  = (pqrs >> 3) & 1;
2081          UInt bQ  = (pqrs >> 2) & 1;
2082          UInt bR  = (pqrs >> 1) & 1;
2083          UInt bS  = (pqrs >> 0) & 1;
2084          UInt insn = XXXXXXXX(0xE, X1110, BITS4(bP,bD,bQ,bR),
2085                               (dN >> 1), (dD >> 1),
2086                               X1010, BITS4(bN,bS,bM,0), (dM >> 1));
2087          *p++ = insn;
2088          goto done;
2089       }
2090       case ARMin_VUnaryD: {
2091          UInt dD   = dregNo(i->ARMin.VUnaryD.dst);
2092          UInt dM   = dregNo(i->ARMin.VUnaryD.src);
2093          UInt insn = 0;
2094          switch (i->ARMin.VUnaryD.op) {
2095             case ARMvfpu_COPY:
2096                insn = XXXXXXXX(0xE, X1110,X1011,X0000,dD,X1011,X0100,dM);
2097                break;
2098             case ARMvfpu_ABS:
2099                insn = XXXXXXXX(0xE, X1110,X1011,X0000,dD,X1011,X1100,dM);
2100                break;
2101             case ARMvfpu_NEG:
2102                insn = XXXXXXXX(0xE, X1110,X1011,X0001,dD,X1011,X0100,dM);
2103                break;
2104             case ARMvfpu_SQRT:
2105                insn = XXXXXXXX(0xE, X1110,X1011,X0001,dD,X1011,X1100,dM);
2106                break;
2107             default:
2108                goto bad;
2109          }
2110          *p++ = insn;
2111          goto done;
2112       }
2113       case ARMin_VUnaryS: {
2114          UInt fD   = fregNo(i->ARMin.VUnaryS.dst);
2115          UInt fM   = fregNo(i->ARMin.VUnaryS.src);
2116          UInt insn = 0;
2117          switch (i->ARMin.VUnaryS.op) {
2118             case ARMvfpu_COPY:
2119                insn = XXXXXXXX(0xE, X1110, BITS4(1,(fD & 1),1,1), X0000,
2120                                (fD >> 1), X1010, BITS4(0,1,(fM & 1),0),
2121                                (fM >> 1));
2122                break;
2123             case ARMvfpu_ABS:
2124                insn = XXXXXXXX(0xE, X1110, BITS4(1,(fD & 1),1,1), X0000,
2125                                (fD >> 1), X1010, BITS4(1,1,(fM & 1),0),
2126                                (fM >> 1));
2127                break;
2128             case ARMvfpu_NEG:
2129                insn = XXXXXXXX(0xE, X1110, BITS4(1,(fD & 1),1,1), X0001,
2130                                (fD >> 1), X1010, BITS4(0,1,(fM & 1),0),
2131                                (fM >> 1));
2132                break;
2133             case ARMvfpu_SQRT:
2134                insn = XXXXXXXX(0xE, X1110, BITS4(1,(fD & 1),1,1), X0001,
2135                                (fD >> 1), X1010, BITS4(1,1,(fM & 1),0),
2136                                (fM >> 1));
2137                break;
2138             default:
2139                goto bad;
2140          }
2141          *p++ = insn;
2142          goto done;
2143       }
2144       case ARMin_VCmpD: {
2145          UInt dD   = dregNo(i->ARMin.VCmpD.argL);
2146          UInt dM   = dregNo(i->ARMin.VCmpD.argR);
2147          UInt insn = XXXXXXXX(0xE, X1110, X1011, X0100, dD, X1011, X0100, dM);
2148          *p++ = insn;       /* FCMPD dD, dM */
2149          *p++ = 0xEEF1FA10; /* FMSTAT */
2150          goto done;
2151       }
2152       case ARMin_VCMovD: {
2153          UInt cc = (UInt)i->ARMin.VCMovD.cond;
2154          UInt dD = dregNo(i->ARMin.VCMovD.dst);
2155          UInt dM = dregNo(i->ARMin.VCMovD.src);
2156          vassert(cc < 16 && cc != ARMcc_AL);
2157          UInt insn = XXXXXXXX(cc, X1110,X1011,X0000,dD,X1011,X0100,dM);
2158          *p++ = insn;
2159          goto done;
2160       }
2161       case ARMin_VCMovS: {
2162          UInt cc = (UInt)i->ARMin.VCMovS.cond;
2163          UInt fD = fregNo(i->ARMin.VCMovS.dst);
2164          UInt fM = fregNo(i->ARMin.VCMovS.src);
2165          vassert(cc < 16 && cc != ARMcc_AL);
2166          UInt insn = XXXXXXXX(cc, X1110, BITS4(1,(fD & 1),1,1),
2167                               X0000,(fD >> 1),X1010,
2168                               BITS4(0,1,(fM & 1),0), (fM >> 1));
2169          *p++ = insn;
2170          goto done;
2171       }
2172       case ARMin_VCvtSD: {
2173          if (i->ARMin.VCvtSD.sToD) {
2174             UInt dD = dregNo(i->ARMin.VCvtSD.dst);
2175             UInt fM = fregNo(i->ARMin.VCvtSD.src);
2176             UInt insn = XXXXXXXX(0xE, X1110, X1011, X0111, dD, X1010,
2177                                  BITS4(1,1, (fM & 1), 0),
2178                                  (fM >> 1));
2179             *p++ = insn;
2180             goto done;
2181          } else {
2182             UInt fD = fregNo(i->ARMin.VCvtSD.dst);
2183             UInt dM = dregNo(i->ARMin.VCvtSD.src);
2184             UInt insn = XXXXXXXX(0xE, X1110, BITS4(1,(fD & 1),1,1),
2185                                  X0111, (fD >> 1),
2186                                  X1011, X1100, dM);
2187             *p++ = insn;
2188             goto done;
2189          }
2190          goto bad;
2191       }
2192       case ARMin_VXferD: {
2193          UInt dD  = dregNo(i->ARMin.VXferD.dD);
2194          UInt rHi = iregNo(i->ARMin.VXferD.rHi);
2195          UInt rLo = iregNo(i->ARMin.VXferD.rLo);
2196          /* vmov dD, rLo, rHi is
2197             E C 4 rHi rLo B (0,0,dD[4],1) dD[3:0]
2198             vmov rLo, rHi, dD is
2199             E C 5 rHi rLo B (0,0,dD[4],1) dD[3:0]
2200          */
2201          UInt insn
2202             = XXXXXXXX(0xE, 0xC, i->ARMin.VXferD.toD ? 4 : 5,
2203                        rHi, rLo, 0xB,
2204                        BITS4(0,0, ((dD >> 4) & 1), 1), (dD & 0xF));
2205          *p++ = insn;
2206          goto done;
2207       }
2208       case ARMin_VXferS: {
2209          UInt fD  = fregNo(i->ARMin.VXferS.fD);
2210          UInt rLo = iregNo(i->ARMin.VXferS.rLo);
2211          /* vmov fD, rLo is
2212             E E 0 fD[4:1] rLo A (fD[0],0,0,1) 0
2213             vmov rLo, fD is
2214             E E 1 fD[4:1] rLo A (fD[0],0,0,1) 0
2215          */
2216          UInt insn
2217             = XXXXXXXX(0xE, 0xE, i->ARMin.VXferS.toS ? 0 : 1,
2218                        (fD >> 1) & 0xF, rLo, 0xA, 
2219                        BITS4((fD & 1),0,0,1), 0);
2220          *p++ = insn;
2221          goto done;
2222       }
2223       case ARMin_VCvtID: {
2224          Bool iToD = i->ARMin.VCvtID.iToD;
2225          Bool syned = i->ARMin.VCvtID.syned;
2226          if (iToD && syned) {
2227             // FSITOD: I32S-in-freg to F64-in-dreg
2228             UInt regF = fregNo(i->ARMin.VCvtID.src);
2229             UInt regD = dregNo(i->ARMin.VCvtID.dst);
2230             UInt insn = XXXXXXXX(0xE, X1110, X1011, X1000, regD,
2231                                  X1011, BITS4(1,1,(regF & 1),0),
2232                                  (regF >> 1) & 0xF);
2233             *p++ = insn;
2234             goto done;
2235          }
2236          if (iToD && (!syned)) {
2237             // FUITOD: I32U-in-freg to F64-in-dreg
2238             UInt regF = fregNo(i->ARMin.VCvtID.src);
2239             UInt regD = dregNo(i->ARMin.VCvtID.dst);
2240             UInt insn = XXXXXXXX(0xE, X1110, X1011, X1000, regD,
2241                                  X1011, BITS4(0,1,(regF & 1),0),
2242                                  (regF >> 1) & 0xF);
2243             *p++ = insn;
2244             goto done;
2245          }
2246          if ((!iToD) && syned) {
2247             // FTOSID: F64-in-dreg to I32S-in-freg
2248             UInt regD = dregNo(i->ARMin.VCvtID.src);
2249             UInt regF = fregNo(i->ARMin.VCvtID.dst);
2250             UInt insn = XXXXXXXX(0xE, X1110, BITS4(1,(regF & 1),1,1),
2251                                  X1101, (regF >> 1) & 0xF,
2252                                  X1011, X0100, regD);
2253             *p++ = insn;
2254             goto done;
2255          }
2256          if ((!iToD) && (!syned)) {
2257             // FTOUID: F64-in-dreg to I32U-in-freg
2258             UInt regD = dregNo(i->ARMin.VCvtID.src);
2259             UInt regF = fregNo(i->ARMin.VCvtID.dst);
2260             UInt insn = XXXXXXXX(0xE, X1110, BITS4(1,(regF & 1),1,1),
2261                                  X1100, (regF >> 1) & 0xF,
2262                                  X1011, X0100, regD);
2263             *p++ = insn;
2264             goto done;
2265          }
2266          /*UNREACHED*/
2267          vassert(0);
2268       }
2269       case ARMin_FPSCR: {
2270          Bool toFPSCR = i->ARMin.FPSCR.toFPSCR;
2271          HReg iReg    = iregNo(i->ARMin.FPSCR.iReg);
2272          if (toFPSCR) {
2273             /* fmxr fpscr, iReg is EEE1 iReg A10 */
2274             *p++ = 0xEEE10A10 | ((iReg & 0xF) << 12);
2275             goto done;
2276          }
2277          goto bad; // FPSCR -> iReg case currently ATC
2278       }
2279       case ARMin_MFence: {
2280          *p++ = 0xEE070F9A; /* mcr 15,0,r0,c7,c10,4 (DSB) */
2281          *p++ = 0xEE070FBA; /* mcr 15,0,r0,c7,c10,5 (DMB) */
2282          *p++ = 0xEE070F95; /* mcr 15,0,r0,c7,c5,4  (ISB) */
2283          goto done;
2284       }
2285       default: 
2286          goto bad;
2287     }
2288
2289   bad:
2290    ppARMInstr(i);
2291    vpanic("emit_ARMInstr");
2292    /*NOTREACHED*/
2293     
2294   done:
2295    vassert(((UChar*)p) - &buf[0] <= 32);
2296    return ((UChar*)p) - &buf[0];
2297 }
2298
2299 #undef BITS4
2300 #undef X0000
2301 #undef X0001
2302 #undef X0010
2303 #undef X0011
2304 #undef X0100
2305 #undef X0101
2306 #undef X0110
2307 #undef X0111
2308 #undef X1000
2309 #undef X1001
2310 #undef X1010
2311 #undef X1011
2312 #undef X1100
2313 #undef X1101
2314 #undef X1110
2315 #undef X1111
2316 #undef XXXXX___
2317 #undef XXXXXX__
2318 #undef XXX___XX
2319 #undef XXXXX__X
2320 #undef XXXXXXXX
2321
2322 /*---------------------------------------------------------------*/
2323 /*--- end                                     host_arm_defs.c ---*/
2324 /*---------------------------------------------------------------*/