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