1
2/*---------------------------------------------------------------*/
3/*--- begin                               guest_arm_helpers.c ---*/
4/*---------------------------------------------------------------*/
5
6/*
7   This file is part of Valgrind, a dynamic binary instrumentation
8   framework.
9
10   Copyright (C) 2004-2013 OpenWorks LLP
11      info@open-works.net
12
13   This program is free software; you can redistribute it and/or
14   modify it under the terms of the GNU General Public License as
15   published by the Free Software Foundation; either version 2 of the
16   License, or (at your option) any later version.
17
18   This program is distributed in the hope that it will be useful, but
19   WITHOUT ANY WARRANTY; without even the implied warranty of
20   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21   General Public License for more details.
22
23   You should have received a copy of the GNU General Public License
24   along with this program; if not, write to the Free Software
25   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
26   02110-1301, USA.
27
28   The GNU General Public License is contained in the file COPYING.
29*/
30
31#include "libvex_basictypes.h"
32#include "libvex_emnote.h"
33#include "libvex_guest_arm.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_arm_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-arm/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
61static UInt tab_n_eval[ARMG_CC_OP_NUMBER];
62static UInt tab_z_eval[ARMG_CC_OP_NUMBER];
63static UInt tab_c_eval[ARMG_CC_OP_NUMBER];
64static UInt tab_v_eval[ARMG_CC_OP_NUMBER];
65static UInt initted = 0;
66static UInt tot_evals = 0;
67
68static void initCounts ( void )
69{
70   UInt i;
71   for (i = 0; i < ARMG_CC_OP_NUMBER; i++) {
72      tab_n_eval[i] = tab_z_eval[i] = tab_c_eval[i] = tab_v_eval[i] = 0;
73   }
74   initted = 1;
75}
76
77static void showCounts ( void )
78{
79   UInt i;
80   vex_printf("\n                 N          Z          C          V\n");
81   vex_printf(  "---------------------------------------------------\n");
82   for (i = 0; i < ARMG_CC_OP_NUMBER; i++) {
83      vex_printf("CC_OP=%d  %9d  %9d  %9d  %9d\n",
84                 i,
85                 tab_n_eval[i], tab_z_eval[i],
86                 tab_c_eval[i], tab_v_eval[i] );
87    }
88}
89
90#define NOTE_N_EVAL(_cc_op) NOTE_EVAL(_cc_op, tab_n_eval)
91#define NOTE_Z_EVAL(_cc_op) NOTE_EVAL(_cc_op, tab_z_eval)
92#define NOTE_C_EVAL(_cc_op) NOTE_EVAL(_cc_op, tab_c_eval)
93#define NOTE_V_EVAL(_cc_op) NOTE_EVAL(_cc_op, tab_v_eval)
94
95#define NOTE_EVAL(_cc_op, _tab) \
96   do { \
97      if (!initted) initCounts(); \
98      vassert( ((UInt)(_cc_op)) < ARMG_CC_OP_NUMBER); \
99      _tab[(UInt)(_cc_op)]++; \
100      tot_evals++; \
101      if (0 == (tot_evals & 0xFFFFF)) \
102        showCounts(); \
103   } while (0)
104
105#endif /* PROFILE_NZCV_FLAGS */
106
107
108/* Calculate the N flag from the supplied thunk components, in the
109   least significant bit of the word.  Returned bits 31:1 are zero. */
110static
111UInt armg_calculate_flag_n ( UInt cc_op, UInt cc_dep1,
112                             UInt cc_dep2, UInt cc_dep3 )
113{
114#  if PROFILE_NZCV_FLAGS
115   NOTE_N_EVAL(cc_op);
116#  endif
117
118   switch (cc_op) {
119      case ARMG_CC_OP_COPY: {
120         /* (nzcv:28x0, unused, unused) */
121         UInt nf   = (cc_dep1 >> ARMG_CC_SHIFT_N) & 1;
122         return nf;
123      }
124      case ARMG_CC_OP_ADD: {
125         /* (argL, argR, unused) */
126         UInt argL = cc_dep1;
127         UInt argR = cc_dep2;
128         UInt res  = argL + argR;
129         UInt nf   = res >> 31;
130         return nf;
131      }
132      case ARMG_CC_OP_SUB: {
133         /* (argL, argR, unused) */
134         UInt argL = cc_dep1;
135         UInt argR = cc_dep2;
136         UInt res  = argL - argR;
137         UInt nf   = res >> 31;
138         return nf;
139      }
140      case ARMG_CC_OP_ADC: {
141         /* (argL, argR, oldC) */
142         UInt argL = cc_dep1;
143         UInt argR = cc_dep2;
144         UInt oldC = cc_dep3;
145         vassert((oldC & ~1) == 0);
146         UInt res  = argL + argR + oldC;
147         UInt nf   = res >> 31;
148         return nf;
149      }
150      case ARMG_CC_OP_SBB: {
151         /* (argL, argR, oldC) */
152         UInt argL = cc_dep1;
153         UInt argR = cc_dep2;
154         UInt oldC = cc_dep3;
155         vassert((oldC & ~1) == 0);
156         UInt res  = argL - argR - (oldC ^ 1);
157         UInt nf   = res >> 31;
158         return nf;
159      }
160      case ARMG_CC_OP_LOGIC: {
161         /* (res, shco, oldV) */
162         UInt res  = cc_dep1;
163         UInt nf   = res >> 31;
164         return nf;
165      }
166      case ARMG_CC_OP_MUL: {
167         /* (res, unused, oldC:oldV) */
168         UInt res  = cc_dep1;
169         UInt nf   = res >> 31;
170         return nf;
171      }
172      case ARMG_CC_OP_MULL: {
173         /* (resLo32, resHi32, oldC:oldV) */
174         UInt resHi32 = cc_dep2;
175         UInt nf      = resHi32 >> 31;
176         return nf;
177      }
178      default:
179         /* shouldn't really make these calls from generated code */
180         vex_printf("armg_calculate_flag_n"
181                    "( op=%u, dep1=0x%x, dep2=0x%x, dep3=0x%x )\n",
182                    cc_op, cc_dep1, cc_dep2, cc_dep3 );
183         vpanic("armg_calculate_flags_n");
184   }
185}
186
187
188/* Calculate the Z flag from the supplied thunk components, in the
189   least significant bit of the word.  Returned bits 31:1 are zero. */
190static
191UInt armg_calculate_flag_z ( UInt cc_op, UInt cc_dep1,
192                             UInt cc_dep2, UInt cc_dep3 )
193{
194#  if PROFILE_NZCV_FLAGS
195   NOTE_Z_EVAL(cc_op);
196#  endif
197
198   switch (cc_op) {
199      case ARMG_CC_OP_COPY: {
200         /* (nzcv:28x0, unused, unused) */
201         UInt zf   = (cc_dep1 >> ARMG_CC_SHIFT_Z) & 1;
202         return zf;
203      }
204      case ARMG_CC_OP_ADD: {
205         /* (argL, argR, unused) */
206         UInt argL = cc_dep1;
207         UInt argR = cc_dep2;
208         UInt res  = argL + argR;
209         UInt zf   = res == 0;
210         return zf;
211      }
212      case ARMG_CC_OP_SUB: {
213         /* (argL, argR, unused) */
214         UInt argL = cc_dep1;
215         UInt argR = cc_dep2;
216         UInt res  = argL - argR;
217         UInt zf   = res == 0;
218         return zf;
219      }
220      case ARMG_CC_OP_ADC: {
221         /* (argL, argR, oldC) */
222         UInt argL = cc_dep1;
223         UInt argR = cc_dep2;
224         UInt oldC = cc_dep3;
225         vassert((oldC & ~1) == 0);
226         UInt res  = argL + argR + oldC;
227         UInt zf   = res == 0;
228         return zf;
229      }
230      case ARMG_CC_OP_SBB: {
231         /* (argL, argR, oldC) */
232         UInt argL = cc_dep1;
233         UInt argR = cc_dep2;
234         UInt oldC = cc_dep3;
235         vassert((oldC & ~1) == 0);
236         UInt res  = argL - argR - (oldC ^ 1);
237         UInt zf   = res == 0;
238         return zf;
239      }
240      case ARMG_CC_OP_LOGIC: {
241         /* (res, shco, oldV) */
242         UInt res  = cc_dep1;
243         UInt zf   = res == 0;
244         return zf;
245      }
246      case ARMG_CC_OP_MUL: {
247         /* (res, unused, oldC:oldV) */
248         UInt res  = cc_dep1;
249         UInt zf   = res == 0;
250         return zf;
251      }
252      case ARMG_CC_OP_MULL: {
253         /* (resLo32, resHi32, oldC:oldV) */
254         UInt resLo32 = cc_dep1;
255         UInt resHi32 = cc_dep2;
256         UInt zf      = (resHi32|resLo32) == 0;
257         return zf;
258      }
259      default:
260         /* shouldn't really make these calls from generated code */
261         vex_printf("armg_calculate_flags_z"
262                    "( op=%u, dep1=0x%x, dep2=0x%x, dep3=0x%x )\n",
263                    cc_op, cc_dep1, cc_dep2, cc_dep3 );
264         vpanic("armg_calculate_flags_z");
265   }
266}
267
268
269/* CALLED FROM GENERATED CODE: CLEAN HELPER */
270/* Calculate the C flag from the supplied thunk components, in the
271   least significant bit of the word.  Returned bits 31:1 are zero. */
272UInt armg_calculate_flag_c ( UInt cc_op, UInt cc_dep1,
273                             UInt cc_dep2, UInt cc_dep3 )
274{
275#  if PROFILE_NZCV_FLAGS
276   NOTE_C_EVAL(cc_op);
277#  endif
278
279   switch (cc_op) {
280      case ARMG_CC_OP_COPY: {
281         /* (nzcv:28x0, unused, unused) */
282         UInt cf   = (cc_dep1 >> ARMG_CC_SHIFT_C) & 1;
283         return cf;
284      }
285      case ARMG_CC_OP_ADD: {
286         /* (argL, argR, unused) */
287         UInt argL = cc_dep1;
288         UInt argR = cc_dep2;
289         UInt res  = argL + argR;
290         UInt cf   = res < argL;
291         return cf;
292      }
293      case ARMG_CC_OP_SUB: {
294         /* (argL, argR, unused) */
295         UInt argL = cc_dep1;
296         UInt argR = cc_dep2;
297         UInt cf   = argL >= argR;
298         return cf;
299      }
300      case ARMG_CC_OP_ADC: {
301         /* (argL, argR, oldC) */
302         UInt argL = cc_dep1;
303         UInt argR = cc_dep2;
304         UInt oldC = cc_dep3;
305         vassert((oldC & ~1) == 0);
306         UInt res  = argL + argR + oldC;
307         UInt cf   = oldC ? (res <= argL) : (res < argL);
308         return cf;
309      }
310      case ARMG_CC_OP_SBB: {
311         /* (argL, argR, oldC) */
312         UInt argL = cc_dep1;
313         UInt argR = cc_dep2;
314         UInt oldC = cc_dep3;
315         vassert((oldC & ~1) == 0);
316         UInt cf   = oldC ? (argL >= argR) : (argL > argR);
317         return cf;
318      }
319      case ARMG_CC_OP_LOGIC: {
320         /* (res, shco, oldV) */
321         UInt shco = cc_dep2;
322         vassert((shco & ~1) == 0);
323         UInt cf   = shco;
324         return cf;
325      }
326      case ARMG_CC_OP_MUL: {
327         /* (res, unused, oldC:oldV) */
328         UInt oldC = (cc_dep3 >> 1) & 1;
329         vassert((cc_dep3 & ~3) == 0);
330         UInt cf   = oldC;
331         return cf;
332      }
333      case ARMG_CC_OP_MULL: {
334         /* (resLo32, resHi32, oldC:oldV) */
335         UInt oldC    = (cc_dep3 >> 1) & 1;
336         vassert((cc_dep3 & ~3) == 0);
337         UInt cf      = oldC;
338         return cf;
339      }
340      default:
341         /* shouldn't really make these calls from generated code */
342         vex_printf("armg_calculate_flag_c"
343                    "( op=%u, dep1=0x%x, dep2=0x%x, dep3=0x%x )\n",
344                    cc_op, cc_dep1, cc_dep2, cc_dep3 );
345         vpanic("armg_calculate_flag_c");
346   }
347}
348
349
350/* CALLED FROM GENERATED CODE: CLEAN HELPER */
351/* Calculate the V flag from the supplied thunk components, in the
352   least significant bit of the word.  Returned bits 31:1 are zero. */
353UInt armg_calculate_flag_v ( UInt cc_op, UInt cc_dep1,
354                             UInt cc_dep2, UInt cc_dep3 )
355{
356#  if PROFILE_NZCV_FLAGS
357   NOTE_V_EVAL(cc_op);
358#  endif
359
360   switch (cc_op) {
361      case ARMG_CC_OP_COPY: {
362         /* (nzcv:28x0, unused, unused) */
363         UInt vf   = (cc_dep1 >> ARMG_CC_SHIFT_V) & 1;
364         return vf;
365      }
366      case ARMG_CC_OP_ADD: {
367         /* (argL, argR, unused) */
368         UInt argL = cc_dep1;
369         UInt argR = cc_dep2;
370         UInt res  = argL + argR;
371         UInt vf   = ((res ^ argL) & (res ^ argR)) >> 31;
372         return vf;
373      }
374      case ARMG_CC_OP_SUB: {
375         /* (argL, argR, unused) */
376         UInt argL = cc_dep1;
377         UInt argR = cc_dep2;
378         UInt res  = argL - argR;
379         UInt vf   = ((argL ^ argR) & (argL ^ res)) >> 31;
380         return vf;
381      }
382      case ARMG_CC_OP_ADC: {
383         /* (argL, argR, oldC) */
384         UInt argL = cc_dep1;
385         UInt argR = cc_dep2;
386         UInt oldC = cc_dep3;
387         vassert((oldC & ~1) == 0);
388         UInt res  = argL + argR + oldC;
389         UInt vf   = ((res ^ argL) & (res ^ argR)) >> 31;
390         return vf;
391      }
392      case ARMG_CC_OP_SBB: {
393         /* (argL, argR, oldC) */
394         UInt argL = cc_dep1;
395         UInt argR = cc_dep2;
396         UInt oldC = cc_dep3;
397         vassert((oldC & ~1) == 0);
398         UInt res  = argL - argR - (oldC ^ 1);
399         UInt vf   = ((argL ^ argR) & (argL ^ res)) >> 31;
400         return vf;
401      }
402      case ARMG_CC_OP_LOGIC: {
403         /* (res, shco, oldV) */
404         UInt oldV = cc_dep3;
405         vassert((oldV & ~1) == 0);
406         UInt vf   = oldV;
407         return vf;
408      }
409      case ARMG_CC_OP_MUL: {
410         /* (res, unused, oldC:oldV) */
411         UInt oldV = (cc_dep3 >> 0) & 1;
412         vassert((cc_dep3 & ~3) == 0);
413         UInt vf   = oldV;
414         return vf;
415      }
416      case ARMG_CC_OP_MULL: {
417         /* (resLo32, resHi32, oldC:oldV) */
418         UInt oldV    = (cc_dep3 >> 0) & 1;
419         vassert((cc_dep3 & ~3) == 0);
420         UInt vf      = oldV;
421         return vf;
422      }
423      default:
424         /* shouldn't really make these calls from generated code */
425         vex_printf("armg_calculate_flag_v"
426                    "( op=%u, dep1=0x%x, dep2=0x%x, dep3=0x%x )\n",
427                    cc_op, cc_dep1, cc_dep2, cc_dep3 );
428         vpanic("armg_calculate_flag_v");
429   }
430}
431
432
433/* CALLED FROM GENERATED CODE: CLEAN HELPER */
434/* Calculate NZCV from the supplied thunk components, in the positions
435   they appear in the CPSR, viz bits 31:28 for N Z C V respectively.
436   Returned bits 27:0 are zero. */
437UInt armg_calculate_flags_nzcv ( UInt cc_op, UInt cc_dep1,
438                                 UInt cc_dep2, UInt cc_dep3 )
439{
440   UInt f;
441   UInt res = 0;
442   f = armg_calculate_flag_n(cc_op, cc_dep1, cc_dep2, cc_dep3);
443   res |= (f << ARMG_CC_SHIFT_N);
444   f = armg_calculate_flag_z(cc_op, cc_dep1, cc_dep2, cc_dep3);
445   res |= (f << ARMG_CC_SHIFT_Z);
446   f = armg_calculate_flag_c(cc_op, cc_dep1, cc_dep2, cc_dep3);
447   res |= (f << ARMG_CC_SHIFT_C);
448   f = armg_calculate_flag_v(cc_op, cc_dep1, cc_dep2, cc_dep3);
449   res |= (f << ARMG_CC_SHIFT_V);
450   return res;
451}
452
453
454/* CALLED FROM GENERATED CODE: CLEAN HELPER */
455/* Calculate the QC flag from the arguments, in the lowest bit
456   of the word (bit 0).  Urr, having this out of line is bizarre.
457   Push back inline. */
458UInt armg_calculate_flag_qc ( UInt resL1, UInt resL2,
459                              UInt resR1, UInt resR2 )
460{
461   if (resL1 != resR1 || resL2 != resR2)
462      return 1;
463   else
464      return 0;
465}
466
467/* CALLED FROM GENERATED CODE: CLEAN HELPER */
468/* Calculate the specified condition from the thunk components, in the
469   lowest bit of the word (bit 0).  Returned bits 31:1 are zero. */
470UInt armg_calculate_condition ( UInt cond_n_op /* (ARMCondcode << 4) | cc_op */,
471                                UInt cc_dep1,
472                                UInt cc_dep2, UInt cc_dep3 )
473{
474   UInt cond  = cond_n_op >> 4;
475   UInt cc_op = cond_n_op & 0xF;
476   UInt nf, zf, vf, cf, inv;
477   //   vex_printf("XXXXXXXX %x %x %x %x\n",
478   //              cond_n_op, cc_dep1, cc_dep2, cc_dep3);
479
480   // skip flags computation in this case
481   if (cond == ARMCondAL) return 1;
482
483   inv  = cond & 1;
484
485   switch (cond) {
486      case ARMCondEQ:    // Z=1         => z
487      case ARMCondNE:    // Z=0
488         zf = armg_calculate_flag_z(cc_op, cc_dep1, cc_dep2, cc_dep3);
489         return inv ^ zf;
490
491      case ARMCondHS:    // C=1         => c
492      case ARMCondLO:    // C=0
493         cf = armg_calculate_flag_c(cc_op, cc_dep1, cc_dep2, cc_dep3);
494         return inv ^ cf;
495
496      case ARMCondMI:    // N=1         => n
497      case ARMCondPL:    // N=0
498         nf = armg_calculate_flag_n(cc_op, cc_dep1, cc_dep2, cc_dep3);
499         return inv ^ nf;
500
501      case ARMCondVS:    // V=1         => v
502      case ARMCondVC:    // V=0
503         vf = armg_calculate_flag_v(cc_op, cc_dep1, cc_dep2, cc_dep3);
504         return inv ^ vf;
505
506      case ARMCondHI:    // C=1 && Z=0   => c & ~z
507      case ARMCondLS:    // C=0 || Z=1
508         cf = armg_calculate_flag_c(cc_op, cc_dep1, cc_dep2, cc_dep3);
509         zf = armg_calculate_flag_z(cc_op, cc_dep1, cc_dep2, cc_dep3);
510         return inv ^ (1 & (cf & ~zf));
511
512      case ARMCondGE:    // N=V          => ~(n^v)
513      case ARMCondLT:    // N!=V
514         nf = armg_calculate_flag_n(cc_op, cc_dep1, cc_dep2, cc_dep3);
515         vf = armg_calculate_flag_v(cc_op, cc_dep1, cc_dep2, cc_dep3);
516         return inv ^ (1 & ~(nf ^ vf));
517
518      case ARMCondGT:    // Z=0 && N=V   => ~z & ~(n^v)  =>  ~(z | (n^v))
519      case ARMCondLE:    // Z=1 || N!=V
520         nf = armg_calculate_flag_n(cc_op, cc_dep1, cc_dep2, cc_dep3);
521         vf = armg_calculate_flag_v(cc_op, cc_dep1, cc_dep2, cc_dep3);
522         zf = armg_calculate_flag_z(cc_op, cc_dep1, cc_dep2, cc_dep3);
523         return inv ^ (1 & ~(zf | (nf ^ vf)));
524
525      case ARMCondAL: // handled above
526      case ARMCondNV: // should never get here: Illegal instr
527      default:
528         /* shouldn't really make these calls from generated code */
529         vex_printf("armg_calculate_condition(ARM)"
530                    "( %u, %u, 0x%x, 0x%x, 0x%x )\n",
531                    cond, cc_op, cc_dep1, cc_dep2, cc_dep3 );
532         vpanic("armg_calculate_condition(ARM)");
533   }
534}
535
536
537/*---------------------------------------------------------------*/
538/*--- Flag-helpers translation-time function specialisers.    ---*/
539/*--- These help iropt specialise calls the above run-time    ---*/
540/*--- flags functions.                                        ---*/
541/*---------------------------------------------------------------*/
542
543/* Used by the optimiser to try specialisations.  Returns an
544   equivalent expression, or NULL if none. */
545
546static Bool isU32 ( IRExpr* e, UInt n )
547{
548   return
549      toBool( e->tag == Iex_Const
550              && e->Iex.Const.con->tag == Ico_U32
551              && e->Iex.Const.con->Ico.U32 == n );
552}
553
554IRExpr* guest_arm_spechelper ( const HChar* function_name,
555                               IRExpr** args,
556                               IRStmt** precedingStmts,
557                               Int      n_precedingStmts )
558{
559#  define unop(_op,_a1) IRExpr_Unop((_op),(_a1))
560#  define binop(_op,_a1,_a2) IRExpr_Binop((_op),(_a1),(_a2))
561#  define mkU32(_n) IRExpr_Const(IRConst_U32(_n))
562#  define mkU8(_n)  IRExpr_Const(IRConst_U8(_n))
563
564   Int i, arity = 0;
565   for (i = 0; args[i]; i++)
566      arity++;
567#  if 0
568   vex_printf("spec request:\n");
569   vex_printf("   %s  ", function_name);
570   for (i = 0; i < arity; i++) {
571      vex_printf("  ");
572      ppIRExpr(args[i]);
573   }
574   vex_printf("\n");
575#  endif
576
577   /* --------- specialising "armg_calculate_condition" --------- */
578
579   if (vex_streq(function_name, "armg_calculate_condition")) {
580
581      /* specialise calls to the "armg_calculate_condition" function.
582         Not sure whether this is strictly necessary, but: the
583         replacement IR must produce only the values 0 or 1.  Bits
584         31:1 are required to be zero. */
585      IRExpr *cond_n_op, *cc_dep1, *cc_dep2, *cc_ndep;
586      vassert(arity == 4);
587      cond_n_op = args[0]; /* (ARMCondcode << 4)  |  ARMG_CC_OP_* */
588      cc_dep1   = args[1];
589      cc_dep2   = args[2];
590      cc_ndep   = args[3];
591
592      /*---------------- SUB ----------------*/
593
594      if (isU32(cond_n_op, (ARMCondEQ << 4) | ARMG_CC_OP_SUB)) {
595         /* EQ after SUB --> test argL == argR */
596         return unop(Iop_1Uto32,
597                     binop(Iop_CmpEQ32, cc_dep1, cc_dep2));
598      }
599      if (isU32(cond_n_op, (ARMCondNE << 4) | ARMG_CC_OP_SUB)) {
600         /* NE after SUB --> test argL != argR */
601         return unop(Iop_1Uto32,
602                     binop(Iop_CmpNE32, cc_dep1, cc_dep2));
603      }
604
605      if (isU32(cond_n_op, (ARMCondGT << 4) | ARMG_CC_OP_SUB)) {
606         /* GT after SUB --> test argL >s argR
607                         --> test argR <s argL */
608         return unop(Iop_1Uto32,
609                     binop(Iop_CmpLT32S, cc_dep2, cc_dep1));
610      }
611      if (isU32(cond_n_op, (ARMCondLE << 4) | ARMG_CC_OP_SUB)) {
612         /* LE after SUB --> test argL <=s argR */
613         return unop(Iop_1Uto32,
614                     binop(Iop_CmpLE32S, cc_dep1, cc_dep2));
615      }
616
617      if (isU32(cond_n_op, (ARMCondLT << 4) | ARMG_CC_OP_SUB)) {
618         /* LT after SUB --> test argL <s argR */
619         return unop(Iop_1Uto32,
620                     binop(Iop_CmpLT32S, cc_dep1, cc_dep2));
621      }
622
623      if (isU32(cond_n_op, (ARMCondGE << 4) | ARMG_CC_OP_SUB)) {
624         /* GE after SUB --> test argL >=s argR
625                         --> test argR <=s argL */
626         return unop(Iop_1Uto32,
627                     binop(Iop_CmpLE32S, cc_dep2, cc_dep1));
628      }
629
630      if (isU32(cond_n_op, (ARMCondHS << 4) | ARMG_CC_OP_SUB)) {
631         /* HS after SUB --> test argL >=u argR
632                         --> test argR <=u argL */
633         return unop(Iop_1Uto32,
634                     binop(Iop_CmpLE32U, cc_dep2, cc_dep1));
635      }
636      if (isU32(cond_n_op, (ARMCondLO << 4) | ARMG_CC_OP_SUB)) {
637         /* LO after SUB --> test argL <u argR */
638         return unop(Iop_1Uto32,
639                     binop(Iop_CmpLT32U, cc_dep1, cc_dep2));
640      }
641
642      if (isU32(cond_n_op, (ARMCondLS << 4) | ARMG_CC_OP_SUB)) {
643         /* LS after SUB --> test argL <=u argR */
644         return unop(Iop_1Uto32,
645                     binop(Iop_CmpLE32U, cc_dep1, cc_dep2));
646      }
647      if (isU32(cond_n_op, (ARMCondHI << 4) | ARMG_CC_OP_SUB)) {
648         /* HI after SUB --> test argL >u argR
649                         --> test argR <u argL */
650         return unop(Iop_1Uto32,
651                     binop(Iop_CmpLT32U, cc_dep2, cc_dep1));
652      }
653
654      /*---------------- SBB ----------------*/
655
656      if (isU32(cond_n_op, (ARMCondHS << 4) | ARMG_CC_OP_SBB)) {
657         /* This seems to happen a lot in softfloat code, eg __divdf3+140 */
658         /* thunk is: (dep1=argL, dep2=argR, ndep=oldC) */
659         /* HS after SBB (same as C after SBB below)
660            --> oldC ? (argL >=u argR) : (argL >u argR)
661            --> oldC ? (argR <=u argL) : (argR <u argL)
662         */
663         return
664            IRExpr_ITE(
665               binop(Iop_CmpNE32, cc_ndep, mkU32(0)),
666               /* case oldC != 0 */
667               unop(Iop_1Uto32, binop(Iop_CmpLE32U, cc_dep2, cc_dep1)),
668               /* case oldC == 0 */
669               unop(Iop_1Uto32, binop(Iop_CmpLT32U, cc_dep2, cc_dep1))
670            );
671      }
672
673      /*---------------- LOGIC ----------------*/
674
675      if (isU32(cond_n_op, (ARMCondEQ << 4) | ARMG_CC_OP_LOGIC)) {
676         /* EQ after LOGIC --> test res == 0 */
677         return unop(Iop_1Uto32,
678                     binop(Iop_CmpEQ32, cc_dep1, mkU32(0)));
679      }
680      if (isU32(cond_n_op, (ARMCondNE << 4) | ARMG_CC_OP_LOGIC)) {
681         /* NE after LOGIC --> test res != 0 */
682         return unop(Iop_1Uto32,
683                     binop(Iop_CmpNE32, cc_dep1, mkU32(0)));
684      }
685
686      if (isU32(cond_n_op, (ARMCondPL << 4) | ARMG_CC_OP_LOGIC)) {
687         /* PL after LOGIC --> test (res >> 31) == 0 */
688         return unop(Iop_1Uto32,
689                     binop(Iop_CmpEQ32,
690                           binop(Iop_Shr32, cc_dep1, mkU8(31)),
691                           mkU32(0)));
692      }
693      if (isU32(cond_n_op, (ARMCondMI << 4) | ARMG_CC_OP_LOGIC)) {
694         /* MI after LOGIC --> test (res >> 31) == 1 */
695         return unop(Iop_1Uto32,
696                     binop(Iop_CmpEQ32,
697                           binop(Iop_Shr32, cc_dep1, mkU8(31)),
698                           mkU32(1)));
699      }
700
701      /*---------------- COPY ----------------*/
702
703      if (isU32(cond_n_op, (ARMCondNE << 4) | ARMG_CC_OP_COPY)) {
704         /* NE after COPY --> ((cc_dep1 >> ARMG_CC_SHIFT_Z) ^ 1) & 1 */
705         return binop(Iop_And32,
706                      binop(Iop_Xor32,
707                            binop(Iop_Shr32, cc_dep1,
708                                             mkU8(ARMG_CC_SHIFT_Z)),
709                            mkU32(1)),
710                      mkU32(1));
711      }
712
713      /*----------------- AL -----------------*/
714
715      /* A critically important case for Thumb code.
716
717         What we're trying to spot is the case where cond_n_op is an
718         expression of the form Or32(..., 0xE0) since that means the
719         caller is asking for CondAL and we can simply return 1
720         without caring what the ... part is.  This is a potentially
721         dodgy kludge in that it assumes that the ... part has zeroes
722         in bits 7:4, so that the result of the Or32 is guaranteed to
723         be 0xE in bits 7:4.  Given that the places where this first
724         arg are constructed (in guest_arm_toIR.c) are very
725         constrained, we can get away with this.  To make this
726         guaranteed safe would require to have a new primop, Slice44
727         or some such, thusly
728
729         Slice44(arg1, arg2) = 0--(24)--0 arg1[7:4] arg2[3:0]
730
731         and we would then look for Slice44(0xE0, ...)
732         which would give the required safety property.
733
734         It would be infeasibly expensive to scan backwards through
735         the entire block looking for an assignment to the temp, so
736         just look at the previous 16 statements.  That should find it
737         if it is an interesting case, as a result of how the
738         boilerplate guff at the start of each Thumb insn translation
739         is made.
740      */
741      if (cond_n_op->tag == Iex_RdTmp) {
742         Int    j;
743         IRTemp look_for = cond_n_op->Iex.RdTmp.tmp;
744         Int    limit    = n_precedingStmts - 16;
745         if (limit < 0) limit = 0;
746         if (0) vex_printf("scanning %d .. %d\n", n_precedingStmts-1, limit);
747         for (j = n_precedingStmts - 1; j >= limit; j--) {
748            IRStmt* st = precedingStmts[j];
749            if (st->tag == Ist_WrTmp
750                && st->Ist.WrTmp.tmp == look_for
751                && st->Ist.WrTmp.data->tag == Iex_Binop
752                && st->Ist.WrTmp.data->Iex.Binop.op == Iop_Or32
753                && isU32(st->Ist.WrTmp.data->Iex.Binop.arg2, (ARMCondAL << 4)))
754               return mkU32(1);
755         }
756         /* Didn't find any useful binding to the first arg
757            in the previous 16 stmts. */
758      }
759   }
760
761   /* --------- specialising "armg_calculate_flag_c" --------- */
762
763   else
764   if (vex_streq(function_name, "armg_calculate_flag_c")) {
765
766      /* specialise calls to the "armg_calculate_flag_c" function.
767         Note that the returned value must be either 0 or 1; nonzero
768         bits 31:1 are not allowed.  In turn, incoming oldV and oldC
769         values (from the thunk) are assumed to have bits 31:1
770         clear. */
771      IRExpr *cc_op, *cc_dep1, *cc_dep2, *cc_ndep;
772      vassert(arity == 4);
773      cc_op   = args[0]; /* ARMG_CC_OP_* */
774      cc_dep1 = args[1];
775      cc_dep2 = args[2];
776      cc_ndep = args[3];
777
778      if (isU32(cc_op, ARMG_CC_OP_LOGIC)) {
779         /* Thunk args are (result, shco, oldV) */
780         /* C after LOGIC --> shco */
781         return cc_dep2;
782      }
783
784      if (isU32(cc_op, ARMG_CC_OP_SUB)) {
785         /* Thunk args are (argL, argR, unused) */
786         /* C after SUB --> argL >=u argR
787                        --> argR <=u argL */
788         return unop(Iop_1Uto32,
789                     binop(Iop_CmpLE32U, cc_dep2, cc_dep1));
790      }
791
792      if (isU32(cc_op, ARMG_CC_OP_SBB)) {
793         /* This happens occasionally in softfloat code, eg __divdf3+140 */
794         /* thunk is: (dep1=argL, dep2=argR, ndep=oldC) */
795         /* C after SBB (same as HS after SBB above)
796            --> oldC ? (argL >=u argR) : (argL >u argR)
797            --> oldC ? (argR <=u argL) : (argR <u argL)
798         */
799         return
800            IRExpr_ITE(
801               binop(Iop_CmpNE32, cc_ndep, mkU32(0)),
802               /* case oldC != 0 */
803               unop(Iop_1Uto32, binop(Iop_CmpLE32U, cc_dep2, cc_dep1)),
804               /* case oldC == 0 */
805               unop(Iop_1Uto32, binop(Iop_CmpLT32U, cc_dep2, cc_dep1))
806            );
807      }
808
809   }
810
811   /* --------- specialising "armg_calculate_flag_v" --------- */
812
813   else
814   if (vex_streq(function_name, "armg_calculate_flag_v")) {
815
816      /* specialise calls to the "armg_calculate_flag_v" function.
817         Note that the returned value must be either 0 or 1; nonzero
818         bits 31:1 are not allowed.  In turn, incoming oldV and oldC
819         values (from the thunk) are assumed to have bits 31:1
820         clear. */
821      IRExpr *cc_op, *cc_dep1, *cc_dep2, *cc_ndep;
822      vassert(arity == 4);
823      cc_op   = args[0]; /* ARMG_CC_OP_* */
824      cc_dep1 = args[1];
825      cc_dep2 = args[2];
826      cc_ndep = args[3];
827
828      if (isU32(cc_op, ARMG_CC_OP_LOGIC)) {
829         /* Thunk args are (result, shco, oldV) */
830         /* V after LOGIC --> oldV */
831         return cc_ndep;
832      }
833
834      if (isU32(cc_op, ARMG_CC_OP_SUB)) {
835         /* Thunk args are (argL, argR, unused) */
836         /* V after SUB
837            --> let res = argL - argR
838                in ((argL ^ argR) & (argL ^ res)) >> 31
839            --> ((argL ^ argR) & (argL ^ (argL - argR))) >> 31
840         */
841         IRExpr* argL = cc_dep1;
842         IRExpr* argR = cc_dep2;
843         return
844            binop(Iop_Shr32,
845                  binop(Iop_And32,
846                        binop(Iop_Xor32, argL, argR),
847                        binop(Iop_Xor32, argL, binop(Iop_Sub32, argL, argR))
848                  ),
849                  mkU8(31)
850            );
851      }
852
853      if (isU32(cc_op, ARMG_CC_OP_SBB)) {
854         /* This happens occasionally in softfloat code, eg __divdf3+140 */
855         /* thunk is: (dep1=argL, dep2=argR, ndep=oldC) */
856         /* V after SBB
857            --> let res = argL - argR - (oldC ^ 1)
858                in  (argL ^ argR) & (argL ^ res) & 1
859         */
860         return
861            binop(
862               Iop_And32,
863               binop(
864                  Iop_And32,
865                  // argL ^ argR
866                  binop(Iop_Xor32, cc_dep1, cc_dep2),
867                  // argL ^ (argL - argR - (oldC ^ 1))
868                  binop(Iop_Xor32,
869                        cc_dep1,
870                        binop(Iop_Sub32,
871                              binop(Iop_Sub32, cc_dep1, cc_dep2),
872                              binop(Iop_Xor32, cc_ndep, mkU32(1)))
873                  )
874               ),
875               mkU32(1)
876            );
877      }
878
879   }
880
881#  undef unop
882#  undef binop
883#  undef mkU32
884#  undef mkU8
885
886   return NULL;
887}
888
889
890/*----------------------------------------------*/
891/*--- The exported fns ..                    ---*/
892/*----------------------------------------------*/
893
894/* VISIBLE TO LIBVEX CLIENT */
895#if 0
896void LibVEX_GuestARM_put_flags ( UInt flags_native,
897                                 /*OUT*/VexGuestARMState* vex_state )
898{
899   vassert(0); // FIXME
900
901   /* Mask out everything except N Z V C. */
902   flags_native
903      &= (ARMG_CC_MASK_N | ARMG_CC_MASK_Z | ARMG_CC_MASK_V | ARMG_CC_MASK_C);
904
905   vex_state->guest_CC_OP   = ARMG_CC_OP_COPY;
906   vex_state->guest_CC_DEP1 = flags_native;
907   vex_state->guest_CC_DEP2 = 0;
908   vex_state->guest_CC_NDEP = 0;
909}
910#endif
911
912/* VISIBLE TO LIBVEX CLIENT */
913UInt LibVEX_GuestARM_get_cpsr ( /*IN*/const VexGuestARMState* vex_state )
914{
915   UInt cpsr = 0;
916   // NZCV
917   cpsr |= armg_calculate_flags_nzcv(
918               vex_state->guest_CC_OP,
919               vex_state->guest_CC_DEP1,
920               vex_state->guest_CC_DEP2,
921               vex_state->guest_CC_NDEP
922            );
923   vassert(0 == (cpsr & 0x0FFFFFFF));
924   // Q
925   if (vex_state->guest_QFLAG32 > 0)
926      cpsr |= (1 << 27);
927   // GE
928   if (vex_state->guest_GEFLAG0 > 0)
929      cpsr |= (1 << 16);
930   if (vex_state->guest_GEFLAG1 > 0)
931      cpsr |= (1 << 17);
932   if (vex_state->guest_GEFLAG2 > 0)
933      cpsr |= (1 << 18);
934   if (vex_state->guest_GEFLAG3 > 0)
935      cpsr |= (1 << 19);
936   // M
937   cpsr |= (1 << 4); // 0b10000 means user-mode
938   // J,T   J (bit 24) is zero by initialisation above
939   // T  we copy from R15T[0]
940   if (vex_state->guest_R15T & 1)
941      cpsr |= (1 << 5);
942   // ITSTATE we punt on for the time being.  Could compute it
943   // if needed though.
944   // E, endianness, 0 (littleendian) from initialisation above
945   // A,I,F disable some async exceptions.  Not sure about these.
946   // Leave as zero for the time being.
947   return cpsr;
948}
949
950/* VISIBLE TO LIBVEX CLIENT */
951void LibVEX_GuestARM_initialise ( /*OUT*/VexGuestARMState* vex_state )
952{
953   vex_state->host_EvC_FAILADDR = 0;
954   vex_state->host_EvC_COUNTER = 0;
955
956   vex_state->guest_R0  = 0;
957   vex_state->guest_R1  = 0;
958   vex_state->guest_R2  = 0;
959   vex_state->guest_R3  = 0;
960   vex_state->guest_R4  = 0;
961   vex_state->guest_R5  = 0;
962   vex_state->guest_R6  = 0;
963   vex_state->guest_R7  = 0;
964   vex_state->guest_R8  = 0;
965   vex_state->guest_R9  = 0;
966   vex_state->guest_R10 = 0;
967   vex_state->guest_R11 = 0;
968   vex_state->guest_R12 = 0;
969   vex_state->guest_R13 = 0;
970   vex_state->guest_R14 = 0;
971   vex_state->guest_R15T = 0;  /* NB: implies ARM mode */
972
973   vex_state->guest_CC_OP   = ARMG_CC_OP_COPY;
974   vex_state->guest_CC_DEP1 = 0;
975   vex_state->guest_CC_DEP2 = 0;
976   vex_state->guest_CC_NDEP = 0;
977   vex_state->guest_QFLAG32 = 0;
978   vex_state->guest_GEFLAG0 = 0;
979   vex_state->guest_GEFLAG1 = 0;
980   vex_state->guest_GEFLAG2 = 0;
981   vex_state->guest_GEFLAG3 = 0;
982
983   vex_state->guest_EMNOTE  = EmNote_NONE;
984   vex_state->guest_CMSTART = 0;
985   vex_state->guest_CMLEN   = 0;
986   vex_state->guest_NRADDR  = 0;
987   vex_state->guest_IP_AT_SYSCALL = 0;
988
989   vex_state->guest_D0  = 0;
990   vex_state->guest_D1  = 0;
991   vex_state->guest_D2  = 0;
992   vex_state->guest_D3  = 0;
993   vex_state->guest_D4  = 0;
994   vex_state->guest_D5  = 0;
995   vex_state->guest_D6  = 0;
996   vex_state->guest_D7  = 0;
997   vex_state->guest_D8  = 0;
998   vex_state->guest_D9  = 0;
999   vex_state->guest_D10 = 0;
1000   vex_state->guest_D11 = 0;
1001   vex_state->guest_D12 = 0;
1002   vex_state->guest_D13 = 0;
1003   vex_state->guest_D14 = 0;
1004   vex_state->guest_D15 = 0;
1005   vex_state->guest_D16 = 0;
1006   vex_state->guest_D17 = 0;
1007   vex_state->guest_D18 = 0;
1008   vex_state->guest_D19 = 0;
1009   vex_state->guest_D20 = 0;
1010   vex_state->guest_D21 = 0;
1011   vex_state->guest_D22 = 0;
1012   vex_state->guest_D23 = 0;
1013   vex_state->guest_D24 = 0;
1014   vex_state->guest_D25 = 0;
1015   vex_state->guest_D26 = 0;
1016   vex_state->guest_D27 = 0;
1017   vex_state->guest_D28 = 0;
1018   vex_state->guest_D29 = 0;
1019   vex_state->guest_D30 = 0;
1020   vex_state->guest_D31 = 0;
1021
1022   /* ARM encoded; zero is the default as it happens (result flags
1023      (NZCV) cleared, FZ disabled, round to nearest, non-vector mode,
1024      all exns masked, all exn sticky bits cleared). */
1025   vex_state->guest_FPSCR = 0;
1026
1027   vex_state->guest_TPIDRURO = 0;
1028
1029   /* Not in a Thumb IT block. */
1030   vex_state->guest_ITSTATE = 0;
1031
1032   vex_state->padding1 = 0;
1033}
1034
1035
1036/*-----------------------------------------------------------*/
1037/*--- Describing the arm guest state, for the benefit     ---*/
1038/*--- of iropt and instrumenters.                         ---*/
1039/*-----------------------------------------------------------*/
1040
1041/* Figure out if any part of the guest state contained in minoff
1042   .. maxoff requires precise memory exceptions.  If in doubt return
1043   True (but this generates significantly slower code).
1044
1045   We enforce precise exns for guest R13(sp), R15T(pc), R7, R11.
1046
1047
1048   Only R13(sp) is needed in mode VexRegUpdSpAtMemAccess.
1049*/
1050Bool guest_arm_state_requires_precise_mem_exns ( Int minoff,
1051                                                 Int maxoff)
1052{
1053   Int sp_min = offsetof(VexGuestARMState, guest_R13);
1054   Int sp_max = sp_min + 4 - 1;
1055   Int pc_min = offsetof(VexGuestARMState, guest_R15T);
1056   Int pc_max = pc_min + 4 - 1;
1057
1058   if (maxoff < sp_min || minoff > sp_max) {
1059      /* no overlap with sp */
1060      if (vex_control.iropt_register_updates == VexRegUpdSpAtMemAccess)
1061         return False; // We only need to check stack pointer.
1062   } else {
1063      return True;
1064   }
1065
1066   if (maxoff < pc_min || minoff > pc_max) {
1067      /* no overlap with pc */
1068   } else {
1069      return True;
1070   }
1071
1072   /* We appear to need precise updates of R11 in order to get proper
1073      stacktraces from non-optimised code. */
1074   Int r11_min = offsetof(VexGuestARMState, guest_R11);
1075   Int r11_max = r11_min + 4 - 1;
1076
1077   if (maxoff < r11_min || minoff > r11_max) {
1078      /* no overlap with r11 */
1079   } else {
1080      return True;
1081   }
1082
1083   /* Ditto R7, particularly needed for proper stacktraces in Thumb
1084      code. */
1085   Int r7_min = offsetof(VexGuestARMState, guest_R7);
1086   Int r7_max = r7_min + 4 - 1;
1087
1088   if (maxoff < r7_min || minoff > r7_max) {
1089      /* no overlap with r7 */
1090   } else {
1091      return True;
1092   }
1093
1094   return False;
1095}
1096
1097
1098
1099#define ALWAYSDEFD(field)                           \
1100    { offsetof(VexGuestARMState, field),            \
1101      (sizeof ((VexGuestARMState*)0)->field) }
1102
1103VexGuestLayout
1104   armGuest_layout
1105      = {
1106          /* Total size of the guest state, in bytes. */
1107          .total_sizeB = sizeof(VexGuestARMState),
1108
1109          /* Describe the stack pointer. */
1110          .offset_SP = offsetof(VexGuestARMState,guest_R13),
1111          .sizeof_SP = 4,
1112
1113          /* Describe the instruction pointer. */
1114          .offset_IP = offsetof(VexGuestARMState,guest_R15T),
1115          .sizeof_IP = 4,
1116
1117          /* Describe any sections to be regarded by Memcheck as
1118             'always-defined'. */
1119          .n_alwaysDefd = 10,
1120
1121          /* flags thunk: OP is always defd, whereas DEP1 and DEP2
1122             have to be tracked.  See detailed comment in gdefs.h on
1123             meaning of thunk fields. */
1124          .alwaysDefd
1125             = { /* 0 */ ALWAYSDEFD(guest_R15T),
1126                 /* 1 */ ALWAYSDEFD(guest_CC_OP),
1127                 /* 2 */ ALWAYSDEFD(guest_CC_NDEP),
1128                 /* 3 */ ALWAYSDEFD(guest_EMNOTE),
1129                 /* 4 */ ALWAYSDEFD(guest_CMSTART),
1130                 /* 5 */ ALWAYSDEFD(guest_CMLEN),
1131                 /* 6 */ ALWAYSDEFD(guest_NRADDR),
1132                 /* 7 */ ALWAYSDEFD(guest_IP_AT_SYSCALL),
1133                 /* 8 */ ALWAYSDEFD(guest_TPIDRURO),
1134                 /* 9 */ ALWAYSDEFD(guest_ITSTATE)
1135               }
1136        };
1137
1138
1139/*---------------------------------------------------------------*/
1140/*--- end                                 guest_arm_helpers.c ---*/
1141/*---------------------------------------------------------------*/
1142