1 /* -*- mode: C; c-basic-offset: 3; -*- */
2
3 /*---------------------------------------------------------------*/
4 /*--- begin host_s390_defs.c ---*/
5 /*---------------------------------------------------------------*/
6
7 /*
8 This file is part of Valgrind, a dynamic binary instrumentation
9 framework.
10
11 Copyright IBM Corp. 2010-2017
12 Copyright (C) 2012-2017 Florian Krohm (britzel@acm.org)
13
14 This program is free software; you can redistribute it and/or
15 modify it under the terms of the GNU General Public License as
16 published by the Free Software Foundation; either version 2 of the
17 License, or (at your option) any later version.
18
19 This program is distributed in the hope that it will be useful, but
20 WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 General Public License for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with this program; if not, write to the Free Software
26 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
27 02110-1301, USA.
28
29 The GNU General Public License is contained in the file COPYING.
30 */
31
32 /* Contributed by Florian Krohm */
33
34 #include "libvex_basictypes.h"
35 #include "libvex.h"
36 #include "libvex_trc_values.h"
37 #include "libvex_s390x_common.h"
38
39 #include "main_util.h"
40 #include "main_globals.h"
41 #include "host_generic_regs.h"
42 #include "host_s390_defs.h"
43 #include "s390_disasm.h"
44 #include "guest_s390_defs.h" /* S390X_GUEST_OFFSET */
45 #include <stdarg.h>
46
47 /*------------------------------------------------------------*/
48 /*--- Forward declarations ---*/
49 /*------------------------------------------------------------*/
50
51 static void s390_insn_map_regs(HRegRemap *, s390_insn *);
52 static void s390_insn_get_reg_usage(HRegUsage *u, const s390_insn *);
53 static UInt s390_tchain_load64_len(void);
54
55
56 /*------------------------------------------------------------*/
57 /*--- Registers ---*/
58 /*------------------------------------------------------------*/
59
60 /* A mapping from register number to register index */
61 static Int gpr_index[16]; // GPR regno -> register index
62 static Int vr_index[32]; // VR regno -> register index
63
64 HReg
s390_hreg_gpr(UInt regno)65 s390_hreg_gpr(UInt regno)
66 {
67 Int ix = gpr_index[regno];
68 vassert(ix >= 0);
69 return mkHReg(/*virtual*/False, HRcInt64, regno, ix);
70 }
71
72 HReg
s390_hreg_fpr(UInt regno)73 s390_hreg_fpr(UInt regno)
74 {
75 Int ix = vr_index[regno];
76 vassert(ix >= 0);
77 return mkHReg(/*virtual*/False, HRcFlt64, regno, ix);
78 }
79
80 HReg
s390_hreg_vr(UInt regno)81 s390_hreg_vr(UInt regno)
82 {
83 Int ix = vr_index[regno];
84 vassert(ix >= 0);
85 return mkHReg(/*virtual*/False, HRcVec128, regno, ix);
86 }
87
88 static __inline__ UInt
hregNumber(HReg reg)89 hregNumber(HReg reg)
90 {
91 return hregEncoding(reg);
92 }
93
94 /* Decompile the given register into a static buffer and return it */
95 const HChar *
s390_hreg_as_string(HReg reg)96 s390_hreg_as_string(HReg reg)
97 {
98 static HChar buf[10];
99
100 static const HChar ireg_names[16][5] = {
101 "%r0", "%r1", "%r2", "%r3", "%r4", "%r5", "%r6", "%r7",
102 "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15"
103 };
104
105 static const HChar freg_names[16][5] = {
106 "%f0", "%f1", "%f2", "%f3", "%f4", "%f5", "%f6", "%f7",
107 "%f8", "%f9", "%f10", "%f11", "%f12", "%f13", "%f14", "%f15"
108 };
109
110 static const HChar vreg_names[32][5] = {
111 "%v0", "%v1", "%v2", "%v3", "%v4", "%v5", "%v6", "%v7",
112 "%v8", "%v9", "%v10", "%v11", "%v12", "%v13", "%v14", "%v15",
113 "%v16", "%v17", "%v18", "%v19", "%v20", "%v21", "%v22", "%v23",
114 "%v24", "%v25", "%v26", "%v27", "%v28", "%v29", "%v30", "%v31"
115 };
116
117 UInt r; /* hregNumber() returns an UInt */
118
119 r = hregNumber(reg);
120
121 /* Be generic for all virtual regs. */
122 if (hregIsVirtual(reg)) {
123 buf[0] = '\0';
124 switch (hregClass(reg)) {
125 case HRcInt64: vex_sprintf(buf, "%%vR%u", r); break;
126 case HRcFlt64: vex_sprintf(buf, "%%vF%u", r); break;
127 case HRcVec128: vex_sprintf(buf, "%%vV%u", r); break;
128 default: goto fail;
129 }
130 return buf;
131 }
132
133 /* But specific for real regs. */
134 switch (hregClass(reg)) {
135 case HRcInt64: vassert(r < 16); return ireg_names[r];
136 case HRcFlt64: vassert(r < 16); return freg_names[r];
137 case HRcVec128: vassert(r < 32); return vreg_names[r];
138 default: goto fail;
139 }
140
141 fail: vpanic("s390_hreg_as_string");
142 }
143
144
145 /* Return the real register that holds the guest state pointer */
146 HReg
s390_hreg_guest_state_pointer(void)147 s390_hreg_guest_state_pointer(void)
148 {
149 return s390_hreg_gpr(S390_REGNO_GUEST_STATE_POINTER);
150 }
151
152 /* Return the real register that holds the stack pointer */
153 HReg
s390_hreg_stack_pointer(void)154 s390_hreg_stack_pointer(void)
155 {
156 return s390_hreg_gpr(S390_REGNO_STACK_POINTER);
157 }
158
159
160 /* Is VALUE within the domain of a 20-bit signed integer. */
161 static __inline__ Bool
fits_signed_20bit(Int value)162 fits_signed_20bit(Int value)
163 {
164 UInt uval = value;
165 return ((Int)(uval << 12) >> 12) == value;
166 }
167
168
169 /* Is VALUE within the domain of a 12-bit unsigned integer. */
170 static __inline__ Bool
fits_unsigned_12bit(Int value)171 fits_unsigned_12bit(Int value)
172 {
173 return (value & 0xFFF) == value;
174 }
175
176 /*------------------------------------------------------------*/
177 /*--- Addressing modes (amodes) ---*/
178 /*------------------------------------------------------------*/
179
180 /* Construct a b12 amode. */
181 s390_amode *
s390_amode_b12(Int d,HReg b)182 s390_amode_b12(Int d, HReg b)
183 {
184 s390_amode *am = LibVEX_Alloc_inline(sizeof(s390_amode));
185
186 vassert(fits_unsigned_12bit(d));
187
188 am->tag = S390_AMODE_B12;
189 am->d = d;
190 am->b = b;
191 am->x = s390_hreg_gpr(0); /* hregNumber(am->x) == 0 */
192
193 return am;
194 }
195
196
197 /* Construct a b20 amode. */
198 s390_amode *
s390_amode_b20(Int d,HReg b)199 s390_amode_b20(Int d, HReg b)
200 {
201 s390_amode *am = LibVEX_Alloc_inline(sizeof(s390_amode));
202
203 vassert(fits_signed_20bit(d));
204
205 am->tag = S390_AMODE_B20;
206 am->d = d;
207 am->b = b;
208 am->x = s390_hreg_gpr(0); /* hregNumber(am->x) == 0 */
209
210 return am;
211 }
212
213
214 /* Construct a bx12 amode. */
215 s390_amode *
s390_amode_bx12(Int d,HReg b,HReg x)216 s390_amode_bx12(Int d, HReg b, HReg x)
217 {
218 s390_amode *am = LibVEX_Alloc_inline(sizeof(s390_amode));
219
220 vassert(fits_unsigned_12bit(d));
221 vassert(hregNumber(b) != 0);
222 vassert(hregNumber(x) != 0);
223
224 am->tag = S390_AMODE_BX12;
225 am->d = d;
226 am->b = b;
227 am->x = x;
228
229 return am;
230 }
231
232
233 /* Construct a bx20 amode. */
234 s390_amode *
s390_amode_bx20(Int d,HReg b,HReg x)235 s390_amode_bx20(Int d, HReg b, HReg x)
236 {
237 s390_amode *am = LibVEX_Alloc_inline(sizeof(s390_amode));
238
239 vassert(fits_signed_20bit(d));
240 vassert(hregNumber(b) != 0);
241 vassert(hregNumber(x) != 0);
242
243 am->tag = S390_AMODE_BX20;
244 am->d = d;
245 am->b = b;
246 am->x = x;
247
248 return am;
249 }
250
251
252 /* Construct an AMODE for accessing the guest state at OFFSET.
253 OFFSET can be at most 3 * sizeof(VexGuestS390XState) + LibVEX_N_SPILL_BYTES
254 which may be too large for a B12 addressing mode.
255 Use a B20 amode as a fallback which will be safe for any offset.
256 */
257 s390_amode *
s390_amode_for_guest_state(Int offset)258 s390_amode_for_guest_state(Int offset)
259 {
260 if (fits_unsigned_12bit(offset))
261 return s390_amode_b12(offset, s390_hreg_guest_state_pointer());
262
263 if (fits_signed_20bit(offset))
264 return s390_amode_b20(offset, s390_hreg_guest_state_pointer());
265
266 vpanic("invalid guest state offset");
267 }
268
269
270 /* Construct an AMODE for accessing stack pointer at OFFSET.
271 OFFSET can be at most 3 * sizeof(VexGuestS390XState) + LibVEX_N_SPILL_BYTES
272 which may be too large for a B12 addressing mode.
273 Use a B20 amode as a fallback which will be safe for any offset.
274 */
275 s390_amode *
s390_amode_for_stack_pointer(Int offset)276 s390_amode_for_stack_pointer(Int offset)
277 {
278 if (fits_unsigned_12bit(offset))
279 return s390_amode_b12(offset, s390_hreg_stack_pointer());
280
281 if (fits_signed_20bit(offset))
282 return s390_amode_b20(offset, s390_hreg_stack_pointer());
283
284 vpanic("invalid stack pointer offset");
285 }
286
287
288 /* Decompile the given amode into a static buffer and return it. */
289 const HChar *
s390_amode_as_string(const s390_amode * am)290 s390_amode_as_string(const s390_amode *am)
291 {
292 static HChar buf[30];
293 HChar *p;
294
295 buf[0] = '\0';
296 p = buf;
297
298 switch (am->tag) {
299 case S390_AMODE_B12:
300 case S390_AMODE_B20:
301 vex_sprintf(p, "%d(%s)", am->d, s390_hreg_as_string(am->b));
302 break;
303
304 case S390_AMODE_BX12:
305 case S390_AMODE_BX20:
306 /* s390_hreg_as_string returns pointer to local buffer. Need to
307 split this into two printfs */
308 p += vex_sprintf(p, "%d(%s,", am->d, s390_hreg_as_string(am->x));
309 vex_sprintf(p, "%s)", s390_hreg_as_string(am->b));
310 break;
311
312 default:
313 vpanic("s390_amode_as_string");
314 }
315
316 return buf;
317 }
318
319
320 /* Helper function for s390_amode_is_sane */
321 static __inline__ Bool
is_virtual_gpr(HReg reg)322 is_virtual_gpr(HReg reg)
323 {
324 return hregIsVirtual(reg) && hregClass(reg) == HRcInt64;
325 }
326
327 /* Helper function for all vector operations */
328 static UChar
s390_getM_from_size(const UChar size)329 s390_getM_from_size(const UChar size) {
330 switch(size) {
331 case 1:
332 return 0;
333 case 2:
334 return 1;
335 case 4:
336 return 2;
337 case 8:
338 return 3;
339 case 16:
340 return 4;
341 default:
342 vex_printf("size=%d\n", size);
343 vpanic("s390_getM_from_size: unknown size");
344 }
345 }
346
347 /* Helper for generating RXB field in vector instructions */
348 static UChar
s390_update_rxb(const UChar rxb,const UChar index,UChar * vr)349 s390_update_rxb(const UChar rxb, const UChar index, UChar* vr) {
350 vassert((index >= 1) && (index <= 4));
351 UChar result = rxb;
352 if(vr != NULL) {
353 if(*vr >= 16) {
354 result |= 1 << (4 - index);
355 *vr -= 16;
356 }
357 }
358 return result;
359 }
360
361 /* Sanity check for an amode */
362 Bool
s390_amode_is_sane(const s390_amode * am)363 s390_amode_is_sane(const s390_amode *am)
364 {
365 switch (am->tag) {
366 case S390_AMODE_B12:
367 return is_virtual_gpr(am->b) && fits_unsigned_12bit(am->d);
368
369 case S390_AMODE_B20:
370 return is_virtual_gpr(am->b) && fits_signed_20bit(am->d);
371
372 case S390_AMODE_BX12:
373 return is_virtual_gpr(am->b) && is_virtual_gpr(am->x) &&
374 fits_unsigned_12bit(am->d);
375
376 case S390_AMODE_BX20:
377 return is_virtual_gpr(am->b) && is_virtual_gpr(am->x) &&
378 fits_signed_20bit(am->d);
379
380 default:
381 vpanic("s390_amode_is_sane");
382 }
383 }
384
385
386 /* Record the register use of an amode */
387 static void
s390_amode_get_reg_usage(HRegUsage * u,const s390_amode * am)388 s390_amode_get_reg_usage(HRegUsage *u, const s390_amode *am)
389 {
390 switch (am->tag) {
391 case S390_AMODE_B12:
392 case S390_AMODE_B20:
393 addHRegUse(u, HRmRead, am->b);
394 return;
395
396 case S390_AMODE_BX12:
397 case S390_AMODE_BX20:
398 addHRegUse(u, HRmRead, am->b);
399 addHRegUse(u, HRmRead, am->x);
400 return;
401
402 default:
403 vpanic("s390_amode_get_reg_usage");
404 }
405 }
406
407
408 static void
s390_amode_map_regs(HRegRemap * m,s390_amode * am)409 s390_amode_map_regs(HRegRemap *m, s390_amode *am)
410 {
411 switch (am->tag) {
412 case S390_AMODE_B12:
413 case S390_AMODE_B20:
414 am->b = lookupHRegRemap(m, am->b);
415 return;
416
417 case S390_AMODE_BX12:
418 case S390_AMODE_BX20:
419 am->b = lookupHRegRemap(m, am->b);
420 am->x = lookupHRegRemap(m, am->x);
421 return;
422
423 default:
424 vpanic("s390_amode_map_regs");
425 }
426 }
427
428
429 void
ppS390AMode(const s390_amode * am)430 ppS390AMode(const s390_amode *am)
431 {
432 vex_printf("%s", s390_amode_as_string(am));
433 }
434
435 void
ppS390Instr(const s390_insn * insn,Bool mode64)436 ppS390Instr(const s390_insn *insn, Bool mode64)
437 {
438 vex_printf("%s", s390_insn_as_string(insn));
439 }
440
441 UInt
ppHRegS390(HReg reg)442 ppHRegS390(HReg reg)
443 {
444 return vex_printf("%s", s390_hreg_as_string(reg));
445 }
446
447 /*------------------------------------------------------------*/
448 /*--- Helpers for register allocation ---*/
449 /*------------------------------------------------------------*/
450
451 /* Initialise and return the "register universe", i.e. a list of
452 all hardware registers. Called once. */
453 const RRegUniverse *
getRRegUniverse_S390(void)454 getRRegUniverse_S390(void)
455 {
456 static RRegUniverse all_regs;
457 static Bool initialised = False;
458 RRegUniverse *ru = &all_regs;
459
460 if (LIKELY(initialised))
461 return ru;
462
463 RRegUniverse__init(ru);
464
465 /* Assign invalid values to the gpr/vr_index */
466 for (UInt i = 0; i < sizeof gpr_index / sizeof gpr_index[0]; ++i)
467 gpr_index[i] = -1;
468 for (UInt i = 0; i < sizeof vr_index / sizeof vr_index[0]; ++i)
469 vr_index[i] = -1;
470
471
472 /* Add the registers that are available to the register allocator.
473 GPRs: registers 6..11 are callee saved, list them first
474 registers 1..5 are caller saved, list them after
475 FPRs: registers 8..15 are callee saved, list them first
476 registers 0..7 are caller saved, list them after
477 FPR12 - FPR15 are also used as register pairs for 128-bit
478 floating point operations
479 VRs: registers 0..31 are available
480 */
481 ru->allocable_start[HRcInt64] = ru->size;
482 for (UInt regno = 6; regno <= 11; ++regno) {
483 gpr_index[regno] = ru->size;
484 ru->regs[ru->size++] = s390_hreg_gpr(regno);
485 }
486 for (UInt regno = 1; regno <= 5; ++regno) {
487 gpr_index[regno] = ru->size;
488 ru->regs[ru->size++] = s390_hreg_gpr(regno);
489 }
490 ru->allocable_end[HRcInt64] = ru->size - 1;
491
492 ru->allocable_start[HRcFlt64] = ru->size;
493 for (UInt regno = 8; regno <= 15; ++regno) {
494 vr_index[regno] = ru->size;
495 ru->regs[ru->size++] = s390_hreg_fpr(regno);
496 }
497 for (UInt regno = 0; regno <= 7; ++regno) {
498 vr_index[regno] = ru->size;
499 ru->regs[ru->size++] = s390_hreg_fpr(regno);
500 }
501 ru->allocable_end[HRcFlt64] = ru->size - 1;
502
503 ru->allocable_start[HRcVec128] = ru->size;
504 for (UInt regno = 16; regno <= 31; ++regno) {
505 vr_index[regno] = ru->size;
506 ru->regs[ru->size++] = s390_hreg_vr(regno);
507 }
508 ru->allocable_end[HRcVec128] = ru->size - 1;
509 ru->allocable = ru->size;
510
511 /* Add the registers that are not available for allocation.
512 r0 -- cannot be used as a base or index register
513 r12 -- scratch register for translation chaining support
514 r13 -- guest state pointer
515 r14 -- link register
516 r15 -- stack pointer
517 */
518 UInt other[] = { 0, 12, 13, 14, 15 };
519 for (UInt i = 0; i < sizeof other / sizeof other[0]; ++i) {
520 gpr_index[other[i]] = ru->size;
521 ru->regs[ru->size++] = s390_hreg_gpr(other[i]);
522 }
523
524 /* Sanity checking */
525 for (UInt i = 0; i < sizeof gpr_index / sizeof gpr_index[0]; ++i)
526 vassert(gpr_index[i] >= 0);
527 for (UInt i = 0; i < sizeof vr_index / sizeof vr_index[0]; ++i)
528 vassert(vr_index[i] >= 0);
529
530 initialised = True;
531
532 RRegUniverse__check_is_sane(ru);
533 return ru;
534 }
535
536 /* Tell the register allocator how the given instruction uses the registers
537 it refers to. */
538 void
getRegUsage_S390Instr(HRegUsage * u,const s390_insn * insn,Bool mode64)539 getRegUsage_S390Instr(HRegUsage *u, const s390_insn *insn, Bool mode64)
540 {
541 s390_insn_get_reg_usage(u, insn);
542 }
543
544
545 /* Map the registers of the given instruction */
546 void
mapRegs_S390Instr(HRegRemap * m,s390_insn * insn,Bool mode64)547 mapRegs_S390Instr(HRegRemap *m, s390_insn *insn, Bool mode64)
548 {
549 s390_insn_map_regs(m, insn);
550 }
551
552
553 /* Generate s390 spill/reload instructions under the direction of the
554 register allocator. Note it's critical these don't write the
555 condition codes. This is like an Ist_Put */
556 void
genSpill_S390(HInstr ** i1,HInstr ** i2,HReg rreg,Int offsetB,Bool mode64)557 genSpill_S390(HInstr **i1, HInstr **i2, HReg rreg, Int offsetB, Bool mode64)
558 {
559 s390_amode *am;
560
561 vassert(offsetB >= 0);
562 vassert(!hregIsVirtual(rreg));
563
564 *i1 = *i2 = NULL;
565
566 am = s390_amode_for_guest_state(offsetB);
567
568 switch (hregClass(rreg)) {
569 case HRcInt64:
570 case HRcFlt64:
571 *i1 = s390_insn_store(8, am, rreg);
572 return;
573 case HRcVec128:
574 *i1 = s390_insn_store(16, am, rreg);
575 return;
576 default:
577 ppHRegClass(hregClass(rreg));
578 vpanic("genSpill_S390: unimplemented regclass");
579 }
580 }
581
582
583 /* This is like an Iex_Get */
584 void
genReload_S390(HInstr ** i1,HInstr ** i2,HReg rreg,Int offsetB,Bool mode64)585 genReload_S390(HInstr **i1, HInstr **i2, HReg rreg, Int offsetB, Bool mode64)
586 {
587 s390_amode *am;
588
589 vassert(offsetB >= 0);
590 vassert(!hregIsVirtual(rreg));
591
592 *i1 = *i2 = NULL;
593
594 am = s390_amode_for_guest_state(offsetB);
595
596 switch (hregClass(rreg)) {
597 case HRcInt64:
598 case HRcFlt64:
599 *i1 = s390_insn_load(8, rreg, am);
600 return;
601 case HRcVec128:
602 *i1 = s390_insn_load(16, rreg, am);
603 return;
604 default:
605 ppHRegClass(hregClass(rreg));
606 vpanic("genReload_S390: unimplemented regclass");
607 }
608 }
609
genMove_S390(HReg from,HReg to,Bool mode64)610 s390_insn* genMove_S390(HReg from, HReg to, Bool mode64)
611 {
612 switch (hregClass(from)) {
613 case HRcInt64:
614 return s390_insn_move(sizeofIRType(Ity_I64), to, from);
615 case HRcVec128:
616 return s390_insn_move(sizeofIRType(Ity_V128), to, from);
617 default:
618 ppHRegClass(hregClass(from));
619 vpanic("genMove_S390: unimplemented regclass");
620 }
621 }
622
623 /* Helper function for s390_insn_get_reg_usage */
624 static void
s390_opnd_RMI_get_reg_usage(HRegUsage * u,s390_opnd_RMI op)625 s390_opnd_RMI_get_reg_usage(HRegUsage *u, s390_opnd_RMI op)
626 {
627 switch (op.tag) {
628 case S390_OPND_REG:
629 addHRegUse(u, HRmRead, op.variant.reg);
630 break;
631
632 case S390_OPND_AMODE:
633 s390_amode_get_reg_usage(u, op.variant.am);
634 break;
635
636 case S390_OPND_IMMEDIATE:
637 break;
638
639 default:
640 vpanic("s390_opnd_RMI_get_reg_usage");
641 }
642 }
643
644
645 /* Tell the register allocator how the given insn uses the registers */
646 static void
s390_insn_get_reg_usage(HRegUsage * u,const s390_insn * insn)647 s390_insn_get_reg_usage(HRegUsage *u, const s390_insn *insn)
648 {
649 initHRegUsage(u);
650
651 switch (insn->tag) {
652 case S390_INSN_LOAD:
653 addHRegUse(u, HRmWrite, insn->variant.load.dst);
654 s390_amode_get_reg_usage(u, insn->variant.load.src);
655 break;
656
657 case S390_INSN_LOAD_IMMEDIATE:
658 addHRegUse(u, HRmWrite, insn->variant.load_immediate.dst);
659 break;
660
661 case S390_INSN_STORE:
662 addHRegUse(u, HRmRead, insn->variant.store.src);
663 s390_amode_get_reg_usage(u, insn->variant.store.dst);
664 break;
665
666 case S390_INSN_MOVE:
667 addHRegUse(u, HRmRead, insn->variant.move.src);
668 addHRegUse(u, HRmWrite, insn->variant.move.dst);
669
670 if (hregClass(insn->variant.move.src) == hregClass(insn->variant.move.dst)) {
671 u->isRegRegMove = True;
672 u->regMoveSrc = insn->variant.move.src;
673 u->regMoveDst = insn->variant.move.dst;
674 }
675 break;
676
677 case S390_INSN_MEMCPY:
678 s390_amode_get_reg_usage(u, insn->variant.memcpy.src);
679 s390_amode_get_reg_usage(u, insn->variant.memcpy.dst);
680 break;
681
682 case S390_INSN_COND_MOVE:
683 s390_opnd_RMI_get_reg_usage(u, insn->variant.cond_move.src);
684 addHRegUse(u, HRmWrite, insn->variant.cond_move.dst);
685 break;
686
687 case S390_INSN_ALU:
688 addHRegUse(u, HRmWrite, insn->variant.alu.dst);
689 addHRegUse(u, HRmRead, insn->variant.alu.dst); /* op1 */
690 s390_opnd_RMI_get_reg_usage(u, insn->variant.alu.op2);
691 break;
692
693 case S390_INSN_SMUL:
694 case S390_INSN_UMUL:
695 addHRegUse(u, HRmRead, insn->variant.mul.dst_lo); /* op1 */
696 addHRegUse(u, HRmWrite, insn->variant.mul.dst_lo);
697 addHRegUse(u, HRmWrite, insn->variant.mul.dst_hi);
698 s390_opnd_RMI_get_reg_usage(u, insn->variant.mul.op2);
699 break;
700
701 case S390_INSN_SDIV:
702 case S390_INSN_UDIV:
703 addHRegUse(u, HRmRead, insn->variant.div.op1_lo);
704 addHRegUse(u, HRmRead, insn->variant.div.op1_hi);
705 addHRegUse(u, HRmWrite, insn->variant.div.op1_lo);
706 addHRegUse(u, HRmWrite, insn->variant.div.op1_hi);
707 s390_opnd_RMI_get_reg_usage(u, insn->variant.div.op2);
708 break;
709
710 case S390_INSN_DIVS:
711 addHRegUse(u, HRmRead, insn->variant.divs.op1);
712 addHRegUse(u, HRmWrite, insn->variant.divs.op1); /* quotient */
713 addHRegUse(u, HRmWrite, insn->variant.divs.rem); /* remainder */
714 s390_opnd_RMI_get_reg_usage(u, insn->variant.divs.op2);
715 break;
716
717 case S390_INSN_CLZ:
718 addHRegUse(u, HRmWrite, insn->variant.clz.num_bits);
719 addHRegUse(u, HRmWrite, insn->variant.clz.clobber);
720 s390_opnd_RMI_get_reg_usage(u, insn->variant.clz.src);
721 break;
722
723 case S390_INSN_UNOP:
724 addHRegUse(u, HRmWrite, insn->variant.unop.dst);
725 s390_opnd_RMI_get_reg_usage(u, insn->variant.unop.src);
726 break;
727
728 case S390_INSN_TEST:
729 s390_opnd_RMI_get_reg_usage(u, insn->variant.test.src);
730 break;
731
732 case S390_INSN_CC2BOOL:
733 addHRegUse(u, HRmWrite, insn->variant.cc2bool.dst);
734 break;
735
736 case S390_INSN_CAS:
737 addHRegUse(u, HRmRead, insn->variant.cas.op1);
738 s390_amode_get_reg_usage(u, insn->variant.cas.op2);
739 addHRegUse(u, HRmRead, insn->variant.cas.op3);
740 addHRegUse(u, HRmWrite, insn->variant.cas.old_mem);
741 break;
742
743 case S390_INSN_CDAS: {
744 s390_cdas *cdas = insn->variant.cdas.details;
745
746 addHRegUse(u, HRmRead, cdas->op1_high);
747 addHRegUse(u, HRmRead, cdas->op1_low);
748 s390_amode_get_reg_usage(u, cdas->op2);
749 addHRegUse(u, HRmRead, cdas->op3_high);
750 addHRegUse(u, HRmRead, cdas->op3_low);
751 addHRegUse(u, HRmWrite, cdas->old_mem_high);
752 addHRegUse(u, HRmWrite, cdas->old_mem_low);
753 addHRegUse(u, HRmWrite, cdas->scratch);
754 break;
755 }
756
757 case S390_INSN_COMPARE:
758 addHRegUse(u, HRmRead, insn->variant.compare.src1);
759 s390_opnd_RMI_get_reg_usage(u, insn->variant.compare.src2);
760 break;
761
762 case S390_INSN_HELPER_CALL: {
763 UInt i;
764
765 /* Assume that all volatile registers are clobbered. ABI says,
766 volatile registers are: r0 - r5. Valgrind's register allocator
767 does not know about r0, so we can leave that out */
768 for (i = 1; i <= 5; ++i) {
769 addHRegUse(u, HRmWrite, s390_hreg_gpr(i));
770 }
771
772 /* Ditto for floating point registers. f0 - f7 are volatile */
773 for (i = 0; i <= 7; ++i) {
774 addHRegUse(u, HRmWrite, s390_hreg_fpr(i));
775 }
776
777 /* The registers that are used for passing arguments will be read.
778 Not all of them may, but in general we need to assume that. */
779 for (i = 0; i < insn->variant.helper_call.details->num_args; ++i) {
780 addHRegUse(u, HRmRead, s390_hreg_gpr(s390_gprno_from_arg_index(i)));
781 }
782
783 /* s390_insn_helper_call_emit also reads / writes the link register
784 and stack pointer. But those registers are not visible to the
785 register allocator. So we don't need to do anything for them. */
786 break;
787 }
788
789 case S390_INSN_BFP_TRIOP:
790 addHRegUse(u, HRmWrite, insn->variant.bfp_triop.dst);
791 addHRegUse(u, HRmRead, insn->variant.bfp_triop.dst); /* first */
792 addHRegUse(u, HRmRead, insn->variant.bfp_triop.op2); /* second */
793 addHRegUse(u, HRmRead, insn->variant.bfp_triop.op3); /* third */
794 break;
795
796 case S390_INSN_BFP_BINOP:
797 addHRegUse(u, HRmWrite, insn->variant.bfp_binop.dst_hi);
798 addHRegUse(u, HRmRead, insn->variant.bfp_binop.dst_hi); /* left */
799 addHRegUse(u, HRmRead, insn->variant.bfp_binop.op2_hi); /* right */
800 if (insn->size == 16) {
801 addHRegUse(u, HRmWrite, insn->variant.bfp_binop.dst_lo);
802 addHRegUse(u, HRmRead, insn->variant.bfp_binop.dst_lo); /* left */
803 addHRegUse(u, HRmRead, insn->variant.bfp_binop.op2_lo); /* right */
804 }
805 break;
806
807 case S390_INSN_BFP_UNOP:
808 addHRegUse(u, HRmWrite, insn->variant.bfp_unop.dst_hi);
809 addHRegUse(u, HRmRead, insn->variant.bfp_unop.op_hi); /* operand */
810 if (insn->size == 16) {
811 addHRegUse(u, HRmWrite, insn->variant.bfp_unop.dst_lo);
812 addHRegUse(u, HRmRead, insn->variant.bfp_unop.op_lo); /* operand */
813 }
814 break;
815
816 case S390_INSN_BFP_COMPARE:
817 addHRegUse(u, HRmWrite, insn->variant.bfp_compare.dst);
818 addHRegUse(u, HRmRead, insn->variant.bfp_compare.op1_hi); /* left */
819 addHRegUse(u, HRmRead, insn->variant.bfp_compare.op2_hi); /* right */
820 if (insn->size == 16) {
821 addHRegUse(u, HRmRead, insn->variant.bfp_compare.op1_lo); /* left */
822 addHRegUse(u, HRmRead, insn->variant.bfp_compare.op2_lo); /* right */
823 }
824 break;
825
826 case S390_INSN_BFP_CONVERT:
827 addHRegUse(u, HRmWrite, insn->variant.bfp_convert.dst_hi);
828 if (! hregIsInvalid(insn->variant.bfp_convert.dst_lo))
829 addHRegUse(u, HRmWrite, insn->variant.bfp_convert.dst_lo);
830 addHRegUse(u, HRmRead, insn->variant.bfp_convert.op_hi);
831 if (! hregIsInvalid(insn->variant.bfp_convert.op_lo))
832 addHRegUse(u, HRmRead, insn->variant.bfp_convert.op_lo);
833 break;
834
835 case S390_INSN_DFP_BINOP: {
836 s390_dfp_binop *dfp_binop = insn->variant.dfp_binop.details;
837
838 addHRegUse(u, HRmWrite, dfp_binop->dst_hi);
839 addHRegUse(u, HRmRead, dfp_binop->op2_hi); /* left */
840 addHRegUse(u, HRmRead, dfp_binop->op3_hi); /* right */
841 if (insn->size == 16) {
842 addHRegUse(u, HRmWrite, dfp_binop->dst_lo);
843 addHRegUse(u, HRmRead, dfp_binop->op2_lo); /* left */
844 addHRegUse(u, HRmRead, dfp_binop->op3_lo); /* right */
845 }
846 break;
847 }
848
849 case S390_INSN_DFP_UNOP:
850 addHRegUse(u, HRmWrite, insn->variant.dfp_unop.dst_hi);
851 addHRegUse(u, HRmRead, insn->variant.dfp_unop.op_hi); /* operand */
852 if (insn->size == 16) {
853 addHRegUse(u, HRmWrite, insn->variant.dfp_unop.dst_lo);
854 addHRegUse(u, HRmRead, insn->variant.dfp_unop.op_lo); /* operand */
855 }
856 break;
857
858 case S390_INSN_DFP_INTOP:
859 addHRegUse(u, HRmWrite, insn->variant.dfp_intop.dst_hi);
860 addHRegUse(u, HRmRead, insn->variant.dfp_intop.op2);
861 addHRegUse(u, HRmRead, insn->variant.dfp_intop.op3_hi);
862 if (insn->size == 16) {
863 addHRegUse(u, HRmWrite, insn->variant.dfp_intop.dst_lo);
864 addHRegUse(u, HRmRead, insn->variant.dfp_intop.op3_lo);
865 }
866 break;
867
868 case S390_INSN_DFP_COMPARE:
869 addHRegUse(u, HRmWrite, insn->variant.dfp_compare.dst);
870 addHRegUse(u, HRmRead, insn->variant.dfp_compare.op1_hi); /* left */
871 addHRegUse(u, HRmRead, insn->variant.dfp_compare.op2_hi); /* right */
872 if (insn->size == 16) {
873 addHRegUse(u, HRmRead, insn->variant.dfp_compare.op1_lo); /* left */
874 addHRegUse(u, HRmRead, insn->variant.dfp_compare.op2_lo); /* right */
875 }
876 break;
877
878 case S390_INSN_DFP_CONVERT:
879 addHRegUse(u, HRmWrite, insn->variant.dfp_convert.dst_hi);
880 if (! hregIsInvalid(insn->variant.dfp_convert.dst_lo))
881 addHRegUse(u, HRmWrite, insn->variant.dfp_convert.dst_lo);
882 addHRegUse(u, HRmRead, insn->variant.dfp_convert.op_hi); /* operand */
883 if (! hregIsInvalid(insn->variant.dfp_convert.op_lo))
884 addHRegUse(u, HRmRead, insn->variant.dfp_convert.op_lo); /* operand */
885 break;
886
887 case S390_INSN_DFP_REROUND:
888 addHRegUse(u, HRmWrite, insn->variant.dfp_reround.dst_hi);
889 addHRegUse(u, HRmRead, insn->variant.dfp_reround.op2); /* left */
890 addHRegUse(u, HRmRead, insn->variant.dfp_reround.op3_hi); /* right */
891 if (insn->size == 16) {
892 addHRegUse(u, HRmWrite, insn->variant.dfp_reround.dst_lo);
893 addHRegUse(u, HRmRead, insn->variant.dfp_reround.op3_lo); /* right */
894 }
895 break;
896
897 case S390_INSN_FP_CONVERT: {
898 s390_fp_convert *fp_convert = insn->variant.fp_convert.details;
899
900 addHRegUse(u, HRmWrite, fp_convert->dst_hi);
901 if (! hregIsInvalid(fp_convert->dst_lo))
902 addHRegUse(u, HRmWrite, fp_convert->dst_lo);
903 addHRegUse(u, HRmRead, fp_convert->op_hi);
904 if (! hregIsInvalid(fp_convert->op_lo))
905 addHRegUse(u, HRmRead, fp_convert->op_lo);
906 addHRegUse(u, HRmWrite, fp_convert->r1);
907 break;
908 }
909
910 case S390_INSN_MIMM:
911 s390_amode_get_reg_usage(u, insn->variant.mimm.dst);
912 break;
913
914 case S390_INSN_MADD:
915 s390_amode_get_reg_usage(u, insn->variant.madd.dst);
916 break;
917
918 case S390_INSN_MFENCE:
919 break;
920
921 case S390_INSN_SET_FPC_BFPRM:
922 addHRegUse(u, HRmRead, insn->variant.set_fpc_bfprm.mode);
923 break;
924
925 case S390_INSN_SET_FPC_DFPRM:
926 addHRegUse(u, HRmRead, insn->variant.set_fpc_dfprm.mode);
927 break;
928
929 case S390_INSN_EVCHECK:
930 s390_amode_get_reg_usage(u, insn->variant.evcheck.counter);
931 s390_amode_get_reg_usage(u, insn->variant.evcheck.fail_addr);
932 break;
933
934 case S390_INSN_PROFINC:
935 /* Does not use any register visible to the register allocator */
936 break;
937
938 case S390_INSN_XDIRECT:
939 s390_amode_get_reg_usage(u, insn->variant.xdirect.guest_IA);
940 break;
941
942 case S390_INSN_XINDIR:
943 addHRegUse(u, HRmRead, insn->variant.xindir.dst);
944 s390_amode_get_reg_usage(u, insn->variant.xindir.guest_IA);
945 break;
946
947 case S390_INSN_XASSISTED:
948 addHRegUse(u, HRmRead, insn->variant.xassisted.dst);
949 s390_amode_get_reg_usage(u, insn->variant.xassisted.guest_IA);
950 break;
951
952 case S390_INSN_VEC_AMODEOP:
953 addHRegUse(u, HRmWrite, insn->variant.vec_amodeop.dst);
954 addHRegUse(u, HRmRead, insn->variant.vec_amodeop.op1);
955 s390_amode_get_reg_usage(u, insn->variant.vec_amodeop.op2);
956 break;
957
958 case S390_INSN_VEC_AMODEINTOP:
959 addHRegUse(u, HRmRead, insn->variant.vec_amodeintop.dst);
960 addHRegUse(u, HRmWrite, insn->variant.vec_amodeintop.dst);
961 s390_amode_get_reg_usage(u, insn->variant.vec_amodeintop.op2);
962 addHRegUse(u, HRmRead, insn->variant.vec_amodeintop.op3);
963 break;
964
965 case S390_INSN_VEC_BINOP:
966 addHRegUse(u, HRmWrite, insn->variant.vec_binop.dst);
967 addHRegUse(u, HRmRead, insn->variant.vec_binop.op1);
968 addHRegUse(u, HRmRead, insn->variant.vec_binop.op2);
969 break;
970
971 case S390_INSN_VEC_TRIOP:
972 addHRegUse(u, HRmWrite, insn->variant.vec_triop.dst);
973 addHRegUse(u, HRmRead, insn->variant.vec_triop.op1);
974 addHRegUse(u, HRmRead, insn->variant.vec_triop.op2);
975 addHRegUse(u, HRmRead, insn->variant.vec_triop.op3);
976 break;
977
978 default:
979 vpanic("s390_insn_get_reg_usage");
980 }
981 }
982
983
984 /* Helper function for s390_insn_map_regs */
985 static void
s390_opnd_RMI_map_regs(HRegRemap * m,s390_opnd_RMI * op)986 s390_opnd_RMI_map_regs(HRegRemap *m, s390_opnd_RMI *op)
987 {
988 switch (op->tag) {
989 case S390_OPND_REG:
990 op->variant.reg = lookupHRegRemap(m, op->variant.reg);
991 break;
992
993 case S390_OPND_IMMEDIATE:
994 break;
995
996 case S390_OPND_AMODE:
997 s390_amode_map_regs(m, op->variant.am);
998 break;
999
1000 default:
1001 vpanic("s390_opnd_RMI_map_regs");
1002 }
1003 }
1004
1005
1006 static void
s390_insn_map_regs(HRegRemap * m,s390_insn * insn)1007 s390_insn_map_regs(HRegRemap *m, s390_insn *insn)
1008 {
1009 switch (insn->tag) {
1010 case S390_INSN_LOAD:
1011 insn->variant.load.dst = lookupHRegRemap(m, insn->variant.load.dst);
1012 s390_amode_map_regs(m, insn->variant.load.src);
1013 break;
1014
1015 case S390_INSN_STORE:
1016 s390_amode_map_regs(m, insn->variant.store.dst);
1017 insn->variant.store.src = lookupHRegRemap(m, insn->variant.store.src);
1018 break;
1019
1020 case S390_INSN_MOVE:
1021 insn->variant.move.dst = lookupHRegRemap(m, insn->variant.move.dst);
1022 insn->variant.move.src = lookupHRegRemap(m, insn->variant.move.src);
1023 break;
1024
1025 case S390_INSN_MEMCPY:
1026 s390_amode_map_regs(m, insn->variant.memcpy.dst);
1027 s390_amode_map_regs(m, insn->variant.memcpy.src);
1028 break;
1029
1030 case S390_INSN_COND_MOVE:
1031 insn->variant.cond_move.dst = lookupHRegRemap(m, insn->variant.cond_move.dst);
1032 s390_opnd_RMI_map_regs(m, &insn->variant.cond_move.src);
1033 break;
1034
1035 case S390_INSN_LOAD_IMMEDIATE:
1036 insn->variant.load_immediate.dst =
1037 lookupHRegRemap(m, insn->variant.load_immediate.dst);
1038 break;
1039
1040 case S390_INSN_ALU:
1041 insn->variant.alu.dst = lookupHRegRemap(m, insn->variant.alu.dst);
1042 s390_opnd_RMI_map_regs(m, &insn->variant.alu.op2);
1043 break;
1044
1045 case S390_INSN_SMUL:
1046 case S390_INSN_UMUL:
1047 insn->variant.mul.dst_hi = lookupHRegRemap(m, insn->variant.mul.dst_hi);
1048 insn->variant.mul.dst_lo = lookupHRegRemap(m, insn->variant.mul.dst_lo);
1049 s390_opnd_RMI_map_regs(m, &insn->variant.mul.op2);
1050 break;
1051
1052 case S390_INSN_SDIV:
1053 case S390_INSN_UDIV:
1054 insn->variant.div.op1_hi = lookupHRegRemap(m, insn->variant.div.op1_hi);
1055 insn->variant.div.op1_lo = lookupHRegRemap(m, insn->variant.div.op1_lo);
1056 s390_opnd_RMI_map_regs(m, &insn->variant.div.op2);
1057 break;
1058
1059 case S390_INSN_DIVS:
1060 insn->variant.divs.op1 = lookupHRegRemap(m, insn->variant.divs.op1);
1061 insn->variant.divs.rem = lookupHRegRemap(m, insn->variant.divs.rem);
1062 s390_opnd_RMI_map_regs(m, &insn->variant.divs.op2);
1063 break;
1064
1065 case S390_INSN_CLZ:
1066 insn->variant.clz.num_bits = lookupHRegRemap(m, insn->variant.clz.num_bits);
1067 insn->variant.clz.clobber = lookupHRegRemap(m, insn->variant.clz.clobber);
1068 s390_opnd_RMI_map_regs(m, &insn->variant.clz.src);
1069 break;
1070
1071 case S390_INSN_UNOP:
1072 insn->variant.unop.dst = lookupHRegRemap(m, insn->variant.unop.dst);
1073 s390_opnd_RMI_map_regs(m, &insn->variant.unop.src);
1074 break;
1075
1076 case S390_INSN_TEST:
1077 s390_opnd_RMI_map_regs(m, &insn->variant.test.src);
1078 break;
1079
1080 case S390_INSN_CC2BOOL:
1081 insn->variant.cc2bool.dst = lookupHRegRemap(m, insn->variant.cc2bool.dst);
1082 break;
1083
1084 case S390_INSN_CAS:
1085 insn->variant.cas.op1 = lookupHRegRemap(m, insn->variant.cas.op1);
1086 s390_amode_map_regs(m, insn->variant.cas.op2);
1087 insn->variant.cas.op3 = lookupHRegRemap(m, insn->variant.cas.op3);
1088 insn->variant.cas.old_mem = lookupHRegRemap(m, insn->variant.cas.old_mem);
1089 break;
1090
1091 case S390_INSN_CDAS: {
1092 s390_cdas *cdas = insn->variant.cdas.details;
1093
1094 cdas->op1_high = lookupHRegRemap(m, cdas->op1_high);
1095 cdas->op1_low = lookupHRegRemap(m, cdas->op1_low);
1096 s390_amode_map_regs(m, cdas->op2);
1097 cdas->op3_high = lookupHRegRemap(m, cdas->op3_high);
1098 cdas->op3_low = lookupHRegRemap(m, cdas->op3_low);
1099 cdas->old_mem_high = lookupHRegRemap(m, cdas->old_mem_high);
1100 cdas->old_mem_low = lookupHRegRemap(m, cdas->old_mem_low);
1101 cdas->scratch = lookupHRegRemap(m, cdas->scratch);
1102 break;
1103 }
1104
1105 case S390_INSN_COMPARE:
1106 insn->variant.compare.src1 = lookupHRegRemap(m, insn->variant.compare.src1);
1107 s390_opnd_RMI_map_regs(m, &insn->variant.compare.src2);
1108 break;
1109
1110 case S390_INSN_HELPER_CALL:
1111 /* s390_insn_helper_call_emit also reads / writes the link register
1112 and stack pointer. But those registers are not visible to the
1113 register allocator. So we don't need to do anything for them.
1114 As for the arguments of the helper call -- they will be loaded into
1115 non-virtual registers. Again, we don't need to do anything for those
1116 here. */
1117 break;
1118
1119 case S390_INSN_BFP_TRIOP:
1120 insn->variant.bfp_triop.dst =
1121 lookupHRegRemap(m, insn->variant.bfp_triop.dst);
1122 insn->variant.bfp_triop.op2 =
1123 lookupHRegRemap(m, insn->variant.bfp_triop.op2);
1124 insn->variant.bfp_triop.op3 =
1125 lookupHRegRemap(m, insn->variant.bfp_triop.op3);
1126 break;
1127
1128 case S390_INSN_BFP_BINOP:
1129 insn->variant.bfp_binop.dst_hi =
1130 lookupHRegRemap(m, insn->variant.bfp_binop.dst_hi);
1131 insn->variant.bfp_binop.op2_hi =
1132 lookupHRegRemap(m, insn->variant.bfp_binop.op2_hi);
1133 if (insn->size == 16) {
1134 insn->variant.bfp_binop.dst_lo =
1135 lookupHRegRemap(m, insn->variant.bfp_binop.dst_lo);
1136 insn->variant.bfp_binop.op2_lo =
1137 lookupHRegRemap(m, insn->variant.bfp_binop.op2_lo);
1138 }
1139 break;
1140
1141 case S390_INSN_BFP_UNOP:
1142 insn->variant.bfp_unop.dst_hi =
1143 lookupHRegRemap(m, insn->variant.bfp_unop.dst_hi);
1144 insn->variant.bfp_unop.op_hi =
1145 lookupHRegRemap(m, insn->variant.bfp_unop.op_hi);
1146 if (insn->size == 16) {
1147 insn->variant.bfp_unop.dst_lo =
1148 lookupHRegRemap(m, insn->variant.bfp_unop.dst_lo);
1149 insn->variant.bfp_unop.op_lo =
1150 lookupHRegRemap(m, insn->variant.bfp_unop.op_lo);
1151 }
1152 break;
1153
1154 case S390_INSN_BFP_COMPARE:
1155 insn->variant.bfp_compare.dst =
1156 lookupHRegRemap(m, insn->variant.bfp_compare.dst);
1157 insn->variant.bfp_compare.op1_hi =
1158 lookupHRegRemap(m, insn->variant.bfp_compare.op1_hi);
1159 insn->variant.bfp_compare.op2_hi =
1160 lookupHRegRemap(m, insn->variant.bfp_compare.op2_hi);
1161 if (insn->size == 16) {
1162 insn->variant.bfp_compare.op1_lo =
1163 lookupHRegRemap(m, insn->variant.bfp_compare.op1_lo);
1164 insn->variant.bfp_compare.op2_lo =
1165 lookupHRegRemap(m, insn->variant.bfp_compare.op2_lo);
1166 }
1167 break;
1168
1169 case S390_INSN_BFP_CONVERT:
1170 insn->variant.bfp_convert.dst_hi =
1171 lookupHRegRemap(m, insn->variant.bfp_convert.dst_hi);
1172 if (! hregIsInvalid(insn->variant.bfp_convert.dst_lo))
1173 insn->variant.bfp_convert.dst_lo =
1174 lookupHRegRemap(m, insn->variant.bfp_convert.dst_lo);
1175 insn->variant.bfp_convert.op_hi =
1176 lookupHRegRemap(m, insn->variant.bfp_convert.op_hi);
1177 if (! hregIsInvalid(insn->variant.bfp_convert.op_lo))
1178 insn->variant.bfp_convert.op_lo =
1179 lookupHRegRemap(m, insn->variant.bfp_convert.op_lo);
1180 break;
1181
1182 case S390_INSN_DFP_BINOP: {
1183 s390_dfp_binop *dfp_binop = insn->variant.dfp_binop.details;
1184
1185 dfp_binop->dst_hi = lookupHRegRemap(m, dfp_binop->dst_hi);
1186 dfp_binop->op2_hi = lookupHRegRemap(m, dfp_binop->op2_hi);
1187 dfp_binop->op3_hi = lookupHRegRemap(m, dfp_binop->op3_hi);
1188 if (insn->size == 16) {
1189 dfp_binop->dst_lo = lookupHRegRemap(m, dfp_binop->dst_lo);
1190 dfp_binop->op2_lo = lookupHRegRemap(m, dfp_binop->op2_lo);
1191 dfp_binop->op3_lo = lookupHRegRemap(m, dfp_binop->op3_lo);
1192 }
1193 break;
1194 }
1195
1196 case S390_INSN_DFP_UNOP:
1197 insn->variant.dfp_unop.dst_hi =
1198 lookupHRegRemap(m, insn->variant.dfp_unop.dst_hi);
1199 insn->variant.dfp_unop.op_hi =
1200 lookupHRegRemap(m, insn->variant.dfp_unop.op_hi);
1201 if (insn->size == 16) {
1202 insn->variant.dfp_unop.dst_lo =
1203 lookupHRegRemap(m, insn->variant.dfp_unop.dst_lo);
1204 insn->variant.dfp_unop.op_lo =
1205 lookupHRegRemap(m, insn->variant.dfp_unop.op_lo);
1206 }
1207 break;
1208
1209 case S390_INSN_DFP_INTOP:
1210 insn->variant.dfp_intop.dst_hi =
1211 lookupHRegRemap(m, insn->variant.dfp_intop.dst_hi);
1212 insn->variant.dfp_intop.op2 =
1213 lookupHRegRemap(m, insn->variant.dfp_intop.op2);
1214 insn->variant.dfp_intop.op3_hi =
1215 lookupHRegRemap(m, insn->variant.dfp_intop.op3_hi);
1216 if (insn->size == 16) {
1217 insn->variant.dfp_intop.dst_lo =
1218 lookupHRegRemap(m, insn->variant.dfp_intop.dst_lo);
1219 insn->variant.dfp_intop.op3_lo =
1220 lookupHRegRemap(m, insn->variant.dfp_intop.op3_lo);
1221 }
1222 break;
1223
1224 case S390_INSN_DFP_COMPARE:
1225 insn->variant.dfp_compare.dst =
1226 lookupHRegRemap(m, insn->variant.dfp_compare.dst);
1227 insn->variant.dfp_compare.op1_hi =
1228 lookupHRegRemap(m, insn->variant.dfp_compare.op1_hi);
1229 insn->variant.dfp_compare.op2_hi =
1230 lookupHRegRemap(m, insn->variant.dfp_compare.op2_hi);
1231 if (insn->size == 16) {
1232 insn->variant.dfp_compare.op1_lo =
1233 lookupHRegRemap(m, insn->variant.dfp_compare.op1_lo);
1234 insn->variant.dfp_compare.op2_lo =
1235 lookupHRegRemap(m, insn->variant.dfp_compare.op2_lo);
1236 }
1237 break;
1238
1239 case S390_INSN_DFP_CONVERT:
1240 insn->variant.dfp_convert.dst_hi =
1241 lookupHRegRemap(m, insn->variant.dfp_convert.dst_hi);
1242 if (! hregIsInvalid(insn->variant.dfp_convert.dst_lo))
1243 insn->variant.dfp_convert.dst_lo =
1244 lookupHRegRemap(m, insn->variant.dfp_convert.dst_lo);
1245 insn->variant.dfp_convert.op_hi =
1246 lookupHRegRemap(m, insn->variant.dfp_convert.op_hi);
1247 if (! hregIsInvalid(insn->variant.dfp_convert.op_lo))
1248 insn->variant.dfp_convert.op_lo =
1249 lookupHRegRemap(m, insn->variant.dfp_convert.op_lo);
1250 break;
1251
1252 case S390_INSN_DFP_REROUND:
1253 insn->variant.dfp_reround.dst_hi =
1254 lookupHRegRemap(m, insn->variant.dfp_reround.dst_hi);
1255 insn->variant.dfp_reround.op2 =
1256 lookupHRegRemap(m, insn->variant.dfp_reround.op2);
1257 insn->variant.dfp_reround.op3_hi =
1258 lookupHRegRemap(m, insn->variant.dfp_reround.op3_hi);
1259 if (insn->size == 16) {
1260 insn->variant.dfp_reround.dst_lo =
1261 lookupHRegRemap(m, insn->variant.dfp_reround.dst_lo);
1262 insn->variant.dfp_reround.op3_lo =
1263 lookupHRegRemap(m, insn->variant.dfp_reround.op3_lo);
1264 }
1265 break;
1266
1267 case S390_INSN_FP_CONVERT: {
1268 s390_fp_convert *fp_convert = insn->variant.fp_convert.details;
1269
1270 fp_convert->dst_hi = lookupHRegRemap(m, fp_convert->dst_hi);
1271 if (! hregIsInvalid(fp_convert->dst_lo))
1272 fp_convert->dst_lo = lookupHRegRemap(m, fp_convert->dst_lo);
1273 fp_convert->op_hi = lookupHRegRemap(m, fp_convert->op_hi);
1274 if (! hregIsInvalid(fp_convert->op_lo))
1275 fp_convert->op_lo = lookupHRegRemap(m, fp_convert->op_lo);
1276 fp_convert->r1 = lookupHRegRemap(m, fp_convert->r1);
1277 break;
1278 }
1279
1280 case S390_INSN_MIMM:
1281 s390_amode_map_regs(m, insn->variant.mimm.dst);
1282 break;
1283
1284 case S390_INSN_MADD:
1285 s390_amode_map_regs(m, insn->variant.madd.dst);
1286 break;
1287
1288 case S390_INSN_MFENCE:
1289 break;
1290
1291 case S390_INSN_SET_FPC_BFPRM:
1292 insn->variant.set_fpc_bfprm.mode =
1293 lookupHRegRemap(m, insn->variant.set_fpc_bfprm.mode);
1294 break;
1295
1296 case S390_INSN_SET_FPC_DFPRM:
1297 insn->variant.set_fpc_dfprm.mode =
1298 lookupHRegRemap(m, insn->variant.set_fpc_dfprm.mode);
1299 break;
1300
1301 case S390_INSN_EVCHECK:
1302 s390_amode_map_regs(m, insn->variant.evcheck.counter);
1303 s390_amode_map_regs(m, insn->variant.evcheck.fail_addr);
1304 break;
1305
1306 case S390_INSN_PROFINC:
1307 /* Does not use any register visible to the register allocator */
1308 break;
1309
1310 case S390_INSN_XDIRECT:
1311 s390_amode_map_regs(m, insn->variant.xdirect.guest_IA);
1312 break;
1313
1314 case S390_INSN_XINDIR:
1315 s390_amode_map_regs(m, insn->variant.xindir.guest_IA);
1316 insn->variant.xindir.dst =
1317 lookupHRegRemap(m, insn->variant.xindir.dst);
1318 break;
1319
1320 case S390_INSN_XASSISTED:
1321 s390_amode_map_regs(m, insn->variant.xassisted.guest_IA);
1322 insn->variant.xassisted.dst =
1323 lookupHRegRemap(m, insn->variant.xassisted.dst);
1324 break;
1325
1326 case S390_INSN_VEC_AMODEOP:
1327 insn->variant.vec_amodeop.dst =
1328 lookupHRegRemap(m, insn->variant.vec_amodeop.dst);
1329 insn->variant.vec_amodeop.op1 =
1330 lookupHRegRemap(m, insn->variant.vec_amodeop.op1);
1331 s390_amode_map_regs(m, insn->variant.vec_amodeop.op2);
1332 break;
1333
1334 case S390_INSN_VEC_AMODEINTOP:
1335 insn->variant.vec_amodeintop.dst =
1336 lookupHRegRemap(m, insn->variant.vec_amodeintop.dst);
1337 s390_amode_map_regs(m, insn->variant.vec_amodeintop.op2);
1338 insn->variant.vec_amodeintop.op3 =
1339 lookupHRegRemap(m, insn->variant.vec_amodeintop.op3);
1340 break;
1341
1342 case S390_INSN_VEC_BINOP:
1343 insn->variant.vec_binop.dst =
1344 lookupHRegRemap(m, insn->variant.vec_binop.dst);
1345 insn->variant.vec_binop.op1 =
1346 lookupHRegRemap(m, insn->variant.vec_binop.op1);
1347 insn->variant.vec_binop.op2 =
1348 lookupHRegRemap(m, insn->variant.vec_binop.op2);
1349 break;
1350
1351 case S390_INSN_VEC_TRIOP:
1352 insn->variant.vec_triop.dst =
1353 lookupHRegRemap(m, insn->variant.vec_triop.dst);
1354 insn->variant.vec_triop.op1 =
1355 lookupHRegRemap(m, insn->variant.vec_triop.op1);
1356 insn->variant.vec_triop.op2 =
1357 lookupHRegRemap(m, insn->variant.vec_triop.op2);
1358 insn->variant.vec_triop.op3 =
1359 lookupHRegRemap(m, insn->variant.vec_triop.op3);
1360 break;
1361 default:
1362 vpanic("s390_insn_map_regs");
1363 }
1364 }
1365
1366
1367 /*------------------------------------------------------------*/
1368 /*--- Functions to emit a sequence of bytes ---*/
1369 /*------------------------------------------------------------*/
1370
1371 static __inline__ UChar *
emit_2bytes(UChar * p,ULong val)1372 emit_2bytes(UChar *p, ULong val)
1373 {
1374 return (UChar *)__builtin_memcpy(p, ((UChar *)&val) + 6, 2) + 2;
1375 }
1376
1377
1378 static __inline__ UChar *
emit_4bytes(UChar * p,ULong val)1379 emit_4bytes(UChar *p, ULong val)
1380 {
1381 return (UChar *)__builtin_memcpy(p, ((UChar *)&val) + 4, 4) + 4;
1382 }
1383
1384
1385 static __inline__ UChar *
emit_6bytes(UChar * p,ULong val)1386 emit_6bytes(UChar *p, ULong val)
1387 {
1388 return (UChar *)__builtin_memcpy(p, ((UChar *)&val) + 2, 6) + 6;
1389 }
1390
1391
1392 /*------------------------------------------------------------*/
1393 /*--- Functions to emit various instruction formats ---*/
1394 /*------------------------------------------------------------*/
1395
1396 static UChar *
emit_RI(UChar * p,UInt op,UChar r1,UShort i2)1397 emit_RI(UChar *p, UInt op, UChar r1, UShort i2)
1398 {
1399 ULong the_insn = op;
1400
1401 the_insn |= ((ULong)r1) << 20;
1402 the_insn |= ((ULong)i2) << 0;
1403
1404 return emit_4bytes(p, the_insn);
1405 }
1406
1407
1408 static UChar *
emit_RIL(UChar * p,ULong op,UChar r1,UInt i2)1409 emit_RIL(UChar *p, ULong op, UChar r1, UInt i2)
1410 {
1411 ULong the_insn = op;
1412
1413 the_insn |= ((ULong)r1) << 36;
1414 the_insn |= ((ULong)i2) << 0;
1415
1416 return emit_6bytes(p, the_insn);
1417 }
1418
1419
1420 static UChar *
emit_RR(UChar * p,UInt op,UChar r1,UChar r2)1421 emit_RR(UChar *p, UInt op, UChar r1, UChar r2)
1422 {
1423 ULong the_insn = op;
1424
1425 the_insn |= ((ULong)r1) << 4;
1426 the_insn |= ((ULong)r2) << 0;
1427
1428 return emit_2bytes(p, the_insn);
1429 }
1430
1431
1432 static UChar *
emit_RRE(UChar * p,UInt op,UChar r1,UChar r2)1433 emit_RRE(UChar *p, UInt op, UChar r1, UChar r2)
1434 {
1435 ULong the_insn = op;
1436
1437 the_insn |= ((ULong)r1) << 4;
1438 the_insn |= ((ULong)r2) << 0;
1439
1440 return emit_4bytes(p, the_insn);
1441 }
1442
1443
1444 static UChar *
emit_RRF(UChar * p,UInt op,UChar r1,UChar r3,UChar r2)1445 emit_RRF(UChar *p, UInt op, UChar r1, UChar r3, UChar r2)
1446 {
1447 ULong the_insn = op;
1448
1449 the_insn |= ((ULong)r1) << 12;
1450 the_insn |= ((ULong)r3) << 4;
1451 the_insn |= ((ULong)r2) << 0;
1452
1453 return emit_4bytes(p, the_insn);
1454 }
1455
1456
1457 static UChar *
emit_RRF2(UChar * p,UInt op,UChar m3,UChar m4,UChar r1,UChar r2)1458 emit_RRF2(UChar *p, UInt op, UChar m3, UChar m4, UChar r1, UChar r2)
1459 {
1460 ULong the_insn = op;
1461
1462 the_insn |= ((ULong)m3) << 12;
1463 the_insn |= ((ULong)m4) << 8;
1464 the_insn |= ((ULong)r1) << 4;
1465 the_insn |= ((ULong)r2) << 0;
1466
1467 return emit_4bytes(p, the_insn);
1468 }
1469
1470
1471 static UChar *
emit_RRF3(UChar * p,UInt op,UChar r3,UChar r1,UChar r2)1472 emit_RRF3(UChar *p, UInt op, UChar r3, UChar r1, UChar r2)
1473 {
1474 ULong the_insn = op;
1475
1476 the_insn |= ((ULong)r3) << 12;
1477 the_insn |= ((ULong)r1) << 4;
1478 the_insn |= ((ULong)r2) << 0;
1479
1480 return emit_4bytes(p, the_insn);
1481 }
1482
1483
1484 static UChar *
emit_RRF4(UChar * p,UInt op,UChar r3,UChar m4,UChar r1,UChar r2)1485 emit_RRF4(UChar *p, UInt op, UChar r3, UChar m4, UChar r1, UChar r2)
1486 {
1487 ULong the_insn = op;
1488
1489 the_insn |= ((ULong)r3) << 12;
1490 the_insn |= ((ULong)m4) << 8;
1491 the_insn |= ((ULong)r1) << 4;
1492 the_insn |= ((ULong)r2) << 0;
1493
1494 return emit_4bytes(p, the_insn);
1495 }
1496
1497
1498 static UChar *
emit_RRF5(UChar * p,UInt op,UChar m4,UChar r1,UChar r2)1499 emit_RRF5(UChar *p, UInt op, UChar m4, UChar r1, UChar r2)
1500 {
1501 ULong the_insn = op;
1502
1503 the_insn |= ((ULong)m4) << 8;
1504 the_insn |= ((ULong)r1) << 4;
1505 the_insn |= ((ULong)r2) << 0;
1506
1507 return emit_4bytes(p, the_insn);
1508 }
1509
1510
1511 static UChar *
emit_RS(UChar * p,UInt op,UChar r1,UChar r3,UChar b2,UShort d2)1512 emit_RS(UChar *p, UInt op, UChar r1, UChar r3, UChar b2, UShort d2)
1513 {
1514 ULong the_insn = op;
1515
1516 the_insn |= ((ULong)r1) << 20;
1517 the_insn |= ((ULong)r3) << 16;
1518 the_insn |= ((ULong)b2) << 12;
1519 the_insn |= ((ULong)d2) << 0;
1520
1521 return emit_4bytes(p, the_insn);
1522 }
1523
1524
1525 static UChar *
emit_RSY(UChar * p,ULong op,UChar r1,UChar r3,UChar b2,UShort dl2,UChar dh2)1526 emit_RSY(UChar *p, ULong op, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
1527 {
1528 ULong the_insn = op;
1529
1530 the_insn |= ((ULong)r1) << 36;
1531 the_insn |= ((ULong)r3) << 32;
1532 the_insn |= ((ULong)b2) << 28;
1533 the_insn |= ((ULong)dl2) << 16;
1534 the_insn |= ((ULong)dh2) << 8;
1535
1536 return emit_6bytes(p, the_insn);
1537 }
1538
1539
1540 static UChar *
emit_RX(UChar * p,UInt op,UChar r1,UChar x2,UChar b2,UShort d2)1541 emit_RX(UChar *p, UInt op, UChar r1, UChar x2, UChar b2, UShort d2)
1542 {
1543 ULong the_insn = op;
1544
1545 the_insn |= ((ULong)r1) << 20;
1546 the_insn |= ((ULong)x2) << 16;
1547 the_insn |= ((ULong)b2) << 12;
1548 the_insn |= ((ULong)d2) << 0;
1549
1550 return emit_4bytes(p, the_insn);
1551 }
1552
1553
1554 static UChar *
emit_RXF(UChar * p,ULong op,UChar r3,UChar x2,UChar b2,UShort d2,UChar r1)1555 emit_RXF(UChar *p, ULong op, UChar r3, UChar x2, UChar b2, UShort d2, UChar r1)
1556 {
1557 ULong the_insn = op;
1558
1559 the_insn |= ((ULong)r3) << 36;
1560 the_insn |= ((ULong)x2) << 32;
1561 the_insn |= ((ULong)b2) << 28;
1562 the_insn |= ((ULong)d2) << 16;
1563 the_insn |= ((ULong)r1) << 12;
1564
1565 return emit_6bytes(p, the_insn);
1566 }
1567
1568
1569 static UChar *
emit_RXY(UChar * p,ULong op,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)1570 emit_RXY(UChar *p, ULong op, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1571 {
1572 ULong the_insn = op;
1573
1574 the_insn |= ((ULong)r1) << 36;
1575 the_insn |= ((ULong)x2) << 32;
1576 the_insn |= ((ULong)b2) << 28;
1577 the_insn |= ((ULong)dl2) << 16;
1578 the_insn |= ((ULong)dh2) << 8;
1579
1580 return emit_6bytes(p, the_insn);
1581 }
1582
1583
1584 static UChar *
emit_S(UChar * p,UInt op,UChar b2,UShort d2)1585 emit_S(UChar *p, UInt op, UChar b2, UShort d2)
1586 {
1587 ULong the_insn = op;
1588
1589 the_insn |= ((ULong)b2) << 12;
1590 the_insn |= ((ULong)d2) << 0;
1591
1592 return emit_4bytes(p, the_insn);
1593 }
1594
1595
1596 static UChar *
emit_SI(UChar * p,UInt op,UChar i2,UChar b1,UShort d1)1597 emit_SI(UChar *p, UInt op, UChar i2, UChar b1, UShort d1)
1598 {
1599 ULong the_insn = op;
1600
1601 the_insn |= ((ULong)i2) << 16;
1602 the_insn |= ((ULong)b1) << 12;
1603 the_insn |= ((ULong)d1) << 0;
1604
1605 return emit_4bytes(p, the_insn);
1606 }
1607
1608
1609 static UChar *
emit_SIL(UChar * p,ULong op,UChar b1,UShort d1,UShort i2)1610 emit_SIL(UChar *p, ULong op, UChar b1, UShort d1, UShort i2)
1611 {
1612 ULong the_insn = op;
1613
1614 the_insn |= ((ULong)b1) << 28;
1615 the_insn |= ((ULong)d1) << 16;
1616 the_insn |= ((ULong)i2) << 0;
1617
1618 return emit_6bytes(p, the_insn);
1619 }
1620
1621
1622 static UChar *
emit_SIY(UChar * p,ULong op,UChar i2,UChar b1,UShort dl1,UChar dh1)1623 emit_SIY(UChar *p, ULong op, UChar i2, UChar b1, UShort dl1, UChar dh1)
1624 {
1625 ULong the_insn = op;
1626
1627 the_insn |= ((ULong)i2) << 32;
1628 the_insn |= ((ULong)b1) << 28;
1629 the_insn |= ((ULong)dl1) << 16;
1630 the_insn |= ((ULong)dh1) << 8;
1631
1632 return emit_6bytes(p, the_insn);
1633 }
1634
1635
1636 static UChar *
emit_SSa(UChar * p,ULong op,UChar l,UChar b1,UShort d1,UChar b2,UShort d2)1637 emit_SSa(UChar *p, ULong op, UChar l, UChar b1, UShort d1, UChar b2, UShort d2)
1638 {
1639 ULong the_insn = op;
1640
1641 the_insn |= ((ULong)l) << 32;
1642 the_insn |= ((ULong)b1) << 28;
1643 the_insn |= ((ULong)d1) << 16;
1644 the_insn |= ((ULong)b2) << 12;
1645 the_insn |= ((ULong)d2) << 0;
1646
1647 return emit_6bytes(p, the_insn);
1648 }
1649
1650
1651 static UChar *
emit_VRI_VI(UChar * p,ULong op,UChar v1,UShort i2)1652 emit_VRI_VI(UChar *p, ULong op, UChar v1, UShort i2)
1653 {
1654 ULong the_insn = op;
1655 ULong rxb = s390_update_rxb(0, 1, &v1);
1656
1657 the_insn |= ((ULong)v1) << 36;
1658 the_insn |= ((ULong)i2) << 16;
1659 the_insn |= ((ULong)rxb)<< 8;
1660
1661 return emit_6bytes(p, the_insn);
1662 }
1663
1664
1665 static UChar *
emit_VRX(UChar * p,ULong op,UChar v1,UChar x2,UChar b2,UShort d2)1666 emit_VRX(UChar *p, ULong op, UChar v1, UChar x2, UChar b2, UShort d2)
1667 {
1668 ULong the_insn = op;
1669 ULong rxb = s390_update_rxb(0, 1, &v1);
1670
1671 the_insn |= ((ULong)v1) << 36;
1672 the_insn |= ((ULong)x2) << 32;
1673 the_insn |= ((ULong)b2) << 28;
1674 the_insn |= ((ULong)d2) << 16;
1675 the_insn |= ((ULong)rxb)<< 8;
1676
1677 return emit_6bytes(p, the_insn);
1678 }
1679
1680
1681 static UChar *
emit_VRS(UChar * p,ULong op,UChar reg1,UChar b2,UShort d2,UChar reg3,UChar m4)1682 emit_VRS(UChar *p, ULong op, UChar reg1, UChar b2, UShort d2, UChar reg3, UChar m4)
1683 {
1684 ULong the_insn = op;
1685 ULong rxb = s390_update_rxb(0, 1, ®1);
1686 rxb = s390_update_rxb(rxb, 2, ®3);
1687
1688 the_insn |= ((ULong)reg1) << 36;
1689 the_insn |= ((ULong)reg3) << 32;
1690 the_insn |= ((ULong)b2) << 28;
1691 the_insn |= ((ULong)d2) << 16;
1692 the_insn |= ((ULong)m4) << 12;
1693 the_insn |= ((ULong)rxb) << 8;
1694
1695 return emit_6bytes(p, the_insn);
1696 }
1697
1698
1699 static UChar *
emit_VRR_VVM(UChar * p,ULong op,UChar v1,UChar v2,UChar m4)1700 emit_VRR_VVM(UChar *p, ULong op, UChar v1, UChar v2, UChar m4)
1701 {
1702 ULong the_insn = op;
1703 ULong rxb = s390_update_rxb(0, 1, &v1);
1704 rxb = s390_update_rxb(rxb, 2, &v2);
1705
1706 the_insn |= ((ULong)v1) << 36;
1707 the_insn |= ((ULong)v2) << 32;
1708 the_insn |= ((ULong)m4) << 12;
1709 the_insn |= ((ULong)rxb)<< 8;
1710
1711 return emit_6bytes(p, the_insn);
1712 }
1713
1714 static UChar *
emit_VRR_VVMMM(UChar * p,ULong op,UChar v1,UChar v2,UChar m3,UChar m4,UChar m5)1715 emit_VRR_VVMMM(UChar *p, ULong op, UChar v1, UChar v2, UChar m3, UChar m4,
1716 UChar m5)
1717 {
1718 ULong the_insn = op;
1719 ULong rxb = s390_update_rxb(0, 1, &v1);
1720 rxb = s390_update_rxb(rxb, 2, &v2);
1721
1722 the_insn |= ((ULong)v1) << 36;
1723 the_insn |= ((ULong)v2) << 32;
1724 the_insn |= ((ULong)m5) << 20;
1725 the_insn |= ((ULong)m4) << 16;
1726 the_insn |= ((ULong)m3) << 12;
1727 the_insn |= ((ULong)rxb) << 8;
1728
1729 return emit_6bytes(p, the_insn);
1730 }
1731
1732 static UChar *
emit_VRR_VVVM(UChar * p,ULong op,UChar v1,UChar v2,UChar v3,UChar m4)1733 emit_VRR_VVVM(UChar *p, ULong op, UChar v1, UChar v2, UChar v3, UChar m4)
1734 {
1735 ULong the_insn = op;
1736 ULong rxb = s390_update_rxb(0, 1, &v1);
1737 rxb = s390_update_rxb(rxb, 2, &v2);
1738 rxb = s390_update_rxb(rxb, 3, &v3);
1739
1740 the_insn |= ((ULong)v1) << 36;
1741 the_insn |= ((ULong)v2) << 32;
1742 the_insn |= ((ULong)v3) << 28;
1743 the_insn |= ((ULong)m4) << 12;
1744 the_insn |= ((ULong)rxb)<< 8;
1745
1746 return emit_6bytes(p, the_insn);
1747 }
1748
1749
1750 static UChar *
emit_VRR_VVV(UChar * p,ULong op,UChar v1,UChar v2,UChar v3)1751 emit_VRR_VVV(UChar *p, ULong op, UChar v1, UChar v2, UChar v3)
1752 {
1753 return emit_VRR_VVVM(p, op, v1, v2, v3, 0);
1754 }
1755
1756
1757 static UChar *
emit_VRR_VV(UChar * p,ULong op,UChar v1,UChar v2)1758 emit_VRR_VV(UChar *p, ULong op, UChar v1, UChar v2)
1759 {
1760 return emit_VRR_VVM(p, op, v1, v2, 0);
1761 }
1762
1763
1764 static UChar *
emit_VRR_VVVV(UChar * p,ULong op,UChar v1,UChar v2,UChar v3,UChar v4)1765 emit_VRR_VVVV(UChar *p, ULong op, UChar v1, UChar v2, UChar v3, UChar v4)
1766 {
1767 ULong the_insn = op;
1768 ULong rxb = s390_update_rxb(0, 1, &v1);
1769 rxb = s390_update_rxb(rxb, 2, &v2);
1770 rxb = s390_update_rxb(rxb, 3, &v3);
1771 rxb = s390_update_rxb(rxb, 4, &v4);
1772
1773 the_insn |= ((ULong)v1) << 36;
1774 the_insn |= ((ULong)v2) << 32;
1775 the_insn |= ((ULong)v3) << 28;
1776 the_insn |= ((ULong)v4) << 12;
1777 the_insn |= ((ULong)rxb)<< 8;
1778
1779 return emit_6bytes(p, the_insn);
1780 }
1781
1782 static UChar *
emit_VRRe_VVVVMM(UChar * p,ULong op,UChar v1,UChar v2,UChar v3,UChar v4,UChar m5,UChar m6)1783 emit_VRRe_VVVVMM(UChar *p, ULong op, UChar v1, UChar v2, UChar v3, UChar v4,
1784 UChar m5, UChar m6)
1785 {
1786 ULong the_insn = op;
1787 ULong rxb = s390_update_rxb(0, 1, &v1);
1788 rxb = s390_update_rxb(rxb, 2, &v2);
1789 rxb = s390_update_rxb(rxb, 3, &v3);
1790 rxb = s390_update_rxb(rxb, 4, &v4);
1791
1792 the_insn |= ((ULong)v1) << 36;
1793 the_insn |= ((ULong)v2) << 32;
1794 the_insn |= ((ULong)v3) << 28;
1795 the_insn |= ((ULong)m6) << 24;
1796 the_insn |= ((ULong)m5) << 16;
1797 the_insn |= ((ULong)v4) << 12;
1798 the_insn |= ((ULong)rxb) << 8;
1799
1800 return emit_6bytes(p, the_insn);
1801 }
1802
1803 static UChar *
emit_VRR_VRR(UChar * p,ULong op,UChar v1,UChar r2,UChar r3)1804 emit_VRR_VRR(UChar *p, ULong op, UChar v1, UChar r2, UChar r3)
1805 {
1806 ULong the_insn = op;
1807 ULong rxb = s390_update_rxb(0, 1, &v1);
1808
1809 the_insn |= ((ULong)v1) << 36;
1810 the_insn |= ((ULong)r2) << 32;
1811 the_insn |= ((ULong)r3) << 28;
1812 the_insn |= ((ULong)rxb)<< 8;
1813
1814 return emit_6bytes(p, the_insn);
1815 }
1816
1817 static UChar *
emit_VRR_VVVMMM(UChar * p,ULong op,UChar v1,UChar v2,UChar v3,UChar m4,UChar m5,UChar m6)1818 emit_VRR_VVVMMM(UChar *p, ULong op, UChar v1, UChar v2, UChar v3, UChar m4,
1819 UChar m5, UChar m6)
1820 {
1821 ULong the_insn = op;
1822 ULong rxb = s390_update_rxb(0, 1, &v1);
1823 rxb = s390_update_rxb(rxb, 2, &v2);
1824 rxb = s390_update_rxb(rxb, 3, &v3);
1825
1826 the_insn |= ((ULong)v1) << 36;
1827 the_insn |= ((ULong)v2) << 32;
1828 the_insn |= ((ULong)v3) << 28;
1829 the_insn |= ((ULong)m6) << 20;
1830 the_insn |= ((ULong)m5) << 16;
1831 the_insn |= ((ULong)m4) << 12;
1832 the_insn |= ((ULong)rxb) << 8;
1833
1834 return emit_6bytes(p, the_insn);
1835 }
1836
1837 static UChar*
emit_VRR_VVVMM(UChar * p,ULong op,UChar v1,UChar v2,UChar v3,UChar m4,UChar m5)1838 emit_VRR_VVVMM(UChar *p, ULong op, UChar v1, UChar v2, UChar v3, UChar m4,
1839 UChar m5)
1840 {
1841 return emit_VRR_VVVMMM(p, op, v1, v2, v3, m4, m5, 0);
1842 }
1843
1844 /*------------------------------------------------------------*/
1845 /*--- Functions to emit particular instructions ---*/
1846 /*------------------------------------------------------------*/
1847
1848 static UChar *
s390_emit_AR(UChar * p,UChar r1,UChar r2)1849 s390_emit_AR(UChar *p, UChar r1, UChar r2)
1850 {
1851 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1852 s390_disasm(ENC3(MNM, GPR, GPR), "ar", r1, r2);
1853
1854 return emit_RR(p, 0x1a00, r1, r2);
1855 }
1856
1857
1858 static UChar *
s390_emit_AGR(UChar * p,UChar r1,UChar r2)1859 s390_emit_AGR(UChar *p, UChar r1, UChar r2)
1860 {
1861 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1862 s390_disasm(ENC3(MNM, GPR, GPR), "agr", r1, r2);
1863
1864 return emit_RRE(p, 0xb9080000, r1, r2);
1865 }
1866
1867
1868 static UChar *
s390_emit_A(UChar * p,UChar r1,UChar x2,UChar b2,UShort d2)1869 s390_emit_A(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
1870 {
1871 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1872 s390_disasm(ENC3(MNM, GPR, UDXB), "a", r1, d2, x2, b2);
1873
1874 return emit_RX(p, 0x5a000000, r1, x2, b2, d2);
1875 }
1876
1877
1878 static UChar *
s390_emit_AY(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)1879 s390_emit_AY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1880 {
1881 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1882 s390_disasm(ENC3(MNM, GPR, SDXB), "ay", r1, dh2, dl2, x2, b2);
1883
1884 return emit_RXY(p, 0xe3000000005aULL, r1, x2, b2, dl2, dh2);
1885 }
1886
1887
1888 static UChar *
s390_emit_AG(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)1889 s390_emit_AG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1890 {
1891 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1892 s390_disasm(ENC3(MNM, GPR, SDXB), "ag", r1, dh2, dl2, x2, b2);
1893
1894 return emit_RXY(p, 0xe30000000008ULL, r1, x2, b2, dl2, dh2);
1895 }
1896
1897
1898 static UChar *
s390_emit_AFI(UChar * p,UChar r1,UInt i2)1899 s390_emit_AFI(UChar *p, UChar r1, UInt i2)
1900 {
1901 vassert(s390_host_has_eimm);
1902
1903 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1904 s390_disasm(ENC3(MNM, GPR, INT), "afi", r1, i2);
1905
1906 return emit_RIL(p, 0xc20900000000ULL, r1, i2);
1907 }
1908
1909
1910 static UChar *
s390_emit_AGFI(UChar * p,UChar r1,UInt i2)1911 s390_emit_AGFI(UChar *p, UChar r1, UInt i2)
1912 {
1913 vassert(s390_host_has_eimm);
1914
1915 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1916 s390_disasm(ENC3(MNM, GPR, INT), "agfi", r1, i2);
1917
1918 return emit_RIL(p, 0xc20800000000ULL, r1, i2);
1919 }
1920
1921
1922 static UChar *
s390_emit_AH(UChar * p,UChar r1,UChar x2,UChar b2,UShort d2)1923 s390_emit_AH(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
1924 {
1925 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1926 s390_disasm(ENC3(MNM, GPR, UDXB), "ah", r1, d2, x2, b2);
1927
1928 return emit_RX(p, 0x4a000000, r1, x2, b2, d2);
1929 }
1930
1931
1932 static UChar *
s390_emit_AHY(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)1933 s390_emit_AHY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1934 {
1935 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1936 s390_disasm(ENC3(MNM, GPR, SDXB), "ahy", r1, dh2, dl2, x2, b2);
1937
1938 return emit_RXY(p, 0xe3000000007aULL, r1, x2, b2, dl2, dh2);
1939 }
1940
1941
1942 static UChar *
s390_emit_AHI(UChar * p,UChar r1,UShort i2)1943 s390_emit_AHI(UChar *p, UChar r1, UShort i2)
1944 {
1945 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1946 s390_disasm(ENC3(MNM, GPR, INT), "ahi", r1, (Int)(Short)i2);
1947
1948 return emit_RI(p, 0xa70a0000, r1, i2);
1949 }
1950
1951
1952 static UChar *
s390_emit_AGHI(UChar * p,UChar r1,UShort i2)1953 s390_emit_AGHI(UChar *p, UChar r1, UShort i2)
1954 {
1955 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1956 s390_disasm(ENC3(MNM, GPR, INT), "aghi", r1, (Int)(Short)i2);
1957
1958 return emit_RI(p, 0xa70b0000, r1, i2);
1959 }
1960
1961
1962 static UChar *
s390_emit_AGSI(UChar * p,UChar i2,UChar b1,UShort dl1,UChar dh1)1963 s390_emit_AGSI(UChar *p, UChar i2, UChar b1, UShort dl1, UChar dh1)
1964 {
1965 vassert(s390_host_has_gie);
1966
1967 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1968 s390_disasm(ENC3(MNM, SDXB, INT), "agsi", dh1, dl1, 0, b1, (Int)(Char)i2);
1969
1970 return emit_SIY(p, 0xeb000000007aULL, i2, b1, dl1, dh1);
1971 }
1972
1973
1974 static UChar *
s390_emit_ASI(UChar * p,UChar i2,UChar b1,UShort dl1,UChar dh1)1975 s390_emit_ASI(UChar *p, UChar i2, UChar b1, UShort dl1, UChar dh1)
1976 {
1977 vassert(s390_host_has_gie);
1978
1979 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1980 s390_disasm(ENC3(MNM, SDXB, INT), "asi", dh1, dl1, 0, b1, (Int)(Char)i2);
1981
1982 return emit_SIY(p, 0xeb000000006aULL, i2, b1, dl1, dh1);
1983 }
1984
1985
1986 static UChar *
s390_emit_NR(UChar * p,UChar r1,UChar r2)1987 s390_emit_NR(UChar *p, UChar r1, UChar r2)
1988 {
1989 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1990 s390_disasm(ENC3(MNM, GPR, GPR), "nr", r1, r2);
1991
1992 return emit_RR(p, 0x1400, r1, r2);
1993 }
1994
1995
1996 static UChar *
s390_emit_NGR(UChar * p,UChar r1,UChar r2)1997 s390_emit_NGR(UChar *p, UChar r1, UChar r2)
1998 {
1999 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2000 s390_disasm(ENC3(MNM, GPR, GPR), "ngr", r1, r2);
2001
2002 return emit_RRE(p, 0xb9800000, r1, r2);
2003 }
2004
2005
2006 static UChar *
s390_emit_N(UChar * p,UChar r1,UChar x2,UChar b2,UShort d2)2007 s390_emit_N(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2008 {
2009 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2010 s390_disasm(ENC3(MNM, GPR, UDXB), "n", r1, d2, x2, b2);
2011
2012 return emit_RX(p, 0x54000000, r1, x2, b2, d2);
2013 }
2014
2015
2016 static UChar *
s390_emit_NY(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)2017 s390_emit_NY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2018 {
2019 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2020 s390_disasm(ENC3(MNM, GPR, SDXB), "ny", r1, dh2, dl2, x2, b2);
2021
2022 return emit_RXY(p, 0xe30000000054ULL, r1, x2, b2, dl2, dh2);
2023 }
2024
2025
2026 static UChar *
s390_emit_NG(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)2027 s390_emit_NG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2028 {
2029 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2030 s390_disasm(ENC3(MNM, GPR, SDXB), "ng", r1, dh2, dl2, x2, b2);
2031
2032 return emit_RXY(p, 0xe30000000080ULL, r1, x2, b2, dl2, dh2);
2033 }
2034
2035
2036 static UChar *
s390_emit_NIHF(UChar * p,UChar r1,UInt i2)2037 s390_emit_NIHF(UChar *p, UChar r1, UInt i2)
2038 {
2039 vassert(s390_host_has_eimm);
2040
2041 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2042 s390_disasm(ENC3(MNM, GPR, UINT), "nihf", r1, i2);
2043
2044 return emit_RIL(p, 0xc00a00000000ULL, r1, i2);
2045 }
2046
2047
2048 static UChar *
s390_emit_NILF(UChar * p,UChar r1,UInt i2)2049 s390_emit_NILF(UChar *p, UChar r1, UInt i2)
2050 {
2051 vassert(s390_host_has_eimm);
2052
2053 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2054 s390_disasm(ENC3(MNM, GPR, UINT), "nilf", r1, i2);
2055
2056 return emit_RIL(p, 0xc00b00000000ULL, r1, i2);
2057 }
2058
2059
2060 static UChar *
s390_emit_NILL(UChar * p,UChar r1,UShort i2)2061 s390_emit_NILL(UChar *p, UChar r1, UShort i2)
2062 {
2063 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2064 s390_disasm(ENC3(MNM, GPR, UINT), "nill", r1, i2);
2065
2066 return emit_RI(p, 0xa5070000, r1, i2);
2067 }
2068
2069
2070 static UChar *
s390_emit_BASR(UChar * p,UChar r1,UChar r2)2071 s390_emit_BASR(UChar *p, UChar r1, UChar r2)
2072 {
2073 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2074 s390_disasm(ENC3(MNM, GPR, GPR), "basr", r1, r2);
2075
2076 return emit_RR(p, 0x0d00, r1, r2);
2077 }
2078
2079
2080 static UChar *
s390_emit_BCR(UChar * p,UChar r1,UChar r2)2081 s390_emit_BCR(UChar *p, UChar r1, UChar r2)
2082 {
2083 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2084 s390_disasm(ENC2(XMNM, GPR), S390_XMNM_BCR, r1, r2);
2085
2086 return emit_RR(p, 0x0700, r1, r2);
2087 }
2088
2089
2090 static UChar *
s390_emit_BRC(UChar * p,UChar r1,UShort i2)2091 s390_emit_BRC(UChar *p, UChar r1, UShort i2)
2092 {
2093 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2094 s390_disasm(ENC2(XMNM, PCREL), S390_XMNM_BRC, r1, (Int)(Short)i2);
2095
2096 return emit_RI(p, 0xa7040000, r1, i2);
2097 }
2098
2099
2100 static UChar *
s390_emit_BRCL(UChar * p,UChar r1,ULong i2)2101 s390_emit_BRCL(UChar *p, UChar r1, ULong i2)
2102 {
2103 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2104 s390_disasm(ENC2(XMNM, PCREL), S390_XMNM_BRCL, r1, i2);
2105
2106 return emit_RIL(p, 0xc00400000000ULL, r1, i2);
2107 }
2108
2109
2110 static UChar *
s390_emit_CR(UChar * p,UChar r1,UChar r2)2111 s390_emit_CR(UChar *p, UChar r1, UChar r2)
2112 {
2113 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2114 s390_disasm(ENC3(MNM, GPR, GPR), "cr", r1, r2);
2115
2116 return emit_RR(p, 0x1900, r1, r2);
2117 }
2118
2119
2120 static UChar *
s390_emit_CGR(UChar * p,UChar r1,UChar r2)2121 s390_emit_CGR(UChar *p, UChar r1, UChar r2)
2122 {
2123 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2124 s390_disasm(ENC3(MNM, GPR, GPR), "cgr", r1, r2);
2125
2126 return emit_RRE(p, 0xb9200000, r1, r2);
2127 }
2128
2129
2130 static UChar *
s390_emit_C(UChar * p,UChar r1,UChar x2,UChar b2,UShort d2)2131 s390_emit_C(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2132 {
2133 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2134 s390_disasm(ENC3(MNM, GPR, UDXB), "c", r1, d2, x2, b2);
2135
2136 return emit_RX(p, 0x59000000, r1, x2, b2, d2);
2137 }
2138
2139
2140 static UChar *
s390_emit_CY(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)2141 s390_emit_CY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2142 {
2143 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2144 s390_disasm(ENC3(MNM, GPR, SDXB), "cy", r1, dh2, dl2, x2, b2);
2145
2146 return emit_RXY(p, 0xe30000000059ULL, r1, x2, b2, dl2, dh2);
2147 }
2148
2149
2150 static UChar *
s390_emit_CG(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)2151 s390_emit_CG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2152 {
2153 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2154 s390_disasm(ENC3(MNM, GPR, SDXB), "cg", r1, dh2, dl2, x2, b2);
2155
2156 return emit_RXY(p, 0xe30000000020ULL, r1, x2, b2, dl2, dh2);
2157 }
2158
2159
2160 static UChar *
s390_emit_CFI(UChar * p,UChar r1,UInt i2)2161 s390_emit_CFI(UChar *p, UChar r1, UInt i2)
2162 {
2163 vassert(s390_host_has_eimm);
2164
2165 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2166 s390_disasm(ENC3(MNM, GPR, INT), "cfi", r1, i2);
2167
2168 return emit_RIL(p, 0xc20d00000000ULL, r1, i2);
2169 }
2170
2171
2172 static UChar *
s390_emit_CGFI(UChar * p,UChar r1,UInt i2)2173 s390_emit_CGFI(UChar *p, UChar r1, UInt i2)
2174 {
2175 vassert(s390_host_has_eimm);
2176
2177 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2178 s390_disasm(ENC3(MNM, GPR, INT), "cgfi", r1, i2);
2179
2180 return emit_RIL(p, 0xc20c00000000ULL, r1, i2);
2181 }
2182
2183
2184 static UChar *
s390_emit_CS(UChar * p,UChar r1,UChar r3,UChar b2,UShort d2)2185 s390_emit_CS(UChar *p, UChar r1, UChar r3, UChar b2, UShort d2)
2186 {
2187 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2188 s390_disasm(ENC4(MNM, GPR, GPR, UDXB), "cs", r1, r3, d2, 0, b2);
2189
2190 return emit_RS(p, 0xba000000, r1, r3, b2, d2);
2191 }
2192
2193
2194 static UChar *
s390_emit_CSY(UChar * p,UChar r1,UChar r3,UChar b2,UShort dl2,UChar dh2)2195 s390_emit_CSY(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
2196 {
2197 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2198 s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "csy", r1, r3, dh2, dl2, 0, b2);
2199
2200 return emit_RSY(p, 0xeb0000000014ULL, r1, r3, b2, dl2, dh2);
2201 }
2202
2203
2204 static UChar *
s390_emit_CSG(UChar * p,UChar r1,UChar r3,UChar b2,UShort dl2,UChar dh2)2205 s390_emit_CSG(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
2206 {
2207 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2208 s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "csg", r1, r3, dh2, dl2, 0, b2);
2209
2210 return emit_RSY(p, 0xeb0000000030ULL, r1, r3, b2, dl2, dh2);
2211 }
2212
2213
2214 static UChar *
s390_emit_CDS(UChar * p,UChar r1,UChar r3,UChar b2,UShort d2)2215 s390_emit_CDS(UChar *p, UChar r1, UChar r3, UChar b2, UShort d2)
2216 {
2217 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2218 s390_disasm(ENC4(MNM, GPR, GPR, UDXB), "cds", r1, r3, d2, 0, b2);
2219
2220 return emit_RS(p, 0xbb000000, r1, r3, b2, d2);
2221 }
2222
2223
2224 static UChar *
s390_emit_CDSY(UChar * p,UChar r1,UChar r3,UChar b2,UShort dl2,UChar dh2)2225 s390_emit_CDSY(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
2226 {
2227 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2228 s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "cdsy", r1, r3, dh2, dl2, 0, b2);
2229
2230 return emit_RSY(p, 0xeb0000000031ULL, r1, r3, b2, dl2, dh2);
2231 }
2232
2233
2234 static UChar *
s390_emit_CDSG(UChar * p,UChar r1,UChar r3,UChar b2,UShort dl2,UChar dh2)2235 s390_emit_CDSG(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
2236 {
2237 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2238 s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "cdsg", r1, r3, dh2, dl2, 0, b2);
2239
2240 return emit_RSY(p, 0xeb000000003eULL, r1, r3, b2, dl2, dh2);
2241 }
2242
2243
2244 static UChar *
s390_emit_CLR(UChar * p,UChar r1,UChar r2)2245 s390_emit_CLR(UChar *p, UChar r1, UChar r2)
2246 {
2247 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2248 s390_disasm(ENC3(MNM, GPR, GPR), "clr", r1, r2);
2249
2250 return emit_RR(p, 0x1500, r1, r2);
2251 }
2252
2253
2254 static UChar *
s390_emit_CLGR(UChar * p,UChar r1,UChar r2)2255 s390_emit_CLGR(UChar *p, UChar r1, UChar r2)
2256 {
2257 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2258 s390_disasm(ENC3(MNM, GPR, GPR), "clgr", r1, r2);
2259
2260 return emit_RRE(p, 0xb9210000, r1, r2);
2261 }
2262
2263
2264 static UChar *
s390_emit_CL(UChar * p,UChar r1,UChar x2,UChar b2,UShort d2)2265 s390_emit_CL(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2266 {
2267 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2268 s390_disasm(ENC3(MNM, GPR, UDXB), "cl", r1, d2, x2, b2);
2269
2270 return emit_RX(p, 0x55000000, r1, x2, b2, d2);
2271 }
2272
2273
2274 static UChar *
s390_emit_CLY(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)2275 s390_emit_CLY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2276 {
2277 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2278 s390_disasm(ENC3(MNM, GPR, SDXB), "cly", r1, dh2, dl2, x2, b2);
2279
2280 return emit_RXY(p, 0xe30000000055ULL, r1, x2, b2, dl2, dh2);
2281 }
2282
2283
2284 static UChar *
s390_emit_CLG(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)2285 s390_emit_CLG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2286 {
2287 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2288 s390_disasm(ENC3(MNM, GPR, SDXB), "clg", r1, dh2, dl2, x2, b2);
2289
2290 return emit_RXY(p, 0xe30000000021ULL, r1, x2, b2, dl2, dh2);
2291 }
2292
2293
2294 static UChar *
s390_emit_CLFI(UChar * p,UChar r1,UInt i2)2295 s390_emit_CLFI(UChar *p, UChar r1, UInt i2)
2296 {
2297 vassert(s390_host_has_eimm);
2298
2299 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2300 s390_disasm(ENC3(MNM, GPR, UINT), "clfi", r1, i2);
2301
2302 return emit_RIL(p, 0xc20f00000000ULL, r1, i2);
2303 }
2304
2305
2306 static UChar *
s390_emit_CLGFI(UChar * p,UChar r1,UInt i2)2307 s390_emit_CLGFI(UChar *p, UChar r1, UInt i2)
2308 {
2309 vassert(s390_host_has_eimm);
2310
2311 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2312 s390_disasm(ENC3(MNM, GPR, UINT), "clgfi", r1, i2);
2313
2314 return emit_RIL(p, 0xc20e00000000ULL, r1, i2);
2315 }
2316
2317
2318 static UChar *
s390_emit_DR(UChar * p,UChar r1,UChar r2)2319 s390_emit_DR(UChar *p, UChar r1, UChar r2)
2320 {
2321 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2322 s390_disasm(ENC3(MNM, GPR, GPR), "dr", r1, r2);
2323
2324 return emit_RR(p, 0x1d00, r1, r2);
2325 }
2326
2327
2328 static UChar *
s390_emit_D(UChar * p,UChar r1,UChar x2,UChar b2,UShort d2)2329 s390_emit_D(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2330 {
2331 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2332 s390_disasm(ENC3(MNM, GPR, UDXB), "d", r1, d2, x2, b2);
2333
2334 return emit_RX(p, 0x5d000000, r1, x2, b2, d2);
2335 }
2336
2337
2338 static UChar *
s390_emit_DLR(UChar * p,UChar r1,UChar r2)2339 s390_emit_DLR(UChar *p, UChar r1, UChar r2)
2340 {
2341 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2342 s390_disasm(ENC3(MNM, GPR, GPR), "dlr", r1, r2);
2343
2344 return emit_RRE(p, 0xb9970000, r1, r2);
2345 }
2346
2347
2348 static UChar *
s390_emit_DLGR(UChar * p,UChar r1,UChar r2)2349 s390_emit_DLGR(UChar *p, UChar r1, UChar r2)
2350 {
2351 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2352 s390_disasm(ENC3(MNM, GPR, GPR), "dlgr", r1, r2);
2353
2354 return emit_RRE(p, 0xb9870000, r1, r2);
2355 }
2356
2357
2358 static UChar *
s390_emit_DL(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)2359 s390_emit_DL(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2360 {
2361 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2362 s390_disasm(ENC3(MNM, GPR, SDXB), "dl", r1, dh2, dl2, x2, b2);
2363
2364 return emit_RXY(p, 0xe30000000097ULL, r1, x2, b2, dl2, dh2);
2365 }
2366
2367
2368 static UChar *
s390_emit_DLG(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)2369 s390_emit_DLG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2370 {
2371 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2372 s390_disasm(ENC3(MNM, GPR, SDXB), "dlg", r1, dh2, dl2, x2, b2);
2373
2374 return emit_RXY(p, 0xe30000000087ULL, r1, x2, b2, dl2, dh2);
2375 }
2376
2377
2378 static UChar *
s390_emit_DSGR(UChar * p,UChar r1,UChar r2)2379 s390_emit_DSGR(UChar *p, UChar r1, UChar r2)
2380 {
2381 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2382 s390_disasm(ENC3(MNM, GPR, GPR), "dsgr", r1, r2);
2383
2384 return emit_RRE(p, 0xb90d0000, r1, r2);
2385 }
2386
2387
2388 static UChar *
s390_emit_DSG(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)2389 s390_emit_DSG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2390 {
2391 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2392 s390_disasm(ENC3(MNM, GPR, SDXB), "dsg", r1, dh2, dl2, x2, b2);
2393
2394 return emit_RXY(p, 0xe3000000000dULL, r1, x2, b2, dl2, dh2);
2395 }
2396
2397
2398 static UChar *
s390_emit_XR(UChar * p,UChar r1,UChar r2)2399 s390_emit_XR(UChar *p, UChar r1, UChar r2)
2400 {
2401 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2402 s390_disasm(ENC3(MNM, GPR, GPR), "xr", r1, r2);
2403
2404 return emit_RR(p, 0x1700, r1, r2);
2405 }
2406
2407
2408 static UChar *
s390_emit_XGR(UChar * p,UChar r1,UChar r2)2409 s390_emit_XGR(UChar *p, UChar r1, UChar r2)
2410 {
2411 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2412 s390_disasm(ENC3(MNM, GPR, GPR), "xgr", r1, r2);
2413
2414 return emit_RRE(p, 0xb9820000, r1, r2);
2415 }
2416
2417
2418 static UChar *
s390_emit_X(UChar * p,UChar r1,UChar x2,UChar b2,UShort d2)2419 s390_emit_X(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2420 {
2421 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2422 s390_disasm(ENC3(MNM, GPR, UDXB), "x", r1, d2, x2, b2);
2423
2424 return emit_RX(p, 0x57000000, r1, x2, b2, d2);
2425 }
2426
2427
2428 static UChar *
s390_emit_XY(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)2429 s390_emit_XY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2430 {
2431 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2432 s390_disasm(ENC3(MNM, GPR, SDXB), "xy", r1, dh2, dl2, x2, b2);
2433
2434 return emit_RXY(p, 0xe30000000057ULL, r1, x2, b2, dl2, dh2);
2435 }
2436
2437
2438 static UChar *
s390_emit_XG(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)2439 s390_emit_XG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2440 {
2441 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2442 s390_disasm(ENC3(MNM, GPR, SDXB), "xg", r1, dh2, dl2, x2, b2);
2443
2444 return emit_RXY(p, 0xe30000000082ULL, r1, x2, b2, dl2, dh2);
2445 }
2446
2447
2448 static UChar *
s390_emit_XIHF(UChar * p,UChar r1,UInt i2)2449 s390_emit_XIHF(UChar *p, UChar r1, UInt i2)
2450 {
2451 vassert(s390_host_has_eimm);
2452
2453 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2454 s390_disasm(ENC3(MNM, GPR, UINT), "xihf", r1, i2);
2455
2456 return emit_RIL(p, 0xc00600000000ULL, r1, i2);
2457 }
2458
2459
2460 static UChar *
s390_emit_XILF(UChar * p,UChar r1,UInt i2)2461 s390_emit_XILF(UChar *p, UChar r1, UInt i2)
2462 {
2463 vassert(s390_host_has_eimm);
2464
2465 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2466 s390_disasm(ENC3(MNM, GPR, UINT), "xilf", r1, i2);
2467
2468 return emit_RIL(p, 0xc00700000000ULL, r1, i2);
2469 }
2470
2471
2472 static UChar *
s390_emit_XC(UChar * p,UInt l,UChar b1,UShort d1,UChar b2,UShort d2)2473 s390_emit_XC(UChar *p, UInt l, UChar b1, UShort d1, UChar b2, UShort d2)
2474 {
2475 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2476 s390_disasm(ENC3(MNM, UDLB, UDXB), "xc", d1, l, b1, d2, 0, b2);
2477
2478 return emit_SSa(p, 0xd70000000000ULL, l, b1, d1, b2, d2);
2479 }
2480
2481
2482 static UChar *
s390_emit_FLOGR(UChar * p,UChar r1,UChar r2)2483 s390_emit_FLOGR(UChar *p, UChar r1, UChar r2)
2484 {
2485 vassert(s390_host_has_eimm);
2486
2487 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2488 s390_disasm(ENC3(MNM, GPR, GPR), "flogr", r1, r2);
2489
2490 return emit_RRE(p, 0xb9830000, r1, r2);
2491 }
2492
2493
2494 static UChar *
s390_emit_IC(UChar * p,UChar r1,UChar x2,UChar b2,UShort d2)2495 s390_emit_IC(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2496 {
2497 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2498 s390_disasm(ENC3(MNM, GPR, UDXB), "ic", r1, d2, x2, b2);
2499
2500 return emit_RX(p, 0x43000000, r1, x2, b2, d2);
2501 }
2502
2503
2504 static UChar *
s390_emit_ICY(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)2505 s390_emit_ICY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2506 {
2507 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2508 s390_disasm(ENC3(MNM, GPR, SDXB), "icy", r1, dh2, dl2, x2, b2);
2509
2510 return emit_RXY(p, 0xe30000000073ULL, r1, x2, b2, dl2, dh2);
2511 }
2512
2513
2514 static UChar *
s390_emit_IIHF(UChar * p,UChar r1,UInt i2)2515 s390_emit_IIHF(UChar *p, UChar r1, UInt i2)
2516 {
2517 vassert(s390_host_has_eimm);
2518
2519 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2520 s390_disasm(ENC3(MNM, GPR, UINT), "iihf", r1, i2);
2521
2522 return emit_RIL(p, 0xc00800000000ULL, r1, i2);
2523 }
2524
2525
2526 static UChar *
s390_emit_IIHH(UChar * p,UChar r1,UShort i2)2527 s390_emit_IIHH(UChar *p, UChar r1, UShort i2)
2528 {
2529 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2530 s390_disasm(ENC3(MNM, GPR, UINT), "iihh", r1, i2);
2531
2532 return emit_RI(p, 0xa5000000, r1, i2);
2533 }
2534
2535
2536 static UChar *
s390_emit_IIHL(UChar * p,UChar r1,UShort i2)2537 s390_emit_IIHL(UChar *p, UChar r1, UShort i2)
2538 {
2539 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2540 s390_disasm(ENC3(MNM, GPR, UINT), "iihl", r1, i2);
2541
2542 return emit_RI(p, 0xa5010000, r1, i2);
2543 }
2544
2545
2546 static UChar *
s390_emit_IILF(UChar * p,UChar r1,UInt i2)2547 s390_emit_IILF(UChar *p, UChar r1, UInt i2)
2548 {
2549 vassert(s390_host_has_eimm);
2550
2551 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2552 s390_disasm(ENC3(MNM, GPR, UINT), "iilf", r1, i2);
2553
2554 return emit_RIL(p, 0xc00900000000ULL, r1, i2);
2555 }
2556
2557
2558 static UChar *
s390_emit_IILH(UChar * p,UChar r1,UShort i2)2559 s390_emit_IILH(UChar *p, UChar r1, UShort i2)
2560 {
2561 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2562 s390_disasm(ENC3(MNM, GPR, UINT), "iilh", r1, i2);
2563
2564 return emit_RI(p, 0xa5020000, r1, i2);
2565 }
2566
2567
2568 static UChar *
s390_emit_IILL(UChar * p,UChar r1,UShort i2)2569 s390_emit_IILL(UChar *p, UChar r1, UShort i2)
2570 {
2571 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2572 s390_disasm(ENC3(MNM, GPR, UINT), "iill", r1, i2);
2573
2574 return emit_RI(p, 0xa5030000, r1, i2);
2575 }
2576
2577
2578 static UChar *
s390_emit_IPM(UChar * p,UChar r1,UChar r2)2579 s390_emit_IPM(UChar *p, UChar r1, UChar r2)
2580 {
2581 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2582 s390_disasm(ENC2(MNM, GPR), "ipm", r1);
2583
2584 return emit_RRE(p, 0xb2220000, r1, r2);
2585 }
2586
2587
2588 static UChar *
s390_emit_LR(UChar * p,UChar r1,UChar r2)2589 s390_emit_LR(UChar *p, UChar r1, UChar r2)
2590 {
2591 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2592 s390_disasm(ENC3(MNM, GPR, GPR), "lr", r1, r2);
2593
2594 return emit_RR(p, 0x1800, r1, r2);
2595 }
2596
2597
2598 static UChar *
s390_emit_LGR(UChar * p,UChar r1,UChar r2)2599 s390_emit_LGR(UChar *p, UChar r1, UChar r2)
2600 {
2601 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2602 s390_disasm(ENC3(MNM, GPR, GPR), "lgr", r1, r2);
2603
2604 return emit_RRE(p, 0xb9040000, r1, r2);
2605 }
2606
2607
2608 static UChar *
s390_emit_LGFR(UChar * p,UChar r1,UChar r2)2609 s390_emit_LGFR(UChar *p, UChar r1, UChar r2)
2610 {
2611 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2612 s390_disasm(ENC3(MNM, GPR, GPR), "lgfr", r1, r2);
2613
2614 return emit_RRE(p, 0xb9140000, r1, r2);
2615 }
2616
2617
2618 static UChar *
s390_emit_L(UChar * p,UChar r1,UChar x2,UChar b2,UShort d2)2619 s390_emit_L(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2620 {
2621 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2622 s390_disasm(ENC3(MNM, GPR, UDXB), "l", r1, d2, x2, b2);
2623
2624 return emit_RX(p, 0x58000000, r1, x2, b2, d2);
2625 }
2626
2627
2628 static UChar *
s390_emit_LY(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)2629 s390_emit_LY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2630 {
2631 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2632 s390_disasm(ENC3(MNM, GPR, SDXB), "ly", r1, dh2, dl2, x2, b2);
2633
2634 return emit_RXY(p, 0xe30000000058ULL, r1, x2, b2, dl2, dh2);
2635 }
2636
2637
2638 static UChar *
s390_emit_LG(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)2639 s390_emit_LG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2640 {
2641 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2642 s390_disasm(ENC3(MNM, GPR, SDXB), "lg", r1, dh2, dl2, x2, b2);
2643
2644 return emit_RXY(p, 0xe30000000004ULL, r1, x2, b2, dl2, dh2);
2645 }
2646
2647
2648 static UChar *
s390_emit_LGF(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)2649 s390_emit_LGF(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2650 {
2651 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2652 s390_disasm(ENC3(MNM, GPR, SDXB), "lgf", r1, dh2, dl2, x2, b2);
2653
2654 return emit_RXY(p, 0xe30000000014ULL, r1, x2, b2, dl2, dh2);
2655 }
2656
2657
2658 static UChar *
s390_emit_LGFI(UChar * p,UChar r1,UInt i2)2659 s390_emit_LGFI(UChar *p, UChar r1, UInt i2)
2660 {
2661 vassert(s390_host_has_eimm);
2662
2663 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2664 s390_disasm(ENC3(MNM, GPR, INT), "lgfi", r1, i2);
2665
2666 return emit_RIL(p, 0xc00100000000ULL, r1, i2);
2667 }
2668
2669
2670 static UChar *
s390_emit_LTR(UChar * p,UChar r1,UChar r2)2671 s390_emit_LTR(UChar *p, UChar r1, UChar r2)
2672 {
2673 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2674 s390_disasm(ENC3(MNM, GPR, GPR), "ltr", r1, r2);
2675
2676 return emit_RR(p, 0x1200, r1, r2);
2677 }
2678
2679
2680 static UChar *
s390_emit_LTGR(UChar * p,UChar r1,UChar r2)2681 s390_emit_LTGR(UChar *p, UChar r1, UChar r2)
2682 {
2683 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2684 s390_disasm(ENC3(MNM, GPR, GPR), "ltgr", r1, r2);
2685
2686 return emit_RRE(p, 0xb9020000, r1, r2);
2687 }
2688
2689
2690 static UChar *
s390_emit_LT(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)2691 s390_emit_LT(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2692 {
2693 vassert(s390_host_has_eimm);
2694
2695 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2696 s390_disasm(ENC3(MNM, GPR, SDXB), "lt", r1, dh2, dl2, x2, b2);
2697
2698 return emit_RXY(p, 0xe30000000012ULL, r1, x2, b2, dl2, dh2);
2699 }
2700
2701
2702 static UChar *
s390_emit_LTG(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)2703 s390_emit_LTG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2704 {
2705 vassert(s390_host_has_eimm);
2706
2707 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2708 s390_disasm(ENC3(MNM, GPR, SDXB), "ltg", r1, dh2, dl2, x2, b2);
2709
2710 return emit_RXY(p, 0xe30000000002ULL, r1, x2, b2, dl2, dh2);
2711 }
2712
2713
2714 static UChar *
s390_emit_LBR(UChar * p,UChar r1,UChar r2)2715 s390_emit_LBR(UChar *p, UChar r1, UChar r2)
2716 {
2717 vassert(s390_host_has_eimm);
2718
2719 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2720 s390_disasm(ENC3(MNM, GPR, GPR), "lbr", r1, r2);
2721
2722 return emit_RRE(p, 0xb9260000, r1, r2);
2723 }
2724
2725
2726 static UChar *
s390_emit_LGBR(UChar * p,UChar r1,UChar r2)2727 s390_emit_LGBR(UChar *p, UChar r1, UChar r2)
2728 {
2729 vassert(s390_host_has_eimm);
2730
2731 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2732 s390_disasm(ENC3(MNM, GPR, GPR), "lgbr", r1, r2);
2733
2734 return emit_RRE(p, 0xb9060000, r1, r2);
2735 }
2736
2737
2738 static UChar *
s390_emit_LB(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)2739 s390_emit_LB(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2740 {
2741 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2742 s390_disasm(ENC3(MNM, GPR, SDXB), "lb", r1, dh2, dl2, x2, b2);
2743
2744 return emit_RXY(p, 0xe30000000076ULL, r1, x2, b2, dl2, dh2);
2745 }
2746
2747
2748 static UChar *
s390_emit_LGB(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)2749 s390_emit_LGB(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2750 {
2751 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2752 s390_disasm(ENC3(MNM, GPR, SDXB), "lgb", r1, dh2, dl2, x2, b2);
2753
2754 return emit_RXY(p, 0xe30000000077ULL, r1, x2, b2, dl2, dh2);
2755 }
2756
2757
2758 static UChar *
s390_emit_LCR(UChar * p,UChar r1,UChar r2)2759 s390_emit_LCR(UChar *p, UChar r1, UChar r2)
2760 {
2761 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2762 s390_disasm(ENC3(MNM, GPR, GPR), "lcr", r1, r2);
2763
2764 return emit_RR(p, 0x1300, r1, r2);
2765 }
2766
2767
2768 static UChar *
s390_emit_LCGR(UChar * p,UChar r1,UChar r2)2769 s390_emit_LCGR(UChar *p, UChar r1, UChar r2)
2770 {
2771 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2772 s390_disasm(ENC3(MNM, GPR, GPR), "lcgr", r1, r2);
2773
2774 return emit_RRE(p, 0xb9030000, r1, r2);
2775 }
2776
2777
2778 static UChar *
s390_emit_LHR(UChar * p,UChar r1,UChar r2)2779 s390_emit_LHR(UChar *p, UChar r1, UChar r2)
2780 {
2781 vassert(s390_host_has_eimm);
2782
2783 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2784 s390_disasm(ENC3(MNM, GPR, GPR), "lhr", r1, r2);
2785
2786 return emit_RRE(p, 0xb9270000, r1, r2);
2787 }
2788
2789
2790 static UChar *
s390_emit_LGHR(UChar * p,UChar r1,UChar r2)2791 s390_emit_LGHR(UChar *p, UChar r1, UChar r2)
2792 {
2793 vassert(s390_host_has_eimm);
2794
2795 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2796 s390_disasm(ENC3(MNM, GPR, GPR), "lghr", r1, r2);
2797
2798 return emit_RRE(p, 0xb9070000, r1, r2);
2799 }
2800
2801
2802 static UChar *
s390_emit_LH(UChar * p,UChar r1,UChar x2,UChar b2,UShort d2)2803 s390_emit_LH(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2804 {
2805 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2806 s390_disasm(ENC3(MNM, GPR, UDXB), "lh", r1, d2, x2, b2);
2807
2808 return emit_RX(p, 0x48000000, r1, x2, b2, d2);
2809 }
2810
2811
2812 static UChar *
s390_emit_LHY(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)2813 s390_emit_LHY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2814 {
2815 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2816 s390_disasm(ENC3(MNM, GPR, SDXB), "lhy", r1, dh2, dl2, x2, b2);
2817
2818 return emit_RXY(p, 0xe30000000078ULL, r1, x2, b2, dl2, dh2);
2819 }
2820
2821
2822 static UChar *
s390_emit_LGH(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)2823 s390_emit_LGH(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2824 {
2825 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2826 s390_disasm(ENC3(MNM, GPR, SDXB), "lgh", r1, dh2, dl2, x2, b2);
2827
2828 return emit_RXY(p, 0xe30000000015ULL, r1, x2, b2, dl2, dh2);
2829 }
2830
2831
2832 static UChar *
s390_emit_LHI(UChar * p,UChar r1,UShort i2)2833 s390_emit_LHI(UChar *p, UChar r1, UShort i2)
2834 {
2835 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2836 s390_disasm(ENC3(MNM, GPR, INT), "lhi", r1, (Int)(Short)i2);
2837
2838 return emit_RI(p, 0xa7080000, r1, i2);
2839 }
2840
2841
2842 static UChar *
s390_emit_LGHI(UChar * p,UChar r1,UShort i2)2843 s390_emit_LGHI(UChar *p, UChar r1, UShort i2)
2844 {
2845 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2846 s390_disasm(ENC3(MNM, GPR, INT), "lghi", r1, (Int)(Short)i2);
2847
2848 return emit_RI(p, 0xa7090000, r1, i2);
2849 }
2850
2851
2852 static UChar *
s390_emit_LLGFR(UChar * p,UChar r1,UChar r2)2853 s390_emit_LLGFR(UChar *p, UChar r1, UChar r2)
2854 {
2855 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2856 s390_disasm(ENC3(MNM, GPR, GPR), "llgfr", r1, r2);
2857
2858 return emit_RRE(p, 0xb9160000, r1, r2);
2859 }
2860
2861
2862 static UChar *
s390_emit_LLGF(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)2863 s390_emit_LLGF(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2864 {
2865 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2866 s390_disasm(ENC3(MNM, GPR, SDXB), "llgf", r1, dh2, dl2, x2, b2);
2867
2868 return emit_RXY(p, 0xe30000000016ULL, r1, x2, b2, dl2, dh2);
2869 }
2870
2871
2872 static UChar *
s390_emit_LLCR(UChar * p,UChar r1,UChar r2)2873 s390_emit_LLCR(UChar *p, UChar r1, UChar r2)
2874 {
2875 vassert(s390_host_has_eimm);
2876
2877 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2878 s390_disasm(ENC3(MNM, GPR, GPR), "llcr", r1, r2);
2879
2880 return emit_RRE(p, 0xb9940000, r1, r2);
2881 }
2882
2883
2884 static UChar *
s390_emit_LLGCR(UChar * p,UChar r1,UChar r2)2885 s390_emit_LLGCR(UChar *p, UChar r1, UChar r2)
2886 {
2887 vassert(s390_host_has_eimm);
2888
2889 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2890 s390_disasm(ENC3(MNM, GPR, GPR), "llgcr", r1, r2);
2891
2892 return emit_RRE(p, 0xb9840000, r1, r2);
2893 }
2894
2895
2896 static UChar *
s390_emit_LLC(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)2897 s390_emit_LLC(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2898 {
2899 vassert(s390_host_has_eimm);
2900
2901 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2902 s390_disasm(ENC3(MNM, GPR, SDXB), "llc", r1, dh2, dl2, x2, b2);
2903
2904 return emit_RXY(p, 0xe30000000094ULL, r1, x2, b2, dl2, dh2);
2905 }
2906
2907
2908 static UChar *
s390_emit_LLGC(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)2909 s390_emit_LLGC(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2910 {
2911 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2912 s390_disasm(ENC3(MNM, GPR, SDXB), "llgc", r1, dh2, dl2, x2, b2);
2913
2914 return emit_RXY(p, 0xe30000000090ULL, r1, x2, b2, dl2, dh2);
2915 }
2916
2917
2918 static UChar *
s390_emit_LLHR(UChar * p,UChar r1,UChar r2)2919 s390_emit_LLHR(UChar *p, UChar r1, UChar r2)
2920 {
2921 vassert(s390_host_has_eimm);
2922
2923 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2924 s390_disasm(ENC3(MNM, GPR, GPR), "llhr", r1, r2);
2925
2926 return emit_RRE(p, 0xb9950000, r1, r2);
2927 }
2928
2929
2930 static UChar *
s390_emit_LLGHR(UChar * p,UChar r1,UChar r2)2931 s390_emit_LLGHR(UChar *p, UChar r1, UChar r2)
2932 {
2933 vassert(s390_host_has_eimm);
2934
2935 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2936 s390_disasm(ENC3(MNM, GPR, GPR), "llghr", r1, r2);
2937
2938 return emit_RRE(p, 0xb9850000, r1, r2);
2939 }
2940
2941
2942 static UChar *
s390_emit_LLH(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)2943 s390_emit_LLH(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2944 {
2945 vassert(s390_host_has_eimm);
2946
2947 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2948 s390_disasm(ENC3(MNM, GPR, SDXB), "llh", r1, dh2, dl2, x2, b2);
2949
2950 return emit_RXY(p, 0xe30000000095ULL, r1, x2, b2, dl2, dh2);
2951 }
2952
2953
2954 static UChar *
s390_emit_LLGH(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)2955 s390_emit_LLGH(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2956 {
2957 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2958 s390_disasm(ENC3(MNM, GPR, SDXB), "llgh", r1, dh2, dl2, x2, b2);
2959
2960 return emit_RXY(p, 0xe30000000091ULL, r1, x2, b2, dl2, dh2);
2961 }
2962
2963
2964 static UChar *
s390_emit_LLILF(UChar * p,UChar r1,UInt i2)2965 s390_emit_LLILF(UChar *p, UChar r1, UInt i2)
2966 {
2967 vassert(s390_host_has_eimm);
2968
2969 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2970 s390_disasm(ENC3(MNM, GPR, UINT), "llilf", r1, i2);
2971
2972 return emit_RIL(p, 0xc00f00000000ULL, r1, i2);
2973 }
2974
2975
2976 static UChar *
s390_emit_LLILH(UChar * p,UChar r1,UShort i2)2977 s390_emit_LLILH(UChar *p, UChar r1, UShort i2)
2978 {
2979 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2980 s390_disasm(ENC3(MNM, GPR, UINT), "llilh", r1, i2);
2981
2982 return emit_RI(p, 0xa50e0000, r1, i2);
2983 }
2984
2985
2986 static UChar *
s390_emit_LLILL(UChar * p,UChar r1,UShort i2)2987 s390_emit_LLILL(UChar *p, UChar r1, UShort i2)
2988 {
2989 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2990 s390_disasm(ENC3(MNM, GPR, UINT), "llill", r1, i2);
2991
2992 return emit_RI(p, 0xa50f0000, r1, i2);
2993 }
2994
2995
2996 static UChar *
s390_emit_MR(UChar * p,UChar r1,UChar r2)2997 s390_emit_MR(UChar *p, UChar r1, UChar r2)
2998 {
2999 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3000 s390_disasm(ENC3(MNM, GPR, GPR), "mr", r1, r2);
3001
3002 return emit_RR(p, 0x1c00, r1, r2);
3003 }
3004
3005
3006 static UChar *
s390_emit_M(UChar * p,UChar r1,UChar x2,UChar b2,UShort d2)3007 s390_emit_M(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
3008 {
3009 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3010 s390_disasm(ENC3(MNM, GPR, UDXB), "m", r1, d2, x2, b2);
3011
3012 return emit_RX(p, 0x5c000000, r1, x2, b2, d2);
3013 }
3014
3015
3016 static UChar *
s390_emit_MFY(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)3017 s390_emit_MFY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3018 {
3019 vassert(s390_host_has_gie);
3020
3021 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3022 s390_disasm(ENC3(MNM, GPR, SDXB), "mfy", r1, dh2, dl2, x2, b2);
3023
3024 return emit_RXY(p, 0xe3000000005cULL, r1, x2, b2, dl2, dh2);
3025 }
3026
3027
3028 static UChar *
s390_emit_MH(UChar * p,UChar r1,UChar x2,UChar b2,UShort d2)3029 s390_emit_MH(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
3030 {
3031 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3032 s390_disasm(ENC3(MNM, GPR, UDXB), "mh", r1, d2, x2, b2);
3033
3034 return emit_RX(p, 0x4c000000, r1, x2, b2, d2);
3035 }
3036
3037
3038 static UChar *
s390_emit_MHY(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)3039 s390_emit_MHY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3040 {
3041 vassert(s390_host_has_gie);
3042
3043 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3044 s390_disasm(ENC3(MNM, GPR, SDXB), "mhy", r1, dh2, dl2, x2, b2);
3045
3046 return emit_RXY(p, 0xe3000000007cULL, r1, x2, b2, dl2, dh2);
3047 }
3048
3049
3050 static UChar *
s390_emit_MHI(UChar * p,UChar r1,UShort i2)3051 s390_emit_MHI(UChar *p, UChar r1, UShort i2)
3052 {
3053 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3054 s390_disasm(ENC3(MNM, GPR, INT), "mhi", r1, (Int)(Short)i2);
3055
3056 return emit_RI(p, 0xa70c0000, r1, i2);
3057 }
3058
3059
3060 static UChar *
s390_emit_MLR(UChar * p,UChar r1,UChar r2)3061 s390_emit_MLR(UChar *p, UChar r1, UChar r2)
3062 {
3063 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3064 s390_disasm(ENC3(MNM, GPR, GPR), "mlr", r1, r2);
3065
3066 return emit_RRE(p, 0xb9960000, r1, r2);
3067 }
3068
3069
3070 static UChar *
s390_emit_MLGR(UChar * p,UChar r1,UChar r2)3071 s390_emit_MLGR(UChar *p, UChar r1, UChar r2)
3072 {
3073 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3074 s390_disasm(ENC3(MNM, GPR, GPR), "mlgr", r1, r2);
3075
3076 return emit_RRE(p, 0xb9860000, r1, r2);
3077 }
3078
3079
3080 static UChar *
s390_emit_ML(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)3081 s390_emit_ML(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3082 {
3083 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3084 s390_disasm(ENC3(MNM, GPR, SDXB), "ml", r1, dh2, dl2, x2, b2);
3085
3086 return emit_RXY(p, 0xe30000000096ULL, r1, x2, b2, dl2, dh2);
3087 }
3088
3089
3090 static UChar *
s390_emit_MLG(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)3091 s390_emit_MLG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3092 {
3093 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3094 s390_disasm(ENC3(MNM, GPR, SDXB), "mlg", r1, dh2, dl2, x2, b2);
3095
3096 return emit_RXY(p, 0xe30000000086ULL, r1, x2, b2, dl2, dh2);
3097 }
3098
3099
3100 static UChar *
s390_emit_MSR(UChar * p,UChar r1,UChar r2)3101 s390_emit_MSR(UChar *p, UChar r1, UChar r2)
3102 {
3103 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3104 s390_disasm(ENC3(MNM, GPR, GPR), "msr", r1, r2);
3105
3106 return emit_RRE(p, 0xb2520000, r1, r2);
3107 }
3108
3109
3110 static UChar *
s390_emit_MSGR(UChar * p,UChar r1,UChar r2)3111 s390_emit_MSGR(UChar *p, UChar r1, UChar r2)
3112 {
3113 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3114 s390_disasm(ENC3(MNM, GPR, GPR), "msgr", r1, r2);
3115
3116 return emit_RRE(p, 0xb90c0000, r1, r2);
3117 }
3118
3119
3120 static UChar *
s390_emit_MS(UChar * p,UChar r1,UChar x2,UChar b2,UShort d2)3121 s390_emit_MS(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
3122 {
3123 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3124 s390_disasm(ENC3(MNM, GPR, UDXB), "ms", r1, d2, x2, b2);
3125
3126 return emit_RX(p, 0x71000000, r1, x2, b2, d2);
3127 }
3128
3129
3130 static UChar *
s390_emit_MSY(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)3131 s390_emit_MSY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3132 {
3133 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3134 s390_disasm(ENC3(MNM, GPR, SDXB), "msy", r1, dh2, dl2, x2, b2);
3135
3136 return emit_RXY(p, 0xe30000000051ULL, r1, x2, b2, dl2, dh2);
3137 }
3138
3139
3140 static UChar *
s390_emit_MSG(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)3141 s390_emit_MSG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3142 {
3143 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3144 s390_disasm(ENC3(MNM, GPR, SDXB), "msg", r1, dh2, dl2, x2, b2);
3145
3146 return emit_RXY(p, 0xe3000000000cULL, r1, x2, b2, dl2, dh2);
3147 }
3148
3149
3150 static UChar *
s390_emit_MSFI(UChar * p,UChar r1,UInt i2)3151 s390_emit_MSFI(UChar *p, UChar r1, UInt i2)
3152 {
3153 vassert(s390_host_has_gie);
3154
3155 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3156 s390_disasm(ENC3(MNM, GPR, INT), "msfi", r1, i2);
3157
3158 return emit_RIL(p, 0xc20100000000ULL, r1, i2);
3159 }
3160
3161
3162 static UChar *
s390_emit_MSGFI(UChar * p,UChar r1,UInt i2)3163 s390_emit_MSGFI(UChar *p, UChar r1, UInt i2)
3164 {
3165 vassert(s390_host_has_gie);
3166
3167 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3168 s390_disasm(ENC3(MNM, GPR, INT), "msgfi", r1, i2);
3169
3170 return emit_RIL(p, 0xc20000000000ULL, r1, i2);
3171 }
3172
3173
3174 static UChar *
s390_emit_MVC(UChar * p,UInt l,UChar b1,UShort d1,UChar b2,UShort d2)3175 s390_emit_MVC(UChar *p, UInt l, UChar b1, UShort d1, UChar b2, UShort d2)
3176 {
3177 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3178 s390_disasm(ENC3(MNM, UDLB, UDXB), "mvc", d1, l, b1, d2, 0, b2);
3179
3180 return emit_SSa(p, 0xd20000000000ULL, l, b1, d1, b2, d2);
3181 }
3182
3183
3184 static UChar *
s390_emit_MVI(UChar * p,UChar i2,UChar b1,UShort d1)3185 s390_emit_MVI(UChar *p, UChar i2, UChar b1, UShort d1)
3186 {
3187 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3188 s390_disasm(ENC3(MNM, UDXB, INT), "mvi", d1, 0, b1, i2);
3189
3190 return emit_SI(p, 0x92000000, i2, b1, d1);
3191 }
3192
3193
3194 static UChar *
s390_emit_MVHHI(UChar * p,UChar b1,UShort d1,UShort i2)3195 s390_emit_MVHHI(UChar *p, UChar b1, UShort d1, UShort i2)
3196 {
3197 vassert(s390_host_has_gie);
3198
3199 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3200 s390_disasm(ENC3(MNM, UDXB, INT), "mvhhi", d1, 0, b1, i2);
3201
3202 return emit_SIL(p, 0xe54400000000ULL, b1, d1, i2);
3203 }
3204
3205
3206 static UChar *
s390_emit_MVHI(UChar * p,UChar b1,UShort d1,UShort i2)3207 s390_emit_MVHI(UChar *p, UChar b1, UShort d1, UShort i2)
3208 {
3209 vassert(s390_host_has_gie);
3210
3211 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3212 s390_disasm(ENC3(MNM, UDXB, INT), "mvhi", d1, 0, b1, i2);
3213
3214 return emit_SIL(p, 0xe54c00000000ULL, b1, d1, i2);
3215 }
3216
3217
3218 static UChar *
s390_emit_MVGHI(UChar * p,UChar b1,UShort d1,UShort i2)3219 s390_emit_MVGHI(UChar *p, UChar b1, UShort d1, UShort i2)
3220 {
3221 vassert(s390_host_has_gie);
3222
3223 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3224 s390_disasm(ENC3(MNM, UDXB, INT), "mvghi", d1, 0, b1, i2);
3225
3226 return emit_SIL(p, 0xe54800000000ULL, b1, d1, i2);
3227 }
3228
3229
3230 static UChar *
s390_emit_OR(UChar * p,UChar r1,UChar r2)3231 s390_emit_OR(UChar *p, UChar r1, UChar r2)
3232 {
3233 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3234 s390_disasm(ENC3(MNM, GPR, GPR), "or", r1, r2);
3235
3236 return emit_RR(p, 0x1600, r1, r2);
3237 }
3238
3239
3240 static UChar *
s390_emit_OGR(UChar * p,UChar r1,UChar r2)3241 s390_emit_OGR(UChar *p, UChar r1, UChar r2)
3242 {
3243 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3244 s390_disasm(ENC3(MNM, GPR, GPR), "ogr", r1, r2);
3245
3246 return emit_RRE(p, 0xb9810000, r1, r2);
3247 }
3248
3249
3250 static UChar *
s390_emit_O(UChar * p,UChar r1,UChar x2,UChar b2,UShort d2)3251 s390_emit_O(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
3252 {
3253 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3254 s390_disasm(ENC3(MNM, GPR, UDXB), "o", r1, d2, x2, b2);
3255
3256 return emit_RX(p, 0x56000000, r1, x2, b2, d2);
3257 }
3258
3259
3260 static UChar *
s390_emit_OY(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)3261 s390_emit_OY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3262 {
3263 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3264 s390_disasm(ENC3(MNM, GPR, SDXB), "oy", r1, dh2, dl2, x2, b2);
3265
3266 return emit_RXY(p, 0xe30000000056ULL, r1, x2, b2, dl2, dh2);
3267 }
3268
3269
3270 static UChar *
s390_emit_OG(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)3271 s390_emit_OG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3272 {
3273 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3274 s390_disasm(ENC3(MNM, GPR, SDXB), "og", r1, dh2, dl2, x2, b2);
3275
3276 return emit_RXY(p, 0xe30000000081ULL, r1, x2, b2, dl2, dh2);
3277 }
3278
3279
3280 static UChar *
s390_emit_OIHF(UChar * p,UChar r1,UInt i2)3281 s390_emit_OIHF(UChar *p, UChar r1, UInt i2)
3282 {
3283 vassert(s390_host_has_eimm);
3284
3285 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3286 s390_disasm(ENC3(MNM, GPR, UINT), "oihf", r1, i2);
3287
3288 return emit_RIL(p, 0xc00c00000000ULL, r1, i2);
3289 }
3290
3291
3292 static UChar *
s390_emit_OILF(UChar * p,UChar r1,UInt i2)3293 s390_emit_OILF(UChar *p, UChar r1, UInt i2)
3294 {
3295 vassert(s390_host_has_eimm);
3296
3297 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3298 s390_disasm(ENC3(MNM, GPR, UINT), "oilf", r1, i2);
3299
3300 return emit_RIL(p, 0xc00d00000000ULL, r1, i2);
3301 }
3302
3303
3304 static UChar *
s390_emit_OILL(UChar * p,UChar r1,UShort i2)3305 s390_emit_OILL(UChar *p, UChar r1, UShort i2)
3306 {
3307 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3308 s390_disasm(ENC3(MNM, GPR, UINT), "oill", r1, i2);
3309
3310 return emit_RI(p, 0xa50b0000, r1, i2);
3311 }
3312
3313
3314 static UChar *
s390_emit_SLL(UChar * p,UChar r1,UChar b2,UShort d2)3315 s390_emit_SLL(UChar *p, UChar r1, UChar b2, UShort d2)
3316 {
3317 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3318 s390_disasm(ENC3(MNM, GPR, UDXB), "sll", r1, d2, 0, b2);
3319
3320 return emit_RS(p, 0x89000000, r1, 0, b2, d2);
3321 }
3322
3323
3324 static UChar *
s390_emit_SLLG(UChar * p,UChar r1,UChar r3,UChar b2,UShort dl2,UChar dh2)3325 s390_emit_SLLG(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
3326 {
3327 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3328 s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "sllg", r1, r3, dh2, dl2, 0, b2);
3329
3330 return emit_RSY(p, 0xeb000000000dULL, r1, r3, b2, dl2, dh2);
3331 }
3332
3333
3334 static UChar *
s390_emit_SRA(UChar * p,UChar r1,UChar b2,UShort d2)3335 s390_emit_SRA(UChar *p, UChar r1, UChar b2, UShort d2)
3336 {
3337 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3338 s390_disasm(ENC3(MNM, GPR, UDXB), "sra", r1, d2, 0, b2);
3339
3340 return emit_RS(p, 0x8a000000, r1, 0, b2, d2);
3341 }
3342
3343
3344 static UChar *
s390_emit_SRAG(UChar * p,UChar r1,UChar r3,UChar b2,UShort dl2,UChar dh2)3345 s390_emit_SRAG(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
3346 {
3347 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3348 s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "srag", r1, r3, dh2, dl2, 0, b2);
3349
3350 return emit_RSY(p, 0xeb000000000aULL, r1, r3, b2, dl2, dh2);
3351 }
3352
3353
3354 static UChar *
s390_emit_SRL(UChar * p,UChar r1,UChar b2,UShort d2)3355 s390_emit_SRL(UChar *p, UChar r1, UChar b2, UShort d2)
3356 {
3357 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3358 s390_disasm(ENC3(MNM, GPR, UDXB), "srl", r1, d2, 0, b2);
3359
3360 return emit_RS(p, 0x88000000, r1, 0, b2, d2);
3361 }
3362
3363
3364 static UChar *
s390_emit_SRLG(UChar * p,UChar r1,UChar r3,UChar b2,UShort dl2,UChar dh2)3365 s390_emit_SRLG(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
3366 {
3367 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3368 s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "srlg", r1, r3, dh2, dl2, 0, b2);
3369
3370 return emit_RSY(p, 0xeb000000000cULL, r1, r3, b2, dl2, dh2);
3371 }
3372
3373
3374 static UChar *
s390_emit_ST(UChar * p,UChar r1,UChar x2,UChar b2,UShort d2)3375 s390_emit_ST(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
3376 {
3377 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3378 s390_disasm(ENC3(MNM, GPR, UDXB), "st", r1, d2, x2, b2);
3379
3380 return emit_RX(p, 0x50000000, r1, x2, b2, d2);
3381 }
3382
3383
3384 static UChar *
s390_emit_STY(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)3385 s390_emit_STY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3386 {
3387 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3388 s390_disasm(ENC3(MNM, GPR, SDXB), "sty", r1, dh2, dl2, x2, b2);
3389
3390 return emit_RXY(p, 0xe30000000050ULL, r1, x2, b2, dl2, dh2);
3391 }
3392
3393
3394 static UChar *
s390_emit_STG(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)3395 s390_emit_STG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3396 {
3397 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3398 s390_disasm(ENC3(MNM, GPR, SDXB), "stg", r1, dh2, dl2, x2, b2);
3399
3400 return emit_RXY(p, 0xe30000000024ULL, r1, x2, b2, dl2, dh2);
3401 }
3402
3403
3404 static UChar *
s390_emit_STC(UChar * p,UChar r1,UChar x2,UChar b2,UShort d2)3405 s390_emit_STC(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
3406 {
3407 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3408 s390_disasm(ENC3(MNM, GPR, UDXB), "stc", r1, d2, x2, b2);
3409
3410 return emit_RX(p, 0x42000000, r1, x2, b2, d2);
3411 }
3412
3413
3414 static UChar *
s390_emit_STCY(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)3415 s390_emit_STCY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3416 {
3417 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3418 s390_disasm(ENC3(MNM, GPR, SDXB), "stcy", r1, dh2, dl2, x2, b2);
3419
3420 return emit_RXY(p, 0xe30000000072ULL, r1, x2, b2, dl2, dh2);
3421 }
3422
3423
3424 static UChar *
s390_emit_STH(UChar * p,UChar r1,UChar x2,UChar b2,UShort d2)3425 s390_emit_STH(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
3426 {
3427 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3428 s390_disasm(ENC3(MNM, GPR, UDXB), "sth", r1, d2, x2, b2);
3429
3430 return emit_RX(p, 0x40000000, r1, x2, b2, d2);
3431 }
3432
3433
3434 static UChar *
s390_emit_STHY(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)3435 s390_emit_STHY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3436 {
3437 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3438 s390_disasm(ENC3(MNM, GPR, SDXB), "sthy", r1, dh2, dl2, x2, b2);
3439
3440 return emit_RXY(p, 0xe30000000070ULL, r1, x2, b2, dl2, dh2);
3441 }
3442
3443
3444 static UChar *
s390_emit_SR(UChar * p,UChar r1,UChar r2)3445 s390_emit_SR(UChar *p, UChar r1, UChar r2)
3446 {
3447 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3448 s390_disasm(ENC3(MNM, GPR, GPR), "sr", r1, r2);
3449
3450 return emit_RR(p, 0x1b00, r1, r2);
3451 }
3452
3453
3454 static UChar *
s390_emit_SGR(UChar * p,UChar r1,UChar r2)3455 s390_emit_SGR(UChar *p, UChar r1, UChar r2)
3456 {
3457 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3458 s390_disasm(ENC3(MNM, GPR, GPR), "sgr", r1, r2);
3459
3460 return emit_RRE(p, 0xb9090000, r1, r2);
3461 }
3462
3463
3464 static UChar *
s390_emit_S(UChar * p,UChar r1,UChar x2,UChar b2,UShort d2)3465 s390_emit_S(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
3466 {
3467 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3468 s390_disasm(ENC3(MNM, GPR, UDXB), "s", r1, d2, x2, b2);
3469
3470 return emit_RX(p, 0x5b000000, r1, x2, b2, d2);
3471 }
3472
3473
3474 static UChar *
s390_emit_SY(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)3475 s390_emit_SY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3476 {
3477 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3478 s390_disasm(ENC3(MNM, GPR, SDXB), "sy", r1, dh2, dl2, x2, b2);
3479
3480 return emit_RXY(p, 0xe3000000005bULL, r1, x2, b2, dl2, dh2);
3481 }
3482
3483
3484 static UChar *
s390_emit_SG(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)3485 s390_emit_SG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3486 {
3487 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3488 s390_disasm(ENC3(MNM, GPR, SDXB), "sg", r1, dh2, dl2, x2, b2);
3489
3490 return emit_RXY(p, 0xe30000000009ULL, r1, x2, b2, dl2, dh2);
3491 }
3492
3493
3494 static UChar *
s390_emit_SH(UChar * p,UChar r1,UChar x2,UChar b2,UShort d2)3495 s390_emit_SH(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
3496 {
3497 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3498 s390_disasm(ENC3(MNM, GPR, UDXB), "sh", r1, d2, x2, b2);
3499
3500 return emit_RX(p, 0x4b000000, r1, x2, b2, d2);
3501 }
3502
3503
3504 static UChar *
s390_emit_SHY(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)3505 s390_emit_SHY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3506 {
3507 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3508 s390_disasm(ENC3(MNM, GPR, SDXB), "shy", r1, dh2, dl2, x2, b2);
3509
3510 return emit_RXY(p, 0xe3000000007bULL, r1, x2, b2, dl2, dh2);
3511 }
3512
3513
3514 static UChar *
s390_emit_SLFI(UChar * p,UChar r1,UInt i2)3515 s390_emit_SLFI(UChar *p, UChar r1, UInt i2)
3516 {
3517 vassert(s390_host_has_eimm);
3518
3519 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3520 s390_disasm(ENC3(MNM, GPR, UINT), "slfi", r1, i2);
3521
3522 return emit_RIL(p, 0xc20500000000ULL, r1, i2);
3523 }
3524
3525
3526 static UChar *
s390_emit_SLGFI(UChar * p,UChar r1,UInt i2)3527 s390_emit_SLGFI(UChar *p, UChar r1, UInt i2)
3528 {
3529 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3530 s390_disasm(ENC3(MNM, GPR, UINT), "slgfi", r1, i2);
3531
3532 return emit_RIL(p, 0xc20400000000ULL, r1, i2);
3533 }
3534
3535
3536 static UChar *
s390_emit_LDR(UChar * p,UChar r1,UChar r2)3537 s390_emit_LDR(UChar *p, UChar r1, UChar r2)
3538 {
3539 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3540 s390_disasm(ENC3(MNM, FPR, FPR), "ldr", r1, r2);
3541
3542 return emit_RR(p, 0x2800, r1, r2);
3543 }
3544
3545
3546 static UChar *
s390_emit_LE(UChar * p,UChar r1,UChar x2,UChar b2,UShort d2)3547 s390_emit_LE(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
3548 {
3549 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3550 s390_disasm(ENC3(MNM, FPR, UDXB), "le", r1, d2, x2, b2);
3551
3552 return emit_RX(p, 0x78000000, r1, x2, b2, d2);
3553 }
3554
3555
3556 static UChar *
s390_emit_LD(UChar * p,UChar r1,UChar x2,UChar b2,UShort d2)3557 s390_emit_LD(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
3558 {
3559 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3560 s390_disasm(ENC3(MNM, FPR, UDXB), "ld", r1, d2, x2, b2);
3561
3562 return emit_RX(p, 0x68000000, r1, x2, b2, d2);
3563 }
3564
3565
3566 static UChar *
s390_emit_LEY(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)3567 s390_emit_LEY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3568 {
3569 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3570 s390_disasm(ENC3(MNM, FPR, SDXB), "ley", r1, dh2, dl2, x2, b2);
3571
3572 return emit_RXY(p, 0xed0000000064ULL, r1, x2, b2, dl2, dh2);
3573 }
3574
3575
3576 static UChar *
s390_emit_LDY(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)3577 s390_emit_LDY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3578 {
3579 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3580 s390_disasm(ENC3(MNM, FPR, SDXB), "ldy", r1, dh2, dl2, x2, b2);
3581
3582 return emit_RXY(p, 0xed0000000065ULL, r1, x2, b2, dl2, dh2);
3583 }
3584
3585
3586 static UChar *
s390_emit_LFPC(UChar * p,UChar b2,UShort d2)3587 s390_emit_LFPC(UChar *p, UChar b2, UShort d2)
3588 {
3589 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3590 s390_disasm(ENC2(MNM, UDXB), "lfpc", d2, 0, b2);
3591
3592 return emit_S(p, 0xb29d0000, b2, d2);
3593 }
3594
3595
3596 static UChar *
s390_emit_LDGR(UChar * p,UChar r1,UChar r2)3597 s390_emit_LDGR(UChar *p, UChar r1, UChar r2)
3598 {
3599 vassert(s390_host_has_fgx);
3600
3601 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3602 s390_disasm(ENC3(MNM, FPR, GPR), "ldgr", r1, r2);
3603
3604 return emit_RRE(p, 0xb3c10000, r1, r2);
3605 }
3606
3607
3608 static UChar *
s390_emit_LGDR(UChar * p,UChar r1,UChar r2)3609 s390_emit_LGDR(UChar *p, UChar r1, UChar r2)
3610 {
3611 vassert(s390_host_has_fgx);
3612
3613 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3614 s390_disasm(ENC3(MNM, GPR, FPR), "lgdr", r1, r2);
3615
3616 return emit_RRE(p, 0xb3cd0000, r1, r2);
3617 }
3618
3619
3620 static UChar *
s390_emit_LZER(UChar * p,UChar r1,UChar r2)3621 s390_emit_LZER(UChar *p, UChar r1, UChar r2)
3622 {
3623 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3624 s390_disasm(ENC2(MNM, FPR), "lzer", r1);
3625
3626 return emit_RRE(p, 0xb3740000, r1, r2);
3627 }
3628
3629
3630 static UChar *
s390_emit_LZDR(UChar * p,UChar r1,UChar r2)3631 s390_emit_LZDR(UChar *p, UChar r1, UChar r2)
3632 {
3633 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3634 s390_disasm(ENC2(MNM, FPR), "lzdr", r1);
3635
3636 return emit_RRE(p, 0xb3750000, r1, r2);
3637 }
3638
3639
3640 static UChar *
s390_emit_SFPC(UChar * p,UChar r1)3641 s390_emit_SFPC(UChar *p, UChar r1)
3642 {
3643 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3644 s390_disasm(ENC2(MNM, GPR), "sfpc", r1);
3645
3646 return emit_RRE(p, 0xb3840000, r1, 0);
3647 }
3648
3649
3650 static UChar *
s390_emit_STE(UChar * p,UChar r1,UChar x2,UChar b2,UShort d2)3651 s390_emit_STE(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
3652 {
3653 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3654 s390_disasm(ENC3(MNM, FPR, UDXB), "ste", r1, d2, x2, b2);
3655
3656 return emit_RX(p, 0x70000000, r1, x2, b2, d2);
3657 }
3658
3659
3660 static UChar *
s390_emit_STD(UChar * p,UChar r1,UChar x2,UChar b2,UShort d2)3661 s390_emit_STD(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
3662 {
3663 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3664 s390_disasm(ENC3(MNM, FPR, UDXB), "std", r1, d2, x2, b2);
3665
3666 return emit_RX(p, 0x60000000, r1, x2, b2, d2);
3667 }
3668
3669
3670 static UChar *
s390_emit_STEY(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)3671 s390_emit_STEY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3672 {
3673 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3674 s390_disasm(ENC3(MNM, FPR, SDXB), "stey", r1, dh2, dl2, x2, b2);
3675
3676 return emit_RXY(p, 0xed0000000066ULL, r1, x2, b2, dl2, dh2);
3677 }
3678
3679
3680 static UChar *
s390_emit_STDY(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)3681 s390_emit_STDY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3682 {
3683 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3684 s390_disasm(ENC3(MNM, FPR, SDXB), "stdy", r1, dh2, dl2, x2, b2);
3685
3686 return emit_RXY(p, 0xed0000000067ULL, r1, x2, b2, dl2, dh2);
3687 }
3688
3689
3690 static UChar *
s390_emit_STFPC(UChar * p,UChar b2,UShort d2)3691 s390_emit_STFPC(UChar *p, UChar b2, UShort d2)
3692 {
3693 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3694 s390_disasm(ENC2(MNM, UDXB), "stfpc", d2, 0, b2);
3695
3696 return emit_S(p, 0xb29c0000, b2, d2);
3697 }
3698
3699
3700 static UChar *
s390_emit_AEBR(UChar * p,UChar r1,UChar r2)3701 s390_emit_AEBR(UChar *p, UChar r1, UChar r2)
3702 {
3703 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3704 s390_disasm(ENC3(MNM, FPR, FPR), "aebr", r1, r2);
3705
3706 return emit_RRE(p, 0xb30a0000, r1, r2);
3707 }
3708
3709
3710 static UChar *
s390_emit_ADBR(UChar * p,UChar r1,UChar r2)3711 s390_emit_ADBR(UChar *p, UChar r1, UChar r2)
3712 {
3713 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3714 s390_disasm(ENC3(MNM, FPR, FPR), "adbr", r1, r2);
3715
3716 return emit_RRE(p, 0xb31a0000, r1, r2);
3717 }
3718
3719
3720 static UChar *
s390_emit_AXBR(UChar * p,UChar r1,UChar r2)3721 s390_emit_AXBR(UChar *p, UChar r1, UChar r2)
3722 {
3723 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3724 s390_disasm(ENC3(MNM, FPR, FPR), "axbr", r1, r2);
3725
3726 return emit_RRE(p, 0xb34a0000, r1, r2);
3727 }
3728
3729
3730 static UChar *
s390_emit_CEBR(UChar * p,UChar r1,UChar r2)3731 s390_emit_CEBR(UChar *p, UChar r1, UChar r2)
3732 {
3733 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3734 s390_disasm(ENC3(MNM, FPR, FPR), "cebr", r1, r2);
3735
3736 return emit_RRE(p, 0xb3090000, r1, r2);
3737 }
3738
3739
3740 static UChar *
s390_emit_CDBR(UChar * p,UChar r1,UChar r2)3741 s390_emit_CDBR(UChar *p, UChar r1, UChar r2)
3742 {
3743 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3744 s390_disasm(ENC3(MNM, FPR, FPR), "cdbr", r1, r2);
3745
3746 return emit_RRE(p, 0xb3190000, r1, r2);
3747 }
3748
3749
3750 static UChar *
s390_emit_CXBR(UChar * p,UChar r1,UChar r2)3751 s390_emit_CXBR(UChar *p, UChar r1, UChar r2)
3752 {
3753 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3754 s390_disasm(ENC3(MNM, FPR, FPR), "cxbr", r1, r2);
3755
3756 return emit_RRE(p, 0xb3490000, r1, r2);
3757 }
3758
3759
3760 static UChar *
s390_emit_CEFBRA(UChar * p,UChar m3,UChar m4,UChar r1,UChar r2)3761 s390_emit_CEFBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
3762 {
3763 vassert(m4 == 0);
3764 vassert(m3 == 0 || s390_host_has_fpext);
3765
3766 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
3767 if (m3 == 0)
3768 s390_disasm(ENC3(MNM, FPR, GPR), "cefbr", r1, r2);
3769 else
3770 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT),
3771 "cefbra", r1, m3, r2, m4);
3772 }
3773
3774 return emit_RRF2(p, 0xb3940000, m3, m4, r1, r2);
3775 }
3776
3777
3778 static UChar *
s390_emit_CDFBRA(UChar * p,UChar m3,UChar m4,UChar r1,UChar r2)3779 s390_emit_CDFBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
3780 {
3781 vassert(m4 == 0);
3782 vassert(m3 == 0 || s390_host_has_fpext);
3783
3784 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
3785 if (m3 == 0)
3786 s390_disasm(ENC3(MNM, FPR, GPR), "cdfbr", r1, r2);
3787 else
3788 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT),
3789 "cdfbra", r1, m3, r2, m4);
3790 }
3791
3792 return emit_RRF2(p, 0xb3950000, m3, m4, r1, r2);
3793 }
3794
3795
3796 static UChar *
s390_emit_CXFBRA(UChar * p,UChar m3,UChar m4,UChar r1,UChar r2)3797 s390_emit_CXFBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
3798 {
3799 vassert(m4 == 0);
3800 vassert(m3 == 0 || s390_host_has_fpext);
3801
3802 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
3803 if (m3 == 0)
3804 s390_disasm(ENC3(MNM, FPR, GPR), "cxfbr", r1, r2);
3805 else
3806 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT),
3807 "cxfbra", r1, m3, r2, m4);
3808 }
3809
3810 return emit_RRF2(p, 0xb3960000, m3, m4, r1, r2);
3811 }
3812
3813
3814 static UChar *
s390_emit_CEGBRA(UChar * p,UChar m3,UChar m4,UChar r1,UChar r2)3815 s390_emit_CEGBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
3816 {
3817 vassert(m4 == 0);
3818 vassert(m3 == 0 || s390_host_has_fpext);
3819
3820 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
3821 if (m3 == 0)
3822 s390_disasm(ENC3(MNM, FPR, GPR), "cegbr", r1, r2);
3823 else
3824 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT),
3825 "cegbra", r1, m3, r2, m4);
3826 }
3827
3828 return emit_RRF2(p, 0xb3a40000, m3, m4, r1, r2);
3829 }
3830
3831
3832 static UChar *
s390_emit_CDGBRA(UChar * p,UChar m3,UChar m4,UChar r1,UChar r2)3833 s390_emit_CDGBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
3834 {
3835 vassert(m4 == 0);
3836 vassert(m3 == 0 || s390_host_has_fpext);
3837
3838 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
3839 if (m3 == 0)
3840 s390_disasm(ENC3(MNM, FPR, GPR), "cdgbr", r1, r2);
3841 else
3842 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT),
3843 "cdgbra", r1, m3, r2, m4);
3844 }
3845
3846 return emit_RRF2(p, 0xb3a50000, m3, m4, r1, r2);
3847 }
3848
3849
3850 static UChar *
s390_emit_CXGBRA(UChar * p,UChar m3,UChar m4,UChar r1,UChar r2)3851 s390_emit_CXGBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
3852 {
3853 vassert(m4 == 0);
3854 vassert(m3 == 0 || s390_host_has_fpext);
3855
3856 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
3857 if (m3 == 0)
3858 s390_disasm(ENC3(MNM, FPR, GPR), "cxgbr", r1, r2);
3859 else
3860 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT),
3861 "cxgbra", r1, m3, r2, m4);
3862 }
3863
3864 return emit_RRF2(p, 0xb3a60000, m3, m4, r1, r2);
3865 }
3866
3867
3868 static UChar *
s390_emit_CELFBR(UChar * p,UChar m3,UChar m4,UChar r1,UChar r2)3869 s390_emit_CELFBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
3870 {
3871 vassert(m4 == 0);
3872 vassert(s390_host_has_fpext);
3873
3874 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3875 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "celfbr", r1, m3, r2, m4);
3876
3877 return emit_RRF2(p, 0xb3900000, m3, m4, r1, r2);
3878 }
3879
3880
3881 static UChar *
s390_emit_CDLFBR(UChar * p,UChar m3,UChar m4,UChar r1,UChar r2)3882 s390_emit_CDLFBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
3883 {
3884 vassert(m4 == 0);
3885 vassert(s390_host_has_fpext);
3886
3887 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3888 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cdlfbr", r1, m3, r2, m4);
3889
3890 return emit_RRF2(p, 0xb3910000, m3, m4, r1, r2);
3891 }
3892
3893
3894 static UChar *
s390_emit_CXLFBR(UChar * p,UChar m3,UChar m4,UChar r1,UChar r2)3895 s390_emit_CXLFBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
3896 {
3897 vassert(m4 == 0);
3898 vassert(s390_host_has_fpext);
3899
3900 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3901 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cxlfbr", r1, m3, r2, m4);
3902
3903 return emit_RRF2(p, 0xb3920000, m3, m4, r1, r2);
3904 }
3905
3906
3907 static UChar *
s390_emit_CELGBR(UChar * p,UChar m3,UChar m4,UChar r1,UChar r2)3908 s390_emit_CELGBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
3909 {
3910 vassert(m4 == 0);
3911 vassert(s390_host_has_fpext);
3912
3913 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3914 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "celgbr", r1, m3, r2, m4);
3915
3916 return emit_RRF2(p, 0xb3a00000, m3, m4, r1, r2);
3917 }
3918
3919
3920 static UChar *
s390_emit_CDLGBR(UChar * p,UChar m3,UChar m4,UChar r1,UChar r2)3921 s390_emit_CDLGBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
3922 {
3923 vassert(m4 == 0);
3924 vassert(s390_host_has_fpext);
3925
3926 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3927 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cdlgbr", r1, m3, r2, m4);
3928
3929 return emit_RRF2(p, 0xb3a10000, m3, m4, r1, r2);
3930 }
3931
3932
3933 static UChar *
s390_emit_CXLGBR(UChar * p,UChar m3,UChar m4,UChar r1,UChar r2)3934 s390_emit_CXLGBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
3935 {
3936 vassert(m4 == 0);
3937 vassert(s390_host_has_fpext);
3938
3939 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3940 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cxlgbr", r1, m3, r2, m4);
3941
3942 return emit_RRF2(p, 0xb3a20000, m3, m4, r1, r2);
3943 }
3944
3945
3946 static UChar *
s390_emit_CLFEBR(UChar * p,UChar m3,UChar m4,UChar r1,UChar r2)3947 s390_emit_CLFEBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
3948 {
3949 vassert(m4 == 0);
3950 vassert(s390_host_has_fpext);
3951
3952 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3953 s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clfebr", r1, m3, r2, m4);
3954
3955 return emit_RRF2(p, 0xb39c0000, m3, m4, r1, r2);
3956 }
3957
3958
3959 static UChar *
s390_emit_CLFDBR(UChar * p,UChar m3,UChar m4,UChar r1,UChar r2)3960 s390_emit_CLFDBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
3961 {
3962 vassert(m4 == 0);
3963 vassert(s390_host_has_fpext);
3964
3965 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3966 s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clfdbr", r1, m3, r2, m4);
3967
3968 return emit_RRF2(p, 0xb39d0000, m3, m4, r1, r2);
3969 }
3970
3971
3972 static UChar *
s390_emit_CLFXBR(UChar * p,UChar m3,UChar m4,UChar r1,UChar r2)3973 s390_emit_CLFXBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
3974 {
3975 vassert(m4 == 0);
3976 vassert(s390_host_has_fpext);
3977
3978 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3979 s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clfxbr", r1, m3, r2, m4);
3980
3981 return emit_RRF2(p, 0xb39e0000, m3, m4, r1, r2);
3982 }
3983
3984
3985 static UChar *
s390_emit_CLGEBR(UChar * p,UChar m3,UChar m4,UChar r1,UChar r2)3986 s390_emit_CLGEBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
3987 {
3988 vassert(m4 == 0);
3989 vassert(s390_host_has_fpext);
3990
3991 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3992 s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clgebr", r1, m3, r2, m4);
3993
3994 return emit_RRF2(p, 0xb3ac0000, m3, m4, r1, r2);
3995 }
3996
3997
3998 static UChar *
s390_emit_CLGDBR(UChar * p,UChar m3,UChar m4,UChar r1,UChar r2)3999 s390_emit_CLGDBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4000 {
4001 vassert(m4 == 0);
4002 vassert(s390_host_has_fpext);
4003
4004 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4005 s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clgdbr", r1, m3, r2, m4);
4006
4007 return emit_RRF2(p, 0xb3ad0000, m3, m4, r1, r2);
4008 }
4009
4010
4011 static UChar *
s390_emit_CLGXBR(UChar * p,UChar m3,UChar m4,UChar r1,UChar r2)4012 s390_emit_CLGXBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4013 {
4014 vassert(m4 == 0);
4015 vassert(s390_host_has_fpext);
4016
4017 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4018 s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clgxbr", r1, m3, r2, m4);
4019
4020 return emit_RRF2(p, 0xb3ae0000, m3, m4, r1, r2);
4021 }
4022
4023
4024 static UChar *
s390_emit_CFEBR(UChar * p,UChar r3,UChar r1,UChar r2)4025 s390_emit_CFEBR(UChar *p, UChar r3, UChar r1, UChar r2)
4026 {
4027 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4028 s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cfebr", r1, r3, r2);
4029
4030 return emit_RRF3(p, 0xb3980000, r3, r1, r2);
4031 }
4032
4033
4034 static UChar *
s390_emit_CFDBR(UChar * p,UChar r3,UChar r1,UChar r2)4035 s390_emit_CFDBR(UChar *p, UChar r3, UChar r1, UChar r2)
4036 {
4037 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4038 s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cfdbr", r1, r3, r2);
4039
4040 return emit_RRF3(p, 0xb3990000, r3, r1, r2);
4041 }
4042
4043
4044 static UChar *
s390_emit_CFXBR(UChar * p,UChar r3,UChar r1,UChar r2)4045 s390_emit_CFXBR(UChar *p, UChar r3, UChar r1, UChar r2)
4046 {
4047 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4048 s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cfxbr", r1, r3, r2);
4049
4050 return emit_RRF3(p, 0xb39a0000, r3, r1, r2);
4051 }
4052
4053
4054 static UChar *
s390_emit_CGEBR(UChar * p,UChar r3,UChar r1,UChar r2)4055 s390_emit_CGEBR(UChar *p, UChar r3, UChar r1, UChar r2)
4056 {
4057 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4058 s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cgebr", r1, r3, r2);
4059
4060 return emit_RRF3(p, 0xb3a80000, r3, r1, r2);
4061 }
4062
4063
4064 static UChar *
s390_emit_CGDBR(UChar * p,UChar r3,UChar r1,UChar r2)4065 s390_emit_CGDBR(UChar *p, UChar r3, UChar r1, UChar r2)
4066 {
4067 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4068 s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cgdbr", r1, r3, r2);
4069
4070 return emit_RRF3(p, 0xb3a90000, r3, r1, r2);
4071 }
4072
4073
4074 static UChar *
s390_emit_CGXBR(UChar * p,UChar r3,UChar r1,UChar r2)4075 s390_emit_CGXBR(UChar *p, UChar r3, UChar r1, UChar r2)
4076 {
4077 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4078 s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cgxbr", r1, r3, r2);
4079
4080 return emit_RRF3(p, 0xb3aa0000, r3, r1, r2);
4081 }
4082
4083
4084 static UChar *
s390_emit_DEBR(UChar * p,UChar r1,UChar r2)4085 s390_emit_DEBR(UChar *p, UChar r1, UChar r2)
4086 {
4087 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4088 s390_disasm(ENC3(MNM, FPR, FPR), "debr", r1, r2);
4089
4090 return emit_RRE(p, 0xb30d0000, r1, r2);
4091 }
4092
4093
4094 static UChar *
s390_emit_DDBR(UChar * p,UChar r1,UChar r2)4095 s390_emit_DDBR(UChar *p, UChar r1, UChar r2)
4096 {
4097 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4098 s390_disasm(ENC3(MNM, FPR, FPR), "ddbr", r1, r2);
4099
4100 return emit_RRE(p, 0xb31d0000, r1, r2);
4101 }
4102
4103
4104 static UChar *
s390_emit_DXBR(UChar * p,UChar r1,UChar r2)4105 s390_emit_DXBR(UChar *p, UChar r1, UChar r2)
4106 {
4107 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4108 s390_disasm(ENC3(MNM, FPR, FPR), "dxbr", r1, r2);
4109
4110 return emit_RRE(p, 0xb34d0000, r1, r2);
4111 }
4112
4113
4114 static UChar *
s390_emit_LCEBR(UChar * p,UChar r1,UChar r2)4115 s390_emit_LCEBR(UChar *p, UChar r1, UChar r2)
4116 {
4117 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4118 s390_disasm(ENC3(MNM, FPR, FPR), "lcebr", r1, r2);
4119
4120 return emit_RRE(p, 0xb3030000, r1, r2);
4121 }
4122
4123
4124 static UChar *
s390_emit_LCDBR(UChar * p,UChar r1,UChar r2)4125 s390_emit_LCDBR(UChar *p, UChar r1, UChar r2)
4126 {
4127 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4128 s390_disasm(ENC3(MNM, FPR, FPR), "lcdbr", r1, r2);
4129
4130 return emit_RRE(p, 0xb3130000, r1, r2);
4131 }
4132
4133
4134 static UChar *
s390_emit_LCXBR(UChar * p,UChar r1,UChar r2)4135 s390_emit_LCXBR(UChar *p, UChar r1, UChar r2)
4136 {
4137 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4138 s390_disasm(ENC3(MNM, FPR, FPR), "lcxbr", r1, r2);
4139
4140 return emit_RRE(p, 0xb3430000, r1, r2);
4141 }
4142
4143
4144 static UChar *
s390_emit_LDEBR(UChar * p,UChar r1,UChar r2)4145 s390_emit_LDEBR(UChar *p, UChar r1, UChar r2)
4146 {
4147 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4148 s390_disasm(ENC3(MNM, FPR, FPR), "ldebr", r1, r2);
4149
4150 return emit_RRE(p, 0xb3040000, r1, r2);
4151 }
4152
4153
4154 static UChar *
s390_emit_LXDBR(UChar * p,UChar r1,UChar r2)4155 s390_emit_LXDBR(UChar *p, UChar r1, UChar r2)
4156 {
4157 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4158 s390_disasm(ENC3(MNM, FPR, FPR), "lxdbr", r1, r2);
4159
4160 return emit_RRE(p, 0xb3050000, r1, r2);
4161 }
4162
4163
4164 static UChar *
s390_emit_LXEBR(UChar * p,UChar r1,UChar r2)4165 s390_emit_LXEBR(UChar *p, UChar r1, UChar r2)
4166 {
4167 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4168 s390_disasm(ENC3(MNM, FPR, FPR), "lxebr", r1, r2);
4169
4170 return emit_RRE(p, 0xb3060000, r1, r2);
4171 }
4172
4173
4174 static UChar *
s390_emit_LNEBR(UChar * p,UChar r1,UChar r2)4175 s390_emit_LNEBR(UChar *p, UChar r1, UChar r2)
4176 {
4177 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4178 s390_disasm(ENC3(MNM, FPR, FPR), "lnebr", r1, r2);
4179
4180 return emit_RRE(p, 0xb3010000, r1, r2);
4181 }
4182
4183
4184 static UChar *
s390_emit_LNDBR(UChar * p,UChar r1,UChar r2)4185 s390_emit_LNDBR(UChar *p, UChar r1, UChar r2)
4186 {
4187 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4188 s390_disasm(ENC3(MNM, FPR, FPR), "lndbr", r1, r2);
4189
4190 return emit_RRE(p, 0xb3110000, r1, r2);
4191 }
4192
4193
4194 static UChar *
s390_emit_LNXBR(UChar * p,UChar r1,UChar r2)4195 s390_emit_LNXBR(UChar *p, UChar r1, UChar r2)
4196 {
4197 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4198 s390_disasm(ENC3(MNM, FPR, FPR), "lnxbr", r1, r2);
4199
4200 return emit_RRE(p, 0xb3410000, r1, r2);
4201 }
4202
4203
4204 static UChar *
s390_emit_LPEBR(UChar * p,UChar r1,UChar r2)4205 s390_emit_LPEBR(UChar *p, UChar r1, UChar r2)
4206 {
4207 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4208 s390_disasm(ENC3(MNM, FPR, FPR), "lpebr", r1, r2);
4209
4210 return emit_RRE(p, 0xb3000000, r1, r2);
4211 }
4212
4213
4214 static UChar *
s390_emit_LPDBR(UChar * p,UChar r1,UChar r2)4215 s390_emit_LPDBR(UChar *p, UChar r1, UChar r2)
4216 {
4217 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4218 s390_disasm(ENC3(MNM, FPR, FPR), "lpdbr", r1, r2);
4219
4220 return emit_RRE(p, 0xb3100000, r1, r2);
4221 }
4222
4223
4224 static UChar *
s390_emit_LPXBR(UChar * p,UChar r1,UChar r2)4225 s390_emit_LPXBR(UChar *p, UChar r1, UChar r2)
4226 {
4227 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4228 s390_disasm(ENC3(MNM, FPR, FPR), "lpxbr", r1, r2);
4229
4230 return emit_RRE(p, 0xb3400000, r1, r2);
4231 }
4232
4233
4234 static UChar *
s390_emit_LEDBRA(UChar * p,UChar m3,UChar m4,UChar r1,UChar r2)4235 s390_emit_LEDBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4236 {
4237 vassert(m4 == 0);
4238 vassert(m3 == 0 || s390_host_has_fpext);
4239
4240 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
4241 if (m3 == 0)
4242 s390_disasm(ENC3(MNM, FPR, FPR), "ledbr", r1, r2);
4243 else
4244 s390_disasm(ENC5(MNM, FPR, UINT, FPR, UINT),
4245 "ledbra", r1, m3, r2, m4);
4246 }
4247
4248 return emit_RRF2(p, 0xb3440000, m3, m4, r1, r2);
4249 }
4250
4251
4252 static UChar *
s390_emit_LDXBRA(UChar * p,UChar m3,UChar m4,UChar r1,UChar r2)4253 s390_emit_LDXBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4254 {
4255 vassert(m4 == 0);
4256 vassert(m3 == 0 || s390_host_has_fpext);
4257
4258 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
4259 if (m3 == 0)
4260 s390_disasm(ENC3(MNM, FPR, FPR), "ldxbr", r1, r2);
4261 else
4262 s390_disasm(ENC5(MNM, FPR, UINT, FPR, UINT),
4263 "ldxbra", r1, m3, r2, m4);
4264 }
4265
4266 return emit_RRF2(p, 0xb3450000, m3, m4, r1, r2);
4267 }
4268
4269
4270 static UChar *
s390_emit_LEXBRA(UChar * p,UChar m3,UChar m4,UChar r1,UChar r2)4271 s390_emit_LEXBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4272 {
4273 vassert(m4 == 0);
4274 vassert(m3 == 0 || s390_host_has_fpext);
4275
4276 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
4277 if (m3 == 0)
4278 s390_disasm(ENC3(MNM, FPR, FPR), "lexbr", r1, r2);
4279 else
4280 s390_disasm(ENC5(MNM, FPR, UINT, FPR, UINT),
4281 "lexbra", r1, m3, r2, m4);
4282 }
4283
4284 return emit_RRF2(p, 0xb3460000, m3, m4, r1, r2);
4285 }
4286
4287
4288 static UChar *
s390_emit_FIEBRA(UChar * p,UChar m3,UChar m4,UChar r1,UChar r2)4289 s390_emit_FIEBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4290 {
4291 vassert(m3 == 0 || s390_host_has_fpext);
4292
4293 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
4294 if (m4 == 0)
4295 s390_disasm(ENC4(MNM, FPR, UINT, FPR), "fiebr", r1, m3, r2);
4296 else
4297 s390_disasm(ENC5(MNM, FPR, UINT, FPR, UINT),
4298 "fiebra", r1, m3, r2, m4);
4299 }
4300
4301 return emit_RRF2(p, 0xb3570000, m3, m4, r1, r2);
4302 }
4303
4304
4305 static UChar *
s390_emit_FIDBRA(UChar * p,UChar m3,UChar m4,UChar r1,UChar r2)4306 s390_emit_FIDBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4307 {
4308 vassert(m3 == 0 || s390_host_has_fpext);
4309
4310 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
4311 if (m4 == 0)
4312 s390_disasm(ENC4(MNM, FPR, UINT, FPR), "fidbr", r1, m3, r2);
4313 else
4314 s390_disasm(ENC5(MNM, FPR, UINT, FPR, UINT),
4315 "fidbra", r1, m3, r2, m4);
4316 }
4317
4318 return emit_RRF2(p, 0xb35f0000, m3, m4, r1, r2);
4319 }
4320
4321
4322 static UChar *
s390_emit_FIXBRA(UChar * p,UChar m3,UChar m4,UChar r1,UChar r2)4323 s390_emit_FIXBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4324 {
4325 vassert(m3 == 0 || s390_host_has_fpext);
4326
4327 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
4328 if (m4 == 0)
4329 s390_disasm(ENC4(MNM, FPR, UINT, FPR), "fixbr", r1, m3, r2);
4330 else
4331 s390_disasm(ENC5(MNM, FPR, UINT, FPR, UINT),
4332 "fixbra", r1, m3, r2, m4);
4333 }
4334
4335 return emit_RRF2(p, 0xb3470000, m3, m4, r1, r2);
4336 }
4337
4338
4339 static UChar *
s390_emit_MEEBR(UChar * p,UChar r1,UChar r2)4340 s390_emit_MEEBR(UChar *p, UChar r1, UChar r2)
4341 {
4342 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4343 s390_disasm(ENC3(MNM, FPR, FPR), "meebr", r1, r2);
4344
4345 return emit_RRE(p, 0xb3170000, r1, r2);
4346 }
4347
4348
4349 static UChar *
s390_emit_MDBR(UChar * p,UChar r1,UChar r2)4350 s390_emit_MDBR(UChar *p, UChar r1, UChar r2)
4351 {
4352 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4353 s390_disasm(ENC3(MNM, FPR, FPR), "mdbr", r1, r2);
4354
4355 return emit_RRE(p, 0xb31c0000, r1, r2);
4356 }
4357
4358
4359 static UChar *
s390_emit_MXBR(UChar * p,UChar r1,UChar r2)4360 s390_emit_MXBR(UChar *p, UChar r1, UChar r2)
4361 {
4362 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4363 s390_disasm(ENC3(MNM, FPR, FPR), "mxbr", r1, r2);
4364
4365 return emit_RRE(p, 0xb34c0000, r1, r2);
4366 }
4367
4368
4369 static UChar *
s390_emit_MAEBR(UChar * p,UChar r1,UChar r3,UChar r2)4370 s390_emit_MAEBR(UChar *p, UChar r1, UChar r3, UChar r2)
4371 {
4372 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4373 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "maebr", r1, r3, r2);
4374
4375 return emit_RRF(p, 0xb30e0000, r1, r3, r2);
4376 }
4377
4378
4379 static UChar *
s390_emit_MADBR(UChar * p,UChar r1,UChar r3,UChar r2)4380 s390_emit_MADBR(UChar *p, UChar r1, UChar r3, UChar r2)
4381 {
4382 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4383 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "madbr", r1, r3, r2);
4384
4385 return emit_RRF(p, 0xb31e0000, r1, r3, r2);
4386 }
4387
4388
4389 static UChar *
s390_emit_MSEBR(UChar * p,UChar r1,UChar r3,UChar r2)4390 s390_emit_MSEBR(UChar *p, UChar r1, UChar r3, UChar r2)
4391 {
4392 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4393 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "msebr", r1, r3, r2);
4394
4395 return emit_RRF(p, 0xb30f0000, r1, r3, r2);
4396 }
4397
4398
4399 static UChar *
s390_emit_MSDBR(UChar * p,UChar r1,UChar r3,UChar r2)4400 s390_emit_MSDBR(UChar *p, UChar r1, UChar r3, UChar r2)
4401 {
4402 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4403 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "msdbr", r1, r3, r2);
4404
4405 return emit_RRF(p, 0xb31f0000, r1, r3, r2);
4406 }
4407
4408
4409 static UChar *
s390_emit_SQEBR(UChar * p,UChar r1,UChar r2)4410 s390_emit_SQEBR(UChar *p, UChar r1, UChar r2)
4411 {
4412 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4413 s390_disasm(ENC3(MNM, FPR, FPR), "sqebr", r1, r2);
4414
4415 return emit_RRE(p, 0xb3140000, r1, r2);
4416 }
4417
4418
4419 static UChar *
s390_emit_SQDBR(UChar * p,UChar r1,UChar r2)4420 s390_emit_SQDBR(UChar *p, UChar r1, UChar r2)
4421 {
4422 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4423 s390_disasm(ENC3(MNM, FPR, FPR), "sqdbr", r1, r2);
4424
4425 return emit_RRE(p, 0xb3150000, r1, r2);
4426 }
4427
4428
4429 static UChar *
s390_emit_SQXBR(UChar * p,UChar r1,UChar r2)4430 s390_emit_SQXBR(UChar *p, UChar r1, UChar r2)
4431 {
4432 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4433 s390_disasm(ENC3(MNM, FPR, FPR), "sqxbr", r1, r2);
4434
4435 return emit_RRE(p, 0xb3160000, r1, r2);
4436 }
4437
4438
4439 static UChar *
s390_emit_SEBR(UChar * p,UChar r1,UChar r2)4440 s390_emit_SEBR(UChar *p, UChar r1, UChar r2)
4441 {
4442 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4443 s390_disasm(ENC3(MNM, FPR, FPR), "sebr", r1, r2);
4444
4445 return emit_RRE(p, 0xb30b0000, r1, r2);
4446 }
4447
4448
4449 static UChar *
s390_emit_SDBR(UChar * p,UChar r1,UChar r2)4450 s390_emit_SDBR(UChar *p, UChar r1, UChar r2)
4451 {
4452 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4453 s390_disasm(ENC3(MNM, FPR, FPR), "sdbr", r1, r2);
4454
4455 return emit_RRE(p, 0xb31b0000, r1, r2);
4456 }
4457
4458
4459 static UChar *
s390_emit_SXBR(UChar * p,UChar r1,UChar r2)4460 s390_emit_SXBR(UChar *p, UChar r1, UChar r2)
4461 {
4462 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4463 s390_disasm(ENC3(MNM, FPR, FPR), "sxbr", r1, r2);
4464
4465 return emit_RRE(p, 0xb34b0000, r1, r2);
4466 }
4467
4468
4469 static UChar *
s390_emit_ADTRA(UChar * p,UChar r3,UChar m4,UChar r1,UChar r2)4470 s390_emit_ADTRA(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
4471 {
4472 vassert(s390_host_has_dfp);
4473 vassert(m4 == 0 || s390_host_has_fpext);
4474 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
4475 if (m4 == 0)
4476 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "adtr", r1, r2, r3);
4477 else
4478 s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "adtra", r1, r2, r3, m4);
4479 }
4480
4481 return emit_RRF4(p, 0xb3d20000, r3, m4, r1, r2);
4482 }
4483
4484
4485 static UChar *
s390_emit_AXTRA(UChar * p,UChar r3,UChar m4,UChar r1,UChar r2)4486 s390_emit_AXTRA(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
4487 {
4488 vassert(s390_host_has_dfp);
4489 vassert(m4 == 0 || s390_host_has_fpext);
4490 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
4491 if (m4 == 0)
4492 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "axtr", r1, r2, r3);
4493 else
4494 s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "axtra", r1, r2, r3, m4);
4495 }
4496
4497 return emit_RRF4(p, 0xb3da0000, r3, m4, r1, r2);
4498 }
4499
4500
4501 static UChar *
s390_emit_CDTR(UChar * p,UChar r1,UChar r2)4502 s390_emit_CDTR(UChar *p, UChar r1, UChar r2)
4503 {
4504 vassert(s390_host_has_dfp);
4505 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4506 s390_disasm(ENC3(MNM, FPR, FPR), "cdtr", r1, r2);
4507
4508 return emit_RRE(p, 0xb3e40000, r1, r2);
4509 }
4510
4511
4512 static UChar *
s390_emit_CXTR(UChar * p,UChar r1,UChar r2)4513 s390_emit_CXTR(UChar *p, UChar r1, UChar r2)
4514 {
4515 vassert(s390_host_has_dfp);
4516 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4517 s390_disasm(ENC3(MNM, FPR, FPR), "cxtr", r1, r2);
4518
4519 return emit_RRE(p, 0xb3ec0000, r1, r2);
4520 }
4521
4522
4523 static UChar *
s390_emit_CDGTRA(UChar * p,UChar m3,UChar m4,UChar r1,UChar r2)4524 s390_emit_CDGTRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4525 {
4526 vassert(s390_host_has_dfp);
4527 vassert(m4 == 0);
4528 vassert(m3 == 0 || s390_host_has_fpext);
4529
4530 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
4531 if (m3 == 0)
4532 s390_disasm(ENC3(MNM, FPR, GPR), "cdgtr", r1, r2);
4533 else
4534 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cdgtra", r1, m3, r2, m4);
4535 }
4536
4537 return emit_RRF2(p, 0xb3f10000, m3, m4, r1, r2);
4538 }
4539
4540
4541 static UChar *
s390_emit_CXGTR(UChar * p,UChar m3,UChar m4,UChar r1,UChar r2)4542 s390_emit_CXGTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4543 {
4544 vassert(s390_host_has_dfp);
4545 vassert(m4 == 0);
4546 /* rounding mode m3 is not considered, as the corresponding
4547 IRop (Iop_I64StoD128) does not take rounding mode. */
4548 vassert(m3 == 0);
4549
4550 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4551 s390_disasm(ENC3(MNM, FPR, GPR), "cxgtr", r1, r2);
4552
4553 return emit_RRF2(p, 0xb3f90000, m3, m4, r1, r2);
4554 }
4555
4556
4557 static UChar *
s390_emit_CDFTR(UChar * p,UChar m3,UChar m4,UChar r1,UChar r2)4558 s390_emit_CDFTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4559 {
4560 vassert(m4 == 0);
4561 vassert(s390_host_has_dfp);
4562 vassert(s390_host_has_fpext);
4563
4564 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4565 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cdftr", r1, m3, r2, m4);
4566
4567 return emit_RRF2(p, 0xb9510000, m3, m4, r1, r2);
4568 }
4569
4570
4571 static UChar *
s390_emit_CXFTR(UChar * p,UChar m3,UChar m4,UChar r1,UChar r2)4572 s390_emit_CXFTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4573 {
4574 vassert(m4 == 0);
4575 vassert(s390_host_has_dfp);
4576 vassert(s390_host_has_fpext);
4577
4578 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4579 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cxftr", r1, m3, r2, m4);
4580
4581 return emit_RRF2(p, 0xb9590000, m3, m4, r1, r2);
4582 }
4583
4584
4585 static UChar *
s390_emit_CDLFTR(UChar * p,UChar m3,UChar m4,UChar r1,UChar r2)4586 s390_emit_CDLFTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4587 {
4588 vassert(m4 == 0);
4589 vassert(s390_host_has_dfp);
4590 vassert(s390_host_has_fpext);
4591
4592 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4593 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cdlftr", r1, m3, r2, m4);
4594
4595 return emit_RRF2(p, 0xb9530000, m3, m4, r1, r2);
4596 }
4597
4598
4599 static UChar *
s390_emit_CXLFTR(UChar * p,UChar m3,UChar m4,UChar r1,UChar r2)4600 s390_emit_CXLFTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4601 {
4602 vassert(m4 == 0);
4603 vassert(s390_host_has_dfp);
4604 vassert(s390_host_has_fpext);
4605
4606 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4607 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cxlftr", r1, m3, r2, m4);
4608
4609 return emit_RRF2(p, 0xb95b0000, m3, m4, r1, r2);
4610 }
4611
4612
4613 static UChar *
s390_emit_CDLGTR(UChar * p,UChar m3,UChar m4,UChar r1,UChar r2)4614 s390_emit_CDLGTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4615 {
4616 vassert(m4 == 0);
4617 vassert(s390_host_has_dfp);
4618 vassert(s390_host_has_fpext);
4619
4620 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4621 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cdlgtr", r1, m3, r2, m4);
4622
4623 return emit_RRF2(p, 0xb9520000, m3, m4, r1, r2);
4624 }
4625
4626
4627 static UChar *
s390_emit_CXLGTR(UChar * p,UChar m3,UChar m4,UChar r1,UChar r2)4628 s390_emit_CXLGTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4629 {
4630 vassert(m4 == 0);
4631 vassert(s390_host_has_dfp);
4632 vassert(s390_host_has_fpext);
4633
4634 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4635 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cxlgtr", r1, m3, r2, m4);
4636
4637 return emit_RRF2(p, 0xb95a0000, m3, m4, r1, r2);
4638 }
4639
4640
4641 static UChar *
s390_emit_CEDTR(UChar * p,UChar r1,UChar r2)4642 s390_emit_CEDTR(UChar *p, UChar r1, UChar r2)
4643 {
4644 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4645 s390_disasm(ENC3(MNM, FPR, FPR), "cedtr", r1, r2);
4646
4647 return emit_RRE(p, 0xb3f40000, r1, r2);
4648 }
4649
4650
4651 static UChar *
s390_emit_CEXTR(UChar * p,UChar r1,UChar r2)4652 s390_emit_CEXTR(UChar *p, UChar r1, UChar r2)
4653 {
4654 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4655 s390_disasm(ENC3(MNM, FPR, FPR), "cextr", r1, r2);
4656
4657 return emit_RRE(p, 0xb3fc0000, r1, r2);
4658 }
4659
4660
4661 static UChar *
s390_emit_CFDTR(UChar * p,UChar m3,UChar m4,UChar r1,UChar r2)4662 s390_emit_CFDTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4663 {
4664 vassert(m4 == 0);
4665 vassert(s390_host_has_dfp);
4666 vassert(s390_host_has_fpext);
4667
4668 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4669 s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "cfdtr", r1, m3, r2, m4);
4670
4671 return emit_RRF2(p, 0xb9410000, m3, m4, r1, r2);
4672 }
4673
4674
4675 static UChar *
s390_emit_CFXTR(UChar * p,UChar m3,UChar m4,UChar r1,UChar r2)4676 s390_emit_CFXTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4677 {
4678 vassert(m4 == 0);
4679 vassert(s390_host_has_dfp);
4680 vassert(s390_host_has_fpext);
4681
4682 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4683 s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "cfxtr", r1, m3, r2, m4);
4684
4685 return emit_RRF2(p, 0xb9490000, m3, m4, r1, r2);
4686 }
4687
4688
4689 static UChar *
s390_emit_CGDTR(UChar * p,UChar m3,UChar m4,UChar r1,UChar r2)4690 s390_emit_CGDTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4691 {
4692 vassert(s390_host_has_dfp);
4693 vassert(m4 == 0);
4694 vassert(s390_host_has_fpext || m3 < 1 || m3 > 7);
4695
4696 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4697 s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cgdtr", r1, m3, r2);
4698
4699 return emit_RRF2(p, 0xb3e10000, m3, m4, r1, r2);
4700 }
4701
4702
4703 static UChar *
s390_emit_CGXTR(UChar * p,UChar m3,UChar m4,UChar r1,UChar r2)4704 s390_emit_CGXTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4705 {
4706 vassert(s390_host_has_dfp);
4707 vassert(m4 == 0);
4708 vassert(s390_host_has_fpext || m3 < 1 || m3 > 7);
4709
4710 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4711 s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cgxtr", r1, m3, r2);
4712
4713 return emit_RRF2(p, 0xb3e90000, m3, m4, r1, r2);
4714 }
4715
4716
4717 static UChar *
s390_emit_CLFDTR(UChar * p,UChar m3,UChar m4,UChar r1,UChar r2)4718 s390_emit_CLFDTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4719 {
4720 vassert(m4 == 0);
4721 vassert(s390_host_has_dfp);
4722 vassert(s390_host_has_fpext);
4723
4724 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4725 s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clfdtr", r1, m3, r2, m4);
4726
4727 return emit_RRF2(p, 0xb9430000, m3, m4, r1, r2);
4728 }
4729
4730
4731 static UChar *
s390_emit_CLFXTR(UChar * p,UChar m3,UChar m4,UChar r1,UChar r2)4732 s390_emit_CLFXTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4733 {
4734 vassert(m4 == 0);
4735 vassert(s390_host_has_dfp);
4736 vassert(s390_host_has_fpext);
4737
4738 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4739 s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clfxtr", r1, m3, r2, m4);
4740
4741 return emit_RRF2(p, 0xb94b0000, m3, m4, r1, r2);
4742 }
4743
4744
4745 static UChar *
s390_emit_CLGDTR(UChar * p,UChar m3,UChar m4,UChar r1,UChar r2)4746 s390_emit_CLGDTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4747 {
4748 vassert(m4 == 0);
4749 vassert(s390_host_has_dfp);
4750 vassert(s390_host_has_fpext);
4751
4752 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4753 s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clgdtr", r1, m3, r2, m4);
4754
4755 return emit_RRF2(p, 0xb9420000, m3, m4, r1, r2);
4756 }
4757
4758
4759 static UChar *
s390_emit_CLGXTR(UChar * p,UChar m3,UChar m4,UChar r1,UChar r2)4760 s390_emit_CLGXTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4761 {
4762 vassert(m4 == 0);
4763 vassert(s390_host_has_dfp);
4764 vassert(s390_host_has_fpext);
4765
4766 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4767 s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clgxtr", r1, m3, r2, m4);
4768
4769 return emit_RRF2(p, 0xb94a0000, m3, m4, r1, r2);
4770 }
4771
4772
4773 static UChar *
s390_emit_DDTRA(UChar * p,UChar r3,UChar m4,UChar r1,UChar r2)4774 s390_emit_DDTRA(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
4775 {
4776 vassert(s390_host_has_dfp);
4777 vassert(m4 == 0 || s390_host_has_fpext);
4778 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
4779 if (m4 == 0)
4780 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "ddtr", r1, r2, r3);
4781 else
4782 s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "ddtra", r1, r2, r3, m4);
4783 }
4784
4785 return emit_RRF4(p, 0xb3d10000, r3, m4, r1, r2);
4786 }
4787
4788
4789 static UChar *
s390_emit_DXTRA(UChar * p,UChar r3,UChar m4,UChar r1,UChar r2)4790 s390_emit_DXTRA(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
4791 {
4792 vassert(s390_host_has_dfp);
4793 vassert(m4 == 0 || s390_host_has_fpext);
4794 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
4795 if (m4 == 0)
4796 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "dxtr", r1, r2, r3);
4797 else
4798 s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "dxtra", r1, r2, r3, m4);
4799 }
4800
4801 return emit_RRF4(p, 0xb3d90000, r3, m4, r1, r2);
4802 }
4803
4804
4805 static UChar *
s390_emit_EEDTR(UChar * p,UChar r1,UChar r2)4806 s390_emit_EEDTR(UChar *p, UChar r1, UChar r2)
4807 {
4808 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4809 s390_disasm(ENC3(MNM, GPR, FPR), "eedtr", r1, r2);
4810
4811 return emit_RRE(p, 0xb3e50000, r1, r2);
4812 }
4813
4814
4815 static UChar *
s390_emit_EEXTR(UChar * p,UChar r1,UChar r2)4816 s390_emit_EEXTR(UChar *p, UChar r1, UChar r2)
4817 {
4818 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4819 s390_disasm(ENC3(MNM, GPR, FPR), "eextr", r1, r2);
4820
4821 return emit_RRE(p, 0xb3ed0000, r1, r2);
4822 }
4823
4824
4825 static UChar *
s390_emit_ESDTR(UChar * p,UChar r1,UChar r2)4826 s390_emit_ESDTR(UChar *p, UChar r1, UChar r2)
4827 {
4828 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4829 s390_disasm(ENC3(MNM, GPR, FPR), "esdtr", r1, r2);
4830
4831 return emit_RRE(p, 0xb3e70000, r1, r2);
4832 }
4833
4834
4835 static UChar *
s390_emit_ESXTR(UChar * p,UChar r1,UChar r2)4836 s390_emit_ESXTR(UChar *p, UChar r1, UChar r2)
4837 {
4838 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4839 s390_disasm(ENC3(MNM, GPR, FPR), "esxtr", r1, r2);
4840
4841 return emit_RRE(p, 0xb3ef0000, r1, r2);
4842 }
4843
4844
4845 static UChar *
s390_emit_IEDTR(UChar * p,UChar r3,UChar r1,UChar r2)4846 s390_emit_IEDTR(UChar *p, UChar r3, UChar r1, UChar r2)
4847 {
4848 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4849 s390_disasm(ENC4(MNM, FPR, FPR, GPR), "iedtr", r1, r3, r2);
4850
4851 return emit_RRF(p, 0xb3f60000, r3, r1, r2);
4852 }
4853
4854
4855 static UChar *
s390_emit_IEXTR(UChar * p,UChar r3,UChar r1,UChar r2)4856 s390_emit_IEXTR(UChar *p, UChar r3, UChar r1, UChar r2)
4857 {
4858 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4859 s390_disasm(ENC4(MNM, FPR, FPR, GPR), "iextr", r1, r3, r2);
4860
4861 return emit_RRF(p, 0xb3fe0000, r3, r1, r2);
4862 }
4863
4864
4865 static UChar *
s390_emit_LDETR(UChar * p,UChar m4,UChar r1,UChar r2)4866 s390_emit_LDETR(UChar *p, UChar m4, UChar r1, UChar r2)
4867 {
4868 vassert(s390_host_has_dfp);
4869 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4870 s390_disasm(ENC4(MNM, FPR, FPR, UINT), "ldetr", r1, r2, m4);
4871
4872 return emit_RRF5(p, 0xb3d40000, m4, r1, r2);
4873 }
4874
4875
4876 static UChar *
s390_emit_LXDTR(UChar * p,UChar m4,UChar r1,UChar r2)4877 s390_emit_LXDTR(UChar *p, UChar m4, UChar r1, UChar r2)
4878 {
4879 vassert(s390_host_has_dfp);
4880 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4881 s390_disasm(ENC4(MNM, FPR, FPR, UINT), "lxdtr", r1, r2, m4);
4882
4883 return emit_RRF5(p, 0xb3dc0000, m4, r1, r2);
4884 }
4885
4886
4887 static UChar *
s390_emit_LEDTR(UChar * p,UChar m3,UChar m4,UChar r1,UChar r2)4888 s390_emit_LEDTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4889 {
4890 vassert(s390_host_has_dfp);
4891 vassert(m4 == 0);
4892 vassert(s390_host_has_fpext || m3 < 1 || m3 > 7);
4893
4894 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4895 s390_disasm(ENC5(MNM, FPR, UINT, FPR, UINT), "ledtr", r1, m3, r2, m4);
4896
4897 return emit_RRF2(p, 0xb3d50000, m3, m4, r1, r2);
4898 }
4899
4900
4901 static UChar *
s390_emit_LDXTR(UChar * p,UChar m3,UChar m4,UChar r1,UChar r2)4902 s390_emit_LDXTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4903 {
4904 vassert(s390_host_has_dfp);
4905 vassert(m4 == 0);
4906 vassert(s390_host_has_fpext || m3 < 1 || m3 > 7);
4907
4908 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4909 s390_disasm(ENC5(MNM, FPR, UINT, FPR, UINT), "ldxtr", r1, m3, r2, m4);
4910
4911 return emit_RRF2(p, 0xb3dd0000, m3, m4, r1, r2);
4912 }
4913
4914
4915 static UChar *
s390_emit_MDTRA(UChar * p,UChar r3,UChar m4,UChar r1,UChar r2)4916 s390_emit_MDTRA(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
4917 {
4918 vassert(s390_host_has_dfp);
4919 vassert(m4 == 0 || s390_host_has_fpext);
4920 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
4921 if (m4 == 0)
4922 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "mdtr", r1, r2, r3);
4923 else
4924 s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "mdtra", r1, r2, r3, m4);
4925 }
4926
4927 return emit_RRF4(p, 0xb3d00000, r3, m4, r1, r2);
4928 }
4929
4930
4931 static UChar *
s390_emit_MXTRA(UChar * p,UChar r3,UChar m4,UChar r1,UChar r2)4932 s390_emit_MXTRA(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
4933 {
4934 vassert(s390_host_has_dfp);
4935 vassert(m4 == 0 || s390_host_has_fpext);
4936 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
4937 if (m4 == 0)
4938 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "mxtr", r1, r2, r3);
4939 else
4940 s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "mxtra", r1, r2, r3, m4);
4941 }
4942
4943 return emit_RRF4(p, 0xb3d80000, r3, m4, r1, r2);
4944 }
4945
4946
4947 static UChar *
emit_E(UChar * p,UInt op)4948 emit_E(UChar *p, UInt op)
4949 {
4950 ULong the_insn = op;
4951
4952 return emit_2bytes(p, the_insn);
4953 }
4954
4955
4956 static UChar *
s390_emit_PFPO(UChar * p)4957 s390_emit_PFPO(UChar *p)
4958 {
4959 vassert(s390_host_has_pfpo);
4960 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
4961 s390_disasm(ENC1(MNM), "pfpo");
4962 }
4963
4964 return emit_E(p, 0x010a);
4965 }
4966
4967
4968 static UChar *
s390_emit_QADTR(UChar * p,UChar r3,UChar m4,UChar r1,UChar r2)4969 s390_emit_QADTR(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
4970 {
4971 vassert(s390_host_has_dfp);
4972 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4973 s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "qadtr", r1, r3, r2, m4);
4974
4975 return emit_RRF4(p, 0xb3f50000, r3, m4, r1, r2);
4976 }
4977
4978
4979 static UChar *
s390_emit_QAXTR(UChar * p,UChar r3,UChar m4,UChar r1,UChar r2)4980 s390_emit_QAXTR(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
4981 {
4982 vassert(s390_host_has_dfp);
4983 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4984 s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "qaxtr", r1, r3, r2, m4);
4985
4986 return emit_RRF4(p, 0xb3fd0000, r3, m4, r1, r2);
4987 }
4988
4989
4990 static UChar *
s390_emit_RRDTR(UChar * p,UChar r3,UChar m4,UChar r1,UChar r2)4991 s390_emit_RRDTR(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
4992 {
4993 vassert(s390_host_has_dfp);
4994 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4995 s390_disasm(ENC5(MNM, FPR, FPR, GPR, UINT), "rrdtr", r1, r3, r2, m4);
4996
4997 return emit_RRF4(p, 0xb3f70000, r3, m4, r1, r2);
4998 }
4999
5000
5001 static UChar *
s390_emit_RRXTR(UChar * p,UChar r3,UChar m4,UChar r1,UChar r2)5002 s390_emit_RRXTR(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
5003 {
5004 vassert(s390_host_has_dfp);
5005 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
5006 s390_disasm(ENC5(MNM, FPR, FPR, GPR, UINT), "rrxtr", r1, r3, r2, m4);
5007
5008 return emit_RRF4(p, 0xb3ff0000, r3, m4, r1, r2);
5009 }
5010
5011
5012 static UChar *
s390_emit_SDTRA(UChar * p,UChar r3,UChar m4,UChar r1,UChar r2)5013 s390_emit_SDTRA(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
5014 {
5015 vassert(s390_host_has_dfp);
5016 vassert(m4 == 0 || s390_host_has_fpext);
5017 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
5018 if (m4 == 0)
5019 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "sdtr", r1, r2, r3);
5020 else
5021 s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "sdtra", r1, r2, r3, m4);
5022 }
5023
5024 return emit_RRF4(p, 0xb3d30000, r3, m4, r1, r2);
5025 }
5026
5027
5028 static UChar *
s390_emit_SXTRA(UChar * p,UChar r3,UChar m4,UChar r1,UChar r2)5029 s390_emit_SXTRA(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
5030 {
5031 vassert(s390_host_has_dfp);
5032 vassert(m4 == 0 || s390_host_has_fpext);
5033 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
5034 if (m4 == 0)
5035 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "sxtr", r1, r2, r3);
5036 else
5037 s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "sxtra", r1, r2, r3, m4);
5038 }
5039
5040 return emit_RRF4(p, 0xb3db0000, r3, m4, r1, r2);
5041 }
5042
5043
5044 static UChar *
s390_emit_SLDT(UChar * p,UChar r3,UChar r1,UChar r2)5045 s390_emit_SLDT(UChar *p, UChar r3, UChar r1, UChar r2)
5046 {
5047 vassert(s390_host_has_dfp);
5048 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
5049 s390_disasm(ENC4(MNM, FPR, FPR, UDXB), "sldt", r1, r3, 0, 0, r2);
5050
5051 return emit_RXF(p, 0xED0000000040ULL, r3, 0, r2, 0, r1);
5052 }
5053
5054
5055 static UChar *
s390_emit_SLXT(UChar * p,UChar r3,UChar r1,UChar r2)5056 s390_emit_SLXT(UChar *p, UChar r3, UChar r1, UChar r2)
5057 {
5058 vassert(s390_host_has_dfp);
5059 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
5060 s390_disasm(ENC4(MNM, FPR, FPR, UDXB), "slxt", r1, r3, 0, 0, r2);
5061
5062 return emit_RXF(p, 0xED0000000048ULL, r3, 0, r2, 0, r1);
5063 }
5064
5065
5066 static UChar *
s390_emit_SRDT(UChar * p,UChar r3,UChar r1,UChar r2)5067 s390_emit_SRDT(UChar *p, UChar r3, UChar r1, UChar r2)
5068 {
5069 vassert(s390_host_has_dfp);
5070 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
5071 s390_disasm(ENC4(MNM, FPR, FPR, UDXB), "srdt", r1, r3, 0, 0, r2);
5072
5073 return emit_RXF(p, 0xED0000000041ULL, r3, 0, r2, 0, r1);
5074 }
5075
5076
5077 static UChar *
s390_emit_SRXT(UChar * p,UChar r3,UChar r1,UChar r2)5078 s390_emit_SRXT(UChar *p, UChar r3, UChar r1, UChar r2)
5079 {
5080 vassert(s390_host_has_dfp);
5081 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
5082 s390_disasm(ENC4(MNM, FPR, FPR, UDXB), "srxt", r1, r3, 0, 0, r2);
5083
5084 return emit_RXF(p, 0xED0000000049ULL, r3, 0, r2, 0, r1);
5085 }
5086
5087
5088 static UChar *
s390_emit_LOCGR(UChar * p,UChar m3,UChar r1,UChar r2)5089 s390_emit_LOCGR(UChar *p, UChar m3, UChar r1, UChar r2)
5090 {
5091 vassert(s390_host_has_lsc);
5092 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
5093 s390_disasm(ENC4(MNM, GPR, GPR, UINT), "locgr", r1, r2, m3);
5094
5095 return emit_RRF3(p, 0xb9e20000, m3, r1, r2);
5096 }
5097
5098
5099 static UChar *
s390_emit_LOC(UChar * p,UChar r1,UChar m3,UChar b2,UShort dl2,UChar dh2)5100 s390_emit_LOC(UChar *p, UChar r1, UChar m3, UChar b2, UShort dl2, UChar dh2)
5101 {
5102 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
5103 s390_disasm(ENC4(MNM, GPR, UINT, SDXB), "loc", r1, m3, dh2, dl2, 0, b2);
5104
5105 return emit_RSY(p, 0xeb00000000f2ULL, r1, m3, b2, dl2, dh2);
5106 }
5107
5108
5109 static UChar *
s390_emit_LOCG(UChar * p,UChar r1,UChar m3,UChar b2,UShort dl2,UChar dh2)5110 s390_emit_LOCG(UChar *p, UChar r1, UChar m3, UChar b2, UShort dl2, UChar dh2)
5111 {
5112 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
5113 s390_disasm(ENC4(MNM, GPR, UINT, SDXB), "locg", r1, m3, dh2, dl2, 0, b2);
5114
5115 return emit_RSY(p, 0xeb00000000e2ULL, r1, m3, b2, dl2, dh2);
5116 }
5117
5118
5119 /* Provide a symbolic name for register "R0" */
5120 #define R0 0
5121
5122 /* Split up a 20-bit displacement into its high and low piece
5123 suitable for passing as function arguments */
5124 #define DISP20(d) (((UInt)d) & 0xFFF), ((((UInt)d) >> 12) & 0xFF)
5125
5126 /*---------------------------------------------------------------*/
5127 /*--- Helper functions ---*/
5128 /*---------------------------------------------------------------*/
5129
5130 static __inline__ Bool
uint_fits_signed_16bit(UInt val)5131 uint_fits_signed_16bit(UInt val)
5132 {
5133 UInt v = val & 0xFFFFu;
5134
5135 /* sign extend */
5136 v = (Int)(v << 16) >> 16;
5137
5138 return val == v;
5139 }
5140
5141
5142 static __inline__ Bool
ulong_fits_signed_16bit(ULong val)5143 ulong_fits_signed_16bit(ULong val)
5144 {
5145 ULong v = val & 0xFFFFu;
5146
5147 /* sign extend */
5148 v = (Long)(v << 48) >> 48;
5149
5150 return val == v;
5151 }
5152
5153
5154 static __inline__ Bool
ulong_fits_signed_32bit(ULong val)5155 ulong_fits_signed_32bit(ULong val)
5156 {
5157 ULong v = val & 0xFFFFFFFFu;
5158
5159 /* sign extend */
5160 v = (Long)(v << 32) >> 32;
5161
5162 return val == v;
5163 }
5164
5165
5166 static __inline__ Bool
ulong_fits_unsigned_32bit(ULong val)5167 ulong_fits_unsigned_32bit(ULong val)
5168 {
5169 return (val & 0xFFFFFFFFu) == val;
5170 }
5171
5172
5173 /* Load a 64-bit immediate VAL into register REG. */
5174 static UChar *
s390_emit_load_64imm(UChar * p,UChar reg,ULong val)5175 s390_emit_load_64imm(UChar *p, UChar reg, ULong val)
5176 {
5177 if (ulong_fits_signed_16bit(val)) {
5178 return s390_emit_LGHI(p, reg, val);
5179 }
5180
5181 if (s390_host_has_eimm) {
5182 if (ulong_fits_unsigned_32bit(val)) {
5183 return s390_emit_LLILF(p, reg, val);
5184 }
5185 if (ulong_fits_signed_32bit(val)) {
5186 /* LGFI's sign extension will recreate the correct 64-bit value */
5187 return s390_emit_LGFI(p, reg, val);
5188 }
5189 /* Do it in two steps: upper half [0:31] and lower half [32:63] */
5190 p = s390_emit_IIHF(p, reg, val >> 32);
5191 return s390_emit_IILF(p, reg, val & 0xFFFFFFFF);
5192 }
5193
5194 /* Fall back */
5195 if (ulong_fits_unsigned_32bit(val)) {
5196 p = s390_emit_LLILH(p, reg, (val >> 16) & 0xFFFF); /* sets val[32:47]
5197 val[0:31] = 0 */
5198 p = s390_emit_IILL(p, reg, val & 0xFFFF); /* sets val[48:63] */
5199 return p;
5200 }
5201
5202 p = s390_emit_IIHH(p, reg, (val >> 48) & 0xFFFF);
5203 p = s390_emit_IIHL(p, reg, (val >> 32) & 0xFFFF);
5204 p = s390_emit_IILH(p, reg, (val >> 16) & 0xFFFF);
5205 p = s390_emit_IILL(p, reg, val & 0xFFFF);
5206
5207 return p;
5208 }
5209
5210 /* Load a 32-bit immediate VAL into register REG. */
5211 static UChar *
s390_emit_load_32imm(UChar * p,UChar reg,UInt val)5212 s390_emit_load_32imm(UChar *p, UChar reg, UInt val)
5213 {
5214 if (uint_fits_signed_16bit(val)) {
5215 /* LHI's sign extension will recreate the correct 32-bit value */
5216 return s390_emit_LHI(p, reg, val);
5217 }
5218 if (s390_host_has_eimm) {
5219 return s390_emit_IILF(p, reg, val);
5220 }
5221 /* val[0:15] --> (val >> 16) & 0xFFFF
5222 val[16:31] --> val & 0xFFFF */
5223 p = s390_emit_IILH(p, reg, (val >> 16) & 0xFFFF);
5224 return s390_emit_IILL(p, reg, val & 0xFFFF);
5225 }
5226
5227 /*------------------------------------------------------------*/
5228 /*--- Wrapper functions ---*/
5229 /*------------------------------------------------------------*/
5230
5231 /* r1[32:63],r1+1[32:63] = r1+1[32:63] * memory[op2addr][0:31] */
5232 static UChar *
s390_emit_MFYw(UChar * p,UChar r1,UChar x,UChar b,UShort dl,UChar dh)5233 s390_emit_MFYw(UChar *p, UChar r1, UChar x, UChar b, UShort dl, UChar dh)
5234 {
5235 if (s390_host_has_gie) {
5236 return s390_emit_MFY(p, r1, x, b, dl, dh);
5237 }
5238
5239 /* Load from memory into R0, then MULTIPLY with R1 */
5240 p = s390_emit_LY(p, R0, x, b, dl, dh);
5241 return s390_emit_MR(p, r1, R0);
5242 }
5243
5244 /* r1[32:63] = r1[32:63] * memory[op2addr][0:15] */
5245 static UChar *
s390_emit_MHYw(UChar * p,UChar r1,UChar x,UChar b,UShort dl,UChar dh)5246 s390_emit_MHYw(UChar *p, UChar r1, UChar x, UChar b, UShort dl, UChar dh)
5247 {
5248 if (s390_host_has_gie) {
5249 return s390_emit_MHY(p, r1, x, b, dl, dh);
5250 }
5251
5252 /* Load from memory into R0, then MULTIPLY with R1 */
5253 p = s390_emit_LHY(p, R0, x, b, dl, dh);
5254 return s390_emit_MSR(p, r1, R0);
5255 }
5256
5257 /* r1[32:63] = r1[32:63] * i2 */
5258 static UChar *
s390_emit_MSFIw(UChar * p,UChar r1,UInt i2)5259 s390_emit_MSFIw(UChar *p, UChar r1, UInt i2)
5260 {
5261 if (s390_host_has_gie) {
5262 return s390_emit_MSFI(p, r1, i2);
5263 }
5264
5265 /* Load I2 into R0; then MULTIPLY R0 with R1 */
5266 p = s390_emit_load_32imm(p, R0, i2);
5267 return s390_emit_MSR(p, r1, R0);
5268 }
5269
5270
5271 /* r1[32:63] = r1[32:63] & i2 */
5272 static UChar *
s390_emit_NILFw(UChar * p,UChar r1,UInt i2)5273 s390_emit_NILFw(UChar *p, UChar r1, UInt i2)
5274 {
5275 if (s390_host_has_eimm) {
5276 return s390_emit_NILF(p, r1, i2);
5277 }
5278
5279 /* Load I2 into R0; then AND R0 with R1 */
5280 p = s390_emit_load_32imm(p, R0, i2);
5281 return s390_emit_NR(p, r1, R0);
5282 }
5283
5284
5285 /* r1[32:63] = r1[32:63] | i2 */
5286 static UChar *
s390_emit_OILFw(UChar * p,UChar r1,UInt i2)5287 s390_emit_OILFw(UChar *p, UChar r1, UInt i2)
5288 {
5289 if (s390_host_has_eimm) {
5290 return s390_emit_OILF(p, r1, i2);
5291 }
5292
5293 /* Load I2 into R0; then AND R0 with R1 */
5294 p = s390_emit_load_32imm(p, R0, i2);
5295 return s390_emit_OR(p, r1, R0);
5296 }
5297
5298
5299 /* r1[32:63] = r1[32:63] ^ i2 */
5300 static UChar *
s390_emit_XILFw(UChar * p,UChar r1,UInt i2)5301 s390_emit_XILFw(UChar *p, UChar r1, UInt i2)
5302 {
5303 if (s390_host_has_eimm) {
5304 return s390_emit_XILF(p, r1, i2);
5305 }
5306
5307 /* Load I2 into R0; then AND R0 with R1 */
5308 p = s390_emit_load_32imm(p, R0, i2);
5309 return s390_emit_XR(p, r1, R0);
5310 }
5311
5312
5313 /* r1[32:63] = sign_extend(r2[56:63]) */
5314 static UChar *
s390_emit_LBRw(UChar * p,UChar r1,UChar r2)5315 s390_emit_LBRw(UChar *p, UChar r1, UChar r2)
5316 {
5317 if (s390_host_has_eimm) {
5318 return s390_emit_LBR(p, r1, r2);
5319 }
5320
5321 p = s390_emit_LR(p, r1, r2); /* r1 = r2 */
5322 p = s390_emit_SLL(p, r1, R0, 24); /* r1 = r1 << 24 */
5323 return s390_emit_SRA(p, r1, R0, 24); /* r1 = r1 >>a 24 */
5324 }
5325
5326
5327 /* r1[0:63] = sign_extend(r2[56:63]) */
5328 static UChar *
s390_emit_LGBRw(UChar * p,UChar r1,UChar r2)5329 s390_emit_LGBRw(UChar *p, UChar r1, UChar r2)
5330 {
5331 if (s390_host_has_eimm) {
5332 return s390_emit_LGBR(p, r1, r2);
5333 }
5334
5335 p = s390_emit_LR(p, r1, r2); /* r1 = r2 */
5336 p = s390_emit_SLLG(p, r1, r1, R0, DISP20(56)); /* r1 = r1 << 56 */
5337 return s390_emit_SRAG(p, r1, r1, R0, DISP20(56)); /* r1 = r1 >>a 56 */
5338 }
5339
5340
5341 /* r1[32:63] = sign_extend(r2[48:63]) */
5342 static UChar *
s390_emit_LHRw(UChar * p,UChar r1,UChar r2)5343 s390_emit_LHRw(UChar *p, UChar r1, UChar r2)
5344 {
5345 if (s390_host_has_eimm) {
5346 return s390_emit_LHR(p, r1, r2);
5347 }
5348
5349 p = s390_emit_LR(p, r1, r2); /* r1 = r2 */
5350 p = s390_emit_SLL(p, r1, R0, 16); /* r1 = r1 << 16 */
5351 return s390_emit_SRA(p, r1, R0, 16); /* r1 = r1 >>a 16 */
5352 }
5353
5354
5355 /* r1[0:63] = sign_extend(r2[48:63]) */
5356 static UChar *
s390_emit_LGHRw(UChar * p,UChar r1,UChar r2)5357 s390_emit_LGHRw(UChar *p, UChar r1, UChar r2)
5358 {
5359 if (s390_host_has_eimm) {
5360 return s390_emit_LGHR(p, r1, r2);
5361 }
5362
5363 p = s390_emit_LR(p, r1, r2); /* r1 = r2 */
5364 p = s390_emit_SLLG(p, r1, r1, R0, DISP20(48)); /* r1 = r1 << 48 */
5365 return s390_emit_SRAG(p, r1, r1, R0, DISP20(48)); /* r1 = r1 >>a 48 */
5366 }
5367
5368
5369 /* r1[0:63] = sign_extend(i2) */
5370 static UChar *
s390_emit_LGFIw(UChar * p,UChar r1,UInt i2)5371 s390_emit_LGFIw(UChar *p, UChar r1, UInt i2)
5372 {
5373 if (s390_host_has_eimm) {
5374 return s390_emit_LGFI(p, r1, i2);
5375 }
5376
5377 p = s390_emit_load_32imm(p, R0, i2);
5378 return s390_emit_LGFR(p, r1, R0);
5379 }
5380
5381
5382 /* r1[32:63] = zero_extend($r2[56:63]) */
5383 static UChar *
s390_emit_LLCRw(UChar * p,UChar r1,UChar r2)5384 s390_emit_LLCRw(UChar *p, UChar r1, UChar r2)
5385 {
5386 if (s390_host_has_eimm) {
5387 return s390_emit_LLCR(p, r1, r2);
5388 }
5389
5390 p = s390_emit_LR(p, r1, r2);
5391 p = s390_emit_LHI(p, R0, 0xFF);
5392 return s390_emit_NR(p, r1, R0);
5393 }
5394
5395
5396 /* r1[0:63] = zero_extend($r2[56:63]) */
5397 static UChar *
s390_emit_LLGCRw(UChar * p,UChar r1,UChar r2)5398 s390_emit_LLGCRw(UChar *p, UChar r1, UChar r2)
5399 {
5400 if (s390_host_has_eimm) {
5401 return s390_emit_LLGCR(p, r1, r2);
5402 }
5403
5404 p = s390_emit_LR(p, r1, r2);
5405 p = s390_emit_LLILL(p, R0, 0xFF);
5406 return s390_emit_NGR(p, r1, R0);
5407 }
5408
5409
5410 /* r1[32:63] = zero_extend(r2[48:63]) */
5411 static UChar *
s390_emit_LLHRw(UChar * p,UChar r1,UChar r2)5412 s390_emit_LLHRw(UChar *p, UChar r1, UChar r2)
5413 {
5414 if (s390_host_has_eimm) {
5415 return s390_emit_LLHR(p, r1, r2);
5416 }
5417
5418 p = s390_emit_LR(p, r1, r2);
5419 p = s390_emit_LLILL(p, R0, 0xFFFF);
5420 return s390_emit_NR(p, r1, R0);
5421 }
5422
5423
5424 /* r1[0:63] = zero_extend(r2[48:63]) */
5425 static UChar *
s390_emit_LLGHRw(UChar * p,UChar r1,UChar r2)5426 s390_emit_LLGHRw(UChar *p, UChar r1, UChar r2)
5427 {
5428 if (s390_host_has_eimm) {
5429 return s390_emit_LLGHR(p, r1, r2);
5430 }
5431
5432 p = s390_emit_LR(p, r1, r2);
5433 p = s390_emit_LLILL(p, R0, 0xFFFF);
5434 return s390_emit_NGR(p, r1, R0);
5435 }
5436
5437
5438 /* r1[32:63] = zero_extend(mem[op2addr][0:7]) */
5439 static UChar *
s390_emit_LLCw(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl,UChar dh)5440 s390_emit_LLCw(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl, UChar dh)
5441 {
5442 if (s390_host_has_eimm) {
5443 return s390_emit_LLC(p, r1, x2, b2, dl, dh);
5444 }
5445
5446 if (dh == 0) {
5447 p = s390_emit_IC(p, r1, x2, b2, dl);
5448 } else {
5449 p = s390_emit_ICY(p, r1, x2, b2, dl, dh);
5450 }
5451 p = s390_emit_LLILL(p, R0, 0xFF);
5452 return s390_emit_NR(p, r1, R0);
5453 }
5454
5455
5456 /* r1[32:63] = zero_extend(mem[op2addr][0:15]) */
5457 static UChar *
s390_emit_LLHw(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl,UChar dh)5458 s390_emit_LLHw(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl, UChar dh)
5459 {
5460 if (s390_host_has_eimm) {
5461 return s390_emit_LLH(p, r1, x2, b2, dl, dh);
5462 }
5463
5464 p = s390_emit_LLGH(p, r1, x2, b2, dl, dh);
5465 p = s390_emit_LLILL(p, R0, 0xFFFF);
5466 return s390_emit_NR(p, r1, R0);
5467 }
5468
5469
5470 /* r1[0:63] = zero_extend(i2) */
5471 static UChar *
s390_emit_LLILFw(UChar * p,UChar r1,UInt i2)5472 s390_emit_LLILFw(UChar *p, UChar r1, UInt i2)
5473 {
5474 if (s390_host_has_eimm) {
5475 return s390_emit_LLILF(p, r1, i2);
5476 }
5477
5478 p = s390_emit_LLILH(p, r1, (i2 >> 16) & 0xFFFF); /* i2[0:15] */
5479 return s390_emit_OILL(p, r1, i2 & 0xFFFF);
5480 }
5481
5482
5483 /* r1[32:63] = r1[32:63] + i2 */
5484 static UChar *
s390_emit_AFIw(UChar * p,UChar r1,UInt i2)5485 s390_emit_AFIw(UChar *p, UChar r1, UInt i2)
5486 {
5487 if (s390_host_has_eimm) {
5488 return s390_emit_AFI(p, r1, i2);
5489 }
5490 /* Load 32 bit immediate to R0 then add */
5491 p = s390_emit_load_32imm(p, R0, i2);
5492 return s390_emit_AR(p, r1, R0);
5493 }
5494
5495
5496 /* r1[32:63] = r1[32:63] - i2 */
5497 static UChar *
s390_emit_SLFIw(UChar * p,UChar r1,UInt i2)5498 s390_emit_SLFIw(UChar *p, UChar r1, UInt i2)
5499 {
5500 if (s390_host_has_eimm) {
5501 return s390_emit_SLFI(p, r1, i2);
5502 }
5503
5504 /* Load 32 bit immediate to R0 then subtract */
5505 p = s390_emit_load_32imm(p, R0, i2);
5506 return s390_emit_SR(p, r1, R0);
5507 }
5508
5509
5510 /* r1[0:63] = r1[0:63] - zero_extend(i2) */
5511 static UChar *
s390_emit_SLGFIw(UChar * p,UChar r1,UInt i2)5512 s390_emit_SLGFIw(UChar *p, UChar r1, UInt i2)
5513 {
5514 if (s390_host_has_eimm) {
5515 return s390_emit_SLGFI(p, r1, i2);
5516 }
5517
5518 /* Load zero-extended 32 bit immediate to R0 then subtract */
5519 p = s390_emit_load_64imm(p, R0, i2);
5520 return s390_emit_SGR(p, r1, R0);
5521 }
5522
5523
5524 static UChar *
s390_emit_LTw(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl,UChar dh)5525 s390_emit_LTw(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl, UChar dh)
5526 {
5527 if (s390_host_has_eimm) {
5528 return s390_emit_LT(p, r1, x2, b2, dl, dh);
5529 }
5530 /* Load 32 bit from memory to R0 then compare */
5531 if (dh == 0) {
5532 p = s390_emit_L(p, R0, x2, b2, dl);
5533 } else {
5534 p = s390_emit_LY(p, R0, x2, b2, dl, dh);
5535 }
5536 return s390_emit_LTR(p, r1, R0);
5537 }
5538
5539
5540 static UChar *
s390_emit_LTGw(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl,UChar dh)5541 s390_emit_LTGw(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl, UChar dh)
5542 {
5543 if (s390_host_has_eimm) {
5544 return s390_emit_LTG(p, r1, x2, b2, dl, dh);
5545 }
5546 /* Load 64 bit from memory to R0 then compare */
5547 p = s390_emit_LG(p, R0, x2, b2, dl, dh);
5548 return s390_emit_LTGR(p, r1, R0);
5549 }
5550
5551
5552 static UChar *
s390_emit_CFIw(UChar * p,UChar r1,UInt i2)5553 s390_emit_CFIw(UChar *p, UChar r1, UInt i2)
5554 {
5555 if (s390_host_has_eimm) {
5556 return s390_emit_CFI(p, r1, i2);
5557 }
5558 /* Load 32 bit immediate to R0 then compare */
5559 p = s390_emit_load_32imm(p, R0, i2);
5560 return s390_emit_CR(p, r1, R0);
5561 }
5562
5563
5564 static UChar *
s390_emit_CLFIw(UChar * p,UChar r1,UInt i2)5565 s390_emit_CLFIw(UChar *p, UChar r1, UInt i2)
5566 {
5567 if (s390_host_has_eimm) {
5568 return s390_emit_CLFI(p, r1, i2);
5569 }
5570 /* Load 32 bit immediate to R0 then compare */
5571 p = s390_emit_load_32imm(p, R0, i2);
5572 return s390_emit_CLR(p, r1, R0);
5573 }
5574
5575
5576 static UChar *
s390_emit_LGDRw(UChar * p,UChar r1,UChar r2)5577 s390_emit_LGDRw(UChar *p, UChar r1, UChar r2)
5578 {
5579 if (s390_host_has_fgx) {
5580 return s390_emit_LGDR(p, r1, r2);
5581 }
5582
5583 /* Store the FPR at memory[sp - 8]. This is safe because SP grows towards
5584 smaller addresses and is 8-byte aligned. Then load the GPR from that
5585 memory location/ */
5586 p = s390_emit_STDY(p, r2, R0, S390_REGNO_STACK_POINTER, DISP20(-8));
5587 return s390_emit_LG(p, r1, R0, S390_REGNO_STACK_POINTER, DISP20(-8));
5588 }
5589
5590
5591 static UChar *
s390_emit_LDGRw(UChar * p,UChar r1,UChar r2)5592 s390_emit_LDGRw(UChar *p, UChar r1, UChar r2)
5593 {
5594 if (s390_host_has_fgx) {
5595 return s390_emit_LDGR(p, r1, r2);
5596 }
5597
5598 /* Store the GPR at memory[sp - 8]. This is safe because SP grows towards
5599 smaller addresses and is 8-byte aligned. Then load the FPR from that
5600 memory location/ */
5601 p = s390_emit_STG(p, r2, R0, S390_REGNO_STACK_POINTER, DISP20(-8));
5602 return s390_emit_LDY(p, r1, R0, S390_REGNO_STACK_POINTER, DISP20(-8));
5603 }
5604
5605
5606 static UChar *
s390_emit_VL(UChar * p,UChar v1,UChar x2,UChar b2,UShort d2)5607 s390_emit_VL(UChar *p, UChar v1, UChar x2, UChar b2, UShort d2)
5608 {
5609 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
5610 s390_disasm(ENC3(MNM, VR, UDXB), "vl", v1, d2, x2, b2);
5611
5612 return emit_VRX(p, 0xE70000000006ULL, v1, x2, b2, d2);
5613 }
5614
5615 static UChar *
s390_emit_VLR(UChar * p,UChar v1,UChar v2)5616 s390_emit_VLR(UChar *p, UChar v1, UChar v2)
5617 {
5618 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
5619 s390_disasm(ENC3(MNM, VR, UDXB), "vlr", v1, v2);
5620
5621 return emit_VRR_VV(p, 0xE70000000056ULL, v1, v2);
5622 }
5623
5624
5625 static UChar *
s390_emit_VST(UChar * p,UChar v1,UChar x2,UChar b2,UShort d2)5626 s390_emit_VST(UChar *p, UChar v1, UChar x2, UChar b2, UShort d2)
5627 {
5628 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
5629 s390_disasm(ENC3(MNM, VR, UDXB), "vst", v1, d2, x2, b2);
5630
5631 return emit_VRX(p, 0xE7000000000eULL, v1, x2, b2, d2);
5632 }
5633
5634
5635 static UChar *
s390_emit_VLGV(UChar * p,UChar r1,UChar b2,UShort d2,UChar v3,UChar m4)5636 s390_emit_VLGV(UChar *p, UChar r1, UChar b2, UShort d2, UChar v3, UChar m4)
5637 {
5638 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
5639 s390_disasm(ENC5(MNM, GPR, UDXB, VR, UINT), "vlgv", r1, d2, 0, b2, v3, m4);
5640
5641 return emit_VRS(p, 0xE70000000021ULL, r1, b2, d2, v3, m4);
5642 }
5643
5644
5645 static UChar *
s390_emit_VLVG(UChar * p,UChar v1,UChar b2,UShort d2,UChar r3,UChar m4)5646 s390_emit_VLVG(UChar *p, UChar v1, UChar b2, UShort d2, UChar r3, UChar m4)
5647 {
5648 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
5649 s390_disasm(ENC5(MNM, VR, UDXB, GPR, UINT), "vlvg", v1, d2, 0, b2, r3, m4);
5650
5651 return emit_VRS(p, 0xE70000000022ULL, v1, b2, d2, r3, m4);
5652 }
5653
5654
5655 static UChar *
s390_emit_VPERM(UChar * p,UChar v1,UChar v2,UChar v3,UChar v4)5656 s390_emit_VPERM(UChar *p, UChar v1, UChar v2, UChar v3, UChar v4)
5657 {
5658 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
5659 s390_disasm(ENC5(MNM, VR, VR, VR, VR), "vperm", v1, v2, v3, v4);
5660
5661 return emit_VRR_VVVV(p, 0xE7000000008cULL, v1, v2, v3, v4);
5662 }
5663
5664 static UChar *
s390_emit_VO(UChar * p,UChar v1,UChar v2,UChar v3)5665 s390_emit_VO(UChar *p, UChar v1, UChar v2, UChar v3)
5666 {
5667 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
5668 s390_disasm(ENC4(MNM, VR, VR, VR), "vo", v1, v2, v3);
5669
5670 return emit_VRR_VVV(p, 0xE7000000006aULL, v1, v2, v3);
5671 }
5672
5673 static UChar *
s390_emit_VX(UChar * p,UChar v1,UChar v2,UChar v3)5674 s390_emit_VX(UChar *p, UChar v1, UChar v2, UChar v3)
5675 {
5676 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
5677 s390_disasm(ENC4(MNM, VR, VR, VR), "vx", v1, v2, v3);
5678
5679 return emit_VRR_VVV(p, 0xE7000000006dULL, v1, v2, v3);
5680 }
5681
5682 static UChar *
s390_emit_VN(UChar * p,UChar v1,UChar v2,UChar v3)5683 s390_emit_VN(UChar *p, UChar v1, UChar v2, UChar v3)
5684 {
5685 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
5686 s390_disasm(ENC4(MNM, VR, VR, VR), "vn", v1, v2, v3);
5687
5688 return emit_VRR_VVV(p, 0xE70000000068ULL, v1, v2, v3);
5689 }
5690
5691 static UChar*
s390_emit_VCEQ(UChar * p,UChar v1,UChar v2,UChar v3,UChar m4)5692 s390_emit_VCEQ(UChar *p, UChar v1, UChar v2, UChar v3, UChar m4)
5693 {
5694 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
5695 s390_disasm(ENC5(MNM, VR, VR, VR, UINT), "vceq", v1, v2, v3, m4);
5696
5697 return emit_VRR_VVVM(p, 0xE700000000f8ULL, v1, v2, v3, m4);
5698 }
5699
5700
5701 static UChar *
s390_emit_VGBM(UChar * p,UChar v1,UShort i2)5702 s390_emit_VGBM(UChar *p, UChar v1, UShort i2)
5703 {
5704 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
5705 s390_disasm(ENC3(MNM, VR, UINT), "vgbm", v1, i2);
5706
5707 return emit_VRI_VI(p, 0xE70000000044ULL, v1, i2);
5708 }
5709
5710
5711 static UChar *
s390_emit_VPK(UChar * p,UChar v1,UChar v2,UChar v3,UChar m4)5712 s390_emit_VPK(UChar *p, UChar v1, UChar v2, UChar v3, UChar m4)
5713 {
5714 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
5715 s390_disasm(ENC5(MNM, VR, VR, VR, UINT), "vpk", v1, v2, v3, m4);
5716
5717 return emit_VRR_VVVM(p, 0xE70000000094ULL, v1, v2, v3, m4);
5718 }
5719
5720
5721 static UChar *
s390_emit_VPKS(UChar * p,UChar v1,UChar v2,UChar v3,UChar m4)5722 s390_emit_VPKS(UChar *p, UChar v1, UChar v2, UChar v3, UChar m4)
5723 {
5724 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
5725 s390_disasm(ENC6(MNM, VR, VR, VR, UINT, UINT), "vpks", v1, v2, v3, m4, 0);
5726
5727 return emit_VRR_VVVM(p, 0xE70000000097ULL, v1, v2, v3, m4);
5728 }
5729
5730
5731 static UChar *
s390_emit_VPKLS(UChar * p,UChar v1,UChar v2,UChar v3,UChar m4)5732 s390_emit_VPKLS(UChar *p, UChar v1, UChar v2, UChar v3, UChar m4)
5733 {
5734 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
5735 s390_disasm(ENC6(MNM, VR, VR, VR, UINT, UINT), "vpkls", v1, v2, v3, m4, 0);
5736
5737 return emit_VRR_VVVM(p, 0xE70000000095ULL, v1, v2, v3, m4);
5738 }
5739
5740
5741 static UChar *
s390_emit_VREP(UChar * p,UChar v1,UChar v3,UChar m3)5742 s390_emit_VREP(UChar *p, UChar v1, UChar v3, UChar m3)
5743 {
5744 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
5745 s390_disasm(ENC5(MNM, VR, VR, UINT, UINT), "vrep", v1, v3, 0, m3);
5746
5747 return emit_VRR_VVM(p, 0xE7000000004DULL, v1, v3, m3);
5748 }
5749
5750
5751
5752 static UChar *
s390_emit_VUPH(UChar * p,UChar v1,UChar v3,UChar m3)5753 s390_emit_VUPH(UChar *p, UChar v1, UChar v3, UChar m3)
5754 {
5755 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
5756 s390_disasm(ENC4(MNM, VR, VR, UINT), "vuph", v1, v3, m3);
5757
5758 return emit_VRR_VVM(p, 0xE700000000D7ULL, v1, v3, m3);
5759 }
5760
5761
5762 static UChar *
s390_emit_VUPLH(UChar * p,UChar v1,UChar v3,UChar m3)5763 s390_emit_VUPLH(UChar *p, UChar v1, UChar v3, UChar m3)
5764 {
5765 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
5766 s390_disasm(ENC4(MNM, VR, VR, UINT), "vuplh", v1, v3, m3);
5767
5768 return emit_VRR_VVM(p, 0xE700000000D5ULL, v1, v3, m3);
5769 }
5770
5771
5772 static UChar*
s390_emit_VMRH(UChar * p,UChar v1,UChar v2,UChar v3,UChar m4)5773 s390_emit_VMRH(UChar *p, UChar v1, UChar v2, UChar v3, UChar m4)
5774 {
5775 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
5776 s390_disasm(ENC5(MNM, VR, VR, VR, UINT), "vmrh", v1, v2, v3, m4);
5777
5778 return emit_VRR_VVVM(p, 0xE70000000061ULL, v1, v2, v3, m4);
5779 }
5780
5781
5782 static UChar*
s390_emit_VMRL(UChar * p,UChar v1,UChar v2,UChar v3,UChar m4)5783 s390_emit_VMRL(UChar *p, UChar v1, UChar v2, UChar v3, UChar m4)
5784 {
5785 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
5786 s390_disasm(ENC5(MNM, VR, VR, VR, UINT), "vmrl", v1, v2, v3, m4);
5787
5788 return emit_VRR_VVVM(p, 0xE70000000060ULL, v1, v2, v3, m4);
5789 }
5790
5791 static UChar *
s390_emit_VA(UChar * p,UChar v1,UChar v2,UChar v3,UChar m4)5792 s390_emit_VA(UChar *p, UChar v1, UChar v2, UChar v3, UChar m4)
5793 {
5794 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
5795 s390_disasm(ENC5(MNM, VR, VR, VR, UINT), "va", v1, v2, v3, m4);
5796
5797 return emit_VRR_VVVM(p, 0xE700000000f3ULL, v1, v2, v3, m4);
5798 }
5799
5800 static UChar *
s390_emit_VS(UChar * p,UChar v1,UChar v2,UChar v3,UChar m4)5801 s390_emit_VS(UChar *p, UChar v1, UChar v2, UChar v3, UChar m4)
5802 {
5803 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
5804 s390_disasm(ENC5(MNM, VR, VR, VR, UINT), "vs", v1, v2, v3, m4);
5805
5806 return emit_VRR_VVVM(p, 0xE700000000f7ULL, v1, v2, v3, m4);
5807 }
5808
5809 static UChar *
s390_emit_VNO(UChar * p,UChar v1,UChar v2,UChar v3)5810 s390_emit_VNO(UChar *p, UChar v1, UChar v2, UChar v3)
5811 {
5812 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
5813 s390_disasm(ENC4(MNM, VR, VR, VR), "vno", v1, v2, v3);
5814
5815 return emit_VRR_VVV(p, 0xE7000000006bULL, v1, v2, v3);
5816 }
5817
5818 static UChar *
s390_emit_VCH(UChar * p,UChar v1,UChar v2,UChar v3,UChar m4)5819 s390_emit_VCH(UChar *p, UChar v1, UChar v2, UChar v3, UChar m4)
5820 {
5821 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
5822 s390_disasm(ENC5(MNM, VR, VR, VR, UINT), "vch", v1, v2, v3, m4);
5823
5824 return emit_VRR_VVVM(p, 0xE700000000fbULL, v1, v2, v3, m4);
5825 }
5826
5827 static UChar *
s390_emit_VCHL(UChar * p,UChar v1,UChar v2,UChar v3,UChar m4)5828 s390_emit_VCHL(UChar *p, UChar v1, UChar v2, UChar v3, UChar m4)
5829 {
5830 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
5831 s390_disasm(ENC5(MNM, VR, VR, VR, UINT), "vchl", v1, v2, v3, m4);
5832
5833 return emit_VRR_VVVM(p, 0xE700000000f9ULL, v1, v2, v3, m4);
5834 }
5835
5836 static UChar *
s390_emit_VCLZ(UChar * p,UChar v1,UChar v2,UChar m4)5837 s390_emit_VCLZ(UChar *p, UChar v1, UChar v2, UChar m4)
5838 {
5839 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
5840 s390_disasm(ENC4(MNM, VR, VR, UINT), "vclz", v1, v2, m4);
5841
5842 return emit_VRR_VVM(p, 0xE70000000053ULL, v1, v2, m4);
5843 }
5844
5845 static UChar *
s390_emit_VCTZ(UChar * p,UChar v1,UChar v2,UChar m4)5846 s390_emit_VCTZ(UChar *p, UChar v1, UChar v2, UChar m4)
5847 {
5848 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
5849 s390_disasm(ENC4(MNM, VR, VR, UINT), "vctz", v1, v2, m4);
5850
5851 return emit_VRR_VVM(p, 0xE70000000052ULL, v1, v2, m4);
5852 }
5853
5854 static UChar *
s390_emit_VPOPCT(UChar * p,UChar v1,UChar v2,UChar m4)5855 s390_emit_VPOPCT(UChar *p, UChar v1, UChar v2, UChar m4)
5856 {
5857 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
5858 s390_disasm(ENC4(MNM, VR, VR, UINT), "vpopct", v1, v2, m4);
5859
5860 return emit_VRR_VVM(p, 0xE70000000050ULL, v1, v2, m4);
5861 }
5862
5863 static UChar *
s390_emit_VMX(UChar * p,UChar v1,UChar v2,UChar v3,UChar m4)5864 s390_emit_VMX(UChar *p, UChar v1, UChar v2, UChar v3, UChar m4)
5865 {
5866 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
5867 s390_disasm(ENC5(MNM, VR, VR, VR, UINT), "vmx", v1, v2, v3, m4);
5868
5869 return emit_VRR_VVVM(p, 0xE700000000ffULL, v1, v2, v3, m4);
5870 }
5871
5872 static UChar *
s390_emit_VMXL(UChar * p,UChar v1,UChar v2,UChar v3,UChar m4)5873 s390_emit_VMXL(UChar *p, UChar v1, UChar v2, UChar v3, UChar m4)
5874 {
5875 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
5876 s390_disasm(ENC5(MNM, VR, VR, VR, UINT), "vmxl", v1, v2, v3, m4);
5877
5878 return emit_VRR_VVVM(p, 0xE700000000fdULL, v1, v2, v3, m4);
5879 }
5880
5881 static UChar *
s390_emit_VMN(UChar * p,UChar v1,UChar v2,UChar v3,UChar m4)5882 s390_emit_VMN(UChar *p, UChar v1, UChar v2, UChar v3, UChar m4)
5883 {
5884 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
5885 s390_disasm(ENC5(MNM, VR, VR, VR, UINT), "vmn", v1, v2, v3, m4);
5886
5887 return emit_VRR_VVVM(p, 0xE700000000feULL, v1, v2, v3, m4);
5888 }
5889
5890 static UChar *
s390_emit_VMNL(UChar * p,UChar v1,UChar v2,UChar v3,UChar m4)5891 s390_emit_VMNL(UChar *p, UChar v1, UChar v2, UChar v3, UChar m4)
5892 {
5893 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
5894 s390_disasm(ENC5(MNM, VR, VR, VR, UINT), "vmnl", v1, v2, v3, m4);
5895
5896 return emit_VRR_VVVM(p, 0xE700000000fcULL, v1, v2, v3, m4);
5897 }
5898
5899 static UChar *
s390_emit_VAVG(UChar * p,UChar v1,UChar v2,UChar v3,UChar m4)5900 s390_emit_VAVG(UChar *p, UChar v1, UChar v2, UChar v3, UChar m4)
5901 {
5902 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
5903 s390_disasm(ENC5(MNM, VR, VR, VR, UINT), "vavg", v1, v2, v3, m4);
5904
5905 return emit_VRR_VVVM(p, 0xE700000000f2ULL, v1, v2, v3, m4);
5906 }
5907
5908 static UChar *
s390_emit_VAVGL(UChar * p,UChar v1,UChar v2,UChar v3,UChar m4)5909 s390_emit_VAVGL(UChar *p, UChar v1, UChar v2, UChar v3, UChar m4)
5910 {
5911 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
5912 s390_disasm(ENC5(MNM, VR, VR, VR, UINT), "vavgl", v1, v2, v3, m4);
5913
5914 return emit_VRR_VVVM(p, 0xE700000000f0ULL, v1, v2, v3, m4);
5915 }
5916
5917 static UChar *
s390_emit_VLP(UChar * p,UChar v1,UChar v2,UChar m3)5918 s390_emit_VLP(UChar *p, UChar v1, UChar v2, UChar m3)
5919 {
5920 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
5921 s390_disasm(ENC4(MNM, VR, VR, UINT), "vlp", v1, v2, m3);
5922
5923 return emit_VRR_VVM(p, 0xE700000000DFULL, v1, v2, m3);
5924 }
5925
5926 static UChar *
s390_emit_VMH(UChar * p,UChar v1,UChar v2,UChar v3,UChar m4)5927 s390_emit_VMH(UChar *p, UChar v1, UChar v2, UChar v3, UChar m4)
5928 {
5929 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
5930 s390_disasm(ENC5(MNM, VR, VR, VR, UINT), "vmh", v1, v2, v3, m4);
5931
5932 return emit_VRR_VVVM(p, 0xE700000000a3ULL, v1, v2, v3, m4);
5933 }
5934
5935 static UChar *
s390_emit_VMLH(UChar * p,UChar v1,UChar v2,UChar v3,UChar m4)5936 s390_emit_VMLH(UChar *p, UChar v1, UChar v2, UChar v3, UChar m4)
5937 {
5938 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
5939 s390_disasm(ENC5(MNM, VR, VR, VR, UINT), "vmlh", v1, v2, v3, m4);
5940
5941 return emit_VRR_VVVM(p, 0xE700000000a1ULL, v1, v2, v3, m4);
5942 }
5943
5944 static UChar *
s390_emit_VML(UChar * p,UChar v1,UChar v2,UChar v3,UChar m4)5945 s390_emit_VML(UChar *p, UChar v1, UChar v2, UChar v3, UChar m4)
5946 {
5947 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
5948 s390_disasm(ENC5(MNM, VR, VR, VR, UINT), "vml", v1, v2, v3, m4);
5949
5950 return emit_VRR_VVVM(p, 0xE700000000a2ULL, v1, v2, v3, m4);
5951 }
5952
5953 static UChar *
s390_emit_VME(UChar * p,UChar v1,UChar v2,UChar v3,UChar m4)5954 s390_emit_VME(UChar *p, UChar v1, UChar v2, UChar v3, UChar m4)
5955 {
5956 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
5957 s390_disasm(ENC5(MNM, VR, VR, VR, UINT), "vme", v1, v2, v3, m4);
5958
5959 return emit_VRR_VVVM(p, 0xE700000000a6ULL, v1, v2, v3, m4);
5960 }
5961
5962 static UChar *
s390_emit_VMLE(UChar * p,UChar v1,UChar v2,UChar v3,UChar m4)5963 s390_emit_VMLE(UChar *p, UChar v1, UChar v2, UChar v3, UChar m4)
5964 {
5965 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
5966 s390_disasm(ENC5(MNM, VR, VR, VR, UINT), "vmle", v1, v2, v3, m4);
5967
5968 return emit_VRR_VVVM(p, 0xE700000000a4ULL, v1, v2, v3, m4);
5969 }
5970
5971 static UChar *
s390_emit_VESLV(UChar * p,UChar v1,UChar v2,UChar v3,UChar m4)5972 s390_emit_VESLV(UChar *p, UChar v1, UChar v2, UChar v3, UChar m4)
5973 {
5974 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
5975 s390_disasm(ENC5(MNM, VR, VR, VR, UINT), "veslv", v1, v2, v3, m4);
5976
5977 return emit_VRR_VVVM(p, 0xE70000000070ULL, v1, v2, v3, m4);
5978 }
5979
5980 static UChar *
s390_emit_VESRAV(UChar * p,UChar v1,UChar v2,UChar v3,UChar m4)5981 s390_emit_VESRAV(UChar *p, UChar v1, UChar v2, UChar v3, UChar m4)
5982 {
5983 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
5984 s390_disasm(ENC5(MNM, VR, VR, VR, UINT), "vesrav", v1, v2, v3, m4);
5985
5986 return emit_VRR_VVVM(p, 0xE7000000007aULL, v1, v2, v3, m4);
5987 }
5988
5989 static UChar *
s390_emit_VESRLV(UChar * p,UChar v1,UChar v2,UChar v3,UChar m4)5990 s390_emit_VESRLV(UChar *p, UChar v1, UChar v2, UChar v3, UChar m4)
5991 {
5992 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
5993 s390_disasm(ENC5(MNM, VR, VR, VR, UINT), "vesrlv", v1, v2, v3, m4);
5994
5995 return emit_VRR_VVVM(p, 0xE70000000078ULL, v1, v2, v3, m4);
5996 }
5997
5998 static UChar *
s390_emit_VESL(UChar * p,UChar v1,UChar b2,UShort d2,UChar v3,UChar m4)5999 s390_emit_VESL(UChar *p, UChar v1, UChar b2, UShort d2, UChar v3, UChar m4)
6000 {
6001 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
6002 s390_disasm(ENC5(MNM, VR, UDXB, VR, UINT), "vesl", v1, d2, 0, b2, v3, m4);
6003
6004 return emit_VRS(p, 0xE70000000030ULL, v1, b2, d2, v3, m4);
6005 }
6006
6007 static UChar *
s390_emit_VESRA(UChar * p,UChar v1,UChar b2,UShort d2,UChar v3,UChar m4)6008 s390_emit_VESRA(UChar *p, UChar v1, UChar b2, UShort d2, UChar v3, UChar m4)
6009 {
6010 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
6011 s390_disasm(ENC5(MNM, VR, UDXB, VR, UINT), "vesra", v1, d2, 0, b2, v3, m4);
6012
6013 return emit_VRS(p, 0xE7000000003aULL, v1, b2, d2, v3, m4);
6014 }
6015
6016 static UChar *
s390_emit_VESRL(UChar * p,UChar v1,UChar b2,UShort d2,UChar v3,UChar m4)6017 s390_emit_VESRL(UChar *p, UChar v1, UChar b2, UShort d2, UChar v3, UChar m4)
6018 {
6019 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
6020 s390_disasm(ENC5(MNM, VR, UDXB, VR, UINT), "vesrl", v1, d2, 0, b2, v3, m4);
6021
6022 return emit_VRS(p, 0xE70000000038ULL, v1, b2, d2, v3, m4);
6023 }
6024
6025 static UChar *
s390_emit_VERLLV(UChar * p,UChar v1,UChar v2,UChar v3,UChar m4)6026 s390_emit_VERLLV(UChar *p, UChar v1, UChar v2, UChar v3, UChar m4)
6027 {
6028 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
6029 s390_disasm(ENC5(MNM, VR, VR, VR, UINT), "verllv", v1, v2, v3, m4);
6030
6031 return emit_VRR_VVVM(p, 0xE70000000073ULL, v1, v2, v3, m4);
6032 }
6033
6034 static UChar *
s390_emit_VSL(UChar * p,UChar v1,UChar v2,UChar v3)6035 s390_emit_VSL(UChar *p, UChar v1, UChar v2, UChar v3)
6036 {
6037 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
6038 s390_disasm(ENC4(MNM, VR, VR, VR), "vsl", v1, v2, v3);
6039
6040 return emit_VRR_VVV(p, 0xE70000000074ULL, v1, v2, v3);
6041 }
6042
6043 static UChar *
s390_emit_VSRL(UChar * p,UChar v1,UChar v2,UChar v3)6044 s390_emit_VSRL(UChar *p, UChar v1, UChar v2, UChar v3)
6045 {
6046 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
6047 s390_disasm(ENC4(MNM, VR, VR, VR), "vsrl", v1, v2, v3);
6048
6049 return emit_VRR_VVV(p, 0xE7000000007cULL, v1, v2, v3);
6050 }
6051
6052 static UChar *
s390_emit_VSRA(UChar * p,UChar v1,UChar v2,UChar v3)6053 s390_emit_VSRA(UChar *p, UChar v1, UChar v2, UChar v3)
6054 {
6055 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
6056 s390_disasm(ENC4(MNM, VR, VR, VR), "vsra", v1, v2, v3);
6057
6058 return emit_VRR_VVV(p, 0xE7000000007eULL, v1, v2, v3);
6059 }
6060
6061 static UChar *
s390_emit_VSLB(UChar * p,UChar v1,UChar v2,UChar v3)6062 s390_emit_VSLB(UChar *p, UChar v1, UChar v2, UChar v3)
6063 {
6064 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
6065 s390_disasm(ENC4(MNM, VR, VR, VR), "vslb", v1, v2, v3);
6066
6067 return emit_VRR_VVV(p, 0xE70000000075ULL, v1, v2, v3);
6068 }
6069
6070 static UChar *
s390_emit_VSRLB(UChar * p,UChar v1,UChar v2,UChar v3)6071 s390_emit_VSRLB(UChar *p, UChar v1, UChar v2, UChar v3)
6072 {
6073 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
6074 s390_disasm(ENC4(MNM, VR, VR, VR), "vsrlb", v1, v2, v3);
6075
6076 return emit_VRR_VVV(p, 0xE7000000007dULL, v1, v2, v3);
6077 }
6078
6079 static UChar *
s390_emit_VSRAB(UChar * p,UChar v1,UChar v2,UChar v3)6080 s390_emit_VSRAB(UChar *p, UChar v1, UChar v2, UChar v3)
6081 {
6082 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
6083 s390_disasm(ENC4(MNM, VR, VR, VR), "vsrab", v1, v2, v3);
6084
6085 return emit_VRR_VVV(p, 0xE7000000007fULL, v1, v2, v3);
6086 }
6087
6088 static UChar *
s390_emit_VSUM(UChar * p,UChar v1,UChar v2,UChar v3,UChar m4)6089 s390_emit_VSUM(UChar *p, UChar v1, UChar v2, UChar v3, UChar m4)
6090 {
6091 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
6092 s390_disasm(ENC5(MNM, VR, VR, VR, UINT), "vsum", v1, v2, v3, m4);
6093
6094 return emit_VRR_VVVM(p, 0xE70000000064ULL, v1, v2, v3, m4);
6095 }
6096
6097 static UChar *
s390_emit_VSUMG(UChar * p,UChar v1,UChar v2,UChar v3,UChar m4)6098 s390_emit_VSUMG(UChar *p, UChar v1, UChar v2, UChar v3, UChar m4)
6099 {
6100 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
6101 s390_disasm(ENC5(MNM, VR, VR, VR, UINT), "vsumg", v1, v2, v3, m4);
6102
6103 return emit_VRR_VVVM(p, 0xE70000000065ULL, v1, v2, v3, m4);
6104 }
6105
6106 static UChar *
s390_emit_VSUMQ(UChar * p,UChar v1,UChar v2,UChar v3,UChar m4)6107 s390_emit_VSUMQ(UChar *p, UChar v1, UChar v2, UChar v3, UChar m4)
6108 {
6109 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
6110 s390_disasm(ENC5(MNM, VR, VR, VR, UINT), "vsumq", v1, v2, v3, m4);
6111
6112 return emit_VRR_VVVM(p, 0xE70000000067ULL, v1, v2, v3, m4);
6113 }
6114
6115 static UChar *
s390_emit_VLVGP(UChar * p,UChar v1,UChar r2,UChar r3)6116 s390_emit_VLVGP(UChar *p, UChar v1, UChar r2, UChar r3)
6117 {
6118 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
6119 s390_disasm(ENC4(MNM, VR, GPR, GPR), "vlvgp", v1, r2, r3);
6120
6121 return emit_VRR_VRR(p, 0xE70000000062ULL, v1, r2, r3);
6122 }
6123
6124 static UChar *
s390_emit_VFPSO(UChar * p,UChar v1,UChar v2,UChar m3,UChar m4,UChar m5)6125 s390_emit_VFPSO(UChar *p, UChar v1, UChar v2, UChar m3, UChar m4, UChar m5)
6126 {
6127 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
6128 s390_disasm(ENC6(MNM, VR, VR, UINT, UINT, UINT), "vfpso", v1, v2, m3, m4,
6129 m5);
6130
6131 return emit_VRR_VVMMM(p, 0xE700000000CCULL, v1, v2, m3, m4, m5);
6132 }
6133
6134 static UChar *
s390_emit_VFA(UChar * p,UChar v1,UChar v2,UChar v3,UChar m4,UChar m5)6135 s390_emit_VFA(UChar *p, UChar v1, UChar v2, UChar v3, UChar m4, UChar m5)
6136 {
6137 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
6138 s390_disasm(ENC6(MNM, VR, VR, VR, UINT, UINT), "vfa", v1, v2, v3, m4, m5);
6139
6140 return emit_VRR_VVVMM(p, 0xE700000000e3ULL, v1, v2, v3, m4, m5);
6141 }
6142
6143 static UChar *
s390_emit_VFS(UChar * p,UChar v1,UChar v2,UChar v3,UChar m4,UChar m5)6144 s390_emit_VFS(UChar *p, UChar v1, UChar v2, UChar v3, UChar m4, UChar m5)
6145 {
6146 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
6147 s390_disasm(ENC6(MNM, VR, VR, VR, UINT, UINT), "vfs", v1, v2, v3, m4, m5);
6148
6149 return emit_VRR_VVVMM(p, 0xE700000000e2ULL, v1, v2, v3, m4, m5);
6150 }
6151
6152 static UChar *
s390_emit_VFM(UChar * p,UChar v1,UChar v2,UChar v3,UChar m4,UChar m5)6153 s390_emit_VFM(UChar *p, UChar v1, UChar v2, UChar v3, UChar m4, UChar m5)
6154 {
6155 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
6156 s390_disasm(ENC6(MNM, VR, VR, VR, UINT, UINT), "vfm", v1, v2, v3, m4, m5);
6157
6158 return emit_VRR_VVVMM(p, 0xE700000000e7ULL, v1, v2, v3, m4, m5);
6159 }
6160
6161 static UChar *
s390_emit_VFD(UChar * p,UChar v1,UChar v2,UChar v3,UChar m4,UChar m5)6162 s390_emit_VFD(UChar *p, UChar v1, UChar v2, UChar v3, UChar m4, UChar m5)
6163 {
6164 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
6165 s390_disasm(ENC6(MNM, VR, VR, VR, UINT, UINT), "vfd", v1, v2, v3, m4, m5);
6166
6167 return emit_VRR_VVVMM(p, 0xE700000000e5ULL, v1, v2, v3, m4, m5);
6168 }
6169
6170 static UChar *
s390_emit_VFSQ(UChar * p,UChar v1,UChar v2,UChar m3,UChar m4)6171 s390_emit_VFSQ(UChar *p, UChar v1, UChar v2, UChar m3, UChar m4)
6172 {
6173 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
6174 s390_disasm(ENC5(MNM, VR, VR, UINT, UINT), "vfsq", v1, v2, m3, m4);
6175
6176 return emit_VRR_VVMMM(p, 0xE700000000CEULL, v1, v2, m3, m4, 0);
6177 }
6178
6179 static UChar *
s390_emit_VFMA(UChar * p,UChar v1,UChar v2,UChar v3,UChar v4,UChar m5,UChar m6)6180 s390_emit_VFMA(UChar *p, UChar v1, UChar v2, UChar v3, UChar v4, UChar m5,
6181 UChar m6)
6182 {
6183 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
6184 s390_disasm(ENC7(MNM, VR, VR, VR, VR, UINT, UINT), "vfma",
6185 v1, v2, v3, v4, m5, m6);
6186
6187 return emit_VRRe_VVVVMM(p, 0xE7000000008fULL, v1, v2, v3, v4, m5, m6);
6188 }
6189
6190 static UChar *
s390_emit_VFMS(UChar * p,UChar v1,UChar v2,UChar v3,UChar v4,UChar m5,UChar m6)6191 s390_emit_VFMS(UChar *p, UChar v1, UChar v2, UChar v3, UChar v4, UChar m5,
6192 UChar m6)
6193 {
6194 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
6195 s390_disasm(ENC7(MNM, VR, VR, VR, VR, UINT, UINT), "vfms",
6196 v1, v2, v3, v4, m5, m6);
6197
6198 return emit_VRRe_VVVVMM(p, 0xE7000000008eULL, v1, v2, v3, v4, m5, m6);
6199 }
6200
6201 static UChar *
s390_emit_VFCE(UChar * p,UChar v1,UChar v2,UChar v3,UChar m4,UChar m5,UChar m6)6202 s390_emit_VFCE(UChar *p, UChar v1, UChar v2, UChar v3, UChar m4, UChar m5,
6203 UChar m6)
6204 {
6205 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
6206 s390_disasm(ENC7(MNM, VR, VR, VR, UINT, UINT, UINT), "vfce",
6207 v1, v2, v3, m4, m5, m6);
6208
6209 return emit_VRR_VVVMMM(p, 0xE700000000e8ULL, v1, v2, v3, m4, m5, m6);
6210 }
6211
6212 static UChar *
s390_emit_VFCH(UChar * p,UChar v1,UChar v2,UChar v3,UChar m4,UChar m5,UChar m6)6213 s390_emit_VFCH(UChar *p, UChar v1, UChar v2, UChar v3, UChar m4, UChar m5,
6214 UChar m6)
6215 {
6216 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
6217 s390_disasm(ENC7(MNM, VR, VR, VR, UINT, UINT, UINT), "vfch",
6218 v1, v2, v3, m4, m5, m6);
6219
6220 return emit_VRR_VVVMMM(p, 0xE700000000ebULL, v1, v2, v3, m4, m5, m6);
6221 }
6222
6223 static UChar *
s390_emit_VFCHE(UChar * p,UChar v1,UChar v2,UChar v3,UChar m4,UChar m5,UChar m6)6224 s390_emit_VFCHE(UChar *p, UChar v1, UChar v2, UChar v3, UChar m4, UChar m5,
6225 UChar m6)
6226 {
6227 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
6228 s390_disasm(ENC7(MNM, VR, VR, VR, UINT, UINT, UINT), "vfche",
6229 v1, v2, v3, m4, m5, m6);
6230
6231 return emit_VRR_VVVMMM(p, 0xE700000000eaULL, v1, v2, v3, m4, m5, m6);
6232 }
6233
6234 /*---------------------------------------------------------------*/
6235 /*--- Constructors for the various s390_insn kinds ---*/
6236 /*---------------------------------------------------------------*/
6237
6238 s390_insn *
s390_insn_load(UChar size,HReg dst,s390_amode * src)6239 s390_insn_load(UChar size, HReg dst, s390_amode *src)
6240 {
6241 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
6242
6243 insn->tag = S390_INSN_LOAD;
6244 insn->size = size;
6245 insn->variant.load.src = src;
6246 insn->variant.load.dst = dst;
6247
6248 vassert(size == 1 || size == 2 || size == 4 || size == 8 || size == 16);
6249
6250 return insn;
6251 }
6252
6253
6254 s390_insn *
s390_insn_store(UChar size,s390_amode * dst,HReg src)6255 s390_insn_store(UChar size, s390_amode *dst, HReg src)
6256 {
6257 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
6258
6259 insn->tag = S390_INSN_STORE;
6260 insn->size = size;
6261 insn->variant.store.src = src;
6262 insn->variant.store.dst = dst;
6263
6264 vassert(size == 1 || size == 2 || size == 4 || size == 8 || size == 16);
6265
6266 return insn;
6267 }
6268
6269
6270 s390_insn *
s390_insn_move(UChar size,HReg dst,HReg src)6271 s390_insn_move(UChar size, HReg dst, HReg src)
6272 {
6273 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
6274
6275 insn->tag = S390_INSN_MOVE;
6276 insn->size = size;
6277 insn->variant.move.src = src;
6278 insn->variant.move.dst = dst;
6279
6280 vassert(size == 1 || size == 2 || size == 4 || size == 8 || size ==16);
6281
6282 return insn;
6283 }
6284
6285
6286 s390_insn *
s390_insn_memcpy(UChar size,s390_amode * dst,s390_amode * src)6287 s390_insn_memcpy(UChar size, s390_amode *dst, s390_amode *src)
6288 {
6289 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
6290
6291 /* This insn will be mapped to MVC which requires base register
6292 plus 12-bit displacement */
6293 vassert(src->tag == S390_AMODE_B12);
6294 vassert(dst->tag == S390_AMODE_B12);
6295
6296 insn->tag = S390_INSN_MEMCPY;
6297 insn->size = size;
6298 insn->variant.memcpy.src = src;
6299 insn->variant.memcpy.dst = dst;
6300
6301 vassert(size == 1 || size == 2 || size == 4 || size == 8);
6302
6303 return insn;
6304 }
6305
6306
6307 s390_insn *
s390_insn_cond_move(UChar size,s390_cc_t cond,HReg dst,s390_opnd_RMI src)6308 s390_insn_cond_move(UChar size, s390_cc_t cond, HReg dst, s390_opnd_RMI src)
6309 {
6310 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
6311
6312 insn->tag = S390_INSN_COND_MOVE;
6313 insn->size = size;
6314 insn->variant.cond_move.cond = cond;
6315 insn->variant.cond_move.src = src;
6316 insn->variant.cond_move.dst = dst;
6317
6318 vassert(size == 1 || size == 2 || size == 4 || size == 8);
6319
6320 return insn;
6321 }
6322
6323
6324 s390_insn *
s390_insn_load_immediate(UChar size,HReg dst,ULong value)6325 s390_insn_load_immediate(UChar size, HReg dst, ULong value)
6326 {
6327 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
6328
6329 insn->tag = S390_INSN_LOAD_IMMEDIATE;
6330 insn->size = size;
6331 insn->variant.load_immediate.dst = dst;
6332 insn->variant.load_immediate.value = value;
6333
6334 return insn;
6335 }
6336
6337
6338 s390_insn *
s390_insn_alu(UChar size,s390_alu_t tag,HReg dst,s390_opnd_RMI op2)6339 s390_insn_alu(UChar size, s390_alu_t tag, HReg dst, s390_opnd_RMI op2)
6340 {
6341 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
6342
6343 insn->tag = S390_INSN_ALU;
6344 insn->size = size;
6345 insn->variant.alu.tag = tag;
6346 insn->variant.alu.dst = dst;
6347 insn->variant.alu.op2 = op2;
6348
6349 return insn;
6350 }
6351
6352
6353 s390_insn *
s390_insn_mul(UChar size,HReg dst_hi,HReg dst_lo,s390_opnd_RMI op2,Bool signed_multiply)6354 s390_insn_mul(UChar size, HReg dst_hi, HReg dst_lo, s390_opnd_RMI op2,
6355 Bool signed_multiply)
6356 {
6357 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
6358
6359 vassert(! hregIsVirtual(dst_hi));
6360 vassert(! hregIsVirtual(dst_lo));
6361
6362 insn->tag = signed_multiply ? S390_INSN_SMUL : S390_INSN_UMUL;
6363 insn->size = size;
6364 insn->variant.mul.dst_hi = dst_hi;
6365 insn->variant.mul.dst_lo = dst_lo;
6366 insn->variant.mul.op2 = op2;
6367
6368 return insn;
6369 }
6370
6371
6372 s390_insn *
s390_insn_div(UChar size,HReg op1_hi,HReg op1_lo,s390_opnd_RMI op2,Bool signed_divide)6373 s390_insn_div(UChar size, HReg op1_hi, HReg op1_lo, s390_opnd_RMI op2,
6374 Bool signed_divide)
6375 {
6376 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
6377
6378 vassert(size == 4 || size == 8);
6379 vassert(! hregIsVirtual(op1_hi));
6380 vassert(! hregIsVirtual(op1_lo));
6381
6382 insn->tag = signed_divide ? S390_INSN_SDIV : S390_INSN_UDIV;
6383 insn->size = size;
6384 insn->variant.div.op1_hi = op1_hi;
6385 insn->variant.div.op1_lo = op1_lo;
6386 insn->variant.div.op2 = op2;
6387
6388 return insn;
6389 }
6390
6391
6392 s390_insn *
s390_insn_divs(UChar size,HReg rem,HReg op1,s390_opnd_RMI op2)6393 s390_insn_divs(UChar size, HReg rem, HReg op1, s390_opnd_RMI op2)
6394 {
6395 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
6396
6397 vassert(size == 8);
6398 vassert(! hregIsVirtual(op1));
6399 vassert(! hregIsVirtual(rem));
6400
6401 insn->tag = S390_INSN_DIVS;
6402 insn->size = size;
6403 insn->variant.divs.rem = rem; /* remainder */
6404 insn->variant.divs.op1 = op1; /* also quotient */
6405 insn->variant.divs.op2 = op2;
6406
6407 return insn;
6408 }
6409
6410
6411 s390_insn *
s390_insn_clz(UChar size,HReg num_bits,HReg clobber,s390_opnd_RMI src)6412 s390_insn_clz(UChar size, HReg num_bits, HReg clobber, s390_opnd_RMI src)
6413 {
6414 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
6415
6416 vassert(size == 8);
6417 vassert(! hregIsVirtual(num_bits));
6418 vassert(! hregIsVirtual(clobber));
6419
6420 insn->tag = S390_INSN_CLZ;
6421 insn->size = size;
6422 insn->variant.clz.num_bits = num_bits;
6423 insn->variant.clz.clobber = clobber;
6424 insn->variant.clz.src = src;
6425
6426 return insn;
6427 }
6428
6429
6430 s390_insn *
s390_insn_unop(UChar size,s390_unop_t tag,HReg dst,s390_opnd_RMI opnd)6431 s390_insn_unop(UChar size, s390_unop_t tag, HReg dst, s390_opnd_RMI opnd)
6432 {
6433 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
6434
6435 insn->tag = S390_INSN_UNOP;
6436 insn->size = size;
6437 insn->variant.unop.tag = tag;
6438 insn->variant.unop.dst = dst;
6439 insn->variant.unop.src = opnd;
6440
6441 return insn;
6442 }
6443
6444
6445 s390_insn *
s390_insn_test(UChar size,s390_opnd_RMI src)6446 s390_insn_test(UChar size, s390_opnd_RMI src)
6447 {
6448 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
6449
6450 vassert(size == 4 || size == 8);
6451
6452 insn->tag = S390_INSN_TEST;
6453 insn->size = size;
6454 insn->variant.test.src = src;
6455
6456 return insn;
6457 }
6458
6459
6460 s390_insn *
s390_insn_cc2bool(HReg dst,s390_cc_t cond)6461 s390_insn_cc2bool(HReg dst, s390_cc_t cond)
6462 {
6463 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
6464
6465 insn->tag = S390_INSN_CC2BOOL;
6466 insn->size = 0; /* does not matter */
6467 insn->variant.cc2bool.cond = cond;
6468 insn->variant.cc2bool.dst = dst;
6469
6470 return insn;
6471 }
6472
6473
6474 s390_insn *
s390_insn_cas(UChar size,HReg op1,s390_amode * op2,HReg op3,HReg old_mem)6475 s390_insn_cas(UChar size, HReg op1, s390_amode *op2, HReg op3, HReg old_mem)
6476 {
6477 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
6478
6479 vassert(size == 4 || size == 8);
6480 vassert(hregNumber(op2->x) == 0);
6481 vassert(op2->tag == S390_AMODE_B12 || op2->tag == S390_AMODE_B20);
6482
6483 insn->tag = S390_INSN_CAS;
6484 insn->size = size;
6485 insn->variant.cas.op1 = op1;
6486 insn->variant.cas.op2 = op2;
6487 insn->variant.cas.op3 = op3;
6488 insn->variant.cas.old_mem = old_mem;
6489
6490 return insn;
6491 }
6492
6493
6494 s390_insn *
s390_insn_cdas(UChar size,HReg op1_high,HReg op1_low,s390_amode * op2,HReg op3_high,HReg op3_low,HReg old_mem_high,HReg old_mem_low,HReg scratch)6495 s390_insn_cdas(UChar size, HReg op1_high, HReg op1_low, s390_amode *op2,
6496 HReg op3_high, HReg op3_low, HReg old_mem_high, HReg old_mem_low,
6497 HReg scratch)
6498 {
6499 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
6500 s390_cdas *cdas = LibVEX_Alloc_inline(sizeof(s390_cdas));
6501
6502 vassert(size == 4 || size == 8);
6503 vassert(hregNumber(op2->x) == 0);
6504 vassert(hregNumber(scratch) == 1); /* r0,r1 used as scratch reg pair */
6505 vassert(op2->tag == S390_AMODE_B12 || op2->tag == S390_AMODE_B20);
6506
6507 insn->tag = S390_INSN_CDAS;
6508 insn->size = size;
6509 insn->variant.cdas.details = cdas;
6510
6511 cdas->op1_high = op1_high;
6512 cdas->op1_low = op1_low;
6513 cdas->op2 = op2;
6514 cdas->op3_high = op3_high;
6515 cdas->op3_low = op3_low;
6516 cdas->old_mem_high = old_mem_high;
6517 cdas->old_mem_low = old_mem_low;
6518 cdas->scratch = scratch;
6519
6520 return insn;
6521 }
6522
6523
6524 s390_insn *
s390_insn_compare(UChar size,HReg src1,s390_opnd_RMI src2,Bool signed_comparison)6525 s390_insn_compare(UChar size, HReg src1, s390_opnd_RMI src2,
6526 Bool signed_comparison)
6527 {
6528 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
6529
6530 vassert(size == 4 || size == 8);
6531
6532 insn->tag = S390_INSN_COMPARE;
6533 insn->size = size;
6534 insn->variant.compare.src1 = src1;
6535 insn->variant.compare.src2 = src2;
6536 insn->variant.compare.signed_comparison = signed_comparison;
6537
6538 return insn;
6539 }
6540
6541
6542 s390_insn *
s390_insn_helper_call(s390_cc_t cond,Addr64 target,UInt num_args,const HChar * name,RetLoc rloc)6543 s390_insn_helper_call(s390_cc_t cond, Addr64 target, UInt num_args,
6544 const HChar *name, RetLoc rloc)
6545 {
6546 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
6547 s390_helper_call *helper_call = LibVEX_Alloc_inline(sizeof(s390_helper_call));
6548
6549 insn->tag = S390_INSN_HELPER_CALL;
6550 insn->size = 0; /* does not matter */
6551 insn->variant.helper_call.details = helper_call;
6552
6553 helper_call->cond = cond;
6554 helper_call->target = target;
6555 helper_call->num_args = num_args;
6556 helper_call->name = name;
6557 helper_call->rloc = rloc;
6558
6559 vassert(is_sane_RetLoc(rloc));
6560
6561 return insn;
6562 }
6563
6564
6565 s390_insn *
s390_insn_bfp_triop(UChar size,s390_bfp_triop_t tag,HReg dst,HReg op2,HReg op3)6566 s390_insn_bfp_triop(UChar size, s390_bfp_triop_t tag, HReg dst, HReg op2,
6567 HReg op3)
6568 {
6569 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
6570
6571 vassert(size == 4 || size == 8);
6572
6573 insn->tag = S390_INSN_BFP_TRIOP;
6574 insn->size = size;
6575 insn->variant.bfp_triop.tag = tag;
6576 insn->variant.bfp_triop.dst = dst;
6577 insn->variant.bfp_triop.op2 = op2;
6578 insn->variant.bfp_triop.op3 = op3;
6579
6580 return insn;
6581 }
6582
6583
6584 s390_insn *
s390_insn_bfp_binop(UChar size,s390_bfp_binop_t tag,HReg dst,HReg op2)6585 s390_insn_bfp_binop(UChar size, s390_bfp_binop_t tag, HReg dst, HReg op2)
6586 {
6587 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
6588
6589 vassert(size == 4 || size == 8);
6590
6591 insn->tag = S390_INSN_BFP_BINOP;
6592 insn->size = size;
6593 insn->variant.bfp_binop.tag = tag;
6594 insn->variant.bfp_binop.dst_hi = dst;
6595 insn->variant.bfp_binop.op2_hi = op2;
6596 insn->variant.bfp_binop.dst_lo = INVALID_HREG;
6597 insn->variant.bfp_binop.op2_lo = INVALID_HREG;
6598
6599 return insn;
6600 }
6601
6602
6603 s390_insn *
s390_insn_bfp_unop(UChar size,s390_bfp_unop_t tag,HReg dst,HReg op)6604 s390_insn_bfp_unop(UChar size, s390_bfp_unop_t tag, HReg dst, HReg op)
6605 {
6606 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
6607
6608 vassert(size == 4 || size == 8);
6609
6610 insn->tag = S390_INSN_BFP_UNOP;
6611 insn->size = size;
6612 insn->variant.bfp_unop.tag = tag;
6613 insn->variant.bfp_unop.dst_hi = dst;
6614 insn->variant.bfp_unop.op_hi = op;
6615 insn->variant.bfp_unop.dst_lo = INVALID_HREG;
6616 insn->variant.bfp_unop.op_lo = INVALID_HREG;
6617
6618 return insn;
6619 }
6620
6621
6622 s390_insn *
s390_insn_bfp_compare(UChar size,HReg dst,HReg op1,HReg op2)6623 s390_insn_bfp_compare(UChar size, HReg dst, HReg op1, HReg op2)
6624 {
6625 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
6626
6627 vassert(size == 4 || size == 8);
6628
6629 insn->tag = S390_INSN_BFP_COMPARE;
6630 insn->size = size;
6631 insn->variant.bfp_compare.dst = dst;
6632 insn->variant.bfp_compare.op1_hi = op1;
6633 insn->variant.bfp_compare.op2_hi = op2;
6634 insn->variant.bfp_compare.op1_lo = INVALID_HREG;
6635 insn->variant.bfp_compare.op2_lo = INVALID_HREG;
6636
6637 return insn;
6638 }
6639
6640
6641 s390_insn *
s390_insn_bfp_convert(UChar size,s390_bfp_conv_t tag,HReg dst,HReg op,s390_bfp_round_t rounding_mode)6642 s390_insn_bfp_convert(UChar size, s390_bfp_conv_t tag, HReg dst, HReg op,
6643 s390_bfp_round_t rounding_mode)
6644 {
6645 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
6646
6647 vassert(size == 4 || size == 8);
6648
6649 insn->tag = S390_INSN_BFP_CONVERT;
6650 insn->size = size;
6651 insn->variant.bfp_convert.tag = tag;
6652 insn->variant.bfp_convert.dst_hi = dst;
6653 insn->variant.bfp_convert.op_hi = op;
6654 insn->variant.bfp_convert.dst_lo = INVALID_HREG;
6655 insn->variant.bfp_convert.op_lo = INVALID_HREG;
6656 insn->variant.bfp_convert.rounding_mode = rounding_mode;
6657
6658 return insn;
6659 }
6660
6661
6662 /* Check validity of a register pair for 128-bit FP. Valid register
6663 pairs are (0,2), (1,3), (4, 6), (5, 7), (8, 10), (9, 11), (12, 14),
6664 and (13, 15). */
6665 static Bool
is_valid_fp128_regpair(HReg hi,HReg lo)6666 is_valid_fp128_regpair(HReg hi, HReg lo)
6667 {
6668 UInt hi_regno = hregNumber(hi);
6669 UInt lo_regno = hregNumber(lo);
6670
6671 if (lo_regno != hi_regno + 2) return False;
6672 if ((hi_regno & 0x2) != 0) return False;
6673
6674 return True;
6675 }
6676
6677 s390_insn *
s390_insn_bfp128_binop(UChar size,s390_bfp_binop_t tag,HReg dst_hi,HReg dst_lo,HReg op2_hi,HReg op2_lo)6678 s390_insn_bfp128_binop(UChar size, s390_bfp_binop_t tag, HReg dst_hi,
6679 HReg dst_lo, HReg op2_hi, HReg op2_lo)
6680 {
6681 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
6682
6683 vassert(size == 16);
6684 vassert(is_valid_fp128_regpair(dst_hi, dst_lo));
6685 vassert(is_valid_fp128_regpair(op2_hi, op2_lo));
6686
6687 insn->tag = S390_INSN_BFP_BINOP;
6688 insn->size = size;
6689 insn->variant.bfp_binop.tag = tag;
6690 insn->variant.bfp_binop.dst_hi = dst_hi;
6691 insn->variant.bfp_binop.dst_lo = dst_lo;
6692 insn->variant.bfp_binop.op2_hi = op2_hi;
6693 insn->variant.bfp_binop.op2_lo = op2_lo;
6694
6695 return insn;
6696 }
6697
6698
6699 s390_insn *
s390_insn_bfp128_unop(UChar size,s390_bfp_unop_t tag,HReg dst_hi,HReg dst_lo,HReg op_hi,HReg op_lo)6700 s390_insn_bfp128_unop(UChar size, s390_bfp_unop_t tag, HReg dst_hi,
6701 HReg dst_lo, HReg op_hi, HReg op_lo)
6702 {
6703 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
6704
6705 vassert(size == 16);
6706 vassert(is_valid_fp128_regpair(dst_hi, dst_lo));
6707 vassert(is_valid_fp128_regpair(op_hi, op_lo));
6708
6709 insn->tag = S390_INSN_BFP_UNOP;
6710 insn->size = size;
6711 insn->variant.bfp_unop.tag = tag;
6712 insn->variant.bfp_unop.dst_hi = dst_hi;
6713 insn->variant.bfp_unop.dst_lo = dst_lo;
6714 insn->variant.bfp_unop.op_hi = op_hi;
6715 insn->variant.bfp_unop.op_lo = op_lo;
6716
6717 return insn;
6718 }
6719
6720
6721 s390_insn *
s390_insn_bfp128_compare(UChar size,HReg dst,HReg op1_hi,HReg op1_lo,HReg op2_hi,HReg op2_lo)6722 s390_insn_bfp128_compare(UChar size, HReg dst, HReg op1_hi, HReg op1_lo,
6723 HReg op2_hi, HReg op2_lo)
6724 {
6725 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
6726
6727 vassert(size == 16);
6728 vassert(is_valid_fp128_regpair(op1_hi, op1_lo));
6729 vassert(is_valid_fp128_regpair(op2_hi, op2_lo));
6730
6731 insn->tag = S390_INSN_BFP_COMPARE;
6732 insn->size = size;
6733 insn->variant.bfp_compare.dst = dst;
6734 insn->variant.bfp_compare.op1_hi = op1_hi;
6735 insn->variant.bfp_compare.op1_lo = op1_lo;
6736 insn->variant.bfp_compare.op2_hi = op2_hi;
6737 insn->variant.bfp_compare.op2_lo = op2_lo;
6738
6739 return insn;
6740 }
6741
6742
6743 s390_insn *
s390_insn_bfp128_convert(UChar size,s390_bfp_conv_t tag,HReg dst_hi,HReg dst_lo,HReg op_hi,HReg op_lo,s390_bfp_round_t rounding_mode)6744 s390_insn_bfp128_convert(UChar size, s390_bfp_conv_t tag, HReg dst_hi,
6745 HReg dst_lo, HReg op_hi, HReg op_lo,
6746 s390_bfp_round_t rounding_mode)
6747 {
6748 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
6749
6750 if (size == 16) {
6751 /* From smaller or equal size to 16 bytes */
6752 vassert(is_valid_fp128_regpair(dst_hi, dst_lo));
6753 vassert(hregIsInvalid(op_lo)
6754 || is_valid_fp128_regpair(op_hi, op_lo));
6755 } else {
6756 /* From 16 bytes to smaller size */
6757 vassert(is_valid_fp128_regpair(op_hi, op_lo));
6758 }
6759
6760 insn->tag = S390_INSN_BFP_CONVERT;
6761 insn->size = size;
6762 insn->variant.bfp_convert.tag = tag;
6763 insn->variant.bfp_convert.dst_hi = dst_hi;
6764 insn->variant.bfp_convert.dst_lo = dst_lo;
6765 insn->variant.bfp_convert.op_hi = op_hi;
6766 insn->variant.bfp_convert.op_lo = op_lo;
6767 insn->variant.bfp_convert.rounding_mode = rounding_mode;
6768
6769 return insn;
6770 }
6771
6772
6773 s390_insn *
s390_insn_bfp128_convert_to(UChar size,s390_bfp_conv_t tag,HReg dst_hi,HReg dst_lo,HReg op)6774 s390_insn_bfp128_convert_to(UChar size, s390_bfp_conv_t tag, HReg dst_hi,
6775 HReg dst_lo, HReg op)
6776 {
6777 /* Conversion to bfp128 never requires a rounding mode. Provide default
6778 rounding mode. It will not be used when emitting insns. */
6779 s390_bfp_round_t rounding_mode = S390_BFP_ROUND_NEAREST_EVEN;
6780
6781 return s390_insn_bfp128_convert(size, tag, dst_hi, dst_lo, op,
6782 INVALID_HREG, rounding_mode);
6783 }
6784
6785
6786 s390_insn *
s390_insn_bfp128_convert_from(UChar size,s390_bfp_conv_t tag,HReg dst_hi,HReg dst_lo,HReg op_hi,HReg op_lo,s390_bfp_round_t rounding_mode)6787 s390_insn_bfp128_convert_from(UChar size, s390_bfp_conv_t tag, HReg dst_hi,
6788 HReg dst_lo, HReg op_hi, HReg op_lo,
6789 s390_bfp_round_t rounding_mode)
6790 {
6791 return s390_insn_bfp128_convert(size, tag, dst_hi, dst_lo, op_hi, op_lo,
6792 rounding_mode);
6793 }
6794
6795
6796 s390_insn *
s390_insn_dfp_binop(UChar size,s390_dfp_binop_t tag,HReg dst,HReg op2,HReg op3,s390_dfp_round_t rounding_mode)6797 s390_insn_dfp_binop(UChar size, s390_dfp_binop_t tag, HReg dst, HReg op2,
6798 HReg op3, s390_dfp_round_t rounding_mode)
6799 {
6800 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
6801 s390_dfp_binop *dfp_binop = LibVEX_Alloc_inline(sizeof(s390_dfp_binop));
6802
6803 vassert(size == 8);
6804
6805 insn->tag = S390_INSN_DFP_BINOP;
6806 insn->size = size;
6807 insn->variant.dfp_binop.details = dfp_binop;
6808
6809 dfp_binop->tag = tag;
6810 dfp_binop->dst_hi = dst;
6811 dfp_binop->op2_hi = op2;
6812 dfp_binop->op3_hi = op3;
6813 dfp_binop->dst_lo = INVALID_HREG;
6814 dfp_binop->op2_lo = INVALID_HREG;
6815 dfp_binop->op3_lo = INVALID_HREG;
6816 dfp_binop->rounding_mode = rounding_mode;
6817
6818 return insn;
6819 }
6820
6821
6822 s390_insn *
s390_insn_dfp_unop(UChar size,s390_dfp_unop_t tag,HReg dst,HReg op)6823 s390_insn_dfp_unop(UChar size, s390_dfp_unop_t tag, HReg dst, HReg op)
6824 {
6825 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
6826
6827 vassert(size == 8);
6828
6829 insn->tag = S390_INSN_DFP_UNOP;
6830 insn->size = size;
6831 insn->variant.dfp_unop.tag = tag;
6832 insn->variant.dfp_unop.dst_hi = dst;
6833 insn->variant.dfp_unop.op_hi = op;
6834 insn->variant.dfp_unop.dst_lo = INVALID_HREG;
6835 insn->variant.dfp_unop.op_lo = INVALID_HREG;
6836
6837 return insn;
6838 }
6839
6840
6841 s390_insn *
s390_insn_dfp_intop(UChar size,s390_dfp_intop_t tag,HReg dst,HReg op2,HReg op3)6842 s390_insn_dfp_intop(UChar size, s390_dfp_intop_t tag, HReg dst, HReg op2,
6843 HReg op3)
6844 {
6845 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
6846
6847 vassert(size == 8);
6848
6849 insn->tag = S390_INSN_DFP_INTOP;
6850 insn->size = size;
6851 insn->variant.dfp_intop.tag = tag;
6852 insn->variant.dfp_intop.dst_hi = dst;
6853 insn->variant.dfp_intop.op2 = op2;
6854 insn->variant.dfp_intop.op3_hi = op3;
6855 insn->variant.dfp_intop.dst_lo = INVALID_HREG;
6856 insn->variant.dfp_intop.op3_lo = INVALID_HREG;
6857
6858 return insn;
6859 }
6860
6861
6862 s390_insn *
s390_insn_dfp_compare(UChar size,s390_dfp_cmp_t tag,HReg dst,HReg op1,HReg op2)6863 s390_insn_dfp_compare(UChar size, s390_dfp_cmp_t tag, HReg dst,
6864 HReg op1, HReg op2)
6865 {
6866 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
6867
6868 vassert(size == 8);
6869
6870 insn->tag = S390_INSN_DFP_COMPARE;
6871 insn->size = size;
6872 insn->variant.dfp_compare.tag = tag;
6873 insn->variant.dfp_compare.dst = dst;
6874 insn->variant.dfp_compare.op1_hi = op1;
6875 insn->variant.dfp_compare.op2_hi = op2;
6876 insn->variant.dfp_compare.op1_lo = INVALID_HREG;
6877 insn->variant.dfp_compare.op2_lo = INVALID_HREG;
6878
6879 return insn;
6880 }
6881
6882
6883 s390_insn *
s390_insn_dfp_convert(UChar size,s390_dfp_conv_t tag,HReg dst,HReg op,s390_dfp_round_t rounding_mode)6884 s390_insn_dfp_convert(UChar size, s390_dfp_conv_t tag, HReg dst, HReg op,
6885 s390_dfp_round_t rounding_mode)
6886 {
6887 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
6888
6889 vassert(size == 4 || size == 8);
6890
6891 insn->tag = S390_INSN_DFP_CONVERT;
6892 insn->size = size;
6893 insn->variant.dfp_convert.tag = tag;
6894 insn->variant.dfp_convert.dst_hi = dst;
6895 insn->variant.dfp_convert.op_hi = op;
6896 insn->variant.dfp_convert.dst_lo = INVALID_HREG;
6897 insn->variant.dfp_convert.op_lo = INVALID_HREG;
6898 insn->variant.dfp_convert.rounding_mode = rounding_mode;
6899
6900 return insn;
6901 }
6902
6903
6904 s390_insn *
s390_insn_dfp_reround(UChar size,HReg dst,HReg op2,HReg op3,s390_dfp_round_t rounding_mode)6905 s390_insn_dfp_reround(UChar size, HReg dst, HReg op2, HReg op3,
6906 s390_dfp_round_t rounding_mode)
6907 {
6908 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
6909
6910 vassert(size == 8);
6911
6912 insn->tag = S390_INSN_DFP_REROUND;
6913 insn->size = size;
6914 insn->variant.dfp_reround.dst_hi = dst;
6915 insn->variant.dfp_reround.op2 = op2;
6916 insn->variant.dfp_reround.op3_hi = op3;
6917 insn->variant.dfp_reround.dst_lo = INVALID_HREG;
6918 insn->variant.dfp_reround.op3_lo = INVALID_HREG;
6919 insn->variant.dfp_reround.rounding_mode = rounding_mode;
6920
6921 return insn;
6922 }
6923
6924
6925 s390_insn *
s390_insn_fp_convert(UChar size,s390_fp_conv_t tag,HReg dst,HReg op,HReg r1,s390_dfp_round_t rounding_mode)6926 s390_insn_fp_convert(UChar size, s390_fp_conv_t tag, HReg dst, HReg op,
6927 HReg r1, s390_dfp_round_t rounding_mode)
6928 {
6929 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
6930 s390_fp_convert *fp_convert = LibVEX_Alloc_inline(sizeof(s390_fp_convert));
6931
6932 vassert(size == 4 || size == 8);
6933
6934 insn->tag = S390_INSN_FP_CONVERT;
6935 insn->size = size;
6936 insn->variant.fp_convert.details = fp_convert;
6937
6938 fp_convert->tag = tag;
6939 fp_convert->dst_hi = dst;
6940 fp_convert->op_hi = op;
6941 fp_convert->r1 = r1;
6942 fp_convert->dst_lo = INVALID_HREG;
6943 fp_convert->op_lo = INVALID_HREG;
6944 fp_convert->rounding_mode = rounding_mode;
6945
6946 return insn;
6947 }
6948
6949
6950 s390_insn *
s390_insn_fp128_convert(UChar size,s390_fp_conv_t tag,HReg dst_hi,HReg dst_lo,HReg op_hi,HReg op_lo,HReg r1,s390_dfp_round_t rounding_mode)6951 s390_insn_fp128_convert(UChar size, s390_fp_conv_t tag, HReg dst_hi,
6952 HReg dst_lo, HReg op_hi, HReg op_lo, HReg r1,
6953 s390_dfp_round_t rounding_mode)
6954 {
6955 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
6956 s390_fp_convert *fp_convert = LibVEX_Alloc_inline(sizeof(s390_fp_convert));
6957
6958 vassert(size == 16);
6959
6960 insn->tag = S390_INSN_FP_CONVERT;
6961 insn->size = size;
6962 insn->variant.fp_convert.details = fp_convert;
6963
6964 fp_convert->tag = tag;
6965 fp_convert->dst_hi = dst_hi;
6966 fp_convert->dst_lo = dst_lo;
6967 fp_convert->op_hi = op_hi;
6968 fp_convert->r1 = r1;
6969 fp_convert->op_lo = op_lo;
6970 fp_convert->rounding_mode = rounding_mode;
6971
6972 return insn;
6973 }
6974
6975
6976 s390_insn *
s390_insn_dfp128_binop(UChar size,s390_dfp_binop_t tag,HReg dst_hi,HReg dst_lo,HReg op2_hi,HReg op2_lo,HReg op3_hi,HReg op3_lo,s390_dfp_round_t rounding_mode)6977 s390_insn_dfp128_binop(UChar size, s390_dfp_binop_t tag, HReg dst_hi,
6978 HReg dst_lo, HReg op2_hi, HReg op2_lo, HReg op3_hi,
6979 HReg op3_lo, s390_dfp_round_t rounding_mode)
6980 {
6981 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
6982 s390_dfp_binop *dfp_binop = LibVEX_Alloc_inline(sizeof(s390_dfp_binop));
6983
6984 vassert(size == 16);
6985 vassert(is_valid_fp128_regpair(dst_hi, dst_lo));
6986 vassert(is_valid_fp128_regpair(op2_hi, op2_lo));
6987 vassert(is_valid_fp128_regpair(op3_hi, op3_lo));
6988
6989 insn->tag = S390_INSN_DFP_BINOP;
6990 insn->size = size;
6991 insn->variant.dfp_binop.details = dfp_binop;
6992
6993 dfp_binop->tag = tag;
6994 dfp_binop->dst_hi = dst_hi;
6995 dfp_binop->dst_lo = dst_lo;
6996 dfp_binop->op2_hi = op2_hi;
6997 dfp_binop->op2_lo = op2_lo;
6998 dfp_binop->op3_hi = op3_hi;
6999 dfp_binop->op3_lo = op3_lo;
7000 dfp_binop->rounding_mode = rounding_mode;
7001
7002 return insn;
7003 }
7004
7005
7006 s390_insn *
s390_insn_dfp128_unop(UChar size,s390_dfp_unop_t tag,HReg dst,HReg op_hi,HReg op_lo)7007 s390_insn_dfp128_unop(UChar size, s390_dfp_unop_t tag, HReg dst,
7008 HReg op_hi, HReg op_lo)
7009 {
7010 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
7011
7012 /* destination is an 8 byte integer value */
7013 vassert(size == 8);
7014 vassert(is_valid_fp128_regpair(op_hi, op_lo));
7015
7016 insn->tag = S390_INSN_DFP_UNOP;
7017 insn->size = size;
7018 insn->variant.dfp_unop.tag = tag;
7019 insn->variant.dfp_unop.dst_hi = dst;
7020 insn->variant.dfp_unop.dst_lo = INVALID_HREG;
7021 insn->variant.dfp_unop.op_hi = op_hi;
7022 insn->variant.dfp_unop.op_lo = op_lo;
7023
7024 return insn;
7025 }
7026
7027
7028 s390_insn *
s390_insn_dfp128_intop(UChar size,s390_dfp_intop_t tag,HReg dst_hi,HReg dst_lo,HReg op2,HReg op3_hi,HReg op3_lo)7029 s390_insn_dfp128_intop(UChar size, s390_dfp_intop_t tag, HReg dst_hi,
7030 HReg dst_lo, HReg op2, HReg op3_hi, HReg op3_lo)
7031 {
7032 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
7033
7034 vassert(size == 16);
7035 vassert(is_valid_fp128_regpair(dst_hi, dst_lo));
7036 vassert(is_valid_fp128_regpair(op3_hi, op3_lo));
7037
7038 insn->tag = S390_INSN_DFP_INTOP;
7039 insn->size = size;
7040 insn->variant.dfp_intop.tag = tag;
7041 insn->variant.dfp_intop.dst_hi = dst_hi;
7042 insn->variant.dfp_intop.dst_lo = dst_lo;
7043 insn->variant.dfp_intop.op2 = op2;
7044 insn->variant.dfp_intop.op3_hi = op3_hi;
7045 insn->variant.dfp_intop.op3_lo = op3_lo;
7046
7047 return insn;
7048 }
7049
7050
7051 s390_insn *
s390_insn_dfp128_compare(UChar size,s390_dfp_cmp_t tag,HReg dst,HReg op1_hi,HReg op1_lo,HReg op2_hi,HReg op2_lo)7052 s390_insn_dfp128_compare(UChar size, s390_dfp_cmp_t tag, HReg dst, HReg op1_hi,
7053 HReg op1_lo, HReg op2_hi, HReg op2_lo)
7054 {
7055 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
7056
7057 vassert(size == 16);
7058 vassert(is_valid_fp128_regpair(op1_hi, op1_lo));
7059 vassert(is_valid_fp128_regpair(op2_hi, op2_lo));
7060
7061 insn->tag = S390_INSN_DFP_COMPARE;
7062 insn->size = size;
7063 insn->variant.dfp_compare.tag = tag;
7064 insn->variant.dfp_compare.dst = dst;
7065 insn->variant.dfp_compare.op1_hi = op1_hi;
7066 insn->variant.dfp_compare.op1_lo = op1_lo;
7067 insn->variant.dfp_compare.op2_hi = op2_hi;
7068 insn->variant.dfp_compare.op2_lo = op2_lo;
7069
7070 return insn;
7071 }
7072
7073
7074 static s390_insn *
s390_insn_dfp128_convert(UChar size,s390_dfp_conv_t tag,HReg dst_hi,HReg dst_lo,HReg op_hi,HReg op_lo,s390_dfp_round_t rounding_mode)7075 s390_insn_dfp128_convert(UChar size, s390_dfp_conv_t tag, HReg dst_hi,
7076 HReg dst_lo, HReg op_hi, HReg op_lo,
7077 s390_dfp_round_t rounding_mode)
7078 {
7079 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
7080
7081 if (size == 16) {
7082 /* From smaller size to 16 bytes */
7083 vassert(is_valid_fp128_regpair(dst_hi, dst_lo));
7084 vassert(hregIsInvalid(op_lo));
7085 } else {
7086 /* From 16 bytes to smaller size */
7087 vassert(is_valid_fp128_regpair(op_hi, op_lo));
7088 }
7089
7090 insn->tag = S390_INSN_DFP_CONVERT;
7091 insn->size = size;
7092 insn->variant.dfp_convert.tag = tag;
7093 insn->variant.dfp_convert.dst_hi = dst_hi;
7094 insn->variant.dfp_convert.dst_lo = dst_lo;
7095 insn->variant.dfp_convert.op_hi = op_hi;
7096 insn->variant.dfp_convert.op_lo = op_lo;
7097 insn->variant.dfp_convert.rounding_mode = rounding_mode;
7098
7099 return insn;
7100 }
7101
7102
7103 s390_insn *
s390_insn_dfp128_convert_to(UChar size,s390_dfp_conv_t tag,HReg dst_hi,HReg dst_lo,HReg op)7104 s390_insn_dfp128_convert_to(UChar size, s390_dfp_conv_t tag, HReg dst_hi,
7105 HReg dst_lo, HReg op)
7106 {
7107 /* Conversion to dfp128 never requires a rounding mode. Provide default
7108 rounding mode. It will not be used when emitting insns. */
7109 s390_dfp_round_t rounding_mode = S390_DFP_ROUND_NEAREST_EVEN_4;
7110
7111 return s390_insn_dfp128_convert(size, tag, dst_hi, dst_lo, op,
7112 INVALID_HREG, rounding_mode);
7113 }
7114
7115
7116 s390_insn *
s390_insn_dfp128_convert_from(UChar size,s390_dfp_conv_t tag,HReg dst_hi,HReg dst_lo,HReg op_hi,HReg op_lo,s390_dfp_round_t rounding_mode)7117 s390_insn_dfp128_convert_from(UChar size, s390_dfp_conv_t tag, HReg dst_hi,
7118 HReg dst_lo, HReg op_hi, HReg op_lo,
7119 s390_dfp_round_t rounding_mode)
7120 {
7121 return s390_insn_dfp128_convert(size, tag, dst_hi, dst_lo, op_hi, op_lo,
7122 rounding_mode);
7123 }
7124
7125
7126 s390_insn *
s390_insn_dfp128_reround(UChar size,HReg dst_hi,HReg dst_lo,HReg op2,HReg op3_hi,HReg op3_lo,s390_dfp_round_t rounding_mode)7127 s390_insn_dfp128_reround(UChar size, HReg dst_hi, HReg dst_lo, HReg op2,
7128 HReg op3_hi, HReg op3_lo,
7129 s390_dfp_round_t rounding_mode)
7130 {
7131 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
7132
7133 vassert(size == 16);
7134 vassert(is_valid_fp128_regpair(dst_hi, dst_lo));
7135 vassert(is_valid_fp128_regpair(op3_hi, op3_lo));
7136
7137 insn->tag = S390_INSN_DFP_REROUND;
7138 insn->size = size;
7139 insn->variant.dfp_reround.dst_hi = dst_hi;
7140 insn->variant.dfp_reround.dst_lo = dst_lo;
7141 insn->variant.dfp_reround.op2 = op2;
7142 insn->variant.dfp_reround.op3_hi = op3_hi;
7143 insn->variant.dfp_reround.op3_lo = op3_lo;
7144 insn->variant.dfp_reround.rounding_mode = rounding_mode;
7145
7146 return insn;
7147 }
7148
7149
7150 s390_insn *
s390_insn_mfence(void)7151 s390_insn_mfence(void)
7152 {
7153 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
7154
7155 insn->tag = S390_INSN_MFENCE;
7156 insn->size = 0; /* not needed */
7157
7158 return insn;
7159 }
7160
7161
7162 s390_insn *
s390_insn_mimm(UChar size,s390_amode * dst,ULong value)7163 s390_insn_mimm(UChar size, s390_amode *dst, ULong value)
7164 {
7165 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
7166
7167 /* This insn will be mapped to insns that require base register
7168 plus 12-bit displacement */
7169 vassert(dst->tag == S390_AMODE_B12);
7170
7171 insn->tag = S390_INSN_MIMM;
7172 insn->size = size;
7173 insn->variant.mimm.dst = dst;
7174 insn->variant.mimm.value = value;
7175
7176 return insn;
7177 }
7178
7179
7180 s390_insn *
s390_insn_madd(UChar size,s390_amode * dst,UChar delta,ULong value)7181 s390_insn_madd(UChar size, s390_amode *dst, UChar delta, ULong value)
7182 {
7183 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
7184
7185 vassert(size == 4 || size == 8);
7186
7187 /* This insn will be mapped to an ASI or AGSI so we can only allow base
7188 register plus 12-bit / 20-bit displacement. */
7189 vassert(dst->tag == S390_AMODE_B12 || dst->tag == S390_AMODE_B20);
7190 /* ASI and AGSI require the GIE facility */
7191 vassert(s390_host_has_gie);
7192
7193 insn->tag = S390_INSN_MADD;
7194 insn->size = size;
7195 insn->variant.madd.dst = dst;
7196 insn->variant.madd.delta = delta;
7197 insn->variant.madd.value = value;
7198
7199 return insn;
7200 }
7201
7202
7203 s390_insn *
s390_insn_set_fpc_bfprm(UChar size,HReg mode)7204 s390_insn_set_fpc_bfprm(UChar size, HReg mode)
7205 {
7206 vassert(size == 4);
7207
7208 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
7209
7210 insn->tag = S390_INSN_SET_FPC_BFPRM;
7211 insn->size = size;
7212 insn->variant.set_fpc_bfprm.mode = mode;
7213
7214 return insn;
7215 }
7216
7217
7218 s390_insn *
s390_insn_set_fpc_dfprm(UChar size,HReg mode)7219 s390_insn_set_fpc_dfprm(UChar size, HReg mode)
7220 {
7221 vassert(size == 4);
7222
7223 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
7224
7225 insn->tag = S390_INSN_SET_FPC_DFPRM;
7226 insn->size = size;
7227 insn->variant.set_fpc_dfprm.mode = mode;
7228
7229 return insn;
7230 }
7231
7232
7233 s390_insn *
s390_insn_xdirect(s390_cc_t cond,Addr64 dst,s390_amode * guest_IA,Bool to_fast_entry)7234 s390_insn_xdirect(s390_cc_t cond, Addr64 dst, s390_amode *guest_IA,
7235 Bool to_fast_entry)
7236 {
7237 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
7238
7239 vassert(guest_IA->tag == S390_AMODE_B12);
7240
7241 insn->tag = S390_INSN_XDIRECT;
7242 insn->size = 0; /* does not matter */
7243
7244 insn->variant.xdirect.cond = cond;
7245 insn->variant.xdirect.dst = dst;
7246 insn->variant.xdirect.guest_IA = guest_IA;
7247 insn->variant.xdirect.to_fast_entry = to_fast_entry;
7248
7249 return insn;
7250 }
7251
7252
7253 s390_insn *
s390_insn_xindir(s390_cc_t cond,HReg dst,s390_amode * guest_IA)7254 s390_insn_xindir(s390_cc_t cond, HReg dst, s390_amode *guest_IA)
7255 {
7256 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
7257
7258 vassert(guest_IA->tag == S390_AMODE_B12);
7259
7260 insn->tag = S390_INSN_XINDIR;
7261 insn->size = 0; /* does not matter */
7262
7263 insn->variant.xindir.cond = cond;
7264 insn->variant.xindir.dst = dst;
7265 insn->variant.xindir.guest_IA = guest_IA;
7266
7267 return insn;
7268 }
7269
7270
7271 s390_insn *
s390_insn_xassisted(s390_cc_t cond,HReg dst,s390_amode * guest_IA,IRJumpKind kind)7272 s390_insn_xassisted(s390_cc_t cond, HReg dst, s390_amode *guest_IA,
7273 IRJumpKind kind)
7274 {
7275 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
7276
7277 vassert(guest_IA->tag == S390_AMODE_B12);
7278
7279 insn->tag = S390_INSN_XASSISTED;
7280 insn->size = 0; /* does not matter */
7281
7282 insn->variant.xassisted.cond = cond;
7283 insn->variant.xassisted.dst = dst;
7284 insn->variant.xassisted.guest_IA = guest_IA;
7285 insn->variant.xassisted.kind = kind;
7286
7287 return insn;
7288 }
7289
7290
7291 s390_insn *
s390_insn_evcheck(s390_amode * counter,s390_amode * fail_addr)7292 s390_insn_evcheck(s390_amode *counter, s390_amode *fail_addr)
7293 {
7294 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
7295
7296 vassert(counter->tag == S390_AMODE_B12);
7297 vassert(fail_addr->tag == S390_AMODE_B12);
7298
7299 insn->tag = S390_INSN_EVCHECK;
7300 insn->size = 0; /* does not matter */
7301
7302 insn->variant.evcheck.counter = counter;
7303 insn->variant.evcheck.fail_addr = fail_addr;
7304
7305 return insn;
7306 }
7307
7308
7309 s390_insn *
s390_insn_profinc(void)7310 s390_insn_profinc(void)
7311 {
7312 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
7313
7314 insn->tag = S390_INSN_PROFINC;
7315 insn->size = 0; /* does not matter */
7316
7317 return insn;
7318 }
7319
7320
7321 s390_insn *
s390_insn_vec_amodeop(UChar size,s390_vec_amodeop_t tag,HReg dst,HReg op1,s390_amode * op2)7322 s390_insn_vec_amodeop(UChar size, s390_vec_amodeop_t tag, HReg dst, HReg op1,
7323 s390_amode *op2)
7324 {
7325 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
7326
7327 vassert(size == 1 || size == 2 || size == 4 || size == 8);
7328
7329 insn->tag = S390_INSN_VEC_AMODEOP;
7330 insn->size = size;
7331 insn->variant.vec_amodeop.tag = tag;
7332 insn->variant.vec_amodeop.dst = dst;
7333 insn->variant.vec_amodeop.op1 = op1;
7334 insn->variant.vec_amodeop.op2 = op2;
7335
7336 return insn;
7337 }
7338
s390_insn_vec_amodeintop(UChar size,s390_vec_amodeintop_t tag,HReg dst,s390_amode * op2,HReg op3)7339 s390_insn *s390_insn_vec_amodeintop(UChar size, s390_vec_amodeintop_t tag, HReg dst,
7340 s390_amode* op2, HReg op3)
7341 {
7342 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
7343
7344 vassert(size == 1 || size == 2 || size == 4 || size == 8);
7345
7346 insn->tag = S390_INSN_VEC_AMODEINTOP;
7347 insn->size = size;
7348 insn->variant.vec_amodeintop.tag = tag;
7349 insn->variant.vec_amodeintop.dst = dst;
7350 insn->variant.vec_amodeintop.op2 = op2;
7351 insn->variant.vec_amodeintop.op3 = op3;
7352
7353 return insn;
7354 }
7355
s390_insn_vec_binop(UChar size,s390_vec_binop_t tag,HReg dst,HReg op1,HReg op2)7356 s390_insn *s390_insn_vec_binop(UChar size, s390_vec_binop_t tag, HReg dst,
7357 HReg op1, HReg op2)
7358 {
7359 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
7360
7361 vassert(size == 1 || size == 2 || size == 4 || size == 8 || size == 16);
7362
7363 insn->tag = S390_INSN_VEC_BINOP;
7364 insn->size = size;
7365 insn->variant.vec_binop.tag = tag;
7366 insn->variant.vec_binop.dst = dst;
7367 insn->variant.vec_binop.op1 = op1;
7368 insn->variant.vec_binop.op2 = op2;
7369
7370 return insn;
7371 }
7372
s390_insn_vec_triop(UChar size,s390_vec_triop_t tag,HReg dst,HReg op1,HReg op2,HReg op3)7373 s390_insn *s390_insn_vec_triop(UChar size, s390_vec_triop_t tag, HReg dst,
7374 HReg op1, HReg op2, HReg op3)
7375 {
7376 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
7377
7378
7379 insn->tag = S390_INSN_VEC_TRIOP;
7380 insn->size = size;
7381 insn->variant.vec_triop.tag = tag;
7382 insn->variant.vec_triop.dst = dst;
7383 insn->variant.vec_triop.op1 = op1;
7384 insn->variant.vec_triop.op2 = op2;
7385 insn->variant.vec_triop.op3 = op3;
7386
7387 return insn;
7388 }
7389
7390 /*---------------------------------------------------------------*/
7391 /*--- Debug print ---*/
7392 /*---------------------------------------------------------------*/
7393
7394 static const HChar *
s390_cc_as_string(s390_cc_t cc)7395 s390_cc_as_string(s390_cc_t cc)
7396 {
7397 switch (cc) {
7398 case S390_CC_NEVER: return "never";
7399 case S390_CC_OVFL: return "overflow";
7400 case S390_CC_H: return "greater than"; /* A > B ; high */
7401 case S390_CC_NLE: return "not low or equal";
7402 case S390_CC_L: return "less than"; /* A < B ; low */
7403 case S390_CC_NHE: return "not high or equal";
7404 case S390_CC_LH: return "low or high";
7405 case S390_CC_NE: return "not equal"; /* A != B ; not zero */
7406 case S390_CC_E: return "equal"; /* A == B ; zero */
7407 case S390_CC_NLH: return "not low or high";
7408 case S390_CC_HE: return "greater or equal"; /* A >= B ; high or equal*/
7409 case S390_CC_NL: return "not low"; /* not low */
7410 case S390_CC_LE: return "less or equal"; /* A <= B ; low or equal */
7411 case S390_CC_NH: return "not high";
7412 case S390_CC_NO: return "not overflow";
7413 case S390_CC_ALWAYS: return "always";
7414 default:
7415 vpanic("s390_cc_as_string");
7416 }
7417 }
7418
7419
7420 static const HChar *
s390_jump_kind_as_string(IRJumpKind kind)7421 s390_jump_kind_as_string(IRJumpKind kind)
7422 {
7423 switch (kind) {
7424 case Ijk_Boring: return "Boring";
7425 case Ijk_Call: return "Call";
7426 case Ijk_Ret: return "Return";
7427 case Ijk_ClientReq: return "ClientReq";
7428 case Ijk_Yield: return "Yield";
7429 case Ijk_EmWarn: return "EmWarn";
7430 case Ijk_EmFail: return "EmFail";
7431 case Ijk_NoDecode: return "NoDecode";
7432 case Ijk_MapFail: return "MapFail";
7433 case Ijk_InvalICache: return "Invalidate";
7434 case Ijk_NoRedir: return "NoRedir";
7435 case Ijk_SigTRAP: return "SigTRAP";
7436 case Ijk_SigFPE: return "SigFPE";
7437 case Ijk_SigSEGV: return "SigSEGV";
7438 case Ijk_SigBUS: return "SigBUS";
7439 case Ijk_Sys_syscall: return "Sys_syscall";
7440 default:
7441 vpanic("s390_jump_kind_as_string");
7442 }
7443 }
7444
7445
7446 /* Helper function for writing out a V insn */
7447 static void
s390_sprintf(HChar * buf,const HChar * fmt,...)7448 s390_sprintf(HChar *buf, const HChar *fmt, ...)
7449 {
7450 HChar *p;
7451 ULong value;
7452 va_list args;
7453 va_start(args, fmt);
7454
7455 p = buf;
7456 for ( ; *fmt; ++fmt) {
7457 Int c = *fmt;
7458
7459 if (c != '%') {
7460 *p++ = c;
7461 continue;
7462 }
7463
7464 c = *++fmt; /* next char */
7465 switch (c) {
7466 case '%':
7467 *p++ = c; /* %% */
7468 continue;
7469
7470 case 's': /* %s */
7471 p += vex_sprintf(p, "%s", va_arg(args, HChar *));
7472 continue;
7473
7474 case 'M': /* %M = mnemonic */
7475 p += vex_sprintf(p, "%-8s", va_arg(args, HChar *));
7476 continue;
7477
7478 case 'R': /* %R = register */
7479 p += vex_sprintf(p, "%s", s390_hreg_as_string(va_arg(args, HReg)));
7480 continue;
7481
7482 case 'A': /* %A = amode */
7483 p += vex_sprintf(p, "%s",
7484 s390_amode_as_string(va_arg(args, s390_amode *)));
7485 continue;
7486
7487 case 'G': /* %G = guest state @ offset */
7488 p += vex_sprintf(p, "guest[%u]", va_arg(args, UInt));
7489 continue;
7490
7491 case 'C': /* %C = condition code */
7492 p += vex_sprintf(p, "%s", s390_cc_as_string(va_arg(args, s390_cc_t)));
7493 continue;
7494
7495 case 'J': /* &J = jump kind */
7496 p += vex_sprintf(p, "%s",
7497 s390_jump_kind_as_string(va_arg(args, IRJumpKind)));
7498 continue;
7499
7500 case 'L': { /* %L = argument list in helper call*/
7501 UInt i, num_args;
7502
7503 num_args = va_arg(args, UInt);
7504
7505 for (i = 0; i < num_args; ++i) {
7506 if (i != 0) p += vex_sprintf(p, ", ");
7507 p += vex_sprintf(p, "r%u", s390_gprno_from_arg_index(i));
7508 }
7509 continue;
7510 }
7511
7512 case 'O': { /* %O = RMI operand */
7513 s390_opnd_RMI *op = va_arg(args, s390_opnd_RMI *);
7514
7515 switch (op->tag) {
7516 case S390_OPND_REG:
7517 p += vex_sprintf(p, "%s", s390_hreg_as_string(op->variant.reg));
7518 continue;
7519
7520 case S390_OPND_AMODE:
7521 p += vex_sprintf(p, "%s", s390_amode_as_string(op->variant.am));
7522 continue;
7523
7524 case S390_OPND_IMMEDIATE:
7525 value = op->variant.imm;
7526 goto print_value;
7527
7528 default:
7529 goto fail;
7530 }
7531 }
7532
7533 case 'I': /* %I = immediate value */
7534 value = va_arg(args, ULong);
7535 goto print_value;
7536
7537 print_value:
7538 if ((Long)value < 0)
7539 p += vex_sprintf(p, "%lld", (Long)value);
7540 else if (value < 100)
7541 p += vex_sprintf(p, "%llu", value);
7542 else
7543 p += vex_sprintf(p, "0x%llx", value);
7544 continue;
7545
7546 default:
7547 goto fail;
7548 }
7549 }
7550 *p = '\0';
7551 va_end(args);
7552
7553 return;
7554
7555 fail: vpanic("s390_printf");
7556 }
7557
7558
7559 /* Decompile the given insn into a static buffer and return it */
7560 const HChar *
s390_insn_as_string(const s390_insn * insn)7561 s390_insn_as_string(const s390_insn *insn)
7562 {
7563 static HChar buf[300]; // large enough
7564 const HChar *op;
7565 HChar *p;
7566
7567 buf[0] = '\0';
7568
7569 switch (insn->tag) {
7570 case S390_INSN_LOAD:
7571 s390_sprintf(buf, "%M %R,%A", "v-load", insn->variant.load.dst,
7572 insn->variant.load.src);
7573 break;
7574
7575 case S390_INSN_STORE:
7576 s390_sprintf(buf, "%M %R,%A", "v-store", insn->variant.store.src,
7577 insn->variant.store.dst);
7578 break;
7579
7580 case S390_INSN_MOVE:
7581 s390_sprintf(buf, "%M %R,%R", "v-move", insn->variant.move.dst,
7582 insn->variant.move.src);
7583 break;
7584
7585 case S390_INSN_MEMCPY:
7586 s390_sprintf(buf, "%M %A,%A", "v-memcpy", insn->variant.memcpy.dst,
7587 insn->variant.memcpy.src);
7588 break;
7589
7590 case S390_INSN_COND_MOVE:
7591 s390_sprintf(buf, "%M if (%C) %R,%O", "v-move",
7592 insn->variant.cond_move.cond, insn->variant.cond_move.dst,
7593 &insn->variant.cond_move.src);
7594 break;
7595
7596 case S390_INSN_LOAD_IMMEDIATE:
7597 s390_sprintf(buf, "%M %R,%I", "v-loadi", insn->variant.load_immediate.dst,
7598 insn->variant.load_immediate.value);
7599 break;
7600
7601 case S390_INSN_ALU:
7602 switch (insn->variant.alu.tag) {
7603 case S390_ALU_ADD: op = "v-add"; break;
7604 case S390_ALU_SUB: op = "v-sub"; break;
7605 case S390_ALU_MUL: op = "v-mul"; break;
7606 case S390_ALU_AND: op = "v-and"; break;
7607 case S390_ALU_OR: op = "v-or"; break;
7608 case S390_ALU_XOR: op = "v-xor"; break;
7609 case S390_ALU_LSH: op = "v-lsh"; break;
7610 case S390_ALU_RSH: op = "v-rsh"; break;
7611 case S390_ALU_RSHA: op = "v-rsha"; break;
7612 default: goto fail;
7613 }
7614 s390_sprintf(buf, "%M %R,%O", op, insn->variant.alu.dst, /* also op1 */
7615 &insn->variant.alu.op2);
7616 break;
7617
7618 case S390_INSN_SMUL:
7619 case S390_INSN_UMUL:
7620 if (insn->tag == S390_INSN_SMUL) {
7621 op = "v-muls";
7622 } else {
7623 op = "v-mulu";
7624 }
7625 s390_sprintf(buf, "%M %R,%O", op, insn->variant.mul.dst_hi,
7626 &insn->variant.mul.op2);
7627 break;
7628
7629 case S390_INSN_SDIV:
7630 case S390_INSN_UDIV:
7631 if (insn->tag == S390_INSN_SDIV) {
7632 op = "v-divs";
7633 } else {
7634 op = "v-divu";
7635 }
7636 s390_sprintf(buf, "%M %R,%O", op, insn->variant.div.op1_hi,
7637 &insn->variant.div.op2);
7638 break;
7639
7640 case S390_INSN_DIVS:
7641 s390_sprintf(buf, "%M %R,%O", "v-divsi", insn->variant.divs.op1,
7642 &insn->variant.divs.op2);
7643 break;
7644
7645 case S390_INSN_CLZ:
7646 s390_sprintf(buf, "%M %R,%O", "v-clz", insn->variant.clz.num_bits,
7647 &insn->variant.clz.src);
7648 break;
7649
7650 case S390_INSN_UNOP:
7651 switch (insn->variant.unop.tag) {
7652 case S390_ZERO_EXTEND_8:
7653 case S390_ZERO_EXTEND_16:
7654 case S390_ZERO_EXTEND_32:
7655 op = "v-zerox";
7656 break;
7657
7658 case S390_SIGN_EXTEND_8:
7659 case S390_SIGN_EXTEND_16:
7660 case S390_SIGN_EXTEND_32:
7661 op = "v-signx";
7662 break;
7663
7664 case S390_NEGATE:
7665 op = "v-neg";
7666 break;
7667
7668 case S390_VEC_FILL:
7669 op = "v-vfill";
7670 break;
7671
7672 case S390_VEC_DUPLICATE:
7673 op = "v-vdup";
7674 break;
7675
7676 case S390_VEC_UNPACKLOWS:
7677 op = "v-vunpacks";
7678 break;
7679
7680 case S390_VEC_UNPACKLOWU:
7681 op = "v-vunpacku";
7682 break;
7683
7684 case S390_VEC_FLOAT_NEG:
7685 op = "v-vfloatneg";
7686 break;
7687
7688 case S390_VEC_FLOAT_SQRT:
7689 op = "v-vfloatsqrt";
7690 break;
7691
7692 case S390_VEC_FLOAT_ABS:
7693 op = "v-vfloatabs";
7694 break;
7695
7696 default:
7697 goto fail;
7698 }
7699 s390_sprintf(buf, "%M %R,%O", op, insn->variant.unop.dst,
7700 &insn->variant.unop.src);
7701 break;
7702
7703 case S390_INSN_TEST:
7704 s390_sprintf(buf, "%M %O", "v-test", &insn->variant.test.src);
7705 break;
7706
7707 case S390_INSN_CC2BOOL:
7708 s390_sprintf(buf, "%M %R,%C", "v-cc2b", insn->variant.cc2bool.dst,
7709 insn->variant.cc2bool.cond);
7710 break;
7711
7712 case S390_INSN_CAS:
7713 s390_sprintf(buf, "%M %R,%A,%R,%R", "v-cas", insn->variant.cas.op1,
7714 insn->variant.cas.op2, insn->variant.cas.op3,
7715 insn->variant.cas.old_mem);
7716 break;
7717
7718 case S390_INSN_CDAS: {
7719 s390_cdas *cdas = insn->variant.cdas.details;
7720
7721 s390_sprintf(buf, "%M %R,%R,%A,%R,%R,%R,%R", "v-cdas",
7722 cdas->op1_high, cdas->op1_low, cdas->op2, cdas->op3_high,
7723 cdas->op3_low, cdas->old_mem_high, cdas->old_mem_low);
7724 break;
7725 }
7726
7727 case S390_INSN_COMPARE:
7728 if (insn->variant.compare.signed_comparison) {
7729 op = "v-cmps";
7730 } else {
7731 op = "v-cmpu";
7732 }
7733 s390_sprintf(buf, "%M %R,%O", op, insn->variant.compare.src1,
7734 &insn->variant.compare.src2);
7735 break;
7736
7737 case S390_INSN_HELPER_CALL: {
7738 s390_helper_call *helper_call = insn->variant.helper_call.details;
7739 s390_sprintf(buf, "%M if (%C) %s{%I}(%L)", "v-call",
7740 helper_call->cond,
7741 helper_call->name,
7742 helper_call->target,
7743 helper_call->num_args);
7744 return buf; /* avoid printing "size = ..." which is meaningless */
7745 }
7746
7747 case S390_INSN_BFP_TRIOP:
7748 switch (insn->variant.bfp_triop.tag) {
7749 case S390_BFP_MADD: op = "v-fmadd"; break;
7750 case S390_BFP_MSUB: op = "v-fmsub"; break;
7751 default: goto fail;
7752 }
7753 s390_sprintf(buf, "%M %R,%R,%R", op,
7754 insn->variant.bfp_triop.dst /* op1 same as dst */,
7755 insn->variant.bfp_triop.op2, insn->variant.bfp_triop.op3);
7756 break;
7757
7758 case S390_INSN_BFP_BINOP:
7759 switch (insn->variant.bfp_binop.tag) {
7760 case S390_BFP_ADD: op = "v-fadd"; break;
7761 case S390_BFP_SUB: op = "v-fsub"; break;
7762 case S390_BFP_MUL: op = "v-fmul"; break;
7763 case S390_BFP_DIV: op = "v-fdiv"; break;
7764 default: goto fail;
7765 }
7766 s390_sprintf(buf, "%M %R,%R", op,
7767 insn->variant.bfp_binop.dst_hi /* op1 same as dst */,
7768 insn->variant.bfp_binop.op2_hi);
7769 break;
7770
7771 case S390_INSN_BFP_COMPARE:
7772 s390_sprintf(buf, "%M %R,%R,%R", "v-fcmp", insn->variant.bfp_compare.dst,
7773 insn->variant.bfp_compare.op1_hi,
7774 insn->variant.bfp_compare.op2_hi);
7775 break;
7776
7777 case S390_INSN_BFP_UNOP:
7778 switch (insn->variant.bfp_unop.tag) {
7779 case S390_BFP_ABS: op = "v-fabs"; break;
7780 case S390_BFP_NABS: op = "v-fnabs"; break;
7781 case S390_BFP_NEG: op = "v-fneg"; break;
7782 case S390_BFP_SQRT: op = "v-fsqrt"; break;
7783 default: goto fail;
7784 }
7785 s390_sprintf(buf, "%M %R,%R", op, insn->variant.bfp_unop.dst_hi,
7786 insn->variant.bfp_unop.op_hi);
7787 break;
7788
7789 case S390_INSN_BFP_CONVERT:
7790 switch (insn->variant.bfp_convert.tag) {
7791 case S390_BFP_I32_TO_F32:
7792 case S390_BFP_I32_TO_F64:
7793 case S390_BFP_I32_TO_F128:
7794 case S390_BFP_I64_TO_F32:
7795 case S390_BFP_I64_TO_F64:
7796 case S390_BFP_I64_TO_F128: op = "v-i2f"; break;
7797 case S390_BFP_U32_TO_F32:
7798 case S390_BFP_U32_TO_F64:
7799 case S390_BFP_U32_TO_F128:
7800 case S390_BFP_U64_TO_F32:
7801 case S390_BFP_U64_TO_F64:
7802 case S390_BFP_U64_TO_F128: op = "v-u2f"; break;
7803 case S390_BFP_F32_TO_I32:
7804 case S390_BFP_F32_TO_I64:
7805 case S390_BFP_F64_TO_I32:
7806 case S390_BFP_F64_TO_I64:
7807 case S390_BFP_F128_TO_I32:
7808 case S390_BFP_F128_TO_I64: op = "v-f2i"; break;
7809 case S390_BFP_F32_TO_U32:
7810 case S390_BFP_F32_TO_U64:
7811 case S390_BFP_F64_TO_U32:
7812 case S390_BFP_F64_TO_U64:
7813 case S390_BFP_F128_TO_U32:
7814 case S390_BFP_F128_TO_U64: op = "v-f2u"; break;
7815 case S390_BFP_F32_TO_F64:
7816 case S390_BFP_F32_TO_F128:
7817 case S390_BFP_F64_TO_F32:
7818 case S390_BFP_F64_TO_F128:
7819 case S390_BFP_F128_TO_F32:
7820 case S390_BFP_F128_TO_F64: op = "v-f2f"; break;
7821 case S390_BFP_F32_TO_F32I:
7822 case S390_BFP_F64_TO_F64I:
7823 case S390_BFP_F128_TO_F128I: op = "v-f2fi"; break;
7824 default: goto fail;
7825 }
7826 s390_sprintf(buf, "%M %R,%R", op, insn->variant.bfp_convert.dst_hi,
7827 insn->variant.bfp_convert.op_hi);
7828 break;
7829
7830 case S390_INSN_DFP_BINOP: {
7831 s390_dfp_binop *dfp_binop = insn->variant.dfp_binop.details;
7832
7833 switch (dfp_binop->tag) {
7834 case S390_DFP_ADD: op = "v-dadd"; break;
7835 case S390_DFP_SUB: op = "v-dsub"; break;
7836 case S390_DFP_MUL: op = "v-dmul"; break;
7837 case S390_DFP_DIV: op = "v-ddiv"; break;
7838 case S390_DFP_QUANTIZE: op = "v-dqua"; break;
7839 default: goto fail;
7840 }
7841 s390_sprintf(buf, "%M %R,%R,%R", op, dfp_binop->dst_hi,
7842 dfp_binop->op2_hi, dfp_binop->op3_hi);
7843 break;
7844 }
7845
7846 case S390_INSN_DFP_UNOP:
7847 switch (insn->variant.dfp_unop.tag) {
7848 case S390_DFP_EXTRACT_EXP_D64:
7849 case S390_DFP_EXTRACT_EXP_D128: op = "v-d2exp"; break;
7850 case S390_DFP_EXTRACT_SIG_D64:
7851 case S390_DFP_EXTRACT_SIG_D128: op = "v-d2sig"; break;
7852 default: goto fail;
7853 }
7854 s390_sprintf(buf, "%M %R,%R", op, insn->variant.dfp_unop.dst_hi,
7855 insn->variant.dfp_unop.op_hi);
7856 break;
7857
7858 case S390_INSN_DFP_INTOP:
7859 switch (insn->variant.dfp_intop.tag) {
7860 case S390_DFP_SHIFT_LEFT: op = "v-dshl"; break;
7861 case S390_DFP_SHIFT_RIGHT: op = "v-dshr"; break;
7862 case S390_DFP_INSERT_EXP: op = "v-diexp"; break;
7863 default: goto fail;
7864 }
7865 s390_sprintf(buf, "%M %R,%R,%R", op, insn->variant.dfp_intop.dst_hi,
7866 insn->variant.dfp_intop.op2,
7867 insn->variant.dfp_intop.op3_hi);
7868 break;
7869
7870 case S390_INSN_DFP_COMPARE:
7871 switch (insn->variant.dfp_compare.tag) {
7872 case S390_DFP_COMPARE: op = "v-dcmp"; break;
7873 case S390_DFP_COMPARE_EXP: op = "v-dcmpexp"; break;
7874 default: goto fail;
7875 }
7876 s390_sprintf(buf, "%M %R,%R,%R", op, insn->variant.dfp_compare.dst,
7877 insn->variant.dfp_compare.op1_hi,
7878 insn->variant.dfp_compare.op2_hi);
7879 break;
7880
7881 case S390_INSN_DFP_CONVERT:
7882 switch (insn->variant.dfp_convert.tag) {
7883 case S390_DFP_D32_TO_D64:
7884 case S390_DFP_D64_TO_D32:
7885 case S390_DFP_D64_TO_D128:
7886 case S390_DFP_D128_TO_D64: op = "v-d2d"; break;
7887 case S390_DFP_I32_TO_D64:
7888 case S390_DFP_I32_TO_D128:
7889 case S390_DFP_I64_TO_D64:
7890 case S390_DFP_I64_TO_D128: op = "v-i2d"; break;
7891 case S390_DFP_U32_TO_D64:
7892 case S390_DFP_U32_TO_D128:
7893 case S390_DFP_U64_TO_D64:
7894 case S390_DFP_U64_TO_D128: op = "v-u2d"; break;
7895 case S390_DFP_D64_TO_I32:
7896 case S390_DFP_D128_TO_I32:
7897 case S390_DFP_D64_TO_I64:
7898 case S390_DFP_D128_TO_I64: op = "v-d2i"; break;
7899 case S390_DFP_D64_TO_U32:
7900 case S390_DFP_D64_TO_U64:
7901 case S390_DFP_D128_TO_U32:
7902 case S390_DFP_D128_TO_U64: op = "v-d2u"; break;
7903 default: goto fail;
7904 }
7905 s390_sprintf(buf, "%M %R,%R", op, insn->variant.dfp_convert.dst_hi,
7906 insn->variant.dfp_convert.op_hi);
7907 break;
7908
7909 case S390_INSN_DFP_REROUND:
7910 s390_sprintf(buf, "%M %R,%R,%R", "v-drrnd",
7911 insn->variant.dfp_reround.dst_hi,
7912 insn->variant.dfp_reround.op2,
7913 insn->variant.dfp_reround.op3_hi);
7914 break;
7915
7916 case S390_INSN_FP_CONVERT: {
7917 s390_fp_convert *fp_convert = insn->variant.fp_convert.details;
7918
7919 switch (fp_convert->tag) {
7920 case S390_FP_F32_TO_D32:
7921 case S390_FP_F32_TO_D64:
7922 case S390_FP_F32_TO_D128:
7923 case S390_FP_F64_TO_D32:
7924 case S390_FP_F64_TO_D64:
7925 case S390_FP_F64_TO_D128:
7926 case S390_FP_F128_TO_D32:
7927 case S390_FP_F128_TO_D64:
7928 case S390_FP_F128_TO_D128: op = "v-f2d"; break;
7929 case S390_FP_D32_TO_F32:
7930 case S390_FP_D32_TO_F64:
7931 case S390_FP_D32_TO_F128:
7932 case S390_FP_D64_TO_F32:
7933 case S390_FP_D64_TO_F64:
7934 case S390_FP_D64_TO_F128:
7935 case S390_FP_D128_TO_F32:
7936 case S390_FP_D128_TO_F64:
7937 case S390_FP_D128_TO_F128: op = "v-d2f"; break;
7938 default: goto fail;
7939 }
7940 s390_sprintf(buf, "%M %R,%R", op, fp_convert->dst_hi,
7941 fp_convert->op_hi);
7942 break;
7943 }
7944
7945 case S390_INSN_MFENCE:
7946 s390_sprintf(buf, "%M", "v-mfence");
7947 return buf; /* avoid printing "size = ..." which is meaningless */
7948
7949 case S390_INSN_MIMM:
7950 s390_sprintf(buf, "%M %A,%I", "v-mimm", insn->variant.mimm.dst,
7951 insn->variant.mimm.value);
7952 break;
7953
7954 case S390_INSN_MADD:
7955 s390_sprintf(buf, "%M %A += %I (= %I)", "v-madd",
7956 insn->variant.madd.dst,
7957 (Long)(Char)insn->variant.madd.delta,
7958 insn->variant.madd.value);
7959 break;
7960
7961 case S390_INSN_SET_FPC_BFPRM:
7962 s390_sprintf(buf, "%M %R", "v-set-fpc-bfprm",
7963 insn->variant.set_fpc_bfprm.mode);
7964 break;
7965
7966 case S390_INSN_SET_FPC_DFPRM:
7967 s390_sprintf(buf, "%M %R", "v-set-fpc-dfprm",
7968 insn->variant.set_fpc_dfprm.mode);
7969 break;
7970
7971 case S390_INSN_EVCHECK:
7972 s390_sprintf(buf, "%M counter = %A, fail-addr = %A", "v-evcheck",
7973 insn->variant.evcheck.counter,
7974 insn->variant.evcheck.fail_addr);
7975 return buf; /* avoid printing "size = ..." which is meaningless */
7976
7977 case S390_INSN_PROFINC:
7978 s390_sprintf(buf, "%M", "v-profinc");
7979 return buf; /* avoid printing "size = ..." which is meaningless */
7980
7981 case S390_INSN_XDIRECT:
7982 s390_sprintf(buf, "%M if (%C) %A = %I %s", "v-xdirect",
7983 insn->variant.xdirect.cond,
7984 insn->variant.xdirect.guest_IA,
7985 insn->variant.xdirect.dst,
7986 insn->variant.xdirect.to_fast_entry ? "fast" : "slow");
7987 return buf; /* avoid printing "size = ..." which is meaningless */
7988
7989 case S390_INSN_XINDIR:
7990 s390_sprintf(buf, "%M if (%C) %A = %R", "v-xindir",
7991 insn->variant.xindir.cond,
7992 insn->variant.xindir.guest_IA,
7993 insn->variant.xindir.dst);
7994 return buf; /* avoid printing "size = ..." which is meaningless */
7995
7996 case S390_INSN_XASSISTED:
7997 s390_sprintf(buf, "%M if (%C) %J %A = %R", "v-xassisted",
7998 insn->variant.xassisted.cond,
7999 insn->variant.xassisted.kind,
8000 insn->variant.xassisted.guest_IA,
8001 insn->variant.xassisted.dst);
8002 return buf; /* avoid printing "size = ..." which is meaningless */
8003
8004 case S390_INSN_VEC_AMODEOP:
8005 switch (insn->variant.vec_amodeop.tag) {
8006 case S390_VEC_GET_ELEM: op = "v-vgetelem"; break;
8007 case S390_VEC_ELEM_SHL_INT: op = "v-veshl"; break;
8008 case S390_VEC_ELEM_SHRA_INT: op = "v-veshra"; break;
8009 case S390_VEC_ELEM_SHRL_INT: op = "v-veshrl"; break;
8010 default: goto fail;
8011 }
8012 s390_sprintf(buf, "%M %R, %R, %A", op, insn->variant.vec_amodeop.dst,
8013 insn->variant.vec_amodeop.op1,
8014 insn->variant.vec_amodeop.op2);
8015 break;
8016
8017 case S390_INSN_VEC_AMODEINTOP:
8018 switch (insn->variant.vec_amodeintop.tag) {
8019 case S390_VEC_SET_ELEM: op = "v-vsetelem"; break;
8020 default: goto fail;
8021 }
8022 s390_sprintf(buf, "%M %R, %A, %R", op, insn->variant.vec_amodeintop.dst,
8023 insn->variant.vec_amodeintop.op2,
8024 insn->variant.vec_amodeintop.op3);
8025 break;
8026
8027 case S390_INSN_VEC_BINOP:
8028 switch (insn->variant.vec_binop.tag) {
8029 case S390_VEC_PACK: op = "v-vpack"; break;
8030 case S390_VEC_PACK_SATURS: op = "v-vpacksaturs"; break;
8031 case S390_VEC_PACK_SATURU: op = "v-vpacksaturu"; break;
8032 case S390_VEC_COMPARE_EQUAL: op = "v-vcmpeq"; break;
8033 case S390_VEC_OR: op = "v-vor"; break;
8034 case S390_VEC_XOR: op = "v-vxor"; break;
8035 case S390_VEC_AND: op = "v-vand"; break;
8036 case S390_VEC_MERGEL: op = "v-vmergel"; break;
8037 case S390_VEC_MERGEH: op = "v-vmergeh"; break;
8038 case S390_VEC_NOR: op = "v-vnor"; break;
8039 case S390_VEC_INT_ADD: op = "v-vintadd"; break;
8040 case S390_VEC_INT_SUB: op = "v-vintsub"; break;
8041 case S390_VEC_MAXU: op = "v-vmaxu"; break;
8042 case S390_VEC_MAXS: op = "v-vmaxs"; break;
8043 case S390_VEC_MINU: op = "v-vminu"; break;
8044 case S390_VEC_MINS: op = "v-vmins"; break;
8045 case S390_VEC_AVGU: op = "v-vavgu"; break;
8046 case S390_VEC_AVGS: op = "v-vavgs"; break;
8047 case S390_VEC_COMPARE_GREATERS: op = "v-vcmpgts"; break;
8048 case S390_VEC_COMPARE_GREATERU: op = "v-vcmpgtu"; break;
8049 case S390_VEC_INT_MUL_HIGHS: op = "v-vintmulhis"; break;
8050 case S390_VEC_INT_MUL_HIGHU: op = "v-vintmulhiu"; break;
8051 case S390_VEC_INT_MUL_LOW: op = "v-vintmullo"; break;
8052 case S390_VEC_INT_MUL_EVENS: op = "v-vintmulevens"; break;
8053 case S390_VEC_INT_MUL_EVENU: op = "v-vintmulevenu"; break;
8054 case S390_VEC_ELEM_SHL_V: op = "v-velemshl"; break;
8055 case S390_VEC_ELEM_SHRA_V: op = "v-vshrav"; break;
8056 case S390_VEC_ELEM_SHRL_V: op = "v-vshrlv"; break;
8057 case S390_VEC_ELEM_ROLL_V: op = "v-vrollv"; break;
8058 case S390_VEC_SHL_BITS: op = "v-vshlbits"; break;
8059 case S390_VEC_SHRL_BITS: op = "v-vshrlbits"; break;
8060 case S390_VEC_SHRA_BITS: op = "v-vshrabits"; break;
8061 case S390_VEC_SHL_BYTES: op = "v-vshlbytes"; break;
8062 case S390_VEC_SHRL_BYTES: op = "v-vshrlbytes"; break;
8063 case S390_VEC_SHRA_BYTES: op = "v-vshrabytes"; break;
8064 case S390_VEC_PWSUM_W: op = "v-vpwsumw"; break;
8065 case S390_VEC_PWSUM_DW: op = "v-vpwsumdw"; break;
8066 case S390_VEC_PWSUM_QW: op = "v-vpwsumqw"; break;
8067 case S390_VEC_INIT_FROM_GPRS: op = "v-vinitfromgprs"; break;
8068 case S390_VEC_FLOAT_ADD: op = "v-vfloatadd"; break;
8069 case S390_VEC_FLOAT_SUB: op = "v-vfloatsub"; break;
8070 case S390_VEC_FLOAT_MUL: op = "v-vfloatmul"; break;
8071 case S390_VEC_FLOAT_DIV: op = "v-vfloatdiv"; break;
8072 case S390_VEC_FLOAT_COMPARE_EQUAL: op = "v-vfloatcmpeq"; break;
8073 case S390_VEC_FLOAT_COMPARE_LESS_OR_EQUAL: op = "v-vfloatcmple"; break;
8074 case S390_VEC_FLOAT_COMPARE_LESS: op = "v-vfloatcmpl"; break;
8075 default: goto fail;
8076 }
8077 s390_sprintf(buf, "%M %R, %R, %R", op, insn->variant.vec_binop.dst,
8078 insn->variant.vec_binop.op1, insn->variant.vec_binop.op2);
8079 break;
8080
8081 case S390_INSN_VEC_TRIOP:
8082 switch (insn->variant.vec_triop.tag) {
8083 case S390_VEC_PERM: op = "v-vperm"; break;
8084 case S390_VEC_FLOAT_MADD: op = "v-vfloatmadd"; break;
8085 case S390_VEC_FLOAT_MSUB: op = "v-vfloatmsub"; break;
8086 default: goto fail;
8087 }
8088 s390_sprintf(buf, "%M %R, %R, %R, %R", op, insn->variant.vec_triop.dst,
8089 insn->variant.vec_triop.op1, insn->variant.vec_triop.op2,
8090 insn->variant.vec_triop.op3);
8091 break;
8092
8093 default: goto fail;
8094 }
8095
8096 /* Write out how many bytes are involved in the operation */
8097
8098 {
8099 UInt len, i;
8100
8101 for (p = buf; *p; ++p)
8102 continue;
8103
8104 len = p - buf;
8105
8106 if (len < 32) {
8107 for (i = len; i < 32; ++i)
8108 p += vex_sprintf(p, " ");
8109 } else {
8110 p += vex_sprintf(p, "\t");
8111 }
8112 }
8113
8114 /* Special cases first */
8115 switch (insn->tag) {
8116 case S390_INSN_UNOP:
8117 switch (insn->variant.unop.tag) {
8118 case S390_SIGN_EXTEND_8:
8119 case S390_ZERO_EXTEND_8: p += vex_sprintf(p, "1 -> "); goto common;
8120 case S390_SIGN_EXTEND_16:
8121 case S390_ZERO_EXTEND_16: p += vex_sprintf(p, "2 -> "); goto common;
8122 case S390_SIGN_EXTEND_32:
8123 case S390_ZERO_EXTEND_32: p += vex_sprintf(p, "4 -> "); goto common;
8124 default:
8125 goto common;
8126 }
8127
8128 case S390_INSN_BFP_CONVERT:
8129 switch (insn->variant.bfp_convert.tag) {
8130 case S390_BFP_I32_TO_F32:
8131 case S390_BFP_I32_TO_F64:
8132 case S390_BFP_I32_TO_F128:
8133 case S390_BFP_U32_TO_F32:
8134 case S390_BFP_U32_TO_F64:
8135 case S390_BFP_U32_TO_F128:
8136 case S390_BFP_F32_TO_I32:
8137 case S390_BFP_F32_TO_I64:
8138 case S390_BFP_F32_TO_U32:
8139 case S390_BFP_F32_TO_U64:
8140 case S390_BFP_F32_TO_F64:
8141 case S390_BFP_F32_TO_F128: p += vex_sprintf(p, "4 -> "); goto common;
8142 case S390_BFP_I64_TO_F32:
8143 case S390_BFP_I64_TO_F64:
8144 case S390_BFP_I64_TO_F128:
8145 case S390_BFP_U64_TO_F32:
8146 case S390_BFP_U64_TO_F64:
8147 case S390_BFP_U64_TO_F128:
8148 case S390_BFP_F64_TO_I32:
8149 case S390_BFP_F64_TO_I64:
8150 case S390_BFP_F64_TO_U32:
8151 case S390_BFP_F64_TO_U64:
8152 case S390_BFP_F64_TO_F32:
8153 case S390_BFP_F64_TO_F128: p += vex_sprintf(p, "8 -> "); goto common;
8154 case S390_BFP_F128_TO_I32:
8155 case S390_BFP_F128_TO_I64:
8156 case S390_BFP_F128_TO_U32:
8157 case S390_BFP_F128_TO_U64:
8158 case S390_BFP_F128_TO_F32:
8159 case S390_BFP_F128_TO_F64: p += vex_sprintf(p, "16 -> "); goto common;
8160 default:
8161 goto common;
8162 }
8163
8164 case S390_INSN_DFP_CONVERT:
8165 switch (insn->variant.dfp_convert.tag) {
8166 case S390_DFP_D32_TO_D64:
8167 case S390_DFP_I32_TO_D64:
8168 case S390_DFP_I32_TO_D128:
8169 case S390_DFP_U32_TO_D64:
8170 case S390_DFP_U32_TO_D128: p += vex_sprintf(p, "4 -> "); goto common;
8171 case S390_DFP_D64_TO_D32:
8172 case S390_DFP_D64_TO_D128:
8173 case S390_DFP_I64_TO_D64:
8174 case S390_DFP_I64_TO_D128:
8175 case S390_DFP_U64_TO_D64:
8176 case S390_DFP_U64_TO_D128:
8177 case S390_DFP_D64_TO_I32:
8178 case S390_DFP_D64_TO_I64:
8179 case S390_DFP_D64_TO_U32:
8180 case S390_DFP_D64_TO_U64: p += vex_sprintf(p, "8 -> "); goto common;
8181 case S390_DFP_D128_TO_D64:
8182 case S390_DFP_D128_TO_I32:
8183 case S390_DFP_D128_TO_I64:
8184 case S390_DFP_D128_TO_U32:
8185 case S390_DFP_D128_TO_U64: p += vex_sprintf(p, "16 -> "); goto common;
8186 default:
8187 goto common;
8188 }
8189
8190 case S390_INSN_FP_CONVERT: {
8191 s390_fp_convert *fp_convert = insn->variant.fp_convert.details;
8192
8193 switch (fp_convert->tag) {
8194 case S390_FP_F32_TO_D32:
8195 case S390_FP_F32_TO_D64:
8196 case S390_FP_F32_TO_D128:
8197 case S390_FP_D32_TO_F32:
8198 case S390_FP_D32_TO_F64:
8199 case S390_FP_D32_TO_F128: p += vex_sprintf(p, "4 -> "); goto common;
8200 case S390_FP_F64_TO_D32:
8201 case S390_FP_F64_TO_D64:
8202 case S390_FP_F64_TO_D128:
8203 case S390_FP_D64_TO_F32:
8204 case S390_FP_D64_TO_F64:
8205 case S390_FP_D64_TO_F128: p += vex_sprintf(p, "8 -> "); goto common;
8206 case S390_FP_F128_TO_D32:
8207 case S390_FP_F128_TO_D64:
8208 case S390_FP_F128_TO_D128:
8209 case S390_FP_D128_TO_F32:
8210 case S390_FP_D128_TO_F64:
8211 case S390_FP_D128_TO_F128: p += vex_sprintf(p, "16 -> "); goto common;
8212 default:
8213 goto common;
8214 }
8215 }
8216
8217 default:
8218 goto common;
8219 }
8220
8221 /* Common case */
8222 common:
8223 vex_sprintf(p, "%u bytes", (UInt)insn->size);
8224
8225 return buf;
8226
8227 fail: vpanic("s390_insn_as_string");
8228 }
8229
8230
8231
8232 /* Load NUM bytes from memory into register REG using addressing mode AM. */
8233 static UChar *
s390_emit_load_mem(UChar * p,UInt num,UChar reg,const s390_amode * am)8234 s390_emit_load_mem(UChar *p, UInt num, UChar reg, const s390_amode *am)
8235 {
8236 UInt b = hregNumber(am->b);
8237 UInt x = hregNumber(am->x); /* 0 for B12 and B20 */
8238 UInt d = am->d;
8239
8240 switch (am->tag) {
8241 case S390_AMODE_B12:
8242 case S390_AMODE_BX12:
8243 switch (num) {
8244 case 1: return s390_emit_IC(p, reg, x, b, d);
8245 case 2: return s390_emit_LH(p, reg, x, b, d);
8246 case 4: return s390_emit_L(p, reg, x, b, d);
8247 case 8: return s390_emit_LG(p, reg, x, b, DISP20(d));
8248 case 16: return s390_emit_VL(p, reg, x, b, d);
8249 default: goto fail;
8250 }
8251 break;
8252
8253 case S390_AMODE_B20:
8254 case S390_AMODE_BX20:
8255 switch (num) {
8256 case 1: return s390_emit_ICY(p, reg, x, b, DISP20(d));
8257 case 2: return s390_emit_LHY(p, reg, x, b, DISP20(d));
8258 case 4: return s390_emit_LY(p, reg, x, b, DISP20(d));
8259 case 8: return s390_emit_LG(p, reg, x, b, DISP20(d));
8260 default: goto fail;
8261 }
8262 break;
8263
8264 default: goto fail;
8265 }
8266
8267 fail:
8268 vpanic("s390_emit_load_mem");
8269 }
8270
8271
8272 /* Load condition code into register REG */
8273 static UChar *
s390_emit_load_cc(UChar * p,UChar reg)8274 s390_emit_load_cc(UChar *p, UChar reg)
8275 {
8276 p = s390_emit_LGHI(p, reg, 0); /* Clear out, cc not affected */
8277 p = s390_emit_IPM(p, reg, reg);
8278 /* Shift 28 bits to the right --> [0,1,2,3] */
8279 return s390_emit_SRL(p, reg, 0, 28); /* REG = cc */
8280 }
8281
8282
8283 /*---------------------------------------------------------------*/
8284 /*--- Code generation ---*/
8285 /*---------------------------------------------------------------*/
8286
8287 /* Do not load more bytes than requested. */
8288 static UChar *
s390_insn_load_emit(UChar * buf,const s390_insn * insn)8289 s390_insn_load_emit(UChar *buf, const s390_insn *insn)
8290 {
8291 UInt r, x, b, d;
8292 const s390_amode *src;
8293
8294 src = insn->variant.load.src;
8295
8296 r = hregNumber(insn->variant.load.dst);
8297
8298 if (hregClass(insn->variant.load.dst) == HRcFlt64) {
8299 b = hregNumber(src->b);
8300 x = hregNumber(src->x); /* 0 for B12 and B20 */
8301 d = src->d;
8302
8303 switch (insn->size) {
8304
8305 case 4:
8306 switch (src->tag) {
8307 case S390_AMODE_B12:
8308 case S390_AMODE_BX12:
8309 return s390_emit_LE(buf, r, x, b, d);
8310
8311 case S390_AMODE_B20:
8312 case S390_AMODE_BX20:
8313 return s390_emit_LEY(buf, r, x, b, DISP20(d));
8314 }
8315 break;
8316
8317 case 8:
8318 switch (src->tag) {
8319 case S390_AMODE_B12:
8320 case S390_AMODE_BX12:
8321 return s390_emit_LD(buf, r, x, b, d);
8322
8323 case S390_AMODE_B20:
8324 case S390_AMODE_BX20:
8325 return s390_emit_LDY(buf, r, x, b, DISP20(d));
8326 }
8327 break;
8328 }
8329 vpanic("s390_insn_load_emit");
8330 }
8331
8332 /* Integer stuff */
8333 return s390_emit_load_mem(buf, insn->size, r, src);
8334 }
8335
8336
8337 static UChar *
s390_insn_store_emit(UChar * buf,const s390_insn * insn)8338 s390_insn_store_emit(UChar *buf, const s390_insn *insn)
8339 {
8340 UInt r, x, b, d;
8341 const s390_amode *dst;
8342
8343 dst = insn->variant.store.dst;
8344
8345 r = hregNumber(insn->variant.store.src);
8346 b = hregNumber(dst->b);
8347 x = hregNumber(dst->x); /* 0 for B12 and B20 */
8348 d = dst->d;
8349
8350 if (hregClass(insn->variant.store.src) == HRcFlt64) {
8351 switch (insn->size) {
8352
8353 case 4:
8354 switch (dst->tag) {
8355 case S390_AMODE_B12:
8356 case S390_AMODE_BX12:
8357 return s390_emit_STE(buf, r, x, b, d);
8358
8359 case S390_AMODE_B20:
8360 case S390_AMODE_BX20:
8361 return s390_emit_STEY(buf, r, x, b, DISP20(d));
8362 }
8363 break;
8364
8365 case 8:
8366 switch (dst->tag) {
8367 case S390_AMODE_B12:
8368 case S390_AMODE_BX12:
8369 return s390_emit_STD(buf, r, x, b, d);
8370
8371 case S390_AMODE_B20:
8372 case S390_AMODE_BX20:
8373 return s390_emit_STDY(buf, r, x, b, DISP20(d));
8374 }
8375 break;
8376 }
8377 vpanic("s390_insn_store_emit");
8378 }
8379
8380 if (hregClass(insn->variant.store.src) == HRcVec128) {
8381 vassert(insn->size == 16);
8382 switch (dst->tag) {
8383 case S390_AMODE_B12:
8384 case S390_AMODE_BX12:
8385 return s390_emit_VST(buf, r, x, b, d);
8386
8387 default:
8388 vpanic("s390_insn_store_emit: unknown dst->tag for HRcVec128");
8389 }
8390 }
8391 /* Integer stuff */
8392 switch (insn->size) {
8393 case 1:
8394 switch (dst->tag) {
8395 case S390_AMODE_B12:
8396 case S390_AMODE_BX12:
8397 return s390_emit_STC(buf, r, x, b, d);
8398
8399 case S390_AMODE_B20:
8400 case S390_AMODE_BX20:
8401 return s390_emit_STCY(buf, r, x, b, DISP20(d));
8402 }
8403 break;
8404
8405 case 2:
8406 switch (dst->tag) {
8407 case S390_AMODE_B12:
8408 case S390_AMODE_BX12:
8409 return s390_emit_STH(buf, r, x, b, d);
8410
8411 case S390_AMODE_B20:
8412 case S390_AMODE_BX20:
8413 return s390_emit_STHY(buf, r, x, b, DISP20(d));
8414 }
8415 break;
8416
8417 case 4:
8418 switch (dst->tag) {
8419 case S390_AMODE_B12:
8420 case S390_AMODE_BX12:
8421 return s390_emit_ST(buf, r, x, b, d);
8422
8423 case S390_AMODE_B20:
8424 case S390_AMODE_BX20:
8425 return s390_emit_STY(buf, r, x, b, DISP20(d));
8426 }
8427 break;
8428
8429 case 8:
8430 return s390_emit_STG(buf, r, x, b, DISP20(d));
8431
8432 default:
8433 break;
8434 }
8435
8436 vpanic("s390_insn_store_emit");
8437 }
8438
8439
8440 static UChar *
s390_insn_move_emit(UChar * buf,const s390_insn * insn)8441 s390_insn_move_emit(UChar *buf, const s390_insn *insn)
8442 {
8443 UInt dst, src;
8444 HRegClass dst_class, src_class;
8445
8446 dst = hregNumber(insn->variant.move.dst);
8447 src = hregNumber(insn->variant.move.src);
8448
8449 dst_class = hregClass(insn->variant.move.dst);
8450 src_class = hregClass(insn->variant.move.src);
8451
8452 if (dst_class == src_class) {
8453 if (dst_class == HRcInt64)
8454 return s390_emit_LGR(buf, dst, src);
8455 if (dst_class == HRcFlt64)
8456 return s390_emit_LDR(buf, dst, src);
8457 if (dst_class == HRcVec128) {
8458 return s390_emit_VLR(buf, dst, src);
8459 }
8460 } else {
8461 if (dst_class == HRcFlt64 && src_class == HRcInt64) {
8462 if (insn->size == 4) {
8463 buf = s390_emit_SLLG(buf, R0, src, 0, DISP20(32)); /* r0 = src << 32 */
8464 return s390_emit_LDGRw(buf, dst, R0);
8465 } else {
8466 return s390_emit_LDGRw(buf, dst, src);
8467 }
8468 }
8469 if (dst_class == HRcInt64 && src_class == HRcFlt64) {
8470 if (insn->size == 4) {
8471 buf = s390_emit_LGDRw(buf, dst, src);
8472 return s390_emit_SRLG(buf, dst, dst, 0, DISP20(32)); /* dst >>= 32 */
8473 } else {
8474 return s390_emit_LGDRw(buf, dst, src);
8475 }
8476 }
8477 /* A move between floating point registers and general purpose
8478 registers of different size should never occur and indicates
8479 an error elsewhere. */
8480 }
8481
8482 vpanic("s390_insn_move_emit");
8483 }
8484
8485
8486 static UChar *
s390_insn_memcpy_emit(UChar * buf,const s390_insn * insn)8487 s390_insn_memcpy_emit(UChar *buf, const s390_insn *insn)
8488 {
8489 s390_amode *dst = insn->variant.memcpy.dst;
8490 s390_amode *src = insn->variant.memcpy.src;
8491
8492 return s390_emit_MVC(buf, insn->size - 1, hregNumber(dst->b), dst->d,
8493 hregNumber(src->b), src->d);
8494 }
8495
8496
8497 static UChar *
s390_insn_load_immediate_emit(UChar * buf,const s390_insn * insn)8498 s390_insn_load_immediate_emit(UChar *buf, const s390_insn *insn)
8499 {
8500 UInt r;
8501 ULong value = insn->variant.load_immediate.value;
8502
8503 r = hregNumber(insn->variant.load_immediate.dst);
8504
8505 if (hregClass(insn->variant.load_immediate.dst) == HRcFlt64) {
8506 vassert(value == 0);
8507 switch (insn->size) {
8508 case 4: return s390_emit_LZER(buf, r, value);
8509 case 8: return s390_emit_LZDR(buf, r, value);
8510 }
8511 vpanic("s390_insn_load_immediate_emit");
8512 }
8513
8514 switch (insn->size) {
8515 case 1:
8516 case 2:
8517 /* Load the immediate values as a 4 byte value. That does not hurt as
8518 those extra bytes will not be looked at. Fall through .... */
8519 case 4:
8520 return s390_emit_load_32imm(buf, r, value);
8521
8522 case 8:
8523 return s390_emit_load_64imm(buf, r, value);
8524 }
8525
8526 vpanic("s390_insn_load_immediate_emit");
8527 }
8528
8529
8530 /* There is no easy way to do ALU operations on 1-byte or 2-byte operands.
8531 So we simply perform a 4-byte operation. Doing so uses possibly undefined
8532 bits and produces an undefined result in those extra bit positions. But
8533 upstream does not look at those positions, so this is OK. */
8534 static UChar *
s390_insn_alu_emit(UChar * buf,const s390_insn * insn)8535 s390_insn_alu_emit(UChar *buf, const s390_insn *insn)
8536 {
8537 s390_opnd_RMI op2;
8538 UInt dst;
8539
8540 dst = hregNumber(insn->variant.alu.dst);
8541 op2 = insn->variant.alu.op2;
8542
8543 /* Second operand is in a register */
8544 if (op2.tag == S390_OPND_REG) {
8545 UInt r2 = hregNumber(op2.variant.reg);
8546
8547 switch (insn->size) {
8548 case 1:
8549 case 2:
8550 case 4:
8551 switch (insn->variant.alu.tag) {
8552 case S390_ALU_ADD: return s390_emit_AR(buf, dst, r2);
8553 case S390_ALU_SUB: return s390_emit_SR(buf, dst, r2);
8554 case S390_ALU_MUL: return s390_emit_MSR(buf, dst, r2);
8555 case S390_ALU_AND: return s390_emit_NR(buf, dst, r2);
8556 case S390_ALU_OR: return s390_emit_OR(buf, dst, r2);
8557 case S390_ALU_XOR: return s390_emit_XR(buf, dst, r2);
8558 case S390_ALU_LSH: return s390_emit_SLL(buf, dst, r2, 0);
8559 case S390_ALU_RSH: return s390_emit_SRL(buf, dst, r2, 0);
8560 case S390_ALU_RSHA: return s390_emit_SRA(buf, dst, r2, 0);
8561 }
8562 goto fail;
8563
8564 case 8:
8565 switch (insn->variant.alu.tag) {
8566 case S390_ALU_ADD: return s390_emit_AGR(buf, dst, r2);
8567 case S390_ALU_SUB: return s390_emit_SGR(buf, dst, r2);
8568 case S390_ALU_MUL: return s390_emit_MSGR(buf, dst, r2);
8569 case S390_ALU_AND: return s390_emit_NGR(buf, dst, r2);
8570 case S390_ALU_OR: return s390_emit_OGR(buf, dst, r2);
8571 case S390_ALU_XOR: return s390_emit_XGR(buf, dst, r2);
8572 case S390_ALU_LSH: return s390_emit_SLLG(buf, dst, dst, r2, DISP20(0));
8573 case S390_ALU_RSH: return s390_emit_SRLG(buf, dst, dst, r2, DISP20(0));
8574 case S390_ALU_RSHA: return s390_emit_SRAG(buf, dst, dst, r2, DISP20(0));
8575 }
8576 goto fail;
8577 }
8578 goto fail;
8579 }
8580
8581 /* 2nd operand is in memory */
8582 if (op2.tag == S390_OPND_AMODE) {
8583 UInt b, x, d;
8584 const s390_amode *src = op2.variant.am;
8585
8586 b = hregNumber(src->b);
8587 x = hregNumber(src->x); /* 0 for B12 and B20 */
8588 d = src->d;
8589
8590 /* Shift operands are special here as there are no opcodes that
8591 allow a memory operand. So we first load the 2nd operand into
8592 some register. R0 is used to save restore the contents of the
8593 chosen register.. */
8594
8595 if (insn->variant.alu.tag == S390_ALU_LSH ||
8596 insn->variant.alu.tag == S390_ALU_RSH ||
8597 insn->variant.alu.tag == S390_ALU_RSHA) {
8598 UInt b2;
8599
8600 /* Choose a register (other than DST or R0) into which to stick the
8601 shift amount. The following works because r15 is reserved and
8602 thusly dst != 15. */
8603 vassert(dst != 15); /* extra paranoia */
8604 b2 = (dst + 1) % 16;
8605
8606 buf = s390_emit_LGR(buf, R0, b2); /* save */
8607
8608 /* Loading SRC to B2 does not modify R0. */
8609 buf = s390_emit_load_mem(buf, insn->size, b2, src);
8610
8611 if (insn->size == 8) {
8612 switch (insn->variant.alu.tag) {
8613 case S390_ALU_LSH:
8614 buf = s390_emit_SLLG(buf, dst, dst, b2, DISP20(0));
8615 break;
8616 case S390_ALU_RSH:
8617 buf = s390_emit_SRLG(buf, dst, dst, b2, DISP20(0));
8618 break;
8619 case S390_ALU_RSHA:
8620 buf = s390_emit_SRAG(buf, dst, dst, b2, DISP20(0));
8621 break;
8622 default: /* unreachable */
8623 goto fail;
8624 }
8625 } else {
8626 switch (insn->variant.alu.tag) {
8627 case S390_ALU_LSH:
8628 buf = s390_emit_SLL(buf, dst, b2, 0);
8629 break;
8630 case S390_ALU_RSH:
8631 buf = s390_emit_SRL(buf, dst, b2, 0);
8632 break;
8633 case S390_ALU_RSHA:
8634 buf = s390_emit_SRA(buf, dst, b2, 0);
8635 break;
8636 default: /* unreachable */
8637 goto fail;
8638 }
8639 }
8640 return s390_emit_LGR(buf, b2, R0); /* restore */
8641 }
8642
8643 switch (insn->size) {
8644 case 1:
8645 /* Move the byte from memory into scratch register r0 */
8646 buf = s390_emit_load_mem(buf, 1, R0, src);
8647
8648 switch (insn->variant.alu.tag) {
8649 case S390_ALU_ADD: return s390_emit_AR(buf, dst, R0);
8650 case S390_ALU_SUB: return s390_emit_SR(buf, dst, R0);
8651 case S390_ALU_MUL: return s390_emit_MSR(buf, dst, R0);
8652 case S390_ALU_AND: return s390_emit_NR(buf, dst, R0);
8653 case S390_ALU_OR: return s390_emit_OR(buf, dst, R0);
8654 case S390_ALU_XOR: return s390_emit_XR(buf, dst, R0);
8655 case S390_ALU_LSH:
8656 case S390_ALU_RSH:
8657 case S390_ALU_RSHA: ; /* avoid GCC warning */
8658 }
8659 goto fail;
8660
8661 case 2:
8662 switch (src->tag) {
8663 case S390_AMODE_B12:
8664 case S390_AMODE_BX12:
8665 switch (insn->variant.alu.tag) {
8666 case S390_ALU_ADD:
8667 return s390_emit_AH(buf, dst, x, b, d);
8668
8669 case S390_ALU_SUB:
8670 return s390_emit_SH(buf, dst, x, b, d);
8671
8672 case S390_ALU_MUL:
8673 return s390_emit_MH(buf, dst, x, b, d);
8674
8675 /* For bitwise operations: Move two bytes from memory into scratch
8676 register r0; then perform operation */
8677 case S390_ALU_AND:
8678 buf = s390_emit_LH(buf, R0, x, b, d);
8679 return s390_emit_NR(buf, dst, R0);
8680
8681 case S390_ALU_OR:
8682 buf = s390_emit_LH(buf, R0, x, b, d);
8683 return s390_emit_OR(buf, dst, R0);
8684
8685 case S390_ALU_XOR:
8686 buf = s390_emit_LH(buf, R0, x, b, d);
8687 return s390_emit_XR(buf, dst, R0);
8688
8689 case S390_ALU_LSH:
8690 case S390_ALU_RSH:
8691 case S390_ALU_RSHA: ; /* avoid GCC warning */
8692 }
8693 goto fail;
8694
8695 case S390_AMODE_B20:
8696 case S390_AMODE_BX20:
8697 switch (insn->variant.alu.tag) {
8698 case S390_ALU_ADD:
8699 return s390_emit_AHY(buf, dst, x, b, DISP20(d));
8700
8701 case S390_ALU_SUB:
8702 return s390_emit_SHY(buf, dst, x, b, DISP20(d));
8703
8704 case S390_ALU_MUL:
8705 return s390_emit_MHYw(buf, dst, x, b, DISP20(d));
8706
8707 /* For bitwise operations: Move two bytes from memory into scratch
8708 register r0; then perform operation */
8709 case S390_ALU_AND:
8710 buf = s390_emit_LHY(buf, R0, x, b, DISP20(d));
8711 return s390_emit_NR(buf, dst, R0);
8712
8713 case S390_ALU_OR:
8714 buf = s390_emit_LHY(buf, R0, x, b, DISP20(d));
8715 return s390_emit_OR(buf, dst, R0);
8716
8717 case S390_ALU_XOR:
8718 buf = s390_emit_LHY(buf, R0, x, b, DISP20(d));
8719 return s390_emit_XR(buf, dst, R0);
8720
8721 case S390_ALU_LSH:
8722 case S390_ALU_RSH:
8723 case S390_ALU_RSHA: ; /* avoid GCC warning */
8724 }
8725 goto fail;
8726 }
8727 goto fail;
8728
8729 case 4:
8730 switch (src->tag) {
8731 case S390_AMODE_B12:
8732 case S390_AMODE_BX12:
8733 switch (insn->variant.alu.tag) {
8734 case S390_ALU_ADD: return s390_emit_A(buf, dst, x, b, d);
8735 case S390_ALU_SUB: return s390_emit_S(buf, dst, x, b, d);
8736 case S390_ALU_MUL: return s390_emit_MS(buf, dst, x, b, d);
8737 case S390_ALU_AND: return s390_emit_N(buf, dst, x, b, d);
8738 case S390_ALU_OR: return s390_emit_O(buf, dst, x, b, d);
8739 case S390_ALU_XOR: return s390_emit_X(buf, dst, x, b, d);
8740 case S390_ALU_LSH:
8741 case S390_ALU_RSH:
8742 case S390_ALU_RSHA: ; /* avoid GCC warning */
8743 }
8744 goto fail;
8745
8746 case S390_AMODE_B20:
8747 case S390_AMODE_BX20:
8748 switch (insn->variant.alu.tag) {
8749 case S390_ALU_ADD: return s390_emit_AY(buf, dst, x, b, DISP20(d));
8750 case S390_ALU_SUB: return s390_emit_SY(buf, dst, x, b, DISP20(d));
8751 case S390_ALU_MUL: return s390_emit_MSY(buf, dst, x, b, DISP20(d));
8752 case S390_ALU_AND: return s390_emit_NY(buf, dst, x, b, DISP20(d));
8753 case S390_ALU_OR: return s390_emit_OY(buf, dst, x, b, DISP20(d));
8754 case S390_ALU_XOR: return s390_emit_XY(buf, dst, x, b, DISP20(d));
8755 case S390_ALU_LSH:
8756 case S390_ALU_RSH:
8757 case S390_ALU_RSHA: ; /* avoid GCC warning */
8758 }
8759 goto fail;
8760 }
8761 goto fail;
8762
8763 case 8:
8764 switch (insn->variant.alu.tag) {
8765 case S390_ALU_ADD: return s390_emit_AG(buf, dst, x, b, DISP20(d));
8766 case S390_ALU_SUB: return s390_emit_SG(buf, dst, x, b, DISP20(d));
8767 case S390_ALU_MUL: return s390_emit_MSG(buf, dst, x, b, DISP20(d));
8768 case S390_ALU_AND: return s390_emit_NG(buf, dst, x, b, DISP20(d));
8769 case S390_ALU_OR: return s390_emit_OG(buf, dst, x, b, DISP20(d));
8770 case S390_ALU_XOR: return s390_emit_XG(buf, dst, x, b, DISP20(d));
8771 case S390_ALU_LSH:
8772 case S390_ALU_RSH:
8773 case S390_ALU_RSHA: ; /* avoid GCC warning */
8774 }
8775 goto fail;
8776 }
8777 goto fail;
8778 }
8779
8780 /* 2nd operand is an immediate value */
8781 if (op2.tag == S390_OPND_IMMEDIATE) {
8782 ULong value;
8783
8784 /* No masking of the value is required as it is not sign extended */
8785 value = op2.variant.imm;
8786
8787 switch (insn->size) {
8788 case 1:
8789 case 2:
8790 /* There is no 1-byte opcode. Do the computation in
8791 2 bytes. The extra byte will be ignored. */
8792 switch (insn->variant.alu.tag) {
8793 case S390_ALU_ADD:
8794 return s390_emit_AHI(buf, dst, value);
8795
8796 case S390_ALU_SUB:
8797 return s390_emit_SLFIw(buf, dst, value);
8798
8799 case S390_ALU_MUL:
8800 return s390_emit_MHI(buf, dst, value);
8801
8802 case S390_ALU_AND: return s390_emit_NILL(buf, dst, value);
8803 case S390_ALU_OR: return s390_emit_OILL(buf, dst, value);
8804 case S390_ALU_XOR:
8805 /* There is no XILL instruction. Load the immediate value into
8806 R0 and combine with the destination register. */
8807 buf = s390_emit_LHI(buf, R0, value);
8808 return s390_emit_XR(buf, dst, R0);
8809
8810 case S390_ALU_LSH:
8811 return s390_emit_SLL(buf, dst, 0, value);
8812
8813 case S390_ALU_RSH:
8814 return s390_emit_SRL(buf, dst, 0, value);
8815
8816 case S390_ALU_RSHA:
8817 return s390_emit_SRA(buf, dst, 0, value);
8818 }
8819 goto fail;
8820
8821 case 4:
8822 switch (insn->variant.alu.tag) {
8823 case S390_ALU_ADD:
8824 if (uint_fits_signed_16bit(value)) {
8825 return s390_emit_AHI(buf, dst, value);
8826 }
8827 return s390_emit_AFIw(buf, dst, value);
8828
8829 case S390_ALU_SUB: return s390_emit_SLFIw(buf, dst, value);
8830 case S390_ALU_MUL: return s390_emit_MSFIw(buf, dst, value);
8831 case S390_ALU_AND: return s390_emit_NILFw(buf, dst, value);
8832 case S390_ALU_OR: return s390_emit_OILFw(buf, dst, value);
8833 case S390_ALU_XOR: return s390_emit_XILFw(buf, dst, value);
8834 case S390_ALU_LSH: return s390_emit_SLL(buf, dst, 0, value);
8835 case S390_ALU_RSH: return s390_emit_SRL(buf, dst, 0, value);
8836 case S390_ALU_RSHA: return s390_emit_SRA(buf, dst, 0, value);
8837 }
8838 goto fail;
8839
8840 case 8:
8841 switch (insn->variant.alu.tag) {
8842 case S390_ALU_ADD:
8843 if (ulong_fits_signed_16bit(value)) {
8844 return s390_emit_AGHI(buf, dst, value);
8845 }
8846 if (ulong_fits_signed_32bit(value) && s390_host_has_eimm) {
8847 return s390_emit_AGFI(buf, dst, value);
8848 }
8849 /* Load constant into R0 then add */
8850 buf = s390_emit_load_64imm(buf, R0, value);
8851 return s390_emit_AGR(buf, dst, R0);
8852
8853 case S390_ALU_SUB:
8854 if (ulong_fits_unsigned_32bit(value)) {
8855 return s390_emit_SLGFIw(buf, dst, value);
8856 }
8857 /* Load value into R0; then subtract from destination reg */
8858 buf = s390_emit_load_64imm(buf, R0, value);
8859 return s390_emit_SGR(buf, dst, R0);
8860
8861 case S390_ALU_MUL:
8862 if (ulong_fits_signed_32bit(value) && s390_host_has_gie) {
8863 return s390_emit_MSGFI(buf, dst, value);
8864 }
8865 /* Load constant into R0 then add */
8866 buf = s390_emit_load_64imm(buf, R0, value);
8867 return s390_emit_MSGR(buf, dst, R0);
8868
8869 /* Do it in two steps: upper half [0:31] and lower half [32:63] */
8870 case S390_ALU_AND:
8871 if (s390_host_has_eimm) {
8872 buf = s390_emit_NIHF(buf, dst, value >> 32);
8873 return s390_emit_NILF(buf, dst, value & 0xFFFFFFFF);
8874 }
8875 /* Load value into R0; then combine with destination reg */
8876 buf = s390_emit_load_64imm(buf, R0, value);
8877 return s390_emit_NGR(buf, dst, R0);
8878
8879 case S390_ALU_OR:
8880 if (s390_host_has_eimm) {
8881 buf = s390_emit_OIHF(buf, dst, value >> 32);
8882 return s390_emit_OILF(buf, dst, value & 0xFFFFFFFF);
8883 }
8884 /* Load value into R0; then combine with destination reg */
8885 buf = s390_emit_load_64imm(buf, R0, value);
8886 return s390_emit_OGR(buf, dst, R0);
8887
8888 case S390_ALU_XOR:
8889 if (s390_host_has_eimm) {
8890 buf = s390_emit_XIHF(buf, dst, value >> 32);
8891 return s390_emit_XILF(buf, dst, value & 0xFFFFFFFF);
8892 }
8893 /* Load value into R0; then combine with destination reg */
8894 buf = s390_emit_load_64imm(buf, R0, value);
8895 return s390_emit_XGR(buf, dst, R0);
8896
8897 /* No special considerations for long displacement here. Only the six
8898 least significant bits of VALUE will be taken; all other bits are
8899 ignored. So the DH2 bits are irrelevant and do not influence the
8900 shift operation, independent of whether long-displacement is available
8901 or not. */
8902 case S390_ALU_LSH: return s390_emit_SLLG(buf, dst, dst, 0, DISP20(value));
8903 case S390_ALU_RSH: return s390_emit_SRLG(buf, dst, dst, 0, DISP20(value));
8904 case S390_ALU_RSHA: return s390_emit_SRAG(buf, dst, dst, 0, DISP20(value));
8905 }
8906 goto fail;
8907 }
8908 goto fail;
8909 }
8910
8911 fail:
8912 vpanic("s390_insn_alu_emit");
8913 }
8914
8915
8916 static UChar *
s390_widen_emit(UChar * buf,const s390_insn * insn,UInt from_size,Bool sign_extend)8917 s390_widen_emit(UChar *buf, const s390_insn *insn, UInt from_size,
8918 Bool sign_extend)
8919 {
8920 s390_opnd_RMI opnd = insn->variant.unop.src;
8921
8922 switch (opnd.tag) {
8923 case S390_OPND_REG: {
8924 UChar r1 = hregNumber(insn->variant.unop.dst);
8925 UChar r2 = hregNumber(opnd.variant.reg);
8926
8927 switch (from_size) {
8928 case 1:
8929 /* Widening to a half-word is implemented like widening to a word
8930 because the upper half-word will not be looked at. */
8931 if (insn->size == 4 || insn->size == 2) { /* 8 --> 32 8 --> 16 */
8932 if (sign_extend)
8933 return s390_emit_LBRw(buf, r1, r2);
8934 else
8935 return s390_emit_LLCRw(buf, r1, r2);
8936 }
8937 if (insn->size == 8) { /* 8 --> 64 */
8938 if (sign_extend)
8939 return s390_emit_LGBRw(buf, r1, r2);
8940 else
8941 return s390_emit_LLGCRw(buf, r1, r2);
8942 }
8943 goto fail;
8944
8945 case 2:
8946 if (insn->size == 4) { /* 16 --> 32 */
8947 if (sign_extend)
8948 return s390_emit_LHRw(buf, r1, r2);
8949 else
8950 return s390_emit_LLHRw(buf, r1, r2);
8951 }
8952 if (insn->size == 8) { /* 16 --> 64 */
8953 if (sign_extend)
8954 return s390_emit_LGHRw(buf, r1, r2);
8955 else
8956 return s390_emit_LLGHRw(buf, r1, r2);
8957 }
8958 goto fail;
8959
8960 case 4:
8961 if (insn->size == 8) { /* 32 --> 64 */
8962 if (sign_extend)
8963 return s390_emit_LGFR(buf, r1, r2);
8964 else
8965 return s390_emit_LLGFR(buf, r1, r2);
8966 }
8967 goto fail;
8968
8969 default: /* unexpected "from" size */
8970 goto fail;
8971 }
8972 }
8973
8974 case S390_OPND_AMODE: {
8975 UChar r1 = hregNumber(insn->variant.unop.dst);
8976 const s390_amode *src = opnd.variant.am;
8977 UChar b = hregNumber(src->b);
8978 UChar x = hregNumber(src->x);
8979 Int d = src->d;
8980
8981 switch (from_size) {
8982 case 1:
8983 if (insn->size == 4 || insn->size == 2) {
8984 if (sign_extend)
8985 return s390_emit_LB(buf, r1, x, b, DISP20(d));
8986 else
8987 return s390_emit_LLCw(buf, r1, x, b, DISP20(d));
8988 }
8989 if (insn->size == 8) {
8990 if (sign_extend)
8991 return s390_emit_LGB(buf, r1, x, b, DISP20(d));
8992 else
8993 return s390_emit_LLGC(buf, r1, x, b, DISP20(d));
8994 }
8995 goto fail;
8996
8997 case 2:
8998 if (insn->size == 4) { /* 16 --> 32 */
8999 if (sign_extend == 0)
9000 return s390_emit_LLHw(buf, r1, x, b, DISP20(d));
9001
9002 switch (src->tag) {
9003 case S390_AMODE_B12:
9004 case S390_AMODE_BX12:
9005 return s390_emit_LH(buf, r1, x, b, d);
9006
9007 case S390_AMODE_B20:
9008 case S390_AMODE_BX20:
9009 return s390_emit_LHY(buf, r1, x, b, DISP20(d));
9010 }
9011 goto fail;
9012 }
9013 if (insn->size == 8) { /* 16 --> 64 */
9014 if (sign_extend)
9015 return s390_emit_LGH(buf, r1, x, b, DISP20(d));
9016 else
9017 return s390_emit_LLGH(buf, r1, x, b, DISP20(d));
9018 }
9019 goto fail;
9020
9021 case 4:
9022 if (insn->size == 8) { /* 32 --> 64 */
9023 if (sign_extend)
9024 return s390_emit_LGF(buf, r1, x, b, DISP20(d));
9025 else
9026 return s390_emit_LLGF(buf, r1, x, b, DISP20(d));
9027 }
9028 goto fail;
9029
9030 default: /* unexpected "from" size */
9031 goto fail;
9032 }
9033 }
9034
9035 case S390_OPND_IMMEDIATE: {
9036 UChar r1 = hregNumber(insn->variant.unop.dst);
9037 ULong value = opnd.variant.imm;
9038
9039 switch (from_size) {
9040 case 1:
9041 if (insn->size == 4 || insn->size == 2) { /* 8 --> 32 8 --> 16 */
9042 if (sign_extend) {
9043 /* host can do the sign extension to 16-bit; LHI does the rest */
9044 return s390_emit_LHI(buf, r1, (Short)(Char)(UChar)value);
9045 } else {
9046 return s390_emit_LHI(buf, r1, value);
9047 }
9048 }
9049 if (insn->size == 8) { /* 8 --> 64 */
9050 if (sign_extend) {
9051 /* host can do the sign extension to 16-bit; LGHI does the rest */
9052 return s390_emit_LGHI(buf, r1, (Short)(Char)(UChar)value);
9053 } else {
9054 return s390_emit_LGHI(buf, r1, value);
9055 }
9056 }
9057 goto fail;
9058
9059 case 2:
9060 if (insn->size == 4) { /* 16 --> 32 */
9061 return s390_emit_LHI(buf, r1, value);
9062 }
9063 if (insn->size == 8) { /* 16 --> 64 */
9064 if (sign_extend)
9065 return s390_emit_LGHI(buf, r1, value);
9066 else
9067 return s390_emit_LLILL(buf, r1, value);
9068 }
9069 goto fail;
9070
9071 case 4:
9072 if (insn->size == 8) { /* 32 --> 64 */
9073 if (sign_extend)
9074 return s390_emit_LGFIw(buf, r1, value);
9075 else
9076 return s390_emit_LLILFw(buf, r1, value);
9077 }
9078 goto fail;
9079
9080 default: /* unexpected "from" size */
9081 goto fail;
9082 }
9083 }
9084 }
9085
9086 fail:
9087 vpanic("s390_widen_emit");
9088 }
9089
9090
9091 static UChar *
s390_negate_emit(UChar * buf,const s390_insn * insn)9092 s390_negate_emit(UChar *buf, const s390_insn *insn)
9093 {
9094 s390_opnd_RMI opnd;
9095
9096 opnd = insn->variant.unop.src;
9097
9098 switch (opnd.tag) {
9099 case S390_OPND_REG: {
9100 UChar r1 = hregNumber(insn->variant.unop.dst);
9101 UChar r2 = hregNumber(opnd.variant.reg);
9102
9103 switch (insn->size) {
9104 case 1:
9105 case 2:
9106 case 4:
9107 return s390_emit_LCR(buf, r1, r2);
9108
9109 case 8:
9110 return s390_emit_LCGR(buf, r1, r2);
9111
9112 default:
9113 goto fail;
9114 }
9115 }
9116
9117 case S390_OPND_AMODE: {
9118 UChar r1 = hregNumber(insn->variant.unop.dst);
9119
9120 /* Load bytes into scratch register R0, then negate */
9121 buf = s390_emit_load_mem(buf, insn->size, R0, opnd.variant.am);
9122
9123 switch (insn->size) {
9124 case 1:
9125 case 2:
9126 case 4:
9127 return s390_emit_LCR(buf, r1, R0);
9128
9129 case 8:
9130 return s390_emit_LCGR(buf, r1, R0);
9131
9132 default:
9133 goto fail;
9134 }
9135 }
9136
9137 case S390_OPND_IMMEDIATE: {
9138 UChar r1 = hregNumber(insn->variant.unop.dst);
9139 ULong value = opnd.variant.imm;
9140
9141 value = ~value + 1; /* two's complement */
9142
9143 switch (insn->size) {
9144 case 1:
9145 case 2:
9146 /* Load the immediate values as a 4 byte value. That does not hurt as
9147 those extra bytes will not be looked at. Fall through .... */
9148 case 4:
9149 return s390_emit_load_32imm(buf, r1, value);
9150
9151 case 8:
9152 return s390_emit_load_64imm(buf, r1, value);
9153
9154 default:
9155 goto fail;
9156 }
9157 }
9158 }
9159
9160 fail:
9161 vpanic("s390_negate_emit");
9162 }
9163
9164
9165 static UChar *
s390_insn_unop_emit(UChar * buf,const s390_insn * insn)9166 s390_insn_unop_emit(UChar *buf, const s390_insn *insn)
9167 {
9168 switch (insn->variant.unop.tag) {
9169 case S390_ZERO_EXTEND_8: return s390_widen_emit(buf, insn, 1, 0);
9170 case S390_ZERO_EXTEND_16: return s390_widen_emit(buf, insn, 2, 0);
9171 case S390_ZERO_EXTEND_32: return s390_widen_emit(buf, insn, 4, 0);
9172
9173 case S390_SIGN_EXTEND_8: return s390_widen_emit(buf, insn, 1, 1);
9174 case S390_SIGN_EXTEND_16: return s390_widen_emit(buf, insn, 2, 1);
9175 case S390_SIGN_EXTEND_32: return s390_widen_emit(buf, insn, 4, 1);
9176
9177 case S390_NEGATE: return s390_negate_emit(buf, insn);
9178 case S390_VEC_FILL: {
9179 vassert(insn->variant.unop.src.tag == S390_OPND_IMMEDIATE);
9180 UChar v1 = hregNumber(insn->variant.unop.dst);
9181 UShort i2 = insn->variant.unop.src.variant.imm;
9182 return s390_emit_VGBM(buf, v1, i2);
9183 }
9184 case S390_VEC_DUPLICATE: {
9185 vassert(insn->variant.unop.src.tag == S390_OPND_REG);
9186 UChar v1 = hregNumber(insn->variant.unop.dst);
9187 UChar v2 = hregNumber(insn->variant.unop.src.variant.reg);
9188 return s390_emit_VREP(buf, v1, v2, s390_getM_from_size(insn->size));
9189 }
9190 case S390_VEC_UNPACKLOWS: {
9191 vassert(insn->variant.unop.src.tag == S390_OPND_REG);
9192 vassert(insn->size < 8);
9193 UChar v1 = hregNumber(insn->variant.unop.dst);
9194 UChar v2 = hregNumber(insn->variant.unop.src.variant.reg);
9195 return s390_emit_VUPH(buf, v1, v2, s390_getM_from_size(insn->size));
9196 }
9197 case S390_VEC_UNPACKLOWU: {
9198 vassert(insn->variant.unop.src.tag == S390_OPND_REG);
9199 vassert(insn->size < 8);
9200 UChar v1 = hregNumber(insn->variant.unop.dst);
9201 UChar v2 = hregNumber(insn->variant.unop.src.variant.reg);
9202 return s390_emit_VUPLH(buf, v1, v2, s390_getM_from_size(insn->size));
9203 }
9204
9205 case S390_VEC_ABS:{
9206 vassert(insn->variant.unop.src.tag == S390_OPND_REG);
9207 UChar v1 = hregNumber(insn->variant.unop.dst);
9208 UChar v2 = hregNumber(insn->variant.unop.src.variant.reg);
9209 return s390_emit_VLP(buf, v1, v2, s390_getM_from_size(insn->size));
9210 }
9211
9212 case S390_VEC_COUNT_LEADING_ZEROES:{
9213 vassert(insn->variant.unop.src.tag == S390_OPND_REG);
9214 UChar v1 = hregNumber(insn->variant.unop.dst);
9215 UChar v2 = hregNumber(insn->variant.unop.src.variant.reg);
9216 return s390_emit_VCLZ(buf, v1, v2, s390_getM_from_size(insn->size));
9217 }
9218
9219 case S390_VEC_COUNT_TRAILING_ZEROES:{
9220 vassert(insn->variant.unop.src.tag == S390_OPND_REG);
9221 UChar v1 = hregNumber(insn->variant.unop.dst);
9222 UChar v2 = hregNumber(insn->variant.unop.src.variant.reg);
9223 return s390_emit_VCTZ(buf, v1, v2, s390_getM_from_size(insn->size));
9224 }
9225
9226 case S390_VEC_COUNT_ONES:{
9227 vassert(insn->variant.unop.src.tag == S390_OPND_REG);
9228 UChar v1 = hregNumber(insn->variant.unop.dst);
9229 UChar v2 = hregNumber(insn->variant.unop.src.variant.reg);
9230 return s390_emit_VPOPCT(buf, v1, v2, s390_getM_from_size(insn->size));
9231 }
9232
9233 case S390_VEC_FLOAT_NEG: {
9234 vassert(insn->variant.unop.src.tag == S390_OPND_REG);
9235 vassert(insn->size == 8);
9236 UChar v1 = hregNumber(insn->variant.unop.dst);
9237 UChar v2 = hregNumber(insn->variant.unop.src.variant.reg);
9238 return s390_emit_VFPSO(buf, v1, v2, s390_getM_from_size(insn->size), 0, 0);
9239 }
9240 case S390_VEC_FLOAT_ABS: {
9241 vassert(insn->variant.unop.src.tag == S390_OPND_REG);
9242 vassert(insn->size == 8);
9243 UChar v1 = hregNumber(insn->variant.unop.dst);
9244 UChar v2 = hregNumber(insn->variant.unop.src.variant.reg);
9245 return s390_emit_VFPSO(buf, v1, v2, s390_getM_from_size(insn->size), 0, 2);
9246 }
9247 case S390_VEC_FLOAT_SQRT: {
9248 vassert(insn->variant.unop.src.tag == S390_OPND_REG);
9249 vassert(insn->size == 8);
9250 UChar v1 = hregNumber(insn->variant.unop.dst);
9251 UChar v2 = hregNumber(insn->variant.unop.src.variant.reg);
9252 return s390_emit_VFSQ(buf, v1, v2, s390_getM_from_size(insn->size), 0);
9253 }
9254 default:
9255 vpanic("s390_insn_unop_emit");
9256 }
9257 }
9258
9259
9260 /* Only 4-byte and 8-byte operands are handled. 1-byte and 2-byte
9261 comparisons will have been converted to 4-byte comparisons in
9262 s390_isel_cc and should not occur here. */
9263 static UChar *
s390_insn_test_emit(UChar * buf,const s390_insn * insn)9264 s390_insn_test_emit(UChar *buf, const s390_insn *insn)
9265 {
9266 s390_opnd_RMI opnd;
9267
9268 opnd = insn->variant.test.src;
9269
9270 switch (opnd.tag) {
9271 case S390_OPND_REG: {
9272 UInt reg = hregNumber(opnd.variant.reg);
9273
9274 switch (insn->size) {
9275 case 4:
9276 return s390_emit_LTR(buf, reg, reg);
9277
9278 case 8:
9279 return s390_emit_LTGR(buf, reg, reg);
9280
9281 default:
9282 goto fail;
9283 }
9284 }
9285
9286 case S390_OPND_AMODE: {
9287 const s390_amode *am = opnd.variant.am;
9288 UChar b = hregNumber(am->b);
9289 UChar x = hregNumber(am->x);
9290 Int d = am->d;
9291
9292 switch (insn->size) {
9293 case 4:
9294 return s390_emit_LTw(buf, R0, x, b, DISP20(d));
9295
9296 case 8:
9297 return s390_emit_LTGw(buf, R0, x, b, DISP20(d));
9298
9299 default:
9300 goto fail;
9301 }
9302 }
9303
9304 case S390_OPND_IMMEDIATE: {
9305 ULong value = opnd.variant.imm;
9306
9307 switch (insn->size) {
9308 case 4:
9309 buf = s390_emit_load_32imm(buf, R0, value);
9310 return s390_emit_LTR(buf, R0, R0);
9311
9312 case 8:
9313 buf = s390_emit_load_64imm(buf, R0, value);
9314 return s390_emit_LTGR(buf, R0, R0);
9315
9316 default:
9317 goto fail;
9318 }
9319 }
9320
9321 default:
9322 goto fail;
9323 }
9324
9325 fail:
9326 vpanic("s390_insn_test_emit");
9327 }
9328
9329
9330 static UChar *
s390_insn_cc2bool_emit(UChar * buf,const s390_insn * insn)9331 s390_insn_cc2bool_emit(UChar *buf, const s390_insn *insn)
9332 {
9333 UChar r1 = hregNumber(insn->variant.cc2bool.dst);
9334 s390_cc_t cond = insn->variant.cc2bool.cond;
9335
9336 /* Make the destination register be 1 or 0, depending on whether
9337 the relevant condition holds. A 64-bit value is computed. */
9338 if (cond == S390_CC_ALWAYS)
9339 return s390_emit_LGHI(buf, r1, 1); /* r1 = 1 */
9340
9341 buf = s390_emit_load_cc(buf, r1); /* r1 = cc */
9342 buf = s390_emit_LGHI(buf, R0, cond); /* r0 = mask */
9343 buf = s390_emit_SLLG(buf, r1, R0, r1, DISP20(0)); /* r1 = mask << cc */
9344 buf = s390_emit_SRLG(buf, r1, r1, 0, DISP20(3)); /* r1 = r1 >> 3 */
9345 buf = s390_emit_NILL(buf, r1, 1); /* r1 = r1 & 0x1 */
9346
9347 return buf;
9348 }
9349
9350
9351 /* Only 4-byte and 8-byte operands are handled. */
9352 static UChar *
s390_insn_cas_emit(UChar * buf,const s390_insn * insn)9353 s390_insn_cas_emit(UChar *buf, const s390_insn *insn)
9354 {
9355 UChar r1, r3, b, old;
9356 Int d;
9357 s390_amode *am;
9358
9359 r1 = hregNumber(insn->variant.cas.op1); /* expected value */
9360 r3 = hregNumber(insn->variant.cas.op3);
9361 old= hregNumber(insn->variant.cas.old_mem);
9362 am = insn->variant.cas.op2;
9363 b = hregNumber(am->b);
9364 d = am->d;
9365
9366 vassert(am->tag == S390_AMODE_B12 || am->tag == S390_AMODE_B20);
9367
9368 switch (insn->size) {
9369 case 4:
9370 /* r1 must not be overwritten. So copy it to R0 and let CS clobber it */
9371 buf = s390_emit_LR(buf, R0, r1);
9372 if (am->tag == S390_AMODE_B12)
9373 buf = s390_emit_CS(buf, R0, r3, b, d);
9374 else
9375 buf = s390_emit_CSY(buf, R0, r3, b, DISP20(d));
9376 /* Now copy R0 which has the old memory value to OLD */
9377 return s390_emit_LR(buf, old, R0);
9378
9379 case 8:
9380 /* r1 must not be overwritten. So copy it to R0 and let CS clobber it */
9381 buf = s390_emit_LGR(buf, R0, r1);
9382 buf = s390_emit_CSG(buf, R0, r3, b, DISP20(d));
9383 /* Now copy R0 which has the old memory value to OLD */
9384 return s390_emit_LGR(buf, old, R0);
9385
9386 default:
9387 goto fail;
9388 }
9389
9390 fail:
9391 vpanic("s390_insn_cas_emit");
9392 }
9393
9394
9395 /* Only 4-byte and 8-byte operands are handled. */
9396 static UChar *
s390_insn_cdas_emit(UChar * buf,const s390_insn * insn)9397 s390_insn_cdas_emit(UChar *buf, const s390_insn *insn)
9398 {
9399 UChar r1, r1p1, r3, /*r3p1,*/ b, old_high, old_low, scratch;
9400 Int d;
9401 s390_amode *am;
9402 s390_cdas *cdas = insn->variant.cdas.details;
9403
9404 r1 = hregNumber(cdas->op1_high); /* expected value */
9405 r1p1 = hregNumber(cdas->op1_low); /* expected value */
9406 r3 = hregNumber(cdas->op3_high);
9407 /* r3p1 = hregNumber(cdas->op3_low); */ /* unused */
9408 old_high = hregNumber(cdas->old_mem_high);
9409 old_low = hregNumber(cdas->old_mem_low);
9410 scratch = hregNumber(cdas->scratch);
9411 am = cdas->op2;
9412 b = hregNumber(am->b);
9413 d = am->d;
9414
9415 vassert(scratch == 1);
9416 vassert(am->tag == S390_AMODE_B12 || am->tag == S390_AMODE_B20);
9417
9418 switch (insn->size) {
9419 case 4:
9420 /* r1, r1+1 must not be overwritten. So copy them to R0,scratch
9421 and let CDS/CDSY clobber it */
9422 buf = s390_emit_LR(buf, R0, r1);
9423 buf = s390_emit_LR(buf, scratch, r1p1);
9424
9425 if (am->tag == S390_AMODE_B12)
9426 buf = s390_emit_CDS(buf, R0, r3, b, d);
9427 else
9428 buf = s390_emit_CDSY(buf, R0, r3, b, DISP20(d));
9429
9430 /* Now copy R0,scratch which has the old memory value to OLD */
9431 buf = s390_emit_LR(buf, old_high, R0);
9432 buf = s390_emit_LR(buf, old_low, scratch);
9433 return buf;
9434
9435 case 8:
9436 /* r1, r1+1 must not be overwritten. So copy them to R0,scratch
9437 and let CDSG clobber it */
9438 buf = s390_emit_LGR(buf, R0, r1);
9439 buf = s390_emit_LGR(buf, scratch, r1p1);
9440
9441 buf = s390_emit_CDSG(buf, R0, r3, b, DISP20(d));
9442
9443 /* Now copy R0,scratch which has the old memory value to OLD */
9444 buf = s390_emit_LGR(buf, old_high, R0);
9445 buf = s390_emit_LGR(buf, old_low, scratch);
9446 return buf;
9447
9448 default:
9449 goto fail;
9450 }
9451
9452 fail:
9453 vpanic("s390_insn_cdas_emit");
9454 }
9455
9456
9457 /* Only 4-byte and 8-byte comparisons are handled. 1-byte and 2-byte
9458 comparisons will have been converted to 4-byte comparisons in
9459 s390_isel_cc and should not occur here. */
9460 static UChar *
s390_insn_compare_emit(UChar * buf,const s390_insn * insn)9461 s390_insn_compare_emit(UChar *buf, const s390_insn *insn)
9462 {
9463 s390_opnd_RMI op2;
9464 HReg op1;
9465 Bool signed_comparison;
9466
9467 op1 = insn->variant.compare.src1;
9468 op2 = insn->variant.compare.src2;
9469 signed_comparison = insn->variant.compare.signed_comparison;
9470
9471 switch (op2.tag) {
9472 case S390_OPND_REG: {
9473 UInt r1 = hregNumber(op1);
9474 UInt r2 = hregNumber(op2.variant.reg);
9475
9476 switch (insn->size) {
9477 case 4:
9478 if (signed_comparison)
9479 return s390_emit_CR(buf, r1, r2);
9480 else
9481 return s390_emit_CLR(buf, r1, r2);
9482
9483 case 8:
9484 if (signed_comparison)
9485 return s390_emit_CGR(buf, r1, r2);
9486 else
9487 return s390_emit_CLGR(buf, r1, r2);
9488
9489 default:
9490 goto fail;
9491 }
9492 }
9493
9494 case S390_OPND_AMODE: {
9495 UChar r1 = hregNumber(op1);
9496 const s390_amode *am = op2.variant.am;
9497 UChar b = hregNumber(am->b);
9498 UChar x = hregNumber(am->x);
9499 Int d = am->d;
9500
9501 switch (insn->size) {
9502 case 4:
9503 switch (am->tag) {
9504 case S390_AMODE_B12:
9505 case S390_AMODE_BX12:
9506 if (signed_comparison)
9507 return s390_emit_C(buf, r1, x, b, d);
9508 else
9509 return s390_emit_CL(buf, r1, x, b, d);
9510
9511 case S390_AMODE_B20:
9512 case S390_AMODE_BX20:
9513 if (signed_comparison)
9514 return s390_emit_CY(buf, r1, x, b, DISP20(d));
9515 else
9516 return s390_emit_CLY(buf, r1, x, b, DISP20(d));
9517 }
9518 goto fail;
9519
9520 case 8:
9521 if (signed_comparison)
9522 return s390_emit_CG(buf, r1, x, b, DISP20(d));
9523 else
9524 return s390_emit_CLG(buf, r1, x, b, DISP20(d));
9525
9526 default:
9527 goto fail;
9528 }
9529 }
9530
9531 case S390_OPND_IMMEDIATE: {
9532 UChar r1 = hregNumber(op1);
9533 ULong value = op2.variant.imm;
9534
9535 switch (insn->size) {
9536 case 4:
9537 if (signed_comparison)
9538 return s390_emit_CFIw(buf, r1, value);
9539 else
9540 return s390_emit_CLFIw(buf, r1, value);
9541
9542 case 8:
9543 if (s390_host_has_eimm) {
9544 if (signed_comparison) {
9545 if (ulong_fits_signed_32bit(value))
9546 return s390_emit_CGFI(buf, r1, value);
9547 } else {
9548 if (ulong_fits_unsigned_32bit(value))
9549 return s390_emit_CLGFI(buf, r1, value);
9550 }
9551 }
9552 buf = s390_emit_load_64imm(buf, R0, value);
9553 if (signed_comparison)
9554 return s390_emit_CGR(buf, r1, R0);
9555 else
9556 return s390_emit_CLGR(buf, r1, R0);
9557
9558 default:
9559 goto fail;
9560 }
9561 }
9562
9563 default:
9564 goto fail;
9565 }
9566
9567 fail:
9568 vpanic("s390_insn_compare_emit");
9569 }
9570
9571
9572 static UChar *
s390_insn_mul_emit(UChar * buf,const s390_insn * insn)9573 s390_insn_mul_emit(UChar *buf, const s390_insn *insn)
9574 {
9575 s390_opnd_RMI op2;
9576 UChar r1;
9577 Bool signed_multiply;
9578
9579 /* The register number identifying the register pair */
9580 r1 = hregNumber(insn->variant.mul.dst_hi);
9581
9582 op2 = insn->variant.mul.op2;
9583 signed_multiply = insn->tag == S390_INSN_SMUL;
9584
9585 switch (op2.tag) {
9586 case S390_OPND_REG: {
9587 UInt r2 = hregNumber(op2.variant.reg);
9588
9589 switch (insn->size) {
9590 case 1:
9591 case 2:
9592 case 4:
9593 if (signed_multiply)
9594 return s390_emit_MR(buf, r1, r2);
9595 else
9596 return s390_emit_MLR(buf, r1, r2);
9597
9598 case 8:
9599 if (signed_multiply)
9600 vpanic("s390_insn_mul_emit");
9601 else
9602 return s390_emit_MLGR(buf, r1, r2);
9603
9604 default:
9605 goto fail;
9606 }
9607 }
9608
9609 case S390_OPND_AMODE: {
9610 const s390_amode *am = op2.variant.am;
9611 UChar b = hregNumber(am->b);
9612 UChar x = hregNumber(am->x);
9613 Int d = am->d;
9614
9615 switch (insn->size) {
9616 case 1:
9617 case 2:
9618 /* Load bytes into scratch register R0, then multiply */
9619 buf = s390_emit_load_mem(buf, insn->size, R0, am);
9620 if (signed_multiply)
9621 return s390_emit_MR(buf, r1, R0);
9622 else
9623 return s390_emit_MLR(buf, r1, R0);
9624
9625 case 4:
9626 switch (am->tag) {
9627 case S390_AMODE_B12:
9628 case S390_AMODE_BX12:
9629 if (signed_multiply)
9630 return s390_emit_M(buf, r1, x, b, d);
9631 else
9632 return s390_emit_ML(buf, r1, x, b, DISP20(d));
9633
9634 case S390_AMODE_B20:
9635 case S390_AMODE_BX20:
9636 if (signed_multiply)
9637 return s390_emit_MFYw(buf, r1, x, b, DISP20(d));
9638 else
9639 return s390_emit_ML(buf, r1, x, b, DISP20(d));
9640 }
9641 goto fail;
9642
9643 case 8:
9644 if (signed_multiply)
9645 vpanic("s390_insn_mul_emit");
9646 else
9647 return s390_emit_MLG(buf, r1, x, b, DISP20(d));
9648
9649 default:
9650 goto fail;
9651 }
9652 }
9653
9654 case S390_OPND_IMMEDIATE: {
9655 ULong value = op2.variant.imm;
9656
9657 switch (insn->size) {
9658 case 1:
9659 case 2:
9660 case 4:
9661 buf = s390_emit_load_32imm(buf, R0, value);
9662 if (signed_multiply)
9663 return s390_emit_MR(buf, r1, R0);
9664 else
9665 return s390_emit_MLR(buf, r1, R0);
9666
9667 case 8:
9668 buf = s390_emit_load_64imm(buf, R0, value);
9669 if (signed_multiply)
9670 vpanic("s390_insn_mul_emit");
9671 else
9672 return s390_emit_MLGR(buf, r1, R0);
9673
9674 default:
9675 goto fail;
9676 }
9677 }
9678
9679 default:
9680 goto fail;
9681 }
9682
9683 fail:
9684 vpanic("s390_insn_mul_emit");
9685 }
9686
9687
9688 static UChar *
s390_insn_div_emit(UChar * buf,const s390_insn * insn)9689 s390_insn_div_emit(UChar *buf, const s390_insn *insn)
9690 {
9691 s390_opnd_RMI op2;
9692 UChar r1;
9693 Bool signed_divide;
9694
9695 r1 = hregNumber(insn->variant.div.op1_hi);
9696 op2 = insn->variant.div.op2;
9697 signed_divide = insn->tag == S390_INSN_SDIV;
9698
9699 switch (op2.tag) {
9700 case S390_OPND_REG: {
9701 UInt r2 = hregNumber(op2.variant.reg);
9702
9703 switch (insn->size) {
9704 case 4:
9705 if (signed_divide)
9706 return s390_emit_DR(buf, r1, r2);
9707 else
9708 return s390_emit_DLR(buf, r1, r2);
9709
9710 case 8:
9711 if (signed_divide)
9712 vpanic("s390_insn_div_emit");
9713 else
9714 return s390_emit_DLGR(buf, r1, r2);
9715
9716 default:
9717 goto fail;
9718 }
9719 }
9720
9721 case S390_OPND_AMODE: {
9722 const s390_amode *am = op2.variant.am;
9723 UChar b = hregNumber(am->b);
9724 UChar x = hregNumber(am->x);
9725 Int d = am->d;
9726
9727 switch (insn->size) {
9728 case 4:
9729 switch (am->tag) {
9730 case S390_AMODE_B12:
9731 case S390_AMODE_BX12:
9732 if (signed_divide)
9733 return s390_emit_D(buf, r1, x, b, d);
9734 else
9735 return s390_emit_DL(buf, r1, x, b, DISP20(d));
9736
9737 case S390_AMODE_B20:
9738 case S390_AMODE_BX20:
9739 if (signed_divide) {
9740 buf = s390_emit_LY(buf, R0, x, b, DISP20(d));
9741 return s390_emit_DR(buf, r1, R0);
9742 } else
9743 return s390_emit_DL(buf, r1, x, b, DISP20(d));
9744 }
9745 goto fail;
9746
9747 case 8:
9748 if (signed_divide)
9749 vpanic("s390_insn_div_emit");
9750 else
9751 return s390_emit_DLG(buf, r1, x, b, DISP20(d));
9752
9753 default:
9754 goto fail;
9755 }
9756 }
9757
9758 case S390_OPND_IMMEDIATE: {
9759 ULong value = op2.variant.imm;
9760
9761 switch (insn->size) {
9762 case 4:
9763 buf = s390_emit_load_32imm(buf, R0, value);
9764 if (signed_divide)
9765 return s390_emit_DR(buf, r1, R0);
9766 else
9767 return s390_emit_DLR(buf, r1, R0);
9768
9769 case 8:
9770 buf = s390_emit_load_64imm(buf, R0, value);
9771 if (signed_divide)
9772 vpanic("s390_insn_div_emit");
9773 else
9774 return s390_emit_DLGR(buf, r1, R0);
9775
9776 default:
9777 goto fail;
9778 }
9779 }
9780
9781 default:
9782 goto fail;
9783 }
9784
9785 fail:
9786 vpanic("s390_insn_div_emit");
9787 }
9788
9789
9790 static UChar *
s390_insn_divs_emit(UChar * buf,const s390_insn * insn)9791 s390_insn_divs_emit(UChar *buf, const s390_insn *insn)
9792 {
9793 s390_opnd_RMI op2;
9794 UChar r1;
9795
9796 r1 = hregNumber(insn->variant.divs.rem);
9797 op2 = insn->variant.divs.op2;
9798
9799 switch (op2.tag) {
9800 case S390_OPND_REG: {
9801 UInt r2 = hregNumber(op2.variant.reg);
9802
9803 return s390_emit_DSGR(buf, r1, r2);
9804 }
9805
9806 case S390_OPND_AMODE: {
9807 const s390_amode *am = op2.variant.am;
9808 UChar b = hregNumber(am->b);
9809 UChar x = hregNumber(am->x);
9810 Int d = am->d;
9811
9812 return s390_emit_DSG(buf, r1, x, b, DISP20(d));
9813 }
9814
9815 case S390_OPND_IMMEDIATE: {
9816 ULong value = op2.variant.imm;
9817
9818 buf = s390_emit_load_64imm(buf, R0, value);
9819 return s390_emit_DSGR(buf, r1, R0);
9820 }
9821
9822 default:
9823 goto fail;
9824 }
9825
9826 fail:
9827 vpanic("s390_insn_divs_emit");
9828 }
9829
9830
9831 static UChar *
s390_insn_clz_emit(UChar * buf,const s390_insn * insn)9832 s390_insn_clz_emit(UChar *buf, const s390_insn *insn)
9833 {
9834 s390_opnd_RMI src;
9835 UChar r1, r1p1, r2, *p;
9836
9837 r1 = hregNumber(insn->variant.clz.num_bits);
9838 r1p1 = hregNumber(insn->variant.clz.clobber);
9839
9840 vassert((r1 & 0x1) == 0);
9841 vassert(r1p1 == r1 + 1);
9842
9843 p = buf;
9844 src = insn->variant.clz.src;
9845
9846 /* Get operand and move it to r2 */
9847 switch (src.tag) {
9848 case S390_OPND_REG:
9849 r2 = hregNumber(src.variant.reg);
9850 break;
9851
9852 case S390_OPND_AMODE: {
9853 const s390_amode *am = src.variant.am;
9854 UChar b = hregNumber(am->b);
9855 UChar x = hregNumber(am->x);
9856 Int d = am->d;
9857
9858 p = s390_emit_LG(p, R0, x, b, DISP20(d));
9859 r2 = R0;
9860 break;
9861 }
9862
9863 case S390_OPND_IMMEDIATE: {
9864 ULong value = src.variant.imm;
9865
9866 p = s390_emit_load_64imm(p, R0, value);
9867 r2 = R0;
9868 break;
9869 }
9870
9871 default:
9872 goto fail;
9873 }
9874
9875 /* Use FLOGR if you can */
9876 if (s390_host_has_eimm) {
9877 return s390_emit_FLOGR(p, r1, r2);
9878 }
9879
9880 /*
9881 r0 = r2;
9882 r1 = 64;
9883 while (r0 != 0) {
9884 r1 -= 1;
9885 r0 >>= 1;
9886 }
9887 */
9888 p = s390_emit_LTGR(p, R0, r2);
9889 p = s390_emit_LLILL(p, r1, 64);
9890
9891 p = s390_emit_BRC(p, S390_CC_E, (4 + 4 + 6 + 4 + 4)/ 2); /* 4 bytes */
9892 p = s390_emit_AGHI(p, r1, (UShort)-1); /* r1 -= 1; 4 bytes */
9893 p = s390_emit_SRLG(p, R0, R0, R0, DISP20(1)); /* r0 >>= 1; 6 bytes */
9894 p = s390_emit_LTGR(p, R0, R0); /* set cc 4 bytes */
9895 p = s390_emit_BRC(p, S390_CC_NE, /* 4 bytes */
9896 (UShort)(-(4 + 6 + 4) / 2));
9897 return p;
9898
9899 fail:
9900 vpanic("s390_insn_clz_emit");
9901 }
9902
9903
9904 /* Returns a value == BUF to denote failure, != BUF to denote success. */
9905 static UChar *
s390_insn_helper_call_emit(UChar * buf,const s390_insn * insn)9906 s390_insn_helper_call_emit(UChar *buf, const s390_insn *insn)
9907 {
9908 s390_cc_t cond;
9909 ULong target;
9910 Int delta;
9911 s390_helper_call *helper_call = insn->variant.helper_call.details;
9912
9913 cond = helper_call->cond;
9914 target = helper_call->target;
9915
9916 const Bool not_always = (cond != S390_CC_ALWAYS);
9917 const Bool not_void_return = (helper_call->rloc.pri != RLPri_None);
9918
9919 /* We have this situation:
9920 ( *** code in this braces is for not_always && not_void_return*** )
9921 ...
9922 before:
9923 brc{!cond} else
9924 call_helper
9925 preElse:
9926 *** j after ***
9927 else:
9928 *** load_64imm $0x5555555555555555, %%r2 *** // e.g. for Int RetLoc
9929 after:
9930 ...
9931 */
9932
9933 // before:
9934 UChar *pBefore = buf;
9935 if (not_always) {
9936 /* 4 bytes (a BRC insn) to be filled in here */
9937 buf += 4;
9938 }
9939
9940 // call_helper
9941 /* Load the target address into a register, that
9942 (a) is not used for passing parameters to the helper and
9943 (b) can be clobbered by the callee
9944 (c) is not special to the BASR insn
9945 r1 is the only choice.
9946 Also, need to arrange for the return address be put into the
9947 link-register */
9948 buf = s390_emit_load_64imm(buf, 1, target);
9949
9950 /* Stash away the client's FPC register because the helper might change it. */
9951 buf = s390_emit_STFPC(buf, S390_REGNO_STACK_POINTER, S390_OFFSET_SAVED_FPC_C);
9952
9953 buf = s390_emit_BASR(buf, S390_REGNO_LINK_REGISTER, 1); // call helper
9954
9955 buf = s390_emit_LFPC(buf, S390_REGNO_STACK_POINTER, // restore FPC
9956 S390_OFFSET_SAVED_FPC_C);
9957
9958 // preElse:
9959 UChar* pPreElse = buf;
9960 if (not_always && not_void_return) {
9961 /* 4 bytes (a BRC insn) to be filled in here */
9962 buf += 4;
9963 }
9964
9965 // else:
9966 UChar* pElse = buf;
9967 if (not_always && not_void_return) {
9968 switch (helper_call->rloc.pri) {
9969 case RLPri_Int:
9970 buf = s390_emit_load_64imm(buf, S390_REGNO_RETURN_VALUE, 0x5555555555555555ULL);
9971 break;
9972 default:
9973 ppS390Instr(insn, True);
9974 vpanic("s390_insn_helper_call_emit: invalid conditional RetLoc.");
9975 }
9976 }
9977
9978 // after:
9979 UChar* pAfter = buf;
9980
9981 // fill "brc{!cond} else"
9982 if(not_always)
9983 {
9984 delta = pElse - pBefore;
9985 delta >>= 1; /* immediate constant is #half-words */
9986 vassert(delta > 0 && delta < (1 << 16));
9987 s390_emit_BRC(pBefore, s390_cc_invert(cond), delta);
9988 }
9989
9990 // fill "brc{ALWAYS} after"
9991 if (not_always && not_void_return)
9992 {
9993 delta = pAfter - pPreElse;
9994 delta >>= 1; /* immediate constant is #half-words */
9995 vassert(delta > 0 && delta < (1 << 16));
9996 s390_emit_BRC(pPreElse, S390_CC_ALWAYS, delta);
9997 }
9998
9999 return buf;
10000 }
10001
10002
10003 static UChar *
s390_insn_cond_move_emit(UChar * buf,const s390_insn * insn)10004 s390_insn_cond_move_emit(UChar *buf, const s390_insn *insn)
10005 {
10006 HReg dst;
10007 s390_opnd_RMI src;
10008 s390_cc_t cond;
10009 UChar *p, *ptmp = 0; /* avoid compiler warnings */
10010
10011 cond = insn->variant.cond_move.cond;
10012 dst = insn->variant.cond_move.dst;
10013 src = insn->variant.cond_move.src;
10014
10015 if (cond == S390_CC_NEVER) return buf;
10016
10017 p = buf;
10018
10019 if (s390_host_has_lsc) {
10020 /* LOCx is not the preferred way to implement an unconditional load. */
10021 if (cond != S390_CC_ALWAYS) goto use_branch_insn;
10022
10023 switch (src.tag) {
10024 case S390_OPND_REG:
10025 return s390_emit_LOCGR(p, cond, hregNumber(dst),
10026 hregNumber(src.variant.reg));
10027
10028 case S390_OPND_AMODE: {
10029 const s390_amode *am = src.variant.am;
10030
10031 /* We cannot use LOCx for loads less than 4 bytes. In that case
10032 load into R0 and then use LOCGR. Do the same if the amode uses
10033 an index register. */
10034 if (insn->size < 4 ||
10035 am->tag == S390_AMODE_BX12 || am->tag == S390_AMODE_BX20) {
10036 p = s390_emit_load_mem(p, insn->size, R0, am);
10037 p = s390_emit_LOCGR(p, cond, hregNumber(dst), R0);
10038 return p;
10039 }
10040
10041 vassert(am->tag == S390_AMODE_B12 || am->tag == S390_AMODE_B20);
10042 vassert(insn->size == 4 || insn->size == 8);
10043
10044 UInt b = hregNumber(am->b);
10045 UInt d = am->d;
10046
10047 if (insn->size == 4) {
10048 return s390_emit_LOC(p, hregNumber(dst), cond, b, DISP20(d));
10049 }
10050 return s390_emit_LOCG(p, hregNumber(dst), cond, b, DISP20(d));
10051 }
10052
10053 case S390_OPND_IMMEDIATE: {
10054 ULong value = src.variant.imm;
10055
10056 /* Load value into R0, then use LOCGR */
10057 if (insn->size <= 4) {
10058 p = s390_emit_load_32imm(p, R0, value);
10059 return s390_emit_LOCGR(p, cond, hregNumber(dst), R0);
10060 }
10061
10062 vassert(insn->size == 8);
10063 p = s390_emit_load_64imm(p, R0, value);
10064 return s390_emit_LOCGR(p, cond, hregNumber(dst), R0);
10065 }
10066 }
10067 }
10068
10069 use_branch_insn:
10070 /* Branch (if cond fails) over move instrs */
10071 if (cond != S390_CC_ALWAYS) {
10072 /* Don't know how many bytes to jump over yet.
10073 Make space for a BRC instruction (4 bytes) and fill in later. */
10074 ptmp = p; /* to be filled in here */
10075 p += 4;
10076 }
10077
10078 // cond true: move src => dst
10079
10080 switch (src.tag) {
10081 case S390_OPND_REG:
10082 p = s390_emit_LGR(p, hregNumber(dst), hregNumber(src.variant.reg));
10083 break;
10084
10085 case S390_OPND_AMODE:
10086 p = s390_emit_load_mem(p, insn->size, hregNumber(dst), src.variant.am);
10087 break;
10088
10089 case S390_OPND_IMMEDIATE: {
10090 ULong value = src.variant.imm;
10091 UInt r = hregNumber(dst);
10092
10093 switch (insn->size) {
10094 case 1:
10095 case 2:
10096 /* Load the immediate values as a 4 byte value. That does not hurt as
10097 those extra bytes will not be looked at. Fall through .... */
10098 case 4:
10099 p = s390_emit_load_32imm(p, r, value);
10100 break;
10101
10102 case 8:
10103 p = s390_emit_load_64imm(p, r, value);
10104 break;
10105 }
10106 break;
10107 }
10108
10109 default:
10110 goto fail;
10111 }
10112
10113 if (cond != S390_CC_ALWAYS) {
10114 Int delta = p - ptmp;
10115
10116 delta >>= 1; /* immediate constant is #half-words */
10117 vassert(delta > 0 && delta < (1 << 16));
10118 s390_emit_BRC(ptmp, s390_cc_invert(cond), delta);
10119 }
10120
10121 return p;
10122
10123 fail:
10124 vpanic("s390_insn_cond_move_emit");
10125 }
10126
10127
10128 static UChar *
s390_insn_bfp_triop_emit(UChar * buf,const s390_insn * insn)10129 s390_insn_bfp_triop_emit(UChar *buf, const s390_insn *insn)
10130 {
10131 UInt r1 = hregNumber(insn->variant.bfp_triop.dst);
10132 UInt r2 = hregNumber(insn->variant.bfp_triop.op2);
10133 UInt r3 = hregNumber(insn->variant.bfp_triop.op3);
10134
10135 switch (insn->size) {
10136 case 4:
10137 switch (insn->variant.bfp_triop.tag) {
10138 case S390_BFP_MADD: return s390_emit_MAEBR(buf, r1, r3, r2);
10139 case S390_BFP_MSUB: return s390_emit_MSEBR(buf, r1, r3, r2);
10140 default: goto fail;
10141 }
10142 break;
10143
10144 case 8:
10145 switch (insn->variant.bfp_triop.tag) {
10146 case S390_BFP_MADD: return s390_emit_MADBR(buf, r1, r3, r2);
10147 case S390_BFP_MSUB: return s390_emit_MSDBR(buf, r1, r3, r2);
10148 default: goto fail;
10149 }
10150 break;
10151
10152 default: goto fail;
10153 }
10154
10155 fail:
10156 vpanic("s390_insn_bfp_triop_emit");
10157 }
10158
10159
10160 static UChar *
s390_insn_bfp_binop_emit(UChar * buf,const s390_insn * insn)10161 s390_insn_bfp_binop_emit(UChar *buf, const s390_insn *insn)
10162 {
10163 UInt r1 = hregNumber(insn->variant.bfp_binop.dst_hi);
10164 UInt r2 = hregNumber(insn->variant.bfp_binop.op2_hi);
10165
10166 switch (insn->size) {
10167 case 4:
10168 switch (insn->variant.bfp_binop.tag) {
10169 case S390_BFP_ADD: return s390_emit_AEBR(buf, r1, r2);
10170 case S390_BFP_SUB: return s390_emit_SEBR(buf, r1, r2);
10171 case S390_BFP_MUL: return s390_emit_MEEBR(buf, r1, r2);
10172 case S390_BFP_DIV: return s390_emit_DEBR(buf, r1, r2);
10173 default: goto fail;
10174 }
10175 break;
10176
10177 case 8:
10178 switch (insn->variant.bfp_binop.tag) {
10179 case S390_BFP_ADD: return s390_emit_ADBR(buf, r1, r2);
10180 case S390_BFP_SUB: return s390_emit_SDBR(buf, r1, r2);
10181 case S390_BFP_MUL: return s390_emit_MDBR(buf, r1, r2);
10182 case S390_BFP_DIV: return s390_emit_DDBR(buf, r1, r2);
10183 default: goto fail;
10184 }
10185 break;
10186
10187 case 16:
10188 switch (insn->variant.bfp_binop.tag) {
10189 case S390_BFP_ADD: return s390_emit_AXBR(buf, r1, r2);
10190 case S390_BFP_SUB: return s390_emit_SXBR(buf, r1, r2);
10191 case S390_BFP_MUL: return s390_emit_MXBR(buf, r1, r2);
10192 case S390_BFP_DIV: return s390_emit_DXBR(buf, r1, r2);
10193 default: goto fail;
10194 }
10195 break;
10196
10197 default: goto fail;
10198 }
10199
10200 fail:
10201 vpanic("s390_insn_bfp_binop_emit");
10202 }
10203
10204
10205 static UChar *
s390_insn_bfp_unop_emit(UChar * buf,const s390_insn * insn)10206 s390_insn_bfp_unop_emit(UChar *buf, const s390_insn *insn)
10207 {
10208 UInt r1 = hregNumber(insn->variant.bfp_unop.dst_hi);
10209 UInt r2 = hregNumber(insn->variant.bfp_unop.op_hi);
10210
10211 switch (insn->variant.bfp_unop.tag) {
10212 case S390_BFP_ABS:
10213 switch (insn->size) {
10214 case 4: return s390_emit_LPEBR(buf, r1, r2);
10215 case 8: return s390_emit_LPDBR(buf, r1, r2);
10216 case 16: return s390_emit_LPXBR(buf, r1, r2);
10217 default: goto fail;
10218 }
10219 break;
10220
10221 case S390_BFP_NABS:
10222 switch (insn->size) {
10223 case 4: return s390_emit_LNEBR(buf, r1, r2);
10224 case 8: return s390_emit_LNDBR(buf, r1, r2);
10225 case 16: return s390_emit_LNXBR(buf, r1, r2);
10226 default: goto fail;
10227 }
10228 break;
10229
10230 case S390_BFP_NEG:
10231 switch (insn->size) {
10232 case 4: return s390_emit_LCEBR(buf, r1, r2);
10233 case 8: return s390_emit_LCDBR(buf, r1, r2);
10234 case 16: return s390_emit_LCXBR(buf, r1, r2);
10235 default: goto fail;
10236 }
10237 break;
10238
10239 case S390_BFP_SQRT:
10240 switch (insn->size) {
10241 case 4: return s390_emit_SQEBR(buf, r1, r2);
10242 case 8: return s390_emit_SQDBR(buf, r1, r2);
10243 case 16: return s390_emit_SQXBR(buf, r1, r2);
10244 default: goto fail;
10245 }
10246 break;
10247
10248 default: goto fail;
10249 }
10250
10251 fail:
10252 vpanic("s390_insn_bfp_unop_emit");
10253 }
10254
10255
10256 static UChar *
s390_insn_bfp_convert_emit(UChar * buf,const s390_insn * insn)10257 s390_insn_bfp_convert_emit(UChar *buf, const s390_insn *insn)
10258 {
10259 UInt r1 = hregNumber(insn->variant.bfp_convert.dst_hi);
10260 UInt r2 = hregNumber(insn->variant.bfp_convert.op_hi);
10261 s390_bfp_round_t m3 = insn->variant.bfp_convert.rounding_mode;
10262 /* The IEEE-inexact-exception control is not modelled. So the
10263 m4 field is 0 (which is what GCC does, too) */
10264 const UInt m4 = 0;
10265
10266 switch (insn->variant.bfp_convert.tag) {
10267 /* Convert to fixed */
10268 case S390_BFP_F32_TO_I32: return s390_emit_CFEBR(buf, m3, r1, r2);
10269 case S390_BFP_F64_TO_I32: return s390_emit_CFDBR(buf, m3, r1, r2);
10270 case S390_BFP_F128_TO_I32: return s390_emit_CFXBR(buf, m3, r1, r2);
10271 case S390_BFP_F32_TO_I64: return s390_emit_CGEBR(buf, m3, r1, r2);
10272 case S390_BFP_F64_TO_I64: return s390_emit_CGDBR(buf, m3, r1, r2);
10273 case S390_BFP_F128_TO_I64: return s390_emit_CGXBR(buf, m3, r1, r2);
10274
10275 /* Convert to logical */
10276 case S390_BFP_F32_TO_U32: return s390_emit_CLFEBR(buf, m3, m4, r1, r2);
10277 case S390_BFP_F64_TO_U32: return s390_emit_CLFDBR(buf, m3, m4, r1, r2);
10278 case S390_BFP_F128_TO_U32: return s390_emit_CLFXBR(buf, m3, m4, r1, r2);
10279 case S390_BFP_F32_TO_U64: return s390_emit_CLGEBR(buf, m3, m4, r1, r2);
10280 case S390_BFP_F64_TO_U64: return s390_emit_CLGDBR(buf, m3, m4, r1, r2);
10281 case S390_BFP_F128_TO_U64: return s390_emit_CLGXBR(buf, m3, m4, r1, r2);
10282
10283 /* Convert from fixed */
10284 case S390_BFP_I32_TO_F32: return s390_emit_CEFBRA(buf, m3, m4, r1, r2);
10285 case S390_BFP_I32_TO_F64: return s390_emit_CDFBRA(buf, 0, m4, r1, r2);
10286 case S390_BFP_I32_TO_F128: return s390_emit_CXFBRA(buf, 0, m4, r1, r2);
10287 case S390_BFP_I64_TO_F32: return s390_emit_CEGBRA(buf, m3, m4, r1, r2);
10288 case S390_BFP_I64_TO_F64: return s390_emit_CDGBRA(buf, m3, m4, r1, r2);
10289 case S390_BFP_I64_TO_F128: return s390_emit_CXGBRA(buf, 0, m4, r1, r2);
10290
10291 /* Convert from logical */
10292 case S390_BFP_U32_TO_F32: return s390_emit_CELFBR(buf, m3, m4, r1, r2);
10293 case S390_BFP_U32_TO_F64: return s390_emit_CDLFBR(buf, m3, m4, r1, r2);
10294 case S390_BFP_U32_TO_F128: return s390_emit_CXLFBR(buf, m3, m4, r1, r2);
10295 case S390_BFP_U64_TO_F32: return s390_emit_CELGBR(buf, m3, m4, r1, r2);
10296 case S390_BFP_U64_TO_F64: return s390_emit_CDLGBR(buf, m3, m4, r1, r2);
10297 case S390_BFP_U64_TO_F128: return s390_emit_CXLGBR(buf, m3, m4, r1, r2);
10298
10299 /* Load lengthened */
10300 case S390_BFP_F32_TO_F64: return s390_emit_LDEBR(buf, r1, r2);
10301 case S390_BFP_F32_TO_F128: return s390_emit_LXEBR(buf, r1, r2);
10302 case S390_BFP_F64_TO_F128: return s390_emit_LXDBR(buf, r1, r2);
10303
10304 /* Load rounded */
10305 case S390_BFP_F64_TO_F32: return s390_emit_LEDBRA(buf, m3, m4, r1, r2);
10306 case S390_BFP_F128_TO_F32: return s390_emit_LEXBRA(buf, m3, m4, r1, r2);
10307 case S390_BFP_F128_TO_F64: return s390_emit_LDXBRA(buf, m3, m4, r1, r2);
10308
10309 /* Load FP integer */
10310 case S390_BFP_F32_TO_F32I: return s390_emit_FIEBRA(buf, m3, m4, r1, r2);
10311 case S390_BFP_F64_TO_F64I: return s390_emit_FIDBRA(buf, m3, m4, r1, r2);
10312 case S390_BFP_F128_TO_F128I: return s390_emit_FIXBRA(buf, m3, m4, r1, r2);
10313
10314 default: goto fail;
10315 }
10316
10317 fail:
10318 vpanic("s390_insn_bfp_convert_emit");
10319 }
10320
10321
10322 static UChar *
s390_insn_bfp_compare_emit(UChar * buf,const s390_insn * insn)10323 s390_insn_bfp_compare_emit(UChar *buf, const s390_insn *insn)
10324 {
10325 UInt dst = hregNumber(insn->variant.bfp_compare.dst);
10326 UInt r1 = hregNumber(insn->variant.bfp_compare.op1_hi);
10327 UInt r2 = hregNumber(insn->variant.bfp_compare.op2_hi);
10328
10329 switch (insn->size) {
10330 case 4: buf = s390_emit_CEBR(buf, r1, r2); break;
10331 case 8: buf = s390_emit_CDBR(buf, r1, r2); break;
10332 case 16: buf = s390_emit_CXBR(buf, r1, r2); break;
10333 default: goto fail;
10334 }
10335
10336 return s390_emit_load_cc(buf, dst); /* Load condition code into DST */
10337
10338 fail:
10339 vpanic("s390_insn_bfp_compare_emit");
10340 }
10341
10342
10343 static UChar *
s390_insn_dfp_binop_emit(UChar * buf,const s390_insn * insn)10344 s390_insn_dfp_binop_emit(UChar *buf, const s390_insn *insn)
10345 {
10346 s390_dfp_binop *dfp_binop = insn->variant.dfp_binop.details;
10347
10348 UInt r1 = hregNumber(dfp_binop->dst_hi);
10349 UInt r2 = hregNumber(dfp_binop->op2_hi);
10350 UInt r3 = hregNumber(dfp_binop->op3_hi);
10351 s390_dfp_round_t m4 = dfp_binop->rounding_mode;
10352
10353 switch (insn->size) {
10354 case 8:
10355 switch (dfp_binop->tag) {
10356 case S390_DFP_ADD: return s390_emit_ADTRA(buf, r3, m4, r1, r2);
10357 case S390_DFP_SUB: return s390_emit_SDTRA(buf, r3, m4, r1, r2);
10358 case S390_DFP_MUL: return s390_emit_MDTRA(buf, r3, m4, r1, r2);
10359 case S390_DFP_DIV: return s390_emit_DDTRA(buf, r3, m4, r1, r2);
10360 case S390_DFP_QUANTIZE: return s390_emit_QADTR(buf, r3, m4, r1, r2);
10361 default: goto fail;
10362 }
10363 break;
10364
10365 case 16:
10366 switch (dfp_binop->tag) {
10367 case S390_DFP_ADD: return s390_emit_AXTRA(buf, r3, m4, r1, r2);
10368 case S390_DFP_SUB: return s390_emit_SXTRA(buf, r3, m4, r1, r2);
10369 case S390_DFP_MUL: return s390_emit_MXTRA(buf, r3, m4, r1, r2);
10370 case S390_DFP_DIV: return s390_emit_DXTRA(buf, r3, m4, r1, r2);
10371 case S390_DFP_QUANTIZE: return s390_emit_QAXTR(buf, r3, m4, r1, r2);
10372 default: goto fail;
10373 }
10374 break;
10375
10376 default: goto fail;
10377 }
10378
10379 fail:
10380 vpanic("s390_insn_dfp_binop_emit");
10381 }
10382
10383
10384 static UChar *
s390_insn_dfp_reround_emit(UChar * buf,const s390_insn * insn)10385 s390_insn_dfp_reround_emit(UChar *buf, const s390_insn *insn)
10386 {
10387 UInt r1 = hregNumber(insn->variant.dfp_reround.dst_hi);
10388 UInt r2 = hregNumber(insn->variant.dfp_reround.op2);
10389 UInt r3 = hregNumber(insn->variant.dfp_reround.op3_hi);
10390 s390_dfp_round_t m4 = insn->variant.dfp_reround.rounding_mode;
10391
10392 switch (insn->size) {
10393 case 8:
10394 return s390_emit_RRDTR(buf, r3, m4, r1, r2);
10395
10396 case 16:
10397 return s390_emit_RRXTR(buf, r3, m4, r1, r2);
10398
10399 default: goto fail;
10400 }
10401 fail:
10402 vpanic("s390_insn_dfp_reround_emit");
10403 }
10404
10405
10406 static UChar *
s390_insn_dfp_unop_emit(UChar * buf,const s390_insn * insn)10407 s390_insn_dfp_unop_emit(UChar *buf, const s390_insn *insn)
10408 {
10409 UInt r1 = hregNumber(insn->variant.dfp_unop.dst_hi);
10410 UInt r2 = hregNumber(insn->variant.dfp_unop.op_hi);
10411
10412 switch (insn->variant.dfp_unop.tag) {
10413 case S390_DFP_EXTRACT_EXP_D64: return s390_emit_EEDTR(buf, r1, r2); break;
10414 case S390_DFP_EXTRACT_EXP_D128: return s390_emit_EEXTR(buf, r1, r2); break;
10415 case S390_DFP_EXTRACT_SIG_D64: return s390_emit_ESDTR(buf, r1, r2); break;
10416 case S390_DFP_EXTRACT_SIG_D128: return s390_emit_ESXTR(buf, r1, r2); break;
10417 default: goto fail;
10418 }
10419 fail:
10420 vpanic("s390_insn_dfp_unop_emit");
10421 }
10422
10423
10424 static UChar *
s390_insn_dfp_intop_emit(UChar * buf,const s390_insn * insn)10425 s390_insn_dfp_intop_emit(UChar *buf, const s390_insn *insn)
10426 {
10427 UInt r1 = hregNumber(insn->variant.dfp_intop.dst_hi);
10428 UInt r2 = hregNumber(insn->variant.dfp_intop.op2);
10429 UInt r3 = hregNumber(insn->variant.dfp_intop.op3_hi);
10430
10431 switch (insn->size) {
10432 case 8:
10433 switch (insn->variant.dfp_intop.tag) {
10434 case S390_DFP_SHIFT_LEFT: return s390_emit_SLDT(buf, r3, r1, r2);
10435 case S390_DFP_SHIFT_RIGHT: return s390_emit_SRDT(buf, r3, r1, r2);
10436 case S390_DFP_INSERT_EXP: return s390_emit_IEDTR(buf, r3, r1, r2);
10437 default: goto fail;
10438 }
10439 break;
10440
10441 case 16:
10442 switch (insn->variant.dfp_intop.tag) {
10443 case S390_DFP_SHIFT_LEFT: return s390_emit_SLXT(buf, r3, r1, r2);
10444 case S390_DFP_SHIFT_RIGHT: return s390_emit_SRXT(buf, r3, r1, r2);
10445 case S390_DFP_INSERT_EXP: return s390_emit_IEXTR(buf, r3, r1, r2);
10446 default: goto fail;
10447 }
10448 break;
10449
10450 default: goto fail;
10451 }
10452
10453 fail:
10454 vpanic("s390_insn_dfp_intop_emit");
10455 }
10456
10457
10458 static UChar *
s390_insn_dfp_compare_emit(UChar * buf,const s390_insn * insn)10459 s390_insn_dfp_compare_emit(UChar *buf, const s390_insn *insn)
10460 {
10461 UInt dst = hregNumber(insn->variant.dfp_compare.dst);
10462 UInt r1 = hregNumber(insn->variant.dfp_compare.op1_hi);
10463 UInt r2 = hregNumber(insn->variant.dfp_compare.op2_hi);
10464
10465 switch (insn->size) {
10466 case 8:
10467 switch(insn->variant.dfp_compare.tag) {
10468 case S390_DFP_COMPARE: buf = s390_emit_CDTR(buf, r1, r2); break;
10469 case S390_DFP_COMPARE_EXP: buf = s390_emit_CEDTR(buf, r1, r2); break;
10470 default: goto fail;
10471 }
10472 break;
10473
10474 case 16:
10475 switch(insn->variant.dfp_compare.tag) {
10476 case S390_DFP_COMPARE: buf = s390_emit_CXTR(buf, r1, r2); break;
10477 case S390_DFP_COMPARE_EXP: buf = s390_emit_CEXTR(buf, r1, r2); break;
10478 default: goto fail;
10479 }
10480 break;
10481
10482 default: goto fail;
10483 }
10484
10485 return s390_emit_load_cc(buf, dst); /* Load condition code into DST */
10486
10487 fail:
10488 vpanic("s390_insn_dfp_compare_emit");
10489 }
10490
10491
10492 static UChar *
s390_insn_dfp_convert_emit(UChar * buf,const s390_insn * insn)10493 s390_insn_dfp_convert_emit(UChar *buf, const s390_insn *insn)
10494 {
10495 UInt r1 = hregNumber(insn->variant.dfp_convert.dst_hi);
10496 UInt r2 = hregNumber(insn->variant.dfp_convert.op_hi);
10497 s390_dfp_round_t m3 = insn->variant.dfp_convert.rounding_mode;
10498 /* The IEEE-inexact-exception control is not modelled. So the
10499 m4 field is 0 (which is what GCC does, too) */
10500 const UInt m4 = 0;
10501
10502 switch (insn->variant.dfp_convert.tag) {
10503
10504 /* Convert to fixed */
10505 case S390_DFP_D64_TO_I32: return s390_emit_CFDTR(buf, m3, m4, r1, r2);
10506 case S390_DFP_D128_TO_I32: return s390_emit_CFXTR(buf, m3, m4, r1, r2);
10507 case S390_DFP_D64_TO_I64: return s390_emit_CGDTR(buf, m3, m4, r1, r2);
10508 case S390_DFP_D128_TO_I64: return s390_emit_CGXTR(buf, m3, m4, r1, r2);
10509
10510 /* Convert to logical */
10511 case S390_DFP_D64_TO_U32: return s390_emit_CLFDTR(buf, m3, m4, r1, r2);
10512 case S390_DFP_D128_TO_U32: return s390_emit_CLFXTR(buf, m3, m4, r1, r2);
10513 case S390_DFP_D64_TO_U64: return s390_emit_CLGDTR(buf, m3, m4, r1, r2);
10514 case S390_DFP_D128_TO_U64: return s390_emit_CLGXTR(buf, m3, m4, r1, r2);
10515
10516 /* Convert from fixed */
10517 case S390_DFP_I32_TO_D64: return s390_emit_CDFTR(buf, 0, m4, r1, r2);
10518 case S390_DFP_I32_TO_D128: return s390_emit_CXFTR(buf, 0, m4, r1, r2);
10519 case S390_DFP_I64_TO_D64: return s390_emit_CDGTRA(buf, m3, m4, r1, r2);
10520 case S390_DFP_I64_TO_D128: return s390_emit_CXGTR(buf, 0, m4, r1, r2);
10521
10522 /* Convert from logical */
10523 case S390_DFP_U32_TO_D64: return s390_emit_CDLFTR(buf, m3, m4, r1, r2);
10524 case S390_DFP_U64_TO_D64: return s390_emit_CDLGTR(buf, m3, m4, r1, r2);
10525 case S390_DFP_U32_TO_D128: return s390_emit_CXLFTR(buf, m3, m4, r1, r2);
10526 case S390_DFP_U64_TO_D128: return s390_emit_CXLGTR(buf, m3, m4, r1, r2);
10527
10528 /* Load lengthened */
10529 case S390_DFP_D32_TO_D64: return s390_emit_LDETR(buf, m4, r1, r2);
10530 case S390_DFP_D64_TO_D128: return s390_emit_LXDTR(buf, m4, r1, r2);
10531
10532 /* Load rounded */
10533 case S390_DFP_D64_TO_D32: return s390_emit_LEDTR(buf, m3, m4, r1, r2);
10534 case S390_DFP_D128_TO_D64: return s390_emit_LDXTR(buf, m3, m4, r1, r2);
10535
10536 default: goto fail;
10537 }
10538
10539 fail:
10540 vpanic("s390_insn_dfp_convert_emit");
10541 }
10542
10543
10544 static UChar *
s390_insn_fp_convert_emit(UChar * buf,const s390_insn * insn)10545 s390_insn_fp_convert_emit(UChar *buf, const s390_insn *insn)
10546 {
10547 UInt pfpo;
10548 s390_fp_convert *fp_convert = insn->variant.fp_convert.details;
10549 s390_dfp_round_t rm = fp_convert->rounding_mode;
10550
10551 vassert(rm < 2 || rm > 7);
10552
10553 switch (fp_convert->tag) {
10554 case S390_FP_F32_TO_D32: pfpo = S390_PFPO_F32_TO_D32 << 8; break;
10555 case S390_FP_F32_TO_D64: pfpo = S390_PFPO_F32_TO_D64 << 8; break;
10556 case S390_FP_F32_TO_D128: pfpo = S390_PFPO_F32_TO_D128 << 8; break;
10557 case S390_FP_F64_TO_D32: pfpo = S390_PFPO_F64_TO_D32 << 8; break;
10558 case S390_FP_F64_TO_D64: pfpo = S390_PFPO_F64_TO_D64 << 8; break;
10559 case S390_FP_F64_TO_D128: pfpo = S390_PFPO_F64_TO_D128 << 8; break;
10560 case S390_FP_F128_TO_D32: pfpo = S390_PFPO_F128_TO_D32 << 8; break;
10561 case S390_FP_F128_TO_D64: pfpo = S390_PFPO_F128_TO_D64 << 8; break;
10562 case S390_FP_F128_TO_D128: pfpo = S390_PFPO_F128_TO_D128 << 8; break;
10563 case S390_FP_D32_TO_F32: pfpo = S390_PFPO_D32_TO_F32 << 8; break;
10564 case S390_FP_D32_TO_F64: pfpo = S390_PFPO_D32_TO_F64 << 8; break;
10565 case S390_FP_D32_TO_F128: pfpo = S390_PFPO_D32_TO_F128 << 8; break;
10566 case S390_FP_D64_TO_F32: pfpo = S390_PFPO_D64_TO_F32 << 8; break;
10567 case S390_FP_D64_TO_F64: pfpo = S390_PFPO_D64_TO_F64 << 8; break;
10568 case S390_FP_D64_TO_F128: pfpo = S390_PFPO_D64_TO_F128 << 8; break;
10569 case S390_FP_D128_TO_F32: pfpo = S390_PFPO_D128_TO_F32 << 8; break;
10570 case S390_FP_D128_TO_F64: pfpo = S390_PFPO_D128_TO_F64 << 8; break;
10571 case S390_FP_D128_TO_F128: pfpo = S390_PFPO_D128_TO_F128 << 8; break;
10572 default: goto fail;
10573 }
10574
10575 pfpo = pfpo | rm;
10576 buf = s390_emit_load_32imm(buf, R0, pfpo);
10577 buf = s390_emit_PFPO(buf);
10578 return buf;
10579
10580 fail:
10581 vpanic("s390_insn_fp_convert_emit");
10582 }
10583
10584
10585 static UChar *
s390_insn_mfence_emit(UChar * buf,const s390_insn * insn)10586 s390_insn_mfence_emit(UChar *buf, const s390_insn *insn)
10587 {
10588 return s390_emit_BCR(buf, 0xF, 0x0);
10589 }
10590
10591
10592 static UChar *
s390_insn_mimm_emit(UChar * buf,const s390_insn * insn)10593 s390_insn_mimm_emit(UChar *buf, const s390_insn *insn)
10594 {
10595 s390_amode *am = insn->variant.mimm.dst;
10596 UChar b = hregNumber(am->b);
10597 Int d = am->d;
10598 ULong value = insn->variant.mimm.value;
10599
10600 if (value == 0) {
10601 return s390_emit_XC(buf, insn->size - 1, b, d, b, d);
10602 }
10603
10604 if (insn->size == 1) {
10605 return s390_emit_MVI(buf, value & 0xFF, b, d);
10606 }
10607
10608 if (s390_host_has_gie && ulong_fits_signed_16bit(value)) {
10609 value &= 0xFFFF;
10610 switch (insn->size) {
10611 case 2: return s390_emit_MVHHI(buf, b, d, value);
10612 case 4: return s390_emit_MVHI(buf, b, d, value);
10613 case 8: return s390_emit_MVGHI(buf, b, d, value);
10614 }
10615 } else {
10616 // Load value to R0, then store.
10617 switch (insn->size) {
10618 case 2:
10619 buf = s390_emit_LHI(buf, R0, value & 0xFFFF);
10620 return s390_emit_STH(buf, R0, 0, b, d);
10621 case 4:
10622 buf = s390_emit_load_32imm(buf, R0, value);
10623 return s390_emit_ST(buf, R0, 0, b, d);
10624 case 8:
10625 buf = s390_emit_load_64imm(buf, R0, value);
10626 return s390_emit_STG(buf, R0, 0, b, DISP20(d));
10627 }
10628 }
10629
10630 vpanic("s390_insn_mimm_emit");
10631 }
10632
10633
10634 static UChar *
s390_insn_madd_emit(UChar * buf,const s390_insn * insn)10635 s390_insn_madd_emit(UChar *buf, const s390_insn *insn)
10636 {
10637 s390_amode *am = insn->variant.madd.dst;
10638 UChar b = hregNumber(am->b);
10639 Int d = am->d;
10640
10641 if (insn->size == 4) {
10642 return s390_emit_ASI(buf, insn->variant.madd.delta, b, DISP20(d));
10643 }
10644
10645 return s390_emit_AGSI(buf, insn->variant.madd.delta, b, DISP20(d));
10646 }
10647
10648
10649 static UChar *
s390_insn_set_fpc_bfprm_emit(UChar * buf,const s390_insn * insn)10650 s390_insn_set_fpc_bfprm_emit(UChar *buf, const s390_insn *insn)
10651 {
10652 UInt mode = hregNumber(insn->variant.set_fpc_bfprm.mode);
10653
10654 /* Copy FPC from guest state to R0 and OR in the new rounding mode */
10655 buf = s390_emit_L(buf, R0, 0, S390_REGNO_GUEST_STATE_POINTER,
10656 S390X_GUEST_OFFSET(guest_fpc)); // r0 = guest_fpc
10657
10658 buf = s390_emit_NILL(buf, R0, 0xFFF8); /* Clear out right-most 3 bits */
10659 buf = s390_emit_OR(buf, R0, mode); /* OR in the new rounding mode */
10660 buf = s390_emit_SFPC(buf, R0); /* Load FPC register from R0 */
10661
10662 return buf;
10663 }
10664
10665
10666 static UChar *
s390_insn_set_fpc_dfprm_emit(UChar * buf,const s390_insn * insn)10667 s390_insn_set_fpc_dfprm_emit(UChar *buf, const s390_insn *insn)
10668 {
10669 UInt mode = hregNumber(insn->variant.set_fpc_dfprm.mode);
10670
10671 /* Copy FPC from guest state to R0 and OR in the new rounding mode */
10672 buf = s390_emit_L(buf, R0, 0, S390_REGNO_GUEST_STATE_POINTER,
10673 S390X_GUEST_OFFSET(guest_fpc)); // r0 = guest_fpc
10674
10675 /* DFP rounding mode is set at bit position 25:27 in FPC register */
10676 buf = s390_emit_NILL(buf, R0, 0xFF8F); /* Clear out 25:27 bits */
10677 buf = s390_emit_SLL(buf, mode, 0, 4); /* bring mode to 25:27 bits */
10678 buf = s390_emit_OR(buf, R0, mode); /* OR in the new rounding mode */
10679 buf = s390_emit_SFPC(buf, R0); /* Load FPC register from R0 */
10680
10681 return buf;
10682 }
10683
10684
10685 /* Define convenience functions needed for translation chaining.
10686 Any changes need to be applied to the functions in concert. */
10687
10688 static __inline__ Bool
s390_insn_is_BRCL(const UChar * p,UChar condition)10689 s390_insn_is_BRCL(const UChar *p, UChar condition)
10690 {
10691 return p[0] == 0xc0 && p[1] == ((condition << 4) | 0x04);
10692 }
10693
10694 static __inline__ Bool
s390_insn_is_BR(const UChar * p,UChar reg)10695 s390_insn_is_BR(const UChar *p, UChar reg)
10696 {
10697 return p[0] == 0x07 && p[1] == (0xF0 | reg); /* BCR 15,reg */
10698 }
10699
10700
10701 /* The length of the BASR insn */
10702 #define S390_BASR_LEN 2
10703
10704
10705 /* Load the 64-bit VALUE into REG. Note that this function must NOT
10706 optimise the generated code by looking at the value. I.e. using
10707 LGHI if value == 0 would be very wrong. */
10708 static UChar *
s390_tchain_load64(UChar * buf,UChar regno,ULong value)10709 s390_tchain_load64(UChar *buf, UChar regno, ULong value)
10710 {
10711 UChar *begin = buf;
10712
10713 if (s390_host_has_eimm) {
10714 /* Do it in two steps: upper half [0:31] and lower half [32:63] */
10715 buf = s390_emit_IIHF(buf, regno, value >> 32);
10716 buf = s390_emit_IILF(buf, regno, value & 0xFFFFFFFF);
10717 } else {
10718 buf = s390_emit_IILL(buf, regno, value & 0xFFFF);
10719 value >>= 16;
10720 buf = s390_emit_IILH(buf, regno, value & 0xFFFF);
10721 value >>= 16;
10722 buf = s390_emit_IIHL(buf, regno, value & 0xFFFF);
10723 value >>= 16;
10724 buf = s390_emit_IIHH(buf, regno, value & 0xFFFF);
10725 }
10726
10727 vassert(buf - begin == s390_tchain_load64_len());
10728
10729 return buf;
10730 }
10731
10732 /* Return number of bytes generated by s390_tchain_load64 */
10733 static UInt
s390_tchain_load64_len(void)10734 s390_tchain_load64_len(void)
10735 {
10736 if (s390_host_has_eimm) {
10737 return 6 + 6; /* IIHF + IILF */
10738 }
10739 return 4 + 4 + 4 + 4; /* IIHH + IIHL + IILH + IILL */
10740 }
10741
10742 /* Verify that CODE is the code sequence generated by s390_tchain_load64
10743 to load VALUE into REGNO. Return pointer to the byte following the
10744 insn sequence. */
10745 static const UChar *
s390_tchain_verify_load64(const UChar * code,UChar regno,ULong value)10746 s390_tchain_verify_load64(const UChar *code, UChar regno, ULong value)
10747 {
10748 UInt regmask = regno << 4;
10749 UInt hw;
10750
10751 if (s390_host_has_eimm) {
10752 /* Check for IIHF */
10753 vassert(code[0] == 0xC0);
10754 vassert(code[1] == (0x08 | regmask));
10755 vassert(*(const UInt *)&code[2] == (value >> 32));
10756 /* Check for IILF */
10757 vassert(code[6] == 0xC0);
10758 vassert(code[7] == (0x09 | regmask));
10759 vassert(*(const UInt *)&code[8] == (value & 0xFFFFFFFF));
10760 } else {
10761 /* Check for IILL */
10762 hw = value & 0xFFFF;
10763 vassert(code[0] == 0xA5);
10764 vassert(code[1] == (0x03 | regmask));
10765 vassert(code[2] == (hw >> 8));
10766 vassert(code[3] == (hw & 0xFF));
10767
10768 /* Check for IILH */
10769 hw = (value >> 16) & 0xFFFF;
10770 vassert(code[4] == 0xA5);
10771 vassert(code[5] == (0x02 | regmask));
10772 vassert(code[6] == (hw >> 8));
10773 vassert(code[7] == (hw & 0xFF));
10774
10775 /* Check for IIHL */
10776 hw = (value >> 32) & 0xFFFF;
10777 vassert(code[8] == 0xA5);
10778 vassert(code[9] == (0x01 | regmask));
10779 vassert(code[10] == (hw >> 8));
10780 vassert(code[11] == (hw & 0xFF));
10781
10782 /* Check for IIHH */
10783 hw = (value >> 48) & 0xFFFF;
10784 vassert(code[12] == 0xA5);
10785 vassert(code[13] == (0x00 | regmask));
10786 vassert(code[14] == (hw >> 8));
10787 vassert(code[15] == (hw & 0xFF));
10788 }
10789
10790 return code + s390_tchain_load64_len();
10791 }
10792
10793 /* CODE points to the code sequence as generated by s390_tchain_load64.
10794 Change the loaded value to IMM64. Return pointer to the byte following
10795 the patched code sequence. */
10796 static UChar *
s390_tchain_patch_load64(UChar * code,ULong imm64)10797 s390_tchain_patch_load64(UChar *code, ULong imm64)
10798 {
10799 if (s390_host_has_eimm) {
10800 /* Patch IIHF */
10801 *(UInt *)&code[2] = imm64 >> 32;
10802 /* Patch IILF */
10803 *(UInt *)&code[8] = imm64 & 0xFFFFFFFF;
10804 } else {
10805 code[3] = imm64 & 0xFF; imm64 >>= 8;
10806 code[2] = imm64 & 0xFF; imm64 >>= 8;
10807 code[7] = imm64 & 0xFF; imm64 >>= 8;
10808 code[6] = imm64 & 0xFF; imm64 >>= 8;
10809 code[11] = imm64 & 0xFF; imm64 >>= 8;
10810 code[10] = imm64 & 0xFF; imm64 >>= 8;
10811 code[15] = imm64 & 0xFF; imm64 >>= 8;
10812 code[14] = imm64 & 0xFF; imm64 >>= 8;
10813 }
10814
10815 return code + s390_tchain_load64_len();
10816 }
10817
10818
10819 /* NB: what goes on here has to be very closely coordinated with the
10820 chainXDirect_S390 and unchainXDirect_S390 below. */
10821 static UChar *
s390_insn_xdirect_emit(UChar * buf,const s390_insn * insn,const void * disp_cp_chain_me_to_slowEP,const void * disp_cp_chain_me_to_fastEP)10822 s390_insn_xdirect_emit(UChar *buf, const s390_insn *insn,
10823 const void *disp_cp_chain_me_to_slowEP,
10824 const void *disp_cp_chain_me_to_fastEP)
10825 {
10826 /* We're generating chain-me requests here, so we need to be
10827 sure this is actually allowed -- no-redir translations can't
10828 use chain-me's. Hence: */
10829 vassert(disp_cp_chain_me_to_slowEP != NULL);
10830 vassert(disp_cp_chain_me_to_fastEP != NULL);
10831
10832 /* Use ptmp for backpatching conditional jumps. */
10833 UChar *ptmp = buf;
10834
10835 /* First off, if this is conditional, create a conditional
10836 jump over the rest of it. */
10837 s390_cc_t cond = insn->variant.xdirect.cond;
10838
10839 if (cond != S390_CC_ALWAYS) {
10840 /* So we have something like this
10841 if (cond) do_xdirect;
10842 Y: ...
10843 We convert this into
10844 if (! cond) goto Y; // BRC opcode; 4 bytes
10845 do_xdirect;
10846 Y:
10847 */
10848 /* 4 bytes (a BRC insn) to be filled in here */
10849 buf += 4;
10850 }
10851
10852 /* Update the guest IA. */
10853 buf = s390_emit_load_64imm(buf, R0, insn->variant.xdirect.dst);
10854
10855 const s390_amode *amode = insn->variant.xdirect.guest_IA;
10856 vassert(amode->tag == S390_AMODE_B12);
10857 UInt b = hregNumber(amode->b);
10858 UInt d = amode->d;
10859
10860 buf = s390_emit_STG(buf, R0, 0, b, DISP20(d));
10861
10862 /* Load the chosen entry point into the scratch reg */
10863 const void *disp_cp_chain_me;
10864
10865 disp_cp_chain_me =
10866 insn->variant.xdirect.to_fast_entry ? disp_cp_chain_me_to_fastEP
10867 : disp_cp_chain_me_to_slowEP;
10868 /* Get the address of the beginning of the load64 code sequence into %r1.
10869 Do not change the register! This is part of the protocol with the
10870 dispatcher. */
10871 buf = s390_emit_BASR(buf, 1, R0);
10872
10873 /* --- FIRST PATCHABLE BYTE follows (must not modify %r1) --- */
10874 Addr64 addr = (Addr)disp_cp_chain_me;
10875 buf = s390_tchain_load64(buf, S390_REGNO_TCHAIN_SCRATCH, addr);
10876
10877 /* goto *tchain_scratch */
10878 buf = s390_emit_BCR(buf, S390_CC_ALWAYS, S390_REGNO_TCHAIN_SCRATCH);
10879
10880 /* --- END of PATCHABLE BYTES --- */
10881
10882 /* Fix up the conditional jump, if there was one. */
10883 if (cond != S390_CC_ALWAYS) {
10884 Int delta = buf - ptmp;
10885
10886 delta >>= 1; /* immediate constant is #half-words */
10887 vassert(delta > 0 && delta < (1 << 16));
10888 s390_emit_BRC(ptmp, s390_cc_invert(cond), delta);
10889 }
10890
10891 return buf;
10892 }
10893
10894 /* Return the number of patchable bytes from an xdirect insn. */
10895 static UInt
s390_xdirect_patchable_len(void)10896 s390_xdirect_patchable_len(void)
10897 {
10898 return s390_tchain_load64_len() + S390_BASR_LEN;
10899 }
10900
10901
10902 static UChar *
s390_insn_xindir_emit(UChar * buf,const s390_insn * insn,const void * disp_cp_xindir)10903 s390_insn_xindir_emit(UChar *buf, const s390_insn *insn,
10904 const void *disp_cp_xindir)
10905 {
10906 /* We're generating transfers that could lead indirectly to a
10907 chain-me, so we need to be sure this is actually allowed --
10908 no-redir translations are not allowed to reach normal
10909 translations without going through the scheduler. That means
10910 no XDirects or XIndirs out from no-redir translations.
10911 Hence: */
10912 vassert(disp_cp_xindir != NULL);
10913
10914 /* Use ptmp for backpatching conditional jumps. */
10915 UChar *ptmp = buf;
10916
10917 /* First off, if this is conditional, create a conditional
10918 jump over the rest of it. */
10919 s390_cc_t cond = insn->variant.xdirect.cond;
10920
10921 if (cond != S390_CC_ALWAYS) {
10922 /* So we have something like this
10923 if (cond) do_xdirect;
10924 Y: ...
10925 We convert this into
10926 if (! cond) goto Y; // BRC opcode; 4 bytes
10927 do_xdirect;
10928 Y:
10929 */
10930 /* 4 bytes (a BRC insn) to be filled in here */
10931 buf += 4;
10932 }
10933
10934 /* Update the guest IA with the address in xdirect.dst. */
10935 const s390_amode *amode = insn->variant.xindir.guest_IA;
10936
10937 vassert(amode->tag == S390_AMODE_B12);
10938 UInt b = hregNumber(amode->b);
10939 UInt d = amode->d;
10940 UInt regno = hregNumber(insn->variant.xindir.dst);
10941
10942 buf = s390_emit_STG(buf, regno, 0, b, DISP20(d));
10943
10944 /* load tchain_scratch, #disp_indir */
10945 buf = s390_tchain_load64(buf, S390_REGNO_TCHAIN_SCRATCH,
10946 (Addr)disp_cp_xindir);
10947 /* goto *tchain_direct */
10948 buf = s390_emit_BCR(buf, S390_CC_ALWAYS, S390_REGNO_TCHAIN_SCRATCH);
10949
10950 /* Fix up the conditional jump, if there was one. */
10951 if (cond != S390_CC_ALWAYS) {
10952 Int delta = buf - ptmp;
10953
10954 delta >>= 1; /* immediate constant is #half-words */
10955 vassert(delta > 0 && delta < (1 << 16));
10956 s390_emit_BRC(ptmp, s390_cc_invert(cond), delta);
10957 }
10958
10959 return buf;
10960 }
10961
10962 static UChar *
s390_insn_xassisted_emit(UChar * buf,const s390_insn * insn,const void * disp_cp_xassisted)10963 s390_insn_xassisted_emit(UChar *buf, const s390_insn *insn,
10964 const void *disp_cp_xassisted)
10965 {
10966 /* Use ptmp for backpatching conditional jumps. */
10967 UChar *ptmp = buf;
10968
10969 /* First off, if this is conditional, create a conditional
10970 jump over the rest of it. */
10971 s390_cc_t cond = insn->variant.xdirect.cond;
10972
10973 if (cond != S390_CC_ALWAYS) {
10974 /* So we have something like this
10975 if (cond) do_xdirect;
10976 Y: ...
10977 We convert this into
10978 if (! cond) goto Y; // BRC opcode; 4 bytes
10979 do_xdirect;
10980 Y:
10981 */
10982 /* 4 bytes (a BRC insn) to be filled in here */
10983 buf += 4;
10984 }
10985
10986 /* Update the guest IA with the address in xassisted.dst. */
10987 const s390_amode *amode = insn->variant.xassisted.guest_IA;
10988
10989 vassert(amode->tag == S390_AMODE_B12);
10990 UInt b = hregNumber(amode->b);
10991 UInt d = amode->d;
10992 UInt regno = hregNumber(insn->variant.xassisted.dst);
10993
10994 buf = s390_emit_STG(buf, regno, 0, b, DISP20(d));
10995
10996 UInt trcval = 0;
10997
10998 switch (insn->variant.xassisted.kind) {
10999 case Ijk_ClientReq: trcval = VEX_TRC_JMP_CLIENTREQ; break;
11000 case Ijk_Sys_syscall: trcval = VEX_TRC_JMP_SYS_SYSCALL; break;
11001 case Ijk_Yield: trcval = VEX_TRC_JMP_YIELD; break;
11002 case Ijk_EmWarn: trcval = VEX_TRC_JMP_EMWARN; break;
11003 case Ijk_EmFail: trcval = VEX_TRC_JMP_EMFAIL; break;
11004 case Ijk_MapFail: trcval = VEX_TRC_JMP_MAPFAIL; break;
11005 case Ijk_NoDecode: trcval = VEX_TRC_JMP_NODECODE; break;
11006 case Ijk_InvalICache: trcval = VEX_TRC_JMP_INVALICACHE; break;
11007 case Ijk_NoRedir: trcval = VEX_TRC_JMP_NOREDIR; break;
11008 case Ijk_SigTRAP: trcval = VEX_TRC_JMP_SIGTRAP; break;
11009 case Ijk_SigFPE: trcval = VEX_TRC_JMP_SIGFPE; break;
11010 case Ijk_SigSEGV: trcval = VEX_TRC_JMP_SIGSEGV; break;
11011 case Ijk_Boring: trcval = VEX_TRC_JMP_BORING; break;
11012 /* We don't expect to see the following being assisted. */
11013 case Ijk_Ret:
11014 case Ijk_Call:
11015 /* fallthrough */
11016 default:
11017 ppIRJumpKind(insn->variant.xassisted.kind);
11018 vpanic("s390_insn_xassisted_emit: unexpected jump kind");
11019 }
11020
11021 vassert(trcval != 0);
11022
11023 /* guest_state_pointer = trcval */
11024 buf = s390_emit_LGHI(buf, S390_REGNO_GUEST_STATE_POINTER, trcval);
11025
11026 /* load tchain_scratch, #disp_assisted */
11027 buf = s390_tchain_load64(buf, S390_REGNO_TCHAIN_SCRATCH,
11028 (Addr)disp_cp_xassisted);
11029
11030 /* goto *tchain_direct */
11031 buf = s390_emit_BCR(buf, S390_CC_ALWAYS, S390_REGNO_TCHAIN_SCRATCH);
11032
11033 /* Fix up the conditional jump, if there was one. */
11034 if (cond != S390_CC_ALWAYS) {
11035 Int delta = buf - ptmp;
11036
11037 delta >>= 1; /* immediate constant is #half-words */
11038 vassert(delta > 0 && delta < (1 << 16));
11039 s390_emit_BRC(ptmp, s390_cc_invert(cond), delta);
11040 }
11041
11042 return buf;
11043 }
11044
11045
11046 /* Pseudo code:
11047
11048 guest_state[host_EvC_COUNTER] -= 1;
11049 if (guest_state[host_EvC_COUNTER] >= 0) goto nofail;
11050 goto guest_state[host_EvC_FAILADDR];
11051 nofail: ;
11052
11053 The dispatch counter is a 32-bit value. */
11054 static UChar *
s390_insn_evcheck_emit(UChar * buf,const s390_insn * insn,VexEndness endness_host)11055 s390_insn_evcheck_emit(UChar *buf, const s390_insn *insn,
11056 VexEndness endness_host)
11057 {
11058 s390_amode *amode;
11059 UInt b, d;
11060 UChar *code_begin, *code_end;
11061
11062 code_begin = buf;
11063
11064 amode = insn->variant.evcheck.counter;
11065 vassert(amode->tag == S390_AMODE_B12);
11066 b = hregNumber(amode->b);
11067 d = amode->d;
11068
11069 /* Decrement the dispatch counter in the guest state */
11070 if (s390_host_has_gie) {
11071 buf = s390_emit_ASI(buf, -1, b, DISP20(d)); /* 6 bytes */
11072 } else {
11073 buf = s390_emit_LHI(buf, R0, -1); /* 4 bytes */
11074 buf = s390_emit_A(buf, R0, 0, b, d); /* 4 bytes */
11075 buf = s390_emit_ST(buf, R0, 0, b, d); /* 4 bytes */
11076 }
11077
11078 /* Jump over the next insn if >= 0 */
11079 buf = s390_emit_BRC(buf, S390_CC_HE, (4 + 6 + 2) / 2); /* 4 bytes */
11080
11081 /* Computed goto to fail_address */
11082 amode = insn->variant.evcheck.fail_addr;
11083 b = hregNumber(amode->b);
11084 d = amode->d;
11085 buf = s390_emit_LG(buf, S390_REGNO_TCHAIN_SCRATCH, 0, b, DISP20(d)); /* 6 bytes */
11086 buf = s390_emit_BCR(buf, S390_CC_ALWAYS, S390_REGNO_TCHAIN_SCRATCH); /* 2 bytes */
11087
11088 code_end = buf;
11089
11090 /* Make sure the size of the generated code is identical to the size
11091 returned by evCheckSzB_S390 */
11092 vassert(evCheckSzB_S390() == code_end - code_begin);
11093
11094 return buf;
11095 }
11096
11097
11098 static UChar *
s390_insn_profinc_emit(UChar * buf,const s390_insn * insn)11099 s390_insn_profinc_emit(UChar *buf,
11100 const s390_insn *insn __attribute__((unused)))
11101 {
11102 /* Generate a code template to increment a memory location whose
11103 address will be known later as an immediate value. This code
11104 template will be patched once the memory location is known.
11105 For now we do this with address == 0. */
11106 buf = s390_tchain_load64(buf, S390_REGNO_TCHAIN_SCRATCH, 0);
11107 if (s390_host_has_gie) {
11108 buf = s390_emit_AGSI(buf, 1, S390_REGNO_TCHAIN_SCRATCH, DISP20(0));
11109 } else {
11110 buf = s390_emit_LGHI(buf, R0, 1);
11111 buf = s390_emit_AG( buf, R0, 0, S390_REGNO_TCHAIN_SCRATCH, DISP20(0));
11112 buf = s390_emit_STG(buf, R0, 0, S390_REGNO_TCHAIN_SCRATCH, DISP20(0));
11113 }
11114
11115 return buf;
11116 }
11117
11118
11119 static UChar *
s390_insn_vec_amodeop_emit(UChar * buf,const s390_insn * insn)11120 s390_insn_vec_amodeop_emit(UChar *buf, const s390_insn *insn)
11121 {
11122 UChar v1 = hregNumber(insn->variant.vec_amodeop.dst);
11123 UChar v2 = hregNumber(insn->variant.vec_amodeop.op1);
11124 s390_amode* op2 = insn->variant.vec_amodeop.op2;
11125
11126 vassert(hregNumber(op2->x) == 0);
11127 vassert(fits_unsigned_12bit(op2->d));
11128
11129 UChar b = hregNumber(op2->b);
11130 UShort d = op2->d;
11131
11132
11133 switch (insn->variant.vec_amodeop.tag) {
11134 case S390_VEC_GET_ELEM:
11135 return s390_emit_VLGV(buf, v1, b, d, v2, s390_getM_from_size(insn->size));
11136
11137 case S390_VEC_ELEM_SHL_INT:
11138 return s390_emit_VESL(buf, v1, b, d, v2, s390_getM_from_size(insn->size));
11139
11140 case S390_VEC_ELEM_SHRA_INT:
11141 return s390_emit_VESRA(buf, v1, b, d, v2, s390_getM_from_size(insn->size));
11142
11143 case S390_VEC_ELEM_SHRL_INT:
11144 return s390_emit_VESRL(buf, v1, b, d, v2, s390_getM_from_size(insn->size));
11145
11146 default: goto fail;
11147 }
11148
11149 fail:
11150 vpanic("s390_insn_vec_amodeop_emit");
11151 }
11152
11153
11154 static UChar *
s390_insn_vec_amodeintop_emit(UChar * buf,const s390_insn * insn)11155 s390_insn_vec_amodeintop_emit(UChar *buf, const s390_insn *insn)
11156 {
11157 UChar v1 = hregNumber(insn->variant.vec_amodeintop.dst);
11158 s390_amode* op2 = insn->variant.vec_amodeintop.op2;
11159 UChar r3 = hregNumber(insn->variant.vec_amodeintop.op3);
11160
11161 vassert(hregNumber(op2->x) == 0);
11162 UChar b = hregNumber(op2->b);
11163 UShort d = op2->d;
11164
11165 switch (insn->variant.vec_amodeintop.tag) {
11166 case S390_VEC_SET_ELEM:
11167 return s390_emit_VLVG(buf, v1, b, d, r3, s390_getM_from_size(insn->size));
11168 default: goto fail;
11169 }
11170
11171 fail:
11172 vpanic("s390_insn_vec_amodeop_emit");
11173 }
11174
11175
11176 static UChar *
s390_insn_vec_binop_emit(UChar * buf,const s390_insn * insn)11177 s390_insn_vec_binop_emit(UChar *buf, const s390_insn *insn)
11178 {
11179 s390_vec_binop_t tag = insn->variant.vec_binop.tag;
11180 UChar size = insn->size;
11181 UChar v1 = hregNumber(insn->variant.vec_binop.dst);
11182 UChar v2 = hregNumber(insn->variant.vec_binop.op1);
11183 UChar v3 = hregNumber(insn->variant.vec_binop.op2);
11184
11185 switch (tag) {
11186 case S390_VEC_PACK:
11187 return s390_emit_VPK(buf, v1, v2, v3, s390_getM_from_size(size));
11188 case S390_VEC_PACK_SATURU:
11189 return s390_emit_VPKLS(buf, v1, v2, v3, s390_getM_from_size(size));
11190 case S390_VEC_PACK_SATURS:
11191 return s390_emit_VPKS(buf, v1, v2, v3, s390_getM_from_size(size));
11192 case S390_VEC_COMPARE_EQUAL:
11193 return s390_emit_VCEQ(buf, v1, v2, v3, s390_getM_from_size(size));
11194 case S390_VEC_OR:
11195 return s390_emit_VO(buf, v1, v2, v3);
11196 case S390_VEC_XOR:
11197 return s390_emit_VX(buf, v1, v2, v3);
11198 case S390_VEC_AND:
11199 return s390_emit_VN(buf, v1, v2, v3);
11200 case S390_VEC_MERGEL:
11201 return s390_emit_VMRL(buf, v1, v2, v3, s390_getM_from_size(size));
11202 case S390_VEC_MERGEH:
11203 return s390_emit_VMRH(buf, v1, v2, v3, s390_getM_from_size(size));
11204 case S390_VEC_NOR:
11205 return s390_emit_VNO(buf, v1, v2, v3);
11206 case S390_VEC_INT_ADD:
11207 return s390_emit_VA(buf, v1, v2, v3, s390_getM_from_size(size));
11208 case S390_VEC_INT_SUB:
11209 return s390_emit_VS(buf, v1, v2, v3, s390_getM_from_size(size));
11210 case S390_VEC_MAXU:
11211 return s390_emit_VMXL(buf, v1, v2, v3, s390_getM_from_size(size));
11212 case S390_VEC_MAXS:
11213 return s390_emit_VMX(buf, v1, v2, v3, s390_getM_from_size(size));
11214 case S390_VEC_MINU:
11215 return s390_emit_VMNL(buf, v1, v2, v3, s390_getM_from_size(size));
11216 case S390_VEC_MINS:
11217 return s390_emit_VMN(buf, v1, v2, v3, s390_getM_from_size(size));
11218 case S390_VEC_AVGU:
11219 return s390_emit_VAVGL(buf, v1, v2, v3, s390_getM_from_size(size));
11220 case S390_VEC_AVGS:
11221 return s390_emit_VAVG(buf, v1, v2, v3, s390_getM_from_size(size));
11222 case S390_VEC_COMPARE_GREATERS:
11223 return s390_emit_VCH(buf, v1, v2, v3, s390_getM_from_size(size));
11224 case S390_VEC_COMPARE_GREATERU:
11225 return s390_emit_VCHL(buf, v1, v2, v3, s390_getM_from_size(size));
11226 case S390_VEC_INT_MUL_HIGHS:
11227 return s390_emit_VMH(buf, v1, v2, v3, s390_getM_from_size(size));
11228 case S390_VEC_INT_MUL_HIGHU:
11229 return s390_emit_VMLH(buf, v1, v2, v3, s390_getM_from_size(size));
11230 case S390_VEC_INT_MUL_LOW:
11231 return s390_emit_VML(buf, v1, v2, v3, s390_getM_from_size(size));
11232 case S390_VEC_INT_MUL_EVENS:
11233 return s390_emit_VME(buf, v1, v2, v3, s390_getM_from_size(size));
11234 case S390_VEC_INT_MUL_EVENU:
11235 return s390_emit_VMLE(buf, v1, v2, v3, s390_getM_from_size(size));
11236 case S390_VEC_ELEM_SHL_V:
11237 return s390_emit_VESLV(buf, v1, v2, v3, s390_getM_from_size(size));
11238 case S390_VEC_ELEM_SHRA_V:
11239 return s390_emit_VESRAV(buf, v1, v2, v3, s390_getM_from_size(size));
11240 case S390_VEC_ELEM_SHRL_V:
11241 return s390_emit_VESRLV(buf, v1, v2, v3, s390_getM_from_size(size));
11242 case S390_VEC_ELEM_ROLL_V:
11243 return s390_emit_VERLLV(buf, v1, v2, v3, s390_getM_from_size(size));
11244 case S390_VEC_SHL_BITS:
11245 return s390_emit_VSL(buf, v1, v2, v3);
11246 case S390_VEC_SHRL_BITS:
11247 return s390_emit_VSRL(buf, v1, v2, v3);
11248 case S390_VEC_SHRA_BITS:
11249 return s390_emit_VSRA(buf, v1, v2, v3);
11250 case S390_VEC_SHL_BYTES:
11251 return s390_emit_VSLB(buf, v1, v2, v3);
11252 case S390_VEC_SHRL_BYTES:
11253 return s390_emit_VSRLB(buf, v1, v2, v3);
11254 case S390_VEC_SHRA_BYTES:
11255 return s390_emit_VSRAB(buf, v1, v2, v3);
11256 case S390_VEC_PWSUM_W:
11257 vassert((size == 1) || (size == 2));
11258 return s390_emit_VSUM(buf, v1, v2, v3, s390_getM_from_size(size));
11259 case S390_VEC_PWSUM_DW:
11260 vassert((size == 2) || (size == 4));
11261 return s390_emit_VSUMG(buf, v1, v2, v3, s390_getM_from_size(size));
11262 case S390_VEC_PWSUM_QW:
11263 vassert((size == 4) || (size == 8));
11264 return s390_emit_VSUMQ(buf, v1, v2, v3, s390_getM_from_size(size));
11265 case S390_VEC_INIT_FROM_GPRS:
11266 return s390_emit_VLVGP(buf, v1, v2, v3);
11267 case S390_VEC_FLOAT_ADD:
11268 return s390_emit_VFA(buf, v1, v2, v3, s390_getM_from_size(size), 0);
11269 case S390_VEC_FLOAT_SUB:
11270 return s390_emit_VFS(buf, v1, v2, v3, s390_getM_from_size(size), 0);
11271 case S390_VEC_FLOAT_MUL:
11272 return s390_emit_VFM(buf, v1, v2, v3, s390_getM_from_size(size), 0);
11273 case S390_VEC_FLOAT_DIV:
11274 return s390_emit_VFD(buf, v1, v2, v3, s390_getM_from_size(size), 0);
11275 case S390_VEC_FLOAT_COMPARE_EQUAL:
11276 return s390_emit_VFCE(buf, v1, v2, v3, s390_getM_from_size(size), 0, 0);
11277 case S390_VEC_FLOAT_COMPARE_LESS_OR_EQUAL:
11278 return s390_emit_VFCH(buf, v1, v3, v2, s390_getM_from_size(size), 0, 0);
11279 case S390_VEC_FLOAT_COMPARE_LESS:
11280 return s390_emit_VFCHE(buf, v1, v3, v2, s390_getM_from_size(size), 0, 0);
11281
11282 default:
11283 goto fail;
11284 }
11285
11286 fail:
11287 ppS390Instr(insn, True);
11288 vpanic("s390_insn_vec_binop_emit");
11289
11290 }
11291
11292
11293 static UChar *
s390_insn_vec_triop_emit(UChar * buf,const s390_insn * insn)11294 s390_insn_vec_triop_emit(UChar *buf, const s390_insn *insn)
11295 {
11296 s390_vec_triop_t tag = insn->variant.vec_triop.tag;
11297 UChar v1 = hregNumber(insn->variant.vec_triop.dst);
11298 UChar v2 = hregNumber(insn->variant.vec_triop.op1);
11299 UChar v3 = hregNumber(insn->variant.vec_triop.op2);
11300 UChar v4 = hregNumber(insn->variant.vec_triop.op3);
11301
11302 switch (tag) {
11303 case S390_VEC_PERM: {
11304 vassert(insn->size == 16);
11305 return s390_emit_VPERM(buf, v1, v2, v3, v4);
11306 }
11307 case S390_VEC_FLOAT_MADD:
11308 return s390_emit_VFMA(buf, v1, v2, v3, v4, 0, 3);
11309 case S390_VEC_FLOAT_MSUB:
11310 return s390_emit_VFMS(buf, v1, v2, v3, v4, 0, 3);
11311 default:
11312 goto fail;
11313 }
11314
11315 fail:
11316 vpanic("s390_insn_vec_triop_emit");
11317
11318 }
11319
11320
11321 Int
emit_S390Instr(Bool * is_profinc,UChar * buf,Int nbuf,const s390_insn * insn,Bool mode64,VexEndness endness_host,const void * disp_cp_chain_me_to_slowEP,const void * disp_cp_chain_me_to_fastEP,const void * disp_cp_xindir,const void * disp_cp_xassisted)11322 emit_S390Instr(Bool *is_profinc, UChar *buf, Int nbuf, const s390_insn *insn,
11323 Bool mode64, VexEndness endness_host,
11324 const void *disp_cp_chain_me_to_slowEP,
11325 const void *disp_cp_chain_me_to_fastEP,
11326 const void *disp_cp_xindir,
11327 const void *disp_cp_xassisted)
11328 {
11329 UChar *end;
11330
11331 /* Used to be 48 bytes. Make sure it stays low */
11332 vassert(sizeof(s390_insn) == 32);
11333
11334 switch (insn->tag) {
11335 case S390_INSN_LOAD:
11336 end = s390_insn_load_emit(buf, insn);
11337 break;
11338
11339 case S390_INSN_STORE:
11340 end = s390_insn_store_emit(buf, insn);
11341 break;
11342
11343 case S390_INSN_MOVE:
11344 end = s390_insn_move_emit(buf, insn);
11345 break;
11346
11347 case S390_INSN_MEMCPY:
11348 end = s390_insn_memcpy_emit(buf, insn);
11349 break;
11350
11351 case S390_INSN_COND_MOVE:
11352 end = s390_insn_cond_move_emit(buf, insn);
11353 break;
11354
11355 case S390_INSN_LOAD_IMMEDIATE:
11356 end = s390_insn_load_immediate_emit(buf, insn);
11357 break;
11358
11359 case S390_INSN_ALU:
11360 end = s390_insn_alu_emit(buf, insn);
11361 break;
11362
11363 case S390_INSN_SMUL:
11364 case S390_INSN_UMUL:
11365 end = s390_insn_mul_emit(buf, insn);
11366 break;
11367
11368 case S390_INSN_SDIV:
11369 case S390_INSN_UDIV:
11370 end = s390_insn_div_emit(buf, insn);
11371 break;
11372
11373 case S390_INSN_DIVS:
11374 end = s390_insn_divs_emit(buf, insn);
11375 break;
11376
11377 case S390_INSN_CLZ:
11378 end = s390_insn_clz_emit(buf, insn);
11379 break;
11380
11381 case S390_INSN_UNOP:
11382 end = s390_insn_unop_emit(buf, insn);
11383 break;
11384
11385 case S390_INSN_TEST:
11386 end = s390_insn_test_emit(buf, insn);
11387 break;
11388
11389 case S390_INSN_CC2BOOL:
11390 end = s390_insn_cc2bool_emit(buf, insn);
11391 break;
11392
11393 case S390_INSN_CAS:
11394 end = s390_insn_cas_emit(buf, insn);
11395 break;
11396
11397 case S390_INSN_CDAS:
11398 end = s390_insn_cdas_emit(buf, insn);
11399 break;
11400
11401 case S390_INSN_COMPARE:
11402 end = s390_insn_compare_emit(buf, insn);
11403 break;
11404
11405 case S390_INSN_HELPER_CALL:
11406 end = s390_insn_helper_call_emit(buf, insn);
11407 if (end == buf) goto fail;
11408 break;
11409
11410 case S390_INSN_BFP_TRIOP:
11411 end = s390_insn_bfp_triop_emit(buf, insn);
11412 break;
11413
11414 case S390_INSN_BFP_BINOP:
11415 end = s390_insn_bfp_binop_emit(buf, insn);
11416 break;
11417
11418 case S390_INSN_BFP_UNOP:
11419 end = s390_insn_bfp_unop_emit(buf, insn);
11420 break;
11421
11422 case S390_INSN_BFP_COMPARE:
11423 end = s390_insn_bfp_compare_emit(buf, insn);
11424 break;
11425
11426 case S390_INSN_BFP_CONVERT:
11427 end = s390_insn_bfp_convert_emit(buf, insn);
11428 break;
11429
11430 case S390_INSN_DFP_BINOP:
11431 end = s390_insn_dfp_binop_emit(buf, insn);
11432 break;
11433
11434 case S390_INSN_DFP_UNOP:
11435 end = s390_insn_dfp_unop_emit(buf, insn);
11436 break;
11437
11438 case S390_INSN_DFP_INTOP:
11439 end = s390_insn_dfp_intop_emit(buf, insn);
11440 break;
11441
11442 case S390_INSN_DFP_COMPARE:
11443 end = s390_insn_dfp_compare_emit(buf, insn);
11444 break;
11445
11446 case S390_INSN_DFP_CONVERT:
11447 end = s390_insn_dfp_convert_emit(buf, insn);
11448 break;
11449
11450 case S390_INSN_DFP_REROUND:
11451 end = s390_insn_dfp_reround_emit(buf, insn);
11452 break;
11453
11454 case S390_INSN_FP_CONVERT:
11455 end = s390_insn_fp_convert_emit(buf, insn);
11456 break;
11457
11458 case S390_INSN_MFENCE:
11459 end = s390_insn_mfence_emit(buf, insn);
11460 break;
11461
11462 case S390_INSN_MIMM:
11463 end = s390_insn_mimm_emit(buf, insn);
11464 break;
11465
11466 case S390_INSN_MADD:
11467 end = s390_insn_madd_emit(buf, insn);
11468 break;
11469
11470 case S390_INSN_SET_FPC_BFPRM:
11471 end = s390_insn_set_fpc_bfprm_emit(buf, insn);
11472 break;
11473
11474 case S390_INSN_SET_FPC_DFPRM:
11475 end = s390_insn_set_fpc_dfprm_emit(buf, insn);
11476 break;
11477
11478 case S390_INSN_PROFINC:
11479 end = s390_insn_profinc_emit(buf, insn);
11480 /* Tell the caller .. */
11481 vassert(*is_profinc == False);
11482 *is_profinc = True;
11483 break;
11484
11485 case S390_INSN_EVCHECK:
11486 end = s390_insn_evcheck_emit(buf, insn, endness_host);
11487 break;
11488
11489 case S390_INSN_XDIRECT:
11490 end = s390_insn_xdirect_emit(buf, insn, disp_cp_chain_me_to_slowEP,
11491 disp_cp_chain_me_to_fastEP);
11492 break;
11493
11494 case S390_INSN_XINDIR:
11495 end = s390_insn_xindir_emit(buf, insn, disp_cp_xindir);
11496 break;
11497
11498 case S390_INSN_XASSISTED:
11499 end = s390_insn_xassisted_emit(buf, insn, disp_cp_xassisted);
11500 break;
11501
11502 case S390_INSN_VEC_AMODEOP:
11503 end = s390_insn_vec_amodeop_emit(buf, insn);
11504 break;
11505
11506 case S390_INSN_VEC_AMODEINTOP:
11507 end = s390_insn_vec_amodeintop_emit(buf, insn);
11508 break;
11509
11510 case S390_INSN_VEC_BINOP:
11511 end = s390_insn_vec_binop_emit(buf, insn);
11512 break;
11513
11514 case S390_INSN_VEC_TRIOP:
11515 end = s390_insn_vec_triop_emit(buf, insn);
11516 break;
11517 fail:
11518 default:
11519 vpanic("emit_S390Instr");
11520 }
11521
11522 vassert(end - buf <= nbuf);
11523
11524 return end - buf;
11525 }
11526
11527
11528 /* Return the number of bytes emitted for an S390_INSN_EVCHECK.
11529 See s390_insn_evcheck_emit */
11530 Int
evCheckSzB_S390(void)11531 evCheckSzB_S390(void)
11532 {
11533 return s390_host_has_gie ? 18 : 24;
11534 }
11535
11536
11537 /* Patch the counter address into CODE_TO_PATCH as previously
11538 generated by s390_insn_profinc_emit. */
11539 VexInvalRange
patchProfInc_S390(VexEndness endness_host,void * code_to_patch,const ULong * location_of_counter)11540 patchProfInc_S390(VexEndness endness_host,
11541 void *code_to_patch, const ULong *location_of_counter)
11542 {
11543 vassert(sizeof(ULong *) == 8);
11544
11545 s390_tchain_verify_load64(code_to_patch, S390_REGNO_TCHAIN_SCRATCH, 0);
11546
11547 UChar *p = s390_tchain_patch_load64(code_to_patch,
11548 (Addr)location_of_counter);
11549
11550 UInt len = p - (UChar *)code_to_patch;
11551 VexInvalRange vir = { (HWord)code_to_patch, len };
11552 return vir;
11553 }
11554
11555
11556 /* NB: what goes on here has to be very closely coordinated with the
11557 s390_insn_xdirect_emit code above. */
11558 VexInvalRange
chainXDirect_S390(VexEndness endness_host,void * place_to_chain,const void * disp_cp_chain_me_EXPECTED,const void * place_to_jump_to)11559 chainXDirect_S390(VexEndness endness_host,
11560 void *place_to_chain,
11561 const void *disp_cp_chain_me_EXPECTED,
11562 const void *place_to_jump_to)
11563 {
11564 vassert(endness_host == VexEndnessBE);
11565
11566 /* What we're expecting to see @ PLACE_TO_CHAIN is:
11567
11568 load tchain_scratch, #disp_cp_chain_me_EXPECTED
11569 goto *tchain_scratch
11570 */
11571 const UChar *next;
11572 next = s390_tchain_verify_load64(place_to_chain, S390_REGNO_TCHAIN_SCRATCH,
11573 (Addr)disp_cp_chain_me_EXPECTED);
11574 vassert(s390_insn_is_BR(next, S390_REGNO_TCHAIN_SCRATCH));
11575
11576 /* And what we want to change it to is either:
11577 (general case):
11578
11579 load tchain_scratch, #place_to_jump_to
11580 goto *tchain_scratch
11581
11582 ---OR---
11583
11584 in the case where the displacement is small enough
11585
11586 BRCL delta where delta is in half-words
11587 invalid opcodes
11588
11589 In both cases the replacement has the same length as the original.
11590 To remain sane & verifiable,
11591 (1) limit the displacement for the short form to
11592 (say) +/- one billion, so as to avoid wraparound
11593 off-by-ones
11594 (2) even if the short form is applicable, once every (say)
11595 1024 times use the long form anyway, so as to maintain
11596 verifiability
11597 */
11598
11599 /* This is the delta we need to put into a BRCL insn. Note, that the
11600 offset in BRCL is in half-words. Hence division by 2. */
11601 Long delta =
11602 (Long)((const UChar *)place_to_jump_to - (const UChar *)place_to_chain) / 2;
11603 Bool shortOK = delta >= -1000*1000*1000 && delta < 1000*1000*1000;
11604
11605 static UInt shortCTR = 0; /* DO NOT MAKE NON-STATIC */
11606 if (shortOK) {
11607 shortCTR++; // thread safety bleh
11608 if (0 == (shortCTR & 0x3FF)) {
11609 shortOK = False;
11610 if (0)
11611 vex_printf("QQQ chainXDirect_S390: shortCTR = %u, "
11612 "using long jmp\n", shortCTR);
11613 }
11614 }
11615
11616 /* And make the modifications. */
11617 UChar *p = (UChar *)place_to_chain;
11618 if (shortOK) {
11619 p = s390_emit_BRCL(p, S390_CC_ALWAYS, delta); /* 6 bytes */
11620
11621 /* Make sure that BRCL fits into the patchable part of an xdirect
11622 code sequence */
11623 vassert(6 <= s390_xdirect_patchable_len());
11624
11625 /* Fill remaining bytes with 0x00 (invalid opcode) */
11626 Int i;
11627 for (i = 0; i < s390_xdirect_patchable_len() - 6; ++i)
11628 p[i] = 0x00;
11629 } else {
11630 /*
11631 load tchain_scratch, #place_to_jump_to
11632 goto *tchain_scratch
11633 */
11634 Addr64 addr = (Addr)place_to_jump_to;
11635 p = s390_tchain_load64(p, S390_REGNO_TCHAIN_SCRATCH, addr);
11636 /* There is not need to emit a BCR here, as it is already there. */
11637 }
11638
11639 UInt len = p - (UChar *)place_to_chain;
11640 VexInvalRange vir = { (HWord)place_to_chain, len };
11641 return vir;
11642 }
11643
11644
11645 /* NB: what goes on here has to be very closely coordinated with the
11646 s390_insn_xdirect_emit code above. */
11647 VexInvalRange
unchainXDirect_S390(VexEndness endness_host,void * place_to_unchain,const void * place_to_jump_to_EXPECTED,const void * disp_cp_chain_me)11648 unchainXDirect_S390(VexEndness endness_host,
11649 void *place_to_unchain,
11650 const void *place_to_jump_to_EXPECTED,
11651 const void *disp_cp_chain_me)
11652 {
11653 vassert(endness_host == VexEndnessBE);
11654
11655 /* What we're expecting to see @ PLACE_TO_UNCHAIN:
11656
11657 load tchain_scratch, #place_to_jump_to_EXPECTED
11658 goto *tchain_scratch
11659
11660 ---OR---
11661 in the case where the displacement falls within 32 bits
11662
11663 BRCL delta
11664 invalid opcodes
11665 */
11666 UChar *p = place_to_unchain;
11667
11668 Bool uses_short_form = False;
11669
11670 if (s390_insn_is_BRCL(p, S390_CC_ALWAYS)) {
11671 /* Looks like the short form */
11672 Int num_hw = *(Int *)&p[2];
11673 Int delta = 2 *num_hw;
11674
11675 vassert(p + delta == place_to_jump_to_EXPECTED);
11676
11677 Int i;
11678 for (i = 0; i < s390_xdirect_patchable_len() - 6; ++i)
11679 vassert(p[6+i] == 0x00);
11680 uses_short_form = True;
11681 } else {
11682 /* Should be the long form */
11683 const UChar *next;
11684
11685 next = s390_tchain_verify_load64(p, S390_REGNO_TCHAIN_SCRATCH,
11686 (Addr)place_to_jump_to_EXPECTED);
11687 /* Check for BR *tchain_scratch */
11688 vassert(s390_insn_is_BR(next, S390_REGNO_TCHAIN_SCRATCH));
11689 }
11690
11691 /* And what we want to change it to is:
11692
11693 load tchain_scratch, #disp_cp_chain_me
11694 goto *tchain_scratch
11695 */
11696
11697 /* Get the address of the beginning of the load64 code sequence into %r1.
11698 Do not change the register! This is part of the protocol with the
11699 dispatcher.
11700 Note: the incoming argument PLACE_TO_CHAIN points to the beginning of the
11701 load64 insn sequence. That sequence is prefixed with a BASR to get its
11702 address (see s390_insn_xdirect_emit). */
11703 p = s390_emit_BASR(p - S390_BASR_LEN, 1, R0);
11704
11705 Addr64 addr = (Addr)disp_cp_chain_me;
11706 p = s390_tchain_load64(p, S390_REGNO_TCHAIN_SCRATCH, addr);
11707
11708 /* Emit the BCR in case the short form was used. In case of the long
11709 form, the BCR is already there. */
11710 if (uses_short_form)
11711 s390_emit_BCR(p, S390_CC_ALWAYS, S390_REGNO_TCHAIN_SCRATCH);
11712
11713 UInt len = p - (UChar *)place_to_unchain;
11714 VexInvalRange vir = { (HWord)place_to_unchain, len };
11715 return vir;
11716 }
11717
11718 /*---------------------------------------------------------------*/
11719 /*--- end host_s390_defs.c ---*/
11720 /*---------------------------------------------------------------*/
11721