Home | History | Annotate | Download | only in priv
      1 /* -*- mode: C; c-basic-offset: 3; -*- */
      2 
      3 /*---------------------------------------------------------------*/
      4 /*--- begin                              guest_s390_helpers.c ---*/
      5 /*---------------------------------------------------------------*/
      6 
      7 /*
      8    This file is part of Valgrind, a dynamic binary instrumentation
      9    framework.
     10 
     11    Copyright IBM Corp. 2010-2012
     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 /* Contributed by Florian Krohm */
     32 
     33 #include "libvex_basictypes.h"
     34 #include "libvex_emwarn.h"
     35 #include "libvex_guest_s390x.h"
     36 #include "libvex_ir.h"
     37 #include "libvex.h"
     38 #include "libvex_s390x_common.h"
     39 
     40 #include "main_util.h"
     41 #include "guest_generic_bb_to_IR.h"
     42 #include "guest_s390_defs.h"
     43 
     44 void
     45 LibVEX_GuestS390X_initialise(VexGuestS390XState *state)
     46 {
     47 /*------------------------------------------------------------*/
     48 /*--- Initialise ar registers                              ---*/
     49 /*------------------------------------------------------------*/
     50 
     51    state->guest_a0 = 0;
     52    state->guest_a1 = 0;
     53    state->guest_a2 = 0;
     54    state->guest_a3 = 0;
     55    state->guest_a4 = 0;
     56    state->guest_a5 = 0;
     57    state->guest_a6 = 0;
     58    state->guest_a7 = 0;
     59    state->guest_a8 = 0;
     60    state->guest_a9 = 0;
     61    state->guest_a10 = 0;
     62    state->guest_a11 = 0;
     63    state->guest_a12 = 0;
     64    state->guest_a13 = 0;
     65    state->guest_a14 = 0;
     66    state->guest_a15 = 0;
     67 
     68 /*------------------------------------------------------------*/
     69 /*--- Initialise fpr registers                             ---*/
     70 /*------------------------------------------------------------*/
     71 
     72    state->guest_f0 = 0;
     73    state->guest_f1 = 0;
     74    state->guest_f2 = 0;
     75    state->guest_f3 = 0;
     76    state->guest_f4 = 0;
     77    state->guest_f5 = 0;
     78    state->guest_f6 = 0;
     79    state->guest_f7 = 0;
     80    state->guest_f8 = 0;
     81    state->guest_f9 = 0;
     82    state->guest_f10 = 0;
     83    state->guest_f11 = 0;
     84    state->guest_f12 = 0;
     85    state->guest_f13 = 0;
     86    state->guest_f14 = 0;
     87    state->guest_f15 = 0;
     88 
     89 /*------------------------------------------------------------*/
     90 /*--- Initialise gpr registers                             ---*/
     91 /*------------------------------------------------------------*/
     92 
     93    state->guest_r0 = 0;
     94    state->guest_r1 = 0;
     95    state->guest_r2 = 0;
     96    state->guest_r3 = 0;
     97    state->guest_r4 = 0;
     98    state->guest_r5 = 0;
     99    state->guest_r6 = 0;
    100    state->guest_r7 = 0;
    101    state->guest_r8 = 0;
    102    state->guest_r9 = 0;
    103    state->guest_r10 = 0;
    104    state->guest_r11 = 0;
    105    state->guest_r12 = 0;
    106    state->guest_r13 = 0;
    107    state->guest_r14 = 0;
    108    state->guest_r15 = 0;
    109 
    110 /*------------------------------------------------------------*/
    111 /*--- Initialise S390 miscellaneous registers              ---*/
    112 /*------------------------------------------------------------*/
    113 
    114    state->guest_counter = 0;
    115    state->guest_fpc = 0;
    116    state->guest_IA = 0;
    117 
    118 /*------------------------------------------------------------*/
    119 /*--- Initialise S390 pseudo registers                     ---*/
    120 /*------------------------------------------------------------*/
    121 
    122    state->guest_SYSNO = 0;
    123 
    124 /*------------------------------------------------------------*/
    125 /*--- Initialise generic pseudo registers                  ---*/
    126 /*------------------------------------------------------------*/
    127 
    128    state->guest_NRADDR = 0;
    129    state->guest_TISTART = 0;
    130    state->guest_TILEN = 0;
    131    state->guest_IP_AT_SYSCALL = 0;
    132    state->guest_EMWARN = EmWarn_NONE;
    133    state->host_EvC_COUNTER = 0;
    134    state->host_EvC_FAILADDR = 0;
    135 
    136 /*------------------------------------------------------------*/
    137 /*--- Initialise thunk                                     ---*/
    138 /*------------------------------------------------------------*/
    139 
    140    state->guest_CC_OP = 0;
    141    state->guest_CC_DEP1 = 0;
    142    state->guest_CC_DEP2 = 0;
    143    state->guest_CC_NDEP = 0;
    144 
    145    __builtin_memset(state->padding, 0x0, sizeof(state->padding));
    146 }
    147 
    148 
    149 /* Figure out if any part of the guest state contained in minoff
    150    .. maxoff requires precise memory exceptions.  If in doubt return
    151    True (but this is generates significantly slower code).  */
    152 Bool
    153 guest_s390x_state_requires_precise_mem_exns(Int minoff, Int maxoff)
    154 {
    155    Int lr_min = S390X_GUEST_OFFSET(guest_LR);
    156    Int lr_max = lr_min + 8 - 1;
    157    Int sp_min = S390X_GUEST_OFFSET(guest_SP);
    158    Int sp_max = sp_min + 8 - 1;
    159    Int fp_min = S390X_GUEST_OFFSET(guest_FP);
    160    Int fp_max = fp_min + 8 - 1;
    161    Int ia_min = S390X_GUEST_OFFSET(guest_IA);
    162    Int ia_max = ia_min + 8 - 1;
    163 
    164    if (maxoff < lr_min || minoff > lr_max) {
    165       /* No overlap with LR */
    166    } else {
    167       return True;
    168    }
    169 
    170    if (maxoff < sp_min || minoff > sp_max) {
    171       /* No overlap with SP */
    172    } else {
    173       return True;
    174    }
    175 
    176    if (maxoff < fp_min || minoff > fp_max) {
    177       /* No overlap with FP */
    178    } else {
    179       return True;
    180    }
    181 
    182    if (maxoff < ia_min || minoff > ia_max) {
    183       /* No overlap with IA */
    184    } else {
    185       return True;
    186    }
    187 
    188    return False;
    189 }
    190 
    191 
    192 #define ALWAYSDEFD(field)                             \
    193     { S390X_GUEST_OFFSET(field),            \
    194       (sizeof ((VexGuestS390XState*)0)->field) }
    195 
    196 VexGuestLayout s390xGuest_layout = {
    197 
    198    /* Total size of the guest state, in bytes. */
    199    .total_sizeB = sizeof(VexGuestS390XState),
    200 
    201    /* Describe the stack pointer. */
    202    .offset_SP = S390X_GUEST_OFFSET(guest_SP),
    203    .sizeof_SP = 8,
    204 
    205    /* Describe the frame pointer. */
    206    .offset_FP = S390X_GUEST_OFFSET(guest_FP),
    207    .sizeof_FP = 8,
    208 
    209    /* Describe the instruction pointer. */
    210    .offset_IP = S390X_GUEST_OFFSET(guest_IA),
    211    .sizeof_IP = 8,
    212 
    213    /* Describe any sections to be regarded by Memcheck as
    214       'always-defined'. */
    215    .n_alwaysDefd = 9,
    216 
    217    /* Flags thunk: OP and NDEP are always defined, whereas DEP1
    218       and DEP2 have to be tracked.  See detailed comment in
    219       gdefs.h on meaning of thunk fields. */
    220    .alwaysDefd = {
    221       /*  0 */ ALWAYSDEFD(guest_CC_OP),     /* generic */
    222       /*  1 */ ALWAYSDEFD(guest_CC_NDEP),   /* generic */
    223       /*  2 */ ALWAYSDEFD(guest_EMWARN),    /* generic */
    224       /*  3 */ ALWAYSDEFD(guest_TISTART),   /* generic */
    225       /*  4 */ ALWAYSDEFD(guest_TILEN),     /* generic */
    226       /*  5 */ ALWAYSDEFD(guest_IP_AT_SYSCALL), /* generic */
    227       /*  6 */ ALWAYSDEFD(guest_IA),        /* control reg */
    228       /*  7 */ ALWAYSDEFD(guest_fpc),       /* control reg */
    229       /*  8 */ ALWAYSDEFD(guest_counter),   /* internal usage register */
    230    }
    231 };
    232 
    233 /*------------------------------------------------------------*/
    234 /*--- Dirty helper for EXecute                             ---*/
    235 /*------------------------------------------------------------*/
    236 void
    237 s390x_dirtyhelper_EX(ULong torun)
    238 {
    239    last_execute_target = torun;
    240 }
    241 
    242 
    243 /*------------------------------------------------------------*/
    244 /*--- Dirty helper for Clock instructions                  ---*/
    245 /*------------------------------------------------------------*/
    246 #if defined(VGA_s390x)
    247 ULong
    248 s390x_dirtyhelper_STCK(ULong *addr)
    249 {
    250    int cc;
    251 
    252    asm volatile("stck %0\n"
    253                 "ipm %1\n"
    254                 "srl %1,28\n"
    255                 : "+Q" (*addr), "=d" (cc) : : "cc");
    256    return cc;
    257 }
    258 
    259 ULong
    260 s390x_dirtyhelper_STCKE(ULong *addr)
    261 {
    262    int cc;
    263 
    264    asm volatile("stcke %0\n"
    265                 "ipm %1\n"
    266                 "srl %1,28\n"
    267                 : "+Q" (*addr), "=d" (cc) : : "cc");
    268    return cc;
    269 }
    270 
    271 ULong s390x_dirtyhelper_STCKF(ULong *addr)
    272 {
    273    int cc;
    274 
    275    asm volatile(".insn s,0xb27c0000,%0\n"
    276                 "ipm %1\n"
    277                 "srl %1,28\n"
    278                 : "+Q" (*addr), "=d" (cc) : : "cc");
    279    return cc;
    280 }
    281 #else
    282 ULong s390x_dirtyhelper_STCK(ULong *addr)  {return 3;}
    283 ULong s390x_dirtyhelper_STCKF(ULong *addr) {return 3;}
    284 ULong s390x_dirtyhelper_STCKE(ULong *addr) {return 3;}
    285 #endif /* VGA_s390x */
    286 
    287 /*------------------------------------------------------------*/
    288 /*--- Dirty helper for Store Facility instruction          ---*/
    289 /*------------------------------------------------------------*/
    290 #if defined(VGA_s390x)
    291 ULong
    292 s390x_dirtyhelper_STFLE(VexGuestS390XState *guest_state, ULong *addr)
    293 {
    294    ULong hoststfle[S390_NUM_FACILITY_DW], cc, num_dw, i;
    295    register ULong reg0 asm("0") = guest_state->guest_r0 & 0xF;  /* r0[56:63] */
    296 
    297    /* We cannot store more than S390_NUM_FACILITY_DW
    298       (and it makes not much sense to do so anyhow) */
    299    if (reg0 > S390_NUM_FACILITY_DW - 1)
    300       reg0 = S390_NUM_FACILITY_DW - 1;
    301 
    302    num_dw = reg0 + 1;  /* number of double words written */
    303 
    304    asm volatile(" .insn s,0xb2b00000,%0\n"   /* stfle */
    305                 "ipm    %2\n"
    306                 "srl    %2,28\n"
    307                 : "=m" (hoststfle), "+d"(reg0), "=d"(cc) : : "cc", "memory");
    308 
    309    /* Update guest register 0  with what STFLE set r0 to */
    310    guest_state->guest_r0 = reg0;
    311 
    312    for (i = 0; i < num_dw; ++i)
    313       addr[i] = hoststfle[i];
    314 
    315    return cc;
    316 }
    317 
    318 #else
    319 
    320 ULong
    321 s390x_dirtyhelper_STFLE(VexGuestS390XState *guest_state, ULong *addr)
    322 {
    323    return 3;
    324 }
    325 #endif /* VGA_s390x */
    326 
    327 /*------------------------------------------------------------*/
    328 /*--- Dirty helper for the "convert unicode" insn family.  ---*/
    329 /*------------------------------------------------------------*/
    330 void
    331 s390x_dirtyhelper_CUxy(UChar *address, ULong data, ULong num_bytes)
    332 {
    333    UInt i;
    334 
    335    vassert(num_bytes >= 1 && num_bytes <= 4);
    336 
    337    /* Store the least significant NUM_BYTES bytes in DATA left to right
    338       at ADDRESS. */
    339    for (i = 1; i <= num_bytes; ++i) {
    340       address[num_bytes - i] = data & 0xff;
    341       data >>= 8;
    342    }
    343 }
    344 
    345 
    346 /*------------------------------------------------------------*/
    347 /*--- Clean helper for CU21.                               ---*/
    348 /*------------------------------------------------------------*/
    349 
    350 /* The function performs a CU21 operation. It returns three things
    351    encoded in an ULong value:
    352    - the converted bytes (at most 4)
    353    - the number of converted bytes
    354    - an indication whether LOW_SURROGATE, if any, is invalid
    355 
    356    64      48                16           8                       0
    357     +-------+-----------------+-----------+-----------------------+
    358     |  0x0  | converted bytes | num_bytes | invalid_low_surrogate |
    359     +-------+-----------------+-----------+-----------------------+
    360 */
    361 ULong
    362 s390_do_cu21(UInt srcval, UInt low_surrogate)
    363 {
    364    ULong retval = 0;   // shut up gcc
    365    UInt b1, b2, b3, b4, num_bytes, invalid_low_surrogate = 0;
    366 
    367    srcval &= 0xffff;
    368 
    369    /* Determine the number of bytes in the converted value */
    370    if (srcval <= 0x007f)
    371       num_bytes = 1;
    372    else if (srcval >= 0x0080 && srcval <= 0x07ff)
    373       num_bytes = 2;
    374    else if ((srcval >= 0x0800 && srcval <= 0xd7ff) ||
    375             (srcval >= 0xdc00 && srcval <= 0xffff))
    376       num_bytes = 3;
    377    else
    378       num_bytes = 4;
    379 
    380    /* Determine UTF-8 bytes according to calculated num_bytes */
    381    switch (num_bytes){
    382    case 1:
    383       retval = srcval;
    384       break;
    385 
    386    case 2:
    387       /* order of bytes left to right: b1, b2 */
    388       b1  = 0xc0;
    389       b1 |= srcval >> 6;
    390 
    391       b2  = 0x80;
    392       b2 |= srcval & 0x3f;
    393 
    394       retval = (b1 << 8) | b2;
    395       break;
    396 
    397    case 3:
    398       /* order of bytes left to right: b1, b2, b3 */
    399       b1  = 0xe0;
    400       b1 |= srcval >> 12;
    401 
    402       b2  = 0x80;
    403       b2 |= (srcval >> 6) & 0x3f;
    404 
    405       b3  = 0x80;
    406       b3 |= srcval & 0x3f;
    407 
    408       retval = (b1 << 16) | (b2 << 8) | b3;
    409       break;
    410 
    411    case 4: {
    412       /* order of bytes left to right: b1, b2, b3, b4 */
    413       UInt high_surrogate = srcval;
    414       UInt uvwxy = ((high_surrogate >> 6) & 0xf) + 1;   // abcd + 1
    415 
    416       b1  = 0xf0;
    417       b1 |= uvwxy >> 2;     // uvw
    418 
    419       b2  = 0x80;
    420       b2 |= (uvwxy & 0x3) << 4;           // xy
    421       b2 |= (high_surrogate >> 2) & 0xf;  // efgh
    422 
    423       b3  = 0x80;
    424       b3 |= (high_surrogate & 0x3) << 4;   // ij
    425       b3 |= (low_surrogate >> 6) & 0xf;    // klmn
    426 
    427       b4  = 0x80;
    428       b4 |= low_surrogate & 0x3f;
    429 
    430       retval = (b1 << 24) | (b2 << 16) | (b3 << 8) | b4;
    431 
    432       invalid_low_surrogate = (low_surrogate & 0xfc00) != 0xdc00;
    433       break;
    434    }
    435    }
    436 
    437    /* At this point RETVAL contains the converted bytes.
    438       Build up the final return value. */
    439    return (retval << 16) | (num_bytes << 8) | invalid_low_surrogate;
    440 }
    441 
    442 
    443 /*------------------------------------------------------------*/
    444 /*--- Clean helper for CU24.                               ---*/
    445 /*------------------------------------------------------------*/
    446 
    447 /* The function performs a CU24 operation. It returns two things
    448    encoded in an ULong value:
    449    - the 4 converted bytes
    450    - an indication whether LOW_SURROGATE, if any, is invalid
    451 
    452    64     40                 8                       0
    453     +------------------------+-----------------------+
    454     |  0x0 | converted bytes | invalid_low_surrogate |
    455     +------------------------+-----------------------+
    456 */
    457 ULong
    458 s390_do_cu24(UInt srcval, UInt low_surrogate)
    459 {
    460    ULong retval;
    461    UInt invalid_low_surrogate = 0;
    462 
    463    srcval &= 0xffff;
    464 
    465    if ((srcval >= 0x0000 && srcval <= 0xd7ff) ||
    466        (srcval >= 0xdc00 && srcval <= 0xffff)) {
    467       retval = srcval;
    468    } else {
    469       /* D800 - DBFF */
    470       UInt high_surrogate = srcval;
    471       UInt uvwxy  = ((high_surrogate >> 6) & 0xf) + 1;   // abcd + 1
    472       UInt efghij = high_surrogate & 0x3f;
    473       UInt klmnoprst = low_surrogate & 0x3ff;
    474 
    475       retval = (uvwxy << 16) | (efghij << 10) | klmnoprst;
    476 
    477       invalid_low_surrogate = (low_surrogate & 0xfc00) != 0xdc00;
    478    }
    479 
    480    /* At this point RETVAL contains the converted bytes.
    481       Build up the final return value. */
    482    return (retval << 8) | invalid_low_surrogate;
    483 }
    484 
    485 
    486 /*------------------------------------------------------------*/
    487 /*--- Clean helper for CU42.                               ---*/
    488 /*------------------------------------------------------------*/
    489 
    490 /* The function performs a CU42 operation. It returns three things
    491    encoded in an ULong value:
    492    - the converted bytes (at most 4)
    493    - the number of converted bytes (2 or 4; 0 if invalid character)
    494    - an indication whether the UTF-32 character is invalid
    495 
    496    64      48                16           8                   0
    497     +-------+-----------------+-----------+-------------------+
    498     |  0x0  | converted bytes | num_bytes | invalid_character |
    499     +-------+-----------------+-----------+-------------------+
    500 */
    501 ULong
    502 s390_do_cu42(UInt srcval)
    503 {
    504    ULong retval;
    505    UInt num_bytes, invalid_character = 0;
    506 
    507    if ((srcval >= 0x0000 && srcval <= 0xd7ff) ||
    508        (srcval >= 0xdc00 && srcval <= 0xffff)) {
    509       retval = srcval;
    510       num_bytes = 2;
    511    } else if (srcval >= 0x00010000 && srcval <= 0x0010FFFF) {
    512       UInt uvwxy  = srcval >> 16;
    513       UInt abcd   = (uvwxy - 1) & 0xf;
    514       UInt efghij = (srcval >> 10) & 0x3f;
    515 
    516       UInt high_surrogate = (0xd8 << 8) | (abcd << 6) | efghij;
    517       UInt low_surrogate  = (0xdc << 8) | (srcval & 0x3ff);
    518 
    519       retval = (high_surrogate << 16) | low_surrogate;
    520       num_bytes = 4;
    521    } else {
    522       /* D800 - DBFF or 00110000 - FFFFFFFF */
    523       invalid_character = 1;
    524       retval = num_bytes = 0;   /* does not matter; not used */
    525    }
    526 
    527    /* At this point RETVAL contains the converted bytes.
    528       Build up the final return value. */
    529    return (retval << 16) | (num_bytes << 8) | invalid_character;
    530 }
    531 
    532 
    533 /*------------------------------------------------------------*/
    534 /*--- Clean helper for CU41.                               ---*/
    535 /*------------------------------------------------------------*/
    536 
    537 /* The function performs a CU41 operation. It returns three things
    538    encoded in an ULong value:
    539    - the converted bytes (at most 4)
    540    - the number of converted bytes (1, 2, 3, or 4; 0 if invalid character)
    541    - an indication whether the UTF-32 character is invalid
    542 
    543    64      48                16           8                   0
    544     +-------+-----------------+-----------+-------------------+
    545     |  0x0  | converted bytes | num_bytes | invalid_character |
    546     +-------+-----------------+-----------+-------------------+
    547 */
    548 ULong
    549 s390_do_cu41(UInt srcval)
    550 {
    551    ULong retval;
    552    UInt num_bytes, invalid_character = 0;
    553 
    554    if (srcval <= 0x7f) {
    555       retval = srcval;
    556       num_bytes = 1;
    557    } else if (srcval >= 0x80 && srcval <= 0x7ff) {
    558       UInt fghij  = srcval >> 6;
    559       UInt klmnop = srcval & 0x3f;
    560       UInt byte1  = (0xc0 | fghij);
    561       UInt byte2  = (0x80 | klmnop);
    562 
    563       retval = (byte1 << 8) | byte2;
    564       num_bytes = 2;
    565    } else if ((srcval >= 0x800  && srcval <= 0xd7ff) ||
    566               (srcval >= 0xdc00 && srcval <= 0xffff)) {
    567       UInt abcd   = srcval >> 12;
    568       UInt efghij = (srcval >> 6) & 0x3f;
    569       UInt klmnop = srcval & 0x3f;
    570       UInt byte1  = 0xe0 | abcd;
    571       UInt byte2  = 0x80 | efghij;
    572       UInt byte3  = 0x80 | klmnop;
    573 
    574       retval = (byte1 << 16) | (byte2 << 8) | byte3;
    575       num_bytes = 3;
    576    } else if (srcval >= 0x10000 && srcval <= 0x10ffff) {
    577       UInt uvw    = (srcval >> 18) & 0x7;
    578       UInt xy     = (srcval >> 16) & 0x3;
    579       UInt efgh   = (srcval >> 12) & 0xf;
    580       UInt ijklmn = (srcval >>  6) & 0x3f;
    581       UInt opqrst = srcval & 0x3f;
    582       UInt byte1  = 0xf0 | uvw;
    583       UInt byte2  = 0x80 | (xy << 4) | efgh;
    584       UInt byte3  = 0x80 | ijklmn;
    585       UInt byte4  = 0x80 | opqrst;
    586 
    587       retval = (byte1 << 24) | (byte2 << 16) | (byte3 << 8) | byte4;
    588       num_bytes = 4;
    589    } else {
    590       /* d800 ... dbff or 00110000 ... ffffffff */
    591       invalid_character = 1;
    592 
    593       retval = 0;
    594       num_bytes = 0;
    595    }
    596 
    597    /* At this point RETVAL contains the converted bytes.
    598       Build up the final return value. */
    599    return (retval << 16) | (num_bytes << 8) | invalid_character;
    600 }
    601 
    602 
    603 /*------------------------------------------------------------*/
    604 /*--- Clean helpers for CU12.                              ---*/
    605 /*------------------------------------------------------------*/
    606 
    607 /* The function looks at the first byte of an UTF-8 character and returns
    608    two things encoded in an ULong value:
    609 
    610    - the number of bytes that need to be read
    611    - an indication whether the UTF-8 character is invalid
    612 
    613    64      16           8                   0
    614     +-------------------+-------------------+
    615     |  0x0  | num_bytes | invalid_character |
    616     +-------+-----------+-------------------+
    617 */
    618 ULong
    619 s390_do_cu12_cu14_helper1(UInt byte, UInt etf3_and_m3_is_1)
    620 {
    621    vassert(byte <= 0xff);
    622 
    623    /* Check whether the character is invalid */
    624    if (byte >= 0x80 && byte <= 0xbf) return 1;
    625    if (byte >= 0xf8) return 1;
    626 
    627    if (etf3_and_m3_is_1) {
    628       if (byte == 0xc0 || byte == 0xc1) return 1;
    629       if (byte >= 0xf5 && byte <= 0xf7) return 1;
    630    }
    631 
    632    /* Character is valid */
    633    if (byte <= 0x7f) return 1 << 8;   // 1 byte
    634    if (byte <= 0xdf) return 2 << 8;   // 2 bytes
    635    if (byte <= 0xef) return 3 << 8;   // 3 bytes
    636 
    637    return 4 << 8;  // 4 bytes
    638 }
    639 
    640 /* The function performs a CU12 or CU14 operation. BYTE1, BYTE2, etc are the
    641    bytes as read from the input stream, left to right. BYTE1 is a valid
    642    byte. The function returns three things encoded in an ULong value:
    643 
    644    - the converted bytes
    645    - the number of converted bytes (2 or 4; 0 if invalid character)
    646    - an indication whether the UTF-16 character is invalid
    647 
    648    64      48                16           8                   0
    649     +-------+-----------------+-----------+-------------------+
    650     |  0x0  | converted bytes | num_bytes | invalid_character |
    651     +-------+-----------------+-----------+-------------------+
    652 */
    653 static ULong
    654 s390_do_cu12_cu14_helper2(UInt byte1, UInt byte2, UInt byte3, UInt byte4,
    655                           ULong stuff, Bool is_cu12)
    656 {
    657    UInt num_src_bytes = stuff >> 1, etf3_and_m3_is_1 = stuff & 0x1;
    658    UInt num_bytes = 0, invalid_character = 0;
    659    ULong retval = 0;
    660 
    661    vassert(num_src_bytes <= 4);
    662 
    663    switch (num_src_bytes) {
    664    case 1:
    665       num_bytes = 2;
    666       retval = byte1;
    667       break;
    668 
    669    case 2: {
    670       /* Test validity */
    671       if (etf3_and_m3_is_1) {
    672          if (byte2 < 0x80 || byte2 > 0xbf) {
    673             invalid_character = 1;
    674             break;
    675          }
    676       }
    677 
    678       /* OK */
    679       UInt fghij  = byte1 & 0x1f;
    680       UInt klmnop = byte2 & 0x3f;
    681 
    682       num_bytes = 2;
    683       retval = (fghij << 6) | klmnop;
    684       break;
    685    }
    686 
    687    case 3: {
    688       /* Test validity */
    689       if (etf3_and_m3_is_1) {
    690          if (byte1 == 0xe0) {
    691             if ((byte2 < 0xa0 || byte2 > 0xbf) ||
    692                 (byte3 < 0x80 || byte3 > 0xbf)) {
    693                invalid_character = 1;
    694                break;
    695             }
    696          }
    697          if ((byte1 >= 0xe1 && byte1 <= 0xec) ||
    698              byte1 == 0xee || byte1 == 0xef) {
    699             if ((byte2 < 0x80 || byte2 > 0xbf) ||
    700                 (byte3 < 0x80 || byte3 > 0xbf)) {
    701                invalid_character = 1;
    702                break;
    703             }
    704          }
    705          if (byte1 == 0xed) {
    706             if ((byte2 < 0x80 || byte2 > 0x9f) ||
    707                 (byte3 < 0x80 || byte3 > 0xbf)) {
    708                invalid_character = 1;
    709                break;
    710             }
    711          }
    712       }
    713 
    714       /* OK */
    715       UInt abcd   = byte1 & 0xf;
    716       UInt efghij = byte2 & 0x3f;
    717       UInt klmnop = byte3 & 0x3f;
    718 
    719       num_bytes = 2;
    720       retval = (abcd << 12) | (efghij << 6) | klmnop;
    721       break;
    722    }
    723 
    724    case 4: {
    725       /* Test validity */
    726       if (etf3_and_m3_is_1) {
    727          if (byte1 == 0xf0) {
    728             if ((byte2 < 0x90 || byte2 > 0xbf) ||
    729                 (byte3 < 0x80 || byte3 > 0xbf) ||
    730                 (byte4 < 0x80 || byte4 > 0xbf)) {
    731                invalid_character = 1;
    732                break;
    733             }
    734          }
    735          if (byte1 == 0xf1 || byte1 == 0xf2 || byte1 == 0xf3) {
    736             if ((byte2 < 0x80 || byte2 > 0xbf) ||
    737                 (byte3 < 0x80 || byte3 > 0xbf) ||
    738                 (byte4 < 0x80 || byte4 > 0xbf)) {
    739                invalid_character = 1;
    740                break;
    741             }
    742          }
    743          if (byte1 == 0xf4) {
    744             if ((byte2 < 0x80 || byte2 > 0x8f) ||
    745                 (byte3 < 0x80 || byte3 > 0xbf) ||
    746                 (byte4 < 0x80 || byte4 > 0xbf)) {
    747                invalid_character = 1;
    748                break;
    749             }
    750          }
    751       }
    752 
    753       /* OK */
    754       UInt uvw    = byte1 & 0x7;
    755       UInt xy     = (byte2 >> 4) & 0x3;
    756       UInt uvwxy  = (uvw << 2) | xy;
    757       UInt efgh   = byte2 & 0xf;
    758       UInt ij     = (byte3 >> 4) & 0x3;
    759       UInt klmn   = byte3 & 0xf;
    760       UInt opqrst = byte4 & 0x3f;
    761 
    762       if (is_cu12) {
    763          UInt abcd = (uvwxy - 1) & 0xf;
    764          UInt high_surrogate = (0xd8 << 8) | (abcd << 6) | (efgh << 2) | ij;
    765          UInt low_surrogate  = (0xdc << 8) | (klmn << 6) | opqrst;
    766 
    767          num_bytes = 4;
    768          retval = (high_surrogate << 16) | low_surrogate;
    769       } else {
    770          num_bytes = 4;
    771          retval =
    772             (uvwxy << 16) | (efgh << 12) | (ij << 10) | (klmn << 6) | opqrst;
    773       }
    774       break;
    775    }
    776    }
    777 
    778    if (! is_cu12) num_bytes = 4;   // for CU14, by definition
    779 
    780    /* At this point RETVAL contains the converted bytes.
    781       Build up the final return value. */
    782    return (retval << 16) | (num_bytes << 8) | invalid_character;
    783 }
    784 
    785 ULong
    786 s390_do_cu12_helper2(UInt byte1, UInt byte2, UInt byte3, UInt byte4,
    787                      ULong stuff)
    788 {
    789    return s390_do_cu12_cu14_helper2(byte1, byte2, byte3, byte4, stuff,
    790                                     /* is_cu12 = */ 1);
    791 }
    792 
    793 ULong
    794 s390_do_cu14_helper2(UInt byte1, UInt byte2, UInt byte3, UInt byte4,
    795                      ULong stuff)
    796 {
    797    return s390_do_cu12_cu14_helper2(byte1, byte2, byte3, byte4, stuff,
    798                                     /* is_cu12 = */ 0);
    799 }
    800 
    801 
    802 /*------------------------------------------------------------*/
    803 /*--- Clean helper for "convert to binary".                ---*/
    804 /*------------------------------------------------------------*/
    805 #if defined(VGA_s390x)
    806 UInt
    807 s390_do_cvb(ULong decimal)
    808 {
    809    UInt binary;
    810 
    811    __asm__ volatile (
    812         "cvb %[result],%[input]\n\t"
    813           : [result] "=d"(binary)
    814           : [input] "m"(decimal)
    815    );
    816 
    817    return binary;
    818 }
    819 
    820 #else
    821 UInt s390_do_cvb(ULong decimal) { return 0; }
    822 #endif
    823 
    824 
    825 /*------------------------------------------------------------*/
    826 /*--- Clean helper for "convert to decimal".                ---*/
    827 /*------------------------------------------------------------*/
    828 #if defined(VGA_s390x)
    829 ULong
    830 s390_do_cvd(ULong binary_in)
    831 {
    832    UInt binary = binary_in & 0xffffffffULL;
    833    ULong decimal;
    834 
    835    __asm__ volatile (
    836         "cvd %[input],%[result]\n\t"
    837           : [result] "=m"(decimal)
    838           : [input] "d"(binary)
    839    );
    840 
    841    return decimal;
    842 }
    843 
    844 #else
    845 ULong s390_do_cvd(ULong binary) { return 0; }
    846 #endif
    847 
    848 
    849 /*------------------------------------------------------------*/
    850 /*--- Helper for condition code.                           ---*/
    851 /*------------------------------------------------------------*/
    852 
    853 #define S390_CC_FOR_BINARY(opcode,cc_dep1,cc_dep2) \
    854 ({ \
    855    __asm__ volatile ( \
    856         opcode " %[op1],%[op2]\n\t" \
    857         "ipm %[psw]\n\t"           : [psw] "=d"(psw), [op1] "+d"(cc_dep1) \
    858                                    : [op2] "d"(cc_dep2) \
    859                                    : "cc");\
    860    psw >> 28;   /* cc */ \
    861 })
    862 
    863 #define S390_CC_FOR_TERNARY_SUBB(opcode,cc_dep1,cc_dep2,cc_ndep) \
    864 ({ \
    865    /* Recover the original DEP2 value. See comment near s390_cc_thunk_put3 \
    866       for rationale. */ \
    867    cc_dep2 = cc_dep2 ^ cc_ndep; \
    868    __asm__ volatile ( \
    869 	"lghi 0,1\n\t" \
    870 	"sr 0,%[op3]\n\t" /* borrow to cc */ \
    871         opcode " %[op1],%[op2]\n\t" /* then redo the op */\
    872         "ipm %[psw]\n\t"           : [psw] "=d"(psw), [op1] "+&d"(cc_dep1) \
    873                                    : [op2] "d"(cc_dep2), [op3] "d"(cc_ndep) \
    874                                    : "0", "cc");\
    875    psw >> 28;   /* cc */ \
    876 })
    877 
    878 #define S390_CC_FOR_TERNARY_ADDC(opcode,cc_dep1,cc_dep2,cc_ndep) \
    879 ({ \
    880    /* Recover the original DEP2 value. See comment near s390_cc_thunk_put3 \
    881       for rationale. */ \
    882    cc_dep2 = cc_dep2 ^ cc_ndep; \
    883    __asm__ volatile ( \
    884 	"lgfr 0,%[op3]\n\t" /* first load cc_ndep */ \
    885 	"aghi 0,0\n\t" /* and convert it into a cc */ \
    886         opcode " %[op1],%[op2]\n\t" /* then redo the op */\
    887         "ipm %[psw]\n\t"           : [psw] "=d"(psw), [op1] "+&d"(cc_dep1) \
    888                                    : [op2] "d"(cc_dep2), [op3] "d"(cc_ndep) \
    889                                    : "0", "cc");\
    890    psw >> 28;   /* cc */ \
    891 })
    892 
    893 
    894 #define S390_CC_FOR_BFP_RESULT(opcode,cc_dep1) \
    895 ({ \
    896    __asm__ volatile ( \
    897         opcode " 0,%[op]\n\t" \
    898         "ipm %[psw]\n\t"           : [psw] "=d"(psw) \
    899                                    : [op]  "f"(cc_dep1) \
    900                                    : "cc", "f0");\
    901    psw >> 28;   /* cc */ \
    902 })
    903 
    904 #define S390_CC_FOR_BFP128_RESULT(hi,lo) \
    905 ({ \
    906    __asm__ volatile ( \
    907         "ldr   4,%[high]\n\t" \
    908         "ldr   6,%[low]\n\t" \
    909         "ltxbr 0,4\n\t" \
    910         "ipm %[psw]\n\t"           : [psw] "=d"(psw) \
    911                                    : [high] "f"(hi), [low] "f"(lo) \
    912                                    : "cc", "f0", "f2", "f4", "f6");\
    913    psw >> 28;   /* cc */ \
    914 })
    915 
    916 #define S390_CC_FOR_BFP_CONVERT(opcode,cc_dep1) \
    917 ({ \
    918    __asm__ volatile ( \
    919         opcode " 0,0,%[op]\n\t" \
    920         "ipm %[psw]\n\t"           : [psw] "=d"(psw) \
    921                                    : [op]  "f"(cc_dep1) \
    922                                    : "cc", "r0");\
    923    psw >> 28;   /* cc */ \
    924 })
    925 
    926 #define S390_CC_FOR_BFP128_CONVERT(opcode,hi,lo) \
    927 ({ \
    928    __asm__ volatile ( \
    929         "ldr   4,%[high]\n\t" \
    930         "ldr   6,%[low]\n\t" \
    931         opcode " 0,0,4\n\t" \
    932         "ipm %[psw]\n\t"           : [psw] "=d"(psw) \
    933                                    : [high] "f"(hi), [low] "f"(lo) \
    934                                    : "cc", "r0", "f4", "f6");\
    935    psw >> 28;   /* cc */ \
    936 })
    937 
    938 #define S390_CC_FOR_BFP_TDC(opcode,cc_dep1,cc_dep2) \
    939 ({ \
    940    __asm__ volatile ( \
    941         opcode " %[value],0(%[class])\n\t" \
    942         "ipm %[psw]\n\t"           : [psw] "=d"(psw) \
    943                                    : [value] "f"(cc_dep1), \
    944                                      [class] "a"(cc_dep2)  \
    945                                    : "cc");\
    946    psw >> 28;   /* cc */ \
    947 })
    948 
    949 #define S390_CC_FOR_BFP128_TDC(cc_dep1,cc_dep2,cc_ndep) \
    950 ({ \
    951    /* Recover the original DEP2 value. See comment near s390_cc_thunk_put1f128Z \
    952       for rationale. */ \
    953    cc_dep2 = cc_dep2 ^ cc_ndep; \
    954    __asm__ volatile ( \
    955         "ldr  4,%[high]\n\t" \
    956         "ldr  6,%[low]\n\t" \
    957         "tcxb 4,0(%[class])\n\t" \
    958         "ipm  %[psw]\n\t"          : [psw] "=d"(psw) \
    959                                    : [high] "f"(cc_dep1), [low] "f"(cc_dep2), \
    960                                      [class] "a"(cc_ndep)  \
    961                                    : "cc", "f4", "f6");\
    962    psw >> 28;   /* cc */ \
    963 })
    964 
    965 
    966 /* Return the value of the condition code from the supplied thunk parameters.
    967    This is not the value of the PSW. It is the value of the 2 CC bits within
    968    the PSW. The returned value is thusly in the interval [0:3]. */
    969 UInt
    970 s390_calculate_cc(ULong cc_op, ULong cc_dep1, ULong cc_dep2, ULong cc_ndep)
    971 {
    972 #if defined(VGA_s390x)
    973    UInt psw;
    974 
    975    switch (cc_op) {
    976 
    977    case S390_CC_OP_BITWISE:
    978       return S390_CC_FOR_BINARY("ogr", cc_dep1, (ULong)0);
    979 
    980    case S390_CC_OP_SIGNED_COMPARE:
    981       return S390_CC_FOR_BINARY("cgr", cc_dep1, cc_dep2);
    982 
    983    case S390_CC_OP_UNSIGNED_COMPARE:
    984       return S390_CC_FOR_BINARY("clgr", cc_dep1, cc_dep2);
    985 
    986    case S390_CC_OP_SIGNED_ADD_64:
    987       return S390_CC_FOR_BINARY("agr", cc_dep1, cc_dep2);
    988 
    989    case S390_CC_OP_SIGNED_ADD_32:
    990       return S390_CC_FOR_BINARY("ar", cc_dep1, cc_dep2);
    991 
    992    case S390_CC_OP_SIGNED_SUB_64:
    993       return S390_CC_FOR_BINARY("sgr", cc_dep1, cc_dep2);
    994 
    995    case S390_CC_OP_SIGNED_SUB_32:
    996       return S390_CC_FOR_BINARY("sr", cc_dep1, cc_dep2);
    997 
    998    case S390_CC_OP_UNSIGNED_ADD_64:
    999       return S390_CC_FOR_BINARY("algr", cc_dep1, cc_dep2);
   1000 
   1001    case S390_CC_OP_UNSIGNED_ADD_32:
   1002       return S390_CC_FOR_BINARY("alr", cc_dep1, cc_dep2);
   1003 
   1004    case S390_CC_OP_UNSIGNED_ADDC_64:
   1005       return S390_CC_FOR_TERNARY_ADDC("alcgr", cc_dep1, cc_dep2, cc_ndep);
   1006 
   1007    case S390_CC_OP_UNSIGNED_ADDC_32:
   1008       return S390_CC_FOR_TERNARY_ADDC("alcr", cc_dep1, cc_dep2, cc_ndep);
   1009 
   1010    case S390_CC_OP_UNSIGNED_SUB_64:
   1011       return S390_CC_FOR_BINARY("slgr", cc_dep1, cc_dep2);
   1012 
   1013    case S390_CC_OP_UNSIGNED_SUB_32:
   1014       return S390_CC_FOR_BINARY("slr", cc_dep1, cc_dep2);
   1015 
   1016    case S390_CC_OP_UNSIGNED_SUBB_64:
   1017       return S390_CC_FOR_TERNARY_SUBB("slbgr", cc_dep1, cc_dep2, cc_ndep);
   1018 
   1019    case S390_CC_OP_UNSIGNED_SUBB_32:
   1020       return S390_CC_FOR_TERNARY_SUBB("slbr", cc_dep1, cc_dep2, cc_ndep);
   1021 
   1022    case S390_CC_OP_LOAD_AND_TEST:
   1023       /* Like signed comparison with 0 */
   1024       return S390_CC_FOR_BINARY("cgr", cc_dep1, (Long)0);
   1025 
   1026    case S390_CC_OP_LOAD_POSITIVE_32:
   1027       __asm__ volatile (
   1028            "lpr  %[result],%[op]\n\t"
   1029            "ipm  %[psw]\n\t"         : [psw] "=d"(psw), [result] "=d"(cc_dep1)
   1030                                      : [op] "d"(cc_dep1)
   1031                                      : "cc");
   1032       return psw >> 28;   /* cc */
   1033 
   1034    case S390_CC_OP_LOAD_POSITIVE_64:
   1035       __asm__ volatile (
   1036            "lpgr %[result],%[op]\n\t"
   1037            "ipm  %[psw]\n\t"         : [psw] "=d"(psw), [result] "=d"(cc_dep1)
   1038                                      : [op] "d"(cc_dep1)
   1039                                      : "cc");
   1040       return psw >> 28;   /* cc */
   1041 
   1042    case S390_CC_OP_TEST_UNDER_MASK_8: {
   1043       UChar value  = cc_dep1;
   1044       UChar mask   = cc_dep2;
   1045 
   1046       __asm__ volatile (
   1047            "bras %%r2,1f\n\t"             /* %r2 = address of next insn */
   1048            "tm %[value],0\n\t"            /* this is skipped, then EXecuted */
   1049            "1: ex %[mask],0(%%r2)\n\t"    /* EXecute TM after modifying mask */
   1050            "ipm %[psw]\n\t"             : [psw] "=d"(psw)
   1051                                         : [value] "m"(value), [mask] "a"(mask)
   1052                                         : "r2", "cc");
   1053       return psw >> 28;   /* cc */
   1054    }
   1055 
   1056    case S390_CC_OP_TEST_UNDER_MASK_16: {
   1057       /* Create a TMLL insn with the mask as given by cc_dep2 */
   1058       UInt insn  = (0xA701 << 16) | cc_dep2;
   1059       UInt value = cc_dep1;
   1060 
   1061       __asm__ volatile (
   1062            "lr   1,%[value]\n\t"
   1063            "lhi  2,0x10\n\t"
   1064            "ex   2,%[insn]\n\t"
   1065            "ipm  %[psw]\n\t"       : [psw] "=d"(psw)
   1066                                    : [value] "d"(value), [insn] "m"(insn)
   1067                                    : "r1", "r2", "cc");
   1068       return psw >> 28;   /* cc */
   1069    }
   1070 
   1071    case S390_CC_OP_SHIFT_LEFT_32:
   1072       __asm__ volatile (
   1073            "sla  %[op],0(%[amount])\n\t"
   1074            "ipm  %[psw]\n\t"            : [psw] "=d"(psw), [op] "+d"(cc_dep1)
   1075                                         : [amount] "a"(cc_dep2)
   1076                                         : "cc");
   1077       return psw >> 28;   /* cc */
   1078 
   1079    case S390_CC_OP_SHIFT_LEFT_64: {
   1080       Int high = (Int)(cc_dep1 >> 32);
   1081       Int low  = (Int)(cc_dep1 & 0xFFFFFFFF);
   1082 
   1083       __asm__ volatile (
   1084            "lr   2,%[high]\n\t"
   1085            "lr   3,%[low]\n\t"
   1086            "slda 2,0(%[amount])\n\t"
   1087            "ipm %[psw]\n\t"             : [psw] "=d"(psw), [high] "+d"(high),
   1088                                           [low] "+d"(low)
   1089                                         : [amount] "a"(cc_dep2)
   1090                                         : "cc", "r2", "r3");
   1091       return psw >> 28;   /* cc */
   1092    }
   1093 
   1094    case S390_CC_OP_INSERT_CHAR_MASK_32: {
   1095       Int inserted = 0;
   1096       Int msb = 0;
   1097 
   1098       if (cc_dep2 & 1) {
   1099          inserted |= cc_dep1 & 0xff;
   1100          msb = 0x80;
   1101       }
   1102       if (cc_dep2 & 2) {
   1103          inserted |= cc_dep1 & 0xff00;
   1104          msb = 0x8000;
   1105       }
   1106       if (cc_dep2 & 4) {
   1107          inserted |= cc_dep1 & 0xff0000;
   1108          msb = 0x800000;
   1109       }
   1110       if (cc_dep2 & 8) {
   1111          inserted |= cc_dep1 & 0xff000000;
   1112          msb = 0x80000000;
   1113       }
   1114 
   1115       if (inserted & msb)  // MSB is 1
   1116          return 1;
   1117       if (inserted > 0)
   1118          return 2;
   1119       return 0;
   1120    }
   1121 
   1122    case S390_CC_OP_BFP_RESULT_32:
   1123       return S390_CC_FOR_BFP_RESULT("ltebr", cc_dep1);
   1124 
   1125    case S390_CC_OP_BFP_RESULT_64:
   1126       return S390_CC_FOR_BFP_RESULT("ltdbr", cc_dep1);
   1127 
   1128    case S390_CC_OP_BFP_RESULT_128:
   1129       return S390_CC_FOR_BFP128_RESULT(cc_dep1, cc_dep2);
   1130 
   1131    case S390_CC_OP_BFP_32_TO_INT_32:
   1132       return S390_CC_FOR_BFP_CONVERT("cfebr", cc_dep1);
   1133 
   1134    case S390_CC_OP_BFP_64_TO_INT_32:
   1135       return S390_CC_FOR_BFP_CONVERT("cfdbr", cc_dep1);
   1136 
   1137    case S390_CC_OP_BFP_128_TO_INT_32:
   1138       return S390_CC_FOR_BFP128_CONVERT("cfxbr", cc_dep1, cc_dep2);
   1139 
   1140    case S390_CC_OP_BFP_32_TO_INT_64:
   1141       return S390_CC_FOR_BFP_CONVERT("cgebr", cc_dep1);
   1142 
   1143    case S390_CC_OP_BFP_64_TO_INT_64:
   1144       return S390_CC_FOR_BFP_CONVERT("cgdbr", cc_dep1);
   1145 
   1146    case S390_CC_OP_BFP_128_TO_INT_64:
   1147       return S390_CC_FOR_BFP128_CONVERT("cgxbr", cc_dep1, cc_dep2);
   1148 
   1149    case S390_CC_OP_BFP_TDC_32:
   1150       return S390_CC_FOR_BFP_TDC("tceb", cc_dep1, cc_dep2);
   1151 
   1152    case S390_CC_OP_BFP_TDC_64:
   1153       return S390_CC_FOR_BFP_TDC("tcdb", cc_dep1, cc_dep2);
   1154 
   1155    case S390_CC_OP_BFP_TDC_128:
   1156       return S390_CC_FOR_BFP128_TDC(cc_dep1, cc_dep2, cc_ndep);
   1157 
   1158    case S390_CC_OP_SET:
   1159       return cc_dep1;
   1160 
   1161    default:
   1162       break;
   1163    }
   1164 #endif
   1165    vpanic("s390_calculate_cc");
   1166 }
   1167 
   1168 
   1169 /* Note that this does *not* return a Boolean value. The result needs to be
   1170    explicitly tested against zero. */
   1171 UInt
   1172 s390_calculate_cond(ULong mask, ULong op, ULong dep1, ULong dep2, ULong ndep)
   1173 {
   1174    UInt cc = s390_calculate_cc(op, dep1, dep2, ndep);
   1175 
   1176    return ((mask << cc) & 0x8);
   1177 }
   1178 
   1179 /*------------------------------------------------------------*/
   1180 /*--- spechelper for performance                           ---*/
   1181 /*------------------------------------------------------------*/
   1182 
   1183 
   1184 /* Convenience macros */
   1185 #define unop(op,a1) IRExpr_Unop((op),(a1))
   1186 #define binop(op,a1,a2) IRExpr_Binop((op),(a1),(a2))
   1187 #define mkU64(v) IRExpr_Const(IRConst_U64(v))
   1188 #define mkU32(v) IRExpr_Const(IRConst_U32(v))
   1189 #define mkU8(v)  IRExpr_Const(IRConst_U8(v))
   1190 
   1191 
   1192 static inline Bool
   1193 isC64(IRExpr *expr)
   1194 {
   1195    return expr->tag == Iex_Const && expr->Iex.Const.con->tag == Ico_U64;
   1196 }
   1197 
   1198 
   1199 /* The returned expression is NULL if no specialization was found. In that
   1200    case the helper function will be called. Otherwise, the expression has
   1201    type Ity_I32 and a Boolean value. */
   1202 IRExpr *
   1203 guest_s390x_spechelper(HChar *function_name, IRExpr **args,
   1204                        IRStmt **precedingStmts, Int n_precedingStmts)
   1205 {
   1206    UInt i, arity = 0;
   1207 
   1208    for (i = 0; args[i]; i++)
   1209       arity++;
   1210 
   1211 #  if 0
   1212    vex_printf("spec request:\n");
   1213    vex_printf("   %s  ", function_name);
   1214    for (i = 0; i < arity; i++) {
   1215       vex_printf("  ");
   1216       ppIRExpr(args[i]);
   1217    }
   1218    vex_printf("\n");
   1219 #  endif
   1220 
   1221    /* --------- Specialising "s390_calculate_cond" --------- */
   1222 
   1223    if (vex_streq(function_name, "s390_calculate_cond")) {
   1224       IRExpr *cond_expr, *cc_op_expr, *cc_dep1, *cc_dep2;
   1225       ULong cond, cc_op;
   1226 
   1227       vassert(arity == 5);
   1228 
   1229       cond_expr  = args[0];
   1230       cc_op_expr = args[1];
   1231 
   1232       /* The necessary requirement for all optimizations here is that the
   1233          condition and the cc_op are constant. So check that upfront. */
   1234       if (! isC64(cond_expr))  return NULL;
   1235       if (! isC64(cc_op_expr)) return NULL;
   1236 
   1237       cond    = cond_expr->Iex.Const.con->Ico.U64;
   1238       cc_op   = cc_op_expr->Iex.Const.con->Ico.U64;
   1239 
   1240       vassert(cond <= 15);
   1241 
   1242       /*
   1243         +------+---+---+---+---+
   1244         | cc   | 0 | 1 | 2 | 3 |
   1245         | cond | 8 | 4 | 2 | 1 |
   1246         +------+---+---+---+---+
   1247       */
   1248       cc_dep1 = args[2];
   1249       cc_dep2 = args[3];
   1250 
   1251       /* S390_CC_OP_SIGNED_COMPARE */
   1252       if (cc_op == S390_CC_OP_SIGNED_COMPARE) {
   1253          /*
   1254             cc == 0  --> cc_dep1 == cc_dep2   (cond == 8)
   1255             cc == 1  --> cc_dep1 <  cc_dep2   (cond == 4)
   1256             cc == 2  --> cc_dep1 >  cc_dep2   (cond == 2)
   1257 
   1258             Because cc == 3 cannot occur the rightmost bit of cond is
   1259             a don't care.
   1260          */
   1261          if (cond == 8 || cond == 8 + 1) {
   1262             return unop(Iop_1Uto32, binop(Iop_CmpEQ64, cc_dep1, cc_dep2));
   1263          }
   1264          if (cond == 4 + 2 || cond == 4 + 2 + 1) {
   1265             return unop(Iop_1Uto32, binop(Iop_CmpNE64, cc_dep1, cc_dep2));
   1266          }
   1267          if (cond == 4 || cond == 4 + 1) {
   1268             return unop(Iop_1Uto32, binop(Iop_CmpLT64S, cc_dep1, cc_dep2));
   1269          }
   1270          if (cond == 8 + 4 || cond == 8 + 4 + 1) {
   1271             return unop(Iop_1Uto32, binop(Iop_CmpLE64S, cc_dep1, cc_dep2));
   1272          }
   1273          /* cc_dep1 > cc_dep2  ---->  cc_dep2 < cc_dep1 */
   1274          if (cond == 2 || cond == 2 + 1) {
   1275             return unop(Iop_1Uto32, binop(Iop_CmpLT64S, cc_dep2, cc_dep1));
   1276          }
   1277          if (cond == 8 + 2 || cond == 8 + 2 + 1) {
   1278             return unop(Iop_1Uto32, binop(Iop_CmpLE64S, cc_dep2, cc_dep1));
   1279          }
   1280          if (cond == 8 + 4 + 2 || cond == 8 + 4 + 2 + 1) {
   1281             return mkU32(1);
   1282          }
   1283          /* Remaining case */
   1284          return mkU32(0);
   1285       }
   1286 
   1287       /* S390_CC_OP_UNSIGNED_COMPARE */
   1288       if (cc_op == S390_CC_OP_UNSIGNED_COMPARE) {
   1289          /*
   1290             cc == 0  --> cc_dep1 == cc_dep2   (cond == 8)
   1291             cc == 1  --> cc_dep1 <  cc_dep2   (cond == 4)
   1292             cc == 2  --> cc_dep1 >  cc_dep2   (cond == 2)
   1293 
   1294             Because cc == 3 cannot occur the rightmost bit of cond is
   1295             a don't care.
   1296          */
   1297          if (cond == 8 || cond == 8 + 1) {
   1298             return unop(Iop_1Uto32, binop(Iop_CmpEQ64, cc_dep1, cc_dep2));
   1299          }
   1300          if (cond == 4 + 2 || cond == 4 + 2 + 1) {
   1301             return unop(Iop_1Uto32, binop(Iop_CmpNE64, cc_dep1, cc_dep2));
   1302          }
   1303          if (cond == 4 || cond == 4 + 1) {
   1304             return unop(Iop_1Uto32, binop(Iop_CmpLT64U, cc_dep1, cc_dep2));
   1305          }
   1306          if (cond == 8 + 4 || cond == 8 + 4 + 1) {
   1307             return unop(Iop_1Uto32, binop(Iop_CmpLE64U, cc_dep1, cc_dep2));
   1308          }
   1309          /* cc_dep1 > cc_dep2  ---->  cc_dep2 < cc_dep1 */
   1310          if (cond == 2 || cond == 2 + 1) {
   1311             return unop(Iop_1Uto32, binop(Iop_CmpLT64U, cc_dep2, cc_dep1));
   1312          }
   1313          if (cond == 8 + 2 || cond == 8 + 2 + 1) {
   1314             return unop(Iop_1Uto32, binop(Iop_CmpLE64U, cc_dep2, cc_dep1));
   1315          }
   1316          if (cond == 8 + 4 + 2 || cond == 8 + 4 + 2 + 1) {
   1317             return mkU32(1);
   1318          }
   1319          /* Remaining case */
   1320          return mkU32(0);
   1321       }
   1322 
   1323       /* S390_CC_OP_LOAD_AND_TEST */
   1324       if (cc_op == S390_CC_OP_LOAD_AND_TEST) {
   1325          /*
   1326             cc == 0  --> cc_dep1 == 0   (cond == 8)
   1327             cc == 1  --> cc_dep1 <  0   (cond == 4)
   1328             cc == 2  --> cc_dep1 >  0   (cond == 2)
   1329 
   1330             Because cc == 3 cannot occur the rightmost bit of cond is
   1331             a don't care.
   1332          */
   1333          if (cond == 8 || cond == 8 + 1) {
   1334             return unop(Iop_1Uto32, binop(Iop_CmpEQ64, cc_dep1, mkU64(0)));
   1335          }
   1336          if (cond == 4 + 2 || cond == 4 + 2 + 1) {
   1337             return unop(Iop_1Uto32, binop(Iop_CmpNE64, cc_dep1, mkU64(0)));
   1338          }
   1339          if (cond == 4 || cond == 4 + 1) {
   1340             return unop(Iop_1Uto32, binop(Iop_CmpLT64S, cc_dep1, mkU64(0)));
   1341          }
   1342          if (cond == 8 + 4 || cond == 8 + 4 + 1) {
   1343             return unop(Iop_1Uto32, binop(Iop_CmpLE64S, cc_dep1, mkU64(0)));
   1344          }
   1345          /* cc_dep1 > 0  ---->  0 < cc_dep1 */
   1346          if (cond == 2 || cond == 2 + 1) {
   1347             return unop(Iop_1Uto32, binop(Iop_CmpLT64S, mkU64(0), cc_dep1));
   1348          }
   1349          if (cond == 8 + 2 || cond == 8 + 2 + 1) {
   1350             return unop(Iop_1Uto32, binop(Iop_CmpLE64S, mkU64(0), cc_dep1));
   1351          }
   1352          if (cond == 8 + 4 + 2 || cond == 8 + 4 + 2 + 1) {
   1353             return mkU32(1);
   1354          }
   1355          /* Remaining case */
   1356          return mkU32(0);
   1357       }
   1358 
   1359       /* S390_CC_OP_BITWISE */
   1360       if (cc_op == S390_CC_OP_BITWISE) {
   1361          /*
   1362             cc_dep1 is the result of the boolean operation.
   1363 
   1364             cc == 0  --> cc_dep1 == 0   (cond == 8)
   1365             cc == 1  --> cc_dep1 != 0   (cond == 4)
   1366 
   1367             Because cc == 2 and cc == 3 cannot occur the two rightmost bits of
   1368             cond are don't cares. Therefore:
   1369 
   1370             cond == 00xx  -> always false
   1371             cond == 01xx  -> not equal
   1372             cond == 10xx  -> equal
   1373             cond == 11xx  -> always true
   1374          */
   1375          if ((cond & (8 + 4)) == 8 + 4) {
   1376             return mkU32(1);
   1377          }
   1378          if (cond & 8) {
   1379             return unop(Iop_1Uto32, binop(Iop_CmpEQ64, cc_dep1, mkU64(0)));
   1380          }
   1381          if (cond & 4) {
   1382             return unop(Iop_1Uto32, binop(Iop_CmpNE64, cc_dep1, mkU64(0)));
   1383          }
   1384          /* Remaining case */
   1385          return mkU32(0);
   1386       }
   1387 
   1388       /* S390_CC_OP_INSERT_CHAR_MASK_32
   1389          Since the mask comes from an immediate field in the opcode, we
   1390          expect the mask to be a constant here. That simplifies matters. */
   1391       if (cc_op == S390_CC_OP_INSERT_CHAR_MASK_32) {
   1392          ULong mask;
   1393          UInt imask = 0, shift = 0;
   1394          IRExpr *word;
   1395 
   1396          if (! isC64(cc_dep2)) goto missed;
   1397 
   1398          mask = cc_dep2->Iex.Const.con->Ico.U64;
   1399 
   1400          /* Extract the 32-bit value from the thunk */
   1401 
   1402          word = unop(Iop_64to32, cc_dep1);
   1403 
   1404          switch (mask) {
   1405          case 0:  shift =  0; imask = 0x00000000; break;
   1406          case 1:  shift = 24; imask = 0x000000FF; break;
   1407          case 2:  shift = 16; imask = 0x0000FF00; break;
   1408          case 3:  shift = 16; imask = 0x0000FFFF; break;
   1409          case 4:  shift =  8; imask = 0x00FF0000; break;
   1410          case 5:  shift =  8; imask = 0x00FF00FF; break;
   1411          case 6:  shift =  8; imask = 0x00FFFF00; break;
   1412          case 7:  shift =  8; imask = 0x00FFFFFF; break;
   1413          case 8:  shift =  0; imask = 0xFF000000; break;
   1414          case 9:  shift =  0; imask = 0xFF0000FF; break;
   1415          case 10: shift =  0; imask = 0xFF00FF00; break;
   1416          case 11: shift =  0; imask = 0xFF00FFFF; break;
   1417          case 12: shift =  0; imask = 0xFFFF0000; break;
   1418          case 13: shift =  0; imask = 0xFFFF00FF; break;
   1419          case 14: shift =  0; imask = 0xFFFFFF00; break;
   1420          case 15: shift =  0; imask = 0xFFFFFFFF; break;
   1421          }
   1422 
   1423          /* Select the bits that were inserted */
   1424          word = binop(Iop_And32, word, mkU32(imask));
   1425 
   1426          /* cc == 0  --> all inserted bits zero or mask == 0   (cond == 8)
   1427             cc == 1  --> leftmost inserted bit is one          (cond == 4)
   1428             cc == 2  --> leftmost inserted bit is zero and not (cond == 2)
   1429                          all inserted bits are zero
   1430 
   1431             Because cc == 0,1,2 the rightmost bit of the mask is a don't care */
   1432          if (cond == 8 || cond == 8 + 1) {
   1433             return unop(Iop_1Uto32, binop(Iop_CmpEQ32, word, mkU32(0)));
   1434          }
   1435          if (cond == 4 + 2 || cond == 4 + 2 + 1) {
   1436             return unop(Iop_1Uto32, binop(Iop_CmpNE32, word, mkU32(0)));
   1437          }
   1438 
   1439          /* Sign extend */
   1440          if (shift != 0) {
   1441             word = binop(Iop_Sar32, binop(Iop_Shl32, word, mkU8(shift)),
   1442                          mkU8(shift));
   1443          }
   1444 
   1445          if (cond == 4 || cond == 4 + 1) {  /* word < 0 */
   1446             return unop(Iop_1Uto32, binop(Iop_CmpLT32S, word, mkU32(0)));
   1447          }
   1448          if (cond == 2 || cond == 2 + 1) {  /* word > 0 */
   1449             return unop(Iop_1Uto32, binop(Iop_CmpLT32S, mkU32(0), word));
   1450          }
   1451          if (cond == 8 + 4 || cond == 8 + 4 + 1) {
   1452             return unop(Iop_1Uto32, binop(Iop_CmpLE32S, word, mkU32(0)));
   1453          }
   1454          if (cond == 8 + 2 || cond == 8 + 2 + 1) {
   1455             return unop(Iop_1Uto32, binop(Iop_CmpLE32S, mkU32(0), word));
   1456          }
   1457          if (cond == 8 + 4 + 2 || cond == 8 + 4 + 2 + 1) {
   1458             return mkU32(1);
   1459          }
   1460          /* Remaining case */
   1461          return mkU32(0);
   1462       }
   1463 
   1464       /* S390_CC_OP_TEST_UNDER_MASK_8
   1465          Since the mask comes from an immediate field in the opcode, we
   1466          expect the mask to be a constant here. That simplifies matters. */
   1467       if (cc_op == S390_CC_OP_TEST_UNDER_MASK_8) {
   1468          ULong mask16;
   1469 
   1470          if (! isC64(cc_dep2)) goto missed;
   1471 
   1472          mask16 = cc_dep2->Iex.Const.con->Ico.U64;
   1473 
   1474          /* Get rid of the mask16 == 0 case first. Some of the simplifications
   1475             below (e.g. for OVFL) only hold if mask16 == 0.  */
   1476          if (mask16 == 0) {   /* cc == 0 */
   1477             if (cond & 0x8) return mkU32(1);
   1478             return mkU32(0);
   1479          }
   1480 
   1481          /* cc == 2 is a don't care */
   1482          if (cond == 8 || cond == 8 + 2) {
   1483             return unop(Iop_1Uto32, binop(Iop_CmpEQ64,
   1484                                           binop(Iop_And64, cc_dep1, cc_dep2),
   1485                                           mkU64(0)));
   1486          }
   1487          if (cond == 7 || cond == 7 - 2) {
   1488             return unop(Iop_1Uto32, binop(Iop_CmpNE64,
   1489                                           binop(Iop_And64, cc_dep1, cc_dep2),
   1490                                           mkU64(0)));
   1491          }
   1492          if (cond == 1 || cond == 1 + 2) {
   1493             return unop(Iop_1Uto32, binop(Iop_CmpEQ64,
   1494                                           binop(Iop_And64, cc_dep1, cc_dep2),
   1495                                           cc_dep2));
   1496          }
   1497          if (cond == 14 || cond == 14 - 2) {  /* ! OVFL */
   1498             return unop(Iop_1Uto32, binop(Iop_CmpNE64,
   1499                                           binop(Iop_And64, cc_dep1, cc_dep2),
   1500                                           cc_dep2));
   1501          }
   1502          goto missed;
   1503       }
   1504 
   1505       /* S390_CC_OP_TEST_UNDER_MASK_16
   1506          Since the mask comes from an immediate field in the opcode, we
   1507          expect the mask to be a constant here. That simplifies matters. */
   1508       if (cc_op == S390_CC_OP_TEST_UNDER_MASK_16) {
   1509          ULong mask16;
   1510          UInt msb;
   1511 
   1512          if (! isC64(cc_dep2)) goto missed;
   1513 
   1514          mask16 = cc_dep2->Iex.Const.con->Ico.U64;
   1515 
   1516          /* Get rid of the mask16 == 0 case first. Some of the simplifications
   1517             below (e.g. for OVFL) only hold if mask16 == 0.  */
   1518          if (mask16 == 0) {   /* cc == 0 */
   1519             if (cond & 0x8) return mkU32(1);
   1520             return mkU32(0);
   1521          }
   1522 
   1523          if (cond == 8) {
   1524             return unop(Iop_1Uto32, binop(Iop_CmpEQ64,
   1525                                           binop(Iop_And64, cc_dep1, cc_dep2),
   1526                                           mkU64(0)));
   1527          }
   1528          if (cond == 7) {
   1529             return unop(Iop_1Uto32, binop(Iop_CmpNE64,
   1530                                           binop(Iop_And64, cc_dep1, cc_dep2),
   1531                                           mkU64(0)));
   1532          }
   1533          if (cond == 1) {
   1534             return unop(Iop_1Uto32, binop(Iop_CmpEQ64,
   1535                                           binop(Iop_And64, cc_dep1, cc_dep2),
   1536                                           mkU64(mask16)));
   1537          }
   1538          if (cond == 14) {  /* ! OVFL */
   1539             return unop(Iop_1Uto32, binop(Iop_CmpNE64,
   1540                                           binop(Iop_And64, cc_dep1, cc_dep2),
   1541                                           mkU64(mask16)));
   1542          }
   1543 
   1544          /* Find MSB in mask */
   1545          msb = 0x8000;
   1546          while (msb > mask16)
   1547             msb >>= 1;
   1548 
   1549          if (cond == 2) {  /* cc == 2 */
   1550             IRExpr *c1, *c2;
   1551 
   1552             /* (cc_dep & msb) != 0 && (cc_dep & mask16) != mask16 */
   1553             c1 = binop(Iop_CmpNE64,
   1554                        binop(Iop_And64, cc_dep1, mkU64(msb)), mkU64(0));
   1555             c2 = binop(Iop_CmpNE64,
   1556                        binop(Iop_And64, cc_dep1, cc_dep2),
   1557                        mkU64(mask16));
   1558             return binop(Iop_And32, unop(Iop_1Uto32, c1),
   1559                          unop(Iop_1Uto32, c2));
   1560          }
   1561 
   1562          if (cond == 4) {  /* cc == 1 */
   1563             IRExpr *c1, *c2;
   1564 
   1565             /* (cc_dep & msb) == 0 && (cc_dep & mask16) != 0 */
   1566             c1 = binop(Iop_CmpEQ64,
   1567                        binop(Iop_And64, cc_dep1, mkU64(msb)), mkU64(0));
   1568             c2 = binop(Iop_CmpNE64,
   1569                        binop(Iop_And64, cc_dep1, cc_dep2),
   1570                        mkU64(0));
   1571             return binop(Iop_And32, unop(Iop_1Uto32, c1),
   1572                          unop(Iop_1Uto32, c2));
   1573          }
   1574 
   1575          if (cond == 11) {  /* cc == 0,2,3 */
   1576             IRExpr *c1, *c2;
   1577 
   1578             c1 = binop(Iop_CmpNE64,
   1579                        binop(Iop_And64, cc_dep1, mkU64(msb)), mkU64(0));
   1580             c2 = binop(Iop_CmpEQ64,
   1581                        binop(Iop_And64, cc_dep1, cc_dep2),
   1582                        mkU64(0));
   1583             return binop(Iop_Or32, unop(Iop_1Uto32, c1),
   1584                          unop(Iop_1Uto32, c2));
   1585          }
   1586 
   1587          if (cond == 3) {  /* cc == 2 || cc == 3 */
   1588             return unop(Iop_1Uto32,
   1589                         binop(Iop_CmpNE64,
   1590                               binop(Iop_And64, cc_dep1, mkU64(msb)),
   1591                               mkU64(0)));
   1592          }
   1593          if (cond == 12) { /* cc == 0 || cc == 1 */
   1594             return unop(Iop_1Uto32,
   1595                         binop(Iop_CmpEQ64,
   1596                               binop(Iop_And64, cc_dep1, mkU64(msb)),
   1597                               mkU64(0)));
   1598          }
   1599          // vex_printf("TUM mask = 0x%llx\n", mask16);
   1600          goto missed;
   1601       }
   1602 
   1603       /* S390_CC_OP_UNSIGNED_SUB_64/32 */
   1604       if (cc_op == S390_CC_OP_UNSIGNED_SUB_64 ||
   1605           cc_op == S390_CC_OP_UNSIGNED_SUB_32) {
   1606          /*
   1607             cc_dep1, cc_dep2 are the zero extended left and right operands
   1608 
   1609             cc == 1  --> result != 0, borrow    (cond == 4)
   1610             cc == 2  --> result == 0, no borrow (cond == 2)
   1611             cc == 3  --> result != 0, no borrow (cond == 1)
   1612 
   1613             cc = (cc_dep1 == cc_dep2) ? 2
   1614                                       : (cc_dep1 > cc_dep2) ? 3 : 1;
   1615 
   1616             Because cc == 0 cannot occur the leftmost bit of cond is
   1617             a don't care.
   1618          */
   1619          if (cond == 1 || cond == 1 + 8) {  /* cc == 3   op2 < op1 */
   1620             return unop(Iop_1Uto32, binop(Iop_CmpLT64U, cc_dep2, cc_dep1));
   1621          }
   1622          if (cond == 2 || cond == 2 + 8) {  /* cc == 2 */
   1623             return unop(Iop_1Uto32, binop(Iop_CmpEQ64, cc_dep1, cc_dep2));
   1624          }
   1625          if (cond == 4 || cond == 4 + 8) {  /* cc == 1 */
   1626             return unop(Iop_1Uto32, binop(Iop_CmpLT64U, cc_dep1, cc_dep2));
   1627          }
   1628          if (cond == 3 || cond == 3 + 8) {  /* cc == 2 || cc == 3 */
   1629             return unop(Iop_1Uto32, binop(Iop_CmpLE64U, cc_dep2, cc_dep1));
   1630          }
   1631          if (cond == 6 || cond == 6 + 8) {  /* cc == 2 || cc == 1 */
   1632             return unop(Iop_1Uto32, binop(Iop_CmpLE64U, cc_dep1, cc_dep2));
   1633          }
   1634 
   1635          if (cond == 5 || cond == 5 + 8) {  /* cc == 3 || cc == 1 */
   1636             return unop(Iop_1Uto32, binop(Iop_CmpNE64, cc_dep1, cc_dep2));
   1637          }
   1638          if (cond == 7 || cond == 7 + 8) {
   1639             return mkU32(1);
   1640          }
   1641          /* Remaining case */
   1642          return mkU32(0);
   1643       }
   1644 
   1645       /* S390_CC_OP_UNSIGNED_ADD_64 */
   1646       if (cc_op == S390_CC_OP_UNSIGNED_ADD_64) {
   1647          /*
   1648             cc_dep1, cc_dep2 are the zero extended left and right operands
   1649 
   1650             cc == 0  --> result == 0, no carry  (cond == 8)
   1651             cc == 1  --> result != 0, no carry  (cond == 4)
   1652             cc == 2  --> result == 0, carry     (cond == 2)
   1653             cc == 3  --> result != 0, carry     (cond == 1)
   1654          */
   1655          if (cond == 8) { /* cc == 0 */
   1656             /* Both inputs are 0 */
   1657             return unop(Iop_1Uto32, binop(Iop_CmpEQ64,
   1658                                           binop(Iop_Or64, cc_dep1, cc_dep2),
   1659                                           mkU64(0)));
   1660          }
   1661          if (cond == 7) { /* cc == 1,2,3 */
   1662             /* Not both inputs are 0 */
   1663             return unop(Iop_1Uto32, binop(Iop_CmpNE64,
   1664                                           binop(Iop_Or64, cc_dep1, cc_dep2),
   1665                                           mkU64(0)));
   1666          }
   1667          if (cond == 8 + 2) {  /* cc == 0,2  -> result is zero */
   1668             return unop(Iop_1Uto32, binop(Iop_CmpEQ64,
   1669                                           binop(Iop_Add64, cc_dep1, cc_dep2),
   1670                                           mkU64(0)));
   1671          }
   1672          if (cond == 4 + 1) {  /* cc == 1,3  -> result is not zero */
   1673             return unop(Iop_1Uto32, binop(Iop_CmpNE64,
   1674                                           binop(Iop_Add64, cc_dep1, cc_dep2),
   1675                                           mkU64(0)));
   1676          }
   1677          goto missed;
   1678       }
   1679 
   1680       /* S390_CC_OP_UNSIGNED_ADD_32 */
   1681       if (cc_op == S390_CC_OP_UNSIGNED_ADD_32) {
   1682          /*
   1683             cc_dep1, cc_dep2 are the zero extended left and right operands
   1684 
   1685             cc == 0  --> result == 0, no carry  (cond == 8)
   1686             cc == 1  --> result != 0, no carry  (cond == 4)
   1687             cc == 2  --> result == 0, carry     (cond == 2)
   1688             cc == 3  --> result != 0, carry     (cond == 1)
   1689          */
   1690          if (cond == 8) { /* cc == 0 */
   1691             /* Both inputs are 0 */
   1692             return unop(Iop_1Uto32, binop(Iop_CmpEQ64,
   1693                                           binop(Iop_Or64, cc_dep1, cc_dep2),
   1694                                           mkU64(0)));
   1695          }
   1696          if (cond == 7) { /* cc == 1,2,3 */
   1697             /* Not both inputs are 0 */
   1698             return unop(Iop_1Uto32, binop(Iop_CmpNE64,
   1699                                           binop(Iop_Or64, cc_dep1, cc_dep2),
   1700                                           mkU64(0)));
   1701          }
   1702          if (cond == 8 + 2) {  /* cc == 0,2  -> result is zero */
   1703             return unop(Iop_1Uto32, binop(Iop_CmpEQ32,
   1704                                           binop(Iop_Add32,
   1705                                                 unop(Iop_64to32, cc_dep1),
   1706                                                 unop(Iop_64to32, cc_dep2)),
   1707                                           mkU32(0)));
   1708          }
   1709          if (cond == 4 + 1) {  /* cc == 1,3  -> result is not zero */
   1710             return unop(Iop_1Uto32, binop(Iop_CmpNE32,
   1711                                           binop(Iop_Add32,
   1712                                                 unop(Iop_64to32, cc_dep1),
   1713                                                 unop(Iop_64to32, cc_dep2)),
   1714                                           mkU32(0)));
   1715          }
   1716          goto missed;
   1717       }
   1718 
   1719       /* S390_CC_OP_SET */
   1720       if (cc_op == S390_CC_OP_SET) {
   1721          /* cc_dep1 is the condition code
   1722 
   1723             Return 1, if ((cond << cc_dep1) & 0x8) != 0 */
   1724 
   1725         return unop(Iop_1Uto32,
   1726                     binop(Iop_CmpNE64,
   1727                           binop(Iop_And64,
   1728                                 binop(Iop_Shl64, cond_expr,
   1729                                       unop(Iop_64to8, cc_dep1)),
   1730                                 mkU64(8)),
   1731                           mkU64(0)));
   1732       }
   1733 
   1734 missed:
   1735       ;
   1736    }
   1737 
   1738    return NULL;
   1739 }
   1740 
   1741 /*---------------------------------------------------------------*/
   1742 /*--- end                                guest_s390_helpers.c ---*/
   1743 /*---------------------------------------------------------------*/
   1744