Home | History | Annotate | Download | only in priv
      1 
      2 /*---------------------------------------------------------------*/
      3 /*--- begin                             guest_arm64_helpers.c ---*/
      4 /*---------------------------------------------------------------*/
      5 
      6 /*
      7    This file is part of Valgrind, a dynamic binary instrumentation
      8    framework.
      9 
     10    Copyright (C) 2013-2015 OpenWorks
     11       info (at) open-works.net
     12 
     13    This program is free software; you can redistribute it and/or
     14    modify it under the terms of the GNU General Public License as
     15    published by the Free Software Foundation; either version 2 of the
     16    License, or (at your option) any later version.
     17 
     18    This program is distributed in the hope that it will be useful, but
     19    WITHOUT ANY WARRANTY; without even the implied warranty of
     20    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     21    General Public License for more details.
     22 
     23    You should have received a copy of the GNU General Public License
     24    along with this program; if not, write to the Free Software
     25    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
     26    02110-1301, USA.
     27 
     28    The GNU General Public License is contained in the file COPYING.
     29 */
     30 
     31 #include "libvex_basictypes.h"
     32 #include "libvex_emnote.h"
     33 #include "libvex_guest_arm64.h"
     34 #include "libvex_ir.h"
     35 #include "libvex.h"
     36 
     37 #include "main_util.h"
     38 #include "main_globals.h"
     39 #include "guest_generic_bb_to_IR.h"
     40 #include "guest_arm64_defs.h"
     41 
     42 
     43 /* This file contains helper functions for arm guest code.  Calls to
     44    these functions are generated by the back end.  These calls are of
     45    course in the host machine code and this file will be compiled to
     46    host machine code, so that all makes sense.
     47 
     48    Only change the signatures of these helper functions very
     49    carefully.  If you change the signature here, you'll have to change
     50    the parameters passed to it in the IR calls constructed by
     51    guest_arm64_toIR.c.
     52 */
     53 
     54 
     55 /* Set to 1 to get detailed profiling info about individual N, Z, C
     56    and V flag evaluation. */
     57 #define PROFILE_NZCV_FLAGS 0
     58 
     59 #if PROFILE_NZCV_FLAGS
     60 
     61 static UInt tab_eval[ARM64G_CC_OP_NUMBER][16];
     62 static UInt initted = 0;
     63 static UInt tot_evals = 0;
     64 
     65 static void initCounts ( void )
     66 {
     67    UInt i, j;
     68    for (i = 0; i < ARM64G_CC_OP_NUMBER; i++) {
     69       for (j = 0; j < 16; j++) {
     70          tab_eval[i][j] = 0;
     71       }
     72    }
     73    initted = 1;
     74 }
     75 
     76 static void showCounts ( void )
     77 {
     78    const HChar* nameCC[16]
     79       = { "EQ", "NE", "CS", "CC", "MI", "PL", "VS", "VC",
     80           "HI", "LS", "GE", "LT", "GT", "LE", "AL", "NV" };
     81    UInt i, j;
     82    ULong sum = 0;
     83    vex_printf("\nCC_OP          0         1         2         3    "
     84               "     4         5         6\n");
     85    vex_printf(  "--------------------------------------------------"
     86               "--------------------------\n");
     87    for (j = 0; j < 16; j++) {
     88       vex_printf("%2d %s  ", j, nameCC[j]);
     89       for (i = 0; i < ARM64G_CC_OP_NUMBER; i++) {
     90          vex_printf("%9d ", tab_eval[i][j]);
     91          sum += tab_eval[i][j];
     92       }
     93       vex_printf("\n");
     94    }
     95    vex_printf("(In total %llu calls)\n", sum);
     96 }
     97 
     98 #define NOTE_EVAL(_cc_op, _cond) \
     99    do { \
    100       if (!initted) initCounts(); \
    101       vassert( ((UInt)(_cc_op)) < ARM64G_CC_OP_NUMBER); \
    102       vassert( ((UInt)(_cond)) < 16); \
    103       tab_eval[(UInt)(_cc_op)][(UInt)(cond)]++;  \
    104       tot_evals++; \
    105       if (0 == (tot_evals & 0x7FFF)) \
    106         showCounts(); \
    107    } while (0)
    108 
    109 #endif /* PROFILE_NZCV_FLAGS */
    110 
    111 
    112 /* Calculate the N flag from the supplied thunk components, in the
    113    least significant bit of the word.  Returned bits 63:1 are zero. */
    114 static
    115 ULong arm64g_calculate_flag_n ( ULong cc_op, ULong cc_dep1,
    116                                 ULong cc_dep2, ULong cc_dep3 )
    117 {
    118    switch (cc_op) {
    119       case ARM64G_CC_OP_COPY: {
    120          /* (nzcv:28x0, unused, unused) */
    121          ULong nf   = (cc_dep1 >> ARM64G_CC_SHIFT_N) & 1;
    122          return nf;
    123       }
    124       case ARM64G_CC_OP_ADD32: {
    125          /* (argL, argR, unused) */
    126          UInt  argL = (UInt)cc_dep1;
    127          UInt  argR = (UInt)cc_dep2;
    128          UInt  res  = argL + argR;
    129          ULong nf   = (ULong)(res >> 31);
    130          return nf;
    131       }
    132       case ARM64G_CC_OP_ADD64: {
    133          /* (argL, argR, unused) */
    134          ULong argL = cc_dep1;
    135          ULong argR = cc_dep2;
    136          ULong res  = argL + argR;
    137          ULong nf   = (ULong)(res >> 63);
    138          return nf;
    139       }
    140       case ARM64G_CC_OP_SUB32: {
    141          /* (argL, argR, unused) */
    142          UInt  argL = (UInt)cc_dep1;
    143          UInt  argR = (UInt)cc_dep2;
    144          UInt  res  = argL - argR;
    145          ULong nf   = (ULong)(res >> 31);
    146          return nf;
    147       }
    148       case ARM64G_CC_OP_SUB64: {
    149          /* (argL, argR, unused) */
    150          ULong argL = cc_dep1;
    151          ULong argR = cc_dep2;
    152          ULong res  = argL - argR;
    153          ULong nf   = res >> 63;
    154          return nf;
    155       }
    156       case ARM64G_CC_OP_ADC32: {
    157          /* (argL, argR, oldC) */
    158          UInt  argL = cc_dep1;
    159          UInt  argR = cc_dep2;
    160          UInt  oldC = cc_dep3;
    161          vassert((oldC & ~1) == 0);
    162          UInt  res  = argL + argR + oldC;
    163          ULong nf   = (ULong)(res >> 31);
    164          return nf;
    165       }
    166       case ARM64G_CC_OP_ADC64: {
    167          /* (argL, argR, oldC) */
    168          ULong argL = cc_dep1;
    169          ULong argR = cc_dep2;
    170          ULong oldC = cc_dep3;
    171          vassert((oldC & ~1) == 0);
    172          ULong res  = argL + argR + oldC;
    173          ULong nf   = res >> 63;
    174          return nf;
    175       }
    176       case ARM64G_CC_OP_SBC32: {
    177          /* (argL, argR, oldC) */
    178          UInt  argL = cc_dep1;
    179          UInt  argR = cc_dep2;
    180          UInt  oldC = cc_dep3;
    181          vassert((oldC & ~1) == 0);
    182          UInt  res  = argL - argR - (oldC ^ 1);
    183          ULong nf   = (ULong)(res >> 31);
    184          return nf;
    185       }
    186       case ARM64G_CC_OP_SBC64: {
    187          /* (argL, argR, oldC) */
    188          ULong argL = cc_dep1;
    189          ULong argR = cc_dep2;
    190          ULong oldC = cc_dep3;
    191          vassert((oldC & ~1) == 0);
    192          ULong res  = argL - argR - (oldC ^ 1);
    193          ULong nf   = res >> 63;
    194          return nf;
    195       }
    196       case ARM64G_CC_OP_LOGIC32: {
    197          /* (res, unused, unused) */
    198          UInt  res = (UInt)cc_dep1;
    199          ULong nf  = res >> 31;
    200          return nf;
    201       }
    202       case ARM64G_CC_OP_LOGIC64: {
    203          /* (res, unused, unused) */
    204          ULong res = cc_dep1;
    205          ULong nf  = res >> 63;
    206          return nf;
    207       }
    208 //ZZ       case ARMG_CC_OP_MUL: {
    209 //ZZ          /* (res, unused, oldC:oldV) */
    210 //ZZ          UInt res  = cc_dep1;
    211 //ZZ          UInt nf   = res >> 31;
    212 //ZZ          return nf;
    213 //ZZ       }
    214 //ZZ       case ARMG_CC_OP_MULL: {
    215 //ZZ          /* (resLo32, resHi32, oldC:oldV) */
    216 //ZZ          UInt resHi32 = cc_dep2;
    217 //ZZ          UInt nf      = resHi32 >> 31;
    218 //ZZ          return nf;
    219 //ZZ       }
    220       default:
    221          /* shouldn't really make these calls from generated code */
    222          vex_printf("arm64g_calculate_flag_n"
    223                     "( op=%llu, dep1=0x%llx, dep2=0x%llx, dep3=0x%llx )\n",
    224                     cc_op, cc_dep1, cc_dep2, cc_dep3 );
    225          vpanic("arm64g_calculate_flag_n");
    226    }
    227 }
    228 
    229 
    230 /* Calculate the Z flag from the supplied thunk components, in the
    231    least significant bit of the word.  Returned bits 63:1 are zero. */
    232 static
    233 ULong arm64g_calculate_flag_z ( ULong cc_op, ULong cc_dep1,
    234                                 ULong cc_dep2, ULong cc_dep3 )
    235 {
    236    switch (cc_op) {
    237       case ARM64G_CC_OP_COPY: {
    238          /* (nzcv:28x0, unused, unused) */
    239          ULong zf   = (cc_dep1 >> ARM64G_CC_SHIFT_Z) & 1;
    240          return zf;
    241       }
    242       case ARM64G_CC_OP_ADD32: {
    243          /* (argL, argR, unused) */
    244          UInt  argL = (UInt)cc_dep1;
    245          UInt  argR = (UInt)cc_dep2;
    246          UInt  res  = argL + argR;
    247          ULong zf   = res == 0;
    248          return zf;
    249       }
    250       case ARM64G_CC_OP_ADD64: {
    251          /* (argL, argR, unused) */
    252          ULong argL = cc_dep1;
    253          ULong argR = cc_dep2;
    254          ULong res  = argL + argR;
    255          ULong zf   = res == 0;
    256          return zf;
    257       }
    258       case ARM64G_CC_OP_SUB32: {
    259          /* (argL, argR, unused) */
    260          UInt  argL = (UInt)cc_dep1;
    261          UInt  argR = (UInt)cc_dep2;
    262          UInt  res  = argL - argR;
    263          ULong zf   = res == 0;
    264          return zf;
    265       }
    266       case ARM64G_CC_OP_SUB64: {
    267          /* (argL, argR, unused) */
    268          ULong argL = cc_dep1;
    269          ULong argR = cc_dep2;
    270          ULong res  = argL - argR;
    271          ULong zf   = res == 0;
    272          return zf;
    273       }
    274       case ARM64G_CC_OP_ADC32: {
    275          /* (argL, argR, oldC) */
    276          UInt  argL = cc_dep1;
    277          UInt  argR = cc_dep2;
    278          UInt  oldC = cc_dep3;
    279          vassert((oldC & ~1) == 0);
    280          UInt  res  = argL + argR + oldC;
    281          ULong zf   = res == 0;
    282          return zf;
    283       }
    284       case ARM64G_CC_OP_ADC64: {
    285          /* (argL, argR, oldC) */
    286          ULong argL = cc_dep1;
    287          ULong argR = cc_dep2;
    288          ULong oldC = cc_dep3;
    289          vassert((oldC & ~1) == 0);
    290          ULong res  = argL + argR + oldC;
    291          ULong zf   = res == 0;
    292          return zf;
    293       }
    294       case ARM64G_CC_OP_SBC32: {
    295          /* (argL, argR, oldC) */
    296          UInt  argL = cc_dep1;
    297          UInt  argR = cc_dep2;
    298          UInt  oldC = cc_dep3;
    299          vassert((oldC & ~1) == 0);
    300          UInt  res  = argL - argR - (oldC ^ 1);
    301          ULong zf   = res == 0;
    302          return zf;
    303       }
    304       case ARM64G_CC_OP_SBC64: {
    305          /* (argL, argR, oldC) */
    306          ULong argL = cc_dep1;
    307          ULong argR = cc_dep2;
    308          ULong oldC = cc_dep3;
    309          vassert((oldC & ~1) == 0);
    310          ULong res  = argL - argR - (oldC ^ 1);
    311          ULong zf   = res == 0;
    312          return zf;
    313       }
    314       case ARM64G_CC_OP_LOGIC32: {
    315          /* (res, unused, unused) */
    316          UInt  res  = (UInt)cc_dep1;
    317          ULong zf   = res == 0;
    318          return zf;
    319       }
    320       case ARM64G_CC_OP_LOGIC64: {
    321          /* (res, unused, unused) */
    322          ULong res  = cc_dep1;
    323          ULong zf   = res == 0;
    324          return zf;
    325       }
    326 //ZZ       case ARMG_CC_OP_MUL: {
    327 //ZZ          /* (res, unused, oldC:oldV) */
    328 //ZZ          UInt res  = cc_dep1;
    329 //ZZ          UInt zf   = res == 0;
    330 //ZZ          return zf;
    331 //ZZ       }
    332 //ZZ       case ARMG_CC_OP_MULL: {
    333 //ZZ          /* (resLo32, resHi32, oldC:oldV) */
    334 //ZZ          UInt resLo32 = cc_dep1;
    335 //ZZ          UInt resHi32 = cc_dep2;
    336 //ZZ          UInt zf      = (resHi32|resLo32) == 0;
    337 //ZZ          return zf;
    338 //ZZ       }
    339       default:
    340          /* shouldn't really make these calls from generated code */
    341          vex_printf("arm64g_calculate_flag_z"
    342                     "( op=%llu, dep1=0x%llx, dep2=0x%llx, dep3=0x%llx )\n",
    343                     cc_op, cc_dep1, cc_dep2, cc_dep3 );
    344          vpanic("arm64g_calculate_flag_z");
    345    }
    346 }
    347 
    348 
    349 /* CALLED FROM GENERATED CODE: CLEAN HELPER */
    350 /* Calculate the C flag from the supplied thunk components, in the
    351    least significant bit of the word.  Returned bits 63:1 are zero. */
    352 ULong arm64g_calculate_flag_c ( ULong cc_op, ULong cc_dep1,
    353                                 ULong cc_dep2, ULong cc_dep3 )
    354 {
    355    switch (cc_op) {
    356       case ARM64G_CC_OP_COPY: {
    357          /* (nzcv:28x0, unused, unused) */
    358          ULong cf = (cc_dep1 >> ARM64G_CC_SHIFT_C) & 1;
    359          return cf;
    360       }
    361       case ARM64G_CC_OP_ADD32: {
    362          /* (argL, argR, unused) */
    363          UInt  argL = (UInt)cc_dep1;
    364          UInt  argR = (UInt)cc_dep2;
    365          UInt  res  = argL + argR;
    366          ULong cf   = res < argL;
    367          return cf;
    368       }
    369       case ARM64G_CC_OP_ADD64: {
    370          /* (argL, argR, unused) */
    371          ULong argL = cc_dep1;
    372          ULong argR = cc_dep2;
    373          ULong res  = argL + argR;
    374          ULong cf   = res < argL;
    375          return cf;
    376       }
    377       case ARM64G_CC_OP_SUB32: {
    378          /* (argL, argR, unused) */
    379          UInt  argL = (UInt)cc_dep1;
    380          UInt  argR = (UInt)cc_dep2;
    381          ULong cf   = argL >= argR;
    382          return cf;
    383       }
    384       case ARM64G_CC_OP_SUB64: {
    385          /* (argL, argR, unused) */
    386          ULong argL = cc_dep1;
    387          ULong argR = cc_dep2;
    388          ULong cf   = argL >= argR;
    389          return cf;
    390       }
    391       case ARM64G_CC_OP_ADC32: {
    392          /* (argL, argR, oldC) */
    393          UInt  argL = cc_dep1;
    394          UInt  argR = cc_dep2;
    395          UInt  oldC = cc_dep3;
    396          vassert((oldC & ~1) == 0);
    397          UInt  res  = argL + argR + oldC;
    398          ULong cf   = oldC ? (res <= argL) : (res < argL);
    399          return cf;
    400       }
    401       case ARM64G_CC_OP_ADC64: {
    402          /* (argL, argR, oldC) */
    403          ULong argL = cc_dep1;
    404          ULong argR = cc_dep2;
    405          ULong oldC = cc_dep3;
    406          vassert((oldC & ~1) == 0);
    407          ULong res  = argL + argR + oldC;
    408          ULong cf   = oldC ? (res <= argL) : (res < argL);
    409          return cf;
    410       }
    411       case ARM64G_CC_OP_SBC32: {
    412          /* (argL, argR, oldC) */
    413          UInt  argL = cc_dep1;
    414          UInt  argR = cc_dep2;
    415          UInt  oldC = cc_dep3;
    416          vassert((oldC & ~1) == 0);
    417          ULong cf   = oldC ? (argL >= argR) : (argL > argR);
    418          return cf;
    419       }
    420       case ARM64G_CC_OP_SBC64: {
    421          /* (argL, argR, oldC) */
    422          ULong argL = cc_dep1;
    423          ULong argR = cc_dep2;
    424          ULong oldC = cc_dep3;
    425          vassert((oldC & ~1) == 0);
    426          ULong cf   = oldC ? (argL >= argR) : (argL > argR);
    427          return cf;
    428       }
    429       case ARM64G_CC_OP_LOGIC32:
    430       case ARM64G_CC_OP_LOGIC64: {
    431          /* (res, unused, unused) */
    432          return 0; // C after logic is zero on arm64
    433       }
    434 //ZZ       case ARMG_CC_OP_MUL: {
    435 //ZZ          /* (res, unused, oldC:oldV) */
    436 //ZZ          UInt oldC = (cc_dep3 >> 1) & 1;
    437 //ZZ          vassert((cc_dep3 & ~3) == 0);
    438 //ZZ          UInt cf   = oldC;
    439 //ZZ          return cf;
    440 //ZZ       }
    441 //ZZ       case ARMG_CC_OP_MULL: {
    442 //ZZ          /* (resLo32, resHi32, oldC:oldV) */
    443 //ZZ          UInt oldC    = (cc_dep3 >> 1) & 1;
    444 //ZZ          vassert((cc_dep3 & ~3) == 0);
    445 //ZZ          UInt cf      = oldC;
    446 //ZZ          return cf;
    447 //ZZ       }
    448       default:
    449          /* shouldn't really make these calls from generated code */
    450          vex_printf("arm64g_calculate_flag_c"
    451                     "( op=%llu, dep1=0x%llx, dep2=0x%llx, dep3=0x%llx )\n",
    452                     cc_op, cc_dep1, cc_dep2, cc_dep3 );
    453          vpanic("arm64g_calculate_flag_c");
    454    }
    455 }
    456 
    457 
    458 /* CALLED FROM GENERATED CODE: CLEAN HELPER */
    459 /* Calculate the V flag from the supplied thunk components, in the
    460    least significant bit of the word.  Returned bits 63:1 are zero. */
    461 static
    462 ULong arm64g_calculate_flag_v ( ULong cc_op, ULong cc_dep1,
    463                                 ULong cc_dep2, ULong cc_dep3 )
    464 {
    465    switch (cc_op) {
    466       case ARM64G_CC_OP_COPY: {
    467          /* (nzcv:28x0, unused, unused) */
    468          ULong vf   = (cc_dep1 >> ARM64G_CC_SHIFT_V) & 1;
    469          return vf;
    470       }
    471       case ARM64G_CC_OP_ADD32: {
    472          /* (argL, argR, unused) */
    473          UInt  argL = (UInt)cc_dep1;
    474          UInt  argR = (UInt)cc_dep2;
    475          UInt  res  = argL + argR;
    476          ULong vf   = (ULong)(((res ^ argL) & (res ^ argR)) >> 31);
    477          return vf;
    478       }
    479       case ARM64G_CC_OP_ADD64: {
    480          /* (argL, argR, unused) */
    481          ULong argL = cc_dep1;
    482          ULong argR = cc_dep2;
    483          ULong res  = argL + argR;
    484          ULong vf   = ((res ^ argL) & (res ^ argR)) >> 63;
    485          return vf;
    486       }
    487       case ARM64G_CC_OP_SUB32: {
    488          /* (argL, argR, unused) */
    489          UInt  argL = (UInt)cc_dep1;
    490          UInt  argR = (UInt)cc_dep2;
    491          UInt  res  = argL - argR;
    492          ULong vf   = (ULong)(((argL ^ argR) & (argL ^ res)) >> 31);
    493          return vf;
    494       }
    495       case ARM64G_CC_OP_SUB64: {
    496          /* (argL, argR, unused) */
    497          ULong argL = cc_dep1;
    498          ULong argR = cc_dep2;
    499          ULong res  = argL - argR;
    500          ULong vf   = (((argL ^ argR) & (argL ^ res))) >> 63;
    501          return vf;
    502       }
    503       case ARM64G_CC_OP_ADC32: {
    504          /* (argL, argR, oldC) */
    505          UInt  argL = cc_dep1;
    506          UInt  argR = cc_dep2;
    507          UInt  oldC = cc_dep3;
    508          vassert((oldC & ~1) == 0);
    509          UInt  res  = argL + argR + oldC;
    510          ULong vf   = (ULong)(((res ^ argL) & (res ^ argR)) >> 31);
    511          return vf;
    512       }
    513       case ARM64G_CC_OP_ADC64: {
    514          /* (argL, argR, oldC) */
    515          ULong argL = cc_dep1;
    516          ULong argR = cc_dep2;
    517          ULong oldC = cc_dep3;
    518          vassert((oldC & ~1) == 0);
    519          ULong res  = argL + argR + oldC;
    520          ULong vf   = ((res ^ argL) & (res ^ argR)) >> 63;
    521          return vf;
    522       }
    523       case ARM64G_CC_OP_SBC32: {
    524          /* (argL, argR, oldC) */
    525          UInt  argL = cc_dep1;
    526          UInt  argR = cc_dep2;
    527          UInt  oldC = cc_dep3;
    528          vassert((oldC & ~1) == 0);
    529          UInt  res  = argL - argR - (oldC ^ 1);
    530          ULong vf   = (ULong)(((argL ^ argR) & (argL ^ res)) >> 31);
    531          return vf;
    532       }
    533       case ARM64G_CC_OP_SBC64: {
    534          /* (argL, argR, oldC) */
    535          ULong argL = cc_dep1;
    536          ULong argR = cc_dep2;
    537          ULong oldC = cc_dep3;
    538          vassert((oldC & ~1) == 0);
    539          ULong res  = argL - argR - (oldC ^ 1);
    540          ULong vf   = ((argL ^ argR) & (argL ^ res)) >> 63;
    541          return vf;
    542       }
    543       case ARM64G_CC_OP_LOGIC32:
    544       case ARM64G_CC_OP_LOGIC64: {
    545          /* (res, unused, unused) */
    546          return 0; // V after logic is zero on arm64
    547       }
    548 //ZZ       case ARMG_CC_OP_MUL: {
    549 //ZZ          /* (res, unused, oldC:oldV) */
    550 //ZZ          UInt oldV = (cc_dep3 >> 0) & 1;
    551 //ZZ          vassert((cc_dep3 & ~3) == 0);
    552 //ZZ          UInt vf   = oldV;
    553 //ZZ          return vf;
    554 //ZZ       }
    555 //ZZ       case ARMG_CC_OP_MULL: {
    556 //ZZ          /* (resLo32, resHi32, oldC:oldV) */
    557 //ZZ          UInt oldV    = (cc_dep3 >> 0) & 1;
    558 //ZZ          vassert((cc_dep3 & ~3) == 0);
    559 //ZZ          UInt vf      = oldV;
    560 //ZZ          return vf;
    561 //ZZ       }
    562       default:
    563          /* shouldn't really make these calls from generated code */
    564          vex_printf("arm64g_calculate_flag_v"
    565                     "( op=%llu, dep1=0x%llx, dep2=0x%llx, dep3=0x%llx )\n",
    566                     cc_op, cc_dep1, cc_dep2, cc_dep3 );
    567          vpanic("arm64g_calculate_flag_v");
    568    }
    569 }
    570 
    571 
    572 /* CALLED FROM GENERATED CODE: CLEAN HELPER */
    573 /* Calculate NZCV from the supplied thunk components, in the positions
    574    they appear in the CPSR, viz bits 31:28 for N Z C V respectively.
    575    Returned bits 27:0 are zero. */
    576 ULong arm64g_calculate_flags_nzcv ( ULong cc_op, ULong cc_dep1,
    577                                     ULong cc_dep2, ULong cc_dep3 )
    578 {
    579    ULong f;
    580    ULong res = 0;
    581    f = 1 & arm64g_calculate_flag_n(cc_op, cc_dep1, cc_dep2, cc_dep3);
    582    res |= (f << ARM64G_CC_SHIFT_N);
    583    f = 1 & arm64g_calculate_flag_z(cc_op, cc_dep1, cc_dep2, cc_dep3);
    584    res |= (f << ARM64G_CC_SHIFT_Z);
    585    f = 1 & arm64g_calculate_flag_c(cc_op, cc_dep1, cc_dep2, cc_dep3);
    586    res |= (f << ARM64G_CC_SHIFT_C);
    587    f = 1 & arm64g_calculate_flag_v(cc_op, cc_dep1, cc_dep2, cc_dep3);
    588    res |= (f << ARM64G_CC_SHIFT_V);
    589    return res;
    590 }
    591 
    592 //ZZ
    593 //ZZ /* CALLED FROM GENERATED CODE: CLEAN HELPER */
    594 //ZZ /* Calculate the QC flag from the arguments, in the lowest bit
    595 //ZZ    of the word (bit 0).  Urr, having this out of line is bizarre.
    596 //ZZ    Push back inline. */
    597 //ZZ UInt armg_calculate_flag_qc ( UInt resL1, UInt resL2,
    598 //ZZ                               UInt resR1, UInt resR2 )
    599 //ZZ {
    600 //ZZ    if (resL1 != resR1 || resL2 != resR2)
    601 //ZZ       return 1;
    602 //ZZ    else
    603 //ZZ       return 0;
    604 //ZZ }
    605 
    606 /* CALLED FROM GENERATED CODE: CLEAN HELPER */
    607 /* Calculate the specified condition from the thunk components, in the
    608    lowest bit of the word (bit 0).  Returned bits 63:1 are zero. */
    609 ULong arm64g_calculate_condition ( /* ARM64Condcode << 4 | cc_op */
    610                                    ULong cond_n_op ,
    611                                    ULong cc_dep1,
    612                                    ULong cc_dep2, ULong cc_dep3 )
    613 {
    614    ULong cond  = cond_n_op >> 4;
    615    ULong cc_op = cond_n_op & 0xF;
    616    ULong inv   = cond & 1;
    617    ULong nf, zf, vf, cf;
    618 
    619 #  if PROFILE_NZCV_FLAGS
    620    NOTE_EVAL(cc_op, cond);
    621 #  endif
    622 
    623    //   vex_printf("XXXXXXXX %llx %llx %llx %llx\n",
    624    //              cond_n_op, cc_dep1, cc_dep2, cc_dep3);
    625 
    626    switch (cond) {
    627       case ARM64CondEQ:    // Z=1         => z
    628       case ARM64CondNE:    // Z=0
    629          zf = arm64g_calculate_flag_z(cc_op, cc_dep1, cc_dep2, cc_dep3);
    630          return inv ^ zf;
    631 
    632       case ARM64CondCS:    // C=1         => c
    633       case ARM64CondCC:    // C=0
    634          cf = arm64g_calculate_flag_c(cc_op, cc_dep1, cc_dep2, cc_dep3);
    635          return inv ^ cf;
    636 
    637       case ARM64CondMI:    // N=1         => n
    638       case ARM64CondPL:    // N=0
    639          nf = arm64g_calculate_flag_n(cc_op, cc_dep1, cc_dep2, cc_dep3);
    640          return inv ^ nf;
    641 
    642       case ARM64CondVS:    // V=1         => v
    643       case ARM64CondVC:    // V=0
    644          vf = arm64g_calculate_flag_v(cc_op, cc_dep1, cc_dep2, cc_dep3);
    645          return inv ^ vf;
    646 
    647       case ARM64CondHI:    // C=1 && Z=0   => c & ~z
    648       case ARM64CondLS:    // C=0 || Z=1
    649          cf = arm64g_calculate_flag_c(cc_op, cc_dep1, cc_dep2, cc_dep3);
    650          zf = arm64g_calculate_flag_z(cc_op, cc_dep1, cc_dep2, cc_dep3);
    651          return inv ^ (1 & (cf & ~zf));
    652 
    653       case ARM64CondGE:    // N=V          => ~(n^v)
    654       case ARM64CondLT:    // N!=V
    655          nf = arm64g_calculate_flag_n(cc_op, cc_dep1, cc_dep2, cc_dep3);
    656          vf = arm64g_calculate_flag_v(cc_op, cc_dep1, cc_dep2, cc_dep3);
    657          return inv ^ (1 & ~(nf ^ vf));
    658 
    659       case ARM64CondGT:    // Z=0 && N=V   => ~z & ~(n^v)  =>  ~(z | (n^v))
    660       case ARM64CondLE:    // Z=1 || N!=V
    661          nf = arm64g_calculate_flag_n(cc_op, cc_dep1, cc_dep2, cc_dep3);
    662          vf = arm64g_calculate_flag_v(cc_op, cc_dep1, cc_dep2, cc_dep3);
    663          zf = arm64g_calculate_flag_z(cc_op, cc_dep1, cc_dep2, cc_dep3);
    664          return inv ^ (1 & ~(zf | (nf ^ vf)));
    665 
    666       case ARM64CondAL:    // 1
    667       case ARM64CondNV:    // 1
    668          return 1;
    669 
    670       default:
    671          /* shouldn't really make these calls from generated code */
    672          vex_printf("arm64g_calculate_condition(ARM64)"
    673                     "( %llu, %llu, 0x%llx, 0x%llx, 0x%llx )\n",
    674                     cond, cc_op, cc_dep1, cc_dep2, cc_dep3 );
    675          vpanic("armg_calculate_condition(ARM64)");
    676    }
    677 }
    678 
    679 
    680 /* CALLED FROM GENERATED CODE */
    681 /* DIRTY HELPER (non-referentially-transparent) */
    682 /* Horrible hack.  On non-arm64 platforms, return 0. */
    683 ULong arm64g_dirtyhelper_MRS_CNTVCT_EL0 ( void )
    684 {
    685 #  if defined(__aarch64__) && !defined(__arm__)
    686    ULong w = 0x5555555555555555ULL; /* overwritten */
    687    __asm__ __volatile__("mrs %0, cntvct_el0" : "=r"(w));
    688    return w;
    689 #  else
    690    return 0ULL;
    691 #  endif
    692 }
    693 
    694 
    695 /*---------------------------------------------------------------*/
    696 /*--- Flag-helpers translation-time function specialisers.    ---*/
    697 /*--- These help iropt specialise calls the above run-time    ---*/
    698 /*--- flags functions.                                        ---*/
    699 /*---------------------------------------------------------------*/
    700 
    701 /* Used by the optimiser to try specialisations.  Returns an
    702    equivalent expression, or NULL if none. */
    703 
    704 static Bool isU64 ( IRExpr* e, ULong n )
    705 {
    706    return
    707       toBool( e->tag == Iex_Const
    708               && e->Iex.Const.con->tag == Ico_U64
    709               && e->Iex.Const.con->Ico.U64 == n );
    710 }
    711 
    712 IRExpr* guest_arm64_spechelper ( const HChar* function_name,
    713                                  IRExpr** args,
    714                                  IRStmt** precedingStmts,
    715                                  Int      n_precedingStmts )
    716 {
    717 #  define unop(_op,_a1) IRExpr_Unop((_op),(_a1))
    718 #  define binop(_op,_a1,_a2) IRExpr_Binop((_op),(_a1),(_a2))
    719 #  define mkU64(_n) IRExpr_Const(IRConst_U64(_n))
    720 #  define mkU8(_n)  IRExpr_Const(IRConst_U8(_n))
    721 
    722    Int i, arity = 0;
    723    for (i = 0; args[i]; i++)
    724       arity++;
    725 //ZZ #  if 0
    726 //ZZ    vex_printf("spec request:\n");
    727 //ZZ    vex_printf("   %s  ", function_name);
    728 //ZZ    for (i = 0; i < arity; i++) {
    729 //ZZ       vex_printf("  ");
    730 //ZZ       ppIRExpr(args[i]);
    731 //ZZ    }
    732 //ZZ    vex_printf("\n");
    733 //ZZ #  endif
    734 
    735    /* --------- specialising "arm64g_calculate_condition" --------- */
    736 
    737    if (vex_streq(function_name, "arm64g_calculate_condition")) {
    738 
    739       /* specialise calls to the "arm64g_calculate_condition" function.
    740          Not sure whether this is strictly necessary, but: the
    741          replacement IR must produce only the values 0 or 1.  Bits
    742          63:1 are required to be zero. */
    743       IRExpr *cond_n_op, *cc_dep1, *cc_dep2  ; //, *cc_ndep;
    744       vassert(arity == 4);
    745       cond_n_op = args[0]; /* (ARM64Condcode << 4)  |  ARM64G_CC_OP_* */
    746       cc_dep1   = args[1];
    747       cc_dep2   = args[2];
    748       //cc_ndep   = args[3];
    749 
    750       /*---------------- SUB64 ----------------*/
    751 
    752       /* 0, 1 */
    753       if (isU64(cond_n_op, (ARM64CondEQ << 4) | ARM64G_CC_OP_SUB64)) {
    754          /* EQ after SUB --> test argL == argR */
    755          return unop(Iop_1Uto64,
    756                      binop(Iop_CmpEQ64, cc_dep1, cc_dep2));
    757       }
    758       if (isU64(cond_n_op, (ARM64CondNE << 4) | ARM64G_CC_OP_SUB64)) {
    759          /* NE after SUB --> test argL != argR */
    760          return unop(Iop_1Uto64,
    761                      binop(Iop_CmpNE64, cc_dep1, cc_dep2));
    762       }
    763 
    764       /* 2, 3 */
    765       if (isU64(cond_n_op, (ARM64CondCS << 4) | ARM64G_CC_OP_SUB64)) {
    766          /* CS after SUB --> test argL >=u argR
    767                          --> test argR <=u argL */
    768          return unop(Iop_1Uto64,
    769                      binop(Iop_CmpLE64U, cc_dep2, cc_dep1));
    770       }
    771       if (isU64(cond_n_op, (ARM64CondCC << 4) | ARM64G_CC_OP_SUB64)) {
    772          /* CC after SUB --> test argL <u argR */
    773          return unop(Iop_1Uto64,
    774                      binop(Iop_CmpLT64U, cc_dep1, cc_dep2));
    775       }
    776 
    777       /* 8, 9 */
    778       if (isU64(cond_n_op, (ARM64CondLS << 4) | ARM64G_CC_OP_SUB64)) {
    779          /* LS after SUB --> test argL <=u argR */
    780          return unop(Iop_1Uto64,
    781                      binop(Iop_CmpLE64U, cc_dep1, cc_dep2));
    782       }
    783       if (isU64(cond_n_op, (ARM64CondHI << 4) | ARM64G_CC_OP_SUB64)) {
    784          /* HI after SUB --> test argL >u argR
    785                          --> test argR <u argL */
    786          return unop(Iop_1Uto64,
    787                      binop(Iop_CmpLT64U, cc_dep2, cc_dep1));
    788       }
    789 
    790       /* 10, 11 */
    791       if (isU64(cond_n_op, (ARM64CondLT << 4) | ARM64G_CC_OP_SUB64)) {
    792          /* LT after SUB --> test argL <s argR */
    793          return unop(Iop_1Uto64,
    794                      binop(Iop_CmpLT64S, cc_dep1, cc_dep2));
    795       }
    796       if (isU64(cond_n_op, (ARM64CondGE << 4) | ARM64G_CC_OP_SUB64)) {
    797          /* GE after SUB --> test argL >=s argR
    798                          --> test argR <=s argL */
    799          return unop(Iop_1Uto64,
    800                      binop(Iop_CmpLE64S, cc_dep2, cc_dep1));
    801       }
    802 
    803       /* 12, 13 */
    804       if (isU64(cond_n_op, (ARM64CondGT << 4) | ARM64G_CC_OP_SUB64)) {
    805          /* GT after SUB --> test argL >s argR
    806                          --> test argR <s argL */
    807          return unop(Iop_1Uto64,
    808                      binop(Iop_CmpLT64S, cc_dep2, cc_dep1));
    809       }
    810       if (isU64(cond_n_op, (ARM64CondLE << 4) | ARM64G_CC_OP_SUB64)) {
    811          /* LE after SUB --> test argL <=s argR */
    812          return unop(Iop_1Uto64,
    813                      binop(Iop_CmpLE64S, cc_dep1, cc_dep2));
    814       }
    815 
    816       /*---------------- SUB32 ----------------*/
    817 
    818       /* 0, 1 */
    819       if (isU64(cond_n_op, (ARM64CondEQ << 4) | ARM64G_CC_OP_SUB32)) {
    820          /* EQ after SUB --> test argL == argR */
    821          return unop(Iop_1Uto64,
    822                      binop(Iop_CmpEQ32, unop(Iop_64to32, cc_dep1),
    823                                         unop(Iop_64to32, cc_dep2)));
    824       }
    825       if (isU64(cond_n_op, (ARM64CondNE << 4) | ARM64G_CC_OP_SUB32)) {
    826          /* NE after SUB --> test argL != argR */
    827          return unop(Iop_1Uto64,
    828                      binop(Iop_CmpNE32, unop(Iop_64to32, cc_dep1),
    829                                         unop(Iop_64to32, cc_dep2)));
    830       }
    831 
    832       /* 2, 3 */
    833       if (isU64(cond_n_op, (ARM64CondCS << 4) | ARM64G_CC_OP_SUB32)) {
    834          /* CS after SUB --> test argL >=u argR
    835                          --> test argR <=u argL */
    836          return unop(Iop_1Uto64,
    837                      binop(Iop_CmpLE32U, unop(Iop_64to32, cc_dep2),
    838                                          unop(Iop_64to32, cc_dep1)));
    839       }
    840       if (isU64(cond_n_op, (ARM64CondCC << 4) | ARM64G_CC_OP_SUB32)) {
    841          /* CC after SUB --> test argL <u argR */
    842          return unop(Iop_1Uto64,
    843                      binop(Iop_CmpLT32U, unop(Iop_64to32, cc_dep1),
    844                                          unop(Iop_64to32, cc_dep2)));
    845       }
    846 
    847       /* 8, 9 */
    848       if (isU64(cond_n_op, (ARM64CondLS << 4) | ARM64G_CC_OP_SUB32)) {
    849          /* LS after SUB --> test argL <=u argR */
    850          return unop(Iop_1Uto64,
    851                      binop(Iop_CmpLE32U, unop(Iop_64to32, cc_dep1),
    852                                          unop(Iop_64to32, cc_dep2)));
    853       }
    854       if (isU64(cond_n_op, (ARM64CondHI << 4) | ARM64G_CC_OP_SUB32)) {
    855          /* HI after SUB --> test argL >u argR
    856                          --> test argR <u argL */
    857          return unop(Iop_1Uto64,
    858                      binop(Iop_CmpLT32U, unop(Iop_64to32, cc_dep2),
    859                                          unop(Iop_64to32, cc_dep1)));
    860       }
    861 
    862       /* 10, 11 */
    863       if (isU64(cond_n_op, (ARM64CondLT << 4) | ARM64G_CC_OP_SUB32)) {
    864          /* LT after SUB --> test argL <s argR */
    865          return unop(Iop_1Uto64,
    866                      binop(Iop_CmpLT32S, unop(Iop_64to32, cc_dep1),
    867                                          unop(Iop_64to32, cc_dep2)));
    868       }
    869       if (isU64(cond_n_op, (ARM64CondGE << 4) | ARM64G_CC_OP_SUB32)) {
    870          /* GE after SUB --> test argL >=s argR
    871                          --> test argR <=s argL */
    872          return unop(Iop_1Uto64,
    873                      binop(Iop_CmpLE32S, unop(Iop_64to32, cc_dep2),
    874                                          unop(Iop_64to32, cc_dep1)));
    875       }
    876 
    877       /* 12, 13 */
    878       if (isU64(cond_n_op, (ARM64CondGT << 4) | ARM64G_CC_OP_SUB32)) {
    879          /* GT after SUB --> test argL >s argR
    880                          --> test argR <s argL */
    881          return unop(Iop_1Uto64,
    882                      binop(Iop_CmpLT32S, unop(Iop_64to32, cc_dep2),
    883                                          unop(Iop_64to32, cc_dep1)));
    884       }
    885       if (isU64(cond_n_op, (ARM64CondLE << 4) | ARM64G_CC_OP_SUB32)) {
    886          /* LE after SUB --> test argL <=s argR */
    887          return unop(Iop_1Uto64,
    888                      binop(Iop_CmpLE32S, unop(Iop_64to32, cc_dep1),
    889                                          unop(Iop_64to32, cc_dep2)));
    890       }
    891 
    892 //ZZ       /*---------------- SBB ----------------*/
    893 //ZZ
    894 //ZZ       if (isU32(cond_n_op, (ARMCondHS << 4) | ARMG_CC_OP_SBB)) {
    895 //ZZ          /* This seems to happen a lot in softfloat code, eg __divdf3+140 */
    896 //ZZ          /* thunk is: (dep1=argL, dep2=argR, ndep=oldC) */
    897 //ZZ          /* HS after SBB (same as C after SBB below)
    898 //ZZ             --> oldC ? (argL >=u argR) : (argL >u argR)
    899 //ZZ             --> oldC ? (argR <=u argL) : (argR <u argL)
    900 //ZZ          */
    901 //ZZ          return
    902 //ZZ             IRExpr_ITE(
    903 //ZZ                binop(Iop_CmpNE32, cc_ndep, mkU32(0)),
    904 //ZZ                /* case oldC != 0 */
    905 //ZZ                unop(Iop_1Uto32, binop(Iop_CmpLE32U, cc_dep2, cc_dep1)),
    906 //ZZ                /* case oldC == 0 */
    907 //ZZ                unop(Iop_1Uto32, binop(Iop_CmpLT32U, cc_dep2, cc_dep1))
    908 //ZZ             );
    909 //ZZ       }
    910 //ZZ
    911 //ZZ       /*---------------- LOGIC ----------------*/
    912 //ZZ
    913 //ZZ       if (isU32(cond_n_op, (ARMCondEQ << 4) | ARMG_CC_OP_LOGIC)) {
    914 //ZZ          /* EQ after LOGIC --> test res == 0 */
    915 //ZZ          return unop(Iop_1Uto32,
    916 //ZZ                      binop(Iop_CmpEQ32, cc_dep1, mkU32(0)));
    917 //ZZ       }
    918 //ZZ       if (isU32(cond_n_op, (ARMCondNE << 4) | ARMG_CC_OP_LOGIC)) {
    919 //ZZ          /* NE after LOGIC --> test res != 0 */
    920 //ZZ          return unop(Iop_1Uto32,
    921 //ZZ                      binop(Iop_CmpNE32, cc_dep1, mkU32(0)));
    922 //ZZ       }
    923 //ZZ
    924 //ZZ       if (isU32(cond_n_op, (ARMCondPL << 4) | ARMG_CC_OP_LOGIC)) {
    925 //ZZ          /* PL after LOGIC --> test (res >> 31) == 0 */
    926 //ZZ          return unop(Iop_1Uto32,
    927 //ZZ                      binop(Iop_CmpEQ32,
    928 //ZZ                            binop(Iop_Shr32, cc_dep1, mkU8(31)),
    929 //ZZ                            mkU32(0)));
    930 //ZZ       }
    931 //ZZ       if (isU32(cond_n_op, (ARMCondMI << 4) | ARMG_CC_OP_LOGIC)) {
    932 //ZZ          /* MI after LOGIC --> test (res >> 31) == 1 */
    933 //ZZ          return unop(Iop_1Uto32,
    934 //ZZ                      binop(Iop_CmpEQ32,
    935 //ZZ                            binop(Iop_Shr32, cc_dep1, mkU8(31)),
    936 //ZZ                            mkU32(1)));
    937 //ZZ       }
    938 
    939       /*---------------- COPY ----------------*/
    940 
    941       if (isU64(cond_n_op, (ARM64CondEQ << 4) | ARM64G_CC_OP_COPY)) {
    942          /* EQ after COPY --> (cc_dep1 >> ARM64G_CC_SHIFT_Z) & 1 */
    943          return binop(Iop_And64,
    944                       binop(Iop_Shr64, cc_dep1,
    945                                        mkU8(ARM64G_CC_SHIFT_Z)),
    946                       mkU64(1));
    947       }
    948       if (isU64(cond_n_op, (ARM64CondNE << 4) | ARM64G_CC_OP_COPY)) {
    949          /* NE after COPY --> ((cc_dep1 >> ARM64G_CC_SHIFT_Z) ^ 1) & 1 */
    950          return binop(Iop_And64,
    951                       binop(Iop_Xor64,
    952                             binop(Iop_Shr64, cc_dep1,
    953                                              mkU8(ARM64G_CC_SHIFT_Z)),
    954                             mkU64(1)),
    955                       mkU64(1));
    956       }
    957 
    958 //ZZ       /*----------------- AL -----------------*/
    959 //ZZ
    960 //ZZ       /* A critically important case for Thumb code.
    961 //ZZ
    962 //ZZ          What we're trying to spot is the case where cond_n_op is an
    963 //ZZ          expression of the form Or32(..., 0xE0) since that means the
    964 //ZZ          caller is asking for CondAL and we can simply return 1
    965 //ZZ          without caring what the ... part is.  This is a potentially
    966 //ZZ          dodgy kludge in that it assumes that the ... part has zeroes
    967 //ZZ          in bits 7:4, so that the result of the Or32 is guaranteed to
    968 //ZZ          be 0xE in bits 7:4.  Given that the places where this first
    969 //ZZ          arg are constructed (in guest_arm_toIR.c) are very
    970 //ZZ          constrained, we can get away with this.  To make this
    971 //ZZ          guaranteed safe would require to have a new primop, Slice44
    972 //ZZ          or some such, thusly
    973 //ZZ
    974 //ZZ          Slice44(arg1, arg2) = 0--(24)--0 arg1[7:4] arg2[3:0]
    975 //ZZ
    976 //ZZ          and we would then look for Slice44(0xE0, ...)
    977 //ZZ          which would give the required safety property.
    978 //ZZ
    979 //ZZ          It would be infeasibly expensive to scan backwards through
    980 //ZZ          the entire block looking for an assignment to the temp, so
    981 //ZZ          just look at the previous 16 statements.  That should find it
    982 //ZZ          if it is an interesting case, as a result of how the
    983 //ZZ          boilerplate guff at the start of each Thumb insn translation
    984 //ZZ          is made.
    985 //ZZ       */
    986 //ZZ       if (cond_n_op->tag == Iex_RdTmp) {
    987 //ZZ          Int    j;
    988 //ZZ          IRTemp look_for = cond_n_op->Iex.RdTmp.tmp;
    989 //ZZ          Int    limit    = n_precedingStmts - 16;
    990 //ZZ          if (limit < 0) limit = 0;
    991 //ZZ          if (0) vex_printf("scanning %d .. %d\n", n_precedingStmts-1, limit);
    992 //ZZ          for (j = n_precedingStmts - 1; j >= limit; j--) {
    993 //ZZ             IRStmt* st = precedingStmts[j];
    994 //ZZ             if (st->tag == Ist_WrTmp
    995 //ZZ                 && st->Ist.WrTmp.tmp == look_for
    996 //ZZ                 && st->Ist.WrTmp.data->tag == Iex_Binop
    997 //ZZ                 && st->Ist.WrTmp.data->Iex.Binop.op == Iop_Or32
    998 //ZZ                 && isU32(st->Ist.WrTmp.data->Iex.Binop.arg2, (ARMCondAL << 4)))
    999 //ZZ                return mkU32(1);
   1000 //ZZ          }
   1001 //ZZ          /* Didn't find any useful binding to the first arg
   1002 //ZZ             in the previous 16 stmts. */
   1003 //ZZ       }
   1004    }
   1005 
   1006 //ZZ    /* --------- specialising "armg_calculate_flag_c" --------- */
   1007 //ZZ
   1008 //ZZ    else
   1009 //ZZ    if (vex_streq(function_name, "armg_calculate_flag_c")) {
   1010 //ZZ
   1011 //ZZ       /* specialise calls to the "armg_calculate_flag_c" function.
   1012 //ZZ          Note that the returned value must be either 0 or 1; nonzero
   1013 //ZZ          bits 31:1 are not allowed.  In turn, incoming oldV and oldC
   1014 //ZZ          values (from the thunk) are assumed to have bits 31:1
   1015 //ZZ          clear. */
   1016 //ZZ       IRExpr *cc_op, *cc_dep1, *cc_dep2, *cc_ndep;
   1017 //ZZ       vassert(arity == 4);
   1018 //ZZ       cc_op   = args[0]; /* ARMG_CC_OP_* */
   1019 //ZZ       cc_dep1 = args[1];
   1020 //ZZ       cc_dep2 = args[2];
   1021 //ZZ       cc_ndep = args[3];
   1022 //ZZ
   1023 //ZZ       if (isU32(cc_op, ARMG_CC_OP_LOGIC)) {
   1024 //ZZ          /* Thunk args are (result, shco, oldV) */
   1025 //ZZ          /* C after LOGIC --> shco */
   1026 //ZZ          return cc_dep2;
   1027 //ZZ       }
   1028 //ZZ
   1029 //ZZ       if (isU32(cc_op, ARMG_CC_OP_SUB)) {
   1030 //ZZ          /* Thunk args are (argL, argR, unused) */
   1031 //ZZ          /* C after SUB --> argL >=u argR
   1032 //ZZ                         --> argR <=u argL */
   1033 //ZZ          return unop(Iop_1Uto32,
   1034 //ZZ                      binop(Iop_CmpLE32U, cc_dep2, cc_dep1));
   1035 //ZZ       }
   1036 //ZZ
   1037 //ZZ       if (isU32(cc_op, ARMG_CC_OP_SBB)) {
   1038 //ZZ          /* This happens occasionally in softfloat code, eg __divdf3+140 */
   1039 //ZZ          /* thunk is: (dep1=argL, dep2=argR, ndep=oldC) */
   1040 //ZZ          /* C after SBB (same as HS after SBB above)
   1041 //ZZ             --> oldC ? (argL >=u argR) : (argL >u argR)
   1042 //ZZ             --> oldC ? (argR <=u argL) : (argR <u argL)
   1043 //ZZ          */
   1044 //ZZ          return
   1045 //ZZ             IRExpr_ITE(
   1046 //ZZ                binop(Iop_CmpNE32, cc_ndep, mkU32(0)),
   1047 //ZZ                /* case oldC != 0 */
   1048 //ZZ                unop(Iop_1Uto32, binop(Iop_CmpLE32U, cc_dep2, cc_dep1)),
   1049 //ZZ                /* case oldC == 0 */
   1050 //ZZ                unop(Iop_1Uto32, binop(Iop_CmpLT32U, cc_dep2, cc_dep1))
   1051 //ZZ             );
   1052 //ZZ       }
   1053 //ZZ
   1054 //ZZ    }
   1055 //ZZ
   1056 //ZZ    /* --------- specialising "armg_calculate_flag_v" --------- */
   1057 //ZZ
   1058 //ZZ    else
   1059 //ZZ    if (vex_streq(function_name, "armg_calculate_flag_v")) {
   1060 //ZZ
   1061 //ZZ       /* specialise calls to the "armg_calculate_flag_v" function.
   1062 //ZZ          Note that the returned value must be either 0 or 1; nonzero
   1063 //ZZ          bits 31:1 are not allowed.  In turn, incoming oldV and oldC
   1064 //ZZ          values (from the thunk) are assumed to have bits 31:1
   1065 //ZZ          clear. */
   1066 //ZZ       IRExpr *cc_op, *cc_dep1, *cc_dep2, *cc_ndep;
   1067 //ZZ       vassert(arity == 4);
   1068 //ZZ       cc_op   = args[0]; /* ARMG_CC_OP_* */
   1069 //ZZ       cc_dep1 = args[1];
   1070 //ZZ       cc_dep2 = args[2];
   1071 //ZZ       cc_ndep = args[3];
   1072 //ZZ
   1073 //ZZ       if (isU32(cc_op, ARMG_CC_OP_LOGIC)) {
   1074 //ZZ          /* Thunk args are (result, shco, oldV) */
   1075 //ZZ          /* V after LOGIC --> oldV */
   1076 //ZZ          return cc_ndep;
   1077 //ZZ       }
   1078 //ZZ
   1079 //ZZ       if (isU32(cc_op, ARMG_CC_OP_SUB)) {
   1080 //ZZ          /* Thunk args are (argL, argR, unused) */
   1081 //ZZ          /* V after SUB
   1082 //ZZ             --> let res = argL - argR
   1083 //ZZ                 in ((argL ^ argR) & (argL ^ res)) >> 31
   1084 //ZZ             --> ((argL ^ argR) & (argL ^ (argL - argR))) >> 31
   1085 //ZZ          */
   1086 //ZZ          IRExpr* argL = cc_dep1;
   1087 //ZZ          IRExpr* argR = cc_dep2;
   1088 //ZZ          return
   1089 //ZZ             binop(Iop_Shr32,
   1090 //ZZ                   binop(Iop_And32,
   1091 //ZZ                         binop(Iop_Xor32, argL, argR),
   1092 //ZZ                         binop(Iop_Xor32, argL, binop(Iop_Sub32, argL, argR))
   1093 //ZZ                   ),
   1094 //ZZ                   mkU8(31)
   1095 //ZZ             );
   1096 //ZZ       }
   1097 //ZZ
   1098 //ZZ       if (isU32(cc_op, ARMG_CC_OP_SBB)) {
   1099 //ZZ          /* This happens occasionally in softfloat code, eg __divdf3+140 */
   1100 //ZZ          /* thunk is: (dep1=argL, dep2=argR, ndep=oldC) */
   1101 //ZZ          /* V after SBB
   1102 //ZZ             --> let res = argL - argR - (oldC ^ 1)
   1103 //ZZ                 in  (argL ^ argR) & (argL ^ res) & 1
   1104 //ZZ          */
   1105 //ZZ          return
   1106 //ZZ             binop(
   1107 //ZZ                Iop_And32,
   1108 //ZZ                binop(
   1109 //ZZ                   Iop_And32,
   1110 //ZZ                   // argL ^ argR
   1111 //ZZ                   binop(Iop_Xor32, cc_dep1, cc_dep2),
   1112 //ZZ                   // argL ^ (argL - argR - (oldC ^ 1))
   1113 //ZZ                   binop(Iop_Xor32,
   1114 //ZZ                         cc_dep1,
   1115 //ZZ                         binop(Iop_Sub32,
   1116 //ZZ                               binop(Iop_Sub32, cc_dep1, cc_dep2),
   1117 //ZZ                               binop(Iop_Xor32, cc_ndep, mkU32(1)))
   1118 //ZZ                   )
   1119 //ZZ                ),
   1120 //ZZ                mkU32(1)
   1121 //ZZ             );
   1122 //ZZ       }
   1123 //ZZ
   1124 //ZZ    }
   1125 
   1126 #  undef unop
   1127 #  undef binop
   1128 #  undef mkU64
   1129 #  undef mkU8
   1130 
   1131    return NULL;
   1132 }
   1133 
   1134 
   1135 /*----------------------------------------------*/
   1136 /*--- The exported fns ..                    ---*/
   1137 /*----------------------------------------------*/
   1138 
   1139 //ZZ /* VISIBLE TO LIBVEX CLIENT */
   1140 //ZZ #if 0
   1141 //ZZ void LibVEX_GuestARM_put_flags ( UInt flags_native,
   1142 //ZZ                                  /*OUT*/VexGuestARMState* vex_state )
   1143 //ZZ {
   1144 //ZZ    vassert(0); // FIXME
   1145 //ZZ
   1146 //ZZ    /* Mask out everything except N Z V C. */
   1147 //ZZ    flags_native
   1148 //ZZ       &= (ARMG_CC_MASK_N | ARMG_CC_MASK_Z | ARMG_CC_MASK_V | ARMG_CC_MASK_C);
   1149 //ZZ
   1150 //ZZ    vex_state->guest_CC_OP   = ARMG_CC_OP_COPY;
   1151 //ZZ    vex_state->guest_CC_DEP1 = flags_native;
   1152 //ZZ    vex_state->guest_CC_DEP2 = 0;
   1153 //ZZ    vex_state->guest_CC_NDEP = 0;
   1154 //ZZ }
   1155 //ZZ #endif
   1156 
   1157 /* VISIBLE TO LIBVEX CLIENT */
   1158 ULong LibVEX_GuestARM64_get_nzcv ( /*IN*/const VexGuestARM64State* vex_state )
   1159 {
   1160    ULong nzcv = 0;
   1161    // NZCV
   1162    nzcv |= arm64g_calculate_flags_nzcv(
   1163                vex_state->guest_CC_OP,
   1164                vex_state->guest_CC_DEP1,
   1165                vex_state->guest_CC_DEP2,
   1166                vex_state->guest_CC_NDEP
   1167             );
   1168    vassert(0 == (nzcv & 0xFFFFFFFF0FFFFFFFULL));
   1169 //ZZ    // Q
   1170 //ZZ    if (vex_state->guest_QFLAG32 > 0)
   1171 //ZZ       cpsr |= (1 << 27);
   1172 //ZZ    // GE
   1173 //ZZ    if (vex_state->guest_GEFLAG0 > 0)
   1174 //ZZ       cpsr |= (1 << 16);
   1175 //ZZ    if (vex_state->guest_GEFLAG1 > 0)
   1176 //ZZ       cpsr |= (1 << 17);
   1177 //ZZ    if (vex_state->guest_GEFLAG2 > 0)
   1178 //ZZ       cpsr |= (1 << 18);
   1179 //ZZ    if (vex_state->guest_GEFLAG3 > 0)
   1180 //ZZ       cpsr |= (1 << 19);
   1181 //ZZ    // M
   1182 //ZZ    cpsr |= (1 << 4); // 0b10000 means user-mode
   1183 //ZZ    // J,T   J (bit 24) is zero by initialisation above
   1184 //ZZ    // T  we copy from R15T[0]
   1185 //ZZ    if (vex_state->guest_R15T & 1)
   1186 //ZZ       cpsr |= (1 << 5);
   1187 //ZZ    // ITSTATE we punt on for the time being.  Could compute it
   1188 //ZZ    // if needed though.
   1189 //ZZ    // E, endianness, 0 (littleendian) from initialisation above
   1190 //ZZ    // A,I,F disable some async exceptions.  Not sure about these.
   1191 //ZZ    // Leave as zero for the time being.
   1192    return nzcv;
   1193 }
   1194 
   1195 /* VISIBLE TO LIBVEX CLIENT */
   1196 ULong LibVEX_GuestARM64_get_fpsr ( const VexGuestARM64State* vex_state )
   1197 {
   1198    UInt w32 = vex_state->guest_QCFLAG[0] | vex_state->guest_QCFLAG[1]
   1199               | vex_state->guest_QCFLAG[2] | vex_state->guest_QCFLAG[3];
   1200    ULong fpsr = 0;
   1201    // QC
   1202    if (w32 != 0)
   1203       fpsr |= (1 << 27);
   1204    return fpsr;
   1205 }
   1206 
   1207 void LibVEX_GuestARM64_set_fpsr ( /*MOD*/VexGuestARM64State* vex_state,
   1208                                   ULong fpsr )
   1209 {
   1210    // QC
   1211    vex_state->guest_QCFLAG[0] = (UInt)((fpsr >> 27) & 1);
   1212    vex_state->guest_QCFLAG[1] = 0;
   1213    vex_state->guest_QCFLAG[2] = 0;
   1214    vex_state->guest_QCFLAG[3] = 0;
   1215 }
   1216 
   1217 /* VISIBLE TO LIBVEX CLIENT */
   1218 void LibVEX_GuestARM64_initialise ( /*OUT*/VexGuestARM64State* vex_state )
   1219 {
   1220    vex_bzero(vex_state, sizeof(*vex_state));
   1221 //ZZ    vex_state->host_EvC_FAILADDR = 0;
   1222 //ZZ    vex_state->host_EvC_COUNTER = 0;
   1223 //ZZ
   1224 //ZZ    vex_state->guest_R0  = 0;
   1225 //ZZ    vex_state->guest_R1  = 0;
   1226 //ZZ    vex_state->guest_R2  = 0;
   1227 //ZZ    vex_state->guest_R3  = 0;
   1228 //ZZ    vex_state->guest_R4  = 0;
   1229 //ZZ    vex_state->guest_R5  = 0;
   1230 //ZZ    vex_state->guest_R6  = 0;
   1231 //ZZ    vex_state->guest_R7  = 0;
   1232 //ZZ    vex_state->guest_R8  = 0;
   1233 //ZZ    vex_state->guest_R9  = 0;
   1234 //ZZ    vex_state->guest_R10 = 0;
   1235 //ZZ    vex_state->guest_R11 = 0;
   1236 //ZZ    vex_state->guest_R12 = 0;
   1237 //ZZ    vex_state->guest_R13 = 0;
   1238 //ZZ    vex_state->guest_R14 = 0;
   1239 //ZZ    vex_state->guest_R15T = 0;  /* NB: implies ARM mode */
   1240 //ZZ
   1241    vex_state->guest_CC_OP   = ARM64G_CC_OP_COPY;
   1242 //ZZ    vex_state->guest_CC_DEP1 = 0;
   1243 //ZZ    vex_state->guest_CC_DEP2 = 0;
   1244 //ZZ    vex_state->guest_CC_NDEP = 0;
   1245 //ZZ    vex_state->guest_QFLAG32 = 0;
   1246 //ZZ    vex_state->guest_GEFLAG0 = 0;
   1247 //ZZ    vex_state->guest_GEFLAG1 = 0;
   1248 //ZZ    vex_state->guest_GEFLAG2 = 0;
   1249 //ZZ    vex_state->guest_GEFLAG3 = 0;
   1250 //ZZ
   1251 //ZZ    vex_state->guest_EMNOTE  = EmNote_NONE;
   1252 //ZZ    vex_state->guest_CMSTART = 0;
   1253 //ZZ    vex_state->guest_CMLEN   = 0;
   1254 //ZZ    vex_state->guest_NRADDR  = 0;
   1255 //ZZ    vex_state->guest_IP_AT_SYSCALL = 0;
   1256 //ZZ
   1257 //ZZ    vex_state->guest_D0  = 0;
   1258 //ZZ    vex_state->guest_D1  = 0;
   1259 //ZZ    vex_state->guest_D2  = 0;
   1260 //ZZ    vex_state->guest_D3  = 0;
   1261 //ZZ    vex_state->guest_D4  = 0;
   1262 //ZZ    vex_state->guest_D5  = 0;
   1263 //ZZ    vex_state->guest_D6  = 0;
   1264 //ZZ    vex_state->guest_D7  = 0;
   1265 //ZZ    vex_state->guest_D8  = 0;
   1266 //ZZ    vex_state->guest_D9  = 0;
   1267 //ZZ    vex_state->guest_D10 = 0;
   1268 //ZZ    vex_state->guest_D11 = 0;
   1269 //ZZ    vex_state->guest_D12 = 0;
   1270 //ZZ    vex_state->guest_D13 = 0;
   1271 //ZZ    vex_state->guest_D14 = 0;
   1272 //ZZ    vex_state->guest_D15 = 0;
   1273 //ZZ    vex_state->guest_D16 = 0;
   1274 //ZZ    vex_state->guest_D17 = 0;
   1275 //ZZ    vex_state->guest_D18 = 0;
   1276 //ZZ    vex_state->guest_D19 = 0;
   1277 //ZZ    vex_state->guest_D20 = 0;
   1278 //ZZ    vex_state->guest_D21 = 0;
   1279 //ZZ    vex_state->guest_D22 = 0;
   1280 //ZZ    vex_state->guest_D23 = 0;
   1281 //ZZ    vex_state->guest_D24 = 0;
   1282 //ZZ    vex_state->guest_D25 = 0;
   1283 //ZZ    vex_state->guest_D26 = 0;
   1284 //ZZ    vex_state->guest_D27 = 0;
   1285 //ZZ    vex_state->guest_D28 = 0;
   1286 //ZZ    vex_state->guest_D29 = 0;
   1287 //ZZ    vex_state->guest_D30 = 0;
   1288 //ZZ    vex_state->guest_D31 = 0;
   1289 //ZZ
   1290 //ZZ    /* ARM encoded; zero is the default as it happens (result flags
   1291 //ZZ       (NZCV) cleared, FZ disabled, round to nearest, non-vector mode,
   1292 //ZZ       all exns masked, all exn sticky bits cleared). */
   1293 //ZZ    vex_state->guest_FPSCR = 0;
   1294 //ZZ
   1295 //ZZ    vex_state->guest_TPIDRURO = 0;
   1296 //ZZ
   1297 //ZZ    /* Not in a Thumb IT block. */
   1298 //ZZ    vex_state->guest_ITSTATE = 0;
   1299 //ZZ
   1300 //ZZ    vex_state->padding1 = 0;
   1301 //ZZ    vex_state->padding2 = 0;
   1302 //ZZ    vex_state->padding3 = 0;
   1303 //ZZ    vex_state->padding4 = 0;
   1304 //ZZ    vex_state->padding5 = 0;
   1305 }
   1306 
   1307 
   1308 /*-----------------------------------------------------------*/
   1309 /*--- Describing the arm guest state, for the benefit     ---*/
   1310 /*--- of iropt and instrumenters.                         ---*/
   1311 /*-----------------------------------------------------------*/
   1312 
   1313 /* Figure out if any part of the guest state contained in minoff
   1314    .. maxoff requires precise memory exceptions.  If in doubt return
   1315    True (but this generates significantly slower code).
   1316 
   1317    We enforce precise exns for guest SP, PC, 29(FP), 30(LR).
   1318    That might be overkill (for 29 and 30); I don't know.
   1319 */
   1320 Bool guest_arm64_state_requires_precise_mem_exns (
   1321         Int minoff, Int maxoff, VexRegisterUpdates pxControl
   1322      )
   1323 {
   1324    Int xsp_min = offsetof(VexGuestARM64State, guest_XSP);
   1325    Int xsp_max = xsp_min + 8 - 1;
   1326    Int pc_min  = offsetof(VexGuestARM64State, guest_PC);
   1327    Int pc_max  = pc_min + 8 - 1;
   1328 
   1329    if (maxoff < xsp_min || minoff > xsp_max) {
   1330       /* no overlap with xsp */
   1331       if (pxControl == VexRegUpdSpAtMemAccess)
   1332          return False; // We only need to check stack pointer.
   1333    } else {
   1334       return True;
   1335    }
   1336 
   1337    if (maxoff < pc_min || minoff > pc_max) {
   1338       /* no overlap with pc */
   1339    } else {
   1340       return True;
   1341    }
   1342 
   1343    /* Guessing that we need PX for FP, but I don't really know. */
   1344    Int x29_min = offsetof(VexGuestARM64State, guest_X29);
   1345    Int x29_max = x29_min + 8 - 1;
   1346 
   1347    if (maxoff < x29_min || minoff > x29_max) {
   1348       /* no overlap with x29 */
   1349    } else {
   1350       return True;
   1351    }
   1352 
   1353    /* Guessing that we need PX for LR, but I don't really know. */
   1354    Int x30_min = offsetof(VexGuestARM64State, guest_X30);
   1355    Int x30_max = x30_min + 8 - 1;
   1356 
   1357    if (maxoff < x30_min || minoff > x30_max) {
   1358       /* no overlap with r30 */
   1359    } else {
   1360       return True;
   1361    }
   1362 
   1363    return False;
   1364 }
   1365 
   1366 
   1367 #define ALWAYSDEFD(field)                             \
   1368     { offsetof(VexGuestARM64State, field),            \
   1369       (sizeof ((VexGuestARM64State*)0)->field) }
   1370 VexGuestLayout
   1371    arm64Guest_layout
   1372       = {
   1373           /* Total size of the guest state, in bytes. */
   1374           .total_sizeB = sizeof(VexGuestARM64State),
   1375 
   1376           /* Describe the stack pointer. */
   1377           .offset_SP = offsetof(VexGuestARM64State,guest_XSP),
   1378           .sizeof_SP = 8,
   1379 
   1380           /* Describe the instruction pointer. */
   1381           .offset_IP = offsetof(VexGuestARM64State,guest_PC),
   1382           .sizeof_IP = 8,
   1383 
   1384           /* Describe any sections to be regarded by Memcheck as
   1385              'always-defined'. */
   1386           .n_alwaysDefd = 9,
   1387 
   1388           /* flags thunk: OP is always defd, whereas DEP1 and DEP2
   1389              have to be tracked.  See detailed comment in gdefs.h on
   1390              meaning of thunk fields. */
   1391           .alwaysDefd
   1392              = { /* 0 */ ALWAYSDEFD(guest_PC),
   1393                  /* 1 */ ALWAYSDEFD(guest_CC_OP),
   1394                  /* 2 */ ALWAYSDEFD(guest_CC_NDEP),
   1395                  /* 3 */ ALWAYSDEFD(guest_EMNOTE),
   1396                  /* 4 */ ALWAYSDEFD(guest_CMSTART),
   1397                  /* 5 */ ALWAYSDEFD(guest_CMLEN),
   1398                  /* 6 */ ALWAYSDEFD(guest_NRADDR),
   1399                  /* 7 */ ALWAYSDEFD(guest_IP_AT_SYSCALL),
   1400                  /* 8 */ ALWAYSDEFD(guest_TPIDR_EL0)
   1401                }
   1402         };
   1403 
   1404 
   1405 /*---------------------------------------------------------------*/
   1406 /*--- end                               guest_arm64_helpers.c ---*/
   1407 /*---------------------------------------------------------------*/
   1408