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