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-2013
     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_emnote.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 "main_globals.h"
     42 #include "guest_generic_bb_to_IR.h"
     43 #include "guest_s390_defs.h"
     44 #include "s390_defs.h"               /* S390_BFP_ROUND_xyzzy */
     45 
     46 void
     47 LibVEX_GuestS390X_initialise(VexGuestS390XState *state)
     48 {
     49 /*------------------------------------------------------------*/
     50 /*--- Initialise ar registers                              ---*/
     51 /*------------------------------------------------------------*/
     52 
     53    state->guest_a0 = 0;
     54    state->guest_a1 = 0;
     55    state->guest_a2 = 0;
     56    state->guest_a3 = 0;
     57    state->guest_a4 = 0;
     58    state->guest_a5 = 0;
     59    state->guest_a6 = 0;
     60    state->guest_a7 = 0;
     61    state->guest_a8 = 0;
     62    state->guest_a9 = 0;
     63    state->guest_a10 = 0;
     64    state->guest_a11 = 0;
     65    state->guest_a12 = 0;
     66    state->guest_a13 = 0;
     67    state->guest_a14 = 0;
     68    state->guest_a15 = 0;
     69 
     70 /*------------------------------------------------------------*/
     71 /*--- Initialise fpr registers                             ---*/
     72 /*------------------------------------------------------------*/
     73 
     74    state->guest_f0 = 0;
     75    state->guest_f1 = 0;
     76    state->guest_f2 = 0;
     77    state->guest_f3 = 0;
     78    state->guest_f4 = 0;
     79    state->guest_f5 = 0;
     80    state->guest_f6 = 0;
     81    state->guest_f7 = 0;
     82    state->guest_f8 = 0;
     83    state->guest_f9 = 0;
     84    state->guest_f10 = 0;
     85    state->guest_f11 = 0;
     86    state->guest_f12 = 0;
     87    state->guest_f13 = 0;
     88    state->guest_f14 = 0;
     89    state->guest_f15 = 0;
     90 
     91 /*------------------------------------------------------------*/
     92 /*--- Initialise gpr registers                             ---*/
     93 /*------------------------------------------------------------*/
     94 
     95    state->guest_r0 = 0;
     96    state->guest_r1 = 0;
     97    state->guest_r2 = 0;
     98    state->guest_r3 = 0;
     99    state->guest_r4 = 0;
    100    state->guest_r5 = 0;
    101    state->guest_r6 = 0;
    102    state->guest_r7 = 0;
    103    state->guest_r8 = 0;
    104    state->guest_r9 = 0;
    105    state->guest_r10 = 0;
    106    state->guest_r11 = 0;
    107    state->guest_r12 = 0;
    108    state->guest_r13 = 0;
    109    state->guest_r14 = 0;
    110    state->guest_r15 = 0;
    111 
    112 /*------------------------------------------------------------*/
    113 /*--- Initialise S390 miscellaneous registers              ---*/
    114 /*------------------------------------------------------------*/
    115 
    116    state->guest_counter = 0;
    117    state->guest_fpc = 0;
    118    state->guest_IA = 0;
    119 
    120 /*------------------------------------------------------------*/
    121 /*--- Initialise S390 pseudo registers                     ---*/
    122 /*------------------------------------------------------------*/
    123 
    124    state->guest_SYSNO = 0;
    125 
    126 /*------------------------------------------------------------*/
    127 /*--- Initialise generic pseudo registers                  ---*/
    128 /*------------------------------------------------------------*/
    129 
    130    state->guest_NRADDR = 0;
    131    state->guest_CMSTART = 0;
    132    state->guest_CMLEN = 0;
    133    state->guest_IP_AT_SYSCALL = 0;
    134    state->guest_EMNOTE = EmNote_NONE;
    135    state->host_EvC_COUNTER = 0;
    136    state->host_EvC_FAILADDR = 0;
    137 
    138 /*------------------------------------------------------------*/
    139 /*--- Initialise thunk                                     ---*/
    140 /*------------------------------------------------------------*/
    141 
    142    state->guest_CC_OP = 0;
    143    state->guest_CC_DEP1 = 0;
    144    state->guest_CC_DEP2 = 0;
    145    state->guest_CC_NDEP = 0;
    146 
    147    __builtin_memset(state->padding, 0x0, sizeof(state->padding));
    148 }
    149 
    150 
    151 /* Figure out if any part of the guest state contained in minoff
    152    .. maxoff requires precise memory exceptions.  If in doubt return
    153    True (but this generates significantly slower code).  */
    154 Bool
    155 guest_s390x_state_requires_precise_mem_exns(Int minoff, Int maxoff)
    156 {
    157    Int lr_min = S390X_GUEST_OFFSET(guest_LR);
    158    Int lr_max = lr_min + 8 - 1;
    159    Int sp_min = S390X_GUEST_OFFSET(guest_SP);
    160    Int sp_max = sp_min + 8 - 1;
    161    Int fp_min = S390X_GUEST_OFFSET(guest_FP);
    162    Int fp_max = fp_min + 8 - 1;
    163    Int ia_min = S390X_GUEST_OFFSET(guest_IA);
    164    Int ia_max = ia_min + 8 - 1;
    165 
    166    if (maxoff < sp_min || minoff > sp_max) {
    167       /* No overlap with SP */
    168       if (vex_control.iropt_register_updates == VexRegUpdSpAtMemAccess)
    169          return False; // We only need to check stack pointer.
    170    } else {
    171       return True;
    172    }
    173 
    174    if (maxoff < lr_min || minoff > lr_max) {
    175       /* No overlap with LR */
    176    } else {
    177       return True;
    178    }
    179 
    180    if (maxoff < fp_min || minoff > fp_max) {
    181       /* No overlap with FP */
    182    } else {
    183       return True;
    184    }
    185 
    186    if (maxoff < ia_min || minoff > ia_max) {
    187       /* No overlap with IA */
    188    } else {
    189       return True;
    190    }
    191 
    192    return False;
    193 }
    194 
    195 
    196 #define ALWAYSDEFD(field)                             \
    197     { S390X_GUEST_OFFSET(field),            \
    198       (sizeof ((VexGuestS390XState*)0)->field) }
    199 
    200 VexGuestLayout s390xGuest_layout = {
    201 
    202    /* Total size of the guest state, in bytes. */
    203    .total_sizeB = sizeof(VexGuestS390XState),
    204 
    205    /* Describe the stack pointer. */
    206    .offset_SP = S390X_GUEST_OFFSET(guest_SP),
    207    .sizeof_SP = 8,
    208 
    209    /* Describe the frame pointer. */
    210    .offset_FP = S390X_GUEST_OFFSET(guest_FP),
    211    .sizeof_FP = 8,
    212 
    213    /* Describe the instruction pointer. */
    214    .offset_IP = S390X_GUEST_OFFSET(guest_IA),
    215    .sizeof_IP = 8,
    216 
    217    /* Describe any sections to be regarded by Memcheck as
    218       'always-defined'. */
    219    .n_alwaysDefd = 9,
    220 
    221    /* Flags thunk: OP and NDEP are always defined, whereas DEP1
    222       and DEP2 have to be tracked.  See detailed comment in
    223       gdefs.h on meaning of thunk fields. */
    224    .alwaysDefd = {
    225       /*  0 */ ALWAYSDEFD(guest_CC_OP),     /* generic */
    226       /*  1 */ ALWAYSDEFD(guest_CC_NDEP),   /* generic */
    227       /*  2 */ ALWAYSDEFD(guest_EMNOTE),    /* generic */
    228       /*  3 */ ALWAYSDEFD(guest_CMSTART),   /* generic */
    229       /*  4 */ ALWAYSDEFD(guest_CMLEN),     /* generic */
    230       /*  5 */ ALWAYSDEFD(guest_IP_AT_SYSCALL), /* generic */
    231       /*  6 */ ALWAYSDEFD(guest_IA),        /* control reg */
    232       /*  7 */ ALWAYSDEFD(guest_fpc),       /* control reg */
    233       /*  8 */ ALWAYSDEFD(guest_counter),   /* internal usage register */
    234    }
    235 };
    236 
    237 /*------------------------------------------------------------*/
    238 /*--- Dirty helper for EXecute                             ---*/
    239 /*------------------------------------------------------------*/
    240 void
    241 s390x_dirtyhelper_EX(ULong torun)
    242 {
    243    last_execute_target = torun;
    244 }
    245 
    246 
    247 /*------------------------------------------------------------*/
    248 /*--- Dirty helper for Clock instructions                  ---*/
    249 /*------------------------------------------------------------*/
    250 #if defined(VGA_s390x)
    251 ULong
    252 s390x_dirtyhelper_STCK(ULong *addr)
    253 {
    254    UInt cc;
    255 
    256    asm volatile("stck %0\n"
    257                 "ipm %1\n"
    258                 "srl %1,28\n"
    259                 : "+Q" (*addr), "=d" (cc) : : "cc");
    260    return cc;
    261 }
    262 
    263 ULong
    264 s390x_dirtyhelper_STCKE(ULong *addr)
    265 {
    266    UInt cc;
    267 
    268    asm volatile("stcke %0\n"
    269                 "ipm %1\n"
    270                 "srl %1,28\n"
    271                 : "+Q" (*addr), "=d" (cc) : : "cc");
    272    return cc;
    273 }
    274 
    275 ULong s390x_dirtyhelper_STCKF(ULong *addr)
    276 {
    277    UInt cc;
    278 
    279    asm volatile(".insn s,0xb27c0000,%0\n"
    280                 "ipm %1\n"
    281                 "srl %1,28\n"
    282                 : "+Q" (*addr), "=d" (cc) : : "cc");
    283    return cc;
    284 }
    285 #else
    286 ULong s390x_dirtyhelper_STCK(ULong *addr)  {return 3;}
    287 ULong s390x_dirtyhelper_STCKF(ULong *addr) {return 3;}
    288 ULong s390x_dirtyhelper_STCKE(ULong *addr) {return 3;}
    289 #endif /* VGA_s390x */
    290 
    291 /*------------------------------------------------------------*/
    292 /*--- Dirty helper for Store Facility instruction          ---*/
    293 /*------------------------------------------------------------*/
    294 #if defined(VGA_s390x)
    295 static void
    296 s390_set_facility_bit(ULong *addr, UInt bitno, UInt value)
    297 {
    298    addr  += bitno / 64;
    299    bitno  = bitno % 64;
    300 
    301    ULong mask = 1;
    302    mask <<= (63 - bitno);
    303 
    304    if (value == 1) {
    305       *addr |= mask;   // set
    306    } else {
    307       *addr &= ~mask;  // clear
    308    }
    309 }
    310 
    311 ULong
    312 s390x_dirtyhelper_STFLE(VexGuestS390XState *guest_state, ULong *addr)
    313 {
    314    ULong hoststfle[S390_NUM_FACILITY_DW], cc, num_dw, i;
    315    register ULong reg0 asm("0") = guest_state->guest_r0 & 0xF;  /* r0[56:63] */
    316 
    317    /* We cannot store more than S390_NUM_FACILITY_DW
    318       (and it makes not much sense to do so anyhow) */
    319    if (reg0 > S390_NUM_FACILITY_DW - 1)
    320       reg0 = S390_NUM_FACILITY_DW - 1;
    321 
    322    num_dw = reg0 + 1;  /* number of double words written */
    323 
    324    asm volatile(" .insn s,0xb2b00000,%0\n"   /* stfle */
    325                 "ipm    %2\n"
    326                 "srl    %2,28\n"
    327                 : "=m" (hoststfle), "+d"(reg0), "=d"(cc) : : "cc", "memory");
    328 
    329    /* Update guest register 0  with what STFLE set r0 to */
    330    guest_state->guest_r0 = reg0;
    331 
    332    /* Set default: VM facilities = host facilities */
    333    for (i = 0; i < num_dw; ++i)
    334       addr[i] = hoststfle[i];
    335 
    336    /* Now adjust the VM facilities according to what the VM supports */
    337    s390_set_facility_bit(addr, S390_FAC_LDISP,  1);
    338    s390_set_facility_bit(addr, S390_FAC_EIMM,   1);
    339    s390_set_facility_bit(addr, S390_FAC_ETF2,   1);
    340    s390_set_facility_bit(addr, S390_FAC_ETF3,   1);
    341    s390_set_facility_bit(addr, S390_FAC_GIE,    1);
    342    s390_set_facility_bit(addr, S390_FAC_EXEXT,  1);
    343    s390_set_facility_bit(addr, S390_FAC_HIGHW,  1);
    344 
    345    s390_set_facility_bit(addr, S390_FAC_HFPMAS, 0);
    346    s390_set_facility_bit(addr, S390_FAC_HFPUNX, 0);
    347    s390_set_facility_bit(addr, S390_FAC_XCPUT,  0);
    348    s390_set_facility_bit(addr, S390_FAC_MSA,    0);
    349    s390_set_facility_bit(addr, S390_FAC_PENH,   0);
    350    s390_set_facility_bit(addr, S390_FAC_DFP,    0);
    351    s390_set_facility_bit(addr, S390_FAC_PFPO,   0);
    352    s390_set_facility_bit(addr, S390_FAC_DFPZC,  0);
    353    s390_set_facility_bit(addr, S390_FAC_MISC,   0);
    354    s390_set_facility_bit(addr, S390_FAC_CTREXE, 0);
    355    s390_set_facility_bit(addr, S390_FAC_TREXE,  0);
    356    s390_set_facility_bit(addr, S390_FAC_MSA4,   0);
    357 
    358    return cc;
    359 }
    360 
    361 #else
    362 
    363 ULong
    364 s390x_dirtyhelper_STFLE(VexGuestS390XState *guest_state, ULong *addr)
    365 {
    366    return 3;
    367 }
    368 #endif /* VGA_s390x */
    369 
    370 /*------------------------------------------------------------*/
    371 /*--- Dirty helper for the "convert unicode" insn family.  ---*/
    372 /*------------------------------------------------------------*/
    373 void
    374 s390x_dirtyhelper_CUxy(UChar *address, ULong data, ULong num_bytes)
    375 {
    376    UInt i;
    377 
    378    vassert(num_bytes >= 1 && num_bytes <= 4);
    379 
    380    /* Store the least significant NUM_BYTES bytes in DATA left to right
    381       at ADDRESS. */
    382    for (i = 1; i <= num_bytes; ++i) {
    383       address[num_bytes - i] = data & 0xff;
    384       data >>= 8;
    385    }
    386 }
    387 
    388 
    389 /*------------------------------------------------------------*/
    390 /*--- Clean helper for CU21.                               ---*/
    391 /*------------------------------------------------------------*/
    392 
    393 /* The function performs a CU21 operation. It returns three things
    394    encoded in an ULong value:
    395    - the converted bytes (at most 4)
    396    - the number of converted bytes
    397    - an indication whether LOW_SURROGATE, if any, is invalid
    398 
    399    64      48                16           8                       0
    400     +-------+-----------------+-----------+-----------------------+
    401     |  0x0  | converted bytes | num_bytes | invalid_low_surrogate |
    402     +-------+-----------------+-----------+-----------------------+
    403 */
    404 ULong
    405 s390_do_cu21(UInt srcval, UInt low_surrogate)
    406 {
    407    ULong retval = 0;   // shut up gcc
    408    UInt b1, b2, b3, b4, num_bytes, invalid_low_surrogate = 0;
    409 
    410    srcval &= 0xffff;
    411 
    412    /* Determine the number of bytes in the converted value */
    413    if (srcval <= 0x007f)
    414       num_bytes = 1;
    415    else if (srcval >= 0x0080 && srcval <= 0x07ff)
    416       num_bytes = 2;
    417    else if ((srcval >= 0x0800 && srcval <= 0xd7ff) ||
    418             (srcval >= 0xdc00 && srcval <= 0xffff))
    419       num_bytes = 3;
    420    else
    421       num_bytes = 4;
    422 
    423    /* Determine UTF-8 bytes according to calculated num_bytes */
    424    switch (num_bytes){
    425    case 1:
    426       retval = srcval;
    427       break;
    428 
    429    case 2:
    430       /* order of bytes left to right: b1, b2 */
    431       b1  = 0xc0;
    432       b1 |= srcval >> 6;
    433 
    434       b2  = 0x80;
    435       b2 |= srcval & 0x3f;
    436 
    437       retval = (b1 << 8) | b2;
    438       break;
    439 
    440    case 3:
    441       /* order of bytes left to right: b1, b2, b3 */
    442       b1  = 0xe0;
    443       b1 |= srcval >> 12;
    444 
    445       b2  = 0x80;
    446       b2 |= (srcval >> 6) & 0x3f;
    447 
    448       b3  = 0x80;
    449       b3 |= srcval & 0x3f;
    450 
    451       retval = (b1 << 16) | (b2 << 8) | b3;
    452       break;
    453 
    454    case 4: {
    455       /* order of bytes left to right: b1, b2, b3, b4 */
    456       UInt high_surrogate = srcval;
    457       UInt uvwxy = ((high_surrogate >> 6) & 0xf) + 1;   // abcd + 1
    458 
    459       b1  = 0xf0;
    460       b1 |= uvwxy >> 2;     // uvw
    461 
    462       b2  = 0x80;
    463       b2 |= (uvwxy & 0x3) << 4;           // xy
    464       b2 |= (high_surrogate >> 2) & 0xf;  // efgh
    465 
    466       b3  = 0x80;
    467       b3 |= (high_surrogate & 0x3) << 4;   // ij
    468       b3 |= (low_surrogate >> 6) & 0xf;    // klmn
    469 
    470       b4  = 0x80;
    471       b4 |= low_surrogate & 0x3f;
    472 
    473       retval = (b1 << 24) | (b2 << 16) | (b3 << 8) | b4;
    474 
    475       invalid_low_surrogate = (low_surrogate & 0xfc00) != 0xdc00;
    476       break;
    477    }
    478    }
    479 
    480    /* At this point RETVAL contains the converted bytes.
    481       Build up the final return value. */
    482    return (retval << 16) | (num_bytes << 8) | invalid_low_surrogate;
    483 }
    484 
    485 
    486 /*------------------------------------------------------------*/
    487 /*--- Clean helper for CU24.                               ---*/
    488 /*------------------------------------------------------------*/
    489 
    490 /* The function performs a CU24 operation. It returns two things
    491    encoded in an ULong value:
    492    - the 4 converted bytes
    493    - an indication whether LOW_SURROGATE, if any, is invalid
    494 
    495    64     40                 8                       0
    496     +------------------------+-----------------------+
    497     |  0x0 | converted bytes | invalid_low_surrogate |
    498     +------------------------+-----------------------+
    499 */
    500 ULong
    501 s390_do_cu24(UInt srcval, UInt low_surrogate)
    502 {
    503    ULong retval;
    504    UInt invalid_low_surrogate = 0;
    505 
    506    srcval &= 0xffff;
    507 
    508    if ((srcval >= 0x0000 && srcval <= 0xd7ff) ||
    509        (srcval >= 0xdc00 && srcval <= 0xffff)) {
    510       retval = srcval;
    511    } else {
    512       /* D800 - DBFF */
    513       UInt high_surrogate = srcval;
    514       UInt uvwxy  = ((high_surrogate >> 6) & 0xf) + 1;   // abcd + 1
    515       UInt efghij = high_surrogate & 0x3f;
    516       UInt klmnoprst = low_surrogate & 0x3ff;
    517 
    518       retval = (uvwxy << 16) | (efghij << 10) | klmnoprst;
    519 
    520       invalid_low_surrogate = (low_surrogate & 0xfc00) != 0xdc00;
    521    }
    522 
    523    /* At this point RETVAL contains the converted bytes.
    524       Build up the final return value. */
    525    return (retval << 8) | invalid_low_surrogate;
    526 }
    527 
    528 
    529 /*------------------------------------------------------------*/
    530 /*--- Clean helper for CU42.                               ---*/
    531 /*------------------------------------------------------------*/
    532 
    533 /* The function performs a CU42 operation. It returns three things
    534    encoded in an ULong value:
    535    - the converted bytes (at most 4)
    536    - the number of converted bytes (2 or 4; 0 if invalid character)
    537    - an indication whether the UTF-32 character is invalid
    538 
    539    64      48                16           8                   0
    540     +-------+-----------------+-----------+-------------------+
    541     |  0x0  | converted bytes | num_bytes | invalid_character |
    542     +-------+-----------------+-----------+-------------------+
    543 */
    544 ULong
    545 s390_do_cu42(UInt srcval)
    546 {
    547    ULong retval;
    548    UInt num_bytes, invalid_character = 0;
    549 
    550    if ((srcval >= 0x0000 && srcval <= 0xd7ff) ||
    551        (srcval >= 0xdc00 && srcval <= 0xffff)) {
    552       retval = srcval;
    553       num_bytes = 2;
    554    } else if (srcval >= 0x00010000 && srcval <= 0x0010FFFF) {
    555       UInt uvwxy  = srcval >> 16;
    556       UInt abcd   = (uvwxy - 1) & 0xf;
    557       UInt efghij = (srcval >> 10) & 0x3f;
    558 
    559       UInt high_surrogate = (0xd8 << 8) | (abcd << 6) | efghij;
    560       UInt low_surrogate  = (0xdc << 8) | (srcval & 0x3ff);
    561 
    562       retval = (high_surrogate << 16) | low_surrogate;
    563       num_bytes = 4;
    564    } else {
    565       /* D800 - DBFF or 00110000 - FFFFFFFF */
    566       invalid_character = 1;
    567       retval = num_bytes = 0;   /* does not matter; not used */
    568    }
    569 
    570    /* At this point RETVAL contains the converted bytes.
    571       Build up the final return value. */
    572    return (retval << 16) | (num_bytes << 8) | invalid_character;
    573 }
    574 
    575 
    576 /*------------------------------------------------------------*/
    577 /*--- Clean helper for CU41.                               ---*/
    578 /*------------------------------------------------------------*/
    579 
    580 /* The function performs a CU41 operation. It returns three things
    581    encoded in an ULong value:
    582    - the converted bytes (at most 4)
    583    - the number of converted bytes (1, 2, 3, or 4; 0 if invalid character)
    584    - an indication whether the UTF-32 character is invalid
    585 
    586    64      48                16           8                   0
    587     +-------+-----------------+-----------+-------------------+
    588     |  0x0  | converted bytes | num_bytes | invalid_character |
    589     +-------+-----------------+-----------+-------------------+
    590 */
    591 ULong
    592 s390_do_cu41(UInt srcval)
    593 {
    594    ULong retval;
    595    UInt num_bytes, invalid_character = 0;
    596 
    597    if (srcval <= 0x7f) {
    598       retval = srcval;
    599       num_bytes = 1;
    600    } else if (srcval >= 0x80 && srcval <= 0x7ff) {
    601       UInt fghij  = srcval >> 6;
    602       UInt klmnop = srcval & 0x3f;
    603       UInt byte1  = (0xc0 | fghij);
    604       UInt byte2  = (0x80 | klmnop);
    605 
    606       retval = (byte1 << 8) | byte2;
    607       num_bytes = 2;
    608    } else if ((srcval >= 0x800  && srcval <= 0xd7ff) ||
    609               (srcval >= 0xdc00 && srcval <= 0xffff)) {
    610       UInt abcd   = srcval >> 12;
    611       UInt efghij = (srcval >> 6) & 0x3f;
    612       UInt klmnop = srcval & 0x3f;
    613       UInt byte1  = 0xe0 | abcd;
    614       UInt byte2  = 0x80 | efghij;
    615       UInt byte3  = 0x80 | klmnop;
    616 
    617       retval = (byte1 << 16) | (byte2 << 8) | byte3;
    618       num_bytes = 3;
    619    } else if (srcval >= 0x10000 && srcval <= 0x10ffff) {
    620       UInt uvw    = (srcval >> 18) & 0x7;
    621       UInt xy     = (srcval >> 16) & 0x3;
    622       UInt efgh   = (srcval >> 12) & 0xf;
    623       UInt ijklmn = (srcval >>  6) & 0x3f;
    624       UInt opqrst = srcval & 0x3f;
    625       UInt byte1  = 0xf0 | uvw;
    626       UInt byte2  = 0x80 | (xy << 4) | efgh;
    627       UInt byte3  = 0x80 | ijklmn;
    628       UInt byte4  = 0x80 | opqrst;
    629 
    630       retval = (byte1 << 24) | (byte2 << 16) | (byte3 << 8) | byte4;
    631       num_bytes = 4;
    632    } else {
    633       /* d800 ... dbff or 00110000 ... ffffffff */
    634       invalid_character = 1;
    635 
    636       retval = 0;
    637       num_bytes = 0;
    638    }
    639 
    640    /* At this point RETVAL contains the converted bytes.
    641       Build up the final return value. */
    642    return (retval << 16) | (num_bytes << 8) | invalid_character;
    643 }
    644 
    645 
    646 /*------------------------------------------------------------*/
    647 /*--- Clean helpers for CU12.                              ---*/
    648 /*------------------------------------------------------------*/
    649 
    650 /* The function looks at the first byte of an UTF-8 character and returns
    651    two things encoded in an ULong value:
    652 
    653    - the number of bytes that need to be read
    654    - an indication whether the UTF-8 character is invalid
    655 
    656    64      16           8                   0
    657     +-------------------+-------------------+
    658     |  0x0  | num_bytes | invalid_character |
    659     +-------+-----------+-------------------+
    660 */
    661 ULong
    662 s390_do_cu12_cu14_helper1(UInt byte, UInt etf3_and_m3_is_1)
    663 {
    664    vassert(byte <= 0xff);
    665 
    666    /* Check whether the character is invalid */
    667    if (byte >= 0x80 && byte <= 0xbf) return 1;
    668    if (byte >= 0xf8) return 1;
    669 
    670    if (etf3_and_m3_is_1) {
    671       if (byte == 0xc0 || byte == 0xc1) return 1;
    672       if (byte >= 0xf5 && byte <= 0xf7) return 1;
    673    }
    674 
    675    /* Character is valid */
    676    if (byte <= 0x7f) return 1 << 8;   // 1 byte
    677    if (byte <= 0xdf) return 2 << 8;   // 2 bytes
    678    if (byte <= 0xef) return 3 << 8;   // 3 bytes
    679 
    680    return 4 << 8;  // 4 bytes
    681 }
    682 
    683 /* The function performs a CU12 or CU14 operation. BYTE1, BYTE2, etc are the
    684    bytes as read from the input stream, left to right. BYTE1 is a valid
    685    byte. The function returns three things encoded in an ULong value:
    686 
    687    - the converted bytes
    688    - the number of converted bytes (2 or 4; 0 if invalid character)
    689    - an indication whether the UTF-16 character is invalid
    690 
    691    64      48                16           8                   0
    692     +-------+-----------------+-----------+-------------------+
    693     |  0x0  | converted bytes | num_bytes | invalid_character |
    694     +-------+-----------------+-----------+-------------------+
    695 */
    696 static ULong
    697 s390_do_cu12_cu14_helper2(UInt byte1, UInt byte2, UInt byte3, UInt byte4,
    698                           ULong stuff, Bool is_cu12)
    699 {
    700    UInt num_src_bytes = stuff >> 1, etf3_and_m3_is_1 = stuff & 0x1;
    701    UInt num_bytes = 0, invalid_character = 0;
    702    ULong retval = 0;
    703 
    704    vassert(num_src_bytes <= 4);
    705 
    706    switch (num_src_bytes) {
    707    case 1:
    708       num_bytes = 2;
    709       retval = byte1;
    710       break;
    711 
    712    case 2: {
    713       /* Test validity */
    714       if (etf3_and_m3_is_1) {
    715          if (byte2 < 0x80 || byte2 > 0xbf) {
    716             invalid_character = 1;
    717             break;
    718          }
    719       }
    720 
    721       /* OK */
    722       UInt fghij  = byte1 & 0x1f;
    723       UInt klmnop = byte2 & 0x3f;
    724 
    725       num_bytes = 2;
    726       retval = (fghij << 6) | klmnop;
    727       break;
    728    }
    729 
    730    case 3: {
    731       /* Test validity */
    732       if (etf3_and_m3_is_1) {
    733          if (byte1 == 0xe0) {
    734             if ((byte2 < 0xa0 || byte2 > 0xbf) ||
    735                 (byte3 < 0x80 || byte3 > 0xbf)) {
    736                invalid_character = 1;
    737                break;
    738             }
    739          }
    740          if ((byte1 >= 0xe1 && byte1 <= 0xec) ||
    741              byte1 == 0xee || byte1 == 0xef) {
    742             if ((byte2 < 0x80 || byte2 > 0xbf) ||
    743                 (byte3 < 0x80 || byte3 > 0xbf)) {
    744                invalid_character = 1;
    745                break;
    746             }
    747          }
    748          if (byte1 == 0xed) {
    749             if ((byte2 < 0x80 || byte2 > 0x9f) ||
    750                 (byte3 < 0x80 || byte3 > 0xbf)) {
    751                invalid_character = 1;
    752                break;
    753             }
    754          }
    755       }
    756 
    757       /* OK */
    758       UInt abcd   = byte1 & 0xf;
    759       UInt efghij = byte2 & 0x3f;
    760       UInt klmnop = byte3 & 0x3f;
    761 
    762       num_bytes = 2;
    763       retval = (abcd << 12) | (efghij << 6) | klmnop;
    764       break;
    765    }
    766 
    767    case 4: {
    768       /* Test validity */
    769       if (etf3_and_m3_is_1) {
    770          if (byte1 == 0xf0) {
    771             if ((byte2 < 0x90 || byte2 > 0xbf) ||
    772                 (byte3 < 0x80 || byte3 > 0xbf) ||
    773                 (byte4 < 0x80 || byte4 > 0xbf)) {
    774                invalid_character = 1;
    775                break;
    776             }
    777          }
    778          if (byte1 == 0xf1 || byte1 == 0xf2 || byte1 == 0xf3) {
    779             if ((byte2 < 0x80 || byte2 > 0xbf) ||
    780                 (byte3 < 0x80 || byte3 > 0xbf) ||
    781                 (byte4 < 0x80 || byte4 > 0xbf)) {
    782                invalid_character = 1;
    783                break;
    784             }
    785          }
    786          if (byte1 == 0xf4) {
    787             if ((byte2 < 0x80 || byte2 > 0x8f) ||
    788                 (byte3 < 0x80 || byte3 > 0xbf) ||
    789                 (byte4 < 0x80 || byte4 > 0xbf)) {
    790                invalid_character = 1;
    791                break;
    792             }
    793          }
    794       }
    795 
    796       /* OK */
    797       UInt uvw    = byte1 & 0x7;
    798       UInt xy     = (byte2 >> 4) & 0x3;
    799       UInt uvwxy  = (uvw << 2) | xy;
    800       UInt efgh   = byte2 & 0xf;
    801       UInt ij     = (byte3 >> 4) & 0x3;
    802       UInt klmn   = byte3 & 0xf;
    803       UInt opqrst = byte4 & 0x3f;
    804 
    805       if (is_cu12) {
    806          UInt abcd = (uvwxy - 1) & 0xf;
    807          UInt high_surrogate = (0xd8 << 8) | (abcd << 6) | (efgh << 2) | ij;
    808          UInt low_surrogate  = (0xdc << 8) | (klmn << 6) | opqrst;
    809 
    810          num_bytes = 4;
    811          retval = (high_surrogate << 16) | low_surrogate;
    812       } else {
    813          num_bytes = 4;
    814          retval =
    815             (uvwxy << 16) | (efgh << 12) | (ij << 10) | (klmn << 6) | opqrst;
    816       }
    817       break;
    818    }
    819    }
    820 
    821    if (! is_cu12) num_bytes = 4;   // for CU14, by definition
    822 
    823    /* At this point RETVAL contains the converted bytes.
    824       Build up the final return value. */
    825    return (retval << 16) | (num_bytes << 8) | invalid_character;
    826 }
    827 
    828 ULong
    829 s390_do_cu12_helper2(UInt byte1, UInt byte2, UInt byte3, UInt byte4,
    830                      ULong stuff)
    831 {
    832    return s390_do_cu12_cu14_helper2(byte1, byte2, byte3, byte4, stuff,
    833                                     /* is_cu12 = */ 1);
    834 }
    835 
    836 ULong
    837 s390_do_cu14_helper2(UInt byte1, UInt byte2, UInt byte3, UInt byte4,
    838                      ULong stuff)
    839 {
    840    return s390_do_cu12_cu14_helper2(byte1, byte2, byte3, byte4, stuff,
    841                                     /* is_cu12 = */ 0);
    842 }
    843 
    844 
    845 /*------------------------------------------------------------*/
    846 /*--- Clean helper for "convert to binary".                ---*/
    847 /*------------------------------------------------------------*/
    848 #if defined(VGA_s390x)
    849 UInt
    850 s390_do_cvb(ULong decimal)
    851 {
    852    UInt binary;
    853 
    854    __asm__ volatile (
    855         "cvb %[result],%[input]\n\t"
    856           : [result] "=d"(binary)
    857           : [input] "m"(decimal)
    858    );
    859 
    860    return binary;
    861 }
    862 
    863 #else
    864 UInt s390_do_cvb(ULong decimal) { return 0; }
    865 #endif
    866 
    867 
    868 /*------------------------------------------------------------*/
    869 /*--- Clean helper for "convert to decimal".                ---*/
    870 /*------------------------------------------------------------*/
    871 #if defined(VGA_s390x)
    872 ULong
    873 s390_do_cvd(ULong binary_in)
    874 {
    875    UInt binary = binary_in & 0xffffffffULL;
    876    ULong decimal;
    877 
    878    __asm__ volatile (
    879         "cvd %[input],%[result]\n\t"
    880           : [result] "=m"(decimal)
    881           : [input] "d"(binary)
    882    );
    883 
    884    return decimal;
    885 }
    886 
    887 #else
    888 ULong s390_do_cvd(ULong binary) { return 0; }
    889 #endif
    890 
    891 /*------------------------------------------------------------*/
    892 /*--- Clean helper for "Extract cache attribute".          ---*/
    893 /*------------------------------------------------------------*/
    894 #if defined(VGA_s390x)
    895 ULong
    896 s390_do_ecag(ULong op2addr)
    897 {
    898    ULong result;
    899 
    900    __asm__ volatile(".insn rsy,0xEB000000004C,%[out],0,0(%[in])\n\t"
    901                     : [out] "=d"(result)
    902                     : [in] "d"(op2addr));
    903    return result;
    904 }
    905 
    906 #else
    907 ULong s390_do_ecag(ULong op2addr) { return 0; }
    908 #endif
    909 
    910 /*------------------------------------------------------------*/
    911 /*--- Clean helper for "Perform Floating Point Operation". ---*/
    912 /*------------------------------------------------------------*/
    913 #if defined(VGA_s390x)
    914 UInt
    915 s390_do_pfpo(UInt gpr0)
    916 {
    917    UChar rm;
    918    UChar op1_ty, op2_ty;
    919 
    920    rm  = gpr0 & 0xf;
    921    if (rm > 1 && rm < 8)
    922       return EmFail_S390X_invalid_PFPO_rounding_mode;
    923 
    924    op1_ty = (gpr0 >> 16) & 0xff; // gpr0[40:47]
    925    op2_ty = (gpr0 >> 8)  & 0xff; // gpr0[48:55]
    926    /* Operand type must be BFP 32, 64, 128 or DFP 32, 64, 128
    927       which correspond to 0x5, 0x6, 0x7, 0x8, 0x9, 0xa respectively.
    928       Any other operand type value is unsupported */
    929    if ((op1_ty == op2_ty) ||
    930        (op1_ty < 0x5 || op1_ty > 0xa) ||
    931        (op2_ty < 0x5 || op2_ty > 0xa))
    932       return EmFail_S390X_invalid_PFPO_function;
    933 
    934    return EmNote_NONE;
    935 }
    936 #else
    937 UInt s390_do_pfpo(UInt gpr0) { return 0; }
    938 #endif
    939 
    940 /*------------------------------------------------------------*/
    941 /*--- Helper for condition code.                           ---*/
    942 /*------------------------------------------------------------*/
    943 
    944 /* Convert an IRRoundingMode value to s390_bfp_round_t */
    945 #if defined(VGA_s390x)
    946 static s390_bfp_round_t
    947 decode_bfp_rounding_mode(UInt irrm)
    948 {
    949    switch (irrm) {
    950    case Irrm_NEAREST: return S390_BFP_ROUND_NEAREST_EVEN;
    951    case Irrm_NegINF:  return S390_BFP_ROUND_NEGINF;
    952    case Irrm_PosINF:  return S390_BFP_ROUND_POSINF;
    953    case Irrm_ZERO:    return S390_BFP_ROUND_ZERO;
    954    }
    955    vpanic("decode_bfp_rounding_mode");
    956 }
    957 #endif
    958 
    959 
    960 #define S390_CC_FOR_BINARY(opcode,cc_dep1,cc_dep2) \
    961 ({ \
    962    __asm__ volatile ( \
    963         opcode " %[op1],%[op2]\n\t" \
    964         "ipm %[psw]\n\t"           : [psw] "=d"(psw), [op1] "+d"(cc_dep1) \
    965                                    : [op2] "d"(cc_dep2) \
    966                                    : "cc");\
    967    psw >> 28;   /* cc */ \
    968 })
    969 
    970 #define S390_CC_FOR_TERNARY_SUBB(opcode,cc_dep1,cc_dep2,cc_ndep) \
    971 ({ \
    972    /* Recover the original DEP2 value. See comment near s390_cc_thunk_put3 \
    973       for rationale. */ \
    974    cc_dep2 = cc_dep2 ^ cc_ndep; \
    975    __asm__ volatile ( \
    976 	"lghi 0,1\n\t" \
    977 	"sr 0,%[op3]\n\t" /* borrow to cc */ \
    978         opcode " %[op1],%[op2]\n\t" /* then redo the op */\
    979         "ipm %[psw]\n\t"           : [psw] "=d"(psw), [op1] "+&d"(cc_dep1) \
    980                                    : [op2] "d"(cc_dep2), [op3] "d"(cc_ndep) \
    981                                    : "0", "cc");\
    982    psw >> 28;   /* cc */ \
    983 })
    984 
    985 #define S390_CC_FOR_TERNARY_ADDC(opcode,cc_dep1,cc_dep2,cc_ndep) \
    986 ({ \
    987    /* Recover the original DEP2 value. See comment near s390_cc_thunk_put3 \
    988       for rationale. */ \
    989    cc_dep2 = cc_dep2 ^ cc_ndep; \
    990    __asm__ volatile ( \
    991 	"lgfr 0,%[op3]\n\t" /* first load cc_ndep */ \
    992 	"aghi 0,0\n\t" /* and convert it into a cc */ \
    993         opcode " %[op1],%[op2]\n\t" /* then redo the op */\
    994         "ipm %[psw]\n\t"           : [psw] "=d"(psw), [op1] "+&d"(cc_dep1) \
    995                                    : [op2] "d"(cc_dep2), [op3] "d"(cc_ndep) \
    996                                    : "0", "cc");\
    997    psw >> 28;   /* cc */ \
    998 })
    999 
   1000 
   1001 #define S390_CC_FOR_BFP_RESULT(opcode,cc_dep1) \
   1002 ({ \
   1003    __asm__ volatile ( \
   1004         opcode " 0,%[op]\n\t" \
   1005         "ipm %[psw]\n\t"           : [psw] "=d"(psw) \
   1006                                    : [op]  "f"(cc_dep1) \
   1007                                    : "cc", "f0");\
   1008    psw >> 28;   /* cc */ \
   1009 })
   1010 
   1011 #define S390_CC_FOR_BFP128_RESULT(hi,lo) \
   1012 ({ \
   1013    __asm__ volatile ( \
   1014         "ldr   4,%[high]\n\t" \
   1015         "ldr   6,%[low]\n\t" \
   1016         "ltxbr 0,4\n\t" \
   1017         "ipm %[psw]\n\t"           : [psw] "=d"(psw) \
   1018                                    : [high] "f"(hi), [low] "f"(lo) \
   1019                                    : "cc", "f0", "f2", "f4", "f6");\
   1020    psw >> 28;   /* cc */ \
   1021 })
   1022 
   1023 #define S390_CC_FOR_BFP_CONVERT_AUX(opcode,cc_dep1,rounding_mode) \
   1024 ({ \
   1025    __asm__ volatile ( \
   1026         opcode " 0," #rounding_mode ",%[op]\n\t" \
   1027         "ipm %[psw]\n\t"           : [psw] "=d"(psw) \
   1028                                    : [op]  "f"(cc_dep1) \
   1029                                    : "cc", "r0");\
   1030    psw >> 28;   /* cc */ \
   1031 })
   1032 
   1033 #define S390_CC_FOR_BFP_CONVERT(opcode,cc_dep1,cc_dep2)   \
   1034 ({                                                        \
   1035    UInt cc;                                               \
   1036    switch (decode_bfp_rounding_mode(cc_dep2)) {           \
   1037    case S390_BFP_ROUND_NEAREST_EVEN:                      \
   1038       cc = S390_CC_FOR_BFP_CONVERT_AUX(opcode,cc_dep1,4); \
   1039       break;                                              \
   1040    case S390_BFP_ROUND_ZERO:                              \
   1041       cc = S390_CC_FOR_BFP_CONVERT_AUX(opcode,cc_dep1,5); \
   1042       break;                                              \
   1043    case S390_BFP_ROUND_POSINF:                            \
   1044       cc = S390_CC_FOR_BFP_CONVERT_AUX(opcode,cc_dep1,6); \
   1045       break;                                              \
   1046    case S390_BFP_ROUND_NEGINF:                            \
   1047       cc = S390_CC_FOR_BFP_CONVERT_AUX(opcode,cc_dep1,7); \
   1048       break;                                              \
   1049    default:                                               \
   1050       vpanic("unexpected bfp rounding mode");             \
   1051    }                                                      \
   1052    cc;                                                    \
   1053 })
   1054 
   1055 #define S390_CC_FOR_BFP_UCONVERT_AUX(opcode,cc_dep1,rounding_mode) \
   1056 ({ \
   1057    __asm__ volatile ( \
   1058         opcode ",0,%[op]," #rounding_mode ",0\n\t" \
   1059         "ipm %[psw]\n\t"           : [psw] "=d"(psw) \
   1060                                    : [op]  "f"(cc_dep1) \
   1061                                    : "cc", "r0");\
   1062    psw >> 28;   /* cc */ \
   1063 })
   1064 
   1065 #define S390_CC_FOR_BFP_UCONVERT(opcode,cc_dep1,cc_dep2)   \
   1066 ({                                                         \
   1067    UInt cc;                                                \
   1068    switch (decode_bfp_rounding_mode(cc_dep2)) {            \
   1069    case S390_BFP_ROUND_NEAREST_EVEN:                       \
   1070       cc = S390_CC_FOR_BFP_UCONVERT_AUX(opcode,cc_dep1,4); \
   1071       break;                                               \
   1072    case S390_BFP_ROUND_ZERO:                               \
   1073       cc = S390_CC_FOR_BFP_UCONVERT_AUX(opcode,cc_dep1,5); \
   1074       break;                                               \
   1075    case S390_BFP_ROUND_POSINF:                             \
   1076       cc = S390_CC_FOR_BFP_UCONVERT_AUX(opcode,cc_dep1,6); \
   1077       break;                                               \
   1078    case S390_BFP_ROUND_NEGINF:                             \
   1079       cc = S390_CC_FOR_BFP_UCONVERT_AUX(opcode,cc_dep1,7); \
   1080       break;                                               \
   1081    default:                                                \
   1082       vpanic("unexpected bfp rounding mode");              \
   1083    }                                                       \
   1084    cc;                                                     \
   1085 })
   1086 
   1087 #define S390_CC_FOR_BFP128_CONVERT_AUX(opcode,hi,lo,rounding_mode) \
   1088 ({ \
   1089    __asm__ volatile ( \
   1090         "ldr   4,%[high]\n\t" \
   1091         "ldr   6,%[low]\n\t" \
   1092         opcode " 0," #rounding_mode ",4\n\t" \
   1093         "ipm %[psw]\n\t"           : [psw] "=d"(psw) \
   1094                                    : [high] "f"(hi), [low] "f"(lo) \
   1095                                    : "cc", "r0", "f4", "f6");\
   1096    psw >> 28;   /* cc */ \
   1097 })
   1098 
   1099 #define S390_CC_FOR_BFP128_CONVERT(opcode,cc_dep1,cc_dep2,cc_ndep)   \
   1100 ({                                                                   \
   1101    UInt cc;                                                          \
   1102    /* Recover the original DEP2 value. See comment near              \
   1103       s390_cc_thunk_put3 for rationale. */                           \
   1104    cc_dep2 = cc_dep2 ^ cc_ndep;                                      \
   1105    switch (decode_bfp_rounding_mode(cc_ndep)) {                      \
   1106    case S390_BFP_ROUND_NEAREST_EVEN:                                 \
   1107       cc = S390_CC_FOR_BFP128_CONVERT_AUX(opcode,cc_dep1,cc_dep2,4); \
   1108       break;                                                         \
   1109    case S390_BFP_ROUND_ZERO:                                         \
   1110       cc = S390_CC_FOR_BFP128_CONVERT_AUX(opcode,cc_dep1,cc_dep2,5); \
   1111       break;                                                         \
   1112    case S390_BFP_ROUND_POSINF:                                       \
   1113       cc = S390_CC_FOR_BFP128_CONVERT_AUX(opcode,cc_dep1,cc_dep2,6); \
   1114       break;                                                         \
   1115    case S390_BFP_ROUND_NEGINF:                                       \
   1116       cc = S390_CC_FOR_BFP128_CONVERT_AUX(opcode,cc_dep1,cc_dep2,7); \
   1117       break;                                                         \
   1118    default:                                                          \
   1119       vpanic("unexpected bfp rounding mode");                        \
   1120    }                                                                 \
   1121    cc;                                                               \
   1122 })
   1123 
   1124 #define S390_CC_FOR_BFP128_UCONVERT_AUX(opcode,hi,lo,rounding_mode) \
   1125 ({ \
   1126    __asm__ volatile ( \
   1127         "ldr   4,%[high]\n\t" \
   1128         "ldr   6,%[low]\n\t" \
   1129         opcode ",0,4," #rounding_mode ",0\n\t" \
   1130         "ipm %[psw]\n\t"           : [psw] "=d"(psw) \
   1131                                    : [high] "f"(hi), [low] "f"(lo) \
   1132                                    : "cc", "r0", "f4", "f6");\
   1133    psw >> 28;   /* cc */ \
   1134 })
   1135 
   1136 #define S390_CC_FOR_BFP128_UCONVERT(opcode,cc_dep1,cc_dep2,cc_ndep)   \
   1137 ({                                                                    \
   1138    UInt cc;                                                           \
   1139    /* Recover the original DEP2 value. See comment near               \
   1140       s390_cc_thunk_put3 for rationale. */                            \
   1141    cc_dep2 = cc_dep2 ^ cc_ndep;                                       \
   1142    switch (decode_bfp_rounding_mode(cc_ndep)) {                       \
   1143    case S390_BFP_ROUND_NEAREST_EVEN:                                  \
   1144       cc = S390_CC_FOR_BFP128_UCONVERT_AUX(opcode,cc_dep1,cc_dep2,4); \
   1145       break;                                                          \
   1146    case S390_BFP_ROUND_ZERO:                                          \
   1147       cc = S390_CC_FOR_BFP128_UCONVERT_AUX(opcode,cc_dep1,cc_dep2,5); \
   1148       break;                                                          \
   1149    case S390_BFP_ROUND_POSINF:                                        \
   1150       cc = S390_CC_FOR_BFP128_UCONVERT_AUX(opcode,cc_dep1,cc_dep2,6); \
   1151       break;                                                          \
   1152    case S390_BFP_ROUND_NEGINF:                                        \
   1153       cc = S390_CC_FOR_BFP128_UCONVERT_AUX(opcode,cc_dep1,cc_dep2,7); \
   1154       break;                                                          \
   1155    default:                                                           \
   1156       vpanic("unexpected bfp rounding mode");                         \
   1157    }                                                                  \
   1158    cc;                                                                \
   1159 })
   1160 
   1161 #define S390_CC_FOR_BFP_TDC(opcode,cc_dep1,cc_dep2) \
   1162 ({ \
   1163    __asm__ volatile ( \
   1164         opcode " %[value],0(%[class])\n\t" \
   1165         "ipm %[psw]\n\t"           : [psw] "=d"(psw) \
   1166                                    : [value] "f"(cc_dep1), \
   1167                                      [class] "a"(cc_dep2)  \
   1168                                    : "cc");\
   1169    psw >> 28;   /* cc */ \
   1170 })
   1171 
   1172 #define S390_CC_FOR_BFP128_TDC(cc_dep1,cc_dep2,cc_ndep) \
   1173 ({ \
   1174    /* Recover the original DEP2 value. See comment near \
   1175       s390_cc_thunk_put1f128Z for rationale. */ \
   1176    cc_dep2 = cc_dep2 ^ cc_ndep; \
   1177    __asm__ volatile ( \
   1178         "ldr  4,%[high]\n\t" \
   1179         "ldr  6,%[low]\n\t" \
   1180         "tcxb 4,0(%[class])\n\t" \
   1181         "ipm  %[psw]\n\t"          : [psw] "=d"(psw) \
   1182                                    : [high] "f"(cc_dep1), [low] "f"(cc_dep2), \
   1183                                      [class] "a"(cc_ndep)  \
   1184                                    : "cc", "f4", "f6");\
   1185    psw >> 28;   /* cc */ \
   1186 })
   1187 
   1188 /* Convert an IRRoundingMode value to s390_dfp_round_t */
   1189 #if defined(VGA_s390x)
   1190 static s390_dfp_round_t
   1191 decode_dfp_rounding_mode(UInt irrm)
   1192 {
   1193    switch (irrm) {
   1194    case Irrm_NEAREST:
   1195       return S390_DFP_ROUND_NEAREST_EVEN_4;
   1196    case Irrm_NegINF:
   1197       return S390_DFP_ROUND_NEGINF_7;
   1198    case Irrm_PosINF:
   1199       return S390_DFP_ROUND_POSINF_6;
   1200    case Irrm_ZERO:
   1201       return S390_DFP_ROUND_ZERO_5;
   1202    case Irrm_NEAREST_TIE_AWAY_0:
   1203       return S390_DFP_ROUND_NEAREST_TIE_AWAY_0_1;
   1204    case Irrm_PREPARE_SHORTER:
   1205       return S390_DFP_ROUND_PREPARE_SHORT_3;
   1206    case Irrm_AWAY_FROM_ZERO:
   1207       return S390_DFP_ROUND_AWAY_0;
   1208    case Irrm_NEAREST_TIE_TOWARD_0:
   1209       return S390_DFP_ROUND_NEAREST_TIE_TOWARD_0;
   1210    }
   1211    vpanic("decode_dfp_rounding_mode");
   1212 }
   1213 #endif
   1214 
   1215 #define S390_CC_FOR_DFP_RESULT(cc_dep1) \
   1216 ({ \
   1217    __asm__ volatile ( \
   1218         ".insn rre, 0xb3d60000,0,%[op]\n\t"              /* LTDTR */ \
   1219         "ipm %[psw]\n\t"           : [psw] "=d"(psw) \
   1220                                    : [op]  "f"(cc_dep1) \
   1221                                    : "cc", "f0"); \
   1222    psw >> 28;   /* cc */ \
   1223 })
   1224 
   1225 #define S390_CC_FOR_DFP128_RESULT(hi,lo) \
   1226 ({ \
   1227    __asm__ volatile ( \
   1228         "ldr   4,%[high]\n\t"                                           \
   1229         "ldr   6,%[low]\n\t"                                            \
   1230         ".insn rre, 0xb3de0000,0,4\n\t"    /* LTXTR */                  \
   1231         "ipm %[psw]\n\t"           : [psw] "=d"(psw)                    \
   1232                                    : [high] "f"(hi), [low] "f"(lo)      \
   1233                                    : "cc", "f0", "f2", "f4", "f6");     \
   1234    psw >> 28;   /* cc */                                                \
   1235 })
   1236 
   1237 #define S390_CC_FOR_DFP_TD(opcode,cc_dep1,cc_dep2)                      \
   1238 ({                                                                      \
   1239    __asm__ volatile (                                                   \
   1240         opcode ",%[value],0(%[class])\n\t"                              \
   1241         "ipm %[psw]\n\t"           : [psw] "=d"(psw)                    \
   1242                                    : [value] "f"(cc_dep1),              \
   1243                                      [class] "a"(cc_dep2)               \
   1244                                    : "cc");                             \
   1245    psw >> 28;   /* cc */                                                \
   1246 })
   1247 
   1248 #define S390_CC_FOR_DFP128_TD(opcode,cc_dep1,cc_dep2,cc_ndep)           \
   1249 ({                                                                      \
   1250    /* Recover the original DEP2 value. See comment near                 \
   1251       s390_cc_thunk_put1d128Z for rationale. */                         \
   1252    cc_dep2 = cc_dep2 ^ cc_ndep;                                         \
   1253    __asm__ volatile (                                                   \
   1254         "ldr  4,%[high]\n\t"                                            \
   1255         "ldr  6,%[low]\n\t"                                             \
   1256         opcode ",4,0(%[class])\n\t"                                     \
   1257         "ipm  %[psw]\n\t"          : [psw] "=d"(psw)                    \
   1258                                    : [high] "f"(cc_dep1), [low] "f"(cc_dep2), \
   1259                                      [class] "a"(cc_ndep)               \
   1260                                    : "cc", "f4", "f6");                 \
   1261    psw >> 28;   /* cc */                                                \
   1262 })
   1263 
   1264 #define S390_CC_FOR_DFP_CONVERT_AUX(opcode,cc_dep1,rounding_mode)       \
   1265    ({                                                                   \
   1266       __asm__ volatile (                                                \
   1267                         opcode ",0,%[op]," #rounding_mode ",0\n\t"      \
   1268                         "ipm %[psw]\n\t"           : [psw] "=d"(psw)    \
   1269                         : [op] "f"(cc_dep1)                             \
   1270                         : "cc", "r0");                                  \
   1271       psw >> 28;   /* cc */                                             \
   1272    })
   1273 
   1274 #define S390_CC_FOR_DFP_CONVERT(opcode,cc_dep1,cc_dep2)                 \
   1275    ({                                                                   \
   1276       UInt cc;                                                          \
   1277       switch (decode_dfp_rounding_mode(cc_dep2)) {                      \
   1278       case S390_DFP_ROUND_NEAREST_TIE_AWAY_0_1:                         \
   1279       case S390_DFP_ROUND_NEAREST_TIE_AWAY_0_12:                        \
   1280          cc = S390_CC_FOR_DFP_CONVERT_AUX(opcode,cc_dep1,1);            \
   1281          break;                                                         \
   1282       case S390_DFP_ROUND_PREPARE_SHORT_3:                              \
   1283       case S390_DFP_ROUND_PREPARE_SHORT_15:                             \
   1284          cc = S390_CC_FOR_DFP_CONVERT_AUX(opcode,cc_dep1,3);            \
   1285          break;                                                         \
   1286       case S390_DFP_ROUND_NEAREST_EVEN_4:                               \
   1287       case S390_DFP_ROUND_NEAREST_EVEN_8:                               \
   1288          cc = S390_CC_FOR_DFP_CONVERT_AUX(opcode,cc_dep1,4);            \
   1289          break;                                                         \
   1290       case S390_DFP_ROUND_ZERO_5:                                       \
   1291       case S390_DFP_ROUND_ZERO_9:                                       \
   1292          cc = S390_CC_FOR_DFP_CONVERT_AUX(opcode,cc_dep1,5);            \
   1293          break;                                                         \
   1294       case S390_DFP_ROUND_POSINF_6:                                     \
   1295       case S390_DFP_ROUND_POSINF_10:                                    \
   1296          cc = S390_CC_FOR_DFP_CONVERT_AUX(opcode,cc_dep1,6);            \
   1297          break;                                                         \
   1298       case S390_DFP_ROUND_NEGINF_7:                                     \
   1299       case S390_DFP_ROUND_NEGINF_11:                                    \
   1300          cc = S390_CC_FOR_DFP_CONVERT_AUX(opcode,cc_dep1,7);            \
   1301          break;                                                         \
   1302       case S390_DFP_ROUND_NEAREST_TIE_TOWARD_0:                         \
   1303          cc = S390_CC_FOR_DFP_CONVERT_AUX(opcode,cc_dep1,13);           \
   1304          break;                                                         \
   1305       case S390_DFP_ROUND_AWAY_0:                                       \
   1306          cc = S390_CC_FOR_DFP_CONVERT_AUX(opcode,cc_dep1,14);           \
   1307          break;                                                         \
   1308       default:                                                          \
   1309          vpanic("unexpected dfp rounding mode");                        \
   1310       }                                                                 \
   1311       cc;                                                               \
   1312    })
   1313 
   1314 #define S390_CC_FOR_DFP_UCONVERT_AUX(opcode,cc_dep1,rounding_mode)      \
   1315    ({                                                                   \
   1316       __asm__ volatile (                                                \
   1317                         opcode ",0,%[op]," #rounding_mode ",0\n\t"      \
   1318                         "ipm %[psw]\n\t"           : [psw] "=d"(psw)    \
   1319                         : [op] "f"(cc_dep1)                             \
   1320                         : "cc", "r0");                                  \
   1321       psw >> 28;   /* cc */                                             \
   1322    })
   1323 
   1324 #define S390_CC_FOR_DFP_UCONVERT(opcode,cc_dep1,cc_dep2)                \
   1325    ({                                                                   \
   1326       UInt cc;                                                          \
   1327       switch (decode_dfp_rounding_mode(cc_dep2)) {                      \
   1328       case S390_DFP_ROUND_NEAREST_TIE_AWAY_0_1:                         \
   1329       case S390_DFP_ROUND_NEAREST_TIE_AWAY_0_12:                        \
   1330          cc = S390_CC_FOR_DFP_UCONVERT_AUX(opcode,cc_dep1,1);           \
   1331          break;                                                         \
   1332       case S390_DFP_ROUND_PREPARE_SHORT_3:                              \
   1333       case S390_DFP_ROUND_PREPARE_SHORT_15:                             \
   1334          cc = S390_CC_FOR_DFP_UCONVERT_AUX(opcode,cc_dep1,3);           \
   1335          break;                                                         \
   1336       case S390_DFP_ROUND_NEAREST_EVEN_4:                               \
   1337       case S390_DFP_ROUND_NEAREST_EVEN_8:                               \
   1338          cc = S390_CC_FOR_DFP_UCONVERT_AUX(opcode,cc_dep1,4);           \
   1339          break;                                                         \
   1340       case S390_DFP_ROUND_ZERO_5:                                       \
   1341       case S390_DFP_ROUND_ZERO_9:                                       \
   1342          cc = S390_CC_FOR_DFP_UCONVERT_AUX(opcode,cc_dep1,5);           \
   1343          break;                                                         \
   1344       case S390_DFP_ROUND_POSINF_6:                                     \
   1345       case S390_DFP_ROUND_POSINF_10:                                    \
   1346          cc = S390_CC_FOR_DFP_UCONVERT_AUX(opcode,cc_dep1,6);           \
   1347          break;                                                         \
   1348       case S390_DFP_ROUND_NEGINF_7:                                     \
   1349       case S390_DFP_ROUND_NEGINF_11:                                    \
   1350          cc = S390_CC_FOR_DFP_UCONVERT_AUX(opcode,cc_dep1,7);           \
   1351          break;                                                         \
   1352       case S390_DFP_ROUND_NEAREST_TIE_TOWARD_0:                         \
   1353          cc = S390_CC_FOR_DFP_UCONVERT_AUX(opcode,cc_dep1,13);          \
   1354          break;                                                         \
   1355       case S390_DFP_ROUND_AWAY_0:                                       \
   1356          cc = S390_CC_FOR_DFP_UCONVERT_AUX(opcode,cc_dep1,14);          \
   1357          break;                                                         \
   1358       default:                                                          \
   1359          vpanic("unexpected dfp rounding mode");                        \
   1360       }                                                                 \
   1361       cc;                                                               \
   1362    })
   1363 
   1364 #define S390_CC_FOR_DFP128_CONVERT_AUX(opcode,hi,lo,rounding_mode)      \
   1365    ({                                                                   \
   1366       __asm__ volatile (                                                \
   1367                         "ldr   4,%[high]\n\t"                           \
   1368                         "ldr   6,%[low]\n\t"                            \
   1369                         opcode ",0,4," #rounding_mode ",0\n\t"          \
   1370                         "ipm %[psw]\n\t"           : [psw] "=d"(psw)    \
   1371                         : [high] "f"(hi), [low] "f"(lo)                 \
   1372                         : "cc", "r0", "f4", "f6");                      \
   1373       psw >> 28;   /* cc */                                             \
   1374    })
   1375 
   1376 #define S390_CC_FOR_DFP128_CONVERT(opcode,cc_dep1,cc_dep2,cc_ndep)       \
   1377    ({                                                                    \
   1378       UInt cc;                                                           \
   1379       /* Recover the original DEP2 value. See comment near               \
   1380          s390_cc_thunk_put3 for rationale. */                            \
   1381       cc_dep2 = cc_dep2 ^ cc_ndep;                                       \
   1382       switch (decode_dfp_rounding_mode(cc_ndep)) {                       \
   1383       case S390_DFP_ROUND_NEAREST_TIE_AWAY_0_1:                          \
   1384       case S390_DFP_ROUND_NEAREST_TIE_AWAY_0_12:                         \
   1385          cc = S390_CC_FOR_DFP128_CONVERT_AUX(opcode,cc_dep1,cc_dep2,1);  \
   1386          break;                                                          \
   1387       case S390_DFP_ROUND_PREPARE_SHORT_3:                               \
   1388       case S390_DFP_ROUND_PREPARE_SHORT_15:                              \
   1389          cc = S390_CC_FOR_DFP128_CONVERT_AUX(opcode,cc_dep1,cc_dep2,3);  \
   1390          break;                                                          \
   1391       case S390_DFP_ROUND_NEAREST_EVEN_4:                                \
   1392       case S390_DFP_ROUND_NEAREST_EVEN_8:                                \
   1393          cc = S390_CC_FOR_DFP128_CONVERT_AUX(opcode,cc_dep1,cc_dep2,4);  \
   1394          break;                                                          \
   1395       case S390_DFP_ROUND_ZERO_5:                                        \
   1396       case S390_DFP_ROUND_ZERO_9:                                        \
   1397          cc = S390_CC_FOR_DFP128_CONVERT_AUX(opcode,cc_dep1,cc_dep2,5);  \
   1398          break;                                                          \
   1399       case S390_DFP_ROUND_POSINF_6:                                      \
   1400       case S390_DFP_ROUND_POSINF_10:                                     \
   1401          cc = S390_CC_FOR_DFP128_CONVERT_AUX(opcode,cc_dep1,cc_dep2,6);  \
   1402          break;                                                          \
   1403       case S390_DFP_ROUND_NEGINF_7:                                      \
   1404       case S390_DFP_ROUND_NEGINF_11:                                     \
   1405          cc = S390_CC_FOR_DFP128_CONVERT_AUX(opcode,cc_dep1,cc_dep2,7);  \
   1406          break;                                                          \
   1407       case S390_DFP_ROUND_NEAREST_TIE_TOWARD_0:                          \
   1408          cc = S390_CC_FOR_DFP128_CONVERT_AUX(opcode,cc_dep1,cc_dep2,13); \
   1409          break;                                                          \
   1410       case S390_DFP_ROUND_AWAY_0:                                        \
   1411          cc = S390_CC_FOR_DFP128_CONVERT_AUX(opcode,cc_dep1,cc_dep2,14); \
   1412          break;                                                          \
   1413       default:                                                           \
   1414          vpanic("unexpected dfp rounding mode");                         \
   1415       }                                                                  \
   1416       cc;                                                                \
   1417    })
   1418 
   1419 #define S390_CC_FOR_DFP128_UCONVERT_AUX(opcode,hi,lo,rounding_mode)      \
   1420    ({                                                                    \
   1421       __asm__ volatile (                                                 \
   1422                         "ldr   4,%[high]\n\t"                            \
   1423                         "ldr   6,%[low]\n\t"                             \
   1424                         opcode ",0,4," #rounding_mode ",0\n\t"           \
   1425                         "ipm %[psw]\n\t"           : [psw] "=d"(psw)     \
   1426                         : [high] "f"(hi), [low] "f"(lo)                  \
   1427                         : "cc", "r0", "f4", "f6");                       \
   1428       psw >> 28;   /* cc */                                              \
   1429    })
   1430 
   1431 #define S390_CC_FOR_DFP128_UCONVERT(opcode,cc_dep1,cc_dep2,cc_ndep)       \
   1432    ({                                                                     \
   1433       UInt cc;                                                            \
   1434       /* Recover the original DEP2 value. See comment near                \
   1435          s390_cc_thunk_put3 for rationale. */                             \
   1436       cc_dep2 = cc_dep2 ^ cc_ndep;                                        \
   1437       switch (decode_dfp_rounding_mode(cc_ndep)) {                        \
   1438       case S390_DFP_ROUND_NEAREST_TIE_AWAY_0_1:                           \
   1439       case S390_DFP_ROUND_NEAREST_TIE_AWAY_0_12:                          \
   1440          cc = S390_CC_FOR_DFP128_UCONVERT_AUX(opcode,cc_dep1,cc_dep2,1);  \
   1441          break;                                                           \
   1442       case S390_DFP_ROUND_PREPARE_SHORT_3:                                \
   1443       case S390_DFP_ROUND_PREPARE_SHORT_15:                               \
   1444          cc = S390_CC_FOR_DFP128_UCONVERT_AUX(opcode,cc_dep1,cc_dep2,3);  \
   1445          break;                                                           \
   1446       case S390_DFP_ROUND_NEAREST_EVEN_4:                                 \
   1447       case S390_DFP_ROUND_NEAREST_EVEN_8:                                 \
   1448          cc = S390_CC_FOR_DFP128_UCONVERT_AUX(opcode,cc_dep1,cc_dep2,4);  \
   1449          break;                                                           \
   1450       case S390_DFP_ROUND_ZERO_5:                                         \
   1451       case S390_DFP_ROUND_ZERO_9:                                         \
   1452          cc = S390_CC_FOR_DFP128_UCONVERT_AUX(opcode,cc_dep1,cc_dep2,5);  \
   1453          break;                                                           \
   1454       case S390_DFP_ROUND_POSINF_6:                                       \
   1455       case S390_DFP_ROUND_POSINF_10:                                      \
   1456          cc = S390_CC_FOR_DFP128_UCONVERT_AUX(opcode,cc_dep1,cc_dep2,6);  \
   1457          break;                                                           \
   1458       case S390_DFP_ROUND_NEGINF_7:                                       \
   1459       case S390_DFP_ROUND_NEGINF_11:                                      \
   1460          cc = S390_CC_FOR_DFP128_UCONVERT_AUX(opcode,cc_dep1,cc_dep2,7);  \
   1461          break;                                                           \
   1462       case S390_DFP_ROUND_NEAREST_TIE_TOWARD_0:                           \
   1463          cc = S390_CC_FOR_DFP128_UCONVERT_AUX(opcode,cc_dep1,cc_dep2,13); \
   1464          break;                                                           \
   1465       case S390_DFP_ROUND_AWAY_0:                                         \
   1466          cc = S390_CC_FOR_DFP128_UCONVERT_AUX(opcode,cc_dep1,cc_dep2,14); \
   1467          break;                                                           \
   1468       default:                                                            \
   1469          vpanic("unexpected dfp rounding mode");                          \
   1470       }                                                                   \
   1471       cc;                                                                 \
   1472    })
   1473 
   1474 
   1475 /* Return the value of the condition code from the supplied thunk parameters.
   1476    This is not the value of the PSW. It is the value of the 2 CC bits within
   1477    the PSW. The returned value is thusly in the interval [0:3]. */
   1478 UInt
   1479 s390_calculate_cc(ULong cc_op, ULong cc_dep1, ULong cc_dep2, ULong cc_ndep)
   1480 {
   1481 #if defined(VGA_s390x)
   1482    UInt psw;
   1483 
   1484    switch (cc_op) {
   1485 
   1486    case S390_CC_OP_BITWISE:
   1487       return S390_CC_FOR_BINARY("ogr", cc_dep1, (ULong)0);
   1488 
   1489    case S390_CC_OP_SIGNED_COMPARE:
   1490       return S390_CC_FOR_BINARY("cgr", cc_dep1, cc_dep2);
   1491 
   1492    case S390_CC_OP_UNSIGNED_COMPARE:
   1493       return S390_CC_FOR_BINARY("clgr", cc_dep1, cc_dep2);
   1494 
   1495    case S390_CC_OP_SIGNED_ADD_64:
   1496       return S390_CC_FOR_BINARY("agr", cc_dep1, cc_dep2);
   1497 
   1498    case S390_CC_OP_SIGNED_ADD_32:
   1499       return S390_CC_FOR_BINARY("ar", cc_dep1, cc_dep2);
   1500 
   1501    case S390_CC_OP_SIGNED_SUB_64:
   1502       return S390_CC_FOR_BINARY("sgr", cc_dep1, cc_dep2);
   1503 
   1504    case S390_CC_OP_SIGNED_SUB_32:
   1505       return S390_CC_FOR_BINARY("sr", cc_dep1, cc_dep2);
   1506 
   1507    case S390_CC_OP_UNSIGNED_ADD_64:
   1508       return S390_CC_FOR_BINARY("algr", cc_dep1, cc_dep2);
   1509 
   1510    case S390_CC_OP_UNSIGNED_ADD_32:
   1511       return S390_CC_FOR_BINARY("alr", cc_dep1, cc_dep2);
   1512 
   1513    case S390_CC_OP_UNSIGNED_ADDC_64:
   1514       return S390_CC_FOR_TERNARY_ADDC("alcgr", cc_dep1, cc_dep2, cc_ndep);
   1515 
   1516    case S390_CC_OP_UNSIGNED_ADDC_32:
   1517       return S390_CC_FOR_TERNARY_ADDC("alcr", cc_dep1, cc_dep2, cc_ndep);
   1518 
   1519    case S390_CC_OP_UNSIGNED_SUB_64:
   1520       return S390_CC_FOR_BINARY("slgr", cc_dep1, cc_dep2);
   1521 
   1522    case S390_CC_OP_UNSIGNED_SUB_32:
   1523       return S390_CC_FOR_BINARY("slr", cc_dep1, cc_dep2);
   1524 
   1525    case S390_CC_OP_UNSIGNED_SUBB_64:
   1526       return S390_CC_FOR_TERNARY_SUBB("slbgr", cc_dep1, cc_dep2, cc_ndep);
   1527 
   1528    case S390_CC_OP_UNSIGNED_SUBB_32:
   1529       return S390_CC_FOR_TERNARY_SUBB("slbr", cc_dep1, cc_dep2, cc_ndep);
   1530 
   1531    case S390_CC_OP_LOAD_AND_TEST:
   1532       /* Like signed comparison with 0 */
   1533       return S390_CC_FOR_BINARY("cgr", cc_dep1, (Long)0);
   1534 
   1535    case S390_CC_OP_LOAD_POSITIVE_32:
   1536       __asm__ volatile (
   1537            "lpr  %[result],%[op]\n\t"
   1538            "ipm  %[psw]\n\t"         : [psw] "=d"(psw), [result] "=d"(cc_dep1)
   1539                                      : [op] "d"(cc_dep1)
   1540                                      : "cc");
   1541       return psw >> 28;   /* cc */
   1542 
   1543    case S390_CC_OP_LOAD_POSITIVE_64:
   1544       __asm__ volatile (
   1545            "lpgr %[result],%[op]\n\t"
   1546            "ipm  %[psw]\n\t"         : [psw] "=d"(psw), [result] "=d"(cc_dep1)
   1547                                      : [op] "d"(cc_dep1)
   1548                                      : "cc");
   1549       return psw >> 28;   /* cc */
   1550 
   1551    case S390_CC_OP_TEST_UNDER_MASK_8: {
   1552       UChar value  = cc_dep1;
   1553       UChar mask   = cc_dep2;
   1554 
   1555       __asm__ volatile (
   1556            "bras %%r2,1f\n\t"             /* %r2 = address of next insn */
   1557            "tm %[value],0\n\t"            /* this is skipped, then EXecuted */
   1558            "1: ex %[mask],0(%%r2)\n\t"    /* EXecute TM after modifying mask */
   1559            "ipm %[psw]\n\t"             : [psw] "=d"(psw)
   1560                                         : [value] "m"(value), [mask] "a"(mask)
   1561                                         : "r2", "cc");
   1562       return psw >> 28;   /* cc */
   1563    }
   1564 
   1565    case S390_CC_OP_TEST_UNDER_MASK_16: {
   1566       /* Create a TMLL insn with the mask as given by cc_dep2 */
   1567       UInt insn  = (0xA701 << 16) | cc_dep2;
   1568       UInt value = cc_dep1;
   1569 
   1570       __asm__ volatile (
   1571            "lr   1,%[value]\n\t"
   1572            "lhi  2,0x10\n\t"
   1573            "ex   2,%[insn]\n\t"
   1574            "ipm  %[psw]\n\t"       : [psw] "=d"(psw)
   1575                                    : [value] "d"(value), [insn] "m"(insn)
   1576                                    : "r1", "r2", "cc");
   1577       return psw >> 28;   /* cc */
   1578    }
   1579 
   1580    case S390_CC_OP_SHIFT_LEFT_32:
   1581       __asm__ volatile (
   1582            "sla  %[op],0(%[amount])\n\t"
   1583            "ipm  %[psw]\n\t"            : [psw] "=d"(psw), [op] "+d"(cc_dep1)
   1584                                         : [amount] "a"(cc_dep2)
   1585                                         : "cc");
   1586       return psw >> 28;   /* cc */
   1587 
   1588    case S390_CC_OP_SHIFT_LEFT_64: {
   1589       Int high = (Int)(cc_dep1 >> 32);
   1590       Int low  = (Int)(cc_dep1 & 0xFFFFFFFF);
   1591 
   1592       __asm__ volatile (
   1593            "lr   2,%[high]\n\t"
   1594            "lr   3,%[low]\n\t"
   1595            "slda 2,0(%[amount])\n\t"
   1596            "ipm %[psw]\n\t"             : [psw] "=d"(psw), [high] "+d"(high),
   1597                                           [low] "+d"(low)
   1598                                         : [amount] "a"(cc_dep2)
   1599                                         : "cc", "r2", "r3");
   1600       return psw >> 28;   /* cc */
   1601    }
   1602 
   1603    case S390_CC_OP_INSERT_CHAR_MASK_32: {
   1604       Int inserted = 0;
   1605       Int msb = 0;
   1606 
   1607       if (cc_dep2 & 1) {
   1608          inserted |= cc_dep1 & 0xff;
   1609          msb = 0x80;
   1610       }
   1611       if (cc_dep2 & 2) {
   1612          inserted |= cc_dep1 & 0xff00;
   1613          msb = 0x8000;
   1614       }
   1615       if (cc_dep2 & 4) {
   1616          inserted |= cc_dep1 & 0xff0000;
   1617          msb = 0x800000;
   1618       }
   1619       if (cc_dep2 & 8) {
   1620          inserted |= cc_dep1 & 0xff000000;
   1621          msb = 0x80000000;
   1622       }
   1623 
   1624       if (inserted & msb)  // MSB is 1
   1625          return 1;
   1626       if (inserted > 0)
   1627          return 2;
   1628       return 0;
   1629    }
   1630 
   1631    case S390_CC_OP_BFP_RESULT_32:
   1632       return S390_CC_FOR_BFP_RESULT("ltebr", cc_dep1);
   1633 
   1634    case S390_CC_OP_BFP_RESULT_64:
   1635       return S390_CC_FOR_BFP_RESULT("ltdbr", cc_dep1);
   1636 
   1637    case S390_CC_OP_BFP_RESULT_128:
   1638       return S390_CC_FOR_BFP128_RESULT(cc_dep1, cc_dep2);
   1639 
   1640    case S390_CC_OP_BFP_32_TO_INT_32:
   1641       return S390_CC_FOR_BFP_CONVERT("cfebr", cc_dep1, cc_dep2);
   1642 
   1643    case S390_CC_OP_BFP_64_TO_INT_32:
   1644       return S390_CC_FOR_BFP_CONVERT("cfdbr", cc_dep1, cc_dep2);
   1645 
   1646    case S390_CC_OP_BFP_128_TO_INT_32:
   1647       return S390_CC_FOR_BFP128_CONVERT("cfxbr", cc_dep1, cc_dep2, cc_ndep);
   1648 
   1649    case S390_CC_OP_BFP_32_TO_INT_64:
   1650       return S390_CC_FOR_BFP_CONVERT("cgebr", cc_dep1, cc_dep2);
   1651 
   1652    case S390_CC_OP_BFP_64_TO_INT_64:
   1653       return S390_CC_FOR_BFP_CONVERT("cgdbr", cc_dep1, cc_dep2);
   1654 
   1655    case S390_CC_OP_BFP_128_TO_INT_64:
   1656       return S390_CC_FOR_BFP128_CONVERT("cgxbr", cc_dep1, cc_dep2, cc_ndep);
   1657 
   1658    case S390_CC_OP_BFP_TDC_32:
   1659       return S390_CC_FOR_BFP_TDC("tceb", cc_dep1, cc_dep2);
   1660 
   1661    case S390_CC_OP_BFP_TDC_64:
   1662       return S390_CC_FOR_BFP_TDC("tcdb", cc_dep1, cc_dep2);
   1663 
   1664    case S390_CC_OP_BFP_TDC_128:
   1665       return S390_CC_FOR_BFP128_TDC(cc_dep1, cc_dep2, cc_ndep);
   1666 
   1667    case S390_CC_OP_SET:
   1668       return cc_dep1;
   1669 
   1670    case S390_CC_OP_BFP_32_TO_UINT_32:
   1671       return S390_CC_FOR_BFP_UCONVERT(".insn rrf,0xb39c0000", cc_dep1, cc_dep2);
   1672 
   1673    case S390_CC_OP_BFP_64_TO_UINT_32:
   1674       return S390_CC_FOR_BFP_UCONVERT(".insn rrf,0xb39d0000", cc_dep1, cc_dep2);
   1675 
   1676    case S390_CC_OP_BFP_128_TO_UINT_32:
   1677       return S390_CC_FOR_BFP128_UCONVERT(".insn rrf,0xb39e0000", cc_dep1,
   1678                                          cc_dep2, cc_ndep);
   1679 
   1680    case S390_CC_OP_BFP_32_TO_UINT_64:
   1681       return S390_CC_FOR_BFP_UCONVERT(".insn rrf,0xb3ac0000", cc_dep1, cc_dep2);
   1682 
   1683    case S390_CC_OP_BFP_64_TO_UINT_64:
   1684       return S390_CC_FOR_BFP_UCONVERT(".insn rrf,0xb3ad0000", cc_dep1, cc_dep2);
   1685 
   1686    case S390_CC_OP_BFP_128_TO_UINT_64:
   1687       return S390_CC_FOR_BFP128_UCONVERT(".insn rrf,0xb3ae0000", cc_dep1,
   1688                                          cc_dep2, cc_ndep);
   1689 
   1690    case S390_CC_OP_DFP_RESULT_64:
   1691       return S390_CC_FOR_DFP_RESULT(cc_dep1);
   1692 
   1693    case S390_CC_OP_DFP_RESULT_128:
   1694       return S390_CC_FOR_DFP128_RESULT(cc_dep1, cc_dep2);
   1695 
   1696    case S390_CC_OP_DFP_TDC_32:  /* TDCET */
   1697       return S390_CC_FOR_DFP_TD(".insn rxe, 0xed0000000050", cc_dep1, cc_dep2);
   1698 
   1699    case S390_CC_OP_DFP_TDC_64:  /* TDCDT */
   1700       return S390_CC_FOR_DFP_TD(".insn rxe, 0xed0000000054", cc_dep1, cc_dep2);
   1701 
   1702    case S390_CC_OP_DFP_TDC_128: /* TDCXT */
   1703       return S390_CC_FOR_DFP128_TD(".insn rxe, 0xed0000000058", cc_dep1,
   1704                                    cc_dep2, cc_ndep);
   1705 
   1706    case S390_CC_OP_DFP_TDG_32:  /* TDGET */
   1707       return S390_CC_FOR_DFP_TD(".insn rxe, 0xed0000000051", cc_dep1, cc_dep2);
   1708 
   1709    case S390_CC_OP_DFP_TDG_64:  /* TDGDT */
   1710       return S390_CC_FOR_DFP_TD(".insn rxe, 0xed0000000055", cc_dep1, cc_dep2);
   1711 
   1712    case S390_CC_OP_DFP_TDG_128: /* TDGXT */
   1713       return S390_CC_FOR_DFP128_TD(".insn rxe, 0xed0000000059", cc_dep1,
   1714                                    cc_dep2, cc_ndep);
   1715 
   1716    case S390_CC_OP_DFP_64_TO_INT_32: /* CFDTR */
   1717       return S390_CC_FOR_DFP_CONVERT(".insn rrf,0xb9410000", cc_dep1, cc_dep2);
   1718 
   1719    case S390_CC_OP_DFP_128_TO_INT_32: /* CFXTR */
   1720       return S390_CC_FOR_DFP128_CONVERT(".insn rrf,0xb9490000", cc_dep1,
   1721                                         cc_dep2, cc_ndep);
   1722 
   1723    case S390_CC_OP_DFP_64_TO_INT_64: /* CGDTR */
   1724       return S390_CC_FOR_DFP_CONVERT(".insn rrf,0xb3e10000", cc_dep1, cc_dep2);
   1725 
   1726    case S390_CC_OP_DFP_128_TO_INT_64: /* CGXTR */
   1727       return S390_CC_FOR_DFP128_CONVERT(".insn rrf,0xb3e90000", cc_dep1,
   1728                                         cc_dep2, cc_ndep);
   1729 
   1730    case S390_CC_OP_DFP_64_TO_UINT_32: /* CLFDTR */
   1731       return S390_CC_FOR_DFP_UCONVERT(".insn rrf,0xb9430000", cc_dep1, cc_dep2);
   1732 
   1733    case S390_CC_OP_DFP_128_TO_UINT_32: /* CLFXTR */
   1734       return S390_CC_FOR_DFP128_UCONVERT(".insn rrf,0xb94b0000", cc_dep1,
   1735                                          cc_dep2, cc_ndep);
   1736 
   1737    case S390_CC_OP_DFP_64_TO_UINT_64: /* CLGDTR */
   1738       return S390_CC_FOR_DFP_UCONVERT(".insn rrf,0xb9420000", cc_dep1, cc_dep2);
   1739 
   1740    case S390_CC_OP_DFP_128_TO_UINT_64: /* CLGXTR */
   1741       return S390_CC_FOR_DFP128_UCONVERT(".insn rrf,0xb94a0000", cc_dep1,
   1742                                          cc_dep2, cc_ndep);
   1743 
   1744    case S390_CC_OP_PFPO_32: {
   1745       __asm__ volatile(
   1746            "ler 4, %[cc_dep1]\n\t"      /* 32 bit FR move */
   1747            "lr  0, %[cc_dep2]\n\t"      /* 32 bit GR move */
   1748            ".short 0x010a\n\t"          /* PFPO */
   1749            "ipm %[psw]\n\t"             : [psw] "=d"(psw)
   1750                                         : [cc_dep1] "f"(cc_dep1),
   1751                                           [cc_dep2] "d"(cc_dep2)
   1752                                         : "r0", "r1", "f4");
   1753       return psw >> 28;  /* cc */
   1754    }
   1755 
   1756    case S390_CC_OP_PFPO_64: {
   1757       __asm__ volatile(
   1758            "ldr 4, %[cc_dep1]\n\t"
   1759            "lr  0, %[cc_dep2]\n\t"      /* 32 bit register move */
   1760            ".short 0x010a\n\t"          /* PFPO */
   1761            "ipm %[psw]\n\t"             : [psw] "=d"(psw)
   1762                                         : [cc_dep1] "f"(cc_dep1),
   1763                                           [cc_dep2] "d"(cc_dep2)
   1764                                         : "r0", "r1", "f4");
   1765       return psw >> 28;  /* cc */
   1766    }
   1767 
   1768    case S390_CC_OP_PFPO_128: {
   1769       __asm__ volatile(
   1770            "ldr 4,%[cc_dep1]\n\t"
   1771            "ldr 6,%[cc_dep2]\n\t"
   1772            "lr  0,%[cc_ndep]\n\t"       /* 32 bit register move */
   1773            ".short 0x010a\n\t"          /* PFPO */
   1774            "ipm %[psw]\n\t"             : [psw] "=d"(psw)
   1775                                         : [cc_dep1] "f"(cc_dep1),
   1776                                           [cc_dep2] "f"(cc_dep2),
   1777                                           [cc_ndep] "d"(cc_ndep)
   1778                                         : "r0", "r1", "f0", "f2", "f4", "f6");
   1779       return psw >> 28;  /* cc */
   1780    }
   1781 
   1782    default:
   1783       break;
   1784    }
   1785 #endif
   1786    vpanic("s390_calculate_cc");
   1787 }
   1788 
   1789 
   1790 /* Note that this does *not* return a Boolean value. The result needs to be
   1791    explicitly tested against zero. */
   1792 UInt
   1793 s390_calculate_cond(ULong mask, ULong op, ULong dep1, ULong dep2, ULong ndep)
   1794 {
   1795    UInt cc = s390_calculate_cc(op, dep1, dep2, ndep);
   1796 
   1797    return ((mask << cc) & 0x8);
   1798 }
   1799 
   1800 /*------------------------------------------------------------*/
   1801 /*--- spechelper for performance                           ---*/
   1802 /*------------------------------------------------------------*/
   1803 
   1804 
   1805 /* Convenience macros */
   1806 #define unop(op,a1) IRExpr_Unop((op),(a1))
   1807 #define binop(op,a1,a2) IRExpr_Binop((op),(a1),(a2))
   1808 #define mkU64(v) IRExpr_Const(IRConst_U64(v))
   1809 #define mkU32(v) IRExpr_Const(IRConst_U32(v))
   1810 #define mkU8(v)  IRExpr_Const(IRConst_U8(v))
   1811 
   1812 
   1813 static inline Bool
   1814 isC64(IRExpr *expr)
   1815 {
   1816    return expr->tag == Iex_Const && expr->Iex.Const.con->tag == Ico_U64;
   1817 }
   1818 
   1819 
   1820 /* The returned expression is NULL if no specialization was found. In that
   1821    case the helper function will be called. Otherwise, the expression has
   1822    type Ity_I32 and a Boolean value. */
   1823 IRExpr *
   1824 guest_s390x_spechelper(const HChar *function_name, IRExpr **args,
   1825                        IRStmt **precedingStmts, Int n_precedingStmts)
   1826 {
   1827    UInt i, arity = 0;
   1828 
   1829    for (i = 0; args[i]; i++)
   1830       arity++;
   1831 
   1832 #  if 0
   1833    vex_printf("spec request:\n");
   1834    vex_printf("   %s  ", function_name);
   1835    for (i = 0; i < arity; i++) {
   1836       vex_printf("  ");
   1837       ppIRExpr(args[i]);
   1838    }
   1839    vex_printf("\n");
   1840 #  endif
   1841 
   1842    /* --------- Specialising "s390_calculate_cond" --------- */
   1843 
   1844    if (vex_streq(function_name, "s390_calculate_cond")) {
   1845       IRExpr *cond_expr, *cc_op_expr, *cc_dep1, *cc_dep2;
   1846       ULong cond, cc_op;
   1847 
   1848       vassert(arity == 5);
   1849 
   1850       cond_expr  = args[0];
   1851       cc_op_expr = args[1];
   1852 
   1853       /* The necessary requirement for all optimizations here is that the
   1854          condition and the cc_op are constant. So check that upfront. */
   1855       if (! isC64(cond_expr))  return NULL;
   1856       if (! isC64(cc_op_expr)) return NULL;
   1857 
   1858       cond    = cond_expr->Iex.Const.con->Ico.U64;
   1859       cc_op   = cc_op_expr->Iex.Const.con->Ico.U64;
   1860 
   1861       vassert(cond <= 15);
   1862 
   1863       /*
   1864         +------+---+---+---+---+
   1865         | cc   | 0 | 1 | 2 | 3 |
   1866         | cond | 8 | 4 | 2 | 1 |
   1867         +------+---+---+---+---+
   1868       */
   1869       cc_dep1 = args[2];
   1870       cc_dep2 = args[3];
   1871 
   1872       /* S390_CC_OP_SIGNED_COMPARE */
   1873       if (cc_op == S390_CC_OP_SIGNED_COMPARE) {
   1874          /*
   1875             cc == 0  --> cc_dep1 == cc_dep2   (cond == 8)
   1876             cc == 1  --> cc_dep1 <  cc_dep2   (cond == 4)
   1877             cc == 2  --> cc_dep1 >  cc_dep2   (cond == 2)
   1878 
   1879             Because cc == 3 cannot occur the rightmost bit of cond is
   1880             a don't care.
   1881          */
   1882          if (cond == 8 || cond == 8 + 1) {
   1883             return unop(Iop_1Uto32, binop(Iop_CmpEQ64, cc_dep1, cc_dep2));
   1884          }
   1885          if (cond == 4 + 2 || cond == 4 + 2 + 1) {
   1886             return unop(Iop_1Uto32, binop(Iop_CmpNE64, cc_dep1, cc_dep2));
   1887          }
   1888          if (cond == 4 || cond == 4 + 1) {
   1889             return unop(Iop_1Uto32, binop(Iop_CmpLT64S, cc_dep1, cc_dep2));
   1890          }
   1891          if (cond == 8 + 4 || cond == 8 + 4 + 1) {
   1892             return unop(Iop_1Uto32, binop(Iop_CmpLE64S, cc_dep1, cc_dep2));
   1893          }
   1894          /* cc_dep1 > cc_dep2  ---->  cc_dep2 < cc_dep1 */
   1895          if (cond == 2 || cond == 2 + 1) {
   1896             return unop(Iop_1Uto32, binop(Iop_CmpLT64S, cc_dep2, cc_dep1));
   1897          }
   1898          if (cond == 8 + 2 || cond == 8 + 2 + 1) {
   1899             return unop(Iop_1Uto32, binop(Iop_CmpLE64S, cc_dep2, cc_dep1));
   1900          }
   1901          if (cond == 8 + 4 + 2 || cond == 8 + 4 + 2 + 1) {
   1902             return mkU32(1);
   1903          }
   1904          /* Remaining case */
   1905          return mkU32(0);
   1906       }
   1907 
   1908       /* S390_CC_OP_UNSIGNED_COMPARE */
   1909       if (cc_op == S390_CC_OP_UNSIGNED_COMPARE) {
   1910          /*
   1911             cc == 0  --> cc_dep1 == cc_dep2   (cond == 8)
   1912             cc == 1  --> cc_dep1 <  cc_dep2   (cond == 4)
   1913             cc == 2  --> cc_dep1 >  cc_dep2   (cond == 2)
   1914 
   1915             Because cc == 3 cannot occur the rightmost bit of cond is
   1916             a don't care.
   1917          */
   1918          if (cond == 8 || cond == 8 + 1) {
   1919             return unop(Iop_1Uto32, binop(Iop_CmpEQ64, cc_dep1, cc_dep2));
   1920          }
   1921          if (cond == 4 + 2 || cond == 4 + 2 + 1) {
   1922             return unop(Iop_1Uto32, binop(Iop_CmpNE64, cc_dep1, cc_dep2));
   1923          }
   1924          if (cond == 4 || cond == 4 + 1) {
   1925             return unop(Iop_1Uto32, binop(Iop_CmpLT64U, cc_dep1, cc_dep2));
   1926          }
   1927          if (cond == 8 + 4 || cond == 8 + 4 + 1) {
   1928             return unop(Iop_1Uto32, binop(Iop_CmpLE64U, cc_dep1, cc_dep2));
   1929          }
   1930          /* cc_dep1 > cc_dep2  ---->  cc_dep2 < cc_dep1 */
   1931          if (cond == 2 || cond == 2 + 1) {
   1932             return unop(Iop_1Uto32, binop(Iop_CmpLT64U, cc_dep2, cc_dep1));
   1933          }
   1934          if (cond == 8 + 2 || cond == 8 + 2 + 1) {
   1935             return unop(Iop_1Uto32, binop(Iop_CmpLE64U, cc_dep2, cc_dep1));
   1936          }
   1937          if (cond == 8 + 4 + 2 || cond == 8 + 4 + 2 + 1) {
   1938             return mkU32(1);
   1939          }
   1940          /* Remaining case */
   1941          return mkU32(0);
   1942       }
   1943 
   1944       /* S390_CC_OP_LOAD_AND_TEST */
   1945       if (cc_op == S390_CC_OP_LOAD_AND_TEST) {
   1946          /*
   1947             cc == 0  --> cc_dep1 == 0   (cond == 8)
   1948             cc == 1  --> cc_dep1 <  0   (cond == 4)
   1949             cc == 2  --> cc_dep1 >  0   (cond == 2)
   1950 
   1951             Because cc == 3 cannot occur the rightmost bit of cond is
   1952             a don't care.
   1953          */
   1954          if (cond == 8 || cond == 8 + 1) {
   1955             return unop(Iop_1Uto32, binop(Iop_CmpEQ64, cc_dep1, mkU64(0)));
   1956          }
   1957          if (cond == 4 + 2 || cond == 4 + 2 + 1) {
   1958             return unop(Iop_1Uto32, binop(Iop_CmpNE64, cc_dep1, mkU64(0)));
   1959          }
   1960          if (cond == 4 || cond == 4 + 1) {
   1961             return unop(Iop_1Uto32, binop(Iop_CmpLT64S, cc_dep1, mkU64(0)));
   1962          }
   1963          if (cond == 8 + 4 || cond == 8 + 4 + 1) {
   1964             return unop(Iop_1Uto32, binop(Iop_CmpLE64S, cc_dep1, mkU64(0)));
   1965          }
   1966          /* cc_dep1 > 0  ---->  0 < cc_dep1 */
   1967          if (cond == 2 || cond == 2 + 1) {
   1968             return unop(Iop_1Uto32, binop(Iop_CmpLT64S, mkU64(0), cc_dep1));
   1969          }
   1970          if (cond == 8 + 2 || cond == 8 + 2 + 1) {
   1971             /* Special case cc_dep >= 0. Only check the MSB to avoid bogus
   1972                memcheck complaints due to gcc magic. Fixes 308427
   1973              */
   1974             return unop(Iop_64to32, binop(Iop_Xor64,
   1975                                           binop(Iop_Shr64, cc_dep1, mkU8(63)),
   1976                                           mkU64(1)));
   1977          }
   1978          if (cond == 8 + 4 + 2 || cond == 8 + 4 + 2 + 1) {
   1979             return mkU32(1);
   1980          }
   1981          /* Remaining case */
   1982          return mkU32(0);
   1983       }
   1984 
   1985       /* S390_CC_OP_BITWISE */
   1986       if (cc_op == S390_CC_OP_BITWISE) {
   1987          /*
   1988             cc_dep1 is the result of the boolean operation.
   1989 
   1990             cc == 0  --> cc_dep1 == 0   (cond == 8)
   1991             cc == 1  --> cc_dep1 != 0   (cond == 4)
   1992 
   1993             Because cc == 2 and cc == 3 cannot occur the two rightmost bits of
   1994             cond are don't cares. Therefore:
   1995 
   1996             cond == 00xx  -> always false
   1997             cond == 01xx  -> not equal
   1998             cond == 10xx  -> equal
   1999             cond == 11xx  -> always true
   2000          */
   2001          if ((cond & (8 + 4)) == 8 + 4) {
   2002             return mkU32(1);
   2003          }
   2004          if (cond & 8) {
   2005             return unop(Iop_1Uto32, binop(Iop_CmpEQ64, cc_dep1, mkU64(0)));
   2006          }
   2007          if (cond & 4) {
   2008             return unop(Iop_1Uto32, binop(Iop_CmpNE64, cc_dep1, mkU64(0)));
   2009          }
   2010          /* Remaining case */
   2011          return mkU32(0);
   2012       }
   2013 
   2014       /* S390_CC_OP_INSERT_CHAR_MASK_32
   2015          Since the mask comes from an immediate field in the opcode, we
   2016          expect the mask to be a constant here. That simplifies matters. */
   2017       if (cc_op == S390_CC_OP_INSERT_CHAR_MASK_32) {
   2018          ULong mask;
   2019          UInt imask = 0, shift = 0;
   2020          IRExpr *word;
   2021 
   2022          if (! isC64(cc_dep2)) goto missed;
   2023 
   2024          mask = cc_dep2->Iex.Const.con->Ico.U64;
   2025 
   2026          /* Extract the 32-bit value from the thunk */
   2027 
   2028          word = unop(Iop_64to32, cc_dep1);
   2029 
   2030          switch (mask) {
   2031          case 0:  shift =  0; imask = 0x00000000; break;
   2032          case 1:  shift = 24; imask = 0x000000FF; break;
   2033          case 2:  shift = 16; imask = 0x0000FF00; break;
   2034          case 3:  shift = 16; imask = 0x0000FFFF; break;
   2035          case 4:  shift =  8; imask = 0x00FF0000; break;
   2036          case 5:  shift =  8; imask = 0x00FF00FF; break;
   2037          case 6:  shift =  8; imask = 0x00FFFF00; break;
   2038          case 7:  shift =  8; imask = 0x00FFFFFF; break;
   2039          case 8:  shift =  0; imask = 0xFF000000; break;
   2040          case 9:  shift =  0; imask = 0xFF0000FF; break;
   2041          case 10: shift =  0; imask = 0xFF00FF00; break;
   2042          case 11: shift =  0; imask = 0xFF00FFFF; break;
   2043          case 12: shift =  0; imask = 0xFFFF0000; break;
   2044          case 13: shift =  0; imask = 0xFFFF00FF; break;
   2045          case 14: shift =  0; imask = 0xFFFFFF00; break;
   2046          case 15: shift =  0; imask = 0xFFFFFFFF; break;
   2047          }
   2048 
   2049          /* Select the bits that were inserted */
   2050          word = binop(Iop_And32, word, mkU32(imask));
   2051 
   2052          /* cc == 0  --> all inserted bits zero or mask == 0   (cond == 8)
   2053             cc == 1  --> leftmost inserted bit is one          (cond == 4)
   2054             cc == 2  --> leftmost inserted bit is zero and not (cond == 2)
   2055                          all inserted bits are zero
   2056 
   2057             Because cc == 0,1,2 the rightmost bit of the mask is a don't care */
   2058          if (cond == 8 || cond == 8 + 1) {
   2059             return unop(Iop_1Uto32, binop(Iop_CmpEQ32, word, mkU32(0)));
   2060          }
   2061          if (cond == 4 + 2 || cond == 4 + 2 + 1) {
   2062             return unop(Iop_1Uto32, binop(Iop_CmpNE32, word, mkU32(0)));
   2063          }
   2064 
   2065          /* Sign extend */
   2066          if (shift != 0) {
   2067             word = binop(Iop_Sar32, binop(Iop_Shl32, word, mkU8(shift)),
   2068                          mkU8(shift));
   2069          }
   2070 
   2071          if (cond == 4 || cond == 4 + 1) {  /* word < 0 */
   2072             return unop(Iop_1Uto32, binop(Iop_CmpLT32S, word, mkU32(0)));
   2073          }
   2074          if (cond == 2 || cond == 2 + 1) {  /* word > 0 */
   2075             return unop(Iop_1Uto32, binop(Iop_CmpLT32S, mkU32(0), word));
   2076          }
   2077          if (cond == 8 + 4 || cond == 8 + 4 + 1) {
   2078             return unop(Iop_1Uto32, binop(Iop_CmpLE32S, word, mkU32(0)));
   2079          }
   2080          if (cond == 8 + 2 || cond == 8 + 2 + 1) {
   2081             return unop(Iop_1Uto32, binop(Iop_CmpLE32S, mkU32(0), word));
   2082          }
   2083          if (cond == 8 + 4 + 2 || cond == 8 + 4 + 2 + 1) {
   2084             return mkU32(1);
   2085          }
   2086          /* Remaining case */
   2087          return mkU32(0);
   2088       }
   2089 
   2090       /* S390_CC_OP_TEST_UNDER_MASK_8
   2091          Since the mask comes from an immediate field in the opcode, we
   2092          expect the mask to be a constant here. That simplifies matters. */
   2093       if (cc_op == S390_CC_OP_TEST_UNDER_MASK_8) {
   2094          ULong mask16;
   2095 
   2096          if (! isC64(cc_dep2)) goto missed;
   2097 
   2098          mask16 = cc_dep2->Iex.Const.con->Ico.U64;
   2099 
   2100          /* Get rid of the mask16 == 0 case first. Some of the simplifications
   2101             below (e.g. for OVFL) only hold if mask16 == 0.  */
   2102          if (mask16 == 0) {   /* cc == 0 */
   2103             if (cond & 0x8) return mkU32(1);
   2104             return mkU32(0);
   2105          }
   2106 
   2107          /* cc == 2 is a don't care */
   2108          if (cond == 8 || cond == 8 + 2) {
   2109             return unop(Iop_1Uto32, binop(Iop_CmpEQ64,
   2110                                           binop(Iop_And64, cc_dep1, cc_dep2),
   2111                                           mkU64(0)));
   2112          }
   2113          if (cond == 7 || cond == 7 - 2) {
   2114             return unop(Iop_1Uto32, binop(Iop_CmpNE64,
   2115                                           binop(Iop_And64, cc_dep1, cc_dep2),
   2116                                           mkU64(0)));
   2117          }
   2118          if (cond == 1 || cond == 1 + 2) {
   2119             return unop(Iop_1Uto32, binop(Iop_CmpEQ64,
   2120                                           binop(Iop_And64, cc_dep1, cc_dep2),
   2121                                           cc_dep2));
   2122          }
   2123          if (cond == 14 || cond == 14 - 2) {  /* ! OVFL */
   2124             return unop(Iop_1Uto32, binop(Iop_CmpNE64,
   2125                                           binop(Iop_And64, cc_dep1, cc_dep2),
   2126                                           cc_dep2));
   2127          }
   2128          goto missed;
   2129       }
   2130 
   2131       /* S390_CC_OP_TEST_UNDER_MASK_16
   2132          Since the mask comes from an immediate field in the opcode, we
   2133          expect the mask to be a constant here. That simplifies matters. */
   2134       if (cc_op == S390_CC_OP_TEST_UNDER_MASK_16) {
   2135          ULong mask16;
   2136          UInt msb;
   2137 
   2138          if (! isC64(cc_dep2)) goto missed;
   2139 
   2140          mask16 = cc_dep2->Iex.Const.con->Ico.U64;
   2141 
   2142          /* Get rid of the mask16 == 0 case first. Some of the simplifications
   2143             below (e.g. for OVFL) only hold if mask16 == 0.  */
   2144          if (mask16 == 0) {   /* cc == 0 */
   2145             if (cond & 0x8) return mkU32(1);
   2146             return mkU32(0);
   2147          }
   2148 
   2149          if (cond == 8) {
   2150             return unop(Iop_1Uto32, binop(Iop_CmpEQ64,
   2151                                           binop(Iop_And64, cc_dep1, cc_dep2),
   2152                                           mkU64(0)));
   2153          }
   2154          if (cond == 7) {
   2155             return unop(Iop_1Uto32, binop(Iop_CmpNE64,
   2156                                           binop(Iop_And64, cc_dep1, cc_dep2),
   2157                                           mkU64(0)));
   2158          }
   2159          if (cond == 1) {
   2160             return unop(Iop_1Uto32, binop(Iop_CmpEQ64,
   2161                                           binop(Iop_And64, cc_dep1, cc_dep2),
   2162                                           mkU64(mask16)));
   2163          }
   2164          if (cond == 14) {  /* ! OVFL */
   2165             return unop(Iop_1Uto32, binop(Iop_CmpNE64,
   2166                                           binop(Iop_And64, cc_dep1, cc_dep2),
   2167                                           mkU64(mask16)));
   2168          }
   2169 
   2170          /* Find MSB in mask */
   2171          msb = 0x8000;
   2172          while (msb > mask16)
   2173             msb >>= 1;
   2174 
   2175          if (cond == 2) {  /* cc == 2 */
   2176             IRExpr *c1, *c2;
   2177 
   2178             /* (cc_dep & msb) != 0 && (cc_dep & mask16) != mask16 */
   2179             c1 = binop(Iop_CmpNE64,
   2180                        binop(Iop_And64, cc_dep1, mkU64(msb)), mkU64(0));
   2181             c2 = binop(Iop_CmpNE64,
   2182                        binop(Iop_And64, cc_dep1, cc_dep2),
   2183                        mkU64(mask16));
   2184             return binop(Iop_And32, unop(Iop_1Uto32, c1),
   2185                          unop(Iop_1Uto32, c2));
   2186          }
   2187 
   2188          if (cond == 4) {  /* cc == 1 */
   2189             IRExpr *c1, *c2;
   2190 
   2191             /* (cc_dep & msb) == 0 && (cc_dep & mask16) != 0 */
   2192             c1 = binop(Iop_CmpEQ64,
   2193                        binop(Iop_And64, cc_dep1, mkU64(msb)), mkU64(0));
   2194             c2 = binop(Iop_CmpNE64,
   2195                        binop(Iop_And64, cc_dep1, cc_dep2),
   2196                        mkU64(0));
   2197             return binop(Iop_And32, unop(Iop_1Uto32, c1),
   2198                          unop(Iop_1Uto32, c2));
   2199          }
   2200 
   2201          if (cond == 11) {  /* cc == 0,2,3 */
   2202             IRExpr *c1, *c2;
   2203 
   2204             c1 = binop(Iop_CmpNE64,
   2205                        binop(Iop_And64, cc_dep1, mkU64(msb)), mkU64(0));
   2206             c2 = binop(Iop_CmpEQ64,
   2207                        binop(Iop_And64, cc_dep1, cc_dep2),
   2208                        mkU64(0));
   2209             return binop(Iop_Or32, unop(Iop_1Uto32, c1),
   2210                          unop(Iop_1Uto32, c2));
   2211          }
   2212 
   2213          if (cond == 3) {  /* cc == 2 || cc == 3 */
   2214             return unop(Iop_1Uto32,
   2215                         binop(Iop_CmpNE64,
   2216                               binop(Iop_And64, cc_dep1, mkU64(msb)),
   2217                               mkU64(0)));
   2218          }
   2219          if (cond == 12) { /* cc == 0 || cc == 1 */
   2220             return unop(Iop_1Uto32,
   2221                         binop(Iop_CmpEQ64,
   2222                               binop(Iop_And64, cc_dep1, mkU64(msb)),
   2223                               mkU64(0)));
   2224          }
   2225          // vex_printf("TUM mask = 0x%llx\n", mask16);
   2226          goto missed;
   2227       }
   2228 
   2229       /* S390_CC_OP_UNSIGNED_SUB_64/32 */
   2230       if (cc_op == S390_CC_OP_UNSIGNED_SUB_64 ||
   2231           cc_op == S390_CC_OP_UNSIGNED_SUB_32) {
   2232          /*
   2233             cc_dep1, cc_dep2 are the zero extended left and right operands
   2234 
   2235             cc == 1  --> result != 0, borrow    (cond == 4)
   2236             cc == 2  --> result == 0, no borrow (cond == 2)
   2237             cc == 3  --> result != 0, no borrow (cond == 1)
   2238 
   2239             cc = (cc_dep1 == cc_dep2) ? 2
   2240                                       : (cc_dep1 > cc_dep2) ? 3 : 1;
   2241 
   2242             Because cc == 0 cannot occur the leftmost bit of cond is
   2243             a don't care.
   2244          */
   2245          if (cond == 1 || cond == 1 + 8) {  /* cc == 3   op2 < op1 */
   2246             return unop(Iop_1Uto32, binop(Iop_CmpLT64U, cc_dep2, cc_dep1));
   2247          }
   2248          if (cond == 2 || cond == 2 + 8) {  /* cc == 2 */
   2249             return unop(Iop_1Uto32, binop(Iop_CmpEQ64, cc_dep1, cc_dep2));
   2250          }
   2251          if (cond == 4 || cond == 4 + 8) {  /* cc == 1 */
   2252             return unop(Iop_1Uto32, binop(Iop_CmpLT64U, cc_dep1, cc_dep2));
   2253          }
   2254          if (cond == 3 || cond == 3 + 8) {  /* cc == 2 || cc == 3 */
   2255             return unop(Iop_1Uto32, binop(Iop_CmpLE64U, cc_dep2, cc_dep1));
   2256          }
   2257          if (cond == 6 || cond == 6 + 8) {  /* cc == 2 || cc == 1 */
   2258             return unop(Iop_1Uto32, binop(Iop_CmpLE64U, cc_dep1, cc_dep2));
   2259          }
   2260 
   2261          if (cond == 5 || cond == 5 + 8) {  /* cc == 3 || cc == 1 */
   2262             return unop(Iop_1Uto32, binop(Iop_CmpNE64, cc_dep1, cc_dep2));
   2263          }
   2264          if (cond == 7 || cond == 7 + 8) {
   2265             return mkU32(1);
   2266          }
   2267          /* Remaining case */
   2268          return mkU32(0);
   2269       }
   2270 
   2271       /* S390_CC_OP_UNSIGNED_ADD_64 */
   2272       if (cc_op == S390_CC_OP_UNSIGNED_ADD_64) {
   2273          /*
   2274             cc_dep1, cc_dep2 are the zero extended left and right operands
   2275 
   2276             cc == 0  --> result == 0, no carry  (cond == 8)
   2277             cc == 1  --> result != 0, no carry  (cond == 4)
   2278             cc == 2  --> result == 0, carry     (cond == 2)
   2279             cc == 3  --> result != 0, carry     (cond == 1)
   2280          */
   2281          if (cond == 8) { /* cc == 0 */
   2282             /* Both inputs are 0 */
   2283             return unop(Iop_1Uto32, binop(Iop_CmpEQ64,
   2284                                           binop(Iop_Or64, cc_dep1, cc_dep2),
   2285                                           mkU64(0)));
   2286          }
   2287          if (cond == 7) { /* cc == 1,2,3 */
   2288             /* Not both inputs are 0 */
   2289             return unop(Iop_1Uto32, binop(Iop_CmpNE64,
   2290                                           binop(Iop_Or64, cc_dep1, cc_dep2),
   2291                                           mkU64(0)));
   2292          }
   2293          if (cond == 8 + 2) {  /* cc == 0,2  -> result is zero */
   2294             return unop(Iop_1Uto32, binop(Iop_CmpEQ64,
   2295                                           binop(Iop_Add64, cc_dep1, cc_dep2),
   2296                                           mkU64(0)));
   2297          }
   2298          if (cond == 4 + 1) {  /* cc == 1,3  -> result is not zero */
   2299             return unop(Iop_1Uto32, binop(Iop_CmpNE64,
   2300                                           binop(Iop_Add64, cc_dep1, cc_dep2),
   2301                                           mkU64(0)));
   2302          }
   2303          goto missed;
   2304       }
   2305 
   2306       /* S390_CC_OP_UNSIGNED_ADD_32 */
   2307       if (cc_op == S390_CC_OP_UNSIGNED_ADD_32) {
   2308          /*
   2309             cc_dep1, cc_dep2 are the zero extended left and right operands
   2310 
   2311             cc == 0  --> result == 0, no carry  (cond == 8)
   2312             cc == 1  --> result != 0, no carry  (cond == 4)
   2313             cc == 2  --> result == 0, carry     (cond == 2)
   2314             cc == 3  --> result != 0, carry     (cond == 1)
   2315          */
   2316          if (cond == 8) { /* cc == 0 */
   2317             /* Both inputs are 0 */
   2318             return unop(Iop_1Uto32, binop(Iop_CmpEQ64,
   2319                                           binop(Iop_Or64, cc_dep1, cc_dep2),
   2320                                           mkU64(0)));
   2321          }
   2322          if (cond == 7) { /* cc == 1,2,3 */
   2323             /* Not both inputs are 0 */
   2324             return unop(Iop_1Uto32, binop(Iop_CmpNE64,
   2325                                           binop(Iop_Or64, cc_dep1, cc_dep2),
   2326                                           mkU64(0)));
   2327          }
   2328          if (cond == 8 + 2) {  /* cc == 0,2  -> result is zero */
   2329             return unop(Iop_1Uto32, binop(Iop_CmpEQ32,
   2330                                           binop(Iop_Add32,
   2331                                                 unop(Iop_64to32, cc_dep1),
   2332                                                 unop(Iop_64to32, cc_dep2)),
   2333                                           mkU32(0)));
   2334          }
   2335          if (cond == 4 + 1) {  /* cc == 1,3  -> result is not zero */
   2336             return unop(Iop_1Uto32, binop(Iop_CmpNE32,
   2337                                           binop(Iop_Add32,
   2338                                                 unop(Iop_64to32, cc_dep1),
   2339                                                 unop(Iop_64to32, cc_dep2)),
   2340                                           mkU32(0)));
   2341          }
   2342          goto missed;
   2343       }
   2344 
   2345       /* S390_CC_OP_SET */
   2346       if (cc_op == S390_CC_OP_SET) {
   2347          /* cc_dep1 is the condition code
   2348 
   2349             Return 1, if ((cond << cc_dep1) & 0x8) != 0 */
   2350 
   2351         return unop(Iop_1Uto32,
   2352                     binop(Iop_CmpNE64,
   2353                           binop(Iop_And64,
   2354                                 binop(Iop_Shl64, cond_expr,
   2355                                       unop(Iop_64to8, cc_dep1)),
   2356                                 mkU64(8)),
   2357                           mkU64(0)));
   2358       }
   2359 
   2360       goto missed;
   2361    }
   2362 
   2363    /* --------- Specialising "s390_calculate_cond" --------- */
   2364 
   2365    if (vex_streq(function_name, "s390_calculate_cc")) {
   2366       IRExpr *cc_op_expr, *cc_dep1;
   2367       ULong cc_op;
   2368 
   2369       vassert(arity == 4);
   2370 
   2371       cc_op_expr = args[0];
   2372 
   2373       /* The necessary requirement for all optimizations here is that
   2374          cc_op is constant. So check that upfront. */
   2375       if (! isC64(cc_op_expr)) return NULL;
   2376 
   2377       cc_op   = cc_op_expr->Iex.Const.con->Ico.U64;
   2378       cc_dep1 = args[1];
   2379 
   2380       if (cc_op == S390_CC_OP_BITWISE) {
   2381          return unop(Iop_1Uto32,
   2382                      binop(Iop_CmpNE64, cc_dep1, mkU64(0)));
   2383       }
   2384 
   2385       if (cc_op == S390_CC_OP_SET) {
   2386          return unop(Iop_64to32, cc_dep1);
   2387       }
   2388 
   2389       goto missed;
   2390    }
   2391 
   2392 missed:
   2393    return NULL;
   2394 }
   2395 
   2396 /*---------------------------------------------------------------*/
   2397 /*--- end                                guest_s390_helpers.c ---*/
   2398 /*---------------------------------------------------------------*/
   2399