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
55 /* generalised left-shifter */
lshift(UInt x,Int n)56 static inline UInt lshift ( UInt x, Int n )
57 {
58 if (n >= 0)
59 return x << n;
60 else
61 return x >> (-n);
62 }
63
64
65 /* CALLED FROM GENERATED CODE: CLEAN HELPER */
66 /* Calculate NZCV from the supplied thunk components, in the positions
67 they appear in the CPSR, viz bits 31:28 for N Z C V respectively.
68 Returned bits 27:0 are zero. */
armg_calculate_flags_nzcv(UInt cc_op,UInt cc_dep1,UInt cc_dep2,UInt cc_dep3)69 UInt armg_calculate_flags_nzcv ( UInt cc_op, UInt cc_dep1,
70 UInt cc_dep2, UInt cc_dep3 )
71 {
72 switch (cc_op) {
73 case ARMG_CC_OP_COPY:
74 /* (nzcv, unused, unused) */
75 return cc_dep1;
76 case ARMG_CC_OP_ADD: {
77 /* (argL, argR, unused) */
78 UInt argL = cc_dep1;
79 UInt argR = cc_dep2;
80 UInt res = argL + argR;
81 UInt nf = lshift( res & (1<<31), ARMG_CC_SHIFT_N - 31 );
82 UInt zf = lshift( res == 0, ARMG_CC_SHIFT_Z );
83 // CF and VF need verification
84 UInt cf = lshift( res < argL, ARMG_CC_SHIFT_C );
85 UInt vf = lshift( (res ^ argL) & (res ^ argR),
86 ARMG_CC_SHIFT_V + 1 - 32 )
87 & ARMG_CC_MASK_V;
88 //vex_printf("%08x %08x -> n %x z %x c %x v %x\n",
89 // argL, argR, nf, zf, cf, vf);
90 return nf | zf | cf | vf;
91 }
92 case ARMG_CC_OP_SUB: {
93 /* (argL, argR, unused) */
94 UInt argL = cc_dep1;
95 UInt argR = cc_dep2;
96 UInt res = argL - argR;
97 UInt nf = lshift( res & (1<<31), ARMG_CC_SHIFT_N - 31 );
98 UInt zf = lshift( res == 0, ARMG_CC_SHIFT_Z );
99 // XXX cf is inverted relative to normal sense
100 UInt cf = lshift( argL >= argR, ARMG_CC_SHIFT_C );
101 UInt vf = lshift( (argL ^ argR) & (argL ^ res),
102 ARMG_CC_SHIFT_V + 1 - 32 )
103 & ARMG_CC_MASK_V;
104 //vex_printf("%08x %08x -> n %x z %x c %x v %x\n",
105 // argL, argR, nf, zf, cf, vf);
106 return nf | zf | cf | vf;
107 }
108 case ARMG_CC_OP_ADC: {
109 /* (argL, argR, oldC) */
110 UInt argL = cc_dep1;
111 UInt argR = cc_dep2;
112 UInt oldC = cc_dep3;
113 UInt res = (argL + argR) + oldC;
114 UInt nf = lshift( res & (1<<31), ARMG_CC_SHIFT_N - 31 );
115 UInt zf = lshift( res == 0, ARMG_CC_SHIFT_Z );
116 UInt cf = oldC ? lshift( res <= argL, ARMG_CC_SHIFT_C )
117 : lshift( res < argL, ARMG_CC_SHIFT_C );
118 UInt vf = lshift( (res ^ argL) & (res ^ argR),
119 ARMG_CC_SHIFT_V + 1 - 32 )
120 & ARMG_CC_MASK_V;
121 //vex_printf("%08x %08x -> n %x z %x c %x v %x\n",
122 // argL, argR, nf, zf, cf, vf);
123 return nf | zf | cf | vf;
124 }
125 case ARMG_CC_OP_SBB: {
126 /* (argL, argR, oldC) */
127 UInt argL = cc_dep1;
128 UInt argR = cc_dep2;
129 UInt oldC = cc_dep3;
130 UInt res = argL - argR - (oldC ^ 1);
131 UInt nf = lshift( res & (1<<31), ARMG_CC_SHIFT_N - 31 );
132 UInt zf = lshift( res == 0, ARMG_CC_SHIFT_Z );
133 UInt cf = oldC ? lshift( argL >= argR, ARMG_CC_SHIFT_C )
134 : lshift( argL > argR, ARMG_CC_SHIFT_C );
135 UInt vf = lshift( (argL ^ argR) & (argL ^ res),
136 ARMG_CC_SHIFT_V + 1 - 32 )
137 & ARMG_CC_MASK_V;
138 //vex_printf("%08x %08x -> n %x z %x c %x v %x\n",
139 // argL, argR, nf, zf, cf, vf);
140 return nf | zf | cf | vf;
141 }
142 case ARMG_CC_OP_LOGIC: {
143 /* (res, shco, oldV) */
144 UInt res = cc_dep1;
145 UInt shco = cc_dep2;
146 UInt oldV = cc_dep3;
147 UInt nf = lshift( res & (1<<31), ARMG_CC_SHIFT_N - 31 );
148 UInt zf = lshift( res == 0, ARMG_CC_SHIFT_Z );
149 UInt cf = lshift( shco & 1, ARMG_CC_SHIFT_C );
150 UInt vf = lshift( oldV & 1, ARMG_CC_SHIFT_V );
151 return nf | zf | cf | vf;
152 }
153 case ARMG_CC_OP_MUL: {
154 /* (res, unused, oldC:oldV) */
155 UInt res = cc_dep1;
156 UInt oldC = (cc_dep3 >> 1) & 1;
157 UInt oldV = (cc_dep3 >> 0) & 1;
158 UInt nf = lshift( res & (1<<31), ARMG_CC_SHIFT_N - 31 );
159 UInt zf = lshift( res == 0, ARMG_CC_SHIFT_Z );
160 UInt cf = lshift( oldC & 1, ARMG_CC_SHIFT_C );
161 UInt vf = lshift( oldV & 1, ARMG_CC_SHIFT_V );
162 return nf | zf | cf | vf;
163 }
164 case ARMG_CC_OP_MULL: {
165 /* (resLo32, resHi32, oldC:oldV) */
166 UInt resLo32 = cc_dep1;
167 UInt resHi32 = cc_dep2;
168 UInt oldC = (cc_dep3 >> 1) & 1;
169 UInt oldV = (cc_dep3 >> 0) & 1;
170 UInt nf = lshift( resHi32 & (1<<31), ARMG_CC_SHIFT_N - 31 );
171 UInt zf = lshift( (resHi32|resLo32) == 0, ARMG_CC_SHIFT_Z );
172 UInt cf = lshift( oldC & 1, ARMG_CC_SHIFT_C );
173 UInt vf = lshift( oldV & 1, ARMG_CC_SHIFT_V );
174 return nf | zf | cf | vf;
175 }
176 default:
177 /* shouldn't really make these calls from generated code */
178 vex_printf("armg_calculate_flags_nzcv"
179 "( op=%u, dep1=0x%x, dep2=0x%x, dep3=0x%x )\n",
180 cc_op, cc_dep1, cc_dep2, cc_dep3 );
181 vpanic("armg_calculate_flags_nzcv");
182 }
183 }
184
185
186 /* CALLED FROM GENERATED CODE: CLEAN HELPER */
187 /* Calculate the C flag from the thunk components, in the lowest bit
188 of the word (bit 0). */
armg_calculate_flag_c(UInt cc_op,UInt cc_dep1,UInt cc_dep2,UInt cc_dep3)189 UInt armg_calculate_flag_c ( UInt cc_op, UInt cc_dep1,
190 UInt cc_dep2, UInt cc_dep3 )
191 {
192 UInt r = armg_calculate_flags_nzcv(cc_op, cc_dep1, cc_dep2, cc_dep3);
193 return (r >> ARMG_CC_SHIFT_C) & 1;
194 }
195
196
197 /* CALLED FROM GENERATED CODE: CLEAN HELPER */
198 /* Calculate the V flag from the thunk components, in the lowest bit
199 of the word (bit 0). */
armg_calculate_flag_v(UInt cc_op,UInt cc_dep1,UInt cc_dep2,UInt cc_dep3)200 UInt armg_calculate_flag_v ( UInt cc_op, UInt cc_dep1,
201 UInt cc_dep2, UInt cc_dep3 )
202 {
203 UInt r = armg_calculate_flags_nzcv(cc_op, cc_dep1, cc_dep2, cc_dep3);
204 return (r >> ARMG_CC_SHIFT_V) & 1;
205 }
206
207 /* CALLED FROM GENERATED CODE: CLEAN HELPER */
208 /* Calculate the QC flag from the arguments, in the lowest bit
209 of the word (bit 0). Urr, having this out of line is bizarre.
210 Push back inline. */
armg_calculate_flag_qc(UInt resL1,UInt resL2,UInt resR1,UInt resR2)211 UInt armg_calculate_flag_qc ( UInt resL1, UInt resL2,
212 UInt resR1, UInt resR2 )
213 {
214 if (resL1 != resR1 || resL2 != resR2)
215 return 1;
216 else
217 return 0;
218 }
219
220 /* CALLED FROM GENERATED CODE: CLEAN HELPER */
221 /* Calculate the specified condition from the thunk components, in the
222 lowest bit of the word (bit 0). */
223 extern
armg_calculate_condition(UInt cond_n_op,UInt cc_dep1,UInt cc_dep2,UInt cc_dep3)224 UInt armg_calculate_condition ( UInt cond_n_op /* ARMCondcode << 4 | cc_op */,
225 UInt cc_dep1,
226 UInt cc_dep2, UInt cc_dep3 )
227 {
228 UInt cond = cond_n_op >> 4;
229 UInt cc_op = cond_n_op & 0xF;
230 UInt nf, zf, vf, cf, nzcv, inv;
231 // vex_printf("XXXXXXXX %x %x %x %x\n",
232 // cond_n_op, cc_dep1, cc_dep2, cc_dep3);
233
234 // skip flags computation in this case
235 if (cond == ARMCondAL) return 1;
236
237 inv = cond & 1;
238 nzcv = armg_calculate_flags_nzcv(cc_op, cc_dep1, cc_dep2, cc_dep3);
239
240 switch (cond) {
241 case ARMCondEQ: // Z=1 => z
242 case ARMCondNE: // Z=0
243 zf = nzcv >> ARMG_CC_SHIFT_Z;
244 return 1 & (inv ^ zf);
245
246 case ARMCondHS: // C=1 => c
247 case ARMCondLO: // C=0
248 cf = nzcv >> ARMG_CC_SHIFT_C;
249 return 1 & (inv ^ cf);
250
251 case ARMCondMI: // N=1 => n
252 case ARMCondPL: // N=0
253 nf = nzcv >> ARMG_CC_SHIFT_N;
254 return 1 & (inv ^ nf);
255
256 case ARMCondVS: // V=1 => v
257 case ARMCondVC: // V=0
258 vf = nzcv >> ARMG_CC_SHIFT_V;
259 return 1 & (inv ^ vf);
260
261 case ARMCondHI: // C=1 && Z=0 => c & ~z
262 case ARMCondLS: // C=0 || Z=1
263 cf = nzcv >> ARMG_CC_SHIFT_C;
264 zf = nzcv >> ARMG_CC_SHIFT_Z;
265 return 1 & (inv ^ (cf & ~zf));
266
267 case ARMCondGE: // N=V => ~(n^v)
268 case ARMCondLT: // N!=V
269 nf = nzcv >> ARMG_CC_SHIFT_N;
270 vf = nzcv >> ARMG_CC_SHIFT_V;
271 return 1 & (inv ^ ~(nf ^ vf));
272
273 case ARMCondGT: // Z=0 && N=V => ~z & ~(n^v) => ~(z | (n^v))
274 case ARMCondLE: // Z=1 || N!=V
275 nf = nzcv >> ARMG_CC_SHIFT_N;
276 vf = nzcv >> ARMG_CC_SHIFT_V;
277 zf = nzcv >> ARMG_CC_SHIFT_Z;
278 return 1 & (inv ^ ~(zf | (nf ^ vf)));
279
280 case ARMCondAL: // handled above
281 case ARMCondNV: // should never get here: Illegal instr
282 default:
283 /* shouldn't really make these calls from generated code */
284 vex_printf("armg_calculate_condition(ARM)"
285 "( %u, %u, 0x%x, 0x%x, 0x%x )\n",
286 cond, cc_op, cc_dep1, cc_dep2, cc_dep3 );
287 vpanic("armg_calculate_condition(ARM)");
288 }
289 }
290
291
292 /*---------------------------------------------------------------*/
293 /*--- Flag-helpers translation-time function specialisers. ---*/
294 /*--- These help iropt specialise calls the above run-time ---*/
295 /*--- flags functions. ---*/
296 /*---------------------------------------------------------------*/
297
298 /* Used by the optimiser to try specialisations. Returns an
299 equivalent expression, or NULL if none. */
300
isU32(IRExpr * e,UInt n)301 static Bool isU32 ( IRExpr* e, UInt n )
302 {
303 return
304 toBool( e->tag == Iex_Const
305 && e->Iex.Const.con->tag == Ico_U32
306 && e->Iex.Const.con->Ico.U32 == n );
307 }
308
guest_arm_spechelper(HChar * function_name,IRExpr ** args,IRStmt ** precedingStmts,Int n_precedingStmts)309 IRExpr* guest_arm_spechelper ( HChar* function_name,
310 IRExpr** args,
311 IRStmt** precedingStmts,
312 Int n_precedingStmts )
313 {
314 # define unop(_op,_a1) IRExpr_Unop((_op),(_a1))
315 # define binop(_op,_a1,_a2) IRExpr_Binop((_op),(_a1),(_a2))
316 # define mkU32(_n) IRExpr_Const(IRConst_U32(_n))
317 # define mkU8(_n) IRExpr_Const(IRConst_U8(_n))
318
319 Int i, arity = 0;
320 for (i = 0; args[i]; i++)
321 arity++;
322 # if 0
323 vex_printf("spec request:\n");
324 vex_printf(" %s ", function_name);
325 for (i = 0; i < arity; i++) {
326 vex_printf(" ");
327 ppIRExpr(args[i]);
328 }
329 vex_printf("\n");
330 # endif
331
332 /* --------- specialising "armg_calculate_condition" --------- */
333
334 if (vex_streq(function_name, "armg_calculate_condition")) {
335 /* specialise calls to above "armg_calculate condition" function */
336 IRExpr *cond_n_op, *cc_dep1, *cc_dep2, *cc_dep3;
337 vassert(arity == 4);
338 cond_n_op = args[0]; /* ARMCondcode << 4 | ARMG_CC_OP_* */
339 cc_dep1 = args[1];
340 cc_dep2 = args[2];
341 cc_dep3 = args[3];
342
343 /*---------------- SUB ----------------*/
344
345 if (isU32(cond_n_op, (ARMCondEQ << 4) | ARMG_CC_OP_SUB)) {
346 /* EQ after SUB --> test argL == argR */
347 return unop(Iop_1Uto32,
348 binop(Iop_CmpEQ32, cc_dep1, cc_dep2));
349 }
350 if (isU32(cond_n_op, (ARMCondNE << 4) | ARMG_CC_OP_SUB)) {
351 /* NE after SUB --> test argL != argR */
352 return unop(Iop_1Uto32,
353 binop(Iop_CmpNE32, cc_dep1, cc_dep2));
354 }
355
356 if (isU32(cond_n_op, (ARMCondLE << 4) | ARMG_CC_OP_SUB)) {
357 /* LE after SUB --> test argL <=s argR */
358 return unop(Iop_1Uto32,
359 binop(Iop_CmpLE32S, cc_dep1, cc_dep2));
360 }
361
362 if (isU32(cond_n_op, (ARMCondLT << 4) | ARMG_CC_OP_SUB)) {
363 /* LT after SUB --> test argL <s argR */
364 return unop(Iop_1Uto32,
365 binop(Iop_CmpLT32S, cc_dep1, cc_dep2));
366 }
367
368 if (isU32(cond_n_op, (ARMCondGE << 4) | ARMG_CC_OP_SUB)) {
369 /* GE after SUB --> test argL >=s argR
370 --> test argR <=s argL */
371 return unop(Iop_1Uto32,
372 binop(Iop_CmpLE32S, cc_dep2, cc_dep1));
373 }
374
375 if (isU32(cond_n_op, (ARMCondHS << 4) | ARMG_CC_OP_SUB)) {
376 /* HS after SUB --> test argL >=u argR
377 --> test argR <=u argL */
378 return unop(Iop_1Uto32,
379 binop(Iop_CmpLE32U, cc_dep2, cc_dep1));
380 }
381
382 if (isU32(cond_n_op, (ARMCondLS << 4) | ARMG_CC_OP_SUB)) {
383 /* LS after SUB --> test argL <=u argR */
384 return unop(Iop_1Uto32,
385 binop(Iop_CmpLE32U, cc_dep1, cc_dep2));
386 }
387
388 /*---------------- LOGIC ----------------*/
389 if (isU32(cond_n_op, (ARMCondEQ << 4) | ARMG_CC_OP_LOGIC)) {
390 /* EQ after LOGIC --> test res == 0 */
391 return unop(Iop_1Uto32,
392 binop(Iop_CmpEQ32, cc_dep1, mkU32(0)));
393 }
394 if (isU32(cond_n_op, (ARMCondNE << 4) | ARMG_CC_OP_LOGIC)) {
395 /* NE after LOGIC --> test res != 0 */
396 return unop(Iop_1Uto32,
397 binop(Iop_CmpNE32, cc_dep1, mkU32(0)));
398 }
399
400 /*----------------- AL -----------------*/
401 /* A critically important case for Thumb code.
402
403 What we're trying to spot is the case where cond_n_op is an
404 expression of the form Or32(..., 0xE0) since that means the
405 caller is asking for CondAL and we can simply return 1
406 without caring what the ... part is. This is a potentially
407 dodgy kludge in that it assumes that the ... part has zeroes
408 in bits 7:4, so that the result of the Or32 is guaranteed to
409 be 0xE in bits 7:4. Given that the places where this first
410 arg are constructed (in guest_arm_toIR.c) are very
411 constrained, we can get away with this. To make this
412 guaranteed safe would require to have a new primop, Slice44
413 or some such, thusly
414
415 Slice44(arg1, arg2) = 0--(24)--0 arg1[7:4] arg2[3:0]
416
417 and we would then look for Slice44(0xE0, ...)
418 which would give the required safety property.
419
420 It would be infeasibly expensive to scan backwards through
421 the entire block looking for an assignment to the temp, so
422 just look at the previous 16 statements. That should find it
423 if it is an interesting case, as a result of how the
424 boilerplate guff at the start of each Thumb insn translation
425 is made.
426 */
427 if (cond_n_op->tag == Iex_RdTmp) {
428 Int j;
429 IRTemp look_for = cond_n_op->Iex.RdTmp.tmp;
430 Int limit = n_precedingStmts - 16;
431 if (limit < 0) limit = 0;
432 if (0) vex_printf("scanning %d .. %d\n", n_precedingStmts-1, limit);
433 for (j = n_precedingStmts - 1; j >= limit; j--) {
434 IRStmt* st = precedingStmts[j];
435 if (st->tag == Ist_WrTmp
436 && st->Ist.WrTmp.tmp == look_for
437 && st->Ist.WrTmp.data->tag == Iex_Binop
438 && st->Ist.WrTmp.data->Iex.Binop.op == Iop_Or32
439 && isU32(st->Ist.WrTmp.data->Iex.Binop.arg2, (ARMCondAL << 4)))
440 return mkU32(1);
441 }
442 /* Didn't find any useful binding to the first arg
443 in the previous 16 stmts. */
444 }
445 }
446
447 # undef unop
448 # undef binop
449 # undef mkU32
450 # undef mkU8
451
452 return NULL;
453 }
454
455
456 /*----------------------------------------------*/
457 /*--- The exported fns .. ---*/
458 /*----------------------------------------------*/
459
460 /* VISIBLE TO LIBVEX CLIENT */
461 #if 0
462 void LibVEX_GuestARM_put_flags ( UInt flags_native,
463 /*OUT*/VexGuestARMState* vex_state )
464 {
465 vassert(0); // FIXME
466
467 /* Mask out everything except N Z V C. */
468 flags_native
469 &= (ARMG_CC_MASK_N | ARMG_CC_MASK_Z | ARMG_CC_MASK_V | ARMG_CC_MASK_C);
470
471 vex_state->guest_CC_OP = ARMG_CC_OP_COPY;
472 vex_state->guest_CC_DEP1 = flags_native;
473 vex_state->guest_CC_DEP2 = 0;
474 vex_state->guest_CC_NDEP = 0;
475 }
476 #endif
477
478 /* VISIBLE TO LIBVEX CLIENT */
LibVEX_GuestARM_get_cpsr(VexGuestARMState * vex_state)479 UInt LibVEX_GuestARM_get_cpsr ( /*IN*/VexGuestARMState* vex_state )
480 {
481 UInt cpsr = 0;
482 // NZCV
483 cpsr |= armg_calculate_flags_nzcv(
484 vex_state->guest_CC_OP,
485 vex_state->guest_CC_DEP1,
486 vex_state->guest_CC_DEP2,
487 vex_state->guest_CC_NDEP
488 );
489 vassert(0 == (cpsr & 0x0FFFFFFF));
490 // Q
491 if (vex_state->guest_QFLAG32 > 0)
492 cpsr |= (1 << 27);
493 // GE
494 if (vex_state->guest_GEFLAG0 > 0)
495 cpsr |= (1 << 16);
496 if (vex_state->guest_GEFLAG1 > 0)
497 cpsr |= (1 << 17);
498 if (vex_state->guest_GEFLAG2 > 0)
499 cpsr |= (1 << 18);
500 if (vex_state->guest_GEFLAG3 > 0)
501 cpsr |= (1 << 19);
502 // M
503 cpsr |= (1 << 4); // 0b10000 means user-mode
504 // J,T J (bit 24) is zero by initialisation above
505 // T we copy from R15T[0]
506 if (vex_state->guest_R15T & 1)
507 cpsr |= (1 << 5);
508 // ITSTATE we punt on for the time being. Could compute it
509 // if needed though.
510 // E, endianness, 0 (littleendian) from initialisation above
511 // A,I,F disable some async exceptions. Not sure about these.
512 // Leave as zero for the time being.
513 return cpsr;
514 }
515
516 /* VISIBLE TO LIBVEX CLIENT */
LibVEX_GuestARM_initialise(VexGuestARMState * vex_state)517 void LibVEX_GuestARM_initialise ( /*OUT*/VexGuestARMState* vex_state )
518 {
519 vex_state->guest_R0 = 0;
520 vex_state->guest_R1 = 0;
521 vex_state->guest_R2 = 0;
522 vex_state->guest_R3 = 0;
523 vex_state->guest_R4 = 0;
524 vex_state->guest_R5 = 0;
525 vex_state->guest_R6 = 0;
526 vex_state->guest_R7 = 0;
527 vex_state->guest_R8 = 0;
528 vex_state->guest_R9 = 0;
529 vex_state->guest_R10 = 0;
530 vex_state->guest_R11 = 0;
531 vex_state->guest_R12 = 0;
532 vex_state->guest_R13 = 0;
533 vex_state->guest_R14 = 0;
534 vex_state->guest_R15T = 0; /* NB: implies ARM mode */
535
536 vex_state->guest_CC_OP = ARMG_CC_OP_COPY;
537 vex_state->guest_CC_DEP1 = 0;
538 vex_state->guest_CC_DEP2 = 0;
539 vex_state->guest_CC_NDEP = 0;
540 vex_state->guest_QFLAG32 = 0;
541 vex_state->guest_GEFLAG0 = 0;
542 vex_state->guest_GEFLAG1 = 0;
543 vex_state->guest_GEFLAG2 = 0;
544 vex_state->guest_GEFLAG3 = 0;
545
546 vex_state->guest_EMWARN = 0;
547 vex_state->guest_TISTART = 0;
548 vex_state->guest_TILEN = 0;
549 vex_state->guest_NRADDR = 0;
550 vex_state->guest_IP_AT_SYSCALL = 0;
551
552 vex_state->guest_D0 = 0;
553 vex_state->guest_D1 = 0;
554 vex_state->guest_D2 = 0;
555 vex_state->guest_D3 = 0;
556 vex_state->guest_D4 = 0;
557 vex_state->guest_D5 = 0;
558 vex_state->guest_D6 = 0;
559 vex_state->guest_D7 = 0;
560 vex_state->guest_D8 = 0;
561 vex_state->guest_D9 = 0;
562 vex_state->guest_D10 = 0;
563 vex_state->guest_D11 = 0;
564 vex_state->guest_D12 = 0;
565 vex_state->guest_D13 = 0;
566 vex_state->guest_D14 = 0;
567 vex_state->guest_D15 = 0;
568 vex_state->guest_D16 = 0;
569 vex_state->guest_D17 = 0;
570 vex_state->guest_D18 = 0;
571 vex_state->guest_D19 = 0;
572 vex_state->guest_D20 = 0;
573 vex_state->guest_D21 = 0;
574 vex_state->guest_D22 = 0;
575 vex_state->guest_D23 = 0;
576 vex_state->guest_D24 = 0;
577 vex_state->guest_D25 = 0;
578 vex_state->guest_D26 = 0;
579 vex_state->guest_D27 = 0;
580 vex_state->guest_D28 = 0;
581 vex_state->guest_D29 = 0;
582 vex_state->guest_D30 = 0;
583 vex_state->guest_D31 = 0;
584
585 /* ARM encoded; zero is the default as it happens (result flags
586 (NZCV) cleared, FZ disabled, round to nearest, non-vector mode,
587 all exns masked, all exn sticky bits cleared). */
588 vex_state->guest_FPSCR = 0;
589
590 vex_state->guest_TPIDRURO = 0;
591
592 /* Not in a Thumb IT block. */
593 vex_state->guest_ITSTATE = 0;
594
595 vex_state->padding1 = 0;
596 vex_state->padding2 = 0;
597 vex_state->padding3 = 0;
598 }
599
600
601 /*-----------------------------------------------------------*/
602 /*--- Describing the arm guest state, for the benefit ---*/
603 /*--- of iropt and instrumenters. ---*/
604 /*-----------------------------------------------------------*/
605
606 /* Figure out if any part of the guest state contained in minoff
607 .. maxoff requires precise memory exceptions. If in doubt return
608 True (but this is generates significantly slower code).
609
610 We enforce precise exns for guest R13(sp), R15T(pc).
611 */
guest_arm_state_requires_precise_mem_exns(Int minoff,Int maxoff)612 Bool guest_arm_state_requires_precise_mem_exns ( Int minoff,
613 Int maxoff)
614 {
615 Int sp_min = offsetof(VexGuestARMState, guest_R13);
616 Int sp_max = sp_min + 4 - 1;
617 Int pc_min = offsetof(VexGuestARMState, guest_R15T);
618 Int pc_max = pc_min + 4 - 1;
619
620 if (maxoff < sp_min || minoff > sp_max) {
621 /* no overlap with sp */
622 } else {
623 return True;
624 }
625
626 if (maxoff < pc_min || minoff > pc_max) {
627 /* no overlap with pc */
628 } else {
629 return True;
630 }
631
632 /* We appear to need precise updates of R11 in order to get proper
633 stacktraces from non-optimised code. */
634 Int r11_min = offsetof(VexGuestARMState, guest_R11);
635 Int r11_max = r11_min + 4 - 1;
636
637 if (maxoff < r11_min || minoff > r11_max) {
638 /* no overlap with r11 */
639 } else {
640 return True;
641 }
642
643 /* Ditto R7, particularly needed for proper stacktraces in Thumb
644 code. */
645 Int r7_min = offsetof(VexGuestARMState, guest_R7);
646 Int r7_max = r7_min + 4 - 1;
647
648 if (maxoff < r7_min || minoff > r7_max) {
649 /* no overlap with r7 */
650 } else {
651 return True;
652 }
653
654 return False;
655 }
656
657
658
659 #define ALWAYSDEFD(field) \
660 { offsetof(VexGuestARMState, field), \
661 (sizeof ((VexGuestARMState*)0)->field) }
662
663 VexGuestLayout
664 armGuest_layout
665 = {
666 /* Total size of the guest state, in bytes. */
667 .total_sizeB = sizeof(VexGuestARMState),
668
669 /* Describe the stack pointer. */
670 .offset_SP = offsetof(VexGuestARMState,guest_R13),
671 .sizeof_SP = 4,
672
673 /* Describe the instruction pointer. */
674 .offset_IP = offsetof(VexGuestARMState,guest_R15T),
675 .sizeof_IP = 4,
676
677 /* Describe any sections to be regarded by Memcheck as
678 'always-defined'. */
679 .n_alwaysDefd = 10,
680
681 /* flags thunk: OP is always defd, whereas DEP1 and DEP2
682 have to be tracked. See detailed comment in gdefs.h on
683 meaning of thunk fields. */
684 .alwaysDefd
685 = { /* 0 */ ALWAYSDEFD(guest_R15T),
686 /* 1 */ ALWAYSDEFD(guest_CC_OP),
687 /* 2 */ ALWAYSDEFD(guest_CC_NDEP),
688 /* 3 */ ALWAYSDEFD(guest_EMWARN),
689 /* 4 */ ALWAYSDEFD(guest_TISTART),
690 /* 5 */ ALWAYSDEFD(guest_TILEN),
691 /* 6 */ ALWAYSDEFD(guest_NRADDR),
692 /* 7 */ ALWAYSDEFD(guest_IP_AT_SYSCALL),
693 /* 8 */ ALWAYSDEFD(guest_TPIDRURO),
694 /* 9 */ ALWAYSDEFD(guest_ITSTATE)
695 }
696 };
697
698
699 /*---------------------------------------------------------------*/
700 /*--- end guest_arm_helpers.c ---*/
701 /*---------------------------------------------------------------*/
702