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