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