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-2012
     12 
     13    This program is free software; you can redistribute it and/or
     14    modify it under the terms of the GNU General Public License as
     15    published by the Free Software Foundation; either version 2 of the
     16    License, or (at your option) any later version.
     17 
     18    This program is distributed in the hope that it will be useful, but
     19    WITHOUT ANY WARRANTY; without even the implied warranty of
     20    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     21    General Public License for more details.
     22 
     23    You should have received a copy of the GNU General Public License
     24    along with this program; if not, write to the Free Software
     25    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
     26    02110-1301, USA.
     27 
     28    The GNU General Public License is contained in the file COPYING.
     29 */
     30 
     31 /* Contributed by Florian Krohm */
     32 
     33 #include "libvex_basictypes.h"
     34 #include "libvex_ir.h"
     35 #include "libvex.h"
     36 #include "libvex_s390x_common.h"
     37 
     38 #include "main_util.h"
     39 #include "main_globals.h"
     40 #include "guest_s390_defs.h"   /* guest_s390x_state_requires_precise_mem_exns */
     41 #include "host_generic_regs.h"
     42 #include "host_s390_defs.h"
     43 
     44 /*---------------------------------------------------------*/
     45 /*--- ISelEnv                                           ---*/
     46 /*---------------------------------------------------------*/
     47 
     48 /* This carries around:
     49 
     50    - A mapping from IRTemp to IRType, giving the type of any IRTemp we
     51      might encounter.  This is computed before insn selection starts,
     52      and does not change.
     53 
     54    - A mapping from IRTemp to HReg.  This tells the insn selector
     55      which virtual register(s) are associated with each IRTemp
     56       temporary.  This is computed before insn selection starts, and
     57       does not change.  We expect this mapping to map precisely the
     58       same set of IRTemps as the type mapping does.
     59 
     60          - vregmap   holds the primary register for the IRTemp.
     61          - vregmapHI holds the secondary register for the IRTemp,
     62               if any is needed.  That's only for Ity_I64 temps
     63               in 32 bit mode or Ity_I128 temps in 64-bit mode.
     64 
     65     - The code array, that is, the insns selected so far.
     66 
     67     - A counter, for generating new virtual registers.
     68 
     69     - The host subarchitecture we are selecting insns for.
     70       This is set at the start and does not change.
     71 
     72    - A Bool for indicating whether we may generate chain-me
     73      instructions for control flow transfers, or whether we must use
     74      XAssisted.
     75 
     76    - The maximum guest address of any guest insn in this block.
     77      Actually, the address of the highest-addressed byte from any insn
     78      in this block.  Is set at the start and does not change.  This is
     79      used for detecting jumps which are definitely forward-edges from
     80      this block, and therefore can be made (chained) to the fast entry
     81      point of the destination, thereby avoiding the destination's
     82      event check.
     83 
     84     - A flag to indicate whether the guest IA has been assigned to.
     85 
     86     - Values of certain guest registers which are often assigned constants.
     87 */
     88 
     89 /* Symbolic names for guest registers whose value we're tracking */
     90 enum {
     91    GUEST_IA,
     92    GUEST_CC_OP,
     93    GUEST_CC_DEP1,
     94    GUEST_CC_DEP2,
     95    GUEST_CC_NDEP,
     96    GUEST_SYSNO,
     97    GUEST_COUNTER,
     98    GUEST_UNKNOWN    /* must be the last entry */
     99 };
    100 
    101 /* Number of registers we're tracking. */
    102 #define NUM_TRACKED_REGS GUEST_UNKNOWN
    103 
    104 
    105 typedef struct {
    106    IRTypeEnv   *type_env;
    107 
    108    HInstrArray *code;
    109    HReg        *vregmap;
    110    HReg        *vregmapHI;
    111    UInt         n_vregmap;
    112    UInt         vreg_ctr;
    113    UInt         hwcaps;
    114 
    115    ULong        old_value[NUM_TRACKED_REGS];
    116 
    117    /* The next two are for translation chaining */
    118    Addr64       max_ga;
    119    Bool         chaining_allowed;
    120 
    121    Bool         first_IA_assignment;
    122    Bool         old_value_valid[NUM_TRACKED_REGS];
    123 } ISelEnv;
    124 
    125 
    126 /* Forward declarations */
    127 static HReg          s390_isel_int_expr(ISelEnv *, IRExpr *);
    128 static s390_amode   *s390_isel_amode(ISelEnv *, IRExpr *);
    129 static s390_cc_t     s390_isel_cc(ISelEnv *, IRExpr *);
    130 static s390_opnd_RMI s390_isel_int_expr_RMI(ISelEnv *, IRExpr *);
    131 static void          s390_isel_int128_expr(HReg *, HReg *, ISelEnv *, IRExpr *);
    132 static HReg          s390_isel_float_expr(ISelEnv *, IRExpr *);
    133 static void          s390_isel_float128_expr(HReg *, HReg *, ISelEnv *, IRExpr *);
    134 
    135 
    136 static Int
    137 get_guest_reg(Int offset)
    138 {
    139    switch (offset) {
    140    case S390X_GUEST_OFFSET(guest_IA):        return GUEST_IA;
    141    case S390X_GUEST_OFFSET(guest_CC_OP):     return GUEST_CC_OP;
    142    case S390X_GUEST_OFFSET(guest_CC_DEP1):   return GUEST_CC_DEP1;
    143    case S390X_GUEST_OFFSET(guest_CC_DEP2):   return GUEST_CC_DEP2;
    144    case S390X_GUEST_OFFSET(guest_CC_NDEP):   return GUEST_CC_NDEP;
    145    case S390X_GUEST_OFFSET(guest_SYSNO):     return GUEST_SYSNO;
    146    case S390X_GUEST_OFFSET(guest_counter):   return GUEST_COUNTER;
    147 
    148       /* Also make sure there is never a partial write to one of
    149          these registers. That would complicate matters. */
    150    case S390X_GUEST_OFFSET(guest_IA)+1      ... S390X_GUEST_OFFSET(guest_IA)+7:
    151    case S390X_GUEST_OFFSET(guest_CC_OP)+1   ... S390X_GUEST_OFFSET(guest_CC_OP)+7:
    152    case S390X_GUEST_OFFSET(guest_CC_DEP1)+1 ... S390X_GUEST_OFFSET(guest_CC_DEP1)+7:
    153    case S390X_GUEST_OFFSET(guest_CC_DEP2)+1 ... S390X_GUEST_OFFSET(guest_CC_DEP2)+7:
    154    case S390X_GUEST_OFFSET(guest_CC_NDEP)+1 ... S390X_GUEST_OFFSET(guest_CC_NDEP)+7:
    155    case S390X_GUEST_OFFSET(guest_SYSNO)+1   ... S390X_GUEST_OFFSET(guest_SYSNO)+7:
    156       /* counter is used both as 4-byte and as 8-byte entity */
    157    case S390X_GUEST_OFFSET(guest_counter)+1 ... S390X_GUEST_OFFSET(guest_counter)+3:
    158    case S390X_GUEST_OFFSET(guest_counter)+5 ... S390X_GUEST_OFFSET(guest_counter)+7:
    159       vpanic("partial update of this guest state register is not allowed");
    160       break;
    161 
    162    default: break;
    163    }
    164 
    165    return GUEST_UNKNOWN;
    166 }
    167 
    168 /* Add an instruction */
    169 static void
    170 addInstr(ISelEnv *env, s390_insn *insn)
    171 {
    172    addHInstr(env->code, insn);
    173 
    174    if (vex_traceflags & VEX_TRACE_VCODE) {
    175       vex_printf("%s\n", s390_insn_as_string(insn));
    176    }
    177 }
    178 
    179 
    180 static __inline__ IRExpr *
    181 mkU64(ULong value)
    182 {
    183    return IRExpr_Const(IRConst_U64(value));
    184 }
    185 
    186 
    187 /*---------------------------------------------------------*/
    188 /*--- Registers                                         ---*/
    189 /*---------------------------------------------------------*/
    190 
    191 /* Return the virtual register to which a given IRTemp is mapped. */
    192 static HReg
    193 lookupIRTemp(ISelEnv *env, IRTemp tmp)
    194 {
    195    vassert(tmp < env->n_vregmap);
    196    vassert(env->vregmap[tmp] != INVALID_HREG);
    197 
    198    return env->vregmap[tmp];
    199 }
    200 
    201 
    202 /* Return the two virtual registers to which the IRTemp is mapped. */
    203 static void
    204 lookupIRTemp128(HReg *hi, HReg *lo, ISelEnv *env, IRTemp tmp)
    205 {
    206    vassert(tmp < env->n_vregmap);
    207    vassert(env->vregmapHI[tmp] != INVALID_HREG);
    208 
    209    *lo = env->vregmap[tmp];
    210    *hi = env->vregmapHI[tmp];
    211 }
    212 
    213 
    214 /* Allocate a new integer register */
    215 static HReg
    216 newVRegI(ISelEnv *env)
    217 {
    218    HReg reg = mkHReg(env->vreg_ctr, HRcInt64, True /* virtual */ );
    219    env->vreg_ctr++;
    220 
    221    return reg;
    222 }
    223 
    224 
    225 /* Allocate a new floating point register */
    226 static HReg
    227 newVRegF(ISelEnv *env)
    228 {
    229    HReg reg = mkHReg(env->vreg_ctr, HRcFlt64, True /* virtual */ );
    230 
    231    env->vreg_ctr++;
    232 
    233    return reg;
    234 }
    235 
    236 
    237 /* Construct a non-virtual general purpose register */
    238 static __inline__ HReg
    239 make_gpr(UInt regno)
    240 {
    241    return mkHReg(regno, HRcInt64, False /* virtual */ );
    242 }
    243 
    244 
    245 /* Construct a non-virtual floating point register */
    246 static __inline__ HReg
    247 make_fpr(UInt regno)
    248 {
    249    return mkHReg(regno, HRcFlt64, False /* virtual */ );
    250 }
    251 
    252 
    253 /*---------------------------------------------------------*/
    254 /*--- Amode                                             ---*/
    255 /*---------------------------------------------------------*/
    256 
    257 static __inline__ Bool
    258 ulong_fits_unsigned_12bit(ULong val)
    259 {
    260    return (val & 0xFFFu) == val;
    261 }
    262 
    263 
    264 static __inline__ Bool
    265 ulong_fits_signed_20bit(ULong val)
    266 {
    267    Long v = val & 0xFFFFFu;
    268 
    269    v = (v << 44) >> 44;  /* sign extend */
    270 
    271    return val == (ULong)v;
    272 }
    273 
    274 
    275 static __inline__ Bool
    276 ulong_fits_signed_8bit(ULong val)
    277 {
    278    Long v = val & 0xFFu;
    279 
    280    v = (v << 56) >> 56;  /* sign extend */
    281 
    282    return val == (ULong)v;
    283 }
    284 
    285 /* EXPR is an expression that is used as an address. Return an s390_amode
    286    for it. */
    287 static s390_amode *
    288 s390_isel_amode_wrk(ISelEnv *env, IRExpr *expr)
    289 {
    290    if (expr->tag == Iex_Binop && expr->Iex.Binop.op == Iop_Add64) {
    291       IRExpr *arg1 = expr->Iex.Binop.arg1;
    292       IRExpr *arg2 = expr->Iex.Binop.arg2;
    293 
    294       /* Move constant into right subtree */
    295       if (arg1->tag == Iex_Const) {
    296          IRExpr *tmp;
    297          tmp  = arg1;
    298          arg1 = arg2;
    299          arg2 = tmp;
    300       }
    301 
    302       /* r + constant: Check for b12 first, then b20 */
    303       if (arg2->tag == Iex_Const && arg2->Iex.Const.con->tag == Ico_U64) {
    304          ULong value = arg2->Iex.Const.con->Ico.U64;
    305 
    306          if (ulong_fits_unsigned_12bit(value)) {
    307             return s390_amode_b12((Int)value, s390_isel_int_expr(env, arg1));
    308          }
    309          /* If long-displacement is not available, do not construct B20 or
    310             BX20 amodes because code generation cannot handle them. */
    311          if (s390_host_has_ldisp && ulong_fits_signed_20bit(value)) {
    312             return s390_amode_b20((Int)value, s390_isel_int_expr(env, arg1));
    313          }
    314       }
    315    }
    316 
    317    /* Doesn't match anything in particular.  Generate it into
    318       a register and use that. */
    319    return s390_amode_b12(0, s390_isel_int_expr(env, expr));
    320 }
    321 
    322 
    323 static s390_amode *
    324 s390_isel_amode(ISelEnv *env, IRExpr *expr)
    325 {
    326    s390_amode *am;
    327 
    328    /* Address computation should yield a 64-bit value */
    329    vassert(typeOfIRExpr(env->type_env, expr) == Ity_I64);
    330 
    331    am = s390_isel_amode_wrk(env, expr);
    332 
    333    /* Check post-condition */
    334    vassert(s390_amode_is_sane(am));
    335 
    336    return am;
    337 }
    338 
    339 
    340 /*---------------------------------------------------------*/
    341 /*--- Helper functions                                  ---*/
    342 /*---------------------------------------------------------*/
    343 
    344 /* Constants and memory accesses should be right operands */
    345 #define order_commutative_operands(left, right)                   \
    346         do {                                                      \
    347           if (left->tag == Iex_Const || left->tag == Iex_Load ||  \
    348               left->tag == Iex_Get) {                             \
    349             IRExpr *tmp;                                          \
    350             tmp   = left;                                         \
    351             left  = right;                                        \
    352             right = tmp;                                          \
    353           }                                                       \
    354         } while (0)
    355 
    356 
    357 /* Copy an RMI operand to the DST register */
    358 static s390_insn *
    359 s390_opnd_copy(UChar size, HReg dst, s390_opnd_RMI opnd)
    360 {
    361    switch (opnd.tag) {
    362    case S390_OPND_AMODE:
    363       return s390_insn_load(size, dst, opnd.variant.am);
    364 
    365    case S390_OPND_REG:
    366       return s390_insn_move(size, dst, opnd.variant.reg);
    367 
    368    case S390_OPND_IMMEDIATE:
    369       return s390_insn_load_immediate(size, dst, opnd.variant.imm);
    370 
    371    default:
    372       vpanic("s390_opnd_copy");
    373    }
    374 }
    375 
    376 
    377 /* Construct a RMI operand for a register */
    378 static __inline__ s390_opnd_RMI
    379 s390_opnd_reg(HReg reg)
    380 {
    381    s390_opnd_RMI opnd;
    382 
    383    opnd.tag  = S390_OPND_REG;
    384    opnd.variant.reg = reg;
    385 
    386    return opnd;
    387 }
    388 
    389 
    390 /* Construct a RMI operand for an immediate constant */
    391 static __inline__ s390_opnd_RMI
    392 s390_opnd_imm(ULong value)
    393 {
    394    s390_opnd_RMI opnd;
    395 
    396    opnd.tag  = S390_OPND_IMMEDIATE;
    397    opnd.variant.imm = value;
    398 
    399    return opnd;
    400 }
    401 
    402 
    403 /* Return 1, if EXPR represents the cosntant 0 */
    404 static int
    405 s390_expr_is_const_zero(IRExpr *expr)
    406 {
    407    ULong value;
    408 
    409    if (expr->tag == Iex_Const) {
    410       switch (expr->Iex.Const.con->tag) {
    411       case Ico_U1:  value = expr->Iex.Const.con->Ico.U1;  break;
    412       case Ico_U8:  value = expr->Iex.Const.con->Ico.U8;  break;
    413       case Ico_U16: value = expr->Iex.Const.con->Ico.U16; break;
    414       case Ico_U32: value = expr->Iex.Const.con->Ico.U32; break;
    415       case Ico_U64: value = expr->Iex.Const.con->Ico.U64; break;
    416       default:
    417          vpanic("s390_expr_is_const_zero");
    418       }
    419       return value == 0;
    420    }
    421 
    422    return 0;
    423 }
    424 
    425 
    426 /* Call a helper (clean or dirty)
    427    Arguments must satisfy the following conditions:
    428 
    429    (a) they are expressions yielding an integer result
    430    (b) there can be no more than S390_NUM_GPRPARMS arguments
    431 
    432    guard is a Ity_Bit expression indicating whether or not the
    433    call happens.  If guard == NULL, the call is unconditional.
    434 
    435    Calling the helper function proceeds as follows:
    436 
    437    (1) The helper arguments are evaluated and their value stored in
    438        virtual registers.
    439    (2) The condition code is evaluated
    440    (3) The argument values are copied from the virtual registers to the
    441        registers mandated by the ABI.
    442    (4) Call the helper function.
    443 
    444    This is not the most efficient way as step 3 generates register-to-register
    445    moves. But it is the least fragile way as the only hidden dependency here
    446    is that register-to-register moves (step 3) must not clobber the condition
    447    code. Other schemes (e.g. VEX r2326) that attempt to avoid the register-
    448    to-register add more such dependencies. Not good. Besides, it's the job
    449    of the register allocator to throw out those reg-to-reg moves.
    450 */
    451 static void
    452 doHelperCall(ISelEnv *env, Bool passBBP, IRExpr *guard,
    453              IRCallee *callee, IRExpr **args, HReg dst)
    454 {
    455    UInt n_args, i, argreg, size;
    456    ULong target;
    457    HReg tmpregs[S390_NUM_GPRPARMS];
    458    s390_cc_t cc;
    459 
    460    n_args = 0;
    461    for (i = 0; args[i]; i++)
    462       ++n_args;
    463 
    464    if (n_args > (S390_NUM_GPRPARMS - (passBBP ? 1 : 0))) {
    465       vpanic("doHelperCall: too many arguments");
    466    }
    467 
    468    /* All arguments must have Ity_I64. For two reasons:
    469       (1) We do not handle floating point arguments.
    470       (2) The ABI requires that integer values are sign- or zero-extended
    471            to 64 bit.
    472    */
    473    Int arg_errors = 0;
    474    for (i = 0; i < n_args; ++i) {
    475       IRType type = typeOfIRExpr(env->type_env, args[i]);
    476       if (type != Ity_I64) {
    477          ++arg_errors;
    478          vex_printf("calling %s: argument #%d has type ", callee->name, i);
    479          ppIRType(type);
    480          vex_printf("; Ity_I64 is required\n");
    481       }
    482    }
    483 
    484    if (arg_errors)
    485       vpanic("cannot continue due to errors in argument passing");
    486 
    487    argreg = 0;
    488 
    489    /* If we need the guest state pointer put it in a temporary arg reg */
    490    if (passBBP) {
    491       tmpregs[argreg] = newVRegI(env);
    492       addInstr(env, s390_insn_move(sizeof(ULong), tmpregs[argreg],
    493                                    s390_hreg_guest_state_pointer()));
    494       argreg++;
    495    }
    496 
    497    /* Compute the function arguments into a temporary register each */
    498    for (i = 0; i < n_args; i++) {
    499       tmpregs[argreg] = s390_isel_int_expr(env, args[i]);
    500       argreg++;
    501    }
    502 
    503    /* Compute the condition */
    504    cc = S390_CC_ALWAYS;
    505    if (guard) {
    506       if (guard->tag == Iex_Const
    507           && guard->Iex.Const.con->tag == Ico_U1
    508           && guard->Iex.Const.con->Ico.U1 == True) {
    509          /* unconditional -- do nothing */
    510       } else {
    511          cc = s390_isel_cc(env, guard);
    512       }
    513    }
    514 
    515    /* Move the args to the final register. It is paramount, that the
    516       code to move the registers does not clobber the condition code ! */
    517    for (i = 0; i < argreg; i++) {
    518       HReg finalreg;
    519 
    520       finalreg = make_gpr(s390_gprno_from_arg_index(i));
    521       size = sizeofIRType(Ity_I64);
    522       addInstr(env, s390_insn_move(size, finalreg, tmpregs[i]));
    523    }
    524 
    525    target = Ptr_to_ULong(callee->addr);
    526 
    527    /* Finally, the call itself. */
    528    addInstr(env, s390_insn_helper_call(cc, (Addr64)target, n_args,
    529                                        callee->name, dst));
    530 }
    531 
    532 
    533 /* Given an expression representing a rounding mode using IRRoundingMode
    534    encoding convert it to an s390_round_t value.  */
    535 static s390_round_t
    536 decode_rounding_mode(IRExpr *rounding_expr)
    537 {
    538    if (rounding_expr->tag == Iex_Const &&
    539        rounding_expr->Iex.Const.con->tag == Ico_U32) {
    540       IRRoundingMode mode = rounding_expr->Iex.Const.con->Ico.U32;
    541 
    542       switch (mode) {
    543       case Irrm_NEAREST:       return S390_ROUND_NEAREST_EVEN;
    544       case Irrm_ZERO:          return S390_ROUND_ZERO;
    545       case Irrm_PosINF:        return S390_ROUND_POSINF;
    546       case Irrm_NegINF:        return S390_ROUND_NEGINF;
    547       }
    548    }
    549 
    550    vpanic("decode_rounding_mode");
    551 }
    552 
    553 
    554 /* CC_S390 holds the condition code in s390 encoding. Convert it to
    555    VEX encoding
    556 
    557    s390     VEX              b6 b2 b0   cc.1  cc.0
    558    0      0x40 EQ             1  0  0     0     0
    559    1      0x01 LT             0  0  1     0     1
    560    2      0x00 GT             0  0  0     1     0
    561    3      0x45 Unordered      1  1  1     1     1
    562 
    563    b0 = cc.0
    564    b2 = cc.0 & cc.1
    565    b6 = ~(cc.0 ^ cc.1)   // ((cc.0 - cc.1) + 0x1 ) & 0x1
    566 
    567    VEX = b0 | (b2 << 2) | (b6 << 6);
    568 */
    569 static HReg
    570 convert_s390_fpcc_to_vex(ISelEnv *env, HReg cc_s390)
    571 {
    572    HReg cc0, cc1, b2, b6, cc_vex;
    573 
    574    cc0 = newVRegI(env);
    575    addInstr(env, s390_insn_move(4, cc0, cc_s390));
    576    addInstr(env, s390_insn_alu(4, S390_ALU_AND, cc0, s390_opnd_imm(1)));
    577 
    578    cc1 = newVRegI(env);
    579    addInstr(env, s390_insn_move(4, cc1, cc_s390));
    580    addInstr(env, s390_insn_alu(4, S390_ALU_RSH, cc1, s390_opnd_imm(1)));
    581 
    582    b2 = newVRegI(env);
    583    addInstr(env, s390_insn_move(4, b2, cc0));
    584    addInstr(env, s390_insn_alu(4, S390_ALU_AND, b2, s390_opnd_reg(cc1)));
    585    addInstr(env, s390_insn_alu(4, S390_ALU_LSH, b2, s390_opnd_imm(2)));
    586 
    587    b6 = newVRegI(env);
    588    addInstr(env, s390_insn_move(4, b6, cc0));
    589    addInstr(env, s390_insn_alu(4, S390_ALU_SUB, b6, s390_opnd_reg(cc1)));
    590    addInstr(env, s390_insn_alu(4, S390_ALU_ADD, b6, s390_opnd_imm(1)));
    591    addInstr(env, s390_insn_alu(4, S390_ALU_AND, b6, s390_opnd_imm(1)));
    592    addInstr(env, s390_insn_alu(4, S390_ALU_LSH, b6, s390_opnd_imm(6)));
    593 
    594    cc_vex = newVRegI(env);
    595    addInstr(env, s390_insn_move(4, cc_vex, cc0));
    596    addInstr(env, s390_insn_alu(4, S390_ALU_OR, cc_vex, s390_opnd_reg(b2)));
    597    addInstr(env, s390_insn_alu(4, S390_ALU_OR, cc_vex, s390_opnd_reg(b6)));
    598 
    599    return cc_vex;
    600 }
    601 
    602 
    603 /*---------------------------------------------------------*/
    604 /*--- ISEL: Integer expressions (128 bit)               ---*/
    605 /*---------------------------------------------------------*/
    606 static void
    607 s390_isel_int128_expr_wrk(HReg *dst_hi, HReg *dst_lo, ISelEnv *env,
    608                           IRExpr *expr)
    609 {
    610    IRType ty = typeOfIRExpr(env->type_env, expr);
    611 
    612    vassert(ty == Ity_I128);
    613 
    614    /* No need to consider the following
    615       - 128-bit constants (they do not exist in VEX)
    616       - 128-bit loads from memory (will not be generated)
    617    */
    618 
    619    /* Read 128-bit IRTemp */
    620    if (expr->tag == Iex_RdTmp) {
    621       lookupIRTemp128(dst_hi, dst_lo, env, expr->Iex.RdTmp.tmp);
    622       return;
    623    }
    624 
    625    if (expr->tag == Iex_Binop) {
    626       IRExpr *arg1 = expr->Iex.Binop.arg1;
    627       IRExpr *arg2 = expr->Iex.Binop.arg2;
    628       Bool is_signed_multiply, is_signed_divide;
    629 
    630       switch (expr->Iex.Binop.op) {
    631       case Iop_MullU64:
    632          is_signed_multiply = False;
    633          goto do_multiply64;
    634 
    635       case Iop_MullS64:
    636          is_signed_multiply = True;
    637          goto do_multiply64;
    638 
    639       case Iop_DivModU128to64:
    640          is_signed_divide = False;
    641          goto do_divide64;
    642 
    643       case Iop_DivModS128to64:
    644          is_signed_divide = True;
    645          goto do_divide64;
    646 
    647       case Iop_64HLto128:
    648          *dst_hi = s390_isel_int_expr(env, arg1);
    649          *dst_lo = s390_isel_int_expr(env, arg2);
    650          return;
    651 
    652       case Iop_DivModS64to64: {
    653          HReg r10, r11, h1;
    654          s390_opnd_RMI op2;
    655 
    656          h1  = s390_isel_int_expr(env, arg1);       /* Process 1st operand */
    657          op2 = s390_isel_int_expr_RMI(env, arg2);   /* Process 2nd operand */
    658 
    659          /* We use non-virtual registers r10 and r11 as pair */
    660          r10  = make_gpr(10);
    661          r11  = make_gpr(11);
    662 
    663          /* Move 1st operand into r11 and */
    664          addInstr(env, s390_insn_move(8, r11, h1));
    665 
    666          /* Divide */
    667          addInstr(env, s390_insn_divs(8, r10, r11, op2));
    668 
    669          /* The result is in registers r10 (remainder) and r11 (quotient).
    670             Move the result into the reg pair that is being returned such
    671             such that the low 64 bits are the quotient and the upper 64 bits
    672             are the remainder. (see libvex_ir.h). */
    673          *dst_hi = newVRegI(env);
    674          *dst_lo = newVRegI(env);
    675          addInstr(env, s390_insn_move(8, *dst_hi, r10));
    676          addInstr(env, s390_insn_move(8, *dst_lo, r11));
    677          return;
    678       }
    679 
    680       default:
    681          break;
    682 
    683       do_multiply64: {
    684             HReg r10, r11, h1;
    685             s390_opnd_RMI op2;
    686 
    687             order_commutative_operands(arg1, arg2);
    688 
    689             h1   = s390_isel_int_expr(env, arg1);       /* Process 1st operand */
    690             op2  = s390_isel_int_expr_RMI(env, arg2);   /* Process 2nd operand */
    691 
    692             /* We use non-virtual registers r10 and r11 as pair */
    693             r10  = make_gpr(10);
    694             r11  = make_gpr(11);
    695 
    696             /* Move the first operand to r11 */
    697             addInstr(env, s390_insn_move(8, r11, h1));
    698 
    699             /* Multiply */
    700             addInstr(env, s390_insn_mul(8, r10, r11, op2, is_signed_multiply));
    701 
    702             /* The result is in registers r10 and r11. Assign to two virtual regs
    703                and return. */
    704             *dst_hi = newVRegI(env);
    705             *dst_lo = newVRegI(env);
    706             addInstr(env, s390_insn_move(8, *dst_hi, r10));
    707             addInstr(env, s390_insn_move(8, *dst_lo, r11));
    708             return;
    709          }
    710 
    711       do_divide64: {
    712          HReg r10, r11, hi, lo;
    713          s390_opnd_RMI op2;
    714 
    715          s390_isel_int128_expr(&hi, &lo, env, arg1);
    716          op2  = s390_isel_int_expr_RMI(env, arg2);   /* Process 2nd operand */
    717 
    718          /* We use non-virtual registers r10 and r11 as pair */
    719          r10  = make_gpr(10);
    720          r11  = make_gpr(11);
    721 
    722          /* Move high 64 bits of the 1st operand into r10 and
    723             the low 64 bits into r11. */
    724          addInstr(env, s390_insn_move(8, r10, hi));
    725          addInstr(env, s390_insn_move(8, r11, lo));
    726 
    727          /* Divide */
    728          addInstr(env, s390_insn_div(8, r10, r11, op2, is_signed_divide));
    729 
    730          /* The result is in registers r10 (remainder) and r11 (quotient).
    731             Move the result into the reg pair that is being returned such
    732             such that the low 64 bits are the quotient and the upper 64 bits
    733             are the remainder. (see libvex_ir.h). */
    734          *dst_hi = newVRegI(env);
    735          *dst_lo = newVRegI(env);
    736          addInstr(env, s390_insn_move(8, *dst_hi, r10));
    737          addInstr(env, s390_insn_move(8, *dst_lo, r11));
    738          return;
    739       }
    740       }
    741    }
    742 
    743    vpanic("s390_isel_int128_expr");
    744 }
    745 
    746 
    747 /* Compute a 128-bit value into two 64-bit registers. These may be either
    748    real or virtual regs; in any case they must not be changed by subsequent
    749    code emitted by the caller. */
    750 static void
    751 s390_isel_int128_expr(HReg *dst_hi, HReg *dst_lo, ISelEnv *env, IRExpr *expr)
    752 {
    753    s390_isel_int128_expr_wrk(dst_hi, dst_lo, env, expr);
    754 
    755    /* Sanity checks ... */
    756    vassert(hregIsVirtual(*dst_hi));
    757    vassert(hregIsVirtual(*dst_lo));
    758    vassert(hregClass(*dst_hi) == HRcInt64);
    759    vassert(hregClass(*dst_lo) == HRcInt64);
    760 }
    761 
    762 
    763 /*---------------------------------------------------------*/
    764 /*--- ISEL: Integer expressions (64/32/16/8 bit)        ---*/
    765 /*---------------------------------------------------------*/
    766 
    767 /* Select insns for an integer-typed expression, and add them to the
    768    code list.  Return a reg holding the result.  This reg will be a
    769    virtual register.  THE RETURNED REG MUST NOT BE MODIFIED.  If you
    770    want to modify it, ask for a new vreg, copy it in there, and modify
    771    the copy.  The register allocator will do its best to map both
    772    vregs to the same real register, so the copies will often disappear
    773    later in the game.
    774 
    775    This should handle expressions of 64, 32, 16 and 8-bit type.
    776    All results are returned in a 64bit register.
    777    For 16- and 8-bit expressions, the upper (32/48/56 : 16/24) bits
    778    are arbitrary, so you should mask or sign extend partial values
    779    if necessary.
    780 */
    781 
    782 /* DO NOT CALL THIS DIRECTLY ! */
    783 static HReg
    784 s390_isel_int_expr_wrk(ISelEnv *env, IRExpr *expr)
    785 {
    786    IRType ty = typeOfIRExpr(env->type_env, expr);
    787    UChar size;
    788    s390_bfp_unop_t bfpop;
    789 
    790    vassert(ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32 || ty == Ity_I64);
    791 
    792    size = sizeofIRType(ty);   /* size of the result after evaluating EXPR */
    793 
    794    switch (expr->tag) {
    795 
    796       /* --------- TEMP --------- */
    797    case Iex_RdTmp:
    798       /* Return the virtual register that holds the temporary. */
    799       return lookupIRTemp(env, expr->Iex.RdTmp.tmp);
    800 
    801       /* --------- LOAD --------- */
    802    case Iex_Load: {
    803       HReg        dst = newVRegI(env);
    804       s390_amode *am  = s390_isel_amode(env, expr->Iex.Load.addr);
    805 
    806       if (expr->Iex.Load.end != Iend_BE)
    807          goto irreducible;
    808 
    809       addInstr(env, s390_insn_load(size, dst, am));
    810 
    811       return dst;
    812    }
    813 
    814       /* --------- BINARY OP --------- */
    815    case Iex_Binop: {
    816       IRExpr *arg1 = expr->Iex.Binop.arg1;
    817       IRExpr *arg2 = expr->Iex.Binop.arg2;
    818       HReg h1, res;
    819       s390_alu_t opkind;
    820       s390_opnd_RMI op2, value, opnd;
    821       s390_insn *insn;
    822       Bool is_commutative, is_signed_multiply, is_signed_divide;
    823 
    824       is_commutative = True;
    825 
    826       switch (expr->Iex.Binop.op) {
    827       case Iop_MullU8:
    828       case Iop_MullU16:
    829       case Iop_MullU32:
    830          is_signed_multiply = False;
    831          goto do_multiply;
    832 
    833       case Iop_MullS8:
    834       case Iop_MullS16:
    835       case Iop_MullS32:
    836          is_signed_multiply = True;
    837          goto do_multiply;
    838 
    839       do_multiply: {
    840             HReg r10, r11;
    841             UInt arg_size = size / 2;
    842 
    843             order_commutative_operands(arg1, arg2);
    844 
    845             h1   = s390_isel_int_expr(env, arg1);       /* Process 1st operand */
    846             op2  = s390_isel_int_expr_RMI(env, arg2);   /* Process 2nd operand */
    847 
    848             /* We use non-virtual registers r10 and r11 as pair */
    849             r10  = make_gpr(10);
    850             r11  = make_gpr(11);
    851 
    852             /* Move the first operand to r11 */
    853             addInstr(env, s390_insn_move(arg_size, r11, h1));
    854 
    855             /* Multiply */
    856             addInstr(env, s390_insn_mul(arg_size, r10, r11, op2, is_signed_multiply));
    857 
    858             /* The result is in registers r10 and r11. Combine them into a SIZE-bit
    859                value into the destination register. */
    860             res  = newVRegI(env);
    861             addInstr(env, s390_insn_move(arg_size, res, r10));
    862             value = s390_opnd_imm(arg_size * 8);
    863             addInstr(env, s390_insn_alu(size, S390_ALU_LSH, res, value));
    864             value = s390_opnd_imm((((ULong)1) << arg_size * 8) - 1);
    865             addInstr(env, s390_insn_alu(size, S390_ALU_AND, r11, value));
    866             opnd = s390_opnd_reg(r11);
    867             addInstr(env, s390_insn_alu(size, S390_ALU_OR,  res, opnd));
    868             return res;
    869          }
    870 
    871       case Iop_DivModS64to32:
    872          is_signed_divide = True;
    873          goto do_divide;
    874 
    875       case Iop_DivModU64to32:
    876          is_signed_divide = False;
    877          goto do_divide;
    878 
    879       do_divide: {
    880             HReg r10, r11;
    881 
    882             h1   = s390_isel_int_expr(env, arg1);       /* Process 1st operand */
    883             op2  = s390_isel_int_expr_RMI(env, arg2);   /* Process 2nd operand */
    884 
    885             /* We use non-virtual registers r10 and r11 as pair */
    886             r10  = make_gpr(10);
    887             r11  = make_gpr(11);
    888 
    889             /* Split the first operand and put the high 32 bits into r10 and
    890                the low 32 bits into r11. */
    891             addInstr(env, s390_insn_move(8, r10, h1));
    892             addInstr(env, s390_insn_move(8, r11, h1));
    893             value = s390_opnd_imm(32);
    894             addInstr(env, s390_insn_alu(8, S390_ALU_RSH, r10, value));
    895 
    896             /* Divide */
    897             addInstr(env, s390_insn_div(4, r10, r11, op2, is_signed_divide));
    898 
    899             /* The result is in registers r10 (remainder) and r11 (quotient).
    900                Combine them into a 64-bit value such that the low 32 bits are
    901                the quotient and the upper 32 bits are the remainder. (see
    902                libvex_ir.h). */
    903             res  = newVRegI(env);
    904             addInstr(env, s390_insn_move(8, res, r10));
    905             value = s390_opnd_imm(32);
    906             addInstr(env, s390_insn_alu(8, S390_ALU_LSH, res, value));
    907             value = s390_opnd_imm((((ULong)1) << 32) - 1);
    908             addInstr(env, s390_insn_alu(8, S390_ALU_AND, r11, value));
    909             opnd = s390_opnd_reg(r11);
    910             addInstr(env, s390_insn_alu(8, S390_ALU_OR,  res, opnd));
    911             return res;
    912          }
    913 
    914       case Iop_F32toI32S:  bfpop = S390_BFP_F32_TO_I32;  goto do_convert;
    915       case Iop_F32toI64S:  bfpop = S390_BFP_F32_TO_I64;  goto do_convert;
    916       case Iop_F64toI32S:  bfpop = S390_BFP_F64_TO_I32;  goto do_convert;
    917       case Iop_F64toI64S:  bfpop = S390_BFP_F64_TO_I64;  goto do_convert;
    918       case Iop_F128toI32S: bfpop = S390_BFP_F128_TO_I32; goto do_convert_128;
    919       case Iop_F128toI64S: bfpop = S390_BFP_F128_TO_I64; goto do_convert_128;
    920 
    921       do_convert: {
    922          s390_round_t rounding_mode;
    923 
    924          res  = newVRegI(env);
    925          h1   = s390_isel_float_expr(env, arg2);   /* Process operand */
    926 
    927          rounding_mode = decode_rounding_mode(arg1);
    928          addInstr(env, s390_insn_bfp_unop(size, bfpop, res, h1, rounding_mode));
    929          return res;
    930       }
    931 
    932       do_convert_128: {
    933          s390_round_t rounding_mode;
    934          HReg op_hi, op_lo, f13, f15;
    935 
    936          res = newVRegI(env);
    937          s390_isel_float128_expr(&op_hi, &op_lo, env, arg2); /* operand */
    938 
    939          /* We use non-virtual registers r13 and r15 as pair */
    940          f13 = make_fpr(13);
    941          f15 = make_fpr(15);
    942 
    943          /* operand --> (f13, f15) */
    944          addInstr(env, s390_insn_move(8, f13, op_hi));
    945          addInstr(env, s390_insn_move(8, f15, op_lo));
    946 
    947          rounding_mode = decode_rounding_mode(arg1);
    948          addInstr(env, s390_insn_bfp128_convert_from(size, bfpop, res, f13, f15,
    949                                                      rounding_mode));
    950          return res;
    951       }
    952 
    953       case Iop_8HLto16:
    954       case Iop_16HLto32:
    955       case Iop_32HLto64: {
    956          HReg h2;
    957          UInt arg_size = size / 2;
    958 
    959          res  = newVRegI(env);
    960          h1   = s390_isel_int_expr(env, arg1);   /* Process 1st operand */
    961          h2   = s390_isel_int_expr(env, arg2);   /* Process 2nd operand */
    962 
    963          addInstr(env, s390_insn_move(arg_size, res, h1));
    964          value = s390_opnd_imm(arg_size * 8);
    965          addInstr(env, s390_insn_alu(size, S390_ALU_LSH, res, value));
    966          value = s390_opnd_imm((((ULong)1) << arg_size * 8) - 1);
    967          addInstr(env, s390_insn_alu(size, S390_ALU_AND, h2, value));
    968          opnd = s390_opnd_reg(h2);
    969          addInstr(env, s390_insn_alu(size, S390_ALU_OR,  res, opnd));
    970          return res;
    971       }
    972 
    973       case Iop_Max32U: {
    974          /* arg1 > arg2 ? arg1 : arg2   using uint32_t arguments */
    975          res = newVRegI(env);
    976          h1  = s390_isel_int_expr(env, arg1);
    977          op2 = s390_isel_int_expr_RMI(env, arg2);
    978 
    979          addInstr(env, s390_insn_move(size, res, h1));
    980          addInstr(env, s390_insn_compare(size, res, op2, False /* signed */));
    981          addInstr(env, s390_insn_cond_move(size, S390_CC_L, res, op2));
    982          return res;
    983       }
    984 
    985       case Iop_CmpF32:
    986       case Iop_CmpF64: {
    987          HReg cc_s390, h2;
    988 
    989          h1 = s390_isel_float_expr(env, arg1);
    990          h2 = s390_isel_float_expr(env, arg2);
    991          cc_s390 = newVRegI(env);
    992 
    993          size = (expr->Iex.Binop.op == Iop_CmpF32) ? 4 : 8;
    994 
    995          addInstr(env, s390_insn_bfp_compare(size, cc_s390, h1, h2));
    996 
    997          return convert_s390_fpcc_to_vex(env, cc_s390);
    998       }
    999 
   1000       case Iop_CmpF128: {
   1001          HReg op1_hi, op1_lo, op2_hi, op2_lo, f12, f13, f14, f15, cc_s390;
   1002 
   1003          s390_isel_float128_expr(&op1_hi, &op1_lo, env, arg1); /* 1st operand */
   1004          s390_isel_float128_expr(&op2_hi, &op2_lo, env, arg2); /* 2nd operand */
   1005          cc_s390 = newVRegI(env);
   1006 
   1007          /* We use non-virtual registers as pairs (f13, f15) and (f12, f14)) */
   1008          f12 = make_fpr(12);
   1009          f13 = make_fpr(13);
   1010          f14 = make_fpr(14);
   1011          f15 = make_fpr(15);
   1012 
   1013          /* 1st operand --> (f12, f14) */
   1014          addInstr(env, s390_insn_move(8, f12, op1_hi));
   1015          addInstr(env, s390_insn_move(8, f14, op1_lo));
   1016 
   1017          /* 2nd operand --> (f13, f15) */
   1018          addInstr(env, s390_insn_move(8, f13, op2_hi));
   1019          addInstr(env, s390_insn_move(8, f15, op2_lo));
   1020 
   1021          res = newVRegI(env);
   1022          addInstr(env, s390_insn_bfp128_compare(16, cc_s390, f12, f14, f13, f15));
   1023 
   1024          return convert_s390_fpcc_to_vex(env, cc_s390);
   1025       }
   1026 
   1027       case Iop_Add8:
   1028       case Iop_Add16:
   1029       case Iop_Add32:
   1030       case Iop_Add64:
   1031          opkind = S390_ALU_ADD;
   1032          break;
   1033 
   1034       case Iop_Sub8:
   1035       case Iop_Sub16:
   1036       case Iop_Sub32:
   1037       case Iop_Sub64:
   1038          opkind = S390_ALU_SUB;
   1039          is_commutative = False;
   1040          break;
   1041 
   1042       case Iop_And8:
   1043       case Iop_And16:
   1044       case Iop_And32:
   1045       case Iop_And64:
   1046          opkind = S390_ALU_AND;
   1047          break;
   1048 
   1049       case Iop_Or8:
   1050       case Iop_Or16:
   1051       case Iop_Or32:
   1052       case Iop_Or64:
   1053          opkind = S390_ALU_OR;
   1054          break;
   1055 
   1056       case Iop_Xor8:
   1057       case Iop_Xor16:
   1058       case Iop_Xor32:
   1059       case Iop_Xor64:
   1060          opkind = S390_ALU_XOR;
   1061          break;
   1062 
   1063       case Iop_Shl8:
   1064       case Iop_Shl16:
   1065       case Iop_Shl32:
   1066       case Iop_Shl64:
   1067          opkind = S390_ALU_LSH;
   1068          is_commutative = False;
   1069          break;
   1070 
   1071       case Iop_Shr8:
   1072       case Iop_Shr16:
   1073       case Iop_Shr32:
   1074       case Iop_Shr64:
   1075          opkind = S390_ALU_RSH;
   1076          is_commutative = False;
   1077          break;
   1078 
   1079       case Iop_Sar8:
   1080       case Iop_Sar16:
   1081       case Iop_Sar32:
   1082       case Iop_Sar64:
   1083          opkind = S390_ALU_RSHA;
   1084          is_commutative = False;
   1085          break;
   1086 
   1087       default:
   1088          goto irreducible;
   1089       }
   1090 
   1091       /* Pattern match: 0 - arg1  -->  -arg1   */
   1092       if (opkind == S390_ALU_SUB && s390_expr_is_const_zero(arg1)) {
   1093          res  = newVRegI(env);
   1094          op2  = s390_isel_int_expr_RMI(env, arg2);   /* Process 2nd operand */
   1095          insn = s390_insn_unop(size, S390_NEGATE, res, op2);
   1096          addInstr(env, insn);
   1097 
   1098          return res;
   1099       }
   1100 
   1101       if (is_commutative) {
   1102          order_commutative_operands(arg1, arg2);
   1103       }
   1104 
   1105       h1   = s390_isel_int_expr(env, arg1);       /* Process 1st operand */
   1106       op2  = s390_isel_int_expr_RMI(env, arg2);   /* Process 2nd operand */
   1107       res  = newVRegI(env);
   1108       addInstr(env, s390_insn_move(size, res, h1));
   1109       insn = s390_insn_alu(size, opkind, res, op2);
   1110 
   1111       addInstr(env, insn);
   1112 
   1113       return res;
   1114    }
   1115 
   1116       /* --------- UNARY OP --------- */
   1117    case Iex_Unop: {
   1118       static s390_opnd_RMI mask  = { S390_OPND_IMMEDIATE };
   1119       static s390_opnd_RMI shift = { S390_OPND_IMMEDIATE };
   1120       s390_opnd_RMI opnd;
   1121       s390_insn    *insn;
   1122       IRExpr *arg;
   1123       HReg    dst, h1;
   1124       IROp    unop, binop;
   1125 
   1126       arg = expr->Iex.Unop.arg;
   1127 
   1128       /* Special cases are handled here */
   1129 
   1130       /* 32-bit multiply with 32-bit result or
   1131          64-bit multiply with 64-bit result */
   1132       unop  = expr->Iex.Unop.op;
   1133       binop = arg->Iex.Binop.op;
   1134 
   1135       if ((arg->tag == Iex_Binop &&
   1136            ((unop == Iop_64to32 &&
   1137              (binop == Iop_MullS32 || binop == Iop_MullU32)) ||
   1138             (unop == Iop_128to64 &&
   1139              (binop == Iop_MullS64 || binop == Iop_MullU64))))) {
   1140          h1   = s390_isel_int_expr(env, arg->Iex.Binop.arg1);     /* 1st opnd */
   1141          opnd = s390_isel_int_expr_RMI(env, arg->Iex.Binop.arg2); /* 2nd opnd */
   1142          dst  = newVRegI(env);     /* Result goes into a new register */
   1143          addInstr(env, s390_insn_move(size, dst, h1));
   1144          addInstr(env, s390_insn_alu(size, S390_ALU_MUL, dst, opnd));
   1145 
   1146          return dst;
   1147       }
   1148 
   1149       if (unop == Iop_ReinterpF64asI64 || unop == Iop_ReinterpF32asI32) {
   1150          dst = newVRegI(env);
   1151          h1  = s390_isel_float_expr(env, arg);     /* Process the operand */
   1152          addInstr(env, s390_insn_move(size, dst, h1));
   1153 
   1154          return dst;
   1155       }
   1156 
   1157       /* Expressions whose argument is 1-bit wide */
   1158       if (typeOfIRExpr(env->type_env, arg) == Ity_I1) {
   1159          s390_cc_t cond = s390_isel_cc(env, arg);
   1160          dst = newVRegI(env);     /* Result goes into a new register */
   1161          addInstr(env, s390_insn_cc2bool(dst, cond));
   1162 
   1163          switch (unop) {
   1164          case Iop_1Uto8:
   1165          case Iop_1Uto32:
   1166             /* Zero extend */
   1167             mask.variant.imm = 1;
   1168             addInstr(env, s390_insn_alu(4, S390_ALU_AND,  dst, mask));
   1169             break;
   1170 
   1171          case Iop_1Uto64:
   1172             /* Zero extend */
   1173             mask.variant.imm = 1;
   1174             addInstr(env, s390_insn_alu(8, S390_ALU_AND,  dst, mask));
   1175             break;
   1176 
   1177          case Iop_1Sto8:
   1178          case Iop_1Sto16:
   1179          case Iop_1Sto32:
   1180             shift.variant.imm = 31;
   1181             addInstr(env, s390_insn_alu(4, S390_ALU_LSH,  dst, shift));
   1182             addInstr(env, s390_insn_alu(4, S390_ALU_RSHA, dst, shift));
   1183             break;
   1184 
   1185          case Iop_1Sto64:
   1186             shift.variant.imm = 63;
   1187             addInstr(env, s390_insn_alu(8, S390_ALU_LSH,  dst, shift));
   1188             addInstr(env, s390_insn_alu(8, S390_ALU_RSHA, dst, shift));
   1189             break;
   1190 
   1191          default:
   1192             goto irreducible;
   1193          }
   1194 
   1195          return dst;
   1196       }
   1197 
   1198       /* Regular processing */
   1199 
   1200       if (unop == Iop_128to64) {
   1201          HReg dst_hi, dst_lo;
   1202 
   1203          s390_isel_int128_expr(&dst_hi, &dst_lo, env, arg);
   1204          return dst_lo;
   1205       }
   1206 
   1207       if (unop == Iop_128HIto64) {
   1208          HReg dst_hi, dst_lo;
   1209 
   1210          s390_isel_int128_expr(&dst_hi, &dst_lo, env, arg);
   1211          return dst_hi;
   1212       }
   1213 
   1214       dst  = newVRegI(env);     /* Result goes into a new register */
   1215       opnd = s390_isel_int_expr_RMI(env, arg);     /* Process the operand */
   1216 
   1217       switch (unop) {
   1218       case Iop_8Uto16:
   1219       case Iop_8Uto32:
   1220       case Iop_8Uto64:
   1221          insn = s390_insn_unop(size, S390_ZERO_EXTEND_8, dst, opnd);
   1222          break;
   1223 
   1224       case Iop_16Uto32:
   1225       case Iop_16Uto64:
   1226          insn = s390_insn_unop(size, S390_ZERO_EXTEND_16, dst, opnd);
   1227          break;
   1228 
   1229       case Iop_32Uto64:
   1230          insn = s390_insn_unop(size, S390_ZERO_EXTEND_32, dst, opnd);
   1231          break;
   1232 
   1233       case Iop_8Sto16:
   1234       case Iop_8Sto32:
   1235       case Iop_8Sto64:
   1236          insn = s390_insn_unop(size, S390_SIGN_EXTEND_8, dst, opnd);
   1237          break;
   1238 
   1239       case Iop_16Sto32:
   1240       case Iop_16Sto64:
   1241          insn = s390_insn_unop(size, S390_SIGN_EXTEND_16, dst, opnd);
   1242          break;
   1243 
   1244       case Iop_32Sto64:
   1245          insn = s390_insn_unop(size, S390_SIGN_EXTEND_32, dst, opnd);
   1246          break;
   1247 
   1248       case Iop_64to8:
   1249       case Iop_64to16:
   1250       case Iop_64to32:
   1251       case Iop_32to8:
   1252       case Iop_32to16:
   1253       case Iop_16to8:
   1254          /* Down-casts are no-ops. Upstream operations will only look at
   1255             the bytes that make up the result of the down-cast. So there
   1256             is no point setting the other bytes to 0. */
   1257          insn = s390_opnd_copy(8, dst, opnd);
   1258          break;
   1259 
   1260       case Iop_64HIto32:
   1261          addInstr(env, s390_opnd_copy(8, dst, opnd));
   1262          shift.variant.imm = 32;
   1263          insn = s390_insn_alu(8, S390_ALU_RSH, dst, shift);
   1264          break;
   1265 
   1266       case Iop_32HIto16:
   1267          addInstr(env, s390_opnd_copy(4, dst, opnd));
   1268          shift.variant.imm = 16;
   1269          insn = s390_insn_alu(4, S390_ALU_RSH, dst, shift);
   1270          break;
   1271 
   1272       case Iop_16HIto8:
   1273          addInstr(env, s390_opnd_copy(2, dst, opnd));
   1274          shift.variant.imm = 8;
   1275          insn = s390_insn_alu(2, S390_ALU_RSH, dst, shift);
   1276          break;
   1277 
   1278       case Iop_Not8:
   1279       case Iop_Not16:
   1280       case Iop_Not32:
   1281       case Iop_Not64:
   1282          /* XOR with ffff... */
   1283          mask.variant.imm = ~(ULong)0;
   1284          addInstr(env, s390_opnd_copy(size, dst, opnd));
   1285          insn = s390_insn_alu(size, S390_ALU_XOR, dst, mask);
   1286          break;
   1287 
   1288       case Iop_Left8:
   1289       case Iop_Left16:
   1290       case Iop_Left32:
   1291       case Iop_Left64:
   1292          addInstr(env, s390_insn_unop(size, S390_NEGATE, dst, opnd));
   1293          insn = s390_insn_alu(size, S390_ALU_OR, dst, opnd);
   1294          break;
   1295 
   1296       case Iop_CmpwNEZ32:
   1297       case Iop_CmpwNEZ64: {
   1298          /* Use the fact that x | -x == 0 iff x == 0. Otherwise, either X
   1299             or -X will have a 1 in the MSB. */
   1300          addInstr(env, s390_insn_unop(size, S390_NEGATE, dst, opnd));
   1301          addInstr(env, s390_insn_alu(size, S390_ALU_OR,  dst, opnd));
   1302          shift.variant.imm = (unop == Iop_CmpwNEZ32) ? 31 : 63;
   1303          addInstr(env, s390_insn_alu(size, S390_ALU_RSHA,  dst, shift));
   1304          return dst;
   1305       }
   1306 
   1307       case Iop_Clz64: {
   1308          HReg r10, r11;
   1309 
   1310          /* This will be implemented using FLOGR, if possible. So we need to
   1311             set aside a pair of non-virtual registers. The result (number of
   1312             left-most zero bits) will be in r10. The value in r11 is unspecified
   1313             and must not be used. */
   1314          r10  = make_gpr(10);
   1315          r11  = make_gpr(11);
   1316 
   1317          addInstr(env, s390_insn_clz(8, r10, r11, opnd));
   1318          addInstr(env, s390_insn_move(8, dst, r10));
   1319          return dst;
   1320       }
   1321 
   1322       default:
   1323          goto irreducible;
   1324       }
   1325 
   1326       addInstr(env, insn);
   1327 
   1328       return dst;
   1329    }
   1330 
   1331       /* --------- GET --------- */
   1332    case Iex_Get: {
   1333       HReg dst = newVRegI(env);
   1334       s390_amode *am = s390_amode_for_guest_state(expr->Iex.Get.offset);
   1335 
   1336       /* We never load more than 8 bytes from the guest state, because the
   1337          floating point register pair is not contiguous. */
   1338       vassert(size <= 8);
   1339 
   1340       addInstr(env, s390_insn_load(size, dst, am));
   1341 
   1342       return dst;
   1343    }
   1344 
   1345    case Iex_GetI:
   1346       /* not needed */
   1347       break;
   1348 
   1349       /* --------- CCALL --------- */
   1350    case Iex_CCall: {
   1351       HReg dst = newVRegI(env);
   1352 
   1353       doHelperCall(env, False, NULL, expr->Iex.CCall.cee,
   1354                    expr->Iex.CCall.args, dst);
   1355       return dst;
   1356    }
   1357 
   1358       /* --------- LITERAL --------- */
   1359 
   1360       /* Load a literal into a register. Create a "load immediate"
   1361          v-insn and return the register. */
   1362    case Iex_Const: {
   1363       ULong value;
   1364       HReg  dst = newVRegI(env);
   1365       const IRConst *con = expr->Iex.Const.con;
   1366 
   1367       /* Bitwise copy of the value. No sign/zero-extension */
   1368       switch (con->tag) {
   1369       case Ico_U64: value = con->Ico.U64; break;
   1370       case Ico_U32: value = con->Ico.U32; break;
   1371       case Ico_U16: value = con->Ico.U16; break;
   1372       case Ico_U8:  value = con->Ico.U8;  break;
   1373       default:      vpanic("s390_isel_int_expr: invalid constant");
   1374       }
   1375 
   1376       addInstr(env, s390_insn_load_immediate(size, dst, value));
   1377 
   1378       return dst;
   1379    }
   1380 
   1381       /* --------- MULTIPLEX --------- */
   1382    case Iex_Mux0X: {
   1383       IRExpr *cond_expr;
   1384       HReg dst, tmp, rX;
   1385       s390_opnd_RMI cond, r0, zero;
   1386 
   1387       cond_expr = expr->Iex.Mux0X.cond;
   1388 
   1389       dst  = newVRegI(env);
   1390       r0   = s390_isel_int_expr_RMI(env, expr->Iex.Mux0X.expr0);
   1391       rX   = s390_isel_int_expr(env, expr->Iex.Mux0X.exprX);
   1392       size = sizeofIRType(typeOfIRExpr(env->type_env, expr->Iex.Mux0X.exprX));
   1393 
   1394       if (cond_expr->tag == Iex_Unop && cond_expr->Iex.Unop.op == Iop_1Uto8) {
   1395          s390_cc_t cc = s390_isel_cc(env, cond_expr->Iex.Unop.arg);
   1396 
   1397          addInstr(env, s390_insn_move(size, dst, rX));
   1398          addInstr(env, s390_insn_cond_move(size, s390_cc_invert(cc), dst, r0));
   1399          return dst;
   1400       }
   1401 
   1402       /* Assume the condition is true and move rX to the destination reg. */
   1403       addInstr(env, s390_insn_move(size, dst, rX));
   1404 
   1405       /* Compute the condition ... */
   1406       cond = s390_isel_int_expr_RMI(env, cond_expr);
   1407 
   1408       /* tmp = cond & 0xFF */
   1409       tmp  = newVRegI(env);
   1410       addInstr(env, s390_insn_load_immediate(4, tmp, 0xFF));
   1411       addInstr(env, s390_insn_alu(4, S390_ALU_AND, tmp, cond));
   1412 
   1413       /* ... and compare it with zero */
   1414       zero = s390_opnd_imm(0);
   1415       addInstr(env, s390_insn_compare(4, tmp, zero, 0 /* signed */));
   1416 
   1417       /* ... and if it compared equal move r0 to the destination reg. */
   1418       size = sizeofIRType(typeOfIRExpr(env->type_env, expr->Iex.Mux0X.expr0));
   1419       addInstr(env, s390_insn_cond_move(size, S390_CC_E, dst, r0));
   1420 
   1421       return dst;
   1422    }
   1423 
   1424    default:
   1425       break;
   1426    }
   1427 
   1428    /* We get here if no pattern matched. */
   1429  irreducible:
   1430    ppIRExpr(expr);
   1431    vpanic("s390_isel_int_expr: cannot reduce tree");
   1432 }
   1433 
   1434 
   1435 static HReg
   1436 s390_isel_int_expr(ISelEnv *env, IRExpr *expr)
   1437 {
   1438    HReg dst = s390_isel_int_expr_wrk(env, expr);
   1439 
   1440    /* Sanity checks ... */
   1441    vassert(hregClass(dst) == HRcInt64);
   1442    vassert(hregIsVirtual(dst));
   1443 
   1444    return dst;
   1445 }
   1446 
   1447 
   1448 static s390_opnd_RMI
   1449 s390_isel_int_expr_RMI(ISelEnv *env, IRExpr *expr)
   1450 {
   1451    IRType ty = typeOfIRExpr(env->type_env, expr);
   1452    s390_opnd_RMI dst;
   1453 
   1454    vassert(ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32 ||
   1455            ty == Ity_I64);
   1456 
   1457    if (expr->tag == Iex_Load) {
   1458       dst.tag = S390_OPND_AMODE;
   1459       dst.variant.am = s390_isel_amode(env, expr->Iex.Load.addr);
   1460    } else if (expr->tag == Iex_Get) {
   1461       dst.tag = S390_OPND_AMODE;
   1462       dst.variant.am = s390_amode_for_guest_state(expr->Iex.Get.offset);
   1463    } else if (expr->tag == Iex_Const) {
   1464       ULong value;
   1465 
   1466       /* The bit pattern for the value will be stored as is in the least
   1467          significant bits of VALUE. */
   1468       switch (expr->Iex.Const.con->tag) {
   1469       case Ico_U1:  value = expr->Iex.Const.con->Ico.U1;  break;
   1470       case Ico_U8:  value = expr->Iex.Const.con->Ico.U8;  break;
   1471       case Ico_U16: value = expr->Iex.Const.con->Ico.U16; break;
   1472       case Ico_U32: value = expr->Iex.Const.con->Ico.U32; break;
   1473       case Ico_U64: value = expr->Iex.Const.con->Ico.U64; break;
   1474       default:
   1475          vpanic("s390_isel_int_expr_RMI");
   1476       }
   1477 
   1478       dst.tag = S390_OPND_IMMEDIATE;
   1479       dst.variant.imm = value;
   1480    } else {
   1481       dst.tag = S390_OPND_REG;
   1482       dst.variant.reg = s390_isel_int_expr(env, expr);
   1483    }
   1484 
   1485    return dst;
   1486 }
   1487 
   1488 
   1489 /*---------------------------------------------------------*/
   1490 /*--- ISEL: Floating point expressions (128 bit)        ---*/
   1491 /*---------------------------------------------------------*/
   1492 static void
   1493 s390_isel_float128_expr_wrk(HReg *dst_hi, HReg *dst_lo, ISelEnv *env,
   1494                             IRExpr *expr)
   1495 {
   1496    IRType ty = typeOfIRExpr(env->type_env, expr);
   1497 
   1498    vassert(ty == Ity_F128);
   1499 
   1500    /* Read 128-bit IRTemp */
   1501    if (expr->tag == Iex_RdTmp) {
   1502       lookupIRTemp128(dst_hi, dst_lo, env, expr->Iex.RdTmp.tmp);
   1503       return;
   1504    }
   1505 
   1506    switch (expr->tag) {
   1507    case Iex_RdTmp:
   1508       /* Return the virtual registers that hold the temporary. */
   1509       lookupIRTemp128(dst_hi, dst_lo, env, expr->Iex.RdTmp.tmp);
   1510       return;
   1511 
   1512       /* --------- LOAD --------- */
   1513    case Iex_Load: {
   1514       IRExpr *addr_hi, *addr_lo;
   1515       s390_amode *am_hi, *am_lo;
   1516 
   1517       if (expr->Iex.Load.end != Iend_BE)
   1518          goto irreducible;
   1519 
   1520       addr_hi = expr->Iex.Load.addr;
   1521       addr_lo = IRExpr_Binop(Iop_Add64, addr_hi, mkU64(8));
   1522 
   1523       am_hi  = s390_isel_amode(env, addr_hi);
   1524       am_lo  = s390_isel_amode(env, addr_lo);
   1525 
   1526       *dst_hi = newVRegF(env);
   1527       *dst_lo = newVRegF(env);
   1528       addInstr(env, s390_insn_load(8, *dst_hi, am_hi));
   1529       addInstr(env, s390_insn_load(8, *dst_hi, am_lo));
   1530       return;
   1531    }
   1532 
   1533 
   1534       /* --------- GET --------- */
   1535    case Iex_Get:
   1536       /* This is not supported because loading 128-bit from the guest
   1537          state is almost certainly wrong. Use get_fpr_pair instead. */
   1538       vpanic("Iex_Get with F128 data");
   1539 
   1540       /* --------- 4-ary OP --------- */
   1541    case Iex_Qop:
   1542       vpanic("Iex_Qop with F128 data");
   1543 
   1544       /* --------- TERNARY OP --------- */
   1545    case Iex_Triop: {
   1546       IRTriop *triop = expr->Iex.Triop.details;
   1547       IROp    op     = triop->op;
   1548       IRExpr *left   = triop->arg2;
   1549       IRExpr *right  = triop->arg3;
   1550       s390_bfp_binop_t bfpop;
   1551       s390_round_t rounding_mode;
   1552       HReg op1_hi, op1_lo, op2_hi, op2_lo, f12, f13, f14, f15;
   1553 
   1554       s390_isel_float128_expr(&op1_hi, &op1_lo, env, left);  /* 1st operand */
   1555       s390_isel_float128_expr(&op2_hi, &op2_lo, env, right); /* 2nd operand */
   1556 
   1557       /* We use non-virtual registers as pairs (f13, f15) and (f12, f14)) */
   1558       f12 = make_fpr(12);
   1559       f13 = make_fpr(13);
   1560       f14 = make_fpr(14);
   1561       f15 = make_fpr(15);
   1562 
   1563       /* 1st operand --> (f12, f14) */
   1564       addInstr(env, s390_insn_move(8, f12, op1_hi));
   1565       addInstr(env, s390_insn_move(8, f14, op1_lo));
   1566 
   1567       /* 2nd operand --> (f13, f15) */
   1568       addInstr(env, s390_insn_move(8, f13, op2_hi));
   1569       addInstr(env, s390_insn_move(8, f15, op2_lo));
   1570 
   1571       switch (op) {
   1572       case Iop_AddF128: bfpop = S390_BFP_ADD; break;
   1573       case Iop_SubF128: bfpop = S390_BFP_SUB; break;
   1574       case Iop_MulF128: bfpop = S390_BFP_MUL; break;
   1575       case Iop_DivF128: bfpop = S390_BFP_DIV; break;
   1576       default:
   1577          goto irreducible;
   1578       }
   1579 
   1580       rounding_mode = decode_rounding_mode(triop->arg1);
   1581       addInstr(env, s390_insn_bfp128_binop(16, bfpop, f12, f14, f13,
   1582                                            f15, rounding_mode));
   1583 
   1584       /* Move result to virtual destination register */
   1585       *dst_hi = newVRegF(env);
   1586       *dst_lo = newVRegF(env);
   1587       addInstr(env, s390_insn_move(8, *dst_hi, f12));
   1588       addInstr(env, s390_insn_move(8, *dst_lo, f14));
   1589 
   1590       return;
   1591    }
   1592 
   1593       /* --------- BINARY OP --------- */
   1594    case Iex_Binop: {
   1595       HReg op_hi, op_lo, f12, f13, f14, f15;
   1596       s390_bfp_unop_t bfpop;
   1597       s390_round_t rounding_mode;
   1598 
   1599       /* We use non-virtual registers as pairs (f13, f15) and (f12, f14)) */
   1600       f12 = make_fpr(12);
   1601       f13 = make_fpr(13);
   1602       f14 = make_fpr(14);
   1603       f15 = make_fpr(15);
   1604 
   1605       switch (expr->Iex.Binop.op) {
   1606       case Iop_SqrtF128:
   1607          s390_isel_float128_expr(&op_hi, &op_lo, env, expr->Iex.Binop.arg2);
   1608 
   1609          /* operand --> (f13, f15) */
   1610          addInstr(env, s390_insn_move(8, f13, op_hi));
   1611          addInstr(env, s390_insn_move(8, f15, op_lo));
   1612 
   1613          bfpop = S390_BFP_SQRT;
   1614          rounding_mode = decode_rounding_mode(expr->Iex.Binop.arg1);
   1615 
   1616          addInstr(env, s390_insn_bfp128_unop(16, bfpop, f12, f14, f13, f15,
   1617                                              rounding_mode));
   1618 
   1619          /* Move result to virtual destination registers */
   1620          *dst_hi = newVRegF(env);
   1621          *dst_lo = newVRegF(env);
   1622          addInstr(env, s390_insn_move(8, *dst_hi, f12));
   1623          addInstr(env, s390_insn_move(8, *dst_lo, f14));
   1624          return;
   1625 
   1626       case Iop_F64HLtoF128:
   1627          *dst_hi = s390_isel_float_expr(env, expr->Iex.Binop.arg1);
   1628          *dst_lo = s390_isel_float_expr(env, expr->Iex.Binop.arg2);
   1629          return;
   1630 
   1631       default:
   1632          goto irreducible;
   1633       }
   1634    }
   1635 
   1636       /* --------- UNARY OP --------- */
   1637    case Iex_Unop: {
   1638       IRExpr *left = expr->Iex.Unop.arg;
   1639       s390_bfp_unop_t bfpop;
   1640       s390_round_t rounding_mode;
   1641       HReg op_hi, op_lo, op, f12, f13, f14, f15;
   1642 
   1643       /* We use non-virtual registers as pairs (f13, f15) and (f12, f14)) */
   1644       f12 = make_fpr(12);
   1645       f13 = make_fpr(13);
   1646       f14 = make_fpr(14);
   1647       f15 = make_fpr(15);
   1648 
   1649       switch (expr->Iex.Unop.op) {
   1650       case Iop_NegF128:       bfpop = S390_BFP_NEG;          goto float128_opnd;
   1651       case Iop_AbsF128:       bfpop = S390_BFP_ABS;          goto float128_opnd;
   1652       case Iop_I32StoF128:    bfpop = S390_BFP_I32_TO_F128;  goto convert_int;
   1653       case Iop_I64StoF128:    bfpop = S390_BFP_I64_TO_F128;  goto convert_int;
   1654       case Iop_F32toF128:     bfpop = S390_BFP_F32_TO_F128;  goto convert_float;
   1655       case Iop_F64toF128:     bfpop = S390_BFP_F64_TO_F128;  goto convert_float;
   1656       default:
   1657          goto irreducible;
   1658       }
   1659 
   1660    float128_opnd:
   1661       s390_isel_float128_expr(&op_hi, &op_lo, env, left);
   1662 
   1663       /* operand --> (f13, f15) */
   1664       addInstr(env, s390_insn_move(8, f13, op_hi));
   1665       addInstr(env, s390_insn_move(8, f15, op_lo));
   1666 
   1667       rounding_mode = S390_ROUND_NEAREST_EVEN;  /* will not be used later on */
   1668       addInstr(env, s390_insn_bfp128_unop(16, bfpop, f12, f14, f13, f15,
   1669                                           rounding_mode));
   1670       goto move_dst;
   1671 
   1672    convert_float:
   1673       op  = s390_isel_float_expr(env, left);
   1674       addInstr(env, s390_insn_bfp128_convert_to(16, bfpop, f12, f14,
   1675                                                 op));
   1676       goto move_dst;
   1677 
   1678    convert_int:
   1679       op  = s390_isel_int_expr(env, left);
   1680       addInstr(env, s390_insn_bfp128_convert_to(16, bfpop, f12, f14,
   1681                                                 op));
   1682       goto move_dst;
   1683 
   1684    move_dst:
   1685       /* Move result to virtual destination registers */
   1686       *dst_hi = newVRegF(env);
   1687       *dst_lo = newVRegF(env);
   1688       addInstr(env, s390_insn_move(8, *dst_hi, f12));
   1689       addInstr(env, s390_insn_move(8, *dst_lo, f14));
   1690       return;
   1691    }
   1692 
   1693    default:
   1694       goto irreducible;
   1695    }
   1696 
   1697    /* We get here if no pattern matched. */
   1698  irreducible:
   1699    ppIRExpr(expr);
   1700    vpanic("s390_isel_int_expr: cannot reduce tree");
   1701 }
   1702 
   1703 /* Compute a 128-bit value into two 64-bit registers. These may be either
   1704    real or virtual regs; in any case they must not be changed by subsequent
   1705    code emitted by the caller. */
   1706 static void
   1707 s390_isel_float128_expr(HReg *dst_hi, HReg *dst_lo, ISelEnv *env, IRExpr *expr)
   1708 {
   1709    s390_isel_float128_expr_wrk(dst_hi, dst_lo, env, expr);
   1710 
   1711    /* Sanity checks ... */
   1712    vassert(hregIsVirtual(*dst_hi));
   1713    vassert(hregIsVirtual(*dst_lo));
   1714    vassert(hregClass(*dst_hi) == HRcFlt64);
   1715    vassert(hregClass(*dst_lo) == HRcFlt64);
   1716 }
   1717 
   1718 
   1719 /*---------------------------------------------------------*/
   1720 /*--- ISEL: Floating point expressions (64 bit)         ---*/
   1721 /*---------------------------------------------------------*/
   1722 
   1723 static HReg
   1724 s390_isel_float_expr_wrk(ISelEnv *env, IRExpr *expr)
   1725 {
   1726    IRType ty = typeOfIRExpr(env->type_env, expr);
   1727    UChar size;
   1728 
   1729    vassert(ty == Ity_F32 || ty == Ity_F64);
   1730 
   1731    size = sizeofIRType(ty);
   1732 
   1733    switch (expr->tag) {
   1734    case Iex_RdTmp:
   1735       /* Return the virtual register that holds the temporary. */
   1736       return lookupIRTemp(env, expr->Iex.RdTmp.tmp);
   1737 
   1738       /* --------- LOAD --------- */
   1739    case Iex_Load: {
   1740       HReg        dst = newVRegF(env);
   1741       s390_amode *am  = s390_isel_amode(env, expr->Iex.Load.addr);
   1742 
   1743       if (expr->Iex.Load.end != Iend_BE)
   1744          goto irreducible;
   1745 
   1746       addInstr(env, s390_insn_load(size, dst, am));
   1747 
   1748       return dst;
   1749    }
   1750 
   1751       /* --------- GET --------- */
   1752    case Iex_Get: {
   1753       HReg dst = newVRegF(env);
   1754       s390_amode *am = s390_amode_for_guest_state(expr->Iex.Get.offset);
   1755 
   1756       addInstr(env, s390_insn_load(size, dst, am));
   1757 
   1758       return dst;
   1759    }
   1760 
   1761       /* --------- LITERAL --------- */
   1762 
   1763       /* Load a literal into a register. Create a "load immediate"
   1764          v-insn and return the register. */
   1765    case Iex_Const: {
   1766       ULong value;
   1767       HReg  dst = newVRegF(env);
   1768       const IRConst *con = expr->Iex.Const.con;
   1769 
   1770       /* Bitwise copy of the value. No sign/zero-extension */
   1771       switch (con->tag) {
   1772       case Ico_F32i: value = con->Ico.F32i; break;
   1773       case Ico_F64i: value = con->Ico.F64i; break;
   1774       default:       vpanic("s390_isel_float_expr: invalid constant");
   1775       }
   1776 
   1777       if (value != 0) vpanic("cannot load immediate floating point constant");
   1778 
   1779       addInstr(env, s390_insn_load_immediate(size, dst, value));
   1780 
   1781       return dst;
   1782    }
   1783 
   1784       /* --------- 4-ary OP --------- */
   1785    case Iex_Qop: {
   1786       HReg op1, op2, op3, dst;
   1787       s390_bfp_triop_t bfpop;
   1788       s390_round_t rounding_mode;
   1789 
   1790       op1 = s390_isel_float_expr(env, expr->Iex.Qop.details->arg2);
   1791       op2 = s390_isel_float_expr(env, expr->Iex.Qop.details->arg3);
   1792       op3 = s390_isel_float_expr(env, expr->Iex.Qop.details->arg4);
   1793       dst = newVRegF(env);
   1794       addInstr(env, s390_insn_move(size, dst, op1));
   1795 
   1796       switch (expr->Iex.Qop.details->op) {
   1797       case Iop_MAddF32:
   1798       case Iop_MAddF64:  bfpop = S390_BFP_MADD; break;
   1799       case Iop_MSubF32:
   1800       case Iop_MSubF64:  bfpop = S390_BFP_MSUB; break;
   1801 
   1802       default:
   1803          goto irreducible;
   1804       }
   1805 
   1806       rounding_mode = decode_rounding_mode(expr->Iex.Qop.details->arg1);
   1807       addInstr(env, s390_insn_bfp_triop(size, bfpop, dst, op2, op3,
   1808                                         rounding_mode));
   1809       return dst;
   1810    }
   1811 
   1812       /* --------- TERNARY OP --------- */
   1813    case Iex_Triop: {
   1814       IRTriop *triop = expr->Iex.Triop.details;
   1815       IROp    op     = triop->op;
   1816       IRExpr *left   = triop->arg2;
   1817       IRExpr *right  = triop->arg3;
   1818       s390_bfp_binop_t bfpop;
   1819       s390_round_t rounding_mode;
   1820       HReg h1, op2, dst;
   1821 
   1822       h1   = s390_isel_float_expr(env, left);  /* Process 1st operand */
   1823       op2  = s390_isel_float_expr(env, right); /* Process 2nd operand */
   1824       dst  = newVRegF(env);
   1825       addInstr(env, s390_insn_move(size, dst, h1));
   1826       switch (op) {
   1827       case Iop_AddF32:
   1828       case Iop_AddF64:  bfpop = S390_BFP_ADD; break;
   1829       case Iop_SubF32:
   1830       case Iop_SubF64:  bfpop = S390_BFP_SUB; break;
   1831       case Iop_MulF32:
   1832       case Iop_MulF64:  bfpop = S390_BFP_MUL; break;
   1833       case Iop_DivF32:
   1834       case Iop_DivF64:  bfpop = S390_BFP_DIV; break;
   1835 
   1836       default:
   1837          goto irreducible;
   1838       }
   1839 
   1840       rounding_mode = decode_rounding_mode(triop->arg1);
   1841       addInstr(env, s390_insn_bfp_binop(size, bfpop, dst, op2, rounding_mode));
   1842       return dst;
   1843    }
   1844 
   1845       /* --------- BINARY OP --------- */
   1846    case Iex_Binop: {
   1847       IROp    op   = expr->Iex.Binop.op;
   1848       IRExpr *left = expr->Iex.Binop.arg2;
   1849       HReg h1, dst;
   1850       s390_bfp_unop_t bfpop;
   1851       s390_round_t rounding_mode;
   1852       Int integer_operand;
   1853 
   1854       integer_operand = 1;
   1855 
   1856       switch (op) {
   1857       case Iop_SqrtF32:
   1858       case Iop_SqrtF64:
   1859          bfpop = S390_BFP_SQRT;
   1860          integer_operand = 0;
   1861          break;
   1862 
   1863       case Iop_F64toF32:
   1864          bfpop = S390_BFP_F64_TO_F32;
   1865          integer_operand = 0;
   1866          break;
   1867 
   1868       case Iop_I32StoF32: bfpop = S390_BFP_I32_TO_F32; break;
   1869       case Iop_I64StoF32: bfpop = S390_BFP_I64_TO_F32; break;
   1870       case Iop_I64StoF64: bfpop = S390_BFP_I64_TO_F64; break;
   1871       default:
   1872          goto irreducible;
   1873 
   1874       case Iop_F128toF64:
   1875       case Iop_F128toF32: {
   1876          HReg op_hi, op_lo, f12, f13, f14, f15;
   1877 
   1878          bfpop = op == Iop_F128toF32 ? S390_BFP_F128_TO_F32
   1879             : S390_BFP_F128_TO_F64;
   1880 
   1881          rounding_mode = decode_rounding_mode(expr->Iex.Binop.arg1);
   1882 
   1883          s390_isel_float128_expr(&op_hi, &op_lo, env, expr->Iex.Binop.arg2);
   1884 
   1885          /* We use non-virtual registers as pairs (f13, f15) and (f12, f14)) */
   1886          f12 = make_fpr(12);
   1887          f13 = make_fpr(13);
   1888          f14 = make_fpr(14);
   1889          f15 = make_fpr(15);
   1890 
   1891          /* operand --> (f13, f15) */
   1892          addInstr(env, s390_insn_move(8, f13, op_hi));
   1893          addInstr(env, s390_insn_move(8, f15, op_lo));
   1894 
   1895          dst = newVRegF(env);
   1896          addInstr(env, s390_insn_bfp128_unop(16, bfpop, f12, f14, f13, f15,
   1897                                              rounding_mode));
   1898 
   1899          /* Move result to virtual destination registers */
   1900          addInstr(env, s390_insn_move(8, dst, f12));
   1901          return dst;
   1902       }
   1903       }
   1904 
   1905       /* Process operand */
   1906       if (integer_operand) {
   1907          h1  = s390_isel_int_expr(env, left);
   1908       } else {
   1909          h1  = s390_isel_float_expr(env, left);
   1910       }
   1911 
   1912       dst = newVRegF(env);
   1913       rounding_mode = decode_rounding_mode(expr->Iex.Binop.arg1);
   1914       addInstr(env, s390_insn_bfp_unop(size, bfpop, dst, h1, rounding_mode));
   1915       return dst;
   1916    }
   1917 
   1918       /* --------- UNARY OP --------- */
   1919    case Iex_Unop: {
   1920       IROp    op   = expr->Iex.Unop.op;
   1921       IRExpr *left = expr->Iex.Unop.arg;
   1922       s390_bfp_unop_t bfpop;
   1923       s390_round_t rounding_mode;
   1924       HReg h1, dst;
   1925 
   1926       if (op == Iop_F128HItoF64 || op == Iop_F128LOtoF64) {
   1927          HReg dst_hi, dst_lo;
   1928 
   1929          s390_isel_float128_expr(&dst_hi, &dst_lo, env, left);
   1930          return op == Iop_F128LOtoF64 ? dst_lo : dst_hi;
   1931       }
   1932 
   1933       if (op == Iop_ReinterpI64asF64 || op == Iop_ReinterpI32asF32) {
   1934          dst = newVRegF(env);
   1935          h1  = s390_isel_int_expr(env, left);     /* Process the operand */
   1936          addInstr(env, s390_insn_move(size, dst, h1));
   1937 
   1938          return dst;
   1939       }
   1940 
   1941       switch (op) {
   1942       case Iop_NegF32:
   1943       case Iop_NegF64:
   1944          if (left->tag == Iex_Unop &&
   1945              (left->Iex.Unop.op == Iop_AbsF32 || left->Iex.Unop.op == Iop_AbsF64))
   1946             bfpop = S390_BFP_NABS;
   1947          else
   1948             bfpop = S390_BFP_NEG;
   1949          break;
   1950 
   1951       case Iop_AbsF32:
   1952       case Iop_AbsF64:        bfpop = S390_BFP_ABS;  break;
   1953       case Iop_I32StoF64:     bfpop = S390_BFP_I32_TO_F64;  break;
   1954       case Iop_F32toF64:      bfpop = S390_BFP_F32_TO_F64;  break;
   1955       default:
   1956          goto irreducible;
   1957       }
   1958 
   1959       /* Process operand */
   1960       if (op == Iop_I32StoF64)
   1961          h1 = s390_isel_int_expr(env, left);
   1962       else if (bfpop == S390_BFP_NABS)
   1963          h1 = s390_isel_float_expr(env, left->Iex.Unop.arg);
   1964       else
   1965          h1 = s390_isel_float_expr(env, left);
   1966 
   1967       dst = newVRegF(env);
   1968       rounding_mode = S390_ROUND_NEAREST_EVEN;  /* will not be used later on */
   1969       addInstr(env, s390_insn_bfp_unop(size, bfpop, dst, h1, rounding_mode));
   1970       return dst;
   1971    }
   1972 
   1973    default:
   1974       goto irreducible;
   1975    }
   1976 
   1977    /* We get here if no pattern matched. */
   1978  irreducible:
   1979    ppIRExpr(expr);
   1980    vpanic("s390_isel_float_expr: cannot reduce tree");
   1981 }
   1982 
   1983 
   1984 static HReg
   1985 s390_isel_float_expr(ISelEnv *env, IRExpr *expr)
   1986 {
   1987    HReg dst = s390_isel_float_expr_wrk(env, expr);
   1988 
   1989    /* Sanity checks ... */
   1990    vassert(hregClass(dst) == HRcFlt64);
   1991    vassert(hregIsVirtual(dst));
   1992 
   1993    return dst;
   1994 }
   1995 
   1996 
   1997 /*---------------------------------------------------------*/
   1998 /*--- ISEL: Condition Code                              ---*/
   1999 /*---------------------------------------------------------*/
   2000 
   2001 /* This function handles all operators that produce a 1-bit result */
   2002 static s390_cc_t
   2003 s390_isel_cc(ISelEnv *env, IRExpr *cond)
   2004 {
   2005    UChar size;
   2006 
   2007    vassert(typeOfIRExpr(env->type_env, cond) == Ity_I1);
   2008 
   2009    /* Constant: either 1 or 0 */
   2010    if (cond->tag == Iex_Const) {
   2011       vassert(cond->Iex.Const.con->tag == Ico_U1);
   2012       vassert(cond->Iex.Const.con->Ico.U1 == True
   2013               || cond->Iex.Const.con->Ico.U1 == False);
   2014 
   2015       return cond->Iex.Const.con->Ico.U1 == True ? S390_CC_ALWAYS : S390_CC_NEVER;
   2016    }
   2017 
   2018    /* Variable: values are 1 or 0 */
   2019    if (cond->tag == Iex_RdTmp) {
   2020       IRTemp tmp = cond->Iex.RdTmp.tmp;
   2021       HReg   reg = lookupIRTemp(env, tmp);
   2022 
   2023       /* Load-and-test does not modify REG; so this is OK. */
   2024       if (typeOfIRTemp(env->type_env, tmp) == Ity_I1)
   2025          size = 4;
   2026       else
   2027          size = sizeofIRType(typeOfIRTemp(env->type_env, tmp));
   2028       addInstr(env, s390_insn_test(size, s390_opnd_reg(reg)));
   2029       return S390_CC_NE;
   2030    }
   2031 
   2032    /* Unary operators */
   2033    if (cond->tag == Iex_Unop) {
   2034       IRExpr *arg = cond->Iex.Unop.arg;
   2035 
   2036       switch (cond->Iex.Unop.op) {
   2037       case Iop_Not1:  /* Not1(cond) */
   2038          /* Generate code for EXPR, and negate the test condition */
   2039          return s390_cc_invert(s390_isel_cc(env, arg));
   2040 
   2041          /* Iop_32/64to1  select the LSB from their operand */
   2042       case Iop_32to1:
   2043       case Iop_64to1: {
   2044          HReg dst = newVRegI(env);
   2045          HReg h1  = s390_isel_int_expr(env, arg);
   2046 
   2047          size = sizeofIRType(typeOfIRExpr(env->type_env, arg));
   2048 
   2049          addInstr(env, s390_insn_move(size, dst, h1));
   2050          addInstr(env, s390_insn_alu(size, S390_ALU_AND, dst, s390_opnd_imm(1)));
   2051          addInstr(env, s390_insn_test(size, s390_opnd_reg(dst)));
   2052          return S390_CC_NE;
   2053       }
   2054 
   2055       case Iop_CmpNEZ8:
   2056       case Iop_CmpNEZ16: {
   2057          s390_opnd_RMI src;
   2058          s390_unop_t   op;
   2059          HReg dst;
   2060 
   2061          op  = (cond->Iex.Unop.op == Iop_CmpNEZ8) ? S390_ZERO_EXTEND_8
   2062             : S390_ZERO_EXTEND_16;
   2063          dst = newVRegI(env);
   2064          src = s390_isel_int_expr_RMI(env, arg);
   2065          addInstr(env, s390_insn_unop(4, op, dst, src));
   2066          addInstr(env, s390_insn_test(4, s390_opnd_reg(dst)));
   2067          return S390_CC_NE;
   2068       }
   2069 
   2070       case Iop_CmpNEZ32:
   2071       case Iop_CmpNEZ64: {
   2072          s390_opnd_RMI src;
   2073 
   2074          src = s390_isel_int_expr_RMI(env, arg);
   2075          size = sizeofIRType(typeOfIRExpr(env->type_env, arg));
   2076          addInstr(env, s390_insn_test(size, src));
   2077          return S390_CC_NE;
   2078       }
   2079 
   2080       default:
   2081          goto fail;
   2082       }
   2083    }
   2084 
   2085    /* Binary operators */
   2086    if (cond->tag == Iex_Binop) {
   2087       IRExpr *arg1 = cond->Iex.Binop.arg1;
   2088       IRExpr *arg2 = cond->Iex.Binop.arg2;
   2089       HReg reg1, reg2;
   2090 
   2091       size = sizeofIRType(typeOfIRExpr(env->type_env, arg1));
   2092 
   2093       switch (cond->Iex.Binop.op) {
   2094          s390_unop_t op;
   2095          s390_cc_t   result;
   2096 
   2097       case Iop_CmpEQ8:
   2098       case Iop_CasCmpEQ8:
   2099          op     = S390_ZERO_EXTEND_8;
   2100          result = S390_CC_E;
   2101          goto do_compare_ze;
   2102 
   2103       case Iop_CmpNE8:
   2104       case Iop_CasCmpNE8:
   2105          op     = S390_ZERO_EXTEND_8;
   2106          result = S390_CC_NE;
   2107          goto do_compare_ze;
   2108 
   2109       case Iop_CmpEQ16:
   2110       case Iop_CasCmpEQ16:
   2111          op     = S390_ZERO_EXTEND_16;
   2112          result = S390_CC_E;
   2113          goto do_compare_ze;
   2114 
   2115       case Iop_CmpNE16:
   2116       case Iop_CasCmpNE16:
   2117          op     = S390_ZERO_EXTEND_16;
   2118          result = S390_CC_NE;
   2119          goto do_compare_ze;
   2120 
   2121       do_compare_ze: {
   2122             s390_opnd_RMI op1, op2;
   2123 
   2124             op1  = s390_isel_int_expr_RMI(env, arg1);
   2125             reg1 = newVRegI(env);
   2126             addInstr(env, s390_insn_unop(4, op, reg1, op1));
   2127 
   2128             op2  = s390_isel_int_expr_RMI(env, arg2);
   2129             reg2 = newVRegI(env);
   2130             addInstr(env, s390_insn_unop(4, op, reg2, op2));  /* zero extend */
   2131 
   2132             op2 = s390_opnd_reg(reg2);
   2133             addInstr(env, s390_insn_compare(4, reg1, op2, False));
   2134 
   2135             return result;
   2136          }
   2137 
   2138       case Iop_CmpEQ32:
   2139       case Iop_CmpEQ64:
   2140       case Iop_CasCmpEQ32:
   2141       case Iop_CasCmpEQ64:
   2142          result = S390_CC_E;
   2143          goto do_compare;
   2144 
   2145       case Iop_CmpNE32:
   2146       case Iop_CmpNE64:
   2147       case Iop_CasCmpNE32:
   2148       case Iop_CasCmpNE64:
   2149          result = S390_CC_NE;
   2150          goto do_compare;
   2151 
   2152       do_compare: {
   2153             HReg op1;
   2154             s390_opnd_RMI op2;
   2155 
   2156             order_commutative_operands(arg1, arg2);
   2157 
   2158             op1 = s390_isel_int_expr(env, arg1);
   2159             op2 = s390_isel_int_expr_RMI(env, arg2);
   2160 
   2161             addInstr(env, s390_insn_compare(size, op1, op2, False));
   2162 
   2163             return result;
   2164          }
   2165 
   2166       case Iop_CmpLT32S:
   2167       case Iop_CmpLE32S:
   2168       case Iop_CmpLT64S:
   2169       case Iop_CmpLE64S: {
   2170          HReg op1;
   2171          s390_opnd_RMI op2;
   2172 
   2173          op1 = s390_isel_int_expr(env, arg1);
   2174          op2 = s390_isel_int_expr_RMI(env, arg2);
   2175 
   2176          addInstr(env, s390_insn_compare(size, op1, op2, True));
   2177 
   2178          return (cond->Iex.Binop.op == Iop_CmpLT32S ||
   2179                  cond->Iex.Binop.op == Iop_CmpLT64S) ? S390_CC_L : S390_CC_LE;
   2180       }
   2181 
   2182       case Iop_CmpLT32U:
   2183       case Iop_CmpLE32U:
   2184       case Iop_CmpLT64U:
   2185       case Iop_CmpLE64U: {
   2186          HReg op1;
   2187          s390_opnd_RMI op2;
   2188 
   2189          op1 = s390_isel_int_expr(env, arg1);
   2190          op2 = s390_isel_int_expr_RMI(env, arg2);
   2191 
   2192          addInstr(env, s390_insn_compare(size, op1, op2, False));
   2193 
   2194          return (cond->Iex.Binop.op == Iop_CmpLT32U ||
   2195                  cond->Iex.Binop.op == Iop_CmpLT64U) ? S390_CC_L : S390_CC_LE;
   2196       }
   2197 
   2198       default:
   2199          goto fail;
   2200       }
   2201    }
   2202 
   2203  fail:
   2204    ppIRExpr(cond);
   2205    vpanic("s390_isel_cc: unexpected operator");
   2206 }
   2207 
   2208 
   2209 /*---------------------------------------------------------*/
   2210 /*--- ISEL: Statements                                  ---*/
   2211 /*---------------------------------------------------------*/
   2212 
   2213 static void
   2214 s390_isel_stmt(ISelEnv *env, IRStmt *stmt)
   2215 {
   2216    if (vex_traceflags & VEX_TRACE_VCODE) {
   2217       vex_printf("\n -- ");
   2218       ppIRStmt(stmt);
   2219       vex_printf("\n");
   2220    }
   2221 
   2222    switch (stmt->tag) {
   2223 
   2224       /* --------- STORE --------- */
   2225    case Ist_Store: {
   2226       IRType tyd = typeOfIRExpr(env->type_env, stmt->Ist.Store.data);
   2227       s390_amode *am;
   2228       HReg src;
   2229 
   2230       if (stmt->Ist.Store.end != Iend_BE) goto stmt_fail;
   2231 
   2232       am = s390_isel_amode(env, stmt->Ist.Store.addr);
   2233 
   2234       switch (tyd) {
   2235       case Ity_I8:
   2236       case Ity_I16:
   2237       case Ity_I32:
   2238       case Ity_I64:
   2239          src = s390_isel_int_expr(env, stmt->Ist.Store.data);
   2240          break;
   2241 
   2242       case Ity_F32:
   2243       case Ity_F64:
   2244          src = s390_isel_float_expr(env, stmt->Ist.Store.data);
   2245          break;
   2246 
   2247       case Ity_F128:
   2248          /* Cannot occur. No such instruction */
   2249          vpanic("Ist_Store with F128 data");
   2250 
   2251       default:
   2252          goto stmt_fail;
   2253       }
   2254 
   2255       addInstr(env, s390_insn_store(sizeofIRType(tyd), am, src));
   2256       return;
   2257    }
   2258 
   2259       /* --------- PUT --------- */
   2260    case Ist_Put: {
   2261       IRType tyd = typeOfIRExpr(env->type_env, stmt->Ist.Put.data);
   2262       HReg src;
   2263       s390_amode *am;
   2264       ULong new_value, old_value, difference;
   2265 
   2266       /* Detect updates to certain guest registers. We track the contents
   2267          of those registers as long as they contain constants. If the new
   2268          constant is either zero or in the 8-bit neighbourhood of the
   2269          current value we can use a memory-to-memory insn to do the update. */
   2270 
   2271       Int offset = stmt->Ist.Put.offset;
   2272 
   2273       /* Check necessary conditions:
   2274          (1) must be one of the registers we care about
   2275          (2) assigned value must be a constant */
   2276       Int guest_reg = get_guest_reg(offset);
   2277 
   2278       if (guest_reg == GUEST_UNKNOWN) goto not_special;
   2279 
   2280       if (guest_reg == GUEST_IA) {
   2281          /* If this is the first assignment to the IA reg, don't special case
   2282             it. We need to do a full 8-byte assignment here. The reason is
   2283             that in case of a redirected translation the guest IA does not
   2284             contain the redirected-to address. Instead it contains the
   2285             redirected-from address and those can be far apart. So in order to
   2286             do incremnetal updates if the IA in the future we need to get the
   2287             initial address of the super block correct. */
   2288          if (env->first_IA_assignment) {
   2289             env->first_IA_assignment = False;
   2290             goto not_special;
   2291          }
   2292       }
   2293 
   2294       if (stmt->Ist.Put.data->tag != Iex_Const) {
   2295          /* Invalidate guest register contents */
   2296          env->old_value_valid[guest_reg] = False;
   2297          goto not_special;
   2298       }
   2299 
   2300       /* We can only handle Ity_I64, but the CC_DEPS field can have floats */
   2301       if (tyd != Ity_I64)
   2302          goto not_special;
   2303 
   2304       /* OK. Necessary conditions are satisfied. */
   2305 
   2306       old_value = env->old_value[guest_reg];
   2307       new_value = stmt->Ist.Put.data->Iex.Const.con->Ico.U64;
   2308       env->old_value[guest_reg] = new_value;
   2309 
   2310       Bool old_value_is_valid = env->old_value_valid[guest_reg];
   2311       env->old_value_valid[guest_reg] = True;
   2312 
   2313       /* If the register already contains the new value, there is nothing
   2314          to do here. Unless the guest register requires precise memory
   2315          exceptions. */
   2316       if (old_value_is_valid && new_value == old_value) {
   2317          if (! guest_s390x_state_requires_precise_mem_exns(offset, offset + 8)) {
   2318             return;
   2319          }
   2320       }
   2321 
   2322       /* guest register = 0 */
   2323       if (new_value == 0) {
   2324          addInstr(env, s390_insn_gzero(sizeofIRType(tyd), offset));
   2325          return;
   2326       }
   2327 
   2328       if (old_value_is_valid == False) goto not_special;
   2329 
   2330       /* If the new value is in the neighbourhood of the old value
   2331          we can use a memory-to-memory insn */
   2332       difference = new_value - old_value;
   2333 
   2334       if (s390_host_has_gie && ulong_fits_signed_8bit(difference)) {
   2335          addInstr(env, s390_insn_gadd(sizeofIRType(tyd), offset,
   2336                                       (difference & 0xFF), new_value));
   2337          return;
   2338       }
   2339 
   2340       /* If the high word is the same it is sufficient to load the low word.
   2341          Use R0 as a scratch reg. */
   2342       if ((old_value >> 32) == (new_value >> 32)) {
   2343          HReg r0  = make_gpr(0);
   2344          HReg gsp = make_gpr(S390_REGNO_GUEST_STATE_POINTER);
   2345          s390_amode *gam;
   2346 
   2347          gam = s390_amode_b12(offset + 4, gsp);
   2348          addInstr(env, s390_insn_load_immediate(4, r0,
   2349                                                 new_value & 0xFFFFFFFF));
   2350          addInstr(env, s390_insn_store(4, gam, r0));
   2351          return;
   2352       }
   2353 
   2354       /* No special case applies... fall through */
   2355 
   2356    not_special:
   2357       am = s390_amode_for_guest_state(stmt->Ist.Put.offset);
   2358 
   2359       switch (tyd) {
   2360       case Ity_I8:
   2361       case Ity_I16:
   2362       case Ity_I32:
   2363       case Ity_I64:
   2364          src = s390_isel_int_expr(env, stmt->Ist.Put.data);
   2365          break;
   2366 
   2367       case Ity_F32:
   2368       case Ity_F64:
   2369          src = s390_isel_float_expr(env, stmt->Ist.Put.data);
   2370          break;
   2371 
   2372       case Ity_F128:
   2373          /* Does not occur. See function put_fpr_pair. */
   2374          vpanic("Ist_Put with F128 data");
   2375 
   2376       default:
   2377          goto stmt_fail;
   2378       }
   2379 
   2380       addInstr(env, s390_insn_store(sizeofIRType(tyd), am, src));
   2381       return;
   2382    }
   2383 
   2384       /* --------- TMP --------- */
   2385    case Ist_WrTmp: {
   2386       IRTemp tmp = stmt->Ist.WrTmp.tmp;
   2387       IRType tyd = typeOfIRTemp(env->type_env, tmp);
   2388       HReg src, dst;
   2389 
   2390       switch (tyd) {
   2391       case Ity_I128: {
   2392          HReg dst_hi, dst_lo, res_hi, res_lo;
   2393 
   2394          s390_isel_int128_expr(&res_hi, &res_lo, env, stmt->Ist.WrTmp.data);
   2395          lookupIRTemp128(&dst_hi, &dst_lo, env, tmp);
   2396 
   2397          addInstr(env, s390_insn_move(8, dst_hi, res_hi));
   2398          addInstr(env, s390_insn_move(8, dst_lo, res_lo));
   2399          return;
   2400       }
   2401 
   2402       case Ity_I8:
   2403       case Ity_I16:
   2404       case Ity_I32:
   2405       case Ity_I64:
   2406          src = s390_isel_int_expr(env, stmt->Ist.WrTmp.data);
   2407          dst = lookupIRTemp(env, tmp);
   2408          break;
   2409 
   2410       case Ity_I1: {
   2411          s390_cc_t cond = s390_isel_cc(env, stmt->Ist.WrTmp.data);
   2412          dst = lookupIRTemp(env, tmp);
   2413          addInstr(env, s390_insn_cc2bool(dst, cond));
   2414          return;
   2415       }
   2416 
   2417       case Ity_F32:
   2418       case Ity_F64:
   2419          src = s390_isel_float_expr(env, stmt->Ist.WrTmp.data);
   2420          dst = lookupIRTemp(env, tmp);
   2421          break;
   2422 
   2423       case Ity_F128: {
   2424          HReg dst_hi, dst_lo, res_hi, res_lo;
   2425 
   2426          s390_isel_float128_expr(&res_hi, &res_lo, env, stmt->Ist.WrTmp.data);
   2427          lookupIRTemp128(&dst_hi, &dst_lo, env, tmp);
   2428 
   2429          addInstr(env, s390_insn_move(8, dst_hi, res_hi));
   2430          addInstr(env, s390_insn_move(8, dst_lo, res_lo));
   2431          return;
   2432       }
   2433 
   2434       default:
   2435          goto stmt_fail;
   2436       }
   2437 
   2438       addInstr(env, s390_insn_move(sizeofIRType(tyd), dst, src));
   2439       return;
   2440    }
   2441 
   2442       /* --------- Call to DIRTY helper --------- */
   2443    case Ist_Dirty: {
   2444       IRType   retty;
   2445       IRDirty* d = stmt->Ist.Dirty.details;
   2446       Bool     passBBP;
   2447       HReg dst;
   2448       Int i;
   2449 
   2450       /* Invalidate tracked values of those guest state registers that are
   2451          modified by this helper. */
   2452       for (i = 0; i < d->nFxState; ++i) {
   2453          /* JRS 1 June 2012: AFAICS, s390 guest doesn't use 'repeat'
   2454             descriptors in guest state effect descriptions.  Hence: */
   2455          vassert(d->fxState[i].nRepeats == 0 && d->fxState[i].repeatLen == 0);
   2456          if ((d->fxState[i].fx == Ifx_Write || d->fxState[i].fx == Ifx_Modify)) {
   2457             Int guest_reg = get_guest_reg(d->fxState[i].offset);
   2458             if (guest_reg != GUEST_UNKNOWN)
   2459                env->old_value_valid[guest_reg] = False;
   2460          }
   2461       }
   2462 
   2463       if (d->nFxState == 0)
   2464          vassert(!d->needsBBP);
   2465 
   2466       passBBP = toBool(d->nFxState > 0 && d->needsBBP);
   2467 
   2468       if (d->tmp == IRTemp_INVALID) {
   2469          /* No return value. */
   2470          dst = INVALID_HREG;
   2471          doHelperCall(env, passBBP, d->guard, d->cee, d->args, dst);
   2472          return;
   2473       }
   2474 
   2475       retty = typeOfIRTemp(env->type_env, d->tmp);
   2476       if (retty == Ity_I64 || retty == Ity_I32
   2477           || retty == Ity_I16 || retty == Ity_I8) {
   2478          /* Move the returned value to the destination register */
   2479          dst = lookupIRTemp(env, d->tmp);
   2480          doHelperCall(env, passBBP, d->guard, d->cee, d->args, dst);
   2481          return;
   2482       }
   2483       break;
   2484    }
   2485 
   2486    case Ist_CAS:
   2487       if (stmt->Ist.CAS.details->oldHi == IRTemp_INVALID) {
   2488          IRCAS *cas = stmt->Ist.CAS.details;
   2489          s390_amode *op2 = s390_isel_amode(env, cas->addr);
   2490          HReg op3 = s390_isel_int_expr(env, cas->dataLo);  /* new value */
   2491          HReg op1 = s390_isel_int_expr(env, cas->expdLo);  /* expected value */
   2492          HReg old = lookupIRTemp(env, cas->oldLo);
   2493 
   2494          if (typeOfIRTemp(env->type_env, cas->oldLo) == Ity_I32) {
   2495             addInstr(env, s390_insn_cas(4, op1, op2, op3, old));
   2496          } else {
   2497             addInstr(env, s390_insn_cas(8, op1, op2, op3, old));
   2498          }
   2499          return;
   2500       } else {
   2501          IRCAS *cas = stmt->Ist.CAS.details;
   2502          s390_amode *op2 = s390_isel_amode(env,  cas->addr);
   2503          HReg r8, r9, r10, r11, r1;
   2504          HReg op3_high = s390_isel_int_expr(env, cas->dataHi);  /* new value */
   2505          HReg op3_low  = s390_isel_int_expr(env, cas->dataLo);  /* new value */
   2506          HReg op1_high = s390_isel_int_expr(env, cas->expdHi);  /* expected value */
   2507          HReg op1_low  = s390_isel_int_expr(env, cas->expdLo);  /* expected value */
   2508          HReg old_low  = lookupIRTemp(env, cas->oldLo);
   2509          HReg old_high = lookupIRTemp(env, cas->oldHi);
   2510 
   2511          /* Use non-virtual registers r8 and r9 as pair for op1
   2512             and move op1 there */
   2513          r8 = make_gpr(8);
   2514          r9 = make_gpr(9);
   2515          addInstr(env, s390_insn_move(8, r8, op1_high));
   2516          addInstr(env, s390_insn_move(8, r9, op1_low));
   2517 
   2518          /* Use non-virtual registers r10 and r11 as pair for op3
   2519             and move op3 there */
   2520          r10 = make_gpr(10);
   2521          r11 = make_gpr(11);
   2522          addInstr(env, s390_insn_move(8, r10, op3_high));
   2523          addInstr(env, s390_insn_move(8, r11, op3_low));
   2524 
   2525          /* Register r1 is used as a scratch register */
   2526          r1 = make_gpr(1);
   2527 
   2528          if (typeOfIRTemp(env->type_env, cas->oldLo) == Ity_I32) {
   2529             addInstr(env, s390_insn_cdas(4, r8, r9, op2, r10, r11,
   2530                                          old_high, old_low, r1));
   2531          } else {
   2532             addInstr(env, s390_insn_cdas(8, r8, r9, op2, r10, r11,
   2533                                          old_high, old_low, r1));
   2534          }
   2535          addInstr(env, s390_insn_move(8, op1_high, r8));
   2536          addInstr(env, s390_insn_move(8, op1_low,  r9));
   2537          addInstr(env, s390_insn_move(8, op3_high, r10));
   2538          addInstr(env, s390_insn_move(8, op3_low,  r11));
   2539          return;
   2540       }
   2541       break;
   2542 
   2543       /* --------- EXIT --------- */
   2544    case Ist_Exit: {
   2545       s390_cc_t cond;
   2546       IRConstTag tag = stmt->Ist.Exit.dst->tag;
   2547 
   2548       if (tag != Ico_U64)
   2549          vpanic("s390_isel_stmt: Ist_Exit: dst is not a 64-bit value");
   2550 
   2551       s390_amode *guest_IA = s390_amode_for_guest_state(stmt->Ist.Exit.offsIP);
   2552       cond = s390_isel_cc(env, stmt->Ist.Exit.guard);
   2553 
   2554       /* Case: boring transfer to known address */
   2555       if (stmt->Ist.Exit.jk == Ijk_Boring) {
   2556          if (env->chaining_allowed) {
   2557             /* .. almost always true .. */
   2558             /* Skip the event check at the dst if this is a forwards
   2559                edge. */
   2560             Bool to_fast_entry
   2561                = ((Addr64)stmt->Ist.Exit.dst->Ico.U64) > env->max_ga;
   2562             if (0) vex_printf("%s", to_fast_entry ? "Y" : ",");
   2563             addInstr(env, s390_insn_xdirect(cond, stmt->Ist.Exit.dst->Ico.U64,
   2564                                             guest_IA, to_fast_entry));
   2565          } else {
   2566             /* .. very occasionally .. */
   2567             /* We can't use chaining, so ask for an assisted transfer,
   2568                as that's the only alternative that is allowable. */
   2569             HReg dst = s390_isel_int_expr(env,
   2570                                           IRExpr_Const(stmt->Ist.Exit.dst));
   2571             addInstr(env, s390_insn_xassisted(cond, dst, guest_IA, Ijk_Boring));
   2572          }
   2573          return;
   2574       }
   2575 
   2576       /* Case: assisted transfer to arbitrary address */
   2577       switch (stmt->Ist.Exit.jk) {
   2578       case Ijk_NoDecode:
   2579       case Ijk_TInval:
   2580       case Ijk_Sys_syscall:
   2581       case Ijk_ClientReq:
   2582       case Ijk_NoRedir:
   2583       case Ijk_Yield:
   2584       case Ijk_SigTRAP: {
   2585          HReg dst = s390_isel_int_expr(env, IRExpr_Const(stmt->Ist.Exit.dst));
   2586          addInstr(env, s390_insn_xassisted(cond, dst, guest_IA,
   2587                                            stmt->Ist.Exit.jk));
   2588          return;
   2589       }
   2590       default:
   2591          break;
   2592       }
   2593 
   2594       /* Do we ever expect to see any other kind? */
   2595       goto stmt_fail;
   2596    }
   2597 
   2598       /* --------- MEM FENCE --------- */
   2599    case Ist_MBE:
   2600       switch (stmt->Ist.MBE.event) {
   2601          case Imbe_Fence:
   2602             addInstr(env, s390_insn_mfence());
   2603             return;
   2604          default:
   2605             break;
   2606       }
   2607       break;
   2608 
   2609       /* --------- Miscellaneous --------- */
   2610 
   2611    case Ist_PutI:    /* Not needed */
   2612    case Ist_IMark:   /* Doesn't generate any executable code */
   2613    case Ist_NoOp:    /* Doesn't generate any executable code */
   2614    case Ist_AbiHint: /* Meaningless in IR */
   2615       return;
   2616 
   2617    default:
   2618       break;
   2619    }
   2620 
   2621  stmt_fail:
   2622    ppIRStmt(stmt);
   2623    vpanic("s390_isel_stmt");
   2624 }
   2625 
   2626 
   2627 /*---------------------------------------------------------*/
   2628 /*--- ISEL: Basic block terminators (Nexts)             ---*/
   2629 /*---------------------------------------------------------*/
   2630 
   2631 static void
   2632 iselNext(ISelEnv *env, IRExpr *next, IRJumpKind jk, int offsIP)
   2633 {
   2634    if (vex_traceflags & VEX_TRACE_VCODE) {
   2635       vex_printf("\n-- PUT(%d) = ", offsIP);
   2636       ppIRExpr(next);
   2637       vex_printf("; exit-");
   2638       ppIRJumpKind(jk);
   2639       vex_printf("\n");
   2640    }
   2641 
   2642    s390_amode *guest_IA = s390_amode_for_guest_state(offsIP);
   2643 
   2644    /* Case: boring transfer to known address */
   2645    if (next->tag == Iex_Const) {
   2646       IRConst *cdst = next->Iex.Const.con;
   2647       vassert(cdst->tag == Ico_U64);
   2648       if (jk == Ijk_Boring || jk == Ijk_Call) {
   2649          /* Boring transfer to known address */
   2650          if (env->chaining_allowed) {
   2651             /* .. almost always true .. */
   2652             /* Skip the event check at the dst if this is a forwards
   2653                edge. */
   2654             Bool to_fast_entry
   2655                = ((Addr64)cdst->Ico.U64) > env->max_ga;
   2656             if (0) vex_printf("%s", to_fast_entry ? "X" : ".");
   2657             addInstr(env, s390_insn_xdirect(S390_CC_ALWAYS, cdst->Ico.U64,
   2658                                             guest_IA, to_fast_entry));
   2659          } else {
   2660             /* .. very occasionally .. */
   2661             /* We can't use chaining, so ask for an indirect transfer,
   2662                as that's the cheapest alternative that is allowable. */
   2663             HReg dst = s390_isel_int_expr(env, next);
   2664             addInstr(env, s390_insn_xassisted(S390_CC_ALWAYS, dst, guest_IA,
   2665                                               Ijk_Boring));
   2666          }
   2667          return;
   2668       }
   2669    }
   2670 
   2671    /* Case: call/return (==boring) transfer to any address */
   2672    switch (jk) {
   2673    case Ijk_Boring:
   2674    case Ijk_Ret:
   2675    case Ijk_Call: {
   2676       HReg dst = s390_isel_int_expr(env, next);
   2677       if (env->chaining_allowed) {
   2678          addInstr(env, s390_insn_xindir(S390_CC_ALWAYS, dst, guest_IA));
   2679       } else {
   2680          addInstr(env, s390_insn_xassisted(S390_CC_ALWAYS, dst, guest_IA,
   2681                                            Ijk_Boring));
   2682       }
   2683       return;
   2684    }
   2685    default:
   2686       break;
   2687    }
   2688 
   2689    /* Case: some other kind of transfer to any address */
   2690    switch (jk) {
   2691    case Ijk_NoDecode:
   2692    case Ijk_TInval:
   2693    case Ijk_Sys_syscall:
   2694    case Ijk_ClientReq:
   2695    case Ijk_NoRedir:
   2696    case Ijk_Yield:
   2697    case Ijk_SigTRAP: {
   2698       HReg dst = s390_isel_int_expr(env, next);
   2699       addInstr(env, s390_insn_xassisted(S390_CC_ALWAYS, dst, guest_IA, jk));
   2700       return;
   2701    }
   2702    default:
   2703       break;
   2704    }
   2705 
   2706    vpanic("iselNext");
   2707 }
   2708 
   2709 
   2710 /*---------------------------------------------------------*/
   2711 /*--- Insn selector top-level                           ---*/
   2712 /*---------------------------------------------------------*/
   2713 
   2714 /* Translate an entire SB to s390 code.
   2715    Note: archinfo_host is a pointer to a stack-allocated variable.
   2716    Do not assign it to a global variable! */
   2717 
   2718 HInstrArray *
   2719 iselSB_S390(IRSB *bb, VexArch arch_host, VexArchInfo *archinfo_host,
   2720             VexAbiInfo *vbi, Int offset_host_evcheck_counter,
   2721             Int offset_host_evcheck_fail_addr, Bool chaining_allowed,
   2722             Bool add_profinc, Addr64 max_ga)
   2723 {
   2724    UInt     i, j;
   2725    HReg     hreg, hregHI;
   2726    ISelEnv *env;
   2727    UInt     hwcaps_host = archinfo_host->hwcaps;
   2728 
   2729    /* KLUDGE: export hwcaps. */
   2730    s390_host_hwcaps = hwcaps_host;
   2731 
   2732    /* Do some sanity checks */
   2733    vassert((VEX_HWCAPS_S390X(hwcaps_host) & ~(VEX_HWCAPS_S390X_ALL)) == 0);
   2734 
   2735    /* Make up an initial environment to use. */
   2736    env = LibVEX_Alloc(sizeof(ISelEnv));
   2737    env->vreg_ctr = 0;
   2738 
   2739    /* Set up output code array. */
   2740    env->code = newHInstrArray();
   2741 
   2742    /* Copy BB's type env. */
   2743    env->type_env = bb->tyenv;
   2744 
   2745    /* Set up data structures for tracking guest register values. */
   2746    env->first_IA_assignment = True;
   2747    for (i = 0; i < NUM_TRACKED_REGS; ++i) {
   2748       env->old_value[i] = 0;  /* just something to have a defined value */
   2749       env->old_value_valid[i] = False;
   2750    }
   2751 
   2752    /* Make up an IRTemp -> virtual HReg mapping.  This doesn't
   2753       change as we go along. For some reason types_used has Int type -- but
   2754       it should be unsigned. Internally we use an unsigned type; so we
   2755       assert it here. */
   2756    vassert(bb->tyenv->types_used >= 0);
   2757 
   2758    env->n_vregmap = bb->tyenv->types_used;
   2759    env->vregmap   = LibVEX_Alloc(env->n_vregmap * sizeof(HReg));
   2760    env->vregmapHI = LibVEX_Alloc(env->n_vregmap * sizeof(HReg));
   2761 
   2762    /* and finally ... */
   2763    env->hwcaps    = hwcaps_host;
   2764 
   2765    env->max_ga = max_ga;
   2766    env->chaining_allowed = chaining_allowed;
   2767 
   2768    /* For each IR temporary, allocate a suitably-kinded virtual
   2769       register. */
   2770    j = 0;
   2771    for (i = 0; i < env->n_vregmap; i++) {
   2772       hregHI = hreg = INVALID_HREG;
   2773       switch (bb->tyenv->types[i]) {
   2774       case Ity_I1:
   2775       case Ity_I8:
   2776       case Ity_I16:
   2777       case Ity_I32:
   2778          hreg = mkHReg(j++, HRcInt64, True);
   2779          break;
   2780 
   2781       case Ity_I64:
   2782          hreg   = mkHReg(j++, HRcInt64, True);
   2783          break;
   2784 
   2785       case Ity_I128:
   2786          hreg   = mkHReg(j++, HRcInt64, True);
   2787          hregHI = mkHReg(j++, HRcInt64, True);
   2788          break;
   2789 
   2790       case Ity_F32:
   2791       case Ity_F64:
   2792          hreg = mkHReg(j++, HRcFlt64, True);
   2793          break;
   2794 
   2795       case Ity_F128:
   2796          hreg   = mkHReg(j++, HRcFlt64, True);
   2797          hregHI = mkHReg(j++, HRcFlt64, True);
   2798          break;
   2799 
   2800       case Ity_V128: /* fall through */
   2801       default:
   2802          ppIRType(bb->tyenv->types[i]);
   2803          vpanic("s390_isel_sb: IRTemp type");
   2804       }
   2805 
   2806       env->vregmap[i]   = hreg;
   2807       env->vregmapHI[i] = hregHI;
   2808    }
   2809    env->vreg_ctr = j;
   2810 
   2811    /* The very first instruction must be an event check. */
   2812    s390_amode *counter, *fail_addr;
   2813    counter   = s390_amode_for_guest_state(offset_host_evcheck_counter);
   2814    fail_addr = s390_amode_for_guest_state(offset_host_evcheck_fail_addr);
   2815    addInstr(env, s390_insn_evcheck(counter, fail_addr));
   2816 
   2817    /* Possibly a block counter increment (for profiling).  At this
   2818       point we don't know the address of the counter, so just pretend
   2819       it is zero.  It will have to be patched later, but before this
   2820       translation is used, by a call to LibVEX_patchProfInc. */
   2821    if (add_profinc) {
   2822       addInstr(env, s390_insn_profinc());
   2823    }
   2824 
   2825    /* Ok, finally we can iterate over the statements. */
   2826    for (i = 0; i < bb->stmts_used; i++)
   2827       if (bb->stmts[i])
   2828          s390_isel_stmt(env, bb->stmts[i]);
   2829 
   2830    iselNext(env, bb->next, bb->jumpkind, bb->offsIP);
   2831 
   2832    /* Record the number of vregs we used. */
   2833    env->code->n_vregs = env->vreg_ctr;
   2834 
   2835    return env->code;
   2836 }
   2837 
   2838 /*---------------------------------------------------------------*/
   2839 /*--- end                                    host_s390_isel.c ---*/
   2840 /*---------------------------------------------------------------*/
   2841