• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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-2012 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 
60 static UInt tab_n_eval[ARMG_CC_OP_NUMBER];
61 static UInt tab_z_eval[ARMG_CC_OP_NUMBER];
62 static UInt tab_c_eval[ARMG_CC_OP_NUMBER];
63 static UInt tab_v_eval[ARMG_CC_OP_NUMBER];
64 static UInt initted = 0;
65 static UInt tot_evals = 0;
66 
initCounts(void)67 static 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 
showCounts(void)76 static 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. */
109 static
armg_calculate_flag_n(UInt cc_op,UInt cc_dep1,UInt cc_dep2,UInt cc_dep3)110 UInt 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. */
189 static
armg_calculate_flag_z(UInt cc_op,UInt cc_dep1,UInt cc_dep2,UInt cc_dep3)190 UInt 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. */
armg_calculate_flag_c(UInt cc_op,UInt cc_dep1,UInt cc_dep2,UInt cc_dep3)271 UInt 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. */
armg_calculate_flag_v(UInt cc_op,UInt cc_dep1,UInt cc_dep2,UInt cc_dep3)352 UInt 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. */
armg_calculate_flags_nzcv(UInt cc_op,UInt cc_dep1,UInt cc_dep2,UInt cc_dep3)436 UInt 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. */
armg_calculate_flag_qc(UInt resL1,UInt resL2,UInt resR1,UInt resR2)457 UInt 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. */
armg_calculate_condition(UInt cond_n_op,UInt cc_dep1,UInt cc_dep2,UInt cc_dep3)469 UInt 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 
isU32(IRExpr * e,UInt n)545 static 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 
guest_arm_spechelper(HChar * function_name,IRExpr ** args,IRStmt ** precedingStmts,Int n_precedingStmts)553 IRExpr* 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       if (isU32(cond_n_op, (ARMCondHI << 4) | ARMG_CC_OP_SUB)) {
647          /* HI after SUB --> test argL >u argR
648                          --> test argR <u argL */
649          return unop(Iop_1Uto32,
650                      binop(Iop_CmpLT32U, cc_dep2, cc_dep1));
651       }
652 
653       /*---------------- SBB ----------------*/
654 
655       if (isU32(cond_n_op, (ARMCondHS << 4) | ARMG_CC_OP_SBB)) {
656          /* This seems to happen a lot in softfloat code, eg __divdf3+140 */
657          /* thunk is: (dep1=argL, dep2=argR, ndep=oldC) */
658          /* HS after SBB (same as C after SBB below)
659             --> oldC ? (argL >=u argR) : (argL >u argR)
660             --> oldC ? (argR <=u argL) : (argR <u argL)
661          */
662          return
663             IRExpr_Mux0X(
664                unop(Iop_32to8, cc_ndep),
665                /* case oldC == 0 */
666                unop(Iop_1Uto32, binop(Iop_CmpLT32U, cc_dep2, cc_dep1)),
667                /* case oldC != 0 */
668                unop(Iop_1Uto32, binop(Iop_CmpLE32U, cc_dep2, cc_dep1))
669             );
670       }
671 
672       /*---------------- LOGIC ----------------*/
673 
674       if (isU32(cond_n_op, (ARMCondEQ << 4) | ARMG_CC_OP_LOGIC)) {
675          /* EQ after LOGIC --> test res == 0 */
676          return unop(Iop_1Uto32,
677                      binop(Iop_CmpEQ32, cc_dep1, mkU32(0)));
678       }
679       if (isU32(cond_n_op, (ARMCondNE << 4) | ARMG_CC_OP_LOGIC)) {
680          /* NE after LOGIC --> test res != 0 */
681          return unop(Iop_1Uto32,
682                      binop(Iop_CmpNE32, cc_dep1, mkU32(0)));
683       }
684 
685       if (isU32(cond_n_op, (ARMCondPL << 4) | ARMG_CC_OP_LOGIC)) {
686          /* PL after LOGIC --> test (res >> 31) == 0 */
687          return unop(Iop_1Uto32,
688                      binop(Iop_CmpEQ32,
689                            binop(Iop_Shr32, cc_dep1, mkU8(31)),
690                            mkU32(0)));
691       }
692       if (isU32(cond_n_op, (ARMCondMI << 4) | ARMG_CC_OP_LOGIC)) {
693          /* MI after LOGIC --> test (res >> 31) == 1 */
694          return unop(Iop_1Uto32,
695                      binop(Iop_CmpEQ32,
696                            binop(Iop_Shr32, cc_dep1, mkU8(31)),
697                            mkU32(1)));
698       }
699 
700       /*---------------- COPY ----------------*/
701 
702       if (isU32(cond_n_op, (ARMCondNE << 4) | ARMG_CC_OP_COPY)) {
703          /* NE after COPY --> ((cc_dep1 >> ARMG_CC_SHIFT_Z) ^ 1) & 1 */
704          return binop(Iop_And32,
705                       binop(Iop_Xor32,
706                             binop(Iop_Shr32, cc_dep1,
707                                              mkU8(ARMG_CC_SHIFT_Z)),
708                             mkU32(1)),
709                       mkU32(1));
710       }
711 
712       /*----------------- AL -----------------*/
713 
714       /* A critically important case for Thumb code.
715 
716          What we're trying to spot is the case where cond_n_op is an
717          expression of the form Or32(..., 0xE0) since that means the
718          caller is asking for CondAL and we can simply return 1
719          without caring what the ... part is.  This is a potentially
720          dodgy kludge in that it assumes that the ... part has zeroes
721          in bits 7:4, so that the result of the Or32 is guaranteed to
722          be 0xE in bits 7:4.  Given that the places where this first
723          arg are constructed (in guest_arm_toIR.c) are very
724          constrained, we can get away with this.  To make this
725          guaranteed safe would require to have a new primop, Slice44
726          or some such, thusly
727 
728          Slice44(arg1, arg2) = 0--(24)--0 arg1[7:4] arg2[3:0]
729 
730          and we would then look for Slice44(0xE0, ...)
731          which would give the required safety property.
732 
733          It would be infeasibly expensive to scan backwards through
734          the entire block looking for an assignment to the temp, so
735          just look at the previous 16 statements.  That should find it
736          if it is an interesting case, as a result of how the
737          boilerplate guff at the start of each Thumb insn translation
738          is made.
739       */
740       if (cond_n_op->tag == Iex_RdTmp) {
741          Int    j;
742          IRTemp look_for = cond_n_op->Iex.RdTmp.tmp;
743          Int    limit    = n_precedingStmts - 16;
744          if (limit < 0) limit = 0;
745          if (0) vex_printf("scanning %d .. %d\n", n_precedingStmts-1, limit);
746          for (j = n_precedingStmts - 1; j >= limit; j--) {
747             IRStmt* st = precedingStmts[j];
748             if (st->tag == Ist_WrTmp
749                 && st->Ist.WrTmp.tmp == look_for
750                 && st->Ist.WrTmp.data->tag == Iex_Binop
751                 && st->Ist.WrTmp.data->Iex.Binop.op == Iop_Or32
752                 && isU32(st->Ist.WrTmp.data->Iex.Binop.arg2, (ARMCondAL << 4)))
753                return mkU32(1);
754          }
755          /* Didn't find any useful binding to the first arg
756             in the previous 16 stmts. */
757       }
758    }
759 
760    /* --------- specialising "armg_calculate_flag_c" --------- */
761 
762    else
763    if (vex_streq(function_name, "armg_calculate_flag_c")) {
764 
765       /* specialise calls to the "armg_calculate_flag_c" function.
766          Note that the returned value must be either 0 or 1; nonzero
767          bits 31:1 are not allowed.  In turn, incoming oldV and oldC
768          values (from the thunk) are assumed to have bits 31:1
769          clear. */
770       IRExpr *cc_op, *cc_dep1, *cc_dep2, *cc_ndep;
771       vassert(arity == 4);
772       cc_op   = args[0]; /* ARMG_CC_OP_* */
773       cc_dep1 = args[1];
774       cc_dep2 = args[2];
775       cc_ndep = args[3];
776 
777       if (isU32(cc_op, ARMG_CC_OP_LOGIC)) {
778          /* Thunk args are (result, shco, oldV) */
779          /* C after LOGIC --> shco */
780          return cc_dep2;
781       }
782 
783       if (isU32(cc_op, ARMG_CC_OP_SUB)) {
784          /* Thunk args are (argL, argR, unused) */
785          /* C after SUB --> argL >=u argR
786                         --> argR <=u argL */
787          return unop(Iop_1Uto32,
788                      binop(Iop_CmpLE32U, cc_dep2, cc_dep1));
789       }
790 
791       if (isU32(cc_op, ARMG_CC_OP_SBB)) {
792          /* This happens occasionally in softfloat code, eg __divdf3+140 */
793          /* thunk is: (dep1=argL, dep2=argR, ndep=oldC) */
794          /* C after SBB (same as HS after SBB above)
795             --> oldC ? (argL >=u argR) : (argL >u argR)
796             --> oldC ? (argR <=u argL) : (argR <u argL)
797          */
798          return
799             IRExpr_Mux0X(
800                unop(Iop_32to8, cc_ndep),
801                /* case oldC == 0 */
802                unop(Iop_1Uto32, binop(Iop_CmpLT32U, cc_dep2, cc_dep1)),
803                /* case oldC != 0 */
804                unop(Iop_1Uto32, binop(Iop_CmpLE32U, cc_dep2, cc_dep1))
805             );
806       }
807 
808    }
809 
810    /* --------- specialising "armg_calculate_flag_v" --------- */
811 
812    else
813    if (vex_streq(function_name, "armg_calculate_flag_v")) {
814 
815       /* specialise calls to the "armg_calculate_flag_v" function.
816          Note that the returned value must be either 0 or 1; nonzero
817          bits 31:1 are not allowed.  In turn, incoming oldV and oldC
818          values (from the thunk) are assumed to have bits 31:1
819          clear. */
820       IRExpr *cc_op, *cc_dep1, *cc_dep2, *cc_ndep;
821       vassert(arity == 4);
822       cc_op   = args[0]; /* ARMG_CC_OP_* */
823       cc_dep1 = args[1];
824       cc_dep2 = args[2];
825       cc_ndep = args[3];
826 
827       if (isU32(cc_op, ARMG_CC_OP_LOGIC)) {
828          /* Thunk args are (result, shco, oldV) */
829          /* V after LOGIC --> oldV */
830          return cc_ndep;
831       }
832 
833       if (isU32(cc_op, ARMG_CC_OP_SUB)) {
834          /* Thunk args are (argL, argR, unused) */
835          /* V after SUB
836             --> let res = argL - argR
837                 in ((argL ^ argR) & (argL ^ res)) >> 31
838             --> ((argL ^ argR) & (argL ^ (argL - argR))) >> 31
839          */
840          IRExpr* argL = cc_dep1;
841          IRExpr* argR = cc_dep2;
842          return
843             binop(Iop_Shr32,
844                   binop(Iop_And32,
845                         binop(Iop_Xor32, argL, argR),
846                         binop(Iop_Xor32, argL, binop(Iop_Sub32, argL, argR))
847                   ),
848                   mkU8(31)
849             );
850       }
851 
852       if (isU32(cc_op, ARMG_CC_OP_SBB)) {
853          /* This happens occasionally in softfloat code, eg __divdf3+140 */
854          /* thunk is: (dep1=argL, dep2=argR, ndep=oldC) */
855          /* V after SBB
856             --> let res = argL - argR - (oldC ^ 1)
857                 in  (argL ^ argR) & (argL ^ res) & 1
858          */
859          return
860             binop(
861                Iop_And32,
862                binop(
863                   Iop_And32,
864                   // argL ^ argR
865                   binop(Iop_Xor32, cc_dep1, cc_dep2),
866                   // argL ^ (argL - argR - (oldC ^ 1))
867                   binop(Iop_Xor32,
868                         cc_dep1,
869                         binop(Iop_Sub32,
870                               binop(Iop_Sub32, cc_dep1, cc_dep2),
871                               binop(Iop_Xor32, cc_ndep, mkU32(1)))
872                   )
873                ),
874                mkU32(1)
875             );
876       }
877 
878    }
879 
880 #  undef unop
881 #  undef binop
882 #  undef mkU32
883 #  undef mkU8
884 
885    return NULL;
886 }
887 
888 
889 /*----------------------------------------------*/
890 /*--- The exported fns ..                    ---*/
891 /*----------------------------------------------*/
892 
893 /* VISIBLE TO LIBVEX CLIENT */
894 #if 0
895 void LibVEX_GuestARM_put_flags ( UInt flags_native,
896                                  /*OUT*/VexGuestARMState* vex_state )
897 {
898    vassert(0); // FIXME
899 
900    /* Mask out everything except N Z V C. */
901    flags_native
902       &= (ARMG_CC_MASK_N | ARMG_CC_MASK_Z | ARMG_CC_MASK_V | ARMG_CC_MASK_C);
903 
904    vex_state->guest_CC_OP   = ARMG_CC_OP_COPY;
905    vex_state->guest_CC_DEP1 = flags_native;
906    vex_state->guest_CC_DEP2 = 0;
907    vex_state->guest_CC_NDEP = 0;
908 }
909 #endif
910 
911 /* VISIBLE TO LIBVEX CLIENT */
LibVEX_GuestARM_get_cpsr(VexGuestARMState * vex_state)912 UInt LibVEX_GuestARM_get_cpsr ( /*IN*/VexGuestARMState* vex_state )
913 {
914    UInt cpsr = 0;
915    // NZCV
916    cpsr |= armg_calculate_flags_nzcv(
917                vex_state->guest_CC_OP,
918                vex_state->guest_CC_DEP1,
919                vex_state->guest_CC_DEP2,
920                vex_state->guest_CC_NDEP
921             );
922    vassert(0 == (cpsr & 0x0FFFFFFF));
923    // Q
924    if (vex_state->guest_QFLAG32 > 0)
925       cpsr |= (1 << 27);
926    // GE
927    if (vex_state->guest_GEFLAG0 > 0)
928       cpsr |= (1 << 16);
929    if (vex_state->guest_GEFLAG1 > 0)
930       cpsr |= (1 << 17);
931    if (vex_state->guest_GEFLAG2 > 0)
932       cpsr |= (1 << 18);
933    if (vex_state->guest_GEFLAG3 > 0)
934       cpsr |= (1 << 19);
935    // M
936    cpsr |= (1 << 4); // 0b10000 means user-mode
937    // J,T   J (bit 24) is zero by initialisation above
938    // T  we copy from R15T[0]
939    if (vex_state->guest_R15T & 1)
940       cpsr |= (1 << 5);
941    // ITSTATE we punt on for the time being.  Could compute it
942    // if needed though.
943    // E, endianness, 0 (littleendian) from initialisation above
944    // A,I,F disable some async exceptions.  Not sure about these.
945    // Leave as zero for the time being.
946    return cpsr;
947 }
948 
949 /* VISIBLE TO LIBVEX CLIENT */
LibVEX_GuestARM_initialise(VexGuestARMState * vex_state)950 void LibVEX_GuestARM_initialise ( /*OUT*/VexGuestARMState* vex_state )
951 {
952    vex_state->host_EvC_FAILADDR = 0;
953    vex_state->host_EvC_COUNTER = 0;
954 
955    vex_state->guest_R0  = 0;
956    vex_state->guest_R1  = 0;
957    vex_state->guest_R2  = 0;
958    vex_state->guest_R3  = 0;
959    vex_state->guest_R4  = 0;
960    vex_state->guest_R5  = 0;
961    vex_state->guest_R6  = 0;
962    vex_state->guest_R7  = 0;
963    vex_state->guest_R8  = 0;
964    vex_state->guest_R9  = 0;
965    vex_state->guest_R10 = 0;
966    vex_state->guest_R11 = 0;
967    vex_state->guest_R12 = 0;
968    vex_state->guest_R13 = 0;
969    vex_state->guest_R14 = 0;
970    vex_state->guest_R15T = 0;  /* NB: implies ARM mode */
971 
972    vex_state->guest_CC_OP   = ARMG_CC_OP_COPY;
973    vex_state->guest_CC_DEP1 = 0;
974    vex_state->guest_CC_DEP2 = 0;
975    vex_state->guest_CC_NDEP = 0;
976    vex_state->guest_QFLAG32 = 0;
977    vex_state->guest_GEFLAG0 = 0;
978    vex_state->guest_GEFLAG1 = 0;
979    vex_state->guest_GEFLAG2 = 0;
980    vex_state->guest_GEFLAG3 = 0;
981 
982    vex_state->guest_EMWARN  = 0;
983    vex_state->guest_TISTART = 0;
984    vex_state->guest_TILEN   = 0;
985    vex_state->guest_NRADDR  = 0;
986    vex_state->guest_IP_AT_SYSCALL = 0;
987 
988    vex_state->guest_D0  = 0;
989    vex_state->guest_D1  = 0;
990    vex_state->guest_D2  = 0;
991    vex_state->guest_D3  = 0;
992    vex_state->guest_D4  = 0;
993    vex_state->guest_D5  = 0;
994    vex_state->guest_D6  = 0;
995    vex_state->guest_D7  = 0;
996    vex_state->guest_D8  = 0;
997    vex_state->guest_D9  = 0;
998    vex_state->guest_D10 = 0;
999    vex_state->guest_D11 = 0;
1000    vex_state->guest_D12 = 0;
1001    vex_state->guest_D13 = 0;
1002    vex_state->guest_D14 = 0;
1003    vex_state->guest_D15 = 0;
1004    vex_state->guest_D16 = 0;
1005    vex_state->guest_D17 = 0;
1006    vex_state->guest_D18 = 0;
1007    vex_state->guest_D19 = 0;
1008    vex_state->guest_D20 = 0;
1009    vex_state->guest_D21 = 0;
1010    vex_state->guest_D22 = 0;
1011    vex_state->guest_D23 = 0;
1012    vex_state->guest_D24 = 0;
1013    vex_state->guest_D25 = 0;
1014    vex_state->guest_D26 = 0;
1015    vex_state->guest_D27 = 0;
1016    vex_state->guest_D28 = 0;
1017    vex_state->guest_D29 = 0;
1018    vex_state->guest_D30 = 0;
1019    vex_state->guest_D31 = 0;
1020 
1021    /* ARM encoded; zero is the default as it happens (result flags
1022       (NZCV) cleared, FZ disabled, round to nearest, non-vector mode,
1023       all exns masked, all exn sticky bits cleared). */
1024    vex_state->guest_FPSCR = 0;
1025 
1026    vex_state->guest_TPIDRURO = 0;
1027 
1028    /* Not in a Thumb IT block. */
1029    vex_state->guest_ITSTATE = 0;
1030 
1031    vex_state->padding1 = 0;
1032    vex_state->padding2 = 0;
1033    vex_state->padding3 = 0;
1034    vex_state->padding4 = 0;
1035    vex_state->padding5 = 0;
1036 }
1037 
1038 
1039 /*-----------------------------------------------------------*/
1040 /*--- Describing the arm guest state, for the benefit     ---*/
1041 /*--- of iropt and instrumenters.                         ---*/
1042 /*-----------------------------------------------------------*/
1043 
1044 /* Figure out if any part of the guest state contained in minoff
1045    .. maxoff requires precise memory exceptions.  If in doubt return
1046    True (but this is generates significantly slower code).
1047 
1048    We enforce precise exns for guest R13(sp), R15T(pc).
1049 */
guest_arm_state_requires_precise_mem_exns(Int minoff,Int maxoff)1050 Bool 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    } else {
1061       return True;
1062    }
1063 
1064    if (maxoff < pc_min || minoff > pc_max) {
1065       /* no overlap with pc */
1066    } else {
1067       return True;
1068    }
1069 
1070    /* We appear to need precise updates of R11 in order to get proper
1071       stacktraces from non-optimised code. */
1072    Int r11_min = offsetof(VexGuestARMState, guest_R11);
1073    Int r11_max = r11_min + 4 - 1;
1074 
1075    if (maxoff < r11_min || minoff > r11_max) {
1076       /* no overlap with r11 */
1077    } else {
1078       return True;
1079    }
1080 
1081    /* Ditto R7, particularly needed for proper stacktraces in Thumb
1082       code. */
1083    Int r7_min = offsetof(VexGuestARMState, guest_R7);
1084    Int r7_max = r7_min + 4 - 1;
1085 
1086    if (maxoff < r7_min || minoff > r7_max) {
1087       /* no overlap with r7 */
1088    } else {
1089       return True;
1090    }
1091 
1092    return False;
1093 }
1094 
1095 
1096 
1097 #define ALWAYSDEFD(field)                           \
1098     { offsetof(VexGuestARMState, field),            \
1099       (sizeof ((VexGuestARMState*)0)->field) }
1100 
1101 VexGuestLayout
1102    armGuest_layout
1103       = {
1104           /* Total size of the guest state, in bytes. */
1105           .total_sizeB = sizeof(VexGuestARMState),
1106 
1107           /* Describe the stack pointer. */
1108           .offset_SP = offsetof(VexGuestARMState,guest_R13),
1109           .sizeof_SP = 4,
1110 
1111           /* Describe the instruction pointer. */
1112           .offset_IP = offsetof(VexGuestARMState,guest_R15T),
1113           .sizeof_IP = 4,
1114 
1115           /* Describe any sections to be regarded by Memcheck as
1116              'always-defined'. */
1117           .n_alwaysDefd = 10,
1118 
1119           /* flags thunk: OP is always defd, whereas DEP1 and DEP2
1120              have to be tracked.  See detailed comment in gdefs.h on
1121              meaning of thunk fields. */
1122           .alwaysDefd
1123              = { /* 0 */ ALWAYSDEFD(guest_R15T),
1124                  /* 1 */ ALWAYSDEFD(guest_CC_OP),
1125                  /* 2 */ ALWAYSDEFD(guest_CC_NDEP),
1126                  /* 3 */ ALWAYSDEFD(guest_EMWARN),
1127                  /* 4 */ ALWAYSDEFD(guest_TISTART),
1128                  /* 5 */ ALWAYSDEFD(guest_TILEN),
1129                  /* 6 */ ALWAYSDEFD(guest_NRADDR),
1130                  /* 7 */ ALWAYSDEFD(guest_IP_AT_SYSCALL),
1131                  /* 8 */ ALWAYSDEFD(guest_TPIDRURO),
1132                  /* 9 */ ALWAYSDEFD(guest_ITSTATE)
1133                }
1134         };
1135 
1136 
1137 /*---------------------------------------------------------------*/
1138 /*--- end                                 guest_arm_helpers.c ---*/
1139 /*---------------------------------------------------------------*/
1140