Home | History | Annotate | Download | only in priv
      1 /* -*- mode: C; c-basic-offset: 3; -*- */
      2 
      3 /*---------------------------------------------------------------*/
      4 /*--- begin                                  host_s390_defs.c ---*/
      5 /*---------------------------------------------------------------*/
      6 
      7 /*
      8    This file is part of Valgrind, a dynamic binary instrumentation
      9    framework.
     10 
     11    Copyright IBM Corp. 2010-2017
     12    Copyright (C) 2012-2017  Florian Krohm   (britzel (at) acm.org)
     13 
     14    This program is free software; you can redistribute it and/or
     15    modify it under the terms of the GNU General Public License as
     16    published by the Free Software Foundation; either version 2 of the
     17    License, or (at your option) any later version.
     18 
     19    This program is distributed in the hope that it will be useful, but
     20    WITHOUT ANY WARRANTY; without even the implied warranty of
     21    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     22    General Public License for more details.
     23 
     24    You should have received a copy of the GNU General Public License
     25    along with this program; if not, write to the Free Software
     26    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
     27    02110-1301, USA.
     28 
     29    The GNU General Public License is contained in the file COPYING.
     30 */
     31 
     32 /* Contributed by Florian Krohm */
     33 
     34 #include "libvex_basictypes.h"
     35 #include "libvex.h"
     36 #include "libvex_trc_values.h"
     37 #include "libvex_s390x_common.h"
     38 
     39 #include "main_util.h"
     40 #include "main_globals.h"
     41 #include "host_generic_regs.h"
     42 #include "host_s390_defs.h"
     43 #include "s390_disasm.h"
     44 #include "guest_s390_defs.h"    /* S390X_GUEST_OFFSET */
     45 #include <stdarg.h>
     46 
     47 /*------------------------------------------------------------*/
     48 /*--- Forward declarations                                 ---*/
     49 /*------------------------------------------------------------*/
     50 
     51 static Bool s390_insn_is_reg_reg_move(const s390_insn *, HReg *src, HReg *dst);
     52 static void s390_insn_map_regs(HRegRemap *, s390_insn *);
     53 static void s390_insn_get_reg_usage(HRegUsage *u, const s390_insn *);
     54 static UInt s390_tchain_load64_len(void);
     55 
     56 
     57 /*------------------------------------------------------------*/
     58 /*--- Registers                                            ---*/
     59 /*------------------------------------------------------------*/
     60 
     61 /* A mapping from register number to register index */
     62 static Int gpr_index[16];  // GPR regno -> register index
     63 static Int fpr_index[16];  // FPR regno -> register index
     64 
     65 HReg
     66 s390_hreg_gpr(UInt regno)
     67 {
     68    Int ix = gpr_index[regno];
     69    vassert(ix >= 0);
     70    return mkHReg(/*virtual*/False, HRcInt64, regno, ix);
     71 }
     72 
     73 HReg
     74 s390_hreg_fpr(UInt regno)
     75 {
     76    Int ix = fpr_index[regno];
     77    vassert(ix >= 0);
     78    return mkHReg(/*virtual*/False, HRcFlt64, regno, ix);
     79 }
     80 
     81 static __inline__ UInt
     82 hregNumber(HReg reg)
     83 {
     84    return hregEncoding(reg);
     85 }
     86 
     87 /* Decompile the given register into a static buffer and return it */
     88 const HChar *
     89 s390_hreg_as_string(HReg reg)
     90 {
     91    static HChar buf[10];
     92 
     93    static const HChar ireg_names[16][5] = {
     94       "%r0",  "%r1",  "%r2",  "%r3",  "%r4",  "%r5",  "%r6",  "%r7",
     95       "%r8",  "%r9",  "%r10", "%r11", "%r12", "%r13", "%r14", "%r15"
     96    };
     97 
     98    static const HChar freg_names[16][5] = {
     99       "%f0",  "%f1",  "%f2",  "%f3",  "%f4",  "%f5",  "%f6",  "%f7",
    100       "%f8",  "%f9",  "%f10", "%f11", "%f12", "%f13", "%f14", "%f15"
    101    };
    102 
    103    UInt r;  /* hregNumber() returns an UInt */
    104 
    105    r = hregNumber(reg);
    106 
    107    /* Be generic for all virtual regs. */
    108    if (hregIsVirtual(reg)) {
    109       buf[0] = '\0';
    110       switch (hregClass(reg)) {
    111       case HRcInt64: vex_sprintf(buf, "%%vR%u", r); break;
    112       case HRcFlt64: vex_sprintf(buf, "%%vF%u", r); break;
    113       default:       goto fail;
    114       }
    115       return buf;
    116    }
    117 
    118    /* But specific for real regs. */
    119    vassert(r < 16);
    120 
    121    switch (hregClass(reg)) {
    122    case HRcInt64: return ireg_names[r];
    123    case HRcFlt64: return freg_names[r];
    124    default:       goto fail;
    125    }
    126 
    127  fail: vpanic("s390_hreg_as_string");
    128 }
    129 
    130 
    131 /* Return the real register that holds the guest state pointer */
    132 HReg
    133 s390_hreg_guest_state_pointer(void)
    134 {
    135    return s390_hreg_gpr(S390_REGNO_GUEST_STATE_POINTER);
    136 }
    137 
    138 
    139 /* Is VALUE within the domain of a 20-bit signed integer. */
    140 static __inline__ Bool
    141 fits_signed_20bit(Int value)
    142 {
    143    UInt uval = value;
    144    return ((Int)(uval << 12) >> 12) == value;
    145 }
    146 
    147 
    148 /* Is VALUE within the domain of a 12-bit unsigned integer. */
    149 static __inline__ Bool
    150 fits_unsigned_12bit(Int value)
    151 {
    152    return (value & 0xFFF) == value;
    153 }
    154 
    155 /*------------------------------------------------------------*/
    156 /*--- Addressing modes (amodes)                            ---*/
    157 /*------------------------------------------------------------*/
    158 
    159 /* Construct a b12 amode. */
    160 s390_amode *
    161 s390_amode_b12(Int d, HReg b)
    162 {
    163    s390_amode *am = LibVEX_Alloc_inline(sizeof(s390_amode));
    164 
    165    vassert(fits_unsigned_12bit(d));
    166 
    167    am->tag = S390_AMODE_B12;
    168    am->d = d;
    169    am->b = b;
    170    am->x = s390_hreg_gpr(0);  /* hregNumber(am->x) == 0 */
    171 
    172    return am;
    173 }
    174 
    175 
    176 /* Construct a b20 amode. */
    177 s390_amode *
    178 s390_amode_b20(Int d, HReg b)
    179 {
    180    s390_amode *am = LibVEX_Alloc_inline(sizeof(s390_amode));
    181 
    182    vassert(fits_signed_20bit(d));
    183 
    184    am->tag = S390_AMODE_B20;
    185    am->d = d;
    186    am->b = b;
    187    am->x = s390_hreg_gpr(0);  /* hregNumber(am->x) == 0 */
    188 
    189    return am;
    190 }
    191 
    192 
    193 /* Construct a bx12 amode. */
    194 s390_amode *
    195 s390_amode_bx12(Int d, HReg b, HReg x)
    196 {
    197    s390_amode *am = LibVEX_Alloc_inline(sizeof(s390_amode));
    198 
    199    vassert(fits_unsigned_12bit(d));
    200    vassert(hregNumber(b) != 0);
    201    vassert(hregNumber(x) != 0);
    202 
    203    am->tag = S390_AMODE_BX12;
    204    am->d = d;
    205    am->b = b;
    206    am->x = x;
    207 
    208    return am;
    209 }
    210 
    211 
    212 /* Construct a bx20 amode. */
    213 s390_amode *
    214 s390_amode_bx20(Int d, HReg b, HReg x)
    215 {
    216    s390_amode *am = LibVEX_Alloc_inline(sizeof(s390_amode));
    217 
    218    vassert(fits_signed_20bit(d));
    219    vassert(hregNumber(b) != 0);
    220    vassert(hregNumber(x) != 0);
    221 
    222    am->tag = S390_AMODE_BX20;
    223    am->d = d;
    224    am->b = b;
    225    am->x = x;
    226 
    227    return am;
    228 }
    229 
    230 
    231 /* Construct an AMODE for accessing the guest state at OFFSET.
    232    OFFSET can be at most 3 * sizeof(VexGuestS390XState) + LibVEX_N_SPILL_BYTES
    233    which may be too large for a B12 addressing mode.
    234    Use a B20 amode as a fallback which will be safe for any offset.
    235 */
    236 s390_amode *
    237 s390_amode_for_guest_state(Int offset)
    238 {
    239    if (fits_unsigned_12bit(offset))
    240       return s390_amode_b12(offset, s390_hreg_guest_state_pointer());
    241 
    242    if (fits_signed_20bit(offset))
    243       return s390_amode_b20(offset, s390_hreg_guest_state_pointer());
    244 
    245    vpanic("invalid guest state offset");
    246 }
    247 
    248 
    249 /* Decompile the given amode into a static buffer and return it. */
    250 const HChar *
    251 s390_amode_as_string(const s390_amode *am)
    252 {
    253    static HChar buf[30];
    254    HChar *p;
    255 
    256    buf[0] = '\0';
    257    p = buf;
    258 
    259    switch (am->tag) {
    260    case S390_AMODE_B12:
    261    case S390_AMODE_B20:
    262       vex_sprintf(p, "%d(%s)", am->d, s390_hreg_as_string(am->b));
    263       break;
    264 
    265    case S390_AMODE_BX12:
    266    case S390_AMODE_BX20:
    267       /* s390_hreg_as_string returns pointer to local buffer. Need to
    268          split this into two printfs */
    269       p += vex_sprintf(p, "%d(%s,", am->d, s390_hreg_as_string(am->x));
    270       vex_sprintf(p, "%s)", s390_hreg_as_string(am->b));
    271       break;
    272 
    273    default:
    274       vpanic("s390_amode_as_string");
    275    }
    276 
    277    return buf;
    278 }
    279 
    280 
    281 /* Helper function for s390_amode_is_sane */
    282 static __inline__ Bool
    283 is_virtual_gpr(HReg reg)
    284 {
    285    return hregIsVirtual(reg) && hregClass(reg) == HRcInt64;
    286 }
    287 
    288 
    289 /* Sanity check for an amode */
    290 Bool
    291 s390_amode_is_sane(const s390_amode *am)
    292 {
    293    switch (am->tag) {
    294    case S390_AMODE_B12:
    295       return is_virtual_gpr(am->b) && fits_unsigned_12bit(am->d);
    296 
    297    case S390_AMODE_B20:
    298       return is_virtual_gpr(am->b) && fits_signed_20bit(am->d);
    299 
    300    case S390_AMODE_BX12:
    301       return is_virtual_gpr(am->b) && is_virtual_gpr(am->x) &&
    302              fits_unsigned_12bit(am->d);
    303 
    304    case S390_AMODE_BX20:
    305       return is_virtual_gpr(am->b) && is_virtual_gpr(am->x) &&
    306              fits_signed_20bit(am->d);
    307 
    308    default:
    309       vpanic("s390_amode_is_sane");
    310    }
    311 }
    312 
    313 
    314 /* Record the register use of an amode */
    315 static void
    316 s390_amode_get_reg_usage(HRegUsage *u, const s390_amode *am)
    317 {
    318    switch (am->tag) {
    319    case S390_AMODE_B12:
    320    case S390_AMODE_B20:
    321       addHRegUse(u, HRmRead, am->b);
    322       return;
    323 
    324    case S390_AMODE_BX12:
    325    case S390_AMODE_BX20:
    326       addHRegUse(u, HRmRead, am->b);
    327       addHRegUse(u, HRmRead, am->x);
    328       return;
    329 
    330    default:
    331       vpanic("s390_amode_get_reg_usage");
    332    }
    333 }
    334 
    335 
    336 static void
    337 s390_amode_map_regs(HRegRemap *m, s390_amode *am)
    338 {
    339    switch (am->tag) {
    340    case S390_AMODE_B12:
    341    case S390_AMODE_B20:
    342       am->b = lookupHRegRemap(m, am->b);
    343       return;
    344 
    345    case S390_AMODE_BX12:
    346    case S390_AMODE_BX20:
    347       am->b = lookupHRegRemap(m, am->b);
    348       am->x = lookupHRegRemap(m, am->x);
    349       return;
    350 
    351    default:
    352       vpanic("s390_amode_map_regs");
    353    }
    354 }
    355 
    356 
    357 void
    358 ppS390AMode(const s390_amode *am)
    359 {
    360    vex_printf("%s", s390_amode_as_string(am));
    361 }
    362 
    363 void
    364 ppS390Instr(const s390_insn *insn, Bool mode64)
    365 {
    366    vex_printf("%s", s390_insn_as_string(insn));
    367 }
    368 
    369 void
    370 ppHRegS390(HReg reg)
    371 {
    372    vex_printf("%s", s390_hreg_as_string(reg));
    373 }
    374 
    375 /*------------------------------------------------------------*/
    376 /*--- Helpers for register allocation                      ---*/
    377 /*------------------------------------------------------------*/
    378 
    379 /* Initialise and return the "register universe", i.e. a list of
    380    all hardware registers. Called once. */
    381 const RRegUniverse *
    382 getRRegUniverse_S390(void)
    383 {
    384    static RRegUniverse all_regs;
    385    static Bool initialised = False;
    386    RRegUniverse *ru = &all_regs;
    387 
    388    if (LIKELY(initialised))
    389       return ru;
    390 
    391    RRegUniverse__init(ru);
    392 
    393    /* Assign invalid values to the gpr/fpr_index */
    394    for (UInt i = 0; i < sizeof gpr_index / sizeof gpr_index[0]; ++i)
    395       gpr_index[i] = -1;
    396    for (UInt i = 0; i < sizeof fpr_index / sizeof fpr_index[0]; ++i)
    397       fpr_index[i] = -1;
    398 
    399    /* Add the registers that are available to the register allocator.
    400       GPRs:  registers 1..11 are available
    401       FPRs:  registers 0..15 are available
    402              FPR12 - FPR15 are also used as register pairs for 128-bit
    403              floating point operations
    404    */
    405    UInt regno;
    406    for (regno = 1; regno <= 11; ++regno) {
    407       gpr_index[regno] = ru->size;
    408       ru->regs[ru->size++] = s390_hreg_gpr(regno);
    409    }
    410    for (regno = 0; regno <= 15; ++regno) {
    411       fpr_index[regno] = ru->size;
    412       ru->regs[ru->size++] = s390_hreg_fpr(regno);
    413    }
    414    ru->allocable = ru->size;
    415 
    416    /* Add the registers that are not available for allocation.
    417       r0  -- cannot be used as a base or index register
    418       r12 -- scratch register for translation chaining support
    419       r13 -- guest state pointer
    420       r14 -- link register
    421       r15 -- stack pointer
    422    */
    423    UInt other[] = { 0, 12, 13, 14, 15 };
    424    for (UInt i = 0; i < sizeof other / sizeof other[0]; ++i) {
    425       gpr_index[other[i]] = ru->size;
    426       ru->regs[ru->size++] = s390_hreg_gpr(other[i]);
    427    }
    428 
    429    /* Sanity checking */
    430    for (UInt i = 0; i < sizeof gpr_index / sizeof gpr_index[0]; ++i)
    431       vassert(gpr_index[i] >= 0);
    432    for (UInt i = 0; i < sizeof fpr_index / sizeof fpr_index[0]; ++i)
    433       vassert(fpr_index[i] >= 0);
    434 
    435    initialised = True;
    436    return ru;
    437 }
    438 
    439 /* Tell the register allocator how the given instruction uses the registers
    440    it refers to. */
    441 void
    442 getRegUsage_S390Instr(HRegUsage *u, const s390_insn *insn, Bool mode64)
    443 {
    444    s390_insn_get_reg_usage(u, insn);
    445 }
    446 
    447 
    448 /* Map the registers of the given instruction */
    449 void
    450 mapRegs_S390Instr(HRegRemap *m, s390_insn *insn, Bool mode64)
    451 {
    452    s390_insn_map_regs(m, insn);
    453 }
    454 
    455 
    456 /* Figure out if the given insn represents a reg-reg move, and if so
    457    assign the source and destination to *src and *dst.  If in doubt say No.
    458    Used by the register allocator to do move coalescing. */
    459 Bool
    460 isMove_S390Instr(const s390_insn *insn, HReg *src, HReg *dst)
    461 {
    462    return s390_insn_is_reg_reg_move(insn, src, dst);
    463 }
    464 
    465 
    466 /* Generate s390 spill/reload instructions under the direction of the
    467    register allocator.  Note it's critical these don't write the
    468    condition codes. This is like an Ist_Put */
    469 void
    470 genSpill_S390(HInstr **i1, HInstr **i2, HReg rreg, Int offsetB, Bool mode64)
    471 {
    472    s390_amode *am;
    473 
    474    vassert(offsetB >= 0);
    475    vassert(!hregIsVirtual(rreg));
    476 
    477    *i1 = *i2 = NULL;
    478 
    479    am = s390_amode_for_guest_state(offsetB);
    480 
    481    switch (hregClass(rreg)) {
    482    case HRcInt64:
    483    case HRcFlt64:
    484       *i1 = s390_insn_store(8, am, rreg);
    485       return;
    486 
    487    default:
    488       ppHRegClass(hregClass(rreg));
    489       vpanic("genSpill_S390: unimplemented regclass");
    490    }
    491 }
    492 
    493 
    494 /* This is like an Iex_Get */
    495 void
    496 genReload_S390(HInstr **i1, HInstr **i2, HReg rreg, Int offsetB, Bool mode64)
    497 {
    498    s390_amode *am;
    499 
    500    vassert(offsetB >= 0);
    501    vassert(!hregIsVirtual(rreg));
    502 
    503    *i1 = *i2 = NULL;
    504 
    505    am = s390_amode_for_guest_state(offsetB);
    506 
    507    switch (hregClass(rreg)) {
    508    case HRcInt64:
    509    case HRcFlt64:
    510       *i1 = s390_insn_load(8, rreg, am);
    511       return;
    512 
    513    default:
    514       ppHRegClass(hregClass(rreg));
    515       vpanic("genReload_S390: unimplemented regclass");
    516    }
    517 }
    518 
    519 /* Helper function for s390_insn_get_reg_usage */
    520 static void
    521 s390_opnd_RMI_get_reg_usage(HRegUsage *u, s390_opnd_RMI op)
    522 {
    523    switch (op.tag) {
    524    case S390_OPND_REG:
    525       addHRegUse(u, HRmRead, op.variant.reg);
    526       break;
    527 
    528    case S390_OPND_AMODE:
    529       s390_amode_get_reg_usage(u, op.variant.am);
    530       break;
    531 
    532    case S390_OPND_IMMEDIATE:
    533       break;
    534 
    535    default:
    536       vpanic("s390_opnd_RMI_get_reg_usage");
    537    }
    538 }
    539 
    540 
    541 /* Tell the register allocator how the given insn uses the registers */
    542 static void
    543 s390_insn_get_reg_usage(HRegUsage *u, const s390_insn *insn)
    544 {
    545    initHRegUsage(u);
    546 
    547    switch (insn->tag) {
    548    case S390_INSN_LOAD:
    549       addHRegUse(u, HRmWrite, insn->variant.load.dst);
    550       s390_amode_get_reg_usage(u, insn->variant.load.src);
    551       break;
    552 
    553    case S390_INSN_LOAD_IMMEDIATE:
    554       addHRegUse(u, HRmWrite, insn->variant.load_immediate.dst);
    555       break;
    556 
    557    case S390_INSN_STORE:
    558       addHRegUse(u, HRmRead, insn->variant.store.src);
    559       s390_amode_get_reg_usage(u, insn->variant.store.dst);
    560       break;
    561 
    562    case S390_INSN_MOVE:
    563       addHRegUse(u, HRmRead,  insn->variant.move.src);
    564       addHRegUse(u, HRmWrite, insn->variant.move.dst);
    565       break;
    566 
    567    case S390_INSN_MEMCPY:
    568       s390_amode_get_reg_usage(u, insn->variant.memcpy.src);
    569       s390_amode_get_reg_usage(u, insn->variant.memcpy.dst);
    570       break;
    571 
    572    case S390_INSN_COND_MOVE:
    573       s390_opnd_RMI_get_reg_usage(u, insn->variant.cond_move.src);
    574       addHRegUse(u, HRmWrite, insn->variant.cond_move.dst);
    575       break;
    576 
    577    case S390_INSN_ALU:
    578       addHRegUse(u, HRmWrite, insn->variant.alu.dst);
    579       addHRegUse(u, HRmRead,  insn->variant.alu.dst);  /* op1 */
    580       s390_opnd_RMI_get_reg_usage(u, insn->variant.alu.op2);
    581       break;
    582 
    583    case S390_INSN_SMUL:
    584    case S390_INSN_UMUL:
    585       addHRegUse(u, HRmRead,  insn->variant.mul.dst_lo);  /* op1 */
    586       addHRegUse(u, HRmWrite, insn->variant.mul.dst_lo);
    587       addHRegUse(u, HRmWrite, insn->variant.mul.dst_hi);
    588       s390_opnd_RMI_get_reg_usage(u, insn->variant.mul.op2);
    589       break;
    590 
    591    case S390_INSN_SDIV:
    592    case S390_INSN_UDIV:
    593       addHRegUse(u, HRmRead,  insn->variant.div.op1_lo);
    594       addHRegUse(u, HRmRead,  insn->variant.div.op1_hi);
    595       addHRegUse(u, HRmWrite, insn->variant.div.op1_lo);
    596       addHRegUse(u, HRmWrite, insn->variant.div.op1_hi);
    597       s390_opnd_RMI_get_reg_usage(u, insn->variant.div.op2);
    598       break;
    599 
    600    case S390_INSN_DIVS:
    601       addHRegUse(u, HRmRead,  insn->variant.divs.op1);
    602       addHRegUse(u, HRmWrite, insn->variant.divs.op1); /* quotient */
    603       addHRegUse(u, HRmWrite, insn->variant.divs.rem); /* remainder */
    604       s390_opnd_RMI_get_reg_usage(u, insn->variant.divs.op2);
    605       break;
    606 
    607    case S390_INSN_CLZ:
    608       addHRegUse(u, HRmWrite, insn->variant.clz.num_bits);
    609       addHRegUse(u, HRmWrite, insn->variant.clz.clobber);
    610       s390_opnd_RMI_get_reg_usage(u, insn->variant.clz.src);
    611       break;
    612 
    613    case S390_INSN_UNOP:
    614       addHRegUse(u, HRmWrite, insn->variant.unop.dst);
    615       s390_opnd_RMI_get_reg_usage(u, insn->variant.unop.src);
    616       break;
    617 
    618    case S390_INSN_TEST:
    619       s390_opnd_RMI_get_reg_usage(u, insn->variant.test.src);
    620       break;
    621 
    622    case S390_INSN_CC2BOOL:
    623       addHRegUse(u, HRmWrite, insn->variant.cc2bool.dst);
    624       break;
    625 
    626    case S390_INSN_CAS:
    627       addHRegUse(u, HRmRead,  insn->variant.cas.op1);
    628       s390_amode_get_reg_usage(u, insn->variant.cas.op2);
    629       addHRegUse(u, HRmRead,  insn->variant.cas.op3);
    630       addHRegUse(u, HRmWrite,  insn->variant.cas.old_mem);
    631       break;
    632 
    633    case S390_INSN_CDAS: {
    634       s390_cdas *cdas = insn->variant.cdas.details;
    635 
    636       addHRegUse(u, HRmRead,  cdas->op1_high);
    637       addHRegUse(u, HRmRead,  cdas->op1_low);
    638       s390_amode_get_reg_usage(u, cdas->op2);
    639       addHRegUse(u, HRmRead,  cdas->op3_high);
    640       addHRegUse(u, HRmRead,  cdas->op3_low);
    641       addHRegUse(u, HRmWrite, cdas->old_mem_high);
    642       addHRegUse(u, HRmWrite, cdas->old_mem_low);
    643       addHRegUse(u, HRmWrite, cdas->scratch);
    644       break;
    645    }
    646 
    647    case S390_INSN_COMPARE:
    648       addHRegUse(u, HRmRead, insn->variant.compare.src1);
    649       s390_opnd_RMI_get_reg_usage(u, insn->variant.compare.src2);
    650       break;
    651 
    652    case S390_INSN_HELPER_CALL: {
    653       UInt i;
    654 
    655       /* Assume that all volatile registers are clobbered. ABI says,
    656          volatile registers are: r0 - r5. Valgrind's register allocator
    657          does not know about r0, so we can leave that out */
    658       for (i = 1; i <= 5; ++i) {
    659          addHRegUse(u, HRmWrite, s390_hreg_gpr(i));
    660       }
    661 
    662       /* Ditto for floating point registers. f0 - f7 are volatile */
    663       for (i = 0; i <= 7; ++i) {
    664          addHRegUse(u, HRmWrite, s390_hreg_fpr(i));
    665       }
    666 
    667       /* The registers that are used for passing arguments will be read.
    668          Not all of them may, but in general we need to assume that. */
    669       for (i = 0; i < insn->variant.helper_call.details->num_args; ++i) {
    670          addHRegUse(u, HRmRead, s390_hreg_gpr(s390_gprno_from_arg_index(i)));
    671       }
    672 
    673       /* s390_insn_helper_call_emit also reads / writes the link register
    674          and stack pointer. But those registers are not visible to the
    675          register allocator. So we don't need to do anything for them. */
    676       break;
    677    }
    678 
    679    case S390_INSN_BFP_TRIOP:
    680       addHRegUse(u, HRmWrite, insn->variant.bfp_triop.dst);
    681       addHRegUse(u, HRmRead,  insn->variant.bfp_triop.dst);  /* first */
    682       addHRegUse(u, HRmRead,  insn->variant.bfp_triop.op2);  /* second */
    683       addHRegUse(u, HRmRead,  insn->variant.bfp_triop.op3);  /* third */
    684       break;
    685 
    686    case S390_INSN_BFP_BINOP:
    687       addHRegUse(u, HRmWrite, insn->variant.bfp_binop.dst_hi);
    688       addHRegUse(u, HRmRead,  insn->variant.bfp_binop.dst_hi);  /* left */
    689       addHRegUse(u, HRmRead,  insn->variant.bfp_binop.op2_hi);  /* right */
    690       if (insn->size == 16) {
    691          addHRegUse(u, HRmWrite, insn->variant.bfp_binop.dst_lo);
    692          addHRegUse(u, HRmRead,  insn->variant.bfp_binop.dst_lo);  /* left */
    693          addHRegUse(u, HRmRead,  insn->variant.bfp_binop.op2_lo);  /* right */
    694       }
    695       break;
    696 
    697    case S390_INSN_BFP_UNOP:
    698       addHRegUse(u, HRmWrite, insn->variant.bfp_unop.dst_hi);
    699       addHRegUse(u, HRmRead,  insn->variant.bfp_unop.op_hi);  /* operand */
    700       if (insn->size == 16) {
    701          addHRegUse(u, HRmWrite, insn->variant.bfp_unop.dst_lo);
    702          addHRegUse(u, HRmRead,  insn->variant.bfp_unop.op_lo);  /* operand */
    703       }
    704       break;
    705 
    706    case S390_INSN_BFP_COMPARE:
    707       addHRegUse(u, HRmWrite, insn->variant.bfp_compare.dst);
    708       addHRegUse(u, HRmRead,  insn->variant.bfp_compare.op1_hi);  /* left */
    709       addHRegUse(u, HRmRead,  insn->variant.bfp_compare.op2_hi);  /* right */
    710       if (insn->size == 16) {
    711          addHRegUse(u, HRmRead,  insn->variant.bfp_compare.op1_lo);  /* left */
    712          addHRegUse(u, HRmRead,  insn->variant.bfp_compare.op2_lo);  /* right */
    713       }
    714       break;
    715 
    716    case S390_INSN_BFP_CONVERT:
    717       addHRegUse(u, HRmWrite, insn->variant.bfp_convert.dst_hi);
    718       if (! hregIsInvalid(insn->variant.bfp_convert.dst_lo))
    719          addHRegUse(u, HRmWrite, insn->variant.bfp_convert.dst_lo);
    720       addHRegUse(u, HRmRead,  insn->variant.bfp_convert.op_hi);
    721       if (! hregIsInvalid(insn->variant.bfp_convert.op_lo))
    722          addHRegUse(u, HRmRead, insn->variant.bfp_convert.op_lo);
    723       break;
    724 
    725    case S390_INSN_DFP_BINOP: {
    726       s390_dfp_binop *dfp_binop = insn->variant.dfp_binop.details;
    727 
    728       addHRegUse(u, HRmWrite, dfp_binop->dst_hi);
    729       addHRegUse(u, HRmRead,  dfp_binop->op2_hi);  /* left */
    730       addHRegUse(u, HRmRead,  dfp_binop->op3_hi);  /* right */
    731       if (insn->size == 16) {
    732          addHRegUse(u, HRmWrite, dfp_binop->dst_lo);
    733          addHRegUse(u, HRmRead,  dfp_binop->op2_lo);  /* left */
    734          addHRegUse(u, HRmRead,  dfp_binop->op3_lo);  /* right */
    735       }
    736       break;
    737    }
    738 
    739    case S390_INSN_DFP_UNOP:
    740       addHRegUse(u, HRmWrite, insn->variant.dfp_unop.dst_hi);
    741       addHRegUse(u, HRmRead,  insn->variant.dfp_unop.op_hi);  /* operand */
    742       if (insn->size == 16) {
    743          addHRegUse(u, HRmWrite, insn->variant.dfp_unop.dst_lo);
    744          addHRegUse(u, HRmRead,  insn->variant.dfp_unop.op_lo);  /* operand */
    745       }
    746       break;
    747 
    748    case S390_INSN_DFP_INTOP:
    749       addHRegUse(u, HRmWrite, insn->variant.dfp_intop.dst_hi);
    750       addHRegUse(u, HRmRead,  insn->variant.dfp_intop.op2);
    751       addHRegUse(u, HRmRead,  insn->variant.dfp_intop.op3_hi);
    752       if (insn->size == 16) {
    753          addHRegUse(u, HRmWrite, insn->variant.dfp_intop.dst_lo);
    754          addHRegUse(u, HRmRead,  insn->variant.dfp_intop.op3_lo);
    755       }
    756       break;
    757 
    758    case S390_INSN_DFP_COMPARE:
    759       addHRegUse(u, HRmWrite, insn->variant.dfp_compare.dst);
    760       addHRegUse(u, HRmRead,  insn->variant.dfp_compare.op1_hi);  /* left */
    761       addHRegUse(u, HRmRead,  insn->variant.dfp_compare.op2_hi);  /* right */
    762       if (insn->size == 16) {
    763          addHRegUse(u, HRmRead,  insn->variant.dfp_compare.op1_lo);  /* left */
    764          addHRegUse(u, HRmRead,  insn->variant.dfp_compare.op2_lo);  /* right */
    765       }
    766       break;
    767 
    768    case S390_INSN_DFP_CONVERT:
    769       addHRegUse(u, HRmWrite, insn->variant.dfp_convert.dst_hi);
    770       if (! hregIsInvalid(insn->variant.dfp_convert.dst_lo))
    771          addHRegUse(u, HRmWrite, insn->variant.dfp_convert.dst_lo);
    772       addHRegUse(u, HRmRead,  insn->variant.dfp_convert.op_hi);  /* operand */
    773       if (! hregIsInvalid(insn->variant.dfp_convert.op_lo))
    774          addHRegUse(u, HRmRead, insn->variant.dfp_convert.op_lo); /* operand */
    775       break;
    776 
    777    case S390_INSN_DFP_REROUND:
    778       addHRegUse(u, HRmWrite, insn->variant.dfp_reround.dst_hi);
    779       addHRegUse(u, HRmRead,  insn->variant.dfp_reround.op2);     /* left */
    780       addHRegUse(u, HRmRead,  insn->variant.dfp_reround.op3_hi);  /* right */
    781       if (insn->size == 16) {
    782          addHRegUse(u, HRmWrite, insn->variant.dfp_reround.dst_lo);
    783          addHRegUse(u, HRmRead,  insn->variant.dfp_reround.op3_lo); /* right */
    784       }
    785       break;
    786 
    787    case S390_INSN_FP_CONVERT: {
    788       s390_fp_convert *fp_convert = insn->variant.fp_convert.details;
    789 
    790       addHRegUse(u, HRmWrite, fp_convert->dst_hi);
    791       if (! hregIsInvalid(fp_convert->dst_lo))
    792          addHRegUse(u, HRmWrite, fp_convert->dst_lo);
    793       addHRegUse(u, HRmRead,  fp_convert->op_hi);
    794       if (! hregIsInvalid(fp_convert->op_lo))
    795          addHRegUse(u, HRmRead, fp_convert->op_lo);
    796       addHRegUse(u, HRmWrite, fp_convert->r1);
    797       break;
    798    }
    799 
    800    case S390_INSN_MIMM:
    801       s390_amode_get_reg_usage(u, insn->variant.mimm.dst);
    802       break;
    803 
    804    case S390_INSN_MADD:
    805       s390_amode_get_reg_usage(u, insn->variant.madd.dst);
    806       break;
    807 
    808    case S390_INSN_MFENCE:
    809       break;
    810 
    811    case S390_INSN_SET_FPC_BFPRM:
    812       addHRegUse(u, HRmRead,  insn->variant.set_fpc_bfprm.mode);
    813       break;
    814 
    815    case S390_INSN_SET_FPC_DFPRM:
    816       addHRegUse(u, HRmRead,  insn->variant.set_fpc_dfprm.mode);
    817       break;
    818 
    819    case S390_INSN_EVCHECK:
    820       s390_amode_get_reg_usage(u, insn->variant.evcheck.counter);
    821       s390_amode_get_reg_usage(u, insn->variant.evcheck.fail_addr);
    822       break;
    823 
    824    case S390_INSN_PROFINC:
    825       /* Does not use any register visible to the register allocator */
    826       break;
    827 
    828    case S390_INSN_XDIRECT:
    829       s390_amode_get_reg_usage(u, insn->variant.xdirect.guest_IA);
    830       break;
    831 
    832    case S390_INSN_XINDIR:
    833       addHRegUse(u, HRmRead, insn->variant.xindir.dst);
    834       s390_amode_get_reg_usage(u, insn->variant.xindir.guest_IA);
    835       break;
    836 
    837    case S390_INSN_XASSISTED:
    838       addHRegUse(u, HRmRead, insn->variant.xassisted.dst);
    839       s390_amode_get_reg_usage(u, insn->variant.xassisted.guest_IA);
    840       break;
    841 
    842    default:
    843       vpanic("s390_insn_get_reg_usage");
    844    }
    845 }
    846 
    847 
    848 /* Helper function for s390_insn_map_regs */
    849 static void
    850 s390_opnd_RMI_map_regs(HRegRemap *m, s390_opnd_RMI *op)
    851 {
    852    switch (op->tag) {
    853    case S390_OPND_REG:
    854       op->variant.reg = lookupHRegRemap(m, op->variant.reg);
    855       break;
    856 
    857    case S390_OPND_IMMEDIATE:
    858       break;
    859 
    860    case S390_OPND_AMODE:
    861       s390_amode_map_regs(m, op->variant.am);
    862       break;
    863 
    864    default:
    865       vpanic("s390_opnd_RMI_map_regs");
    866    }
    867 }
    868 
    869 
    870 static void
    871 s390_insn_map_regs(HRegRemap *m, s390_insn *insn)
    872 {
    873    switch (insn->tag) {
    874    case S390_INSN_LOAD:
    875       insn->variant.load.dst = lookupHRegRemap(m, insn->variant.load.dst);
    876       s390_amode_map_regs(m, insn->variant.load.src);
    877       break;
    878 
    879    case S390_INSN_STORE:
    880       s390_amode_map_regs(m, insn->variant.store.dst);
    881       insn->variant.store.src = lookupHRegRemap(m, insn->variant.store.src);
    882       break;
    883 
    884    case S390_INSN_MOVE:
    885       insn->variant.move.dst = lookupHRegRemap(m, insn->variant.move.dst);
    886       insn->variant.move.src = lookupHRegRemap(m, insn->variant.move.src);
    887       break;
    888 
    889    case S390_INSN_MEMCPY:
    890       s390_amode_map_regs(m, insn->variant.memcpy.dst);
    891       s390_amode_map_regs(m, insn->variant.memcpy.src);
    892       break;
    893 
    894    case S390_INSN_COND_MOVE:
    895       insn->variant.cond_move.dst = lookupHRegRemap(m, insn->variant.cond_move.dst);
    896       s390_opnd_RMI_map_regs(m, &insn->variant.cond_move.src);
    897       break;
    898 
    899    case S390_INSN_LOAD_IMMEDIATE:
    900       insn->variant.load_immediate.dst =
    901          lookupHRegRemap(m, insn->variant.load_immediate.dst);
    902       break;
    903 
    904    case S390_INSN_ALU:
    905       insn->variant.alu.dst = lookupHRegRemap(m, insn->variant.alu.dst);
    906       s390_opnd_RMI_map_regs(m, &insn->variant.alu.op2);
    907       break;
    908 
    909    case S390_INSN_SMUL:
    910    case S390_INSN_UMUL:
    911       insn->variant.mul.dst_hi = lookupHRegRemap(m, insn->variant.mul.dst_hi);
    912       insn->variant.mul.dst_lo = lookupHRegRemap(m, insn->variant.mul.dst_lo);
    913       s390_opnd_RMI_map_regs(m, &insn->variant.mul.op2);
    914       break;
    915 
    916    case S390_INSN_SDIV:
    917    case S390_INSN_UDIV:
    918       insn->variant.div.op1_hi = lookupHRegRemap(m, insn->variant.div.op1_hi);
    919       insn->variant.div.op1_lo = lookupHRegRemap(m, insn->variant.div.op1_lo);
    920       s390_opnd_RMI_map_regs(m, &insn->variant.div.op2);
    921       break;
    922 
    923    case S390_INSN_DIVS:
    924       insn->variant.divs.op1 = lookupHRegRemap(m, insn->variant.divs.op1);
    925       insn->variant.divs.rem = lookupHRegRemap(m, insn->variant.divs.rem);
    926       s390_opnd_RMI_map_regs(m, &insn->variant.divs.op2);
    927       break;
    928 
    929    case S390_INSN_CLZ:
    930       insn->variant.clz.num_bits = lookupHRegRemap(m, insn->variant.clz.num_bits);
    931       insn->variant.clz.clobber  = lookupHRegRemap(m, insn->variant.clz.clobber);
    932       s390_opnd_RMI_map_regs(m, &insn->variant.clz.src);
    933       break;
    934 
    935    case S390_INSN_UNOP:
    936       insn->variant.unop.dst = lookupHRegRemap(m, insn->variant.unop.dst);
    937       s390_opnd_RMI_map_regs(m, &insn->variant.unop.src);
    938       break;
    939 
    940    case S390_INSN_TEST:
    941       s390_opnd_RMI_map_regs(m, &insn->variant.test.src);
    942       break;
    943 
    944    case S390_INSN_CC2BOOL:
    945       insn->variant.cc2bool.dst = lookupHRegRemap(m, insn->variant.cc2bool.dst);
    946       break;
    947 
    948    case S390_INSN_CAS:
    949       insn->variant.cas.op1 = lookupHRegRemap(m, insn->variant.cas.op1);
    950       s390_amode_map_regs(m, insn->variant.cas.op2);
    951       insn->variant.cas.op3 = lookupHRegRemap(m, insn->variant.cas.op3);
    952       insn->variant.cas.old_mem = lookupHRegRemap(m, insn->variant.cas.old_mem);
    953       break;
    954 
    955    case S390_INSN_CDAS: {
    956       s390_cdas *cdas = insn->variant.cdas.details;
    957 
    958       cdas->op1_high = lookupHRegRemap(m, cdas->op1_high);
    959       cdas->op1_low  = lookupHRegRemap(m, cdas->op1_low);
    960       s390_amode_map_regs(m, cdas->op2);
    961       cdas->op3_high = lookupHRegRemap(m, cdas->op3_high);
    962       cdas->op3_low  = lookupHRegRemap(m, cdas->op3_low);
    963       cdas->old_mem_high = lookupHRegRemap(m, cdas->old_mem_high);
    964       cdas->old_mem_low  = lookupHRegRemap(m, cdas->old_mem_low);
    965       cdas->scratch  = lookupHRegRemap(m, cdas->scratch);
    966       break;
    967    }
    968 
    969    case S390_INSN_COMPARE:
    970       insn->variant.compare.src1 = lookupHRegRemap(m, insn->variant.compare.src1);
    971       s390_opnd_RMI_map_regs(m, &insn->variant.compare.src2);
    972       break;
    973 
    974    case S390_INSN_HELPER_CALL:
    975       /* s390_insn_helper_call_emit also reads / writes the link register
    976          and stack pointer. But those registers are not visible to the
    977          register allocator. So we don't need to do anything for them.
    978          As for the arguments of the helper call -- they will be loaded into
    979          non-virtual registers. Again, we don't need to do anything for those
    980          here. */
    981       break;
    982 
    983    case S390_INSN_BFP_TRIOP:
    984       insn->variant.bfp_triop.dst =
    985          lookupHRegRemap(m, insn->variant.bfp_triop.dst);
    986       insn->variant.bfp_triop.op2 =
    987          lookupHRegRemap(m, insn->variant.bfp_triop.op2);
    988       insn->variant.bfp_triop.op3 =
    989          lookupHRegRemap(m, insn->variant.bfp_triop.op3);
    990       break;
    991 
    992    case S390_INSN_BFP_BINOP:
    993       insn->variant.bfp_binop.dst_hi =
    994          lookupHRegRemap(m, insn->variant.bfp_binop.dst_hi);
    995       insn->variant.bfp_binop.op2_hi =
    996          lookupHRegRemap(m, insn->variant.bfp_binop.op2_hi);
    997       if (insn->size == 16) {
    998          insn->variant.bfp_binop.dst_lo =
    999             lookupHRegRemap(m, insn->variant.bfp_binop.dst_lo);
   1000          insn->variant.bfp_binop.op2_lo  =
   1001             lookupHRegRemap(m, insn->variant.bfp_binop.op2_lo);
   1002       }
   1003       break;
   1004 
   1005    case S390_INSN_BFP_UNOP:
   1006       insn->variant.bfp_unop.dst_hi =
   1007          lookupHRegRemap(m, insn->variant.bfp_unop.dst_hi);
   1008       insn->variant.bfp_unop.op_hi  =
   1009          lookupHRegRemap(m, insn->variant.bfp_unop.op_hi);
   1010       if (insn->size == 16) {
   1011          insn->variant.bfp_unop.dst_lo =
   1012             lookupHRegRemap(m, insn->variant.bfp_unop.dst_lo);
   1013          insn->variant.bfp_unop.op_lo  =
   1014             lookupHRegRemap(m, insn->variant.bfp_unop.op_lo);
   1015       }
   1016       break;
   1017 
   1018    case S390_INSN_BFP_COMPARE:
   1019       insn->variant.bfp_compare.dst =
   1020          lookupHRegRemap(m, insn->variant.bfp_compare.dst);
   1021       insn->variant.bfp_compare.op1_hi =
   1022          lookupHRegRemap(m, insn->variant.bfp_compare.op1_hi);
   1023       insn->variant.bfp_compare.op2_hi =
   1024          lookupHRegRemap(m, insn->variant.bfp_compare.op2_hi);
   1025       if (insn->size == 16) {
   1026          insn->variant.bfp_compare.op1_lo =
   1027             lookupHRegRemap(m, insn->variant.bfp_compare.op1_lo);
   1028          insn->variant.bfp_compare.op2_lo =
   1029             lookupHRegRemap(m, insn->variant.bfp_compare.op2_lo);
   1030       }
   1031       break;
   1032 
   1033    case S390_INSN_BFP_CONVERT:
   1034       insn->variant.bfp_convert.dst_hi =
   1035          lookupHRegRemap(m, insn->variant.bfp_convert.dst_hi);
   1036       if (! hregIsInvalid(insn->variant.bfp_convert.dst_lo))
   1037          insn->variant.bfp_convert.dst_lo =
   1038             lookupHRegRemap(m, insn->variant.bfp_convert.dst_lo);
   1039       insn->variant.bfp_convert.op_hi =
   1040          lookupHRegRemap(m, insn->variant.bfp_convert.op_hi);
   1041       if (! hregIsInvalid(insn->variant.bfp_convert.op_lo))
   1042          insn->variant.bfp_convert.op_lo =
   1043             lookupHRegRemap(m, insn->variant.bfp_convert.op_lo);
   1044       break;
   1045 
   1046    case S390_INSN_DFP_BINOP: {
   1047       s390_dfp_binop *dfp_binop = insn->variant.dfp_binop.details;
   1048 
   1049       dfp_binop->dst_hi = lookupHRegRemap(m, dfp_binop->dst_hi);
   1050       dfp_binop->op2_hi = lookupHRegRemap(m, dfp_binop->op2_hi);
   1051       dfp_binop->op3_hi = lookupHRegRemap(m, dfp_binop->op3_hi);
   1052       if (insn->size == 16) {
   1053          dfp_binop->dst_lo = lookupHRegRemap(m, dfp_binop->dst_lo);
   1054          dfp_binop->op2_lo = lookupHRegRemap(m, dfp_binop->op2_lo);
   1055          dfp_binop->op3_lo = lookupHRegRemap(m, dfp_binop->op3_lo);
   1056       }
   1057       break;
   1058    }
   1059 
   1060    case S390_INSN_DFP_UNOP:
   1061       insn->variant.dfp_unop.dst_hi =
   1062          lookupHRegRemap(m, insn->variant.dfp_unop.dst_hi);
   1063       insn->variant.dfp_unop.op_hi  =
   1064          lookupHRegRemap(m, insn->variant.dfp_unop.op_hi);
   1065       if (insn->size == 16) {
   1066          insn->variant.dfp_unop.dst_lo =
   1067             lookupHRegRemap(m, insn->variant.dfp_unop.dst_lo);
   1068          insn->variant.dfp_unop.op_lo  =
   1069             lookupHRegRemap(m, insn->variant.dfp_unop.op_lo);
   1070       }
   1071       break;
   1072 
   1073    case S390_INSN_DFP_INTOP:
   1074       insn->variant.dfp_intop.dst_hi =
   1075          lookupHRegRemap(m, insn->variant.dfp_intop.dst_hi);
   1076       insn->variant.dfp_intop.op2    =
   1077          lookupHRegRemap(m, insn->variant.dfp_intop.op2);
   1078       insn->variant.dfp_intop.op3_hi =
   1079          lookupHRegRemap(m, insn->variant.dfp_intop.op3_hi);
   1080       if (insn->size == 16) {
   1081          insn->variant.dfp_intop.dst_lo =
   1082             lookupHRegRemap(m, insn->variant.dfp_intop.dst_lo);
   1083          insn->variant.dfp_intop.op3_lo =
   1084             lookupHRegRemap(m, insn->variant.dfp_intop.op3_lo);
   1085       }
   1086       break;
   1087 
   1088    case S390_INSN_DFP_COMPARE:
   1089       insn->variant.dfp_compare.dst =
   1090          lookupHRegRemap(m, insn->variant.dfp_compare.dst);
   1091       insn->variant.dfp_compare.op1_hi =
   1092          lookupHRegRemap(m, insn->variant.dfp_compare.op1_hi);
   1093       insn->variant.dfp_compare.op2_hi =
   1094          lookupHRegRemap(m, insn->variant.dfp_compare.op2_hi);
   1095       if (insn->size == 16) {
   1096          insn->variant.dfp_compare.op1_lo =
   1097             lookupHRegRemap(m, insn->variant.dfp_compare.op1_lo);
   1098          insn->variant.dfp_compare.op2_lo =
   1099             lookupHRegRemap(m, insn->variant.dfp_compare.op2_lo);
   1100       }
   1101       break;
   1102 
   1103    case S390_INSN_DFP_CONVERT:
   1104       insn->variant.dfp_convert.dst_hi =
   1105          lookupHRegRemap(m, insn->variant.dfp_convert.dst_hi);
   1106       if (! hregIsInvalid(insn->variant.dfp_convert.dst_lo))
   1107          insn->variant.dfp_convert.dst_lo =
   1108             lookupHRegRemap(m, insn->variant.dfp_convert.dst_lo);
   1109       insn->variant.dfp_convert.op_hi =
   1110          lookupHRegRemap(m, insn->variant.dfp_convert.op_hi);
   1111       if (! hregIsInvalid(insn->variant.dfp_convert.op_lo))
   1112          insn->variant.dfp_convert.op_lo =
   1113             lookupHRegRemap(m, insn->variant.dfp_convert.op_lo);
   1114       break;
   1115 
   1116    case S390_INSN_DFP_REROUND:
   1117       insn->variant.dfp_reround.dst_hi =
   1118          lookupHRegRemap(m, insn->variant.dfp_reround.dst_hi);
   1119       insn->variant.dfp_reround.op2    =
   1120          lookupHRegRemap(m, insn->variant.dfp_reround.op2);
   1121       insn->variant.dfp_reround.op3_hi =
   1122          lookupHRegRemap(m, insn->variant.dfp_reround.op3_hi);
   1123       if (insn->size == 16) {
   1124          insn->variant.dfp_reround.dst_lo =
   1125             lookupHRegRemap(m, insn->variant.dfp_reround.dst_lo);
   1126          insn->variant.dfp_reround.op3_lo =
   1127             lookupHRegRemap(m, insn->variant.dfp_reround.op3_lo);
   1128       }
   1129       break;
   1130 
   1131    case S390_INSN_FP_CONVERT: {
   1132       s390_fp_convert *fp_convert = insn->variant.fp_convert.details;
   1133 
   1134       fp_convert->dst_hi = lookupHRegRemap(m, fp_convert->dst_hi);
   1135       if (! hregIsInvalid(fp_convert->dst_lo))
   1136          fp_convert->dst_lo = lookupHRegRemap(m, fp_convert->dst_lo);
   1137       fp_convert->op_hi = lookupHRegRemap(m, fp_convert->op_hi);
   1138       if (! hregIsInvalid(fp_convert->op_lo))
   1139          fp_convert->op_lo = lookupHRegRemap(m, fp_convert->op_lo);
   1140       fp_convert->r1 = lookupHRegRemap(m, fp_convert->r1);
   1141       break;
   1142    }
   1143 
   1144    case S390_INSN_MIMM:
   1145       s390_amode_map_regs(m, insn->variant.mimm.dst);
   1146       break;
   1147 
   1148    case S390_INSN_MADD:
   1149       s390_amode_map_regs(m, insn->variant.madd.dst);
   1150       break;
   1151 
   1152    case S390_INSN_MFENCE:
   1153       break;
   1154 
   1155    case S390_INSN_SET_FPC_BFPRM:
   1156       insn->variant.set_fpc_bfprm.mode =
   1157          lookupHRegRemap(m, insn->variant.set_fpc_bfprm.mode);
   1158       break;
   1159 
   1160    case S390_INSN_SET_FPC_DFPRM:
   1161       insn->variant.set_fpc_dfprm.mode =
   1162          lookupHRegRemap(m, insn->variant.set_fpc_dfprm.mode);
   1163       break;
   1164 
   1165    case S390_INSN_EVCHECK:
   1166       s390_amode_map_regs(m, insn->variant.evcheck.counter);
   1167       s390_amode_map_regs(m, insn->variant.evcheck.fail_addr);
   1168       break;
   1169 
   1170    case S390_INSN_PROFINC:
   1171       /* Does not use any register visible to the register allocator */
   1172       break;
   1173 
   1174    case S390_INSN_XDIRECT:
   1175       s390_amode_map_regs(m, insn->variant.xdirect.guest_IA);
   1176       break;
   1177 
   1178    case S390_INSN_XINDIR:
   1179       s390_amode_map_regs(m, insn->variant.xindir.guest_IA);
   1180       insn->variant.xindir.dst =
   1181          lookupHRegRemap(m, insn->variant.xindir.dst);
   1182       break;
   1183 
   1184    case S390_INSN_XASSISTED:
   1185       s390_amode_map_regs(m, insn->variant.xassisted.guest_IA);
   1186       insn->variant.xassisted.dst =
   1187          lookupHRegRemap(m, insn->variant.xassisted.dst);
   1188       break;
   1189 
   1190    default:
   1191       vpanic("s390_insn_map_regs");
   1192    }
   1193 }
   1194 
   1195 
   1196 /* Return True, if INSN is a move between two registers of the same class.
   1197    In that case assign the source and destination registers to SRC and DST,
   1198    respectively. */
   1199 static Bool
   1200 s390_insn_is_reg_reg_move(const s390_insn *insn, HReg *src, HReg *dst)
   1201 {
   1202    if (insn->tag == S390_INSN_MOVE &&
   1203        hregClass(insn->variant.move.src) == hregClass(insn->variant.move.dst)) {
   1204       *src = insn->variant.move.src;
   1205       *dst = insn->variant.move.dst;
   1206       return True;
   1207    }
   1208 
   1209    return False;
   1210 }
   1211 
   1212 
   1213 /*------------------------------------------------------------*/
   1214 /*--- Functions to emit a sequence of bytes                ---*/
   1215 /*------------------------------------------------------------*/
   1216 
   1217 static __inline__ UChar *
   1218 emit_2bytes(UChar *p, ULong val)
   1219 {
   1220    return (UChar *)__builtin_memcpy(p, ((UChar *)&val) + 6, 2) + 2;
   1221 }
   1222 
   1223 
   1224 static __inline__ UChar *
   1225 emit_4bytes(UChar *p, ULong val)
   1226 {
   1227    return (UChar *)__builtin_memcpy(p, ((UChar *)&val) + 4, 4) + 4;
   1228 }
   1229 
   1230 
   1231 static __inline__ UChar *
   1232 emit_6bytes(UChar *p, ULong val)
   1233 {
   1234    return (UChar *)__builtin_memcpy(p, ((UChar *)&val) + 2, 6) + 6;
   1235 }
   1236 
   1237 
   1238 /*------------------------------------------------------------*/
   1239 /*--- Functions to emit various instruction formats        ---*/
   1240 /*------------------------------------------------------------*/
   1241 
   1242 static UChar *
   1243 emit_RI(UChar *p, UInt op, UChar r1, UShort i2)
   1244 {
   1245    ULong the_insn = op;
   1246 
   1247    the_insn |= ((ULong)r1) << 20;
   1248    the_insn |= ((ULong)i2) << 0;
   1249 
   1250    return emit_4bytes(p, the_insn);
   1251 }
   1252 
   1253 
   1254 static UChar *
   1255 emit_RIL(UChar *p, ULong op, UChar r1, UInt i2)
   1256 {
   1257    ULong the_insn = op;
   1258 
   1259    the_insn |= ((ULong)r1) << 36;
   1260    the_insn |= ((ULong)i2) << 0;
   1261 
   1262    return emit_6bytes(p, the_insn);
   1263 }
   1264 
   1265 
   1266 static UChar *
   1267 emit_RR(UChar *p, UInt op, UChar r1, UChar r2)
   1268 {
   1269    ULong the_insn = op;
   1270 
   1271    the_insn |= ((ULong)r1) << 4;
   1272    the_insn |= ((ULong)r2) << 0;
   1273 
   1274    return emit_2bytes(p, the_insn);
   1275 }
   1276 
   1277 
   1278 static UChar *
   1279 emit_RRE(UChar *p, UInt op, UChar r1, UChar r2)
   1280 {
   1281    ULong the_insn = op;
   1282 
   1283    the_insn |= ((ULong)r1) << 4;
   1284    the_insn |= ((ULong)r2) << 0;
   1285 
   1286    return emit_4bytes(p, the_insn);
   1287 }
   1288 
   1289 
   1290 static UChar *
   1291 emit_RRF(UChar *p, UInt op, UChar r1, UChar r3, UChar r2)
   1292 {
   1293    ULong the_insn = op;
   1294 
   1295    the_insn |= ((ULong)r1) << 12;
   1296    the_insn |= ((ULong)r3) << 4;
   1297    the_insn |= ((ULong)r2) << 0;
   1298 
   1299    return emit_4bytes(p, the_insn);
   1300 }
   1301 
   1302 
   1303 static UChar *
   1304 emit_RRF2(UChar *p, UInt op, UChar m3, UChar m4, UChar r1, UChar r2)
   1305 {
   1306    ULong the_insn = op;
   1307 
   1308    the_insn |= ((ULong)m3) << 12;
   1309    the_insn |= ((ULong)m4) << 8;
   1310    the_insn |= ((ULong)r1) << 4;
   1311    the_insn |= ((ULong)r2) << 0;
   1312 
   1313    return emit_4bytes(p, the_insn);
   1314 }
   1315 
   1316 
   1317 static UChar *
   1318 emit_RRF3(UChar *p, UInt op, UChar r3, UChar r1, UChar r2)
   1319 {
   1320    ULong the_insn = op;
   1321 
   1322    the_insn |= ((ULong)r3) << 12;
   1323    the_insn |= ((ULong)r1) << 4;
   1324    the_insn |= ((ULong)r2) << 0;
   1325 
   1326    return emit_4bytes(p, the_insn);
   1327 }
   1328 
   1329 
   1330 static UChar *
   1331 emit_RRF4(UChar *p, UInt op, UChar r3, UChar m4, UChar r1, UChar r2)
   1332 {
   1333    ULong the_insn = op;
   1334 
   1335    the_insn |= ((ULong)r3) << 12;
   1336    the_insn |= ((ULong)m4) << 8;
   1337    the_insn |= ((ULong)r1) << 4;
   1338    the_insn |= ((ULong)r2) << 0;
   1339 
   1340    return emit_4bytes(p, the_insn);
   1341 }
   1342 
   1343 
   1344 static UChar *
   1345 emit_RRF5(UChar *p, UInt op, UChar m4, UChar r1, UChar r2)
   1346 {
   1347    ULong the_insn = op;
   1348 
   1349    the_insn |= ((ULong)m4) << 8;
   1350    the_insn |= ((ULong)r1) << 4;
   1351    the_insn |= ((ULong)r2) << 0;
   1352 
   1353    return emit_4bytes(p, the_insn);
   1354 }
   1355 
   1356 
   1357 static UChar *
   1358 emit_RS(UChar *p, UInt op, UChar r1, UChar r3, UChar b2, UShort d2)
   1359 {
   1360    ULong the_insn = op;
   1361 
   1362    the_insn |= ((ULong)r1) << 20;
   1363    the_insn |= ((ULong)r3) << 16;
   1364    the_insn |= ((ULong)b2) << 12;
   1365    the_insn |= ((ULong)d2) << 0;
   1366 
   1367    return emit_4bytes(p, the_insn);
   1368 }
   1369 
   1370 
   1371 static UChar *
   1372 emit_RSY(UChar *p, ULong op, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
   1373 {
   1374    ULong the_insn = op;
   1375 
   1376    the_insn |= ((ULong)r1) << 36;
   1377    the_insn |= ((ULong)r3) << 32;
   1378    the_insn |= ((ULong)b2) << 28;
   1379    the_insn |= ((ULong)dl2) << 16;
   1380    the_insn |= ((ULong)dh2) << 8;
   1381 
   1382    return emit_6bytes(p, the_insn);
   1383 }
   1384 
   1385 
   1386 static UChar *
   1387 emit_RX(UChar *p, UInt op, UChar r1, UChar x2, UChar b2, UShort d2)
   1388 {
   1389    ULong the_insn = op;
   1390 
   1391    the_insn |= ((ULong)r1) << 20;
   1392    the_insn |= ((ULong)x2) << 16;
   1393    the_insn |= ((ULong)b2) << 12;
   1394    the_insn |= ((ULong)d2) << 0;
   1395 
   1396    return emit_4bytes(p, the_insn);
   1397 }
   1398 
   1399 
   1400 static UChar *
   1401 emit_RXF(UChar *p, ULong op, UChar r3, UChar x2, UChar b2, UShort d2, UChar r1)
   1402 {
   1403    ULong the_insn = op;
   1404 
   1405    the_insn |= ((ULong)r3) << 36;
   1406    the_insn |= ((ULong)x2) << 32;
   1407    the_insn |= ((ULong)b2) << 28;
   1408    the_insn |= ((ULong)d2) << 16;
   1409    the_insn |= ((ULong)r1) << 12;
   1410 
   1411    return emit_6bytes(p, the_insn);
   1412 }
   1413 
   1414 
   1415 static UChar *
   1416 emit_RXY(UChar *p, ULong op, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
   1417 {
   1418    ULong the_insn = op;
   1419 
   1420    the_insn |= ((ULong)r1) << 36;
   1421    the_insn |= ((ULong)x2) << 32;
   1422    the_insn |= ((ULong)b2) << 28;
   1423    the_insn |= ((ULong)dl2) << 16;
   1424    the_insn |= ((ULong)dh2) << 8;
   1425 
   1426    return emit_6bytes(p, the_insn);
   1427 }
   1428 
   1429 
   1430 static UChar *
   1431 emit_S(UChar *p, UInt op, UChar b2, UShort d2)
   1432 {
   1433    ULong the_insn = op;
   1434 
   1435    the_insn |= ((ULong)b2) << 12;
   1436    the_insn |= ((ULong)d2) << 0;
   1437 
   1438    return emit_4bytes(p, the_insn);
   1439 }
   1440 
   1441 
   1442 static UChar *
   1443 emit_SI(UChar *p, UInt op, UChar i2, UChar b1, UShort d1)
   1444 {
   1445    ULong the_insn = op;
   1446 
   1447    the_insn |= ((ULong)i2) << 16;
   1448    the_insn |= ((ULong)b1) << 12;
   1449    the_insn |= ((ULong)d1) << 0;
   1450 
   1451    return emit_4bytes(p, the_insn);
   1452 }
   1453 
   1454 
   1455 static UChar *
   1456 emit_SIL(UChar *p, ULong op, UChar b1, UShort d1, UShort i2)
   1457 {
   1458    ULong the_insn = op;
   1459 
   1460    the_insn |= ((ULong)b1) << 28;
   1461    the_insn |= ((ULong)d1) << 16;
   1462    the_insn |= ((ULong)i2) << 0;
   1463 
   1464    return emit_6bytes(p, the_insn);
   1465 }
   1466 
   1467 
   1468 static UChar *
   1469 emit_SIY(UChar *p, ULong op, UChar i2, UChar b1, UShort dl1, UChar dh1)
   1470 {
   1471    ULong the_insn = op;
   1472 
   1473    the_insn |= ((ULong)i2) << 32;
   1474    the_insn |= ((ULong)b1) << 28;
   1475    the_insn |= ((ULong)dl1) << 16;
   1476    the_insn |= ((ULong)dh1) << 8;
   1477 
   1478    return emit_6bytes(p, the_insn);
   1479 }
   1480 
   1481 
   1482 static UChar *
   1483 emit_SSa(UChar *p, ULong op, UChar l, UChar b1, UShort d1, UChar b2, UShort d2)
   1484 {
   1485    ULong the_insn = op;
   1486 
   1487    the_insn |= ((ULong)l)  << 32;
   1488    the_insn |= ((ULong)b1) << 28;
   1489    the_insn |= ((ULong)d1) << 16;
   1490    the_insn |= ((ULong)b2) << 12;
   1491    the_insn |= ((ULong)d2) << 0;
   1492 
   1493    return emit_6bytes(p, the_insn);
   1494 }
   1495 
   1496 
   1497 /*------------------------------------------------------------*/
   1498 /*--- Functions to emit particular instructions            ---*/
   1499 /*------------------------------------------------------------*/
   1500 
   1501 static UChar *
   1502 s390_emit_AR(UChar *p, UChar r1, UChar r2)
   1503 {
   1504    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   1505       s390_disasm(ENC3(MNM, GPR, GPR), "ar", r1, r2);
   1506 
   1507    return emit_RR(p, 0x1a00, r1, r2);
   1508 }
   1509 
   1510 
   1511 static UChar *
   1512 s390_emit_AGR(UChar *p, UChar r1, UChar r2)
   1513 {
   1514    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   1515       s390_disasm(ENC3(MNM, GPR, GPR), "agr", r1, r2);
   1516 
   1517    return emit_RRE(p, 0xb9080000, r1, r2);
   1518 }
   1519 
   1520 
   1521 static UChar *
   1522 s390_emit_A(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
   1523 {
   1524    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   1525       s390_disasm(ENC3(MNM, GPR, UDXB), "a", r1, d2, x2, b2);
   1526 
   1527    return emit_RX(p, 0x5a000000, r1, x2, b2, d2);
   1528 }
   1529 
   1530 
   1531 static UChar *
   1532 s390_emit_AY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
   1533 {
   1534    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   1535       s390_disasm(ENC3(MNM, GPR, SDXB), "ay", r1, dh2, dl2, x2, b2);
   1536 
   1537    return emit_RXY(p, 0xe3000000005aULL, r1, x2, b2, dl2, dh2);
   1538 }
   1539 
   1540 
   1541 static UChar *
   1542 s390_emit_AG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
   1543 {
   1544    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   1545       s390_disasm(ENC3(MNM, GPR, SDXB), "ag", r1, dh2, dl2, x2, b2);
   1546 
   1547    return emit_RXY(p, 0xe30000000008ULL, r1, x2, b2, dl2, dh2);
   1548 }
   1549 
   1550 
   1551 static UChar *
   1552 s390_emit_AFI(UChar *p, UChar r1, UInt i2)
   1553 {
   1554    vassert(s390_host_has_eimm);
   1555 
   1556    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   1557       s390_disasm(ENC3(MNM, GPR, INT), "afi", r1, i2);
   1558 
   1559    return emit_RIL(p, 0xc20900000000ULL, r1, i2);
   1560 }
   1561 
   1562 
   1563 static UChar *
   1564 s390_emit_AGFI(UChar *p, UChar r1, UInt i2)
   1565 {
   1566    vassert(s390_host_has_eimm);
   1567 
   1568    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   1569       s390_disasm(ENC3(MNM, GPR, INT), "agfi", r1, i2);
   1570 
   1571    return emit_RIL(p, 0xc20800000000ULL, r1, i2);
   1572 }
   1573 
   1574 
   1575 static UChar *
   1576 s390_emit_AH(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
   1577 {
   1578    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   1579       s390_disasm(ENC3(MNM, GPR, UDXB), "ah", r1, d2, x2, b2);
   1580 
   1581    return emit_RX(p, 0x4a000000, r1, x2, b2, d2);
   1582 }
   1583 
   1584 
   1585 static UChar *
   1586 s390_emit_AHY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
   1587 {
   1588    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   1589       s390_disasm(ENC3(MNM, GPR, SDXB), "ahy", r1, dh2, dl2, x2, b2);
   1590 
   1591    return emit_RXY(p, 0xe3000000007aULL, r1, x2, b2, dl2, dh2);
   1592 }
   1593 
   1594 
   1595 static UChar *
   1596 s390_emit_AHI(UChar *p, UChar r1, UShort i2)
   1597 {
   1598    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   1599       s390_disasm(ENC3(MNM, GPR, INT), "ahi", r1, (Int)(Short)i2);
   1600 
   1601    return emit_RI(p, 0xa70a0000, r1, i2);
   1602 }
   1603 
   1604 
   1605 static UChar *
   1606 s390_emit_AGHI(UChar *p, UChar r1, UShort i2)
   1607 {
   1608    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   1609       s390_disasm(ENC3(MNM, GPR, INT), "aghi", r1, (Int)(Short)i2);
   1610 
   1611    return emit_RI(p, 0xa70b0000, r1, i2);
   1612 }
   1613 
   1614 
   1615 static UChar *
   1616 s390_emit_AGSI(UChar *p, UChar i2, UChar b1, UShort dl1, UChar dh1)
   1617 {
   1618    vassert(s390_host_has_gie);
   1619 
   1620    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   1621       s390_disasm(ENC3(MNM, SDXB, INT), "agsi", dh1, dl1, 0, b1, (Int)(Char)i2);
   1622 
   1623    return emit_SIY(p, 0xeb000000007aULL, i2, b1, dl1, dh1);
   1624 }
   1625 
   1626 
   1627 static UChar *
   1628 s390_emit_ASI(UChar *p, UChar i2, UChar b1, UShort dl1, UChar dh1)
   1629 {
   1630    vassert(s390_host_has_gie);
   1631 
   1632    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   1633       s390_disasm(ENC3(MNM, SDXB, INT), "asi", dh1, dl1, 0, b1, (Int)(Char)i2);
   1634 
   1635    return emit_SIY(p, 0xeb000000006aULL, i2, b1, dl1, dh1);
   1636 }
   1637 
   1638 
   1639 static UChar *
   1640 s390_emit_NR(UChar *p, UChar r1, UChar r2)
   1641 {
   1642    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   1643       s390_disasm(ENC3(MNM, GPR, GPR), "nr", r1, r2);
   1644 
   1645    return emit_RR(p, 0x1400, r1, r2);
   1646 }
   1647 
   1648 
   1649 static UChar *
   1650 s390_emit_NGR(UChar *p, UChar r1, UChar r2)
   1651 {
   1652    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   1653       s390_disasm(ENC3(MNM, GPR, GPR), "ngr", r1, r2);
   1654 
   1655    return emit_RRE(p, 0xb9800000, r1, r2);
   1656 }
   1657 
   1658 
   1659 static UChar *
   1660 s390_emit_N(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
   1661 {
   1662    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   1663       s390_disasm(ENC3(MNM, GPR, UDXB), "n", r1, d2, x2, b2);
   1664 
   1665    return emit_RX(p, 0x54000000, r1, x2, b2, d2);
   1666 }
   1667 
   1668 
   1669 static UChar *
   1670 s390_emit_NY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
   1671 {
   1672    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   1673       s390_disasm(ENC3(MNM, GPR, SDXB), "ny", r1, dh2, dl2, x2, b2);
   1674 
   1675    return emit_RXY(p, 0xe30000000054ULL, r1, x2, b2, dl2, dh2);
   1676 }
   1677 
   1678 
   1679 static UChar *
   1680 s390_emit_NG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
   1681 {
   1682    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   1683       s390_disasm(ENC3(MNM, GPR, SDXB), "ng", r1, dh2, dl2, x2, b2);
   1684 
   1685    return emit_RXY(p, 0xe30000000080ULL, r1, x2, b2, dl2, dh2);
   1686 }
   1687 
   1688 
   1689 static UChar *
   1690 s390_emit_NIHF(UChar *p, UChar r1, UInt i2)
   1691 {
   1692    vassert(s390_host_has_eimm);
   1693 
   1694    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   1695       s390_disasm(ENC3(MNM, GPR, UINT), "nihf", r1, i2);
   1696 
   1697    return emit_RIL(p, 0xc00a00000000ULL, r1, i2);
   1698 }
   1699 
   1700 
   1701 static UChar *
   1702 s390_emit_NILF(UChar *p, UChar r1, UInt i2)
   1703 {
   1704    vassert(s390_host_has_eimm);
   1705 
   1706    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   1707       s390_disasm(ENC3(MNM, GPR, UINT), "nilf", r1, i2);
   1708 
   1709    return emit_RIL(p, 0xc00b00000000ULL, r1, i2);
   1710 }
   1711 
   1712 
   1713 static UChar *
   1714 s390_emit_NILL(UChar *p, UChar r1, UShort i2)
   1715 {
   1716    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   1717       s390_disasm(ENC3(MNM, GPR, UINT), "nill", r1, i2);
   1718 
   1719    return emit_RI(p, 0xa5070000, r1, i2);
   1720 }
   1721 
   1722 
   1723 static UChar *
   1724 s390_emit_BASR(UChar *p, UChar r1, UChar r2)
   1725 {
   1726    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   1727       s390_disasm(ENC3(MNM, GPR, GPR), "basr", r1, r2);
   1728 
   1729    return emit_RR(p, 0x0d00, r1, r2);
   1730 }
   1731 
   1732 
   1733 static UChar *
   1734 s390_emit_BCR(UChar *p, UChar r1, UChar r2)
   1735 {
   1736    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   1737       s390_disasm(ENC2(XMNM, GPR), S390_XMNM_BCR, r1, r2);
   1738 
   1739    return emit_RR(p, 0x0700, r1, r2);
   1740 }
   1741 
   1742 
   1743 static UChar *
   1744 s390_emit_BRC(UChar *p, UChar r1, UShort i2)
   1745 {
   1746    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   1747       s390_disasm(ENC2(XMNM, PCREL), S390_XMNM_BRC, r1, (Int)(Short)i2);
   1748 
   1749    return emit_RI(p, 0xa7040000, r1, i2);
   1750 }
   1751 
   1752 
   1753 static UChar *
   1754 s390_emit_BRCL(UChar *p, UChar r1, ULong i2)
   1755 {
   1756    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   1757       s390_disasm(ENC2(XMNM, PCREL), S390_XMNM_BRCL, r1, i2);
   1758 
   1759    return emit_RIL(p, 0xc00400000000ULL, r1, i2);
   1760 }
   1761 
   1762 
   1763 static UChar *
   1764 s390_emit_CR(UChar *p, UChar r1, UChar r2)
   1765 {
   1766    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   1767       s390_disasm(ENC3(MNM, GPR, GPR), "cr", r1, r2);
   1768 
   1769    return emit_RR(p, 0x1900, r1, r2);
   1770 }
   1771 
   1772 
   1773 static UChar *
   1774 s390_emit_CGR(UChar *p, UChar r1, UChar r2)
   1775 {
   1776    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   1777       s390_disasm(ENC3(MNM, GPR, GPR), "cgr", r1, r2);
   1778 
   1779    return emit_RRE(p, 0xb9200000, r1, r2);
   1780 }
   1781 
   1782 
   1783 static UChar *
   1784 s390_emit_C(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
   1785 {
   1786    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   1787       s390_disasm(ENC3(MNM, GPR, UDXB), "c", r1, d2, x2, b2);
   1788 
   1789    return emit_RX(p, 0x59000000, r1, x2, b2, d2);
   1790 }
   1791 
   1792 
   1793 static UChar *
   1794 s390_emit_CY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
   1795 {
   1796    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   1797       s390_disasm(ENC3(MNM, GPR, SDXB), "cy", r1, dh2, dl2, x2, b2);
   1798 
   1799    return emit_RXY(p, 0xe30000000059ULL, r1, x2, b2, dl2, dh2);
   1800 }
   1801 
   1802 
   1803 static UChar *
   1804 s390_emit_CG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
   1805 {
   1806    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   1807       s390_disasm(ENC3(MNM, GPR, SDXB), "cg", r1, dh2, dl2, x2, b2);
   1808 
   1809    return emit_RXY(p, 0xe30000000020ULL, r1, x2, b2, dl2, dh2);
   1810 }
   1811 
   1812 
   1813 static UChar *
   1814 s390_emit_CFI(UChar *p, UChar r1, UInt i2)
   1815 {
   1816    vassert(s390_host_has_eimm);
   1817 
   1818    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   1819       s390_disasm(ENC3(MNM, GPR, INT), "cfi", r1, i2);
   1820 
   1821    return emit_RIL(p, 0xc20d00000000ULL, r1, i2);
   1822 }
   1823 
   1824 
   1825 static UChar *
   1826 s390_emit_CGFI(UChar *p, UChar r1, UInt i2)
   1827 {
   1828    vassert(s390_host_has_eimm);
   1829 
   1830    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   1831       s390_disasm(ENC3(MNM, GPR, INT), "cgfi", r1, i2);
   1832 
   1833    return emit_RIL(p, 0xc20c00000000ULL, r1, i2);
   1834 }
   1835 
   1836 
   1837 static UChar *
   1838 s390_emit_CS(UChar *p, UChar r1, UChar r3, UChar b2, UShort d2)
   1839 {
   1840    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   1841       s390_disasm(ENC4(MNM, GPR, GPR, UDXB), "cs", r1, r3, d2, 0, b2);
   1842 
   1843    return emit_RS(p, 0xba000000, r1, r3, b2, d2);
   1844 }
   1845 
   1846 
   1847 static UChar *
   1848 s390_emit_CSY(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
   1849 {
   1850    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   1851       s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "csy", r1, r3, dh2, dl2, 0, b2);
   1852 
   1853    return emit_RSY(p, 0xeb0000000014ULL, r1, r3, b2, dl2, dh2);
   1854 }
   1855 
   1856 
   1857 static UChar *
   1858 s390_emit_CSG(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
   1859 {
   1860    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   1861       s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "csg", r1, r3, dh2, dl2, 0, b2);
   1862 
   1863    return emit_RSY(p, 0xeb0000000030ULL, r1, r3, b2, dl2, dh2);
   1864 }
   1865 
   1866 
   1867 static UChar *
   1868 s390_emit_CDS(UChar *p, UChar r1, UChar r3, UChar b2, UShort d2)
   1869 {
   1870    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   1871       s390_disasm(ENC4(MNM, GPR, GPR, UDXB), "cds", r1, r3, d2, 0, b2);
   1872 
   1873    return emit_RS(p, 0xbb000000, r1, r3, b2, d2);
   1874 }
   1875 
   1876 
   1877 static UChar *
   1878 s390_emit_CDSY(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
   1879 {
   1880    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   1881       s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "cdsy", r1, r3, dh2, dl2, 0, b2);
   1882 
   1883    return emit_RSY(p, 0xeb0000000031ULL, r1, r3, b2, dl2, dh2);
   1884 }
   1885 
   1886 
   1887 static UChar *
   1888 s390_emit_CDSG(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
   1889 {
   1890    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   1891       s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "cdsg", r1, r3, dh2, dl2, 0, b2);
   1892 
   1893    return emit_RSY(p, 0xeb000000003eULL, r1, r3, b2, dl2, dh2);
   1894 }
   1895 
   1896 
   1897 static UChar *
   1898 s390_emit_CLR(UChar *p, UChar r1, UChar r2)
   1899 {
   1900    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   1901       s390_disasm(ENC3(MNM, GPR, GPR), "clr", r1, r2);
   1902 
   1903    return emit_RR(p, 0x1500, r1, r2);
   1904 }
   1905 
   1906 
   1907 static UChar *
   1908 s390_emit_CLGR(UChar *p, UChar r1, UChar r2)
   1909 {
   1910    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   1911       s390_disasm(ENC3(MNM, GPR, GPR), "clgr", r1, r2);
   1912 
   1913    return emit_RRE(p, 0xb9210000, r1, r2);
   1914 }
   1915 
   1916 
   1917 static UChar *
   1918 s390_emit_CL(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
   1919 {
   1920    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   1921       s390_disasm(ENC3(MNM, GPR, UDXB), "cl", r1, d2, x2, b2);
   1922 
   1923    return emit_RX(p, 0x55000000, r1, x2, b2, d2);
   1924 }
   1925 
   1926 
   1927 static UChar *
   1928 s390_emit_CLY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
   1929 {
   1930    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   1931       s390_disasm(ENC3(MNM, GPR, SDXB), "cly", r1, dh2, dl2, x2, b2);
   1932 
   1933    return emit_RXY(p, 0xe30000000055ULL, r1, x2, b2, dl2, dh2);
   1934 }
   1935 
   1936 
   1937 static UChar *
   1938 s390_emit_CLG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
   1939 {
   1940    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   1941       s390_disasm(ENC3(MNM, GPR, SDXB), "clg", r1, dh2, dl2, x2, b2);
   1942 
   1943    return emit_RXY(p, 0xe30000000021ULL, r1, x2, b2, dl2, dh2);
   1944 }
   1945 
   1946 
   1947 static UChar *
   1948 s390_emit_CLFI(UChar *p, UChar r1, UInt i2)
   1949 {
   1950    vassert(s390_host_has_eimm);
   1951 
   1952    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   1953       s390_disasm(ENC3(MNM, GPR, UINT), "clfi", r1, i2);
   1954 
   1955    return emit_RIL(p, 0xc20f00000000ULL, r1, i2);
   1956 }
   1957 
   1958 
   1959 static UChar *
   1960 s390_emit_CLGFI(UChar *p, UChar r1, UInt i2)
   1961 {
   1962    vassert(s390_host_has_eimm);
   1963 
   1964    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   1965       s390_disasm(ENC3(MNM, GPR, UINT), "clgfi", r1, i2);
   1966 
   1967    return emit_RIL(p, 0xc20e00000000ULL, r1, i2);
   1968 }
   1969 
   1970 
   1971 static UChar *
   1972 s390_emit_DR(UChar *p, UChar r1, UChar r2)
   1973 {
   1974    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   1975       s390_disasm(ENC3(MNM, GPR, GPR), "dr", r1, r2);
   1976 
   1977    return emit_RR(p, 0x1d00, r1, r2);
   1978 }
   1979 
   1980 
   1981 static UChar *
   1982 s390_emit_D(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
   1983 {
   1984    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   1985       s390_disasm(ENC3(MNM, GPR, UDXB), "d", r1, d2, x2, b2);
   1986 
   1987    return emit_RX(p, 0x5d000000, r1, x2, b2, d2);
   1988 }
   1989 
   1990 
   1991 static UChar *
   1992 s390_emit_DLR(UChar *p, UChar r1, UChar r2)
   1993 {
   1994    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   1995       s390_disasm(ENC3(MNM, GPR, GPR), "dlr", r1, r2);
   1996 
   1997    return emit_RRE(p, 0xb9970000, r1, r2);
   1998 }
   1999 
   2000 
   2001 static UChar *
   2002 s390_emit_DLGR(UChar *p, UChar r1, UChar r2)
   2003 {
   2004    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   2005       s390_disasm(ENC3(MNM, GPR, GPR), "dlgr", r1, r2);
   2006 
   2007    return emit_RRE(p, 0xb9870000, r1, r2);
   2008 }
   2009 
   2010 
   2011 static UChar *
   2012 s390_emit_DL(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
   2013 {
   2014    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   2015       s390_disasm(ENC3(MNM, GPR, SDXB), "dl", r1, dh2, dl2, x2, b2);
   2016 
   2017    return emit_RXY(p, 0xe30000000097ULL, r1, x2, b2, dl2, dh2);
   2018 }
   2019 
   2020 
   2021 static UChar *
   2022 s390_emit_DLG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
   2023 {
   2024    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   2025       s390_disasm(ENC3(MNM, GPR, SDXB), "dlg", r1, dh2, dl2, x2, b2);
   2026 
   2027    return emit_RXY(p, 0xe30000000087ULL, r1, x2, b2, dl2, dh2);
   2028 }
   2029 
   2030 
   2031 static UChar *
   2032 s390_emit_DSGR(UChar *p, UChar r1, UChar r2)
   2033 {
   2034    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   2035       s390_disasm(ENC3(MNM, GPR, GPR), "dsgr", r1, r2);
   2036 
   2037    return emit_RRE(p, 0xb90d0000, r1, r2);
   2038 }
   2039 
   2040 
   2041 static UChar *
   2042 s390_emit_DSG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
   2043 {
   2044    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   2045       s390_disasm(ENC3(MNM, GPR, SDXB), "dsg", r1, dh2, dl2, x2, b2);
   2046 
   2047    return emit_RXY(p, 0xe3000000000dULL, r1, x2, b2, dl2, dh2);
   2048 }
   2049 
   2050 
   2051 static UChar *
   2052 s390_emit_XR(UChar *p, UChar r1, UChar r2)
   2053 {
   2054    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   2055       s390_disasm(ENC3(MNM, GPR, GPR), "xr", r1, r2);
   2056 
   2057    return emit_RR(p, 0x1700, r1, r2);
   2058 }
   2059 
   2060 
   2061 static UChar *
   2062 s390_emit_XGR(UChar *p, UChar r1, UChar r2)
   2063 {
   2064    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   2065       s390_disasm(ENC3(MNM, GPR, GPR), "xgr", r1, r2);
   2066 
   2067    return emit_RRE(p, 0xb9820000, r1, r2);
   2068 }
   2069 
   2070 
   2071 static UChar *
   2072 s390_emit_X(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
   2073 {
   2074    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   2075       s390_disasm(ENC3(MNM, GPR, UDXB), "x", r1, d2, x2, b2);
   2076 
   2077    return emit_RX(p, 0x57000000, r1, x2, b2, d2);
   2078 }
   2079 
   2080 
   2081 static UChar *
   2082 s390_emit_XY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
   2083 {
   2084    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   2085       s390_disasm(ENC3(MNM, GPR, SDXB), "xy", r1, dh2, dl2, x2, b2);
   2086 
   2087    return emit_RXY(p, 0xe30000000057ULL, r1, x2, b2, dl2, dh2);
   2088 }
   2089 
   2090 
   2091 static UChar *
   2092 s390_emit_XG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
   2093 {
   2094    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   2095       s390_disasm(ENC3(MNM, GPR, SDXB), "xg", r1, dh2, dl2, x2, b2);
   2096 
   2097    return emit_RXY(p, 0xe30000000082ULL, r1, x2, b2, dl2, dh2);
   2098 }
   2099 
   2100 
   2101 static UChar *
   2102 s390_emit_XIHF(UChar *p, UChar r1, UInt i2)
   2103 {
   2104    vassert(s390_host_has_eimm);
   2105 
   2106    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   2107       s390_disasm(ENC3(MNM, GPR, UINT), "xihf", r1, i2);
   2108 
   2109    return emit_RIL(p, 0xc00600000000ULL, r1, i2);
   2110 }
   2111 
   2112 
   2113 static UChar *
   2114 s390_emit_XILF(UChar *p, UChar r1, UInt i2)
   2115 {
   2116    vassert(s390_host_has_eimm);
   2117 
   2118    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   2119       s390_disasm(ENC3(MNM, GPR, UINT), "xilf", r1, i2);
   2120 
   2121    return emit_RIL(p, 0xc00700000000ULL, r1, i2);
   2122 }
   2123 
   2124 
   2125 static UChar *
   2126 s390_emit_XC(UChar *p, UInt l, UChar b1, UShort d1, UChar b2, UShort d2)
   2127 {
   2128    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   2129       s390_disasm(ENC3(MNM, UDLB, UDXB), "xc", d1, l, b1, d2, 0, b2);
   2130 
   2131    return emit_SSa(p, 0xd70000000000ULL, l, b1, d1, b2, d2);
   2132 }
   2133 
   2134 
   2135 static UChar *
   2136 s390_emit_FLOGR(UChar *p, UChar r1, UChar r2)
   2137 {
   2138    vassert(s390_host_has_eimm);
   2139 
   2140    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   2141       s390_disasm(ENC3(MNM, GPR, GPR), "flogr", r1, r2);
   2142 
   2143    return emit_RRE(p, 0xb9830000, r1, r2);
   2144 }
   2145 
   2146 
   2147 static UChar *
   2148 s390_emit_IC(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
   2149 {
   2150    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   2151       s390_disasm(ENC3(MNM, GPR, UDXB), "ic", r1, d2, x2, b2);
   2152 
   2153    return emit_RX(p, 0x43000000, r1, x2, b2, d2);
   2154 }
   2155 
   2156 
   2157 static UChar *
   2158 s390_emit_ICY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
   2159 {
   2160    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   2161       s390_disasm(ENC3(MNM, GPR, SDXB), "icy", r1, dh2, dl2, x2, b2);
   2162 
   2163    return emit_RXY(p, 0xe30000000073ULL, r1, x2, b2, dl2, dh2);
   2164 }
   2165 
   2166 
   2167 static UChar *
   2168 s390_emit_IIHF(UChar *p, UChar r1, UInt i2)
   2169 {
   2170    vassert(s390_host_has_eimm);
   2171 
   2172    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   2173       s390_disasm(ENC3(MNM, GPR, UINT), "iihf", r1, i2);
   2174 
   2175    return emit_RIL(p, 0xc00800000000ULL, r1, i2);
   2176 }
   2177 
   2178 
   2179 static UChar *
   2180 s390_emit_IIHH(UChar *p, UChar r1, UShort i2)
   2181 {
   2182    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   2183       s390_disasm(ENC3(MNM, GPR, UINT), "iihh", r1, i2);
   2184 
   2185    return emit_RI(p, 0xa5000000, r1, i2);
   2186 }
   2187 
   2188 
   2189 static UChar *
   2190 s390_emit_IIHL(UChar *p, UChar r1, UShort i2)
   2191 {
   2192    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   2193       s390_disasm(ENC3(MNM, GPR, UINT), "iihl", r1, i2);
   2194 
   2195    return emit_RI(p, 0xa5010000, r1, i2);
   2196 }
   2197 
   2198 
   2199 static UChar *
   2200 s390_emit_IILF(UChar *p, UChar r1, UInt i2)
   2201 {
   2202    vassert(s390_host_has_eimm);
   2203 
   2204    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   2205       s390_disasm(ENC3(MNM, GPR, UINT), "iilf", r1, i2);
   2206 
   2207    return emit_RIL(p, 0xc00900000000ULL, r1, i2);
   2208 }
   2209 
   2210 
   2211 static UChar *
   2212 s390_emit_IILH(UChar *p, UChar r1, UShort i2)
   2213 {
   2214    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   2215       s390_disasm(ENC3(MNM, GPR, UINT), "iilh", r1, i2);
   2216 
   2217    return emit_RI(p, 0xa5020000, r1, i2);
   2218 }
   2219 
   2220 
   2221 static UChar *
   2222 s390_emit_IILL(UChar *p, UChar r1, UShort i2)
   2223 {
   2224    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   2225       s390_disasm(ENC3(MNM, GPR, UINT), "iill", r1, i2);
   2226 
   2227    return emit_RI(p, 0xa5030000, r1, i2);
   2228 }
   2229 
   2230 
   2231 static UChar *
   2232 s390_emit_IPM(UChar *p, UChar r1, UChar r2)
   2233 {
   2234    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   2235       s390_disasm(ENC2(MNM, GPR), "ipm", r1);
   2236 
   2237    return emit_RRE(p, 0xb2220000, r1, r2);
   2238 }
   2239 
   2240 
   2241 static UChar *
   2242 s390_emit_LR(UChar *p, UChar r1, UChar r2)
   2243 {
   2244    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   2245       s390_disasm(ENC3(MNM, GPR, GPR), "lr", r1, r2);
   2246 
   2247    return emit_RR(p, 0x1800, r1, r2);
   2248 }
   2249 
   2250 
   2251 static UChar *
   2252 s390_emit_LGR(UChar *p, UChar r1, UChar r2)
   2253 {
   2254    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   2255       s390_disasm(ENC3(MNM, GPR, GPR), "lgr", r1, r2);
   2256 
   2257    return emit_RRE(p, 0xb9040000, r1, r2);
   2258 }
   2259 
   2260 
   2261 static UChar *
   2262 s390_emit_LGFR(UChar *p, UChar r1, UChar r2)
   2263 {
   2264    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   2265       s390_disasm(ENC3(MNM, GPR, GPR), "lgfr", r1, r2);
   2266 
   2267    return emit_RRE(p, 0xb9140000, r1, r2);
   2268 }
   2269 
   2270 
   2271 static UChar *
   2272 s390_emit_L(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
   2273 {
   2274    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   2275       s390_disasm(ENC3(MNM, GPR, UDXB), "l", r1, d2, x2, b2);
   2276 
   2277    return emit_RX(p, 0x58000000, r1, x2, b2, d2);
   2278 }
   2279 
   2280 
   2281 static UChar *
   2282 s390_emit_LY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
   2283 {
   2284    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   2285       s390_disasm(ENC3(MNM, GPR, SDXB), "ly", r1, dh2, dl2, x2, b2);
   2286 
   2287    return emit_RXY(p, 0xe30000000058ULL, r1, x2, b2, dl2, dh2);
   2288 }
   2289 
   2290 
   2291 static UChar *
   2292 s390_emit_LG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
   2293 {
   2294    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   2295       s390_disasm(ENC3(MNM, GPR, SDXB), "lg", r1, dh2, dl2, x2, b2);
   2296 
   2297    return emit_RXY(p, 0xe30000000004ULL, r1, x2, b2, dl2, dh2);
   2298 }
   2299 
   2300 
   2301 static UChar *
   2302 s390_emit_LGF(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
   2303 {
   2304    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   2305       s390_disasm(ENC3(MNM, GPR, SDXB), "lgf", r1, dh2, dl2, x2, b2);
   2306 
   2307    return emit_RXY(p, 0xe30000000014ULL, r1, x2, b2, dl2, dh2);
   2308 }
   2309 
   2310 
   2311 static UChar *
   2312 s390_emit_LGFI(UChar *p, UChar r1, UInt i2)
   2313 {
   2314    vassert(s390_host_has_eimm);
   2315 
   2316    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   2317       s390_disasm(ENC3(MNM, GPR, INT), "lgfi", r1, i2);
   2318 
   2319    return emit_RIL(p, 0xc00100000000ULL, r1, i2);
   2320 }
   2321 
   2322 
   2323 static UChar *
   2324 s390_emit_LTR(UChar *p, UChar r1, UChar r2)
   2325 {
   2326    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   2327       s390_disasm(ENC3(MNM, GPR, GPR), "ltr", r1, r2);
   2328 
   2329    return emit_RR(p, 0x1200, r1, r2);
   2330 }
   2331 
   2332 
   2333 static UChar *
   2334 s390_emit_LTGR(UChar *p, UChar r1, UChar r2)
   2335 {
   2336    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   2337       s390_disasm(ENC3(MNM, GPR, GPR), "ltgr", r1, r2);
   2338 
   2339    return emit_RRE(p, 0xb9020000, r1, r2);
   2340 }
   2341 
   2342 
   2343 static UChar *
   2344 s390_emit_LT(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
   2345 {
   2346    vassert(s390_host_has_eimm);
   2347 
   2348    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   2349       s390_disasm(ENC3(MNM, GPR, SDXB), "lt", r1, dh2, dl2, x2, b2);
   2350 
   2351    return emit_RXY(p, 0xe30000000012ULL, r1, x2, b2, dl2, dh2);
   2352 }
   2353 
   2354 
   2355 static UChar *
   2356 s390_emit_LTG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
   2357 {
   2358    vassert(s390_host_has_eimm);
   2359 
   2360    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   2361       s390_disasm(ENC3(MNM, GPR, SDXB), "ltg", r1, dh2, dl2, x2, b2);
   2362 
   2363    return emit_RXY(p, 0xe30000000002ULL, r1, x2, b2, dl2, dh2);
   2364 }
   2365 
   2366 
   2367 static UChar *
   2368 s390_emit_LBR(UChar *p, UChar r1, UChar r2)
   2369 {
   2370    vassert(s390_host_has_eimm);
   2371 
   2372    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   2373       s390_disasm(ENC3(MNM, GPR, GPR), "lbr", r1, r2);
   2374 
   2375    return emit_RRE(p, 0xb9260000, r1, r2);
   2376 }
   2377 
   2378 
   2379 static UChar *
   2380 s390_emit_LGBR(UChar *p, UChar r1, UChar r2)
   2381 {
   2382    vassert(s390_host_has_eimm);
   2383 
   2384    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   2385       s390_disasm(ENC3(MNM, GPR, GPR), "lgbr", r1, r2);
   2386 
   2387    return emit_RRE(p, 0xb9060000, r1, r2);
   2388 }
   2389 
   2390 
   2391 static UChar *
   2392 s390_emit_LB(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
   2393 {
   2394    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   2395       s390_disasm(ENC3(MNM, GPR, SDXB), "lb", r1, dh2, dl2, x2, b2);
   2396 
   2397    return emit_RXY(p, 0xe30000000076ULL, r1, x2, b2, dl2, dh2);
   2398 }
   2399 
   2400 
   2401 static UChar *
   2402 s390_emit_LGB(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
   2403 {
   2404    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   2405       s390_disasm(ENC3(MNM, GPR, SDXB), "lgb", r1, dh2, dl2, x2, b2);
   2406 
   2407    return emit_RXY(p, 0xe30000000077ULL, r1, x2, b2, dl2, dh2);
   2408 }
   2409 
   2410 
   2411 static UChar *
   2412 s390_emit_LCR(UChar *p, UChar r1, UChar r2)
   2413 {
   2414    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   2415       s390_disasm(ENC3(MNM, GPR, GPR), "lcr", r1, r2);
   2416 
   2417    return emit_RR(p, 0x1300, r1, r2);
   2418 }
   2419 
   2420 
   2421 static UChar *
   2422 s390_emit_LCGR(UChar *p, UChar r1, UChar r2)
   2423 {
   2424    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   2425       s390_disasm(ENC3(MNM, GPR, GPR), "lcgr", r1, r2);
   2426 
   2427    return emit_RRE(p, 0xb9030000, r1, r2);
   2428 }
   2429 
   2430 
   2431 static UChar *
   2432 s390_emit_LHR(UChar *p, UChar r1, UChar r2)
   2433 {
   2434    vassert(s390_host_has_eimm);
   2435 
   2436    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   2437       s390_disasm(ENC3(MNM, GPR, GPR), "lhr", r1, r2);
   2438 
   2439    return emit_RRE(p, 0xb9270000, r1, r2);
   2440 }
   2441 
   2442 
   2443 static UChar *
   2444 s390_emit_LGHR(UChar *p, UChar r1, UChar r2)
   2445 {
   2446    vassert(s390_host_has_eimm);
   2447 
   2448    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   2449       s390_disasm(ENC3(MNM, GPR, GPR), "lghr", r1, r2);
   2450 
   2451    return emit_RRE(p, 0xb9070000, r1, r2);
   2452 }
   2453 
   2454 
   2455 static UChar *
   2456 s390_emit_LH(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
   2457 {
   2458    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   2459       s390_disasm(ENC3(MNM, GPR, UDXB), "lh", r1, d2, x2, b2);
   2460 
   2461    return emit_RX(p, 0x48000000, r1, x2, b2, d2);
   2462 }
   2463 
   2464 
   2465 static UChar *
   2466 s390_emit_LHY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
   2467 {
   2468    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   2469       s390_disasm(ENC3(MNM, GPR, SDXB), "lhy", r1, dh2, dl2, x2, b2);
   2470 
   2471    return emit_RXY(p, 0xe30000000078ULL, r1, x2, b2, dl2, dh2);
   2472 }
   2473 
   2474 
   2475 static UChar *
   2476 s390_emit_LGH(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
   2477 {
   2478    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   2479       s390_disasm(ENC3(MNM, GPR, SDXB), "lgh", r1, dh2, dl2, x2, b2);
   2480 
   2481    return emit_RXY(p, 0xe30000000015ULL, r1, x2, b2, dl2, dh2);
   2482 }
   2483 
   2484 
   2485 static UChar *
   2486 s390_emit_LHI(UChar *p, UChar r1, UShort i2)
   2487 {
   2488    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   2489       s390_disasm(ENC3(MNM, GPR, INT), "lhi", r1, (Int)(Short)i2);
   2490 
   2491    return emit_RI(p, 0xa7080000, r1, i2);
   2492 }
   2493 
   2494 
   2495 static UChar *
   2496 s390_emit_LGHI(UChar *p, UChar r1, UShort i2)
   2497 {
   2498    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   2499       s390_disasm(ENC3(MNM, GPR, INT), "lghi", r1, (Int)(Short)i2);
   2500 
   2501    return emit_RI(p, 0xa7090000, r1, i2);
   2502 }
   2503 
   2504 
   2505 static UChar *
   2506 s390_emit_LLGFR(UChar *p, UChar r1, UChar r2)
   2507 {
   2508    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   2509       s390_disasm(ENC3(MNM, GPR, GPR), "llgfr", r1, r2);
   2510 
   2511    return emit_RRE(p, 0xb9160000, r1, r2);
   2512 }
   2513 
   2514 
   2515 static UChar *
   2516 s390_emit_LLGF(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
   2517 {
   2518    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   2519       s390_disasm(ENC3(MNM, GPR, SDXB), "llgf", r1, dh2, dl2, x2, b2);
   2520 
   2521    return emit_RXY(p, 0xe30000000016ULL, r1, x2, b2, dl2, dh2);
   2522 }
   2523 
   2524 
   2525 static UChar *
   2526 s390_emit_LLCR(UChar *p, UChar r1, UChar r2)
   2527 {
   2528    vassert(s390_host_has_eimm);
   2529 
   2530    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   2531       s390_disasm(ENC3(MNM, GPR, GPR), "llcr", r1, r2);
   2532 
   2533    return emit_RRE(p, 0xb9940000, r1, r2);
   2534 }
   2535 
   2536 
   2537 static UChar *
   2538 s390_emit_LLGCR(UChar *p, UChar r1, UChar r2)
   2539 {
   2540    vassert(s390_host_has_eimm);
   2541 
   2542    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   2543       s390_disasm(ENC3(MNM, GPR, GPR), "llgcr", r1, r2);
   2544 
   2545    return emit_RRE(p, 0xb9840000, r1, r2);
   2546 }
   2547 
   2548 
   2549 static UChar *
   2550 s390_emit_LLC(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
   2551 {
   2552    vassert(s390_host_has_eimm);
   2553 
   2554    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   2555       s390_disasm(ENC3(MNM, GPR, SDXB), "llc", r1, dh2, dl2, x2, b2);
   2556 
   2557    return emit_RXY(p, 0xe30000000094ULL, r1, x2, b2, dl2, dh2);
   2558 }
   2559 
   2560 
   2561 static UChar *
   2562 s390_emit_LLGC(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
   2563 {
   2564    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   2565       s390_disasm(ENC3(MNM, GPR, SDXB), "llgc", r1, dh2, dl2, x2, b2);
   2566 
   2567    return emit_RXY(p, 0xe30000000090ULL, r1, x2, b2, dl2, dh2);
   2568 }
   2569 
   2570 
   2571 static UChar *
   2572 s390_emit_LLHR(UChar *p, UChar r1, UChar r2)
   2573 {
   2574    vassert(s390_host_has_eimm);
   2575 
   2576    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   2577       s390_disasm(ENC3(MNM, GPR, GPR), "llhr", r1, r2);
   2578 
   2579    return emit_RRE(p, 0xb9950000, r1, r2);
   2580 }
   2581 
   2582 
   2583 static UChar *
   2584 s390_emit_LLGHR(UChar *p, UChar r1, UChar r2)
   2585 {
   2586    vassert(s390_host_has_eimm);
   2587 
   2588    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   2589       s390_disasm(ENC3(MNM, GPR, GPR), "llghr", r1, r2);
   2590 
   2591    return emit_RRE(p, 0xb9850000, r1, r2);
   2592 }
   2593 
   2594 
   2595 static UChar *
   2596 s390_emit_LLH(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
   2597 {
   2598    vassert(s390_host_has_eimm);
   2599 
   2600    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   2601       s390_disasm(ENC3(MNM, GPR, SDXB), "llh", r1, dh2, dl2, x2, b2);
   2602 
   2603    return emit_RXY(p, 0xe30000000095ULL, r1, x2, b2, dl2, dh2);
   2604 }
   2605 
   2606 
   2607 static UChar *
   2608 s390_emit_LLGH(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
   2609 {
   2610    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   2611       s390_disasm(ENC3(MNM, GPR, SDXB), "llgh", r1, dh2, dl2, x2, b2);
   2612 
   2613    return emit_RXY(p, 0xe30000000091ULL, r1, x2, b2, dl2, dh2);
   2614 }
   2615 
   2616 
   2617 static UChar *
   2618 s390_emit_LLILF(UChar *p, UChar r1, UInt i2)
   2619 {
   2620    vassert(s390_host_has_eimm);
   2621 
   2622    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   2623       s390_disasm(ENC3(MNM, GPR, UINT), "llilf", r1, i2);
   2624 
   2625    return emit_RIL(p, 0xc00f00000000ULL, r1, i2);
   2626 }
   2627 
   2628 
   2629 static UChar *
   2630 s390_emit_LLILH(UChar *p, UChar r1, UShort i2)
   2631 {
   2632    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   2633       s390_disasm(ENC3(MNM, GPR, UINT), "llilh", r1, i2);
   2634 
   2635    return emit_RI(p, 0xa50e0000, r1, i2);
   2636 }
   2637 
   2638 
   2639 static UChar *
   2640 s390_emit_LLILL(UChar *p, UChar r1, UShort i2)
   2641 {
   2642    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   2643       s390_disasm(ENC3(MNM, GPR, UINT), "llill", r1, i2);
   2644 
   2645    return emit_RI(p, 0xa50f0000, r1, i2);
   2646 }
   2647 
   2648 
   2649 static UChar *
   2650 s390_emit_MR(UChar *p, UChar r1, UChar r2)
   2651 {
   2652    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   2653       s390_disasm(ENC3(MNM, GPR, GPR), "mr", r1, r2);
   2654 
   2655    return emit_RR(p, 0x1c00, r1, r2);
   2656 }
   2657 
   2658 
   2659 static UChar *
   2660 s390_emit_M(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
   2661 {
   2662    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   2663       s390_disasm(ENC3(MNM, GPR, UDXB), "m", r1, d2, x2, b2);
   2664 
   2665    return emit_RX(p, 0x5c000000, r1, x2, b2, d2);
   2666 }
   2667 
   2668 
   2669 static UChar *
   2670 s390_emit_MFY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
   2671 {
   2672    vassert(s390_host_has_gie);
   2673 
   2674    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   2675       s390_disasm(ENC3(MNM, GPR, SDXB), "mfy", r1, dh2, dl2, x2, b2);
   2676 
   2677    return emit_RXY(p, 0xe3000000005cULL, r1, x2, b2, dl2, dh2);
   2678 }
   2679 
   2680 
   2681 static UChar *
   2682 s390_emit_MH(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
   2683 {
   2684    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   2685       s390_disasm(ENC3(MNM, GPR, UDXB), "mh", r1, d2, x2, b2);
   2686 
   2687    return emit_RX(p, 0x4c000000, r1, x2, b2, d2);
   2688 }
   2689 
   2690 
   2691 static UChar *
   2692 s390_emit_MHY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
   2693 {
   2694    vassert(s390_host_has_gie);
   2695 
   2696    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   2697       s390_disasm(ENC3(MNM, GPR, SDXB), "mhy", r1, dh2, dl2, x2, b2);
   2698 
   2699    return emit_RXY(p, 0xe3000000007cULL, r1, x2, b2, dl2, dh2);
   2700 }
   2701 
   2702 
   2703 static UChar *
   2704 s390_emit_MHI(UChar *p, UChar r1, UShort i2)
   2705 {
   2706    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   2707       s390_disasm(ENC3(MNM, GPR, INT), "mhi", r1, (Int)(Short)i2);
   2708 
   2709    return emit_RI(p, 0xa70c0000, r1, i2);
   2710 }
   2711 
   2712 
   2713 static UChar *
   2714 s390_emit_MLR(UChar *p, UChar r1, UChar r2)
   2715 {
   2716    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   2717       s390_disasm(ENC3(MNM, GPR, GPR), "mlr", r1, r2);
   2718 
   2719    return emit_RRE(p, 0xb9960000, r1, r2);
   2720 }
   2721 
   2722 
   2723 static UChar *
   2724 s390_emit_MLGR(UChar *p, UChar r1, UChar r2)
   2725 {
   2726    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   2727       s390_disasm(ENC3(MNM, GPR, GPR), "mlgr", r1, r2);
   2728 
   2729    return emit_RRE(p, 0xb9860000, r1, r2);
   2730 }
   2731 
   2732 
   2733 static UChar *
   2734 s390_emit_ML(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
   2735 {
   2736    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   2737       s390_disasm(ENC3(MNM, GPR, SDXB), "ml", r1, dh2, dl2, x2, b2);
   2738 
   2739    return emit_RXY(p, 0xe30000000096ULL, r1, x2, b2, dl2, dh2);
   2740 }
   2741 
   2742 
   2743 static UChar *
   2744 s390_emit_MLG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
   2745 {
   2746    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   2747       s390_disasm(ENC3(MNM, GPR, SDXB), "mlg", r1, dh2, dl2, x2, b2);
   2748 
   2749    return emit_RXY(p, 0xe30000000086ULL, r1, x2, b2, dl2, dh2);
   2750 }
   2751 
   2752 
   2753 static UChar *
   2754 s390_emit_MSR(UChar *p, UChar r1, UChar r2)
   2755 {
   2756    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   2757       s390_disasm(ENC3(MNM, GPR, GPR), "msr", r1, r2);
   2758 
   2759    return emit_RRE(p, 0xb2520000, r1, r2);
   2760 }
   2761 
   2762 
   2763 static UChar *
   2764 s390_emit_MSGR(UChar *p, UChar r1, UChar r2)
   2765 {
   2766    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   2767       s390_disasm(ENC3(MNM, GPR, GPR), "msgr", r1, r2);
   2768 
   2769    return emit_RRE(p, 0xb90c0000, r1, r2);
   2770 }
   2771 
   2772 
   2773 static UChar *
   2774 s390_emit_MS(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
   2775 {
   2776    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   2777       s390_disasm(ENC3(MNM, GPR, UDXB), "ms", r1, d2, x2, b2);
   2778 
   2779    return emit_RX(p, 0x71000000, r1, x2, b2, d2);
   2780 }
   2781 
   2782 
   2783 static UChar *
   2784 s390_emit_MSY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
   2785 {
   2786    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   2787       s390_disasm(ENC3(MNM, GPR, SDXB), "msy", r1, dh2, dl2, x2, b2);
   2788 
   2789    return emit_RXY(p, 0xe30000000051ULL, r1, x2, b2, dl2, dh2);
   2790 }
   2791 
   2792 
   2793 static UChar *
   2794 s390_emit_MSG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
   2795 {
   2796    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   2797       s390_disasm(ENC3(MNM, GPR, SDXB), "msg", r1, dh2, dl2, x2, b2);
   2798 
   2799    return emit_RXY(p, 0xe3000000000cULL, r1, x2, b2, dl2, dh2);
   2800 }
   2801 
   2802 
   2803 static UChar *
   2804 s390_emit_MSFI(UChar *p, UChar r1, UInt i2)
   2805 {
   2806    vassert(s390_host_has_gie);
   2807 
   2808    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   2809       s390_disasm(ENC3(MNM, GPR, INT), "msfi", r1, i2);
   2810 
   2811    return emit_RIL(p, 0xc20100000000ULL, r1, i2);
   2812 }
   2813 
   2814 
   2815 static UChar *
   2816 s390_emit_MSGFI(UChar *p, UChar r1, UInt i2)
   2817 {
   2818    vassert(s390_host_has_gie);
   2819 
   2820    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   2821       s390_disasm(ENC3(MNM, GPR, INT), "msgfi", r1, i2);
   2822 
   2823    return emit_RIL(p, 0xc20000000000ULL, r1, i2);
   2824 }
   2825 
   2826 
   2827 static UChar *
   2828 s390_emit_MVC(UChar *p, UInt l, UChar b1, UShort d1, UChar b2, UShort d2)
   2829 {
   2830    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   2831       s390_disasm(ENC3(MNM, UDLB, UDXB), "mvc", d1, l, b1, d2, 0, b2);
   2832 
   2833    return emit_SSa(p, 0xd20000000000ULL, l, b1, d1, b2, d2);
   2834 }
   2835 
   2836 
   2837 static UChar *
   2838 s390_emit_MVI(UChar *p, UChar i2, UChar b1, UShort d1)
   2839 {
   2840    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   2841       s390_disasm(ENC3(MNM, UDXB, INT), "mvi", d1, 0, b1, i2);
   2842 
   2843    return emit_SI(p, 0x92000000, i2, b1, d1);
   2844 }
   2845 
   2846 
   2847 static UChar *
   2848 s390_emit_MVHHI(UChar *p, UChar b1, UShort d1, UShort i2)
   2849 {
   2850    vassert(s390_host_has_gie);
   2851 
   2852    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   2853       s390_disasm(ENC3(MNM, UDXB, INT), "mvhhi", d1, 0, b1, i2);
   2854 
   2855    return emit_SIL(p, 0xe54400000000ULL, b1, d1, i2);
   2856 }
   2857 
   2858 
   2859 static UChar *
   2860 s390_emit_MVHI(UChar *p, UChar b1, UShort d1, UShort i2)
   2861 {
   2862    vassert(s390_host_has_gie);
   2863 
   2864    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   2865       s390_disasm(ENC3(MNM, UDXB, INT), "mvhi", d1, 0, b1, i2);
   2866 
   2867    return emit_SIL(p, 0xe54c00000000ULL, b1, d1, i2);
   2868 }
   2869 
   2870 
   2871 static UChar *
   2872 s390_emit_MVGHI(UChar *p, UChar b1, UShort d1, UShort i2)
   2873 {
   2874    vassert(s390_host_has_gie);
   2875 
   2876    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   2877       s390_disasm(ENC3(MNM, UDXB, INT), "mvghi", d1, 0, b1, i2);
   2878 
   2879    return emit_SIL(p, 0xe54800000000ULL, b1, d1, i2);
   2880 }
   2881 
   2882 
   2883 static UChar *
   2884 s390_emit_OR(UChar *p, UChar r1, UChar r2)
   2885 {
   2886    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   2887       s390_disasm(ENC3(MNM, GPR, GPR), "or", r1, r2);
   2888 
   2889    return emit_RR(p, 0x1600, r1, r2);
   2890 }
   2891 
   2892 
   2893 static UChar *
   2894 s390_emit_OGR(UChar *p, UChar r1, UChar r2)
   2895 {
   2896    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   2897       s390_disasm(ENC3(MNM, GPR, GPR), "ogr", r1, r2);
   2898 
   2899    return emit_RRE(p, 0xb9810000, r1, r2);
   2900 }
   2901 
   2902 
   2903 static UChar *
   2904 s390_emit_O(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
   2905 {
   2906    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   2907       s390_disasm(ENC3(MNM, GPR, UDXB), "o", r1, d2, x2, b2);
   2908 
   2909    return emit_RX(p, 0x56000000, r1, x2, b2, d2);
   2910 }
   2911 
   2912 
   2913 static UChar *
   2914 s390_emit_OY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
   2915 {
   2916    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   2917       s390_disasm(ENC3(MNM, GPR, SDXB), "oy", r1, dh2, dl2, x2, b2);
   2918 
   2919    return emit_RXY(p, 0xe30000000056ULL, r1, x2, b2, dl2, dh2);
   2920 }
   2921 
   2922 
   2923 static UChar *
   2924 s390_emit_OG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
   2925 {
   2926    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   2927       s390_disasm(ENC3(MNM, GPR, SDXB), "og", r1, dh2, dl2, x2, b2);
   2928 
   2929    return emit_RXY(p, 0xe30000000081ULL, r1, x2, b2, dl2, dh2);
   2930 }
   2931 
   2932 
   2933 static UChar *
   2934 s390_emit_OIHF(UChar *p, UChar r1, UInt i2)
   2935 {
   2936    vassert(s390_host_has_eimm);
   2937 
   2938    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   2939       s390_disasm(ENC3(MNM, GPR, UINT), "oihf", r1, i2);
   2940 
   2941    return emit_RIL(p, 0xc00c00000000ULL, r1, i2);
   2942 }
   2943 
   2944 
   2945 static UChar *
   2946 s390_emit_OILF(UChar *p, UChar r1, UInt i2)
   2947 {
   2948    vassert(s390_host_has_eimm);
   2949 
   2950    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   2951       s390_disasm(ENC3(MNM, GPR, UINT), "oilf", r1, i2);
   2952 
   2953    return emit_RIL(p, 0xc00d00000000ULL, r1, i2);
   2954 }
   2955 
   2956 
   2957 static UChar *
   2958 s390_emit_OILL(UChar *p, UChar r1, UShort i2)
   2959 {
   2960    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   2961       s390_disasm(ENC3(MNM, GPR, UINT), "oill", r1, i2);
   2962 
   2963    return emit_RI(p, 0xa50b0000, r1, i2);
   2964 }
   2965 
   2966 
   2967 static UChar *
   2968 s390_emit_SLL(UChar *p, UChar r1, UChar b2, UShort d2)
   2969 {
   2970    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   2971       s390_disasm(ENC3(MNM, GPR, UDXB), "sll", r1, d2, 0, b2);
   2972 
   2973    return emit_RS(p, 0x89000000, r1, 0, b2, d2);
   2974 }
   2975 
   2976 
   2977 static UChar *
   2978 s390_emit_SLLG(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
   2979 {
   2980    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   2981       s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "sllg", r1, r3, dh2, dl2, 0, b2);
   2982 
   2983    return emit_RSY(p, 0xeb000000000dULL, r1, r3, b2, dl2, dh2);
   2984 }
   2985 
   2986 
   2987 static UChar *
   2988 s390_emit_SRA(UChar *p, UChar r1, UChar b2, UShort d2)
   2989 {
   2990    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   2991       s390_disasm(ENC3(MNM, GPR, UDXB), "sra", r1, d2, 0, b2);
   2992 
   2993    return emit_RS(p, 0x8a000000, r1, 0, b2, d2);
   2994 }
   2995 
   2996 
   2997 static UChar *
   2998 s390_emit_SRAG(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
   2999 {
   3000    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   3001       s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "srag", r1, r3, dh2, dl2, 0, b2);
   3002 
   3003    return emit_RSY(p, 0xeb000000000aULL, r1, r3, b2, dl2, dh2);
   3004 }
   3005 
   3006 
   3007 static UChar *
   3008 s390_emit_SRL(UChar *p, UChar r1, UChar b2, UShort d2)
   3009 {
   3010    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   3011       s390_disasm(ENC3(MNM, GPR, UDXB), "srl", r1, d2, 0, b2);
   3012 
   3013    return emit_RS(p, 0x88000000, r1, 0, b2, d2);
   3014 }
   3015 
   3016 
   3017 static UChar *
   3018 s390_emit_SRLG(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
   3019 {
   3020    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   3021       s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "srlg", r1, r3, dh2, dl2, 0, b2);
   3022 
   3023    return emit_RSY(p, 0xeb000000000cULL, r1, r3, b2, dl2, dh2);
   3024 }
   3025 
   3026 
   3027 static UChar *
   3028 s390_emit_ST(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
   3029 {
   3030    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   3031       s390_disasm(ENC3(MNM, GPR, UDXB), "st", r1, d2, x2, b2);
   3032 
   3033    return emit_RX(p, 0x50000000, r1, x2, b2, d2);
   3034 }
   3035 
   3036 
   3037 static UChar *
   3038 s390_emit_STY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
   3039 {
   3040    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   3041       s390_disasm(ENC3(MNM, GPR, SDXB), "sty", r1, dh2, dl2, x2, b2);
   3042 
   3043    return emit_RXY(p, 0xe30000000050ULL, r1, x2, b2, dl2, dh2);
   3044 }
   3045 
   3046 
   3047 static UChar *
   3048 s390_emit_STG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
   3049 {
   3050    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   3051       s390_disasm(ENC3(MNM, GPR, SDXB), "stg", r1, dh2, dl2, x2, b2);
   3052 
   3053    return emit_RXY(p, 0xe30000000024ULL, r1, x2, b2, dl2, dh2);
   3054 }
   3055 
   3056 
   3057 static UChar *
   3058 s390_emit_STC(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
   3059 {
   3060    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   3061       s390_disasm(ENC3(MNM, GPR, UDXB), "stc", r1, d2, x2, b2);
   3062 
   3063    return emit_RX(p, 0x42000000, r1, x2, b2, d2);
   3064 }
   3065 
   3066 
   3067 static UChar *
   3068 s390_emit_STCY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
   3069 {
   3070    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   3071       s390_disasm(ENC3(MNM, GPR, SDXB), "stcy", r1, dh2, dl2, x2, b2);
   3072 
   3073    return emit_RXY(p, 0xe30000000072ULL, r1, x2, b2, dl2, dh2);
   3074 }
   3075 
   3076 
   3077 static UChar *
   3078 s390_emit_STH(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
   3079 {
   3080    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   3081       s390_disasm(ENC3(MNM, GPR, UDXB), "sth", r1, d2, x2, b2);
   3082 
   3083    return emit_RX(p, 0x40000000, r1, x2, b2, d2);
   3084 }
   3085 
   3086 
   3087 static UChar *
   3088 s390_emit_STHY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
   3089 {
   3090    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   3091       s390_disasm(ENC3(MNM, GPR, SDXB), "sthy", r1, dh2, dl2, x2, b2);
   3092 
   3093    return emit_RXY(p, 0xe30000000070ULL, r1, x2, b2, dl2, dh2);
   3094 }
   3095 
   3096 
   3097 static UChar *
   3098 s390_emit_SR(UChar *p, UChar r1, UChar r2)
   3099 {
   3100    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   3101       s390_disasm(ENC3(MNM, GPR, GPR), "sr", r1, r2);
   3102 
   3103    return emit_RR(p, 0x1b00, r1, r2);
   3104 }
   3105 
   3106 
   3107 static UChar *
   3108 s390_emit_SGR(UChar *p, UChar r1, UChar r2)
   3109 {
   3110    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   3111       s390_disasm(ENC3(MNM, GPR, GPR), "sgr", r1, r2);
   3112 
   3113    return emit_RRE(p, 0xb9090000, r1, r2);
   3114 }
   3115 
   3116 
   3117 static UChar *
   3118 s390_emit_S(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
   3119 {
   3120    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   3121       s390_disasm(ENC3(MNM, GPR, UDXB), "s", r1, d2, x2, b2);
   3122 
   3123    return emit_RX(p, 0x5b000000, r1, x2, b2, d2);
   3124 }
   3125 
   3126 
   3127 static UChar *
   3128 s390_emit_SY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
   3129 {
   3130    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   3131       s390_disasm(ENC3(MNM, GPR, SDXB), "sy", r1, dh2, dl2, x2, b2);
   3132 
   3133    return emit_RXY(p, 0xe3000000005bULL, r1, x2, b2, dl2, dh2);
   3134 }
   3135 
   3136 
   3137 static UChar *
   3138 s390_emit_SG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
   3139 {
   3140    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   3141       s390_disasm(ENC3(MNM, GPR, SDXB), "sg", r1, dh2, dl2, x2, b2);
   3142 
   3143    return emit_RXY(p, 0xe30000000009ULL, r1, x2, b2, dl2, dh2);
   3144 }
   3145 
   3146 
   3147 static UChar *
   3148 s390_emit_SH(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
   3149 {
   3150    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   3151       s390_disasm(ENC3(MNM, GPR, UDXB), "sh", r1, d2, x2, b2);
   3152 
   3153    return emit_RX(p, 0x4b000000, r1, x2, b2, d2);
   3154 }
   3155 
   3156 
   3157 static UChar *
   3158 s390_emit_SHY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
   3159 {
   3160    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   3161       s390_disasm(ENC3(MNM, GPR, SDXB), "shy", r1, dh2, dl2, x2, b2);
   3162 
   3163    return emit_RXY(p, 0xe3000000007bULL, r1, x2, b2, dl2, dh2);
   3164 }
   3165 
   3166 
   3167 static UChar *
   3168 s390_emit_SLFI(UChar *p, UChar r1, UInt i2)
   3169 {
   3170    vassert(s390_host_has_eimm);
   3171 
   3172    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   3173       s390_disasm(ENC3(MNM, GPR, UINT), "slfi", r1, i2);
   3174 
   3175    return emit_RIL(p, 0xc20500000000ULL, r1, i2);
   3176 }
   3177 
   3178 
   3179 static UChar *
   3180 s390_emit_SLGFI(UChar *p, UChar r1, UInt i2)
   3181 {
   3182    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   3183       s390_disasm(ENC3(MNM, GPR, UINT), "slgfi", r1, i2);
   3184 
   3185    return emit_RIL(p, 0xc20400000000ULL, r1, i2);
   3186 }
   3187 
   3188 
   3189 static UChar *
   3190 s390_emit_LDR(UChar *p, UChar r1, UChar r2)
   3191 {
   3192    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   3193       s390_disasm(ENC3(MNM, FPR, FPR), "ldr", r1, r2);
   3194 
   3195    return emit_RR(p, 0x2800, r1, r2);
   3196 }
   3197 
   3198 
   3199 static UChar *
   3200 s390_emit_LE(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
   3201 {
   3202    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   3203       s390_disasm(ENC3(MNM, FPR, UDXB), "le", r1, d2, x2, b2);
   3204 
   3205    return emit_RX(p, 0x78000000, r1, x2, b2, d2);
   3206 }
   3207 
   3208 
   3209 static UChar *
   3210 s390_emit_LD(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
   3211 {
   3212    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   3213       s390_disasm(ENC3(MNM, FPR, UDXB), "ld", r1, d2, x2, b2);
   3214 
   3215    return emit_RX(p, 0x68000000, r1, x2, b2, d2);
   3216 }
   3217 
   3218 
   3219 static UChar *
   3220 s390_emit_LEY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
   3221 {
   3222    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   3223       s390_disasm(ENC3(MNM, FPR, SDXB), "ley", r1, dh2, dl2, x2, b2);
   3224 
   3225    return emit_RXY(p, 0xed0000000064ULL, r1, x2, b2, dl2, dh2);
   3226 }
   3227 
   3228 
   3229 static UChar *
   3230 s390_emit_LDY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
   3231 {
   3232    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   3233       s390_disasm(ENC3(MNM, FPR, SDXB), "ldy", r1, dh2, dl2, x2, b2);
   3234 
   3235    return emit_RXY(p, 0xed0000000065ULL, r1, x2, b2, dl2, dh2);
   3236 }
   3237 
   3238 
   3239 static UChar *
   3240 s390_emit_LFPC(UChar *p, UChar b2, UShort d2)
   3241 {
   3242    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   3243       s390_disasm(ENC2(MNM, UDXB), "lfpc", d2, 0, b2);
   3244 
   3245    return emit_S(p, 0xb29d0000, b2, d2);
   3246 }
   3247 
   3248 
   3249 static UChar *
   3250 s390_emit_LDGR(UChar *p, UChar r1, UChar r2)
   3251 {
   3252    vassert(s390_host_has_fgx);
   3253 
   3254    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   3255       s390_disasm(ENC3(MNM, FPR, GPR), "ldgr", r1, r2);
   3256 
   3257    return emit_RRE(p, 0xb3c10000, r1, r2);
   3258 }
   3259 
   3260 
   3261 static UChar *
   3262 s390_emit_LGDR(UChar *p, UChar r1, UChar r2)
   3263 {
   3264    vassert(s390_host_has_fgx);
   3265 
   3266    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   3267       s390_disasm(ENC3(MNM, GPR, FPR), "lgdr", r1, r2);
   3268 
   3269    return emit_RRE(p, 0xb3cd0000, r1, r2);
   3270 }
   3271 
   3272 
   3273 static UChar *
   3274 s390_emit_LZER(UChar *p, UChar r1, UChar r2)
   3275 {
   3276    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   3277       s390_disasm(ENC2(MNM, FPR), "lzer", r1);
   3278 
   3279    return emit_RRE(p, 0xb3740000, r1, r2);
   3280 }
   3281 
   3282 
   3283 static UChar *
   3284 s390_emit_LZDR(UChar *p, UChar r1, UChar r2)
   3285 {
   3286    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   3287       s390_disasm(ENC2(MNM, FPR), "lzdr", r1);
   3288 
   3289    return emit_RRE(p, 0xb3750000, r1, r2);
   3290 }
   3291 
   3292 
   3293 static UChar *
   3294 s390_emit_SFPC(UChar *p, UChar r1)
   3295 {
   3296    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   3297       s390_disasm(ENC2(MNM, GPR), "sfpc", r1);
   3298 
   3299    return emit_RRE(p, 0xb3840000, r1, 0);
   3300 }
   3301 
   3302 
   3303 static UChar *
   3304 s390_emit_STE(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
   3305 {
   3306    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   3307       s390_disasm(ENC3(MNM, FPR, UDXB), "ste", r1, d2, x2, b2);
   3308 
   3309    return emit_RX(p, 0x70000000, r1, x2, b2, d2);
   3310 }
   3311 
   3312 
   3313 static UChar *
   3314 s390_emit_STD(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
   3315 {
   3316    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   3317       s390_disasm(ENC3(MNM, FPR, UDXB), "std", r1, d2, x2, b2);
   3318 
   3319    return emit_RX(p, 0x60000000, r1, x2, b2, d2);
   3320 }
   3321 
   3322 
   3323 static UChar *
   3324 s390_emit_STEY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
   3325 {
   3326    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   3327       s390_disasm(ENC3(MNM, FPR, SDXB), "stey", r1, dh2, dl2, x2, b2);
   3328 
   3329    return emit_RXY(p, 0xed0000000066ULL, r1, x2, b2, dl2, dh2);
   3330 }
   3331 
   3332 
   3333 static UChar *
   3334 s390_emit_STDY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
   3335 {
   3336    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   3337       s390_disasm(ENC3(MNM, FPR, SDXB), "stdy", r1, dh2, dl2, x2, b2);
   3338 
   3339    return emit_RXY(p, 0xed0000000067ULL, r1, x2, b2, dl2, dh2);
   3340 }
   3341 
   3342 
   3343 static UChar *
   3344 s390_emit_STFPC(UChar *p, UChar b2, UShort d2)
   3345 {
   3346    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   3347       s390_disasm(ENC2(MNM, UDXB), "stfpc", d2, 0, b2);
   3348 
   3349    return emit_S(p, 0xb29c0000, b2, d2);
   3350 }
   3351 
   3352 
   3353 static UChar *
   3354 s390_emit_AEBR(UChar *p, UChar r1, UChar r2)
   3355 {
   3356    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   3357       s390_disasm(ENC3(MNM, FPR, FPR), "aebr", r1, r2);
   3358 
   3359    return emit_RRE(p, 0xb30a0000, r1, r2);
   3360 }
   3361 
   3362 
   3363 static UChar *
   3364 s390_emit_ADBR(UChar *p, UChar r1, UChar r2)
   3365 {
   3366    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   3367       s390_disasm(ENC3(MNM, FPR, FPR), "adbr", r1, r2);
   3368 
   3369    return emit_RRE(p, 0xb31a0000, r1, r2);
   3370 }
   3371 
   3372 
   3373 static UChar *
   3374 s390_emit_AXBR(UChar *p, UChar r1, UChar r2)
   3375 {
   3376    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   3377       s390_disasm(ENC3(MNM, FPR, FPR), "axbr", r1, r2);
   3378 
   3379    return emit_RRE(p, 0xb34a0000, r1, r2);
   3380 }
   3381 
   3382 
   3383 static UChar *
   3384 s390_emit_CEBR(UChar *p, UChar r1, UChar r2)
   3385 {
   3386    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   3387       s390_disasm(ENC3(MNM, FPR, FPR), "cebr", r1, r2);
   3388 
   3389    return emit_RRE(p, 0xb3090000, r1, r2);
   3390 }
   3391 
   3392 
   3393 static UChar *
   3394 s390_emit_CDBR(UChar *p, UChar r1, UChar r2)
   3395 {
   3396    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   3397       s390_disasm(ENC3(MNM, FPR, FPR), "cdbr", r1, r2);
   3398 
   3399    return emit_RRE(p, 0xb3190000, r1, r2);
   3400 }
   3401 
   3402 
   3403 static UChar *
   3404 s390_emit_CXBR(UChar *p, UChar r1, UChar r2)
   3405 {
   3406    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   3407       s390_disasm(ENC3(MNM, FPR, FPR), "cxbr", r1, r2);
   3408 
   3409    return emit_RRE(p, 0xb3490000, r1, r2);
   3410 }
   3411 
   3412 
   3413 static UChar *
   3414 s390_emit_CEFBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
   3415 {
   3416    vassert(m4 == 0);
   3417    vassert(m3 == 0 || s390_host_has_fpext);
   3418 
   3419    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
   3420       if (m3 == 0)
   3421          s390_disasm(ENC3(MNM, FPR, GPR), "cefbr", r1, r2);
   3422       else
   3423          s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT),
   3424                      "cefbra", r1, m3, r2, m4);
   3425    }
   3426 
   3427    return emit_RRF2(p, 0xb3940000, m3, m4, r1, r2);
   3428 }
   3429 
   3430 
   3431 static UChar *
   3432 s390_emit_CDFBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
   3433 {
   3434    vassert(m4 == 0);
   3435    vassert(m3 == 0 || s390_host_has_fpext);
   3436 
   3437    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
   3438       if (m3 == 0)
   3439          s390_disasm(ENC3(MNM, FPR, GPR), "cdfbr", r1, r2);
   3440       else
   3441          s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT),
   3442                      "cdfbra", r1, m3, r2, m4);
   3443    }
   3444 
   3445    return emit_RRF2(p, 0xb3950000, m3, m4, r1, r2);
   3446 }
   3447 
   3448 
   3449 static UChar *
   3450 s390_emit_CXFBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
   3451 {
   3452    vassert(m4 == 0);
   3453    vassert(m3 == 0 || s390_host_has_fpext);
   3454 
   3455    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
   3456       if (m3 == 0)
   3457          s390_disasm(ENC3(MNM, FPR, GPR), "cxfbr", r1, r2);
   3458       else
   3459          s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT),
   3460                      "cxfbra", r1, m3, r2, m4);
   3461    }
   3462 
   3463    return emit_RRF2(p, 0xb3960000, m3, m4, r1, r2);
   3464 }
   3465 
   3466 
   3467 static UChar *
   3468 s390_emit_CEGBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
   3469 {
   3470    vassert(m4 == 0);
   3471    vassert(m3 == 0 || s390_host_has_fpext);
   3472 
   3473    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
   3474       if (m3 == 0)
   3475          s390_disasm(ENC3(MNM, FPR, GPR), "cegbr", r1, r2);
   3476       else
   3477          s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT),
   3478                      "cegbra", r1, m3, r2, m4);
   3479    }
   3480 
   3481    return emit_RRF2(p, 0xb3a40000, m3, m4, r1, r2);
   3482 }
   3483 
   3484 
   3485 static UChar *
   3486 s390_emit_CDGBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
   3487 {
   3488    vassert(m4 == 0);
   3489    vassert(m3 == 0 || s390_host_has_fpext);
   3490 
   3491    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
   3492       if (m3 == 0)
   3493          s390_disasm(ENC3(MNM, FPR, GPR), "cdgbr", r1, r2);
   3494       else
   3495          s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT),
   3496                      "cdgbra", r1, m3, r2, m4);
   3497    }
   3498 
   3499    return emit_RRF2(p, 0xb3a50000, m3, m4, r1, r2);
   3500 }
   3501 
   3502 
   3503 static UChar *
   3504 s390_emit_CXGBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
   3505 {
   3506    vassert(m4 == 0);
   3507    vassert(m3 == 0 || s390_host_has_fpext);
   3508 
   3509    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
   3510       if (m3 == 0)
   3511          s390_disasm(ENC3(MNM, FPR, GPR), "cxgbr", r1, r2);
   3512       else
   3513          s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT),
   3514                      "cxgbra", r1, m3, r2, m4);
   3515    }
   3516 
   3517    return emit_RRF2(p, 0xb3a60000, m3, m4, r1, r2);
   3518 }
   3519 
   3520 
   3521 static UChar *
   3522 s390_emit_CELFBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
   3523 {
   3524    vassert(m4 == 0);
   3525    vassert(s390_host_has_fpext);
   3526 
   3527    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   3528       s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "celfbr", r1, m3, r2, m4);
   3529 
   3530    return emit_RRF2(p, 0xb3900000, m3, m4, r1, r2);
   3531 }
   3532 
   3533 
   3534 static UChar *
   3535 s390_emit_CDLFBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
   3536 {
   3537    vassert(m4 == 0);
   3538    vassert(s390_host_has_fpext);
   3539 
   3540    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   3541       s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cdlfbr", r1, m3, r2, m4);
   3542 
   3543    return emit_RRF2(p, 0xb3910000, m3, m4, r1, r2);
   3544 }
   3545 
   3546 
   3547 static UChar *
   3548 s390_emit_CXLFBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
   3549 {
   3550    vassert(m4 == 0);
   3551    vassert(s390_host_has_fpext);
   3552 
   3553    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   3554       s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cxlfbr", r1, m3, r2, m4);
   3555 
   3556    return emit_RRF2(p, 0xb3920000, m3, m4, r1, r2);
   3557 }
   3558 
   3559 
   3560 static UChar *
   3561 s390_emit_CELGBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
   3562 {
   3563    vassert(m4 == 0);
   3564    vassert(s390_host_has_fpext);
   3565 
   3566    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   3567       s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "celgbr", r1, m3, r2, m4);
   3568 
   3569    return emit_RRF2(p, 0xb3a00000, m3, m4, r1, r2);
   3570 }
   3571 
   3572 
   3573 static UChar *
   3574 s390_emit_CDLGBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
   3575 {
   3576    vassert(m4 == 0);
   3577    vassert(s390_host_has_fpext);
   3578 
   3579    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   3580       s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cdlgbr", r1, m3, r2, m4);
   3581 
   3582    return emit_RRF2(p, 0xb3a10000, m3, m4, r1, r2);
   3583 }
   3584 
   3585 
   3586 static UChar *
   3587 s390_emit_CXLGBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
   3588 {
   3589    vassert(m4 == 0);
   3590    vassert(s390_host_has_fpext);
   3591 
   3592    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   3593       s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cxlgbr", r1, m3, r2, m4);
   3594 
   3595    return emit_RRF2(p, 0xb3a20000, m3, m4, r1, r2);
   3596 }
   3597 
   3598 
   3599 static UChar *
   3600 s390_emit_CLFEBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
   3601 {
   3602    vassert(m4 == 0);
   3603    vassert(s390_host_has_fpext);
   3604 
   3605    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   3606       s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clfebr", r1, m3, r2, m4);
   3607 
   3608    return emit_RRF2(p, 0xb39c0000, m3, m4, r1, r2);
   3609 }
   3610 
   3611 
   3612 static UChar *
   3613 s390_emit_CLFDBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
   3614 {
   3615    vassert(m4 == 0);
   3616    vassert(s390_host_has_fpext);
   3617 
   3618    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   3619       s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clfdbr", r1, m3, r2, m4);
   3620 
   3621    return emit_RRF2(p, 0xb39d0000, m3, m4, r1, r2);
   3622 }
   3623 
   3624 
   3625 static UChar *
   3626 s390_emit_CLFXBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
   3627 {
   3628    vassert(m4 == 0);
   3629    vassert(s390_host_has_fpext);
   3630 
   3631    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   3632       s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clfxbr", r1, m3, r2, m4);
   3633 
   3634    return emit_RRF2(p, 0xb39e0000, m3, m4, r1, r2);
   3635 }
   3636 
   3637 
   3638 static UChar *
   3639 s390_emit_CLGEBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
   3640 {
   3641    vassert(m4 == 0);
   3642    vassert(s390_host_has_fpext);
   3643 
   3644    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   3645       s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clgebr", r1, m3, r2, m4);
   3646 
   3647    return emit_RRF2(p, 0xb3ac0000, m3, m4, r1, r2);
   3648 }
   3649 
   3650 
   3651 static UChar *
   3652 s390_emit_CLGDBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
   3653 {
   3654    vassert(m4 == 0);
   3655    vassert(s390_host_has_fpext);
   3656 
   3657    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   3658       s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clgdbr", r1, m3, r2, m4);
   3659 
   3660    return emit_RRF2(p, 0xb3ad0000, m3, m4, r1, r2);
   3661 }
   3662 
   3663 
   3664 static UChar *
   3665 s390_emit_CLGXBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
   3666 {
   3667    vassert(m4 == 0);
   3668    vassert(s390_host_has_fpext);
   3669 
   3670    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   3671       s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clgxbr", r1, m3, r2, m4);
   3672 
   3673    return emit_RRF2(p, 0xb3ae0000, m3, m4, r1, r2);
   3674 }
   3675 
   3676 
   3677 static UChar *
   3678 s390_emit_CFEBR(UChar *p, UChar r3, UChar r1, UChar r2)
   3679 {
   3680    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   3681       s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cfebr", r1, r3, r2);
   3682 
   3683    return emit_RRF3(p, 0xb3980000, r3, r1, r2);
   3684 }
   3685 
   3686 
   3687 static UChar *
   3688 s390_emit_CFDBR(UChar *p, UChar r3, UChar r1, UChar r2)
   3689 {
   3690    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   3691       s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cfdbr", r1, r3, r2);
   3692 
   3693    return emit_RRF3(p, 0xb3990000, r3, r1, r2);
   3694 }
   3695 
   3696 
   3697 static UChar *
   3698 s390_emit_CFXBR(UChar *p, UChar r3, UChar r1, UChar r2)
   3699 {
   3700    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   3701       s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cfxbr", r1, r3, r2);
   3702 
   3703    return emit_RRF3(p, 0xb39a0000, r3, r1, r2);
   3704 }
   3705 
   3706 
   3707 static UChar *
   3708 s390_emit_CGEBR(UChar *p, UChar r3, UChar r1, UChar r2)
   3709 {
   3710    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   3711       s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cgebr", r1, r3, r2);
   3712 
   3713    return emit_RRF3(p, 0xb3a80000, r3, r1, r2);
   3714 }
   3715 
   3716 
   3717 static UChar *
   3718 s390_emit_CGDBR(UChar *p, UChar r3, UChar r1, UChar r2)
   3719 {
   3720    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   3721       s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cgdbr", r1, r3, r2);
   3722 
   3723    return emit_RRF3(p, 0xb3a90000, r3, r1, r2);
   3724 }
   3725 
   3726 
   3727 static UChar *
   3728 s390_emit_CGXBR(UChar *p, UChar r3, UChar r1, UChar r2)
   3729 {
   3730    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   3731       s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cgxbr", r1, r3, r2);
   3732 
   3733    return emit_RRF3(p, 0xb3aa0000, r3, r1, r2);
   3734 }
   3735 
   3736 
   3737 static UChar *
   3738 s390_emit_DEBR(UChar *p, UChar r1, UChar r2)
   3739 {
   3740    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   3741       s390_disasm(ENC3(MNM, FPR, FPR), "debr", r1, r2);
   3742 
   3743    return emit_RRE(p, 0xb30d0000, r1, r2);
   3744 }
   3745 
   3746 
   3747 static UChar *
   3748 s390_emit_DDBR(UChar *p, UChar r1, UChar r2)
   3749 {
   3750    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   3751       s390_disasm(ENC3(MNM, FPR, FPR), "ddbr", r1, r2);
   3752 
   3753    return emit_RRE(p, 0xb31d0000, r1, r2);
   3754 }
   3755 
   3756 
   3757 static UChar *
   3758 s390_emit_DXBR(UChar *p, UChar r1, UChar r2)
   3759 {
   3760    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   3761       s390_disasm(ENC3(MNM, FPR, FPR), "dxbr", r1, r2);
   3762 
   3763    return emit_RRE(p, 0xb34d0000, r1, r2);
   3764 }
   3765 
   3766 
   3767 static UChar *
   3768 s390_emit_LCEBR(UChar *p, UChar r1, UChar r2)
   3769 {
   3770    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   3771       s390_disasm(ENC3(MNM, FPR, FPR), "lcebr", r1, r2);
   3772 
   3773    return emit_RRE(p, 0xb3030000, r1, r2);
   3774 }
   3775 
   3776 
   3777 static UChar *
   3778 s390_emit_LCDBR(UChar *p, UChar r1, UChar r2)
   3779 {
   3780    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   3781       s390_disasm(ENC3(MNM, FPR, FPR), "lcdbr", r1, r2);
   3782 
   3783    return emit_RRE(p, 0xb3130000, r1, r2);
   3784 }
   3785 
   3786 
   3787 static UChar *
   3788 s390_emit_LCXBR(UChar *p, UChar r1, UChar r2)
   3789 {
   3790    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   3791       s390_disasm(ENC3(MNM, FPR, FPR), "lcxbr", r1, r2);
   3792 
   3793    return emit_RRE(p, 0xb3430000, r1, r2);
   3794 }
   3795 
   3796 
   3797 static UChar *
   3798 s390_emit_LDEBR(UChar *p, UChar r1, UChar r2)
   3799 {
   3800    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   3801       s390_disasm(ENC3(MNM, FPR, FPR), "ldebr", r1, r2);
   3802 
   3803    return emit_RRE(p, 0xb3040000, r1, r2);
   3804 }
   3805 
   3806 
   3807 static UChar *
   3808 s390_emit_LXDBR(UChar *p, UChar r1, UChar r2)
   3809 {
   3810    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   3811       s390_disasm(ENC3(MNM, FPR, FPR), "lxdbr", r1, r2);
   3812 
   3813    return emit_RRE(p, 0xb3050000, r1, r2);
   3814 }
   3815 
   3816 
   3817 static UChar *
   3818 s390_emit_LXEBR(UChar *p, UChar r1, UChar r2)
   3819 {
   3820    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   3821       s390_disasm(ENC3(MNM, FPR, FPR), "lxebr", r1, r2);
   3822 
   3823    return emit_RRE(p, 0xb3060000, r1, r2);
   3824 }
   3825 
   3826 
   3827 static UChar *
   3828 s390_emit_LNEBR(UChar *p, UChar r1, UChar r2)
   3829 {
   3830    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   3831       s390_disasm(ENC3(MNM, FPR, FPR), "lnebr", r1, r2);
   3832 
   3833    return emit_RRE(p, 0xb3010000, r1, r2);
   3834 }
   3835 
   3836 
   3837 static UChar *
   3838 s390_emit_LNDBR(UChar *p, UChar r1, UChar r2)
   3839 {
   3840    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   3841       s390_disasm(ENC3(MNM, FPR, FPR), "lndbr", r1, r2);
   3842 
   3843    return emit_RRE(p, 0xb3110000, r1, r2);
   3844 }
   3845 
   3846 
   3847 static UChar *
   3848 s390_emit_LNXBR(UChar *p, UChar r1, UChar r2)
   3849 {
   3850    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   3851       s390_disasm(ENC3(MNM, FPR, FPR), "lnxbr", r1, r2);
   3852 
   3853    return emit_RRE(p, 0xb3410000, r1, r2);
   3854 }
   3855 
   3856 
   3857 static UChar *
   3858 s390_emit_LPEBR(UChar *p, UChar r1, UChar r2)
   3859 {
   3860    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   3861       s390_disasm(ENC3(MNM, FPR, FPR), "lpebr", r1, r2);
   3862 
   3863    return emit_RRE(p, 0xb3000000, r1, r2);
   3864 }
   3865 
   3866 
   3867 static UChar *
   3868 s390_emit_LPDBR(UChar *p, UChar r1, UChar r2)
   3869 {
   3870    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   3871       s390_disasm(ENC3(MNM, FPR, FPR), "lpdbr", r1, r2);
   3872 
   3873    return emit_RRE(p, 0xb3100000, r1, r2);
   3874 }
   3875 
   3876 
   3877 static UChar *
   3878 s390_emit_LPXBR(UChar *p, UChar r1, UChar r2)
   3879 {
   3880    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   3881       s390_disasm(ENC3(MNM, FPR, FPR), "lpxbr", r1, r2);
   3882 
   3883    return emit_RRE(p, 0xb3400000, r1, r2);
   3884 }
   3885 
   3886 
   3887 static UChar *
   3888 s390_emit_LEDBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
   3889 {
   3890    vassert(m4 == 0);
   3891    vassert(m3 == 0 || s390_host_has_fpext);
   3892 
   3893    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
   3894       if (m3 == 0)
   3895          s390_disasm(ENC3(MNM, FPR, FPR), "ledbr", r1, r2);
   3896       else
   3897          s390_disasm(ENC5(MNM, FPR, UINT, FPR, UINT),
   3898                      "ledbra", r1, m3, r2, m4);
   3899    }
   3900 
   3901    return emit_RRF2(p, 0xb3440000, m3, m4, r1, r2);
   3902 }
   3903 
   3904 
   3905 static UChar *
   3906 s390_emit_LDXBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
   3907 {
   3908    vassert(m4 == 0);
   3909    vassert(m3 == 0 || s390_host_has_fpext);
   3910 
   3911    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
   3912       if (m3 == 0)
   3913          s390_disasm(ENC3(MNM, FPR, FPR), "ldxbr", r1, r2);
   3914       else
   3915          s390_disasm(ENC5(MNM, FPR, UINT, FPR, UINT),
   3916                      "ldxbra", r1, m3, r2, m4);
   3917    }
   3918 
   3919    return emit_RRF2(p, 0xb3450000, m3, m4, r1, r2);
   3920 }
   3921 
   3922 
   3923 static UChar *
   3924 s390_emit_LEXBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
   3925 {
   3926    vassert(m4 == 0);
   3927    vassert(m3 == 0 || s390_host_has_fpext);
   3928 
   3929    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
   3930       if (m3 == 0)
   3931          s390_disasm(ENC3(MNM, FPR, FPR), "lexbr", r1, r2);
   3932       else
   3933          s390_disasm(ENC5(MNM, FPR, UINT, FPR, UINT),
   3934                      "lexbra", r1, m3, r2, m4);
   3935    }
   3936 
   3937    return emit_RRF2(p, 0xb3460000, m3, m4, r1, r2);
   3938 }
   3939 
   3940 
   3941 static UChar *
   3942 s390_emit_FIEBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
   3943 {
   3944    vassert(m3 == 0 || s390_host_has_fpext);
   3945 
   3946    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
   3947       if (m4 == 0)
   3948          s390_disasm(ENC4(MNM, FPR, UINT, FPR), "fiebr", r1, m3, r2);
   3949       else
   3950          s390_disasm(ENC5(MNM, FPR, UINT, FPR, UINT),
   3951                      "fiebra", r1, m3, r2, m4);
   3952    }
   3953 
   3954    return emit_RRF2(p, 0xb3570000, m3, m4, r1, r2);
   3955 }
   3956 
   3957 
   3958 static UChar *
   3959 s390_emit_FIDBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
   3960 {
   3961    vassert(m3 == 0 || s390_host_has_fpext);
   3962 
   3963    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
   3964       if (m4 == 0)
   3965          s390_disasm(ENC4(MNM, FPR, UINT, FPR), "fidbr", r1, m3, r2);
   3966       else
   3967          s390_disasm(ENC5(MNM, FPR, UINT, FPR, UINT),
   3968                      "fidbra", r1, m3, r2, m4);
   3969    }
   3970 
   3971    return emit_RRF2(p, 0xb35f0000, m3, m4, r1, r2);
   3972 }
   3973 
   3974 
   3975 static UChar *
   3976 s390_emit_FIXBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
   3977 {
   3978    vassert(m3 == 0 || s390_host_has_fpext);
   3979 
   3980    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
   3981       if (m4 == 0)
   3982          s390_disasm(ENC4(MNM, FPR, UINT, FPR), "fixbr", r1, m3, r2);
   3983       else
   3984          s390_disasm(ENC5(MNM, FPR, UINT, FPR, UINT),
   3985                      "fixbra", r1, m3, r2, m4);
   3986    }
   3987 
   3988    return emit_RRF2(p, 0xb3470000, m3, m4, r1, r2);
   3989 }
   3990 
   3991 
   3992 static UChar *
   3993 s390_emit_MEEBR(UChar *p, UChar r1, UChar r2)
   3994 {
   3995    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   3996       s390_disasm(ENC3(MNM, FPR, FPR), "meebr", r1, r2);
   3997 
   3998    return emit_RRE(p, 0xb3170000, r1, r2);
   3999 }
   4000 
   4001 
   4002 static UChar *
   4003 s390_emit_MDBR(UChar *p, UChar r1, UChar r2)
   4004 {
   4005    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   4006       s390_disasm(ENC3(MNM, FPR, FPR), "mdbr", r1, r2);
   4007 
   4008    return emit_RRE(p, 0xb31c0000, r1, r2);
   4009 }
   4010 
   4011 
   4012 static UChar *
   4013 s390_emit_MXBR(UChar *p, UChar r1, UChar r2)
   4014 {
   4015    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   4016       s390_disasm(ENC3(MNM, FPR, FPR), "mxbr", r1, r2);
   4017 
   4018    return emit_RRE(p, 0xb34c0000, r1, r2);
   4019 }
   4020 
   4021 
   4022 static UChar *
   4023 s390_emit_MAEBR(UChar *p, UChar r1, UChar r3, UChar r2)
   4024 {
   4025    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   4026       s390_disasm(ENC4(MNM, FPR, FPR, FPR), "maebr", r1, r3, r2);
   4027 
   4028    return emit_RRF(p, 0xb30e0000, r1, r3, r2);
   4029 }
   4030 
   4031 
   4032 static UChar *
   4033 s390_emit_MADBR(UChar *p, UChar r1, UChar r3, UChar r2)
   4034 {
   4035    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   4036       s390_disasm(ENC4(MNM, FPR, FPR, FPR), "madbr", r1, r3, r2);
   4037 
   4038    return emit_RRF(p, 0xb31e0000, r1, r3, r2);
   4039 }
   4040 
   4041 
   4042 static UChar *
   4043 s390_emit_MSEBR(UChar *p, UChar r1, UChar r3, UChar r2)
   4044 {
   4045    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   4046       s390_disasm(ENC4(MNM, FPR, FPR, FPR), "msebr", r1, r3, r2);
   4047 
   4048    return emit_RRF(p, 0xb30f0000, r1, r3, r2);
   4049 }
   4050 
   4051 
   4052 static UChar *
   4053 s390_emit_MSDBR(UChar *p, UChar r1, UChar r3, UChar r2)
   4054 {
   4055    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   4056       s390_disasm(ENC4(MNM, FPR, FPR, FPR), "msdbr", r1, r3, r2);
   4057 
   4058    return emit_RRF(p, 0xb31f0000, r1, r3, r2);
   4059 }
   4060 
   4061 
   4062 static UChar *
   4063 s390_emit_SQEBR(UChar *p, UChar r1, UChar r2)
   4064 {
   4065    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   4066       s390_disasm(ENC3(MNM, FPR, FPR), "sqebr", r1, r2);
   4067 
   4068    return emit_RRE(p, 0xb3140000, r1, r2);
   4069 }
   4070 
   4071 
   4072 static UChar *
   4073 s390_emit_SQDBR(UChar *p, UChar r1, UChar r2)
   4074 {
   4075    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   4076       s390_disasm(ENC3(MNM, FPR, FPR), "sqdbr", r1, r2);
   4077 
   4078    return emit_RRE(p, 0xb3150000, r1, r2);
   4079 }
   4080 
   4081 
   4082 static UChar *
   4083 s390_emit_SQXBR(UChar *p, UChar r1, UChar r2)
   4084 {
   4085    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   4086       s390_disasm(ENC3(MNM, FPR, FPR), "sqxbr", r1, r2);
   4087 
   4088    return emit_RRE(p, 0xb3160000, r1, r2);
   4089 }
   4090 
   4091 
   4092 static UChar *
   4093 s390_emit_SEBR(UChar *p, UChar r1, UChar r2)
   4094 {
   4095    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   4096       s390_disasm(ENC3(MNM, FPR, FPR), "sebr", r1, r2);
   4097 
   4098    return emit_RRE(p, 0xb30b0000, r1, r2);
   4099 }
   4100 
   4101 
   4102 static UChar *
   4103 s390_emit_SDBR(UChar *p, UChar r1, UChar r2)
   4104 {
   4105    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   4106       s390_disasm(ENC3(MNM, FPR, FPR), "sdbr", r1, r2);
   4107 
   4108    return emit_RRE(p, 0xb31b0000, r1, r2);
   4109 }
   4110 
   4111 
   4112 static UChar *
   4113 s390_emit_SXBR(UChar *p, UChar r1, UChar r2)
   4114 {
   4115    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   4116       s390_disasm(ENC3(MNM, FPR, FPR), "sxbr", r1, r2);
   4117 
   4118    return emit_RRE(p, 0xb34b0000, r1, r2);
   4119 }
   4120 
   4121 
   4122 static UChar *
   4123 s390_emit_ADTRA(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
   4124 {
   4125    vassert(s390_host_has_dfp);
   4126    vassert(m4 == 0 || s390_host_has_fpext);
   4127    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
   4128       if (m4 == 0)
   4129          s390_disasm(ENC4(MNM, FPR, FPR, FPR), "adtr", r1, r2, r3);
   4130       else
   4131          s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "adtra", r1, r2, r3, m4);
   4132    }
   4133 
   4134    return emit_RRF4(p, 0xb3d20000, r3, m4, r1, r2);
   4135 }
   4136 
   4137 
   4138 static UChar *
   4139 s390_emit_AXTRA(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
   4140 {
   4141    vassert(s390_host_has_dfp);
   4142    vassert(m4 == 0 || s390_host_has_fpext);
   4143    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
   4144       if (m4 == 0)
   4145          s390_disasm(ENC4(MNM, FPR, FPR, FPR), "axtr", r1, r2, r3);
   4146       else
   4147          s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "axtra", r1, r2, r3, m4);
   4148    }
   4149 
   4150    return emit_RRF4(p, 0xb3da0000, r3, m4, r1, r2);
   4151 }
   4152 
   4153 
   4154 static UChar *
   4155 s390_emit_CDTR(UChar *p, UChar r1, UChar r2)
   4156 {
   4157    vassert(s390_host_has_dfp);
   4158    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   4159       s390_disasm(ENC3(MNM, FPR, FPR), "cdtr", r1, r2);
   4160 
   4161    return emit_RRE(p, 0xb3e40000, r1, r2);
   4162 }
   4163 
   4164 
   4165 static UChar *
   4166 s390_emit_CXTR(UChar *p, UChar r1, UChar r2)
   4167 {
   4168    vassert(s390_host_has_dfp);
   4169    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   4170       s390_disasm(ENC3(MNM, FPR, FPR), "cxtr", r1, r2);
   4171 
   4172    return emit_RRE(p, 0xb3ec0000, r1, r2);
   4173 }
   4174 
   4175 
   4176 static UChar *
   4177 s390_emit_CDGTRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
   4178 {
   4179    vassert(s390_host_has_dfp);
   4180    vassert(m4 == 0);
   4181    vassert(m3 == 0 || s390_host_has_fpext);
   4182 
   4183    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
   4184       if (m3 == 0)
   4185          s390_disasm(ENC3(MNM, FPR, GPR), "cdgtr", r1, r2);
   4186       else
   4187          s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cdgtra", r1, m3, r2, m4);
   4188    }
   4189 
   4190    return emit_RRF2(p, 0xb3f10000, m3, m4, r1, r2);
   4191 }
   4192 
   4193 
   4194 static UChar *
   4195 s390_emit_CXGTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
   4196 {
   4197    vassert(s390_host_has_dfp);
   4198    vassert(m4 == 0);
   4199    /* rounding mode m3 is not considered, as the corresponding
   4200       IRop (Iop_I64StoD128) does not take rounding mode. */
   4201    vassert(m3 == 0);
   4202 
   4203    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   4204       s390_disasm(ENC3(MNM, FPR, GPR), "cxgtr", r1, r2);
   4205 
   4206    return emit_RRF2(p, 0xb3f90000, m3, m4, r1, r2);
   4207 }
   4208 
   4209 
   4210 static UChar *
   4211 s390_emit_CDFTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
   4212 {
   4213    vassert(m4 == 0);
   4214    vassert(s390_host_has_dfp);
   4215    vassert(s390_host_has_fpext);
   4216 
   4217    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   4218       s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cdftr", r1, m3, r2, m4);
   4219 
   4220    return emit_RRF2(p, 0xb9510000, m3, m4, r1, r2);
   4221 }
   4222 
   4223 
   4224 static UChar *
   4225 s390_emit_CXFTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
   4226 {
   4227    vassert(m4 == 0);
   4228    vassert(s390_host_has_dfp);
   4229    vassert(s390_host_has_fpext);
   4230 
   4231    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   4232       s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cxftr", r1, m3, r2, m4);
   4233 
   4234    return emit_RRF2(p, 0xb9590000, m3, m4, r1, r2);
   4235 }
   4236 
   4237 
   4238 static UChar *
   4239 s390_emit_CDLFTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
   4240 {
   4241    vassert(m4 == 0);
   4242    vassert(s390_host_has_dfp);
   4243    vassert(s390_host_has_fpext);
   4244 
   4245    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   4246       s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cdlftr", r1, m3, r2, m4);
   4247 
   4248    return emit_RRF2(p, 0xb9530000, m3, m4, r1, r2);
   4249 }
   4250 
   4251 
   4252 static UChar *
   4253 s390_emit_CXLFTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
   4254 {
   4255    vassert(m4 == 0);
   4256    vassert(s390_host_has_dfp);
   4257    vassert(s390_host_has_fpext);
   4258 
   4259    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   4260       s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cxlftr", r1, m3, r2, m4);
   4261 
   4262    return emit_RRF2(p, 0xb95b0000, m3, m4, r1, r2);
   4263 }
   4264 
   4265 
   4266 static UChar *
   4267 s390_emit_CDLGTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
   4268 {
   4269    vassert(m4 == 0);
   4270    vassert(s390_host_has_dfp);
   4271    vassert(s390_host_has_fpext);
   4272 
   4273    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   4274       s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cdlgtr", r1, m3, r2, m4);
   4275 
   4276    return emit_RRF2(p, 0xb9520000, m3, m4, r1, r2);
   4277 }
   4278 
   4279 
   4280 static UChar *
   4281 s390_emit_CXLGTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
   4282 {
   4283    vassert(m4 == 0);
   4284    vassert(s390_host_has_dfp);
   4285    vassert(s390_host_has_fpext);
   4286 
   4287    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   4288       s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cxlgtr", r1, m3, r2, m4);
   4289 
   4290    return emit_RRF2(p, 0xb95a0000, m3, m4, r1, r2);
   4291 }
   4292 
   4293 
   4294 static UChar *
   4295 s390_emit_CEDTR(UChar *p, UChar r1, UChar r2)
   4296 {
   4297    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   4298       s390_disasm(ENC3(MNM, FPR, FPR), "cedtr", r1, r2);
   4299 
   4300    return emit_RRE(p, 0xb3f40000, r1, r2);
   4301 }
   4302 
   4303 
   4304 static UChar *
   4305 s390_emit_CEXTR(UChar *p, UChar r1, UChar r2)
   4306 {
   4307    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   4308       s390_disasm(ENC3(MNM, FPR, FPR), "cextr", r1, r2);
   4309 
   4310    return emit_RRE(p, 0xb3fc0000, r1, r2);
   4311 }
   4312 
   4313 
   4314 static UChar *
   4315 s390_emit_CFDTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
   4316 {
   4317    vassert(m4 == 0);
   4318    vassert(s390_host_has_dfp);
   4319    vassert(s390_host_has_fpext);
   4320 
   4321    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   4322       s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "cfdtr", r1, m3, r2, m4);
   4323 
   4324    return emit_RRF2(p, 0xb9410000, m3, m4, r1, r2);
   4325 }
   4326 
   4327 
   4328 static UChar *
   4329 s390_emit_CFXTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
   4330 {
   4331    vassert(m4 == 0);
   4332    vassert(s390_host_has_dfp);
   4333    vassert(s390_host_has_fpext);
   4334 
   4335    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   4336       s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "cfxtr", r1, m3, r2, m4);
   4337 
   4338    return emit_RRF2(p, 0xb9490000, m3, m4, r1, r2);
   4339 }
   4340 
   4341 
   4342 static UChar *
   4343 s390_emit_CGDTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
   4344 {
   4345    vassert(s390_host_has_dfp);
   4346    vassert(m4 == 0);
   4347    vassert(s390_host_has_fpext || m3 < 1 || m3 > 7);
   4348 
   4349    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   4350       s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cgdtr", r1, m3, r2);
   4351 
   4352    return emit_RRF2(p, 0xb3e10000, m3, m4, r1, r2);
   4353 }
   4354 
   4355 
   4356 static UChar *
   4357 s390_emit_CGXTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
   4358 {
   4359    vassert(s390_host_has_dfp);
   4360    vassert(m4 == 0);
   4361    vassert(s390_host_has_fpext || m3 < 1 || m3 > 7);
   4362 
   4363    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   4364       s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cgxtr", r1, m3, r2);
   4365 
   4366    return emit_RRF2(p, 0xb3e90000, m3, m4, r1, r2);
   4367 }
   4368 
   4369 
   4370 static UChar *
   4371 s390_emit_CLFDTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
   4372 {
   4373    vassert(m4 == 0);
   4374    vassert(s390_host_has_dfp);
   4375    vassert(s390_host_has_fpext);
   4376 
   4377    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   4378       s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clfdtr", r1, m3, r2, m4);
   4379 
   4380    return emit_RRF2(p, 0xb9430000, m3, m4, r1, r2);
   4381 }
   4382 
   4383 
   4384 static UChar *
   4385 s390_emit_CLFXTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
   4386 {
   4387    vassert(m4 == 0);
   4388    vassert(s390_host_has_dfp);
   4389    vassert(s390_host_has_fpext);
   4390 
   4391    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   4392       s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clfxtr", r1, m3, r2, m4);
   4393 
   4394    return emit_RRF2(p, 0xb94b0000, m3, m4, r1, r2);
   4395 }
   4396 
   4397 
   4398 static UChar *
   4399 s390_emit_CLGDTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
   4400 {
   4401    vassert(m4 == 0);
   4402    vassert(s390_host_has_dfp);
   4403    vassert(s390_host_has_fpext);
   4404 
   4405    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   4406       s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clgdtr", r1, m3, r2, m4);
   4407 
   4408    return emit_RRF2(p, 0xb9420000, m3, m4, r1, r2);
   4409 }
   4410 
   4411 
   4412 static UChar *
   4413 s390_emit_CLGXTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
   4414 {
   4415    vassert(m4 == 0);
   4416    vassert(s390_host_has_dfp);
   4417    vassert(s390_host_has_fpext);
   4418 
   4419    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   4420       s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clgxtr", r1, m3, r2, m4);
   4421 
   4422    return emit_RRF2(p, 0xb94a0000, m3, m4, r1, r2);
   4423 }
   4424 
   4425 
   4426 static UChar *
   4427 s390_emit_DDTRA(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
   4428 {
   4429    vassert(s390_host_has_dfp);
   4430    vassert(m4 == 0 || s390_host_has_fpext);
   4431    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
   4432       if (m4 == 0)
   4433          s390_disasm(ENC4(MNM, FPR, FPR, FPR), "ddtr", r1, r2, r3);
   4434       else
   4435          s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "ddtra", r1, r2, r3, m4);
   4436    }
   4437 
   4438    return emit_RRF4(p, 0xb3d10000, r3, m4, r1, r2);
   4439 }
   4440 
   4441 
   4442 static UChar *
   4443 s390_emit_DXTRA(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
   4444 {
   4445    vassert(s390_host_has_dfp);
   4446    vassert(m4 == 0 || s390_host_has_fpext);
   4447    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
   4448       if (m4 == 0)
   4449          s390_disasm(ENC4(MNM, FPR, FPR, FPR), "dxtr", r1, r2, r3);
   4450       else
   4451          s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "dxtra", r1, r2, r3, m4);
   4452    }
   4453 
   4454    return emit_RRF4(p, 0xb3d90000, r3, m4, r1, r2);
   4455 }
   4456 
   4457 
   4458 static UChar *
   4459 s390_emit_EEDTR(UChar *p, UChar r1, UChar r2)
   4460 {
   4461    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   4462       s390_disasm(ENC3(MNM, GPR, FPR), "eedtr", r1, r2);
   4463 
   4464    return emit_RRE(p, 0xb3e50000, r1, r2);
   4465 }
   4466 
   4467 
   4468 static UChar *
   4469 s390_emit_EEXTR(UChar *p, UChar r1, UChar r2)
   4470 {
   4471    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   4472       s390_disasm(ENC3(MNM, GPR, FPR), "eextr", r1, r2);
   4473 
   4474    return emit_RRE(p, 0xb3ed0000, r1, r2);
   4475 }
   4476 
   4477 
   4478 static UChar *
   4479 s390_emit_ESDTR(UChar *p, UChar r1, UChar r2)
   4480 {
   4481    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   4482       s390_disasm(ENC3(MNM, GPR, FPR), "esdtr", r1, r2);
   4483 
   4484    return emit_RRE(p, 0xb3e70000, r1, r2);
   4485 }
   4486 
   4487 
   4488 static UChar *
   4489 s390_emit_ESXTR(UChar *p, UChar r1, UChar r2)
   4490 {
   4491    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   4492       s390_disasm(ENC3(MNM, GPR, FPR), "esxtr", r1, r2);
   4493 
   4494    return emit_RRE(p, 0xb3ef0000, r1, r2);
   4495 }
   4496 
   4497 
   4498 static UChar *
   4499 s390_emit_IEDTR(UChar *p, UChar r3, UChar r1, UChar r2)
   4500 {
   4501    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   4502       s390_disasm(ENC4(MNM, FPR, FPR, GPR), "iedtr", r1, r3, r2);
   4503 
   4504    return emit_RRF(p, 0xb3f60000, r3, r1, r2);
   4505 }
   4506 
   4507 
   4508 static UChar *
   4509 s390_emit_IEXTR(UChar *p, UChar r3, UChar r1, UChar r2)
   4510 {
   4511    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   4512       s390_disasm(ENC4(MNM, FPR, FPR, GPR), "iextr", r1, r3, r2);
   4513 
   4514    return emit_RRF(p, 0xb3fe0000, r3, r1, r2);
   4515 }
   4516 
   4517 
   4518 static UChar *
   4519 s390_emit_LDETR(UChar *p, UChar m4, UChar r1, UChar r2)
   4520 {
   4521    vassert(s390_host_has_dfp);
   4522    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   4523       s390_disasm(ENC4(MNM, FPR, FPR, UINT), "ldetr", r1, r2, m4);
   4524 
   4525    return emit_RRF5(p, 0xb3d40000, m4, r1, r2);
   4526 }
   4527 
   4528 
   4529 static UChar *
   4530 s390_emit_LXDTR(UChar *p, UChar m4, UChar r1, UChar r2)
   4531 {
   4532    vassert(s390_host_has_dfp);
   4533    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   4534       s390_disasm(ENC4(MNM, FPR, FPR, UINT), "lxdtr", r1, r2, m4);
   4535 
   4536    return emit_RRF5(p, 0xb3dc0000, m4, r1, r2);
   4537 }
   4538 
   4539 
   4540 static UChar *
   4541 s390_emit_LEDTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
   4542 {
   4543    vassert(s390_host_has_dfp);
   4544    vassert(m4 == 0);
   4545    vassert(s390_host_has_fpext || m3 < 1 || m3 > 7);
   4546 
   4547    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   4548       s390_disasm(ENC5(MNM, FPR, UINT, FPR, UINT), "ledtr", r1, m3, r2, m4);
   4549 
   4550    return emit_RRF2(p, 0xb3d50000, m3, m4, r1, r2);
   4551 }
   4552 
   4553 
   4554 static UChar *
   4555 s390_emit_LDXTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
   4556 {
   4557    vassert(s390_host_has_dfp);
   4558    vassert(m4 == 0);
   4559    vassert(s390_host_has_fpext || m3 < 1 || m3 > 7);
   4560 
   4561    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   4562       s390_disasm(ENC5(MNM, FPR, UINT, FPR, UINT), "ldxtr", r1, m3, r2, m4);
   4563 
   4564    return emit_RRF2(p, 0xb3dd0000, m3, m4, r1, r2);
   4565 }
   4566 
   4567 
   4568 static UChar *
   4569 s390_emit_MDTRA(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
   4570 {
   4571    vassert(s390_host_has_dfp);
   4572    vassert(m4 == 0 || s390_host_has_fpext);
   4573    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
   4574       if (m4 == 0)
   4575          s390_disasm(ENC4(MNM, FPR, FPR, FPR), "mdtr", r1, r2, r3);
   4576       else
   4577          s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "mdtra", r1, r2, r3, m4);
   4578    }
   4579 
   4580    return emit_RRF4(p, 0xb3d00000, r3, m4, r1, r2);
   4581 }
   4582 
   4583 
   4584 static UChar *
   4585 s390_emit_MXTRA(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
   4586 {
   4587    vassert(s390_host_has_dfp);
   4588    vassert(m4 == 0 || s390_host_has_fpext);
   4589    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
   4590       if (m4 == 0)
   4591          s390_disasm(ENC4(MNM, FPR, FPR, FPR), "mxtr", r1, r2, r3);
   4592       else
   4593          s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "mxtra", r1, r2, r3, m4);
   4594    }
   4595 
   4596    return emit_RRF4(p, 0xb3d80000, r3, m4, r1, r2);
   4597 }
   4598 
   4599 
   4600 static UChar *
   4601 emit_E(UChar *p, UInt op)
   4602 {
   4603    ULong the_insn = op;
   4604 
   4605    return emit_2bytes(p, the_insn);
   4606 }
   4607 
   4608 
   4609 static UChar *
   4610 s390_emit_PFPO(UChar *p)
   4611 {
   4612    vassert(s390_host_has_pfpo);
   4613    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
   4614       s390_disasm(ENC1(MNM), "pfpo");
   4615    }
   4616 
   4617    return emit_E(p, 0x010a);
   4618 }
   4619 
   4620 
   4621 static UChar *
   4622 s390_emit_QADTR(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
   4623 {
   4624    vassert(s390_host_has_dfp);
   4625    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   4626       s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "qadtr", r1, r3, r2, m4);
   4627 
   4628    return emit_RRF4(p, 0xb3f50000, r3, m4, r1, r2);
   4629 }
   4630 
   4631 
   4632 static UChar *
   4633 s390_emit_QAXTR(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
   4634 {
   4635    vassert(s390_host_has_dfp);
   4636    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   4637       s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "qaxtr", r1, r3, r2, m4);
   4638 
   4639    return emit_RRF4(p, 0xb3fd0000, r3, m4, r1, r2);
   4640 }
   4641 
   4642 
   4643 static UChar *
   4644 s390_emit_RRDTR(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
   4645 {
   4646    vassert(s390_host_has_dfp);
   4647    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   4648       s390_disasm(ENC5(MNM, FPR, FPR, GPR, UINT), "rrdtr", r1, r3, r2, m4);
   4649 
   4650    return emit_RRF4(p, 0xb3f70000, r3, m4, r1, r2);
   4651 }
   4652 
   4653 
   4654 static UChar *
   4655 s390_emit_RRXTR(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
   4656 {
   4657    vassert(s390_host_has_dfp);
   4658    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   4659       s390_disasm(ENC5(MNM, FPR, FPR, GPR, UINT), "rrxtr", r1, r3, r2, m4);
   4660 
   4661    return emit_RRF4(p, 0xb3ff0000, r3, m4, r1, r2);
   4662 }
   4663 
   4664 
   4665 static UChar *
   4666 s390_emit_SDTRA(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
   4667 {
   4668    vassert(s390_host_has_dfp);
   4669    vassert(m4 == 0 || s390_host_has_fpext);
   4670    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
   4671       if (m4 == 0)
   4672          s390_disasm(ENC4(MNM, FPR, FPR, FPR), "sdtr", r1, r2, r3);
   4673       else
   4674          s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "sdtra", r1, r2, r3, m4);
   4675    }
   4676 
   4677    return emit_RRF4(p, 0xb3d30000, r3, m4, r1, r2);
   4678 }
   4679 
   4680 
   4681 static UChar *
   4682 s390_emit_SXTRA(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
   4683 {
   4684    vassert(s390_host_has_dfp);
   4685    vassert(m4 == 0 || s390_host_has_fpext);
   4686    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
   4687       if (m4 == 0)
   4688          s390_disasm(ENC4(MNM, FPR, FPR, FPR), "sxtr", r1, r2, r3);
   4689       else
   4690          s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "sxtra", r1, r2, r3, m4);
   4691    }
   4692 
   4693    return emit_RRF4(p, 0xb3db0000, r3, m4, r1, r2);
   4694 }
   4695 
   4696 
   4697 static UChar *
   4698 s390_emit_SLDT(UChar *p, UChar r3, UChar r1, UChar r2)
   4699 {
   4700    vassert(s390_host_has_dfp);
   4701    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   4702       s390_disasm(ENC4(MNM, FPR, FPR, UDXB), "sldt", r1, r3, 0, 0, r2);
   4703 
   4704    return emit_RXF(p, 0xED0000000040ULL, r3, 0, r2, 0, r1);
   4705 }
   4706 
   4707 
   4708 static UChar *
   4709 s390_emit_SLXT(UChar *p, UChar r3, UChar r1, UChar r2)
   4710 {
   4711    vassert(s390_host_has_dfp);
   4712    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   4713       s390_disasm(ENC4(MNM, FPR, FPR, UDXB), "slxt", r1, r3, 0, 0, r2);
   4714 
   4715    return emit_RXF(p, 0xED0000000048ULL, r3, 0, r2, 0, r1);
   4716 }
   4717 
   4718 
   4719 static UChar *
   4720 s390_emit_SRDT(UChar *p, UChar r3, UChar r1, UChar r2)
   4721 {
   4722    vassert(s390_host_has_dfp);
   4723    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   4724       s390_disasm(ENC4(MNM, FPR, FPR, UDXB), "srdt", r1, r3, 0, 0, r2);
   4725 
   4726    return emit_RXF(p, 0xED0000000041ULL, r3, 0, r2, 0, r1);
   4727 }
   4728 
   4729 
   4730 static UChar *
   4731 s390_emit_SRXT(UChar *p, UChar r3, UChar r1, UChar r2)
   4732 {
   4733    vassert(s390_host_has_dfp);
   4734    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   4735       s390_disasm(ENC4(MNM, FPR, FPR, UDXB), "srxt", r1, r3, 0, 0, r2);
   4736 
   4737    return emit_RXF(p, 0xED0000000049ULL, r3, 0, r2, 0, r1);
   4738 }
   4739 
   4740 
   4741 static UChar *
   4742 s390_emit_LOCGR(UChar *p, UChar m3, UChar r1, UChar r2)
   4743 {
   4744    vassert(s390_host_has_lsc);
   4745    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   4746       s390_disasm(ENC4(MNM, GPR, GPR, UINT), "locgr", r1, r2, m3);
   4747 
   4748    return emit_RRF3(p, 0xb9e20000, m3, r1, r2);
   4749 }
   4750 
   4751 
   4752 static UChar *
   4753 s390_emit_LOC(UChar *p, UChar r1, UChar m3, UChar b2, UShort dl2, UChar dh2)
   4754 {
   4755    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   4756       s390_disasm(ENC4(MNM, GPR, UINT, SDXB), "loc", r1, m3, dh2, dl2, 0, b2);
   4757 
   4758    return emit_RSY(p, 0xeb00000000f2ULL, r1, m3, b2, dl2, dh2);
   4759 }
   4760 
   4761 
   4762 static UChar *
   4763 s390_emit_LOCG(UChar *p, UChar r1, UChar m3, UChar b2, UShort dl2, UChar dh2)
   4764 {
   4765    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   4766       s390_disasm(ENC4(MNM, GPR, UINT, SDXB), "locg", r1, m3, dh2, dl2, 0, b2);
   4767 
   4768    return emit_RSY(p, 0xeb00000000e2ULL, r1, m3, b2, dl2, dh2);
   4769 }
   4770 
   4771 
   4772 /* Provide a symbolic name for register "R0" */
   4773 #define R0 0
   4774 
   4775 /* Split up a 20-bit displacement into its high and low piece
   4776    suitable for passing as function arguments */
   4777 #define DISP20(d) (((UInt)d) & 0xFFF), ((((UInt)d) >> 12) & 0xFF)
   4778 
   4779 /*---------------------------------------------------------------*/
   4780 /*--- Helper functions                                        ---*/
   4781 /*---------------------------------------------------------------*/
   4782 
   4783 static __inline__ Bool
   4784 uint_fits_signed_16bit(UInt val)
   4785 {
   4786    UInt v = val & 0xFFFFu;
   4787 
   4788    /* sign extend */
   4789    v = (Int)(v << 16) >> 16;
   4790 
   4791    return val == v;
   4792 }
   4793 
   4794 
   4795 static __inline__ Bool
   4796 ulong_fits_signed_16bit(ULong val)
   4797 {
   4798    ULong v = val & 0xFFFFu;
   4799 
   4800    /* sign extend */
   4801    v = (Long)(v << 48) >> 48;
   4802 
   4803    return val == v;
   4804 }
   4805 
   4806 
   4807 static __inline__ Bool
   4808 ulong_fits_signed_32bit(ULong val)
   4809 {
   4810    ULong v = val & 0xFFFFFFFFu;
   4811 
   4812    /* sign extend */
   4813    v = (Long)(v << 32) >> 32;
   4814 
   4815    return val == v;
   4816 }
   4817 
   4818 
   4819 static __inline__ Bool
   4820 ulong_fits_unsigned_32bit(ULong val)
   4821 {
   4822    return (val & 0xFFFFFFFFu) == val;
   4823 }
   4824 
   4825 
   4826 /* Load a 64-bit immediate VAL into register REG. */
   4827 static UChar *
   4828 s390_emit_load_64imm(UChar *p, UChar reg, ULong val)
   4829 {
   4830    if (ulong_fits_signed_16bit(val)) {
   4831       return s390_emit_LGHI(p, reg, val);
   4832    }
   4833 
   4834    if (s390_host_has_eimm) {
   4835       if (ulong_fits_unsigned_32bit(val)) {
   4836          return s390_emit_LLILF(p, reg, val);
   4837       }
   4838       if (ulong_fits_signed_32bit(val)) {
   4839          /* LGFI's sign extension will recreate the correct 64-bit value */
   4840          return s390_emit_LGFI(p, reg, val);
   4841       }
   4842       /* Do it in two steps: upper half [0:31] and lower half [32:63] */
   4843       p =  s390_emit_IIHF(p, reg, val >> 32);
   4844       return s390_emit_IILF(p, reg, val & 0xFFFFFFFF);
   4845    }
   4846 
   4847    /* Fall back */
   4848    if (ulong_fits_unsigned_32bit(val)) {
   4849       p = s390_emit_LLILH(p, reg, (val >> 16) & 0xFFFF); /* sets val[32:47]
   4850                                                             val[0:31] = 0 */
   4851       p = s390_emit_IILL(p, reg, val & 0xFFFF);          /* sets val[48:63] */
   4852       return p;
   4853    }
   4854 
   4855    p = s390_emit_IIHH(p, reg, (val >> 48) & 0xFFFF);
   4856    p = s390_emit_IIHL(p, reg, (val >> 32) & 0xFFFF);
   4857    p = s390_emit_IILH(p, reg, (val >> 16) & 0xFFFF);
   4858    p = s390_emit_IILL(p, reg, val & 0xFFFF);
   4859 
   4860    return p;
   4861 }
   4862 
   4863 /* Load a 32-bit immediate VAL into register REG. */
   4864 static UChar *
   4865 s390_emit_load_32imm(UChar *p, UChar reg, UInt val)
   4866 {
   4867    if (uint_fits_signed_16bit(val)) {
   4868       /* LHI's sign extension will recreate the correct 32-bit value */
   4869       return s390_emit_LHI(p, reg, val);
   4870    }
   4871    if (s390_host_has_eimm) {
   4872       return s390_emit_IILF(p, reg, val);
   4873    }
   4874    /* val[0:15]  --> (val >> 16) & 0xFFFF
   4875       val[16:31] --> val & 0xFFFF */
   4876    p = s390_emit_IILH(p, reg, (val >> 16) & 0xFFFF);
   4877    return s390_emit_IILL(p, reg, val & 0xFFFF);
   4878 }
   4879 
   4880 /*------------------------------------------------------------*/
   4881 /*--- Wrapper functions                                    ---*/
   4882 /*------------------------------------------------------------*/
   4883 
   4884 /* r1[32:63],r1+1[32:63] = r1+1[32:63] * memory[op2addr][0:31] */
   4885 static UChar *
   4886 s390_emit_MFYw(UChar *p, UChar r1, UChar x, UChar b,  UShort dl, UChar dh)
   4887 {
   4888    if (s390_host_has_gie) {
   4889       return s390_emit_MFY(p, r1, x, b, dl, dh);
   4890    }
   4891 
   4892    /* Load from memory into R0, then MULTIPLY with R1 */
   4893    p = s390_emit_LY(p, R0, x, b, dl, dh);
   4894    return s390_emit_MR(p, r1, R0);
   4895 }
   4896 
   4897 /* r1[32:63] = r1[32:63] * memory[op2addr][0:15] */
   4898 static UChar *
   4899 s390_emit_MHYw(UChar *p, UChar r1, UChar x, UChar b,  UShort dl, UChar dh)
   4900 {
   4901    if (s390_host_has_gie) {
   4902       return s390_emit_MHY(p, r1, x, b, dl, dh);
   4903    }
   4904 
   4905    /* Load from memory into R0, then MULTIPLY with R1 */
   4906    p = s390_emit_LHY(p, R0, x, b, dl, dh);
   4907    return s390_emit_MSR(p, r1, R0);
   4908 }
   4909 
   4910 /* r1[32:63] = r1[32:63] * i2 */
   4911 static UChar *
   4912 s390_emit_MSFIw(UChar *p, UChar r1, UInt i2)
   4913 {
   4914    if (s390_host_has_gie) {
   4915       return s390_emit_MSFI(p, r1, i2);
   4916    }
   4917 
   4918    /* Load I2 into R0; then MULTIPLY R0 with R1 */
   4919    p = s390_emit_load_32imm(p, R0, i2);
   4920    return s390_emit_MSR(p, r1, R0);
   4921 }
   4922 
   4923 
   4924 /* r1[32:63] = r1[32:63] & i2 */
   4925 static UChar *
   4926 s390_emit_NILFw(UChar *p, UChar r1, UInt i2)
   4927 {
   4928    if (s390_host_has_eimm) {
   4929       return s390_emit_NILF(p, r1, i2);
   4930    }
   4931 
   4932    /* Load I2 into R0; then AND R0 with R1 */
   4933    p = s390_emit_load_32imm(p, R0, i2);
   4934    return s390_emit_NR(p, r1, R0);
   4935 }
   4936 
   4937 
   4938 /* r1[32:63] = r1[32:63] | i2 */
   4939 static UChar *
   4940 s390_emit_OILFw(UChar *p, UChar r1, UInt i2)
   4941 {
   4942    if (s390_host_has_eimm) {
   4943       return s390_emit_OILF(p, r1, i2);
   4944    }
   4945 
   4946    /* Load I2 into R0; then AND R0 with R1 */
   4947    p = s390_emit_load_32imm(p, R0, i2);
   4948    return s390_emit_OR(p, r1, R0);
   4949 }
   4950 
   4951 
   4952 /* r1[32:63] = r1[32:63] ^ i2 */
   4953 static UChar *
   4954 s390_emit_XILFw(UChar *p, UChar r1, UInt i2)
   4955 {
   4956    if (s390_host_has_eimm) {
   4957       return s390_emit_XILF(p, r1, i2);
   4958    }
   4959 
   4960    /* Load I2 into R0; then AND R0 with R1 */
   4961    p = s390_emit_load_32imm(p, R0, i2);
   4962    return s390_emit_XR(p, r1, R0);
   4963 }
   4964 
   4965 
   4966 /*  r1[32:63] = sign_extend(r2[56:63]) */
   4967 static UChar *
   4968 s390_emit_LBRw(UChar *p, UChar r1, UChar r2)
   4969 {
   4970    if (s390_host_has_eimm) {
   4971       return s390_emit_LBR(p, r1, r2);
   4972    }
   4973 
   4974    p = s390_emit_LR(p, r1, r2);               /* r1 = r2 */
   4975    p = s390_emit_SLL(p, r1, R0, 24);          /* r1 = r1 << 24  */
   4976    return s390_emit_SRA(p, r1, R0, 24);       /* r1 = r1 >>a 24 */
   4977 }
   4978 
   4979 
   4980 /*  r1[0:63] = sign_extend(r2[56:63]) */
   4981 static UChar *
   4982 s390_emit_LGBRw(UChar *p, UChar r1, UChar r2)
   4983 {
   4984    if (s390_host_has_eimm) {
   4985       return s390_emit_LGBR(p, r1, r2);
   4986    }
   4987 
   4988    p = s390_emit_LR(p, r1, r2);                       /* r1 = r2 */
   4989    p = s390_emit_SLLG(p, r1, r1, R0, DISP20(56));     /* r1 = r1 << 56  */
   4990    return s390_emit_SRAG(p, r1, r1, R0, DISP20(56));  /* r1 = r1 >>a 56 */
   4991 }
   4992 
   4993 
   4994 /* r1[32:63] = sign_extend(r2[48:63]) */
   4995 static UChar *
   4996 s390_emit_LHRw(UChar *p, UChar r1, UChar r2)
   4997 {
   4998    if (s390_host_has_eimm) {
   4999       return s390_emit_LHR(p, r1, r2);
   5000    }
   5001 
   5002    p = s390_emit_LR(p, r1, r2);               /* r1 = r2 */
   5003    p = s390_emit_SLL(p, r1, R0, 16);          /* r1 = r1 << 16  */
   5004    return s390_emit_SRA(p, r1, R0, 16);       /* r1 = r1 >>a 16 */
   5005 }
   5006 
   5007 
   5008 /* r1[0:63] = sign_extend(r2[48:63]) */
   5009 static UChar *
   5010 s390_emit_LGHRw(UChar *p, UChar r1, UChar r2)
   5011 {
   5012    if (s390_host_has_eimm) {
   5013       return s390_emit_LGHR(p, r1, r2);
   5014    }
   5015 
   5016    p = s390_emit_LR(p, r1, r2);               /* r1 = r2 */
   5017    p = s390_emit_SLLG(p, r1, r1, R0, DISP20(48));     /* r1 = r1 << 48  */
   5018    return s390_emit_SRAG(p, r1, r1, R0, DISP20(48));  /* r1 = r1 >>a 48 */
   5019 }
   5020 
   5021 
   5022 /* r1[0:63] = sign_extend(i2) */
   5023 static UChar *
   5024 s390_emit_LGFIw(UChar *p, UChar r1, UInt i2)
   5025 {
   5026    if (s390_host_has_eimm) {
   5027       return s390_emit_LGFI(p, r1, i2);
   5028    }
   5029 
   5030    p = s390_emit_load_32imm(p, R0, i2);
   5031    return s390_emit_LGFR(p, r1, R0);
   5032 }
   5033 
   5034 
   5035 /* r1[32:63] = zero_extend($r2[56:63]) */
   5036 static UChar *
   5037 s390_emit_LLCRw(UChar *p, UChar r1, UChar r2)
   5038 {
   5039    if (s390_host_has_eimm) {
   5040       return s390_emit_LLCR(p, r1, r2);
   5041    }
   5042 
   5043    p = s390_emit_LR(p, r1, r2);
   5044    p = s390_emit_LHI(p, R0, 0xFF);
   5045    return s390_emit_NR(p, r1, R0);
   5046 }
   5047 
   5048 
   5049 /* r1[0:63] = zero_extend($r2[56:63]) */
   5050 static UChar *
   5051 s390_emit_LLGCRw(UChar *p, UChar r1, UChar r2)
   5052 {
   5053    if (s390_host_has_eimm) {
   5054       return s390_emit_LLGCR(p, r1, r2);
   5055    }
   5056 
   5057    p = s390_emit_LR(p, r1, r2);
   5058    p = s390_emit_LLILL(p, R0, 0xFF);
   5059    return s390_emit_NGR(p, r1, R0);
   5060 }
   5061 
   5062 
   5063 /* r1[32:63] = zero_extend(r2[48:63]) */
   5064 static UChar *
   5065 s390_emit_LLHRw(UChar *p, UChar r1, UChar r2)
   5066 {
   5067    if (s390_host_has_eimm) {
   5068       return s390_emit_LLHR(p, r1, r2);
   5069    }
   5070 
   5071    p = s390_emit_LR(p, r1, r2);
   5072    p = s390_emit_LLILL(p, R0, 0xFFFF);
   5073    return s390_emit_NR(p, r1, R0);
   5074 }
   5075 
   5076 
   5077 /* r1[0:63] = zero_extend(r2[48:63]) */
   5078 static UChar *
   5079 s390_emit_LLGHRw(UChar *p, UChar r1, UChar r2)
   5080 {
   5081    if (s390_host_has_eimm) {
   5082       return s390_emit_LLGHR(p, r1, r2);
   5083    }
   5084 
   5085    p = s390_emit_LR(p, r1, r2);
   5086    p = s390_emit_LLILL(p, R0, 0xFFFF);
   5087    return s390_emit_NGR(p, r1, R0);
   5088 }
   5089 
   5090 
   5091 /* r1[32:63] = zero_extend(mem[op2addr][0:7]) */
   5092 static UChar *
   5093 s390_emit_LLCw(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl, UChar dh)
   5094 {
   5095    if (s390_host_has_eimm) {
   5096       return s390_emit_LLC(p, r1, x2, b2, dl, dh);
   5097    }
   5098 
   5099    if (dh == 0) {
   5100       p = s390_emit_IC(p, r1, x2, b2, dl);
   5101    } else {
   5102       p = s390_emit_ICY(p, r1, x2, b2, dl, dh);
   5103    }
   5104    p = s390_emit_LLILL(p, R0, 0xFF);
   5105    return s390_emit_NR(p, r1, R0);
   5106 }
   5107 
   5108 
   5109 /* r1[32:63] = zero_extend(mem[op2addr][0:15]) */
   5110 static UChar *
   5111 s390_emit_LLHw(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl, UChar dh)
   5112 {
   5113    if (s390_host_has_eimm) {
   5114       return s390_emit_LLH(p, r1, x2, b2, dl, dh);
   5115    }
   5116 
   5117    p = s390_emit_LLGH(p, r1, x2, b2, dl, dh);
   5118    p = s390_emit_LLILL(p, R0, 0xFFFF);
   5119    return s390_emit_NR(p, r1, R0);
   5120 }
   5121 
   5122 
   5123 /* r1[0:63] = zero_extend(i2) */
   5124 static UChar *
   5125 s390_emit_LLILFw(UChar *p, UChar r1, UInt i2)
   5126 {
   5127    if (s390_host_has_eimm) {
   5128       return s390_emit_LLILF(p, r1, i2);
   5129    }
   5130 
   5131    p = s390_emit_LLILH(p, r1, (i2 >> 16) & 0xFFFF);  /* i2[0:15] */
   5132    return s390_emit_OILL(p, r1, i2 & 0xFFFF);
   5133 }
   5134 
   5135 
   5136 /* r1[32:63] = r1[32:63] + i2 */
   5137 static UChar *
   5138 s390_emit_AFIw(UChar *p, UChar r1, UInt i2)
   5139 {
   5140    if (s390_host_has_eimm) {
   5141       return s390_emit_AFI(p, r1, i2);
   5142    }
   5143    /* Load 32 bit immediate to R0 then add */
   5144    p = s390_emit_load_32imm(p, R0, i2);
   5145    return s390_emit_AR(p, r1, R0);
   5146 }
   5147 
   5148 
   5149 /* r1[32:63] = r1[32:63] - i2 */
   5150 static UChar *
   5151 s390_emit_SLFIw(UChar *p, UChar r1, UInt i2)
   5152 {
   5153    if (s390_host_has_eimm) {
   5154       return s390_emit_SLFI(p, r1, i2);
   5155    }
   5156 
   5157    /* Load 32 bit immediate to R0 then subtract */
   5158    p = s390_emit_load_32imm(p, R0, i2);
   5159    return s390_emit_SR(p, r1, R0);
   5160 }
   5161 
   5162 
   5163 /* r1[0:63] = r1[0:63] - zero_extend(i2) */
   5164 static UChar *
   5165 s390_emit_SLGFIw(UChar *p, UChar r1, UInt i2)
   5166 {
   5167    if (s390_host_has_eimm) {
   5168       return s390_emit_SLGFI(p, r1, i2);
   5169    }
   5170 
   5171    /* Load zero-extended 32 bit immediate to R0 then subtract */
   5172    p = s390_emit_load_64imm(p, R0, i2);
   5173    return s390_emit_SGR(p, r1, R0);
   5174 }
   5175 
   5176 
   5177 static UChar *
   5178 s390_emit_LTw(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl, UChar dh)
   5179 {
   5180    if (s390_host_has_eimm) {
   5181       return s390_emit_LT(p, r1, x2, b2, dl, dh);
   5182    }
   5183    /* Load 32 bit from memory to R0 then compare */
   5184    if (dh == 0) {
   5185       p = s390_emit_L(p, R0, x2, b2, dl);
   5186    } else {
   5187       p = s390_emit_LY(p, R0, x2, b2, dl, dh);
   5188    }
   5189    return s390_emit_LTR(p, r1, R0);
   5190 }
   5191 
   5192 
   5193 static UChar *
   5194 s390_emit_LTGw(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl, UChar dh)
   5195 {
   5196    if (s390_host_has_eimm) {
   5197       return s390_emit_LTG(p, r1, x2, b2, dl, dh);
   5198    }
   5199    /* Load 64 bit from memory to R0 then compare */
   5200    p = s390_emit_LG(p, R0, x2, b2, dl, dh);
   5201    return s390_emit_LTGR(p, r1, R0);
   5202 }
   5203 
   5204 
   5205 static UChar *
   5206 s390_emit_CFIw(UChar *p, UChar r1, UInt i2)
   5207 {
   5208    if (s390_host_has_eimm) {
   5209       return s390_emit_CFI(p, r1, i2);
   5210    }
   5211    /* Load 32 bit immediate to R0 then compare */
   5212    p = s390_emit_load_32imm(p, R0, i2);
   5213    return s390_emit_CR(p, r1, R0);
   5214 }
   5215 
   5216 
   5217 static UChar *
   5218 s390_emit_CLFIw(UChar *p, UChar r1, UInt i2)
   5219 {
   5220    if (s390_host_has_eimm) {
   5221       return s390_emit_CLFI(p, r1, i2);
   5222    }
   5223    /* Load 32 bit immediate to R0 then compare */
   5224    p = s390_emit_load_32imm(p, R0, i2);
   5225    return s390_emit_CLR(p, r1, R0);
   5226 }
   5227 
   5228 
   5229 static UChar *
   5230 s390_emit_LGDRw(UChar *p, UChar r1, UChar r2)
   5231 {
   5232    if (s390_host_has_fgx) {
   5233       return s390_emit_LGDR(p, r1, r2);
   5234    }
   5235 
   5236    /* Store the FPR at memory[sp - 8]. This is safe because SP grows towards
   5237       smaller addresses and is 8-byte aligned. Then load the GPR from that
   5238       memory location/ */
   5239    p = s390_emit_STDY(p, r2, R0, S390_REGNO_STACK_POINTER, DISP20(-8));
   5240    return s390_emit_LG(p, r1, R0, S390_REGNO_STACK_POINTER, DISP20(-8));
   5241 }
   5242 
   5243 
   5244 static UChar *
   5245 s390_emit_LDGRw(UChar *p, UChar r1, UChar r2)
   5246 {
   5247    if (s390_host_has_fgx) {
   5248       return s390_emit_LDGR(p, r1, r2);
   5249    }
   5250 
   5251    /* Store the GPR at memory[sp - 8]. This is safe because SP grows towards
   5252       smaller addresses and is 8-byte aligned. Then load the FPR from that
   5253       memory location/ */
   5254    p = s390_emit_STG(p, r2, R0, S390_REGNO_STACK_POINTER, DISP20(-8));
   5255    return s390_emit_LDY(p, r1, R0, S390_REGNO_STACK_POINTER, DISP20(-8));
   5256 }
   5257 
   5258 
   5259 /*---------------------------------------------------------------*/
   5260 /*--- Constructors for the various s390_insn kinds            ---*/
   5261 /*---------------------------------------------------------------*/
   5262 
   5263 s390_insn *
   5264 s390_insn_load(UChar size, HReg dst, s390_amode *src)
   5265 {
   5266    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   5267 
   5268    insn->tag  = S390_INSN_LOAD;
   5269    insn->size = size;
   5270    insn->variant.load.src  = src;
   5271    insn->variant.load.dst  = dst;
   5272 
   5273    vassert(size == 1 || size == 2 || size == 4 || size == 8);
   5274 
   5275    return insn;
   5276 }
   5277 
   5278 
   5279 s390_insn *
   5280 s390_insn_store(UChar size, s390_amode *dst, HReg src)
   5281 {
   5282    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   5283 
   5284    insn->tag  = S390_INSN_STORE;
   5285    insn->size = size;
   5286    insn->variant.store.src  = src;
   5287    insn->variant.store.dst  = dst;
   5288 
   5289    vassert(size == 1 || size == 2 || size == 4 || size == 8);
   5290 
   5291    return insn;
   5292 }
   5293 
   5294 
   5295 s390_insn *
   5296 s390_insn_move(UChar size, HReg dst, HReg src)
   5297 {
   5298    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   5299 
   5300    insn->tag  = S390_INSN_MOVE;
   5301    insn->size = size;
   5302    insn->variant.move.src  = src;
   5303    insn->variant.move.dst  = dst;
   5304 
   5305    vassert(size == 1 || size == 2 || size == 4 || size == 8);
   5306 
   5307    return insn;
   5308 }
   5309 
   5310 
   5311 s390_insn *
   5312 s390_insn_memcpy(UChar size, s390_amode *dst, s390_amode *src)
   5313 {
   5314    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   5315 
   5316    /* This insn will be mapped to MVC which requires base register
   5317       plus 12-bit displacement */
   5318    vassert(src->tag == S390_AMODE_B12);
   5319    vassert(dst->tag == S390_AMODE_B12);
   5320 
   5321    insn->tag  = S390_INSN_MEMCPY;
   5322    insn->size = size;
   5323    insn->variant.memcpy.src = src;
   5324    insn->variant.memcpy.dst = dst;
   5325 
   5326    vassert(size == 1 || size == 2 || size == 4 || size == 8);
   5327 
   5328    return insn;
   5329 }
   5330 
   5331 
   5332 s390_insn *
   5333 s390_insn_cond_move(UChar size, s390_cc_t cond, HReg dst, s390_opnd_RMI src)
   5334 {
   5335    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   5336 
   5337    insn->tag  = S390_INSN_COND_MOVE;
   5338    insn->size = size;
   5339    insn->variant.cond_move.cond = cond;
   5340    insn->variant.cond_move.src  = src;
   5341    insn->variant.cond_move.dst  = dst;
   5342 
   5343    vassert(size == 1 || size == 2 || size == 4 || size == 8);
   5344 
   5345    return insn;
   5346 }
   5347 
   5348 
   5349 s390_insn *
   5350 s390_insn_load_immediate(UChar size, HReg dst, ULong value)
   5351 {
   5352    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   5353 
   5354    insn->tag  = S390_INSN_LOAD_IMMEDIATE;
   5355    insn->size = size;
   5356    insn->variant.load_immediate.dst   = dst;
   5357    insn->variant.load_immediate.value = value;
   5358 
   5359    return insn;
   5360 }
   5361 
   5362 
   5363 s390_insn *
   5364 s390_insn_alu(UChar size, s390_alu_t tag, HReg dst, s390_opnd_RMI op2)
   5365 {
   5366    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   5367 
   5368    insn->tag  = S390_INSN_ALU;
   5369    insn->size = size;
   5370    insn->variant.alu.tag = tag;
   5371    insn->variant.alu.dst = dst;
   5372    insn->variant.alu.op2 = op2;
   5373 
   5374    return insn;
   5375 }
   5376 
   5377 
   5378 s390_insn *
   5379 s390_insn_mul(UChar size, HReg dst_hi, HReg dst_lo, s390_opnd_RMI op2,
   5380               Bool signed_multiply)
   5381 {
   5382    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   5383 
   5384    vassert(! hregIsVirtual(dst_hi));
   5385    vassert(! hregIsVirtual(dst_lo));
   5386 
   5387    insn->tag  = signed_multiply ? S390_INSN_SMUL : S390_INSN_UMUL;
   5388    insn->size = size;
   5389    insn->variant.mul.dst_hi = dst_hi;
   5390    insn->variant.mul.dst_lo = dst_lo;
   5391    insn->variant.mul.op2 = op2;
   5392 
   5393    return insn;
   5394 }
   5395 
   5396 
   5397 s390_insn *
   5398 s390_insn_div(UChar size, HReg op1_hi, HReg op1_lo, s390_opnd_RMI op2,
   5399               Bool signed_divide)
   5400 {
   5401    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   5402 
   5403    vassert(size == 4 || size == 8);
   5404    vassert(! hregIsVirtual(op1_hi));
   5405    vassert(! hregIsVirtual(op1_lo));
   5406 
   5407    insn->tag  = signed_divide ? S390_INSN_SDIV : S390_INSN_UDIV;
   5408    insn->size = size;
   5409    insn->variant.div.op1_hi = op1_hi;
   5410    insn->variant.div.op1_lo = op1_lo;
   5411    insn->variant.div.op2 = op2;
   5412 
   5413    return insn;
   5414 }
   5415 
   5416 
   5417 s390_insn *
   5418 s390_insn_divs(UChar size, HReg rem, HReg op1, s390_opnd_RMI op2)
   5419 {
   5420    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   5421 
   5422    vassert(size == 8);
   5423    vassert(! hregIsVirtual(op1));
   5424    vassert(! hregIsVirtual(rem));
   5425 
   5426    insn->tag  = S390_INSN_DIVS;
   5427    insn->size = size;
   5428    insn->variant.divs.rem = rem;   /* remainder */
   5429    insn->variant.divs.op1 = op1;   /* also quotient */
   5430    insn->variant.divs.op2 = op2;
   5431 
   5432    return insn;
   5433 }
   5434 
   5435 
   5436 s390_insn *
   5437 s390_insn_clz(UChar size, HReg num_bits, HReg clobber, s390_opnd_RMI src)
   5438 {
   5439    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   5440 
   5441    vassert(size == 8);
   5442    vassert(! hregIsVirtual(num_bits));
   5443    vassert(! hregIsVirtual(clobber));
   5444 
   5445    insn->tag  = S390_INSN_CLZ;
   5446    insn->size = size;
   5447    insn->variant.clz.num_bits = num_bits;
   5448    insn->variant.clz.clobber  = clobber;
   5449    insn->variant.clz.src = src;
   5450 
   5451    return insn;
   5452 }
   5453 
   5454 
   5455 s390_insn *
   5456 s390_insn_unop(UChar size, s390_unop_t tag, HReg dst, s390_opnd_RMI opnd)
   5457 {
   5458    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   5459 
   5460    insn->tag  = S390_INSN_UNOP;
   5461    insn->size = size;
   5462    insn->variant.unop.tag = tag;
   5463    insn->variant.unop.dst = dst;
   5464    insn->variant.unop.src = opnd;
   5465 
   5466    return insn;
   5467 }
   5468 
   5469 
   5470 s390_insn *
   5471 s390_insn_test(UChar size, s390_opnd_RMI src)
   5472 {
   5473    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   5474 
   5475    vassert(size == 4 || size == 8);
   5476 
   5477    insn->tag  = S390_INSN_TEST;
   5478    insn->size = size;
   5479    insn->variant.test.src = src;
   5480 
   5481    return insn;
   5482 }
   5483 
   5484 
   5485 s390_insn *
   5486 s390_insn_cc2bool(HReg dst, s390_cc_t cond)
   5487 {
   5488    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   5489 
   5490    insn->tag  = S390_INSN_CC2BOOL;
   5491    insn->size = 0;   /* does not matter */
   5492    insn->variant.cc2bool.cond = cond;
   5493    insn->variant.cc2bool.dst  = dst;
   5494 
   5495    return insn;
   5496 }
   5497 
   5498 
   5499 s390_insn *
   5500 s390_insn_cas(UChar size, HReg op1, s390_amode *op2, HReg op3, HReg old_mem)
   5501 {
   5502    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   5503 
   5504    vassert(size == 4 || size == 8);
   5505    vassert(hregNumber(op2->x) == 0);
   5506    vassert(op2->tag == S390_AMODE_B12 || op2->tag == S390_AMODE_B20);
   5507 
   5508    insn->tag  = S390_INSN_CAS;
   5509    insn->size = size;
   5510    insn->variant.cas.op1 = op1;
   5511    insn->variant.cas.op2 = op2;
   5512    insn->variant.cas.op3 = op3;
   5513    insn->variant.cas.old_mem = old_mem;
   5514 
   5515    return insn;
   5516 }
   5517 
   5518 
   5519 s390_insn *
   5520 s390_insn_cdas(UChar size, HReg op1_high, HReg op1_low, s390_amode *op2,
   5521                HReg op3_high, HReg op3_low, HReg old_mem_high, HReg old_mem_low,
   5522                HReg scratch)
   5523 {
   5524    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   5525    s390_cdas *cdas = LibVEX_Alloc_inline(sizeof(s390_cdas));
   5526 
   5527    vassert(size == 4 || size == 8);
   5528    vassert(hregNumber(op2->x) == 0);
   5529    vassert(hregNumber(scratch) == 1);  /* r0,r1 used as scratch reg pair */
   5530    vassert(op2->tag == S390_AMODE_B12 || op2->tag == S390_AMODE_B20);
   5531 
   5532    insn->tag  = S390_INSN_CDAS;
   5533    insn->size = size;
   5534    insn->variant.cdas.details = cdas;
   5535 
   5536    cdas->op1_high = op1_high;
   5537    cdas->op1_low  = op1_low;
   5538    cdas->op2 = op2;
   5539    cdas->op3_high = op3_high;
   5540    cdas->op3_low  = op3_low;
   5541    cdas->old_mem_high = old_mem_high;
   5542    cdas->old_mem_low  = old_mem_low;
   5543    cdas->scratch = scratch;
   5544 
   5545    return insn;
   5546 }
   5547 
   5548 
   5549 s390_insn *
   5550 s390_insn_compare(UChar size, HReg src1, s390_opnd_RMI src2,
   5551                   Bool signed_comparison)
   5552 {
   5553    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   5554 
   5555    vassert(size == 4 || size == 8);
   5556 
   5557    insn->tag  = S390_INSN_COMPARE;
   5558    insn->size = size;
   5559    insn->variant.compare.src1 = src1;
   5560    insn->variant.compare.src2 = src2;
   5561    insn->variant.compare.signed_comparison = signed_comparison;
   5562 
   5563    return insn;
   5564 }
   5565 
   5566 
   5567 s390_insn *
   5568 s390_insn_helper_call(s390_cc_t cond, Addr64 target, UInt num_args,
   5569                       const HChar *name, RetLoc rloc)
   5570 {
   5571    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   5572    s390_helper_call *helper_call = LibVEX_Alloc_inline(sizeof(s390_helper_call));
   5573 
   5574    insn->tag  = S390_INSN_HELPER_CALL;
   5575    insn->size = 0;  /* does not matter */
   5576    insn->variant.helper_call.details = helper_call;
   5577 
   5578    helper_call->cond = cond;
   5579    helper_call->target = target;
   5580    helper_call->num_args = num_args;
   5581    helper_call->name = name;
   5582    helper_call->rloc = rloc;
   5583 
   5584    vassert(is_sane_RetLoc(rloc));
   5585 
   5586    return insn;
   5587 }
   5588 
   5589 
   5590 s390_insn *
   5591 s390_insn_bfp_triop(UChar size, s390_bfp_triop_t tag, HReg dst, HReg op2,
   5592                     HReg op3)
   5593 {
   5594    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   5595 
   5596    vassert(size == 4 || size == 8);
   5597 
   5598    insn->tag  = S390_INSN_BFP_TRIOP;
   5599    insn->size = size;
   5600    insn->variant.bfp_triop.tag = tag;
   5601    insn->variant.bfp_triop.dst = dst;
   5602    insn->variant.bfp_triop.op2 = op2;
   5603    insn->variant.bfp_triop.op3 = op3;
   5604 
   5605    return insn;
   5606 }
   5607 
   5608 
   5609 s390_insn *
   5610 s390_insn_bfp_binop(UChar size, s390_bfp_binop_t tag, HReg dst, HReg op2)
   5611 {
   5612    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   5613 
   5614    vassert(size == 4 || size == 8);
   5615 
   5616    insn->tag  = S390_INSN_BFP_BINOP;
   5617    insn->size = size;
   5618    insn->variant.bfp_binop.tag = tag;
   5619    insn->variant.bfp_binop.dst_hi = dst;
   5620    insn->variant.bfp_binop.op2_hi = op2;
   5621    insn->variant.bfp_binop.dst_lo = INVALID_HREG;
   5622    insn->variant.bfp_binop.op2_lo = INVALID_HREG;
   5623 
   5624    return insn;
   5625 }
   5626 
   5627 
   5628 s390_insn *
   5629 s390_insn_bfp_unop(UChar size, s390_bfp_unop_t tag, HReg dst, HReg op)
   5630 {
   5631    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   5632 
   5633    vassert(size == 4 || size == 8);
   5634 
   5635    insn->tag  = S390_INSN_BFP_UNOP;
   5636    insn->size = size;
   5637    insn->variant.bfp_unop.tag = tag;
   5638    insn->variant.bfp_unop.dst_hi = dst;
   5639    insn->variant.bfp_unop.op_hi  = op;
   5640    insn->variant.bfp_unop.dst_lo = INVALID_HREG;
   5641    insn->variant.bfp_unop.op_lo  = INVALID_HREG;
   5642 
   5643    return insn;
   5644 }
   5645 
   5646 
   5647 s390_insn *
   5648 s390_insn_bfp_compare(UChar size, HReg dst, HReg op1, HReg op2)
   5649 {
   5650    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   5651 
   5652    vassert(size == 4 || size == 8);
   5653 
   5654    insn->tag  = S390_INSN_BFP_COMPARE;
   5655    insn->size = size;
   5656    insn->variant.bfp_compare.dst = dst;
   5657    insn->variant.bfp_compare.op1_hi = op1;
   5658    insn->variant.bfp_compare.op2_hi = op2;
   5659    insn->variant.bfp_compare.op1_lo = INVALID_HREG;
   5660    insn->variant.bfp_compare.op2_lo = INVALID_HREG;
   5661 
   5662    return insn;
   5663 }
   5664 
   5665 
   5666 s390_insn *
   5667 s390_insn_bfp_convert(UChar size, s390_bfp_conv_t tag, HReg dst, HReg op,
   5668                       s390_bfp_round_t rounding_mode)
   5669 {
   5670    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   5671 
   5672    vassert(size == 4 || size == 8);
   5673 
   5674    insn->tag  = S390_INSN_BFP_CONVERT;
   5675    insn->size = size;
   5676    insn->variant.bfp_convert.tag = tag;
   5677    insn->variant.bfp_convert.dst_hi = dst;
   5678    insn->variant.bfp_convert.op_hi  = op;
   5679    insn->variant.bfp_convert.dst_lo = INVALID_HREG;
   5680    insn->variant.bfp_convert.op_lo  = INVALID_HREG;
   5681    insn->variant.bfp_convert.rounding_mode = rounding_mode;
   5682 
   5683    return insn;
   5684 }
   5685 
   5686 
   5687 /* Check validity of a register pair for 128-bit FP. Valid register
   5688    pairs are (0,2), (1,3), (4, 6), (5, 7), (8, 10), (9, 11), (12, 14),
   5689    and (13, 15). */
   5690 static Bool
   5691 is_valid_fp128_regpair(HReg hi, HReg lo)
   5692 {
   5693    UInt hi_regno = hregNumber(hi);
   5694    UInt lo_regno = hregNumber(lo);
   5695 
   5696    if (lo_regno != hi_regno + 2) return False;
   5697    if ((hi_regno & 0x2) != 0) return False;
   5698 
   5699    return True;
   5700 }
   5701 
   5702 s390_insn *
   5703 s390_insn_bfp128_binop(UChar size, s390_bfp_binop_t tag, HReg dst_hi,
   5704                        HReg dst_lo, HReg op2_hi, HReg op2_lo)
   5705 {
   5706    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   5707 
   5708    vassert(size == 16);
   5709    vassert(is_valid_fp128_regpair(dst_hi, dst_lo));
   5710    vassert(is_valid_fp128_regpair(op2_hi, op2_lo));
   5711 
   5712    insn->tag  = S390_INSN_BFP_BINOP;
   5713    insn->size = size;
   5714    insn->variant.bfp_binop.tag = tag;
   5715    insn->variant.bfp_binop.dst_hi = dst_hi;
   5716    insn->variant.bfp_binop.dst_lo = dst_lo;
   5717    insn->variant.bfp_binop.op2_hi = op2_hi;
   5718    insn->variant.bfp_binop.op2_lo = op2_lo;
   5719 
   5720    return insn;
   5721 }
   5722 
   5723 
   5724 s390_insn *
   5725 s390_insn_bfp128_unop(UChar size, s390_bfp_unop_t tag, HReg dst_hi,
   5726                       HReg dst_lo, HReg op_hi, HReg op_lo)
   5727 {
   5728    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   5729 
   5730    vassert(size == 16);
   5731    vassert(is_valid_fp128_regpair(dst_hi, dst_lo));
   5732    vassert(is_valid_fp128_regpair(op_hi, op_lo));
   5733 
   5734    insn->tag  = S390_INSN_BFP_UNOP;
   5735    insn->size = size;
   5736    insn->variant.bfp_unop.tag = tag;
   5737    insn->variant.bfp_unop.dst_hi = dst_hi;
   5738    insn->variant.bfp_unop.dst_lo = dst_lo;
   5739    insn->variant.bfp_unop.op_hi = op_hi;
   5740    insn->variant.bfp_unop.op_lo = op_lo;
   5741 
   5742    return insn;
   5743 }
   5744 
   5745 
   5746 s390_insn *
   5747 s390_insn_bfp128_compare(UChar size, HReg dst, HReg op1_hi, HReg op1_lo,
   5748                          HReg op2_hi, HReg op2_lo)
   5749 {
   5750    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   5751 
   5752    vassert(size == 16);
   5753    vassert(is_valid_fp128_regpair(op1_hi, op1_lo));
   5754    vassert(is_valid_fp128_regpair(op2_hi, op2_lo));
   5755 
   5756    insn->tag  = S390_INSN_BFP_COMPARE;
   5757    insn->size = size;
   5758    insn->variant.bfp_compare.dst = dst;
   5759    insn->variant.bfp_compare.op1_hi = op1_hi;
   5760    insn->variant.bfp_compare.op1_lo = op1_lo;
   5761    insn->variant.bfp_compare.op2_hi = op2_hi;
   5762    insn->variant.bfp_compare.op2_lo = op2_lo;
   5763 
   5764    return insn;
   5765 }
   5766 
   5767 
   5768 s390_insn *
   5769 s390_insn_bfp128_convert(UChar size, s390_bfp_conv_t tag, HReg dst_hi,
   5770                          HReg dst_lo, HReg op_hi, HReg op_lo,
   5771                          s390_bfp_round_t rounding_mode)
   5772 {
   5773    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   5774 
   5775    if (size == 16) {
   5776       /* From smaller or equal size to 16 bytes */
   5777       vassert(is_valid_fp128_regpair(dst_hi, dst_lo));
   5778       vassert(hregIsInvalid(op_lo)
   5779               || is_valid_fp128_regpair(op_hi, op_lo));
   5780    } else {
   5781       /* From 16 bytes to smaller size */
   5782       vassert(is_valid_fp128_regpair(op_hi, op_lo));
   5783    }
   5784 
   5785    insn->tag  = S390_INSN_BFP_CONVERT;
   5786    insn->size = size;
   5787    insn->variant.bfp_convert.tag = tag;
   5788    insn->variant.bfp_convert.dst_hi = dst_hi;
   5789    insn->variant.bfp_convert.dst_lo = dst_lo;
   5790    insn->variant.bfp_convert.op_hi = op_hi;
   5791    insn->variant.bfp_convert.op_lo = op_lo;
   5792    insn->variant.bfp_convert.rounding_mode = rounding_mode;
   5793 
   5794    return insn;
   5795 }
   5796 
   5797 
   5798 s390_insn *
   5799 s390_insn_bfp128_convert_to(UChar size, s390_bfp_conv_t tag, HReg dst_hi,
   5800                             HReg dst_lo, HReg op)
   5801 {
   5802    /* Conversion to bfp128 never requires a rounding mode. Provide default
   5803       rounding mode. It will not be used when emitting insns. */
   5804    s390_bfp_round_t rounding_mode = S390_BFP_ROUND_NEAREST_EVEN;
   5805 
   5806    return s390_insn_bfp128_convert(size, tag, dst_hi, dst_lo, op,
   5807                                    INVALID_HREG, rounding_mode);
   5808 }
   5809 
   5810 
   5811 s390_insn *
   5812 s390_insn_bfp128_convert_from(UChar size, s390_bfp_conv_t tag, HReg dst_hi,
   5813                               HReg dst_lo, HReg op_hi, HReg op_lo,
   5814                               s390_bfp_round_t rounding_mode)
   5815 {
   5816    return s390_insn_bfp128_convert(size, tag, dst_hi, dst_lo, op_hi, op_lo,
   5817                                    rounding_mode);
   5818 }
   5819 
   5820 
   5821 s390_insn *
   5822 s390_insn_dfp_binop(UChar size, s390_dfp_binop_t tag, HReg dst, HReg op2,
   5823                     HReg op3, s390_dfp_round_t rounding_mode)
   5824 {
   5825    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   5826    s390_dfp_binop *dfp_binop = LibVEX_Alloc_inline(sizeof(s390_dfp_binop));
   5827 
   5828    vassert(size == 8);
   5829 
   5830    insn->tag  = S390_INSN_DFP_BINOP;
   5831    insn->size = size;
   5832    insn->variant.dfp_binop.details = dfp_binop;
   5833 
   5834    dfp_binop->tag = tag;
   5835    dfp_binop->dst_hi = dst;
   5836    dfp_binop->op2_hi = op2;
   5837    dfp_binop->op3_hi = op3;
   5838    dfp_binop->dst_lo = INVALID_HREG;
   5839    dfp_binop->op2_lo = INVALID_HREG;
   5840    dfp_binop->op3_lo = INVALID_HREG;
   5841    dfp_binop->rounding_mode = rounding_mode;
   5842 
   5843    return insn;
   5844 }
   5845 
   5846 
   5847 s390_insn *
   5848 s390_insn_dfp_unop(UChar size, s390_dfp_unop_t tag, HReg dst, HReg op)
   5849 {
   5850    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   5851 
   5852    vassert(size == 8);
   5853 
   5854    insn->tag  = S390_INSN_DFP_UNOP;
   5855    insn->size = size;
   5856    insn->variant.dfp_unop.tag = tag;
   5857    insn->variant.dfp_unop.dst_hi = dst;
   5858    insn->variant.dfp_unop.op_hi  = op;
   5859    insn->variant.dfp_unop.dst_lo = INVALID_HREG;
   5860    insn->variant.dfp_unop.op_lo  = INVALID_HREG;
   5861 
   5862    return insn;
   5863 }
   5864 
   5865 
   5866 s390_insn *
   5867 s390_insn_dfp_intop(UChar size, s390_dfp_intop_t tag, HReg dst, HReg op2,
   5868                     HReg op3)
   5869 {
   5870    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   5871 
   5872    vassert(size == 8);
   5873 
   5874    insn->tag  = S390_INSN_DFP_INTOP;
   5875    insn->size = size;
   5876    insn->variant.dfp_intop.tag = tag;
   5877    insn->variant.dfp_intop.dst_hi = dst;
   5878    insn->variant.dfp_intop.op2    = op2;
   5879    insn->variant.dfp_intop.op3_hi = op3;
   5880    insn->variant.dfp_intop.dst_lo = INVALID_HREG;
   5881    insn->variant.dfp_intop.op3_lo = INVALID_HREG;
   5882 
   5883    return insn;
   5884 }
   5885 
   5886 
   5887 s390_insn *
   5888 s390_insn_dfp_compare(UChar size, s390_dfp_cmp_t tag, HReg dst,
   5889                       HReg op1, HReg op2)
   5890 {
   5891    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   5892 
   5893    vassert(size == 8);
   5894 
   5895    insn->tag  = S390_INSN_DFP_COMPARE;
   5896    insn->size = size;
   5897    insn->variant.dfp_compare.tag = tag;
   5898    insn->variant.dfp_compare.dst = dst;
   5899    insn->variant.dfp_compare.op1_hi = op1;
   5900    insn->variant.dfp_compare.op2_hi = op2;
   5901    insn->variant.dfp_compare.op1_lo = INVALID_HREG;
   5902    insn->variant.dfp_compare.op2_lo = INVALID_HREG;
   5903 
   5904    return insn;
   5905 }
   5906 
   5907 
   5908 s390_insn *
   5909 s390_insn_dfp_convert(UChar size, s390_dfp_conv_t tag, HReg dst, HReg op,
   5910                       s390_dfp_round_t rounding_mode)
   5911 {
   5912    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   5913 
   5914    vassert(size == 4 || size == 8);
   5915 
   5916    insn->tag  = S390_INSN_DFP_CONVERT;
   5917    insn->size = size;
   5918    insn->variant.dfp_convert.tag = tag;
   5919    insn->variant.dfp_convert.dst_hi = dst;
   5920    insn->variant.dfp_convert.op_hi  = op;
   5921    insn->variant.dfp_convert.dst_lo = INVALID_HREG;
   5922    insn->variant.dfp_convert.op_lo  = INVALID_HREG;
   5923    insn->variant.dfp_convert.rounding_mode = rounding_mode;
   5924 
   5925    return insn;
   5926 }
   5927 
   5928 
   5929 s390_insn *
   5930 s390_insn_dfp_reround(UChar size, HReg dst, HReg op2, HReg op3,
   5931                       s390_dfp_round_t rounding_mode)
   5932 {
   5933    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   5934 
   5935    vassert(size == 8);
   5936 
   5937    insn->tag  = S390_INSN_DFP_REROUND;
   5938    insn->size = size;
   5939    insn->variant.dfp_reround.dst_hi = dst;
   5940    insn->variant.dfp_reround.op2 = op2;
   5941    insn->variant.dfp_reround.op3_hi = op3;
   5942    insn->variant.dfp_reround.dst_lo = INVALID_HREG;
   5943    insn->variant.dfp_reround.op3_lo = INVALID_HREG;
   5944    insn->variant.dfp_reround.rounding_mode = rounding_mode;
   5945 
   5946    return insn;
   5947 }
   5948 
   5949 
   5950 s390_insn *
   5951 s390_insn_fp_convert(UChar size, s390_fp_conv_t tag, HReg dst, HReg op,
   5952                      HReg r1, s390_dfp_round_t rounding_mode)
   5953 {
   5954    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   5955    s390_fp_convert *fp_convert = LibVEX_Alloc_inline(sizeof(s390_fp_convert));
   5956 
   5957    vassert(size == 4 || size == 8);
   5958 
   5959    insn->tag  = S390_INSN_FP_CONVERT;
   5960    insn->size = size;
   5961    insn->variant.fp_convert.details = fp_convert;
   5962 
   5963    fp_convert->tag = tag;
   5964    fp_convert->dst_hi = dst;
   5965    fp_convert->op_hi  = op;
   5966    fp_convert->r1 = r1;
   5967    fp_convert->dst_lo = INVALID_HREG;
   5968    fp_convert->op_lo  = INVALID_HREG;
   5969    fp_convert->rounding_mode = rounding_mode;
   5970 
   5971    return insn;
   5972 }
   5973 
   5974 
   5975 s390_insn *
   5976 s390_insn_fp128_convert(UChar size, s390_fp_conv_t tag, HReg dst_hi,
   5977                         HReg dst_lo, HReg op_hi, HReg op_lo, HReg r1,
   5978                         s390_dfp_round_t rounding_mode)
   5979 {
   5980    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   5981    s390_fp_convert *fp_convert = LibVEX_Alloc_inline(sizeof(s390_fp_convert));
   5982 
   5983    vassert(size == 16);
   5984 
   5985    insn->tag  = S390_INSN_FP_CONVERT;
   5986    insn->size = size;
   5987    insn->variant.fp_convert.details = fp_convert;
   5988 
   5989    fp_convert->tag = tag;
   5990    fp_convert->dst_hi = dst_hi;
   5991    fp_convert->dst_lo = dst_lo;
   5992    fp_convert->op_hi  = op_hi;
   5993    fp_convert->r1 = r1;
   5994    fp_convert->op_lo  = op_lo;
   5995    fp_convert->rounding_mode = rounding_mode;
   5996 
   5997    return insn;
   5998 }
   5999 
   6000 
   6001 s390_insn *
   6002 s390_insn_dfp128_binop(UChar size, s390_dfp_binop_t tag, HReg dst_hi,
   6003                        HReg dst_lo, HReg op2_hi, HReg op2_lo, HReg op3_hi,
   6004                        HReg op3_lo, s390_dfp_round_t rounding_mode)
   6005 {
   6006    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   6007    s390_dfp_binop *dfp_binop = LibVEX_Alloc_inline(sizeof(s390_dfp_binop));
   6008 
   6009    vassert(size == 16);
   6010    vassert(is_valid_fp128_regpair(dst_hi, dst_lo));
   6011    vassert(is_valid_fp128_regpair(op2_hi, op2_lo));
   6012    vassert(is_valid_fp128_regpair(op3_hi, op3_lo));
   6013 
   6014    insn->tag  = S390_INSN_DFP_BINOP;
   6015    insn->size = size;
   6016    insn->variant.dfp_binop.details = dfp_binop;
   6017 
   6018    dfp_binop->tag = tag;
   6019    dfp_binop->dst_hi = dst_hi;
   6020    dfp_binop->dst_lo = dst_lo;
   6021    dfp_binop->op2_hi = op2_hi;
   6022    dfp_binop->op2_lo = op2_lo;
   6023    dfp_binop->op3_hi = op3_hi;
   6024    dfp_binop->op3_lo = op3_lo;
   6025    dfp_binop->rounding_mode = rounding_mode;
   6026 
   6027    return insn;
   6028 }
   6029 
   6030 
   6031 s390_insn *
   6032 s390_insn_dfp128_unop(UChar size, s390_dfp_unop_t tag, HReg dst,
   6033                       HReg op_hi, HReg op_lo)
   6034 {
   6035    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   6036 
   6037    /* destination is an 8 byte integer value */
   6038    vassert(size == 8);
   6039    vassert(is_valid_fp128_regpair(op_hi, op_lo));
   6040 
   6041    insn->tag  = S390_INSN_DFP_UNOP;
   6042    insn->size = size;
   6043    insn->variant.dfp_unop.tag = tag;
   6044    insn->variant.dfp_unop.dst_hi = dst;
   6045    insn->variant.dfp_unop.dst_lo = INVALID_HREG;
   6046    insn->variant.dfp_unop.op_hi = op_hi;
   6047    insn->variant.dfp_unop.op_lo = op_lo;
   6048 
   6049    return insn;
   6050 }
   6051 
   6052 
   6053 s390_insn *
   6054 s390_insn_dfp128_intop(UChar size, s390_dfp_intop_t tag, HReg dst_hi,
   6055                        HReg dst_lo, HReg op2, HReg op3_hi, HReg op3_lo)
   6056 {
   6057    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   6058 
   6059    vassert(size == 16);
   6060    vassert(is_valid_fp128_regpair(dst_hi, dst_lo));
   6061    vassert(is_valid_fp128_regpair(op3_hi, op3_lo));
   6062 
   6063    insn->tag  = S390_INSN_DFP_INTOP;
   6064    insn->size = size;
   6065    insn->variant.dfp_intop.tag = tag;
   6066    insn->variant.dfp_intop.dst_hi = dst_hi;
   6067    insn->variant.dfp_intop.dst_lo = dst_lo;
   6068    insn->variant.dfp_intop.op2    = op2;
   6069    insn->variant.dfp_intop.op3_hi = op3_hi;
   6070    insn->variant.dfp_intop.op3_lo = op3_lo;
   6071 
   6072    return insn;
   6073 }
   6074 
   6075 
   6076 s390_insn *
   6077 s390_insn_dfp128_compare(UChar size, s390_dfp_cmp_t tag, HReg dst, HReg op1_hi,
   6078                          HReg op1_lo, HReg op2_hi, HReg op2_lo)
   6079 {
   6080    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   6081 
   6082    vassert(size == 16);
   6083    vassert(is_valid_fp128_regpair(op1_hi, op1_lo));
   6084    vassert(is_valid_fp128_regpair(op2_hi, op2_lo));
   6085 
   6086    insn->tag  = S390_INSN_DFP_COMPARE;
   6087    insn->size = size;
   6088    insn->variant.dfp_compare.tag = tag;
   6089    insn->variant.dfp_compare.dst = dst;
   6090    insn->variant.dfp_compare.op1_hi = op1_hi;
   6091    insn->variant.dfp_compare.op1_lo = op1_lo;
   6092    insn->variant.dfp_compare.op2_hi = op2_hi;
   6093    insn->variant.dfp_compare.op2_lo = op2_lo;
   6094 
   6095    return insn;
   6096 }
   6097 
   6098 
   6099 static s390_insn *
   6100 s390_insn_dfp128_convert(UChar size, s390_dfp_conv_t tag, HReg dst_hi,
   6101                          HReg dst_lo, HReg op_hi, HReg op_lo,
   6102                          s390_dfp_round_t rounding_mode)
   6103 {
   6104    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   6105 
   6106    if (size == 16) {
   6107       /* From smaller size to 16 bytes */
   6108       vassert(is_valid_fp128_regpair(dst_hi, dst_lo));
   6109       vassert(hregIsInvalid(op_lo));
   6110    } else {
   6111       /* From 16 bytes to smaller size */
   6112       vassert(is_valid_fp128_regpair(op_hi, op_lo));
   6113    }
   6114 
   6115    insn->tag  = S390_INSN_DFP_CONVERT;
   6116    insn->size = size;
   6117    insn->variant.dfp_convert.tag = tag;
   6118    insn->variant.dfp_convert.dst_hi = dst_hi;
   6119    insn->variant.dfp_convert.dst_lo = dst_lo;
   6120    insn->variant.dfp_convert.op_hi = op_hi;
   6121    insn->variant.dfp_convert.op_lo = op_lo;
   6122    insn->variant.dfp_convert.rounding_mode = rounding_mode;
   6123 
   6124    return insn;
   6125 }
   6126 
   6127 
   6128 s390_insn *
   6129 s390_insn_dfp128_convert_to(UChar size, s390_dfp_conv_t tag, HReg dst_hi,
   6130                             HReg dst_lo, HReg op)
   6131 {
   6132    /* Conversion to dfp128 never requires a rounding mode. Provide default
   6133       rounding mode. It will not be used when emitting insns. */
   6134    s390_dfp_round_t rounding_mode = S390_DFP_ROUND_NEAREST_EVEN_4;
   6135 
   6136    return s390_insn_dfp128_convert(size, tag, dst_hi, dst_lo, op,
   6137                                    INVALID_HREG, rounding_mode);
   6138 }
   6139 
   6140 
   6141 s390_insn *
   6142 s390_insn_dfp128_convert_from(UChar size, s390_dfp_conv_t tag, HReg dst_hi,
   6143                               HReg dst_lo, HReg op_hi, HReg op_lo,
   6144                               s390_dfp_round_t rounding_mode)
   6145 {
   6146    return s390_insn_dfp128_convert(size, tag, dst_hi, dst_lo, op_hi, op_lo,
   6147                                    rounding_mode);
   6148 }
   6149 
   6150 
   6151 s390_insn *
   6152 s390_insn_dfp128_reround(UChar size, HReg dst_hi, HReg dst_lo, HReg op2,
   6153                          HReg op3_hi, HReg op3_lo,
   6154                          s390_dfp_round_t rounding_mode)
   6155 {
   6156    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   6157 
   6158    vassert(size == 16);
   6159    vassert(is_valid_fp128_regpair(dst_hi, dst_lo));
   6160    vassert(is_valid_fp128_regpair(op3_hi, op3_lo));
   6161 
   6162    insn->tag  = S390_INSN_DFP_REROUND;
   6163    insn->size = size;
   6164    insn->variant.dfp_reround.dst_hi = dst_hi;
   6165    insn->variant.dfp_reround.dst_lo = dst_lo;
   6166    insn->variant.dfp_reround.op2    = op2;
   6167    insn->variant.dfp_reround.op3_hi = op3_hi;
   6168    insn->variant.dfp_reround.op3_lo = op3_lo;
   6169    insn->variant.dfp_reround.rounding_mode = rounding_mode;
   6170 
   6171    return insn;
   6172 }
   6173 
   6174 
   6175 s390_insn *
   6176 s390_insn_mfence(void)
   6177 {
   6178    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   6179 
   6180    insn->tag  = S390_INSN_MFENCE;
   6181    insn->size = 0;   /* not needed */
   6182 
   6183    return insn;
   6184 }
   6185 
   6186 
   6187 s390_insn *
   6188 s390_insn_mimm(UChar size, s390_amode *dst, ULong value)
   6189 {
   6190    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   6191 
   6192    /* This insn will be mapped to insns that require base register
   6193       plus 12-bit displacement */
   6194    vassert(dst->tag == S390_AMODE_B12);
   6195 
   6196    insn->tag  = S390_INSN_MIMM;
   6197    insn->size = size;
   6198    insn->variant.mimm.dst = dst;
   6199    insn->variant.mimm.value = value;
   6200 
   6201    return insn;
   6202 }
   6203 
   6204 
   6205 s390_insn *
   6206 s390_insn_madd(UChar size, s390_amode *dst, UChar delta, ULong value)
   6207 {
   6208    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   6209 
   6210    vassert(size == 4 || size == 8);
   6211 
   6212    /* This insn will be mapped to an ASI or AGSI so we can only allow base
   6213       register plus 12-bit / 20-bit displacement. */
   6214    vassert(dst->tag == S390_AMODE_B12 || dst->tag == S390_AMODE_B20);
   6215    /* ASI and AGSI require the GIE facility */
   6216    vassert(s390_host_has_gie);
   6217 
   6218    insn->tag  = S390_INSN_MADD;
   6219    insn->size = size;
   6220    insn->variant.madd.dst   = dst;
   6221    insn->variant.madd.delta = delta;
   6222    insn->variant.madd.value = value;
   6223 
   6224    return insn;
   6225 }
   6226 
   6227 
   6228 s390_insn *
   6229 s390_insn_set_fpc_bfprm(UChar size, HReg mode)
   6230 {
   6231    vassert(size == 4);
   6232 
   6233    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   6234 
   6235    insn->tag  = S390_INSN_SET_FPC_BFPRM;
   6236    insn->size = size;
   6237    insn->variant.set_fpc_bfprm.mode = mode;
   6238 
   6239    return insn;
   6240 }
   6241 
   6242 
   6243 s390_insn *
   6244 s390_insn_set_fpc_dfprm(UChar size, HReg mode)
   6245 {
   6246    vassert(size == 4);
   6247 
   6248    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   6249 
   6250    insn->tag  = S390_INSN_SET_FPC_DFPRM;
   6251    insn->size = size;
   6252    insn->variant.set_fpc_dfprm.mode = mode;
   6253 
   6254    return insn;
   6255 }
   6256 
   6257 
   6258 s390_insn *
   6259 s390_insn_xdirect(s390_cc_t cond, Addr64 dst, s390_amode *guest_IA,
   6260                   Bool to_fast_entry)
   6261 {
   6262    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   6263 
   6264    vassert(guest_IA->tag == S390_AMODE_B12);
   6265 
   6266    insn->tag  = S390_INSN_XDIRECT;
   6267    insn->size = 0;   /* does not matter */
   6268 
   6269    insn->variant.xdirect.cond = cond;
   6270    insn->variant.xdirect.dst = dst;
   6271    insn->variant.xdirect.guest_IA = guest_IA;
   6272    insn->variant.xdirect.to_fast_entry = to_fast_entry;
   6273 
   6274    return insn;
   6275 }
   6276 
   6277 
   6278 s390_insn *
   6279 s390_insn_xindir(s390_cc_t cond, HReg dst, s390_amode *guest_IA)
   6280 {
   6281    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   6282 
   6283    vassert(guest_IA->tag == S390_AMODE_B12);
   6284 
   6285    insn->tag  = S390_INSN_XINDIR;
   6286    insn->size = 0;   /* does not matter */
   6287 
   6288    insn->variant.xindir.cond = cond;
   6289    insn->variant.xindir.dst = dst;
   6290    insn->variant.xindir.guest_IA = guest_IA;
   6291 
   6292    return insn;
   6293 }
   6294 
   6295 
   6296 s390_insn *
   6297 s390_insn_xassisted(s390_cc_t cond, HReg dst, s390_amode *guest_IA,
   6298                     IRJumpKind kind)
   6299 {
   6300    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   6301 
   6302    vassert(guest_IA->tag == S390_AMODE_B12);
   6303 
   6304    insn->tag  = S390_INSN_XASSISTED;
   6305    insn->size = 0;   /* does not matter */
   6306 
   6307    insn->variant.xassisted.cond = cond;
   6308    insn->variant.xassisted.dst = dst;
   6309    insn->variant.xassisted.guest_IA = guest_IA;
   6310    insn->variant.xassisted.kind = kind;
   6311 
   6312    return insn;
   6313 }
   6314 
   6315 
   6316 s390_insn *
   6317 s390_insn_evcheck(s390_amode *counter, s390_amode *fail_addr)
   6318 {
   6319    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   6320 
   6321    vassert(counter->tag   == S390_AMODE_B12);
   6322    vassert(fail_addr->tag == S390_AMODE_B12);
   6323 
   6324    insn->tag  = S390_INSN_EVCHECK;
   6325    insn->size = 0;   /* does not matter */
   6326 
   6327    insn->variant.evcheck.counter = counter;
   6328    insn->variant.evcheck.fail_addr = fail_addr;
   6329 
   6330    return insn;
   6331 }
   6332 
   6333 
   6334 s390_insn *
   6335 s390_insn_profinc(void)
   6336 {
   6337    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   6338 
   6339    insn->tag  = S390_INSN_PROFINC;
   6340    insn->size = 0;   /* does not matter */
   6341 
   6342    return insn;
   6343 }
   6344 
   6345 
   6346 /*---------------------------------------------------------------*/
   6347 /*--- Debug print                                             ---*/
   6348 /*---------------------------------------------------------------*/
   6349 
   6350 static const HChar *
   6351 s390_cc_as_string(s390_cc_t cc)
   6352 {
   6353    switch (cc) {
   6354    case S390_CC_NEVER:  return "never";
   6355    case S390_CC_OVFL:   return "overflow";
   6356    case S390_CC_H:      return "greater than";     /* A > B ; high */
   6357    case S390_CC_NLE:    return "not low or equal";
   6358    case S390_CC_L:      return "less than";        /* A < B ; low */
   6359    case S390_CC_NHE:    return "not high or equal";
   6360    case S390_CC_LH:     return "low or high";
   6361    case S390_CC_NE:     return "not equal";        /* A != B ; not zero */
   6362    case S390_CC_E:      return "equal";            /* A == B ; zero */
   6363    case S390_CC_NLH:    return "not low or high";
   6364    case S390_CC_HE:     return "greater or equal"; /* A >= B ; high or equal*/
   6365    case S390_CC_NL:     return "not low";          /* not low */
   6366    case S390_CC_LE:     return "less or equal";    /* A <= B ; low or equal */
   6367    case S390_CC_NH:     return "not high";
   6368    case S390_CC_NO:     return "not overflow";
   6369    case S390_CC_ALWAYS: return "always";
   6370    default:
   6371       vpanic("s390_cc_as_string");
   6372    }
   6373 }
   6374 
   6375 
   6376 static const HChar *
   6377 s390_jump_kind_as_string(IRJumpKind kind)
   6378 {
   6379    switch (kind) {
   6380    case Ijk_Boring:      return "Boring";
   6381    case Ijk_Call:        return "Call";
   6382    case Ijk_Ret:         return "Return";
   6383    case Ijk_ClientReq:   return "ClientReq";
   6384    case Ijk_Yield:       return "Yield";
   6385    case Ijk_EmWarn:      return "EmWarn";
   6386    case Ijk_EmFail:      return "EmFail";
   6387    case Ijk_NoDecode:    return "NoDecode";
   6388    case Ijk_MapFail:     return "MapFail";
   6389    case Ijk_InvalICache: return "Invalidate";
   6390    case Ijk_NoRedir:     return "NoRedir";
   6391    case Ijk_SigTRAP:     return "SigTRAP";
   6392    case Ijk_SigSEGV:     return "SigSEGV";
   6393    case Ijk_SigBUS:      return "SigBUS";
   6394    case Ijk_Sys_syscall: return "Sys_syscall";
   6395    default:
   6396       vpanic("s390_jump_kind_as_string");
   6397    }
   6398 }
   6399 
   6400 
   6401 /* Helper function for writing out a V insn */
   6402 static void
   6403 s390_sprintf(HChar *buf, const HChar *fmt, ...)
   6404 {
   6405    HChar *p;
   6406    ULong value;
   6407    va_list args;
   6408    va_start(args, fmt);
   6409 
   6410    p = buf;
   6411    for ( ; *fmt; ++fmt) {
   6412       Int c = *fmt;
   6413 
   6414       if (c != '%') {
   6415          *p++ = c;
   6416          continue;
   6417       }
   6418 
   6419       c = *++fmt;  /* next char */
   6420       switch (c) {
   6421       case '%':
   6422          *p++ = c;   /* %% */
   6423          continue;
   6424 
   6425       case 's':     /* %s */
   6426          p += vex_sprintf(p, "%s", va_arg(args, HChar *));
   6427          continue;
   6428 
   6429       case 'M':     /* %M = mnemonic */
   6430          p += vex_sprintf(p, "%-8s", va_arg(args, HChar *));
   6431          continue;
   6432 
   6433       case 'R':     /* %R = register */
   6434          p += vex_sprintf(p, "%s", s390_hreg_as_string(va_arg(args, HReg)));
   6435          continue;
   6436 
   6437       case 'A':     /* %A = amode */
   6438          p += vex_sprintf(p, "%s",
   6439                           s390_amode_as_string(va_arg(args, s390_amode *)));
   6440          continue;
   6441 
   6442       case 'G':     /* %G = guest state @ offset */
   6443          p += vex_sprintf(p, "guest[%u]", va_arg(args, UInt));
   6444          continue;
   6445 
   6446       case 'C':     /* %C = condition code */
   6447          p += vex_sprintf(p, "%s", s390_cc_as_string(va_arg(args, s390_cc_t)));
   6448          continue;
   6449 
   6450       case 'J':     /* &J = jump kind */
   6451          p += vex_sprintf(p, "%s",
   6452                           s390_jump_kind_as_string(va_arg(args, IRJumpKind)));
   6453          continue;
   6454 
   6455       case 'L': {   /* %L = argument list in helper call*/
   6456          UInt i, num_args;
   6457 
   6458          num_args = va_arg(args, UInt);
   6459 
   6460          for (i = 0; i < num_args; ++i) {
   6461             if (i != 0) p += vex_sprintf(p, ", ");
   6462             p += vex_sprintf(p, "r%u", s390_gprno_from_arg_index(i));
   6463          }
   6464          continue;
   6465       }
   6466 
   6467       case 'O': {   /* %O = RMI operand */
   6468          s390_opnd_RMI *op = va_arg(args, s390_opnd_RMI *);
   6469 
   6470          switch (op->tag) {
   6471          case S390_OPND_REG:
   6472             p += vex_sprintf(p, "%s", s390_hreg_as_string(op->variant.reg));
   6473             continue;
   6474 
   6475          case S390_OPND_AMODE:
   6476             p += vex_sprintf(p, "%s", s390_amode_as_string(op->variant.am));
   6477             continue;
   6478 
   6479          case S390_OPND_IMMEDIATE:
   6480             value = op->variant.imm;
   6481             goto print_value;
   6482 
   6483          default:
   6484             goto fail;
   6485          }
   6486       }
   6487 
   6488       case 'I':     /* %I = immediate value */
   6489          value = va_arg(args, ULong);
   6490          goto print_value;
   6491 
   6492       print_value:
   6493          if ((Long)value < 0)
   6494             p += vex_sprintf(p, "%lld", (Long)value);
   6495          else if (value < 100)
   6496             p += vex_sprintf(p, "%llu", value);
   6497          else
   6498             p += vex_sprintf(p, "0x%llx", value);
   6499          continue;
   6500 
   6501       default:
   6502          goto fail;
   6503       }
   6504    }
   6505    *p = '\0';
   6506    va_end(args);
   6507 
   6508    return;
   6509 
   6510  fail: vpanic("s390_printf");
   6511 }
   6512 
   6513 
   6514 /* Decompile the given insn into a static buffer and return it */
   6515 const HChar *
   6516 s390_insn_as_string(const s390_insn *insn)
   6517 {
   6518    static HChar buf[300];  // large enough
   6519    const HChar *op;
   6520    HChar *p;
   6521 
   6522    buf[0] = '\0';
   6523 
   6524    switch (insn->tag) {
   6525    case S390_INSN_LOAD:
   6526       s390_sprintf(buf, "%M %R,%A", "v-load", insn->variant.load.dst,
   6527                    insn->variant.load.src);
   6528       break;
   6529 
   6530    case S390_INSN_STORE:
   6531       s390_sprintf(buf, "%M %R,%A", "v-store", insn->variant.store.src,
   6532                    insn->variant.store.dst);
   6533       break;
   6534 
   6535    case S390_INSN_MOVE:
   6536       s390_sprintf(buf, "%M %R,%R", "v-move", insn->variant.move.dst,
   6537                    insn->variant.move.src);
   6538       break;
   6539 
   6540    case S390_INSN_MEMCPY:
   6541       s390_sprintf(buf, "%M %A,%A", "v-memcpy", insn->variant.memcpy.dst,
   6542                    insn->variant.memcpy.src);
   6543       break;
   6544 
   6545    case S390_INSN_COND_MOVE:
   6546       s390_sprintf(buf, "%M if (%C) %R,%O", "v-move",
   6547                    insn->variant.cond_move.cond, insn->variant.cond_move.dst,
   6548                    &insn->variant.cond_move.src);
   6549       break;
   6550 
   6551    case S390_INSN_LOAD_IMMEDIATE:
   6552       s390_sprintf(buf, "%M %R,%I", "v-loadi", insn->variant.load_immediate.dst,
   6553                    insn->variant.load_immediate.value);
   6554       break;
   6555 
   6556    case S390_INSN_ALU:
   6557       switch (insn->variant.alu.tag) {
   6558       case S390_ALU_ADD:  op = "v-add";  break;
   6559       case S390_ALU_SUB:  op = "v-sub";  break;
   6560       case S390_ALU_MUL:  op = "v-mul";  break;
   6561       case S390_ALU_AND:  op = "v-and";  break;
   6562       case S390_ALU_OR:   op = "v-or";   break;
   6563       case S390_ALU_XOR:  op = "v-xor";  break;
   6564       case S390_ALU_LSH:  op = "v-lsh";  break;
   6565       case S390_ALU_RSH:  op = "v-rsh";  break;
   6566       case S390_ALU_RSHA: op = "v-rsha"; break;
   6567       default: goto fail;
   6568       }
   6569       s390_sprintf(buf, "%M %R,%O", op, insn->variant.alu.dst, /* also op1 */
   6570                    &insn->variant.alu.op2);
   6571       break;
   6572 
   6573    case S390_INSN_SMUL:
   6574    case S390_INSN_UMUL:
   6575       if (insn->tag == S390_INSN_SMUL) {
   6576          op = "v-muls";
   6577       } else {
   6578          op = "v-mulu";
   6579       }
   6580       s390_sprintf(buf, "%M %R,%O", op, insn->variant.mul.dst_hi,
   6581                    &insn->variant.mul.op2);
   6582       break;
   6583 
   6584    case S390_INSN_SDIV:
   6585    case S390_INSN_UDIV:
   6586       if (insn->tag == S390_INSN_SDIV) {
   6587          op = "v-divs";
   6588       } else {
   6589          op = "v-divu";
   6590       }
   6591       s390_sprintf(buf, "%M %R,%O", op, insn->variant.div.op1_hi,
   6592                    &insn->variant.div.op2);
   6593       break;
   6594 
   6595    case S390_INSN_DIVS:
   6596       s390_sprintf(buf, "%M %R,%O", "v-divsi", insn->variant.divs.op1,
   6597                    &insn->variant.divs.op2);
   6598       break;
   6599 
   6600    case S390_INSN_CLZ:
   6601       s390_sprintf(buf, "%M %R,%O", "v-clz", insn->variant.clz.num_bits,
   6602                    &insn->variant.clz.src);
   6603       break;
   6604 
   6605    case S390_INSN_UNOP:
   6606       switch (insn->variant.unop.tag) {
   6607       case S390_ZERO_EXTEND_8:
   6608       case S390_ZERO_EXTEND_16:
   6609       case S390_ZERO_EXTEND_32:
   6610          op = "v-zerox";
   6611          break;
   6612 
   6613       case S390_SIGN_EXTEND_8:
   6614       case S390_SIGN_EXTEND_16:
   6615       case S390_SIGN_EXTEND_32:
   6616          op = "v-signx";
   6617          break;
   6618 
   6619       case S390_NEGATE:
   6620          op = "v-neg";
   6621          break;
   6622 
   6623       default:
   6624          goto fail;
   6625       }
   6626       s390_sprintf(buf, "%M %R,%O", op, insn->variant.unop.dst,
   6627                    &insn->variant.unop.src);
   6628       break;
   6629 
   6630    case S390_INSN_TEST:
   6631       s390_sprintf(buf, "%M %O", "v-test", &insn->variant.test.src);
   6632       break;
   6633 
   6634    case S390_INSN_CC2BOOL:
   6635       s390_sprintf(buf, "%M %R,%C", "v-cc2b", insn->variant.cc2bool.dst,
   6636                    insn->variant.cc2bool.cond);
   6637       break;
   6638 
   6639    case S390_INSN_CAS:
   6640       s390_sprintf(buf, "%M %R,%A,%R,%R", "v-cas", insn->variant.cas.op1,
   6641                    insn->variant.cas.op2, insn->variant.cas.op3,
   6642                    insn->variant.cas.old_mem);
   6643       break;
   6644 
   6645    case S390_INSN_CDAS: {
   6646       s390_cdas *cdas = insn->variant.cdas.details;
   6647 
   6648       s390_sprintf(buf, "%M %R,%R,%A,%R,%R,%R,%R", "v-cdas",
   6649                    cdas->op1_high, cdas->op1_low, cdas->op2, cdas->op3_high,
   6650                    cdas->op3_low, cdas->old_mem_high, cdas->old_mem_low);
   6651       break;
   6652    }
   6653 
   6654    case S390_INSN_COMPARE:
   6655       if (insn->variant.compare.signed_comparison) {
   6656          op = "v-cmps";
   6657       } else {
   6658          op = "v-cmpu";
   6659       }
   6660       s390_sprintf(buf, "%M %R,%O", op, insn->variant.compare.src1,
   6661                    &insn->variant.compare.src2);
   6662       break;
   6663 
   6664    case S390_INSN_HELPER_CALL: {
   6665       s390_helper_call *helper_call = insn->variant.helper_call.details;
   6666       s390_sprintf(buf, "%M if (%C) %s{%I}(%L)", "v-call",
   6667                    helper_call->cond,
   6668                    helper_call->name,
   6669                    helper_call->target,
   6670                    helper_call->num_args);
   6671       return buf;   /* avoid printing "size = ..." which is meaningless */
   6672    }
   6673 
   6674    case S390_INSN_BFP_TRIOP:
   6675       switch (insn->variant.bfp_triop.tag) {
   6676       case S390_BFP_MADD:  op = "v-fmadd";  break;
   6677       case S390_BFP_MSUB:  op = "v-fmsub";  break;
   6678       default: goto fail;
   6679       }
   6680       s390_sprintf(buf, "%M %R,%R,%R", op,
   6681                    insn->variant.bfp_triop.dst  /* op1 same as dst */,
   6682                    insn->variant.bfp_triop.op2, insn->variant.bfp_triop.op3);
   6683       break;
   6684 
   6685    case S390_INSN_BFP_BINOP:
   6686       switch (insn->variant.bfp_binop.tag) {
   6687       case S390_BFP_ADD:      op = "v-fadd";  break;
   6688       case S390_BFP_SUB:      op = "v-fsub";  break;
   6689       case S390_BFP_MUL:      op = "v-fmul";  break;
   6690       case S390_BFP_DIV:      op = "v-fdiv";  break;
   6691       default: goto fail;
   6692       }
   6693       s390_sprintf(buf, "%M %R,%R", op,
   6694                    insn->variant.bfp_binop.dst_hi  /* op1 same as dst */,
   6695                    insn->variant.bfp_binop.op2_hi);
   6696       break;
   6697 
   6698    case S390_INSN_BFP_COMPARE:
   6699       s390_sprintf(buf, "%M %R,%R,%R", "v-fcmp", insn->variant.bfp_compare.dst,
   6700                    insn->variant.bfp_compare.op1_hi,
   6701                    insn->variant.bfp_compare.op2_hi);
   6702       break;
   6703 
   6704    case S390_INSN_BFP_UNOP:
   6705       switch (insn->variant.bfp_unop.tag) {
   6706       case S390_BFP_ABS:         op = "v-fabs";  break;
   6707       case S390_BFP_NABS:        op = "v-fnabs"; break;
   6708       case S390_BFP_NEG:         op = "v-fneg";  break;
   6709       case S390_BFP_SQRT:        op = "v-fsqrt"; break;
   6710       default: goto fail;
   6711       }
   6712       s390_sprintf(buf, "%M %R,%R", op, insn->variant.bfp_unop.dst_hi,
   6713                    insn->variant.bfp_unop.op_hi);
   6714       break;
   6715 
   6716    case S390_INSN_BFP_CONVERT:
   6717       switch (insn->variant.bfp_convert.tag) {
   6718       case S390_BFP_I32_TO_F32:
   6719       case S390_BFP_I32_TO_F64:
   6720       case S390_BFP_I32_TO_F128:
   6721       case S390_BFP_I64_TO_F32:
   6722       case S390_BFP_I64_TO_F64:
   6723       case S390_BFP_I64_TO_F128: op = "v-i2f"; break;
   6724       case S390_BFP_U32_TO_F32:
   6725       case S390_BFP_U32_TO_F64:
   6726       case S390_BFP_U32_TO_F128:
   6727       case S390_BFP_U64_TO_F32:
   6728       case S390_BFP_U64_TO_F64:
   6729       case S390_BFP_U64_TO_F128: op = "v-u2f"; break;
   6730       case S390_BFP_F32_TO_I32:
   6731       case S390_BFP_F32_TO_I64:
   6732       case S390_BFP_F64_TO_I32:
   6733       case S390_BFP_F64_TO_I64:
   6734       case S390_BFP_F128_TO_I32:
   6735       case S390_BFP_F128_TO_I64: op = "v-f2i"; break;
   6736       case S390_BFP_F32_TO_U32:
   6737       case S390_BFP_F32_TO_U64:
   6738       case S390_BFP_F64_TO_U32:
   6739       case S390_BFP_F64_TO_U64:
   6740       case S390_BFP_F128_TO_U32:
   6741       case S390_BFP_F128_TO_U64: op = "v-f2u"; break;
   6742       case S390_BFP_F32_TO_F64:
   6743       case S390_BFP_F32_TO_F128:
   6744       case S390_BFP_F64_TO_F32:
   6745       case S390_BFP_F64_TO_F128:
   6746       case S390_BFP_F128_TO_F32:
   6747       case S390_BFP_F128_TO_F64: op = "v-f2f"; break;
   6748       case S390_BFP_F32_TO_F32I:
   6749       case S390_BFP_F64_TO_F64I:
   6750       case S390_BFP_F128_TO_F128I: op = "v-f2fi"; break;
   6751       default: goto fail;
   6752       }
   6753       s390_sprintf(buf, "%M %R,%R", op, insn->variant.bfp_convert.dst_hi,
   6754                    insn->variant.bfp_convert.op_hi);
   6755       break;
   6756 
   6757    case S390_INSN_DFP_BINOP: {
   6758       s390_dfp_binop *dfp_binop = insn->variant.dfp_binop.details;
   6759 
   6760       switch (dfp_binop->tag) {
   6761       case S390_DFP_ADD:  op = "v-dadd";  break;
   6762       case S390_DFP_SUB:  op = "v-dsub";  break;
   6763       case S390_DFP_MUL:  op = "v-dmul";  break;
   6764       case S390_DFP_DIV:  op = "v-ddiv";  break;
   6765       case S390_DFP_QUANTIZE:  op = "v-dqua";  break;
   6766       default: goto fail;
   6767       }
   6768       s390_sprintf(buf, "%M %R,%R,%R", op, dfp_binop->dst_hi,
   6769                    dfp_binop->op2_hi, dfp_binop->op3_hi);
   6770       break;
   6771    }
   6772 
   6773    case S390_INSN_DFP_UNOP:
   6774       switch (insn->variant.dfp_unop.tag) {
   6775       case S390_DFP_EXTRACT_EXP_D64:
   6776       case S390_DFP_EXTRACT_EXP_D128:  op = "v-d2exp";  break;
   6777       case S390_DFP_EXTRACT_SIG_D64:
   6778       case S390_DFP_EXTRACT_SIG_D128:  op = "v-d2sig";  break;
   6779       default: goto fail;
   6780       }
   6781       s390_sprintf(buf, "%M %R,%R", op, insn->variant.dfp_unop.dst_hi,
   6782                    insn->variant.dfp_unop.op_hi);
   6783       break;
   6784 
   6785    case S390_INSN_DFP_INTOP:
   6786       switch (insn->variant.dfp_intop.tag) {
   6787       case S390_DFP_SHIFT_LEFT:  op = "v-dshl"; break;
   6788       case S390_DFP_SHIFT_RIGHT: op = "v-dshr"; break;
   6789       case S390_DFP_INSERT_EXP:  op = "v-diexp"; break;
   6790       default: goto fail;
   6791       }
   6792       s390_sprintf(buf, "%M %R,%R,%R", op, insn->variant.dfp_intop.dst_hi,
   6793                    insn->variant.dfp_intop.op2,
   6794                    insn->variant.dfp_intop.op3_hi);
   6795       break;
   6796 
   6797    case S390_INSN_DFP_COMPARE:
   6798       switch (insn->variant.dfp_compare.tag) {
   6799       case S390_DFP_COMPARE:     op = "v-dcmp"; break;
   6800       case S390_DFP_COMPARE_EXP: op = "v-dcmpexp"; break;
   6801       default: goto fail;
   6802       }
   6803       s390_sprintf(buf, "%M %R,%R,%R", op, insn->variant.dfp_compare.dst,
   6804                    insn->variant.dfp_compare.op1_hi,
   6805                    insn->variant.dfp_compare.op2_hi);
   6806       break;
   6807 
   6808    case S390_INSN_DFP_CONVERT:
   6809       switch (insn->variant.dfp_convert.tag) {
   6810       case S390_DFP_D32_TO_D64:
   6811       case S390_DFP_D64_TO_D32:
   6812       case S390_DFP_D64_TO_D128:
   6813       case S390_DFP_D128_TO_D64: op = "v-d2d"; break;
   6814       case S390_DFP_I32_TO_D64:
   6815       case S390_DFP_I32_TO_D128:
   6816       case S390_DFP_I64_TO_D64:
   6817       case S390_DFP_I64_TO_D128: op = "v-i2d"; break;
   6818       case S390_DFP_U32_TO_D64:
   6819       case S390_DFP_U32_TO_D128:
   6820       case S390_DFP_U64_TO_D64:
   6821       case S390_DFP_U64_TO_D128: op = "v-u2d"; break;
   6822       case S390_DFP_D64_TO_I32:
   6823       case S390_DFP_D128_TO_I32:
   6824       case S390_DFP_D64_TO_I64:
   6825       case S390_DFP_D128_TO_I64: op = "v-d2i"; break;
   6826       case S390_DFP_D64_TO_U32:
   6827       case S390_DFP_D64_TO_U64:
   6828       case S390_DFP_D128_TO_U32:
   6829       case S390_DFP_D128_TO_U64: op = "v-d2u"; break;
   6830       default: goto fail;
   6831       }
   6832       s390_sprintf(buf, "%M %R,%R", op, insn->variant.dfp_convert.dst_hi,
   6833                    insn->variant.dfp_convert.op_hi);
   6834       break;
   6835 
   6836    case S390_INSN_DFP_REROUND:
   6837       s390_sprintf(buf, "%M %R,%R,%R", "v-drrnd",
   6838                    insn->variant.dfp_reround.dst_hi,
   6839                    insn->variant.dfp_reround.op2,
   6840                    insn->variant.dfp_reround.op3_hi);
   6841       break;
   6842 
   6843    case S390_INSN_FP_CONVERT: {
   6844       s390_fp_convert *fp_convert = insn->variant.fp_convert.details;
   6845 
   6846       switch (fp_convert->tag) {
   6847       case S390_FP_F32_TO_D32:
   6848       case S390_FP_F32_TO_D64:
   6849       case S390_FP_F32_TO_D128:
   6850       case S390_FP_F64_TO_D32:
   6851       case S390_FP_F64_TO_D64:
   6852       case S390_FP_F64_TO_D128:
   6853       case S390_FP_F128_TO_D32:
   6854       case S390_FP_F128_TO_D64:
   6855       case S390_FP_F128_TO_D128: op = "v-f2d"; break;
   6856       case S390_FP_D32_TO_F32:
   6857       case S390_FP_D32_TO_F64:
   6858       case S390_FP_D32_TO_F128:
   6859       case S390_FP_D64_TO_F32:
   6860       case S390_FP_D64_TO_F64:
   6861       case S390_FP_D64_TO_F128:
   6862       case S390_FP_D128_TO_F32:
   6863       case S390_FP_D128_TO_F64:
   6864       case S390_FP_D128_TO_F128: op = "v-d2f"; break;
   6865       default: goto fail;
   6866       }
   6867       s390_sprintf(buf, "%M %R,%R", op, fp_convert->dst_hi,
   6868                    fp_convert->op_hi);
   6869       break;
   6870    }
   6871 
   6872    case S390_INSN_MFENCE:
   6873       s390_sprintf(buf, "%M", "v-mfence");
   6874       return buf;   /* avoid printing "size = ..." which is meaningless */
   6875 
   6876    case S390_INSN_MIMM:
   6877       s390_sprintf(buf, "%M %A,%I", "v-mimm", insn->variant.mimm.dst,
   6878                    insn->variant.mimm.value);
   6879       break;
   6880 
   6881    case S390_INSN_MADD:
   6882       s390_sprintf(buf, "%M %A += %I  (= %I)", "v-madd",
   6883                    insn->variant.madd.dst,
   6884                    (Long)(Char)insn->variant.madd.delta,
   6885                    insn->variant.madd.value);
   6886       break;
   6887 
   6888    case S390_INSN_SET_FPC_BFPRM:
   6889       s390_sprintf(buf, "%M %R", "v-set-fpc-bfprm",
   6890                    insn->variant.set_fpc_bfprm.mode);
   6891       break;
   6892 
   6893    case S390_INSN_SET_FPC_DFPRM:
   6894       s390_sprintf(buf, "%M %R", "v-set-fpc-dfprm",
   6895                    insn->variant.set_fpc_dfprm.mode);
   6896       break;
   6897 
   6898    case S390_INSN_EVCHECK:
   6899       s390_sprintf(buf, "%M counter = %A, fail-addr = %A", "v-evcheck",
   6900                    insn->variant.evcheck.counter,
   6901                    insn->variant.evcheck.fail_addr);
   6902       return buf;   /* avoid printing "size = ..." which is meaningless */
   6903 
   6904    case S390_INSN_PROFINC:
   6905       s390_sprintf(buf, "%M", "v-profinc");
   6906       return buf;   /* avoid printing "size = ..." which is meaningless */
   6907 
   6908    case S390_INSN_XDIRECT:
   6909       s390_sprintf(buf, "%M if (%C) %A = %I  %s", "v-xdirect",
   6910                    insn->variant.xdirect.cond,
   6911                    insn->variant.xdirect.guest_IA,
   6912                    insn->variant.xdirect.dst,
   6913                    insn->variant.xdirect.to_fast_entry ? "fast" : "slow");
   6914       return buf;   /* avoid printing "size = ..." which is meaningless */
   6915 
   6916    case S390_INSN_XINDIR:
   6917       s390_sprintf(buf, "%M if (%C) %A = %R", "v-xindir",
   6918                    insn->variant.xindir.cond,
   6919                    insn->variant.xindir.guest_IA,
   6920                    insn->variant.xindir.dst);
   6921       return buf;   /* avoid printing "size = ..." which is meaningless */
   6922 
   6923    case S390_INSN_XASSISTED:
   6924       s390_sprintf(buf, "%M if (%C) %J %A = %R", "v-xassisted",
   6925                    insn->variant.xassisted.cond,
   6926                    insn->variant.xassisted.kind,
   6927                    insn->variant.xassisted.guest_IA,
   6928                    insn->variant.xassisted.dst);
   6929       return buf;   /* avoid printing "size = ..." which is meaningless */
   6930 
   6931    default: goto fail;
   6932    }
   6933 
   6934    /* Write out how many bytes are involved in the operation */
   6935 
   6936    {
   6937       UInt len, i;
   6938 
   6939       for (p = buf; *p; ++p)
   6940          continue;
   6941 
   6942       len = p - buf;
   6943 
   6944       if (len < 32) {
   6945          for (i = len; i < 32; ++i)
   6946             p += vex_sprintf(p, " ");
   6947       } else {
   6948          p += vex_sprintf(p, "\t");
   6949       }
   6950    }
   6951 
   6952    /* Special cases first */
   6953    switch (insn->tag) {
   6954    case S390_INSN_UNOP:
   6955       switch (insn->variant.unop.tag) {
   6956       case S390_SIGN_EXTEND_8:
   6957       case S390_ZERO_EXTEND_8:  p += vex_sprintf(p, "1 -> "); goto common;
   6958       case S390_SIGN_EXTEND_16:
   6959       case S390_ZERO_EXTEND_16: p += vex_sprintf(p, "2 -> "); goto common;
   6960       case S390_SIGN_EXTEND_32:
   6961       case S390_ZERO_EXTEND_32: p += vex_sprintf(p, "4 -> "); goto common;
   6962       default:
   6963          goto common;
   6964       }
   6965 
   6966    case S390_INSN_BFP_CONVERT:
   6967       switch (insn->variant.bfp_convert.tag) {
   6968       case S390_BFP_I32_TO_F32:
   6969       case S390_BFP_I32_TO_F64:
   6970       case S390_BFP_I32_TO_F128:
   6971       case S390_BFP_U32_TO_F32:
   6972       case S390_BFP_U32_TO_F64:
   6973       case S390_BFP_U32_TO_F128:
   6974       case S390_BFP_F32_TO_I32:
   6975       case S390_BFP_F32_TO_I64:
   6976       case S390_BFP_F32_TO_U32:
   6977       case S390_BFP_F32_TO_U64:
   6978       case S390_BFP_F32_TO_F64:
   6979       case S390_BFP_F32_TO_F128: p += vex_sprintf(p, "4 -> "); goto common;
   6980       case S390_BFP_I64_TO_F32:
   6981       case S390_BFP_I64_TO_F64:
   6982       case S390_BFP_I64_TO_F128:
   6983       case S390_BFP_U64_TO_F32:
   6984       case S390_BFP_U64_TO_F64:
   6985       case S390_BFP_U64_TO_F128:
   6986       case S390_BFP_F64_TO_I32:
   6987       case S390_BFP_F64_TO_I64:
   6988       case S390_BFP_F64_TO_U32:
   6989       case S390_BFP_F64_TO_U64:
   6990       case S390_BFP_F64_TO_F32:
   6991       case S390_BFP_F64_TO_F128: p += vex_sprintf(p, "8 -> "); goto common;
   6992       case S390_BFP_F128_TO_I32:
   6993       case S390_BFP_F128_TO_I64:
   6994       case S390_BFP_F128_TO_U32:
   6995       case S390_BFP_F128_TO_U64:
   6996       case S390_BFP_F128_TO_F32:
   6997       case S390_BFP_F128_TO_F64: p += vex_sprintf(p, "16 -> "); goto common;
   6998       default:
   6999          goto common;
   7000       }
   7001 
   7002    case S390_INSN_DFP_CONVERT:
   7003       switch (insn->variant.dfp_convert.tag) {
   7004       case S390_DFP_D32_TO_D64:
   7005       case S390_DFP_I32_TO_D64:
   7006       case S390_DFP_I32_TO_D128:
   7007       case S390_DFP_U32_TO_D64:
   7008       case S390_DFP_U32_TO_D128: p += vex_sprintf(p, "4 -> "); goto common;
   7009       case S390_DFP_D64_TO_D32:
   7010       case S390_DFP_D64_TO_D128:
   7011       case S390_DFP_I64_TO_D64:
   7012       case S390_DFP_I64_TO_D128:
   7013       case S390_DFP_U64_TO_D64:
   7014       case S390_DFP_U64_TO_D128:
   7015       case S390_DFP_D64_TO_I32:
   7016       case S390_DFP_D64_TO_I64:
   7017       case S390_DFP_D64_TO_U32:
   7018       case S390_DFP_D64_TO_U64:  p += vex_sprintf(p, "8 -> "); goto common;
   7019       case S390_DFP_D128_TO_D64:
   7020       case S390_DFP_D128_TO_I32:
   7021       case S390_DFP_D128_TO_I64:
   7022       case S390_DFP_D128_TO_U32:
   7023       case S390_DFP_D128_TO_U64: p += vex_sprintf(p, "16 -> "); goto common;
   7024       default:
   7025          goto common;
   7026       }
   7027 
   7028    case S390_INSN_FP_CONVERT: {
   7029       s390_fp_convert *fp_convert = insn->variant.fp_convert.details;
   7030 
   7031       switch (fp_convert->tag) {
   7032       case S390_FP_F32_TO_D32:
   7033       case S390_FP_F32_TO_D64:
   7034       case S390_FP_F32_TO_D128:
   7035       case S390_FP_D32_TO_F32:
   7036       case S390_FP_D32_TO_F64:
   7037       case S390_FP_D32_TO_F128:  p += vex_sprintf(p, "4 -> "); goto common;
   7038       case S390_FP_F64_TO_D32:
   7039       case S390_FP_F64_TO_D64:
   7040       case S390_FP_F64_TO_D128:
   7041       case S390_FP_D64_TO_F32:
   7042       case S390_FP_D64_TO_F64:
   7043       case S390_FP_D64_TO_F128:  p += vex_sprintf(p, "8 -> "); goto common;
   7044       case S390_FP_F128_TO_D32:
   7045       case S390_FP_F128_TO_D64:
   7046       case S390_FP_F128_TO_D128:
   7047       case S390_FP_D128_TO_F32:
   7048       case S390_FP_D128_TO_F64:
   7049       case S390_FP_D128_TO_F128: p += vex_sprintf(p, "16 -> "); goto common;
   7050       default:
   7051          goto common;
   7052       }
   7053    }
   7054 
   7055    default:
   7056       goto common;
   7057    }
   7058 
   7059    /* Common case */
   7060  common:
   7061    vex_sprintf(p, "%u bytes", (UInt)insn->size);
   7062 
   7063    return buf;
   7064 
   7065  fail: vpanic("s390_insn_as_string");
   7066 }
   7067 
   7068 
   7069 
   7070 /* Load NUM bytes from memory into register REG using addressing mode AM. */
   7071 static UChar *
   7072 s390_emit_load_mem(UChar *p, UInt num, UChar reg, const s390_amode *am)
   7073 {
   7074    UInt b = hregNumber(am->b);
   7075    UInt x = hregNumber(am->x);  /* 0 for B12 and B20 */
   7076    UInt d = am->d;
   7077 
   7078    switch (am->tag) {
   7079    case S390_AMODE_B12:
   7080    case S390_AMODE_BX12:
   7081       switch (num) {
   7082       case 1: return s390_emit_IC(p, reg, x, b, d);
   7083       case 2: return s390_emit_LH(p, reg, x, b, d);
   7084       case 4: return s390_emit_L(p, reg, x, b, d);
   7085       case 8: return s390_emit_LG(p, reg, x, b, DISP20(d));
   7086       default: goto fail;
   7087       }
   7088       break;
   7089 
   7090    case S390_AMODE_B20:
   7091    case S390_AMODE_BX20:
   7092       switch (num) {
   7093       case 1: return s390_emit_ICY(p, reg, x, b, DISP20(d));
   7094       case 2: return s390_emit_LHY(p, reg, x, b, DISP20(d));
   7095       case 4: return s390_emit_LY(p, reg, x, b, DISP20(d));
   7096       case 8: return s390_emit_LG(p, reg, x, b, DISP20(d));
   7097       default: goto fail;
   7098       }
   7099       break;
   7100 
   7101    default: goto fail;
   7102    }
   7103 
   7104  fail:
   7105    vpanic("s390_emit_load_mem");
   7106 }
   7107 
   7108 
   7109 /* Load condition code into register REG */
   7110 static UChar *
   7111 s390_emit_load_cc(UChar *p, UChar reg)
   7112 {
   7113    p = s390_emit_LGHI(p, reg, 0);  /* Clear out, cc not affected */
   7114    p = s390_emit_IPM(p, reg, reg);
   7115    /* Shift 28 bits to the right --> [0,1,2,3] */
   7116    return s390_emit_SRL(p, reg, 0, 28); /* REG = cc */
   7117 }
   7118 
   7119 
   7120 /*---------------------------------------------------------------*/
   7121 /*--- Code generation                                         ---*/
   7122 /*---------------------------------------------------------------*/
   7123 
   7124 /* Do not load more bytes than requested. */
   7125 static UChar *
   7126 s390_insn_load_emit(UChar *buf, const s390_insn *insn)
   7127 {
   7128    UInt r, x, b, d;
   7129    const s390_amode *src;
   7130 
   7131    src = insn->variant.load.src;
   7132 
   7133    r = hregNumber(insn->variant.load.dst);
   7134 
   7135    if (hregClass(insn->variant.load.dst) == HRcFlt64) {
   7136       b = hregNumber(src->b);
   7137       x = hregNumber(src->x);  /* 0 for B12 and B20 */
   7138       d = src->d;
   7139 
   7140       switch (insn->size) {
   7141 
   7142       case 4:
   7143          switch (src->tag) {
   7144          case S390_AMODE_B12:
   7145          case S390_AMODE_BX12:
   7146             return s390_emit_LE(buf, r, x, b, d);
   7147 
   7148          case S390_AMODE_B20:
   7149          case S390_AMODE_BX20:
   7150             return s390_emit_LEY(buf, r, x, b, DISP20(d));
   7151          }
   7152          break;
   7153 
   7154       case 8:
   7155          switch (src->tag) {
   7156          case S390_AMODE_B12:
   7157          case S390_AMODE_BX12:
   7158             return s390_emit_LD(buf, r, x, b, d);
   7159 
   7160          case S390_AMODE_B20:
   7161          case S390_AMODE_BX20:
   7162             return s390_emit_LDY(buf, r, x, b, DISP20(d));
   7163          }
   7164          break;
   7165       }
   7166       vpanic("s390_insn_load_emit");
   7167    }
   7168 
   7169    /* Integer stuff */
   7170    return s390_emit_load_mem(buf, insn->size, r, src);
   7171 }
   7172 
   7173 
   7174 static UChar *
   7175 s390_insn_store_emit(UChar *buf, const s390_insn *insn)
   7176 {
   7177    UInt r, x, b, d;
   7178    const s390_amode *dst;
   7179 
   7180    dst = insn->variant.store.dst;
   7181 
   7182    r = hregNumber(insn->variant.store.src);
   7183    b = hregNumber(dst->b);
   7184    x = hregNumber(dst->x);  /* 0 for B12 and B20 */
   7185    d = dst->d;
   7186 
   7187    if (hregClass(insn->variant.store.src) == HRcFlt64) {
   7188       switch (insn->size) {
   7189 
   7190       case 4:
   7191          switch (dst->tag) {
   7192          case S390_AMODE_B12:
   7193          case S390_AMODE_BX12:
   7194             return s390_emit_STE(buf, r, x, b, d);
   7195 
   7196          case S390_AMODE_B20:
   7197          case S390_AMODE_BX20:
   7198             return s390_emit_STEY(buf, r, x, b, DISP20(d));
   7199          }
   7200          break;
   7201 
   7202       case 8:
   7203          switch (dst->tag) {
   7204          case S390_AMODE_B12:
   7205          case S390_AMODE_BX12:
   7206             return s390_emit_STD(buf, r, x, b, d);
   7207 
   7208          case S390_AMODE_B20:
   7209          case S390_AMODE_BX20:
   7210             return s390_emit_STDY(buf, r, x, b, DISP20(d));
   7211          }
   7212          break;
   7213       }
   7214       vpanic("s390_insn_store_emit");
   7215    }
   7216 
   7217    /* Integer stuff */
   7218    switch (insn->size) {
   7219    case 1:
   7220       switch (dst->tag) {
   7221       case S390_AMODE_B12:
   7222       case S390_AMODE_BX12:
   7223          return s390_emit_STC(buf, r, x, b, d);
   7224 
   7225       case S390_AMODE_B20:
   7226       case S390_AMODE_BX20:
   7227          return s390_emit_STCY(buf, r, x, b, DISP20(d));
   7228       }
   7229       break;
   7230 
   7231    case 2:
   7232       switch (dst->tag) {
   7233       case S390_AMODE_B12:
   7234       case S390_AMODE_BX12:
   7235          return s390_emit_STH(buf, r, x, b, d);
   7236 
   7237       case S390_AMODE_B20:
   7238       case S390_AMODE_BX20:
   7239          return s390_emit_STHY(buf, r, x, b, DISP20(d));
   7240       }
   7241       break;
   7242 
   7243    case 4:
   7244       switch (dst->tag) {
   7245       case S390_AMODE_B12:
   7246       case S390_AMODE_BX12:
   7247          return s390_emit_ST(buf, r, x, b, d);
   7248 
   7249       case S390_AMODE_B20:
   7250       case S390_AMODE_BX20:
   7251          return s390_emit_STY(buf, r, x, b, DISP20(d));
   7252       }
   7253       break;
   7254 
   7255    case 8:
   7256       return s390_emit_STG(buf, r, x, b, DISP20(d));
   7257 
   7258    default:
   7259       break;
   7260    }
   7261 
   7262    vpanic("s390_insn_store_emit");
   7263 }
   7264 
   7265 
   7266 static UChar *
   7267 s390_insn_move_emit(UChar *buf, const s390_insn *insn)
   7268 {
   7269    UInt dst, src;
   7270    HRegClass dst_class, src_class;
   7271 
   7272    dst = hregNumber(insn->variant.move.dst);
   7273    src = hregNumber(insn->variant.move.src);
   7274 
   7275    dst_class = hregClass(insn->variant.move.dst);
   7276    src_class = hregClass(insn->variant.move.src);
   7277 
   7278    if (dst_class == src_class) {
   7279       if (dst_class == HRcInt64)
   7280          return s390_emit_LGR(buf, dst, src);
   7281       if (dst_class == HRcFlt64)
   7282          return s390_emit_LDR(buf, dst, src);
   7283    } else {
   7284       if (dst_class == HRcFlt64 && src_class == HRcInt64) {
   7285          if (insn->size == 4) {
   7286             buf = s390_emit_SLLG(buf, R0, src, 0, DISP20(32)); /* r0 = src << 32 */
   7287             return s390_emit_LDGRw(buf, dst, R0);
   7288          } else {
   7289             return s390_emit_LDGRw(buf, dst, src);
   7290          }
   7291       }
   7292       if (dst_class == HRcInt64 && src_class == HRcFlt64) {
   7293          if (insn->size == 4) {
   7294             buf = s390_emit_LGDRw(buf, dst, src);
   7295             return s390_emit_SRLG(buf, dst, dst, 0, DISP20(32)); /* dst >>= 32 */
   7296          } else {
   7297             return s390_emit_LGDRw(buf, dst, src);
   7298          }
   7299       }
   7300       /* A move between floating point registers and general purpose
   7301          registers of different size should never occur and indicates
   7302          an error elsewhere. */
   7303    }
   7304 
   7305    vpanic("s390_insn_move_emit");
   7306 }
   7307 
   7308 
   7309 static UChar *
   7310 s390_insn_memcpy_emit(UChar *buf, const s390_insn *insn)
   7311 {
   7312    s390_amode *dst = insn->variant.memcpy.dst;
   7313    s390_amode *src = insn->variant.memcpy.src;
   7314 
   7315    return s390_emit_MVC(buf, insn->size - 1, hregNumber(dst->b), dst->d,
   7316                         hregNumber(src->b), src->d);
   7317 }
   7318 
   7319 
   7320 static UChar *
   7321 s390_insn_load_immediate_emit(UChar *buf, const s390_insn *insn)
   7322 {
   7323    UInt  r;
   7324    ULong value = insn->variant.load_immediate.value;
   7325 
   7326    r = hregNumber(insn->variant.load_immediate.dst);
   7327 
   7328    if (hregClass(insn->variant.load_immediate.dst) == HRcFlt64) {
   7329       vassert(value == 0);
   7330       switch (insn->size) {
   7331       case 4: return s390_emit_LZER(buf, r, value);
   7332       case 8: return s390_emit_LZDR(buf, r, value);
   7333       }
   7334       vpanic("s390_insn_load_immediate_emit");
   7335    }
   7336 
   7337    switch (insn->size) {
   7338    case 1:
   7339    case 2:
   7340       /* Load the immediate values as a 4 byte value. That does not hurt as
   7341          those extra bytes will not be looked at. Fall through .... */
   7342    case 4:
   7343       return s390_emit_load_32imm(buf, r, value);
   7344 
   7345    case 8:
   7346       return s390_emit_load_64imm(buf, r, value);
   7347    }
   7348 
   7349    vpanic("s390_insn_load_immediate_emit");
   7350 }
   7351 
   7352 
   7353 /* There is no easy way to do ALU operations on 1-byte or 2-byte operands.
   7354    So we simply perform a 4-byte operation. Doing so uses possibly undefined
   7355    bits and produces an undefined result in those extra bit positions. But
   7356    upstream does not look at those positions, so this is OK. */
   7357 static UChar *
   7358 s390_insn_alu_emit(UChar *buf, const s390_insn *insn)
   7359 {
   7360    s390_opnd_RMI op2;
   7361    UInt dst;
   7362 
   7363    dst = hregNumber(insn->variant.alu.dst);
   7364    op2 = insn->variant.alu.op2;
   7365 
   7366    /* Second operand is in a register */
   7367    if (op2.tag == S390_OPND_REG) {
   7368       UInt r2 = hregNumber(op2.variant.reg);
   7369 
   7370       switch (insn->size) {
   7371       case 1:
   7372       case 2:
   7373       case 4:
   7374          switch (insn->variant.alu.tag) {
   7375          case S390_ALU_ADD:  return s390_emit_AR(buf, dst, r2);
   7376          case S390_ALU_SUB:  return s390_emit_SR(buf, dst, r2);
   7377          case S390_ALU_MUL:  return s390_emit_MSR(buf, dst, r2);
   7378          case S390_ALU_AND:  return s390_emit_NR(buf, dst, r2);
   7379          case S390_ALU_OR:   return s390_emit_OR(buf, dst, r2);
   7380          case S390_ALU_XOR:  return s390_emit_XR(buf, dst, r2);
   7381          case S390_ALU_LSH:  return s390_emit_SLL(buf, dst, r2, 0);
   7382          case S390_ALU_RSH:  return s390_emit_SRL(buf, dst, r2, 0);
   7383          case S390_ALU_RSHA: return s390_emit_SRA(buf, dst, r2, 0);
   7384          }
   7385          goto fail;
   7386 
   7387       case 8:
   7388          switch (insn->variant.alu.tag) {
   7389          case S390_ALU_ADD:  return s390_emit_AGR(buf, dst, r2);
   7390          case S390_ALU_SUB:  return s390_emit_SGR(buf, dst, r2);
   7391          case S390_ALU_MUL:  return s390_emit_MSGR(buf, dst, r2);
   7392          case S390_ALU_AND:  return s390_emit_NGR(buf, dst, r2);
   7393          case S390_ALU_OR:   return s390_emit_OGR(buf, dst, r2);
   7394          case S390_ALU_XOR:  return s390_emit_XGR(buf, dst, r2);
   7395          case S390_ALU_LSH:  return s390_emit_SLLG(buf, dst, dst, r2, DISP20(0));
   7396          case S390_ALU_RSH:  return s390_emit_SRLG(buf, dst, dst, r2, DISP20(0));
   7397          case S390_ALU_RSHA: return s390_emit_SRAG(buf, dst, dst, r2, DISP20(0));
   7398          }
   7399          goto fail;
   7400       }
   7401       goto fail;
   7402    }
   7403 
   7404    /* 2nd operand is in memory */
   7405    if (op2.tag == S390_OPND_AMODE) {
   7406       UInt b, x, d;
   7407       const s390_amode *src = op2.variant.am;
   7408 
   7409       b = hregNumber(src->b);
   7410       x = hregNumber(src->x);  /* 0 for B12 and B20 */
   7411       d = src->d;
   7412 
   7413       /* Shift operands are special here as there are no opcodes that
   7414          allow a memory operand. So we first load the 2nd operand into
   7415          some register. R0 is used to save restore the contents of the
   7416          chosen register.. */
   7417 
   7418       if (insn->variant.alu.tag == S390_ALU_LSH ||
   7419           insn->variant.alu.tag == S390_ALU_RSH ||
   7420           insn->variant.alu.tag == S390_ALU_RSHA) {
   7421          UInt b2;
   7422 
   7423          /* Choose a register (other than DST or R0) into which to stick the
   7424             shift amount. The following works because r15 is reserved and
   7425             thusly dst != 15. */
   7426          vassert(dst != 15);  /* extra paranoia */
   7427          b2 = (dst + 1) % 16;
   7428 
   7429          buf = s390_emit_LGR(buf, R0, b2);  /* save */
   7430 
   7431          /* Loading SRC to B2 does not modify R0. */
   7432          buf = s390_emit_load_mem(buf, insn->size, b2, src);
   7433 
   7434          if (insn->size == 8) {
   7435             switch (insn->variant.alu.tag) {
   7436             case S390_ALU_LSH:
   7437                buf = s390_emit_SLLG(buf, dst, dst, b2, DISP20(0));
   7438                break;
   7439             case S390_ALU_RSH:
   7440                buf = s390_emit_SRLG(buf, dst, dst, b2, DISP20(0));
   7441                break;
   7442             case S390_ALU_RSHA:
   7443                buf = s390_emit_SRAG(buf, dst, dst, b2, DISP20(0));
   7444                break;
   7445             default: /* unreachable */
   7446                goto fail;
   7447             }
   7448          } else {
   7449             switch (insn->variant.alu.tag) {
   7450             case S390_ALU_LSH:
   7451                buf = s390_emit_SLL(buf, dst, b2, 0);
   7452                break;
   7453             case S390_ALU_RSH:
   7454                buf = s390_emit_SRL(buf, dst, b2, 0);
   7455                break;
   7456             case S390_ALU_RSHA:
   7457                buf = s390_emit_SRA(buf, dst, b2, 0);
   7458                break;
   7459             default: /* unreachable */
   7460                goto fail;
   7461             }
   7462          }
   7463          return s390_emit_LGR(buf, b2, R0);  /* restore */
   7464       }
   7465 
   7466       switch (insn->size) {
   7467       case 1:
   7468          /* Move the byte from memory into scratch register r0 */
   7469          buf = s390_emit_load_mem(buf, 1, R0, src);
   7470 
   7471          switch (insn->variant.alu.tag) {
   7472          case S390_ALU_ADD: return s390_emit_AR(buf, dst, R0);
   7473          case S390_ALU_SUB: return s390_emit_SR(buf, dst, R0);
   7474          case S390_ALU_MUL: return s390_emit_MSR(buf, dst, R0);
   7475          case S390_ALU_AND: return s390_emit_NR(buf, dst, R0);
   7476          case S390_ALU_OR:  return s390_emit_OR(buf, dst, R0);
   7477          case S390_ALU_XOR: return s390_emit_XR(buf, dst, R0);
   7478          case S390_ALU_LSH:
   7479          case S390_ALU_RSH:
   7480          case S390_ALU_RSHA: ; /* avoid GCC warning */
   7481          }
   7482          goto fail;
   7483 
   7484       case 2:
   7485          switch (src->tag) {
   7486          case S390_AMODE_B12:
   7487          case S390_AMODE_BX12:
   7488             switch (insn->variant.alu.tag) {
   7489             case S390_ALU_ADD:
   7490                return s390_emit_AH(buf, dst, x, b, d);
   7491 
   7492             case S390_ALU_SUB:
   7493                return s390_emit_SH(buf, dst, x, b, d);
   7494 
   7495             case S390_ALU_MUL:
   7496                return s390_emit_MH(buf, dst, x, b, d);
   7497 
   7498                /* For bitwise operations: Move two bytes from memory into scratch
   7499                   register r0; then perform operation */
   7500             case S390_ALU_AND:
   7501                buf = s390_emit_LH(buf, R0, x, b, d);
   7502                return s390_emit_NR(buf, dst, R0);
   7503 
   7504             case S390_ALU_OR:
   7505                buf = s390_emit_LH(buf, R0, x, b, d);
   7506                return s390_emit_OR(buf, dst, R0);
   7507 
   7508             case S390_ALU_XOR:
   7509                buf = s390_emit_LH(buf, R0, x, b, d);
   7510                return s390_emit_XR(buf, dst, R0);
   7511 
   7512             case S390_ALU_LSH:
   7513             case S390_ALU_RSH:
   7514             case S390_ALU_RSHA: ; /* avoid GCC warning */
   7515             }
   7516             goto fail;
   7517 
   7518          case S390_AMODE_B20:
   7519          case S390_AMODE_BX20:
   7520             switch (insn->variant.alu.tag) {
   7521             case S390_ALU_ADD:
   7522                return s390_emit_AHY(buf, dst, x, b, DISP20(d));
   7523 
   7524             case S390_ALU_SUB:
   7525                return s390_emit_SHY(buf, dst, x, b, DISP20(d));
   7526 
   7527             case S390_ALU_MUL:
   7528                return s390_emit_MHYw(buf, dst, x, b, DISP20(d));
   7529 
   7530                /* For bitwise operations: Move two bytes from memory into scratch
   7531                   register r0; then perform operation */
   7532             case S390_ALU_AND:
   7533                buf = s390_emit_LHY(buf, R0, x, b, DISP20(d));
   7534                return s390_emit_NR(buf, dst, R0);
   7535 
   7536             case S390_ALU_OR:
   7537                buf = s390_emit_LHY(buf, R0, x, b, DISP20(d));
   7538                return s390_emit_OR(buf, dst, R0);
   7539 
   7540             case S390_ALU_XOR:
   7541                buf = s390_emit_LHY(buf, R0, x, b, DISP20(d));
   7542                return s390_emit_XR(buf, dst, R0);
   7543 
   7544             case S390_ALU_LSH:
   7545             case S390_ALU_RSH:
   7546             case S390_ALU_RSHA: ; /* avoid GCC warning */
   7547             }
   7548             goto fail;
   7549          }
   7550          goto fail;
   7551 
   7552       case 4:
   7553          switch (src->tag) {
   7554          case S390_AMODE_B12:
   7555          case S390_AMODE_BX12:
   7556             switch (insn->variant.alu.tag) {
   7557             case S390_ALU_ADD: return s390_emit_A(buf, dst, x, b, d);
   7558             case S390_ALU_SUB: return s390_emit_S(buf, dst, x, b, d);
   7559             case S390_ALU_MUL: return s390_emit_MS(buf, dst, x, b, d);
   7560             case S390_ALU_AND: return s390_emit_N(buf, dst, x, b, d);
   7561             case S390_ALU_OR:  return s390_emit_O(buf, dst, x, b, d);
   7562             case S390_ALU_XOR: return s390_emit_X(buf, dst, x, b, d);
   7563             case S390_ALU_LSH:
   7564             case S390_ALU_RSH:
   7565             case S390_ALU_RSHA: ; /* avoid GCC warning */
   7566             }
   7567             goto fail;
   7568 
   7569          case S390_AMODE_B20:
   7570          case S390_AMODE_BX20:
   7571             switch (insn->variant.alu.tag) {
   7572             case S390_ALU_ADD: return s390_emit_AY(buf, dst, x, b, DISP20(d));
   7573             case S390_ALU_SUB: return s390_emit_SY(buf, dst, x, b, DISP20(d));
   7574             case S390_ALU_MUL: return s390_emit_MSY(buf, dst, x, b, DISP20(d));
   7575             case S390_ALU_AND: return s390_emit_NY(buf, dst, x, b, DISP20(d));
   7576             case S390_ALU_OR:  return s390_emit_OY(buf, dst, x, b, DISP20(d));
   7577             case S390_ALU_XOR: return s390_emit_XY(buf, dst, x, b, DISP20(d));
   7578             case S390_ALU_LSH:
   7579             case S390_ALU_RSH:
   7580             case S390_ALU_RSHA: ; /* avoid GCC warning */
   7581             }
   7582             goto fail;
   7583          }
   7584          goto fail;
   7585 
   7586       case 8:
   7587          switch (insn->variant.alu.tag) {
   7588          case S390_ALU_ADD: return s390_emit_AG(buf, dst, x, b, DISP20(d));
   7589          case S390_ALU_SUB: return s390_emit_SG(buf, dst, x, b, DISP20(d));
   7590          case S390_ALU_MUL: return s390_emit_MSG(buf, dst, x, b, DISP20(d));
   7591          case S390_ALU_AND: return s390_emit_NG(buf, dst, x, b, DISP20(d));
   7592          case S390_ALU_OR:  return s390_emit_OG(buf, dst, x, b, DISP20(d));
   7593          case S390_ALU_XOR: return s390_emit_XG(buf, dst, x, b, DISP20(d));
   7594          case S390_ALU_LSH:
   7595          case S390_ALU_RSH:
   7596          case S390_ALU_RSHA: ; /* avoid GCC warning */
   7597          }
   7598          goto fail;
   7599       }
   7600       goto fail;
   7601    }
   7602 
   7603    /* 2nd operand is an immediate value */
   7604    if (op2.tag == S390_OPND_IMMEDIATE) {
   7605       ULong value;
   7606 
   7607       /* No masking of the value is required as it is not sign extended */
   7608       value = op2.variant.imm;
   7609 
   7610       switch (insn->size) {
   7611       case 1:
   7612       case 2:
   7613          /* There is no 1-byte opcode. Do the computation in
   7614             2 bytes. The extra byte will be ignored. */
   7615          switch (insn->variant.alu.tag) {
   7616          case S390_ALU_ADD:
   7617             return s390_emit_AHI(buf, dst, value);
   7618 
   7619          case S390_ALU_SUB:
   7620             return s390_emit_SLFIw(buf, dst, value);
   7621 
   7622          case S390_ALU_MUL:
   7623             return s390_emit_MHI(buf, dst, value);
   7624 
   7625          case S390_ALU_AND: return s390_emit_NILL(buf, dst, value);
   7626          case S390_ALU_OR:  return s390_emit_OILL(buf, dst, value);
   7627          case S390_ALU_XOR:
   7628             /* There is no XILL instruction.  Load the immediate value into
   7629                R0 and combine with the destination register. */
   7630             buf = s390_emit_LHI(buf, R0, value);
   7631             return s390_emit_XR(buf, dst, R0);
   7632 
   7633          case S390_ALU_LSH:
   7634             return s390_emit_SLL(buf, dst, 0, value);
   7635 
   7636          case S390_ALU_RSH:
   7637             return s390_emit_SRL(buf, dst, 0, value);
   7638 
   7639          case S390_ALU_RSHA:
   7640             return s390_emit_SRA(buf, dst, 0, value);
   7641          }
   7642          goto fail;
   7643 
   7644       case 4:
   7645          switch (insn->variant.alu.tag) {
   7646          case S390_ALU_ADD:
   7647             if (uint_fits_signed_16bit(value)) {
   7648                return s390_emit_AHI(buf, dst, value);
   7649             }
   7650             return s390_emit_AFIw(buf, dst, value);
   7651 
   7652          case S390_ALU_SUB:  return s390_emit_SLFIw(buf, dst, value);
   7653          case S390_ALU_MUL:  return s390_emit_MSFIw(buf, dst, value);
   7654          case S390_ALU_AND:  return s390_emit_NILFw(buf, dst, value);
   7655          case S390_ALU_OR:   return s390_emit_OILFw(buf, dst, value);
   7656          case S390_ALU_XOR:  return s390_emit_XILFw(buf, dst, value);
   7657          case S390_ALU_LSH:  return s390_emit_SLL(buf, dst, 0, value);
   7658          case S390_ALU_RSH:  return s390_emit_SRL(buf, dst, 0, value);
   7659          case S390_ALU_RSHA: return s390_emit_SRA(buf, dst, 0, value);
   7660          }
   7661          goto fail;
   7662 
   7663       case 8:
   7664          switch (insn->variant.alu.tag) {
   7665          case S390_ALU_ADD:
   7666             if (ulong_fits_signed_16bit(value)) {
   7667                return s390_emit_AGHI(buf, dst, value);
   7668             }
   7669             if (ulong_fits_signed_32bit(value) && s390_host_has_eimm) {
   7670                return s390_emit_AGFI(buf, dst, value);
   7671             }
   7672             /* Load constant into R0 then add */
   7673             buf = s390_emit_load_64imm(buf, R0, value);
   7674             return s390_emit_AGR(buf, dst, R0);
   7675 
   7676          case S390_ALU_SUB:
   7677             if (ulong_fits_unsigned_32bit(value)) {
   7678                return s390_emit_SLGFIw(buf, dst, value);
   7679             }
   7680             /* Load value into R0; then subtract from destination reg */
   7681             buf = s390_emit_load_64imm(buf, R0, value);
   7682             return s390_emit_SGR(buf, dst, R0);
   7683 
   7684          case S390_ALU_MUL:
   7685             if (ulong_fits_signed_32bit(value) && s390_host_has_gie) {
   7686                return s390_emit_MSGFI(buf, dst, value);
   7687             }
   7688             /* Load constant into R0 then add */
   7689             buf = s390_emit_load_64imm(buf, R0, value);
   7690             return s390_emit_MSGR(buf, dst, R0);
   7691 
   7692             /* Do it in two steps: upper half [0:31] and lower half [32:63] */
   7693          case S390_ALU_AND:
   7694             if (s390_host_has_eimm) {
   7695                buf  = s390_emit_NIHF(buf, dst, value >> 32);
   7696                return s390_emit_NILF(buf, dst, value & 0xFFFFFFFF);
   7697             }
   7698             /* Load value into R0; then combine with destination reg */
   7699             buf = s390_emit_load_64imm(buf, R0, value);
   7700             return s390_emit_NGR(buf, dst, R0);
   7701 
   7702          case S390_ALU_OR:
   7703             if (s390_host_has_eimm) {
   7704                buf  = s390_emit_OIHF(buf, dst, value >> 32);
   7705                return s390_emit_OILF(buf, dst, value & 0xFFFFFFFF);
   7706             }
   7707             /* Load value into R0; then combine with destination reg */
   7708             buf = s390_emit_load_64imm(buf, R0, value);
   7709             return s390_emit_OGR(buf, dst, R0);
   7710 
   7711          case S390_ALU_XOR:
   7712             if (s390_host_has_eimm) {
   7713                buf  = s390_emit_XIHF(buf, dst, value >> 32);
   7714                return s390_emit_XILF(buf, dst, value & 0xFFFFFFFF);
   7715             }
   7716             /* Load value into R0; then combine with destination reg */
   7717             buf = s390_emit_load_64imm(buf, R0, value);
   7718             return s390_emit_XGR(buf, dst, R0);
   7719 
   7720             /* No special considerations for long displacement here. Only the six
   7721                least significant bits of VALUE will be taken; all other bits are
   7722                ignored. So the DH2 bits are irrelevant and do not influence the
   7723                shift operation, independent of whether long-displacement is available
   7724                or not. */
   7725          case S390_ALU_LSH:  return s390_emit_SLLG(buf, dst, dst, 0, DISP20(value));
   7726          case S390_ALU_RSH:  return s390_emit_SRLG(buf, dst, dst, 0, DISP20(value));
   7727          case S390_ALU_RSHA: return s390_emit_SRAG(buf, dst, dst, 0, DISP20(value));
   7728          }
   7729          goto fail;
   7730       }
   7731       goto fail;
   7732    }
   7733 
   7734  fail:
   7735    vpanic("s390_insn_alu_emit");
   7736 }
   7737 
   7738 
   7739 static UChar *
   7740 s390_widen_emit(UChar *buf, const s390_insn *insn, UInt from_size,
   7741                 Bool sign_extend)
   7742 {
   7743    s390_opnd_RMI opnd = insn->variant.unop.src;
   7744 
   7745    switch (opnd.tag) {
   7746    case S390_OPND_REG: {
   7747       UChar r1 = hregNumber(insn->variant.unop.dst);
   7748       UChar r2 = hregNumber(opnd.variant.reg);
   7749 
   7750       switch (from_size) {
   7751       case 1:
   7752          /* Widening to a half-word is implemented like widening to a word
   7753             because the upper half-word will not be looked at. */
   7754          if (insn->size == 4 || insn->size == 2) {  /* 8 --> 32    8 --> 16 */
   7755             if (sign_extend)
   7756                return s390_emit_LBRw(buf, r1, r2);
   7757             else
   7758                return s390_emit_LLCRw(buf, r1, r2);
   7759          }
   7760          if (insn->size == 8) {  /* 8 --> 64 */
   7761             if (sign_extend)
   7762                return s390_emit_LGBRw(buf, r1, r2);
   7763             else
   7764                return s390_emit_LLGCRw(buf, r1, r2);
   7765          }
   7766          goto fail;
   7767 
   7768       case 2:
   7769          if (insn->size == 4) {  /* 16 --> 32 */
   7770             if (sign_extend)
   7771                return s390_emit_LHRw(buf, r1, r2);
   7772             else
   7773                return s390_emit_LLHRw(buf, r1, r2);
   7774          }
   7775          if (insn->size == 8) {  /* 16 --> 64 */
   7776             if (sign_extend)
   7777                return s390_emit_LGHRw(buf, r1, r2);
   7778             else
   7779                return s390_emit_LLGHRw(buf, r1, r2);
   7780          }
   7781          goto fail;
   7782 
   7783       case 4:
   7784          if (insn->size == 8) {  /* 32 --> 64 */
   7785             if (sign_extend)
   7786                return s390_emit_LGFR(buf, r1, r2);
   7787             else
   7788                return s390_emit_LLGFR(buf, r1, r2);
   7789          }
   7790          goto fail;
   7791 
   7792       default: /* unexpected "from" size */
   7793          goto fail;
   7794       }
   7795    }
   7796 
   7797    case S390_OPND_AMODE: {
   7798       UChar r1 = hregNumber(insn->variant.unop.dst);
   7799       const s390_amode *src = opnd.variant.am;
   7800       UChar b = hregNumber(src->b);
   7801       UChar x = hregNumber(src->x);
   7802       Int   d = src->d;
   7803 
   7804       switch (from_size) {
   7805       case 1:
   7806          if (insn->size == 4 || insn->size == 2) {
   7807             if (sign_extend)
   7808                return s390_emit_LB(buf, r1, x, b, DISP20(d));
   7809             else
   7810                return s390_emit_LLCw(buf, r1, x, b, DISP20(d));
   7811          }
   7812          if (insn->size == 8) {
   7813             if (sign_extend)
   7814                return s390_emit_LGB(buf, r1, x, b, DISP20(d));
   7815             else
   7816                return s390_emit_LLGC(buf, r1, x, b, DISP20(d));
   7817          }
   7818          goto fail;
   7819 
   7820       case 2:
   7821          if (insn->size == 4) {  /* 16 --> 32 */
   7822             if (sign_extend == 0)
   7823                return s390_emit_LLHw(buf, r1, x, b, DISP20(d));
   7824 
   7825             switch (src->tag) {
   7826             case S390_AMODE_B12:
   7827             case S390_AMODE_BX12:
   7828                return s390_emit_LH(buf, r1, x, b, d);
   7829 
   7830             case S390_AMODE_B20:
   7831             case S390_AMODE_BX20:
   7832                return s390_emit_LHY(buf, r1, x, b, DISP20(d));
   7833             }
   7834             goto fail;
   7835          }
   7836          if (insn->size == 8) {  /* 16 --> 64 */
   7837             if (sign_extend)
   7838                return s390_emit_LGH(buf, r1, x, b, DISP20(d));
   7839             else
   7840                return s390_emit_LLGH(buf, r1, x, b, DISP20(d));
   7841          }
   7842          goto fail;
   7843 
   7844       case 4:
   7845          if (insn->size == 8) {  /* 32 --> 64 */
   7846             if (sign_extend)
   7847                return s390_emit_LGF(buf, r1, x, b, DISP20(d));
   7848             else
   7849                return s390_emit_LLGF(buf, r1, x, b, DISP20(d));
   7850          }
   7851          goto fail;
   7852 
   7853       default: /* unexpected "from" size */
   7854          goto fail;
   7855       }
   7856    }
   7857 
   7858    case S390_OPND_IMMEDIATE: {
   7859       UChar r1 = hregNumber(insn->variant.unop.dst);
   7860       ULong value = opnd.variant.imm;
   7861 
   7862       switch (from_size) {
   7863       case 1:
   7864          if (insn->size == 4 || insn->size == 2) {  /* 8 --> 32   8 --> 16 */
   7865             if (sign_extend) {
   7866                /* host can do the sign extension to 16-bit; LHI does the rest */
   7867                return s390_emit_LHI(buf, r1, (Short)(Char)(UChar)value);
   7868             } else {
   7869                return s390_emit_LHI(buf, r1, value);
   7870             }
   7871          }
   7872          if (insn->size == 8) {  /* 8 --> 64 */
   7873             if (sign_extend) {
   7874                /* host can do the sign extension to 16-bit; LGHI does the rest */
   7875                return s390_emit_LGHI(buf, r1, (Short)(Char)(UChar)value);
   7876             } else {
   7877                return s390_emit_LGHI(buf, r1, value);
   7878             }
   7879          }
   7880          goto fail;
   7881 
   7882       case 2:
   7883          if (insn->size == 4) {  /* 16 --> 32 */
   7884             return s390_emit_LHI(buf, r1, value);
   7885          }
   7886          if (insn->size == 8) {  /* 16 --> 64 */
   7887             if (sign_extend)
   7888                return s390_emit_LGHI(buf, r1, value);
   7889             else
   7890                return s390_emit_LLILL(buf, r1, value);
   7891          }
   7892          goto fail;
   7893 
   7894       case 4:
   7895          if (insn->size == 8) {  /* 32 --> 64 */
   7896             if (sign_extend)
   7897                return s390_emit_LGFIw(buf, r1, value);
   7898             else
   7899                return s390_emit_LLILFw(buf, r1, value);
   7900          }
   7901          goto fail;
   7902 
   7903       default: /* unexpected "from" size */
   7904          goto fail;
   7905       }
   7906    }
   7907    }
   7908 
   7909  fail:
   7910    vpanic("s390_widen_emit");
   7911 }
   7912 
   7913 
   7914 static UChar *
   7915 s390_negate_emit(UChar *buf, const s390_insn *insn)
   7916 {
   7917    s390_opnd_RMI opnd;
   7918 
   7919    opnd = insn->variant.unop.src;
   7920 
   7921    switch (opnd.tag) {
   7922    case S390_OPND_REG: {
   7923       UChar r1 = hregNumber(insn->variant.unop.dst);
   7924       UChar r2 = hregNumber(opnd.variant.reg);
   7925 
   7926       switch (insn->size) {
   7927       case 1:
   7928       case 2:
   7929       case 4:
   7930          return s390_emit_LCR(buf, r1, r2);
   7931 
   7932       case 8:
   7933          return s390_emit_LCGR(buf, r1, r2);
   7934 
   7935       default:
   7936          goto fail;
   7937       }
   7938    }
   7939 
   7940    case S390_OPND_AMODE: {
   7941       UChar r1 = hregNumber(insn->variant.unop.dst);
   7942 
   7943       /* Load bytes into scratch register R0, then negate */
   7944       buf = s390_emit_load_mem(buf, insn->size, R0, opnd.variant.am);
   7945 
   7946       switch (insn->size) {
   7947       case 1:
   7948       case 2:
   7949       case 4:
   7950          return s390_emit_LCR(buf, r1, R0);
   7951 
   7952       case 8:
   7953          return s390_emit_LCGR(buf, r1, R0);
   7954 
   7955       default:
   7956          goto fail;
   7957       }
   7958    }
   7959 
   7960    case S390_OPND_IMMEDIATE: {
   7961       UChar r1 = hregNumber(insn->variant.unop.dst);
   7962       ULong value = opnd.variant.imm;
   7963 
   7964       value = ~value + 1;   /* two's complement */
   7965 
   7966       switch (insn->size) {
   7967       case 1:
   7968       case 2:
   7969          /* Load the immediate values as a 4 byte value. That does not hurt as
   7970             those extra bytes will not be looked at. Fall through .... */
   7971       case 4:
   7972          return s390_emit_load_32imm(buf, r1, value);
   7973 
   7974       case 8:
   7975          return s390_emit_load_64imm(buf, r1, value);
   7976 
   7977       default:
   7978          goto fail;
   7979       }
   7980    }
   7981    }
   7982 
   7983  fail:
   7984    vpanic("s390_negate_emit");
   7985 }
   7986 
   7987 
   7988 static UChar *
   7989 s390_insn_unop_emit(UChar *buf, const s390_insn *insn)
   7990 {
   7991    switch (insn->variant.unop.tag) {
   7992    case S390_ZERO_EXTEND_8:  return s390_widen_emit(buf, insn, 1, 0);
   7993    case S390_ZERO_EXTEND_16: return s390_widen_emit(buf, insn, 2, 0);
   7994    case S390_ZERO_EXTEND_32: return s390_widen_emit(buf, insn, 4, 0);
   7995 
   7996    case S390_SIGN_EXTEND_8:  return s390_widen_emit(buf, insn, 1, 1);
   7997    case S390_SIGN_EXTEND_16: return s390_widen_emit(buf, insn, 2, 1);
   7998    case S390_SIGN_EXTEND_32: return s390_widen_emit(buf, insn, 4, 1);
   7999 
   8000    case S390_NEGATE:         return s390_negate_emit(buf, insn);
   8001    }
   8002 
   8003    vpanic("s390_insn_unop_emit");
   8004 }
   8005 
   8006 
   8007 /* Only 4-byte and 8-byte operands are handled. 1-byte and 2-byte
   8008    comparisons will have been converted to 4-byte comparisons in
   8009    s390_isel_cc and should not occur here. */
   8010 static UChar *
   8011 s390_insn_test_emit(UChar *buf, const s390_insn *insn)
   8012 {
   8013    s390_opnd_RMI opnd;
   8014 
   8015    opnd = insn->variant.test.src;
   8016 
   8017    switch (opnd.tag) {
   8018    case S390_OPND_REG: {
   8019       UInt reg = hregNumber(opnd.variant.reg);
   8020 
   8021       switch (insn->size) {
   8022       case 4:
   8023          return s390_emit_LTR(buf, reg, reg);
   8024 
   8025       case 8:
   8026          return s390_emit_LTGR(buf, reg, reg);
   8027 
   8028       default:
   8029          goto fail;
   8030       }
   8031    }
   8032 
   8033    case S390_OPND_AMODE: {
   8034       const s390_amode *am = opnd.variant.am;
   8035       UChar b = hregNumber(am->b);
   8036       UChar x = hregNumber(am->x);
   8037       Int   d = am->d;
   8038 
   8039       switch (insn->size) {
   8040       case 4:
   8041          return s390_emit_LTw(buf, R0, x, b, DISP20(d));
   8042 
   8043       case 8:
   8044          return s390_emit_LTGw(buf, R0, x, b, DISP20(d));
   8045 
   8046       default:
   8047          goto fail;
   8048       }
   8049    }
   8050 
   8051    case S390_OPND_IMMEDIATE: {
   8052       ULong value = opnd.variant.imm;
   8053 
   8054       switch (insn->size) {
   8055       case 4:
   8056          buf = s390_emit_load_32imm(buf, R0, value);
   8057          return s390_emit_LTR(buf, R0, R0);
   8058 
   8059       case 8:
   8060          buf = s390_emit_load_64imm(buf, R0, value);
   8061          return s390_emit_LTGR(buf, R0, R0);
   8062 
   8063       default:
   8064          goto fail;
   8065       }
   8066    }
   8067 
   8068    default:
   8069       goto fail;
   8070    }
   8071 
   8072  fail:
   8073    vpanic("s390_insn_test_emit");
   8074 }
   8075 
   8076 
   8077 static UChar *
   8078 s390_insn_cc2bool_emit(UChar *buf, const s390_insn *insn)
   8079 {
   8080    UChar r1 = hregNumber(insn->variant.cc2bool.dst);
   8081    s390_cc_t cond = insn->variant.cc2bool.cond;
   8082 
   8083    /* Make the destination register be 1 or 0, depending on whether
   8084       the relevant condition holds. A 64-bit value is computed. */
   8085    if (cond == S390_CC_ALWAYS)
   8086       return s390_emit_LGHI(buf, r1, 1);  /* r1 = 1 */
   8087 
   8088    buf = s390_emit_load_cc(buf, r1);                 /* r1 = cc */
   8089    buf = s390_emit_LGHI(buf, R0, cond);              /* r0 = mask */
   8090    buf = s390_emit_SLLG(buf, r1, R0, r1, DISP20(0)); /* r1 = mask << cc */
   8091    buf = s390_emit_SRLG(buf, r1, r1, 0,  DISP20(3)); /* r1 = r1 >> 3 */
   8092    buf = s390_emit_NILL(buf, r1, 1);                 /* r1 = r1 & 0x1 */
   8093 
   8094    return buf;
   8095 }
   8096 
   8097 
   8098 /* Only 4-byte and 8-byte operands are handled. */
   8099 static UChar *
   8100 s390_insn_cas_emit(UChar *buf, const s390_insn *insn)
   8101 {
   8102    UChar r1, r3, b, old;
   8103    Int d;
   8104    s390_amode *am;
   8105 
   8106    r1 = hregNumber(insn->variant.cas.op1); /* expected value */
   8107    r3 = hregNumber(insn->variant.cas.op3);
   8108    old= hregNumber(insn->variant.cas.old_mem);
   8109    am = insn->variant.cas.op2;
   8110    b  = hregNumber(am->b);
   8111    d  = am->d;
   8112 
   8113    vassert(am->tag == S390_AMODE_B12 || am->tag == S390_AMODE_B20);
   8114 
   8115    switch (insn->size) {
   8116    case 4:
   8117       /* r1 must not be overwritten. So copy it to R0 and let CS clobber it */
   8118       buf = s390_emit_LR(buf, R0, r1);
   8119       if (am->tag == S390_AMODE_B12)
   8120          buf = s390_emit_CS(buf, R0, r3, b, d);
   8121       else
   8122          buf = s390_emit_CSY(buf, R0, r3, b, DISP20(d));
   8123       /* Now copy R0 which has the old memory value to OLD */
   8124       return s390_emit_LR(buf, old, R0);
   8125 
   8126    case 8:
   8127       /* r1 must not be overwritten. So copy it to R0 and let CS clobber it */
   8128       buf = s390_emit_LGR(buf, R0, r1);
   8129       buf = s390_emit_CSG(buf, R0, r3, b, DISP20(d));
   8130       /* Now copy R0 which has the old memory value to OLD */
   8131       return s390_emit_LGR(buf, old, R0);
   8132 
   8133    default:
   8134       goto fail;
   8135    }
   8136 
   8137  fail:
   8138    vpanic("s390_insn_cas_emit");
   8139 }
   8140 
   8141 
   8142 /* Only 4-byte and 8-byte operands are handled. */
   8143 static UChar *
   8144 s390_insn_cdas_emit(UChar *buf, const s390_insn *insn)
   8145 {
   8146    UChar r1, r1p1, r3, /*r3p1,*/ b, old_high, old_low, scratch;
   8147    Int d;
   8148    s390_amode *am;
   8149    s390_cdas *cdas = insn->variant.cdas.details;
   8150 
   8151    r1   = hregNumber(cdas->op1_high); /* expected value */
   8152    r1p1 = hregNumber(cdas->op1_low);  /* expected value */
   8153    r3   = hregNumber(cdas->op3_high);
   8154    /* r3p1 = hregNumber(cdas->op3_low); */ /* unused */
   8155    old_high = hregNumber(cdas->old_mem_high);
   8156    old_low  = hregNumber(cdas->old_mem_low);
   8157    scratch  = hregNumber(cdas->scratch);
   8158    am = cdas->op2;
   8159    b  = hregNumber(am->b);
   8160    d  = am->d;
   8161 
   8162    vassert(scratch == 1);
   8163    vassert(am->tag == S390_AMODE_B12 || am->tag == S390_AMODE_B20);
   8164 
   8165    switch (insn->size) {
   8166    case 4:
   8167       /* r1, r1+1 must not be overwritten. So copy them to R0,scratch
   8168          and let CDS/CDSY clobber it */
   8169       buf = s390_emit_LR(buf, R0, r1);
   8170       buf = s390_emit_LR(buf, scratch, r1p1);
   8171 
   8172       if (am->tag == S390_AMODE_B12)
   8173          buf = s390_emit_CDS(buf, R0, r3, b, d);
   8174       else
   8175          buf = s390_emit_CDSY(buf, R0, r3, b, DISP20(d));
   8176 
   8177       /* Now copy R0,scratch which has the old memory value to OLD */
   8178       buf = s390_emit_LR(buf, old_high, R0);
   8179       buf = s390_emit_LR(buf, old_low,  scratch);
   8180       return buf;
   8181 
   8182    case 8:
   8183       /* r1, r1+1 must not be overwritten. So copy them to R0,scratch
   8184          and let CDSG clobber it */
   8185       buf = s390_emit_LGR(buf, R0, r1);
   8186       buf = s390_emit_LGR(buf, scratch, r1p1);
   8187 
   8188       buf = s390_emit_CDSG(buf, R0, r3, b, DISP20(d));
   8189 
   8190       /* Now copy R0,scratch which has the old memory value to OLD */
   8191       buf = s390_emit_LGR(buf, old_high, R0);
   8192       buf = s390_emit_LGR(buf, old_low,  scratch);
   8193       return buf;
   8194 
   8195    default:
   8196       goto fail;
   8197    }
   8198 
   8199  fail:
   8200    vpanic("s390_insn_cdas_emit");
   8201 }
   8202 
   8203 
   8204 /* Only 4-byte and 8-byte comparisons are handled. 1-byte and 2-byte
   8205    comparisons will have been converted to 4-byte comparisons in
   8206    s390_isel_cc and should not occur here. */
   8207 static UChar *
   8208 s390_insn_compare_emit(UChar *buf, const s390_insn *insn)
   8209 {
   8210    s390_opnd_RMI op2;
   8211    HReg op1;
   8212    Bool signed_comparison;
   8213 
   8214    op1 = insn->variant.compare.src1;
   8215    op2 = insn->variant.compare.src2;
   8216    signed_comparison = insn->variant.compare.signed_comparison;
   8217 
   8218    switch (op2.tag) {
   8219    case S390_OPND_REG: {
   8220       UInt r1 = hregNumber(op1);
   8221       UInt r2 = hregNumber(op2.variant.reg);
   8222 
   8223       switch (insn->size) {
   8224       case 4:
   8225          if (signed_comparison)
   8226             return s390_emit_CR(buf, r1, r2);
   8227          else
   8228             return s390_emit_CLR(buf, r1, r2);
   8229 
   8230       case 8:
   8231          if (signed_comparison)
   8232             return s390_emit_CGR(buf, r1, r2);
   8233          else
   8234             return s390_emit_CLGR(buf, r1, r2);
   8235 
   8236       default:
   8237          goto fail;
   8238       }
   8239    }
   8240 
   8241    case S390_OPND_AMODE: {
   8242       UChar r1 = hregNumber(op1);
   8243       const s390_amode *am = op2.variant.am;
   8244       UChar b = hregNumber(am->b);
   8245       UChar x = hregNumber(am->x);
   8246       Int   d = am->d;
   8247 
   8248       switch (insn->size) {
   8249       case 4:
   8250          switch (am->tag) {
   8251          case S390_AMODE_B12:
   8252          case S390_AMODE_BX12:
   8253             if (signed_comparison)
   8254                return s390_emit_C(buf, r1, x, b, d);
   8255             else
   8256                return s390_emit_CL(buf, r1, x, b, d);
   8257 
   8258          case S390_AMODE_B20:
   8259          case S390_AMODE_BX20:
   8260             if (signed_comparison)
   8261                return s390_emit_CY(buf, r1, x, b, DISP20(d));
   8262             else
   8263                return s390_emit_CLY(buf, r1, x, b, DISP20(d));
   8264          }
   8265          goto fail;
   8266 
   8267       case 8:
   8268          if (signed_comparison)
   8269             return s390_emit_CG(buf, r1, x, b, DISP20(d));
   8270          else
   8271             return s390_emit_CLG(buf, r1, x, b, DISP20(d));
   8272 
   8273       default:
   8274          goto fail;
   8275       }
   8276    }
   8277 
   8278    case S390_OPND_IMMEDIATE: {
   8279       UChar r1 = hregNumber(op1);
   8280       ULong value = op2.variant.imm;
   8281 
   8282       switch (insn->size) {
   8283       case 4:
   8284          if (signed_comparison)
   8285             return s390_emit_CFIw(buf, r1, value);
   8286          else
   8287             return s390_emit_CLFIw(buf, r1, value);
   8288 
   8289       case 8:
   8290          if (s390_host_has_eimm) {
   8291             if (signed_comparison) {
   8292                if (ulong_fits_signed_32bit(value))
   8293                   return s390_emit_CGFI(buf, r1, value);
   8294             } else {
   8295                if (ulong_fits_unsigned_32bit(value))
   8296                   return s390_emit_CLGFI(buf, r1, value);
   8297             }
   8298          }
   8299          buf = s390_emit_load_64imm(buf, R0, value);
   8300          if (signed_comparison)
   8301             return s390_emit_CGR(buf, r1, R0);
   8302          else
   8303             return s390_emit_CLGR(buf, r1, R0);
   8304 
   8305       default:
   8306          goto fail;
   8307       }
   8308    }
   8309 
   8310    default:
   8311       goto fail;
   8312    }
   8313 
   8314  fail:
   8315    vpanic("s390_insn_compare_emit");
   8316 }
   8317 
   8318 
   8319 static UChar *
   8320 s390_insn_mul_emit(UChar *buf, const s390_insn *insn)
   8321 {
   8322    s390_opnd_RMI op2;
   8323    UChar r1;
   8324    Bool signed_multiply;
   8325 
   8326    /* The register number identifying the register pair */
   8327    r1  = hregNumber(insn->variant.mul.dst_hi);
   8328 
   8329    op2 = insn->variant.mul.op2;
   8330    signed_multiply = insn->tag == S390_INSN_SMUL;
   8331 
   8332    switch (op2.tag) {
   8333    case S390_OPND_REG: {
   8334       UInt r2 = hregNumber(op2.variant.reg);
   8335 
   8336       switch (insn->size) {
   8337       case 1:
   8338       case 2:
   8339       case 4:
   8340          if (signed_multiply)
   8341             return s390_emit_MR(buf, r1, r2);
   8342          else
   8343             return s390_emit_MLR(buf, r1, r2);
   8344 
   8345       case 8:
   8346          if (signed_multiply)
   8347             vpanic("s390_insn_mul_emit");
   8348          else
   8349             return s390_emit_MLGR(buf, r1, r2);
   8350 
   8351       default:
   8352          goto fail;
   8353       }
   8354    }
   8355 
   8356    case S390_OPND_AMODE: {
   8357       const s390_amode *am = op2.variant.am;
   8358       UChar b = hregNumber(am->b);
   8359       UChar x = hregNumber(am->x);
   8360       Int   d = am->d;
   8361 
   8362       switch (insn->size) {
   8363       case 1:
   8364       case 2:
   8365          /* Load bytes into scratch register R0, then multiply */
   8366          buf = s390_emit_load_mem(buf, insn->size, R0, am);
   8367          if (signed_multiply)
   8368             return s390_emit_MR(buf, r1, R0);
   8369          else
   8370             return s390_emit_MLR(buf, r1, R0);
   8371 
   8372       case 4:
   8373          switch (am->tag) {
   8374          case S390_AMODE_B12:
   8375          case S390_AMODE_BX12:
   8376             if (signed_multiply)
   8377                return s390_emit_M(buf, r1, x, b, d);
   8378             else
   8379                return s390_emit_ML(buf, r1, x, b, DISP20(d));
   8380 
   8381          case S390_AMODE_B20:
   8382          case S390_AMODE_BX20:
   8383             if (signed_multiply)
   8384                return s390_emit_MFYw(buf, r1, x, b, DISP20(d));
   8385             else
   8386                return s390_emit_ML(buf, r1, x, b, DISP20(d));
   8387          }
   8388          goto fail;
   8389 
   8390       case 8:
   8391          if (signed_multiply)
   8392             vpanic("s390_insn_mul_emit");
   8393          else
   8394             return s390_emit_MLG(buf, r1, x, b, DISP20(d));
   8395 
   8396       default:
   8397          goto fail;
   8398       }
   8399    }
   8400 
   8401    case S390_OPND_IMMEDIATE: {
   8402       ULong value = op2.variant.imm;
   8403 
   8404       switch (insn->size) {
   8405       case 1:
   8406       case 2:
   8407       case 4:
   8408          buf = s390_emit_load_32imm(buf, R0, value);
   8409          if (signed_multiply)
   8410             return s390_emit_MR(buf, r1, R0);
   8411          else
   8412             return s390_emit_MLR(buf, r1, R0);
   8413 
   8414       case 8:
   8415          buf = s390_emit_load_64imm(buf, R0, value);
   8416          if (signed_multiply)
   8417             vpanic("s390_insn_mul_emit");
   8418          else
   8419             return s390_emit_MLGR(buf, r1, R0);
   8420 
   8421       default:
   8422          goto fail;
   8423       }
   8424    }
   8425 
   8426    default:
   8427       goto fail;
   8428    }
   8429 
   8430  fail:
   8431    vpanic("s390_insn_mul_emit");
   8432 }
   8433 
   8434 
   8435 static UChar *
   8436 s390_insn_div_emit(UChar *buf, const s390_insn *insn)
   8437 {
   8438    s390_opnd_RMI op2;
   8439    UChar r1;
   8440    Bool signed_divide;
   8441 
   8442    r1  = hregNumber(insn->variant.div.op1_hi);
   8443    op2 = insn->variant.div.op2;
   8444    signed_divide = insn->tag == S390_INSN_SDIV;
   8445 
   8446    switch (op2.tag) {
   8447    case S390_OPND_REG: {
   8448       UInt r2 = hregNumber(op2.variant.reg);
   8449 
   8450       switch (insn->size) {
   8451       case 4:
   8452          if (signed_divide)
   8453             return s390_emit_DR(buf, r1, r2);
   8454          else
   8455             return s390_emit_DLR(buf, r1, r2);
   8456 
   8457       case 8:
   8458          if (signed_divide)
   8459             vpanic("s390_insn_div_emit");
   8460          else
   8461             return s390_emit_DLGR(buf, r1, r2);
   8462 
   8463       default:
   8464          goto fail;
   8465       }
   8466    }
   8467 
   8468    case S390_OPND_AMODE: {
   8469       const s390_amode *am = op2.variant.am;
   8470       UChar b = hregNumber(am->b);
   8471       UChar x = hregNumber(am->x);
   8472       Int   d = am->d;
   8473 
   8474       switch (insn->size) {
   8475       case 4:
   8476          switch (am->tag) {
   8477          case S390_AMODE_B12:
   8478          case S390_AMODE_BX12:
   8479             if (signed_divide)
   8480                return s390_emit_D(buf, r1, x, b, d);
   8481             else
   8482                return s390_emit_DL(buf, r1, x, b, DISP20(d));
   8483 
   8484          case S390_AMODE_B20:
   8485          case S390_AMODE_BX20:
   8486             if (signed_divide) {
   8487                buf = s390_emit_LY(buf, R0, x, b, DISP20(d));
   8488                return s390_emit_DR(buf, r1, R0);
   8489             } else
   8490                return s390_emit_DL(buf, r1, x, b, DISP20(d));
   8491          }
   8492          goto fail;
   8493 
   8494       case 8:
   8495          if (signed_divide)
   8496             vpanic("s390_insn_div_emit");
   8497          else
   8498             return s390_emit_DLG(buf, r1, x, b, DISP20(d));
   8499 
   8500       default:
   8501          goto fail;
   8502       }
   8503    }
   8504 
   8505    case S390_OPND_IMMEDIATE: {
   8506       ULong value = op2.variant.imm;
   8507 
   8508       switch (insn->size) {
   8509       case 4:
   8510          buf = s390_emit_load_32imm(buf, R0, value);
   8511          if (signed_divide)
   8512             return s390_emit_DR(buf, r1, R0);
   8513          else
   8514             return s390_emit_DLR(buf, r1, R0);
   8515 
   8516       case 8:
   8517          buf = s390_emit_load_64imm(buf, R0, value);
   8518          if (signed_divide)
   8519             vpanic("s390_insn_div_emit");
   8520          else
   8521             return s390_emit_DLGR(buf, r1, R0);
   8522 
   8523       default:
   8524          goto fail;
   8525       }
   8526    }
   8527 
   8528    default:
   8529       goto fail;
   8530    }
   8531 
   8532  fail:
   8533    vpanic("s390_insn_div_emit");
   8534 }
   8535 
   8536 
   8537 static UChar *
   8538 s390_insn_divs_emit(UChar *buf, const s390_insn *insn)
   8539 {
   8540    s390_opnd_RMI op2;
   8541    UChar r1;
   8542 
   8543    r1  = hregNumber(insn->variant.divs.rem);
   8544    op2 = insn->variant.divs.op2;
   8545 
   8546    switch (op2.tag) {
   8547    case S390_OPND_REG: {
   8548       UInt r2 = hregNumber(op2.variant.reg);
   8549 
   8550       return s390_emit_DSGR(buf, r1, r2);
   8551    }
   8552 
   8553    case S390_OPND_AMODE: {
   8554       const s390_amode *am = op2.variant.am;
   8555       UChar b = hregNumber(am->b);
   8556       UChar x = hregNumber(am->x);
   8557       Int   d = am->d;
   8558 
   8559       return s390_emit_DSG(buf, r1, x, b, DISP20(d));
   8560    }
   8561 
   8562    case S390_OPND_IMMEDIATE: {
   8563       ULong value = op2.variant.imm;
   8564 
   8565       buf = s390_emit_load_64imm(buf, R0, value);
   8566       return s390_emit_DSGR(buf, r1, R0);
   8567    }
   8568 
   8569    default:
   8570       goto fail;
   8571    }
   8572 
   8573  fail:
   8574    vpanic("s390_insn_divs_emit");
   8575 }
   8576 
   8577 
   8578 static UChar *
   8579 s390_insn_clz_emit(UChar *buf, const s390_insn *insn)
   8580 {
   8581    s390_opnd_RMI src;
   8582    UChar r1, r1p1, r2, *p;
   8583 
   8584    r1   = hregNumber(insn->variant.clz.num_bits);
   8585    r1p1 = hregNumber(insn->variant.clz.clobber);
   8586 
   8587    vassert((r1 & 0x1) == 0);
   8588    vassert(r1p1 == r1 + 1);
   8589 
   8590    p = buf;
   8591    src = insn->variant.clz.src;
   8592 
   8593    /* Get operand and move it to r2 */
   8594    switch (src.tag) {
   8595    case S390_OPND_REG:
   8596       r2 = hregNumber(src.variant.reg);
   8597       break;
   8598 
   8599    case S390_OPND_AMODE: {
   8600       const s390_amode *am = src.variant.am;
   8601       UChar b = hregNumber(am->b);
   8602       UChar x = hregNumber(am->x);
   8603       Int   d = am->d;
   8604 
   8605       p  = s390_emit_LG(p, R0, x, b, DISP20(d));
   8606       r2 = R0;
   8607       break;
   8608    }
   8609 
   8610    case S390_OPND_IMMEDIATE: {
   8611       ULong value = src.variant.imm;
   8612 
   8613       p  = s390_emit_load_64imm(p, R0, value);
   8614       r2 = R0;
   8615       break;
   8616    }
   8617 
   8618    default:
   8619       goto fail;
   8620    }
   8621 
   8622    /* Use FLOGR if you can */
   8623    if (s390_host_has_eimm) {
   8624       return s390_emit_FLOGR(p, r1, r2);
   8625    }
   8626 
   8627    /*
   8628       r0 = r2;
   8629       r1 = 64;
   8630       while (r0 != 0) {
   8631         r1 -= 1;
   8632         r0 >>= 1;
   8633       }
   8634    */
   8635    p = s390_emit_LTGR(p, R0, r2);
   8636    p = s390_emit_LLILL(p, r1,  64);
   8637 
   8638    p = s390_emit_BRC(p, S390_CC_E, (4 + 4 + 6 + 4 + 4)/ 2);  /* 4 bytes */
   8639    p = s390_emit_AGHI(p, r1, (UShort)-1);         /* r1  -= 1;  4 bytes */
   8640    p = s390_emit_SRLG(p, R0, R0, R0, DISP20(1));  /* r0 >>= 1;  6 bytes */
   8641    p = s390_emit_LTGR(p, R0, R0);                 /* set cc     4 bytes */
   8642    p = s390_emit_BRC(p, S390_CC_NE,               /*            4 bytes */
   8643                      (UShort)(-(4 + 6 + 4) / 2));
   8644    return p;
   8645 
   8646  fail:
   8647    vpanic("s390_insn_clz_emit");
   8648 }
   8649 
   8650 
   8651 /* Returns a value == BUF to denote failure, != BUF to denote success. */
   8652 static UChar *
   8653 s390_insn_helper_call_emit(UChar *buf, const s390_insn *insn)
   8654 {
   8655    s390_cc_t cond;
   8656    ULong target;
   8657    UChar *ptmp = buf;
   8658    s390_helper_call *helper_call = insn->variant.helper_call.details;
   8659 
   8660    cond = helper_call->cond;
   8661    target = helper_call->target;
   8662 
   8663    if (cond != S390_CC_ALWAYS
   8664        && helper_call->rloc.pri != RLPri_None) {
   8665       /* The call might not happen (it isn't unconditional) and it
   8666          returns a result.  In this case we will need to generate a
   8667          control flow diamond to put 0x555..555 in the return
   8668          register(s) in the case where the call doesn't happen.  If
   8669          this ever becomes necessary, maybe copy code from the ARM
   8670          equivalent.  Until that day, just give up. */
   8671       return buf; /* To denote failure. */
   8672    }
   8673 
   8674    if (cond != S390_CC_ALWAYS) {
   8675       /* So we have something like this
   8676          if (cond) call X;
   8677          Y: ...
   8678          We convert this into
   8679          if (! cond) goto Y;        // BRC opcode; 4 bytes
   8680          call X;
   8681          Y:
   8682       */
   8683       /* 4 bytes (a BRC insn) to be filled in here */
   8684       buf += 4;
   8685    }
   8686 
   8687    /* Load the target address into a register, that
   8688       (a) is not used for passing parameters to the helper and
   8689       (b) can be clobbered by the callee
   8690       (c) is not special to the BASR insn
   8691       r1 is the only choice.
   8692       Also, need to arrange for the return address be put into the
   8693       link-register */
   8694    buf = s390_emit_load_64imm(buf, 1, target);
   8695 
   8696    /* Stash away the client's FPC register because the helper might change it. */
   8697    buf = s390_emit_STFPC(buf, S390_REGNO_STACK_POINTER, S390_OFFSET_SAVED_FPC_C);
   8698 
   8699    buf = s390_emit_BASR(buf, S390_REGNO_LINK_REGISTER, 1);      // call helper
   8700 
   8701    buf = s390_emit_LFPC(buf, S390_REGNO_STACK_POINTER,          // restore FPC
   8702                         S390_OFFSET_SAVED_FPC_C);
   8703 
   8704    if (cond != S390_CC_ALWAYS) {
   8705       Int delta = buf - ptmp;
   8706 
   8707       delta >>= 1;  /* immediate constant is #half-words */
   8708       vassert(delta > 0 && delta < (1 << 16));
   8709       s390_emit_BRC(ptmp, s390_cc_invert(cond), delta);
   8710    }
   8711 
   8712    return buf;
   8713 }
   8714 
   8715 
   8716 static UChar *
   8717 s390_insn_cond_move_emit(UChar *buf, const s390_insn *insn)
   8718 {
   8719    HReg dst;
   8720    s390_opnd_RMI src;
   8721    s390_cc_t cond;
   8722    UChar *p, *ptmp = 0;   /* avoid compiler warnings */
   8723 
   8724    cond = insn->variant.cond_move.cond;
   8725    dst  = insn->variant.cond_move.dst;
   8726    src  = insn->variant.cond_move.src;
   8727 
   8728    if (cond == S390_CC_NEVER) return buf;
   8729 
   8730    p = buf;
   8731 
   8732    if (s390_host_has_lsc) {
   8733       /* LOCx is not the preferred way to implement an unconditional load. */
   8734       if (cond != S390_CC_ALWAYS) goto use_branch_insn;
   8735 
   8736       switch (src.tag) {
   8737       case S390_OPND_REG:
   8738          return s390_emit_LOCGR(p, cond, hregNumber(dst),
   8739                                 hregNumber(src.variant.reg));
   8740 
   8741       case S390_OPND_AMODE: {
   8742          const s390_amode *am = src.variant.am;
   8743 
   8744          /* We cannot use LOCx for loads less than 4 bytes. In that case
   8745             load into R0 and then use LOCGR. Do the same if the amode uses
   8746             an index register. */
   8747          if (insn->size < 4 ||
   8748              am->tag == S390_AMODE_BX12 || am->tag == S390_AMODE_BX20) {
   8749             p = s390_emit_load_mem(p, insn->size, R0, am);
   8750             p = s390_emit_LOCGR(p, cond, hregNumber(dst), R0);
   8751             return p;
   8752          }
   8753 
   8754          vassert(am->tag == S390_AMODE_B12 || am->tag == S390_AMODE_B20);
   8755          vassert(insn->size == 4 || insn->size == 8);
   8756 
   8757          UInt b = hregNumber(am->b);
   8758          UInt d = am->d;
   8759 
   8760          if (insn->size == 4) {
   8761             return s390_emit_LOC(p, hregNumber(dst), cond, b, DISP20(d));
   8762          }
   8763          return s390_emit_LOCG(p, hregNumber(dst), cond, b, DISP20(d));
   8764       }
   8765 
   8766       case S390_OPND_IMMEDIATE: {
   8767          ULong value = src.variant.imm;
   8768 
   8769          /* Load value into R0, then use LOCGR */
   8770          if (insn->size <= 4) {
   8771             p = s390_emit_load_32imm(p, R0, value);
   8772             return s390_emit_LOCGR(p, cond, hregNumber(dst), R0);
   8773          }
   8774 
   8775          vassert(insn->size == 8);
   8776          p = s390_emit_load_64imm(p, R0, value);
   8777          return s390_emit_LOCGR(p, cond, hregNumber(dst), R0);
   8778       }
   8779       }
   8780    }
   8781 
   8782 use_branch_insn:
   8783    /* Branch (if cond fails) over move instrs */
   8784    if (cond != S390_CC_ALWAYS) {
   8785       /* Don't know how many bytes to jump over yet.
   8786          Make space for a BRC instruction (4 bytes) and fill in later. */
   8787       ptmp = p;   /*  to be filled in here */
   8788       p += 4;
   8789    }
   8790 
   8791    // cond true: move src => dst
   8792 
   8793    switch (src.tag) {
   8794    case S390_OPND_REG:
   8795       p = s390_emit_LGR(p, hregNumber(dst), hregNumber(src.variant.reg));
   8796       break;
   8797 
   8798    case S390_OPND_AMODE:
   8799       p = s390_emit_load_mem(p, insn->size, hregNumber(dst), src.variant.am);
   8800       break;
   8801 
   8802    case S390_OPND_IMMEDIATE: {
   8803       ULong value = src.variant.imm;
   8804       UInt  r = hregNumber(dst);
   8805 
   8806       switch (insn->size) {
   8807       case 1:
   8808       case 2:
   8809          /* Load the immediate values as a 4 byte value. That does not hurt as
   8810             those extra bytes will not be looked at. Fall through .... */
   8811       case 4:
   8812          p = s390_emit_load_32imm(p, r, value);
   8813          break;
   8814 
   8815       case 8:
   8816          p = s390_emit_load_64imm(p, r, value);
   8817          break;
   8818       }
   8819       break;
   8820    }
   8821 
   8822    default:
   8823       goto fail;
   8824    }
   8825 
   8826    if (cond != S390_CC_ALWAYS) {
   8827       Int delta = p - ptmp;
   8828 
   8829       delta >>= 1;  /* immediate constant is #half-words */
   8830       vassert(delta > 0 && delta < (1 << 16));
   8831       s390_emit_BRC(ptmp, s390_cc_invert(cond), delta);
   8832    }
   8833 
   8834    return p;
   8835 
   8836  fail:
   8837    vpanic("s390_insn_cond_move_emit");
   8838 }
   8839 
   8840 
   8841 static UChar *
   8842 s390_insn_bfp_triop_emit(UChar *buf, const s390_insn *insn)
   8843 {
   8844    UInt r1 = hregNumber(insn->variant.bfp_triop.dst);
   8845    UInt r2 = hregNumber(insn->variant.bfp_triop.op2);
   8846    UInt r3 = hregNumber(insn->variant.bfp_triop.op3);
   8847 
   8848    switch (insn->size) {
   8849    case 4:
   8850       switch (insn->variant.bfp_triop.tag) {
   8851       case S390_BFP_MADD:  return s390_emit_MAEBR(buf, r1, r3, r2);
   8852       case S390_BFP_MSUB:  return s390_emit_MSEBR(buf, r1, r3, r2);
   8853       default:  goto fail;
   8854       }
   8855       break;
   8856 
   8857    case 8:
   8858       switch (insn->variant.bfp_triop.tag) {
   8859       case S390_BFP_MADD:  return s390_emit_MADBR(buf, r1, r3, r2);
   8860       case S390_BFP_MSUB:  return s390_emit_MSDBR(buf, r1, r3, r2);
   8861       default:  goto fail;
   8862       }
   8863       break;
   8864 
   8865    default:  goto fail;
   8866    }
   8867 
   8868  fail:
   8869    vpanic("s390_insn_bfp_triop_emit");
   8870 }
   8871 
   8872 
   8873 static UChar *
   8874 s390_insn_bfp_binop_emit(UChar *buf, const s390_insn *insn)
   8875 {
   8876    UInt r1 = hregNumber(insn->variant.bfp_binop.dst_hi);
   8877    UInt r2 = hregNumber(insn->variant.bfp_binop.op2_hi);
   8878 
   8879    switch (insn->size) {
   8880    case 4:
   8881       switch (insn->variant.bfp_binop.tag) {
   8882       case S390_BFP_ADD:     return s390_emit_AEBR(buf, r1, r2);
   8883       case S390_BFP_SUB:     return s390_emit_SEBR(buf, r1, r2);
   8884       case S390_BFP_MUL:     return s390_emit_MEEBR(buf, r1, r2);
   8885       case S390_BFP_DIV:     return s390_emit_DEBR(buf, r1, r2);
   8886       default:  goto fail;
   8887       }
   8888       break;
   8889 
   8890    case 8:
   8891       switch (insn->variant.bfp_binop.tag) {
   8892       case S390_BFP_ADD:     return s390_emit_ADBR(buf, r1, r2);
   8893       case S390_BFP_SUB:     return s390_emit_SDBR(buf, r1, r2);
   8894       case S390_BFP_MUL:     return s390_emit_MDBR(buf, r1, r2);
   8895       case S390_BFP_DIV:     return s390_emit_DDBR(buf, r1, r2);
   8896       default:  goto fail;
   8897       }
   8898       break;
   8899 
   8900    case 16:
   8901       switch (insn->variant.bfp_binop.tag) {
   8902       case S390_BFP_ADD:     return s390_emit_AXBR(buf, r1, r2);
   8903       case S390_BFP_SUB:     return s390_emit_SXBR(buf, r1, r2);
   8904       case S390_BFP_MUL:     return s390_emit_MXBR(buf, r1, r2);
   8905       case S390_BFP_DIV:     return s390_emit_DXBR(buf, r1, r2);
   8906       default:  goto fail;
   8907       }
   8908       break;
   8909 
   8910    default:  goto fail;
   8911    }
   8912 
   8913  fail:
   8914    vpanic("s390_insn_bfp_binop_emit");
   8915 }
   8916 
   8917 
   8918 static UChar *
   8919 s390_insn_bfp_unop_emit(UChar *buf, const s390_insn *insn)
   8920 {
   8921    UInt  r1 = hregNumber(insn->variant.bfp_unop.dst_hi);
   8922    UInt  r2 = hregNumber(insn->variant.bfp_unop.op_hi);
   8923 
   8924    switch (insn->variant.bfp_unop.tag) {
   8925    case S390_BFP_ABS:
   8926       switch (insn->size) {
   8927       case 4:   return s390_emit_LPEBR(buf, r1, r2);
   8928       case 8:   return s390_emit_LPDBR(buf, r1, r2);
   8929       case 16:  return s390_emit_LPXBR(buf, r1, r2);
   8930       default:  goto fail;
   8931       }
   8932       break;
   8933 
   8934    case S390_BFP_NABS:
   8935       switch (insn->size) {
   8936       case 4:   return s390_emit_LNEBR(buf, r1, r2);
   8937       case 8:   return s390_emit_LNDBR(buf, r1, r2);
   8938       case 16:  return s390_emit_LNXBR(buf, r1, r2);
   8939       default:  goto fail;
   8940       }
   8941       break;
   8942 
   8943    case S390_BFP_NEG:
   8944       switch (insn->size) {
   8945       case 4:   return s390_emit_LCEBR(buf, r1, r2);
   8946       case 8:   return s390_emit_LCDBR(buf, r1, r2);
   8947       case 16:  return s390_emit_LCXBR(buf, r1, r2);
   8948       default:  goto fail;
   8949       }
   8950       break;
   8951 
   8952    case S390_BFP_SQRT:
   8953       switch (insn->size) {
   8954       case 4:   return s390_emit_SQEBR(buf, r1, r2);
   8955       case 8:   return s390_emit_SQDBR(buf, r1, r2);
   8956       case 16:  return s390_emit_SQXBR(buf, r1, r2);
   8957       default:  goto fail;
   8958       }
   8959       break;
   8960 
   8961    default: goto fail;
   8962    }
   8963 
   8964  fail:
   8965    vpanic("s390_insn_bfp_unop_emit");
   8966 }
   8967 
   8968 
   8969 static UChar *
   8970 s390_insn_bfp_convert_emit(UChar *buf, const s390_insn *insn)
   8971 {
   8972    UInt  r1 = hregNumber(insn->variant.bfp_convert.dst_hi);
   8973    UInt  r2 = hregNumber(insn->variant.bfp_convert.op_hi);
   8974    s390_bfp_round_t m3 = insn->variant.bfp_convert.rounding_mode;
   8975    /* The IEEE-inexact-exception control is not modelled. So the
   8976       m4 field is 0 (which is what GCC does, too) */
   8977    const UInt m4 = 0;
   8978 
   8979    switch (insn->variant.bfp_convert.tag) {
   8980       /* Convert to fixed */
   8981    case S390_BFP_F32_TO_I32:  return s390_emit_CFEBR(buf, m3, r1, r2);
   8982    case S390_BFP_F64_TO_I32:  return s390_emit_CFDBR(buf, m3, r1, r2);
   8983    case S390_BFP_F128_TO_I32: return s390_emit_CFXBR(buf, m3, r1, r2);
   8984    case S390_BFP_F32_TO_I64:  return s390_emit_CGEBR(buf, m3, r1, r2);
   8985    case S390_BFP_F64_TO_I64:  return s390_emit_CGDBR(buf, m3, r1, r2);
   8986    case S390_BFP_F128_TO_I64: return s390_emit_CGXBR(buf, m3, r1, r2);
   8987 
   8988       /* Convert to logical */
   8989    case S390_BFP_F32_TO_U32:  return s390_emit_CLFEBR(buf, m3, m4, r1, r2);
   8990    case S390_BFP_F64_TO_U32:  return s390_emit_CLFDBR(buf, m3, m4, r1, r2);
   8991    case S390_BFP_F128_TO_U32: return s390_emit_CLFXBR(buf, m3, m4, r1, r2);
   8992    case S390_BFP_F32_TO_U64:  return s390_emit_CLGEBR(buf, m3, m4, r1, r2);
   8993    case S390_BFP_F64_TO_U64:  return s390_emit_CLGDBR(buf, m3, m4, r1, r2);
   8994    case S390_BFP_F128_TO_U64: return s390_emit_CLGXBR(buf, m3, m4, r1, r2);
   8995 
   8996       /* Convert from fixed */
   8997    case S390_BFP_I32_TO_F32:  return s390_emit_CEFBRA(buf, m3, m4, r1, r2);
   8998    case S390_BFP_I32_TO_F64:  return s390_emit_CDFBRA(buf,  0, m4, r1, r2);
   8999    case S390_BFP_I32_TO_F128: return s390_emit_CXFBRA(buf,  0, m4, r1, r2);
   9000    case S390_BFP_I64_TO_F32:  return s390_emit_CEGBRA(buf, m3, m4, r1, r2);
   9001    case S390_BFP_I64_TO_F64:  return s390_emit_CDGBRA(buf, m3, m4, r1, r2);
   9002    case S390_BFP_I64_TO_F128: return s390_emit_CXGBRA(buf,  0, m4, r1, r2);
   9003 
   9004       /* Convert from logical */
   9005    case S390_BFP_U32_TO_F32:  return s390_emit_CELFBR(buf, m3, m4, r1, r2);
   9006    case S390_BFP_U32_TO_F64:  return s390_emit_CDLFBR(buf, m3, m4, r1, r2);
   9007    case S390_BFP_U32_TO_F128: return s390_emit_CXLFBR(buf, m3, m4, r1, r2);
   9008    case S390_BFP_U64_TO_F32:  return s390_emit_CELGBR(buf, m3, m4, r1, r2);
   9009    case S390_BFP_U64_TO_F64:  return s390_emit_CDLGBR(buf, m3, m4, r1, r2);
   9010    case S390_BFP_U64_TO_F128: return s390_emit_CXLGBR(buf, m3, m4, r1, r2);
   9011 
   9012       /* Load lengthened */
   9013    case S390_BFP_F32_TO_F64:  return s390_emit_LDEBR(buf, r1, r2);
   9014    case S390_BFP_F32_TO_F128: return s390_emit_LXEBR(buf, r1, r2);
   9015    case S390_BFP_F64_TO_F128: return s390_emit_LXDBR(buf, r1, r2);
   9016 
   9017       /* Load rounded */
   9018    case S390_BFP_F64_TO_F32:  return s390_emit_LEDBRA(buf, m3, m4, r1, r2);
   9019    case S390_BFP_F128_TO_F32: return s390_emit_LEXBRA(buf, m3, m4, r1, r2);
   9020    case S390_BFP_F128_TO_F64: return s390_emit_LDXBRA(buf, m3, m4, r1, r2);
   9021 
   9022       /* Load FP integer */
   9023    case S390_BFP_F32_TO_F32I: return s390_emit_FIEBRA(buf, m3, m4, r1, r2);
   9024    case S390_BFP_F64_TO_F64I: return s390_emit_FIDBRA(buf, m3, m4, r1, r2);
   9025    case S390_BFP_F128_TO_F128I: return s390_emit_FIXBRA(buf, m3, m4, r1, r2);
   9026 
   9027    default: goto fail;
   9028    }
   9029 
   9030  fail:
   9031    vpanic("s390_insn_bfp_convert_emit");
   9032 }
   9033 
   9034 
   9035 static UChar *
   9036 s390_insn_bfp_compare_emit(UChar *buf, const s390_insn *insn)
   9037 {
   9038    UInt dst = hregNumber(insn->variant.bfp_compare.dst);
   9039    UInt r1  = hregNumber(insn->variant.bfp_compare.op1_hi);
   9040    UInt r2  = hregNumber(insn->variant.bfp_compare.op2_hi);
   9041 
   9042    switch (insn->size) {
   9043    case 4:  buf = s390_emit_CEBR(buf, r1, r2); break;
   9044    case 8:  buf = s390_emit_CDBR(buf, r1, r2); break;
   9045    case 16: buf = s390_emit_CXBR(buf, r1, r2); break;
   9046    default:  goto fail;
   9047    }
   9048 
   9049    return s390_emit_load_cc(buf, dst);  /* Load condition code into DST */
   9050 
   9051  fail:
   9052    vpanic("s390_insn_bfp_compare_emit");
   9053 }
   9054 
   9055 
   9056 static UChar *
   9057 s390_insn_dfp_binop_emit(UChar *buf, const s390_insn *insn)
   9058 {
   9059    s390_dfp_binop *dfp_binop = insn->variant.dfp_binop.details;
   9060 
   9061    UInt r1 = hregNumber(dfp_binop->dst_hi);
   9062    UInt r2 = hregNumber(dfp_binop->op2_hi);
   9063    UInt r3 = hregNumber(dfp_binop->op3_hi);
   9064    s390_dfp_round_t m4 = dfp_binop->rounding_mode;
   9065 
   9066    switch (insn->size) {
   9067    case 8:
   9068       switch (dfp_binop->tag) {
   9069       case S390_DFP_ADD: return s390_emit_ADTRA(buf, r3, m4, r1, r2);
   9070       case S390_DFP_SUB: return s390_emit_SDTRA(buf, r3, m4, r1, r2);
   9071       case S390_DFP_MUL: return s390_emit_MDTRA(buf, r3, m4, r1, r2);
   9072       case S390_DFP_DIV: return s390_emit_DDTRA(buf, r3, m4, r1, r2);
   9073       case S390_DFP_QUANTIZE: return s390_emit_QADTR(buf, r3, m4, r1, r2);
   9074       default:  goto fail;
   9075       }
   9076       break;
   9077 
   9078    case 16:
   9079       switch (dfp_binop->tag) {
   9080       case S390_DFP_ADD:     return s390_emit_AXTRA(buf, r3, m4, r1, r2);
   9081       case S390_DFP_SUB:     return s390_emit_SXTRA(buf, r3, m4, r1, r2);
   9082       case S390_DFP_MUL:     return s390_emit_MXTRA(buf, r3, m4, r1, r2);
   9083       case S390_DFP_DIV:     return s390_emit_DXTRA(buf, r3, m4, r1, r2);
   9084       case S390_DFP_QUANTIZE: return s390_emit_QAXTR(buf, r3, m4, r1, r2);
   9085       default:  goto fail;
   9086       }
   9087       break;
   9088 
   9089    default:  goto fail;
   9090    }
   9091 
   9092  fail:
   9093    vpanic("s390_insn_dfp_binop_emit");
   9094 }
   9095 
   9096 
   9097 static UChar *
   9098 s390_insn_dfp_reround_emit(UChar *buf, const s390_insn *insn)
   9099 {
   9100    UInt r1 = hregNumber(insn->variant.dfp_reround.dst_hi);
   9101    UInt r2 = hregNumber(insn->variant.dfp_reround.op2);
   9102    UInt r3 = hregNumber(insn->variant.dfp_reround.op3_hi);
   9103    s390_dfp_round_t m4 = insn->variant.dfp_reround.rounding_mode;
   9104 
   9105    switch (insn->size) {
   9106    case 8:
   9107       return s390_emit_RRDTR(buf, r3, m4, r1, r2);
   9108 
   9109    case 16:
   9110       return s390_emit_RRXTR(buf, r3, m4, r1, r2);
   9111 
   9112    default: goto fail;
   9113    }
   9114  fail:
   9115    vpanic("s390_insn_dfp_reround_emit");
   9116 }
   9117 
   9118 
   9119 static UChar *
   9120 s390_insn_dfp_unop_emit(UChar *buf, const s390_insn *insn)
   9121 {
   9122    UInt  r1 = hregNumber(insn->variant.dfp_unop.dst_hi);
   9123    UInt  r2 = hregNumber(insn->variant.dfp_unop.op_hi);
   9124 
   9125    switch (insn->variant.dfp_unop.tag) {
   9126    case S390_DFP_EXTRACT_EXP_D64:  return s390_emit_EEDTR(buf, r1, r2); break;
   9127    case S390_DFP_EXTRACT_EXP_D128: return s390_emit_EEXTR(buf, r1, r2); break;
   9128    case S390_DFP_EXTRACT_SIG_D64:  return s390_emit_ESDTR(buf, r1, r2); break;
   9129    case S390_DFP_EXTRACT_SIG_D128: return s390_emit_ESXTR(buf, r1, r2); break;
   9130    default: goto fail;
   9131    }
   9132  fail:
   9133    vpanic("s390_insn_dfp_unop_emit");
   9134 }
   9135 
   9136 
   9137 static UChar *
   9138 s390_insn_dfp_intop_emit(UChar *buf, const s390_insn *insn)
   9139 {
   9140    UInt r1 = hregNumber(insn->variant.dfp_intop.dst_hi);
   9141    UInt r2 = hregNumber(insn->variant.dfp_intop.op2);
   9142    UInt r3 = hregNumber(insn->variant.dfp_intop.op3_hi);
   9143 
   9144    switch (insn->size) {
   9145    case 8:
   9146       switch (insn->variant.dfp_intop.tag) {
   9147       case S390_DFP_SHIFT_LEFT:  return s390_emit_SLDT(buf, r3, r1, r2);
   9148       case S390_DFP_SHIFT_RIGHT: return s390_emit_SRDT(buf, r3, r1, r2);
   9149       case S390_DFP_INSERT_EXP:  return s390_emit_IEDTR(buf, r3, r1, r2);
   9150       default:  goto fail;
   9151       }
   9152       break;
   9153 
   9154    case 16:
   9155       switch (insn->variant.dfp_intop.tag) {
   9156       case S390_DFP_SHIFT_LEFT:  return s390_emit_SLXT(buf, r3, r1, r2);
   9157       case S390_DFP_SHIFT_RIGHT: return s390_emit_SRXT(buf, r3, r1, r2);
   9158       case S390_DFP_INSERT_EXP:  return s390_emit_IEXTR(buf, r3, r1, r2);
   9159       default:  goto fail;
   9160       }
   9161       break;
   9162 
   9163    default: goto fail;
   9164    }
   9165 
   9166  fail:
   9167    vpanic("s390_insn_dfp_intop_emit");
   9168 }
   9169 
   9170 
   9171 static UChar *
   9172 s390_insn_dfp_compare_emit(UChar *buf, const s390_insn *insn)
   9173 {
   9174    UInt dst = hregNumber(insn->variant.dfp_compare.dst);
   9175    UInt r1  = hregNumber(insn->variant.dfp_compare.op1_hi);
   9176    UInt r2  = hregNumber(insn->variant.dfp_compare.op2_hi);
   9177 
   9178    switch (insn->size) {
   9179    case 8:
   9180       switch(insn->variant.dfp_compare.tag) {
   9181       case S390_DFP_COMPARE:     buf = s390_emit_CDTR(buf, r1, r2); break;
   9182       case S390_DFP_COMPARE_EXP: buf = s390_emit_CEDTR(buf, r1, r2); break;
   9183       default: goto fail;
   9184       }
   9185       break;
   9186 
   9187    case 16:
   9188       switch(insn->variant.dfp_compare.tag) {
   9189       case S390_DFP_COMPARE:     buf = s390_emit_CXTR(buf, r1, r2); break;
   9190       case S390_DFP_COMPARE_EXP: buf = s390_emit_CEXTR(buf, r1, r2); break;
   9191       default: goto fail;
   9192       }
   9193       break;
   9194 
   9195    default:  goto fail;
   9196    }
   9197 
   9198    return s390_emit_load_cc(buf, dst);  /* Load condition code into DST */
   9199 
   9200  fail:
   9201    vpanic("s390_insn_dfp_compare_emit");
   9202 }
   9203 
   9204 
   9205 static UChar *
   9206 s390_insn_dfp_convert_emit(UChar *buf, const s390_insn *insn)
   9207 {
   9208    UInt  r1 = hregNumber(insn->variant.dfp_convert.dst_hi);
   9209    UInt  r2 = hregNumber(insn->variant.dfp_convert.op_hi);
   9210    s390_dfp_round_t m3 = insn->variant.dfp_convert.rounding_mode;
   9211    /* The IEEE-inexact-exception control is not modelled. So the
   9212       m4 field is 0 (which is what GCC does, too) */
   9213    const UInt m4 = 0;
   9214 
   9215    switch (insn->variant.dfp_convert.tag) {
   9216 
   9217       /* Convert to fixed */
   9218    case S390_DFP_D64_TO_I32:  return s390_emit_CFDTR(buf, m3, m4, r1, r2);
   9219    case S390_DFP_D128_TO_I32: return s390_emit_CFXTR(buf, m3, m4, r1, r2);
   9220    case S390_DFP_D64_TO_I64:  return s390_emit_CGDTR(buf, m3, m4, r1, r2);
   9221    case S390_DFP_D128_TO_I64: return s390_emit_CGXTR(buf, m3, m4, r1, r2);
   9222 
   9223       /* Convert to logical */
   9224    case S390_DFP_D64_TO_U32:  return s390_emit_CLFDTR(buf, m3, m4, r1, r2);
   9225    case S390_DFP_D128_TO_U32: return s390_emit_CLFXTR(buf, m3, m4, r1, r2);
   9226    case S390_DFP_D64_TO_U64:  return s390_emit_CLGDTR(buf, m3, m4, r1, r2);
   9227    case S390_DFP_D128_TO_U64: return s390_emit_CLGXTR(buf, m3, m4, r1, r2);
   9228 
   9229       /* Convert from fixed */
   9230    case S390_DFP_I32_TO_D64:  return s390_emit_CDFTR(buf, 0, m4, r1, r2);
   9231    case S390_DFP_I32_TO_D128: return s390_emit_CXFTR(buf, 0, m4, r1, r2);
   9232    case S390_DFP_I64_TO_D64:  return s390_emit_CDGTRA(buf, m3, m4, r1, r2);
   9233    case S390_DFP_I64_TO_D128: return s390_emit_CXGTR(buf, 0, m4, r1, r2);
   9234 
   9235       /* Convert from logical */
   9236    case S390_DFP_U32_TO_D64:  return s390_emit_CDLFTR(buf, m3, m4, r1, r2);
   9237    case S390_DFP_U64_TO_D64:  return s390_emit_CDLGTR(buf, m3, m4, r1, r2);
   9238    case S390_DFP_U32_TO_D128: return s390_emit_CXLFTR(buf, m3, m4, r1, r2);
   9239    case S390_DFP_U64_TO_D128: return s390_emit_CXLGTR(buf, m3, m4, r1, r2);
   9240 
   9241       /* Load lengthened */
   9242    case S390_DFP_D32_TO_D64:   return s390_emit_LDETR(buf, m4, r1, r2);
   9243    case S390_DFP_D64_TO_D128:  return s390_emit_LXDTR(buf, m4, r1, r2);
   9244 
   9245       /* Load rounded */
   9246    case S390_DFP_D64_TO_D32:   return s390_emit_LEDTR(buf, m3, m4, r1, r2);
   9247    case S390_DFP_D128_TO_D64:  return s390_emit_LDXTR(buf, m3, m4, r1, r2);
   9248 
   9249    default: goto fail;
   9250    }
   9251 
   9252  fail:
   9253    vpanic("s390_insn_dfp_convert_emit");
   9254 }
   9255 
   9256 
   9257 static UChar *
   9258 s390_insn_fp_convert_emit(UChar *buf, const s390_insn *insn)
   9259 {
   9260    UInt pfpo;
   9261    s390_fp_convert *fp_convert = insn->variant.fp_convert.details;
   9262    s390_dfp_round_t rm = fp_convert->rounding_mode;
   9263 
   9264    vassert(rm < 2 || rm > 7);
   9265 
   9266    switch (fp_convert->tag) {
   9267    case S390_FP_F32_TO_D32:   pfpo = S390_PFPO_F32_TO_D32   << 8; break;
   9268    case S390_FP_F32_TO_D64:   pfpo = S390_PFPO_F32_TO_D64   << 8; break;
   9269    case S390_FP_F32_TO_D128:  pfpo = S390_PFPO_F32_TO_D128  << 8; break;
   9270    case S390_FP_F64_TO_D32:   pfpo = S390_PFPO_F64_TO_D32   << 8; break;
   9271    case S390_FP_F64_TO_D64:   pfpo = S390_PFPO_F64_TO_D64   << 8; break;
   9272    case S390_FP_F64_TO_D128:  pfpo = S390_PFPO_F64_TO_D128  << 8; break;
   9273    case S390_FP_F128_TO_D32:  pfpo = S390_PFPO_F128_TO_D32  << 8; break;
   9274    case S390_FP_F128_TO_D64:  pfpo = S390_PFPO_F128_TO_D64  << 8; break;
   9275    case S390_FP_F128_TO_D128: pfpo = S390_PFPO_F128_TO_D128 << 8; break;
   9276    case S390_FP_D32_TO_F32:   pfpo = S390_PFPO_D32_TO_F32   << 8; break;
   9277    case S390_FP_D32_TO_F64:   pfpo = S390_PFPO_D32_TO_F64   << 8; break;
   9278    case S390_FP_D32_TO_F128:  pfpo = S390_PFPO_D32_TO_F128  << 8; break;
   9279    case S390_FP_D64_TO_F32:   pfpo = S390_PFPO_D64_TO_F32   << 8; break;
   9280    case S390_FP_D64_TO_F64:   pfpo = S390_PFPO_D64_TO_F64   << 8; break;
   9281    case S390_FP_D64_TO_F128:  pfpo = S390_PFPO_D64_TO_F128  << 8; break;
   9282    case S390_FP_D128_TO_F32:  pfpo = S390_PFPO_D128_TO_F32  << 8; break;
   9283    case S390_FP_D128_TO_F64:  pfpo = S390_PFPO_D128_TO_F64  << 8; break;
   9284    case S390_FP_D128_TO_F128: pfpo = S390_PFPO_D128_TO_F128 << 8; break;
   9285    default: goto fail;
   9286    }
   9287 
   9288    pfpo = pfpo | rm;
   9289    buf = s390_emit_load_32imm(buf, R0, pfpo);
   9290    buf = s390_emit_PFPO(buf);
   9291    return buf;
   9292 
   9293  fail:
   9294    vpanic("s390_insn_fp_convert_emit");
   9295 }
   9296 
   9297 
   9298 static UChar *
   9299 s390_insn_mfence_emit(UChar *buf, const s390_insn *insn)
   9300 {
   9301    return s390_emit_BCR(buf, 0xF, 0x0);
   9302 }
   9303 
   9304 
   9305 static UChar *
   9306 s390_insn_mimm_emit(UChar *buf, const s390_insn *insn)
   9307 {
   9308    s390_amode *am = insn->variant.mimm.dst;
   9309    UChar b = hregNumber(am->b);
   9310    Int   d = am->d;
   9311    ULong value = insn->variant.mimm.value;
   9312 
   9313    if (value == 0) {
   9314       return s390_emit_XC(buf, insn->size - 1, b, d, b, d);
   9315    }
   9316 
   9317    if (insn->size == 1) {
   9318       return s390_emit_MVI(buf, value & 0xFF, b, d);
   9319    }
   9320 
   9321    if (s390_host_has_gie && ulong_fits_signed_16bit(value)) {
   9322       value &= 0xFFFF;
   9323       switch (insn->size) {
   9324       case 2: return s390_emit_MVHHI(buf, b, d, value);
   9325       case 4: return s390_emit_MVHI(buf,  b, d, value);
   9326       case 8: return s390_emit_MVGHI(buf, b, d, value);
   9327       }
   9328    } else {
   9329       // Load value to R0, then store.
   9330       switch (insn->size) {
   9331       case 2:
   9332          buf = s390_emit_LHI(buf, R0, value & 0xFFFF);
   9333          return s390_emit_STH(buf, R0, 0, b, d);
   9334       case 4:
   9335          buf = s390_emit_load_32imm(buf, R0, value);
   9336          return s390_emit_ST(buf, R0, 0, b, d);
   9337       case 8:
   9338          buf = s390_emit_load_64imm(buf, R0, value);
   9339          return s390_emit_STG(buf, R0, 0, b, DISP20(d));
   9340       }
   9341    }
   9342 
   9343    vpanic("s390_insn_mimm_emit");
   9344 }
   9345 
   9346 
   9347 static UChar *
   9348 s390_insn_madd_emit(UChar *buf, const s390_insn *insn)
   9349 {
   9350    s390_amode *am = insn->variant.madd.dst;
   9351    UChar b = hregNumber(am->b);
   9352    Int   d = am->d;
   9353 
   9354    if (insn->size == 4) {
   9355       return s390_emit_ASI(buf, insn->variant.madd.delta, b, DISP20(d));
   9356    }
   9357 
   9358    return s390_emit_AGSI(buf, insn->variant.madd.delta, b, DISP20(d));
   9359 }
   9360 
   9361 
   9362 static UChar *
   9363 s390_insn_set_fpc_bfprm_emit(UChar *buf, const s390_insn *insn)
   9364 {
   9365    UInt mode = hregNumber(insn->variant.set_fpc_bfprm.mode);
   9366 
   9367    /* Copy FPC from guest state to R0 and OR in the new rounding mode */
   9368    buf = s390_emit_L(buf, R0, 0, S390_REGNO_GUEST_STATE_POINTER,
   9369                      S390X_GUEST_OFFSET(guest_fpc));   // r0 = guest_fpc
   9370 
   9371    buf = s390_emit_NILL(buf, R0, 0xFFF8); /* Clear out right-most 3 bits */
   9372    buf = s390_emit_OR(buf, R0, mode);     /* OR in the new rounding mode */
   9373    buf = s390_emit_SFPC(buf, R0);         /* Load FPC register from R0 */
   9374 
   9375    return buf;
   9376 }
   9377 
   9378 
   9379 static UChar *
   9380 s390_insn_set_fpc_dfprm_emit(UChar *buf, const s390_insn *insn)
   9381 {
   9382    UInt mode = hregNumber(insn->variant.set_fpc_dfprm.mode);
   9383 
   9384    /* Copy FPC from guest state to R0 and OR in the new rounding mode */
   9385    buf = s390_emit_L(buf, R0, 0, S390_REGNO_GUEST_STATE_POINTER,
   9386                      S390X_GUEST_OFFSET(guest_fpc));   // r0 = guest_fpc
   9387 
   9388    /* DFP rounding mode is set at bit position 25:27 in FPC register */
   9389    buf = s390_emit_NILL(buf, R0, 0xFF8F); /* Clear out 25:27 bits */
   9390    buf = s390_emit_SLL(buf, mode, 0, 4);  /* bring mode to 25:27 bits */
   9391    buf = s390_emit_OR(buf, R0, mode);     /* OR in the new rounding mode */
   9392    buf = s390_emit_SFPC(buf, R0);         /* Load FPC register from R0 */
   9393 
   9394    return buf;
   9395 }
   9396 
   9397 
   9398 /* Define convenience functions needed for translation chaining.
   9399    Any changes need to be applied to the functions in concert. */
   9400 
   9401 static __inline__ Bool
   9402 s390_insn_is_BRCL(const UChar *p, UChar condition)
   9403 {
   9404    return p[0] == 0xc0 && p[1] == ((condition << 4) | 0x04);
   9405 }
   9406 
   9407 static __inline__ Bool
   9408 s390_insn_is_BR(const UChar *p, UChar reg)
   9409 {
   9410    return p[0] == 0x07 && p[1] == (0xF0 | reg);  /* BCR 15,reg */
   9411 }
   9412 
   9413 
   9414 /* The length of the BASR insn */
   9415 #define S390_BASR_LEN  2
   9416 
   9417 
   9418 /* Load the 64-bit VALUE into REG. Note that this function must NOT
   9419    optimise the generated code by looking at the value. I.e. using
   9420    LGHI if value == 0 would be very wrong. */
   9421 static UChar *
   9422 s390_tchain_load64(UChar *buf, UChar regno, ULong value)
   9423 {
   9424    UChar *begin = buf;
   9425 
   9426    if (s390_host_has_eimm) {
   9427       /* Do it in two steps: upper half [0:31] and lower half [32:63] */
   9428       buf = s390_emit_IIHF(buf, regno, value >> 32);
   9429       buf = s390_emit_IILF(buf, regno, value & 0xFFFFFFFF);
   9430    } else {
   9431       buf = s390_emit_IILL(buf, regno, value & 0xFFFF);
   9432       value >>= 16;
   9433       buf = s390_emit_IILH(buf, regno, value & 0xFFFF);
   9434       value >>= 16;
   9435       buf = s390_emit_IIHL(buf, regno, value & 0xFFFF);
   9436       value >>= 16;
   9437       buf = s390_emit_IIHH(buf, regno, value & 0xFFFF);
   9438    }
   9439 
   9440    vassert(buf - begin == s390_tchain_load64_len());
   9441 
   9442    return buf;
   9443 }
   9444 
   9445 /* Return number of bytes generated by s390_tchain_load64 */
   9446 static UInt
   9447 s390_tchain_load64_len(void)
   9448 {
   9449    if (s390_host_has_eimm) {
   9450       return 6 + 6;      /* IIHF + IILF */
   9451    }
   9452    return 4 + 4 + 4 + 4; /* IIHH + IIHL + IILH + IILL */
   9453 }
   9454 
   9455 /* Verify that CODE is the code sequence generated by s390_tchain_load64
   9456    to load VALUE into REGNO. Return pointer to the byte following the
   9457    insn sequence. */
   9458 static const UChar *
   9459 s390_tchain_verify_load64(const UChar *code, UChar regno, ULong value)
   9460 {
   9461    UInt regmask = regno << 4;
   9462    UInt hw;
   9463 
   9464    if (s390_host_has_eimm) {
   9465       /* Check for IIHF */
   9466       vassert(code[0]  ==  0xC0);
   9467       vassert(code[1]  == (0x08 | regmask));
   9468       vassert(*(const UInt *)&code[2] == (value >> 32));
   9469       /* Check for IILF */
   9470       vassert(code[6]  ==  0xC0);
   9471       vassert(code[7]  == (0x09 | regmask));
   9472       vassert(*(const UInt *)&code[8] == (value & 0xFFFFFFFF));
   9473    } else {
   9474       /* Check for IILL */
   9475       hw = value & 0xFFFF;
   9476       vassert(code[0]  ==  0xA5);
   9477       vassert(code[1]  == (0x03 | regmask));
   9478       vassert(code[2]  == (hw >> 8));
   9479       vassert(code[3]  == (hw & 0xFF));
   9480 
   9481       /* Check for IILH */
   9482       hw = (value >> 16) & 0xFFFF;
   9483       vassert(code[4]  ==  0xA5);
   9484       vassert(code[5]  == (0x02 | regmask));
   9485       vassert(code[6]  == (hw >> 8));
   9486       vassert(code[7]  == (hw & 0xFF));
   9487 
   9488       /* Check for IIHL */
   9489       hw = (value >> 32) & 0xFFFF;
   9490       vassert(code[8]  ==  0xA5);
   9491       vassert(code[9]  == (0x01 | regmask));
   9492       vassert(code[10] == (hw >> 8));
   9493       vassert(code[11] == (hw & 0xFF));
   9494 
   9495       /* Check for IIHH */
   9496       hw = (value >> 48) & 0xFFFF;
   9497       vassert(code[12] ==  0xA5);
   9498       vassert(code[13] == (0x00 | regmask));
   9499       vassert(code[14] == (hw >> 8));
   9500       vassert(code[15] == (hw & 0xFF));
   9501    }
   9502 
   9503    return code + s390_tchain_load64_len();
   9504 }
   9505 
   9506 /* CODE points to the code sequence as generated by s390_tchain_load64.
   9507    Change the loaded value to IMM64. Return pointer to the byte following
   9508    the patched code sequence. */
   9509 static UChar *
   9510 s390_tchain_patch_load64(UChar *code, ULong imm64)
   9511 {
   9512    if (s390_host_has_eimm) {
   9513       /* Patch IIHF */
   9514       *(UInt *)&code[2] = imm64 >> 32;
   9515       /* Patch IILF */
   9516       *(UInt *)&code[8] = imm64 & 0xFFFFFFFF;
   9517    } else {
   9518       code[3]  = imm64 & 0xFF; imm64 >>= 8;
   9519       code[2]  = imm64 & 0xFF; imm64 >>= 8;
   9520       code[7]  = imm64 & 0xFF; imm64 >>= 8;
   9521       code[6]  = imm64 & 0xFF; imm64 >>= 8;
   9522       code[11] = imm64 & 0xFF; imm64 >>= 8;
   9523       code[10] = imm64 & 0xFF; imm64 >>= 8;
   9524       code[15] = imm64 & 0xFF; imm64 >>= 8;
   9525       code[14] = imm64 & 0xFF; imm64 >>= 8;
   9526    }
   9527 
   9528    return code + s390_tchain_load64_len();
   9529 }
   9530 
   9531 
   9532 /* NB: what goes on here has to be very closely coordinated with the
   9533    chainXDirect_S390 and unchainXDirect_S390 below. */
   9534 static UChar *
   9535 s390_insn_xdirect_emit(UChar *buf, const s390_insn *insn,
   9536                        const void *disp_cp_chain_me_to_slowEP,
   9537                        const void *disp_cp_chain_me_to_fastEP)
   9538 {
   9539    /* We're generating chain-me requests here, so we need to be
   9540       sure this is actually allowed -- no-redir translations can't
   9541       use chain-me's.  Hence: */
   9542    vassert(disp_cp_chain_me_to_slowEP != NULL);
   9543    vassert(disp_cp_chain_me_to_fastEP != NULL);
   9544 
   9545    /* Use ptmp for backpatching conditional jumps. */
   9546    UChar *ptmp = buf;
   9547 
   9548    /* First off, if this is conditional, create a conditional
   9549       jump over the rest of it. */
   9550    s390_cc_t cond = insn->variant.xdirect.cond;
   9551 
   9552    if (cond != S390_CC_ALWAYS) {
   9553       /* So we have something like this
   9554          if (cond) do_xdirect;
   9555          Y: ...
   9556          We convert this into
   9557          if (! cond) goto Y;        // BRC opcode; 4 bytes
   9558          do_xdirect;
   9559          Y:
   9560       */
   9561       /* 4 bytes (a BRC insn) to be filled in here */
   9562       buf += 4;
   9563    }
   9564 
   9565    /* Update the guest IA. */
   9566    buf = s390_emit_load_64imm(buf, R0, insn->variant.xdirect.dst);
   9567 
   9568    const s390_amode *amode = insn->variant.xdirect.guest_IA;
   9569    vassert(amode->tag == S390_AMODE_B12);
   9570    UInt b = hregNumber(amode->b);
   9571    UInt d = amode->d;
   9572 
   9573    buf = s390_emit_STG(buf, R0, 0, b, DISP20(d));
   9574 
   9575    /* Load the chosen entry point into the scratch reg */
   9576    const void *disp_cp_chain_me;
   9577 
   9578    disp_cp_chain_me =
   9579       insn->variant.xdirect.to_fast_entry ? disp_cp_chain_me_to_fastEP
   9580                                           : disp_cp_chain_me_to_slowEP;
   9581    /* Get the address of the beginning of the load64 code sequence into %r1.
   9582       Do not change the register! This is part of the protocol with the
   9583       dispatcher. */
   9584    buf = s390_emit_BASR(buf, 1, R0);
   9585 
   9586    /* --- FIRST PATCHABLE BYTE follows (must not modify %r1) --- */
   9587    Addr64 addr = (Addr)disp_cp_chain_me;
   9588    buf = s390_tchain_load64(buf, S390_REGNO_TCHAIN_SCRATCH, addr);
   9589 
   9590    /* goto *tchain_scratch */
   9591    buf = s390_emit_BCR(buf, S390_CC_ALWAYS, S390_REGNO_TCHAIN_SCRATCH);
   9592 
   9593    /* --- END of PATCHABLE BYTES --- */
   9594 
   9595    /* Fix up the conditional jump, if there was one. */
   9596    if (cond != S390_CC_ALWAYS) {
   9597       Int delta = buf - ptmp;
   9598 
   9599       delta >>= 1;  /* immediate constant is #half-words */
   9600       vassert(delta > 0 && delta < (1 << 16));
   9601       s390_emit_BRC(ptmp, s390_cc_invert(cond), delta);
   9602    }
   9603 
   9604    return buf;
   9605 }
   9606 
   9607 /* Return the number of patchable bytes from an xdirect insn. */
   9608 static UInt
   9609 s390_xdirect_patchable_len(void)
   9610 {
   9611    return s390_tchain_load64_len() + S390_BASR_LEN;
   9612 }
   9613 
   9614 
   9615 static UChar *
   9616 s390_insn_xindir_emit(UChar *buf, const s390_insn *insn,
   9617                       const void *disp_cp_xindir)
   9618 {
   9619    /* We're generating transfers that could lead indirectly to a
   9620       chain-me, so we need to be sure this is actually allowed --
   9621       no-redir translations are not allowed to reach normal
   9622       translations without going through the scheduler.  That means
   9623       no XDirects or XIndirs out from no-redir translations.
   9624       Hence: */
   9625    vassert(disp_cp_xindir != NULL);
   9626 
   9627    /* Use ptmp for backpatching conditional jumps. */
   9628    UChar *ptmp = buf;
   9629 
   9630    /* First off, if this is conditional, create a conditional
   9631       jump over the rest of it. */
   9632    s390_cc_t cond = insn->variant.xdirect.cond;
   9633 
   9634    if (cond != S390_CC_ALWAYS) {
   9635       /* So we have something like this
   9636          if (cond) do_xdirect;
   9637          Y: ...
   9638          We convert this into
   9639          if (! cond) goto Y;        // BRC opcode; 4 bytes
   9640          do_xdirect;
   9641          Y:
   9642       */
   9643       /* 4 bytes (a BRC insn) to be filled in here */
   9644       buf += 4;
   9645    }
   9646 
   9647    /* Update the guest IA with the address in xdirect.dst. */
   9648    const s390_amode *amode = insn->variant.xindir.guest_IA;
   9649 
   9650    vassert(amode->tag == S390_AMODE_B12);
   9651    UInt b = hregNumber(amode->b);
   9652    UInt d = amode->d;
   9653    UInt regno = hregNumber(insn->variant.xindir.dst);
   9654 
   9655    buf = s390_emit_STG(buf, regno, 0, b, DISP20(d));
   9656 
   9657    /* load tchain_scratch, #disp_indir */
   9658    buf = s390_tchain_load64(buf, S390_REGNO_TCHAIN_SCRATCH,
   9659                             (Addr)disp_cp_xindir);
   9660    /* goto *tchain_direct */
   9661    buf = s390_emit_BCR(buf, S390_CC_ALWAYS, S390_REGNO_TCHAIN_SCRATCH);
   9662 
   9663    /* Fix up the conditional jump, if there was one. */
   9664    if (cond != S390_CC_ALWAYS) {
   9665       Int delta = buf - ptmp;
   9666 
   9667       delta >>= 1;  /* immediate constant is #half-words */
   9668       vassert(delta > 0 && delta < (1 << 16));
   9669       s390_emit_BRC(ptmp, s390_cc_invert(cond), delta);
   9670    }
   9671 
   9672    return buf;
   9673 }
   9674 
   9675 static UChar *
   9676 s390_insn_xassisted_emit(UChar *buf, const s390_insn *insn,
   9677                          const void *disp_cp_xassisted)
   9678 {
   9679    /* Use ptmp for backpatching conditional jumps. */
   9680    UChar *ptmp = buf;
   9681 
   9682    /* First off, if this is conditional, create a conditional
   9683       jump over the rest of it. */
   9684    s390_cc_t cond = insn->variant.xdirect.cond;
   9685 
   9686    if (cond != S390_CC_ALWAYS) {
   9687       /* So we have something like this
   9688          if (cond) do_xdirect;
   9689          Y: ...
   9690          We convert this into
   9691          if (! cond) goto Y;        // BRC opcode; 4 bytes
   9692          do_xdirect;
   9693          Y:
   9694       */
   9695       /* 4 bytes (a BRC insn) to be filled in here */
   9696       buf += 4;
   9697    }
   9698 
   9699    /* Update the guest IA with the address in xassisted.dst. */
   9700    const s390_amode *amode = insn->variant.xassisted.guest_IA;
   9701 
   9702    vassert(amode->tag == S390_AMODE_B12);
   9703    UInt b = hregNumber(amode->b);
   9704    UInt d = amode->d;
   9705    UInt regno = hregNumber(insn->variant.xassisted.dst);
   9706 
   9707    buf = s390_emit_STG(buf, regno, 0, b, DISP20(d));
   9708 
   9709    UInt trcval = 0;
   9710 
   9711    switch (insn->variant.xassisted.kind) {
   9712    case Ijk_ClientReq:   trcval = VEX_TRC_JMP_CLIENTREQ;   break;
   9713    case Ijk_Sys_syscall: trcval = VEX_TRC_JMP_SYS_SYSCALL; break;
   9714    case Ijk_Yield:       trcval = VEX_TRC_JMP_YIELD;       break;
   9715    case Ijk_EmWarn:      trcval = VEX_TRC_JMP_EMWARN;      break;
   9716    case Ijk_EmFail:      trcval = VEX_TRC_JMP_EMFAIL;      break;
   9717    case Ijk_MapFail:     trcval = VEX_TRC_JMP_MAPFAIL;     break;
   9718    case Ijk_NoDecode:    trcval = VEX_TRC_JMP_NODECODE;    break;
   9719    case Ijk_InvalICache: trcval = VEX_TRC_JMP_INVALICACHE; break;
   9720    case Ijk_NoRedir:     trcval = VEX_TRC_JMP_NOREDIR;     break;
   9721    case Ijk_SigTRAP:     trcval = VEX_TRC_JMP_SIGTRAP;     break;
   9722    case Ijk_SigSEGV:     trcval = VEX_TRC_JMP_SIGSEGV;     break;
   9723    case Ijk_Boring:      trcval = VEX_TRC_JMP_BORING;      break;
   9724       /* We don't expect to see the following being assisted. */
   9725    case Ijk_Ret:
   9726    case Ijk_Call:
   9727       /* fallthrough */
   9728    default:
   9729       ppIRJumpKind(insn->variant.xassisted.kind);
   9730       vpanic("s390_insn_xassisted_emit: unexpected jump kind");
   9731    }
   9732 
   9733    vassert(trcval != 0);
   9734 
   9735    /* guest_state_pointer = trcval */
   9736    buf = s390_emit_LGHI(buf, S390_REGNO_GUEST_STATE_POINTER, trcval);
   9737 
   9738    /* load tchain_scratch, #disp_assisted */
   9739    buf = s390_tchain_load64(buf, S390_REGNO_TCHAIN_SCRATCH,
   9740                             (Addr)disp_cp_xassisted);
   9741 
   9742    /* goto *tchain_direct */
   9743    buf = s390_emit_BCR(buf, S390_CC_ALWAYS, S390_REGNO_TCHAIN_SCRATCH);
   9744 
   9745    /* Fix up the conditional jump, if there was one. */
   9746    if (cond != S390_CC_ALWAYS) {
   9747       Int delta = buf - ptmp;
   9748 
   9749       delta >>= 1;  /* immediate constant is #half-words */
   9750       vassert(delta > 0 && delta < (1 << 16));
   9751       s390_emit_BRC(ptmp, s390_cc_invert(cond), delta);
   9752    }
   9753 
   9754    return buf;
   9755 }
   9756 
   9757 
   9758 /* Pseudo code:
   9759 
   9760    guest_state[host_EvC_COUNTER] -= 1;
   9761    if (guest_state[host_EvC_COUNTER] >= 0) goto nofail;
   9762    goto guest_state[host_EvC_FAILADDR];
   9763    nofail: ;
   9764 
   9765    The dispatch counter is a 32-bit value. */
   9766 static UChar *
   9767 s390_insn_evcheck_emit(UChar *buf, const s390_insn *insn,
   9768                        VexEndness endness_host)
   9769 {
   9770    s390_amode *amode;
   9771    UInt b, d;
   9772    UChar *code_begin, *code_end;
   9773 
   9774    code_begin = buf;
   9775 
   9776    amode = insn->variant.evcheck.counter;
   9777    vassert(amode->tag == S390_AMODE_B12);
   9778    b = hregNumber(amode->b);
   9779    d = amode->d;
   9780 
   9781    /* Decrement the dispatch counter in the guest state */
   9782    if (s390_host_has_gie) {
   9783       buf = s390_emit_ASI(buf, -1, b, DISP20(d));   /* 6 bytes */
   9784    } else {
   9785       buf = s390_emit_LHI(buf, R0, -1);             /* 4 bytes */
   9786       buf = s390_emit_A(buf, R0, 0, b, d);          /* 4 bytes */
   9787       buf = s390_emit_ST(buf, R0, 0, b, d);         /* 4 bytes */
   9788    }
   9789 
   9790    /* Jump over the next insn if >= 0 */
   9791    buf = s390_emit_BRC(buf, S390_CC_HE, (4 + 6 + 2) / 2);  /* 4 bytes */
   9792 
   9793    /* Computed goto to fail_address */
   9794    amode = insn->variant.evcheck.fail_addr;
   9795    b = hregNumber(amode->b);
   9796    d = amode->d;
   9797    buf = s390_emit_LG(buf, S390_REGNO_TCHAIN_SCRATCH, 0, b, DISP20(d));  /* 6 bytes */
   9798    buf = s390_emit_BCR(buf, S390_CC_ALWAYS, S390_REGNO_TCHAIN_SCRATCH);  /* 2 bytes */
   9799 
   9800    code_end = buf;
   9801 
   9802    /* Make sure the size of the generated code is identical to the size
   9803       returned by evCheckSzB_S390 */
   9804    vassert(evCheckSzB_S390() == code_end - code_begin);
   9805 
   9806    return buf;
   9807 }
   9808 
   9809 
   9810 static UChar *
   9811 s390_insn_profinc_emit(UChar *buf,
   9812                        const s390_insn *insn __attribute__((unused)))
   9813 {
   9814    /* Generate a code template to increment a memory location whose
   9815       address will be known later as an immediate value. This code
   9816       template will be patched once the memory location is known.
   9817       For now we do this with address == 0. */
   9818    buf = s390_tchain_load64(buf, S390_REGNO_TCHAIN_SCRATCH, 0);
   9819    if (s390_host_has_gie) {
   9820       buf = s390_emit_AGSI(buf, 1, S390_REGNO_TCHAIN_SCRATCH, DISP20(0));
   9821    } else {
   9822       buf = s390_emit_LGHI(buf, R0, 1);
   9823       buf = s390_emit_AG( buf, R0, 0, S390_REGNO_TCHAIN_SCRATCH, DISP20(0));
   9824       buf = s390_emit_STG(buf, R0, 0, S390_REGNO_TCHAIN_SCRATCH, DISP20(0));
   9825    }
   9826 
   9827    return buf;
   9828 }
   9829 
   9830 
   9831 Int
   9832 emit_S390Instr(Bool *is_profinc, UChar *buf, Int nbuf, const s390_insn *insn,
   9833                Bool mode64, VexEndness endness_host,
   9834                const void *disp_cp_chain_me_to_slowEP,
   9835                const void *disp_cp_chain_me_to_fastEP,
   9836                const void *disp_cp_xindir,
   9837                const void *disp_cp_xassisted)
   9838 {
   9839    UChar *end;
   9840 
   9841    /* Used to be 48 bytes. Make sure it stays low */
   9842    vassert(sizeof(s390_insn) == 32);
   9843 
   9844    switch (insn->tag) {
   9845    case S390_INSN_LOAD:
   9846       end = s390_insn_load_emit(buf, insn);
   9847       break;
   9848 
   9849    case S390_INSN_STORE:
   9850       end = s390_insn_store_emit(buf, insn);
   9851       break;
   9852 
   9853    case S390_INSN_MOVE:
   9854       end = s390_insn_move_emit(buf, insn);
   9855       break;
   9856 
   9857    case S390_INSN_MEMCPY:
   9858       end = s390_insn_memcpy_emit(buf, insn);
   9859       break;
   9860 
   9861    case S390_INSN_COND_MOVE:
   9862       end = s390_insn_cond_move_emit(buf, insn);
   9863       break;
   9864 
   9865    case S390_INSN_LOAD_IMMEDIATE:
   9866       end = s390_insn_load_immediate_emit(buf, insn);
   9867       break;
   9868 
   9869    case S390_INSN_ALU:
   9870       end = s390_insn_alu_emit(buf, insn);
   9871       break;
   9872 
   9873    case S390_INSN_SMUL:
   9874    case S390_INSN_UMUL:
   9875       end = s390_insn_mul_emit(buf, insn);
   9876       break;
   9877 
   9878    case S390_INSN_SDIV:
   9879    case S390_INSN_UDIV:
   9880       end = s390_insn_div_emit(buf, insn);
   9881       break;
   9882 
   9883    case S390_INSN_DIVS:
   9884       end = s390_insn_divs_emit(buf, insn);
   9885       break;
   9886 
   9887    case S390_INSN_CLZ:
   9888       end = s390_insn_clz_emit(buf, insn);
   9889       break;
   9890 
   9891    case S390_INSN_UNOP:
   9892       end = s390_insn_unop_emit(buf, insn);
   9893       break;
   9894 
   9895    case S390_INSN_TEST:
   9896       end = s390_insn_test_emit(buf, insn);
   9897       break;
   9898 
   9899    case S390_INSN_CC2BOOL:
   9900       end = s390_insn_cc2bool_emit(buf, insn);
   9901       break;
   9902 
   9903    case S390_INSN_CAS:
   9904       end = s390_insn_cas_emit(buf, insn);
   9905       break;
   9906 
   9907    case S390_INSN_CDAS:
   9908       end = s390_insn_cdas_emit(buf, insn);
   9909       break;
   9910 
   9911    case S390_INSN_COMPARE:
   9912       end = s390_insn_compare_emit(buf, insn);
   9913       break;
   9914 
   9915    case S390_INSN_HELPER_CALL:
   9916       end = s390_insn_helper_call_emit(buf, insn);
   9917       if (end == buf) goto fail;
   9918       break;
   9919 
   9920    case S390_INSN_BFP_TRIOP:
   9921       end = s390_insn_bfp_triop_emit(buf, insn);
   9922       break;
   9923 
   9924    case S390_INSN_BFP_BINOP:
   9925       end = s390_insn_bfp_binop_emit(buf, insn);
   9926       break;
   9927 
   9928    case S390_INSN_BFP_UNOP:
   9929       end = s390_insn_bfp_unop_emit(buf, insn);
   9930       break;
   9931 
   9932    case S390_INSN_BFP_COMPARE:
   9933       end = s390_insn_bfp_compare_emit(buf, insn);
   9934       break;
   9935 
   9936    case S390_INSN_BFP_CONVERT:
   9937       end = s390_insn_bfp_convert_emit(buf, insn);
   9938       break;
   9939 
   9940    case S390_INSN_DFP_BINOP:
   9941       end = s390_insn_dfp_binop_emit(buf, insn);
   9942       break;
   9943 
   9944    case S390_INSN_DFP_UNOP:
   9945       end = s390_insn_dfp_unop_emit(buf, insn);
   9946       break;
   9947 
   9948    case S390_INSN_DFP_INTOP:
   9949       end = s390_insn_dfp_intop_emit(buf, insn);
   9950       break;
   9951 
   9952    case S390_INSN_DFP_COMPARE:
   9953       end = s390_insn_dfp_compare_emit(buf, insn);
   9954       break;
   9955 
   9956    case S390_INSN_DFP_CONVERT:
   9957       end = s390_insn_dfp_convert_emit(buf, insn);
   9958       break;
   9959 
   9960    case S390_INSN_DFP_REROUND:
   9961       end = s390_insn_dfp_reround_emit(buf, insn);
   9962       break;
   9963 
   9964    case S390_INSN_FP_CONVERT:
   9965       end = s390_insn_fp_convert_emit(buf, insn);
   9966       break;
   9967 
   9968    case S390_INSN_MFENCE:
   9969       end = s390_insn_mfence_emit(buf, insn);
   9970       break;
   9971 
   9972    case S390_INSN_MIMM:
   9973       end = s390_insn_mimm_emit(buf, insn);
   9974       break;
   9975 
   9976    case S390_INSN_MADD:
   9977       end = s390_insn_madd_emit(buf, insn);
   9978       break;
   9979 
   9980    case S390_INSN_SET_FPC_BFPRM:
   9981       end = s390_insn_set_fpc_bfprm_emit(buf, insn);
   9982       break;
   9983 
   9984    case S390_INSN_SET_FPC_DFPRM:
   9985       end = s390_insn_set_fpc_dfprm_emit(buf, insn);
   9986       break;
   9987 
   9988    case S390_INSN_PROFINC:
   9989       end = s390_insn_profinc_emit(buf, insn);
   9990       /* Tell the caller .. */
   9991       vassert(*is_profinc == False);
   9992       *is_profinc = True;
   9993       break;
   9994 
   9995    case S390_INSN_EVCHECK:
   9996       end = s390_insn_evcheck_emit(buf, insn, endness_host);
   9997       break;
   9998 
   9999    case S390_INSN_XDIRECT:
   10000       end = s390_insn_xdirect_emit(buf, insn, disp_cp_chain_me_to_slowEP,
   10001                                    disp_cp_chain_me_to_fastEP);
   10002       break;
   10003 
   10004    case S390_INSN_XINDIR:
   10005       end = s390_insn_xindir_emit(buf, insn, disp_cp_xindir);
   10006       break;
   10007 
   10008    case S390_INSN_XASSISTED:
   10009       end = s390_insn_xassisted_emit(buf, insn, disp_cp_xassisted);
   10010       break;
   10011 
   10012    fail:
   10013    default:
   10014       vpanic("emit_S390Instr");
   10015    }
   10016 
   10017    vassert(end - buf <= nbuf);
   10018 
   10019    return end - buf;
   10020 }
   10021 
   10022 
   10023 /* Return the number of bytes emitted for an S390_INSN_EVCHECK.
   10024    See s390_insn_evcheck_emit */
   10025 Int
   10026 evCheckSzB_S390(void)
   10027 {
   10028    return s390_host_has_gie ? 18 : 24;
   10029 }
   10030 
   10031 
   10032 /* Patch the counter address into CODE_TO_PATCH as previously
   10033    generated by s390_insn_profinc_emit. */
   10034 VexInvalRange
   10035 patchProfInc_S390(VexEndness endness_host,
   10036                   void *code_to_patch, const ULong *location_of_counter)
   10037 {
   10038    vassert(sizeof(ULong *) == 8);
   10039 
   10040    s390_tchain_verify_load64(code_to_patch, S390_REGNO_TCHAIN_SCRATCH, 0);
   10041 
   10042    UChar *p = s390_tchain_patch_load64(code_to_patch,
   10043                                        (Addr)location_of_counter);
   10044 
   10045    UInt len = p - (UChar *)code_to_patch;
   10046    VexInvalRange vir = { (HWord)code_to_patch, len };
   10047    return vir;
   10048 }
   10049 
   10050 
   10051 /* NB: what goes on here has to be very closely coordinated with the
   10052    s390_insn_xdirect_emit code above. */
   10053 VexInvalRange
   10054 chainXDirect_S390(VexEndness endness_host,
   10055                   void *place_to_chain,
   10056                   const void *disp_cp_chain_me_EXPECTED,
   10057                   const void *place_to_jump_to)
   10058 {
   10059    vassert(endness_host == VexEndnessBE);
   10060 
   10061    /* What we're expecting to see @ PLACE_TO_CHAIN is:
   10062 
   10063         load  tchain_scratch, #disp_cp_chain_me_EXPECTED
   10064         goto *tchain_scratch
   10065    */
   10066    const UChar *next;
   10067    next = s390_tchain_verify_load64(place_to_chain, S390_REGNO_TCHAIN_SCRATCH,
   10068                                     (Addr)disp_cp_chain_me_EXPECTED);
   10069    vassert(s390_insn_is_BR(next, S390_REGNO_TCHAIN_SCRATCH));
   10070 
   10071    /* And what we want to change it to is either:
   10072         (general case):
   10073 
   10074           load  tchain_scratch, #place_to_jump_to
   10075           goto *tchain_scratch
   10076 
   10077       ---OR---
   10078 
   10079         in the case where the displacement is small enough
   10080 
   10081           BRCL delta       where delta is in half-words
   10082           invalid opcodes
   10083 
   10084       In both cases the replacement has the same length as the original.
   10085       To remain sane & verifiable,
   10086       (1) limit the displacement for the short form to
   10087           (say) +/- one billion, so as to avoid wraparound
   10088           off-by-ones
   10089       (2) even if the short form is applicable, once every (say)
   10090           1024 times use the long form anyway, so as to maintain
   10091           verifiability
   10092    */
   10093 
   10094    /* This is the delta we need to put into a BRCL insn. Note, that the
   10095       offset in BRCL is in half-words. Hence division by 2. */
   10096    Long delta =
   10097       (Long)((const UChar *)place_to_jump_to - (const UChar *)place_to_chain) / 2;
   10098    Bool shortOK = delta >= -1000*1000*1000 && delta < 1000*1000*1000;
   10099 
   10100    static UInt shortCTR = 0; /* DO NOT MAKE NON-STATIC */
   10101    if (shortOK) {
   10102       shortCTR++; // thread safety bleh
   10103       if (0 == (shortCTR & 0x3FF)) {
   10104          shortOK = False;
   10105          if (0)
   10106             vex_printf("QQQ chainXDirect_S390: shortCTR = %u, "
   10107                        "using long jmp\n", shortCTR);
   10108       }
   10109    }
   10110 
   10111    /* And make the modifications. */
   10112    UChar *p = (UChar *)place_to_chain;
   10113    if (shortOK) {
   10114       p = s390_emit_BRCL(p, S390_CC_ALWAYS, delta);  /* 6 bytes */
   10115 
   10116       /* Make sure that BRCL fits into the patchable part of an xdirect
   10117          code sequence */
   10118       vassert(6 <= s390_xdirect_patchable_len());
   10119 
   10120       /* Fill remaining bytes with 0x00 (invalid opcode) */
   10121       Int i;
   10122       for (i = 0; i < s390_xdirect_patchable_len() - 6; ++i)
   10123          p[i] = 0x00;
   10124    } else {
   10125       /*
   10126           load  tchain_scratch, #place_to_jump_to
   10127           goto *tchain_scratch
   10128       */
   10129       Addr64 addr = (Addr)place_to_jump_to;
   10130       p = s390_tchain_load64(p, S390_REGNO_TCHAIN_SCRATCH, addr);
   10131       /* There is not need to emit a BCR here, as it is already there. */
   10132    }
   10133 
   10134    UInt len = p - (UChar *)place_to_chain;
   10135    VexInvalRange vir = { (HWord)place_to_chain, len };
   10136    return vir;
   10137 }
   10138 
   10139 
   10140 /* NB: what goes on here has to be very closely coordinated with the
   10141    s390_insn_xdirect_emit code above. */
   10142 VexInvalRange
   10143 unchainXDirect_S390(VexEndness endness_host,
   10144                     void *place_to_unchain,
   10145                     const void *place_to_jump_to_EXPECTED,
   10146                     const void *disp_cp_chain_me)
   10147 {
   10148    vassert(endness_host == VexEndnessBE);
   10149 
   10150    /* What we're expecting to see @ PLACE_TO_UNCHAIN:
   10151 
   10152           load  tchain_scratch, #place_to_jump_to_EXPECTED
   10153           goto *tchain_scratch
   10154 
   10155       ---OR---
   10156         in the case where the displacement falls within 32 bits
   10157 
   10158           BRCL delta
   10159           invalid opcodes
   10160    */
   10161    UChar *p = place_to_unchain;
   10162 
   10163    Bool uses_short_form = False;
   10164 
   10165    if (s390_insn_is_BRCL(p, S390_CC_ALWAYS)) {
   10166       /* Looks like the short form */
   10167       Int num_hw = *(Int *)&p[2];
   10168       Int delta = 2 *num_hw;
   10169 
   10170       vassert(p + delta == place_to_jump_to_EXPECTED);
   10171 
   10172       Int i;
   10173       for (i = 0; i < s390_xdirect_patchable_len() - 6; ++i)
   10174          vassert(p[6+i] == 0x00);
   10175       uses_short_form = True;
   10176    } else {
   10177       /* Should be the long form */
   10178       const UChar *next;
   10179 
   10180       next = s390_tchain_verify_load64(p, S390_REGNO_TCHAIN_SCRATCH,
   10181                                        (Addr)place_to_jump_to_EXPECTED);
   10182       /* Check for BR *tchain_scratch */
   10183       vassert(s390_insn_is_BR(next, S390_REGNO_TCHAIN_SCRATCH));
   10184    }
   10185 
   10186    /* And what we want to change it to is:
   10187 
   10188         load  tchain_scratch, #disp_cp_chain_me
   10189         goto *tchain_scratch
   10190    */
   10191 
   10192    /* Get the address of the beginning of the load64 code sequence into %r1.
   10193       Do not change the register! This is part of the protocol with the
   10194       dispatcher.
   10195       Note: the incoming argument PLACE_TO_CHAIN points to the beginning of the
   10196       load64 insn sequence. That sequence is prefixed with a BASR to get its
   10197       address (see s390_insn_xdirect_emit).  */
   10198    p = s390_emit_BASR(p - S390_BASR_LEN, 1, R0);
   10199 
   10200    Addr64 addr = (Addr)disp_cp_chain_me;
   10201    p = s390_tchain_load64(p, S390_REGNO_TCHAIN_SCRATCH, addr);
   10202 
   10203    /* Emit the BCR in case the short form was used. In case of the long
   10204       form, the BCR is already there. */
   10205    if (uses_short_form)
   10206       s390_emit_BCR(p, S390_CC_ALWAYS, S390_REGNO_TCHAIN_SCRATCH);
   10207 
   10208    UInt len = p - (UChar *)place_to_unchain;
   10209    VexInvalRange vir = { (HWord)place_to_unchain, len };
   10210    return vir;
   10211 }
   10212 
   10213 /*---------------------------------------------------------------*/
   10214 /*--- end                                    host_s390_defs.c ---*/
   10215 /*---------------------------------------------------------------*/
   10216