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