1 
2 /*---------------------------------------------------------------*/
3 /*--- begin                             guest_arm64_helpers.c ---*/
4 /*---------------------------------------------------------------*/
5 
6 /*
7    This file is part of Valgrind, a dynamic binary instrumentation
8    framework.
9 
10    Copyright (C) 2013-2015 OpenWorks
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_emnote.h"
33 #include "libvex_guest_arm64.h"
34 #include "libvex_ir.h"
35 #include "libvex.h"
36 
37 #include "main_util.h"
38 #include "main_globals.h"
39 #include "guest_generic_bb_to_IR.h"
40 #include "guest_arm64_defs.h"
41 
42 
43 /* This file contains helper functions for arm guest code.  Calls to
44    these functions are generated by the back end.  These calls are of
45    course in the host machine code and this file will be compiled to
46    host machine code, so that all makes sense.
47 
48    Only change the signatures of these helper functions very
49    carefully.  If you change the signature here, you'll have to change
50    the parameters passed to it in the IR calls constructed by
51    guest_arm64_toIR.c.
52 */
53 
54 
55 /* Set to 1 to get detailed profiling info about individual N, Z, C
56    and V flag evaluation. */
57 #define PROFILE_NZCV_FLAGS 0
58 
59 #if PROFILE_NZCV_FLAGS
60 
61 static UInt tab_eval[ARM64G_CC_OP_NUMBER][16];
62 static UInt initted = 0;
63 static UInt tot_evals = 0;
64 
initCounts(void)65 static void initCounts ( void )
66 {
67    UInt i, j;
68    for (i = 0; i < ARM64G_CC_OP_NUMBER; i++) {
69       for (j = 0; j < 16; j++) {
70          tab_eval[i][j] = 0;
71       }
72    }
73    initted = 1;
74 }
75 
showCounts(void)76 static void showCounts ( void )
77 {
78    const HChar* nameCC[16]
79       = { "EQ", "NE", "CS", "CC", "MI", "PL", "VS", "VC",
80           "HI", "LS", "GE", "LT", "GT", "LE", "AL", "NV" };
81    UInt i, j;
82    ULong sum = 0;
83    vex_printf("\nCC_OP          0         1         2         3    "
84               "     4         5         6\n");
85    vex_printf(  "--------------------------------------------------"
86               "--------------------------\n");
87    for (j = 0; j < 16; j++) {
88       vex_printf("%2d %s  ", j, nameCC[j]);
89       for (i = 0; i < ARM64G_CC_OP_NUMBER; i++) {
90          vex_printf("%9d ", tab_eval[i][j]);
91          sum += tab_eval[i][j];
92       }
93       vex_printf("\n");
94    }
95    vex_printf("(In total %llu calls)\n", sum);
96 }
97 
98 #define NOTE_EVAL(_cc_op, _cond) \
99    do { \
100       if (!initted) initCounts(); \
101       vassert( ((UInt)(_cc_op)) < ARM64G_CC_OP_NUMBER); \
102       vassert( ((UInt)(_cond)) < 16); \
103       tab_eval[(UInt)(_cc_op)][(UInt)(cond)]++;  \
104       tot_evals++; \
105       if (0 == (tot_evals & 0x7FFF)) \
106         showCounts(); \
107    } while (0)
108 
109 #endif /* PROFILE_NZCV_FLAGS */
110 
111 
112 /* Calculate the N flag from the supplied thunk components, in the
113    least significant bit of the word.  Returned bits 63:1 are zero. */
114 static
arm64g_calculate_flag_n(ULong cc_op,ULong cc_dep1,ULong cc_dep2,ULong cc_dep3)115 ULong arm64g_calculate_flag_n ( ULong cc_op, ULong cc_dep1,
116                                 ULong cc_dep2, ULong cc_dep3 )
117 {
118    switch (cc_op) {
119       case ARM64G_CC_OP_COPY: {
120          /* (nzcv:28x0, unused, unused) */
121          ULong nf   = (cc_dep1 >> ARM64G_CC_SHIFT_N) & 1;
122          return nf;
123       }
124       case ARM64G_CC_OP_ADD32: {
125          /* (argL, argR, unused) */
126          UInt  argL = (UInt)cc_dep1;
127          UInt  argR = (UInt)cc_dep2;
128          UInt  res  = argL + argR;
129          ULong nf   = (ULong)(res >> 31);
130          return nf;
131       }
132       case ARM64G_CC_OP_ADD64: {
133          /* (argL, argR, unused) */
134          ULong argL = cc_dep1;
135          ULong argR = cc_dep2;
136          ULong res  = argL + argR;
137          ULong nf   = (ULong)(res >> 63);
138          return nf;
139       }
140       case ARM64G_CC_OP_SUB32: {
141          /* (argL, argR, unused) */
142          UInt  argL = (UInt)cc_dep1;
143          UInt  argR = (UInt)cc_dep2;
144          UInt  res  = argL - argR;
145          ULong nf   = (ULong)(res >> 31);
146          return nf;
147       }
148       case ARM64G_CC_OP_SUB64: {
149          /* (argL, argR, unused) */
150          ULong argL = cc_dep1;
151          ULong argR = cc_dep2;
152          ULong res  = argL - argR;
153          ULong nf   = res >> 63;
154          return nf;
155       }
156       case ARM64G_CC_OP_ADC32: {
157          /* (argL, argR, oldC) */
158          UInt  argL = cc_dep1;
159          UInt  argR = cc_dep2;
160          UInt  oldC = cc_dep3;
161          vassert((oldC & ~1) == 0);
162          UInt  res  = argL + argR + oldC;
163          ULong nf   = (ULong)(res >> 31);
164          return nf;
165       }
166       case ARM64G_CC_OP_ADC64: {
167          /* (argL, argR, oldC) */
168          ULong argL = cc_dep1;
169          ULong argR = cc_dep2;
170          ULong oldC = cc_dep3;
171          vassert((oldC & ~1) == 0);
172          ULong res  = argL + argR + oldC;
173          ULong nf   = res >> 63;
174          return nf;
175       }
176       case ARM64G_CC_OP_SBC32: {
177          /* (argL, argR, oldC) */
178          UInt  argL = cc_dep1;
179          UInt  argR = cc_dep2;
180          UInt  oldC = cc_dep3;
181          vassert((oldC & ~1) == 0);
182          UInt  res  = argL - argR - (oldC ^ 1);
183          ULong nf   = (ULong)(res >> 31);
184          return nf;
185       }
186       case ARM64G_CC_OP_SBC64: {
187          /* (argL, argR, oldC) */
188          ULong argL = cc_dep1;
189          ULong argR = cc_dep2;
190          ULong oldC = cc_dep3;
191          vassert((oldC & ~1) == 0);
192          ULong res  = argL - argR - (oldC ^ 1);
193          ULong nf   = res >> 63;
194          return nf;
195       }
196       case ARM64G_CC_OP_LOGIC32: {
197          /* (res, unused, unused) */
198          UInt  res = (UInt)cc_dep1;
199          ULong nf  = res >> 31;
200          return nf;
201       }
202       case ARM64G_CC_OP_LOGIC64: {
203          /* (res, unused, unused) */
204          ULong res = cc_dep1;
205          ULong nf  = res >> 63;
206          return nf;
207       }
208 //ZZ       case ARMG_CC_OP_MUL: {
209 //ZZ          /* (res, unused, oldC:oldV) */
210 //ZZ          UInt res  = cc_dep1;
211 //ZZ          UInt nf   = res >> 31;
212 //ZZ          return nf;
213 //ZZ       }
214 //ZZ       case ARMG_CC_OP_MULL: {
215 //ZZ          /* (resLo32, resHi32, oldC:oldV) */
216 //ZZ          UInt resHi32 = cc_dep2;
217 //ZZ          UInt nf      = resHi32 >> 31;
218 //ZZ          return nf;
219 //ZZ       }
220       default:
221          /* shouldn't really make these calls from generated code */
222          vex_printf("arm64g_calculate_flag_n"
223                     "( op=%llu, dep1=0x%llx, dep2=0x%llx, dep3=0x%llx )\n",
224                     cc_op, cc_dep1, cc_dep2, cc_dep3 );
225          vpanic("arm64g_calculate_flag_n");
226    }
227 }
228 
229 
230 /* Calculate the Z flag from the supplied thunk components, in the
231    least significant bit of the word.  Returned bits 63:1 are zero. */
232 static
arm64g_calculate_flag_z(ULong cc_op,ULong cc_dep1,ULong cc_dep2,ULong cc_dep3)233 ULong arm64g_calculate_flag_z ( ULong cc_op, ULong cc_dep1,
234                                 ULong cc_dep2, ULong cc_dep3 )
235 {
236    switch (cc_op) {
237       case ARM64G_CC_OP_COPY: {
238          /* (nzcv:28x0, unused, unused) */
239          ULong zf   = (cc_dep1 >> ARM64G_CC_SHIFT_Z) & 1;
240          return zf;
241       }
242       case ARM64G_CC_OP_ADD32: {
243          /* (argL, argR, unused) */
244          UInt  argL = (UInt)cc_dep1;
245          UInt  argR = (UInt)cc_dep2;
246          UInt  res  = argL + argR;
247          ULong zf   = res == 0;
248          return zf;
249       }
250       case ARM64G_CC_OP_ADD64: {
251          /* (argL, argR, unused) */
252          ULong argL = cc_dep1;
253          ULong argR = cc_dep2;
254          ULong res  = argL + argR;
255          ULong zf   = res == 0;
256          return zf;
257       }
258       case ARM64G_CC_OP_SUB32: {
259          /* (argL, argR, unused) */
260          UInt  argL = (UInt)cc_dep1;
261          UInt  argR = (UInt)cc_dep2;
262          UInt  res  = argL - argR;
263          ULong zf   = res == 0;
264          return zf;
265       }
266       case ARM64G_CC_OP_SUB64: {
267          /* (argL, argR, unused) */
268          ULong argL = cc_dep1;
269          ULong argR = cc_dep2;
270          ULong res  = argL - argR;
271          ULong zf   = res == 0;
272          return zf;
273       }
274       case ARM64G_CC_OP_ADC32: {
275          /* (argL, argR, oldC) */
276          UInt  argL = cc_dep1;
277          UInt  argR = cc_dep2;
278          UInt  oldC = cc_dep3;
279          vassert((oldC & ~1) == 0);
280          UInt  res  = argL + argR + oldC;
281          ULong zf   = res == 0;
282          return zf;
283       }
284       case ARM64G_CC_OP_ADC64: {
285          /* (argL, argR, oldC) */
286          ULong argL = cc_dep1;
287          ULong argR = cc_dep2;
288          ULong oldC = cc_dep3;
289          vassert((oldC & ~1) == 0);
290          ULong res  = argL + argR + oldC;
291          ULong zf   = res == 0;
292          return zf;
293       }
294       case ARM64G_CC_OP_SBC32: {
295          /* (argL, argR, oldC) */
296          UInt  argL = cc_dep1;
297          UInt  argR = cc_dep2;
298          UInt  oldC = cc_dep3;
299          vassert((oldC & ~1) == 0);
300          UInt  res  = argL - argR - (oldC ^ 1);
301          ULong zf   = res == 0;
302          return zf;
303       }
304       case ARM64G_CC_OP_SBC64: {
305          /* (argL, argR, oldC) */
306          ULong argL = cc_dep1;
307          ULong argR = cc_dep2;
308          ULong oldC = cc_dep3;
309          vassert((oldC & ~1) == 0);
310          ULong res  = argL - argR - (oldC ^ 1);
311          ULong zf   = res == 0;
312          return zf;
313       }
314       case ARM64G_CC_OP_LOGIC32: {
315          /* (res, unused, unused) */
316          UInt  res  = (UInt)cc_dep1;
317          ULong zf   = res == 0;
318          return zf;
319       }
320       case ARM64G_CC_OP_LOGIC64: {
321          /* (res, unused, unused) */
322          ULong res  = cc_dep1;
323          ULong zf   = res == 0;
324          return zf;
325       }
326 //ZZ       case ARMG_CC_OP_MUL: {
327 //ZZ          /* (res, unused, oldC:oldV) */
328 //ZZ          UInt res  = cc_dep1;
329 //ZZ          UInt zf   = res == 0;
330 //ZZ          return zf;
331 //ZZ       }
332 //ZZ       case ARMG_CC_OP_MULL: {
333 //ZZ          /* (resLo32, resHi32, oldC:oldV) */
334 //ZZ          UInt resLo32 = cc_dep1;
335 //ZZ          UInt resHi32 = cc_dep2;
336 //ZZ          UInt zf      = (resHi32|resLo32) == 0;
337 //ZZ          return zf;
338 //ZZ       }
339       default:
340          /* shouldn't really make these calls from generated code */
341          vex_printf("arm64g_calculate_flag_z"
342                     "( op=%llu, dep1=0x%llx, dep2=0x%llx, dep3=0x%llx )\n",
343                     cc_op, cc_dep1, cc_dep2, cc_dep3 );
344          vpanic("arm64g_calculate_flag_z");
345    }
346 }
347 
348 
349 /* CALLED FROM GENERATED CODE: CLEAN HELPER */
350 /* Calculate the C flag from the supplied thunk components, in the
351    least significant bit of the word.  Returned bits 63:1 are zero. */
arm64g_calculate_flag_c(ULong cc_op,ULong cc_dep1,ULong cc_dep2,ULong cc_dep3)352 ULong arm64g_calculate_flag_c ( ULong cc_op, ULong cc_dep1,
353                                 ULong cc_dep2, ULong cc_dep3 )
354 {
355    switch (cc_op) {
356       case ARM64G_CC_OP_COPY: {
357          /* (nzcv:28x0, unused, unused) */
358          ULong cf = (cc_dep1 >> ARM64G_CC_SHIFT_C) & 1;
359          return cf;
360       }
361       case ARM64G_CC_OP_ADD32: {
362          /* (argL, argR, unused) */
363          UInt  argL = (UInt)cc_dep1;
364          UInt  argR = (UInt)cc_dep2;
365          UInt  res  = argL + argR;
366          ULong cf   = res < argL;
367          return cf;
368       }
369       case ARM64G_CC_OP_ADD64: {
370          /* (argL, argR, unused) */
371          ULong argL = cc_dep1;
372          ULong argR = cc_dep2;
373          ULong res  = argL + argR;
374          ULong cf   = res < argL;
375          return cf;
376       }
377       case ARM64G_CC_OP_SUB32: {
378          /* (argL, argR, unused) */
379          UInt  argL = (UInt)cc_dep1;
380          UInt  argR = (UInt)cc_dep2;
381          ULong cf   = argL >= argR;
382          return cf;
383       }
384       case ARM64G_CC_OP_SUB64: {
385          /* (argL, argR, unused) */
386          ULong argL = cc_dep1;
387          ULong argR = cc_dep2;
388          ULong cf   = argL >= argR;
389          return cf;
390       }
391       case ARM64G_CC_OP_ADC32: {
392          /* (argL, argR, oldC) */
393          UInt  argL = cc_dep1;
394          UInt  argR = cc_dep2;
395          UInt  oldC = cc_dep3;
396          vassert((oldC & ~1) == 0);
397          UInt  res  = argL + argR + oldC;
398          ULong cf   = oldC ? (res <= argL) : (res < argL);
399          return cf;
400       }
401       case ARM64G_CC_OP_ADC64: {
402          /* (argL, argR, oldC) */
403          ULong argL = cc_dep1;
404          ULong argR = cc_dep2;
405          ULong oldC = cc_dep3;
406          vassert((oldC & ~1) == 0);
407          ULong res  = argL + argR + oldC;
408          ULong cf   = oldC ? (res <= argL) : (res < argL);
409          return cf;
410       }
411       case ARM64G_CC_OP_SBC32: {
412          /* (argL, argR, oldC) */
413          UInt  argL = cc_dep1;
414          UInt  argR = cc_dep2;
415          UInt  oldC = cc_dep3;
416          vassert((oldC & ~1) == 0);
417          ULong cf   = oldC ? (argL >= argR) : (argL > argR);
418          return cf;
419       }
420       case ARM64G_CC_OP_SBC64: {
421          /* (argL, argR, oldC) */
422          ULong argL = cc_dep1;
423          ULong argR = cc_dep2;
424          ULong oldC = cc_dep3;
425          vassert((oldC & ~1) == 0);
426          ULong cf   = oldC ? (argL >= argR) : (argL > argR);
427          return cf;
428       }
429       case ARM64G_CC_OP_LOGIC32:
430       case ARM64G_CC_OP_LOGIC64: {
431          /* (res, unused, unused) */
432          return 0; // C after logic is zero on arm64
433       }
434 //ZZ       case ARMG_CC_OP_MUL: {
435 //ZZ          /* (res, unused, oldC:oldV) */
436 //ZZ          UInt oldC = (cc_dep3 >> 1) & 1;
437 //ZZ          vassert((cc_dep3 & ~3) == 0);
438 //ZZ          UInt cf   = oldC;
439 //ZZ          return cf;
440 //ZZ       }
441 //ZZ       case ARMG_CC_OP_MULL: {
442 //ZZ          /* (resLo32, resHi32, oldC:oldV) */
443 //ZZ          UInt oldC    = (cc_dep3 >> 1) & 1;
444 //ZZ          vassert((cc_dep3 & ~3) == 0);
445 //ZZ          UInt cf      = oldC;
446 //ZZ          return cf;
447 //ZZ       }
448       default:
449          /* shouldn't really make these calls from generated code */
450          vex_printf("arm64g_calculate_flag_c"
451                     "( op=%llu, dep1=0x%llx, dep2=0x%llx, dep3=0x%llx )\n",
452                     cc_op, cc_dep1, cc_dep2, cc_dep3 );
453          vpanic("arm64g_calculate_flag_c");
454    }
455 }
456 
457 
458 /* CALLED FROM GENERATED CODE: CLEAN HELPER */
459 /* Calculate the V flag from the supplied thunk components, in the
460    least significant bit of the word.  Returned bits 63:1 are zero. */
461 static
arm64g_calculate_flag_v(ULong cc_op,ULong cc_dep1,ULong cc_dep2,ULong cc_dep3)462 ULong arm64g_calculate_flag_v ( ULong cc_op, ULong cc_dep1,
463                                 ULong cc_dep2, ULong cc_dep3 )
464 {
465    switch (cc_op) {
466       case ARM64G_CC_OP_COPY: {
467          /* (nzcv:28x0, unused, unused) */
468          ULong vf   = (cc_dep1 >> ARM64G_CC_SHIFT_V) & 1;
469          return vf;
470       }
471       case ARM64G_CC_OP_ADD32: {
472          /* (argL, argR, unused) */
473          UInt  argL = (UInt)cc_dep1;
474          UInt  argR = (UInt)cc_dep2;
475          UInt  res  = argL + argR;
476          ULong vf   = (ULong)(((res ^ argL) & (res ^ argR)) >> 31);
477          return vf;
478       }
479       case ARM64G_CC_OP_ADD64: {
480          /* (argL, argR, unused) */
481          ULong argL = cc_dep1;
482          ULong argR = cc_dep2;
483          ULong res  = argL + argR;
484          ULong vf   = ((res ^ argL) & (res ^ argR)) >> 63;
485          return vf;
486       }
487       case ARM64G_CC_OP_SUB32: {
488          /* (argL, argR, unused) */
489          UInt  argL = (UInt)cc_dep1;
490          UInt  argR = (UInt)cc_dep2;
491          UInt  res  = argL - argR;
492          ULong vf   = (ULong)(((argL ^ argR) & (argL ^ res)) >> 31);
493          return vf;
494       }
495       case ARM64G_CC_OP_SUB64: {
496          /* (argL, argR, unused) */
497          ULong argL = cc_dep1;
498          ULong argR = cc_dep2;
499          ULong res  = argL - argR;
500          ULong vf   = (((argL ^ argR) & (argL ^ res))) >> 63;
501          return vf;
502       }
503       case ARM64G_CC_OP_ADC32: {
504          /* (argL, argR, oldC) */
505          UInt  argL = cc_dep1;
506          UInt  argR = cc_dep2;
507          UInt  oldC = cc_dep3;
508          vassert((oldC & ~1) == 0);
509          UInt  res  = argL + argR + oldC;
510          ULong vf   = (ULong)(((res ^ argL) & (res ^ argR)) >> 31);
511          return vf;
512       }
513       case ARM64G_CC_OP_ADC64: {
514          /* (argL, argR, oldC) */
515          ULong argL = cc_dep1;
516          ULong argR = cc_dep2;
517          ULong oldC = cc_dep3;
518          vassert((oldC & ~1) == 0);
519          ULong res  = argL + argR + oldC;
520          ULong vf   = ((res ^ argL) & (res ^ argR)) >> 63;
521          return vf;
522       }
523       case ARM64G_CC_OP_SBC32: {
524          /* (argL, argR, oldC) */
525          UInt  argL = cc_dep1;
526          UInt  argR = cc_dep2;
527          UInt  oldC = cc_dep3;
528          vassert((oldC & ~1) == 0);
529          UInt  res  = argL - argR - (oldC ^ 1);
530          ULong vf   = (ULong)(((argL ^ argR) & (argL ^ res)) >> 31);
531          return vf;
532       }
533       case ARM64G_CC_OP_SBC64: {
534          /* (argL, argR, oldC) */
535          ULong argL = cc_dep1;
536          ULong argR = cc_dep2;
537          ULong oldC = cc_dep3;
538          vassert((oldC & ~1) == 0);
539          ULong res  = argL - argR - (oldC ^ 1);
540          ULong vf   = ((argL ^ argR) & (argL ^ res)) >> 63;
541          return vf;
542       }
543       case ARM64G_CC_OP_LOGIC32:
544       case ARM64G_CC_OP_LOGIC64: {
545          /* (res, unused, unused) */
546          return 0; // V after logic is zero on arm64
547       }
548 //ZZ       case ARMG_CC_OP_MUL: {
549 //ZZ          /* (res, unused, oldC:oldV) */
550 //ZZ          UInt oldV = (cc_dep3 >> 0) & 1;
551 //ZZ          vassert((cc_dep3 & ~3) == 0);
552 //ZZ          UInt vf   = oldV;
553 //ZZ          return vf;
554 //ZZ       }
555 //ZZ       case ARMG_CC_OP_MULL: {
556 //ZZ          /* (resLo32, resHi32, oldC:oldV) */
557 //ZZ          UInt oldV    = (cc_dep3 >> 0) & 1;
558 //ZZ          vassert((cc_dep3 & ~3) == 0);
559 //ZZ          UInt vf      = oldV;
560 //ZZ          return vf;
561 //ZZ       }
562       default:
563          /* shouldn't really make these calls from generated code */
564          vex_printf("arm64g_calculate_flag_v"
565                     "( op=%llu, dep1=0x%llx, dep2=0x%llx, dep3=0x%llx )\n",
566                     cc_op, cc_dep1, cc_dep2, cc_dep3 );
567          vpanic("arm64g_calculate_flag_v");
568    }
569 }
570 
571 
572 /* CALLED FROM GENERATED CODE: CLEAN HELPER */
573 /* Calculate NZCV from the supplied thunk components, in the positions
574    they appear in the CPSR, viz bits 31:28 for N Z C V respectively.
575    Returned bits 27:0 are zero. */
arm64g_calculate_flags_nzcv(ULong cc_op,ULong cc_dep1,ULong cc_dep2,ULong cc_dep3)576 ULong arm64g_calculate_flags_nzcv ( ULong cc_op, ULong cc_dep1,
577                                     ULong cc_dep2, ULong cc_dep3 )
578 {
579    ULong f;
580    ULong res = 0;
581    f = 1 & arm64g_calculate_flag_n(cc_op, cc_dep1, cc_dep2, cc_dep3);
582    res |= (f << ARM64G_CC_SHIFT_N);
583    f = 1 & arm64g_calculate_flag_z(cc_op, cc_dep1, cc_dep2, cc_dep3);
584    res |= (f << ARM64G_CC_SHIFT_Z);
585    f = 1 & arm64g_calculate_flag_c(cc_op, cc_dep1, cc_dep2, cc_dep3);
586    res |= (f << ARM64G_CC_SHIFT_C);
587    f = 1 & arm64g_calculate_flag_v(cc_op, cc_dep1, cc_dep2, cc_dep3);
588    res |= (f << ARM64G_CC_SHIFT_V);
589    return res;
590 }
591 
592 //ZZ
593 //ZZ /* CALLED FROM GENERATED CODE: CLEAN HELPER */
594 //ZZ /* Calculate the QC flag from the arguments, in the lowest bit
595 //ZZ    of the word (bit 0).  Urr, having this out of line is bizarre.
596 //ZZ    Push back inline. */
597 //ZZ UInt armg_calculate_flag_qc ( UInt resL1, UInt resL2,
598 //ZZ                               UInt resR1, UInt resR2 )
599 //ZZ {
600 //ZZ    if (resL1 != resR1 || resL2 != resR2)
601 //ZZ       return 1;
602 //ZZ    else
603 //ZZ       return 0;
604 //ZZ }
605 
606 /* CALLED FROM GENERATED CODE: CLEAN HELPER */
607 /* Calculate the specified condition from the thunk components, in the
608    lowest bit of the word (bit 0).  Returned bits 63:1 are zero. */
arm64g_calculate_condition(ULong cond_n_op,ULong cc_dep1,ULong cc_dep2,ULong cc_dep3)609 ULong arm64g_calculate_condition ( /* ARM64Condcode << 4 | cc_op */
610                                    ULong cond_n_op ,
611                                    ULong cc_dep1,
612                                    ULong cc_dep2, ULong cc_dep3 )
613 {
614    ULong cond  = cond_n_op >> 4;
615    ULong cc_op = cond_n_op & 0xF;
616    ULong inv   = cond & 1;
617    ULong nf, zf, vf, cf;
618 
619 #  if PROFILE_NZCV_FLAGS
620    NOTE_EVAL(cc_op, cond);
621 #  endif
622 
623    //   vex_printf("XXXXXXXX %llx %llx %llx %llx\n",
624    //              cond_n_op, cc_dep1, cc_dep2, cc_dep3);
625 
626    switch (cond) {
627       case ARM64CondEQ:    // Z=1         => z
628       case ARM64CondNE:    // Z=0
629          zf = arm64g_calculate_flag_z(cc_op, cc_dep1, cc_dep2, cc_dep3);
630          return inv ^ zf;
631 
632       case ARM64CondCS:    // C=1         => c
633       case ARM64CondCC:    // C=0
634          cf = arm64g_calculate_flag_c(cc_op, cc_dep1, cc_dep2, cc_dep3);
635          return inv ^ cf;
636 
637       case ARM64CondMI:    // N=1         => n
638       case ARM64CondPL:    // N=0
639          nf = arm64g_calculate_flag_n(cc_op, cc_dep1, cc_dep2, cc_dep3);
640          return inv ^ nf;
641 
642       case ARM64CondVS:    // V=1         => v
643       case ARM64CondVC:    // V=0
644          vf = arm64g_calculate_flag_v(cc_op, cc_dep1, cc_dep2, cc_dep3);
645          return inv ^ vf;
646 
647       case ARM64CondHI:    // C=1 && Z=0   => c & ~z
648       case ARM64CondLS:    // C=0 || Z=1
649          cf = arm64g_calculate_flag_c(cc_op, cc_dep1, cc_dep2, cc_dep3);
650          zf = arm64g_calculate_flag_z(cc_op, cc_dep1, cc_dep2, cc_dep3);
651          return inv ^ (1 & (cf & ~zf));
652 
653       case ARM64CondGE:    // N=V          => ~(n^v)
654       case ARM64CondLT:    // N!=V
655          nf = arm64g_calculate_flag_n(cc_op, cc_dep1, cc_dep2, cc_dep3);
656          vf = arm64g_calculate_flag_v(cc_op, cc_dep1, cc_dep2, cc_dep3);
657          return inv ^ (1 & ~(nf ^ vf));
658 
659       case ARM64CondGT:    // Z=0 && N=V   => ~z & ~(n^v)  =>  ~(z | (n^v))
660       case ARM64CondLE:    // Z=1 || N!=V
661          nf = arm64g_calculate_flag_n(cc_op, cc_dep1, cc_dep2, cc_dep3);
662          vf = arm64g_calculate_flag_v(cc_op, cc_dep1, cc_dep2, cc_dep3);
663          zf = arm64g_calculate_flag_z(cc_op, cc_dep1, cc_dep2, cc_dep3);
664          return inv ^ (1 & ~(zf | (nf ^ vf)));
665 
666       case ARM64CondAL:    // 1
667       case ARM64CondNV:    // 1
668          return 1;
669 
670       default:
671          /* shouldn't really make these calls from generated code */
672          vex_printf("arm64g_calculate_condition(ARM64)"
673                     "( %llu, %llu, 0x%llx, 0x%llx, 0x%llx )\n",
674                     cond, cc_op, cc_dep1, cc_dep2, cc_dep3 );
675          vpanic("armg_calculate_condition(ARM64)");
676    }
677 }
678 
679 
680 /* CALLED FROM GENERATED CODE: CLEAN HELPER */
arm64g_calc_crc32b(ULong acc,ULong bits)681 ULong arm64g_calc_crc32b ( ULong acc, ULong bits )
682 {
683    UInt  i;
684    ULong crc = (bits & 0xFFULL) ^ acc;
685    for (i = 0; i < 8; i++)
686       crc = (crc >> 1) ^ ((crc & 1) ? 0xEDB88320ULL : 0);
687    return crc;
688 }
689 
690 /* CALLED FROM GENERATED CODE: CLEAN HELPER */
arm64g_calc_crc32h(ULong acc,ULong bits)691 ULong arm64g_calc_crc32h ( ULong acc, ULong bits )
692 {
693    UInt  i;
694    ULong crc = (bits & 0xFFFFULL) ^ acc;
695    for (i = 0; i < 16; i++)
696       crc = (crc >> 1) ^ ((crc & 1) ? 0xEDB88320ULL : 0);
697    return crc;
698 }
699 
700 /* CALLED FROM GENERATED CODE: CLEAN HELPER */
arm64g_calc_crc32w(ULong acc,ULong bits)701 ULong arm64g_calc_crc32w ( ULong acc, ULong bits )
702 {
703    UInt  i;
704    ULong crc = (bits & 0xFFFFFFFFULL) ^ acc;
705    for (i = 0; i < 32; i++)
706       crc = (crc >> 1) ^ ((crc & 1) ? 0xEDB88320ULL : 0);
707    return crc;
708 }
709 
710 /* CALLED FROM GENERATED CODE: CLEAN HELPER */
arm64g_calc_crc32x(ULong acc,ULong bits)711 ULong arm64g_calc_crc32x ( ULong acc, ULong bits )
712 {
713    UInt  i;
714    ULong crc = bits ^ acc;
715    for (i = 0; i < 64; i++)
716       crc = (crc >> 1) ^ ((crc & 1) ? 0xEDB88320ULL : 0);
717    return crc;
718 
719 }
720 
721 /* CALLED FROM GENERATED CODE: CLEAN HELPER */
arm64g_calc_crc32cb(ULong acc,ULong bits)722 ULong arm64g_calc_crc32cb ( ULong acc, ULong bits )
723 {
724    UInt  i;
725    ULong crc = (bits & 0xFFULL) ^ acc;
726    for (i = 0; i < 8; i++)
727       crc = (crc >> 1) ^ ((crc & 1) ? 0x82F63B78ULL : 0);
728    return crc;
729 }
730 
731 /* CALLED FROM GENERATED CODE: CLEAN HELPER */
arm64g_calc_crc32ch(ULong acc,ULong bits)732 ULong arm64g_calc_crc32ch ( ULong acc, ULong bits )
733 {
734    UInt  i;
735    ULong crc = (bits & 0xFFFFULL) ^ acc;
736    for (i = 0; i < 16; i++)
737       crc = (crc >> 1) ^ ((crc & 1) ? 0x82F63B78ULL : 0);
738    return crc;
739 }
740 
741 /* CALLED FROM GENERATED CODE: CLEAN HELPER */
arm64g_calc_crc32cw(ULong acc,ULong bits)742 ULong arm64g_calc_crc32cw ( ULong acc, ULong bits )
743 {
744    UInt  i;
745    ULong crc = (bits & 0xFFFFFFFFULL) ^ acc;
746    for (i = 0; i < 32; i++)
747       crc = (crc >> 1) ^ ((crc & 1) ? 0x82F63B78ULL : 0);
748    return crc;
749 }
750 
751 /* CALLED FROM GENERATED CODE: CLEAN HELPER */
arm64g_calc_crc32cx(ULong acc,ULong bits)752 ULong arm64g_calc_crc32cx ( ULong acc, ULong bits )
753 {
754    UInt  i;
755    ULong crc = bits ^ acc;
756    for (i = 0; i < 64; i++)
757       crc = (crc >> 1) ^ ((crc & 1) ? 0x82F63B78ULL : 0);
758    return crc;
759 }
760 
761 
762 /* CALLED FROM GENERATED CODE */
763 /* DIRTY HELPER (non-referentially-transparent) */
764 /* Horrible hack.  On non-arm64 platforms, return 0. */
arm64g_dirtyhelper_MRS_CNTVCT_EL0(void)765 ULong arm64g_dirtyhelper_MRS_CNTVCT_EL0 ( void )
766 {
767 #  if defined(__aarch64__) && !defined(__arm__)
768    ULong w = 0x5555555555555555ULL; /* overwritten */
769    __asm__ __volatile__("mrs %0, cntvct_el0" : "=r"(w));
770    return w;
771 #  else
772    return 0ULL;
773 #  endif
774 }
775 
776 
arm64g_dirtyhelper_PMULLQ(V128 * res,ULong arg1,ULong arg2)777 void arm64g_dirtyhelper_PMULLQ ( /*OUT*/V128* res, ULong arg1, ULong arg2 )
778 {
779    /* This doesn't need to be a dirty helper, except for the fact that
780       a clean helper can't return a 128 bit value.  This is a pretty
781       lame implementation of PMULLQ, but at least it doesn't contain any
782       data dependent branches, and has lots of ILP.  I guess we could unroll
783       the loop completely and offer extensive prayers to the gods of ILP
784       if more performance is needed. */
785    UInt i;
786    ULong accHi = 0, accLo = 0;
787    ULong op2Hi = 0, op2Lo = arg2;
788    for (i = 0; i < 64; i++) {
789       /* Make |mask| be all 0s or all 1s, a copy of arg1[i] */
790       Long mask = arg1 << (63-i);
791       mask >>= 63;
792       accHi ^= (op2Hi & mask);
793       accLo ^= (op2Lo & mask);
794       /* do: op2Hi:op2Lo <<=u 1 */
795       op2Hi <<= 1;
796       op2Hi |= ((op2Lo >> 63) & 1);
797       op2Lo <<= 1;
798    }
799    res->w64[1] = accHi;
800    res->w64[0] = accLo;
801 }
802 
803 
804 /*---------------------------------------------------------------*/
805 /*--- Crypto instruction helpers                              ---*/
806 /*---------------------------------------------------------------*/
807 
808 /* DIRTY HELPERS for doing AES support:
809    * AESE (SubBytes, then ShiftRows)
810    * AESD (InvShiftRows, then InvSubBytes)
811    * AESMC (MixColumns)
812    * AESIMC (InvMixColumns)
813    These don't actually have to be dirty helpers -- they could be
814    clean, but for the fact that they return a V128 and a clean helper
815    can't do that.
816 
817    The ARMv8 manual seems to imply that AESE first performs ShiftRows,
818    then SubBytes.  This seems to contradict FIPS 197, so the
819    implementation below is consistent with FIPS 197.  One can observe
820    that the two transformations commute -- the order in which they
821    happen makes no difference to the result.  So the ambiguity doesn't
822    actually matter, but it is confusing.  The v8 manual looks correct
823    about AESD, though.
824 
825    The three functions rj_xtime, aesMixColumn and aesInvMixColumn only,
826    are taken from "A byte-oriented AES-256 implementation" and are subject
827    to the following usage terms:
828 
829      Byte-oriented AES-256 implementation.
830      All lookup tables replaced with 'on the fly' calculations.
831 
832      Copyright (c) 2007-2011 Ilya O. Levin, http://www.literatecode.com
833      Other contributors: Hal Finney
834 
835      Permission to use, copy, modify, and distribute this software for any
836      purpose with or without fee is hereby granted, provided that the above
837      copyright notice and this permission notice appear in all copies.
838 
839      THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
840      WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
841      MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
842      ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
843      WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
844      ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
845      OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
846 */
847 
848 const UChar aesMapSubBytes[256]
849    = { 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5,
850        0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
851        0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0,
852        0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
853        0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc,
854        0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
855        0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a,
856        0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
857        0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0,
858        0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
859        0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b,
860        0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
861        0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85,
862        0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
863        0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5,
864        0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
865        0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17,
866        0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
867        0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88,
868        0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
869        0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c,
870        0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
871        0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9,
872        0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
873        0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6,
874        0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
875        0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e,
876        0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
877        0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94,
878        0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
879        0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68,
880        0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
881      };
882 
883 const UChar aesMapInvSubBytes[256]
884    = { 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38,
885        0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
886        0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87,
887        0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
888        0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d,
889        0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
890        0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2,
891        0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
892        0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16,
893        0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
894        0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda,
895        0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
896        0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a,
897        0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
898        0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02,
899        0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
900        0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea,
901        0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
902        0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85,
903        0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
904        0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89,
905        0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
906        0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20,
907        0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
908        0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31,
909        0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
910        0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d,
911        0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
912        0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0,
913        0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
914        0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26,
915        0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d
916      };
917 
rj_xtime(UChar x)918 static inline UChar rj_xtime ( UChar x )
919 {
920    UChar y = (UChar)(x << 1);
921    return (x & 0x80) ? (y ^ 0x1b) : y;
922 }
923 
aesMixColumn(UChar * r)924 static void aesMixColumn ( /*MOD*/UChar* r )
925 {
926    UChar a = r[0];
927    UChar b = r[1];
928    UChar c = r[2];
929    UChar d = r[3];
930    UChar e = a ^ b ^ c ^ d;
931    r[0] ^= e ^ rj_xtime(a ^ b);
932    r[1] ^= e ^ rj_xtime(b ^ c);
933    r[2] ^= e ^ rj_xtime(c ^ d);
934    r[3] ^= e ^ rj_xtime(d ^ a);
935 }
936 
aesInvMixColumn(UChar * r)937 static void aesInvMixColumn ( /*MOD*/UChar* r )
938 {
939    UChar a = r[0];
940    UChar b = r[1];
941    UChar c = r[2];
942    UChar d = r[3];
943    UChar e = a ^ b ^ c ^ d;
944    UChar z = rj_xtime(e);
945    UChar x = e ^ rj_xtime(rj_xtime(z ^ a ^ c));
946    UChar y = e ^ rj_xtime(rj_xtime(z ^ b ^ d));
947    r[0] ^= x ^ rj_xtime(a ^ b);
948    r[1] ^= y ^ rj_xtime(b ^ c);
949    r[2] ^= x ^ rj_xtime(c ^ d);
950    r[3] ^= y ^ rj_xtime(d ^ a);
951 }
952 
953 
954 /* CALLED FROM GENERATED CODE */
arm64g_dirtyhelper_AESE(V128 * res,ULong argHi,ULong argLo)955 void arm64g_dirtyhelper_AESE ( /*OUT*/V128* res, ULong argHi, ULong argLo )
956 {
957    res->w64[1] = argHi;
958    res->w64[0] = argLo;
959 
960    /* First do SubBytes on the State. */
961    UInt i;
962    for (i = 0; i < 16; i++) {
963       res->w8[i] = aesMapSubBytes[res->w8[i] & 0xFF];
964    }
965 
966    /* Then do ShiftRows on the State. */
967 #  define XX(_ix) res->w8[_ix]
968    { UChar old1 = XX(1);
969      XX(1) = XX(5); XX(5) = XX(9); XX(9) = XX(13); XX(13) = old1;
970    }
971    { UChar old2 = XX(2); UChar old6 = XX(6);
972      XX(2) = XX(10); XX(6) = XX(14); XX(10) = old2; XX(14) = old6;
973    }
974    { UChar old15 = XX(15);
975      XX(15) = XX(11); XX(11) = XX(7); XX(7) = XX(3); XX(3) = old15;
976    }
977 #  undef XX
978 }
979 
980 
981 /* CALLED FROM GENERATED CODE */
arm64g_dirtyhelper_AESD(V128 * res,ULong argHi,ULong argLo)982 void arm64g_dirtyhelper_AESD ( /*OUT*/V128* res, ULong argHi, ULong argLo )
983 {
984    res->w64[1] = argHi;
985    res->w64[0] = argLo;
986 
987    /* First do InvShiftRows on the State. */
988 #  define XX(_ix) res->w8[_ix]
989    { UChar old13 = XX(13);
990      XX(13) = XX(9); XX(9) = XX(5); XX(5) = XX(1); XX(1) = old13;
991    }
992    { UChar old14 = XX(14); UChar old10 = XX(10);
993      XX(14) = XX(6); XX(10) = XX(2); XX(6) = old14; XX(2) = old10;
994    }
995    { UChar old3 = XX(3);
996      XX(3) = XX(7); XX(7) = XX(11); XX(11) = XX(15); XX(15) = old3;
997    }
998 #  undef XX
999 
1000 /* Then do InvSubBytes on the State. */
1001    UInt i;
1002    for (i = 0; i < 16; i++) {
1003       res->w8[i] = aesMapInvSubBytes[res->w8[i] & 0xFF];
1004    }
1005 }
1006 
1007 
1008 /* CALLED FROM GENERATED CODE */
arm64g_dirtyhelper_AESMC(V128 * res,ULong argHi,ULong argLo)1009 void arm64g_dirtyhelper_AESMC ( /*OUT*/V128* res, ULong argHi, ULong argLo )
1010 {
1011    res->w64[1] = argHi;
1012    res->w64[0] = argLo;
1013    aesMixColumn(&res->w8[0]);
1014    aesMixColumn(&res->w8[4]);
1015    aesMixColumn(&res->w8[8]);
1016    aesMixColumn(&res->w8[12]);
1017 }
1018 
1019 
1020 /* CALLED FROM GENERATED CODE */
arm64g_dirtyhelper_AESIMC(V128 * res,ULong argHi,ULong argLo)1021 void arm64g_dirtyhelper_AESIMC ( /*OUT*/V128* res, ULong argHi, ULong argLo )
1022 {
1023    res->w64[1] = argHi;
1024    res->w64[0] = argLo;
1025    aesInvMixColumn(&res->w8[0]);
1026    aesInvMixColumn(&res->w8[4]);
1027    aesInvMixColumn(&res->w8[8]);
1028    aesInvMixColumn(&res->w8[12]);
1029 }
1030 
1031 
1032 /* DIRTY HELPERS for SHA instruction support.  As with the AES helpers
1033    above, these are actually pure functions and are only dirty because
1034    clean helpers can't return a V128. */
1035 
ROL32(UInt x,UInt sh)1036 static inline UInt ROL32 ( UInt x, UInt sh ) {
1037    vassert(sh > 0 && sh < 32);
1038    return (x << sh) | (x >> (32 - sh));
1039 }
1040 
ROR32(UInt x,UInt sh)1041 static inline UInt ROR32 ( UInt x, UInt sh ) {
1042    vassert(sh > 0 && sh < 32);
1043    return (x >> sh) | (x << (32 - sh));
1044 }
1045 
SHAchoose(UInt x,UInt y,UInt z)1046 static inline UInt SHAchoose ( UInt x, UInt y, UInt z ) {
1047    return ((y ^ z) & x) ^ z;
1048 }
1049 
SHAmajority(UInt x,UInt y,UInt z)1050 static inline UInt SHAmajority ( UInt x, UInt y, UInt z ) {
1051    return (x & y) | ((x | y) & z);
1052 }
1053 
SHAparity(UInt x,UInt y,UInt z)1054 static inline UInt SHAparity ( UInt x, UInt y, UInt z ) {
1055    return x ^ y ^ z;
1056 }
1057 
SHAhashSIGMA0(UInt x)1058 static inline UInt SHAhashSIGMA0 ( UInt x ) {
1059    return ROR32(x, 2) ^ ROR32(x, 13) ^ ROR32(x, 22);
1060 }
1061 
SHAhashSIGMA1(UInt x)1062 static inline UInt SHAhashSIGMA1 ( UInt x ) {
1063    return ROR32(x, 6) ^ ROR32(x, 11) ^ ROR32(x, 25);
1064 }
1065 
SHA256hash(V128 * X,V128 * Y,const V128 * W)1066 static void SHA256hash ( /*MOD*/V128* X, /*MOD*/V128* Y, const V128* W )
1067 {
1068    UInt e;
1069    for (e = 0; e <= 3; e++) {
1070       UInt chs = SHAchoose(Y->w32[0], Y->w32[1], Y->w32[2]);
1071       UInt maj = SHAmajority(X->w32[0], X->w32[1], X->w32[2]);
1072       UInt t   = Y->w32[3] + SHAhashSIGMA1(Y->w32[0]) + chs + W->w32[e];
1073       X->w32[3] = t + X->w32[3];
1074       Y->w32[3] = t + SHAhashSIGMA0(X->w32[0]) + maj;
1075       UInt ts = Y->w32[3];
1076       Y->w32[3] = Y->w32[2];
1077       Y->w32[2] = Y->w32[1];
1078       Y->w32[1] = Y->w32[0];
1079       Y->w32[0] = X->w32[3];
1080       X->w32[3] = X->w32[2];
1081       X->w32[2] = X->w32[1];
1082       X->w32[1] = X->w32[0];
1083       X->w32[0] = ts;
1084    }
1085 }
1086 
1087 /* CALLED FROM GENERATED CODE */
arm64g_dirtyhelper_SHA1C(V128 * res,ULong dHi,ULong dLo,ULong nHi,ULong nLo,ULong mHi,ULong mLo)1088 void arm64g_dirtyhelper_SHA1C ( /*OUT*/V128* res, ULong dHi, ULong dLo,
1089                                 ULong nHi, ULong nLo, ULong mHi, ULong mLo )
1090 {
1091    vassert(nHi == 0);
1092    vassert((nLo >> 32) == 0);
1093    V128 X; X.w64[1] = dHi; X.w64[0] = dLo;
1094    UInt Y; Y = (UInt)nLo;
1095    V128 W; W.w64[1] = mHi; W.w64[0] = mLo;
1096    UInt e;
1097    for (e = 0; e <= 3; e++) {
1098       UInt t = SHAchoose(X.w32[1], X.w32[2], X.w32[3]);
1099       Y = Y + ROL32(X.w32[0], 5) + t + W.w32[e];
1100       X.w32[1] = ROL32(X.w32[1], 30);
1101       UInt oldY = Y;
1102       Y = X.w32[3];
1103       X.w32[3] = X.w32[2];
1104       X.w32[2] = X.w32[1];
1105       X.w32[1] = X.w32[0];
1106       X.w32[0] = oldY;
1107    }
1108    res->w64[1] = X.w64[1];
1109    res->w64[0] = X.w64[0];
1110 }
1111 
1112 /* CALLED FROM GENERATED CODE */
arm64g_dirtyhelper_SHA1H(V128 * res,ULong nHi,ULong nLo)1113 void arm64g_dirtyhelper_SHA1H ( /*OUT*/V128* res, ULong nHi, ULong nLo )
1114 {
1115    vassert(nHi == 0);
1116    vassert((nLo >> 32) == 0);
1117    res->w32[3] = res->w32[2] = res->w32[1] = 0;
1118    res->w32[0] = ROL32((UInt)nLo, 30);
1119 }
1120 
1121 /* CALLED FROM GENERATED CODE */
arm64g_dirtyhelper_SHA1M(V128 * res,ULong dHi,ULong dLo,ULong nHi,ULong nLo,ULong mHi,ULong mLo)1122 void arm64g_dirtyhelper_SHA1M ( /*OUT*/V128* res, ULong dHi, ULong dLo,
1123                                 ULong nHi, ULong nLo, ULong mHi, ULong mLo )
1124 {
1125    vassert(nHi == 0);
1126    vassert((nLo >> 32) == 0);
1127    V128 X; X.w64[1] = dHi; X.w64[0] = dLo;
1128    UInt Y; Y = (UInt)nLo;
1129    V128 W; W.w64[1] = mHi; W.w64[0] = mLo;
1130    UInt e;
1131    for (e = 0; e <= 3; e++) {
1132       UInt t = SHAmajority(X.w32[1], X.w32[2], X.w32[3]);
1133       Y = Y + ROL32(X.w32[0], 5) + t + W.w32[e];
1134       X.w32[1] = ROL32(X.w32[1], 30);
1135       UInt oldY = Y;
1136       Y = X.w32[3];
1137       X.w32[3] = X.w32[2];
1138       X.w32[2] = X.w32[1];
1139       X.w32[1] = X.w32[0];
1140       X.w32[0] = oldY;
1141    }
1142    res->w64[1] = X.w64[1];
1143    res->w64[0] = X.w64[0];
1144 }
1145 
1146 /* CALLED FROM GENERATED CODE */
arm64g_dirtyhelper_SHA1P(V128 * res,ULong dHi,ULong dLo,ULong nHi,ULong nLo,ULong mHi,ULong mLo)1147 void arm64g_dirtyhelper_SHA1P ( /*OUT*/V128* res, ULong dHi, ULong dLo,
1148                                 ULong nHi, ULong nLo, ULong mHi, ULong mLo )
1149 {
1150    vassert(nHi == 0);
1151    vassert((nLo >> 32) == 0);
1152    V128 X; X.w64[1] = dHi; X.w64[0] = dLo;
1153    UInt Y; Y = (UInt)nLo;
1154    V128 W; W.w64[1] = mHi; W.w64[0] = mLo;
1155    UInt e;
1156    for (e = 0; e <= 3; e++) {
1157       UInt t = SHAparity(X.w32[1], X.w32[2], X.w32[3]);
1158       Y = Y + ROL32(X.w32[0], 5) + t + W.w32[e];
1159       X.w32[1] = ROL32(X.w32[1], 30);
1160       UInt oldY = Y;
1161       Y = X.w32[3];
1162       X.w32[3] = X.w32[2];
1163       X.w32[2] = X.w32[1];
1164       X.w32[1] = X.w32[0];
1165       X.w32[0] = oldY;
1166    }
1167    res->w64[1] = X.w64[1];
1168    res->w64[0] = X.w64[0];
1169 }
1170 
1171 /* CALLED FROM GENERATED CODE */
arm64g_dirtyhelper_SHA1SU0(V128 * res,ULong dHi,ULong dLo,ULong nHi,ULong nLo,ULong mHi,ULong mLo)1172 void arm64g_dirtyhelper_SHA1SU0 ( /*OUT*/V128* res, ULong dHi, ULong dLo,
1173                                   ULong nHi, ULong nLo, ULong mHi, ULong mLo )
1174 {
1175    res->w64[1] = nLo;
1176    res->w64[0] = dHi;
1177    res->w64[1] ^= dHi ^ mHi;
1178    res->w64[0] ^= dLo ^ mLo;
1179 }
1180 
1181 /* CALLED FROM GENERATED CODE */
arm64g_dirtyhelper_SHA1SU1(V128 * res,ULong dHi,ULong dLo,ULong nHi,ULong nLo)1182 void arm64g_dirtyhelper_SHA1SU1 ( /*OUT*/V128* res, ULong dHi, ULong dLo,
1183                                   ULong nHi, ULong nLo )
1184 {
1185    /* This computes "T = Vd ^ (Vn >>u 32)" */
1186    V128 T; T.w64[1] = nHi; T.w64[0] = nLo;
1187    T.w32[0] = T.w32[1];
1188    T.w32[1] = T.w32[2];
1189    T.w32[2] = T.w32[3];
1190    T.w32[3] = 0;
1191    T.w64[1] ^= dHi;
1192    T.w64[0] ^= dLo;
1193    /* */
1194    res->w32[0] = ROL32(T.w32[0], 1);
1195    res->w32[1] = ROL32(T.w32[1], 1);
1196    res->w32[2] = ROL32(T.w32[2], 1);
1197    res->w32[3] = ROL32(T.w32[3], 1) ^ ROL32(T.w32[0], 2);
1198 }
1199 
1200 /* CALLED FROM GENERATED CODE */
arm64g_dirtyhelper_SHA256H2(V128 * res,ULong dHi,ULong dLo,ULong nHi,ULong nLo,ULong mHi,ULong mLo)1201 void arm64g_dirtyhelper_SHA256H2 ( /*OUT*/V128* res, ULong dHi, ULong dLo,
1202                                    ULong nHi, ULong nLo, ULong mHi, ULong mLo )
1203 {
1204    V128 X; X.w64[1] = nHi; X.w64[0] = nLo;
1205    V128 Y; Y.w64[1] = dHi; Y.w64[0] = dLo;
1206    V128 W; W.w64[1] = mHi; W.w64[0] = mLo;
1207    SHA256hash(&X, &Y, &W);
1208    res->w64[1] = Y.w64[1];
1209    res->w64[0] = Y.w64[0];
1210 }
1211 
1212 /* CALLED FROM GENERATED CODE */
arm64g_dirtyhelper_SHA256H(V128 * res,ULong dHi,ULong dLo,ULong nHi,ULong nLo,ULong mHi,ULong mLo)1213 void arm64g_dirtyhelper_SHA256H ( /*OUT*/V128* res, ULong dHi, ULong dLo,
1214                                   ULong nHi, ULong nLo, ULong mHi, ULong mLo )
1215 {
1216    V128 X; X.w64[1] = dHi; X.w64[0] = dLo;
1217    V128 Y; Y.w64[1] = nHi; Y.w64[0] = nLo;
1218    V128 W; W.w64[1] = mHi; W.w64[0] = mLo;
1219    SHA256hash(&X, &Y, &W);
1220    res->w64[1] = X.w64[1];
1221    res->w64[0] = X.w64[0];
1222 }
1223 
1224 /* CALLED FROM GENERATED CODE */
arm64g_dirtyhelper_SHA256SU0(V128 * res,ULong dHi,ULong dLo,ULong nHi,ULong nLo)1225 void arm64g_dirtyhelper_SHA256SU0 ( /*OUT*/V128* res, ULong dHi, ULong dLo,
1226                                     ULong nHi, ULong nLo )
1227 
1228 {
1229    res->w64[1] = res->w64[0] = 0;
1230    V128 op1; op1.w64[1] = dHi; op1.w64[0] = dLo;
1231    V128 op2; op2.w64[1] = nHi; op2.w64[0] = nLo;
1232    V128 T;
1233    T.w32[3] = op2.w32[0];
1234    T.w32[2] = op1.w32[3];
1235    T.w32[1] = op1.w32[2];
1236    T.w32[0] = op1.w32[1];
1237    UInt e;
1238    for (e = 0; e <= 3; e++) {
1239       UInt elt = T.w32[e];
1240       elt = ROR32(elt, 7) ^ ROR32(elt, 18) ^ (elt >> 3);
1241       res->w32[e] = elt + op1.w32[e];
1242    }
1243 }
1244 
1245 /* CALLED FROM GENERATED CODE */
arm64g_dirtyhelper_SHA256SU1(V128 * res,ULong dHi,ULong dLo,ULong nHi,ULong nLo,ULong mHi,ULong mLo)1246 void arm64g_dirtyhelper_SHA256SU1 ( /*OUT*/V128* res, ULong dHi, ULong dLo,
1247                                     ULong nHi, ULong nLo,
1248                                     ULong mHi, ULong mLo )
1249 {
1250    res->w64[0] = res->w64[1] = 0;
1251    V128 op1; op1.w64[1] = dHi; op1.w64[0] = dLo;
1252    V128 op2; op2.w64[1] = nHi; op2.w64[0] = nLo;
1253    V128 op3; op3.w64[1] = mHi; op3.w64[0] = mLo;
1254    V128 T0;
1255    T0.w32[3] = op3.w32[0];
1256    T0.w32[2] = op2.w32[3];
1257    T0.w32[1] = op2.w32[2];
1258    T0.w32[0] = op2.w32[1];
1259    UInt T1[2];
1260    UInt e;
1261    T1[1] = op3.w32[3];
1262    T1[0] = op3.w32[2];
1263    for (e = 0; e <= 1; e++) {
1264       UInt elt = T1[e];
1265       elt = ROR32(elt, 17) ^ ROR32(elt, 19) ^ (elt >> 10);
1266       elt = elt + op1.w32[e] + T0.w32[e];
1267       res->w32[e] = elt;
1268    }
1269    T1[1] = res->w32[1];
1270    T1[0] = res->w32[0];
1271    for (e = 2; e <= 3; e++) {
1272       UInt elt = T1[e-2];
1273       elt = ROR32(elt, 17) ^ ROR32(elt, 19) ^ (elt >> 10);
1274       elt = elt + op1.w32[e] + T0.w32[e];
1275       res->w32[e] = elt;
1276    }
1277 }
1278 
1279 
1280 /*---------------------------------------------------------------*/
1281 /*--- Flag-helpers translation-time function specialisers.    ---*/
1282 /*--- These help iropt specialise calls the above run-time    ---*/
1283 /*--- flags functions.                                        ---*/
1284 /*---------------------------------------------------------------*/
1285 
1286 /* Used by the optimiser to try specialisations.  Returns an
1287    equivalent expression, or NULL if none. */
1288 
isU64(IRExpr * e,ULong n)1289 static Bool isU64 ( IRExpr* e, ULong n )
1290 {
1291    return
1292       toBool( e->tag == Iex_Const
1293               && e->Iex.Const.con->tag == Ico_U64
1294               && e->Iex.Const.con->Ico.U64 == n );
1295 }
1296 
guest_arm64_spechelper(const HChar * function_name,IRExpr ** args,IRStmt ** precedingStmts,Int n_precedingStmts)1297 IRExpr* guest_arm64_spechelper ( const HChar* function_name,
1298                                  IRExpr** args,
1299                                  IRStmt** precedingStmts,
1300                                  Int      n_precedingStmts )
1301 {
1302 #  define unop(_op,_a1) IRExpr_Unop((_op),(_a1))
1303 #  define binop(_op,_a1,_a2) IRExpr_Binop((_op),(_a1),(_a2))
1304 #  define mkU64(_n) IRExpr_Const(IRConst_U64(_n))
1305 #  define mkU8(_n)  IRExpr_Const(IRConst_U8(_n))
1306 
1307    Int i, arity = 0;
1308    for (i = 0; args[i]; i++)
1309       arity++;
1310 //ZZ #  if 0
1311 //ZZ    vex_printf("spec request:\n");
1312 //ZZ    vex_printf("   %s  ", function_name);
1313 //ZZ    for (i = 0; i < arity; i++) {
1314 //ZZ       vex_printf("  ");
1315 //ZZ       ppIRExpr(args[i]);
1316 //ZZ    }
1317 //ZZ    vex_printf("\n");
1318 //ZZ #  endif
1319 
1320    /* --------- specialising "arm64g_calculate_condition" --------- */
1321 
1322    if (vex_streq(function_name, "arm64g_calculate_condition")) {
1323 
1324       /* specialise calls to the "arm64g_calculate_condition" function.
1325          Not sure whether this is strictly necessary, but: the
1326          replacement IR must produce only the values 0 or 1.  Bits
1327          63:1 are required to be zero. */
1328       IRExpr *cond_n_op, *cc_dep1, *cc_dep2  ; //, *cc_ndep;
1329       vassert(arity == 4);
1330       cond_n_op = args[0]; /* (ARM64Condcode << 4)  |  ARM64G_CC_OP_* */
1331       cc_dep1   = args[1];
1332       cc_dep2   = args[2];
1333       //cc_ndep   = args[3];
1334 
1335       /*---------------- SUB64 ----------------*/
1336 
1337       /* 0, 1 */
1338       if (isU64(cond_n_op, (ARM64CondEQ << 4) | ARM64G_CC_OP_SUB64)) {
1339          /* EQ after SUB --> test argL == argR */
1340          return unop(Iop_1Uto64,
1341                      binop(Iop_CmpEQ64, cc_dep1, cc_dep2));
1342       }
1343       if (isU64(cond_n_op, (ARM64CondNE << 4) | ARM64G_CC_OP_SUB64)) {
1344          /* NE after SUB --> test argL != argR */
1345          return unop(Iop_1Uto64,
1346                      binop(Iop_CmpNE64, cc_dep1, cc_dep2));
1347       }
1348 
1349       /* 2, 3 */
1350       if (isU64(cond_n_op, (ARM64CondCS << 4) | ARM64G_CC_OP_SUB64)) {
1351          /* CS after SUB --> test argL >=u argR
1352                          --> test argR <=u argL */
1353          return unop(Iop_1Uto64,
1354                      binop(Iop_CmpLE64U, cc_dep2, cc_dep1));
1355       }
1356       if (isU64(cond_n_op, (ARM64CondCC << 4) | ARM64G_CC_OP_SUB64)) {
1357          /* CC after SUB --> test argL <u argR */
1358          return unop(Iop_1Uto64,
1359                      binop(Iop_CmpLT64U, cc_dep1, cc_dep2));
1360       }
1361 
1362       /* 8, 9 */
1363       if (isU64(cond_n_op, (ARM64CondLS << 4) | ARM64G_CC_OP_SUB64)) {
1364          /* LS after SUB --> test argL <=u argR */
1365          return unop(Iop_1Uto64,
1366                      binop(Iop_CmpLE64U, cc_dep1, cc_dep2));
1367       }
1368       if (isU64(cond_n_op, (ARM64CondHI << 4) | ARM64G_CC_OP_SUB64)) {
1369          /* HI after SUB --> test argL >u argR
1370                          --> test argR <u argL */
1371          return unop(Iop_1Uto64,
1372                      binop(Iop_CmpLT64U, cc_dep2, cc_dep1));
1373       }
1374 
1375       /* 10, 11 */
1376       if (isU64(cond_n_op, (ARM64CondLT << 4) | ARM64G_CC_OP_SUB64)) {
1377          /* LT after SUB --> test argL <s argR */
1378          return unop(Iop_1Uto64,
1379                      binop(Iop_CmpLT64S, cc_dep1, cc_dep2));
1380       }
1381       if (isU64(cond_n_op, (ARM64CondGE << 4) | ARM64G_CC_OP_SUB64)) {
1382          /* GE after SUB --> test argL >=s argR
1383                          --> test argR <=s argL */
1384          return unop(Iop_1Uto64,
1385                      binop(Iop_CmpLE64S, cc_dep2, cc_dep1));
1386       }
1387 
1388       /* 12, 13 */
1389       if (isU64(cond_n_op, (ARM64CondGT << 4) | ARM64G_CC_OP_SUB64)) {
1390          /* GT after SUB --> test argL >s argR
1391                          --> test argR <s argL */
1392          return unop(Iop_1Uto64,
1393                      binop(Iop_CmpLT64S, cc_dep2, cc_dep1));
1394       }
1395       if (isU64(cond_n_op, (ARM64CondLE << 4) | ARM64G_CC_OP_SUB64)) {
1396          /* LE after SUB --> test argL <=s argR */
1397          return unop(Iop_1Uto64,
1398                      binop(Iop_CmpLE64S, cc_dep1, cc_dep2));
1399       }
1400 
1401       /*---------------- SUB32 ----------------*/
1402 
1403       /* 0, 1 */
1404       if (isU64(cond_n_op, (ARM64CondEQ << 4) | ARM64G_CC_OP_SUB32)) {
1405          /* EQ after SUB --> test argL == argR */
1406          return unop(Iop_1Uto64,
1407                      binop(Iop_CmpEQ32, unop(Iop_64to32, cc_dep1),
1408                                         unop(Iop_64to32, cc_dep2)));
1409       }
1410       if (isU64(cond_n_op, (ARM64CondNE << 4) | ARM64G_CC_OP_SUB32)) {
1411          /* NE after SUB --> test argL != argR */
1412          return unop(Iop_1Uto64,
1413                      binop(Iop_CmpNE32, unop(Iop_64to32, cc_dep1),
1414                                         unop(Iop_64to32, cc_dep2)));
1415       }
1416 
1417       /* 2, 3 */
1418       if (isU64(cond_n_op, (ARM64CondCS << 4) | ARM64G_CC_OP_SUB32)) {
1419          /* CS after SUB --> test argL >=u argR
1420                          --> test argR <=u argL */
1421          return unop(Iop_1Uto64,
1422                      binop(Iop_CmpLE32U, unop(Iop_64to32, cc_dep2),
1423                                          unop(Iop_64to32, cc_dep1)));
1424       }
1425       if (isU64(cond_n_op, (ARM64CondCC << 4) | ARM64G_CC_OP_SUB32)) {
1426          /* CC after SUB --> test argL <u argR */
1427          return unop(Iop_1Uto64,
1428                      binop(Iop_CmpLT32U, unop(Iop_64to32, cc_dep1),
1429                                          unop(Iop_64to32, cc_dep2)));
1430       }
1431 
1432       /* 8, 9 */
1433       if (isU64(cond_n_op, (ARM64CondLS << 4) | ARM64G_CC_OP_SUB32)) {
1434          /* LS after SUB --> test argL <=u argR */
1435          return unop(Iop_1Uto64,
1436                      binop(Iop_CmpLE32U, unop(Iop_64to32, cc_dep1),
1437                                          unop(Iop_64to32, cc_dep2)));
1438       }
1439       if (isU64(cond_n_op, (ARM64CondHI << 4) | ARM64G_CC_OP_SUB32)) {
1440          /* HI after SUB --> test argL >u argR
1441                          --> test argR <u argL */
1442          return unop(Iop_1Uto64,
1443                      binop(Iop_CmpLT32U, unop(Iop_64to32, cc_dep2),
1444                                          unop(Iop_64to32, cc_dep1)));
1445       }
1446 
1447       /* 10, 11 */
1448       if (isU64(cond_n_op, (ARM64CondLT << 4) | ARM64G_CC_OP_SUB32)) {
1449          /* LT after SUB --> test argL <s argR */
1450          return unop(Iop_1Uto64,
1451                      binop(Iop_CmpLT32S, unop(Iop_64to32, cc_dep1),
1452                                          unop(Iop_64to32, cc_dep2)));
1453       }
1454       if (isU64(cond_n_op, (ARM64CondGE << 4) | ARM64G_CC_OP_SUB32)) {
1455          /* GE after SUB --> test argL >=s argR
1456                          --> test argR <=s argL */
1457          return unop(Iop_1Uto64,
1458                      binop(Iop_CmpLE32S, unop(Iop_64to32, cc_dep2),
1459                                          unop(Iop_64to32, cc_dep1)));
1460       }
1461 
1462       /* 12, 13 */
1463       if (isU64(cond_n_op, (ARM64CondGT << 4) | ARM64G_CC_OP_SUB32)) {
1464          /* GT after SUB --> test argL >s argR
1465                          --> test argR <s argL */
1466          return unop(Iop_1Uto64,
1467                      binop(Iop_CmpLT32S, unop(Iop_64to32, cc_dep2),
1468                                          unop(Iop_64to32, cc_dep1)));
1469       }
1470       if (isU64(cond_n_op, (ARM64CondLE << 4) | ARM64G_CC_OP_SUB32)) {
1471          /* LE after SUB --> test argL <=s argR */
1472          return unop(Iop_1Uto64,
1473                      binop(Iop_CmpLE32S, unop(Iop_64to32, cc_dep1),
1474                                          unop(Iop_64to32, cc_dep2)));
1475       }
1476 
1477 //ZZ       /*---------------- SBB ----------------*/
1478 //ZZ
1479 //ZZ       if (isU32(cond_n_op, (ARMCondHS << 4) | ARMG_CC_OP_SBB)) {
1480 //ZZ          /* This seems to happen a lot in softfloat code, eg __divdf3+140 */
1481 //ZZ          /* thunk is: (dep1=argL, dep2=argR, ndep=oldC) */
1482 //ZZ          /* HS after SBB (same as C after SBB below)
1483 //ZZ             --> oldC ? (argL >=u argR) : (argL >u argR)
1484 //ZZ             --> oldC ? (argR <=u argL) : (argR <u argL)
1485 //ZZ          */
1486 //ZZ          return
1487 //ZZ             IRExpr_ITE(
1488 //ZZ                binop(Iop_CmpNE32, cc_ndep, mkU32(0)),
1489 //ZZ                /* case oldC != 0 */
1490 //ZZ                unop(Iop_1Uto32, binop(Iop_CmpLE32U, cc_dep2, cc_dep1)),
1491 //ZZ                /* case oldC == 0 */
1492 //ZZ                unop(Iop_1Uto32, binop(Iop_CmpLT32U, cc_dep2, cc_dep1))
1493 //ZZ             );
1494 //ZZ       }
1495 //ZZ
1496 //ZZ       /*---------------- LOGIC ----------------*/
1497 //ZZ
1498 //ZZ       if (isU32(cond_n_op, (ARMCondEQ << 4) | ARMG_CC_OP_LOGIC)) {
1499 //ZZ          /* EQ after LOGIC --> test res == 0 */
1500 //ZZ          return unop(Iop_1Uto32,
1501 //ZZ                      binop(Iop_CmpEQ32, cc_dep1, mkU32(0)));
1502 //ZZ       }
1503 //ZZ       if (isU32(cond_n_op, (ARMCondNE << 4) | ARMG_CC_OP_LOGIC)) {
1504 //ZZ          /* NE after LOGIC --> test res != 0 */
1505 //ZZ          return unop(Iop_1Uto32,
1506 //ZZ                      binop(Iop_CmpNE32, cc_dep1, mkU32(0)));
1507 //ZZ       }
1508 //ZZ
1509 //ZZ       if (isU32(cond_n_op, (ARMCondPL << 4) | ARMG_CC_OP_LOGIC)) {
1510 //ZZ          /* PL after LOGIC --> test (res >> 31) == 0 */
1511 //ZZ          return unop(Iop_1Uto32,
1512 //ZZ                      binop(Iop_CmpEQ32,
1513 //ZZ                            binop(Iop_Shr32, cc_dep1, mkU8(31)),
1514 //ZZ                            mkU32(0)));
1515 //ZZ       }
1516 //ZZ       if (isU32(cond_n_op, (ARMCondMI << 4) | ARMG_CC_OP_LOGIC)) {
1517 //ZZ          /* MI after LOGIC --> test (res >> 31) == 1 */
1518 //ZZ          return unop(Iop_1Uto32,
1519 //ZZ                      binop(Iop_CmpEQ32,
1520 //ZZ                            binop(Iop_Shr32, cc_dep1, mkU8(31)),
1521 //ZZ                            mkU32(1)));
1522 //ZZ       }
1523 
1524       /*---------------- COPY ----------------*/
1525 
1526       if (isU64(cond_n_op, (ARM64CondEQ << 4) | ARM64G_CC_OP_COPY)) {
1527          /* EQ after COPY --> (cc_dep1 >> ARM64G_CC_SHIFT_Z) & 1 */
1528          return binop(Iop_And64,
1529                       binop(Iop_Shr64, cc_dep1,
1530                                        mkU8(ARM64G_CC_SHIFT_Z)),
1531                       mkU64(1));
1532       }
1533       if (isU64(cond_n_op, (ARM64CondNE << 4) | ARM64G_CC_OP_COPY)) {
1534          /* NE after COPY --> ((cc_dep1 >> ARM64G_CC_SHIFT_Z) ^ 1) & 1 */
1535          return binop(Iop_And64,
1536                       binop(Iop_Xor64,
1537                             binop(Iop_Shr64, cc_dep1,
1538                                              mkU8(ARM64G_CC_SHIFT_Z)),
1539                             mkU64(1)),
1540                       mkU64(1));
1541       }
1542 
1543 //ZZ       /*----------------- AL -----------------*/
1544 //ZZ
1545 //ZZ       /* A critically important case for Thumb code.
1546 //ZZ
1547 //ZZ          What we're trying to spot is the case where cond_n_op is an
1548 //ZZ          expression of the form Or32(..., 0xE0) since that means the
1549 //ZZ          caller is asking for CondAL and we can simply return 1
1550 //ZZ          without caring what the ... part is.  This is a potentially
1551 //ZZ          dodgy kludge in that it assumes that the ... part has zeroes
1552 //ZZ          in bits 7:4, so that the result of the Or32 is guaranteed to
1553 //ZZ          be 0xE in bits 7:4.  Given that the places where this first
1554 //ZZ          arg are constructed (in guest_arm_toIR.c) are very
1555 //ZZ          constrained, we can get away with this.  To make this
1556 //ZZ          guaranteed safe would require to have a new primop, Slice44
1557 //ZZ          or some such, thusly
1558 //ZZ
1559 //ZZ          Slice44(arg1, arg2) = 0--(24)--0 arg1[7:4] arg2[3:0]
1560 //ZZ
1561 //ZZ          and we would then look for Slice44(0xE0, ...)
1562 //ZZ          which would give the required safety property.
1563 //ZZ
1564 //ZZ          It would be infeasibly expensive to scan backwards through
1565 //ZZ          the entire block looking for an assignment to the temp, so
1566 //ZZ          just look at the previous 16 statements.  That should find it
1567 //ZZ          if it is an interesting case, as a result of how the
1568 //ZZ          boilerplate guff at the start of each Thumb insn translation
1569 //ZZ          is made.
1570 //ZZ       */
1571 //ZZ       if (cond_n_op->tag == Iex_RdTmp) {
1572 //ZZ          Int    j;
1573 //ZZ          IRTemp look_for = cond_n_op->Iex.RdTmp.tmp;
1574 //ZZ          Int    limit    = n_precedingStmts - 16;
1575 //ZZ          if (limit < 0) limit = 0;
1576 //ZZ          if (0) vex_printf("scanning %d .. %d\n", n_precedingStmts-1, limit);
1577 //ZZ          for (j = n_precedingStmts - 1; j >= limit; j--) {
1578 //ZZ             IRStmt* st = precedingStmts[j];
1579 //ZZ             if (st->tag == Ist_WrTmp
1580 //ZZ                 && st->Ist.WrTmp.tmp == look_for
1581 //ZZ                 && st->Ist.WrTmp.data->tag == Iex_Binop
1582 //ZZ                 && st->Ist.WrTmp.data->Iex.Binop.op == Iop_Or32
1583 //ZZ                 && isU32(st->Ist.WrTmp.data->Iex.Binop.arg2, (ARMCondAL << 4)))
1584 //ZZ                return mkU32(1);
1585 //ZZ          }
1586 //ZZ          /* Didn't find any useful binding to the first arg
1587 //ZZ             in the previous 16 stmts. */
1588 //ZZ       }
1589    }
1590 
1591 //ZZ    /* --------- specialising "armg_calculate_flag_c" --------- */
1592 //ZZ
1593 //ZZ    else
1594 //ZZ    if (vex_streq(function_name, "armg_calculate_flag_c")) {
1595 //ZZ
1596 //ZZ       /* specialise calls to the "armg_calculate_flag_c" function.
1597 //ZZ          Note that the returned value must be either 0 or 1; nonzero
1598 //ZZ          bits 31:1 are not allowed.  In turn, incoming oldV and oldC
1599 //ZZ          values (from the thunk) are assumed to have bits 31:1
1600 //ZZ          clear. */
1601 //ZZ       IRExpr *cc_op, *cc_dep1, *cc_dep2, *cc_ndep;
1602 //ZZ       vassert(arity == 4);
1603 //ZZ       cc_op   = args[0]; /* ARMG_CC_OP_* */
1604 //ZZ       cc_dep1 = args[1];
1605 //ZZ       cc_dep2 = args[2];
1606 //ZZ       cc_ndep = args[3];
1607 //ZZ
1608 //ZZ       if (isU32(cc_op, ARMG_CC_OP_LOGIC)) {
1609 //ZZ          /* Thunk args are (result, shco, oldV) */
1610 //ZZ          /* C after LOGIC --> shco */
1611 //ZZ          return cc_dep2;
1612 //ZZ       }
1613 //ZZ
1614 //ZZ       if (isU32(cc_op, ARMG_CC_OP_SUB)) {
1615 //ZZ          /* Thunk args are (argL, argR, unused) */
1616 //ZZ          /* C after SUB --> argL >=u argR
1617 //ZZ                         --> argR <=u argL */
1618 //ZZ          return unop(Iop_1Uto32,
1619 //ZZ                      binop(Iop_CmpLE32U, cc_dep2, cc_dep1));
1620 //ZZ       }
1621 //ZZ
1622 //ZZ       if (isU32(cc_op, ARMG_CC_OP_SBB)) {
1623 //ZZ          /* This happens occasionally in softfloat code, eg __divdf3+140 */
1624 //ZZ          /* thunk is: (dep1=argL, dep2=argR, ndep=oldC) */
1625 //ZZ          /* C after SBB (same as HS after SBB above)
1626 //ZZ             --> oldC ? (argL >=u argR) : (argL >u argR)
1627 //ZZ             --> oldC ? (argR <=u argL) : (argR <u argL)
1628 //ZZ          */
1629 //ZZ          return
1630 //ZZ             IRExpr_ITE(
1631 //ZZ                binop(Iop_CmpNE32, cc_ndep, mkU32(0)),
1632 //ZZ                /* case oldC != 0 */
1633 //ZZ                unop(Iop_1Uto32, binop(Iop_CmpLE32U, cc_dep2, cc_dep1)),
1634 //ZZ                /* case oldC == 0 */
1635 //ZZ                unop(Iop_1Uto32, binop(Iop_CmpLT32U, cc_dep2, cc_dep1))
1636 //ZZ             );
1637 //ZZ       }
1638 //ZZ
1639 //ZZ    }
1640 //ZZ
1641 //ZZ    /* --------- specialising "armg_calculate_flag_v" --------- */
1642 //ZZ
1643 //ZZ    else
1644 //ZZ    if (vex_streq(function_name, "armg_calculate_flag_v")) {
1645 //ZZ
1646 //ZZ       /* specialise calls to the "armg_calculate_flag_v" function.
1647 //ZZ          Note that the returned value must be either 0 or 1; nonzero
1648 //ZZ          bits 31:1 are not allowed.  In turn, incoming oldV and oldC
1649 //ZZ          values (from the thunk) are assumed to have bits 31:1
1650 //ZZ          clear. */
1651 //ZZ       IRExpr *cc_op, *cc_dep1, *cc_dep2, *cc_ndep;
1652 //ZZ       vassert(arity == 4);
1653 //ZZ       cc_op   = args[0]; /* ARMG_CC_OP_* */
1654 //ZZ       cc_dep1 = args[1];
1655 //ZZ       cc_dep2 = args[2];
1656 //ZZ       cc_ndep = args[3];
1657 //ZZ
1658 //ZZ       if (isU32(cc_op, ARMG_CC_OP_LOGIC)) {
1659 //ZZ          /* Thunk args are (result, shco, oldV) */
1660 //ZZ          /* V after LOGIC --> oldV */
1661 //ZZ          return cc_ndep;
1662 //ZZ       }
1663 //ZZ
1664 //ZZ       if (isU32(cc_op, ARMG_CC_OP_SUB)) {
1665 //ZZ          /* Thunk args are (argL, argR, unused) */
1666 //ZZ          /* V after SUB
1667 //ZZ             --> let res = argL - argR
1668 //ZZ                 in ((argL ^ argR) & (argL ^ res)) >> 31
1669 //ZZ             --> ((argL ^ argR) & (argL ^ (argL - argR))) >> 31
1670 //ZZ          */
1671 //ZZ          IRExpr* argL = cc_dep1;
1672 //ZZ          IRExpr* argR = cc_dep2;
1673 //ZZ          return
1674 //ZZ             binop(Iop_Shr32,
1675 //ZZ                   binop(Iop_And32,
1676 //ZZ                         binop(Iop_Xor32, argL, argR),
1677 //ZZ                         binop(Iop_Xor32, argL, binop(Iop_Sub32, argL, argR))
1678 //ZZ                   ),
1679 //ZZ                   mkU8(31)
1680 //ZZ             );
1681 //ZZ       }
1682 //ZZ
1683 //ZZ       if (isU32(cc_op, ARMG_CC_OP_SBB)) {
1684 //ZZ          /* This happens occasionally in softfloat code, eg __divdf3+140 */
1685 //ZZ          /* thunk is: (dep1=argL, dep2=argR, ndep=oldC) */
1686 //ZZ          /* V after SBB
1687 //ZZ             --> let res = argL - argR - (oldC ^ 1)
1688 //ZZ                 in  (argL ^ argR) & (argL ^ res) & 1
1689 //ZZ          */
1690 //ZZ          return
1691 //ZZ             binop(
1692 //ZZ                Iop_And32,
1693 //ZZ                binop(
1694 //ZZ                   Iop_And32,
1695 //ZZ                   // argL ^ argR
1696 //ZZ                   binop(Iop_Xor32, cc_dep1, cc_dep2),
1697 //ZZ                   // argL ^ (argL - argR - (oldC ^ 1))
1698 //ZZ                   binop(Iop_Xor32,
1699 //ZZ                         cc_dep1,
1700 //ZZ                         binop(Iop_Sub32,
1701 //ZZ                               binop(Iop_Sub32, cc_dep1, cc_dep2),
1702 //ZZ                               binop(Iop_Xor32, cc_ndep, mkU32(1)))
1703 //ZZ                   )
1704 //ZZ                ),
1705 //ZZ                mkU32(1)
1706 //ZZ             );
1707 //ZZ       }
1708 //ZZ
1709 //ZZ    }
1710 
1711 #  undef unop
1712 #  undef binop
1713 #  undef mkU64
1714 #  undef mkU8
1715 
1716    return NULL;
1717 }
1718 
1719 
1720 /*----------------------------------------------*/
1721 /*--- The exported fns ..                    ---*/
1722 /*----------------------------------------------*/
1723 
1724 //ZZ /* VISIBLE TO LIBVEX CLIENT */
1725 //ZZ #if 0
1726 //ZZ void LibVEX_GuestARM_put_flags ( UInt flags_native,
1727 //ZZ                                  /*OUT*/VexGuestARMState* vex_state )
1728 //ZZ {
1729 //ZZ    vassert(0); // FIXME
1730 //ZZ
1731 //ZZ    /* Mask out everything except N Z V C. */
1732 //ZZ    flags_native
1733 //ZZ       &= (ARMG_CC_MASK_N | ARMG_CC_MASK_Z | ARMG_CC_MASK_V | ARMG_CC_MASK_C);
1734 //ZZ
1735 //ZZ    vex_state->guest_CC_OP   = ARMG_CC_OP_COPY;
1736 //ZZ    vex_state->guest_CC_DEP1 = flags_native;
1737 //ZZ    vex_state->guest_CC_DEP2 = 0;
1738 //ZZ    vex_state->guest_CC_NDEP = 0;
1739 //ZZ }
1740 //ZZ #endif
1741 
1742 /* VISIBLE TO LIBVEX CLIENT */
LibVEX_GuestARM64_get_nzcv(const VexGuestARM64State * vex_state)1743 ULong LibVEX_GuestARM64_get_nzcv ( /*IN*/const VexGuestARM64State* vex_state )
1744 {
1745    ULong nzcv = 0;
1746    // NZCV
1747    nzcv |= arm64g_calculate_flags_nzcv(
1748                vex_state->guest_CC_OP,
1749                vex_state->guest_CC_DEP1,
1750                vex_state->guest_CC_DEP2,
1751                vex_state->guest_CC_NDEP
1752             );
1753    vassert(0 == (nzcv & 0xFFFFFFFF0FFFFFFFULL));
1754 //ZZ    // Q
1755 //ZZ    if (vex_state->guest_QFLAG32 > 0)
1756 //ZZ       cpsr |= (1 << 27);
1757 //ZZ    // GE
1758 //ZZ    if (vex_state->guest_GEFLAG0 > 0)
1759 //ZZ       cpsr |= (1 << 16);
1760 //ZZ    if (vex_state->guest_GEFLAG1 > 0)
1761 //ZZ       cpsr |= (1 << 17);
1762 //ZZ    if (vex_state->guest_GEFLAG2 > 0)
1763 //ZZ       cpsr |= (1 << 18);
1764 //ZZ    if (vex_state->guest_GEFLAG3 > 0)
1765 //ZZ       cpsr |= (1 << 19);
1766 //ZZ    // M
1767 //ZZ    cpsr |= (1 << 4); // 0b10000 means user-mode
1768 //ZZ    // J,T   J (bit 24) is zero by initialisation above
1769 //ZZ    // T  we copy from R15T[0]
1770 //ZZ    if (vex_state->guest_R15T & 1)
1771 //ZZ       cpsr |= (1 << 5);
1772 //ZZ    // ITSTATE we punt on for the time being.  Could compute it
1773 //ZZ    // if needed though.
1774 //ZZ    // E, endianness, 0 (littleendian) from initialisation above
1775 //ZZ    // A,I,F disable some async exceptions.  Not sure about these.
1776 //ZZ    // Leave as zero for the time being.
1777    return nzcv;
1778 }
1779 
1780 /* VISIBLE TO LIBVEX CLIENT */
LibVEX_GuestARM64_get_fpsr(const VexGuestARM64State * vex_state)1781 ULong LibVEX_GuestARM64_get_fpsr ( const VexGuestARM64State* vex_state )
1782 {
1783    UInt w32 = vex_state->guest_QCFLAG[0] | vex_state->guest_QCFLAG[1]
1784               | vex_state->guest_QCFLAG[2] | vex_state->guest_QCFLAG[3];
1785    ULong fpsr = 0;
1786    // QC
1787    if (w32 != 0)
1788       fpsr |= (1 << 27);
1789    return fpsr;
1790 }
1791 
LibVEX_GuestARM64_set_fpsr(VexGuestARM64State * vex_state,ULong fpsr)1792 void LibVEX_GuestARM64_set_fpsr ( /*MOD*/VexGuestARM64State* vex_state,
1793                                   ULong fpsr )
1794 {
1795    // QC
1796    vex_state->guest_QCFLAG[0] = (UInt)((fpsr >> 27) & 1);
1797    vex_state->guest_QCFLAG[1] = 0;
1798    vex_state->guest_QCFLAG[2] = 0;
1799    vex_state->guest_QCFLAG[3] = 0;
1800 }
1801 
1802 /* VISIBLE TO LIBVEX CLIENT */
LibVEX_GuestARM64_initialise(VexGuestARM64State * vex_state)1803 void LibVEX_GuestARM64_initialise ( /*OUT*/VexGuestARM64State* vex_state )
1804 {
1805    vex_bzero(vex_state, sizeof(*vex_state));
1806 //ZZ    vex_state->host_EvC_FAILADDR = 0;
1807 //ZZ    vex_state->host_EvC_COUNTER = 0;
1808 //ZZ
1809 //ZZ    vex_state->guest_R0  = 0;
1810 //ZZ    vex_state->guest_R1  = 0;
1811 //ZZ    vex_state->guest_R2  = 0;
1812 //ZZ    vex_state->guest_R3  = 0;
1813 //ZZ    vex_state->guest_R4  = 0;
1814 //ZZ    vex_state->guest_R5  = 0;
1815 //ZZ    vex_state->guest_R6  = 0;
1816 //ZZ    vex_state->guest_R7  = 0;
1817 //ZZ    vex_state->guest_R8  = 0;
1818 //ZZ    vex_state->guest_R9  = 0;
1819 //ZZ    vex_state->guest_R10 = 0;
1820 //ZZ    vex_state->guest_R11 = 0;
1821 //ZZ    vex_state->guest_R12 = 0;
1822 //ZZ    vex_state->guest_R13 = 0;
1823 //ZZ    vex_state->guest_R14 = 0;
1824 //ZZ    vex_state->guest_R15T = 0;  /* NB: implies ARM mode */
1825 //ZZ
1826    vex_state->guest_CC_OP   = ARM64G_CC_OP_COPY;
1827 //ZZ    vex_state->guest_CC_DEP1 = 0;
1828 //ZZ    vex_state->guest_CC_DEP2 = 0;
1829 //ZZ    vex_state->guest_CC_NDEP = 0;
1830 //ZZ    vex_state->guest_QFLAG32 = 0;
1831 //ZZ    vex_state->guest_GEFLAG0 = 0;
1832 //ZZ    vex_state->guest_GEFLAG1 = 0;
1833 //ZZ    vex_state->guest_GEFLAG2 = 0;
1834 //ZZ    vex_state->guest_GEFLAG3 = 0;
1835 //ZZ
1836 //ZZ    vex_state->guest_EMNOTE  = EmNote_NONE;
1837 //ZZ    vex_state->guest_CMSTART = 0;
1838 //ZZ    vex_state->guest_CMLEN   = 0;
1839 //ZZ    vex_state->guest_NRADDR  = 0;
1840 //ZZ    vex_state->guest_IP_AT_SYSCALL = 0;
1841 //ZZ
1842 //ZZ    vex_state->guest_D0  = 0;
1843 //ZZ    vex_state->guest_D1  = 0;
1844 //ZZ    vex_state->guest_D2  = 0;
1845 //ZZ    vex_state->guest_D3  = 0;
1846 //ZZ    vex_state->guest_D4  = 0;
1847 //ZZ    vex_state->guest_D5  = 0;
1848 //ZZ    vex_state->guest_D6  = 0;
1849 //ZZ    vex_state->guest_D7  = 0;
1850 //ZZ    vex_state->guest_D8  = 0;
1851 //ZZ    vex_state->guest_D9  = 0;
1852 //ZZ    vex_state->guest_D10 = 0;
1853 //ZZ    vex_state->guest_D11 = 0;
1854 //ZZ    vex_state->guest_D12 = 0;
1855 //ZZ    vex_state->guest_D13 = 0;
1856 //ZZ    vex_state->guest_D14 = 0;
1857 //ZZ    vex_state->guest_D15 = 0;
1858 //ZZ    vex_state->guest_D16 = 0;
1859 //ZZ    vex_state->guest_D17 = 0;
1860 //ZZ    vex_state->guest_D18 = 0;
1861 //ZZ    vex_state->guest_D19 = 0;
1862 //ZZ    vex_state->guest_D20 = 0;
1863 //ZZ    vex_state->guest_D21 = 0;
1864 //ZZ    vex_state->guest_D22 = 0;
1865 //ZZ    vex_state->guest_D23 = 0;
1866 //ZZ    vex_state->guest_D24 = 0;
1867 //ZZ    vex_state->guest_D25 = 0;
1868 //ZZ    vex_state->guest_D26 = 0;
1869 //ZZ    vex_state->guest_D27 = 0;
1870 //ZZ    vex_state->guest_D28 = 0;
1871 //ZZ    vex_state->guest_D29 = 0;
1872 //ZZ    vex_state->guest_D30 = 0;
1873 //ZZ    vex_state->guest_D31 = 0;
1874 //ZZ
1875 //ZZ    /* ARM encoded; zero is the default as it happens (result flags
1876 //ZZ       (NZCV) cleared, FZ disabled, round to nearest, non-vector mode,
1877 //ZZ       all exns masked, all exn sticky bits cleared). */
1878 //ZZ    vex_state->guest_FPSCR = 0;
1879 //ZZ
1880 //ZZ    vex_state->guest_TPIDRURO = 0;
1881 //ZZ
1882 //ZZ    /* Not in a Thumb IT block. */
1883 //ZZ    vex_state->guest_ITSTATE = 0;
1884 //ZZ
1885 //ZZ    vex_state->padding1 = 0;
1886 //ZZ    vex_state->padding2 = 0;
1887 //ZZ    vex_state->padding3 = 0;
1888 //ZZ    vex_state->padding4 = 0;
1889 //ZZ    vex_state->padding5 = 0;
1890 }
1891 
1892 
1893 /*-----------------------------------------------------------*/
1894 /*--- Describing the arm guest state, for the benefit     ---*/
1895 /*--- of iropt and instrumenters.                         ---*/
1896 /*-----------------------------------------------------------*/
1897 
1898 /* Figure out if any part of the guest state contained in minoff
1899    .. maxoff requires precise memory exceptions.  If in doubt return
1900    True (but this generates significantly slower code).
1901 
1902    We enforce precise exns for guest SP, PC, 29(FP), 30(LR).
1903    That might be overkill (for 29 and 30); I don't know.
1904 */
guest_arm64_state_requires_precise_mem_exns(Int minoff,Int maxoff,VexRegisterUpdates pxControl)1905 Bool guest_arm64_state_requires_precise_mem_exns (
1906         Int minoff, Int maxoff, VexRegisterUpdates pxControl
1907      )
1908 {
1909    Int xsp_min = offsetof(VexGuestARM64State, guest_XSP);
1910    Int xsp_max = xsp_min + 8 - 1;
1911    Int pc_min  = offsetof(VexGuestARM64State, guest_PC);
1912    Int pc_max  = pc_min + 8 - 1;
1913 
1914    if (maxoff < xsp_min || minoff > xsp_max) {
1915       /* no overlap with xsp */
1916       if (pxControl == VexRegUpdSpAtMemAccess)
1917          return False; // We only need to check stack pointer.
1918    } else {
1919       return True;
1920    }
1921 
1922    if (maxoff < pc_min || minoff > pc_max) {
1923       /* no overlap with pc */
1924    } else {
1925       return True;
1926    }
1927 
1928    /* Guessing that we need PX for FP, but I don't really know. */
1929    Int x29_min = offsetof(VexGuestARM64State, guest_X29);
1930    Int x29_max = x29_min + 8 - 1;
1931 
1932    if (maxoff < x29_min || minoff > x29_max) {
1933       /* no overlap with x29 */
1934    } else {
1935       return True;
1936    }
1937 
1938    /* Guessing that we need PX for LR, but I don't really know. */
1939    Int x30_min = offsetof(VexGuestARM64State, guest_X30);
1940    Int x30_max = x30_min + 8 - 1;
1941 
1942    if (maxoff < x30_min || minoff > x30_max) {
1943       /* no overlap with r30 */
1944    } else {
1945       return True;
1946    }
1947 
1948    return False;
1949 }
1950 
1951 
1952 #define ALWAYSDEFD(field)                             \
1953     { offsetof(VexGuestARM64State, field),            \
1954       (sizeof ((VexGuestARM64State*)0)->field) }
1955 VexGuestLayout
1956    arm64Guest_layout
1957       = {
1958           /* Total size of the guest state, in bytes. */
1959           .total_sizeB = sizeof(VexGuestARM64State),
1960 
1961           /* Describe the stack pointer. */
1962           .offset_SP = offsetof(VexGuestARM64State,guest_XSP),
1963           .sizeof_SP = 8,
1964 
1965           /* Describe the instruction pointer. */
1966           .offset_IP = offsetof(VexGuestARM64State,guest_PC),
1967           .sizeof_IP = 8,
1968 
1969           /* Describe any sections to be regarded by Memcheck as
1970              'always-defined'. */
1971           .n_alwaysDefd = 9,
1972 
1973           /* flags thunk: OP is always defd, whereas DEP1 and DEP2
1974              have to be tracked.  See detailed comment in gdefs.h on
1975              meaning of thunk fields. */
1976           .alwaysDefd
1977              = { /* 0 */ ALWAYSDEFD(guest_PC),
1978                  /* 1 */ ALWAYSDEFD(guest_CC_OP),
1979                  /* 2 */ ALWAYSDEFD(guest_CC_NDEP),
1980                  /* 3 */ ALWAYSDEFD(guest_EMNOTE),
1981                  /* 4 */ ALWAYSDEFD(guest_CMSTART),
1982                  /* 5 */ ALWAYSDEFD(guest_CMLEN),
1983                  /* 6 */ ALWAYSDEFD(guest_NRADDR),
1984                  /* 7 */ ALWAYSDEFD(guest_IP_AT_SYSCALL),
1985                  /* 8 */ ALWAYSDEFD(guest_TPIDR_EL0)
1986                }
1987         };
1988 
1989 
1990 /*---------------------------------------------------------------*/
1991 /*--- end                               guest_arm64_helpers.c ---*/
1992 /*---------------------------------------------------------------*/
1993