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