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-2013
     12    Copyright (C) 2012-2013  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%d", r); break;
    112       case HRcFlt64: vex_sprintf(buf, "%%vF%d", 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_MEEBR(UChar *p, UChar r1, UChar r2)
   3943 {
   3944    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   3945       s390_disasm(ENC3(MNM, FPR, FPR), "meebr", r1, r2);
   3946 
   3947    return emit_RRE(p, 0xb3170000, r1, r2);
   3948 }
   3949 
   3950 
   3951 static UChar *
   3952 s390_emit_MDBR(UChar *p, UChar r1, UChar r2)
   3953 {
   3954    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   3955       s390_disasm(ENC3(MNM, FPR, FPR), "mdbr", r1, r2);
   3956 
   3957    return emit_RRE(p, 0xb31c0000, r1, r2);
   3958 }
   3959 
   3960 
   3961 static UChar *
   3962 s390_emit_MXBR(UChar *p, UChar r1, UChar r2)
   3963 {
   3964    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   3965       s390_disasm(ENC3(MNM, FPR, FPR), "mxbr", r1, r2);
   3966 
   3967    return emit_RRE(p, 0xb34c0000, r1, r2);
   3968 }
   3969 
   3970 
   3971 static UChar *
   3972 s390_emit_MAEBR(UChar *p, UChar r1, UChar r3, UChar r2)
   3973 {
   3974    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   3975       s390_disasm(ENC4(MNM, FPR, FPR, FPR), "maebr", r1, r3, r2);
   3976 
   3977    return emit_RRF(p, 0xb30e0000, r1, r3, r2);
   3978 }
   3979 
   3980 
   3981 static UChar *
   3982 s390_emit_MADBR(UChar *p, UChar r1, UChar r3, UChar r2)
   3983 {
   3984    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   3985       s390_disasm(ENC4(MNM, FPR, FPR, FPR), "madbr", r1, r3, r2);
   3986 
   3987    return emit_RRF(p, 0xb31e0000, r1, r3, r2);
   3988 }
   3989 
   3990 
   3991 static UChar *
   3992 s390_emit_MSEBR(UChar *p, UChar r1, UChar r3, UChar r2)
   3993 {
   3994    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   3995       s390_disasm(ENC4(MNM, FPR, FPR, FPR), "msebr", r1, r3, r2);
   3996 
   3997    return emit_RRF(p, 0xb30f0000, r1, r3, r2);
   3998 }
   3999 
   4000 
   4001 static UChar *
   4002 s390_emit_MSDBR(UChar *p, UChar r1, UChar r3, UChar r2)
   4003 {
   4004    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   4005       s390_disasm(ENC4(MNM, FPR, FPR, FPR), "msdbr", r1, r3, r2);
   4006 
   4007    return emit_RRF(p, 0xb31f0000, r1, r3, r2);
   4008 }
   4009 
   4010 
   4011 static UChar *
   4012 s390_emit_SQEBR(UChar *p, UChar r1, UChar r2)
   4013 {
   4014    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   4015       s390_disasm(ENC3(MNM, FPR, FPR), "sqebr", r1, r2);
   4016 
   4017    return emit_RRE(p, 0xb3140000, r1, r2);
   4018 }
   4019 
   4020 
   4021 static UChar *
   4022 s390_emit_SQDBR(UChar *p, UChar r1, UChar r2)
   4023 {
   4024    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   4025       s390_disasm(ENC3(MNM, FPR, FPR), "sqdbr", r1, r2);
   4026 
   4027    return emit_RRE(p, 0xb3150000, r1, r2);
   4028 }
   4029 
   4030 
   4031 static UChar *
   4032 s390_emit_SQXBR(UChar *p, UChar r1, UChar r2)
   4033 {
   4034    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   4035       s390_disasm(ENC3(MNM, FPR, FPR), "sqxbr", r1, r2);
   4036 
   4037    return emit_RRE(p, 0xb3160000, r1, r2);
   4038 }
   4039 
   4040 
   4041 static UChar *
   4042 s390_emit_SEBR(UChar *p, UChar r1, UChar r2)
   4043 {
   4044    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   4045       s390_disasm(ENC3(MNM, FPR, FPR), "sebr", r1, r2);
   4046 
   4047    return emit_RRE(p, 0xb30b0000, r1, r2);
   4048 }
   4049 
   4050 
   4051 static UChar *
   4052 s390_emit_SDBR(UChar *p, UChar r1, UChar r2)
   4053 {
   4054    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   4055       s390_disasm(ENC3(MNM, FPR, FPR), "sdbr", r1, r2);
   4056 
   4057    return emit_RRE(p, 0xb31b0000, r1, r2);
   4058 }
   4059 
   4060 
   4061 static UChar *
   4062 s390_emit_SXBR(UChar *p, UChar r1, UChar r2)
   4063 {
   4064    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   4065       s390_disasm(ENC3(MNM, FPR, FPR), "sxbr", r1, r2);
   4066 
   4067    return emit_RRE(p, 0xb34b0000, r1, r2);
   4068 }
   4069 
   4070 
   4071 static UChar *
   4072 s390_emit_ADTRA(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
   4073 {
   4074    vassert(s390_host_has_dfp);
   4075    vassert(m4 == 0 || s390_host_has_fpext);
   4076    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
   4077       if (m4 == 0)
   4078          s390_disasm(ENC4(MNM, FPR, FPR, FPR), "adtr", r1, r2, r3);
   4079       else
   4080          s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "adtra", r1, r2, r3, m4);
   4081    }
   4082 
   4083    return emit_RRF4(p, 0xb3d20000, r3, m4, r1, r2);
   4084 }
   4085 
   4086 
   4087 static UChar *
   4088 s390_emit_AXTRA(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
   4089 {
   4090    vassert(s390_host_has_dfp);
   4091    vassert(m4 == 0 || s390_host_has_fpext);
   4092    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
   4093       if (m4 == 0)
   4094          s390_disasm(ENC4(MNM, FPR, FPR, FPR), "axtr", r1, r2, r3);
   4095       else
   4096          s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "axtra", r1, r2, r3, m4);
   4097    }
   4098 
   4099    return emit_RRF4(p, 0xb3da0000, r3, m4, r1, r2);
   4100 }
   4101 
   4102 
   4103 static UChar *
   4104 s390_emit_CDTR(UChar *p, UChar r1, UChar r2)
   4105 {
   4106    vassert(s390_host_has_dfp);
   4107    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   4108       s390_disasm(ENC3(MNM, FPR, FPR), "cdtr", r1, r2);
   4109 
   4110    return emit_RRE(p, 0xb3e40000, r1, r2);
   4111 }
   4112 
   4113 
   4114 static UChar *
   4115 s390_emit_CXTR(UChar *p, UChar r1, UChar r2)
   4116 {
   4117    vassert(s390_host_has_dfp);
   4118    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   4119       s390_disasm(ENC3(MNM, FPR, FPR), "cxtr", r1, r2);
   4120 
   4121    return emit_RRE(p, 0xb3ec0000, r1, r2);
   4122 }
   4123 
   4124 
   4125 static UChar *
   4126 s390_emit_CDGTRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
   4127 {
   4128    vassert(s390_host_has_dfp);
   4129    vassert(m4 == 0);
   4130    vassert(m3 == 0 || s390_host_has_fpext);
   4131 
   4132    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
   4133       if (m3 == 0)
   4134          s390_disasm(ENC3(MNM, FPR, GPR), "cdgtr", r1, r2);
   4135       else
   4136          s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cdgtra", r1, m3, r2, m4);
   4137    }
   4138 
   4139    return emit_RRF2(p, 0xb3f10000, m3, m4, r1, r2);
   4140 }
   4141 
   4142 
   4143 static UChar *
   4144 s390_emit_CXGTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
   4145 {
   4146    vassert(s390_host_has_dfp);
   4147    vassert(m4 == 0);
   4148    /* rounding mode m3 is not considered, as the corresponding
   4149       IRop (Iop_I64StoD128) does not take rounding mode. */
   4150    vassert(m3 == 0);
   4151 
   4152    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   4153       s390_disasm(ENC3(MNM, FPR, GPR), "cxgtr", r1, r2);
   4154 
   4155    return emit_RRF2(p, 0xb3f90000, m3, m4, r1, r2);
   4156 }
   4157 
   4158 
   4159 static UChar *
   4160 s390_emit_CDFTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
   4161 {
   4162    vassert(m4 == 0);
   4163    vassert(s390_host_has_dfp);
   4164    vassert(s390_host_has_fpext);
   4165 
   4166    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   4167       s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cdftr", r1, m3, r2, m4);
   4168 
   4169    return emit_RRF2(p, 0xb9510000, m3, m4, r1, r2);
   4170 }
   4171 
   4172 
   4173 static UChar *
   4174 s390_emit_CXFTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
   4175 {
   4176    vassert(m4 == 0);
   4177    vassert(s390_host_has_dfp);
   4178    vassert(s390_host_has_fpext);
   4179 
   4180    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   4181       s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cxftr", r1, m3, r2, m4);
   4182 
   4183    return emit_RRF2(p, 0xb9590000, m3, m4, r1, r2);
   4184 }
   4185 
   4186 
   4187 static UChar *
   4188 s390_emit_CDLFTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
   4189 {
   4190    vassert(m4 == 0);
   4191    vassert(s390_host_has_dfp);
   4192    vassert(s390_host_has_fpext);
   4193 
   4194    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   4195       s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cdlftr", r1, m3, r2, m4);
   4196 
   4197    return emit_RRF2(p, 0xb9530000, m3, m4, r1, r2);
   4198 }
   4199 
   4200 
   4201 static UChar *
   4202 s390_emit_CXLFTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
   4203 {
   4204    vassert(m4 == 0);
   4205    vassert(s390_host_has_dfp);
   4206    vassert(s390_host_has_fpext);
   4207 
   4208    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   4209       s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cxlftr", r1, m3, r2, m4);
   4210 
   4211    return emit_RRF2(p, 0xb95b0000, m3, m4, r1, r2);
   4212 }
   4213 
   4214 
   4215 static UChar *
   4216 s390_emit_CDLGTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
   4217 {
   4218    vassert(m4 == 0);
   4219    vassert(s390_host_has_dfp);
   4220    vassert(s390_host_has_fpext);
   4221 
   4222    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   4223       s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cdlgtr", r1, m3, r2, m4);
   4224 
   4225    return emit_RRF2(p, 0xb9520000, m3, m4, r1, r2);
   4226 }
   4227 
   4228 
   4229 static UChar *
   4230 s390_emit_CXLGTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
   4231 {
   4232    vassert(m4 == 0);
   4233    vassert(s390_host_has_dfp);
   4234    vassert(s390_host_has_fpext);
   4235 
   4236    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   4237       s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cxlgtr", r1, m3, r2, m4);
   4238 
   4239    return emit_RRF2(p, 0xb95a0000, m3, m4, r1, r2);
   4240 }
   4241 
   4242 
   4243 static UChar *
   4244 s390_emit_CEDTR(UChar *p, UChar r1, UChar r2)
   4245 {
   4246    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   4247       s390_disasm(ENC3(MNM, FPR, FPR), "cedtr", r1, r2);
   4248 
   4249    return emit_RRE(p, 0xb3f40000, r1, r2);
   4250 }
   4251 
   4252 
   4253 static UChar *
   4254 s390_emit_CEXTR(UChar *p, UChar r1, UChar r2)
   4255 {
   4256    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   4257       s390_disasm(ENC3(MNM, FPR, FPR), "cextr", r1, r2);
   4258 
   4259    return emit_RRE(p, 0xb3fc0000, r1, r2);
   4260 }
   4261 
   4262 
   4263 static UChar *
   4264 s390_emit_CFDTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
   4265 {
   4266    vassert(m4 == 0);
   4267    vassert(s390_host_has_dfp);
   4268    vassert(s390_host_has_fpext);
   4269 
   4270    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   4271       s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "cfdtr", r1, m3, r2, m4);
   4272 
   4273    return emit_RRF2(p, 0xb9410000, m3, m4, r1, r2);
   4274 }
   4275 
   4276 
   4277 static UChar *
   4278 s390_emit_CFXTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
   4279 {
   4280    vassert(m4 == 0);
   4281    vassert(s390_host_has_dfp);
   4282    vassert(s390_host_has_fpext);
   4283 
   4284    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   4285       s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "cfxtr", r1, m3, r2, m4);
   4286 
   4287    return emit_RRF2(p, 0xb9490000, m3, m4, r1, r2);
   4288 }
   4289 
   4290 
   4291 static UChar *
   4292 s390_emit_CGDTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
   4293 {
   4294    vassert(s390_host_has_dfp);
   4295    vassert(m4 == 0);
   4296    vassert(s390_host_has_fpext || m3 < 1 || m3 > 7);
   4297 
   4298    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   4299       s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cgdtr", r1, m3, r2);
   4300 
   4301    return emit_RRF2(p, 0xb3e10000, m3, m4, r1, r2);
   4302 }
   4303 
   4304 
   4305 static UChar *
   4306 s390_emit_CGXTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
   4307 {
   4308    vassert(s390_host_has_dfp);
   4309    vassert(m4 == 0);
   4310    vassert(s390_host_has_fpext || m3 < 1 || m3 > 7);
   4311 
   4312    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   4313       s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cgxtr", r1, m3, r2);
   4314 
   4315    return emit_RRF2(p, 0xb3e90000, m3, m4, r1, r2);
   4316 }
   4317 
   4318 
   4319 static UChar *
   4320 s390_emit_CLFDTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
   4321 {
   4322    vassert(m4 == 0);
   4323    vassert(s390_host_has_dfp);
   4324    vassert(s390_host_has_fpext);
   4325 
   4326    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   4327       s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clfdtr", r1, m3, r2, m4);
   4328 
   4329    return emit_RRF2(p, 0xb9430000, m3, m4, r1, r2);
   4330 }
   4331 
   4332 
   4333 static UChar *
   4334 s390_emit_CLFXTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
   4335 {
   4336    vassert(m4 == 0);
   4337    vassert(s390_host_has_dfp);
   4338    vassert(s390_host_has_fpext);
   4339 
   4340    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   4341       s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clfxtr", r1, m3, r2, m4);
   4342 
   4343    return emit_RRF2(p, 0xb94b0000, m3, m4, r1, r2);
   4344 }
   4345 
   4346 
   4347 static UChar *
   4348 s390_emit_CLGDTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
   4349 {
   4350    vassert(m4 == 0);
   4351    vassert(s390_host_has_dfp);
   4352    vassert(s390_host_has_fpext);
   4353 
   4354    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   4355       s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clgdtr", r1, m3, r2, m4);
   4356 
   4357    return emit_RRF2(p, 0xb9420000, m3, m4, r1, r2);
   4358 }
   4359 
   4360 
   4361 static UChar *
   4362 s390_emit_CLGXTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
   4363 {
   4364    vassert(m4 == 0);
   4365    vassert(s390_host_has_dfp);
   4366    vassert(s390_host_has_fpext);
   4367 
   4368    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   4369       s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clgxtr", r1, m3, r2, m4);
   4370 
   4371    return emit_RRF2(p, 0xb94a0000, m3, m4, r1, r2);
   4372 }
   4373 
   4374 
   4375 static UChar *
   4376 s390_emit_DDTRA(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
   4377 {
   4378    vassert(s390_host_has_dfp);
   4379    vassert(m4 == 0 || s390_host_has_fpext);
   4380    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
   4381       if (m4 == 0)
   4382          s390_disasm(ENC4(MNM, FPR, FPR, FPR), "ddtr", r1, r2, r3);
   4383       else
   4384          s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "ddtra", r1, r2, r3, m4);
   4385    }
   4386 
   4387    return emit_RRF4(p, 0xb3d10000, r3, m4, r1, r2);
   4388 }
   4389 
   4390 
   4391 static UChar *
   4392 s390_emit_DXTRA(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
   4393 {
   4394    vassert(s390_host_has_dfp);
   4395    vassert(m4 == 0 || s390_host_has_fpext);
   4396    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
   4397       if (m4 == 0)
   4398          s390_disasm(ENC4(MNM, FPR, FPR, FPR), "dxtr", r1, r2, r3);
   4399       else
   4400          s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "dxtra", r1, r2, r3, m4);
   4401    }
   4402 
   4403    return emit_RRF4(p, 0xb3d90000, r3, m4, r1, r2);
   4404 }
   4405 
   4406 
   4407 static UChar *
   4408 s390_emit_EEDTR(UChar *p, UChar r1, UChar r2)
   4409 {
   4410    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   4411       s390_disasm(ENC3(MNM, GPR, FPR), "eedtr", r1, r2);
   4412 
   4413    return emit_RRE(p, 0xb3e50000, r1, r2);
   4414 }
   4415 
   4416 
   4417 static UChar *
   4418 s390_emit_EEXTR(UChar *p, UChar r1, UChar r2)
   4419 {
   4420    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   4421       s390_disasm(ENC3(MNM, GPR, FPR), "eextr", r1, r2);
   4422 
   4423    return emit_RRE(p, 0xb3ed0000, r1, r2);
   4424 }
   4425 
   4426 
   4427 static UChar *
   4428 s390_emit_ESDTR(UChar *p, UChar r1, UChar r2)
   4429 {
   4430    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   4431       s390_disasm(ENC3(MNM, GPR, FPR), "esdtr", r1, r2);
   4432 
   4433    return emit_RRE(p, 0xb3e70000, r1, r2);
   4434 }
   4435 
   4436 
   4437 static UChar *
   4438 s390_emit_ESXTR(UChar *p, UChar r1, UChar r2)
   4439 {
   4440    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   4441       s390_disasm(ENC3(MNM, GPR, FPR), "esxtr", r1, r2);
   4442 
   4443    return emit_RRE(p, 0xb3ef0000, r1, r2);
   4444 }
   4445 
   4446 
   4447 static UChar *
   4448 s390_emit_IEDTR(UChar *p, UChar r3, UChar r1, UChar r2)
   4449 {
   4450    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   4451       s390_disasm(ENC4(MNM, FPR, FPR, GPR), "iedtr", r1, r3, r2);
   4452 
   4453    return emit_RRF(p, 0xb3f60000, r3, r1, r2);
   4454 }
   4455 
   4456 
   4457 static UChar *
   4458 s390_emit_IEXTR(UChar *p, UChar r3, UChar r1, UChar r2)
   4459 {
   4460    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   4461       s390_disasm(ENC4(MNM, FPR, FPR, GPR), "iextr", r1, r3, r2);
   4462 
   4463    return emit_RRF(p, 0xb3fe0000, r3, r1, r2);
   4464 }
   4465 
   4466 
   4467 static UChar *
   4468 s390_emit_LDETR(UChar *p, UChar m4, UChar r1, UChar r2)
   4469 {
   4470    vassert(s390_host_has_dfp);
   4471    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   4472       s390_disasm(ENC4(MNM, FPR, FPR, UINT), "ldetr", r1, r2, m4);
   4473 
   4474    return emit_RRF5(p, 0xb3d40000, m4, r1, r2);
   4475 }
   4476 
   4477 
   4478 static UChar *
   4479 s390_emit_LXDTR(UChar *p, UChar m4, UChar r1, UChar r2)
   4480 {
   4481    vassert(s390_host_has_dfp);
   4482    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   4483       s390_disasm(ENC4(MNM, FPR, FPR, UINT), "lxdtr", r1, r2, m4);
   4484 
   4485    return emit_RRF5(p, 0xb3dc0000, m4, r1, r2);
   4486 }
   4487 
   4488 
   4489 static UChar *
   4490 s390_emit_LEDTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
   4491 {
   4492    vassert(s390_host_has_dfp);
   4493    vassert(m4 == 0);
   4494    vassert(s390_host_has_fpext || m3 < 1 || m3 > 7);
   4495 
   4496    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   4497       s390_disasm(ENC5(MNM, FPR, UINT, FPR, UINT), "ledtr", r1, m3, r2, m4);
   4498 
   4499    return emit_RRF2(p, 0xb3d50000, m3, m4, r1, r2);
   4500 }
   4501 
   4502 
   4503 static UChar *
   4504 s390_emit_LDXTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
   4505 {
   4506    vassert(s390_host_has_dfp);
   4507    vassert(m4 == 0);
   4508    vassert(s390_host_has_fpext || m3 < 1 || m3 > 7);
   4509 
   4510    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   4511       s390_disasm(ENC5(MNM, FPR, UINT, FPR, UINT), "ldxtr", r1, m3, r2, m4);
   4512 
   4513    return emit_RRF2(p, 0xb3dd0000, m3, m4, r1, r2);
   4514 }
   4515 
   4516 
   4517 static UChar *
   4518 s390_emit_MDTRA(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
   4519 {
   4520    vassert(s390_host_has_dfp);
   4521    vassert(m4 == 0 || s390_host_has_fpext);
   4522    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
   4523       if (m4 == 0)
   4524          s390_disasm(ENC4(MNM, FPR, FPR, FPR), "mdtr", r1, r2, r3);
   4525       else
   4526          s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "mdtra", r1, r2, r3, m4);
   4527    }
   4528 
   4529    return emit_RRF4(p, 0xb3d00000, r3, m4, r1, r2);
   4530 }
   4531 
   4532 
   4533 static UChar *
   4534 s390_emit_MXTRA(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
   4535 {
   4536    vassert(s390_host_has_dfp);
   4537    vassert(m4 == 0 || s390_host_has_fpext);
   4538    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
   4539       if (m4 == 0)
   4540          s390_disasm(ENC4(MNM, FPR, FPR, FPR), "mxtr", r1, r2, r3);
   4541       else
   4542          s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "mxtra", r1, r2, r3, m4);
   4543    }
   4544 
   4545    return emit_RRF4(p, 0xb3d80000, r3, m4, r1, r2);
   4546 }
   4547 
   4548 
   4549 static UChar *
   4550 emit_E(UChar *p, UInt op)
   4551 {
   4552    ULong the_insn = op;
   4553 
   4554    return emit_2bytes(p, the_insn);
   4555 }
   4556 
   4557 
   4558 static UChar *
   4559 s390_emit_PFPO(UChar *p)
   4560 {
   4561    vassert(s390_host_has_pfpo);
   4562    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
   4563       s390_disasm(ENC1(MNM), "pfpo");
   4564    }
   4565 
   4566    return emit_E(p, 0x010a);
   4567 }
   4568 
   4569 
   4570 static UChar *
   4571 s390_emit_QADTR(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
   4572 {
   4573    vassert(s390_host_has_dfp);
   4574    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   4575       s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "qadtr", r1, r3, r2, m4);
   4576 
   4577    return emit_RRF4(p, 0xb3f50000, r3, m4, r1, r2);
   4578 }
   4579 
   4580 
   4581 static UChar *
   4582 s390_emit_QAXTR(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
   4583 {
   4584    vassert(s390_host_has_dfp);
   4585    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   4586       s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "qaxtr", r1, r3, r2, m4);
   4587 
   4588    return emit_RRF4(p, 0xb3fd0000, r3, m4, r1, r2);
   4589 }
   4590 
   4591 
   4592 static UChar *
   4593 s390_emit_RRDTR(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
   4594 {
   4595    vassert(s390_host_has_dfp);
   4596    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   4597       s390_disasm(ENC5(MNM, FPR, FPR, GPR, UINT), "rrdtr", r1, r3, r2, m4);
   4598 
   4599    return emit_RRF4(p, 0xb3f70000, r3, m4, r1, r2);
   4600 }
   4601 
   4602 
   4603 static UChar *
   4604 s390_emit_RRXTR(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
   4605 {
   4606    vassert(s390_host_has_dfp);
   4607    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   4608       s390_disasm(ENC5(MNM, FPR, FPR, GPR, UINT), "rrxtr", r1, r3, r2, m4);
   4609 
   4610    return emit_RRF4(p, 0xb3ff0000, r3, m4, r1, r2);
   4611 }
   4612 
   4613 
   4614 static UChar *
   4615 s390_emit_SDTRA(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
   4616 {
   4617    vassert(s390_host_has_dfp);
   4618    vassert(m4 == 0 || s390_host_has_fpext);
   4619    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
   4620       if (m4 == 0)
   4621          s390_disasm(ENC4(MNM, FPR, FPR, FPR), "sdtr", r1, r2, r3);
   4622       else
   4623          s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "sdtra", r1, r2, r3, m4);
   4624    }
   4625 
   4626    return emit_RRF4(p, 0xb3d30000, r3, m4, r1, r2);
   4627 }
   4628 
   4629 
   4630 static UChar *
   4631 s390_emit_SXTRA(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
   4632 {
   4633    vassert(s390_host_has_dfp);
   4634    vassert(m4 == 0 || s390_host_has_fpext);
   4635    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
   4636       if (m4 == 0)
   4637          s390_disasm(ENC4(MNM, FPR, FPR, FPR), "sxtr", r1, r2, r3);
   4638       else
   4639          s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "sxtra", r1, r2, r3, m4);
   4640    }
   4641 
   4642    return emit_RRF4(p, 0xb3db0000, r3, m4, r1, r2);
   4643 }
   4644 
   4645 
   4646 static UChar *
   4647 s390_emit_SLDT(UChar *p, UChar r3, UChar r1, UChar r2)
   4648 {
   4649    vassert(s390_host_has_dfp);
   4650    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   4651       s390_disasm(ENC4(MNM, FPR, FPR, UDXB), "sldt", r1, r3, 0, 0, r2);
   4652 
   4653    return emit_RXF(p, 0xED0000000040ULL, r3, 0, r2, 0, r1);
   4654 }
   4655 
   4656 
   4657 static UChar *
   4658 s390_emit_SLXT(UChar *p, UChar r3, UChar r1, UChar r2)
   4659 {
   4660    vassert(s390_host_has_dfp);
   4661    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   4662       s390_disasm(ENC4(MNM, FPR, FPR, UDXB), "slxt", r1, r3, 0, 0, r2);
   4663 
   4664    return emit_RXF(p, 0xED0000000048ULL, r3, 0, r2, 0, r1);
   4665 }
   4666 
   4667 
   4668 static UChar *
   4669 s390_emit_SRDT(UChar *p, UChar r3, UChar r1, UChar r2)
   4670 {
   4671    vassert(s390_host_has_dfp);
   4672    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   4673       s390_disasm(ENC4(MNM, FPR, FPR, UDXB), "srdt", r1, r3, 0, 0, r2);
   4674 
   4675    return emit_RXF(p, 0xED0000000041ULL, r3, 0, r2, 0, r1);
   4676 }
   4677 
   4678 
   4679 static UChar *
   4680 s390_emit_SRXT(UChar *p, UChar r3, UChar r1, UChar r2)
   4681 {
   4682    vassert(s390_host_has_dfp);
   4683    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   4684       s390_disasm(ENC4(MNM, FPR, FPR, UDXB), "srxt", r1, r3, 0, 0, r2);
   4685 
   4686    return emit_RXF(p, 0xED0000000049ULL, r3, 0, r2, 0, r1);
   4687 }
   4688 
   4689 
   4690 static UChar *
   4691 s390_emit_LOCGR(UChar *p, UChar m3, UChar r1, UChar r2)
   4692 {
   4693    vassert(s390_host_has_lsc);
   4694    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   4695       s390_disasm(ENC4(MNM, GPR, GPR, UINT), "locgr", r1, r2, m3);
   4696 
   4697    return emit_RRF3(p, 0xb9e20000, m3, r1, r2);
   4698 }
   4699 
   4700 
   4701 static UChar *
   4702 s390_emit_LOC(UChar *p, UChar r1, UChar m3, UChar b2, UShort dl2, UChar dh2)
   4703 {
   4704    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   4705       s390_disasm(ENC4(MNM, GPR, UINT, SDXB), "loc", r1, m3, dh2, dl2, 0, b2);
   4706 
   4707    return emit_RSY(p, 0xeb00000000f2ULL, r1, m3, b2, dl2, dh2);
   4708 }
   4709 
   4710 
   4711 static UChar *
   4712 s390_emit_LOCG(UChar *p, UChar r1, UChar m3, UChar b2, UShort dl2, UChar dh2)
   4713 {
   4714    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
   4715       s390_disasm(ENC4(MNM, GPR, UINT, SDXB), "locg", r1, m3, dh2, dl2, 0, b2);
   4716 
   4717    return emit_RSY(p, 0xeb00000000e2ULL, r1, m3, b2, dl2, dh2);
   4718 }
   4719 
   4720 
   4721 /* Provide a symbolic name for register "R0" */
   4722 #define R0 0
   4723 
   4724 /* Split up a 20-bit displacement into its high and low piece
   4725    suitable for passing as function arguments */
   4726 #define DISP20(d) (((UInt)d) & 0xFFF), ((((UInt)d) >> 12) & 0xFF)
   4727 
   4728 /*---------------------------------------------------------------*/
   4729 /*--- Helper functions                                        ---*/
   4730 /*---------------------------------------------------------------*/
   4731 
   4732 static __inline__ Bool
   4733 uint_fits_signed_16bit(UInt val)
   4734 {
   4735    UInt v = val & 0xFFFFu;
   4736 
   4737    /* sign extend */
   4738    v = (Int)(v << 16) >> 16;
   4739 
   4740    return val == v;
   4741 }
   4742 
   4743 
   4744 static __inline__ Bool
   4745 ulong_fits_signed_16bit(ULong val)
   4746 {
   4747    ULong v = val & 0xFFFFu;
   4748 
   4749    /* sign extend */
   4750    v = (Long)(v << 48) >> 48;
   4751 
   4752    return val == v;
   4753 }
   4754 
   4755 
   4756 static __inline__ Bool
   4757 ulong_fits_signed_32bit(ULong val)
   4758 {
   4759    ULong v = val & 0xFFFFFFFFu;
   4760 
   4761    /* sign extend */
   4762    v = (Long)(v << 32) >> 32;
   4763 
   4764    return val == v;
   4765 }
   4766 
   4767 
   4768 static __inline__ Bool
   4769 ulong_fits_unsigned_32bit(ULong val)
   4770 {
   4771    return (val & 0xFFFFFFFFu) == val;
   4772 }
   4773 
   4774 
   4775 /* Load a 64-bit immediate VAL into register REG. */
   4776 static UChar *
   4777 s390_emit_load_64imm(UChar *p, UChar reg, ULong val)
   4778 {
   4779    if (ulong_fits_signed_16bit(val)) {
   4780       return s390_emit_LGHI(p, reg, val);
   4781    }
   4782 
   4783    if (s390_host_has_eimm) {
   4784       if (ulong_fits_unsigned_32bit(val)) {
   4785          return s390_emit_LLILF(p, reg, val);
   4786       }
   4787       if (ulong_fits_signed_32bit(val)) {
   4788          /* LGFI's sign extension will recreate the correct 64-bit value */
   4789          return s390_emit_LGFI(p, reg, val);
   4790       }
   4791       /* Do it in two steps: upper half [0:31] and lower half [32:63] */
   4792       p =  s390_emit_IIHF(p, reg, val >> 32);
   4793       return s390_emit_IILF(p, reg, val & 0xFFFFFFFF);
   4794    }
   4795 
   4796    /* Fall back */
   4797    if (ulong_fits_unsigned_32bit(val)) {
   4798       p = s390_emit_LLILH(p, reg, (val >> 16) & 0xFFFF); /* sets val[32:47]
   4799                                                             val[0:31] = 0 */
   4800       p = s390_emit_IILL(p, reg, val & 0xFFFF);          /* sets val[48:63] */
   4801       return p;
   4802    }
   4803 
   4804    p = s390_emit_IIHH(p, reg, (val >> 48) & 0xFFFF);
   4805    p = s390_emit_IIHL(p, reg, (val >> 32) & 0xFFFF);
   4806    p = s390_emit_IILH(p, reg, (val >> 16) & 0xFFFF);
   4807    p = s390_emit_IILL(p, reg, val & 0xFFFF);
   4808 
   4809    return p;
   4810 }
   4811 
   4812 /* Load a 32-bit immediate VAL into register REG. */
   4813 static UChar *
   4814 s390_emit_load_32imm(UChar *p, UChar reg, UInt val)
   4815 {
   4816    if (uint_fits_signed_16bit(val)) {
   4817       /* LHI's sign extension will recreate the correct 32-bit value */
   4818       return s390_emit_LHI(p, reg, val);
   4819    }
   4820    if (s390_host_has_eimm) {
   4821       return s390_emit_IILF(p, reg, val);
   4822    }
   4823    /* val[0:15]  --> (val >> 16) & 0xFFFF
   4824       val[16:31] --> val & 0xFFFF */
   4825    p = s390_emit_IILH(p, reg, (val >> 16) & 0xFFFF);
   4826    return s390_emit_IILL(p, reg, val & 0xFFFF);
   4827 }
   4828 
   4829 /*------------------------------------------------------------*/
   4830 /*--- Wrapper functions                                    ---*/
   4831 /*------------------------------------------------------------*/
   4832 
   4833 /* r1[32:63],r1+1[32:63] = r1+1[32:63] * memory[op2addr][0:31] */
   4834 static UChar *
   4835 s390_emit_MFYw(UChar *p, UChar r1, UChar x, UChar b,  UShort dl, UChar dh)
   4836 {
   4837    if (s390_host_has_gie) {
   4838       return s390_emit_MFY(p, r1, x, b, dl, dh);
   4839    }
   4840 
   4841    /* Load from memory into R0, then MULTIPLY with R1 */
   4842    p = s390_emit_LY(p, R0, x, b, dl, dh);
   4843    return s390_emit_MR(p, r1, R0);
   4844 }
   4845 
   4846 /* r1[32:63] = r1[32:63] * memory[op2addr][0:15] */
   4847 static UChar *
   4848 s390_emit_MHYw(UChar *p, UChar r1, UChar x, UChar b,  UShort dl, UChar dh)
   4849 {
   4850    if (s390_host_has_gie) {
   4851       return s390_emit_MHY(p, r1, x, b, dl, dh);
   4852    }
   4853 
   4854    /* Load from memory into R0, then MULTIPLY with R1 */
   4855    p = s390_emit_LHY(p, R0, x, b, dl, dh);
   4856    return s390_emit_MSR(p, r1, R0);
   4857 }
   4858 
   4859 /* r1[32:63] = r1[32:63] * i2 */
   4860 static UChar *
   4861 s390_emit_MSFIw(UChar *p, UChar r1, UInt i2)
   4862 {
   4863    if (s390_host_has_gie) {
   4864       return s390_emit_MSFI(p, r1, i2);
   4865    }
   4866 
   4867    /* Load I2 into R0; then MULTIPLY R0 with R1 */
   4868    p = s390_emit_load_32imm(p, R0, i2);
   4869    return s390_emit_MSR(p, r1, R0);
   4870 }
   4871 
   4872 
   4873 /* r1[32:63] = r1[32:63] & i2 */
   4874 static UChar *
   4875 s390_emit_NILFw(UChar *p, UChar r1, UInt i2)
   4876 {
   4877    if (s390_host_has_eimm) {
   4878       return s390_emit_NILF(p, r1, i2);
   4879    }
   4880 
   4881    /* Load I2 into R0; then AND R0 with R1 */
   4882    p = s390_emit_load_32imm(p, R0, i2);
   4883    return s390_emit_NR(p, r1, R0);
   4884 }
   4885 
   4886 
   4887 /* r1[32:63] = r1[32:63] | i2 */
   4888 static UChar *
   4889 s390_emit_OILFw(UChar *p, UChar r1, UInt i2)
   4890 {
   4891    if (s390_host_has_eimm) {
   4892       return s390_emit_OILF(p, r1, i2);
   4893    }
   4894 
   4895    /* Load I2 into R0; then AND R0 with R1 */
   4896    p = s390_emit_load_32imm(p, R0, i2);
   4897    return s390_emit_OR(p, r1, R0);
   4898 }
   4899 
   4900 
   4901 /* r1[32:63] = r1[32:63] ^ i2 */
   4902 static UChar *
   4903 s390_emit_XILFw(UChar *p, UChar r1, UInt i2)
   4904 {
   4905    if (s390_host_has_eimm) {
   4906       return s390_emit_XILF(p, r1, i2);
   4907    }
   4908 
   4909    /* Load I2 into R0; then AND R0 with R1 */
   4910    p = s390_emit_load_32imm(p, R0, i2);
   4911    return s390_emit_XR(p, r1, R0);
   4912 }
   4913 
   4914 
   4915 /*  r1[32:63] = sign_extend(r2[56:63]) */
   4916 static UChar *
   4917 s390_emit_LBRw(UChar *p, UChar r1, UChar r2)
   4918 {
   4919    if (s390_host_has_eimm) {
   4920       return s390_emit_LBR(p, r1, r2);
   4921    }
   4922 
   4923    p = s390_emit_LR(p, r1, r2);               /* r1 = r2 */
   4924    p = s390_emit_SLL(p, r1, R0, 24);          /* r1 = r1 << 24  */
   4925    return s390_emit_SRA(p, r1, R0, 24);       /* r1 = r1 >>a 24 */
   4926 }
   4927 
   4928 
   4929 /*  r1[0:63] = sign_extend(r2[56:63]) */
   4930 static UChar *
   4931 s390_emit_LGBRw(UChar *p, UChar r1, UChar r2)
   4932 {
   4933    if (s390_host_has_eimm) {
   4934       return s390_emit_LGBR(p, r1, r2);
   4935    }
   4936 
   4937    p = s390_emit_LR(p, r1, r2);                       /* r1 = r2 */
   4938    p = s390_emit_SLLG(p, r1, r1, R0, DISP20(56));     /* r1 = r1 << 56  */
   4939    return s390_emit_SRAG(p, r1, r1, R0, DISP20(56));  /* r1 = r1 >>a 56 */
   4940 }
   4941 
   4942 
   4943 /* r1[32:63] = sign_extend(r2[48:63]) */
   4944 static UChar *
   4945 s390_emit_LHRw(UChar *p, UChar r1, UChar r2)
   4946 {
   4947    if (s390_host_has_eimm) {
   4948       return s390_emit_LHR(p, r1, r2);
   4949    }
   4950 
   4951    p = s390_emit_LR(p, r1, r2);               /* r1 = r2 */
   4952    p = s390_emit_SLL(p, r1, R0, 16);          /* r1 = r1 << 16  */
   4953    return s390_emit_SRA(p, r1, R0, 16);       /* r1 = r1 >>a 16 */
   4954 }
   4955 
   4956 
   4957 /* r1[0:63] = sign_extend(r2[48:63]) */
   4958 static UChar *
   4959 s390_emit_LGHRw(UChar *p, UChar r1, UChar r2)
   4960 {
   4961    if (s390_host_has_eimm) {
   4962       return s390_emit_LGHR(p, r1, r2);
   4963    }
   4964 
   4965    p = s390_emit_LR(p, r1, r2);               /* r1 = r2 */
   4966    p = s390_emit_SLLG(p, r1, r1, R0, DISP20(48));     /* r1 = r1 << 48  */
   4967    return s390_emit_SRAG(p, r1, r1, R0, DISP20(48));  /* r1 = r1 >>a 48 */
   4968 }
   4969 
   4970 
   4971 /* r1[0:63] = sign_extend(i2) */
   4972 static UChar *
   4973 s390_emit_LGFIw(UChar *p, UChar r1, UInt i2)
   4974 {
   4975    if (s390_host_has_eimm) {
   4976       return s390_emit_LGFI(p, r1, i2);
   4977    }
   4978 
   4979    p = s390_emit_load_32imm(p, R0, i2);
   4980    return s390_emit_LGFR(p, r1, R0);
   4981 }
   4982 
   4983 
   4984 /* r1[32:63] = zero_extend($r2[56:63]) */
   4985 static UChar *
   4986 s390_emit_LLCRw(UChar *p, UChar r1, UChar r2)
   4987 {
   4988    if (s390_host_has_eimm) {
   4989       return s390_emit_LLCR(p, r1, r2);
   4990    }
   4991 
   4992    p = s390_emit_LR(p, r1, r2);
   4993    p = s390_emit_LHI(p, R0, 0xFF);
   4994    return s390_emit_NR(p, r1, R0);
   4995 }
   4996 
   4997 
   4998 /* r1[0:63] = zero_extend($r2[56:63]) */
   4999 static UChar *
   5000 s390_emit_LLGCRw(UChar *p, UChar r1, UChar r2)
   5001 {
   5002    if (s390_host_has_eimm) {
   5003       return s390_emit_LLGCR(p, r1, r2);
   5004    }
   5005 
   5006    p = s390_emit_LR(p, r1, r2);
   5007    p = s390_emit_LLILL(p, R0, 0xFF);
   5008    return s390_emit_NGR(p, r1, R0);
   5009 }
   5010 
   5011 
   5012 /* r1[32:63] = zero_extend(r2[48:63]) */
   5013 static UChar *
   5014 s390_emit_LLHRw(UChar *p, UChar r1, UChar r2)
   5015 {
   5016    if (s390_host_has_eimm) {
   5017       return s390_emit_LLHR(p, r1, r2);
   5018    }
   5019 
   5020    p = s390_emit_LR(p, r1, r2);
   5021    p = s390_emit_LLILL(p, R0, 0xFFFF);
   5022    return s390_emit_NR(p, r1, R0);
   5023 }
   5024 
   5025 
   5026 /* r1[0:63] = zero_extend(r2[48:63]) */
   5027 static UChar *
   5028 s390_emit_LLGHRw(UChar *p, UChar r1, UChar r2)
   5029 {
   5030    if (s390_host_has_eimm) {
   5031       return s390_emit_LLGHR(p, r1, r2);
   5032    }
   5033 
   5034    p = s390_emit_LR(p, r1, r2);
   5035    p = s390_emit_LLILL(p, R0, 0xFFFF);
   5036    return s390_emit_NGR(p, r1, R0);
   5037 }
   5038 
   5039 
   5040 /* r1[32:63] = zero_extend(mem[op2addr][0:7]) */
   5041 static UChar *
   5042 s390_emit_LLCw(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl, UChar dh)
   5043 {
   5044    if (s390_host_has_eimm) {
   5045       return s390_emit_LLC(p, r1, x2, b2, dl, dh);
   5046    }
   5047 
   5048    if (dh == 0) {
   5049       p = s390_emit_IC(p, r1, x2, b2, dl);
   5050    } else {
   5051       p = s390_emit_ICY(p, r1, x2, b2, dl, dh);
   5052    }
   5053    p = s390_emit_LLILL(p, R0, 0xFF);
   5054    return s390_emit_NR(p, r1, R0);
   5055 }
   5056 
   5057 
   5058 /* r1[32:63] = zero_extend(mem[op2addr][0:15]) */
   5059 static UChar *
   5060 s390_emit_LLHw(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl, UChar dh)
   5061 {
   5062    if (s390_host_has_eimm) {
   5063       return s390_emit_LLH(p, r1, x2, b2, dl, dh);
   5064    }
   5065 
   5066    p = s390_emit_LLGH(p, r1, x2, b2, dl, dh);
   5067    p = s390_emit_LLILL(p, R0, 0xFFFF);
   5068    return s390_emit_NR(p, r1, R0);
   5069 }
   5070 
   5071 
   5072 /* r1[0:63] = zero_extend(i2) */
   5073 static UChar *
   5074 s390_emit_LLILFw(UChar *p, UChar r1, UInt i2)
   5075 {
   5076    if (s390_host_has_eimm) {
   5077       return s390_emit_LLILF(p, r1, i2);
   5078    }
   5079 
   5080    p = s390_emit_LLILH(p, r1, (i2 >> 16) & 0xFFFF);  /* i2[0:15] */
   5081    return s390_emit_OILL(p, r1, i2 & 0xFFFF);
   5082 }
   5083 
   5084 
   5085 /* r1[32:63] = r1[32:63] + i2 */
   5086 static UChar *
   5087 s390_emit_AFIw(UChar *p, UChar r1, UInt i2)
   5088 {
   5089    if (s390_host_has_eimm) {
   5090       return s390_emit_AFI(p, r1, i2);
   5091    }
   5092    /* Load 32 bit immediate to R0 then add */
   5093    p = s390_emit_load_32imm(p, R0, i2);
   5094    return s390_emit_AR(p, r1, R0);
   5095 }
   5096 
   5097 
   5098 /* r1[32:63] = r1[32:63] - i2 */
   5099 static UChar *
   5100 s390_emit_SLFIw(UChar *p, UChar r1, UInt i2)
   5101 {
   5102    if (s390_host_has_eimm) {
   5103       return s390_emit_SLFI(p, r1, i2);
   5104    }
   5105 
   5106    /* Load 32 bit immediate to R0 then subtract */
   5107    p = s390_emit_load_32imm(p, R0, i2);
   5108    return s390_emit_SR(p, r1, R0);
   5109 }
   5110 
   5111 
   5112 /* r1[0:63] = r1[0:63] - zero_extend(i2) */
   5113 static UChar *
   5114 s390_emit_SLGFIw(UChar *p, UChar r1, UInt i2)
   5115 {
   5116    if (s390_host_has_eimm) {
   5117       return s390_emit_SLGFI(p, r1, i2);
   5118    }
   5119 
   5120    /* Load zero-extended 32 bit immediate to R0 then subtract */
   5121    p = s390_emit_load_64imm(p, R0, i2);
   5122    return s390_emit_SGR(p, r1, R0);
   5123 }
   5124 
   5125 
   5126 static UChar *
   5127 s390_emit_LTw(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl, UChar dh)
   5128 {
   5129    if (s390_host_has_eimm) {
   5130       return s390_emit_LT(p, r1, x2, b2, dl, dh);
   5131    }
   5132    /* Load 32 bit from memory to R0 then compare */
   5133    if (dh == 0) {
   5134       p = s390_emit_L(p, R0, x2, b2, dl);
   5135    } else {
   5136       p = s390_emit_LY(p, R0, x2, b2, dl, dh);
   5137    }
   5138    return s390_emit_LTR(p, r1, R0);
   5139 }
   5140 
   5141 
   5142 static UChar *
   5143 s390_emit_LTGw(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl, UChar dh)
   5144 {
   5145    if (s390_host_has_eimm) {
   5146       return s390_emit_LTG(p, r1, x2, b2, dl, dh);
   5147    }
   5148    /* Load 64 bit from memory to R0 then compare */
   5149    p = s390_emit_LG(p, R0, x2, b2, dl, dh);
   5150    return s390_emit_LTGR(p, r1, R0);
   5151 }
   5152 
   5153 
   5154 static UChar *
   5155 s390_emit_CFIw(UChar *p, UChar r1, UInt i2)
   5156 {
   5157    if (s390_host_has_eimm) {
   5158       return s390_emit_CFI(p, r1, i2);
   5159    }
   5160    /* Load 32 bit immediate to R0 then compare */
   5161    p = s390_emit_load_32imm(p, R0, i2);
   5162    return s390_emit_CR(p, r1, R0);
   5163 }
   5164 
   5165 
   5166 static UChar *
   5167 s390_emit_CLFIw(UChar *p, UChar r1, UInt i2)
   5168 {
   5169    if (s390_host_has_eimm) {
   5170       return s390_emit_CLFI(p, r1, i2);
   5171    }
   5172    /* Load 32 bit immediate to R0 then compare */
   5173    p = s390_emit_load_32imm(p, R0, i2);
   5174    return s390_emit_CLR(p, r1, R0);
   5175 }
   5176 
   5177 
   5178 static UChar *
   5179 s390_emit_LGDRw(UChar *p, UChar r1, UChar r2)
   5180 {
   5181    if (s390_host_has_fgx) {
   5182       return s390_emit_LGDR(p, r1, r2);
   5183    }
   5184 
   5185    /* Store the FPR at memory[sp - 8]. This is safe because SP grows towards
   5186       smaller addresses and is 8-byte aligned. Then load the GPR from that
   5187       memory location/ */
   5188    p = s390_emit_STDY(p, r2, R0, S390_REGNO_STACK_POINTER, DISP20(-8));
   5189    return s390_emit_LG(p, r1, R0, S390_REGNO_STACK_POINTER, DISP20(-8));
   5190 }
   5191 
   5192 
   5193 static UChar *
   5194 s390_emit_LDGRw(UChar *p, UChar r1, UChar r2)
   5195 {
   5196    if (s390_host_has_fgx) {
   5197       return s390_emit_LDGR(p, r1, r2);
   5198    }
   5199 
   5200    /* Store the GPR at memory[sp - 8]. This is safe because SP grows towards
   5201       smaller addresses and is 8-byte aligned. Then load the FPR from that
   5202       memory location/ */
   5203    p = s390_emit_STG(p, r2, R0, S390_REGNO_STACK_POINTER, DISP20(-8));
   5204    return s390_emit_LDY(p, r1, R0, S390_REGNO_STACK_POINTER, DISP20(-8));
   5205 }
   5206 
   5207 
   5208 /*---------------------------------------------------------------*/
   5209 /*--- Constructors for the various s390_insn kinds            ---*/
   5210 /*---------------------------------------------------------------*/
   5211 
   5212 s390_insn *
   5213 s390_insn_load(UChar size, HReg dst, s390_amode *src)
   5214 {
   5215    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   5216 
   5217    insn->tag  = S390_INSN_LOAD;
   5218    insn->size = size;
   5219    insn->variant.load.src  = src;
   5220    insn->variant.load.dst  = dst;
   5221 
   5222    vassert(size == 1 || size == 2 || size == 4 || size == 8);
   5223 
   5224    return insn;
   5225 }
   5226 
   5227 
   5228 s390_insn *
   5229 s390_insn_store(UChar size, s390_amode *dst, HReg src)
   5230 {
   5231    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   5232 
   5233    insn->tag  = S390_INSN_STORE;
   5234    insn->size = size;
   5235    insn->variant.store.src  = src;
   5236    insn->variant.store.dst  = dst;
   5237 
   5238    vassert(size == 1 || size == 2 || size == 4 || size == 8);
   5239 
   5240    return insn;
   5241 }
   5242 
   5243 
   5244 s390_insn *
   5245 s390_insn_move(UChar size, HReg dst, HReg src)
   5246 {
   5247    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   5248 
   5249    insn->tag  = S390_INSN_MOVE;
   5250    insn->size = size;
   5251    insn->variant.move.src  = src;
   5252    insn->variant.move.dst  = dst;
   5253 
   5254    vassert(size == 1 || size == 2 || size == 4 || size == 8);
   5255 
   5256    return insn;
   5257 }
   5258 
   5259 
   5260 s390_insn *
   5261 s390_insn_memcpy(UChar size, s390_amode *dst, s390_amode *src)
   5262 {
   5263    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   5264 
   5265    /* This insn will be mapped to MVC which requires base register
   5266       plus 12-bit displacement */
   5267    vassert(src->tag == S390_AMODE_B12);
   5268    vassert(dst->tag == S390_AMODE_B12);
   5269 
   5270    insn->tag  = S390_INSN_MEMCPY;
   5271    insn->size = size;
   5272    insn->variant.memcpy.src = src;
   5273    insn->variant.memcpy.dst = dst;
   5274 
   5275    vassert(size == 1 || size == 2 || size == 4 || size == 8);
   5276 
   5277    return insn;
   5278 }
   5279 
   5280 
   5281 s390_insn *
   5282 s390_insn_cond_move(UChar size, s390_cc_t cond, HReg dst, s390_opnd_RMI src)
   5283 {
   5284    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   5285 
   5286    insn->tag  = S390_INSN_COND_MOVE;
   5287    insn->size = size;
   5288    insn->variant.cond_move.cond = cond;
   5289    insn->variant.cond_move.src  = src;
   5290    insn->variant.cond_move.dst  = dst;
   5291 
   5292    vassert(size == 1 || size == 2 || size == 4 || size == 8);
   5293 
   5294    return insn;
   5295 }
   5296 
   5297 
   5298 s390_insn *
   5299 s390_insn_load_immediate(UChar size, HReg dst, ULong value)
   5300 {
   5301    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   5302 
   5303    insn->tag  = S390_INSN_LOAD_IMMEDIATE;
   5304    insn->size = size;
   5305    insn->variant.load_immediate.dst   = dst;
   5306    insn->variant.load_immediate.value = value;
   5307 
   5308    return insn;
   5309 }
   5310 
   5311 
   5312 s390_insn *
   5313 s390_insn_alu(UChar size, s390_alu_t tag, HReg dst, s390_opnd_RMI op2)
   5314 {
   5315    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   5316 
   5317    insn->tag  = S390_INSN_ALU;
   5318    insn->size = size;
   5319    insn->variant.alu.tag = tag;
   5320    insn->variant.alu.dst = dst;
   5321    insn->variant.alu.op2 = op2;
   5322 
   5323    return insn;
   5324 }
   5325 
   5326 
   5327 s390_insn *
   5328 s390_insn_mul(UChar size, HReg dst_hi, HReg dst_lo, s390_opnd_RMI op2,
   5329               Bool signed_multiply)
   5330 {
   5331    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   5332 
   5333    vassert(! hregIsVirtual(dst_hi));
   5334    vassert(! hregIsVirtual(dst_lo));
   5335 
   5336    insn->tag  = signed_multiply ? S390_INSN_SMUL : S390_INSN_UMUL;
   5337    insn->size = size;
   5338    insn->variant.mul.dst_hi = dst_hi;
   5339    insn->variant.mul.dst_lo = dst_lo;
   5340    insn->variant.mul.op2 = op2;
   5341 
   5342    return insn;
   5343 }
   5344 
   5345 
   5346 s390_insn *
   5347 s390_insn_div(UChar size, HReg op1_hi, HReg op1_lo, s390_opnd_RMI op2,
   5348               Bool signed_divide)
   5349 {
   5350    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   5351 
   5352    vassert(size == 4 || size == 8);
   5353    vassert(! hregIsVirtual(op1_hi));
   5354    vassert(! hregIsVirtual(op1_lo));
   5355 
   5356    insn->tag  = signed_divide ? S390_INSN_SDIV : S390_INSN_UDIV;
   5357    insn->size = size;
   5358    insn->variant.div.op1_hi = op1_hi;
   5359    insn->variant.div.op1_lo = op1_lo;
   5360    insn->variant.div.op2 = op2;
   5361 
   5362    return insn;
   5363 }
   5364 
   5365 
   5366 s390_insn *
   5367 s390_insn_divs(UChar size, HReg rem, HReg op1, s390_opnd_RMI op2)
   5368 {
   5369    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   5370 
   5371    vassert(size == 8);
   5372    vassert(! hregIsVirtual(op1));
   5373    vassert(! hregIsVirtual(rem));
   5374 
   5375    insn->tag  = S390_INSN_DIVS;
   5376    insn->size = size;
   5377    insn->variant.divs.rem = rem;   /* remainder */
   5378    insn->variant.divs.op1 = op1;   /* also quotient */
   5379    insn->variant.divs.op2 = op2;
   5380 
   5381    return insn;
   5382 }
   5383 
   5384 
   5385 s390_insn *
   5386 s390_insn_clz(UChar size, HReg num_bits, HReg clobber, s390_opnd_RMI src)
   5387 {
   5388    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   5389 
   5390    vassert(size == 8);
   5391    vassert(! hregIsVirtual(num_bits));
   5392    vassert(! hregIsVirtual(clobber));
   5393 
   5394    insn->tag  = S390_INSN_CLZ;
   5395    insn->size = size;
   5396    insn->variant.clz.num_bits = num_bits;
   5397    insn->variant.clz.clobber  = clobber;
   5398    insn->variant.clz.src = src;
   5399 
   5400    return insn;
   5401 }
   5402 
   5403 
   5404 s390_insn *
   5405 s390_insn_unop(UChar size, s390_unop_t tag, HReg dst, s390_opnd_RMI opnd)
   5406 {
   5407    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   5408 
   5409    insn->tag  = S390_INSN_UNOP;
   5410    insn->size = size;
   5411    insn->variant.unop.tag = tag;
   5412    insn->variant.unop.dst = dst;
   5413    insn->variant.unop.src = opnd;
   5414 
   5415    return insn;
   5416 }
   5417 
   5418 
   5419 s390_insn *
   5420 s390_insn_test(UChar size, s390_opnd_RMI src)
   5421 {
   5422    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   5423 
   5424    vassert(size == 4 || size == 8);
   5425 
   5426    insn->tag  = S390_INSN_TEST;
   5427    insn->size = size;
   5428    insn->variant.test.src = src;
   5429 
   5430    return insn;
   5431 }
   5432 
   5433 
   5434 s390_insn *
   5435 s390_insn_cc2bool(HReg dst, s390_cc_t cond)
   5436 {
   5437    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   5438 
   5439    insn->tag  = S390_INSN_CC2BOOL;
   5440    insn->size = 0;   /* does not matter */
   5441    insn->variant.cc2bool.cond = cond;
   5442    insn->variant.cc2bool.dst  = dst;
   5443 
   5444    return insn;
   5445 }
   5446 
   5447 
   5448 s390_insn *
   5449 s390_insn_cas(UChar size, HReg op1, s390_amode *op2, HReg op3, HReg old_mem)
   5450 {
   5451    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   5452 
   5453    vassert(size == 4 || size == 8);
   5454    vassert(hregNumber(op2->x) == 0);
   5455    vassert(op2->tag == S390_AMODE_B12 || op2->tag == S390_AMODE_B20);
   5456 
   5457    insn->tag  = S390_INSN_CAS;
   5458    insn->size = size;
   5459    insn->variant.cas.op1 = op1;
   5460    insn->variant.cas.op2 = op2;
   5461    insn->variant.cas.op3 = op3;
   5462    insn->variant.cas.old_mem = old_mem;
   5463 
   5464    return insn;
   5465 }
   5466 
   5467 
   5468 s390_insn *
   5469 s390_insn_cdas(UChar size, HReg op1_high, HReg op1_low, s390_amode *op2,
   5470                HReg op3_high, HReg op3_low, HReg old_mem_high, HReg old_mem_low,
   5471                HReg scratch)
   5472 {
   5473    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   5474    s390_cdas *cdas = LibVEX_Alloc_inline(sizeof(s390_cdas));
   5475 
   5476    vassert(size == 4 || size == 8);
   5477    vassert(hregNumber(op2->x) == 0);
   5478    vassert(hregNumber(scratch) == 1);  /* r0,r1 used as scratch reg pair */
   5479    vassert(op2->tag == S390_AMODE_B12 || op2->tag == S390_AMODE_B20);
   5480 
   5481    insn->tag  = S390_INSN_CDAS;
   5482    insn->size = size;
   5483    insn->variant.cdas.details = cdas;
   5484 
   5485    cdas->op1_high = op1_high;
   5486    cdas->op1_low  = op1_low;
   5487    cdas->op2 = op2;
   5488    cdas->op3_high = op3_high;
   5489    cdas->op3_low  = op3_low;
   5490    cdas->old_mem_high = old_mem_high;
   5491    cdas->old_mem_low  = old_mem_low;
   5492    cdas->scratch = scratch;
   5493 
   5494    return insn;
   5495 }
   5496 
   5497 
   5498 s390_insn *
   5499 s390_insn_compare(UChar size, HReg src1, s390_opnd_RMI src2,
   5500                   Bool signed_comparison)
   5501 {
   5502    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   5503 
   5504    vassert(size == 4 || size == 8);
   5505 
   5506    insn->tag  = S390_INSN_COMPARE;
   5507    insn->size = size;
   5508    insn->variant.compare.src1 = src1;
   5509    insn->variant.compare.src2 = src2;
   5510    insn->variant.compare.signed_comparison = signed_comparison;
   5511 
   5512    return insn;
   5513 }
   5514 
   5515 
   5516 s390_insn *
   5517 s390_insn_helper_call(s390_cc_t cond, Addr64 target, UInt num_args,
   5518                       const HChar *name, RetLoc rloc)
   5519 {
   5520    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   5521    s390_helper_call *helper_call = LibVEX_Alloc_inline(sizeof(s390_helper_call));
   5522 
   5523    insn->tag  = S390_INSN_HELPER_CALL;
   5524    insn->size = 0;  /* does not matter */
   5525    insn->variant.helper_call.details = helper_call;
   5526 
   5527    helper_call->cond = cond;
   5528    helper_call->target = target;
   5529    helper_call->num_args = num_args;
   5530    helper_call->name = name;
   5531    helper_call->rloc = rloc;
   5532 
   5533    vassert(is_sane_RetLoc(rloc));
   5534 
   5535    return insn;
   5536 }
   5537 
   5538 
   5539 s390_insn *
   5540 s390_insn_bfp_triop(UChar size, s390_bfp_triop_t tag, HReg dst, HReg op2,
   5541                     HReg op3)
   5542 {
   5543    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   5544 
   5545    vassert(size == 4 || size == 8);
   5546 
   5547    insn->tag  = S390_INSN_BFP_TRIOP;
   5548    insn->size = size;
   5549    insn->variant.bfp_triop.tag = tag;
   5550    insn->variant.bfp_triop.dst = dst;
   5551    insn->variant.bfp_triop.op2 = op2;
   5552    insn->variant.bfp_triop.op3 = op3;
   5553 
   5554    return insn;
   5555 }
   5556 
   5557 
   5558 s390_insn *
   5559 s390_insn_bfp_binop(UChar size, s390_bfp_binop_t tag, HReg dst, HReg op2)
   5560 {
   5561    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   5562 
   5563    vassert(size == 4 || size == 8);
   5564 
   5565    insn->tag  = S390_INSN_BFP_BINOP;
   5566    insn->size = size;
   5567    insn->variant.bfp_binop.tag = tag;
   5568    insn->variant.bfp_binop.dst_hi = dst;
   5569    insn->variant.bfp_binop.op2_hi = op2;
   5570    insn->variant.bfp_binop.dst_lo = INVALID_HREG;
   5571    insn->variant.bfp_binop.op2_lo = INVALID_HREG;
   5572 
   5573    return insn;
   5574 }
   5575 
   5576 
   5577 s390_insn *
   5578 s390_insn_bfp_unop(UChar size, s390_bfp_unop_t tag, HReg dst, HReg op)
   5579 {
   5580    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   5581 
   5582    vassert(size == 4 || size == 8);
   5583 
   5584    insn->tag  = S390_INSN_BFP_UNOP;
   5585    insn->size = size;
   5586    insn->variant.bfp_unop.tag = tag;
   5587    insn->variant.bfp_unop.dst_hi = dst;
   5588    insn->variant.bfp_unop.op_hi  = op;
   5589    insn->variant.bfp_unop.dst_lo = INVALID_HREG;
   5590    insn->variant.bfp_unop.op_lo  = INVALID_HREG;
   5591 
   5592    return insn;
   5593 }
   5594 
   5595 
   5596 s390_insn *
   5597 s390_insn_bfp_compare(UChar size, HReg dst, HReg op1, HReg op2)
   5598 {
   5599    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   5600 
   5601    vassert(size == 4 || size == 8);
   5602 
   5603    insn->tag  = S390_INSN_BFP_COMPARE;
   5604    insn->size = size;
   5605    insn->variant.bfp_compare.dst = dst;
   5606    insn->variant.bfp_compare.op1_hi = op1;
   5607    insn->variant.bfp_compare.op2_hi = op2;
   5608    insn->variant.bfp_compare.op1_lo = INVALID_HREG;
   5609    insn->variant.bfp_compare.op2_lo = INVALID_HREG;
   5610 
   5611    return insn;
   5612 }
   5613 
   5614 
   5615 s390_insn *
   5616 s390_insn_bfp_convert(UChar size, s390_bfp_conv_t tag, HReg dst, HReg op,
   5617                       s390_bfp_round_t rounding_mode)
   5618 {
   5619    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   5620 
   5621    vassert(size == 4 || size == 8);
   5622 
   5623    insn->tag  = S390_INSN_BFP_CONVERT;
   5624    insn->size = size;
   5625    insn->variant.bfp_convert.tag = tag;
   5626    insn->variant.bfp_convert.dst_hi = dst;
   5627    insn->variant.bfp_convert.op_hi  = op;
   5628    insn->variant.bfp_convert.dst_lo = INVALID_HREG;
   5629    insn->variant.bfp_convert.op_lo  = INVALID_HREG;
   5630    insn->variant.bfp_convert.rounding_mode = rounding_mode;
   5631 
   5632    return insn;
   5633 }
   5634 
   5635 
   5636 /* Check validity of a register pair for 128-bit FP. Valid register
   5637    pairs are (0,2), (1,3), (4, 6), (5, 7), (8, 10), (9, 11), (12, 14),
   5638    and (13, 15). */
   5639 static Bool
   5640 is_valid_fp128_regpair(HReg hi, HReg lo)
   5641 {
   5642    UInt hi_regno = hregNumber(hi);
   5643    UInt lo_regno = hregNumber(lo);
   5644 
   5645    if (lo_regno != hi_regno + 2) return False;
   5646    if ((hi_regno & 0x2) != 0) return False;
   5647 
   5648    return True;
   5649 }
   5650 
   5651 s390_insn *
   5652 s390_insn_bfp128_binop(UChar size, s390_bfp_binop_t tag, HReg dst_hi,
   5653                        HReg dst_lo, HReg op2_hi, HReg op2_lo)
   5654 {
   5655    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   5656 
   5657    vassert(size == 16);
   5658    vassert(is_valid_fp128_regpair(dst_hi, dst_lo));
   5659    vassert(is_valid_fp128_regpair(op2_hi, op2_lo));
   5660 
   5661    insn->tag  = S390_INSN_BFP_BINOP;
   5662    insn->size = size;
   5663    insn->variant.bfp_binop.tag = tag;
   5664    insn->variant.bfp_binop.dst_hi = dst_hi;
   5665    insn->variant.bfp_binop.dst_lo = dst_lo;
   5666    insn->variant.bfp_binop.op2_hi = op2_hi;
   5667    insn->variant.bfp_binop.op2_lo = op2_lo;
   5668 
   5669    return insn;
   5670 }
   5671 
   5672 
   5673 s390_insn *
   5674 s390_insn_bfp128_unop(UChar size, s390_bfp_unop_t tag, HReg dst_hi,
   5675                       HReg dst_lo, HReg op_hi, HReg op_lo)
   5676 {
   5677    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   5678 
   5679    vassert(size == 16);
   5680    vassert(is_valid_fp128_regpair(dst_hi, dst_lo));
   5681    vassert(is_valid_fp128_regpair(op_hi, op_lo));
   5682 
   5683    insn->tag  = S390_INSN_BFP_UNOP;
   5684    insn->size = size;
   5685    insn->variant.bfp_unop.tag = tag;
   5686    insn->variant.bfp_unop.dst_hi = dst_hi;
   5687    insn->variant.bfp_unop.dst_lo = dst_lo;
   5688    insn->variant.bfp_unop.op_hi = op_hi;
   5689    insn->variant.bfp_unop.op_lo = op_lo;
   5690 
   5691    return insn;
   5692 }
   5693 
   5694 
   5695 s390_insn *
   5696 s390_insn_bfp128_compare(UChar size, HReg dst, HReg op1_hi, HReg op1_lo,
   5697                          HReg op2_hi, HReg op2_lo)
   5698 {
   5699    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   5700 
   5701    vassert(size == 16);
   5702    vassert(is_valid_fp128_regpair(op1_hi, op1_lo));
   5703    vassert(is_valid_fp128_regpair(op2_hi, op2_lo));
   5704 
   5705    insn->tag  = S390_INSN_BFP_COMPARE;
   5706    insn->size = size;
   5707    insn->variant.bfp_compare.dst = dst;
   5708    insn->variant.bfp_compare.op1_hi = op1_hi;
   5709    insn->variant.bfp_compare.op1_lo = op1_lo;
   5710    insn->variant.bfp_compare.op2_hi = op2_hi;
   5711    insn->variant.bfp_compare.op2_lo = op2_lo;
   5712 
   5713    return insn;
   5714 }
   5715 
   5716 
   5717 static s390_insn *
   5718 s390_insn_bfp128_convert(UChar size, s390_bfp_conv_t tag, HReg dst_hi,
   5719                          HReg dst_lo, HReg op_hi, HReg op_lo,
   5720                          s390_bfp_round_t rounding_mode)
   5721 {
   5722    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   5723 
   5724    if (size == 16) {
   5725       /* From smaller size to 16 bytes */
   5726       vassert(is_valid_fp128_regpair(dst_hi, dst_lo));
   5727       vassert(hregIsInvalid(op_lo));
   5728    } else {
   5729       /* From 16 bytes to smaller size */
   5730       vassert(is_valid_fp128_regpair(op_hi, op_lo));
   5731    }
   5732 
   5733    insn->tag  = S390_INSN_BFP_CONVERT;
   5734    insn->size = size;
   5735    insn->variant.bfp_convert.tag = tag;
   5736    insn->variant.bfp_convert.dst_hi = dst_hi;
   5737    insn->variant.bfp_convert.dst_lo = dst_lo;
   5738    insn->variant.bfp_convert.op_hi = op_hi;
   5739    insn->variant.bfp_convert.op_lo = op_lo;
   5740    insn->variant.bfp_convert.rounding_mode = rounding_mode;
   5741 
   5742    return insn;
   5743 }
   5744 
   5745 
   5746 s390_insn *
   5747 s390_insn_bfp128_convert_to(UChar size, s390_bfp_conv_t tag, HReg dst_hi,
   5748                             HReg dst_lo, HReg op)
   5749 {
   5750    /* Conversion to bfp128 never requires a rounding mode. Provide default
   5751       rounding mode. It will not be used when emitting insns. */
   5752    s390_bfp_round_t rounding_mode = S390_BFP_ROUND_NEAREST_EVEN;
   5753 
   5754    return s390_insn_bfp128_convert(size, tag, dst_hi, dst_lo, op,
   5755                                    INVALID_HREG, rounding_mode);
   5756 }
   5757 
   5758 
   5759 s390_insn *
   5760 s390_insn_bfp128_convert_from(UChar size, s390_bfp_conv_t tag, HReg dst_hi,
   5761                               HReg dst_lo, HReg op_hi, HReg op_lo,
   5762                               s390_bfp_round_t rounding_mode)
   5763 {
   5764    return s390_insn_bfp128_convert(size, tag, dst_hi, dst_lo, op_hi, op_lo,
   5765                                    rounding_mode);
   5766 }
   5767 
   5768 
   5769 s390_insn *
   5770 s390_insn_dfp_binop(UChar size, s390_dfp_binop_t tag, HReg dst, HReg op2,
   5771                     HReg op3, s390_dfp_round_t rounding_mode)
   5772 {
   5773    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   5774    s390_dfp_binop *dfp_binop = LibVEX_Alloc_inline(sizeof(s390_dfp_binop));
   5775 
   5776    vassert(size == 8);
   5777 
   5778    insn->tag  = S390_INSN_DFP_BINOP;
   5779    insn->size = size;
   5780    insn->variant.dfp_binop.details = dfp_binop;
   5781 
   5782    dfp_binop->tag = tag;
   5783    dfp_binop->dst_hi = dst;
   5784    dfp_binop->op2_hi = op2;
   5785    dfp_binop->op3_hi = op3;
   5786    dfp_binop->dst_lo = INVALID_HREG;
   5787    dfp_binop->op2_lo = INVALID_HREG;
   5788    dfp_binop->op3_lo = INVALID_HREG;
   5789    dfp_binop->rounding_mode = rounding_mode;
   5790 
   5791    return insn;
   5792 }
   5793 
   5794 
   5795 s390_insn *
   5796 s390_insn_dfp_unop(UChar size, s390_dfp_unop_t tag, HReg dst, HReg op)
   5797 {
   5798    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   5799 
   5800    vassert(size == 8);
   5801 
   5802    insn->tag  = S390_INSN_DFP_UNOP;
   5803    insn->size = size;
   5804    insn->variant.dfp_unop.tag = tag;
   5805    insn->variant.dfp_unop.dst_hi = dst;
   5806    insn->variant.dfp_unop.op_hi  = op;
   5807    insn->variant.dfp_unop.dst_lo = INVALID_HREG;
   5808    insn->variant.dfp_unop.op_lo  = INVALID_HREG;
   5809 
   5810    return insn;
   5811 }
   5812 
   5813 
   5814 s390_insn *
   5815 s390_insn_dfp_intop(UChar size, s390_dfp_intop_t tag, HReg dst, HReg op2,
   5816                     HReg op3)
   5817 {
   5818    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   5819 
   5820    vassert(size == 8);
   5821 
   5822    insn->tag  = S390_INSN_DFP_INTOP;
   5823    insn->size = size;
   5824    insn->variant.dfp_intop.tag = tag;
   5825    insn->variant.dfp_intop.dst_hi = dst;
   5826    insn->variant.dfp_intop.op2    = op2;
   5827    insn->variant.dfp_intop.op3_hi = op3;
   5828    insn->variant.dfp_intop.dst_lo = INVALID_HREG;
   5829    insn->variant.dfp_intop.op3_lo = INVALID_HREG;
   5830 
   5831    return insn;
   5832 }
   5833 
   5834 
   5835 s390_insn *
   5836 s390_insn_dfp_compare(UChar size, s390_dfp_cmp_t tag, HReg dst,
   5837                       HReg op1, HReg op2)
   5838 {
   5839    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   5840 
   5841    vassert(size == 8);
   5842 
   5843    insn->tag  = S390_INSN_DFP_COMPARE;
   5844    insn->size = size;
   5845    insn->variant.dfp_compare.tag = tag;
   5846    insn->variant.dfp_compare.dst = dst;
   5847    insn->variant.dfp_compare.op1_hi = op1;
   5848    insn->variant.dfp_compare.op2_hi = op2;
   5849    insn->variant.dfp_compare.op1_lo = INVALID_HREG;
   5850    insn->variant.dfp_compare.op2_lo = INVALID_HREG;
   5851 
   5852    return insn;
   5853 }
   5854 
   5855 
   5856 s390_insn *
   5857 s390_insn_dfp_convert(UChar size, s390_dfp_conv_t tag, HReg dst, HReg op,
   5858                       s390_dfp_round_t rounding_mode)
   5859 {
   5860    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   5861 
   5862    vassert(size == 4 || size == 8);
   5863 
   5864    insn->tag  = S390_INSN_DFP_CONVERT;
   5865    insn->size = size;
   5866    insn->variant.dfp_convert.tag = tag;
   5867    insn->variant.dfp_convert.dst_hi = dst;
   5868    insn->variant.dfp_convert.op_hi  = op;
   5869    insn->variant.dfp_convert.dst_lo = INVALID_HREG;
   5870    insn->variant.dfp_convert.op_lo  = INVALID_HREG;
   5871    insn->variant.dfp_convert.rounding_mode = rounding_mode;
   5872 
   5873    return insn;
   5874 }
   5875 
   5876 
   5877 s390_insn *
   5878 s390_insn_dfp_reround(UChar size, HReg dst, HReg op2, HReg op3,
   5879                       s390_dfp_round_t rounding_mode)
   5880 {
   5881    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   5882 
   5883    vassert(size == 8);
   5884 
   5885    insn->tag  = S390_INSN_DFP_REROUND;
   5886    insn->size = size;
   5887    insn->variant.dfp_reround.dst_hi = dst;
   5888    insn->variant.dfp_reround.op2 = op2;
   5889    insn->variant.dfp_reround.op3_hi = op3;
   5890    insn->variant.dfp_reround.dst_lo = INVALID_HREG;
   5891    insn->variant.dfp_reround.op3_lo = INVALID_HREG;
   5892    insn->variant.dfp_reround.rounding_mode = rounding_mode;
   5893 
   5894    return insn;
   5895 }
   5896 
   5897 
   5898 s390_insn *
   5899 s390_insn_fp_convert(UChar size, s390_fp_conv_t tag, HReg dst, HReg op,
   5900                      HReg r1, s390_dfp_round_t rounding_mode)
   5901 {
   5902    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   5903    s390_fp_convert *fp_convert = LibVEX_Alloc_inline(sizeof(s390_fp_convert));
   5904 
   5905    vassert(size == 4 || size == 8);
   5906 
   5907    insn->tag  = S390_INSN_FP_CONVERT;
   5908    insn->size = size;
   5909    insn->variant.fp_convert.details = fp_convert;
   5910 
   5911    fp_convert->tag = tag;
   5912    fp_convert->dst_hi = dst;
   5913    fp_convert->op_hi  = op;
   5914    fp_convert->r1 = r1;
   5915    fp_convert->dst_lo = INVALID_HREG;
   5916    fp_convert->op_lo  = INVALID_HREG;
   5917    fp_convert->rounding_mode = rounding_mode;
   5918 
   5919    return insn;
   5920 }
   5921 
   5922 
   5923 s390_insn *
   5924 s390_insn_fp128_convert(UChar size, s390_fp_conv_t tag, HReg dst_hi,
   5925                         HReg dst_lo, HReg op_hi, HReg op_lo, HReg r1,
   5926                         s390_dfp_round_t rounding_mode)
   5927 {
   5928    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   5929    s390_fp_convert *fp_convert = LibVEX_Alloc_inline(sizeof(s390_fp_convert));
   5930 
   5931    vassert(size == 16);
   5932 
   5933    insn->tag  = S390_INSN_FP_CONVERT;
   5934    insn->size = size;
   5935    insn->variant.fp_convert.details = fp_convert;
   5936 
   5937    fp_convert->tag = tag;
   5938    fp_convert->dst_hi = dst_hi;
   5939    fp_convert->dst_lo = dst_lo;
   5940    fp_convert->op_hi  = op_hi;
   5941    fp_convert->r1 = r1;
   5942    fp_convert->op_lo  = op_lo;
   5943    fp_convert->rounding_mode = rounding_mode;
   5944 
   5945    return insn;
   5946 }
   5947 
   5948 
   5949 s390_insn *
   5950 s390_insn_dfp128_binop(UChar size, s390_dfp_binop_t tag, HReg dst_hi,
   5951                        HReg dst_lo, HReg op2_hi, HReg op2_lo, HReg op3_hi,
   5952                        HReg op3_lo, s390_dfp_round_t rounding_mode)
   5953 {
   5954    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   5955    s390_dfp_binop *dfp_binop = LibVEX_Alloc_inline(sizeof(s390_dfp_binop));
   5956 
   5957    vassert(size == 16);
   5958    vassert(is_valid_fp128_regpair(dst_hi, dst_lo));
   5959    vassert(is_valid_fp128_regpair(op2_hi, op2_lo));
   5960    vassert(is_valid_fp128_regpair(op3_hi, op3_lo));
   5961 
   5962    insn->tag  = S390_INSN_DFP_BINOP;
   5963    insn->size = size;
   5964    insn->variant.dfp_binop.details = dfp_binop;
   5965 
   5966    dfp_binop->tag = tag;
   5967    dfp_binop->dst_hi = dst_hi;
   5968    dfp_binop->dst_lo = dst_lo;
   5969    dfp_binop->op2_hi = op2_hi;
   5970    dfp_binop->op2_lo = op2_lo;
   5971    dfp_binop->op3_hi = op3_hi;
   5972    dfp_binop->op3_lo = op3_lo;
   5973    dfp_binop->rounding_mode = rounding_mode;
   5974 
   5975    return insn;
   5976 }
   5977 
   5978 
   5979 s390_insn *
   5980 s390_insn_dfp128_unop(UChar size, s390_dfp_unop_t tag, HReg dst,
   5981                       HReg op_hi, HReg op_lo)
   5982 {
   5983    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   5984 
   5985    /* destination is an 8 byte integer value */
   5986    vassert(size == 8);
   5987    vassert(is_valid_fp128_regpair(op_hi, op_lo));
   5988 
   5989    insn->tag  = S390_INSN_DFP_UNOP;
   5990    insn->size = size;
   5991    insn->variant.dfp_unop.tag = tag;
   5992    insn->variant.dfp_unop.dst_hi = dst;
   5993    insn->variant.dfp_unop.dst_lo = INVALID_HREG;
   5994    insn->variant.dfp_unop.op_hi = op_hi;
   5995    insn->variant.dfp_unop.op_lo = op_lo;
   5996 
   5997    return insn;
   5998 }
   5999 
   6000 
   6001 s390_insn *
   6002 s390_insn_dfp128_intop(UChar size, s390_dfp_intop_t tag, HReg dst_hi,
   6003                        HReg dst_lo, HReg op2, HReg op3_hi, HReg op3_lo)
   6004 {
   6005    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   6006 
   6007    vassert(size == 16);
   6008    vassert(is_valid_fp128_regpair(dst_hi, dst_lo));
   6009    vassert(is_valid_fp128_regpair(op3_hi, op3_lo));
   6010 
   6011    insn->tag  = S390_INSN_DFP_INTOP;
   6012    insn->size = size;
   6013    insn->variant.dfp_intop.tag = tag;
   6014    insn->variant.dfp_intop.dst_hi = dst_hi;
   6015    insn->variant.dfp_intop.dst_lo = dst_lo;
   6016    insn->variant.dfp_intop.op2    = op2;
   6017    insn->variant.dfp_intop.op3_hi = op3_hi;
   6018    insn->variant.dfp_intop.op3_lo = op3_lo;
   6019 
   6020    return insn;
   6021 }
   6022 
   6023 
   6024 s390_insn *
   6025 s390_insn_dfp128_compare(UChar size, s390_dfp_cmp_t tag, HReg dst, HReg op1_hi,
   6026                          HReg op1_lo, HReg op2_hi, HReg op2_lo)
   6027 {
   6028    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   6029 
   6030    vassert(size == 16);
   6031    vassert(is_valid_fp128_regpair(op1_hi, op1_lo));
   6032    vassert(is_valid_fp128_regpair(op2_hi, op2_lo));
   6033 
   6034    insn->tag  = S390_INSN_DFP_COMPARE;
   6035    insn->size = size;
   6036    insn->variant.dfp_compare.tag = tag;
   6037    insn->variant.dfp_compare.dst = dst;
   6038    insn->variant.dfp_compare.op1_hi = op1_hi;
   6039    insn->variant.dfp_compare.op1_lo = op1_lo;
   6040    insn->variant.dfp_compare.op2_hi = op2_hi;
   6041    insn->variant.dfp_compare.op2_lo = op2_lo;
   6042 
   6043    return insn;
   6044 }
   6045 
   6046 
   6047 static s390_insn *
   6048 s390_insn_dfp128_convert(UChar size, s390_dfp_conv_t tag, HReg dst_hi,
   6049                          HReg dst_lo, HReg op_hi, HReg op_lo,
   6050                          s390_dfp_round_t rounding_mode)
   6051 {
   6052    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   6053 
   6054    if (size == 16) {
   6055       /* From smaller size to 16 bytes */
   6056       vassert(is_valid_fp128_regpair(dst_hi, dst_lo));
   6057       vassert(hregIsInvalid(op_lo));
   6058    } else {
   6059       /* From 16 bytes to smaller size */
   6060       vassert(is_valid_fp128_regpair(op_hi, op_lo));
   6061    }
   6062 
   6063    insn->tag  = S390_INSN_DFP_CONVERT;
   6064    insn->size = size;
   6065    insn->variant.dfp_convert.tag = tag;
   6066    insn->variant.dfp_convert.dst_hi = dst_hi;
   6067    insn->variant.dfp_convert.dst_lo = dst_lo;
   6068    insn->variant.dfp_convert.op_hi = op_hi;
   6069    insn->variant.dfp_convert.op_lo = op_lo;
   6070    insn->variant.dfp_convert.rounding_mode = rounding_mode;
   6071 
   6072    return insn;
   6073 }
   6074 
   6075 
   6076 s390_insn *
   6077 s390_insn_dfp128_convert_to(UChar size, s390_dfp_conv_t tag, HReg dst_hi,
   6078                             HReg dst_lo, HReg op)
   6079 {
   6080    /* Conversion to dfp128 never requires a rounding mode. Provide default
   6081       rounding mode. It will not be used when emitting insns. */
   6082    s390_dfp_round_t rounding_mode = S390_DFP_ROUND_NEAREST_EVEN_4;
   6083 
   6084    return s390_insn_dfp128_convert(size, tag, dst_hi, dst_lo, op,
   6085                                    INVALID_HREG, rounding_mode);
   6086 }
   6087 
   6088 
   6089 s390_insn *
   6090 s390_insn_dfp128_convert_from(UChar size, s390_dfp_conv_t tag, HReg dst_hi,
   6091                               HReg dst_lo, HReg op_hi, HReg op_lo,
   6092                               s390_dfp_round_t rounding_mode)
   6093 {
   6094    return s390_insn_dfp128_convert(size, tag, dst_hi, dst_lo, op_hi, op_lo,
   6095                                    rounding_mode);
   6096 }
   6097 
   6098 
   6099 s390_insn *
   6100 s390_insn_dfp128_reround(UChar size, HReg dst_hi, HReg dst_lo, HReg op2,
   6101                          HReg op3_hi, HReg op3_lo,
   6102                          s390_dfp_round_t rounding_mode)
   6103 {
   6104    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   6105 
   6106    vassert(size == 16);
   6107    vassert(is_valid_fp128_regpair(dst_hi, dst_lo));
   6108    vassert(is_valid_fp128_regpair(op3_hi, op3_lo));
   6109 
   6110    insn->tag  = S390_INSN_DFP_REROUND;
   6111    insn->size = size;
   6112    insn->variant.dfp_reround.dst_hi = dst_hi;
   6113    insn->variant.dfp_reround.dst_lo = dst_lo;
   6114    insn->variant.dfp_reround.op2    = op2;
   6115    insn->variant.dfp_reround.op3_hi = op3_hi;
   6116    insn->variant.dfp_reround.op3_lo = op3_lo;
   6117    insn->variant.dfp_reround.rounding_mode = rounding_mode;
   6118 
   6119    return insn;
   6120 }
   6121 
   6122 
   6123 s390_insn *
   6124 s390_insn_mfence(void)
   6125 {
   6126    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   6127 
   6128    insn->tag  = S390_INSN_MFENCE;
   6129    insn->size = 0;   /* not needed */
   6130 
   6131    return insn;
   6132 }
   6133 
   6134 
   6135 s390_insn *
   6136 s390_insn_mimm(UChar size, s390_amode *dst, ULong value)
   6137 {
   6138    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   6139 
   6140    /* This insn will be mapped to insns that require base register
   6141       plus 12-bit displacement */
   6142    vassert(dst->tag == S390_AMODE_B12);
   6143 
   6144    insn->tag  = S390_INSN_MIMM;
   6145    insn->size = size;
   6146    insn->variant.mimm.dst = dst;
   6147    insn->variant.mimm.value = value;
   6148 
   6149    return insn;
   6150 }
   6151 
   6152 
   6153 s390_insn *
   6154 s390_insn_madd(UChar size, s390_amode *dst, UChar delta, ULong value)
   6155 {
   6156    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   6157 
   6158    vassert(size == 4 || size == 8);
   6159 
   6160    /* This insn will be mapped to an ASI or AGSI so we can only allow base
   6161       register plus 12-bit / 20-bit displacement. */
   6162    vassert(dst->tag == S390_AMODE_B12 || dst->tag == S390_AMODE_B20);
   6163    /* ASI and AGSI require the GIE facility */
   6164    vassert(s390_host_has_gie);
   6165 
   6166    insn->tag  = S390_INSN_MADD;
   6167    insn->size = size;
   6168    insn->variant.madd.dst   = dst;
   6169    insn->variant.madd.delta = delta;
   6170    insn->variant.madd.value = value;
   6171 
   6172    return insn;
   6173 }
   6174 
   6175 
   6176 s390_insn *
   6177 s390_insn_set_fpc_bfprm(UChar size, HReg mode)
   6178 {
   6179    vassert(size == 4);
   6180 
   6181    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   6182 
   6183    insn->tag  = S390_INSN_SET_FPC_BFPRM;
   6184    insn->size = size;
   6185    insn->variant.set_fpc_bfprm.mode = mode;
   6186 
   6187    return insn;
   6188 }
   6189 
   6190 
   6191 s390_insn *
   6192 s390_insn_set_fpc_dfprm(UChar size, HReg mode)
   6193 {
   6194    vassert(size == 4);
   6195 
   6196    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   6197 
   6198    insn->tag  = S390_INSN_SET_FPC_DFPRM;
   6199    insn->size = size;
   6200    insn->variant.set_fpc_dfprm.mode = mode;
   6201 
   6202    return insn;
   6203 }
   6204 
   6205 
   6206 s390_insn *
   6207 s390_insn_xdirect(s390_cc_t cond, Addr64 dst, s390_amode *guest_IA,
   6208                   Bool to_fast_entry)
   6209 {
   6210    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   6211 
   6212    vassert(guest_IA->tag == S390_AMODE_B12);
   6213 
   6214    insn->tag  = S390_INSN_XDIRECT;
   6215    insn->size = 0;   /* does not matter */
   6216 
   6217    insn->variant.xdirect.cond = cond;
   6218    insn->variant.xdirect.dst = dst;
   6219    insn->variant.xdirect.guest_IA = guest_IA;
   6220    insn->variant.xdirect.to_fast_entry = to_fast_entry;
   6221 
   6222    return insn;
   6223 }
   6224 
   6225 
   6226 s390_insn *
   6227 s390_insn_xindir(s390_cc_t cond, HReg dst, s390_amode *guest_IA)
   6228 {
   6229    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   6230 
   6231    vassert(guest_IA->tag == S390_AMODE_B12);
   6232 
   6233    insn->tag  = S390_INSN_XINDIR;
   6234    insn->size = 0;   /* does not matter */
   6235 
   6236    insn->variant.xindir.cond = cond;
   6237    insn->variant.xindir.dst = dst;
   6238    insn->variant.xindir.guest_IA = guest_IA;
   6239 
   6240    return insn;
   6241 }
   6242 
   6243 
   6244 s390_insn *
   6245 s390_insn_xassisted(s390_cc_t cond, HReg dst, s390_amode *guest_IA,
   6246                     IRJumpKind kind)
   6247 {
   6248    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   6249 
   6250    vassert(guest_IA->tag == S390_AMODE_B12);
   6251 
   6252    insn->tag  = S390_INSN_XASSISTED;
   6253    insn->size = 0;   /* does not matter */
   6254 
   6255    insn->variant.xassisted.cond = cond;
   6256    insn->variant.xassisted.dst = dst;
   6257    insn->variant.xassisted.guest_IA = guest_IA;
   6258    insn->variant.xassisted.kind = kind;
   6259 
   6260    return insn;
   6261 }
   6262 
   6263 
   6264 s390_insn *
   6265 s390_insn_evcheck(s390_amode *counter, s390_amode *fail_addr)
   6266 {
   6267    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   6268 
   6269    vassert(counter->tag   == S390_AMODE_B12);
   6270    vassert(fail_addr->tag == S390_AMODE_B12);
   6271 
   6272    insn->tag  = S390_INSN_EVCHECK;
   6273    insn->size = 0;   /* does not matter */
   6274 
   6275    insn->variant.evcheck.counter = counter;
   6276    insn->variant.evcheck.fail_addr = fail_addr;
   6277 
   6278    return insn;
   6279 }
   6280 
   6281 
   6282 s390_insn *
   6283 s390_insn_profinc(void)
   6284 {
   6285    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
   6286 
   6287    insn->tag  = S390_INSN_PROFINC;
   6288    insn->size = 0;   /* does not matter */
   6289 
   6290    return insn;
   6291 }
   6292 
   6293 
   6294 /*---------------------------------------------------------------*/
   6295 /*--- Debug print                                             ---*/
   6296 /*---------------------------------------------------------------*/
   6297 
   6298 static const HChar *
   6299 s390_cc_as_string(s390_cc_t cc)
   6300 {
   6301    switch (cc) {
   6302    case S390_CC_NEVER:  return "never";
   6303    case S390_CC_OVFL:   return "overflow";
   6304    case S390_CC_H:      return "greater than";     /* A > B ; high */
   6305    case S390_CC_NLE:    return "not low or equal";
   6306    case S390_CC_L:      return "less than";        /* A < B ; low */
   6307    case S390_CC_NHE:    return "not high or equal";
   6308    case S390_CC_LH:     return "low or high";
   6309    case S390_CC_NE:     return "not equal";        /* A != B ; not zero */
   6310    case S390_CC_E:      return "equal";            /* A == B ; zero */
   6311    case S390_CC_NLH:    return "not low or high";
   6312    case S390_CC_HE:     return "greater or equal"; /* A >= B ; high or equal*/
   6313    case S390_CC_NL:     return "not low";          /* not low */
   6314    case S390_CC_LE:     return "less or equal";    /* A <= B ; low or equal */
   6315    case S390_CC_NH:     return "not high";
   6316    case S390_CC_NO:     return "not overflow";
   6317    case S390_CC_ALWAYS: return "always";
   6318    default:
   6319       vpanic("s390_cc_as_string");
   6320    }
   6321 }
   6322 
   6323 
   6324 static const HChar *
   6325 s390_jump_kind_as_string(IRJumpKind kind)
   6326 {
   6327    switch (kind) {
   6328    case Ijk_Boring:      return "Boring";
   6329    case Ijk_Call:        return "Call";
   6330    case Ijk_Ret:         return "Return";
   6331    case Ijk_ClientReq:   return "ClientReq";
   6332    case Ijk_Yield:       return "Yield";
   6333    case Ijk_EmWarn:      return "EmWarn";
   6334    case Ijk_EmFail:      return "EmFail";
   6335    case Ijk_NoDecode:    return "NoDecode";
   6336    case Ijk_MapFail:     return "MapFail";
   6337    case Ijk_InvalICache: return "Invalidate";
   6338    case Ijk_NoRedir:     return "NoRedir";
   6339    case Ijk_SigTRAP:     return "SigTRAP";
   6340    case Ijk_SigSEGV:     return "SigSEGV";
   6341    case Ijk_SigBUS:      return "SigBUS";
   6342    case Ijk_Sys_syscall: return "Sys_syscall";
   6343    default:
   6344       vpanic("s390_jump_kind_as_string");
   6345    }
   6346 }
   6347 
   6348 
   6349 /* Helper function for writing out a V insn */
   6350 static void
   6351 s390_sprintf(HChar *buf, const HChar *fmt, ...)
   6352 {
   6353    HChar *p;
   6354    ULong value;
   6355    va_list args;
   6356    va_start(args, fmt);
   6357 
   6358    p = buf;
   6359    for ( ; *fmt; ++fmt) {
   6360       Int c = *fmt;
   6361 
   6362       if (c != '%') {
   6363          *p++ = c;
   6364          continue;
   6365       }
   6366 
   6367       c = *++fmt;  /* next char */
   6368       switch (c) {
   6369       case '%':
   6370          *p++ = c;   /* %% */
   6371          continue;
   6372 
   6373       case 's':     /* %s */
   6374          p += vex_sprintf(p, "%s", va_arg(args, HChar *));
   6375          continue;
   6376 
   6377       case 'M':     /* %M = mnemonic */
   6378          p += vex_sprintf(p, "%-8s", va_arg(args, HChar *));
   6379          continue;
   6380 
   6381       case 'R':     /* %R = register */
   6382          p += vex_sprintf(p, "%s", s390_hreg_as_string(va_arg(args, HReg)));
   6383          continue;
   6384 
   6385       case 'A':     /* %A = amode */
   6386          p += vex_sprintf(p, "%s",
   6387                           s390_amode_as_string(va_arg(args, s390_amode *)));
   6388          continue;
   6389 
   6390       case 'G':     /* %G = guest state @ offset */
   6391          p += vex_sprintf(p, "guest[%d]", va_arg(args, UInt));
   6392          continue;
   6393 
   6394       case 'C':     /* %C = condition code */
   6395          p += vex_sprintf(p, "%s", s390_cc_as_string(va_arg(args, s390_cc_t)));
   6396          continue;
   6397 
   6398       case 'J':     /* &J = jump kind */
   6399          p += vex_sprintf(p, "%s",
   6400                           s390_jump_kind_as_string(va_arg(args, IRJumpKind)));
   6401          continue;
   6402 
   6403       case 'L': {   /* %L = argument list in helper call*/
   6404          UInt i, num_args;
   6405 
   6406          num_args = va_arg(args, UInt);
   6407 
   6408          for (i = 0; i < num_args; ++i) {
   6409             if (i != 0) p += vex_sprintf(p, ", ");
   6410             p += vex_sprintf(p, "r%d", s390_gprno_from_arg_index(i));
   6411          }
   6412          continue;
   6413       }
   6414 
   6415       case 'O': {   /* %O = RMI operand */
   6416          s390_opnd_RMI *op = va_arg(args, s390_opnd_RMI *);
   6417 
   6418          switch (op->tag) {
   6419          case S390_OPND_REG:
   6420             p += vex_sprintf(p, "%s", s390_hreg_as_string(op->variant.reg));
   6421             continue;
   6422 
   6423          case S390_OPND_AMODE:
   6424             p += vex_sprintf(p, "%s", s390_amode_as_string(op->variant.am));
   6425             continue;
   6426 
   6427          case S390_OPND_IMMEDIATE:
   6428             value = op->variant.imm;
   6429             goto print_value;
   6430 
   6431          default:
   6432             goto fail;
   6433          }
   6434       }
   6435 
   6436       case 'I':     /* %I = immediate value */
   6437          value = va_arg(args, ULong);
   6438          goto print_value;
   6439 
   6440       print_value:
   6441          if ((Long)value < 0)
   6442             p += vex_sprintf(p, "%lld", (Long)value);
   6443          else if (value < 100)
   6444             p += vex_sprintf(p, "%llu", value);
   6445          else
   6446             p += vex_sprintf(p, "0x%llx", value);
   6447          continue;
   6448 
   6449       default:
   6450          goto fail;
   6451       }
   6452    }
   6453    *p = '\0';
   6454    va_end(args);
   6455 
   6456    return;
   6457 
   6458  fail: vpanic("s390_printf");
   6459 }
   6460 
   6461 
   6462 /* Decompile the given insn into a static buffer and return it */
   6463 const HChar *
   6464 s390_insn_as_string(const s390_insn *insn)
   6465 {
   6466    static HChar buf[300];  // large enough
   6467    const HChar *op;
   6468    HChar *p;
   6469 
   6470    buf[0] = '\0';
   6471 
   6472    switch (insn->tag) {
   6473    case S390_INSN_LOAD:
   6474       s390_sprintf(buf, "%M %R,%A", "v-load", insn->variant.load.dst,
   6475                    insn->variant.load.src);
   6476       break;
   6477 
   6478    case S390_INSN_STORE:
   6479       s390_sprintf(buf, "%M %R,%A", "v-store", insn->variant.store.src,
   6480                    insn->variant.store.dst);
   6481       break;
   6482 
   6483    case S390_INSN_MOVE:
   6484       s390_sprintf(buf, "%M %R,%R", "v-move", insn->variant.move.dst,
   6485                    insn->variant.move.src);
   6486       break;
   6487 
   6488    case S390_INSN_MEMCPY:
   6489       s390_sprintf(buf, "%M %A,%A", "v-memcpy", insn->variant.memcpy.dst,
   6490                    insn->variant.memcpy.src);
   6491       break;
   6492 
   6493    case S390_INSN_COND_MOVE:
   6494       s390_sprintf(buf, "%M if (%C) %R,%O", "v-move",
   6495                    insn->variant.cond_move.cond, insn->variant.cond_move.dst,
   6496                    &insn->variant.cond_move.src);
   6497       break;
   6498 
   6499    case S390_INSN_LOAD_IMMEDIATE:
   6500       s390_sprintf(buf, "%M %R,%I", "v-loadi", insn->variant.load_immediate.dst,
   6501                    insn->variant.load_immediate.value);
   6502       break;
   6503 
   6504    case S390_INSN_ALU:
   6505       switch (insn->variant.alu.tag) {
   6506       case S390_ALU_ADD:  op = "v-add";  break;
   6507       case S390_ALU_SUB:  op = "v-sub";  break;
   6508       case S390_ALU_MUL:  op = "v-mul";  break;
   6509       case S390_ALU_AND:  op = "v-and";  break;
   6510       case S390_ALU_OR:   op = "v-or";   break;
   6511       case S390_ALU_XOR:  op = "v-xor";  break;
   6512       case S390_ALU_LSH:  op = "v-lsh";  break;
   6513       case S390_ALU_RSH:  op = "v-rsh";  break;
   6514       case S390_ALU_RSHA: op = "v-rsha"; break;
   6515       default: goto fail;
   6516       }
   6517       s390_sprintf(buf, "%M %R,%O", op, insn->variant.alu.dst, /* also op1 */
   6518                    &insn->variant.alu.op2);
   6519       break;
   6520 
   6521    case S390_INSN_SMUL:
   6522    case S390_INSN_UMUL:
   6523       if (insn->tag == S390_INSN_SMUL) {
   6524          op = "v-muls";
   6525       } else {
   6526          op = "v-mulu";
   6527       }
   6528       s390_sprintf(buf, "%M %R,%O", op, insn->variant.mul.dst_hi,
   6529                    &insn->variant.mul.op2);
   6530       break;
   6531 
   6532    case S390_INSN_SDIV:
   6533    case S390_INSN_UDIV:
   6534       if (insn->tag == S390_INSN_SDIV) {
   6535          op = "v-divs";
   6536       } else {
   6537          op = "v-divu";
   6538       }
   6539       s390_sprintf(buf, "%M %R,%O", op, insn->variant.div.op1_hi,
   6540                    &insn->variant.div.op2);
   6541       break;
   6542 
   6543    case S390_INSN_DIVS:
   6544       s390_sprintf(buf, "%M %R,%O", "v-divsi", insn->variant.divs.op1,
   6545                    &insn->variant.divs.op2);
   6546       break;
   6547 
   6548    case S390_INSN_CLZ:
   6549       s390_sprintf(buf, "%M %R,%O", "v-clz", insn->variant.clz.num_bits,
   6550                    &insn->variant.clz.src);
   6551       break;
   6552 
   6553    case S390_INSN_UNOP:
   6554       switch (insn->variant.unop.tag) {
   6555       case S390_ZERO_EXTEND_8:
   6556       case S390_ZERO_EXTEND_16:
   6557       case S390_ZERO_EXTEND_32:
   6558          op = "v-zerox";
   6559          break;
   6560 
   6561       case S390_SIGN_EXTEND_8:
   6562       case S390_SIGN_EXTEND_16:
   6563       case S390_SIGN_EXTEND_32:
   6564          op = "v-signx";
   6565          break;
   6566 
   6567       case S390_NEGATE:
   6568          op = "v-neg";
   6569          break;
   6570 
   6571       default:
   6572          goto fail;
   6573       }
   6574       s390_sprintf(buf, "%M %R,%O", op, insn->variant.unop.dst,
   6575                    &insn->variant.unop.src);
   6576       break;
   6577 
   6578    case S390_INSN_TEST:
   6579       s390_sprintf(buf, "%M %O", "v-test", &insn->variant.test.src);
   6580       break;
   6581 
   6582    case S390_INSN_CC2BOOL:
   6583       s390_sprintf(buf, "%M %R,%C", "v-cc2b", insn->variant.cc2bool.dst,
   6584                    insn->variant.cc2bool.cond);
   6585       break;
   6586 
   6587    case S390_INSN_CAS:
   6588       s390_sprintf(buf, "%M %R,%A,%R,%R", "v-cas", insn->variant.cas.op1,
   6589                    insn->variant.cas.op2, insn->variant.cas.op3,
   6590                    insn->variant.cas.old_mem);
   6591       break;
   6592 
   6593    case S390_INSN_CDAS: {
   6594       s390_cdas *cdas = insn->variant.cdas.details;
   6595 
   6596       s390_sprintf(buf, "%M %R,%R,%A,%R,%R,%R,%R", "v-cdas",
   6597                    cdas->op1_high, cdas->op1_low, cdas->op2, cdas->op3_high,
   6598                    cdas->op3_low, cdas->old_mem_high, cdas->old_mem_low);
   6599       break;
   6600    }
   6601 
   6602    case S390_INSN_COMPARE:
   6603       if (insn->variant.compare.signed_comparison) {
   6604          op = "v-cmps";
   6605       } else {
   6606          op = "v-cmpu";
   6607       }
   6608       s390_sprintf(buf, "%M %R,%O", op, insn->variant.compare.src1,
   6609                    &insn->variant.compare.src2);
   6610       break;
   6611 
   6612    case S390_INSN_HELPER_CALL: {
   6613       s390_helper_call *helper_call = insn->variant.helper_call.details;
   6614       s390_sprintf(buf, "%M if (%C) %s{%I}(%L)", "v-call",
   6615                    helper_call->cond,
   6616                    helper_call->name,
   6617                    helper_call->target,
   6618                    helper_call->num_args);
   6619       return buf;   /* avoid printing "size = ..." which is meaningless */
   6620    }
   6621 
   6622    case S390_INSN_BFP_TRIOP:
   6623       switch (insn->variant.bfp_triop.tag) {
   6624       case S390_BFP_MADD:  op = "v-fmadd";  break;
   6625       case S390_BFP_MSUB:  op = "v-fmsub";  break;
   6626       default: goto fail;
   6627       }
   6628       s390_sprintf(buf, "%M %R,%R,%R", op,
   6629                    insn->variant.bfp_triop.dst  /* op1 same as dst */,
   6630                    insn->variant.bfp_triop.op2, insn->variant.bfp_triop.op3);
   6631       break;
   6632 
   6633    case S390_INSN_BFP_BINOP:
   6634       switch (insn->variant.bfp_binop.tag) {
   6635       case S390_BFP_ADD:      op = "v-fadd";  break;
   6636       case S390_BFP_SUB:      op = "v-fsub";  break;
   6637       case S390_BFP_MUL:      op = "v-fmul";  break;
   6638       case S390_BFP_DIV:      op = "v-fdiv";  break;
   6639       default: goto fail;
   6640       }
   6641       s390_sprintf(buf, "%M %R,%R", op,
   6642                    insn->variant.bfp_binop.dst_hi  /* op1 same as dst */,
   6643                    insn->variant.bfp_binop.op2_hi);
   6644       break;
   6645 
   6646    case S390_INSN_BFP_COMPARE:
   6647       s390_sprintf(buf, "%M %R,%R,%R", "v-fcmp", insn->variant.bfp_compare.dst,
   6648                    insn->variant.bfp_compare.op1_hi,
   6649                    insn->variant.bfp_compare.op2_hi);
   6650       break;
   6651 
   6652    case S390_INSN_BFP_UNOP:
   6653       switch (insn->variant.bfp_unop.tag) {
   6654       case S390_BFP_ABS:         op = "v-fabs";  break;
   6655       case S390_BFP_NABS:        op = "v-fnabs"; break;
   6656       case S390_BFP_NEG:         op = "v-fneg";  break;
   6657       case S390_BFP_SQRT:        op = "v-fsqrt"; break;
   6658       default: goto fail;
   6659       }
   6660       s390_sprintf(buf, "%M %R,%R", op, insn->variant.bfp_unop.dst_hi,
   6661                    insn->variant.bfp_unop.op_hi);
   6662       break;
   6663 
   6664    case S390_INSN_BFP_CONVERT:
   6665       switch (insn->variant.bfp_convert.tag) {
   6666       case S390_BFP_I32_TO_F32:
   6667       case S390_BFP_I32_TO_F64:
   6668       case S390_BFP_I32_TO_F128:
   6669       case S390_BFP_I64_TO_F32:
   6670       case S390_BFP_I64_TO_F64:
   6671       case S390_BFP_I64_TO_F128: op = "v-i2f"; break;
   6672       case S390_BFP_U32_TO_F32:
   6673       case S390_BFP_U32_TO_F64:
   6674       case S390_BFP_U32_TO_F128:
   6675       case S390_BFP_U64_TO_F32:
   6676       case S390_BFP_U64_TO_F64:
   6677       case S390_BFP_U64_TO_F128: op = "v-u2f"; break;
   6678       case S390_BFP_F32_TO_I32:
   6679       case S390_BFP_F32_TO_I64:
   6680       case S390_BFP_F64_TO_I32:
   6681       case S390_BFP_F64_TO_I64:
   6682       case S390_BFP_F128_TO_I32:
   6683       case S390_BFP_F128_TO_I64: op = "v-f2i"; break;
   6684       case S390_BFP_F32_TO_U32:
   6685       case S390_BFP_F32_TO_U64:
   6686       case S390_BFP_F64_TO_U32:
   6687       case S390_BFP_F64_TO_U64:
   6688       case S390_BFP_F128_TO_U32:
   6689       case S390_BFP_F128_TO_U64: op = "v-f2u"; break;
   6690       case S390_BFP_F32_TO_F64:
   6691       case S390_BFP_F32_TO_F128:
   6692       case S390_BFP_F64_TO_F32:
   6693       case S390_BFP_F64_TO_F128:
   6694       case S390_BFP_F128_TO_F32:
   6695       case S390_BFP_F128_TO_F64: op = "v-f2f"; break;
   6696       default: goto fail;
   6697       }
   6698       s390_sprintf(buf, "%M %R,%R", op, insn->variant.bfp_convert.dst_hi,
   6699                    insn->variant.bfp_convert.op_hi);
   6700       break;
   6701 
   6702    case S390_INSN_DFP_BINOP: {
   6703       s390_dfp_binop *dfp_binop = insn->variant.dfp_binop.details;
   6704 
   6705       switch (dfp_binop->tag) {
   6706       case S390_DFP_ADD:  op = "v-dadd";  break;
   6707       case S390_DFP_SUB:  op = "v-dsub";  break;
   6708       case S390_DFP_MUL:  op = "v-dmul";  break;
   6709       case S390_DFP_DIV:  op = "v-ddiv";  break;
   6710       case S390_DFP_QUANTIZE:  op = "v-dqua";  break;
   6711       default: goto fail;
   6712       }
   6713       s390_sprintf(buf, "%M %R,%R,%R", op, dfp_binop->dst_hi,
   6714                    dfp_binop->op2_hi, dfp_binop->op3_hi);
   6715       break;
   6716    }
   6717 
   6718    case S390_INSN_DFP_UNOP:
   6719       switch (insn->variant.dfp_unop.tag) {
   6720       case S390_DFP_EXTRACT_EXP_D64:
   6721       case S390_DFP_EXTRACT_EXP_D128:  op = "v-d2exp";  break;
   6722       case S390_DFP_EXTRACT_SIG_D64:
   6723       case S390_DFP_EXTRACT_SIG_D128:  op = "v-d2sig";  break;
   6724       default: goto fail;
   6725       }
   6726       s390_sprintf(buf, "%M %R,%R", op, insn->variant.dfp_unop.dst_hi,
   6727                    insn->variant.dfp_unop.op_hi);
   6728       break;
   6729 
   6730    case S390_INSN_DFP_INTOP:
   6731       switch (insn->variant.dfp_intop.tag) {
   6732       case S390_DFP_SHIFT_LEFT:  op = "v-dshl"; break;
   6733       case S390_DFP_SHIFT_RIGHT: op = "v-dshr"; break;
   6734       case S390_DFP_INSERT_EXP:  op = "v-diexp"; break;
   6735       default: goto fail;
   6736       }
   6737       s390_sprintf(buf, "%M %R,%R,%R", op, insn->variant.dfp_intop.dst_hi,
   6738                    insn->variant.dfp_intop.op2,
   6739                    insn->variant.dfp_intop.op3_hi);
   6740       break;
   6741 
   6742    case S390_INSN_DFP_COMPARE:
   6743       switch (insn->variant.dfp_compare.tag) {
   6744       case S390_DFP_COMPARE:     op = "v-dcmp"; break;
   6745       case S390_DFP_COMPARE_EXP: op = "v-dcmpexp"; break;
   6746       default: goto fail;
   6747       }
   6748       s390_sprintf(buf, "%M %R,%R,%R", op, insn->variant.dfp_compare.dst,
   6749                    insn->variant.dfp_compare.op1_hi,
   6750                    insn->variant.dfp_compare.op2_hi);
   6751       break;
   6752 
   6753    case S390_INSN_DFP_CONVERT:
   6754       switch (insn->variant.dfp_convert.tag) {
   6755       case S390_DFP_D32_TO_D64:
   6756       case S390_DFP_D64_TO_D32:
   6757       case S390_DFP_D64_TO_D128:
   6758       case S390_DFP_D128_TO_D64: op = "v-d2d"; break;
   6759       case S390_DFP_I32_TO_D64:
   6760       case S390_DFP_I32_TO_D128:
   6761       case S390_DFP_I64_TO_D64:
   6762       case S390_DFP_I64_TO_D128: op = "v-i2d"; break;
   6763       case S390_DFP_U32_TO_D64:
   6764       case S390_DFP_U32_TO_D128:
   6765       case S390_DFP_U64_TO_D64:
   6766       case S390_DFP_U64_TO_D128: op = "v-u2d"; break;
   6767       case S390_DFP_D64_TO_I32:
   6768       case S390_DFP_D128_TO_I32:
   6769       case S390_DFP_D64_TO_I64:
   6770       case S390_DFP_D128_TO_I64: op = "v-d2i"; break;
   6771       case S390_DFP_D64_TO_U32:
   6772       case S390_DFP_D64_TO_U64:
   6773       case S390_DFP_D128_TO_U32:
   6774       case S390_DFP_D128_TO_U64: op = "v-d2u"; break;
   6775       default: goto fail;
   6776       }
   6777       s390_sprintf(buf, "%M %R,%R", op, insn->variant.dfp_convert.dst_hi,
   6778                    insn->variant.dfp_convert.op_hi);
   6779       break;
   6780 
   6781    case S390_INSN_DFP_REROUND:
   6782       s390_sprintf(buf, "%M %R,%R,%R", "v-drrnd",
   6783                    insn->variant.dfp_reround.dst_hi,
   6784                    insn->variant.dfp_reround.op2,
   6785                    insn->variant.dfp_reround.op3_hi);
   6786       break;
   6787 
   6788    case S390_INSN_FP_CONVERT: {
   6789       s390_fp_convert *fp_convert = insn->variant.fp_convert.details;
   6790 
   6791       switch (fp_convert->tag) {
   6792       case S390_FP_F32_TO_D32:
   6793       case S390_FP_F32_TO_D64:
   6794       case S390_FP_F32_TO_D128:
   6795       case S390_FP_F64_TO_D32:
   6796       case S390_FP_F64_TO_D64:
   6797       case S390_FP_F64_TO_D128:
   6798       case S390_FP_F128_TO_D32:
   6799       case S390_FP_F128_TO_D64:
   6800       case S390_FP_F128_TO_D128: op = "v-f2d"; break;
   6801       case S390_FP_D32_TO_F32:
   6802       case S390_FP_D32_TO_F64:
   6803       case S390_FP_D32_TO_F128:
   6804       case S390_FP_D64_TO_F32:
   6805       case S390_FP_D64_TO_F64:
   6806       case S390_FP_D64_TO_F128:
   6807       case S390_FP_D128_TO_F32:
   6808       case S390_FP_D128_TO_F64:
   6809       case S390_FP_D128_TO_F128: op = "v-d2f"; break;
   6810       default: goto fail;
   6811       }
   6812       s390_sprintf(buf, "%M %R,%R", op, fp_convert->dst_hi,
   6813                    fp_convert->op_hi);
   6814       break;
   6815    }
   6816 
   6817    case S390_INSN_MFENCE:
   6818       s390_sprintf(buf, "%M", "v-mfence");
   6819       return buf;   /* avoid printing "size = ..." which is meaningless */
   6820 
   6821    case S390_INSN_MIMM:
   6822       s390_sprintf(buf, "%M %A,%I", "v-mimm", insn->variant.mimm.dst,
   6823                    insn->variant.mimm.value);
   6824       break;
   6825 
   6826    case S390_INSN_MADD:
   6827       s390_sprintf(buf, "%M %A += %I  (= %I)", "v-madd",
   6828                    insn->variant.madd.dst,
   6829                    (Long)(Char)insn->variant.madd.delta,
   6830                    insn->variant.madd.value);
   6831       break;
   6832 
   6833    case S390_INSN_SET_FPC_BFPRM:
   6834       s390_sprintf(buf, "%M %R", "v-set-fpc-bfprm",
   6835                    insn->variant.set_fpc_bfprm.mode);
   6836       break;
   6837 
   6838    case S390_INSN_SET_FPC_DFPRM:
   6839       s390_sprintf(buf, "%M %R", "v-set-fpc-dfprm",
   6840                    insn->variant.set_fpc_dfprm.mode);
   6841       break;
   6842 
   6843    case S390_INSN_EVCHECK:
   6844       s390_sprintf(buf, "%M counter = %A, fail-addr = %A", "v-evcheck",
   6845                    insn->variant.evcheck.counter,
   6846                    insn->variant.evcheck.fail_addr);
   6847       return buf;   /* avoid printing "size = ..." which is meaningless */
   6848 
   6849    case S390_INSN_PROFINC:
   6850       s390_sprintf(buf, "%M", "v-profinc");
   6851       return buf;   /* avoid printing "size = ..." which is meaningless */
   6852 
   6853    case S390_INSN_XDIRECT:
   6854       s390_sprintf(buf, "%M if (%C) %A = %I  %s", "v-xdirect",
   6855                    insn->variant.xdirect.cond,
   6856                    insn->variant.xdirect.guest_IA,
   6857                    insn->variant.xdirect.dst,
   6858                    insn->variant.xdirect.to_fast_entry ? "fast" : "slow");
   6859       return buf;   /* avoid printing "size = ..." which is meaningless */
   6860 
   6861    case S390_INSN_XINDIR:
   6862       s390_sprintf(buf, "%M if (%C) %A = %R", "v-xindir",
   6863                    insn->variant.xindir.cond,
   6864                    insn->variant.xindir.guest_IA,
   6865                    insn->variant.xindir.dst);
   6866       return buf;   /* avoid printing "size = ..." which is meaningless */
   6867 
   6868    case S390_INSN_XASSISTED:
   6869       s390_sprintf(buf, "%M if (%C) %J %A = %R", "v-xassisted",
   6870                    insn->variant.xassisted.cond,
   6871                    insn->variant.xassisted.kind,
   6872                    insn->variant.xassisted.guest_IA,
   6873                    insn->variant.xassisted.dst);
   6874       return buf;   /* avoid printing "size = ..." which is meaningless */
   6875 
   6876    default: goto fail;
   6877    }
   6878 
   6879    /* Write out how many bytes are involved in the operation */
   6880 
   6881    {
   6882       UInt len, i;
   6883 
   6884       for (p = buf; *p; ++p)
   6885          continue;
   6886 
   6887       len = p - buf;
   6888 
   6889       if (len < 32) {
   6890          for (i = len; i < 32; ++i)
   6891             p += vex_sprintf(p, " ");
   6892       } else {
   6893          p += vex_sprintf(p, "\t");
   6894       }
   6895    }
   6896 
   6897    /* Special cases first */
   6898    switch (insn->tag) {
   6899    case S390_INSN_UNOP:
   6900       switch (insn->variant.unop.tag) {
   6901       case S390_SIGN_EXTEND_8:
   6902       case S390_ZERO_EXTEND_8:  p += vex_sprintf(p, "1 -> "); goto common;
   6903       case S390_SIGN_EXTEND_16:
   6904       case S390_ZERO_EXTEND_16: p += vex_sprintf(p, "2 -> "); goto common;
   6905       case S390_SIGN_EXTEND_32:
   6906       case S390_ZERO_EXTEND_32: p += vex_sprintf(p, "4 -> "); goto common;
   6907       default:
   6908          goto common;
   6909       }
   6910 
   6911    case S390_INSN_BFP_CONVERT:
   6912       switch (insn->variant.bfp_convert.tag) {
   6913       case S390_BFP_I32_TO_F32:
   6914       case S390_BFP_I32_TO_F64:
   6915       case S390_BFP_I32_TO_F128:
   6916       case S390_BFP_U32_TO_F32:
   6917       case S390_BFP_U32_TO_F64:
   6918       case S390_BFP_U32_TO_F128:
   6919       case S390_BFP_F32_TO_I32:
   6920       case S390_BFP_F32_TO_I64:
   6921       case S390_BFP_F32_TO_U32:
   6922       case S390_BFP_F32_TO_U64:
   6923       case S390_BFP_F32_TO_F64:
   6924       case S390_BFP_F32_TO_F128: p += vex_sprintf(p, "4 -> "); goto common;
   6925       case S390_BFP_I64_TO_F32:
   6926       case S390_BFP_I64_TO_F64:
   6927       case S390_BFP_I64_TO_F128:
   6928       case S390_BFP_U64_TO_F32:
   6929       case S390_BFP_U64_TO_F64:
   6930       case S390_BFP_U64_TO_F128:
   6931       case S390_BFP_F64_TO_I32:
   6932       case S390_BFP_F64_TO_I64:
   6933       case S390_BFP_F64_TO_U32:
   6934       case S390_BFP_F64_TO_U64:
   6935       case S390_BFP_F64_TO_F32:
   6936       case S390_BFP_F64_TO_F128: p += vex_sprintf(p, "8 -> "); goto common;
   6937       case S390_BFP_F128_TO_I32:
   6938       case S390_BFP_F128_TO_I64:
   6939       case S390_BFP_F128_TO_U32:
   6940       case S390_BFP_F128_TO_U64:
   6941       case S390_BFP_F128_TO_F32:
   6942       case S390_BFP_F128_TO_F64: p += vex_sprintf(p, "16 -> "); goto common;
   6943       default:
   6944          goto common;
   6945       }
   6946 
   6947    case S390_INSN_DFP_CONVERT:
   6948       switch (insn->variant.dfp_convert.tag) {
   6949       case S390_DFP_D32_TO_D64:
   6950       case S390_DFP_I32_TO_D64:
   6951       case S390_DFP_I32_TO_D128:
   6952       case S390_DFP_U32_TO_D64:
   6953       case S390_DFP_U32_TO_D128: p += vex_sprintf(p, "4 -> "); goto common;
   6954       case S390_DFP_D64_TO_D32:
   6955       case S390_DFP_D64_TO_D128:
   6956       case S390_DFP_I64_TO_D64:
   6957       case S390_DFP_I64_TO_D128:
   6958       case S390_DFP_U64_TO_D64:
   6959       case S390_DFP_U64_TO_D128:
   6960       case S390_DFP_D64_TO_I32:
   6961       case S390_DFP_D64_TO_I64:
   6962       case S390_DFP_D64_TO_U32:
   6963       case S390_DFP_D64_TO_U64:  p += vex_sprintf(p, "8 -> "); goto common;
   6964       case S390_DFP_D128_TO_D64:
   6965       case S390_DFP_D128_TO_I32:
   6966       case S390_DFP_D128_TO_I64:
   6967       case S390_DFP_D128_TO_U32:
   6968       case S390_DFP_D128_TO_U64: p += vex_sprintf(p, "16 -> "); goto common;
   6969       default:
   6970          goto common;
   6971       }
   6972 
   6973    case S390_INSN_FP_CONVERT: {
   6974       s390_fp_convert *fp_convert = insn->variant.fp_convert.details;
   6975 
   6976       switch (fp_convert->tag) {
   6977       case S390_FP_F32_TO_D32:
   6978       case S390_FP_F32_TO_D64:
   6979       case S390_FP_F32_TO_D128:
   6980       case S390_FP_D32_TO_F32:
   6981       case S390_FP_D32_TO_F64:
   6982       case S390_FP_D32_TO_F128:  p += vex_sprintf(p, "4 -> "); goto common;
   6983       case S390_FP_F64_TO_D32:
   6984       case S390_FP_F64_TO_D64:
   6985       case S390_FP_F64_TO_D128:
   6986       case S390_FP_D64_TO_F32:
   6987       case S390_FP_D64_TO_F64:
   6988       case S390_FP_D64_TO_F128:  p += vex_sprintf(p, "8 -> "); goto common;
   6989       case S390_FP_F128_TO_D32:
   6990       case S390_FP_F128_TO_D64:
   6991       case S390_FP_F128_TO_D128:
   6992       case S390_FP_D128_TO_F32:
   6993       case S390_FP_D128_TO_F64:
   6994       case S390_FP_D128_TO_F128: p += vex_sprintf(p, "16 -> "); goto common;
   6995       default:
   6996          goto common;
   6997       }
   6998    }
   6999 
   7000    default:
   7001       goto common;
   7002    }
   7003 
   7004    /* Common case */
   7005  common:
   7006    vex_sprintf(p, "%u bytes", (UInt)insn->size);
   7007 
   7008    return buf;
   7009 
   7010  fail: vpanic("s390_insn_as_string");
   7011 }
   7012 
   7013 
   7014 
   7015 /* Load NUM bytes from memory into register REG using addressing mode AM. */
   7016 static UChar *
   7017 s390_emit_load_mem(UChar *p, UInt num, UChar reg, const s390_amode *am)
   7018 {
   7019    UInt b = hregNumber(am->b);
   7020    UInt x = hregNumber(am->x);  /* 0 for B12 and B20 */
   7021    UInt d = am->d;
   7022 
   7023    switch (am->tag) {
   7024    case S390_AMODE_B12:
   7025    case S390_AMODE_BX12:
   7026       switch (num) {
   7027       case 1: return s390_emit_IC(p, reg, x, b, d);
   7028       case 2: return s390_emit_LH(p, reg, x, b, d);
   7029       case 4: return s390_emit_L(p, reg, x, b, d);
   7030       case 8: return s390_emit_LG(p, reg, x, b, DISP20(d));
   7031       default: goto fail;
   7032       }
   7033       break;
   7034 
   7035    case S390_AMODE_B20:
   7036    case S390_AMODE_BX20:
   7037       switch (num) {
   7038       case 1: return s390_emit_ICY(p, reg, x, b, DISP20(d));
   7039       case 2: return s390_emit_LHY(p, reg, x, b, DISP20(d));
   7040       case 4: return s390_emit_LY(p, reg, x, b, DISP20(d));
   7041       case 8: return s390_emit_LG(p, reg, x, b, DISP20(d));
   7042       default: goto fail;
   7043       }
   7044       break;
   7045 
   7046    default: goto fail;
   7047    }
   7048 
   7049  fail:
   7050    vpanic("s390_emit_load_mem");
   7051 }
   7052 
   7053 
   7054 /* Load condition code into register REG */
   7055 static UChar *
   7056 s390_emit_load_cc(UChar *p, UChar reg)
   7057 {
   7058    p = s390_emit_LGHI(p, reg, 0);  /* Clear out, cc not affected */
   7059    p = s390_emit_IPM(p, reg, reg);
   7060    /* Shift 28 bits to the right --> [0,1,2,3] */
   7061    return s390_emit_SRL(p, reg, 0, 28); /* REG = cc */
   7062 }
   7063 
   7064 
   7065 /*---------------------------------------------------------------*/
   7066 /*--- Code generation                                         ---*/
   7067 /*---------------------------------------------------------------*/
   7068 
   7069 /* Do not load more bytes than requested. */
   7070 static UChar *
   7071 s390_insn_load_emit(UChar *buf, const s390_insn *insn)
   7072 {
   7073    UInt r, x, b, d;
   7074    const s390_amode *src;
   7075 
   7076    src = insn->variant.load.src;
   7077 
   7078    r = hregNumber(insn->variant.load.dst);
   7079 
   7080    if (hregClass(insn->variant.load.dst) == HRcFlt64) {
   7081       b = hregNumber(src->b);
   7082       x = hregNumber(src->x);  /* 0 for B12 and B20 */
   7083       d = src->d;
   7084 
   7085       switch (insn->size) {
   7086 
   7087       case 4:
   7088          switch (src->tag) {
   7089          case S390_AMODE_B12:
   7090          case S390_AMODE_BX12:
   7091             return s390_emit_LE(buf, r, x, b, d);
   7092 
   7093          case S390_AMODE_B20:
   7094          case S390_AMODE_BX20:
   7095             return s390_emit_LEY(buf, r, x, b, DISP20(d));
   7096          }
   7097          break;
   7098 
   7099       case 8:
   7100          switch (src->tag) {
   7101          case S390_AMODE_B12:
   7102          case S390_AMODE_BX12:
   7103             return s390_emit_LD(buf, r, x, b, d);
   7104 
   7105          case S390_AMODE_B20:
   7106          case S390_AMODE_BX20:
   7107             return s390_emit_LDY(buf, r, x, b, DISP20(d));
   7108          }
   7109          break;
   7110       }
   7111       vpanic("s390_insn_load_emit");
   7112    }
   7113 
   7114    /* Integer stuff */
   7115    return s390_emit_load_mem(buf, insn->size, r, src);
   7116 }
   7117 
   7118 
   7119 static UChar *
   7120 s390_insn_store_emit(UChar *buf, const s390_insn *insn)
   7121 {
   7122    UInt r, x, b, d;
   7123    const s390_amode *dst;
   7124 
   7125    dst = insn->variant.store.dst;
   7126 
   7127    r = hregNumber(insn->variant.store.src);
   7128    b = hregNumber(dst->b);
   7129    x = hregNumber(dst->x);  /* 0 for B12 and B20 */
   7130    d = dst->d;
   7131 
   7132    if (hregClass(insn->variant.store.src) == HRcFlt64) {
   7133       switch (insn->size) {
   7134 
   7135       case 4:
   7136          switch (dst->tag) {
   7137          case S390_AMODE_B12:
   7138          case S390_AMODE_BX12:
   7139             return s390_emit_STE(buf, r, x, b, d);
   7140 
   7141          case S390_AMODE_B20:
   7142          case S390_AMODE_BX20:
   7143             return s390_emit_STEY(buf, r, x, b, DISP20(d));
   7144          }
   7145          break;
   7146 
   7147       case 8:
   7148          switch (dst->tag) {
   7149          case S390_AMODE_B12:
   7150          case S390_AMODE_BX12:
   7151             return s390_emit_STD(buf, r, x, b, d);
   7152 
   7153          case S390_AMODE_B20:
   7154          case S390_AMODE_BX20:
   7155             return s390_emit_STDY(buf, r, x, b, DISP20(d));
   7156          }
   7157          break;
   7158       }
   7159       vpanic("s390_insn_store_emit");
   7160    }
   7161 
   7162    /* Integer stuff */
   7163    switch (insn->size) {
   7164    case 1:
   7165       switch (dst->tag) {
   7166       case S390_AMODE_B12:
   7167       case S390_AMODE_BX12:
   7168          return s390_emit_STC(buf, r, x, b, d);
   7169 
   7170       case S390_AMODE_B20:
   7171       case S390_AMODE_BX20:
   7172          return s390_emit_STCY(buf, r, x, b, DISP20(d));
   7173       }
   7174       break;
   7175 
   7176    case 2:
   7177       switch (dst->tag) {
   7178       case S390_AMODE_B12:
   7179       case S390_AMODE_BX12:
   7180          return s390_emit_STH(buf, r, x, b, d);
   7181 
   7182       case S390_AMODE_B20:
   7183       case S390_AMODE_BX20:
   7184          return s390_emit_STHY(buf, r, x, b, DISP20(d));
   7185       }
   7186       break;
   7187 
   7188    case 4:
   7189       switch (dst->tag) {
   7190       case S390_AMODE_B12:
   7191       case S390_AMODE_BX12:
   7192          return s390_emit_ST(buf, r, x, b, d);
   7193 
   7194       case S390_AMODE_B20:
   7195       case S390_AMODE_BX20:
   7196          return s390_emit_STY(buf, r, x, b, DISP20(d));
   7197       }
   7198       break;
   7199 
   7200    case 8:
   7201       return s390_emit_STG(buf, r, x, b, DISP20(d));
   7202 
   7203    default:
   7204       break;
   7205    }
   7206 
   7207    vpanic("s390_insn_store_emit");
   7208 }
   7209 
   7210 
   7211 static UChar *
   7212 s390_insn_move_emit(UChar *buf, const s390_insn *insn)
   7213 {
   7214    UInt dst, src;
   7215    HRegClass dst_class, src_class;
   7216 
   7217    dst = hregNumber(insn->variant.move.dst);
   7218    src = hregNumber(insn->variant.move.src);
   7219 
   7220    dst_class = hregClass(insn->variant.move.dst);
   7221    src_class = hregClass(insn->variant.move.src);
   7222 
   7223    if (dst_class == src_class) {
   7224       if (dst_class == HRcInt64)
   7225          return s390_emit_LGR(buf, dst, src);
   7226       if (dst_class == HRcFlt64)
   7227          return s390_emit_LDR(buf, dst, src);
   7228    } else {
   7229       if (dst_class == HRcFlt64 && src_class == HRcInt64) {
   7230          if (insn->size == 4) {
   7231             buf = s390_emit_SLLG(buf, R0, src, 0, DISP20(32)); /* r0 = src << 32 */
   7232             return s390_emit_LDGRw(buf, dst, R0);
   7233          } else {
   7234             return s390_emit_LDGRw(buf, dst, src);
   7235          }
   7236       }
   7237       if (dst_class == HRcInt64 && src_class == HRcFlt64) {
   7238          if (insn->size == 4) {
   7239             buf = s390_emit_LGDRw(buf, dst, src);
   7240             return s390_emit_SRLG(buf, dst, dst, 0, DISP20(32)); /* dst >>= 32 */
   7241          } else {
   7242             return s390_emit_LGDRw(buf, dst, src);
   7243          }
   7244       }
   7245       /* A move between floating point registers and general purpose
   7246          registers of different size should never occur and indicates
   7247          an error elsewhere. */
   7248    }
   7249 
   7250    vpanic("s390_insn_move_emit");
   7251 }
   7252 
   7253 
   7254 static UChar *
   7255 s390_insn_memcpy_emit(UChar *buf, const s390_insn *insn)
   7256 {
   7257    s390_amode *dst = insn->variant.memcpy.dst;
   7258    s390_amode *src = insn->variant.memcpy.src;
   7259 
   7260    return s390_emit_MVC(buf, insn->size - 1, hregNumber(dst->b), dst->d,
   7261                         hregNumber(src->b), src->d);
   7262 }
   7263 
   7264 
   7265 static UChar *
   7266 s390_insn_load_immediate_emit(UChar *buf, const s390_insn *insn)
   7267 {
   7268    UInt  r;
   7269    ULong value = insn->variant.load_immediate.value;
   7270 
   7271    r = hregNumber(insn->variant.load_immediate.dst);
   7272 
   7273    if (hregClass(insn->variant.load_immediate.dst) == HRcFlt64) {
   7274       vassert(value == 0);
   7275       switch (insn->size) {
   7276       case 4: return s390_emit_LZER(buf, r, value);
   7277       case 8: return s390_emit_LZDR(buf, r, value);
   7278       }
   7279       vpanic("s390_insn_load_immediate_emit");
   7280    }
   7281 
   7282    switch (insn->size) {
   7283    case 1:
   7284    case 2:
   7285       /* Load the immediate values as a 4 byte value. That does not hurt as
   7286          those extra bytes will not be looked at. Fall through .... */
   7287    case 4:
   7288       return s390_emit_load_32imm(buf, r, value);
   7289 
   7290    case 8:
   7291       return s390_emit_load_64imm(buf, r, value);
   7292    }
   7293 
   7294    vpanic("s390_insn_load_immediate_emit");
   7295 }
   7296 
   7297 
   7298 /* There is no easy way to do ALU operations on 1-byte or 2-byte operands.
   7299    So we simply perform a 4-byte operation. Doing so uses possibly undefined
   7300    bits and produces an undefined result in those extra bit positions. But
   7301    upstream does not look at those positions, so this is OK. */
   7302 static UChar *
   7303 s390_insn_alu_emit(UChar *buf, const s390_insn *insn)
   7304 {
   7305    s390_opnd_RMI op2;
   7306    UInt dst;
   7307 
   7308    dst = hregNumber(insn->variant.alu.dst);
   7309    op2 = insn->variant.alu.op2;
   7310 
   7311    /* Second operand is in a register */
   7312    if (op2.tag == S390_OPND_REG) {
   7313       UInt r2 = hregNumber(op2.variant.reg);
   7314 
   7315       switch (insn->size) {
   7316       case 1:
   7317       case 2:
   7318       case 4:
   7319          switch (insn->variant.alu.tag) {
   7320          case S390_ALU_ADD:  return s390_emit_AR(buf, dst, r2);
   7321          case S390_ALU_SUB:  return s390_emit_SR(buf, dst, r2);
   7322          case S390_ALU_MUL:  return s390_emit_MSR(buf, dst, r2);
   7323          case S390_ALU_AND:  return s390_emit_NR(buf, dst, r2);
   7324          case S390_ALU_OR:   return s390_emit_OR(buf, dst, r2);
   7325          case S390_ALU_XOR:  return s390_emit_XR(buf, dst, r2);
   7326          case S390_ALU_LSH:  return s390_emit_SLL(buf, dst, r2, 0);
   7327          case S390_ALU_RSH:  return s390_emit_SRL(buf, dst, r2, 0);
   7328          case S390_ALU_RSHA: return s390_emit_SRA(buf, dst, r2, 0);
   7329          }
   7330          goto fail;
   7331 
   7332       case 8:
   7333          switch (insn->variant.alu.tag) {
   7334          case S390_ALU_ADD:  return s390_emit_AGR(buf, dst, r2);
   7335          case S390_ALU_SUB:  return s390_emit_SGR(buf, dst, r2);
   7336          case S390_ALU_MUL:  return s390_emit_MSGR(buf, dst, r2);
   7337          case S390_ALU_AND:  return s390_emit_NGR(buf, dst, r2);
   7338          case S390_ALU_OR:   return s390_emit_OGR(buf, dst, r2);
   7339          case S390_ALU_XOR:  return s390_emit_XGR(buf, dst, r2);
   7340          case S390_ALU_LSH:  return s390_emit_SLLG(buf, dst, dst, r2, DISP20(0));
   7341          case S390_ALU_RSH:  return s390_emit_SRLG(buf, dst, dst, r2, DISP20(0));
   7342          case S390_ALU_RSHA: return s390_emit_SRAG(buf, dst, dst, r2, DISP20(0));
   7343          }
   7344          goto fail;
   7345       }
   7346       goto fail;
   7347    }
   7348 
   7349    /* 2nd operand is in memory */
   7350    if (op2.tag == S390_OPND_AMODE) {
   7351       UInt b, x, d;
   7352       const s390_amode *src = op2.variant.am;
   7353 
   7354       b = hregNumber(src->b);
   7355       x = hregNumber(src->x);  /* 0 for B12 and B20 */
   7356       d = src->d;
   7357 
   7358       /* Shift operands are special here as there are no opcodes that
   7359          allow a memory operand. So we first load the 2nd operand into
   7360          some register. R0 is used to save restore the contents of the
   7361          chosen register.. */
   7362 
   7363       if (insn->variant.alu.tag == S390_ALU_LSH ||
   7364           insn->variant.alu.tag == S390_ALU_RSH ||
   7365           insn->variant.alu.tag == S390_ALU_RSHA) {
   7366          UInt b2;
   7367 
   7368          /* Choose a register (other than DST or R0) into which to stick the
   7369             shift amount. The following works because r15 is reserved and
   7370             thusly dst != 15. */
   7371          vassert(dst != 15);  /* extra paranoia */
   7372          b2 = (dst + 1) % 16;
   7373 
   7374          buf = s390_emit_LGR(buf, R0, b2);  /* save */
   7375 
   7376          /* Loading SRC to B2 does not modify R0. */
   7377          buf = s390_emit_load_mem(buf, insn->size, b2, src);
   7378 
   7379          if (insn->size == 8) {
   7380             switch (insn->variant.alu.tag) {
   7381             case S390_ALU_LSH:
   7382                buf = s390_emit_SLLG(buf, dst, dst, b2, DISP20(0));
   7383                break;
   7384             case S390_ALU_RSH:
   7385                buf = s390_emit_SRLG(buf, dst, dst, b2, DISP20(0));
   7386                break;
   7387             case S390_ALU_RSHA:
   7388                buf = s390_emit_SRAG(buf, dst, dst, b2, DISP20(0));
   7389                break;
   7390             default: /* unreachable */
   7391                goto fail;
   7392             }
   7393          } else {
   7394             switch (insn->variant.alu.tag) {
   7395             case S390_ALU_LSH:
   7396                buf = s390_emit_SLL(buf, dst, b2, 0);
   7397                break;
   7398             case S390_ALU_RSH:
   7399                buf = s390_emit_SRL(buf, dst, b2, 0);
   7400                break;
   7401             case S390_ALU_RSHA:
   7402                buf = s390_emit_SRA(buf, dst, b2, 0);
   7403                break;
   7404             default: /* unreachable */
   7405                goto fail;
   7406             }
   7407          }
   7408          return s390_emit_LGR(buf, b2, R0);  /* restore */
   7409       }
   7410 
   7411       switch (insn->size) {
   7412       case 1:
   7413          /* Move the byte from memory into scratch register r0 */
   7414          buf = s390_emit_load_mem(buf, 1, R0, src);
   7415 
   7416          switch (insn->variant.alu.tag) {
   7417          case S390_ALU_ADD: return s390_emit_AR(buf, dst, R0);
   7418          case S390_ALU_SUB: return s390_emit_SR(buf, dst, R0);
   7419          case S390_ALU_MUL: return s390_emit_MSR(buf, dst, R0);
   7420          case S390_ALU_AND: return s390_emit_NR(buf, dst, R0);
   7421          case S390_ALU_OR:  return s390_emit_OR(buf, dst, R0);
   7422          case S390_ALU_XOR: return s390_emit_XR(buf, dst, R0);
   7423          case S390_ALU_LSH:
   7424          case S390_ALU_RSH:
   7425          case S390_ALU_RSHA: ; /* avoid GCC warning */
   7426          }
   7427          goto fail;
   7428 
   7429       case 2:
   7430          switch (src->tag) {
   7431          case S390_AMODE_B12:
   7432          case S390_AMODE_BX12:
   7433             switch (insn->variant.alu.tag) {
   7434             case S390_ALU_ADD:
   7435                return s390_emit_AH(buf, dst, x, b, d);
   7436 
   7437             case S390_ALU_SUB:
   7438                return s390_emit_SH(buf, dst, x, b, d);
   7439 
   7440             case S390_ALU_MUL:
   7441                return s390_emit_MH(buf, dst, x, b, d);
   7442 
   7443                /* For bitwise operations: Move two bytes from memory into scratch
   7444                   register r0; then perform operation */
   7445             case S390_ALU_AND:
   7446                buf = s390_emit_LH(buf, R0, x, b, d);
   7447                return s390_emit_NR(buf, dst, R0);
   7448 
   7449             case S390_ALU_OR:
   7450                buf = s390_emit_LH(buf, R0, x, b, d);
   7451                return s390_emit_OR(buf, dst, R0);
   7452 
   7453             case S390_ALU_XOR:
   7454                buf = s390_emit_LH(buf, R0, x, b, d);
   7455                return s390_emit_XR(buf, dst, R0);
   7456 
   7457             case S390_ALU_LSH:
   7458             case S390_ALU_RSH:
   7459             case S390_ALU_RSHA: ; /* avoid GCC warning */
   7460             }
   7461             goto fail;
   7462 
   7463          case S390_AMODE_B20:
   7464          case S390_AMODE_BX20:
   7465             switch (insn->variant.alu.tag) {
   7466             case S390_ALU_ADD:
   7467                return s390_emit_AHY(buf, dst, x, b, DISP20(d));
   7468 
   7469             case S390_ALU_SUB:
   7470                return s390_emit_SHY(buf, dst, x, b, DISP20(d));
   7471 
   7472             case S390_ALU_MUL:
   7473                return s390_emit_MHYw(buf, dst, x, b, DISP20(d));
   7474 
   7475                /* For bitwise operations: Move two bytes from memory into scratch
   7476                   register r0; then perform operation */
   7477             case S390_ALU_AND:
   7478                buf = s390_emit_LHY(buf, R0, x, b, DISP20(d));
   7479                return s390_emit_NR(buf, dst, R0);
   7480 
   7481             case S390_ALU_OR:
   7482                buf = s390_emit_LHY(buf, R0, x, b, DISP20(d));
   7483                return s390_emit_OR(buf, dst, R0);
   7484 
   7485             case S390_ALU_XOR:
   7486                buf = s390_emit_LHY(buf, R0, x, b, DISP20(d));
   7487                return s390_emit_XR(buf, dst, R0);
   7488 
   7489             case S390_ALU_LSH:
   7490             case S390_ALU_RSH:
   7491             case S390_ALU_RSHA: ; /* avoid GCC warning */
   7492             }
   7493             goto fail;
   7494          }
   7495          goto fail;
   7496 
   7497       case 4:
   7498          switch (src->tag) {
   7499          case S390_AMODE_B12:
   7500          case S390_AMODE_BX12:
   7501             switch (insn->variant.alu.tag) {
   7502             case S390_ALU_ADD: return s390_emit_A(buf, dst, x, b, d);
   7503             case S390_ALU_SUB: return s390_emit_S(buf, dst, x, b, d);
   7504             case S390_ALU_MUL: return s390_emit_MS(buf, dst, x, b, d);
   7505             case S390_ALU_AND: return s390_emit_N(buf, dst, x, b, d);
   7506             case S390_ALU_OR:  return s390_emit_O(buf, dst, x, b, d);
   7507             case S390_ALU_XOR: return s390_emit_X(buf, dst, x, b, d);
   7508             case S390_ALU_LSH:
   7509             case S390_ALU_RSH:
   7510             case S390_ALU_RSHA: ; /* avoid GCC warning */
   7511             }
   7512             goto fail;
   7513 
   7514          case S390_AMODE_B20:
   7515          case S390_AMODE_BX20:
   7516             switch (insn->variant.alu.tag) {
   7517             case S390_ALU_ADD: return s390_emit_AY(buf, dst, x, b, DISP20(d));
   7518             case S390_ALU_SUB: return s390_emit_SY(buf, dst, x, b, DISP20(d));
   7519             case S390_ALU_MUL: return s390_emit_MSY(buf, dst, x, b, DISP20(d));
   7520             case S390_ALU_AND: return s390_emit_NY(buf, dst, x, b, DISP20(d));
   7521             case S390_ALU_OR:  return s390_emit_OY(buf, dst, x, b, DISP20(d));
   7522             case S390_ALU_XOR: return s390_emit_XY(buf, dst, x, b, DISP20(d));
   7523             case S390_ALU_LSH:
   7524             case S390_ALU_RSH:
   7525             case S390_ALU_RSHA: ; /* avoid GCC warning */
   7526             }
   7527             goto fail;
   7528          }
   7529          goto fail;
   7530 
   7531       case 8:
   7532          switch (insn->variant.alu.tag) {
   7533          case S390_ALU_ADD: return s390_emit_AG(buf, dst, x, b, DISP20(d));
   7534          case S390_ALU_SUB: return s390_emit_SG(buf, dst, x, b, DISP20(d));
   7535          case S390_ALU_MUL: return s390_emit_MSG(buf, dst, x, b, DISP20(d));
   7536          case S390_ALU_AND: return s390_emit_NG(buf, dst, x, b, DISP20(d));
   7537          case S390_ALU_OR:  return s390_emit_OG(buf, dst, x, b, DISP20(d));
   7538          case S390_ALU_XOR: return s390_emit_XG(buf, dst, x, b, DISP20(d));
   7539          case S390_ALU_LSH:
   7540          case S390_ALU_RSH:
   7541          case S390_ALU_RSHA: ; /* avoid GCC warning */
   7542          }
   7543          goto fail;
   7544       }
   7545       goto fail;
   7546    }
   7547 
   7548    /* 2nd operand is an immediate value */
   7549    if (op2.tag == S390_OPND_IMMEDIATE) {
   7550       ULong value;
   7551 
   7552       /* No masking of the value is required as it is not sign extended */
   7553       value = op2.variant.imm;
   7554 
   7555       switch (insn->size) {
   7556       case 1:
   7557       case 2:
   7558          /* There is no 1-byte opcode. Do the computation in
   7559             2 bytes. The extra byte will be ignored. */
   7560          switch (insn->variant.alu.tag) {
   7561          case S390_ALU_ADD:
   7562             return s390_emit_AHI(buf, dst, value);
   7563 
   7564          case S390_ALU_SUB:
   7565             return s390_emit_SLFIw(buf, dst, value);
   7566 
   7567          case S390_ALU_MUL:
   7568             return s390_emit_MHI(buf, dst, value);
   7569 
   7570          case S390_ALU_AND: return s390_emit_NILL(buf, dst, value);
   7571          case S390_ALU_OR:  return s390_emit_OILL(buf, dst, value);
   7572          case S390_ALU_XOR:
   7573             /* There is no XILL instruction.  Load the immediate value into
   7574                R0 and combine with the destination register. */
   7575             buf = s390_emit_LHI(buf, R0, value);
   7576             return s390_emit_XR(buf, dst, R0);
   7577 
   7578          case S390_ALU_LSH:
   7579             return s390_emit_SLL(buf, dst, 0, value);
   7580 
   7581          case S390_ALU_RSH:
   7582             return s390_emit_SRL(buf, dst, 0, value);
   7583 
   7584          case S390_ALU_RSHA:
   7585             return s390_emit_SRA(buf, dst, 0, value);
   7586          }
   7587          goto fail;
   7588 
   7589       case 4:
   7590          switch (insn->variant.alu.tag) {
   7591          case S390_ALU_ADD:
   7592             if (uint_fits_signed_16bit(value)) {
   7593                return s390_emit_AHI(buf, dst, value);
   7594             }
   7595             return s390_emit_AFIw(buf, dst, value);
   7596 
   7597          case S390_ALU_SUB:  return s390_emit_SLFIw(buf, dst, value);
   7598          case S390_ALU_MUL:  return s390_emit_MSFIw(buf, dst, value);
   7599          case S390_ALU_AND:  return s390_emit_NILFw(buf, dst, value);
   7600          case S390_ALU_OR:   return s390_emit_OILFw(buf, dst, value);
   7601          case S390_ALU_XOR:  return s390_emit_XILFw(buf, dst, value);
   7602          case S390_ALU_LSH:  return s390_emit_SLL(buf, dst, 0, value);
   7603          case S390_ALU_RSH:  return s390_emit_SRL(buf, dst, 0, value);
   7604          case S390_ALU_RSHA: return s390_emit_SRA(buf, dst, 0, value);
   7605          }
   7606          goto fail;
   7607 
   7608       case 8:
   7609          switch (insn->variant.alu.tag) {
   7610          case S390_ALU_ADD:
   7611             if (ulong_fits_signed_16bit(value)) {
   7612                return s390_emit_AGHI(buf, dst, value);
   7613             }
   7614             if (ulong_fits_signed_32bit(value) && s390_host_has_eimm) {
   7615                return s390_emit_AGFI(buf, dst, value);
   7616             }
   7617             /* Load constant into R0 then add */
   7618             buf = s390_emit_load_64imm(buf, R0, value);
   7619             return s390_emit_AGR(buf, dst, R0);
   7620 
   7621          case S390_ALU_SUB:
   7622             if (ulong_fits_unsigned_32bit(value)) {
   7623                return s390_emit_SLGFIw(buf, dst, value);
   7624             }
   7625             /* Load value into R0; then subtract from destination reg */
   7626             buf = s390_emit_load_64imm(buf, R0, value);
   7627             return s390_emit_SGR(buf, dst, R0);
   7628 
   7629          case S390_ALU_MUL:
   7630             if (ulong_fits_signed_32bit(value) && s390_host_has_gie) {
   7631                return s390_emit_MSGFI(buf, dst, value);
   7632             }
   7633             /* Load constant into R0 then add */
   7634             buf = s390_emit_load_64imm(buf, R0, value);
   7635             return s390_emit_MSGR(buf, dst, R0);
   7636 
   7637             /* Do it in two steps: upper half [0:31] and lower half [32:63] */
   7638          case S390_ALU_AND:
   7639             if (s390_host_has_eimm) {
   7640                buf  = s390_emit_NIHF(buf, dst, value >> 32);
   7641                return s390_emit_NILF(buf, dst, value & 0xFFFFFFFF);
   7642             }
   7643             /* Load value into R0; then combine with destination reg */
   7644             buf = s390_emit_load_64imm(buf, R0, value);
   7645             return s390_emit_NGR(buf, dst, R0);
   7646 
   7647          case S390_ALU_OR:
   7648             if (s390_host_has_eimm) {
   7649                buf  = s390_emit_OIHF(buf, dst, value >> 32);
   7650                return s390_emit_OILF(buf, dst, value & 0xFFFFFFFF);
   7651             }
   7652             /* Load value into R0; then combine with destination reg */
   7653             buf = s390_emit_load_64imm(buf, R0, value);
   7654             return s390_emit_OGR(buf, dst, R0);
   7655 
   7656          case S390_ALU_XOR:
   7657             if (s390_host_has_eimm) {
   7658                buf  = s390_emit_XIHF(buf, dst, value >> 32);
   7659                return s390_emit_XILF(buf, dst, value & 0xFFFFFFFF);
   7660             }
   7661             /* Load value into R0; then combine with destination reg */
   7662             buf = s390_emit_load_64imm(buf, R0, value);
   7663             return s390_emit_XGR(buf, dst, R0);
   7664 
   7665             /* No special considerations for long displacement here. Only the six
   7666                least significant bits of VALUE will be taken; all other bits are
   7667                ignored. So the DH2 bits are irrelevant and do not influence the
   7668                shift operation, independent of whether long-displacement is available
   7669                or not. */
   7670          case S390_ALU_LSH:  return s390_emit_SLLG(buf, dst, dst, 0, DISP20(value));
   7671          case S390_ALU_RSH:  return s390_emit_SRLG(buf, dst, dst, 0, DISP20(value));
   7672          case S390_ALU_RSHA: return s390_emit_SRAG(buf, dst, dst, 0, DISP20(value));
   7673          }
   7674          goto fail;
   7675       }
   7676       goto fail;
   7677    }
   7678 
   7679  fail:
   7680    vpanic("s390_insn_alu_emit");
   7681 }
   7682 
   7683 
   7684 static UChar *
   7685 s390_widen_emit(UChar *buf, const s390_insn *insn, UInt from_size,
   7686                 Bool sign_extend)
   7687 {
   7688    s390_opnd_RMI opnd = insn->variant.unop.src;
   7689 
   7690    switch (opnd.tag) {
   7691    case S390_OPND_REG: {
   7692       UChar r1 = hregNumber(insn->variant.unop.dst);
   7693       UChar r2 = hregNumber(opnd.variant.reg);
   7694 
   7695       switch (from_size) {
   7696       case 1:
   7697          /* Widening to a half-word is implemented like widening to a word
   7698             because the upper half-word will not be looked at. */
   7699          if (insn->size == 4 || insn->size == 2) {  /* 8 --> 32    8 --> 16 */
   7700             if (sign_extend)
   7701                return s390_emit_LBRw(buf, r1, r2);
   7702             else
   7703                return s390_emit_LLCRw(buf, r1, r2);
   7704          }
   7705          if (insn->size == 8) {  /* 8 --> 64 */
   7706             if (sign_extend)
   7707                return s390_emit_LGBRw(buf, r1, r2);
   7708             else
   7709                return s390_emit_LLGCRw(buf, r1, r2);
   7710          }
   7711          goto fail;
   7712 
   7713       case 2:
   7714          if (insn->size == 4) {  /* 16 --> 32 */
   7715             if (sign_extend)
   7716                return s390_emit_LHRw(buf, r1, r2);
   7717             else
   7718                return s390_emit_LLHRw(buf, r1, r2);
   7719          }
   7720          if (insn->size == 8) {  /* 16 --> 64 */
   7721             if (sign_extend)
   7722                return s390_emit_LGHRw(buf, r1, r2);
   7723             else
   7724                return s390_emit_LLGHRw(buf, r1, r2);
   7725          }
   7726          goto fail;
   7727 
   7728       case 4:
   7729          if (insn->size == 8) {  /* 32 --> 64 */
   7730             if (sign_extend)
   7731                return s390_emit_LGFR(buf, r1, r2);
   7732             else
   7733                return s390_emit_LLGFR(buf, r1, r2);
   7734          }
   7735          goto fail;
   7736 
   7737       default: /* unexpected "from" size */
   7738          goto fail;
   7739       }
   7740    }
   7741 
   7742    case S390_OPND_AMODE: {
   7743       UChar r1 = hregNumber(insn->variant.unop.dst);
   7744       const s390_amode *src = opnd.variant.am;
   7745       UChar b = hregNumber(src->b);
   7746       UChar x = hregNumber(src->x);
   7747       Int   d = src->d;
   7748 
   7749       switch (from_size) {
   7750       case 1:
   7751          if (insn->size == 4 || insn->size == 2) {
   7752             if (sign_extend)
   7753                return s390_emit_LB(buf, r1, x, b, DISP20(d));
   7754             else
   7755                return s390_emit_LLCw(buf, r1, x, b, DISP20(d));
   7756          }
   7757          if (insn->size == 8) {
   7758             if (sign_extend)
   7759                return s390_emit_LGB(buf, r1, x, b, DISP20(d));
   7760             else
   7761                return s390_emit_LLGC(buf, r1, x, b, DISP20(d));
   7762          }
   7763          goto fail;
   7764 
   7765       case 2:
   7766          if (insn->size == 4) {  /* 16 --> 32 */
   7767             if (sign_extend == 0)
   7768                return s390_emit_LLHw(buf, r1, x, b, DISP20(d));
   7769 
   7770             switch (src->tag) {
   7771             case S390_AMODE_B12:
   7772             case S390_AMODE_BX12:
   7773                return s390_emit_LH(buf, r1, x, b, d);
   7774 
   7775             case S390_AMODE_B20:
   7776             case S390_AMODE_BX20:
   7777                return s390_emit_LHY(buf, r1, x, b, DISP20(d));
   7778             }
   7779             goto fail;
   7780          }
   7781          if (insn->size == 8) {  /* 16 --> 64 */
   7782             if (sign_extend)
   7783                return s390_emit_LGH(buf, r1, x, b, DISP20(d));
   7784             else
   7785                return s390_emit_LLGH(buf, r1, x, b, DISP20(d));
   7786          }
   7787          goto fail;
   7788 
   7789       case 4:
   7790          if (insn->size == 8) {  /* 32 --> 64 */
   7791             if (sign_extend)
   7792                return s390_emit_LGF(buf, r1, x, b, DISP20(d));
   7793             else
   7794                return s390_emit_LLGF(buf, r1, x, b, DISP20(d));
   7795          }
   7796          goto fail;
   7797 
   7798       default: /* unexpected "from" size */
   7799          goto fail;
   7800       }
   7801    }
   7802 
   7803    case S390_OPND_IMMEDIATE: {
   7804       UChar r1 = hregNumber(insn->variant.unop.dst);
   7805       ULong value = opnd.variant.imm;
   7806 
   7807       switch (from_size) {
   7808       case 1:
   7809          if (insn->size == 4 || insn->size == 2) {  /* 8 --> 32   8 --> 16 */
   7810             if (sign_extend) {
   7811                /* host can do the sign extension to 16-bit; LHI does the rest */
   7812                return s390_emit_LHI(buf, r1, (Short)(Char)(UChar)value);
   7813             } else {
   7814                return s390_emit_LHI(buf, r1, value);
   7815             }
   7816          }
   7817          if (insn->size == 8) {  /* 8 --> 64 */
   7818             if (sign_extend) {
   7819                /* host can do the sign extension to 16-bit; LGHI does the rest */
   7820                return s390_emit_LGHI(buf, r1, (Short)(Char)(UChar)value);
   7821             } else {
   7822                return s390_emit_LGHI(buf, r1, value);
   7823             }
   7824          }
   7825          goto fail;
   7826 
   7827       case 2:
   7828          if (insn->size == 4) {  /* 16 --> 32 */
   7829             return s390_emit_LHI(buf, r1, value);
   7830          }
   7831          if (insn->size == 8) {  /* 16 --> 64 */
   7832             if (sign_extend)
   7833                return s390_emit_LGHI(buf, r1, value);
   7834             else
   7835                return s390_emit_LLILL(buf, r1, value);
   7836          }
   7837          goto fail;
   7838 
   7839       case 4:
   7840          if (insn->size == 8) {  /* 32 --> 64 */
   7841             if (sign_extend)
   7842                return s390_emit_LGFIw(buf, r1, value);
   7843             else
   7844                return s390_emit_LLILFw(buf, r1, value);
   7845          }
   7846          goto fail;
   7847 
   7848       default: /* unexpected "from" size */
   7849          goto fail;
   7850       }
   7851    }
   7852    }
   7853 
   7854  fail:
   7855    vpanic("s390_widen_emit");
   7856 }
   7857 
   7858 
   7859 static UChar *
   7860 s390_negate_emit(UChar *buf, const s390_insn *insn)
   7861 {
   7862    s390_opnd_RMI opnd;
   7863 
   7864    opnd = insn->variant.unop.src;
   7865 
   7866    switch (opnd.tag) {
   7867    case S390_OPND_REG: {
   7868       UChar r1 = hregNumber(insn->variant.unop.dst);
   7869       UChar r2 = hregNumber(opnd.variant.reg);
   7870 
   7871       switch (insn->size) {
   7872       case 1:
   7873       case 2:
   7874       case 4:
   7875          return s390_emit_LCR(buf, r1, r2);
   7876 
   7877       case 8:
   7878          return s390_emit_LCGR(buf, r1, r2);
   7879 
   7880       default:
   7881          goto fail;
   7882       }
   7883    }
   7884 
   7885    case S390_OPND_AMODE: {
   7886       UChar r1 = hregNumber(insn->variant.unop.dst);
   7887 
   7888       /* Load bytes into scratch register R0, then negate */
   7889       buf = s390_emit_load_mem(buf, insn->size, R0, opnd.variant.am);
   7890 
   7891       switch (insn->size) {
   7892       case 1:
   7893       case 2:
   7894       case 4:
   7895          return s390_emit_LCR(buf, r1, R0);
   7896 
   7897       case 8:
   7898          return s390_emit_LCGR(buf, r1, R0);
   7899 
   7900       default:
   7901          goto fail;
   7902       }
   7903    }
   7904 
   7905    case S390_OPND_IMMEDIATE: {
   7906       UChar r1 = hregNumber(insn->variant.unop.dst);
   7907       ULong value = opnd.variant.imm;
   7908 
   7909       value = ~value + 1;   /* two's complement */
   7910 
   7911       switch (insn->size) {
   7912       case 1:
   7913       case 2:
   7914          /* Load the immediate values as a 4 byte value. That does not hurt as
   7915             those extra bytes will not be looked at. Fall through .... */
   7916       case 4:
   7917          return s390_emit_load_32imm(buf, r1, value);
   7918 
   7919       case 8:
   7920          return s390_emit_load_64imm(buf, r1, value);
   7921 
   7922       default:
   7923          goto fail;
   7924       }
   7925    }
   7926    }
   7927 
   7928  fail:
   7929    vpanic("s390_negate_emit");
   7930 }
   7931 
   7932 
   7933 static UChar *
   7934 s390_insn_unop_emit(UChar *buf, const s390_insn *insn)
   7935 {
   7936    switch (insn->variant.unop.tag) {
   7937    case S390_ZERO_EXTEND_8:  return s390_widen_emit(buf, insn, 1, 0);
   7938    case S390_ZERO_EXTEND_16: return s390_widen_emit(buf, insn, 2, 0);
   7939    case S390_ZERO_EXTEND_32: return s390_widen_emit(buf, insn, 4, 0);
   7940 
   7941    case S390_SIGN_EXTEND_8:  return s390_widen_emit(buf, insn, 1, 1);
   7942    case S390_SIGN_EXTEND_16: return s390_widen_emit(buf, insn, 2, 1);
   7943    case S390_SIGN_EXTEND_32: return s390_widen_emit(buf, insn, 4, 1);
   7944 
   7945    case S390_NEGATE:         return s390_negate_emit(buf, insn);
   7946    }
   7947 
   7948    vpanic("s390_insn_unop_emit");
   7949 }
   7950 
   7951 
   7952 /* Only 4-byte and 8-byte operands are handled. 1-byte and 2-byte
   7953    comparisons will have been converted to 4-byte comparisons in
   7954    s390_isel_cc and should not occur here. */
   7955 static UChar *
   7956 s390_insn_test_emit(UChar *buf, const s390_insn *insn)
   7957 {
   7958    s390_opnd_RMI opnd;
   7959 
   7960    opnd = insn->variant.test.src;
   7961 
   7962    switch (opnd.tag) {
   7963    case S390_OPND_REG: {
   7964       UInt reg = hregNumber(opnd.variant.reg);
   7965 
   7966       switch (insn->size) {
   7967       case 4:
   7968          return s390_emit_LTR(buf, reg, reg);
   7969 
   7970       case 8:
   7971          return s390_emit_LTGR(buf, reg, reg);
   7972 
   7973       default:
   7974          goto fail;
   7975       }
   7976    }
   7977 
   7978    case S390_OPND_AMODE: {
   7979       const s390_amode *am = opnd.variant.am;
   7980       UChar b = hregNumber(am->b);
   7981       UChar x = hregNumber(am->x);
   7982       Int   d = am->d;
   7983 
   7984       switch (insn->size) {
   7985       case 4:
   7986          return s390_emit_LTw(buf, R0, x, b, DISP20(d));
   7987 
   7988       case 8:
   7989          return s390_emit_LTGw(buf, R0, x, b, DISP20(d));
   7990 
   7991       default:
   7992          goto fail;
   7993       }
   7994    }
   7995 
   7996    case S390_OPND_IMMEDIATE: {
   7997       ULong value = opnd.variant.imm;
   7998 
   7999       switch (insn->size) {
   8000       case 4:
   8001          buf = s390_emit_load_32imm(buf, R0, value);
   8002          return s390_emit_LTR(buf, R0, R0);
   8003 
   8004       case 8:
   8005          buf = s390_emit_load_64imm(buf, R0, value);
   8006          return s390_emit_LTGR(buf, R0, R0);
   8007 
   8008       default:
   8009          goto fail;
   8010       }
   8011    }
   8012 
   8013    default:
   8014       goto fail;
   8015    }
   8016 
   8017  fail:
   8018    vpanic("s390_insn_test_emit");
   8019 }
   8020 
   8021 
   8022 static UChar *
   8023 s390_insn_cc2bool_emit(UChar *buf, const s390_insn *insn)
   8024 {
   8025    UChar r1 = hregNumber(insn->variant.cc2bool.dst);
   8026    s390_cc_t cond = insn->variant.cc2bool.cond;
   8027 
   8028    /* Make the destination register be 1 or 0, depending on whether
   8029       the relevant condition holds. A 64-bit value is computed. */
   8030    if (cond == S390_CC_ALWAYS)
   8031       return s390_emit_LGHI(buf, r1, 1);  /* r1 = 1 */
   8032 
   8033    buf = s390_emit_load_cc(buf, r1);                 /* r1 = cc */
   8034    buf = s390_emit_LGHI(buf, R0, cond);              /* r0 = mask */
   8035    buf = s390_emit_SLLG(buf, r1, R0, r1, DISP20(0)); /* r1 = mask << cc */
   8036    buf = s390_emit_SRLG(buf, r1, r1, 0,  DISP20(3)); /* r1 = r1 >> 3 */
   8037    buf = s390_emit_NILL(buf, r1, 1);                 /* r1 = r1 & 0x1 */
   8038 
   8039    return buf;
   8040 }
   8041 
   8042 
   8043 /* Only 4-byte and 8-byte operands are handled. */
   8044 static UChar *
   8045 s390_insn_cas_emit(UChar *buf, const s390_insn *insn)
   8046 {
   8047    UChar r1, r3, b, old;
   8048    Int d;
   8049    s390_amode *am;
   8050 
   8051    r1 = hregNumber(insn->variant.cas.op1); /* expected value */
   8052    r3 = hregNumber(insn->variant.cas.op3);
   8053    old= hregNumber(insn->variant.cas.old_mem);
   8054    am = insn->variant.cas.op2;
   8055    b  = hregNumber(am->b);
   8056    d  = am->d;
   8057 
   8058    vassert(am->tag == S390_AMODE_B12 || am->tag == S390_AMODE_B20);
   8059 
   8060    switch (insn->size) {
   8061    case 4:
   8062       /* r1 must not be overwritten. So copy it to R0 and let CS clobber it */
   8063       buf = s390_emit_LR(buf, R0, r1);
   8064       if (am->tag == S390_AMODE_B12)
   8065          buf = s390_emit_CS(buf, R0, r3, b, d);
   8066       else
   8067          buf = s390_emit_CSY(buf, R0, r3, b, DISP20(d));
   8068       /* Now copy R0 which has the old memory value to OLD */
   8069       return s390_emit_LR(buf, old, R0);
   8070 
   8071    case 8:
   8072       /* r1 must not be overwritten. So copy it to R0 and let CS clobber it */
   8073       buf = s390_emit_LGR(buf, R0, r1);
   8074       buf = s390_emit_CSG(buf, R0, r3, b, DISP20(d));
   8075       /* Now copy R0 which has the old memory value to OLD */
   8076       return s390_emit_LGR(buf, old, R0);
   8077 
   8078    default:
   8079       goto fail;
   8080    }
   8081 
   8082  fail:
   8083    vpanic("s390_insn_cas_emit");
   8084 }
   8085 
   8086 
   8087 /* Only 4-byte and 8-byte operands are handled. */
   8088 static UChar *
   8089 s390_insn_cdas_emit(UChar *buf, const s390_insn *insn)
   8090 {
   8091    UChar r1, r1p1, r3, /*r3p1,*/ b, old_high, old_low, scratch;
   8092    Int d;
   8093    s390_amode *am;
   8094    s390_cdas *cdas = insn->variant.cdas.details;
   8095 
   8096    r1   = hregNumber(cdas->op1_high); /* expected value */
   8097    r1p1 = hregNumber(cdas->op1_low);  /* expected value */
   8098    r3   = hregNumber(cdas->op3_high);
   8099    /* r3p1 = hregNumber(cdas->op3_low); */ /* unused */
   8100    old_high = hregNumber(cdas->old_mem_high);
   8101    old_low  = hregNumber(cdas->old_mem_low);
   8102    scratch  = hregNumber(cdas->scratch);
   8103    am = cdas->op2;
   8104    b  = hregNumber(am->b);
   8105    d  = am->d;
   8106 
   8107    vassert(scratch == 1);
   8108    vassert(am->tag == S390_AMODE_B12 || am->tag == S390_AMODE_B20);
   8109 
   8110    switch (insn->size) {
   8111    case 4:
   8112       /* r1, r1+1 must not be overwritten. So copy them to R0,scratch
   8113          and let CDS/CDSY clobber it */
   8114       buf = s390_emit_LR(buf, R0, r1);
   8115       buf = s390_emit_LR(buf, scratch, r1p1);
   8116 
   8117       if (am->tag == S390_AMODE_B12)
   8118          buf = s390_emit_CDS(buf, R0, r3, b, d);
   8119       else
   8120          buf = s390_emit_CDSY(buf, R0, r3, b, DISP20(d));
   8121 
   8122       /* Now copy R0,scratch which has the old memory value to OLD */
   8123       buf = s390_emit_LR(buf, old_high, R0);
   8124       buf = s390_emit_LR(buf, old_low,  scratch);
   8125       return buf;
   8126 
   8127    case 8:
   8128       /* r1, r1+1 must not be overwritten. So copy them to R0,scratch
   8129          and let CDSG clobber it */
   8130       buf = s390_emit_LGR(buf, R0, r1);
   8131       buf = s390_emit_LGR(buf, scratch, r1p1);
   8132 
   8133       buf = s390_emit_CDSG(buf, R0, r3, b, DISP20(d));
   8134 
   8135       /* Now copy R0,scratch which has the old memory value to OLD */
   8136       buf = s390_emit_LGR(buf, old_high, R0);
   8137       buf = s390_emit_LGR(buf, old_low,  scratch);
   8138       return buf;
   8139 
   8140    default:
   8141       goto fail;
   8142    }
   8143 
   8144  fail:
   8145    vpanic("s390_insn_cdas_emit");
   8146 }
   8147 
   8148 
   8149 /* Only 4-byte and 8-byte comparisons are handled. 1-byte and 2-byte
   8150    comparisons will have been converted to 4-byte comparisons in
   8151    s390_isel_cc and should not occur here. */
   8152 static UChar *
   8153 s390_insn_compare_emit(UChar *buf, const s390_insn *insn)
   8154 {
   8155    s390_opnd_RMI op2;
   8156    HReg op1;
   8157    Bool signed_comparison;
   8158 
   8159    op1 = insn->variant.compare.src1;
   8160    op2 = insn->variant.compare.src2;
   8161    signed_comparison = insn->variant.compare.signed_comparison;
   8162 
   8163    switch (op2.tag) {
   8164    case S390_OPND_REG: {
   8165       UInt r1 = hregNumber(op1);
   8166       UInt r2 = hregNumber(op2.variant.reg);
   8167 
   8168       switch (insn->size) {
   8169       case 4:
   8170          if (signed_comparison)
   8171             return s390_emit_CR(buf, r1, r2);
   8172          else
   8173             return s390_emit_CLR(buf, r1, r2);
   8174 
   8175       case 8:
   8176          if (signed_comparison)
   8177             return s390_emit_CGR(buf, r1, r2);
   8178          else
   8179             return s390_emit_CLGR(buf, r1, r2);
   8180 
   8181       default:
   8182          goto fail;
   8183       }
   8184    }
   8185 
   8186    case S390_OPND_AMODE: {
   8187       UChar r1 = hregNumber(op1);
   8188       const s390_amode *am = op2.variant.am;
   8189       UChar b = hregNumber(am->b);
   8190       UChar x = hregNumber(am->x);
   8191       Int   d = am->d;
   8192 
   8193       switch (insn->size) {
   8194       case 4:
   8195          switch (am->tag) {
   8196          case S390_AMODE_B12:
   8197          case S390_AMODE_BX12:
   8198             if (signed_comparison)
   8199                return s390_emit_C(buf, r1, x, b, d);
   8200             else
   8201                return s390_emit_CL(buf, r1, x, b, d);
   8202 
   8203          case S390_AMODE_B20:
   8204          case S390_AMODE_BX20:
   8205             if (signed_comparison)
   8206                return s390_emit_CY(buf, r1, x, b, DISP20(d));
   8207             else
   8208                return s390_emit_CLY(buf, r1, x, b, DISP20(d));
   8209          }
   8210          goto fail;
   8211 
   8212       case 8:
   8213          if (signed_comparison)
   8214             return s390_emit_CG(buf, r1, x, b, DISP20(d));
   8215          else
   8216             return s390_emit_CLG(buf, r1, x, b, DISP20(d));
   8217 
   8218       default:
   8219          goto fail;
   8220       }
   8221    }
   8222 
   8223    case S390_OPND_IMMEDIATE: {
   8224       UChar r1 = hregNumber(op1);
   8225       ULong value = op2.variant.imm;
   8226 
   8227       switch (insn->size) {
   8228       case 4:
   8229          if (signed_comparison)
   8230             return s390_emit_CFIw(buf, r1, value);
   8231          else
   8232             return s390_emit_CLFIw(buf, r1, value);
   8233 
   8234       case 8:
   8235          if (s390_host_has_eimm) {
   8236             if (signed_comparison) {
   8237                if (ulong_fits_signed_32bit(value))
   8238                   return s390_emit_CGFI(buf, r1, value);
   8239             } else {
   8240                if (ulong_fits_unsigned_32bit(value))
   8241                   return s390_emit_CLGFI(buf, r1, value);
   8242             }
   8243          }
   8244          buf = s390_emit_load_64imm(buf, R0, value);
   8245          if (signed_comparison)
   8246             return s390_emit_CGR(buf, r1, R0);
   8247          else
   8248             return s390_emit_CLGR(buf, r1, R0);
   8249 
   8250       default:
   8251          goto fail;
   8252       }
   8253    }
   8254 
   8255    default:
   8256       goto fail;
   8257    }
   8258 
   8259  fail:
   8260    vpanic("s390_insn_compare_emit");
   8261 }
   8262 
   8263 
   8264 static UChar *
   8265 s390_insn_mul_emit(UChar *buf, const s390_insn *insn)
   8266 {
   8267    s390_opnd_RMI op2;
   8268    UChar r1;
   8269    Bool signed_multiply;
   8270 
   8271    /* The register number identifying the register pair */
   8272    r1  = hregNumber(insn->variant.mul.dst_hi);
   8273 
   8274    op2 = insn->variant.mul.op2;
   8275    signed_multiply = insn->tag == S390_INSN_SMUL;
   8276 
   8277    switch (op2.tag) {
   8278    case S390_OPND_REG: {
   8279       UInt r2 = hregNumber(op2.variant.reg);
   8280 
   8281       switch (insn->size) {
   8282       case 1:
   8283       case 2:
   8284       case 4:
   8285          if (signed_multiply)
   8286             return s390_emit_MR(buf, r1, r2);
   8287          else
   8288             return s390_emit_MLR(buf, r1, r2);
   8289 
   8290       case 8:
   8291          if (signed_multiply)
   8292             vpanic("s390_insn_mul_emit");
   8293          else
   8294             return s390_emit_MLGR(buf, r1, r2);
   8295 
   8296       default:
   8297          goto fail;
   8298       }
   8299    }
   8300 
   8301    case S390_OPND_AMODE: {
   8302       const s390_amode *am = op2.variant.am;
   8303       UChar b = hregNumber(am->b);
   8304       UChar x = hregNumber(am->x);
   8305       Int   d = am->d;
   8306 
   8307       switch (insn->size) {
   8308       case 1:
   8309       case 2:
   8310          /* Load bytes into scratch register R0, then multiply */
   8311          buf = s390_emit_load_mem(buf, insn->size, R0, am);
   8312          if (signed_multiply)
   8313             return s390_emit_MR(buf, r1, R0);
   8314          else
   8315             return s390_emit_MLR(buf, r1, R0);
   8316 
   8317       case 4:
   8318          switch (am->tag) {
   8319          case S390_AMODE_B12:
   8320          case S390_AMODE_BX12:
   8321             if (signed_multiply)
   8322                return s390_emit_M(buf, r1, x, b, d);
   8323             else
   8324                return s390_emit_ML(buf, r1, x, b, DISP20(d));
   8325 
   8326          case S390_AMODE_B20:
   8327          case S390_AMODE_BX20:
   8328             if (signed_multiply)
   8329                return s390_emit_MFYw(buf, r1, x, b, DISP20(d));
   8330             else
   8331                return s390_emit_ML(buf, r1, x, b, DISP20(d));
   8332          }
   8333          goto fail;
   8334 
   8335       case 8:
   8336          if (signed_multiply)
   8337             vpanic("s390_insn_mul_emit");
   8338          else
   8339             return s390_emit_MLG(buf, r1, x, b, DISP20(d));
   8340 
   8341       default:
   8342          goto fail;
   8343       }
   8344    }
   8345 
   8346    case S390_OPND_IMMEDIATE: {
   8347       ULong value = op2.variant.imm;
   8348 
   8349       switch (insn->size) {
   8350       case 1:
   8351       case 2:
   8352       case 4:
   8353          buf = s390_emit_load_32imm(buf, R0, value);
   8354          if (signed_multiply)
   8355             return s390_emit_MR(buf, r1, R0);
   8356          else
   8357             return s390_emit_MLR(buf, r1, R0);
   8358 
   8359       case 8:
   8360          buf = s390_emit_load_64imm(buf, R0, value);
   8361          if (signed_multiply)
   8362             vpanic("s390_insn_mul_emit");
   8363          else
   8364             return s390_emit_MLGR(buf, r1, R0);
   8365 
   8366       default:
   8367          goto fail;
   8368       }
   8369    }
   8370 
   8371    default:
   8372       goto fail;
   8373    }
   8374 
   8375  fail:
   8376    vpanic("s390_insn_mul_emit");
   8377 }
   8378 
   8379 
   8380 static UChar *
   8381 s390_insn_div_emit(UChar *buf, const s390_insn *insn)
   8382 {
   8383    s390_opnd_RMI op2;
   8384    UChar r1;
   8385    Bool signed_divide;
   8386 
   8387    r1  = hregNumber(insn->variant.div.op1_hi);
   8388    op2 = insn->variant.div.op2;
   8389    signed_divide = insn->tag == S390_INSN_SDIV;
   8390 
   8391    switch (op2.tag) {
   8392    case S390_OPND_REG: {
   8393       UInt r2 = hregNumber(op2.variant.reg);
   8394 
   8395       switch (insn->size) {
   8396       case 4:
   8397          if (signed_divide)
   8398             return s390_emit_DR(buf, r1, r2);
   8399          else
   8400             return s390_emit_DLR(buf, r1, r2);
   8401 
   8402       case 8:
   8403          if (signed_divide)
   8404             vpanic("s390_insn_div_emit");
   8405          else
   8406             return s390_emit_DLGR(buf, r1, r2);
   8407 
   8408       default:
   8409          goto fail;
   8410       }
   8411    }
   8412 
   8413    case S390_OPND_AMODE: {
   8414       const s390_amode *am = op2.variant.am;
   8415       UChar b = hregNumber(am->b);
   8416       UChar x = hregNumber(am->x);
   8417       Int   d = am->d;
   8418 
   8419       switch (insn->size) {
   8420       case 4:
   8421          switch (am->tag) {
   8422          case S390_AMODE_B12:
   8423          case S390_AMODE_BX12:
   8424             if (signed_divide)
   8425                return s390_emit_D(buf, r1, x, b, d);
   8426             else
   8427                return s390_emit_DL(buf, r1, x, b, DISP20(d));
   8428 
   8429          case S390_AMODE_B20:
   8430          case S390_AMODE_BX20:
   8431             if (signed_divide) {
   8432                buf = s390_emit_LY(buf, R0, x, b, DISP20(d));
   8433                return s390_emit_DR(buf, r1, R0);
   8434             } else
   8435                return s390_emit_DL(buf, r1, x, b, DISP20(d));
   8436          }
   8437          goto fail;
   8438 
   8439       case 8:
   8440          if (signed_divide)
   8441             vpanic("s390_insn_div_emit");
   8442          else
   8443             return s390_emit_DLG(buf, r1, x, b, DISP20(d));
   8444 
   8445       default:
   8446          goto fail;
   8447       }
   8448    }
   8449 
   8450    case S390_OPND_IMMEDIATE: {
   8451       ULong value = op2.variant.imm;
   8452 
   8453       switch (insn->size) {
   8454       case 4:
   8455          buf = s390_emit_load_32imm(buf, R0, value);
   8456          if (signed_divide)
   8457             return s390_emit_DR(buf, r1, R0);
   8458          else
   8459             return s390_emit_DLR(buf, r1, R0);
   8460 
   8461       case 8:
   8462          buf = s390_emit_load_64imm(buf, R0, value);
   8463          if (signed_divide)
   8464             vpanic("s390_insn_div_emit");
   8465          else
   8466             return s390_emit_DLGR(buf, r1, R0);
   8467 
   8468       default:
   8469          goto fail;
   8470       }
   8471    }
   8472 
   8473    default:
   8474       goto fail;
   8475    }
   8476 
   8477  fail:
   8478    vpanic("s390_insn_div_emit");
   8479 }
   8480 
   8481 
   8482 static UChar *
   8483 s390_insn_divs_emit(UChar *buf, const s390_insn *insn)
   8484 {
   8485    s390_opnd_RMI op2;
   8486    UChar r1;
   8487 
   8488    r1  = hregNumber(insn->variant.divs.rem);
   8489    op2 = insn->variant.divs.op2;
   8490 
   8491    switch (op2.tag) {
   8492    case S390_OPND_REG: {
   8493       UInt r2 = hregNumber(op2.variant.reg);
   8494 
   8495       return s390_emit_DSGR(buf, r1, r2);
   8496    }
   8497 
   8498    case S390_OPND_AMODE: {
   8499       const s390_amode *am = op2.variant.am;
   8500       UChar b = hregNumber(am->b);
   8501       UChar x = hregNumber(am->x);
   8502       Int   d = am->d;
   8503 
   8504       return s390_emit_DSG(buf, r1, x, b, DISP20(d));
   8505    }
   8506 
   8507    case S390_OPND_IMMEDIATE: {
   8508       ULong value = op2.variant.imm;
   8509 
   8510       buf = s390_emit_load_64imm(buf, R0, value);
   8511       return s390_emit_DSGR(buf, r1, R0);
   8512    }
   8513 
   8514    default:
   8515       goto fail;
   8516    }
   8517 
   8518  fail:
   8519    vpanic("s390_insn_divs_emit");
   8520 }
   8521 
   8522 
   8523 static UChar *
   8524 s390_insn_clz_emit(UChar *buf, const s390_insn *insn)
   8525 {
   8526    s390_opnd_RMI src;
   8527    UChar r1, r1p1, r2, *p;
   8528 
   8529    r1   = hregNumber(insn->variant.clz.num_bits);
   8530    r1p1 = hregNumber(insn->variant.clz.clobber);
   8531 
   8532    vassert((r1 & 0x1) == 0);
   8533    vassert(r1p1 == r1 + 1);
   8534 
   8535    p = buf;
   8536    src = insn->variant.clz.src;
   8537 
   8538    /* Get operand and move it to r2 */
   8539    switch (src.tag) {
   8540    case S390_OPND_REG:
   8541       r2 = hregNumber(src.variant.reg);
   8542       break;
   8543 
   8544    case S390_OPND_AMODE: {
   8545       const s390_amode *am = src.variant.am;
   8546       UChar b = hregNumber(am->b);
   8547       UChar x = hregNumber(am->x);
   8548       Int   d = am->d;
   8549 
   8550       p  = s390_emit_LG(p, R0, x, b, DISP20(d));
   8551       r2 = R0;
   8552       break;
   8553    }
   8554 
   8555    case S390_OPND_IMMEDIATE: {
   8556       ULong value = src.variant.imm;
   8557 
   8558       p  = s390_emit_load_64imm(p, R0, value);
   8559       r2 = R0;
   8560       break;
   8561    }
   8562 
   8563    default:
   8564       goto fail;
   8565    }
   8566 
   8567    /* Use FLOGR if you can */
   8568    if (s390_host_has_eimm) {
   8569       return s390_emit_FLOGR(p, r1, r2);
   8570    }
   8571 
   8572    /*
   8573       r0 = r2;
   8574       r1 = 64;
   8575       while (r0 != 0) {
   8576         r1 -= 1;
   8577         r0 >>= 1;
   8578       }
   8579    */
   8580    p = s390_emit_LTGR(p, R0, r2);
   8581    p = s390_emit_LLILL(p, r1,  64);
   8582 
   8583    p = s390_emit_BRC(p, S390_CC_E, (4 + 4 + 6 + 4 + 4)/ 2);  /* 4 bytes */
   8584    p = s390_emit_AGHI(p, r1, (UShort)-1);         /* r1  -= 1;  4 bytes */
   8585    p = s390_emit_SRLG(p, R0, R0, R0, DISP20(1));  /* r0 >>= 1;  6 bytes */
   8586    p = s390_emit_LTGR(p, R0, R0);                 /* set cc     4 bytes */
   8587    p = s390_emit_BRC(p, S390_CC_NE,               /*            4 bytes */
   8588                      (UShort)(-(4 + 6 + 4) / 2));
   8589    return p;
   8590 
   8591  fail:
   8592    vpanic("s390_insn_clz_emit");
   8593 }
   8594 
   8595 
   8596 /* Returns a value == BUF to denote failure, != BUF to denote success. */
   8597 static UChar *
   8598 s390_insn_helper_call_emit(UChar *buf, const s390_insn *insn)
   8599 {
   8600    s390_cc_t cond;
   8601    ULong target;
   8602    UChar *ptmp = buf;
   8603    s390_helper_call *helper_call = insn->variant.helper_call.details;
   8604 
   8605    cond = helper_call->cond;
   8606    target = helper_call->target;
   8607 
   8608    if (cond != S390_CC_ALWAYS
   8609        && helper_call->rloc.pri != RLPri_None) {
   8610       /* The call might not happen (it isn't unconditional) and it
   8611          returns a result.  In this case we will need to generate a
   8612          control flow diamond to put 0x555..555 in the return
   8613          register(s) in the case where the call doesn't happen.  If
   8614          this ever becomes necessary, maybe copy code from the ARM
   8615          equivalent.  Until that day, just give up. */
   8616       return buf; /* To denote failure. */
   8617    }
   8618 
   8619    if (cond != S390_CC_ALWAYS) {
   8620       /* So we have something like this
   8621          if (cond) call X;
   8622          Y: ...
   8623          We convert this into
   8624          if (! cond) goto Y;        // BRC opcode; 4 bytes
   8625          call X;
   8626          Y:
   8627       */
   8628       /* 4 bytes (a BRC insn) to be filled in here */
   8629       buf += 4;
   8630    }
   8631 
   8632    /* Load the target address into a register, that
   8633       (a) is not used for passing parameters to the helper and
   8634       (b) can be clobbered by the callee
   8635       (c) is not special to the BASR insn
   8636       r1 is the only choice.
   8637       Also, need to arrange for the return address be put into the
   8638       link-register */
   8639    buf = s390_emit_load_64imm(buf, 1, target);
   8640 
   8641    /* Stash away the client's FPC register because the helper might change it. */
   8642    buf = s390_emit_STFPC(buf, S390_REGNO_STACK_POINTER, S390_OFFSET_SAVED_FPC_C);
   8643 
   8644    buf = s390_emit_BASR(buf, S390_REGNO_LINK_REGISTER, 1);      // call helper
   8645 
   8646    buf = s390_emit_LFPC(buf, S390_REGNO_STACK_POINTER,          // restore FPC
   8647                         S390_OFFSET_SAVED_FPC_C);
   8648 
   8649    if (cond != S390_CC_ALWAYS) {
   8650       Int delta = buf - ptmp;
   8651 
   8652       delta >>= 1;  /* immediate constant is #half-words */
   8653       vassert(delta > 0 && delta < (1 << 16));
   8654       s390_emit_BRC(ptmp, s390_cc_invert(cond), delta);
   8655    }
   8656 
   8657    return buf;
   8658 }
   8659 
   8660 
   8661 static UChar *
   8662 s390_insn_cond_move_emit(UChar *buf, const s390_insn *insn)
   8663 {
   8664    HReg dst;
   8665    s390_opnd_RMI src;
   8666    s390_cc_t cond;
   8667    UChar *p, *ptmp = 0;   /* avoid compiler warnings */
   8668 
   8669    cond = insn->variant.cond_move.cond;
   8670    dst  = insn->variant.cond_move.dst;
   8671    src  = insn->variant.cond_move.src;
   8672 
   8673    if (cond == S390_CC_NEVER) return buf;
   8674 
   8675    p = buf;
   8676 
   8677    if (s390_host_has_lsc) {
   8678       /* LOCx is not the preferred way to implement an unconditional load. */
   8679       if (cond != S390_CC_ALWAYS) goto use_branch_insn;
   8680 
   8681       switch (src.tag) {
   8682       case S390_OPND_REG:
   8683          return s390_emit_LOCGR(p, cond, hregNumber(dst),
   8684                                 hregNumber(src.variant.reg));
   8685 
   8686       case S390_OPND_AMODE: {
   8687          const s390_amode *am = src.variant.am;
   8688 
   8689          /* We cannot use LOCx for loads less than 4 bytes. In that case
   8690             load into R0 and then use LOCGR. Do the same if the amode uses
   8691             an index register. */
   8692          if (insn->size < 4 ||
   8693              am->tag == S390_AMODE_BX12 || am->tag == S390_AMODE_BX20) {
   8694             p = s390_emit_load_mem(p, insn->size, R0, am);
   8695             p = s390_emit_LOCGR(p, cond, hregNumber(dst), R0);
   8696             return p;
   8697          }
   8698 
   8699          vassert(am->tag == S390_AMODE_B12 || am->tag == S390_AMODE_B20);
   8700          vassert(insn->size == 4 || insn->size == 8);
   8701 
   8702          UInt b = hregNumber(am->b);
   8703          UInt d = am->d;
   8704 
   8705          if (insn->size == 4) {
   8706             return s390_emit_LOC(p, hregNumber(dst), cond, b, DISP20(d));
   8707          }
   8708          return s390_emit_LOCG(p, hregNumber(dst), cond, b, DISP20(d));
   8709       }
   8710 
   8711       case S390_OPND_IMMEDIATE: {
   8712          ULong value = src.variant.imm;
   8713 
   8714          /* Load value into R0, then use LOCGR */
   8715          if (insn->size <= 4) {
   8716             p = s390_emit_load_32imm(p, R0, value);
   8717             return s390_emit_LOCGR(p, cond, hregNumber(dst), R0);
   8718          }
   8719 
   8720          vassert(insn->size == 8);
   8721          p = s390_emit_load_64imm(p, R0, value);
   8722          return s390_emit_LOCGR(p, cond, hregNumber(dst), R0);
   8723       }
   8724       }
   8725    }
   8726 
   8727 use_branch_insn:
   8728    /* Branch (if cond fails) over move instrs */
   8729    if (cond != S390_CC_ALWAYS) {
   8730       /* Don't know how many bytes to jump over yet.
   8731          Make space for a BRC instruction (4 bytes) and fill in later. */
   8732       ptmp = p;   /*  to be filled in here */
   8733       p += 4;
   8734    }
   8735 
   8736    // cond true: move src => dst
   8737 
   8738    switch (src.tag) {
   8739    case S390_OPND_REG:
   8740       p = s390_emit_LGR(p, hregNumber(dst), hregNumber(src.variant.reg));
   8741       break;
   8742 
   8743    case S390_OPND_AMODE:
   8744       p = s390_emit_load_mem(p, insn->size, hregNumber(dst), src.variant.am);
   8745       break;
   8746 
   8747    case S390_OPND_IMMEDIATE: {
   8748       ULong value = src.variant.imm;
   8749       UInt  r = hregNumber(dst);
   8750 
   8751       switch (insn->size) {
   8752       case 1:
   8753       case 2:
   8754          /* Load the immediate values as a 4 byte value. That does not hurt as
   8755             those extra bytes will not be looked at. Fall through .... */
   8756       case 4:
   8757          p = s390_emit_load_32imm(p, r, value);
   8758          break;
   8759 
   8760       case 8:
   8761          p = s390_emit_load_64imm(p, r, value);
   8762          break;
   8763       }
   8764       break;
   8765    }
   8766 
   8767    default:
   8768       goto fail;
   8769    }
   8770 
   8771    if (cond != S390_CC_ALWAYS) {
   8772       Int delta = p - ptmp;
   8773 
   8774       delta >>= 1;  /* immediate constant is #half-words */
   8775       vassert(delta > 0 && delta < (1 << 16));
   8776       s390_emit_BRC(ptmp, s390_cc_invert(cond), delta);
   8777    }
   8778 
   8779    return p;
   8780 
   8781  fail:
   8782    vpanic("s390_insn_cond_move_emit");
   8783 }
   8784 
   8785 
   8786 static UChar *
   8787 s390_insn_bfp_triop_emit(UChar *buf, const s390_insn *insn)
   8788 {
   8789    UInt r1 = hregNumber(insn->variant.bfp_triop.dst);
   8790    UInt r2 = hregNumber(insn->variant.bfp_triop.op2);
   8791    UInt r3 = hregNumber(insn->variant.bfp_triop.op3);
   8792 
   8793    switch (insn->size) {
   8794    case 4:
   8795       switch (insn->variant.bfp_triop.tag) {
   8796       case S390_BFP_MADD:  return s390_emit_MAEBR(buf, r1, r3, r2);
   8797       case S390_BFP_MSUB:  return s390_emit_MSEBR(buf, r1, r3, r2);
   8798       default:  goto fail;
   8799       }
   8800       break;
   8801 
   8802    case 8:
   8803       switch (insn->variant.bfp_triop.tag) {
   8804       case S390_BFP_MADD:  return s390_emit_MADBR(buf, r1, r3, r2);
   8805       case S390_BFP_MSUB:  return s390_emit_MSDBR(buf, r1, r3, r2);
   8806       default:  goto fail;
   8807       }
   8808       break;
   8809 
   8810    default:  goto fail;
   8811    }
   8812 
   8813  fail:
   8814    vpanic("s390_insn_bfp_triop_emit");
   8815 }
   8816 
   8817 
   8818 static UChar *
   8819 s390_insn_bfp_binop_emit(UChar *buf, const s390_insn *insn)
   8820 {
   8821    UInt r1 = hregNumber(insn->variant.bfp_binop.dst_hi);
   8822    UInt r2 = hregNumber(insn->variant.bfp_binop.op2_hi);
   8823 
   8824    switch (insn->size) {
   8825    case 4:
   8826       switch (insn->variant.bfp_binop.tag) {
   8827       case S390_BFP_ADD:     return s390_emit_AEBR(buf, r1, r2);
   8828       case S390_BFP_SUB:     return s390_emit_SEBR(buf, r1, r2);
   8829       case S390_BFP_MUL:     return s390_emit_MEEBR(buf, r1, r2);
   8830       case S390_BFP_DIV:     return s390_emit_DEBR(buf, r1, r2);
   8831       default:  goto fail;
   8832       }
   8833       break;
   8834 
   8835    case 8:
   8836       switch (insn->variant.bfp_binop.tag) {
   8837       case S390_BFP_ADD:     return s390_emit_ADBR(buf, r1, r2);
   8838       case S390_BFP_SUB:     return s390_emit_SDBR(buf, r1, r2);
   8839       case S390_BFP_MUL:     return s390_emit_MDBR(buf, r1, r2);
   8840       case S390_BFP_DIV:     return s390_emit_DDBR(buf, r1, r2);
   8841       default:  goto fail;
   8842       }
   8843       break;
   8844 
   8845    case 16:
   8846       switch (insn->variant.bfp_binop.tag) {
   8847       case S390_BFP_ADD:     return s390_emit_AXBR(buf, r1, r2);
   8848       case S390_BFP_SUB:     return s390_emit_SXBR(buf, r1, r2);
   8849       case S390_BFP_MUL:     return s390_emit_MXBR(buf, r1, r2);
   8850       case S390_BFP_DIV:     return s390_emit_DXBR(buf, r1, r2);
   8851       default:  goto fail;
   8852       }
   8853       break;
   8854 
   8855    default:  goto fail;
   8856    }
   8857 
   8858  fail:
   8859    vpanic("s390_insn_bfp_binop_emit");
   8860 }
   8861 
   8862 
   8863 static UChar *
   8864 s390_insn_bfp_unop_emit(UChar *buf, const s390_insn *insn)
   8865 {
   8866    UInt  r1 = hregNumber(insn->variant.bfp_unop.dst_hi);
   8867    UInt  r2 = hregNumber(insn->variant.bfp_unop.op_hi);
   8868 
   8869    switch (insn->variant.bfp_unop.tag) {
   8870    case S390_BFP_ABS:
   8871       switch (insn->size) {
   8872       case 4:   return s390_emit_LPEBR(buf, r1, r2);
   8873       case 8:   return s390_emit_LPDBR(buf, r1, r2);
   8874       case 16:  return s390_emit_LPXBR(buf, r1, r2);
   8875       default:  goto fail;
   8876       }
   8877       break;
   8878 
   8879    case S390_BFP_NABS:
   8880       switch (insn->size) {
   8881       case 4:   return s390_emit_LNEBR(buf, r1, r2);
   8882       case 8:   return s390_emit_LNDBR(buf, r1, r2);
   8883       case 16:  return s390_emit_LNXBR(buf, r1, r2);
   8884       default:  goto fail;
   8885       }
   8886       break;
   8887 
   8888    case S390_BFP_NEG:
   8889       switch (insn->size) {
   8890       case 4:   return s390_emit_LCEBR(buf, r1, r2);
   8891       case 8:   return s390_emit_LCDBR(buf, r1, r2);
   8892       case 16:  return s390_emit_LCXBR(buf, r1, r2);
   8893       default:  goto fail;
   8894       }
   8895       break;
   8896 
   8897    case S390_BFP_SQRT:
   8898       switch (insn->size) {
   8899       case 4:   return s390_emit_SQEBR(buf, r1, r2);
   8900       case 8:   return s390_emit_SQDBR(buf, r1, r2);
   8901       case 16:  return s390_emit_SQXBR(buf, r1, r2);
   8902       default:  goto fail;
   8903       }
   8904       break;
   8905 
   8906    default: goto fail;
   8907    }
   8908 
   8909  fail:
   8910    vpanic("s390_insn_bfp_unop_emit");
   8911 }
   8912 
   8913 
   8914 static UChar *
   8915 s390_insn_bfp_convert_emit(UChar *buf, const s390_insn *insn)
   8916 {
   8917    UInt  r1 = hregNumber(insn->variant.bfp_convert.dst_hi);
   8918    UInt  r2 = hregNumber(insn->variant.bfp_convert.op_hi);
   8919    s390_bfp_round_t m3 = insn->variant.bfp_convert.rounding_mode;
   8920    /* The IEEE-inexact-exception control is not modelled. So the
   8921       m4 field is 0 (which is what GCC does, too) */
   8922    const UInt m4 = 0;
   8923 
   8924    switch (insn->variant.bfp_convert.tag) {
   8925       /* Convert to fixed */
   8926    case S390_BFP_F32_TO_I32:  return s390_emit_CFEBR(buf, m3, r1, r2);
   8927    case S390_BFP_F64_TO_I32:  return s390_emit_CFDBR(buf, m3, r1, r2);
   8928    case S390_BFP_F128_TO_I32: return s390_emit_CFXBR(buf, m3, r1, r2);
   8929    case S390_BFP_F32_TO_I64:  return s390_emit_CGEBR(buf, m3, r1, r2);
   8930    case S390_BFP_F64_TO_I64:  return s390_emit_CGDBR(buf, m3, r1, r2);
   8931    case S390_BFP_F128_TO_I64: return s390_emit_CGXBR(buf, m3, r1, r2);
   8932 
   8933       /* Convert to logical */
   8934    case S390_BFP_F32_TO_U32:  return s390_emit_CLFEBR(buf, m3, m4, r1, r2);
   8935    case S390_BFP_F64_TO_U32:  return s390_emit_CLFDBR(buf, m3, m4, r1, r2);
   8936    case S390_BFP_F128_TO_U32: return s390_emit_CLFXBR(buf, m3, m4, r1, r2);
   8937    case S390_BFP_F32_TO_U64:  return s390_emit_CLGEBR(buf, m3, m4, r1, r2);
   8938    case S390_BFP_F64_TO_U64:  return s390_emit_CLGDBR(buf, m3, m4, r1, r2);
   8939    case S390_BFP_F128_TO_U64: return s390_emit_CLGXBR(buf, m3, m4, r1, r2);
   8940 
   8941       /* Convert from fixed */
   8942    case S390_BFP_I32_TO_F32:  return s390_emit_CEFBRA(buf, m3, m4, r1, r2);
   8943    case S390_BFP_I32_TO_F64:  return s390_emit_CDFBRA(buf,  0, m4, r1, r2);
   8944    case S390_BFP_I32_TO_F128: return s390_emit_CXFBRA(buf,  0, m4, r1, r2);
   8945    case S390_BFP_I64_TO_F32:  return s390_emit_CEGBRA(buf, m3, m4, r1, r2);
   8946    case S390_BFP_I64_TO_F64:  return s390_emit_CDGBRA(buf, m3, m4, r1, r2);
   8947    case S390_BFP_I64_TO_F128: return s390_emit_CXGBRA(buf,  0, m4, r1, r2);
   8948 
   8949       /* Convert from logical */
   8950    case S390_BFP_U32_TO_F32:  return s390_emit_CELFBR(buf, m3, m4, r1, r2);
   8951    case S390_BFP_U32_TO_F64:  return s390_emit_CDLFBR(buf, m3, m4, r1, r2);
   8952    case S390_BFP_U32_TO_F128: return s390_emit_CXLFBR(buf, m3, m4, r1, r2);
   8953    case S390_BFP_U64_TO_F32:  return s390_emit_CELGBR(buf, m3, m4, r1, r2);
   8954    case S390_BFP_U64_TO_F64:  return s390_emit_CDLGBR(buf, m3, m4, r1, r2);
   8955    case S390_BFP_U64_TO_F128: return s390_emit_CXLGBR(buf, m3, m4, r1, r2);
   8956 
   8957       /* Load lengthened */
   8958    case S390_BFP_F32_TO_F64:  return s390_emit_LDEBR(buf, r1, r2);
   8959    case S390_BFP_F32_TO_F128: return s390_emit_LXEBR(buf, r1, r2);
   8960    case S390_BFP_F64_TO_F128: return s390_emit_LXDBR(buf, r1, r2);
   8961 
   8962       /* Load rounded */
   8963    case S390_BFP_F64_TO_F32:  return s390_emit_LEDBRA(buf, m3, m4, r1, r2);
   8964    case S390_BFP_F128_TO_F32: return s390_emit_LEXBRA(buf, m3, m4, r1, r2);
   8965    case S390_BFP_F128_TO_F64: return s390_emit_LDXBRA(buf, m3, m4, r1, r2);
   8966 
   8967    default: goto fail;
   8968    }
   8969 
   8970  fail:
   8971    vpanic("s390_insn_bfp_convert_emit");
   8972 }
   8973 
   8974 
   8975 static UChar *
   8976 s390_insn_bfp_compare_emit(UChar *buf, const s390_insn *insn)
   8977 {
   8978    UInt dst = hregNumber(insn->variant.bfp_compare.dst);
   8979    UInt r1  = hregNumber(insn->variant.bfp_compare.op1_hi);
   8980    UInt r2  = hregNumber(insn->variant.bfp_compare.op2_hi);
   8981 
   8982    switch (insn->size) {
   8983    case 4:  buf = s390_emit_CEBR(buf, r1, r2); break;
   8984    case 8:  buf = s390_emit_CDBR(buf, r1, r2); break;
   8985    case 16: buf = s390_emit_CXBR(buf, r1, r2); break;
   8986    default:  goto fail;
   8987    }
   8988 
   8989    return s390_emit_load_cc(buf, dst);  /* Load condition code into DST */
   8990 
   8991  fail:
   8992    vpanic("s390_insn_bfp_compare_emit");
   8993 }
   8994 
   8995 
   8996 static UChar *
   8997 s390_insn_dfp_binop_emit(UChar *buf, const s390_insn *insn)
   8998 {
   8999    s390_dfp_binop *dfp_binop = insn->variant.dfp_binop.details;
   9000 
   9001    UInt r1 = hregNumber(dfp_binop->dst_hi);
   9002    UInt r2 = hregNumber(dfp_binop->op2_hi);
   9003    UInt r3 = hregNumber(dfp_binop->op3_hi);
   9004    s390_dfp_round_t m4 = dfp_binop->rounding_mode;
   9005 
   9006    switch (insn->size) {
   9007    case 8:
   9008       switch (dfp_binop->tag) {
   9009       case S390_DFP_ADD: return s390_emit_ADTRA(buf, r3, m4, r1, r2);
   9010       case S390_DFP_SUB: return s390_emit_SDTRA(buf, r3, m4, r1, r2);
   9011       case S390_DFP_MUL: return s390_emit_MDTRA(buf, r3, m4, r1, r2);
   9012       case S390_DFP_DIV: return s390_emit_DDTRA(buf, r3, m4, r1, r2);
   9013       case S390_DFP_QUANTIZE: return s390_emit_QADTR(buf, r3, m4, r1, r2);
   9014       default:  goto fail;
   9015       }
   9016       break;
   9017 
   9018    case 16:
   9019       switch (dfp_binop->tag) {
   9020       case S390_DFP_ADD:     return s390_emit_AXTRA(buf, r3, m4, r1, r2);
   9021       case S390_DFP_SUB:     return s390_emit_SXTRA(buf, r3, m4, r1, r2);
   9022       case S390_DFP_MUL:     return s390_emit_MXTRA(buf, r3, m4, r1, r2);
   9023       case S390_DFP_DIV:     return s390_emit_DXTRA(buf, r3, m4, r1, r2);
   9024       case S390_DFP_QUANTIZE: return s390_emit_QAXTR(buf, r3, m4, r1, r2);
   9025       default:  goto fail;
   9026       }
   9027       break;
   9028 
   9029    default:  goto fail;
   9030    }
   9031 
   9032  fail:
   9033    vpanic("s390_insn_dfp_binop_emit");
   9034 }
   9035 
   9036 
   9037 static UChar *
   9038 s390_insn_dfp_reround_emit(UChar *buf, const s390_insn *insn)
   9039 {
   9040    UInt r1 = hregNumber(insn->variant.dfp_reround.dst_hi);
   9041    UInt r2 = hregNumber(insn->variant.dfp_reround.op2);
   9042    UInt r3 = hregNumber(insn->variant.dfp_reround.op3_hi);
   9043    s390_dfp_round_t m4 = insn->variant.dfp_reround.rounding_mode;
   9044 
   9045    switch (insn->size) {
   9046    case 8:
   9047       return s390_emit_RRDTR(buf, r3, m4, r1, r2);
   9048 
   9049    case 16:
   9050       return s390_emit_RRXTR(buf, r3, m4, r1, r2);
   9051 
   9052    default: goto fail;
   9053    }
   9054  fail:
   9055    vpanic("s390_insn_dfp_reround_emit");
   9056 }
   9057 
   9058 
   9059 static UChar *
   9060 s390_insn_dfp_unop_emit(UChar *buf, const s390_insn *insn)
   9061 {
   9062    UInt  r1 = hregNumber(insn->variant.dfp_unop.dst_hi);
   9063    UInt  r2 = hregNumber(insn->variant.dfp_unop.op_hi);
   9064 
   9065    switch (insn->variant.dfp_unop.tag) {
   9066    case S390_DFP_EXTRACT_EXP_D64:  return s390_emit_EEDTR(buf, r1, r2); break;
   9067    case S390_DFP_EXTRACT_EXP_D128: return s390_emit_EEXTR(buf, r1, r2); break;
   9068    case S390_DFP_EXTRACT_SIG_D64:  return s390_emit_ESDTR(buf, r1, r2); break;
   9069    case S390_DFP_EXTRACT_SIG_D128: return s390_emit_ESXTR(buf, r1, r2); break;
   9070    default: goto fail;
   9071    }
   9072  fail:
   9073    vpanic("s390_insn_dfp_unop_emit");
   9074 }
   9075 
   9076 
   9077 static UChar *
   9078 s390_insn_dfp_intop_emit(UChar *buf, const s390_insn *insn)
   9079 {
   9080    UInt r1 = hregNumber(insn->variant.dfp_intop.dst_hi);
   9081    UInt r2 = hregNumber(insn->variant.dfp_intop.op2);
   9082    UInt r3 = hregNumber(insn->variant.dfp_intop.op3_hi);
   9083 
   9084    switch (insn->size) {
   9085    case 8:
   9086       switch (insn->variant.dfp_intop.tag) {
   9087       case S390_DFP_SHIFT_LEFT:  return s390_emit_SLDT(buf, r3, r1, r2);
   9088       case S390_DFP_SHIFT_RIGHT: return s390_emit_SRDT(buf, r3, r1, r2);
   9089       case S390_DFP_INSERT_EXP:  return s390_emit_IEDTR(buf, r3, r1, r2);
   9090       default:  goto fail;
   9091       }
   9092       break;
   9093 
   9094    case 16:
   9095       switch (insn->variant.dfp_intop.tag) {
   9096       case S390_DFP_SHIFT_LEFT:  return s390_emit_SLXT(buf, r3, r1, r2);
   9097       case S390_DFP_SHIFT_RIGHT: return s390_emit_SRXT(buf, r3, r1, r2);
   9098       case S390_DFP_INSERT_EXP:  return s390_emit_IEXTR(buf, r3, r1, r2);
   9099       default:  goto fail;
   9100       }
   9101       break;
   9102 
   9103    default: goto fail;
   9104    }
   9105 
   9106  fail:
   9107    vpanic("s390_insn_dfp_intop_emit");
   9108 }
   9109 
   9110 
   9111 static UChar *
   9112 s390_insn_dfp_compare_emit(UChar *buf, const s390_insn *insn)
   9113 {
   9114    UInt dst = hregNumber(insn->variant.dfp_compare.dst);
   9115    UInt r1  = hregNumber(insn->variant.dfp_compare.op1_hi);
   9116    UInt r2  = hregNumber(insn->variant.dfp_compare.op2_hi);
   9117 
   9118    switch (insn->size) {
   9119    case 8:
   9120       switch(insn->variant.dfp_compare.tag) {
   9121       case S390_DFP_COMPARE:     buf = s390_emit_CDTR(buf, r1, r2); break;
   9122       case S390_DFP_COMPARE_EXP: buf = s390_emit_CEDTR(buf, r1, r2); break;
   9123       default: goto fail;
   9124       }
   9125       break;
   9126 
   9127    case 16:
   9128       switch(insn->variant.dfp_compare.tag) {
   9129       case S390_DFP_COMPARE:     buf = s390_emit_CXTR(buf, r1, r2); break;
   9130       case S390_DFP_COMPARE_EXP: buf = s390_emit_CEXTR(buf, r1, r2); break;
   9131       default: goto fail;
   9132       }
   9133       break;
   9134 
   9135    default:  goto fail;
   9136    }
   9137 
   9138    return s390_emit_load_cc(buf, dst);  /* Load condition code into DST */
   9139 
   9140  fail:
   9141    vpanic("s390_insn_dfp_compare_emit");
   9142 }
   9143 
   9144 
   9145 static UChar *
   9146 s390_insn_dfp_convert_emit(UChar *buf, const s390_insn *insn)
   9147 {
   9148    UInt  r1 = hregNumber(insn->variant.dfp_convert.dst_hi);
   9149    UInt  r2 = hregNumber(insn->variant.dfp_convert.op_hi);
   9150    s390_dfp_round_t m3 = insn->variant.dfp_convert.rounding_mode;
   9151    /* The IEEE-inexact-exception control is not modelled. So the
   9152       m4 field is 0 (which is what GCC does, too) */
   9153    const UInt m4 = 0;
   9154 
   9155    switch (insn->variant.dfp_convert.tag) {
   9156 
   9157       /* Convert to fixed */
   9158    case S390_DFP_D64_TO_I32:  return s390_emit_CFDTR(buf, m3, m4, r1, r2);
   9159    case S390_DFP_D128_TO_I32: return s390_emit_CFXTR(buf, m3, m4, r1, r2);
   9160    case S390_DFP_D64_TO_I64:  return s390_emit_CGDTR(buf, m3, m4, r1, r2);
   9161    case S390_DFP_D128_TO_I64: return s390_emit_CGXTR(buf, m3, m4, r1, r2);
   9162 
   9163       /* Convert to logical */
   9164    case S390_DFP_D64_TO_U32:  return s390_emit_CLFDTR(buf, m3, m4, r1, r2);
   9165    case S390_DFP_D128_TO_U32: return s390_emit_CLFXTR(buf, m3, m4, r1, r2);
   9166    case S390_DFP_D64_TO_U64:  return s390_emit_CLGDTR(buf, m3, m4, r1, r2);
   9167    case S390_DFP_D128_TO_U64: return s390_emit_CLGXTR(buf, m3, m4, r1, r2);
   9168 
   9169       /* Convert from fixed */
   9170    case S390_DFP_I32_TO_D64:  return s390_emit_CDFTR(buf, 0, m4, r1, r2);
   9171    case S390_DFP_I32_TO_D128: return s390_emit_CXFTR(buf, 0, m4, r1, r2);
   9172    case S390_DFP_I64_TO_D64:  return s390_emit_CDGTRA(buf, m3, m4, r1, r2);
   9173    case S390_DFP_I64_TO_D128: return s390_emit_CXGTR(buf, 0, m4, r1, r2);
   9174 
   9175       /* Convert from logical */
   9176    case S390_DFP_U32_TO_D64:  return s390_emit_CDLFTR(buf, m3, m4, r1, r2);
   9177    case S390_DFP_U64_TO_D64:  return s390_emit_CDLGTR(buf, m3, m4, r1, r2);
   9178    case S390_DFP_U32_TO_D128: return s390_emit_CXLFTR(buf, m3, m4, r1, r2);
   9179    case S390_DFP_U64_TO_D128: return s390_emit_CXLGTR(buf, m3, m4, r1, r2);
   9180 
   9181       /* Load lengthened */
   9182    case S390_DFP_D32_TO_D64:   return s390_emit_LDETR(buf, m4, r1, r2);
   9183    case S390_DFP_D64_TO_D128:  return s390_emit_LXDTR(buf, m4, r1, r2);
   9184 
   9185       /* Load rounded */
   9186    case S390_DFP_D64_TO_D32:   return s390_emit_LEDTR(buf, m3, m4, r1, r2);
   9187    case S390_DFP_D128_TO_D64:  return s390_emit_LDXTR(buf, m3, m4, r1, r2);
   9188 
   9189    default: goto fail;
   9190    }
   9191 
   9192  fail:
   9193    vpanic("s390_insn_dfp_convert_emit");
   9194 }
   9195 
   9196 
   9197 static UChar *
   9198 s390_insn_fp_convert_emit(UChar *buf, const s390_insn *insn)
   9199 {
   9200    UInt pfpo;
   9201    s390_fp_convert *fp_convert = insn->variant.fp_convert.details;
   9202    s390_dfp_round_t rm = fp_convert->rounding_mode;
   9203 
   9204    vassert(rm < 2 || rm > 7);
   9205 
   9206    switch (fp_convert->tag) {
   9207    case S390_FP_F32_TO_D32:   pfpo = S390_PFPO_F32_TO_D32   << 8; break;
   9208    case S390_FP_F32_TO_D64:   pfpo = S390_PFPO_F32_TO_D64   << 8; break;
   9209    case S390_FP_F32_TO_D128:  pfpo = S390_PFPO_F32_TO_D128  << 8; break;
   9210    case S390_FP_F64_TO_D32:   pfpo = S390_PFPO_F64_TO_D32   << 8; break;
   9211    case S390_FP_F64_TO_D64:   pfpo = S390_PFPO_F64_TO_D64   << 8; break;
   9212    case S390_FP_F64_TO_D128:  pfpo = S390_PFPO_F64_TO_D128  << 8; break;
   9213    case S390_FP_F128_TO_D32:  pfpo = S390_PFPO_F128_TO_D32  << 8; break;
   9214    case S390_FP_F128_TO_D64:  pfpo = S390_PFPO_F128_TO_D64  << 8; break;
   9215    case S390_FP_F128_TO_D128: pfpo = S390_PFPO_F128_TO_D128 << 8; break;
   9216    case S390_FP_D32_TO_F32:   pfpo = S390_PFPO_D32_TO_F32   << 8; break;
   9217    case S390_FP_D32_TO_F64:   pfpo = S390_PFPO_D32_TO_F64   << 8; break;
   9218    case S390_FP_D32_TO_F128:  pfpo = S390_PFPO_D32_TO_F128  << 8; break;
   9219    case S390_FP_D64_TO_F32:   pfpo = S390_PFPO_D64_TO_F32   << 8; break;
   9220    case S390_FP_D64_TO_F64:   pfpo = S390_PFPO_D64_TO_F64   << 8; break;
   9221    case S390_FP_D64_TO_F128:  pfpo = S390_PFPO_D64_TO_F128  << 8; break;
   9222    case S390_FP_D128_TO_F32:  pfpo = S390_PFPO_D128_TO_F32  << 8; break;
   9223    case S390_FP_D128_TO_F64:  pfpo = S390_PFPO_D128_TO_F64  << 8; break;
   9224    case S390_FP_D128_TO_F128: pfpo = S390_PFPO_D128_TO_F128 << 8; break;
   9225    default: goto fail;
   9226    }
   9227 
   9228    pfpo = pfpo | rm;
   9229    buf = s390_emit_load_32imm(buf, R0, pfpo);
   9230    buf = s390_emit_PFPO(buf);
   9231    return buf;
   9232 
   9233  fail:
   9234    vpanic("s390_insn_fp_convert_emit");
   9235 }
   9236 
   9237 
   9238 static UChar *
   9239 s390_insn_mfence_emit(UChar *buf, const s390_insn *insn)
   9240 {
   9241    return s390_emit_BCR(buf, 0xF, 0x0);
   9242 }
   9243 
   9244 
   9245 static UChar *
   9246 s390_insn_mimm_emit(UChar *buf, const s390_insn *insn)
   9247 {
   9248    s390_amode *am = insn->variant.mimm.dst;
   9249    UChar b = hregNumber(am->b);
   9250    Int   d = am->d;
   9251    ULong value = insn->variant.mimm.value;
   9252 
   9253    if (value == 0) {
   9254       return s390_emit_XC(buf, insn->size - 1, b, d, b, d);
   9255    }
   9256 
   9257    if (insn->size == 1) {
   9258       return s390_emit_MVI(buf, value & 0xFF, b, d);
   9259    }
   9260 
   9261    if (s390_host_has_gie && ulong_fits_signed_16bit(value)) {
   9262       value &= 0xFFFF;
   9263       switch (insn->size) {
   9264       case 2: return s390_emit_MVHHI(buf, b, d, value);
   9265       case 4: return s390_emit_MVHI(buf,  b, d, value);
   9266       case 8: return s390_emit_MVGHI(buf, b, d, value);
   9267       }
   9268    } else {
   9269       // Load value to R0, then store.
   9270       switch (insn->size) {
   9271       case 2:
   9272          buf = s390_emit_LHI(buf, R0, value & 0xFFFF);
   9273          return s390_emit_STH(buf, R0, 0, b, d);
   9274       case 4:
   9275          buf = s390_emit_load_32imm(buf, R0, value);
   9276          return s390_emit_ST(buf, R0, 0, b, d);
   9277       case 8:
   9278          buf = s390_emit_load_64imm(buf, R0, value);
   9279          return s390_emit_STG(buf, R0, 0, b, DISP20(d));
   9280       }
   9281    }
   9282 
   9283    vpanic("s390_insn_mimm_emit");
   9284 }
   9285 
   9286 
   9287 static UChar *
   9288 s390_insn_madd_emit(UChar *buf, const s390_insn *insn)
   9289 {
   9290    s390_amode *am = insn->variant.madd.dst;
   9291    UChar b = hregNumber(am->b);
   9292    Int   d = am->d;
   9293 
   9294    if (insn->size == 4) {
   9295       return s390_emit_ASI(buf, insn->variant.madd.delta, b, DISP20(d));
   9296    }
   9297 
   9298    return s390_emit_AGSI(buf, insn->variant.madd.delta, b, DISP20(d));
   9299 }
   9300 
   9301 
   9302 static UChar *
   9303 s390_insn_set_fpc_bfprm_emit(UChar *buf, const s390_insn *insn)
   9304 {
   9305    UInt mode = hregNumber(insn->variant.set_fpc_bfprm.mode);
   9306 
   9307    /* Copy FPC from guest state to R0 and OR in the new rounding mode */
   9308    buf = s390_emit_L(buf, R0, 0, S390_REGNO_GUEST_STATE_POINTER,
   9309                      S390X_GUEST_OFFSET(guest_fpc));   // r0 = guest_fpc
   9310 
   9311    buf = s390_emit_NILL(buf, R0, 0xFFF8); /* Clear out right-most 3 bits */
   9312    buf = s390_emit_OR(buf, R0, mode);     /* OR in the new rounding mode */
   9313    buf = s390_emit_SFPC(buf, R0);         /* Load FPC register from R0 */
   9314 
   9315    return buf;
   9316 }
   9317 
   9318 
   9319 static UChar *
   9320 s390_insn_set_fpc_dfprm_emit(UChar *buf, const s390_insn *insn)
   9321 {
   9322    UInt mode = hregNumber(insn->variant.set_fpc_dfprm.mode);
   9323 
   9324    /* Copy FPC from guest state to R0 and OR in the new rounding mode */
   9325    buf = s390_emit_L(buf, R0, 0, S390_REGNO_GUEST_STATE_POINTER,
   9326                      S390X_GUEST_OFFSET(guest_fpc));   // r0 = guest_fpc
   9327 
   9328    /* DFP rounding mode is set at bit position 25:27 in FPC register */
   9329    buf = s390_emit_NILL(buf, R0, 0xFF8F); /* Clear out 25:27 bits */
   9330    buf = s390_emit_SLL(buf, mode, 0, 4);  /* bring mode to 25:27 bits */
   9331    buf = s390_emit_OR(buf, R0, mode);     /* OR in the new rounding mode */
   9332    buf = s390_emit_SFPC(buf, R0);         /* Load FPC register from R0 */
   9333 
   9334    return buf;
   9335 }
   9336 
   9337 
   9338 /* Define convenience functions needed for translation chaining.
   9339    Any changes need to be applied to the functions in concert. */
   9340 
   9341 static __inline__ Bool
   9342 s390_insn_is_BRCL(const UChar *p, UChar condition)
   9343 {
   9344    return p[0] == 0xc0 && p[1] == ((condition << 4) | 0x04);
   9345 }
   9346 
   9347 static __inline__ Bool
   9348 s390_insn_is_BR(const UChar *p, UChar reg)
   9349 {
   9350    return p[0] == 0x07 && p[1] == (0xF0 | reg);  /* BCR 15,reg */
   9351 }
   9352 
   9353 
   9354 /* The length of the BASR insn */
   9355 #define S390_BASR_LEN  2
   9356 
   9357 
   9358 /* Load the 64-bit VALUE into REG. Note that this function must NOT
   9359    optimise the generated code by looking at the value. I.e. using
   9360    LGHI if value == 0 would be very wrong. */
   9361 static UChar *
   9362 s390_tchain_load64(UChar *buf, UChar regno, ULong value)
   9363 {
   9364    UChar *begin = buf;
   9365 
   9366    if (s390_host_has_eimm) {
   9367       /* Do it in two steps: upper half [0:31] and lower half [32:63] */
   9368       buf = s390_emit_IIHF(buf, regno, value >> 32);
   9369       buf = s390_emit_IILF(buf, regno, value & 0xFFFFFFFF);
   9370    } else {
   9371       buf = s390_emit_IILL(buf, regno, value & 0xFFFF);
   9372       value >>= 16;
   9373       buf = s390_emit_IILH(buf, regno, value & 0xFFFF);
   9374       value >>= 16;
   9375       buf = s390_emit_IIHL(buf, regno, value & 0xFFFF);
   9376       value >>= 16;
   9377       buf = s390_emit_IIHH(buf, regno, value & 0xFFFF);
   9378    }
   9379 
   9380    vassert(buf - begin == s390_tchain_load64_len());
   9381 
   9382    return buf;
   9383 }
   9384 
   9385 /* Return number of bytes generated by s390_tchain_load64 */
   9386 static UInt
   9387 s390_tchain_load64_len(void)
   9388 {
   9389    if (s390_host_has_eimm) {
   9390       return 6 + 6;      /* IIHF + IILF */
   9391    }
   9392    return 4 + 4 + 4 + 4; /* IIHH + IIHL + IILH + IILL */
   9393 }
   9394 
   9395 /* Verify that CODE is the code sequence generated by s390_tchain_load64
   9396    to load VALUE into REGNO. Return pointer to the byte following the
   9397    insn sequence. */
   9398 static const UChar *
   9399 s390_tchain_verify_load64(const UChar *code, UChar regno, ULong value)
   9400 {
   9401    UInt regmask = regno << 4;
   9402    UInt hw;
   9403 
   9404    if (s390_host_has_eimm) {
   9405       /* Check for IIHF */
   9406       vassert(code[0]  ==  0xC0);
   9407       vassert(code[1]  == (0x08 | regmask));
   9408       vassert(*(const UInt *)&code[2] == (value >> 32));
   9409       /* Check for IILF */
   9410       vassert(code[6]  ==  0xC0);
   9411       vassert(code[7]  == (0x09 | regmask));
   9412       vassert(*(const UInt *)&code[8] == (value & 0xFFFFFFFF));
   9413    } else {
   9414       /* Check for IILL */
   9415       hw = value & 0xFFFF;
   9416       vassert(code[0]  ==  0xA5);
   9417       vassert(code[1]  == (0x03 | regmask));
   9418       vassert(code[2]  == (hw >> 8));
   9419       vassert(code[3]  == (hw & 0xFF));
   9420 
   9421       /* Check for IILH */
   9422       hw = (value >> 16) & 0xFFFF;
   9423       vassert(code[4]  ==  0xA5);
   9424       vassert(code[5]  == (0x02 | regmask));
   9425       vassert(code[6]  == (hw >> 8));
   9426       vassert(code[7]  == (hw & 0xFF));
   9427 
   9428       /* Check for IIHL */
   9429       hw = (value >> 32) & 0xFFFF;
   9430       vassert(code[8]  ==  0xA5);
   9431       vassert(code[9]  == (0x01 | regmask));
   9432       vassert(code[10] == (hw >> 8));
   9433       vassert(code[11] == (hw & 0xFF));
   9434 
   9435       /* Check for IIHH */
   9436       hw = (value >> 48) & 0xFFFF;
   9437       vassert(code[12] ==  0xA5);
   9438       vassert(code[13] == (0x00 | regmask));
   9439       vassert(code[14] == (hw >> 8));
   9440       vassert(code[15] == (hw & 0xFF));
   9441    }
   9442 
   9443    return code + s390_tchain_load64_len();
   9444 }
   9445 
   9446 /* CODE points to the code sequence as generated by s390_tchain_load64.
   9447    Change the loaded value to IMM64. Return pointer to the byte following
   9448    the patched code sequence. */
   9449 static UChar *
   9450 s390_tchain_patch_load64(UChar *code, ULong imm64)
   9451 {
   9452    if (s390_host_has_eimm) {
   9453       /* Patch IIHF */
   9454       *(UInt *)&code[2] = imm64 >> 32;
   9455       /* Patch IILF */
   9456       *(UInt *)&code[8] = imm64 & 0xFFFFFFFF;
   9457    } else {
   9458       code[3]  = imm64 & 0xFF; imm64 >>= 8;
   9459       code[2]  = imm64 & 0xFF; imm64 >>= 8;
   9460       code[7]  = imm64 & 0xFF; imm64 >>= 8;
   9461       code[6]  = imm64 & 0xFF; imm64 >>= 8;
   9462       code[11] = imm64 & 0xFF; imm64 >>= 8;
   9463       code[10] = imm64 & 0xFF; imm64 >>= 8;
   9464       code[15] = imm64 & 0xFF; imm64 >>= 8;
   9465       code[14] = imm64 & 0xFF; imm64 >>= 8;
   9466    }
   9467 
   9468    return code + s390_tchain_load64_len();
   9469 }
   9470 
   9471 
   9472 /* NB: what goes on here has to be very closely coordinated with the
   9473    chainXDirect_S390 and unchainXDirect_S390 below. */
   9474 static UChar *
   9475 s390_insn_xdirect_emit(UChar *buf, const s390_insn *insn,
   9476                        const void *disp_cp_chain_me_to_slowEP,
   9477                        const void *disp_cp_chain_me_to_fastEP)
   9478 {
   9479    /* We're generating chain-me requests here, so we need to be
   9480       sure this is actually allowed -- no-redir translations can't
   9481       use chain-me's.  Hence: */
   9482    vassert(disp_cp_chain_me_to_slowEP != NULL);
   9483    vassert(disp_cp_chain_me_to_fastEP != NULL);
   9484 
   9485    /* Use ptmp for backpatching conditional jumps. */
   9486    UChar *ptmp = buf;
   9487 
   9488    /* First off, if this is conditional, create a conditional
   9489       jump over the rest of it. */
   9490    s390_cc_t cond = insn->variant.xdirect.cond;
   9491 
   9492    if (cond != S390_CC_ALWAYS) {
   9493       /* So we have something like this
   9494          if (cond) do_xdirect;
   9495          Y: ...
   9496          We convert this into
   9497          if (! cond) goto Y;        // BRC opcode; 4 bytes
   9498          do_xdirect;
   9499          Y:
   9500       */
   9501       /* 4 bytes (a BRC insn) to be filled in here */
   9502       buf += 4;
   9503    }
   9504 
   9505    /* Update the guest IA. */
   9506    buf = s390_emit_load_64imm(buf, R0, insn->variant.xdirect.dst);
   9507 
   9508    const s390_amode *amode = insn->variant.xdirect.guest_IA;
   9509    vassert(amode->tag == S390_AMODE_B12);
   9510    UInt b = hregNumber(amode->b);
   9511    UInt d = amode->d;
   9512 
   9513    buf = s390_emit_STG(buf, R0, 0, b, DISP20(d));
   9514 
   9515    /* Load the chosen entry point into the scratch reg */
   9516    const void *disp_cp_chain_me;
   9517 
   9518    disp_cp_chain_me =
   9519       insn->variant.xdirect.to_fast_entry ? disp_cp_chain_me_to_fastEP
   9520                                           : disp_cp_chain_me_to_slowEP;
   9521    /* Get the address of the beginning of the load64 code sequence into %r1.
   9522       Do not change the register! This is part of the protocol with the
   9523       dispatcher. */
   9524    buf = s390_emit_BASR(buf, 1, R0);
   9525 
   9526    /* --- FIRST PATCHABLE BYTE follows (must not modify %r1) --- */
   9527    Addr64 addr = (Addr)disp_cp_chain_me;
   9528    buf = s390_tchain_load64(buf, S390_REGNO_TCHAIN_SCRATCH, addr);
   9529 
   9530    /* goto *tchain_scratch */
   9531    buf = s390_emit_BCR(buf, S390_CC_ALWAYS, S390_REGNO_TCHAIN_SCRATCH);
   9532 
   9533    /* --- END of PATCHABLE BYTES --- */
   9534 
   9535    /* Fix up the conditional jump, if there was one. */
   9536    if (cond != S390_CC_ALWAYS) {
   9537       Int delta = buf - ptmp;
   9538 
   9539       delta >>= 1;  /* immediate constant is #half-words */
   9540       vassert(delta > 0 && delta < (1 << 16));
   9541       s390_emit_BRC(ptmp, s390_cc_invert(cond), delta);
   9542    }
   9543 
   9544    return buf;
   9545 }
   9546 
   9547 /* Return the number of patchable bytes from an xdirect insn. */
   9548 static UInt
   9549 s390_xdirect_patchable_len(void)
   9550 {
   9551    return s390_tchain_load64_len() + S390_BASR_LEN;
   9552 }
   9553 
   9554 
   9555 static UChar *
   9556 s390_insn_xindir_emit(UChar *buf, const s390_insn *insn,
   9557                       const void *disp_cp_xindir)
   9558 {
   9559    /* We're generating transfers that could lead indirectly to a
   9560       chain-me, so we need to be sure this is actually allowed --
   9561       no-redir translations are not allowed to reach normal
   9562       translations without going through the scheduler.  That means
   9563       no XDirects or XIndirs out from no-redir translations.
   9564       Hence: */
   9565    vassert(disp_cp_xindir != NULL);
   9566 
   9567    /* Use ptmp for backpatching conditional jumps. */
   9568    UChar *ptmp = buf;
   9569 
   9570    /* First off, if this is conditional, create a conditional
   9571       jump over the rest of it. */
   9572    s390_cc_t cond = insn->variant.xdirect.cond;
   9573 
   9574    if (cond != S390_CC_ALWAYS) {
   9575       /* So we have something like this
   9576          if (cond) do_xdirect;
   9577          Y: ...
   9578          We convert this into
   9579          if (! cond) goto Y;        // BRC opcode; 4 bytes
   9580          do_xdirect;
   9581          Y:
   9582       */
   9583       /* 4 bytes (a BRC insn) to be filled in here */
   9584       buf += 4;
   9585    }
   9586 
   9587    /* Update the guest IA with the address in xdirect.dst. */
   9588    const s390_amode *amode = insn->variant.xindir.guest_IA;
   9589 
   9590    vassert(amode->tag == S390_AMODE_B12);
   9591    UInt b = hregNumber(amode->b);
   9592    UInt d = amode->d;
   9593    UInt regno = hregNumber(insn->variant.xindir.dst);
   9594 
   9595    buf = s390_emit_STG(buf, regno, 0, b, DISP20(d));
   9596 
   9597    /* load tchain_scratch, #disp_indir */
   9598    buf = s390_tchain_load64(buf, S390_REGNO_TCHAIN_SCRATCH,
   9599                             (Addr)disp_cp_xindir);
   9600    /* goto *tchain_direct */
   9601    buf = s390_emit_BCR(buf, S390_CC_ALWAYS, S390_REGNO_TCHAIN_SCRATCH);
   9602 
   9603    /* Fix up the conditional jump, if there was one. */
   9604    if (cond != S390_CC_ALWAYS) {
   9605       Int delta = buf - ptmp;
   9606 
   9607       delta >>= 1;  /* immediate constant is #half-words */
   9608       vassert(delta > 0 && delta < (1 << 16));
   9609       s390_emit_BRC(ptmp, s390_cc_invert(cond), delta);
   9610    }
   9611 
   9612    return buf;
   9613 }
   9614 
   9615 static UChar *
   9616 s390_insn_xassisted_emit(UChar *buf, const s390_insn *insn,
   9617                          const void *disp_cp_xassisted)
   9618 {
   9619    /* Use ptmp for backpatching conditional jumps. */
   9620    UChar *ptmp = buf;
   9621 
   9622    /* First off, if this is conditional, create a conditional
   9623       jump over the rest of it. */
   9624    s390_cc_t cond = insn->variant.xdirect.cond;
   9625 
   9626    if (cond != S390_CC_ALWAYS) {
   9627       /* So we have something like this
   9628          if (cond) do_xdirect;
   9629          Y: ...
   9630          We convert this into
   9631          if (! cond) goto Y;        // BRC opcode; 4 bytes
   9632          do_xdirect;
   9633          Y:
   9634       */
   9635       /* 4 bytes (a BRC insn) to be filled in here */
   9636       buf += 4;
   9637    }
   9638 
   9639    /* Update the guest IA with the address in xassisted.dst. */
   9640    const s390_amode *amode = insn->variant.xassisted.guest_IA;
   9641 
   9642    vassert(amode->tag == S390_AMODE_B12);
   9643    UInt b = hregNumber(amode->b);
   9644    UInt d = amode->d;
   9645    UInt regno = hregNumber(insn->variant.xassisted.dst);
   9646 
   9647    buf = s390_emit_STG(buf, regno, 0, b, DISP20(d));
   9648 
   9649    UInt trcval = 0;
   9650 
   9651    switch (insn->variant.xassisted.kind) {
   9652    case Ijk_ClientReq:   trcval = VEX_TRC_JMP_CLIENTREQ;   break;
   9653    case Ijk_Sys_syscall: trcval = VEX_TRC_JMP_SYS_SYSCALL; break;
   9654    case Ijk_Yield:       trcval = VEX_TRC_JMP_YIELD;       break;
   9655    case Ijk_EmWarn:      trcval = VEX_TRC_JMP_EMWARN;      break;
   9656    case Ijk_EmFail:      trcval = VEX_TRC_JMP_EMFAIL;      break;
   9657    case Ijk_MapFail:     trcval = VEX_TRC_JMP_MAPFAIL;     break;
   9658    case Ijk_NoDecode:    trcval = VEX_TRC_JMP_NODECODE;    break;
   9659    case Ijk_InvalICache: trcval = VEX_TRC_JMP_INVALICACHE; break;
   9660    case Ijk_NoRedir:     trcval = VEX_TRC_JMP_NOREDIR;     break;
   9661    case Ijk_SigTRAP:     trcval = VEX_TRC_JMP_SIGTRAP;     break;
   9662    case Ijk_SigSEGV:     trcval = VEX_TRC_JMP_SIGSEGV;     break;
   9663    case Ijk_Boring:      trcval = VEX_TRC_JMP_BORING;      break;
   9664       /* We don't expect to see the following being assisted. */
   9665    case Ijk_Ret:
   9666    case Ijk_Call:
   9667       /* fallthrough */
   9668    default:
   9669       ppIRJumpKind(insn->variant.xassisted.kind);
   9670       vpanic("s390_insn_xassisted_emit: unexpected jump kind");
   9671    }
   9672 
   9673    vassert(trcval != 0);
   9674 
   9675    /* guest_state_pointer = trcval */
   9676    buf = s390_emit_LGHI(buf, S390_REGNO_GUEST_STATE_POINTER, trcval);
   9677 
   9678    /* load tchain_scratch, #disp_assisted */
   9679    buf = s390_tchain_load64(buf, S390_REGNO_TCHAIN_SCRATCH,
   9680                             (Addr)disp_cp_xassisted);
   9681 
   9682    /* goto *tchain_direct */
   9683    buf = s390_emit_BCR(buf, S390_CC_ALWAYS, S390_REGNO_TCHAIN_SCRATCH);
   9684 
   9685    /* Fix up the conditional jump, if there was one. */
   9686    if (cond != S390_CC_ALWAYS) {
   9687       Int delta = buf - ptmp;
   9688 
   9689       delta >>= 1;  /* immediate constant is #half-words */
   9690       vassert(delta > 0 && delta < (1 << 16));
   9691       s390_emit_BRC(ptmp, s390_cc_invert(cond), delta);
   9692    }
   9693 
   9694    return buf;
   9695 }
   9696 
   9697 
   9698 /* Pseudo code:
   9699 
   9700    guest_state[host_EvC_COUNTER] -= 1;
   9701    if (guest_state[host_EvC_COUNTER] >= 0) goto nofail;
   9702    goto guest_state[host_EvC_FAILADDR];
   9703    nofail: ;
   9704 
   9705    The dispatch counter is a 32-bit value. */
   9706 static UChar *
   9707 s390_insn_evcheck_emit(UChar *buf, const s390_insn *insn,
   9708                        VexEndness endness_host)
   9709 {
   9710    s390_amode *amode;
   9711    UInt b, d;
   9712    UChar *code_begin, *code_end;
   9713 
   9714    code_begin = buf;
   9715 
   9716    amode = insn->variant.evcheck.counter;
   9717    vassert(amode->tag == S390_AMODE_B12);
   9718    b = hregNumber(amode->b);
   9719    d = amode->d;
   9720 
   9721    /* Decrement the dispatch counter in the guest state */
   9722    if (s390_host_has_gie) {
   9723       buf = s390_emit_ASI(buf, -1, b, DISP20(d));   /* 6 bytes */
   9724    } else {
   9725       buf = s390_emit_LHI(buf, R0, -1);             /* 4 bytes */
   9726       buf = s390_emit_A(buf, R0, 0, b, d);          /* 4 bytes */
   9727       buf = s390_emit_ST(buf, R0, 0, b, d);         /* 4 bytes */
   9728    }
   9729 
   9730    /* Jump over the next insn if >= 0 */
   9731    buf = s390_emit_BRC(buf, S390_CC_HE, (4 + 6 + 2) / 2);  /* 4 bytes */
   9732 
   9733    /* Computed goto to fail_address */
   9734    amode = insn->variant.evcheck.fail_addr;
   9735    b = hregNumber(amode->b);
   9736    d = amode->d;
   9737    buf = s390_emit_LG(buf, S390_REGNO_TCHAIN_SCRATCH, 0, b, DISP20(d));  /* 6 bytes */
   9738    buf = s390_emit_BCR(buf, S390_CC_ALWAYS, S390_REGNO_TCHAIN_SCRATCH);  /* 2 bytes */
   9739 
   9740    code_end = buf;
   9741 
   9742    /* Make sure the size of the generated code is identical to the size
   9743       returned by evCheckSzB_S390 */
   9744    vassert(evCheckSzB_S390() == code_end - code_begin);
   9745 
   9746    return buf;
   9747 }
   9748 
   9749 
   9750 static UChar *
   9751 s390_insn_profinc_emit(UChar *buf,
   9752                        const s390_insn *insn __attribute__((unused)))
   9753 {
   9754    /* Generate a code template to increment a memory location whose
   9755       address will be known later as an immediate value. This code
   9756       template will be patched once the memory location is known.
   9757       For now we do this with address == 0. */
   9758    buf = s390_tchain_load64(buf, S390_REGNO_TCHAIN_SCRATCH, 0);
   9759    if (s390_host_has_gie) {
   9760       buf = s390_emit_AGSI(buf, 1, S390_REGNO_TCHAIN_SCRATCH, DISP20(0));
   9761    } else {
   9762       buf = s390_emit_LGHI(buf, R0, 1);
   9763       buf = s390_emit_AG( buf, R0, 0, S390_REGNO_TCHAIN_SCRATCH, DISP20(0));
   9764       buf = s390_emit_STG(buf, R0, 0, S390_REGNO_TCHAIN_SCRATCH, DISP20(0));
   9765    }
   9766 
   9767    return buf;
   9768 }
   9769 
   9770 
   9771 Int
   9772 emit_S390Instr(Bool *is_profinc, UChar *buf, Int nbuf, const s390_insn *insn,
   9773                Bool mode64, VexEndness endness_host,
   9774                const void *disp_cp_chain_me_to_slowEP,
   9775                const void *disp_cp_chain_me_to_fastEP,
   9776                const void *disp_cp_xindir,
   9777                const void *disp_cp_xassisted)
   9778 {
   9779    UChar *end;
   9780 
   9781    /* Used to be 48 bytes. Make sure it stays low */
   9782    vassert(sizeof(s390_insn) == 32);
   9783 
   9784    switch (insn->tag) {
   9785    case S390_INSN_LOAD:
   9786       end = s390_insn_load_emit(buf, insn);
   9787       break;
   9788 
   9789    case S390_INSN_STORE:
   9790       end = s390_insn_store_emit(buf, insn);
   9791       break;
   9792 
   9793    case S390_INSN_MOVE:
   9794       end = s390_insn_move_emit(buf, insn);
   9795       break;
   9796 
   9797    case S390_INSN_MEMCPY:
   9798       end = s390_insn_memcpy_emit(buf, insn);
   9799       break;
   9800 
   9801    case S390_INSN_COND_MOVE:
   9802       end = s390_insn_cond_move_emit(buf, insn);
   9803       break;
   9804 
   9805    case S390_INSN_LOAD_IMMEDIATE:
   9806       end = s390_insn_load_immediate_emit(buf, insn);
   9807       break;
   9808 
   9809    case S390_INSN_ALU:
   9810       end = s390_insn_alu_emit(buf, insn);
   9811       break;
   9812 
   9813    case S390_INSN_SMUL:
   9814    case S390_INSN_UMUL:
   9815       end = s390_insn_mul_emit(buf, insn);
   9816       break;
   9817 
   9818    case S390_INSN_SDIV:
   9819    case S390_INSN_UDIV:
   9820       end = s390_insn_div_emit(buf, insn);
   9821       break;
   9822 
   9823    case S390_INSN_DIVS:
   9824       end = s390_insn_divs_emit(buf, insn);
   9825       break;
   9826 
   9827    case S390_INSN_CLZ:
   9828       end = s390_insn_clz_emit(buf, insn);
   9829       break;
   9830 
   9831    case S390_INSN_UNOP:
   9832       end = s390_insn_unop_emit(buf, insn);
   9833       break;
   9834 
   9835    case S390_INSN_TEST:
   9836       end = s390_insn_test_emit(buf, insn);
   9837       break;
   9838 
   9839    case S390_INSN_CC2BOOL:
   9840       end = s390_insn_cc2bool_emit(buf, insn);
   9841       break;
   9842 
   9843    case S390_INSN_CAS:
   9844       end = s390_insn_cas_emit(buf, insn);
   9845       break;
   9846 
   9847    case S390_INSN_CDAS:
   9848       end = s390_insn_cdas_emit(buf, insn);
   9849       break;
   9850 
   9851    case S390_INSN_COMPARE:
   9852       end = s390_insn_compare_emit(buf, insn);
   9853       break;
   9854 
   9855    case S390_INSN_HELPER_CALL:
   9856       end = s390_insn_helper_call_emit(buf, insn);
   9857       if (end == buf) goto fail;
   9858       break;
   9859 
   9860    case S390_INSN_BFP_TRIOP:
   9861       end = s390_insn_bfp_triop_emit(buf, insn);
   9862       break;
   9863 
   9864    case S390_INSN_BFP_BINOP:
   9865       end = s390_insn_bfp_binop_emit(buf, insn);
   9866       break;
   9867 
   9868    case S390_INSN_BFP_UNOP:
   9869       end = s390_insn_bfp_unop_emit(buf, insn);
   9870       break;
   9871 
   9872    case S390_INSN_BFP_COMPARE:
   9873       end = s390_insn_bfp_compare_emit(buf, insn);
   9874       break;
   9875 
   9876    case S390_INSN_BFP_CONVERT:
   9877       end = s390_insn_bfp_convert_emit(buf, insn);
   9878       break;
   9879 
   9880    case S390_INSN_DFP_BINOP:
   9881       end = s390_insn_dfp_binop_emit(buf, insn);
   9882       break;
   9883 
   9884    case S390_INSN_DFP_UNOP:
   9885       end = s390_insn_dfp_unop_emit(buf, insn);
   9886       break;
   9887 
   9888    case S390_INSN_DFP_INTOP:
   9889       end = s390_insn_dfp_intop_emit(buf, insn);
   9890       break;
   9891 
   9892    case S390_INSN_DFP_COMPARE:
   9893       end = s390_insn_dfp_compare_emit(buf, insn);
   9894       break;
   9895 
   9896    case S390_INSN_DFP_CONVERT:
   9897       end = s390_insn_dfp_convert_emit(buf, insn);
   9898       break;
   9899 
   9900    case S390_INSN_DFP_REROUND:
   9901       end = s390_insn_dfp_reround_emit(buf, insn);
   9902       break;
   9903 
   9904    case S390_INSN_FP_CONVERT:
   9905       end = s390_insn_fp_convert_emit(buf, insn);
   9906       break;
   9907 
   9908    case S390_INSN_MFENCE:
   9909       end = s390_insn_mfence_emit(buf, insn);
   9910       break;
   9911 
   9912    case S390_INSN_MIMM:
   9913       end = s390_insn_mimm_emit(buf, insn);
   9914       break;
   9915 
   9916    case S390_INSN_MADD:
   9917       end = s390_insn_madd_emit(buf, insn);
   9918       break;
   9919 
   9920    case S390_INSN_SET_FPC_BFPRM:
   9921       end = s390_insn_set_fpc_bfprm_emit(buf, insn);
   9922       break;
   9923 
   9924    case S390_INSN_SET_FPC_DFPRM:
   9925       end = s390_insn_set_fpc_dfprm_emit(buf, insn);
   9926       break;
   9927 
   9928    case S390_INSN_PROFINC:
   9929       end = s390_insn_profinc_emit(buf, insn);
   9930       /* Tell the caller .. */
   9931       vassert(*is_profinc == False);
   9932       *is_profinc = True;
   9933       break;
   9934 
   9935    case S390_INSN_EVCHECK:
   9936       end = s390_insn_evcheck_emit(buf, insn, endness_host);
   9937       break;
   9938 
   9939    case S390_INSN_XDIRECT:
   9940       end = s390_insn_xdirect_emit(buf, insn, disp_cp_chain_me_to_slowEP,
   9941                                    disp_cp_chain_me_to_fastEP);
   9942       break;
   9943 
   9944    case S390_INSN_XINDIR:
   9945       end = s390_insn_xindir_emit(buf, insn, disp_cp_xindir);
   9946       break;
   9947 
   9948    case S390_INSN_XASSISTED:
   9949       end = s390_insn_xassisted_emit(buf, insn, disp_cp_xassisted);
   9950       break;
   9951 
   9952    fail:
   9953    default:
   9954       vpanic("emit_S390Instr");
   9955    }
   9956 
   9957    vassert(end - buf <= nbuf);
   9958 
   9959    return end - buf;
   9960 }
   9961 
   9962 
   9963 /* Return the number of bytes emitted for an S390_INSN_EVCHECK.
   9964    See s390_insn_evcheck_emit */
   9965 Int
   9966 evCheckSzB_S390(void)
   9967 {
   9968    return s390_host_has_gie ? 18 : 24;
   9969 }
   9970 
   9971 
   9972 /* Patch the counter address into CODE_TO_PATCH as previously
   9973    generated by s390_insn_profinc_emit. */
   9974 VexInvalRange
   9975 patchProfInc_S390(VexEndness endness_host,
   9976                   void *code_to_patch, const ULong *location_of_counter)
   9977 {
   9978    vassert(sizeof(ULong *) == 8);
   9979 
   9980    s390_tchain_verify_load64(code_to_patch, S390_REGNO_TCHAIN_SCRATCH, 0);
   9981 
   9982    UChar *p = s390_tchain_patch_load64(code_to_patch,
   9983                                        (Addr)location_of_counter);
   9984 
   9985    UInt len = p - (UChar *)code_to_patch;
   9986    VexInvalRange vir = { (HWord)code_to_patch, len };
   9987    return vir;
   9988 }
   9989 
   9990 
   9991 /* NB: what goes on here has to be very closely coordinated with the
   9992    s390_insn_xdirect_emit code above. */
   9993 VexInvalRange
   9994 chainXDirect_S390(VexEndness endness_host,
   9995                   void *place_to_chain,
   9996                   const void *disp_cp_chain_me_EXPECTED,
   9997                   const void *place_to_jump_to)
   9998 {
   9999    vassert(endness_host == VexEndnessBE);
   10000 
   10001    /* What we're expecting to see @ PLACE_TO_CHAIN is:
   10002 
   10003         load  tchain_scratch, #disp_cp_chain_me_EXPECTED
   10004         goto *tchain_scratch
   10005    */
   10006    const UChar *next;
   10007    next = s390_tchain_verify_load64(place_to_chain, S390_REGNO_TCHAIN_SCRATCH,
   10008                                     (Addr)disp_cp_chain_me_EXPECTED);
   10009    vassert(s390_insn_is_BR(next, S390_REGNO_TCHAIN_SCRATCH));
   10010 
   10011    /* And what we want to change it to is either:
   10012         (general case):
   10013 
   10014           load  tchain_scratch, #place_to_jump_to
   10015           goto *tchain_scratch
   10016 
   10017       ---OR---
   10018 
   10019         in the case where the displacement is small enough
   10020 
   10021           BRCL delta       where delta is in half-words
   10022           invalid opcodes
   10023 
   10024       In both cases the replacement has the same length as the original.
   10025       To remain sane & verifiable,
   10026       (1) limit the displacement for the short form to
   10027           (say) +/- one billion, so as to avoid wraparound
   10028           off-by-ones
   10029       (2) even if the short form is applicable, once every (say)
   10030           1024 times use the long form anyway, so as to maintain
   10031           verifiability
   10032    */
   10033 
   10034    /* This is the delta we need to put into a BRCL insn. Note, that the
   10035       offset in BRCL is in half-words. Hence division by 2. */
   10036    Long delta =
   10037       (Long)((const UChar *)place_to_jump_to - (const UChar *)place_to_chain) / 2;
   10038    Bool shortOK = delta >= -1000*1000*1000 && delta < 1000*1000*1000;
   10039 
   10040    static UInt shortCTR = 0; /* DO NOT MAKE NON-STATIC */
   10041    if (shortOK) {
   10042       shortCTR++; // thread safety bleh
   10043       if (0 == (shortCTR & 0x3FF)) {
   10044          shortOK = False;
   10045          if (0)
   10046             vex_printf("QQQ chainXDirect_S390: shortCTR = %u, "
   10047                        "using long jmp\n", shortCTR);
   10048       }
   10049    }
   10050 
   10051    /* And make the modifications. */
   10052    UChar *p = (UChar *)place_to_chain;
   10053    if (shortOK) {
   10054       p = s390_emit_BRCL(p, S390_CC_ALWAYS, delta);  /* 6 bytes */
   10055 
   10056       /* Make sure that BRCL fits into the patchable part of an xdirect
   10057          code sequence */
   10058       vassert(6 <= s390_xdirect_patchable_len());
   10059 
   10060       /* Fill remaining bytes with 0x00 (invalid opcode) */
   10061       Int i;
   10062       for (i = 0; i < s390_xdirect_patchable_len() - 6; ++i)
   10063          p[i] = 0x00;
   10064    } else {
   10065       /*
   10066           load  tchain_scratch, #place_to_jump_to
   10067           goto *tchain_scratch
   10068       */
   10069       Addr64 addr = (Addr)place_to_jump_to;
   10070       p = s390_tchain_load64(p, S390_REGNO_TCHAIN_SCRATCH, addr);
   10071       /* There is not need to emit a BCR here, as it is already there. */
   10072    }
   10073 
   10074    UInt len = p - (UChar *)place_to_chain;
   10075    VexInvalRange vir = { (HWord)place_to_chain, len };
   10076    return vir;
   10077 }
   10078 
   10079 
   10080 /* NB: what goes on here has to be very closely coordinated with the
   10081    s390_insn_xdirect_emit code above. */
   10082 VexInvalRange
   10083 unchainXDirect_S390(VexEndness endness_host,
   10084                     void *place_to_unchain,
   10085                     const void *place_to_jump_to_EXPECTED,
   10086                     const void *disp_cp_chain_me)
   10087 {
   10088    vassert(endness_host == VexEndnessBE);
   10089 
   10090    /* What we're expecting to see @ PLACE_TO_UNCHAIN:
   10091 
   10092           load  tchain_scratch, #place_to_jump_to_EXPECTED
   10093           goto *tchain_scratch
   10094 
   10095       ---OR---
   10096         in the case where the displacement falls within 32 bits
   10097 
   10098           BRCL delta
   10099           invalid opcodes
   10100    */
   10101    UChar *p = place_to_unchain;
   10102 
   10103    Bool uses_short_form = False;
   10104 
   10105    if (s390_insn_is_BRCL(p, S390_CC_ALWAYS)) {
   10106       /* Looks like the short form */
   10107       Int num_hw = *(Int *)&p[2];
   10108       Int delta = 2 *num_hw;
   10109 
   10110       vassert(p + delta == place_to_jump_to_EXPECTED);
   10111 
   10112       Int i;
   10113       for (i = 0; i < s390_xdirect_patchable_len() - 6; ++i)
   10114          vassert(p[6+i] == 0x00);
   10115       uses_short_form = True;
   10116    } else {
   10117       /* Should be the long form */
   10118       const UChar *next;
   10119 
   10120       next = s390_tchain_verify_load64(p, S390_REGNO_TCHAIN_SCRATCH,
   10121                                        (Addr)place_to_jump_to_EXPECTED);
   10122       /* Check for BR *tchain_scratch */
   10123       vassert(s390_insn_is_BR(next, S390_REGNO_TCHAIN_SCRATCH));
   10124    }
   10125 
   10126    /* And what we want to change it to is:
   10127 
   10128         load  tchain_scratch, #disp_cp_chain_me
   10129         goto *tchain_scratch
   10130    */
   10131 
   10132    /* Get the address of the beginning of the load64 code sequence into %r1.
   10133       Do not change the register! This is part of the protocol with the
   10134       dispatcher.
   10135       Note: the incoming argument PLACE_TO_CHAIN points to the beginning of the
   10136       load64 insn sequence. That sequence is prefixed with a BASR to get its
   10137       address (see s390_insn_xdirect_emit).  */
   10138    p = s390_emit_BASR(p - S390_BASR_LEN, 1, R0);
   10139 
   10140    Addr64 addr = (Addr)disp_cp_chain_me;
   10141    p = s390_tchain_load64(p, S390_REGNO_TCHAIN_SCRATCH, addr);
   10142 
   10143    /* Emit the BCR in case the short form was used. In case of the long
   10144       form, the BCR is already there. */
   10145    if (uses_short_form)
   10146       s390_emit_BCR(p, S390_CC_ALWAYS, S390_REGNO_TCHAIN_SCRATCH);
   10147 
   10148    UInt len = p - (UChar *)place_to_unchain;
   10149    VexInvalRange vir = { (HWord)place_to_unchain, len };
   10150    return vir;
   10151 }
   10152 
   10153 /*---------------------------------------------------------------*/
   10154 /*--- end                                    host_s390_defs.c ---*/
   10155 /*---------------------------------------------------------------*/
   10156