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