1 /* -*- mode: C; c-basic-offset: 3; -*- */
3 /*---------------------------------------------------------------*/
4 /*--- begin host_s390_defs.c ---*/
5 /*---------------------------------------------------------------*/
8 This file is part of Valgrind, a dynamic binary instrumentation
11 Copyright IBM Corp. 2010-2011
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.
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.
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
28 The GNU General Public License is contained in the file COPYING.
31 /* Contributed by Florian Krohm */
33 #include "libvex_basictypes.h"
35 #include "libvex_trc_values.h"
36 #include "libvex_guest_offsets.h"
37 #include "libvex_s390x_common.h"
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"
46 /* KLUDGE: We need to know the hwcaps of the host when generating
47 code. But that info is not passed to emit_S390Instr. Only mode64 is
48 being passed. So, ideally, we want this passed as an argument, too.
49 Until then, we use a global variable. This variable is set as a side
50 effect of iselSB_S390. This is safe because instructions are selected
51 before they are emitted. */
52 const VexArchInfo *s390_archinfo_host;
54 /*------------------------------------------------------------*/
56 /*------------------------------------------------------------*/
58 /* Decompile the given register into a static buffer and return it */
60 s390_hreg_as_string(HReg reg)
64 static const HChar ireg_names[16][5] = {
65 "%r0", "%r1", "%r2", "%r3", "%r4", "%r5", "%r6", "%r7",
66 "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15"
69 static const HChar freg_names[16][5] = {
70 "%f0", "%f1", "%f2", "%f3", "%f4", "%f5", "%f6", "%f7",
71 "%f8", "%f9", "%f10", "%f11", "%f12", "%f13", "%f14", "%f15"
74 UInt r; /* hregNumber() returns an UInt */
78 /* Be generic for all virtual regs. */
79 if (hregIsVirtual(reg)) {
81 switch (hregClass(reg)) {
82 case HRcInt64: vex_sprintf(buf, "%%vR%d", r); break;
83 case HRcFlt64: vex_sprintf(buf, "%%vF%d", r); break;
89 /* But specific for real regs. */
92 switch (hregClass(reg)) {
93 case HRcInt64: return ireg_names[r];
94 case HRcFlt64: return freg_names[r];
98 fail: vpanic("s390_hreg_as_string");
102 /* Tell the register allocator which registers can be allocated. */
104 s390_hreg_get_allocable(Int *nregs, HReg **arr)
108 /* Total number of allocable registers (all classes) */
109 *nregs = 16 /* GPRs */
111 - 1 /* r12 register holding VG_(dispatch_ctr) */
112 - 1 /* r13 guest state pointer */
113 - 1 /* r14 link register */
114 - 1 /* r15 stack pointer */
118 *arr = LibVEX_Alloc(*nregs * sizeof(HReg));
122 /* GPR0 is not available because it is interpreted as 0, when used
123 as a base or index register. */
124 (*arr)[i++] = mkHReg(1, HRcInt64, False);
125 (*arr)[i++] = mkHReg(2, HRcInt64, False);
126 (*arr)[i++] = mkHReg(3, HRcInt64, False);
127 (*arr)[i++] = mkHReg(4, HRcInt64, False);
128 (*arr)[i++] = mkHReg(5, HRcInt64, False);
129 (*arr)[i++] = mkHReg(6, HRcInt64, False);
130 (*arr)[i++] = mkHReg(7, HRcInt64, False);
131 (*arr)[i++] = mkHReg(8, HRcInt64, False);
132 (*arr)[i++] = mkHReg(9, HRcInt64, False);
133 /* GPR10 and GPR11 are used for instructions that use register pairs.
134 Otherwise, they are available to the allocator */
135 (*arr)[i++] = mkHReg(10, HRcInt64, False);
136 (*arr)[i++] = mkHReg(11, HRcInt64, False);
137 /* GPR12 is not available because it caches VG_(dispatch_ctr) */
138 /* GPR13 is not available because it is used as guest state pointer */
139 /* GPR14 is not available because it is used as link register */
140 /* GPR15 is not available because it is used as stack pointer */
142 /* Add the available real (non-virtual) FPRs */
143 (*arr)[i++] = mkHReg(0, HRcFlt64, False);
144 (*arr)[i++] = mkHReg(1, HRcFlt64, False);
145 (*arr)[i++] = mkHReg(2, HRcFlt64, False);
146 (*arr)[i++] = mkHReg(3, HRcFlt64, False);
147 (*arr)[i++] = mkHReg(4, HRcFlt64, False);
148 (*arr)[i++] = mkHReg(5, HRcFlt64, False);
149 (*arr)[i++] = mkHReg(6, HRcFlt64, False);
150 (*arr)[i++] = mkHReg(7, HRcFlt64, False);
151 (*arr)[i++] = mkHReg(8, HRcFlt64, False);
152 (*arr)[i++] = mkHReg(9, HRcFlt64, False);
153 (*arr)[i++] = mkHReg(10, HRcFlt64, False);
154 (*arr)[i++] = mkHReg(11, HRcFlt64, False);
155 (*arr)[i++] = mkHReg(12, HRcFlt64, False);
156 (*arr)[i++] = mkHReg(13, HRcFlt64, False);
157 (*arr)[i++] = mkHReg(14, HRcFlt64, False);
158 (*arr)[i++] = mkHReg(15, HRcFlt64, False);
159 /* FPR12 - FPR15 are also used as register pairs for 128-bit
160 floating point operations */
164 /* Return the real register that holds the guest state pointer */
166 s390_hreg_guest_state_pointer(void)
168 return mkHReg(S390_REGNO_GUEST_STATE_POINTER, HRcInt64, False);
171 /* Is VALUE within the domain of a 20-bit signed integer. */
172 static __inline__ Bool
173 fits_signed_20bit(Int value)
175 return ((value << 12) >> 12) == value;
179 /* Is VALUE within the domain of a 12-bit unsigned integer. */
180 static __inline__ Bool
181 fits_unsigned_12bit(Int value)
183 return (value & 0xFFF) == value;
186 /*------------------------------------------------------------*/
187 /*--- Addressing modes (amodes) ---*/
188 /*------------------------------------------------------------*/
190 /* Construct a b12 amode. */
192 s390_amode_b12(Int d, HReg b)
194 s390_amode *am = LibVEX_Alloc(sizeof(s390_amode));
196 vassert(fits_unsigned_12bit(d));
198 am->tag = S390_AMODE_B12;
201 am->x = 0; /* hregNumber(0) == 0 */
207 /* Construct a b20 amode. */
209 s390_amode_b20(Int d, HReg b)
211 s390_amode *am = LibVEX_Alloc(sizeof(s390_amode));
213 vassert(fits_signed_20bit(d));
215 am->tag = S390_AMODE_B20;
218 am->x = 0; /* hregNumber(0) == 0 */
224 /* Construct a bx12 amode. */
226 s390_amode_bx12(Int d, HReg b, HReg x)
228 s390_amode *am = LibVEX_Alloc(sizeof(s390_amode));
230 vassert(fits_unsigned_12bit(d));
234 am->tag = S390_AMODE_BX12;
243 /* Construct a bx20 amode. */
245 s390_amode_bx20(Int d, HReg b, HReg x)
247 s390_amode *am = LibVEX_Alloc(sizeof(s390_amode));
249 vassert(fits_signed_20bit(d));
253 am->tag = S390_AMODE_BX20;
262 /* Construct an AMODE for accessing the guest state at OFFSET */
264 s390_amode_for_guest_state(Int offset)
266 if (fits_unsigned_12bit(offset))
267 return s390_amode_b12(offset, s390_hreg_guest_state_pointer());
269 vpanic("invalid guest state offset");
273 /* Decompile the given amode into a static buffer and return it. */
275 s390_amode_as_string(const s390_amode *am)
277 static HChar buf[30];
286 vex_sprintf(p, "%d(%s)", am->d, s390_hreg_as_string(am->b));
289 case S390_AMODE_BX12:
290 case S390_AMODE_BX20:
291 /* s390_hreg_as_string returns pointer to local buffer. Need to
292 split this into two printfs */
293 p += vex_sprintf(p, "%d(%s,", am->d, s390_hreg_as_string(am->x));
294 vex_sprintf(p, "%s)", s390_hreg_as_string(am->b));
298 vpanic("s390_amode_as_string");
305 /* Helper function for s390_amode_is_sane */
306 static __inline__ Bool
307 is_virtual_gpr(HReg reg)
309 return hregIsVirtual(reg) && hregClass(reg) == HRcInt64;
313 /* Sanity check for an amode */
315 s390_amode_is_sane(const s390_amode *am)
319 return is_virtual_gpr(am->b) && fits_unsigned_12bit(am->d);
322 return is_virtual_gpr(am->b) && fits_signed_20bit(am->d);
324 case S390_AMODE_BX12:
325 return is_virtual_gpr(am->b) && is_virtual_gpr(am->x) &&
326 fits_unsigned_12bit(am->d);
328 case S390_AMODE_BX20:
329 return is_virtual_gpr(am->b) && is_virtual_gpr(am->x) &&
330 fits_signed_20bit(am->d);
333 vpanic("s390_amode_is_sane");
338 /* Record the register use of an amode */
340 s390_amode_get_reg_usage(HRegUsage *u, const s390_amode *am)
345 addHRegUse(u, HRmRead, am->b);
348 case S390_AMODE_BX12:
349 case S390_AMODE_BX20:
350 addHRegUse(u, HRmRead, am->b);
351 addHRegUse(u, HRmRead, am->x);
355 vpanic("s390_amode_get_reg_usage");
361 s390_amode_map_regs(HRegRemap *m, s390_amode *am)
366 am->b = lookupHRegRemap(m, am->b);
369 case S390_AMODE_BX12:
370 case S390_AMODE_BX20:
371 am->b = lookupHRegRemap(m, am->b);
372 am->x = lookupHRegRemap(m, am->x);
376 vpanic("s390_amode_map_regs");
383 ppS390AMode(struct s390_amode *am)
385 vex_printf("%s", s390_amode_as_string(am));
389 ppS390Instr(struct s390_insn *insn, Bool mode64)
391 vex_printf("%s", s390_insn_as_string(insn));
397 vex_printf("%s", s390_hreg_as_string(reg));
400 /*------------------------------------------------------------*/
401 /*--- Helpers for register allocation ---*/
402 /*------------------------------------------------------------*/
404 /* Called once per translation. */
406 getAllocableRegs_S390(Int *nregs, HReg **arr, Bool mode64)
408 s390_hreg_get_allocable(nregs, arr);
412 /* Tell the register allocator how the given instruction uses the registers
415 getRegUsage_S390Instr(HRegUsage *u, struct s390_insn *insn, Bool mode64)
417 s390_insn_get_reg_usage(u, insn);
421 /* Map the registers of the given instruction */
423 mapRegs_S390Instr(HRegRemap *m, struct s390_insn *insn, Bool mode64)
425 s390_insn_map_regs(m, insn);
429 /* Figure out if the given insn represents a reg-reg move, and if so
430 assign the source and destination to *src and *dst. If in doubt say No.
431 Used by the register allocator to do move coalescing. */
433 isMove_S390Instr(struct s390_insn *insn, HReg *src, HReg *dst)
435 return s390_insn_is_reg_reg_move(insn, src, dst);
439 /* Generate s390 spill/reload instructions under the direction of the
440 register allocator. Note it's critical these don't write the
441 condition codes. This is like an Ist_Put */
443 genSpill_S390(HInstr **i1, HInstr **i2, HReg rreg, Int offsetB, Bool mode64)
447 vassert(offsetB >= 0);
448 vassert(offsetB <= (1 << 12)); /* because we use b12 amode */
449 vassert(!hregIsVirtual(rreg));
453 am = s390_amode_for_guest_state(offsetB);
455 switch (hregClass(rreg)) {
458 *i1 = s390_insn_store(8, am, rreg);
462 ppHRegClass(hregClass(rreg));
463 vpanic("genSpill_S390: unimplemented regclass");
468 /* This is like an Iex_Get */
470 genReload_S390(HInstr **i1, HInstr **i2, HReg rreg, Int offsetB, Bool mode64)
474 vassert(offsetB >= 0);
475 vassert(offsetB <= (1 << 12)); /* because we use b12 amode */
476 vassert(!hregIsVirtual(rreg));
480 am = s390_amode_for_guest_state(offsetB);
482 switch (hregClass(rreg)) {
485 *i1 = s390_insn_load(8, rreg, am);
489 ppHRegClass(hregClass(rreg));
490 vpanic("genReload_S390: unimplemented regclass");
494 /* Helper function for s390_insn_get_reg_usage */
496 s390_opnd_RMI_get_reg_usage(HRegUsage *u, s390_opnd_RMI op)
500 addHRegUse(u, HRmRead, op.variant.reg);
503 case S390_OPND_AMODE:
504 s390_amode_get_reg_usage(u, op.variant.am);
507 case S390_OPND_IMMEDIATE:
511 vpanic("s390_opnd_RMI_get_reg_usage");
516 /* Tell the register allocator how the given insn uses the registers */
518 s390_insn_get_reg_usage(HRegUsage *u, const s390_insn *insn)
524 addHRegUse(u, HRmWrite, insn->variant.load.dst);
525 s390_amode_get_reg_usage(u, insn->variant.load.src);
528 case S390_INSN_LOAD_IMMEDIATE:
529 addHRegUse(u, HRmWrite, insn->variant.load_immediate.dst);
532 case S390_INSN_STORE:
533 addHRegUse(u, HRmRead, insn->variant.store.src);
534 s390_amode_get_reg_usage(u, insn->variant.store.dst);
538 addHRegUse(u, HRmRead, insn->variant.move.src);
539 addHRegUse(u, HRmWrite, insn->variant.move.dst);
542 case S390_INSN_COND_MOVE:
543 s390_opnd_RMI_get_reg_usage(u, insn->variant.cond_move.src);
544 addHRegUse(u, HRmWrite, insn->variant.cond_move.dst);
548 addHRegUse(u, HRmWrite, insn->variant.alu.dst);
549 addHRegUse(u, HRmRead, insn->variant.alu.dst); /* op1 */
550 s390_opnd_RMI_get_reg_usage(u, insn->variant.alu.op2);
554 addHRegUse(u, HRmRead, insn->variant.mul.dst_lo); /* op1 */
555 addHRegUse(u, HRmWrite, insn->variant.mul.dst_lo);
556 addHRegUse(u, HRmWrite, insn->variant.mul.dst_hi);
557 s390_opnd_RMI_get_reg_usage(u, insn->variant.mul.op2);
561 addHRegUse(u, HRmRead, insn->variant.div.op1_lo);
562 addHRegUse(u, HRmRead, insn->variant.div.op1_hi);
563 addHRegUse(u, HRmWrite, insn->variant.div.op1_lo);
564 addHRegUse(u, HRmWrite, insn->variant.div.op1_hi);
565 s390_opnd_RMI_get_reg_usage(u, insn->variant.div.op2);
569 addHRegUse(u, HRmRead, insn->variant.divs.op1);
570 addHRegUse(u, HRmWrite, insn->variant.divs.op1); /* quotient */
571 addHRegUse(u, HRmWrite, insn->variant.divs.rem); /* remainder */
572 s390_opnd_RMI_get_reg_usage(u, insn->variant.divs.op2);
576 addHRegUse(u, HRmWrite, insn->variant.clz.num_bits);
577 addHRegUse(u, HRmWrite, insn->variant.clz.clobber);
578 s390_opnd_RMI_get_reg_usage(u, insn->variant.clz.src);
582 addHRegUse(u, HRmWrite, insn->variant.unop.dst);
583 s390_opnd_RMI_get_reg_usage(u, insn->variant.unop.src);
587 s390_opnd_RMI_get_reg_usage(u, insn->variant.test.src);
590 case S390_INSN_CC2BOOL:
591 addHRegUse(u, HRmWrite, insn->variant.cc2bool.dst);
595 addHRegUse(u, HRmRead, insn->variant.cas.op1);
596 s390_amode_get_reg_usage(u, insn->variant.cas.op2);
597 addHRegUse(u, HRmRead, insn->variant.cas.op3);
598 addHRegUse(u, HRmWrite, insn->variant.cas.old_mem);
601 case S390_INSN_COMPARE:
602 addHRegUse(u, HRmRead, insn->variant.compare.src1);
603 s390_opnd_RMI_get_reg_usage(u, insn->variant.compare.src2);
606 case S390_INSN_BRANCH:
607 s390_opnd_RMI_get_reg_usage(u, insn->variant.branch.dst);
608 /* The destination address is loaded into S390_REGNO_RETURN_VALUE.
609 See s390_insn_branch_emit. */
610 addHRegUse(u, HRmWrite,
611 mkHReg(S390_REGNO_RETURN_VALUE, HRcInt64, False));
614 case S390_INSN_HELPER_CALL: {
617 /* Assume that all volatile registers are clobbered. ABI says,
618 volatile registers are: r0 - r5. Valgrind's register allocator
619 does not know about r0, so we can leave that out */
620 for (i = 1; i <= 5; ++i) {
621 addHRegUse(u, HRmWrite, mkHReg(i, HRcInt64, False));
624 /* Ditto for floating point registers. f0 - f7 are volatile */
625 for (i = 0; i <= 7; ++i) {
626 addHRegUse(u, HRmWrite, mkHReg(i, HRcFlt64, False));
629 /* The registers that are used for passing arguments will be read.
630 Not all of them may, but in general we need to assume that. */
631 for (i = 0; i < insn->variant.helper_call.num_args; ++i) {
632 addHRegUse(u, HRmRead, mkHReg(s390_gprno_from_arg_index(i),
636 /* s390_insn_helper_call_emit also reads / writes the link register
637 and stack pointer. But those registers are not visible to the
638 register allocator. So we don't need to do anything for them. */
642 case S390_INSN_BFP_TRIOP:
643 addHRegUse(u, HRmWrite, insn->variant.bfp_triop.dst);
644 addHRegUse(u, HRmRead, insn->variant.bfp_triop.dst); /* first */
645 addHRegUse(u, HRmRead, insn->variant.bfp_triop.op2); /* second */
646 addHRegUse(u, HRmRead, insn->variant.bfp_triop.op3); /* third */
649 case S390_INSN_BFP_BINOP:
650 addHRegUse(u, HRmWrite, insn->variant.bfp_binop.dst);
651 addHRegUse(u, HRmRead, insn->variant.bfp_binop.dst); /* left */
652 addHRegUse(u, HRmRead, insn->variant.bfp_binop.op2); /* right */
655 case S390_INSN_BFP_UNOP:
656 addHRegUse(u, HRmWrite, insn->variant.bfp_unop.dst);
657 addHRegUse(u, HRmRead, insn->variant.bfp_unop.op); /* operand */
660 case S390_INSN_BFP_COMPARE:
661 addHRegUse(u, HRmWrite, insn->variant.bfp_compare.dst);
662 addHRegUse(u, HRmRead, insn->variant.bfp_compare.op1); /* left */
663 addHRegUse(u, HRmRead, insn->variant.bfp_compare.op2); /* right */
666 case S390_INSN_BFP128_BINOP:
667 addHRegUse(u, HRmWrite, insn->variant.bfp128_binop.dst_hi);
668 addHRegUse(u, HRmWrite, insn->variant.bfp128_binop.dst_lo);
669 addHRegUse(u, HRmRead, insn->variant.bfp128_binop.dst_hi); /* left */
670 addHRegUse(u, HRmRead, insn->variant.bfp128_binop.dst_lo); /* left */
671 addHRegUse(u, HRmRead, insn->variant.bfp128_binop.op2_hi); /* right */
672 addHRegUse(u, HRmRead, insn->variant.bfp128_binop.op2_lo); /* right */
675 case S390_INSN_BFP128_COMPARE:
676 addHRegUse(u, HRmWrite, insn->variant.bfp128_compare.dst);
677 addHRegUse(u, HRmRead, insn->variant.bfp128_compare.op1_hi); /* left */
678 addHRegUse(u, HRmRead, insn->variant.bfp128_compare.op1_lo); /* left */
679 addHRegUse(u, HRmRead, insn->variant.bfp128_compare.op2_hi); /* right */
680 addHRegUse(u, HRmRead, insn->variant.bfp128_compare.op2_lo); /* right */
683 case S390_INSN_BFP128_UNOP:
684 addHRegUse(u, HRmWrite, insn->variant.bfp128_unop.dst_hi);
685 addHRegUse(u, HRmWrite, insn->variant.bfp128_unop.dst_lo);
686 addHRegUse(u, HRmRead, insn->variant.bfp128_unop.op_hi);
687 addHRegUse(u, HRmRead, insn->variant.bfp128_unop.op_lo);
690 case S390_INSN_BFP128_CONVERT_TO:
691 addHRegUse(u, HRmWrite, insn->variant.bfp128_unop.dst_hi);
692 addHRegUse(u, HRmWrite, insn->variant.bfp128_unop.dst_lo);
693 addHRegUse(u, HRmRead, insn->variant.bfp128_unop.op_hi);
696 case S390_INSN_BFP128_CONVERT_FROM:
697 addHRegUse(u, HRmWrite, insn->variant.bfp128_unop.dst_hi);
698 addHRegUse(u, HRmRead, insn->variant.bfp128_unop.op_hi);
699 addHRegUse(u, HRmRead, insn->variant.bfp128_unop.op_lo);
702 case S390_INSN_MFENCE:
706 vpanic("s390_insn_get_reg_usage");
711 /* Helper function for s390_insn_map_regs */
713 s390_opnd_RMI_map_regs(HRegRemap *m, s390_opnd_RMI *op)
717 op->variant.reg = lookupHRegRemap(m, op->variant.reg);
720 case S390_OPND_IMMEDIATE:
723 case S390_OPND_AMODE:
724 s390_amode_map_regs(m, op->variant.am);
728 vpanic("s390_opnd_RMI_map_regs");
734 s390_insn_map_regs(HRegRemap *m, s390_insn *insn)
738 insn->variant.load.dst = lookupHRegRemap(m, insn->variant.load.dst);
739 s390_amode_map_regs(m, insn->variant.load.src);
742 case S390_INSN_STORE:
743 s390_amode_map_regs(m, insn->variant.store.dst);
744 insn->variant.store.src = lookupHRegRemap(m, insn->variant.store.src);
748 insn->variant.move.dst = lookupHRegRemap(m, insn->variant.move.dst);
749 insn->variant.move.src = lookupHRegRemap(m, insn->variant.move.src);
752 case S390_INSN_COND_MOVE:
753 insn->variant.cond_move.dst = lookupHRegRemap(m, insn->variant.cond_move.dst);
754 s390_opnd_RMI_map_regs(m, &insn->variant.cond_move.src);
757 case S390_INSN_LOAD_IMMEDIATE:
758 insn->variant.load_immediate.dst =
759 lookupHRegRemap(m, insn->variant.load_immediate.dst);
763 insn->variant.alu.dst = lookupHRegRemap(m, insn->variant.alu.dst);
764 s390_opnd_RMI_map_regs(m, &insn->variant.alu.op2);
768 insn->variant.mul.dst_hi = lookupHRegRemap(m, insn->variant.mul.dst_hi);
769 insn->variant.mul.dst_lo = lookupHRegRemap(m, insn->variant.mul.dst_lo);
770 s390_opnd_RMI_map_regs(m, &insn->variant.mul.op2);
774 insn->variant.div.op1_hi = lookupHRegRemap(m, insn->variant.div.op1_hi);
775 insn->variant.div.op1_lo = lookupHRegRemap(m, insn->variant.div.op1_lo);
776 s390_opnd_RMI_map_regs(m, &insn->variant.div.op2);
780 insn->variant.divs.op1 = lookupHRegRemap(m, insn->variant.divs.op1);
781 insn->variant.divs.rem = lookupHRegRemap(m, insn->variant.divs.rem);
782 s390_opnd_RMI_map_regs(m, &insn->variant.divs.op2);
786 insn->variant.clz.num_bits = lookupHRegRemap(m, insn->variant.clz.num_bits);
787 insn->variant.clz.clobber = lookupHRegRemap(m, insn->variant.clz.clobber);
788 s390_opnd_RMI_map_regs(m, &insn->variant.clz.src);
792 insn->variant.unop.dst = lookupHRegRemap(m, insn->variant.unop.dst);
793 s390_opnd_RMI_map_regs(m, &insn->variant.unop.src);
797 s390_opnd_RMI_map_regs(m, &insn->variant.test.src);
800 case S390_INSN_CC2BOOL:
801 insn->variant.cc2bool.dst = lookupHRegRemap(m, insn->variant.cc2bool.dst);
805 insn->variant.cas.op1 = lookupHRegRemap(m, insn->variant.cas.op1);
806 s390_amode_map_regs(m, insn->variant.cas.op2);
807 insn->variant.cas.op3 = lookupHRegRemap(m, insn->variant.cas.op3);
808 insn->variant.cas.old_mem = lookupHRegRemap(m, insn->variant.cas.old_mem);
811 case S390_INSN_COMPARE:
812 insn->variant.compare.src1 = lookupHRegRemap(m, insn->variant.compare.src1);
813 s390_opnd_RMI_map_regs(m, &insn->variant.compare.src2);
816 case S390_INSN_BRANCH:
817 s390_opnd_RMI_map_regs(m, &insn->variant.branch.dst);
818 /* No need to map S390_REGNO_RETURN_VALUE. It's not virtual */
821 case S390_INSN_HELPER_CALL:
822 /* s390_insn_helper_call_emit also reads / writes the link register
823 and stack pointer. But those registers are not visible to the
824 register allocator. So we don't need to do anything for them.
825 As for the arguments of the helper call -- they will be loaded into
826 non-virtual registers. Again, we don't need to do anything for those
830 case S390_INSN_BFP_TRIOP:
831 insn->variant.bfp_triop.dst = lookupHRegRemap(m, insn->variant.bfp_triop.dst);
832 insn->variant.bfp_triop.op2 = lookupHRegRemap(m, insn->variant.bfp_triop.op2);
833 insn->variant.bfp_triop.op3 = lookupHRegRemap(m, insn->variant.bfp_triop.op3);
836 case S390_INSN_BFP_BINOP:
837 insn->variant.bfp_binop.dst = lookupHRegRemap(m, insn->variant.bfp_binop.dst);
838 insn->variant.bfp_binop.op2 = lookupHRegRemap(m, insn->variant.bfp_binop.op2);
841 case S390_INSN_BFP_UNOP:
842 insn->variant.bfp_unop.dst = lookupHRegRemap(m, insn->variant.bfp_unop.dst);
843 insn->variant.bfp_unop.op = lookupHRegRemap(m, insn->variant.bfp_unop.op);
846 case S390_INSN_BFP_COMPARE:
847 insn->variant.bfp_compare.dst = lookupHRegRemap(m, insn->variant.bfp_compare.dst);
848 insn->variant.bfp_compare.op1 = lookupHRegRemap(m, insn->variant.bfp_compare.op1);
849 insn->variant.bfp_compare.op2 = lookupHRegRemap(m, insn->variant.bfp_compare.op2);
852 case S390_INSN_BFP128_BINOP:
853 insn->variant.bfp128_binop.dst_hi =
854 lookupHRegRemap(m, insn->variant.bfp128_binop.dst_hi);
855 insn->variant.bfp128_binop.dst_lo =
856 lookupHRegRemap(m, insn->variant.bfp128_binop.dst_lo);
857 insn->variant.bfp128_binop.op2_hi =
858 lookupHRegRemap(m, insn->variant.bfp128_binop.op2_hi);
859 insn->variant.bfp128_binop.op2_lo =
860 lookupHRegRemap(m, insn->variant.bfp128_binop.op2_lo);
863 case S390_INSN_BFP128_COMPARE:
864 insn->variant.bfp128_compare.dst =
865 lookupHRegRemap(m, insn->variant.bfp128_compare.dst);
866 insn->variant.bfp128_compare.op1_hi =
867 lookupHRegRemap(m, insn->variant.bfp128_compare.op1_hi);
868 insn->variant.bfp128_compare.op1_lo =
869 lookupHRegRemap(m, insn->variant.bfp128_compare.op1_lo);
870 insn->variant.bfp128_compare.op2_hi =
871 lookupHRegRemap(m, insn->variant.bfp128_compare.op2_hi);
872 insn->variant.bfp128_compare.op2_lo =
873 lookupHRegRemap(m, insn->variant.bfp128_compare.op2_lo);
876 case S390_INSN_BFP128_UNOP:
877 insn->variant.bfp128_unop.dst_hi =
878 lookupHRegRemap(m, insn->variant.bfp128_unop.dst_hi);
879 insn->variant.bfp128_unop.dst_lo =
880 lookupHRegRemap(m, insn->variant.bfp128_unop.dst_lo);
881 insn->variant.bfp128_unop.op_hi =
882 lookupHRegRemap(m, insn->variant.bfp128_unop.op_hi);
883 insn->variant.bfp128_unop.op_lo =
884 lookupHRegRemap(m, insn->variant.bfp128_unop.op_lo);
887 case S390_INSN_BFP128_CONVERT_TO:
888 insn->variant.bfp128_unop.dst_hi =
889 lookupHRegRemap(m, insn->variant.bfp128_unop.dst_hi);
890 insn->variant.bfp128_unop.dst_lo =
891 lookupHRegRemap(m, insn->variant.bfp128_unop.dst_lo);
892 insn->variant.bfp128_unop.op_hi =
893 lookupHRegRemap(m, insn->variant.bfp128_unop.op_hi);
896 case S390_INSN_BFP128_CONVERT_FROM:
897 insn->variant.bfp128_unop.dst_hi =
898 lookupHRegRemap(m, insn->variant.bfp128_unop.dst_hi);
899 insn->variant.bfp128_unop.op_hi =
900 lookupHRegRemap(m, insn->variant.bfp128_unop.op_hi);
901 insn->variant.bfp128_unop.op_lo =
902 lookupHRegRemap(m, insn->variant.bfp128_unop.op_lo);
905 case S390_INSN_MFENCE:
909 vpanic("s390_insn_map_regs");
914 /* Return True, if INSN is a move between two registers of the same class.
915 In that case assign the source and destination registers to SRC and DST,
918 s390_insn_is_reg_reg_move(const s390_insn *insn, HReg *src, HReg *dst)
920 if (insn->tag == S390_INSN_MOVE &&
921 hregClass(insn->variant.move.src) == hregClass(insn->variant.move.dst)) {
922 *src = insn->variant.move.src;
923 *dst = insn->variant.move.dst;
931 /*------------------------------------------------------------*/
932 /*--- Functions to emit a sequence of bytes ---*/
933 /*------------------------------------------------------------*/
936 static __inline__ UChar *
937 emit_2bytes(UChar *p, ULong val)
939 return (UChar *)__builtin_memcpy(p, ((UChar *)&val) + 6, 2) + 2;
943 static __inline__ UChar *
944 emit_4bytes(UChar *p, ULong val)
946 return (UChar *)__builtin_memcpy(p, ((UChar *)&val) + 4, 4) + 4;
950 static __inline__ UChar *
951 emit_6bytes(UChar *p, ULong val)
953 return (UChar *)__builtin_memcpy(p, ((UChar *)&val) + 2, 6) + 6;
957 /*------------------------------------------------------------*/
958 /*--- Functions to emit various instruction formats ---*/
959 /*------------------------------------------------------------*/
963 emit_RI(UChar *p, UInt op, UChar r1, UShort i2)
967 the_insn |= ((ULong)r1) << 20;
968 the_insn |= ((ULong)i2) << 0;
970 return emit_4bytes(p, the_insn);
975 emit_RIL(UChar *p, ULong op, UChar r1, UInt i2)
979 the_insn |= ((ULong)r1) << 36;
980 the_insn |= ((ULong)i2) << 0;
982 return emit_6bytes(p, the_insn);
987 emit_RR(UChar *p, UInt op, UChar r1, UChar r2)
991 the_insn |= ((ULong)r1) << 4;
992 the_insn |= ((ULong)r2) << 0;
994 return emit_2bytes(p, the_insn);
999 emit_RRE(UChar *p, UInt op, UChar r1, UChar r2)
1001 ULong the_insn = op;
1003 the_insn |= ((ULong)r1) << 4;
1004 the_insn |= ((ULong)r2) << 0;
1006 return emit_4bytes(p, the_insn);
1011 emit_RRF(UChar *p, UInt op, UChar r1, UChar r3, UChar r2)
1013 ULong the_insn = op;
1015 the_insn |= ((ULong)r1) << 12;
1016 the_insn |= ((ULong)r3) << 4;
1017 the_insn |= ((ULong)r2) << 0;
1019 return emit_4bytes(p, the_insn);
1024 emit_RRF3(UChar *p, UInt op, UChar r3, UChar r1, UChar r2)
1026 ULong the_insn = op;
1028 the_insn |= ((ULong)r3) << 12;
1029 the_insn |= ((ULong)r1) << 4;
1030 the_insn |= ((ULong)r2) << 0;
1032 return emit_4bytes(p, the_insn);
1037 emit_RS(UChar *p, UInt op, UChar r1, UChar r3, UChar b2, UShort d2)
1039 ULong the_insn = op;
1041 the_insn |= ((ULong)r1) << 20;
1042 the_insn |= ((ULong)r3) << 16;
1043 the_insn |= ((ULong)b2) << 12;
1044 the_insn |= ((ULong)d2) << 0;
1046 return emit_4bytes(p, the_insn);
1051 emit_RSY(UChar *p, ULong op, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
1053 ULong the_insn = op;
1055 the_insn |= ((ULong)r1) << 36;
1056 the_insn |= ((ULong)r3) << 32;
1057 the_insn |= ((ULong)b2) << 28;
1058 the_insn |= ((ULong)dl2) << 16;
1059 the_insn |= ((ULong)dh2) << 8;
1061 return emit_6bytes(p, the_insn);
1066 emit_RX(UChar *p, UInt op, UChar r1, UChar x2, UChar b2, UShort d2)
1068 ULong the_insn = op;
1070 the_insn |= ((ULong)r1) << 20;
1071 the_insn |= ((ULong)x2) << 16;
1072 the_insn |= ((ULong)b2) << 12;
1073 the_insn |= ((ULong)d2) << 0;
1075 return emit_4bytes(p, the_insn);
1080 emit_RXY(UChar *p, ULong op, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1082 ULong the_insn = op;
1084 the_insn |= ((ULong)r1) << 36;
1085 the_insn |= ((ULong)x2) << 32;
1086 the_insn |= ((ULong)b2) << 28;
1087 the_insn |= ((ULong)dl2) << 16;
1088 the_insn |= ((ULong)dh2) << 8;
1090 return emit_6bytes(p, the_insn);
1095 emit_S(UChar *p, UInt op, UChar b2, UShort d2)
1097 ULong the_insn = op;
1099 the_insn |= ((ULong)b2) << 12;
1100 the_insn |= ((ULong)d2) << 0;
1102 return emit_4bytes(p, the_insn);
1106 /*------------------------------------------------------------*/
1107 /*--- Functions to emit particular instructions ---*/
1108 /*------------------------------------------------------------*/
1112 s390_emit_AR(UChar *p, UChar r1, UChar r2)
1114 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1115 s390_disasm(ENC3(MNM, GPR, GPR), "ar", r1, r2);
1117 return emit_RR(p, 0x1a00, r1, r2);
1122 s390_emit_AGR(UChar *p, UChar r1, UChar r2)
1124 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1125 s390_disasm(ENC3(MNM, GPR, GPR), "agr", r1, r2);
1127 return emit_RRE(p, 0xb9080000, r1, r2);
1132 s390_emit_A(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
1134 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1135 s390_disasm(ENC3(MNM, GPR, UDXB), "a", r1, d2, x2, b2);
1137 return emit_RX(p, 0x5a000000, r1, x2, b2, d2);
1142 s390_emit_AY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1144 vassert(s390_host_has_ldisp);
1146 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1147 s390_disasm(ENC3(MNM, GPR, SDXB), "ay", r1, dh2, dl2, x2, b2);
1149 return emit_RXY(p, 0xe3000000005aULL, r1, x2, b2, dl2, dh2);
1154 s390_emit_AG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1156 vassert(s390_host_has_ldisp || dh2 == 0);
1158 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1159 s390_disasm(ENC3(MNM, GPR, SDXB), "ag", r1, dh2, dl2, x2, b2);
1161 return emit_RXY(p, 0xe30000000008ULL, r1, x2, b2, dl2, dh2);
1166 s390_emit_AFI(UChar *p, UChar r1, UInt i2)
1168 vassert(s390_host_has_eimm);
1170 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1171 s390_disasm(ENC3(MNM, GPR, INT), "afi", r1, i2);
1173 return emit_RIL(p, 0xc20900000000ULL, r1, i2);
1178 s390_emit_AGFI(UChar *p, UChar r1, UInt i2)
1180 vassert(s390_host_has_eimm);
1182 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1183 s390_disasm(ENC3(MNM, GPR, INT), "agfi", r1, i2);
1185 return emit_RIL(p, 0xc20800000000ULL, r1, i2);
1190 s390_emit_AH(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
1192 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1193 s390_disasm(ENC3(MNM, GPR, UDXB), "ah", r1, d2, x2, b2);
1195 return emit_RX(p, 0x4a000000, r1, x2, b2, d2);
1200 s390_emit_AHY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1202 vassert(s390_host_has_ldisp);
1204 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1205 s390_disasm(ENC3(MNM, GPR, SDXB), "ahy", r1, dh2, dl2, x2, b2);
1207 return emit_RXY(p, 0xe3000000007aULL, r1, x2, b2, dl2, dh2);
1212 s390_emit_AHI(UChar *p, UChar r1, UShort i2)
1214 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1215 s390_disasm(ENC3(MNM, GPR, INT), "ahi", r1, (Int)(Short)i2);
1217 return emit_RI(p, 0xa70a0000, r1, i2);
1222 s390_emit_AGHI(UChar *p, UChar r1, UShort i2)
1224 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1225 s390_disasm(ENC3(MNM, GPR, INT), "aghi", r1, (Int)(Short)i2);
1227 return emit_RI(p, 0xa70b0000, r1, i2);
1232 s390_emit_NR(UChar *p, UChar r1, UChar r2)
1234 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1235 s390_disasm(ENC3(MNM, GPR, GPR), "nr", r1, r2);
1237 return emit_RR(p, 0x1400, r1, r2);
1242 s390_emit_NGR(UChar *p, UChar r1, UChar r2)
1244 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1245 s390_disasm(ENC3(MNM, GPR, GPR), "ngr", r1, r2);
1247 return emit_RRE(p, 0xb9800000, r1, r2);
1252 s390_emit_N(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
1254 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1255 s390_disasm(ENC3(MNM, GPR, UDXB), "n", r1, d2, x2, b2);
1257 return emit_RX(p, 0x54000000, r1, x2, b2, d2);
1262 s390_emit_NY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1264 vassert(s390_host_has_ldisp);
1266 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1267 s390_disasm(ENC3(MNM, GPR, SDXB), "ny", r1, dh2, dl2, x2, b2);
1269 return emit_RXY(p, 0xe30000000054ULL, r1, x2, b2, dl2, dh2);
1274 s390_emit_NG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1276 vassert(s390_host_has_ldisp || dh2 == 0);
1278 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1279 s390_disasm(ENC3(MNM, GPR, SDXB), "ng", r1, dh2, dl2, x2, b2);
1281 return emit_RXY(p, 0xe30000000080ULL, r1, x2, b2, dl2, dh2);
1286 s390_emit_NIHF(UChar *p, UChar r1, UInt i2)
1288 vassert(s390_host_has_eimm);
1290 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1291 s390_disasm(ENC3(MNM, GPR, UINT), "nihf", r1, i2);
1293 return emit_RIL(p, 0xc00a00000000ULL, r1, i2);
1298 s390_emit_NILF(UChar *p, UChar r1, UInt i2)
1300 vassert(s390_host_has_eimm);
1302 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1303 s390_disasm(ENC3(MNM, GPR, UINT), "nilf", r1, i2);
1305 return emit_RIL(p, 0xc00b00000000ULL, r1, i2);
1310 s390_emit_NILL(UChar *p, UChar r1, UShort i2)
1312 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1313 s390_disasm(ENC3(MNM, GPR, UINT), "nill", r1, i2);
1315 return emit_RI(p, 0xa5070000, r1, i2);
1320 s390_emit_BASR(UChar *p, UChar r1, UChar r2)
1322 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1323 s390_disasm(ENC3(MNM, GPR, GPR), "basr", r1, r2);
1325 return emit_RR(p, 0x0d00, r1, r2);
1330 s390_emit_BCR(UChar *p, UChar r1, UChar r2)
1332 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1333 s390_disasm(ENC2(XMNM, GPR), S390_XMNM_BCR, r1, r2);
1335 return emit_RR(p, 0x0700, r1, r2);
1340 s390_emit_BRC(UChar *p, UChar r1, UShort i2)
1342 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1343 s390_disasm(ENC2(XMNM, PCREL), S390_XMNM_BRC, r1, (Int)(Short)i2);
1345 return emit_RI(p, 0xa7040000, r1, i2);
1350 s390_emit_CR(UChar *p, UChar r1, UChar r2)
1352 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1353 s390_disasm(ENC3(MNM, GPR, GPR), "cr", r1, r2);
1355 return emit_RR(p, 0x1900, r1, r2);
1360 s390_emit_CGR(UChar *p, UChar r1, UChar r2)
1362 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1363 s390_disasm(ENC3(MNM, GPR, GPR), "cgr", r1, r2);
1365 return emit_RRE(p, 0xb9200000, r1, r2);
1370 s390_emit_C(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
1372 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1373 s390_disasm(ENC3(MNM, GPR, UDXB), "c", r1, d2, x2, b2);
1375 return emit_RX(p, 0x59000000, r1, x2, b2, d2);
1380 s390_emit_CY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1382 vassert(s390_host_has_ldisp);
1384 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1385 s390_disasm(ENC3(MNM, GPR, SDXB), "cy", r1, dh2, dl2, x2, b2);
1387 return emit_RXY(p, 0xe30000000059ULL, r1, x2, b2, dl2, dh2);
1392 s390_emit_CG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1394 vassert(s390_host_has_ldisp || dh2 == 0);
1396 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1397 s390_disasm(ENC3(MNM, GPR, SDXB), "cg", r1, dh2, dl2, x2, b2);
1399 return emit_RXY(p, 0xe30000000020ULL, r1, x2, b2, dl2, dh2);
1404 s390_emit_CFI(UChar *p, UChar r1, UInt i2)
1406 vassert(s390_host_has_eimm);
1408 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1409 s390_disasm(ENC3(MNM, GPR, INT), "cfi", r1, i2);
1411 return emit_RIL(p, 0xc20d00000000ULL, r1, i2);
1416 s390_emit_CS(UChar *p, UChar r1, UChar r3, UChar b2, UShort d2)
1418 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1419 s390_disasm(ENC4(MNM, GPR, GPR, UDXB), "cs", r1, r3, d2, 0, b2);
1421 return emit_RS(p, 0xba000000, r1, r3, b2, d2);
1426 s390_emit_CSY(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
1428 vassert(s390_host_has_ldisp);
1430 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1431 s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "csy", r1, r3, dh2, dl2, 0, b2);
1433 return emit_RSY(p, 0xeb0000000014ULL, r1, r3, b2, dl2, dh2);
1438 s390_emit_CSG(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
1440 vassert(s390_host_has_ldisp || dh2 == 0);
1442 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1443 s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "csg", r1, r3, dh2, dl2, 0, b2);
1445 return emit_RSY(p, 0xeb0000000030ULL, r1, r3, b2, dl2, dh2);
1450 s390_emit_CLR(UChar *p, UChar r1, UChar r2)
1452 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1453 s390_disasm(ENC3(MNM, GPR, GPR), "clr", r1, r2);
1455 return emit_RR(p, 0x1500, r1, r2);
1460 s390_emit_CLGR(UChar *p, UChar r1, UChar r2)
1462 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1463 s390_disasm(ENC3(MNM, GPR, GPR), "clgr", r1, r2);
1465 return emit_RRE(p, 0xb9210000, r1, r2);
1470 s390_emit_CL(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
1472 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1473 s390_disasm(ENC3(MNM, GPR, UDXB), "cl", r1, d2, x2, b2);
1475 return emit_RX(p, 0x55000000, r1, x2, b2, d2);
1480 s390_emit_CLY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1482 vassert(s390_host_has_ldisp);
1484 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1485 s390_disasm(ENC3(MNM, GPR, SDXB), "cly", r1, dh2, dl2, x2, b2);
1487 return emit_RXY(p, 0xe30000000055ULL, r1, x2, b2, dl2, dh2);
1492 s390_emit_CLG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1494 vassert(s390_host_has_ldisp || dh2 == 0);
1496 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1497 s390_disasm(ENC3(MNM, GPR, SDXB), "clg", r1, dh2, dl2, x2, b2);
1499 return emit_RXY(p, 0xe30000000021ULL, r1, x2, b2, dl2, dh2);
1504 s390_emit_CLFI(UChar *p, UChar r1, UInt i2)
1506 vassert(s390_host_has_eimm);
1508 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1509 s390_disasm(ENC3(MNM, GPR, UINT), "clfi", r1, i2);
1511 return emit_RIL(p, 0xc20f00000000ULL, r1, i2);
1516 s390_emit_DR(UChar *p, UChar r1, UChar r2)
1518 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1519 s390_disasm(ENC3(MNM, GPR, GPR), "dr", r1, r2);
1521 return emit_RR(p, 0x1d00, r1, r2);
1526 s390_emit_D(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
1528 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1529 s390_disasm(ENC3(MNM, GPR, UDXB), "d", r1, d2, x2, b2);
1531 return emit_RX(p, 0x5d000000, r1, x2, b2, d2);
1536 s390_emit_DLR(UChar *p, UChar r1, UChar r2)
1538 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1539 s390_disasm(ENC3(MNM, GPR, GPR), "dlr", r1, r2);
1541 return emit_RRE(p, 0xb9970000, r1, r2);
1546 s390_emit_DLGR(UChar *p, UChar r1, UChar r2)
1548 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1549 s390_disasm(ENC3(MNM, GPR, GPR), "dlgr", r1, r2);
1551 return emit_RRE(p, 0xb9870000, r1, r2);
1556 s390_emit_DL(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1558 vassert(s390_host_has_ldisp || dh2 == 0);
1560 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1561 s390_disasm(ENC3(MNM, GPR, SDXB), "dl", r1, dh2, dl2, x2, b2);
1563 return emit_RXY(p, 0xe30000000097ULL, r1, x2, b2, dl2, dh2);
1568 s390_emit_DLG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1570 vassert(s390_host_has_ldisp || dh2 == 0);
1572 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1573 s390_disasm(ENC3(MNM, GPR, SDXB), "dlg", r1, dh2, dl2, x2, b2);
1575 return emit_RXY(p, 0xe30000000087ULL, r1, x2, b2, dl2, dh2);
1580 s390_emit_DSGR(UChar *p, UChar r1, UChar r2)
1582 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1583 s390_disasm(ENC3(MNM, GPR, GPR), "dsgr", r1, r2);
1585 return emit_RRE(p, 0xb90d0000, r1, r2);
1590 s390_emit_DSG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1592 vassert(s390_host_has_ldisp || dh2 == 0);
1594 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1595 s390_disasm(ENC3(MNM, GPR, SDXB), "dsg", r1, dh2, dl2, x2, b2);
1597 return emit_RXY(p, 0xe3000000000dULL, r1, x2, b2, dl2, dh2);
1602 s390_emit_XR(UChar *p, UChar r1, UChar r2)
1604 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1605 s390_disasm(ENC3(MNM, GPR, GPR), "xr", r1, r2);
1607 return emit_RR(p, 0x1700, r1, r2);
1612 s390_emit_XGR(UChar *p, UChar r1, UChar r2)
1614 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1615 s390_disasm(ENC3(MNM, GPR, GPR), "xgr", r1, r2);
1617 return emit_RRE(p, 0xb9820000, r1, r2);
1622 s390_emit_X(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
1624 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1625 s390_disasm(ENC3(MNM, GPR, UDXB), "x", r1, d2, x2, b2);
1627 return emit_RX(p, 0x57000000, r1, x2, b2, d2);
1632 s390_emit_XY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1634 vassert(s390_host_has_ldisp);
1636 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1637 s390_disasm(ENC3(MNM, GPR, SDXB), "xy", r1, dh2, dl2, x2, b2);
1639 return emit_RXY(p, 0xe30000000057ULL, r1, x2, b2, dl2, dh2);
1644 s390_emit_XG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1646 vassert(s390_host_has_ldisp || dh2 == 0);
1648 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1649 s390_disasm(ENC3(MNM, GPR, SDXB), "xg", r1, dh2, dl2, x2, b2);
1651 return emit_RXY(p, 0xe30000000082ULL, r1, x2, b2, dl2, dh2);
1656 s390_emit_XIHF(UChar *p, UChar r1, UInt i2)
1658 vassert(s390_host_has_eimm);
1660 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1661 s390_disasm(ENC3(MNM, GPR, UINT), "xihf", r1, i2);
1663 return emit_RIL(p, 0xc00600000000ULL, r1, i2);
1668 s390_emit_XILF(UChar *p, UChar r1, UInt i2)
1670 vassert(s390_host_has_eimm);
1672 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1673 s390_disasm(ENC3(MNM, GPR, UINT), "xilf", r1, i2);
1675 return emit_RIL(p, 0xc00700000000ULL, r1, i2);
1680 s390_emit_FLOGR(UChar *p, UChar r1, UChar r2)
1682 vassert(s390_host_has_eimm);
1684 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1685 s390_disasm(ENC3(MNM, GPR, GPR), "flogr", r1, r2);
1687 return emit_RRE(p, 0xb9830000, r1, r2);
1692 s390_emit_IC(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
1694 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1695 s390_disasm(ENC3(MNM, GPR, UDXB), "ic", r1, d2, x2, b2);
1697 return emit_RX(p, 0x43000000, r1, x2, b2, d2);
1702 s390_emit_ICY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1704 vassert(s390_host_has_ldisp);
1706 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1707 s390_disasm(ENC3(MNM, GPR, SDXB), "icy", r1, dh2, dl2, x2, b2);
1709 return emit_RXY(p, 0xe30000000073ULL, r1, x2, b2, dl2, dh2);
1714 s390_emit_IIHF(UChar *p, UChar r1, UInt i2)
1716 vassert(s390_host_has_eimm);
1718 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1719 s390_disasm(ENC3(MNM, GPR, UINT), "iihf", r1, i2);
1721 return emit_RIL(p, 0xc00800000000ULL, r1, i2);
1726 s390_emit_IIHH(UChar *p, UChar r1, UShort i2)
1728 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1729 s390_disasm(ENC3(MNM, GPR, UINT), "iihh", r1, i2);
1731 return emit_RI(p, 0xa5000000, r1, i2);
1736 s390_emit_IIHL(UChar *p, UChar r1, UShort i2)
1738 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1739 s390_disasm(ENC3(MNM, GPR, UINT), "iihl", r1, i2);
1741 return emit_RI(p, 0xa5010000, r1, i2);
1746 s390_emit_IILF(UChar *p, UChar r1, UInt i2)
1748 vassert(s390_host_has_eimm);
1750 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1751 s390_disasm(ENC3(MNM, GPR, UINT), "iilf", r1, i2);
1753 return emit_RIL(p, 0xc00900000000ULL, r1, i2);
1758 s390_emit_IILH(UChar *p, UChar r1, UShort i2)
1760 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1761 s390_disasm(ENC3(MNM, GPR, UINT), "iilh", r1, i2);
1763 return emit_RI(p, 0xa5020000, r1, i2);
1768 s390_emit_IILL(UChar *p, UChar r1, UShort i2)
1770 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1771 s390_disasm(ENC3(MNM, GPR, UINT), "iill", r1, i2);
1773 return emit_RI(p, 0xa5030000, r1, i2);
1778 s390_emit_IPM(UChar *p, UChar r1, UChar r2)
1780 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1781 s390_disasm(ENC2(MNM, GPR), "ipm", r1);
1783 return emit_RRE(p, 0xb2220000, r1, r2);
1788 s390_emit_LR(UChar *p, UChar r1, UChar r2)
1790 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1791 s390_disasm(ENC3(MNM, GPR, GPR), "lr", r1, r2);
1793 return emit_RR(p, 0x1800, r1, r2);
1798 s390_emit_LGR(UChar *p, UChar r1, UChar r2)
1800 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1801 s390_disasm(ENC3(MNM, GPR, GPR), "lgr", r1, r2);
1803 return emit_RRE(p, 0xb9040000, r1, r2);
1808 s390_emit_LGFR(UChar *p, UChar r1, UChar r2)
1810 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1811 s390_disasm(ENC3(MNM, GPR, GPR), "lgfr", r1, r2);
1813 return emit_RRE(p, 0xb9140000, r1, r2);
1818 s390_emit_L(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
1820 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1821 s390_disasm(ENC3(MNM, GPR, UDXB), "l", r1, d2, x2, b2);
1823 return emit_RX(p, 0x58000000, r1, x2, b2, d2);
1828 s390_emit_LY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1830 vassert(s390_host_has_ldisp);
1832 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1833 s390_disasm(ENC3(MNM, GPR, SDXB), "ly", r1, dh2, dl2, x2, b2);
1835 return emit_RXY(p, 0xe30000000058ULL, r1, x2, b2, dl2, dh2);
1840 s390_emit_LG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1842 vassert(s390_host_has_ldisp || dh2 == 0);
1844 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1845 s390_disasm(ENC3(MNM, GPR, SDXB), "lg", r1, dh2, dl2, x2, b2);
1847 return emit_RXY(p, 0xe30000000004ULL, r1, x2, b2, dl2, dh2);
1852 s390_emit_LGF(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1854 vassert(s390_host_has_ldisp || dh2 == 0);
1856 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1857 s390_disasm(ENC3(MNM, GPR, SDXB), "lgf", r1, dh2, dl2, x2, b2);
1859 return emit_RXY(p, 0xe30000000014ULL, r1, x2, b2, dl2, dh2);
1864 s390_emit_LGFI(UChar *p, UChar r1, UInt i2)
1866 vassert(s390_host_has_eimm);
1868 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1869 s390_disasm(ENC3(MNM, GPR, INT), "lgfi", r1, i2);
1871 return emit_RIL(p, 0xc00100000000ULL, r1, i2);
1876 s390_emit_LTR(UChar *p, UChar r1, UChar r2)
1878 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1879 s390_disasm(ENC3(MNM, GPR, GPR), "ltr", r1, r2);
1881 return emit_RR(p, 0x1200, r1, r2);
1886 s390_emit_LTGR(UChar *p, UChar r1, UChar r2)
1888 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1889 s390_disasm(ENC3(MNM, GPR, GPR), "ltgr", r1, r2);
1891 return emit_RRE(p, 0xb9020000, r1, r2);
1896 s390_emit_LT(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1898 vassert(s390_host_has_eimm);
1900 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1901 s390_disasm(ENC3(MNM, GPR, SDXB), "lt", r1, dh2, dl2, x2, b2);
1903 return emit_RXY(p, 0xe30000000012ULL, r1, x2, b2, dl2, dh2);
1908 s390_emit_LTG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1910 vassert(s390_host_has_eimm);
1912 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1913 s390_disasm(ENC3(MNM, GPR, SDXB), "ltg", r1, dh2, dl2, x2, b2);
1915 return emit_RXY(p, 0xe30000000002ULL, r1, x2, b2, dl2, dh2);
1920 s390_emit_LBR(UChar *p, UChar r1, UChar r2)
1922 vassert(s390_host_has_eimm);
1924 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1925 s390_disasm(ENC3(MNM, GPR, GPR), "lbr", r1, r2);
1927 return emit_RRE(p, 0xb9260000, r1, r2);
1932 s390_emit_LGBR(UChar *p, UChar r1, UChar r2)
1934 vassert(s390_host_has_eimm);
1936 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1937 s390_disasm(ENC3(MNM, GPR, GPR), "lgbr", r1, r2);
1939 return emit_RRE(p, 0xb9060000, r1, r2);
1944 s390_emit_LB(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1946 vassert(s390_host_has_ldisp);
1948 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1949 s390_disasm(ENC3(MNM, GPR, SDXB), "lb", r1, dh2, dl2, x2, b2);
1951 return emit_RXY(p, 0xe30000000076ULL, r1, x2, b2, dl2, dh2);
1956 s390_emit_LGB(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1958 vassert(s390_host_has_ldisp);
1960 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1961 s390_disasm(ENC3(MNM, GPR, SDXB), "lgb", r1, dh2, dl2, x2, b2);
1963 return emit_RXY(p, 0xe30000000077ULL, r1, x2, b2, dl2, dh2);
1968 s390_emit_LCR(UChar *p, UChar r1, UChar r2)
1970 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1971 s390_disasm(ENC3(MNM, GPR, GPR), "lcr", r1, r2);
1973 return emit_RR(p, 0x1300, r1, r2);
1978 s390_emit_LCGR(UChar *p, UChar r1, UChar r2)
1980 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1981 s390_disasm(ENC3(MNM, GPR, GPR), "lcgr", r1, r2);
1983 return emit_RRE(p, 0xb9030000, r1, r2);
1988 s390_emit_LHR(UChar *p, UChar r1, UChar r2)
1990 vassert(s390_host_has_eimm);
1992 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1993 s390_disasm(ENC3(MNM, GPR, GPR), "lhr", r1, r2);
1995 return emit_RRE(p, 0xb9270000, r1, r2);
2000 s390_emit_LGHR(UChar *p, UChar r1, UChar r2)
2002 vassert(s390_host_has_eimm);
2004 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2005 s390_disasm(ENC3(MNM, GPR, GPR), "lghr", r1, r2);
2007 return emit_RRE(p, 0xb9070000, r1, r2);
2012 s390_emit_LH(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2014 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2015 s390_disasm(ENC3(MNM, GPR, UDXB), "lh", r1, d2, x2, b2);
2017 return emit_RX(p, 0x48000000, r1, x2, b2, d2);
2022 s390_emit_LHY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2024 vassert(s390_host_has_ldisp);
2026 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2027 s390_disasm(ENC3(MNM, GPR, SDXB), "lhy", r1, dh2, dl2, x2, b2);
2029 return emit_RXY(p, 0xe30000000078ULL, r1, x2, b2, dl2, dh2);
2034 s390_emit_LGH(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2036 vassert(s390_host_has_ldisp || dh2 == 0);
2038 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2039 s390_disasm(ENC3(MNM, GPR, SDXB), "lgh", r1, dh2, dl2, x2, b2);
2041 return emit_RXY(p, 0xe30000000015ULL, r1, x2, b2, dl2, dh2);
2046 s390_emit_LHI(UChar *p, UChar r1, UShort i2)
2048 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2049 s390_disasm(ENC3(MNM, GPR, INT), "lhi", r1, (Int)(Short)i2);
2051 return emit_RI(p, 0xa7080000, r1, i2);
2056 s390_emit_LGHI(UChar *p, UChar r1, UShort i2)
2058 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2059 s390_disasm(ENC3(MNM, GPR, INT), "lghi", r1, (Int)(Short)i2);
2061 return emit_RI(p, 0xa7090000, r1, i2);
2066 s390_emit_LLGFR(UChar *p, UChar r1, UChar r2)
2068 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2069 s390_disasm(ENC3(MNM, GPR, GPR), "llgfr", r1, r2);
2071 return emit_RRE(p, 0xb9160000, r1, r2);
2076 s390_emit_LLGF(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2078 vassert(s390_host_has_ldisp || dh2 == 0);
2080 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2081 s390_disasm(ENC3(MNM, GPR, SDXB), "llgf", r1, dh2, dl2, x2, b2);
2083 return emit_RXY(p, 0xe30000000016ULL, r1, x2, b2, dl2, dh2);
2088 s390_emit_LLCR(UChar *p, UChar r1, UChar r2)
2090 vassert(s390_host_has_eimm);
2092 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2093 s390_disasm(ENC3(MNM, GPR, GPR), "llcr", r1, r2);
2095 return emit_RRE(p, 0xb9940000, r1, r2);
2100 s390_emit_LLGCR(UChar *p, UChar r1, UChar r2)
2102 vassert(s390_host_has_eimm);
2104 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2105 s390_disasm(ENC3(MNM, GPR, GPR), "llgcr", r1, r2);
2107 return emit_RRE(p, 0xb9840000, r1, r2);
2112 s390_emit_LLC(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2114 vassert(s390_host_has_eimm);
2116 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2117 s390_disasm(ENC3(MNM, GPR, SDXB), "llc", r1, dh2, dl2, x2, b2);
2119 return emit_RXY(p, 0xe30000000094ULL, r1, x2, b2, dl2, dh2);
2124 s390_emit_LLGC(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2126 vassert(s390_host_has_ldisp || dh2 == 0);
2128 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2129 s390_disasm(ENC3(MNM, GPR, SDXB), "llgc", r1, dh2, dl2, x2, b2);
2131 return emit_RXY(p, 0xe30000000090ULL, r1, x2, b2, dl2, dh2);
2136 s390_emit_LLHR(UChar *p, UChar r1, UChar r2)
2138 vassert(s390_host_has_eimm);
2140 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2141 s390_disasm(ENC3(MNM, GPR, GPR), "llhr", r1, r2);
2143 return emit_RRE(p, 0xb9950000, r1, r2);
2148 s390_emit_LLGHR(UChar *p, UChar r1, UChar r2)
2150 vassert(s390_host_has_eimm);
2152 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2153 s390_disasm(ENC3(MNM, GPR, GPR), "llghr", r1, r2);
2155 return emit_RRE(p, 0xb9850000, r1, r2);
2160 s390_emit_LLH(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2162 vassert(s390_host_has_eimm);
2164 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2165 s390_disasm(ENC3(MNM, GPR, SDXB), "llh", r1, dh2, dl2, x2, b2);
2167 return emit_RXY(p, 0xe30000000095ULL, r1, x2, b2, dl2, dh2);
2172 s390_emit_LLGH(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2174 vassert(s390_host_has_ldisp || dh2 == 0);
2176 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2177 s390_disasm(ENC3(MNM, GPR, SDXB), "llgh", r1, dh2, dl2, x2, b2);
2179 return emit_RXY(p, 0xe30000000091ULL, r1, x2, b2, dl2, dh2);
2184 s390_emit_LLILF(UChar *p, UChar r1, UInt i2)
2186 vassert(s390_host_has_eimm);
2188 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2189 s390_disasm(ENC3(MNM, GPR, UINT), "llilf", r1, i2);
2191 return emit_RIL(p, 0xc00f00000000ULL, r1, i2);
2196 s390_emit_LLILH(UChar *p, UChar r1, UShort i2)
2198 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2199 s390_disasm(ENC3(MNM, GPR, UINT), "llilh", r1, i2);
2201 return emit_RI(p, 0xa50e0000, r1, i2);
2206 s390_emit_LLILL(UChar *p, UChar r1, UShort i2)
2208 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2209 s390_disasm(ENC3(MNM, GPR, UINT), "llill", r1, i2);
2211 return emit_RI(p, 0xa50f0000, r1, i2);
2216 s390_emit_MR(UChar *p, UChar r1, UChar r2)
2218 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2219 s390_disasm(ENC3(MNM, GPR, GPR), "mr", r1, r2);
2221 return emit_RR(p, 0x1c00, r1, r2);
2226 s390_emit_M(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2228 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2229 s390_disasm(ENC3(MNM, GPR, UDXB), "m", r1, d2, x2, b2);
2231 return emit_RX(p, 0x5c000000, r1, x2, b2, d2);
2236 s390_emit_MFY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2238 vassert(s390_host_has_gie);
2240 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2241 s390_disasm(ENC3(MNM, GPR, SDXB), "mfy", r1, dh2, dl2, x2, b2);
2243 return emit_RXY(p, 0xe3000000005cULL, r1, x2, b2, dl2, dh2);
2248 s390_emit_MH(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2250 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2251 s390_disasm(ENC3(MNM, GPR, UDXB), "mh", r1, d2, x2, b2);
2253 return emit_RX(p, 0x4c000000, r1, x2, b2, d2);
2258 s390_emit_MHY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2260 vassert(s390_host_has_gie);
2262 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2263 s390_disasm(ENC3(MNM, GPR, SDXB), "mhy", r1, dh2, dl2, x2, b2);
2265 return emit_RXY(p, 0xe3000000007cULL, r1, x2, b2, dl2, dh2);
2270 s390_emit_MHI(UChar *p, UChar r1, UShort i2)
2272 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2273 s390_disasm(ENC3(MNM, GPR, INT), "mhi", r1, (Int)(Short)i2);
2275 return emit_RI(p, 0xa70c0000, r1, i2);
2280 s390_emit_MLR(UChar *p, UChar r1, UChar r2)
2282 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2283 s390_disasm(ENC3(MNM, GPR, GPR), "mlr", r1, r2);
2285 return emit_RRE(p, 0xb9960000, r1, r2);
2290 s390_emit_MLGR(UChar *p, UChar r1, UChar r2)
2292 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2293 s390_disasm(ENC3(MNM, GPR, GPR), "mlgr", r1, r2);
2295 return emit_RRE(p, 0xb9860000, r1, r2);
2300 s390_emit_ML(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2302 vassert(s390_host_has_ldisp || dh2 == 0);
2304 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2305 s390_disasm(ENC3(MNM, GPR, SDXB), "ml", r1, dh2, dl2, x2, b2);
2307 return emit_RXY(p, 0xe30000000096ULL, r1, x2, b2, dl2, dh2);
2312 s390_emit_MLG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2314 vassert(s390_host_has_ldisp || dh2 == 0);
2316 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2317 s390_disasm(ENC3(MNM, GPR, SDXB), "mlg", r1, dh2, dl2, x2, b2);
2319 return emit_RXY(p, 0xe30000000086ULL, r1, x2, b2, dl2, dh2);
2324 s390_emit_MSR(UChar *p, UChar r1, UChar r2)
2326 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2327 s390_disasm(ENC3(MNM, GPR, GPR), "msr", r1, r2);
2329 return emit_RRE(p, 0xb2520000, r1, r2);
2334 s390_emit_MSGR(UChar *p, UChar r1, UChar r2)
2336 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2337 s390_disasm(ENC3(MNM, GPR, GPR), "msgr", r1, r2);
2339 return emit_RRE(p, 0xb90c0000, r1, r2);
2344 s390_emit_MS(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2346 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2347 s390_disasm(ENC3(MNM, GPR, UDXB), "ms", r1, d2, x2, b2);
2349 return emit_RX(p, 0x71000000, r1, x2, b2, d2);
2354 s390_emit_MSY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2356 vassert(s390_host_has_ldisp);
2358 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2359 s390_disasm(ENC3(MNM, GPR, SDXB), "msy", r1, dh2, dl2, x2, b2);
2361 return emit_RXY(p, 0xe30000000051ULL, r1, x2, b2, dl2, dh2);
2366 s390_emit_MSG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2368 vassert(s390_host_has_ldisp || dh2 == 0);
2370 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2371 s390_disasm(ENC3(MNM, GPR, SDXB), "msg", r1, dh2, dl2, x2, b2);
2373 return emit_RXY(p, 0xe3000000000cULL, r1, x2, b2, dl2, dh2);
2378 s390_emit_MSFI(UChar *p, UChar r1, UInt i2)
2380 vassert(s390_host_has_gie);
2382 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2383 s390_disasm(ENC3(MNM, GPR, INT), "msfi", r1, i2);
2385 return emit_RIL(p, 0xc20100000000ULL, r1, i2);
2390 s390_emit_MSGFI(UChar *p, UChar r1, UInt i2)
2392 vassert(s390_host_has_gie);
2394 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2395 s390_disasm(ENC3(MNM, GPR, INT), "msgfi", r1, i2);
2397 return emit_RIL(p, 0xc20000000000ULL, r1, i2);
2402 s390_emit_OR(UChar *p, UChar r1, UChar r2)
2404 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2405 s390_disasm(ENC3(MNM, GPR, GPR), "or", r1, r2);
2407 return emit_RR(p, 0x1600, r1, r2);
2412 s390_emit_OGR(UChar *p, UChar r1, UChar r2)
2414 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2415 s390_disasm(ENC3(MNM, GPR, GPR), "ogr", r1, r2);
2417 return emit_RRE(p, 0xb9810000, r1, r2);
2422 s390_emit_O(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2424 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2425 s390_disasm(ENC3(MNM, GPR, UDXB), "o", r1, d2, x2, b2);
2427 return emit_RX(p, 0x56000000, r1, x2, b2, d2);
2432 s390_emit_OY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2434 vassert(s390_host_has_ldisp);
2436 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2437 s390_disasm(ENC3(MNM, GPR, SDXB), "oy", r1, dh2, dl2, x2, b2);
2439 return emit_RXY(p, 0xe30000000056ULL, r1, x2, b2, dl2, dh2);
2444 s390_emit_OG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2446 vassert(s390_host_has_ldisp || dh2 == 0);
2448 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2449 s390_disasm(ENC3(MNM, GPR, SDXB), "og", r1, dh2, dl2, x2, b2);
2451 return emit_RXY(p, 0xe30000000081ULL, r1, x2, b2, dl2, dh2);
2456 s390_emit_OIHF(UChar *p, UChar r1, UInt i2)
2458 vassert(s390_host_has_eimm);
2460 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2461 s390_disasm(ENC3(MNM, GPR, UINT), "oihf", r1, i2);
2463 return emit_RIL(p, 0xc00c00000000ULL, r1, i2);
2468 s390_emit_OILF(UChar *p, UChar r1, UInt i2)
2470 vassert(s390_host_has_eimm);
2472 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2473 s390_disasm(ENC3(MNM, GPR, UINT), "oilf", r1, i2);
2475 return emit_RIL(p, 0xc00d00000000ULL, r1, i2);
2480 s390_emit_OILL(UChar *p, UChar r1, UShort i2)
2482 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2483 s390_disasm(ENC3(MNM, GPR, UINT), "oill", r1, i2);
2485 return emit_RI(p, 0xa50b0000, r1, i2);
2490 s390_emit_SLL(UChar *p, UChar r1, UChar b2, UShort d2)
2492 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2493 s390_disasm(ENC3(MNM, GPR, UDXB), "sll", r1, d2, 0, b2);
2495 return emit_RS(p, 0x89000000, r1, 0, b2, d2);
2500 s390_emit_SLLG(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
2502 vassert(s390_host_has_ldisp || dh2 == 0);
2504 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2505 s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "sllg", r1, r3, dh2, dl2, 0, b2);
2507 return emit_RSY(p, 0xeb000000000dULL, r1, r3, b2, dl2, dh2);
2512 s390_emit_SRA(UChar *p, UChar r1, UChar b2, UShort d2)
2514 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2515 s390_disasm(ENC3(MNM, GPR, UDXB), "sra", r1, d2, 0, b2);
2517 return emit_RS(p, 0x8a000000, r1, 0, b2, d2);
2522 s390_emit_SRAG(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
2524 vassert(s390_host_has_ldisp || dh2 == 0);
2526 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2527 s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "srag", r1, r3, dh2, dl2, 0, b2);
2529 return emit_RSY(p, 0xeb000000000aULL, r1, r3, b2, dl2, dh2);
2534 s390_emit_SRL(UChar *p, UChar r1, UChar b2, UShort d2)
2536 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2537 s390_disasm(ENC3(MNM, GPR, UDXB), "srl", r1, d2, 0, b2);
2539 return emit_RS(p, 0x88000000, r1, 0, b2, d2);
2544 s390_emit_SRLG(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
2546 vassert(s390_host_has_ldisp || dh2 == 0);
2548 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2549 s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "srlg", r1, r3, dh2, dl2, 0, b2);
2551 return emit_RSY(p, 0xeb000000000cULL, r1, r3, b2, dl2, dh2);
2556 s390_emit_ST(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2558 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2559 s390_disasm(ENC3(MNM, GPR, UDXB), "st", r1, d2, x2, b2);
2561 return emit_RX(p, 0x50000000, r1, x2, b2, d2);
2566 s390_emit_STY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2568 vassert(s390_host_has_ldisp);
2570 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2571 s390_disasm(ENC3(MNM, GPR, SDXB), "sty", r1, dh2, dl2, x2, b2);
2573 return emit_RXY(p, 0xe30000000050ULL, r1, x2, b2, dl2, dh2);
2578 s390_emit_STG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2580 vassert(s390_host_has_ldisp || dh2 == 0);
2582 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2583 s390_disasm(ENC3(MNM, GPR, SDXB), "stg", r1, dh2, dl2, x2, b2);
2585 return emit_RXY(p, 0xe30000000024ULL, r1, x2, b2, dl2, dh2);
2590 s390_emit_STC(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2592 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2593 s390_disasm(ENC3(MNM, GPR, UDXB), "stc", r1, d2, x2, b2);
2595 return emit_RX(p, 0x42000000, r1, x2, b2, d2);
2600 s390_emit_STCY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2602 vassert(s390_host_has_ldisp);
2604 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2605 s390_disasm(ENC3(MNM, GPR, SDXB), "stcy", r1, dh2, dl2, x2, b2);
2607 return emit_RXY(p, 0xe30000000072ULL, r1, x2, b2, dl2, dh2);
2612 s390_emit_STH(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2614 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2615 s390_disasm(ENC3(MNM, GPR, UDXB), "sth", r1, d2, x2, b2);
2617 return emit_RX(p, 0x40000000, r1, x2, b2, d2);
2622 s390_emit_STHY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2624 vassert(s390_host_has_ldisp);
2626 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2627 s390_disasm(ENC3(MNM, GPR, SDXB), "sthy", r1, dh2, dl2, x2, b2);
2629 return emit_RXY(p, 0xe30000000070ULL, r1, x2, b2, dl2, dh2);
2634 s390_emit_SR(UChar *p, UChar r1, UChar r2)
2636 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2637 s390_disasm(ENC3(MNM, GPR, GPR), "sr", r1, r2);
2639 return emit_RR(p, 0x1b00, r1, r2);
2644 s390_emit_SGR(UChar *p, UChar r1, UChar r2)
2646 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2647 s390_disasm(ENC3(MNM, GPR, GPR), "sgr", r1, r2);
2649 return emit_RRE(p, 0xb9090000, r1, r2);
2654 s390_emit_S(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2656 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2657 s390_disasm(ENC3(MNM, GPR, UDXB), "s", r1, d2, x2, b2);
2659 return emit_RX(p, 0x5b000000, r1, x2, b2, d2);
2664 s390_emit_SY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2666 vassert(s390_host_has_ldisp);
2668 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2669 s390_disasm(ENC3(MNM, GPR, SDXB), "sy", r1, dh2, dl2, x2, b2);
2671 return emit_RXY(p, 0xe3000000005bULL, r1, x2, b2, dl2, dh2);
2676 s390_emit_SG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2678 vassert(s390_host_has_ldisp || dh2 == 0);
2680 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2681 s390_disasm(ENC3(MNM, GPR, SDXB), "sg", r1, dh2, dl2, x2, b2);
2683 return emit_RXY(p, 0xe30000000009ULL, r1, x2, b2, dl2, dh2);
2688 s390_emit_SH(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2690 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2691 s390_disasm(ENC3(MNM, GPR, UDXB), "sh", r1, d2, x2, b2);
2693 return emit_RX(p, 0x4b000000, r1, x2, b2, d2);
2698 s390_emit_SHY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2700 vassert(s390_host_has_ldisp);
2702 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2703 s390_disasm(ENC3(MNM, GPR, SDXB), "shy", r1, dh2, dl2, x2, b2);
2705 return emit_RXY(p, 0xe3000000007bULL, r1, x2, b2, dl2, dh2);
2710 s390_emit_SLFI(UChar *p, UChar r1, UInt i2)
2712 vassert(s390_host_has_eimm);
2714 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2715 s390_disasm(ENC3(MNM, GPR, UINT), "slfi", r1, i2);
2717 return emit_RIL(p, 0xc20500000000ULL, r1, i2);
2722 s390_emit_SLGFI(UChar *p, UChar r1, UInt i2)
2724 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2725 s390_disasm(ENC3(MNM, GPR, UINT), "slgfi", r1, i2);
2727 return emit_RIL(p, 0xc20400000000ULL, r1, i2);
2732 s390_emit_LDR(UChar *p, UChar r1, UChar r2)
2734 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2735 s390_disasm(ENC3(MNM, FPR, FPR), "ldr", r1, r2);
2737 return emit_RR(p, 0x2800, r1, r2);
2742 s390_emit_LE(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2744 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2745 s390_disasm(ENC3(MNM, FPR, UDXB), "le", r1, d2, x2, b2);
2747 return emit_RX(p, 0x78000000, r1, x2, b2, d2);
2752 s390_emit_LD(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2754 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2755 s390_disasm(ENC3(MNM, FPR, UDXB), "ld", r1, d2, x2, b2);
2757 return emit_RX(p, 0x68000000, r1, x2, b2, d2);
2762 s390_emit_LEY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2764 vassert(s390_host_has_ldisp);
2766 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2767 s390_disasm(ENC3(MNM, FPR, SDXB), "ley", r1, dh2, dl2, x2, b2);
2769 return emit_RXY(p, 0xed0000000064ULL, r1, x2, b2, dl2, dh2);
2774 s390_emit_LDY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2776 vassert(s390_host_has_ldisp);
2778 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2779 s390_disasm(ENC3(MNM, FPR, SDXB), "ldy", r1, dh2, dl2, x2, b2);
2781 return emit_RXY(p, 0xed0000000065ULL, r1, x2, b2, dl2, dh2);
2786 s390_emit_LFPC(UChar *p, UChar b2, UShort d2)
2788 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2789 s390_disasm(ENC2(MNM, UDXB), "lfpc", d2, 0, b2);
2791 return emit_S(p, 0xb29d0000, b2, d2);
2796 s390_emit_LDGR(UChar *p, UChar r1, UChar r2)
2798 vassert(s390_host_has_fgx);
2800 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2801 s390_disasm(ENC3(MNM, FPR, GPR), "ldgr", r1, r2);
2803 return emit_RRE(p, 0xb3c10000, r1, r2);
2808 s390_emit_LGDR(UChar *p, UChar r1, UChar r2)
2810 vassert(s390_host_has_fgx);
2812 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2813 s390_disasm(ENC3(MNM, GPR, FPR), "lgdr", r1, r2);
2815 return emit_RRE(p, 0xb3cd0000, r1, r2);
2820 s390_emit_LZER(UChar *p, UChar r1, UChar r2)
2822 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2823 s390_disasm(ENC2(MNM, FPR), "lzer", r1);
2825 return emit_RRE(p, 0xb3740000, r1, r2);
2830 s390_emit_LZDR(UChar *p, UChar r1, UChar r2)
2832 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2833 s390_disasm(ENC2(MNM, FPR), "lzdr", r1);
2835 return emit_RRE(p, 0xb3750000, r1, r2);
2840 s390_emit_SFPC(UChar *p, UChar r1, UChar r2)
2842 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2843 s390_disasm(ENC2(MNM, GPR), "sfpc", r1);
2845 return emit_RRE(p, 0xb3840000, r1, r2);
2850 s390_emit_STE(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2852 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2853 s390_disasm(ENC3(MNM, FPR, UDXB), "ste", r1, d2, x2, b2);
2855 return emit_RX(p, 0x70000000, r1, x2, b2, d2);
2860 s390_emit_STD(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2862 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2863 s390_disasm(ENC3(MNM, FPR, UDXB), "std", r1, d2, x2, b2);
2865 return emit_RX(p, 0x60000000, r1, x2, b2, d2);
2870 s390_emit_STEY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2872 vassert(s390_host_has_ldisp);
2874 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2875 s390_disasm(ENC3(MNM, FPR, SDXB), "stey", r1, dh2, dl2, x2, b2);
2877 return emit_RXY(p, 0xed0000000066ULL, r1, x2, b2, dl2, dh2);
2882 s390_emit_STDY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2884 vassert(s390_host_has_ldisp);
2886 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2887 s390_disasm(ENC3(MNM, FPR, SDXB), "stdy", r1, dh2, dl2, x2, b2);
2889 return emit_RXY(p, 0xed0000000067ULL, r1, x2, b2, dl2, dh2);
2894 s390_emit_STFPC(UChar *p, UChar b2, UShort d2)
2896 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2897 s390_disasm(ENC2(MNM, UDXB), "stfpc", d2, 0, b2);
2899 return emit_S(p, 0xb29c0000, b2, d2);
2904 s390_emit_AEBR(UChar *p, UChar r1, UChar r2)
2906 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2907 s390_disasm(ENC3(MNM, FPR, FPR), "aebr", r1, r2);
2909 return emit_RRE(p, 0xb30a0000, r1, r2);
2914 s390_emit_ADBR(UChar *p, UChar r1, UChar r2)
2916 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2917 s390_disasm(ENC3(MNM, FPR, FPR), "adbr", r1, r2);
2919 return emit_RRE(p, 0xb31a0000, r1, r2);
2924 s390_emit_AXBR(UChar *p, UChar r1, UChar r2)
2926 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2927 s390_disasm(ENC3(MNM, FPR, FPR), "axbr", r1, r2);
2929 return emit_RRE(p, 0xb34a0000, r1, r2);
2934 s390_emit_CEBR(UChar *p, UChar r1, UChar r2)
2936 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2937 s390_disasm(ENC3(MNM, FPR, FPR), "cebr", r1, r2);
2939 return emit_RRE(p, 0xb3090000, r1, r2);
2944 s390_emit_CDBR(UChar *p, UChar r1, UChar r2)
2946 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2947 s390_disasm(ENC3(MNM, FPR, FPR), "cdbr", r1, r2);
2949 return emit_RRE(p, 0xb3190000, r1, r2);
2954 s390_emit_CXBR(UChar *p, UChar r1, UChar r2)
2956 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2957 s390_disasm(ENC3(MNM, FPR, FPR), "cxbr", r1, r2);
2959 return emit_RRE(p, 0xb3490000, r1, r2);
2964 s390_emit_CEFBR(UChar *p, UChar r1, UChar r2)
2966 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2967 s390_disasm(ENC3(MNM, FPR, GPR), "cefbr", r1, r2);
2969 return emit_RRE(p, 0xb3940000, r1, r2);
2974 s390_emit_CDFBR(UChar *p, UChar r1, UChar r2)
2976 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2977 s390_disasm(ENC3(MNM, FPR, GPR), "cdfbr", r1, r2);
2979 return emit_RRE(p, 0xb3950000, r1, r2);
2984 s390_emit_CXFBR(UChar *p, UChar r1, UChar r2)
2986 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2987 s390_disasm(ENC3(MNM, FPR, GPR), "cxfbr", r1, r2);
2989 return emit_RRE(p, 0xb3960000, r1, r2);
2994 s390_emit_CEGBR(UChar *p, UChar r1, UChar r2)
2996 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2997 s390_disasm(ENC3(MNM, FPR, GPR), "cegbr", r1, r2);
2999 return emit_RRE(p, 0xb3a40000, r1, r2);
3004 s390_emit_CDGBR(UChar *p, UChar r1, UChar r2)
3006 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3007 s390_disasm(ENC3(MNM, FPR, GPR), "cdgbr", r1, r2);
3009 return emit_RRE(p, 0xb3a50000, r1, r2);
3014 s390_emit_CXGBR(UChar *p, UChar r1, UChar r2)
3016 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3017 s390_disasm(ENC3(MNM, FPR, GPR), "cxgbr", r1, r2);
3019 return emit_RRE(p, 0xb3a60000, r1, r2);
3024 s390_emit_CFEBR(UChar *p, UChar r3, UChar r1, UChar r2)
3026 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3027 s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cfebr", r1, r3, r2);
3029 return emit_RRF3(p, 0xb3980000, r3, r1, r2);
3034 s390_emit_CFDBR(UChar *p, UChar r3, UChar r1, UChar r2)
3036 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3037 s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cfdbr", r1, r3, r2);
3039 return emit_RRF3(p, 0xb3990000, r3, r1, r2);
3044 s390_emit_CFXBR(UChar *p, UChar r3, UChar r1, UChar r2)
3046 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3047 s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cfxbr", r1, r3, r2);
3049 return emit_RRF3(p, 0xb39a0000, r3, r1, r2);
3054 s390_emit_CGEBR(UChar *p, UChar r3, UChar r1, UChar r2)
3056 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3057 s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cgebr", r1, r3, r2);
3059 return emit_RRF3(p, 0xb3a80000, r3, r1, r2);
3064 s390_emit_CGDBR(UChar *p, UChar r3, UChar r1, UChar r2)
3066 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3067 s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cgdbr", r1, r3, r2);
3069 return emit_RRF3(p, 0xb3a90000, r3, r1, r2);
3074 s390_emit_CGXBR(UChar *p, UChar r3, UChar r1, UChar r2)
3076 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3077 s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cgxbr", r1, r3, r2);
3079 return emit_RRF3(p, 0xb3aa0000, r3, r1, r2);
3084 s390_emit_DEBR(UChar *p, UChar r1, UChar r2)
3086 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3087 s390_disasm(ENC3(MNM, FPR, FPR), "debr", r1, r2);
3089 return emit_RRE(p, 0xb30d0000, r1, r2);
3094 s390_emit_DDBR(UChar *p, UChar r1, UChar r2)
3096 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3097 s390_disasm(ENC3(MNM, FPR, FPR), "ddbr", r1, r2);
3099 return emit_RRE(p, 0xb31d0000, r1, r2);
3104 s390_emit_DXBR(UChar *p, UChar r1, UChar r2)
3106 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3107 s390_disasm(ENC3(MNM, FPR, FPR), "dxbr", r1, r2);
3109 return emit_RRE(p, 0xb34d0000, r1, r2);
3114 s390_emit_LCEBR(UChar *p, UChar r1, UChar r2)
3116 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3117 s390_disasm(ENC3(MNM, FPR, FPR), "lcebr", r1, r2);
3119 return emit_RRE(p, 0xb3030000, r1, r2);
3124 s390_emit_LCDBR(UChar *p, UChar r1, UChar r2)
3126 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3127 s390_disasm(ENC3(MNM, FPR, FPR), "lcdbr", r1, r2);
3129 return emit_RRE(p, 0xb3130000, r1, r2);
3134 s390_emit_LCXBR(UChar *p, UChar r1, UChar r2)
3136 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3137 s390_disasm(ENC3(MNM, FPR, FPR), "lcxbr", r1, r2);
3139 return emit_RRE(p, 0xb3430000, r1, r2);
3144 s390_emit_LDEBR(UChar *p, UChar r1, UChar r2)
3146 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3147 s390_disasm(ENC3(MNM, FPR, FPR), "ldebr", r1, r2);
3149 return emit_RRE(p, 0xb3040000, r1, r2);
3154 s390_emit_LXDBR(UChar *p, UChar r1, UChar r2)
3156 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3157 s390_disasm(ENC3(MNM, FPR, FPR), "lxdbr", r1, r2);
3159 return emit_RRE(p, 0xb3050000, r1, r2);
3164 s390_emit_LXEBR(UChar *p, UChar r1, UChar r2)
3166 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3167 s390_disasm(ENC3(MNM, FPR, FPR), "lxebr", r1, r2);
3169 return emit_RRE(p, 0xb3060000, r1, r2);
3174 s390_emit_LNEBR(UChar *p, UChar r1, UChar r2)
3176 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3177 s390_disasm(ENC3(MNM, FPR, FPR), "lnebr", r1, r2);
3179 return emit_RRE(p, 0xb3010000, r1, r2);
3184 s390_emit_LNDBR(UChar *p, UChar r1, UChar r2)
3186 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3187 s390_disasm(ENC3(MNM, FPR, FPR), "lndbr", r1, r2);
3189 return emit_RRE(p, 0xb3110000, r1, r2);
3194 s390_emit_LNXBR(UChar *p, UChar r1, UChar r2)
3196 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3197 s390_disasm(ENC3(MNM, FPR, FPR), "lnxbr", r1, r2);
3199 return emit_RRE(p, 0xb3410000, r1, r2);
3204 s390_emit_LPEBR(UChar *p, UChar r1, UChar r2)
3206 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3207 s390_disasm(ENC3(MNM, FPR, FPR), "lpebr", r1, r2);
3209 return emit_RRE(p, 0xb3000000, r1, r2);
3214 s390_emit_LPDBR(UChar *p, UChar r1, UChar r2)
3216 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3217 s390_disasm(ENC3(MNM, FPR, FPR), "lpdbr", r1, r2);
3219 return emit_RRE(p, 0xb3100000, r1, r2);
3224 s390_emit_LPXBR(UChar *p, UChar r1, UChar r2)
3226 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3227 s390_disasm(ENC3(MNM, FPR, FPR), "lpxbr", r1, r2);
3229 return emit_RRE(p, 0xb3400000, r1, r2);
3234 s390_emit_LEDBR(UChar *p, UChar r1, UChar r2)
3236 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3237 s390_disasm(ENC3(MNM, FPR, FPR), "ledbr", r1, r2);
3239 return emit_RRE(p, 0xb3440000, r1, r2);
3244 s390_emit_LDXBR(UChar *p, UChar r1, UChar r2)
3246 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3247 s390_disasm(ENC3(MNM, FPR, FPR), "ldxbr", r1, r2);
3249 return emit_RRE(p, 0xb3450000, r1, r2);
3254 s390_emit_LEXBR(UChar *p, UChar r1, UChar r2)
3256 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3257 s390_disasm(ENC3(MNM, FPR, FPR), "lexbr", r1, r2);
3259 return emit_RRE(p, 0xb3460000, r1, r2);
3264 s390_emit_MEEBR(UChar *p, UChar r1, UChar r2)
3266 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3267 s390_disasm(ENC3(MNM, FPR, FPR), "meebr", r1, r2);
3269 return emit_RRE(p, 0xb3170000, r1, r2);
3274 s390_emit_MDBR(UChar *p, UChar r1, UChar r2)
3276 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3277 s390_disasm(ENC3(MNM, FPR, FPR), "mdbr", r1, r2);
3279 return emit_RRE(p, 0xb31c0000, r1, r2);
3284 s390_emit_MXBR(UChar *p, UChar r1, UChar r2)
3286 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3287 s390_disasm(ENC3(MNM, FPR, FPR), "mxbr", r1, r2);
3289 return emit_RRE(p, 0xb34c0000, r1, r2);
3294 s390_emit_MAEBR(UChar *p, UChar r1, UChar r3, UChar r2)
3296 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3297 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "maebr", r1, r3, r2);
3299 return emit_RRF(p, 0xb30e0000, r1, r3, r2);
3304 s390_emit_MADBR(UChar *p, UChar r1, UChar r3, UChar r2)
3306 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3307 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "madbr", r1, r3, r2);
3309 return emit_RRF(p, 0xb31e0000, r1, r3, r2);
3314 s390_emit_MSEBR(UChar *p, UChar r1, UChar r3, UChar r2)
3316 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3317 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "msebr", r1, r3, r2);
3319 return emit_RRF(p, 0xb30f0000, r1, r3, r2);
3324 s390_emit_MSDBR(UChar *p, UChar r1, UChar r3, UChar r2)
3326 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3327 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "msdbr", r1, r3, r2);
3329 return emit_RRF(p, 0xb31f0000, r1, r3, r2);
3334 s390_emit_SQEBR(UChar *p, UChar r1, UChar r2)
3336 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3337 s390_disasm(ENC3(MNM, FPR, FPR), "sqebr", r1, r2);
3339 return emit_RRE(p, 0xb3140000, r1, r2);
3344 s390_emit_SQDBR(UChar *p, UChar r1, UChar r2)
3346 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3347 s390_disasm(ENC3(MNM, FPR, FPR), "sqdbr", r1, r2);
3349 return emit_RRE(p, 0xb3150000, r1, r2);
3354 s390_emit_SQXBR(UChar *p, UChar r1, UChar r2)
3356 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3357 s390_disasm(ENC3(MNM, FPR, FPR), "sqxbr", r1, r2);
3359 return emit_RRE(p, 0xb3160000, r1, r2);
3364 s390_emit_SEBR(UChar *p, UChar r1, UChar r2)
3366 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3367 s390_disasm(ENC3(MNM, FPR, FPR), "sebr", r1, r2);
3369 return emit_RRE(p, 0xb30b0000, r1, r2);
3374 s390_emit_SDBR(UChar *p, UChar r1, UChar r2)
3376 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3377 s390_disasm(ENC3(MNM, FPR, FPR), "sdbr", r1, r2);
3379 return emit_RRE(p, 0xb31b0000, r1, r2);
3384 s390_emit_SXBR(UChar *p, UChar r1, UChar r2)
3386 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3387 s390_disasm(ENC3(MNM, FPR, FPR), "sxbr", r1, r2);
3389 return emit_RRE(p, 0xb34b0000, r1, r2);
3393 /* Provide a symbolic name for register "R0" */
3396 /* Split up a 20-bit displacement into its high and low piece
3397 suitable for passing as function arguments */
3398 #define DISP20(d) (((UInt)d) & 0xFFF), ((((UInt)d) >> 12) & 0xFF)
3400 /*---------------------------------------------------------------*/
3401 /*--- Helper functions ---*/
3402 /*---------------------------------------------------------------*/
3404 static __inline__ Bool
3405 uint_fits_signed_16bit(UInt val)
3407 int v = val & 0xFFFFu;
3410 v = (v << 16) >> 16;
3412 return val == (UInt)v;
3416 static __inline__ Bool
3417 ulong_fits_signed_16bit(ULong val)
3419 Long v = val & 0xFFFFu;
3422 v = (v << 48) >> 48;
3424 return val == (ULong)v;
3428 static __inline__ Bool
3429 ulong_fits_signed_32bit(ULong val)
3431 Long v = val & 0xFFFFFFFFu;
3434 v = (v << 32) >> 32;
3436 return val == (ULong)v;
3440 static __inline__ Bool
3441 ulong_fits_unsigned_32bit(ULong val)
3443 return (val & 0xFFFFFFFFu) == val;
3447 /* Load a 64-bit immediate VAL into register REG. */
3449 s390_emit_load_64imm(UChar *p, UChar reg, ULong val)
3451 if (ulong_fits_signed_16bit(val)) {
3452 return s390_emit_LGHI(p, reg, val);
3455 if (s390_host_has_eimm) {
3456 if (ulong_fits_unsigned_32bit(val)) {
3457 return s390_emit_LLILF(p, reg, val);
3459 if (ulong_fits_signed_32bit(val)) {
3460 /* LGFI's sign extension will recreate the correct 64-bit value */
3461 return s390_emit_LGFI(p, reg, val);
3463 /* Do it in two steps: upper half [0:31] and lower half [32:63] */
3464 p = s390_emit_IIHF(p, reg, val >> 32);
3465 return s390_emit_IILF(p, reg, val & 0xFFFFFFFF);
3469 if (ulong_fits_unsigned_32bit(val)) {
3470 p = s390_emit_LLILH(p, reg, (val >> 16) & 0xFFFF); /* sets val[32:47]
3472 p = s390_emit_IILL(p, reg, val & 0xFFFF); /* sets val[48:63] */
3476 p = s390_emit_IIHH(p, reg, (val >> 48) & 0xFFFF);
3477 p = s390_emit_IIHL(p, reg, (val >> 32) & 0xFFFF);
3478 p = s390_emit_IILH(p, reg, (val >> 16) & 0xFFFF);
3479 p = s390_emit_IILL(p, reg, val & 0xFFFF);
3484 /* Load a 32-bit immediate VAL into register REG. */
3486 s390_emit_load_32imm(UChar *p, UChar reg, UInt val)
3488 if (uint_fits_signed_16bit(val)) {
3489 /* LHI's sign extension will recreate the correct 32-bit value */
3490 return s390_emit_LHI(p, reg, val);
3492 if (s390_host_has_eimm) {
3493 return s390_emit_IILF(p, reg, val);
3495 /* val[0:15] --> (val >> 16) & 0xFFFF
3496 val[16:31] --> val & 0xFFFF */
3497 p = s390_emit_IILH(p, reg, (val >> 16) & 0xFFFF);
3498 return s390_emit_IILL(p, reg, val & 0xFFFF);
3501 /*------------------------------------------------------------*/
3502 /*--- Wrapper functions ---*/
3503 /*------------------------------------------------------------*/
3505 /* r1[32:63],r1+1[32:63] = r1+1[32:63] * memory[op2addr][0:31] */
3507 s390_emit_MFYw(UChar *p, UChar r1, UChar x, UChar b, UShort dl, UChar dh)
3509 if (s390_host_has_gie) {
3510 return s390_emit_MFY(p, r1, x, b, dl, dh);
3513 /* Load from memory into R0, then MULTIPLY with R1 */
3514 p = s390_emit_LY(p, R0, x, b, dl, dh);
3515 return s390_emit_MR(p, r1, R0);
3518 /* r1[32:63] = r1[32:63] * memory[op2addr][0:15] */
3520 s390_emit_MHYw(UChar *p, UChar r1, UChar x, UChar b, UShort dl, UChar dh)
3522 if (s390_host_has_gie) {
3523 return s390_emit_MHY(p, r1, x, b, dl, dh);
3526 /* Load from memory into R0, then MULTIPLY with R1 */
3527 p = s390_emit_LHY(p, R0, x, b, dl, dh);
3528 return s390_emit_MSR(p, r1, R0);
3531 /* r1[32:63] = r1[32:63] * i2 */
3533 s390_emit_MSFIw(UChar *p, UChar r1, UInt i2)
3535 if (s390_host_has_gie) {
3536 return s390_emit_MSFI(p, r1, i2);
3539 /* Load I2 into R0; then MULTIPLY R0 with R1 */
3540 p = s390_emit_load_32imm(p, R0, i2);
3541 return s390_emit_MSR(p, r1, R0);
3545 /* r1[32:63] = r1[32:63] & i2 */
3547 s390_emit_NILFw(UChar *p, UChar r1, UInt i2)
3549 if (s390_host_has_eimm) {
3550 return s390_emit_NILF(p, r1, i2);
3553 /* Load I2 into R0; then AND R0 with R1 */
3554 p = s390_emit_load_32imm(p, R0, i2);
3555 return s390_emit_NR(p, r1, R0);
3559 /* r1[32:63] = r1[32:63] | i2 */
3561 s390_emit_OILFw(UChar *p, UChar r1, UInt i2)
3563 if (s390_host_has_eimm) {
3564 return s390_emit_OILF(p, r1, i2);
3567 /* Load I2 into R0; then AND R0 with R1 */
3568 p = s390_emit_load_32imm(p, R0, i2);
3569 return s390_emit_OR(p, r1, R0);
3573 /* r1[32:63] = r1[32:63] ^ i2 */
3575 s390_emit_XILFw(UChar *p, UChar r1, UInt i2)
3577 if (s390_host_has_eimm) {
3578 return s390_emit_XILF(p, r1, i2);
3581 /* Load I2 into R0; then AND R0 with R1 */
3582 p = s390_emit_load_32imm(p, R0, i2);
3583 return s390_emit_XR(p, r1, R0);
3587 /* r1[32:63] = sign_extend(mem[op2addr][0:7]) */
3589 s390_emit_LBw(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3591 vassert(s390_host_has_ldisp || dh2 == 0);
3593 if (s390_host_has_ldisp) {
3594 return s390_emit_LB(p, r1, x2, b2, dl2, dh2);
3597 p = s390_emit_IC(p, r1, x2, b2, dl2); /* r1[56:63] = mem[op2addr][0:7] */
3598 p = s390_emit_SLL(p, r1, R0, 24); /* r1 = r1 << 24 */
3599 return s390_emit_SRA(p, r1, R0, 24); /* r1 = r1 >>a 24 */
3603 /* r1[32:63] = sign_extend(r2[56:63]) */
3605 s390_emit_LBRw(UChar *p, UChar r1, UChar r2)
3607 if (s390_host_has_eimm) {
3608 return s390_emit_LBR(p, r1, r2);
3611 p = s390_emit_LR(p, r1, r2); /* r1 = r2 */
3612 p = s390_emit_SLL(p, r1, R0, 24); /* r1 = r1 << 24 */
3613 return s390_emit_SRA(p, r1, R0, 24); /* r1 = r1 >>a 24 */
3617 /* r1[0:63] = sign_extend(mem[op2addr][0:7]) */
3619 s390_emit_LGBw(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3621 vassert(s390_host_has_ldisp || dh2 == 0);
3623 if (s390_host_has_ldisp) {
3624 return s390_emit_LGB(p, r1, x2, b2, dl2, dh2);
3627 p = s390_emit_IC(p, r1, x2, b2, dl2); /* r1[56:63] = mem[op2addr][0:7] */
3628 p = s390_emit_SLLG(p, r1, r1, R0, DISP20(56)); /* r1 = r1 << 56 */
3629 return s390_emit_SRAG(p, r1, r1, R0, DISP20(56)); /* r1 = r1 >>a 56 */
3633 /* r1[0:63] = sign_extend(r2[56:63]) */
3635 s390_emit_LGBRw(UChar *p, UChar r1, UChar r2)
3637 if (s390_host_has_eimm) {
3638 return s390_emit_LGBR(p, r1, r2);
3641 p = s390_emit_LR(p, r1, r2); /* r1 = r2 */
3642 p = s390_emit_SLLG(p, r1, r1, R0, DISP20(56)); /* r1 = r1 << 56 */
3643 return s390_emit_SRAG(p, r1, r1, R0, DISP20(56)); /* r1 = r1 >>a 56 */
3647 /* r1[32:63] = sign_extend(r2[48:63]) */
3649 s390_emit_LHRw(UChar *p, UChar r1, UChar r2)
3651 if (s390_host_has_eimm) {
3652 return s390_emit_LHR(p, r1, r2);
3655 p = s390_emit_LR(p, r1, r2); /* r1 = r2 */
3656 p = s390_emit_SLL(p, r1, R0, 16); /* r1 = r1 << 16 */
3657 return s390_emit_SRA(p, r1, R0, 16); /* r1 = r1 >>a 16 */
3661 /* r1[0:63] = sign_extend(r2[48:63]) */
3663 s390_emit_LGHRw(UChar *p, UChar r1, UChar r2)
3665 if (s390_host_has_eimm) {
3666 return s390_emit_LGHR(p, r1, r2);
3669 p = s390_emit_LR(p, r1, r2); /* r1 = r2 */
3670 p = s390_emit_SLLG(p, r1, r1, R0, DISP20(48)); /* r1 = r1 << 48 */
3671 return s390_emit_SRAG(p, r1, r1, R0, DISP20(48)); /* r1 = r1 >>a 48 */
3675 /* r1[0:63] = sign_extend(i2) */
3677 s390_emit_LGFIw(UChar *p, UChar r1, UInt i2)
3679 if (s390_host_has_eimm) {
3680 return s390_emit_LGFI(p, r1, i2);
3683 p = s390_emit_load_32imm(p, R0, i2);
3684 return s390_emit_LGFR(p, r1, R0);
3688 /* r1[32:63] = zero_extend($r2[56:63]) */
3690 s390_emit_LLCRw(UChar *p, UChar r1, UChar r2)
3692 if (s390_host_has_eimm) {
3693 return s390_emit_LLCR(p, r1, r2);
3696 p = s390_emit_LR(p, r1, r2);
3697 p = s390_emit_LHI(p, R0, 0xFF);
3698 return s390_emit_NR(p, r1, R0);
3702 /* r1[0:63] = zero_extend($r2[56:63]) */
3704 s390_emit_LLGCRw(UChar *p, UChar r1, UChar r2)
3706 if (s390_host_has_eimm) {
3707 return s390_emit_LLGCR(p, r1, r2);
3710 p = s390_emit_LR(p, r1, r2);
3711 p = s390_emit_LLILL(p, R0, 0xFF);
3712 return s390_emit_NGR(p, r1, R0);
3716 /* r1[32:63] = zero_extend(r2[48:63]) */
3718 s390_emit_LLHRw(UChar *p, UChar r1, UChar r2)
3720 if (s390_host_has_eimm) {
3721 return s390_emit_LLHR(p, r1, r2);
3724 p = s390_emit_LR(p, r1, r2);
3725 p = s390_emit_LLILL(p, R0, 0xFFFF);
3726 return s390_emit_NR(p, r1, R0);
3730 /* r1[0:63] = zero_extend(r2[48:63]) */
3732 s390_emit_LLGHRw(UChar *p, UChar r1, UChar r2)
3734 if (s390_host_has_eimm) {
3735 return s390_emit_LLGHR(p, r1, r2);
3738 p = s390_emit_LR(p, r1, r2);
3739 p = s390_emit_LLILL(p, R0, 0xFFFF);
3740 return s390_emit_NGR(p, r1, R0);
3744 /* r1[32:63] = zero_extend(mem[op2addr][0:7]) */
3746 s390_emit_LLCw(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl, UChar dh)
3748 if (s390_host_has_eimm) {
3749 return s390_emit_LLC(p, r1, x2, b2, dl, dh);
3753 p = s390_emit_IC(p, r1, x2, b2, dl);
3755 p = s390_emit_ICY(p, r1, x2, b2, dl, dh);
3757 p = s390_emit_LLILL(p, R0, 0xFF);
3758 return s390_emit_NR(p, r1, R0);
3762 /* r1[32:63] = zero_extend(mem[op2addr][0:15]) */
3764 s390_emit_LLHw(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl, UChar dh)
3766 if (s390_host_has_eimm) {
3767 return s390_emit_LLH(p, r1, x2, b2, dl, dh);
3770 p = s390_emit_LLGH(p, r1, x2, b2, dl, dh);
3771 p = s390_emit_LLILL(p, R0, 0xFFFF);
3772 return s390_emit_NR(p, r1, R0);
3776 /* r1[0:63] = zero_extend(i2) */
3778 s390_emit_LLILFw(UChar *p, UChar r1, UInt i2)
3780 if (s390_host_has_eimm) {
3781 return s390_emit_LLILF(p, r1, i2);
3784 p = s390_emit_LLILH(p, r1, (i2 >> 16) & 0xFFFF); /* i2[0:15] */
3785 return s390_emit_OILL(p, r1, i2 & 0xFFFF);
3789 /* r1[32:63] = r1[32:63] + i2 */
3791 s390_emit_AFIw(UChar *p, UChar r1, UInt i2)
3793 if (s390_host_has_eimm) {
3794 return s390_emit_AFI(p, r1, i2);
3796 /* Load 32 bit immediate to R0 then add */
3797 p = s390_emit_load_32imm(p, R0, i2);
3798 return s390_emit_AR(p, r1, R0);
3802 /* r1[32:63] = r1[32:63] - i2 */
3804 s390_emit_SLFIw(UChar *p, UChar r1, UInt i2)
3806 if (s390_host_has_eimm) {
3807 return s390_emit_SLFI(p, r1, i2);
3810 /* Load 32 bit immediate to R0 then subtract */
3811 p = s390_emit_load_32imm(p, R0, i2);
3812 return s390_emit_SR(p, r1, R0);
3816 /* r1[0:63] = r1[0:63] - zero_extend(i2) */
3818 s390_emit_SLGFIw(UChar *p, UChar r1, UInt i2)
3820 if (s390_host_has_eimm) {
3821 return s390_emit_SLGFI(p, r1, i2);
3824 /* Load zero-extended 32 bit immediate to R0 then subtract */
3825 p = s390_emit_load_64imm(p, R0, i2);
3826 return s390_emit_SGR(p, r1, R0);
3831 s390_emit_LTw(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl, UChar dh)
3833 if (s390_host_has_eimm) {
3834 return s390_emit_LT(p, r1, x2, b2, dl, dh);
3836 /* Load 32 bit from memory to R0 then compare */
3838 p = s390_emit_L(p, R0, x2, b2, dl);
3840 p = s390_emit_LY(p, R0, x2, b2, dl, dh);
3842 return s390_emit_LTR(p, r1, R0);
3847 s390_emit_LTGw(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl, UChar dh)
3849 if (s390_host_has_eimm) {
3850 return s390_emit_LTG(p, r1, x2, b2, dl, dh);
3852 /* Load 64 bit from memory to R0 then compare */
3853 p = s390_emit_LG(p, R0, x2, b2, dl, dh);
3854 return s390_emit_LTGR(p, r1, R0);
3859 s390_emit_CFIw(UChar *p, UChar r1, UInt i2)
3861 if (s390_host_has_eimm) {
3862 return s390_emit_CFI(p, r1, i2);
3864 /* Load 32 bit immediate to R0 then compare */
3865 p = s390_emit_load_32imm(p, R0, i2);
3866 return s390_emit_CR(p, r1, R0);
3871 s390_emit_CLFIw(UChar *p, UChar r1, UInt i2)
3873 if (s390_host_has_eimm) {
3874 return s390_emit_CLFI(p, r1, i2);
3876 /* Load 32 bit immediate to R0 then compare */
3877 p = s390_emit_load_32imm(p, R0, i2);
3878 return s390_emit_CLR(p, r1, R0);
3883 s390_emit_LGDRw(UChar *p, UChar r1, UChar r2)
3885 if (s390_host_has_fgx) {
3886 return s390_emit_LGDR(p, r1, r2);
3889 /* Store the FPR at memory[sp - 8]. This is safe because SP grows towards
3890 smaller addresses and is 8-byte aligned. Then load the GPR from that
3892 if (s390_host_has_ldisp) {
3893 p = s390_emit_STDY(p, r2, R0, S390_REGNO_STACK_POINTER, DISP20(-8));
3894 return s390_emit_LG(p, r1, R0, S390_REGNO_STACK_POINTER, DISP20(-8));
3897 /* No long displacement. Need to adjust SP explicitly as to avoid negative
3899 p = s390_emit_AGHI(p, S390_REGNO_STACK_POINTER, -8);
3900 p = s390_emit_STD(p, r2, R0, S390_REGNO_STACK_POINTER, 0);
3901 p = s390_emit_LG(p, r1, R0, S390_REGNO_STACK_POINTER, DISP20(0));
3902 return s390_emit_AGHI(p, S390_REGNO_STACK_POINTER, 8);
3907 s390_emit_LDGRw(UChar *p, UChar r1, UChar r2)
3909 if (s390_host_has_fgx) {
3910 return s390_emit_LDGR(p, r1, r2);
3913 /* Store the GPR at memory[sp - 8]. This is safe because SP grows towards
3914 smaller addresses and is 8-byte aligned. Then load the FPR from that
3916 if (s390_host_has_ldisp) {
3917 p = s390_emit_STG(p, r2, R0, S390_REGNO_STACK_POINTER, DISP20(-8));
3918 return s390_emit_LDY(p, r1, R0, S390_REGNO_STACK_POINTER, DISP20(-8));
3921 /* No long displacement. Need to adjust SP explicitly as to avoid negative
3923 p = s390_emit_AGHI(p, S390_REGNO_STACK_POINTER, -8);
3924 p = s390_emit_STG(p, r2, R0, S390_REGNO_STACK_POINTER, DISP20(0));
3925 p = s390_emit_LD(p, r1, R0, S390_REGNO_STACK_POINTER, 0);
3926 return s390_emit_AGHI(p, S390_REGNO_STACK_POINTER, 8);
3930 /*---------------------------------------------------------------*/
3931 /*--- Constructors for the various s390_insn kinds ---*/
3932 /*---------------------------------------------------------------*/
3935 s390_insn_load(UChar size, HReg dst, s390_amode *src)
3937 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
3939 insn->tag = S390_INSN_LOAD;
3941 insn->variant.load.src = src;
3942 insn->variant.load.dst = dst;
3944 vassert(size == 1 || size == 2 || size == 4 || size == 8);
3951 s390_insn_store(UChar size, s390_amode *dst, HReg src)
3953 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
3955 insn->tag = S390_INSN_STORE;
3957 insn->variant.store.src = src;
3958 insn->variant.store.dst = dst;
3960 vassert(size == 1 || size == 2 || size == 4 || size == 8);
3967 s390_insn_move(UChar size, HReg dst, HReg src)
3969 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
3971 insn->tag = S390_INSN_MOVE;
3973 insn->variant.move.src = src;
3974 insn->variant.move.dst = dst;
3976 vassert(size == 1 || size == 2 || size == 4 || size == 8);
3983 s390_insn_cond_move(UChar size, s390_cc_t cond, HReg dst, s390_opnd_RMI src)
3985 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
3987 insn->tag = S390_INSN_COND_MOVE;
3989 insn->variant.cond_move.cond = cond;
3990 insn->variant.cond_move.src = src;
3991 insn->variant.cond_move.dst = dst;
3993 vassert(size == 1 || size == 2 || size == 4 || size == 8);
4000 s390_insn_load_immediate(UChar size, HReg dst, ULong value)
4002 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4004 insn->tag = S390_INSN_LOAD_IMMEDIATE;
4006 insn->variant.load_immediate.dst = dst;
4007 insn->variant.load_immediate.value = value;
4014 s390_insn_alu(UChar size, s390_alu_t tag, HReg dst, s390_opnd_RMI op2)
4016 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4018 insn->tag = S390_INSN_ALU;
4020 insn->variant.alu.tag = tag;
4021 insn->variant.alu.dst = dst;
4022 insn->variant.alu.op2 = op2;
4029 s390_insn_mul(UChar size, HReg dst_hi, HReg dst_lo, s390_opnd_RMI op2,
4030 Bool signed_multiply)
4032 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4034 vassert(! hregIsVirtual(dst_hi));
4035 vassert(! hregIsVirtual(dst_lo));
4037 insn->tag = S390_INSN_MUL;
4039 insn->variant.mul.dst_hi = dst_hi;
4040 insn->variant.mul.dst_lo = dst_lo;
4041 insn->variant.mul.op2 = op2;
4042 insn->variant.mul.signed_multiply = signed_multiply;
4049 s390_insn_div(UChar size, HReg op1_hi, HReg op1_lo, s390_opnd_RMI op2,
4052 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4054 vassert(size == 4 || size == 8);
4055 vassert(! hregIsVirtual(op1_hi));
4056 vassert(! hregIsVirtual(op1_lo));
4058 insn->tag = S390_INSN_DIV;
4060 insn->variant.div.op1_hi = op1_hi;
4061 insn->variant.div.op1_lo = op1_lo;
4062 insn->variant.div.op2 = op2;
4063 insn->variant.div.signed_divide = signed_divide;
4070 s390_insn_divs(UChar size, HReg rem, HReg op1, s390_opnd_RMI op2)
4072 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4075 vassert(! hregIsVirtual(op1));
4076 vassert(! hregIsVirtual(rem));
4078 insn->tag = S390_INSN_DIVS;
4080 insn->variant.divs.rem = rem; /* remainder */
4081 insn->variant.divs.op1 = op1; /* also quotient */
4082 insn->variant.divs.op2 = op2;
4089 s390_insn_clz(UChar size, HReg num_bits, HReg clobber, s390_opnd_RMI src)
4091 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4094 vassert(! hregIsVirtual(num_bits));
4095 vassert(! hregIsVirtual(clobber));
4097 insn->tag = S390_INSN_CLZ;
4099 insn->variant.clz.num_bits = num_bits;
4100 insn->variant.clz.clobber = clobber;
4101 insn->variant.clz.src = src;
4108 s390_insn_unop(UChar size, s390_unop_t tag, HReg dst, s390_opnd_RMI opnd)
4110 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4112 insn->tag = S390_INSN_UNOP;
4114 insn->variant.unop.tag = tag;
4115 insn->variant.unop.dst = dst;
4116 insn->variant.unop.src = opnd;
4123 s390_insn_test(UChar size, s390_opnd_RMI src)
4125 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4127 vassert(size == 4 || size == 8);
4129 insn->tag = S390_INSN_TEST;
4131 insn->variant.test.src = src;
4138 s390_insn_cc2bool(HReg dst, s390_cc_t cond)
4140 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4142 insn->tag = S390_INSN_CC2BOOL;
4143 insn->size = 0; /* does not matter */
4144 insn->variant.cc2bool.cond = cond;
4145 insn->variant.cc2bool.dst = dst;
4152 s390_insn_cas(UChar size, HReg op1, s390_amode *op2, HReg op3, HReg old_mem)
4154 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4156 vassert(size == 4 || size == 8);
4157 vassert(op2->x == 0);
4159 insn->tag = S390_INSN_CAS;
4161 insn->variant.cas.op1 = op1;
4162 insn->variant.cas.op2 = op2;
4163 insn->variant.cas.op3 = op3;
4164 insn->variant.cas.old_mem = old_mem;
4171 s390_insn_compare(UChar size, HReg src1, s390_opnd_RMI src2,
4172 Bool signed_comparison)
4174 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4176 vassert(size == 4 || size == 8);
4178 insn->tag = S390_INSN_COMPARE;
4180 insn->variant.compare.src1 = src1;
4181 insn->variant.compare.src2 = src2;
4182 insn->variant.compare.signed_comparison = signed_comparison;
4189 s390_insn_branch(IRJumpKind kind, s390_cc_t cond, s390_opnd_RMI dst)
4191 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4193 insn->tag = S390_INSN_BRANCH;
4194 insn->size = 0; /* does not matter */
4195 insn->variant.branch.kind = kind;
4196 insn->variant.branch.dst = dst;
4197 insn->variant.branch.cond = cond;
4204 s390_insn_helper_call(s390_cc_t cond, Addr64 target, UInt num_args,
4207 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4209 insn->tag = S390_INSN_HELPER_CALL;
4210 insn->size = 0; /* does not matter */
4211 insn->variant.helper_call.cond = cond;
4212 insn->variant.helper_call.target = target;
4213 insn->variant.helper_call.num_args = num_args;
4214 insn->variant.helper_call.name = name;
4221 s390_insn_bfp_triop(UChar size, s390_bfp_triop_t tag, HReg dst, HReg op2,
4222 HReg op3, s390_round_t rounding_mode)
4224 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4226 insn->tag = S390_INSN_BFP_TRIOP;
4228 insn->variant.bfp_triop.tag = tag;
4229 insn->variant.bfp_triop.dst = dst;
4230 insn->variant.bfp_triop.op2 = op2;
4231 insn->variant.bfp_triop.op3 = op3;
4232 insn->variant.bfp_triop.rounding_mode = rounding_mode;
4239 s390_insn_bfp_binop(UChar size, s390_bfp_binop_t tag, HReg dst, HReg op2,
4240 s390_round_t rounding_mode)
4242 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4244 insn->tag = S390_INSN_BFP_BINOP;
4246 insn->variant.bfp_binop.tag = tag;
4247 insn->variant.bfp_binop.dst = dst;
4248 insn->variant.bfp_binop.op2 = op2;
4249 insn->variant.bfp_binop.rounding_mode = rounding_mode;
4256 s390_insn_bfp_unop(UChar size, s390_bfp_unop_t tag, HReg dst, HReg op,
4257 s390_round_t rounding_mode)
4259 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4261 insn->tag = S390_INSN_BFP_UNOP;
4263 insn->variant.bfp_unop.tag = tag;
4264 insn->variant.bfp_unop.dst = dst;
4265 insn->variant.bfp_unop.op = op;
4266 insn->variant.bfp_unop.rounding_mode = rounding_mode;
4273 s390_insn_bfp_compare(UChar size, HReg dst, HReg op1, HReg op2)
4275 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4277 vassert(size == 4 || size == 8);
4279 insn->tag = S390_INSN_BFP_COMPARE;
4281 insn->variant.bfp_compare.dst = dst;
4282 insn->variant.bfp_compare.op1 = op1;
4283 insn->variant.bfp_compare.op2 = op2;
4290 s390_insn_bfp128_binop(UChar size, s390_bfp_binop_t tag, HReg dst_hi,
4291 HReg dst_lo, HReg op2_hi, HReg op2_lo,
4292 s390_round_t rounding_mode)
4294 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4296 insn->tag = S390_INSN_BFP128_BINOP;
4298 insn->variant.bfp128_binop.tag = tag;
4299 insn->variant.bfp128_binop.dst_hi = dst_hi;
4300 insn->variant.bfp128_binop.dst_lo = dst_lo;
4301 insn->variant.bfp128_binop.op2_hi = op2_hi;
4302 insn->variant.bfp128_binop.op2_lo = op2_lo;
4303 insn->variant.bfp128_binop.rounding_mode = rounding_mode;
4310 s390_insn_bfp128_unop(UChar size, s390_bfp_unop_t tag, HReg dst_hi,
4311 HReg dst_lo, HReg op_hi, HReg op_lo,
4312 s390_round_t rounding_mode)
4314 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4316 insn->tag = S390_INSN_BFP128_UNOP;
4318 insn->variant.bfp128_unop.tag = tag;
4319 insn->variant.bfp128_unop.dst_hi = dst_hi;
4320 insn->variant.bfp128_unop.dst_lo = dst_lo;
4321 insn->variant.bfp128_unop.op_hi = op_hi;
4322 insn->variant.bfp128_unop.op_lo = op_lo;
4323 insn->variant.bfp128_unop.rounding_mode = rounding_mode;
4330 s390_insn_bfp128_compare(UChar size, HReg dst, HReg op1_hi, HReg op1_lo,
4331 HReg op2_hi, HReg op2_lo)
4333 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4335 insn->tag = S390_INSN_BFP128_COMPARE;
4337 insn->variant.bfp128_compare.dst = dst;
4338 insn->variant.bfp128_compare.op1_hi = op1_hi;
4339 insn->variant.bfp128_compare.op1_lo = op1_lo;
4340 insn->variant.bfp128_compare.op2_hi = op2_hi;
4341 insn->variant.bfp128_compare.op2_lo = op2_lo;
4348 s390_insn_bfp128_convert_to(UChar size, s390_bfp_unop_t tag, HReg dst_hi,
4349 HReg dst_lo, HReg op)
4351 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4353 insn->tag = S390_INSN_BFP128_CONVERT_TO;
4355 insn->variant.bfp128_unop.tag = tag;
4356 insn->variant.bfp128_unop.dst_hi = dst_hi;
4357 insn->variant.bfp128_unop.dst_lo = dst_lo;
4358 insn->variant.bfp128_unop.op_hi = op;
4359 insn->variant.bfp128_unop.op_lo = INVALID_HREG; /* unused */
4360 insn->variant.bfp128_unop.rounding_mode = S390_ROUND_NEAREST_EVEN; /* unused */
4367 s390_insn_bfp128_convert_from(UChar size, s390_bfp_unop_t tag, HReg dst,
4368 HReg op_hi, HReg op_lo,
4369 s390_round_t rounding_mode)
4371 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4373 insn->tag = S390_INSN_BFP128_CONVERT_FROM;
4375 insn->variant.bfp128_unop.tag = tag;
4376 insn->variant.bfp128_unop.dst_hi = dst;
4377 insn->variant.bfp128_unop.dst_lo = INVALID_HREG; /* unused */
4378 insn->variant.bfp128_unop.op_hi = op_hi;
4379 insn->variant.bfp128_unop.op_lo = op_lo;
4380 insn->variant.bfp128_unop.rounding_mode = rounding_mode;
4387 s390_insn_mfence(void)
4389 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4391 insn->tag = S390_INSN_MFENCE;
4392 insn->size = 0; /* not needed */
4398 /*---------------------------------------------------------------*/
4399 /*--- Debug print ---*/
4400 /*---------------------------------------------------------------*/
4402 static const HChar *
4403 s390_cc_as_string(s390_cc_t cc)
4406 case S390_CC_NEVER: return "never";
4407 case S390_CC_OVFL: return "overflow";
4408 case S390_CC_H: return "greater than"; /* A > B ; high */
4409 case S390_CC_NLE: return "not low or equal";
4410 case S390_CC_L: return "less than"; /* A < B ; low */
4411 case S390_CC_NHE: return "not high or equal";
4412 case S390_CC_LH: return "low or high";
4413 case S390_CC_NE: return "not equal"; /* A != B ; not zero */
4414 case S390_CC_E: return "equal"; /* A == B ; zero */
4415 case S390_CC_NLH: return "not low or high";
4416 case S390_CC_HE: return "greater or equal"; /* A >= B ; high or equal*/
4417 case S390_CC_NL: return "not low"; /* not low */
4418 case S390_CC_LE: return "less or equal"; /* A <= B ; low or equal */
4419 case S390_CC_NH: return "not high";
4420 case S390_CC_NO: return "not overflow";
4421 case S390_CC_ALWAYS: return "always";
4423 vpanic("s390_cc_as_string");
4428 /* Helper function for writing out a V insn */
4430 s390_sprintf(HChar *buf, HChar *fmt, ...)
4435 va_start(args, fmt);
4438 for ( ; *fmt; ++fmt) {
4446 c = *++fmt; /* next char */
4453 p += vex_sprintf(p, "%s", va_arg(args, HChar *));
4456 case 'M': /* %M = mnemonic */
4457 p += vex_sprintf(p, "%-8s", va_arg(args, HChar *));
4460 case 'R': /* %R = register */
4461 p += vex_sprintf(p, "%s", s390_hreg_as_string(va_arg(args, HReg)));
4464 case 'A': /* %A = amode */
4465 p += vex_sprintf(p, "%s",
4466 s390_amode_as_string(va_arg(args, s390_amode *)));
4469 case 'C': /* %C = condition code */
4470 p += vex_sprintf(p, "%s", s390_cc_as_string(va_arg(args, s390_cc_t)));
4473 case 'L': { /* %L = argument list in helper call*/
4476 num_args = va_arg(args, UInt);
4478 for (i = 0; i < num_args; ++i) {
4479 if (i != 0) p += vex_sprintf(p, ", ");
4480 p += vex_sprintf(p, "r%d", s390_gprno_from_arg_index(i));
4485 case 'O': { /* %O = RMI operand */
4486 s390_opnd_RMI *op = va_arg(args, s390_opnd_RMI *);
4490 p += vex_sprintf(p, "%s", s390_hreg_as_string(op->variant.reg));
4493 case S390_OPND_AMODE:
4494 p += vex_sprintf(p, "%s", s390_amode_as_string(op->variant.am));
4497 case S390_OPND_IMMEDIATE:
4498 value = op->variant.imm;
4506 case 'I': /* %I = immediate value */
4507 value = va_arg(args, ULong);
4511 if ((Long)value < 0)
4512 p += vex_sprintf(p, "%lld", (Long)value);
4513 else if (value < 100)
4514 p += vex_sprintf(p, "%llu", value);
4516 p += vex_sprintf(p, "0x%llx", value);
4528 fail: vpanic("s390_printf");
4532 /* Decompile the given insn into a static buffer and return it */
4534 s390_insn_as_string(const s390_insn *insn)
4536 static HChar buf[300];
4542 switch (insn->tag) {
4543 case S390_INSN_LOAD:
4544 s390_sprintf(buf, "%M %R,%A", "v-load", insn->variant.load.dst,
4545 insn->variant.load.src);
4548 case S390_INSN_STORE:
4549 s390_sprintf(buf, "%M %R,%A", "v-store", insn->variant.store.src,
4550 insn->variant.store.dst);
4553 case S390_INSN_MOVE:
4554 s390_sprintf(buf, "%M %R,%R", "v-move", insn->variant.move.dst,
4555 insn->variant.move.src);
4558 case S390_INSN_COND_MOVE:
4559 s390_sprintf(buf, "%M if (%C) %R,%O", "v-move",
4560 insn->variant.cond_move.cond, insn->variant.cond_move.dst,
4561 &insn->variant.cond_move.src);
4564 case S390_INSN_LOAD_IMMEDIATE:
4565 s390_sprintf(buf, "%M %R,%I", "v-loadi", insn->variant.load_immediate.dst,
4566 insn->variant.load_immediate.value);
4570 switch (insn->variant.alu.tag) {
4571 case S390_ALU_ADD: op = "v-add"; break;
4572 case S390_ALU_SUB: op = "v-sub"; break;
4573 case S390_ALU_MUL: op = "v-mul"; break;
4574 case S390_ALU_AND: op = "v-and"; break;
4575 case S390_ALU_OR: op = "v-or"; break;
4576 case S390_ALU_XOR: op = "v-xor"; break;
4577 case S390_ALU_LSH: op = "v-lsh"; break;
4578 case S390_ALU_RSH: op = "v-rsh"; break;
4579 case S390_ALU_RSHA: op = "v-rsha"; break;
4582 s390_sprintf(buf, "%M %R,%R,%O", op, insn->variant.alu.dst,
4583 insn->variant.alu.dst /* op1 same as dst */,
4584 &insn->variant.alu.op2);
4588 if (insn->variant.mul.signed_multiply) {
4593 s390_sprintf(buf, "%M %R,%O", op, insn->variant.mul.dst_hi,
4594 &insn->variant.mul.op2);
4598 if (insn->variant.div.signed_divide) {
4603 s390_sprintf(buf, "%M %R,%O", op, insn->variant.div.op1_hi,
4604 &insn->variant.div.op2);
4607 case S390_INSN_DIVS:
4608 s390_sprintf(buf, "%M %R,%O", "v-divsi", insn->variant.divs.op1,
4609 &insn->variant.divs.op2);
4613 s390_sprintf(buf, "%M %R,%O", "v-clz", insn->variant.clz.num_bits,
4614 &insn->variant.clz.src);
4617 case S390_INSN_UNOP:
4618 switch (insn->variant.unop.tag) {
4619 case S390_ZERO_EXTEND_8:
4620 case S390_ZERO_EXTEND_16:
4621 case S390_ZERO_EXTEND_32:
4625 case S390_SIGN_EXTEND_8:
4626 case S390_SIGN_EXTEND_16:
4627 case S390_SIGN_EXTEND_32:
4638 s390_sprintf(buf, "%M %R,%O", op, insn->variant.unop.dst,
4639 &insn->variant.unop.src);
4642 case S390_INSN_TEST:
4643 s390_sprintf(buf, "%M %O", "v-test", &insn->variant.test.src);
4646 case S390_INSN_CC2BOOL:
4647 s390_sprintf(buf, "%M %R,%C", "v-cc2b", insn->variant.cc2bool.dst,
4648 insn->variant.cc2bool.cond);
4652 s390_sprintf(buf, "%M %R,%A,%R,%R", "v-cas", insn->variant.cas.op1,
4653 insn->variant.cas.op2, insn->variant.cas.op3,
4654 insn->variant.cas.old_mem);
4657 case S390_INSN_COMPARE:
4658 if (insn->variant.compare.signed_comparison) {
4663 s390_sprintf(buf, "%M %R,%O", op, insn->variant.compare.src1,
4664 &insn->variant.compare.src2);
4667 case S390_INSN_BRANCH:
4668 switch (insn->variant.branch.kind) {
4669 case Ijk_ClientReq: op = "clientreq"; break;
4670 case Ijk_Sys_syscall: op = "syscall"; break;
4671 case Ijk_Yield: op = "yield"; break;
4672 case Ijk_EmWarn: op = "emwarn"; break;
4673 case Ijk_EmFail: op = "emfail"; break;
4674 case Ijk_MapFail: op = "mapfail"; break;
4675 case Ijk_NoDecode: op = "nodecode"; break;
4676 case Ijk_TInval: op = "tinval"; break;
4677 case Ijk_NoRedir: op = "noredir"; break;
4678 case Ijk_SigTRAP: op = "sigtrap"; break;
4679 case Ijk_Boring: op = "goto"; break;
4680 case Ijk_Call: op = "call"; break;
4681 case Ijk_Ret: op = "return"; break;
4685 s390_sprintf(buf, "if (%C) %s %O", insn->variant.branch.cond, op,
4686 &insn->variant.branch.dst);
4689 case S390_INSN_HELPER_CALL: {
4691 if (insn->variant.helper_call.cond != S390_CC_ALWAYS) {
4692 s390_sprintf(buf, "%M if (%C) %s{%I}(%L)", "v-call",
4693 insn->variant.helper_call.cond,
4694 insn->variant.helper_call.name,
4695 insn->variant.helper_call.target,
4696 insn->variant.helper_call.num_args);
4698 s390_sprintf(buf, "%M %s{%I}(%L)", "v-call",
4699 insn->variant.helper_call.name,
4700 insn->variant.helper_call.target,
4701 insn->variant.helper_call.num_args);
4706 case S390_INSN_BFP_TRIOP:
4707 switch (insn->variant.bfp_triop.tag) {
4708 case S390_BFP_MADD: op = "v-fmadd"; break;
4709 case S390_BFP_MSUB: op = "v-fmsub"; break;
4712 s390_sprintf(buf, "%M %R,%R,%R,%R", op, insn->variant.bfp_triop.dst,
4713 insn->variant.bfp_triop.dst /* op1 same as dst */,
4714 insn->variant.bfp_triop.op2, insn->variant.bfp_triop.op3);
4717 case S390_INSN_BFP_BINOP:
4718 switch (insn->variant.bfp_binop.tag) {
4719 case S390_BFP_ADD: op = "v-fadd"; break;
4720 case S390_BFP_SUB: op = "v-fsub"; break;
4721 case S390_BFP_MUL: op = "v-fmul"; break;
4722 case S390_BFP_DIV: op = "v-fdiv"; break;
4725 s390_sprintf(buf, "%M %R,%R,%R", op, insn->variant.bfp_binop.dst,
4726 insn->variant.bfp_binop.dst /* op1 same as dst */,
4727 insn->variant.bfp_binop.op2);
4730 case S390_INSN_BFP_COMPARE:
4731 s390_sprintf(buf, "%M %R,%R,%R", "v-fcmp", insn->variant.bfp_compare.dst,
4732 insn->variant.bfp_compare.op1, insn->variant.bfp_compare.op2);
4735 case S390_INSN_BFP_UNOP:
4736 switch (insn->variant.bfp_unop.tag) {
4737 case S390_BFP_ABS: op = "v-fabs"; break;
4738 case S390_BFP_NABS: op = "v-fnabs"; break;
4739 case S390_BFP_NEG: op = "v-fneg"; break;
4740 case S390_BFP_SQRT: op = "v-fsqrt"; break;
4741 case S390_BFP_I32_TO_F32:
4742 case S390_BFP_I32_TO_F64:
4743 case S390_BFP_I32_TO_F128:
4744 case S390_BFP_I64_TO_F32:
4745 case S390_BFP_I64_TO_F64:
4746 case S390_BFP_I64_TO_F128: op = "v-i2f"; break;
4747 case S390_BFP_F32_TO_I32:
4748 case S390_BFP_F32_TO_I64:
4749 case S390_BFP_F64_TO_I32:
4750 case S390_BFP_F64_TO_I64:
4751 case S390_BFP_F128_TO_I32:
4752 case S390_BFP_F128_TO_I64: op = "v-f2i"; break;
4753 case S390_BFP_F32_TO_F64:
4754 case S390_BFP_F32_TO_F128:
4755 case S390_BFP_F64_TO_F32:
4756 case S390_BFP_F64_TO_F128:
4757 case S390_BFP_F128_TO_F32:
4758 case S390_BFP_F128_TO_F64: op = "v-f2f"; break;
4761 s390_sprintf(buf, "%M %R,%R", op, insn->variant.bfp_unop.dst,
4762 insn->variant.bfp_unop.op);
4765 case S390_INSN_BFP128_BINOP:
4766 switch (insn->variant.bfp128_binop.tag) {
4767 case S390_BFP_ADD: op = "v-fadd"; break;
4768 case S390_BFP_SUB: op = "v-fsub"; break;
4769 case S390_BFP_MUL: op = "v-fmul"; break;
4770 case S390_BFP_DIV: op = "v-fdiv"; break;
4773 /* Only write the register that identifies the register pair */
4774 s390_sprintf(buf, "%M %R,%R,%R", op, insn->variant.bfp128_binop.dst_hi,
4775 insn->variant.bfp128_binop.dst_hi /* op1 same as dst */,
4776 insn->variant.bfp128_binop.op2_hi);
4779 case S390_INSN_BFP128_COMPARE:
4780 /* Only write the register that identifies the register pair */
4781 s390_sprintf(buf, "%M %R,%R,%R", "v-fcmp", insn->variant.bfp128_compare.dst,
4782 insn->variant.bfp128_compare.op1_hi,
4783 insn->variant.bfp128_compare.op2_hi);
4786 case S390_INSN_BFP128_UNOP:
4787 case S390_INSN_BFP128_CONVERT_TO:
4788 case S390_INSN_BFP128_CONVERT_FROM:
4789 switch (insn->variant.bfp128_unop.tag) {
4790 case S390_BFP_ABS: op = "v-fabs"; break;
4791 case S390_BFP_NABS: op = "v-fnabs"; break;
4792 case S390_BFP_NEG: op = "v-fneg"; break;
4793 case S390_BFP_SQRT: op = "v-fsqrt"; break;
4794 case S390_BFP_I32_TO_F128:
4795 case S390_BFP_I64_TO_F128: op = "v-i2f"; break;
4796 case S390_BFP_F128_TO_I32:
4797 case S390_BFP_F128_TO_I64: op = "v-f2i"; break;
4798 case S390_BFP_F32_TO_F128:
4799 case S390_BFP_F64_TO_F128:
4800 case S390_BFP_F128_TO_F32:
4801 case S390_BFP_F128_TO_F64: op = "v-f2f"; break;
4804 /* Only write the register that identifies the register pair */
4805 s390_sprintf(buf, "%M %R,%R", op, insn->variant.bfp128_unop.dst_hi,
4806 insn->variant.bfp128_unop.op_hi);
4809 case S390_INSN_MFENCE:
4810 s390_sprintf(buf, "%M", "v-mfence");
4811 return buf; /* avoid printing "size = ..." which is meaningless */
4816 /* Write out how many bytes are involved in the operation */
4821 for (p = buf; *p; ++p)
4827 for (i = len; i < 32; ++i)
4828 p += vex_sprintf(p, " ");
4830 p += vex_sprintf(p, "\t");
4834 /* Special cases first */
4835 switch (insn->tag) {
4836 case S390_INSN_UNOP:
4837 switch (insn->variant.unop.tag) {
4838 case S390_SIGN_EXTEND_8:
4839 case S390_ZERO_EXTEND_8: p += vex_sprintf(p, "1 -> "); goto common;
4840 case S390_SIGN_EXTEND_16:
4841 case S390_ZERO_EXTEND_16: p += vex_sprintf(p, "2 -> "); goto common;
4842 case S390_SIGN_EXTEND_32:
4843 case S390_ZERO_EXTEND_32: p += vex_sprintf(p, "4 -> "); goto common;
4848 case S390_INSN_BFP_UNOP:
4849 switch (insn->variant.bfp_unop.tag) {
4850 case S390_BFP_I32_TO_F32:
4851 case S390_BFP_I32_TO_F64:
4852 case S390_BFP_I32_TO_F128:
4853 case S390_BFP_F32_TO_I32:
4854 case S390_BFP_F32_TO_I64:
4855 case S390_BFP_F32_TO_F64:
4856 case S390_BFP_F32_TO_F128: p += vex_sprintf(p, "4 -> "); goto common;
4857 case S390_BFP_I64_TO_F32:
4858 case S390_BFP_I64_TO_F64:
4859 case S390_BFP_I64_TO_F128:
4860 case S390_BFP_F64_TO_I32:
4861 case S390_BFP_F64_TO_I64:
4862 case S390_BFP_F64_TO_F32:
4863 case S390_BFP_F64_TO_F128: p += vex_sprintf(p, "8 -> "); goto common;
4864 case S390_BFP_F128_TO_I32:
4865 case S390_BFP_F128_TO_I64:
4866 case S390_BFP_F128_TO_F32:
4867 case S390_BFP_F128_TO_F64: p += vex_sprintf(p, "16 -> "); goto common;
4872 case S390_INSN_BFP128_UNOP:
4873 case S390_INSN_BFP128_CONVERT_TO:
4874 case S390_INSN_BFP128_CONVERT_FROM:
4875 switch (insn->variant.bfp128_unop.tag) {
4876 case S390_BFP_I32_TO_F128:
4877 case S390_BFP_F32_TO_F128: p += vex_sprintf(p, "4 -> "); goto common;
4878 case S390_BFP_I64_TO_F128:
4879 case S390_BFP_F64_TO_F128: p += vex_sprintf(p, "8 -> "); goto common;
4880 case S390_BFP_F128_TO_I32:
4881 case S390_BFP_F128_TO_I64:
4882 case S390_BFP_F128_TO_F32:
4883 case S390_BFP_F128_TO_F64: p += vex_sprintf(p, "16 -> "); goto common;
4894 vex_sprintf(p, "%u bytes", (UInt)insn->size);
4898 fail: vpanic("s390_insn_as_string");
4903 /* Load NUM bytes from memory into register REG using addressing mode AM. */
4905 s390_emit_load_mem(UChar *p, UInt num, UChar reg, const s390_amode *am)
4907 UInt b = hregNumber(am->b);
4908 UInt x = hregNumber(am->x); /* 0 for B12 and B20 */
4912 case S390_AMODE_B12:
4913 case S390_AMODE_BX12:
4915 case 1: return s390_emit_IC(p, reg, x, b, d);
4916 case 2: return s390_emit_LH(p, reg, x, b, d);
4917 case 4: return s390_emit_L(p, reg, x, b, d);
4918 case 8: return s390_emit_LG(p, reg, x, b, DISP20(d));
4923 case S390_AMODE_B20:
4924 case S390_AMODE_BX20:
4926 case 1: return s390_emit_ICY(p, reg, x, b, DISP20(d));
4927 case 2: return s390_emit_LHY(p, reg, x, b, DISP20(d));
4928 case 4: return s390_emit_LY(p, reg, x, b, DISP20(d));
4929 case 8: return s390_emit_LG(p, reg, x, b, DISP20(d));
4938 vpanic("s390_emit_load_mem");
4942 /* Load condition code into register REG */
4944 s390_emit_load_cc(UChar *p, UChar reg)
4946 p = s390_emit_LGHI(p, reg, 0); /* Clear out, cc not affected */
4947 p = s390_emit_IPM(p, reg, reg);
4948 /* Shift 28 bits to the right --> [0,1,2,3] */
4949 return s390_emit_SRL(p, reg, 0, 28); /* REG = cc */
4953 /*---------------------------------------------------------------*/
4954 /*--- Code generation ---*/
4955 /*---------------------------------------------------------------*/
4957 /* Do not load more bytes than requested. */
4959 s390_insn_load_emit(UChar *buf, const s390_insn *insn)
4962 const s390_amode *src;
4964 src = insn->variant.load.src;
4966 r = hregNumber(insn->variant.load.dst);
4968 if (hregClass(insn->variant.load.dst) == HRcFlt64) {
4969 b = hregNumber(src->b);
4970 x = hregNumber(src->x); /* 0 for B12 and B20 */
4973 switch (insn->size) {
4977 case S390_AMODE_B12:
4978 case S390_AMODE_BX12:
4979 return s390_emit_LE(buf, r, x, b, d);
4981 case S390_AMODE_B20:
4982 case S390_AMODE_BX20:
4983 return s390_emit_LEY(buf, r, x, b, DISP20(d));
4989 case S390_AMODE_B12:
4990 case S390_AMODE_BX12:
4991 return s390_emit_LD(buf, r, x, b, d);
4993 case S390_AMODE_B20:
4994 case S390_AMODE_BX20:
4995 return s390_emit_LDY(buf, r, x, b, DISP20(d));
4999 vpanic("s390_insn_load_emit");
5003 return s390_emit_load_mem(buf, insn->size, r, src);
5008 s390_insn_store_emit(UChar *buf, const s390_insn *insn)
5011 const s390_amode *dst;
5013 dst = insn->variant.store.dst;
5015 r = hregNumber(insn->variant.store.src);
5016 b = hregNumber(dst->b);
5017 x = hregNumber(dst->x); /* 0 for B12 and B20 */
5020 if (hregClass(insn->variant.store.src) == HRcFlt64) {
5021 switch (insn->size) {
5025 case S390_AMODE_B12:
5026 case S390_AMODE_BX12:
5027 return s390_emit_STE(buf, r, x, b, d);
5029 case S390_AMODE_B20:
5030 case S390_AMODE_BX20:
5031 return s390_emit_STEY(buf, r, x, b, DISP20(d));
5037 case S390_AMODE_B12:
5038 case S390_AMODE_BX12:
5039 return s390_emit_STD(buf, r, x, b, d);
5041 case S390_AMODE_B20:
5042 case S390_AMODE_BX20:
5043 return s390_emit_STDY(buf, r, x, b, DISP20(d));
5047 vpanic("s390_insn_store_emit");
5051 switch (insn->size) {
5054 case S390_AMODE_B12:
5055 case S390_AMODE_BX12:
5056 return s390_emit_STC(buf, r, x, b, d);
5058 case S390_AMODE_B20:
5059 case S390_AMODE_BX20:
5060 return s390_emit_STCY(buf, r, x, b, DISP20(d));
5066 case S390_AMODE_B12:
5067 case S390_AMODE_BX12:
5068 return s390_emit_STH(buf, r, x, b, d);
5070 case S390_AMODE_B20:
5071 case S390_AMODE_BX20:
5072 return s390_emit_STHY(buf, r, x, b, DISP20(d));
5078 case S390_AMODE_B12:
5079 case S390_AMODE_BX12:
5080 return s390_emit_ST(buf, r, x, b, d);
5082 case S390_AMODE_B20:
5083 case S390_AMODE_BX20:
5084 return s390_emit_STY(buf, r, x, b, DISP20(d));
5089 return s390_emit_STG(buf, r, x, b, DISP20(d));
5095 vpanic("s390_insn_store_emit");
5100 s390_insn_move_emit(UChar *buf, const s390_insn *insn)
5103 HRegClass dst_class, src_class;
5105 dst = hregNumber(insn->variant.move.dst);
5106 src = hregNumber(insn->variant.move.src);
5108 dst_class = hregClass(insn->variant.move.dst);
5109 src_class = hregClass(insn->variant.move.src);
5111 if (dst_class == src_class) {
5112 if (dst_class == HRcInt64)
5113 return s390_emit_LGR(buf, dst, src);
5114 if (dst_class == HRcFlt64)
5115 return s390_emit_LDR(buf, dst, src);
5117 if (dst_class == HRcFlt64 && src_class == HRcInt64)
5118 return s390_emit_LDGRw(buf, dst, src);
5119 if (dst_class == HRcInt64 && src_class == HRcFlt64)
5120 return s390_emit_LGDRw(buf, dst, src);
5121 /* A move between floating point registers and general purpose
5122 registers of different size should never occur and indicates
5123 an error elsewhere. */
5126 vpanic("s390_insn_move_emit");
5131 s390_insn_load_immediate_emit(UChar *buf, const s390_insn *insn)
5134 ULong value = insn->variant.load_immediate.value;
5136 r = hregNumber(insn->variant.load_immediate.dst);
5138 if (hregClass(insn->variant.load_immediate.dst) == HRcFlt64) {
5139 vassert(value == 0);
5140 switch (insn->size) {
5141 case 4: return s390_emit_LZER(buf, r, value);
5142 case 8: return s390_emit_LZDR(buf, r, value);
5144 vpanic("s390_insn_load_immediate_emit");
5147 switch (insn->size) {
5150 /* Load the immediate values as a 4 byte value. That does not hurt as
5151 those extra bytes will not be looked at. Fall through .... */
5153 return s390_emit_load_32imm(buf, r, value);
5156 return s390_emit_load_64imm(buf, r, value);
5159 vpanic("s390_insn_load_immediate_emit");
5163 /* There is no easy way to do ALU operations on 1-byte or 2-byte operands.
5164 So we simply perform a 4-byte operation. Doing so uses possibly undefined
5165 bits and produces an undefined result in those extra bit positions. But
5166 upstream does not look at those positions, so this is OK. */
5168 s390_insn_alu_emit(UChar *buf, const s390_insn *insn)
5173 dst = hregNumber(insn->variant.alu.dst);
5174 op2 = insn->variant.alu.op2;
5176 /* Second operand is in a register */
5177 if (op2.tag == S390_OPND_REG) {
5178 UInt r2 = hregNumber(op2.variant.reg);
5180 switch (insn->size) {
5184 switch (insn->variant.alu.tag) {
5185 case S390_ALU_ADD: return s390_emit_AR(buf, dst, r2);
5186 case S390_ALU_SUB: return s390_emit_SR(buf, dst, r2);
5187 case S390_ALU_MUL: return s390_emit_MSR(buf, dst, r2);
5188 case S390_ALU_AND: return s390_emit_NR(buf, dst, r2);
5189 case S390_ALU_OR: return s390_emit_OR(buf, dst, r2);
5190 case S390_ALU_XOR: return s390_emit_XR(buf, dst, r2);
5191 case S390_ALU_LSH: return s390_emit_SLL(buf, dst, r2, 0);
5192 case S390_ALU_RSH: return s390_emit_SRL(buf, dst, r2, 0);
5193 case S390_ALU_RSHA: return s390_emit_SRA(buf, dst, r2, 0);
5198 switch (insn->variant.alu.tag) {
5199 case S390_ALU_ADD: return s390_emit_AGR(buf, dst, r2);
5200 case S390_ALU_SUB: return s390_emit_SGR(buf, dst, r2);
5201 case S390_ALU_MUL: return s390_emit_MSGR(buf, dst, r2);
5202 case S390_ALU_AND: return s390_emit_NGR(buf, dst, r2);
5203 case S390_ALU_OR: return s390_emit_OGR(buf, dst, r2);
5204 case S390_ALU_XOR: return s390_emit_XGR(buf, dst, r2);
5205 case S390_ALU_LSH: return s390_emit_SLLG(buf, dst, dst, r2, DISP20(0));
5206 case S390_ALU_RSH: return s390_emit_SRLG(buf, dst, dst, r2, DISP20(0));
5207 case S390_ALU_RSHA: return s390_emit_SRAG(buf, dst, dst, r2, DISP20(0));
5214 /* 2nd operand is in memory */
5215 if (op2.tag == S390_OPND_AMODE) {
5217 const s390_amode *src = op2.variant.am;
5219 b = hregNumber(src->b);
5220 x = hregNumber(src->x); /* 0 for B12 and B20 */
5223 /* Shift operands are special here as there are no opcodes that
5224 allow a memory operand. So we first load the 2nd operand into
5225 some register. R0 is used to save restore the contents of the
5226 chosen register.. */
5228 if (insn->variant.alu.tag == S390_ALU_LSH ||
5229 insn->variant.alu.tag == S390_ALU_RSH ||
5230 insn->variant.alu.tag == S390_ALU_RSHA) {
5233 /* Choose a register (other than DST or R0) into which to stick the
5234 shift amount. The following works because r15 is reserved and
5235 thusly dst != 15. */
5236 vassert(dst != 15); /* extra paranoia */
5237 b2 = (dst + 1) % 16;
5239 buf = s390_emit_LGR(buf, R0, b2); /* save */
5241 /* Loading SRC to B2 does not modify R0. */
5242 buf = s390_emit_load_mem(buf, insn->size, b2, src);
5244 if (insn->size == 8) {
5245 switch (insn->variant.alu.tag) {
5247 buf = s390_emit_SLLG(buf, dst, dst, b2, DISP20(0));
5250 buf = s390_emit_SRLG(buf, dst, dst, b2, DISP20(0));
5253 buf = s390_emit_SRAG(buf, dst, dst, b2, DISP20(0));
5255 default: /* unreachable */
5259 switch (insn->variant.alu.tag) {
5261 buf = s390_emit_SLL(buf, dst, b2, 0);
5264 buf = s390_emit_SRL(buf, dst, b2, 0);
5267 buf = s390_emit_SRA(buf, dst, b2, 0);
5269 default: /* unreachable */
5273 return s390_emit_LGR(buf, b2, R0); /* restore */
5276 switch (insn->size) {
5278 /* Move the byte from memory into scratch register r0 */
5279 buf = s390_emit_load_mem(buf, 1, R0, src);
5281 switch (insn->variant.alu.tag) {
5282 case S390_ALU_ADD: return s390_emit_AR(buf, dst, R0);
5283 case S390_ALU_SUB: return s390_emit_SR(buf, dst, R0);
5284 case S390_ALU_MUL: return s390_emit_MSR(buf, dst, R0);
5285 case S390_ALU_AND: return s390_emit_NR(buf, dst, R0);
5286 case S390_ALU_OR: return s390_emit_OR(buf, dst, R0);
5287 case S390_ALU_XOR: return s390_emit_XR(buf, dst, R0);
5290 case S390_ALU_RSHA: ; /* avoid GCC warning */
5296 case S390_AMODE_B12:
5297 case S390_AMODE_BX12:
5298 switch (insn->variant.alu.tag) {
5300 return s390_emit_AH(buf, dst, x, b, d);
5303 return s390_emit_SH(buf, dst, x, b, d);
5306 return s390_emit_MH(buf, dst, x, b, d);
5308 /* For bitwise operations: Move two bytes from memory into scratch
5309 register r0; then perform operation */
5311 buf = s390_emit_LH(buf, R0, x, b, d);
5312 return s390_emit_NR(buf, dst, R0);
5315 buf = s390_emit_LH(buf, R0, x, b, d);
5316 return s390_emit_OR(buf, dst, R0);
5319 buf = s390_emit_LH(buf, R0, x, b, d);
5320 return s390_emit_XR(buf, dst, R0);
5324 case S390_ALU_RSHA: ; /* avoid GCC warning */
5328 case S390_AMODE_B20:
5329 case S390_AMODE_BX20:
5330 switch (insn->variant.alu.tag) {
5332 return s390_emit_AHY(buf, dst, x, b, DISP20(d));
5335 return s390_emit_SHY(buf, dst, x, b, DISP20(d));
5338 return s390_emit_MHYw(buf, dst, x, b, DISP20(d));
5340 /* For bitwise operations: Move two bytes from memory into scratch
5341 register r0; then perform operation */
5343 buf = s390_emit_LHY(buf, R0, x, b, DISP20(d));
5344 return s390_emit_NR(buf, dst, R0);
5347 buf = s390_emit_LHY(buf, R0, x, b, DISP20(d));
5348 return s390_emit_OR(buf, dst, R0);
5351 buf = s390_emit_LHY(buf, R0, x, b, DISP20(d));
5352 return s390_emit_XR(buf, dst, R0);
5356 case S390_ALU_RSHA: ; /* avoid GCC warning */
5364 case S390_AMODE_B12:
5365 case S390_AMODE_BX12:
5366 switch (insn->variant.alu.tag) {
5367 case S390_ALU_ADD: return s390_emit_A(buf, dst, x, b, d);
5368 case S390_ALU_SUB: return s390_emit_S(buf, dst, x, b, d);
5369 case S390_ALU_MUL: return s390_emit_MS(buf, dst, x, b, d);
5370 case S390_ALU_AND: return s390_emit_N(buf, dst, x, b, d);
5371 case S390_ALU_OR: return s390_emit_O(buf, dst, x, b, d);
5372 case S390_ALU_XOR: return s390_emit_X(buf, dst, x, b, d);
5375 case S390_ALU_RSHA: ; /* avoid GCC warning */
5379 case S390_AMODE_B20:
5380 case S390_AMODE_BX20:
5381 switch (insn->variant.alu.tag) {
5382 case S390_ALU_ADD: return s390_emit_AY(buf, dst, x, b, DISP20(d));
5383 case S390_ALU_SUB: return s390_emit_SY(buf, dst, x, b, DISP20(d));
5384 case S390_ALU_MUL: return s390_emit_MSY(buf, dst, x, b, DISP20(d));
5385 case S390_ALU_AND: return s390_emit_NY(buf, dst, x, b, DISP20(d));
5386 case S390_ALU_OR: return s390_emit_OY(buf, dst, x, b, DISP20(d));
5387 case S390_ALU_XOR: return s390_emit_XY(buf, dst, x, b, DISP20(d));
5390 case S390_ALU_RSHA: ; /* avoid GCC warning */
5397 switch (insn->variant.alu.tag) {
5398 case S390_ALU_ADD: return s390_emit_AG(buf, dst, x, b, DISP20(d));
5399 case S390_ALU_SUB: return s390_emit_SG(buf, dst, x, b, DISP20(d));
5400 case S390_ALU_MUL: return s390_emit_MSG(buf, dst, x, b, DISP20(d));
5401 case S390_ALU_AND: return s390_emit_NG(buf, dst, x, b, DISP20(d));
5402 case S390_ALU_OR: return s390_emit_OG(buf, dst, x, b, DISP20(d));
5403 case S390_ALU_XOR: return s390_emit_XG(buf, dst, x, b, DISP20(d));
5406 case S390_ALU_RSHA: ; /* avoid GCC warning */
5413 /* 2nd operand is an immediate value */
5414 if (op2.tag == S390_OPND_IMMEDIATE) {
5417 /* No masking of the value is required as it is not sign extended */
5418 value = op2.variant.imm;
5420 switch (insn->size) {
5423 /* There is no 1-byte opcode. Do the computation in
5424 2 bytes. The extra byte will be ignored. */
5425 switch (insn->variant.alu.tag) {
5427 return s390_emit_AHI(buf, dst, value);
5430 return s390_emit_SLFIw(buf, dst, value);
5433 return s390_emit_MHI(buf, dst, value);
5435 case S390_ALU_AND: return s390_emit_NILL(buf, dst, value);
5436 case S390_ALU_OR: return s390_emit_OILL(buf, dst, value);
5438 /* There is no XILL instruction. Load the immediate value into
5439 R0 and combine with the destination register. */
5440 buf = s390_emit_LHI(buf, R0, value);
5441 return s390_emit_XR(buf, dst, R0);
5444 return s390_emit_SLL(buf, dst, 0, value);
5447 return s390_emit_SRL(buf, dst, 0, value);
5450 return s390_emit_SRA(buf, dst, 0, value);
5455 switch (insn->variant.alu.tag) {
5457 if (uint_fits_signed_16bit(value)) {
5458 return s390_emit_AHI(buf, dst, value);
5460 return s390_emit_AFIw(buf, dst, value);
5462 case S390_ALU_SUB: return s390_emit_SLFIw(buf, dst, value);
5463 case S390_ALU_MUL: return s390_emit_MSFIw(buf, dst, value);
5464 case S390_ALU_AND: return s390_emit_NILFw(buf, dst, value);
5465 case S390_ALU_OR: return s390_emit_OILFw(buf, dst, value);
5466 case S390_ALU_XOR: return s390_emit_XILFw(buf, dst, value);
5467 case S390_ALU_LSH: return s390_emit_SLL(buf, dst, 0, value);
5468 case S390_ALU_RSH: return s390_emit_SRL(buf, dst, 0, value);
5469 case S390_ALU_RSHA: return s390_emit_SRA(buf, dst, 0, value);
5474 switch (insn->variant.alu.tag) {
5476 if (ulong_fits_signed_16bit(value)) {
5477 return s390_emit_AGHI(buf, dst, value);
5479 if (ulong_fits_signed_32bit(value) && s390_host_has_eimm) {
5480 return s390_emit_AGFI(buf, dst, value);
5482 /* Load constant into R0 then add */
5483 buf = s390_emit_load_64imm(buf, R0, value);
5484 return s390_emit_AGR(buf, dst, R0);
5487 if (ulong_fits_unsigned_32bit(value)) {
5488 return s390_emit_SLGFIw(buf, dst, value);
5490 /* Load value into R0; then subtract from destination reg */
5491 buf = s390_emit_load_64imm(buf, R0, value);
5492 return s390_emit_SGR(buf, dst, R0);
5495 if (ulong_fits_signed_32bit(value) && s390_host_has_gie) {
5496 return s390_emit_MSGFI(buf, dst, value);
5498 /* Load constant into R0 then add */
5499 buf = s390_emit_load_64imm(buf, R0, value);
5500 return s390_emit_MSGR(buf, dst, R0);
5502 /* Do it in two steps: upper half [0:31] and lower half [32:63] */
5504 if (s390_host_has_eimm) {
5505 buf = s390_emit_NIHF(buf, dst, value >> 32);
5506 return s390_emit_NILF(buf, dst, value & 0xFFFFFFFF);
5508 /* Load value into R0; then combine with destination reg */
5509 buf = s390_emit_load_64imm(buf, R0, value);
5510 return s390_emit_NGR(buf, dst, R0);
5513 if (s390_host_has_eimm) {
5514 buf = s390_emit_OIHF(buf, dst, value >> 32);
5515 return s390_emit_OILF(buf, dst, value & 0xFFFFFFFF);
5517 /* Load value into R0; then combine with destination reg */
5518 buf = s390_emit_load_64imm(buf, R0, value);
5519 return s390_emit_OGR(buf, dst, R0);
5522 if (s390_host_has_eimm) {
5523 buf = s390_emit_XIHF(buf, dst, value >> 32);
5524 return s390_emit_XILF(buf, dst, value & 0xFFFFFFFF);
5526 /* Load value into R0; then combine with destination reg */
5527 buf = s390_emit_load_64imm(buf, R0, value);
5528 return s390_emit_XGR(buf, dst, R0);
5530 /* No special considerations for long displacement here. Only the six
5531 least significant bits of VALUE will be taken; all other bits are
5532 ignored. So the DH2 bits are irrelevant and do not influence the
5533 shift operation, independent of whether long-displacement is available
5535 case S390_ALU_LSH: return s390_emit_SLLG(buf, dst, dst, 0, DISP20(value));
5536 case S390_ALU_RSH: return s390_emit_SRLG(buf, dst, dst, 0, DISP20(value));
5537 case S390_ALU_RSHA: return s390_emit_SRAG(buf, dst, dst, 0, DISP20(value));
5545 vpanic("s390_insn_alu_emit");
5550 s390_widen_emit(UChar *buf, const s390_insn *insn, UInt from_size,
5553 s390_opnd_RMI opnd = insn->variant.unop.src;
5556 case S390_OPND_REG: {
5557 UChar r1 = hregNumber(insn->variant.unop.dst);
5558 UChar r2 = hregNumber(opnd.variant.reg);
5560 switch (from_size) {
5562 /* Widening to a half-word is implemented like widening to a word
5563 because the upper half-word will not be looked at. */
5564 if (insn->size == 4 || insn->size == 2) { /* 8 --> 32 8 --> 16 */
5566 return s390_emit_LBRw(buf, r1, r2);
5568 return s390_emit_LLCRw(buf, r1, r2);
5570 if (insn->size == 8) { /* 8 --> 64 */
5572 return s390_emit_LGBRw(buf, r1, r2);
5574 return s390_emit_LLGCRw(buf, r1, r2);
5579 if (insn->size == 4) { /* 16 --> 32 */
5581 return s390_emit_LHRw(buf, r1, r2);
5583 return s390_emit_LLHRw(buf, r1, r2);
5585 if (insn->size == 8) { /* 16 --> 64 */
5587 return s390_emit_LGHRw(buf, r1, r2);
5589 return s390_emit_LLGHRw(buf, r1, r2);
5594 if (insn->size == 8) { /* 32 --> 64 */
5596 return s390_emit_LGFR(buf, r1, r2);
5598 return s390_emit_LLGFR(buf, r1, r2);
5602 default: /* unexpected "from" size */
5607 case S390_OPND_AMODE: {
5608 UChar r1 = hregNumber(insn->variant.unop.dst);
5609 const s390_amode *src = opnd.variant.am;
5610 UChar b = hregNumber(src->b);
5611 UChar x = hregNumber(src->x);
5614 switch (from_size) {
5616 if (insn->size == 4 || insn->size == 2) {
5618 return s390_emit_LBw(buf, r1, x, b, DISP20(d));
5620 return s390_emit_LLCw(buf, r1, x, b, DISP20(d));
5622 if (insn->size == 8) {
5624 return s390_emit_LGBw(buf, r1, x, b, DISP20(d));
5626 return s390_emit_LLGC(buf, r1, x, b, DISP20(d));
5631 if (insn->size == 4) { /* 16 --> 32 */
5632 if (sign_extend == 0)
5633 return s390_emit_LLHw(buf, r1, x, b, DISP20(d));
5636 case S390_AMODE_B12:
5637 case S390_AMODE_BX12:
5638 return s390_emit_LH(buf, r1, x, b, d);
5640 case S390_AMODE_B20:
5641 case S390_AMODE_BX20:
5642 return s390_emit_LHY(buf, r1, x, b, DISP20(d));
5646 if (insn->size == 8) { /* 16 --> 64 */
5648 return s390_emit_LGH(buf, r1, x, b, DISP20(d));
5650 return s390_emit_LLGH(buf, r1, x, b, DISP20(d));
5655 if (insn->size == 8) { /* 32 --> 64 */
5657 return s390_emit_LGF(buf, r1, x, b, DISP20(d));
5659 return s390_emit_LLGF(buf, r1, x, b, DISP20(d));
5663 default: /* unexpected "from" size */
5668 case S390_OPND_IMMEDIATE: {
5669 UChar r1 = hregNumber(insn->variant.unop.dst);
5670 ULong value = opnd.variant.imm;
5672 switch (from_size) {
5674 if (insn->size == 4 || insn->size == 2) { /* 8 --> 32 8 --> 16 */
5676 /* host can do the sign extension to 16-bit; LHI does the rest */
5677 return s390_emit_LHI(buf, r1, (Short)(Char)(UChar)value);
5679 return s390_emit_LHI(buf, r1, value);
5682 if (insn->size == 8) { /* 8 --> 64 */
5684 /* host can do the sign extension to 16-bit; LGHI does the rest */
5685 return s390_emit_LGHI(buf, r1, (Short)(Char)(UChar)value);
5687 return s390_emit_LGHI(buf, r1, value);
5693 if (insn->size == 4) { /* 16 --> 32 */
5694 return s390_emit_LHI(buf, r1, value);
5696 if (insn->size == 8) { /* 16 --> 64 */
5698 return s390_emit_LGHI(buf, r1, value);
5700 return s390_emit_LLILL(buf, r1, value);
5705 if (insn->size == 8) { /* 32 --> 64 */
5707 return s390_emit_LGFIw(buf, r1, value);
5709 return s390_emit_LLILFw(buf, r1, value);
5713 default: /* unexpected "from" size */
5720 vpanic("s390_widen_emit");
5725 s390_negate_emit(UChar *buf, const s390_insn *insn)
5729 opnd = insn->variant.unop.src;
5732 case S390_OPND_REG: {
5733 UChar r1 = hregNumber(insn->variant.unop.dst);
5734 UChar r2 = hregNumber(opnd.variant.reg);
5736 switch (insn->size) {
5740 return s390_emit_LCR(buf, r1, r2);
5743 return s390_emit_LCGR(buf, r1, r2);
5750 case S390_OPND_AMODE: {
5751 UChar r1 = hregNumber(insn->variant.unop.dst);
5753 /* Load bytes into scratch register R0, then negate */
5754 buf = s390_emit_load_mem(buf, insn->size, R0, opnd.variant.am);
5756 switch (insn->size) {
5760 return s390_emit_LCR(buf, r1, R0);
5763 return s390_emit_LCGR(buf, r1, R0);
5770 case S390_OPND_IMMEDIATE: {
5771 UChar r1 = hregNumber(insn->variant.unop.dst);
5772 ULong value = opnd.variant.imm;
5774 value = ~value + 1; /* two's complement */
5776 switch (insn->size) {
5779 /* Load the immediate values as a 4 byte value. That does not hurt as
5780 those extra bytes will not be looked at. Fall through .... */
5782 return s390_emit_load_32imm(buf, r1, value);
5785 return s390_emit_load_64imm(buf, r1, value);
5794 vpanic("s390_negate_emit");
5799 s390_insn_unop_emit(UChar *buf, const s390_insn *insn)
5801 switch (insn->variant.unop.tag) {
5802 case S390_ZERO_EXTEND_8: return s390_widen_emit(buf, insn, 1, 0);
5803 case S390_ZERO_EXTEND_16: return s390_widen_emit(buf, insn, 2, 0);
5804 case S390_ZERO_EXTEND_32: return s390_widen_emit(buf, insn, 4, 0);
5806 case S390_SIGN_EXTEND_8: return s390_widen_emit(buf, insn, 1, 1);
5807 case S390_SIGN_EXTEND_16: return s390_widen_emit(buf, insn, 2, 1);
5808 case S390_SIGN_EXTEND_32: return s390_widen_emit(buf, insn, 4, 1);
5810 case S390_NEGATE: return s390_negate_emit(buf, insn);
5813 vpanic("s390_insn_unop_emit");
5817 /* Only 4-byte and 8-byte operands are handled. 1-byte and 2-byte
5818 comparisons will have been converted to 4-byte comparisons in
5819 s390_isel_cc and should not occur here. */
5821 s390_insn_test_emit(UChar *buf, const s390_insn *insn)
5825 opnd = insn->variant.test.src;
5828 case S390_OPND_REG: {
5829 UInt reg = hregNumber(opnd.variant.reg);
5831 switch (insn->size) {
5833 return s390_emit_LTR(buf, reg, reg);
5836 return s390_emit_LTGR(buf, reg, reg);
5843 case S390_OPND_AMODE: {
5844 const s390_amode *am = opnd.variant.am;
5845 UChar b = hregNumber(am->b);
5846 UChar x = hregNumber(am->x);
5849 switch (insn->size) {
5851 return s390_emit_LTw(buf, R0, x, b, DISP20(d));
5854 return s390_emit_LTGw(buf, R0, x, b, DISP20(d));
5861 case S390_OPND_IMMEDIATE: {
5862 ULong value = opnd.variant.imm;
5864 switch (insn->size) {
5866 buf = s390_emit_load_32imm(buf, R0, value);
5867 return s390_emit_LTR(buf, R0, R0);
5870 buf = s390_emit_load_64imm(buf, R0, value);
5871 return s390_emit_LTGR(buf, R0, R0);
5883 vpanic("s390_insn_test_emit");
5888 s390_insn_cc2bool_emit(UChar *buf, const s390_insn *insn)
5890 UChar r1 = hregNumber(insn->variant.cc2bool.dst);
5891 s390_cc_t cond = insn->variant.cc2bool.cond;
5893 /* Make the destination register be 1 or 0, depending on whether
5894 the relevant condition holds. A 64-bit value is computed. */
5895 if (cond == S390_CC_ALWAYS)
5896 return s390_emit_LGHI(buf, r1, 1); /* r1 = 1 */
5898 buf = s390_emit_load_cc(buf, r1); /* r1 = cc */
5899 buf = s390_emit_LGHI(buf, R0, cond); /* r0 = mask */
5900 buf = s390_emit_SLLG(buf, r1, R0, r1, DISP20(0)); /* r1 = mask << cc */
5901 buf = s390_emit_SRLG(buf, r1, r1, 0, DISP20(3)); /* r1 = r1 >> 3 */
5902 buf = s390_emit_NILL(buf, r1, 1); /* r1 = r1 & 0x1 */
5908 /* Only 4-byte and 8-byte operands are handled. */
5910 s390_insn_cas_emit(UChar *buf, const s390_insn *insn)
5912 UChar r1, r3, b, old;
5916 r1 = hregNumber(insn->variant.cas.op1); /* expected value */
5917 r3 = hregNumber(insn->variant.cas.op3);
5918 old= hregNumber(insn->variant.cas.old_mem);
5919 am = insn->variant.cas.op2;
5920 b = hregNumber(am->b);
5923 switch (insn->size) {
5925 /* r1 must no be overwritten. So copy it to R0 and let CS clobber it */
5926 buf = s390_emit_LR(buf, R0, r1);
5927 if (am->tag == S390_AMODE_B12)
5928 buf = s390_emit_CS(buf, R0, r3, b, d);
5930 buf = s390_emit_CSY(buf, R0, r3, b, DISP20(d));
5931 /* Now copy R0 which has the old memory value to OLD */
5932 return s390_emit_LR(buf, old, R0);
5935 /* r1 must no be overwritten. So copy it to R0 and let CS clobber it */
5936 buf = s390_emit_LGR(buf, R0, r1);
5937 buf = s390_emit_CSG(buf, R0, r3, b, DISP20(d));
5938 /* Now copy R0 which has the old memory value to OLD */
5939 return s390_emit_LGR(buf, old, R0);
5946 vpanic("s390_insn_cas_emit");
5950 /* Only 4-byte and 8-byte comparisons are handled. 1-byte and 2-byte
5951 comparisons will have been converted to 4-byte comparisons in
5952 s390_isel_cc and should not occur here. */
5954 s390_insn_compare_emit(UChar *buf, const s390_insn *insn)
5958 Bool signed_comparison;
5960 op1 = insn->variant.compare.src1;
5961 op2 = insn->variant.compare.src2;
5962 signed_comparison = insn->variant.compare.signed_comparison;
5965 case S390_OPND_REG: {
5966 UInt r1 = hregNumber(op1);
5967 UInt r2 = hregNumber(op2.variant.reg);
5969 switch (insn->size) {
5971 if (signed_comparison)
5972 return s390_emit_CR(buf, r1, r2);
5974 return s390_emit_CLR(buf, r1, r2);
5977 if (signed_comparison)
5978 return s390_emit_CGR(buf, r1, r2);
5980 return s390_emit_CLGR(buf, r1, r2);
5987 case S390_OPND_AMODE: {
5988 UChar r1 = hregNumber(op1);
5989 const s390_amode *am = op2.variant.am;
5990 UChar b = hregNumber(am->b);
5991 UChar x = hregNumber(am->x);
5994 switch (insn->size) {
5997 case S390_AMODE_B12:
5998 case S390_AMODE_BX12:
5999 if (signed_comparison)
6000 return s390_emit_C(buf, r1, x, b, d);
6002 return s390_emit_CL(buf, r1, x, b, d);
6004 case S390_AMODE_B20:
6005 case S390_AMODE_BX20:
6006 if (signed_comparison)
6007 return s390_emit_CY(buf, r1, x, b, DISP20(d));
6009 return s390_emit_CLY(buf, r1, x, b, DISP20(d));
6014 if (signed_comparison)
6015 return s390_emit_CG(buf, r1, x, b, DISP20(d));
6017 return s390_emit_CLG(buf, r1, x, b, DISP20(d));
6024 case S390_OPND_IMMEDIATE: {
6025 UChar r1 = hregNumber(op1);
6026 ULong value = op2.variant.imm;
6028 switch (insn->size) {
6030 if (signed_comparison)
6031 return s390_emit_CFIw(buf, r1, value);
6033 return s390_emit_CLFIw(buf, r1, value);
6036 buf = s390_emit_load_64imm(buf, R0, value);
6037 if (signed_comparison)
6038 return s390_emit_CGR(buf, r1, R0);
6040 return s390_emit_CLGR(buf, r1, R0);
6052 vpanic("s390_insn_compare_emit");
6057 s390_insn_mul_emit(UChar *buf, const s390_insn *insn)
6061 Bool signed_multiply;
6063 /* The register number identifying the register pair */
6064 r1 = hregNumber(insn->variant.mul.dst_hi);
6066 op2 = insn->variant.mul.op2;
6067 signed_multiply = insn->variant.mul.signed_multiply;
6070 case S390_OPND_REG: {
6071 UInt r2 = hregNumber(op2.variant.reg);
6073 switch (insn->size) {
6077 if (signed_multiply)
6078 return s390_emit_MR(buf, r1, r2);
6080 return s390_emit_MLR(buf, r1, r2);
6083 if (signed_multiply)
6084 vpanic("s390_insn_mul_emit");
6086 return s390_emit_MLGR(buf, r1, r2);
6093 case S390_OPND_AMODE: {
6094 const s390_amode *am = op2.variant.am;
6095 UChar b = hregNumber(am->b);
6096 UChar x = hregNumber(am->x);
6099 switch (insn->size) {
6102 /* Load bytes into scratch register R0, then multiply */
6103 buf = s390_emit_load_mem(buf, insn->size, R0, am);
6104 if (signed_multiply)
6105 return s390_emit_MR(buf, r1, R0);
6107 return s390_emit_MLR(buf, r1, R0);
6111 case S390_AMODE_B12:
6112 case S390_AMODE_BX12:
6113 if (signed_multiply)
6114 return s390_emit_M(buf, r1, x, b, d);
6116 return s390_emit_ML(buf, r1, x, b, DISP20(d));
6118 case S390_AMODE_B20:
6119 case S390_AMODE_BX20:
6120 if (signed_multiply)
6121 return s390_emit_MFYw(buf, r1, x, b, DISP20(d));
6123 return s390_emit_ML(buf, r1, x, b, DISP20(d));
6128 if (signed_multiply)
6129 vpanic("s390_insn_mul_emit");
6131 return s390_emit_MLG(buf, r1, x, b, DISP20(d));
6138 case S390_OPND_IMMEDIATE: {
6139 ULong value = op2.variant.imm;
6141 switch (insn->size) {
6145 buf = s390_emit_load_32imm(buf, R0, value);
6146 if (signed_multiply)
6147 return s390_emit_MR(buf, r1, R0);
6149 return s390_emit_MLR(buf, r1, R0);
6152 buf = s390_emit_load_64imm(buf, R0, value);
6153 if (signed_multiply)
6154 vpanic("s390_insn_mul_emit");
6156 return s390_emit_MLGR(buf, r1, R0);
6168 vpanic("s390_insn_mul_emit");
6173 s390_insn_div_emit(UChar *buf, const s390_insn *insn)
6179 r1 = hregNumber(insn->variant.div.op1_hi);
6180 op2 = insn->variant.div.op2;
6181 signed_divide = insn->variant.div.signed_divide;
6184 case S390_OPND_REG: {
6185 UInt r2 = hregNumber(op2.variant.reg);
6187 switch (insn->size) {
6190 return s390_emit_DR(buf, r1, r2);
6192 return s390_emit_DLR(buf, r1, r2);
6196 vpanic("s390_insn_div_emit");
6198 return s390_emit_DLGR(buf, r1, r2);
6205 case S390_OPND_AMODE: {
6206 const s390_amode *am = op2.variant.am;
6207 UChar b = hregNumber(am->b);
6208 UChar x = hregNumber(am->x);
6211 switch (insn->size) {
6214 case S390_AMODE_B12:
6215 case S390_AMODE_BX12:
6217 return s390_emit_D(buf, r1, x, b, d);
6219 return s390_emit_DL(buf, r1, x, b, DISP20(d));
6221 case S390_AMODE_B20:
6222 case S390_AMODE_BX20:
6223 if (signed_divide) {
6224 buf = s390_emit_LY(buf, R0, x, b, DISP20(d));
6225 return s390_emit_DR(buf, r1, R0);
6227 return s390_emit_DL(buf, r1, x, b, DISP20(d));
6233 vpanic("s390_insn_div_emit");
6235 return s390_emit_DLG(buf, r1, x, b, DISP20(d));
6242 case S390_OPND_IMMEDIATE: {
6243 ULong value = op2.variant.imm;
6245 switch (insn->size) {
6247 buf = s390_emit_load_32imm(buf, R0, value);
6249 return s390_emit_DR(buf, r1, R0);
6251 return s390_emit_DLR(buf, r1, R0);
6254 buf = s390_emit_load_64imm(buf, R0, value);
6256 vpanic("s390_insn_div_emit");
6258 return s390_emit_DLGR(buf, r1, R0);
6270 vpanic("s390_insn_div_emit");
6275 s390_insn_divs_emit(UChar *buf, const s390_insn *insn)
6280 r1 = hregNumber(insn->variant.divs.rem);
6281 op2 = insn->variant.divs.op2;
6284 case S390_OPND_REG: {
6285 UInt r2 = hregNumber(op2.variant.reg);
6287 return s390_emit_DSGR(buf, r1, r2);
6290 case S390_OPND_AMODE: {
6291 const s390_amode *am = op2.variant.am;
6292 UChar b = hregNumber(am->b);
6293 UChar x = hregNumber(am->x);
6296 return s390_emit_DSG(buf, r1, x, b, DISP20(d));
6299 case S390_OPND_IMMEDIATE: {
6300 ULong value = op2.variant.imm;
6302 buf = s390_emit_load_64imm(buf, R0, value);
6303 return s390_emit_DSGR(buf, r1, R0);
6311 vpanic("s390_insn_divs_emit");
6316 s390_insn_clz_emit(UChar *buf, const s390_insn *insn)
6319 UChar r1, r1p1, r2, *p;
6321 r1 = hregNumber(insn->variant.clz.num_bits);
6322 r1p1 = hregNumber(insn->variant.clz.clobber);
6324 vassert((r1 & 0x1) == 0);
6325 vassert(r1p1 == r1 + 1);
6328 src = insn->variant.clz.src;
6330 /* Get operand and move it to r2 */
6333 r2 = hregNumber(src.variant.reg);
6336 case S390_OPND_AMODE: {
6337 const s390_amode *am = src.variant.am;
6338 UChar b = hregNumber(am->b);
6339 UChar x = hregNumber(am->x);
6342 p = s390_emit_LG(p, R0, x, b, DISP20(d));
6347 case S390_OPND_IMMEDIATE: {
6348 ULong value = src.variant.imm;
6350 p = s390_emit_load_64imm(p, R0, value);
6359 /* Use FLOGR if you can */
6360 if (s390_host_has_eimm) {
6361 return s390_emit_FLOGR(p, r1, r2);
6372 p = s390_emit_LTGR(p, R0, r2);
6373 p = s390_emit_LLILL(p, r1, 64);
6375 p = s390_emit_BRC(p, S390_CC_E, (4 + 4 + 6 + 4 + 4)/ 2); /* 4 bytes */
6376 p = s390_emit_AGHI(p, r1, (UShort)-1); /* r1 -= 1; 4 bytes */
6377 p = s390_emit_SRLG(p, R0, R0, R0, DISP20(1)); /* r0 >>= 1; 6 bytes */
6378 p = s390_emit_LTGR(p, R0, R0); /* set cc 4 bytes */
6379 p = s390_emit_BRC(p, S390_CC_NE, /* 4 bytes */
6380 (UShort)(-(4 + 6 + 4) / 2));
6384 vpanic("s390_insn_clz_emit");
6389 s390_insn_branch_emit(UChar *buf, const s390_insn *insn)
6394 UChar *p, *ptmp = 0; /* avoid compiler warnings */
6396 cond = insn->variant.branch.cond;
6397 dst = insn->variant.branch.dst;
6402 if (cond != S390_CC_ALWAYS) {
6403 /* So we have something like this
6406 We convert this into
6407 if (! cond) goto Y; // BRC insn; 4 bytes
6409 return to dispatcher
6412 ptmp = p; /* 4 bytes (a BRC insn) to be filled in here */
6416 /* If a non-boring, set guest-state-pointer appropriately. */
6418 switch (insn->variant.branch.kind) {
6419 case Ijk_ClientReq: trc = VEX_TRC_JMP_CLIENTREQ; break;
6420 case Ijk_Sys_syscall: trc = VEX_TRC_JMP_SYS_SYSCALL; break;
6421 case Ijk_Yield: trc = VEX_TRC_JMP_YIELD; break;
6422 case Ijk_EmWarn: trc = VEX_TRC_JMP_EMWARN; break;
6423 case Ijk_EmFail: trc = VEX_TRC_JMP_EMFAIL; break;
6424 case Ijk_MapFail: trc = VEX_TRC_JMP_MAPFAIL; break;
6425 case Ijk_NoDecode: trc = VEX_TRC_JMP_NODECODE; break;
6426 case Ijk_TInval: trc = VEX_TRC_JMP_TINVAL; break;
6427 case Ijk_NoRedir: trc = VEX_TRC_JMP_NOREDIR; break;
6428 case Ijk_SigTRAP: trc = VEX_TRC_JMP_SIGTRAP; break;
6429 case Ijk_Ret: trc = 0; break;
6430 case Ijk_Call: trc = 0; break;
6431 case Ijk_Boring: trc = 0; break;
6435 vpanic("s390_insn_branch_emit: unknown jump kind");
6438 /* Get the destination address into the return register */
6441 p = s390_emit_LGR(p, S390_REGNO_RETURN_VALUE, hregNumber(dst.variant.reg));
6444 case S390_OPND_AMODE: {
6445 const s390_amode *am = dst.variant.am;
6446 UChar b = hregNumber(am->b);
6447 UChar x = hregNumber(am->x);
6450 p = s390_emit_LG(p, S390_REGNO_RETURN_VALUE, x, b, DISP20(d));
6454 case S390_OPND_IMMEDIATE:
6455 p = s390_emit_load_64imm(p, S390_REGNO_RETURN_VALUE, dst.variant.imm);
6463 /* Something special. Set guest-state pointer appropriately */
6464 p = s390_emit_LGHI(p, S390_REGNO_GUEST_STATE_POINTER, trc);
6466 /* Nothing special needs to be done for calls and returns. */
6469 p = s390_emit_BCR(p, S390_CC_ALWAYS, S390_REGNO_LINK_REGISTER);
6471 if (cond != S390_CC_ALWAYS) {
6472 Int delta = p - ptmp;
6474 delta >>= 1; /* immediate constant is #half-words */
6475 vassert(delta > 0 && delta < (1 << 16));
6476 s390_emit_BRC(ptmp, s390_cc_invert(cond), delta);
6482 vpanic("s390_insn_branch_emit");
6487 s390_insn_helper_call_emit(UChar *buf, const s390_insn *insn)
6493 cond = insn->variant.helper_call.cond;
6494 target = insn->variant.helper_call.target;
6496 if (cond != S390_CC_ALWAYS) {
6497 /* So we have something like this
6500 We convert this into
6501 if (! cond) goto Y; // BRC opcode; 4 bytes
6505 /* 4 bytes (a BRC insn) to be filled in here */
6509 /* Load the target address into a register, that
6510 (a) is not used for passing parameters to the helper and
6511 (b) can be clobbered by the callee
6512 r1 looks like a good choice.
6513 Also, need to arrange for the return address be put into the
6515 buf = s390_emit_load_64imm(buf, 1, target);
6517 /* Stash away the client's FPC register because the helper might change it. */
6518 buf = s390_emit_STFPC(buf, S390_REGNO_STACK_POINTER, S390_OFFSET_SAVED_FPC_C);
6520 /* Before we can call the helper, we need to save the link register,
6521 because the BASR will overwrite it. We cannot use a register for that.
6522 (a) Volatile registers will be modified by the helper.
6523 (b) For saved registers the client code assumes that they have not
6524 changed after the function returns. So we cannot use it to store
6526 In the dispatcher, before calling the client code, we have arranged for
6527 a location on the stack for this purpose. See dispatch-s390x-linux.S. */
6528 buf = s390_emit_STG(buf, S390_REGNO_LINK_REGISTER, 0, // save LR
6529 S390_REGNO_STACK_POINTER, S390_OFFSET_SAVED_LR, 0);
6530 buf = s390_emit_BASR(buf, S390_REGNO_LINK_REGISTER, 1); // call helper
6531 buf = s390_emit_LG(buf, S390_REGNO_LINK_REGISTER, 0, // restore LR
6532 S390_REGNO_STACK_POINTER, S390_OFFSET_SAVED_LR, 0);
6533 buf = s390_emit_LFPC(buf, S390_REGNO_STACK_POINTER, // restore FPC
6534 S390_OFFSET_SAVED_FPC_C);
6536 if (cond != S390_CC_ALWAYS) {
6537 Int delta = buf - ptmp;
6539 delta >>= 1; /* immediate constant is #half-words */
6540 vassert(delta > 0 && delta < (1 << 16));
6541 s390_emit_BRC(ptmp, s390_cc_invert(cond), delta);
6549 s390_insn_cond_move_emit(UChar *buf, const s390_insn *insn)
6554 UChar *p, *ptmp = 0; /* avoid compiler warnings */
6556 cond = insn->variant.cond_move.cond;
6557 dst = insn->variant.cond_move.dst;
6558 src = insn->variant.cond_move.src;
6562 /* Branch (if cond fails) over move instrs */
6563 if (cond != S390_CC_ALWAYS) {
6564 /* Don't know how many bytes to jump over yet.
6565 Make space for a BRC instruction (4 bytes) and fill in later. */
6566 ptmp = p; /* to be filled in here */
6570 // cond true: move src => dst
6574 p = s390_emit_LGR(p, hregNumber(dst), hregNumber(src.variant.reg));
6577 case S390_OPND_AMODE:
6578 p = s390_emit_load_mem(p, insn->size, hregNumber(dst), src.variant.am);
6581 case S390_OPND_IMMEDIATE: {
6582 ULong value = src.variant.imm;
6583 UInt r = hregNumber(dst);
6585 switch (insn->size) {
6588 /* Load the immediate values as a 4 byte value. That does not hurt as
6589 those extra bytes will not be looked at. Fall through .... */
6591 p = s390_emit_load_32imm(p, r, value);
6595 p = s390_emit_load_64imm(p, r, value);
6605 if (cond != S390_CC_ALWAYS) {
6606 Int delta = p - ptmp;
6608 delta >>= 1; /* immediate constant is #half-words */
6609 vassert(delta > 0 && delta < (1 << 16));
6610 s390_emit_BRC(ptmp, s390_cc_invert(cond), delta);
6616 vpanic("s390_insn_cond_move_emit");
6620 /* Little helper function to the rounding mode in the real FPC
6623 s390_set_fpc_rounding_mode(UChar *buf, s390_round_t rounding_mode)
6627 /* Determine BFP rounding bits */
6628 switch (rounding_mode) {
6629 case S390_ROUND_NEAREST_EVEN: bits = 0; break;
6630 case S390_ROUND_ZERO: bits = 1; break;
6631 case S390_ROUND_POSINF: bits = 2; break;
6632 case S390_ROUND_NEGINF: bits = 3; break;
6633 default: vpanic("invalid rounding mode\n");
6636 /* Copy FPC from guest state to R0 and OR in the new rounding mode */
6637 buf = s390_emit_L(buf, R0, 0, S390_REGNO_GUEST_STATE_POINTER,
6638 OFFSET_s390x_fpc); // r0 = guest_fpc
6640 buf = s390_emit_NILL(buf, R0, 0xFFFC); /* Clear out right-most 2 bits */
6641 buf = s390_emit_OILL(buf, R0, bits); /* OR in the new rounding mode */
6642 buf = s390_emit_SFPC(buf, R0, 0); /* Load FPC register from R0 */
6649 s390_insn_bfp_triop_emit(UChar *buf, const s390_insn *insn)
6651 UInt r1 = hregNumber(insn->variant.bfp_triop.dst);
6652 UInt r2 = hregNumber(insn->variant.bfp_triop.op2);
6653 UInt r3 = hregNumber(insn->variant.bfp_triop.op3);
6654 s390_round_t rounding_mode = insn->variant.bfp_triop.rounding_mode;
6656 if (rounding_mode != S390_ROUND_NEAREST_EVEN) {
6657 buf = s390_set_fpc_rounding_mode(buf, rounding_mode);
6660 switch (insn->size) {
6662 switch (insn->variant.bfp_triop.tag) {
6663 case S390_BFP_MADD: buf = s390_emit_MAEBR(buf, r1, r3, r2); break;
6664 case S390_BFP_MSUB: buf = s390_emit_MSEBR(buf, r1, r3, r2); break;
6670 switch (insn->variant.bfp_triop.tag) {
6671 case S390_BFP_MADD: buf = s390_emit_MADBR(buf, r1, r3, r2); break;
6672 case S390_BFP_MSUB: buf = s390_emit_MSDBR(buf, r1, r3, r2); break;
6680 if (rounding_mode != S390_ROUND_NEAREST_EVEN) {
6681 /* Restore FPC register from guest state */
6682 buf = s390_emit_LFPC(buf, S390_REGNO_GUEST_STATE_POINTER,
6683 OFFSET_s390x_fpc); // fpc = guest_fpc
6688 vpanic("s390_insn_bfp_triop_emit");
6693 s390_insn_bfp_binop_emit(UChar *buf, const s390_insn *insn)
6695 UInt r1 = hregNumber(insn->variant.bfp_binop.dst);
6696 UInt r2 = hregNumber(insn->variant.bfp_binop.op2);
6697 s390_round_t rounding_mode = insn->variant.bfp_binop.rounding_mode;
6699 if (rounding_mode != S390_ROUND_NEAREST_EVEN) {
6700 buf = s390_set_fpc_rounding_mode(buf, rounding_mode);
6703 switch (insn->size) {
6705 switch (insn->variant.bfp_binop.tag) {
6706 case S390_BFP_ADD: buf = s390_emit_AEBR(buf, r1, r2); break;
6707 case S390_BFP_SUB: buf = s390_emit_SEBR(buf, r1, r2); break;
6708 case S390_BFP_MUL: buf = s390_emit_MEEBR(buf, r1, r2); break;
6709 case S390_BFP_DIV: buf = s390_emit_DEBR(buf, r1, r2); break;
6715 switch (insn->variant.bfp_binop.tag) {
6716 case S390_BFP_ADD: buf = s390_emit_ADBR(buf, r1, r2); break;
6717 case S390_BFP_SUB: buf = s390_emit_SDBR(buf, r1, r2); break;
6718 case S390_BFP_MUL: buf = s390_emit_MDBR(buf, r1, r2); break;
6719 case S390_BFP_DIV: buf = s390_emit_DDBR(buf, r1, r2); break;
6727 if (rounding_mode != S390_ROUND_NEAREST_EVEN) {
6728 /* Restore FPC register from guest state */
6729 buf = s390_emit_LFPC(buf, S390_REGNO_GUEST_STATE_POINTER,
6735 vpanic("s390_insn_bfp_binop_emit");
6740 s390_insn_bfp_unop_emit(UChar *buf, const s390_insn *insn)
6742 UInt r1 = hregNumber(insn->variant.bfp_unop.dst);
6743 UInt r2 = hregNumber(insn->variant.bfp_unop.op);
6744 s390_round_t rounding_mode = insn->variant.bfp_unop.rounding_mode;
6745 s390_round_t m3 = rounding_mode;
6747 /* The "convert to fixed" instructions have a field for the rounding
6748 mode and no FPC modification is necessary. So we handle them
6750 switch (insn->variant.bfp_unop.tag) {
6751 case S390_BFP_F32_TO_I32: return s390_emit_CFEBR(buf, m3, r1, r2);
6752 case S390_BFP_F64_TO_I32: return s390_emit_CFDBR(buf, m3, r1, r2);
6753 case S390_BFP_F32_TO_I64: return s390_emit_CGEBR(buf, m3, r1, r2);
6754 case S390_BFP_F64_TO_I64: return s390_emit_CGDBR(buf, m3, r1, r2);
6758 /* For all other insns if a special rounding mode is requested,
6759 we need to set the FPC first and restore it later. */
6760 if (rounding_mode != S390_ROUND_NEAREST_EVEN) {
6761 buf = s390_set_fpc_rounding_mode(buf, rounding_mode);
6764 switch (insn->variant.bfp_unop.tag) {
6766 switch (insn->size) {
6767 case 4: buf = s390_emit_LPEBR(buf, r1, r2); break;
6768 case 8: buf = s390_emit_LPDBR(buf, r1, r2); break;
6769 case 16: buf = s390_emit_LPXBR(buf, r1, r2); break;
6775 switch (insn->size) {
6776 case 4: buf = s390_emit_LNEBR(buf, r1, r2); break;
6777 case 8: buf = s390_emit_LNDBR(buf, r1, r2); break;
6778 case 16: buf = s390_emit_LNXBR(buf, r1, r2); break;
6784 switch (insn->size) {
6785 case 4: buf = s390_emit_LCEBR(buf, r1, r2); break;
6786 case 8: buf = s390_emit_LCDBR(buf, r1, r2); break;
6787 case 16: buf = s390_emit_LCXBR(buf, r1, r2); break;
6793 switch (insn->size) {
6794 case 4: buf = s390_emit_SQEBR(buf, r1, r2); break;
6795 case 8: buf = s390_emit_SQDBR(buf, r1, r2); break;
6796 case 16: buf = s390_emit_SQXBR(buf, r1, r2); break;
6801 case S390_BFP_I32_TO_F32: buf = s390_emit_CEFBR(buf, r1, r2); break;
6802 case S390_BFP_I32_TO_F64: buf = s390_emit_CDFBR(buf, r1, r2); break;
6803 case S390_BFP_I32_TO_F128: buf = s390_emit_CXFBR(buf, r1, r2); break;
6804 case S390_BFP_I64_TO_F32: buf = s390_emit_CEGBR(buf, r1, r2); break;
6805 case S390_BFP_I64_TO_F64: buf = s390_emit_CDGBR(buf, r1, r2); break;
6806 case S390_BFP_I64_TO_F128: buf = s390_emit_CXGBR(buf, r1, r2); break;
6808 case S390_BFP_F32_TO_F64: buf = s390_emit_LDEBR(buf, r1, r2); break;
6809 case S390_BFP_F32_TO_F128: buf = s390_emit_LXEBR(buf, r1, r2); break;
6810 case S390_BFP_F64_TO_F32: buf = s390_emit_LEDBR(buf, r1, r2); break;
6811 case S390_BFP_F64_TO_F128: buf = s390_emit_LXDBR(buf, r1, r2); break;
6816 if (rounding_mode != S390_ROUND_NEAREST_EVEN) {
6817 /* Restore FPC register from guest state */
6818 buf = s390_emit_LFPC(buf, S390_REGNO_GUEST_STATE_POINTER,
6819 OFFSET_s390x_fpc); // fpc = guest_fpc
6824 vpanic("s390_insn_bfp_unop_emit");
6829 s390_insn_bfp_compare_emit(UChar *buf, const s390_insn *insn)
6831 UInt dst = hregNumber(insn->variant.bfp_compare.dst);
6832 UInt r1 = hregNumber(insn->variant.bfp_compare.op1);
6833 UInt r2 = hregNumber(insn->variant.bfp_compare.op2);
6835 switch (insn->size) {
6837 buf = s390_emit_CEBR(buf, r1, r2);
6841 buf = s390_emit_CDBR(buf, r1, r2);
6847 return s390_emit_load_cc(buf, dst); /* Load condition code into DST */
6850 vpanic("s390_insn_bfp_compare_emit");
6855 s390_insn_bfp128_binop_emit(UChar *buf, const s390_insn *insn)
6857 UInt r1_hi = hregNumber(insn->variant.bfp128_binop.dst_hi);
6858 UInt r1_lo = hregNumber(insn->variant.bfp128_binop.dst_lo);
6859 UInt r2_hi = hregNumber(insn->variant.bfp128_binop.op2_hi);
6860 UInt r2_lo = hregNumber(insn->variant.bfp128_binop.op2_lo);
6861 s390_round_t rounding_mode = insn->variant.bfp_binop.rounding_mode;
6864 vassert(insn->size == 16);
6865 vassert(r1_lo == r1_hi + 2);
6866 vassert(r2_lo == r2_hi + 2);
6867 vassert((r1_hi & 0x2) == 0);
6868 vassert((r2_hi & 0x2) == 0);
6870 if (rounding_mode != S390_ROUND_NEAREST_EVEN) {
6871 buf = s390_set_fpc_rounding_mode(buf, rounding_mode);
6874 switch (insn->variant.bfp128_binop.tag) {
6875 case S390_BFP_ADD: buf = s390_emit_AXBR(buf, r1_hi, r2_hi); break;
6876 case S390_BFP_SUB: buf = s390_emit_SXBR(buf, r1_hi, r2_hi); break;
6877 case S390_BFP_MUL: buf = s390_emit_MXBR(buf, r1_hi, r2_hi); break;
6878 case S390_BFP_DIV: buf = s390_emit_DXBR(buf, r1_hi, r2_hi); break;
6882 if (rounding_mode != S390_ROUND_NEAREST_EVEN) {
6883 /* Restore FPC register from guest state */
6884 buf = s390_emit_LFPC(buf, S390_REGNO_GUEST_STATE_POINTER,
6885 OFFSET_s390x_fpc); // fpc = guest_fpc
6890 vpanic("s390_insn_bfp128_binop_emit");
6895 s390_insn_bfp128_compare_emit(UChar *buf, const s390_insn *insn)
6897 UInt dst = hregNumber(insn->variant.bfp128_compare.dst);
6898 UInt r1_hi = hregNumber(insn->variant.bfp128_compare.op1_hi);
6899 UInt r1_lo = hregNumber(insn->variant.bfp128_compare.op1_lo);
6900 UInt r2_hi = hregNumber(insn->variant.bfp128_compare.op2_hi);
6901 UInt r2_lo = hregNumber(insn->variant.bfp128_compare.op2_lo);
6904 vassert(insn->size == 16);
6905 vassert(r1_lo == r1_hi + 2);
6906 vassert(r2_lo == r2_hi + 2);
6907 vassert((r1_hi & 0x2) == 0);
6908 vassert((r2_hi & 0x2) == 0);
6910 buf = s390_emit_CXBR(buf, r1_hi, r2_hi);
6912 /* Load condition code into DST */
6913 return s390_emit_load_cc(buf, dst);
6918 s390_insn_bfp128_unop_emit(UChar *buf, const s390_insn *insn)
6920 UInt r1_hi = hregNumber(insn->variant.bfp128_unop.dst_hi);
6921 UInt r1_lo = hregNumber(insn->variant.bfp128_unop.dst_lo);
6922 UInt r2_hi = hregNumber(insn->variant.bfp128_unop.op_hi);
6923 UInt r2_lo = hregNumber(insn->variant.bfp128_unop.op_lo);
6924 s390_round_t rounding_mode = insn->variant.bfp_binop.rounding_mode;
6927 vassert(insn->size == 16);
6928 vassert(r1_lo == r1_hi + 2);
6929 vassert(r2_lo == r2_hi + 2);
6930 vassert((r1_hi & 0x2) == 0);
6931 vassert((r2_hi & 0x2) == 0);
6933 if (rounding_mode != S390_ROUND_NEAREST_EVEN) {
6934 buf = s390_set_fpc_rounding_mode(buf, rounding_mode);
6937 switch (insn->variant.bfp128_unop.tag) {
6938 case S390_BFP_ABS: buf = s390_emit_LPXBR(buf, r1_hi, r2_hi); break;
6939 case S390_BFP_NABS: buf = s390_emit_LNXBR(buf, r1_hi, r2_hi); break;
6940 case S390_BFP_NEG: buf = s390_emit_LCXBR(buf, r1_hi, r2_hi); break;
6941 case S390_BFP_SQRT: buf = s390_emit_SQXBR(buf, r1_hi, r2_hi); break;
6942 case S390_BFP_F128_TO_F32: buf = s390_emit_LEXBR(buf, r1_hi, r2_hi); break;
6943 case S390_BFP_F128_TO_F64: buf = s390_emit_LDXBR(buf, r1_hi, r2_hi); break;
6947 if (rounding_mode != S390_ROUND_NEAREST_EVEN) {
6948 /* Restore FPC register from guest state */
6949 buf = s390_emit_LFPC(buf, S390_REGNO_GUEST_STATE_POINTER,
6950 OFFSET_s390x_fpc); // fpc = guest_fpc
6955 vpanic("s390_insn_bfp128_unop_emit");
6959 /* Conversion to 128-bit BFP does not require a rounding mode */
6961 s390_insn_bfp128_convert_to_emit(UChar *buf, const s390_insn *insn)
6963 UInt r1_hi = hregNumber(insn->variant.bfp128_unop.dst_hi);
6964 UInt r1_lo = hregNumber(insn->variant.bfp128_unop.dst_lo);
6965 UInt r2 = hregNumber(insn->variant.bfp128_unop.op_hi);
6968 vassert(insn->size == 16);
6969 vassert(r1_lo == r1_hi + 2);
6970 vassert((r1_hi & 0x2) == 0);
6972 switch (insn->variant.bfp128_unop.tag) {
6973 case S390_BFP_I32_TO_F128: buf = s390_emit_CXFBR(buf, r1_hi, r2); break;
6974 case S390_BFP_I64_TO_F128: buf = s390_emit_CXGBR(buf, r1_hi, r2); break;
6975 case S390_BFP_F32_TO_F128: buf = s390_emit_LXEBR(buf, r1_hi, r2); break;
6976 case S390_BFP_F64_TO_F128: buf = s390_emit_LXDBR(buf, r1_hi, r2); break;
6983 vpanic("s390_insn_bfp128_convert_to_emit");
6988 s390_insn_bfp128_convert_from_emit(UChar *buf, const s390_insn *insn)
6990 UInt r1 = hregNumber(insn->variant.bfp128_unop.dst_hi);
6991 UInt r2_hi = hregNumber(insn->variant.bfp128_unop.op_hi);
6992 UInt r2_lo = hregNumber(insn->variant.bfp128_unop.op_lo);
6993 s390_round_t rounding_mode = insn->variant.bfp_binop.rounding_mode;
6996 vassert(insn->size != 16);
6997 vassert(r2_lo == r2_hi + 2);
6998 vassert((r2_hi & 0x2) == 0);
7000 /* The "convert to fixed" instructions have a field for the rounding
7001 mode and no FPC modification is necessary. So we handle them
7003 switch (insn->variant.bfp_unop.tag) {
7004 case S390_BFP_F128_TO_I32: return s390_emit_CFXBR(buf, rounding_mode,
7006 case S390_BFP_F128_TO_I64: return s390_emit_CGXBR(buf, rounding_mode,
7011 vpanic("s390_insn_bfp128_convert_from_emit");
7016 s390_insn_mfence_emit(UChar *buf, const s390_insn *insn)
7018 return s390_emit_BCR(buf, 0xF, 0x0);
7023 emit_S390Instr(UChar *buf, Int nbuf, struct s390_insn *insn,
7024 Bool mode64, void *dispatch)
7028 switch (insn->tag) {
7029 case S390_INSN_LOAD:
7030 end = s390_insn_load_emit(buf, insn);
7033 case S390_INSN_STORE:
7034 end = s390_insn_store_emit(buf, insn);
7037 case S390_INSN_MOVE:
7038 end = s390_insn_move_emit(buf, insn);
7041 case S390_INSN_COND_MOVE:
7042 end = s390_insn_cond_move_emit(buf, insn);
7045 case S390_INSN_LOAD_IMMEDIATE:
7046 end = s390_insn_load_immediate_emit(buf, insn);
7050 end = s390_insn_alu_emit(buf, insn);
7054 end = s390_insn_mul_emit(buf, insn);
7058 end = s390_insn_div_emit(buf, insn);
7061 case S390_INSN_DIVS:
7062 end = s390_insn_divs_emit(buf, insn);
7066 end = s390_insn_clz_emit(buf, insn);
7069 case S390_INSN_UNOP:
7070 end = s390_insn_unop_emit(buf, insn);
7073 case S390_INSN_TEST:
7074 end = s390_insn_test_emit(buf, insn);
7077 case S390_INSN_CC2BOOL:
7078 end = s390_insn_cc2bool_emit(buf, insn);
7082 end = s390_insn_cas_emit(buf, insn);
7085 case S390_INSN_COMPARE:
7086 end = s390_insn_compare_emit(buf, insn);
7089 case S390_INSN_BRANCH:
7090 end = s390_insn_branch_emit(buf, insn);
7093 case S390_INSN_HELPER_CALL:
7094 end = s390_insn_helper_call_emit(buf, insn);
7097 case S390_INSN_BFP_TRIOP:
7098 end = s390_insn_bfp_triop_emit(buf, insn);
7101 case S390_INSN_BFP_BINOP:
7102 end = s390_insn_bfp_binop_emit(buf, insn);
7105 case S390_INSN_BFP_UNOP:
7106 end = s390_insn_bfp_unop_emit(buf, insn);
7109 case S390_INSN_BFP_COMPARE:
7110 end = s390_insn_bfp_compare_emit(buf, insn);
7113 case S390_INSN_BFP128_BINOP:
7114 end = s390_insn_bfp128_binop_emit(buf, insn);
7117 case S390_INSN_BFP128_COMPARE:
7118 end = s390_insn_bfp128_compare_emit(buf, insn);
7121 case S390_INSN_BFP128_UNOP:
7122 end = s390_insn_bfp128_unop_emit(buf, insn);
7125 case S390_INSN_BFP128_CONVERT_TO:
7126 end = s390_insn_bfp128_convert_to_emit(buf, insn);
7129 case S390_INSN_BFP128_CONVERT_FROM:
7130 end = s390_insn_bfp128_convert_from_emit(buf, insn);
7133 case S390_INSN_MFENCE:
7134 end = s390_insn_mfence_emit(buf, insn);
7138 vpanic("s390_insn_emit");
7141 vassert(end - buf <= nbuf);
7147 /*---------------------------------------------------------------*/
7148 /*--- end host_s390_defs.c ---*/
7149 /*---------------------------------------------------------------*/