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