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