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