• 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-2012
12 
13    This program is free software; you can redistribute it and/or
14    modify it under the terms of the GNU General Public License as
15    published by the Free Software Foundation; either version 2 of the
16    License, or (at your option) any later version.
17 
18    This program is distributed in the hope that it will be useful, but
19    WITHOUT ANY WARRANTY; without even the implied warranty of
20    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21    General Public License for more details.
22 
23    You should have received a copy of the GNU General Public License
24    along with this program; if not, write to the Free Software
25    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
26    02110-1301, USA.
27 
28    The GNU General Public License is contained in the file COPYING.
29 */
30 
31 /* Contributed by Florian Krohm */
32 
33 #include "libvex_basictypes.h"
34 #include "libvex.h"
35 #include "libvex_trc_values.h"
36 #include "libvex_s390x_common.h"
37 
38 #include "main_util.h"
39 #include "main_globals.h"
40 #include "host_generic_regs.h"
41 #include "host_s390_defs.h"
42 #include "host_s390_disasm.h"
43 #include "guest_s390_defs.h"    /* S390X_GUEST_OFFSET */
44 #include <stdarg.h>
45 
46 /* KLUDGE: We need to know the hwcaps of the host when generating
47    code. But that info is not passed to emit_S390Instr. Only mode64 is
48    being passed. So, ideally, we want this passed as an argument, too.
49    Until then, we use a global variable. This variable is set as a side
50    effect of iselSB_S390. This is safe because instructions are selected
51    before they are emitted. */
52 UInt s390_host_hwcaps;
53 
54 
55 /*------------------------------------------------------------*/
56 /*--- Forward declarations                                 ---*/
57 /*------------------------------------------------------------*/
58 
59 static Bool s390_insn_is_reg_reg_move(const s390_insn *, HReg *src, HReg *dst);
60 static void s390_insn_map_regs(HRegRemap *, s390_insn *);
61 static void s390_insn_get_reg_usage(HRegUsage *u, const s390_insn *);
62 static UInt s390_tchain_load64_len(void);
63 
64 
65 /*------------------------------------------------------------*/
66 /*--- Registers                                            ---*/
67 /*------------------------------------------------------------*/
68 
69 /* Decompile the given register into a static buffer and return it */
70 const HChar *
s390_hreg_as_string(HReg reg)71 s390_hreg_as_string(HReg reg)
72 {
73    static HChar buf[10];
74 
75    static const HChar ireg_names[16][5] = {
76       "%r0",  "%r1",  "%r2",  "%r3",  "%r4",  "%r5",  "%r6",  "%r7",
77       "%r8",  "%r9",  "%r10", "%r11", "%r12", "%r13", "%r14", "%r15"
78    };
79 
80    static const HChar freg_names[16][5] = {
81       "%f0",  "%f1",  "%f2",  "%f3",  "%f4",  "%f5",  "%f6",  "%f7",
82       "%f8",  "%f9",  "%f10", "%f11", "%f12", "%f13", "%f14", "%f15"
83    };
84 
85    UInt r;  /* hregNumber() returns an UInt */
86 
87    r = hregNumber(reg);
88 
89    /* Be generic for all virtual regs. */
90    if (hregIsVirtual(reg)) {
91       buf[0] = '\0';
92       switch (hregClass(reg)) {
93       case HRcInt64: vex_sprintf(buf, "%%vR%d", r); break;
94       case HRcFlt64: vex_sprintf(buf, "%%vF%d", r); break;
95       default:       goto fail;
96       }
97       return buf;
98    }
99 
100    /* But specific for real regs. */
101    vassert(r < 16);
102 
103    switch (hregClass(reg)) {
104    case HRcInt64: return ireg_names[r];
105    case HRcFlt64: return freg_names[r];
106    default:       goto fail;
107    }
108 
109  fail: vpanic("s390_hreg_as_string");
110 }
111 
112 
113 /* Tell the register allocator which registers can be allocated. */
114 static void
s390_hreg_get_allocable(Int * nregs,HReg ** arr)115 s390_hreg_get_allocable(Int *nregs, HReg **arr)
116 {
117    UInt i;
118 
119    /* Total number of allocable registers (all classes) */
120    *nregs =  16 /* GPRs */
121       -  1 /* r0 */
122       -  1 /* r12 scratch register for translation chaining support */
123       -  1 /* r13 guest state pointer */
124       -  1 /* r14 link register */
125       -  1 /* r15 stack pointer */
126       + 16 /* FPRs */
127       ;
128 
129    *arr = LibVEX_Alloc(*nregs * sizeof(HReg));
130 
131    i = 0;
132 
133    /* GPR0 is not available because it is interpreted as 0, when used
134       as a base or index register. */
135    (*arr)[i++] = mkHReg(1,  HRcInt64, False);
136    (*arr)[i++] = mkHReg(2,  HRcInt64, False);
137    (*arr)[i++] = mkHReg(3,  HRcInt64, False);
138    (*arr)[i++] = mkHReg(4,  HRcInt64, False);
139    (*arr)[i++] = mkHReg(5,  HRcInt64, False);
140    (*arr)[i++] = mkHReg(6,  HRcInt64, False);
141    (*arr)[i++] = mkHReg(7,  HRcInt64, False);
142    (*arr)[i++] = mkHReg(8,  HRcInt64, False);
143    (*arr)[i++] = mkHReg(9,  HRcInt64, False);
144    /* GPR10 and GPR11 are used for instructions that use register pairs.
145       Otherwise, they are available to the allocator */
146    (*arr)[i++] = mkHReg(10, HRcInt64, False);
147    (*arr)[i++] = mkHReg(11, HRcInt64, False);
148    /* GPR12 is not available because it us used as a scratch register
149       in translation chaining. */
150    /* GPR13 is not available because it is used as guest state pointer */
151    /* GPR14 is not available because it is used as link register */
152    /* GPR15 is not available because it is used as stack pointer */
153 
154    /* Add the available real (non-virtual) FPRs */
155    (*arr)[i++] = mkHReg(0,  HRcFlt64, False);
156    (*arr)[i++] = mkHReg(1,  HRcFlt64, False);
157    (*arr)[i++] = mkHReg(2,  HRcFlt64, False);
158    (*arr)[i++] = mkHReg(3,  HRcFlt64, False);
159    (*arr)[i++] = mkHReg(4,  HRcFlt64, False);
160    (*arr)[i++] = mkHReg(5,  HRcFlt64, False);
161    (*arr)[i++] = mkHReg(6,  HRcFlt64, False);
162    (*arr)[i++] = mkHReg(7,  HRcFlt64, False);
163    (*arr)[i++] = mkHReg(8,  HRcFlt64, False);
164    (*arr)[i++] = mkHReg(9,  HRcFlt64, False);
165    (*arr)[i++] = mkHReg(10, HRcFlt64, False);
166    (*arr)[i++] = mkHReg(11, HRcFlt64, False);
167    (*arr)[i++] = mkHReg(12, HRcFlt64, False);
168    (*arr)[i++] = mkHReg(13, HRcFlt64, False);
169    (*arr)[i++] = mkHReg(14, HRcFlt64, False);
170    (*arr)[i++] = mkHReg(15, HRcFlt64, False);
171    /* FPR12 - FPR15 are also used as register pairs for 128-bit
172       floating point operations */
173 }
174 
175 
176 /* Return the real register that holds the guest state pointer */
177 HReg
s390_hreg_guest_state_pointer(void)178 s390_hreg_guest_state_pointer(void)
179 {
180    return mkHReg(S390_REGNO_GUEST_STATE_POINTER, HRcInt64, False);
181 }
182 
183 
184 /* Is VALUE within the domain of a 20-bit signed integer. */
185 static __inline__ Bool
fits_signed_20bit(Int value)186 fits_signed_20bit(Int value)
187 {
188    return ((value << 12) >> 12) == value;
189 }
190 
191 
192 /* Is VALUE within the domain of a 12-bit unsigned integer. */
193 static __inline__ Bool
fits_unsigned_12bit(Int value)194 fits_unsigned_12bit(Int value)
195 {
196    return (value & 0xFFF) == value;
197 }
198 
199 /*------------------------------------------------------------*/
200 /*--- Addressing modes (amodes)                            ---*/
201 /*------------------------------------------------------------*/
202 
203 /* Construct a b12 amode. */
204 s390_amode *
s390_amode_b12(Int d,HReg b)205 s390_amode_b12(Int d, HReg b)
206 {
207    s390_amode *am = LibVEX_Alloc(sizeof(s390_amode));
208 
209    vassert(fits_unsigned_12bit(d));
210 
211    am->tag = S390_AMODE_B12;
212    am->d = d;
213    am->b = b;
214    am->x = 0;  /* hregNumber(0) == 0 */
215 
216    return am;
217 }
218 
219 
220 /* Construct a b20 amode. */
221 s390_amode *
s390_amode_b20(Int d,HReg b)222 s390_amode_b20(Int d, HReg b)
223 {
224    s390_amode *am = LibVEX_Alloc(sizeof(s390_amode));
225 
226    vassert(fits_signed_20bit(d));
227 
228    am->tag = S390_AMODE_B20;
229    am->d = d;
230    am->b = b;
231    am->x = 0;  /* hregNumber(0) == 0 */
232 
233    return am;
234 }
235 
236 
237 /* Construct a bx12 amode. */
238 s390_amode *
s390_amode_bx12(Int d,HReg b,HReg x)239 s390_amode_bx12(Int d, HReg b, HReg x)
240 {
241    s390_amode *am = LibVEX_Alloc(sizeof(s390_amode));
242 
243    vassert(fits_unsigned_12bit(d));
244    vassert(b != 0);
245    vassert(x != 0);
246 
247    am->tag = S390_AMODE_BX12;
248    am->d = d;
249    am->b = b;
250    am->x = x;
251 
252    return am;
253 }
254 
255 
256 /* Construct a bx20 amode. */
257 s390_amode *
s390_amode_bx20(Int d,HReg b,HReg x)258 s390_amode_bx20(Int d, HReg b, HReg x)
259 {
260    s390_amode *am = LibVEX_Alloc(sizeof(s390_amode));
261 
262    vassert(fits_signed_20bit(d));
263    vassert(b != 0);
264    vassert(x != 0);
265 
266    am->tag = S390_AMODE_BX20;
267    am->d = d;
268    am->b = b;
269    am->x = x;
270 
271    return am;
272 }
273 
274 
275 /* Construct an AMODE for accessing the guest state at OFFSET */
276 s390_amode *
s390_amode_for_guest_state(Int offset)277 s390_amode_for_guest_state(Int offset)
278 {
279    if (fits_unsigned_12bit(offset))
280       return s390_amode_b12(offset, s390_hreg_guest_state_pointer());
281 
282    vpanic("invalid guest state offset");
283 }
284 
285 
286 /* Decompile the given amode into a static buffer and return it. */
287 const HChar *
s390_amode_as_string(const s390_amode * am)288 s390_amode_as_string(const s390_amode *am)
289 {
290    static HChar buf[30];
291    HChar *p;
292 
293    buf[0] = '\0';
294    p = buf;
295 
296    switch (am->tag) {
297    case S390_AMODE_B12:
298    case S390_AMODE_B20:
299       vex_sprintf(p, "%d(%s)", am->d, s390_hreg_as_string(am->b));
300       break;
301 
302    case S390_AMODE_BX12:
303    case S390_AMODE_BX20:
304       /* s390_hreg_as_string returns pointer to local buffer. Need to
305          split this into two printfs */
306       p += vex_sprintf(p, "%d(%s,", am->d, s390_hreg_as_string(am->x));
307       vex_sprintf(p, "%s)", s390_hreg_as_string(am->b));
308       break;
309 
310    default:
311       vpanic("s390_amode_as_string");
312    }
313 
314    return buf;
315 }
316 
317 
318 /* Helper function for s390_amode_is_sane */
319 static __inline__ Bool
is_virtual_gpr(HReg reg)320 is_virtual_gpr(HReg reg)
321 {
322    return hregIsVirtual(reg) && hregClass(reg) == HRcInt64;
323 }
324 
325 
326 /* Sanity check for an amode */
327 Bool
s390_amode_is_sane(const s390_amode * am)328 s390_amode_is_sane(const s390_amode *am)
329 {
330    switch (am->tag) {
331    case S390_AMODE_B12:
332       return is_virtual_gpr(am->b) && fits_unsigned_12bit(am->d);
333 
334    case S390_AMODE_B20:
335       return is_virtual_gpr(am->b) && fits_signed_20bit(am->d);
336 
337    case S390_AMODE_BX12:
338       return is_virtual_gpr(am->b) && is_virtual_gpr(am->x) &&
339              fits_unsigned_12bit(am->d);
340 
341    case S390_AMODE_BX20:
342       return is_virtual_gpr(am->b) && is_virtual_gpr(am->x) &&
343              fits_signed_20bit(am->d);
344 
345    default:
346       vpanic("s390_amode_is_sane");
347    }
348 }
349 
350 
351 /* Record the register use of an amode */
352 static void
s390_amode_get_reg_usage(HRegUsage * u,const s390_amode * am)353 s390_amode_get_reg_usage(HRegUsage *u, const s390_amode *am)
354 {
355    switch (am->tag) {
356    case S390_AMODE_B12:
357    case S390_AMODE_B20:
358       addHRegUse(u, HRmRead, am->b);
359       return;
360 
361    case S390_AMODE_BX12:
362    case S390_AMODE_BX20:
363       addHRegUse(u, HRmRead, am->b);
364       addHRegUse(u, HRmRead, am->x);
365       return;
366 
367    default:
368       vpanic("s390_amode_get_reg_usage");
369    }
370 }
371 
372 
373 static void
s390_amode_map_regs(HRegRemap * m,s390_amode * am)374 s390_amode_map_regs(HRegRemap *m, s390_amode *am)
375 {
376    switch (am->tag) {
377    case S390_AMODE_B12:
378    case S390_AMODE_B20:
379       am->b = lookupHRegRemap(m, am->b);
380       return;
381 
382    case S390_AMODE_BX12:
383    case S390_AMODE_BX20:
384       am->b = lookupHRegRemap(m, am->b);
385       am->x = lookupHRegRemap(m, am->x);
386       return;
387 
388    default:
389       vpanic("s390_amode_map_regs");
390    }
391 }
392 
393 
394 void
ppS390AMode(s390_amode * am)395 ppS390AMode(s390_amode *am)
396 {
397    vex_printf("%s", s390_amode_as_string(am));
398 }
399 
400 void
ppS390Instr(s390_insn * insn,Bool mode64)401 ppS390Instr(s390_insn *insn, Bool mode64)
402 {
403    vex_printf("%s", s390_insn_as_string(insn));
404 }
405 
406 void
ppHRegS390(HReg reg)407 ppHRegS390(HReg reg)
408 {
409    vex_printf("%s", s390_hreg_as_string(reg));
410 }
411 
412 /*------------------------------------------------------------*/
413 /*--- Helpers for register allocation                      ---*/
414 /*------------------------------------------------------------*/
415 
416 /* Called once per translation. */
417 void
getAllocableRegs_S390(Int * nregs,HReg ** arr,Bool mode64)418 getAllocableRegs_S390(Int *nregs, HReg **arr, Bool mode64)
419 {
420    s390_hreg_get_allocable(nregs, arr);
421 }
422 
423 
424 /* Tell the register allocator how the given instruction uses the registers
425    it refers to. */
426 void
getRegUsage_S390Instr(HRegUsage * u,s390_insn * insn,Bool mode64)427 getRegUsage_S390Instr(HRegUsage *u, s390_insn *insn, Bool mode64)
428 {
429    s390_insn_get_reg_usage(u, insn);
430 }
431 
432 
433 /* Map the registers of the given instruction */
434 void
mapRegs_S390Instr(HRegRemap * m,s390_insn * insn,Bool mode64)435 mapRegs_S390Instr(HRegRemap *m, s390_insn *insn, Bool mode64)
436 {
437    s390_insn_map_regs(m, insn);
438 }
439 
440 
441 /* Figure out if the given insn represents a reg-reg move, and if so
442    assign the source and destination to *src and *dst.  If in doubt say No.
443    Used by the register allocator to do move coalescing. */
444 Bool
isMove_S390Instr(s390_insn * insn,HReg * src,HReg * dst)445 isMove_S390Instr(s390_insn *insn, HReg *src, HReg *dst)
446 {
447    return s390_insn_is_reg_reg_move(insn, src, dst);
448 }
449 
450 
451 /* Generate s390 spill/reload instructions under the direction of the
452    register allocator.  Note it's critical these don't write the
453    condition codes. This is like an Ist_Put */
454 void
genSpill_S390(HInstr ** i1,HInstr ** i2,HReg rreg,Int offsetB,Bool mode64)455 genSpill_S390(HInstr **i1, HInstr **i2, HReg rreg, Int offsetB, Bool mode64)
456 {
457    s390_amode *am;
458 
459    vassert(offsetB >= 0);
460    vassert(offsetB <= (1 << 12));  /* because we use b12 amode */
461    vassert(!hregIsVirtual(rreg));
462 
463    *i1 = *i2 = NULL;
464 
465    am = s390_amode_for_guest_state(offsetB);
466 
467    switch (hregClass(rreg)) {
468    case HRcInt64:
469    case HRcFlt64:
470       *i1 = s390_insn_store(8, am, rreg);
471       return;
472 
473    default:
474       ppHRegClass(hregClass(rreg));
475       vpanic("genSpill_S390: unimplemented regclass");
476    }
477 }
478 
479 
480 /* This is like an Iex_Get */
481 void
genReload_S390(HInstr ** i1,HInstr ** i2,HReg rreg,Int offsetB,Bool mode64)482 genReload_S390(HInstr **i1, HInstr **i2, HReg rreg, Int offsetB, Bool mode64)
483 {
484    s390_amode *am;
485 
486    vassert(offsetB >= 0);
487    vassert(offsetB <= (1 << 12));  /* because we use b12 amode */
488    vassert(!hregIsVirtual(rreg));
489 
490    *i1 = *i2 = NULL;
491 
492    am = s390_amode_for_guest_state(offsetB);
493 
494    switch (hregClass(rreg)) {
495    case HRcInt64:
496    case HRcFlt64:
497       *i1 = s390_insn_load(8, rreg, am);
498       return;
499 
500    default:
501       ppHRegClass(hregClass(rreg));
502       vpanic("genReload_S390: unimplemented regclass");
503    }
504 }
505 
506 /* Helper function for s390_insn_get_reg_usage */
507 static void
s390_opnd_RMI_get_reg_usage(HRegUsage * u,s390_opnd_RMI op)508 s390_opnd_RMI_get_reg_usage(HRegUsage *u, s390_opnd_RMI op)
509 {
510    switch (op.tag) {
511    case S390_OPND_REG:
512       addHRegUse(u, HRmRead, op.variant.reg);
513       break;
514 
515    case S390_OPND_AMODE:
516       s390_amode_get_reg_usage(u, op.variant.am);
517       break;
518 
519    case S390_OPND_IMMEDIATE:
520       break;
521 
522    default:
523       vpanic("s390_opnd_RMI_get_reg_usage");
524    }
525 }
526 
527 
528 /* Tell the register allocator how the given insn uses the registers */
529 static void
s390_insn_get_reg_usage(HRegUsage * u,const s390_insn * insn)530 s390_insn_get_reg_usage(HRegUsage *u, const s390_insn *insn)
531 {
532    initHRegUsage(u);
533 
534    switch (insn->tag) {
535    case S390_INSN_LOAD:
536       addHRegUse(u, HRmWrite, insn->variant.load.dst);
537       s390_amode_get_reg_usage(u, insn->variant.load.src);
538       break;
539 
540    case S390_INSN_LOAD_IMMEDIATE:
541       addHRegUse(u, HRmWrite, insn->variant.load_immediate.dst);
542       break;
543 
544    case S390_INSN_STORE:
545       addHRegUse(u, HRmRead, insn->variant.store.src);
546       s390_amode_get_reg_usage(u, insn->variant.store.dst);
547       break;
548 
549    case S390_INSN_MOVE:
550       addHRegUse(u, HRmRead,  insn->variant.move.src);
551       addHRegUse(u, HRmWrite, insn->variant.move.dst);
552       break;
553 
554    case S390_INSN_COND_MOVE:
555       s390_opnd_RMI_get_reg_usage(u, insn->variant.cond_move.src);
556       addHRegUse(u, HRmWrite, insn->variant.cond_move.dst);
557       break;
558 
559    case S390_INSN_ALU:
560       addHRegUse(u, HRmWrite, insn->variant.alu.dst);
561       addHRegUse(u, HRmRead,  insn->variant.alu.dst);  /* op1 */
562       s390_opnd_RMI_get_reg_usage(u, insn->variant.alu.op2);
563       break;
564 
565    case S390_INSN_MUL:
566       addHRegUse(u, HRmRead,  insn->variant.mul.dst_lo);  /* op1 */
567       addHRegUse(u, HRmWrite, insn->variant.mul.dst_lo);
568       addHRegUse(u, HRmWrite, insn->variant.mul.dst_hi);
569       s390_opnd_RMI_get_reg_usage(u, insn->variant.mul.op2);
570       break;
571 
572    case S390_INSN_DIV:
573       addHRegUse(u, HRmRead,  insn->variant.div.op1_lo);
574       addHRegUse(u, HRmRead,  insn->variant.div.op1_hi);
575       addHRegUse(u, HRmWrite, insn->variant.div.op1_lo);
576       addHRegUse(u, HRmWrite, insn->variant.div.op1_hi);
577       s390_opnd_RMI_get_reg_usage(u, insn->variant.div.op2);
578       break;
579 
580    case S390_INSN_DIVS:
581       addHRegUse(u, HRmRead,  insn->variant.divs.op1);
582       addHRegUse(u, HRmWrite, insn->variant.divs.op1); /* quotient */
583       addHRegUse(u, HRmWrite, insn->variant.divs.rem); /* remainder */
584       s390_opnd_RMI_get_reg_usage(u, insn->variant.divs.op2);
585       break;
586 
587    case S390_INSN_CLZ:
588       addHRegUse(u, HRmWrite, insn->variant.clz.num_bits);
589       addHRegUse(u, HRmWrite, insn->variant.clz.clobber);
590       s390_opnd_RMI_get_reg_usage(u, insn->variant.clz.src);
591       break;
592 
593    case S390_INSN_UNOP:
594       addHRegUse(u, HRmWrite, insn->variant.unop.dst);
595       s390_opnd_RMI_get_reg_usage(u, insn->variant.unop.src);
596       break;
597 
598    case S390_INSN_TEST:
599       s390_opnd_RMI_get_reg_usage(u, insn->variant.test.src);
600       break;
601 
602    case S390_INSN_CC2BOOL:
603       addHRegUse(u, HRmWrite, insn->variant.cc2bool.dst);
604       break;
605 
606    case S390_INSN_CAS:
607       addHRegUse(u, HRmRead,  insn->variant.cas.op1);
608       s390_amode_get_reg_usage(u, insn->variant.cas.op2);
609       addHRegUse(u, HRmRead,  insn->variant.cas.op3);
610       addHRegUse(u, HRmWrite,  insn->variant.cas.old_mem);
611       break;
612 
613    case S390_INSN_CDAS:
614       addHRegUse(u, HRmRead,  insn->variant.cdas.op1_high);
615       addHRegUse(u, HRmRead,  insn->variant.cdas.op1_low);
616       s390_amode_get_reg_usage(u, insn->variant.cas.op2);
617       addHRegUse(u, HRmRead,  insn->variant.cdas.op3_high);
618       addHRegUse(u, HRmRead,  insn->variant.cdas.op3_low);
619       addHRegUse(u, HRmWrite, insn->variant.cdas.old_mem_high);
620       addHRegUse(u, HRmWrite, insn->variant.cdas.old_mem_low);
621       addHRegUse(u, HRmWrite, insn->variant.cdas.scratch);
622       break;
623 
624    case S390_INSN_COMPARE:
625       addHRegUse(u, HRmRead, insn->variant.compare.src1);
626       s390_opnd_RMI_get_reg_usage(u, insn->variant.compare.src2);
627       break;
628 
629    case S390_INSN_HELPER_CALL: {
630       UInt i;
631 
632       /* Assume that all volatile registers are clobbered. ABI says,
633          volatile registers are: r0 - r5. Valgrind's register allocator
634          does not know about r0, so we can leave that out */
635       for (i = 1; i <= 5; ++i) {
636          addHRegUse(u, HRmWrite, mkHReg(i, HRcInt64, False));
637       }
638       if (insn->variant.helper_call.dst != INVALID_HREG)
639          addHRegUse(u, HRmWrite, insn->variant.helper_call.dst);
640 
641       /* Ditto for floating point registers. f0 - f7 are volatile */
642       for (i = 0; i <= 7; ++i) {
643          addHRegUse(u, HRmWrite, mkHReg(i, HRcFlt64, False));
644       }
645 
646       /* The registers that are used for passing arguments will be read.
647          Not all of them may, but in general we need to assume that. */
648       for (i = 0; i < insn->variant.helper_call.num_args; ++i) {
649          addHRegUse(u, HRmRead, mkHReg(s390_gprno_from_arg_index(i),
650                                        HRcInt64, False));
651       }
652 
653       /* s390_insn_helper_call_emit also reads / writes the link register
654          and stack pointer. But those registers are not visible to the
655          register allocator. So we don't need to do anything for them. */
656       break;
657    }
658 
659    case S390_INSN_BFP_TRIOP:
660       addHRegUse(u, HRmWrite, insn->variant.bfp_triop.dst);
661       addHRegUse(u, HRmRead,  insn->variant.bfp_triop.dst);  /* first */
662       addHRegUse(u, HRmRead,  insn->variant.bfp_triop.op2);  /* second */
663       addHRegUse(u, HRmRead,  insn->variant.bfp_triop.op3);  /* third */
664       break;
665 
666    case S390_INSN_BFP_BINOP:
667       addHRegUse(u, HRmWrite, insn->variant.bfp_binop.dst);
668       addHRegUse(u, HRmRead,  insn->variant.bfp_binop.dst);  /* left */
669       addHRegUse(u, HRmRead,  insn->variant.bfp_binop.op2);  /* right */
670       break;
671 
672    case S390_INSN_BFP_UNOP:
673       addHRegUse(u, HRmWrite, insn->variant.bfp_unop.dst);
674       addHRegUse(u, HRmRead,  insn->variant.bfp_unop.op);  /* operand */
675       break;
676 
677    case S390_INSN_BFP_COMPARE:
678       addHRegUse(u, HRmWrite, insn->variant.bfp_compare.dst);
679       addHRegUse(u, HRmRead,  insn->variant.bfp_compare.op1);  /* left */
680       addHRegUse(u, HRmRead,  insn->variant.bfp_compare.op2);  /* right */
681       break;
682 
683    case S390_INSN_BFP128_BINOP:
684       addHRegUse(u, HRmWrite, insn->variant.bfp128_binop.dst_hi);
685       addHRegUse(u, HRmWrite, insn->variant.bfp128_binop.dst_lo);
686       addHRegUse(u, HRmRead,  insn->variant.bfp128_binop.dst_hi);  /* left */
687       addHRegUse(u, HRmRead,  insn->variant.bfp128_binop.dst_lo);  /* left */
688       addHRegUse(u, HRmRead,  insn->variant.bfp128_binop.op2_hi);  /* right */
689       addHRegUse(u, HRmRead,  insn->variant.bfp128_binop.op2_lo);  /* right */
690       break;
691 
692    case S390_INSN_BFP128_COMPARE:
693       addHRegUse(u, HRmWrite, insn->variant.bfp128_compare.dst);
694       addHRegUse(u, HRmRead,  insn->variant.bfp128_compare.op1_hi);  /* left */
695       addHRegUse(u, HRmRead,  insn->variant.bfp128_compare.op1_lo);  /* left */
696       addHRegUse(u, HRmRead,  insn->variant.bfp128_compare.op2_hi);  /* right */
697       addHRegUse(u, HRmRead,  insn->variant.bfp128_compare.op2_lo);  /* right */
698       break;
699 
700    case S390_INSN_BFP128_UNOP:
701       addHRegUse(u, HRmWrite, insn->variant.bfp128_unop.dst_hi);
702       addHRegUse(u, HRmWrite, insn->variant.bfp128_unop.dst_lo);
703       addHRegUse(u, HRmRead,  insn->variant.bfp128_unop.op_hi);
704       addHRegUse(u, HRmRead,  insn->variant.bfp128_unop.op_lo);
705       break;
706 
707    case S390_INSN_BFP128_CONVERT_TO:
708       addHRegUse(u, HRmWrite, insn->variant.bfp128_unop.dst_hi);
709       addHRegUse(u, HRmWrite, insn->variant.bfp128_unop.dst_lo);
710       addHRegUse(u, HRmRead,  insn->variant.bfp128_unop.op_hi);
711       break;
712 
713    case S390_INSN_BFP128_CONVERT_FROM:
714       addHRegUse(u, HRmWrite, insn->variant.bfp128_unop.dst_hi);
715       addHRegUse(u, HRmRead,  insn->variant.bfp128_unop.op_hi);
716       addHRegUse(u, HRmRead,  insn->variant.bfp128_unop.op_lo);
717       break;
718 
719    case S390_INSN_MFENCE:
720    case S390_INSN_GZERO:
721    case S390_INSN_GADD:
722       break;
723 
724    case S390_INSN_EVCHECK:
725       s390_amode_get_reg_usage(u, insn->variant.evcheck.counter);
726       s390_amode_get_reg_usage(u, insn->variant.evcheck.fail_addr);
727       break;
728 
729    case S390_INSN_PROFINC:
730       /* Does not use any register visible to the register allocator */
731       break;
732 
733    case S390_INSN_XDIRECT:
734       s390_amode_get_reg_usage(u, insn->variant.xdirect.guest_IA);
735       break;
736 
737    case S390_INSN_XINDIR:
738       addHRegUse(u, HRmRead, insn->variant.xindir.dst);
739       s390_amode_get_reg_usage(u, insn->variant.xindir.guest_IA);
740       break;
741 
742    case S390_INSN_XASSISTED:
743       addHRegUse(u, HRmRead, insn->variant.xassisted.dst);
744       s390_amode_get_reg_usage(u, insn->variant.xassisted.guest_IA);
745       break;
746 
747    default:
748       vpanic("s390_insn_get_reg_usage");
749    }
750 }
751 
752 
753 /* Helper function for s390_insn_map_regs */
754 static void
s390_opnd_RMI_map_regs(HRegRemap * m,s390_opnd_RMI * op)755 s390_opnd_RMI_map_regs(HRegRemap *m, s390_opnd_RMI *op)
756 {
757    switch (op->tag) {
758    case S390_OPND_REG:
759       op->variant.reg = lookupHRegRemap(m, op->variant.reg);
760       break;
761 
762    case S390_OPND_IMMEDIATE:
763       break;
764 
765    case S390_OPND_AMODE:
766       s390_amode_map_regs(m, op->variant.am);
767       break;
768 
769    default:
770       vpanic("s390_opnd_RMI_map_regs");
771    }
772 }
773 
774 
775 static void
s390_insn_map_regs(HRegRemap * m,s390_insn * insn)776 s390_insn_map_regs(HRegRemap *m, s390_insn *insn)
777 {
778    switch (insn->tag) {
779    case S390_INSN_LOAD:
780       insn->variant.load.dst = lookupHRegRemap(m, insn->variant.load.dst);
781       s390_amode_map_regs(m, insn->variant.load.src);
782       break;
783 
784    case S390_INSN_STORE:
785       s390_amode_map_regs(m, insn->variant.store.dst);
786       insn->variant.store.src = lookupHRegRemap(m, insn->variant.store.src);
787       break;
788 
789    case S390_INSN_MOVE:
790       insn->variant.move.dst = lookupHRegRemap(m, insn->variant.move.dst);
791       insn->variant.move.src = lookupHRegRemap(m, insn->variant.move.src);
792       break;
793 
794    case S390_INSN_COND_MOVE:
795       insn->variant.cond_move.dst = lookupHRegRemap(m, insn->variant.cond_move.dst);
796       s390_opnd_RMI_map_regs(m, &insn->variant.cond_move.src);
797       break;
798 
799    case S390_INSN_LOAD_IMMEDIATE:
800       insn->variant.load_immediate.dst =
801          lookupHRegRemap(m, insn->variant.load_immediate.dst);
802       break;
803 
804    case S390_INSN_ALU:
805       insn->variant.alu.dst = lookupHRegRemap(m, insn->variant.alu.dst);
806       s390_opnd_RMI_map_regs(m, &insn->variant.alu.op2);
807       break;
808 
809    case S390_INSN_MUL:
810       insn->variant.mul.dst_hi = lookupHRegRemap(m, insn->variant.mul.dst_hi);
811       insn->variant.mul.dst_lo = lookupHRegRemap(m, insn->variant.mul.dst_lo);
812       s390_opnd_RMI_map_regs(m, &insn->variant.mul.op2);
813       break;
814 
815    case S390_INSN_DIV:
816       insn->variant.div.op1_hi = lookupHRegRemap(m, insn->variant.div.op1_hi);
817       insn->variant.div.op1_lo = lookupHRegRemap(m, insn->variant.div.op1_lo);
818       s390_opnd_RMI_map_regs(m, &insn->variant.div.op2);
819       break;
820 
821    case S390_INSN_DIVS:
822       insn->variant.divs.op1 = lookupHRegRemap(m, insn->variant.divs.op1);
823       insn->variant.divs.rem = lookupHRegRemap(m, insn->variant.divs.rem);
824       s390_opnd_RMI_map_regs(m, &insn->variant.divs.op2);
825       break;
826 
827    case S390_INSN_CLZ:
828       insn->variant.clz.num_bits = lookupHRegRemap(m, insn->variant.clz.num_bits);
829       insn->variant.clz.clobber  = lookupHRegRemap(m, insn->variant.clz.clobber);
830       s390_opnd_RMI_map_regs(m, &insn->variant.clz.src);
831       break;
832 
833    case S390_INSN_UNOP:
834       insn->variant.unop.dst = lookupHRegRemap(m, insn->variant.unop.dst);
835       s390_opnd_RMI_map_regs(m, &insn->variant.unop.src);
836       break;
837 
838    case S390_INSN_TEST:
839       s390_opnd_RMI_map_regs(m, &insn->variant.test.src);
840       break;
841 
842    case S390_INSN_CC2BOOL:
843       insn->variant.cc2bool.dst = lookupHRegRemap(m, insn->variant.cc2bool.dst);
844       break;
845 
846    case S390_INSN_CAS:
847       insn->variant.cas.op1 = lookupHRegRemap(m, insn->variant.cas.op1);
848       s390_amode_map_regs(m, insn->variant.cas.op2);
849       insn->variant.cas.op3 = lookupHRegRemap(m, insn->variant.cas.op3);
850       insn->variant.cas.old_mem = lookupHRegRemap(m, insn->variant.cas.old_mem);
851       break;
852 
853    case S390_INSN_CDAS:
854       insn->variant.cdas.op1_high = lookupHRegRemap(m, insn->variant.cdas.op1_high);
855       insn->variant.cdas.op1_low  = lookupHRegRemap(m, insn->variant.cdas.op1_low);
856       s390_amode_map_regs(m, insn->variant.cdas.op2);
857       insn->variant.cdas.op3_high = lookupHRegRemap(m, insn->variant.cdas.op3_high);
858       insn->variant.cdas.op3_low  = lookupHRegRemap(m, insn->variant.cdas.op3_low);
859       insn->variant.cdas.old_mem_high = lookupHRegRemap(m, insn->variant.cdas.old_mem_high);
860       insn->variant.cdas.old_mem_low  = lookupHRegRemap(m, insn->variant.cdas.old_mem_low);
861       insn->variant.cdas.scratch  = lookupHRegRemap(m, insn->variant.cdas.scratch);
862       break;
863 
864    case S390_INSN_COMPARE:
865       insn->variant.compare.src1 = lookupHRegRemap(m, insn->variant.compare.src1);
866       s390_opnd_RMI_map_regs(m, &insn->variant.compare.src2);
867       break;
868 
869    case S390_INSN_HELPER_CALL:
870       /* s390_insn_helper_call_emit also reads / writes the link register
871          and stack pointer. But those registers are not visible to the
872          register allocator. So we don't need to do anything for them.
873          As for the arguments of the helper call -- they will be loaded into
874          non-virtual registers. Again, we don't need to do anything for those
875          here. */
876       if (insn->variant.helper_call.dst != INVALID_HREG)
877          insn->variant.helper_call.dst = lookupHRegRemap(m, insn->variant.helper_call.dst);
878       break;
879 
880    case S390_INSN_BFP_TRIOP:
881       insn->variant.bfp_triop.dst = lookupHRegRemap(m, insn->variant.bfp_triop.dst);
882       insn->variant.bfp_triop.op2 = lookupHRegRemap(m, insn->variant.bfp_triop.op2);
883       insn->variant.bfp_triop.op3 = lookupHRegRemap(m, insn->variant.bfp_triop.op3);
884       break;
885 
886    case S390_INSN_BFP_BINOP:
887       insn->variant.bfp_binop.dst = lookupHRegRemap(m, insn->variant.bfp_binop.dst);
888       insn->variant.bfp_binop.op2 = lookupHRegRemap(m, insn->variant.bfp_binop.op2);
889       break;
890 
891    case S390_INSN_BFP_UNOP:
892       insn->variant.bfp_unop.dst = lookupHRegRemap(m, insn->variant.bfp_unop.dst);
893       insn->variant.bfp_unop.op  = lookupHRegRemap(m, insn->variant.bfp_unop.op);
894       break;
895 
896    case S390_INSN_BFP_COMPARE:
897       insn->variant.bfp_compare.dst = lookupHRegRemap(m, insn->variant.bfp_compare.dst);
898       insn->variant.bfp_compare.op1 = lookupHRegRemap(m, insn->variant.bfp_compare.op1);
899       insn->variant.bfp_compare.op2 = lookupHRegRemap(m, insn->variant.bfp_compare.op2);
900       break;
901 
902    case S390_INSN_BFP128_BINOP:
903       insn->variant.bfp128_binop.dst_hi =
904          lookupHRegRemap(m, insn->variant.bfp128_binop.dst_hi);
905       insn->variant.bfp128_binop.dst_lo =
906          lookupHRegRemap(m, insn->variant.bfp128_binop.dst_lo);
907       insn->variant.bfp128_binop.op2_hi =
908          lookupHRegRemap(m, insn->variant.bfp128_binop.op2_hi);
909       insn->variant.bfp128_binop.op2_lo =
910          lookupHRegRemap(m, insn->variant.bfp128_binop.op2_lo);
911       break;
912 
913    case S390_INSN_BFP128_COMPARE:
914       insn->variant.bfp128_compare.dst =
915          lookupHRegRemap(m, insn->variant.bfp128_compare.dst);
916       insn->variant.bfp128_compare.op1_hi =
917          lookupHRegRemap(m, insn->variant.bfp128_compare.op1_hi);
918       insn->variant.bfp128_compare.op1_lo =
919          lookupHRegRemap(m, insn->variant.bfp128_compare.op1_lo);
920       insn->variant.bfp128_compare.op2_hi =
921          lookupHRegRemap(m, insn->variant.bfp128_compare.op2_hi);
922       insn->variant.bfp128_compare.op2_lo =
923          lookupHRegRemap(m, insn->variant.bfp128_compare.op2_lo);
924       break;
925 
926    case S390_INSN_BFP128_UNOP:
927       insn->variant.bfp128_unop.dst_hi =
928          lookupHRegRemap(m, insn->variant.bfp128_unop.dst_hi);
929       insn->variant.bfp128_unop.dst_lo =
930          lookupHRegRemap(m, insn->variant.bfp128_unop.dst_lo);
931       insn->variant.bfp128_unop.op_hi =
932          lookupHRegRemap(m, insn->variant.bfp128_unop.op_hi);
933       insn->variant.bfp128_unop.op_lo =
934          lookupHRegRemap(m, insn->variant.bfp128_unop.op_lo);
935       break;
936 
937    case S390_INSN_BFP128_CONVERT_TO:
938       insn->variant.bfp128_unop.dst_hi =
939          lookupHRegRemap(m, insn->variant.bfp128_unop.dst_hi);
940       insn->variant.bfp128_unop.dst_lo =
941          lookupHRegRemap(m, insn->variant.bfp128_unop.dst_lo);
942       insn->variant.bfp128_unop.op_hi =
943          lookupHRegRemap(m, insn->variant.bfp128_unop.op_hi);
944       break;
945 
946    case S390_INSN_BFP128_CONVERT_FROM:
947       insn->variant.bfp128_unop.dst_hi =
948          lookupHRegRemap(m, insn->variant.bfp128_unop.dst_hi);
949       insn->variant.bfp128_unop.op_hi =
950          lookupHRegRemap(m, insn->variant.bfp128_unop.op_hi);
951       insn->variant.bfp128_unop.op_lo =
952          lookupHRegRemap(m, insn->variant.bfp128_unop.op_lo);
953       break;
954 
955    case S390_INSN_MFENCE:
956    case S390_INSN_GZERO:
957    case S390_INSN_GADD:
958       break;
959 
960    case S390_INSN_EVCHECK:
961       s390_amode_map_regs(m, insn->variant.evcheck.counter);
962       s390_amode_map_regs(m, insn->variant.evcheck.fail_addr);
963       break;
964 
965    case S390_INSN_PROFINC:
966       /* Does not use any register visible to the register allocator */
967       break;
968 
969    case S390_INSN_XDIRECT:
970       s390_amode_map_regs(m, insn->variant.xdirect.guest_IA);
971       break;
972 
973    case S390_INSN_XINDIR:
974       s390_amode_map_regs(m, insn->variant.xindir.guest_IA);
975       insn->variant.xindir.dst =
976          lookupHRegRemap(m, insn->variant.xindir.dst);
977       break;
978 
979    case S390_INSN_XASSISTED:
980       s390_amode_map_regs(m, insn->variant.xassisted.guest_IA);
981       insn->variant.xassisted.dst =
982          lookupHRegRemap(m, insn->variant.xassisted.dst);
983       break;
984 
985    default:
986       vpanic("s390_insn_map_regs");
987    }
988 }
989 
990 
991 /* Return True, if INSN is a move between two registers of the same class.
992    In that case assign the source and destination registers to SRC and DST,
993    respectively. */
994 static Bool
s390_insn_is_reg_reg_move(const s390_insn * insn,HReg * src,HReg * dst)995 s390_insn_is_reg_reg_move(const s390_insn *insn, HReg *src, HReg *dst)
996 {
997    if (insn->tag == S390_INSN_MOVE &&
998        hregClass(insn->variant.move.src) == hregClass(insn->variant.move.dst)) {
999       *src = insn->variant.move.src;
1000       *dst = insn->variant.move.dst;
1001       return True;
1002    }
1003 
1004    return False;
1005 }
1006 
1007 
1008 /*------------------------------------------------------------*/
1009 /*--- Functions to emit a sequence of bytes                ---*/
1010 /*------------------------------------------------------------*/
1011 
1012 static __inline__ UChar *
emit_2bytes(UChar * p,ULong val)1013 emit_2bytes(UChar *p, ULong val)
1014 {
1015    return (UChar *)__builtin_memcpy(p, ((UChar *)&val) + 6, 2) + 2;
1016 }
1017 
1018 
1019 static __inline__ UChar *
emit_4bytes(UChar * p,ULong val)1020 emit_4bytes(UChar *p, ULong val)
1021 {
1022    return (UChar *)__builtin_memcpy(p, ((UChar *)&val) + 4, 4) + 4;
1023 }
1024 
1025 
1026 static __inline__ UChar *
emit_6bytes(UChar * p,ULong val)1027 emit_6bytes(UChar *p, ULong val)
1028 {
1029    return (UChar *)__builtin_memcpy(p, ((UChar *)&val) + 2, 6) + 6;
1030 }
1031 
1032 
1033 /*------------------------------------------------------------*/
1034 /*--- Functions to emit various instruction formats        ---*/
1035 /*------------------------------------------------------------*/
1036 
1037 static UChar *
emit_RI(UChar * p,UInt op,UChar r1,UShort i2)1038 emit_RI(UChar *p, UInt op, UChar r1, UShort i2)
1039 {
1040    ULong the_insn = op;
1041 
1042    the_insn |= ((ULong)r1) << 20;
1043    the_insn |= ((ULong)i2) << 0;
1044 
1045    return emit_4bytes(p, the_insn);
1046 }
1047 
1048 
1049 static UChar *
emit_RIL(UChar * p,ULong op,UChar r1,UInt i2)1050 emit_RIL(UChar *p, ULong op, UChar r1, UInt i2)
1051 {
1052    ULong the_insn = op;
1053 
1054    the_insn |= ((ULong)r1) << 36;
1055    the_insn |= ((ULong)i2) << 0;
1056 
1057    return emit_6bytes(p, the_insn);
1058 }
1059 
1060 
1061 static UChar *
emit_RR(UChar * p,UInt op,UChar r1,UChar r2)1062 emit_RR(UChar *p, UInt op, UChar r1, UChar r2)
1063 {
1064    ULong the_insn = op;
1065 
1066    the_insn |= ((ULong)r1) << 4;
1067    the_insn |= ((ULong)r2) << 0;
1068 
1069    return emit_2bytes(p, the_insn);
1070 }
1071 
1072 
1073 static UChar *
emit_RRE(UChar * p,UInt op,UChar r1,UChar r2)1074 emit_RRE(UChar *p, UInt op, UChar r1, UChar r2)
1075 {
1076    ULong the_insn = op;
1077 
1078    the_insn |= ((ULong)r1) << 4;
1079    the_insn |= ((ULong)r2) << 0;
1080 
1081    return emit_4bytes(p, the_insn);
1082 }
1083 
1084 
1085 static UChar *
emit_RRF(UChar * p,UInt op,UChar r1,UChar r3,UChar r2)1086 emit_RRF(UChar *p, UInt op, UChar r1, UChar r3, UChar r2)
1087 {
1088    ULong the_insn = op;
1089 
1090    the_insn |= ((ULong)r1) << 12;
1091    the_insn |= ((ULong)r3) << 4;
1092    the_insn |= ((ULong)r2) << 0;
1093 
1094    return emit_4bytes(p, the_insn);
1095 }
1096 
1097 
1098 static UChar *
emit_RRF3(UChar * p,UInt op,UChar r3,UChar r1,UChar r2)1099 emit_RRF3(UChar *p, UInt op, UChar r3, UChar r1, UChar r2)
1100 {
1101    ULong the_insn = op;
1102 
1103    the_insn |= ((ULong)r3) << 12;
1104    the_insn |= ((ULong)r1) << 4;
1105    the_insn |= ((ULong)r2) << 0;
1106 
1107    return emit_4bytes(p, the_insn);
1108 }
1109 
1110 
1111 static UChar *
emit_RS(UChar * p,UInt op,UChar r1,UChar r3,UChar b2,UShort d2)1112 emit_RS(UChar *p, UInt op, UChar r1, UChar r3, UChar b2, UShort d2)
1113 {
1114    ULong the_insn = op;
1115 
1116    the_insn |= ((ULong)r1) << 20;
1117    the_insn |= ((ULong)r3) << 16;
1118    the_insn |= ((ULong)b2) << 12;
1119    the_insn |= ((ULong)d2) << 0;
1120 
1121    return emit_4bytes(p, the_insn);
1122 }
1123 
1124 
1125 static UChar *
emit_RSY(UChar * p,ULong op,UChar r1,UChar r3,UChar b2,UShort dl2,UChar dh2)1126 emit_RSY(UChar *p, ULong op, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
1127 {
1128    ULong the_insn = op;
1129 
1130    the_insn |= ((ULong)r1) << 36;
1131    the_insn |= ((ULong)r3) << 32;
1132    the_insn |= ((ULong)b2) << 28;
1133    the_insn |= ((ULong)dl2) << 16;
1134    the_insn |= ((ULong)dh2) << 8;
1135 
1136    return emit_6bytes(p, the_insn);
1137 }
1138 
1139 
1140 static UChar *
emit_RX(UChar * p,UInt op,UChar r1,UChar x2,UChar b2,UShort d2)1141 emit_RX(UChar *p, UInt op, UChar r1, UChar x2, UChar b2, UShort d2)
1142 {
1143    ULong the_insn = op;
1144 
1145    the_insn |= ((ULong)r1) << 20;
1146    the_insn |= ((ULong)x2) << 16;
1147    the_insn |= ((ULong)b2) << 12;
1148    the_insn |= ((ULong)d2) << 0;
1149 
1150    return emit_4bytes(p, the_insn);
1151 }
1152 
1153 
1154 static UChar *
emit_RXY(UChar * p,ULong op,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)1155 emit_RXY(UChar *p, ULong op, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1156 {
1157    ULong the_insn = op;
1158 
1159    the_insn |= ((ULong)r1) << 36;
1160    the_insn |= ((ULong)x2) << 32;
1161    the_insn |= ((ULong)b2) << 28;
1162    the_insn |= ((ULong)dl2) << 16;
1163    the_insn |= ((ULong)dh2) << 8;
1164 
1165    return emit_6bytes(p, the_insn);
1166 }
1167 
1168 
1169 static UChar *
emit_S(UChar * p,UInt op,UChar b2,UShort d2)1170 emit_S(UChar *p, UInt op, UChar b2, UShort d2)
1171 {
1172    ULong the_insn = op;
1173 
1174    the_insn |= ((ULong)b2) << 12;
1175    the_insn |= ((ULong)d2) << 0;
1176 
1177    return emit_4bytes(p, the_insn);
1178 }
1179 
1180 
1181 static UChar *
emit_SIY(UChar * p,ULong op,UChar i2,UChar b1,UShort dl1,UChar dh1)1182 emit_SIY(UChar *p, ULong op, UChar i2, UChar b1, UShort dl1, UChar dh1)
1183 {
1184    ULong the_insn = op;
1185 
1186    the_insn |= ((ULong)i2) << 32;
1187    the_insn |= ((ULong)b1) << 28;
1188    the_insn |= ((ULong)dl1) << 16;
1189    the_insn |= ((ULong)dh1) << 8;
1190 
1191    return emit_6bytes(p, the_insn);
1192 }
1193 
1194 
1195 static UChar *
emit_SSa(UChar * p,ULong op,UChar l,UChar b1,UShort d1,UChar b2,UShort d2)1196 emit_SSa(UChar *p, ULong op, UChar l, UChar b1, UShort d1, UChar b2, UShort d2)
1197 {
1198    ULong the_insn = op;
1199 
1200    the_insn |= ((ULong)l)  << 32;
1201    the_insn |= ((ULong)b1) << 28;
1202    the_insn |= ((ULong)d1) << 16;
1203    the_insn |= ((ULong)b2) << 12;
1204    the_insn |= ((ULong)d2) << 0;
1205 
1206    return emit_6bytes(p, the_insn);
1207 }
1208 
1209 
1210 /*------------------------------------------------------------*/
1211 /*--- Functions to emit particular instructions            ---*/
1212 /*------------------------------------------------------------*/
1213 
1214 static UChar *
s390_emit_AR(UChar * p,UChar r1,UChar r2)1215 s390_emit_AR(UChar *p, UChar r1, UChar r2)
1216 {
1217    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1218       s390_disasm(ENC3(MNM, GPR, GPR), "ar", r1, r2);
1219 
1220    return emit_RR(p, 0x1a00, r1, r2);
1221 }
1222 
1223 
1224 static UChar *
s390_emit_AGR(UChar * p,UChar r1,UChar r2)1225 s390_emit_AGR(UChar *p, UChar r1, UChar r2)
1226 {
1227    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1228       s390_disasm(ENC3(MNM, GPR, GPR), "agr", r1, r2);
1229 
1230    return emit_RRE(p, 0xb9080000, r1, r2);
1231 }
1232 
1233 
1234 static UChar *
s390_emit_A(UChar * p,UChar r1,UChar x2,UChar b2,UShort d2)1235 s390_emit_A(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
1236 {
1237    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1238       s390_disasm(ENC3(MNM, GPR, UDXB), "a", r1, d2, x2, b2);
1239 
1240    return emit_RX(p, 0x5a000000, r1, x2, b2, d2);
1241 }
1242 
1243 
1244 static UChar *
s390_emit_AY(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)1245 s390_emit_AY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1246 {
1247    vassert(s390_host_has_ldisp);
1248 
1249    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1250       s390_disasm(ENC3(MNM, GPR, SDXB), "ay", r1, dh2, dl2, x2, b2);
1251 
1252    return emit_RXY(p, 0xe3000000005aULL, r1, x2, b2, dl2, dh2);
1253 }
1254 
1255 
1256 static UChar *
s390_emit_AG(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)1257 s390_emit_AG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1258 {
1259    vassert(s390_host_has_ldisp || dh2 == 0);
1260 
1261    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1262       s390_disasm(ENC3(MNM, GPR, SDXB), "ag", r1, dh2, dl2, x2, b2);
1263 
1264    return emit_RXY(p, 0xe30000000008ULL, r1, x2, b2, dl2, dh2);
1265 }
1266 
1267 
1268 static UChar *
s390_emit_AFI(UChar * p,UChar r1,UInt i2)1269 s390_emit_AFI(UChar *p, UChar r1, UInt i2)
1270 {
1271    vassert(s390_host_has_eimm);
1272 
1273    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1274       s390_disasm(ENC3(MNM, GPR, INT), "afi", r1, i2);
1275 
1276    return emit_RIL(p, 0xc20900000000ULL, r1, i2);
1277 }
1278 
1279 
1280 static UChar *
s390_emit_AGFI(UChar * p,UChar r1,UInt i2)1281 s390_emit_AGFI(UChar *p, UChar r1, UInt i2)
1282 {
1283    vassert(s390_host_has_eimm);
1284 
1285    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1286       s390_disasm(ENC3(MNM, GPR, INT), "agfi", r1, i2);
1287 
1288    return emit_RIL(p, 0xc20800000000ULL, r1, i2);
1289 }
1290 
1291 
1292 static UChar *
s390_emit_AH(UChar * p,UChar r1,UChar x2,UChar b2,UShort d2)1293 s390_emit_AH(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
1294 {
1295    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1296       s390_disasm(ENC3(MNM, GPR, UDXB), "ah", r1, d2, x2, b2);
1297 
1298    return emit_RX(p, 0x4a000000, r1, x2, b2, d2);
1299 }
1300 
1301 
1302 static UChar *
s390_emit_AHY(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)1303 s390_emit_AHY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1304 {
1305    vassert(s390_host_has_ldisp);
1306 
1307    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1308       s390_disasm(ENC3(MNM, GPR, SDXB), "ahy", r1, dh2, dl2, x2, b2);
1309 
1310    return emit_RXY(p, 0xe3000000007aULL, r1, x2, b2, dl2, dh2);
1311 }
1312 
1313 
1314 static UChar *
s390_emit_AHI(UChar * p,UChar r1,UShort i2)1315 s390_emit_AHI(UChar *p, UChar r1, UShort i2)
1316 {
1317    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1318       s390_disasm(ENC3(MNM, GPR, INT), "ahi", r1, (Int)(Short)i2);
1319 
1320    return emit_RI(p, 0xa70a0000, r1, i2);
1321 }
1322 
1323 
1324 static UChar *
s390_emit_AGHI(UChar * p,UChar r1,UShort i2)1325 s390_emit_AGHI(UChar *p, UChar r1, UShort i2)
1326 {
1327    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1328       s390_disasm(ENC3(MNM, GPR, INT), "aghi", r1, (Int)(Short)i2);
1329 
1330    return emit_RI(p, 0xa70b0000, r1, i2);
1331 }
1332 
1333 
1334 static UChar *
s390_emit_AGSI(UChar * p,UChar i2,UChar b1,UShort dl1,UChar dh1)1335 s390_emit_AGSI(UChar *p, UChar i2, UChar b1, UShort dl1, UChar dh1)
1336 {
1337    vassert(s390_host_has_gie);
1338 
1339    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1340       s390_disasm(ENC3(MNM, SDXB, INT), "agsi", dh1, dl1, 0, b1, (Int)(Char)i2);
1341 
1342    return emit_SIY(p, 0xeb000000007aULL, i2, b1, dl1, dh1);
1343 }
1344 
1345 
1346 static UChar *
s390_emit_ASI(UChar * p,UChar i2,UChar b1,UShort dl1,UChar dh1)1347 s390_emit_ASI(UChar *p, UChar i2, UChar b1, UShort dl1, UChar dh1)
1348 {
1349    vassert(s390_host_has_gie);
1350 
1351    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1352       s390_disasm(ENC3(MNM, SDXB, INT), "asi", dh1, dl1, 0, b1, (Int)(Char)i2);
1353 
1354    return emit_SIY(p, 0xeb000000006aULL, i2, b1, dl1, dh1);
1355 }
1356 
1357 
1358 static UChar *
s390_emit_NR(UChar * p,UChar r1,UChar r2)1359 s390_emit_NR(UChar *p, UChar r1, UChar r2)
1360 {
1361    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1362       s390_disasm(ENC3(MNM, GPR, GPR), "nr", r1, r2);
1363 
1364    return emit_RR(p, 0x1400, r1, r2);
1365 }
1366 
1367 
1368 static UChar *
s390_emit_NGR(UChar * p,UChar r1,UChar r2)1369 s390_emit_NGR(UChar *p, UChar r1, UChar r2)
1370 {
1371    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1372       s390_disasm(ENC3(MNM, GPR, GPR), "ngr", r1, r2);
1373 
1374    return emit_RRE(p, 0xb9800000, r1, r2);
1375 }
1376 
1377 
1378 static UChar *
s390_emit_N(UChar * p,UChar r1,UChar x2,UChar b2,UShort d2)1379 s390_emit_N(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
1380 {
1381    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1382       s390_disasm(ENC3(MNM, GPR, UDXB), "n", r1, d2, x2, b2);
1383 
1384    return emit_RX(p, 0x54000000, r1, x2, b2, d2);
1385 }
1386 
1387 
1388 static UChar *
s390_emit_NY(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)1389 s390_emit_NY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1390 {
1391    vassert(s390_host_has_ldisp);
1392 
1393    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1394       s390_disasm(ENC3(MNM, GPR, SDXB), "ny", r1, dh2, dl2, x2, b2);
1395 
1396    return emit_RXY(p, 0xe30000000054ULL, r1, x2, b2, dl2, dh2);
1397 }
1398 
1399 
1400 static UChar *
s390_emit_NG(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)1401 s390_emit_NG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1402 {
1403    vassert(s390_host_has_ldisp || dh2 == 0);
1404 
1405    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1406       s390_disasm(ENC3(MNM, GPR, SDXB), "ng", r1, dh2, dl2, x2, b2);
1407 
1408    return emit_RXY(p, 0xe30000000080ULL, r1, x2, b2, dl2, dh2);
1409 }
1410 
1411 
1412 static UChar *
s390_emit_NIHF(UChar * p,UChar r1,UInt i2)1413 s390_emit_NIHF(UChar *p, UChar r1, UInt i2)
1414 {
1415    vassert(s390_host_has_eimm);
1416 
1417    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1418       s390_disasm(ENC3(MNM, GPR, UINT), "nihf", r1, i2);
1419 
1420    return emit_RIL(p, 0xc00a00000000ULL, r1, i2);
1421 }
1422 
1423 
1424 static UChar *
s390_emit_NILF(UChar * p,UChar r1,UInt i2)1425 s390_emit_NILF(UChar *p, UChar r1, UInt i2)
1426 {
1427    vassert(s390_host_has_eimm);
1428 
1429    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1430       s390_disasm(ENC3(MNM, GPR, UINT), "nilf", r1, i2);
1431 
1432    return emit_RIL(p, 0xc00b00000000ULL, r1, i2);
1433 }
1434 
1435 
1436 static UChar *
s390_emit_NILL(UChar * p,UChar r1,UShort i2)1437 s390_emit_NILL(UChar *p, UChar r1, UShort i2)
1438 {
1439    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1440       s390_disasm(ENC3(MNM, GPR, UINT), "nill", r1, i2);
1441 
1442    return emit_RI(p, 0xa5070000, r1, i2);
1443 }
1444 
1445 
1446 static UChar *
s390_emit_BASR(UChar * p,UChar r1,UChar r2)1447 s390_emit_BASR(UChar *p, UChar r1, UChar r2)
1448 {
1449    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1450       s390_disasm(ENC3(MNM, GPR, GPR), "basr", r1, r2);
1451 
1452    return emit_RR(p, 0x0d00, r1, r2);
1453 }
1454 
1455 
1456 static UChar *
s390_emit_BCR(UChar * p,UChar r1,UChar r2)1457 s390_emit_BCR(UChar *p, UChar r1, UChar r2)
1458 {
1459    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1460       s390_disasm(ENC2(XMNM, GPR), S390_XMNM_BCR, r1, r2);
1461 
1462    return emit_RR(p, 0x0700, r1, r2);
1463 }
1464 
1465 
1466 static UChar *
s390_emit_BRC(UChar * p,UChar r1,UShort i2)1467 s390_emit_BRC(UChar *p, UChar r1, UShort i2)
1468 {
1469    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1470       s390_disasm(ENC2(XMNM, PCREL), S390_XMNM_BRC, r1, (Int)(Short)i2);
1471 
1472    return emit_RI(p, 0xa7040000, r1, i2);
1473 }
1474 
1475 
1476 static UChar *
s390_emit_BRCL(UChar * p,UChar r1,ULong i2)1477 s390_emit_BRCL(UChar *p, UChar r1, ULong i2)
1478 {
1479    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1480       s390_disasm(ENC2(XMNM, PCREL), S390_XMNM_BRCL, r1, i2);
1481 
1482    return emit_RIL(p, 0xc00400000000ULL, r1, i2);
1483 }
1484 
1485 
1486 static UChar *
s390_emit_CR(UChar * p,UChar r1,UChar r2)1487 s390_emit_CR(UChar *p, UChar r1, UChar r2)
1488 {
1489    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1490       s390_disasm(ENC3(MNM, GPR, GPR), "cr", r1, r2);
1491 
1492    return emit_RR(p, 0x1900, r1, r2);
1493 }
1494 
1495 
1496 static UChar *
s390_emit_CGR(UChar * p,UChar r1,UChar r2)1497 s390_emit_CGR(UChar *p, UChar r1, UChar r2)
1498 {
1499    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1500       s390_disasm(ENC3(MNM, GPR, GPR), "cgr", r1, r2);
1501 
1502    return emit_RRE(p, 0xb9200000, r1, r2);
1503 }
1504 
1505 
1506 static UChar *
s390_emit_C(UChar * p,UChar r1,UChar x2,UChar b2,UShort d2)1507 s390_emit_C(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
1508 {
1509    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1510       s390_disasm(ENC3(MNM, GPR, UDXB), "c", r1, d2, x2, b2);
1511 
1512    return emit_RX(p, 0x59000000, r1, x2, b2, d2);
1513 }
1514 
1515 
1516 static UChar *
s390_emit_CY(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)1517 s390_emit_CY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1518 {
1519    vassert(s390_host_has_ldisp);
1520 
1521    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1522       s390_disasm(ENC3(MNM, GPR, SDXB), "cy", r1, dh2, dl2, x2, b2);
1523 
1524    return emit_RXY(p, 0xe30000000059ULL, r1, x2, b2, dl2, dh2);
1525 }
1526 
1527 
1528 static UChar *
s390_emit_CG(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)1529 s390_emit_CG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1530 {
1531    vassert(s390_host_has_ldisp || dh2 == 0);
1532 
1533    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1534       s390_disasm(ENC3(MNM, GPR, SDXB), "cg", r1, dh2, dl2, x2, b2);
1535 
1536    return emit_RXY(p, 0xe30000000020ULL, r1, x2, b2, dl2, dh2);
1537 }
1538 
1539 
1540 static UChar *
s390_emit_CFI(UChar * p,UChar r1,UInt i2)1541 s390_emit_CFI(UChar *p, UChar r1, UInt i2)
1542 {
1543    vassert(s390_host_has_eimm);
1544 
1545    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1546       s390_disasm(ENC3(MNM, GPR, INT), "cfi", r1, i2);
1547 
1548    return emit_RIL(p, 0xc20d00000000ULL, r1, i2);
1549 }
1550 
1551 
1552 static UChar *
s390_emit_CGFI(UChar * p,UChar r1,UInt i2)1553 s390_emit_CGFI(UChar *p, UChar r1, UInt i2)
1554 {
1555    vassert(s390_host_has_eimm);
1556 
1557    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1558       s390_disasm(ENC3(MNM, GPR, INT), "cgfi", r1, i2);
1559 
1560    return emit_RIL(p, 0xc20c00000000ULL, r1, i2);
1561 }
1562 
1563 
1564 static UChar *
s390_emit_CS(UChar * p,UChar r1,UChar r3,UChar b2,UShort d2)1565 s390_emit_CS(UChar *p, UChar r1, UChar r3, UChar b2, UShort d2)
1566 {
1567    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1568       s390_disasm(ENC4(MNM, GPR, GPR, UDXB), "cs", r1, r3, d2, 0, b2);
1569 
1570    return emit_RS(p, 0xba000000, r1, r3, b2, d2);
1571 }
1572 
1573 
1574 static UChar *
s390_emit_CSY(UChar * p,UChar r1,UChar r3,UChar b2,UShort dl2,UChar dh2)1575 s390_emit_CSY(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
1576 {
1577    vassert(s390_host_has_ldisp);
1578 
1579    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1580       s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "csy", r1, r3, dh2, dl2, 0, b2);
1581 
1582    return emit_RSY(p, 0xeb0000000014ULL, r1, r3, b2, dl2, dh2);
1583 }
1584 
1585 
1586 static UChar *
s390_emit_CSG(UChar * p,UChar r1,UChar r3,UChar b2,UShort dl2,UChar dh2)1587 s390_emit_CSG(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
1588 {
1589    vassert(s390_host_has_ldisp || dh2 == 0);
1590 
1591    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1592       s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "csg", r1, r3, dh2, dl2, 0, b2);
1593 
1594    return emit_RSY(p, 0xeb0000000030ULL, r1, r3, b2, dl2, dh2);
1595 }
1596 
1597 
1598 static UChar *
s390_emit_CDS(UChar * p,UChar r1,UChar r3,UChar b2,UShort d2)1599 s390_emit_CDS(UChar *p, UChar r1, UChar r3, UChar b2, UShort d2)
1600 {
1601    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1602       s390_disasm(ENC4(MNM, GPR, GPR, UDXB), "cds", r1, r3, d2, 0, b2);
1603 
1604    return emit_RS(p, 0xbb000000, r1, r3, b2, d2);
1605 }
1606 
1607 
1608 static UChar *
s390_emit_CDSY(UChar * p,UChar r1,UChar r3,UChar b2,UShort dl2,UChar dh2)1609 s390_emit_CDSY(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
1610 {
1611    vassert(s390_host_has_ldisp);
1612 
1613    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1614       s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "cdsy", r1, r3, dh2, dl2, 0, b2);
1615 
1616    return emit_RSY(p, 0xeb0000000031ULL, r1, r3, b2, dl2, dh2);
1617 }
1618 
1619 
1620 static UChar *
s390_emit_CDSG(UChar * p,UChar r1,UChar r3,UChar b2,UShort dl2,UChar dh2)1621 s390_emit_CDSG(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
1622 {
1623    vassert(s390_host_has_ldisp || dh2 == 0);
1624 
1625    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1626       s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "cdsg", r1, r3, dh2, dl2, 0, b2);
1627 
1628    return emit_RSY(p, 0xeb000000003eULL, r1, r3, b2, dl2, dh2);
1629 }
1630 
1631 
1632 static UChar *
s390_emit_CLR(UChar * p,UChar r1,UChar r2)1633 s390_emit_CLR(UChar *p, UChar r1, UChar r2)
1634 {
1635    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1636       s390_disasm(ENC3(MNM, GPR, GPR), "clr", r1, r2);
1637 
1638    return emit_RR(p, 0x1500, r1, r2);
1639 }
1640 
1641 
1642 static UChar *
s390_emit_CLGR(UChar * p,UChar r1,UChar r2)1643 s390_emit_CLGR(UChar *p, UChar r1, UChar r2)
1644 {
1645    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1646       s390_disasm(ENC3(MNM, GPR, GPR), "clgr", r1, r2);
1647 
1648    return emit_RRE(p, 0xb9210000, r1, r2);
1649 }
1650 
1651 
1652 static UChar *
s390_emit_CL(UChar * p,UChar r1,UChar x2,UChar b2,UShort d2)1653 s390_emit_CL(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
1654 {
1655    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1656       s390_disasm(ENC3(MNM, GPR, UDXB), "cl", r1, d2, x2, b2);
1657 
1658    return emit_RX(p, 0x55000000, r1, x2, b2, d2);
1659 }
1660 
1661 
1662 static UChar *
s390_emit_CLY(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)1663 s390_emit_CLY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1664 {
1665    vassert(s390_host_has_ldisp);
1666 
1667    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1668       s390_disasm(ENC3(MNM, GPR, SDXB), "cly", r1, dh2, dl2, x2, b2);
1669 
1670    return emit_RXY(p, 0xe30000000055ULL, r1, x2, b2, dl2, dh2);
1671 }
1672 
1673 
1674 static UChar *
s390_emit_CLG(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)1675 s390_emit_CLG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1676 {
1677    vassert(s390_host_has_ldisp || dh2 == 0);
1678 
1679    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1680       s390_disasm(ENC3(MNM, GPR, SDXB), "clg", r1, dh2, dl2, x2, b2);
1681 
1682    return emit_RXY(p, 0xe30000000021ULL, r1, x2, b2, dl2, dh2);
1683 }
1684 
1685 
1686 static UChar *
s390_emit_CLFI(UChar * p,UChar r1,UInt i2)1687 s390_emit_CLFI(UChar *p, UChar r1, UInt i2)
1688 {
1689    vassert(s390_host_has_eimm);
1690 
1691    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1692       s390_disasm(ENC3(MNM, GPR, UINT), "clfi", r1, i2);
1693 
1694    return emit_RIL(p, 0xc20f00000000ULL, r1, i2);
1695 }
1696 
1697 
1698 static UChar *
s390_emit_CLGFI(UChar * p,UChar r1,UInt i2)1699 s390_emit_CLGFI(UChar *p, UChar r1, UInt i2)
1700 {
1701    vassert(s390_host_has_eimm);
1702 
1703    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1704       s390_disasm(ENC3(MNM, GPR, UINT), "clgfi", r1, i2);
1705 
1706    return emit_RIL(p, 0xc20e00000000ULL, r1, i2);
1707 }
1708 
1709 
1710 static UChar *
s390_emit_DR(UChar * p,UChar r1,UChar r2)1711 s390_emit_DR(UChar *p, UChar r1, UChar r2)
1712 {
1713    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1714       s390_disasm(ENC3(MNM, GPR, GPR), "dr", r1, r2);
1715 
1716    return emit_RR(p, 0x1d00, r1, r2);
1717 }
1718 
1719 
1720 static UChar *
s390_emit_D(UChar * p,UChar r1,UChar x2,UChar b2,UShort d2)1721 s390_emit_D(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
1722 {
1723    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1724       s390_disasm(ENC3(MNM, GPR, UDXB), "d", r1, d2, x2, b2);
1725 
1726    return emit_RX(p, 0x5d000000, r1, x2, b2, d2);
1727 }
1728 
1729 
1730 static UChar *
s390_emit_DLR(UChar * p,UChar r1,UChar r2)1731 s390_emit_DLR(UChar *p, UChar r1, UChar r2)
1732 {
1733    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1734       s390_disasm(ENC3(MNM, GPR, GPR), "dlr", r1, r2);
1735 
1736    return emit_RRE(p, 0xb9970000, r1, r2);
1737 }
1738 
1739 
1740 static UChar *
s390_emit_DLGR(UChar * p,UChar r1,UChar r2)1741 s390_emit_DLGR(UChar *p, UChar r1, UChar r2)
1742 {
1743    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1744       s390_disasm(ENC3(MNM, GPR, GPR), "dlgr", r1, r2);
1745 
1746    return emit_RRE(p, 0xb9870000, r1, r2);
1747 }
1748 
1749 
1750 static UChar *
s390_emit_DL(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)1751 s390_emit_DL(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1752 {
1753    vassert(s390_host_has_ldisp || dh2 == 0);
1754 
1755    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1756       s390_disasm(ENC3(MNM, GPR, SDXB), "dl", r1, dh2, dl2, x2, b2);
1757 
1758    return emit_RXY(p, 0xe30000000097ULL, r1, x2, b2, dl2, dh2);
1759 }
1760 
1761 
1762 static UChar *
s390_emit_DLG(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)1763 s390_emit_DLG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1764 {
1765    vassert(s390_host_has_ldisp || dh2 == 0);
1766 
1767    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1768       s390_disasm(ENC3(MNM, GPR, SDXB), "dlg", r1, dh2, dl2, x2, b2);
1769 
1770    return emit_RXY(p, 0xe30000000087ULL, r1, x2, b2, dl2, dh2);
1771 }
1772 
1773 
1774 static UChar *
s390_emit_DSGR(UChar * p,UChar r1,UChar r2)1775 s390_emit_DSGR(UChar *p, UChar r1, UChar r2)
1776 {
1777    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1778       s390_disasm(ENC3(MNM, GPR, GPR), "dsgr", r1, r2);
1779 
1780    return emit_RRE(p, 0xb90d0000, r1, r2);
1781 }
1782 
1783 
1784 static UChar *
s390_emit_DSG(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)1785 s390_emit_DSG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1786 {
1787    vassert(s390_host_has_ldisp || dh2 == 0);
1788 
1789    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1790       s390_disasm(ENC3(MNM, GPR, SDXB), "dsg", r1, dh2, dl2, x2, b2);
1791 
1792    return emit_RXY(p, 0xe3000000000dULL, r1, x2, b2, dl2, dh2);
1793 }
1794 
1795 
1796 static UChar *
s390_emit_XR(UChar * p,UChar r1,UChar r2)1797 s390_emit_XR(UChar *p, UChar r1, UChar r2)
1798 {
1799    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1800       s390_disasm(ENC3(MNM, GPR, GPR), "xr", r1, r2);
1801 
1802    return emit_RR(p, 0x1700, r1, r2);
1803 }
1804 
1805 
1806 static UChar *
s390_emit_XGR(UChar * p,UChar r1,UChar r2)1807 s390_emit_XGR(UChar *p, UChar r1, UChar r2)
1808 {
1809    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1810       s390_disasm(ENC3(MNM, GPR, GPR), "xgr", r1, r2);
1811 
1812    return emit_RRE(p, 0xb9820000, r1, r2);
1813 }
1814 
1815 
1816 static UChar *
s390_emit_X(UChar * p,UChar r1,UChar x2,UChar b2,UShort d2)1817 s390_emit_X(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
1818 {
1819    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1820       s390_disasm(ENC3(MNM, GPR, UDXB), "x", r1, d2, x2, b2);
1821 
1822    return emit_RX(p, 0x57000000, r1, x2, b2, d2);
1823 }
1824 
1825 
1826 static UChar *
s390_emit_XY(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)1827 s390_emit_XY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1828 {
1829    vassert(s390_host_has_ldisp);
1830 
1831    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1832       s390_disasm(ENC3(MNM, GPR, SDXB), "xy", r1, dh2, dl2, x2, b2);
1833 
1834    return emit_RXY(p, 0xe30000000057ULL, r1, x2, b2, dl2, dh2);
1835 }
1836 
1837 
1838 static UChar *
s390_emit_XG(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)1839 s390_emit_XG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1840 {
1841    vassert(s390_host_has_ldisp || dh2 == 0);
1842 
1843    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1844       s390_disasm(ENC3(MNM, GPR, SDXB), "xg", r1, dh2, dl2, x2, b2);
1845 
1846    return emit_RXY(p, 0xe30000000082ULL, r1, x2, b2, dl2, dh2);
1847 }
1848 
1849 
1850 static UChar *
s390_emit_XIHF(UChar * p,UChar r1,UInt i2)1851 s390_emit_XIHF(UChar *p, UChar r1, UInt i2)
1852 {
1853    vassert(s390_host_has_eimm);
1854 
1855    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1856       s390_disasm(ENC3(MNM, GPR, UINT), "xihf", r1, i2);
1857 
1858    return emit_RIL(p, 0xc00600000000ULL, r1, i2);
1859 }
1860 
1861 
1862 static UChar *
s390_emit_XILF(UChar * p,UChar r1,UInt i2)1863 s390_emit_XILF(UChar *p, UChar r1, UInt i2)
1864 {
1865    vassert(s390_host_has_eimm);
1866 
1867    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1868       s390_disasm(ENC3(MNM, GPR, UINT), "xilf", r1, i2);
1869 
1870    return emit_RIL(p, 0xc00700000000ULL, r1, i2);
1871 }
1872 
1873 
1874 static UChar *
s390_emit_XC(UChar * p,UInt l,UChar b1,UShort d1,UChar b2,UShort d2)1875 s390_emit_XC(UChar *p, UInt l, UChar b1, UShort d1, UChar b2, UShort d2)
1876 {
1877    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1878       s390_disasm(ENC3(MNM, UDLB, UDXB), "xc", d1, l, b1, d2, 0, b2);
1879 
1880    return emit_SSa(p, 0xd70000000000ULL, l, b1, d1, b2, d2);
1881 }
1882 
1883 
1884 static UChar *
s390_emit_FLOGR(UChar * p,UChar r1,UChar r2)1885 s390_emit_FLOGR(UChar *p, UChar r1, UChar r2)
1886 {
1887    vassert(s390_host_has_eimm);
1888 
1889    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1890       s390_disasm(ENC3(MNM, GPR, GPR), "flogr", r1, r2);
1891 
1892    return emit_RRE(p, 0xb9830000, r1, r2);
1893 }
1894 
1895 
1896 static UChar *
s390_emit_IC(UChar * p,UChar r1,UChar x2,UChar b2,UShort d2)1897 s390_emit_IC(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
1898 {
1899    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1900       s390_disasm(ENC3(MNM, GPR, UDXB), "ic", r1, d2, x2, b2);
1901 
1902    return emit_RX(p, 0x43000000, r1, x2, b2, d2);
1903 }
1904 
1905 
1906 static UChar *
s390_emit_ICY(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)1907 s390_emit_ICY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1908 {
1909    vassert(s390_host_has_ldisp);
1910 
1911    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1912       s390_disasm(ENC3(MNM, GPR, SDXB), "icy", r1, dh2, dl2, x2, b2);
1913 
1914    return emit_RXY(p, 0xe30000000073ULL, r1, x2, b2, dl2, dh2);
1915 }
1916 
1917 
1918 static UChar *
s390_emit_IIHF(UChar * p,UChar r1,UInt i2)1919 s390_emit_IIHF(UChar *p, UChar r1, UInt i2)
1920 {
1921    vassert(s390_host_has_eimm);
1922 
1923    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1924       s390_disasm(ENC3(MNM, GPR, UINT), "iihf", r1, i2);
1925 
1926    return emit_RIL(p, 0xc00800000000ULL, r1, i2);
1927 }
1928 
1929 
1930 static UChar *
s390_emit_IIHH(UChar * p,UChar r1,UShort i2)1931 s390_emit_IIHH(UChar *p, UChar r1, UShort i2)
1932 {
1933    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1934       s390_disasm(ENC3(MNM, GPR, UINT), "iihh", r1, i2);
1935 
1936    return emit_RI(p, 0xa5000000, r1, i2);
1937 }
1938 
1939 
1940 static UChar *
s390_emit_IIHL(UChar * p,UChar r1,UShort i2)1941 s390_emit_IIHL(UChar *p, UChar r1, UShort i2)
1942 {
1943    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1944       s390_disasm(ENC3(MNM, GPR, UINT), "iihl", r1, i2);
1945 
1946    return emit_RI(p, 0xa5010000, r1, i2);
1947 }
1948 
1949 
1950 static UChar *
s390_emit_IILF(UChar * p,UChar r1,UInt i2)1951 s390_emit_IILF(UChar *p, UChar r1, UInt i2)
1952 {
1953    vassert(s390_host_has_eimm);
1954 
1955    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1956       s390_disasm(ENC3(MNM, GPR, UINT), "iilf", r1, i2);
1957 
1958    return emit_RIL(p, 0xc00900000000ULL, r1, i2);
1959 }
1960 
1961 
1962 static UChar *
s390_emit_IILH(UChar * p,UChar r1,UShort i2)1963 s390_emit_IILH(UChar *p, UChar r1, UShort i2)
1964 {
1965    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1966       s390_disasm(ENC3(MNM, GPR, UINT), "iilh", r1, i2);
1967 
1968    return emit_RI(p, 0xa5020000, r1, i2);
1969 }
1970 
1971 
1972 static UChar *
s390_emit_IILL(UChar * p,UChar r1,UShort i2)1973 s390_emit_IILL(UChar *p, UChar r1, UShort i2)
1974 {
1975    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1976       s390_disasm(ENC3(MNM, GPR, UINT), "iill", r1, i2);
1977 
1978    return emit_RI(p, 0xa5030000, r1, i2);
1979 }
1980 
1981 
1982 static UChar *
s390_emit_IPM(UChar * p,UChar r1,UChar r2)1983 s390_emit_IPM(UChar *p, UChar r1, UChar r2)
1984 {
1985    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1986       s390_disasm(ENC2(MNM, GPR), "ipm", r1);
1987 
1988    return emit_RRE(p, 0xb2220000, r1, r2);
1989 }
1990 
1991 
1992 static UChar *
s390_emit_LR(UChar * p,UChar r1,UChar r2)1993 s390_emit_LR(UChar *p, UChar r1, UChar r2)
1994 {
1995    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1996       s390_disasm(ENC3(MNM, GPR, GPR), "lr", r1, r2);
1997 
1998    return emit_RR(p, 0x1800, r1, r2);
1999 }
2000 
2001 
2002 static UChar *
s390_emit_LGR(UChar * p,UChar r1,UChar r2)2003 s390_emit_LGR(UChar *p, UChar r1, UChar r2)
2004 {
2005    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2006       s390_disasm(ENC3(MNM, GPR, GPR), "lgr", r1, r2);
2007 
2008    return emit_RRE(p, 0xb9040000, r1, r2);
2009 }
2010 
2011 
2012 static UChar *
s390_emit_LGFR(UChar * p,UChar r1,UChar r2)2013 s390_emit_LGFR(UChar *p, UChar r1, UChar r2)
2014 {
2015    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2016       s390_disasm(ENC3(MNM, GPR, GPR), "lgfr", r1, r2);
2017 
2018    return emit_RRE(p, 0xb9140000, r1, r2);
2019 }
2020 
2021 
2022 static UChar *
s390_emit_L(UChar * p,UChar r1,UChar x2,UChar b2,UShort d2)2023 s390_emit_L(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2024 {
2025    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2026       s390_disasm(ENC3(MNM, GPR, UDXB), "l", r1, d2, x2, b2);
2027 
2028    return emit_RX(p, 0x58000000, r1, x2, b2, d2);
2029 }
2030 
2031 
2032 static UChar *
s390_emit_LY(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)2033 s390_emit_LY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2034 {
2035    vassert(s390_host_has_ldisp);
2036 
2037    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2038       s390_disasm(ENC3(MNM, GPR, SDXB), "ly", r1, dh2, dl2, x2, b2);
2039 
2040    return emit_RXY(p, 0xe30000000058ULL, r1, x2, b2, dl2, dh2);
2041 }
2042 
2043 
2044 static UChar *
s390_emit_LG(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)2045 s390_emit_LG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2046 {
2047    vassert(s390_host_has_ldisp || dh2 == 0);
2048 
2049    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2050       s390_disasm(ENC3(MNM, GPR, SDXB), "lg", r1, dh2, dl2, x2, b2);
2051 
2052    return emit_RXY(p, 0xe30000000004ULL, r1, x2, b2, dl2, dh2);
2053 }
2054 
2055 
2056 static UChar *
s390_emit_LGF(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)2057 s390_emit_LGF(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2058 {
2059    vassert(s390_host_has_ldisp || dh2 == 0);
2060 
2061    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2062       s390_disasm(ENC3(MNM, GPR, SDXB), "lgf", r1, dh2, dl2, x2, b2);
2063 
2064    return emit_RXY(p, 0xe30000000014ULL, r1, x2, b2, dl2, dh2);
2065 }
2066 
2067 
2068 static UChar *
s390_emit_LGFI(UChar * p,UChar r1,UInt i2)2069 s390_emit_LGFI(UChar *p, UChar r1, UInt i2)
2070 {
2071    vassert(s390_host_has_eimm);
2072 
2073    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2074       s390_disasm(ENC3(MNM, GPR, INT), "lgfi", r1, i2);
2075 
2076    return emit_RIL(p, 0xc00100000000ULL, r1, i2);
2077 }
2078 
2079 
2080 static UChar *
s390_emit_LTR(UChar * p,UChar r1,UChar r2)2081 s390_emit_LTR(UChar *p, UChar r1, UChar r2)
2082 {
2083    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2084       s390_disasm(ENC3(MNM, GPR, GPR), "ltr", r1, r2);
2085 
2086    return emit_RR(p, 0x1200, r1, r2);
2087 }
2088 
2089 
2090 static UChar *
s390_emit_LTGR(UChar * p,UChar r1,UChar r2)2091 s390_emit_LTGR(UChar *p, UChar r1, UChar r2)
2092 {
2093    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2094       s390_disasm(ENC3(MNM, GPR, GPR), "ltgr", r1, r2);
2095 
2096    return emit_RRE(p, 0xb9020000, r1, r2);
2097 }
2098 
2099 
2100 static UChar *
s390_emit_LT(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)2101 s390_emit_LT(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2102 {
2103    vassert(s390_host_has_eimm);
2104 
2105    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2106       s390_disasm(ENC3(MNM, GPR, SDXB), "lt", r1, dh2, dl2, x2, b2);
2107 
2108    return emit_RXY(p, 0xe30000000012ULL, r1, x2, b2, dl2, dh2);
2109 }
2110 
2111 
2112 static UChar *
s390_emit_LTG(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)2113 s390_emit_LTG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2114 {
2115    vassert(s390_host_has_eimm);
2116 
2117    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2118       s390_disasm(ENC3(MNM, GPR, SDXB), "ltg", r1, dh2, dl2, x2, b2);
2119 
2120    return emit_RXY(p, 0xe30000000002ULL, r1, x2, b2, dl2, dh2);
2121 }
2122 
2123 
2124 static UChar *
s390_emit_LBR(UChar * p,UChar r1,UChar r2)2125 s390_emit_LBR(UChar *p, UChar r1, UChar r2)
2126 {
2127    vassert(s390_host_has_eimm);
2128 
2129    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2130       s390_disasm(ENC3(MNM, GPR, GPR), "lbr", r1, r2);
2131 
2132    return emit_RRE(p, 0xb9260000, r1, r2);
2133 }
2134 
2135 
2136 static UChar *
s390_emit_LGBR(UChar * p,UChar r1,UChar r2)2137 s390_emit_LGBR(UChar *p, UChar r1, UChar r2)
2138 {
2139    vassert(s390_host_has_eimm);
2140 
2141    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2142       s390_disasm(ENC3(MNM, GPR, GPR), "lgbr", r1, r2);
2143 
2144    return emit_RRE(p, 0xb9060000, r1, r2);
2145 }
2146 
2147 
2148 static UChar *
s390_emit_LB(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)2149 s390_emit_LB(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2150 {
2151    vassert(s390_host_has_ldisp);
2152 
2153    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2154       s390_disasm(ENC3(MNM, GPR, SDXB), "lb", r1, dh2, dl2, x2, b2);
2155 
2156    return emit_RXY(p, 0xe30000000076ULL, r1, x2, b2, dl2, dh2);
2157 }
2158 
2159 
2160 static UChar *
s390_emit_LGB(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)2161 s390_emit_LGB(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2162 {
2163    vassert(s390_host_has_ldisp);
2164 
2165    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2166       s390_disasm(ENC3(MNM, GPR, SDXB), "lgb", r1, dh2, dl2, x2, b2);
2167 
2168    return emit_RXY(p, 0xe30000000077ULL, r1, x2, b2, dl2, dh2);
2169 }
2170 
2171 
2172 static UChar *
s390_emit_LCR(UChar * p,UChar r1,UChar r2)2173 s390_emit_LCR(UChar *p, UChar r1, UChar r2)
2174 {
2175    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2176       s390_disasm(ENC3(MNM, GPR, GPR), "lcr", r1, r2);
2177 
2178    return emit_RR(p, 0x1300, r1, r2);
2179 }
2180 
2181 
2182 static UChar *
s390_emit_LCGR(UChar * p,UChar r1,UChar r2)2183 s390_emit_LCGR(UChar *p, UChar r1, UChar r2)
2184 {
2185    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2186       s390_disasm(ENC3(MNM, GPR, GPR), "lcgr", r1, r2);
2187 
2188    return emit_RRE(p, 0xb9030000, r1, r2);
2189 }
2190 
2191 
2192 static UChar *
s390_emit_LHR(UChar * p,UChar r1,UChar r2)2193 s390_emit_LHR(UChar *p, UChar r1, UChar r2)
2194 {
2195    vassert(s390_host_has_eimm);
2196 
2197    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2198       s390_disasm(ENC3(MNM, GPR, GPR), "lhr", r1, r2);
2199 
2200    return emit_RRE(p, 0xb9270000, r1, r2);
2201 }
2202 
2203 
2204 static UChar *
s390_emit_LGHR(UChar * p,UChar r1,UChar r2)2205 s390_emit_LGHR(UChar *p, UChar r1, UChar r2)
2206 {
2207    vassert(s390_host_has_eimm);
2208 
2209    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2210       s390_disasm(ENC3(MNM, GPR, GPR), "lghr", r1, r2);
2211 
2212    return emit_RRE(p, 0xb9070000, r1, r2);
2213 }
2214 
2215 
2216 static UChar *
s390_emit_LH(UChar * p,UChar r1,UChar x2,UChar b2,UShort d2)2217 s390_emit_LH(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2218 {
2219    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2220       s390_disasm(ENC3(MNM, GPR, UDXB), "lh", r1, d2, x2, b2);
2221 
2222    return emit_RX(p, 0x48000000, r1, x2, b2, d2);
2223 }
2224 
2225 
2226 static UChar *
s390_emit_LHY(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)2227 s390_emit_LHY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2228 {
2229    vassert(s390_host_has_ldisp);
2230 
2231    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2232       s390_disasm(ENC3(MNM, GPR, SDXB), "lhy", r1, dh2, dl2, x2, b2);
2233 
2234    return emit_RXY(p, 0xe30000000078ULL, r1, x2, b2, dl2, dh2);
2235 }
2236 
2237 
2238 static UChar *
s390_emit_LGH(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)2239 s390_emit_LGH(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2240 {
2241    vassert(s390_host_has_ldisp || dh2 == 0);
2242 
2243    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2244       s390_disasm(ENC3(MNM, GPR, SDXB), "lgh", r1, dh2, dl2, x2, b2);
2245 
2246    return emit_RXY(p, 0xe30000000015ULL, r1, x2, b2, dl2, dh2);
2247 }
2248 
2249 
2250 static UChar *
s390_emit_LHI(UChar * p,UChar r1,UShort i2)2251 s390_emit_LHI(UChar *p, UChar r1, UShort i2)
2252 {
2253    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2254       s390_disasm(ENC3(MNM, GPR, INT), "lhi", r1, (Int)(Short)i2);
2255 
2256    return emit_RI(p, 0xa7080000, r1, i2);
2257 }
2258 
2259 
2260 static UChar *
s390_emit_LGHI(UChar * p,UChar r1,UShort i2)2261 s390_emit_LGHI(UChar *p, UChar r1, UShort i2)
2262 {
2263    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2264       s390_disasm(ENC3(MNM, GPR, INT), "lghi", r1, (Int)(Short)i2);
2265 
2266    return emit_RI(p, 0xa7090000, r1, i2);
2267 }
2268 
2269 
2270 static UChar *
s390_emit_LLGFR(UChar * p,UChar r1,UChar r2)2271 s390_emit_LLGFR(UChar *p, UChar r1, UChar r2)
2272 {
2273    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2274       s390_disasm(ENC3(MNM, GPR, GPR), "llgfr", r1, r2);
2275 
2276    return emit_RRE(p, 0xb9160000, r1, r2);
2277 }
2278 
2279 
2280 static UChar *
s390_emit_LLGF(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)2281 s390_emit_LLGF(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2282 {
2283    vassert(s390_host_has_ldisp || dh2 == 0);
2284 
2285    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2286       s390_disasm(ENC3(MNM, GPR, SDXB), "llgf", r1, dh2, dl2, x2, b2);
2287 
2288    return emit_RXY(p, 0xe30000000016ULL, r1, x2, b2, dl2, dh2);
2289 }
2290 
2291 
2292 static UChar *
s390_emit_LLCR(UChar * p,UChar r1,UChar r2)2293 s390_emit_LLCR(UChar *p, UChar r1, UChar r2)
2294 {
2295    vassert(s390_host_has_eimm);
2296 
2297    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2298       s390_disasm(ENC3(MNM, GPR, GPR), "llcr", r1, r2);
2299 
2300    return emit_RRE(p, 0xb9940000, r1, r2);
2301 }
2302 
2303 
2304 static UChar *
s390_emit_LLGCR(UChar * p,UChar r1,UChar r2)2305 s390_emit_LLGCR(UChar *p, UChar r1, UChar r2)
2306 {
2307    vassert(s390_host_has_eimm);
2308 
2309    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2310       s390_disasm(ENC3(MNM, GPR, GPR), "llgcr", r1, r2);
2311 
2312    return emit_RRE(p, 0xb9840000, r1, r2);
2313 }
2314 
2315 
2316 static UChar *
s390_emit_LLC(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)2317 s390_emit_LLC(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2318 {
2319    vassert(s390_host_has_eimm);
2320 
2321    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2322       s390_disasm(ENC3(MNM, GPR, SDXB), "llc", r1, dh2, dl2, x2, b2);
2323 
2324    return emit_RXY(p, 0xe30000000094ULL, r1, x2, b2, dl2, dh2);
2325 }
2326 
2327 
2328 static UChar *
s390_emit_LLGC(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)2329 s390_emit_LLGC(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2330 {
2331    vassert(s390_host_has_ldisp || dh2 == 0);
2332 
2333    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2334       s390_disasm(ENC3(MNM, GPR, SDXB), "llgc", r1, dh2, dl2, x2, b2);
2335 
2336    return emit_RXY(p, 0xe30000000090ULL, r1, x2, b2, dl2, dh2);
2337 }
2338 
2339 
2340 static UChar *
s390_emit_LLHR(UChar * p,UChar r1,UChar r2)2341 s390_emit_LLHR(UChar *p, UChar r1, UChar r2)
2342 {
2343    vassert(s390_host_has_eimm);
2344 
2345    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2346       s390_disasm(ENC3(MNM, GPR, GPR), "llhr", r1, r2);
2347 
2348    return emit_RRE(p, 0xb9950000, r1, r2);
2349 }
2350 
2351 
2352 static UChar *
s390_emit_LLGHR(UChar * p,UChar r1,UChar r2)2353 s390_emit_LLGHR(UChar *p, UChar r1, UChar r2)
2354 {
2355    vassert(s390_host_has_eimm);
2356 
2357    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2358       s390_disasm(ENC3(MNM, GPR, GPR), "llghr", r1, r2);
2359 
2360    return emit_RRE(p, 0xb9850000, r1, r2);
2361 }
2362 
2363 
2364 static UChar *
s390_emit_LLH(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)2365 s390_emit_LLH(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2366 {
2367    vassert(s390_host_has_eimm);
2368 
2369    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2370       s390_disasm(ENC3(MNM, GPR, SDXB), "llh", r1, dh2, dl2, x2, b2);
2371 
2372    return emit_RXY(p, 0xe30000000095ULL, r1, x2, b2, dl2, dh2);
2373 }
2374 
2375 
2376 static UChar *
s390_emit_LLGH(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)2377 s390_emit_LLGH(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2378 {
2379    vassert(s390_host_has_ldisp || dh2 == 0);
2380 
2381    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2382       s390_disasm(ENC3(MNM, GPR, SDXB), "llgh", r1, dh2, dl2, x2, b2);
2383 
2384    return emit_RXY(p, 0xe30000000091ULL, r1, x2, b2, dl2, dh2);
2385 }
2386 
2387 
2388 static UChar *
s390_emit_LLILF(UChar * p,UChar r1,UInt i2)2389 s390_emit_LLILF(UChar *p, UChar r1, UInt i2)
2390 {
2391    vassert(s390_host_has_eimm);
2392 
2393    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2394       s390_disasm(ENC3(MNM, GPR, UINT), "llilf", r1, i2);
2395 
2396    return emit_RIL(p, 0xc00f00000000ULL, r1, i2);
2397 }
2398 
2399 
2400 static UChar *
s390_emit_LLILH(UChar * p,UChar r1,UShort i2)2401 s390_emit_LLILH(UChar *p, UChar r1, UShort i2)
2402 {
2403    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2404       s390_disasm(ENC3(MNM, GPR, UINT), "llilh", r1, i2);
2405 
2406    return emit_RI(p, 0xa50e0000, r1, i2);
2407 }
2408 
2409 
2410 static UChar *
s390_emit_LLILL(UChar * p,UChar r1,UShort i2)2411 s390_emit_LLILL(UChar *p, UChar r1, UShort i2)
2412 {
2413    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2414       s390_disasm(ENC3(MNM, GPR, UINT), "llill", r1, i2);
2415 
2416    return emit_RI(p, 0xa50f0000, r1, i2);
2417 }
2418 
2419 
2420 static UChar *
s390_emit_MR(UChar * p,UChar r1,UChar r2)2421 s390_emit_MR(UChar *p, UChar r1, UChar r2)
2422 {
2423    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2424       s390_disasm(ENC3(MNM, GPR, GPR), "mr", r1, r2);
2425 
2426    return emit_RR(p, 0x1c00, r1, r2);
2427 }
2428 
2429 
2430 static UChar *
s390_emit_M(UChar * p,UChar r1,UChar x2,UChar b2,UShort d2)2431 s390_emit_M(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2432 {
2433    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2434       s390_disasm(ENC3(MNM, GPR, UDXB), "m", r1, d2, x2, b2);
2435 
2436    return emit_RX(p, 0x5c000000, r1, x2, b2, d2);
2437 }
2438 
2439 
2440 static UChar *
s390_emit_MFY(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)2441 s390_emit_MFY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2442 {
2443    vassert(s390_host_has_gie);
2444 
2445    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2446       s390_disasm(ENC3(MNM, GPR, SDXB), "mfy", r1, dh2, dl2, x2, b2);
2447 
2448    return emit_RXY(p, 0xe3000000005cULL, r1, x2, b2, dl2, dh2);
2449 }
2450 
2451 
2452 static UChar *
s390_emit_MH(UChar * p,UChar r1,UChar x2,UChar b2,UShort d2)2453 s390_emit_MH(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2454 {
2455    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2456       s390_disasm(ENC3(MNM, GPR, UDXB), "mh", r1, d2, x2, b2);
2457 
2458    return emit_RX(p, 0x4c000000, r1, x2, b2, d2);
2459 }
2460 
2461 
2462 static UChar *
s390_emit_MHY(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)2463 s390_emit_MHY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2464 {
2465    vassert(s390_host_has_gie);
2466 
2467    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2468       s390_disasm(ENC3(MNM, GPR, SDXB), "mhy", r1, dh2, dl2, x2, b2);
2469 
2470    return emit_RXY(p, 0xe3000000007cULL, r1, x2, b2, dl2, dh2);
2471 }
2472 
2473 
2474 static UChar *
s390_emit_MHI(UChar * p,UChar r1,UShort i2)2475 s390_emit_MHI(UChar *p, UChar r1, UShort i2)
2476 {
2477    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2478       s390_disasm(ENC3(MNM, GPR, INT), "mhi", r1, (Int)(Short)i2);
2479 
2480    return emit_RI(p, 0xa70c0000, r1, i2);
2481 }
2482 
2483 
2484 static UChar *
s390_emit_MLR(UChar * p,UChar r1,UChar r2)2485 s390_emit_MLR(UChar *p, UChar r1, UChar r2)
2486 {
2487    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2488       s390_disasm(ENC3(MNM, GPR, GPR), "mlr", r1, r2);
2489 
2490    return emit_RRE(p, 0xb9960000, r1, r2);
2491 }
2492 
2493 
2494 static UChar *
s390_emit_MLGR(UChar * p,UChar r1,UChar r2)2495 s390_emit_MLGR(UChar *p, UChar r1, UChar r2)
2496 {
2497    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2498       s390_disasm(ENC3(MNM, GPR, GPR), "mlgr", r1, r2);
2499 
2500    return emit_RRE(p, 0xb9860000, r1, r2);
2501 }
2502 
2503 
2504 static UChar *
s390_emit_ML(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)2505 s390_emit_ML(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2506 {
2507    vassert(s390_host_has_ldisp || dh2 == 0);
2508 
2509    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2510       s390_disasm(ENC3(MNM, GPR, SDXB), "ml", r1, dh2, dl2, x2, b2);
2511 
2512    return emit_RXY(p, 0xe30000000096ULL, r1, x2, b2, dl2, dh2);
2513 }
2514 
2515 
2516 static UChar *
s390_emit_MLG(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)2517 s390_emit_MLG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2518 {
2519    vassert(s390_host_has_ldisp || dh2 == 0);
2520 
2521    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2522       s390_disasm(ENC3(MNM, GPR, SDXB), "mlg", r1, dh2, dl2, x2, b2);
2523 
2524    return emit_RXY(p, 0xe30000000086ULL, r1, x2, b2, dl2, dh2);
2525 }
2526 
2527 
2528 static UChar *
s390_emit_MSR(UChar * p,UChar r1,UChar r2)2529 s390_emit_MSR(UChar *p, UChar r1, UChar r2)
2530 {
2531    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2532       s390_disasm(ENC3(MNM, GPR, GPR), "msr", r1, r2);
2533 
2534    return emit_RRE(p, 0xb2520000, r1, r2);
2535 }
2536 
2537 
2538 static UChar *
s390_emit_MSGR(UChar * p,UChar r1,UChar r2)2539 s390_emit_MSGR(UChar *p, UChar r1, UChar r2)
2540 {
2541    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2542       s390_disasm(ENC3(MNM, GPR, GPR), "msgr", r1, r2);
2543 
2544    return emit_RRE(p, 0xb90c0000, r1, r2);
2545 }
2546 
2547 
2548 static UChar *
s390_emit_MS(UChar * p,UChar r1,UChar x2,UChar b2,UShort d2)2549 s390_emit_MS(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2550 {
2551    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2552       s390_disasm(ENC3(MNM, GPR, UDXB), "ms", r1, d2, x2, b2);
2553 
2554    return emit_RX(p, 0x71000000, r1, x2, b2, d2);
2555 }
2556 
2557 
2558 static UChar *
s390_emit_MSY(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)2559 s390_emit_MSY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2560 {
2561    vassert(s390_host_has_ldisp);
2562 
2563    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2564       s390_disasm(ENC3(MNM, GPR, SDXB), "msy", r1, dh2, dl2, x2, b2);
2565 
2566    return emit_RXY(p, 0xe30000000051ULL, r1, x2, b2, dl2, dh2);
2567 }
2568 
2569 
2570 static UChar *
s390_emit_MSG(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)2571 s390_emit_MSG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2572 {
2573    vassert(s390_host_has_ldisp || dh2 == 0);
2574 
2575    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2576       s390_disasm(ENC3(MNM, GPR, SDXB), "msg", r1, dh2, dl2, x2, b2);
2577 
2578    return emit_RXY(p, 0xe3000000000cULL, r1, x2, b2, dl2, dh2);
2579 }
2580 
2581 
2582 static UChar *
s390_emit_MSFI(UChar * p,UChar r1,UInt i2)2583 s390_emit_MSFI(UChar *p, UChar r1, UInt i2)
2584 {
2585    vassert(s390_host_has_gie);
2586 
2587    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2588       s390_disasm(ENC3(MNM, GPR, INT), "msfi", r1, i2);
2589 
2590    return emit_RIL(p, 0xc20100000000ULL, r1, i2);
2591 }
2592 
2593 
2594 static UChar *
s390_emit_MSGFI(UChar * p,UChar r1,UInt i2)2595 s390_emit_MSGFI(UChar *p, UChar r1, UInt i2)
2596 {
2597    vassert(s390_host_has_gie);
2598 
2599    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2600       s390_disasm(ENC3(MNM, GPR, INT), "msgfi", r1, i2);
2601 
2602    return emit_RIL(p, 0xc20000000000ULL, r1, i2);
2603 }
2604 
2605 
2606 static UChar *
s390_emit_OR(UChar * p,UChar r1,UChar r2)2607 s390_emit_OR(UChar *p, UChar r1, UChar r2)
2608 {
2609    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2610       s390_disasm(ENC3(MNM, GPR, GPR), "or", r1, r2);
2611 
2612    return emit_RR(p, 0x1600, r1, r2);
2613 }
2614 
2615 
2616 static UChar *
s390_emit_OGR(UChar * p,UChar r1,UChar r2)2617 s390_emit_OGR(UChar *p, UChar r1, UChar r2)
2618 {
2619    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2620       s390_disasm(ENC3(MNM, GPR, GPR), "ogr", r1, r2);
2621 
2622    return emit_RRE(p, 0xb9810000, r1, r2);
2623 }
2624 
2625 
2626 static UChar *
s390_emit_O(UChar * p,UChar r1,UChar x2,UChar b2,UShort d2)2627 s390_emit_O(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2628 {
2629    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2630       s390_disasm(ENC3(MNM, GPR, UDXB), "o", r1, d2, x2, b2);
2631 
2632    return emit_RX(p, 0x56000000, r1, x2, b2, d2);
2633 }
2634 
2635 
2636 static UChar *
s390_emit_OY(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)2637 s390_emit_OY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2638 {
2639    vassert(s390_host_has_ldisp);
2640 
2641    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2642       s390_disasm(ENC3(MNM, GPR, SDXB), "oy", r1, dh2, dl2, x2, b2);
2643 
2644    return emit_RXY(p, 0xe30000000056ULL, r1, x2, b2, dl2, dh2);
2645 }
2646 
2647 
2648 static UChar *
s390_emit_OG(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)2649 s390_emit_OG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2650 {
2651    vassert(s390_host_has_ldisp || dh2 == 0);
2652 
2653    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2654       s390_disasm(ENC3(MNM, GPR, SDXB), "og", r1, dh2, dl2, x2, b2);
2655 
2656    return emit_RXY(p, 0xe30000000081ULL, r1, x2, b2, dl2, dh2);
2657 }
2658 
2659 
2660 static UChar *
s390_emit_OIHF(UChar * p,UChar r1,UInt i2)2661 s390_emit_OIHF(UChar *p, UChar r1, UInt i2)
2662 {
2663    vassert(s390_host_has_eimm);
2664 
2665    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2666       s390_disasm(ENC3(MNM, GPR, UINT), "oihf", r1, i2);
2667 
2668    return emit_RIL(p, 0xc00c00000000ULL, r1, i2);
2669 }
2670 
2671 
2672 static UChar *
s390_emit_OILF(UChar * p,UChar r1,UInt i2)2673 s390_emit_OILF(UChar *p, UChar r1, UInt i2)
2674 {
2675    vassert(s390_host_has_eimm);
2676 
2677    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2678       s390_disasm(ENC3(MNM, GPR, UINT), "oilf", r1, i2);
2679 
2680    return emit_RIL(p, 0xc00d00000000ULL, r1, i2);
2681 }
2682 
2683 
2684 static UChar *
s390_emit_OILL(UChar * p,UChar r1,UShort i2)2685 s390_emit_OILL(UChar *p, UChar r1, UShort i2)
2686 {
2687    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2688       s390_disasm(ENC3(MNM, GPR, UINT), "oill", r1, i2);
2689 
2690    return emit_RI(p, 0xa50b0000, r1, i2);
2691 }
2692 
2693 
2694 static UChar *
s390_emit_SLL(UChar * p,UChar r1,UChar b2,UShort d2)2695 s390_emit_SLL(UChar *p, UChar r1, UChar b2, UShort d2)
2696 {
2697    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2698       s390_disasm(ENC3(MNM, GPR, UDXB), "sll", r1, d2, 0, b2);
2699 
2700    return emit_RS(p, 0x89000000, r1, 0, b2, d2);
2701 }
2702 
2703 
2704 static UChar *
s390_emit_SLLG(UChar * p,UChar r1,UChar r3,UChar b2,UShort dl2,UChar dh2)2705 s390_emit_SLLG(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
2706 {
2707    vassert(s390_host_has_ldisp || dh2 == 0);
2708 
2709    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2710       s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "sllg", r1, r3, dh2, dl2, 0, b2);
2711 
2712    return emit_RSY(p, 0xeb000000000dULL, r1, r3, b2, dl2, dh2);
2713 }
2714 
2715 
2716 static UChar *
s390_emit_SRA(UChar * p,UChar r1,UChar b2,UShort d2)2717 s390_emit_SRA(UChar *p, UChar r1, UChar b2, UShort d2)
2718 {
2719    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2720       s390_disasm(ENC3(MNM, GPR, UDXB), "sra", r1, d2, 0, b2);
2721 
2722    return emit_RS(p, 0x8a000000, r1, 0, b2, d2);
2723 }
2724 
2725 
2726 static UChar *
s390_emit_SRAG(UChar * p,UChar r1,UChar r3,UChar b2,UShort dl2,UChar dh2)2727 s390_emit_SRAG(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
2728 {
2729    vassert(s390_host_has_ldisp || dh2 == 0);
2730 
2731    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2732       s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "srag", r1, r3, dh2, dl2, 0, b2);
2733 
2734    return emit_RSY(p, 0xeb000000000aULL, r1, r3, b2, dl2, dh2);
2735 }
2736 
2737 
2738 static UChar *
s390_emit_SRL(UChar * p,UChar r1,UChar b2,UShort d2)2739 s390_emit_SRL(UChar *p, UChar r1, UChar b2, UShort d2)
2740 {
2741    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2742       s390_disasm(ENC3(MNM, GPR, UDXB), "srl", r1, d2, 0, b2);
2743 
2744    return emit_RS(p, 0x88000000, r1, 0, b2, d2);
2745 }
2746 
2747 
2748 static UChar *
s390_emit_SRLG(UChar * p,UChar r1,UChar r3,UChar b2,UShort dl2,UChar dh2)2749 s390_emit_SRLG(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
2750 {
2751    vassert(s390_host_has_ldisp || dh2 == 0);
2752 
2753    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2754       s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "srlg", r1, r3, dh2, dl2, 0, b2);
2755 
2756    return emit_RSY(p, 0xeb000000000cULL, r1, r3, b2, dl2, dh2);
2757 }
2758 
2759 
2760 static UChar *
s390_emit_ST(UChar * p,UChar r1,UChar x2,UChar b2,UShort d2)2761 s390_emit_ST(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2762 {
2763    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2764       s390_disasm(ENC3(MNM, GPR, UDXB), "st", r1, d2, x2, b2);
2765 
2766    return emit_RX(p, 0x50000000, r1, x2, b2, d2);
2767 }
2768 
2769 
2770 static UChar *
s390_emit_STY(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)2771 s390_emit_STY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2772 {
2773    vassert(s390_host_has_ldisp);
2774 
2775    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2776       s390_disasm(ENC3(MNM, GPR, SDXB), "sty", r1, dh2, dl2, x2, b2);
2777 
2778    return emit_RXY(p, 0xe30000000050ULL, r1, x2, b2, dl2, dh2);
2779 }
2780 
2781 
2782 static UChar *
s390_emit_STG(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)2783 s390_emit_STG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2784 {
2785    vassert(s390_host_has_ldisp || dh2 == 0);
2786 
2787    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2788       s390_disasm(ENC3(MNM, GPR, SDXB), "stg", r1, dh2, dl2, x2, b2);
2789 
2790    return emit_RXY(p, 0xe30000000024ULL, r1, x2, b2, dl2, dh2);
2791 }
2792 
2793 
2794 static UChar *
s390_emit_STC(UChar * p,UChar r1,UChar x2,UChar b2,UShort d2)2795 s390_emit_STC(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2796 {
2797    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2798       s390_disasm(ENC3(MNM, GPR, UDXB), "stc", r1, d2, x2, b2);
2799 
2800    return emit_RX(p, 0x42000000, r1, x2, b2, d2);
2801 }
2802 
2803 
2804 static UChar *
s390_emit_STCY(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)2805 s390_emit_STCY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2806 {
2807    vassert(s390_host_has_ldisp);
2808 
2809    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2810       s390_disasm(ENC3(MNM, GPR, SDXB), "stcy", r1, dh2, dl2, x2, b2);
2811 
2812    return emit_RXY(p, 0xe30000000072ULL, r1, x2, b2, dl2, dh2);
2813 }
2814 
2815 
2816 static UChar *
s390_emit_STH(UChar * p,UChar r1,UChar x2,UChar b2,UShort d2)2817 s390_emit_STH(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2818 {
2819    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2820       s390_disasm(ENC3(MNM, GPR, UDXB), "sth", r1, d2, x2, b2);
2821 
2822    return emit_RX(p, 0x40000000, r1, x2, b2, d2);
2823 }
2824 
2825 
2826 static UChar *
s390_emit_STHY(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)2827 s390_emit_STHY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2828 {
2829    vassert(s390_host_has_ldisp);
2830 
2831    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2832       s390_disasm(ENC3(MNM, GPR, SDXB), "sthy", r1, dh2, dl2, x2, b2);
2833 
2834    return emit_RXY(p, 0xe30000000070ULL, r1, x2, b2, dl2, dh2);
2835 }
2836 
2837 
2838 static UChar *
s390_emit_SR(UChar * p,UChar r1,UChar r2)2839 s390_emit_SR(UChar *p, UChar r1, UChar r2)
2840 {
2841    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2842       s390_disasm(ENC3(MNM, GPR, GPR), "sr", r1, r2);
2843 
2844    return emit_RR(p, 0x1b00, r1, r2);
2845 }
2846 
2847 
2848 static UChar *
s390_emit_SGR(UChar * p,UChar r1,UChar r2)2849 s390_emit_SGR(UChar *p, UChar r1, UChar r2)
2850 {
2851    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2852       s390_disasm(ENC3(MNM, GPR, GPR), "sgr", r1, r2);
2853 
2854    return emit_RRE(p, 0xb9090000, r1, r2);
2855 }
2856 
2857 
2858 static UChar *
s390_emit_S(UChar * p,UChar r1,UChar x2,UChar b2,UShort d2)2859 s390_emit_S(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2860 {
2861    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2862       s390_disasm(ENC3(MNM, GPR, UDXB), "s", r1, d2, x2, b2);
2863 
2864    return emit_RX(p, 0x5b000000, r1, x2, b2, d2);
2865 }
2866 
2867 
2868 static UChar *
s390_emit_SY(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)2869 s390_emit_SY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2870 {
2871    vassert(s390_host_has_ldisp);
2872 
2873    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2874       s390_disasm(ENC3(MNM, GPR, SDXB), "sy", r1, dh2, dl2, x2, b2);
2875 
2876    return emit_RXY(p, 0xe3000000005bULL, r1, x2, b2, dl2, dh2);
2877 }
2878 
2879 
2880 static UChar *
s390_emit_SG(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)2881 s390_emit_SG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2882 {
2883    vassert(s390_host_has_ldisp || dh2 == 0);
2884 
2885    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2886       s390_disasm(ENC3(MNM, GPR, SDXB), "sg", r1, dh2, dl2, x2, b2);
2887 
2888    return emit_RXY(p, 0xe30000000009ULL, r1, x2, b2, dl2, dh2);
2889 }
2890 
2891 
2892 static UChar *
s390_emit_SH(UChar * p,UChar r1,UChar x2,UChar b2,UShort d2)2893 s390_emit_SH(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2894 {
2895    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2896       s390_disasm(ENC3(MNM, GPR, UDXB), "sh", r1, d2, x2, b2);
2897 
2898    return emit_RX(p, 0x4b000000, r1, x2, b2, d2);
2899 }
2900 
2901 
2902 static UChar *
s390_emit_SHY(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)2903 s390_emit_SHY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2904 {
2905    vassert(s390_host_has_ldisp);
2906 
2907    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2908       s390_disasm(ENC3(MNM, GPR, SDXB), "shy", r1, dh2, dl2, x2, b2);
2909 
2910    return emit_RXY(p, 0xe3000000007bULL, r1, x2, b2, dl2, dh2);
2911 }
2912 
2913 
2914 static UChar *
s390_emit_SLFI(UChar * p,UChar r1,UInt i2)2915 s390_emit_SLFI(UChar *p, UChar r1, UInt i2)
2916 {
2917    vassert(s390_host_has_eimm);
2918 
2919    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2920       s390_disasm(ENC3(MNM, GPR, UINT), "slfi", r1, i2);
2921 
2922    return emit_RIL(p, 0xc20500000000ULL, r1, i2);
2923 }
2924 
2925 
2926 static UChar *
s390_emit_SLGFI(UChar * p,UChar r1,UInt i2)2927 s390_emit_SLGFI(UChar *p, UChar r1, UInt i2)
2928 {
2929    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2930       s390_disasm(ENC3(MNM, GPR, UINT), "slgfi", r1, i2);
2931 
2932    return emit_RIL(p, 0xc20400000000ULL, r1, i2);
2933 }
2934 
2935 
2936 static UChar *
s390_emit_LDR(UChar * p,UChar r1,UChar r2)2937 s390_emit_LDR(UChar *p, UChar r1, UChar r2)
2938 {
2939    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2940       s390_disasm(ENC3(MNM, FPR, FPR), "ldr", r1, r2);
2941 
2942    return emit_RR(p, 0x2800, r1, r2);
2943 }
2944 
2945 
2946 static UChar *
s390_emit_LE(UChar * p,UChar r1,UChar x2,UChar b2,UShort d2)2947 s390_emit_LE(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2948 {
2949    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2950       s390_disasm(ENC3(MNM, FPR, UDXB), "le", r1, d2, x2, b2);
2951 
2952    return emit_RX(p, 0x78000000, r1, x2, b2, d2);
2953 }
2954 
2955 
2956 static UChar *
s390_emit_LD(UChar * p,UChar r1,UChar x2,UChar b2,UShort d2)2957 s390_emit_LD(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2958 {
2959    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2960       s390_disasm(ENC3(MNM, FPR, UDXB), "ld", r1, d2, x2, b2);
2961 
2962    return emit_RX(p, 0x68000000, r1, x2, b2, d2);
2963 }
2964 
2965 
2966 static UChar *
s390_emit_LEY(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)2967 s390_emit_LEY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2968 {
2969    vassert(s390_host_has_ldisp);
2970 
2971    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2972       s390_disasm(ENC3(MNM, FPR, SDXB), "ley", r1, dh2, dl2, x2, b2);
2973 
2974    return emit_RXY(p, 0xed0000000064ULL, r1, x2, b2, dl2, dh2);
2975 }
2976 
2977 
2978 static UChar *
s390_emit_LDY(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)2979 s390_emit_LDY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2980 {
2981    vassert(s390_host_has_ldisp);
2982 
2983    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2984       s390_disasm(ENC3(MNM, FPR, SDXB), "ldy", r1, dh2, dl2, x2, b2);
2985 
2986    return emit_RXY(p, 0xed0000000065ULL, r1, x2, b2, dl2, dh2);
2987 }
2988 
2989 
2990 static UChar *
s390_emit_LFPC(UChar * p,UChar b2,UShort d2)2991 s390_emit_LFPC(UChar *p, UChar b2, UShort d2)
2992 {
2993    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2994       s390_disasm(ENC2(MNM, UDXB), "lfpc", d2, 0, b2);
2995 
2996    return emit_S(p, 0xb29d0000, b2, d2);
2997 }
2998 
2999 
3000 static UChar *
s390_emit_LDGR(UChar * p,UChar r1,UChar r2)3001 s390_emit_LDGR(UChar *p, UChar r1, UChar r2)
3002 {
3003    vassert(s390_host_has_fgx);
3004 
3005    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3006       s390_disasm(ENC3(MNM, FPR, GPR), "ldgr", r1, r2);
3007 
3008    return emit_RRE(p, 0xb3c10000, r1, r2);
3009 }
3010 
3011 
3012 static UChar *
s390_emit_LGDR(UChar * p,UChar r1,UChar r2)3013 s390_emit_LGDR(UChar *p, UChar r1, UChar r2)
3014 {
3015    vassert(s390_host_has_fgx);
3016 
3017    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3018       s390_disasm(ENC3(MNM, GPR, FPR), "lgdr", r1, r2);
3019 
3020    return emit_RRE(p, 0xb3cd0000, r1, r2);
3021 }
3022 
3023 
3024 static UChar *
s390_emit_LZER(UChar * p,UChar r1,UChar r2)3025 s390_emit_LZER(UChar *p, UChar r1, UChar r2)
3026 {
3027    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3028       s390_disasm(ENC2(MNM, FPR), "lzer", r1);
3029 
3030    return emit_RRE(p, 0xb3740000, r1, r2);
3031 }
3032 
3033 
3034 static UChar *
s390_emit_LZDR(UChar * p,UChar r1,UChar r2)3035 s390_emit_LZDR(UChar *p, UChar r1, UChar r2)
3036 {
3037    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3038       s390_disasm(ENC2(MNM, FPR), "lzdr", r1);
3039 
3040    return emit_RRE(p, 0xb3750000, r1, r2);
3041 }
3042 
3043 
3044 static UChar *
s390_emit_SFPC(UChar * p,UChar r1,UChar r2)3045 s390_emit_SFPC(UChar *p, UChar r1, UChar r2)
3046 {
3047    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3048       s390_disasm(ENC2(MNM, GPR), "sfpc", r1);
3049 
3050    return emit_RRE(p, 0xb3840000, r1, r2);
3051 }
3052 
3053 
3054 static UChar *
s390_emit_STE(UChar * p,UChar r1,UChar x2,UChar b2,UShort d2)3055 s390_emit_STE(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
3056 {
3057    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3058       s390_disasm(ENC3(MNM, FPR, UDXB), "ste", r1, d2, x2, b2);
3059 
3060    return emit_RX(p, 0x70000000, r1, x2, b2, d2);
3061 }
3062 
3063 
3064 static UChar *
s390_emit_STD(UChar * p,UChar r1,UChar x2,UChar b2,UShort d2)3065 s390_emit_STD(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
3066 {
3067    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3068       s390_disasm(ENC3(MNM, FPR, UDXB), "std", r1, d2, x2, b2);
3069 
3070    return emit_RX(p, 0x60000000, r1, x2, b2, d2);
3071 }
3072 
3073 
3074 static UChar *
s390_emit_STEY(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)3075 s390_emit_STEY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3076 {
3077    vassert(s390_host_has_ldisp);
3078 
3079    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3080       s390_disasm(ENC3(MNM, FPR, SDXB), "stey", r1, dh2, dl2, x2, b2);
3081 
3082    return emit_RXY(p, 0xed0000000066ULL, r1, x2, b2, dl2, dh2);
3083 }
3084 
3085 
3086 static UChar *
s390_emit_STDY(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)3087 s390_emit_STDY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3088 {
3089    vassert(s390_host_has_ldisp);
3090 
3091    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3092       s390_disasm(ENC3(MNM, FPR, SDXB), "stdy", r1, dh2, dl2, x2, b2);
3093 
3094    return emit_RXY(p, 0xed0000000067ULL, r1, x2, b2, dl2, dh2);
3095 }
3096 
3097 
3098 static UChar *
s390_emit_STFPC(UChar * p,UChar b2,UShort d2)3099 s390_emit_STFPC(UChar *p, UChar b2, UShort d2)
3100 {
3101    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3102       s390_disasm(ENC2(MNM, UDXB), "stfpc", d2, 0, b2);
3103 
3104    return emit_S(p, 0xb29c0000, b2, d2);
3105 }
3106 
3107 
3108 static UChar *
s390_emit_AEBR(UChar * p,UChar r1,UChar r2)3109 s390_emit_AEBR(UChar *p, UChar r1, UChar r2)
3110 {
3111    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3112       s390_disasm(ENC3(MNM, FPR, FPR), "aebr", r1, r2);
3113 
3114    return emit_RRE(p, 0xb30a0000, r1, r2);
3115 }
3116 
3117 
3118 static UChar *
s390_emit_ADBR(UChar * p,UChar r1,UChar r2)3119 s390_emit_ADBR(UChar *p, UChar r1, UChar r2)
3120 {
3121    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3122       s390_disasm(ENC3(MNM, FPR, FPR), "adbr", r1, r2);
3123 
3124    return emit_RRE(p, 0xb31a0000, r1, r2);
3125 }
3126 
3127 
3128 static UChar *
s390_emit_AXBR(UChar * p,UChar r1,UChar r2)3129 s390_emit_AXBR(UChar *p, UChar r1, UChar r2)
3130 {
3131    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3132       s390_disasm(ENC3(MNM, FPR, FPR), "axbr", r1, r2);
3133 
3134    return emit_RRE(p, 0xb34a0000, r1, r2);
3135 }
3136 
3137 
3138 static UChar *
s390_emit_CEBR(UChar * p,UChar r1,UChar r2)3139 s390_emit_CEBR(UChar *p, UChar r1, UChar r2)
3140 {
3141    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3142       s390_disasm(ENC3(MNM, FPR, FPR), "cebr", r1, r2);
3143 
3144    return emit_RRE(p, 0xb3090000, r1, r2);
3145 }
3146 
3147 
3148 static UChar *
s390_emit_CDBR(UChar * p,UChar r1,UChar r2)3149 s390_emit_CDBR(UChar *p, UChar r1, UChar r2)
3150 {
3151    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3152       s390_disasm(ENC3(MNM, FPR, FPR), "cdbr", r1, r2);
3153 
3154    return emit_RRE(p, 0xb3190000, r1, r2);
3155 }
3156 
3157 
3158 static UChar *
s390_emit_CXBR(UChar * p,UChar r1,UChar r2)3159 s390_emit_CXBR(UChar *p, UChar r1, UChar r2)
3160 {
3161    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3162       s390_disasm(ENC3(MNM, FPR, FPR), "cxbr", r1, r2);
3163 
3164    return emit_RRE(p, 0xb3490000, r1, r2);
3165 }
3166 
3167 
3168 static UChar *
s390_emit_CEFBR(UChar * p,UChar r1,UChar r2)3169 s390_emit_CEFBR(UChar *p, UChar r1, UChar r2)
3170 {
3171    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3172       s390_disasm(ENC3(MNM, FPR, GPR), "cefbr", r1, r2);
3173 
3174    return emit_RRE(p, 0xb3940000, r1, r2);
3175 }
3176 
3177 
3178 static UChar *
s390_emit_CDFBR(UChar * p,UChar r1,UChar r2)3179 s390_emit_CDFBR(UChar *p, UChar r1, UChar r2)
3180 {
3181    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3182       s390_disasm(ENC3(MNM, FPR, GPR), "cdfbr", r1, r2);
3183 
3184    return emit_RRE(p, 0xb3950000, r1, r2);
3185 }
3186 
3187 
3188 static UChar *
s390_emit_CXFBR(UChar * p,UChar r1,UChar r2)3189 s390_emit_CXFBR(UChar *p, UChar r1, UChar r2)
3190 {
3191    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3192       s390_disasm(ENC3(MNM, FPR, GPR), "cxfbr", r1, r2);
3193 
3194    return emit_RRE(p, 0xb3960000, r1, r2);
3195 }
3196 
3197 
3198 static UChar *
s390_emit_CEGBR(UChar * p,UChar r1,UChar r2)3199 s390_emit_CEGBR(UChar *p, UChar r1, UChar r2)
3200 {
3201    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3202       s390_disasm(ENC3(MNM, FPR, GPR), "cegbr", r1, r2);
3203 
3204    return emit_RRE(p, 0xb3a40000, r1, r2);
3205 }
3206 
3207 
3208 static UChar *
s390_emit_CDGBR(UChar * p,UChar r1,UChar r2)3209 s390_emit_CDGBR(UChar *p, UChar r1, UChar r2)
3210 {
3211    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3212       s390_disasm(ENC3(MNM, FPR, GPR), "cdgbr", r1, r2);
3213 
3214    return emit_RRE(p, 0xb3a50000, r1, r2);
3215 }
3216 
3217 
3218 static UChar *
s390_emit_CXGBR(UChar * p,UChar r1,UChar r2)3219 s390_emit_CXGBR(UChar *p, UChar r1, UChar r2)
3220 {
3221    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3222       s390_disasm(ENC3(MNM, FPR, GPR), "cxgbr", r1, r2);
3223 
3224    return emit_RRE(p, 0xb3a60000, r1, r2);
3225 }
3226 
3227 
3228 static UChar *
s390_emit_CFEBR(UChar * p,UChar r3,UChar r1,UChar r2)3229 s390_emit_CFEBR(UChar *p, UChar r3, UChar r1, UChar r2)
3230 {
3231    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3232       s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cfebr", r1, r3, r2);
3233 
3234    return emit_RRF3(p, 0xb3980000, r3, r1, r2);
3235 }
3236 
3237 
3238 static UChar *
s390_emit_CFDBR(UChar * p,UChar r3,UChar r1,UChar r2)3239 s390_emit_CFDBR(UChar *p, UChar r3, UChar r1, UChar r2)
3240 {
3241    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3242       s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cfdbr", r1, r3, r2);
3243 
3244    return emit_RRF3(p, 0xb3990000, r3, r1, r2);
3245 }
3246 
3247 
3248 static UChar *
s390_emit_CFXBR(UChar * p,UChar r3,UChar r1,UChar r2)3249 s390_emit_CFXBR(UChar *p, UChar r3, UChar r1, UChar r2)
3250 {
3251    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3252       s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cfxbr", r1, r3, r2);
3253 
3254    return emit_RRF3(p, 0xb39a0000, r3, r1, r2);
3255 }
3256 
3257 
3258 static UChar *
s390_emit_CGEBR(UChar * p,UChar r3,UChar r1,UChar r2)3259 s390_emit_CGEBR(UChar *p, UChar r3, UChar r1, UChar r2)
3260 {
3261    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3262       s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cgebr", r1, r3, r2);
3263 
3264    return emit_RRF3(p, 0xb3a80000, r3, r1, r2);
3265 }
3266 
3267 
3268 static UChar *
s390_emit_CGDBR(UChar * p,UChar r3,UChar r1,UChar r2)3269 s390_emit_CGDBR(UChar *p, UChar r3, UChar r1, UChar r2)
3270 {
3271    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3272       s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cgdbr", r1, r3, r2);
3273 
3274    return emit_RRF3(p, 0xb3a90000, r3, r1, r2);
3275 }
3276 
3277 
3278 static UChar *
s390_emit_CGXBR(UChar * p,UChar r3,UChar r1,UChar r2)3279 s390_emit_CGXBR(UChar *p, UChar r3, UChar r1, UChar r2)
3280 {
3281    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3282       s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cgxbr", r1, r3, r2);
3283 
3284    return emit_RRF3(p, 0xb3aa0000, r3, r1, r2);
3285 }
3286 
3287 
3288 static UChar *
s390_emit_DEBR(UChar * p,UChar r1,UChar r2)3289 s390_emit_DEBR(UChar *p, UChar r1, UChar r2)
3290 {
3291    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3292       s390_disasm(ENC3(MNM, FPR, FPR), "debr", r1, r2);
3293 
3294    return emit_RRE(p, 0xb30d0000, r1, r2);
3295 }
3296 
3297 
3298 static UChar *
s390_emit_DDBR(UChar * p,UChar r1,UChar r2)3299 s390_emit_DDBR(UChar *p, UChar r1, UChar r2)
3300 {
3301    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3302       s390_disasm(ENC3(MNM, FPR, FPR), "ddbr", r1, r2);
3303 
3304    return emit_RRE(p, 0xb31d0000, r1, r2);
3305 }
3306 
3307 
3308 static UChar *
s390_emit_DXBR(UChar * p,UChar r1,UChar r2)3309 s390_emit_DXBR(UChar *p, UChar r1, UChar r2)
3310 {
3311    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3312       s390_disasm(ENC3(MNM, FPR, FPR), "dxbr", r1, r2);
3313 
3314    return emit_RRE(p, 0xb34d0000, r1, r2);
3315 }
3316 
3317 
3318 static UChar *
s390_emit_LCEBR(UChar * p,UChar r1,UChar r2)3319 s390_emit_LCEBR(UChar *p, UChar r1, UChar r2)
3320 {
3321    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3322       s390_disasm(ENC3(MNM, FPR, FPR), "lcebr", r1, r2);
3323 
3324    return emit_RRE(p, 0xb3030000, r1, r2);
3325 }
3326 
3327 
3328 static UChar *
s390_emit_LCDBR(UChar * p,UChar r1,UChar r2)3329 s390_emit_LCDBR(UChar *p, UChar r1, UChar r2)
3330 {
3331    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3332       s390_disasm(ENC3(MNM, FPR, FPR), "lcdbr", r1, r2);
3333 
3334    return emit_RRE(p, 0xb3130000, r1, r2);
3335 }
3336 
3337 
3338 static UChar *
s390_emit_LCXBR(UChar * p,UChar r1,UChar r2)3339 s390_emit_LCXBR(UChar *p, UChar r1, UChar r2)
3340 {
3341    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3342       s390_disasm(ENC3(MNM, FPR, FPR), "lcxbr", r1, r2);
3343 
3344    return emit_RRE(p, 0xb3430000, r1, r2);
3345 }
3346 
3347 
3348 static UChar *
s390_emit_LDEBR(UChar * p,UChar r1,UChar r2)3349 s390_emit_LDEBR(UChar *p, UChar r1, UChar r2)
3350 {
3351    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3352       s390_disasm(ENC3(MNM, FPR, FPR), "ldebr", r1, r2);
3353 
3354    return emit_RRE(p, 0xb3040000, r1, r2);
3355 }
3356 
3357 
3358 static UChar *
s390_emit_LXDBR(UChar * p,UChar r1,UChar r2)3359 s390_emit_LXDBR(UChar *p, UChar r1, UChar r2)
3360 {
3361    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3362       s390_disasm(ENC3(MNM, FPR, FPR), "lxdbr", r1, r2);
3363 
3364    return emit_RRE(p, 0xb3050000, r1, r2);
3365 }
3366 
3367 
3368 static UChar *
s390_emit_LXEBR(UChar * p,UChar r1,UChar r2)3369 s390_emit_LXEBR(UChar *p, UChar r1, UChar r2)
3370 {
3371    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3372       s390_disasm(ENC3(MNM, FPR, FPR), "lxebr", r1, r2);
3373 
3374    return emit_RRE(p, 0xb3060000, r1, r2);
3375 }
3376 
3377 
3378 static UChar *
s390_emit_LNEBR(UChar * p,UChar r1,UChar r2)3379 s390_emit_LNEBR(UChar *p, UChar r1, UChar r2)
3380 {
3381    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3382       s390_disasm(ENC3(MNM, FPR, FPR), "lnebr", r1, r2);
3383 
3384    return emit_RRE(p, 0xb3010000, r1, r2);
3385 }
3386 
3387 
3388 static UChar *
s390_emit_LNDBR(UChar * p,UChar r1,UChar r2)3389 s390_emit_LNDBR(UChar *p, UChar r1, UChar r2)
3390 {
3391    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3392       s390_disasm(ENC3(MNM, FPR, FPR), "lndbr", r1, r2);
3393 
3394    return emit_RRE(p, 0xb3110000, r1, r2);
3395 }
3396 
3397 
3398 static UChar *
s390_emit_LNXBR(UChar * p,UChar r1,UChar r2)3399 s390_emit_LNXBR(UChar *p, UChar r1, UChar r2)
3400 {
3401    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3402       s390_disasm(ENC3(MNM, FPR, FPR), "lnxbr", r1, r2);
3403 
3404    return emit_RRE(p, 0xb3410000, r1, r2);
3405 }
3406 
3407 
3408 static UChar *
s390_emit_LPEBR(UChar * p,UChar r1,UChar r2)3409 s390_emit_LPEBR(UChar *p, UChar r1, UChar r2)
3410 {
3411    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3412       s390_disasm(ENC3(MNM, FPR, FPR), "lpebr", r1, r2);
3413 
3414    return emit_RRE(p, 0xb3000000, r1, r2);
3415 }
3416 
3417 
3418 static UChar *
s390_emit_LPDBR(UChar * p,UChar r1,UChar r2)3419 s390_emit_LPDBR(UChar *p, UChar r1, UChar r2)
3420 {
3421    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3422       s390_disasm(ENC3(MNM, FPR, FPR), "lpdbr", r1, r2);
3423 
3424    return emit_RRE(p, 0xb3100000, r1, r2);
3425 }
3426 
3427 
3428 static UChar *
s390_emit_LPXBR(UChar * p,UChar r1,UChar r2)3429 s390_emit_LPXBR(UChar *p, UChar r1, UChar r2)
3430 {
3431    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3432       s390_disasm(ENC3(MNM, FPR, FPR), "lpxbr", r1, r2);
3433 
3434    return emit_RRE(p, 0xb3400000, r1, r2);
3435 }
3436 
3437 
3438 static UChar *
s390_emit_LEDBR(UChar * p,UChar r1,UChar r2)3439 s390_emit_LEDBR(UChar *p, UChar r1, UChar r2)
3440 {
3441    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3442       s390_disasm(ENC3(MNM, FPR, FPR), "ledbr", r1, r2);
3443 
3444    return emit_RRE(p, 0xb3440000, r1, r2);
3445 }
3446 
3447 
3448 static UChar *
s390_emit_LDXBR(UChar * p,UChar r1,UChar r2)3449 s390_emit_LDXBR(UChar *p, UChar r1, UChar r2)
3450 {
3451    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3452       s390_disasm(ENC3(MNM, FPR, FPR), "ldxbr", r1, r2);
3453 
3454    return emit_RRE(p, 0xb3450000, r1, r2);
3455 }
3456 
3457 
3458 static UChar *
s390_emit_LEXBR(UChar * p,UChar r1,UChar r2)3459 s390_emit_LEXBR(UChar *p, UChar r1, UChar r2)
3460 {
3461    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3462       s390_disasm(ENC3(MNM, FPR, FPR), "lexbr", r1, r2);
3463 
3464    return emit_RRE(p, 0xb3460000, r1, r2);
3465 }
3466 
3467 
3468 static UChar *
s390_emit_MEEBR(UChar * p,UChar r1,UChar r2)3469 s390_emit_MEEBR(UChar *p, UChar r1, UChar r2)
3470 {
3471    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3472       s390_disasm(ENC3(MNM, FPR, FPR), "meebr", r1, r2);
3473 
3474    return emit_RRE(p, 0xb3170000, r1, r2);
3475 }
3476 
3477 
3478 static UChar *
s390_emit_MDBR(UChar * p,UChar r1,UChar r2)3479 s390_emit_MDBR(UChar *p, UChar r1, UChar r2)
3480 {
3481    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3482       s390_disasm(ENC3(MNM, FPR, FPR), "mdbr", r1, r2);
3483 
3484    return emit_RRE(p, 0xb31c0000, r1, r2);
3485 }
3486 
3487 
3488 static UChar *
s390_emit_MXBR(UChar * p,UChar r1,UChar r2)3489 s390_emit_MXBR(UChar *p, UChar r1, UChar r2)
3490 {
3491    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3492       s390_disasm(ENC3(MNM, FPR, FPR), "mxbr", r1, r2);
3493 
3494    return emit_RRE(p, 0xb34c0000, r1, r2);
3495 }
3496 
3497 
3498 static UChar *
s390_emit_MAEBR(UChar * p,UChar r1,UChar r3,UChar r2)3499 s390_emit_MAEBR(UChar *p, UChar r1, UChar r3, UChar r2)
3500 {
3501    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3502       s390_disasm(ENC4(MNM, FPR, FPR, FPR), "maebr", r1, r3, r2);
3503 
3504    return emit_RRF(p, 0xb30e0000, r1, r3, r2);
3505 }
3506 
3507 
3508 static UChar *
s390_emit_MADBR(UChar * p,UChar r1,UChar r3,UChar r2)3509 s390_emit_MADBR(UChar *p, UChar r1, UChar r3, UChar r2)
3510 {
3511    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3512       s390_disasm(ENC4(MNM, FPR, FPR, FPR), "madbr", r1, r3, r2);
3513 
3514    return emit_RRF(p, 0xb31e0000, r1, r3, r2);
3515 }
3516 
3517 
3518 static UChar *
s390_emit_MSEBR(UChar * p,UChar r1,UChar r3,UChar r2)3519 s390_emit_MSEBR(UChar *p, UChar r1, UChar r3, UChar r2)
3520 {
3521    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3522       s390_disasm(ENC4(MNM, FPR, FPR, FPR), "msebr", r1, r3, r2);
3523 
3524    return emit_RRF(p, 0xb30f0000, r1, r3, r2);
3525 }
3526 
3527 
3528 static UChar *
s390_emit_MSDBR(UChar * p,UChar r1,UChar r3,UChar r2)3529 s390_emit_MSDBR(UChar *p, UChar r1, UChar r3, UChar r2)
3530 {
3531    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3532       s390_disasm(ENC4(MNM, FPR, FPR, FPR), "msdbr", r1, r3, r2);
3533 
3534    return emit_RRF(p, 0xb31f0000, r1, r3, r2);
3535 }
3536 
3537 
3538 static UChar *
s390_emit_SQEBR(UChar * p,UChar r1,UChar r2)3539 s390_emit_SQEBR(UChar *p, UChar r1, UChar r2)
3540 {
3541    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3542       s390_disasm(ENC3(MNM, FPR, FPR), "sqebr", r1, r2);
3543 
3544    return emit_RRE(p, 0xb3140000, r1, r2);
3545 }
3546 
3547 
3548 static UChar *
s390_emit_SQDBR(UChar * p,UChar r1,UChar r2)3549 s390_emit_SQDBR(UChar *p, UChar r1, UChar r2)
3550 {
3551    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3552       s390_disasm(ENC3(MNM, FPR, FPR), "sqdbr", r1, r2);
3553 
3554    return emit_RRE(p, 0xb3150000, r1, r2);
3555 }
3556 
3557 
3558 static UChar *
s390_emit_SQXBR(UChar * p,UChar r1,UChar r2)3559 s390_emit_SQXBR(UChar *p, UChar r1, UChar r2)
3560 {
3561    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3562       s390_disasm(ENC3(MNM, FPR, FPR), "sqxbr", r1, r2);
3563 
3564    return emit_RRE(p, 0xb3160000, r1, r2);
3565 }
3566 
3567 
3568 static UChar *
s390_emit_SEBR(UChar * p,UChar r1,UChar r2)3569 s390_emit_SEBR(UChar *p, UChar r1, UChar r2)
3570 {
3571    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3572       s390_disasm(ENC3(MNM, FPR, FPR), "sebr", r1, r2);
3573 
3574    return emit_RRE(p, 0xb30b0000, r1, r2);
3575 }
3576 
3577 
3578 static UChar *
s390_emit_SDBR(UChar * p,UChar r1,UChar r2)3579 s390_emit_SDBR(UChar *p, UChar r1, UChar r2)
3580 {
3581    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3582       s390_disasm(ENC3(MNM, FPR, FPR), "sdbr", r1, r2);
3583 
3584    return emit_RRE(p, 0xb31b0000, r1, r2);
3585 }
3586 
3587 
3588 static UChar *
s390_emit_SXBR(UChar * p,UChar r1,UChar r2)3589 s390_emit_SXBR(UChar *p, UChar r1, UChar r2)
3590 {
3591    if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3592       s390_disasm(ENC3(MNM, FPR, FPR), "sxbr", r1, r2);
3593 
3594    return emit_RRE(p, 0xb34b0000, r1, r2);
3595 }
3596 
3597 
3598 /* Provide a symbolic name for register "R0" */
3599 #define R0 0
3600 
3601 /* Split up a 20-bit displacement into its high and low piece
3602    suitable for passing as function arguments */
3603 #define DISP20(d) (((UInt)d) & 0xFFF), ((((UInt)d) >> 12) & 0xFF)
3604 
3605 /*---------------------------------------------------------------*/
3606 /*--- Helper functions                                        ---*/
3607 /*---------------------------------------------------------------*/
3608 
3609 static __inline__ Bool
uint_fits_signed_16bit(UInt val)3610 uint_fits_signed_16bit(UInt val)
3611 {
3612    int v = val & 0xFFFFu;
3613 
3614    /* sign extend */
3615    v = (v << 16) >> 16;
3616 
3617    return val == (UInt)v;
3618 }
3619 
3620 
3621 static __inline__ Bool
ulong_fits_signed_16bit(ULong val)3622 ulong_fits_signed_16bit(ULong val)
3623 {
3624    Long v = val & 0xFFFFu;
3625 
3626    /* sign extend */
3627    v = (v << 48) >> 48;
3628 
3629    return val == (ULong)v;
3630 }
3631 
3632 
3633 static __inline__ Bool
ulong_fits_signed_32bit(ULong val)3634 ulong_fits_signed_32bit(ULong val)
3635 {
3636    Long v = val & 0xFFFFFFFFu;
3637 
3638    /* sign extend */
3639    v = (v << 32) >> 32;
3640 
3641    return val == (ULong)v;
3642 }
3643 
3644 
3645 static __inline__ Bool
ulong_fits_unsigned_32bit(ULong val)3646 ulong_fits_unsigned_32bit(ULong val)
3647 {
3648    return (val & 0xFFFFFFFFu) == val;
3649 }
3650 
3651 
3652 /* Load a 64-bit immediate VAL into register REG. */
3653 static UChar *
s390_emit_load_64imm(UChar * p,UChar reg,ULong val)3654 s390_emit_load_64imm(UChar *p, UChar reg, ULong val)
3655 {
3656    if (ulong_fits_signed_16bit(val)) {
3657       return s390_emit_LGHI(p, reg, val);
3658    }
3659 
3660    if (s390_host_has_eimm) {
3661       if (ulong_fits_unsigned_32bit(val)) {
3662          return s390_emit_LLILF(p, reg, val);
3663       }
3664       if (ulong_fits_signed_32bit(val)) {
3665          /* LGFI's sign extension will recreate the correct 64-bit value */
3666          return s390_emit_LGFI(p, reg, val);
3667       }
3668       /* Do it in two steps: upper half [0:31] and lower half [32:63] */
3669       p =  s390_emit_IIHF(p, reg, val >> 32);
3670       return s390_emit_IILF(p, reg, val & 0xFFFFFFFF);
3671    }
3672 
3673    /* Fall back */
3674    if (ulong_fits_unsigned_32bit(val)) {
3675       p = s390_emit_LLILH(p, reg, (val >> 16) & 0xFFFF); /* sets val[32:47]
3676                                                             val[0:31] = 0 */
3677       p = s390_emit_IILL(p, reg, val & 0xFFFF);          /* sets val[48:63] */
3678       return p;
3679    }
3680 
3681    p = s390_emit_IIHH(p, reg, (val >> 48) & 0xFFFF);
3682    p = s390_emit_IIHL(p, reg, (val >> 32) & 0xFFFF);
3683    p = s390_emit_IILH(p, reg, (val >> 16) & 0xFFFF);
3684    p = s390_emit_IILL(p, reg, val & 0xFFFF);
3685 
3686    return p;
3687 }
3688 
3689 /* Load a 32-bit immediate VAL into register REG. */
3690 static UChar *
s390_emit_load_32imm(UChar * p,UChar reg,UInt val)3691 s390_emit_load_32imm(UChar *p, UChar reg, UInt val)
3692 {
3693    if (uint_fits_signed_16bit(val)) {
3694       /* LHI's sign extension will recreate the correct 32-bit value */
3695       return s390_emit_LHI(p, reg, val);
3696    }
3697    if (s390_host_has_eimm) {
3698       return s390_emit_IILF(p, reg, val);
3699    }
3700    /* val[0:15]  --> (val >> 16) & 0xFFFF
3701       val[16:31] --> val & 0xFFFF */
3702    p = s390_emit_IILH(p, reg, (val >> 16) & 0xFFFF);
3703    return s390_emit_IILL(p, reg, val & 0xFFFF);
3704 }
3705 
3706 /*------------------------------------------------------------*/
3707 /*--- Wrapper functions                                    ---*/
3708 /*------------------------------------------------------------*/
3709 
3710 /* r1[32:63],r1+1[32:63] = r1+1[32:63] * memory[op2addr][0:31] */
3711 static UChar *
s390_emit_MFYw(UChar * p,UChar r1,UChar x,UChar b,UShort dl,UChar dh)3712 s390_emit_MFYw(UChar *p, UChar r1, UChar x, UChar b,  UShort dl, UChar dh)
3713 {
3714    if (s390_host_has_gie) {
3715       return s390_emit_MFY(p, r1, x, b, dl, dh);
3716    }
3717 
3718    /* Load from memory into R0, then MULTIPLY with R1 */
3719    p = s390_emit_LY(p, R0, x, b, dl, dh);
3720    return s390_emit_MR(p, r1, R0);
3721 }
3722 
3723 /* r1[32:63] = r1[32:63] * memory[op2addr][0:15] */
3724 static UChar *
s390_emit_MHYw(UChar * p,UChar r1,UChar x,UChar b,UShort dl,UChar dh)3725 s390_emit_MHYw(UChar *p, UChar r1, UChar x, UChar b,  UShort dl, UChar dh)
3726 {
3727    if (s390_host_has_gie) {
3728       return s390_emit_MHY(p, r1, x, b, dl, dh);
3729    }
3730 
3731    /* Load from memory into R0, then MULTIPLY with R1 */
3732    p = s390_emit_LHY(p, R0, x, b, dl, dh);
3733    return s390_emit_MSR(p, r1, R0);
3734 }
3735 
3736 /* r1[32:63] = r1[32:63] * i2 */
3737 static UChar *
s390_emit_MSFIw(UChar * p,UChar r1,UInt i2)3738 s390_emit_MSFIw(UChar *p, UChar r1, UInt i2)
3739 {
3740    if (s390_host_has_gie) {
3741       return s390_emit_MSFI(p, r1, i2);
3742    }
3743 
3744    /* Load I2 into R0; then MULTIPLY R0 with R1 */
3745    p = s390_emit_load_32imm(p, R0, i2);
3746    return s390_emit_MSR(p, r1, R0);
3747 }
3748 
3749 
3750 /* r1[32:63] = r1[32:63] & i2 */
3751 static UChar *
s390_emit_NILFw(UChar * p,UChar r1,UInt i2)3752 s390_emit_NILFw(UChar *p, UChar r1, UInt i2)
3753 {
3754    if (s390_host_has_eimm) {
3755       return s390_emit_NILF(p, r1, i2);
3756    }
3757 
3758    /* Load I2 into R0; then AND R0 with R1 */
3759    p = s390_emit_load_32imm(p, R0, i2);
3760    return s390_emit_NR(p, r1, R0);
3761 }
3762 
3763 
3764 /* r1[32:63] = r1[32:63] | i2 */
3765 static UChar *
s390_emit_OILFw(UChar * p,UChar r1,UInt i2)3766 s390_emit_OILFw(UChar *p, UChar r1, UInt i2)
3767 {
3768    if (s390_host_has_eimm) {
3769       return s390_emit_OILF(p, r1, i2);
3770    }
3771 
3772    /* Load I2 into R0; then AND R0 with R1 */
3773    p = s390_emit_load_32imm(p, R0, i2);
3774    return s390_emit_OR(p, r1, R0);
3775 }
3776 
3777 
3778 /* r1[32:63] = r1[32:63] ^ i2 */
3779 static UChar *
s390_emit_XILFw(UChar * p,UChar r1,UInt i2)3780 s390_emit_XILFw(UChar *p, UChar r1, UInt i2)
3781 {
3782    if (s390_host_has_eimm) {
3783       return s390_emit_XILF(p, r1, i2);
3784    }
3785 
3786    /* Load I2 into R0; then AND R0 with R1 */
3787    p = s390_emit_load_32imm(p, R0, i2);
3788    return s390_emit_XR(p, r1, R0);
3789 }
3790 
3791 
3792 /* r1[32:63] = sign_extend(mem[op2addr][0:7]) */
3793 static UChar *
s390_emit_LBw(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)3794 s390_emit_LBw(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3795 {
3796    vassert(s390_host_has_ldisp || dh2 == 0);
3797 
3798    if (s390_host_has_ldisp) {
3799       return s390_emit_LB(p, r1, x2, b2, dl2, dh2);
3800    }
3801 
3802    p = s390_emit_IC(p, r1, x2, b2, dl2);    /* r1[56:63] = mem[op2addr][0:7] */
3803    p = s390_emit_SLL(p, r1, R0, 24);        /* r1 = r1 << 24  */
3804    return s390_emit_SRA(p, r1, R0, 24);     /* r1 = r1 >>a 24 */
3805 }
3806 
3807 
3808 /*  r1[32:63] = sign_extend(r2[56:63]) */
3809 static UChar *
s390_emit_LBRw(UChar * p,UChar r1,UChar r2)3810 s390_emit_LBRw(UChar *p, UChar r1, UChar r2)
3811 {
3812    if (s390_host_has_eimm) {
3813       return s390_emit_LBR(p, r1, r2);
3814    }
3815 
3816    p = s390_emit_LR(p, r1, r2);               /* r1 = r2 */
3817    p = s390_emit_SLL(p, r1, R0, 24);          /* r1 = r1 << 24  */
3818    return s390_emit_SRA(p, r1, R0, 24);       /* r1 = r1 >>a 24 */
3819 }
3820 
3821 
3822 /* r1[0:63] = sign_extend(mem[op2addr][0:7]) */
3823 static UChar *
s390_emit_LGBw(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)3824 s390_emit_LGBw(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3825 {
3826    vassert(s390_host_has_ldisp || dh2 == 0);
3827 
3828    if (s390_host_has_ldisp) {
3829       return s390_emit_LGB(p, r1, x2, b2, dl2, dh2);
3830    }
3831 
3832    p = s390_emit_IC(p, r1, x2, b2, dl2);             /* r1[56:63] = mem[op2addr][0:7] */
3833    p = s390_emit_SLLG(p, r1, r1, R0, DISP20(56));    /* r1 = r1 << 56  */
3834    return s390_emit_SRAG(p, r1, r1, R0, DISP20(56)); /* r1 = r1 >>a 56 */
3835 }
3836 
3837 
3838 /*  r1[0:63] = sign_extend(r2[56:63]) */
3839 static UChar *
s390_emit_LGBRw(UChar * p,UChar r1,UChar r2)3840 s390_emit_LGBRw(UChar *p, UChar r1, UChar r2)
3841 {
3842    if (s390_host_has_eimm) {
3843       return s390_emit_LGBR(p, r1, r2);
3844    }
3845 
3846    p = s390_emit_LR(p, r1, r2);                       /* r1 = r2 */
3847    p = s390_emit_SLLG(p, r1, r1, R0, DISP20(56));     /* r1 = r1 << 56  */
3848    return s390_emit_SRAG(p, r1, r1, R0, DISP20(56));  /* r1 = r1 >>a 56 */
3849 }
3850 
3851 
3852 /* r1[32:63] = sign_extend(r2[48:63]) */
3853 static UChar *
s390_emit_LHRw(UChar * p,UChar r1,UChar r2)3854 s390_emit_LHRw(UChar *p, UChar r1, UChar r2)
3855 {
3856    if (s390_host_has_eimm) {
3857       return s390_emit_LHR(p, r1, r2);
3858    }
3859 
3860    p = s390_emit_LR(p, r1, r2);               /* r1 = r2 */
3861    p = s390_emit_SLL(p, r1, R0, 16);          /* r1 = r1 << 16  */
3862    return s390_emit_SRA(p, r1, R0, 16);       /* r1 = r1 >>a 16 */
3863 }
3864 
3865 
3866 /* r1[0:63] = sign_extend(r2[48:63]) */
3867 static UChar *
s390_emit_LGHRw(UChar * p,UChar r1,UChar r2)3868 s390_emit_LGHRw(UChar *p, UChar r1, UChar r2)
3869 {
3870    if (s390_host_has_eimm) {
3871       return s390_emit_LGHR(p, r1, r2);
3872    }
3873 
3874    p = s390_emit_LR(p, r1, r2);               /* r1 = r2 */
3875    p = s390_emit_SLLG(p, r1, r1, R0, DISP20(48));     /* r1 = r1 << 48  */
3876    return s390_emit_SRAG(p, r1, r1, R0, DISP20(48));  /* r1 = r1 >>a 48 */
3877 }
3878 
3879 
3880 /* r1[0:63] = sign_extend(i2) */
3881 static UChar *
s390_emit_LGFIw(UChar * p,UChar r1,UInt i2)3882 s390_emit_LGFIw(UChar *p, UChar r1, UInt i2)
3883 {
3884    if (s390_host_has_eimm) {
3885       return s390_emit_LGFI(p, r1, i2);
3886    }
3887 
3888    p = s390_emit_load_32imm(p, R0, i2);
3889    return s390_emit_LGFR(p, r1, R0);
3890 }
3891 
3892 
3893 /* r1[32:63] = zero_extend($r2[56:63]) */
3894 static UChar *
s390_emit_LLCRw(UChar * p,UChar r1,UChar r2)3895 s390_emit_LLCRw(UChar *p, UChar r1, UChar r2)
3896 {
3897    if (s390_host_has_eimm) {
3898       return s390_emit_LLCR(p, r1, r2);
3899    }
3900 
3901    p = s390_emit_LR(p, r1, r2);
3902    p = s390_emit_LHI(p, R0, 0xFF);
3903    return s390_emit_NR(p, r1, R0);
3904 }
3905 
3906 
3907 /* r1[0:63] = zero_extend($r2[56:63]) */
3908 static UChar *
s390_emit_LLGCRw(UChar * p,UChar r1,UChar r2)3909 s390_emit_LLGCRw(UChar *p, UChar r1, UChar r2)
3910 {
3911    if (s390_host_has_eimm) {
3912       return s390_emit_LLGCR(p, r1, r2);
3913    }
3914 
3915    p = s390_emit_LR(p, r1, r2);
3916    p = s390_emit_LLILL(p, R0, 0xFF);
3917    return s390_emit_NGR(p, r1, R0);
3918 }
3919 
3920 
3921 /* r1[32:63] = zero_extend(r2[48:63]) */
3922 static UChar *
s390_emit_LLHRw(UChar * p,UChar r1,UChar r2)3923 s390_emit_LLHRw(UChar *p, UChar r1, UChar r2)
3924 {
3925    if (s390_host_has_eimm) {
3926       return s390_emit_LLHR(p, r1, r2);
3927    }
3928 
3929    p = s390_emit_LR(p, r1, r2);
3930    p = s390_emit_LLILL(p, R0, 0xFFFF);
3931    return s390_emit_NR(p, r1, R0);
3932 }
3933 
3934 
3935 /* r1[0:63] = zero_extend(r2[48:63]) */
3936 static UChar *
s390_emit_LLGHRw(UChar * p,UChar r1,UChar r2)3937 s390_emit_LLGHRw(UChar *p, UChar r1, UChar r2)
3938 {
3939    if (s390_host_has_eimm) {
3940       return s390_emit_LLGHR(p, r1, r2);
3941    }
3942 
3943    p = s390_emit_LR(p, r1, r2);
3944    p = s390_emit_LLILL(p, R0, 0xFFFF);
3945    return s390_emit_NGR(p, r1, R0);
3946 }
3947 
3948 
3949 /* r1[32:63] = zero_extend(mem[op2addr][0:7]) */
3950 static UChar *
s390_emit_LLCw(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl,UChar dh)3951 s390_emit_LLCw(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl, UChar dh)
3952 {
3953    if (s390_host_has_eimm) {
3954       return s390_emit_LLC(p, r1, x2, b2, dl, dh);
3955    }
3956 
3957    if (dh == 0) {
3958       p = s390_emit_IC(p, r1, x2, b2, dl);
3959    } else {
3960       p = s390_emit_ICY(p, r1, x2, b2, dl, dh);
3961    }
3962    p = s390_emit_LLILL(p, R0, 0xFF);
3963    return s390_emit_NR(p, r1, R0);
3964 }
3965 
3966 
3967 /* r1[32:63] = zero_extend(mem[op2addr][0:15]) */
3968 static UChar *
s390_emit_LLHw(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl,UChar dh)3969 s390_emit_LLHw(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl, UChar dh)
3970 {
3971    if (s390_host_has_eimm) {
3972       return s390_emit_LLH(p, r1, x2, b2, dl, dh);
3973    }
3974 
3975    p = s390_emit_LLGH(p, r1, x2, b2, dl, dh);
3976    p = s390_emit_LLILL(p, R0, 0xFFFF);
3977    return s390_emit_NR(p, r1, R0);
3978 }
3979 
3980 
3981 /* r1[0:63] = zero_extend(i2) */
3982 static UChar *
s390_emit_LLILFw(UChar * p,UChar r1,UInt i2)3983 s390_emit_LLILFw(UChar *p, UChar r1, UInt i2)
3984 {
3985    if (s390_host_has_eimm) {
3986       return s390_emit_LLILF(p, r1, i2);
3987    }
3988 
3989    p = s390_emit_LLILH(p, r1, (i2 >> 16) & 0xFFFF);  /* i2[0:15] */
3990    return s390_emit_OILL(p, r1, i2 & 0xFFFF);
3991 }
3992 
3993 
3994 /* r1[32:63] = r1[32:63] + i2 */
3995 static UChar *
s390_emit_AFIw(UChar * p,UChar r1,UInt i2)3996 s390_emit_AFIw(UChar *p, UChar r1, UInt i2)
3997 {
3998    if (s390_host_has_eimm) {
3999       return s390_emit_AFI(p, r1, i2);
4000    }
4001    /* Load 32 bit immediate to R0 then add */
4002    p = s390_emit_load_32imm(p, R0, i2);
4003    return s390_emit_AR(p, r1, R0);
4004 }
4005 
4006 
4007 /* r1[32:63] = r1[32:63] - i2 */
4008 static UChar *
s390_emit_SLFIw(UChar * p,UChar r1,UInt i2)4009 s390_emit_SLFIw(UChar *p, UChar r1, UInt i2)
4010 {
4011    if (s390_host_has_eimm) {
4012       return s390_emit_SLFI(p, r1, i2);
4013    }
4014 
4015    /* Load 32 bit immediate to R0 then subtract */
4016    p = s390_emit_load_32imm(p, R0, i2);
4017    return s390_emit_SR(p, r1, R0);
4018 }
4019 
4020 
4021 /* r1[0:63] = r1[0:63] - zero_extend(i2) */
4022 static UChar *
s390_emit_SLGFIw(UChar * p,UChar r1,UInt i2)4023 s390_emit_SLGFIw(UChar *p, UChar r1, UInt i2)
4024 {
4025    if (s390_host_has_eimm) {
4026       return s390_emit_SLGFI(p, r1, i2);
4027    }
4028 
4029    /* Load zero-extended 32 bit immediate to R0 then subtract */
4030    p = s390_emit_load_64imm(p, R0, i2);
4031    return s390_emit_SGR(p, r1, R0);
4032 }
4033 
4034 
4035 static UChar *
s390_emit_LTw(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl,UChar dh)4036 s390_emit_LTw(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl, UChar dh)
4037 {
4038    if (s390_host_has_eimm) {
4039       return s390_emit_LT(p, r1, x2, b2, dl, dh);
4040    }
4041    /* Load 32 bit from memory to R0 then compare */
4042    if (dh == 0) {
4043       p = s390_emit_L(p, R0, x2, b2, dl);
4044    } else {
4045       p = s390_emit_LY(p, R0, x2, b2, dl, dh);
4046    }
4047    return s390_emit_LTR(p, r1, R0);
4048 }
4049 
4050 
4051 static UChar *
s390_emit_LTGw(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl,UChar dh)4052 s390_emit_LTGw(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl, UChar dh)
4053 {
4054    if (s390_host_has_eimm) {
4055       return s390_emit_LTG(p, r1, x2, b2, dl, dh);
4056    }
4057    /* Load 64 bit from memory to R0 then compare */
4058    p = s390_emit_LG(p, R0, x2, b2, dl, dh);
4059    return s390_emit_LTGR(p, r1, R0);
4060 }
4061 
4062 
4063 static UChar *
s390_emit_CFIw(UChar * p,UChar r1,UInt i2)4064 s390_emit_CFIw(UChar *p, UChar r1, UInt i2)
4065 {
4066    if (s390_host_has_eimm) {
4067       return s390_emit_CFI(p, r1, i2);
4068    }
4069    /* Load 32 bit immediate to R0 then compare */
4070    p = s390_emit_load_32imm(p, R0, i2);
4071    return s390_emit_CR(p, r1, R0);
4072 }
4073 
4074 
4075 static UChar *
s390_emit_CLFIw(UChar * p,UChar r1,UInt i2)4076 s390_emit_CLFIw(UChar *p, UChar r1, UInt i2)
4077 {
4078    if (s390_host_has_eimm) {
4079       return s390_emit_CLFI(p, r1, i2);
4080    }
4081    /* Load 32 bit immediate to R0 then compare */
4082    p = s390_emit_load_32imm(p, R0, i2);
4083    return s390_emit_CLR(p, r1, R0);
4084 }
4085 
4086 
4087 static UChar *
s390_emit_LGDRw(UChar * p,UChar r1,UChar r2)4088 s390_emit_LGDRw(UChar *p, UChar r1, UChar r2)
4089 {
4090    if (s390_host_has_fgx) {
4091       return s390_emit_LGDR(p, r1, r2);
4092    }
4093 
4094    /* Store the FPR at memory[sp - 8]. This is safe because SP grows towards
4095       smaller addresses and is 8-byte aligned. Then load the GPR from that
4096       memory location/ */
4097    if (s390_host_has_ldisp) {
4098       p = s390_emit_STDY(p, r2, R0, S390_REGNO_STACK_POINTER, DISP20(-8));
4099       return s390_emit_LG(p, r1, R0, S390_REGNO_STACK_POINTER, DISP20(-8));
4100    }
4101 
4102    /* No long displacement. Need to adjust SP explicitly as to avoid negative
4103       displacements. */
4104    p = s390_emit_AGHI(p, S390_REGNO_STACK_POINTER, -8);
4105    p = s390_emit_STD(p, r2, R0, S390_REGNO_STACK_POINTER, 0);
4106    p = s390_emit_LG(p, r1, R0, S390_REGNO_STACK_POINTER, DISP20(0));
4107    return s390_emit_AGHI(p, S390_REGNO_STACK_POINTER, 8);
4108 }
4109 
4110 
4111 static UChar *
s390_emit_LDGRw(UChar * p,UChar r1,UChar r2)4112 s390_emit_LDGRw(UChar *p, UChar r1, UChar r2)
4113 {
4114    if (s390_host_has_fgx) {
4115       return s390_emit_LDGR(p, r1, r2);
4116    }
4117 
4118    /* Store the GPR at memory[sp - 8]. This is safe because SP grows towards
4119       smaller addresses and is 8-byte aligned. Then load the FPR from that
4120       memory location/ */
4121    if (s390_host_has_ldisp) {
4122       p = s390_emit_STG(p, r2, R0, S390_REGNO_STACK_POINTER, DISP20(-8));
4123       return s390_emit_LDY(p, r1, R0, S390_REGNO_STACK_POINTER, DISP20(-8));
4124    }
4125 
4126    /* No long displacement. Need to adjust SP explicitly as to avoid negative
4127       displacements. */
4128    p = s390_emit_AGHI(p, S390_REGNO_STACK_POINTER, -8);
4129    p = s390_emit_STG(p, r2, R0, S390_REGNO_STACK_POINTER, DISP20(0));
4130    p = s390_emit_LD(p, r1, R0, S390_REGNO_STACK_POINTER, 0);
4131    return s390_emit_AGHI(p, S390_REGNO_STACK_POINTER, 8);
4132 }
4133 
4134 
4135 /*---------------------------------------------------------------*/
4136 /*--- Constructors for the various s390_insn kinds            ---*/
4137 /*---------------------------------------------------------------*/
4138 
4139 s390_insn *
s390_insn_load(UChar size,HReg dst,s390_amode * src)4140 s390_insn_load(UChar size, HReg dst, s390_amode *src)
4141 {
4142    s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4143 
4144    insn->tag  = S390_INSN_LOAD;
4145    insn->size = size;
4146    insn->variant.load.src  = src;
4147    insn->variant.load.dst  = dst;
4148 
4149    vassert(size == 1 || size == 2 || size == 4 || size == 8);
4150 
4151    return insn;
4152 }
4153 
4154 
4155 s390_insn *
s390_insn_store(UChar size,s390_amode * dst,HReg src)4156 s390_insn_store(UChar size, s390_amode *dst, HReg src)
4157 {
4158    s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4159 
4160    insn->tag  = S390_INSN_STORE;
4161    insn->size = size;
4162    insn->variant.store.src  = src;
4163    insn->variant.store.dst  = dst;
4164 
4165    vassert(size == 1 || size == 2 || size == 4 || size == 8);
4166 
4167    return insn;
4168 }
4169 
4170 
4171 s390_insn *
s390_insn_move(UChar size,HReg dst,HReg src)4172 s390_insn_move(UChar size, HReg dst, HReg src)
4173 {
4174    s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4175 
4176    insn->tag  = S390_INSN_MOVE;
4177    insn->size = size;
4178    insn->variant.move.src  = src;
4179    insn->variant.move.dst  = dst;
4180 
4181    vassert(size == 1 || size == 2 || size == 4 || size == 8);
4182 
4183    return insn;
4184 }
4185 
4186 
4187 s390_insn *
s390_insn_cond_move(UChar size,s390_cc_t cond,HReg dst,s390_opnd_RMI src)4188 s390_insn_cond_move(UChar size, s390_cc_t cond, HReg dst, s390_opnd_RMI src)
4189 {
4190    s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4191 
4192    insn->tag  = S390_INSN_COND_MOVE;
4193    insn->size = size;
4194    insn->variant.cond_move.cond = cond;
4195    insn->variant.cond_move.src  = src;
4196    insn->variant.cond_move.dst  = dst;
4197 
4198    vassert(size == 1 || size == 2 || size == 4 || size == 8);
4199 
4200    return insn;
4201 }
4202 
4203 
4204 s390_insn *
s390_insn_load_immediate(UChar size,HReg dst,ULong value)4205 s390_insn_load_immediate(UChar size, HReg dst, ULong value)
4206 {
4207    s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4208 
4209    insn->tag  = S390_INSN_LOAD_IMMEDIATE;
4210    insn->size = size;
4211    insn->variant.load_immediate.dst   = dst;
4212    insn->variant.load_immediate.value = value;
4213 
4214    return insn;
4215 }
4216 
4217 
4218 s390_insn *
s390_insn_alu(UChar size,s390_alu_t tag,HReg dst,s390_opnd_RMI op2)4219 s390_insn_alu(UChar size, s390_alu_t tag, HReg dst, s390_opnd_RMI op2)
4220 {
4221    s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4222 
4223    insn->tag  = S390_INSN_ALU;
4224    insn->size = size;
4225    insn->variant.alu.tag = tag;
4226    insn->variant.alu.dst = dst;
4227    insn->variant.alu.op2 = op2;
4228 
4229    return insn;
4230 }
4231 
4232 
4233 s390_insn *
s390_insn_mul(UChar size,HReg dst_hi,HReg dst_lo,s390_opnd_RMI op2,Bool signed_multiply)4234 s390_insn_mul(UChar size, HReg dst_hi, HReg dst_lo, s390_opnd_RMI op2,
4235               Bool signed_multiply)
4236 {
4237    s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4238 
4239    vassert(! hregIsVirtual(dst_hi));
4240    vassert(! hregIsVirtual(dst_lo));
4241 
4242    insn->tag  = S390_INSN_MUL;
4243    insn->size = size;
4244    insn->variant.mul.dst_hi = dst_hi;
4245    insn->variant.mul.dst_lo = dst_lo;
4246    insn->variant.mul.op2 = op2;
4247    insn->variant.mul.signed_multiply = signed_multiply;
4248 
4249    return insn;
4250 }
4251 
4252 
4253 s390_insn *
s390_insn_div(UChar size,HReg op1_hi,HReg op1_lo,s390_opnd_RMI op2,Bool signed_divide)4254 s390_insn_div(UChar size, HReg op1_hi, HReg op1_lo, s390_opnd_RMI op2,
4255               Bool signed_divide)
4256 {
4257    s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4258 
4259    vassert(size == 4 || size == 8);
4260    vassert(! hregIsVirtual(op1_hi));
4261    vassert(! hregIsVirtual(op1_lo));
4262 
4263    insn->tag  = S390_INSN_DIV;
4264    insn->size = size;
4265    insn->variant.div.op1_hi = op1_hi;
4266    insn->variant.div.op1_lo = op1_lo;
4267    insn->variant.div.op2 = op2;
4268    insn->variant.div.signed_divide = signed_divide;
4269 
4270    return insn;
4271 }
4272 
4273 
4274 s390_insn *
s390_insn_divs(UChar size,HReg rem,HReg op1,s390_opnd_RMI op2)4275 s390_insn_divs(UChar size, HReg rem, HReg op1, s390_opnd_RMI op2)
4276 {
4277    s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4278 
4279    vassert(size == 8);
4280    vassert(! hregIsVirtual(op1));
4281    vassert(! hregIsVirtual(rem));
4282 
4283    insn->tag  = S390_INSN_DIVS;
4284    insn->size = size;
4285    insn->variant.divs.rem = rem;   /* remainder */
4286    insn->variant.divs.op1 = op1;   /* also quotient */
4287    insn->variant.divs.op2 = op2;
4288 
4289    return insn;
4290 }
4291 
4292 
4293 s390_insn *
s390_insn_clz(UChar size,HReg num_bits,HReg clobber,s390_opnd_RMI src)4294 s390_insn_clz(UChar size, HReg num_bits, HReg clobber, s390_opnd_RMI src)
4295 {
4296    s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4297 
4298    vassert(size == 8);
4299    vassert(! hregIsVirtual(num_bits));
4300    vassert(! hregIsVirtual(clobber));
4301 
4302    insn->tag  = S390_INSN_CLZ;
4303    insn->size = size;
4304    insn->variant.clz.num_bits = num_bits;
4305    insn->variant.clz.clobber  = clobber;
4306    insn->variant.clz.src = src;
4307 
4308    return insn;
4309 }
4310 
4311 
4312 s390_insn *
s390_insn_unop(UChar size,s390_unop_t tag,HReg dst,s390_opnd_RMI opnd)4313 s390_insn_unop(UChar size, s390_unop_t tag, HReg dst, s390_opnd_RMI opnd)
4314 {
4315    s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4316 
4317    insn->tag  = S390_INSN_UNOP;
4318    insn->size = size;
4319    insn->variant.unop.tag = tag;
4320    insn->variant.unop.dst = dst;
4321    insn->variant.unop.src = opnd;
4322 
4323    return insn;
4324 }
4325 
4326 
4327 s390_insn *
s390_insn_test(UChar size,s390_opnd_RMI src)4328 s390_insn_test(UChar size, s390_opnd_RMI src)
4329 {
4330    s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4331 
4332    vassert(size == 4 || size == 8);
4333 
4334    insn->tag  = S390_INSN_TEST;
4335    insn->size = size;
4336    insn->variant.test.src = src;
4337 
4338    return insn;
4339 }
4340 
4341 
4342 s390_insn *
s390_insn_cc2bool(HReg dst,s390_cc_t cond)4343 s390_insn_cc2bool(HReg dst, s390_cc_t cond)
4344 {
4345    s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4346 
4347    insn->tag  = S390_INSN_CC2BOOL;
4348    insn->size = 0;   /* does not matter */
4349    insn->variant.cc2bool.cond = cond;
4350    insn->variant.cc2bool.dst  = dst;
4351 
4352    return insn;
4353 }
4354 
4355 
4356 s390_insn *
s390_insn_cas(UChar size,HReg op1,s390_amode * op2,HReg op3,HReg old_mem)4357 s390_insn_cas(UChar size, HReg op1, s390_amode *op2, HReg op3, HReg old_mem)
4358 {
4359    s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4360 
4361    vassert(size == 4 || size == 8);
4362    vassert(op2->x == 0);
4363 
4364    insn->tag  = S390_INSN_CAS;
4365    insn->size = size;
4366    insn->variant.cas.op1 = op1;
4367    insn->variant.cas.op2 = op2;
4368    insn->variant.cas.op3 = op3;
4369    insn->variant.cas.old_mem = old_mem;
4370 
4371    return insn;
4372 }
4373 
4374 
4375 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)4376 s390_insn_cdas(UChar size, HReg op1_high, HReg op1_low, s390_amode *op2,
4377                HReg op3_high, HReg op3_low, HReg old_mem_high, HReg old_mem_low,
4378                HReg scratch)
4379 {
4380    s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4381 
4382    vassert(size == 4 || size == 8);
4383    vassert(op2->x == 0);
4384    vassert(hregNumber(scratch) == 1);  /* r0,r1 used as scratch reg pair */
4385 
4386    insn->tag  = S390_INSN_CDAS;
4387    insn->size = size;
4388    insn->variant.cdas.op1_high = op1_high;
4389    insn->variant.cdas.op1_low  = op1_low;
4390    insn->variant.cdas.op2 = op2;
4391    insn->variant.cdas.op3_high = op3_high;
4392    insn->variant.cdas.op3_low  = op3_low;
4393    insn->variant.cdas.old_mem_high = old_mem_high;
4394    insn->variant.cdas.old_mem_low  = old_mem_low;
4395    insn->variant.cdas.scratch = scratch;
4396 
4397    return insn;
4398 }
4399 
4400 
4401 s390_insn *
s390_insn_compare(UChar size,HReg src1,s390_opnd_RMI src2,Bool signed_comparison)4402 s390_insn_compare(UChar size, HReg src1, s390_opnd_RMI src2,
4403                   Bool signed_comparison)
4404 {
4405    s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4406 
4407    vassert(size == 4 || size == 8);
4408 
4409    insn->tag  = S390_INSN_COMPARE;
4410    insn->size = size;
4411    insn->variant.compare.src1 = src1;
4412    insn->variant.compare.src2 = src2;
4413    insn->variant.compare.signed_comparison = signed_comparison;
4414 
4415    return insn;
4416 }
4417 
4418 
4419 s390_insn *
s390_insn_helper_call(s390_cc_t cond,Addr64 target,UInt num_args,HChar * name,HReg dst)4420 s390_insn_helper_call(s390_cc_t cond, Addr64 target, UInt num_args,
4421                       HChar *name, HReg dst)
4422 {
4423    s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4424 
4425    insn->tag  = S390_INSN_HELPER_CALL;
4426    insn->size = 0;  /* does not matter */
4427    insn->variant.helper_call.cond = cond;
4428    insn->variant.helper_call.target = target;
4429    insn->variant.helper_call.num_args = num_args;
4430    insn->variant.helper_call.name = name;
4431    insn->variant.helper_call.dst = dst;
4432 
4433    return insn;
4434 }
4435 
4436 
4437 s390_insn *
s390_insn_bfp_triop(UChar size,s390_bfp_triop_t tag,HReg dst,HReg op2,HReg op3,s390_round_t rounding_mode)4438 s390_insn_bfp_triop(UChar size, s390_bfp_triop_t tag, HReg dst, HReg op2,
4439                     HReg op3, s390_round_t rounding_mode)
4440 {
4441    s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4442 
4443    insn->tag  = S390_INSN_BFP_TRIOP;
4444    insn->size = size;
4445    insn->variant.bfp_triop.tag = tag;
4446    insn->variant.bfp_triop.dst = dst;
4447    insn->variant.bfp_triop.op2 = op2;
4448    insn->variant.bfp_triop.op3 = op3;
4449    insn->variant.bfp_triop.rounding_mode = rounding_mode;
4450 
4451    return insn;
4452 }
4453 
4454 
4455 s390_insn *
s390_insn_bfp_binop(UChar size,s390_bfp_binop_t tag,HReg dst,HReg op2,s390_round_t rounding_mode)4456 s390_insn_bfp_binop(UChar size, s390_bfp_binop_t tag, HReg dst, HReg op2,
4457                     s390_round_t rounding_mode)
4458 {
4459    s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4460 
4461    insn->tag  = S390_INSN_BFP_BINOP;
4462    insn->size = size;
4463    insn->variant.bfp_binop.tag = tag;
4464    insn->variant.bfp_binop.dst = dst;
4465    insn->variant.bfp_binop.op2 = op2;
4466    insn->variant.bfp_binop.rounding_mode = rounding_mode;
4467 
4468    return insn;
4469 }
4470 
4471 
4472 s390_insn *
s390_insn_bfp_unop(UChar size,s390_bfp_unop_t tag,HReg dst,HReg op,s390_round_t rounding_mode)4473 s390_insn_bfp_unop(UChar size, s390_bfp_unop_t tag, HReg dst, HReg op,
4474                    s390_round_t rounding_mode)
4475 {
4476    s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4477 
4478    insn->tag  = S390_INSN_BFP_UNOP;
4479    insn->size = size;
4480    insn->variant.bfp_unop.tag = tag;
4481    insn->variant.bfp_unop.dst = dst;
4482    insn->variant.bfp_unop.op  = op;
4483    insn->variant.bfp_unop.rounding_mode = rounding_mode;
4484 
4485    return insn;
4486 }
4487 
4488 
4489 s390_insn *
s390_insn_bfp_compare(UChar size,HReg dst,HReg op1,HReg op2)4490 s390_insn_bfp_compare(UChar size, HReg dst, HReg op1, HReg op2)
4491 {
4492    s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4493 
4494    vassert(size == 4 || size == 8);
4495 
4496    insn->tag  = S390_INSN_BFP_COMPARE;
4497    insn->size = size;
4498    insn->variant.bfp_compare.dst = dst;
4499    insn->variant.bfp_compare.op1 = op1;
4500    insn->variant.bfp_compare.op2 = op2;
4501 
4502    return insn;
4503 }
4504 
4505 
4506 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,s390_round_t rounding_mode)4507 s390_insn_bfp128_binop(UChar size, s390_bfp_binop_t tag, HReg dst_hi,
4508                        HReg dst_lo, HReg op2_hi, HReg op2_lo,
4509                        s390_round_t rounding_mode)
4510 {
4511    s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4512 
4513    insn->tag  = S390_INSN_BFP128_BINOP;
4514    insn->size = size;
4515    insn->variant.bfp128_binop.tag = tag;
4516    insn->variant.bfp128_binop.dst_hi = dst_hi;
4517    insn->variant.bfp128_binop.dst_lo = dst_lo;
4518    insn->variant.bfp128_binop.op2_hi = op2_hi;
4519    insn->variant.bfp128_binop.op2_lo = op2_lo;
4520    insn->variant.bfp128_binop.rounding_mode = rounding_mode;
4521 
4522    return insn;
4523 }
4524 
4525 
4526 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,s390_round_t rounding_mode)4527 s390_insn_bfp128_unop(UChar size, s390_bfp_unop_t tag, HReg dst_hi,
4528                       HReg dst_lo, HReg op_hi, HReg op_lo,
4529                       s390_round_t rounding_mode)
4530 {
4531    s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4532 
4533    insn->tag  = S390_INSN_BFP128_UNOP;
4534    insn->size = size;
4535    insn->variant.bfp128_unop.tag = tag;
4536    insn->variant.bfp128_unop.dst_hi = dst_hi;
4537    insn->variant.bfp128_unop.dst_lo = dst_lo;
4538    insn->variant.bfp128_unop.op_hi = op_hi;
4539    insn->variant.bfp128_unop.op_lo = op_lo;
4540    insn->variant.bfp128_unop.rounding_mode = rounding_mode;
4541 
4542    return insn;
4543 }
4544 
4545 
4546 s390_insn *
s390_insn_bfp128_compare(UChar size,HReg dst,HReg op1_hi,HReg op1_lo,HReg op2_hi,HReg op2_lo)4547 s390_insn_bfp128_compare(UChar size, HReg dst, HReg op1_hi, HReg op1_lo,
4548                          HReg op2_hi, HReg op2_lo)
4549 {
4550    s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4551 
4552    insn->tag  = S390_INSN_BFP128_COMPARE;
4553    insn->size = size;
4554    insn->variant.bfp128_compare.dst = dst;
4555    insn->variant.bfp128_compare.op1_hi = op1_hi;
4556    insn->variant.bfp128_compare.op1_lo = op1_lo;
4557    insn->variant.bfp128_compare.op2_hi = op2_hi;
4558    insn->variant.bfp128_compare.op2_lo = op2_lo;
4559 
4560    return insn;
4561 }
4562 
4563 
4564 s390_insn *
s390_insn_bfp128_convert_to(UChar size,s390_bfp_unop_t tag,HReg dst_hi,HReg dst_lo,HReg op)4565 s390_insn_bfp128_convert_to(UChar size, s390_bfp_unop_t tag, HReg dst_hi,
4566                             HReg dst_lo, HReg op)
4567 {
4568    s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4569 
4570    insn->tag  = S390_INSN_BFP128_CONVERT_TO;
4571    insn->size = size;
4572    insn->variant.bfp128_unop.tag = tag;
4573    insn->variant.bfp128_unop.dst_hi = dst_hi;
4574    insn->variant.bfp128_unop.dst_lo = dst_lo;
4575    insn->variant.bfp128_unop.op_hi = op;
4576    insn->variant.bfp128_unop.op_lo = INVALID_HREG;  /* unused */
4577    insn->variant.bfp128_unop.rounding_mode = S390_ROUND_NEAREST_EVEN; /* unused */
4578 
4579    return insn;
4580 }
4581 
4582 
4583 s390_insn *
s390_insn_bfp128_convert_from(UChar size,s390_bfp_unop_t tag,HReg dst,HReg op_hi,HReg op_lo,s390_round_t rounding_mode)4584 s390_insn_bfp128_convert_from(UChar size, s390_bfp_unop_t tag, HReg dst,
4585                               HReg op_hi, HReg op_lo,
4586                               s390_round_t rounding_mode)
4587 {
4588    s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4589 
4590    insn->tag  = S390_INSN_BFP128_CONVERT_FROM;
4591    insn->size = size;
4592    insn->variant.bfp128_unop.tag = tag;
4593    insn->variant.bfp128_unop.dst_hi = dst;
4594    insn->variant.bfp128_unop.dst_lo = INVALID_HREG;  /* unused */
4595    insn->variant.bfp128_unop.op_hi = op_hi;
4596    insn->variant.bfp128_unop.op_lo = op_lo;
4597    insn->variant.bfp128_unop.rounding_mode = rounding_mode;
4598 
4599    return insn;
4600 }
4601 
4602 
4603 s390_insn *
s390_insn_mfence(void)4604 s390_insn_mfence(void)
4605 {
4606    s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4607 
4608    insn->tag  = S390_INSN_MFENCE;
4609    insn->size = 0;   /* not needed */
4610 
4611    return insn;
4612 }
4613 
4614 
4615 s390_insn *
s390_insn_gzero(UChar size,UInt offset)4616 s390_insn_gzero(UChar size, UInt offset)
4617 {
4618    s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4619 
4620    insn->tag  = S390_INSN_GZERO;
4621    insn->size = size;
4622    insn->variant.gzero.offset = offset;
4623 
4624    return insn;
4625 }
4626 
4627 
4628 s390_insn *
s390_insn_gadd(UChar size,UInt offset,UChar delta,ULong value)4629 s390_insn_gadd(UChar size, UInt offset, UChar delta, ULong value)
4630 {
4631    s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4632 
4633    insn->tag  = S390_INSN_GADD;
4634    insn->size = size;
4635    insn->variant.gadd.offset = offset;
4636    insn->variant.gadd.delta = delta;
4637    insn->variant.gadd.value = value;
4638 
4639    return insn;
4640 }
4641 
4642 
4643 s390_insn *
s390_insn_xdirect(s390_cc_t cond,Addr64 dst,s390_amode * guest_IA,Bool to_fast_entry)4644 s390_insn_xdirect(s390_cc_t cond, Addr64 dst, s390_amode *guest_IA,
4645                   Bool to_fast_entry)
4646 {
4647    s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4648 
4649    insn->tag  = S390_INSN_XDIRECT;
4650    insn->size = 0;   /* does not matter */
4651 
4652    insn->variant.xdirect.cond = cond;
4653    insn->variant.xdirect.dst = dst;
4654    insn->variant.xdirect.guest_IA = guest_IA;
4655    insn->variant.xdirect.to_fast_entry = to_fast_entry;
4656 
4657    return insn;
4658 }
4659 
4660 
4661 s390_insn *
s390_insn_xindir(s390_cc_t cond,HReg dst,s390_amode * guest_IA)4662 s390_insn_xindir(s390_cc_t cond, HReg dst, s390_amode *guest_IA)
4663 {
4664    s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4665 
4666    insn->tag  = S390_INSN_XINDIR;
4667    insn->size = 0;   /* does not matter */
4668 
4669    insn->variant.xindir.cond = cond;
4670    insn->variant.xindir.dst = dst;
4671    insn->variant.xindir.guest_IA = guest_IA;
4672 
4673    return insn;
4674 }
4675 
4676 
4677 s390_insn *
s390_insn_xassisted(s390_cc_t cond,HReg dst,s390_amode * guest_IA,IRJumpKind kind)4678 s390_insn_xassisted(s390_cc_t cond, HReg dst, s390_amode *guest_IA,
4679                     IRJumpKind kind)
4680 {
4681    s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4682 
4683    insn->tag  = S390_INSN_XASSISTED;
4684    insn->size = 0;   /* does not matter */
4685 
4686    insn->variant.xassisted.cond = cond;
4687    insn->variant.xassisted.dst = dst;
4688    insn->variant.xassisted.guest_IA = guest_IA;
4689    insn->variant.xassisted.kind = kind;
4690 
4691    return insn;
4692 }
4693 
4694 
4695 s390_insn *
s390_insn_evcheck(s390_amode * counter,s390_amode * fail_addr)4696 s390_insn_evcheck(s390_amode *counter, s390_amode *fail_addr)
4697 {
4698    s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4699 
4700    vassert(counter->tag   == S390_AMODE_B12);
4701    vassert(fail_addr->tag == S390_AMODE_B12);
4702 
4703    insn->tag  = S390_INSN_EVCHECK;
4704    insn->size = 0;   /* does not matter */
4705 
4706    insn->variant.evcheck.counter = counter;
4707    insn->variant.evcheck.fail_addr = fail_addr;
4708 
4709    return insn;
4710 }
4711 
4712 
4713 s390_insn *
s390_insn_profinc(void)4714 s390_insn_profinc(void)
4715 {
4716    s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4717 
4718    insn->tag  = S390_INSN_PROFINC;
4719    insn->size = 0;   /* does not matter */
4720 
4721    return insn;
4722 }
4723 
4724 
4725 /*---------------------------------------------------------------*/
4726 /*--- Debug print                                             ---*/
4727 /*---------------------------------------------------------------*/
4728 
4729 static const HChar *
s390_cc_as_string(s390_cc_t cc)4730 s390_cc_as_string(s390_cc_t cc)
4731 {
4732    switch (cc) {
4733    case S390_CC_NEVER:  return "never";
4734    case S390_CC_OVFL:   return "overflow";
4735    case S390_CC_H:      return "greater than";     /* A > B ; high */
4736    case S390_CC_NLE:    return "not low or equal";
4737    case S390_CC_L:      return "less than";        /* A < B ; low */
4738    case S390_CC_NHE:    return "not high or equal";
4739    case S390_CC_LH:     return "low or high";
4740    case S390_CC_NE:     return "not equal";        /* A != B ; not zero */
4741    case S390_CC_E:      return "equal";            /* A == B ; zero */
4742    case S390_CC_NLH:    return "not low or high";
4743    case S390_CC_HE:     return "greater or equal"; /* A >= B ; high or equal*/
4744    case S390_CC_NL:     return "not low";          /* not low */
4745    case S390_CC_LE:     return "less or equal";    /* A <= B ; low or equal */
4746    case S390_CC_NH:     return "not high";
4747    case S390_CC_NO:     return "not overflow";
4748    case S390_CC_ALWAYS: return "always";
4749    default:
4750       vpanic("s390_cc_as_string");
4751    }
4752 }
4753 
4754 
4755 static const HChar *
s390_jump_kind_as_string(IRJumpKind kind)4756 s390_jump_kind_as_string(IRJumpKind kind)
4757 {
4758    switch (kind) {
4759    case Ijk_Boring:      return "Boring";
4760    case Ijk_Call:        return "Call";
4761    case Ijk_Ret:         return "Return";
4762    case Ijk_ClientReq:   return "ClientReq";
4763    case Ijk_Yield:       return "Yield";
4764    case Ijk_EmWarn:      return "EmWarn";
4765    case Ijk_EmFail:      return "EmFail";
4766    case Ijk_NoDecode:    return "NoDecode";
4767    case Ijk_MapFail:     return "MapFail";
4768    case Ijk_TInval:      return "Invalidate";
4769    case Ijk_NoRedir:     return "NoRedir";
4770    case Ijk_SigTRAP:     return "SigTRAP";
4771    case Ijk_SigSEGV:     return "SigSEGV";
4772    case Ijk_SigBUS:      return "SigBUS";
4773    case Ijk_Sys_syscall: return "Sys_syscall";
4774    default:
4775       vpanic("s390_jump_kind_as_string");
4776    }
4777 }
4778 
4779 
4780 /* Helper function for writing out a V insn */
4781 static void
s390_sprintf(HChar * buf,HChar * fmt,...)4782 s390_sprintf(HChar *buf, HChar *fmt, ...)
4783 {
4784    HChar *p;
4785    ULong value;
4786    va_list args;
4787    va_start(args, fmt);
4788 
4789    p = buf;
4790    for ( ; *fmt; ++fmt) {
4791       Int c = *fmt;
4792 
4793       if (c != '%') {
4794          *p++ = c;
4795          continue;
4796       }
4797 
4798       c = *++fmt;  /* next char */
4799       switch (c) {
4800       case '%':
4801          *p++ = c;   /* %% */
4802          continue;
4803 
4804       case 's':     /* %s */
4805          p += vex_sprintf(p, "%s", va_arg(args, HChar *));
4806          continue;
4807 
4808       case 'M':     /* %M = mnemonic */
4809          p += vex_sprintf(p, "%-8s", va_arg(args, HChar *));
4810          continue;
4811 
4812       case 'R':     /* %R = register */
4813          p += vex_sprintf(p, "%s", s390_hreg_as_string(va_arg(args, HReg)));
4814          continue;
4815 
4816       case 'A':     /* %A = amode */
4817          p += vex_sprintf(p, "%s",
4818                           s390_amode_as_string(va_arg(args, s390_amode *)));
4819          continue;
4820 
4821       case 'G':     /* %G = guest state @ offset */
4822          p += vex_sprintf(p, "guest[%d]", va_arg(args, UInt));
4823          continue;
4824 
4825       case 'C':     /* %C = condition code */
4826          p += vex_sprintf(p, "%s", s390_cc_as_string(va_arg(args, s390_cc_t)));
4827          continue;
4828 
4829       case 'J':     /* &J = jump kind */
4830          p += vex_sprintf(p, "%s",
4831                           s390_jump_kind_as_string(va_arg(args, IRJumpKind)));
4832          continue;
4833 
4834       case 'L': {   /* %L = argument list in helper call*/
4835          UInt i, num_args;
4836 
4837          num_args = va_arg(args, UInt);
4838 
4839          for (i = 0; i < num_args; ++i) {
4840             if (i != 0) p += vex_sprintf(p, ", ");
4841             p += vex_sprintf(p, "r%d", s390_gprno_from_arg_index(i));
4842          }
4843          continue;
4844       }
4845 
4846       case 'O': {   /* %O = RMI operand */
4847          s390_opnd_RMI *op = va_arg(args, s390_opnd_RMI *);
4848 
4849          switch (op->tag) {
4850          case S390_OPND_REG:
4851             p += vex_sprintf(p, "%s", s390_hreg_as_string(op->variant.reg));
4852             continue;
4853 
4854          case S390_OPND_AMODE:
4855             p += vex_sprintf(p, "%s", s390_amode_as_string(op->variant.am));
4856             continue;
4857 
4858          case S390_OPND_IMMEDIATE:
4859             value = op->variant.imm;
4860             goto print_value;
4861 
4862          default:
4863             goto fail;
4864          }
4865       }
4866 
4867       case 'I':     /* %I = immediate value */
4868          value = va_arg(args, ULong);
4869          goto print_value;
4870 
4871       print_value:
4872          if ((Long)value < 0)
4873             p += vex_sprintf(p, "%lld", (Long)value);
4874          else if (value < 100)
4875             p += vex_sprintf(p, "%llu", value);
4876          else
4877             p += vex_sprintf(p, "0x%llx", value);
4878          continue;
4879 
4880       default:
4881          goto fail;
4882       }
4883    }
4884    *p = '\0';
4885    va_end(args);
4886 
4887    return;
4888 
4889  fail: vpanic("s390_printf");
4890 }
4891 
4892 
4893 /* Decompile the given insn into a static buffer and return it */
4894 const HChar *
s390_insn_as_string(const s390_insn * insn)4895 s390_insn_as_string(const s390_insn *insn)
4896 {
4897    static HChar buf[300];
4898    const HChar *op;
4899    HChar *p;
4900 
4901    buf[0] = '\0';
4902 
4903    switch (insn->tag) {
4904    case S390_INSN_LOAD:
4905       s390_sprintf(buf, "%M %R,%A", "v-load", insn->variant.load.dst,
4906                    insn->variant.load.src);
4907       break;
4908 
4909    case S390_INSN_STORE:
4910       s390_sprintf(buf, "%M %R,%A", "v-store", insn->variant.store.src,
4911                    insn->variant.store.dst);
4912       break;
4913 
4914    case S390_INSN_MOVE:
4915       s390_sprintf(buf, "%M %R,%R", "v-move", insn->variant.move.dst,
4916                    insn->variant.move.src);
4917       break;
4918 
4919    case S390_INSN_COND_MOVE:
4920       s390_sprintf(buf, "%M if (%C) %R,%O", "v-move",
4921                    insn->variant.cond_move.cond, insn->variant.cond_move.dst,
4922                    &insn->variant.cond_move.src);
4923       break;
4924 
4925    case S390_INSN_LOAD_IMMEDIATE:
4926       s390_sprintf(buf, "%M %R,%I", "v-loadi", insn->variant.load_immediate.dst,
4927                    insn->variant.load_immediate.value);
4928       break;
4929 
4930    case S390_INSN_ALU:
4931       switch (insn->variant.alu.tag) {
4932       case S390_ALU_ADD:  op = "v-add";  break;
4933       case S390_ALU_SUB:  op = "v-sub";  break;
4934       case S390_ALU_MUL:  op = "v-mul";  break;
4935       case S390_ALU_AND:  op = "v-and";  break;
4936       case S390_ALU_OR:   op = "v-or";   break;
4937       case S390_ALU_XOR:  op = "v-xor";  break;
4938       case S390_ALU_LSH:  op = "v-lsh";  break;
4939       case S390_ALU_RSH:  op = "v-rsh";  break;
4940       case S390_ALU_RSHA: op = "v-rsha"; break;
4941       default: goto fail;
4942       }
4943       s390_sprintf(buf, "%M %R,%O", op, insn->variant.alu.dst, /* also op1 */
4944                    &insn->variant.alu.op2);
4945       break;
4946 
4947    case S390_INSN_MUL:
4948       if (insn->variant.mul.signed_multiply) {
4949          op = "v-muls";
4950       } else {
4951          op = "v-mulu";
4952       }
4953       s390_sprintf(buf, "%M %R,%O", op, insn->variant.mul.dst_hi,
4954                    &insn->variant.mul.op2);
4955       break;
4956 
4957    case S390_INSN_DIV:
4958       if (insn->variant.div.signed_divide) {
4959          op = "v-divs";
4960       } else {
4961          op = "v-divu";
4962       }
4963       s390_sprintf(buf, "%M %R,%O", op, insn->variant.div.op1_hi,
4964                    &insn->variant.div.op2);
4965       break;
4966 
4967    case S390_INSN_DIVS:
4968       s390_sprintf(buf, "%M %R,%O", "v-divsi", insn->variant.divs.op1,
4969                    &insn->variant.divs.op2);
4970       break;
4971 
4972    case S390_INSN_CLZ:
4973       s390_sprintf(buf, "%M %R,%O", "v-clz", insn->variant.clz.num_bits,
4974                    &insn->variant.clz.src);
4975       break;
4976 
4977    case S390_INSN_UNOP:
4978       switch (insn->variant.unop.tag) {
4979       case S390_ZERO_EXTEND_8:
4980       case S390_ZERO_EXTEND_16:
4981       case S390_ZERO_EXTEND_32:
4982          op = "v-zerox";
4983          break;
4984 
4985       case S390_SIGN_EXTEND_8:
4986       case S390_SIGN_EXTEND_16:
4987       case S390_SIGN_EXTEND_32:
4988          op = "v-signx";
4989          break;
4990 
4991       case S390_NEGATE:
4992          op = "v-neg";
4993          break;
4994 
4995       default:
4996          goto fail;
4997       }
4998       s390_sprintf(buf, "%M %R,%O", op, insn->variant.unop.dst,
4999                    &insn->variant.unop.src);
5000       break;
5001 
5002    case S390_INSN_TEST:
5003       s390_sprintf(buf, "%M %O", "v-test", &insn->variant.test.src);
5004       break;
5005 
5006    case S390_INSN_CC2BOOL:
5007       s390_sprintf(buf, "%M %R,%C", "v-cc2b", insn->variant.cc2bool.dst,
5008                    insn->variant.cc2bool.cond);
5009       break;
5010 
5011    case S390_INSN_CAS:
5012       s390_sprintf(buf, "%M %R,%A,%R,%R", "v-cas", insn->variant.cas.op1,
5013                    insn->variant.cas.op2, insn->variant.cas.op3,
5014                    insn->variant.cas.old_mem);
5015       break;
5016 
5017    case S390_INSN_CDAS:
5018       s390_sprintf(buf, "%M %R,%R,%A,%R,%R,%R,%R", "v-cdas",
5019                    insn->variant.cdas.op1_high, insn->variant.cdas.op1_low,
5020                    insn->variant.cdas.op2, insn->variant.cdas.op3_high,
5021                    insn->variant.cdas.op3_low, insn->variant.cdas.old_mem_high,
5022                    insn->variant.cdas.old_mem_low);
5023       break;
5024 
5025    case S390_INSN_COMPARE:
5026       if (insn->variant.compare.signed_comparison) {
5027          op = "v-cmps";
5028       } else {
5029          op = "v-cmpu";
5030       }
5031       s390_sprintf(buf, "%M %R,%O", op, insn->variant.compare.src1,
5032                    &insn->variant.compare.src2);
5033       break;
5034 
5035    case S390_INSN_HELPER_CALL: {
5036       if (insn->variant.helper_call.dst != INVALID_HREG) {
5037          s390_sprintf(buf, "%M if (%C) %R = %s{%I}(%L)", "v-call",
5038                       insn->variant.helper_call.cond,
5039                       insn->variant.helper_call.dst,
5040                       insn->variant.helper_call.name,
5041                       insn->variant.helper_call.target,
5042                       insn->variant.helper_call.num_args);
5043       } else {
5044          s390_sprintf(buf, "%M if (%C) %s{%I}(%L)", "v-call",
5045                       insn->variant.helper_call.cond,
5046                       insn->variant.helper_call.name,
5047                       insn->variant.helper_call.target,
5048                       insn->variant.helper_call.num_args);
5049       }
5050       return buf;   /* avoid printing "size = ..." which is meaningless */
5051    }
5052 
5053    case S390_INSN_BFP_TRIOP:
5054       switch (insn->variant.bfp_triop.tag) {
5055       case S390_BFP_MADD:  op = "v-fmadd";  break;
5056       case S390_BFP_MSUB:  op = "v-fmsub";  break;
5057       default: goto fail;
5058       }
5059       s390_sprintf(buf, "%M %R,%R,%R", op,
5060                    insn->variant.bfp_triop.dst  /* op1 same as dst */,
5061                    insn->variant.bfp_triop.op2, insn->variant.bfp_triop.op3);
5062       break;
5063 
5064    case S390_INSN_BFP_BINOP:
5065       switch (insn->variant.bfp_binop.tag) {
5066       case S390_BFP_ADD:      op = "v-fadd";  break;
5067       case S390_BFP_SUB:      op = "v-fsub";  break;
5068       case S390_BFP_MUL:      op = "v-fmul";  break;
5069       case S390_BFP_DIV:      op = "v-fdiv";  break;
5070       default: goto fail;
5071       }
5072       s390_sprintf(buf, "%M %R,%R", op,
5073                    insn->variant.bfp_binop.dst  /* op1 same as dst */,
5074                    insn->variant.bfp_binop.op2);
5075       break;
5076 
5077    case S390_INSN_BFP_COMPARE:
5078       s390_sprintf(buf, "%M %R,%R,%R", "v-fcmp", insn->variant.bfp_compare.dst,
5079                    insn->variant.bfp_compare.op1, insn->variant.bfp_compare.op2);
5080       break;
5081 
5082    case S390_INSN_BFP_UNOP:
5083       switch (insn->variant.bfp_unop.tag) {
5084       case S390_BFP_ABS:         op = "v-fabs";  break;
5085       case S390_BFP_NABS:        op = "v-fnabs"; break;
5086       case S390_BFP_NEG:         op = "v-fneg";  break;
5087       case S390_BFP_SQRT:        op = "v-fsqrt"; break;
5088       case S390_BFP_I32_TO_F32:
5089       case S390_BFP_I32_TO_F64:
5090       case S390_BFP_I32_TO_F128:
5091       case S390_BFP_I64_TO_F32:
5092       case S390_BFP_I64_TO_F64:
5093       case S390_BFP_I64_TO_F128: op = "v-i2f"; break;
5094       case S390_BFP_F32_TO_I32:
5095       case S390_BFP_F32_TO_I64:
5096       case S390_BFP_F64_TO_I32:
5097       case S390_BFP_F64_TO_I64:
5098       case S390_BFP_F128_TO_I32:
5099       case S390_BFP_F128_TO_I64: op = "v-f2i"; break;
5100       case S390_BFP_F32_TO_F64:
5101       case S390_BFP_F32_TO_F128:
5102       case S390_BFP_F64_TO_F32:
5103       case S390_BFP_F64_TO_F128:
5104       case S390_BFP_F128_TO_F32:
5105       case S390_BFP_F128_TO_F64: op = "v-f2f"; break;
5106       default: goto fail;
5107       }
5108       s390_sprintf(buf, "%M %R,%R", op, insn->variant.bfp_unop.dst,
5109                    insn->variant.bfp_unop.op);
5110       break;
5111 
5112    case S390_INSN_BFP128_BINOP:
5113       switch (insn->variant.bfp128_binop.tag) {
5114       case S390_BFP_ADD:      op = "v-fadd";  break;
5115       case S390_BFP_SUB:      op = "v-fsub";  break;
5116       case S390_BFP_MUL:      op = "v-fmul";  break;
5117       case S390_BFP_DIV:      op = "v-fdiv";  break;
5118       default: goto fail;
5119       }
5120       /* Only write the register that identifies the register pair */
5121       s390_sprintf(buf, "%M %R,%R", op,
5122                    insn->variant.bfp128_binop.dst_hi  /* op1 same as dst */,
5123                    insn->variant.bfp128_binop.op2_hi);
5124       break;
5125 
5126    case S390_INSN_BFP128_COMPARE:
5127       /* Only write the register that identifies the register pair */
5128       s390_sprintf(buf, "%M %R,%R,%R", "v-fcmp", insn->variant.bfp128_compare.dst,
5129                    insn->variant.bfp128_compare.op1_hi,
5130                    insn->variant.bfp128_compare.op2_hi);
5131       break;
5132 
5133    case S390_INSN_BFP128_UNOP:
5134    case S390_INSN_BFP128_CONVERT_TO:
5135    case S390_INSN_BFP128_CONVERT_FROM:
5136       switch (insn->variant.bfp128_unop.tag) {
5137       case S390_BFP_ABS:         op = "v-fabs";  break;
5138       case S390_BFP_NABS:        op = "v-fnabs"; break;
5139       case S390_BFP_NEG:         op = "v-fneg";  break;
5140       case S390_BFP_SQRT:        op = "v-fsqrt"; break;
5141       case S390_BFP_I32_TO_F128:
5142       case S390_BFP_I64_TO_F128: op = "v-i2f";   break;
5143       case S390_BFP_F128_TO_I32:
5144       case S390_BFP_F128_TO_I64: op = "v-f2i";   break;
5145       case S390_BFP_F32_TO_F128:
5146       case S390_BFP_F64_TO_F128:
5147       case S390_BFP_F128_TO_F32:
5148       case S390_BFP_F128_TO_F64: op = "v-f2f";   break;
5149       default: goto fail;
5150       }
5151       /* Only write the register that identifies the register pair */
5152       s390_sprintf(buf, "%M %R,%R", op, insn->variant.bfp128_unop.dst_hi,
5153                    insn->variant.bfp128_unop.op_hi);
5154       break;
5155 
5156    case S390_INSN_MFENCE:
5157       s390_sprintf(buf, "%M", "v-mfence");
5158       return buf;   /* avoid printing "size = ..." which is meaningless */
5159 
5160    case S390_INSN_GZERO:
5161       s390_sprintf(buf, "%M %G", "v-gzero", insn->variant.gzero.offset);
5162       break;
5163 
5164    case S390_INSN_GADD:
5165       s390_sprintf(buf, "%M %G += %I  (= %I)", "v-gadd",
5166                    insn->variant.gadd.offset,
5167                    (Long)(Char)insn->variant.gadd.delta,
5168                    insn->variant.gadd.value);
5169       break;
5170 
5171    case S390_INSN_EVCHECK:
5172       s390_sprintf(buf, "%M counter = %A, fail-addr = %A", "v-evcheck",
5173                    insn->variant.evcheck.counter,
5174                    insn->variant.evcheck.fail_addr);
5175       return buf;   /* avoid printing "size = ..." which is meaningless */
5176 
5177    case S390_INSN_PROFINC:
5178       s390_sprintf(buf, "%M", "v-profinc");
5179       return buf;   /* avoid printing "size = ..." which is meaningless */
5180 
5181    case S390_INSN_XDIRECT:
5182       s390_sprintf(buf, "%M if (%C) %A = %I  %s", "v-xdirect",
5183                    insn->variant.xdirect.cond,
5184                    insn->variant.xdirect.guest_IA,
5185                    insn->variant.xdirect.dst,
5186                    insn->variant.xdirect.to_fast_entry ? "fast" : "slow");
5187       return buf;   /* avoid printing "size = ..." which is meaningless */
5188 
5189    case S390_INSN_XINDIR:
5190       s390_sprintf(buf, "%M if (%C) %A = %R", "v-xindir",
5191                    insn->variant.xindir.cond,
5192                    insn->variant.xindir.guest_IA,
5193                    insn->variant.xindir.dst);
5194       return buf;   /* avoid printing "size = ..." which is meaningless */
5195 
5196    case S390_INSN_XASSISTED:
5197       s390_sprintf(buf, "%M if (%C) %J %A = %R", "v-xassisted",
5198                    insn->variant.xassisted.cond,
5199                    insn->variant.xassisted.kind,
5200                    insn->variant.xassisted.guest_IA,
5201                    insn->variant.xassisted.dst);
5202       return buf;   /* avoid printing "size = ..." which is meaningless */
5203 
5204    default: goto fail;
5205    }
5206 
5207    /* Write out how many bytes are involved in the operation */
5208 
5209    {
5210       UInt len, i;
5211 
5212       for (p = buf; *p; ++p)
5213          continue;
5214 
5215       len = p - buf;
5216 
5217       if (len < 32) {
5218          for (i = len; i < 32; ++i)
5219             p += vex_sprintf(p, " ");
5220       } else {
5221          p += vex_sprintf(p, "\t");
5222       }
5223    }
5224 
5225    /* Special cases first */
5226    switch (insn->tag) {
5227    case S390_INSN_UNOP:
5228       switch (insn->variant.unop.tag) {
5229       case S390_SIGN_EXTEND_8:
5230       case S390_ZERO_EXTEND_8:  p += vex_sprintf(p, "1 -> "); goto common;
5231       case S390_SIGN_EXTEND_16:
5232       case S390_ZERO_EXTEND_16: p += vex_sprintf(p, "2 -> "); goto common;
5233       case S390_SIGN_EXTEND_32:
5234       case S390_ZERO_EXTEND_32: p += vex_sprintf(p, "4 -> "); goto common;
5235       default:
5236          goto common;
5237       }
5238 
5239    case S390_INSN_BFP_UNOP:
5240       switch (insn->variant.bfp_unop.tag) {
5241       case S390_BFP_I32_TO_F32:
5242       case S390_BFP_I32_TO_F64:
5243       case S390_BFP_I32_TO_F128:
5244       case S390_BFP_F32_TO_I32:
5245       case S390_BFP_F32_TO_I64:
5246       case S390_BFP_F32_TO_F64:
5247       case S390_BFP_F32_TO_F128: p += vex_sprintf(p, "4 -> "); goto common;
5248       case S390_BFP_I64_TO_F32:
5249       case S390_BFP_I64_TO_F64:
5250       case S390_BFP_I64_TO_F128:
5251       case S390_BFP_F64_TO_I32:
5252       case S390_BFP_F64_TO_I64:
5253       case S390_BFP_F64_TO_F32:
5254       case S390_BFP_F64_TO_F128: p += vex_sprintf(p, "8 -> "); goto common;
5255       case S390_BFP_F128_TO_I32:
5256       case S390_BFP_F128_TO_I64:
5257       case S390_BFP_F128_TO_F32:
5258       case S390_BFP_F128_TO_F64: p += vex_sprintf(p, "16 -> "); goto common;
5259       default:
5260          goto common;
5261       }
5262 
5263    case S390_INSN_BFP128_UNOP:
5264    case S390_INSN_BFP128_CONVERT_TO:
5265    case S390_INSN_BFP128_CONVERT_FROM:
5266       switch (insn->variant.bfp128_unop.tag) {
5267       case S390_BFP_I32_TO_F128:
5268       case S390_BFP_F32_TO_F128: p += vex_sprintf(p, "4 -> "); goto common;
5269       case S390_BFP_I64_TO_F128:
5270       case S390_BFP_F64_TO_F128: p += vex_sprintf(p, "8 -> "); goto common;
5271       case S390_BFP_F128_TO_I32:
5272       case S390_BFP_F128_TO_I64:
5273       case S390_BFP_F128_TO_F32:
5274       case S390_BFP_F128_TO_F64: p += vex_sprintf(p, "16 -> "); goto common;
5275       default:
5276          goto common;
5277       }
5278 
5279    default:
5280       goto common;
5281    }
5282 
5283    /* Common case */
5284  common:
5285    vex_sprintf(p, "%u bytes", (UInt)insn->size);
5286 
5287    return buf;
5288 
5289  fail: vpanic("s390_insn_as_string");
5290 }
5291 
5292 
5293 
5294 /* Load NUM bytes from memory into register REG using addressing mode AM. */
5295 static UChar *
s390_emit_load_mem(UChar * p,UInt num,UChar reg,const s390_amode * am)5296 s390_emit_load_mem(UChar *p, UInt num, UChar reg, const s390_amode *am)
5297 {
5298    UInt b = hregNumber(am->b);
5299    UInt x = hregNumber(am->x);  /* 0 for B12 and B20 */
5300    UInt d = am->d;
5301 
5302    switch (am->tag) {
5303    case S390_AMODE_B12:
5304    case S390_AMODE_BX12:
5305       switch (num) {
5306       case 1: return s390_emit_IC(p, reg, x, b, d);
5307       case 2: return s390_emit_LH(p, reg, x, b, d);
5308       case 4: return s390_emit_L(p, reg, x, b, d);
5309       case 8: return s390_emit_LG(p, reg, x, b, DISP20(d));
5310       default: goto fail;
5311       }
5312       break;
5313 
5314    case S390_AMODE_B20:
5315    case S390_AMODE_BX20:
5316       switch (num) {
5317       case 1: return s390_emit_ICY(p, reg, x, b, DISP20(d));
5318       case 2: return s390_emit_LHY(p, reg, x, b, DISP20(d));
5319       case 4: return s390_emit_LY(p, reg, x, b, DISP20(d));
5320       case 8: return s390_emit_LG(p, reg, x, b, DISP20(d));
5321       default: goto fail;
5322       }
5323       break;
5324 
5325    default: goto fail;
5326    }
5327 
5328  fail:
5329    vpanic("s390_emit_load_mem");
5330 }
5331 
5332 
5333 /* Load condition code into register REG */
5334 static UChar *
s390_emit_load_cc(UChar * p,UChar reg)5335 s390_emit_load_cc(UChar *p, UChar reg)
5336 {
5337    p = s390_emit_LGHI(p, reg, 0);  /* Clear out, cc not affected */
5338    p = s390_emit_IPM(p, reg, reg);
5339    /* Shift 28 bits to the right --> [0,1,2,3] */
5340    return s390_emit_SRL(p, reg, 0, 28); /* REG = cc */
5341 }
5342 
5343 
5344 /*---------------------------------------------------------------*/
5345 /*--- Code generation                                         ---*/
5346 /*---------------------------------------------------------------*/
5347 
5348 /* Do not load more bytes than requested. */
5349 static UChar *
s390_insn_load_emit(UChar * buf,const s390_insn * insn)5350 s390_insn_load_emit(UChar *buf, const s390_insn *insn)
5351 {
5352    UInt r, x, b, d;
5353    const s390_amode *src;
5354 
5355    src = insn->variant.load.src;
5356 
5357    r = hregNumber(insn->variant.load.dst);
5358 
5359    if (hregClass(insn->variant.load.dst) == HRcFlt64) {
5360       b = hregNumber(src->b);
5361       x = hregNumber(src->x);  /* 0 for B12 and B20 */
5362       d = src->d;
5363 
5364       switch (insn->size) {
5365 
5366       case 4:
5367          switch (src->tag) {
5368          case S390_AMODE_B12:
5369          case S390_AMODE_BX12:
5370             return s390_emit_LE(buf, r, x, b, d);
5371 
5372          case S390_AMODE_B20:
5373          case S390_AMODE_BX20:
5374             return s390_emit_LEY(buf, r, x, b, DISP20(d));
5375          }
5376          break;
5377 
5378       case 8:
5379          switch (src->tag) {
5380          case S390_AMODE_B12:
5381          case S390_AMODE_BX12:
5382             return s390_emit_LD(buf, r, x, b, d);
5383 
5384          case S390_AMODE_B20:
5385          case S390_AMODE_BX20:
5386             return s390_emit_LDY(buf, r, x, b, DISP20(d));
5387          }
5388          break;
5389       }
5390       vpanic("s390_insn_load_emit");
5391    }
5392 
5393    /* Integer stuff */
5394    return s390_emit_load_mem(buf, insn->size, r, src);
5395 }
5396 
5397 
5398 static UChar *
s390_insn_store_emit(UChar * buf,const s390_insn * insn)5399 s390_insn_store_emit(UChar *buf, const s390_insn *insn)
5400 {
5401    UInt r, x, b, d;
5402    const s390_amode *dst;
5403 
5404    dst = insn->variant.store.dst;
5405 
5406    r = hregNumber(insn->variant.store.src);
5407    b = hregNumber(dst->b);
5408    x = hregNumber(dst->x);  /* 0 for B12 and B20 */
5409    d = dst->d;
5410 
5411    if (hregClass(insn->variant.store.src) == HRcFlt64) {
5412       switch (insn->size) {
5413 
5414       case 4:
5415          switch (dst->tag) {
5416          case S390_AMODE_B12:
5417          case S390_AMODE_BX12:
5418             return s390_emit_STE(buf, r, x, b, d);
5419 
5420          case S390_AMODE_B20:
5421          case S390_AMODE_BX20:
5422             return s390_emit_STEY(buf, r, x, b, DISP20(d));
5423          }
5424          break;
5425 
5426       case 8:
5427          switch (dst->tag) {
5428          case S390_AMODE_B12:
5429          case S390_AMODE_BX12:
5430             return s390_emit_STD(buf, r, x, b, d);
5431 
5432          case S390_AMODE_B20:
5433          case S390_AMODE_BX20:
5434             return s390_emit_STDY(buf, r, x, b, DISP20(d));
5435          }
5436          break;
5437       }
5438       vpanic("s390_insn_store_emit");
5439    }
5440 
5441    /* Integer stuff */
5442    switch (insn->size) {
5443    case 1:
5444       switch (dst->tag) {
5445       case S390_AMODE_B12:
5446       case S390_AMODE_BX12:
5447          return s390_emit_STC(buf, r, x, b, d);
5448 
5449       case S390_AMODE_B20:
5450       case S390_AMODE_BX20:
5451          return s390_emit_STCY(buf, r, x, b, DISP20(d));
5452       }
5453       break;
5454 
5455    case 2:
5456       switch (dst->tag) {
5457       case S390_AMODE_B12:
5458       case S390_AMODE_BX12:
5459          return s390_emit_STH(buf, r, x, b, d);
5460 
5461       case S390_AMODE_B20:
5462       case S390_AMODE_BX20:
5463          return s390_emit_STHY(buf, r, x, b, DISP20(d));
5464       }
5465       break;
5466 
5467    case 4:
5468       switch (dst->tag) {
5469       case S390_AMODE_B12:
5470       case S390_AMODE_BX12:
5471          return s390_emit_ST(buf, r, x, b, d);
5472 
5473       case S390_AMODE_B20:
5474       case S390_AMODE_BX20:
5475          return s390_emit_STY(buf, r, x, b, DISP20(d));
5476       }
5477       break;
5478 
5479    case 8:
5480       return s390_emit_STG(buf, r, x, b, DISP20(d));
5481 
5482    default:
5483       break;
5484    }
5485 
5486    vpanic("s390_insn_store_emit");
5487 }
5488 
5489 
5490 static UChar *
s390_insn_move_emit(UChar * buf,const s390_insn * insn)5491 s390_insn_move_emit(UChar *buf, const s390_insn *insn)
5492 {
5493    UInt dst, src;
5494    HRegClass dst_class, src_class;
5495 
5496    dst = hregNumber(insn->variant.move.dst);
5497    src = hregNumber(insn->variant.move.src);
5498 
5499    dst_class = hregClass(insn->variant.move.dst);
5500    src_class = hregClass(insn->variant.move.src);
5501 
5502    if (dst_class == src_class) {
5503       if (dst_class == HRcInt64)
5504          return s390_emit_LGR(buf, dst, src);
5505       if (dst_class == HRcFlt64)
5506          return s390_emit_LDR(buf, dst, src);
5507    } else {
5508       if (dst_class == HRcFlt64 && src_class == HRcInt64) {
5509          if (insn->size == 4) {
5510             buf = s390_emit_SLLG(buf, R0, src, 0, DISP20(32)); /* r0 = src << 32 */
5511             return s390_emit_LDGRw(buf, dst, R0);
5512          } else {
5513             return s390_emit_LDGRw(buf, dst, src);
5514          }
5515       }
5516       if (dst_class == HRcInt64 && src_class == HRcFlt64) {
5517          if (insn->size == 4) {
5518             buf = s390_emit_LGDRw(buf, dst, src);
5519             return s390_emit_SRLG(buf, dst, dst, 0, DISP20(32)); /* dst >>= 32 */
5520          } else {
5521             return s390_emit_LGDRw(buf, dst, src);
5522          }
5523       }
5524       /* A move between floating point registers and general purpose
5525          registers of different size should never occur and indicates
5526          an error elsewhere. */
5527    }
5528 
5529    vpanic("s390_insn_move_emit");
5530 }
5531 
5532 
5533 static UChar *
s390_insn_load_immediate_emit(UChar * buf,const s390_insn * insn)5534 s390_insn_load_immediate_emit(UChar *buf, const s390_insn *insn)
5535 {
5536    UInt  r;
5537    ULong value = insn->variant.load_immediate.value;
5538 
5539    r = hregNumber(insn->variant.load_immediate.dst);
5540 
5541    if (hregClass(insn->variant.load_immediate.dst) == HRcFlt64) {
5542       vassert(value == 0);
5543       switch (insn->size) {
5544       case 4: return s390_emit_LZER(buf, r, value);
5545       case 8: return s390_emit_LZDR(buf, r, value);
5546       }
5547       vpanic("s390_insn_load_immediate_emit");
5548    }
5549 
5550    switch (insn->size) {
5551    case 1:
5552    case 2:
5553       /* Load the immediate values as a 4 byte value. That does not hurt as
5554          those extra bytes will not be looked at. Fall through .... */
5555    case 4:
5556       return s390_emit_load_32imm(buf, r, value);
5557 
5558    case 8:
5559       return s390_emit_load_64imm(buf, r, value);
5560    }
5561 
5562    vpanic("s390_insn_load_immediate_emit");
5563 }
5564 
5565 
5566 /* There is no easy way to do ALU operations on 1-byte or 2-byte operands.
5567    So we simply perform a 4-byte operation. Doing so uses possibly undefined
5568    bits and produces an undefined result in those extra bit positions. But
5569    upstream does not look at those positions, so this is OK. */
5570 static UChar *
s390_insn_alu_emit(UChar * buf,const s390_insn * insn)5571 s390_insn_alu_emit(UChar *buf, const s390_insn *insn)
5572 {
5573    s390_opnd_RMI op2;
5574    UInt dst;
5575 
5576    dst = hregNumber(insn->variant.alu.dst);
5577    op2 = insn->variant.alu.op2;
5578 
5579    /* Second operand is in a register */
5580    if (op2.tag == S390_OPND_REG) {
5581       UInt r2 = hregNumber(op2.variant.reg);
5582 
5583       switch (insn->size) {
5584       case 1:
5585       case 2:
5586       case 4:
5587          switch (insn->variant.alu.tag) {
5588          case S390_ALU_ADD:  return s390_emit_AR(buf, dst, r2);
5589          case S390_ALU_SUB:  return s390_emit_SR(buf, dst, r2);
5590          case S390_ALU_MUL:  return s390_emit_MSR(buf, dst, r2);
5591          case S390_ALU_AND:  return s390_emit_NR(buf, dst, r2);
5592          case S390_ALU_OR:   return s390_emit_OR(buf, dst, r2);
5593          case S390_ALU_XOR:  return s390_emit_XR(buf, dst, r2);
5594          case S390_ALU_LSH:  return s390_emit_SLL(buf, dst, r2, 0);
5595          case S390_ALU_RSH:  return s390_emit_SRL(buf, dst, r2, 0);
5596          case S390_ALU_RSHA: return s390_emit_SRA(buf, dst, r2, 0);
5597          }
5598          goto fail;
5599 
5600       case 8:
5601          switch (insn->variant.alu.tag) {
5602          case S390_ALU_ADD:  return s390_emit_AGR(buf, dst, r2);
5603          case S390_ALU_SUB:  return s390_emit_SGR(buf, dst, r2);
5604          case S390_ALU_MUL:  return s390_emit_MSGR(buf, dst, r2);
5605          case S390_ALU_AND:  return s390_emit_NGR(buf, dst, r2);
5606          case S390_ALU_OR:   return s390_emit_OGR(buf, dst, r2);
5607          case S390_ALU_XOR:  return s390_emit_XGR(buf, dst, r2);
5608          case S390_ALU_LSH:  return s390_emit_SLLG(buf, dst, dst, r2, DISP20(0));
5609          case S390_ALU_RSH:  return s390_emit_SRLG(buf, dst, dst, r2, DISP20(0));
5610          case S390_ALU_RSHA: return s390_emit_SRAG(buf, dst, dst, r2, DISP20(0));
5611          }
5612          goto fail;
5613       }
5614       goto fail;
5615    }
5616 
5617    /* 2nd operand is in memory */
5618    if (op2.tag == S390_OPND_AMODE) {
5619       UInt b, x, d;
5620       const s390_amode *src = op2.variant.am;
5621 
5622       b = hregNumber(src->b);
5623       x = hregNumber(src->x);  /* 0 for B12 and B20 */
5624       d = src->d;
5625 
5626       /* Shift operands are special here as there are no opcodes that
5627          allow a memory operand. So we first load the 2nd operand into
5628          some register. R0 is used to save restore the contents of the
5629          chosen register.. */
5630 
5631       if (insn->variant.alu.tag == S390_ALU_LSH ||
5632           insn->variant.alu.tag == S390_ALU_RSH ||
5633           insn->variant.alu.tag == S390_ALU_RSHA) {
5634          UInt b2;
5635 
5636          /* Choose a register (other than DST or R0) into which to stick the
5637             shift amount. The following works because r15 is reserved and
5638             thusly dst != 15. */
5639          vassert(dst != 15);  /* extra paranoia */
5640          b2 = (dst + 1) % 16;
5641 
5642          buf = s390_emit_LGR(buf, R0, b2);  /* save */
5643 
5644          /* Loading SRC to B2 does not modify R0. */
5645          buf = s390_emit_load_mem(buf, insn->size, b2, src);
5646 
5647          if (insn->size == 8) {
5648             switch (insn->variant.alu.tag) {
5649             case S390_ALU_LSH:
5650                buf = s390_emit_SLLG(buf, dst, dst, b2, DISP20(0));
5651                break;
5652             case S390_ALU_RSH:
5653                buf = s390_emit_SRLG(buf, dst, dst, b2, DISP20(0));
5654                break;
5655             case S390_ALU_RSHA:
5656                buf = s390_emit_SRAG(buf, dst, dst, b2, DISP20(0));
5657                break;
5658             default: /* unreachable */
5659                goto fail;
5660             }
5661          } else {
5662             switch (insn->variant.alu.tag) {
5663             case S390_ALU_LSH:
5664                buf = s390_emit_SLL(buf, dst, b2, 0);
5665                break;
5666             case S390_ALU_RSH:
5667                buf = s390_emit_SRL(buf, dst, b2, 0);
5668                break;
5669             case S390_ALU_RSHA:
5670                buf = s390_emit_SRA(buf, dst, b2, 0);
5671                break;
5672             default: /* unreachable */
5673                goto fail;
5674             }
5675          }
5676          return s390_emit_LGR(buf, b2, R0);  /* restore */
5677       }
5678 
5679       switch (insn->size) {
5680       case 1:
5681          /* Move the byte from memory into scratch register r0 */
5682          buf = s390_emit_load_mem(buf, 1, R0, src);
5683 
5684          switch (insn->variant.alu.tag) {
5685          case S390_ALU_ADD: return s390_emit_AR(buf, dst, R0);
5686          case S390_ALU_SUB: return s390_emit_SR(buf, dst, R0);
5687          case S390_ALU_MUL: return s390_emit_MSR(buf, dst, R0);
5688          case S390_ALU_AND: return s390_emit_NR(buf, dst, R0);
5689          case S390_ALU_OR:  return s390_emit_OR(buf, dst, R0);
5690          case S390_ALU_XOR: return s390_emit_XR(buf, dst, R0);
5691          case S390_ALU_LSH:
5692          case S390_ALU_RSH:
5693          case S390_ALU_RSHA: ; /* avoid GCC warning */
5694          }
5695          goto fail;
5696 
5697       case 2:
5698          switch (src->tag) {
5699          case S390_AMODE_B12:
5700          case S390_AMODE_BX12:
5701             switch (insn->variant.alu.tag) {
5702             case S390_ALU_ADD:
5703                return s390_emit_AH(buf, dst, x, b, d);
5704 
5705             case S390_ALU_SUB:
5706                return s390_emit_SH(buf, dst, x, b, d);
5707 
5708             case S390_ALU_MUL:
5709                return s390_emit_MH(buf, dst, x, b, d);
5710 
5711                /* For bitwise operations: Move two bytes from memory into scratch
5712                   register r0; then perform operation */
5713             case S390_ALU_AND:
5714                buf = s390_emit_LH(buf, R0, x, b, d);
5715                return s390_emit_NR(buf, dst, R0);
5716 
5717             case S390_ALU_OR:
5718                buf = s390_emit_LH(buf, R0, x, b, d);
5719                return s390_emit_OR(buf, dst, R0);
5720 
5721             case S390_ALU_XOR:
5722                buf = s390_emit_LH(buf, R0, x, b, d);
5723                return s390_emit_XR(buf, dst, R0);
5724 
5725             case S390_ALU_LSH:
5726             case S390_ALU_RSH:
5727             case S390_ALU_RSHA: ; /* avoid GCC warning */
5728             }
5729             goto fail;
5730 
5731          case S390_AMODE_B20:
5732          case S390_AMODE_BX20:
5733             switch (insn->variant.alu.tag) {
5734             case S390_ALU_ADD:
5735                return s390_emit_AHY(buf, dst, x, b, DISP20(d));
5736 
5737             case S390_ALU_SUB:
5738                return s390_emit_SHY(buf, dst, x, b, DISP20(d));
5739 
5740             case S390_ALU_MUL:
5741                return s390_emit_MHYw(buf, dst, x, b, DISP20(d));
5742 
5743                /* For bitwise operations: Move two bytes from memory into scratch
5744                   register r0; then perform operation */
5745             case S390_ALU_AND:
5746                buf = s390_emit_LHY(buf, R0, x, b, DISP20(d));
5747                return s390_emit_NR(buf, dst, R0);
5748 
5749             case S390_ALU_OR:
5750                buf = s390_emit_LHY(buf, R0, x, b, DISP20(d));
5751                return s390_emit_OR(buf, dst, R0);
5752 
5753             case S390_ALU_XOR:
5754                buf = s390_emit_LHY(buf, R0, x, b, DISP20(d));
5755                return s390_emit_XR(buf, dst, R0);
5756 
5757             case S390_ALU_LSH:
5758             case S390_ALU_RSH:
5759             case S390_ALU_RSHA: ; /* avoid GCC warning */
5760             }
5761             goto fail;
5762          }
5763          goto fail;
5764 
5765       case 4:
5766          switch (src->tag) {
5767          case S390_AMODE_B12:
5768          case S390_AMODE_BX12:
5769             switch (insn->variant.alu.tag) {
5770             case S390_ALU_ADD: return s390_emit_A(buf, dst, x, b, d);
5771             case S390_ALU_SUB: return s390_emit_S(buf, dst, x, b, d);
5772             case S390_ALU_MUL: return s390_emit_MS(buf, dst, x, b, d);
5773             case S390_ALU_AND: return s390_emit_N(buf, dst, x, b, d);
5774             case S390_ALU_OR:  return s390_emit_O(buf, dst, x, b, d);
5775             case S390_ALU_XOR: return s390_emit_X(buf, dst, x, b, d);
5776             case S390_ALU_LSH:
5777             case S390_ALU_RSH:
5778             case S390_ALU_RSHA: ; /* avoid GCC warning */
5779             }
5780             goto fail;
5781 
5782          case S390_AMODE_B20:
5783          case S390_AMODE_BX20:
5784             switch (insn->variant.alu.tag) {
5785             case S390_ALU_ADD: return s390_emit_AY(buf, dst, x, b, DISP20(d));
5786             case S390_ALU_SUB: return s390_emit_SY(buf, dst, x, b, DISP20(d));
5787             case S390_ALU_MUL: return s390_emit_MSY(buf, dst, x, b, DISP20(d));
5788             case S390_ALU_AND: return s390_emit_NY(buf, dst, x, b, DISP20(d));
5789             case S390_ALU_OR:  return s390_emit_OY(buf, dst, x, b, DISP20(d));
5790             case S390_ALU_XOR: return s390_emit_XY(buf, dst, x, b, DISP20(d));
5791             case S390_ALU_LSH:
5792             case S390_ALU_RSH:
5793             case S390_ALU_RSHA: ; /* avoid GCC warning */
5794             }
5795             goto fail;
5796          }
5797          goto fail;
5798 
5799       case 8:
5800          switch (insn->variant.alu.tag) {
5801          case S390_ALU_ADD: return s390_emit_AG(buf, dst, x, b, DISP20(d));
5802          case S390_ALU_SUB: return s390_emit_SG(buf, dst, x, b, DISP20(d));
5803          case S390_ALU_MUL: return s390_emit_MSG(buf, dst, x, b, DISP20(d));
5804          case S390_ALU_AND: return s390_emit_NG(buf, dst, x, b, DISP20(d));
5805          case S390_ALU_OR:  return s390_emit_OG(buf, dst, x, b, DISP20(d));
5806          case S390_ALU_XOR: return s390_emit_XG(buf, dst, x, b, DISP20(d));
5807          case S390_ALU_LSH:
5808          case S390_ALU_RSH:
5809          case S390_ALU_RSHA: ; /* avoid GCC warning */
5810          }
5811          goto fail;
5812       }
5813       goto fail;
5814    }
5815 
5816    /* 2nd operand is an immediate value */
5817    if (op2.tag == S390_OPND_IMMEDIATE) {
5818       ULong value;
5819 
5820       /* No masking of the value is required as it is not sign extended */
5821       value = op2.variant.imm;
5822 
5823       switch (insn->size) {
5824       case 1:
5825       case 2:
5826          /* There is no 1-byte opcode. Do the computation in
5827             2 bytes. The extra byte will be ignored. */
5828          switch (insn->variant.alu.tag) {
5829          case S390_ALU_ADD:
5830             return s390_emit_AHI(buf, dst, value);
5831 
5832          case S390_ALU_SUB:
5833             return s390_emit_SLFIw(buf, dst, value);
5834 
5835          case S390_ALU_MUL:
5836             return s390_emit_MHI(buf, dst, value);
5837 
5838          case S390_ALU_AND: return s390_emit_NILL(buf, dst, value);
5839          case S390_ALU_OR:  return s390_emit_OILL(buf, dst, value);
5840          case S390_ALU_XOR:
5841             /* There is no XILL instruction.  Load the immediate value into
5842                R0 and combine with the destination register. */
5843             buf = s390_emit_LHI(buf, R0, value);
5844             return s390_emit_XR(buf, dst, R0);
5845 
5846          case S390_ALU_LSH:
5847             return s390_emit_SLL(buf, dst, 0, value);
5848 
5849          case S390_ALU_RSH:
5850             return s390_emit_SRL(buf, dst, 0, value);
5851 
5852          case S390_ALU_RSHA:
5853             return s390_emit_SRA(buf, dst, 0, value);
5854          }
5855          goto fail;
5856 
5857       case 4:
5858          switch (insn->variant.alu.tag) {
5859          case S390_ALU_ADD:
5860             if (uint_fits_signed_16bit(value)) {
5861                return s390_emit_AHI(buf, dst, value);
5862             }
5863             return s390_emit_AFIw(buf, dst, value);
5864 
5865          case S390_ALU_SUB:  return s390_emit_SLFIw(buf, dst, value);
5866          case S390_ALU_MUL:  return s390_emit_MSFIw(buf, dst, value);
5867          case S390_ALU_AND:  return s390_emit_NILFw(buf, dst, value);
5868          case S390_ALU_OR:   return s390_emit_OILFw(buf, dst, value);
5869          case S390_ALU_XOR:  return s390_emit_XILFw(buf, dst, value);
5870          case S390_ALU_LSH:  return s390_emit_SLL(buf, dst, 0, value);
5871          case S390_ALU_RSH:  return s390_emit_SRL(buf, dst, 0, value);
5872          case S390_ALU_RSHA: return s390_emit_SRA(buf, dst, 0, value);
5873          }
5874          goto fail;
5875 
5876       case 8:
5877          switch (insn->variant.alu.tag) {
5878          case S390_ALU_ADD:
5879             if (ulong_fits_signed_16bit(value)) {
5880                return s390_emit_AGHI(buf, dst, value);
5881             }
5882             if (ulong_fits_signed_32bit(value) && s390_host_has_eimm) {
5883                return s390_emit_AGFI(buf, dst, value);
5884             }
5885             /* Load constant into R0 then add */
5886             buf = s390_emit_load_64imm(buf, R0, value);
5887             return s390_emit_AGR(buf, dst, R0);
5888 
5889          case S390_ALU_SUB:
5890             if (ulong_fits_unsigned_32bit(value)) {
5891                return s390_emit_SLGFIw(buf, dst, value);
5892             }
5893             /* Load value into R0; then subtract from destination reg */
5894             buf = s390_emit_load_64imm(buf, R0, value);
5895             return s390_emit_SGR(buf, dst, R0);
5896 
5897          case S390_ALU_MUL:
5898             if (ulong_fits_signed_32bit(value) && s390_host_has_gie) {
5899                return s390_emit_MSGFI(buf, dst, value);
5900             }
5901             /* Load constant into R0 then add */
5902             buf = s390_emit_load_64imm(buf, R0, value);
5903             return s390_emit_MSGR(buf, dst, R0);
5904 
5905             /* Do it in two steps: upper half [0:31] and lower half [32:63] */
5906          case S390_ALU_AND:
5907             if (s390_host_has_eimm) {
5908                buf  = s390_emit_NIHF(buf, dst, value >> 32);
5909                return s390_emit_NILF(buf, dst, value & 0xFFFFFFFF);
5910             }
5911             /* Load value into R0; then combine with destination reg */
5912             buf = s390_emit_load_64imm(buf, R0, value);
5913             return s390_emit_NGR(buf, dst, R0);
5914 
5915          case S390_ALU_OR:
5916             if (s390_host_has_eimm) {
5917                buf  = s390_emit_OIHF(buf, dst, value >> 32);
5918                return s390_emit_OILF(buf, dst, value & 0xFFFFFFFF);
5919             }
5920             /* Load value into R0; then combine with destination reg */
5921             buf = s390_emit_load_64imm(buf, R0, value);
5922             return s390_emit_OGR(buf, dst, R0);
5923 
5924          case S390_ALU_XOR:
5925             if (s390_host_has_eimm) {
5926                buf  = s390_emit_XIHF(buf, dst, value >> 32);
5927                return s390_emit_XILF(buf, dst, value & 0xFFFFFFFF);
5928             }
5929             /* Load value into R0; then combine with destination reg */
5930             buf = s390_emit_load_64imm(buf, R0, value);
5931             return s390_emit_XGR(buf, dst, R0);
5932 
5933             /* No special considerations for long displacement here. Only the six
5934                least significant bits of VALUE will be taken; all other bits are
5935                ignored. So the DH2 bits are irrelevant and do not influence the
5936                shift operation, independent of whether long-displacement is available
5937                or not. */
5938          case S390_ALU_LSH:  return s390_emit_SLLG(buf, dst, dst, 0, DISP20(value));
5939          case S390_ALU_RSH:  return s390_emit_SRLG(buf, dst, dst, 0, DISP20(value));
5940          case S390_ALU_RSHA: return s390_emit_SRAG(buf, dst, dst, 0, DISP20(value));
5941          }
5942          goto fail;
5943       }
5944       goto fail;
5945    }
5946 
5947  fail:
5948    vpanic("s390_insn_alu_emit");
5949 }
5950 
5951 
5952 static UChar *
s390_widen_emit(UChar * buf,const s390_insn * insn,UInt from_size,Bool sign_extend)5953 s390_widen_emit(UChar *buf, const s390_insn *insn, UInt from_size,
5954                 Bool sign_extend)
5955 {
5956    s390_opnd_RMI opnd = insn->variant.unop.src;
5957 
5958    switch (opnd.tag) {
5959    case S390_OPND_REG: {
5960       UChar r1 = hregNumber(insn->variant.unop.dst);
5961       UChar r2 = hregNumber(opnd.variant.reg);
5962 
5963       switch (from_size) {
5964       case 1:
5965          /* Widening to a half-word is implemented like widening to a word
5966             because the upper half-word will not be looked at. */
5967          if (insn->size == 4 || insn->size == 2) {  /* 8 --> 32    8 --> 16 */
5968             if (sign_extend)
5969                return s390_emit_LBRw(buf, r1, r2);
5970             else
5971                return s390_emit_LLCRw(buf, r1, r2);
5972          }
5973          if (insn->size == 8) {  /* 8 --> 64 */
5974             if (sign_extend)
5975                return s390_emit_LGBRw(buf, r1, r2);
5976             else
5977                return s390_emit_LLGCRw(buf, r1, r2);
5978          }
5979          goto fail;
5980 
5981       case 2:
5982          if (insn->size == 4) {  /* 16 --> 32 */
5983             if (sign_extend)
5984                return s390_emit_LHRw(buf, r1, r2);
5985             else
5986                return s390_emit_LLHRw(buf, r1, r2);
5987          }
5988          if (insn->size == 8) {  /* 16 --> 64 */
5989             if (sign_extend)
5990                return s390_emit_LGHRw(buf, r1, r2);
5991             else
5992                return s390_emit_LLGHRw(buf, r1, r2);
5993          }
5994          goto fail;
5995 
5996       case 4:
5997          if (insn->size == 8) {  /* 32 --> 64 */
5998             if (sign_extend)
5999                return s390_emit_LGFR(buf, r1, r2);
6000             else
6001                return s390_emit_LLGFR(buf, r1, r2);
6002          }
6003          goto fail;
6004 
6005       default: /* unexpected "from" size */
6006          goto fail;
6007       }
6008    }
6009 
6010    case S390_OPND_AMODE: {
6011       UChar r1 = hregNumber(insn->variant.unop.dst);
6012       const s390_amode *src = opnd.variant.am;
6013       UChar b = hregNumber(src->b);
6014       UChar x = hregNumber(src->x);
6015       Int   d = src->d;
6016 
6017       switch (from_size) {
6018       case 1:
6019          if (insn->size == 4 || insn->size == 2) {
6020             if (sign_extend)
6021                return s390_emit_LBw(buf, r1, x, b, DISP20(d));
6022             else
6023                return s390_emit_LLCw(buf, r1, x, b, DISP20(d));
6024          }
6025          if (insn->size == 8) {
6026             if (sign_extend)
6027                return s390_emit_LGBw(buf, r1, x, b, DISP20(d));
6028             else
6029                return s390_emit_LLGC(buf, r1, x, b, DISP20(d));
6030          }
6031          goto fail;
6032 
6033       case 2:
6034          if (insn->size == 4) {  /* 16 --> 32 */
6035             if (sign_extend == 0)
6036                return s390_emit_LLHw(buf, r1, x, b, DISP20(d));
6037 
6038             switch (src->tag) {
6039             case S390_AMODE_B12:
6040             case S390_AMODE_BX12:
6041                return s390_emit_LH(buf, r1, x, b, d);
6042 
6043             case S390_AMODE_B20:
6044             case S390_AMODE_BX20:
6045                return s390_emit_LHY(buf, r1, x, b, DISP20(d));
6046             }
6047             goto fail;
6048          }
6049          if (insn->size == 8) {  /* 16 --> 64 */
6050             if (sign_extend)
6051                return s390_emit_LGH(buf, r1, x, b, DISP20(d));
6052             else
6053                return s390_emit_LLGH(buf, r1, x, b, DISP20(d));
6054          }
6055          goto fail;
6056 
6057       case 4:
6058          if (insn->size == 8) {  /* 32 --> 64 */
6059             if (sign_extend)
6060                return s390_emit_LGF(buf, r1, x, b, DISP20(d));
6061             else
6062                return s390_emit_LLGF(buf, r1, x, b, DISP20(d));
6063          }
6064          goto fail;
6065 
6066       default: /* unexpected "from" size */
6067          goto fail;
6068       }
6069    }
6070 
6071    case S390_OPND_IMMEDIATE: {
6072       UChar r1 = hregNumber(insn->variant.unop.dst);
6073       ULong value = opnd.variant.imm;
6074 
6075       switch (from_size) {
6076       case 1:
6077          if (insn->size == 4 || insn->size == 2) {  /* 8 --> 32   8 --> 16 */
6078             if (sign_extend) {
6079                /* host can do the sign extension to 16-bit; LHI does the rest */
6080                return s390_emit_LHI(buf, r1, (Short)(Char)(UChar)value);
6081             } else {
6082                return s390_emit_LHI(buf, r1, value);
6083             }
6084          }
6085          if (insn->size == 8) {  /* 8 --> 64 */
6086             if (sign_extend) {
6087                /* host can do the sign extension to 16-bit; LGHI does the rest */
6088                return s390_emit_LGHI(buf, r1, (Short)(Char)(UChar)value);
6089             } else {
6090                return s390_emit_LGHI(buf, r1, value);
6091             }
6092          }
6093          goto fail;
6094 
6095       case 2:
6096          if (insn->size == 4) {  /* 16 --> 32 */
6097             return s390_emit_LHI(buf, r1, value);
6098          }
6099          if (insn->size == 8) {  /* 16 --> 64 */
6100             if (sign_extend)
6101                return s390_emit_LGHI(buf, r1, value);
6102             else
6103                return s390_emit_LLILL(buf, r1, value);
6104          }
6105          goto fail;
6106 
6107       case 4:
6108          if (insn->size == 8) {  /* 32 --> 64 */
6109             if (sign_extend)
6110                return s390_emit_LGFIw(buf, r1, value);
6111             else
6112                return s390_emit_LLILFw(buf, r1, value);
6113          }
6114          goto fail;
6115 
6116       default: /* unexpected "from" size */
6117          goto fail;
6118       }
6119    }
6120    }
6121 
6122  fail:
6123    vpanic("s390_widen_emit");
6124 }
6125 
6126 
6127 static UChar *
s390_negate_emit(UChar * buf,const s390_insn * insn)6128 s390_negate_emit(UChar *buf, const s390_insn *insn)
6129 {
6130    s390_opnd_RMI opnd;
6131 
6132    opnd = insn->variant.unop.src;
6133 
6134    switch (opnd.tag) {
6135    case S390_OPND_REG: {
6136       UChar r1 = hregNumber(insn->variant.unop.dst);
6137       UChar r2 = hregNumber(opnd.variant.reg);
6138 
6139       switch (insn->size) {
6140       case 1:
6141       case 2:
6142       case 4:
6143          return s390_emit_LCR(buf, r1, r2);
6144 
6145       case 8:
6146          return s390_emit_LCGR(buf, r1, r2);
6147 
6148       default:
6149          goto fail;
6150       }
6151    }
6152 
6153    case S390_OPND_AMODE: {
6154       UChar r1 = hregNumber(insn->variant.unop.dst);
6155 
6156       /* Load bytes into scratch register R0, then negate */
6157       buf = s390_emit_load_mem(buf, insn->size, R0, opnd.variant.am);
6158 
6159       switch (insn->size) {
6160       case 1:
6161       case 2:
6162       case 4:
6163          return s390_emit_LCR(buf, r1, R0);
6164 
6165       case 8:
6166          return s390_emit_LCGR(buf, r1, R0);
6167 
6168       default:
6169          goto fail;
6170       }
6171    }
6172 
6173    case S390_OPND_IMMEDIATE: {
6174       UChar r1 = hregNumber(insn->variant.unop.dst);
6175       ULong value = opnd.variant.imm;
6176 
6177       value = ~value + 1;   /* two's complement */
6178 
6179       switch (insn->size) {
6180       case 1:
6181       case 2:
6182          /* Load the immediate values as a 4 byte value. That does not hurt as
6183             those extra bytes will not be looked at. Fall through .... */
6184       case 4:
6185          return s390_emit_load_32imm(buf, r1, value);
6186 
6187       case 8:
6188          return s390_emit_load_64imm(buf, r1, value);
6189 
6190       default:
6191          goto fail;
6192       }
6193    }
6194    }
6195 
6196  fail:
6197    vpanic("s390_negate_emit");
6198 }
6199 
6200 
6201 static UChar *
s390_insn_unop_emit(UChar * buf,const s390_insn * insn)6202 s390_insn_unop_emit(UChar *buf, const s390_insn *insn)
6203 {
6204    switch (insn->variant.unop.tag) {
6205    case S390_ZERO_EXTEND_8:  return s390_widen_emit(buf, insn, 1, 0);
6206    case S390_ZERO_EXTEND_16: return s390_widen_emit(buf, insn, 2, 0);
6207    case S390_ZERO_EXTEND_32: return s390_widen_emit(buf, insn, 4, 0);
6208 
6209    case S390_SIGN_EXTEND_8:  return s390_widen_emit(buf, insn, 1, 1);
6210    case S390_SIGN_EXTEND_16: return s390_widen_emit(buf, insn, 2, 1);
6211    case S390_SIGN_EXTEND_32: return s390_widen_emit(buf, insn, 4, 1);
6212 
6213    case S390_NEGATE:         return s390_negate_emit(buf, insn);
6214    }
6215 
6216    vpanic("s390_insn_unop_emit");
6217 }
6218 
6219 
6220 /* Only 4-byte and 8-byte operands are handled. 1-byte and 2-byte
6221    comparisons will have been converted to 4-byte comparisons in
6222    s390_isel_cc and should not occur here. */
6223 static UChar *
s390_insn_test_emit(UChar * buf,const s390_insn * insn)6224 s390_insn_test_emit(UChar *buf, const s390_insn *insn)
6225 {
6226    s390_opnd_RMI opnd;
6227 
6228    opnd = insn->variant.test.src;
6229 
6230    switch (opnd.tag) {
6231    case S390_OPND_REG: {
6232       UInt reg = hregNumber(opnd.variant.reg);
6233 
6234       switch (insn->size) {
6235       case 4:
6236          return s390_emit_LTR(buf, reg, reg);
6237 
6238       case 8:
6239          return s390_emit_LTGR(buf, reg, reg);
6240 
6241       default:
6242          goto fail;
6243       }
6244    }
6245 
6246    case S390_OPND_AMODE: {
6247       const s390_amode *am = opnd.variant.am;
6248       UChar b = hregNumber(am->b);
6249       UChar x = hregNumber(am->x);
6250       Int   d = am->d;
6251 
6252       switch (insn->size) {
6253       case 4:
6254          return s390_emit_LTw(buf, R0, x, b, DISP20(d));
6255 
6256       case 8:
6257          return s390_emit_LTGw(buf, R0, x, b, DISP20(d));
6258 
6259       default:
6260          goto fail;
6261       }
6262    }
6263 
6264    case S390_OPND_IMMEDIATE: {
6265       ULong value = opnd.variant.imm;
6266 
6267       switch (insn->size) {
6268       case 4:
6269          buf = s390_emit_load_32imm(buf, R0, value);
6270          return s390_emit_LTR(buf, R0, R0);
6271 
6272       case 8:
6273          buf = s390_emit_load_64imm(buf, R0, value);
6274          return s390_emit_LTGR(buf, R0, R0);
6275 
6276       default:
6277          goto fail;
6278       }
6279    }
6280 
6281    default:
6282       goto fail;
6283    }
6284 
6285  fail:
6286    vpanic("s390_insn_test_emit");
6287 }
6288 
6289 
6290 static UChar *
s390_insn_cc2bool_emit(UChar * buf,const s390_insn * insn)6291 s390_insn_cc2bool_emit(UChar *buf, const s390_insn *insn)
6292 {
6293    UChar r1 = hregNumber(insn->variant.cc2bool.dst);
6294    s390_cc_t cond = insn->variant.cc2bool.cond;
6295 
6296    /* Make the destination register be 1 or 0, depending on whether
6297       the relevant condition holds. A 64-bit value is computed. */
6298    if (cond == S390_CC_ALWAYS)
6299       return s390_emit_LGHI(buf, r1, 1);  /* r1 = 1 */
6300 
6301    buf = s390_emit_load_cc(buf, r1);                 /* r1 = cc */
6302    buf = s390_emit_LGHI(buf, R0, cond);              /* r0 = mask */
6303    buf = s390_emit_SLLG(buf, r1, R0, r1, DISP20(0)); /* r1 = mask << cc */
6304    buf = s390_emit_SRLG(buf, r1, r1, 0,  DISP20(3)); /* r1 = r1 >> 3 */
6305    buf = s390_emit_NILL(buf, r1, 1);                 /* r1 = r1 & 0x1 */
6306 
6307    return buf;
6308 }
6309 
6310 
6311 /* Only 4-byte and 8-byte operands are handled. */
6312 static UChar *
s390_insn_cas_emit(UChar * buf,const s390_insn * insn)6313 s390_insn_cas_emit(UChar *buf, const s390_insn *insn)
6314 {
6315    UChar r1, r3, b, old;
6316    Int d;
6317    s390_amode *am;
6318 
6319    r1 = hregNumber(insn->variant.cas.op1); /* expected value */
6320    r3 = hregNumber(insn->variant.cas.op3);
6321    old= hregNumber(insn->variant.cas.old_mem);
6322    am = insn->variant.cas.op2;
6323    b  = hregNumber(am->b);
6324    d  = am->d;
6325 
6326    switch (insn->size) {
6327    case 4:
6328       /* r1 must no be overwritten. So copy it to R0 and let CS clobber it */
6329       buf = s390_emit_LR(buf, R0, r1);
6330       if (am->tag == S390_AMODE_B12)
6331          buf = s390_emit_CS(buf, R0, r3, b, d);
6332       else
6333          buf = s390_emit_CSY(buf, R0, r3, b, DISP20(d));
6334       /* Now copy R0 which has the old memory value to OLD */
6335       return s390_emit_LR(buf, old, R0);
6336 
6337    case 8:
6338       /* r1 must no be overwritten. So copy it to R0 and let CS clobber it */
6339       buf = s390_emit_LGR(buf, R0, r1);
6340       buf = s390_emit_CSG(buf, R0, r3, b, DISP20(d));
6341       /* Now copy R0 which has the old memory value to OLD */
6342       return s390_emit_LGR(buf, old, R0);
6343 
6344    default:
6345       goto fail;
6346    }
6347 
6348  fail:
6349    vpanic("s390_insn_cas_emit");
6350 }
6351 
6352 
6353 /* Only 4-byte and 8-byte operands are handled. */
6354 static UChar *
s390_insn_cdas_emit(UChar * buf,const s390_insn * insn)6355 s390_insn_cdas_emit(UChar *buf, const s390_insn *insn)
6356 {
6357    UChar r1, r1p1, r3, /*r3p1,*/ b, old_high, old_low, scratch;
6358    Int d;
6359    s390_amode *am;
6360 
6361    r1   = hregNumber(insn->variant.cdas.op1_high); /* expected value */
6362    r1p1 = hregNumber(insn->variant.cdas.op1_low);  /* expected value */
6363    r3   = hregNumber(insn->variant.cdas.op3_high);
6364    /* r3p1 = hregNumber(insn->variant.cdas.op3_low); */ /* unused */
6365    old_high = hregNumber(insn->variant.cdas.old_mem_high);
6366    old_low  = hregNumber(insn->variant.cdas.old_mem_low);
6367    scratch  = hregNumber(insn->variant.cdas.scratch);
6368    am = insn->variant.cdas.op2;
6369    b  = hregNumber(am->b);
6370    d  = am->d;
6371 
6372    vassert(scratch == 1);
6373 
6374    switch (insn->size) {
6375    case 4:
6376       /* r1, r1+1 must not be overwritten. So copy them to R0,scratch
6377          and let CDS/CDSY clobber it */
6378       buf = s390_emit_LR(buf, R0, r1);
6379       buf = s390_emit_LR(buf, scratch, r1p1);
6380 
6381       if (am->tag == S390_AMODE_B12)
6382          buf = s390_emit_CDS(buf, R0, r3, b, d);
6383       else
6384          buf = s390_emit_CDSY(buf, R0, r3, b, DISP20(d));
6385 
6386       /* Now copy R0,scratch which has the old memory value to OLD */
6387       buf = s390_emit_LR(buf, old_high, R0);
6388       buf = s390_emit_LR(buf, old_low,  scratch);
6389       return buf;
6390 
6391    case 8:
6392       /* r1, r1+1 must not be overwritten. So copy them to R0,scratch
6393          and let CDSG clobber it */
6394       buf = s390_emit_LGR(buf, R0, r1);
6395       buf = s390_emit_LGR(buf, scratch, r1p1);
6396 
6397       buf = s390_emit_CDSG(buf, R0, r3, b, DISP20(d));
6398 
6399       /* Now copy R0,scratch which has the old memory value to OLD */
6400       buf = s390_emit_LGR(buf, old_high, R0);
6401       buf = s390_emit_LGR(buf, old_low,  scratch);
6402       return buf;
6403 
6404    default:
6405       goto fail;
6406    }
6407 
6408  fail:
6409    vpanic("s390_insn_cas_emit");
6410 }
6411 
6412 
6413 /* Only 4-byte and 8-byte comparisons are handled. 1-byte and 2-byte
6414    comparisons will have been converted to 4-byte comparisons in
6415    s390_isel_cc and should not occur here. */
6416 static UChar *
s390_insn_compare_emit(UChar * buf,const s390_insn * insn)6417 s390_insn_compare_emit(UChar *buf, const s390_insn *insn)
6418 {
6419    s390_opnd_RMI op2;
6420    HReg op1;
6421    Bool signed_comparison;
6422 
6423    op1 = insn->variant.compare.src1;
6424    op2 = insn->variant.compare.src2;
6425    signed_comparison = insn->variant.compare.signed_comparison;
6426 
6427    switch (op2.tag) {
6428    case S390_OPND_REG: {
6429       UInt r1 = hregNumber(op1);
6430       UInt r2 = hregNumber(op2.variant.reg);
6431 
6432       switch (insn->size) {
6433       case 4:
6434          if (signed_comparison)
6435             return s390_emit_CR(buf, r1, r2);
6436          else
6437             return s390_emit_CLR(buf, r1, r2);
6438 
6439       case 8:
6440          if (signed_comparison)
6441             return s390_emit_CGR(buf, r1, r2);
6442          else
6443             return s390_emit_CLGR(buf, r1, r2);
6444 
6445       default:
6446          goto fail;
6447       }
6448    }
6449 
6450    case S390_OPND_AMODE: {
6451       UChar r1 = hregNumber(op1);
6452       const s390_amode *am = op2.variant.am;
6453       UChar b = hregNumber(am->b);
6454       UChar x = hregNumber(am->x);
6455       Int   d = am->d;
6456 
6457       switch (insn->size) {
6458       case 4:
6459          switch (am->tag) {
6460          case S390_AMODE_B12:
6461          case S390_AMODE_BX12:
6462             if (signed_comparison)
6463                return s390_emit_C(buf, r1, x, b, d);
6464             else
6465                return s390_emit_CL(buf, r1, x, b, d);
6466 
6467          case S390_AMODE_B20:
6468          case S390_AMODE_BX20:
6469             if (signed_comparison)
6470                return s390_emit_CY(buf, r1, x, b, DISP20(d));
6471             else
6472                return s390_emit_CLY(buf, r1, x, b, DISP20(d));
6473          }
6474          goto fail;
6475 
6476       case 8:
6477          if (signed_comparison)
6478             return s390_emit_CG(buf, r1, x, b, DISP20(d));
6479          else
6480             return s390_emit_CLG(buf, r1, x, b, DISP20(d));
6481 
6482       default:
6483          goto fail;
6484       }
6485    }
6486 
6487    case S390_OPND_IMMEDIATE: {
6488       UChar r1 = hregNumber(op1);
6489       ULong value = op2.variant.imm;
6490 
6491       switch (insn->size) {
6492       case 4:
6493          if (signed_comparison)
6494             return s390_emit_CFIw(buf, r1, value);
6495          else
6496             return s390_emit_CLFIw(buf, r1, value);
6497 
6498       case 8:
6499          if (s390_host_has_eimm) {
6500             if (signed_comparison) {
6501                if (ulong_fits_signed_32bit(value))
6502                   return s390_emit_CGFI(buf, r1, value);
6503             } else {
6504                if (ulong_fits_unsigned_32bit(value))
6505                   return s390_emit_CLGFI(buf, r1, value);
6506             }
6507          }
6508          buf = s390_emit_load_64imm(buf, R0, value);
6509          if (signed_comparison)
6510             return s390_emit_CGR(buf, r1, R0);
6511          else
6512             return s390_emit_CLGR(buf, r1, R0);
6513 
6514       default:
6515          goto fail;
6516       }
6517    }
6518 
6519    default:
6520       goto fail;
6521    }
6522 
6523  fail:
6524    vpanic("s390_insn_compare_emit");
6525 }
6526 
6527 
6528 static UChar *
s390_insn_mul_emit(UChar * buf,const s390_insn * insn)6529 s390_insn_mul_emit(UChar *buf, const s390_insn *insn)
6530 {
6531    s390_opnd_RMI op2;
6532    UChar r1;
6533    Bool signed_multiply;
6534 
6535    /* The register number identifying the register pair */
6536    r1  = hregNumber(insn->variant.mul.dst_hi);
6537 
6538    op2 = insn->variant.mul.op2;
6539    signed_multiply = insn->variant.mul.signed_multiply;
6540 
6541    switch (op2.tag) {
6542    case S390_OPND_REG: {
6543       UInt r2 = hregNumber(op2.variant.reg);
6544 
6545       switch (insn->size) {
6546       case 1:
6547       case 2:
6548       case 4:
6549          if (signed_multiply)
6550             return s390_emit_MR(buf, r1, r2);
6551          else
6552             return s390_emit_MLR(buf, r1, r2);
6553 
6554       case 8:
6555          if (signed_multiply)
6556             vpanic("s390_insn_mul_emit");
6557          else
6558             return s390_emit_MLGR(buf, r1, r2);
6559 
6560       default:
6561          goto fail;
6562       }
6563    }
6564 
6565    case S390_OPND_AMODE: {
6566       const s390_amode *am = op2.variant.am;
6567       UChar b = hregNumber(am->b);
6568       UChar x = hregNumber(am->x);
6569       Int   d = am->d;
6570 
6571       switch (insn->size) {
6572       case 1:
6573       case 2:
6574          /* Load bytes into scratch register R0, then multiply */
6575          buf = s390_emit_load_mem(buf, insn->size, R0, am);
6576          if (signed_multiply)
6577             return s390_emit_MR(buf, r1, R0);
6578          else
6579             return s390_emit_MLR(buf, r1, R0);
6580 
6581       case 4:
6582          switch (am->tag) {
6583          case S390_AMODE_B12:
6584          case S390_AMODE_BX12:
6585             if (signed_multiply)
6586                return s390_emit_M(buf, r1, x, b, d);
6587             else
6588                return s390_emit_ML(buf, r1, x, b, DISP20(d));
6589 
6590          case S390_AMODE_B20:
6591          case S390_AMODE_BX20:
6592             if (signed_multiply)
6593                return s390_emit_MFYw(buf, r1, x, b, DISP20(d));
6594             else
6595                return s390_emit_ML(buf, r1, x, b, DISP20(d));
6596          }
6597          goto fail;
6598 
6599       case 8:
6600          if (signed_multiply)
6601             vpanic("s390_insn_mul_emit");
6602          else
6603             return s390_emit_MLG(buf, r1, x, b, DISP20(d));
6604 
6605       default:
6606          goto fail;
6607       }
6608    }
6609 
6610    case S390_OPND_IMMEDIATE: {
6611       ULong value = op2.variant.imm;
6612 
6613       switch (insn->size) {
6614       case 1:
6615       case 2:
6616       case 4:
6617          buf = s390_emit_load_32imm(buf, R0, value);
6618          if (signed_multiply)
6619             return s390_emit_MR(buf, r1, R0);
6620          else
6621             return s390_emit_MLR(buf, r1, R0);
6622 
6623       case 8:
6624          buf = s390_emit_load_64imm(buf, R0, value);
6625          if (signed_multiply)
6626             vpanic("s390_insn_mul_emit");
6627          else
6628             return s390_emit_MLGR(buf, r1, R0);
6629 
6630       default:
6631          goto fail;
6632       }
6633    }
6634 
6635    default:
6636       goto fail;
6637    }
6638 
6639  fail:
6640    vpanic("s390_insn_mul_emit");
6641 }
6642 
6643 
6644 static UChar *
s390_insn_div_emit(UChar * buf,const s390_insn * insn)6645 s390_insn_div_emit(UChar *buf, const s390_insn *insn)
6646 {
6647    s390_opnd_RMI op2;
6648    UChar r1;
6649    Bool signed_divide;
6650 
6651    r1  = hregNumber(insn->variant.div.op1_hi);
6652    op2 = insn->variant.div.op2;
6653    signed_divide = insn->variant.div.signed_divide;
6654 
6655    switch (op2.tag) {
6656    case S390_OPND_REG: {
6657       UInt r2 = hregNumber(op2.variant.reg);
6658 
6659       switch (insn->size) {
6660       case 4:
6661          if (signed_divide)
6662             return s390_emit_DR(buf, r1, r2);
6663          else
6664             return s390_emit_DLR(buf, r1, r2);
6665 
6666       case 8:
6667          if (signed_divide)
6668             vpanic("s390_insn_div_emit");
6669          else
6670             return s390_emit_DLGR(buf, r1, r2);
6671 
6672       default:
6673          goto fail;
6674       }
6675    }
6676 
6677    case S390_OPND_AMODE: {
6678       const s390_amode *am = op2.variant.am;
6679       UChar b = hregNumber(am->b);
6680       UChar x = hregNumber(am->x);
6681       Int   d = am->d;
6682 
6683       switch (insn->size) {
6684       case 4:
6685          switch (am->tag) {
6686          case S390_AMODE_B12:
6687          case S390_AMODE_BX12:
6688             if (signed_divide)
6689                return s390_emit_D(buf, r1, x, b, d);
6690             else
6691                return s390_emit_DL(buf, r1, x, b, DISP20(d));
6692 
6693          case S390_AMODE_B20:
6694          case S390_AMODE_BX20:
6695             if (signed_divide) {
6696                buf = s390_emit_LY(buf, R0, x, b, DISP20(d));
6697                return s390_emit_DR(buf, r1, R0);
6698             } else
6699                return s390_emit_DL(buf, r1, x, b, DISP20(d));
6700          }
6701          goto fail;
6702 
6703       case 8:
6704          if (signed_divide)
6705             vpanic("s390_insn_div_emit");
6706          else
6707             return s390_emit_DLG(buf, r1, x, b, DISP20(d));
6708 
6709       default:
6710          goto fail;
6711       }
6712    }
6713 
6714    case S390_OPND_IMMEDIATE: {
6715       ULong value = op2.variant.imm;
6716 
6717       switch (insn->size) {
6718       case 4:
6719          buf = s390_emit_load_32imm(buf, R0, value);
6720          if (signed_divide)
6721             return s390_emit_DR(buf, r1, R0);
6722          else
6723             return s390_emit_DLR(buf, r1, R0);
6724 
6725       case 8:
6726          buf = s390_emit_load_64imm(buf, R0, value);
6727          if (signed_divide)
6728             vpanic("s390_insn_div_emit");
6729          else
6730             return s390_emit_DLGR(buf, r1, R0);
6731 
6732       default:
6733          goto fail;
6734       }
6735    }
6736 
6737    default:
6738       goto fail;
6739    }
6740 
6741  fail:
6742    vpanic("s390_insn_div_emit");
6743 }
6744 
6745 
6746 static UChar *
s390_insn_divs_emit(UChar * buf,const s390_insn * insn)6747 s390_insn_divs_emit(UChar *buf, const s390_insn *insn)
6748 {
6749    s390_opnd_RMI op2;
6750    UChar r1;
6751 
6752    r1  = hregNumber(insn->variant.divs.rem);
6753    op2 = insn->variant.divs.op2;
6754 
6755    switch (op2.tag) {
6756    case S390_OPND_REG: {
6757       UInt r2 = hregNumber(op2.variant.reg);
6758 
6759       return s390_emit_DSGR(buf, r1, r2);
6760    }
6761 
6762    case S390_OPND_AMODE: {
6763       const s390_amode *am = op2.variant.am;
6764       UChar b = hregNumber(am->b);
6765       UChar x = hregNumber(am->x);
6766       Int   d = am->d;
6767 
6768       return s390_emit_DSG(buf, r1, x, b, DISP20(d));
6769    }
6770 
6771    case S390_OPND_IMMEDIATE: {
6772       ULong value = op2.variant.imm;
6773 
6774       buf = s390_emit_load_64imm(buf, R0, value);
6775       return s390_emit_DSGR(buf, r1, R0);
6776    }
6777 
6778    default:
6779       goto fail;
6780    }
6781 
6782  fail:
6783    vpanic("s390_insn_divs_emit");
6784 }
6785 
6786 
6787 static UChar *
s390_insn_clz_emit(UChar * buf,const s390_insn * insn)6788 s390_insn_clz_emit(UChar *buf, const s390_insn *insn)
6789 {
6790    s390_opnd_RMI src;
6791    UChar r1, r1p1, r2, *p;
6792 
6793    r1   = hregNumber(insn->variant.clz.num_bits);
6794    r1p1 = hregNumber(insn->variant.clz.clobber);
6795 
6796    vassert((r1 & 0x1) == 0);
6797    vassert(r1p1 == r1 + 1);
6798 
6799    p = buf;
6800    src = insn->variant.clz.src;
6801 
6802    /* Get operand and move it to r2 */
6803    switch (src.tag) {
6804    case S390_OPND_REG:
6805       r2 = hregNumber(src.variant.reg);
6806       break;
6807 
6808    case S390_OPND_AMODE: {
6809       const s390_amode *am = src.variant.am;
6810       UChar b = hregNumber(am->b);
6811       UChar x = hregNumber(am->x);
6812       Int   d = am->d;
6813 
6814       p  = s390_emit_LG(p, R0, x, b, DISP20(d));
6815       r2 = R0;
6816       break;
6817    }
6818 
6819    case S390_OPND_IMMEDIATE: {
6820       ULong value = src.variant.imm;
6821 
6822       p  = s390_emit_load_64imm(p, R0, value);
6823       r2 = R0;
6824       break;
6825    }
6826 
6827    default:
6828       goto fail;
6829    }
6830 
6831    /* Use FLOGR if you can */
6832    if (s390_host_has_eimm) {
6833       return s390_emit_FLOGR(p, r1, r2);
6834    }
6835 
6836    /*
6837       r0 = r2;
6838       r1 = 64;
6839       while (r0 != 0) {
6840         r1 -= 1;
6841         r0 >>= 1;
6842       }
6843    */
6844    p = s390_emit_LTGR(p, R0, r2);
6845    p = s390_emit_LLILL(p, r1,  64);
6846 
6847    p = s390_emit_BRC(p, S390_CC_E, (4 + 4 + 6 + 4 + 4)/ 2);  /* 4 bytes */
6848    p = s390_emit_AGHI(p, r1, (UShort)-1);         /* r1  -= 1;  4 bytes */
6849    p = s390_emit_SRLG(p, R0, R0, R0, DISP20(1));  /* r0 >>= 1;  6 bytes */
6850    p = s390_emit_LTGR(p, R0, R0);                 /* set cc     4 bytes */
6851    p = s390_emit_BRC(p, S390_CC_NE,               /*            4 bytes */
6852                      (UShort)(-(4 + 6 + 4) / 2));
6853    return p;
6854 
6855  fail:
6856    vpanic("s390_insn_clz_emit");
6857 }
6858 
6859 
6860 static UChar *
s390_insn_helper_call_emit(UChar * buf,const s390_insn * insn)6861 s390_insn_helper_call_emit(UChar *buf, const s390_insn *insn)
6862 {
6863    s390_cc_t cond;
6864    ULong target;
6865    UChar *ptmp = buf;
6866 
6867    cond = insn->variant.helper_call.cond;
6868    target = insn->variant.helper_call.target;
6869 
6870    if (cond != S390_CC_ALWAYS) {
6871       /* So we have something like this
6872          if (cond) call X;
6873          Y: ...
6874          We convert this into
6875          if (! cond) goto Y;        // BRC opcode; 4 bytes
6876          call X;
6877          Y:
6878       */
6879       /* 4 bytes (a BRC insn) to be filled in here */
6880       buf += 4;
6881    }
6882 
6883    /* Load the target address into a register, that
6884       (a) is not used for passing parameters to the helper and
6885       (b) can be clobbered by the callee
6886       (c) is not special to the BASR insn
6887       r1 is the only choice.
6888       Also, need to arrange for the return address be put into the
6889       link-register */
6890    buf = s390_emit_load_64imm(buf, 1, target);
6891 
6892    /* Stash away the client's FPC register because the helper might change it. */
6893    buf = s390_emit_STFPC(buf, S390_REGNO_STACK_POINTER, S390_OFFSET_SAVED_FPC_C);
6894 
6895    /* Before we can call the helper, we need to save the link register,
6896       because the BASR will overwrite it. We cannot use a register for that.
6897       (a) Volatile registers will be modified by the helper.
6898       (b) For saved registers the client code assumes that they have not
6899           changed after the function returns. So we cannot use it to store
6900           the link register.
6901       In the dispatcher, before calling the client code, we have arranged for
6902       a location on the stack for this purpose. See dispatch-s390x-linux.S. */
6903    buf = s390_emit_STG(buf, S390_REGNO_LINK_REGISTER, 0,        // save LR
6904                        S390_REGNO_STACK_POINTER, S390_OFFSET_SAVED_LR, 0);
6905    buf = s390_emit_BASR(buf, S390_REGNO_LINK_REGISTER, 1);      // call helper
6906 
6907    /* Move the return value to the destination register */
6908    if (insn->variant.helper_call.dst != INVALID_HREG) {
6909       buf = s390_emit_LGR(buf, hregNumber(insn->variant.helper_call.dst),
6910                           S390_REGNO_RETURN_VALUE);
6911    }
6912 
6913    buf = s390_emit_LG(buf, S390_REGNO_LINK_REGISTER, 0,         // restore LR
6914                       S390_REGNO_STACK_POINTER, S390_OFFSET_SAVED_LR, 0);
6915    buf = s390_emit_LFPC(buf, S390_REGNO_STACK_POINTER,          // restore FPC
6916                         S390_OFFSET_SAVED_FPC_C);
6917 
6918    if (cond != S390_CC_ALWAYS) {
6919       Int delta = buf - ptmp;
6920 
6921       delta >>= 1;  /* immediate constant is #half-words */
6922       vassert(delta > 0 && delta < (1 << 16));
6923       s390_emit_BRC(ptmp, s390_cc_invert(cond), delta);
6924    }
6925 
6926    return buf;
6927 }
6928 
6929 
6930 static UChar *
s390_insn_cond_move_emit(UChar * buf,const s390_insn * insn)6931 s390_insn_cond_move_emit(UChar *buf, const s390_insn *insn)
6932 {
6933    HReg dst;
6934    s390_opnd_RMI src;
6935    s390_cc_t cond;
6936    UChar *p, *ptmp = 0;   /* avoid compiler warnings */
6937 
6938    cond = insn->variant.cond_move.cond;
6939    dst  = insn->variant.cond_move.dst;
6940    src  = insn->variant.cond_move.src;
6941 
6942    p = buf;
6943 
6944    /* Branch (if cond fails) over move instrs */
6945    if (cond != S390_CC_ALWAYS) {
6946       /* Don't know how many bytes to jump over yet.
6947          Make space for a BRC instruction (4 bytes) and fill in later. */
6948       ptmp = p;   /*  to be filled in here */
6949       p += 4;
6950    }
6951 
6952    // cond true: move src => dst
6953 
6954    switch (src.tag) {
6955    case S390_OPND_REG:
6956       p = s390_emit_LGR(p, hregNumber(dst), hregNumber(src.variant.reg));
6957       break;
6958 
6959    case S390_OPND_AMODE:
6960       p = s390_emit_load_mem(p, insn->size, hregNumber(dst), src.variant.am);
6961       break;
6962 
6963    case S390_OPND_IMMEDIATE: {
6964       ULong value = src.variant.imm;
6965       UInt  r = hregNumber(dst);
6966 
6967       switch (insn->size) {
6968       case 1:
6969       case 2:
6970          /* Load the immediate values as a 4 byte value. That does not hurt as
6971             those extra bytes will not be looked at. Fall through .... */
6972       case 4:
6973          p = s390_emit_load_32imm(p, r, value);
6974          break;
6975 
6976       case 8:
6977          p = s390_emit_load_64imm(p, r, value);
6978          break;
6979       }
6980       break;
6981    }
6982 
6983    default:
6984       goto fail;
6985    }
6986 
6987    if (cond != S390_CC_ALWAYS) {
6988       Int delta = p - ptmp;
6989 
6990       delta >>= 1;  /* immediate constant is #half-words */
6991       vassert(delta > 0 && delta < (1 << 16));
6992       s390_emit_BRC(ptmp, s390_cc_invert(cond), delta);
6993    }
6994 
6995    return p;
6996 
6997  fail:
6998    vpanic("s390_insn_cond_move_emit");
6999 }
7000 
7001 
7002 /* Little helper function to the rounding mode in the real FPC
7003    register */
7004 static UChar *
s390_set_fpc_rounding_mode(UChar * buf,s390_round_t rounding_mode)7005 s390_set_fpc_rounding_mode(UChar *buf, s390_round_t rounding_mode)
7006 {
7007    UChar bits;
7008 
7009    /* Determine BFP rounding bits */
7010    switch (rounding_mode) {
7011    case S390_ROUND_NEAREST_EVEN: bits = 0; break;
7012    case S390_ROUND_ZERO:         bits = 1; break;
7013    case S390_ROUND_POSINF:       bits = 2; break;
7014    case S390_ROUND_NEGINF:       bits = 3; break;
7015    default: vpanic("invalid rounding mode\n");
7016    }
7017 
7018    /* Copy FPC from guest state to R0 and OR in the new rounding mode */
7019    buf = s390_emit_L(buf, R0, 0, S390_REGNO_GUEST_STATE_POINTER,
7020                      S390X_GUEST_OFFSET(guest_fpc));   // r0 = guest_fpc
7021 
7022    buf = s390_emit_NILL(buf, R0, 0xFFFC); /* Clear out right-most 2 bits */
7023    buf = s390_emit_OILL(buf, R0, bits);   /* OR in the new rounding mode */
7024    buf = s390_emit_SFPC(buf, R0, 0);      /* Load FPC register from R0 */
7025 
7026    return buf;
7027 }
7028 
7029 
7030 static UChar *
s390_insn_bfp_triop_emit(UChar * buf,const s390_insn * insn)7031 s390_insn_bfp_triop_emit(UChar *buf, const s390_insn *insn)
7032 {
7033    UInt r1 = hregNumber(insn->variant.bfp_triop.dst);
7034    UInt r2 = hregNumber(insn->variant.bfp_triop.op2);
7035    UInt r3 = hregNumber(insn->variant.bfp_triop.op3);
7036    s390_round_t rounding_mode = insn->variant.bfp_triop.rounding_mode;
7037 
7038    if (rounding_mode != S390_ROUND_NEAREST_EVEN) {
7039       buf = s390_set_fpc_rounding_mode(buf, rounding_mode);
7040    }
7041 
7042    switch (insn->size) {
7043    case 4:
7044       switch (insn->variant.bfp_triop.tag) {
7045       case S390_BFP_MADD:  buf = s390_emit_MAEBR(buf, r1, r3, r2); break;
7046       case S390_BFP_MSUB:  buf = s390_emit_MSEBR(buf, r1, r3, r2); break;
7047       default:  goto fail;
7048       }
7049       break;
7050 
7051    case 8:
7052       switch (insn->variant.bfp_triop.tag) {
7053       case S390_BFP_MADD:  buf = s390_emit_MADBR(buf, r1, r3, r2); break;
7054       case S390_BFP_MSUB:  buf = s390_emit_MSDBR(buf, r1, r3, r2); break;
7055       default:  goto fail;
7056       }
7057       break;
7058 
7059    default:  goto fail;
7060    }
7061 
7062    if (rounding_mode != S390_ROUND_NEAREST_EVEN) {
7063       /* Restore FPC register from guest state */
7064       buf = s390_emit_LFPC(buf, S390_REGNO_GUEST_STATE_POINTER,
7065                            S390X_GUEST_OFFSET(guest_fpc));   // fpc = guest_fpc
7066    }
7067    return buf;
7068 
7069  fail:
7070    vpanic("s390_insn_bfp_triop_emit");
7071 }
7072 
7073 
7074 static UChar *
s390_insn_bfp_binop_emit(UChar * buf,const s390_insn * insn)7075 s390_insn_bfp_binop_emit(UChar *buf, const s390_insn *insn)
7076 {
7077    UInt r1 = hregNumber(insn->variant.bfp_binop.dst);
7078    UInt r2 = hregNumber(insn->variant.bfp_binop.op2);
7079    s390_round_t rounding_mode = insn->variant.bfp_binop.rounding_mode;
7080 
7081    if (rounding_mode != S390_ROUND_NEAREST_EVEN) {
7082       buf = s390_set_fpc_rounding_mode(buf, rounding_mode);
7083    }
7084 
7085    switch (insn->size) {
7086    case 4:
7087       switch (insn->variant.bfp_binop.tag) {
7088       case S390_BFP_ADD:     buf = s390_emit_AEBR(buf, r1, r2);  break;
7089       case S390_BFP_SUB:     buf = s390_emit_SEBR(buf, r1, r2);  break;
7090       case S390_BFP_MUL:     buf = s390_emit_MEEBR(buf, r1, r2); break;
7091       case S390_BFP_DIV:     buf = s390_emit_DEBR(buf, r1, r2);  break;
7092       default:  goto fail;
7093       }
7094       break;
7095 
7096    case 8:
7097       switch (insn->variant.bfp_binop.tag) {
7098       case S390_BFP_ADD:     buf = s390_emit_ADBR(buf, r1, r2); break;
7099       case S390_BFP_SUB:     buf = s390_emit_SDBR(buf, r1, r2); break;
7100       case S390_BFP_MUL:     buf = s390_emit_MDBR(buf, r1, r2); break;
7101       case S390_BFP_DIV:     buf = s390_emit_DDBR(buf, r1, r2); break;
7102       default:  goto fail;
7103       }
7104       break;
7105 
7106    default:  goto fail;
7107    }
7108 
7109    if (rounding_mode != S390_ROUND_NEAREST_EVEN) {
7110       /* Restore FPC register from guest state */
7111       buf = s390_emit_LFPC(buf, S390_REGNO_GUEST_STATE_POINTER,
7112                            S390X_GUEST_OFFSET(guest_fpc));
7113    }
7114    return buf;
7115 
7116  fail:
7117    vpanic("s390_insn_bfp_binop_emit");
7118 }
7119 
7120 
7121 static UChar *
s390_insn_bfp_unop_emit(UChar * buf,const s390_insn * insn)7122 s390_insn_bfp_unop_emit(UChar *buf, const s390_insn *insn)
7123 {
7124    UInt  r1 = hregNumber(insn->variant.bfp_unop.dst);
7125    UInt  r2 = hregNumber(insn->variant.bfp_unop.op);
7126    s390_round_t rounding_mode = insn->variant.bfp_unop.rounding_mode;
7127    s390_round_t m3 = rounding_mode;
7128 
7129    /* The "convert to fixed" instructions have a field for the rounding
7130       mode and no FPC modification is necessary. So we handle them
7131       upfront. */
7132    switch (insn->variant.bfp_unop.tag) {
7133    case S390_BFP_F32_TO_I32:  return s390_emit_CFEBR(buf, m3, r1, r2);
7134    case S390_BFP_F64_TO_I32:  return s390_emit_CFDBR(buf, m3, r1, r2);
7135    case S390_BFP_F32_TO_I64:  return s390_emit_CGEBR(buf, m3, r1, r2);
7136    case S390_BFP_F64_TO_I64:  return s390_emit_CGDBR(buf, m3, r1, r2);
7137    default: break;
7138    }
7139 
7140    /* For all other insns if a special rounding mode is requested,
7141       we need to set the FPC first and restore it later. */
7142    if (rounding_mode != S390_ROUND_NEAREST_EVEN) {
7143       buf = s390_set_fpc_rounding_mode(buf, rounding_mode);
7144    }
7145 
7146    switch (insn->variant.bfp_unop.tag) {
7147    case S390_BFP_ABS:
7148       switch (insn->size) {
7149       case 4:   buf = s390_emit_LPEBR(buf, r1, r2); break;
7150       case 8:   buf = s390_emit_LPDBR(buf, r1, r2); break;
7151       case 16:  buf = s390_emit_LPXBR(buf, r1, r2); break;
7152       default:  goto fail;
7153       }
7154       break;
7155 
7156    case S390_BFP_NABS:
7157       switch (insn->size) {
7158       case 4:   buf = s390_emit_LNEBR(buf, r1, r2); break;
7159       case 8:   buf = s390_emit_LNDBR(buf, r1, r2); break;
7160       case 16:  buf = s390_emit_LNXBR(buf, r1, r2); break;
7161       default:  goto fail;
7162       }
7163       break;
7164 
7165    case S390_BFP_NEG:
7166       switch (insn->size) {
7167       case 4:   buf = s390_emit_LCEBR(buf, r1, r2); break;
7168       case 8:   buf = s390_emit_LCDBR(buf, r1, r2); break;
7169       case 16:  buf = s390_emit_LCXBR(buf, r1, r2); break;
7170       default:  goto fail;
7171       }
7172       break;
7173 
7174    case S390_BFP_SQRT:
7175       switch (insn->size) {
7176       case 4:   buf = s390_emit_SQEBR(buf, r1, r2); break;
7177       case 8:   buf = s390_emit_SQDBR(buf, r1, r2); break;
7178       case 16:  buf = s390_emit_SQXBR(buf, r1, r2); break;
7179       default:  goto fail;
7180       }
7181       break;
7182 
7183    case S390_BFP_I32_TO_F32:  buf = s390_emit_CEFBR(buf, r1, r2); break;
7184    case S390_BFP_I32_TO_F64:  buf = s390_emit_CDFBR(buf, r1, r2); break;
7185    case S390_BFP_I32_TO_F128: buf = s390_emit_CXFBR(buf, r1, r2); break;
7186    case S390_BFP_I64_TO_F32:  buf = s390_emit_CEGBR(buf, r1, r2); break;
7187    case S390_BFP_I64_TO_F64:  buf = s390_emit_CDGBR(buf, r1, r2); break;
7188    case S390_BFP_I64_TO_F128: buf = s390_emit_CXGBR(buf, r1, r2); break;
7189 
7190    case S390_BFP_F32_TO_F64:  buf = s390_emit_LDEBR(buf, r1, r2); break;
7191    case S390_BFP_F32_TO_F128: buf = s390_emit_LXEBR(buf, r1, r2); break;
7192    case S390_BFP_F64_TO_F32:  buf = s390_emit_LEDBR(buf, r1, r2); break;
7193    case S390_BFP_F64_TO_F128: buf = s390_emit_LXDBR(buf, r1, r2); break;
7194 
7195    default: goto fail;
7196    }
7197 
7198    if (rounding_mode != S390_ROUND_NEAREST_EVEN) {
7199       /* Restore FPC register from guest state */
7200       buf = s390_emit_LFPC(buf, S390_REGNO_GUEST_STATE_POINTER,
7201                            S390X_GUEST_OFFSET(guest_fpc));   // fpc = guest_fpc
7202    }
7203    return buf;
7204 
7205  fail:
7206    vpanic("s390_insn_bfp_unop_emit");
7207 }
7208 
7209 
7210 static UChar *
s390_insn_bfp_compare_emit(UChar * buf,const s390_insn * insn)7211 s390_insn_bfp_compare_emit(UChar *buf, const s390_insn *insn)
7212 {
7213    UInt dst = hregNumber(insn->variant.bfp_compare.dst);
7214    UInt r1  = hregNumber(insn->variant.bfp_compare.op1);
7215    UInt r2  = hregNumber(insn->variant.bfp_compare.op2);
7216 
7217    switch (insn->size) {
7218    case 4:
7219       buf = s390_emit_CEBR(buf, r1, r2);
7220       break;
7221 
7222    case 8:
7223       buf = s390_emit_CDBR(buf, r1, r2);
7224       break;
7225 
7226    default:  goto fail;
7227    }
7228 
7229    return s390_emit_load_cc(buf, dst);  /* Load condition code into DST */
7230 
7231  fail:
7232    vpanic("s390_insn_bfp_compare_emit");
7233 }
7234 
7235 
7236 static UChar *
s390_insn_bfp128_binop_emit(UChar * buf,const s390_insn * insn)7237 s390_insn_bfp128_binop_emit(UChar *buf, const s390_insn *insn)
7238 {
7239    UInt r1_hi = hregNumber(insn->variant.bfp128_binop.dst_hi);
7240    UInt r1_lo = hregNumber(insn->variant.bfp128_binop.dst_lo);
7241    UInt r2_hi = hregNumber(insn->variant.bfp128_binop.op2_hi);
7242    UInt r2_lo = hregNumber(insn->variant.bfp128_binop.op2_lo);
7243    s390_round_t rounding_mode = insn->variant.bfp_binop.rounding_mode;
7244 
7245    /* Paranoia */
7246    vassert(insn->size == 16);
7247    vassert(r1_lo == r1_hi + 2);
7248    vassert(r2_lo == r2_hi + 2);
7249    vassert((r1_hi & 0x2) == 0);
7250    vassert((r2_hi & 0x2) == 0);
7251 
7252    if (rounding_mode != S390_ROUND_NEAREST_EVEN) {
7253       buf = s390_set_fpc_rounding_mode(buf, rounding_mode);
7254    }
7255 
7256    switch (insn->variant.bfp128_binop.tag) {
7257    case S390_BFP_ADD:     buf = s390_emit_AXBR(buf, r1_hi, r2_hi); break;
7258    case S390_BFP_SUB:     buf = s390_emit_SXBR(buf, r1_hi, r2_hi); break;
7259    case S390_BFP_MUL:     buf = s390_emit_MXBR(buf, r1_hi, r2_hi); break;
7260    case S390_BFP_DIV:     buf = s390_emit_DXBR(buf, r1_hi, r2_hi); break;
7261    default:  goto fail;
7262    }
7263 
7264    if (rounding_mode != S390_ROUND_NEAREST_EVEN) {
7265       /* Restore FPC register from guest state */
7266       buf = s390_emit_LFPC(buf, S390_REGNO_GUEST_STATE_POINTER,
7267                            S390X_GUEST_OFFSET(guest_fpc));   // fpc = guest_fpc
7268    }
7269    return buf;
7270 
7271  fail:
7272    vpanic("s390_insn_bfp128_binop_emit");
7273 }
7274 
7275 
7276 static UChar *
s390_insn_bfp128_compare_emit(UChar * buf,const s390_insn * insn)7277 s390_insn_bfp128_compare_emit(UChar *buf, const s390_insn *insn)
7278 {
7279    UInt dst   = hregNumber(insn->variant.bfp128_compare.dst);
7280    UInt r1_hi = hregNumber(insn->variant.bfp128_compare.op1_hi);
7281    UInt r1_lo = hregNumber(insn->variant.bfp128_compare.op1_lo);
7282    UInt r2_hi = hregNumber(insn->variant.bfp128_compare.op2_hi);
7283    UInt r2_lo = hregNumber(insn->variant.bfp128_compare.op2_lo);
7284 
7285    /* Paranoia */
7286    vassert(insn->size == 16);
7287    vassert(r1_lo == r1_hi + 2);
7288    vassert(r2_lo == r2_hi + 2);
7289    vassert((r1_hi & 0x2) == 0);
7290    vassert((r2_hi & 0x2) == 0);
7291 
7292    buf = s390_emit_CXBR(buf, r1_hi, r2_hi);
7293 
7294    /* Load condition code into DST */
7295    return s390_emit_load_cc(buf, dst);
7296 }
7297 
7298 
7299 static UChar *
s390_insn_bfp128_unop_emit(UChar * buf,const s390_insn * insn)7300 s390_insn_bfp128_unop_emit(UChar *buf, const s390_insn *insn)
7301 {
7302    UInt r1_hi = hregNumber(insn->variant.bfp128_unop.dst_hi);
7303    UInt r1_lo = hregNumber(insn->variant.bfp128_unop.dst_lo);
7304    UInt r2_hi = hregNumber(insn->variant.bfp128_unop.op_hi);
7305    UInt r2_lo = hregNumber(insn->variant.bfp128_unop.op_lo);
7306    s390_round_t rounding_mode = insn->variant.bfp_binop.rounding_mode;
7307 
7308    /* Paranoia */
7309    vassert(insn->size == 16);
7310    vassert(r1_lo == r1_hi + 2);
7311    vassert(r2_lo == r2_hi + 2);
7312    vassert((r1_hi & 0x2) == 0);
7313    vassert((r2_hi & 0x2) == 0);
7314 
7315    if (rounding_mode != S390_ROUND_NEAREST_EVEN) {
7316       buf = s390_set_fpc_rounding_mode(buf, rounding_mode);
7317    }
7318 
7319    switch (insn->variant.bfp128_unop.tag) {
7320    case S390_BFP_ABS:         buf = s390_emit_LPXBR(buf, r1_hi, r2_hi); break;
7321    case S390_BFP_NABS:        buf = s390_emit_LNXBR(buf, r1_hi, r2_hi); break;
7322    case S390_BFP_NEG:         buf = s390_emit_LCXBR(buf, r1_hi, r2_hi); break;
7323    case S390_BFP_SQRT:        buf = s390_emit_SQXBR(buf, r1_hi, r2_hi); break;
7324    case S390_BFP_F128_TO_F32: buf = s390_emit_LEXBR(buf, r1_hi, r2_hi); break;
7325    case S390_BFP_F128_TO_F64: buf = s390_emit_LDXBR(buf, r1_hi, r2_hi); break;
7326    default:  goto fail;
7327    }
7328 
7329    if (rounding_mode != S390_ROUND_NEAREST_EVEN) {
7330       /* Restore FPC register from guest state */
7331       buf = s390_emit_LFPC(buf, S390_REGNO_GUEST_STATE_POINTER,
7332                            S390X_GUEST_OFFSET(guest_fpc));   // fpc = guest_fpc
7333    }
7334    return buf;
7335 
7336  fail:
7337    vpanic("s390_insn_bfp128_unop_emit");
7338 }
7339 
7340 
7341 /* Conversion to 128-bit BFP does not require a rounding mode */
7342 static UChar *
s390_insn_bfp128_convert_to_emit(UChar * buf,const s390_insn * insn)7343 s390_insn_bfp128_convert_to_emit(UChar *buf, const s390_insn *insn)
7344 {
7345    UInt r1_hi = hregNumber(insn->variant.bfp128_unop.dst_hi);
7346    UInt r1_lo = hregNumber(insn->variant.bfp128_unop.dst_lo);
7347    UInt r2    = hregNumber(insn->variant.bfp128_unop.op_hi);
7348 
7349    /* Paranoia */
7350    vassert(insn->size == 16);
7351    vassert(r1_lo == r1_hi + 2);
7352    vassert((r1_hi & 0x2) == 0);
7353 
7354    switch (insn->variant.bfp128_unop.tag) {
7355    case S390_BFP_I32_TO_F128: buf = s390_emit_CXFBR(buf, r1_hi, r2); break;
7356    case S390_BFP_I64_TO_F128: buf = s390_emit_CXGBR(buf, r1_hi, r2); break;
7357    case S390_BFP_F32_TO_F128: buf = s390_emit_LXEBR(buf, r1_hi, r2); break;
7358    case S390_BFP_F64_TO_F128: buf = s390_emit_LXDBR(buf, r1_hi, r2); break;
7359    default:  goto fail;
7360    }
7361 
7362    return buf;
7363 
7364  fail:
7365    vpanic("s390_insn_bfp128_convert_to_emit");
7366 }
7367 
7368 
7369 static UChar *
s390_insn_bfp128_convert_from_emit(UChar * buf,const s390_insn * insn)7370 s390_insn_bfp128_convert_from_emit(UChar *buf, const s390_insn *insn)
7371 {
7372    UInt r1    = hregNumber(insn->variant.bfp128_unop.dst_hi);
7373    UInt r2_hi = hregNumber(insn->variant.bfp128_unop.op_hi);
7374    UInt r2_lo = hregNumber(insn->variant.bfp128_unop.op_lo);
7375    s390_round_t rounding_mode = insn->variant.bfp128_unop.rounding_mode;
7376 
7377    /* Paranoia */
7378    vassert(insn->size != 16);
7379    vassert(r2_lo == r2_hi + 2);
7380    vassert((r2_hi & 0x2) == 0);
7381 
7382    /* The "convert to fixed" instructions have a field for the rounding
7383       mode and no FPC modification is necessary. So we handle them
7384       upfront. */
7385    switch (insn->variant.bfp_unop.tag) {
7386    case S390_BFP_F128_TO_I32:
7387       return s390_emit_CFXBR(buf, rounding_mode, r1, r2_hi);
7388 
7389    case S390_BFP_F128_TO_I64:
7390       return s390_emit_CGXBR(buf, rounding_mode, r1, r2_hi);
7391 
7392    default: break;
7393    }
7394 
7395    vpanic("s390_insn_bfp128_convert_from_emit");
7396 }
7397 
7398 
7399 static UChar *
s390_insn_mfence_emit(UChar * buf,const s390_insn * insn)7400 s390_insn_mfence_emit(UChar *buf, const s390_insn *insn)
7401 {
7402    return s390_emit_BCR(buf, 0xF, 0x0);
7403 }
7404 
7405 
7406 static UChar *
s390_insn_gzero_emit(UChar * buf,const s390_insn * insn)7407 s390_insn_gzero_emit(UChar *buf, const s390_insn *insn)
7408 {
7409    return s390_emit_XC(buf, insn->size - 1,
7410                        S390_REGNO_GUEST_STATE_POINTER, insn->variant.gzero.offset,
7411                        S390_REGNO_GUEST_STATE_POINTER, insn->variant.gzero.offset);
7412 }
7413 
7414 
7415 static UChar *
s390_insn_gadd_emit(UChar * buf,const s390_insn * insn)7416 s390_insn_gadd_emit(UChar *buf, const s390_insn *insn)
7417 {
7418    return s390_emit_AGSI(buf, insn->variant.gadd.delta,
7419                          S390_REGNO_GUEST_STATE_POINTER,
7420                          DISP20(insn->variant.gadd.offset));
7421 }
7422 
7423 
7424 /* Define convenience functions needed for translation chaining.
7425    Any changes need to be applied to the functions in concert. */
7426 
7427 static __inline__ Bool
s390_insn_is_BRCL(const UChar * p,UChar condition)7428 s390_insn_is_BRCL(const UChar *p, UChar condition)
7429 {
7430    return p[0] == 0xc0 && p[1] == ((condition << 4) | 0x04);
7431 }
7432 
7433 static __inline__ Bool
s390_insn_is_BR(const UChar * p,UChar reg)7434 s390_insn_is_BR(const UChar *p, UChar reg)
7435 {
7436    return p[0] == 0x07 && p[1] == (0xF0 | reg);  /* BCR 15,reg */
7437 }
7438 
7439 
7440 /* The length of the BASR insn */
7441 #define S390_BASR_LEN  2
7442 
7443 
7444 /* Load the 64-bit VALUE into REG. Note that this function must NOT
7445    optimise the generated code by looking at the value. I.e. using
7446    LGHI if value == 0 would be very wrong. */
7447 static UChar *
s390_tchain_load64(UChar * buf,UChar regno,ULong value)7448 s390_tchain_load64(UChar *buf, UChar regno, ULong value)
7449 {
7450    UChar *begin = buf;
7451 
7452    if (s390_host_has_eimm) {
7453       /* Do it in two steps: upper half [0:31] and lower half [32:63] */
7454       buf = s390_emit_IIHF(buf, regno, value >> 32);
7455       buf = s390_emit_IILF(buf, regno, value & 0xFFFFFFFF);
7456    } else {
7457       buf = s390_emit_IILL(buf, regno, value & 0xFFFF);
7458       value >>= 16;
7459       buf = s390_emit_IILH(buf, regno, value & 0xFFFF);
7460       value >>= 16;
7461       buf = s390_emit_IIHL(buf, regno, value & 0xFFFF);
7462       value >>= 16;
7463       buf = s390_emit_IIHH(buf, regno, value & 0xFFFF);
7464    }
7465 
7466    vassert(buf - begin == s390_tchain_load64_len());
7467 
7468    return buf;
7469 }
7470 
7471 /* Return number of bytes generated by s390_tchain_load64 */
7472 static UInt
s390_tchain_load64_len(void)7473 s390_tchain_load64_len(void)
7474 {
7475    if (s390_host_has_eimm) {
7476       return 6 + 6;      /* IIHF + IILF */
7477    }
7478    return 4 + 4 + 4 + 4; /* IIHH + IIHL + IILH + IILL */
7479 }
7480 
7481 /* Verify that CODE is the code sequence generated by s390_tchain_load64
7482    to load VALUE into REGNO. Return pointer to the byte following the
7483    insn sequence. */
7484 static const UChar *
s390_tchain_verify_load64(const UChar * code,UChar regno,ULong value)7485 s390_tchain_verify_load64(const UChar *code, UChar regno, ULong value)
7486 {
7487    UInt regmask = regno << 4;
7488    UInt hw;
7489 
7490    if (s390_host_has_eimm) {
7491       /* Check for IIHF */
7492       vassert(code[0]  ==  0xC0);
7493       vassert(code[1]  == (0x08 | regmask));
7494       vassert(*(const UInt *)&code[2] == (value >> 32));
7495       /* Check for IILF */
7496       vassert(code[6]  ==  0xC0);
7497       vassert(code[7]  == (0x09 | regmask));
7498       vassert(*(const UInt *)&code[8] == (value & 0xFFFFFFFF));
7499    } else {
7500       /* Check for IILL */
7501       hw = value & 0xFFFF;
7502       vassert(code[0]  ==  0xA5);
7503       vassert(code[1]  == (0x03 | regmask));
7504       vassert(code[2]  == (hw >> 8));
7505       vassert(code[3]  == (hw & 0xFF));
7506 
7507       /* Check for IILH */
7508       hw = (value >> 16) & 0xFFFF;
7509       vassert(code[4]  ==  0xA5);
7510       vassert(code[5]  == (0x02 | regmask));
7511       vassert(code[6]  == (hw >> 8));
7512       vassert(code[7]  == (hw & 0xFF));
7513 
7514       /* Check for IIHL */
7515       hw = (value >> 32) & 0xFFFF;
7516       vassert(code[8]  ==  0xA5);
7517       vassert(code[9]  == (0x01 | regmask));
7518       vassert(code[10] == (hw >> 8));
7519       vassert(code[11] == (hw & 0xFF));
7520 
7521       /* Check for IIHH */
7522       hw = (value >> 48) & 0xFFFF;
7523       vassert(code[12] ==  0xA5);
7524       vassert(code[13] == (0x00 | regmask));
7525       vassert(code[14] == (hw >> 8));
7526       vassert(code[15] == (hw & 0xFF));
7527    }
7528 
7529    return code + s390_tchain_load64_len();
7530 }
7531 
7532 /* CODE points to the code sequence as generated by s390_tchain_load64.
7533    Change the loaded value to VALUE. Return pointer to the byte following
7534    the patched code sequence. */
7535 static UChar *
s390_tchain_patch_load64(UChar * code,ULong imm64)7536 s390_tchain_patch_load64(UChar *code, ULong imm64)
7537 {
7538    if (s390_host_has_eimm) {
7539       /* Patch IIHF */
7540       *(UInt *)&code[2] = imm64 >> 32;
7541       /* Patch IILF */
7542       *(UInt *)&code[8] = imm64 & 0xFFFFFFFF;
7543    } else {
7544       code[3]  = imm64 & 0xFF; imm64 >>= 8;
7545       code[2]  = imm64 & 0xFF; imm64 >>= 8;
7546       code[7]  = imm64 & 0xFF; imm64 >>= 8;
7547       code[6]  = imm64 & 0xFF; imm64 >>= 8;
7548       code[11] = imm64 & 0xFF; imm64 >>= 8;
7549       code[10] = imm64 & 0xFF; imm64 >>= 8;
7550       code[15] = imm64 & 0xFF; imm64 >>= 8;
7551       code[14] = imm64 & 0xFF; imm64 >>= 8;
7552    }
7553 
7554    return code + s390_tchain_load64_len();
7555 }
7556 
7557 
7558 /* NB: what goes on here has to be very closely coordinated with the
7559    chainXDirect_S390 and unchainXDirect_S390 below. */
7560 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)7561 s390_insn_xdirect_emit(UChar *buf, const s390_insn *insn,
7562                        void *disp_cp_chain_me_to_slowEP,
7563                        void *disp_cp_chain_me_to_fastEP)
7564 {
7565    /* We're generating chain-me requests here, so we need to be
7566       sure this is actually allowed -- no-redir translations can't
7567       use chain-me's.  Hence: */
7568    vassert(disp_cp_chain_me_to_slowEP != NULL);
7569    vassert(disp_cp_chain_me_to_fastEP != NULL);
7570 
7571    /* Use ptmp for backpatching conditional jumps. */
7572    UChar *ptmp = buf;
7573 
7574    /* First off, if this is conditional, create a conditional
7575       jump over the rest of it. */
7576    s390_cc_t cond = insn->variant.xdirect.cond;
7577 
7578    if (cond != S390_CC_ALWAYS) {
7579       /* So we have something like this
7580          if (cond) do_xdirect;
7581          Y: ...
7582          We convert this into
7583          if (! cond) goto Y;        // BRC opcode; 4 bytes
7584          do_xdirect;
7585          Y:
7586       */
7587       /* 4 bytes (a BRC insn) to be filled in here */
7588       buf += 4;
7589    }
7590 
7591    /* Update the guest IA. */
7592    buf = s390_emit_load_64imm(buf, R0, insn->variant.xdirect.dst);
7593 
7594    const s390_amode *amode = insn->variant.xdirect.guest_IA;
7595    vassert(amode->tag == S390_AMODE_B12);
7596    UInt b = hregNumber(amode->b);
7597    UInt d = amode->d;
7598 
7599    buf = s390_emit_STG(buf, R0, 0, b, DISP20(d));
7600 
7601    /* Load the chosen entry point into the scratch reg */
7602    void *disp_cp_chain_me;
7603 
7604    disp_cp_chain_me =
7605       insn->variant.xdirect.to_fast_entry ? disp_cp_chain_me_to_fastEP
7606                                           : disp_cp_chain_me_to_slowEP;
7607    /* Get the address of the beginning of the load64 code sequence into %r1.
7608       Do not change the register! This is part of the protocol with the
7609       dispatcher. */
7610    buf = s390_emit_BASR(buf, 1, R0);
7611 
7612    /* --- FIRST PATCHABLE BYTE follows (must not modify %r1) --- */
7613    ULong addr = Ptr_to_ULong(disp_cp_chain_me);
7614    buf = s390_tchain_load64(buf, S390_REGNO_TCHAIN_SCRATCH, addr);
7615 
7616    /* goto *tchain_scratch */
7617    buf = s390_emit_BCR(buf, S390_CC_ALWAYS, S390_REGNO_TCHAIN_SCRATCH);
7618 
7619    /* --- END of PATCHABLE BYTES --- */
7620 
7621    /* Fix up the conditional jump, if there was one. */
7622    if (cond != S390_CC_ALWAYS) {
7623       Int delta = buf - ptmp;
7624 
7625       delta >>= 1;  /* immediate constant is #half-words */
7626       vassert(delta > 0 && delta < (1 << 16));
7627       s390_emit_BRC(ptmp, s390_cc_invert(cond), delta);
7628    }
7629 
7630    return buf;
7631 }
7632 
7633 /* Return the number of patchable bytes from an xdirect insn. */
7634 static UInt
s390_xdirect_patchable_len(void)7635 s390_xdirect_patchable_len(void)
7636 {
7637    return s390_tchain_load64_len() + S390_BASR_LEN;
7638 }
7639 
7640 
7641 static UChar *
s390_insn_xindir_emit(UChar * buf,const s390_insn * insn,void * disp_cp_xindir)7642 s390_insn_xindir_emit(UChar *buf, const s390_insn *insn, void *disp_cp_xindir)
7643 {
7644    /* We're generating transfers that could lead indirectly to a
7645       chain-me, so we need to be sure this is actually allowed --
7646       no-redir translations are not allowed to reach normal
7647       translations without going through the scheduler.  That means
7648       no XDirects or XIndirs out from no-redir translations.
7649       Hence: */
7650    vassert(disp_cp_xindir != NULL);
7651 
7652    /* Use ptmp for backpatching conditional jumps. */
7653    UChar *ptmp = buf;
7654 
7655    /* First off, if this is conditional, create a conditional
7656       jump over the rest of it. */
7657    s390_cc_t cond = insn->variant.xdirect.cond;
7658 
7659    if (cond != S390_CC_ALWAYS) {
7660       /* So we have something like this
7661          if (cond) do_xdirect;
7662          Y: ...
7663          We convert this into
7664          if (! cond) goto Y;        // BRC opcode; 4 bytes
7665          do_xdirect;
7666          Y:
7667       */
7668       /* 4 bytes (a BRC insn) to be filled in here */
7669       buf += 4;
7670    }
7671 
7672    /* Update the guest IA with the address in xdirect.dst. */
7673    const s390_amode *amode = insn->variant.xindir.guest_IA;
7674 
7675    vassert(amode->tag == S390_AMODE_B12);
7676    UInt b = hregNumber(amode->b);
7677    UInt d = amode->d;
7678    UInt regno = hregNumber(insn->variant.xindir.dst);
7679 
7680    buf = s390_emit_STG(buf, regno, 0, b, DISP20(d));
7681 
7682    /* load tchain_scratch, #disp_indir */
7683    buf = s390_tchain_load64(buf, S390_REGNO_TCHAIN_SCRATCH,
7684                             Ptr_to_ULong(disp_cp_xindir));
7685    /* goto *tchain_direct */
7686    buf = s390_emit_BCR(buf, S390_CC_ALWAYS, S390_REGNO_TCHAIN_SCRATCH);
7687 
7688    /* Fix up the conditional jump, if there was one. */
7689    if (cond != S390_CC_ALWAYS) {
7690       Int delta = buf - ptmp;
7691 
7692       delta >>= 1;  /* immediate constant is #half-words */
7693       vassert(delta > 0 && delta < (1 << 16));
7694       s390_emit_BRC(ptmp, s390_cc_invert(cond), delta);
7695    }
7696 
7697    return buf;
7698 }
7699 
7700 static UChar *
s390_insn_xassisted_emit(UChar * buf,const s390_insn * insn,void * disp_cp_xassisted)7701 s390_insn_xassisted_emit(UChar *buf, const s390_insn *insn,
7702                          void *disp_cp_xassisted)
7703 {
7704    /* Use ptmp for backpatching conditional jumps. */
7705    UChar *ptmp = buf;
7706 
7707    /* First off, if this is conditional, create a conditional
7708       jump over the rest of it. */
7709    s390_cc_t cond = insn->variant.xdirect.cond;
7710 
7711    if (cond != S390_CC_ALWAYS) {
7712       /* So we have something like this
7713          if (cond) do_xdirect;
7714          Y: ...
7715          We convert this into
7716          if (! cond) goto Y;        // BRC opcode; 4 bytes
7717          do_xdirect;
7718          Y:
7719       */
7720       /* 4 bytes (a BRC insn) to be filled in here */
7721       buf += 4;
7722    }
7723 
7724    /* Update the guest IA with the address in xassisted.dst. */
7725    const s390_amode *amode = insn->variant.xassisted.guest_IA;
7726 
7727    vassert(amode->tag == S390_AMODE_B12);
7728    UInt b = hregNumber(amode->b);
7729    UInt d = amode->d;
7730    UInt regno = hregNumber(insn->variant.xassisted.dst);
7731 
7732    buf = s390_emit_STG(buf, regno, 0, b, DISP20(d));
7733 
7734    UInt trcval = 0;
7735 
7736    switch (insn->variant.xassisted.kind) {
7737    case Ijk_ClientReq:   trcval = VEX_TRC_JMP_CLIENTREQ;   break;
7738    case Ijk_Sys_syscall: trcval = VEX_TRC_JMP_SYS_SYSCALL; break;
7739    case Ijk_Yield:       trcval = VEX_TRC_JMP_YIELD;       break;
7740    case Ijk_EmWarn:      trcval = VEX_TRC_JMP_EMWARN;      break;
7741    case Ijk_MapFail:     trcval = VEX_TRC_JMP_MAPFAIL;     break;
7742    case Ijk_NoDecode:    trcval = VEX_TRC_JMP_NODECODE;    break;
7743    case Ijk_TInval:      trcval = VEX_TRC_JMP_TINVAL;      break;
7744    case Ijk_NoRedir:     trcval = VEX_TRC_JMP_NOREDIR;     break;
7745    case Ijk_SigTRAP:     trcval = VEX_TRC_JMP_SIGTRAP;     break;
7746    case Ijk_SigSEGV:     trcval = VEX_TRC_JMP_SIGSEGV;     break;
7747    case Ijk_Boring:      trcval = VEX_TRC_JMP_BORING;      break;
7748       /* We don't expect to see the following being assisted. */
7749    case Ijk_Ret:
7750    case Ijk_Call:
7751       /* fallthrough */
7752    default:
7753       ppIRJumpKind(insn->variant.xassisted.kind);
7754       vpanic("s390_insn_xassisted_emit: unexpected jump kind");
7755    }
7756 
7757    vassert(trcval != 0);
7758 
7759    /* guest_state_pointer = trcval */
7760    buf = s390_emit_LGHI(buf, S390_REGNO_GUEST_STATE_POINTER, trcval);
7761 
7762    /* load tchain_scratch, #disp_assisted */
7763    buf = s390_tchain_load64(buf, S390_REGNO_TCHAIN_SCRATCH,
7764                             Ptr_to_ULong(disp_cp_xassisted));
7765 
7766    /* goto *tchain_direct */
7767    buf = s390_emit_BCR(buf, S390_CC_ALWAYS, S390_REGNO_TCHAIN_SCRATCH);
7768 
7769    /* Fix up the conditional jump, if there was one. */
7770    if (cond != S390_CC_ALWAYS) {
7771       Int delta = buf - ptmp;
7772 
7773       delta >>= 1;  /* immediate constant is #half-words */
7774       vassert(delta > 0 && delta < (1 << 16));
7775       s390_emit_BRC(ptmp, s390_cc_invert(cond), delta);
7776    }
7777 
7778    return buf;
7779 }
7780 
7781 
7782 /* Pseudo code:
7783 
7784    guest_state[host_EvC_COUNTER] -= 1;
7785    if (guest_state[host_EvC_COUNTER] >= 0) goto nofail;
7786    goto guest_state[host_EvC_FAILADDR];
7787    nofail: ;
7788 
7789    The dispatch counter is a 32-bit value. */
7790 static UChar *
s390_insn_evcheck_emit(UChar * buf,const s390_insn * insn)7791 s390_insn_evcheck_emit(UChar *buf, const s390_insn *insn)
7792 {
7793    s390_amode *amode;
7794    UInt b, d;
7795    UChar *code_begin, *code_end;
7796 
7797    code_begin = buf;
7798 
7799    amode = insn->variant.evcheck.counter;
7800    vassert(amode->tag == S390_AMODE_B12);
7801    b = hregNumber(amode->b);
7802    d = amode->d;
7803 
7804    /* Decrement the dispatch counter in the guest state */
7805    if (s390_host_has_gie) {
7806       buf = s390_emit_ASI(buf, -1, b, DISP20(d));   /* 6 bytes */
7807    } else {
7808       buf = s390_emit_LHI(buf, R0, -1);             /* 4 bytes */
7809       buf = s390_emit_A(buf, R0, 0, b, d);          /* 4 bytes */
7810       buf = s390_emit_ST(buf, R0, 0, b, d);         /* 4 bytes */
7811    }
7812 
7813    /* Jump over the next insn if >= 0 */
7814    buf = s390_emit_BRC(buf, S390_CC_HE, (4 + 6 + 2) / 2);  /* 4 bytes */
7815 
7816    /* Computed goto to fail_address */
7817    amode = insn->variant.evcheck.fail_addr;
7818    b = hregNumber(amode->b);
7819    d = amode->d;
7820    buf = s390_emit_LG(buf, S390_REGNO_TCHAIN_SCRATCH, 0, b, DISP20(d));  /* 6 bytes */
7821    buf = s390_emit_BCR(buf, S390_CC_ALWAYS, S390_REGNO_TCHAIN_SCRATCH);  /* 2 bytes */
7822 
7823    code_end = buf;
7824 
7825    /* Make sure the size of the generated code is identical to the size
7826       returned by evCheckSzB_S390 */
7827    vassert(evCheckSzB_S390() == code_end - code_begin);
7828 
7829    return buf;
7830 }
7831 
7832 
7833 static UChar *
s390_insn_profinc_emit(UChar * buf,const s390_insn * insn)7834 s390_insn_profinc_emit(UChar *buf,
7835                        const s390_insn *insn __attribute__((unused)))
7836 {
7837    /* Generate a code template to increment a memory location whose
7838       address will be known later as an immediate value. This code
7839       template will be patched once the memory location is known.
7840       For now we do this with address == 0. */
7841    buf = s390_tchain_load64(buf, S390_REGNO_TCHAIN_SCRATCH, 0);
7842    if (s390_host_has_gie) {
7843       buf = s390_emit_AGSI(buf, 1, S390_REGNO_TCHAIN_SCRATCH, DISP20(0));
7844    } else {
7845       buf = s390_emit_LGHI(buf, R0, 1);
7846       buf = s390_emit_AG( buf, R0, 0, S390_REGNO_TCHAIN_SCRATCH, DISP20(0));
7847       buf = s390_emit_STG(buf, R0, 0, S390_REGNO_TCHAIN_SCRATCH, DISP20(0));
7848    }
7849 
7850    return buf;
7851 }
7852 
7853 
7854 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)7855 emit_S390Instr(Bool *is_profinc, UChar *buf, Int nbuf, s390_insn *insn,
7856                Bool mode64, void *disp_cp_chain_me_to_slowEP,
7857                void *disp_cp_chain_me_to_fastEP, void *disp_cp_xindir,
7858                void *disp_cp_xassisted)
7859 {
7860    UChar *end;
7861 
7862    switch (insn->tag) {
7863    case S390_INSN_LOAD:
7864       end = s390_insn_load_emit(buf, insn);
7865       break;
7866 
7867    case S390_INSN_STORE:
7868       end = s390_insn_store_emit(buf, insn);
7869       break;
7870 
7871    case S390_INSN_MOVE:
7872       end = s390_insn_move_emit(buf, insn);
7873       break;
7874 
7875    case S390_INSN_COND_MOVE:
7876       end = s390_insn_cond_move_emit(buf, insn);
7877       break;
7878 
7879    case S390_INSN_LOAD_IMMEDIATE:
7880       end = s390_insn_load_immediate_emit(buf, insn);
7881       break;
7882 
7883    case S390_INSN_ALU:
7884       end = s390_insn_alu_emit(buf, insn);
7885       break;
7886 
7887    case S390_INSN_MUL:
7888       end = s390_insn_mul_emit(buf, insn);
7889       break;
7890 
7891    case S390_INSN_DIV:
7892       end = s390_insn_div_emit(buf, insn);
7893       break;
7894 
7895    case S390_INSN_DIVS:
7896       end = s390_insn_divs_emit(buf, insn);
7897       break;
7898 
7899    case S390_INSN_CLZ:
7900       end = s390_insn_clz_emit(buf, insn);
7901       break;
7902 
7903    case S390_INSN_UNOP:
7904       end = s390_insn_unop_emit(buf, insn);
7905       break;
7906 
7907    case S390_INSN_TEST:
7908       end = s390_insn_test_emit(buf, insn);
7909       break;
7910 
7911    case S390_INSN_CC2BOOL:
7912       end = s390_insn_cc2bool_emit(buf, insn);
7913       break;
7914 
7915    case S390_INSN_CAS:
7916       end = s390_insn_cas_emit(buf, insn);
7917       break;
7918 
7919    case S390_INSN_CDAS:
7920       end = s390_insn_cdas_emit(buf, insn);
7921       break;
7922 
7923    case S390_INSN_COMPARE:
7924       end = s390_insn_compare_emit(buf, insn);
7925       break;
7926 
7927    case S390_INSN_HELPER_CALL:
7928       end = s390_insn_helper_call_emit(buf, insn);
7929       break;
7930 
7931    case S390_INSN_BFP_TRIOP:
7932       end = s390_insn_bfp_triop_emit(buf, insn);
7933       break;
7934 
7935    case S390_INSN_BFP_BINOP:
7936       end = s390_insn_bfp_binop_emit(buf, insn);
7937       break;
7938 
7939    case S390_INSN_BFP_UNOP:
7940       end = s390_insn_bfp_unop_emit(buf, insn);
7941       break;
7942 
7943    case S390_INSN_BFP_COMPARE:
7944       end = s390_insn_bfp_compare_emit(buf, insn);
7945       break;
7946 
7947    case S390_INSN_BFP128_BINOP:
7948       end = s390_insn_bfp128_binop_emit(buf, insn);
7949       break;
7950 
7951    case S390_INSN_BFP128_COMPARE:
7952       end = s390_insn_bfp128_compare_emit(buf, insn);
7953       break;
7954 
7955    case S390_INSN_BFP128_UNOP:
7956       end = s390_insn_bfp128_unop_emit(buf, insn);
7957       break;
7958 
7959    case S390_INSN_BFP128_CONVERT_TO:
7960       end = s390_insn_bfp128_convert_to_emit(buf, insn);
7961       break;
7962 
7963    case S390_INSN_BFP128_CONVERT_FROM:
7964       end = s390_insn_bfp128_convert_from_emit(buf, insn);
7965       break;
7966 
7967    case S390_INSN_MFENCE:
7968       end = s390_insn_mfence_emit(buf, insn);
7969       break;
7970 
7971    case S390_INSN_GZERO:
7972       end = s390_insn_gzero_emit(buf, insn);
7973       break;
7974 
7975    case S390_INSN_GADD:
7976       end = s390_insn_gadd_emit(buf, insn);
7977       break;
7978 
7979    case S390_INSN_PROFINC:
7980       end = s390_insn_profinc_emit(buf, insn);
7981       /* Tell the caller .. */
7982       vassert(*is_profinc == False);
7983       *is_profinc = True;
7984       break;
7985 
7986    case S390_INSN_EVCHECK:
7987       end = s390_insn_evcheck_emit(buf, insn);
7988       break;
7989 
7990    case S390_INSN_XDIRECT:
7991       end = s390_insn_xdirect_emit(buf, insn, disp_cp_chain_me_to_slowEP,
7992                                    disp_cp_chain_me_to_fastEP);
7993       break;
7994 
7995    case S390_INSN_XINDIR:
7996       end = s390_insn_xindir_emit(buf, insn, disp_cp_xindir);
7997       break;
7998 
7999    case S390_INSN_XASSISTED:
8000       end = s390_insn_xassisted_emit(buf, insn, disp_cp_xassisted);
8001       break;
8002 
8003    default:
8004       vpanic("emit_S390Instr");
8005    }
8006 
8007    vassert(end - buf <= nbuf);
8008 
8009    return end - buf;
8010 }
8011 
8012 
8013 /* Return the number of bytes emitted for an S390_INSN_EVCHECK.
8014    See s390_insn_evcheck_emit */
8015 Int
evCheckSzB_S390(void)8016 evCheckSzB_S390(void)
8017 {
8018    return s390_host_has_gie ? 18 : 24;
8019 }
8020 
8021 
8022 /* Patch the counter address into CODE_TO_PATCH as previously
8023    generated by s390_insn_profinc_emit. */
8024 VexInvalRange
patchProfInc_S390(void * code_to_patch,ULong * location_of_counter)8025 patchProfInc_S390(void *code_to_patch, ULong *location_of_counter)
8026 {
8027    vassert(sizeof(ULong *) == 8);
8028 
8029    s390_tchain_verify_load64(code_to_patch, S390_REGNO_TCHAIN_SCRATCH, 0);
8030 
8031    s390_tchain_patch_load64(code_to_patch, Ptr_to_ULong(location_of_counter));
8032 
8033    VexInvalRange vir = {0, 0};
8034    return vir;
8035 }
8036 
8037 
8038 /* NB: what goes on here has to be very closely coordinated with the
8039    s390_insn_xdirect_emit code above. */
8040 VexInvalRange
chainXDirect_S390(void * place_to_chain,void * disp_cp_chain_me_EXPECTED,void * place_to_jump_to)8041 chainXDirect_S390(void *place_to_chain,
8042                   void *disp_cp_chain_me_EXPECTED,
8043                   void *place_to_jump_to)
8044 {
8045    /* What we're expecting to see @ PLACE_TO_CHAIN is:
8046 
8047         load  tchain_scratch, #disp_cp_chain_me_EXPECTED
8048         goto *tchain_scratch
8049    */
8050    const UChar *next;
8051    next = s390_tchain_verify_load64(place_to_chain, S390_REGNO_TCHAIN_SCRATCH,
8052                                     Ptr_to_ULong(disp_cp_chain_me_EXPECTED));
8053    vassert(s390_insn_is_BR(next, S390_REGNO_TCHAIN_SCRATCH));
8054 
8055    /* And what we want to change it to is either:
8056         (general case):
8057 
8058           load  tchain_scratch, #place_to_jump_to
8059           goto *tchain_scratch
8060 
8061       ---OR---
8062 
8063         in the case where the displacement is small enough
8064 
8065           BRCL delta       where delta is in half-words
8066           invalid opcodes
8067 
8068       In both cases the replacement has the same length as the original.
8069       To remain sane & verifiable,
8070       (1) limit the displacement for the short form to
8071           (say) +/- one billion, so as to avoid wraparound
8072           off-by-ones
8073       (2) even if the short form is applicable, once every (say)
8074           1024 times use the long form anyway, so as to maintain
8075           verifiability
8076    */
8077 
8078    /* This is the delta we need to put into a BRCL insn. Note, that the
8079       offset in BRCL is in half-words. Hence division by 2. */
8080    Long delta = (Long)((UChar *)place_to_jump_to - (UChar *)place_to_chain) / 2;
8081    Bool shortOK = delta >= -1000*1000*1000 && delta < 1000*1000*1000;
8082 
8083    static UInt shortCTR = 0; /* DO NOT MAKE NON-STATIC */
8084    if (shortOK) {
8085       shortCTR++; // thread safety bleh
8086       if (0 == (shortCTR & 0x3FF)) {
8087          shortOK = False;
8088          if (0)
8089             vex_printf("QQQ chainXDirect_S390: shortCTR = %u, "
8090                        "using long jmp\n", shortCTR);
8091       }
8092    }
8093 
8094    /* And make the modifications. */
8095    UChar *p = (UChar *)place_to_chain;
8096    if (shortOK) {
8097       p = s390_emit_BRCL(p, S390_CC_ALWAYS, delta);  /* 6 bytes */
8098 
8099       /* Make sure that BRCL fits into the patchable part of an xdirect
8100          code sequence */
8101       vassert(6 <= s390_xdirect_patchable_len());
8102 
8103       /* Fill remaining bytes with 0x00 (invalid opcode) */
8104       Int i;
8105       for (i = 0; i < s390_xdirect_patchable_len() - 6; ++i)
8106          p[i] = 0x00;
8107    } else {
8108       /*
8109           load  tchain_scratch, #place_to_jump_to
8110           goto *tchain_scratch
8111       */
8112       ULong addr = Ptr_to_ULong(place_to_jump_to);
8113       p = s390_tchain_load64(p, S390_REGNO_TCHAIN_SCRATCH, addr);
8114       /* There is not need to emit a BCR here, as it is already there. */
8115    }
8116 
8117    VexInvalRange vir = {0, 0};
8118    return vir;
8119 }
8120 
8121 
8122 /* NB: what goes on here has to be very closely coordinated with the
8123    s390_insn_xdirect_emit code above. */
8124 VexInvalRange
unchainXDirect_S390(void * place_to_unchain,void * place_to_jump_to_EXPECTED,void * disp_cp_chain_me)8125 unchainXDirect_S390(void *place_to_unchain,
8126                     void *place_to_jump_to_EXPECTED,
8127                     void *disp_cp_chain_me)
8128 {
8129    /* What we're expecting to see @ PLACE_TO_UNCHAIN:
8130 
8131           load  tchain_scratch, #place_to_jump_to_EXPECTED
8132           goto *tchain_scratch
8133 
8134       ---OR---
8135         in the case where the displacement falls within 32 bits
8136 
8137           BRCL delta
8138           invalid opcodes
8139    */
8140    UChar *p = place_to_unchain;
8141 
8142    Bool uses_short_form = False;
8143 
8144    if (s390_insn_is_BRCL(p, S390_CC_ALWAYS)) {
8145       /* Looks like the short form */
8146       Int num_hw = *(Int *)&p[2];
8147       Int delta = 2 *num_hw;
8148 
8149       vassert(p + delta == place_to_jump_to_EXPECTED);
8150 
8151       Int i;
8152       for (i = 0; i < s390_xdirect_patchable_len() - 6; ++i)
8153          vassert(p[6+i] == 0x00);
8154       uses_short_form = True;
8155    } else {
8156       /* Should be the long form */
8157       const UChar *next;
8158 
8159       next = s390_tchain_verify_load64(p, S390_REGNO_TCHAIN_SCRATCH,
8160                                        Ptr_to_ULong(place_to_jump_to_EXPECTED));
8161       /* Check for BR *tchain_scratch */
8162       vassert(s390_insn_is_BR(next, S390_REGNO_TCHAIN_SCRATCH));
8163    }
8164 
8165    /* And what we want to change it to is:
8166 
8167         load  tchain_scratch, #disp_cp_chain_me
8168         goto *tchain_scratch
8169    */
8170 
8171    /* Get the address of the beginning of the load64 code sequence into %r1.
8172       Do not change the register! This is part of the protocol with the
8173       dispatcher.
8174       Note: the incoming argument PLACE_TO_CHAIN points to the beginning of the
8175       load64 insn sequence. That sequence is prefixed with a BASR to get its
8176       address (see s390_insn_xdirect_emit).  */
8177    p = s390_emit_BASR(p - S390_BASR_LEN, 1, R0);
8178 
8179    ULong addr = Ptr_to_ULong(disp_cp_chain_me);
8180    p = s390_tchain_load64(p, S390_REGNO_TCHAIN_SCRATCH, addr);
8181 
8182    /* Emit the BCR in case the short form was used. In case of the long
8183       form, the BCR is already there. */
8184    if (uses_short_form)
8185       s390_emit_BCR(p, S390_CC_ALWAYS, S390_REGNO_TCHAIN_SCRATCH);
8186 
8187    VexInvalRange vir = {0, 0};
8188    return vir;
8189 }
8190 
8191 /*---------------------------------------------------------------*/
8192 /*--- end                                    host_s390_defs.c ---*/
8193 /*---------------------------------------------------------------*/
8194