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