2 /*---------------------------------------------------------------*/
3 /*--- begin guest_arm_helpers.c ---*/
4 /*---------------------------------------------------------------*/
7 This file is part of Valgrind, a dynamic binary instrumentation
10 Copyright (C) 2004-2010 OpenWorks LLP
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.
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.
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
28 The GNU General Public License is contained in the file COPYING.
31 #include "libvex_basictypes.h"
32 #include "libvex_emwarn.h"
33 #include "libvex_guest_arm.h"
34 #include "libvex_ir.h"
37 #include "main_util.h"
38 #include "guest_generic_bb_to_IR.h"
39 #include "guest_arm_defs.h"
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.
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
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. */
57 UInt armg_calculate_flag_n ( UInt cc_op, UInt cc_dep1,
58 UInt cc_dep2, UInt cc_dep3 )
61 case ARMG_CC_OP_COPY: {
62 /* (nzcv:28x0, unused, unused) */
63 UInt nf = (cc_dep1 >> ARMG_CC_SHIFT_N) & 1;
66 case ARMG_CC_OP_ADD: {
67 /* (argL, argR, unused) */
70 UInt res = argL + argR;
74 case ARMG_CC_OP_SUB: {
75 /* (argL, argR, unused) */
78 UInt res = argL - argR;
82 case ARMG_CC_OP_ADC: {
83 /* (argL, argR, oldC) */
87 vassert((oldC & ~1) == 0);
88 UInt res = argL + argR + oldC;
92 case ARMG_CC_OP_SBB: {
93 /* (argL, argR, oldC) */
97 vassert((oldC & ~1) == 0);
98 UInt res = argL - argR - (oldC ^ 1);
102 case ARMG_CC_OP_LOGIC: {
103 /* (res, shco, oldV) */
108 case ARMG_CC_OP_MUL: {
109 /* (res, unused, oldC:oldV) */
114 case ARMG_CC_OP_MULL: {
115 /* (resLo32, resHi32, oldC:oldV) */
116 UInt resHi32 = cc_dep2;
117 UInt nf = resHi32 >> 31;
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");
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. */
133 UInt armg_calculate_flag_z ( UInt cc_op, UInt cc_dep1,
134 UInt cc_dep2, UInt cc_dep3 )
137 case ARMG_CC_OP_COPY: {
138 /* (nzcv:28x0, unused, unused) */
139 UInt zf = (cc_dep1 >> ARMG_CC_SHIFT_Z) & 1;
142 case ARMG_CC_OP_ADD: {
143 /* (argL, argR, unused) */
146 UInt res = argL + argR;
150 case ARMG_CC_OP_SUB: {
151 /* (argL, argR, unused) */
154 UInt res = argL - argR;
158 case ARMG_CC_OP_ADC: {
159 /* (argL, argR, oldC) */
163 vassert((oldC & ~1) == 0);
164 UInt res = argL + argR + oldC;
168 case ARMG_CC_OP_SBB: {
169 /* (argL, argR, oldC) */
173 vassert((oldC & ~1) == 0);
174 UInt res = argL - argR - (oldC ^ 1);
178 case ARMG_CC_OP_LOGIC: {
179 /* (res, shco, oldV) */
184 case ARMG_CC_OP_MUL: {
185 /* (res, unused, oldC:oldV) */
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;
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");
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 )
214 case ARMG_CC_OP_COPY: {
215 /* (nzcv:28x0, unused, unused) */
216 UInt cf = (cc_dep1 >> ARMG_CC_SHIFT_C) & 1;
219 case ARMG_CC_OP_ADD: {
220 /* (argL, argR, unused) */
223 UInt res = argL + argR;
224 UInt cf = res < argL;
227 case ARMG_CC_OP_SUB: {
228 /* (argL, argR, unused) */
231 UInt cf = argL >= argR;
234 case ARMG_CC_OP_ADC: {
235 /* (argL, argR, oldC) */
239 vassert((oldC & ~1) == 0);
240 UInt res = argL + argR + oldC;
241 UInt cf = oldC ? (res <= argL) : (res < argL);
244 case ARMG_CC_OP_SBB: {
245 /* (argL, argR, oldC) */
249 vassert((oldC & ~1) == 0);
250 UInt cf = oldC ? (argL >= argR) : (argL > argR);
253 case ARMG_CC_OP_LOGIC: {
254 /* (res, shco, oldV) */
256 vassert((shco & ~1) == 0);
260 case ARMG_CC_OP_MUL: {
261 /* (res, unused, oldC:oldV) */
262 UInt oldC = (cc_dep3 >> 1) & 1;
263 vassert((cc_dep3 & ~3) == 0);
267 case ARMG_CC_OP_MULL: {
268 /* (resLo32, resHi32, oldC:oldV) */
269 UInt oldC = (cc_dep3 >> 1) & 1;
270 vassert((cc_dep3 & ~3) == 0);
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");
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 )
291 case ARMG_CC_OP_COPY: {
292 /* (nzcv:28x0, unused, unused) */
293 UInt vf = (cc_dep1 >> ARMG_CC_SHIFT_V) & 1;
296 case ARMG_CC_OP_ADD: {
297 /* (argL, argR, unused) */
300 UInt res = argL + argR;
301 UInt vf = ((res ^ argL) & (res ^ argR)) >> 31;
304 case ARMG_CC_OP_SUB: {
305 /* (argL, argR, unused) */
308 UInt res = argL - argR;
309 UInt vf = ((argL ^ argR) & (argL ^ res)) >> 31;
312 case ARMG_CC_OP_ADC: {
313 /* (argL, argR, oldC) */
317 vassert((oldC & ~1) == 0);
318 UInt res = argL + argR + oldC;
319 UInt vf = ((res ^ argL) & (res ^ argR)) >> 31;
322 case ARMG_CC_OP_SBB: {
323 /* (argL, argR, oldC) */
327 vassert((oldC & ~1) == 0);
328 UInt res = argL - argR - (oldC ^ 1);
329 UInt vf = ((argL ^ argR) & (argL ^ res)) >> 31;
332 case ARMG_CC_OP_LOGIC: {
333 /* (res, shco, oldV) */
335 vassert((oldV & ~1) == 0);
339 case ARMG_CC_OP_MUL: {
340 /* (res, unused, oldC:oldV) */
341 UInt oldV = (cc_dep3 >> 0) & 1;
342 vassert((cc_dep3 & ~3) == 0);
346 case ARMG_CC_OP_MULL: {
347 /* (resLo32, resHi32, oldC:oldV) */
348 UInt oldV = (cc_dep3 >> 0) & 1;
349 vassert((cc_dep3 & ~3) == 0);
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");
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 )
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);
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.
388 UInt armg_calculate_flag_qc ( UInt resL1, UInt resL2,
389 UInt resR1, UInt resR2 )
391 if (resL1 != resR1 || resL2 != resR2)
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 */,
402 UInt cc_dep2, UInt cc_dep3 )
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);
410 // skip flags computation in this case
411 if (cond == ARMCondAL) return 1;
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);
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);
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);
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);
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);
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));
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)));
455 case ARMCondAL: // handled above
456 case ARMCondNV: // should never get here: Illegal instr
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)");
467 /*---------------------------------------------------------------*/
468 /*--- Flag-helpers translation-time function specialisers. ---*/
469 /*--- These help iropt specialise calls the above run-time ---*/
470 /*--- flags functions. ---*/
471 /*---------------------------------------------------------------*/
473 /* Used by the optimiser to try specialisations. Returns an
474 equivalent expression, or NULL if none. */
476 static Bool isU32 ( IRExpr* e, UInt n )
479 toBool( e->tag == Iex_Const
480 && e->Iex.Const.con->tag == Ico_U32
481 && e->Iex.Const.con->Ico.U32 == n );
484 IRExpr* guest_arm_spechelper ( HChar* function_name,
486 IRStmt** precedingStmts,
487 Int n_precedingStmts )
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))
495 for (i = 0; args[i]; i++)
498 vex_printf("spec request:\n");
499 vex_printf(" %s ", function_name);
500 for (i = 0; i < arity; i++) {
507 /* --------- specialising "armg_calculate_condition" --------- */
509 if (vex_streq(function_name, "armg_calculate_condition")) {
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;
517 cond_n_op = args[0]; /* (ARMCondcode << 4) | ARMG_CC_OP_* */
522 /*---------------- SUB ----------------*/
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));
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));
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));
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));
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));
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));
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));
567 /*---------------- SBB ----------------*/
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)
578 unop(Iop_32to8, cc_ndep),
580 unop(Iop_1Uto32, binop(Iop_CmpLT32U, cc_dep2, cc_dep1)),
582 unop(Iop_1Uto32, binop(Iop_CmpLE32U, cc_dep2, cc_dep1))
586 /*---------------- LOGIC ----------------*/
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)));
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)));
599 /*----------------- AL -----------------*/
601 /* A critically important case for Thumb code.
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
615 Slice44(arg1, arg2) = 0--(24)--0 arg1[7:4] arg2[3:0]
617 and we would then look for Slice44(0xE0, ...)
618 which would give the required safety property.
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
627 if (cond_n_op->tag == Iex_RdTmp) {
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)))
642 /* Didn't find any useful binding to the first arg
643 in the previous 16 stmts. */
647 /* --------- specialising "armg_calculate_flag_c" --------- */
650 if (vex_streq(function_name, "armg_calculate_flag_c")) {
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
657 IRExpr *cc_op, *cc_dep1, *cc_dep2, *cc_ndep;
659 cc_op = args[0]; /* ARMG_CC_OP_* */
664 if (isU32(cc_op, ARMG_CC_OP_LOGIC)) {
665 /* Thunk args are (result, shco, oldV) */
666 /* C after LOGIC --> shco */
670 if (isU32(cc_op, ARMG_CC_OP_SUB)) {
671 /* Thunk args are (argL, argR, unused) */
672 /* C after SUB --> argL >=u argR
674 return unop(Iop_1Uto32,
675 binop(Iop_CmpLE32U, cc_dep2, cc_dep1));
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)
687 unop(Iop_32to8, cc_ndep),
689 unop(Iop_1Uto32, binop(Iop_CmpLT32U, cc_dep2, cc_dep1)),
691 unop(Iop_1Uto32, binop(Iop_CmpLE32U, cc_dep2, cc_dep1))
697 /* --------- specialising "armg_calculate_flag_v" --------- */
700 if (vex_streq(function_name, "armg_calculate_flag_v")) {
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
707 IRExpr *cc_op, *cc_dep1, *cc_dep2, *cc_ndep;
709 cc_op = args[0]; /* ARMG_CC_OP_* */
714 if (isU32(cc_op, ARMG_CC_OP_LOGIC)) {
715 /* Thunk args are (result, shco, oldV) */
716 /* V after LOGIC --> oldV */
720 if (isU32(cc_op, ARMG_CC_OP_SUB)) {
721 /* Thunk args are (argL, argR, unused) */
723 --> let res = argL - argR
724 in ((argL ^ argR) & (argL ^ res)) >> 31
725 --> ((argL ^ argR) & (argL ^ (argL - argR))) >> 31
727 IRExpr* argL = cc_dep1;
728 IRExpr* argR = cc_dep2;
732 binop(Iop_Xor32, argL, argR),
733 binop(Iop_Xor32, argL, binop(Iop_Sub32, argL, argR))
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) */
743 --> let res = argL - argR - (oldC ^ 1)
744 in (argL ^ argR) & (argL ^ res) & 1
752 binop(Iop_Xor32, cc_dep1, cc_dep2),
753 // argL ^ (argL - argR - (oldC ^ 1))
757 binop(Iop_Sub32, cc_dep1, cc_dep2),
758 binop(Iop_Xor32, cc_ndep, mkU32(1)))
776 /*----------------------------------------------*/
777 /*--- The exported fns .. ---*/
778 /*----------------------------------------------*/
780 /* VISIBLE TO LIBVEX CLIENT */
782 void LibVEX_GuestARM_put_flags ( UInt flags_native,
783 /*OUT*/VexGuestARMState* vex_state )
787 /* Mask out everything except N Z V C. */
789 &= (ARMG_CC_MASK_N | ARMG_CC_MASK_Z | ARMG_CC_MASK_V | ARMG_CC_MASK_C);
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;
798 /* VISIBLE TO LIBVEX CLIENT */
799 UInt LibVEX_GuestARM_get_cpsr ( /*IN*/VexGuestARMState* vex_state )
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
809 vassert(0 == (cpsr & 0x0FFFFFFF));
811 if (vex_state->guest_QFLAG32 > 0)
814 if (vex_state->guest_GEFLAG0 > 0)
816 if (vex_state->guest_GEFLAG1 > 0)
818 if (vex_state->guest_GEFLAG2 > 0)
820 if (vex_state->guest_GEFLAG3 > 0)
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)
828 // ITSTATE we punt on for the time being. Could compute it
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.
836 /* VISIBLE TO LIBVEX CLIENT */
837 void LibVEX_GuestARM_initialise ( /*OUT*/VexGuestARMState* vex_state )
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 */
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;
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;
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;
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;
910 vex_state->guest_TPIDRURO = 0;
912 /* Not in a Thumb IT block. */
913 vex_state->guest_ITSTATE = 0;
915 vex_state->padding1 = 0;
916 vex_state->padding2 = 0;
917 vex_state->padding3 = 0;
921 /*-----------------------------------------------------------*/
922 /*--- Describing the arm guest state, for the benefit ---*/
923 /*--- of iropt and instrumenters. ---*/
924 /*-----------------------------------------------------------*/
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).
930 We enforce precise exns for guest R13(sp), R15T(pc).
932 Bool guest_arm_state_requires_precise_mem_exns ( Int minoff,
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;
940 if (maxoff < sp_min || minoff > sp_max) {
941 /* no overlap with sp */
946 if (maxoff < pc_min || minoff > pc_max) {
947 /* no overlap with pc */
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;
957 if (maxoff < r11_min || minoff > r11_max) {
958 /* no overlap with r11 */
963 /* Ditto R7, particularly needed for proper stacktraces in Thumb
965 Int r7_min = offsetof(VexGuestARMState, guest_R7);
966 Int r7_max = r7_min + 4 - 1;
968 if (maxoff < r7_min || minoff > r7_max) {
969 /* no overlap with r7 */
979 #define ALWAYSDEFD(field) \
980 { offsetof(VexGuestARMState, field), \
981 (sizeof ((VexGuestARMState*)0)->field) }
986 /* Total size of the guest state, in bytes. */
987 .total_sizeB = sizeof(VexGuestARMState),
989 /* Describe the stack pointer. */
990 .offset_SP = offsetof(VexGuestARMState,guest_R13),
993 /* Describe the instruction pointer. */
994 .offset_IP = offsetof(VexGuestARMState,guest_R15T),
997 /* Describe any sections to be regarded by Memcheck as
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. */
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)
1019 /*---------------------------------------------------------------*/
1020 /*--- end guest_arm_helpers.c ---*/
1021 /*---------------------------------------------------------------*/