12a9ad023890d3b34cf45e429df2a8ae88b419128sewardj
22a9ad023890d3b34cf45e429df2a8ae88b419128sewardj/*---------------------------------------------------------------*/
3752f90673ebbb6b2f55fc5e46606dea371313713sewardj/*--- begin                               guest_arm_helpers.c ---*/
42a9ad023890d3b34cf45e429df2a8ae88b419128sewardj/*---------------------------------------------------------------*/
52a9ad023890d3b34cf45e429df2a8ae88b419128sewardj
62a9ad023890d3b34cf45e429df2a8ae88b419128sewardj/*
7752f90673ebbb6b2f55fc5e46606dea371313713sewardj   This file is part of Valgrind, a dynamic binary instrumentation
8752f90673ebbb6b2f55fc5e46606dea371313713sewardj   framework.
92a9ad023890d3b34cf45e429df2a8ae88b419128sewardj
1089ae8477745fd2a15453557d729a50e627325ee2sewardj   Copyright (C) 2004-2013 OpenWorks LLP
11752f90673ebbb6b2f55fc5e46606dea371313713sewardj      info@open-works.net
127bd6ffe203f3aa9e7b25f7eae40a9b9cf48710cfsewardj
13752f90673ebbb6b2f55fc5e46606dea371313713sewardj   This program is free software; you can redistribute it and/or
14752f90673ebbb6b2f55fc5e46606dea371313713sewardj   modify it under the terms of the GNU General Public License as
15752f90673ebbb6b2f55fc5e46606dea371313713sewardj   published by the Free Software Foundation; either version 2 of the
16752f90673ebbb6b2f55fc5e46606dea371313713sewardj   License, or (at your option) any later version.
177bd6ffe203f3aa9e7b25f7eae40a9b9cf48710cfsewardj
18752f90673ebbb6b2f55fc5e46606dea371313713sewardj   This program is distributed in the hope that it will be useful, but
19752f90673ebbb6b2f55fc5e46606dea371313713sewardj   WITHOUT ANY WARRANTY; without even the implied warranty of
20752f90673ebbb6b2f55fc5e46606dea371313713sewardj   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21752f90673ebbb6b2f55fc5e46606dea371313713sewardj   General Public License for more details.
22752f90673ebbb6b2f55fc5e46606dea371313713sewardj
23752f90673ebbb6b2f55fc5e46606dea371313713sewardj   You should have received a copy of the GNU General Public License
24752f90673ebbb6b2f55fc5e46606dea371313713sewardj   along with this program; if not, write to the Free Software
25752f90673ebbb6b2f55fc5e46606dea371313713sewardj   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
267bd6ffe203f3aa9e7b25f7eae40a9b9cf48710cfsewardj   02110-1301, USA.
277bd6ffe203f3aa9e7b25f7eae40a9b9cf48710cfsewardj
28752f90673ebbb6b2f55fc5e46606dea371313713sewardj   The GNU General Public License is contained in the file COPYING.
292a9ad023890d3b34cf45e429df2a8ae88b419128sewardj*/
302a9ad023890d3b34cf45e429df2a8ae88b419128sewardj
312a9ad023890d3b34cf45e429df2a8ae88b419128sewardj#include "libvex_basictypes.h"
3233b024301d2311965cc68dc4cc900f3d0fdd8085florian#include "libvex_emnote.h"
332a9ad023890d3b34cf45e429df2a8ae88b419128sewardj#include "libvex_guest_arm.h"
342a9ad023890d3b34cf45e429df2a8ae88b419128sewardj#include "libvex_ir.h"
352a9ad023890d3b34cf45e429df2a8ae88b419128sewardj#include "libvex.h"
362a9ad023890d3b34cf45e429df2a8ae88b419128sewardj
37cef7d3e3df4796e35b4521158d9dc058f034aa87sewardj#include "main_util.h"
386c46befd9eb90c1b6e739926c1fa335cba75bf46philippe#include "main_globals.h"
396c299f3acab617581ea504e45fbb6cab24c2b29fsewardj#include "guest_generic_bb_to_IR.h"
40cef7d3e3df4796e35b4521158d9dc058f034aa87sewardj#include "guest_arm_defs.h"
412a9ad023890d3b34cf45e429df2a8ae88b419128sewardj
422a9ad023890d3b34cf45e429df2a8ae88b419128sewardj
436c299f3acab617581ea504e45fbb6cab24c2b29fsewardj/* This file contains helper functions for arm guest code.  Calls to
446c299f3acab617581ea504e45fbb6cab24c2b29fsewardj   these functions are generated by the back end.  These calls are of
456c299f3acab617581ea504e45fbb6cab24c2b29fsewardj   course in the host machine code and this file will be compiled to
466c299f3acab617581ea504e45fbb6cab24c2b29fsewardj   host machine code, so that all makes sense.
472a9ad023890d3b34cf45e429df2a8ae88b419128sewardj
482a9ad023890d3b34cf45e429df2a8ae88b419128sewardj   Only change the signatures of these helper functions very
492a9ad023890d3b34cf45e429df2a8ae88b419128sewardj   carefully.  If you change the signature here, you'll have to change
502a9ad023890d3b34cf45e429df2a8ae88b419128sewardj   the parameters passed to it in the IR calls constructed by
512a9ad023890d3b34cf45e429df2a8ae88b419128sewardj   guest-arm/toIR.c.
522a9ad023890d3b34cf45e429df2a8ae88b419128sewardj*/
532a9ad023890d3b34cf45e429df2a8ae88b419128sewardj
542a9ad023890d3b34cf45e429df2a8ae88b419128sewardj
5526bc4823f4e3273aab7741edf221592a57d8d78fsewardj/* Set to 1 to get detailed profiling info about individual N, Z, C
5626bc4823f4e3273aab7741edf221592a57d8d78fsewardj   and V flag evaluation. */
5726bc4823f4e3273aab7741edf221592a57d8d78fsewardj#define PROFILE_NZCV_FLAGS 0
5826bc4823f4e3273aab7741edf221592a57d8d78fsewardj
5926bc4823f4e3273aab7741edf221592a57d8d78fsewardj#if PROFILE_NZCV_FLAGS
6026bc4823f4e3273aab7741edf221592a57d8d78fsewardj
6126bc4823f4e3273aab7741edf221592a57d8d78fsewardjstatic UInt tab_n_eval[ARMG_CC_OP_NUMBER];
6226bc4823f4e3273aab7741edf221592a57d8d78fsewardjstatic UInt tab_z_eval[ARMG_CC_OP_NUMBER];
6326bc4823f4e3273aab7741edf221592a57d8d78fsewardjstatic UInt tab_c_eval[ARMG_CC_OP_NUMBER];
6426bc4823f4e3273aab7741edf221592a57d8d78fsewardjstatic UInt tab_v_eval[ARMG_CC_OP_NUMBER];
6526bc4823f4e3273aab7741edf221592a57d8d78fsewardjstatic UInt initted = 0;
6626bc4823f4e3273aab7741edf221592a57d8d78fsewardjstatic UInt tot_evals = 0;
6726bc4823f4e3273aab7741edf221592a57d8d78fsewardj
6826bc4823f4e3273aab7741edf221592a57d8d78fsewardjstatic void initCounts ( void )
6926bc4823f4e3273aab7741edf221592a57d8d78fsewardj{
7026bc4823f4e3273aab7741edf221592a57d8d78fsewardj   UInt i;
7126bc4823f4e3273aab7741edf221592a57d8d78fsewardj   for (i = 0; i < ARMG_CC_OP_NUMBER; i++) {
7226bc4823f4e3273aab7741edf221592a57d8d78fsewardj      tab_n_eval[i] = tab_z_eval[i] = tab_c_eval[i] = tab_v_eval[i] = 0;
7326bc4823f4e3273aab7741edf221592a57d8d78fsewardj   }
7426bc4823f4e3273aab7741edf221592a57d8d78fsewardj   initted = 1;
7526bc4823f4e3273aab7741edf221592a57d8d78fsewardj}
7626bc4823f4e3273aab7741edf221592a57d8d78fsewardj
7726bc4823f4e3273aab7741edf221592a57d8d78fsewardjstatic void showCounts ( void )
7826bc4823f4e3273aab7741edf221592a57d8d78fsewardj{
7926bc4823f4e3273aab7741edf221592a57d8d78fsewardj   UInt i;
8026bc4823f4e3273aab7741edf221592a57d8d78fsewardj   vex_printf("\n                 N          Z          C          V\n");
8126bc4823f4e3273aab7741edf221592a57d8d78fsewardj   vex_printf(  "---------------------------------------------------\n");
8226bc4823f4e3273aab7741edf221592a57d8d78fsewardj   for (i = 0; i < ARMG_CC_OP_NUMBER; i++) {
8326bc4823f4e3273aab7741edf221592a57d8d78fsewardj      vex_printf("CC_OP=%d  %9d  %9d  %9d  %9d\n",
8426bc4823f4e3273aab7741edf221592a57d8d78fsewardj                 i,
8526bc4823f4e3273aab7741edf221592a57d8d78fsewardj                 tab_n_eval[i], tab_z_eval[i],
8626bc4823f4e3273aab7741edf221592a57d8d78fsewardj                 tab_c_eval[i], tab_v_eval[i] );
8726bc4823f4e3273aab7741edf221592a57d8d78fsewardj    }
8826bc4823f4e3273aab7741edf221592a57d8d78fsewardj}
8926bc4823f4e3273aab7741edf221592a57d8d78fsewardj
9026bc4823f4e3273aab7741edf221592a57d8d78fsewardj#define NOTE_N_EVAL(_cc_op) NOTE_EVAL(_cc_op, tab_n_eval)
9126bc4823f4e3273aab7741edf221592a57d8d78fsewardj#define NOTE_Z_EVAL(_cc_op) NOTE_EVAL(_cc_op, tab_z_eval)
9226bc4823f4e3273aab7741edf221592a57d8d78fsewardj#define NOTE_C_EVAL(_cc_op) NOTE_EVAL(_cc_op, tab_c_eval)
9326bc4823f4e3273aab7741edf221592a57d8d78fsewardj#define NOTE_V_EVAL(_cc_op) NOTE_EVAL(_cc_op, tab_v_eval)
9426bc4823f4e3273aab7741edf221592a57d8d78fsewardj
9526bc4823f4e3273aab7741edf221592a57d8d78fsewardj#define NOTE_EVAL(_cc_op, _tab) \
9626bc4823f4e3273aab7741edf221592a57d8d78fsewardj   do { \
9726bc4823f4e3273aab7741edf221592a57d8d78fsewardj      if (!initted) initCounts(); \
9826bc4823f4e3273aab7741edf221592a57d8d78fsewardj      vassert( ((UInt)(_cc_op)) < ARMG_CC_OP_NUMBER); \
9926bc4823f4e3273aab7741edf221592a57d8d78fsewardj      _tab[(UInt)(_cc_op)]++; \
10026bc4823f4e3273aab7741edf221592a57d8d78fsewardj      tot_evals++; \
10126bc4823f4e3273aab7741edf221592a57d8d78fsewardj      if (0 == (tot_evals & 0xFFFFF)) \
10226bc4823f4e3273aab7741edf221592a57d8d78fsewardj        showCounts(); \
10326bc4823f4e3273aab7741edf221592a57d8d78fsewardj   } while (0)
10426bc4823f4e3273aab7741edf221592a57d8d78fsewardj
10526bc4823f4e3273aab7741edf221592a57d8d78fsewardj#endif /* PROFILE_NZCV_FLAGS */
10626bc4823f4e3273aab7741edf221592a57d8d78fsewardj
10726bc4823f4e3273aab7741edf221592a57d8d78fsewardj
1083c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj/* Calculate the N flag from the supplied thunk components, in the
1093c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj   least significant bit of the word.  Returned bits 31:1 are zero. */
1103c14925dc79642a6c04bb7bf99253a853c1e3f36sewardjstatic
1113c14925dc79642a6c04bb7bf99253a853c1e3f36sewardjUInt armg_calculate_flag_n ( UInt cc_op, UInt cc_dep1,
1123c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj                             UInt cc_dep2, UInt cc_dep3 )
1136c299f3acab617581ea504e45fbb6cab24c2b29fsewardj{
11426bc4823f4e3273aab7741edf221592a57d8d78fsewardj#  if PROFILE_NZCV_FLAGS
11526bc4823f4e3273aab7741edf221592a57d8d78fsewardj   NOTE_N_EVAL(cc_op);
11626bc4823f4e3273aab7741edf221592a57d8d78fsewardj#  endif
11726bc4823f4e3273aab7741edf221592a57d8d78fsewardj
1183c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj   switch (cc_op) {
1193c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj      case ARMG_CC_OP_COPY: {
1203c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         /* (nzcv:28x0, unused, unused) */
1213c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         UInt nf   = (cc_dep1 >> ARMG_CC_SHIFT_N) & 1;
1223c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         return nf;
1233c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj      }
1243c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj      case ARMG_CC_OP_ADD: {
1253c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         /* (argL, argR, unused) */
1263c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         UInt argL = cc_dep1;
1273c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         UInt argR = cc_dep2;
1283c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         UInt res  = argL + argR;
1293c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         UInt nf   = res >> 31;
1303c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         return nf;
1313c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj      }
1323c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj      case ARMG_CC_OP_SUB: {
1333c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         /* (argL, argR, unused) */
1343c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         UInt argL = cc_dep1;
1353c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         UInt argR = cc_dep2;
1363c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         UInt res  = argL - argR;
1373c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         UInt nf   = res >> 31;
1383c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         return nf;
1393c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj      }
1403c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj      case ARMG_CC_OP_ADC: {
1413c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         /* (argL, argR, oldC) */
1423c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         UInt argL = cc_dep1;
1433c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         UInt argR = cc_dep2;
1443c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         UInt oldC = cc_dep3;
1453c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         vassert((oldC & ~1) == 0);
1463c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         UInt res  = argL + argR + oldC;
1473c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         UInt nf   = res >> 31;
1483c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         return nf;
1493c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj      }
1503c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj      case ARMG_CC_OP_SBB: {
1513c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         /* (argL, argR, oldC) */
1523c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         UInt argL = cc_dep1;
1533c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         UInt argR = cc_dep2;
1543c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         UInt oldC = cc_dep3;
1553c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         vassert((oldC & ~1) == 0);
1563c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         UInt res  = argL - argR - (oldC ^ 1);
1573c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         UInt nf   = res >> 31;
1583c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         return nf;
1593c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj      }
1603c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj      case ARMG_CC_OP_LOGIC: {
1613c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         /* (res, shco, oldV) */
1623c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         UInt res  = cc_dep1;
1633c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         UInt nf   = res >> 31;
1643c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         return nf;
1653c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj      }
1663c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj      case ARMG_CC_OP_MUL: {
1673c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         /* (res, unused, oldC:oldV) */
1683c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         UInt res  = cc_dep1;
1693c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         UInt nf   = res >> 31;
1703c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         return nf;
1713c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj      }
1723c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj      case ARMG_CC_OP_MULL: {
1733c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         /* (resLo32, resHi32, oldC:oldV) */
1743c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         UInt resHi32 = cc_dep2;
1753c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         UInt nf      = resHi32 >> 31;
1763c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         return nf;
1773c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj      }
1783c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj      default:
1793c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         /* shouldn't really make these calls from generated code */
1803c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         vex_printf("armg_calculate_flag_n"
1813c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj                    "( op=%u, dep1=0x%x, dep2=0x%x, dep3=0x%x )\n",
1823c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj                    cc_op, cc_dep1, cc_dep2, cc_dep3 );
1833c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         vpanic("armg_calculate_flags_n");
1843c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj   }
185f7da63d911934ee20d39e8c994edf7ca0bbc930fcerion}
186f7da63d911934ee20d39e8c994edf7ca0bbc930fcerion
187f7da63d911934ee20d39e8c994edf7ca0bbc930fcerion
1883c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj/* Calculate the Z flag from the supplied thunk components, in the
1893c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj   least significant bit of the word.  Returned bits 31:1 are zero. */
1903c14925dc79642a6c04bb7bf99253a853c1e3f36sewardjstatic
1913c14925dc79642a6c04bb7bf99253a853c1e3f36sewardjUInt armg_calculate_flag_z ( UInt cc_op, UInt cc_dep1,
1923c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj                             UInt cc_dep2, UInt cc_dep3 )
1932a9ad023890d3b34cf45e429df2a8ae88b419128sewardj{
19426bc4823f4e3273aab7741edf221592a57d8d78fsewardj#  if PROFILE_NZCV_FLAGS
19526bc4823f4e3273aab7741edf221592a57d8d78fsewardj   NOTE_Z_EVAL(cc_op);
19626bc4823f4e3273aab7741edf221592a57d8d78fsewardj#  endif
19726bc4823f4e3273aab7741edf221592a57d8d78fsewardj
1982a9ad023890d3b34cf45e429df2a8ae88b419128sewardj   switch (cc_op) {
1993c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj      case ARMG_CC_OP_COPY: {
2003c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         /* (nzcv:28x0, unused, unused) */
2013c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         UInt zf   = (cc_dep1 >> ARMG_CC_SHIFT_Z) & 1;
2023c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         return zf;
2033c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj      }
2046c299f3acab617581ea504e45fbb6cab24c2b29fsewardj      case ARMG_CC_OP_ADD: {
2056c299f3acab617581ea504e45fbb6cab24c2b29fsewardj         /* (argL, argR, unused) */
2066c299f3acab617581ea504e45fbb6cab24c2b29fsewardj         UInt argL = cc_dep1;
2076c299f3acab617581ea504e45fbb6cab24c2b29fsewardj         UInt argR = cc_dep2;
2086c299f3acab617581ea504e45fbb6cab24c2b29fsewardj         UInt res  = argL + argR;
2093c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         UInt zf   = res == 0;
2103c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         return zf;
2116c299f3acab617581ea504e45fbb6cab24c2b29fsewardj      }
2126c299f3acab617581ea504e45fbb6cab24c2b29fsewardj      case ARMG_CC_OP_SUB: {
2136c299f3acab617581ea504e45fbb6cab24c2b29fsewardj         /* (argL, argR, unused) */
2146c299f3acab617581ea504e45fbb6cab24c2b29fsewardj         UInt argL = cc_dep1;
2156c299f3acab617581ea504e45fbb6cab24c2b29fsewardj         UInt argR = cc_dep2;
2166c299f3acab617581ea504e45fbb6cab24c2b29fsewardj         UInt res  = argL - argR;
2173c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         UInt zf   = res == 0;
2183c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         return zf;
2196c299f3acab617581ea504e45fbb6cab24c2b29fsewardj      }
2206c299f3acab617581ea504e45fbb6cab24c2b29fsewardj      case ARMG_CC_OP_ADC: {
2216c299f3acab617581ea504e45fbb6cab24c2b29fsewardj         /* (argL, argR, oldC) */
2226c299f3acab617581ea504e45fbb6cab24c2b29fsewardj         UInt argL = cc_dep1;
2236c299f3acab617581ea504e45fbb6cab24c2b29fsewardj         UInt argR = cc_dep2;
2246c299f3acab617581ea504e45fbb6cab24c2b29fsewardj         UInt oldC = cc_dep3;
225bb8b394c97a23a17f60712afff6484ab340a93casewardj         vassert((oldC & ~1) == 0);
2263c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         UInt res  = argL + argR + oldC;
2273c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         UInt zf   = res == 0;
2283c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         return zf;
2296c299f3acab617581ea504e45fbb6cab24c2b29fsewardj      }
2306c299f3acab617581ea504e45fbb6cab24c2b29fsewardj      case ARMG_CC_OP_SBB: {
2316c299f3acab617581ea504e45fbb6cab24c2b29fsewardj         /* (argL, argR, oldC) */
2326c299f3acab617581ea504e45fbb6cab24c2b29fsewardj         UInt argL = cc_dep1;
2336c299f3acab617581ea504e45fbb6cab24c2b29fsewardj         UInt argR = cc_dep2;
2346c299f3acab617581ea504e45fbb6cab24c2b29fsewardj         UInt oldC = cc_dep3;
235bb8b394c97a23a17f60712afff6484ab340a93casewardj         vassert((oldC & ~1) == 0);
2366c299f3acab617581ea504e45fbb6cab24c2b29fsewardj         UInt res  = argL - argR - (oldC ^ 1);
2373c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         UInt zf   = res == 0;
2383c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         return zf;
2396c299f3acab617581ea504e45fbb6cab24c2b29fsewardj      }
2406c299f3acab617581ea504e45fbb6cab24c2b29fsewardj      case ARMG_CC_OP_LOGIC: {
2416c299f3acab617581ea504e45fbb6cab24c2b29fsewardj         /* (res, shco, oldV) */
2426c299f3acab617581ea504e45fbb6cab24c2b29fsewardj         UInt res  = cc_dep1;
2433c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         UInt zf   = res == 0;
2443c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         return zf;
2456c299f3acab617581ea504e45fbb6cab24c2b29fsewardj      }
2466c299f3acab617581ea504e45fbb6cab24c2b29fsewardj      case ARMG_CC_OP_MUL: {
2476c299f3acab617581ea504e45fbb6cab24c2b29fsewardj         /* (res, unused, oldC:oldV) */
2486c299f3acab617581ea504e45fbb6cab24c2b29fsewardj         UInt res  = cc_dep1;
2493c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         UInt zf   = res == 0;
2503c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         return zf;
2516c299f3acab617581ea504e45fbb6cab24c2b29fsewardj      }
2526c299f3acab617581ea504e45fbb6cab24c2b29fsewardj      case ARMG_CC_OP_MULL: {
2536c299f3acab617581ea504e45fbb6cab24c2b29fsewardj         /* (resLo32, resHi32, oldC:oldV) */
2546c299f3acab617581ea504e45fbb6cab24c2b29fsewardj         UInt resLo32 = cc_dep1;
2556c299f3acab617581ea504e45fbb6cab24c2b29fsewardj         UInt resHi32 = cc_dep2;
2563c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         UInt zf      = (resHi32|resLo32) == 0;
2573c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         return zf;
2586c299f3acab617581ea504e45fbb6cab24c2b29fsewardj      }
2596c299f3acab617581ea504e45fbb6cab24c2b29fsewardj      default:
2606c299f3acab617581ea504e45fbb6cab24c2b29fsewardj         /* shouldn't really make these calls from generated code */
2613c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         vex_printf("armg_calculate_flags_z"
2626c299f3acab617581ea504e45fbb6cab24c2b29fsewardj                    "( op=%u, dep1=0x%x, dep2=0x%x, dep3=0x%x )\n",
2636c299f3acab617581ea504e45fbb6cab24c2b29fsewardj                    cc_op, cc_dep1, cc_dep2, cc_dep3 );
2643c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         vpanic("armg_calculate_flags_z");
2652a9ad023890d3b34cf45e429df2a8ae88b419128sewardj   }
2662a9ad023890d3b34cf45e429df2a8ae88b419128sewardj}
2672a9ad023890d3b34cf45e429df2a8ae88b419128sewardj
2686c299f3acab617581ea504e45fbb6cab24c2b29fsewardj
269f7da63d911934ee20d39e8c994edf7ca0bbc930fcerion/* CALLED FROM GENERATED CODE: CLEAN HELPER */
2703c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj/* Calculate the C flag from the supplied thunk components, in the
2713c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj   least significant bit of the word.  Returned bits 31:1 are zero. */
2726c299f3acab617581ea504e45fbb6cab24c2b29fsewardjUInt armg_calculate_flag_c ( UInt cc_op, UInt cc_dep1,
2736c299f3acab617581ea504e45fbb6cab24c2b29fsewardj                             UInt cc_dep2, UInt cc_dep3 )
274f7da63d911934ee20d39e8c994edf7ca0bbc930fcerion{
27526bc4823f4e3273aab7741edf221592a57d8d78fsewardj#  if PROFILE_NZCV_FLAGS
27626bc4823f4e3273aab7741edf221592a57d8d78fsewardj   NOTE_C_EVAL(cc_op);
27726bc4823f4e3273aab7741edf221592a57d8d78fsewardj#  endif
27826bc4823f4e3273aab7741edf221592a57d8d78fsewardj
2793c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj   switch (cc_op) {
2803c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj      case ARMG_CC_OP_COPY: {
2813c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         /* (nzcv:28x0, unused, unused) */
2823c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         UInt cf   = (cc_dep1 >> ARMG_CC_SHIFT_C) & 1;
2833c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         return cf;
2843c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj      }
2853c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj      case ARMG_CC_OP_ADD: {
2863c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         /* (argL, argR, unused) */
2873c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         UInt argL = cc_dep1;
2883c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         UInt argR = cc_dep2;
2893c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         UInt res  = argL + argR;
2903c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         UInt cf   = res < argL;
2913c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         return cf;
2923c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj      }
2933c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj      case ARMG_CC_OP_SUB: {
2943c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         /* (argL, argR, unused) */
2953c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         UInt argL = cc_dep1;
2963c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         UInt argR = cc_dep2;
2973c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         UInt cf   = argL >= argR;
2983c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         return cf;
2993c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj      }
3003c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj      case ARMG_CC_OP_ADC: {
3013c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         /* (argL, argR, oldC) */
3023c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         UInt argL = cc_dep1;
3033c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         UInt argR = cc_dep2;
3043c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         UInt oldC = cc_dep3;
3053c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         vassert((oldC & ~1) == 0);
3063c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         UInt res  = argL + argR + oldC;
3073c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         UInt cf   = oldC ? (res <= argL) : (res < argL);
3083c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         return cf;
3093c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj      }
3103c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj      case ARMG_CC_OP_SBB: {
3113c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         /* (argL, argR, oldC) */
3123c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         UInt argL = cc_dep1;
3133c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         UInt argR = cc_dep2;
3143c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         UInt oldC = cc_dep3;
3153c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         vassert((oldC & ~1) == 0);
3163c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         UInt cf   = oldC ? (argL >= argR) : (argL > argR);
3173c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         return cf;
3183c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj      }
3193c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj      case ARMG_CC_OP_LOGIC: {
3203c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         /* (res, shco, oldV) */
3213c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         UInt shco = cc_dep2;
3223c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         vassert((shco & ~1) == 0);
3233c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         UInt cf   = shco;
3243c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         return cf;
3253c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj      }
3263c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj      case ARMG_CC_OP_MUL: {
3273c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         /* (res, unused, oldC:oldV) */
3283c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         UInt oldC = (cc_dep3 >> 1) & 1;
3293c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         vassert((cc_dep3 & ~3) == 0);
3303c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         UInt cf   = oldC;
3313c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         return cf;
3323c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj      }
3333c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj      case ARMG_CC_OP_MULL: {
3343c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         /* (resLo32, resHi32, oldC:oldV) */
3353c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         UInt oldC    = (cc_dep3 >> 1) & 1;
3363c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         vassert((cc_dep3 & ~3) == 0);
3373c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         UInt cf      = oldC;
3383c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         return cf;
3393c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj      }
3403c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj      default:
3413c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         /* shouldn't really make these calls from generated code */
3423c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         vex_printf("armg_calculate_flag_c"
3433c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj                    "( op=%u, dep1=0x%x, dep2=0x%x, dep3=0x%x )\n",
3443c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj                    cc_op, cc_dep1, cc_dep2, cc_dep3 );
3453c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         vpanic("armg_calculate_flag_c");
3463c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj   }
347f7da63d911934ee20d39e8c994edf7ca0bbc930fcerion}
348f7da63d911934ee20d39e8c994edf7ca0bbc930fcerion
349f7da63d911934ee20d39e8c994edf7ca0bbc930fcerion
3502a9ad023890d3b34cf45e429df2a8ae88b419128sewardj/* CALLED FROM GENERATED CODE: CLEAN HELPER */
3513c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj/* Calculate the V flag from the supplied thunk components, in the
3523c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj   least significant bit of the word.  Returned bits 31:1 are zero. */
3536c299f3acab617581ea504e45fbb6cab24c2b29fsewardjUInt armg_calculate_flag_v ( UInt cc_op, UInt cc_dep1,
3546c299f3acab617581ea504e45fbb6cab24c2b29fsewardj                             UInt cc_dep2, UInt cc_dep3 )
3552a9ad023890d3b34cf45e429df2a8ae88b419128sewardj{
35626bc4823f4e3273aab7741edf221592a57d8d78fsewardj#  if PROFILE_NZCV_FLAGS
35726bc4823f4e3273aab7741edf221592a57d8d78fsewardj   NOTE_V_EVAL(cc_op);
35826bc4823f4e3273aab7741edf221592a57d8d78fsewardj#  endif
35926bc4823f4e3273aab7741edf221592a57d8d78fsewardj
3603c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj   switch (cc_op) {
3613c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj      case ARMG_CC_OP_COPY: {
3623c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         /* (nzcv:28x0, unused, unused) */
3633c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         UInt vf   = (cc_dep1 >> ARMG_CC_SHIFT_V) & 1;
3643c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         return vf;
3653c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj      }
3663c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj      case ARMG_CC_OP_ADD: {
3673c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         /* (argL, argR, unused) */
3683c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         UInt argL = cc_dep1;
3693c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         UInt argR = cc_dep2;
3703c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         UInt res  = argL + argR;
3713c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         UInt vf   = ((res ^ argL) & (res ^ argR)) >> 31;
3723c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         return vf;
3733c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj      }
3743c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj      case ARMG_CC_OP_SUB: {
3753c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         /* (argL, argR, unused) */
3763c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         UInt argL = cc_dep1;
3773c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         UInt argR = cc_dep2;
3783c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         UInt res  = argL - argR;
3793c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         UInt vf   = ((argL ^ argR) & (argL ^ res)) >> 31;
3803c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         return vf;
3813c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj      }
3823c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj      case ARMG_CC_OP_ADC: {
3833c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         /* (argL, argR, oldC) */
3843c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         UInt argL = cc_dep1;
3853c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         UInt argR = cc_dep2;
3863c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         UInt oldC = cc_dep3;
3873c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         vassert((oldC & ~1) == 0);
3883c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         UInt res  = argL + argR + oldC;
3893c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         UInt vf   = ((res ^ argL) & (res ^ argR)) >> 31;
3903c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         return vf;
3913c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj      }
3923c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj      case ARMG_CC_OP_SBB: {
3933c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         /* (argL, argR, oldC) */
3943c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         UInt argL = cc_dep1;
3953c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         UInt argR = cc_dep2;
3963c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         UInt oldC = cc_dep3;
3973c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         vassert((oldC & ~1) == 0);
3983c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         UInt res  = argL - argR - (oldC ^ 1);
3993c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         UInt vf   = ((argL ^ argR) & (argL ^ res)) >> 31;
4003c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         return vf;
4013c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj      }
4023c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj      case ARMG_CC_OP_LOGIC: {
4033c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         /* (res, shco, oldV) */
4043c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         UInt oldV = cc_dep3;
4053c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         vassert((oldV & ~1) == 0);
4063c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         UInt vf   = oldV;
4073c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         return vf;
4083c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj      }
4093c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj      case ARMG_CC_OP_MUL: {
4103c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         /* (res, unused, oldC:oldV) */
4113c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         UInt oldV = (cc_dep3 >> 0) & 1;
4123c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         vassert((cc_dep3 & ~3) == 0);
4133c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         UInt vf   = oldV;
4143c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         return vf;
4153c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj      }
4163c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj      case ARMG_CC_OP_MULL: {
4173c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         /* (resLo32, resHi32, oldC:oldV) */
4183c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         UInt oldV    = (cc_dep3 >> 0) & 1;
4193c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         vassert((cc_dep3 & ~3) == 0);
4203c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         UInt vf      = oldV;
4213c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         return vf;
4223c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj      }
4233c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj      default:
4243c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         /* shouldn't really make these calls from generated code */
4253c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         vex_printf("armg_calculate_flag_v"
4263c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj                    "( op=%u, dep1=0x%x, dep2=0x%x, dep3=0x%x )\n",
4273c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj                    cc_op, cc_dep1, cc_dep2, cc_dep3 );
4283c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         vpanic("armg_calculate_flag_v");
4293c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj   }
4306c299f3acab617581ea504e45fbb6cab24c2b29fsewardj}
4316c299f3acab617581ea504e45fbb6cab24c2b29fsewardj
4323c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj
4333c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj/* CALLED FROM GENERATED CODE: CLEAN HELPER */
4343c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj/* Calculate NZCV from the supplied thunk components, in the positions
4353c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj   they appear in the CPSR, viz bits 31:28 for N Z C V respectively.
4363c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj   Returned bits 27:0 are zero. */
4373c14925dc79642a6c04bb7bf99253a853c1e3f36sewardjUInt armg_calculate_flags_nzcv ( UInt cc_op, UInt cc_dep1,
4383c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj                                 UInt cc_dep2, UInt cc_dep3 )
4393c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj{
4403c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj   UInt f;
4413c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj   UInt res = 0;
4423c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj   f = armg_calculate_flag_n(cc_op, cc_dep1, cc_dep2, cc_dep3);
4433c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj   res |= (f << ARMG_CC_SHIFT_N);
4443c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj   f = armg_calculate_flag_z(cc_op, cc_dep1, cc_dep2, cc_dep3);
4453c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj   res |= (f << ARMG_CC_SHIFT_Z);
4463c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj   f = armg_calculate_flag_c(cc_op, cc_dep1, cc_dep2, cc_dep3);
4473c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj   res |= (f << ARMG_CC_SHIFT_C);
4483c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj   f = armg_calculate_flag_v(cc_op, cc_dep1, cc_dep2, cc_dep3);
4493c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj   res |= (f << ARMG_CC_SHIFT_V);
4503c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj   return res;
4513c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj}
4523c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj
4533c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj
454d266447c09a99122cbc220edee5ac936eee7a0ddsewardj/* CALLED FROM GENERATED CODE: CLEAN HELPER */
4559dbbd7b5d3ba12bd46e38bfe6ef24dbabecfed13sewardj/* Calculate the QC flag from the arguments, in the lowest bit
4569dbbd7b5d3ba12bd46e38bfe6ef24dbabecfed13sewardj   of the word (bit 0).  Urr, having this out of line is bizarre.
4579dbbd7b5d3ba12bd46e38bfe6ef24dbabecfed13sewardj   Push back inline. */
458d266447c09a99122cbc220edee5ac936eee7a0ddsewardjUInt armg_calculate_flag_qc ( UInt resL1, UInt resL2,
459d266447c09a99122cbc220edee5ac936eee7a0ddsewardj                              UInt resR1, UInt resR2 )
460d266447c09a99122cbc220edee5ac936eee7a0ddsewardj{
461d266447c09a99122cbc220edee5ac936eee7a0ddsewardj   if (resL1 != resR1 || resL2 != resR2)
462d266447c09a99122cbc220edee5ac936eee7a0ddsewardj      return 1;
463d266447c09a99122cbc220edee5ac936eee7a0ddsewardj   else
464d266447c09a99122cbc220edee5ac936eee7a0ddsewardj      return 0;
465d266447c09a99122cbc220edee5ac936eee7a0ddsewardj}
466d266447c09a99122cbc220edee5ac936eee7a0ddsewardj
4676c299f3acab617581ea504e45fbb6cab24c2b29fsewardj/* CALLED FROM GENERATED CODE: CLEAN HELPER */
4686c299f3acab617581ea504e45fbb6cab24c2b29fsewardj/* Calculate the specified condition from the thunk components, in the
4693c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj   lowest bit of the word (bit 0).  Returned bits 31:1 are zero. */
470bb8b394c97a23a17f60712afff6484ab340a93casewardjUInt armg_calculate_condition ( UInt cond_n_op /* (ARMCondcode << 4) | cc_op */,
4716c299f3acab617581ea504e45fbb6cab24c2b29fsewardj                                UInt cc_dep1,
4726c299f3acab617581ea504e45fbb6cab24c2b29fsewardj                                UInt cc_dep2, UInt cc_dep3 )
4736c299f3acab617581ea504e45fbb6cab24c2b29fsewardj{
4746c299f3acab617581ea504e45fbb6cab24c2b29fsewardj   UInt cond  = cond_n_op >> 4;
4756c299f3acab617581ea504e45fbb6cab24c2b29fsewardj   UInt cc_op = cond_n_op & 0xF;
4763c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj   UInt nf, zf, vf, cf, inv;
477d266447c09a99122cbc220edee5ac936eee7a0ddsewardj   //   vex_printf("XXXXXXXX %x %x %x %x\n",
478d266447c09a99122cbc220edee5ac936eee7a0ddsewardj   //              cond_n_op, cc_dep1, cc_dep2, cc_dep3);
479d266447c09a99122cbc220edee5ac936eee7a0ddsewardj
480d266447c09a99122cbc220edee5ac936eee7a0ddsewardj   // skip flags computation in this case
481d266447c09a99122cbc220edee5ac936eee7a0ddsewardj   if (cond == ARMCondAL) return 1;
482d266447c09a99122cbc220edee5ac936eee7a0ddsewardj
483d266447c09a99122cbc220edee5ac936eee7a0ddsewardj   inv  = cond & 1;
4842a9ad023890d3b34cf45e429df2a8ae88b419128sewardj
4852a9ad023890d3b34cf45e429df2a8ae88b419128sewardj   switch (cond) {
4866c299f3acab617581ea504e45fbb6cab24c2b29fsewardj      case ARMCondEQ:    // Z=1         => z
4876c299f3acab617581ea504e45fbb6cab24c2b29fsewardj      case ARMCondNE:    // Z=0
4883c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         zf = armg_calculate_flag_z(cc_op, cc_dep1, cc_dep2, cc_dep3);
4893c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         return inv ^ zf;
4906c299f3acab617581ea504e45fbb6cab24c2b29fsewardj
4916c299f3acab617581ea504e45fbb6cab24c2b29fsewardj      case ARMCondHS:    // C=1         => c
4926c299f3acab617581ea504e45fbb6cab24c2b29fsewardj      case ARMCondLO:    // C=0
4933c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         cf = armg_calculate_flag_c(cc_op, cc_dep1, cc_dep2, cc_dep3);
4943c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         return inv ^ cf;
4956c299f3acab617581ea504e45fbb6cab24c2b29fsewardj
4966c299f3acab617581ea504e45fbb6cab24c2b29fsewardj      case ARMCondMI:    // N=1         => n
4976c299f3acab617581ea504e45fbb6cab24c2b29fsewardj      case ARMCondPL:    // N=0
4983c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         nf = armg_calculate_flag_n(cc_op, cc_dep1, cc_dep2, cc_dep3);
4993c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         return inv ^ nf;
5006c299f3acab617581ea504e45fbb6cab24c2b29fsewardj
5016c299f3acab617581ea504e45fbb6cab24c2b29fsewardj      case ARMCondVS:    // V=1         => v
5026c299f3acab617581ea504e45fbb6cab24c2b29fsewardj      case ARMCondVC:    // V=0
5033c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         vf = armg_calculate_flag_v(cc_op, cc_dep1, cc_dep2, cc_dep3);
5043c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         return inv ^ vf;
5056c299f3acab617581ea504e45fbb6cab24c2b29fsewardj
5066c299f3acab617581ea504e45fbb6cab24c2b29fsewardj      case ARMCondHI:    // C=1 && Z=0   => c & ~z
5076c299f3acab617581ea504e45fbb6cab24c2b29fsewardj      case ARMCondLS:    // C=0 || Z=1
5083c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         cf = armg_calculate_flag_c(cc_op, cc_dep1, cc_dep2, cc_dep3);
5093c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         zf = armg_calculate_flag_z(cc_op, cc_dep1, cc_dep2, cc_dep3);
510f7e595817bf7acaa9ac392a3c87676968f6eab19sewardj         return inv ^ (1 & (cf & ~zf));
5116c299f3acab617581ea504e45fbb6cab24c2b29fsewardj
5126c299f3acab617581ea504e45fbb6cab24c2b29fsewardj      case ARMCondGE:    // N=V          => ~(n^v)
5136c299f3acab617581ea504e45fbb6cab24c2b29fsewardj      case ARMCondLT:    // N!=V
5143c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         nf = armg_calculate_flag_n(cc_op, cc_dep1, cc_dep2, cc_dep3);
5153c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         vf = armg_calculate_flag_v(cc_op, cc_dep1, cc_dep2, cc_dep3);
5163c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         return inv ^ (1 & ~(nf ^ vf));
5176c299f3acab617581ea504e45fbb6cab24c2b29fsewardj
5186c299f3acab617581ea504e45fbb6cab24c2b29fsewardj      case ARMCondGT:    // Z=0 && N=V   => ~z & ~(n^v)  =>  ~(z | (n^v))
5196c299f3acab617581ea504e45fbb6cab24c2b29fsewardj      case ARMCondLE:    // Z=1 || N!=V
5203c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         nf = armg_calculate_flag_n(cc_op, cc_dep1, cc_dep2, cc_dep3);
5213c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         vf = armg_calculate_flag_v(cc_op, cc_dep1, cc_dep2, cc_dep3);
5223c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         zf = armg_calculate_flag_z(cc_op, cc_dep1, cc_dep2, cc_dep3);
5233c14925dc79642a6c04bb7bf99253a853c1e3f36sewardj         return inv ^ (1 & ~(zf | (nf ^ vf)));
5246c299f3acab617581ea504e45fbb6cab24c2b29fsewardj
525d266447c09a99122cbc220edee5ac936eee7a0ddsewardj      case ARMCondAL: // handled above
5266c299f3acab617581ea504e45fbb6cab24c2b29fsewardj      case ARMCondNV: // should never get here: Illegal instr
5276c299f3acab617581ea504e45fbb6cab24c2b29fsewardj      default:
5286c299f3acab617581ea504e45fbb6cab24c2b29fsewardj         /* shouldn't really make these calls from generated code */
5296c299f3acab617581ea504e45fbb6cab24c2b29fsewardj         vex_printf("armg_calculate_condition(ARM)"
5306c299f3acab617581ea504e45fbb6cab24c2b29fsewardj                    "( %u, %u, 0x%x, 0x%x, 0x%x )\n",
5316c299f3acab617581ea504e45fbb6cab24c2b29fsewardj                    cond, cc_op, cc_dep1, cc_dep2, cc_dep3 );
5326c299f3acab617581ea504e45fbb6cab24c2b29fsewardj         vpanic("armg_calculate_condition(ARM)");
5332a9ad023890d3b34cf45e429df2a8ae88b419128sewardj   }
5342a9ad023890d3b34cf45e429df2a8ae88b419128sewardj}
5352a9ad023890d3b34cf45e429df2a8ae88b419128sewardj
5362a9ad023890d3b34cf45e429df2a8ae88b419128sewardj
5376c299f3acab617581ea504e45fbb6cab24c2b29fsewardj/*---------------------------------------------------------------*/
5386c299f3acab617581ea504e45fbb6cab24c2b29fsewardj/*--- Flag-helpers translation-time function specialisers.    ---*/
5396c299f3acab617581ea504e45fbb6cab24c2b29fsewardj/*--- These help iropt specialise calls the above run-time    ---*/
5406c299f3acab617581ea504e45fbb6cab24c2b29fsewardj/*--- flags functions.                                        ---*/
5416c299f3acab617581ea504e45fbb6cab24c2b29fsewardj/*---------------------------------------------------------------*/
5426c299f3acab617581ea504e45fbb6cab24c2b29fsewardj
5432a9ad023890d3b34cf45e429df2a8ae88b419128sewardj/* Used by the optimiser to try specialisations.  Returns an
5442a9ad023890d3b34cf45e429df2a8ae88b419128sewardj   equivalent expression, or NULL if none. */
5452a9ad023890d3b34cf45e429df2a8ae88b419128sewardj
5462a9ad023890d3b34cf45e429df2a8ae88b419128sewardjstatic Bool isU32 ( IRExpr* e, UInt n )
5472a9ad023890d3b34cf45e429df2a8ae88b419128sewardj{
5486c299f3acab617581ea504e45fbb6cab24c2b29fsewardj   return
5496c299f3acab617581ea504e45fbb6cab24c2b29fsewardj      toBool( e->tag == Iex_Const
5506c299f3acab617581ea504e45fbb6cab24c2b29fsewardj              && e->Iex.Const.con->tag == Ico_U32
5516c299f3acab617581ea504e45fbb6cab24c2b29fsewardj              && e->Iex.Const.con->Ico.U32 == n );
5522a9ad023890d3b34cf45e429df2a8ae88b419128sewardj}
5536c299f3acab617581ea504e45fbb6cab24c2b29fsewardj
5541ff4756e1731485e6bf3cd96717cd8398daec1f2florianIRExpr* guest_arm_spechelper ( const HChar* function_name,
555d266447c09a99122cbc220edee5ac936eee7a0ddsewardj                               IRExpr** args,
556d266447c09a99122cbc220edee5ac936eee7a0ddsewardj                               IRStmt** precedingStmts,
557d266447c09a99122cbc220edee5ac936eee7a0ddsewardj                               Int      n_precedingStmts )
5582a9ad023890d3b34cf45e429df2a8ae88b419128sewardj{
5596c299f3acab617581ea504e45fbb6cab24c2b29fsewardj#  define unop(_op,_a1) IRExpr_Unop((_op),(_a1))
5606c299f3acab617581ea504e45fbb6cab24c2b29fsewardj#  define binop(_op,_a1,_a2) IRExpr_Binop((_op),(_a1),(_a2))
5616c299f3acab617581ea504e45fbb6cab24c2b29fsewardj#  define mkU32(_n) IRExpr_Const(IRConst_U32(_n))
5626c299f3acab617581ea504e45fbb6cab24c2b29fsewardj#  define mkU8(_n)  IRExpr_Const(IRConst_U8(_n))
5636c299f3acab617581ea504e45fbb6cab24c2b29fsewardj
5646c299f3acab617581ea504e45fbb6cab24c2b29fsewardj   Int i, arity = 0;
5656c299f3acab617581ea504e45fbb6cab24c2b29fsewardj   for (i = 0; args[i]; i++)
5666c299f3acab617581ea504e45fbb6cab24c2b29fsewardj      arity++;
5676c299f3acab617581ea504e45fbb6cab24c2b29fsewardj#  if 0
5686c299f3acab617581ea504e45fbb6cab24c2b29fsewardj   vex_printf("spec request:\n");
5696c299f3acab617581ea504e45fbb6cab24c2b29fsewardj   vex_printf("   %s  ", function_name);
5706c299f3acab617581ea504e45fbb6cab24c2b29fsewardj   for (i = 0; i < arity; i++) {
5716c299f3acab617581ea504e45fbb6cab24c2b29fsewardj      vex_printf("  ");
5726c299f3acab617581ea504e45fbb6cab24c2b29fsewardj      ppIRExpr(args[i]);
5736c299f3acab617581ea504e45fbb6cab24c2b29fsewardj   }
5746c299f3acab617581ea504e45fbb6cab24c2b29fsewardj   vex_printf("\n");
5756c299f3acab617581ea504e45fbb6cab24c2b29fsewardj#  endif
5766c299f3acab617581ea504e45fbb6cab24c2b29fsewardj
577d266447c09a99122cbc220edee5ac936eee7a0ddsewardj   /* --------- specialising "armg_calculate_condition" --------- */
5786c299f3acab617581ea504e45fbb6cab24c2b29fsewardj
5796c299f3acab617581ea504e45fbb6cab24c2b29fsewardj   if (vex_streq(function_name, "armg_calculate_condition")) {
580bb8b394c97a23a17f60712afff6484ab340a93casewardj
581bb8b394c97a23a17f60712afff6484ab340a93casewardj      /* specialise calls to the "armg_calculate_condition" function.
582bb8b394c97a23a17f60712afff6484ab340a93casewardj         Not sure whether this is strictly necessary, but: the
583bb8b394c97a23a17f60712afff6484ab340a93casewardj         replacement IR must produce only the values 0 or 1.  Bits
584bb8b394c97a23a17f60712afff6484ab340a93casewardj         31:1 are required to be zero. */
585bb8b394c97a23a17f60712afff6484ab340a93casewardj      IRExpr *cond_n_op, *cc_dep1, *cc_dep2, *cc_ndep;
5866c299f3acab617581ea504e45fbb6cab24c2b29fsewardj      vassert(arity == 4);
587bb8b394c97a23a17f60712afff6484ab340a93casewardj      cond_n_op = args[0]; /* (ARMCondcode << 4)  |  ARMG_CC_OP_* */
5886c299f3acab617581ea504e45fbb6cab24c2b29fsewardj      cc_dep1   = args[1];
5896c299f3acab617581ea504e45fbb6cab24c2b29fsewardj      cc_dep2   = args[2];
590bb8b394c97a23a17f60712afff6484ab340a93casewardj      cc_ndep   = args[3];
5916c299f3acab617581ea504e45fbb6cab24c2b29fsewardj
5926c299f3acab617581ea504e45fbb6cab24c2b29fsewardj      /*---------------- SUB ----------------*/
5936c299f3acab617581ea504e45fbb6cab24c2b29fsewardj
5946c299f3acab617581ea504e45fbb6cab24c2b29fsewardj      if (isU32(cond_n_op, (ARMCondEQ << 4) | ARMG_CC_OP_SUB)) {
5956c299f3acab617581ea504e45fbb6cab24c2b29fsewardj         /* EQ after SUB --> test argL == argR */
5966c299f3acab617581ea504e45fbb6cab24c2b29fsewardj         return unop(Iop_1Uto32,
5976c299f3acab617581ea504e45fbb6cab24c2b29fsewardj                     binop(Iop_CmpEQ32, cc_dep1, cc_dep2));
5986c299f3acab617581ea504e45fbb6cab24c2b29fsewardj      }
5996c299f3acab617581ea504e45fbb6cab24c2b29fsewardj      if (isU32(cond_n_op, (ARMCondNE << 4) | ARMG_CC_OP_SUB)) {
6006c299f3acab617581ea504e45fbb6cab24c2b29fsewardj         /* NE after SUB --> test argL != argR */
6016c299f3acab617581ea504e45fbb6cab24c2b29fsewardj         return unop(Iop_1Uto32,
6026c299f3acab617581ea504e45fbb6cab24c2b29fsewardj                     binop(Iop_CmpNE32, cc_dep1, cc_dep2));
6036c299f3acab617581ea504e45fbb6cab24c2b29fsewardj      }
6046c299f3acab617581ea504e45fbb6cab24c2b29fsewardj
605285c24d360ca1b0ab75728b045a609aa17f63ac6sewardj      if (isU32(cond_n_op, (ARMCondGT << 4) | ARMG_CC_OP_SUB)) {
606285c24d360ca1b0ab75728b045a609aa17f63ac6sewardj         /* GT after SUB --> test argL >s argR
607285c24d360ca1b0ab75728b045a609aa17f63ac6sewardj                         --> test argR <s argL */
608285c24d360ca1b0ab75728b045a609aa17f63ac6sewardj         return unop(Iop_1Uto32,
609285c24d360ca1b0ab75728b045a609aa17f63ac6sewardj                     binop(Iop_CmpLT32S, cc_dep2, cc_dep1));
610285c24d360ca1b0ab75728b045a609aa17f63ac6sewardj      }
6116c299f3acab617581ea504e45fbb6cab24c2b29fsewardj      if (isU32(cond_n_op, (ARMCondLE << 4) | ARMG_CC_OP_SUB)) {
6126c299f3acab617581ea504e45fbb6cab24c2b29fsewardj         /* LE after SUB --> test argL <=s argR */
6136c299f3acab617581ea504e45fbb6cab24c2b29fsewardj         return unop(Iop_1Uto32,
6146c299f3acab617581ea504e45fbb6cab24c2b29fsewardj                     binop(Iop_CmpLE32S, cc_dep1, cc_dep2));
6156c299f3acab617581ea504e45fbb6cab24c2b29fsewardj      }
6166c299f3acab617581ea504e45fbb6cab24c2b29fsewardj
6176c299f3acab617581ea504e45fbb6cab24c2b29fsewardj      if (isU32(cond_n_op, (ARMCondLT << 4) | ARMG_CC_OP_SUB)) {
618d266447c09a99122cbc220edee5ac936eee7a0ddsewardj         /* LT after SUB --> test argL <s argR */
6196c299f3acab617581ea504e45fbb6cab24c2b29fsewardj         return unop(Iop_1Uto32,
6206c299f3acab617581ea504e45fbb6cab24c2b29fsewardj                     binop(Iop_CmpLT32S, cc_dep1, cc_dep2));
6216c299f3acab617581ea504e45fbb6cab24c2b29fsewardj      }
6226c299f3acab617581ea504e45fbb6cab24c2b29fsewardj
6236c299f3acab617581ea504e45fbb6cab24c2b29fsewardj      if (isU32(cond_n_op, (ARMCondGE << 4) | ARMG_CC_OP_SUB)) {
6246c299f3acab617581ea504e45fbb6cab24c2b29fsewardj         /* GE after SUB --> test argL >=s argR
6256c299f3acab617581ea504e45fbb6cab24c2b29fsewardj                         --> test argR <=s argL */
6266c299f3acab617581ea504e45fbb6cab24c2b29fsewardj         return unop(Iop_1Uto32,
6276c299f3acab617581ea504e45fbb6cab24c2b29fsewardj                     binop(Iop_CmpLE32S, cc_dep2, cc_dep1));
6286c299f3acab617581ea504e45fbb6cab24c2b29fsewardj      }
6296c299f3acab617581ea504e45fbb6cab24c2b29fsewardj
6306c299f3acab617581ea504e45fbb6cab24c2b29fsewardj      if (isU32(cond_n_op, (ARMCondHS << 4) | ARMG_CC_OP_SUB)) {
6316c299f3acab617581ea504e45fbb6cab24c2b29fsewardj         /* HS after SUB --> test argL >=u argR
6326c299f3acab617581ea504e45fbb6cab24c2b29fsewardj                         --> test argR <=u argL */
6336c299f3acab617581ea504e45fbb6cab24c2b29fsewardj         return unop(Iop_1Uto32,
6346c299f3acab617581ea504e45fbb6cab24c2b29fsewardj                     binop(Iop_CmpLE32U, cc_dep2, cc_dep1));
6356c299f3acab617581ea504e45fbb6cab24c2b29fsewardj      }
636285c24d360ca1b0ab75728b045a609aa17f63ac6sewardj      if (isU32(cond_n_op, (ARMCondLO << 4) | ARMG_CC_OP_SUB)) {
637285c24d360ca1b0ab75728b045a609aa17f63ac6sewardj         /* LO after SUB --> test argL <u argR */
638285c24d360ca1b0ab75728b045a609aa17f63ac6sewardj         return unop(Iop_1Uto32,
639285c24d360ca1b0ab75728b045a609aa17f63ac6sewardj                     binop(Iop_CmpLT32U, cc_dep1, cc_dep2));
640285c24d360ca1b0ab75728b045a609aa17f63ac6sewardj      }
6416c299f3acab617581ea504e45fbb6cab24c2b29fsewardj
6426c299f3acab617581ea504e45fbb6cab24c2b29fsewardj      if (isU32(cond_n_op, (ARMCondLS << 4) | ARMG_CC_OP_SUB)) {
6436c299f3acab617581ea504e45fbb6cab24c2b29fsewardj         /* LS after SUB --> test argL <=u argR */
6446c299f3acab617581ea504e45fbb6cab24c2b29fsewardj         return unop(Iop_1Uto32,
6456c299f3acab617581ea504e45fbb6cab24c2b29fsewardj                     binop(Iop_CmpLE32U, cc_dep1, cc_dep2));
6466c299f3acab617581ea504e45fbb6cab24c2b29fsewardj      }
64726de96421c01ede25a0691f793174e07a5f0ffe0sewardj      if (isU32(cond_n_op, (ARMCondHI << 4) | ARMG_CC_OP_SUB)) {
64826de96421c01ede25a0691f793174e07a5f0ffe0sewardj         /* HI after SUB --> test argL >u argR
64926de96421c01ede25a0691f793174e07a5f0ffe0sewardj                         --> test argR <u argL */
65026de96421c01ede25a0691f793174e07a5f0ffe0sewardj         return unop(Iop_1Uto32,
65126de96421c01ede25a0691f793174e07a5f0ffe0sewardj                     binop(Iop_CmpLT32U, cc_dep2, cc_dep1));
65226de96421c01ede25a0691f793174e07a5f0ffe0sewardj      }
6536c299f3acab617581ea504e45fbb6cab24c2b29fsewardj
654bb8b394c97a23a17f60712afff6484ab340a93casewardj      /*---------------- SBB ----------------*/
655bb8b394c97a23a17f60712afff6484ab340a93casewardj
656bb8b394c97a23a17f60712afff6484ab340a93casewardj      if (isU32(cond_n_op, (ARMCondHS << 4) | ARMG_CC_OP_SBB)) {
657bb8b394c97a23a17f60712afff6484ab340a93casewardj         /* This seems to happen a lot in softfloat code, eg __divdf3+140 */
658bb8b394c97a23a17f60712afff6484ab340a93casewardj         /* thunk is: (dep1=argL, dep2=argR, ndep=oldC) */
659bb8b394c97a23a17f60712afff6484ab340a93casewardj         /* HS after SBB (same as C after SBB below)
660bb8b394c97a23a17f60712afff6484ab340a93casewardj            --> oldC ? (argL >=u argR) : (argL >u argR)
661bb8b394c97a23a17f60712afff6484ab340a93casewardj            --> oldC ? (argR <=u argL) : (argR <u argL)
662bb8b394c97a23a17f60712afff6484ab340a93casewardj         */
663bb8b394c97a23a17f60712afff6484ab340a93casewardj         return
66499dd03e04a6914d90d5fee727d61d76905334becflorian            IRExpr_ITE(
665d0f1a93e8e4595616087adb7b1e51ad0bbacdec3sewardj               binop(Iop_CmpNE32, cc_ndep, mkU32(0)),
666bb8b394c97a23a17f60712afff6484ab340a93casewardj               /* case oldC != 0 */
66799dd03e04a6914d90d5fee727d61d76905334becflorian               unop(Iop_1Uto32, binop(Iop_CmpLE32U, cc_dep2, cc_dep1)),
66899dd03e04a6914d90d5fee727d61d76905334becflorian               /* case oldC == 0 */
66999dd03e04a6914d90d5fee727d61d76905334becflorian               unop(Iop_1Uto32, binop(Iop_CmpLT32U, cc_dep2, cc_dep1))
670bb8b394c97a23a17f60712afff6484ab340a93casewardj            );
671bb8b394c97a23a17f60712afff6484ab340a93casewardj      }
672bb8b394c97a23a17f60712afff6484ab340a93casewardj
6736c299f3acab617581ea504e45fbb6cab24c2b29fsewardj      /*---------------- LOGIC ----------------*/
674bb8b394c97a23a17f60712afff6484ab340a93casewardj
6756c299f3acab617581ea504e45fbb6cab24c2b29fsewardj      if (isU32(cond_n_op, (ARMCondEQ << 4) | ARMG_CC_OP_LOGIC)) {
6766c299f3acab617581ea504e45fbb6cab24c2b29fsewardj         /* EQ after LOGIC --> test res == 0 */
6776c299f3acab617581ea504e45fbb6cab24c2b29fsewardj         return unop(Iop_1Uto32,
6786c299f3acab617581ea504e45fbb6cab24c2b29fsewardj                     binop(Iop_CmpEQ32, cc_dep1, mkU32(0)));
6796c299f3acab617581ea504e45fbb6cab24c2b29fsewardj      }
6806c299f3acab617581ea504e45fbb6cab24c2b29fsewardj      if (isU32(cond_n_op, (ARMCondNE << 4) | ARMG_CC_OP_LOGIC)) {
6816c299f3acab617581ea504e45fbb6cab24c2b29fsewardj         /* NE after LOGIC --> test res != 0 */
6826c299f3acab617581ea504e45fbb6cab24c2b29fsewardj         return unop(Iop_1Uto32,
6836c299f3acab617581ea504e45fbb6cab24c2b29fsewardj                     binop(Iop_CmpNE32, cc_dep1, mkU32(0)));
6846c299f3acab617581ea504e45fbb6cab24c2b29fsewardj      }
6856c299f3acab617581ea504e45fbb6cab24c2b29fsewardj
686540acf576e17427c55ba021f84d5f701aea6734fsewardj      if (isU32(cond_n_op, (ARMCondPL << 4) | ARMG_CC_OP_LOGIC)) {
687540acf576e17427c55ba021f84d5f701aea6734fsewardj         /* PL after LOGIC --> test (res >> 31) == 0 */
688540acf576e17427c55ba021f84d5f701aea6734fsewardj         return unop(Iop_1Uto32,
689540acf576e17427c55ba021f84d5f701aea6734fsewardj                     binop(Iop_CmpEQ32,
690540acf576e17427c55ba021f84d5f701aea6734fsewardj                           binop(Iop_Shr32, cc_dep1, mkU8(31)),
691540acf576e17427c55ba021f84d5f701aea6734fsewardj                           mkU32(0)));
692540acf576e17427c55ba021f84d5f701aea6734fsewardj      }
693540acf576e17427c55ba021f84d5f701aea6734fsewardj      if (isU32(cond_n_op, (ARMCondMI << 4) | ARMG_CC_OP_LOGIC)) {
694540acf576e17427c55ba021f84d5f701aea6734fsewardj         /* MI after LOGIC --> test (res >> 31) == 1 */
695540acf576e17427c55ba021f84d5f701aea6734fsewardj         return unop(Iop_1Uto32,
696540acf576e17427c55ba021f84d5f701aea6734fsewardj                     binop(Iop_CmpEQ32,
697540acf576e17427c55ba021f84d5f701aea6734fsewardj                           binop(Iop_Shr32, cc_dep1, mkU8(31)),
698540acf576e17427c55ba021f84d5f701aea6734fsewardj                           mkU32(1)));
699540acf576e17427c55ba021f84d5f701aea6734fsewardj      }
700540acf576e17427c55ba021f84d5f701aea6734fsewardj
701ed055d03c4eee0487ac93be5760bae88fb3f4c23sewardj      /*---------------- COPY ----------------*/
702ed055d03c4eee0487ac93be5760bae88fb3f4c23sewardj
703e0542187817e09818c7eba042a1c8ebc5b85544csewardj      /* --- 0,1 --- */
704e0542187817e09818c7eba042a1c8ebc5b85544csewardj      if (isU32(cond_n_op, (ARMCondEQ << 4) | ARMG_CC_OP_COPY)) {
705e0542187817e09818c7eba042a1c8ebc5b85544csewardj         /* EQ after COPY --> (cc_dep1 >> ARMG_CC_SHIFT_Z) & 1 */
706e0542187817e09818c7eba042a1c8ebc5b85544csewardj         return binop(Iop_And32,
707e0542187817e09818c7eba042a1c8ebc5b85544csewardj                      binop(Iop_Shr32, cc_dep1,
708e0542187817e09818c7eba042a1c8ebc5b85544csewardj                            mkU8(ARMG_CC_SHIFT_Z)),
709e0542187817e09818c7eba042a1c8ebc5b85544csewardj                      mkU32(1));
710e0542187817e09818c7eba042a1c8ebc5b85544csewardj      }
711ed055d03c4eee0487ac93be5760bae88fb3f4c23sewardj      if (isU32(cond_n_op, (ARMCondNE << 4) | ARMG_CC_OP_COPY)) {
712ed055d03c4eee0487ac93be5760bae88fb3f4c23sewardj         /* NE after COPY --> ((cc_dep1 >> ARMG_CC_SHIFT_Z) ^ 1) & 1 */
713ed055d03c4eee0487ac93be5760bae88fb3f4c23sewardj         return binop(Iop_And32,
714ed055d03c4eee0487ac93be5760bae88fb3f4c23sewardj                      binop(Iop_Xor32,
715ed055d03c4eee0487ac93be5760bae88fb3f4c23sewardj                            binop(Iop_Shr32, cc_dep1,
716ed055d03c4eee0487ac93be5760bae88fb3f4c23sewardj                                             mkU8(ARMG_CC_SHIFT_Z)),
717ed055d03c4eee0487ac93be5760bae88fb3f4c23sewardj                            mkU32(1)),
718ed055d03c4eee0487ac93be5760bae88fb3f4c23sewardj                      mkU32(1));
719ed055d03c4eee0487ac93be5760bae88fb3f4c23sewardj      }
720ed055d03c4eee0487ac93be5760bae88fb3f4c23sewardj
721e0542187817e09818c7eba042a1c8ebc5b85544csewardj      /* --- 4,5 --- */
722e0542187817e09818c7eba042a1c8ebc5b85544csewardj      if (isU32(cond_n_op, (ARMCondMI << 4) | ARMG_CC_OP_COPY)) {
723e0542187817e09818c7eba042a1c8ebc5b85544csewardj         /* MI after COPY --> (cc_dep1 >> ARMG_CC_SHIFT_N) & 1 */
724e0542187817e09818c7eba042a1c8ebc5b85544csewardj         return binop(Iop_And32,
725e0542187817e09818c7eba042a1c8ebc5b85544csewardj                      binop(Iop_Shr32, cc_dep1,
726e0542187817e09818c7eba042a1c8ebc5b85544csewardj                            mkU8(ARMG_CC_SHIFT_N)),
727e0542187817e09818c7eba042a1c8ebc5b85544csewardj                      mkU32(1));
728e0542187817e09818c7eba042a1c8ebc5b85544csewardj      }
729e0542187817e09818c7eba042a1c8ebc5b85544csewardj      if (isU32(cond_n_op, (ARMCondPL << 4) | ARMG_CC_OP_COPY)) {
730e0542187817e09818c7eba042a1c8ebc5b85544csewardj         /* PL after COPY --> ((cc_dep1 >> ARMG_CC_SHIFT_N) ^ 1) & 1 */
731e0542187817e09818c7eba042a1c8ebc5b85544csewardj         return binop(Iop_And32,
732e0542187817e09818c7eba042a1c8ebc5b85544csewardj                      binop(Iop_Xor32,
733e0542187817e09818c7eba042a1c8ebc5b85544csewardj                            binop(Iop_Shr32, cc_dep1,
734e0542187817e09818c7eba042a1c8ebc5b85544csewardj                                             mkU8(ARMG_CC_SHIFT_N)),
735e0542187817e09818c7eba042a1c8ebc5b85544csewardj                            mkU32(1)),
736e0542187817e09818c7eba042a1c8ebc5b85544csewardj                      mkU32(1));
737e0542187817e09818c7eba042a1c8ebc5b85544csewardj      }
738e0542187817e09818c7eba042a1c8ebc5b85544csewardj
739e0542187817e09818c7eba042a1c8ebc5b85544csewardj      /* --- 12,13 --- */
740e0542187817e09818c7eba042a1c8ebc5b85544csewardj      if (isU32(cond_n_op, (ARMCondGT << 4) | ARMG_CC_OP_COPY)) {
741e0542187817e09818c7eba042a1c8ebc5b85544csewardj         /* GT after COPY --> ((z | (n^v)) & 1) ^ 1 */
742e0542187817e09818c7eba042a1c8ebc5b85544csewardj         IRExpr* n = binop(Iop_Shr32, cc_dep1, mkU8(ARMG_CC_SHIFT_N));
743e0542187817e09818c7eba042a1c8ebc5b85544csewardj         IRExpr* v = binop(Iop_Shr32, cc_dep1, mkU8(ARMG_CC_SHIFT_V));
744e0542187817e09818c7eba042a1c8ebc5b85544csewardj         IRExpr* z = binop(Iop_Shr32, cc_dep1, mkU8(ARMG_CC_SHIFT_Z));
745e0542187817e09818c7eba042a1c8ebc5b85544csewardj         return binop(Iop_Xor32,
746e0542187817e09818c7eba042a1c8ebc5b85544csewardj                      binop(Iop_And32,
747e0542187817e09818c7eba042a1c8ebc5b85544csewardj                            binop(Iop_Or32, z, binop(Iop_Xor32, n, v)),
748e0542187817e09818c7eba042a1c8ebc5b85544csewardj                            mkU32(1)),
749e0542187817e09818c7eba042a1c8ebc5b85544csewardj                      mkU32(1));
750e0542187817e09818c7eba042a1c8ebc5b85544csewardj      }
751e0542187817e09818c7eba042a1c8ebc5b85544csewardj      if (isU32(cond_n_op, (ARMCondLE << 4) | ARMG_CC_OP_COPY)) {
752e0542187817e09818c7eba042a1c8ebc5b85544csewardj         /* LE after COPY --> ((z | (n^v)) & 1) ^ 0 */
753e0542187817e09818c7eba042a1c8ebc5b85544csewardj         IRExpr* n = binop(Iop_Shr32, cc_dep1, mkU8(ARMG_CC_SHIFT_N));
754e0542187817e09818c7eba042a1c8ebc5b85544csewardj         IRExpr* v = binop(Iop_Shr32, cc_dep1, mkU8(ARMG_CC_SHIFT_V));
755e0542187817e09818c7eba042a1c8ebc5b85544csewardj         IRExpr* z = binop(Iop_Shr32, cc_dep1, mkU8(ARMG_CC_SHIFT_Z));
756e0542187817e09818c7eba042a1c8ebc5b85544csewardj         return binop(Iop_Xor32,
757e0542187817e09818c7eba042a1c8ebc5b85544csewardj                      binop(Iop_And32,
758e0542187817e09818c7eba042a1c8ebc5b85544csewardj                            binop(Iop_Or32, z, binop(Iop_Xor32, n, v)),
759e0542187817e09818c7eba042a1c8ebc5b85544csewardj                            mkU32(1)),
760e0542187817e09818c7eba042a1c8ebc5b85544csewardj                      mkU32(0));
761e0542187817e09818c7eba042a1c8ebc5b85544csewardj      }
762e0542187817e09818c7eba042a1c8ebc5b85544csewardj
763d266447c09a99122cbc220edee5ac936eee7a0ddsewardj      /*----------------- AL -----------------*/
764bb8b394c97a23a17f60712afff6484ab340a93casewardj
765d266447c09a99122cbc220edee5ac936eee7a0ddsewardj      /* A critically important case for Thumb code.
766d266447c09a99122cbc220edee5ac936eee7a0ddsewardj
767d266447c09a99122cbc220edee5ac936eee7a0ddsewardj         What we're trying to spot is the case where cond_n_op is an
768d266447c09a99122cbc220edee5ac936eee7a0ddsewardj         expression of the form Or32(..., 0xE0) since that means the
769d266447c09a99122cbc220edee5ac936eee7a0ddsewardj         caller is asking for CondAL and we can simply return 1
770d266447c09a99122cbc220edee5ac936eee7a0ddsewardj         without caring what the ... part is.  This is a potentially
771d266447c09a99122cbc220edee5ac936eee7a0ddsewardj         dodgy kludge in that it assumes that the ... part has zeroes
772d266447c09a99122cbc220edee5ac936eee7a0ddsewardj         in bits 7:4, so that the result of the Or32 is guaranteed to
773d266447c09a99122cbc220edee5ac936eee7a0ddsewardj         be 0xE in bits 7:4.  Given that the places where this first
774d266447c09a99122cbc220edee5ac936eee7a0ddsewardj         arg are constructed (in guest_arm_toIR.c) are very
775d266447c09a99122cbc220edee5ac936eee7a0ddsewardj         constrained, we can get away with this.  To make this
776d266447c09a99122cbc220edee5ac936eee7a0ddsewardj         guaranteed safe would require to have a new primop, Slice44
777d266447c09a99122cbc220edee5ac936eee7a0ddsewardj         or some such, thusly
778d266447c09a99122cbc220edee5ac936eee7a0ddsewardj
779d266447c09a99122cbc220edee5ac936eee7a0ddsewardj         Slice44(arg1, arg2) = 0--(24)--0 arg1[7:4] arg2[3:0]
780d266447c09a99122cbc220edee5ac936eee7a0ddsewardj
781d266447c09a99122cbc220edee5ac936eee7a0ddsewardj         and we would then look for Slice44(0xE0, ...)
782d266447c09a99122cbc220edee5ac936eee7a0ddsewardj         which would give the required safety property.
783d266447c09a99122cbc220edee5ac936eee7a0ddsewardj
784d266447c09a99122cbc220edee5ac936eee7a0ddsewardj         It would be infeasibly expensive to scan backwards through
785d266447c09a99122cbc220edee5ac936eee7a0ddsewardj         the entire block looking for an assignment to the temp, so
786d266447c09a99122cbc220edee5ac936eee7a0ddsewardj         just look at the previous 16 statements.  That should find it
787d266447c09a99122cbc220edee5ac936eee7a0ddsewardj         if it is an interesting case, as a result of how the
788d266447c09a99122cbc220edee5ac936eee7a0ddsewardj         boilerplate guff at the start of each Thumb insn translation
789d266447c09a99122cbc220edee5ac936eee7a0ddsewardj         is made.
790d266447c09a99122cbc220edee5ac936eee7a0ddsewardj      */
791d266447c09a99122cbc220edee5ac936eee7a0ddsewardj      if (cond_n_op->tag == Iex_RdTmp) {
792d266447c09a99122cbc220edee5ac936eee7a0ddsewardj         Int    j;
793d266447c09a99122cbc220edee5ac936eee7a0ddsewardj         IRTemp look_for = cond_n_op->Iex.RdTmp.tmp;
794d266447c09a99122cbc220edee5ac936eee7a0ddsewardj         Int    limit    = n_precedingStmts - 16;
795d266447c09a99122cbc220edee5ac936eee7a0ddsewardj         if (limit < 0) limit = 0;
796d266447c09a99122cbc220edee5ac936eee7a0ddsewardj         if (0) vex_printf("scanning %d .. %d\n", n_precedingStmts-1, limit);
797d266447c09a99122cbc220edee5ac936eee7a0ddsewardj         for (j = n_precedingStmts - 1; j >= limit; j--) {
798d266447c09a99122cbc220edee5ac936eee7a0ddsewardj            IRStmt* st = precedingStmts[j];
799d266447c09a99122cbc220edee5ac936eee7a0ddsewardj            if (st->tag == Ist_WrTmp
800d266447c09a99122cbc220edee5ac936eee7a0ddsewardj                && st->Ist.WrTmp.tmp == look_for
801d266447c09a99122cbc220edee5ac936eee7a0ddsewardj                && st->Ist.WrTmp.data->tag == Iex_Binop
802d266447c09a99122cbc220edee5ac936eee7a0ddsewardj                && st->Ist.WrTmp.data->Iex.Binop.op == Iop_Or32
803d266447c09a99122cbc220edee5ac936eee7a0ddsewardj                && isU32(st->Ist.WrTmp.data->Iex.Binop.arg2, (ARMCondAL << 4)))
804d266447c09a99122cbc220edee5ac936eee7a0ddsewardj               return mkU32(1);
805d266447c09a99122cbc220edee5ac936eee7a0ddsewardj         }
806d266447c09a99122cbc220edee5ac936eee7a0ddsewardj         /* Didn't find any useful binding to the first arg
807d266447c09a99122cbc220edee5ac936eee7a0ddsewardj            in the previous 16 stmts. */
808d266447c09a99122cbc220edee5ac936eee7a0ddsewardj      }
8096c299f3acab617581ea504e45fbb6cab24c2b29fsewardj   }
8106c299f3acab617581ea504e45fbb6cab24c2b29fsewardj
811bb8b394c97a23a17f60712afff6484ab340a93casewardj   /* --------- specialising "armg_calculate_flag_c" --------- */
812bb8b394c97a23a17f60712afff6484ab340a93casewardj
813bb8b394c97a23a17f60712afff6484ab340a93casewardj   else
814bb8b394c97a23a17f60712afff6484ab340a93casewardj   if (vex_streq(function_name, "armg_calculate_flag_c")) {
815bb8b394c97a23a17f60712afff6484ab340a93casewardj
816bb8b394c97a23a17f60712afff6484ab340a93casewardj      /* specialise calls to the "armg_calculate_flag_c" function.
817bb8b394c97a23a17f60712afff6484ab340a93casewardj         Note that the returned value must be either 0 or 1; nonzero
818bb8b394c97a23a17f60712afff6484ab340a93casewardj         bits 31:1 are not allowed.  In turn, incoming oldV and oldC
819bb8b394c97a23a17f60712afff6484ab340a93casewardj         values (from the thunk) are assumed to have bits 31:1
820bb8b394c97a23a17f60712afff6484ab340a93casewardj         clear. */
821bb8b394c97a23a17f60712afff6484ab340a93casewardj      IRExpr *cc_op, *cc_dep1, *cc_dep2, *cc_ndep;
822bb8b394c97a23a17f60712afff6484ab340a93casewardj      vassert(arity == 4);
823bb8b394c97a23a17f60712afff6484ab340a93casewardj      cc_op   = args[0]; /* ARMG_CC_OP_* */
824bb8b394c97a23a17f60712afff6484ab340a93casewardj      cc_dep1 = args[1];
825bb8b394c97a23a17f60712afff6484ab340a93casewardj      cc_dep2 = args[2];
826bb8b394c97a23a17f60712afff6484ab340a93casewardj      cc_ndep = args[3];
827bb8b394c97a23a17f60712afff6484ab340a93casewardj
828bb8b394c97a23a17f60712afff6484ab340a93casewardj      if (isU32(cc_op, ARMG_CC_OP_LOGIC)) {
829bb8b394c97a23a17f60712afff6484ab340a93casewardj         /* Thunk args are (result, shco, oldV) */
830bb8b394c97a23a17f60712afff6484ab340a93casewardj         /* C after LOGIC --> shco */
831bb8b394c97a23a17f60712afff6484ab340a93casewardj         return cc_dep2;
832bb8b394c97a23a17f60712afff6484ab340a93casewardj      }
833bb8b394c97a23a17f60712afff6484ab340a93casewardj
834bb8b394c97a23a17f60712afff6484ab340a93casewardj      if (isU32(cc_op, ARMG_CC_OP_SUB)) {
835bb8b394c97a23a17f60712afff6484ab340a93casewardj         /* Thunk args are (argL, argR, unused) */
836bb8b394c97a23a17f60712afff6484ab340a93casewardj         /* C after SUB --> argL >=u argR
837bb8b394c97a23a17f60712afff6484ab340a93casewardj                        --> argR <=u argL */
838bb8b394c97a23a17f60712afff6484ab340a93casewardj         return unop(Iop_1Uto32,
839bb8b394c97a23a17f60712afff6484ab340a93casewardj                     binop(Iop_CmpLE32U, cc_dep2, cc_dep1));
840bb8b394c97a23a17f60712afff6484ab340a93casewardj      }
841bb8b394c97a23a17f60712afff6484ab340a93casewardj
842bb8b394c97a23a17f60712afff6484ab340a93casewardj      if (isU32(cc_op, ARMG_CC_OP_SBB)) {
843bb8b394c97a23a17f60712afff6484ab340a93casewardj         /* This happens occasionally in softfloat code, eg __divdf3+140 */
844bb8b394c97a23a17f60712afff6484ab340a93casewardj         /* thunk is: (dep1=argL, dep2=argR, ndep=oldC) */
845bb8b394c97a23a17f60712afff6484ab340a93casewardj         /* C after SBB (same as HS after SBB above)
846bb8b394c97a23a17f60712afff6484ab340a93casewardj            --> oldC ? (argL >=u argR) : (argL >u argR)
847bb8b394c97a23a17f60712afff6484ab340a93casewardj            --> oldC ? (argR <=u argL) : (argR <u argL)
848bb8b394c97a23a17f60712afff6484ab340a93casewardj         */
849bb8b394c97a23a17f60712afff6484ab340a93casewardj         return
85099dd03e04a6914d90d5fee727d61d76905334becflorian            IRExpr_ITE(
851009230b9758291b594e60d7c0243a73d53e81854sewardj               binop(Iop_CmpNE32, cc_ndep, mkU32(0)),
852bb8b394c97a23a17f60712afff6484ab340a93casewardj               /* case oldC != 0 */
85399dd03e04a6914d90d5fee727d61d76905334becflorian               unop(Iop_1Uto32, binop(Iop_CmpLE32U, cc_dep2, cc_dep1)),
85499dd03e04a6914d90d5fee727d61d76905334becflorian               /* case oldC == 0 */
85599dd03e04a6914d90d5fee727d61d76905334becflorian               unop(Iop_1Uto32, binop(Iop_CmpLT32U, cc_dep2, cc_dep1))
856bb8b394c97a23a17f60712afff6484ab340a93casewardj            );
857bb8b394c97a23a17f60712afff6484ab340a93casewardj      }
858bb8b394c97a23a17f60712afff6484ab340a93casewardj
859bb8b394c97a23a17f60712afff6484ab340a93casewardj   }
860bb8b394c97a23a17f60712afff6484ab340a93casewardj
861bb8b394c97a23a17f60712afff6484ab340a93casewardj   /* --------- specialising "armg_calculate_flag_v" --------- */
862bb8b394c97a23a17f60712afff6484ab340a93casewardj
863bb8b394c97a23a17f60712afff6484ab340a93casewardj   else
864bb8b394c97a23a17f60712afff6484ab340a93casewardj   if (vex_streq(function_name, "armg_calculate_flag_v")) {
865bb8b394c97a23a17f60712afff6484ab340a93casewardj
866bb8b394c97a23a17f60712afff6484ab340a93casewardj      /* specialise calls to the "armg_calculate_flag_v" function.
867bb8b394c97a23a17f60712afff6484ab340a93casewardj         Note that the returned value must be either 0 or 1; nonzero
868bb8b394c97a23a17f60712afff6484ab340a93casewardj         bits 31:1 are not allowed.  In turn, incoming oldV and oldC
869bb8b394c97a23a17f60712afff6484ab340a93casewardj         values (from the thunk) are assumed to have bits 31:1
870bb8b394c97a23a17f60712afff6484ab340a93casewardj         clear. */
871bb8b394c97a23a17f60712afff6484ab340a93casewardj      IRExpr *cc_op, *cc_dep1, *cc_dep2, *cc_ndep;
872bb8b394c97a23a17f60712afff6484ab340a93casewardj      vassert(arity == 4);
873bb8b394c97a23a17f60712afff6484ab340a93casewardj      cc_op   = args[0]; /* ARMG_CC_OP_* */
874bb8b394c97a23a17f60712afff6484ab340a93casewardj      cc_dep1 = args[1];
875bb8b394c97a23a17f60712afff6484ab340a93casewardj      cc_dep2 = args[2];
876bb8b394c97a23a17f60712afff6484ab340a93casewardj      cc_ndep = args[3];
877bb8b394c97a23a17f60712afff6484ab340a93casewardj
878bb8b394c97a23a17f60712afff6484ab340a93casewardj      if (isU32(cc_op, ARMG_CC_OP_LOGIC)) {
879bb8b394c97a23a17f60712afff6484ab340a93casewardj         /* Thunk args are (result, shco, oldV) */
880bb8b394c97a23a17f60712afff6484ab340a93casewardj         /* V after LOGIC --> oldV */
881bb8b394c97a23a17f60712afff6484ab340a93casewardj         return cc_ndep;
882bb8b394c97a23a17f60712afff6484ab340a93casewardj      }
883bb8b394c97a23a17f60712afff6484ab340a93casewardj
88499ff62020fbc47e05cb7c041e655f9a75d173ad7sewardj      if (isU32(cc_op, ARMG_CC_OP_SUB)) {
88599ff62020fbc47e05cb7c041e655f9a75d173ad7sewardj         /* Thunk args are (argL, argR, unused) */
88699ff62020fbc47e05cb7c041e655f9a75d173ad7sewardj         /* V after SUB
88799ff62020fbc47e05cb7c041e655f9a75d173ad7sewardj            --> let res = argL - argR
88899ff62020fbc47e05cb7c041e655f9a75d173ad7sewardj                in ((argL ^ argR) & (argL ^ res)) >> 31
88999ff62020fbc47e05cb7c041e655f9a75d173ad7sewardj            --> ((argL ^ argR) & (argL ^ (argL - argR))) >> 31
89099ff62020fbc47e05cb7c041e655f9a75d173ad7sewardj         */
89199ff62020fbc47e05cb7c041e655f9a75d173ad7sewardj         IRExpr* argL = cc_dep1;
89299ff62020fbc47e05cb7c041e655f9a75d173ad7sewardj         IRExpr* argR = cc_dep2;
89399ff62020fbc47e05cb7c041e655f9a75d173ad7sewardj         return
89499ff62020fbc47e05cb7c041e655f9a75d173ad7sewardj            binop(Iop_Shr32,
89599ff62020fbc47e05cb7c041e655f9a75d173ad7sewardj                  binop(Iop_And32,
89699ff62020fbc47e05cb7c041e655f9a75d173ad7sewardj                        binop(Iop_Xor32, argL, argR),
89799ff62020fbc47e05cb7c041e655f9a75d173ad7sewardj                        binop(Iop_Xor32, argL, binop(Iop_Sub32, argL, argR))
89899ff62020fbc47e05cb7c041e655f9a75d173ad7sewardj                  ),
89999ff62020fbc47e05cb7c041e655f9a75d173ad7sewardj                  mkU8(31)
90099ff62020fbc47e05cb7c041e655f9a75d173ad7sewardj            );
90199ff62020fbc47e05cb7c041e655f9a75d173ad7sewardj      }
90299ff62020fbc47e05cb7c041e655f9a75d173ad7sewardj
903bb8b394c97a23a17f60712afff6484ab340a93casewardj      if (isU32(cc_op, ARMG_CC_OP_SBB)) {
904bb8b394c97a23a17f60712afff6484ab340a93casewardj         /* This happens occasionally in softfloat code, eg __divdf3+140 */
905bb8b394c97a23a17f60712afff6484ab340a93casewardj         /* thunk is: (dep1=argL, dep2=argR, ndep=oldC) */
906bb8b394c97a23a17f60712afff6484ab340a93casewardj         /* V after SBB
907bb8b394c97a23a17f60712afff6484ab340a93casewardj            --> let res = argL - argR - (oldC ^ 1)
908bb8b394c97a23a17f60712afff6484ab340a93casewardj                in  (argL ^ argR) & (argL ^ res) & 1
909bb8b394c97a23a17f60712afff6484ab340a93casewardj         */
910bb8b394c97a23a17f60712afff6484ab340a93casewardj         return
911bb8b394c97a23a17f60712afff6484ab340a93casewardj            binop(
912bb8b394c97a23a17f60712afff6484ab340a93casewardj               Iop_And32,
913bb8b394c97a23a17f60712afff6484ab340a93casewardj               binop(
914bb8b394c97a23a17f60712afff6484ab340a93casewardj                  Iop_And32,
915bb8b394c97a23a17f60712afff6484ab340a93casewardj                  // argL ^ argR
916bb8b394c97a23a17f60712afff6484ab340a93casewardj                  binop(Iop_Xor32, cc_dep1, cc_dep2),
917bb8b394c97a23a17f60712afff6484ab340a93casewardj                  // argL ^ (argL - argR - (oldC ^ 1))
918bb8b394c97a23a17f60712afff6484ab340a93casewardj                  binop(Iop_Xor32,
919bb8b394c97a23a17f60712afff6484ab340a93casewardj                        cc_dep1,
920bb8b394c97a23a17f60712afff6484ab340a93casewardj                        binop(Iop_Sub32,
921bb8b394c97a23a17f60712afff6484ab340a93casewardj                              binop(Iop_Sub32, cc_dep1, cc_dep2),
922bb8b394c97a23a17f60712afff6484ab340a93casewardj                              binop(Iop_Xor32, cc_ndep, mkU32(1)))
923bb8b394c97a23a17f60712afff6484ab340a93casewardj                  )
924bb8b394c97a23a17f60712afff6484ab340a93casewardj               ),
925bb8b394c97a23a17f60712afff6484ab340a93casewardj               mkU32(1)
926bb8b394c97a23a17f60712afff6484ab340a93casewardj            );
927bb8b394c97a23a17f60712afff6484ab340a93casewardj      }
928bb8b394c97a23a17f60712afff6484ab340a93casewardj
929bb8b394c97a23a17f60712afff6484ab340a93casewardj   }
930bb8b394c97a23a17f60712afff6484ab340a93casewardj
9316c299f3acab617581ea504e45fbb6cab24c2b29fsewardj#  undef unop
9326c299f3acab617581ea504e45fbb6cab24c2b29fsewardj#  undef binop
9336c299f3acab617581ea504e45fbb6cab24c2b29fsewardj#  undef mkU32
9346c299f3acab617581ea504e45fbb6cab24c2b29fsewardj#  undef mkU8
9356c299f3acab617581ea504e45fbb6cab24c2b29fsewardj
9362a9ad023890d3b34cf45e429df2a8ae88b419128sewardj   return NULL;
9372a9ad023890d3b34cf45e429df2a8ae88b419128sewardj}
9382a9ad023890d3b34cf45e429df2a8ae88b419128sewardj
9392a9ad023890d3b34cf45e429df2a8ae88b419128sewardj
9402a9ad023890d3b34cf45e429df2a8ae88b419128sewardj/*----------------------------------------------*/
9412a9ad023890d3b34cf45e429df2a8ae88b419128sewardj/*--- The exported fns ..                    ---*/
9422a9ad023890d3b34cf45e429df2a8ae88b419128sewardj/*----------------------------------------------*/
9432a9ad023890d3b34cf45e429df2a8ae88b419128sewardj
9442a9ad023890d3b34cf45e429df2a8ae88b419128sewardj/* VISIBLE TO LIBVEX CLIENT */
945c60c01ebe42c182f84fa6f5217db95f9a7ee0c36cerion#if 0
946f7da63d911934ee20d39e8c994edf7ca0bbc930fcerionvoid LibVEX_GuestARM_put_flags ( UInt flags_native,
9472a9ad023890d3b34cf45e429df2a8ae88b419128sewardj                                 /*OUT*/VexGuestARMState* vex_state )
9482a9ad023890d3b34cf45e429df2a8ae88b419128sewardj{
9492a9ad023890d3b34cf45e429df2a8ae88b419128sewardj   vassert(0); // FIXME
9502a9ad023890d3b34cf45e429df2a8ae88b419128sewardj
951c60c01ebe42c182f84fa6f5217db95f9a7ee0c36cerion   /* Mask out everything except N Z V C. */
952f7da63d911934ee20d39e8c994edf7ca0bbc930fcerion   flags_native
953c60c01ebe42c182f84fa6f5217db95f9a7ee0c36cerion      &= (ARMG_CC_MASK_N | ARMG_CC_MASK_Z | ARMG_CC_MASK_V | ARMG_CC_MASK_C);
954b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
955c60c01ebe42c182f84fa6f5217db95f9a7ee0c36cerion   vex_state->guest_CC_OP   = ARMG_CC_OP_COPY;
956f7da63d911934ee20d39e8c994edf7ca0bbc930fcerion   vex_state->guest_CC_DEP1 = flags_native;
9572a9ad023890d3b34cf45e429df2a8ae88b419128sewardj   vex_state->guest_CC_DEP2 = 0;
9586c299f3acab617581ea504e45fbb6cab24c2b29fsewardj   vex_state->guest_CC_NDEP = 0;
9592a9ad023890d3b34cf45e429df2a8ae88b419128sewardj}
960c60c01ebe42c182f84fa6f5217db95f9a7ee0c36cerion#endif
9612a9ad023890d3b34cf45e429df2a8ae88b419128sewardj
9622a9ad023890d3b34cf45e429df2a8ae88b419128sewardj/* VISIBLE TO LIBVEX CLIENT */
963efa834abaded25c8aff2f3923e476ef7cc1d0396florianUInt LibVEX_GuestARM_get_cpsr ( /*IN*/const VexGuestARMState* vex_state )
9642a9ad023890d3b34cf45e429df2a8ae88b419128sewardj{
965854cc2bb5228c1b0eba77fb896827203f0e338cdsewardj   UInt cpsr = 0;
966854cc2bb5228c1b0eba77fb896827203f0e338cdsewardj   // NZCV
967854cc2bb5228c1b0eba77fb896827203f0e338cdsewardj   cpsr |= armg_calculate_flags_nzcv(
968854cc2bb5228c1b0eba77fb896827203f0e338cdsewardj               vex_state->guest_CC_OP,
969854cc2bb5228c1b0eba77fb896827203f0e338cdsewardj               vex_state->guest_CC_DEP1,
970854cc2bb5228c1b0eba77fb896827203f0e338cdsewardj               vex_state->guest_CC_DEP2,
971854cc2bb5228c1b0eba77fb896827203f0e338cdsewardj               vex_state->guest_CC_NDEP
972854cc2bb5228c1b0eba77fb896827203f0e338cdsewardj            );
973854cc2bb5228c1b0eba77fb896827203f0e338cdsewardj   vassert(0 == (cpsr & 0x0FFFFFFF));
974854cc2bb5228c1b0eba77fb896827203f0e338cdsewardj   // Q
975854cc2bb5228c1b0eba77fb896827203f0e338cdsewardj   if (vex_state->guest_QFLAG32 > 0)
976854cc2bb5228c1b0eba77fb896827203f0e338cdsewardj      cpsr |= (1 << 27);
977854cc2bb5228c1b0eba77fb896827203f0e338cdsewardj   // GE
978854cc2bb5228c1b0eba77fb896827203f0e338cdsewardj   if (vex_state->guest_GEFLAG0 > 0)
979854cc2bb5228c1b0eba77fb896827203f0e338cdsewardj      cpsr |= (1 << 16);
980854cc2bb5228c1b0eba77fb896827203f0e338cdsewardj   if (vex_state->guest_GEFLAG1 > 0)
981854cc2bb5228c1b0eba77fb896827203f0e338cdsewardj      cpsr |= (1 << 17);
982854cc2bb5228c1b0eba77fb896827203f0e338cdsewardj   if (vex_state->guest_GEFLAG2 > 0)
983854cc2bb5228c1b0eba77fb896827203f0e338cdsewardj      cpsr |= (1 << 18);
984854cc2bb5228c1b0eba77fb896827203f0e338cdsewardj   if (vex_state->guest_GEFLAG3 > 0)
985854cc2bb5228c1b0eba77fb896827203f0e338cdsewardj      cpsr |= (1 << 19);
986854cc2bb5228c1b0eba77fb896827203f0e338cdsewardj   // M
987854cc2bb5228c1b0eba77fb896827203f0e338cdsewardj   cpsr |= (1 << 4); // 0b10000 means user-mode
988854cc2bb5228c1b0eba77fb896827203f0e338cdsewardj   // J,T   J (bit 24) is zero by initialisation above
989854cc2bb5228c1b0eba77fb896827203f0e338cdsewardj   // T  we copy from R15T[0]
990854cc2bb5228c1b0eba77fb896827203f0e338cdsewardj   if (vex_state->guest_R15T & 1)
991854cc2bb5228c1b0eba77fb896827203f0e338cdsewardj      cpsr |= (1 << 5);
992854cc2bb5228c1b0eba77fb896827203f0e338cdsewardj   // ITSTATE we punt on for the time being.  Could compute it
993854cc2bb5228c1b0eba77fb896827203f0e338cdsewardj   // if needed though.
994854cc2bb5228c1b0eba77fb896827203f0e338cdsewardj   // E, endianness, 0 (littleendian) from initialisation above
995854cc2bb5228c1b0eba77fb896827203f0e338cdsewardj   // A,I,F disable some async exceptions.  Not sure about these.
996854cc2bb5228c1b0eba77fb896827203f0e338cdsewardj   // Leave as zero for the time being.
997854cc2bb5228c1b0eba77fb896827203f0e338cdsewardj   return cpsr;
9982a9ad023890d3b34cf45e429df2a8ae88b419128sewardj}
9992a9ad023890d3b34cf45e429df2a8ae88b419128sewardj
10002a9ad023890d3b34cf45e429df2a8ae88b419128sewardj/* VISIBLE TO LIBVEX CLIENT */
10012a9ad023890d3b34cf45e429df2a8ae88b419128sewardjvoid LibVEX_GuestARM_initialise ( /*OUT*/VexGuestARMState* vex_state )
10022a9ad023890d3b34cf45e429df2a8ae88b419128sewardj{
1003c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   vex_state->host_EvC_FAILADDR = 0;
1004c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj   vex_state->host_EvC_COUNTER = 0;
1005c6f970f1fadb640d69c78ac2669efab5c08f1e8dsewardj
10062a9ad023890d3b34cf45e429df2a8ae88b419128sewardj   vex_state->guest_R0  = 0;
10072a9ad023890d3b34cf45e429df2a8ae88b419128sewardj   vex_state->guest_R1  = 0;
10082a9ad023890d3b34cf45e429df2a8ae88b419128sewardj   vex_state->guest_R2  = 0;
10092a9ad023890d3b34cf45e429df2a8ae88b419128sewardj   vex_state->guest_R3  = 0;
10102a9ad023890d3b34cf45e429df2a8ae88b419128sewardj   vex_state->guest_R4  = 0;
10112a9ad023890d3b34cf45e429df2a8ae88b419128sewardj   vex_state->guest_R5  = 0;
10122a9ad023890d3b34cf45e429df2a8ae88b419128sewardj   vex_state->guest_R6  = 0;
10132a9ad023890d3b34cf45e429df2a8ae88b419128sewardj   vex_state->guest_R7  = 0;
10142a9ad023890d3b34cf45e429df2a8ae88b419128sewardj   vex_state->guest_R8  = 0;
10152a9ad023890d3b34cf45e429df2a8ae88b419128sewardj   vex_state->guest_R9  = 0;
10162a9ad023890d3b34cf45e429df2a8ae88b419128sewardj   vex_state->guest_R10 = 0;
10172a9ad023890d3b34cf45e429df2a8ae88b419128sewardj   vex_state->guest_R11 = 0;
10182a9ad023890d3b34cf45e429df2a8ae88b419128sewardj   vex_state->guest_R12 = 0;
10192a9ad023890d3b34cf45e429df2a8ae88b419128sewardj   vex_state->guest_R13 = 0;
10202a9ad023890d3b34cf45e429df2a8ae88b419128sewardj   vex_state->guest_R14 = 0;
1021d266447c09a99122cbc220edee5ac936eee7a0ddsewardj   vex_state->guest_R15T = 0;  /* NB: implies ARM mode */
10222a9ad023890d3b34cf45e429df2a8ae88b419128sewardj
10236c299f3acab617581ea504e45fbb6cab24c2b29fsewardj   vex_state->guest_CC_OP   = ARMG_CC_OP_COPY;
10242a9ad023890d3b34cf45e429df2a8ae88b419128sewardj   vex_state->guest_CC_DEP1 = 0;
10252a9ad023890d3b34cf45e429df2a8ae88b419128sewardj   vex_state->guest_CC_DEP2 = 0;
10266c299f3acab617581ea504e45fbb6cab24c2b29fsewardj   vex_state->guest_CC_NDEP = 0;
1027d266447c09a99122cbc220edee5ac936eee7a0ddsewardj   vex_state->guest_QFLAG32 = 0;
10281f139f58d905803d87fda1229e475c715df603easewardj   vex_state->guest_GEFLAG0 = 0;
10291f139f58d905803d87fda1229e475c715df603easewardj   vex_state->guest_GEFLAG1 = 0;
10301f139f58d905803d87fda1229e475c715df603easewardj   vex_state->guest_GEFLAG2 = 0;
10311f139f58d905803d87fda1229e475c715df603easewardj   vex_state->guest_GEFLAG3 = 0;
10326c299f3acab617581ea504e45fbb6cab24c2b29fsewardj
10336ef84bed9bb3af22060eb1759788034602bbcc88florian   vex_state->guest_EMNOTE  = EmNote_NONE;
103405f5e0172384dd2983fb16fbb7deebd74d71cd35sewardj   vex_state->guest_CMSTART = 0;
103505f5e0172384dd2983fb16fbb7deebd74d71cd35sewardj   vex_state->guest_CMLEN   = 0;
10366c299f3acab617581ea504e45fbb6cab24c2b29fsewardj   vex_state->guest_NRADDR  = 0;
10376c299f3acab617581ea504e45fbb6cab24c2b29fsewardj   vex_state->guest_IP_AT_SYSCALL = 0;
10386c299f3acab617581ea504e45fbb6cab24c2b29fsewardj
10396c299f3acab617581ea504e45fbb6cab24c2b29fsewardj   vex_state->guest_D0  = 0;
10406c299f3acab617581ea504e45fbb6cab24c2b29fsewardj   vex_state->guest_D1  = 0;
10416c299f3acab617581ea504e45fbb6cab24c2b29fsewardj   vex_state->guest_D2  = 0;
10426c299f3acab617581ea504e45fbb6cab24c2b29fsewardj   vex_state->guest_D3  = 0;
10436c299f3acab617581ea504e45fbb6cab24c2b29fsewardj   vex_state->guest_D4  = 0;
10446c299f3acab617581ea504e45fbb6cab24c2b29fsewardj   vex_state->guest_D5  = 0;
10456c299f3acab617581ea504e45fbb6cab24c2b29fsewardj   vex_state->guest_D6  = 0;
10466c299f3acab617581ea504e45fbb6cab24c2b29fsewardj   vex_state->guest_D7  = 0;
10476c299f3acab617581ea504e45fbb6cab24c2b29fsewardj   vex_state->guest_D8  = 0;
10486c299f3acab617581ea504e45fbb6cab24c2b29fsewardj   vex_state->guest_D9  = 0;
10496c299f3acab617581ea504e45fbb6cab24c2b29fsewardj   vex_state->guest_D10 = 0;
10506c299f3acab617581ea504e45fbb6cab24c2b29fsewardj   vex_state->guest_D11 = 0;
10516c299f3acab617581ea504e45fbb6cab24c2b29fsewardj   vex_state->guest_D12 = 0;
10526c299f3acab617581ea504e45fbb6cab24c2b29fsewardj   vex_state->guest_D13 = 0;
10536c299f3acab617581ea504e45fbb6cab24c2b29fsewardj   vex_state->guest_D14 = 0;
10546c299f3acab617581ea504e45fbb6cab24c2b29fsewardj   vex_state->guest_D15 = 0;
1055d266447c09a99122cbc220edee5ac936eee7a0ddsewardj   vex_state->guest_D16 = 0;
1056d266447c09a99122cbc220edee5ac936eee7a0ddsewardj   vex_state->guest_D17 = 0;
1057d266447c09a99122cbc220edee5ac936eee7a0ddsewardj   vex_state->guest_D18 = 0;
1058d266447c09a99122cbc220edee5ac936eee7a0ddsewardj   vex_state->guest_D19 = 0;
1059d266447c09a99122cbc220edee5ac936eee7a0ddsewardj   vex_state->guest_D20 = 0;
1060d266447c09a99122cbc220edee5ac936eee7a0ddsewardj   vex_state->guest_D21 = 0;
1061d266447c09a99122cbc220edee5ac936eee7a0ddsewardj   vex_state->guest_D22 = 0;
1062d266447c09a99122cbc220edee5ac936eee7a0ddsewardj   vex_state->guest_D23 = 0;
1063d266447c09a99122cbc220edee5ac936eee7a0ddsewardj   vex_state->guest_D24 = 0;
1064d266447c09a99122cbc220edee5ac936eee7a0ddsewardj   vex_state->guest_D25 = 0;
1065d266447c09a99122cbc220edee5ac936eee7a0ddsewardj   vex_state->guest_D26 = 0;
1066d266447c09a99122cbc220edee5ac936eee7a0ddsewardj   vex_state->guest_D27 = 0;
1067d266447c09a99122cbc220edee5ac936eee7a0ddsewardj   vex_state->guest_D28 = 0;
1068d266447c09a99122cbc220edee5ac936eee7a0ddsewardj   vex_state->guest_D29 = 0;
1069d266447c09a99122cbc220edee5ac936eee7a0ddsewardj   vex_state->guest_D30 = 0;
1070d266447c09a99122cbc220edee5ac936eee7a0ddsewardj   vex_state->guest_D31 = 0;
10716c299f3acab617581ea504e45fbb6cab24c2b29fsewardj
10726c299f3acab617581ea504e45fbb6cab24c2b29fsewardj   /* ARM encoded; zero is the default as it happens (result flags
10736c299f3acab617581ea504e45fbb6cab24c2b29fsewardj      (NZCV) cleared, FZ disabled, round to nearest, non-vector mode,
10746c299f3acab617581ea504e45fbb6cab24c2b29fsewardj      all exns masked, all exn sticky bits cleared). */
10756c299f3acab617581ea504e45fbb6cab24c2b29fsewardj   vex_state->guest_FPSCR = 0;
10766c299f3acab617581ea504e45fbb6cab24c2b29fsewardj
10776c299f3acab617581ea504e45fbb6cab24c2b29fsewardj   vex_state->guest_TPIDRURO = 0;
10786c299f3acab617581ea504e45fbb6cab24c2b29fsewardj
1079d266447c09a99122cbc220edee5ac936eee7a0ddsewardj   /* Not in a Thumb IT block. */
1080d266447c09a99122cbc220edee5ac936eee7a0ddsewardj   vex_state->guest_ITSTATE = 0;
1081d266447c09a99122cbc220edee5ac936eee7a0ddsewardj
1082d266447c09a99122cbc220edee5ac936eee7a0ddsewardj   vex_state->padding1 = 0;
10832a9ad023890d3b34cf45e429df2a8ae88b419128sewardj}
10842a9ad023890d3b34cf45e429df2a8ae88b419128sewardj
10852a9ad023890d3b34cf45e429df2a8ae88b419128sewardj
10862a9ad023890d3b34cf45e429df2a8ae88b419128sewardj/*-----------------------------------------------------------*/
10872a9ad023890d3b34cf45e429df2a8ae88b419128sewardj/*--- Describing the arm guest state, for the benefit     ---*/
10882a9ad023890d3b34cf45e429df2a8ae88b419128sewardj/*--- of iropt and instrumenters.                         ---*/
10892a9ad023890d3b34cf45e429df2a8ae88b419128sewardj/*-----------------------------------------------------------*/
10902a9ad023890d3b34cf45e429df2a8ae88b419128sewardj
10912a9ad023890d3b34cf45e429df2a8ae88b419128sewardj/* Figure out if any part of the guest state contained in minoff
10922a9ad023890d3b34cf45e429df2a8ae88b419128sewardj   .. maxoff requires precise memory exceptions.  If in doubt return
10936c46befd9eb90c1b6e739926c1fa335cba75bf46philippe   True (but this generates significantly slower code).
10942a9ad023890d3b34cf45e429df2a8ae88b419128sewardj
10956c46befd9eb90c1b6e739926c1fa335cba75bf46philippe   We enforce precise exns for guest R13(sp), R15T(pc), R7, R11.
10966c46befd9eb90c1b6e739926c1fa335cba75bf46philippe
10976c46befd9eb90c1b6e739926c1fa335cba75bf46philippe
10986c46befd9eb90c1b6e739926c1fa335cba75bf46philippe   Only R13(sp) is needed in mode VexRegUpdSpAtMemAccess.
10992a9ad023890d3b34cf45e429df2a8ae88b419128sewardj*/
1100ca2c3c75784d35d136fc7c952717cdee5063c193sewardjBool guest_arm_state_requires_precise_mem_exns (
1101ca2c3c75784d35d136fc7c952717cdee5063c193sewardj        Int minoff, Int maxoff, VexRegisterUpdates pxControl
1102ca2c3c75784d35d136fc7c952717cdee5063c193sewardj     )
11032a9ad023890d3b34cf45e429df2a8ae88b419128sewardj{
11046c299f3acab617581ea504e45fbb6cab24c2b29fsewardj   Int sp_min = offsetof(VexGuestARMState, guest_R13);
11056c299f3acab617581ea504e45fbb6cab24c2b29fsewardj   Int sp_max = sp_min + 4 - 1;
1106d266447c09a99122cbc220edee5ac936eee7a0ddsewardj   Int pc_min = offsetof(VexGuestARMState, guest_R15T);
11076c299f3acab617581ea504e45fbb6cab24c2b29fsewardj   Int pc_max = pc_min + 4 - 1;
11082a9ad023890d3b34cf45e429df2a8ae88b419128sewardj
11096c299f3acab617581ea504e45fbb6cab24c2b29fsewardj   if (maxoff < sp_min || minoff > sp_max) {
11106c299f3acab617581ea504e45fbb6cab24c2b29fsewardj      /* no overlap with sp */
1111ca2c3c75784d35d136fc7c952717cdee5063c193sewardj      if (pxControl == VexRegUpdSpAtMemAccess)
11126c46befd9eb90c1b6e739926c1fa335cba75bf46philippe         return False; // We only need to check stack pointer.
11132a9ad023890d3b34cf45e429df2a8ae88b419128sewardj   } else {
11142a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      return True;
11152a9ad023890d3b34cf45e429df2a8ae88b419128sewardj   }
11162a9ad023890d3b34cf45e429df2a8ae88b419128sewardj
11176c299f3acab617581ea504e45fbb6cab24c2b29fsewardj   if (maxoff < pc_min || minoff > pc_max) {
11186c299f3acab617581ea504e45fbb6cab24c2b29fsewardj      /* no overlap with pc */
11196c299f3acab617581ea504e45fbb6cab24c2b29fsewardj   } else {
11206c299f3acab617581ea504e45fbb6cab24c2b29fsewardj      return True;
11216c299f3acab617581ea504e45fbb6cab24c2b29fsewardj   }
11226c299f3acab617581ea504e45fbb6cab24c2b29fsewardj
11236c299f3acab617581ea504e45fbb6cab24c2b29fsewardj   /* We appear to need precise updates of R11 in order to get proper
11246c299f3acab617581ea504e45fbb6cab24c2b29fsewardj      stacktraces from non-optimised code. */
11256c299f3acab617581ea504e45fbb6cab24c2b29fsewardj   Int r11_min = offsetof(VexGuestARMState, guest_R11);
11266c299f3acab617581ea504e45fbb6cab24c2b29fsewardj   Int r11_max = r11_min + 4 - 1;
11276c299f3acab617581ea504e45fbb6cab24c2b29fsewardj
11286c299f3acab617581ea504e45fbb6cab24c2b29fsewardj   if (maxoff < r11_min || minoff > r11_max) {
11295de202d057461245b2457f6773511989272a69c9sewardj      /* no overlap with r11 */
11305de202d057461245b2457f6773511989272a69c9sewardj   } else {
11315de202d057461245b2457f6773511989272a69c9sewardj      return True;
11325de202d057461245b2457f6773511989272a69c9sewardj   }
11335de202d057461245b2457f6773511989272a69c9sewardj
11345de202d057461245b2457f6773511989272a69c9sewardj   /* Ditto R7, particularly needed for proper stacktraces in Thumb
11355de202d057461245b2457f6773511989272a69c9sewardj      code. */
11365de202d057461245b2457f6773511989272a69c9sewardj   Int r7_min = offsetof(VexGuestARMState, guest_R7);
11375de202d057461245b2457f6773511989272a69c9sewardj   Int r7_max = r7_min + 4 - 1;
11385de202d057461245b2457f6773511989272a69c9sewardj
11395de202d057461245b2457f6773511989272a69c9sewardj   if (maxoff < r7_min || minoff > r7_max) {
11405de202d057461245b2457f6773511989272a69c9sewardj      /* no overlap with r7 */
11412a9ad023890d3b34cf45e429df2a8ae88b419128sewardj   } else {
11422a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      return True;
11432a9ad023890d3b34cf45e429df2a8ae88b419128sewardj   }
11442a9ad023890d3b34cf45e429df2a8ae88b419128sewardj
11452a9ad023890d3b34cf45e429df2a8ae88b419128sewardj   return False;
11462a9ad023890d3b34cf45e429df2a8ae88b419128sewardj}
11472a9ad023890d3b34cf45e429df2a8ae88b419128sewardj
11482a9ad023890d3b34cf45e429df2a8ae88b419128sewardj
11492a9ad023890d3b34cf45e429df2a8ae88b419128sewardj
11502a9ad023890d3b34cf45e429df2a8ae88b419128sewardj#define ALWAYSDEFD(field)                           \
11512a9ad023890d3b34cf45e429df2a8ae88b419128sewardj    { offsetof(VexGuestARMState, field),            \
11522a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      (sizeof ((VexGuestARMState*)0)->field) }
11532a9ad023890d3b34cf45e429df2a8ae88b419128sewardj
11542a9ad023890d3b34cf45e429df2a8ae88b419128sewardjVexGuestLayout
11552a9ad023890d3b34cf45e429df2a8ae88b419128sewardj   armGuest_layout
11562a9ad023890d3b34cf45e429df2a8ae88b419128sewardj      = {
11572a9ad023890d3b34cf45e429df2a8ae88b419128sewardj          /* Total size of the guest state, in bytes. */
11582a9ad023890d3b34cf45e429df2a8ae88b419128sewardj          .total_sizeB = sizeof(VexGuestARMState),
11592a9ad023890d3b34cf45e429df2a8ae88b419128sewardj
11602a9ad023890d3b34cf45e429df2a8ae88b419128sewardj          /* Describe the stack pointer. */
11612a9ad023890d3b34cf45e429df2a8ae88b419128sewardj          .offset_SP = offsetof(VexGuestARMState,guest_R13),
11622a9ad023890d3b34cf45e429df2a8ae88b419128sewardj          .sizeof_SP = 4,
11632a9ad023890d3b34cf45e429df2a8ae88b419128sewardj
11642a9ad023890d3b34cf45e429df2a8ae88b419128sewardj          /* Describe the instruction pointer. */
1165d266447c09a99122cbc220edee5ac936eee7a0ddsewardj          .offset_IP = offsetof(VexGuestARMState,guest_R15T),
11662a9ad023890d3b34cf45e429df2a8ae88b419128sewardj          .sizeof_IP = 4,
11672a9ad023890d3b34cf45e429df2a8ae88b419128sewardj
11682a9ad023890d3b34cf45e429df2a8ae88b419128sewardj          /* Describe any sections to be regarded by Memcheck as
11692a9ad023890d3b34cf45e429df2a8ae88b419128sewardj             'always-defined'. */
1170d266447c09a99122cbc220edee5ac936eee7a0ddsewardj          .n_alwaysDefd = 10,
11716c299f3acab617581ea504e45fbb6cab24c2b29fsewardj
11722a9ad023890d3b34cf45e429df2a8ae88b419128sewardj          /* flags thunk: OP is always defd, whereas DEP1 and DEP2
11732a9ad023890d3b34cf45e429df2a8ae88b419128sewardj             have to be tracked.  See detailed comment in gdefs.h on
11742a9ad023890d3b34cf45e429df2a8ae88b419128sewardj             meaning of thunk fields. */
11756c299f3acab617581ea504e45fbb6cab24c2b29fsewardj          .alwaysDefd
1176d266447c09a99122cbc220edee5ac936eee7a0ddsewardj             = { /* 0 */ ALWAYSDEFD(guest_R15T),
11776c299f3acab617581ea504e45fbb6cab24c2b29fsewardj                 /* 1 */ ALWAYSDEFD(guest_CC_OP),
11786c299f3acab617581ea504e45fbb6cab24c2b29fsewardj                 /* 2 */ ALWAYSDEFD(guest_CC_NDEP),
11796ef84bed9bb3af22060eb1759788034602bbcc88florian                 /* 3 */ ALWAYSDEFD(guest_EMNOTE),
118005f5e0172384dd2983fb16fbb7deebd74d71cd35sewardj                 /* 4 */ ALWAYSDEFD(guest_CMSTART),
118105f5e0172384dd2983fb16fbb7deebd74d71cd35sewardj                 /* 5 */ ALWAYSDEFD(guest_CMLEN),
11826c299f3acab617581ea504e45fbb6cab24c2b29fsewardj                 /* 6 */ ALWAYSDEFD(guest_NRADDR),
11836c299f3acab617581ea504e45fbb6cab24c2b29fsewardj                 /* 7 */ ALWAYSDEFD(guest_IP_AT_SYSCALL),
1184d266447c09a99122cbc220edee5ac936eee7a0ddsewardj                 /* 8 */ ALWAYSDEFD(guest_TPIDRURO),
1185d266447c09a99122cbc220edee5ac936eee7a0ddsewardj                 /* 9 */ ALWAYSDEFD(guest_ITSTATE)
11862a9ad023890d3b34cf45e429df2a8ae88b419128sewardj               }
11872a9ad023890d3b34cf45e429df2a8ae88b419128sewardj        };
11882a9ad023890d3b34cf45e429df2a8ae88b419128sewardj
11892a9ad023890d3b34cf45e429df2a8ae88b419128sewardj
11902a9ad023890d3b34cf45e429df2a8ae88b419128sewardj/*---------------------------------------------------------------*/
1191cef7d3e3df4796e35b4521158d9dc058f034aa87sewardj/*--- end                                 guest_arm_helpers.c ---*/
11922a9ad023890d3b34cf45e429df2a8ae88b419128sewardj/*---------------------------------------------------------------*/
1193