Home | History | Annotate | Download | only in priv
      1 /* -*- mode: C; c-basic-offset: 3; -*- */
      2 
      3 /*---------------------------------------------------------------*/
      4 /*--- begin                                  host_s390_isel.c ---*/
      5 /*---------------------------------------------------------------*/
      6 
      7 /*
      8    This file is part of Valgrind, a dynamic binary instrumentation
      9    framework.
     10 
     11    Copyright IBM Corp. 2010-2017
     12    Copyright (C) 2012-2017  Florian Krohm   (britzel (at) acm.org)
     13 
     14    This program is free software; you can redistribute it and/or
     15    modify it under the terms of the GNU General Public License as
     16    published by the Free Software Foundation; either version 2 of the
     17    License, or (at your option) any later version.
     18 
     19    This program is distributed in the hope that it will be useful, but
     20    WITHOUT ANY WARRANTY; without even the implied warranty of
     21    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     22    General Public License for more details.
     23 
     24    You should have received a copy of the GNU General Public License
     25    along with this program; if not, write to the Free Software
     26    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
     27    02110-1301, USA.
     28 
     29    The GNU General Public License is contained in the file COPYING.
     30 */
     31 
     32 /* Contributed by Florian Krohm */
     33 
     34 #include "libvex_basictypes.h"
     35 #include "libvex_ir.h"
     36 #include "libvex.h"
     37 #include "libvex_s390x_common.h"
     38 
     39 #include "main_util.h"
     40 #include "main_globals.h"
     41 #include "guest_s390_defs.h"   /* S390X_GUEST_OFFSET */
     42 #include "host_generic_regs.h"
     43 #include "host_s390_defs.h"
     44 
     45 /*---------------------------------------------------------*/
     46 /*--- ISelEnv                                           ---*/
     47 /*---------------------------------------------------------*/
     48 
     49 /* This carries around:
     50 
     51    - A mapping from IRTemp to IRType, giving the type of any IRTemp we
     52      might encounter.  This is computed before insn selection starts,
     53      and does not change.
     54 
     55    - A mapping from IRTemp to HReg.  This tells the insn selector
     56      which virtual register(s) are associated with each IRTemp
     57       temporary.  This is computed before insn selection starts, and
     58       does not change.  We expect this mapping to map precisely the
     59       same set of IRTemps as the type mapping does.
     60 
     61          - vregmap   holds the primary register for the IRTemp.
     62          - vregmapHI holds the secondary register for the IRTemp,
     63               if any is needed.  That's only for Ity_I64 temps
     64               in 32 bit mode or Ity_I128 temps in 64-bit mode.
     65 
     66     - The code array, that is, the insns selected so far.
     67 
     68     - A counter, for generating new virtual registers.
     69 
     70     - The host subarchitecture we are selecting insns for.
     71       This is set at the start and does not change.
     72 
     73    - A Bool for indicating whether we may generate chain-me
     74      instructions for control flow transfers, or whether we must use
     75      XAssisted.
     76 
     77    - The maximum guest address of any guest insn in this block.
     78      Actually, the address of the highest-addressed byte from any insn
     79      in this block.  Is set at the start and does not change.  This is
     80      used for detecting jumps which are definitely forward-edges from
     81      this block, and therefore can be made (chained) to the fast entry
     82      point of the destination, thereby avoiding the destination's
     83      event check.
     84 
     85     - Values of certain guest registers which are often assigned constants.
     86 */
     87 
     88 /* Symbolic names for guest registers whose value we're tracking */
     89 enum {
     90    GUEST_IA,
     91    GUEST_CC_OP,
     92    GUEST_CC_DEP1,
     93    GUEST_CC_DEP2,
     94    GUEST_CC_NDEP,
     95    GUEST_SYSNO,
     96    GUEST_COUNTER,
     97    GUEST_UNKNOWN    /* must be the last entry */
     98 };
     99 
    100 /* Number of registers we're tracking. */
    101 #define NUM_TRACKED_REGS GUEST_UNKNOWN
    102 
    103 
    104 typedef struct {
    105    IRTypeEnv   *type_env;
    106 
    107    HInstrArray *code;
    108    HReg        *vregmap;
    109    HReg        *vregmapHI;
    110    UInt         n_vregmap;
    111    UInt         vreg_ctr;
    112    UInt         hwcaps;
    113 
    114    IRExpr      *previous_bfp_rounding_mode;
    115    IRExpr      *previous_dfp_rounding_mode;
    116 
    117    ULong        old_value[NUM_TRACKED_REGS];
    118 
    119    /* The next two are for translation chaining */
    120    Addr64       max_ga;
    121    Bool         chaining_allowed;
    122 
    123    Bool         old_value_valid[NUM_TRACKED_REGS];
    124 } ISelEnv;
    125 
    126 
    127 /* Forward declarations */
    128 static HReg          s390_isel_int_expr(ISelEnv *, IRExpr *);
    129 static s390_amode   *s390_isel_amode(ISelEnv *, IRExpr *);
    130 static s390_amode   *s390_isel_amode_b12_b20(ISelEnv *, IRExpr *);
    131 static s390_cc_t     s390_isel_cc(ISelEnv *, IRExpr *);
    132 static s390_opnd_RMI s390_isel_int_expr_RMI(ISelEnv *, IRExpr *);
    133 static void          s390_isel_int128_expr(HReg *, HReg *, ISelEnv *, IRExpr *);
    134 static HReg          s390_isel_float_expr(ISelEnv *, IRExpr *);
    135 static void          s390_isel_float128_expr(HReg *, HReg *, ISelEnv *, IRExpr *);
    136 static HReg          s390_isel_dfp_expr(ISelEnv *, IRExpr *);
    137 static void          s390_isel_dfp128_expr(HReg *, HReg *, ISelEnv *, IRExpr *);
    138 
    139 
    140 static Int
    141 get_guest_reg(Int offset)
    142 {
    143    switch (offset) {
    144    case S390X_GUEST_OFFSET(guest_IA):        return GUEST_IA;
    145    case S390X_GUEST_OFFSET(guest_CC_OP):     return GUEST_CC_OP;
    146    case S390X_GUEST_OFFSET(guest_CC_DEP1):   return GUEST_CC_DEP1;
    147    case S390X_GUEST_OFFSET(guest_CC_DEP2):   return GUEST_CC_DEP2;
    148    case S390X_GUEST_OFFSET(guest_CC_NDEP):   return GUEST_CC_NDEP;
    149    case S390X_GUEST_OFFSET(guest_SYSNO):     return GUEST_SYSNO;
    150    case S390X_GUEST_OFFSET(guest_counter):   return GUEST_COUNTER;
    151 
    152       /* Also make sure there is never a partial write to one of
    153          these registers. That would complicate matters. */
    154    case S390X_GUEST_OFFSET(guest_IA)+1      ... S390X_GUEST_OFFSET(guest_IA)+7:
    155    case S390X_GUEST_OFFSET(guest_CC_OP)+1   ... S390X_GUEST_OFFSET(guest_CC_OP)+7:
    156    case S390X_GUEST_OFFSET(guest_CC_DEP1)+1 ... S390X_GUEST_OFFSET(guest_CC_DEP1)+7:
    157    case S390X_GUEST_OFFSET(guest_CC_DEP2)+1 ... S390X_GUEST_OFFSET(guest_CC_DEP2)+7:
    158    case S390X_GUEST_OFFSET(guest_CC_NDEP)+1 ... S390X_GUEST_OFFSET(guest_CC_NDEP)+7:
    159    case S390X_GUEST_OFFSET(guest_SYSNO)+1   ... S390X_GUEST_OFFSET(guest_SYSNO)+7:
    160       /* counter is used both as 4-byte and as 8-byte entity */
    161    case S390X_GUEST_OFFSET(guest_counter)+1 ... S390X_GUEST_OFFSET(guest_counter)+3:
    162    case S390X_GUEST_OFFSET(guest_counter)+5 ... S390X_GUEST_OFFSET(guest_counter)+7:
    163       vpanic("partial update of this guest state register is not allowed");
    164       break;
    165 
    166    default: break;
    167    }
    168 
    169    return GUEST_UNKNOWN;
    170 }
    171 
    172 /* Add an instruction */
    173 static void
    174 addInstr(ISelEnv *env, s390_insn *insn)
    175 {
    176    addHInstr(env->code, insn);
    177 
    178    if (vex_traceflags & VEX_TRACE_VCODE) {
    179       vex_printf("%s\n", s390_insn_as_string(insn));
    180    }
    181 }
    182 
    183 
    184 static __inline__ IRExpr *
    185 mkU64(ULong value)
    186 {
    187    return IRExpr_Const(IRConst_U64(value));
    188 }
    189 
    190 
    191 /*---------------------------------------------------------*/
    192 /*--- Registers                                         ---*/
    193 /*---------------------------------------------------------*/
    194 
    195 /* Return the virtual register to which a given IRTemp is mapped. */
    196 static HReg
    197 lookupIRTemp(ISelEnv *env, IRTemp tmp)
    198 {
    199    vassert(tmp < env->n_vregmap);
    200    vassert(! hregIsInvalid(env->vregmap[tmp]));
    201 
    202    return env->vregmap[tmp];
    203 }
    204 
    205 
    206 /* Return the two virtual registers to which the IRTemp is mapped. */
    207 static void
    208 lookupIRTemp128(HReg *hi, HReg *lo, ISelEnv *env, IRTemp tmp)
    209 {
    210    vassert(tmp < env->n_vregmap);
    211    vassert(! hregIsInvalid(env->vregmapHI[tmp]));
    212 
    213    *lo = env->vregmap[tmp];
    214    *hi = env->vregmapHI[tmp];
    215 }
    216 
    217 
    218 /* Allocate a new virtual integer register */
    219 static __inline__ HReg
    220 mkVRegI(UInt ix)
    221 {
    222    return mkHReg(/*virtual*/True, HRcInt64, /*encoding*/0, ix);
    223 }
    224 
    225 static __inline__ HReg
    226 newVRegI(ISelEnv *env)
    227 {
    228    return mkVRegI(env->vreg_ctr++);
    229 }
    230 
    231 
    232 /* Allocate a new virtual floating point register */
    233 static __inline__ HReg
    234 mkVRegF(UInt ix)
    235 {
    236    return mkHReg(/*virtual*/True, HRcFlt64, /*encoding*/0, ix);
    237 }
    238 
    239 static __inline__ HReg
    240 newVRegF(ISelEnv *env)
    241 {
    242    return mkVRegF(env->vreg_ctr++);
    243 }
    244 
    245 
    246 /* Construct a non-virtual general purpose register */
    247 static __inline__ HReg
    248 make_gpr(UInt regno)
    249 {
    250    return s390_hreg_gpr(regno);
    251 }
    252 
    253 
    254 /* Construct a non-virtual floating point register */
    255 static __inline__ HReg
    256 make_fpr(UInt regno)
    257 {
    258    return s390_hreg_fpr(regno);
    259 }
    260 
    261 
    262 /*---------------------------------------------------------*/
    263 /*--- Amode                                             ---*/
    264 /*---------------------------------------------------------*/
    265 
    266 static __inline__ Bool
    267 ulong_fits_unsigned_12bit(ULong val)
    268 {
    269    return (val & 0xFFFu) == val;
    270 }
    271 
    272 
    273 static __inline__ Bool
    274 ulong_fits_signed_20bit(ULong val)
    275 {
    276    ULong v = val & 0xFFFFFu;
    277 
    278    v = (Long)(v << 44) >> 44;  /* sign extend */
    279 
    280    return val == v;
    281 }
    282 
    283 
    284 static __inline__ Bool
    285 ulong_fits_signed_8bit(ULong val)
    286 {
    287    ULong v = val & 0xFFu;
    288 
    289    v = (Long)(v << 56) >> 56;  /* sign extend */
    290 
    291    return val == v;
    292 }
    293 
    294 /* EXPR is an expression that is used as an address. Return an s390_amode
    295    for it. If select_b12_b20_only is true the returned amode must be either
    296    S390_AMODE_B12 or S390_AMODE_B20. */
    297 static s390_amode *
    298 s390_isel_amode_wrk(ISelEnv *env, IRExpr *expr,
    299                     Bool select_b12_b20_only __attribute__((unused)))
    300 {
    301    if (expr->tag == Iex_Binop && expr->Iex.Binop.op == Iop_Add64) {
    302       IRExpr *arg1 = expr->Iex.Binop.arg1;
    303       IRExpr *arg2 = expr->Iex.Binop.arg2;
    304 
    305       /* Move constant into right subtree */
    306       if (arg1->tag == Iex_Const) {
    307          IRExpr *tmp;
    308          tmp  = arg1;
    309          arg1 = arg2;
    310          arg2 = tmp;
    311       }
    312 
    313       /* r + constant: Check for b12 first, then b20 */
    314       if (arg2->tag == Iex_Const && arg2->Iex.Const.con->tag == Ico_U64) {
    315          ULong value = arg2->Iex.Const.con->Ico.U64;
    316 
    317          if (ulong_fits_unsigned_12bit(value)) {
    318             return s390_amode_b12((Int)value, s390_isel_int_expr(env, arg1));
    319          }
    320          if (ulong_fits_signed_20bit(value)) {
    321             return s390_amode_b20((Int)value, s390_isel_int_expr(env, arg1));
    322          }
    323       }
    324    }
    325 
    326    /* Doesn't match anything in particular.  Generate it into
    327       a register and use that. */
    328    return s390_amode_b12(0, s390_isel_int_expr(env, expr));
    329 }
    330 
    331 
    332 static s390_amode *
    333 s390_isel_amode(ISelEnv *env, IRExpr *expr)
    334 {
    335    s390_amode *am;
    336 
    337    /* Address computation should yield a 64-bit value */
    338    vassert(typeOfIRExpr(env->type_env, expr) == Ity_I64);
    339 
    340    am = s390_isel_amode_wrk(env, expr, /* B12, B20 only */ False);
    341 
    342    /* Check post-condition */
    343    vassert(s390_amode_is_sane(am));
    344 
    345    return am;
    346 }
    347 
    348 
    349 /* Sometimes we must compile an expression into an amode that is either
    350    S390_AMODE_B12 or S390_AMODE_B20. An example is the compare-and-swap
    351    opcode. These opcodes do not have a variant hat accepts an addressing
    352    mode with an index register.
    353    Now, in theory we could, when emitting the compare-and-swap insn,
    354    hack a, say, BX12 amode into a B12 amode like so:
    355 
    356       r0 = b       # save away base register
    357       b  = b + x   # add index register to base register
    358       cas(b,d,...) # emit compare-and-swap using b12 amode
    359       b  = r0      # restore base register
    360 
    361    Unfortunately, emitting the compare-and-swap insn already utilises r0
    362    under the covers, so the trick above is off limits, sadly. */
    363 static s390_amode *
    364 s390_isel_amode_b12_b20(ISelEnv *env, IRExpr *expr)
    365 {
    366    s390_amode *am;
    367 
    368    /* Address computation should yield a 64-bit value */
    369    vassert(typeOfIRExpr(env->type_env, expr) == Ity_I64);
    370 
    371    am = s390_isel_amode_wrk(env, expr, /* B12, B20 only */ True);
    372 
    373    /* Check post-condition */
    374    vassert(s390_amode_is_sane(am) &&
    375            (am->tag == S390_AMODE_B12 || am->tag == S390_AMODE_B20));
    376 
    377    return am;
    378 }
    379 
    380 
    381 /*---------------------------------------------------------*/
    382 /*--- Helper functions                                  ---*/
    383 /*---------------------------------------------------------*/
    384 
    385 /* Constants and memory accesses should be right operands */
    386 #define order_commutative_operands(left, right)                   \
    387         do {                                                      \
    388           if (left->tag == Iex_Const || left->tag == Iex_Load ||  \
    389               left->tag == Iex_Get) {                             \
    390             IRExpr *tmp;                                          \
    391             tmp   = left;                                         \
    392             left  = right;                                        \
    393             right = tmp;                                          \
    394           }                                                       \
    395         } while (0)
    396 
    397 
    398 /* Copy an RMI operand to the DST register */
    399 static s390_insn *
    400 s390_opnd_copy(UChar size, HReg dst, s390_opnd_RMI opnd)
    401 {
    402    switch (opnd.tag) {
    403    case S390_OPND_AMODE:
    404       return s390_insn_load(size, dst, opnd.variant.am);
    405 
    406    case S390_OPND_REG:
    407       return s390_insn_move(size, dst, opnd.variant.reg);
    408 
    409    case S390_OPND_IMMEDIATE:
    410       return s390_insn_load_immediate(size, dst, opnd.variant.imm);
    411 
    412    default:
    413       vpanic("s390_opnd_copy");
    414    }
    415 }
    416 
    417 
    418 /* Construct a RMI operand for a register */
    419 static __inline__ s390_opnd_RMI
    420 s390_opnd_reg(HReg reg)
    421 {
    422    s390_opnd_RMI opnd;
    423 
    424    opnd.tag  = S390_OPND_REG;
    425    opnd.variant.reg = reg;
    426 
    427    return opnd;
    428 }
    429 
    430 
    431 /* Construct a RMI operand for an immediate constant */
    432 static __inline__ s390_opnd_RMI
    433 s390_opnd_imm(ULong value)
    434 {
    435    s390_opnd_RMI opnd;
    436 
    437    opnd.tag  = S390_OPND_IMMEDIATE;
    438    opnd.variant.imm = value;
    439 
    440    return opnd;
    441 }
    442 
    443 
    444 /* Return 1, if EXPR represents the constant 0 */
    445 static Bool
    446 s390_expr_is_const_zero(IRExpr *expr)
    447 {
    448    ULong value;
    449 
    450    if (expr->tag == Iex_Const) {
    451       switch (expr->Iex.Const.con->tag) {
    452       case Ico_U1:  value = expr->Iex.Const.con->Ico.U1;  break;
    453       case Ico_U8:  value = expr->Iex.Const.con->Ico.U8;  break;
    454       case Ico_U16: value = expr->Iex.Const.con->Ico.U16; break;
    455       case Ico_U32: value = expr->Iex.Const.con->Ico.U32; break;
    456       case Ico_U64: value = expr->Iex.Const.con->Ico.U64; break;
    457       default:
    458          vpanic("s390_expr_is_const_zero");
    459       }
    460       return value == 0;
    461    }
    462 
    463    return 0;
    464 }
    465 
    466 
    467 /* Return the value of CON as a sign-exteded ULong value */
    468 static ULong
    469 get_const_value_as_ulong(const IRConst *con)
    470 {
    471    ULong value;
    472 
    473    switch (con->tag) {
    474    case Ico_U1:  value = con->Ico.U1;  return ((Long)(value << 63) >> 63);
    475    case Ico_U8:  value = con->Ico.U8;  return ((Long)(value << 56) >> 56);
    476    case Ico_U16: value = con->Ico.U16; return ((Long)(value << 48) >> 48);
    477    case Ico_U32: value = con->Ico.U32; return ((Long)(value << 32) >> 32);
    478    case Ico_U64: return con->Ico.U64;
    479    default:
    480       vpanic("get_const_value_as_ulong");
    481    }
    482 }
    483 
    484 
    485 /* Call a helper (clean or dirty)
    486    Arguments must satisfy the following conditions:
    487 
    488    (a) they are expressions yielding an integer result
    489    (b) there can be no more than S390_NUM_GPRPARMS arguments
    490 
    491    guard is a Ity_Bit expression indicating whether or not the
    492    call happens.  If guard == NULL, the call is unconditional.
    493 
    494    Calling the helper function proceeds as follows:
    495 
    496    (1) The helper arguments are evaluated and their value stored in
    497        virtual registers.
    498    (2) The condition code is evaluated
    499    (3) The argument values are copied from the virtual registers to the
    500        registers mandated by the ABI.
    501    (4) Call the helper function.
    502 
    503    This is not the most efficient way as step 3 generates register-to-register
    504    moves. But it is the least fragile way as the only hidden dependency here
    505    is that register-to-register moves (step 3) must not clobber the condition
    506    code. Other schemes (e.g. VEX r2326) that attempt to avoid the register-
    507    to-register add more such dependencies. Not good. Besides, it's the job
    508    of the register allocator to throw out those reg-to-reg moves.
    509 */
    510 static void
    511 doHelperCall(/*OUT*/UInt *stackAdjustAfterCall,
    512              /*OUT*/RetLoc *retloc,
    513              ISelEnv *env, IRExpr *guard,
    514              IRCallee *callee, IRType retTy, IRExpr **args)
    515 {
    516    UInt n_args, i, argreg, size;
    517    Addr64 target;
    518    HReg tmpregs[S390_NUM_GPRPARMS];
    519    s390_cc_t cc;
    520 
    521    /* Set default returns.  We'll update them later if needed. */
    522    *stackAdjustAfterCall = 0;
    523    *retloc               = mk_RetLoc_INVALID();
    524 
    525    /* The return type can be I{64,32,16,8} or V{128,256}.  In the
    526       latter two cases, it is expected that |args| will contain the
    527       special node IRExpr_VECRET(). For s390, however, V128 and V256 return
    528       values do not occur as we generally do not support vector types.
    529 
    530       |args| may also contain IRExpr_GSPTR(), in which case the value
    531       in the guest state pointer register is passed as the
    532       corresponding argument.
    533 
    534       These are used for cross-checking that IR-level constraints on
    535       the use of IRExpr_VECRET() and IRExpr_GSPTR() are observed. */
    536    UInt nVECRETs = 0;
    537    UInt nGSPTRs  = 0;
    538 
    539    n_args = 0;
    540    for (i = 0; args[i]; i++)
    541       ++n_args;
    542 
    543    if (n_args > S390_NUM_GPRPARMS) {
    544       vpanic("doHelperCall: too many arguments");
    545    }
    546 
    547    /* All arguments must have Ity_I64. For two reasons:
    548       (1) We do not handle floating point arguments.
    549       (2) The ABI requires that integer values are sign- or zero-extended
    550            to 64 bit.
    551    */
    552    Int arg_errors = 0;
    553    for (i = 0; i < n_args; ++i) {
    554       if (UNLIKELY(args[i]->tag == Iex_VECRET)) {
    555          nVECRETs++;
    556       } else if (UNLIKELY(args[i]->tag == Iex_GSPTR)) {
    557          nGSPTRs++;
    558       } else {
    559          IRType type = typeOfIRExpr(env->type_env, args[i]);
    560          if (type != Ity_I64) {
    561             ++arg_errors;
    562             vex_printf("calling %s: argument #%u has type ", callee->name, i);
    563             ppIRType(type);
    564             vex_printf("; Ity_I64 is required\n");
    565          }
    566       }
    567    }
    568 
    569    if (arg_errors)
    570       vpanic("cannot continue due to errors in argument passing");
    571 
    572    /* If these fail, the IR is ill-formed */
    573    vassert(nGSPTRs == 0 || nGSPTRs == 1);
    574    vassert(nVECRETs == 0);
    575 
    576    argreg = 0;
    577 
    578    /* Compute the function arguments into a temporary register each */
    579    for (i = 0; i < n_args; i++) {
    580       IRExpr *arg = args[i];
    581       if (UNLIKELY(arg->tag == Iex_GSPTR)) {
    582          /* If we need the guest state pointer put it in a temporary arg reg */
    583          tmpregs[argreg] = newVRegI(env);
    584          addInstr(env, s390_insn_move(sizeof(ULong), tmpregs[argreg],
    585                                       s390_hreg_guest_state_pointer()));
    586       } else {
    587          tmpregs[argreg] = s390_isel_int_expr(env, args[i]);
    588       }
    589       argreg++;
    590    }
    591 
    592    /* Compute the condition */
    593    cc = S390_CC_ALWAYS;
    594    if (guard) {
    595       if (guard->tag == Iex_Const
    596           && guard->Iex.Const.con->tag == Ico_U1
    597           && guard->Iex.Const.con->Ico.U1 == True) {
    598          /* unconditional -- do nothing */
    599       } else {
    600          cc = s390_isel_cc(env, guard);
    601       }
    602    }
    603 
    604    /* Move the args to the final register. It is paramount, that the
    605       code to move the registers does not clobber the condition code ! */
    606    for (i = 0; i < argreg; i++) {
    607       HReg finalreg;
    608 
    609       finalreg = make_gpr(s390_gprno_from_arg_index(i));
    610       size = sizeofIRType(Ity_I64);
    611       addInstr(env, s390_insn_move(size, finalreg, tmpregs[i]));
    612    }
    613 
    614    target = (Addr)callee->addr;
    615 
    616    /* Do final checks, set the return values, and generate the call
    617       instruction proper. */
    618    vassert(*stackAdjustAfterCall == 0);
    619    vassert(is_RetLoc_INVALID(*retloc));
    620    switch (retTy) {
    621    case Ity_INVALID:
    622       /* Function doesn't return a value. */
    623       *retloc = mk_RetLoc_simple(RLPri_None);
    624       break;
    625    case Ity_I64: case Ity_I32: case Ity_I16: case Ity_I8:
    626       *retloc = mk_RetLoc_simple(RLPri_Int);
    627       break;
    628    default:
    629       /* IR can denote other possible return types, but we don't
    630          handle those here. */
    631       vex_printf("calling %s: return type is ", callee->name);
    632       ppIRType(retTy);
    633       vex_printf("; an integer type is required\n");
    634       vassert(0);
    635    }
    636 
    637    /* Finally, the call itself. */
    638    addInstr(env, s390_insn_helper_call(cc, target, n_args,
    639                                        callee->name, *retloc));
    640 }
    641 
    642 
    643 /*---------------------------------------------------------*/
    644 /*--- BFP helper functions                              ---*/
    645 /*---------------------------------------------------------*/
    646 
    647 /* Set the BFP rounding mode in the FPC. This function is called for
    648    all non-conversion BFP instructions as those will always get the
    649    rounding mode from the FPC. */
    650 static void
    651 set_bfp_rounding_mode_in_fpc(ISelEnv *env, IRExpr *irrm)
    652 {
    653    vassert(typeOfIRExpr(env->type_env, irrm) == Ity_I32);
    654 
    655    /* Do we need to do anything? */
    656    if (env->previous_bfp_rounding_mode &&
    657        env->previous_bfp_rounding_mode->tag == Iex_RdTmp &&
    658        irrm->tag == Iex_RdTmp &&
    659        env->previous_bfp_rounding_mode->Iex.RdTmp.tmp == irrm->Iex.RdTmp.tmp) {
    660       /* No - new mode is identical to previous mode.  */
    661       return;
    662    }
    663 
    664    /* No luck - we better set it, and remember what we set it to. */
    665    env->previous_bfp_rounding_mode = irrm;
    666 
    667    /* The incoming rounding mode is in VEX IR encoding. Need to change
    668       to s390.
    669 
    670       rounding mode | s390 | IR
    671       -------------------------
    672       to nearest    |  00  | 00
    673       to zero       |  01  | 11
    674       to +infinity  |  10  | 10
    675       to -infinity  |  11  | 01
    676 
    677       So: s390 = (4 - IR) & 3
    678    */
    679    HReg ir = s390_isel_int_expr(env, irrm);
    680 
    681    HReg mode = newVRegI(env);
    682 
    683    addInstr(env, s390_insn_load_immediate(4, mode, 4));
    684    addInstr(env, s390_insn_alu(4, S390_ALU_SUB, mode, s390_opnd_reg(ir)));
    685    addInstr(env, s390_insn_alu(4, S390_ALU_AND, mode, s390_opnd_imm(3)));
    686 
    687    addInstr(env, s390_insn_set_fpc_bfprm(4, mode));
    688 }
    689 
    690 
    691 /* This function is invoked for insns that support a specification of
    692    a rounding mode in the insn itself. In that case there is no need to
    693    stick the rounding mode into the FPC -- a good thing. However, the
    694    rounding mode must be known. */
    695 static s390_bfp_round_t
    696 get_bfp_rounding_mode(ISelEnv *env, IRExpr *irrm)
    697 {
    698    if (irrm->tag == Iex_Const) {          /* rounding mode is known */
    699       vassert(irrm->Iex.Const.con->tag == Ico_U32);
    700       IRRoundingMode mode = irrm->Iex.Const.con->Ico.U32;
    701 
    702       switch (mode) {
    703       case Irrm_NEAREST:  return S390_BFP_ROUND_NEAREST_EVEN;
    704       case Irrm_ZERO:     return S390_BFP_ROUND_ZERO;
    705       case Irrm_PosINF:   return S390_BFP_ROUND_POSINF;
    706       case Irrm_NegINF:   return S390_BFP_ROUND_NEGINF;
    707       default:
    708          vpanic("get_bfp_rounding_mode");
    709       }
    710    }
    711 
    712    set_bfp_rounding_mode_in_fpc(env, irrm);
    713    return S390_BFP_ROUND_PER_FPC;
    714 }
    715 
    716 
    717 /*---------------------------------------------------------*/
    718 /*--- DFP helper functions                              ---*/
    719 /*---------------------------------------------------------*/
    720 
    721 /* Set the DFP rounding mode in the FPC. This function is called for
    722    all non-conversion DFP instructions as those will always get the
    723    rounding mode from the FPC. */
    724 static void
    725 set_dfp_rounding_mode_in_fpc(ISelEnv *env, IRExpr *irrm)
    726 {
    727    vassert(typeOfIRExpr(env->type_env, irrm) == Ity_I32);
    728 
    729    /* Do we need to do anything? */
    730    if (env->previous_dfp_rounding_mode &&
    731        env->previous_dfp_rounding_mode->tag == Iex_RdTmp &&
    732        irrm->tag == Iex_RdTmp &&
    733        env->previous_dfp_rounding_mode->Iex.RdTmp.tmp == irrm->Iex.RdTmp.tmp) {
    734       /* No - new mode is identical to previous mode.  */
    735       return;
    736    }
    737 
    738    /* No luck - we better set it, and remember what we set it to. */
    739    env->previous_dfp_rounding_mode = irrm;
    740 
    741    /* The incoming rounding mode is in VEX IR encoding. Need to change
    742       to s390.
    743 
    744       rounding mode                     | S390 |  IR
    745       -----------------------------------------------
    746       to nearest, ties to even          | 000  | 000
    747       to zero                           | 001  | 011
    748       to +infinity                      | 010  | 010
    749       to -infinity                      | 011  | 001
    750       to nearest, ties away from 0      | 100  | 100
    751       to nearest, ties toward 0         | 101  | 111
    752       to away from 0                    | 110  | 110
    753       to prepare for shorter precision  | 111  | 101
    754 
    755       So: s390 = (IR ^ ((IR << 1) & 2))
    756    */
    757    HReg ir = s390_isel_int_expr(env, irrm);
    758 
    759    HReg mode = newVRegI(env);
    760 
    761    addInstr(env, s390_insn_move(4, mode, ir));
    762    addInstr(env, s390_insn_alu(4, S390_ALU_LSH, mode, s390_opnd_imm(1)));
    763    addInstr(env, s390_insn_alu(4, S390_ALU_AND, mode, s390_opnd_imm(2)));
    764    addInstr(env, s390_insn_alu(4, S390_ALU_XOR, mode, s390_opnd_reg(ir)));
    765 
    766    addInstr(env, s390_insn_set_fpc_dfprm(4, mode));
    767 }
    768 
    769 
    770 /* This function is invoked for insns that support a specification of
    771    a rounding mode in the insn itself. In that case there is no need to
    772    stick the rounding mode into the FPC -- a good thing. However, the
    773    rounding mode must be known.
    774 
    775    When mapping an Irrm_XYZ value to an S390_DFP_ROUND_ value there is
    776    often a choice. For instance, Irrm_ZERO could be mapped to either
    777    S390_DFP_ROUND_ZERO_5 or S390_DFP_ROUND_ZERO_9. The difference between
    778    those two is that with S390_DFP_ROUND_ZERO_9 the recognition of the
    779    quantum exception is suppressed whereas with S390_DFP_ROUND_ZERO_5 it
    780    is not.  As the quantum exception is not modelled we can choose either
    781    value. The choice is to use S390_DFP_ROUND_.. values in the range [8:15],
    782    because values in the range [1:7] have unpredictable rounding behaviour
    783    when the floating point exception facility is not installed.
    784 
    785    Translation table of
    786    s390 DFP rounding mode to IRRoundingMode to s390 DFP rounding mode
    787 
    788    s390(S390_DFP_ROUND_)  |  IR(Irrm_)           |  s390(S390_DFP_ROUND_)
    789    --------------------------------------------------------------------
    790    NEAREST_TIE_AWAY_0_1   |  NEAREST_TIE_AWAY_0  |  NEAREST_TIE_AWAY_0_12
    791    NEAREST_TIE_AWAY_0_12  |     "                |     "
    792    PREPARE_SHORT_3        |  PREPARE_SHORTER     |  PREPARE_SHORT_15
    793    PREPARE_SHORT_15       |     "                |     "
    794    NEAREST_EVEN_4         |  NEAREST             |  NEAREST_EVEN_8
    795    NEAREST_EVEN_8         |     "                |     "
    796    ZERO_5                 |  ZERO                |  ZERO_9
    797    ZERO_9                 |     "                |     "
    798    POSINF_6               |  PosINF              |  POSINF_10
    799    POSINF_10              |     "                |     "
    800    NEGINF_7               |  NegINF              |  NEGINF_11
    801    NEGINF_11              |     "                |     "
    802    NEAREST_TIE_TOWARD_0   |  NEAREST_TIE_TOWARD_0|  NEAREST_TIE_TOWARD_0
    803    AWAY_0                 |  AWAY_FROM_ZERO      |  AWAY_0
    804 */
    805 static s390_dfp_round_t
    806 get_dfp_rounding_mode(ISelEnv *env, IRExpr *irrm)
    807 {
    808    if (irrm->tag == Iex_Const) {          /* rounding mode is known */
    809       vassert(irrm->Iex.Const.con->tag == Ico_U32);
    810       IRRoundingMode mode = irrm->Iex.Const.con->Ico.U32;
    811 
    812       switch (mode) {
    813       case Irrm_NEAREST:
    814          return S390_DFP_ROUND_NEAREST_EVEN_8;
    815       case Irrm_NegINF:
    816          return S390_DFP_ROUND_NEGINF_11;
    817       case Irrm_PosINF:
    818          return S390_DFP_ROUND_POSINF_10;
    819       case Irrm_ZERO:
    820          return S390_DFP_ROUND_ZERO_9;
    821       case Irrm_NEAREST_TIE_AWAY_0:
    822          return S390_DFP_ROUND_NEAREST_TIE_AWAY_0_12;
    823       case Irrm_PREPARE_SHORTER:
    824           return S390_DFP_ROUND_PREPARE_SHORT_15;
    825       case Irrm_AWAY_FROM_ZERO:
    826          return S390_DFP_ROUND_AWAY_0;
    827       case Irrm_NEAREST_TIE_TOWARD_0:
    828          return S390_DFP_ROUND_NEAREST_TIE_TOWARD_0;
    829       default:
    830          vpanic("get_dfp_rounding_mode");
    831       }
    832    }
    833 
    834    set_dfp_rounding_mode_in_fpc(env, irrm);
    835    return S390_DFP_ROUND_PER_FPC_0;
    836 }
    837 
    838 
    839 /*---------------------------------------------------------*/
    840 /*--- Condition code helper functions                   ---*/
    841 /*---------------------------------------------------------*/
    842 
    843 /* CC_S390 holds the condition code in s390 encoding. Convert it to
    844    VEX encoding (IRCmpFResult)
    845 
    846    s390     VEX              b6 b2 b0   cc.1  cc.0
    847    0      0x40 EQ             1  0  0     0     0
    848    1      0x01 LT             0  0  1     0     1
    849    2      0x00 GT             0  0  0     1     0
    850    3      0x45 Unordered      1  1  1     1     1
    851 
    852    b0 = cc.0
    853    b2 = cc.0 & cc.1
    854    b6 = ~(cc.0 ^ cc.1)   // ((cc.0 - cc.1) + 0x1 ) & 0x1
    855 
    856    VEX = b0 | (b2 << 2) | (b6 << 6);
    857 */
    858 static HReg
    859 convert_s390_to_vex_bfpcc(ISelEnv *env, HReg cc_s390)
    860 {
    861    HReg cc0, cc1, b2, b6, cc_vex;
    862 
    863    cc0 = newVRegI(env);
    864    addInstr(env, s390_insn_move(4, cc0, cc_s390));
    865    addInstr(env, s390_insn_alu(4, S390_ALU_AND, cc0, s390_opnd_imm(1)));
    866 
    867    cc1 = newVRegI(env);
    868    addInstr(env, s390_insn_move(4, cc1, cc_s390));
    869    addInstr(env, s390_insn_alu(4, S390_ALU_RSH, cc1, s390_opnd_imm(1)));
    870 
    871    b2 = newVRegI(env);
    872    addInstr(env, s390_insn_move(4, b2, cc0));
    873    addInstr(env, s390_insn_alu(4, S390_ALU_AND, b2, s390_opnd_reg(cc1)));
    874    addInstr(env, s390_insn_alu(4, S390_ALU_LSH, b2, s390_opnd_imm(2)));
    875 
    876    b6 = newVRegI(env);
    877    addInstr(env, s390_insn_move(4, b6, cc0));
    878    addInstr(env, s390_insn_alu(4, S390_ALU_SUB, b6, s390_opnd_reg(cc1)));
    879    addInstr(env, s390_insn_alu(4, S390_ALU_ADD, b6, s390_opnd_imm(1)));
    880    addInstr(env, s390_insn_alu(4, S390_ALU_AND, b6, s390_opnd_imm(1)));
    881    addInstr(env, s390_insn_alu(4, S390_ALU_LSH, b6, s390_opnd_imm(6)));
    882 
    883    cc_vex = newVRegI(env);
    884    addInstr(env, s390_insn_move(4, cc_vex, cc0));
    885    addInstr(env, s390_insn_alu(4, S390_ALU_OR, cc_vex, s390_opnd_reg(b2)));
    886    addInstr(env, s390_insn_alu(4, S390_ALU_OR, cc_vex, s390_opnd_reg(b6)));
    887 
    888    return cc_vex;
    889 }
    890 
    891 /* CC_S390 holds the condition code in s390 encoding. Convert it to
    892    VEX encoding (IRCmpDResult) */
    893 static HReg
    894 convert_s390_to_vex_dfpcc(ISelEnv *env, HReg cc_s390)
    895 {
    896    /* The encodings for IRCmpFResult and IRCmpDResult are the same/ */
    897    return convert_s390_to_vex_bfpcc(env, cc_s390);
    898 }
    899 
    900 
    901 /*---------------------------------------------------------*/
    902 /*--- ISEL: Integer expressions (128 bit)               ---*/
    903 /*---------------------------------------------------------*/
    904 static void
    905 s390_isel_int128_expr_wrk(HReg *dst_hi, HReg *dst_lo, ISelEnv *env,
    906                           IRExpr *expr)
    907 {
    908    IRType ty = typeOfIRExpr(env->type_env, expr);
    909 
    910    vassert(ty == Ity_I128);
    911 
    912    /* No need to consider the following
    913       - 128-bit constants (they do not exist in VEX)
    914       - 128-bit loads from memory (will not be generated)
    915    */
    916 
    917    /* Read 128-bit IRTemp */
    918    if (expr->tag == Iex_RdTmp) {
    919       lookupIRTemp128(dst_hi, dst_lo, env, expr->Iex.RdTmp.tmp);
    920       return;
    921    }
    922 
    923    if (expr->tag == Iex_Binop) {
    924       IRExpr *arg1 = expr->Iex.Binop.arg1;
    925       IRExpr *arg2 = expr->Iex.Binop.arg2;
    926       Bool is_signed_multiply, is_signed_divide;
    927 
    928       switch (expr->Iex.Binop.op) {
    929       case Iop_MullU64:
    930          is_signed_multiply = False;
    931          goto do_multiply64;
    932 
    933       case Iop_MullS64:
    934          is_signed_multiply = True;
    935          goto do_multiply64;
    936 
    937       case Iop_DivModU128to64:
    938          is_signed_divide = False;
    939          goto do_divide64;
    940 
    941       case Iop_DivModS128to64:
    942          is_signed_divide = True;
    943          goto do_divide64;
    944 
    945       case Iop_64HLto128:
    946          *dst_hi = s390_isel_int_expr(env, arg1);
    947          *dst_lo = s390_isel_int_expr(env, arg2);
    948          return;
    949 
    950       case Iop_DivModS64to64: {
    951          HReg r10, r11, h1;
    952          s390_opnd_RMI op2;
    953 
    954          h1  = s390_isel_int_expr(env, arg1);       /* Process 1st operand */
    955          op2 = s390_isel_int_expr_RMI(env, arg2);   /* Process 2nd operand */
    956 
    957          /* We use non-virtual registers r10 and r11 as pair */
    958          r10  = make_gpr(10);
    959          r11  = make_gpr(11);
    960 
    961          /* Move 1st operand into r11 and */
    962          addInstr(env, s390_insn_move(8, r11, h1));
    963 
    964          /* Divide */
    965          addInstr(env, s390_insn_divs(8, r10, r11, op2));
    966 
    967          /* The result is in registers r10 (remainder) and r11 (quotient).
    968             Move the result into the reg pair that is being returned such
    969             such that the low 64 bits are the quotient and the upper 64 bits
    970             are the remainder. (see libvex_ir.h). */
    971          *dst_hi = newVRegI(env);
    972          *dst_lo = newVRegI(env);
    973          addInstr(env, s390_insn_move(8, *dst_hi, r10));
    974          addInstr(env, s390_insn_move(8, *dst_lo, r11));
    975          return;
    976       }
    977 
    978       default:
    979          break;
    980 
    981       do_multiply64: {
    982             HReg r10, r11, h1;
    983             s390_opnd_RMI op2;
    984 
    985             order_commutative_operands(arg1, arg2);
    986 
    987             h1   = s390_isel_int_expr(env, arg1);       /* Process 1st operand */
    988             op2  = s390_isel_int_expr_RMI(env, arg2);   /* Process 2nd operand */
    989 
    990             /* We use non-virtual registers r10 and r11 as pair */
    991             r10  = make_gpr(10);
    992             r11  = make_gpr(11);
    993 
    994             /* Move the first operand to r11 */
    995             addInstr(env, s390_insn_move(8, r11, h1));
    996 
    997             /* Multiply */
    998             addInstr(env, s390_insn_mul(8, r10, r11, op2, is_signed_multiply));
    999 
   1000             /* The result is in registers r10 and r11. Assign to two virtual regs
   1001                and return. */
   1002             *dst_hi = newVRegI(env);
   1003             *dst_lo = newVRegI(env);
   1004             addInstr(env, s390_insn_move(8, *dst_hi, r10));
   1005             addInstr(env, s390_insn_move(8, *dst_lo, r11));
   1006             return;
   1007          }
   1008 
   1009       do_divide64: {
   1010          HReg r10, r11, hi, lo;
   1011          s390_opnd_RMI op2;
   1012 
   1013          s390_isel_int128_expr(&hi, &lo, env, arg1);
   1014          op2  = s390_isel_int_expr_RMI(env, arg2);   /* Process 2nd operand */
   1015 
   1016          /* We use non-virtual registers r10 and r11 as pair */
   1017          r10  = make_gpr(10);
   1018          r11  = make_gpr(11);
   1019 
   1020          /* Move high 64 bits of the 1st operand into r10 and
   1021             the low 64 bits into r11. */
   1022          addInstr(env, s390_insn_move(8, r10, hi));
   1023          addInstr(env, s390_insn_move(8, r11, lo));
   1024 
   1025          /* Divide */
   1026          addInstr(env, s390_insn_div(8, r10, r11, op2, is_signed_divide));
   1027 
   1028          /* The result is in registers r10 (remainder) and r11 (quotient).
   1029             Move the result into the reg pair that is being returned such
   1030             such that the low 64 bits are the quotient and the upper 64 bits
   1031             are the remainder. (see libvex_ir.h). */
   1032          *dst_hi = newVRegI(env);
   1033          *dst_lo = newVRegI(env);
   1034          addInstr(env, s390_insn_move(8, *dst_hi, r10));
   1035          addInstr(env, s390_insn_move(8, *dst_lo, r11));
   1036          return;
   1037       }
   1038       }
   1039    }
   1040 
   1041    vpanic("s390_isel_int128_expr");
   1042 }
   1043 
   1044 
   1045 /* Compute a 128-bit value into two 64-bit registers. These may be either
   1046    real or virtual regs; in any case they must not be changed by subsequent
   1047    code emitted by the caller. */
   1048 static void
   1049 s390_isel_int128_expr(HReg *dst_hi, HReg *dst_lo, ISelEnv *env, IRExpr *expr)
   1050 {
   1051    s390_isel_int128_expr_wrk(dst_hi, dst_lo, env, expr);
   1052 
   1053    /* Sanity checks ... */
   1054    vassert(hregIsVirtual(*dst_hi));
   1055    vassert(hregIsVirtual(*dst_lo));
   1056    vassert(hregClass(*dst_hi) == HRcInt64);
   1057    vassert(hregClass(*dst_lo) == HRcInt64);
   1058 }
   1059 
   1060 
   1061 /*---------------------------------------------------------*/
   1062 /*--- ISEL: Integer expressions (64/32/16/8 bit)        ---*/
   1063 /*---------------------------------------------------------*/
   1064 
   1065 /* Select insns for an integer-typed expression, and add them to the
   1066    code list.  Return a reg holding the result.  This reg will be a
   1067    virtual register.  THE RETURNED REG MUST NOT BE MODIFIED.  If you
   1068    want to modify it, ask for a new vreg, copy it in there, and modify
   1069    the copy.  The register allocator will do its best to map both
   1070    vregs to the same real register, so the copies will often disappear
   1071    later in the game.
   1072 
   1073    This should handle expressions of 64, 32, 16 and 8-bit type.
   1074    All results are returned in a 64bit register.
   1075    For 16- and 8-bit expressions, the upper (32/48/56 : 16/24) bits
   1076    are arbitrary, so you should mask or sign extend partial values
   1077    if necessary.
   1078 */
   1079 
   1080 /* DO NOT CALL THIS DIRECTLY ! */
   1081 static HReg
   1082 s390_isel_int_expr_wrk(ISelEnv *env, IRExpr *expr)
   1083 {
   1084    IRType ty = typeOfIRExpr(env->type_env, expr);
   1085    UChar size;
   1086    s390_bfp_conv_t conv;
   1087    s390_dfp_conv_t dconv;
   1088 
   1089    vassert(ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32 || ty == Ity_I64);
   1090 
   1091    size = sizeofIRType(ty);   /* size of the result after evaluating EXPR */
   1092 
   1093    switch (expr->tag) {
   1094 
   1095       /* --------- TEMP --------- */
   1096    case Iex_RdTmp:
   1097       /* Return the virtual register that holds the temporary. */
   1098       return lookupIRTemp(env, expr->Iex.RdTmp.tmp);
   1099 
   1100       /* --------- LOAD --------- */
   1101    case Iex_Load: {
   1102       HReg        dst = newVRegI(env);
   1103       s390_amode *am  = s390_isel_amode(env, expr->Iex.Load.addr);
   1104 
   1105       if (expr->Iex.Load.end != Iend_BE)
   1106          goto irreducible;
   1107 
   1108       addInstr(env, s390_insn_load(size, dst, am));
   1109 
   1110       return dst;
   1111    }
   1112 
   1113       /* --------- BINARY OP --------- */
   1114    case Iex_Binop: {
   1115       IRExpr *arg1 = expr->Iex.Binop.arg1;
   1116       IRExpr *arg2 = expr->Iex.Binop.arg2;
   1117       HReg h1, res;
   1118       s390_alu_t opkind;
   1119       s390_opnd_RMI op2, value, opnd;
   1120       s390_insn *insn;
   1121       Bool is_commutative, is_signed_multiply, is_signed_divide;
   1122 
   1123       is_commutative = True;
   1124 
   1125       switch (expr->Iex.Binop.op) {
   1126       case Iop_MullU8:
   1127       case Iop_MullU16:
   1128       case Iop_MullU32:
   1129          is_signed_multiply = False;
   1130          goto do_multiply;
   1131 
   1132       case Iop_MullS8:
   1133       case Iop_MullS16:
   1134       case Iop_MullS32:
   1135          is_signed_multiply = True;
   1136          goto do_multiply;
   1137 
   1138       do_multiply: {
   1139             HReg r10, r11;
   1140             UInt arg_size = size / 2;
   1141 
   1142             order_commutative_operands(arg1, arg2);
   1143 
   1144             h1   = s390_isel_int_expr(env, arg1);       /* Process 1st operand */
   1145             op2  = s390_isel_int_expr_RMI(env, arg2);   /* Process 2nd operand */
   1146 
   1147             /* We use non-virtual registers r10 and r11 as pair */
   1148             r10  = make_gpr(10);
   1149             r11  = make_gpr(11);
   1150 
   1151             /* Move the first operand to r11 */
   1152             addInstr(env, s390_insn_move(arg_size, r11, h1));
   1153 
   1154             /* Multiply */
   1155             addInstr(env, s390_insn_mul(arg_size, r10, r11, op2, is_signed_multiply));
   1156 
   1157             /* The result is in registers r10 and r11. Combine them into a SIZE-bit
   1158                value into the destination register. */
   1159             res  = newVRegI(env);
   1160             addInstr(env, s390_insn_move(arg_size, res, r10));
   1161             value = s390_opnd_imm(arg_size * 8);
   1162             addInstr(env, s390_insn_alu(size, S390_ALU_LSH, res, value));
   1163             value = s390_opnd_imm((((ULong)1) << arg_size * 8) - 1);
   1164             addInstr(env, s390_insn_alu(size, S390_ALU_AND, r11, value));
   1165             opnd = s390_opnd_reg(r11);
   1166             addInstr(env, s390_insn_alu(size, S390_ALU_OR,  res, opnd));
   1167             return res;
   1168          }
   1169 
   1170       case Iop_DivModS64to32:
   1171          is_signed_divide = True;
   1172          goto do_divide;
   1173 
   1174       case Iop_DivModU64to32:
   1175          is_signed_divide = False;
   1176          goto do_divide;
   1177 
   1178       do_divide: {
   1179             HReg r10, r11;
   1180 
   1181             h1   = s390_isel_int_expr(env, arg1);       /* Process 1st operand */
   1182             op2  = s390_isel_int_expr_RMI(env, arg2);   /* Process 2nd operand */
   1183 
   1184             /* We use non-virtual registers r10 and r11 as pair */
   1185             r10  = make_gpr(10);
   1186             r11  = make_gpr(11);
   1187 
   1188             /* Split the first operand and put the high 32 bits into r10 and
   1189                the low 32 bits into r11. */
   1190             addInstr(env, s390_insn_move(8, r10, h1));
   1191             addInstr(env, s390_insn_move(8, r11, h1));
   1192             value = s390_opnd_imm(32);
   1193             addInstr(env, s390_insn_alu(8, S390_ALU_RSH, r10, value));
   1194 
   1195             /* Divide */
   1196             addInstr(env, s390_insn_div(4, r10, r11, op2, is_signed_divide));
   1197 
   1198             /* The result is in registers r10 (remainder) and r11 (quotient).
   1199                Combine them into a 64-bit value such that the low 32 bits are
   1200                the quotient and the upper 32 bits are the remainder. (see
   1201                libvex_ir.h). */
   1202             res  = newVRegI(env);
   1203             addInstr(env, s390_insn_move(8, res, r10));
   1204             value = s390_opnd_imm(32);
   1205             addInstr(env, s390_insn_alu(8, S390_ALU_LSH, res, value));
   1206             value = s390_opnd_imm((((ULong)1) << 32) - 1);
   1207             addInstr(env, s390_insn_alu(8, S390_ALU_AND, r11, value));
   1208             opnd = s390_opnd_reg(r11);
   1209             addInstr(env, s390_insn_alu(8, S390_ALU_OR,  res, opnd));
   1210             return res;
   1211          }
   1212 
   1213       case Iop_F32toI32S:  conv = S390_BFP_F32_TO_I32;  goto do_convert;
   1214       case Iop_F32toI64S:  conv = S390_BFP_F32_TO_I64;  goto do_convert;
   1215       case Iop_F32toI32U:  conv = S390_BFP_F32_TO_U32;  goto do_convert;
   1216       case Iop_F32toI64U:  conv = S390_BFP_F32_TO_U64;  goto do_convert;
   1217       case Iop_F64toI32S:  conv = S390_BFP_F64_TO_I32;  goto do_convert;
   1218       case Iop_F64toI64S:  conv = S390_BFP_F64_TO_I64;  goto do_convert;
   1219       case Iop_F64toI32U:  conv = S390_BFP_F64_TO_U32;  goto do_convert;
   1220       case Iop_F64toI64U:  conv = S390_BFP_F64_TO_U64;  goto do_convert;
   1221       case Iop_F128toI32S: conv = S390_BFP_F128_TO_I32; goto do_convert_128;
   1222       case Iop_F128toI64S: conv = S390_BFP_F128_TO_I64; goto do_convert_128;
   1223       case Iop_F128toI32U: conv = S390_BFP_F128_TO_U32; goto do_convert_128;
   1224       case Iop_F128toI64U: conv = S390_BFP_F128_TO_U64; goto do_convert_128;
   1225 
   1226       case Iop_D64toI32S:  dconv = S390_DFP_D64_TO_I32;  goto do_convert_dfp;
   1227       case Iop_D64toI64S:  dconv = S390_DFP_D64_TO_I64;  goto do_convert_dfp;
   1228       case Iop_D64toI32U:  dconv = S390_DFP_D64_TO_U32;  goto do_convert_dfp;
   1229       case Iop_D64toI64U:  dconv = S390_DFP_D64_TO_U64;  goto do_convert_dfp;
   1230       case Iop_D128toI32S: dconv = S390_DFP_D128_TO_I32; goto do_convert_dfp128;
   1231       case Iop_D128toI64S: dconv = S390_DFP_D128_TO_I64; goto do_convert_dfp128;
   1232       case Iop_D128toI32U: dconv = S390_DFP_D128_TO_U32; goto do_convert_dfp128;
   1233       case Iop_D128toI64U: dconv = S390_DFP_D128_TO_U64; goto do_convert_dfp128;
   1234 
   1235       do_convert: {
   1236          s390_bfp_round_t rounding_mode;
   1237 
   1238          res  = newVRegI(env);
   1239          h1   = s390_isel_float_expr(env, arg2);   /* Process operand */
   1240 
   1241          rounding_mode = get_bfp_rounding_mode(env, arg1);
   1242          addInstr(env, s390_insn_bfp_convert(size, conv, res, h1,
   1243                                              rounding_mode));
   1244          return res;
   1245       }
   1246 
   1247       do_convert_128: {
   1248          s390_bfp_round_t rounding_mode;
   1249          HReg op_hi, op_lo, f13, f15;
   1250 
   1251          res = newVRegI(env);
   1252          s390_isel_float128_expr(&op_hi, &op_lo, env, arg2); /* operand */
   1253 
   1254          /* We use non-virtual registers r13 and r15 as pair */
   1255          f13 = make_fpr(13);
   1256          f15 = make_fpr(15);
   1257 
   1258          /* operand --> (f13, f15) */
   1259          addInstr(env, s390_insn_move(8, f13, op_hi));
   1260          addInstr(env, s390_insn_move(8, f15, op_lo));
   1261 
   1262          rounding_mode = get_bfp_rounding_mode(env, arg1);
   1263          addInstr(env, s390_insn_bfp128_convert_from(size, conv, res,
   1264                                                      INVALID_HREG, f13, f15,
   1265                                                      rounding_mode));
   1266          return res;
   1267       }
   1268 
   1269       do_convert_dfp: {
   1270             s390_dfp_round_t rounding_mode;
   1271 
   1272             res  = newVRegI(env);
   1273             h1   = s390_isel_dfp_expr(env, arg2);   /* Process operand */
   1274 
   1275             rounding_mode = get_dfp_rounding_mode(env, arg1);
   1276             addInstr(env, s390_insn_dfp_convert(size, dconv, res, h1,
   1277                                                 rounding_mode));
   1278             return res;
   1279          }
   1280 
   1281       do_convert_dfp128: {
   1282             s390_dfp_round_t rounding_mode;
   1283             HReg op_hi, op_lo, f13, f15;
   1284 
   1285             res = newVRegI(env);
   1286             s390_isel_dfp128_expr(&op_hi, &op_lo, env, arg2); /* operand */
   1287 
   1288             /* We use non-virtual registers r13 and r15 as pair */
   1289             f13 = make_fpr(13);
   1290             f15 = make_fpr(15);
   1291 
   1292             /* operand --> (f13, f15) */
   1293             addInstr(env, s390_insn_move(8, f13, op_hi));
   1294             addInstr(env, s390_insn_move(8, f15, op_lo));
   1295 
   1296             rounding_mode = get_dfp_rounding_mode(env, arg1);
   1297             addInstr(env, s390_insn_dfp128_convert_from(size, dconv, res,
   1298                                                         INVALID_HREG, f13,
   1299                                                         f15, rounding_mode));
   1300             return res;
   1301          }
   1302 
   1303       case Iop_8HLto16:
   1304       case Iop_16HLto32:
   1305       case Iop_32HLto64: {
   1306          HReg h2;
   1307          UInt arg_size = size / 2;
   1308 
   1309          res  = newVRegI(env);
   1310          h1   = s390_isel_int_expr(env, arg1);   /* Process 1st operand */
   1311          h2   = s390_isel_int_expr(env, arg2);   /* Process 2nd operand */
   1312 
   1313          addInstr(env, s390_insn_move(arg_size, res, h1));
   1314          value = s390_opnd_imm(arg_size * 8);
   1315          addInstr(env, s390_insn_alu(size, S390_ALU_LSH, res, value));
   1316          value = s390_opnd_imm((((ULong)1) << arg_size * 8) - 1);
   1317          addInstr(env, s390_insn_alu(size, S390_ALU_AND, h2, value));
   1318          opnd = s390_opnd_reg(h2);
   1319          addInstr(env, s390_insn_alu(size, S390_ALU_OR,  res, opnd));
   1320          return res;
   1321       }
   1322 
   1323       case Iop_Max32U: {
   1324          /* arg1 > arg2 ? arg1 : arg2   using uint32_t arguments */
   1325          res = newVRegI(env);
   1326          h1  = s390_isel_int_expr(env, arg1);
   1327          op2 = s390_isel_int_expr_RMI(env, arg2);
   1328 
   1329          addInstr(env, s390_insn_move(size, res, h1));
   1330          addInstr(env, s390_insn_compare(size, res, op2, False /* signed */));
   1331          addInstr(env, s390_insn_cond_move(size, S390_CC_L, res, op2));
   1332          return res;
   1333       }
   1334 
   1335       case Iop_CmpF32:
   1336       case Iop_CmpF64: {
   1337          HReg cc_s390, h2;
   1338 
   1339          h1 = s390_isel_float_expr(env, arg1);
   1340          h2 = s390_isel_float_expr(env, arg2);
   1341          cc_s390 = newVRegI(env);
   1342 
   1343          size = (expr->Iex.Binop.op == Iop_CmpF32) ? 4 : 8;
   1344 
   1345          addInstr(env, s390_insn_bfp_compare(size, cc_s390, h1, h2));
   1346 
   1347          return convert_s390_to_vex_bfpcc(env, cc_s390);
   1348       }
   1349 
   1350       case Iop_CmpF128: {
   1351          HReg op1_hi, op1_lo, op2_hi, op2_lo, f12, f13, f14, f15, cc_s390;
   1352 
   1353          s390_isel_float128_expr(&op1_hi, &op1_lo, env, arg1); /* 1st operand */
   1354          s390_isel_float128_expr(&op2_hi, &op2_lo, env, arg2); /* 2nd operand */
   1355          cc_s390 = newVRegI(env);
   1356 
   1357          /* We use non-virtual registers as pairs (f13, f15) and (f12, f14)) */
   1358          f12 = make_fpr(12);
   1359          f13 = make_fpr(13);
   1360          f14 = make_fpr(14);
   1361          f15 = make_fpr(15);
   1362 
   1363          /* 1st operand --> (f12, f14) */
   1364          addInstr(env, s390_insn_move(8, f12, op1_hi));
   1365          addInstr(env, s390_insn_move(8, f14, op1_lo));
   1366 
   1367          /* 2nd operand --> (f13, f15) */
   1368          addInstr(env, s390_insn_move(8, f13, op2_hi));
   1369          addInstr(env, s390_insn_move(8, f15, op2_lo));
   1370 
   1371          res = newVRegI(env);
   1372          addInstr(env, s390_insn_bfp128_compare(16, cc_s390, f12, f14, f13, f15));
   1373 
   1374          return convert_s390_to_vex_bfpcc(env, cc_s390);
   1375       }
   1376 
   1377       case Iop_CmpD64:
   1378       case Iop_CmpExpD64: {
   1379          HReg cc_s390, h2;
   1380          s390_dfp_cmp_t cmp;
   1381 
   1382          h1 = s390_isel_dfp_expr(env, arg1);
   1383          h2 = s390_isel_dfp_expr(env, arg2);
   1384          cc_s390 = newVRegI(env);
   1385 
   1386          switch(expr->Iex.Binop.op) {
   1387          case Iop_CmpD64:    cmp = S390_DFP_COMPARE; break;
   1388          case Iop_CmpExpD64: cmp = S390_DFP_COMPARE_EXP; break;
   1389          default: goto irreducible;
   1390          }
   1391          addInstr(env, s390_insn_dfp_compare(8, cmp, cc_s390, h1, h2));
   1392 
   1393          return convert_s390_to_vex_dfpcc(env, cc_s390);
   1394       }
   1395 
   1396       case Iop_CmpD128:
   1397       case Iop_CmpExpD128: {
   1398          HReg op1_hi, op1_lo, op2_hi, op2_lo, f12, f13, f14, f15, cc_s390;
   1399          s390_dfp_cmp_t cmp;
   1400 
   1401          s390_isel_dfp128_expr(&op1_hi, &op1_lo, env, arg1); /* 1st operand */
   1402          s390_isel_dfp128_expr(&op2_hi, &op2_lo, env, arg2); /* 2nd operand */
   1403          cc_s390 = newVRegI(env);
   1404 
   1405          /* We use non-virtual registers as pairs (f13, f15) and (f12, f14)) */
   1406          f12 = make_fpr(12);
   1407          f13 = make_fpr(13);
   1408          f14 = make_fpr(14);
   1409          f15 = make_fpr(15);
   1410 
   1411          /* 1st operand --> (f12, f14) */
   1412          addInstr(env, s390_insn_move(8, f12, op1_hi));
   1413          addInstr(env, s390_insn_move(8, f14, op1_lo));
   1414 
   1415          /* 2nd operand --> (f13, f15) */
   1416          addInstr(env, s390_insn_move(8, f13, op2_hi));
   1417          addInstr(env, s390_insn_move(8, f15, op2_lo));
   1418 
   1419          switch(expr->Iex.Binop.op) {
   1420          case Iop_CmpD128:    cmp = S390_DFP_COMPARE; break;
   1421          case Iop_CmpExpD128: cmp = S390_DFP_COMPARE_EXP; break;
   1422          default: goto irreducible;
   1423          }
   1424          addInstr(env, s390_insn_dfp128_compare(16, cmp, cc_s390, f12, f14,
   1425                                                 f13, f15));
   1426 
   1427          return convert_s390_to_vex_dfpcc(env, cc_s390);
   1428       }
   1429 
   1430       case Iop_Add8:
   1431       case Iop_Add16:
   1432       case Iop_Add32:
   1433       case Iop_Add64:
   1434          opkind = S390_ALU_ADD;
   1435          break;
   1436 
   1437       case Iop_Sub8:
   1438       case Iop_Sub16:
   1439       case Iop_Sub32:
   1440       case Iop_Sub64:
   1441          opkind = S390_ALU_SUB;
   1442          is_commutative = False;
   1443          break;
   1444 
   1445       case Iop_And8:
   1446       case Iop_And16:
   1447       case Iop_And32:
   1448       case Iop_And64:
   1449          opkind = S390_ALU_AND;
   1450          break;
   1451 
   1452       case Iop_Or8:
   1453       case Iop_Or16:
   1454       case Iop_Or32:
   1455       case Iop_Or64:
   1456          opkind = S390_ALU_OR;
   1457          break;
   1458 
   1459       case Iop_Xor8:
   1460       case Iop_Xor16:
   1461       case Iop_Xor32:
   1462       case Iop_Xor64:
   1463          opkind = S390_ALU_XOR;
   1464          break;
   1465 
   1466       case Iop_Shl8:
   1467       case Iop_Shl16:
   1468       case Iop_Shl32:
   1469       case Iop_Shl64:
   1470          opkind = S390_ALU_LSH;
   1471          is_commutative = False;
   1472          break;
   1473 
   1474       case Iop_Shr8:
   1475       case Iop_Shr16:
   1476       case Iop_Shr32:
   1477       case Iop_Shr64:
   1478          opkind = S390_ALU_RSH;
   1479          is_commutative = False;
   1480          break;
   1481 
   1482       case Iop_Sar8:
   1483       case Iop_Sar16:
   1484       case Iop_Sar32:
   1485       case Iop_Sar64:
   1486          opkind = S390_ALU_RSHA;
   1487          is_commutative = False;
   1488          break;
   1489 
   1490       default:
   1491          goto irreducible;
   1492       }
   1493 
   1494       /* Pattern match: 0 - arg1  -->  -arg1   */
   1495       if (opkind == S390_ALU_SUB && s390_expr_is_const_zero(arg1)) {
   1496          res  = newVRegI(env);
   1497          op2  = s390_isel_int_expr_RMI(env, arg2);   /* Process 2nd operand */
   1498          insn = s390_insn_unop(size, S390_NEGATE, res, op2);
   1499          addInstr(env, insn);
   1500 
   1501          return res;
   1502       }
   1503 
   1504       if (is_commutative) {
   1505          order_commutative_operands(arg1, arg2);
   1506       }
   1507 
   1508       h1   = s390_isel_int_expr(env, arg1);       /* Process 1st operand */
   1509       op2  = s390_isel_int_expr_RMI(env, arg2);   /* Process 2nd operand */
   1510       res  = newVRegI(env);
   1511 
   1512       /* As right shifts of one/two byte opreands are implemented using a
   1513          4-byte shift op, we first need to zero/sign-extend the shiftee. */
   1514       switch (expr->Iex.Binop.op) {
   1515       case Iop_Shr8:
   1516          insn = s390_insn_unop(4, S390_ZERO_EXTEND_8, res, s390_opnd_reg(h1));
   1517          break;
   1518       case Iop_Shr16:
   1519          insn = s390_insn_unop(4, S390_ZERO_EXTEND_16, res, s390_opnd_reg(h1));
   1520          break;
   1521       case Iop_Sar8:
   1522          insn = s390_insn_unop(4, S390_SIGN_EXTEND_8, res, s390_opnd_reg(h1));
   1523          break;
   1524       case Iop_Sar16:
   1525          insn = s390_insn_unop(4, S390_SIGN_EXTEND_16, res, s390_opnd_reg(h1));
   1526          break;
   1527       default:
   1528          insn = s390_insn_move(size, res, h1);
   1529          break;
   1530       }
   1531       addInstr(env, insn);
   1532 
   1533       insn = s390_insn_alu(size, opkind, res, op2);
   1534 
   1535       addInstr(env, insn);
   1536 
   1537       return res;
   1538    }
   1539 
   1540       /* --------- UNARY OP --------- */
   1541    case Iex_Unop: {
   1542       static s390_opnd_RMI mask  = { S390_OPND_IMMEDIATE };
   1543       static s390_opnd_RMI shift = { S390_OPND_IMMEDIATE };
   1544       s390_opnd_RMI opnd;
   1545       s390_insn    *insn;
   1546       IRExpr *arg;
   1547       HReg    dst, h1;
   1548       IROp    unop, binop;
   1549 
   1550       arg = expr->Iex.Unop.arg;
   1551 
   1552       /* Special cases are handled here */
   1553 
   1554       /* 32-bit multiply with 32-bit result or
   1555          64-bit multiply with 64-bit result */
   1556       unop  = expr->Iex.Unop.op;
   1557       binop = arg->Iex.Binop.op;
   1558 
   1559       if ((arg->tag == Iex_Binop &&
   1560            ((unop == Iop_64to32 &&
   1561              (binop == Iop_MullS32 || binop == Iop_MullU32)) ||
   1562             (unop == Iop_128to64 &&
   1563              (binop == Iop_MullS64 || binop == Iop_MullU64))))) {
   1564          h1   = s390_isel_int_expr(env, arg->Iex.Binop.arg1);     /* 1st opnd */
   1565          opnd = s390_isel_int_expr_RMI(env, arg->Iex.Binop.arg2); /* 2nd opnd */
   1566          dst  = newVRegI(env);     /* Result goes into a new register */
   1567          addInstr(env, s390_insn_move(size, dst, h1));
   1568          addInstr(env, s390_insn_alu(size, S390_ALU_MUL, dst, opnd));
   1569 
   1570          return dst;
   1571       }
   1572 
   1573       if (unop == Iop_ReinterpF64asI64 || unop == Iop_ReinterpF32asI32) {
   1574          dst = newVRegI(env);
   1575          h1  = s390_isel_float_expr(env, arg);     /* Process the operand */
   1576          addInstr(env, s390_insn_move(size, dst, h1));
   1577 
   1578          return dst;
   1579       }
   1580 
   1581       if (unop == Iop_ReinterpD64asI64) {
   1582          dst = newVRegI(env);
   1583          h1  = s390_isel_dfp_expr(env, arg);     /* Process the operand */
   1584          addInstr(env, s390_insn_move(size, dst, h1));
   1585 
   1586          return dst;
   1587       }
   1588 
   1589       if (unop == Iop_ExtractExpD64 || unop == Iop_ExtractSigD64) {
   1590          s390_dfp_unop_t dfpop;
   1591          switch(unop) {
   1592          case Iop_ExtractExpD64: dfpop = S390_DFP_EXTRACT_EXP_D64; break;
   1593          case Iop_ExtractSigD64: dfpop = S390_DFP_EXTRACT_SIG_D64; break;
   1594          default: goto irreducible;
   1595          }
   1596          dst = newVRegI(env);
   1597          h1  = s390_isel_dfp_expr(env, arg);     /* Process the operand */
   1598          addInstr(env, s390_insn_dfp_unop(size, dfpop, dst, h1));
   1599          return dst;
   1600       }
   1601 
   1602       if (unop == Iop_ExtractExpD128 || unop == Iop_ExtractSigD128) {
   1603          s390_dfp_unop_t dfpop;
   1604          HReg op_hi, op_lo, f13, f15;
   1605 
   1606          switch(unop) {
   1607          case Iop_ExtractExpD128: dfpop = S390_DFP_EXTRACT_EXP_D128; break;
   1608          case Iop_ExtractSigD128: dfpop = S390_DFP_EXTRACT_SIG_D128; break;
   1609          default: goto irreducible;
   1610          }
   1611          dst = newVRegI(env);
   1612          s390_isel_dfp128_expr(&op_hi, &op_lo, env, arg); /* Process operand */
   1613 
   1614          /* We use non-virtual registers r13 and r15 as pair */
   1615          f13 = make_fpr(13);
   1616          f15 = make_fpr(15);
   1617 
   1618          /* operand --> (f13, f15) */
   1619          addInstr(env, s390_insn_move(8, f13, op_hi));
   1620          addInstr(env, s390_insn_move(8, f15, op_lo));
   1621 
   1622          addInstr(env, s390_insn_dfp128_unop(size, dfpop, dst, f13, f15));
   1623          return dst;
   1624       }
   1625 
   1626       /* Expressions whose argument is 1-bit wide */
   1627       if (typeOfIRExpr(env->type_env, arg) == Ity_I1) {
   1628          s390_cc_t cond = s390_isel_cc(env, arg);
   1629          dst = newVRegI(env);     /* Result goes into a new register */
   1630          addInstr(env, s390_insn_cc2bool(dst, cond));
   1631 
   1632          switch (unop) {
   1633          case Iop_1Uto8:
   1634          case Iop_1Uto32:
   1635             /* Zero extend */
   1636             mask.variant.imm = 1;
   1637             addInstr(env, s390_insn_alu(4, S390_ALU_AND,  dst, mask));
   1638             break;
   1639 
   1640          case Iop_1Uto64:
   1641             /* Zero extend */
   1642             mask.variant.imm = 1;
   1643             addInstr(env, s390_insn_alu(8, S390_ALU_AND,  dst, mask));
   1644             break;
   1645 
   1646          case Iop_1Sto8:
   1647          case Iop_1Sto16:
   1648          case Iop_1Sto32:
   1649             shift.variant.imm = 31;
   1650             addInstr(env, s390_insn_alu(4, S390_ALU_LSH,  dst, shift));
   1651             addInstr(env, s390_insn_alu(4, S390_ALU_RSHA, dst, shift));
   1652             break;
   1653 
   1654          case Iop_1Sto64:
   1655             shift.variant.imm = 63;
   1656             addInstr(env, s390_insn_alu(8, S390_ALU_LSH,  dst, shift));
   1657             addInstr(env, s390_insn_alu(8, S390_ALU_RSHA, dst, shift));
   1658             break;
   1659 
   1660          default:
   1661             goto irreducible;
   1662          }
   1663 
   1664          return dst;
   1665       }
   1666 
   1667       /* Regular processing */
   1668 
   1669       if (unop == Iop_128to64) {
   1670          HReg dst_hi, dst_lo;
   1671 
   1672          s390_isel_int128_expr(&dst_hi, &dst_lo, env, arg);
   1673          return dst_lo;
   1674       }
   1675 
   1676       if (unop == Iop_128HIto64) {
   1677          HReg dst_hi, dst_lo;
   1678 
   1679          s390_isel_int128_expr(&dst_hi, &dst_lo, env, arg);
   1680          return dst_hi;
   1681       }
   1682 
   1683       dst  = newVRegI(env);     /* Result goes into a new register */
   1684       opnd = s390_isel_int_expr_RMI(env, arg);     /* Process the operand */
   1685 
   1686       switch (unop) {
   1687       case Iop_8Uto16:
   1688       case Iop_8Uto32:
   1689       case Iop_8Uto64:
   1690          insn = s390_insn_unop(size, S390_ZERO_EXTEND_8, dst, opnd);
   1691          break;
   1692 
   1693       case Iop_16Uto32:
   1694       case Iop_16Uto64:
   1695          insn = s390_insn_unop(size, S390_ZERO_EXTEND_16, dst, opnd);
   1696          break;
   1697 
   1698       case Iop_32Uto64:
   1699          insn = s390_insn_unop(size, S390_ZERO_EXTEND_32, dst, opnd);
   1700          break;
   1701 
   1702       case Iop_8Sto16:
   1703       case Iop_8Sto32:
   1704       case Iop_8Sto64:
   1705          insn = s390_insn_unop(size, S390_SIGN_EXTEND_8, dst, opnd);
   1706          break;
   1707 
   1708       case Iop_16Sto32:
   1709       case Iop_16Sto64:
   1710          insn = s390_insn_unop(size, S390_SIGN_EXTEND_16, dst, opnd);
   1711          break;
   1712 
   1713       case Iop_32Sto64:
   1714          insn = s390_insn_unop(size, S390_SIGN_EXTEND_32, dst, opnd);
   1715          break;
   1716 
   1717       case Iop_64to8:
   1718       case Iop_64to16:
   1719       case Iop_64to32:
   1720       case Iop_32to8:
   1721       case Iop_32to16:
   1722       case Iop_16to8:
   1723          /* Down-casts are no-ops. Upstream operations will only look at
   1724             the bytes that make up the result of the down-cast. So there
   1725             is no point setting the other bytes to 0. */
   1726          insn = s390_opnd_copy(8, dst, opnd);
   1727          break;
   1728 
   1729       case Iop_64HIto32:
   1730          addInstr(env, s390_opnd_copy(8, dst, opnd));
   1731          shift.variant.imm = 32;
   1732          insn = s390_insn_alu(8, S390_ALU_RSH, dst, shift);
   1733          break;
   1734 
   1735       case Iop_32HIto16:
   1736          addInstr(env, s390_opnd_copy(4, dst, opnd));
   1737          shift.variant.imm = 16;
   1738          insn = s390_insn_alu(4, S390_ALU_RSH, dst, shift);
   1739          break;
   1740 
   1741       case Iop_16HIto8:
   1742          addInstr(env, s390_opnd_copy(2, dst, opnd));
   1743          shift.variant.imm = 8;
   1744          insn = s390_insn_alu(2, S390_ALU_RSH, dst, shift);
   1745          break;
   1746 
   1747       case Iop_Not8:
   1748       case Iop_Not16:
   1749       case Iop_Not32:
   1750       case Iop_Not64:
   1751          /* XOR with ffff... */
   1752          mask.variant.imm = ~(ULong)0;
   1753          addInstr(env, s390_opnd_copy(size, dst, opnd));
   1754          insn = s390_insn_alu(size, S390_ALU_XOR, dst, mask);
   1755          break;
   1756 
   1757       case Iop_Left8:
   1758       case Iop_Left16:
   1759       case Iop_Left32:
   1760       case Iop_Left64:
   1761          addInstr(env, s390_insn_unop(size, S390_NEGATE, dst, opnd));
   1762          insn = s390_insn_alu(size, S390_ALU_OR, dst, opnd);
   1763          break;
   1764 
   1765       case Iop_CmpwNEZ32:
   1766       case Iop_CmpwNEZ64: {
   1767          /* Use the fact that x | -x == 0 iff x == 0. Otherwise, either X
   1768             or -X will have a 1 in the MSB. */
   1769          addInstr(env, s390_insn_unop(size, S390_NEGATE, dst, opnd));
   1770          addInstr(env, s390_insn_alu(size, S390_ALU_OR,  dst, opnd));
   1771          shift.variant.imm = (unop == Iop_CmpwNEZ32) ? 31 : 63;
   1772          addInstr(env, s390_insn_alu(size, S390_ALU_RSHA,  dst, shift));
   1773          return dst;
   1774       }
   1775 
   1776       case Iop_Clz64: {
   1777          HReg r10, r11;
   1778 
   1779          /* This will be implemented using FLOGR, if possible. So we need to
   1780             set aside a pair of non-virtual registers. The result (number of
   1781             left-most zero bits) will be in r10. The value in r11 is unspecified
   1782             and must not be used. */
   1783          r10  = make_gpr(10);
   1784          r11  = make_gpr(11);
   1785 
   1786          addInstr(env, s390_insn_clz(8, r10, r11, opnd));
   1787          addInstr(env, s390_insn_move(8, dst, r10));
   1788          return dst;
   1789       }
   1790 
   1791       default:
   1792          goto irreducible;
   1793       }
   1794 
   1795       addInstr(env, insn);
   1796 
   1797       return dst;
   1798    }
   1799 
   1800       /* --------- GET --------- */
   1801    case Iex_Get: {
   1802       HReg dst = newVRegI(env);
   1803       s390_amode *am = s390_amode_for_guest_state(expr->Iex.Get.offset);
   1804 
   1805       /* We never load more than 8 bytes from the guest state, because the
   1806          floating point register pair is not contiguous. */
   1807       vassert(size <= 8);
   1808 
   1809       addInstr(env, s390_insn_load(size, dst, am));
   1810 
   1811       return dst;
   1812    }
   1813 
   1814    case Iex_GetI:
   1815       /* not needed */
   1816       break;
   1817 
   1818       /* --------- CCALL --------- */
   1819    case Iex_CCall: {
   1820       HReg dst = newVRegI(env);
   1821       HReg ret = make_gpr(S390_REGNO_RETURN_VALUE);
   1822       UInt   addToSp = 0;
   1823       RetLoc rloc    = mk_RetLoc_INVALID();
   1824 
   1825       doHelperCall(&addToSp, &rloc, env, NULL, expr->Iex.CCall.cee,
   1826                    expr->Iex.CCall.retty, expr->Iex.CCall.args);
   1827       vassert(is_sane_RetLoc(rloc));
   1828       vassert(rloc.pri == RLPri_Int);
   1829       vassert(addToSp == 0);
   1830       addInstr(env, s390_insn_move(sizeof(ULong), dst, ret));
   1831 
   1832       return dst;
   1833    }
   1834 
   1835       /* --------- LITERAL --------- */
   1836 
   1837       /* Load a literal into a register. Create a "load immediate"
   1838          v-insn and return the register. */
   1839    case Iex_Const: {
   1840       ULong value;
   1841       HReg  dst = newVRegI(env);
   1842       const IRConst *con = expr->Iex.Const.con;
   1843 
   1844       /* Bitwise copy of the value. No sign/zero-extension */
   1845       switch (con->tag) {
   1846       case Ico_U64: value = con->Ico.U64; break;
   1847       case Ico_U32: value = con->Ico.U32; break;
   1848       case Ico_U16: value = con->Ico.U16; break;
   1849       case Ico_U8:  value = con->Ico.U8;  break;
   1850       default:      vpanic("s390_isel_int_expr: invalid constant");
   1851       }
   1852 
   1853       addInstr(env, s390_insn_load_immediate(size, dst, value));
   1854 
   1855       return dst;
   1856    }
   1857 
   1858       /* --------- MULTIPLEX --------- */
   1859    case Iex_ITE: {
   1860       IRExpr *cond_expr;
   1861       HReg dst, r1;
   1862       s390_opnd_RMI r0;
   1863 
   1864       cond_expr = expr->Iex.ITE.cond;
   1865 
   1866       vassert(typeOfIRExpr(env->type_env, cond_expr) == Ity_I1);
   1867 
   1868       dst  = newVRegI(env);
   1869       r0   = s390_isel_int_expr_RMI(env, expr->Iex.ITE.iffalse);
   1870       r1   = s390_isel_int_expr(env, expr->Iex.ITE.iftrue);
   1871       size = sizeofIRType(typeOfIRExpr(env->type_env, expr->Iex.ITE.iftrue));
   1872 
   1873       s390_cc_t cc = s390_isel_cc(env, cond_expr);
   1874 
   1875       addInstr(env, s390_insn_move(size, dst, r1));
   1876       addInstr(env, s390_insn_cond_move(size, s390_cc_invert(cc), dst, r0));
   1877       return dst;
   1878    }
   1879 
   1880    default:
   1881       break;
   1882    }
   1883 
   1884    /* We get here if no pattern matched. */
   1885  irreducible:
   1886    ppIRExpr(expr);
   1887    vpanic("s390_isel_int_expr: cannot reduce tree");
   1888 }
   1889 
   1890 
   1891 static HReg
   1892 s390_isel_int_expr(ISelEnv *env, IRExpr *expr)
   1893 {
   1894    HReg dst = s390_isel_int_expr_wrk(env, expr);
   1895 
   1896    /* Sanity checks ... */
   1897    vassert(hregClass(dst) == HRcInt64);
   1898    vassert(hregIsVirtual(dst));
   1899 
   1900    return dst;
   1901 }
   1902 
   1903 
   1904 static s390_opnd_RMI
   1905 s390_isel_int_expr_RMI(ISelEnv *env, IRExpr *expr)
   1906 {
   1907    IRType ty = typeOfIRExpr(env->type_env, expr);
   1908    s390_opnd_RMI dst;
   1909 
   1910    vassert(ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32 ||
   1911            ty == Ity_I64);
   1912 
   1913    if (expr->tag == Iex_Load) {
   1914       dst.tag = S390_OPND_AMODE;
   1915       dst.variant.am = s390_isel_amode(env, expr->Iex.Load.addr);
   1916    } else if (expr->tag == Iex_Get) {
   1917       dst.tag = S390_OPND_AMODE;
   1918       dst.variant.am = s390_amode_for_guest_state(expr->Iex.Get.offset);
   1919    } else if (expr->tag == Iex_Const) {
   1920       ULong value;
   1921 
   1922       /* The bit pattern for the value will be stored as is in the least
   1923          significant bits of VALUE. */
   1924       switch (expr->Iex.Const.con->tag) {
   1925       case Ico_U1:  value = expr->Iex.Const.con->Ico.U1;  break;
   1926       case Ico_U8:  value = expr->Iex.Const.con->Ico.U8;  break;
   1927       case Ico_U16: value = expr->Iex.Const.con->Ico.U16; break;
   1928       case Ico_U32: value = expr->Iex.Const.con->Ico.U32; break;
   1929       case Ico_U64: value = expr->Iex.Const.con->Ico.U64; break;
   1930       default:
   1931          vpanic("s390_isel_int_expr_RMI");
   1932       }
   1933 
   1934       dst.tag = S390_OPND_IMMEDIATE;
   1935       dst.variant.imm = value;
   1936    } else {
   1937       dst.tag = S390_OPND_REG;
   1938       dst.variant.reg = s390_isel_int_expr(env, expr);
   1939    }
   1940 
   1941    return dst;
   1942 }
   1943 
   1944 
   1945 /*---------------------------------------------------------*/
   1946 /*--- ISEL: Floating point expressions (128 bit)        ---*/
   1947 /*---------------------------------------------------------*/
   1948 static void
   1949 s390_isel_float128_expr_wrk(HReg *dst_hi, HReg *dst_lo, ISelEnv *env,
   1950                             IRExpr *expr)
   1951 {
   1952    IRType ty = typeOfIRExpr(env->type_env, expr);
   1953 
   1954    vassert(ty == Ity_F128);
   1955 
   1956    switch (expr->tag) {
   1957    case Iex_RdTmp:
   1958       /* Return the virtual registers that hold the temporary. */
   1959       lookupIRTemp128(dst_hi, dst_lo, env, expr->Iex.RdTmp.tmp);
   1960       return;
   1961 
   1962       /* --------- LOAD --------- */
   1963    case Iex_Load: {
   1964       IRExpr *addr_hi, *addr_lo;
   1965       s390_amode *am_hi, *am_lo;
   1966 
   1967       if (expr->Iex.Load.end != Iend_BE)
   1968          goto irreducible;
   1969 
   1970       addr_hi = expr->Iex.Load.addr;
   1971       addr_lo = IRExpr_Binop(Iop_Add64, addr_hi, mkU64(8));
   1972 
   1973       am_hi  = s390_isel_amode(env, addr_hi);
   1974       am_lo  = s390_isel_amode(env, addr_lo);
   1975 
   1976       *dst_hi = newVRegF(env);
   1977       *dst_lo = newVRegF(env);
   1978       addInstr(env, s390_insn_load(8, *dst_hi, am_hi));
   1979       addInstr(env, s390_insn_load(8, *dst_hi, am_lo));
   1980       return;
   1981    }
   1982 
   1983 
   1984       /* --------- GET --------- */
   1985    case Iex_Get:
   1986       /* This is not supported because loading 128-bit from the guest
   1987          state is almost certainly wrong. Use get_fpr_pair instead. */
   1988       vpanic("Iex_Get with F128 data");
   1989 
   1990       /* --------- 4-ary OP --------- */
   1991    case Iex_Qop:
   1992       vpanic("Iex_Qop with F128 data");
   1993 
   1994       /* --------- TERNARY OP --------- */
   1995    case Iex_Triop: {
   1996       IRTriop *triop = expr->Iex.Triop.details;
   1997       IROp    op     = triop->op;
   1998       IRExpr *left   = triop->arg2;
   1999       IRExpr *right  = triop->arg3;
   2000       s390_bfp_binop_t bfpop;
   2001       HReg op1_hi, op1_lo, op2_hi, op2_lo, f12, f13, f14, f15;
   2002 
   2003       s390_isel_float128_expr(&op1_hi, &op1_lo, env, left);  /* 1st operand */
   2004       s390_isel_float128_expr(&op2_hi, &op2_lo, env, right); /* 2nd operand */
   2005 
   2006       /* We use non-virtual registers as pairs (f13, f15) and (f12, f14)) */
   2007       f12 = make_fpr(12);
   2008       f13 = make_fpr(13);
   2009       f14 = make_fpr(14);
   2010       f15 = make_fpr(15);
   2011 
   2012       /* 1st operand --> (f12, f14) */
   2013       addInstr(env, s390_insn_move(8, f12, op1_hi));
   2014       addInstr(env, s390_insn_move(8, f14, op1_lo));
   2015 
   2016       /* 2nd operand --> (f13, f15) */
   2017       addInstr(env, s390_insn_move(8, f13, op2_hi));
   2018       addInstr(env, s390_insn_move(8, f15, op2_lo));
   2019 
   2020       switch (op) {
   2021       case Iop_AddF128: bfpop = S390_BFP_ADD; break;
   2022       case Iop_SubF128: bfpop = S390_BFP_SUB; break;
   2023       case Iop_MulF128: bfpop = S390_BFP_MUL; break;
   2024       case Iop_DivF128: bfpop = S390_BFP_DIV; break;
   2025       default:
   2026          goto irreducible;
   2027       }
   2028 
   2029       set_bfp_rounding_mode_in_fpc(env, triop->arg1);
   2030       addInstr(env, s390_insn_bfp128_binop(16, bfpop, f12, f14, f13, f15));
   2031 
   2032       /* Move result to virtual destination register */
   2033       *dst_hi = newVRegF(env);
   2034       *dst_lo = newVRegF(env);
   2035       addInstr(env, s390_insn_move(8, *dst_hi, f12));
   2036       addInstr(env, s390_insn_move(8, *dst_lo, f14));
   2037 
   2038       return;
   2039    }
   2040 
   2041       /* --------- BINARY OP --------- */
   2042    case Iex_Binop: {
   2043       switch (expr->Iex.Binop.op) {
   2044       case Iop_SqrtF128: {
   2045          HReg op_hi, op_lo, f12, f13, f14, f15;
   2046 
   2047          /* We use non-virtual registers as pairs (f13, f15) and (f12, f14)) */
   2048          f12 = make_fpr(12);
   2049          f13 = make_fpr(13);
   2050          f14 = make_fpr(14);
   2051          f15 = make_fpr(15);
   2052 
   2053          s390_isel_float128_expr(&op_hi, &op_lo, env, expr->Iex.Binop.arg2);
   2054 
   2055          /* operand --> (f13, f15) */
   2056          addInstr(env, s390_insn_move(8, f13, op_hi));
   2057          addInstr(env, s390_insn_move(8, f15, op_lo));
   2058 
   2059          set_bfp_rounding_mode_in_fpc(env, expr->Iex.Binop.arg1);
   2060          addInstr(env, s390_insn_bfp128_unop(16, S390_BFP_SQRT, f12, f14,
   2061                                              f13, f15));
   2062 
   2063          /* Move result to virtual destination registers */
   2064          *dst_hi = newVRegF(env);
   2065          *dst_lo = newVRegF(env);
   2066          addInstr(env, s390_insn_move(8, *dst_hi, f12));
   2067          addInstr(env, s390_insn_move(8, *dst_lo, f14));
   2068          return;
   2069       }
   2070 
   2071       case Iop_F64HLtoF128:
   2072          *dst_hi = s390_isel_float_expr(env, expr->Iex.Binop.arg1);
   2073          *dst_lo = s390_isel_float_expr(env, expr->Iex.Binop.arg2);
   2074          return;
   2075 
   2076       case Iop_D32toF128:
   2077       case Iop_D64toF128: {
   2078          IRExpr *irrm;
   2079          IRExpr *left;
   2080          s390_dfp_round_t rm;
   2081          HReg h1; /* virtual reg. to hold source */
   2082          HReg f0, f2, f4, r1; /* real registers used by PFPO */
   2083          s390_fp_conv_t fpconv;
   2084 
   2085          switch (expr->Iex.Binop.op) {
   2086          case Iop_D32toF128:
   2087             fpconv = S390_FP_D32_TO_F128;
   2088             break;
   2089          case Iop_D64toF128:
   2090             fpconv = S390_FP_D64_TO_F128;
   2091             break;
   2092          default: goto irreducible;
   2093          }
   2094 
   2095          f4 = make_fpr(4); /* source */
   2096          f0 = make_fpr(0); /* destination */
   2097          f2 = make_fpr(2); /* destination */
   2098          r1 = make_gpr(1); /* GPR #1 clobbered */
   2099          irrm = expr->Iex.Binop.arg1;
   2100          left = expr->Iex.Binop.arg2;
   2101          rm = get_dfp_rounding_mode(env, irrm);
   2102          h1 = s390_isel_dfp_expr(env, left);
   2103          addInstr(env, s390_insn_move(8, f4, h1));
   2104          addInstr(env, s390_insn_fp128_convert(16, fpconv, f0, f2,
   2105                                                f4, INVALID_HREG, r1, rm));
   2106          /* (f0, f2) --> destination */
   2107          *dst_hi = newVRegF(env);
   2108          *dst_lo = newVRegF(env);
   2109          addInstr(env, s390_insn_move(8, *dst_hi, f0));
   2110          addInstr(env, s390_insn_move(8, *dst_lo, f2));
   2111 
   2112          return;
   2113       }
   2114 
   2115       case Iop_D128toF128: {
   2116          IRExpr *irrm;
   2117          IRExpr *left;
   2118          s390_dfp_round_t rm;
   2119          HReg op_hi, op_lo;
   2120          HReg f0, f2, f4, f6, r1; /* real registers used by PFPO */
   2121 
   2122          f4 = make_fpr(4); /* source */
   2123          f6 = make_fpr(6); /* source */
   2124          f0 = make_fpr(0); /* destination */
   2125          f2 = make_fpr(2); /* destination */
   2126          r1 = make_gpr(1); /* GPR #1 clobbered */
   2127 
   2128          irrm = expr->Iex.Binop.arg1;
   2129          left = expr->Iex.Binop.arg2;
   2130          rm = get_dfp_rounding_mode(env, irrm);
   2131          s390_isel_dfp128_expr(&op_hi, &op_lo, env, left);
   2132          /* operand --> (f4, f6) */
   2133          addInstr(env, s390_insn_move(8, f4, op_hi));
   2134          addInstr(env, s390_insn_move(8, f6, op_lo));
   2135          addInstr(env, s390_insn_fp128_convert(16, S390_FP_D128_TO_F128, f0, f2,
   2136                                                f4, f6, r1, rm));
   2137          /* (f0, f2) --> destination */
   2138          *dst_hi = newVRegF(env);
   2139          *dst_lo = newVRegF(env);
   2140          addInstr(env, s390_insn_move(8, *dst_hi, f0));
   2141          addInstr(env, s390_insn_move(8, *dst_lo, f2));
   2142 
   2143          return;
   2144       }
   2145 
   2146       case Iop_RoundF128toInt: {
   2147          IRExpr *irrm;
   2148          IRExpr *left;
   2149          s390_bfp_round_t rm;
   2150          HReg op_hi, op_lo;
   2151          HReg f0, f2, f4, f6;           /* real registers */
   2152 
   2153          f4 = make_fpr(4); /* source */
   2154          f6 = make_fpr(6); /* source */
   2155          f0 = make_fpr(0); /* destination */
   2156          f2 = make_fpr(2); /* destination */
   2157 
   2158          irrm = expr->Iex.Binop.arg1;
   2159          left = expr->Iex.Binop.arg2;
   2160 
   2161          if (s390_host_has_fpext) {
   2162             rm = get_bfp_rounding_mode(env, irrm);
   2163          } else {
   2164             set_bfp_rounding_mode_in_fpc(env, irrm);
   2165             rm = S390_BFP_ROUND_PER_FPC;
   2166          }
   2167 
   2168          s390_isel_float128_expr(&op_hi, &op_lo, env, left);
   2169          /* operand --> (f4, f6) */
   2170          addInstr(env, s390_insn_move(8, f4, op_hi));
   2171          addInstr(env, s390_insn_move(8, f6, op_lo));
   2172          addInstr(env, s390_insn_bfp128_convert(16, S390_BFP_F128_TO_F128I,
   2173                                                 f0, f2, f4, f6, rm));
   2174          /* (f0, f2) --> destination */
   2175          *dst_hi = newVRegF(env);
   2176          *dst_lo = newVRegF(env);
   2177          addInstr(env, s390_insn_move(8, *dst_hi, f0));
   2178          addInstr(env, s390_insn_move(8, *dst_lo, f2));
   2179          return;
   2180       }
   2181 
   2182       default:
   2183          goto irreducible;
   2184       }
   2185    }
   2186 
   2187       /* --------- UNARY OP --------- */
   2188    case Iex_Unop: {
   2189       IRExpr *left = expr->Iex.Unop.arg;
   2190       s390_bfp_unop_t bfpop;
   2191       s390_bfp_conv_t conv;
   2192       HReg op_hi, op_lo, op, f12, f13, f14, f15;
   2193 
   2194       /* We use non-virtual registers as pairs (f13, f15) and (f12, f14)) */
   2195       f12 = make_fpr(12);
   2196       f13 = make_fpr(13);
   2197       f14 = make_fpr(14);
   2198       f15 = make_fpr(15);
   2199 
   2200       switch (expr->Iex.Unop.op) {
   2201       case Iop_NegF128:
   2202          if (left->tag == Iex_Unop &&
   2203              (left->Iex.Unop.op == Iop_AbsF32 ||
   2204               left->Iex.Unop.op == Iop_AbsF64))
   2205             bfpop = S390_BFP_NABS;
   2206          else
   2207             bfpop = S390_BFP_NEG;
   2208          goto float128_opnd;
   2209       case Iop_AbsF128:     bfpop = S390_BFP_ABS;         goto float128_opnd;
   2210       case Iop_I32StoF128:  conv = S390_BFP_I32_TO_F128;  goto convert_int;
   2211       case Iop_I64StoF128:  conv = S390_BFP_I64_TO_F128;  goto convert_int;
   2212       case Iop_I32UtoF128:  conv = S390_BFP_U32_TO_F128;  goto convert_int;
   2213       case Iop_I64UtoF128:  conv = S390_BFP_U64_TO_F128;  goto convert_int;
   2214       case Iop_F32toF128:   conv = S390_BFP_F32_TO_F128;  goto convert_float;
   2215       case Iop_F64toF128:   conv = S390_BFP_F64_TO_F128;  goto convert_float;
   2216       default:
   2217          goto irreducible;
   2218       }
   2219 
   2220    float128_opnd:
   2221       s390_isel_float128_expr(&op_hi, &op_lo, env, left);
   2222 
   2223       /* operand --> (f13, f15) */
   2224       addInstr(env, s390_insn_move(8, f13, op_hi));
   2225       addInstr(env, s390_insn_move(8, f15, op_lo));
   2226 
   2227       addInstr(env, s390_insn_bfp128_unop(16, bfpop, f12, f14, f13, f15));
   2228       goto move_dst;
   2229 
   2230    convert_float:
   2231       op  = s390_isel_float_expr(env, left);
   2232       addInstr(env, s390_insn_bfp128_convert_to(16, conv, f12, f14, op));
   2233       goto move_dst;
   2234 
   2235    convert_int:
   2236       op  = s390_isel_int_expr(env, left);
   2237       addInstr(env, s390_insn_bfp128_convert_to(16, conv, f12, f14, op));
   2238       goto move_dst;
   2239 
   2240    move_dst:
   2241       /* Move result to virtual destination registers */
   2242       *dst_hi = newVRegF(env);
   2243       *dst_lo = newVRegF(env);
   2244       addInstr(env, s390_insn_move(8, *dst_hi, f12));
   2245       addInstr(env, s390_insn_move(8, *dst_lo, f14));
   2246       return;
   2247    }
   2248 
   2249    default:
   2250       goto irreducible;
   2251    }
   2252 
   2253    /* We get here if no pattern matched. */
   2254  irreducible:
   2255    ppIRExpr(expr);
   2256    vpanic("s390_isel_float128_expr: cannot reduce tree");
   2257 }
   2258 
   2259 /* Compute a 128-bit value into two 64-bit registers. These may be either
   2260    real or virtual regs; in any case they must not be changed by subsequent
   2261    code emitted by the caller. */
   2262 static void
   2263 s390_isel_float128_expr(HReg *dst_hi, HReg *dst_lo, ISelEnv *env, IRExpr *expr)
   2264 {
   2265    s390_isel_float128_expr_wrk(dst_hi, dst_lo, env, expr);
   2266 
   2267    /* Sanity checks ... */
   2268    vassert(hregIsVirtual(*dst_hi));
   2269    vassert(hregIsVirtual(*dst_lo));
   2270    vassert(hregClass(*dst_hi) == HRcFlt64);
   2271    vassert(hregClass(*dst_lo) == HRcFlt64);
   2272 }
   2273 
   2274 
   2275 /*---------------------------------------------------------*/
   2276 /*--- ISEL: Floating point expressions (64 bit)         ---*/
   2277 /*---------------------------------------------------------*/
   2278 
   2279 static HReg
   2280 s390_isel_float_expr_wrk(ISelEnv *env, IRExpr *expr)
   2281 {
   2282    IRType ty = typeOfIRExpr(env->type_env, expr);
   2283    UChar size;
   2284 
   2285    vassert(ty == Ity_F32 || ty == Ity_F64);
   2286 
   2287    size = sizeofIRType(ty);
   2288 
   2289    switch (expr->tag) {
   2290    case Iex_RdTmp:
   2291       /* Return the virtual register that holds the temporary. */
   2292       return lookupIRTemp(env, expr->Iex.RdTmp.tmp);
   2293 
   2294       /* --------- LOAD --------- */
   2295    case Iex_Load: {
   2296       HReg        dst = newVRegF(env);
   2297       s390_amode *am  = s390_isel_amode(env, expr->Iex.Load.addr);
   2298 
   2299       if (expr->Iex.Load.end != Iend_BE)
   2300          goto irreducible;
   2301 
   2302       addInstr(env, s390_insn_load(size, dst, am));
   2303 
   2304       return dst;
   2305    }
   2306 
   2307       /* --------- GET --------- */
   2308    case Iex_Get: {
   2309       HReg dst = newVRegF(env);
   2310       s390_amode *am = s390_amode_for_guest_state(expr->Iex.Get.offset);
   2311 
   2312       addInstr(env, s390_insn_load(size, dst, am));
   2313 
   2314       return dst;
   2315    }
   2316 
   2317       /* --------- LITERAL --------- */
   2318 
   2319       /* Load a literal into a register. Create a "load immediate"
   2320          v-insn and return the register. */
   2321    case Iex_Const: {
   2322       ULong value;
   2323       HReg  dst = newVRegF(env);
   2324       const IRConst *con = expr->Iex.Const.con;
   2325 
   2326       /* Bitwise copy of the value. No sign/zero-extension */
   2327       switch (con->tag) {
   2328       case Ico_F32i: value = con->Ico.F32i; break;
   2329       case Ico_F64i: value = con->Ico.F64i; break;
   2330       default:       vpanic("s390_isel_float_expr: invalid constant");
   2331       }
   2332 
   2333       if (value != 0) vpanic("cannot load immediate floating point constant");
   2334 
   2335       addInstr(env, s390_insn_load_immediate(size, dst, value));
   2336 
   2337       return dst;
   2338    }
   2339 
   2340       /* --------- 4-ary OP --------- */
   2341    case Iex_Qop: {
   2342       HReg op1, op2, op3, dst;
   2343       s390_bfp_triop_t bfpop;
   2344 
   2345       op3 = s390_isel_float_expr(env, expr->Iex.Qop.details->arg2);
   2346       op2 = s390_isel_float_expr(env, expr->Iex.Qop.details->arg3);
   2347       op1 = s390_isel_float_expr(env, expr->Iex.Qop.details->arg4);
   2348       dst = newVRegF(env);
   2349       addInstr(env, s390_insn_move(size, dst, op1));
   2350 
   2351       switch (expr->Iex.Qop.details->op) {
   2352       case Iop_MAddF32:
   2353       case Iop_MAddF64:  bfpop = S390_BFP_MADD; break;
   2354       case Iop_MSubF32:
   2355       case Iop_MSubF64:  bfpop = S390_BFP_MSUB; break;
   2356 
   2357       default:
   2358          goto irreducible;
   2359       }
   2360 
   2361       set_bfp_rounding_mode_in_fpc(env, expr->Iex.Qop.details->arg1);
   2362       addInstr(env, s390_insn_bfp_triop(size, bfpop, dst, op2, op3));
   2363       return dst;
   2364    }
   2365 
   2366       /* --------- TERNARY OP --------- */
   2367    case Iex_Triop: {
   2368       IRTriop *triop = expr->Iex.Triop.details;
   2369       IROp    op     = triop->op;
   2370       IRExpr *left   = triop->arg2;
   2371       IRExpr *right  = triop->arg3;
   2372       s390_bfp_binop_t bfpop;
   2373       HReg h1, op2, dst;
   2374 
   2375       h1   = s390_isel_float_expr(env, left);  /* Process 1st operand */
   2376       op2  = s390_isel_float_expr(env, right); /* Process 2nd operand */
   2377       dst  = newVRegF(env);
   2378       addInstr(env, s390_insn_move(size, dst, h1));
   2379       switch (op) {
   2380       case Iop_AddF32:
   2381       case Iop_AddF64:  bfpop = S390_BFP_ADD; break;
   2382       case Iop_SubF32:
   2383       case Iop_SubF64:  bfpop = S390_BFP_SUB; break;
   2384       case Iop_MulF32:
   2385       case Iop_MulF64:  bfpop = S390_BFP_MUL; break;
   2386       case Iop_DivF32:
   2387       case Iop_DivF64:  bfpop = S390_BFP_DIV; break;
   2388 
   2389       default:
   2390          goto irreducible;
   2391       }
   2392 
   2393       set_bfp_rounding_mode_in_fpc(env, triop->arg1);
   2394       addInstr(env, s390_insn_bfp_binop(size, bfpop, dst, op2));
   2395       return dst;
   2396    }
   2397 
   2398       /* --------- BINARY OP --------- */
   2399    case Iex_Binop: {
   2400       IROp    op   = expr->Iex.Binop.op;
   2401       IRExpr *irrm = expr->Iex.Binop.arg1;
   2402       IRExpr *left = expr->Iex.Binop.arg2;
   2403       HReg h1, dst;
   2404       s390_bfp_conv_t  conv;
   2405       s390_fp_conv_t fpconv;
   2406 
   2407       switch (op) {
   2408       case Iop_SqrtF32:
   2409       case Iop_SqrtF64:
   2410          h1  = s390_isel_float_expr(env, left);
   2411          dst = newVRegF(env);
   2412          set_bfp_rounding_mode_in_fpc(env, irrm);
   2413          addInstr(env, s390_insn_bfp_unop(size, S390_BFP_SQRT, dst, h1));
   2414          return dst;
   2415 
   2416       case Iop_F64toF32:  conv = S390_BFP_F64_TO_F32; goto convert_float;
   2417       case Iop_RoundF32toInt: conv = S390_BFP_F32_TO_F32I; goto convert_float;
   2418       case Iop_RoundF64toInt: conv = S390_BFP_F64_TO_F64I; goto convert_float;
   2419       case Iop_I32StoF32: conv = S390_BFP_I32_TO_F32; goto convert_int;
   2420       case Iop_I32UtoF32: conv = S390_BFP_U32_TO_F32; goto convert_int;
   2421       case Iop_I64StoF32: conv = S390_BFP_I64_TO_F32; goto convert_int;
   2422       case Iop_I64StoF64: conv = S390_BFP_I64_TO_F64; goto convert_int;
   2423       case Iop_I64UtoF32: conv = S390_BFP_U64_TO_F32; goto convert_int;
   2424       case Iop_I64UtoF64: conv = S390_BFP_U64_TO_F64; goto convert_int;
   2425       case Iop_D32toF32:  fpconv = S390_FP_D32_TO_F32;  goto convert_dfp;
   2426       case Iop_D32toF64:  fpconv = S390_FP_D32_TO_F64;  goto convert_dfp;
   2427       case Iop_D64toF32:  fpconv = S390_FP_D64_TO_F32;  goto convert_dfp;
   2428       case Iop_D64toF64:  fpconv = S390_FP_D64_TO_F64;  goto convert_dfp;
   2429       case Iop_D128toF32: fpconv = S390_FP_D128_TO_F32; goto convert_dfp128;
   2430       case Iop_D128toF64: fpconv = S390_FP_D128_TO_F64; goto convert_dfp128;
   2431 
   2432       convert_float:
   2433          h1 = s390_isel_float_expr(env, left);
   2434          goto convert;
   2435 
   2436       convert_int:
   2437          h1 = s390_isel_int_expr(env, left);
   2438          goto convert;
   2439 
   2440       convert: {
   2441          s390_bfp_round_t rounding_mode;
   2442          /* convert-from-fixed and load-rounded have a rounding mode field
   2443             when the floating point extension facility is installed. */
   2444          dst = newVRegF(env);
   2445          if (s390_host_has_fpext) {
   2446             rounding_mode = get_bfp_rounding_mode(env, irrm);
   2447          } else {
   2448             set_bfp_rounding_mode_in_fpc(env, irrm);
   2449             rounding_mode = S390_BFP_ROUND_PER_FPC;
   2450          }
   2451          addInstr(env, s390_insn_bfp_convert(size, conv, dst, h1,
   2452                                              rounding_mode));
   2453          return dst;
   2454       }
   2455 
   2456       convert_dfp: {
   2457          s390_dfp_round_t rm;
   2458          HReg f0, f4, r1; /* real registers used by PFPO */
   2459 
   2460          f4 = make_fpr(4); /* source */
   2461          f0 = make_fpr(0); /* destination */
   2462          r1 = make_gpr(1); /* GPR #1 clobbered */
   2463          h1 = s390_isel_dfp_expr(env, left);
   2464          dst = newVRegF(env);
   2465          rm = get_dfp_rounding_mode(env, irrm);
   2466          /* operand --> f4 */
   2467          addInstr(env, s390_insn_move(8, f4, h1));
   2468          addInstr(env, s390_insn_fp_convert(size, fpconv, f0, f4, r1, rm));
   2469          /* f0 --> destination */
   2470          addInstr(env, s390_insn_move(8, dst, f0));
   2471          return dst;
   2472       }
   2473 
   2474       convert_dfp128: {
   2475          s390_dfp_round_t rm;
   2476          HReg op_hi, op_lo;
   2477          HReg f0, f4, f6, r1; /* real registers used by PFPO */
   2478 
   2479          f4 = make_fpr(4); /* source */
   2480          f6 = make_fpr(6); /* source */
   2481          f0 = make_fpr(0); /* destination */
   2482          r1 = make_gpr(1); /* GPR #1 clobbered */
   2483          s390_isel_dfp128_expr(&op_hi, &op_lo, env, left);
   2484          dst = newVRegF(env);
   2485          rm = get_dfp_rounding_mode(env, irrm);
   2486          /* operand --> (f4, f6) */
   2487          addInstr(env, s390_insn_move(8, f4, op_hi));
   2488          addInstr(env, s390_insn_move(8, f6, op_lo));
   2489          addInstr(env, s390_insn_fp128_convert(16, fpconv, f0, INVALID_HREG,
   2490                                                f4, f6, r1, rm));
   2491          /* f0 --> destination */
   2492          addInstr(env, s390_insn_move(8, dst, f0));
   2493          return dst;
   2494       }
   2495 
   2496       default:
   2497          goto irreducible;
   2498 
   2499       case Iop_F128toF64:
   2500       case Iop_F128toF32: {
   2501          HReg op_hi, op_lo, f12, f13, f14, f15;
   2502          s390_bfp_round_t rounding_mode;
   2503 
   2504          conv = op == Iop_F128toF32 ? S390_BFP_F128_TO_F32
   2505                                     : S390_BFP_F128_TO_F64;
   2506 
   2507          s390_isel_float128_expr(&op_hi, &op_lo, env, left);
   2508 
   2509          /* We use non-virtual registers as pairs (f13, f15) and (f12, f14)) */
   2510          f12 = make_fpr(12);
   2511          f13 = make_fpr(13);
   2512          f14 = make_fpr(14);
   2513          f15 = make_fpr(15);
   2514 
   2515          /* operand --> (f13, f15) */
   2516          addInstr(env, s390_insn_move(8, f13, op_hi));
   2517          addInstr(env, s390_insn_move(8, f15, op_lo));
   2518 
   2519          /* result --> (f12, f14) */
   2520 
   2521          /* load-rounded has a rounding mode field when the floating point
   2522             extension facility is installed. */
   2523          if (s390_host_has_fpext) {
   2524             rounding_mode = get_bfp_rounding_mode(env, irrm);
   2525          } else {
   2526             set_bfp_rounding_mode_in_fpc(env, irrm);
   2527             rounding_mode = S390_BFP_ROUND_PER_FPC;
   2528          }
   2529 
   2530          addInstr(env, s390_insn_bfp128_convert_from(size, conv, f12, f14,
   2531                                                      f13, f15, rounding_mode));
   2532          dst = newVRegF(env);
   2533          addInstr(env, s390_insn_move(8, dst, f12));
   2534 
   2535          return dst;
   2536       }
   2537       }
   2538    }
   2539 
   2540       /* --------- UNARY OP --------- */
   2541    case Iex_Unop: {
   2542       IROp    op   = expr->Iex.Unop.op;
   2543       IRExpr *left = expr->Iex.Unop.arg;
   2544       s390_bfp_unop_t bfpop;
   2545       s390_bfp_conv_t conv;
   2546       HReg h1, dst;
   2547 
   2548       if (op == Iop_F128HItoF64 || op == Iop_F128LOtoF64) {
   2549          HReg dst_hi, dst_lo;
   2550 
   2551          s390_isel_float128_expr(&dst_hi, &dst_lo, env, left);
   2552          return op == Iop_F128LOtoF64 ? dst_lo : dst_hi;
   2553       }
   2554 
   2555       if (op == Iop_ReinterpI64asF64 || op == Iop_ReinterpI32asF32) {
   2556          dst = newVRegF(env);
   2557          h1  = s390_isel_int_expr(env, left);     /* Process the operand */
   2558          addInstr(env, s390_insn_move(size, dst, h1));
   2559 
   2560          return dst;
   2561       }
   2562 
   2563       switch (op) {
   2564       case Iop_NegF32:
   2565       case Iop_NegF64:
   2566          if (left->tag == Iex_Unop &&
   2567              (left->Iex.Unop.op == Iop_AbsF32 ||
   2568               left->Iex.Unop.op == Iop_AbsF64))
   2569             bfpop = S390_BFP_NABS;
   2570          else
   2571             bfpop = S390_BFP_NEG;
   2572          break;
   2573 
   2574       case Iop_AbsF32:
   2575       case Iop_AbsF64:
   2576          bfpop = S390_BFP_ABS;
   2577          break;
   2578 
   2579       case Iop_I32StoF64:  conv = S390_BFP_I32_TO_F64;  goto convert_int1;
   2580       case Iop_I32UtoF64:  conv = S390_BFP_U32_TO_F64;  goto convert_int1;
   2581       case Iop_F32toF64:   conv = S390_BFP_F32_TO_F64;  goto convert_float1;
   2582 
   2583       convert_float1:
   2584          h1 = s390_isel_float_expr(env, left);
   2585          goto convert1;
   2586 
   2587       convert_int1:
   2588          h1 = s390_isel_int_expr(env, left);
   2589          goto convert1;
   2590 
   2591       convert1:
   2592          dst = newVRegF(env);
   2593          /* No rounding mode is needed for these conversions. Just stick
   2594             one in. It won't be used later on. */
   2595          addInstr(env, s390_insn_bfp_convert(size, conv, dst, h1,
   2596                                              S390_BFP_ROUND_NEAREST_EVEN));
   2597          return dst;
   2598 
   2599       default:
   2600          goto irreducible;
   2601       }
   2602 
   2603       /* Process operand */
   2604       h1  = s390_isel_float_expr(env, left);
   2605       dst = newVRegF(env);
   2606       addInstr(env, s390_insn_bfp_unop(size, bfpop, dst, h1));
   2607       return dst;
   2608    }
   2609 
   2610    default:
   2611       goto irreducible;
   2612    }
   2613 
   2614    /* We get here if no pattern matched. */
   2615  irreducible:
   2616    ppIRExpr(expr);
   2617    vpanic("s390_isel_float_expr: cannot reduce tree");
   2618 }
   2619 
   2620 
   2621 static HReg
   2622 s390_isel_float_expr(ISelEnv *env, IRExpr *expr)
   2623 {
   2624    HReg dst = s390_isel_float_expr_wrk(env, expr);
   2625 
   2626    /* Sanity checks ... */
   2627    vassert(hregClass(dst) == HRcFlt64);
   2628    vassert(hregIsVirtual(dst));
   2629 
   2630    return dst;
   2631 }
   2632 
   2633 
   2634 /*---------------------------------------------------------*/
   2635 /*--- ISEL: Decimal point expressions (128 bit)         ---*/
   2636 /*---------------------------------------------------------*/
   2637 static void
   2638 s390_isel_dfp128_expr_wrk(HReg *dst_hi, HReg *dst_lo, ISelEnv *env,
   2639                           IRExpr *expr)
   2640 {
   2641    IRType ty = typeOfIRExpr(env->type_env, expr);
   2642 
   2643    vassert(ty == Ity_D128);
   2644 
   2645    switch (expr->tag) {
   2646    case Iex_RdTmp:
   2647       /* Return the virtual registers that hold the temporary. */
   2648       lookupIRTemp128(dst_hi, dst_lo, env, expr->Iex.RdTmp.tmp);
   2649       return;
   2650 
   2651       /* --------- LOAD --------- */
   2652    case Iex_Load: {
   2653       IRExpr *addr_hi, *addr_lo;
   2654       s390_amode *am_hi, *am_lo;
   2655 
   2656       if (expr->Iex.Load.end != Iend_BE)
   2657          goto irreducible;
   2658 
   2659       addr_hi = expr->Iex.Load.addr;
   2660       addr_lo = IRExpr_Binop(Iop_Add64, addr_hi, mkU64(8));
   2661 
   2662       am_hi  = s390_isel_amode(env, addr_hi);
   2663       am_lo  = s390_isel_amode(env, addr_lo);
   2664 
   2665       *dst_hi = newVRegF(env);
   2666       *dst_lo = newVRegF(env);
   2667       addInstr(env, s390_insn_load(8, *dst_hi, am_hi));
   2668       addInstr(env, s390_insn_load(8, *dst_hi, am_lo));
   2669       return;
   2670    }
   2671 
   2672       /* --------- GET --------- */
   2673    case Iex_Get:
   2674       /* This is not supported because loading 128-bit from the guest
   2675          state is almost certainly wrong. Use get_dpr_pair instead. */
   2676       vpanic("Iex_Get with D128 data");
   2677 
   2678       /* --------- 4-ary OP --------- */
   2679    case Iex_Qop:
   2680       vpanic("Iex_Qop with D128 data");
   2681 
   2682       /* --------- TERNARY OP --------- */
   2683    case Iex_Triop: {
   2684       IRTriop *triop = expr->Iex.Triop.details;
   2685       IROp    op     = triop->op;
   2686       IRExpr *irrm   = triop->arg1;
   2687       IRExpr *left   = triop->arg2;
   2688       IRExpr *right  = triop->arg3;
   2689       s390_dfp_round_t rounding_mode;
   2690       s390_dfp_binop_t dfpop;
   2691       HReg op1_hi, op1_lo, op2_hi, op2_lo, f9, f11, f12, f13, f14, f15;
   2692 
   2693       /* We use non-virtual registers as pairs with (f9, f11) as op1,
   2694          (f12, f14) as op2 and (f13, f15)  as destination) */
   2695       f9  = make_fpr(9);
   2696       f11 = make_fpr(11);
   2697       f12 = make_fpr(12);
   2698       f13 = make_fpr(13);
   2699       f14 = make_fpr(14);
   2700       f15 = make_fpr(15);
   2701 
   2702       switch (op) {
   2703       case Iop_AddD128:       dfpop = S390_DFP_ADD;      goto evaluate_dfp128;
   2704       case Iop_SubD128:       dfpop = S390_DFP_SUB;      goto evaluate_dfp128;
   2705       case Iop_MulD128:       dfpop = S390_DFP_MUL;      goto evaluate_dfp128;
   2706       case Iop_DivD128:       dfpop = S390_DFP_DIV;      goto evaluate_dfp128;
   2707       case Iop_QuantizeD128:  dfpop = S390_DFP_QUANTIZE; goto evaluate_dfp128;
   2708 
   2709       evaluate_dfp128: {
   2710          /* Process 1st operand */
   2711          s390_isel_dfp128_expr(&op1_hi, &op1_lo, env, left);
   2712          /* 1st operand --> (f9, f11) */
   2713          addInstr(env, s390_insn_move(8, f9,  op1_hi));
   2714          addInstr(env, s390_insn_move(8, f11, op1_lo));
   2715 
   2716          /* Process 2nd operand */
   2717          s390_isel_dfp128_expr(&op2_hi, &op2_lo, env, right);
   2718          /* 2nd operand --> (f12, f14) */
   2719          addInstr(env, s390_insn_move(8, f12, op2_hi));
   2720          addInstr(env, s390_insn_move(8, f14, op2_lo));
   2721 
   2722          /* DFP arithmetic ops take rounding mode only when fpext is
   2723             installed. But, DFP quantize operation takes rm irrespective
   2724             of fpext facility . */
   2725          if (s390_host_has_fpext || op == Iop_QuantizeD128) {
   2726             rounding_mode = get_dfp_rounding_mode(env, irrm);
   2727          } else {
   2728             set_dfp_rounding_mode_in_fpc(env, irrm);
   2729             rounding_mode = S390_DFP_ROUND_PER_FPC_0;
   2730          }
   2731          addInstr(env, s390_insn_dfp128_binop(16, dfpop, f13, f15, f9, f11,
   2732                                               f12, f14, rounding_mode));
   2733          /* Move result to virtual destination register */
   2734          *dst_hi = newVRegF(env);
   2735          *dst_lo = newVRegF(env);
   2736          addInstr(env, s390_insn_move(8, *dst_hi, f13));
   2737          addInstr(env, s390_insn_move(8, *dst_lo, f15));
   2738          return;
   2739       }
   2740 
   2741       case Iop_SignificanceRoundD128: {
   2742          /* Process 1st operand */
   2743          HReg op1 = s390_isel_int_expr(env, left);
   2744          /* Process 2nd operand */
   2745          s390_isel_dfp128_expr(&op2_hi, &op2_lo, env, right);
   2746          /* 2nd operand --> (f12, f14) */
   2747          addInstr(env, s390_insn_move(8, f12, op2_hi));
   2748          addInstr(env, s390_insn_move(8, f14, op2_lo));
   2749 
   2750          rounding_mode = get_dfp_rounding_mode(env, irrm);
   2751          addInstr(env, s390_insn_dfp128_reround(16, f13, f15, op1, f12, f14,
   2752                                                 rounding_mode));
   2753          /* Move result to virtual destination register */
   2754          *dst_hi = newVRegF(env);
   2755          *dst_lo = newVRegF(env);
   2756          addInstr(env, s390_insn_move(8, *dst_hi, f13));
   2757          addInstr(env, s390_insn_move(8, *dst_lo, f15));
   2758          return;
   2759       }
   2760 
   2761       default:
   2762          goto irreducible;
   2763       }
   2764    }
   2765 
   2766       /* --------- BINARY OP --------- */
   2767    case Iex_Binop: {
   2768 
   2769       switch (expr->Iex.Binop.op) {
   2770       case Iop_D64HLtoD128:
   2771          *dst_hi = s390_isel_dfp_expr(env, expr->Iex.Binop.arg1);
   2772          *dst_lo = s390_isel_dfp_expr(env, expr->Iex.Binop.arg2);
   2773          return;
   2774 
   2775       case Iop_ShlD128:
   2776       case Iop_ShrD128:
   2777       case Iop_InsertExpD128: {
   2778          HReg op1_hi, op1_lo, op2, f9, f11, f13, f15;
   2779          s390_dfp_intop_t intop;
   2780          IRExpr *dfp_op;
   2781          IRExpr *int_op;
   2782 
   2783          switch (expr->Iex.Binop.op) {
   2784          case Iop_ShlD128:       /* (D128, I64) -> D128 */
   2785             intop = S390_DFP_SHIFT_LEFT;
   2786             dfp_op = expr->Iex.Binop.arg1;
   2787             int_op = expr->Iex.Binop.arg2;
   2788             break;
   2789          case Iop_ShrD128:       /* (D128, I64) -> D128 */
   2790             intop = S390_DFP_SHIFT_RIGHT;
   2791             dfp_op = expr->Iex.Binop.arg1;
   2792             int_op = expr->Iex.Binop.arg2;
   2793             break;
   2794          case Iop_InsertExpD128: /* (I64, D128) -> D128 */
   2795             intop = S390_DFP_INSERT_EXP;
   2796             int_op = expr->Iex.Binop.arg1;
   2797             dfp_op = expr->Iex.Binop.arg2;
   2798             break;
   2799          default: goto irreducible;
   2800          }
   2801 
   2802          /* We use non-virtual registers as pairs (f9, f11) and (f13, f15)) */
   2803          f9  = make_fpr(9); /* 128 bit dfp operand */
   2804          f11 = make_fpr(11);
   2805 
   2806          f13 = make_fpr(13); /* 128 bit dfp destination */
   2807          f15 = make_fpr(15);
   2808 
   2809          /* Process dfp operand */
   2810          s390_isel_dfp128_expr(&op1_hi, &op1_lo, env, dfp_op);
   2811          /* op1 -> (f9,f11) */
   2812          addInstr(env, s390_insn_move(8, f9,  op1_hi));
   2813          addInstr(env, s390_insn_move(8, f11, op1_lo));
   2814 
   2815          op2 = s390_isel_int_expr(env, int_op);  /* int operand */
   2816 
   2817          addInstr(env,
   2818                   s390_insn_dfp128_intop(16, intop, f13, f15, op2, f9, f11));
   2819 
   2820          /* Move result to virtual destination register */
   2821          *dst_hi = newVRegF(env);
   2822          *dst_lo = newVRegF(env);
   2823          addInstr(env, s390_insn_move(8, *dst_hi, f13));
   2824          addInstr(env, s390_insn_move(8, *dst_lo, f15));
   2825          return;
   2826       }
   2827 
   2828       case Iop_F32toD128:
   2829       case Iop_F64toD128: {
   2830          IRExpr *irrm;
   2831          IRExpr *left;
   2832          s390_dfp_round_t rm;
   2833          HReg h1; /* virtual reg. to hold source */
   2834          HReg f0, f2, f4, r1; /* real registers used by PFPO */
   2835          s390_fp_conv_t fpconv;
   2836 
   2837          switch (expr->Iex.Binop.op) {
   2838          case Iop_F32toD128:       /* (D128, I64) -> D128 */
   2839             fpconv = S390_FP_F32_TO_D128;
   2840             break;
   2841          case Iop_F64toD128:       /* (D128, I64) -> D128 */
   2842             fpconv = S390_FP_F64_TO_D128;
   2843             break;
   2844          default: goto irreducible;
   2845          }
   2846 
   2847          f4 = make_fpr(4); /* source */
   2848          f0 = make_fpr(0); /* destination */
   2849          f2 = make_fpr(2); /* destination */
   2850          r1 = make_gpr(1); /* GPR #1 clobbered */
   2851          irrm = expr->Iex.Binop.arg1;
   2852          left = expr->Iex.Binop.arg2;
   2853          rm = get_dfp_rounding_mode(env, irrm);
   2854          h1 = s390_isel_float_expr(env, left);
   2855          addInstr(env, s390_insn_move(8, f4, h1));
   2856          addInstr(env, s390_insn_fp128_convert(16, fpconv, f0, f2,
   2857                                                f4, INVALID_HREG, r1, rm));
   2858          /* (f0, f2) --> destination */
   2859          *dst_hi = newVRegF(env);
   2860          *dst_lo = newVRegF(env);
   2861          addInstr(env, s390_insn_move(8, *dst_hi, f0));
   2862          addInstr(env, s390_insn_move(8, *dst_lo, f2));
   2863 
   2864          return;
   2865       }
   2866 
   2867       case Iop_F128toD128: {
   2868          IRExpr *irrm;
   2869          IRExpr *left;
   2870          s390_dfp_round_t rm;
   2871          HReg op_hi, op_lo;
   2872          HReg f0, f2, f4, f6, r1; /* real registers used by PFPO */
   2873 
   2874          f4 = make_fpr(4); /* source */
   2875          f6 = make_fpr(6); /* source */
   2876          f0 = make_fpr(0); /* destination */
   2877          f2 = make_fpr(2); /* destination */
   2878          r1 = make_gpr(1); /* GPR #1 clobbered */
   2879 
   2880          irrm = expr->Iex.Binop.arg1;
   2881          left = expr->Iex.Binop.arg2;
   2882          rm = get_dfp_rounding_mode(env, irrm);
   2883          s390_isel_float128_expr(&op_hi, &op_lo, env, left);
   2884          /* operand --> (f4, f6) */
   2885          addInstr(env, s390_insn_move(8, f4, op_hi));
   2886          addInstr(env, s390_insn_move(8, f6, op_lo));
   2887          addInstr(env, s390_insn_fp128_convert(16, S390_FP_F128_TO_D128, f0, f2,
   2888                                                f4, f6, r1, rm));
   2889          /* (f0, f2) --> destination */
   2890          *dst_hi = newVRegF(env);
   2891          *dst_lo = newVRegF(env);
   2892          addInstr(env, s390_insn_move(8, *dst_hi, f0));
   2893          addInstr(env, s390_insn_move(8, *dst_lo, f2));
   2894 
   2895          return;
   2896       }
   2897 
   2898       default:
   2899          goto irreducible;
   2900       }
   2901    }
   2902 
   2903       /* --------- UNARY OP --------- */
   2904    case Iex_Unop: {
   2905       IRExpr *left = expr->Iex.Unop.arg;
   2906       s390_dfp_conv_t conv;
   2907       HReg op, f12, f14;
   2908 
   2909       /* We use non-virtual registers as pairs (f12, f14)) */
   2910       f12 = make_fpr(12);
   2911       f14 = make_fpr(14);
   2912 
   2913       switch (expr->Iex.Unop.op) {
   2914       case Iop_D64toD128:   conv = S390_DFP_D64_TO_D128;  goto convert_dfp;
   2915       case Iop_I32StoD128:  conv = S390_DFP_I32_TO_D128;  goto convert_int;
   2916       case Iop_I64StoD128:  conv = S390_DFP_I64_TO_D128;  goto convert_int;
   2917       case Iop_I32UtoD128:  conv = S390_DFP_U32_TO_D128;  goto convert_int;
   2918       case Iop_I64UtoD128:  conv = S390_DFP_U64_TO_D128;  goto convert_int;
   2919       default:
   2920          goto irreducible;
   2921       }
   2922 
   2923    convert_dfp:
   2924       op  = s390_isel_dfp_expr(env, left);
   2925       addInstr(env, s390_insn_dfp128_convert_to(16, conv, f12, f14, op));
   2926       goto move_dst;
   2927 
   2928    convert_int:
   2929       op  = s390_isel_int_expr(env, left);
   2930       addInstr(env, s390_insn_dfp128_convert_to(16, conv, f12, f14, op));
   2931       goto move_dst;
   2932 
   2933    move_dst:
   2934       /* Move result to virtual destination registers */
   2935       *dst_hi = newVRegF(env);
   2936       *dst_lo = newVRegF(env);
   2937       addInstr(env, s390_insn_move(8, *dst_hi, f12));
   2938       addInstr(env, s390_insn_move(8, *dst_lo, f14));
   2939       return;
   2940    }
   2941 
   2942    default:
   2943       goto irreducible;
   2944    }
   2945 
   2946    /* We get here if no pattern matched. */
   2947  irreducible:
   2948    ppIRExpr(expr);
   2949    vpanic("s390_isel_dfp128_expr_wrk: cannot reduce tree");
   2950 
   2951 }
   2952 
   2953 
   2954 /* Compute a 128-bit value into two 64-bit registers. These may be either
   2955    real or virtual regs; in any case they must not be changed by subsequent
   2956    code emitted by the caller. */
   2957 static void
   2958 s390_isel_dfp128_expr(HReg *dst_hi, HReg *dst_lo, ISelEnv *env, IRExpr *expr)
   2959 {
   2960    s390_isel_dfp128_expr_wrk(dst_hi, dst_lo, env, expr);
   2961 
   2962    /* Sanity checks ... */
   2963    vassert(hregIsVirtual(*dst_hi));
   2964    vassert(hregIsVirtual(*dst_lo));
   2965    vassert(hregClass(*dst_hi) == HRcFlt64);
   2966    vassert(hregClass(*dst_lo) == HRcFlt64);
   2967 }
   2968 
   2969 
   2970 /*---------------------------------------------------------*/
   2971 /*--- ISEL: Decimal point expressions (64 bit)          ---*/
   2972 /*---------------------------------------------------------*/
   2973 
   2974 static HReg
   2975 s390_isel_dfp_expr_wrk(ISelEnv *env, IRExpr *expr)
   2976 {
   2977    IRType ty = typeOfIRExpr(env->type_env, expr);
   2978    UChar size;
   2979 
   2980    vassert(ty == Ity_D64 || ty == Ity_D32);
   2981 
   2982    size = sizeofIRType(ty);
   2983 
   2984    switch (expr->tag) {
   2985    case Iex_RdTmp:
   2986       /* Return the virtual register that holds the temporary. */
   2987       return lookupIRTemp(env, expr->Iex.RdTmp.tmp);
   2988 
   2989       /* --------- LOAD --------- */
   2990    case Iex_Load: {
   2991       HReg        dst = newVRegF(env);
   2992       s390_amode *am  = s390_isel_amode(env, expr->Iex.Load.addr);
   2993 
   2994       if (expr->Iex.Load.end != Iend_BE)
   2995          goto irreducible;
   2996 
   2997       addInstr(env, s390_insn_load(size, dst, am));
   2998 
   2999       return dst;
   3000    }
   3001 
   3002       /* --------- GET --------- */
   3003    case Iex_Get: {
   3004       HReg dst = newVRegF(env);
   3005       s390_amode *am = s390_amode_for_guest_state(expr->Iex.Get.offset);
   3006 
   3007       addInstr(env, s390_insn_load(size, dst, am));
   3008 
   3009       return dst;
   3010    }
   3011 
   3012       /* --------- BINARY OP --------- */
   3013    case Iex_Binop: {
   3014       IROp    op   = expr->Iex.Binop.op;
   3015       IRExpr *irrm = expr->Iex.Binop.arg1;
   3016       IRExpr *left = expr->Iex.Binop.arg2;
   3017       HReg h1, dst;
   3018       s390_dfp_conv_t  conv;
   3019       s390_fp_conv_t  fpconv;
   3020 
   3021       switch (op) {
   3022       case Iop_D64toD32:  conv = S390_DFP_D64_TO_D32; goto convert_dfp;
   3023       case Iop_I64StoD64: conv = S390_DFP_I64_TO_D64; goto convert_int;
   3024       case Iop_I64UtoD64: conv = S390_DFP_U64_TO_D64; goto convert_int;
   3025       case Iop_F32toD32:  fpconv = S390_FP_F32_TO_D32; goto convert_bfp;
   3026       case Iop_F32toD64:  fpconv = S390_FP_F32_TO_D64; goto convert_bfp;
   3027       case Iop_F64toD32:  fpconv = S390_FP_F64_TO_D32; goto convert_bfp;
   3028       case Iop_F64toD64:  fpconv = S390_FP_F64_TO_D64; goto convert_bfp;
   3029       case Iop_F128toD32: fpconv = S390_FP_F128_TO_D32; goto convert_bfp128;
   3030       case Iop_F128toD64: fpconv = S390_FP_F128_TO_D64; goto convert_bfp128;
   3031 
   3032       convert_dfp:
   3033          h1 = s390_isel_dfp_expr(env, left);
   3034          goto convert;
   3035 
   3036       convert_int:
   3037          h1 = s390_isel_int_expr(env, left);
   3038          goto convert;
   3039 
   3040       convert: {
   3041             s390_dfp_round_t rounding_mode;
   3042             /* convert-from-fixed and load-rounded have a rounding mode field
   3043                when the floating point extension facility is installed. */
   3044             dst = newVRegF(env);
   3045             if (s390_host_has_fpext) {
   3046                rounding_mode = get_dfp_rounding_mode(env, irrm);
   3047             } else {
   3048                set_dfp_rounding_mode_in_fpc(env, irrm);
   3049                rounding_mode = S390_DFP_ROUND_PER_FPC_0;
   3050             }
   3051             addInstr(env, s390_insn_dfp_convert(size, conv, dst, h1,
   3052                                                 rounding_mode));
   3053             return dst;
   3054          }
   3055 
   3056       convert_bfp: {
   3057          s390_dfp_round_t rm;
   3058          HReg f0, f4, r1; /* real registers used by PFPO */
   3059 
   3060          f4 = make_fpr(4); /* source */
   3061          f0 = make_fpr(0); /* destination */
   3062          r1 = make_gpr(1); /* GPR #1 clobbered */
   3063          h1 = s390_isel_float_expr(env, left);
   3064          dst = newVRegF(env);
   3065          rm = get_dfp_rounding_mode(env, irrm);
   3066          /* operand --> f4 */
   3067          addInstr(env, s390_insn_move(8, f4, h1));
   3068          addInstr(env, s390_insn_fp_convert(size, fpconv, f0, f4, r1, rm));
   3069          /* f0 --> destination */
   3070          addInstr(env, s390_insn_move(8, dst, f0));
   3071          return dst;
   3072       }
   3073 
   3074       convert_bfp128: {
   3075          s390_dfp_round_t rm;
   3076          HReg op_hi, op_lo;
   3077          HReg f0, f4, f6, r1; /* real registers used by PFPO */
   3078 
   3079          f4 = make_fpr(4); /* source */
   3080          f6 = make_fpr(6); /* source */
   3081          f0 = make_fpr(0); /* destination */
   3082          r1 = make_gpr(1); /* GPR #1 clobbered */
   3083          s390_isel_float128_expr(&op_hi, &op_lo, env, left);
   3084          dst = newVRegF(env);
   3085          rm = get_dfp_rounding_mode(env, irrm);
   3086          /* operand --> (f4, f6) */
   3087          addInstr(env, s390_insn_move(8, f4, op_hi));
   3088          addInstr(env, s390_insn_move(8, f6, op_lo));
   3089          addInstr(env, s390_insn_fp128_convert(16, fpconv, f0, INVALID_HREG,
   3090                                                f4, f6, r1, rm));
   3091          /* f0 --> destination */
   3092          addInstr(env, s390_insn_move(8, dst, f0));
   3093          return dst;
   3094       }
   3095 
   3096       case Iop_D128toD64: {
   3097          HReg op_hi, op_lo, f12, f13, f14, f15;
   3098          s390_dfp_round_t rounding_mode;
   3099 
   3100          conv = S390_DFP_D128_TO_D64;
   3101 
   3102          s390_isel_dfp128_expr(&op_hi, &op_lo, env, left);
   3103 
   3104          /* We use non-virtual registers as pairs (f13, f15) and (f12, f14) */
   3105          f12 = make_fpr(12);
   3106          f13 = make_fpr(13);
   3107          f14 = make_fpr(14);
   3108          f15 = make_fpr(15);
   3109 
   3110          /* operand --> (f13, f15) */
   3111          addInstr(env, s390_insn_move(8, f13, op_hi));
   3112          addInstr(env, s390_insn_move(8, f15, op_lo));
   3113 
   3114          /* result --> (f12, f14) */
   3115 
   3116          /* load-rounded has a rounding mode field when the floating point
   3117             extension facility is installed. */
   3118          if (s390_host_has_fpext) {
   3119             rounding_mode = get_dfp_rounding_mode(env, irrm);
   3120          } else {
   3121             set_dfp_rounding_mode_in_fpc(env, irrm);
   3122             rounding_mode = S390_DFP_ROUND_PER_FPC_0;
   3123          }
   3124          addInstr(env, s390_insn_dfp128_convert_from(size, conv, f12, f14,
   3125                                                      f13, f15, rounding_mode));
   3126          dst = newVRegF(env);
   3127          addInstr(env, s390_insn_move(8, dst, f12));
   3128 
   3129          return dst;
   3130       }
   3131 
   3132       case Iop_ShlD64:
   3133       case Iop_ShrD64:
   3134       case Iop_InsertExpD64: {
   3135          HReg op2;
   3136          HReg op3;
   3137          IRExpr *dfp_op;
   3138          IRExpr *int_op;
   3139          s390_dfp_intop_t intop;
   3140 
   3141          switch (expr->Iex.Binop.op) {
   3142          case Iop_ShlD64:       /* (D64, I64) -> D64 */
   3143             intop = S390_DFP_SHIFT_LEFT;
   3144             dfp_op = expr->Iex.Binop.arg1;
   3145             int_op = expr->Iex.Binop.arg2;
   3146             break;
   3147          case Iop_ShrD64:       /* (D64, I64) -> D64 */
   3148             intop = S390_DFP_SHIFT_RIGHT;
   3149             dfp_op = expr->Iex.Binop.arg1;
   3150             int_op = expr->Iex.Binop.arg2;
   3151             break;
   3152          case Iop_InsertExpD64: /* (I64, D64) -> D64 */
   3153             intop = S390_DFP_INSERT_EXP;
   3154             int_op = expr->Iex.Binop.arg1;
   3155             dfp_op = expr->Iex.Binop.arg2;
   3156             break;
   3157          default: goto irreducible;
   3158          }
   3159 
   3160          op2 = s390_isel_int_expr(env, int_op);
   3161          op3 = s390_isel_dfp_expr(env, dfp_op);
   3162          dst = newVRegF(env);
   3163 
   3164          addInstr(env, s390_insn_dfp_intop(size, intop, dst, op2, op3));
   3165          return dst;
   3166       }
   3167 
   3168       default:
   3169          goto irreducible;
   3170       }
   3171    }
   3172 
   3173       /* --------- UNARY OP --------- */
   3174    case Iex_Unop: {
   3175       IROp    op   = expr->Iex.Unop.op;
   3176       IRExpr *left = expr->Iex.Unop.arg;
   3177       s390_dfp_conv_t conv;
   3178       HReg h1, dst;
   3179 
   3180       if (op == Iop_D128HItoD64 || op == Iop_D128LOtoD64) {
   3181          HReg dst_hi, dst_lo;
   3182 
   3183          s390_isel_dfp128_expr(&dst_hi, &dst_lo, env, left);
   3184          return op == Iop_D128LOtoD64 ? dst_lo : dst_hi;
   3185       }
   3186 
   3187       if (op == Iop_ReinterpI64asD64) {
   3188          dst = newVRegF(env);
   3189          h1  = s390_isel_int_expr(env, left);     /* Process the operand */
   3190          addInstr(env, s390_insn_move(size, dst, h1));
   3191 
   3192          return dst;
   3193       }
   3194 
   3195       switch (op) {
   3196       case Iop_D32toD64:  conv = S390_DFP_D32_TO_D64;  goto convert_dfp1;
   3197       case Iop_I32StoD64: conv = S390_DFP_I32_TO_D64;  goto convert_int1;
   3198       case Iop_I32UtoD64: conv = S390_DFP_U32_TO_D64;  goto convert_int1;
   3199 
   3200       convert_dfp1:
   3201          h1 = s390_isel_dfp_expr(env, left);
   3202          goto convert1;
   3203 
   3204       convert_int1:
   3205          h1 = s390_isel_int_expr(env, left);
   3206          goto convert1;
   3207 
   3208       convert1:
   3209          dst = newVRegF(env);
   3210          /* No rounding mode is needed for these conversions. Just stick
   3211             one in. It won't be used later on. */
   3212          addInstr(env, s390_insn_dfp_convert(size, conv, dst, h1,
   3213                                              S390_DFP_ROUND_NEAREST_EVEN_4));
   3214          return dst;
   3215 
   3216       default:
   3217          goto irreducible;
   3218       }
   3219    }
   3220 
   3221       /* --------- TERNARY OP --------- */
   3222    case Iex_Triop: {
   3223       IRTriop *triop = expr->Iex.Triop.details;
   3224       IROp    op     = triop->op;
   3225       IRExpr *irrm   = triop->arg1;
   3226       IRExpr *left   = triop->arg2;
   3227       IRExpr *right  = triop->arg3;
   3228       s390_dfp_round_t rounding_mode;
   3229       s390_dfp_binop_t dfpop;
   3230       HReg op2, op3, dst;
   3231 
   3232       switch (op) {
   3233       case Iop_AddD64:      dfpop = S390_DFP_ADD;      goto evaluate_dfp;
   3234       case Iop_SubD64:      dfpop = S390_DFP_SUB;      goto evaluate_dfp;
   3235       case Iop_MulD64:      dfpop = S390_DFP_MUL;      goto evaluate_dfp;
   3236       case Iop_DivD64:      dfpop = S390_DFP_DIV;      goto evaluate_dfp;
   3237       case Iop_QuantizeD64: dfpop = S390_DFP_QUANTIZE; goto evaluate_dfp;
   3238 
   3239       evaluate_dfp: {
   3240          op2  = s390_isel_dfp_expr(env, left);  /* Process 1st operand */
   3241          op3  = s390_isel_dfp_expr(env, right); /* Process 2nd operand */
   3242          dst  = newVRegF(env);
   3243          /* DFP arithmetic ops take rounding mode only when fpext is
   3244             installed. But, DFP quantize operation takes rm irrespective
   3245             of fpext facility . */
   3246          if (s390_host_has_fpext || dfpop == S390_DFP_QUANTIZE) {
   3247             rounding_mode = get_dfp_rounding_mode(env, irrm);
   3248          } else {
   3249             set_dfp_rounding_mode_in_fpc(env, irrm);
   3250             rounding_mode = S390_DFP_ROUND_PER_FPC_0;
   3251          }
   3252          addInstr(env, s390_insn_dfp_binop(size, dfpop, dst, op2, op3,
   3253                                            rounding_mode));
   3254          return dst;
   3255       }
   3256 
   3257       case Iop_SignificanceRoundD64:
   3258          op2  = s390_isel_int_expr(env, left);  /* Process 1st operand */
   3259          op3  = s390_isel_dfp_expr(env, right); /* Process 2nd operand */
   3260          dst  = newVRegF(env);
   3261          rounding_mode = get_dfp_rounding_mode(env, irrm);
   3262          addInstr(env, s390_insn_dfp_reround(size, dst, op2, op3,
   3263                                              rounding_mode));
   3264          return dst;
   3265 
   3266       default:
   3267          goto irreducible;
   3268       }
   3269    }
   3270 
   3271    default:
   3272       goto irreducible;
   3273    }
   3274 
   3275    /* We get here if no pattern matched. */
   3276  irreducible:
   3277    ppIRExpr(expr);
   3278    vpanic("s390_isel_dfp_expr: cannot reduce tree");
   3279 }
   3280 
   3281 static HReg
   3282 s390_isel_dfp_expr(ISelEnv *env, IRExpr *expr)
   3283 {
   3284    HReg dst = s390_isel_dfp_expr_wrk(env, expr);
   3285 
   3286    /* Sanity checks ... */
   3287    vassert(hregClass(dst) == HRcFlt64);
   3288    vassert(hregIsVirtual(dst));
   3289 
   3290    return dst;
   3291 }
   3292 
   3293 
   3294 /*---------------------------------------------------------*/
   3295 /*--- ISEL: Condition Code                              ---*/
   3296 /*---------------------------------------------------------*/
   3297 
   3298 /* This function handles all operators that produce a 1-bit result */
   3299 static s390_cc_t
   3300 s390_isel_cc(ISelEnv *env, IRExpr *cond)
   3301 {
   3302    UChar size;
   3303 
   3304    vassert(typeOfIRExpr(env->type_env, cond) == Ity_I1);
   3305 
   3306    /* Constant: either 1 or 0 */
   3307    if (cond->tag == Iex_Const) {
   3308       vassert(cond->Iex.Const.con->tag == Ico_U1);
   3309       vassert(cond->Iex.Const.con->Ico.U1 == True
   3310               || cond->Iex.Const.con->Ico.U1 == False);
   3311 
   3312       return cond->Iex.Const.con->Ico.U1 == True ? S390_CC_ALWAYS : S390_CC_NEVER;
   3313    }
   3314 
   3315    /* Variable: values are 1 or 0 */
   3316    if (cond->tag == Iex_RdTmp) {
   3317       IRTemp tmp = cond->Iex.RdTmp.tmp;
   3318       HReg   reg = lookupIRTemp(env, tmp);
   3319 
   3320       /* Load-and-test does not modify REG; so this is OK. */
   3321       if (typeOfIRTemp(env->type_env, tmp) == Ity_I1)
   3322          size = 4;
   3323       else
   3324          size = sizeofIRType(typeOfIRTemp(env->type_env, tmp));
   3325       addInstr(env, s390_insn_test(size, s390_opnd_reg(reg)));
   3326       return S390_CC_NE;
   3327    }
   3328 
   3329    /* Unary operators */
   3330    if (cond->tag == Iex_Unop) {
   3331       IRExpr *arg = cond->Iex.Unop.arg;
   3332 
   3333       switch (cond->Iex.Unop.op) {
   3334       case Iop_Not1:  /* Not1(cond) */
   3335          /* Generate code for EXPR, and negate the test condition */
   3336          return s390_cc_invert(s390_isel_cc(env, arg));
   3337 
   3338          /* Iop_32/64to1  select the LSB from their operand */
   3339       case Iop_32to1:
   3340       case Iop_64to1: {
   3341          HReg dst = newVRegI(env);
   3342          HReg h1  = s390_isel_int_expr(env, arg);
   3343 
   3344          size = sizeofIRType(typeOfIRExpr(env->type_env, arg));
   3345 
   3346          addInstr(env, s390_insn_move(size, dst, h1));
   3347          addInstr(env, s390_insn_alu(size, S390_ALU_AND, dst, s390_opnd_imm(1)));
   3348          addInstr(env, s390_insn_test(size, s390_opnd_reg(dst)));
   3349          return S390_CC_NE;
   3350       }
   3351 
   3352       case Iop_CmpNEZ8:
   3353       case Iop_CmpNEZ16: {
   3354          s390_opnd_RMI src;
   3355          s390_unop_t   op;
   3356          HReg dst;
   3357 
   3358          op  = (cond->Iex.Unop.op == Iop_CmpNEZ8) ? S390_ZERO_EXTEND_8
   3359             : S390_ZERO_EXTEND_16;
   3360          dst = newVRegI(env);
   3361          src = s390_isel_int_expr_RMI(env, arg);
   3362          addInstr(env, s390_insn_unop(4, op, dst, src));
   3363          addInstr(env, s390_insn_test(4, s390_opnd_reg(dst)));
   3364          return S390_CC_NE;
   3365       }
   3366 
   3367       case Iop_CmpNEZ32:
   3368       case Iop_CmpNEZ64: {
   3369          s390_opnd_RMI src;
   3370 
   3371          src = s390_isel_int_expr_RMI(env, arg);
   3372          size = sizeofIRType(typeOfIRExpr(env->type_env, arg));
   3373          addInstr(env, s390_insn_test(size, src));
   3374          return S390_CC_NE;
   3375       }
   3376 
   3377       default:
   3378          goto fail;
   3379       }
   3380    }
   3381 
   3382    /* Binary operators */
   3383    if (cond->tag == Iex_Binop) {
   3384       IRExpr *arg1 = cond->Iex.Binop.arg1;
   3385       IRExpr *arg2 = cond->Iex.Binop.arg2;
   3386       HReg reg1, reg2;
   3387 
   3388       size = sizeofIRType(typeOfIRExpr(env->type_env, arg1));
   3389 
   3390       switch (cond->Iex.Binop.op) {
   3391          s390_unop_t op;
   3392          s390_cc_t   result;
   3393 
   3394       case Iop_CmpEQ8:
   3395       case Iop_CasCmpEQ8:
   3396          op     = S390_ZERO_EXTEND_8;
   3397          result = S390_CC_E;
   3398          goto do_compare_ze;
   3399 
   3400       case Iop_CmpNE8:
   3401       case Iop_CasCmpNE8:
   3402          op     = S390_ZERO_EXTEND_8;
   3403          result = S390_CC_NE;
   3404          goto do_compare_ze;
   3405 
   3406       case Iop_CmpEQ16:
   3407       case Iop_CasCmpEQ16:
   3408          op     = S390_ZERO_EXTEND_16;
   3409          result = S390_CC_E;
   3410          goto do_compare_ze;
   3411 
   3412       case Iop_CmpNE16:
   3413       case Iop_CasCmpNE16:
   3414          op     = S390_ZERO_EXTEND_16;
   3415          result = S390_CC_NE;
   3416          goto do_compare_ze;
   3417 
   3418       do_compare_ze: {
   3419             s390_opnd_RMI op1, op2;
   3420 
   3421             op1  = s390_isel_int_expr_RMI(env, arg1);
   3422             reg1 = newVRegI(env);
   3423             addInstr(env, s390_insn_unop(4, op, reg1, op1));
   3424 
   3425             op2  = s390_isel_int_expr_RMI(env, arg2);
   3426             reg2 = newVRegI(env);
   3427             addInstr(env, s390_insn_unop(4, op, reg2, op2));  /* zero extend */
   3428 
   3429             op2 = s390_opnd_reg(reg2);
   3430             addInstr(env, s390_insn_compare(4, reg1, op2, False));
   3431 
   3432             return result;
   3433          }
   3434 
   3435       case Iop_CmpEQ32:
   3436       case Iop_CmpEQ64:
   3437       case Iop_CasCmpEQ32:
   3438       case Iop_CasCmpEQ64:
   3439          result = S390_CC_E;
   3440          goto do_compare;
   3441 
   3442       case Iop_CmpNE32:
   3443       case Iop_CmpNE64:
   3444       case Iop_CasCmpNE32:
   3445       case Iop_CasCmpNE64:
   3446          result = S390_CC_NE;
   3447          goto do_compare;
   3448 
   3449       do_compare: {
   3450             HReg op1;
   3451             s390_opnd_RMI op2;
   3452 
   3453             order_commutative_operands(arg1, arg2);
   3454 
   3455             op1 = s390_isel_int_expr(env, arg1);
   3456             op2 = s390_isel_int_expr_RMI(env, arg2);
   3457 
   3458             addInstr(env, s390_insn_compare(size, op1, op2, False));
   3459 
   3460             return result;
   3461          }
   3462 
   3463       case Iop_CmpLT32S:
   3464       case Iop_CmpLE32S:
   3465       case Iop_CmpLT64S:
   3466       case Iop_CmpLE64S: {
   3467          HReg op1;
   3468          s390_opnd_RMI op2;
   3469 
   3470          op1 = s390_isel_int_expr(env, arg1);
   3471          op2 = s390_isel_int_expr_RMI(env, arg2);
   3472 
   3473          addInstr(env, s390_insn_compare(size, op1, op2, True));
   3474 
   3475          return (cond->Iex.Binop.op == Iop_CmpLT32S ||
   3476                  cond->Iex.Binop.op == Iop_CmpLT64S) ? S390_CC_L : S390_CC_LE;
   3477       }
   3478 
   3479       case Iop_CmpLT32U:
   3480       case Iop_CmpLE32U:
   3481       case Iop_CmpLT64U:
   3482       case Iop_CmpLE64U: {
   3483          HReg op1;
   3484          s390_opnd_RMI op2;
   3485 
   3486          op1 = s390_isel_int_expr(env, arg1);
   3487          op2 = s390_isel_int_expr_RMI(env, arg2);
   3488 
   3489          addInstr(env, s390_insn_compare(size, op1, op2, False));
   3490 
   3491          return (cond->Iex.Binop.op == Iop_CmpLT32U ||
   3492                  cond->Iex.Binop.op == Iop_CmpLT64U) ? S390_CC_L : S390_CC_LE;
   3493       }
   3494 
   3495       default:
   3496          goto fail;
   3497       }
   3498    }
   3499 
   3500  fail:
   3501    ppIRExpr(cond);
   3502    vpanic("s390_isel_cc: unexpected operator");
   3503 }
   3504 
   3505 
   3506 /*---------------------------------------------------------*/
   3507 /*--- ISEL: Statements                                  ---*/
   3508 /*---------------------------------------------------------*/
   3509 
   3510 static void
   3511 s390_isel_stmt(ISelEnv *env, IRStmt *stmt)
   3512 {
   3513    if (vex_traceflags & VEX_TRACE_VCODE) {
   3514       vex_printf("\n -- ");
   3515       ppIRStmt(stmt);
   3516       vex_printf("\n");
   3517    }
   3518 
   3519    switch (stmt->tag) {
   3520 
   3521       /* --------- STORE --------- */
   3522    case Ist_Store: {
   3523       IRType tyd = typeOfIRExpr(env->type_env, stmt->Ist.Store.data);
   3524       s390_amode *am;
   3525       HReg src;
   3526 
   3527       if (stmt->Ist.Store.end != Iend_BE) goto stmt_fail;
   3528 
   3529       am = s390_isel_amode(env, stmt->Ist.Store.addr);
   3530 
   3531       switch (tyd) {
   3532       case Ity_I8:
   3533       case Ity_I16:
   3534       case Ity_I32:
   3535       case Ity_I64:
   3536          /* fixs390: We could check for INSN_MADD here. */
   3537          if (am->tag == S390_AMODE_B12 &&
   3538              stmt->Ist.Store.data->tag == Iex_Const) {
   3539             ULong value =
   3540                get_const_value_as_ulong(stmt->Ist.Store.data->Iex.Const.con);
   3541             addInstr(env, s390_insn_mimm(sizeofIRType(tyd), am, value));
   3542             return;
   3543          }
   3544          /* Check whether we can use a memcpy here. Currently, the restriction
   3545             is that both amodes need to be B12, so MVC can be emitted.
   3546             We do not consider a store whose data expression is a load because
   3547             we don't want to deal with overlapping locations. */
   3548          /* store(get) never overlaps*/
   3549          if (am->tag == S390_AMODE_B12 &&
   3550              stmt->Ist.Store.data->tag == Iex_Get) {
   3551             UInt offset = stmt->Ist.Store.data->Iex.Get.offset;
   3552             s390_amode *from = s390_amode_for_guest_state(offset);
   3553             addInstr(env, s390_insn_memcpy(sizeofIRType(tyd), am, from));
   3554             return;
   3555          }
   3556          /* General case: compile data into a register */
   3557          src = s390_isel_int_expr(env, stmt->Ist.Store.data);
   3558          break;
   3559 
   3560       case Ity_F32:
   3561       case Ity_F64:
   3562          src = s390_isel_float_expr(env, stmt->Ist.Store.data);
   3563          break;
   3564 
   3565       case Ity_D32:
   3566       case Ity_D64:
   3567          src = s390_isel_dfp_expr(env, stmt->Ist.Store.data);
   3568          break;
   3569 
   3570       case Ity_F128:
   3571       case Ity_D128:
   3572          /* Cannot occur. No such instruction */
   3573          vpanic("Ist_Store with 128-bit floating point data");
   3574 
   3575       default:
   3576          goto stmt_fail;
   3577       }
   3578 
   3579       addInstr(env, s390_insn_store(sizeofIRType(tyd), am, src));
   3580       return;
   3581    }
   3582 
   3583       /* --------- PUT --------- */
   3584    case Ist_Put: {
   3585       IRType tyd = typeOfIRExpr(env->type_env, stmt->Ist.Put.data);
   3586       HReg src;
   3587       s390_amode *am;
   3588       ULong new_value, old_value, difference;
   3589 
   3590       /* Detect updates to certain guest registers. We track the contents
   3591          of those registers as long as they contain constants. If the new
   3592          constant is either zero or in the 8-bit neighbourhood of the
   3593          current value we can use a memory-to-memory insn to do the update. */
   3594 
   3595       Int offset = stmt->Ist.Put.offset;
   3596 
   3597       /* Check necessary conditions:
   3598          (1) must be one of the registers we care about
   3599          (2) assigned value must be a constant */
   3600       Int guest_reg = get_guest_reg(offset);
   3601 
   3602       if (guest_reg == GUEST_UNKNOWN) goto not_special;
   3603 
   3604       if (stmt->Ist.Put.data->tag != Iex_Const) {
   3605          /* Invalidate guest register contents */
   3606          env->old_value_valid[guest_reg] = False;
   3607          goto not_special;
   3608       }
   3609 
   3610       /* We can only handle Ity_I64, but the CC_DEPS field can have floats */
   3611       if (tyd != Ity_I64)
   3612          goto not_special;
   3613 
   3614       /* OK. Necessary conditions are satisfied. */
   3615 
   3616       old_value = env->old_value[guest_reg];
   3617       new_value = stmt->Ist.Put.data->Iex.Const.con->Ico.U64;
   3618       env->old_value[guest_reg] = new_value;
   3619 
   3620       Bool old_value_is_valid = env->old_value_valid[guest_reg];
   3621       env->old_value_valid[guest_reg] = True;
   3622 
   3623       /* If the register already contains the new value, there is nothing
   3624          to do here. */
   3625       if (old_value_is_valid && new_value == old_value) {
   3626          return;
   3627       }
   3628 
   3629       if (old_value_is_valid == False) goto not_special;
   3630 
   3631       /* If the new value is in the neighbourhood of the old value
   3632          we can use a memory-to-memory insn */
   3633       difference = new_value - old_value;
   3634 
   3635       if (s390_host_has_gie && ulong_fits_signed_8bit(difference)) {
   3636          am = s390_amode_for_guest_state(offset);
   3637          addInstr(env, s390_insn_madd(sizeofIRType(tyd), am,
   3638                                       (difference & 0xFF), new_value));
   3639          return;
   3640       }
   3641 
   3642       /* If the high word is the same it is sufficient to load the low word. */
   3643       if ((old_value >> 32) == (new_value >> 32)) {
   3644          am = s390_amode_for_guest_state(offset + 4);
   3645          addInstr(env, s390_insn_mimm(4, am, new_value & 0xFFFFFFFF));
   3646          return;
   3647       }
   3648 
   3649       /* No special case applies... fall through */
   3650 
   3651    not_special:
   3652       am = s390_amode_for_guest_state(offset);
   3653 
   3654       switch (tyd) {
   3655       case Ity_I8:
   3656       case Ity_I16:
   3657       case Ity_I32:
   3658       case Ity_I64:
   3659          if (am->tag == S390_AMODE_B12 &&
   3660              stmt->Ist.Put.data->tag == Iex_Const) {
   3661             ULong value =
   3662                get_const_value_as_ulong(stmt->Ist.Put.data->Iex.Const.con);
   3663             addInstr(env, s390_insn_mimm(sizeofIRType(tyd), am, value));
   3664             return;
   3665          }
   3666          /* Check whether we can use a memcpy here. Currently, the restriction
   3667             is that both amodes need to be B12, so MVC can be emitted. */
   3668          /* put(load) never overlaps */
   3669          if (am->tag == S390_AMODE_B12 &&
   3670              stmt->Ist.Put.data->tag == Iex_Load) {
   3671             if (stmt->Ist.Put.data->Iex.Load.end != Iend_BE) goto stmt_fail;
   3672             IRExpr *data = stmt->Ist.Put.data->Iex.Load.addr;
   3673             s390_amode *from = s390_isel_amode(env, data);
   3674             UInt size = sizeofIRType(tyd);
   3675 
   3676             if (from->tag == S390_AMODE_B12) {
   3677                /* Source can be compiled into a B12 amode. */
   3678                addInstr(env, s390_insn_memcpy(size, am, from));
   3679                return;
   3680             }
   3681 
   3682             src = newVRegI(env);
   3683             addInstr(env, s390_insn_load(size, src, from));
   3684             break;
   3685          }
   3686          /* put(get) */
   3687          if (am->tag == S390_AMODE_B12 &&
   3688              stmt->Ist.Put.data->tag == Iex_Get) {
   3689             UInt put_offset = am->d;
   3690             UInt get_offset = stmt->Ist.Put.data->Iex.Get.offset;
   3691             UInt size = sizeofIRType(tyd);
   3692             /* don't memcpy in case of overlap */
   3693             if (put_offset + size <= get_offset ||
   3694                 get_offset + size <= put_offset) {
   3695                s390_amode *from = s390_amode_for_guest_state(get_offset);
   3696                addInstr(env, s390_insn_memcpy(size, am, from));
   3697                return;
   3698             }
   3699             goto no_memcpy_put;
   3700          }
   3701          /* General case: compile data into a register */
   3702 no_memcpy_put:
   3703          src = s390_isel_int_expr(env, stmt->Ist.Put.data);
   3704          break;
   3705 
   3706       case Ity_F32:
   3707       case Ity_F64:
   3708          src = s390_isel_float_expr(env, stmt->Ist.Put.data);
   3709          break;
   3710 
   3711       case Ity_F128:
   3712       case Ity_D128:
   3713          /* Does not occur. See function put_(f|d)pr_pair. */
   3714          vpanic("Ist_Put with 128-bit floating point data");
   3715 
   3716       case Ity_D32:
   3717       case Ity_D64:
   3718          src = s390_isel_dfp_expr(env, stmt->Ist.Put.data);
   3719          break;
   3720 
   3721       default:
   3722          goto stmt_fail;
   3723       }
   3724 
   3725       addInstr(env, s390_insn_store(sizeofIRType(tyd), am, src));
   3726       return;
   3727    }
   3728 
   3729       /* --------- TMP --------- */
   3730    case Ist_WrTmp: {
   3731       IRTemp tmp = stmt->Ist.WrTmp.tmp;
   3732       IRType tyd = typeOfIRTemp(env->type_env, tmp);
   3733       HReg src, dst;
   3734 
   3735       switch (tyd) {
   3736       case Ity_I128: {
   3737          HReg dst_hi, dst_lo, res_hi, res_lo;
   3738 
   3739          s390_isel_int128_expr(&res_hi, &res_lo, env, stmt->Ist.WrTmp.data);
   3740          lookupIRTemp128(&dst_hi, &dst_lo, env, tmp);
   3741 
   3742          addInstr(env, s390_insn_move(8, dst_hi, res_hi));
   3743          addInstr(env, s390_insn_move(8, dst_lo, res_lo));
   3744          return;
   3745       }
   3746 
   3747       case Ity_I8:
   3748       case Ity_I16:
   3749       case Ity_I32:
   3750       case Ity_I64:
   3751          src = s390_isel_int_expr(env, stmt->Ist.WrTmp.data);
   3752          dst = lookupIRTemp(env, tmp);
   3753          break;
   3754 
   3755       case Ity_I1: {
   3756          s390_cc_t cond = s390_isel_cc(env, stmt->Ist.WrTmp.data);
   3757          dst = lookupIRTemp(env, tmp);
   3758          addInstr(env, s390_insn_cc2bool(dst, cond));
   3759          return;
   3760       }
   3761 
   3762       case Ity_F32:
   3763       case Ity_F64:
   3764          src = s390_isel_float_expr(env, stmt->Ist.WrTmp.data);
   3765          dst = lookupIRTemp(env, tmp);
   3766          break;
   3767 
   3768       case Ity_F128: {
   3769          HReg dst_hi, dst_lo, res_hi, res_lo;
   3770 
   3771          s390_isel_float128_expr(&res_hi, &res_lo, env, stmt->Ist.WrTmp.data);
   3772          lookupIRTemp128(&dst_hi, &dst_lo, env, tmp);
   3773 
   3774          addInstr(env, s390_insn_move(8, dst_hi, res_hi));
   3775          addInstr(env, s390_insn_move(8, dst_lo, res_lo));
   3776          return;
   3777       }
   3778 
   3779       case Ity_D32:
   3780       case Ity_D64:
   3781          src = s390_isel_dfp_expr(env, stmt->Ist.WrTmp.data);
   3782          dst = lookupIRTemp(env, tmp);
   3783          break;
   3784 
   3785       case Ity_D128: {
   3786          HReg dst_hi, dst_lo, res_hi, res_lo;
   3787 
   3788          s390_isel_dfp128_expr(&res_hi, &res_lo, env, stmt->Ist.WrTmp.data);
   3789          lookupIRTemp128(&dst_hi, &dst_lo, env, tmp);
   3790 
   3791          addInstr(env, s390_insn_move(8, dst_hi, res_hi));
   3792          addInstr(env, s390_insn_move(8, dst_lo, res_lo));
   3793          return;
   3794       }
   3795 
   3796       default:
   3797          goto stmt_fail;
   3798       }
   3799 
   3800       addInstr(env, s390_insn_move(sizeofIRType(tyd), dst, src));
   3801       return;
   3802    }
   3803 
   3804       /* --------- Call to DIRTY helper --------- */
   3805    case Ist_Dirty: {
   3806       IRType   retty;
   3807       IRDirty* d = stmt->Ist.Dirty.details;
   3808       HReg dst;
   3809       RetLoc rloc    = mk_RetLoc_INVALID();
   3810       UInt   addToSp = 0;
   3811       Int i;
   3812 
   3813       /* Invalidate tracked values of those guest state registers that are
   3814          modified by this helper. */
   3815       for (i = 0; i < d->nFxState; ++i) {
   3816          /* JRS 1 June 2012: AFAICS, s390 guest doesn't use 'repeat'
   3817             descriptors in guest state effect descriptions.  Hence: */
   3818          vassert(d->fxState[i].nRepeats == 0 && d->fxState[i].repeatLen == 0);
   3819          if ((d->fxState[i].fx == Ifx_Write || d->fxState[i].fx == Ifx_Modify)) {
   3820             Int guest_reg = get_guest_reg(d->fxState[i].offset);
   3821             if (guest_reg != GUEST_UNKNOWN)
   3822                env->old_value_valid[guest_reg] = False;
   3823          }
   3824       }
   3825 
   3826       if (d->tmp == IRTemp_INVALID) {
   3827          /* No return value. */
   3828          retty = Ity_INVALID;
   3829          doHelperCall(&addToSp, &rloc, env, d->guard,  d->cee, retty,
   3830                       d->args);
   3831          vassert(is_sane_RetLoc(rloc));
   3832          vassert(rloc.pri == RLPri_None);
   3833          vassert(addToSp == 0);
   3834 
   3835          return;
   3836       }
   3837 
   3838       retty = typeOfIRTemp(env->type_env, d->tmp);
   3839       if (retty == Ity_I64 || retty == Ity_I32
   3840           || retty == Ity_I16 || retty == Ity_I8) {
   3841          /* Move the returned value to the destination register */
   3842          HReg ret = make_gpr(S390_REGNO_RETURN_VALUE);
   3843 
   3844          dst = lookupIRTemp(env, d->tmp);
   3845          doHelperCall(&addToSp, &rloc, env, d->guard,  d->cee, retty,
   3846                       d->args);
   3847          vassert(is_sane_RetLoc(rloc));
   3848          vassert(rloc.pri == RLPri_Int);
   3849          vassert(addToSp == 0);
   3850          addInstr(env, s390_insn_move(sizeof(ULong), dst, ret));
   3851 
   3852          return;
   3853       }
   3854       break;
   3855    }
   3856 
   3857    case Ist_CAS:
   3858       if (stmt->Ist.CAS.details->oldHi == IRTemp_INVALID) {
   3859          IRCAS *cas = stmt->Ist.CAS.details;
   3860          s390_amode *op2 = s390_isel_amode_b12_b20(env, cas->addr);
   3861          HReg op3 = s390_isel_int_expr(env, cas->dataLo);  /* new value */
   3862          HReg op1 = s390_isel_int_expr(env, cas->expdLo);  /* expected value */
   3863          HReg old = lookupIRTemp(env, cas->oldLo);
   3864 
   3865          if (typeOfIRTemp(env->type_env, cas->oldLo) == Ity_I32) {
   3866             addInstr(env, s390_insn_cas(4, op1, op2, op3, old));
   3867          } else {
   3868             addInstr(env, s390_insn_cas(8, op1, op2, op3, old));
   3869          }
   3870          return;
   3871       } else {
   3872          IRCAS *cas = stmt->Ist.CAS.details;
   3873          s390_amode *op2 = s390_isel_amode_b12_b20(env, cas->addr);
   3874          HReg r8, r9, r10, r11, r1;
   3875          HReg op3_high = s390_isel_int_expr(env, cas->dataHi);  /* new value */
   3876          HReg op3_low  = s390_isel_int_expr(env, cas->dataLo);  /* new value */
   3877          HReg op1_high = s390_isel_int_expr(env, cas->expdHi);  /* expected value */
   3878          HReg op1_low  = s390_isel_int_expr(env, cas->expdLo);  /* expected value */
   3879          HReg old_low  = lookupIRTemp(env, cas->oldLo);
   3880          HReg old_high = lookupIRTemp(env, cas->oldHi);
   3881 
   3882          /* Use non-virtual registers r8 and r9 as pair for op1
   3883             and move op1 there */
   3884          r8 = make_gpr(8);
   3885          r9 = make_gpr(9);
   3886          addInstr(env, s390_insn_move(8, r8, op1_high));
   3887          addInstr(env, s390_insn_move(8, r9, op1_low));
   3888 
   3889          /* Use non-virtual registers r10 and r11 as pair for op3
   3890             and move op3 there */
   3891          r10 = make_gpr(10);
   3892          r11 = make_gpr(11);
   3893          addInstr(env, s390_insn_move(8, r10, op3_high));
   3894          addInstr(env, s390_insn_move(8, r11, op3_low));
   3895 
   3896          /* Register r1 is used as a scratch register */
   3897          r1 = make_gpr(1);
   3898 
   3899          if (typeOfIRTemp(env->type_env, cas->oldLo) == Ity_I32) {
   3900             addInstr(env, s390_insn_cdas(4, r8, r9, op2, r10, r11,
   3901                                          old_high, old_low, r1));
   3902          } else {
   3903             addInstr(env, s390_insn_cdas(8, r8, r9, op2, r10, r11,
   3904                                          old_high, old_low, r1));
   3905          }
   3906          addInstr(env, s390_insn_move(8, op1_high, r8));
   3907          addInstr(env, s390_insn_move(8, op1_low,  r9));
   3908          addInstr(env, s390_insn_move(8, op3_high, r10));
   3909          addInstr(env, s390_insn_move(8, op3_low,  r11));
   3910          return;
   3911       }
   3912       break;
   3913 
   3914       /* --------- EXIT --------- */
   3915    case Ist_Exit: {
   3916       s390_cc_t cond;
   3917       IRConstTag tag = stmt->Ist.Exit.dst->tag;
   3918 
   3919       if (tag != Ico_U64)
   3920          vpanic("s390_isel_stmt: Ist_Exit: dst is not a 64-bit value");
   3921 
   3922       s390_amode *guest_IA = s390_amode_for_guest_state(stmt->Ist.Exit.offsIP);
   3923       cond = s390_isel_cc(env, stmt->Ist.Exit.guard);
   3924 
   3925       /* Case: boring transfer to known address */
   3926       if (stmt->Ist.Exit.jk == Ijk_Boring) {
   3927          if (env->chaining_allowed) {
   3928             /* .. almost always true .. */
   3929             /* Skip the event check at the dst if this is a forwards
   3930                edge. */
   3931             Bool to_fast_entry
   3932                = ((Addr64)stmt->Ist.Exit.dst->Ico.U64) > env->max_ga;
   3933             if (0) vex_printf("%s", to_fast_entry ? "Y" : ",");
   3934             addInstr(env, s390_insn_xdirect(cond, stmt->Ist.Exit.dst->Ico.U64,
   3935                                             guest_IA, to_fast_entry));
   3936          } else {
   3937             /* .. very occasionally .. */
   3938             /* We can't use chaining, so ask for an assisted transfer,
   3939                as that's the only alternative that is allowable. */
   3940             HReg dst = s390_isel_int_expr(env,
   3941                                           IRExpr_Const(stmt->Ist.Exit.dst));
   3942             addInstr(env, s390_insn_xassisted(cond, dst, guest_IA, Ijk_Boring));
   3943          }
   3944          return;
   3945       }
   3946 
   3947       /* Case: assisted transfer to arbitrary address */
   3948       switch (stmt->Ist.Exit.jk) {
   3949       case Ijk_EmFail:
   3950       case Ijk_EmWarn:
   3951       case Ijk_NoDecode:
   3952       case Ijk_InvalICache:
   3953       case Ijk_Sys_syscall:
   3954       case Ijk_ClientReq:
   3955       case Ijk_NoRedir:
   3956       case Ijk_Yield:
   3957       case Ijk_SigTRAP: {
   3958          HReg dst = s390_isel_int_expr(env, IRExpr_Const(stmt->Ist.Exit.dst));
   3959          addInstr(env, s390_insn_xassisted(cond, dst, guest_IA,
   3960                                            stmt->Ist.Exit.jk));
   3961          return;
   3962       }
   3963       default:
   3964          break;
   3965       }
   3966 
   3967       /* Do we ever expect to see any other kind? */
   3968       goto stmt_fail;
   3969    }
   3970 
   3971       /* --------- MEM FENCE --------- */
   3972    case Ist_MBE:
   3973       switch (stmt->Ist.MBE.event) {
   3974          case Imbe_Fence:
   3975             addInstr(env, s390_insn_mfence());
   3976             return;
   3977          default:
   3978             break;
   3979       }
   3980       break;
   3981 
   3982       /* --------- Miscellaneous --------- */
   3983 
   3984    case Ist_PutI:    /* Not needed */
   3985    case Ist_IMark:   /* Doesn't generate any executable code */
   3986    case Ist_NoOp:    /* Doesn't generate any executable code */
   3987    case Ist_AbiHint: /* Meaningless in IR */
   3988       return;
   3989 
   3990    default:
   3991       break;
   3992    }
   3993 
   3994  stmt_fail:
   3995    ppIRStmt(stmt);
   3996    vpanic("s390_isel_stmt");
   3997 }
   3998 
   3999 
   4000 /*---------------------------------------------------------*/
   4001 /*--- ISEL: Basic block terminators (Nexts)             ---*/
   4002 /*---------------------------------------------------------*/
   4003 
   4004 static void
   4005 iselNext(ISelEnv *env, IRExpr *next, IRJumpKind jk, Int offsIP)
   4006 {
   4007    if (vex_traceflags & VEX_TRACE_VCODE) {
   4008       vex_printf("\n-- PUT(%d) = ", offsIP);
   4009       ppIRExpr(next);
   4010       vex_printf("; exit-");
   4011       ppIRJumpKind(jk);
   4012       vex_printf("\n");
   4013    }
   4014 
   4015    s390_amode *guest_IA = s390_amode_for_guest_state(offsIP);
   4016 
   4017    /* Case: boring transfer to known address */
   4018    if (next->tag == Iex_Const) {
   4019       IRConst *cdst = next->Iex.Const.con;
   4020       vassert(cdst->tag == Ico_U64);
   4021       if (jk == Ijk_Boring || jk == Ijk_Call) {
   4022          /* Boring transfer to known address */
   4023          if (env->chaining_allowed) {
   4024             /* .. almost always true .. */
   4025             /* Skip the event check at the dst if this is a forwards
   4026                edge. */
   4027             Bool to_fast_entry
   4028                = ((Addr64)cdst->Ico.U64) > env->max_ga;
   4029             if (0) vex_printf("%s", to_fast_entry ? "X" : ".");
   4030             addInstr(env, s390_insn_xdirect(S390_CC_ALWAYS, cdst->Ico.U64,
   4031                                             guest_IA, to_fast_entry));
   4032          } else {
   4033             /* .. very occasionally .. */
   4034             /* We can't use chaining, so ask for an indirect transfer,
   4035                as that's the cheapest alternative that is allowable. */
   4036             HReg dst = s390_isel_int_expr(env, next);
   4037             addInstr(env, s390_insn_xassisted(S390_CC_ALWAYS, dst, guest_IA,
   4038                                               Ijk_Boring));
   4039          }
   4040          return;
   4041       }
   4042    }
   4043 
   4044    /* Case: call/return (==boring) transfer to any address */
   4045    switch (jk) {
   4046    case Ijk_Boring:
   4047    case Ijk_Ret:
   4048    case Ijk_Call: {
   4049       HReg dst = s390_isel_int_expr(env, next);
   4050       if (env->chaining_allowed) {
   4051          addInstr(env, s390_insn_xindir(S390_CC_ALWAYS, dst, guest_IA));
   4052       } else {
   4053          addInstr(env, s390_insn_xassisted(S390_CC_ALWAYS, dst, guest_IA,
   4054                                            Ijk_Boring));
   4055       }
   4056       return;
   4057    }
   4058    default:
   4059       break;
   4060    }
   4061 
   4062    /* Case: some other kind of transfer to any address */
   4063    switch (jk) {
   4064    case Ijk_EmFail:
   4065    case Ijk_EmWarn:
   4066    case Ijk_NoDecode:
   4067    case Ijk_InvalICache:
   4068    case Ijk_Sys_syscall:
   4069    case Ijk_ClientReq:
   4070    case Ijk_NoRedir:
   4071    case Ijk_Yield:
   4072    case Ijk_SigTRAP: {
   4073       HReg dst = s390_isel_int_expr(env, next);
   4074       addInstr(env, s390_insn_xassisted(S390_CC_ALWAYS, dst, guest_IA, jk));
   4075       return;
   4076    }
   4077    default:
   4078       break;
   4079    }
   4080 
   4081    vpanic("iselNext");
   4082 }
   4083 
   4084 
   4085 /*---------------------------------------------------------*/
   4086 /*--- Insn selector top-level                           ---*/
   4087 /*---------------------------------------------------------*/
   4088 
   4089 /* Translate an entire SB to s390 code.
   4090    Note: archinfo_host is a pointer to a stack-allocated variable.
   4091    Do not assign it to a global variable! */
   4092 
   4093 HInstrArray *
   4094 iselSB_S390(const IRSB *bb, VexArch arch_host, const VexArchInfo *archinfo_host,
   4095             const VexAbiInfo *vbi, Int offset_host_evcheck_counter,
   4096             Int offset_host_evcheck_fail_addr, Bool chaining_allowed,
   4097             Bool add_profinc, Addr max_ga)
   4098 {
   4099    UInt     i, j;
   4100    HReg     hreg, hregHI;
   4101    ISelEnv *env;
   4102    UInt     hwcaps_host = archinfo_host->hwcaps;
   4103 
   4104    /* Do some sanity checks */
   4105    vassert((VEX_HWCAPS_S390X(hwcaps_host) & ~(VEX_HWCAPS_S390X_ALL)) == 0);
   4106 
   4107    /* Check that the host's endianness is as expected. */
   4108    vassert(archinfo_host->endness == VexEndnessBE);
   4109 
   4110    /* Make up an initial environment to use. */
   4111    env = LibVEX_Alloc_inline(sizeof(ISelEnv));
   4112    env->vreg_ctr = 0;
   4113 
   4114    /* Set up output code array. */
   4115    env->code = newHInstrArray();
   4116 
   4117    /* Copy BB's type env. */
   4118    env->type_env = bb->tyenv;
   4119 
   4120    /* Set up data structures for tracking guest register values. */
   4121    for (i = 0; i < NUM_TRACKED_REGS; ++i) {
   4122       env->old_value[i] = 0;  /* just something to have a defined value */
   4123       env->old_value_valid[i] = False;
   4124    }
   4125 
   4126    /* Make up an IRTemp -> virtual HReg mapping.  This doesn't
   4127       change as we go along. For some reason types_used has Int type -- but
   4128       it should be unsigned. Internally we use an unsigned type; so we
   4129       assert it here. */
   4130    vassert(bb->tyenv->types_used >= 0);
   4131 
   4132    env->n_vregmap = bb->tyenv->types_used;
   4133    env->vregmap   = LibVEX_Alloc_inline(env->n_vregmap * sizeof(HReg));
   4134    env->vregmapHI = LibVEX_Alloc_inline(env->n_vregmap * sizeof(HReg));
   4135 
   4136    env->previous_bfp_rounding_mode = NULL;
   4137    env->previous_dfp_rounding_mode = NULL;
   4138 
   4139    /* and finally ... */
   4140    env->hwcaps    = hwcaps_host;
   4141 
   4142    env->max_ga = max_ga;
   4143    env->chaining_allowed = chaining_allowed;
   4144 
   4145    /* For each IR temporary, allocate a suitably-kinded virtual
   4146       register. */
   4147    j = 0;
   4148    for (i = 0; i < env->n_vregmap; i++) {
   4149       hregHI = hreg = INVALID_HREG;
   4150       switch (bb->tyenv->types[i]) {
   4151       case Ity_I1:
   4152       case Ity_I8:
   4153       case Ity_I16:
   4154       case Ity_I32:
   4155       case Ity_I64:
   4156          hreg = mkVRegI(j++);
   4157          break;
   4158 
   4159       case Ity_I128:
   4160          hreg   = mkVRegI(j++);
   4161          hregHI = mkVRegI(j++);
   4162          break;
   4163 
   4164       case Ity_F32:
   4165       case Ity_F64:
   4166       case Ity_D32:
   4167       case Ity_D64:
   4168          hreg = mkVRegF(j++);
   4169          break;
   4170 
   4171       case Ity_F128:
   4172       case Ity_D128:
   4173          hreg   = mkVRegF(j++);
   4174          hregHI = mkVRegF(j++);
   4175          break;
   4176 
   4177       case Ity_V128: /* fall through */
   4178       default:
   4179          ppIRType(bb->tyenv->types[i]);
   4180          vpanic("iselSB_S390: IRTemp type");
   4181       }
   4182 
   4183       env->vregmap[i]   = hreg;
   4184       env->vregmapHI[i] = hregHI;
   4185    }
   4186    env->vreg_ctr = j;
   4187 
   4188    /* The very first instruction must be an event check. */
   4189    s390_amode *counter, *fail_addr;
   4190    counter   = s390_amode_for_guest_state(offset_host_evcheck_counter);
   4191    fail_addr = s390_amode_for_guest_state(offset_host_evcheck_fail_addr);
   4192    addInstr(env, s390_insn_evcheck(counter, fail_addr));
   4193 
   4194    /* Possibly a block counter increment (for profiling).  At this
   4195       point we don't know the address of the counter, so just pretend
   4196       it is zero.  It will have to be patched later, but before this
   4197       translation is used, by a call to LibVEX_patchProfInc. */
   4198    if (add_profinc) {
   4199       addInstr(env, s390_insn_profinc());
   4200    }
   4201 
   4202    /* Ok, finally we can iterate over the statements. */
   4203    for (i = 0; i < bb->stmts_used; i++)
   4204       if (bb->stmts[i])
   4205          s390_isel_stmt(env, bb->stmts[i]);
   4206 
   4207    iselNext(env, bb->next, bb->jumpkind, bb->offsIP);
   4208 
   4209    /* Record the number of vregs we used. */
   4210    env->code->n_vregs = env->vreg_ctr;
   4211 
   4212    return env->code;
   4213 }
   4214 
   4215 /*---------------------------------------------------------------*/
   4216 /*--- end                                    host_s390_isel.c ---*/
   4217 /*---------------------------------------------------------------*/
   4218