1 /*---------------------------------------------------------------*/
2 /*--- begin                                   host_arm_defs.h ---*/
3 /*---------------------------------------------------------------*/
4 
5 /*
6    This file is part of Valgrind, a dynamic binary instrumentation
7    framework.
8 
9    Copyright (C) 2004-2015 OpenWorks LLP
10       info@open-works.net
11 
12    This program is free software; you can redistribute it and/or
13    modify it under the terms of the GNU General Public License as
14    published by the Free Software Foundation; either version 2 of the
15    License, or (at your option) any later version.
16 
17    This program is distributed in the hope that it will be useful, but
18    WITHOUT ANY WARRANTY; without even the implied warranty of
19    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20    General Public License for more details.
21 
22    You should have received a copy of the GNU General Public License
23    along with this program; if not, write to the Free Software
24    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
25    02110-1301, USA.
26 
27    The GNU General Public License is contained in the file COPYING.
28 */
29 
30 #ifndef __VEX_HOST_ARM_DEFS_H
31 #define __VEX_HOST_ARM_DEFS_H
32 
33 #include "libvex_basictypes.h"
34 #include "libvex.h"                      // VexArch
35 #include "host_generic_regs.h"           // HReg
36 
37 extern UInt arm_hwcaps;
38 
39 
40 /* --------- Registers. --------- */
41 
42 #define ST_IN static inline
hregARM_R4(void)43 ST_IN HReg hregARM_R4  ( void ) { return mkHReg(False, HRcInt32,  4,  0);  }
hregARM_R5(void)44 ST_IN HReg hregARM_R5  ( void ) { return mkHReg(False, HRcInt32,  5,  1);  }
hregARM_R6(void)45 ST_IN HReg hregARM_R6  ( void ) { return mkHReg(False, HRcInt32,  6,  2);  }
hregARM_R7(void)46 ST_IN HReg hregARM_R7  ( void ) { return mkHReg(False, HRcInt32,  7,  3);  }
hregARM_R10(void)47 ST_IN HReg hregARM_R10 ( void ) { return mkHReg(False, HRcInt32,  10, 4);  }
hregARM_R11(void)48 ST_IN HReg hregARM_R11 ( void ) { return mkHReg(False, HRcInt32,  11, 5);  }
49 
hregARM_R0(void)50 ST_IN HReg hregARM_R0  ( void ) { return mkHReg(False, HRcInt32,  0,  6);  }
hregARM_R1(void)51 ST_IN HReg hregARM_R1  ( void ) { return mkHReg(False, HRcInt32,  1,  7);  }
hregARM_R2(void)52 ST_IN HReg hregARM_R2  ( void ) { return mkHReg(False, HRcInt32,  2,  8);  }
hregARM_R3(void)53 ST_IN HReg hregARM_R3  ( void ) { return mkHReg(False, HRcInt32,  3,  9);  }
hregARM_R9(void)54 ST_IN HReg hregARM_R9  ( void ) { return mkHReg(False, HRcInt32,  9,  10); }
55 
hregARM_D8(void)56 ST_IN HReg hregARM_D8  ( void ) { return mkHReg(False, HRcFlt64,  8,  11); }
hregARM_D9(void)57 ST_IN HReg hregARM_D9  ( void ) { return mkHReg(False, HRcFlt64,  9,  12); }
hregARM_D10(void)58 ST_IN HReg hregARM_D10 ( void ) { return mkHReg(False, HRcFlt64,  10, 13); }
hregARM_D11(void)59 ST_IN HReg hregARM_D11 ( void ) { return mkHReg(False, HRcFlt64,  11, 14); }
hregARM_D12(void)60 ST_IN HReg hregARM_D12 ( void ) { return mkHReg(False, HRcFlt64,  12, 15); }
61 
hregARM_S26(void)62 ST_IN HReg hregARM_S26 ( void ) { return mkHReg(False, HRcFlt32,  26, 16); }
hregARM_S27(void)63 ST_IN HReg hregARM_S27 ( void ) { return mkHReg(False, HRcFlt32,  27, 17); }
hregARM_S28(void)64 ST_IN HReg hregARM_S28 ( void ) { return mkHReg(False, HRcFlt32,  28, 18); }
hregARM_S29(void)65 ST_IN HReg hregARM_S29 ( void ) { return mkHReg(False, HRcFlt32,  29, 19); }
hregARM_S30(void)66 ST_IN HReg hregARM_S30 ( void ) { return mkHReg(False, HRcFlt32,  30, 20); }
67 
hregARM_Q8(void)68 ST_IN HReg hregARM_Q8  ( void ) { return mkHReg(False, HRcVec128, 8,  21); }
hregARM_Q9(void)69 ST_IN HReg hregARM_Q9  ( void ) { return mkHReg(False, HRcVec128, 9,  22); }
hregARM_Q10(void)70 ST_IN HReg hregARM_Q10 ( void ) { return mkHReg(False, HRcVec128, 10, 23); }
hregARM_Q11(void)71 ST_IN HReg hregARM_Q11 ( void ) { return mkHReg(False, HRcVec128, 11, 24); }
hregARM_Q12(void)72 ST_IN HReg hregARM_Q12 ( void ) { return mkHReg(False, HRcVec128, 12, 25); }
73 
hregARM_R8(void)74 ST_IN HReg hregARM_R8  ( void ) { return mkHReg(False, HRcInt32,  8,  26); }
hregARM_R12(void)75 ST_IN HReg hregARM_R12 ( void ) { return mkHReg(False, HRcInt32,  12, 27); }
hregARM_R13(void)76 ST_IN HReg hregARM_R13 ( void ) { return mkHReg(False, HRcInt32,  13, 28); }
hregARM_R14(void)77 ST_IN HReg hregARM_R14 ( void ) { return mkHReg(False, HRcInt32,  14, 29); }
hregARM_R15(void)78 ST_IN HReg hregARM_R15 ( void ) { return mkHReg(False, HRcInt32,  15, 30); }
hregARM_Q13(void)79 ST_IN HReg hregARM_Q13 ( void ) { return mkHReg(False, HRcVec128, 13, 31); }
hregARM_Q14(void)80 ST_IN HReg hregARM_Q14 ( void ) { return mkHReg(False, HRcVec128, 14, 32); }
hregARM_Q15(void)81 ST_IN HReg hregARM_Q15 ( void ) { return mkHReg(False, HRcVec128, 15, 33); }
82 #undef ST_IN
83 
84 extern void ppHRegARM ( HReg );
85 
86 /* Number of registers used arg passing in function calls */
87 #define ARM_N_ARGREGS 4   /* r0, r1, r2, r3 */
88 
89 
90 /* --------- Condition codes. --------- */
91 
92 typedef
93    enum {
94       ARMcc_EQ  = 0,  /* equal                          : Z=1 */
95       ARMcc_NE  = 1,  /* not equal                      : Z=0 */
96 
97       ARMcc_HS  = 2,  /* >=u (higher or same)           : C=1 */
98       ARMcc_LO  = 3,  /* <u  (lower)                    : C=0 */
99 
100       ARMcc_MI  = 4,  /* minus (negative)               : N=1 */
101       ARMcc_PL  = 5,  /* plus (zero or +ve)             : N=0 */
102 
103       ARMcc_VS  = 6,  /* overflow                       : V=1 */
104       ARMcc_VC  = 7,  /* no overflow                    : V=0 */
105 
106       ARMcc_HI  = 8,  /* >u   (higher)                  : C=1 && Z=0 */
107       ARMcc_LS  = 9,  /* <=u  (lower or same)           : C=0 || Z=1 */
108 
109       ARMcc_GE  = 10, /* >=s (signed greater or equal)  : N=V */
110       ARMcc_LT  = 11, /* <s  (signed less than)         : N!=V */
111 
112       ARMcc_GT  = 12, /* >s  (signed greater)           : Z=0 && N=V */
113       ARMcc_LE  = 13, /* <=s (signed less or equal)     : Z=1 || N!=V */
114 
115       ARMcc_AL  = 14, /* always (unconditional) */
116       ARMcc_NV  = 15  /* never (basically undefined meaning), deprecated */
117    }
118    ARMCondCode;
119 
120 extern const HChar* showARMCondCode ( ARMCondCode );
121 
122 
123 
124 /* --------- Memory address expressions (amodes). --------- */
125 
126 /* --- Addressing Mode 1 --- */
127 typedef
128    enum {
129       ARMam1_RI=1,   /* reg +/- imm12 */
130       ARMam1_RRS     /* reg1 + (reg2 << 0, 1 2 or 3) */
131    }
132    ARMAMode1Tag;
133 
134 typedef
135    struct {
136       ARMAMode1Tag tag;
137       union {
138          struct {
139             HReg reg;
140             Int  simm13; /* -4095 .. +4095 */
141          } RI;
142          struct {
143             HReg base;
144             HReg index;
145             UInt shift; /* 0, 1 2 or 3 */
146          } RRS;
147       } ARMam1;
148    }
149    ARMAMode1;
150 
151 extern ARMAMode1* ARMAMode1_RI  ( HReg reg, Int simm13 );
152 extern ARMAMode1* ARMAMode1_RRS ( HReg base, HReg index, UInt shift );
153 
154 extern void ppARMAMode1 ( ARMAMode1* );
155 
156 
157 /* --- Addressing Mode 2 --- */
158 typedef
159    enum {
160       ARMam2_RI=3,   /* reg +/- imm8 */
161       ARMam2_RR      /* reg1 + reg2 */
162    }
163    ARMAMode2Tag;
164 
165 typedef
166    struct {
167       ARMAMode2Tag tag;
168       union {
169          struct {
170             HReg reg;
171             Int  simm9; /* -255 .. 255 */
172          } RI;
173          struct {
174             HReg base;
175             HReg index;
176          } RR;
177       } ARMam2;
178    }
179    ARMAMode2;
180 
181 extern ARMAMode2* ARMAMode2_RI ( HReg reg, Int simm9 );
182 extern ARMAMode2* ARMAMode2_RR ( HReg base, HReg index );
183 
184 extern void ppARMAMode2 ( ARMAMode2* );
185 
186 
187 /* --- Addressing Mode suitable for VFP --- */
188 /* The simm11 is encoded as 8 bits + 1 sign bit,
189    so can only be 0 % 4. */
190 typedef
191    struct {
192       HReg reg;
193       Int  simm11; /* -1020, -1016 .. 1016, 1020 */
194    }
195    ARMAModeV;
196 
197 extern ARMAModeV* mkARMAModeV ( HReg reg, Int simm11 );
198 
199 extern void ppARMAModeV ( ARMAModeV* );
200 
201 /* --- Addressing Mode suitable for Neon --- */
202 typedef
203    enum {
204       ARMamN_R=5,
205       ARMamN_RR
206       /* ... */
207    }
208    ARMAModeNTag;
209 
210 typedef
211    struct {
212       ARMAModeNTag tag;
213       union {
214          struct {
215             HReg rN;
216             HReg rM;
217          } RR;
218          struct {
219             HReg rN;
220          } R;
221          /* ... */
222       } ARMamN;
223    }
224    ARMAModeN;
225 
226 extern ARMAModeN* mkARMAModeN_RR ( HReg, HReg );
227 extern ARMAModeN* mkARMAModeN_R ( HReg );
228 extern void ppARMAModeN ( ARMAModeN* );
229 
230 /* --------- Reg or imm-8x4 operands --------- */
231 /* a.k.a (a very restricted form of) Shifter Operand,
232    in the ARM parlance. */
233 
234 typedef
235    enum {
236       ARMri84_I84=7,   /* imm8 `ror` (2 * imm4) */
237       ARMri84_R        /* reg */
238    }
239    ARMRI84Tag;
240 
241 typedef
242    struct {
243       ARMRI84Tag tag;
244       union {
245          struct {
246             UShort imm8;
247             UShort imm4;
248          } I84;
249          struct {
250             HReg reg;
251          } R;
252       } ARMri84;
253    }
254    ARMRI84;
255 
256 extern ARMRI84* ARMRI84_I84 ( UShort imm8, UShort imm4 );
257 extern ARMRI84* ARMRI84_R   ( HReg );
258 
259 extern void ppARMRI84 ( ARMRI84* );
260 
261 
262 /* --------- Reg or imm5 operands --------- */
263 typedef
264    enum {
265       ARMri5_I5=9,   /* imm5, 1 .. 31 only (no zero!) */
266       ARMri5_R       /* reg */
267    }
268    ARMRI5Tag;
269 
270 typedef
271    struct {
272       ARMRI5Tag tag;
273       union {
274          struct {
275             UInt imm5;
276          } I5;
277          struct {
278             HReg reg;
279          } R;
280       } ARMri5;
281    }
282    ARMRI5;
283 
284 extern ARMRI5* ARMRI5_I5 ( UInt imm5 );
285 extern ARMRI5* ARMRI5_R  ( HReg );
286 
287 extern void ppARMRI5 ( ARMRI5* );
288 
289 /* -------- Neon Immediate operand -------- */
290 
291 /* imm8 = abcdefgh, B = NOT(b);
292 
293 type | value (64bit binary)
294 -----+-------------------------------------------------------------------------
295    0 | 00000000 00000000 00000000 abcdefgh 00000000 00000000 00000000 abcdefgh
296    1 | 00000000 00000000 abcdefgh 00000000 00000000 00000000 abcdefgh 00000000
297    2 | 00000000 abcdefgh 00000000 00000000 00000000 abcdefgh 00000000 00000000
298    3 | abcdefgh 00000000 00000000 00000000 abcdefgh 00000000 00000000 00000000
299    4 | 00000000 abcdefgh 00000000 abcdefgh 00000000 abcdefgh 00000000 abcdefgh
300    5 | abcdefgh 00000000 abcdefgh 00000000 abcdefgh 00000000 abcdefgh 00000000
301    6 | abcdefgh abcdefgh abcdefgh abcdefgh abcdefgh abcdefgh abcdefgh abcdefgh
302    7 | 00000000 00000000 abcdefgh 11111111 00000000 00000000 abcdefgh 11111111
303    8 | 00000000 abcdefgh 11111111 11111111 00000000 abcdefgh 11111111 11111111
304    9 | aaaaaaaa bbbbbbbb cccccccc dddddddd eeeeeeee ffffffff gggggggg hhhhhhhh
305   10 | aBbbbbbc defgh000 00000000 00000000 aBbbbbbc defgh000 00000000 00000000
306 -----+-------------------------------------------------------------------------
307 
308 Type 10 is:
309    (-1)^S * 2^exp * mantissa
310 where S = a, exp = UInt(B:c:d) - 3, mantissa = (16 + UInt(e:f:g:h)) / 16
311 */
312 
313 typedef
314    struct {
315       UInt type;
316       UInt imm8;
317    }
318    ARMNImm;
319 
320 extern ARMNImm* ARMNImm_TI ( UInt type, UInt imm8 );
321 extern ULong ARMNImm_to_Imm64 ( ARMNImm* );
322 extern ARMNImm* Imm64_to_ARMNImm ( ULong );
323 
324 extern void ppARMNImm ( ARMNImm* );
325 
326 /* ------ Neon Register or Scalar Operand ------ */
327 
328 typedef
329    enum {
330       ARMNRS_Reg=11,
331       ARMNRS_Scalar
332    }
333    ARMNRS_tag;
334 
335 typedef
336    struct {
337       ARMNRS_tag tag;
338       HReg reg;
339       UInt index;
340    }
341    ARMNRS;
342 
343 extern ARMNRS* mkARMNRS(ARMNRS_tag, HReg reg, UInt index);
344 extern void ppARMNRS ( ARMNRS* );
345 
346 /* --------- Instructions. --------- */
347 
348 /* --------- */
349 typedef
350    enum {
351       ARMalu_ADD=20,   /* plain 32-bit add */
352       ARMalu_ADDS,     /* 32-bit add, and set the flags */
353       ARMalu_ADC,      /* 32-bit add with carry */
354       ARMalu_SUB,      /* plain 32-bit subtract */
355       ARMalu_SUBS,     /* 32-bit subtract, and set the flags */
356       ARMalu_SBC,      /* 32-bit subtract with carry */
357       ARMalu_AND,
358       ARMalu_BIC,
359       ARMalu_OR,
360       ARMalu_XOR
361    }
362    ARMAluOp;
363 
364 extern const HChar* showARMAluOp ( ARMAluOp op );
365 
366 
367 typedef
368    enum {
369       ARMsh_SHL=40,
370       ARMsh_SHR,
371       ARMsh_SAR
372    }
373    ARMShiftOp;
374 
375 extern const HChar* showARMShiftOp ( ARMShiftOp op );
376 
377 
378 typedef
379    enum {
380       ARMun_NEG=50,
381       ARMun_NOT,
382       ARMun_CLZ
383    }
384    ARMUnaryOp;
385 
386 extern const HChar* showARMUnaryOp ( ARMUnaryOp op );
387 
388 
389 typedef
390    enum {
391       ARMmul_PLAIN=60,
392       ARMmul_ZX,
393       ARMmul_SX
394    }
395    ARMMulOp;
396 
397 extern const HChar* showARMMulOp ( ARMMulOp op );
398 
399 
400 typedef
401    enum {
402       ARMvfp_ADD=70,
403       ARMvfp_SUB,
404       ARMvfp_MUL,
405       ARMvfp_DIV
406    }
407    ARMVfpOp;
408 
409 extern const HChar* showARMVfpOp ( ARMVfpOp op );
410 
411 
412 typedef
413    enum {
414       ARMvfpu_COPY=80,
415       ARMvfpu_NEG,
416       ARMvfpu_ABS,
417       ARMvfpu_SQRT
418    }
419    ARMVfpUnaryOp;
420 
421 extern const HChar* showARMVfpUnaryOp ( ARMVfpUnaryOp op );
422 
423 typedef
424    enum {
425       ARMneon_VAND=90,
426       ARMneon_VORR,
427       ARMneon_VXOR,
428       ARMneon_VADD,
429       ARMneon_VADDFP,
430       ARMneon_VRHADDS,
431       ARMneon_VRHADDU,
432       ARMneon_VPADDFP,
433       ARMneon_VABDFP,
434       ARMneon_VSUB,
435       ARMneon_VSUBFP,
436       ARMneon_VMAXU,
437       ARMneon_VMAXS,
438       ARMneon_VMAXF,
439       ARMneon_VMINU,
440       ARMneon_VMINS,
441       ARMneon_VMINF,
442       ARMneon_VQADDU,
443       ARMneon_VQADDS,
444       ARMneon_VQSUBU,
445       ARMneon_VQSUBS,
446       ARMneon_VCGTU,
447       ARMneon_VCGTS,
448       ARMneon_VCGEU,
449       ARMneon_VCGES,
450       ARMneon_VCGTF,
451       ARMneon_VCGEF,
452       ARMneon_VCEQ,
453       ARMneon_VCEQF,
454       ARMneon_VEXT,
455       ARMneon_VMUL,
456       ARMneon_VMULFP,
457       ARMneon_VMULLU,
458       ARMneon_VMULLS,
459       ARMneon_VMULP,
460       ARMneon_VMULLP,
461       ARMneon_VQDMULH,
462       ARMneon_VQRDMULH,
463       ARMneon_VPADD,
464       ARMneon_VPMINU,
465       ARMneon_VPMINS,
466       ARMneon_VPMINF,
467       ARMneon_VPMAXU,
468       ARMneon_VPMAXS,
469       ARMneon_VPMAXF,
470       ARMneon_VTBL,
471       ARMneon_VQDMULL,
472       ARMneon_VRECPS,
473       ARMneon_VRSQRTS,
474       ARMneon_INVALID
475       /* ... */
476    }
477    ARMNeonBinOp;
478 
479 typedef
480    enum {
481       ARMneon_VSHL=150,
482       ARMneon_VSAL, /* Yah, not SAR but SAL */
483       ARMneon_VQSHL,
484       ARMneon_VQSAL
485    }
486    ARMNeonShiftOp;
487 
488 typedef
489    enum {
490       ARMneon_COPY=160,
491       ARMneon_COPYLU,
492       ARMneon_COPYLS,
493       ARMneon_COPYN,
494       ARMneon_COPYQNSS,
495       ARMneon_COPYQNUS,
496       ARMneon_COPYQNUU,
497       ARMneon_NOT,
498       ARMneon_EQZ,
499       ARMneon_DUP,
500       ARMneon_PADDLS,
501       ARMneon_PADDLU,
502       ARMneon_CNT,
503       ARMneon_CLZ,
504       ARMneon_CLS,
505       ARMneon_VCVTxFPxINT,
506       ARMneon_VQSHLNSS,
507       ARMneon_VQSHLNUU,
508       ARMneon_VQSHLNUS,
509       ARMneon_VCVTFtoU,
510       ARMneon_VCVTFtoS,
511       ARMneon_VCVTUtoF,
512       ARMneon_VCVTStoF,
513       ARMneon_VCVTFtoFixedU,
514       ARMneon_VCVTFtoFixedS,
515       ARMneon_VCVTFixedUtoF,
516       ARMneon_VCVTFixedStoF,
517       ARMneon_VCVTF16toF32,
518       ARMneon_VCVTF32toF16,
519       ARMneon_REV16,
520       ARMneon_REV32,
521       ARMneon_REV64,
522       ARMneon_ABS,
523       ARMneon_VNEGF,
524       ARMneon_VRECIP,
525       ARMneon_VRECIPF,
526       ARMneon_VABSFP,
527       ARMneon_VRSQRTEFP,
528       ARMneon_VRSQRTE
529       /* ... */
530    }
531    ARMNeonUnOp;
532 
533 typedef
534    enum {
535       ARMneon_SETELEM=200,
536       ARMneon_GETELEMU,
537       ARMneon_GETELEMS,
538       ARMneon_VDUP,
539    }
540    ARMNeonUnOpS;
541 
542 typedef
543    enum {
544       ARMneon_TRN=210,
545       ARMneon_ZIP,
546       ARMneon_UZP
547       /* ... */
548    }
549    ARMNeonDualOp;
550 
551 extern const HChar* showARMNeonBinOp ( ARMNeonBinOp op );
552 extern const HChar* showARMNeonUnOp ( ARMNeonUnOp op );
553 extern const HChar* showARMNeonUnOpS ( ARMNeonUnOpS op );
554 extern const HChar* showARMNeonShiftOp ( ARMNeonShiftOp op );
555 extern const HChar* showARMNeonDualOp ( ARMNeonDualOp op );
556 extern const HChar* showARMNeonBinOpDataType ( ARMNeonBinOp op );
557 extern const HChar* showARMNeonUnOpDataType ( ARMNeonUnOp op );
558 extern const HChar* showARMNeonUnOpSDataType ( ARMNeonUnOpS op );
559 extern const HChar* showARMNeonShiftOpDataType ( ARMNeonShiftOp op );
560 extern const HChar* showARMNeonDualOpDataType ( ARMNeonDualOp op );
561 
562 typedef
563    enum {
564       /* baseline */
565       ARMin_Alu=220,
566       ARMin_Shift,
567       ARMin_Unary,
568       ARMin_CmpOrTst,
569       ARMin_Mov,
570       ARMin_Imm32,
571       ARMin_LdSt32,
572       ARMin_LdSt16,
573       ARMin_LdSt8U,
574       ARMin_Ld8S,
575       ARMin_XDirect,     /* direct transfer to GA */
576       ARMin_XIndir,      /* indirect transfer to GA */
577       ARMin_XAssisted,   /* assisted transfer to GA */
578       ARMin_CMov,
579       ARMin_Call,
580       ARMin_Mul,
581       ARMin_LdrEX,
582       ARMin_StrEX,
583       /* vfp */
584       ARMin_VLdStD,
585       ARMin_VLdStS,
586       ARMin_VAluD,
587       ARMin_VAluS,
588       ARMin_VUnaryD,
589       ARMin_VUnaryS,
590       ARMin_VCmpD,
591       ARMin_VCMovD,
592       ARMin_VCMovS,
593       ARMin_VCvtSD,
594       ARMin_VXferD,
595       ARMin_VXferS,
596       ARMin_VCvtID,
597       ARMin_FPSCR,
598       ARMin_MFence,
599       ARMin_CLREX,
600       /* Neon */
601       ARMin_NLdStQ,
602       ARMin_NLdStD,
603       ARMin_NUnary,
604       ARMin_NUnaryS,
605       ARMin_NDual,
606       ARMin_NBinary,
607       ARMin_NBinaryS,
608       ARMin_NShift,
609       ARMin_NShl64, // special case 64-bit shift of Dreg by immediate
610       ARMin_NeonImm,
611       ARMin_NCMovQ,
612       /* This is not a NEON instruction. Actually there is no corresponding
613          instruction in ARM instruction set at all. We need this one to
614          generate spill/reload of 128-bit registers since current register
615          allocator demands them to consist of no more than two instructions.
616          We will split this instruction into 2 or 3 ARM instructions on the
617          emiting phase.
618          NOTE: source and destination registers should be different! */
619       ARMin_Add32,
620       ARMin_EvCheck,     /* Event check */
621       ARMin_ProfInc      /* 64-bit profile counter increment */
622    }
623    ARMInstrTag;
624 
625 /* Destinations are on the LEFT (first operand) */
626 
627 typedef
628    struct {
629       ARMInstrTag tag;
630       union {
631          /* ADD/SUB/AND/OR/XOR, vanilla ALU op */
632          struct {
633             ARMAluOp op;
634             HReg     dst;
635             HReg     argL;
636             ARMRI84* argR;
637          } Alu;
638          /* SHL/SHR/SAR, 2nd arg is reg or imm */
639          struct {
640             ARMShiftOp op;
641             HReg       dst;
642             HReg       argL;
643             ARMRI5*    argR;
644          } Shift;
645          /* NOT/NEG/CLZ */
646          struct {
647             ARMUnaryOp op;
648             HReg       dst;
649             HReg       src;
650          } Unary;
651          /* CMP/TST; subtract/and, discard result, set NZCV */
652          struct {
653             Bool     isCmp;
654             HReg     argL;
655             ARMRI84* argR;
656          } CmpOrTst;
657          /* MOV dst, src -- reg-reg (or reg-imm8x4) move */
658          struct {
659             HReg     dst;
660             ARMRI84* src;
661          } Mov;
662          /* Pseudo-insn; make a 32-bit immediate */
663          struct {
664             HReg dst;
665             UInt imm32;
666          } Imm32;
667          /* 32-bit load or store, may be conditional */
668          struct {
669             ARMCondCode cc; /* ARMcc_NV is not allowed */
670             Bool        isLoad;
671             HReg        rD;
672             ARMAMode1*  amode;
673          } LdSt32;
674          /* 16-bit load or store, may be conditional */
675          struct {
676             ARMCondCode cc; /* ARMcc_NV is not allowed */
677             Bool        isLoad;
678             Bool        signedLoad;
679             HReg        rD;
680             ARMAMode2*  amode;
681          } LdSt16;
682          /* 8-bit (unsigned) load or store, may be conditional */
683          struct {
684             ARMCondCode cc; /* ARMcc_NV is not allowed */
685             Bool        isLoad;
686             HReg        rD;
687             ARMAMode1*  amode;
688          } LdSt8U;
689          /* 8-bit signed load, may be conditional */
690          struct {
691             ARMCondCode cc; /* ARMcc_NV is not allowed */
692             HReg        rD;
693             ARMAMode2*  amode;
694          } Ld8S;
695          /* Update the guest R15T value, then exit requesting to chain
696             to it.  May be conditional.  Urr, use of Addr32 implicitly
697             assumes that wordsize(guest) == wordsize(host). */
698          struct {
699             Addr32      dstGA;    /* next guest address */
700             ARMAMode1*  amR15T;   /* amode in guest state for R15T */
701             ARMCondCode cond;     /* can be ARMcc_AL */
702             Bool        toFastEP; /* chain to the slow or fast point? */
703          } XDirect;
704          /* Boring transfer to a guest address not known at JIT time.
705             Not chainable.  May be conditional. */
706          struct {
707             HReg        dstGA;
708             ARMAMode1*  amR15T;
709             ARMCondCode cond; /* can be ARMcc_AL */
710          } XIndir;
711          /* Assisted transfer to a guest address, most general case.
712             Not chainable.  May be conditional. */
713          struct {
714             HReg        dstGA;
715             ARMAMode1*  amR15T;
716             ARMCondCode cond; /* can be ARMcc_AL */
717             IRJumpKind  jk;
718          } XAssisted;
719          /* Mov src to dst on the given condition, which may not
720             be ARMcc_AL. */
721          struct {
722             ARMCondCode cond;
723             HReg        dst;
724             ARMRI84*    src;
725          } CMov;
726          /* Pseudo-insn.  Call target (an absolute address), on given
727             condition (which could be ARMcc_AL). */
728          struct {
729             ARMCondCode cond;
730             Addr32      target;
731             Int         nArgRegs; /* # regs carrying args: 0 .. 4 */
732             RetLoc      rloc;     /* where the return value will be */
733          } Call;
734          /* (PLAIN) 32 *  32 -> 32:  r0    = r2 * r3
735             (ZX)    32 *u 32 -> 64:  r1:r0 = r2 *u r3
736             (SX)    32 *s 32 -> 64:  r1:r0 = r2 *s r3
737             Why hardwired registers?  Because the ARM ARM specifies
738             (eg for straight MUL) the result (Rd) and the left arg (Rm)
739             may not be the same register.  That's not a constraint we
740             can enforce in the register allocator (without mucho extra
741             complexity).  Hence hardwire it.  At least using caller-saves
742             registers, which are less likely to be in use. */
743          struct {
744             ARMMulOp op;
745          } Mul;
746          /* LDREX{,H,B} r2, [r4]  and
747             LDREXD r2, r3, [r4]   (on LE hosts, transferred value is r3:r2)
748             Again, hardwired registers since this is not performance
749             critical, and there are possibly constraints on the
750             registers that we can't express in the register allocator.*/
751          struct {
752             Int  szB; /* 1, 2, 4 or 8 */
753          } LdrEX;
754          /* STREX{,H,B} r0, r2, [r4]  and
755             STREXD r0, r2, r3, [r4]   (on LE hosts, transferred value is r3:r2)
756             r0 = SC( [r4] = r2 )      (8, 16, 32 bit transfers)
757             r0 = SC( [r4] = r3:r2)    (64 bit transfers)
758             Ditto comment re fixed registers. */
759          struct {
760             Int  szB; /* 1, 2, 4 or 8 */
761          } StrEX;
762          /* VFP INSTRUCTIONS */
763          /* 64-bit Fp load/store */
764          struct {
765             Bool       isLoad;
766             HReg       dD;
767             ARMAModeV* amode;
768          } VLdStD;
769          /* 32-bit Fp load/store */
770          struct {
771             Bool       isLoad;
772             HReg       fD;
773             ARMAModeV* amode;
774          } VLdStS;
775          /* 64-bit FP binary arithmetic */
776          struct {
777             ARMVfpOp op;
778             HReg     dst;
779             HReg     argL;
780             HReg     argR;
781          } VAluD;
782          /* 32-bit FP binary arithmetic */
783          struct {
784             ARMVfpOp op;
785             HReg     dst;
786             HReg     argL;
787             HReg     argR;
788          } VAluS;
789          /* 64-bit FP unary, also reg-reg move */
790          struct {
791             ARMVfpUnaryOp op;
792             HReg          dst;
793             HReg          src;
794          } VUnaryD;
795          /* 32-bit FP unary, also reg-reg move */
796          struct {
797             ARMVfpUnaryOp op;
798             HReg          dst;
799             HReg          src;
800          } VUnaryS;
801          /* 64-bit FP compare and move results to CPSR (FCMPD;FMSTAT) */
802          struct {
803             HReg argL;
804             HReg argR;
805          } VCmpD;
806          /* 64-bit FP mov src to dst on the given condition, which may
807             not be ARMcc_AL. */
808          struct {
809             ARMCondCode cond;
810             HReg        dst;
811             HReg        src;
812          } VCMovD;
813          /* 32-bit FP mov src to dst on the given condition, which may
814             not be ARMcc_AL. */
815          struct {
816             ARMCondCode cond;
817             HReg        dst;
818             HReg        src;
819          } VCMovS;
820          /* Convert between 32-bit and 64-bit FP values (both ways).
821             (FCVTSD, FCVTDS) */
822          struct {
823             Bool sToD; /* True: F32->F64.  False: F64->F32 */
824             HReg dst;
825             HReg src;
826          } VCvtSD;
827          /* Transfer a VFP D reg to/from two integer registers (VMOV) */
828          struct {
829             Bool toD;
830             HReg dD;
831             HReg rHi;
832             HReg rLo;
833          } VXferD;
834          /* Transfer a VFP S reg to/from an integer register (VMOV) */
835          struct {
836             Bool toS;
837             HReg fD;
838             HReg rLo;
839          } VXferS;
840          /* Convert between 32-bit ints and 64-bit FP values (both ways
841             and both signednesses). (FSITOD, FUITOD, FTOSID, FTOUID) */
842          struct {
843             Bool iToD; /* True: I32->F64.  False: F64->I32 */
844             Bool syned; /* True: I32 is signed.  False: I32 is unsigned */
845             HReg dst;
846             HReg src;
847          } VCvtID;
848          /* Move a 32-bit value to/from the FPSCR (FMXR, FMRX) */
849          struct {
850             Bool toFPSCR;
851             HReg iReg;
852          } FPSCR;
853          /* Mem fence.  An insn which fences all loads and stores as
854             much as possible before continuing.  On ARM we emit the
855             sequence
856                mcr 15,0,r0,c7,c10,4 (DSB)
857                mcr 15,0,r0,c7,c10,5 (DMB)
858                mcr 15,0,r0,c7,c5,4 (ISB)
859             which is probably total overkill, but better safe than
860             sorry.
861          */
862          struct {
863          } MFence;
864          /* A CLREX instruction. */
865          struct {
866          } CLREX;
867          /* Neon data processing instruction: 3 registers of the same
868             length */
869          struct {
870             ARMNeonBinOp op;
871             HReg dst;
872             HReg argL;
873             HReg argR;
874             UInt size;
875             Bool Q;
876          } NBinary;
877          struct {
878             ARMNeonBinOp op;
879             ARMNRS* dst;
880             ARMNRS* argL;
881             ARMNRS* argR;
882             UInt size;
883             Bool Q;
884          } NBinaryS;
885          struct {
886             ARMNeonShiftOp op;
887             HReg dst;
888             HReg argL;
889             HReg argR;
890             UInt size;
891             Bool Q;
892          } NShift;
893          struct {
894             HReg dst;
895             HReg src;
896             UInt amt; /* 1..63 only */
897          } NShl64;
898          struct {
899             Bool isLoad;
900             HReg dQ;
901             ARMAModeN *amode;
902          } NLdStQ;
903          struct {
904             Bool isLoad;
905             HReg dD;
906             ARMAModeN *amode;
907          } NLdStD;
908          struct {
909             ARMNeonUnOpS op;
910             ARMNRS*  dst;
911             ARMNRS*  src;
912             UInt size;
913             Bool Q;
914          } NUnaryS;
915          struct {
916             ARMNeonUnOp op;
917             HReg  dst;
918             HReg  src;
919             UInt size;
920             Bool Q;
921          } NUnary;
922          /* Takes two arguments and modifies them both. */
923          struct {
924             ARMNeonDualOp op;
925             HReg  arg1;
926             HReg  arg2;
927             UInt size;
928             Bool Q;
929          } NDual;
930          struct {
931             HReg dst;
932             ARMNImm* imm;
933          } NeonImm;
934          /* 128-bit Neon move src to dst on the given condition, which
935             may not be ARMcc_AL. */
936          struct {
937             ARMCondCode cond;
938             HReg        dst;
939             HReg        src;
940          } NCMovQ;
941          struct {
942             /* Note: rD != rN */
943             HReg rD;
944             HReg rN;
945             UInt imm32;
946          } Add32;
947          struct {
948             ARMAMode1* amCounter;
949             ARMAMode1* amFailAddr;
950          } EvCheck;
951          struct {
952             /* No fields.  The address of the counter to inc is
953                installed later, post-translation, by patching it in,
954                as it is not known at translation time. */
955          } ProfInc;
956       } ARMin;
957    }
958    ARMInstr;
959 
960 
961 extern ARMInstr* ARMInstr_Alu      ( ARMAluOp, HReg, HReg, ARMRI84* );
962 extern ARMInstr* ARMInstr_Shift    ( ARMShiftOp, HReg, HReg, ARMRI5* );
963 extern ARMInstr* ARMInstr_Unary    ( ARMUnaryOp, HReg, HReg );
964 extern ARMInstr* ARMInstr_CmpOrTst ( Bool isCmp, HReg, ARMRI84* );
965 extern ARMInstr* ARMInstr_Mov      ( HReg, ARMRI84* );
966 extern ARMInstr* ARMInstr_Imm32    ( HReg, UInt );
967 extern ARMInstr* ARMInstr_LdSt32   ( ARMCondCode,
968                                      Bool isLoad, HReg, ARMAMode1* );
969 extern ARMInstr* ARMInstr_LdSt16   ( ARMCondCode,
970                                      Bool isLoad, Bool signedLoad,
971                                      HReg, ARMAMode2* );
972 extern ARMInstr* ARMInstr_LdSt8U   ( ARMCondCode,
973                                      Bool isLoad, HReg, ARMAMode1* );
974 extern ARMInstr* ARMInstr_Ld8S     ( ARMCondCode, HReg, ARMAMode2* );
975 extern ARMInstr* ARMInstr_XDirect  ( Addr32 dstGA, ARMAMode1* amR15T,
976                                      ARMCondCode cond, Bool toFastEP );
977 extern ARMInstr* ARMInstr_XIndir   ( HReg dstGA, ARMAMode1* amR15T,
978                                      ARMCondCode cond );
979 extern ARMInstr* ARMInstr_XAssisted ( HReg dstGA, ARMAMode1* amR15T,
980                                       ARMCondCode cond, IRJumpKind jk );
981 extern ARMInstr* ARMInstr_CMov     ( ARMCondCode, HReg dst, ARMRI84* src );
982 extern ARMInstr* ARMInstr_Call     ( ARMCondCode, Addr32, Int nArgRegs,
983                                      RetLoc rloc );
984 extern ARMInstr* ARMInstr_Mul      ( ARMMulOp op );
985 extern ARMInstr* ARMInstr_LdrEX    ( Int szB );
986 extern ARMInstr* ARMInstr_StrEX    ( Int szB );
987 extern ARMInstr* ARMInstr_VLdStD   ( Bool isLoad, HReg, ARMAModeV* );
988 extern ARMInstr* ARMInstr_VLdStS   ( Bool isLoad, HReg, ARMAModeV* );
989 extern ARMInstr* ARMInstr_VAluD    ( ARMVfpOp op, HReg, HReg, HReg );
990 extern ARMInstr* ARMInstr_VAluS    ( ARMVfpOp op, HReg, HReg, HReg );
991 extern ARMInstr* ARMInstr_VUnaryD  ( ARMVfpUnaryOp, HReg dst, HReg src );
992 extern ARMInstr* ARMInstr_VUnaryS  ( ARMVfpUnaryOp, HReg dst, HReg src );
993 extern ARMInstr* ARMInstr_VCmpD    ( HReg argL, HReg argR );
994 extern ARMInstr* ARMInstr_VCMovD   ( ARMCondCode, HReg dst, HReg src );
995 extern ARMInstr* ARMInstr_VCMovS   ( ARMCondCode, HReg dst, HReg src );
996 extern ARMInstr* ARMInstr_VCvtSD   ( Bool sToD, HReg dst, HReg src );
997 extern ARMInstr* ARMInstr_VXferD   ( Bool toD, HReg dD, HReg rHi, HReg rLo );
998 extern ARMInstr* ARMInstr_VXferS   ( Bool toS, HReg fD, HReg rLo );
999 extern ARMInstr* ARMInstr_VCvtID   ( Bool iToD, Bool syned,
1000                                      HReg dst, HReg src );
1001 extern ARMInstr* ARMInstr_FPSCR    ( Bool toFPSCR, HReg iReg );
1002 extern ARMInstr* ARMInstr_MFence   ( void );
1003 extern ARMInstr* ARMInstr_CLREX    ( void );
1004 extern ARMInstr* ARMInstr_NLdStQ   ( Bool isLoad, HReg, ARMAModeN* );
1005 extern ARMInstr* ARMInstr_NLdStD   ( Bool isLoad, HReg, ARMAModeN* );
1006 extern ARMInstr* ARMInstr_NUnary   ( ARMNeonUnOp, HReg, HReg, UInt, Bool );
1007 extern ARMInstr* ARMInstr_NUnaryS  ( ARMNeonUnOpS, ARMNRS*, ARMNRS*,
1008                                      UInt, Bool );
1009 extern ARMInstr* ARMInstr_NDual    ( ARMNeonDualOp, HReg, HReg, UInt, Bool );
1010 extern ARMInstr* ARMInstr_NBinary  ( ARMNeonBinOp, HReg, HReg, HReg,
1011                                      UInt, Bool );
1012 extern ARMInstr* ARMInstr_NShift   ( ARMNeonShiftOp, HReg, HReg, HReg,
1013                                      UInt, Bool );
1014 extern ARMInstr* ARMInstr_NShl64   ( HReg, HReg, UInt );
1015 extern ARMInstr* ARMInstr_NeonImm  ( HReg, ARMNImm* );
1016 extern ARMInstr* ARMInstr_NCMovQ   ( ARMCondCode, HReg, HReg );
1017 extern ARMInstr* ARMInstr_Add32    ( HReg rD, HReg rN, UInt imm32 );
1018 extern ARMInstr* ARMInstr_EvCheck  ( ARMAMode1* amCounter,
1019                                      ARMAMode1* amFailAddr );
1020 extern ARMInstr* ARMInstr_ProfInc  ( void );
1021 
1022 extern void ppARMInstr ( const ARMInstr* );
1023 
1024 
1025 /* Some functions that insulate the register allocator from details
1026    of the underlying instruction set. */
1027 extern void getRegUsage_ARMInstr ( HRegUsage*, const ARMInstr*, Bool );
1028 extern void mapRegs_ARMInstr     ( HRegRemap*, ARMInstr*, Bool );
1029 extern Bool isMove_ARMInstr      ( const ARMInstr*, HReg*, HReg* );
1030 extern Int  emit_ARMInstr        ( /*MB_MOD*/Bool* is_profInc,
1031                                    UChar* buf, Int nbuf, const ARMInstr* i,
1032                                    Bool mode64,
1033                                    VexEndness endness_host,
1034                                    const void* disp_cp_chain_me_to_slowEP,
1035                                    const void* disp_cp_chain_me_to_fastEP,
1036                                    const void* disp_cp_xindir,
1037                                    const void* disp_cp_xassisted );
1038 
1039 extern void genSpill_ARM  ( /*OUT*/HInstr** i1, /*OUT*/HInstr** i2,
1040                             HReg rreg, Int offset, Bool );
1041 extern void genReload_ARM ( /*OUT*/HInstr** i1, /*OUT*/HInstr** i2,
1042                             HReg rreg, Int offset, Bool );
1043 
1044 extern const RRegUniverse* getRRegUniverse_ARM ( void );
1045 
1046 extern HInstrArray* iselSB_ARM   ( const IRSB*,
1047                                    VexArch,
1048                                    const VexArchInfo*,
1049                                    const VexAbiInfo*,
1050                                    Int offs_Host_EvC_Counter,
1051                                    Int offs_Host_EvC_FailAddr,
1052                                    Bool chainingAllowed,
1053                                    Bool addProfInc,
1054                                    Addr max_ga );
1055 
1056 /* How big is an event check?  This is kind of a kludge because it
1057    depends on the offsets of host_EvC_FAILADDR and
1058    host_EvC_COUNTER. */
1059 extern Int evCheckSzB_ARM (void);
1060 
1061 /* Perform a chaining and unchaining of an XDirect jump. */
1062 extern VexInvalRange chainXDirect_ARM ( VexEndness endness_host,
1063                                         void* place_to_chain,
1064                                         const void* disp_cp_chain_me_EXPECTED,
1065                                         const void* place_to_jump_to );
1066 
1067 extern VexInvalRange unchainXDirect_ARM ( VexEndness endness_host,
1068                                           void* place_to_unchain,
1069                                           const void* place_to_jump_to_EXPECTED,
1070                                           const void* disp_cp_chain_me );
1071 
1072 /* Patch the counter location into an existing ProfInc point. */
1073 extern VexInvalRange patchProfInc_ARM ( VexEndness endness_host,
1074                                         void*  place_to_patch,
1075                                         const ULong* location_of_counter );
1076 
1077 
1078 #endif /* ndef __VEX_HOST_ARM_DEFS_H */
1079 
1080 /*---------------------------------------------------------------*/
1081 /*--- end                                     host_arm_defs.h ---*/
1082 /*---------------------------------------------------------------*/
1083