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