Remove warning caused by D demangle testcase
[valgrind.git] / VEX / priv / host_s390_defs.c
blobc811dc5b80be420fc84c1b90dc881eb2ff35e7d1
1 /* -*- mode: C; c-basic-offset: 3; -*- */
3 /*---------------------------------------------------------------*/
4 /*--- begin host_s390_defs.c ---*/
5 /*---------------------------------------------------------------*/
7 /*
8 This file is part of Valgrind, a dynamic binary instrumentation
9 framework.
11 Copyright IBM Corp. 2010-2020
12 Copyright (C) 2012-2017 Florian Krohm (britzel@acm.org)
14 This program is free software; you can redistribute it and/or
15 modify it under the terms of the GNU General Public License as
16 published by the Free Software Foundation; either version 2 of the
17 License, or (at your option) any later version.
19 This program is distributed in the hope that it will be useful, but
20 WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 General Public License for more details.
24 You should have received a copy of the GNU General Public License
25 along with this program; if not, see <http://www.gnu.org/licenses/>.
27 The GNU General Public License is contained in the file COPYING.
30 /* Contributed by Florian Krohm */
32 #include "libvex_basictypes.h"
33 #include "libvex.h"
34 #include "libvex_trc_values.h"
35 #include "libvex_s390x_common.h"
37 #include "main_util.h"
38 #include "main_globals.h"
39 #include "host_generic_regs.h"
40 #include "host_s390_defs.h"
41 #include "s390_disasm.h"
42 #include "guest_s390_defs.h" /* S390X_GUEST_OFFSET */
43 #include <stdarg.h>
45 /*------------------------------------------------------------*/
46 /*--- Forward declarations ---*/
47 /*------------------------------------------------------------*/
49 static void s390_insn_map_regs(HRegRemap *, s390_insn *);
50 static void s390_insn_get_reg_usage(HRegUsage *u, const s390_insn *);
51 static UInt s390_tchain_load64_len(void);
54 /*------------------------------------------------------------*/
55 /*--- Registers ---*/
56 /*------------------------------------------------------------*/
58 /* A mapping from register number to register index */
59 static Int gpr_index[16]; // GPR regno -> register index
60 static Int vr_index[32]; // VR regno -> register index
62 HReg
63 s390_hreg_gpr(UInt regno)
65 Int ix = gpr_index[regno];
66 vassert(ix >= 0);
67 return mkHReg(/*virtual*/False, HRcInt64, regno, ix);
70 HReg
71 s390_hreg_fpr(UInt regno)
73 Int ix = vr_index[regno];
74 vassert(ix >= 0);
75 return mkHReg(/*virtual*/False, HRcFlt64, regno, ix);
78 HReg
79 s390_hreg_vr(UInt regno)
81 Int ix = vr_index[regno];
82 vassert(ix >= 0);
83 return mkHReg(/*virtual*/False, HRcVec128, regno, ix);
86 static __inline__ UInt
87 hregNumber(HReg reg)
89 return hregEncoding(reg);
92 /* Decompile the given register into a static buffer and return it */
93 const HChar *
94 s390_hreg_as_string(HReg reg)
96 static HChar buf[10];
98 static const HChar ireg_names[16][5] = {
99 "%r0", "%r1", "%r2", "%r3", "%r4", "%r5", "%r6", "%r7",
100 "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15"
103 static const HChar freg_names[16][5] = {
104 "%f0", "%f1", "%f2", "%f3", "%f4", "%f5", "%f6", "%f7",
105 "%f8", "%f9", "%f10", "%f11", "%f12", "%f13", "%f14", "%f15"
108 static const HChar vreg_names[32][5] = {
109 "%v0", "%v1", "%v2", "%v3", "%v4", "%v5", "%v6", "%v7",
110 "%v8", "%v9", "%v10", "%v11", "%v12", "%v13", "%v14", "%v15",
111 "%v16", "%v17", "%v18", "%v19", "%v20", "%v21", "%v22", "%v23",
112 "%v24", "%v25", "%v26", "%v27", "%v28", "%v29", "%v30", "%v31"
115 /* Be generic for all virtual regs. */
116 if (hregIsVirtual(reg)) {
117 UInt r = hregIndex(reg);
118 buf[0] = '\0';
119 switch (hregClass(reg)) {
120 case HRcInt64: vex_sprintf(buf, "%%vR%u", r); break;
121 case HRcFlt64: vex_sprintf(buf, "%%vF%u", r); break;
122 case HRcVec128: vex_sprintf(buf, "%%vV%u", r); break;
123 default: goto fail;
125 return buf;
128 /* But specific for real regs. */
129 UInt r = hregNumber(reg);
130 switch (hregClass(reg)) {
131 case HRcInt64: vassert(r < 16); return ireg_names[r];
132 case HRcFlt64: vassert(r < 16); return freg_names[r];
133 case HRcVec128: vassert(r < 32); return vreg_names[r];
134 default: goto fail;
137 fail: vpanic("s390_hreg_as_string");
141 /* Return the real register that holds the guest state pointer */
142 HReg
143 s390_hreg_guest_state_pointer(void)
145 return s390_hreg_gpr(S390_REGNO_GUEST_STATE_POINTER);
148 /* Return the real register that holds the stack pointer */
149 HReg
150 s390_hreg_stack_pointer(void)
152 return s390_hreg_gpr(S390_REGNO_STACK_POINTER);
156 /* Is VALUE within the domain of a 20-bit signed integer. */
157 static __inline__ Bool
158 fits_signed_20bit(Int value)
160 UInt uval = value;
161 return ((Int)(uval << 12) >> 12) == value;
165 /* Is VALUE within the domain of a 12-bit unsigned integer. */
166 static __inline__ Bool
167 fits_unsigned_12bit(Int value)
169 return (value & 0xFFF) == value;
172 /*------------------------------------------------------------*/
173 /*--- Addressing modes (amodes) ---*/
174 /*------------------------------------------------------------*/
176 /* Construct a b12 amode. */
177 s390_amode *
178 s390_amode_b12(Int d, HReg b)
180 s390_amode *am = LibVEX_Alloc_inline(sizeof(s390_amode));
182 vassert(fits_unsigned_12bit(d));
184 am->tag = S390_AMODE_B12;
185 am->d = d;
186 am->b = b;
187 am->x = s390_hreg_gpr(0); /* hregNumber(am->x) == 0 */
189 return am;
193 /* Construct a b20 amode. */
194 s390_amode *
195 s390_amode_b20(Int d, HReg b)
197 s390_amode *am = LibVEX_Alloc_inline(sizeof(s390_amode));
199 vassert(fits_signed_20bit(d));
201 am->tag = S390_AMODE_B20;
202 am->d = d;
203 am->b = b;
204 am->x = s390_hreg_gpr(0); /* hregNumber(am->x) == 0 */
206 return am;
210 /* Construct a bx12 amode. */
211 s390_amode *
212 s390_amode_bx12(Int d, HReg b, HReg x)
214 s390_amode *am = LibVEX_Alloc_inline(sizeof(s390_amode));
216 vassert(fits_unsigned_12bit(d));
217 vassert(hregNumber(b) != 0);
218 vassert(hregNumber(x) != 0);
220 am->tag = S390_AMODE_BX12;
221 am->d = d;
222 am->b = b;
223 am->x = x;
225 return am;
229 /* Construct a bx20 amode. */
230 s390_amode *
231 s390_amode_bx20(Int d, HReg b, HReg x)
233 s390_amode *am = LibVEX_Alloc_inline(sizeof(s390_amode));
235 vassert(fits_signed_20bit(d));
236 vassert(hregNumber(b) != 0);
237 vassert(hregNumber(x) != 0);
239 am->tag = S390_AMODE_BX20;
240 am->d = d;
241 am->b = b;
242 am->x = x;
244 return am;
248 /* Construct an AMODE for accessing the guest state at OFFSET.
249 OFFSET can be at most 3 * sizeof(VexGuestS390XState) + LibVEX_N_SPILL_BYTES
250 which may be too large for a B12 addressing mode.
251 Use a B20 amode as a fallback which will be safe for any offset.
253 s390_amode *
254 s390_amode_for_guest_state(Int offset)
256 if (fits_unsigned_12bit(offset))
257 return s390_amode_b12(offset, s390_hreg_guest_state_pointer());
259 if (fits_signed_20bit(offset))
260 return s390_amode_b20(offset, s390_hreg_guest_state_pointer());
262 vpanic("invalid guest state offset");
266 /* Construct an AMODE for accessing stack pointer at OFFSET.
267 OFFSET can be at most 3 * sizeof(VexGuestS390XState) + LibVEX_N_SPILL_BYTES
268 which may be too large for a B12 addressing mode.
269 Use a B20 amode as a fallback which will be safe for any offset.
271 s390_amode *
272 s390_amode_for_stack_pointer(Int offset)
274 if (fits_unsigned_12bit(offset))
275 return s390_amode_b12(offset, s390_hreg_stack_pointer());
277 if (fits_signed_20bit(offset))
278 return s390_amode_b20(offset, s390_hreg_stack_pointer());
280 vpanic("invalid stack pointer offset");
284 /* Decompile the given amode into a static buffer and return it. */
285 const HChar *
286 s390_amode_as_string(const s390_amode *am)
288 static HChar buf[30];
289 HChar *p;
291 buf[0] = '\0';
292 p = buf;
294 switch (am->tag) {
295 case S390_AMODE_B12:
296 case S390_AMODE_B20:
297 vex_sprintf(p, "%d(%s)", am->d, s390_hreg_as_string(am->b));
298 break;
300 case S390_AMODE_BX12:
301 case S390_AMODE_BX20:
302 /* s390_hreg_as_string returns pointer to local buffer. Need to
303 split this into two printfs */
304 p += vex_sprintf(p, "%d(%s,", am->d, s390_hreg_as_string(am->x));
305 vex_sprintf(p, "%s)", s390_hreg_as_string(am->b));
306 break;
308 default:
309 vpanic("s390_amode_as_string");
312 return buf;
316 /* Helper function for s390_amode_is_sane */
317 static __inline__ Bool
318 is_virtual_gpr(HReg reg)
320 return hregIsVirtual(reg) && hregClass(reg) == HRcInt64;
323 /* Helper function for all vector operations */
324 static UChar
325 s390_getM_from_size(const UChar size) {
326 switch(size) {
327 case 1:
328 return 0;
329 case 2:
330 return 1;
331 case 4:
332 return 2;
333 case 8:
334 return 3;
335 case 16:
336 return 4;
337 default:
338 vex_printf("size=%d\n", size);
339 vpanic("s390_getM_from_size: unknown size");
343 /* Helper for generating RXB field in vector instructions */
344 static UChar
345 s390_update_rxb(const UChar rxb, const UChar index, UChar* vr) {
346 vassert((index >= 1) && (index <= 4));
347 UChar result = rxb;
348 if(vr != NULL) {
349 if(*vr >= 16) {
350 result |= 1 << (4 - index);
351 *vr -= 16;
354 return result;
357 /* Sanity check for an amode */
358 Bool
359 s390_amode_is_sane(const s390_amode *am)
361 switch (am->tag) {
362 case S390_AMODE_B12:
363 return (is_virtual_gpr(am->b) || sameHReg(am->b, s390_hreg_gpr(0))) &&
364 fits_unsigned_12bit(am->d);
366 case S390_AMODE_B20:
367 return is_virtual_gpr(am->b) && fits_signed_20bit(am->d);
369 case S390_AMODE_BX12:
370 return is_virtual_gpr(am->b) && is_virtual_gpr(am->x) &&
371 fits_unsigned_12bit(am->d);
373 case S390_AMODE_BX20:
374 return is_virtual_gpr(am->b) && is_virtual_gpr(am->x) &&
375 fits_signed_20bit(am->d);
377 default:
378 vpanic("s390_amode_is_sane");
382 static Bool
383 s390_amode_is_constant(const s390_amode *am)
385 return am->tag == S390_AMODE_B12 && sameHReg(am->b, s390_hreg_gpr(0));
389 /* Record the register use of an amode */
390 static void
391 s390_amode_get_reg_usage(HRegUsage *u, const s390_amode *am)
393 if (!sameHReg(am->b, s390_hreg_gpr(0)))
394 addHRegUse(u, HRmRead, am->b);
395 if (!sameHReg(am->x, s390_hreg_gpr(0)))
396 addHRegUse(u, HRmRead, am->x);
400 static void
401 s390_amode_map_regs(HRegRemap *m, s390_amode *am)
403 if (!sameHReg(am->b, s390_hreg_gpr(0)))
404 am->b = lookupHRegRemap(m, am->b);
405 if (!sameHReg(am->x, s390_hreg_gpr(0)))
406 am->x = lookupHRegRemap(m, am->x);
410 void
411 ppS390AMode(const s390_amode *am)
413 vex_printf("%s", s390_amode_as_string(am));
416 void
417 ppS390Instr(const s390_insn *insn, Bool mode64)
419 vex_printf("%s", s390_insn_as_string(insn));
422 UInt
423 ppHRegS390(HReg reg)
425 return vex_printf("%s", s390_hreg_as_string(reg));
428 /*------------------------------------------------------------*/
429 /*--- Helpers for register allocation ---*/
430 /*------------------------------------------------------------*/
432 /* Initialise and return the "register universe", i.e. a list of
433 all hardware registers. Called once. */
434 const RRegUniverse *
435 getRRegUniverse_S390(void)
437 static RRegUniverse all_regs;
438 static Bool initialised = False;
439 RRegUniverse *ru = &all_regs;
441 if (LIKELY(initialised))
442 return ru;
444 RRegUniverse__init(ru);
446 /* Assign invalid values to the gpr/vr_index */
447 for (UInt i = 0; i < sizeof gpr_index / sizeof gpr_index[0]; ++i)
448 gpr_index[i] = -1;
449 for (UInt i = 0; i < sizeof vr_index / sizeof vr_index[0]; ++i)
450 vr_index[i] = -1;
453 /* Add the registers that are available to the register allocator.
454 GPRs: registers 6..11 are callee saved, list them first
455 registers 1..5 are caller saved, list them after
456 FPRs: registers 8..15 are callee saved, list them first
457 registers 0..7 are caller saved, list them after
458 FPR12 - FPR15 are also used as register pairs for 128-bit
459 floating point operations
460 VRs: registers 0..31 are available
462 ru->allocable_start[HRcInt64] = ru->size;
463 for (UInt regno = 6; regno <= 11; ++regno) {
464 gpr_index[regno] = ru->size;
465 ru->regs[ru->size++] = s390_hreg_gpr(regno);
467 for (UInt regno = 1; regno <= 5; ++regno) {
468 gpr_index[regno] = ru->size;
469 ru->regs[ru->size++] = s390_hreg_gpr(regno);
471 ru->allocable_end[HRcInt64] = ru->size - 1;
473 ru->allocable_start[HRcFlt64] = ru->size;
474 for (UInt regno = 8; regno <= 15; ++regno) {
475 vr_index[regno] = ru->size;
476 ru->regs[ru->size++] = s390_hreg_fpr(regno);
478 for (UInt regno = 0; regno <= 7; ++regno) {
479 vr_index[regno] = ru->size;
480 ru->regs[ru->size++] = s390_hreg_fpr(regno);
482 ru->allocable_end[HRcFlt64] = ru->size - 1;
484 ru->allocable_start[HRcVec128] = ru->size;
485 for (UInt regno = 16; regno <= 31; ++regno) {
486 vr_index[regno] = ru->size;
487 ru->regs[ru->size++] = s390_hreg_vr(regno);
489 ru->allocable_end[HRcVec128] = ru->size - 1;
490 ru->allocable = ru->size;
492 /* Add the registers that are not available for allocation.
493 r0 -- cannot be used as a base or index register
494 r12 -- scratch register for translation chaining support
495 r13 -- guest state pointer
496 r14 -- link register
497 r15 -- stack pointer
499 UInt other[] = { 0, 12, 13, 14, 15 };
500 for (UInt i = 0; i < sizeof other / sizeof other[0]; ++i) {
501 gpr_index[other[i]] = ru->size;
502 ru->regs[ru->size++] = s390_hreg_gpr(other[i]);
505 /* Sanity checking */
506 for (UInt i = 0; i < sizeof gpr_index / sizeof gpr_index[0]; ++i)
507 vassert(gpr_index[i] >= 0);
508 for (UInt i = 0; i < sizeof vr_index / sizeof vr_index[0]; ++i)
509 vassert(vr_index[i] >= 0);
511 initialised = True;
513 RRegUniverse__check_is_sane(ru);
514 return ru;
517 /* Tell the register allocator how the given instruction uses the registers
518 it refers to. */
519 void
520 getRegUsage_S390Instr(HRegUsage *u, const s390_insn *insn, Bool mode64)
522 s390_insn_get_reg_usage(u, insn);
526 /* Map the registers of the given instruction */
527 void
528 mapRegs_S390Instr(HRegRemap *m, s390_insn *insn, Bool mode64)
530 s390_insn_map_regs(m, insn);
534 /* Generate s390 spill/reload instructions under the direction of the
535 register allocator. Note it's critical these don't write the
536 condition codes. This is like an Ist_Put */
537 void
538 genSpill_S390(HInstr **i1, HInstr **i2, HReg rreg, Int offsetB, Bool mode64)
540 s390_amode *am;
542 vassert(offsetB >= 0);
543 vassert(!hregIsVirtual(rreg));
545 *i1 = *i2 = NULL;
547 am = s390_amode_for_guest_state(offsetB);
549 switch (hregClass(rreg)) {
550 case HRcInt64:
551 case HRcFlt64:
552 *i1 = s390_insn_store(8, am, rreg);
553 return;
554 case HRcVec128:
555 *i1 = s390_insn_store(16, am, rreg);
556 return;
557 default:
558 ppHRegClass(hregClass(rreg));
559 vpanic("genSpill_S390: unimplemented regclass");
564 /* This is like an Iex_Get */
565 void
566 genReload_S390(HInstr **i1, HInstr **i2, HReg rreg, Int offsetB, Bool mode64)
568 s390_amode *am;
570 vassert(offsetB >= 0);
571 vassert(!hregIsVirtual(rreg));
573 *i1 = *i2 = NULL;
575 am = s390_amode_for_guest_state(offsetB);
577 switch (hregClass(rreg)) {
578 case HRcInt64:
579 case HRcFlt64:
580 *i1 = s390_insn_load(8, rreg, am);
581 return;
582 case HRcVec128:
583 *i1 = s390_insn_load(16, rreg, am);
584 return;
585 default:
586 ppHRegClass(hregClass(rreg));
587 vpanic("genReload_S390: unimplemented regclass");
591 /* Direct reload function. For the given vreg (currently located at the given
592 spill offset) and a given instruction that reads vreg exactly once, return a
593 variant of the instruction that references the spill slot directly. Return
594 NULL if no such instruction is found. */
595 HInstr *
596 directReload_S390(HInstr* i, HReg vreg, Short spill_off)
598 s390_insn* insn = (s390_insn *) i;
600 /* For simplicity, reject spill offsets that may cause trouble with 12-bit
601 addressing. They probably shouldn't occur anyway. */
602 if (!fits_unsigned_12bit(spill_off + 15))
603 return NULL;
605 /* In case of a spilled GPR, adjust the offset to be right-aligned within the
606 spill slot. */
607 Int delta = hregClass(vreg) == HRcInt64 ? 8 - insn->size : 0;
608 s390_amode* vreg_am = s390_amode_for_guest_state(spill_off + delta);
609 s390_opnd_RMI vreg_opnd;
610 vreg_opnd.tag = S390_OPND_AMODE;
611 vreg_opnd.variant.am = vreg_am;
613 /* v-move <reg>,<vreg> */
614 if (insn->tag == S390_INSN_MOVE
615 && sameHReg(insn->variant.move.src, vreg)) {
616 return s390_insn_load(insn->size, insn->variant.move.dst, vreg_am);
619 /* v-store <vreg>,<addr> */
620 if (insn->tag == S390_INSN_STORE
621 && sameHReg(insn->variant.store.src, vreg)
622 && insn->variant.store.dst->tag == S390_AMODE_B12) {
623 return s390_insn_memcpy(insn->size, insn->variant.store.dst, vreg_am);
626 /* v-test <vreg> */
627 if (insn->tag == S390_INSN_TEST
628 && insn->variant.test.src.tag == S390_OPND_REG
629 && sameHReg(insn->variant.test.src.variant.reg, vreg)) {
630 return s390_insn_test(insn->size, vreg_opnd);
633 /* v-<alu> <reg>,<vreg> */
634 if (insn->tag == S390_INSN_ALU
635 && insn->variant.alu.op2.tag == S390_OPND_REG
636 && sameHReg(insn->variant.alu.op2.variant.reg, vreg)) {
637 return s390_insn_alu(insn->size, insn->variant.alu.tag,
638 insn->variant.alu.dst, vreg_opnd);
641 /* v-vgetelem <reg>,<vreg> */
642 if (insn->tag == S390_INSN_VEC_AMODEOP
643 && insn->variant.vec_amodeop.tag == S390_VEC_GET_ELEM
644 && insn->size == 8
645 && sameHReg(insn->variant.vec_amodeop.op1, vreg)
646 && s390_amode_is_constant(insn->variant.vec_amodeop.op2)) {
647 vreg_am->d += 8 * insn->variant.vec_amodeop.op2->d;
648 return s390_insn_load(insn->size, insn->variant.vec_amodeop.dst, vreg_am);
651 /* v-<unop> <reg>,<vreg> */
652 if (insn->tag == S390_INSN_UNOP
653 && insn->variant.unop.src.tag == S390_OPND_REG
654 && sameHReg(insn->variant.unop.src.variant.reg, vreg)
655 && hregClass(vreg) == HRcInt64) {
656 /* Some operations define the input size to be different from the insn's
657 `size' field. Adjust the address accordingly. */
658 switch (insn->variant.unop.tag) {
659 case S390_ZERO_EXTEND_8:
660 case S390_SIGN_EXTEND_8: vreg_am->d = spill_off + 7; break;
661 case S390_ZERO_EXTEND_16:
662 case S390_SIGN_EXTEND_16: vreg_am->d = spill_off + 6; break;
663 case S390_ZERO_EXTEND_32:
664 case S390_SIGN_EXTEND_32: vreg_am->d = spill_off + 4; break;
665 case S390_NEGATE: /* Nothing to adjust. */ break;
666 default:
667 goto no_match;
669 return s390_insn_unop(insn->size, insn->variant.unop.tag,
670 insn->variant.unop.dst, vreg_opnd);
673 /* v-vrep <reg>,<vreg>,<idx> */
674 if (insn->tag == S390_INSN_VEC_REPLICATE
675 && sameHReg(insn->variant.vec_replicate.op1, vreg)) {
676 vreg_am->d += insn->size * insn->variant.vec_replicate.idx;
677 return s390_insn_unop(insn->size, S390_VEC_DUPLICATE,
678 insn->variant.vec_replicate.dst, vreg_opnd);
681 no_match:
682 return NULL;
685 s390_insn* genMove_S390(HReg from, HReg to, Bool mode64)
687 switch (hregClass(from)) {
688 case HRcInt64:
689 return s390_insn_move(sizeofIRType(Ity_I64), to, from);
690 case HRcFlt64:
691 return s390_insn_move(sizeofIRType(Ity_F64), to, from);
692 case HRcVec128:
693 return s390_insn_move(sizeofIRType(Ity_V128), to, from);
694 default:
695 ppHRegClass(hregClass(from));
696 vpanic("genMove_S390: unimplemented regclass");
700 /* Helper function for s390_insn_get_reg_usage */
701 static void
702 s390_opnd_RMI_get_reg_usage(HRegUsage *u, s390_opnd_RMI op)
704 switch (op.tag) {
705 case S390_OPND_REG:
706 addHRegUse(u, HRmRead, op.variant.reg);
707 break;
709 case S390_OPND_AMODE:
710 s390_amode_get_reg_usage(u, op.variant.am);
711 break;
713 case S390_OPND_IMMEDIATE:
714 break;
716 default:
717 vpanic("s390_opnd_RMI_get_reg_usage");
722 /* Tell the register allocator how the given insn uses the registers */
723 static void
724 s390_insn_get_reg_usage(HRegUsage *u, const s390_insn *insn)
726 initHRegUsage(u);
728 switch (insn->tag) {
729 case S390_INSN_LOAD:
730 addHRegUse(u, HRmWrite, insn->variant.load.dst);
731 s390_amode_get_reg_usage(u, insn->variant.load.src);
732 break;
734 case S390_INSN_LOAD_IMMEDIATE:
735 addHRegUse(u, HRmWrite, insn->variant.load_immediate.dst);
736 break;
738 case S390_INSN_STORE:
739 addHRegUse(u, HRmRead, insn->variant.store.src);
740 s390_amode_get_reg_usage(u, insn->variant.store.dst);
741 break;
743 case S390_INSN_MOVE:
744 addHRegUse(u, HRmRead, insn->variant.move.src);
745 addHRegUse(u, HRmWrite, insn->variant.move.dst);
747 if (hregClass(insn->variant.move.src) == hregClass(insn->variant.move.dst)) {
748 u->isRegRegMove = True;
749 u->regMoveSrc = insn->variant.move.src;
750 u->regMoveDst = insn->variant.move.dst;
752 break;
754 case S390_INSN_MEMCPY:
755 s390_amode_get_reg_usage(u, insn->variant.memcpy.src);
756 s390_amode_get_reg_usage(u, insn->variant.memcpy.dst);
757 break;
759 case S390_INSN_COND_MOVE:
760 switch (insn->variant.cond_move.cond) {
761 case S390_CC_NEVER:
762 break;
763 case S390_CC_ALWAYS:
764 s390_opnd_RMI_get_reg_usage(u, insn->variant.cond_move.src);
765 addHRegUse(u, HRmWrite, insn->variant.cond_move.dst);
766 break;
767 default:
768 s390_opnd_RMI_get_reg_usage(u, insn->variant.cond_move.src);
769 addHRegUse(u, HRmModify, insn->variant.cond_move.dst);
770 break;
772 break;
774 case S390_INSN_ALU:
775 addHRegUse(u, HRmModify, insn->variant.alu.dst); /* op1 */
776 s390_opnd_RMI_get_reg_usage(u, insn->variant.alu.op2);
777 break;
779 case S390_INSN_SMUL:
780 case S390_INSN_UMUL:
781 addHRegUse(u, HRmModify, insn->variant.mul.dst_lo); /* op1 */
782 addHRegUse(u, HRmWrite, insn->variant.mul.dst_hi);
783 s390_opnd_RMI_get_reg_usage(u, insn->variant.mul.op2);
784 break;
786 case S390_INSN_SDIV:
787 case S390_INSN_UDIV:
788 addHRegUse(u, HRmModify, insn->variant.div.op1_lo);
789 addHRegUse(u, HRmModify, insn->variant.div.op1_hi);
790 s390_opnd_RMI_get_reg_usage(u, insn->variant.div.op2);
791 break;
793 case S390_INSN_DIVS:
794 addHRegUse(u, HRmModify, insn->variant.divs.op1); /* quotient */
795 addHRegUse(u, HRmWrite, insn->variant.divs.rem); /* remainder */
796 s390_opnd_RMI_get_reg_usage(u, insn->variant.divs.op2);
797 break;
799 case S390_INSN_CLZ:
800 addHRegUse(u, HRmWrite, insn->variant.clz.num_bits);
801 addHRegUse(u, HRmWrite, insn->variant.clz.clobber);
802 s390_opnd_RMI_get_reg_usage(u, insn->variant.clz.src);
803 break;
805 case S390_INSN_UNOP:
806 addHRegUse(u, HRmWrite, insn->variant.unop.dst);
807 s390_opnd_RMI_get_reg_usage(u, insn->variant.unop.src);
808 break;
810 case S390_INSN_TEST:
811 s390_opnd_RMI_get_reg_usage(u, insn->variant.test.src);
812 break;
814 case S390_INSN_CC2BOOL:
815 addHRegUse(u, HRmWrite, insn->variant.cc2bool.dst);
816 break;
818 case S390_INSN_CAS:
819 addHRegUse(u, HRmRead, insn->variant.cas.op1);
820 s390_amode_get_reg_usage(u, insn->variant.cas.op2);
821 addHRegUse(u, HRmRead, insn->variant.cas.op3);
822 addHRegUse(u, HRmWrite, insn->variant.cas.old_mem);
823 break;
825 case S390_INSN_CDAS: {
826 s390_cdas *cdas = insn->variant.cdas.details;
828 addHRegUse(u, HRmRead, cdas->op1_high);
829 addHRegUse(u, HRmRead, cdas->op1_low);
830 s390_amode_get_reg_usage(u, cdas->op2);
831 addHRegUse(u, HRmRead, cdas->op3_high);
832 addHRegUse(u, HRmRead, cdas->op3_low);
833 addHRegUse(u, HRmWrite, cdas->old_mem_high);
834 addHRegUse(u, HRmWrite, cdas->old_mem_low);
835 addHRegUse(u, HRmWrite, cdas->scratch);
836 break;
839 case S390_INSN_COMPARE:
840 addHRegUse(u, HRmRead, insn->variant.compare.src1);
841 s390_opnd_RMI_get_reg_usage(u, insn->variant.compare.src2);
842 break;
844 case S390_INSN_HELPER_CALL: {
845 UInt i;
847 /* Assume that all volatile registers are clobbered. ABI says,
848 volatile registers are: r0 - r5. Valgrind's register allocator
849 does not know about r0, so we can leave that out */
850 for (i = 1; i <= 5; ++i) {
851 addHRegUse(u, HRmWrite, s390_hreg_gpr(i));
854 /* Ditto for floating point registers. f0 - f7 are volatile */
855 for (i = 0; i <= 7; ++i) {
856 addHRegUse(u, HRmWrite, s390_hreg_fpr(i));
859 /* Ditto for all allocatable vector registers. */
860 for (i = 16; i <= 31; ++i) {
861 addHRegUse(u, HRmWrite, s390_hreg_vr(i));
864 /* The registers that are used for passing arguments will be read.
865 Not all of them may, but in general we need to assume that. */
866 for (i = 0; i < insn->variant.helper_call.details->num_args; ++i) {
867 addHRegUse(u, HRmRead, s390_hreg_gpr(s390_gprno_from_arg_index(i)));
870 /* s390_insn_helper_call_emit also reads / writes the link register
871 and stack pointer. But those registers are not visible to the
872 register allocator. So we don't need to do anything for them. */
873 break;
876 case S390_INSN_BFP_TRIOP:
877 addHRegUse(u, HRmModify, insn->variant.bfp_triop.dst); /* first */
878 addHRegUse(u, HRmRead, insn->variant.bfp_triop.op2); /* second */
879 addHRegUse(u, HRmRead, insn->variant.bfp_triop.op3); /* third */
880 break;
882 case S390_INSN_BFP_BINOP:
883 addHRegUse(u, HRmModify, insn->variant.bfp_binop.dst_hi); /* left */
884 addHRegUse(u, HRmRead, insn->variant.bfp_binop.op2_hi); /* right */
885 if (insn->size == 16) {
886 addHRegUse(u, HRmModify, insn->variant.bfp_binop.dst_lo); /* left */
887 addHRegUse(u, HRmRead, insn->variant.bfp_binop.op2_lo); /* right */
889 break;
891 case S390_INSN_BFP_UNOP:
892 addHRegUse(u, HRmWrite, insn->variant.bfp_unop.dst_hi);
893 addHRegUse(u, HRmRead, insn->variant.bfp_unop.op_hi); /* operand */
894 if (insn->size == 16) {
895 addHRegUse(u, HRmWrite, insn->variant.bfp_unop.dst_lo);
896 addHRegUse(u, HRmRead, insn->variant.bfp_unop.op_lo); /* operand */
898 break;
900 case S390_INSN_BFP_COMPARE:
901 addHRegUse(u, HRmWrite, insn->variant.bfp_compare.dst);
902 addHRegUse(u, HRmRead, insn->variant.bfp_compare.op1_hi); /* left */
903 addHRegUse(u, HRmRead, insn->variant.bfp_compare.op2_hi); /* right */
904 if (insn->size == 16) {
905 addHRegUse(u, HRmRead, insn->variant.bfp_compare.op1_lo); /* left */
906 addHRegUse(u, HRmRead, insn->variant.bfp_compare.op2_lo); /* right */
908 break;
910 case S390_INSN_BFP_CONVERT:
911 addHRegUse(u, HRmWrite, insn->variant.bfp_convert.dst_hi);
912 if (! hregIsInvalid(insn->variant.bfp_convert.dst_lo))
913 addHRegUse(u, HRmWrite, insn->variant.bfp_convert.dst_lo);
914 addHRegUse(u, HRmRead, insn->variant.bfp_convert.op_hi);
915 if (! hregIsInvalid(insn->variant.bfp_convert.op_lo))
916 addHRegUse(u, HRmRead, insn->variant.bfp_convert.op_lo);
917 break;
919 case S390_INSN_DFP_BINOP: {
920 s390_dfp_binop *dfp_binop = insn->variant.dfp_binop.details;
922 addHRegUse(u, HRmWrite, dfp_binop->dst_hi);
923 addHRegUse(u, HRmRead, dfp_binop->op2_hi); /* left */
924 addHRegUse(u, HRmRead, dfp_binop->op3_hi); /* right */
925 if (insn->size == 16) {
926 addHRegUse(u, HRmWrite, dfp_binop->dst_lo);
927 addHRegUse(u, HRmRead, dfp_binop->op2_lo); /* left */
928 addHRegUse(u, HRmRead, dfp_binop->op3_lo); /* right */
930 break;
933 case S390_INSN_DFP_UNOP:
934 addHRegUse(u, HRmWrite, insn->variant.dfp_unop.dst_hi);
935 addHRegUse(u, HRmRead, insn->variant.dfp_unop.op_hi); /* operand */
936 if (insn->size == 16) {
937 addHRegUse(u, HRmWrite, insn->variant.dfp_unop.dst_lo);
938 addHRegUse(u, HRmRead, insn->variant.dfp_unop.op_lo); /* operand */
940 break;
942 case S390_INSN_DFP_INTOP:
943 addHRegUse(u, HRmWrite, insn->variant.dfp_intop.dst_hi);
944 addHRegUse(u, HRmRead, insn->variant.dfp_intop.op2);
945 addHRegUse(u, HRmRead, insn->variant.dfp_intop.op3_hi);
946 if (insn->size == 16) {
947 addHRegUse(u, HRmWrite, insn->variant.dfp_intop.dst_lo);
948 addHRegUse(u, HRmRead, insn->variant.dfp_intop.op3_lo);
950 break;
952 case S390_INSN_DFP_COMPARE:
953 addHRegUse(u, HRmWrite, insn->variant.dfp_compare.dst);
954 addHRegUse(u, HRmRead, insn->variant.dfp_compare.op1_hi); /* left */
955 addHRegUse(u, HRmRead, insn->variant.dfp_compare.op2_hi); /* right */
956 if (insn->size == 16) {
957 addHRegUse(u, HRmRead, insn->variant.dfp_compare.op1_lo); /* left */
958 addHRegUse(u, HRmRead, insn->variant.dfp_compare.op2_lo); /* right */
960 break;
962 case S390_INSN_DFP_CONVERT:
963 addHRegUse(u, HRmWrite, insn->variant.dfp_convert.dst_hi);
964 if (! hregIsInvalid(insn->variant.dfp_convert.dst_lo))
965 addHRegUse(u, HRmWrite, insn->variant.dfp_convert.dst_lo);
966 addHRegUse(u, HRmRead, insn->variant.dfp_convert.op_hi); /* operand */
967 if (! hregIsInvalid(insn->variant.dfp_convert.op_lo))
968 addHRegUse(u, HRmRead, insn->variant.dfp_convert.op_lo); /* operand */
969 break;
971 case S390_INSN_DFP_REROUND:
972 addHRegUse(u, HRmWrite, insn->variant.dfp_reround.dst_hi);
973 addHRegUse(u, HRmRead, insn->variant.dfp_reround.op2); /* left */
974 addHRegUse(u, HRmRead, insn->variant.dfp_reround.op3_hi); /* right */
975 if (insn->size == 16) {
976 addHRegUse(u, HRmWrite, insn->variant.dfp_reround.dst_lo);
977 addHRegUse(u, HRmRead, insn->variant.dfp_reround.op3_lo); /* right */
979 break;
981 case S390_INSN_FP_CONVERT: {
982 s390_fp_convert *fp_convert = insn->variant.fp_convert.details;
984 addHRegUse(u, HRmWrite, fp_convert->dst_hi);
985 if (! hregIsInvalid(fp_convert->dst_lo))
986 addHRegUse(u, HRmWrite, fp_convert->dst_lo);
987 addHRegUse(u, HRmRead, fp_convert->op_hi);
988 if (! hregIsInvalid(fp_convert->op_lo))
989 addHRegUse(u, HRmRead, fp_convert->op_lo);
990 addHRegUse(u, HRmWrite, fp_convert->r1);
991 break;
994 case S390_INSN_MIMM:
995 s390_amode_get_reg_usage(u, insn->variant.mimm.dst);
996 break;
998 case S390_INSN_MADD:
999 s390_amode_get_reg_usage(u, insn->variant.madd.dst);
1000 break;
1002 case S390_INSN_MFENCE:
1003 break;
1005 case S390_INSN_SET_FPC_BFPRM:
1006 addHRegUse(u, HRmRead, insn->variant.set_fpc_bfprm.mode);
1007 break;
1009 case S390_INSN_SET_FPC_DFPRM:
1010 addHRegUse(u, HRmRead, insn->variant.set_fpc_dfprm.mode);
1011 break;
1013 case S390_INSN_EVCHECK:
1014 s390_amode_get_reg_usage(u, insn->variant.evcheck.counter);
1015 s390_amode_get_reg_usage(u, insn->variant.evcheck.fail_addr);
1016 break;
1018 case S390_INSN_PROFINC:
1019 /* Does not use any register visible to the register allocator */
1020 break;
1022 case S390_INSN_XDIRECT:
1023 s390_amode_get_reg_usage(u, insn->variant.xdirect.guest_IA);
1024 break;
1026 case S390_INSN_XINDIR:
1027 addHRegUse(u, HRmRead, insn->variant.xindir.dst);
1028 s390_amode_get_reg_usage(u, insn->variant.xindir.guest_IA);
1029 break;
1031 case S390_INSN_XASSISTED:
1032 addHRegUse(u, HRmRead, insn->variant.xassisted.dst);
1033 s390_amode_get_reg_usage(u, insn->variant.xassisted.guest_IA);
1034 break;
1036 case S390_INSN_VEC_AMODEOP:
1037 addHRegUse(u, HRmWrite, insn->variant.vec_amodeop.dst);
1038 addHRegUse(u, HRmRead, insn->variant.vec_amodeop.op1);
1039 s390_amode_get_reg_usage(u, insn->variant.vec_amodeop.op2);
1040 break;
1042 case S390_INSN_VEC_AMODEINTOP:
1043 addHRegUse(u, HRmModify, insn->variant.vec_amodeintop.dst);
1044 s390_amode_get_reg_usage(u, insn->variant.vec_amodeintop.op2);
1045 addHRegUse(u, HRmRead, insn->variant.vec_amodeintop.op3);
1046 break;
1048 case S390_INSN_VEC_BINOP:
1049 addHRegUse(u, HRmWrite, insn->variant.vec_binop.dst);
1050 addHRegUse(u, HRmRead, insn->variant.vec_binop.op1);
1051 addHRegUse(u, HRmRead, insn->variant.vec_binop.op2);
1052 break;
1054 case S390_INSN_VEC_TRIOP:
1055 addHRegUse(u, HRmWrite, insn->variant.vec_triop.dst);
1056 addHRegUse(u, HRmRead, insn->variant.vec_triop.op1);
1057 addHRegUse(u, HRmRead, insn->variant.vec_triop.op2);
1058 addHRegUse(u, HRmRead, insn->variant.vec_triop.op3);
1059 break;
1061 case S390_INSN_VEC_REPLICATE:
1062 addHRegUse(u, HRmWrite, insn->variant.vec_replicate.dst);
1063 addHRegUse(u, HRmRead, insn->variant.vec_replicate.op1);
1064 break;
1066 default:
1067 vpanic("s390_insn_get_reg_usage");
1072 /* Helper function for s390_insn_map_regs */
1073 static void
1074 s390_opnd_RMI_map_regs(HRegRemap *m, s390_opnd_RMI *op)
1076 switch (op->tag) {
1077 case S390_OPND_REG:
1078 op->variant.reg = lookupHRegRemap(m, op->variant.reg);
1079 break;
1081 case S390_OPND_IMMEDIATE:
1082 break;
1084 case S390_OPND_AMODE:
1085 s390_amode_map_regs(m, op->variant.am);
1086 break;
1088 default:
1089 vpanic("s390_opnd_RMI_map_regs");
1094 static void
1095 s390_insn_map_regs(HRegRemap *m, s390_insn *insn)
1097 switch (insn->tag) {
1098 case S390_INSN_LOAD:
1099 insn->variant.load.dst = lookupHRegRemap(m, insn->variant.load.dst);
1100 s390_amode_map_regs(m, insn->variant.load.src);
1101 break;
1103 case S390_INSN_STORE:
1104 s390_amode_map_regs(m, insn->variant.store.dst);
1105 insn->variant.store.src = lookupHRegRemap(m, insn->variant.store.src);
1106 break;
1108 case S390_INSN_MOVE:
1109 insn->variant.move.dst = lookupHRegRemap(m, insn->variant.move.dst);
1110 insn->variant.move.src = lookupHRegRemap(m, insn->variant.move.src);
1111 break;
1113 case S390_INSN_MEMCPY:
1114 s390_amode_map_regs(m, insn->variant.memcpy.dst);
1115 s390_amode_map_regs(m, insn->variant.memcpy.src);
1116 break;
1118 case S390_INSN_COND_MOVE:
1119 insn->variant.cond_move.dst = lookupHRegRemap(m, insn->variant.cond_move.dst);
1120 s390_opnd_RMI_map_regs(m, &insn->variant.cond_move.src);
1121 break;
1123 case S390_INSN_LOAD_IMMEDIATE:
1124 insn->variant.load_immediate.dst =
1125 lookupHRegRemap(m, insn->variant.load_immediate.dst);
1126 break;
1128 case S390_INSN_ALU:
1129 insn->variant.alu.dst = lookupHRegRemap(m, insn->variant.alu.dst);
1130 s390_opnd_RMI_map_regs(m, &insn->variant.alu.op2);
1131 break;
1133 case S390_INSN_SMUL:
1134 case S390_INSN_UMUL:
1135 insn->variant.mul.dst_hi = lookupHRegRemap(m, insn->variant.mul.dst_hi);
1136 insn->variant.mul.dst_lo = lookupHRegRemap(m, insn->variant.mul.dst_lo);
1137 s390_opnd_RMI_map_regs(m, &insn->variant.mul.op2);
1138 break;
1140 case S390_INSN_SDIV:
1141 case S390_INSN_UDIV:
1142 insn->variant.div.op1_hi = lookupHRegRemap(m, insn->variant.div.op1_hi);
1143 insn->variant.div.op1_lo = lookupHRegRemap(m, insn->variant.div.op1_lo);
1144 s390_opnd_RMI_map_regs(m, &insn->variant.div.op2);
1145 break;
1147 case S390_INSN_DIVS:
1148 insn->variant.divs.op1 = lookupHRegRemap(m, insn->variant.divs.op1);
1149 insn->variant.divs.rem = lookupHRegRemap(m, insn->variant.divs.rem);
1150 s390_opnd_RMI_map_regs(m, &insn->variant.divs.op2);
1151 break;
1153 case S390_INSN_CLZ:
1154 insn->variant.clz.num_bits = lookupHRegRemap(m, insn->variant.clz.num_bits);
1155 insn->variant.clz.clobber = lookupHRegRemap(m, insn->variant.clz.clobber);
1156 s390_opnd_RMI_map_regs(m, &insn->variant.clz.src);
1157 break;
1159 case S390_INSN_UNOP:
1160 insn->variant.unop.dst = lookupHRegRemap(m, insn->variant.unop.dst);
1161 s390_opnd_RMI_map_regs(m, &insn->variant.unop.src);
1162 break;
1164 case S390_INSN_TEST:
1165 s390_opnd_RMI_map_regs(m, &insn->variant.test.src);
1166 break;
1168 case S390_INSN_CC2BOOL:
1169 insn->variant.cc2bool.dst = lookupHRegRemap(m, insn->variant.cc2bool.dst);
1170 break;
1172 case S390_INSN_CAS:
1173 insn->variant.cas.op1 = lookupHRegRemap(m, insn->variant.cas.op1);
1174 s390_amode_map_regs(m, insn->variant.cas.op2);
1175 insn->variant.cas.op3 = lookupHRegRemap(m, insn->variant.cas.op3);
1176 insn->variant.cas.old_mem = lookupHRegRemap(m, insn->variant.cas.old_mem);
1177 break;
1179 case S390_INSN_CDAS: {
1180 s390_cdas *cdas = insn->variant.cdas.details;
1182 cdas->op1_high = lookupHRegRemap(m, cdas->op1_high);
1183 cdas->op1_low = lookupHRegRemap(m, cdas->op1_low);
1184 s390_amode_map_regs(m, cdas->op2);
1185 cdas->op3_high = lookupHRegRemap(m, cdas->op3_high);
1186 cdas->op3_low = lookupHRegRemap(m, cdas->op3_low);
1187 cdas->old_mem_high = lookupHRegRemap(m, cdas->old_mem_high);
1188 cdas->old_mem_low = lookupHRegRemap(m, cdas->old_mem_low);
1189 cdas->scratch = lookupHRegRemap(m, cdas->scratch);
1190 break;
1193 case S390_INSN_COMPARE:
1194 insn->variant.compare.src1 = lookupHRegRemap(m, insn->variant.compare.src1);
1195 s390_opnd_RMI_map_regs(m, &insn->variant.compare.src2);
1196 break;
1198 case S390_INSN_HELPER_CALL:
1199 /* s390_insn_helper_call_emit also reads / writes the link register
1200 and stack pointer. But those registers are not visible to the
1201 register allocator. So we don't need to do anything for them.
1202 As for the arguments of the helper call -- they will be loaded into
1203 non-virtual registers. Again, we don't need to do anything for those
1204 here. */
1205 break;
1207 case S390_INSN_BFP_TRIOP:
1208 insn->variant.bfp_triop.dst =
1209 lookupHRegRemap(m, insn->variant.bfp_triop.dst);
1210 insn->variant.bfp_triop.op2 =
1211 lookupHRegRemap(m, insn->variant.bfp_triop.op2);
1212 insn->variant.bfp_triop.op3 =
1213 lookupHRegRemap(m, insn->variant.bfp_triop.op3);
1214 break;
1216 case S390_INSN_BFP_BINOP:
1217 insn->variant.bfp_binop.dst_hi =
1218 lookupHRegRemap(m, insn->variant.bfp_binop.dst_hi);
1219 insn->variant.bfp_binop.op2_hi =
1220 lookupHRegRemap(m, insn->variant.bfp_binop.op2_hi);
1221 if (insn->size == 16) {
1222 insn->variant.bfp_binop.dst_lo =
1223 lookupHRegRemap(m, insn->variant.bfp_binop.dst_lo);
1224 insn->variant.bfp_binop.op2_lo =
1225 lookupHRegRemap(m, insn->variant.bfp_binop.op2_lo);
1227 break;
1229 case S390_INSN_BFP_UNOP:
1230 insn->variant.bfp_unop.dst_hi =
1231 lookupHRegRemap(m, insn->variant.bfp_unop.dst_hi);
1232 insn->variant.bfp_unop.op_hi =
1233 lookupHRegRemap(m, insn->variant.bfp_unop.op_hi);
1234 if (insn->size == 16) {
1235 insn->variant.bfp_unop.dst_lo =
1236 lookupHRegRemap(m, insn->variant.bfp_unop.dst_lo);
1237 insn->variant.bfp_unop.op_lo =
1238 lookupHRegRemap(m, insn->variant.bfp_unop.op_lo);
1240 break;
1242 case S390_INSN_BFP_COMPARE:
1243 insn->variant.bfp_compare.dst =
1244 lookupHRegRemap(m, insn->variant.bfp_compare.dst);
1245 insn->variant.bfp_compare.op1_hi =
1246 lookupHRegRemap(m, insn->variant.bfp_compare.op1_hi);
1247 insn->variant.bfp_compare.op2_hi =
1248 lookupHRegRemap(m, insn->variant.bfp_compare.op2_hi);
1249 if (insn->size == 16) {
1250 insn->variant.bfp_compare.op1_lo =
1251 lookupHRegRemap(m, insn->variant.bfp_compare.op1_lo);
1252 insn->variant.bfp_compare.op2_lo =
1253 lookupHRegRemap(m, insn->variant.bfp_compare.op2_lo);
1255 break;
1257 case S390_INSN_BFP_CONVERT:
1258 insn->variant.bfp_convert.dst_hi =
1259 lookupHRegRemap(m, insn->variant.bfp_convert.dst_hi);
1260 if (! hregIsInvalid(insn->variant.bfp_convert.dst_lo))
1261 insn->variant.bfp_convert.dst_lo =
1262 lookupHRegRemap(m, insn->variant.bfp_convert.dst_lo);
1263 insn->variant.bfp_convert.op_hi =
1264 lookupHRegRemap(m, insn->variant.bfp_convert.op_hi);
1265 if (! hregIsInvalid(insn->variant.bfp_convert.op_lo))
1266 insn->variant.bfp_convert.op_lo =
1267 lookupHRegRemap(m, insn->variant.bfp_convert.op_lo);
1268 break;
1270 case S390_INSN_DFP_BINOP: {
1271 s390_dfp_binop *dfp_binop = insn->variant.dfp_binop.details;
1273 dfp_binop->dst_hi = lookupHRegRemap(m, dfp_binop->dst_hi);
1274 dfp_binop->op2_hi = lookupHRegRemap(m, dfp_binop->op2_hi);
1275 dfp_binop->op3_hi = lookupHRegRemap(m, dfp_binop->op3_hi);
1276 if (insn->size == 16) {
1277 dfp_binop->dst_lo = lookupHRegRemap(m, dfp_binop->dst_lo);
1278 dfp_binop->op2_lo = lookupHRegRemap(m, dfp_binop->op2_lo);
1279 dfp_binop->op3_lo = lookupHRegRemap(m, dfp_binop->op3_lo);
1281 break;
1284 case S390_INSN_DFP_UNOP:
1285 insn->variant.dfp_unop.dst_hi =
1286 lookupHRegRemap(m, insn->variant.dfp_unop.dst_hi);
1287 insn->variant.dfp_unop.op_hi =
1288 lookupHRegRemap(m, insn->variant.dfp_unop.op_hi);
1289 if (insn->size == 16) {
1290 insn->variant.dfp_unop.dst_lo =
1291 lookupHRegRemap(m, insn->variant.dfp_unop.dst_lo);
1292 insn->variant.dfp_unop.op_lo =
1293 lookupHRegRemap(m, insn->variant.dfp_unop.op_lo);
1295 break;
1297 case S390_INSN_DFP_INTOP:
1298 insn->variant.dfp_intop.dst_hi =
1299 lookupHRegRemap(m, insn->variant.dfp_intop.dst_hi);
1300 insn->variant.dfp_intop.op2 =
1301 lookupHRegRemap(m, insn->variant.dfp_intop.op2);
1302 insn->variant.dfp_intop.op3_hi =
1303 lookupHRegRemap(m, insn->variant.dfp_intop.op3_hi);
1304 if (insn->size == 16) {
1305 insn->variant.dfp_intop.dst_lo =
1306 lookupHRegRemap(m, insn->variant.dfp_intop.dst_lo);
1307 insn->variant.dfp_intop.op3_lo =
1308 lookupHRegRemap(m, insn->variant.dfp_intop.op3_lo);
1310 break;
1312 case S390_INSN_DFP_COMPARE:
1313 insn->variant.dfp_compare.dst =
1314 lookupHRegRemap(m, insn->variant.dfp_compare.dst);
1315 insn->variant.dfp_compare.op1_hi =
1316 lookupHRegRemap(m, insn->variant.dfp_compare.op1_hi);
1317 insn->variant.dfp_compare.op2_hi =
1318 lookupHRegRemap(m, insn->variant.dfp_compare.op2_hi);
1319 if (insn->size == 16) {
1320 insn->variant.dfp_compare.op1_lo =
1321 lookupHRegRemap(m, insn->variant.dfp_compare.op1_lo);
1322 insn->variant.dfp_compare.op2_lo =
1323 lookupHRegRemap(m, insn->variant.dfp_compare.op2_lo);
1325 break;
1327 case S390_INSN_DFP_CONVERT:
1328 insn->variant.dfp_convert.dst_hi =
1329 lookupHRegRemap(m, insn->variant.dfp_convert.dst_hi);
1330 if (! hregIsInvalid(insn->variant.dfp_convert.dst_lo))
1331 insn->variant.dfp_convert.dst_lo =
1332 lookupHRegRemap(m, insn->variant.dfp_convert.dst_lo);
1333 insn->variant.dfp_convert.op_hi =
1334 lookupHRegRemap(m, insn->variant.dfp_convert.op_hi);
1335 if (! hregIsInvalid(insn->variant.dfp_convert.op_lo))
1336 insn->variant.dfp_convert.op_lo =
1337 lookupHRegRemap(m, insn->variant.dfp_convert.op_lo);
1338 break;
1340 case S390_INSN_DFP_REROUND:
1341 insn->variant.dfp_reround.dst_hi =
1342 lookupHRegRemap(m, insn->variant.dfp_reround.dst_hi);
1343 insn->variant.dfp_reround.op2 =
1344 lookupHRegRemap(m, insn->variant.dfp_reround.op2);
1345 insn->variant.dfp_reround.op3_hi =
1346 lookupHRegRemap(m, insn->variant.dfp_reround.op3_hi);
1347 if (insn->size == 16) {
1348 insn->variant.dfp_reround.dst_lo =
1349 lookupHRegRemap(m, insn->variant.dfp_reround.dst_lo);
1350 insn->variant.dfp_reround.op3_lo =
1351 lookupHRegRemap(m, insn->variant.dfp_reround.op3_lo);
1353 break;
1355 case S390_INSN_FP_CONVERT: {
1356 s390_fp_convert *fp_convert = insn->variant.fp_convert.details;
1358 fp_convert->dst_hi = lookupHRegRemap(m, fp_convert->dst_hi);
1359 if (! hregIsInvalid(fp_convert->dst_lo))
1360 fp_convert->dst_lo = lookupHRegRemap(m, fp_convert->dst_lo);
1361 fp_convert->op_hi = lookupHRegRemap(m, fp_convert->op_hi);
1362 if (! hregIsInvalid(fp_convert->op_lo))
1363 fp_convert->op_lo = lookupHRegRemap(m, fp_convert->op_lo);
1364 fp_convert->r1 = lookupHRegRemap(m, fp_convert->r1);
1365 break;
1368 case S390_INSN_MIMM:
1369 s390_amode_map_regs(m, insn->variant.mimm.dst);
1370 break;
1372 case S390_INSN_MADD:
1373 s390_amode_map_regs(m, insn->variant.madd.dst);
1374 break;
1376 case S390_INSN_MFENCE:
1377 break;
1379 case S390_INSN_SET_FPC_BFPRM:
1380 insn->variant.set_fpc_bfprm.mode =
1381 lookupHRegRemap(m, insn->variant.set_fpc_bfprm.mode);
1382 break;
1384 case S390_INSN_SET_FPC_DFPRM:
1385 insn->variant.set_fpc_dfprm.mode =
1386 lookupHRegRemap(m, insn->variant.set_fpc_dfprm.mode);
1387 break;
1389 case S390_INSN_EVCHECK:
1390 s390_amode_map_regs(m, insn->variant.evcheck.counter);
1391 s390_amode_map_regs(m, insn->variant.evcheck.fail_addr);
1392 break;
1394 case S390_INSN_PROFINC:
1395 /* Does not use any register visible to the register allocator */
1396 break;
1398 case S390_INSN_XDIRECT:
1399 s390_amode_map_regs(m, insn->variant.xdirect.guest_IA);
1400 break;
1402 case S390_INSN_XINDIR:
1403 s390_amode_map_regs(m, insn->variant.xindir.guest_IA);
1404 insn->variant.xindir.dst =
1405 lookupHRegRemap(m, insn->variant.xindir.dst);
1406 break;
1408 case S390_INSN_XASSISTED:
1409 s390_amode_map_regs(m, insn->variant.xassisted.guest_IA);
1410 insn->variant.xassisted.dst =
1411 lookupHRegRemap(m, insn->variant.xassisted.dst);
1412 break;
1414 case S390_INSN_VEC_AMODEOP:
1415 insn->variant.vec_amodeop.dst =
1416 lookupHRegRemap(m, insn->variant.vec_amodeop.dst);
1417 insn->variant.vec_amodeop.op1 =
1418 lookupHRegRemap(m, insn->variant.vec_amodeop.op1);
1419 s390_amode_map_regs(m, insn->variant.vec_amodeop.op2);
1420 break;
1422 case S390_INSN_VEC_AMODEINTOP:
1423 insn->variant.vec_amodeintop.dst =
1424 lookupHRegRemap(m, insn->variant.vec_amodeintop.dst);
1425 s390_amode_map_regs(m, insn->variant.vec_amodeintop.op2);
1426 insn->variant.vec_amodeintop.op3 =
1427 lookupHRegRemap(m, insn->variant.vec_amodeintop.op3);
1428 break;
1430 case S390_INSN_VEC_BINOP:
1431 insn->variant.vec_binop.dst =
1432 lookupHRegRemap(m, insn->variant.vec_binop.dst);
1433 insn->variant.vec_binop.op1 =
1434 lookupHRegRemap(m, insn->variant.vec_binop.op1);
1435 insn->variant.vec_binop.op2 =
1436 lookupHRegRemap(m, insn->variant.vec_binop.op2);
1437 break;
1439 case S390_INSN_VEC_TRIOP:
1440 insn->variant.vec_triop.dst =
1441 lookupHRegRemap(m, insn->variant.vec_triop.dst);
1442 insn->variant.vec_triop.op1 =
1443 lookupHRegRemap(m, insn->variant.vec_triop.op1);
1444 insn->variant.vec_triop.op2 =
1445 lookupHRegRemap(m, insn->variant.vec_triop.op2);
1446 insn->variant.vec_triop.op3 =
1447 lookupHRegRemap(m, insn->variant.vec_triop.op3);
1448 break;
1450 case S390_INSN_VEC_REPLICATE:
1451 insn->variant.vec_replicate.dst =
1452 lookupHRegRemap(m, insn->variant.vec_replicate.dst);
1453 insn->variant.vec_replicate.op1 =
1454 lookupHRegRemap(m, insn->variant.vec_replicate.op1);
1455 break;
1457 default:
1458 vpanic("s390_insn_map_regs");
1463 /*------------------------------------------------------------*/
1464 /*--- Functions to emit a sequence of bytes ---*/
1465 /*------------------------------------------------------------*/
1467 static __inline__ UChar *
1468 emit_2bytes(UChar *p, ULong val)
1470 return (UChar *)__builtin_memcpy(p, ((UChar *)&val) + 6, 2) + 2;
1474 static __inline__ UChar *
1475 emit_4bytes(UChar *p, ULong val)
1477 return (UChar *)__builtin_memcpy(p, ((UChar *)&val) + 4, 4) + 4;
1481 static __inline__ UChar *
1482 emit_6bytes(UChar *p, ULong val)
1484 return (UChar *)__builtin_memcpy(p, ((UChar *)&val) + 2, 6) + 6;
1488 /*------------------------------------------------------------*/
1489 /*--- Functions to emit various instruction formats ---*/
1490 /*------------------------------------------------------------*/
1492 static UChar *
1493 emit_RI(UChar *p, UInt op, UChar r1, UShort i2)
1495 ULong the_insn = op;
1497 the_insn |= ((ULong)r1) << 20;
1498 the_insn |= ((ULong)i2) << 0;
1500 return emit_4bytes(p, the_insn);
1504 static UChar *
1505 emit_RIL(UChar *p, ULong op, UChar r1, UInt i2)
1507 ULong the_insn = op;
1509 the_insn |= ((ULong)r1) << 36;
1510 the_insn |= ((ULong)i2) << 0;
1512 return emit_6bytes(p, the_insn);
1516 static UChar *
1517 emit_RIE(UChar *p, ULong op, UChar r1, UShort i2, UChar m3)
1519 ULong the_insn = op;
1521 the_insn |= ((ULong)r1) << 36;
1522 the_insn |= ((ULong)m3) << 32;
1523 the_insn |= ((ULong)i2) << 16;
1525 return emit_6bytes(p, the_insn);
1529 static UChar *
1530 emit_RIEf(UChar *p, ULong op, UChar r1, UChar r2,
1531 UChar i3, Char i4, UChar i5)
1533 ULong the_insn = op;
1535 the_insn |= ((ULong)r1) << 36;
1536 the_insn |= ((ULong)r2) << 32;
1537 the_insn |= ((ULong)i3) << 24;
1538 the_insn |= ((ULong)i4) << 16;
1539 the_insn |= ((ULong)i5) << 8;
1541 return emit_6bytes(p, the_insn);
1545 static UChar *
1546 emit_RR(UChar *p, UInt op, UChar r1, UChar r2)
1548 ULong the_insn = op;
1550 the_insn |= ((ULong)r1) << 4;
1551 the_insn |= ((ULong)r2) << 0;
1553 return emit_2bytes(p, the_insn);
1557 static UChar *
1558 emit_RRE(UChar *p, UInt op, UChar r1, UChar r2)
1560 ULong the_insn = op;
1562 the_insn |= ((ULong)r1) << 4;
1563 the_insn |= ((ULong)r2) << 0;
1565 return emit_4bytes(p, the_insn);
1569 static UChar *
1570 emit_RRF(UChar *p, UInt op, UChar r1, UChar r3, UChar r2)
1572 ULong the_insn = op;
1574 the_insn |= ((ULong)r1) << 12;
1575 the_insn |= ((ULong)r3) << 4;
1576 the_insn |= ((ULong)r2) << 0;
1578 return emit_4bytes(p, the_insn);
1582 static UChar *
1583 emit_RRF2(UChar *p, UInt op, UChar m3, UChar m4, UChar r1, UChar r2)
1585 ULong the_insn = op;
1587 the_insn |= ((ULong)m3) << 12;
1588 the_insn |= ((ULong)m4) << 8;
1589 the_insn |= ((ULong)r1) << 4;
1590 the_insn |= ((ULong)r2) << 0;
1592 return emit_4bytes(p, the_insn);
1596 static UChar *
1597 emit_RRF3(UChar *p, UInt op, UChar r3, UChar r1, UChar r2)
1599 ULong the_insn = op;
1601 the_insn |= ((ULong)r3) << 12;
1602 the_insn |= ((ULong)r1) << 4;
1603 the_insn |= ((ULong)r2) << 0;
1605 return emit_4bytes(p, the_insn);
1609 static UChar *
1610 emit_RRF4(UChar *p, UInt op, UChar r3, UChar m4, UChar r1, UChar r2)
1612 ULong the_insn = op;
1614 the_insn |= ((ULong)r3) << 12;
1615 the_insn |= ((ULong)m4) << 8;
1616 the_insn |= ((ULong)r1) << 4;
1617 the_insn |= ((ULong)r2) << 0;
1619 return emit_4bytes(p, the_insn);
1623 static UChar *
1624 emit_RRF5(UChar *p, UInt op, UChar m4, UChar r1, UChar r2)
1626 ULong the_insn = op;
1628 the_insn |= ((ULong)m4) << 8;
1629 the_insn |= ((ULong)r1) << 4;
1630 the_insn |= ((ULong)r2) << 0;
1632 return emit_4bytes(p, the_insn);
1636 static UChar *
1637 emit_RS(UChar *p, UInt op, UChar r1, UChar r3, UChar b2, UShort d2)
1639 ULong the_insn = op;
1641 the_insn |= ((ULong)r1) << 20;
1642 the_insn |= ((ULong)r3) << 16;
1643 the_insn |= ((ULong)b2) << 12;
1644 the_insn |= ((ULong)d2) << 0;
1646 return emit_4bytes(p, the_insn);
1650 static UChar *
1651 emit_RSY(UChar *p, ULong op, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
1653 ULong the_insn = op;
1655 the_insn |= ((ULong)r1) << 36;
1656 the_insn |= ((ULong)r3) << 32;
1657 the_insn |= ((ULong)b2) << 28;
1658 the_insn |= ((ULong)dl2) << 16;
1659 the_insn |= ((ULong)dh2) << 8;
1661 return emit_6bytes(p, the_insn);
1665 static UChar *
1666 emit_RX(UChar *p, UInt op, UChar r1, UChar x2, UChar b2, UShort d2)
1668 ULong the_insn = op;
1670 the_insn |= ((ULong)r1) << 20;
1671 the_insn |= ((ULong)x2) << 16;
1672 the_insn |= ((ULong)b2) << 12;
1673 the_insn |= ((ULong)d2) << 0;
1675 return emit_4bytes(p, the_insn);
1679 static UChar *
1680 emit_RXF(UChar *p, ULong op, UChar r3, UChar x2, UChar b2, UShort d2, UChar r1)
1682 ULong the_insn = op;
1684 the_insn |= ((ULong)r3) << 36;
1685 the_insn |= ((ULong)x2) << 32;
1686 the_insn |= ((ULong)b2) << 28;
1687 the_insn |= ((ULong)d2) << 16;
1688 the_insn |= ((ULong)r1) << 12;
1690 return emit_6bytes(p, the_insn);
1694 static UChar *
1695 emit_RXY(UChar *p, ULong op, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1697 ULong the_insn = op;
1699 the_insn |= ((ULong)r1) << 36;
1700 the_insn |= ((ULong)x2) << 32;
1701 the_insn |= ((ULong)b2) << 28;
1702 the_insn |= ((ULong)dl2) << 16;
1703 the_insn |= ((ULong)dh2) << 8;
1705 return emit_6bytes(p, the_insn);
1709 static UChar *
1710 emit_S(UChar *p, UInt op, UChar b2, UShort d2)
1712 ULong the_insn = op;
1714 the_insn |= ((ULong)b2) << 12;
1715 the_insn |= ((ULong)d2) << 0;
1717 return emit_4bytes(p, the_insn);
1721 static UChar *
1722 emit_SI(UChar *p, UInt op, UChar i2, UChar b1, UShort d1)
1724 ULong the_insn = op;
1726 the_insn |= ((ULong)i2) << 16;
1727 the_insn |= ((ULong)b1) << 12;
1728 the_insn |= ((ULong)d1) << 0;
1730 return emit_4bytes(p, the_insn);
1734 static UChar *
1735 emit_SIL(UChar *p, ULong op, UChar b1, UShort d1, UShort i2)
1737 ULong the_insn = op;
1739 the_insn |= ((ULong)b1) << 28;
1740 the_insn |= ((ULong)d1) << 16;
1741 the_insn |= ((ULong)i2) << 0;
1743 return emit_6bytes(p, the_insn);
1747 static UChar *
1748 emit_SIY(UChar *p, ULong op, UChar i2, UChar b1, UShort dl1, UChar dh1)
1750 ULong the_insn = op;
1752 the_insn |= ((ULong)i2) << 32;
1753 the_insn |= ((ULong)b1) << 28;
1754 the_insn |= ((ULong)dl1) << 16;
1755 the_insn |= ((ULong)dh1) << 8;
1757 return emit_6bytes(p, the_insn);
1761 static UChar *
1762 emit_SSa(UChar *p, ULong op, UChar l, UChar b1, UShort d1, UChar b2, UShort d2)
1764 ULong the_insn = op;
1766 the_insn |= ((ULong)l) << 32;
1767 the_insn |= ((ULong)b1) << 28;
1768 the_insn |= ((ULong)d1) << 16;
1769 the_insn |= ((ULong)b2) << 12;
1770 the_insn |= ((ULong)d2) << 0;
1772 return emit_6bytes(p, the_insn);
1776 static UChar *
1777 emit_VRI_VI(UChar *p, ULong op, UChar v1, UShort i2)
1779 ULong the_insn = op;
1780 ULong rxb = s390_update_rxb(0, 1, &v1);
1782 the_insn |= ((ULong)v1) << 36;
1783 the_insn |= ((ULong)i2) << 16;
1784 the_insn |= ((ULong)rxb)<< 8;
1786 return emit_6bytes(p, the_insn);
1790 static UChar *
1791 emit_VRI_VIM(UChar *p, ULong op, UChar v1, UShort i2, UChar m3)
1793 ULong the_insn = op;
1794 ULong rxb = s390_update_rxb(0, 1, &v1);
1796 the_insn |= ((ULong)v1) << 36;
1797 the_insn |= ((ULong)i2) << 16;
1798 the_insn |= ((ULong)m3) << 12;
1799 the_insn |= ((ULong)rxb)<< 8;
1801 return emit_6bytes(p, the_insn);
1805 static UChar *
1806 emit_VRI_VVMM(UChar *p, ULong op, UChar v1, UChar v3, UShort i2, UChar m4)
1808 ULong the_insn = op;
1809 ULong rxb = s390_update_rxb(0, 1, &v1);
1810 rxb = s390_update_rxb(rxb, 2, &v3);
1812 the_insn |= ((ULong)v1) << 36;
1813 the_insn |= ((ULong)v3) << 32;
1814 the_insn |= ((ULong)i2) << 16;
1815 the_insn |= ((ULong)m4) << 12;
1816 the_insn |= ((ULong)rxb) << 8;
1818 return emit_6bytes(p, the_insn);
1822 static UChar *
1823 emit_VRX(UChar *p, ULong op, UChar v1, UChar x2, UChar b2, UShort d2, UChar m3)
1825 ULong the_insn = op;
1826 ULong rxb = s390_update_rxb(0, 1, &v1);
1828 the_insn |= ((ULong)v1) << 36;
1829 the_insn |= ((ULong)x2) << 32;
1830 the_insn |= ((ULong)b2) << 28;
1831 the_insn |= ((ULong)d2) << 16;
1832 the_insn |= ((ULong)m3) << 12;
1833 the_insn |= ((ULong)rxb)<< 8;
1835 return emit_6bytes(p, the_insn);
1839 static UChar *
1840 emit_VRS(UChar *p, ULong op, UChar reg1, UChar b2, UShort d2, UChar reg3, UChar m4)
1842 ULong the_insn = op;
1843 ULong rxb = s390_update_rxb(0, 1, &reg1);
1844 rxb = s390_update_rxb(rxb, 2, &reg3);
1846 the_insn |= ((ULong)reg1) << 36;
1847 the_insn |= ((ULong)reg3) << 32;
1848 the_insn |= ((ULong)b2) << 28;
1849 the_insn |= ((ULong)d2) << 16;
1850 the_insn |= ((ULong)m4) << 12;
1851 the_insn |= ((ULong)rxb) << 8;
1853 return emit_6bytes(p, the_insn);
1857 static UChar *
1858 emit_VRR_VVM(UChar *p, ULong op, UChar v1, UChar v2, UChar m4)
1860 ULong the_insn = op;
1861 ULong rxb = s390_update_rxb(0, 1, &v1);
1862 rxb = s390_update_rxb(rxb, 2, &v2);
1864 the_insn |= ((ULong)v1) << 36;
1865 the_insn |= ((ULong)v2) << 32;
1866 the_insn |= ((ULong)m4) << 12;
1867 the_insn |= ((ULong)rxb)<< 8;
1869 return emit_6bytes(p, the_insn);
1872 static UChar *
1873 emit_VRR_VVMMM(UChar *p, ULong op, UChar v1, UChar v2, UChar m3, UChar m4,
1874 UChar m5)
1876 ULong the_insn = op;
1877 ULong rxb = s390_update_rxb(0, 1, &v1);
1878 rxb = s390_update_rxb(rxb, 2, &v2);
1880 the_insn |= ((ULong)v1) << 36;
1881 the_insn |= ((ULong)v2) << 32;
1882 the_insn |= ((ULong)m5) << 20;
1883 the_insn |= ((ULong)m4) << 16;
1884 the_insn |= ((ULong)m3) << 12;
1885 the_insn |= ((ULong)rxb) << 8;
1887 return emit_6bytes(p, the_insn);
1890 static UChar *
1891 emit_VRR_VVVM(UChar *p, ULong op, UChar v1, UChar v2, UChar v3, UChar m4)
1893 ULong the_insn = op;
1894 ULong rxb = s390_update_rxb(0, 1, &v1);
1895 rxb = s390_update_rxb(rxb, 2, &v2);
1896 rxb = s390_update_rxb(rxb, 3, &v3);
1898 the_insn |= ((ULong)v1) << 36;
1899 the_insn |= ((ULong)v2) << 32;
1900 the_insn |= ((ULong)v3) << 28;
1901 the_insn |= ((ULong)m4) << 12;
1902 the_insn |= ((ULong)rxb)<< 8;
1904 return emit_6bytes(p, the_insn);
1908 static UChar *
1909 emit_VRR_VVV(UChar *p, ULong op, UChar v1, UChar v2, UChar v3)
1911 return emit_VRR_VVVM(p, op, v1, v2, v3, 0);
1915 static UChar *
1916 emit_VRR_VV(UChar *p, ULong op, UChar v1, UChar v2)
1918 return emit_VRR_VVM(p, op, v1, v2, 0);
1922 static UChar *
1923 emit_VRR_VVVV(UChar *p, ULong op, UChar v1, UChar v2, UChar v3, UChar v4)
1925 ULong the_insn = op;
1926 ULong rxb = s390_update_rxb(0, 1, &v1);
1927 rxb = s390_update_rxb(rxb, 2, &v2);
1928 rxb = s390_update_rxb(rxb, 3, &v3);
1929 rxb = s390_update_rxb(rxb, 4, &v4);
1931 the_insn |= ((ULong)v1) << 36;
1932 the_insn |= ((ULong)v2) << 32;
1933 the_insn |= ((ULong)v3) << 28;
1934 the_insn |= ((ULong)v4) << 12;
1935 the_insn |= ((ULong)rxb)<< 8;
1937 return emit_6bytes(p, the_insn);
1940 static UChar *
1941 emit_VRRe_VVVVMM(UChar *p, ULong op, UChar v1, UChar v2, UChar v3, UChar v4,
1942 UChar m5, UChar m6)
1944 ULong the_insn = op;
1945 ULong rxb = s390_update_rxb(0, 1, &v1);
1946 rxb = s390_update_rxb(rxb, 2, &v2);
1947 rxb = s390_update_rxb(rxb, 3, &v3);
1948 rxb = s390_update_rxb(rxb, 4, &v4);
1950 the_insn |= ((ULong)v1) << 36;
1951 the_insn |= ((ULong)v2) << 32;
1952 the_insn |= ((ULong)v3) << 28;
1953 the_insn |= ((ULong)m6) << 24;
1954 the_insn |= ((ULong)m5) << 16;
1955 the_insn |= ((ULong)v4) << 12;
1956 the_insn |= ((ULong)rxb) << 8;
1958 return emit_6bytes(p, the_insn);
1961 static UChar *
1962 emit_VRR_VRR(UChar *p, ULong op, UChar v1, UChar r2, UChar r3)
1964 ULong the_insn = op;
1965 ULong rxb = s390_update_rxb(0, 1, &v1);
1967 the_insn |= ((ULong)v1) << 36;
1968 the_insn |= ((ULong)r2) << 32;
1969 the_insn |= ((ULong)r3) << 28;
1970 the_insn |= ((ULong)rxb)<< 8;
1972 return emit_6bytes(p, the_insn);
1975 static UChar *
1976 emit_VRR_VVVMMM(UChar *p, ULong op, UChar v1, UChar v2, UChar v3, UChar m4,
1977 UChar m5, UChar m6)
1979 ULong the_insn = op;
1980 ULong rxb = s390_update_rxb(0, 1, &v1);
1981 rxb = s390_update_rxb(rxb, 2, &v2);
1982 rxb = s390_update_rxb(rxb, 3, &v3);
1984 the_insn |= ((ULong)v1) << 36;
1985 the_insn |= ((ULong)v2) << 32;
1986 the_insn |= ((ULong)v3) << 28;
1987 the_insn |= ((ULong)m6) << 20;
1988 the_insn |= ((ULong)m5) << 16;
1989 the_insn |= ((ULong)m4) << 12;
1990 the_insn |= ((ULong)rxb) << 8;
1992 return emit_6bytes(p, the_insn);
1995 static UChar*
1996 emit_VRR_VVVMM(UChar *p, ULong op, UChar v1, UChar v2, UChar v3, UChar m4,
1997 UChar m5)
1999 return emit_VRR_VVVMMM(p, op, v1, v2, v3, m4, m5, 0);
2002 /*------------------------------------------------------------*/
2003 /*--- Functions to emit particular instructions ---*/
2004 /*------------------------------------------------------------*/
2006 static UChar *
2007 s390_emit_AR(UChar *p, UChar r1, UChar r2)
2009 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2010 s390_disasm(ENC3(MNM, GPR, GPR), "ar", r1, r2);
2012 return emit_RR(p, 0x1a00, r1, r2);
2016 static UChar *
2017 s390_emit_AGR(UChar *p, UChar r1, UChar r2)
2019 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2020 s390_disasm(ENC3(MNM, GPR, GPR), "agr", r1, r2);
2022 return emit_RRE(p, 0xb9080000, r1, r2);
2026 static UChar *
2027 s390_emit_A(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2029 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2030 s390_disasm(ENC3(MNM, GPR, UDXB), "a", r1, d2, x2, b2);
2032 return emit_RX(p, 0x5a000000, r1, x2, b2, d2);
2036 static UChar *
2037 s390_emit_AY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2039 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2040 s390_disasm(ENC3(MNM, GPR, SDXB), "ay", r1, dh2, dl2, x2, b2);
2042 return emit_RXY(p, 0xe3000000005aULL, r1, x2, b2, dl2, dh2);
2046 static UChar *
2047 s390_emit_AG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2049 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2050 s390_disasm(ENC3(MNM, GPR, SDXB), "ag", r1, dh2, dl2, x2, b2);
2052 return emit_RXY(p, 0xe30000000008ULL, r1, x2, b2, dl2, dh2);
2056 static UChar *
2057 s390_emit_AFI(UChar *p, UChar r1, UInt i2)
2059 vassert(s390_host_has_eimm);
2061 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2062 s390_disasm(ENC3(MNM, GPR, INT), "afi", r1, i2);
2064 return emit_RIL(p, 0xc20900000000ULL, r1, i2);
2068 static UChar *
2069 s390_emit_AGFI(UChar *p, UChar r1, UInt i2)
2071 vassert(s390_host_has_eimm);
2073 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2074 s390_disasm(ENC3(MNM, GPR, INT), "agfi", r1, i2);
2076 return emit_RIL(p, 0xc20800000000ULL, r1, i2);
2080 static UChar *
2081 s390_emit_AH(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2083 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2084 s390_disasm(ENC3(MNM, GPR, UDXB), "ah", r1, d2, x2, b2);
2086 return emit_RX(p, 0x4a000000, r1, x2, b2, d2);
2090 static UChar *
2091 s390_emit_AHY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2093 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2094 s390_disasm(ENC3(MNM, GPR, SDXB), "ahy", r1, dh2, dl2, x2, b2);
2096 return emit_RXY(p, 0xe3000000007aULL, r1, x2, b2, dl2, dh2);
2100 static UChar *
2101 s390_emit_AHI(UChar *p, UChar r1, UShort i2)
2103 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2104 s390_disasm(ENC3(MNM, GPR, INT), "ahi", r1, (Int)(Short)i2);
2106 return emit_RI(p, 0xa70a0000, r1, i2);
2110 static UChar *
2111 s390_emit_AGHI(UChar *p, UChar r1, UShort i2)
2113 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2114 s390_disasm(ENC3(MNM, GPR, INT), "aghi", r1, (Int)(Short)i2);
2116 return emit_RI(p, 0xa70b0000, r1, i2);
2120 static UChar *
2121 s390_emit_AGSI(UChar *p, UChar i2, UChar b1, UShort dl1, UChar dh1)
2123 vassert(s390_host_has_gie);
2125 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2126 s390_disasm(ENC3(MNM, SDXB, INT), "agsi", dh1, dl1, 0, b1, (Int)(Char)i2);
2128 return emit_SIY(p, 0xeb000000007aULL, i2, b1, dl1, dh1);
2132 static UChar *
2133 s390_emit_ASI(UChar *p, UChar i2, UChar b1, UShort dl1, UChar dh1)
2135 vassert(s390_host_has_gie);
2137 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2138 s390_disasm(ENC3(MNM, SDXB, INT), "asi", dh1, dl1, 0, b1, (Int)(Char)i2);
2140 return emit_SIY(p, 0xeb000000006aULL, i2, b1, dl1, dh1);
2144 static UChar *
2145 s390_emit_NR(UChar *p, UChar r1, UChar r2)
2147 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2148 s390_disasm(ENC3(MNM, GPR, GPR), "nr", r1, r2);
2150 return emit_RR(p, 0x1400, r1, r2);
2154 static UChar *
2155 s390_emit_NGR(UChar *p, UChar r1, UChar r2)
2157 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2158 s390_disasm(ENC3(MNM, GPR, GPR), "ngr", r1, r2);
2160 return emit_RRE(p, 0xb9800000, r1, r2);
2164 static UChar *
2165 s390_emit_N(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2167 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2168 s390_disasm(ENC3(MNM, GPR, UDXB), "n", r1, d2, x2, b2);
2170 return emit_RX(p, 0x54000000, r1, x2, b2, d2);
2174 static UChar *
2175 s390_emit_NY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2177 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2178 s390_disasm(ENC3(MNM, GPR, SDXB), "ny", r1, dh2, dl2, x2, b2);
2180 return emit_RXY(p, 0xe30000000054ULL, r1, x2, b2, dl2, dh2);
2184 static UChar *
2185 s390_emit_NG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2187 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2188 s390_disasm(ENC3(MNM, GPR, SDXB), "ng", r1, dh2, dl2, x2, b2);
2190 return emit_RXY(p, 0xe30000000080ULL, r1, x2, b2, dl2, dh2);
2194 static UChar *
2195 s390_emit_NIHF(UChar *p, UChar r1, UInt i2)
2197 vassert(s390_host_has_eimm);
2199 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2200 s390_disasm(ENC3(MNM, GPR, UINT), "nihf", r1, i2);
2202 return emit_RIL(p, 0xc00a00000000ULL, r1, i2);
2206 static UChar *
2207 s390_emit_NILF(UChar *p, UChar r1, UInt i2)
2209 vassert(s390_host_has_eimm);
2211 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2212 s390_disasm(ENC3(MNM, GPR, UINT), "nilf", r1, i2);
2214 return emit_RIL(p, 0xc00b00000000ULL, r1, i2);
2218 static UChar *
2219 s390_emit_NILL(UChar *p, UChar r1, UShort i2)
2221 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2222 s390_disasm(ENC3(MNM, GPR, UINT), "nill", r1, i2);
2224 return emit_RI(p, 0xa5070000, r1, i2);
2228 static UChar *
2229 s390_emit_TM(UChar *p, UChar i2, UChar b1, UShort d1)
2231 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2232 s390_disasm(ENC3(MNM, UDXB, INT), "tm", d1, 0, b1, i2);
2234 return emit_SI(p, 0x91000000, i2, b1, d1);
2238 static UChar *
2239 s390_emit_TMY(UChar *p, UChar i2, UChar b1, UShort dl1, UChar dh1)
2241 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2242 s390_disasm(ENC3(MNM, SDXB, INT), "tmy", dh1, dl1, 0, b1, (Int)(Char)i2);
2244 return emit_SIY(p, 0xeb0000000051ULL, i2, b1, dl1, dh1);
2248 static UChar *
2249 s390_emit_TMLL(UChar *p, UChar r1, UShort i2)
2251 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2252 s390_disasm(ENC3(MNM, GPR, UINT), "tmll", r1, i2);
2254 return emit_RI(p, 0xa7010000, r1, i2);
2258 static UChar *
2259 s390_emit_BASR(UChar *p, UChar r1, UChar r2)
2261 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2262 s390_disasm(ENC3(MNM, GPR, GPR), "basr", r1, r2);
2264 return emit_RR(p, 0x0d00, r1, r2);
2268 static UChar *
2269 s390_emit_BCR(UChar *p, UChar r1, UChar r2)
2271 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2272 s390_disasm(ENC2(XMNM, GPR), S390_XMNM_BCR, r1, r2);
2274 return emit_RR(p, 0x0700, r1, r2);
2278 static UChar *
2279 s390_emit_BRC(UChar *p, UChar r1, UShort i2)
2281 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2282 s390_disasm(ENC2(XMNM, PCREL), S390_XMNM_BRC, r1, (Int)(Short)i2);
2284 return emit_RI(p, 0xa7040000, r1, i2);
2288 static UChar *
2289 s390_emit_BRCL(UChar *p, UChar r1, ULong i2)
2291 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2292 s390_disasm(ENC2(XMNM, PCREL), S390_XMNM_BRCL, r1, i2);
2294 return emit_RIL(p, 0xc00400000000ULL, r1, i2);
2298 static UChar *
2299 s390_emit_CR(UChar *p, UChar r1, UChar r2)
2301 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2302 s390_disasm(ENC3(MNM, GPR, GPR), "cr", r1, r2);
2304 return emit_RR(p, 0x1900, r1, r2);
2308 static UChar *
2309 s390_emit_CGR(UChar *p, UChar r1, UChar r2)
2311 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2312 s390_disasm(ENC3(MNM, GPR, GPR), "cgr", r1, r2);
2314 return emit_RRE(p, 0xb9200000, r1, r2);
2318 static UChar *
2319 s390_emit_C(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2321 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2322 s390_disasm(ENC3(MNM, GPR, UDXB), "c", r1, d2, x2, b2);
2324 return emit_RX(p, 0x59000000, r1, x2, b2, d2);
2328 static UChar *
2329 s390_emit_CY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2331 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2332 s390_disasm(ENC3(MNM, GPR, SDXB), "cy", r1, dh2, dl2, x2, b2);
2334 return emit_RXY(p, 0xe30000000059ULL, r1, x2, b2, dl2, dh2);
2338 static UChar *
2339 s390_emit_CG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2341 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2342 s390_disasm(ENC3(MNM, GPR, SDXB), "cg", r1, dh2, dl2, x2, b2);
2344 return emit_RXY(p, 0xe30000000020ULL, r1, x2, b2, dl2, dh2);
2348 static UChar *
2349 s390_emit_CFI(UChar *p, UChar r1, UInt i2)
2351 vassert(s390_host_has_eimm);
2353 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2354 s390_disasm(ENC3(MNM, GPR, INT), "cfi", r1, i2);
2356 return emit_RIL(p, 0xc20d00000000ULL, r1, i2);
2360 static UChar *
2361 s390_emit_CGFI(UChar *p, UChar r1, UInt i2)
2363 vassert(s390_host_has_eimm);
2365 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2366 s390_disasm(ENC3(MNM, GPR, INT), "cgfi", r1, i2);
2368 return emit_RIL(p, 0xc20c00000000ULL, r1, i2);
2372 static UChar *
2373 s390_emit_CS(UChar *p, UChar r1, UChar r3, UChar b2, UShort d2)
2375 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2376 s390_disasm(ENC4(MNM, GPR, GPR, UDXB), "cs", r1, r3, d2, 0, b2);
2378 return emit_RS(p, 0xba000000, r1, r3, b2, d2);
2382 static UChar *
2383 s390_emit_CSY(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
2385 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2386 s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "csy", r1, r3, dh2, dl2, 0, b2);
2388 return emit_RSY(p, 0xeb0000000014ULL, r1, r3, b2, dl2, dh2);
2392 static UChar *
2393 s390_emit_CSG(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
2395 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2396 s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "csg", r1, r3, dh2, dl2, 0, b2);
2398 return emit_RSY(p, 0xeb0000000030ULL, r1, r3, b2, dl2, dh2);
2402 static UChar *
2403 s390_emit_CDS(UChar *p, UChar r1, UChar r3, UChar b2, UShort d2)
2405 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2406 s390_disasm(ENC4(MNM, GPR, GPR, UDXB), "cds", r1, r3, d2, 0, b2);
2408 return emit_RS(p, 0xbb000000, r1, r3, b2, d2);
2412 static UChar *
2413 s390_emit_CDSY(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
2415 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2416 s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "cdsy", r1, r3, dh2, dl2, 0, b2);
2418 return emit_RSY(p, 0xeb0000000031ULL, r1, r3, b2, dl2, dh2);
2422 static UChar *
2423 s390_emit_CDSG(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
2425 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2426 s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "cdsg", r1, r3, dh2, dl2, 0, b2);
2428 return emit_RSY(p, 0xeb000000003eULL, r1, r3, b2, dl2, dh2);
2432 static UChar *
2433 s390_emit_CLR(UChar *p, UChar r1, UChar r2)
2435 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2436 s390_disasm(ENC3(MNM, GPR, GPR), "clr", r1, r2);
2438 return emit_RR(p, 0x1500, r1, r2);
2442 static UChar *
2443 s390_emit_CLGR(UChar *p, UChar r1, UChar r2)
2445 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2446 s390_disasm(ENC3(MNM, GPR, GPR), "clgr", r1, r2);
2448 return emit_RRE(p, 0xb9210000, r1, r2);
2452 static UChar *
2453 s390_emit_CL(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2455 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2456 s390_disasm(ENC3(MNM, GPR, UDXB), "cl", r1, d2, x2, b2);
2458 return emit_RX(p, 0x55000000, r1, x2, b2, d2);
2462 static UChar *
2463 s390_emit_CLY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2465 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2466 s390_disasm(ENC3(MNM, GPR, SDXB), "cly", r1, dh2, dl2, x2, b2);
2468 return emit_RXY(p, 0xe30000000055ULL, r1, x2, b2, dl2, dh2);
2472 static UChar *
2473 s390_emit_CLG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2475 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2476 s390_disasm(ENC3(MNM, GPR, SDXB), "clg", r1, dh2, dl2, x2, b2);
2478 return emit_RXY(p, 0xe30000000021ULL, r1, x2, b2, dl2, dh2);
2482 static UChar *
2483 s390_emit_CLFI(UChar *p, UChar r1, UInt i2)
2485 vassert(s390_host_has_eimm);
2487 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2488 s390_disasm(ENC3(MNM, GPR, UINT), "clfi", r1, i2);
2490 return emit_RIL(p, 0xc20f00000000ULL, r1, i2);
2494 static UChar *
2495 s390_emit_CLGFI(UChar *p, UChar r1, UInt i2)
2497 vassert(s390_host_has_eimm);
2499 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2500 s390_disasm(ENC3(MNM, GPR, UINT), "clgfi", r1, i2);
2502 return emit_RIL(p, 0xc20e00000000ULL, r1, i2);
2506 static UChar *
2507 s390_emit_DR(UChar *p, UChar r1, UChar r2)
2509 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2510 s390_disasm(ENC3(MNM, GPR, GPR), "dr", r1, r2);
2512 return emit_RR(p, 0x1d00, r1, r2);
2516 static UChar *
2517 s390_emit_D(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2519 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2520 s390_disasm(ENC3(MNM, GPR, UDXB), "d", r1, d2, x2, b2);
2522 return emit_RX(p, 0x5d000000, r1, x2, b2, d2);
2526 static UChar *
2527 s390_emit_DLR(UChar *p, UChar r1, UChar r2)
2529 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2530 s390_disasm(ENC3(MNM, GPR, GPR), "dlr", r1, r2);
2532 return emit_RRE(p, 0xb9970000, r1, r2);
2536 static UChar *
2537 s390_emit_DLGR(UChar *p, UChar r1, UChar r2)
2539 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2540 s390_disasm(ENC3(MNM, GPR, GPR), "dlgr", r1, r2);
2542 return emit_RRE(p, 0xb9870000, r1, r2);
2546 static UChar *
2547 s390_emit_DL(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2549 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2550 s390_disasm(ENC3(MNM, GPR, SDXB), "dl", r1, dh2, dl2, x2, b2);
2552 return emit_RXY(p, 0xe30000000097ULL, r1, x2, b2, dl2, dh2);
2556 static UChar *
2557 s390_emit_DLG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2559 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2560 s390_disasm(ENC3(MNM, GPR, SDXB), "dlg", r1, dh2, dl2, x2, b2);
2562 return emit_RXY(p, 0xe30000000087ULL, r1, x2, b2, dl2, dh2);
2566 static UChar *
2567 s390_emit_DSGR(UChar *p, UChar r1, UChar r2)
2569 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2570 s390_disasm(ENC3(MNM, GPR, GPR), "dsgr", r1, r2);
2572 return emit_RRE(p, 0xb90d0000, r1, r2);
2576 static UChar *
2577 s390_emit_DSG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2579 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2580 s390_disasm(ENC3(MNM, GPR, SDXB), "dsg", r1, dh2, dl2, x2, b2);
2582 return emit_RXY(p, 0xe3000000000dULL, r1, x2, b2, dl2, dh2);
2586 static UChar *
2587 s390_emit_XR(UChar *p, UChar r1, UChar r2)
2589 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2590 s390_disasm(ENC3(MNM, GPR, GPR), "xr", r1, r2);
2592 return emit_RR(p, 0x1700, r1, r2);
2596 static UChar *
2597 s390_emit_XGR(UChar *p, UChar r1, UChar r2)
2599 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2600 s390_disasm(ENC3(MNM, GPR, GPR), "xgr", r1, r2);
2602 return emit_RRE(p, 0xb9820000, r1, r2);
2606 static UChar *
2607 s390_emit_X(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2609 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2610 s390_disasm(ENC3(MNM, GPR, UDXB), "x", r1, d2, x2, b2);
2612 return emit_RX(p, 0x57000000, r1, x2, b2, d2);
2616 static UChar *
2617 s390_emit_XY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2619 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2620 s390_disasm(ENC3(MNM, GPR, SDXB), "xy", r1, dh2, dl2, x2, b2);
2622 return emit_RXY(p, 0xe30000000057ULL, r1, x2, b2, dl2, dh2);
2626 static UChar *
2627 s390_emit_XG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2629 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2630 s390_disasm(ENC3(MNM, GPR, SDXB), "xg", r1, dh2, dl2, x2, b2);
2632 return emit_RXY(p, 0xe30000000082ULL, r1, x2, b2, dl2, dh2);
2636 static UChar *
2637 s390_emit_XIHF(UChar *p, UChar r1, UInt i2)
2639 vassert(s390_host_has_eimm);
2641 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2642 s390_disasm(ENC3(MNM, GPR, UINT), "xihf", r1, i2);
2644 return emit_RIL(p, 0xc00600000000ULL, r1, i2);
2648 static UChar *
2649 s390_emit_XILF(UChar *p, UChar r1, UInt i2)
2651 vassert(s390_host_has_eimm);
2653 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2654 s390_disasm(ENC3(MNM, GPR, UINT), "xilf", r1, i2);
2656 return emit_RIL(p, 0xc00700000000ULL, r1, i2);
2660 static UChar *
2661 s390_emit_XC(UChar *p, UInt l, UChar b1, UShort d1, UChar b2, UShort d2)
2663 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2664 s390_disasm(ENC3(MNM, UDLB, UDXB), "xc", d1, l, b1, d2, 0, b2);
2666 return emit_SSa(p, 0xd70000000000ULL, l, b1, d1, b2, d2);
2670 static UChar *
2671 s390_emit_FLOGR(UChar *p, UChar r1, UChar r2)
2673 vassert(s390_host_has_eimm);
2675 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2676 s390_disasm(ENC3(MNM, GPR, GPR), "flogr", r1, r2);
2678 return emit_RRE(p, 0xb9830000, r1, r2);
2682 static UChar *
2683 s390_emit_IC(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2685 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2686 s390_disasm(ENC3(MNM, GPR, UDXB), "ic", r1, d2, x2, b2);
2688 return emit_RX(p, 0x43000000, r1, x2, b2, d2);
2692 static UChar *
2693 s390_emit_ICY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2695 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2696 s390_disasm(ENC3(MNM, GPR, SDXB), "icy", r1, dh2, dl2, x2, b2);
2698 return emit_RXY(p, 0xe30000000073ULL, r1, x2, b2, dl2, dh2);
2702 static UChar *
2703 s390_emit_IIHF(UChar *p, UChar r1, UInt i2)
2705 vassert(s390_host_has_eimm);
2707 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2708 s390_disasm(ENC3(MNM, GPR, UINT), "iihf", r1, i2);
2710 return emit_RIL(p, 0xc00800000000ULL, r1, i2);
2714 static UChar *
2715 s390_emit_IIHH(UChar *p, UChar r1, UShort i2)
2717 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2718 s390_disasm(ENC3(MNM, GPR, UINT), "iihh", r1, i2);
2720 return emit_RI(p, 0xa5000000, r1, i2);
2724 static UChar *
2725 s390_emit_IIHL(UChar *p, UChar r1, UShort i2)
2727 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2728 s390_disasm(ENC3(MNM, GPR, UINT), "iihl", r1, i2);
2730 return emit_RI(p, 0xa5010000, r1, i2);
2734 static UChar *
2735 s390_emit_IILF(UChar *p, UChar r1, UInt i2)
2737 vassert(s390_host_has_eimm);
2739 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2740 s390_disasm(ENC3(MNM, GPR, UINT), "iilf", r1, i2);
2742 return emit_RIL(p, 0xc00900000000ULL, r1, i2);
2746 static UChar *
2747 s390_emit_IILH(UChar *p, UChar r1, UShort i2)
2749 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2750 s390_disasm(ENC3(MNM, GPR, UINT), "iilh", r1, i2);
2752 return emit_RI(p, 0xa5020000, r1, i2);
2756 static UChar *
2757 s390_emit_IILL(UChar *p, UChar r1, UShort i2)
2759 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2760 s390_disasm(ENC3(MNM, GPR, UINT), "iill", r1, i2);
2762 return emit_RI(p, 0xa5030000, r1, i2);
2766 static UChar *
2767 s390_emit_IPM(UChar *p, UChar r1, UChar r2)
2769 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2770 s390_disasm(ENC2(MNM, GPR), "ipm", r1);
2772 return emit_RRE(p, 0xb2220000, r1, r2);
2776 static UChar *
2777 s390_emit_LR(UChar *p, UChar r1, UChar r2)
2779 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2780 s390_disasm(ENC3(MNM, GPR, GPR), "lr", r1, r2);
2782 return emit_RR(p, 0x1800, r1, r2);
2786 static UChar *
2787 s390_emit_LGR(UChar *p, UChar r1, UChar r2)
2789 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2790 s390_disasm(ENC3(MNM, GPR, GPR), "lgr", r1, r2);
2792 return emit_RRE(p, 0xb9040000, r1, r2);
2796 static UChar *
2797 s390_emit_LGFR(UChar *p, UChar r1, UChar r2)
2799 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2800 s390_disasm(ENC3(MNM, GPR, GPR), "lgfr", r1, r2);
2802 return emit_RRE(p, 0xb9140000, r1, r2);
2806 static UChar *
2807 s390_emit_L(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2809 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2810 s390_disasm(ENC3(MNM, GPR, UDXB), "l", r1, d2, x2, b2);
2812 return emit_RX(p, 0x58000000, r1, x2, b2, d2);
2816 static UChar *
2817 s390_emit_LY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2819 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2820 s390_disasm(ENC3(MNM, GPR, SDXB), "ly", r1, dh2, dl2, x2, b2);
2822 return emit_RXY(p, 0xe30000000058ULL, r1, x2, b2, dl2, dh2);
2826 static UChar *
2827 s390_emit_LG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2829 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2830 s390_disasm(ENC3(MNM, GPR, SDXB), "lg", r1, dh2, dl2, x2, b2);
2832 return emit_RXY(p, 0xe30000000004ULL, r1, x2, b2, dl2, dh2);
2836 static UChar *
2837 s390_emit_LGF(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2839 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2840 s390_disasm(ENC3(MNM, GPR, SDXB), "lgf", r1, dh2, dl2, x2, b2);
2842 return emit_RXY(p, 0xe30000000014ULL, r1, x2, b2, dl2, dh2);
2846 static UChar *
2847 s390_emit_LGFI(UChar *p, UChar r1, UInt i2)
2849 vassert(s390_host_has_eimm);
2851 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2852 s390_disasm(ENC3(MNM, GPR, INT), "lgfi", r1, i2);
2854 return emit_RIL(p, 0xc00100000000ULL, r1, i2);
2858 static UChar *
2859 s390_emit_LTR(UChar *p, UChar r1, UChar r2)
2861 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2862 s390_disasm(ENC3(MNM, GPR, GPR), "ltr", r1, r2);
2864 return emit_RR(p, 0x1200, r1, r2);
2868 static UChar *
2869 s390_emit_LTGR(UChar *p, UChar r1, UChar r2)
2871 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2872 s390_disasm(ENC3(MNM, GPR, GPR), "ltgr", r1, r2);
2874 return emit_RRE(p, 0xb9020000, r1, r2);
2878 static UChar *
2879 s390_emit_LT(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2881 vassert(s390_host_has_eimm);
2883 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2884 s390_disasm(ENC3(MNM, GPR, SDXB), "lt", r1, dh2, dl2, x2, b2);
2886 return emit_RXY(p, 0xe30000000012ULL, r1, x2, b2, dl2, dh2);
2890 static UChar *
2891 s390_emit_LTG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2893 vassert(s390_host_has_eimm);
2895 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2896 s390_disasm(ENC3(MNM, GPR, SDXB), "ltg", r1, dh2, dl2, x2, b2);
2898 return emit_RXY(p, 0xe30000000002ULL, r1, x2, b2, dl2, dh2);
2902 static UChar *
2903 s390_emit_LBR(UChar *p, UChar r1, UChar r2)
2905 vassert(s390_host_has_eimm);
2907 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2908 s390_disasm(ENC3(MNM, GPR, GPR), "lbr", r1, r2);
2910 return emit_RRE(p, 0xb9260000, r1, r2);
2914 static UChar *
2915 s390_emit_LGBR(UChar *p, UChar r1, UChar r2)
2917 vassert(s390_host_has_eimm);
2919 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2920 s390_disasm(ENC3(MNM, GPR, GPR), "lgbr", r1, r2);
2922 return emit_RRE(p, 0xb9060000, r1, r2);
2926 static UChar *
2927 s390_emit_LB(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2929 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2930 s390_disasm(ENC3(MNM, GPR, SDXB), "lb", r1, dh2, dl2, x2, b2);
2932 return emit_RXY(p, 0xe30000000076ULL, r1, x2, b2, dl2, dh2);
2936 static UChar *
2937 s390_emit_LGB(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2939 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2940 s390_disasm(ENC3(MNM, GPR, SDXB), "lgb", r1, dh2, dl2, x2, b2);
2942 return emit_RXY(p, 0xe30000000077ULL, r1, x2, b2, dl2, dh2);
2946 static UChar *
2947 s390_emit_LCR(UChar *p, UChar r1, UChar r2)
2949 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2950 s390_disasm(ENC3(MNM, GPR, GPR), "lcr", r1, r2);
2952 return emit_RR(p, 0x1300, r1, r2);
2956 static UChar *
2957 s390_emit_LCGR(UChar *p, UChar r1, UChar r2)
2959 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2960 s390_disasm(ENC3(MNM, GPR, GPR), "lcgr", r1, r2);
2962 return emit_RRE(p, 0xb9030000, r1, r2);
2966 static UChar *
2967 s390_emit_LHR(UChar *p, UChar r1, UChar r2)
2969 vassert(s390_host_has_eimm);
2971 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2972 s390_disasm(ENC3(MNM, GPR, GPR), "lhr", r1, r2);
2974 return emit_RRE(p, 0xb9270000, r1, r2);
2978 static UChar *
2979 s390_emit_LGHR(UChar *p, UChar r1, UChar r2)
2981 vassert(s390_host_has_eimm);
2983 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2984 s390_disasm(ENC3(MNM, GPR, GPR), "lghr", r1, r2);
2986 return emit_RRE(p, 0xb9070000, r1, r2);
2990 static UChar *
2991 s390_emit_LH(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2993 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2994 s390_disasm(ENC3(MNM, GPR, UDXB), "lh", r1, d2, x2, b2);
2996 return emit_RX(p, 0x48000000, r1, x2, b2, d2);
3000 static UChar *
3001 s390_emit_LHY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3003 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3004 s390_disasm(ENC3(MNM, GPR, SDXB), "lhy", r1, dh2, dl2, x2, b2);
3006 return emit_RXY(p, 0xe30000000078ULL, r1, x2, b2, dl2, dh2);
3010 static UChar *
3011 s390_emit_LGH(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3013 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3014 s390_disasm(ENC3(MNM, GPR, SDXB), "lgh", r1, dh2, dl2, x2, b2);
3016 return emit_RXY(p, 0xe30000000015ULL, r1, x2, b2, dl2, dh2);
3020 static UChar *
3021 s390_emit_LHI(UChar *p, UChar r1, UShort i2)
3023 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3024 s390_disasm(ENC3(MNM, GPR, INT), "lhi", r1, (Int)(Short)i2);
3026 return emit_RI(p, 0xa7080000, r1, i2);
3030 static UChar *
3031 s390_emit_LGHI(UChar *p, UChar r1, UShort i2)
3033 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3034 s390_disasm(ENC3(MNM, GPR, INT), "lghi", r1, (Int)(Short)i2);
3036 return emit_RI(p, 0xa7090000, r1, i2);
3040 static UChar *
3041 s390_emit_LLGFR(UChar *p, UChar r1, UChar r2)
3043 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3044 s390_disasm(ENC3(MNM, GPR, GPR), "llgfr", r1, r2);
3046 return emit_RRE(p, 0xb9160000, r1, r2);
3050 static UChar *
3051 s390_emit_LLGF(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3053 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3054 s390_disasm(ENC3(MNM, GPR, SDXB), "llgf", r1, dh2, dl2, x2, b2);
3056 return emit_RXY(p, 0xe30000000016ULL, r1, x2, b2, dl2, dh2);
3060 static UChar *
3061 s390_emit_LLCR(UChar *p, UChar r1, UChar r2)
3063 vassert(s390_host_has_eimm);
3065 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3066 s390_disasm(ENC3(MNM, GPR, GPR), "llcr", r1, r2);
3068 return emit_RRE(p, 0xb9940000, r1, r2);
3072 static UChar *
3073 s390_emit_LLGCR(UChar *p, UChar r1, UChar r2)
3075 vassert(s390_host_has_eimm);
3077 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3078 s390_disasm(ENC3(MNM, GPR, GPR), "llgcr", r1, r2);
3080 return emit_RRE(p, 0xb9840000, r1, r2);
3084 static UChar *
3085 s390_emit_LLC(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3087 vassert(s390_host_has_eimm);
3089 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3090 s390_disasm(ENC3(MNM, GPR, SDXB), "llc", r1, dh2, dl2, x2, b2);
3092 return emit_RXY(p, 0xe30000000094ULL, r1, x2, b2, dl2, dh2);
3096 static UChar *
3097 s390_emit_LLGC(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3099 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3100 s390_disasm(ENC3(MNM, GPR, SDXB), "llgc", r1, dh2, dl2, x2, b2);
3102 return emit_RXY(p, 0xe30000000090ULL, r1, x2, b2, dl2, dh2);
3106 static UChar *
3107 s390_emit_LLHR(UChar *p, UChar r1, UChar r2)
3109 vassert(s390_host_has_eimm);
3111 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3112 s390_disasm(ENC3(MNM, GPR, GPR), "llhr", r1, r2);
3114 return emit_RRE(p, 0xb9950000, r1, r2);
3118 static UChar *
3119 s390_emit_LLGHR(UChar *p, UChar r1, UChar r2)
3121 vassert(s390_host_has_eimm);
3123 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3124 s390_disasm(ENC3(MNM, GPR, GPR), "llghr", r1, r2);
3126 return emit_RRE(p, 0xb9850000, r1, r2);
3130 static UChar *
3131 s390_emit_LLH(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3133 vassert(s390_host_has_eimm);
3135 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3136 s390_disasm(ENC3(MNM, GPR, SDXB), "llh", r1, dh2, dl2, x2, b2);
3138 return emit_RXY(p, 0xe30000000095ULL, r1, x2, b2, dl2, dh2);
3142 static UChar *
3143 s390_emit_LLGH(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3145 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3146 s390_disasm(ENC3(MNM, GPR, SDXB), "llgh", r1, dh2, dl2, x2, b2);
3148 return emit_RXY(p, 0xe30000000091ULL, r1, x2, b2, dl2, dh2);
3152 static UChar *
3153 s390_emit_LLILF(UChar *p, UChar r1, UInt i2)
3155 vassert(s390_host_has_eimm);
3157 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3158 s390_disasm(ENC3(MNM, GPR, UINT), "llilf", r1, i2);
3160 return emit_RIL(p, 0xc00f00000000ULL, r1, i2);
3164 static UChar *
3165 s390_emit_LLILH(UChar *p, UChar r1, UShort i2)
3167 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3168 s390_disasm(ENC3(MNM, GPR, UINT), "llilh", r1, i2);
3170 return emit_RI(p, 0xa50e0000, r1, i2);
3174 static UChar *
3175 s390_emit_LLILL(UChar *p, UChar r1, UShort i2)
3177 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3178 s390_disasm(ENC3(MNM, GPR, UINT), "llill", r1, i2);
3180 return emit_RI(p, 0xa50f0000, r1, i2);
3184 static UChar *
3185 s390_emit_MR(UChar *p, UChar r1, UChar r2)
3187 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3188 s390_disasm(ENC3(MNM, GPR, GPR), "mr", r1, r2);
3190 return emit_RR(p, 0x1c00, r1, r2);
3194 static UChar *
3195 s390_emit_M(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
3197 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3198 s390_disasm(ENC3(MNM, GPR, UDXB), "m", r1, d2, x2, b2);
3200 return emit_RX(p, 0x5c000000, r1, x2, b2, d2);
3204 static UChar *
3205 s390_emit_MFY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3207 vassert(s390_host_has_gie);
3209 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3210 s390_disasm(ENC3(MNM, GPR, SDXB), "mfy", r1, dh2, dl2, x2, b2);
3212 return emit_RXY(p, 0xe3000000005cULL, r1, x2, b2, dl2, dh2);
3216 static UChar *
3217 s390_emit_MG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3219 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3220 s390_disasm(ENC3(MNM, GPR, SDXB), "mg", r1, dh2, dl2, x2, b2);
3222 return emit_RXY(p, 0xe30000000084ULL, r1, x2, b2, dl2, dh2);
3226 static UChar *
3227 s390_emit_MGRK(UChar *p, UChar r3, UChar r1, UChar r2)
3229 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3230 s390_disasm(ENC4(MNM, GPR, GPR, GPR), "mgrk", r1, r2, r3);
3232 return emit_RRF3(p, 0xb9ec0000, r3, r1, r2);
3236 static UChar *
3237 s390_emit_MH(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
3239 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3240 s390_disasm(ENC3(MNM, GPR, UDXB), "mh", r1, d2, x2, b2);
3242 return emit_RX(p, 0x4c000000, r1, x2, b2, d2);
3246 static UChar *
3247 s390_emit_MHY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3249 vassert(s390_host_has_gie);
3251 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3252 s390_disasm(ENC3(MNM, GPR, SDXB), "mhy", r1, dh2, dl2, x2, b2);
3254 return emit_RXY(p, 0xe3000000007cULL, r1, x2, b2, dl2, dh2);
3258 static UChar *
3259 s390_emit_MHI(UChar *p, UChar r1, UShort i2)
3261 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3262 s390_disasm(ENC3(MNM, GPR, INT), "mhi", r1, (Int)(Short)i2);
3264 return emit_RI(p, 0xa70c0000, r1, i2);
3268 static UChar *
3269 s390_emit_MLR(UChar *p, UChar r1, UChar r2)
3271 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3272 s390_disasm(ENC3(MNM, GPR, GPR), "mlr", r1, r2);
3274 return emit_RRE(p, 0xb9960000, r1, r2);
3278 static UChar *
3279 s390_emit_MLGR(UChar *p, UChar r1, UChar r2)
3281 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3282 s390_disasm(ENC3(MNM, GPR, GPR), "mlgr", r1, r2);
3284 return emit_RRE(p, 0xb9860000, r1, r2);
3288 static UChar *
3289 s390_emit_ML(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3291 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3292 s390_disasm(ENC3(MNM, GPR, SDXB), "ml", r1, dh2, dl2, x2, b2);
3294 return emit_RXY(p, 0xe30000000096ULL, r1, x2, b2, dl2, dh2);
3298 static UChar *
3299 s390_emit_MLG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3301 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3302 s390_disasm(ENC3(MNM, GPR, SDXB), "mlg", r1, dh2, dl2, x2, b2);
3304 return emit_RXY(p, 0xe30000000086ULL, r1, x2, b2, dl2, dh2);
3308 static UChar *
3309 s390_emit_MSR(UChar *p, UChar r1, UChar r2)
3311 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3312 s390_disasm(ENC3(MNM, GPR, GPR), "msr", r1, r2);
3314 return emit_RRE(p, 0xb2520000, r1, r2);
3318 static UChar *
3319 s390_emit_MSGR(UChar *p, UChar r1, UChar r2)
3321 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3322 s390_disasm(ENC3(MNM, GPR, GPR), "msgr", r1, r2);
3324 return emit_RRE(p, 0xb90c0000, r1, r2);
3328 static UChar *
3329 s390_emit_MS(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
3331 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3332 s390_disasm(ENC3(MNM, GPR, UDXB), "ms", r1, d2, x2, b2);
3334 return emit_RX(p, 0x71000000, r1, x2, b2, d2);
3338 static UChar *
3339 s390_emit_MSY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3341 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3342 s390_disasm(ENC3(MNM, GPR, SDXB), "msy", r1, dh2, dl2, x2, b2);
3344 return emit_RXY(p, 0xe30000000051ULL, r1, x2, b2, dl2, dh2);
3348 static UChar *
3349 s390_emit_MSG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3351 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3352 s390_disasm(ENC3(MNM, GPR, SDXB), "msg", r1, dh2, dl2, x2, b2);
3354 return emit_RXY(p, 0xe3000000000cULL, r1, x2, b2, dl2, dh2);
3358 static UChar *
3359 s390_emit_MSFI(UChar *p, UChar r1, UInt i2)
3361 vassert(s390_host_has_gie);
3363 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3364 s390_disasm(ENC3(MNM, GPR, INT), "msfi", r1, i2);
3366 return emit_RIL(p, 0xc20100000000ULL, r1, i2);
3370 static UChar *
3371 s390_emit_MSGFI(UChar *p, UChar r1, UInt i2)
3373 vassert(s390_host_has_gie);
3375 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3376 s390_disasm(ENC3(MNM, GPR, INT), "msgfi", r1, i2);
3378 return emit_RIL(p, 0xc20000000000ULL, r1, i2);
3382 static UChar *
3383 s390_emit_MVC(UChar *p, UInt l, UChar b1, UShort d1, UChar b2, UShort d2)
3385 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3386 s390_disasm(ENC3(MNM, UDLB, UDXB), "mvc", d1, l, b1, d2, 0, b2);
3388 return emit_SSa(p, 0xd20000000000ULL, l, b1, d1, b2, d2);
3392 static UChar *
3393 s390_emit_MVI(UChar *p, UChar i2, UChar b1, UShort d1)
3395 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3396 s390_disasm(ENC3(MNM, UDXB, INT), "mvi", d1, 0, b1, i2);
3398 return emit_SI(p, 0x92000000, i2, b1, d1);
3402 static UChar *
3403 s390_emit_MVHHI(UChar *p, UChar b1, UShort d1, UShort i2)
3405 vassert(s390_host_has_gie);
3407 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3408 s390_disasm(ENC3(MNM, UDXB, INT), "mvhhi", d1, 0, b1, i2);
3410 return emit_SIL(p, 0xe54400000000ULL, b1, d1, i2);
3414 static UChar *
3415 s390_emit_MVHI(UChar *p, UChar b1, UShort d1, UShort i2)
3417 vassert(s390_host_has_gie);
3419 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3420 s390_disasm(ENC3(MNM, UDXB, INT), "mvhi", d1, 0, b1, i2);
3422 return emit_SIL(p, 0xe54c00000000ULL, b1, d1, i2);
3426 static UChar *
3427 s390_emit_MVGHI(UChar *p, UChar b1, UShort d1, UShort i2)
3429 vassert(s390_host_has_gie);
3431 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3432 s390_disasm(ENC3(MNM, UDXB, INT), "mvghi", d1, 0, b1, i2);
3434 return emit_SIL(p, 0xe54800000000ULL, b1, d1, i2);
3438 static UChar *
3439 s390_emit_OR(UChar *p, UChar r1, UChar r2)
3441 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3442 s390_disasm(ENC3(MNM, GPR, GPR), "or", r1, r2);
3444 return emit_RR(p, 0x1600, r1, r2);
3448 static UChar *
3449 s390_emit_OGR(UChar *p, UChar r1, UChar r2)
3451 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3452 s390_disasm(ENC3(MNM, GPR, GPR), "ogr", r1, r2);
3454 return emit_RRE(p, 0xb9810000, r1, r2);
3458 static UChar *
3459 s390_emit_O(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
3461 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3462 s390_disasm(ENC3(MNM, GPR, UDXB), "o", r1, d2, x2, b2);
3464 return emit_RX(p, 0x56000000, r1, x2, b2, d2);
3468 static UChar *
3469 s390_emit_OY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3471 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3472 s390_disasm(ENC3(MNM, GPR, SDXB), "oy", r1, dh2, dl2, x2, b2);
3474 return emit_RXY(p, 0xe30000000056ULL, r1, x2, b2, dl2, dh2);
3478 static UChar *
3479 s390_emit_OG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3481 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3482 s390_disasm(ENC3(MNM, GPR, SDXB), "og", r1, dh2, dl2, x2, b2);
3484 return emit_RXY(p, 0xe30000000081ULL, r1, x2, b2, dl2, dh2);
3488 static UChar *
3489 s390_emit_OIHF(UChar *p, UChar r1, UInt i2)
3491 vassert(s390_host_has_eimm);
3493 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3494 s390_disasm(ENC3(MNM, GPR, UINT), "oihf", r1, i2);
3496 return emit_RIL(p, 0xc00c00000000ULL, r1, i2);
3500 static UChar *
3501 s390_emit_OILF(UChar *p, UChar r1, UInt i2)
3503 vassert(s390_host_has_eimm);
3505 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3506 s390_disasm(ENC3(MNM, GPR, UINT), "oilf", r1, i2);
3508 return emit_RIL(p, 0xc00d00000000ULL, r1, i2);
3512 static UChar *
3513 s390_emit_OILL(UChar *p, UChar r1, UShort i2)
3515 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3516 s390_disasm(ENC3(MNM, GPR, UINT), "oill", r1, i2);
3518 return emit_RI(p, 0xa50b0000, r1, i2);
3522 static UChar *
3523 s390_emit_SLL(UChar *p, UChar r1, UChar b2, UShort d2)
3525 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3526 s390_disasm(ENC3(MNM, GPR, UDXB), "sll", r1, d2, 0, b2);
3528 return emit_RS(p, 0x89000000, r1, 0, b2, d2);
3532 static UChar *
3533 s390_emit_SLLG(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
3535 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3536 s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "sllg", r1, r3, dh2, dl2, 0, b2);
3538 return emit_RSY(p, 0xeb000000000dULL, r1, r3, b2, dl2, dh2);
3542 static UChar *
3543 s390_emit_SRA(UChar *p, UChar r1, UChar b2, UShort d2)
3545 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3546 s390_disasm(ENC3(MNM, GPR, UDXB), "sra", r1, d2, 0, b2);
3548 return emit_RS(p, 0x8a000000, r1, 0, b2, d2);
3552 static UChar *
3553 s390_emit_SRAG(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
3555 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3556 s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "srag", r1, r3, dh2, dl2, 0, b2);
3558 return emit_RSY(p, 0xeb000000000aULL, r1, r3, b2, dl2, dh2);
3562 static UChar *
3563 s390_emit_SRL(UChar *p, UChar r1, UChar b2, UShort d2)
3565 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3566 s390_disasm(ENC3(MNM, GPR, UDXB), "srl", r1, d2, 0, b2);
3568 return emit_RS(p, 0x88000000, r1, 0, b2, d2);
3572 static UChar *
3573 s390_emit_SRLG(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
3575 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3576 s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "srlg", r1, r3, dh2, dl2, 0, b2);
3578 return emit_RSY(p, 0xeb000000000cULL, r1, r3, b2, dl2, dh2);
3582 static UChar *
3583 s390_emit_ST(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
3585 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3586 s390_disasm(ENC3(MNM, GPR, UDXB), "st", r1, d2, x2, b2);
3588 return emit_RX(p, 0x50000000, r1, x2, b2, d2);
3592 static UChar *
3593 s390_emit_STY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3595 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3596 s390_disasm(ENC3(MNM, GPR, SDXB), "sty", r1, dh2, dl2, x2, b2);
3598 return emit_RXY(p, 0xe30000000050ULL, r1, x2, b2, dl2, dh2);
3602 static UChar *
3603 s390_emit_STG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3605 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3606 s390_disasm(ENC3(MNM, GPR, SDXB), "stg", r1, dh2, dl2, x2, b2);
3608 return emit_RXY(p, 0xe30000000024ULL, r1, x2, b2, dl2, dh2);
3612 static UChar *
3613 s390_emit_STC(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
3615 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3616 s390_disasm(ENC3(MNM, GPR, UDXB), "stc", r1, d2, x2, b2);
3618 return emit_RX(p, 0x42000000, r1, x2, b2, d2);
3622 static UChar *
3623 s390_emit_STCY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3625 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3626 s390_disasm(ENC3(MNM, GPR, SDXB), "stcy", r1, dh2, dl2, x2, b2);
3628 return emit_RXY(p, 0xe30000000072ULL, r1, x2, b2, dl2, dh2);
3632 static UChar *
3633 s390_emit_STH(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
3635 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3636 s390_disasm(ENC3(MNM, GPR, UDXB), "sth", r1, d2, x2, b2);
3638 return emit_RX(p, 0x40000000, r1, x2, b2, d2);
3642 static UChar *
3643 s390_emit_STHY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3645 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3646 s390_disasm(ENC3(MNM, GPR, SDXB), "sthy", r1, dh2, dl2, x2, b2);
3648 return emit_RXY(p, 0xe30000000070ULL, r1, x2, b2, dl2, dh2);
3652 static UChar *
3653 s390_emit_SR(UChar *p, UChar r1, UChar r2)
3655 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3656 s390_disasm(ENC3(MNM, GPR, GPR), "sr", r1, r2);
3658 return emit_RR(p, 0x1b00, r1, r2);
3662 static UChar *
3663 s390_emit_SGR(UChar *p, UChar r1, UChar r2)
3665 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3666 s390_disasm(ENC3(MNM, GPR, GPR), "sgr", r1, r2);
3668 return emit_RRE(p, 0xb9090000, r1, r2);
3672 static UChar *
3673 s390_emit_S(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
3675 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3676 s390_disasm(ENC3(MNM, GPR, UDXB), "s", r1, d2, x2, b2);
3678 return emit_RX(p, 0x5b000000, r1, x2, b2, d2);
3682 static UChar *
3683 s390_emit_SY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3685 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3686 s390_disasm(ENC3(MNM, GPR, SDXB), "sy", r1, dh2, dl2, x2, b2);
3688 return emit_RXY(p, 0xe3000000005bULL, r1, x2, b2, dl2, dh2);
3692 static UChar *
3693 s390_emit_SG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3695 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3696 s390_disasm(ENC3(MNM, GPR, SDXB), "sg", r1, dh2, dl2, x2, b2);
3698 return emit_RXY(p, 0xe30000000009ULL, r1, x2, b2, dl2, dh2);
3702 static UChar *
3703 s390_emit_SH(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
3705 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3706 s390_disasm(ENC3(MNM, GPR, UDXB), "sh", r1, d2, x2, b2);
3708 return emit_RX(p, 0x4b000000, r1, x2, b2, d2);
3712 static UChar *
3713 s390_emit_SHY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3715 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3716 s390_disasm(ENC3(MNM, GPR, SDXB), "shy", r1, dh2, dl2, x2, b2);
3718 return emit_RXY(p, 0xe3000000007bULL, r1, x2, b2, dl2, dh2);
3722 static UChar *
3723 s390_emit_SLFI(UChar *p, UChar r1, UInt i2)
3725 vassert(s390_host_has_eimm);
3727 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3728 s390_disasm(ENC3(MNM, GPR, UINT), "slfi", r1, i2);
3730 return emit_RIL(p, 0xc20500000000ULL, r1, i2);
3734 static UChar *
3735 s390_emit_SLGFI(UChar *p, UChar r1, UInt i2)
3737 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3738 s390_disasm(ENC3(MNM, GPR, UINT), "slgfi", r1, i2);
3740 return emit_RIL(p, 0xc20400000000ULL, r1, i2);
3744 static UChar *
3745 s390_emit_LDR(UChar *p, UChar r1, UChar r2)
3747 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3748 s390_disasm(ENC3(MNM, FPR, FPR), "ldr", r1, r2);
3750 return emit_RR(p, 0x2800, r1, r2);
3754 static UChar *
3755 s390_emit_LE(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
3757 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3758 s390_disasm(ENC3(MNM, FPR, UDXB), "le", r1, d2, x2, b2);
3760 return emit_RX(p, 0x78000000, r1, x2, b2, d2);
3764 static UChar *
3765 s390_emit_LD(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
3767 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3768 s390_disasm(ENC3(MNM, FPR, UDXB), "ld", r1, d2, x2, b2);
3770 return emit_RX(p, 0x68000000, r1, x2, b2, d2);
3774 static UChar *
3775 s390_emit_LEY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3777 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3778 s390_disasm(ENC3(MNM, FPR, SDXB), "ley", r1, dh2, dl2, x2, b2);
3780 return emit_RXY(p, 0xed0000000064ULL, r1, x2, b2, dl2, dh2);
3784 static UChar *
3785 s390_emit_LDY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3787 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3788 s390_disasm(ENC3(MNM, FPR, SDXB), "ldy", r1, dh2, dl2, x2, b2);
3790 return emit_RXY(p, 0xed0000000065ULL, r1, x2, b2, dl2, dh2);
3794 static UChar *
3795 s390_emit_LFPC(UChar *p, UChar b2, UShort d2)
3797 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3798 s390_disasm(ENC2(MNM, UDXB), "lfpc", d2, 0, b2);
3800 return emit_S(p, 0xb29d0000, b2, d2);
3804 static UChar *
3805 s390_emit_LDGR(UChar *p, UChar r1, UChar r2)
3807 vassert(s390_host_has_fgx);
3809 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3810 s390_disasm(ENC3(MNM, FPR, GPR), "ldgr", r1, r2);
3812 return emit_RRE(p, 0xb3c10000, r1, r2);
3816 static UChar *
3817 s390_emit_LGDR(UChar *p, UChar r1, UChar r2)
3819 vassert(s390_host_has_fgx);
3821 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3822 s390_disasm(ENC3(MNM, GPR, FPR), "lgdr", r1, r2);
3824 return emit_RRE(p, 0xb3cd0000, r1, r2);
3828 static UChar *
3829 s390_emit_LZER(UChar *p, UChar r1, UChar r2)
3831 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3832 s390_disasm(ENC2(MNM, FPR), "lzer", r1);
3834 return emit_RRE(p, 0xb3740000, r1, r2);
3838 static UChar *
3839 s390_emit_LZDR(UChar *p, UChar r1, UChar r2)
3841 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3842 s390_disasm(ENC2(MNM, FPR), "lzdr", r1);
3844 return emit_RRE(p, 0xb3750000, r1, r2);
3848 static UChar *
3849 s390_emit_SFPC(UChar *p, UChar r1)
3851 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3852 s390_disasm(ENC2(MNM, GPR), "sfpc", r1);
3854 return emit_RRE(p, 0xb3840000, r1, 0);
3858 static UChar *
3859 s390_emit_STE(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
3861 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3862 s390_disasm(ENC3(MNM, FPR, UDXB), "ste", r1, d2, x2, b2);
3864 return emit_RX(p, 0x70000000, r1, x2, b2, d2);
3868 static UChar *
3869 s390_emit_STD(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
3871 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3872 s390_disasm(ENC3(MNM, FPR, UDXB), "std", r1, d2, x2, b2);
3874 return emit_RX(p, 0x60000000, r1, x2, b2, d2);
3878 static UChar *
3879 s390_emit_STEY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3881 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3882 s390_disasm(ENC3(MNM, FPR, SDXB), "stey", r1, dh2, dl2, x2, b2);
3884 return emit_RXY(p, 0xed0000000066ULL, r1, x2, b2, dl2, dh2);
3888 static UChar *
3889 s390_emit_STDY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3891 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3892 s390_disasm(ENC3(MNM, FPR, SDXB), "stdy", r1, dh2, dl2, x2, b2);
3894 return emit_RXY(p, 0xed0000000067ULL, r1, x2, b2, dl2, dh2);
3898 static UChar *
3899 s390_emit_STFPC(UChar *p, UChar b2, UShort d2)
3901 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3902 s390_disasm(ENC2(MNM, UDXB), "stfpc", d2, 0, b2);
3904 return emit_S(p, 0xb29c0000, b2, d2);
3908 static UChar *
3909 s390_emit_AEBR(UChar *p, UChar r1, UChar r2)
3911 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3912 s390_disasm(ENC3(MNM, FPR, FPR), "aebr", r1, r2);
3914 return emit_RRE(p, 0xb30a0000, r1, r2);
3918 static UChar *
3919 s390_emit_ADBR(UChar *p, UChar r1, UChar r2)
3921 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3922 s390_disasm(ENC3(MNM, FPR, FPR), "adbr", r1, r2);
3924 return emit_RRE(p, 0xb31a0000, r1, r2);
3928 static UChar *
3929 s390_emit_AXBR(UChar *p, UChar r1, UChar r2)
3931 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3932 s390_disasm(ENC3(MNM, FPR, FPR), "axbr", r1, r2);
3934 return emit_RRE(p, 0xb34a0000, r1, r2);
3938 static UChar *
3939 s390_emit_CEBR(UChar *p, UChar r1, UChar r2)
3941 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3942 s390_disasm(ENC3(MNM, FPR, FPR), "cebr", r1, r2);
3944 return emit_RRE(p, 0xb3090000, r1, r2);
3948 static UChar *
3949 s390_emit_CDBR(UChar *p, UChar r1, UChar r2)
3951 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3952 s390_disasm(ENC3(MNM, FPR, FPR), "cdbr", r1, r2);
3954 return emit_RRE(p, 0xb3190000, r1, r2);
3958 static UChar *
3959 s390_emit_CXBR(UChar *p, UChar r1, UChar r2)
3961 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3962 s390_disasm(ENC3(MNM, FPR, FPR), "cxbr", r1, r2);
3964 return emit_RRE(p, 0xb3490000, r1, r2);
3968 static UChar *
3969 s390_emit_CEFBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
3971 vassert(m4 == 0);
3972 vassert(m3 == 0 || s390_host_has_fpext);
3974 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
3975 if (m3 == 0)
3976 s390_disasm(ENC3(MNM, FPR, GPR), "cefbr", r1, r2);
3977 else
3978 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT),
3979 "cefbra", r1, m3, r2, m4);
3982 return emit_RRF2(p, 0xb3940000, m3, m4, r1, r2);
3986 static UChar *
3987 s390_emit_CDFBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
3989 vassert(m4 == 0);
3990 vassert(m3 == 0 || s390_host_has_fpext);
3992 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
3993 if (m3 == 0)
3994 s390_disasm(ENC3(MNM, FPR, GPR), "cdfbr", r1, r2);
3995 else
3996 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT),
3997 "cdfbra", r1, m3, r2, m4);
4000 return emit_RRF2(p, 0xb3950000, m3, m4, r1, r2);
4004 static UChar *
4005 s390_emit_CXFBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4007 vassert(m4 == 0);
4008 vassert(m3 == 0 || s390_host_has_fpext);
4010 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
4011 if (m3 == 0)
4012 s390_disasm(ENC3(MNM, FPR, GPR), "cxfbr", r1, r2);
4013 else
4014 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT),
4015 "cxfbra", r1, m3, r2, m4);
4018 return emit_RRF2(p, 0xb3960000, m3, m4, r1, r2);
4022 static UChar *
4023 s390_emit_CEGBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4025 vassert(m4 == 0);
4026 vassert(m3 == 0 || s390_host_has_fpext);
4028 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
4029 if (m3 == 0)
4030 s390_disasm(ENC3(MNM, FPR, GPR), "cegbr", r1, r2);
4031 else
4032 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT),
4033 "cegbra", r1, m3, r2, m4);
4036 return emit_RRF2(p, 0xb3a40000, m3, m4, r1, r2);
4040 static UChar *
4041 s390_emit_CDGBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4043 vassert(m4 == 0);
4044 vassert(m3 == 0 || s390_host_has_fpext);
4046 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
4047 if (m3 == 0)
4048 s390_disasm(ENC3(MNM, FPR, GPR), "cdgbr", r1, r2);
4049 else
4050 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT),
4051 "cdgbra", r1, m3, r2, m4);
4054 return emit_RRF2(p, 0xb3a50000, m3, m4, r1, r2);
4058 static UChar *
4059 s390_emit_CXGBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4061 vassert(m4 == 0);
4062 vassert(m3 == 0 || s390_host_has_fpext);
4064 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
4065 if (m3 == 0)
4066 s390_disasm(ENC3(MNM, FPR, GPR), "cxgbr", r1, r2);
4067 else
4068 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT),
4069 "cxgbra", r1, m3, r2, m4);
4072 return emit_RRF2(p, 0xb3a60000, m3, m4, r1, r2);
4076 static UChar *
4077 s390_emit_CELFBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4079 vassert(m4 == 0);
4080 vassert(s390_host_has_fpext);
4082 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4083 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "celfbr", r1, m3, r2, m4);
4085 return emit_RRF2(p, 0xb3900000, m3, m4, r1, r2);
4089 static UChar *
4090 s390_emit_CDLFBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4092 vassert(m4 == 0);
4093 vassert(s390_host_has_fpext);
4095 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4096 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cdlfbr", r1, m3, r2, m4);
4098 return emit_RRF2(p, 0xb3910000, m3, m4, r1, r2);
4102 static UChar *
4103 s390_emit_CXLFBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4105 vassert(m4 == 0);
4106 vassert(s390_host_has_fpext);
4108 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4109 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cxlfbr", r1, m3, r2, m4);
4111 return emit_RRF2(p, 0xb3920000, m3, m4, r1, r2);
4115 static UChar *
4116 s390_emit_CELGBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4118 vassert(m4 == 0);
4119 vassert(s390_host_has_fpext);
4121 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4122 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "celgbr", r1, m3, r2, m4);
4124 return emit_RRF2(p, 0xb3a00000, m3, m4, r1, r2);
4128 static UChar *
4129 s390_emit_CDLGBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4131 vassert(m4 == 0);
4132 vassert(s390_host_has_fpext);
4134 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4135 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cdlgbr", r1, m3, r2, m4);
4137 return emit_RRF2(p, 0xb3a10000, m3, m4, r1, r2);
4141 static UChar *
4142 s390_emit_CXLGBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4144 vassert(m4 == 0);
4145 vassert(s390_host_has_fpext);
4147 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4148 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cxlgbr", r1, m3, r2, m4);
4150 return emit_RRF2(p, 0xb3a20000, m3, m4, r1, r2);
4154 static UChar *
4155 s390_emit_CLFEBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4157 vassert(m4 == 0);
4158 vassert(s390_host_has_fpext);
4160 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4161 s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clfebr", r1, m3, r2, m4);
4163 return emit_RRF2(p, 0xb39c0000, m3, m4, r1, r2);
4167 static UChar *
4168 s390_emit_CLFDBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4170 vassert(m4 == 0);
4171 vassert(s390_host_has_fpext);
4173 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4174 s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clfdbr", r1, m3, r2, m4);
4176 return emit_RRF2(p, 0xb39d0000, m3, m4, r1, r2);
4180 static UChar *
4181 s390_emit_CLFXBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4183 vassert(m4 == 0);
4184 vassert(s390_host_has_fpext);
4186 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4187 s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clfxbr", r1, m3, r2, m4);
4189 return emit_RRF2(p, 0xb39e0000, m3, m4, r1, r2);
4193 static UChar *
4194 s390_emit_CLGEBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4196 vassert(m4 == 0);
4197 vassert(s390_host_has_fpext);
4199 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4200 s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clgebr", r1, m3, r2, m4);
4202 return emit_RRF2(p, 0xb3ac0000, m3, m4, r1, r2);
4206 static UChar *
4207 s390_emit_CLGDBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4209 vassert(m4 == 0);
4210 vassert(s390_host_has_fpext);
4212 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4213 s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clgdbr", r1, m3, r2, m4);
4215 return emit_RRF2(p, 0xb3ad0000, m3, m4, r1, r2);
4219 static UChar *
4220 s390_emit_CLGXBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4222 vassert(m4 == 0);
4223 vassert(s390_host_has_fpext);
4225 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4226 s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clgxbr", r1, m3, r2, m4);
4228 return emit_RRF2(p, 0xb3ae0000, m3, m4, r1, r2);
4232 static UChar *
4233 s390_emit_CFEBR(UChar *p, UChar r3, UChar r1, UChar r2)
4235 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4236 s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cfebr", r1, r3, r2);
4238 return emit_RRF3(p, 0xb3980000, r3, r1, r2);
4242 static UChar *
4243 s390_emit_CFDBR(UChar *p, UChar r3, UChar r1, UChar r2)
4245 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4246 s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cfdbr", r1, r3, r2);
4248 return emit_RRF3(p, 0xb3990000, r3, r1, r2);
4252 static UChar *
4253 s390_emit_CFXBR(UChar *p, UChar r3, UChar r1, UChar r2)
4255 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4256 s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cfxbr", r1, r3, r2);
4258 return emit_RRF3(p, 0xb39a0000, r3, r1, r2);
4262 static UChar *
4263 s390_emit_CGEBR(UChar *p, UChar r3, UChar r1, UChar r2)
4265 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4266 s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cgebr", r1, r3, r2);
4268 return emit_RRF3(p, 0xb3a80000, r3, r1, r2);
4272 static UChar *
4273 s390_emit_CGDBR(UChar *p, UChar r3, UChar r1, UChar r2)
4275 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4276 s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cgdbr", r1, r3, r2);
4278 return emit_RRF3(p, 0xb3a90000, r3, r1, r2);
4282 static UChar *
4283 s390_emit_CGXBR(UChar *p, UChar r3, UChar r1, UChar r2)
4285 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4286 s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cgxbr", r1, r3, r2);
4288 return emit_RRF3(p, 0xb3aa0000, r3, r1, r2);
4292 static UChar *
4293 s390_emit_DEBR(UChar *p, UChar r1, UChar r2)
4295 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4296 s390_disasm(ENC3(MNM, FPR, FPR), "debr", r1, r2);
4298 return emit_RRE(p, 0xb30d0000, r1, r2);
4302 static UChar *
4303 s390_emit_DDBR(UChar *p, UChar r1, UChar r2)
4305 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4306 s390_disasm(ENC3(MNM, FPR, FPR), "ddbr", r1, r2);
4308 return emit_RRE(p, 0xb31d0000, r1, r2);
4312 static UChar *
4313 s390_emit_DXBR(UChar *p, UChar r1, UChar r2)
4315 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4316 s390_disasm(ENC3(MNM, FPR, FPR), "dxbr", r1, r2);
4318 return emit_RRE(p, 0xb34d0000, r1, r2);
4322 static UChar *
4323 s390_emit_LCEBR(UChar *p, UChar r1, UChar r2)
4325 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4326 s390_disasm(ENC3(MNM, FPR, FPR), "lcebr", r1, r2);
4328 return emit_RRE(p, 0xb3030000, r1, r2);
4332 static UChar *
4333 s390_emit_LCDBR(UChar *p, UChar r1, UChar r2)
4335 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4336 s390_disasm(ENC3(MNM, FPR, FPR), "lcdbr", r1, r2);
4338 return emit_RRE(p, 0xb3130000, r1, r2);
4342 static UChar *
4343 s390_emit_LCXBR(UChar *p, UChar r1, UChar r2)
4345 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4346 s390_disasm(ENC3(MNM, FPR, FPR), "lcxbr", r1, r2);
4348 return emit_RRE(p, 0xb3430000, r1, r2);
4352 static UChar *
4353 s390_emit_LDEBR(UChar *p, UChar r1, UChar r2)
4355 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4356 s390_disasm(ENC3(MNM, FPR, FPR), "ldebr", r1, r2);
4358 return emit_RRE(p, 0xb3040000, r1, r2);
4362 static UChar *
4363 s390_emit_LXDBR(UChar *p, UChar r1, UChar r2)
4365 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4366 s390_disasm(ENC3(MNM, FPR, FPR), "lxdbr", r1, r2);
4368 return emit_RRE(p, 0xb3050000, r1, r2);
4372 static UChar *
4373 s390_emit_LXEBR(UChar *p, UChar r1, UChar r2)
4375 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4376 s390_disasm(ENC3(MNM, FPR, FPR), "lxebr", r1, r2);
4378 return emit_RRE(p, 0xb3060000, r1, r2);
4382 static UChar *
4383 s390_emit_LNEBR(UChar *p, UChar r1, UChar r2)
4385 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4386 s390_disasm(ENC3(MNM, FPR, FPR), "lnebr", r1, r2);
4388 return emit_RRE(p, 0xb3010000, r1, r2);
4392 static UChar *
4393 s390_emit_LNDBR(UChar *p, UChar r1, UChar r2)
4395 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4396 s390_disasm(ENC3(MNM, FPR, FPR), "lndbr", r1, r2);
4398 return emit_RRE(p, 0xb3110000, r1, r2);
4402 static UChar *
4403 s390_emit_LNXBR(UChar *p, UChar r1, UChar r2)
4405 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4406 s390_disasm(ENC3(MNM, FPR, FPR), "lnxbr", r1, r2);
4408 return emit_RRE(p, 0xb3410000, r1, r2);
4412 static UChar *
4413 s390_emit_LPEBR(UChar *p, UChar r1, UChar r2)
4415 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4416 s390_disasm(ENC3(MNM, FPR, FPR), "lpebr", r1, r2);
4418 return emit_RRE(p, 0xb3000000, r1, r2);
4422 static UChar *
4423 s390_emit_LPDBR(UChar *p, UChar r1, UChar r2)
4425 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4426 s390_disasm(ENC3(MNM, FPR, FPR), "lpdbr", r1, r2);
4428 return emit_RRE(p, 0xb3100000, r1, r2);
4432 static UChar *
4433 s390_emit_LPXBR(UChar *p, UChar r1, UChar r2)
4435 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4436 s390_disasm(ENC3(MNM, FPR, FPR), "lpxbr", r1, r2);
4438 return emit_RRE(p, 0xb3400000, r1, r2);
4442 static UChar *
4443 s390_emit_LEDBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4445 vassert(m4 == 0);
4446 vassert(m3 == 0 || s390_host_has_fpext);
4448 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
4449 if (m3 == 0)
4450 s390_disasm(ENC3(MNM, FPR, FPR), "ledbr", r1, r2);
4451 else
4452 s390_disasm(ENC5(MNM, FPR, UINT, FPR, UINT),
4453 "ledbra", r1, m3, r2, m4);
4456 return emit_RRF2(p, 0xb3440000, m3, m4, r1, r2);
4460 static UChar *
4461 s390_emit_LDXBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4463 vassert(m4 == 0);
4464 vassert(m3 == 0 || s390_host_has_fpext);
4466 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
4467 if (m3 == 0)
4468 s390_disasm(ENC3(MNM, FPR, FPR), "ldxbr", r1, r2);
4469 else
4470 s390_disasm(ENC5(MNM, FPR, UINT, FPR, UINT),
4471 "ldxbra", r1, m3, r2, m4);
4474 return emit_RRF2(p, 0xb3450000, m3, m4, r1, r2);
4478 static UChar *
4479 s390_emit_LEXBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4481 vassert(m4 == 0);
4482 vassert(m3 == 0 || s390_host_has_fpext);
4484 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
4485 if (m3 == 0)
4486 s390_disasm(ENC3(MNM, FPR, FPR), "lexbr", r1, r2);
4487 else
4488 s390_disasm(ENC5(MNM, FPR, UINT, FPR, UINT),
4489 "lexbra", r1, m3, r2, m4);
4492 return emit_RRF2(p, 0xb3460000, m3, m4, r1, r2);
4496 static UChar *
4497 s390_emit_FIEBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4499 vassert(m3 == 0 || s390_host_has_fpext);
4501 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
4502 if (m4 == 0)
4503 s390_disasm(ENC4(MNM, FPR, UINT, FPR), "fiebr", r1, m3, r2);
4504 else
4505 s390_disasm(ENC5(MNM, FPR, UINT, FPR, UINT),
4506 "fiebra", r1, m3, r2, m4);
4509 return emit_RRF2(p, 0xb3570000, m3, m4, r1, r2);
4513 static UChar *
4514 s390_emit_FIDBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4516 vassert(m3 == 0 || s390_host_has_fpext);
4518 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
4519 if (m4 == 0)
4520 s390_disasm(ENC4(MNM, FPR, UINT, FPR), "fidbr", r1, m3, r2);
4521 else
4522 s390_disasm(ENC5(MNM, FPR, UINT, FPR, UINT),
4523 "fidbra", r1, m3, r2, m4);
4526 return emit_RRF2(p, 0xb35f0000, m3, m4, r1, r2);
4530 static UChar *
4531 s390_emit_FIXBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4533 vassert(m3 == 0 || s390_host_has_fpext);
4535 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
4536 if (m4 == 0)
4537 s390_disasm(ENC4(MNM, FPR, UINT, FPR), "fixbr", r1, m3, r2);
4538 else
4539 s390_disasm(ENC5(MNM, FPR, UINT, FPR, UINT),
4540 "fixbra", r1, m3, r2, m4);
4543 return emit_RRF2(p, 0xb3470000, m3, m4, r1, r2);
4547 static UChar *
4548 s390_emit_MEEBR(UChar *p, UChar r1, UChar r2)
4550 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4551 s390_disasm(ENC3(MNM, FPR, FPR), "meebr", r1, r2);
4553 return emit_RRE(p, 0xb3170000, r1, r2);
4557 static UChar *
4558 s390_emit_MDBR(UChar *p, UChar r1, UChar r2)
4560 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4561 s390_disasm(ENC3(MNM, FPR, FPR), "mdbr", r1, r2);
4563 return emit_RRE(p, 0xb31c0000, r1, r2);
4567 static UChar *
4568 s390_emit_MXBR(UChar *p, UChar r1, UChar r2)
4570 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4571 s390_disasm(ENC3(MNM, FPR, FPR), "mxbr", r1, r2);
4573 return emit_RRE(p, 0xb34c0000, r1, r2);
4577 static UChar *
4578 s390_emit_MAEBR(UChar *p, UChar r1, UChar r3, UChar r2)
4580 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4581 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "maebr", r1, r3, r2);
4583 return emit_RRF(p, 0xb30e0000, r1, r3, r2);
4587 static UChar *
4588 s390_emit_MADBR(UChar *p, UChar r1, UChar r3, UChar r2)
4590 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4591 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "madbr", r1, r3, r2);
4593 return emit_RRF(p, 0xb31e0000, r1, r3, r2);
4597 static UChar *
4598 s390_emit_MSEBR(UChar *p, UChar r1, UChar r3, UChar r2)
4600 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4601 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "msebr", r1, r3, r2);
4603 return emit_RRF(p, 0xb30f0000, r1, r3, r2);
4607 static UChar *
4608 s390_emit_MSDBR(UChar *p, UChar r1, UChar r3, UChar r2)
4610 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4611 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "msdbr", r1, r3, r2);
4613 return emit_RRF(p, 0xb31f0000, r1, r3, r2);
4617 static UChar *
4618 s390_emit_SQEBR(UChar *p, UChar r1, UChar r2)
4620 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4621 s390_disasm(ENC3(MNM, FPR, FPR), "sqebr", r1, r2);
4623 return emit_RRE(p, 0xb3140000, r1, r2);
4627 static UChar *
4628 s390_emit_SQDBR(UChar *p, UChar r1, UChar r2)
4630 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4631 s390_disasm(ENC3(MNM, FPR, FPR), "sqdbr", r1, r2);
4633 return emit_RRE(p, 0xb3150000, r1, r2);
4637 static UChar *
4638 s390_emit_SQXBR(UChar *p, UChar r1, UChar r2)
4640 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4641 s390_disasm(ENC3(MNM, FPR, FPR), "sqxbr", r1, r2);
4643 return emit_RRE(p, 0xb3160000, r1, r2);
4647 static UChar *
4648 s390_emit_SEBR(UChar *p, UChar r1, UChar r2)
4650 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4651 s390_disasm(ENC3(MNM, FPR, FPR), "sebr", r1, r2);
4653 return emit_RRE(p, 0xb30b0000, r1, r2);
4657 static UChar *
4658 s390_emit_SDBR(UChar *p, UChar r1, UChar r2)
4660 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4661 s390_disasm(ENC3(MNM, FPR, FPR), "sdbr", r1, r2);
4663 return emit_RRE(p, 0xb31b0000, r1, r2);
4667 static UChar *
4668 s390_emit_SXBR(UChar *p, UChar r1, UChar r2)
4670 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4671 s390_disasm(ENC3(MNM, FPR, FPR), "sxbr", r1, r2);
4673 return emit_RRE(p, 0xb34b0000, r1, r2);
4677 static UChar *
4678 s390_emit_ADTRA(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
4680 vassert(s390_host_has_dfp);
4681 vassert(m4 == 0 || s390_host_has_fpext);
4682 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
4683 if (m4 == 0)
4684 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "adtr", r1, r2, r3);
4685 else
4686 s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "adtra", r1, r2, r3, m4);
4689 return emit_RRF4(p, 0xb3d20000, r3, m4, r1, r2);
4693 static UChar *
4694 s390_emit_AXTRA(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
4696 vassert(s390_host_has_dfp);
4697 vassert(m4 == 0 || s390_host_has_fpext);
4698 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
4699 if (m4 == 0)
4700 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "axtr", r1, r2, r3);
4701 else
4702 s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "axtra", r1, r2, r3, m4);
4705 return emit_RRF4(p, 0xb3da0000, r3, m4, r1, r2);
4709 static UChar *
4710 s390_emit_CDTR(UChar *p, UChar r1, UChar r2)
4712 vassert(s390_host_has_dfp);
4713 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4714 s390_disasm(ENC3(MNM, FPR, FPR), "cdtr", r1, r2);
4716 return emit_RRE(p, 0xb3e40000, r1, r2);
4720 static UChar *
4721 s390_emit_CXTR(UChar *p, UChar r1, UChar r2)
4723 vassert(s390_host_has_dfp);
4724 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4725 s390_disasm(ENC3(MNM, FPR, FPR), "cxtr", r1, r2);
4727 return emit_RRE(p, 0xb3ec0000, r1, r2);
4731 static UChar *
4732 s390_emit_CDGTRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4734 vassert(s390_host_has_dfp);
4735 vassert(m4 == 0);
4736 vassert(m3 == 0 || s390_host_has_fpext);
4738 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
4739 if (m3 == 0)
4740 s390_disasm(ENC3(MNM, FPR, GPR), "cdgtr", r1, r2);
4741 else
4742 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cdgtra", r1, m3, r2, m4);
4745 return emit_RRF2(p, 0xb3f10000, m3, m4, r1, r2);
4749 static UChar *
4750 s390_emit_CXGTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4752 vassert(s390_host_has_dfp);
4753 vassert(m4 == 0);
4754 /* rounding mode m3 is not considered, as the corresponding
4755 IRop (Iop_I64StoD128) does not take rounding mode. */
4756 vassert(m3 == 0);
4758 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4759 s390_disasm(ENC3(MNM, FPR, GPR), "cxgtr", r1, r2);
4761 return emit_RRF2(p, 0xb3f90000, m3, m4, r1, r2);
4765 static UChar *
4766 s390_emit_CDFTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4768 vassert(m4 == 0);
4769 vassert(s390_host_has_dfp);
4770 vassert(s390_host_has_fpext);
4772 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4773 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cdftr", r1, m3, r2, m4);
4775 return emit_RRF2(p, 0xb9510000, m3, m4, r1, r2);
4779 static UChar *
4780 s390_emit_CXFTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4782 vassert(m4 == 0);
4783 vassert(s390_host_has_dfp);
4784 vassert(s390_host_has_fpext);
4786 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4787 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cxftr", r1, m3, r2, m4);
4789 return emit_RRF2(p, 0xb9590000, m3, m4, r1, r2);
4793 static UChar *
4794 s390_emit_CDLFTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4796 vassert(m4 == 0);
4797 vassert(s390_host_has_dfp);
4798 vassert(s390_host_has_fpext);
4800 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4801 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cdlftr", r1, m3, r2, m4);
4803 return emit_RRF2(p, 0xb9530000, m3, m4, r1, r2);
4807 static UChar *
4808 s390_emit_CXLFTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4810 vassert(m4 == 0);
4811 vassert(s390_host_has_dfp);
4812 vassert(s390_host_has_fpext);
4814 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4815 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cxlftr", r1, m3, r2, m4);
4817 return emit_RRF2(p, 0xb95b0000, m3, m4, r1, r2);
4821 static UChar *
4822 s390_emit_CDLGTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4824 vassert(m4 == 0);
4825 vassert(s390_host_has_dfp);
4826 vassert(s390_host_has_fpext);
4828 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4829 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cdlgtr", r1, m3, r2, m4);
4831 return emit_RRF2(p, 0xb9520000, m3, m4, r1, r2);
4835 static UChar *
4836 s390_emit_CXLGTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4838 vassert(m4 == 0);
4839 vassert(s390_host_has_dfp);
4840 vassert(s390_host_has_fpext);
4842 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4843 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cxlgtr", r1, m3, r2, m4);
4845 return emit_RRF2(p, 0xb95a0000, m3, m4, r1, r2);
4849 static UChar *
4850 s390_emit_CEDTR(UChar *p, UChar r1, UChar r2)
4852 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4853 s390_disasm(ENC3(MNM, FPR, FPR), "cedtr", r1, r2);
4855 return emit_RRE(p, 0xb3f40000, r1, r2);
4859 static UChar *
4860 s390_emit_CEXTR(UChar *p, UChar r1, UChar r2)
4862 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4863 s390_disasm(ENC3(MNM, FPR, FPR), "cextr", r1, r2);
4865 return emit_RRE(p, 0xb3fc0000, r1, r2);
4869 static UChar *
4870 s390_emit_CFDTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4872 vassert(m4 == 0);
4873 vassert(s390_host_has_dfp);
4874 vassert(s390_host_has_fpext);
4876 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4877 s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "cfdtr", r1, m3, r2, m4);
4879 return emit_RRF2(p, 0xb9410000, m3, m4, r1, r2);
4883 static UChar *
4884 s390_emit_CFXTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4886 vassert(m4 == 0);
4887 vassert(s390_host_has_dfp);
4888 vassert(s390_host_has_fpext);
4890 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4891 s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "cfxtr", r1, m3, r2, m4);
4893 return emit_RRF2(p, 0xb9490000, m3, m4, r1, r2);
4897 static UChar *
4898 s390_emit_CGDTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4900 vassert(s390_host_has_dfp);
4901 vassert(m4 == 0);
4902 vassert(s390_host_has_fpext || m3 < 1 || m3 > 7);
4904 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4905 s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cgdtr", r1, m3, r2);
4907 return emit_RRF2(p, 0xb3e10000, m3, m4, r1, r2);
4911 static UChar *
4912 s390_emit_CGXTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4914 vassert(s390_host_has_dfp);
4915 vassert(m4 == 0);
4916 vassert(s390_host_has_fpext || m3 < 1 || m3 > 7);
4918 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4919 s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cgxtr", r1, m3, r2);
4921 return emit_RRF2(p, 0xb3e90000, m3, m4, r1, r2);
4925 static UChar *
4926 s390_emit_CLFDTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4928 vassert(m4 == 0);
4929 vassert(s390_host_has_dfp);
4930 vassert(s390_host_has_fpext);
4932 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4933 s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clfdtr", r1, m3, r2, m4);
4935 return emit_RRF2(p, 0xb9430000, m3, m4, r1, r2);
4939 static UChar *
4940 s390_emit_CLFXTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4942 vassert(m4 == 0);
4943 vassert(s390_host_has_dfp);
4944 vassert(s390_host_has_fpext);
4946 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4947 s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clfxtr", r1, m3, r2, m4);
4949 return emit_RRF2(p, 0xb94b0000, m3, m4, r1, r2);
4953 static UChar *
4954 s390_emit_CLGDTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4956 vassert(m4 == 0);
4957 vassert(s390_host_has_dfp);
4958 vassert(s390_host_has_fpext);
4960 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4961 s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clgdtr", r1, m3, r2, m4);
4963 return emit_RRF2(p, 0xb9420000, m3, m4, r1, r2);
4967 static UChar *
4968 s390_emit_CLGXTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4970 vassert(m4 == 0);
4971 vassert(s390_host_has_dfp);
4972 vassert(s390_host_has_fpext);
4974 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4975 s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clgxtr", r1, m3, r2, m4);
4977 return emit_RRF2(p, 0xb94a0000, m3, m4, r1, r2);
4981 static UChar *
4982 s390_emit_DDTRA(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
4984 vassert(s390_host_has_dfp);
4985 vassert(m4 == 0 || s390_host_has_fpext);
4986 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
4987 if (m4 == 0)
4988 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "ddtr", r1, r2, r3);
4989 else
4990 s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "ddtra", r1, r2, r3, m4);
4993 return emit_RRF4(p, 0xb3d10000, r3, m4, r1, r2);
4997 static UChar *
4998 s390_emit_DXTRA(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
5000 vassert(s390_host_has_dfp);
5001 vassert(m4 == 0 || s390_host_has_fpext);
5002 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
5003 if (m4 == 0)
5004 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "dxtr", r1, r2, r3);
5005 else
5006 s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "dxtra", r1, r2, r3, m4);
5009 return emit_RRF4(p, 0xb3d90000, r3, m4, r1, r2);
5013 static UChar *
5014 s390_emit_EEDTR(UChar *p, UChar r1, UChar r2)
5016 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
5017 s390_disasm(ENC3(MNM, GPR, FPR), "eedtr", r1, r2);
5019 return emit_RRE(p, 0xb3e50000, r1, r2);
5023 static UChar *
5024 s390_emit_EEXTR(UChar *p, UChar r1, UChar r2)
5026 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
5027 s390_disasm(ENC3(MNM, GPR, FPR), "eextr", r1, r2);
5029 return emit_RRE(p, 0xb3ed0000, r1, r2);
5033 static UChar *
5034 s390_emit_ESDTR(UChar *p, UChar r1, UChar r2)
5036 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
5037 s390_disasm(ENC3(MNM, GPR, FPR), "esdtr", r1, r2);
5039 return emit_RRE(p, 0xb3e70000, r1, r2);
5043 static UChar *
5044 s390_emit_ESXTR(UChar *p, UChar r1, UChar r2)
5046 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
5047 s390_disasm(ENC3(MNM, GPR, FPR), "esxtr", r1, r2);
5049 return emit_RRE(p, 0xb3ef0000, r1, r2);
5053 static UChar *
5054 s390_emit_IEDTR(UChar *p, UChar r3, UChar r1, UChar r2)
5056 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
5057 s390_disasm(ENC4(MNM, FPR, FPR, GPR), "iedtr", r1, r3, r2);
5059 return emit_RRF(p, 0xb3f60000, r3, r1, r2);
5063 static UChar *
5064 s390_emit_IEXTR(UChar *p, UChar r3, UChar r1, UChar r2)
5066 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
5067 s390_disasm(ENC4(MNM, FPR, FPR, GPR), "iextr", r1, r3, r2);
5069 return emit_RRF(p, 0xb3fe0000, r3, r1, r2);
5073 static UChar *
5074 s390_emit_LDETR(UChar *p, UChar m4, UChar r1, UChar r2)
5076 vassert(s390_host_has_dfp);
5077 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
5078 s390_disasm(ENC4(MNM, FPR, FPR, UINT), "ldetr", r1, r2, m4);
5080 return emit_RRF5(p, 0xb3d40000, m4, r1, r2);
5084 static UChar *
5085 s390_emit_LXDTR(UChar *p, UChar m4, UChar r1, UChar r2)
5087 vassert(s390_host_has_dfp);
5088 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
5089 s390_disasm(ENC4(MNM, FPR, FPR, UINT), "lxdtr", r1, r2, m4);
5091 return emit_RRF5(p, 0xb3dc0000, m4, r1, r2);
5095 static UChar *
5096 s390_emit_LEDTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
5098 vassert(s390_host_has_dfp);
5099 vassert(m4 == 0);
5100 vassert(s390_host_has_fpext || m3 < 1 || m3 > 7);
5102 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
5103 s390_disasm(ENC5(MNM, FPR, UINT, FPR, UINT), "ledtr", r1, m3, r2, m4);
5105 return emit_RRF2(p, 0xb3d50000, m3, m4, r1, r2);
5109 static UChar *
5110 s390_emit_LDXTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
5112 vassert(s390_host_has_dfp);
5113 vassert(m4 == 0);
5114 vassert(s390_host_has_fpext || m3 < 1 || m3 > 7);
5116 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
5117 s390_disasm(ENC5(MNM, FPR, UINT, FPR, UINT), "ldxtr", r1, m3, r2, m4);
5119 return emit_RRF2(p, 0xb3dd0000, m3, m4, r1, r2);
5123 static UChar *
5124 s390_emit_MDTRA(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
5126 vassert(s390_host_has_dfp);
5127 vassert(m4 == 0 || s390_host_has_fpext);
5128 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
5129 if (m4 == 0)
5130 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "mdtr", r1, r2, r3);
5131 else
5132 s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "mdtra", r1, r2, r3, m4);
5135 return emit_RRF4(p, 0xb3d00000, r3, m4, r1, r2);
5139 static UChar *
5140 s390_emit_MXTRA(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
5142 vassert(s390_host_has_dfp);
5143 vassert(m4 == 0 || s390_host_has_fpext);
5144 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
5145 if (m4 == 0)
5146 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "mxtr", r1, r2, r3);
5147 else
5148 s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "mxtra", r1, r2, r3, m4);
5151 return emit_RRF4(p, 0xb3d80000, r3, m4, r1, r2);
5155 static UChar *
5156 emit_E(UChar *p, UInt op)
5158 ULong the_insn = op;
5160 return emit_2bytes(p, the_insn);
5164 static UChar *
5165 s390_emit_PFPO(UChar *p)
5167 vassert(s390_host_has_pfpo);
5168 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
5169 s390_disasm(ENC1(MNM), "pfpo");
5172 return emit_E(p, 0x010a);
5176 static UChar *
5177 s390_emit_QADTR(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
5179 vassert(s390_host_has_dfp);
5180 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
5181 s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "qadtr", r1, r3, r2, m4);
5183 return emit_RRF4(p, 0xb3f50000, r3, m4, r1, r2);
5187 static UChar *
5188 s390_emit_QAXTR(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
5190 vassert(s390_host_has_dfp);
5191 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
5192 s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "qaxtr", r1, r3, r2, m4);
5194 return emit_RRF4(p, 0xb3fd0000, r3, m4, r1, r2);
5198 static UChar *
5199 s390_emit_RRDTR(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
5201 vassert(s390_host_has_dfp);
5202 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
5203 s390_disasm(ENC5(MNM, FPR, FPR, GPR, UINT), "rrdtr", r1, r3, r2, m4);
5205 return emit_RRF4(p, 0xb3f70000, r3, m4, r1, r2);
5209 static UChar *
5210 s390_emit_RRXTR(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
5212 vassert(s390_host_has_dfp);
5213 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
5214 s390_disasm(ENC5(MNM, FPR, FPR, GPR, UINT), "rrxtr", r1, r3, r2, m4);
5216 return emit_RRF4(p, 0xb3ff0000, r3, m4, r1, r2);
5220 static UChar *
5221 s390_emit_SDTRA(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
5223 vassert(s390_host_has_dfp);
5224 vassert(m4 == 0 || s390_host_has_fpext);
5225 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
5226 if (m4 == 0)
5227 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "sdtr", r1, r2, r3);
5228 else
5229 s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "sdtra", r1, r2, r3, m4);
5232 return emit_RRF4(p, 0xb3d30000, r3, m4, r1, r2);
5236 static UChar *
5237 s390_emit_SXTRA(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
5239 vassert(s390_host_has_dfp);
5240 vassert(m4 == 0 || s390_host_has_fpext);
5241 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
5242 if (m4 == 0)
5243 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "sxtr", r1, r2, r3);
5244 else
5245 s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "sxtra", r1, r2, r3, m4);
5248 return emit_RRF4(p, 0xb3db0000, r3, m4, r1, r2);
5252 static UChar *
5253 s390_emit_SLDT(UChar *p, UChar r3, UChar r1, UChar r2)
5255 vassert(s390_host_has_dfp);
5256 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
5257 s390_disasm(ENC4(MNM, FPR, FPR, UDXB), "sldt", r1, r3, 0, 0, r2);
5259 return emit_RXF(p, 0xED0000000040ULL, r3, 0, r2, 0, r1);
5263 static UChar *
5264 s390_emit_SLXT(UChar *p, UChar r3, UChar r1, UChar r2)
5266 vassert(s390_host_has_dfp);
5267 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
5268 s390_disasm(ENC4(MNM, FPR, FPR, UDXB), "slxt", r1, r3, 0, 0, r2);
5270 return emit_RXF(p, 0xED0000000048ULL, r3, 0, r2, 0, r1);
5274 static UChar *
5275 s390_emit_SRDT(UChar *p, UChar r3, UChar r1, UChar r2)
5277 vassert(s390_host_has_dfp);
5278 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
5279 s390_disasm(ENC4(MNM, FPR, FPR, UDXB), "srdt", r1, r3, 0, 0, r2);
5281 return emit_RXF(p, 0xED0000000041ULL, r3, 0, r2, 0, r1);
5285 static UChar *
5286 s390_emit_SRXT(UChar *p, UChar r3, UChar r1, UChar r2)
5288 vassert(s390_host_has_dfp);
5289 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
5290 s390_disasm(ENC4(MNM, FPR, FPR, UDXB), "srxt", r1, r3, 0, 0, r2);
5292 return emit_RXF(p, 0xED0000000049ULL, r3, 0, r2, 0, r1);
5296 static UChar *
5297 s390_emit_LOCGR(UChar *p, UChar m3, UChar r1, UChar r2)
5299 vassert(s390_host_has_lsc);
5300 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
5301 s390_disasm(ENC4(MNM, GPR, GPR, UINT), "locgr", r1, r2, m3);
5303 return emit_RRF3(p, 0xb9e20000, m3, r1, r2);
5307 static UChar *
5308 s390_emit_LOC(UChar *p, UChar r1, UChar m3, UChar b2, UShort dl2, UChar dh2)
5310 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
5311 s390_disasm(ENC4(MNM, GPR, UINT, SDXB), "loc", r1, m3, dh2, dl2, 0, b2);
5313 return emit_RSY(p, 0xeb00000000f2ULL, r1, m3, b2, dl2, dh2);
5317 static UChar *
5318 s390_emit_LOCG(UChar *p, UChar r1, UChar m3, UChar b2, UShort dl2, UChar dh2)
5320 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
5321 s390_disasm(ENC4(MNM, GPR, UINT, SDXB), "locg", r1, m3, dh2, dl2, 0, b2);
5323 return emit_RSY(p, 0xeb00000000e2ULL, r1, m3, b2, dl2, dh2);
5326 static UChar *
5327 s390_emit_LOCGHI(UChar *p, UChar r1, UShort i2, UChar m3)
5329 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
5330 s390_disasm(ENC4(MNM, GPR, INT, UINT), "locghi", r1, (Int)(Short)i2, m3);
5332 return emit_RIE(p, 0xec0000000046ULL, r1, i2, m3);
5335 static UChar *
5336 s390_emit_RISBG(UChar *p, UChar r1, UChar r2, UChar i3, Char i4, UChar i5)
5338 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
5339 s390_disasm(ENC6(MNM, GPR, GPR, UINT, UINT, UINT),
5340 "risbg", r1, r2, i3, i4, i5);
5342 return emit_RIEf(p, 0xec0000000055ULL, r1, r2, i3, i4, i5);
5346 /* Provide a symbolic name for register "R0" */
5347 #define R0 0
5349 /* Split up a 20-bit displacement into its high and low piece
5350 suitable for passing as function arguments */
5351 #define DISP20(d) (((UInt)d) & 0xFFF), ((((UInt)d) >> 12) & 0xFF)
5353 /*---------------------------------------------------------------*/
5354 /*--- Helper functions ---*/
5355 /*---------------------------------------------------------------*/
5357 static __inline__ Bool
5358 uint_fits_signed_16bit(UInt val)
5360 UInt v = val & 0xFFFFu;
5362 /* sign extend */
5363 v = (Int)(v << 16) >> 16;
5365 return val == v;
5369 static __inline__ Bool
5370 ulong_fits_signed_16bit(ULong val)
5372 ULong v = val & 0xFFFFu;
5374 /* sign extend */
5375 v = (Long)(v << 48) >> 48;
5377 return val == v;
5381 static __inline__ Bool
5382 ulong_fits_signed_32bit(ULong val)
5384 ULong v = val & 0xFFFFFFFFu;
5386 /* sign extend */
5387 v = (Long)(v << 32) >> 32;
5389 return val == v;
5393 static __inline__ Bool
5394 ulong_fits_unsigned_32bit(ULong val)
5396 return (val & 0xFFFFFFFFu) == val;
5400 /* Load a 64-bit immediate VAL into register REG. */
5401 static UChar *
5402 s390_emit_load_64imm(UChar *p, UChar reg, ULong val)
5404 if (ulong_fits_signed_16bit(val)) {
5405 return s390_emit_LGHI(p, reg, val);
5408 if (s390_host_has_eimm) {
5409 if (ulong_fits_unsigned_32bit(val)) {
5410 return s390_emit_LLILF(p, reg, val);
5412 if (ulong_fits_signed_32bit(val)) {
5413 /* LGFI's sign extension will recreate the correct 64-bit value */
5414 return s390_emit_LGFI(p, reg, val);
5416 /* Do it in two steps: upper half [0:31] and lower half [32:63] */
5417 p = s390_emit_IIHF(p, reg, val >> 32);
5418 return s390_emit_IILF(p, reg, val & 0xFFFFFFFF);
5421 /* Fall back */
5422 if (ulong_fits_unsigned_32bit(val)) {
5423 p = s390_emit_LLILH(p, reg, (val >> 16) & 0xFFFF); /* sets val[32:47]
5424 val[0:31] = 0 */
5425 p = s390_emit_IILL(p, reg, val & 0xFFFF); /* sets val[48:63] */
5426 return p;
5429 p = s390_emit_IIHH(p, reg, (val >> 48) & 0xFFFF);
5430 p = s390_emit_IIHL(p, reg, (val >> 32) & 0xFFFF);
5431 p = s390_emit_IILH(p, reg, (val >> 16) & 0xFFFF);
5432 p = s390_emit_IILL(p, reg, val & 0xFFFF);
5434 return p;
5437 /* Load a 32-bit immediate VAL into register REG. */
5438 static UChar *
5439 s390_emit_load_32imm(UChar *p, UChar reg, UInt val)
5441 if (uint_fits_signed_16bit(val)) {
5442 /* LHI's sign extension will recreate the correct 32-bit value */
5443 return s390_emit_LHI(p, reg, val);
5445 if (s390_host_has_eimm) {
5446 return s390_emit_IILF(p, reg, val);
5448 /* val[0:15] --> (val >> 16) & 0xFFFF
5449 val[16:31] --> val & 0xFFFF */
5450 p = s390_emit_IILH(p, reg, (val >> 16) & 0xFFFF);
5451 return s390_emit_IILL(p, reg, val & 0xFFFF);
5454 /*------------------------------------------------------------*/
5455 /*--- Wrapper functions ---*/
5456 /*------------------------------------------------------------*/
5458 /* r1[32:63],r1+1[32:63] = r1+1[32:63] * memory[op2addr][0:31] */
5459 static UChar *
5460 s390_emit_MFYw(UChar *p, UChar r1, UChar x, UChar b, UShort dl, UChar dh)
5462 if (s390_host_has_gie) {
5463 return s390_emit_MFY(p, r1, x, b, dl, dh);
5466 /* Load from memory into R0, then MULTIPLY with R1 */
5467 p = s390_emit_LY(p, R0, x, b, dl, dh);
5468 return s390_emit_MR(p, r1, R0);
5471 /* r1[32:63] = r1[32:63] * memory[op2addr][0:15] */
5472 static UChar *
5473 s390_emit_MHYw(UChar *p, UChar r1, UChar x, UChar b, UShort dl, UChar dh)
5475 if (s390_host_has_gie) {
5476 return s390_emit_MHY(p, r1, x, b, dl, dh);
5479 /* Load from memory into R0, then MULTIPLY with R1 */
5480 p = s390_emit_LHY(p, R0, x, b, dl, dh);
5481 return s390_emit_MSR(p, r1, R0);
5484 /* r1[32:63] = r1[32:63] * i2 */
5485 static UChar *
5486 s390_emit_MSFIw(UChar *p, UChar r1, UInt i2)
5488 if (s390_host_has_gie) {
5489 return s390_emit_MSFI(p, r1, i2);
5492 /* Load I2 into R0; then MULTIPLY R0 with R1 */
5493 p = s390_emit_load_32imm(p, R0, i2);
5494 return s390_emit_MSR(p, r1, R0);
5498 /* r1[32:63] = r1[32:63] & i2 */
5499 static UChar *
5500 s390_emit_NILFw(UChar *p, UChar r1, UInt i2)
5502 if (s390_host_has_eimm) {
5503 return s390_emit_NILF(p, r1, i2);
5506 /* Load I2 into R0; then AND R0 with R1 */
5507 p = s390_emit_load_32imm(p, R0, i2);
5508 return s390_emit_NR(p, r1, R0);
5512 /* r1[32:63] = r1[32:63] | i2 */
5513 static UChar *
5514 s390_emit_OILFw(UChar *p, UChar r1, UInt i2)
5516 if (s390_host_has_eimm) {
5517 return s390_emit_OILF(p, r1, i2);
5520 /* Load I2 into R0; then AND R0 with R1 */
5521 p = s390_emit_load_32imm(p, R0, i2);
5522 return s390_emit_OR(p, r1, R0);
5526 /* r1[32:63] = r1[32:63] ^ i2 */
5527 static UChar *
5528 s390_emit_XILFw(UChar *p, UChar r1, UInt i2)
5530 if (s390_host_has_eimm) {
5531 return s390_emit_XILF(p, r1, i2);
5534 /* Load I2 into R0; then AND R0 with R1 */
5535 p = s390_emit_load_32imm(p, R0, i2);
5536 return s390_emit_XR(p, r1, R0);
5540 /* r1[32:63] = sign_extend(r2[56:63]) */
5541 static UChar *
5542 s390_emit_LBRw(UChar *p, UChar r1, UChar r2)
5544 if (s390_host_has_eimm) {
5545 return s390_emit_LBR(p, r1, r2);
5548 p = s390_emit_LR(p, r1, r2); /* r1 = r2 */
5549 p = s390_emit_SLL(p, r1, R0, 24); /* r1 = r1 << 24 */
5550 return s390_emit_SRA(p, r1, R0, 24); /* r1 = r1 >>a 24 */
5554 /* r1[0:63] = sign_extend(r2[56:63]) */
5555 static UChar *
5556 s390_emit_LGBRw(UChar *p, UChar r1, UChar r2)
5558 if (s390_host_has_eimm) {
5559 return s390_emit_LGBR(p, r1, r2);
5562 p = s390_emit_LR(p, r1, r2); /* r1 = r2 */
5563 p = s390_emit_SLLG(p, r1, r1, R0, DISP20(56)); /* r1 = r1 << 56 */
5564 return s390_emit_SRAG(p, r1, r1, R0, DISP20(56)); /* r1 = r1 >>a 56 */
5568 /* r1[32:63] = sign_extend(r2[48:63]) */
5569 static UChar *
5570 s390_emit_LHRw(UChar *p, UChar r1, UChar r2)
5572 if (s390_host_has_eimm) {
5573 return s390_emit_LHR(p, r1, r2);
5576 p = s390_emit_LR(p, r1, r2); /* r1 = r2 */
5577 p = s390_emit_SLL(p, r1, R0, 16); /* r1 = r1 << 16 */
5578 return s390_emit_SRA(p, r1, R0, 16); /* r1 = r1 >>a 16 */
5582 /* r1[0:63] = sign_extend(r2[48:63]) */
5583 static UChar *
5584 s390_emit_LGHRw(UChar *p, UChar r1, UChar r2)
5586 if (s390_host_has_eimm) {
5587 return s390_emit_LGHR(p, r1, r2);
5590 p = s390_emit_LR(p, r1, r2); /* r1 = r2 */
5591 p = s390_emit_SLLG(p, r1, r1, R0, DISP20(48)); /* r1 = r1 << 48 */
5592 return s390_emit_SRAG(p, r1, r1, R0, DISP20(48)); /* r1 = r1 >>a 48 */
5596 /* r1[0:63] = sign_extend(i2) */
5597 static UChar *
5598 s390_emit_LGFIw(UChar *p, UChar r1, UInt i2)
5600 if (s390_host_has_eimm) {
5601 return s390_emit_LGFI(p, r1, i2);
5604 p = s390_emit_load_32imm(p, R0, i2);
5605 return s390_emit_LGFR(p, r1, R0);
5609 /* r1[32:63] = zero_extend($r2[56:63]) */
5610 static UChar *
5611 s390_emit_LLCRw(UChar *p, UChar r1, UChar r2)
5613 if (s390_host_has_eimm) {
5614 return s390_emit_LLCR(p, r1, r2);
5617 p = s390_emit_LR(p, r1, r2);
5618 p = s390_emit_LHI(p, R0, 0xFF);
5619 return s390_emit_NR(p, r1, R0);
5623 /* r1[0:63] = zero_extend($r2[56:63]) */
5624 static UChar *
5625 s390_emit_LLGCRw(UChar *p, UChar r1, UChar r2)
5627 if (s390_host_has_eimm) {
5628 return s390_emit_LLGCR(p, r1, r2);
5631 p = s390_emit_LR(p, r1, r2);
5632 p = s390_emit_LLILL(p, R0, 0xFF);
5633 return s390_emit_NGR(p, r1, R0);
5637 /* r1[32:63] = zero_extend(r2[48:63]) */
5638 static UChar *
5639 s390_emit_LLHRw(UChar *p, UChar r1, UChar r2)
5641 if (s390_host_has_eimm) {
5642 return s390_emit_LLHR(p, r1, r2);
5645 p = s390_emit_LR(p, r1, r2);
5646 p = s390_emit_LLILL(p, R0, 0xFFFF);
5647 return s390_emit_NR(p, r1, R0);
5651 /* r1[0:63] = zero_extend(r2[48:63]) */
5652 static UChar *
5653 s390_emit_LLGHRw(UChar *p, UChar r1, UChar r2)
5655 if (s390_host_has_eimm) {
5656 return s390_emit_LLGHR(p, r1, r2);
5659 p = s390_emit_LR(p, r1, r2);
5660 p = s390_emit_LLILL(p, R0, 0xFFFF);
5661 return s390_emit_NGR(p, r1, R0);
5665 /* r1[32:63] = zero_extend(mem[op2addr][0:7]) */
5666 static UChar *
5667 s390_emit_LLCw(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl, UChar dh)
5669 if (s390_host_has_eimm) {
5670 return s390_emit_LLC(p, r1, x2, b2, dl, dh);
5673 if (dh == 0) {
5674 p = s390_emit_IC(p, r1, x2, b2, dl);
5675 } else {
5676 p = s390_emit_ICY(p, r1, x2, b2, dl, dh);
5678 p = s390_emit_LLILL(p, R0, 0xFF);
5679 return s390_emit_NR(p, r1, R0);
5683 /* r1[32:63] = zero_extend(mem[op2addr][0:15]) */
5684 static UChar *
5685 s390_emit_LLHw(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl, UChar dh)
5687 if (s390_host_has_eimm) {
5688 return s390_emit_LLH(p, r1, x2, b2, dl, dh);
5691 p = s390_emit_LLGH(p, r1, x2, b2, dl, dh);
5692 p = s390_emit_LLILL(p, R0, 0xFFFF);
5693 return s390_emit_NR(p, r1, R0);
5697 /* r1[0:63] = zero_extend(i2) */
5698 static UChar *
5699 s390_emit_LLILFw(UChar *p, UChar r1, UInt i2)
5701 if (s390_host_has_eimm) {
5702 return s390_emit_LLILF(p, r1, i2);
5705 p = s390_emit_LLILH(p, r1, (i2 >> 16) & 0xFFFF); /* i2[0:15] */
5706 return s390_emit_OILL(p, r1, i2 & 0xFFFF);
5710 /* r1[32:63] = r1[32:63] + i2 */
5711 static UChar *
5712 s390_emit_AFIw(UChar *p, UChar r1, UInt i2)
5714 if (s390_host_has_eimm) {
5715 return s390_emit_AFI(p, r1, i2);
5717 /* Load 32 bit immediate to R0 then add */
5718 p = s390_emit_load_32imm(p, R0, i2);
5719 return s390_emit_AR(p, r1, R0);
5723 /* r1[32:63] = r1[32:63] - i2 */
5724 static UChar *
5725 s390_emit_SLFIw(UChar *p, UChar r1, UInt i2)
5727 if (s390_host_has_eimm) {
5728 return s390_emit_SLFI(p, r1, i2);
5731 /* Load 32 bit immediate to R0 then subtract */
5732 p = s390_emit_load_32imm(p, R0, i2);
5733 return s390_emit_SR(p, r1, R0);
5737 /* r1[0:63] = r1[0:63] - zero_extend(i2) */
5738 static UChar *
5739 s390_emit_SLGFIw(UChar *p, UChar r1, UInt i2)
5741 if (s390_host_has_eimm) {
5742 return s390_emit_SLGFI(p, r1, i2);
5745 /* Load zero-extended 32 bit immediate to R0 then subtract */
5746 p = s390_emit_load_64imm(p, R0, i2);
5747 return s390_emit_SGR(p, r1, R0);
5751 static UChar *
5752 s390_emit_LTw(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl, UChar dh)
5754 if (s390_host_has_eimm) {
5755 return s390_emit_LT(p, r1, x2, b2, dl, dh);
5757 /* Load 32 bit from memory to R0 then compare */
5758 if (dh == 0) {
5759 p = s390_emit_L(p, R0, x2, b2, dl);
5760 } else {
5761 p = s390_emit_LY(p, R0, x2, b2, dl, dh);
5763 return s390_emit_LTR(p, r1, R0);
5767 static UChar *
5768 s390_emit_LTGw(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl, UChar dh)
5770 if (s390_host_has_eimm) {
5771 return s390_emit_LTG(p, r1, x2, b2, dl, dh);
5773 /* Load 64 bit from memory to R0 then compare */
5774 p = s390_emit_LG(p, R0, x2, b2, dl, dh);
5775 return s390_emit_LTGR(p, r1, R0);
5779 static UChar *
5780 s390_emit_CFIw(UChar *p, UChar r1, UInt i2)
5782 if (s390_host_has_eimm) {
5783 return s390_emit_CFI(p, r1, i2);
5785 /* Load 32 bit immediate to R0 then compare */
5786 p = s390_emit_load_32imm(p, R0, i2);
5787 return s390_emit_CR(p, r1, R0);
5791 static UChar *
5792 s390_emit_CLFIw(UChar *p, UChar r1, UInt i2)
5794 if (s390_host_has_eimm) {
5795 return s390_emit_CLFI(p, r1, i2);
5797 /* Load 32 bit immediate to R0 then compare */
5798 p = s390_emit_load_32imm(p, R0, i2);
5799 return s390_emit_CLR(p, r1, R0);
5803 static UChar *
5804 s390_emit_LGDRw(UChar *p, UChar r1, UChar r2)
5806 if (s390_host_has_fgx) {
5807 return s390_emit_LGDR(p, r1, r2);
5810 /* Store the FPR at memory[sp - 8]. This is safe because SP grows towards
5811 smaller addresses and is 8-byte aligned. Then load the GPR from that
5812 memory location/ */
5813 p = s390_emit_STDY(p, r2, R0, S390_REGNO_STACK_POINTER, DISP20(-8));
5814 return s390_emit_LG(p, r1, R0, S390_REGNO_STACK_POINTER, DISP20(-8));
5818 static UChar *
5819 s390_emit_LDGRw(UChar *p, UChar r1, UChar r2)
5821 if (s390_host_has_fgx) {
5822 return s390_emit_LDGR(p, r1, r2);
5825 /* Store the GPR at memory[sp - 8]. This is safe because SP grows towards
5826 smaller addresses and is 8-byte aligned. Then load the FPR from that
5827 memory location/ */
5828 p = s390_emit_STG(p, r2, R0, S390_REGNO_STACK_POINTER, DISP20(-8));
5829 return s390_emit_LDY(p, r1, R0, S390_REGNO_STACK_POINTER, DISP20(-8));
5833 static UChar *
5834 s390_emit_VL(UChar *p, UChar v1, UChar x2, UChar b2, UShort d2)
5836 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
5837 s390_disasm(ENC3(MNM, VR, UDXB), "vl", v1, d2, x2, b2);
5839 return emit_VRX(p, 0xE70000000006ULL, v1, x2, b2, d2, 0);
5842 static UChar *
5843 s390_emit_VLR(UChar *p, UChar v1, UChar v2)
5845 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
5846 s390_disasm(ENC3(MNM, VR, UDXB), "vlr", v1, v2);
5848 return emit_VRR_VV(p, 0xE70000000056ULL, v1, v2);
5852 static UChar *
5853 s390_emit_VLREP(UChar *p, UChar v1, UChar x2, UChar b2, UShort d2, UShort m3)
5855 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
5856 s390_disasm(ENC4(MNM, VR, UDXB, UINT), "vlrep", v1, d2, x2, b2, m3);
5858 return emit_VRX(p, 0xE70000000005ULL, v1, x2, b2, d2, m3);
5862 static UChar *
5863 s390_emit_VST(UChar *p, UChar v1, UChar x2, UChar b2, UShort d2)
5865 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
5866 s390_disasm(ENC3(MNM, VR, UDXB), "vst", v1, d2, x2, b2);
5868 return emit_VRX(p, 0xE7000000000eULL, v1, x2, b2, d2, 0);
5872 static UChar *
5873 s390_emit_VLGV(UChar *p, UChar r1, UChar b2, UShort d2, UChar v3, UChar m4)
5875 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
5876 s390_disasm(ENC5(MNM, GPR, UDXB, VR, UINT), "vlgv", r1, d2, 0, b2, v3, m4);
5878 return emit_VRS(p, 0xE70000000021ULL, r1, b2, d2, v3, m4);
5882 static UChar *
5883 s390_emit_VLVG(UChar *p, UChar v1, UChar b2, UShort d2, UChar r3, UChar m4)
5885 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
5886 s390_disasm(ENC5(MNM, VR, UDXB, GPR, UINT), "vlvg", v1, d2, 0, b2, r3, m4);
5888 return emit_VRS(p, 0xE70000000022ULL, v1, b2, d2, r3, m4);
5892 static UChar *
5893 s390_emit_VPERM(UChar *p, UChar v1, UChar v2, UChar v3, UChar v4)
5895 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
5896 s390_disasm(ENC5(MNM, VR, VR, VR, VR), "vperm", v1, v2, v3, v4);
5898 return emit_VRR_VVVV(p, 0xE7000000008cULL, v1, v2, v3, v4);
5901 static UChar *
5902 s390_emit_VO(UChar *p, UChar v1, UChar v2, UChar v3)
5904 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
5905 s390_disasm(ENC4(MNM, VR, VR, VR), "vo", v1, v2, v3);
5907 return emit_VRR_VVV(p, 0xE7000000006aULL, v1, v2, v3);
5910 static UChar *
5911 s390_emit_VOC(UChar *p, UChar v1, UChar v2, UChar v3)
5913 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
5914 s390_disasm(ENC4(MNM, VR, VR, VR), "voc", v1, v2, v3);
5916 return emit_VRR_VVV(p, 0xE7000000006fULL, v1, v2, v3);
5919 static UChar *
5920 s390_emit_VX(UChar *p, UChar v1, UChar v2, UChar v3)
5922 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
5923 s390_disasm(ENC4(MNM, VR, VR, VR), "vx", v1, v2, v3);
5925 return emit_VRR_VVV(p, 0xE7000000006dULL, v1, v2, v3);
5928 static UChar *
5929 s390_emit_VN(UChar *p, UChar v1, UChar v2, UChar v3)
5931 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
5932 s390_disasm(ENC4(MNM, VR, VR, VR), "vn", v1, v2, v3);
5934 return emit_VRR_VVV(p, 0xE70000000068ULL, v1, v2, v3);
5937 static UChar*
5938 s390_emit_VCEQ(UChar *p, UChar v1, UChar v2, UChar v3, UChar m4)
5940 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
5941 s390_disasm(ENC5(MNM, VR, VR, VR, UINT), "vceq", v1, v2, v3, m4);
5943 return emit_VRR_VVVM(p, 0xE700000000f8ULL, v1, v2, v3, m4);
5947 static UChar *
5948 s390_emit_VGBM(UChar *p, UChar v1, UShort i2)
5950 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
5951 s390_disasm(ENC3(MNM, VR, UINT), "vgbm", v1, i2);
5953 return emit_VRI_VI(p, 0xE70000000044ULL, v1, i2);
5957 static UChar *
5958 s390_emit_VPK(UChar *p, UChar v1, UChar v2, UChar v3, UChar m4)
5960 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
5961 s390_disasm(ENC5(MNM, VR, VR, VR, UINT), "vpk", v1, v2, v3, m4);
5963 return emit_VRR_VVVM(p, 0xE70000000094ULL, v1, v2, v3, m4);
5967 static UChar *
5968 s390_emit_VPKS(UChar *p, UChar v1, UChar v2, UChar v3, UChar m4)
5970 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
5971 s390_disasm(ENC6(MNM, VR, VR, VR, UINT, UINT), "vpks", v1, v2, v3, m4, 0);
5973 return emit_VRR_VVVM(p, 0xE70000000097ULL, v1, v2, v3, m4);
5977 static UChar *
5978 s390_emit_VPKLS(UChar *p, UChar v1, UChar v2, UChar v3, UChar m4)
5980 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
5981 s390_disasm(ENC6(MNM, VR, VR, VR, UINT, UINT), "vpkls", v1, v2, v3, m4, 0);
5983 return emit_VRR_VVVM(p, 0xE70000000095ULL, v1, v2, v3, m4);
5987 static UChar *
5988 s390_emit_VREP(UChar *p, UChar v1, UChar v3, UShort i2, UChar m4)
5990 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
5991 s390_disasm(ENC5(MNM, VR, VR, UINT, UINT), "vrep", v1, v3, i2, m4);
5993 return emit_VRI_VVMM(p, 0xE7000000004DULL, v1, v3, i2, m4);
5997 static UChar *
5998 s390_emit_VREPI(UChar *p, UChar v1, UShort i2, UChar m3)
6000 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
6001 s390_disasm(ENC4(MNM, VR, UINT, UINT), "vrepi", v1, i2, m3);
6003 return emit_VRI_VIM(p, 0xE70000000045ULL, v1, i2, m3);
6007 static UChar *
6008 s390_emit_VUPH(UChar *p, UChar v1, UChar v3, UChar m3)
6010 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
6011 s390_disasm(ENC4(MNM, VR, VR, UINT), "vuph", v1, v3, m3);
6013 return emit_VRR_VVM(p, 0xE700000000D7ULL, v1, v3, m3);
6017 static UChar *
6018 s390_emit_VUPLH(UChar *p, UChar v1, UChar v3, UChar m3)
6020 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
6021 s390_disasm(ENC4(MNM, VR, VR, UINT), "vuplh", v1, v3, m3);
6023 return emit_VRR_VVM(p, 0xE700000000D5ULL, v1, v3, m3);
6027 static UChar*
6028 s390_emit_VMRH(UChar *p, UChar v1, UChar v2, UChar v3, UChar m4)
6030 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
6031 s390_disasm(ENC5(MNM, VR, VR, VR, UINT), "vmrh", v1, v2, v3, m4);
6033 return emit_VRR_VVVM(p, 0xE70000000061ULL, v1, v2, v3, m4);
6037 static UChar*
6038 s390_emit_VMRL(UChar *p, UChar v1, UChar v2, UChar v3, UChar m4)
6040 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
6041 s390_disasm(ENC5(MNM, VR, VR, VR, UINT), "vmrl", v1, v2, v3, m4);
6043 return emit_VRR_VVVM(p, 0xE70000000060ULL, v1, v2, v3, m4);
6046 static UChar *
6047 s390_emit_VA(UChar *p, UChar v1, UChar v2, UChar v3, UChar m4)
6049 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
6050 s390_disasm(ENC5(MNM, VR, VR, VR, UINT), "va", v1, v2, v3, m4);
6052 return emit_VRR_VVVM(p, 0xE700000000f3ULL, v1, v2, v3, m4);
6055 static UChar *
6056 s390_emit_VS(UChar *p, UChar v1, UChar v2, UChar v3, UChar m4)
6058 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
6059 s390_disasm(ENC5(MNM, VR, VR, VR, UINT), "vs", v1, v2, v3, m4);
6061 return emit_VRR_VVVM(p, 0xE700000000f7ULL, v1, v2, v3, m4);
6064 static UChar *
6065 s390_emit_VNO(UChar *p, UChar v1, UChar v2, UChar v3)
6067 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
6068 s390_disasm(ENC4(MNM, VR, VR, VR), "vno", v1, v2, v3);
6070 return emit_VRR_VVV(p, 0xE7000000006bULL, v1, v2, v3);
6073 static UChar *
6074 s390_emit_VCH(UChar *p, UChar v1, UChar v2, UChar v3, UChar m4)
6076 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
6077 s390_disasm(ENC5(MNM, VR, VR, VR, UINT), "vch", v1, v2, v3, m4);
6079 return emit_VRR_VVVM(p, 0xE700000000fbULL, v1, v2, v3, m4);
6082 static UChar *
6083 s390_emit_VCHL(UChar *p, UChar v1, UChar v2, UChar v3, UChar m4)
6085 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
6086 s390_disasm(ENC5(MNM, VR, VR, VR, UINT), "vchl", v1, v2, v3, m4);
6088 return emit_VRR_VVVM(p, 0xE700000000f9ULL, v1, v2, v3, m4);
6091 static UChar *
6092 s390_emit_VCLZ(UChar *p, UChar v1, UChar v2, UChar m4)
6094 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
6095 s390_disasm(ENC4(MNM, VR, VR, UINT), "vclz", v1, v2, m4);
6097 return emit_VRR_VVM(p, 0xE70000000053ULL, v1, v2, m4);
6100 static UChar *
6101 s390_emit_VCTZ(UChar *p, UChar v1, UChar v2, UChar m4)
6103 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
6104 s390_disasm(ENC4(MNM, VR, VR, UINT), "vctz", v1, v2, m4);
6106 return emit_VRR_VVM(p, 0xE70000000052ULL, v1, v2, m4);
6109 static UChar *
6110 s390_emit_VPOPCT(UChar *p, UChar v1, UChar v2, UChar m4)
6112 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
6113 s390_disasm(ENC4(MNM, VR, VR, UINT), "vpopct", v1, v2, m4);
6115 return emit_VRR_VVM(p, 0xE70000000050ULL, v1, v2, m4);
6118 static UChar *
6119 s390_emit_VMX(UChar *p, UChar v1, UChar v2, UChar v3, UChar m4)
6121 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
6122 s390_disasm(ENC5(MNM, VR, VR, VR, UINT), "vmx", v1, v2, v3, m4);
6124 return emit_VRR_VVVM(p, 0xE700000000ffULL, v1, v2, v3, m4);
6127 static UChar *
6128 s390_emit_VMXL(UChar *p, UChar v1, UChar v2, UChar v3, UChar m4)
6130 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
6131 s390_disasm(ENC5(MNM, VR, VR, VR, UINT), "vmxl", v1, v2, v3, m4);
6133 return emit_VRR_VVVM(p, 0xE700000000fdULL, v1, v2, v3, m4);
6136 static UChar *
6137 s390_emit_VMN(UChar *p, UChar v1, UChar v2, UChar v3, UChar m4)
6139 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
6140 s390_disasm(ENC5(MNM, VR, VR, VR, UINT), "vmn", v1, v2, v3, m4);
6142 return emit_VRR_VVVM(p, 0xE700000000feULL, v1, v2, v3, m4);
6145 static UChar *
6146 s390_emit_VMNL(UChar *p, UChar v1, UChar v2, UChar v3, UChar m4)
6148 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
6149 s390_disasm(ENC5(MNM, VR, VR, VR, UINT), "vmnl", v1, v2, v3, m4);
6151 return emit_VRR_VVVM(p, 0xE700000000fcULL, v1, v2, v3, m4);
6154 static UChar *
6155 s390_emit_VAVG(UChar *p, UChar v1, UChar v2, UChar v3, UChar m4)
6157 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
6158 s390_disasm(ENC5(MNM, VR, VR, VR, UINT), "vavg", v1, v2, v3, m4);
6160 return emit_VRR_VVVM(p, 0xE700000000f2ULL, v1, v2, v3, m4);
6163 static UChar *
6164 s390_emit_VAVGL(UChar *p, UChar v1, UChar v2, UChar v3, UChar m4)
6166 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
6167 s390_disasm(ENC5(MNM, VR, VR, VR, UINT), "vavgl", v1, v2, v3, m4);
6169 return emit_VRR_VVVM(p, 0xE700000000f0ULL, v1, v2, v3, m4);
6172 static UChar *
6173 s390_emit_VLP(UChar *p, UChar v1, UChar v2, UChar m3)
6175 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
6176 s390_disasm(ENC4(MNM, VR, VR, UINT), "vlp", v1, v2, m3);
6178 return emit_VRR_VVM(p, 0xE700000000DFULL, v1, v2, m3);
6181 static UChar *
6182 s390_emit_VMH(UChar *p, UChar v1, UChar v2, UChar v3, UChar m4)
6184 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
6185 s390_disasm(ENC5(MNM, VR, VR, VR, UINT), "vmh", v1, v2, v3, m4);
6187 return emit_VRR_VVVM(p, 0xE700000000a3ULL, v1, v2, v3, m4);
6190 static UChar *
6191 s390_emit_VMLH(UChar *p, UChar v1, UChar v2, UChar v3, UChar m4)
6193 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
6194 s390_disasm(ENC5(MNM, VR, VR, VR, UINT), "vmlh", v1, v2, v3, m4);
6196 return emit_VRR_VVVM(p, 0xE700000000a1ULL, v1, v2, v3, m4);
6199 static UChar *
6200 s390_emit_VML(UChar *p, UChar v1, UChar v2, UChar v3, UChar m4)
6202 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
6203 s390_disasm(ENC5(MNM, VR, VR, VR, UINT), "vml", v1, v2, v3, m4);
6205 return emit_VRR_VVVM(p, 0xE700000000a2ULL, v1, v2, v3, m4);
6208 static UChar *
6209 s390_emit_VME(UChar *p, UChar v1, UChar v2, UChar v3, UChar m4)
6211 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
6212 s390_disasm(ENC5(MNM, VR, VR, VR, UINT), "vme", v1, v2, v3, m4);
6214 return emit_VRR_VVVM(p, 0xE700000000a6ULL, v1, v2, v3, m4);
6217 static UChar *
6218 s390_emit_VMLE(UChar *p, UChar v1, UChar v2, UChar v3, UChar m4)
6220 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
6221 s390_disasm(ENC5(MNM, VR, VR, VR, UINT), "vmle", v1, v2, v3, m4);
6223 return emit_VRR_VVVM(p, 0xE700000000a4ULL, v1, v2, v3, m4);
6226 static UChar *
6227 s390_emit_VESLV(UChar *p, UChar v1, UChar v2, UChar v3, UChar m4)
6229 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
6230 s390_disasm(ENC5(MNM, VR, VR, VR, UINT), "veslv", v1, v2, v3, m4);
6232 return emit_VRR_VVVM(p, 0xE70000000070ULL, v1, v2, v3, m4);
6235 static UChar *
6236 s390_emit_VESRAV(UChar *p, UChar v1, UChar v2, UChar v3, UChar m4)
6238 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
6239 s390_disasm(ENC5(MNM, VR, VR, VR, UINT), "vesrav", v1, v2, v3, m4);
6241 return emit_VRR_VVVM(p, 0xE7000000007aULL, v1, v2, v3, m4);
6244 static UChar *
6245 s390_emit_VESRLV(UChar *p, UChar v1, UChar v2, UChar v3, UChar m4)
6247 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
6248 s390_disasm(ENC5(MNM, VR, VR, VR, UINT), "vesrlv", v1, v2, v3, m4);
6250 return emit_VRR_VVVM(p, 0xE70000000078ULL, v1, v2, v3, m4);
6253 static UChar *
6254 s390_emit_VESL(UChar *p, UChar v1, UChar b2, UShort d2, UChar v3, UChar m4)
6256 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
6257 s390_disasm(ENC5(MNM, VR, UDXB, VR, UINT), "vesl", v1, d2, 0, b2, v3, m4);
6259 return emit_VRS(p, 0xE70000000030ULL, v1, b2, d2, v3, m4);
6262 static UChar *
6263 s390_emit_VESRA(UChar *p, UChar v1, UChar b2, UShort d2, UChar v3, UChar m4)
6265 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
6266 s390_disasm(ENC5(MNM, VR, UDXB, VR, UINT), "vesra", v1, d2, 0, b2, v3, m4);
6268 return emit_VRS(p, 0xE7000000003aULL, v1, b2, d2, v3, m4);
6271 static UChar *
6272 s390_emit_VESRL(UChar *p, UChar v1, UChar b2, UShort d2, UChar v3, UChar m4)
6274 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
6275 s390_disasm(ENC5(MNM, VR, UDXB, VR, UINT), "vesrl", v1, d2, 0, b2, v3, m4);
6277 return emit_VRS(p, 0xE70000000038ULL, v1, b2, d2, v3, m4);
6280 static UChar *
6281 s390_emit_VERLLV(UChar *p, UChar v1, UChar v2, UChar v3, UChar m4)
6283 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
6284 s390_disasm(ENC5(MNM, VR, VR, VR, UINT), "verllv", v1, v2, v3, m4);
6286 return emit_VRR_VVVM(p, 0xE70000000073ULL, v1, v2, v3, m4);
6289 static UChar *
6290 s390_emit_VSL(UChar *p, UChar v1, UChar v2, UChar v3)
6292 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
6293 s390_disasm(ENC4(MNM, VR, VR, VR), "vsl", v1, v2, v3);
6295 return emit_VRR_VVV(p, 0xE70000000074ULL, v1, v2, v3);
6298 static UChar *
6299 s390_emit_VSRL(UChar *p, UChar v1, UChar v2, UChar v3)
6301 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
6302 s390_disasm(ENC4(MNM, VR, VR, VR), "vsrl", v1, v2, v3);
6304 return emit_VRR_VVV(p, 0xE7000000007cULL, v1, v2, v3);
6307 static UChar *
6308 s390_emit_VSRA(UChar *p, UChar v1, UChar v2, UChar v3)
6310 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
6311 s390_disasm(ENC4(MNM, VR, VR, VR), "vsra", v1, v2, v3);
6313 return emit_VRR_VVV(p, 0xE7000000007eULL, v1, v2, v3);
6316 static UChar *
6317 s390_emit_VSLB(UChar *p, UChar v1, UChar v2, UChar v3)
6319 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
6320 s390_disasm(ENC4(MNM, VR, VR, VR), "vslb", v1, v2, v3);
6322 return emit_VRR_VVV(p, 0xE70000000075ULL, v1, v2, v3);
6325 static UChar *
6326 s390_emit_VSRLB(UChar *p, UChar v1, UChar v2, UChar v3)
6328 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
6329 s390_disasm(ENC4(MNM, VR, VR, VR), "vsrlb", v1, v2, v3);
6331 return emit_VRR_VVV(p, 0xE7000000007dULL, v1, v2, v3);
6334 static UChar *
6335 s390_emit_VSRAB(UChar *p, UChar v1, UChar v2, UChar v3)
6337 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
6338 s390_disasm(ENC4(MNM, VR, VR, VR), "vsrab", v1, v2, v3);
6340 return emit_VRR_VVV(p, 0xE7000000007fULL, v1, v2, v3);
6343 static UChar *
6344 s390_emit_VSUM(UChar *p, UChar v1, UChar v2, UChar v3, UChar m4)
6346 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
6347 s390_disasm(ENC5(MNM, VR, VR, VR, UINT), "vsum", v1, v2, v3, m4);
6349 return emit_VRR_VVVM(p, 0xE70000000064ULL, v1, v2, v3, m4);
6352 static UChar *
6353 s390_emit_VSUMG(UChar *p, UChar v1, UChar v2, UChar v3, UChar m4)
6355 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
6356 s390_disasm(ENC5(MNM, VR, VR, VR, UINT), "vsumg", v1, v2, v3, m4);
6358 return emit_VRR_VVVM(p, 0xE70000000065ULL, v1, v2, v3, m4);
6361 static UChar *
6362 s390_emit_VSUMQ(UChar *p, UChar v1, UChar v2, UChar v3, UChar m4)
6364 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
6365 s390_disasm(ENC5(MNM, VR, VR, VR, UINT), "vsumq", v1, v2, v3, m4);
6367 return emit_VRR_VVVM(p, 0xE70000000067ULL, v1, v2, v3, m4);
6370 static UChar *
6371 s390_emit_VLVGP(UChar *p, UChar v1, UChar r2, UChar r3)
6373 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
6374 s390_disasm(ENC4(MNM, VR, GPR, GPR), "vlvgp", v1, r2, r3);
6376 return emit_VRR_VRR(p, 0xE70000000062ULL, v1, r2, r3);
6379 static UChar *
6380 s390_emit_VFPSO(UChar *p, UChar v1, UChar v2, UChar m3, UChar m4, UChar m5)
6382 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
6383 s390_disasm(ENC6(MNM, VR, VR, UINT, UINT, UINT), "vfpso", v1, v2, m3, m4,
6384 m5);
6386 return emit_VRR_VVMMM(p, 0xE700000000CCULL, v1, v2, m3, m4, m5);
6389 static UChar *
6390 s390_emit_VFA(UChar *p, UChar v1, UChar v2, UChar v3, UChar m4, UChar m5)
6392 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
6393 s390_disasm(ENC6(MNM, VR, VR, VR, UINT, UINT), "vfa", v1, v2, v3, m4, m5);
6395 return emit_VRR_VVVMM(p, 0xE700000000e3ULL, v1, v2, v3, m4, m5);
6398 static UChar *
6399 s390_emit_VFS(UChar *p, UChar v1, UChar v2, UChar v3, UChar m4, UChar m5)
6401 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
6402 s390_disasm(ENC6(MNM, VR, VR, VR, UINT, UINT), "vfs", v1, v2, v3, m4, m5);
6404 return emit_VRR_VVVMM(p, 0xE700000000e2ULL, v1, v2, v3, m4, m5);
6407 static UChar *
6408 s390_emit_VFM(UChar *p, UChar v1, UChar v2, UChar v3, UChar m4, UChar m5)
6410 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
6411 s390_disasm(ENC6(MNM, VR, VR, VR, UINT, UINT), "vfm", v1, v2, v3, m4, m5);
6413 return emit_VRR_VVVMM(p, 0xE700000000e7ULL, v1, v2, v3, m4, m5);
6416 static UChar *
6417 s390_emit_VFD(UChar *p, UChar v1, UChar v2, UChar v3, UChar m4, UChar m5)
6419 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
6420 s390_disasm(ENC6(MNM, VR, VR, VR, UINT, UINT), "vfd", v1, v2, v3, m4, m5);
6422 return emit_VRR_VVVMM(p, 0xE700000000e5ULL, v1, v2, v3, m4, m5);
6425 static UChar *
6426 s390_emit_VFSQ(UChar *p, UChar v1, UChar v2, UChar m3, UChar m4)
6428 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
6429 s390_disasm(ENC5(MNM, VR, VR, UINT, UINT), "vfsq", v1, v2, m3, m4);
6431 return emit_VRR_VVMMM(p, 0xE700000000CEULL, v1, v2, m3, m4, 0);
6434 static UChar *
6435 s390_emit_VFMA(UChar *p, UChar v1, UChar v2, UChar v3, UChar v4, UChar m5,
6436 UChar m6)
6438 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
6439 s390_disasm(ENC7(MNM, VR, VR, VR, VR, UINT, UINT), "vfma",
6440 v1, v2, v3, v4, m5, m6);
6442 return emit_VRRe_VVVVMM(p, 0xE7000000008fULL, v1, v2, v3, v4, m5, m6);
6445 static UChar *
6446 s390_emit_VFMS(UChar *p, UChar v1, UChar v2, UChar v3, UChar v4, UChar m5,
6447 UChar m6)
6449 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
6450 s390_disasm(ENC7(MNM, VR, VR, VR, VR, UINT, UINT), "vfms",
6451 v1, v2, v3, v4, m5, m6);
6453 return emit_VRRe_VVVVMM(p, 0xE7000000008eULL, v1, v2, v3, v4, m5, m6);
6456 static UChar *
6457 s390_emit_VFCE(UChar *p, UChar v1, UChar v2, UChar v3, UChar m4, UChar m5,
6458 UChar m6)
6460 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
6461 s390_disasm(ENC7(MNM, VR, VR, VR, UINT, UINT, UINT), "vfce",
6462 v1, v2, v3, m4, m5, m6);
6464 return emit_VRR_VVVMMM(p, 0xE700000000e8ULL, v1, v2, v3, m4, m5, m6);
6467 static UChar *
6468 s390_emit_VFCH(UChar *p, UChar v1, UChar v2, UChar v3, UChar m4, UChar m5,
6469 UChar m6)
6471 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
6472 s390_disasm(ENC7(MNM, VR, VR, VR, UINT, UINT, UINT), "vfch",
6473 v1, v2, v3, m4, m5, m6);
6475 return emit_VRR_VVVMMM(p, 0xE700000000ebULL, v1, v2, v3, m4, m5, m6);
6478 static UChar *
6479 s390_emit_VFCHE(UChar *p, UChar v1, UChar v2, UChar v3, UChar m4, UChar m5,
6480 UChar m6)
6482 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
6483 s390_disasm(ENC7(MNM, VR, VR, VR, UINT, UINT, UINT), "vfche",
6484 v1, v2, v3, m4, m5, m6);
6486 return emit_VRR_VVVMMM(p, 0xE700000000eaULL, v1, v2, v3, m4, m5, m6);
6489 /*---------------------------------------------------------------*/
6490 /*--- Constructors for the various s390_insn kinds ---*/
6491 /*---------------------------------------------------------------*/
6493 s390_insn *
6494 s390_insn_load(UChar size, HReg dst, s390_amode *src)
6496 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
6498 insn->tag = S390_INSN_LOAD;
6499 insn->size = size;
6500 insn->variant.load.src = src;
6501 insn->variant.load.dst = dst;
6503 vassert(size == 1 || size == 2 || size == 4 || size == 8 || size == 16);
6505 return insn;
6509 s390_insn *
6510 s390_insn_store(UChar size, s390_amode *dst, HReg src)
6512 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
6514 insn->tag = S390_INSN_STORE;
6515 insn->size = size;
6516 insn->variant.store.src = src;
6517 insn->variant.store.dst = dst;
6519 vassert(size == 1 || size == 2 || size == 4 || size == 8 || size == 16);
6521 return insn;
6525 s390_insn *
6526 s390_insn_move(UChar size, HReg dst, HReg src)
6528 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
6530 insn->tag = S390_INSN_MOVE;
6531 insn->size = size;
6532 insn->variant.move.src = src;
6533 insn->variant.move.dst = dst;
6535 vassert(size == 1 || size == 2 || size == 4 || size == 8 || size ==16);
6537 return insn;
6541 s390_insn *
6542 s390_insn_memcpy(UChar size, s390_amode *dst, s390_amode *src)
6544 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
6546 /* This insn will be mapped to MVC which requires base register
6547 plus 12-bit displacement */
6548 vassert(src->tag == S390_AMODE_B12);
6549 vassert(dst->tag == S390_AMODE_B12);
6551 insn->tag = S390_INSN_MEMCPY;
6552 insn->size = size;
6553 insn->variant.memcpy.src = src;
6554 insn->variant.memcpy.dst = dst;
6556 vassert(size == 1 || size == 2 || size == 4 || size == 8 || size == 16);
6558 return insn;
6562 s390_insn *
6563 s390_insn_cond_move(UChar size, s390_cc_t cond, HReg dst, s390_opnd_RMI src)
6565 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
6567 insn->tag = S390_INSN_COND_MOVE;
6568 insn->size = size;
6569 insn->variant.cond_move.cond = cond;
6570 insn->variant.cond_move.src = src;
6571 insn->variant.cond_move.dst = dst;
6573 vassert(size == 1 || size == 2 || size == 4 || size == 8 || size == 16);
6575 return insn;
6579 s390_insn *
6580 s390_insn_load_immediate(UChar size, HReg dst, ULong value)
6582 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
6584 insn->tag = S390_INSN_LOAD_IMMEDIATE;
6585 insn->size = size;
6586 insn->variant.load_immediate.dst = dst;
6587 insn->variant.load_immediate.value = value;
6589 return insn;
6593 s390_insn *
6594 s390_insn_alu(UChar size, s390_alu_t tag, HReg dst, s390_opnd_RMI op2)
6596 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
6598 insn->tag = S390_INSN_ALU;
6599 insn->size = size;
6600 insn->variant.alu.tag = tag;
6601 insn->variant.alu.dst = dst;
6602 insn->variant.alu.op2 = op2;
6604 return insn;
6608 s390_insn *
6609 s390_insn_mul(UChar size, HReg dst_hi, HReg dst_lo, s390_opnd_RMI op2,
6610 Bool signed_multiply)
6612 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
6614 vassert(! hregIsVirtual(dst_hi));
6615 vassert(! hregIsVirtual(dst_lo));
6617 insn->tag = signed_multiply ? S390_INSN_SMUL : S390_INSN_UMUL;
6618 insn->size = size;
6619 insn->variant.mul.dst_hi = dst_hi;
6620 insn->variant.mul.dst_lo = dst_lo;
6621 insn->variant.mul.op2 = op2;
6623 return insn;
6627 s390_insn *
6628 s390_insn_div(UChar size, HReg op1_hi, HReg op1_lo, s390_opnd_RMI op2,
6629 Bool signed_divide)
6631 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
6633 vassert(size == 4 || size == 8);
6634 vassert(! hregIsVirtual(op1_hi));
6635 vassert(! hregIsVirtual(op1_lo));
6637 insn->tag = signed_divide ? S390_INSN_SDIV : S390_INSN_UDIV;
6638 insn->size = size;
6639 insn->variant.div.op1_hi = op1_hi;
6640 insn->variant.div.op1_lo = op1_lo;
6641 insn->variant.div.op2 = op2;
6643 return insn;
6647 s390_insn *
6648 s390_insn_divs(UChar size, HReg rem, HReg op1, s390_opnd_RMI op2)
6650 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
6652 vassert(size == 8);
6653 vassert(! hregIsVirtual(op1));
6654 vassert(! hregIsVirtual(rem));
6656 insn->tag = S390_INSN_DIVS;
6657 insn->size = size;
6658 insn->variant.divs.rem = rem; /* remainder */
6659 insn->variant.divs.op1 = op1; /* also quotient */
6660 insn->variant.divs.op2 = op2;
6662 return insn;
6666 s390_insn *
6667 s390_insn_clz(UChar size, HReg num_bits, HReg clobber, s390_opnd_RMI src)
6669 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
6671 vassert(size == 8);
6672 vassert(! hregIsVirtual(num_bits));
6673 vassert(! hregIsVirtual(clobber));
6675 insn->tag = S390_INSN_CLZ;
6676 insn->size = size;
6677 insn->variant.clz.num_bits = num_bits;
6678 insn->variant.clz.clobber = clobber;
6679 insn->variant.clz.src = src;
6681 return insn;
6685 s390_insn *
6686 s390_insn_unop(UChar size, s390_unop_t tag, HReg dst, s390_opnd_RMI opnd)
6688 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
6690 insn->tag = S390_INSN_UNOP;
6691 insn->size = size;
6692 insn->variant.unop.tag = tag;
6693 insn->variant.unop.dst = dst;
6694 insn->variant.unop.src = opnd;
6696 return insn;
6700 s390_insn *
6701 s390_insn_test(UChar size, s390_opnd_RMI src)
6703 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
6705 vassert(size == 1 || size == 2 || size == 4 || size == 8);
6707 insn->tag = S390_INSN_TEST;
6708 insn->size = size;
6709 insn->variant.test.src = src;
6711 return insn;
6715 s390_insn *
6716 s390_insn_cc2bool(HReg dst, s390_cc_t cond)
6718 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
6720 insn->tag = S390_INSN_CC2BOOL;
6721 insn->size = 0; /* does not matter */
6722 insn->variant.cc2bool.cond = cond;
6723 insn->variant.cc2bool.dst = dst;
6725 return insn;
6729 s390_insn *
6730 s390_insn_cas(UChar size, HReg op1, s390_amode *op2, HReg op3, HReg old_mem)
6732 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
6734 vassert(size == 4 || size == 8);
6735 vassert(hregNumber(op2->x) == 0);
6736 vassert(op2->tag == S390_AMODE_B12 || op2->tag == S390_AMODE_B20);
6738 insn->tag = S390_INSN_CAS;
6739 insn->size = size;
6740 insn->variant.cas.op1 = op1;
6741 insn->variant.cas.op2 = op2;
6742 insn->variant.cas.op3 = op3;
6743 insn->variant.cas.old_mem = old_mem;
6745 return insn;
6749 s390_insn *
6750 s390_insn_cdas(UChar size, HReg op1_high, HReg op1_low, s390_amode *op2,
6751 HReg op3_high, HReg op3_low, HReg old_mem_high, HReg old_mem_low,
6752 HReg scratch)
6754 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
6755 s390_cdas *cdas = LibVEX_Alloc_inline(sizeof(s390_cdas));
6757 vassert(size == 4 || size == 8);
6758 vassert(hregNumber(op2->x) == 0);
6759 vassert(hregNumber(scratch) == 1); /* r0,r1 used as scratch reg pair */
6760 vassert(op2->tag == S390_AMODE_B12 || op2->tag == S390_AMODE_B20);
6762 insn->tag = S390_INSN_CDAS;
6763 insn->size = size;
6764 insn->variant.cdas.details = cdas;
6766 cdas->op1_high = op1_high;
6767 cdas->op1_low = op1_low;
6768 cdas->op2 = op2;
6769 cdas->op3_high = op3_high;
6770 cdas->op3_low = op3_low;
6771 cdas->old_mem_high = old_mem_high;
6772 cdas->old_mem_low = old_mem_low;
6773 cdas->scratch = scratch;
6775 return insn;
6779 s390_insn *
6780 s390_insn_compare(UChar size, HReg src1, s390_opnd_RMI src2,
6781 Bool signed_comparison)
6783 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
6785 vassert(size == 4 || size == 8);
6787 insn->tag = S390_INSN_COMPARE;
6788 insn->size = size;
6789 insn->variant.compare.src1 = src1;
6790 insn->variant.compare.src2 = src2;
6791 insn->variant.compare.signed_comparison = signed_comparison;
6793 return insn;
6797 s390_insn *
6798 s390_insn_helper_call(s390_cc_t cond, Addr64 target, UInt num_args,
6799 const HChar *name, RetLoc rloc)
6801 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
6802 s390_helper_call *helper_call = LibVEX_Alloc_inline(sizeof(s390_helper_call));
6804 insn->tag = S390_INSN_HELPER_CALL;
6805 insn->size = 0; /* does not matter */
6806 insn->variant.helper_call.details = helper_call;
6808 helper_call->cond = cond;
6809 helper_call->target = target;
6810 helper_call->num_args = num_args;
6811 helper_call->name = name;
6812 helper_call->rloc = rloc;
6814 vassert(is_sane_RetLoc(rloc));
6816 return insn;
6820 s390_insn *
6821 s390_insn_bfp_triop(UChar size, s390_bfp_triop_t tag, HReg dst, HReg op2,
6822 HReg op3)
6824 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
6826 vassert(size == 4 || size == 8);
6828 insn->tag = S390_INSN_BFP_TRIOP;
6829 insn->size = size;
6830 insn->variant.bfp_triop.tag = tag;
6831 insn->variant.bfp_triop.dst = dst;
6832 insn->variant.bfp_triop.op2 = op2;
6833 insn->variant.bfp_triop.op3 = op3;
6835 return insn;
6839 s390_insn *
6840 s390_insn_bfp_binop(UChar size, s390_bfp_binop_t tag, HReg dst, HReg op2)
6842 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
6844 vassert(size == 4 || size == 8);
6846 insn->tag = S390_INSN_BFP_BINOP;
6847 insn->size = size;
6848 insn->variant.bfp_binop.tag = tag;
6849 insn->variant.bfp_binop.dst_hi = dst;
6850 insn->variant.bfp_binop.op2_hi = op2;
6851 insn->variant.bfp_binop.dst_lo = INVALID_HREG;
6852 insn->variant.bfp_binop.op2_lo = INVALID_HREG;
6854 return insn;
6858 s390_insn *
6859 s390_insn_bfp_unop(UChar size, s390_bfp_unop_t tag, HReg dst, HReg op)
6861 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
6863 vassert(size == 4 || size == 8);
6865 insn->tag = S390_INSN_BFP_UNOP;
6866 insn->size = size;
6867 insn->variant.bfp_unop.tag = tag;
6868 insn->variant.bfp_unop.dst_hi = dst;
6869 insn->variant.bfp_unop.op_hi = op;
6870 insn->variant.bfp_unop.dst_lo = INVALID_HREG;
6871 insn->variant.bfp_unop.op_lo = INVALID_HREG;
6873 return insn;
6877 s390_insn *
6878 s390_insn_bfp_compare(UChar size, HReg dst, HReg op1, HReg op2)
6880 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
6882 vassert(size == 4 || size == 8);
6884 insn->tag = S390_INSN_BFP_COMPARE;
6885 insn->size = size;
6886 insn->variant.bfp_compare.dst = dst;
6887 insn->variant.bfp_compare.op1_hi = op1;
6888 insn->variant.bfp_compare.op2_hi = op2;
6889 insn->variant.bfp_compare.op1_lo = INVALID_HREG;
6890 insn->variant.bfp_compare.op2_lo = INVALID_HREG;
6892 return insn;
6896 s390_insn *
6897 s390_insn_bfp_convert(UChar size, s390_bfp_conv_t tag, HReg dst, HReg op,
6898 s390_bfp_round_t rounding_mode)
6900 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
6902 vassert(size == 4 || size == 8);
6904 insn->tag = S390_INSN_BFP_CONVERT;
6905 insn->size = size;
6906 insn->variant.bfp_convert.tag = tag;
6907 insn->variant.bfp_convert.dst_hi = dst;
6908 insn->variant.bfp_convert.op_hi = op;
6909 insn->variant.bfp_convert.dst_lo = INVALID_HREG;
6910 insn->variant.bfp_convert.op_lo = INVALID_HREG;
6911 insn->variant.bfp_convert.rounding_mode = rounding_mode;
6913 return insn;
6917 /* Check validity of a register pair for 128-bit FP. Valid register
6918 pairs are (0,2), (1,3), (4, 6), (5, 7), (8, 10), (9, 11), (12, 14),
6919 and (13, 15). */
6920 static Bool
6921 is_valid_fp128_regpair(HReg hi, HReg lo)
6923 UInt hi_regno = hregNumber(hi);
6924 UInt lo_regno = hregNumber(lo);
6926 if (lo_regno != hi_regno + 2) return False;
6927 if ((hi_regno & 0x2) != 0) return False;
6929 return True;
6932 s390_insn *
6933 s390_insn_bfp128_binop(UChar size, s390_bfp_binop_t tag, HReg dst_hi,
6934 HReg dst_lo, HReg op2_hi, HReg op2_lo)
6936 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
6938 vassert(size == 16);
6939 vassert(is_valid_fp128_regpair(dst_hi, dst_lo));
6940 vassert(is_valid_fp128_regpair(op2_hi, op2_lo));
6942 insn->tag = S390_INSN_BFP_BINOP;
6943 insn->size = size;
6944 insn->variant.bfp_binop.tag = tag;
6945 insn->variant.bfp_binop.dst_hi = dst_hi;
6946 insn->variant.bfp_binop.dst_lo = dst_lo;
6947 insn->variant.bfp_binop.op2_hi = op2_hi;
6948 insn->variant.bfp_binop.op2_lo = op2_lo;
6950 return insn;
6954 s390_insn *
6955 s390_insn_bfp128_unop(UChar size, s390_bfp_unop_t tag, HReg dst_hi,
6956 HReg dst_lo, HReg op_hi, HReg op_lo)
6958 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
6960 vassert(size == 16);
6961 vassert(is_valid_fp128_regpair(dst_hi, dst_lo));
6962 vassert(is_valid_fp128_regpair(op_hi, op_lo));
6964 insn->tag = S390_INSN_BFP_UNOP;
6965 insn->size = size;
6966 insn->variant.bfp_unop.tag = tag;
6967 insn->variant.bfp_unop.dst_hi = dst_hi;
6968 insn->variant.bfp_unop.dst_lo = dst_lo;
6969 insn->variant.bfp_unop.op_hi = op_hi;
6970 insn->variant.bfp_unop.op_lo = op_lo;
6972 return insn;
6976 s390_insn *
6977 s390_insn_bfp128_compare(UChar size, HReg dst, HReg op1_hi, HReg op1_lo,
6978 HReg op2_hi, HReg op2_lo)
6980 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
6982 vassert(size == 16);
6983 vassert(is_valid_fp128_regpair(op1_hi, op1_lo));
6984 vassert(is_valid_fp128_regpair(op2_hi, op2_lo));
6986 insn->tag = S390_INSN_BFP_COMPARE;
6987 insn->size = size;
6988 insn->variant.bfp_compare.dst = dst;
6989 insn->variant.bfp_compare.op1_hi = op1_hi;
6990 insn->variant.bfp_compare.op1_lo = op1_lo;
6991 insn->variant.bfp_compare.op2_hi = op2_hi;
6992 insn->variant.bfp_compare.op2_lo = op2_lo;
6994 return insn;
6998 s390_insn *
6999 s390_insn_bfp128_convert(UChar size, s390_bfp_conv_t tag, HReg dst_hi,
7000 HReg dst_lo, HReg op_hi, HReg op_lo,
7001 s390_bfp_round_t rounding_mode)
7003 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
7005 if (size == 16) {
7006 /* From smaller or equal size to 16 bytes */
7007 vassert(is_valid_fp128_regpair(dst_hi, dst_lo));
7008 vassert(hregIsInvalid(op_lo)
7009 || is_valid_fp128_regpair(op_hi, op_lo));
7010 } else {
7011 /* From 16 bytes to smaller size */
7012 vassert(is_valid_fp128_regpair(op_hi, op_lo));
7015 insn->tag = S390_INSN_BFP_CONVERT;
7016 insn->size = size;
7017 insn->variant.bfp_convert.tag = tag;
7018 insn->variant.bfp_convert.dst_hi = dst_hi;
7019 insn->variant.bfp_convert.dst_lo = dst_lo;
7020 insn->variant.bfp_convert.op_hi = op_hi;
7021 insn->variant.bfp_convert.op_lo = op_lo;
7022 insn->variant.bfp_convert.rounding_mode = rounding_mode;
7024 return insn;
7028 s390_insn *
7029 s390_insn_bfp128_convert_to(UChar size, s390_bfp_conv_t tag, HReg dst_hi,
7030 HReg dst_lo, HReg op)
7032 /* Conversion to bfp128 never requires a rounding mode. Provide default
7033 rounding mode. It will not be used when emitting insns. */
7034 s390_bfp_round_t rounding_mode = S390_BFP_ROUND_NEAREST_EVEN;
7036 return s390_insn_bfp128_convert(size, tag, dst_hi, dst_lo, op,
7037 INVALID_HREG, rounding_mode);
7041 s390_insn *
7042 s390_insn_bfp128_convert_from(UChar size, s390_bfp_conv_t tag, HReg dst_hi,
7043 HReg dst_lo, HReg op_hi, HReg op_lo,
7044 s390_bfp_round_t rounding_mode)
7046 return s390_insn_bfp128_convert(size, tag, dst_hi, dst_lo, op_hi, op_lo,
7047 rounding_mode);
7051 s390_insn *
7052 s390_insn_dfp_binop(UChar size, s390_dfp_binop_t tag, HReg dst, HReg op2,
7053 HReg op3, s390_dfp_round_t rounding_mode)
7055 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
7056 s390_dfp_binop *dfp_binop = LibVEX_Alloc_inline(sizeof(s390_dfp_binop));
7058 vassert(size == 8);
7060 insn->tag = S390_INSN_DFP_BINOP;
7061 insn->size = size;
7062 insn->variant.dfp_binop.details = dfp_binop;
7064 dfp_binop->tag = tag;
7065 dfp_binop->dst_hi = dst;
7066 dfp_binop->op2_hi = op2;
7067 dfp_binop->op3_hi = op3;
7068 dfp_binop->dst_lo = INVALID_HREG;
7069 dfp_binop->op2_lo = INVALID_HREG;
7070 dfp_binop->op3_lo = INVALID_HREG;
7071 dfp_binop->rounding_mode = rounding_mode;
7073 return insn;
7077 s390_insn *
7078 s390_insn_dfp_unop(UChar size, s390_dfp_unop_t tag, HReg dst, HReg op)
7080 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
7082 vassert(size == 8);
7084 insn->tag = S390_INSN_DFP_UNOP;
7085 insn->size = size;
7086 insn->variant.dfp_unop.tag = tag;
7087 insn->variant.dfp_unop.dst_hi = dst;
7088 insn->variant.dfp_unop.op_hi = op;
7089 insn->variant.dfp_unop.dst_lo = INVALID_HREG;
7090 insn->variant.dfp_unop.op_lo = INVALID_HREG;
7092 return insn;
7096 s390_insn *
7097 s390_insn_dfp_intop(UChar size, s390_dfp_intop_t tag, HReg dst, HReg op2,
7098 HReg op3)
7100 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
7102 vassert(size == 8);
7104 insn->tag = S390_INSN_DFP_INTOP;
7105 insn->size = size;
7106 insn->variant.dfp_intop.tag = tag;
7107 insn->variant.dfp_intop.dst_hi = dst;
7108 insn->variant.dfp_intop.op2 = op2;
7109 insn->variant.dfp_intop.op3_hi = op3;
7110 insn->variant.dfp_intop.dst_lo = INVALID_HREG;
7111 insn->variant.dfp_intop.op3_lo = INVALID_HREG;
7113 return insn;
7117 s390_insn *
7118 s390_insn_dfp_compare(UChar size, s390_dfp_cmp_t tag, HReg dst,
7119 HReg op1, HReg op2)
7121 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
7123 vassert(size == 8);
7125 insn->tag = S390_INSN_DFP_COMPARE;
7126 insn->size = size;
7127 insn->variant.dfp_compare.tag = tag;
7128 insn->variant.dfp_compare.dst = dst;
7129 insn->variant.dfp_compare.op1_hi = op1;
7130 insn->variant.dfp_compare.op2_hi = op2;
7131 insn->variant.dfp_compare.op1_lo = INVALID_HREG;
7132 insn->variant.dfp_compare.op2_lo = INVALID_HREG;
7134 return insn;
7138 s390_insn *
7139 s390_insn_dfp_convert(UChar size, s390_dfp_conv_t tag, HReg dst, HReg op,
7140 s390_dfp_round_t rounding_mode)
7142 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
7144 vassert(size == 4 || size == 8);
7146 insn->tag = S390_INSN_DFP_CONVERT;
7147 insn->size = size;
7148 insn->variant.dfp_convert.tag = tag;
7149 insn->variant.dfp_convert.dst_hi = dst;
7150 insn->variant.dfp_convert.op_hi = op;
7151 insn->variant.dfp_convert.dst_lo = INVALID_HREG;
7152 insn->variant.dfp_convert.op_lo = INVALID_HREG;
7153 insn->variant.dfp_convert.rounding_mode = rounding_mode;
7155 return insn;
7159 s390_insn *
7160 s390_insn_dfp_reround(UChar size, HReg dst, HReg op2, HReg op3,
7161 s390_dfp_round_t rounding_mode)
7163 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
7165 vassert(size == 8);
7167 insn->tag = S390_INSN_DFP_REROUND;
7168 insn->size = size;
7169 insn->variant.dfp_reround.dst_hi = dst;
7170 insn->variant.dfp_reround.op2 = op2;
7171 insn->variant.dfp_reround.op3_hi = op3;
7172 insn->variant.dfp_reround.dst_lo = INVALID_HREG;
7173 insn->variant.dfp_reround.op3_lo = INVALID_HREG;
7174 insn->variant.dfp_reround.rounding_mode = rounding_mode;
7176 return insn;
7180 s390_insn *
7181 s390_insn_fp_convert(UChar size, s390_fp_conv_t tag, HReg dst, HReg op,
7182 HReg r1, s390_dfp_round_t rounding_mode)
7184 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
7185 s390_fp_convert *fp_convert = LibVEX_Alloc_inline(sizeof(s390_fp_convert));
7187 vassert(size == 4 || size == 8);
7189 insn->tag = S390_INSN_FP_CONVERT;
7190 insn->size = size;
7191 insn->variant.fp_convert.details = fp_convert;
7193 fp_convert->tag = tag;
7194 fp_convert->dst_hi = dst;
7195 fp_convert->op_hi = op;
7196 fp_convert->r1 = r1;
7197 fp_convert->dst_lo = INVALID_HREG;
7198 fp_convert->op_lo = INVALID_HREG;
7199 fp_convert->rounding_mode = rounding_mode;
7201 return insn;
7205 s390_insn *
7206 s390_insn_fp128_convert(UChar size, s390_fp_conv_t tag, HReg dst_hi,
7207 HReg dst_lo, HReg op_hi, HReg op_lo, HReg r1,
7208 s390_dfp_round_t rounding_mode)
7210 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
7211 s390_fp_convert *fp_convert = LibVEX_Alloc_inline(sizeof(s390_fp_convert));
7213 vassert(size == 16);
7215 insn->tag = S390_INSN_FP_CONVERT;
7216 insn->size = size;
7217 insn->variant.fp_convert.details = fp_convert;
7219 fp_convert->tag = tag;
7220 fp_convert->dst_hi = dst_hi;
7221 fp_convert->dst_lo = dst_lo;
7222 fp_convert->op_hi = op_hi;
7223 fp_convert->r1 = r1;
7224 fp_convert->op_lo = op_lo;
7225 fp_convert->rounding_mode = rounding_mode;
7227 return insn;
7231 s390_insn *
7232 s390_insn_dfp128_binop(UChar size, s390_dfp_binop_t tag, HReg dst_hi,
7233 HReg dst_lo, HReg op2_hi, HReg op2_lo, HReg op3_hi,
7234 HReg op3_lo, s390_dfp_round_t rounding_mode)
7236 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
7237 s390_dfp_binop *dfp_binop = LibVEX_Alloc_inline(sizeof(s390_dfp_binop));
7239 vassert(size == 16);
7240 vassert(is_valid_fp128_regpair(dst_hi, dst_lo));
7241 vassert(is_valid_fp128_regpair(op2_hi, op2_lo));
7242 vassert(is_valid_fp128_regpair(op3_hi, op3_lo));
7244 insn->tag = S390_INSN_DFP_BINOP;
7245 insn->size = size;
7246 insn->variant.dfp_binop.details = dfp_binop;
7248 dfp_binop->tag = tag;
7249 dfp_binop->dst_hi = dst_hi;
7250 dfp_binop->dst_lo = dst_lo;
7251 dfp_binop->op2_hi = op2_hi;
7252 dfp_binop->op2_lo = op2_lo;
7253 dfp_binop->op3_hi = op3_hi;
7254 dfp_binop->op3_lo = op3_lo;
7255 dfp_binop->rounding_mode = rounding_mode;
7257 return insn;
7261 s390_insn *
7262 s390_insn_dfp128_unop(UChar size, s390_dfp_unop_t tag, HReg dst,
7263 HReg op_hi, HReg op_lo)
7265 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
7267 /* destination is an 8 byte integer value */
7268 vassert(size == 8);
7269 vassert(is_valid_fp128_regpair(op_hi, op_lo));
7271 insn->tag = S390_INSN_DFP_UNOP;
7272 insn->size = size;
7273 insn->variant.dfp_unop.tag = tag;
7274 insn->variant.dfp_unop.dst_hi = dst;
7275 insn->variant.dfp_unop.dst_lo = INVALID_HREG;
7276 insn->variant.dfp_unop.op_hi = op_hi;
7277 insn->variant.dfp_unop.op_lo = op_lo;
7279 return insn;
7283 s390_insn *
7284 s390_insn_dfp128_intop(UChar size, s390_dfp_intop_t tag, HReg dst_hi,
7285 HReg dst_lo, HReg op2, HReg op3_hi, HReg op3_lo)
7287 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
7289 vassert(size == 16);
7290 vassert(is_valid_fp128_regpair(dst_hi, dst_lo));
7291 vassert(is_valid_fp128_regpair(op3_hi, op3_lo));
7293 insn->tag = S390_INSN_DFP_INTOP;
7294 insn->size = size;
7295 insn->variant.dfp_intop.tag = tag;
7296 insn->variant.dfp_intop.dst_hi = dst_hi;
7297 insn->variant.dfp_intop.dst_lo = dst_lo;
7298 insn->variant.dfp_intop.op2 = op2;
7299 insn->variant.dfp_intop.op3_hi = op3_hi;
7300 insn->variant.dfp_intop.op3_lo = op3_lo;
7302 return insn;
7306 s390_insn *
7307 s390_insn_dfp128_compare(UChar size, s390_dfp_cmp_t tag, HReg dst, HReg op1_hi,
7308 HReg op1_lo, HReg op2_hi, HReg op2_lo)
7310 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
7312 vassert(size == 16);
7313 vassert(is_valid_fp128_regpair(op1_hi, op1_lo));
7314 vassert(is_valid_fp128_regpair(op2_hi, op2_lo));
7316 insn->tag = S390_INSN_DFP_COMPARE;
7317 insn->size = size;
7318 insn->variant.dfp_compare.tag = tag;
7319 insn->variant.dfp_compare.dst = dst;
7320 insn->variant.dfp_compare.op1_hi = op1_hi;
7321 insn->variant.dfp_compare.op1_lo = op1_lo;
7322 insn->variant.dfp_compare.op2_hi = op2_hi;
7323 insn->variant.dfp_compare.op2_lo = op2_lo;
7325 return insn;
7329 static s390_insn *
7330 s390_insn_dfp128_convert(UChar size, s390_dfp_conv_t tag, HReg dst_hi,
7331 HReg dst_lo, HReg op_hi, HReg op_lo,
7332 s390_dfp_round_t rounding_mode)
7334 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
7336 if (size == 16) {
7337 /* From smaller size to 16 bytes */
7338 vassert(is_valid_fp128_regpair(dst_hi, dst_lo));
7339 vassert(hregIsInvalid(op_lo));
7340 } else {
7341 /* From 16 bytes to smaller size */
7342 vassert(is_valid_fp128_regpair(op_hi, op_lo));
7345 insn->tag = S390_INSN_DFP_CONVERT;
7346 insn->size = size;
7347 insn->variant.dfp_convert.tag = tag;
7348 insn->variant.dfp_convert.dst_hi = dst_hi;
7349 insn->variant.dfp_convert.dst_lo = dst_lo;
7350 insn->variant.dfp_convert.op_hi = op_hi;
7351 insn->variant.dfp_convert.op_lo = op_lo;
7352 insn->variant.dfp_convert.rounding_mode = rounding_mode;
7354 return insn;
7358 s390_insn *
7359 s390_insn_dfp128_convert_to(UChar size, s390_dfp_conv_t tag, HReg dst_hi,
7360 HReg dst_lo, HReg op)
7362 /* Conversion to dfp128 never requires a rounding mode. Provide default
7363 rounding mode. It will not be used when emitting insns. */
7364 s390_dfp_round_t rounding_mode = S390_DFP_ROUND_NEAREST_EVEN_4;
7366 return s390_insn_dfp128_convert(size, tag, dst_hi, dst_lo, op,
7367 INVALID_HREG, rounding_mode);
7371 s390_insn *
7372 s390_insn_dfp128_convert_from(UChar size, s390_dfp_conv_t tag, HReg dst_hi,
7373 HReg dst_lo, HReg op_hi, HReg op_lo,
7374 s390_dfp_round_t rounding_mode)
7376 return s390_insn_dfp128_convert(size, tag, dst_hi, dst_lo, op_hi, op_lo,
7377 rounding_mode);
7381 s390_insn *
7382 s390_insn_dfp128_reround(UChar size, HReg dst_hi, HReg dst_lo, HReg op2,
7383 HReg op3_hi, HReg op3_lo,
7384 s390_dfp_round_t rounding_mode)
7386 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
7388 vassert(size == 16);
7389 vassert(is_valid_fp128_regpair(dst_hi, dst_lo));
7390 vassert(is_valid_fp128_regpair(op3_hi, op3_lo));
7392 insn->tag = S390_INSN_DFP_REROUND;
7393 insn->size = size;
7394 insn->variant.dfp_reround.dst_hi = dst_hi;
7395 insn->variant.dfp_reround.dst_lo = dst_lo;
7396 insn->variant.dfp_reround.op2 = op2;
7397 insn->variant.dfp_reround.op3_hi = op3_hi;
7398 insn->variant.dfp_reround.op3_lo = op3_lo;
7399 insn->variant.dfp_reround.rounding_mode = rounding_mode;
7401 return insn;
7405 s390_insn *
7406 s390_insn_mfence(void)
7408 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
7410 insn->tag = S390_INSN_MFENCE;
7411 insn->size = 0; /* not needed */
7413 return insn;
7417 s390_insn *
7418 s390_insn_mimm(UChar size, s390_amode *dst, ULong value)
7420 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
7422 /* This insn will be mapped to insns that require base register
7423 plus 12-bit displacement */
7424 vassert(dst->tag == S390_AMODE_B12);
7426 insn->tag = S390_INSN_MIMM;
7427 insn->size = size;
7428 insn->variant.mimm.dst = dst;
7429 insn->variant.mimm.value = value;
7431 return insn;
7435 s390_insn *
7436 s390_insn_madd(UChar size, s390_amode *dst, UChar delta, ULong value)
7438 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
7440 vassert(size == 4 || size == 8);
7442 /* This insn will be mapped to an ASI or AGSI so we can only allow base
7443 register plus 12-bit / 20-bit displacement. */
7444 vassert(dst->tag == S390_AMODE_B12 || dst->tag == S390_AMODE_B20);
7445 /* ASI and AGSI require the GIE facility */
7446 vassert(s390_host_has_gie);
7448 insn->tag = S390_INSN_MADD;
7449 insn->size = size;
7450 insn->variant.madd.dst = dst;
7451 insn->variant.madd.delta = delta;
7452 insn->variant.madd.value = value;
7454 return insn;
7458 s390_insn *
7459 s390_insn_set_fpc_bfprm(UChar size, HReg mode)
7461 vassert(size == 4);
7463 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
7465 insn->tag = S390_INSN_SET_FPC_BFPRM;
7466 insn->size = size;
7467 insn->variant.set_fpc_bfprm.mode = mode;
7469 return insn;
7473 s390_insn *
7474 s390_insn_set_fpc_dfprm(UChar size, HReg mode)
7476 vassert(size == 4);
7478 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
7480 insn->tag = S390_INSN_SET_FPC_DFPRM;
7481 insn->size = size;
7482 insn->variant.set_fpc_dfprm.mode = mode;
7484 return insn;
7488 s390_insn *
7489 s390_insn_xdirect(s390_cc_t cond, Addr64 dst, s390_amode *guest_IA,
7490 Bool to_fast_entry)
7492 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
7494 vassert(guest_IA->tag == S390_AMODE_B12);
7496 insn->tag = S390_INSN_XDIRECT;
7497 insn->size = 0; /* does not matter */
7499 insn->variant.xdirect.cond = cond;
7500 insn->variant.xdirect.dst = dst;
7501 insn->variant.xdirect.guest_IA = guest_IA;
7502 insn->variant.xdirect.to_fast_entry = to_fast_entry;
7504 return insn;
7508 s390_insn *
7509 s390_insn_xindir(s390_cc_t cond, HReg dst, s390_amode *guest_IA)
7511 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
7513 vassert(guest_IA->tag == S390_AMODE_B12);
7515 insn->tag = S390_INSN_XINDIR;
7516 insn->size = 0; /* does not matter */
7518 insn->variant.xindir.cond = cond;
7519 insn->variant.xindir.dst = dst;
7520 insn->variant.xindir.guest_IA = guest_IA;
7522 return insn;
7526 s390_insn *
7527 s390_insn_xassisted(s390_cc_t cond, HReg dst, s390_amode *guest_IA,
7528 IRJumpKind kind)
7530 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
7532 vassert(guest_IA->tag == S390_AMODE_B12);
7534 insn->tag = S390_INSN_XASSISTED;
7535 insn->size = 0; /* does not matter */
7537 insn->variant.xassisted.cond = cond;
7538 insn->variant.xassisted.dst = dst;
7539 insn->variant.xassisted.guest_IA = guest_IA;
7540 insn->variant.xassisted.kind = kind;
7542 return insn;
7546 s390_insn *
7547 s390_insn_evcheck(s390_amode *counter, s390_amode *fail_addr)
7549 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
7551 vassert(counter->tag == S390_AMODE_B12);
7552 vassert(fail_addr->tag == S390_AMODE_B12);
7554 insn->tag = S390_INSN_EVCHECK;
7555 insn->size = 0; /* does not matter */
7557 insn->variant.evcheck.counter = counter;
7558 insn->variant.evcheck.fail_addr = fail_addr;
7560 return insn;
7564 s390_insn *
7565 s390_insn_profinc(void)
7567 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
7569 insn->tag = S390_INSN_PROFINC;
7570 insn->size = 0; /* does not matter */
7572 return insn;
7576 s390_insn *
7577 s390_insn_vec_amodeop(UChar size, s390_vec_amodeop_t tag, HReg dst, HReg op1,
7578 s390_amode *op2)
7580 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
7582 vassert(size == 1 || size == 2 || size == 4 || size == 8);
7584 insn->tag = S390_INSN_VEC_AMODEOP;
7585 insn->size = size;
7586 insn->variant.vec_amodeop.tag = tag;
7587 insn->variant.vec_amodeop.dst = dst;
7588 insn->variant.vec_amodeop.op1 = op1;
7589 insn->variant.vec_amodeop.op2 = op2;
7591 return insn;
7594 s390_insn *s390_insn_vec_amodeintop(UChar size, s390_vec_amodeintop_t tag, HReg dst,
7595 s390_amode* op2, HReg op3)
7597 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
7599 vassert(size == 1 || size == 2 || size == 4 || size == 8);
7601 insn->tag = S390_INSN_VEC_AMODEINTOP;
7602 insn->size = size;
7603 insn->variant.vec_amodeintop.tag = tag;
7604 insn->variant.vec_amodeintop.dst = dst;
7605 insn->variant.vec_amodeintop.op2 = op2;
7606 insn->variant.vec_amodeintop.op3 = op3;
7608 return insn;
7611 s390_insn *s390_insn_vec_binop(UChar size, s390_vec_binop_t tag, HReg dst,
7612 HReg op1, HReg op2)
7614 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
7616 vassert(size == 1 || size == 2 || size == 4 || size == 8 || size == 16);
7618 insn->tag = S390_INSN_VEC_BINOP;
7619 insn->size = size;
7620 insn->variant.vec_binop.tag = tag;
7621 insn->variant.vec_binop.dst = dst;
7622 insn->variant.vec_binop.op1 = op1;
7623 insn->variant.vec_binop.op2 = op2;
7625 return insn;
7628 s390_insn *s390_insn_vec_triop(UChar size, s390_vec_triop_t tag, HReg dst,
7629 HReg op1, HReg op2, HReg op3)
7631 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
7634 insn->tag = S390_INSN_VEC_TRIOP;
7635 insn->size = size;
7636 insn->variant.vec_triop.tag = tag;
7637 insn->variant.vec_triop.dst = dst;
7638 insn->variant.vec_triop.op1 = op1;
7639 insn->variant.vec_triop.op2 = op2;
7640 insn->variant.vec_triop.op3 = op3;
7642 return insn;
7645 s390_insn *s390_insn_vec_replicate(UChar size, HReg dst, HReg op1,
7646 UChar idx)
7648 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
7650 insn->tag = S390_INSN_VEC_REPLICATE;
7651 insn->size = size;
7652 insn->variant.vec_replicate.dst = dst;
7653 insn->variant.vec_replicate.op1 = op1;
7654 insn->variant.vec_replicate.idx = idx;
7656 return insn;
7659 /*---------------------------------------------------------------*/
7660 /*--- Debug print ---*/
7661 /*---------------------------------------------------------------*/
7663 static const HChar *
7664 s390_cc_as_string(s390_cc_t cc)
7666 switch (cc) {
7667 case S390_CC_NEVER: return "never";
7668 case S390_CC_OVFL: return "overflow";
7669 case S390_CC_H: return "greater than"; /* A > B ; high */
7670 case S390_CC_NLE: return "not low or equal";
7671 case S390_CC_L: return "less than"; /* A < B ; low */
7672 case S390_CC_NHE: return "not high or equal";
7673 case S390_CC_LH: return "low or high";
7674 case S390_CC_NE: return "not equal"; /* A != B ; not zero */
7675 case S390_CC_E: return "equal"; /* A == B ; zero */
7676 case S390_CC_NLH: return "not low or high";
7677 case S390_CC_HE: return "greater or equal"; /* A >= B ; high or equal*/
7678 case S390_CC_NL: return "not low"; /* not low */
7679 case S390_CC_LE: return "less or equal"; /* A <= B ; low or equal */
7680 case S390_CC_NH: return "not high";
7681 case S390_CC_NO: return "not overflow";
7682 case S390_CC_ALWAYS: return "always";
7683 default:
7684 vpanic("s390_cc_as_string");
7689 static const HChar *
7690 s390_jump_kind_as_string(IRJumpKind kind)
7692 switch (kind) {
7693 case Ijk_Boring: return "Boring";
7694 case Ijk_Call: return "Call";
7695 case Ijk_Ret: return "Return";
7696 case Ijk_ClientReq: return "ClientReq";
7697 case Ijk_Yield: return "Yield";
7698 case Ijk_EmWarn: return "EmWarn";
7699 case Ijk_EmFail: return "EmFail";
7700 case Ijk_NoDecode: return "NoDecode";
7701 case Ijk_MapFail: return "MapFail";
7702 case Ijk_InvalICache: return "Invalidate";
7703 case Ijk_NoRedir: return "NoRedir";
7704 case Ijk_SigTRAP: return "SigTRAP";
7705 case Ijk_SigFPE: return "SigFPE";
7706 case Ijk_SigSEGV: return "SigSEGV";
7707 case Ijk_SigBUS: return "SigBUS";
7708 case Ijk_Sys_syscall: return "Sys_syscall";
7709 default:
7710 vpanic("s390_jump_kind_as_string");
7715 /* Helper function for writing out a V insn */
7716 static void
7717 s390_sprintf(HChar *buf, const HChar *fmt, ...)
7719 HChar *p;
7720 ULong value;
7721 va_list args;
7722 va_start(args, fmt);
7724 p = buf;
7725 for ( ; *fmt; ++fmt) {
7726 Int c = *fmt;
7728 if (c != '%') {
7729 *p++ = c;
7730 continue;
7733 c = *++fmt; /* next char */
7734 switch (c) {
7735 case '%':
7736 *p++ = c; /* %% */
7737 continue;
7739 case 's': /* %s */
7740 p += vex_sprintf(p, "%s", va_arg(args, HChar *));
7741 continue;
7743 case 'M': /* %M = mnemonic */
7744 p += vex_sprintf(p, "%-8s", va_arg(args, HChar *));
7745 continue;
7747 case 'R': /* %R = register */
7748 p += vex_sprintf(p, "%s", s390_hreg_as_string(va_arg(args, HReg)));
7749 continue;
7751 case 'A': /* %A = amode */
7752 p += vex_sprintf(p, "%s",
7753 s390_amode_as_string(va_arg(args, s390_amode *)));
7754 continue;
7756 case 'G': /* %G = guest state @ offset */
7757 p += vex_sprintf(p, "guest[%u]", va_arg(args, UInt));
7758 continue;
7760 case 'C': /* %C = condition code */
7761 p += vex_sprintf(p, "%s", s390_cc_as_string(va_arg(args, s390_cc_t)));
7762 continue;
7764 case 'J': /* &J = jump kind */
7765 p += vex_sprintf(p, "%s",
7766 s390_jump_kind_as_string(va_arg(args, IRJumpKind)));
7767 continue;
7769 case 'L': { /* %L = argument list in helper call*/
7770 UInt i, num_args;
7772 num_args = va_arg(args, UInt);
7774 for (i = 0; i < num_args; ++i) {
7775 if (i != 0) p += vex_sprintf(p, ", ");
7776 p += vex_sprintf(p, "r%u", s390_gprno_from_arg_index(i));
7778 continue;
7781 case 'O': { /* %O = RMI operand */
7782 s390_opnd_RMI *op = va_arg(args, s390_opnd_RMI *);
7784 switch (op->tag) {
7785 case S390_OPND_REG:
7786 p += vex_sprintf(p, "%s", s390_hreg_as_string(op->variant.reg));
7787 continue;
7789 case S390_OPND_AMODE:
7790 p += vex_sprintf(p, "%s", s390_amode_as_string(op->variant.am));
7791 continue;
7793 case S390_OPND_IMMEDIATE:
7794 value = op->variant.imm;
7795 goto print_value;
7797 default:
7798 goto fail;
7802 case 'I': /* %I = immediate value */
7803 value = va_arg(args, ULong);
7804 goto print_value;
7806 print_value:
7807 if ((Long)value < 0)
7808 p += vex_sprintf(p, "%lld", (Long)value);
7809 else if (value < 100)
7810 p += vex_sprintf(p, "%llu", value);
7811 else
7812 p += vex_sprintf(p, "0x%llx", value);
7813 continue;
7815 default:
7816 goto fail;
7819 *p = '\0';
7820 va_end(args);
7822 return;
7824 fail: vpanic("s390_printf");
7828 /* Decompile the given insn into a static buffer and return it */
7829 const HChar *
7830 s390_insn_as_string(const s390_insn *insn)
7832 static HChar buf[300]; // large enough
7833 const HChar *op;
7834 HChar *p;
7836 buf[0] = '\0';
7838 switch (insn->tag) {
7839 case S390_INSN_LOAD:
7840 s390_sprintf(buf, "%M %R,%A", "v-load", insn->variant.load.dst,
7841 insn->variant.load.src);
7842 break;
7844 case S390_INSN_STORE:
7845 s390_sprintf(buf, "%M %R,%A", "v-store", insn->variant.store.src,
7846 insn->variant.store.dst);
7847 break;
7849 case S390_INSN_MOVE:
7850 s390_sprintf(buf, "%M %R,%R", "v-move", insn->variant.move.dst,
7851 insn->variant.move.src);
7852 break;
7854 case S390_INSN_MEMCPY:
7855 s390_sprintf(buf, "%M %A,%A", "v-memcpy", insn->variant.memcpy.dst,
7856 insn->variant.memcpy.src);
7857 break;
7859 case S390_INSN_COND_MOVE:
7860 s390_sprintf(buf, "%M if (%C) %R,%O", "v-move",
7861 insn->variant.cond_move.cond, insn->variant.cond_move.dst,
7862 &insn->variant.cond_move.src);
7863 break;
7865 case S390_INSN_LOAD_IMMEDIATE:
7866 s390_sprintf(buf, "%M %R,%I", "v-loadi", insn->variant.load_immediate.dst,
7867 insn->variant.load_immediate.value);
7868 break;
7870 case S390_INSN_ALU:
7871 switch (insn->variant.alu.tag) {
7872 case S390_ALU_ADD: op = "v-add"; break;
7873 case S390_ALU_SUB: op = "v-sub"; break;
7874 case S390_ALU_MUL: op = "v-mul"; break;
7875 case S390_ALU_AND: op = "v-and"; break;
7876 case S390_ALU_OR: op = "v-or"; break;
7877 case S390_ALU_XOR: op = "v-xor"; break;
7878 case S390_ALU_LSH: op = "v-lsh"; break;
7879 case S390_ALU_RSH: op = "v-rsh"; break;
7880 case S390_ALU_RSHA: op = "v-rsha"; break;
7881 case S390_ALU_ILIH: op = "v-ilih"; break;
7882 default: goto fail;
7884 s390_sprintf(buf, "%M %R,%O", op, insn->variant.alu.dst, /* also op1 */
7885 &insn->variant.alu.op2);
7886 break;
7888 case S390_INSN_SMUL:
7889 case S390_INSN_UMUL:
7890 if (insn->tag == S390_INSN_SMUL) {
7891 op = "v-muls";
7892 } else {
7893 op = "v-mulu";
7895 s390_sprintf(buf, "%M %R,%O", op, insn->variant.mul.dst_hi,
7896 &insn->variant.mul.op2);
7897 break;
7899 case S390_INSN_SDIV:
7900 case S390_INSN_UDIV:
7901 if (insn->tag == S390_INSN_SDIV) {
7902 op = "v-divs";
7903 } else {
7904 op = "v-divu";
7906 s390_sprintf(buf, "%M %R,%O", op, insn->variant.div.op1_hi,
7907 &insn->variant.div.op2);
7908 break;
7910 case S390_INSN_DIVS:
7911 s390_sprintf(buf, "%M %R,%O", "v-divsi", insn->variant.divs.op1,
7912 &insn->variant.divs.op2);
7913 break;
7915 case S390_INSN_CLZ:
7916 s390_sprintf(buf, "%M %R,%O", "v-clz", insn->variant.clz.num_bits,
7917 &insn->variant.clz.src);
7918 break;
7920 case S390_INSN_UNOP:
7921 switch (insn->variant.unop.tag) {
7922 case S390_ZERO_EXTEND_8:
7923 case S390_ZERO_EXTEND_16:
7924 case S390_ZERO_EXTEND_32:
7925 op = "v-zerox";
7926 break;
7928 case S390_SIGN_EXTEND_8:
7929 case S390_SIGN_EXTEND_16:
7930 case S390_SIGN_EXTEND_32:
7931 op = "v-signx";
7932 break;
7934 case S390_NEGATE:
7935 op = "v-neg";
7936 break;
7938 case S390_VEC_FILL:
7939 op = "v-vfill";
7940 break;
7942 case S390_VEC_DUPLICATE:
7943 op = "v-vdup";
7944 break;
7946 case S390_VEC_UNPACKLOWS:
7947 op = "v-vunpacks";
7948 break;
7950 case S390_VEC_UNPACKLOWU:
7951 op = "v-vunpacku";
7952 break;
7954 case S390_VEC_ABS:
7955 op = "v-vabs";
7956 break;
7958 case S390_VEC_COUNT_LEADING_ZEROES:
7959 op = "v-vclz";
7960 break;
7962 case S390_VEC_COUNT_TRAILING_ZEROES:
7963 op = "v-vctz";
7964 break;
7966 case S390_VEC_COUNT_ONES:
7967 op = "v-vpopct";
7968 break;
7970 case S390_VEC_FLOAT_NEG:
7971 op = "v-vfloatneg";
7972 break;
7974 case S390_VEC_FLOAT_ABS:
7975 op = "v-vfloatabs";
7976 break;
7978 case S390_VEC_FLOAT_NABS:
7979 op = "v-vfloatnabs";
7980 break;
7982 case S390_VEC_FLOAT_SQRT:
7983 op = "v-vfloatsqrt";
7984 break;
7986 default:
7987 goto fail;
7989 s390_sprintf(buf, "%M %R,%O", op, insn->variant.unop.dst,
7990 &insn->variant.unop.src);
7991 break;
7993 case S390_INSN_TEST:
7994 s390_sprintf(buf, "%M %O", "v-test", &insn->variant.test.src);
7995 break;
7997 case S390_INSN_CC2BOOL:
7998 s390_sprintf(buf, "%M %R,%C", "v-cc2b", insn->variant.cc2bool.dst,
7999 insn->variant.cc2bool.cond);
8000 break;
8002 case S390_INSN_CAS:
8003 s390_sprintf(buf, "%M %R,%A,%R,%R", "v-cas", insn->variant.cas.op1,
8004 insn->variant.cas.op2, insn->variant.cas.op3,
8005 insn->variant.cas.old_mem);
8006 break;
8008 case S390_INSN_CDAS: {
8009 s390_cdas *cdas = insn->variant.cdas.details;
8011 s390_sprintf(buf, "%M %R,%R,%A,%R,%R,%R,%R", "v-cdas",
8012 cdas->op1_high, cdas->op1_low, cdas->op2, cdas->op3_high,
8013 cdas->op3_low, cdas->old_mem_high, cdas->old_mem_low);
8014 break;
8017 case S390_INSN_COMPARE:
8018 if (insn->variant.compare.signed_comparison) {
8019 op = "v-cmps";
8020 } else {
8021 op = "v-cmpu";
8023 s390_sprintf(buf, "%M %R,%O", op, insn->variant.compare.src1,
8024 &insn->variant.compare.src2);
8025 break;
8027 case S390_INSN_HELPER_CALL: {
8028 s390_helper_call *helper_call = insn->variant.helper_call.details;
8029 s390_sprintf(buf, "%M if (%C) %s{%I}(%L)", "v-call",
8030 helper_call->cond,
8031 helper_call->name,
8032 helper_call->target,
8033 helper_call->num_args);
8034 return buf; /* avoid printing "size = ..." which is meaningless */
8037 case S390_INSN_BFP_TRIOP:
8038 switch (insn->variant.bfp_triop.tag) {
8039 case S390_BFP_MADD: op = "v-fmadd"; break;
8040 case S390_BFP_MSUB: op = "v-fmsub"; break;
8041 default: goto fail;
8043 s390_sprintf(buf, "%M %R,%R,%R", op,
8044 insn->variant.bfp_triop.dst /* op1 same as dst */,
8045 insn->variant.bfp_triop.op2, insn->variant.bfp_triop.op3);
8046 break;
8048 case S390_INSN_BFP_BINOP:
8049 switch (insn->variant.bfp_binop.tag) {
8050 case S390_BFP_ADD: op = "v-fadd"; break;
8051 case S390_BFP_SUB: op = "v-fsub"; break;
8052 case S390_BFP_MUL: op = "v-fmul"; break;
8053 case S390_BFP_DIV: op = "v-fdiv"; break;
8054 default: goto fail;
8056 s390_sprintf(buf, "%M %R,%R", op,
8057 insn->variant.bfp_binop.dst_hi /* op1 same as dst */,
8058 insn->variant.bfp_binop.op2_hi);
8059 break;
8061 case S390_INSN_BFP_COMPARE:
8062 s390_sprintf(buf, "%M %R,%R,%R", "v-fcmp", insn->variant.bfp_compare.dst,
8063 insn->variant.bfp_compare.op1_hi,
8064 insn->variant.bfp_compare.op2_hi);
8065 break;
8067 case S390_INSN_BFP_UNOP:
8068 switch (insn->variant.bfp_unop.tag) {
8069 case S390_BFP_ABS: op = "v-fabs"; break;
8070 case S390_BFP_NABS: op = "v-fnabs"; break;
8071 case S390_BFP_NEG: op = "v-fneg"; break;
8072 case S390_BFP_SQRT: op = "v-fsqrt"; break;
8073 default: goto fail;
8075 s390_sprintf(buf, "%M %R,%R", op, insn->variant.bfp_unop.dst_hi,
8076 insn->variant.bfp_unop.op_hi);
8077 break;
8079 case S390_INSN_BFP_CONVERT:
8080 switch (insn->variant.bfp_convert.tag) {
8081 case S390_BFP_I32_TO_F32:
8082 case S390_BFP_I32_TO_F64:
8083 case S390_BFP_I32_TO_F128:
8084 case S390_BFP_I64_TO_F32:
8085 case S390_BFP_I64_TO_F64:
8086 case S390_BFP_I64_TO_F128: op = "v-i2f"; break;
8087 case S390_BFP_U32_TO_F32:
8088 case S390_BFP_U32_TO_F64:
8089 case S390_BFP_U32_TO_F128:
8090 case S390_BFP_U64_TO_F32:
8091 case S390_BFP_U64_TO_F64:
8092 case S390_BFP_U64_TO_F128: op = "v-u2f"; break;
8093 case S390_BFP_F32_TO_I32:
8094 case S390_BFP_F32_TO_I64:
8095 case S390_BFP_F64_TO_I32:
8096 case S390_BFP_F64_TO_I64:
8097 case S390_BFP_F128_TO_I32:
8098 case S390_BFP_F128_TO_I64: op = "v-f2i"; break;
8099 case S390_BFP_F32_TO_U32:
8100 case S390_BFP_F32_TO_U64:
8101 case S390_BFP_F64_TO_U32:
8102 case S390_BFP_F64_TO_U64:
8103 case S390_BFP_F128_TO_U32:
8104 case S390_BFP_F128_TO_U64: op = "v-f2u"; break;
8105 case S390_BFP_F32_TO_F64:
8106 case S390_BFP_F32_TO_F128:
8107 case S390_BFP_F64_TO_F32:
8108 case S390_BFP_F64_TO_F128:
8109 case S390_BFP_F128_TO_F32:
8110 case S390_BFP_F128_TO_F64: op = "v-f2f"; break;
8111 case S390_BFP_F32_TO_F32I:
8112 case S390_BFP_F64_TO_F64I:
8113 case S390_BFP_F128_TO_F128I: op = "v-f2fi"; break;
8114 default: goto fail;
8116 s390_sprintf(buf, "%M %R,%R", op, insn->variant.bfp_convert.dst_hi,
8117 insn->variant.bfp_convert.op_hi);
8118 break;
8120 case S390_INSN_DFP_BINOP: {
8121 s390_dfp_binop *dfp_binop = insn->variant.dfp_binop.details;
8123 switch (dfp_binop->tag) {
8124 case S390_DFP_ADD: op = "v-dadd"; break;
8125 case S390_DFP_SUB: op = "v-dsub"; break;
8126 case S390_DFP_MUL: op = "v-dmul"; break;
8127 case S390_DFP_DIV: op = "v-ddiv"; break;
8128 case S390_DFP_QUANTIZE: op = "v-dqua"; break;
8129 default: goto fail;
8131 s390_sprintf(buf, "%M %R,%R,%R", op, dfp_binop->dst_hi,
8132 dfp_binop->op2_hi, dfp_binop->op3_hi);
8133 break;
8136 case S390_INSN_DFP_UNOP:
8137 switch (insn->variant.dfp_unop.tag) {
8138 case S390_DFP_EXTRACT_EXP_D64:
8139 case S390_DFP_EXTRACT_EXP_D128: op = "v-d2exp"; break;
8140 case S390_DFP_EXTRACT_SIG_D64:
8141 case S390_DFP_EXTRACT_SIG_D128: op = "v-d2sig"; break;
8142 default: goto fail;
8144 s390_sprintf(buf, "%M %R,%R", op, insn->variant.dfp_unop.dst_hi,
8145 insn->variant.dfp_unop.op_hi);
8146 break;
8148 case S390_INSN_DFP_INTOP:
8149 switch (insn->variant.dfp_intop.tag) {
8150 case S390_DFP_SHIFT_LEFT: op = "v-dshl"; break;
8151 case S390_DFP_SHIFT_RIGHT: op = "v-dshr"; break;
8152 case S390_DFP_INSERT_EXP: op = "v-diexp"; break;
8153 default: goto fail;
8155 s390_sprintf(buf, "%M %R,%R,%R", op, insn->variant.dfp_intop.dst_hi,
8156 insn->variant.dfp_intop.op2,
8157 insn->variant.dfp_intop.op3_hi);
8158 break;
8160 case S390_INSN_DFP_COMPARE:
8161 switch (insn->variant.dfp_compare.tag) {
8162 case S390_DFP_COMPARE: op = "v-dcmp"; break;
8163 case S390_DFP_COMPARE_EXP: op = "v-dcmpexp"; break;
8164 default: goto fail;
8166 s390_sprintf(buf, "%M %R,%R,%R", op, insn->variant.dfp_compare.dst,
8167 insn->variant.dfp_compare.op1_hi,
8168 insn->variant.dfp_compare.op2_hi);
8169 break;
8171 case S390_INSN_DFP_CONVERT:
8172 switch (insn->variant.dfp_convert.tag) {
8173 case S390_DFP_D32_TO_D64:
8174 case S390_DFP_D64_TO_D32:
8175 case S390_DFP_D64_TO_D128:
8176 case S390_DFP_D128_TO_D64: op = "v-d2d"; break;
8177 case S390_DFP_I32_TO_D64:
8178 case S390_DFP_I32_TO_D128:
8179 case S390_DFP_I64_TO_D64:
8180 case S390_DFP_I64_TO_D128: op = "v-i2d"; break;
8181 case S390_DFP_U32_TO_D64:
8182 case S390_DFP_U32_TO_D128:
8183 case S390_DFP_U64_TO_D64:
8184 case S390_DFP_U64_TO_D128: op = "v-u2d"; break;
8185 case S390_DFP_D64_TO_I32:
8186 case S390_DFP_D128_TO_I32:
8187 case S390_DFP_D64_TO_I64:
8188 case S390_DFP_D128_TO_I64: op = "v-d2i"; break;
8189 case S390_DFP_D64_TO_U32:
8190 case S390_DFP_D64_TO_U64:
8191 case S390_DFP_D128_TO_U32:
8192 case S390_DFP_D128_TO_U64: op = "v-d2u"; break;
8193 default: goto fail;
8195 s390_sprintf(buf, "%M %R,%R", op, insn->variant.dfp_convert.dst_hi,
8196 insn->variant.dfp_convert.op_hi);
8197 break;
8199 case S390_INSN_DFP_REROUND:
8200 s390_sprintf(buf, "%M %R,%R,%R", "v-drrnd",
8201 insn->variant.dfp_reround.dst_hi,
8202 insn->variant.dfp_reround.op2,
8203 insn->variant.dfp_reround.op3_hi);
8204 break;
8206 case S390_INSN_FP_CONVERT: {
8207 s390_fp_convert *fp_convert = insn->variant.fp_convert.details;
8209 switch (fp_convert->tag) {
8210 case S390_FP_F32_TO_D32:
8211 case S390_FP_F32_TO_D64:
8212 case S390_FP_F32_TO_D128:
8213 case S390_FP_F64_TO_D32:
8214 case S390_FP_F64_TO_D64:
8215 case S390_FP_F64_TO_D128:
8216 case S390_FP_F128_TO_D32:
8217 case S390_FP_F128_TO_D64:
8218 case S390_FP_F128_TO_D128: op = "v-f2d"; break;
8219 case S390_FP_D32_TO_F32:
8220 case S390_FP_D32_TO_F64:
8221 case S390_FP_D32_TO_F128:
8222 case S390_FP_D64_TO_F32:
8223 case S390_FP_D64_TO_F64:
8224 case S390_FP_D64_TO_F128:
8225 case S390_FP_D128_TO_F32:
8226 case S390_FP_D128_TO_F64:
8227 case S390_FP_D128_TO_F128: op = "v-d2f"; break;
8228 default: goto fail;
8230 s390_sprintf(buf, "%M %R,%R", op, fp_convert->dst_hi,
8231 fp_convert->op_hi);
8232 break;
8235 case S390_INSN_MFENCE:
8236 s390_sprintf(buf, "%M", "v-mfence");
8237 return buf; /* avoid printing "size = ..." which is meaningless */
8239 case S390_INSN_MIMM:
8240 s390_sprintf(buf, "%M %A,%I", "v-mimm", insn->variant.mimm.dst,
8241 insn->variant.mimm.value);
8242 break;
8244 case S390_INSN_MADD:
8245 s390_sprintf(buf, "%M %A += %I (= %I)", "v-madd",
8246 insn->variant.madd.dst,
8247 (Long)(Char)insn->variant.madd.delta,
8248 insn->variant.madd.value);
8249 break;
8251 case S390_INSN_SET_FPC_BFPRM:
8252 s390_sprintf(buf, "%M %R", "v-set-fpc-bfprm",
8253 insn->variant.set_fpc_bfprm.mode);
8254 break;
8256 case S390_INSN_SET_FPC_DFPRM:
8257 s390_sprintf(buf, "%M %R", "v-set-fpc-dfprm",
8258 insn->variant.set_fpc_dfprm.mode);
8259 break;
8261 case S390_INSN_EVCHECK:
8262 s390_sprintf(buf, "%M counter = %A, fail-addr = %A", "v-evcheck",
8263 insn->variant.evcheck.counter,
8264 insn->variant.evcheck.fail_addr);
8265 return buf; /* avoid printing "size = ..." which is meaningless */
8267 case S390_INSN_PROFINC:
8268 s390_sprintf(buf, "%M", "v-profinc");
8269 return buf; /* avoid printing "size = ..." which is meaningless */
8271 case S390_INSN_XDIRECT:
8272 s390_sprintf(buf, "%M if (%C) %A = %I %s", "v-xdirect",
8273 insn->variant.xdirect.cond,
8274 insn->variant.xdirect.guest_IA,
8275 insn->variant.xdirect.dst,
8276 insn->variant.xdirect.to_fast_entry ? "fast" : "slow");
8277 return buf; /* avoid printing "size = ..." which is meaningless */
8279 case S390_INSN_XINDIR:
8280 s390_sprintf(buf, "%M if (%C) %A = %R", "v-xindir",
8281 insn->variant.xindir.cond,
8282 insn->variant.xindir.guest_IA,
8283 insn->variant.xindir.dst);
8284 return buf; /* avoid printing "size = ..." which is meaningless */
8286 case S390_INSN_XASSISTED:
8287 s390_sprintf(buf, "%M if (%C) %J %A = %R", "v-xassisted",
8288 insn->variant.xassisted.cond,
8289 insn->variant.xassisted.kind,
8290 insn->variant.xassisted.guest_IA,
8291 insn->variant.xassisted.dst);
8292 return buf; /* avoid printing "size = ..." which is meaningless */
8294 case S390_INSN_VEC_AMODEOP:
8295 switch (insn->variant.vec_amodeop.tag) {
8296 case S390_VEC_GET_ELEM: op = "v-vgetelem"; break;
8297 case S390_VEC_ELEM_SHL_INT: op = "v-veshl"; break;
8298 case S390_VEC_ELEM_SHRA_INT: op = "v-veshra"; break;
8299 case S390_VEC_ELEM_SHRL_INT: op = "v-veshrl"; break;
8300 default: goto fail;
8302 s390_sprintf(buf, "%M %R, %R, %A", op, insn->variant.vec_amodeop.dst,
8303 insn->variant.vec_amodeop.op1,
8304 insn->variant.vec_amodeop.op2);
8305 break;
8307 case S390_INSN_VEC_AMODEINTOP:
8308 switch (insn->variant.vec_amodeintop.tag) {
8309 case S390_VEC_SET_ELEM: op = "v-vsetelem"; break;
8310 default: goto fail;
8312 s390_sprintf(buf, "%M %R, %A, %R", op, insn->variant.vec_amodeintop.dst,
8313 insn->variant.vec_amodeintop.op2,
8314 insn->variant.vec_amodeintop.op3);
8315 break;
8317 case S390_INSN_VEC_BINOP:
8318 switch (insn->variant.vec_binop.tag) {
8319 case S390_VEC_PACK: op = "v-vpack"; break;
8320 case S390_VEC_PACK_SATURS: op = "v-vpacksaturs"; break;
8321 case S390_VEC_PACK_SATURU: op = "v-vpacksaturu"; break;
8322 case S390_VEC_COMPARE_EQUAL: op = "v-vcmpeq"; break;
8323 case S390_VEC_OR: op = "v-vor"; break;
8324 case S390_VEC_ORC: op = "v-vorc"; break;
8325 case S390_VEC_XOR: op = "v-vxor"; break;
8326 case S390_VEC_AND: op = "v-vand"; break;
8327 case S390_VEC_MERGEL: op = "v-vmergel"; break;
8328 case S390_VEC_MERGEH: op = "v-vmergeh"; break;
8329 case S390_VEC_NOR: op = "v-vnor"; break;
8330 case S390_VEC_INT_ADD: op = "v-vintadd"; break;
8331 case S390_VEC_INT_SUB: op = "v-vintsub"; break;
8332 case S390_VEC_MAXU: op = "v-vmaxu"; break;
8333 case S390_VEC_MAXS: op = "v-vmaxs"; break;
8334 case S390_VEC_MINU: op = "v-vminu"; break;
8335 case S390_VEC_MINS: op = "v-vmins"; break;
8336 case S390_VEC_AVGU: op = "v-vavgu"; break;
8337 case S390_VEC_AVGS: op = "v-vavgs"; break;
8338 case S390_VEC_COMPARE_GREATERS: op = "v-vcmpgts"; break;
8339 case S390_VEC_COMPARE_GREATERU: op = "v-vcmpgtu"; break;
8340 case S390_VEC_INT_MUL_HIGHS: op = "v-vintmulhis"; break;
8341 case S390_VEC_INT_MUL_HIGHU: op = "v-vintmulhiu"; break;
8342 case S390_VEC_INT_MUL_LOW: op = "v-vintmullo"; break;
8343 case S390_VEC_INT_MUL_EVENS: op = "v-vintmulevens"; break;
8344 case S390_VEC_INT_MUL_EVENU: op = "v-vintmulevenu"; break;
8345 case S390_VEC_ELEM_SHL_V: op = "v-velemshl"; break;
8346 case S390_VEC_ELEM_SHRA_V: op = "v-vshrav"; break;
8347 case S390_VEC_ELEM_SHRL_V: op = "v-vshrlv"; break;
8348 case S390_VEC_ELEM_ROLL_V: op = "v-vrollv"; break;
8349 case S390_VEC_SHL_BITS: op = "v-vshlbits"; break;
8350 case S390_VEC_SHRL_BITS: op = "v-vshrlbits"; break;
8351 case S390_VEC_SHRA_BITS: op = "v-vshrabits"; break;
8352 case S390_VEC_SHL_BYTES: op = "v-vshlbytes"; break;
8353 case S390_VEC_SHRL_BYTES: op = "v-vshrlbytes"; break;
8354 case S390_VEC_SHRA_BYTES: op = "v-vshrabytes"; break;
8355 case S390_VEC_PWSUM_W: op = "v-vpwsumw"; break;
8356 case S390_VEC_PWSUM_DW: op = "v-vpwsumdw"; break;
8357 case S390_VEC_PWSUM_QW: op = "v-vpwsumqw"; break;
8358 case S390_VEC_INIT_FROM_GPRS: op = "v-vinitfromgprs"; break;
8359 case S390_VEC_INIT_FROM_FPRS: op = "v-vinitfromfprs"; break;
8360 case S390_VEC_FLOAT_ADD: op = "v-vfloatadd"; break;
8361 case S390_VEC_FLOAT_SUB: op = "v-vfloatsub"; break;
8362 case S390_VEC_FLOAT_MUL: op = "v-vfloatmul"; break;
8363 case S390_VEC_FLOAT_DIV: op = "v-vfloatdiv"; break;
8364 case S390_VEC_FLOAT_COMPARE_EQUAL: op = "v-vfloatcmpeq"; break;
8365 case S390_VEC_FLOAT_COMPARE_LESS_OR_EQUAL: op = "v-vfloatcmple"; break;
8366 case S390_VEC_FLOAT_COMPARE_LESS: op = "v-vfloatcmpl"; break;
8367 default: goto fail;
8369 s390_sprintf(buf, "%M %R, %R, %R", op, insn->variant.vec_binop.dst,
8370 insn->variant.vec_binop.op1, insn->variant.vec_binop.op2);
8371 break;
8373 case S390_INSN_VEC_TRIOP:
8374 switch (insn->variant.vec_triop.tag) {
8375 case S390_VEC_PERM: op = "v-vperm"; break;
8376 case S390_VEC_FLOAT_MADD: op = "v-vfloatmadd"; break;
8377 case S390_VEC_FLOAT_MSUB: op = "v-vfloatmsub"; break;
8378 default: goto fail;
8380 s390_sprintf(buf, "%M %R, %R, %R, %R", op, insn->variant.vec_triop.dst,
8381 insn->variant.vec_triop.op1, insn->variant.vec_triop.op2,
8382 insn->variant.vec_triop.op3);
8383 break;
8385 case S390_INSN_VEC_REPLICATE:
8386 s390_sprintf(buf, "%M %R, %R, %I", "v-vrep",
8387 insn->variant.vec_replicate.dst,
8388 insn->variant.vec_replicate.op1,
8389 insn->variant.vec_replicate.idx);
8390 break;
8392 default: goto fail;
8395 /* Write out how many bytes are involved in the operation */
8398 UInt len, i;
8400 for (p = buf; *p; ++p)
8401 continue;
8403 len = p - buf;
8405 if (len < 32) {
8406 for (i = len; i < 32; ++i)
8407 p += vex_sprintf(p, " ");
8408 } else {
8409 p += vex_sprintf(p, "\t");
8413 /* Special cases first */
8414 switch (insn->tag) {
8415 case S390_INSN_UNOP:
8416 switch (insn->variant.unop.tag) {
8417 case S390_SIGN_EXTEND_8:
8418 case S390_ZERO_EXTEND_8: p += vex_sprintf(p, "1 -> "); goto common;
8419 case S390_SIGN_EXTEND_16:
8420 case S390_ZERO_EXTEND_16: p += vex_sprintf(p, "2 -> "); goto common;
8421 case S390_SIGN_EXTEND_32:
8422 case S390_ZERO_EXTEND_32: p += vex_sprintf(p, "4 -> "); goto common;
8423 default:
8424 goto common;
8427 case S390_INSN_BFP_CONVERT:
8428 switch (insn->variant.bfp_convert.tag) {
8429 case S390_BFP_I32_TO_F32:
8430 case S390_BFP_I32_TO_F64:
8431 case S390_BFP_I32_TO_F128:
8432 case S390_BFP_U32_TO_F32:
8433 case S390_BFP_U32_TO_F64:
8434 case S390_BFP_U32_TO_F128:
8435 case S390_BFP_F32_TO_I32:
8436 case S390_BFP_F32_TO_I64:
8437 case S390_BFP_F32_TO_U32:
8438 case S390_BFP_F32_TO_U64:
8439 case S390_BFP_F32_TO_F64:
8440 case S390_BFP_F32_TO_F128: p += vex_sprintf(p, "4 -> "); goto common;
8441 case S390_BFP_I64_TO_F32:
8442 case S390_BFP_I64_TO_F64:
8443 case S390_BFP_I64_TO_F128:
8444 case S390_BFP_U64_TO_F32:
8445 case S390_BFP_U64_TO_F64:
8446 case S390_BFP_U64_TO_F128:
8447 case S390_BFP_F64_TO_I32:
8448 case S390_BFP_F64_TO_I64:
8449 case S390_BFP_F64_TO_U32:
8450 case S390_BFP_F64_TO_U64:
8451 case S390_BFP_F64_TO_F32:
8452 case S390_BFP_F64_TO_F128: p += vex_sprintf(p, "8 -> "); goto common;
8453 case S390_BFP_F128_TO_I32:
8454 case S390_BFP_F128_TO_I64:
8455 case S390_BFP_F128_TO_U32:
8456 case S390_BFP_F128_TO_U64:
8457 case S390_BFP_F128_TO_F32:
8458 case S390_BFP_F128_TO_F64: p += vex_sprintf(p, "16 -> "); goto common;
8459 default:
8460 goto common;
8463 case S390_INSN_DFP_CONVERT:
8464 switch (insn->variant.dfp_convert.tag) {
8465 case S390_DFP_D32_TO_D64:
8466 case S390_DFP_I32_TO_D64:
8467 case S390_DFP_I32_TO_D128:
8468 case S390_DFP_U32_TO_D64:
8469 case S390_DFP_U32_TO_D128: p += vex_sprintf(p, "4 -> "); goto common;
8470 case S390_DFP_D64_TO_D32:
8471 case S390_DFP_D64_TO_D128:
8472 case S390_DFP_I64_TO_D64:
8473 case S390_DFP_I64_TO_D128:
8474 case S390_DFP_U64_TO_D64:
8475 case S390_DFP_U64_TO_D128:
8476 case S390_DFP_D64_TO_I32:
8477 case S390_DFP_D64_TO_I64:
8478 case S390_DFP_D64_TO_U32:
8479 case S390_DFP_D64_TO_U64: p += vex_sprintf(p, "8 -> "); goto common;
8480 case S390_DFP_D128_TO_D64:
8481 case S390_DFP_D128_TO_I32:
8482 case S390_DFP_D128_TO_I64:
8483 case S390_DFP_D128_TO_U32:
8484 case S390_DFP_D128_TO_U64: p += vex_sprintf(p, "16 -> "); goto common;
8485 default:
8486 goto common;
8489 case S390_INSN_FP_CONVERT: {
8490 s390_fp_convert *fp_convert = insn->variant.fp_convert.details;
8492 switch (fp_convert->tag) {
8493 case S390_FP_F32_TO_D32:
8494 case S390_FP_F32_TO_D64:
8495 case S390_FP_F32_TO_D128:
8496 case S390_FP_D32_TO_F32:
8497 case S390_FP_D32_TO_F64:
8498 case S390_FP_D32_TO_F128: p += vex_sprintf(p, "4 -> "); goto common;
8499 case S390_FP_F64_TO_D32:
8500 case S390_FP_F64_TO_D64:
8501 case S390_FP_F64_TO_D128:
8502 case S390_FP_D64_TO_F32:
8503 case S390_FP_D64_TO_F64:
8504 case S390_FP_D64_TO_F128: p += vex_sprintf(p, "8 -> "); goto common;
8505 case S390_FP_F128_TO_D32:
8506 case S390_FP_F128_TO_D64:
8507 case S390_FP_F128_TO_D128:
8508 case S390_FP_D128_TO_F32:
8509 case S390_FP_D128_TO_F64:
8510 case S390_FP_D128_TO_F128: p += vex_sprintf(p, "16 -> "); goto common;
8511 default:
8512 goto common;
8516 default:
8517 goto common;
8520 /* Common case */
8521 common:
8522 vex_sprintf(p, "%u bytes", (UInt)insn->size);
8524 return buf;
8526 fail: vpanic("s390_insn_as_string");
8531 /* Load NUM bytes from memory into register REG using addressing mode AM. */
8532 static UChar *
8533 s390_emit_load_mem(UChar *p, UInt num, UChar reg, const s390_amode *am)
8535 UInt b = hregNumber(am->b);
8536 UInt x = hregNumber(am->x); /* 0 for B12 and B20 */
8537 UInt d = am->d;
8539 switch (am->tag) {
8540 case S390_AMODE_B12:
8541 case S390_AMODE_BX12:
8542 switch (num) {
8543 case 1: return s390_emit_IC(p, reg, x, b, d);
8544 case 2: return s390_emit_LH(p, reg, x, b, d);
8545 case 4: return s390_emit_L(p, reg, x, b, d);
8546 case 8: return s390_emit_LG(p, reg, x, b, DISP20(d));
8547 case 16: return s390_emit_VL(p, reg, x, b, d);
8548 default: goto fail;
8550 break;
8552 case S390_AMODE_B20:
8553 case S390_AMODE_BX20:
8554 switch (num) {
8555 case 1: return s390_emit_ICY(p, reg, x, b, DISP20(d));
8556 case 2: return s390_emit_LHY(p, reg, x, b, DISP20(d));
8557 case 4: return s390_emit_LY(p, reg, x, b, DISP20(d));
8558 case 8: return s390_emit_LG(p, reg, x, b, DISP20(d));
8559 default: goto fail;
8561 break;
8563 default: goto fail;
8566 fail:
8567 vpanic("s390_emit_load_mem");
8571 /* Load condition code into register REG */
8572 static UChar *
8573 s390_emit_load_cc(UChar *p, UChar reg)
8575 p = s390_emit_LGHI(p, reg, 0); /* Clear out, cc not affected */
8576 p = s390_emit_IPM(p, reg, reg);
8577 /* Shift 28 bits to the right --> [0,1,2,3] */
8578 return s390_emit_SRL(p, reg, 0, 28); /* REG = cc */
8582 /*---------------------------------------------------------------*/
8583 /*--- Code generation ---*/
8584 /*---------------------------------------------------------------*/
8586 /* Do not load more bytes than requested. */
8587 static UChar *
8588 s390_insn_load_emit(UChar *buf, const s390_insn *insn)
8590 UInt r, x, b, d;
8591 const s390_amode *src;
8593 src = insn->variant.load.src;
8595 r = hregNumber(insn->variant.load.dst);
8597 if (hregClass(insn->variant.load.dst) == HRcFlt64) {
8598 b = hregNumber(src->b);
8599 x = hregNumber(src->x); /* 0 for B12 and B20 */
8600 d = src->d;
8602 switch (insn->size) {
8604 case 4:
8605 switch (src->tag) {
8606 case S390_AMODE_B12:
8607 case S390_AMODE_BX12:
8608 return s390_emit_LE(buf, r, x, b, d);
8610 case S390_AMODE_B20:
8611 case S390_AMODE_BX20:
8612 return s390_emit_LEY(buf, r, x, b, DISP20(d));
8614 break;
8616 case 8:
8617 switch (src->tag) {
8618 case S390_AMODE_B12:
8619 case S390_AMODE_BX12:
8620 return s390_emit_LD(buf, r, x, b, d);
8622 case S390_AMODE_B20:
8623 case S390_AMODE_BX20:
8624 return s390_emit_LDY(buf, r, x, b, DISP20(d));
8626 break;
8628 vpanic("s390_insn_load_emit");
8631 /* Integer stuff */
8632 return s390_emit_load_mem(buf, insn->size, r, src);
8636 static UChar *
8637 s390_insn_store_emit(UChar *buf, const s390_insn *insn)
8639 UInt r, x, b, d;
8640 const s390_amode *dst;
8642 dst = insn->variant.store.dst;
8644 r = hregNumber(insn->variant.store.src);
8645 b = hregNumber(dst->b);
8646 x = hregNumber(dst->x); /* 0 for B12 and B20 */
8647 d = dst->d;
8649 if (hregClass(insn->variant.store.src) == HRcFlt64) {
8650 switch (insn->size) {
8652 case 4:
8653 switch (dst->tag) {
8654 case S390_AMODE_B12:
8655 case S390_AMODE_BX12:
8656 return s390_emit_STE(buf, r, x, b, d);
8658 case S390_AMODE_B20:
8659 case S390_AMODE_BX20:
8660 return s390_emit_STEY(buf, r, x, b, DISP20(d));
8662 break;
8664 case 8:
8665 switch (dst->tag) {
8666 case S390_AMODE_B12:
8667 case S390_AMODE_BX12:
8668 return s390_emit_STD(buf, r, x, b, d);
8670 case S390_AMODE_B20:
8671 case S390_AMODE_BX20:
8672 return s390_emit_STDY(buf, r, x, b, DISP20(d));
8674 break;
8676 vpanic("s390_insn_store_emit");
8679 if (hregClass(insn->variant.store.src) == HRcVec128) {
8680 vassert(insn->size == 16);
8681 switch (dst->tag) {
8682 case S390_AMODE_B12:
8683 case S390_AMODE_BX12:
8684 return s390_emit_VST(buf, r, x, b, d);
8686 default:
8687 vpanic("s390_insn_store_emit: unknown dst->tag for HRcVec128");
8690 /* Integer stuff */
8691 switch (insn->size) {
8692 case 1:
8693 switch (dst->tag) {
8694 case S390_AMODE_B12:
8695 case S390_AMODE_BX12:
8696 return s390_emit_STC(buf, r, x, b, d);
8698 case S390_AMODE_B20:
8699 case S390_AMODE_BX20:
8700 return s390_emit_STCY(buf, r, x, b, DISP20(d));
8702 break;
8704 case 2:
8705 switch (dst->tag) {
8706 case S390_AMODE_B12:
8707 case S390_AMODE_BX12:
8708 return s390_emit_STH(buf, r, x, b, d);
8710 case S390_AMODE_B20:
8711 case S390_AMODE_BX20:
8712 return s390_emit_STHY(buf, r, x, b, DISP20(d));
8714 break;
8716 case 4:
8717 switch (dst->tag) {
8718 case S390_AMODE_B12:
8719 case S390_AMODE_BX12:
8720 return s390_emit_ST(buf, r, x, b, d);
8722 case S390_AMODE_B20:
8723 case S390_AMODE_BX20:
8724 return s390_emit_STY(buf, r, x, b, DISP20(d));
8726 break;
8728 case 8:
8729 return s390_emit_STG(buf, r, x, b, DISP20(d));
8731 default:
8732 break;
8735 vpanic("s390_insn_store_emit");
8739 static UChar *
8740 s390_insn_move_emit(UChar *buf, const s390_insn *insn)
8742 UInt dst, src;
8743 HRegClass dst_class, src_class;
8745 dst = hregNumber(insn->variant.move.dst);
8746 src = hregNumber(insn->variant.move.src);
8748 dst_class = hregClass(insn->variant.move.dst);
8749 src_class = hregClass(insn->variant.move.src);
8751 if (dst_class == src_class) {
8752 if (dst_class == HRcInt64)
8753 return s390_emit_LGR(buf, dst, src);
8754 if (dst_class == HRcFlt64)
8755 return s390_emit_LDR(buf, dst, src);
8756 if (dst_class == HRcVec128) {
8757 return s390_emit_VLR(buf, dst, src);
8759 } else {
8760 if (dst_class == HRcFlt64 && src_class == HRcInt64) {
8761 if (insn->size == 4) {
8762 buf = s390_emit_SLLG(buf, R0, src, 0, DISP20(32)); /* r0 = src << 32 */
8763 return s390_emit_LDGRw(buf, dst, R0);
8764 } else {
8765 return s390_emit_LDGRw(buf, dst, src);
8768 if (dst_class == HRcInt64 && src_class == HRcFlt64) {
8769 if (insn->size == 4) {
8770 buf = s390_emit_LGDRw(buf, dst, src);
8771 return s390_emit_SRLG(buf, dst, dst, 0, DISP20(32)); /* dst >>= 32 */
8772 } else {
8773 return s390_emit_LGDRw(buf, dst, src);
8776 if (dst_class == HRcFlt64 && src_class == HRcVec128) {
8777 return s390_emit_VLR(buf, dst, src);
8779 /* A move between floating point registers and general purpose
8780 registers of different size should never occur and indicates
8781 an error elsewhere. */
8784 vpanic("s390_insn_move_emit");
8788 static UChar *
8789 s390_insn_memcpy_emit(UChar *buf, const s390_insn *insn)
8791 s390_amode *dst = insn->variant.memcpy.dst;
8792 s390_amode *src = insn->variant.memcpy.src;
8794 return s390_emit_MVC(buf, insn->size - 1, hregNumber(dst->b), dst->d,
8795 hregNumber(src->b), src->d);
8799 static UChar *
8800 s390_insn_load_immediate_emit(UChar *buf, const s390_insn *insn)
8802 UInt r;
8803 ULong value = insn->variant.load_immediate.value;
8805 r = hregNumber(insn->variant.load_immediate.dst);
8807 if (hregClass(insn->variant.load_immediate.dst) == HRcFlt64) {
8808 vassert(value == 0);
8809 switch (insn->size) {
8810 case 4: return s390_emit_LZER(buf, r, value);
8811 case 8: return s390_emit_LZDR(buf, r, value);
8813 vpanic("s390_insn_load_immediate_emit");
8816 switch (insn->size) {
8817 case 1:
8818 case 2:
8819 /* Load the immediate values as a 4 byte value. That does not hurt as
8820 those extra bytes will not be looked at. Fall through .... */
8821 case 4:
8822 return s390_emit_load_32imm(buf, r, value);
8824 case 8:
8825 return s390_emit_load_64imm(buf, r, value);
8828 vpanic("s390_insn_load_immediate_emit");
8832 /* Insert low half of r2 into high half of dst. */
8833 static UChar *
8834 s390_emit_ilih(UChar *buf, UChar size, UChar dst, UChar r2)
8836 if (s390_host_has_gie)
8837 return s390_emit_RISBG(buf, dst, r2, 64 - 8 * size, 63 - 4 * size,
8838 4 * size);
8840 /* Clear dst's upper half. */
8841 buf = s390_emit_SLLG(buf, dst, dst, 0, DISP20(64 - 4 * size));
8842 buf = s390_emit_SRLG(buf, dst, dst, 0, DISP20(64 - 4 * size));
8844 /* Shift r2 by appropriate amount and OR it into dst. */
8845 buf = s390_emit_SLLG(buf, R0, r2, 0, DISP20(4 * size));
8846 return s390_emit_OGR(buf, dst, R0);
8850 /* There is no easy way to do ALU operations on 1-byte or 2-byte operands.
8851 So we simply perform a 4-byte operation. Doing so uses possibly undefined
8852 bits and produces an undefined result in those extra bit positions. But
8853 upstream does not look at those positions, so this is OK. */
8854 static UChar *
8855 s390_insn_alu_emit(UChar *buf, const s390_insn *insn)
8857 s390_opnd_RMI op2;
8858 UInt dst;
8860 dst = hregNumber(insn->variant.alu.dst);
8861 op2 = insn->variant.alu.op2;
8863 /* Second operand is in a register */
8864 if (op2.tag == S390_OPND_REG) {
8865 UInt r2 = hregNumber(op2.variant.reg);
8867 switch (insn->size) {
8868 case 1:
8869 case 2:
8870 case 4:
8871 switch (insn->variant.alu.tag) {
8872 case S390_ALU_ADD: return s390_emit_AR(buf, dst, r2);
8873 case S390_ALU_SUB: return s390_emit_SR(buf, dst, r2);
8874 case S390_ALU_MUL: return s390_emit_MSR(buf, dst, r2);
8875 case S390_ALU_AND: return s390_emit_NR(buf, dst, r2);
8876 case S390_ALU_OR: return s390_emit_OR(buf, dst, r2);
8877 case S390_ALU_XOR: return s390_emit_XR(buf, dst, r2);
8878 case S390_ALU_LSH: return s390_emit_SLL(buf, dst, r2, 0);
8879 case S390_ALU_RSH: return s390_emit_SRL(buf, dst, r2, 0);
8880 case S390_ALU_RSHA: return s390_emit_SRA(buf, dst, r2, 0);
8881 case S390_ALU_ILIH: return s390_emit_ilih(buf, insn->size, dst, r2);
8883 goto fail;
8885 case 8:
8886 switch (insn->variant.alu.tag) {
8887 case S390_ALU_ADD: return s390_emit_AGR(buf, dst, r2);
8888 case S390_ALU_SUB: return s390_emit_SGR(buf, dst, r2);
8889 case S390_ALU_MUL: return s390_emit_MSGR(buf, dst, r2);
8890 case S390_ALU_AND: return s390_emit_NGR(buf, dst, r2);
8891 case S390_ALU_OR: return s390_emit_OGR(buf, dst, r2);
8892 case S390_ALU_XOR: return s390_emit_XGR(buf, dst, r2);
8893 case S390_ALU_LSH: return s390_emit_SLLG(buf, dst, dst, r2, DISP20(0));
8894 case S390_ALU_RSH: return s390_emit_SRLG(buf, dst, dst, r2, DISP20(0));
8895 case S390_ALU_RSHA: return s390_emit_SRAG(buf, dst, dst, r2, DISP20(0));
8896 case S390_ALU_ILIH: return s390_emit_ilih(buf, 8, dst, r2);
8898 goto fail;
8900 goto fail;
8903 /* 2nd operand is in memory */
8904 if (op2.tag == S390_OPND_AMODE) {
8905 UInt b, x, d;
8906 const s390_amode *src = op2.variant.am;
8908 b = hregNumber(src->b);
8909 x = hregNumber(src->x); /* 0 for B12 and B20 */
8910 d = src->d;
8912 /* Shift operands are special here as there are no opcodes that
8913 allow a memory operand. So we first load the 2nd operand into
8914 some register. R0 is used to save restore the contents of the
8915 chosen register.. */
8917 if (insn->variant.alu.tag == S390_ALU_LSH ||
8918 insn->variant.alu.tag == S390_ALU_RSH ||
8919 insn->variant.alu.tag == S390_ALU_RSHA) {
8920 UInt b2;
8922 /* Choose a register (other than DST or R0) into which to stick the
8923 shift amount. The following works because r15 is reserved and
8924 thusly dst != 15. */
8925 vassert(dst != 15); /* extra paranoia */
8926 b2 = (dst + 1) % 16;
8928 buf = s390_emit_LGR(buf, R0, b2); /* save */
8930 /* Loading SRC to B2 does not modify R0. */
8931 buf = s390_emit_load_mem(buf, insn->size, b2, src);
8933 if (insn->size == 8) {
8934 switch (insn->variant.alu.tag) {
8935 case S390_ALU_LSH:
8936 buf = s390_emit_SLLG(buf, dst, dst, b2, DISP20(0));
8937 break;
8938 case S390_ALU_RSH:
8939 buf = s390_emit_SRLG(buf, dst, dst, b2, DISP20(0));
8940 break;
8941 case S390_ALU_RSHA:
8942 buf = s390_emit_SRAG(buf, dst, dst, b2, DISP20(0));
8943 break;
8944 default: /* unreachable */
8945 goto fail;
8947 } else {
8948 switch (insn->variant.alu.tag) {
8949 case S390_ALU_LSH:
8950 buf = s390_emit_SLL(buf, dst, b2, 0);
8951 break;
8952 case S390_ALU_RSH:
8953 buf = s390_emit_SRL(buf, dst, b2, 0);
8954 break;
8955 case S390_ALU_RSHA:
8956 buf = s390_emit_SRA(buf, dst, b2, 0);
8957 break;
8958 default: /* unreachable */
8959 goto fail;
8962 return s390_emit_LGR(buf, b2, R0); /* restore */
8965 switch (insn->size) {
8966 case 1:
8967 /* Move the byte from memory into scratch register r0 */
8968 buf = s390_emit_load_mem(buf, 1, R0, src);
8970 switch (insn->variant.alu.tag) {
8971 case S390_ALU_ADD: return s390_emit_AR(buf, dst, R0);
8972 case S390_ALU_SUB: return s390_emit_SR(buf, dst, R0);
8973 case S390_ALU_MUL: return s390_emit_MSR(buf, dst, R0);
8974 case S390_ALU_AND: return s390_emit_NR(buf, dst, R0);
8975 case S390_ALU_OR: return s390_emit_OR(buf, dst, R0);
8976 case S390_ALU_XOR: return s390_emit_XR(buf, dst, R0);
8977 case S390_ALU_ILIH:
8978 case S390_ALU_LSH:
8979 case S390_ALU_RSH:
8980 case S390_ALU_RSHA: ; /* avoid GCC warning */
8982 goto fail;
8984 case 2:
8985 switch (src->tag) {
8986 case S390_AMODE_B12:
8987 case S390_AMODE_BX12:
8988 switch (insn->variant.alu.tag) {
8989 case S390_ALU_ADD:
8990 return s390_emit_AH(buf, dst, x, b, d);
8992 case S390_ALU_SUB:
8993 return s390_emit_SH(buf, dst, x, b, d);
8995 case S390_ALU_MUL:
8996 return s390_emit_MH(buf, dst, x, b, d);
8998 /* For bitwise operations: Move two bytes from memory into scratch
8999 register r0; then perform operation */
9000 case S390_ALU_AND:
9001 buf = s390_emit_LH(buf, R0, x, b, d);
9002 return s390_emit_NR(buf, dst, R0);
9004 case S390_ALU_OR:
9005 buf = s390_emit_LH(buf, R0, x, b, d);
9006 return s390_emit_OR(buf, dst, R0);
9008 case S390_ALU_XOR:
9009 buf = s390_emit_LH(buf, R0, x, b, d);
9010 return s390_emit_XR(buf, dst, R0);
9012 case S390_ALU_ILIH:
9013 case S390_ALU_LSH:
9014 case S390_ALU_RSH:
9015 case S390_ALU_RSHA: ; /* avoid GCC warning */
9017 goto fail;
9019 case S390_AMODE_B20:
9020 case S390_AMODE_BX20:
9021 switch (insn->variant.alu.tag) {
9022 case S390_ALU_ADD:
9023 return s390_emit_AHY(buf, dst, x, b, DISP20(d));
9025 case S390_ALU_SUB:
9026 return s390_emit_SHY(buf, dst, x, b, DISP20(d));
9028 case S390_ALU_MUL:
9029 return s390_emit_MHYw(buf, dst, x, b, DISP20(d));
9031 /* For bitwise operations: Move two bytes from memory into scratch
9032 register r0; then perform operation */
9033 case S390_ALU_AND:
9034 buf = s390_emit_LHY(buf, R0, x, b, DISP20(d));
9035 return s390_emit_NR(buf, dst, R0);
9037 case S390_ALU_OR:
9038 buf = s390_emit_LHY(buf, R0, x, b, DISP20(d));
9039 return s390_emit_OR(buf, dst, R0);
9041 case S390_ALU_XOR:
9042 buf = s390_emit_LHY(buf, R0, x, b, DISP20(d));
9043 return s390_emit_XR(buf, dst, R0);
9045 case S390_ALU_ILIH:
9046 case S390_ALU_LSH:
9047 case S390_ALU_RSH:
9048 case S390_ALU_RSHA: ; /* avoid GCC warning */
9050 goto fail;
9052 goto fail;
9054 case 4:
9055 switch (src->tag) {
9056 case S390_AMODE_B12:
9057 case S390_AMODE_BX12:
9058 switch (insn->variant.alu.tag) {
9059 case S390_ALU_ADD: return s390_emit_A(buf, dst, x, b, d);
9060 case S390_ALU_SUB: return s390_emit_S(buf, dst, x, b, d);
9061 case S390_ALU_MUL: return s390_emit_MS(buf, dst, x, b, d);
9062 case S390_ALU_AND: return s390_emit_N(buf, dst, x, b, d);
9063 case S390_ALU_OR: return s390_emit_O(buf, dst, x, b, d);
9064 case S390_ALU_XOR: return s390_emit_X(buf, dst, x, b, d);
9065 case S390_ALU_ILIH:
9066 case S390_ALU_LSH:
9067 case S390_ALU_RSH:
9068 case S390_ALU_RSHA: ; /* avoid GCC warning */
9070 goto fail;
9072 case S390_AMODE_B20:
9073 case S390_AMODE_BX20:
9074 switch (insn->variant.alu.tag) {
9075 case S390_ALU_ADD: return s390_emit_AY(buf, dst, x, b, DISP20(d));
9076 case S390_ALU_SUB: return s390_emit_SY(buf, dst, x, b, DISP20(d));
9077 case S390_ALU_MUL: return s390_emit_MSY(buf, dst, x, b, DISP20(d));
9078 case S390_ALU_AND: return s390_emit_NY(buf, dst, x, b, DISP20(d));
9079 case S390_ALU_OR: return s390_emit_OY(buf, dst, x, b, DISP20(d));
9080 case S390_ALU_XOR: return s390_emit_XY(buf, dst, x, b, DISP20(d));
9081 case S390_ALU_ILIH:
9082 case S390_ALU_LSH:
9083 case S390_ALU_RSH:
9084 case S390_ALU_RSHA: ; /* avoid GCC warning */
9086 goto fail;
9088 goto fail;
9090 case 8:
9091 switch (insn->variant.alu.tag) {
9092 case S390_ALU_ADD: return s390_emit_AG(buf, dst, x, b, DISP20(d));
9093 case S390_ALU_SUB: return s390_emit_SG(buf, dst, x, b, DISP20(d));
9094 case S390_ALU_MUL: return s390_emit_MSG(buf, dst, x, b, DISP20(d));
9095 case S390_ALU_AND: return s390_emit_NG(buf, dst, x, b, DISP20(d));
9096 case S390_ALU_OR: return s390_emit_OG(buf, dst, x, b, DISP20(d));
9097 case S390_ALU_XOR: return s390_emit_XG(buf, dst, x, b, DISP20(d));
9098 case S390_ALU_ILIH:
9099 case S390_ALU_LSH:
9100 case S390_ALU_RSH:
9101 case S390_ALU_RSHA: ; /* avoid GCC warning */
9103 goto fail;
9105 goto fail;
9108 /* 2nd operand is an immediate value */
9109 if (op2.tag == S390_OPND_IMMEDIATE) {
9110 ULong value;
9112 /* No masking of the value is required as it is not sign extended */
9113 value = op2.variant.imm;
9115 switch (insn->size) {
9116 case 1:
9117 case 2:
9118 /* There is no 1-byte opcode. Do the computation in
9119 2 bytes. The extra byte will be ignored. */
9120 switch (insn->variant.alu.tag) {
9121 case S390_ALU_ADD:
9122 return s390_emit_AHI(buf, dst, value);
9124 case S390_ALU_SUB:
9125 return s390_emit_SLFIw(buf, dst, value);
9127 case S390_ALU_MUL:
9128 return s390_emit_MHI(buf, dst, value);
9130 case S390_ALU_AND: return s390_emit_NILL(buf, dst, value);
9131 case S390_ALU_OR: return s390_emit_OILL(buf, dst, value);
9132 case S390_ALU_XOR:
9133 /* There is no XILL instruction. Load the immediate value into
9134 R0 and combine with the destination register. */
9135 buf = s390_emit_LHI(buf, R0, value);
9136 return s390_emit_XR(buf, dst, R0);
9138 case S390_ALU_LSH:
9139 return s390_emit_SLL(buf, dst, 0, value);
9141 case S390_ALU_RSH:
9142 return s390_emit_SRL(buf, dst, 0, value);
9144 case S390_ALU_RSHA:
9145 return s390_emit_SRA(buf, dst, 0, value);
9147 case S390_ALU_ILIH: ; /* avoid GCC warning */
9149 goto fail;
9151 case 4:
9152 switch (insn->variant.alu.tag) {
9153 case S390_ALU_ADD:
9154 if (uint_fits_signed_16bit(value)) {
9155 return s390_emit_AHI(buf, dst, value);
9157 return s390_emit_AFIw(buf, dst, value);
9159 case S390_ALU_SUB: return s390_emit_SLFIw(buf, dst, value);
9160 case S390_ALU_MUL: return s390_emit_MSFIw(buf, dst, value);
9161 case S390_ALU_AND: return s390_emit_NILFw(buf, dst, value);
9162 case S390_ALU_OR: return s390_emit_OILFw(buf, dst, value);
9163 case S390_ALU_XOR: return s390_emit_XILFw(buf, dst, value);
9164 case S390_ALU_LSH: return s390_emit_SLL(buf, dst, 0, value);
9165 case S390_ALU_RSH: return s390_emit_SRL(buf, dst, 0, value);
9166 case S390_ALU_RSHA: return s390_emit_SRA(buf, dst, 0, value);
9167 case S390_ALU_ILIH: ; /* avoid GCC warning */
9169 goto fail;
9171 case 8:
9172 switch (insn->variant.alu.tag) {
9173 case S390_ALU_ADD:
9174 if (ulong_fits_signed_16bit(value)) {
9175 return s390_emit_AGHI(buf, dst, value);
9177 if (ulong_fits_signed_32bit(value) && s390_host_has_eimm) {
9178 return s390_emit_AGFI(buf, dst, value);
9180 /* Load constant into R0 then add */
9181 buf = s390_emit_load_64imm(buf, R0, value);
9182 return s390_emit_AGR(buf, dst, R0);
9184 case S390_ALU_SUB:
9185 if (ulong_fits_unsigned_32bit(value)) {
9186 return s390_emit_SLGFIw(buf, dst, value);
9188 /* Load value into R0; then subtract from destination reg */
9189 buf = s390_emit_load_64imm(buf, R0, value);
9190 return s390_emit_SGR(buf, dst, R0);
9192 case S390_ALU_MUL:
9193 if (ulong_fits_signed_32bit(value) && s390_host_has_gie) {
9194 return s390_emit_MSGFI(buf, dst, value);
9196 /* Load constant into R0 then add */
9197 buf = s390_emit_load_64imm(buf, R0, value);
9198 return s390_emit_MSGR(buf, dst, R0);
9200 /* Do it in two steps: upper half [0:31] and lower half [32:63] */
9201 case S390_ALU_AND:
9202 if (s390_host_has_eimm) {
9203 buf = s390_emit_NIHF(buf, dst, value >> 32);
9204 return s390_emit_NILF(buf, dst, value & 0xFFFFFFFF);
9206 /* Load value into R0; then combine with destination reg */
9207 buf = s390_emit_load_64imm(buf, R0, value);
9208 return s390_emit_NGR(buf, dst, R0);
9210 case S390_ALU_OR:
9211 if (s390_host_has_eimm) {
9212 buf = s390_emit_OIHF(buf, dst, value >> 32);
9213 return s390_emit_OILF(buf, dst, value & 0xFFFFFFFF);
9215 /* Load value into R0; then combine with destination reg */
9216 buf = s390_emit_load_64imm(buf, R0, value);
9217 return s390_emit_OGR(buf, dst, R0);
9219 case S390_ALU_XOR:
9220 if (s390_host_has_eimm) {
9221 buf = s390_emit_XIHF(buf, dst, value >> 32);
9222 return s390_emit_XILF(buf, dst, value & 0xFFFFFFFF);
9224 /* Load value into R0; then combine with destination reg */
9225 buf = s390_emit_load_64imm(buf, R0, value);
9226 return s390_emit_XGR(buf, dst, R0);
9228 /* No special considerations for long displacement here. Only the six
9229 least significant bits of VALUE will be taken; all other bits are
9230 ignored. So the DH2 bits are irrelevant and do not influence the
9231 shift operation, independent of whether long-displacement is available
9232 or not. */
9233 case S390_ALU_LSH: return s390_emit_SLLG(buf, dst, dst, 0, DISP20(value));
9234 case S390_ALU_RSH: return s390_emit_SRLG(buf, dst, dst, 0, DISP20(value));
9235 case S390_ALU_RSHA: return s390_emit_SRAG(buf, dst, dst, 0, DISP20(value));
9236 case S390_ALU_ILIH: ; /* avoid GCC warning */
9238 goto fail;
9240 goto fail;
9243 fail:
9244 vpanic("s390_insn_alu_emit");
9248 static UChar *
9249 s390_widen_emit(UChar *buf, const s390_insn *insn, UInt from_size,
9250 Bool sign_extend)
9252 s390_opnd_RMI opnd = insn->variant.unop.src;
9254 switch (opnd.tag) {
9255 case S390_OPND_REG: {
9256 UChar r1 = hregNumber(insn->variant.unop.dst);
9257 UChar r2 = hregNumber(opnd.variant.reg);
9259 switch (from_size) {
9260 case 1:
9261 /* Widening to a half-word is implemented like widening to a word
9262 because the upper half-word will not be looked at. */
9263 if (insn->size == 4 || insn->size == 2) { /* 8 --> 32 8 --> 16 */
9264 if (sign_extend)
9265 return s390_emit_LBRw(buf, r1, r2);
9266 else
9267 return s390_emit_LLCRw(buf, r1, r2);
9269 if (insn->size == 8) { /* 8 --> 64 */
9270 if (sign_extend)
9271 return s390_emit_LGBRw(buf, r1, r2);
9272 else
9273 return s390_emit_LLGCRw(buf, r1, r2);
9275 goto fail;
9277 case 2:
9278 if (insn->size == 4) { /* 16 --> 32 */
9279 if (sign_extend)
9280 return s390_emit_LHRw(buf, r1, r2);
9281 else
9282 return s390_emit_LLHRw(buf, r1, r2);
9284 if (insn->size == 8) { /* 16 --> 64 */
9285 if (sign_extend)
9286 return s390_emit_LGHRw(buf, r1, r2);
9287 else
9288 return s390_emit_LLGHRw(buf, r1, r2);
9290 goto fail;
9292 case 4:
9293 if (insn->size == 8) { /* 32 --> 64 */
9294 if (sign_extend)
9295 return s390_emit_LGFR(buf, r1, r2);
9296 else
9297 return s390_emit_LLGFR(buf, r1, r2);
9299 goto fail;
9301 default: /* unexpected "from" size */
9302 goto fail;
9306 case S390_OPND_AMODE: {
9307 UChar r1 = hregNumber(insn->variant.unop.dst);
9308 const s390_amode *src = opnd.variant.am;
9309 UChar b = hregNumber(src->b);
9310 UChar x = hregNumber(src->x);
9311 Int d = src->d;
9313 switch (from_size) {
9314 case 1:
9315 if (insn->size == 4 || insn->size == 2) {
9316 if (sign_extend)
9317 return s390_emit_LB(buf, r1, x, b, DISP20(d));
9318 else
9319 return s390_emit_LLCw(buf, r1, x, b, DISP20(d));
9321 if (insn->size == 8) {
9322 if (sign_extend)
9323 return s390_emit_LGB(buf, r1, x, b, DISP20(d));
9324 else
9325 return s390_emit_LLGC(buf, r1, x, b, DISP20(d));
9327 goto fail;
9329 case 2:
9330 if (insn->size == 4) { /* 16 --> 32 */
9331 if (sign_extend == 0)
9332 return s390_emit_LLHw(buf, r1, x, b, DISP20(d));
9334 switch (src->tag) {
9335 case S390_AMODE_B12:
9336 case S390_AMODE_BX12:
9337 return s390_emit_LH(buf, r1, x, b, d);
9339 case S390_AMODE_B20:
9340 case S390_AMODE_BX20:
9341 return s390_emit_LHY(buf, r1, x, b, DISP20(d));
9343 goto fail;
9345 if (insn->size == 8) { /* 16 --> 64 */
9346 if (sign_extend)
9347 return s390_emit_LGH(buf, r1, x, b, DISP20(d));
9348 else
9349 return s390_emit_LLGH(buf, r1, x, b, DISP20(d));
9351 goto fail;
9353 case 4:
9354 if (insn->size == 8) { /* 32 --> 64 */
9355 if (sign_extend)
9356 return s390_emit_LGF(buf, r1, x, b, DISP20(d));
9357 else
9358 return s390_emit_LLGF(buf, r1, x, b, DISP20(d));
9360 goto fail;
9362 default: /* unexpected "from" size */
9363 goto fail;
9367 case S390_OPND_IMMEDIATE: {
9368 UChar r1 = hregNumber(insn->variant.unop.dst);
9369 ULong value = opnd.variant.imm;
9371 switch (from_size) {
9372 case 1:
9373 if (insn->size == 4 || insn->size == 2) { /* 8 --> 32 8 --> 16 */
9374 if (sign_extend) {
9375 /* host can do the sign extension to 16-bit; LHI does the rest */
9376 return s390_emit_LHI(buf, r1, (Short)(Char)(UChar)value);
9377 } else {
9378 return s390_emit_LHI(buf, r1, value);
9381 if (insn->size == 8) { /* 8 --> 64 */
9382 if (sign_extend) {
9383 /* host can do the sign extension to 16-bit; LGHI does the rest */
9384 return s390_emit_LGHI(buf, r1, (Short)(Char)(UChar)value);
9385 } else {
9386 return s390_emit_LGHI(buf, r1, value);
9389 goto fail;
9391 case 2:
9392 if (insn->size == 4) { /* 16 --> 32 */
9393 return s390_emit_LHI(buf, r1, value);
9395 if (insn->size == 8) { /* 16 --> 64 */
9396 if (sign_extend)
9397 return s390_emit_LGHI(buf, r1, value);
9398 else
9399 return s390_emit_LLILL(buf, r1, value);
9401 goto fail;
9403 case 4:
9404 if (insn->size == 8) { /* 32 --> 64 */
9405 if (sign_extend)
9406 return s390_emit_LGFIw(buf, r1, value);
9407 else
9408 return s390_emit_LLILFw(buf, r1, value);
9410 goto fail;
9412 default: /* unexpected "from" size */
9413 goto fail;
9418 fail:
9419 vpanic("s390_widen_emit");
9423 static UChar *
9424 s390_negate_emit(UChar *buf, const s390_insn *insn)
9426 s390_opnd_RMI opnd;
9428 opnd = insn->variant.unop.src;
9430 switch (opnd.tag) {
9431 case S390_OPND_REG: {
9432 UChar r1 = hregNumber(insn->variant.unop.dst);
9433 UChar r2 = hregNumber(opnd.variant.reg);
9435 switch (insn->size) {
9436 case 1:
9437 case 2:
9438 case 4:
9439 return s390_emit_LCR(buf, r1, r2);
9441 case 8:
9442 return s390_emit_LCGR(buf, r1, r2);
9444 default:
9445 goto fail;
9449 case S390_OPND_AMODE: {
9450 UChar r1 = hregNumber(insn->variant.unop.dst);
9452 /* Load bytes into scratch register R0, then negate */
9453 buf = s390_emit_load_mem(buf, insn->size, R0, opnd.variant.am);
9455 switch (insn->size) {
9456 case 1:
9457 case 2:
9458 case 4:
9459 return s390_emit_LCR(buf, r1, R0);
9461 case 8:
9462 return s390_emit_LCGR(buf, r1, R0);
9464 default:
9465 goto fail;
9469 case S390_OPND_IMMEDIATE: {
9470 UChar r1 = hregNumber(insn->variant.unop.dst);
9471 ULong value = opnd.variant.imm;
9473 value = ~value + 1; /* two's complement */
9475 switch (insn->size) {
9476 case 1:
9477 case 2:
9478 /* Load the immediate values as a 4 byte value. That does not hurt as
9479 those extra bytes will not be looked at. Fall through .... */
9480 case 4:
9481 return s390_emit_load_32imm(buf, r1, value);
9483 case 8:
9484 return s390_emit_load_64imm(buf, r1, value);
9486 default:
9487 goto fail;
9492 fail:
9493 vpanic("s390_negate_emit");
9497 static UChar *
9498 s390_vec_duplicate_emit(UChar *buf, const s390_insn *insn)
9500 UChar v1 = hregNumber(insn->variant.unop.dst);
9501 s390_opnd_RMI opnd = insn->variant.unop.src;
9502 UChar r2;
9504 switch (opnd.tag) {
9505 case S390_OPND_AMODE: {
9506 s390_amode* am = opnd.variant.am;
9507 UInt b = hregNumber(am->b);
9508 UInt x = hregNumber(am->x);
9509 UInt d = am->d;
9511 if (fits_unsigned_12bit(d)) {
9512 return s390_emit_VLREP(buf, v1, x, b, d,
9513 s390_getM_from_size(insn->size));
9515 buf = s390_emit_load_mem(buf, insn->size, R0, am);
9516 r2 = R0;
9517 goto duplicate_from_gpr;
9520 case S390_OPND_IMMEDIATE: {
9521 ULong val = opnd.variant.imm;
9523 if (ulong_fits_signed_16bit(val)) {
9524 return s390_emit_VREPI(buf, v1, val, s390_getM_from_size(insn->size));
9526 buf = s390_emit_load_64imm(buf, R0, val);
9527 r2 = R0;
9528 goto duplicate_from_gpr;
9531 case S390_OPND_REG:
9532 r2 = hregNumber(opnd.variant.reg);
9534 duplicate_from_gpr:
9535 buf = s390_emit_VLVGP(buf, v1, r2, r2);
9536 if (insn->size != 8) {
9537 buf = s390_emit_VREP(buf, v1, v1, 8 / insn->size - 1,
9538 s390_getM_from_size(insn->size));
9540 return buf;
9543 vpanic("s390_vec_duplicate_emit");
9547 static UChar *
9548 s390_insn_unop_emit(UChar *buf, const s390_insn *insn)
9550 switch (insn->variant.unop.tag) {
9551 case S390_ZERO_EXTEND_8: return s390_widen_emit(buf, insn, 1, 0);
9552 case S390_ZERO_EXTEND_16: return s390_widen_emit(buf, insn, 2, 0);
9553 case S390_ZERO_EXTEND_32: return s390_widen_emit(buf, insn, 4, 0);
9555 case S390_SIGN_EXTEND_8: return s390_widen_emit(buf, insn, 1, 1);
9556 case S390_SIGN_EXTEND_16: return s390_widen_emit(buf, insn, 2, 1);
9557 case S390_SIGN_EXTEND_32: return s390_widen_emit(buf, insn, 4, 1);
9559 case S390_NEGATE: return s390_negate_emit(buf, insn);
9560 case S390_VEC_FILL: {
9561 vassert(insn->variant.unop.src.tag == S390_OPND_IMMEDIATE);
9562 UChar v1 = hregNumber(insn->variant.unop.dst);
9563 UShort i2 = insn->variant.unop.src.variant.imm;
9564 return s390_emit_VGBM(buf, v1, i2);
9566 case S390_VEC_DUPLICATE: return s390_vec_duplicate_emit(buf, insn);
9567 case S390_VEC_UNPACKLOWS: {
9568 vassert(insn->variant.unop.src.tag == S390_OPND_REG);
9569 vassert(insn->size < 8);
9570 UChar v1 = hregNumber(insn->variant.unop.dst);
9571 UChar v2 = hregNumber(insn->variant.unop.src.variant.reg);
9572 return s390_emit_VUPH(buf, v1, v2, s390_getM_from_size(insn->size));
9574 case S390_VEC_UNPACKLOWU: {
9575 vassert(insn->variant.unop.src.tag == S390_OPND_REG);
9576 vassert(insn->size < 8);
9577 UChar v1 = hregNumber(insn->variant.unop.dst);
9578 UChar v2 = hregNumber(insn->variant.unop.src.variant.reg);
9579 return s390_emit_VUPLH(buf, v1, v2, s390_getM_from_size(insn->size));
9582 case S390_VEC_ABS:{
9583 vassert(insn->variant.unop.src.tag == S390_OPND_REG);
9584 UChar v1 = hregNumber(insn->variant.unop.dst);
9585 UChar v2 = hregNumber(insn->variant.unop.src.variant.reg);
9586 return s390_emit_VLP(buf, v1, v2, s390_getM_from_size(insn->size));
9589 case S390_VEC_COUNT_LEADING_ZEROES:{
9590 vassert(insn->variant.unop.src.tag == S390_OPND_REG);
9591 UChar v1 = hregNumber(insn->variant.unop.dst);
9592 UChar v2 = hregNumber(insn->variant.unop.src.variant.reg);
9593 return s390_emit_VCLZ(buf, v1, v2, s390_getM_from_size(insn->size));
9596 case S390_VEC_COUNT_TRAILING_ZEROES:{
9597 vassert(insn->variant.unop.src.tag == S390_OPND_REG);
9598 UChar v1 = hregNumber(insn->variant.unop.dst);
9599 UChar v2 = hregNumber(insn->variant.unop.src.variant.reg);
9600 return s390_emit_VCTZ(buf, v1, v2, s390_getM_from_size(insn->size));
9603 case S390_VEC_COUNT_ONES:{
9604 vassert(insn->variant.unop.src.tag == S390_OPND_REG);
9605 UChar v1 = hregNumber(insn->variant.unop.dst);
9606 UChar v2 = hregNumber(insn->variant.unop.src.variant.reg);
9607 return s390_emit_VPOPCT(buf, v1, v2, s390_getM_from_size(insn->size));
9610 case S390_VEC_FLOAT_NEG: {
9611 vassert(insn->variant.unop.src.tag == S390_OPND_REG);
9612 vassert(insn->size >= 4);
9613 UChar v1 = hregNumber(insn->variant.unop.dst);
9614 UChar v2 = hregNumber(insn->variant.unop.src.variant.reg);
9615 return s390_emit_VFPSO(buf, v1, v2, s390_getM_from_size(insn->size), 0, 0);
9617 case S390_VEC_FLOAT_ABS: {
9618 vassert(insn->variant.unop.src.tag == S390_OPND_REG);
9619 vassert(insn->size >= 4);
9620 UChar v1 = hregNumber(insn->variant.unop.dst);
9621 UChar v2 = hregNumber(insn->variant.unop.src.variant.reg);
9622 return s390_emit_VFPSO(buf, v1, v2, s390_getM_from_size(insn->size), 0, 2);
9624 case S390_VEC_FLOAT_NABS: {
9625 vassert(insn->variant.unop.src.tag == S390_OPND_REG);
9626 vassert(insn->size >= 4);
9627 UChar v1 = hregNumber(insn->variant.unop.dst);
9628 UChar v2 = hregNumber(insn->variant.unop.src.variant.reg);
9629 return s390_emit_VFPSO(buf, v1, v2, s390_getM_from_size(insn->size), 0, 1);
9631 case S390_VEC_FLOAT_SQRT: {
9632 vassert(insn->variant.unop.src.tag == S390_OPND_REG);
9633 vassert(insn->size >= 4);
9634 UChar v1 = hregNumber(insn->variant.unop.dst);
9635 UChar v2 = hregNumber(insn->variant.unop.src.variant.reg);
9636 return s390_emit_VFSQ(buf, v1, v2, s390_getM_from_size(insn->size), 0);
9638 default:
9639 vpanic("s390_insn_unop_emit");
9644 /* Test operand for zero. */
9645 static UChar *
9646 s390_insn_test_emit(UChar *buf, const s390_insn *insn)
9648 s390_opnd_RMI opnd;
9650 opnd = insn->variant.test.src;
9652 switch (opnd.tag) {
9653 case S390_OPND_REG: {
9654 UInt reg = hregNumber(opnd.variant.reg);
9656 switch (insn->size) {
9657 case 1:
9658 return s390_emit_TMLL(buf, reg, 0xff);
9660 case 2:
9661 return s390_emit_TMLL(buf, reg, 0xffff);
9663 case 4:
9664 return s390_emit_LTR(buf, reg, reg);
9666 case 8:
9667 return s390_emit_LTGR(buf, reg, reg);
9669 default:
9670 goto fail;
9674 case S390_OPND_AMODE: {
9675 const s390_amode *am = opnd.variant.am;
9676 UChar b = hregNumber(am->b);
9677 UChar x = hregNumber(am->x);
9678 Int d = am->d;
9680 switch (insn->size) {
9681 case 1:
9682 switch (am->tag) {
9683 case S390_AMODE_B12:
9684 return s390_emit_TM(buf, 0xff, b, d);
9685 case S390_AMODE_B20:
9686 return s390_emit_TMY(buf, 0xff, b, DISP20(d));
9687 default:
9688 buf = s390_emit_LB(buf, R0, x, b, DISP20(d));
9689 return s390_emit_TMLL(buf, R0, 0xff);
9692 case 2:
9693 switch (am->tag) {
9694 case S390_AMODE_B12:
9695 buf = s390_emit_LH(buf, R0, x, b, d);
9696 return s390_emit_TMLL(buf, R0, 0xffff);
9697 default:
9698 buf = s390_emit_LHY(buf, R0, x, b, DISP20(d));
9699 return s390_emit_TMLL(buf, R0, 0xffff);
9702 case 4:
9703 return s390_emit_LTw(buf, R0, x, b, DISP20(d));
9705 case 8:
9706 return s390_emit_LTGw(buf, R0, x, b, DISP20(d));
9708 default:
9709 goto fail;
9713 case S390_OPND_IMMEDIATE: {
9714 if (opnd.variant.imm == 0)
9715 return s390_emit_CR(buf, R0, R0);
9716 else
9717 return s390_emit_OILL(buf, R0, 1);
9720 default:
9721 goto fail;
9724 fail:
9725 vpanic("s390_insn_test_emit");
9729 static UChar *
9730 s390_insn_cc2bool_emit(UChar *buf, const s390_insn *insn)
9732 UChar r1 = hregNumber(insn->variant.cc2bool.dst);
9733 s390_cc_t cond = insn->variant.cc2bool.cond;
9735 /* Make the destination register be -1 or 0, depending on whether
9736 the relevant condition holds. A 64-bit value is computed. */
9737 if (cond == S390_CC_ALWAYS)
9738 return s390_emit_LGHI(buf, r1, -1); /* r1 = -1 */
9740 /* If LOCGHI is available, use it. */
9741 if (s390_host_has_lsc2) {
9742 /* Clear r1, then load immediate -1 on condition. */
9743 buf = s390_emit_LGHI(buf, r1, 0);
9744 if (cond != S390_CC_NEVER)
9745 buf = s390_emit_LOCGHI(buf, r1, -1, cond);
9746 return buf;
9749 buf = s390_emit_load_cc(buf, r1); /* r1 = cc */
9750 buf = s390_emit_LGHI(buf, R0, cond); /* r0 = mask */
9751 buf = s390_emit_SLLG(buf, r1, R0, r1, DISP20(60)); /* r1 = mask << (cc+60) */
9752 buf = s390_emit_SRAG(buf, r1, r1, 0, DISP20(63)); /* r1 = r1 >> 63 */
9754 return buf;
9758 /* Only 4-byte and 8-byte operands are handled. */
9759 static UChar *
9760 s390_insn_cas_emit(UChar *buf, const s390_insn *insn)
9762 UChar r1, r3, b, old;
9763 Int d;
9764 s390_amode *am;
9766 r1 = hregNumber(insn->variant.cas.op1); /* expected value */
9767 r3 = hregNumber(insn->variant.cas.op3);
9768 old= hregNumber(insn->variant.cas.old_mem);
9769 am = insn->variant.cas.op2;
9770 b = hregNumber(am->b);
9771 d = am->d;
9773 vassert(am->tag == S390_AMODE_B12 || am->tag == S390_AMODE_B20);
9775 switch (insn->size) {
9776 case 4:
9777 /* r1 must not be overwritten. So copy it to R0 and let CS clobber it */
9778 buf = s390_emit_LR(buf, R0, r1);
9779 if (am->tag == S390_AMODE_B12)
9780 buf = s390_emit_CS(buf, R0, r3, b, d);
9781 else
9782 buf = s390_emit_CSY(buf, R0, r3, b, DISP20(d));
9783 /* Now copy R0 which has the old memory value to OLD */
9784 return s390_emit_LR(buf, old, R0);
9786 case 8:
9787 /* r1 must not be overwritten. So copy it to R0 and let CS clobber it */
9788 buf = s390_emit_LGR(buf, R0, r1);
9789 buf = s390_emit_CSG(buf, R0, r3, b, DISP20(d));
9790 /* Now copy R0 which has the old memory value to OLD */
9791 return s390_emit_LGR(buf, old, R0);
9793 default:
9794 goto fail;
9797 fail:
9798 vpanic("s390_insn_cas_emit");
9802 /* Only 4-byte and 8-byte operands are handled. */
9803 static UChar *
9804 s390_insn_cdas_emit(UChar *buf, const s390_insn *insn)
9806 UChar r1, r1p1, r3, /*r3p1,*/ b, old_high, old_low, scratch;
9807 Int d;
9808 s390_amode *am;
9809 s390_cdas *cdas = insn->variant.cdas.details;
9811 r1 = hregNumber(cdas->op1_high); /* expected value */
9812 r1p1 = hregNumber(cdas->op1_low); /* expected value */
9813 r3 = hregNumber(cdas->op3_high);
9814 /* r3p1 = hregNumber(cdas->op3_low); */ /* unused */
9815 old_high = hregNumber(cdas->old_mem_high);
9816 old_low = hregNumber(cdas->old_mem_low);
9817 scratch = hregNumber(cdas->scratch);
9818 am = cdas->op2;
9819 b = hregNumber(am->b);
9820 d = am->d;
9822 vassert(scratch == 1);
9823 vassert(am->tag == S390_AMODE_B12 || am->tag == S390_AMODE_B20);
9825 switch (insn->size) {
9826 case 4:
9827 /* r1, r1+1 must not be overwritten. So copy them to R0,scratch
9828 and let CDS/CDSY clobber it */
9829 buf = s390_emit_LR(buf, R0, r1);
9830 buf = s390_emit_LR(buf, scratch, r1p1);
9832 if (am->tag == S390_AMODE_B12)
9833 buf = s390_emit_CDS(buf, R0, r3, b, d);
9834 else
9835 buf = s390_emit_CDSY(buf, R0, r3, b, DISP20(d));
9837 /* Now copy R0,scratch which has the old memory value to OLD */
9838 buf = s390_emit_LR(buf, old_high, R0);
9839 buf = s390_emit_LR(buf, old_low, scratch);
9840 return buf;
9842 case 8:
9843 /* r1, r1+1 must not be overwritten. So copy them to R0,scratch
9844 and let CDSG clobber it */
9845 buf = s390_emit_LGR(buf, R0, r1);
9846 buf = s390_emit_LGR(buf, scratch, r1p1);
9848 buf = s390_emit_CDSG(buf, R0, r3, b, DISP20(d));
9850 /* Now copy R0,scratch which has the old memory value to OLD */
9851 buf = s390_emit_LGR(buf, old_high, R0);
9852 buf = s390_emit_LGR(buf, old_low, scratch);
9853 return buf;
9855 default:
9856 goto fail;
9859 fail:
9860 vpanic("s390_insn_cdas_emit");
9864 /* Only 4-byte and 8-byte comparisons are handled. 1-byte and 2-byte
9865 comparisons will have been converted to 4-byte comparisons in
9866 s390_isel_cc and should not occur here. */
9867 static UChar *
9868 s390_insn_compare_emit(UChar *buf, const s390_insn *insn)
9870 s390_opnd_RMI op2;
9871 HReg op1;
9872 Bool signed_comparison;
9874 op1 = insn->variant.compare.src1;
9875 op2 = insn->variant.compare.src2;
9876 signed_comparison = insn->variant.compare.signed_comparison;
9878 switch (op2.tag) {
9879 case S390_OPND_REG: {
9880 UInt r1 = hregNumber(op1);
9881 UInt r2 = hregNumber(op2.variant.reg);
9883 switch (insn->size) {
9884 case 4:
9885 if (signed_comparison)
9886 return s390_emit_CR(buf, r1, r2);
9887 else
9888 return s390_emit_CLR(buf, r1, r2);
9890 case 8:
9891 if (signed_comparison)
9892 return s390_emit_CGR(buf, r1, r2);
9893 else
9894 return s390_emit_CLGR(buf, r1, r2);
9896 default:
9897 goto fail;
9901 case S390_OPND_AMODE: {
9902 UChar r1 = hregNumber(op1);
9903 const s390_amode *am = op2.variant.am;
9904 UChar b = hregNumber(am->b);
9905 UChar x = hregNumber(am->x);
9906 Int d = am->d;
9908 switch (insn->size) {
9909 case 4:
9910 switch (am->tag) {
9911 case S390_AMODE_B12:
9912 case S390_AMODE_BX12:
9913 if (signed_comparison)
9914 return s390_emit_C(buf, r1, x, b, d);
9915 else
9916 return s390_emit_CL(buf, r1, x, b, d);
9918 case S390_AMODE_B20:
9919 case S390_AMODE_BX20:
9920 if (signed_comparison)
9921 return s390_emit_CY(buf, r1, x, b, DISP20(d));
9922 else
9923 return s390_emit_CLY(buf, r1, x, b, DISP20(d));
9925 goto fail;
9927 case 8:
9928 if (signed_comparison)
9929 return s390_emit_CG(buf, r1, x, b, DISP20(d));
9930 else
9931 return s390_emit_CLG(buf, r1, x, b, DISP20(d));
9933 default:
9934 goto fail;
9938 case S390_OPND_IMMEDIATE: {
9939 UChar r1 = hregNumber(op1);
9940 ULong value = op2.variant.imm;
9942 switch (insn->size) {
9943 case 4:
9944 if (signed_comparison)
9945 return s390_emit_CFIw(buf, r1, value);
9946 else
9947 return s390_emit_CLFIw(buf, r1, value);
9949 case 8:
9950 if (s390_host_has_eimm) {
9951 if (signed_comparison) {
9952 if (ulong_fits_signed_32bit(value))
9953 return s390_emit_CGFI(buf, r1, value);
9954 } else {
9955 if (ulong_fits_unsigned_32bit(value))
9956 return s390_emit_CLGFI(buf, r1, value);
9959 buf = s390_emit_load_64imm(buf, R0, value);
9960 if (signed_comparison)
9961 return s390_emit_CGR(buf, r1, R0);
9962 else
9963 return s390_emit_CLGR(buf, r1, R0);
9965 default:
9966 goto fail;
9970 default:
9971 goto fail;
9974 fail:
9975 vpanic("s390_insn_compare_emit");
9979 static UChar *
9980 s390_insn_mul_emit(UChar *buf, const s390_insn *insn)
9982 s390_opnd_RMI op2;
9983 UChar r1;
9984 Bool signed_multiply;
9986 /* The register number identifying the register pair */
9987 r1 = hregNumber(insn->variant.mul.dst_hi);
9989 op2 = insn->variant.mul.op2;
9990 signed_multiply = insn->tag == S390_INSN_SMUL;
9992 switch (op2.tag) {
9993 case S390_OPND_REG: {
9994 UInt r2 = hregNumber(op2.variant.reg);
9996 switch (insn->size) {
9997 case 1:
9998 case 2:
9999 case 4:
10000 if (signed_multiply)
10001 return s390_emit_MR(buf, r1, r2);
10002 else
10003 return s390_emit_MLR(buf, r1, r2);
10005 case 8:
10006 if (signed_multiply)
10007 return s390_emit_MGRK(buf, r1 + 1, r1, r2);
10008 else
10009 return s390_emit_MLGR(buf, r1, r2);
10011 default:
10012 goto fail;
10016 case S390_OPND_AMODE: {
10017 const s390_amode *am = op2.variant.am;
10018 UChar b = hregNumber(am->b);
10019 UChar x = hregNumber(am->x);
10020 Int d = am->d;
10022 switch (insn->size) {
10023 case 1:
10024 case 2:
10025 /* Load bytes into scratch register R0, then multiply */
10026 buf = s390_emit_load_mem(buf, insn->size, R0, am);
10027 if (signed_multiply)
10028 return s390_emit_MR(buf, r1, R0);
10029 else
10030 return s390_emit_MLR(buf, r1, R0);
10032 case 4:
10033 switch (am->tag) {
10034 case S390_AMODE_B12:
10035 case S390_AMODE_BX12:
10036 if (signed_multiply)
10037 return s390_emit_M(buf, r1, x, b, d);
10038 else
10039 return s390_emit_ML(buf, r1, x, b, DISP20(d));
10041 case S390_AMODE_B20:
10042 case S390_AMODE_BX20:
10043 if (signed_multiply)
10044 return s390_emit_MFYw(buf, r1, x, b, DISP20(d));
10045 else
10046 return s390_emit_ML(buf, r1, x, b, DISP20(d));
10048 goto fail;
10050 case 8:
10051 if (signed_multiply)
10052 return s390_emit_MG(buf, r1, x, b, DISP20(d));
10053 else
10054 return s390_emit_MLG(buf, r1, x, b, DISP20(d));
10056 default:
10057 goto fail;
10061 case S390_OPND_IMMEDIATE: {
10062 ULong value = op2.variant.imm;
10064 switch (insn->size) {
10065 case 1:
10066 case 2:
10067 case 4:
10068 buf = s390_emit_load_32imm(buf, R0, value);
10069 if (signed_multiply)
10070 return s390_emit_MR(buf, r1, R0);
10071 else
10072 return s390_emit_MLR(buf, r1, R0);
10074 case 8:
10075 buf = s390_emit_load_64imm(buf, R0, value);
10076 if (signed_multiply)
10077 return s390_emit_MGRK(buf, r1 + 1, r1, R0);
10078 else
10079 return s390_emit_MLGR(buf, r1, R0);
10081 default:
10082 goto fail;
10086 default:
10087 goto fail;
10090 fail:
10091 vpanic("s390_insn_mul_emit");
10095 static UChar *
10096 s390_insn_div_emit(UChar *buf, const s390_insn *insn)
10098 s390_opnd_RMI op2;
10099 UChar r1;
10100 Bool signed_divide;
10102 r1 = hregNumber(insn->variant.div.op1_hi);
10103 op2 = insn->variant.div.op2;
10104 signed_divide = insn->tag == S390_INSN_SDIV;
10106 switch (op2.tag) {
10107 case S390_OPND_REG: {
10108 UInt r2 = hregNumber(op2.variant.reg);
10110 switch (insn->size) {
10111 case 4:
10112 if (signed_divide)
10113 return s390_emit_DR(buf, r1, r2);
10114 else
10115 return s390_emit_DLR(buf, r1, r2);
10117 case 8:
10118 if (signed_divide)
10119 vpanic("s390_insn_div_emit");
10120 else
10121 return s390_emit_DLGR(buf, r1, r2);
10123 default:
10124 goto fail;
10128 case S390_OPND_AMODE: {
10129 const s390_amode *am = op2.variant.am;
10130 UChar b = hregNumber(am->b);
10131 UChar x = hregNumber(am->x);
10132 Int d = am->d;
10134 switch (insn->size) {
10135 case 4:
10136 switch (am->tag) {
10137 case S390_AMODE_B12:
10138 case S390_AMODE_BX12:
10139 if (signed_divide)
10140 return s390_emit_D(buf, r1, x, b, d);
10141 else
10142 return s390_emit_DL(buf, r1, x, b, DISP20(d));
10144 case S390_AMODE_B20:
10145 case S390_AMODE_BX20:
10146 if (signed_divide) {
10147 buf = s390_emit_LY(buf, R0, x, b, DISP20(d));
10148 return s390_emit_DR(buf, r1, R0);
10149 } else
10150 return s390_emit_DL(buf, r1, x, b, DISP20(d));
10152 goto fail;
10154 case 8:
10155 if (signed_divide)
10156 vpanic("s390_insn_div_emit");
10157 else
10158 return s390_emit_DLG(buf, r1, x, b, DISP20(d));
10160 default:
10161 goto fail;
10165 case S390_OPND_IMMEDIATE: {
10166 ULong value = op2.variant.imm;
10168 switch (insn->size) {
10169 case 4:
10170 buf = s390_emit_load_32imm(buf, R0, value);
10171 if (signed_divide)
10172 return s390_emit_DR(buf, r1, R0);
10173 else
10174 return s390_emit_DLR(buf, r1, R0);
10176 case 8:
10177 buf = s390_emit_load_64imm(buf, R0, value);
10178 if (signed_divide)
10179 vpanic("s390_insn_div_emit");
10180 else
10181 return s390_emit_DLGR(buf, r1, R0);
10183 default:
10184 goto fail;
10188 default:
10189 goto fail;
10192 fail:
10193 vpanic("s390_insn_div_emit");
10197 static UChar *
10198 s390_insn_divs_emit(UChar *buf, const s390_insn *insn)
10200 s390_opnd_RMI op2;
10201 UChar r1;
10203 r1 = hregNumber(insn->variant.divs.rem);
10204 op2 = insn->variant.divs.op2;
10206 switch (op2.tag) {
10207 case S390_OPND_REG: {
10208 UInt r2 = hregNumber(op2.variant.reg);
10210 return s390_emit_DSGR(buf, r1, r2);
10213 case S390_OPND_AMODE: {
10214 const s390_amode *am = op2.variant.am;
10215 UChar b = hregNumber(am->b);
10216 UChar x = hregNumber(am->x);
10217 Int d = am->d;
10219 return s390_emit_DSG(buf, r1, x, b, DISP20(d));
10222 case S390_OPND_IMMEDIATE: {
10223 ULong value = op2.variant.imm;
10225 buf = s390_emit_load_64imm(buf, R0, value);
10226 return s390_emit_DSGR(buf, r1, R0);
10229 default:
10230 goto fail;
10233 fail:
10234 vpanic("s390_insn_divs_emit");
10238 static UChar *
10239 s390_insn_clz_emit(UChar *buf, const s390_insn *insn)
10241 s390_opnd_RMI src;
10242 UChar r1, r1p1, r2, *p;
10244 r1 = hregNumber(insn->variant.clz.num_bits);
10245 r1p1 = hregNumber(insn->variant.clz.clobber);
10247 vassert((r1 & 0x1) == 0);
10248 vassert(r1p1 == r1 + 1);
10250 p = buf;
10251 src = insn->variant.clz.src;
10253 /* Get operand and move it to r2 */
10254 switch (src.tag) {
10255 case S390_OPND_REG:
10256 r2 = hregNumber(src.variant.reg);
10257 break;
10259 case S390_OPND_AMODE: {
10260 const s390_amode *am = src.variant.am;
10261 UChar b = hregNumber(am->b);
10262 UChar x = hregNumber(am->x);
10263 Int d = am->d;
10265 p = s390_emit_LG(p, R0, x, b, DISP20(d));
10266 r2 = R0;
10267 break;
10270 case S390_OPND_IMMEDIATE: {
10271 ULong value = src.variant.imm;
10273 p = s390_emit_load_64imm(p, R0, value);
10274 r2 = R0;
10275 break;
10278 default:
10279 goto fail;
10282 /* Use FLOGR if you can */
10283 if (s390_host_has_eimm) {
10284 return s390_emit_FLOGR(p, r1, r2);
10288 r0 = r2;
10289 r1 = 64;
10290 while (r0 != 0) {
10291 r1 -= 1;
10292 r0 >>= 1;
10295 p = s390_emit_LTGR(p, R0, r2);
10296 p = s390_emit_LLILL(p, r1, 64);
10298 p = s390_emit_BRC(p, S390_CC_E, (4 + 4 + 6 + 4 + 4)/ 2); /* 4 bytes */
10299 p = s390_emit_AGHI(p, r1, (UShort)-1); /* r1 -= 1; 4 bytes */
10300 p = s390_emit_SRLG(p, R0, R0, R0, DISP20(1)); /* r0 >>= 1; 6 bytes */
10301 p = s390_emit_LTGR(p, R0, R0); /* set cc 4 bytes */
10302 p = s390_emit_BRC(p, S390_CC_NE, /* 4 bytes */
10303 (UShort)(-(4 + 6 + 4) / 2));
10304 return p;
10306 fail:
10307 vpanic("s390_insn_clz_emit");
10311 /* Returns a value == BUF to denote failure, != BUF to denote success. */
10312 static UChar *
10313 s390_insn_helper_call_emit(UChar *buf, const s390_insn *insn)
10315 s390_cc_t cond;
10316 ULong target;
10317 Int delta;
10318 s390_helper_call *helper_call = insn->variant.helper_call.details;
10320 cond = helper_call->cond;
10321 target = helper_call->target;
10323 const Bool not_always = (cond != S390_CC_ALWAYS);
10324 const Bool not_void_return = (helper_call->rloc.pri != RLPri_None);
10326 /* We have this situation:
10327 ( *** code in this braces is for not_always && not_void_return*** )
10329 before:
10330 brc{!cond} else
10331 call_helper
10332 preElse:
10333 *** j after ***
10334 else:
10335 *** load_64imm $0x5555555555555555, %%r2 *** // e.g. for Int RetLoc
10336 after:
10340 // before:
10341 UChar *pBefore = buf;
10342 if (not_always) {
10343 /* 4 bytes (a BRC insn) to be filled in here */
10344 buf += 4;
10347 // call_helper
10348 /* Load the target address into a register, that
10349 (a) is not used for passing parameters to the helper and
10350 (b) can be clobbered by the callee
10351 (c) is not special to the BASR insn
10352 r1 is the only choice.
10353 Also, need to arrange for the return address be put into the
10354 link-register */
10355 buf = s390_emit_load_64imm(buf, 1, target);
10357 /* Stash away the client's FPC register because the helper might change it. */
10358 buf = s390_emit_STFPC(buf, S390_REGNO_STACK_POINTER, S390_OFFSET_SAVED_FPC_C);
10360 buf = s390_emit_BASR(buf, S390_REGNO_LINK_REGISTER, 1); // call helper
10362 buf = s390_emit_LFPC(buf, S390_REGNO_STACK_POINTER, // restore FPC
10363 S390_OFFSET_SAVED_FPC_C);
10365 // preElse:
10366 UChar* pPreElse = buf;
10367 if (not_always && not_void_return) {
10368 /* 4 bytes (a BRC insn) to be filled in here */
10369 buf += 4;
10372 // else:
10373 UChar* pElse = buf;
10374 if (not_always && not_void_return) {
10375 switch (helper_call->rloc.pri) {
10376 case RLPri_Int:
10377 buf = s390_emit_load_64imm(buf, S390_REGNO_RETURN_VALUE, 0x5555555555555555ULL);
10378 break;
10379 default:
10380 ppS390Instr(insn, True);
10381 vpanic("s390_insn_helper_call_emit: invalid conditional RetLoc.");
10385 // after:
10386 UChar* pAfter = buf;
10388 // fill "brc{!cond} else"
10389 if(not_always)
10391 delta = pElse - pBefore;
10392 delta >>= 1; /* immediate constant is #half-words */
10393 vassert(delta > 0 && delta < (1 << 16));
10394 s390_emit_BRC(pBefore, s390_cc_invert(cond), delta);
10397 // fill "brc{ALWAYS} after"
10398 if (not_always && not_void_return)
10400 delta = pAfter - pPreElse;
10401 delta >>= 1; /* immediate constant is #half-words */
10402 vassert(delta > 0 && delta < (1 << 16));
10403 s390_emit_BRC(pPreElse, S390_CC_ALWAYS, delta);
10406 return buf;
10410 static UChar *
10411 s390_insn_cond_move_emit(UChar *buf, const s390_insn *insn)
10413 HReg dst;
10414 s390_opnd_RMI src;
10415 s390_cc_t cond;
10416 UChar *p, *ptmp = 0; /* avoid compiler warnings */
10418 cond = insn->variant.cond_move.cond;
10419 dst = insn->variant.cond_move.dst;
10420 src = insn->variant.cond_move.src;
10422 if (cond == S390_CC_NEVER) return buf;
10424 p = buf;
10426 if (s390_host_has_lsc && hregClass(dst) == HRcInt64) {
10427 /* LOCx is not the preferred way to implement an unconditional load. */
10428 if (cond == S390_CC_ALWAYS) goto use_branch_insn;
10430 switch (src.tag) {
10431 case S390_OPND_REG:
10432 return s390_emit_LOCGR(p, cond, hregNumber(dst),
10433 hregNumber(src.variant.reg));
10435 case S390_OPND_AMODE: {
10436 const s390_amode *am = src.variant.am;
10438 /* We cannot use LOCx for loads less than 4 bytes. In that case
10439 load into R0 and then use LOCGR. Do the same if the amode uses
10440 an index register. */
10441 if (insn->size < 4 ||
10442 am->tag == S390_AMODE_BX12 || am->tag == S390_AMODE_BX20) {
10443 p = s390_emit_load_mem(p, insn->size, R0, am);
10444 p = s390_emit_LOCGR(p, cond, hregNumber(dst), R0);
10445 return p;
10448 vassert(am->tag == S390_AMODE_B12 || am->tag == S390_AMODE_B20);
10449 vassert(insn->size == 4 || insn->size == 8);
10451 UInt b = hregNumber(am->b);
10452 UInt d = am->d;
10454 if (insn->size == 4) {
10455 return s390_emit_LOC(p, hregNumber(dst), cond, b, DISP20(d));
10457 return s390_emit_LOCG(p, hregNumber(dst), cond, b, DISP20(d));
10460 case S390_OPND_IMMEDIATE: {
10461 ULong value = src.variant.imm;
10463 /* If LOCGHI is available, use it. */
10464 if (s390_host_has_lsc2 && ulong_fits_signed_16bit(value)) {
10465 return s390_emit_LOCGHI(p, hregNumber(dst), value, cond);
10468 /* Load value into R0, then use LOCGR */
10469 if (insn->size <= 4) {
10470 p = s390_emit_load_32imm(p, R0, value);
10471 return s390_emit_LOCGR(p, cond, hregNumber(dst), R0);
10474 vassert(insn->size == 8);
10475 p = s390_emit_load_64imm(p, R0, value);
10476 return s390_emit_LOCGR(p, cond, hregNumber(dst), R0);
10481 use_branch_insn:
10482 /* Branch (if cond fails) over move instrs */
10483 if (cond != S390_CC_ALWAYS) {
10484 /* Don't know how many bytes to jump over yet.
10485 Make space for a BRC instruction (4 bytes) and fill in later. */
10486 ptmp = p; /* to be filled in here */
10487 p += 4;
10490 // cond true: move src => dst
10492 switch (src.tag) {
10493 case S390_OPND_REG:
10494 switch (hregClass(dst)) {
10495 case HRcInt64:
10496 p = s390_emit_LGR(p, hregNumber(dst), hregNumber(src.variant.reg));
10497 break;
10498 case HRcFlt64:
10499 p = s390_emit_LDR(p, hregNumber(dst), hregNumber(src.variant.reg));
10500 break;
10501 case HRcVec128:
10502 p = s390_emit_VLR(p, hregNumber(dst), hregNumber(src.variant.reg));
10503 break;
10504 default:
10505 goto fail;
10507 break;
10509 case S390_OPND_AMODE:
10510 if (hregClass(dst) != HRcInt64)
10511 goto fail;
10513 p = s390_emit_load_mem(p, insn->size, hregNumber(dst), src.variant.am);
10514 break;
10516 case S390_OPND_IMMEDIATE: {
10517 if (hregClass(dst) != HRcInt64)
10518 goto fail;
10520 ULong value = src.variant.imm;
10521 UInt r = hregNumber(dst);
10523 switch (insn->size) {
10524 case 1:
10525 case 2:
10526 /* Load the immediate values as a 4 byte value. That does not hurt as
10527 those extra bytes will not be looked at. Fall through .... */
10528 case 4:
10529 p = s390_emit_load_32imm(p, r, value);
10530 break;
10532 case 8:
10533 p = s390_emit_load_64imm(p, r, value);
10534 break;
10536 break;
10539 default:
10540 goto fail;
10543 if (cond != S390_CC_ALWAYS) {
10544 Int delta = p - ptmp;
10546 delta >>= 1; /* immediate constant is #half-words */
10547 vassert(delta > 0 && delta < (1 << 16));
10548 s390_emit_BRC(ptmp, s390_cc_invert(cond), delta);
10551 return p;
10553 fail:
10554 vpanic("s390_insn_cond_move_emit");
10558 static UChar *
10559 s390_insn_bfp_triop_emit(UChar *buf, const s390_insn *insn)
10561 UInt r1 = hregNumber(insn->variant.bfp_triop.dst);
10562 UInt r2 = hregNumber(insn->variant.bfp_triop.op2);
10563 UInt r3 = hregNumber(insn->variant.bfp_triop.op3);
10565 switch (insn->size) {
10566 case 4:
10567 switch (insn->variant.bfp_triop.tag) {
10568 case S390_BFP_MADD: return s390_emit_MAEBR(buf, r1, r3, r2);
10569 case S390_BFP_MSUB: return s390_emit_MSEBR(buf, r1, r3, r2);
10570 default: goto fail;
10572 break;
10574 case 8:
10575 switch (insn->variant.bfp_triop.tag) {
10576 case S390_BFP_MADD: return s390_emit_MADBR(buf, r1, r3, r2);
10577 case S390_BFP_MSUB: return s390_emit_MSDBR(buf, r1, r3, r2);
10578 default: goto fail;
10580 break;
10582 default: goto fail;
10585 fail:
10586 vpanic("s390_insn_bfp_triop_emit");
10590 static UChar *
10591 s390_insn_bfp_binop_emit(UChar *buf, const s390_insn *insn)
10593 UInt r1 = hregNumber(insn->variant.bfp_binop.dst_hi);
10594 UInt r2 = hregNumber(insn->variant.bfp_binop.op2_hi);
10596 switch (insn->size) {
10597 case 4:
10598 switch (insn->variant.bfp_binop.tag) {
10599 case S390_BFP_ADD: return s390_emit_AEBR(buf, r1, r2);
10600 case S390_BFP_SUB: return s390_emit_SEBR(buf, r1, r2);
10601 case S390_BFP_MUL: return s390_emit_MEEBR(buf, r1, r2);
10602 case S390_BFP_DIV: return s390_emit_DEBR(buf, r1, r2);
10603 default: goto fail;
10605 break;
10607 case 8:
10608 switch (insn->variant.bfp_binop.tag) {
10609 case S390_BFP_ADD: return s390_emit_ADBR(buf, r1, r2);
10610 case S390_BFP_SUB: return s390_emit_SDBR(buf, r1, r2);
10611 case S390_BFP_MUL: return s390_emit_MDBR(buf, r1, r2);
10612 case S390_BFP_DIV: return s390_emit_DDBR(buf, r1, r2);
10613 default: goto fail;
10615 break;
10617 case 16:
10618 switch (insn->variant.bfp_binop.tag) {
10619 case S390_BFP_ADD: return s390_emit_AXBR(buf, r1, r2);
10620 case S390_BFP_SUB: return s390_emit_SXBR(buf, r1, r2);
10621 case S390_BFP_MUL: return s390_emit_MXBR(buf, r1, r2);
10622 case S390_BFP_DIV: return s390_emit_DXBR(buf, r1, r2);
10623 default: goto fail;
10625 break;
10627 default: goto fail;
10630 fail:
10631 vpanic("s390_insn_bfp_binop_emit");
10635 static UChar *
10636 s390_insn_bfp_unop_emit(UChar *buf, const s390_insn *insn)
10638 UInt r1 = hregNumber(insn->variant.bfp_unop.dst_hi);
10639 UInt r2 = hregNumber(insn->variant.bfp_unop.op_hi);
10641 switch (insn->variant.bfp_unop.tag) {
10642 case S390_BFP_ABS:
10643 switch (insn->size) {
10644 case 4: return s390_emit_LPEBR(buf, r1, r2);
10645 case 8: return s390_emit_LPDBR(buf, r1, r2);
10646 case 16: return s390_emit_LPXBR(buf, r1, r2);
10647 default: goto fail;
10649 break;
10651 case S390_BFP_NABS:
10652 switch (insn->size) {
10653 case 4: return s390_emit_LNEBR(buf, r1, r2);
10654 case 8: return s390_emit_LNDBR(buf, r1, r2);
10655 case 16: return s390_emit_LNXBR(buf, r1, r2);
10656 default: goto fail;
10658 break;
10660 case S390_BFP_NEG:
10661 switch (insn->size) {
10662 case 4: return s390_emit_LCEBR(buf, r1, r2);
10663 case 8: return s390_emit_LCDBR(buf, r1, r2);
10664 case 16: return s390_emit_LCXBR(buf, r1, r2);
10665 default: goto fail;
10667 break;
10669 case S390_BFP_SQRT:
10670 switch (insn->size) {
10671 case 4: return s390_emit_SQEBR(buf, r1, r2);
10672 case 8: return s390_emit_SQDBR(buf, r1, r2);
10673 case 16: return s390_emit_SQXBR(buf, r1, r2);
10674 default: goto fail;
10676 break;
10678 default: goto fail;
10681 fail:
10682 vpanic("s390_insn_bfp_unop_emit");
10686 static UChar *
10687 s390_insn_bfp_convert_emit(UChar *buf, const s390_insn *insn)
10689 UInt r1 = hregNumber(insn->variant.bfp_convert.dst_hi);
10690 UInt r2 = hregNumber(insn->variant.bfp_convert.op_hi);
10691 s390_bfp_round_t m3 = insn->variant.bfp_convert.rounding_mode;
10692 /* The IEEE-inexact-exception control is not modelled. So the
10693 m4 field is 0 (which is what GCC does, too) */
10694 const UInt m4 = 0;
10696 switch (insn->variant.bfp_convert.tag) {
10697 /* Convert to fixed */
10698 case S390_BFP_F32_TO_I32: return s390_emit_CFEBR(buf, m3, r1, r2);
10699 case S390_BFP_F64_TO_I32: return s390_emit_CFDBR(buf, m3, r1, r2);
10700 case S390_BFP_F128_TO_I32: return s390_emit_CFXBR(buf, m3, r1, r2);
10701 case S390_BFP_F32_TO_I64: return s390_emit_CGEBR(buf, m3, r1, r2);
10702 case S390_BFP_F64_TO_I64: return s390_emit_CGDBR(buf, m3, r1, r2);
10703 case S390_BFP_F128_TO_I64: return s390_emit_CGXBR(buf, m3, r1, r2);
10705 /* Convert to logical */
10706 case S390_BFP_F32_TO_U32: return s390_emit_CLFEBR(buf, m3, m4, r1, r2);
10707 case S390_BFP_F64_TO_U32: return s390_emit_CLFDBR(buf, m3, m4, r1, r2);
10708 case S390_BFP_F128_TO_U32: return s390_emit_CLFXBR(buf, m3, m4, r1, r2);
10709 case S390_BFP_F32_TO_U64: return s390_emit_CLGEBR(buf, m3, m4, r1, r2);
10710 case S390_BFP_F64_TO_U64: return s390_emit_CLGDBR(buf, m3, m4, r1, r2);
10711 case S390_BFP_F128_TO_U64: return s390_emit_CLGXBR(buf, m3, m4, r1, r2);
10713 /* Convert from fixed */
10714 case S390_BFP_I32_TO_F32: return s390_emit_CEFBRA(buf, m3, m4, r1, r2);
10715 case S390_BFP_I32_TO_F64: return s390_emit_CDFBRA(buf, 0, m4, r1, r2);
10716 case S390_BFP_I32_TO_F128: return s390_emit_CXFBRA(buf, 0, m4, r1, r2);
10717 case S390_BFP_I64_TO_F32: return s390_emit_CEGBRA(buf, m3, m4, r1, r2);
10718 case S390_BFP_I64_TO_F64: return s390_emit_CDGBRA(buf, m3, m4, r1, r2);
10719 case S390_BFP_I64_TO_F128: return s390_emit_CXGBRA(buf, 0, m4, r1, r2);
10721 /* Convert from logical */
10722 case S390_BFP_U32_TO_F32: return s390_emit_CELFBR(buf, m3, m4, r1, r2);
10723 case S390_BFP_U32_TO_F64: return s390_emit_CDLFBR(buf, m3, m4, r1, r2);
10724 case S390_BFP_U32_TO_F128: return s390_emit_CXLFBR(buf, m3, m4, r1, r2);
10725 case S390_BFP_U64_TO_F32: return s390_emit_CELGBR(buf, m3, m4, r1, r2);
10726 case S390_BFP_U64_TO_F64: return s390_emit_CDLGBR(buf, m3, m4, r1, r2);
10727 case S390_BFP_U64_TO_F128: return s390_emit_CXLGBR(buf, m3, m4, r1, r2);
10729 /* Load lengthened */
10730 case S390_BFP_F32_TO_F64: return s390_emit_LDEBR(buf, r1, r2);
10731 case S390_BFP_F32_TO_F128: return s390_emit_LXEBR(buf, r1, r2);
10732 case S390_BFP_F64_TO_F128: return s390_emit_LXDBR(buf, r1, r2);
10734 /* Load rounded */
10735 case S390_BFP_F64_TO_F32: return s390_emit_LEDBRA(buf, m3, m4, r1, r2);
10736 case S390_BFP_F128_TO_F32: return s390_emit_LEXBRA(buf, m3, m4, r1, r2);
10737 case S390_BFP_F128_TO_F64: return s390_emit_LDXBRA(buf, m3, m4, r1, r2);
10739 /* Load FP integer */
10740 case S390_BFP_F32_TO_F32I: return s390_emit_FIEBRA(buf, m3, m4, r1, r2);
10741 case S390_BFP_F64_TO_F64I: return s390_emit_FIDBRA(buf, m3, m4, r1, r2);
10742 case S390_BFP_F128_TO_F128I: return s390_emit_FIXBRA(buf, m3, m4, r1, r2);
10744 default: goto fail;
10747 fail:
10748 vpanic("s390_insn_bfp_convert_emit");
10752 static UChar *
10753 s390_insn_bfp_compare_emit(UChar *buf, const s390_insn *insn)
10755 UInt dst = hregNumber(insn->variant.bfp_compare.dst);
10756 UInt r1 = hregNumber(insn->variant.bfp_compare.op1_hi);
10757 UInt r2 = hregNumber(insn->variant.bfp_compare.op2_hi);
10759 switch (insn->size) {
10760 case 4: buf = s390_emit_CEBR(buf, r1, r2); break;
10761 case 8: buf = s390_emit_CDBR(buf, r1, r2); break;
10762 case 16: buf = s390_emit_CXBR(buf, r1, r2); break;
10763 default: goto fail;
10766 return s390_emit_load_cc(buf, dst); /* Load condition code into DST */
10768 fail:
10769 vpanic("s390_insn_bfp_compare_emit");
10773 static UChar *
10774 s390_insn_dfp_binop_emit(UChar *buf, const s390_insn *insn)
10776 s390_dfp_binop *dfp_binop = insn->variant.dfp_binop.details;
10778 UInt r1 = hregNumber(dfp_binop->dst_hi);
10779 UInt r2 = hregNumber(dfp_binop->op2_hi);
10780 UInt r3 = hregNumber(dfp_binop->op3_hi);
10781 s390_dfp_round_t m4 = dfp_binop->rounding_mode;
10783 switch (insn->size) {
10784 case 8:
10785 switch (dfp_binop->tag) {
10786 case S390_DFP_ADD: return s390_emit_ADTRA(buf, r3, m4, r1, r2);
10787 case S390_DFP_SUB: return s390_emit_SDTRA(buf, r3, m4, r1, r2);
10788 case S390_DFP_MUL: return s390_emit_MDTRA(buf, r3, m4, r1, r2);
10789 case S390_DFP_DIV: return s390_emit_DDTRA(buf, r3, m4, r1, r2);
10790 case S390_DFP_QUANTIZE: return s390_emit_QADTR(buf, r3, m4, r1, r2);
10791 default: goto fail;
10793 break;
10795 case 16:
10796 switch (dfp_binop->tag) {
10797 case S390_DFP_ADD: return s390_emit_AXTRA(buf, r3, m4, r1, r2);
10798 case S390_DFP_SUB: return s390_emit_SXTRA(buf, r3, m4, r1, r2);
10799 case S390_DFP_MUL: return s390_emit_MXTRA(buf, r3, m4, r1, r2);
10800 case S390_DFP_DIV: return s390_emit_DXTRA(buf, r3, m4, r1, r2);
10801 case S390_DFP_QUANTIZE: return s390_emit_QAXTR(buf, r3, m4, r1, r2);
10802 default: goto fail;
10804 break;
10806 default: goto fail;
10809 fail:
10810 vpanic("s390_insn_dfp_binop_emit");
10814 static UChar *
10815 s390_insn_dfp_reround_emit(UChar *buf, const s390_insn *insn)
10817 UInt r1 = hregNumber(insn->variant.dfp_reround.dst_hi);
10818 UInt r2 = hregNumber(insn->variant.dfp_reround.op2);
10819 UInt r3 = hregNumber(insn->variant.dfp_reround.op3_hi);
10820 s390_dfp_round_t m4 = insn->variant.dfp_reround.rounding_mode;
10822 switch (insn->size) {
10823 case 8:
10824 return s390_emit_RRDTR(buf, r3, m4, r1, r2);
10826 case 16:
10827 return s390_emit_RRXTR(buf, r3, m4, r1, r2);
10829 default: goto fail;
10831 fail:
10832 vpanic("s390_insn_dfp_reround_emit");
10836 static UChar *
10837 s390_insn_dfp_unop_emit(UChar *buf, const s390_insn *insn)
10839 UInt r1 = hregNumber(insn->variant.dfp_unop.dst_hi);
10840 UInt r2 = hregNumber(insn->variant.dfp_unop.op_hi);
10842 switch (insn->variant.dfp_unop.tag) {
10843 case S390_DFP_EXTRACT_EXP_D64: return s390_emit_EEDTR(buf, r1, r2); break;
10844 case S390_DFP_EXTRACT_EXP_D128: return s390_emit_EEXTR(buf, r1, r2); break;
10845 case S390_DFP_EXTRACT_SIG_D64: return s390_emit_ESDTR(buf, r1, r2); break;
10846 case S390_DFP_EXTRACT_SIG_D128: return s390_emit_ESXTR(buf, r1, r2); break;
10847 default: goto fail;
10849 fail:
10850 vpanic("s390_insn_dfp_unop_emit");
10854 static UChar *
10855 s390_insn_dfp_intop_emit(UChar *buf, const s390_insn *insn)
10857 UInt r1 = hregNumber(insn->variant.dfp_intop.dst_hi);
10858 UInt r2 = hregNumber(insn->variant.dfp_intop.op2);
10859 UInt r3 = hregNumber(insn->variant.dfp_intop.op3_hi);
10861 switch (insn->size) {
10862 case 8:
10863 switch (insn->variant.dfp_intop.tag) {
10864 case S390_DFP_SHIFT_LEFT: return s390_emit_SLDT(buf, r3, r1, r2);
10865 case S390_DFP_SHIFT_RIGHT: return s390_emit_SRDT(buf, r3, r1, r2);
10866 case S390_DFP_INSERT_EXP: return s390_emit_IEDTR(buf, r3, r1, r2);
10867 default: goto fail;
10869 break;
10871 case 16:
10872 switch (insn->variant.dfp_intop.tag) {
10873 case S390_DFP_SHIFT_LEFT: return s390_emit_SLXT(buf, r3, r1, r2);
10874 case S390_DFP_SHIFT_RIGHT: return s390_emit_SRXT(buf, r3, r1, r2);
10875 case S390_DFP_INSERT_EXP: return s390_emit_IEXTR(buf, r3, r1, r2);
10876 default: goto fail;
10878 break;
10880 default: goto fail;
10883 fail:
10884 vpanic("s390_insn_dfp_intop_emit");
10888 static UChar *
10889 s390_insn_dfp_compare_emit(UChar *buf, const s390_insn *insn)
10891 UInt dst = hregNumber(insn->variant.dfp_compare.dst);
10892 UInt r1 = hregNumber(insn->variant.dfp_compare.op1_hi);
10893 UInt r2 = hregNumber(insn->variant.dfp_compare.op2_hi);
10895 switch (insn->size) {
10896 case 8:
10897 switch(insn->variant.dfp_compare.tag) {
10898 case S390_DFP_COMPARE: buf = s390_emit_CDTR(buf, r1, r2); break;
10899 case S390_DFP_COMPARE_EXP: buf = s390_emit_CEDTR(buf, r1, r2); break;
10900 default: goto fail;
10902 break;
10904 case 16:
10905 switch(insn->variant.dfp_compare.tag) {
10906 case S390_DFP_COMPARE: buf = s390_emit_CXTR(buf, r1, r2); break;
10907 case S390_DFP_COMPARE_EXP: buf = s390_emit_CEXTR(buf, r1, r2); break;
10908 default: goto fail;
10910 break;
10912 default: goto fail;
10915 return s390_emit_load_cc(buf, dst); /* Load condition code into DST */
10917 fail:
10918 vpanic("s390_insn_dfp_compare_emit");
10922 static UChar *
10923 s390_insn_dfp_convert_emit(UChar *buf, const s390_insn *insn)
10925 UInt r1 = hregNumber(insn->variant.dfp_convert.dst_hi);
10926 UInt r2 = hregNumber(insn->variant.dfp_convert.op_hi);
10927 s390_dfp_round_t m3 = insn->variant.dfp_convert.rounding_mode;
10928 /* The IEEE-inexact-exception control is not modelled. So the
10929 m4 field is 0 (which is what GCC does, too) */
10930 const UInt m4 = 0;
10932 switch (insn->variant.dfp_convert.tag) {
10934 /* Convert to fixed */
10935 case S390_DFP_D64_TO_I32: return s390_emit_CFDTR(buf, m3, m4, r1, r2);
10936 case S390_DFP_D128_TO_I32: return s390_emit_CFXTR(buf, m3, m4, r1, r2);
10937 case S390_DFP_D64_TO_I64: return s390_emit_CGDTR(buf, m3, m4, r1, r2);
10938 case S390_DFP_D128_TO_I64: return s390_emit_CGXTR(buf, m3, m4, r1, r2);
10940 /* Convert to logical */
10941 case S390_DFP_D64_TO_U32: return s390_emit_CLFDTR(buf, m3, m4, r1, r2);
10942 case S390_DFP_D128_TO_U32: return s390_emit_CLFXTR(buf, m3, m4, r1, r2);
10943 case S390_DFP_D64_TO_U64: return s390_emit_CLGDTR(buf, m3, m4, r1, r2);
10944 case S390_DFP_D128_TO_U64: return s390_emit_CLGXTR(buf, m3, m4, r1, r2);
10946 /* Convert from fixed */
10947 case S390_DFP_I32_TO_D64: return s390_emit_CDFTR(buf, 0, m4, r1, r2);
10948 case S390_DFP_I32_TO_D128: return s390_emit_CXFTR(buf, 0, m4, r1, r2);
10949 case S390_DFP_I64_TO_D64: return s390_emit_CDGTRA(buf, m3, m4, r1, r2);
10950 case S390_DFP_I64_TO_D128: return s390_emit_CXGTR(buf, 0, m4, r1, r2);
10952 /* Convert from logical */
10953 case S390_DFP_U32_TO_D64: return s390_emit_CDLFTR(buf, m3, m4, r1, r2);
10954 case S390_DFP_U64_TO_D64: return s390_emit_CDLGTR(buf, m3, m4, r1, r2);
10955 case S390_DFP_U32_TO_D128: return s390_emit_CXLFTR(buf, m3, m4, r1, r2);
10956 case S390_DFP_U64_TO_D128: return s390_emit_CXLGTR(buf, m3, m4, r1, r2);
10958 /* Load lengthened */
10959 case S390_DFP_D32_TO_D64: return s390_emit_LDETR(buf, m4, r1, r2);
10960 case S390_DFP_D64_TO_D128: return s390_emit_LXDTR(buf, m4, r1, r2);
10962 /* Load rounded */
10963 case S390_DFP_D64_TO_D32: return s390_emit_LEDTR(buf, m3, m4, r1, r2);
10964 case S390_DFP_D128_TO_D64: return s390_emit_LDXTR(buf, m3, m4, r1, r2);
10966 default: goto fail;
10969 fail:
10970 vpanic("s390_insn_dfp_convert_emit");
10974 static UChar *
10975 s390_insn_fp_convert_emit(UChar *buf, const s390_insn *insn)
10977 UInt pfpo;
10978 s390_fp_convert *fp_convert = insn->variant.fp_convert.details;
10979 s390_dfp_round_t rm = fp_convert->rounding_mode;
10981 vassert(rm < 2 || rm > 7);
10983 switch (fp_convert->tag) {
10984 case S390_FP_F32_TO_D32: pfpo = S390_PFPO_F32_TO_D32 << 8; break;
10985 case S390_FP_F32_TO_D64: pfpo = S390_PFPO_F32_TO_D64 << 8; break;
10986 case S390_FP_F32_TO_D128: pfpo = S390_PFPO_F32_TO_D128 << 8; break;
10987 case S390_FP_F64_TO_D32: pfpo = S390_PFPO_F64_TO_D32 << 8; break;
10988 case S390_FP_F64_TO_D64: pfpo = S390_PFPO_F64_TO_D64 << 8; break;
10989 case S390_FP_F64_TO_D128: pfpo = S390_PFPO_F64_TO_D128 << 8; break;
10990 case S390_FP_F128_TO_D32: pfpo = S390_PFPO_F128_TO_D32 << 8; break;
10991 case S390_FP_F128_TO_D64: pfpo = S390_PFPO_F128_TO_D64 << 8; break;
10992 case S390_FP_F128_TO_D128: pfpo = S390_PFPO_F128_TO_D128 << 8; break;
10993 case S390_FP_D32_TO_F32: pfpo = S390_PFPO_D32_TO_F32 << 8; break;
10994 case S390_FP_D32_TO_F64: pfpo = S390_PFPO_D32_TO_F64 << 8; break;
10995 case S390_FP_D32_TO_F128: pfpo = S390_PFPO_D32_TO_F128 << 8; break;
10996 case S390_FP_D64_TO_F32: pfpo = S390_PFPO_D64_TO_F32 << 8; break;
10997 case S390_FP_D64_TO_F64: pfpo = S390_PFPO_D64_TO_F64 << 8; break;
10998 case S390_FP_D64_TO_F128: pfpo = S390_PFPO_D64_TO_F128 << 8; break;
10999 case S390_FP_D128_TO_F32: pfpo = S390_PFPO_D128_TO_F32 << 8; break;
11000 case S390_FP_D128_TO_F64: pfpo = S390_PFPO_D128_TO_F64 << 8; break;
11001 case S390_FP_D128_TO_F128: pfpo = S390_PFPO_D128_TO_F128 << 8; break;
11002 default: goto fail;
11005 pfpo = pfpo | rm;
11006 buf = s390_emit_load_32imm(buf, R0, pfpo);
11007 buf = s390_emit_PFPO(buf);
11008 return buf;
11010 fail:
11011 vpanic("s390_insn_fp_convert_emit");
11015 static UChar *
11016 s390_insn_mfence_emit(UChar *buf, const s390_insn *insn)
11018 return s390_emit_BCR(buf, 0xF, 0x0);
11022 static UChar *
11023 s390_insn_mimm_emit(UChar *buf, const s390_insn *insn)
11025 s390_amode *am = insn->variant.mimm.dst;
11026 UChar b = hregNumber(am->b);
11027 Int d = am->d;
11028 ULong value = insn->variant.mimm.value;
11030 if (value == 0) {
11031 return s390_emit_XC(buf, insn->size - 1, b, d, b, d);
11034 if (insn->size == 1) {
11035 return s390_emit_MVI(buf, value & 0xFF, b, d);
11038 if (s390_host_has_gie && ulong_fits_signed_16bit(value)) {
11039 value &= 0xFFFF;
11040 switch (insn->size) {
11041 case 2: return s390_emit_MVHHI(buf, b, d, value);
11042 case 4: return s390_emit_MVHI(buf, b, d, value);
11043 case 8: return s390_emit_MVGHI(buf, b, d, value);
11045 } else {
11046 // Load value to R0, then store.
11047 switch (insn->size) {
11048 case 2:
11049 buf = s390_emit_LHI(buf, R0, value & 0xFFFF);
11050 return s390_emit_STH(buf, R0, 0, b, d);
11051 case 4:
11052 buf = s390_emit_load_32imm(buf, R0, value);
11053 return s390_emit_ST(buf, R0, 0, b, d);
11054 case 8:
11055 buf = s390_emit_load_64imm(buf, R0, value);
11056 return s390_emit_STG(buf, R0, 0, b, DISP20(d));
11060 vpanic("s390_insn_mimm_emit");
11064 static UChar *
11065 s390_insn_madd_emit(UChar *buf, const s390_insn *insn)
11067 s390_amode *am = insn->variant.madd.dst;
11068 UChar b = hregNumber(am->b);
11069 Int d = am->d;
11071 if (insn->size == 4) {
11072 return s390_emit_ASI(buf, insn->variant.madd.delta, b, DISP20(d));
11075 return s390_emit_AGSI(buf, insn->variant.madd.delta, b, DISP20(d));
11079 static UChar *
11080 s390_insn_set_fpc_bfprm_emit(UChar *buf, const s390_insn *insn)
11082 UInt mode = hregNumber(insn->variant.set_fpc_bfprm.mode);
11084 /* Copy FPC from guest state to R0 and OR in the new rounding mode */
11085 buf = s390_emit_L(buf, R0, 0, S390_REGNO_GUEST_STATE_POINTER,
11086 S390X_GUEST_OFFSET(guest_fpc)); // r0 = guest_fpc
11088 buf = s390_emit_NILL(buf, R0, 0xFFF8); /* Clear out right-most 3 bits */
11089 buf = s390_emit_OR(buf, R0, mode); /* OR in the new rounding mode */
11090 buf = s390_emit_SFPC(buf, R0); /* Load FPC register from R0 */
11092 return buf;
11096 static UChar *
11097 s390_insn_set_fpc_dfprm_emit(UChar *buf, const s390_insn *insn)
11099 UInt mode = hregNumber(insn->variant.set_fpc_dfprm.mode);
11101 /* Copy FPC from guest state to R0 and OR in the new rounding mode */
11102 buf = s390_emit_L(buf, R0, 0, S390_REGNO_GUEST_STATE_POINTER,
11103 S390X_GUEST_OFFSET(guest_fpc)); // r0 = guest_fpc
11105 /* DFP rounding mode is set at bit position 25:27 in FPC register */
11106 buf = s390_emit_NILL(buf, R0, 0xFF8F); /* Clear out 25:27 bits */
11107 buf = s390_emit_SLL(buf, mode, 0, 4); /* bring mode to 25:27 bits */
11108 buf = s390_emit_OR(buf, R0, mode); /* OR in the new rounding mode */
11109 buf = s390_emit_SFPC(buf, R0); /* Load FPC register from R0 */
11111 return buf;
11115 /* Define convenience functions needed for translation chaining.
11116 Any changes need to be applied to the functions in concert. */
11118 static __inline__ Bool
11119 s390_insn_is_BRCL(const UChar *p, UChar condition)
11121 return p[0] == 0xc0 && p[1] == ((condition << 4) | 0x04);
11124 static __inline__ Bool
11125 s390_insn_is_BR(const UChar *p, UChar reg)
11127 return p[0] == 0x07 && p[1] == (0xF0 | reg); /* BCR 15,reg */
11131 /* The length of the BASR insn */
11132 #define S390_BASR_LEN 2
11135 /* Load the 64-bit VALUE into REG. Note that this function must NOT
11136 optimise the generated code by looking at the value. I.e. using
11137 LGHI if value == 0 would be very wrong. */
11138 static UChar *
11139 s390_tchain_load64(UChar *buf, UChar regno, ULong value)
11141 UChar *begin = buf;
11143 if (s390_host_has_eimm) {
11144 /* Do it in two steps: upper half [0:31] and lower half [32:63] */
11145 buf = s390_emit_IIHF(buf, regno, value >> 32);
11146 buf = s390_emit_IILF(buf, regno, value & 0xFFFFFFFF);
11147 } else {
11148 buf = s390_emit_IILL(buf, regno, value & 0xFFFF);
11149 value >>= 16;
11150 buf = s390_emit_IILH(buf, regno, value & 0xFFFF);
11151 value >>= 16;
11152 buf = s390_emit_IIHL(buf, regno, value & 0xFFFF);
11153 value >>= 16;
11154 buf = s390_emit_IIHH(buf, regno, value & 0xFFFF);
11157 vassert(buf - begin == s390_tchain_load64_len());
11159 return buf;
11162 /* Return number of bytes generated by s390_tchain_load64 */
11163 static UInt
11164 s390_tchain_load64_len(void)
11166 if (s390_host_has_eimm) {
11167 return 6 + 6; /* IIHF + IILF */
11169 return 4 + 4 + 4 + 4; /* IIHH + IIHL + IILH + IILL */
11172 /* Verify that CODE is the code sequence generated by s390_tchain_load64
11173 to load VALUE into REGNO. Return pointer to the byte following the
11174 insn sequence. */
11175 static const UChar *
11176 s390_tchain_verify_load64(const UChar *code, UChar regno, ULong value)
11178 UInt regmask = regno << 4;
11179 UInt hw;
11181 if (s390_host_has_eimm) {
11182 /* Check for IIHF */
11183 vassert(code[0] == 0xC0);
11184 vassert(code[1] == (0x08 | regmask));
11185 vassert(*(const UInt *)&code[2] == (value >> 32));
11186 /* Check for IILF */
11187 vassert(code[6] == 0xC0);
11188 vassert(code[7] == (0x09 | regmask));
11189 vassert(*(const UInt *)&code[8] == (value & 0xFFFFFFFF));
11190 } else {
11191 /* Check for IILL */
11192 hw = value & 0xFFFF;
11193 vassert(code[0] == 0xA5);
11194 vassert(code[1] == (0x03 | regmask));
11195 vassert(code[2] == (hw >> 8));
11196 vassert(code[3] == (hw & 0xFF));
11198 /* Check for IILH */
11199 hw = (value >> 16) & 0xFFFF;
11200 vassert(code[4] == 0xA5);
11201 vassert(code[5] == (0x02 | regmask));
11202 vassert(code[6] == (hw >> 8));
11203 vassert(code[7] == (hw & 0xFF));
11205 /* Check for IIHL */
11206 hw = (value >> 32) & 0xFFFF;
11207 vassert(code[8] == 0xA5);
11208 vassert(code[9] == (0x01 | regmask));
11209 vassert(code[10] == (hw >> 8));
11210 vassert(code[11] == (hw & 0xFF));
11212 /* Check for IIHH */
11213 hw = (value >> 48) & 0xFFFF;
11214 vassert(code[12] == 0xA5);
11215 vassert(code[13] == (0x00 | regmask));
11216 vassert(code[14] == (hw >> 8));
11217 vassert(code[15] == (hw & 0xFF));
11220 return code + s390_tchain_load64_len();
11223 /* CODE points to the code sequence as generated by s390_tchain_load64.
11224 Change the loaded value to IMM64. Return pointer to the byte following
11225 the patched code sequence. */
11226 static UChar *
11227 s390_tchain_patch_load64(UChar *code, ULong imm64)
11229 if (s390_host_has_eimm) {
11230 /* Patch IIHF */
11231 *(UInt *)&code[2] = imm64 >> 32;
11232 /* Patch IILF */
11233 *(UInt *)&code[8] = imm64 & 0xFFFFFFFF;
11234 } else {
11235 code[3] = imm64 & 0xFF; imm64 >>= 8;
11236 code[2] = imm64 & 0xFF; imm64 >>= 8;
11237 code[7] = imm64 & 0xFF; imm64 >>= 8;
11238 code[6] = imm64 & 0xFF; imm64 >>= 8;
11239 code[11] = imm64 & 0xFF; imm64 >>= 8;
11240 code[10] = imm64 & 0xFF; imm64 >>= 8;
11241 code[15] = imm64 & 0xFF; imm64 >>= 8;
11242 code[14] = imm64 & 0xFF; imm64 >>= 8;
11245 return code + s390_tchain_load64_len();
11249 /* NB: what goes on here has to be very closely coordinated with the
11250 chainXDirect_S390 and unchainXDirect_S390 below. */
11251 static UChar *
11252 s390_insn_xdirect_emit(UChar *buf, const s390_insn *insn,
11253 const void *disp_cp_chain_me_to_slowEP,
11254 const void *disp_cp_chain_me_to_fastEP)
11256 /* We're generating chain-me requests here, so we need to be
11257 sure this is actually allowed -- no-redir translations can't
11258 use chain-me's. Hence: */
11259 vassert(disp_cp_chain_me_to_slowEP != NULL);
11260 vassert(disp_cp_chain_me_to_fastEP != NULL);
11262 /* Use ptmp for backpatching conditional jumps. */
11263 UChar *ptmp = buf;
11265 /* First off, if this is conditional, create a conditional
11266 jump over the rest of it. */
11267 s390_cc_t cond = insn->variant.xdirect.cond;
11269 if (cond != S390_CC_ALWAYS) {
11270 /* So we have something like this
11271 if (cond) do_xdirect;
11272 Y: ...
11273 We convert this into
11274 if (! cond) goto Y; // BRC opcode; 4 bytes
11275 do_xdirect;
11278 /* 4 bytes (a BRC insn) to be filled in here */
11279 buf += 4;
11282 /* Update the guest IA. */
11283 buf = s390_emit_load_64imm(buf, R0, insn->variant.xdirect.dst);
11285 const s390_amode *amode = insn->variant.xdirect.guest_IA;
11286 vassert(amode->tag == S390_AMODE_B12);
11287 UInt b = hregNumber(amode->b);
11288 UInt d = amode->d;
11290 buf = s390_emit_STG(buf, R0, 0, b, DISP20(d));
11292 /* Load the chosen entry point into the scratch reg */
11293 const void *disp_cp_chain_me;
11295 disp_cp_chain_me =
11296 insn->variant.xdirect.to_fast_entry ? disp_cp_chain_me_to_fastEP
11297 : disp_cp_chain_me_to_slowEP;
11298 /* Get the address of the beginning of the load64 code sequence into %r1.
11299 Do not change the register! This is part of the protocol with the
11300 dispatcher. */
11301 buf = s390_emit_BASR(buf, 1, R0);
11303 /* --- FIRST PATCHABLE BYTE follows (must not modify %r1) --- */
11304 Addr64 addr = (Addr)disp_cp_chain_me;
11305 buf = s390_tchain_load64(buf, S390_REGNO_TCHAIN_SCRATCH, addr);
11307 /* goto *tchain_scratch */
11308 buf = s390_emit_BCR(buf, S390_CC_ALWAYS, S390_REGNO_TCHAIN_SCRATCH);
11310 /* --- END of PATCHABLE BYTES --- */
11312 /* Fix up the conditional jump, if there was one. */
11313 if (cond != S390_CC_ALWAYS) {
11314 Int delta = buf - ptmp;
11316 delta >>= 1; /* immediate constant is #half-words */
11317 vassert(delta > 0 && delta < (1 << 16));
11318 s390_emit_BRC(ptmp, s390_cc_invert(cond), delta);
11321 return buf;
11324 /* Return the number of patchable bytes from an xdirect insn. */
11325 static UInt
11326 s390_xdirect_patchable_len(void)
11328 return s390_tchain_load64_len() + S390_BASR_LEN;
11332 static UChar *
11333 s390_insn_xindir_emit(UChar *buf, const s390_insn *insn,
11334 const void *disp_cp_xindir)
11336 /* We're generating transfers that could lead indirectly to a
11337 chain-me, so we need to be sure this is actually allowed --
11338 no-redir translations are not allowed to reach normal
11339 translations without going through the scheduler. That means
11340 no XDirects or XIndirs out from no-redir translations.
11341 Hence: */
11342 vassert(disp_cp_xindir != NULL);
11344 /* Use ptmp for backpatching conditional jumps. */
11345 UChar *ptmp = buf;
11347 /* First off, if this is conditional, create a conditional
11348 jump over the rest of it. */
11349 s390_cc_t cond = insn->variant.xdirect.cond;
11351 if (cond != S390_CC_ALWAYS) {
11352 /* So we have something like this
11353 if (cond) do_xdirect;
11354 Y: ...
11355 We convert this into
11356 if (! cond) goto Y; // BRC opcode; 4 bytes
11357 do_xdirect;
11360 /* 4 bytes (a BRC insn) to be filled in here */
11361 buf += 4;
11364 /* Update the guest IA with the address in xdirect.dst. */
11365 const s390_amode *amode = insn->variant.xindir.guest_IA;
11367 vassert(amode->tag == S390_AMODE_B12);
11368 UInt b = hregNumber(amode->b);
11369 UInt d = amode->d;
11370 UInt regno = hregNumber(insn->variant.xindir.dst);
11372 buf = s390_emit_STG(buf, regno, 0, b, DISP20(d));
11374 /* load tchain_scratch, #disp_indir */
11375 buf = s390_tchain_load64(buf, S390_REGNO_TCHAIN_SCRATCH,
11376 (Addr)disp_cp_xindir);
11377 /* goto *tchain_direct */
11378 buf = s390_emit_BCR(buf, S390_CC_ALWAYS, S390_REGNO_TCHAIN_SCRATCH);
11380 /* Fix up the conditional jump, if there was one. */
11381 if (cond != S390_CC_ALWAYS) {
11382 Int delta = buf - ptmp;
11384 delta >>= 1; /* immediate constant is #half-words */
11385 vassert(delta > 0 && delta < (1 << 16));
11386 s390_emit_BRC(ptmp, s390_cc_invert(cond), delta);
11389 return buf;
11392 static UChar *
11393 s390_insn_xassisted_emit(UChar *buf, const s390_insn *insn,
11394 const void *disp_cp_xassisted)
11396 /* Use ptmp for backpatching conditional jumps. */
11397 UChar *ptmp = buf;
11399 /* First off, if this is conditional, create a conditional
11400 jump over the rest of it. */
11401 s390_cc_t cond = insn->variant.xdirect.cond;
11403 if (cond != S390_CC_ALWAYS) {
11404 /* So we have something like this
11405 if (cond) do_xdirect;
11406 Y: ...
11407 We convert this into
11408 if (! cond) goto Y; // BRC opcode; 4 bytes
11409 do_xdirect;
11412 /* 4 bytes (a BRC insn) to be filled in here */
11413 buf += 4;
11416 /* Update the guest IA with the address in xassisted.dst. */
11417 const s390_amode *amode = insn->variant.xassisted.guest_IA;
11419 vassert(amode->tag == S390_AMODE_B12);
11420 UInt b = hregNumber(amode->b);
11421 UInt d = amode->d;
11422 UInt regno = hregNumber(insn->variant.xassisted.dst);
11424 buf = s390_emit_STG(buf, regno, 0, b, DISP20(d));
11426 UInt trcval = 0;
11428 switch (insn->variant.xassisted.kind) {
11429 case Ijk_ClientReq: trcval = VEX_TRC_JMP_CLIENTREQ; break;
11430 case Ijk_Sys_syscall: trcval = VEX_TRC_JMP_SYS_SYSCALL; break;
11431 case Ijk_Yield: trcval = VEX_TRC_JMP_YIELD; break;
11432 case Ijk_EmWarn: trcval = VEX_TRC_JMP_EMWARN; break;
11433 case Ijk_EmFail: trcval = VEX_TRC_JMP_EMFAIL; break;
11434 case Ijk_MapFail: trcval = VEX_TRC_JMP_MAPFAIL; break;
11435 case Ijk_NoDecode: trcval = VEX_TRC_JMP_NODECODE; break;
11436 case Ijk_InvalICache: trcval = VEX_TRC_JMP_INVALICACHE; break;
11437 case Ijk_NoRedir: trcval = VEX_TRC_JMP_NOREDIR; break;
11438 case Ijk_SigTRAP: trcval = VEX_TRC_JMP_SIGTRAP; break;
11439 case Ijk_SigFPE: trcval = VEX_TRC_JMP_SIGFPE; break;
11440 case Ijk_SigSEGV: trcval = VEX_TRC_JMP_SIGSEGV; break;
11441 case Ijk_Boring: trcval = VEX_TRC_JMP_BORING; break;
11442 /* We don't expect to see the following being assisted. */
11443 case Ijk_Ret:
11444 case Ijk_Call:
11445 /* fallthrough */
11446 default:
11447 ppIRJumpKind(insn->variant.xassisted.kind);
11448 vpanic("s390_insn_xassisted_emit: unexpected jump kind");
11451 vassert(trcval != 0);
11453 /* guest_state_pointer = trcval */
11454 buf = s390_emit_LGHI(buf, S390_REGNO_GUEST_STATE_POINTER, trcval);
11456 /* load tchain_scratch, #disp_assisted */
11457 buf = s390_tchain_load64(buf, S390_REGNO_TCHAIN_SCRATCH,
11458 (Addr)disp_cp_xassisted);
11460 /* goto *tchain_direct */
11461 buf = s390_emit_BCR(buf, S390_CC_ALWAYS, S390_REGNO_TCHAIN_SCRATCH);
11463 /* Fix up the conditional jump, if there was one. */
11464 if (cond != S390_CC_ALWAYS) {
11465 Int delta = buf - ptmp;
11467 delta >>= 1; /* immediate constant is #half-words */
11468 vassert(delta > 0 && delta < (1 << 16));
11469 s390_emit_BRC(ptmp, s390_cc_invert(cond), delta);
11472 return buf;
11476 /* Pseudo code:
11478 guest_state[host_EvC_COUNTER] -= 1;
11479 if (guest_state[host_EvC_COUNTER] >= 0) goto nofail;
11480 goto guest_state[host_EvC_FAILADDR];
11481 nofail: ;
11483 The dispatch counter is a 32-bit value. */
11484 static UChar *
11485 s390_insn_evcheck_emit(UChar *buf, const s390_insn *insn,
11486 VexEndness endness_host)
11488 s390_amode *amode;
11489 UInt b, d;
11490 UChar *code_begin, *code_end;
11492 code_begin = buf;
11494 amode = insn->variant.evcheck.counter;
11495 vassert(amode->tag == S390_AMODE_B12);
11496 b = hregNumber(amode->b);
11497 d = amode->d;
11499 /* Decrement the dispatch counter in the guest state */
11500 if (s390_host_has_gie) {
11501 buf = s390_emit_ASI(buf, -1, b, DISP20(d)); /* 6 bytes */
11502 } else {
11503 buf = s390_emit_LHI(buf, R0, -1); /* 4 bytes */
11504 buf = s390_emit_A(buf, R0, 0, b, d); /* 4 bytes */
11505 buf = s390_emit_ST(buf, R0, 0, b, d); /* 4 bytes */
11508 /* Jump over the next insn if >= 0 */
11509 buf = s390_emit_BRC(buf, S390_CC_HE, (4 + 6 + 2) / 2); /* 4 bytes */
11511 /* Computed goto to fail_address */
11512 amode = insn->variant.evcheck.fail_addr;
11513 b = hregNumber(amode->b);
11514 d = amode->d;
11515 buf = s390_emit_LG(buf, S390_REGNO_TCHAIN_SCRATCH, 0, b, DISP20(d)); /* 6 bytes */
11516 buf = s390_emit_BCR(buf, S390_CC_ALWAYS, S390_REGNO_TCHAIN_SCRATCH); /* 2 bytes */
11518 code_end = buf;
11520 /* Make sure the size of the generated code is identical to the size
11521 returned by evCheckSzB_S390 */
11522 vassert(evCheckSzB_S390() == code_end - code_begin);
11524 return buf;
11528 static UChar *
11529 s390_insn_profinc_emit(UChar *buf,
11530 const s390_insn *insn __attribute__((unused)))
11532 /* Generate a code template to increment a memory location whose
11533 address will be known later as an immediate value. This code
11534 template will be patched once the memory location is known.
11535 For now we do this with address == 0. */
11536 buf = s390_tchain_load64(buf, S390_REGNO_TCHAIN_SCRATCH, 0);
11537 if (s390_host_has_gie) {
11538 buf = s390_emit_AGSI(buf, 1, S390_REGNO_TCHAIN_SCRATCH, DISP20(0));
11539 } else {
11540 buf = s390_emit_LGHI(buf, R0, 1);
11541 buf = s390_emit_AG( buf, R0, 0, S390_REGNO_TCHAIN_SCRATCH, DISP20(0));
11542 buf = s390_emit_STG(buf, R0, 0, S390_REGNO_TCHAIN_SCRATCH, DISP20(0));
11545 return buf;
11549 static UChar *
11550 s390_insn_vec_amodeop_emit(UChar *buf, const s390_insn *insn)
11552 UChar v1 = hregNumber(insn->variant.vec_amodeop.dst);
11553 UChar v2 = hregNumber(insn->variant.vec_amodeop.op1);
11554 s390_amode* op2 = insn->variant.vec_amodeop.op2;
11556 vassert(hregNumber(op2->x) == 0);
11557 vassert(fits_unsigned_12bit(op2->d));
11559 UChar b = hregNumber(op2->b);
11560 UShort d = op2->d;
11563 switch (insn->variant.vec_amodeop.tag) {
11564 case S390_VEC_GET_ELEM:
11565 return s390_emit_VLGV(buf, v1, b, d, v2, s390_getM_from_size(insn->size));
11567 case S390_VEC_ELEM_SHL_INT:
11568 return s390_emit_VESL(buf, v1, b, d, v2, s390_getM_from_size(insn->size));
11570 case S390_VEC_ELEM_SHRA_INT:
11571 return s390_emit_VESRA(buf, v1, b, d, v2, s390_getM_from_size(insn->size));
11573 case S390_VEC_ELEM_SHRL_INT:
11574 return s390_emit_VESRL(buf, v1, b, d, v2, s390_getM_from_size(insn->size));
11576 default: goto fail;
11579 fail:
11580 vpanic("s390_insn_vec_amodeop_emit");
11584 static UChar *
11585 s390_insn_vec_amodeintop_emit(UChar *buf, const s390_insn *insn)
11587 UChar v1 = hregNumber(insn->variant.vec_amodeintop.dst);
11588 s390_amode* op2 = insn->variant.vec_amodeintop.op2;
11589 UChar r3 = hregNumber(insn->variant.vec_amodeintop.op3);
11591 vassert(hregNumber(op2->x) == 0);
11592 UChar b = hregNumber(op2->b);
11593 UShort d = op2->d;
11595 switch (insn->variant.vec_amodeintop.tag) {
11596 case S390_VEC_SET_ELEM:
11597 return s390_emit_VLVG(buf, v1, b, d, r3, s390_getM_from_size(insn->size));
11598 default: goto fail;
11601 fail:
11602 vpanic("s390_insn_vec_amodeop_emit");
11606 static UChar *
11607 s390_insn_vec_binop_emit(UChar *buf, const s390_insn *insn)
11609 s390_vec_binop_t tag = insn->variant.vec_binop.tag;
11610 UChar size = insn->size;
11611 UChar v1 = hregNumber(insn->variant.vec_binop.dst);
11612 UChar v2 = hregNumber(insn->variant.vec_binop.op1);
11613 UChar v3 = hregNumber(insn->variant.vec_binop.op2);
11615 switch (tag) {
11616 case S390_VEC_PACK:
11617 return s390_emit_VPK(buf, v1, v2, v3, s390_getM_from_size(size));
11618 case S390_VEC_PACK_SATURU:
11619 return s390_emit_VPKLS(buf, v1, v2, v3, s390_getM_from_size(size));
11620 case S390_VEC_PACK_SATURS:
11621 return s390_emit_VPKS(buf, v1, v2, v3, s390_getM_from_size(size));
11622 case S390_VEC_COMPARE_EQUAL:
11623 return s390_emit_VCEQ(buf, v1, v2, v3, s390_getM_from_size(size));
11624 case S390_VEC_OR:
11625 return s390_emit_VO(buf, v1, v2, v3);
11626 case S390_VEC_ORC:
11627 return s390_emit_VOC(buf, v1, v2, v3);
11628 case S390_VEC_XOR:
11629 return s390_emit_VX(buf, v1, v2, v3);
11630 case S390_VEC_AND:
11631 return s390_emit_VN(buf, v1, v2, v3);
11632 case S390_VEC_MERGEL:
11633 return s390_emit_VMRL(buf, v1, v2, v3, s390_getM_from_size(size));
11634 case S390_VEC_MERGEH:
11635 return s390_emit_VMRH(buf, v1, v2, v3, s390_getM_from_size(size));
11636 case S390_VEC_NOR:
11637 return s390_emit_VNO(buf, v1, v2, v3);
11638 case S390_VEC_INT_ADD:
11639 return s390_emit_VA(buf, v1, v2, v3, s390_getM_from_size(size));
11640 case S390_VEC_INT_SUB:
11641 return s390_emit_VS(buf, v1, v2, v3, s390_getM_from_size(size));
11642 case S390_VEC_MAXU:
11643 return s390_emit_VMXL(buf, v1, v2, v3, s390_getM_from_size(size));
11644 case S390_VEC_MAXS:
11645 return s390_emit_VMX(buf, v1, v2, v3, s390_getM_from_size(size));
11646 case S390_VEC_MINU:
11647 return s390_emit_VMNL(buf, v1, v2, v3, s390_getM_from_size(size));
11648 case S390_VEC_MINS:
11649 return s390_emit_VMN(buf, v1, v2, v3, s390_getM_from_size(size));
11650 case S390_VEC_AVGU:
11651 return s390_emit_VAVGL(buf, v1, v2, v3, s390_getM_from_size(size));
11652 case S390_VEC_AVGS:
11653 return s390_emit_VAVG(buf, v1, v2, v3, s390_getM_from_size(size));
11654 case S390_VEC_COMPARE_GREATERS:
11655 return s390_emit_VCH(buf, v1, v2, v3, s390_getM_from_size(size));
11656 case S390_VEC_COMPARE_GREATERU:
11657 return s390_emit_VCHL(buf, v1, v2, v3, s390_getM_from_size(size));
11658 case S390_VEC_INT_MUL_HIGHS:
11659 return s390_emit_VMH(buf, v1, v2, v3, s390_getM_from_size(size));
11660 case S390_VEC_INT_MUL_HIGHU:
11661 return s390_emit_VMLH(buf, v1, v2, v3, s390_getM_from_size(size));
11662 case S390_VEC_INT_MUL_LOW:
11663 return s390_emit_VML(buf, v1, v2, v3, s390_getM_from_size(size));
11664 case S390_VEC_INT_MUL_EVENS:
11665 return s390_emit_VME(buf, v1, v2, v3, s390_getM_from_size(size));
11666 case S390_VEC_INT_MUL_EVENU:
11667 return s390_emit_VMLE(buf, v1, v2, v3, s390_getM_from_size(size));
11668 case S390_VEC_ELEM_SHL_V:
11669 return s390_emit_VESLV(buf, v1, v2, v3, s390_getM_from_size(size));
11670 case S390_VEC_ELEM_SHRA_V:
11671 return s390_emit_VESRAV(buf, v1, v2, v3, s390_getM_from_size(size));
11672 case S390_VEC_ELEM_SHRL_V:
11673 return s390_emit_VESRLV(buf, v1, v2, v3, s390_getM_from_size(size));
11674 case S390_VEC_ELEM_ROLL_V:
11675 return s390_emit_VERLLV(buf, v1, v2, v3, s390_getM_from_size(size));
11676 case S390_VEC_SHL_BITS:
11677 return s390_emit_VSL(buf, v1, v2, v3);
11678 case S390_VEC_SHRL_BITS:
11679 return s390_emit_VSRL(buf, v1, v2, v3);
11680 case S390_VEC_SHRA_BITS:
11681 return s390_emit_VSRA(buf, v1, v2, v3);
11682 case S390_VEC_SHL_BYTES:
11683 return s390_emit_VSLB(buf, v1, v2, v3);
11684 case S390_VEC_SHRL_BYTES:
11685 return s390_emit_VSRLB(buf, v1, v2, v3);
11686 case S390_VEC_SHRA_BYTES:
11687 return s390_emit_VSRAB(buf, v1, v2, v3);
11688 case S390_VEC_PWSUM_W:
11689 vassert((size == 1) || (size == 2));
11690 return s390_emit_VSUM(buf, v1, v2, v3, s390_getM_from_size(size));
11691 case S390_VEC_PWSUM_DW:
11692 vassert((size == 2) || (size == 4));
11693 return s390_emit_VSUMG(buf, v1, v2, v3, s390_getM_from_size(size));
11694 case S390_VEC_PWSUM_QW:
11695 vassert((size == 4) || (size == 8));
11696 return s390_emit_VSUMQ(buf, v1, v2, v3, s390_getM_from_size(size));
11697 case S390_VEC_INIT_FROM_GPRS:
11698 return s390_emit_VLVGP(buf, v1, v2, v3);
11699 case S390_VEC_INIT_FROM_FPRS:
11700 return s390_emit_VMRH(buf, v1, v2, v3, 3);
11701 case S390_VEC_FLOAT_ADD:
11702 return s390_emit_VFA(buf, v1, v2, v3, s390_getM_from_size(size), 0);
11703 case S390_VEC_FLOAT_SUB:
11704 return s390_emit_VFS(buf, v1, v2, v3, s390_getM_from_size(size), 0);
11705 case S390_VEC_FLOAT_MUL:
11706 return s390_emit_VFM(buf, v1, v2, v3, s390_getM_from_size(size), 0);
11707 case S390_VEC_FLOAT_DIV:
11708 return s390_emit_VFD(buf, v1, v2, v3, s390_getM_from_size(size), 0);
11709 case S390_VEC_FLOAT_COMPARE_EQUAL:
11710 return s390_emit_VFCE(buf, v1, v2, v3, s390_getM_from_size(size), 0, 0);
11711 case S390_VEC_FLOAT_COMPARE_LESS_OR_EQUAL:
11712 return s390_emit_VFCHE(buf, v1, v3, v2, s390_getM_from_size(size), 0, 0);
11713 case S390_VEC_FLOAT_COMPARE_LESS:
11714 return s390_emit_VFCH(buf, v1, v3, v2, s390_getM_from_size(size), 0, 0);
11716 default:
11717 goto fail;
11720 fail:
11721 ppS390Instr(insn, True);
11722 vpanic("s390_insn_vec_binop_emit");
11727 static UChar *
11728 s390_insn_vec_triop_emit(UChar *buf, const s390_insn *insn)
11730 s390_vec_triop_t tag = insn->variant.vec_triop.tag;
11731 UChar size = insn->size;
11732 UChar v1 = hregNumber(insn->variant.vec_triop.dst);
11733 UChar v2 = hregNumber(insn->variant.vec_triop.op1);
11734 UChar v3 = hregNumber(insn->variant.vec_triop.op2);
11735 UChar v4 = hregNumber(insn->variant.vec_triop.op3);
11737 switch (tag) {
11738 case S390_VEC_PERM: {
11739 vassert(size == 16);
11740 return s390_emit_VPERM(buf, v1, v2, v3, v4);
11742 case S390_VEC_FLOAT_MADD:
11743 return s390_emit_VFMA(buf, v1, v2, v3, v4, 0,
11744 s390_getM_from_size(size));
11745 case S390_VEC_FLOAT_MSUB:
11746 return s390_emit_VFMS(buf, v1, v2, v3, v4, 0,
11747 s390_getM_from_size(size));
11748 default:
11749 goto fail;
11752 fail:
11753 vpanic("s390_insn_vec_triop_emit");
11758 static UChar *
11759 s390_insn_vec_replicate_emit(UChar *buf, const s390_insn *insn)
11761 UChar v1 = hregNumber(insn->variant.vec_replicate.dst);
11762 UChar v2 = hregNumber(insn->variant.vec_replicate.op1);
11763 UShort idx = (UShort) insn->variant.vec_replicate.idx;
11764 return s390_emit_VREP(buf, v1, v2, idx, s390_getM_from_size(insn->size));
11769 emit_S390Instr(Bool *is_profinc, UChar *buf, Int nbuf, const s390_insn *insn,
11770 Bool mode64, VexEndness endness_host,
11771 const void *disp_cp_chain_me_to_slowEP,
11772 const void *disp_cp_chain_me_to_fastEP,
11773 const void *disp_cp_xindir,
11774 const void *disp_cp_xassisted)
11776 UChar *end;
11778 /* Used to be 48 bytes. Make sure it stays low */
11779 vassert(sizeof(s390_insn) == 32);
11781 switch (insn->tag) {
11782 case S390_INSN_LOAD:
11783 end = s390_insn_load_emit(buf, insn);
11784 break;
11786 case S390_INSN_STORE:
11787 end = s390_insn_store_emit(buf, insn);
11788 break;
11790 case S390_INSN_MOVE:
11791 end = s390_insn_move_emit(buf, insn);
11792 break;
11794 case S390_INSN_MEMCPY:
11795 end = s390_insn_memcpy_emit(buf, insn);
11796 break;
11798 case S390_INSN_COND_MOVE:
11799 end = s390_insn_cond_move_emit(buf, insn);
11800 break;
11802 case S390_INSN_LOAD_IMMEDIATE:
11803 end = s390_insn_load_immediate_emit(buf, insn);
11804 break;
11806 case S390_INSN_ALU:
11807 end = s390_insn_alu_emit(buf, insn);
11808 break;
11810 case S390_INSN_SMUL:
11811 case S390_INSN_UMUL:
11812 end = s390_insn_mul_emit(buf, insn);
11813 break;
11815 case S390_INSN_SDIV:
11816 case S390_INSN_UDIV:
11817 end = s390_insn_div_emit(buf, insn);
11818 break;
11820 case S390_INSN_DIVS:
11821 end = s390_insn_divs_emit(buf, insn);
11822 break;
11824 case S390_INSN_CLZ:
11825 end = s390_insn_clz_emit(buf, insn);
11826 break;
11828 case S390_INSN_UNOP:
11829 end = s390_insn_unop_emit(buf, insn);
11830 break;
11832 case S390_INSN_TEST:
11833 end = s390_insn_test_emit(buf, insn);
11834 break;
11836 case S390_INSN_CC2BOOL:
11837 end = s390_insn_cc2bool_emit(buf, insn);
11838 break;
11840 case S390_INSN_CAS:
11841 end = s390_insn_cas_emit(buf, insn);
11842 break;
11844 case S390_INSN_CDAS:
11845 end = s390_insn_cdas_emit(buf, insn);
11846 break;
11848 case S390_INSN_COMPARE:
11849 end = s390_insn_compare_emit(buf, insn);
11850 break;
11852 case S390_INSN_HELPER_CALL:
11853 end = s390_insn_helper_call_emit(buf, insn);
11854 if (end == buf) goto fail;
11855 break;
11857 case S390_INSN_BFP_TRIOP:
11858 end = s390_insn_bfp_triop_emit(buf, insn);
11859 break;
11861 case S390_INSN_BFP_BINOP:
11862 end = s390_insn_bfp_binop_emit(buf, insn);
11863 break;
11865 case S390_INSN_BFP_UNOP:
11866 end = s390_insn_bfp_unop_emit(buf, insn);
11867 break;
11869 case S390_INSN_BFP_COMPARE:
11870 end = s390_insn_bfp_compare_emit(buf, insn);
11871 break;
11873 case S390_INSN_BFP_CONVERT:
11874 end = s390_insn_bfp_convert_emit(buf, insn);
11875 break;
11877 case S390_INSN_DFP_BINOP:
11878 end = s390_insn_dfp_binop_emit(buf, insn);
11879 break;
11881 case S390_INSN_DFP_UNOP:
11882 end = s390_insn_dfp_unop_emit(buf, insn);
11883 break;
11885 case S390_INSN_DFP_INTOP:
11886 end = s390_insn_dfp_intop_emit(buf, insn);
11887 break;
11889 case S390_INSN_DFP_COMPARE:
11890 end = s390_insn_dfp_compare_emit(buf, insn);
11891 break;
11893 case S390_INSN_DFP_CONVERT:
11894 end = s390_insn_dfp_convert_emit(buf, insn);
11895 break;
11897 case S390_INSN_DFP_REROUND:
11898 end = s390_insn_dfp_reround_emit(buf, insn);
11899 break;
11901 case S390_INSN_FP_CONVERT:
11902 end = s390_insn_fp_convert_emit(buf, insn);
11903 break;
11905 case S390_INSN_MFENCE:
11906 end = s390_insn_mfence_emit(buf, insn);
11907 break;
11909 case S390_INSN_MIMM:
11910 end = s390_insn_mimm_emit(buf, insn);
11911 break;
11913 case S390_INSN_MADD:
11914 end = s390_insn_madd_emit(buf, insn);
11915 break;
11917 case S390_INSN_SET_FPC_BFPRM:
11918 end = s390_insn_set_fpc_bfprm_emit(buf, insn);
11919 break;
11921 case S390_INSN_SET_FPC_DFPRM:
11922 end = s390_insn_set_fpc_dfprm_emit(buf, insn);
11923 break;
11925 case S390_INSN_PROFINC:
11926 end = s390_insn_profinc_emit(buf, insn);
11927 /* Tell the caller .. */
11928 vassert(*is_profinc == False);
11929 *is_profinc = True;
11930 break;
11932 case S390_INSN_EVCHECK:
11933 end = s390_insn_evcheck_emit(buf, insn, endness_host);
11934 break;
11936 case S390_INSN_XDIRECT:
11937 end = s390_insn_xdirect_emit(buf, insn, disp_cp_chain_me_to_slowEP,
11938 disp_cp_chain_me_to_fastEP);
11939 break;
11941 case S390_INSN_XINDIR:
11942 end = s390_insn_xindir_emit(buf, insn, disp_cp_xindir);
11943 break;
11945 case S390_INSN_XASSISTED:
11946 end = s390_insn_xassisted_emit(buf, insn, disp_cp_xassisted);
11947 break;
11949 case S390_INSN_VEC_AMODEOP:
11950 end = s390_insn_vec_amodeop_emit(buf, insn);
11951 break;
11953 case S390_INSN_VEC_AMODEINTOP:
11954 end = s390_insn_vec_amodeintop_emit(buf, insn);
11955 break;
11957 case S390_INSN_VEC_BINOP:
11958 end = s390_insn_vec_binop_emit(buf, insn);
11959 break;
11961 case S390_INSN_VEC_TRIOP:
11962 end = s390_insn_vec_triop_emit(buf, insn);
11963 break;
11965 case S390_INSN_VEC_REPLICATE:
11966 end = s390_insn_vec_replicate_emit(buf, insn);
11967 break;
11969 fail:
11970 default:
11971 vpanic("emit_S390Instr");
11974 vassert(end - buf <= nbuf);
11976 return end - buf;
11980 /* Return the number of bytes emitted for an S390_INSN_EVCHECK.
11981 See s390_insn_evcheck_emit */
11983 evCheckSzB_S390(void)
11985 return s390_host_has_gie ? 18 : 24;
11989 /* Patch the counter address into CODE_TO_PATCH as previously
11990 generated by s390_insn_profinc_emit. */
11991 VexInvalRange
11992 patchProfInc_S390(VexEndness endness_host,
11993 void *code_to_patch, const ULong *location_of_counter)
11995 vassert(sizeof(ULong *) == 8);
11997 s390_tchain_verify_load64(code_to_patch, S390_REGNO_TCHAIN_SCRATCH, 0);
11999 UChar *p = s390_tchain_patch_load64(code_to_patch,
12000 (Addr)location_of_counter);
12002 UInt len = p - (UChar *)code_to_patch;
12003 VexInvalRange vir = { (HWord)code_to_patch, len };
12004 return vir;
12008 /* NB: what goes on here has to be very closely coordinated with the
12009 s390_insn_xdirect_emit code above. */
12010 VexInvalRange
12011 chainXDirect_S390(VexEndness endness_host,
12012 void *place_to_chain,
12013 const void *disp_cp_chain_me_EXPECTED,
12014 const void *place_to_jump_to)
12016 vassert(endness_host == VexEndnessBE);
12018 /* What we're expecting to see @ PLACE_TO_CHAIN is:
12020 load tchain_scratch, #disp_cp_chain_me_EXPECTED
12021 goto *tchain_scratch
12023 const UChar *next;
12024 next = s390_tchain_verify_load64(place_to_chain, S390_REGNO_TCHAIN_SCRATCH,
12025 (Addr)disp_cp_chain_me_EXPECTED);
12026 vassert(s390_insn_is_BR(next, S390_REGNO_TCHAIN_SCRATCH));
12028 /* And what we want to change it to is either:
12029 (general case):
12031 load tchain_scratch, #place_to_jump_to
12032 goto *tchain_scratch
12034 ---OR---
12036 in the case where the displacement is small enough
12038 BRCL delta where delta is in half-words
12039 invalid opcodes
12041 In both cases the replacement has the same length as the original.
12042 To remain sane & verifiable,
12043 (1) limit the displacement for the short form to
12044 (say) +/- one billion, so as to avoid wraparound
12045 off-by-ones
12046 (2) even if the short form is applicable, once every (say)
12047 1024 times use the long form anyway, so as to maintain
12048 verifiability
12051 /* This is the delta we need to put into a BRCL insn. Note, that the
12052 offset in BRCL is in half-words. Hence division by 2. */
12053 Long delta =
12054 (Long)((const UChar *)place_to_jump_to - (const UChar *)place_to_chain) / 2;
12055 Bool shortOK = delta >= -1000*1000*1000 && delta < 1000*1000*1000;
12057 static UInt shortCTR = 0; /* DO NOT MAKE NON-STATIC */
12058 if (shortOK) {
12059 shortCTR++; // thread safety bleh
12060 if (0 == (shortCTR & 0x3FF)) {
12061 shortOK = False;
12062 if (0)
12063 vex_printf("QQQ chainXDirect_S390: shortCTR = %u, "
12064 "using long jmp\n", shortCTR);
12068 /* And make the modifications. */
12069 UChar *p = (UChar *)place_to_chain;
12070 if (shortOK) {
12071 p = s390_emit_BRCL(p, S390_CC_ALWAYS, delta); /* 6 bytes */
12073 /* Make sure that BRCL fits into the patchable part of an xdirect
12074 code sequence */
12075 vassert(6 <= s390_xdirect_patchable_len());
12077 /* Fill remaining bytes with 0x00 (invalid opcode) */
12078 Int i;
12079 for (i = 0; i < s390_xdirect_patchable_len() - 6; ++i)
12080 p[i] = 0x00;
12081 } else {
12083 load tchain_scratch, #place_to_jump_to
12084 goto *tchain_scratch
12086 Addr64 addr = (Addr)place_to_jump_to;
12087 p = s390_tchain_load64(p, S390_REGNO_TCHAIN_SCRATCH, addr);
12088 /* There is not need to emit a BCR here, as it is already there. */
12091 UInt len = p - (UChar *)place_to_chain;
12092 VexInvalRange vir = { (HWord)place_to_chain, len };
12093 return vir;
12097 /* NB: what goes on here has to be very closely coordinated with the
12098 s390_insn_xdirect_emit code above. */
12099 VexInvalRange
12100 unchainXDirect_S390(VexEndness endness_host,
12101 void *place_to_unchain,
12102 const void *place_to_jump_to_EXPECTED,
12103 const void *disp_cp_chain_me)
12105 vassert(endness_host == VexEndnessBE);
12107 /* What we're expecting to see @ PLACE_TO_UNCHAIN:
12109 load tchain_scratch, #place_to_jump_to_EXPECTED
12110 goto *tchain_scratch
12112 ---OR---
12113 in the case where the displacement falls within 32 bits
12115 BRCL delta
12116 invalid opcodes
12118 UChar *p = place_to_unchain;
12120 Bool uses_short_form = False;
12122 if (s390_insn_is_BRCL(p, S390_CC_ALWAYS)) {
12123 /* Looks like the short form */
12124 Int num_hw = *(Int *)&p[2];
12125 Int delta = 2 *num_hw;
12127 vassert(p + delta == place_to_jump_to_EXPECTED);
12129 Int i;
12130 for (i = 0; i < s390_xdirect_patchable_len() - 6; ++i)
12131 vassert(p[6+i] == 0x00);
12132 uses_short_form = True;
12133 } else {
12134 /* Should be the long form */
12135 const UChar *next;
12137 next = s390_tchain_verify_load64(p, S390_REGNO_TCHAIN_SCRATCH,
12138 (Addr)place_to_jump_to_EXPECTED);
12139 /* Check for BR *tchain_scratch */
12140 vassert(s390_insn_is_BR(next, S390_REGNO_TCHAIN_SCRATCH));
12143 /* And what we want to change it to is:
12145 load tchain_scratch, #disp_cp_chain_me
12146 goto *tchain_scratch
12149 /* Get the address of the beginning of the load64 code sequence into %r1.
12150 Do not change the register! This is part of the protocol with the
12151 dispatcher.
12152 Note: the incoming argument PLACE_TO_CHAIN points to the beginning of the
12153 load64 insn sequence. That sequence is prefixed with a BASR to get its
12154 address (see s390_insn_xdirect_emit). */
12155 p = s390_emit_BASR(p - S390_BASR_LEN, 1, R0);
12157 Addr64 addr = (Addr)disp_cp_chain_me;
12158 p = s390_tchain_load64(p, S390_REGNO_TCHAIN_SCRATCH, addr);
12160 /* Emit the BCR in case the short form was used. In case of the long
12161 form, the BCR is already there. */
12162 if (uses_short_form)
12163 s390_emit_BCR(p, S390_CC_ALWAYS, S390_REGNO_TCHAIN_SCRATCH);
12165 UInt len = p - (UChar *)place_to_unchain;
12166 VexInvalRange vir = { (HWord)place_to_unchain, len };
12167 return vir;
12170 /*---------------------------------------------------------------*/
12171 /*--- end host_s390_defs.c ---*/
12172 /*---------------------------------------------------------------*/