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-2011
     12 
     13    This program is free software; you can redistribute it and/or
     14    modify it under the terms of the GNU General Public License as
     15    published by the Free Software Foundation; either version 2 of the
     16    License, or (at your option) any later version.
     17 
     18    This program is distributed in the hope that it will be useful, but
     19    WITHOUT ANY WARRANTY; without even the implied warranty of
     20    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     21    General Public License for more details.
     22 
     23    You should have received a copy of the GNU General Public License
     24    along with this program; if not, write to the Free Software
     25    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
     26    02110-1301, USA.
     27 
     28    The GNU General Public License is contained in the file COPYING.
     29 */
     30 
     31 /* Contributed by Florian Krohm */
     32 
     33 #include "libvex_basictypes.h"
     34 #include "libvex_emwarn.h"
     35 #include "libvex_guest_s390x.h"
     36 #include "libvex_ir.h"
     37 #include "libvex.h"
     38 #include "libvex_s390x_common.h"
     39 
     40 #include "main_util.h"
     41 #include "guest_generic_bb_to_IR.h"
     42 #include "guest_s390_defs.h"
     43 
     44 void
     45 LibVEX_GuestS390X_initialise(VexGuestS390XState *state)
     46 {
     47 /*------------------------------------------------------------*/
     48 /*--- Initialise ar registers                              ---*/
     49 /*------------------------------------------------------------*/
     50 
     51    state->guest_a0 = 0;
     52    state->guest_a1 = 0;
     53    state->guest_a2 = 0;
     54    state->guest_a3 = 0;
     55    state->guest_a4 = 0;
     56    state->guest_a5 = 0;
     57    state->guest_a6 = 0;
     58    state->guest_a7 = 0;
     59    state->guest_a8 = 0;
     60    state->guest_a9 = 0;
     61    state->guest_a10 = 0;
     62    state->guest_a11 = 0;
     63    state->guest_a12 = 0;
     64    state->guest_a13 = 0;
     65    state->guest_a14 = 0;
     66    state->guest_a15 = 0;
     67 
     68 /*------------------------------------------------------------*/
     69 /*--- Initialise fpr registers                             ---*/
     70 /*------------------------------------------------------------*/
     71 
     72    state->guest_f0 = 0;
     73    state->guest_f1 = 0;
     74    state->guest_f2 = 0;
     75    state->guest_f3 = 0;
     76    state->guest_f4 = 0;
     77    state->guest_f5 = 0;
     78    state->guest_f6 = 0;
     79    state->guest_f7 = 0;
     80    state->guest_f8 = 0;
     81    state->guest_f9 = 0;
     82    state->guest_f10 = 0;
     83    state->guest_f11 = 0;
     84    state->guest_f12 = 0;
     85    state->guest_f13 = 0;
     86    state->guest_f14 = 0;
     87    state->guest_f15 = 0;
     88 
     89 /*------------------------------------------------------------*/
     90 /*--- Initialise gpr registers                             ---*/
     91 /*------------------------------------------------------------*/
     92 
     93    state->guest_r0 = 0;
     94    state->guest_r1 = 0;
     95    state->guest_r2 = 0;
     96    state->guest_r3 = 0;
     97    state->guest_r4 = 0;
     98    state->guest_r5 = 0;
     99    state->guest_r6 = 0;
    100    state->guest_r7 = 0;
    101    state->guest_r8 = 0;
    102    state->guest_r9 = 0;
    103    state->guest_r10 = 0;
    104    state->guest_r11 = 0;
    105    state->guest_r12 = 0;
    106    state->guest_r13 = 0;
    107    state->guest_r14 = 0;
    108    state->guest_r15 = 0;
    109 
    110 /*------------------------------------------------------------*/
    111 /*--- Initialise S390 miscellaneous registers              ---*/
    112 /*------------------------------------------------------------*/
    113 
    114    state->guest_counter = 0;
    115    state->guest_fpc = 0;
    116    state->guest_IA = 0;
    117 
    118 /*------------------------------------------------------------*/
    119 /*--- Initialise S390 pseudo registers                     ---*/
    120 /*------------------------------------------------------------*/
    121 
    122    state->guest_SYSNO = 0;
    123 
    124 /*------------------------------------------------------------*/
    125 /*--- Initialise generic pseudo registers                  ---*/
    126 /*------------------------------------------------------------*/
    127 
    128    state->guest_NRADDR = 0;
    129    state->guest_TISTART = 0;
    130    state->guest_TILEN = 0;
    131    state->guest_IP_AT_SYSCALL = 0;
    132    state->guest_EMWARN = EmWarn_NONE;
    133 
    134 /*------------------------------------------------------------*/
    135 /*--- Initialise thunk                                     ---*/
    136 /*------------------------------------------------------------*/
    137 
    138    state->guest_CC_OP = 0;
    139    state->guest_CC_DEP1 = 0;
    140    state->guest_CC_DEP2 = 0;
    141    state->guest_CC_NDEP = 0;
    142 }
    143 
    144 
    145 /* Figure out if any part of the guest state contained in minoff
    146    .. maxoff requires precise memory exceptions.  If in doubt return
    147    True (but this is generates significantly slower code).  */
    148 Bool
    149 guest_s390x_state_requires_precise_mem_exns(Int minoff, Int maxoff)
    150 {
    151    Int lr_min = S390X_GUEST_OFFSET(guest_LR);
    152    Int lr_max = lr_min + 8 - 1;
    153    Int sp_min = S390X_GUEST_OFFSET(guest_SP);
    154    Int sp_max = sp_min + 8 - 1;
    155    Int fp_min = S390X_GUEST_OFFSET(guest_FP);
    156    Int fp_max = fp_min + 8 - 1;
    157    Int ia_min = S390X_GUEST_OFFSET(guest_IA);
    158    Int ia_max = ia_min + 8 - 1;
    159 
    160    if (maxoff < lr_min || minoff > lr_max) {
    161       /* No overlap with LR */
    162    } else {
    163       return True;
    164    }
    165 
    166    if (maxoff < sp_min || minoff > sp_max) {
    167       /* No overlap with SP */
    168    } else {
    169       return True;
    170    }
    171 
    172    if (maxoff < fp_min || minoff > fp_max) {
    173       /* No overlap with FP */
    174    } else {
    175       return True;
    176    }
    177 
    178    if (maxoff < ia_min || minoff > ia_max) {
    179       /* No overlap with IA */
    180    } else {
    181       return True;
    182    }
    183 
    184    return False;
    185 }
    186 
    187 
    188 #define ALWAYSDEFD(field)                             \
    189     { S390X_GUEST_OFFSET(field),            \
    190       (sizeof ((VexGuestS390XState*)0)->field) }
    191 
    192 VexGuestLayout s390xGuest_layout = {
    193 
    194    /* Total size of the guest state, in bytes. */
    195    .total_sizeB = sizeof(VexGuestS390XState),
    196 
    197    /* Describe the stack pointer. */
    198    .offset_SP = S390X_GUEST_OFFSET(guest_SP),
    199    .sizeof_SP = 8,
    200 
    201    /* Describe the frame pointer. */
    202    .offset_FP = S390X_GUEST_OFFSET(guest_FP),
    203    .sizeof_FP = 8,
    204 
    205    /* Describe the instruction pointer. */
    206    .offset_IP = S390X_GUEST_OFFSET(guest_IA),
    207    .sizeof_IP = 8,
    208 
    209    /* Describe any sections to be regarded by Memcheck as
    210       'always-defined'. */
    211    .n_alwaysDefd = 9,
    212 
    213    /* Flags thunk: OP and NDEP are always defined, whereas DEP1
    214       and DEP2 have to be tracked.  See detailed comment in
    215       gdefs.h on meaning of thunk fields. */
    216    .alwaysDefd = {
    217       /*  0 */ ALWAYSDEFD(guest_CC_OP),     /* generic */
    218       /*  1 */ ALWAYSDEFD(guest_CC_NDEP),   /* generic */
    219       /*  2 */ ALWAYSDEFD(guest_EMWARN),    /* generic */
    220       /*  3 */ ALWAYSDEFD(guest_TISTART),   /* generic */
    221       /*  4 */ ALWAYSDEFD(guest_TILEN),     /* generic */
    222       /*  5 */ ALWAYSDEFD(guest_IP_AT_SYSCALL), /* generic */
    223       /*  6 */ ALWAYSDEFD(guest_IA),        /* control reg */
    224       /*  7 */ ALWAYSDEFD(guest_fpc),       /* control reg */
    225       /*  8 */ ALWAYSDEFD(guest_counter),   /* internal usage register */
    226    }
    227 };
    228 
    229 /*------------------------------------------------------------*/
    230 /*--- Dirty helper for invalid opcode 00                   ---*/
    231 /*------------------------------------------------------------*/
    232 #if defined(VGA_s390x)
    233 void
    234 s390x_dirtyhelper_00(VexGuestS390XState *guest_state)
    235 {
    236    /* Avoid infinite loop in case SIGILL is caught. See also
    237       none/tests/s390x/op_exception.c */
    238    guest_state->guest_IA += 2;
    239 
    240    asm volatile(".hword 0\n");
    241 }
    242 #else
    243 void s390x_dirtyhelper_00(VexGuestS390XState *guest_state) { }
    244 #endif
    245 
    246 /*------------------------------------------------------------*/
    247 /*--- Dirty helper for EXecute                             ---*/
    248 /*------------------------------------------------------------*/
    249 void
    250 s390x_dirtyhelper_EX(ULong torun)
    251 {
    252    last_execute_target = torun;
    253 }
    254 
    255 
    256 /*------------------------------------------------------------*/
    257 /*--- Dirty helper for Clock instructions                  ---*/
    258 /*------------------------------------------------------------*/
    259 #if defined(VGA_s390x)
    260 ULong s390x_dirtyhelper_STCK(ULong *addr)
    261 {
    262    int cc;
    263 
    264    asm volatile("stck %0\n"
    265                 "ipm %1\n"
    266                 "srl %1,28\n"
    267                 : "+Q" (*addr), "=d" (cc) : : "cc");
    268    return cc;
    269 }
    270 
    271 ULong s390x_dirtyhelper_STCKE(ULong *addr)
    272 {
    273    int cc;
    274 
    275    asm volatile("stcke %0\n"
    276                 "ipm %1\n"
    277                 "srl %1,28\n"
    278                 : "+Q" (*addr), "=d" (cc) : : "cc");
    279    return cc;
    280 }
    281 
    282 ULong s390x_dirtyhelper_STCKF(ULong *addr)
    283 {
    284    int cc;
    285 
    286    asm volatile(".insn s,0xb27c0000,%0\n"
    287                 "ipm %1\n"
    288                 "srl %1,28\n"
    289                 : "+Q" (*addr), "=d" (cc) : : "cc");
    290    return cc;
    291 }
    292 #else
    293 ULong s390x_dirtyhelper_STCK(ULong *addr)  {return 3;}
    294 ULong s390x_dirtyhelper_STCKF(ULong *addr) {return 3;}
    295 ULong s390x_dirtyhelper_STCKE(ULong *addr) {return 3;}
    296 #endif /* VGA_s390x */
    297 
    298 /*------------------------------------------------------------*/
    299 /*--- Dirty helper for Store Facility instruction          ---*/
    300 /*------------------------------------------------------------*/
    301 #if defined(VGA_s390x)
    302 ULong
    303 s390x_dirtyhelper_STFLE(VexGuestS390XState *guest_state, HWord addr)
    304 {
    305    ULong hoststfle[S390_NUM_FACILITY_DW], cc, num_dw, i;
    306    register ULong reg0 asm("0") = guest_state->guest_r0 & 0xF;  /* r0[56:63] */
    307 
    308    /* We cannot store more than S390_NUM_FACILITY_DW
    309       (and it makes not much sense to do so anyhow) */
    310    if (reg0 > S390_NUM_FACILITY_DW - 1)
    311       reg0 = S390_NUM_FACILITY_DW - 1;
    312 
    313    num_dw = reg0 + 1;  /* number of double words written */
    314 
    315    asm volatile(" .insn s,0xb2b00000,%0\n"   /* stfle */
    316                 "ipm    %2\n"
    317                 "srl    %2,28\n"
    318                 : "=m" (hoststfle), "+d"(reg0), "=d"(cc) : : "cc", "memory");
    319 
    320    /* Update guest register 0  with what STFLE set r0 to */
    321    guest_state->guest_r0 = reg0;
    322 
    323    for (i = 0; i < num_dw; ++i)
    324       ((ULong *)addr)[i] = hoststfle[i];
    325 
    326    return cc;
    327 }
    328 
    329 #else
    330 
    331 ULong
    332 s390x_dirtyhelper_STFLE(VexGuestS390XState *guest_state, HWord addr)
    333 {
    334    return 3;
    335 }
    336 #endif /* VGA_s390x */
    337 
    338 /*------------------------------------------------------------*/
    339 /*--- Helper for condition code.                           ---*/
    340 /*------------------------------------------------------------*/
    341 
    342 #define S390_CC_FOR_BINARY(opcode,cc_dep1,cc_dep2) \
    343 ({ \
    344    __asm__ volatile ( \
    345         opcode " %[op1],%[op2]\n\t" \
    346         "ipm %[psw]\n\t"           : [psw] "=d"(psw), [op1] "+d"(cc_dep1) \
    347                                    : [op2] "d"(cc_dep2) \
    348                                    : "cc");\
    349    psw >> 28;   /* cc */ \
    350 })
    351 
    352 #define S390_CC_FOR_TERNARY_SUBB(opcode,cc_dep1,cc_dep2,cc_ndep) \
    353 ({ \
    354    /* Recover the original DEP2 value. See comment near s390_cc_thunk_put3 \
    355       for rationale. */ \
    356    cc_dep2 = cc_dep2 ^ cc_ndep; \
    357    __asm__ volatile ( \
    358 	"lghi 0,1\n\t" \
    359 	"sr 0,%[op3]\n\t" /* borrow to cc */ \
    360         opcode " %[op1],%[op2]\n\t" /* then redo the op */\
    361         "ipm %[psw]\n\t"           : [psw] "=d"(psw), [op1] "+&d"(cc_dep1) \
    362                                    : [op2] "d"(cc_dep2), [op3] "d"(cc_ndep) \
    363                                    : "0", "cc");\
    364    psw >> 28;   /* cc */ \
    365 })
    366 
    367 #define S390_CC_FOR_TERNARY_ADDC(opcode,cc_dep1,cc_dep2,cc_ndep) \
    368 ({ \
    369    /* Recover the original DEP2 value. See comment near s390_cc_thunk_put3 \
    370       for rationale. */ \
    371    cc_dep2 = cc_dep2 ^ cc_ndep; \
    372    __asm__ volatile ( \
    373 	"lgfr 0,%[op3]\n\t" /* first load cc_ndep */ \
    374 	"aghi 0,0\n\t" /* and convert it into a cc */ \
    375         opcode " %[op1],%[op2]\n\t" /* then redo the op */\
    376         "ipm %[psw]\n\t"           : [psw] "=d"(psw), [op1] "+&d"(cc_dep1) \
    377                                    : [op2] "d"(cc_dep2), [op3] "d"(cc_ndep) \
    378                                    : "0", "cc");\
    379    psw >> 28;   /* cc */ \
    380 })
    381 
    382 
    383 #define S390_CC_FOR_BFP_RESULT(opcode,cc_dep1) \
    384 ({ \
    385    __asm__ volatile ( \
    386         opcode " 0,%[op]\n\t" \
    387         "ipm %[psw]\n\t"           : [psw] "=d"(psw) \
    388                                    : [op]  "f"(cc_dep1) \
    389                                    : "cc", "f0");\
    390    psw >> 28;   /* cc */ \
    391 })
    392 
    393 #define S390_CC_FOR_BFP128_RESULT(hi,lo) \
    394 ({ \
    395    __asm__ volatile ( \
    396         "ldr   4,%[high]\n\t" \
    397         "ldr   6,%[low]\n\t" \
    398         "ltxbr 0,4\n\t" \
    399         "ipm %[psw]\n\t"           : [psw] "=d"(psw) \
    400                                    : [high] "f"(hi), [low] "f"(lo) \
    401                                    : "cc", "f0", "f2", "f4", "f6");\
    402    psw >> 28;   /* cc */ \
    403 })
    404 
    405 #define S390_CC_FOR_BFP_CONVERT(opcode,cc_dep1) \
    406 ({ \
    407    __asm__ volatile ( \
    408         opcode " 0,0,%[op]\n\t" \
    409         "ipm %[psw]\n\t"           : [psw] "=d"(psw) \
    410                                    : [op]  "f"(cc_dep1) \
    411                                    : "cc", "r0");\
    412    psw >> 28;   /* cc */ \
    413 })
    414 
    415 #define S390_CC_FOR_BFP128_CONVERT(opcode,hi,lo) \
    416 ({ \
    417    __asm__ volatile ( \
    418         "ldr   4,%[high]\n\t" \
    419         "ldr   6,%[low]\n\t" \
    420         opcode " 0,0,4\n\t" \
    421         "ipm %[psw]\n\t"           : [psw] "=d"(psw) \
    422                                    : [high] "f"(hi), [low] "f"(lo) \
    423                                    : "cc", "r0", "f4", "f6");\
    424    psw >> 28;   /* cc */ \
    425 })
    426 
    427 #define S390_CC_FOR_BFP_TDC(opcode,cc_dep1,cc_dep2) \
    428 ({ \
    429    __asm__ volatile ( \
    430         opcode " %[value],0(%[class])\n\t" \
    431         "ipm %[psw]\n\t"           : [psw] "=d"(psw) \
    432                                    : [value] "f"(cc_dep1), \
    433                                      [class] "a"(cc_dep2)  \
    434                                    : "cc");\
    435    psw >> 28;   /* cc */ \
    436 })
    437 
    438 #define S390_CC_FOR_BFP128_TDC(cc_dep1,cc_dep2,cc_ndep) \
    439 ({ \
    440    /* Recover the original DEP2 value. See comment near s390_cc_thunk_put1f128Z \
    441       for rationale. */ \
    442    cc_dep2 = cc_dep2 ^ cc_ndep; \
    443    __asm__ volatile ( \
    444         "ldr  4,%[high]\n\t" \
    445         "ldr  6,%[low]\n\t" \
    446         "tcxb 4,0(%[class])\n\t" \
    447         "ipm  %[psw]\n\t"          : [psw] "=d"(psw) \
    448                                    : [high] "f"(cc_dep1), [low] "f"(cc_dep2), \
    449                                      [class] "a"(cc_ndep)  \
    450                                    : "cc", "f4", "f6");\
    451    psw >> 28;   /* cc */ \
    452 })
    453 
    454 
    455 /* Return the value of the condition code from the supplied thunk parameters.
    456    This is not the value of the PSW. It is the value of the 2 CC bits within
    457    the PSW. The returned value is thusly in the interval [0:3]. */
    458 UInt
    459 s390_calculate_cc(ULong cc_op, ULong cc_dep1, ULong cc_dep2, ULong cc_ndep)
    460 {
    461 #if defined(VGA_s390x)
    462    UInt psw;
    463 
    464    switch (cc_op) {
    465 
    466    case S390_CC_OP_BITWISE:
    467       return S390_CC_FOR_BINARY("ogr", cc_dep1, (ULong)0);
    468 
    469    case S390_CC_OP_SIGNED_COMPARE:
    470       return S390_CC_FOR_BINARY("cgr", cc_dep1, cc_dep2);
    471 
    472    case S390_CC_OP_UNSIGNED_COMPARE:
    473       return S390_CC_FOR_BINARY("clgr", cc_dep1, cc_dep2);
    474 
    475    case S390_CC_OP_SIGNED_ADD_64:
    476       return S390_CC_FOR_BINARY("agr", cc_dep1, cc_dep2);
    477 
    478    case S390_CC_OP_SIGNED_ADD_32:
    479       return S390_CC_FOR_BINARY("ar", cc_dep1, cc_dep2);
    480 
    481    case S390_CC_OP_SIGNED_SUB_64:
    482       return S390_CC_FOR_BINARY("sgr", cc_dep1, cc_dep2);
    483 
    484    case S390_CC_OP_SIGNED_SUB_32:
    485       return S390_CC_FOR_BINARY("sr", cc_dep1, cc_dep2);
    486 
    487    case S390_CC_OP_UNSIGNED_ADD_64:
    488       return S390_CC_FOR_BINARY("algr", cc_dep1, cc_dep2);
    489 
    490    case S390_CC_OP_UNSIGNED_ADD_32:
    491       return S390_CC_FOR_BINARY("alr", cc_dep1, cc_dep2);
    492 
    493    case S390_CC_OP_UNSIGNED_ADDC_64:
    494       return S390_CC_FOR_TERNARY_ADDC("alcgr", cc_dep1, cc_dep2, cc_ndep);
    495 
    496    case S390_CC_OP_UNSIGNED_ADDC_32:
    497       return S390_CC_FOR_TERNARY_ADDC("alcr", cc_dep1, cc_dep2, cc_ndep);
    498 
    499    case S390_CC_OP_UNSIGNED_SUB_64:
    500       return S390_CC_FOR_BINARY("slgr", cc_dep1, cc_dep2);
    501 
    502    case S390_CC_OP_UNSIGNED_SUB_32:
    503       return S390_CC_FOR_BINARY("slr", cc_dep1, cc_dep2);
    504 
    505    case S390_CC_OP_UNSIGNED_SUBB_64:
    506       return S390_CC_FOR_TERNARY_SUBB("slbgr", cc_dep1, cc_dep2, cc_ndep);
    507 
    508    case S390_CC_OP_UNSIGNED_SUBB_32:
    509       return S390_CC_FOR_TERNARY_SUBB("slbr", cc_dep1, cc_dep2, cc_ndep);
    510 
    511    case S390_CC_OP_LOAD_AND_TEST:
    512       /* Like signed comparison with 0 */
    513       return S390_CC_FOR_BINARY("cgr", cc_dep1, (Long)0);
    514 
    515    case S390_CC_OP_TEST_AND_SET:
    516       /* Shift the sign bit into the LSB. Note, that the tested value is an
    517          8-bit value which has been zero-extended to 32/64 bit. */
    518       return cc_dep1 >> 7;
    519 
    520    case S390_CC_OP_LOAD_POSITIVE_32:
    521       __asm__ volatile (
    522            "lpr  %[result],%[op]\n\t"
    523            "ipm  %[psw]\n\t"            : [psw] "=d"(psw), [result] "=d"(cc_dep1)
    524                                         : [op] "d"(cc_dep1)
    525                                         : "cc");
    526       return psw >> 28;   /* cc */
    527 
    528    case S390_CC_OP_LOAD_POSITIVE_64:
    529       __asm__ volatile (
    530            "lpgr %[result],%[op]\n\t"
    531            "ipm  %[psw]\n\t"            : [psw] "=d"(psw), [result] "=d"(cc_dep1)
    532                                         : [op] "d"(cc_dep1)
    533                                         : "cc");
    534       return psw >> 28;   /* cc */
    535 
    536    case S390_CC_OP_TEST_UNDER_MASK_8: {
    537       UChar value  = cc_dep1;
    538       UChar mask   = cc_dep2;
    539 
    540       __asm__ volatile (
    541            "bras %%r2,1f\n\t"             /* %r2 = address of next insn */
    542            "tm %[value],0\n\t"            /* this is skipped, then EXecuted */
    543            "1: ex %[mask],0(%%r2)\n\t"    /* EXecute TM after modifying mask */
    544            "ipm %[psw]\n\t"             : [psw] "=d"(psw)
    545                                         : [value] "m"(value), [mask] "a"(mask)
    546                                         : "r2", "cc");
    547       return psw >> 28;   /* cc */
    548    }
    549 
    550    case S390_CC_OP_TEST_UNDER_MASK_16: {
    551       /* Create a TMLL insn with the mask as given by cc_dep2 */
    552       UInt insn  = (0xA701 << 16) | cc_dep2;
    553       UInt value = cc_dep1;
    554 
    555       __asm__ volatile (
    556            "lr   1,%[value]\n\t"
    557            "lhi  2,0x10\n\t"
    558            "ex   2,%[insn]\n\t"
    559            "ipm  %[psw]\n\t"       : [psw] "=d"(psw)
    560                                    : [value] "d"(value), [insn] "m"(insn)
    561                                    : "r1", "r2", "cc");
    562       return psw >> 28;   /* cc */
    563    }
    564 
    565    case S390_CC_OP_SHIFT_LEFT_32:
    566       __asm__ volatile (
    567            "sla  %[op],0(%[amount])\n\t"
    568            "ipm  %[psw]\n\t"            : [psw] "=d"(psw), [op] "+d"(cc_dep1)
    569                                         : [amount] "a"(cc_dep2)
    570                                         : "cc");
    571       return psw >> 28;   /* cc */
    572 
    573    case S390_CC_OP_SHIFT_LEFT_64: {
    574       Int high = (Int)(cc_dep1 >> 32);
    575       Int low  = (Int)(cc_dep1 & 0xFFFFFFFF);
    576 
    577       __asm__ volatile (
    578            "lr   2,%[high]\n\t"
    579            "lr   3,%[low]\n\t"
    580            "slda 2,0(%[amount])\n\t"
    581            "ipm %[psw]\n\t"             : [psw] "=d"(psw), [high] "+d"(high), [low] "+d"(low)
    582                                         : [amount] "a"(cc_dep2)
    583                                         : "cc", "r2", "r3");
    584       return psw >> 28;   /* cc */
    585    }
    586 
    587    case S390_CC_OP_INSERT_CHAR_MASK_32: {
    588       Int inserted = 0;
    589       Int msb = 0;
    590 
    591       if (cc_dep2 & 1) {
    592          inserted |= cc_dep1 & 0xff;
    593          msb = 0x80;
    594       }
    595       if (cc_dep2 & 2) {
    596          inserted |= cc_dep1 & 0xff00;
    597          msb = 0x8000;
    598       }
    599       if (cc_dep2 & 4) {
    600          inserted |= cc_dep1 & 0xff0000;
    601          msb = 0x800000;
    602       }
    603       if (cc_dep2 & 8) {
    604          inserted |= cc_dep1 & 0xff000000;
    605          msb = 0x80000000;
    606       }
    607 
    608       if (inserted & msb)  // MSB is 1
    609          return 1;
    610       if (inserted > 0)
    611          return 2;
    612       return 0;
    613    }
    614 
    615    case S390_CC_OP_BFP_RESULT_32:
    616       return S390_CC_FOR_BFP_RESULT("ltebr", cc_dep1);
    617 
    618    case S390_CC_OP_BFP_RESULT_64:
    619       return S390_CC_FOR_BFP_RESULT("ltdbr", cc_dep1);
    620 
    621    case S390_CC_OP_BFP_RESULT_128:
    622       return S390_CC_FOR_BFP128_RESULT(cc_dep1, cc_dep2);
    623 
    624    case S390_CC_OP_BFP_32_TO_INT_32:
    625       return S390_CC_FOR_BFP_CONVERT("cfebr", cc_dep1);
    626 
    627    case S390_CC_OP_BFP_64_TO_INT_32:
    628       return S390_CC_FOR_BFP_CONVERT("cfdbr", cc_dep1);
    629 
    630    case S390_CC_OP_BFP_128_TO_INT_32:
    631       return S390_CC_FOR_BFP128_CONVERT("cfxbr", cc_dep1, cc_dep2);
    632 
    633    case S390_CC_OP_BFP_32_TO_INT_64:
    634       return S390_CC_FOR_BFP_CONVERT("cgebr", cc_dep1);
    635 
    636    case S390_CC_OP_BFP_64_TO_INT_64:
    637       return S390_CC_FOR_BFP_CONVERT("cgdbr", cc_dep1);
    638 
    639    case S390_CC_OP_BFP_128_TO_INT_64:
    640       return S390_CC_FOR_BFP128_CONVERT("cgxbr", cc_dep1, cc_dep2);
    641 
    642    case S390_CC_OP_BFP_TDC_32:
    643       return S390_CC_FOR_BFP_TDC("tceb", cc_dep1, cc_dep2);
    644 
    645    case S390_CC_OP_BFP_TDC_64:
    646       return S390_CC_FOR_BFP_TDC("tcdb", cc_dep1, cc_dep2);
    647 
    648    case S390_CC_OP_BFP_TDC_128:
    649       return S390_CC_FOR_BFP128_TDC(cc_dep1, cc_dep2, cc_ndep);
    650 
    651    case S390_CC_OP_SET:
    652       return cc_dep1;
    653 
    654    default:
    655       break;
    656    }
    657 #endif
    658    vpanic("s390_calculate_cc");
    659 }
    660 
    661 
    662 UInt
    663 s390_calculate_icc(ULong op, ULong dep1, ULong dep2)
    664 {
    665    return s390_calculate_cc(op, dep1, dep2, 0 /* unused */);
    666 }
    667 
    668 
    669 /* Note that this does *not* return a Boolean value. The result needs to be
    670    explicitly tested against zero. */
    671 UInt
    672 s390_calculate_cond(ULong mask, ULong op, ULong dep1, ULong dep2, ULong ndep)
    673 {
    674    UInt cc = s390_calculate_cc(op, dep1, dep2, ndep);
    675 
    676    return ((mask << cc) & 0x8);
    677 }
    678 
    679 /*------------------------------------------------------------*/
    680 /*--- spechelper for performance                           ---*/
    681 /*------------------------------------------------------------*/
    682 
    683 
    684 /* Convenience macros */
    685 #define unop(op,a1) IRExpr_Unop((op),(a1))
    686 #define binop(op,a1,a2) IRExpr_Binop((op),(a1),(a2))
    687 #define mkU64(v) IRExpr_Const(IRConst_U64(v))
    688 #define mkU32(v) IRExpr_Const(IRConst_U32(v))
    689 #define mkU8(v)  IRExpr_Const(IRConst_U8(v))
    690 
    691 
    692 static inline Bool
    693 isC64(IRExpr *expr)
    694 {
    695    return expr->tag == Iex_Const && expr->Iex.Const.con->tag == Ico_U64;
    696 }
    697 
    698 
    699 /* The returned expression is NULL if no specialization was found. In that
    700    case the helper function will be called. Otherwise, the expression has
    701    type Ity_I32 and a Boolean value. */
    702 IRExpr *
    703 guest_s390x_spechelper(HChar *function_name, IRExpr **args,
    704                        IRStmt **precedingStmts, Int n_precedingStmts)
    705 {
    706    UInt i, arity = 0;
    707 
    708    for (i = 0; args[i]; i++)
    709       arity++;
    710 
    711 #  if 0
    712    vex_printf("spec request:\n");
    713    vex_printf("   %s  ", function_name);
    714    for (i = 0; i < arity; i++) {
    715       vex_printf("  ");
    716       ppIRExpr(args[i]);
    717    }
    718    vex_printf("\n");
    719 #  endif
    720 
    721    /* --------- Specialising "s390_calculate_cond" --------- */
    722 
    723    if (vex_streq(function_name, "s390_calculate_cond")) {
    724       IRExpr *cond_expr, *cc_op_expr, *cc_dep1, *cc_dep2;
    725       ULong cond, cc_op;
    726 
    727       vassert(arity == 5);
    728 
    729       cond_expr  = args[0];
    730       cc_op_expr = args[1];
    731 
    732       /* The necessary requirement for all optimizations here is that the
    733          condition and the cc_op are constant. So check that upfront. */
    734       if (! isC64(cond_expr))  return NULL;
    735       if (! isC64(cc_op_expr)) return NULL;
    736 
    737       cond    = cond_expr->Iex.Const.con->Ico.U64;
    738       cc_op   = cc_op_expr->Iex.Const.con->Ico.U64;
    739 
    740       vassert(cond <= 15);
    741 
    742       /*
    743         +------+---+---+---+---+
    744         | cc   | 0 | 1 | 2 | 3 |
    745         | cond | 8 | 4 | 2 | 1 |
    746         +------+---+---+---+---+
    747       */
    748       cc_dep1 = args[2];
    749       cc_dep2 = args[3];
    750 
    751       /* S390_CC_OP_SIGNED_COMPARE */
    752       if (cc_op == S390_CC_OP_SIGNED_COMPARE) {
    753          /*
    754             cc == 0  --> cc_dep1 == cc_dep2   (cond == 8)
    755             cc == 1  --> cc_dep1 <  cc_dep2   (cond == 4)
    756             cc == 2  --> cc_dep1 >  cc_dep2   (cond == 2)
    757 
    758             Because cc == 3 cannot occur the rightmost bit of cond is
    759             a don't care.
    760          */
    761          if (cond == 8 || cond == 8 + 1) {
    762             return unop(Iop_1Uto32, binop(Iop_CmpEQ64, cc_dep1, cc_dep2));
    763          }
    764          if (cond == 4 + 2 || cond == 4 + 2 + 1) {
    765             return unop(Iop_1Uto32, binop(Iop_CmpNE64, cc_dep1, cc_dep2));
    766          }
    767          if (cond == 4 || cond == 4 + 1) {
    768             return unop(Iop_1Uto32, binop(Iop_CmpLT64S, cc_dep1, cc_dep2));
    769          }
    770          if (cond == 8 + 4 || cond == 8 + 4 + 1) {
    771             return unop(Iop_1Uto32, binop(Iop_CmpLE64S, cc_dep1, cc_dep2));
    772          }
    773          /* cc_dep1 > cc_dep2  ---->  cc_dep2 < cc_dep1 */
    774          if (cond == 2 || cond == 2 + 1) {
    775             return unop(Iop_1Uto32, binop(Iop_CmpLT64S, cc_dep2, cc_dep1));
    776          }
    777          if (cond == 8 + 2 || cond == 8 + 2 + 1) {
    778             return unop(Iop_1Uto32, binop(Iop_CmpLE64S, cc_dep2, cc_dep1));
    779          }
    780          if (cond == 8 + 4 + 2 || cond == 8 + 4 + 2 + 1) {
    781             return mkU32(1);
    782          }
    783          /* Remaining case */
    784          return mkU32(0);
    785       }
    786 
    787       /* S390_CC_OP_UNSIGNED_COMPARE */
    788       if (cc_op == S390_CC_OP_UNSIGNED_COMPARE) {
    789          /*
    790             cc == 0  --> cc_dep1 == cc_dep2   (cond == 8)
    791             cc == 1  --> cc_dep1 <  cc_dep2   (cond == 4)
    792             cc == 2  --> cc_dep1 >  cc_dep2   (cond == 2)
    793 
    794             Because cc == 3 cannot occur the rightmost bit of cond is
    795             a don't care.
    796          */
    797          if (cond == 8 || cond == 8 + 1) {
    798             return unop(Iop_1Uto32, binop(Iop_CmpEQ64, cc_dep1, cc_dep2));
    799          }
    800          if (cond == 4 + 2 || cond == 4 + 2 + 1) {
    801             return unop(Iop_1Uto32, binop(Iop_CmpNE64, cc_dep1, cc_dep2));
    802          }
    803          if (cond == 4 || cond == 4 + 1) {
    804             return unop(Iop_1Uto32, binop(Iop_CmpLT64U, cc_dep1, cc_dep2));
    805          }
    806          if (cond == 8 + 4 || cond == 8 + 4 + 1) {
    807             return unop(Iop_1Uto32, binop(Iop_CmpLE64U, cc_dep1, cc_dep2));
    808          }
    809          /* cc_dep1 > cc_dep2  ---->  cc_dep2 < cc_dep1 */
    810          if (cond == 2 || cond == 2 + 1) {
    811             return unop(Iop_1Uto32, binop(Iop_CmpLT64U, cc_dep2, cc_dep1));
    812          }
    813          if (cond == 8 + 2 || cond == 8 + 2 + 1) {
    814             return unop(Iop_1Uto32, binop(Iop_CmpLE64U, cc_dep2, cc_dep1));
    815          }
    816          if (cond == 8 + 4 + 2 || cond == 8 + 4 + 2 + 1) {
    817             return mkU32(1);
    818          }
    819          /* Remaining case */
    820          return mkU32(0);
    821       }
    822 
    823       /* S390_CC_OP_LOAD_AND_TEST */
    824       if (cc_op == S390_CC_OP_LOAD_AND_TEST) {
    825          /*
    826             cc == 0  --> cc_dep1 == 0   (cond == 8)
    827             cc == 1  --> cc_dep1 <  0   (cond == 4)
    828             cc == 2  --> cc_dep1 >  0   (cond == 2)
    829 
    830             Because cc == 3 cannot occur the rightmost bit of cond is
    831             a don't care.
    832          */
    833          if (cond == 8 || cond == 8 + 1) {
    834             return unop(Iop_1Uto32, binop(Iop_CmpEQ64, cc_dep1, mkU64(0)));
    835          }
    836          if (cond == 4 + 2 || cond == 4 + 2 + 1) {
    837             return unop(Iop_1Uto32, binop(Iop_CmpNE64, cc_dep1, mkU64(0)));
    838          }
    839          if (cond == 4 || cond == 4 + 1) {
    840             return unop(Iop_1Uto32, binop(Iop_CmpLT64S, cc_dep1, mkU64(0)));
    841          }
    842          if (cond == 8 + 4 || cond == 8 + 4 + 1) {
    843             return unop(Iop_1Uto32, binop(Iop_CmpLE64S, cc_dep1, mkU64(0)));
    844          }
    845          /* cc_dep1 > 0  ---->  0 < cc_dep1 */
    846          if (cond == 2 || cond == 2 + 1) {
    847             return unop(Iop_1Uto32, binop(Iop_CmpLT64S, mkU64(0), cc_dep1));
    848          }
    849          if (cond == 8 + 2 || cond == 8 + 2 + 1) {
    850             return unop(Iop_1Uto32, binop(Iop_CmpLE64S, mkU64(0), cc_dep1));
    851          }
    852          if (cond == 8 + 4 + 2 || cond == 8 + 4 + 2 + 1) {
    853             return mkU32(1);
    854          }
    855          /* Remaining case */
    856          return mkU32(0);
    857       }
    858 
    859       /* S390_CC_OP_BITWISE */
    860       if (cc_op == S390_CC_OP_BITWISE) {
    861          /*
    862             cc_dep1 is the result of the boolean operation.
    863 
    864             cc == 0  --> cc_dep1 == 0   (cond == 8)
    865             cc == 1  --> cc_dep1 != 0   (cond == 4)
    866 
    867             Because cc == 2 and cc == 3 cannot occur the two rightmost bits of
    868             cond are don't cares. Therefore:
    869 
    870             cond == 00xx  -> always false
    871             cond == 01xx  -> not equal
    872             cond == 10xx  -> equal
    873             cond == 11xx  -> always true
    874          */
    875          if ((cond & (8 + 4)) == 8 + 4) {
    876             return mkU32(1);
    877          }
    878          if (cond & 8) {
    879             return unop(Iop_1Uto32, binop(Iop_CmpEQ64, cc_dep1, mkU64(0)));
    880          }
    881          if (cond & 4) {
    882             return unop(Iop_1Uto32, binop(Iop_CmpNE64, cc_dep1, mkU64(0)));
    883          }
    884          /* Remaining case */
    885          return mkU32(0);
    886       }
    887 
    888       /* S390_CC_OP_INSERT_CHAR_MASK_32
    889          Since the mask comes from an immediate field in the opcode, we
    890          expect the mask to be a constant here. That simplifies matters. */
    891       if (cc_op == S390_CC_OP_INSERT_CHAR_MASK_32) {
    892          ULong mask;
    893          UInt imask = 0, shift = 0;
    894          IRExpr *word;
    895 
    896          if (! isC64(cc_dep2)) goto missed;
    897 
    898          mask = cc_dep2->Iex.Const.con->Ico.U64;
    899 
    900          /* Extract the 32-bit value from the thunk */
    901 
    902          word = unop(Iop_64to32, cc_dep1);
    903 
    904          switch (mask) {
    905          case 0:  shift =  0; imask = 0x00000000; break;
    906          case 1:  shift = 24; imask = 0x000000FF; break;
    907          case 2:  shift = 16; imask = 0x0000FF00; break;
    908          case 3:  shift = 16; imask = 0x0000FFFF; break;
    909          case 4:  shift =  8; imask = 0x00FF0000; break;
    910          case 5:  shift =  8; imask = 0x00FF00FF; break;
    911          case 6:  shift =  8; imask = 0x00FFFF00; break;
    912          case 7:  shift =  8; imask = 0x00FFFFFF; break;
    913          case 8:  shift =  0; imask = 0xFF000000; break;
    914          case 9:  shift =  0; imask = 0xFF0000FF; break;
    915          case 10: shift =  0; imask = 0xFF00FF00; break;
    916          case 11: shift =  0; imask = 0xFF00FFFF; break;
    917          case 12: shift =  0; imask = 0xFFFF0000; break;
    918          case 13: shift =  0; imask = 0xFFFF00FF; break;
    919          case 14: shift =  0; imask = 0xFFFFFF00; break;
    920          case 15: shift =  0; imask = 0xFFFFFFFF; break;
    921          }
    922 
    923          /* Select the bits that were inserted */
    924          word = binop(Iop_And32, word, mkU32(imask));
    925 
    926          /* cc == 0  --> all inserted bits zero or mask == 0   (cond == 8)
    927             cc == 1  --> leftmost inserted bit is one          (cond == 4)
    928             cc == 2  --> leftmost inserted bit is zero and not (cond == 2)
    929                          all inserted bits are zero
    930 
    931             Because cc == 0,1,2 the rightmost bit of the mask is a don't care */
    932          if (cond == 8 || cond == 8 + 1) {
    933             return unop(Iop_1Uto32, binop(Iop_CmpEQ32, word, mkU32(0)));
    934          }
    935          if (cond == 4 + 2 || cond == 4 + 2 + 1) {
    936             return unop(Iop_1Uto32, binop(Iop_CmpNE32, word, mkU32(0)));
    937          }
    938 
    939          /* Sign extend */
    940          if (shift != 0) {
    941             word = binop(Iop_Sar32, binop(Iop_Shl32, word, mkU8(shift)),
    942                          mkU8(shift));
    943          }
    944 
    945          if (cond == 4 || cond == 4 + 1) {  /* word < 0 */
    946             return unop(Iop_1Uto32, binop(Iop_CmpLT32S, word, mkU32(0)));
    947          }
    948          if (cond == 2 || cond == 2 + 1) {  /* word > 0 */
    949             return unop(Iop_1Uto32, binop(Iop_CmpLT32S, mkU32(0), word));
    950          }
    951          if (cond == 8 + 4 || cond == 8 + 4 + 1) {
    952             return unop(Iop_1Uto32, binop(Iop_CmpLE32S, word, mkU32(0)));
    953          }
    954          if (cond == 8 + 2 || cond == 8 + 2 + 1) {
    955             return unop(Iop_1Uto32, binop(Iop_CmpLE32S, mkU32(0), word));
    956          }
    957          if (cond == 8 + 4 + 2 || cond == 8 + 4 + 2 + 1) {
    958             return mkU32(1);
    959          }
    960          /* Remaining case */
    961          return mkU32(0);
    962       }
    963 
    964       /* S390_CC_OP_TEST_UNDER_MASK_8
    965          Since the mask comes from an immediate field in the opcode, we
    966          expect the mask to be a constant here. That simplifies matters. */
    967       if (cc_op == S390_CC_OP_TEST_UNDER_MASK_8) {
    968          ULong mask16;
    969 
    970          if (! isC64(cc_dep2)) goto missed;
    971 
    972          mask16 = cc_dep2->Iex.Const.con->Ico.U64;
    973 
    974          /* Get rid of the mask16 == 0 case first. Some of the simplifications
    975             below (e.g. for OVFL) only hold if mask16 == 0.  */
    976          if (mask16 == 0) {   /* cc == 0 */
    977             if (cond & 0x8) return mkU32(1);
    978             return mkU32(0);
    979          }
    980 
    981          /* cc == 2 is a don't care */
    982          if (cond == 8 || cond == 8 + 2) {
    983             return unop(Iop_1Uto32, binop(Iop_CmpEQ64,
    984                                           binop(Iop_And64, cc_dep1, cc_dep2),
    985                                           mkU64(0)));
    986          }
    987          if (cond == 7 || cond == 7 - 2) {
    988             return unop(Iop_1Uto32, binop(Iop_CmpNE64,
    989                                           binop(Iop_And64, cc_dep1, cc_dep2),
    990                                           mkU64(0)));
    991          }
    992          if (cond == 1 || cond == 1 + 2) {
    993             return unop(Iop_1Uto32, binop(Iop_CmpEQ64,
    994                                           binop(Iop_And64, cc_dep1, cc_dep2),
    995                                           cc_dep2));
    996          }
    997          if (cond == 14 || cond == 14 - 2) {  /* ! OVFL */
    998             return unop(Iop_1Uto32, binop(Iop_CmpNE64,
    999                                           binop(Iop_And64, cc_dep1, cc_dep2),
   1000                                           cc_dep2));
   1001          }
   1002          goto missed;
   1003       }
   1004 
   1005       /* S390_CC_OP_TEST_UNDER_MASK_16
   1006          Since the mask comes from an immediate field in the opcode, we
   1007          expect the mask to be a constant here. That simplifies matters. */
   1008       if (cc_op == S390_CC_OP_TEST_UNDER_MASK_16) {
   1009          ULong mask16;
   1010          UInt msb;
   1011 
   1012          if (! isC64(cc_dep2)) goto missed;
   1013 
   1014          mask16 = cc_dep2->Iex.Const.con->Ico.U64;
   1015 
   1016          /* Get rid of the mask16 == 0 case first. Some of the simplifications
   1017             below (e.g. for OVFL) only hold if mask16 == 0.  */
   1018          if (mask16 == 0) {   /* cc == 0 */
   1019             if (cond & 0x8) return mkU32(1);
   1020             return mkU32(0);
   1021          }
   1022 
   1023          if (cond == 8) {
   1024             return unop(Iop_1Uto32, binop(Iop_CmpEQ64,
   1025                                           binop(Iop_And64, cc_dep1, cc_dep2),
   1026                                           mkU64(0)));
   1027          }
   1028          if (cond == 7) {
   1029             return unop(Iop_1Uto32, binop(Iop_CmpNE64,
   1030                                           binop(Iop_And64, cc_dep1, cc_dep2),
   1031                                           mkU64(0)));
   1032          }
   1033          if (cond == 1) {
   1034             return unop(Iop_1Uto32, binop(Iop_CmpEQ64,
   1035                                           binop(Iop_And64, cc_dep1, cc_dep2),
   1036                                           mkU64(mask16)));
   1037          }
   1038          if (cond == 14) {  /* ! OVFL */
   1039             return unop(Iop_1Uto32, binop(Iop_CmpNE64,
   1040                                           binop(Iop_And64, cc_dep1, cc_dep2),
   1041                                           mkU64(mask16)));
   1042          }
   1043 
   1044          /* Find MSB in mask */
   1045          msb = 0x8000;
   1046          while (msb > mask16)
   1047             msb >>= 1;
   1048 
   1049          if (cond == 2) {  /* cc == 2 */
   1050             IRExpr *c1, *c2;
   1051 
   1052             /* (cc_dep & msb) != 0 && (cc_dep & mask16) != mask16 */
   1053             c1 = binop(Iop_CmpNE64,
   1054                        binop(Iop_And64, cc_dep1, mkU64(msb)), mkU64(0));
   1055             c2 = binop(Iop_CmpNE64,
   1056                        binop(Iop_And64, cc_dep1, cc_dep2),
   1057                        mkU64(mask16));
   1058             return binop(Iop_And32, unop(Iop_1Uto32, c1),
   1059                          unop(Iop_1Uto32, c2));
   1060          }
   1061 
   1062          if (cond == 4) {  /* cc == 1 */
   1063             IRExpr *c1, *c2;
   1064 
   1065             /* (cc_dep & msb) == 0 && (cc_dep & mask16) != 0 */
   1066             c1 = binop(Iop_CmpEQ64,
   1067                        binop(Iop_And64, cc_dep1, mkU64(msb)), mkU64(0));
   1068             c2 = binop(Iop_CmpNE64,
   1069                        binop(Iop_And64, cc_dep1, cc_dep2),
   1070                        mkU64(0));
   1071             return binop(Iop_And32, unop(Iop_1Uto32, c1),
   1072                          unop(Iop_1Uto32, c2));
   1073          }
   1074 
   1075          if (cond == 11) {  /* cc == 0,2,3 */
   1076             IRExpr *c1, *c2;
   1077 
   1078             c1 = binop(Iop_CmpNE64,
   1079                        binop(Iop_And64, cc_dep1, mkU64(msb)), mkU64(0));
   1080             c2 = binop(Iop_CmpEQ64,
   1081                        binop(Iop_And64, cc_dep1, cc_dep2),
   1082                        mkU64(0));
   1083             return binop(Iop_Or32, unop(Iop_1Uto32, c1),
   1084                          unop(Iop_1Uto32, c2));
   1085          }
   1086 
   1087          if (cond == 3) {  /* cc == 2 || cc == 3 */
   1088             return unop(Iop_1Uto32,
   1089                         binop(Iop_CmpNE64,
   1090                               binop(Iop_And64, cc_dep1, mkU64(msb)),
   1091                               mkU64(0)));
   1092          }
   1093          if (cond == 12) { /* cc == 0 || cc == 1 */
   1094             return unop(Iop_1Uto32,
   1095                         binop(Iop_CmpEQ64,
   1096                               binop(Iop_And64, cc_dep1, mkU64(msb)),
   1097                               mkU64(0)));
   1098          }
   1099          // vex_printf("TUM mask = 0x%llx\n", mask16);
   1100          goto missed;
   1101       }
   1102 
   1103       /* S390_CC_OP_UNSIGNED_SUB_64/32 */
   1104       if (cc_op == S390_CC_OP_UNSIGNED_SUB_64 ||
   1105           cc_op == S390_CC_OP_UNSIGNED_SUB_32) {
   1106          /*
   1107             cc_dep1, cc_dep2 are the zero extended left and right operands
   1108 
   1109             cc == 1  --> result != 0, borrow    (cond == 4)
   1110             cc == 2  --> result == 0, no borrow (cond == 2)
   1111             cc == 3  --> result != 0, no borrow (cond == 1)
   1112 
   1113             cc = (cc_dep1 == cc_dep2) ? 2
   1114                                       : (cc_dep1 > cc_dep2) ? 3 : 1;
   1115 
   1116             Because cc == 0 cannot occur the leftmost bit of cond is
   1117             a don't care.
   1118          */
   1119          if (cond == 1 || cond == 1 + 8) {  /* cc == 3   op2 < op1 */
   1120             return unop(Iop_1Uto32, binop(Iop_CmpLT64U, cc_dep2, cc_dep1));
   1121          }
   1122          if (cond == 2 || cond == 2 + 8) {  /* cc == 2 */
   1123             return unop(Iop_1Uto32, binop(Iop_CmpEQ64, cc_dep1, cc_dep2));
   1124          }
   1125          if (cond == 4 || cond == 4 + 8) {  /* cc == 1 */
   1126             return unop(Iop_1Uto32, binop(Iop_CmpLT64U, cc_dep1, cc_dep2));
   1127          }
   1128          if (cond == 3 || cond == 3 + 8) {  /* cc == 2 || cc == 3 */
   1129             return unop(Iop_1Uto32, binop(Iop_CmpLE64U, cc_dep2, cc_dep1));
   1130          }
   1131          if (cond == 6 || cond == 6 + 8) {  /* cc == 2 || cc == 1 */
   1132             return unop(Iop_1Uto32, binop(Iop_CmpLE64U, cc_dep1, cc_dep2));
   1133          }
   1134 
   1135          if (cond == 5 || cond == 5 + 8) {  /* cc == 3 || cc == 1 */
   1136             return unop(Iop_1Uto32, binop(Iop_CmpNE64, cc_dep1, cc_dep2));
   1137          }
   1138          if (cond == 7 || cond == 7 + 8) {
   1139             return mkU32(1);
   1140          }
   1141          /* Remaining case */
   1142          return mkU32(0);
   1143       }
   1144 
   1145       /* S390_CC_OP_UNSIGNED_ADD_64 */
   1146       if (cc_op == S390_CC_OP_UNSIGNED_ADD_64) {
   1147          /*
   1148             cc_dep1, cc_dep2 are the zero extended left and right operands
   1149 
   1150             cc == 0  --> result == 0, no carry  (cond == 8)
   1151             cc == 1  --> result != 0, no carry  (cond == 4)
   1152             cc == 2  --> result == 0, carry     (cond == 2)
   1153             cc == 3  --> result != 0, carry     (cond == 1)
   1154          */
   1155          if (cond == 8) { /* cc == 0 */
   1156             /* Both inputs are 0 */
   1157             return unop(Iop_1Uto32, binop(Iop_CmpEQ64,
   1158                                           binop(Iop_Or64, cc_dep1, cc_dep2),
   1159                                           mkU64(0)));
   1160          }
   1161          if (cond == 7) { /* cc == 1,2,3 */
   1162             /* Not both inputs are 0 */
   1163             return unop(Iop_1Uto32, binop(Iop_CmpNE64,
   1164                                           binop(Iop_Or64, cc_dep1, cc_dep2),
   1165                                           mkU64(0)));
   1166          }
   1167          if (cond == 8 + 2) {  /* cc == 0,2  -> result is zero */
   1168             return unop(Iop_1Uto32, binop(Iop_CmpEQ64,
   1169                                           binop(Iop_Add64, cc_dep1, cc_dep2),
   1170                                           mkU64(0)));
   1171          }
   1172          if (cond == 4 + 1) {  /* cc == 1,3  -> result is not zero */
   1173             return unop(Iop_1Uto32, binop(Iop_CmpNE64,
   1174                                           binop(Iop_Add64, cc_dep1, cc_dep2),
   1175                                           mkU64(0)));
   1176          }
   1177          goto missed;
   1178       }
   1179 
   1180       /* S390_CC_OP_UNSIGNED_ADD_32 */
   1181       if (cc_op == S390_CC_OP_UNSIGNED_ADD_32) {
   1182          /*
   1183             cc_dep1, cc_dep2 are the zero extended left and right operands
   1184 
   1185             cc == 0  --> result == 0, no carry  (cond == 8)
   1186             cc == 1  --> result != 0, no carry  (cond == 4)
   1187             cc == 2  --> result == 0, carry     (cond == 2)
   1188             cc == 3  --> result != 0, carry     (cond == 1)
   1189          */
   1190          if (cond == 8) { /* cc == 0 */
   1191             /* Both inputs are 0 */
   1192             return unop(Iop_1Uto32, binop(Iop_CmpEQ64,
   1193                                           binop(Iop_Or64, cc_dep1, cc_dep2),
   1194                                           mkU64(0)));
   1195          }
   1196          if (cond == 7) { /* cc == 1,2,3 */
   1197             /* Not both inputs are 0 */
   1198             return unop(Iop_1Uto32, binop(Iop_CmpNE64,
   1199                                           binop(Iop_Or64, cc_dep1, cc_dep2),
   1200                                           mkU64(0)));
   1201          }
   1202          if (cond == 8 + 2) {  /* cc == 0,2  -> result is zero */
   1203             return unop(Iop_1Uto32, binop(Iop_CmpEQ32,
   1204                                           binop(Iop_Add32,
   1205                                                 unop(Iop_64to32, cc_dep1),
   1206                                                 unop(Iop_64to32, cc_dep2)),
   1207                                           mkU32(0)));
   1208          }
   1209          if (cond == 4 + 1) {  /* cc == 1,3  -> result is not zero */
   1210             return unop(Iop_1Uto32, binop(Iop_CmpNE32,
   1211                                           binop(Iop_Add32,
   1212                                                 unop(Iop_64to32, cc_dep1),
   1213                                                 unop(Iop_64to32, cc_dep2)),
   1214                                           mkU32(0)));
   1215          }
   1216          goto missed;
   1217       }
   1218 
   1219       /* S390_CC_OP_SET */
   1220       if (cc_op == S390_CC_OP_SET) {
   1221          /* cc_dep1 is the condition code
   1222 
   1223             Return 1, if ((cond << cc_dep1) & 0x8) != 0 */
   1224 
   1225         return unop(Iop_1Uto32,
   1226                     binop(Iop_CmpNE64,
   1227                           binop(Iop_And64,
   1228                                 binop(Iop_Shl64, cond_expr,
   1229                                       unop(Iop_64to8, cc_dep1)),
   1230                                 mkU64(8)),
   1231                           mkU64(0)));
   1232       }
   1233 
   1234       /* S390_CC_OP_TEST_AND_SET */
   1235       if (cc_op == S390_CC_OP_TEST_AND_SET) {
   1236          /* cc_dep1 is the zero-extended loaded value
   1237 
   1238             cc == 0  --> leftmost bit is zero  (cond == 8)
   1239             cc == 1  --> leftmost bit is one   (cond == 4)
   1240 
   1241             As cc is either 0 or 1, only the two leftmost bits of the mask
   1242             are relevant. */
   1243          IRExpr *bit = binop(Iop_Shr64, cc_dep1, mkU8(7));
   1244 
   1245          switch (cond & (8 + 4)) {
   1246          case 0:     return mkU32(0);
   1247          case 4:     return unop(Iop_1Uto32, binop(Iop_CmpNE64, bit, mkU64(0)));
   1248          case 8:     return unop(Iop_1Uto32, binop(Iop_CmpEQ64, bit, mkU64(0)));
   1249          case 8 + 4: return mkU32(1);
   1250          }
   1251          /* not reached */
   1252       }
   1253 
   1254 missed:
   1255       ;
   1256    }
   1257 
   1258    return NULL;
   1259 }
   1260 
   1261 /*---------------------------------------------------------------*/
   1262 /*--- end                                guest_s390_helpers.c ---*/
   1263 /*---------------------------------------------------------------*/
   1264