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