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-2015
12 Copyright (C) 2012-2015 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%u", r); break;
112 case HRcFlt64: vex_sprintf(buf, "%%vF%u", 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_FIEBRA(UChar * p,UChar m3,UChar m4,UChar r1,UChar r2)3942 s390_emit_FIEBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
3943 {
3944 vassert(m3 == 0 || s390_host_has_fpext);
3945
3946 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
3947 if (m4 == 0)
3948 s390_disasm(ENC4(MNM, FPR, UINT, FPR), "fiebr", r1, m3, r2);
3949 else
3950 s390_disasm(ENC5(MNM, FPR, UINT, FPR, UINT),
3951 "fiebra", r1, m3, r2, m4);
3952 }
3953
3954 return emit_RRF2(p, 0xb3570000, m3, m4, r1, r2);
3955 }
3956
3957
3958 static UChar *
s390_emit_FIDBRA(UChar * p,UChar m3,UChar m4,UChar r1,UChar r2)3959 s390_emit_FIDBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
3960 {
3961 vassert(m3 == 0 || s390_host_has_fpext);
3962
3963 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
3964 if (m4 == 0)
3965 s390_disasm(ENC4(MNM, FPR, UINT, FPR), "fidbr", r1, m3, r2);
3966 else
3967 s390_disasm(ENC5(MNM, FPR, UINT, FPR, UINT),
3968 "fidbra", r1, m3, r2, m4);
3969 }
3970
3971 return emit_RRF2(p, 0xb35f0000, m3, m4, r1, r2);
3972 }
3973
3974
3975 static UChar *
s390_emit_FIXBRA(UChar * p,UChar m3,UChar m4,UChar r1,UChar r2)3976 s390_emit_FIXBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
3977 {
3978 vassert(m3 == 0 || s390_host_has_fpext);
3979
3980 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
3981 if (m4 == 0)
3982 s390_disasm(ENC4(MNM, FPR, UINT, FPR), "fixbr", r1, m3, r2);
3983 else
3984 s390_disasm(ENC5(MNM, FPR, UINT, FPR, UINT),
3985 "fixbra", r1, m3, r2, m4);
3986 }
3987
3988 return emit_RRF2(p, 0xb3470000, m3, m4, r1, r2);
3989 }
3990
3991
3992 static UChar *
s390_emit_MEEBR(UChar * p,UChar r1,UChar r2)3993 s390_emit_MEEBR(UChar *p, UChar r1, UChar r2)
3994 {
3995 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3996 s390_disasm(ENC3(MNM, FPR, FPR), "meebr", r1, r2);
3997
3998 return emit_RRE(p, 0xb3170000, r1, r2);
3999 }
4000
4001
4002 static UChar *
s390_emit_MDBR(UChar * p,UChar r1,UChar r2)4003 s390_emit_MDBR(UChar *p, UChar r1, UChar r2)
4004 {
4005 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4006 s390_disasm(ENC3(MNM, FPR, FPR), "mdbr", r1, r2);
4007
4008 return emit_RRE(p, 0xb31c0000, r1, r2);
4009 }
4010
4011
4012 static UChar *
s390_emit_MXBR(UChar * p,UChar r1,UChar r2)4013 s390_emit_MXBR(UChar *p, UChar r1, UChar r2)
4014 {
4015 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4016 s390_disasm(ENC3(MNM, FPR, FPR), "mxbr", r1, r2);
4017
4018 return emit_RRE(p, 0xb34c0000, r1, r2);
4019 }
4020
4021
4022 static UChar *
s390_emit_MAEBR(UChar * p,UChar r1,UChar r3,UChar r2)4023 s390_emit_MAEBR(UChar *p, UChar r1, UChar r3, UChar r2)
4024 {
4025 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4026 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "maebr", r1, r3, r2);
4027
4028 return emit_RRF(p, 0xb30e0000, r1, r3, r2);
4029 }
4030
4031
4032 static UChar *
s390_emit_MADBR(UChar * p,UChar r1,UChar r3,UChar r2)4033 s390_emit_MADBR(UChar *p, UChar r1, UChar r3, UChar r2)
4034 {
4035 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4036 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "madbr", r1, r3, r2);
4037
4038 return emit_RRF(p, 0xb31e0000, r1, r3, r2);
4039 }
4040
4041
4042 static UChar *
s390_emit_MSEBR(UChar * p,UChar r1,UChar r3,UChar r2)4043 s390_emit_MSEBR(UChar *p, UChar r1, UChar r3, UChar r2)
4044 {
4045 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4046 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "msebr", r1, r3, r2);
4047
4048 return emit_RRF(p, 0xb30f0000, r1, r3, r2);
4049 }
4050
4051
4052 static UChar *
s390_emit_MSDBR(UChar * p,UChar r1,UChar r3,UChar r2)4053 s390_emit_MSDBR(UChar *p, UChar r1, UChar r3, UChar r2)
4054 {
4055 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4056 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "msdbr", r1, r3, r2);
4057
4058 return emit_RRF(p, 0xb31f0000, r1, r3, r2);
4059 }
4060
4061
4062 static UChar *
s390_emit_SQEBR(UChar * p,UChar r1,UChar r2)4063 s390_emit_SQEBR(UChar *p, UChar r1, UChar r2)
4064 {
4065 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4066 s390_disasm(ENC3(MNM, FPR, FPR), "sqebr", r1, r2);
4067
4068 return emit_RRE(p, 0xb3140000, r1, r2);
4069 }
4070
4071
4072 static UChar *
s390_emit_SQDBR(UChar * p,UChar r1,UChar r2)4073 s390_emit_SQDBR(UChar *p, UChar r1, UChar r2)
4074 {
4075 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4076 s390_disasm(ENC3(MNM, FPR, FPR), "sqdbr", r1, r2);
4077
4078 return emit_RRE(p, 0xb3150000, r1, r2);
4079 }
4080
4081
4082 static UChar *
s390_emit_SQXBR(UChar * p,UChar r1,UChar r2)4083 s390_emit_SQXBR(UChar *p, UChar r1, UChar r2)
4084 {
4085 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4086 s390_disasm(ENC3(MNM, FPR, FPR), "sqxbr", r1, r2);
4087
4088 return emit_RRE(p, 0xb3160000, r1, r2);
4089 }
4090
4091
4092 static UChar *
s390_emit_SEBR(UChar * p,UChar r1,UChar r2)4093 s390_emit_SEBR(UChar *p, UChar r1, UChar r2)
4094 {
4095 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4096 s390_disasm(ENC3(MNM, FPR, FPR), "sebr", r1, r2);
4097
4098 return emit_RRE(p, 0xb30b0000, r1, r2);
4099 }
4100
4101
4102 static UChar *
s390_emit_SDBR(UChar * p,UChar r1,UChar r2)4103 s390_emit_SDBR(UChar *p, UChar r1, UChar r2)
4104 {
4105 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4106 s390_disasm(ENC3(MNM, FPR, FPR), "sdbr", r1, r2);
4107
4108 return emit_RRE(p, 0xb31b0000, r1, r2);
4109 }
4110
4111
4112 static UChar *
s390_emit_SXBR(UChar * p,UChar r1,UChar r2)4113 s390_emit_SXBR(UChar *p, UChar r1, UChar r2)
4114 {
4115 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4116 s390_disasm(ENC3(MNM, FPR, FPR), "sxbr", r1, r2);
4117
4118 return emit_RRE(p, 0xb34b0000, r1, r2);
4119 }
4120
4121
4122 static UChar *
s390_emit_ADTRA(UChar * p,UChar r3,UChar m4,UChar r1,UChar r2)4123 s390_emit_ADTRA(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
4124 {
4125 vassert(s390_host_has_dfp);
4126 vassert(m4 == 0 || s390_host_has_fpext);
4127 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
4128 if (m4 == 0)
4129 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "adtr", r1, r2, r3);
4130 else
4131 s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "adtra", r1, r2, r3, m4);
4132 }
4133
4134 return emit_RRF4(p, 0xb3d20000, r3, m4, r1, r2);
4135 }
4136
4137
4138 static UChar *
s390_emit_AXTRA(UChar * p,UChar r3,UChar m4,UChar r1,UChar r2)4139 s390_emit_AXTRA(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
4140 {
4141 vassert(s390_host_has_dfp);
4142 vassert(m4 == 0 || s390_host_has_fpext);
4143 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
4144 if (m4 == 0)
4145 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "axtr", r1, r2, r3);
4146 else
4147 s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "axtra", r1, r2, r3, m4);
4148 }
4149
4150 return emit_RRF4(p, 0xb3da0000, r3, m4, r1, r2);
4151 }
4152
4153
4154 static UChar *
s390_emit_CDTR(UChar * p,UChar r1,UChar r2)4155 s390_emit_CDTR(UChar *p, UChar r1, UChar r2)
4156 {
4157 vassert(s390_host_has_dfp);
4158 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4159 s390_disasm(ENC3(MNM, FPR, FPR), "cdtr", r1, r2);
4160
4161 return emit_RRE(p, 0xb3e40000, r1, r2);
4162 }
4163
4164
4165 static UChar *
s390_emit_CXTR(UChar * p,UChar r1,UChar r2)4166 s390_emit_CXTR(UChar *p, UChar r1, UChar r2)
4167 {
4168 vassert(s390_host_has_dfp);
4169 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4170 s390_disasm(ENC3(MNM, FPR, FPR), "cxtr", r1, r2);
4171
4172 return emit_RRE(p, 0xb3ec0000, r1, r2);
4173 }
4174
4175
4176 static UChar *
s390_emit_CDGTRA(UChar * p,UChar m3,UChar m4,UChar r1,UChar r2)4177 s390_emit_CDGTRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4178 {
4179 vassert(s390_host_has_dfp);
4180 vassert(m4 == 0);
4181 vassert(m3 == 0 || s390_host_has_fpext);
4182
4183 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
4184 if (m3 == 0)
4185 s390_disasm(ENC3(MNM, FPR, GPR), "cdgtr", r1, r2);
4186 else
4187 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cdgtra", r1, m3, r2, m4);
4188 }
4189
4190 return emit_RRF2(p, 0xb3f10000, m3, m4, r1, r2);
4191 }
4192
4193
4194 static UChar *
s390_emit_CXGTR(UChar * p,UChar m3,UChar m4,UChar r1,UChar r2)4195 s390_emit_CXGTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4196 {
4197 vassert(s390_host_has_dfp);
4198 vassert(m4 == 0);
4199 /* rounding mode m3 is not considered, as the corresponding
4200 IRop (Iop_I64StoD128) does not take rounding mode. */
4201 vassert(m3 == 0);
4202
4203 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4204 s390_disasm(ENC3(MNM, FPR, GPR), "cxgtr", r1, r2);
4205
4206 return emit_RRF2(p, 0xb3f90000, m3, m4, r1, r2);
4207 }
4208
4209
4210 static UChar *
s390_emit_CDFTR(UChar * p,UChar m3,UChar m4,UChar r1,UChar r2)4211 s390_emit_CDFTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4212 {
4213 vassert(m4 == 0);
4214 vassert(s390_host_has_dfp);
4215 vassert(s390_host_has_fpext);
4216
4217 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4218 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cdftr", r1, m3, r2, m4);
4219
4220 return emit_RRF2(p, 0xb9510000, m3, m4, r1, r2);
4221 }
4222
4223
4224 static UChar *
s390_emit_CXFTR(UChar * p,UChar m3,UChar m4,UChar r1,UChar r2)4225 s390_emit_CXFTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4226 {
4227 vassert(m4 == 0);
4228 vassert(s390_host_has_dfp);
4229 vassert(s390_host_has_fpext);
4230
4231 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4232 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cxftr", r1, m3, r2, m4);
4233
4234 return emit_RRF2(p, 0xb9590000, m3, m4, r1, r2);
4235 }
4236
4237
4238 static UChar *
s390_emit_CDLFTR(UChar * p,UChar m3,UChar m4,UChar r1,UChar r2)4239 s390_emit_CDLFTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4240 {
4241 vassert(m4 == 0);
4242 vassert(s390_host_has_dfp);
4243 vassert(s390_host_has_fpext);
4244
4245 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4246 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cdlftr", r1, m3, r2, m4);
4247
4248 return emit_RRF2(p, 0xb9530000, m3, m4, r1, r2);
4249 }
4250
4251
4252 static UChar *
s390_emit_CXLFTR(UChar * p,UChar m3,UChar m4,UChar r1,UChar r2)4253 s390_emit_CXLFTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4254 {
4255 vassert(m4 == 0);
4256 vassert(s390_host_has_dfp);
4257 vassert(s390_host_has_fpext);
4258
4259 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4260 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cxlftr", r1, m3, r2, m4);
4261
4262 return emit_RRF2(p, 0xb95b0000, m3, m4, r1, r2);
4263 }
4264
4265
4266 static UChar *
s390_emit_CDLGTR(UChar * p,UChar m3,UChar m4,UChar r1,UChar r2)4267 s390_emit_CDLGTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4268 {
4269 vassert(m4 == 0);
4270 vassert(s390_host_has_dfp);
4271 vassert(s390_host_has_fpext);
4272
4273 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4274 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cdlgtr", r1, m3, r2, m4);
4275
4276 return emit_RRF2(p, 0xb9520000, m3, m4, r1, r2);
4277 }
4278
4279
4280 static UChar *
s390_emit_CXLGTR(UChar * p,UChar m3,UChar m4,UChar r1,UChar r2)4281 s390_emit_CXLGTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4282 {
4283 vassert(m4 == 0);
4284 vassert(s390_host_has_dfp);
4285 vassert(s390_host_has_fpext);
4286
4287 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4288 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cxlgtr", r1, m3, r2, m4);
4289
4290 return emit_RRF2(p, 0xb95a0000, m3, m4, r1, r2);
4291 }
4292
4293
4294 static UChar *
s390_emit_CEDTR(UChar * p,UChar r1,UChar r2)4295 s390_emit_CEDTR(UChar *p, UChar r1, UChar r2)
4296 {
4297 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4298 s390_disasm(ENC3(MNM, FPR, FPR), "cedtr", r1, r2);
4299
4300 return emit_RRE(p, 0xb3f40000, r1, r2);
4301 }
4302
4303
4304 static UChar *
s390_emit_CEXTR(UChar * p,UChar r1,UChar r2)4305 s390_emit_CEXTR(UChar *p, UChar r1, UChar r2)
4306 {
4307 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4308 s390_disasm(ENC3(MNM, FPR, FPR), "cextr", r1, r2);
4309
4310 return emit_RRE(p, 0xb3fc0000, r1, r2);
4311 }
4312
4313
4314 static UChar *
s390_emit_CFDTR(UChar * p,UChar m3,UChar m4,UChar r1,UChar r2)4315 s390_emit_CFDTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4316 {
4317 vassert(m4 == 0);
4318 vassert(s390_host_has_dfp);
4319 vassert(s390_host_has_fpext);
4320
4321 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4322 s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "cfdtr", r1, m3, r2, m4);
4323
4324 return emit_RRF2(p, 0xb9410000, m3, m4, r1, r2);
4325 }
4326
4327
4328 static UChar *
s390_emit_CFXTR(UChar * p,UChar m3,UChar m4,UChar r1,UChar r2)4329 s390_emit_CFXTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4330 {
4331 vassert(m4 == 0);
4332 vassert(s390_host_has_dfp);
4333 vassert(s390_host_has_fpext);
4334
4335 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4336 s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "cfxtr", r1, m3, r2, m4);
4337
4338 return emit_RRF2(p, 0xb9490000, m3, m4, r1, r2);
4339 }
4340
4341
4342 static UChar *
s390_emit_CGDTR(UChar * p,UChar m3,UChar m4,UChar r1,UChar r2)4343 s390_emit_CGDTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4344 {
4345 vassert(s390_host_has_dfp);
4346 vassert(m4 == 0);
4347 vassert(s390_host_has_fpext || m3 < 1 || m3 > 7);
4348
4349 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4350 s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cgdtr", r1, m3, r2);
4351
4352 return emit_RRF2(p, 0xb3e10000, m3, m4, r1, r2);
4353 }
4354
4355
4356 static UChar *
s390_emit_CGXTR(UChar * p,UChar m3,UChar m4,UChar r1,UChar r2)4357 s390_emit_CGXTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4358 {
4359 vassert(s390_host_has_dfp);
4360 vassert(m4 == 0);
4361 vassert(s390_host_has_fpext || m3 < 1 || m3 > 7);
4362
4363 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4364 s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cgxtr", r1, m3, r2);
4365
4366 return emit_RRF2(p, 0xb3e90000, m3, m4, r1, r2);
4367 }
4368
4369
4370 static UChar *
s390_emit_CLFDTR(UChar * p,UChar m3,UChar m4,UChar r1,UChar r2)4371 s390_emit_CLFDTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4372 {
4373 vassert(m4 == 0);
4374 vassert(s390_host_has_dfp);
4375 vassert(s390_host_has_fpext);
4376
4377 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4378 s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clfdtr", r1, m3, r2, m4);
4379
4380 return emit_RRF2(p, 0xb9430000, m3, m4, r1, r2);
4381 }
4382
4383
4384 static UChar *
s390_emit_CLFXTR(UChar * p,UChar m3,UChar m4,UChar r1,UChar r2)4385 s390_emit_CLFXTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4386 {
4387 vassert(m4 == 0);
4388 vassert(s390_host_has_dfp);
4389 vassert(s390_host_has_fpext);
4390
4391 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4392 s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clfxtr", r1, m3, r2, m4);
4393
4394 return emit_RRF2(p, 0xb94b0000, m3, m4, r1, r2);
4395 }
4396
4397
4398 static UChar *
s390_emit_CLGDTR(UChar * p,UChar m3,UChar m4,UChar r1,UChar r2)4399 s390_emit_CLGDTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4400 {
4401 vassert(m4 == 0);
4402 vassert(s390_host_has_dfp);
4403 vassert(s390_host_has_fpext);
4404
4405 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4406 s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clgdtr", r1, m3, r2, m4);
4407
4408 return emit_RRF2(p, 0xb9420000, m3, m4, r1, r2);
4409 }
4410
4411
4412 static UChar *
s390_emit_CLGXTR(UChar * p,UChar m3,UChar m4,UChar r1,UChar r2)4413 s390_emit_CLGXTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4414 {
4415 vassert(m4 == 0);
4416 vassert(s390_host_has_dfp);
4417 vassert(s390_host_has_fpext);
4418
4419 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4420 s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clgxtr", r1, m3, r2, m4);
4421
4422 return emit_RRF2(p, 0xb94a0000, m3, m4, r1, r2);
4423 }
4424
4425
4426 static UChar *
s390_emit_DDTRA(UChar * p,UChar r3,UChar m4,UChar r1,UChar r2)4427 s390_emit_DDTRA(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
4428 {
4429 vassert(s390_host_has_dfp);
4430 vassert(m4 == 0 || s390_host_has_fpext);
4431 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
4432 if (m4 == 0)
4433 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "ddtr", r1, r2, r3);
4434 else
4435 s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "ddtra", r1, r2, r3, m4);
4436 }
4437
4438 return emit_RRF4(p, 0xb3d10000, r3, m4, r1, r2);
4439 }
4440
4441
4442 static UChar *
s390_emit_DXTRA(UChar * p,UChar r3,UChar m4,UChar r1,UChar r2)4443 s390_emit_DXTRA(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
4444 {
4445 vassert(s390_host_has_dfp);
4446 vassert(m4 == 0 || s390_host_has_fpext);
4447 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
4448 if (m4 == 0)
4449 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "dxtr", r1, r2, r3);
4450 else
4451 s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "dxtra", r1, r2, r3, m4);
4452 }
4453
4454 return emit_RRF4(p, 0xb3d90000, r3, m4, r1, r2);
4455 }
4456
4457
4458 static UChar *
s390_emit_EEDTR(UChar * p,UChar r1,UChar r2)4459 s390_emit_EEDTR(UChar *p, UChar r1, UChar r2)
4460 {
4461 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4462 s390_disasm(ENC3(MNM, GPR, FPR), "eedtr", r1, r2);
4463
4464 return emit_RRE(p, 0xb3e50000, r1, r2);
4465 }
4466
4467
4468 static UChar *
s390_emit_EEXTR(UChar * p,UChar r1,UChar r2)4469 s390_emit_EEXTR(UChar *p, UChar r1, UChar r2)
4470 {
4471 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4472 s390_disasm(ENC3(MNM, GPR, FPR), "eextr", r1, r2);
4473
4474 return emit_RRE(p, 0xb3ed0000, r1, r2);
4475 }
4476
4477
4478 static UChar *
s390_emit_ESDTR(UChar * p,UChar r1,UChar r2)4479 s390_emit_ESDTR(UChar *p, UChar r1, UChar r2)
4480 {
4481 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4482 s390_disasm(ENC3(MNM, GPR, FPR), "esdtr", r1, r2);
4483
4484 return emit_RRE(p, 0xb3e70000, r1, r2);
4485 }
4486
4487
4488 static UChar *
s390_emit_ESXTR(UChar * p,UChar r1,UChar r2)4489 s390_emit_ESXTR(UChar *p, UChar r1, UChar r2)
4490 {
4491 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4492 s390_disasm(ENC3(MNM, GPR, FPR), "esxtr", r1, r2);
4493
4494 return emit_RRE(p, 0xb3ef0000, r1, r2);
4495 }
4496
4497
4498 static UChar *
s390_emit_IEDTR(UChar * p,UChar r3,UChar r1,UChar r2)4499 s390_emit_IEDTR(UChar *p, UChar r3, UChar r1, UChar r2)
4500 {
4501 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4502 s390_disasm(ENC4(MNM, FPR, FPR, GPR), "iedtr", r1, r3, r2);
4503
4504 return emit_RRF(p, 0xb3f60000, r3, r1, r2);
4505 }
4506
4507
4508 static UChar *
s390_emit_IEXTR(UChar * p,UChar r3,UChar r1,UChar r2)4509 s390_emit_IEXTR(UChar *p, UChar r3, UChar r1, UChar r2)
4510 {
4511 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4512 s390_disasm(ENC4(MNM, FPR, FPR, GPR), "iextr", r1, r3, r2);
4513
4514 return emit_RRF(p, 0xb3fe0000, r3, r1, r2);
4515 }
4516
4517
4518 static UChar *
s390_emit_LDETR(UChar * p,UChar m4,UChar r1,UChar r2)4519 s390_emit_LDETR(UChar *p, UChar m4, UChar r1, UChar r2)
4520 {
4521 vassert(s390_host_has_dfp);
4522 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4523 s390_disasm(ENC4(MNM, FPR, FPR, UINT), "ldetr", r1, r2, m4);
4524
4525 return emit_RRF5(p, 0xb3d40000, m4, r1, r2);
4526 }
4527
4528
4529 static UChar *
s390_emit_LXDTR(UChar * p,UChar m4,UChar r1,UChar r2)4530 s390_emit_LXDTR(UChar *p, UChar m4, UChar r1, UChar r2)
4531 {
4532 vassert(s390_host_has_dfp);
4533 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4534 s390_disasm(ENC4(MNM, FPR, FPR, UINT), "lxdtr", r1, r2, m4);
4535
4536 return emit_RRF5(p, 0xb3dc0000, m4, r1, r2);
4537 }
4538
4539
4540 static UChar *
s390_emit_LEDTR(UChar * p,UChar m3,UChar m4,UChar r1,UChar r2)4541 s390_emit_LEDTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4542 {
4543 vassert(s390_host_has_dfp);
4544 vassert(m4 == 0);
4545 vassert(s390_host_has_fpext || m3 < 1 || m3 > 7);
4546
4547 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4548 s390_disasm(ENC5(MNM, FPR, UINT, FPR, UINT), "ledtr", r1, m3, r2, m4);
4549
4550 return emit_RRF2(p, 0xb3d50000, m3, m4, r1, r2);
4551 }
4552
4553
4554 static UChar *
s390_emit_LDXTR(UChar * p,UChar m3,UChar m4,UChar r1,UChar r2)4555 s390_emit_LDXTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4556 {
4557 vassert(s390_host_has_dfp);
4558 vassert(m4 == 0);
4559 vassert(s390_host_has_fpext || m3 < 1 || m3 > 7);
4560
4561 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4562 s390_disasm(ENC5(MNM, FPR, UINT, FPR, UINT), "ldxtr", r1, m3, r2, m4);
4563
4564 return emit_RRF2(p, 0xb3dd0000, m3, m4, r1, r2);
4565 }
4566
4567
4568 static UChar *
s390_emit_MDTRA(UChar * p,UChar r3,UChar m4,UChar r1,UChar r2)4569 s390_emit_MDTRA(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
4570 {
4571 vassert(s390_host_has_dfp);
4572 vassert(m4 == 0 || s390_host_has_fpext);
4573 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
4574 if (m4 == 0)
4575 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "mdtr", r1, r2, r3);
4576 else
4577 s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "mdtra", r1, r2, r3, m4);
4578 }
4579
4580 return emit_RRF4(p, 0xb3d00000, r3, m4, r1, r2);
4581 }
4582
4583
4584 static UChar *
s390_emit_MXTRA(UChar * p,UChar r3,UChar m4,UChar r1,UChar r2)4585 s390_emit_MXTRA(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
4586 {
4587 vassert(s390_host_has_dfp);
4588 vassert(m4 == 0 || s390_host_has_fpext);
4589 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
4590 if (m4 == 0)
4591 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "mxtr", r1, r2, r3);
4592 else
4593 s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "mxtra", r1, r2, r3, m4);
4594 }
4595
4596 return emit_RRF4(p, 0xb3d80000, r3, m4, r1, r2);
4597 }
4598
4599
4600 static UChar *
emit_E(UChar * p,UInt op)4601 emit_E(UChar *p, UInt op)
4602 {
4603 ULong the_insn = op;
4604
4605 return emit_2bytes(p, the_insn);
4606 }
4607
4608
4609 static UChar *
s390_emit_PFPO(UChar * p)4610 s390_emit_PFPO(UChar *p)
4611 {
4612 vassert(s390_host_has_pfpo);
4613 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
4614 s390_disasm(ENC1(MNM), "pfpo");
4615 }
4616
4617 return emit_E(p, 0x010a);
4618 }
4619
4620
4621 static UChar *
s390_emit_QADTR(UChar * p,UChar r3,UChar m4,UChar r1,UChar r2)4622 s390_emit_QADTR(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
4623 {
4624 vassert(s390_host_has_dfp);
4625 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4626 s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "qadtr", r1, r3, r2, m4);
4627
4628 return emit_RRF4(p, 0xb3f50000, r3, m4, r1, r2);
4629 }
4630
4631
4632 static UChar *
s390_emit_QAXTR(UChar * p,UChar r3,UChar m4,UChar r1,UChar r2)4633 s390_emit_QAXTR(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
4634 {
4635 vassert(s390_host_has_dfp);
4636 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4637 s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "qaxtr", r1, r3, r2, m4);
4638
4639 return emit_RRF4(p, 0xb3fd0000, r3, m4, r1, r2);
4640 }
4641
4642
4643 static UChar *
s390_emit_RRDTR(UChar * p,UChar r3,UChar m4,UChar r1,UChar r2)4644 s390_emit_RRDTR(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
4645 {
4646 vassert(s390_host_has_dfp);
4647 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4648 s390_disasm(ENC5(MNM, FPR, FPR, GPR, UINT), "rrdtr", r1, r3, r2, m4);
4649
4650 return emit_RRF4(p, 0xb3f70000, r3, m4, r1, r2);
4651 }
4652
4653
4654 static UChar *
s390_emit_RRXTR(UChar * p,UChar r3,UChar m4,UChar r1,UChar r2)4655 s390_emit_RRXTR(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
4656 {
4657 vassert(s390_host_has_dfp);
4658 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4659 s390_disasm(ENC5(MNM, FPR, FPR, GPR, UINT), "rrxtr", r1, r3, r2, m4);
4660
4661 return emit_RRF4(p, 0xb3ff0000, r3, m4, r1, r2);
4662 }
4663
4664
4665 static UChar *
s390_emit_SDTRA(UChar * p,UChar r3,UChar m4,UChar r1,UChar r2)4666 s390_emit_SDTRA(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
4667 {
4668 vassert(s390_host_has_dfp);
4669 vassert(m4 == 0 || s390_host_has_fpext);
4670 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
4671 if (m4 == 0)
4672 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "sdtr", r1, r2, r3);
4673 else
4674 s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "sdtra", r1, r2, r3, m4);
4675 }
4676
4677 return emit_RRF4(p, 0xb3d30000, r3, m4, r1, r2);
4678 }
4679
4680
4681 static UChar *
s390_emit_SXTRA(UChar * p,UChar r3,UChar m4,UChar r1,UChar r2)4682 s390_emit_SXTRA(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
4683 {
4684 vassert(s390_host_has_dfp);
4685 vassert(m4 == 0 || s390_host_has_fpext);
4686 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
4687 if (m4 == 0)
4688 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "sxtr", r1, r2, r3);
4689 else
4690 s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "sxtra", r1, r2, r3, m4);
4691 }
4692
4693 return emit_RRF4(p, 0xb3db0000, r3, m4, r1, r2);
4694 }
4695
4696
4697 static UChar *
s390_emit_SLDT(UChar * p,UChar r3,UChar r1,UChar r2)4698 s390_emit_SLDT(UChar *p, UChar r3, UChar r1, UChar r2)
4699 {
4700 vassert(s390_host_has_dfp);
4701 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4702 s390_disasm(ENC4(MNM, FPR, FPR, UDXB), "sldt", r1, r3, 0, 0, r2);
4703
4704 return emit_RXF(p, 0xED0000000040ULL, r3, 0, r2, 0, r1);
4705 }
4706
4707
4708 static UChar *
s390_emit_SLXT(UChar * p,UChar r3,UChar r1,UChar r2)4709 s390_emit_SLXT(UChar *p, UChar r3, UChar r1, UChar r2)
4710 {
4711 vassert(s390_host_has_dfp);
4712 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4713 s390_disasm(ENC4(MNM, FPR, FPR, UDXB), "slxt", r1, r3, 0, 0, r2);
4714
4715 return emit_RXF(p, 0xED0000000048ULL, r3, 0, r2, 0, r1);
4716 }
4717
4718
4719 static UChar *
s390_emit_SRDT(UChar * p,UChar r3,UChar r1,UChar r2)4720 s390_emit_SRDT(UChar *p, UChar r3, UChar r1, UChar r2)
4721 {
4722 vassert(s390_host_has_dfp);
4723 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4724 s390_disasm(ENC4(MNM, FPR, FPR, UDXB), "srdt", r1, r3, 0, 0, r2);
4725
4726 return emit_RXF(p, 0xED0000000041ULL, r3, 0, r2, 0, r1);
4727 }
4728
4729
4730 static UChar *
s390_emit_SRXT(UChar * p,UChar r3,UChar r1,UChar r2)4731 s390_emit_SRXT(UChar *p, UChar r3, UChar r1, UChar r2)
4732 {
4733 vassert(s390_host_has_dfp);
4734 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4735 s390_disasm(ENC4(MNM, FPR, FPR, UDXB), "srxt", r1, r3, 0, 0, r2);
4736
4737 return emit_RXF(p, 0xED0000000049ULL, r3, 0, r2, 0, r1);
4738 }
4739
4740
4741 static UChar *
s390_emit_LOCGR(UChar * p,UChar m3,UChar r1,UChar r2)4742 s390_emit_LOCGR(UChar *p, UChar m3, UChar r1, UChar r2)
4743 {
4744 vassert(s390_host_has_lsc);
4745 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4746 s390_disasm(ENC4(MNM, GPR, GPR, UINT), "locgr", r1, r2, m3);
4747
4748 return emit_RRF3(p, 0xb9e20000, m3, r1, r2);
4749 }
4750
4751
4752 static UChar *
s390_emit_LOC(UChar * p,UChar r1,UChar m3,UChar b2,UShort dl2,UChar dh2)4753 s390_emit_LOC(UChar *p, UChar r1, UChar m3, UChar b2, UShort dl2, UChar dh2)
4754 {
4755 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4756 s390_disasm(ENC4(MNM, GPR, UINT, SDXB), "loc", r1, m3, dh2, dl2, 0, b2);
4757
4758 return emit_RSY(p, 0xeb00000000f2ULL, r1, m3, b2, dl2, dh2);
4759 }
4760
4761
4762 static UChar *
s390_emit_LOCG(UChar * p,UChar r1,UChar m3,UChar b2,UShort dl2,UChar dh2)4763 s390_emit_LOCG(UChar *p, UChar r1, UChar m3, UChar b2, UShort dl2, UChar dh2)
4764 {
4765 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4766 s390_disasm(ENC4(MNM, GPR, UINT, SDXB), "locg", r1, m3, dh2, dl2, 0, b2);
4767
4768 return emit_RSY(p, 0xeb00000000e2ULL, r1, m3, b2, dl2, dh2);
4769 }
4770
4771
4772 /* Provide a symbolic name for register "R0" */
4773 #define R0 0
4774
4775 /* Split up a 20-bit displacement into its high and low piece
4776 suitable for passing as function arguments */
4777 #define DISP20(d) (((UInt)d) & 0xFFF), ((((UInt)d) >> 12) & 0xFF)
4778
4779 /*---------------------------------------------------------------*/
4780 /*--- Helper functions ---*/
4781 /*---------------------------------------------------------------*/
4782
4783 static __inline__ Bool
uint_fits_signed_16bit(UInt val)4784 uint_fits_signed_16bit(UInt val)
4785 {
4786 UInt v = val & 0xFFFFu;
4787
4788 /* sign extend */
4789 v = (Int)(v << 16) >> 16;
4790
4791 return val == v;
4792 }
4793
4794
4795 static __inline__ Bool
ulong_fits_signed_16bit(ULong val)4796 ulong_fits_signed_16bit(ULong val)
4797 {
4798 ULong v = val & 0xFFFFu;
4799
4800 /* sign extend */
4801 v = (Long)(v << 48) >> 48;
4802
4803 return val == v;
4804 }
4805
4806
4807 static __inline__ Bool
ulong_fits_signed_32bit(ULong val)4808 ulong_fits_signed_32bit(ULong val)
4809 {
4810 ULong v = val & 0xFFFFFFFFu;
4811
4812 /* sign extend */
4813 v = (Long)(v << 32) >> 32;
4814
4815 return val == v;
4816 }
4817
4818
4819 static __inline__ Bool
ulong_fits_unsigned_32bit(ULong val)4820 ulong_fits_unsigned_32bit(ULong val)
4821 {
4822 return (val & 0xFFFFFFFFu) == val;
4823 }
4824
4825
4826 /* Load a 64-bit immediate VAL into register REG. */
4827 static UChar *
s390_emit_load_64imm(UChar * p,UChar reg,ULong val)4828 s390_emit_load_64imm(UChar *p, UChar reg, ULong val)
4829 {
4830 if (ulong_fits_signed_16bit(val)) {
4831 return s390_emit_LGHI(p, reg, val);
4832 }
4833
4834 if (s390_host_has_eimm) {
4835 if (ulong_fits_unsigned_32bit(val)) {
4836 return s390_emit_LLILF(p, reg, val);
4837 }
4838 if (ulong_fits_signed_32bit(val)) {
4839 /* LGFI's sign extension will recreate the correct 64-bit value */
4840 return s390_emit_LGFI(p, reg, val);
4841 }
4842 /* Do it in two steps: upper half [0:31] and lower half [32:63] */
4843 p = s390_emit_IIHF(p, reg, val >> 32);
4844 return s390_emit_IILF(p, reg, val & 0xFFFFFFFF);
4845 }
4846
4847 /* Fall back */
4848 if (ulong_fits_unsigned_32bit(val)) {
4849 p = s390_emit_LLILH(p, reg, (val >> 16) & 0xFFFF); /* sets val[32:47]
4850 val[0:31] = 0 */
4851 p = s390_emit_IILL(p, reg, val & 0xFFFF); /* sets val[48:63] */
4852 return p;
4853 }
4854
4855 p = s390_emit_IIHH(p, reg, (val >> 48) & 0xFFFF);
4856 p = s390_emit_IIHL(p, reg, (val >> 32) & 0xFFFF);
4857 p = s390_emit_IILH(p, reg, (val >> 16) & 0xFFFF);
4858 p = s390_emit_IILL(p, reg, val & 0xFFFF);
4859
4860 return p;
4861 }
4862
4863 /* Load a 32-bit immediate VAL into register REG. */
4864 static UChar *
s390_emit_load_32imm(UChar * p,UChar reg,UInt val)4865 s390_emit_load_32imm(UChar *p, UChar reg, UInt val)
4866 {
4867 if (uint_fits_signed_16bit(val)) {
4868 /* LHI's sign extension will recreate the correct 32-bit value */
4869 return s390_emit_LHI(p, reg, val);
4870 }
4871 if (s390_host_has_eimm) {
4872 return s390_emit_IILF(p, reg, val);
4873 }
4874 /* val[0:15] --> (val >> 16) & 0xFFFF
4875 val[16:31] --> val & 0xFFFF */
4876 p = s390_emit_IILH(p, reg, (val >> 16) & 0xFFFF);
4877 return s390_emit_IILL(p, reg, val & 0xFFFF);
4878 }
4879
4880 /*------------------------------------------------------------*/
4881 /*--- Wrapper functions ---*/
4882 /*------------------------------------------------------------*/
4883
4884 /* r1[32:63],r1+1[32:63] = r1+1[32:63] * memory[op2addr][0:31] */
4885 static UChar *
s390_emit_MFYw(UChar * p,UChar r1,UChar x,UChar b,UShort dl,UChar dh)4886 s390_emit_MFYw(UChar *p, UChar r1, UChar x, UChar b, UShort dl, UChar dh)
4887 {
4888 if (s390_host_has_gie) {
4889 return s390_emit_MFY(p, r1, x, b, dl, dh);
4890 }
4891
4892 /* Load from memory into R0, then MULTIPLY with R1 */
4893 p = s390_emit_LY(p, R0, x, b, dl, dh);
4894 return s390_emit_MR(p, r1, R0);
4895 }
4896
4897 /* r1[32:63] = r1[32:63] * memory[op2addr][0:15] */
4898 static UChar *
s390_emit_MHYw(UChar * p,UChar r1,UChar x,UChar b,UShort dl,UChar dh)4899 s390_emit_MHYw(UChar *p, UChar r1, UChar x, UChar b, UShort dl, UChar dh)
4900 {
4901 if (s390_host_has_gie) {
4902 return s390_emit_MHY(p, r1, x, b, dl, dh);
4903 }
4904
4905 /* Load from memory into R0, then MULTIPLY with R1 */
4906 p = s390_emit_LHY(p, R0, x, b, dl, dh);
4907 return s390_emit_MSR(p, r1, R0);
4908 }
4909
4910 /* r1[32:63] = r1[32:63] * i2 */
4911 static UChar *
s390_emit_MSFIw(UChar * p,UChar r1,UInt i2)4912 s390_emit_MSFIw(UChar *p, UChar r1, UInt i2)
4913 {
4914 if (s390_host_has_gie) {
4915 return s390_emit_MSFI(p, r1, i2);
4916 }
4917
4918 /* Load I2 into R0; then MULTIPLY R0 with R1 */
4919 p = s390_emit_load_32imm(p, R0, i2);
4920 return s390_emit_MSR(p, r1, R0);
4921 }
4922
4923
4924 /* r1[32:63] = r1[32:63] & i2 */
4925 static UChar *
s390_emit_NILFw(UChar * p,UChar r1,UInt i2)4926 s390_emit_NILFw(UChar *p, UChar r1, UInt i2)
4927 {
4928 if (s390_host_has_eimm) {
4929 return s390_emit_NILF(p, r1, i2);
4930 }
4931
4932 /* Load I2 into R0; then AND R0 with R1 */
4933 p = s390_emit_load_32imm(p, R0, i2);
4934 return s390_emit_NR(p, r1, R0);
4935 }
4936
4937
4938 /* r1[32:63] = r1[32:63] | i2 */
4939 static UChar *
s390_emit_OILFw(UChar * p,UChar r1,UInt i2)4940 s390_emit_OILFw(UChar *p, UChar r1, UInt i2)
4941 {
4942 if (s390_host_has_eimm) {
4943 return s390_emit_OILF(p, r1, i2);
4944 }
4945
4946 /* Load I2 into R0; then AND R0 with R1 */
4947 p = s390_emit_load_32imm(p, R0, i2);
4948 return s390_emit_OR(p, r1, R0);
4949 }
4950
4951
4952 /* r1[32:63] = r1[32:63] ^ i2 */
4953 static UChar *
s390_emit_XILFw(UChar * p,UChar r1,UInt i2)4954 s390_emit_XILFw(UChar *p, UChar r1, UInt i2)
4955 {
4956 if (s390_host_has_eimm) {
4957 return s390_emit_XILF(p, r1, i2);
4958 }
4959
4960 /* Load I2 into R0; then AND R0 with R1 */
4961 p = s390_emit_load_32imm(p, R0, i2);
4962 return s390_emit_XR(p, r1, R0);
4963 }
4964
4965
4966 /* r1[32:63] = sign_extend(r2[56:63]) */
4967 static UChar *
s390_emit_LBRw(UChar * p,UChar r1,UChar r2)4968 s390_emit_LBRw(UChar *p, UChar r1, UChar r2)
4969 {
4970 if (s390_host_has_eimm) {
4971 return s390_emit_LBR(p, r1, r2);
4972 }
4973
4974 p = s390_emit_LR(p, r1, r2); /* r1 = r2 */
4975 p = s390_emit_SLL(p, r1, R0, 24); /* r1 = r1 << 24 */
4976 return s390_emit_SRA(p, r1, R0, 24); /* r1 = r1 >>a 24 */
4977 }
4978
4979
4980 /* r1[0:63] = sign_extend(r2[56:63]) */
4981 static UChar *
s390_emit_LGBRw(UChar * p,UChar r1,UChar r2)4982 s390_emit_LGBRw(UChar *p, UChar r1, UChar r2)
4983 {
4984 if (s390_host_has_eimm) {
4985 return s390_emit_LGBR(p, r1, r2);
4986 }
4987
4988 p = s390_emit_LR(p, r1, r2); /* r1 = r2 */
4989 p = s390_emit_SLLG(p, r1, r1, R0, DISP20(56)); /* r1 = r1 << 56 */
4990 return s390_emit_SRAG(p, r1, r1, R0, DISP20(56)); /* r1 = r1 >>a 56 */
4991 }
4992
4993
4994 /* r1[32:63] = sign_extend(r2[48:63]) */
4995 static UChar *
s390_emit_LHRw(UChar * p,UChar r1,UChar r2)4996 s390_emit_LHRw(UChar *p, UChar r1, UChar r2)
4997 {
4998 if (s390_host_has_eimm) {
4999 return s390_emit_LHR(p, r1, r2);
5000 }
5001
5002 p = s390_emit_LR(p, r1, r2); /* r1 = r2 */
5003 p = s390_emit_SLL(p, r1, R0, 16); /* r1 = r1 << 16 */
5004 return s390_emit_SRA(p, r1, R0, 16); /* r1 = r1 >>a 16 */
5005 }
5006
5007
5008 /* r1[0:63] = sign_extend(r2[48:63]) */
5009 static UChar *
s390_emit_LGHRw(UChar * p,UChar r1,UChar r2)5010 s390_emit_LGHRw(UChar *p, UChar r1, UChar r2)
5011 {
5012 if (s390_host_has_eimm) {
5013 return s390_emit_LGHR(p, r1, r2);
5014 }
5015
5016 p = s390_emit_LR(p, r1, r2); /* r1 = r2 */
5017 p = s390_emit_SLLG(p, r1, r1, R0, DISP20(48)); /* r1 = r1 << 48 */
5018 return s390_emit_SRAG(p, r1, r1, R0, DISP20(48)); /* r1 = r1 >>a 48 */
5019 }
5020
5021
5022 /* r1[0:63] = sign_extend(i2) */
5023 static UChar *
s390_emit_LGFIw(UChar * p,UChar r1,UInt i2)5024 s390_emit_LGFIw(UChar *p, UChar r1, UInt i2)
5025 {
5026 if (s390_host_has_eimm) {
5027 return s390_emit_LGFI(p, r1, i2);
5028 }
5029
5030 p = s390_emit_load_32imm(p, R0, i2);
5031 return s390_emit_LGFR(p, r1, R0);
5032 }
5033
5034
5035 /* r1[32:63] = zero_extend($r2[56:63]) */
5036 static UChar *
s390_emit_LLCRw(UChar * p,UChar r1,UChar r2)5037 s390_emit_LLCRw(UChar *p, UChar r1, UChar r2)
5038 {
5039 if (s390_host_has_eimm) {
5040 return s390_emit_LLCR(p, r1, r2);
5041 }
5042
5043 p = s390_emit_LR(p, r1, r2);
5044 p = s390_emit_LHI(p, R0, 0xFF);
5045 return s390_emit_NR(p, r1, R0);
5046 }
5047
5048
5049 /* r1[0:63] = zero_extend($r2[56:63]) */
5050 static UChar *
s390_emit_LLGCRw(UChar * p,UChar r1,UChar r2)5051 s390_emit_LLGCRw(UChar *p, UChar r1, UChar r2)
5052 {
5053 if (s390_host_has_eimm) {
5054 return s390_emit_LLGCR(p, r1, r2);
5055 }
5056
5057 p = s390_emit_LR(p, r1, r2);
5058 p = s390_emit_LLILL(p, R0, 0xFF);
5059 return s390_emit_NGR(p, r1, R0);
5060 }
5061
5062
5063 /* r1[32:63] = zero_extend(r2[48:63]) */
5064 static UChar *
s390_emit_LLHRw(UChar * p,UChar r1,UChar r2)5065 s390_emit_LLHRw(UChar *p, UChar r1, UChar r2)
5066 {
5067 if (s390_host_has_eimm) {
5068 return s390_emit_LLHR(p, r1, r2);
5069 }
5070
5071 p = s390_emit_LR(p, r1, r2);
5072 p = s390_emit_LLILL(p, R0, 0xFFFF);
5073 return s390_emit_NR(p, r1, R0);
5074 }
5075
5076
5077 /* r1[0:63] = zero_extend(r2[48:63]) */
5078 static UChar *
s390_emit_LLGHRw(UChar * p,UChar r1,UChar r2)5079 s390_emit_LLGHRw(UChar *p, UChar r1, UChar r2)
5080 {
5081 if (s390_host_has_eimm) {
5082 return s390_emit_LLGHR(p, r1, r2);
5083 }
5084
5085 p = s390_emit_LR(p, r1, r2);
5086 p = s390_emit_LLILL(p, R0, 0xFFFF);
5087 return s390_emit_NGR(p, r1, R0);
5088 }
5089
5090
5091 /* r1[32:63] = zero_extend(mem[op2addr][0:7]) */
5092 static UChar *
s390_emit_LLCw(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl,UChar dh)5093 s390_emit_LLCw(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl, UChar dh)
5094 {
5095 if (s390_host_has_eimm) {
5096 return s390_emit_LLC(p, r1, x2, b2, dl, dh);
5097 }
5098
5099 if (dh == 0) {
5100 p = s390_emit_IC(p, r1, x2, b2, dl);
5101 } else {
5102 p = s390_emit_ICY(p, r1, x2, b2, dl, dh);
5103 }
5104 p = s390_emit_LLILL(p, R0, 0xFF);
5105 return s390_emit_NR(p, r1, R0);
5106 }
5107
5108
5109 /* r1[32:63] = zero_extend(mem[op2addr][0:15]) */
5110 static UChar *
s390_emit_LLHw(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl,UChar dh)5111 s390_emit_LLHw(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl, UChar dh)
5112 {
5113 if (s390_host_has_eimm) {
5114 return s390_emit_LLH(p, r1, x2, b2, dl, dh);
5115 }
5116
5117 p = s390_emit_LLGH(p, r1, x2, b2, dl, dh);
5118 p = s390_emit_LLILL(p, R0, 0xFFFF);
5119 return s390_emit_NR(p, r1, R0);
5120 }
5121
5122
5123 /* r1[0:63] = zero_extend(i2) */
5124 static UChar *
s390_emit_LLILFw(UChar * p,UChar r1,UInt i2)5125 s390_emit_LLILFw(UChar *p, UChar r1, UInt i2)
5126 {
5127 if (s390_host_has_eimm) {
5128 return s390_emit_LLILF(p, r1, i2);
5129 }
5130
5131 p = s390_emit_LLILH(p, r1, (i2 >> 16) & 0xFFFF); /* i2[0:15] */
5132 return s390_emit_OILL(p, r1, i2 & 0xFFFF);
5133 }
5134
5135
5136 /* r1[32:63] = r1[32:63] + i2 */
5137 static UChar *
s390_emit_AFIw(UChar * p,UChar r1,UInt i2)5138 s390_emit_AFIw(UChar *p, UChar r1, UInt i2)
5139 {
5140 if (s390_host_has_eimm) {
5141 return s390_emit_AFI(p, r1, i2);
5142 }
5143 /* Load 32 bit immediate to R0 then add */
5144 p = s390_emit_load_32imm(p, R0, i2);
5145 return s390_emit_AR(p, r1, R0);
5146 }
5147
5148
5149 /* r1[32:63] = r1[32:63] - i2 */
5150 static UChar *
s390_emit_SLFIw(UChar * p,UChar r1,UInt i2)5151 s390_emit_SLFIw(UChar *p, UChar r1, UInt i2)
5152 {
5153 if (s390_host_has_eimm) {
5154 return s390_emit_SLFI(p, r1, i2);
5155 }
5156
5157 /* Load 32 bit immediate to R0 then subtract */
5158 p = s390_emit_load_32imm(p, R0, i2);
5159 return s390_emit_SR(p, r1, R0);
5160 }
5161
5162
5163 /* r1[0:63] = r1[0:63] - zero_extend(i2) */
5164 static UChar *
s390_emit_SLGFIw(UChar * p,UChar r1,UInt i2)5165 s390_emit_SLGFIw(UChar *p, UChar r1, UInt i2)
5166 {
5167 if (s390_host_has_eimm) {
5168 return s390_emit_SLGFI(p, r1, i2);
5169 }
5170
5171 /* Load zero-extended 32 bit immediate to R0 then subtract */
5172 p = s390_emit_load_64imm(p, R0, i2);
5173 return s390_emit_SGR(p, r1, R0);
5174 }
5175
5176
5177 static UChar *
s390_emit_LTw(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl,UChar dh)5178 s390_emit_LTw(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl, UChar dh)
5179 {
5180 if (s390_host_has_eimm) {
5181 return s390_emit_LT(p, r1, x2, b2, dl, dh);
5182 }
5183 /* Load 32 bit from memory to R0 then compare */
5184 if (dh == 0) {
5185 p = s390_emit_L(p, R0, x2, b2, dl);
5186 } else {
5187 p = s390_emit_LY(p, R0, x2, b2, dl, dh);
5188 }
5189 return s390_emit_LTR(p, r1, R0);
5190 }
5191
5192
5193 static UChar *
s390_emit_LTGw(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl,UChar dh)5194 s390_emit_LTGw(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl, UChar dh)
5195 {
5196 if (s390_host_has_eimm) {
5197 return s390_emit_LTG(p, r1, x2, b2, dl, dh);
5198 }
5199 /* Load 64 bit from memory to R0 then compare */
5200 p = s390_emit_LG(p, R0, x2, b2, dl, dh);
5201 return s390_emit_LTGR(p, r1, R0);
5202 }
5203
5204
5205 static UChar *
s390_emit_CFIw(UChar * p,UChar r1,UInt i2)5206 s390_emit_CFIw(UChar *p, UChar r1, UInt i2)
5207 {
5208 if (s390_host_has_eimm) {
5209 return s390_emit_CFI(p, r1, i2);
5210 }
5211 /* Load 32 bit immediate to R0 then compare */
5212 p = s390_emit_load_32imm(p, R0, i2);
5213 return s390_emit_CR(p, r1, R0);
5214 }
5215
5216
5217 static UChar *
s390_emit_CLFIw(UChar * p,UChar r1,UInt i2)5218 s390_emit_CLFIw(UChar *p, UChar r1, UInt i2)
5219 {
5220 if (s390_host_has_eimm) {
5221 return s390_emit_CLFI(p, r1, i2);
5222 }
5223 /* Load 32 bit immediate to R0 then compare */
5224 p = s390_emit_load_32imm(p, R0, i2);
5225 return s390_emit_CLR(p, r1, R0);
5226 }
5227
5228
5229 static UChar *
s390_emit_LGDRw(UChar * p,UChar r1,UChar r2)5230 s390_emit_LGDRw(UChar *p, UChar r1, UChar r2)
5231 {
5232 if (s390_host_has_fgx) {
5233 return s390_emit_LGDR(p, r1, r2);
5234 }
5235
5236 /* Store the FPR at memory[sp - 8]. This is safe because SP grows towards
5237 smaller addresses and is 8-byte aligned. Then load the GPR from that
5238 memory location/ */
5239 p = s390_emit_STDY(p, r2, R0, S390_REGNO_STACK_POINTER, DISP20(-8));
5240 return s390_emit_LG(p, r1, R0, S390_REGNO_STACK_POINTER, DISP20(-8));
5241 }
5242
5243
5244 static UChar *
s390_emit_LDGRw(UChar * p,UChar r1,UChar r2)5245 s390_emit_LDGRw(UChar *p, UChar r1, UChar r2)
5246 {
5247 if (s390_host_has_fgx) {
5248 return s390_emit_LDGR(p, r1, r2);
5249 }
5250
5251 /* Store the GPR at memory[sp - 8]. This is safe because SP grows towards
5252 smaller addresses and is 8-byte aligned. Then load the FPR from that
5253 memory location/ */
5254 p = s390_emit_STG(p, r2, R0, S390_REGNO_STACK_POINTER, DISP20(-8));
5255 return s390_emit_LDY(p, r1, R0, S390_REGNO_STACK_POINTER, DISP20(-8));
5256 }
5257
5258
5259 /*---------------------------------------------------------------*/
5260 /*--- Constructors for the various s390_insn kinds ---*/
5261 /*---------------------------------------------------------------*/
5262
5263 s390_insn *
s390_insn_load(UChar size,HReg dst,s390_amode * src)5264 s390_insn_load(UChar size, HReg dst, s390_amode *src)
5265 {
5266 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
5267
5268 insn->tag = S390_INSN_LOAD;
5269 insn->size = size;
5270 insn->variant.load.src = src;
5271 insn->variant.load.dst = dst;
5272
5273 vassert(size == 1 || size == 2 || size == 4 || size == 8);
5274
5275 return insn;
5276 }
5277
5278
5279 s390_insn *
s390_insn_store(UChar size,s390_amode * dst,HReg src)5280 s390_insn_store(UChar size, s390_amode *dst, HReg src)
5281 {
5282 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
5283
5284 insn->tag = S390_INSN_STORE;
5285 insn->size = size;
5286 insn->variant.store.src = src;
5287 insn->variant.store.dst = dst;
5288
5289 vassert(size == 1 || size == 2 || size == 4 || size == 8);
5290
5291 return insn;
5292 }
5293
5294
5295 s390_insn *
s390_insn_move(UChar size,HReg dst,HReg src)5296 s390_insn_move(UChar size, HReg dst, HReg src)
5297 {
5298 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
5299
5300 insn->tag = S390_INSN_MOVE;
5301 insn->size = size;
5302 insn->variant.move.src = src;
5303 insn->variant.move.dst = dst;
5304
5305 vassert(size == 1 || size == 2 || size == 4 || size == 8);
5306
5307 return insn;
5308 }
5309
5310
5311 s390_insn *
s390_insn_memcpy(UChar size,s390_amode * dst,s390_amode * src)5312 s390_insn_memcpy(UChar size, s390_amode *dst, s390_amode *src)
5313 {
5314 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
5315
5316 /* This insn will be mapped to MVC which requires base register
5317 plus 12-bit displacement */
5318 vassert(src->tag == S390_AMODE_B12);
5319 vassert(dst->tag == S390_AMODE_B12);
5320
5321 insn->tag = S390_INSN_MEMCPY;
5322 insn->size = size;
5323 insn->variant.memcpy.src = src;
5324 insn->variant.memcpy.dst = dst;
5325
5326 vassert(size == 1 || size == 2 || size == 4 || size == 8);
5327
5328 return insn;
5329 }
5330
5331
5332 s390_insn *
s390_insn_cond_move(UChar size,s390_cc_t cond,HReg dst,s390_opnd_RMI src)5333 s390_insn_cond_move(UChar size, s390_cc_t cond, HReg dst, s390_opnd_RMI src)
5334 {
5335 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
5336
5337 insn->tag = S390_INSN_COND_MOVE;
5338 insn->size = size;
5339 insn->variant.cond_move.cond = cond;
5340 insn->variant.cond_move.src = src;
5341 insn->variant.cond_move.dst = dst;
5342
5343 vassert(size == 1 || size == 2 || size == 4 || size == 8);
5344
5345 return insn;
5346 }
5347
5348
5349 s390_insn *
s390_insn_load_immediate(UChar size,HReg dst,ULong value)5350 s390_insn_load_immediate(UChar size, HReg dst, ULong value)
5351 {
5352 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
5353
5354 insn->tag = S390_INSN_LOAD_IMMEDIATE;
5355 insn->size = size;
5356 insn->variant.load_immediate.dst = dst;
5357 insn->variant.load_immediate.value = value;
5358
5359 return insn;
5360 }
5361
5362
5363 s390_insn *
s390_insn_alu(UChar size,s390_alu_t tag,HReg dst,s390_opnd_RMI op2)5364 s390_insn_alu(UChar size, s390_alu_t tag, HReg dst, s390_opnd_RMI op2)
5365 {
5366 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
5367
5368 insn->tag = S390_INSN_ALU;
5369 insn->size = size;
5370 insn->variant.alu.tag = tag;
5371 insn->variant.alu.dst = dst;
5372 insn->variant.alu.op2 = op2;
5373
5374 return insn;
5375 }
5376
5377
5378 s390_insn *
s390_insn_mul(UChar size,HReg dst_hi,HReg dst_lo,s390_opnd_RMI op2,Bool signed_multiply)5379 s390_insn_mul(UChar size, HReg dst_hi, HReg dst_lo, s390_opnd_RMI op2,
5380 Bool signed_multiply)
5381 {
5382 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
5383
5384 vassert(! hregIsVirtual(dst_hi));
5385 vassert(! hregIsVirtual(dst_lo));
5386
5387 insn->tag = signed_multiply ? S390_INSN_SMUL : S390_INSN_UMUL;
5388 insn->size = size;
5389 insn->variant.mul.dst_hi = dst_hi;
5390 insn->variant.mul.dst_lo = dst_lo;
5391 insn->variant.mul.op2 = op2;
5392
5393 return insn;
5394 }
5395
5396
5397 s390_insn *
s390_insn_div(UChar size,HReg op1_hi,HReg op1_lo,s390_opnd_RMI op2,Bool signed_divide)5398 s390_insn_div(UChar size, HReg op1_hi, HReg op1_lo, s390_opnd_RMI op2,
5399 Bool signed_divide)
5400 {
5401 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
5402
5403 vassert(size == 4 || size == 8);
5404 vassert(! hregIsVirtual(op1_hi));
5405 vassert(! hregIsVirtual(op1_lo));
5406
5407 insn->tag = signed_divide ? S390_INSN_SDIV : S390_INSN_UDIV;
5408 insn->size = size;
5409 insn->variant.div.op1_hi = op1_hi;
5410 insn->variant.div.op1_lo = op1_lo;
5411 insn->variant.div.op2 = op2;
5412
5413 return insn;
5414 }
5415
5416
5417 s390_insn *
s390_insn_divs(UChar size,HReg rem,HReg op1,s390_opnd_RMI op2)5418 s390_insn_divs(UChar size, HReg rem, HReg op1, s390_opnd_RMI op2)
5419 {
5420 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
5421
5422 vassert(size == 8);
5423 vassert(! hregIsVirtual(op1));
5424 vassert(! hregIsVirtual(rem));
5425
5426 insn->tag = S390_INSN_DIVS;
5427 insn->size = size;
5428 insn->variant.divs.rem = rem; /* remainder */
5429 insn->variant.divs.op1 = op1; /* also quotient */
5430 insn->variant.divs.op2 = op2;
5431
5432 return insn;
5433 }
5434
5435
5436 s390_insn *
s390_insn_clz(UChar size,HReg num_bits,HReg clobber,s390_opnd_RMI src)5437 s390_insn_clz(UChar size, HReg num_bits, HReg clobber, s390_opnd_RMI src)
5438 {
5439 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
5440
5441 vassert(size == 8);
5442 vassert(! hregIsVirtual(num_bits));
5443 vassert(! hregIsVirtual(clobber));
5444
5445 insn->tag = S390_INSN_CLZ;
5446 insn->size = size;
5447 insn->variant.clz.num_bits = num_bits;
5448 insn->variant.clz.clobber = clobber;
5449 insn->variant.clz.src = src;
5450
5451 return insn;
5452 }
5453
5454
5455 s390_insn *
s390_insn_unop(UChar size,s390_unop_t tag,HReg dst,s390_opnd_RMI opnd)5456 s390_insn_unop(UChar size, s390_unop_t tag, HReg dst, s390_opnd_RMI opnd)
5457 {
5458 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
5459
5460 insn->tag = S390_INSN_UNOP;
5461 insn->size = size;
5462 insn->variant.unop.tag = tag;
5463 insn->variant.unop.dst = dst;
5464 insn->variant.unop.src = opnd;
5465
5466 return insn;
5467 }
5468
5469
5470 s390_insn *
s390_insn_test(UChar size,s390_opnd_RMI src)5471 s390_insn_test(UChar size, s390_opnd_RMI src)
5472 {
5473 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
5474
5475 vassert(size == 4 || size == 8);
5476
5477 insn->tag = S390_INSN_TEST;
5478 insn->size = size;
5479 insn->variant.test.src = src;
5480
5481 return insn;
5482 }
5483
5484
5485 s390_insn *
s390_insn_cc2bool(HReg dst,s390_cc_t cond)5486 s390_insn_cc2bool(HReg dst, s390_cc_t cond)
5487 {
5488 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
5489
5490 insn->tag = S390_INSN_CC2BOOL;
5491 insn->size = 0; /* does not matter */
5492 insn->variant.cc2bool.cond = cond;
5493 insn->variant.cc2bool.dst = dst;
5494
5495 return insn;
5496 }
5497
5498
5499 s390_insn *
s390_insn_cas(UChar size,HReg op1,s390_amode * op2,HReg op3,HReg old_mem)5500 s390_insn_cas(UChar size, HReg op1, s390_amode *op2, HReg op3, HReg old_mem)
5501 {
5502 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
5503
5504 vassert(size == 4 || size == 8);
5505 vassert(hregNumber(op2->x) == 0);
5506 vassert(op2->tag == S390_AMODE_B12 || op2->tag == S390_AMODE_B20);
5507
5508 insn->tag = S390_INSN_CAS;
5509 insn->size = size;
5510 insn->variant.cas.op1 = op1;
5511 insn->variant.cas.op2 = op2;
5512 insn->variant.cas.op3 = op3;
5513 insn->variant.cas.old_mem = old_mem;
5514
5515 return insn;
5516 }
5517
5518
5519 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)5520 s390_insn_cdas(UChar size, HReg op1_high, HReg op1_low, s390_amode *op2,
5521 HReg op3_high, HReg op3_low, HReg old_mem_high, HReg old_mem_low,
5522 HReg scratch)
5523 {
5524 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
5525 s390_cdas *cdas = LibVEX_Alloc_inline(sizeof(s390_cdas));
5526
5527 vassert(size == 4 || size == 8);
5528 vassert(hregNumber(op2->x) == 0);
5529 vassert(hregNumber(scratch) == 1); /* r0,r1 used as scratch reg pair */
5530 vassert(op2->tag == S390_AMODE_B12 || op2->tag == S390_AMODE_B20);
5531
5532 insn->tag = S390_INSN_CDAS;
5533 insn->size = size;
5534 insn->variant.cdas.details = cdas;
5535
5536 cdas->op1_high = op1_high;
5537 cdas->op1_low = op1_low;
5538 cdas->op2 = op2;
5539 cdas->op3_high = op3_high;
5540 cdas->op3_low = op3_low;
5541 cdas->old_mem_high = old_mem_high;
5542 cdas->old_mem_low = old_mem_low;
5543 cdas->scratch = scratch;
5544
5545 return insn;
5546 }
5547
5548
5549 s390_insn *
s390_insn_compare(UChar size,HReg src1,s390_opnd_RMI src2,Bool signed_comparison)5550 s390_insn_compare(UChar size, HReg src1, s390_opnd_RMI src2,
5551 Bool signed_comparison)
5552 {
5553 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
5554
5555 vassert(size == 4 || size == 8);
5556
5557 insn->tag = S390_INSN_COMPARE;
5558 insn->size = size;
5559 insn->variant.compare.src1 = src1;
5560 insn->variant.compare.src2 = src2;
5561 insn->variant.compare.signed_comparison = signed_comparison;
5562
5563 return insn;
5564 }
5565
5566
5567 s390_insn *
s390_insn_helper_call(s390_cc_t cond,Addr64 target,UInt num_args,const HChar * name,RetLoc rloc)5568 s390_insn_helper_call(s390_cc_t cond, Addr64 target, UInt num_args,
5569 const HChar *name, RetLoc rloc)
5570 {
5571 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
5572 s390_helper_call *helper_call = LibVEX_Alloc_inline(sizeof(s390_helper_call));
5573
5574 insn->tag = S390_INSN_HELPER_CALL;
5575 insn->size = 0; /* does not matter */
5576 insn->variant.helper_call.details = helper_call;
5577
5578 helper_call->cond = cond;
5579 helper_call->target = target;
5580 helper_call->num_args = num_args;
5581 helper_call->name = name;
5582 helper_call->rloc = rloc;
5583
5584 vassert(is_sane_RetLoc(rloc));
5585
5586 return insn;
5587 }
5588
5589
5590 s390_insn *
s390_insn_bfp_triop(UChar size,s390_bfp_triop_t tag,HReg dst,HReg op2,HReg op3)5591 s390_insn_bfp_triop(UChar size, s390_bfp_triop_t tag, HReg dst, HReg op2,
5592 HReg op3)
5593 {
5594 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
5595
5596 vassert(size == 4 || size == 8);
5597
5598 insn->tag = S390_INSN_BFP_TRIOP;
5599 insn->size = size;
5600 insn->variant.bfp_triop.tag = tag;
5601 insn->variant.bfp_triop.dst = dst;
5602 insn->variant.bfp_triop.op2 = op2;
5603 insn->variant.bfp_triop.op3 = op3;
5604
5605 return insn;
5606 }
5607
5608
5609 s390_insn *
s390_insn_bfp_binop(UChar size,s390_bfp_binop_t tag,HReg dst,HReg op2)5610 s390_insn_bfp_binop(UChar size, s390_bfp_binop_t tag, HReg dst, HReg op2)
5611 {
5612 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
5613
5614 vassert(size == 4 || size == 8);
5615
5616 insn->tag = S390_INSN_BFP_BINOP;
5617 insn->size = size;
5618 insn->variant.bfp_binop.tag = tag;
5619 insn->variant.bfp_binop.dst_hi = dst;
5620 insn->variant.bfp_binop.op2_hi = op2;
5621 insn->variant.bfp_binop.dst_lo = INVALID_HREG;
5622 insn->variant.bfp_binop.op2_lo = INVALID_HREG;
5623
5624 return insn;
5625 }
5626
5627
5628 s390_insn *
s390_insn_bfp_unop(UChar size,s390_bfp_unop_t tag,HReg dst,HReg op)5629 s390_insn_bfp_unop(UChar size, s390_bfp_unop_t tag, HReg dst, HReg op)
5630 {
5631 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
5632
5633 vassert(size == 4 || size == 8);
5634
5635 insn->tag = S390_INSN_BFP_UNOP;
5636 insn->size = size;
5637 insn->variant.bfp_unop.tag = tag;
5638 insn->variant.bfp_unop.dst_hi = dst;
5639 insn->variant.bfp_unop.op_hi = op;
5640 insn->variant.bfp_unop.dst_lo = INVALID_HREG;
5641 insn->variant.bfp_unop.op_lo = INVALID_HREG;
5642
5643 return insn;
5644 }
5645
5646
5647 s390_insn *
s390_insn_bfp_compare(UChar size,HReg dst,HReg op1,HReg op2)5648 s390_insn_bfp_compare(UChar size, HReg dst, HReg op1, HReg op2)
5649 {
5650 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
5651
5652 vassert(size == 4 || size == 8);
5653
5654 insn->tag = S390_INSN_BFP_COMPARE;
5655 insn->size = size;
5656 insn->variant.bfp_compare.dst = dst;
5657 insn->variant.bfp_compare.op1_hi = op1;
5658 insn->variant.bfp_compare.op2_hi = op2;
5659 insn->variant.bfp_compare.op1_lo = INVALID_HREG;
5660 insn->variant.bfp_compare.op2_lo = INVALID_HREG;
5661
5662 return insn;
5663 }
5664
5665
5666 s390_insn *
s390_insn_bfp_convert(UChar size,s390_bfp_conv_t tag,HReg dst,HReg op,s390_bfp_round_t rounding_mode)5667 s390_insn_bfp_convert(UChar size, s390_bfp_conv_t tag, HReg dst, HReg op,
5668 s390_bfp_round_t rounding_mode)
5669 {
5670 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
5671
5672 vassert(size == 4 || size == 8);
5673
5674 insn->tag = S390_INSN_BFP_CONVERT;
5675 insn->size = size;
5676 insn->variant.bfp_convert.tag = tag;
5677 insn->variant.bfp_convert.dst_hi = dst;
5678 insn->variant.bfp_convert.op_hi = op;
5679 insn->variant.bfp_convert.dst_lo = INVALID_HREG;
5680 insn->variant.bfp_convert.op_lo = INVALID_HREG;
5681 insn->variant.bfp_convert.rounding_mode = rounding_mode;
5682
5683 return insn;
5684 }
5685
5686
5687 /* Check validity of a register pair for 128-bit FP. Valid register
5688 pairs are (0,2), (1,3), (4, 6), (5, 7), (8, 10), (9, 11), (12, 14),
5689 and (13, 15). */
5690 static Bool
is_valid_fp128_regpair(HReg hi,HReg lo)5691 is_valid_fp128_regpair(HReg hi, HReg lo)
5692 {
5693 UInt hi_regno = hregNumber(hi);
5694 UInt lo_regno = hregNumber(lo);
5695
5696 if (lo_regno != hi_regno + 2) return False;
5697 if ((hi_regno & 0x2) != 0) return False;
5698
5699 return True;
5700 }
5701
5702 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)5703 s390_insn_bfp128_binop(UChar size, s390_bfp_binop_t tag, HReg dst_hi,
5704 HReg dst_lo, HReg op2_hi, HReg op2_lo)
5705 {
5706 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
5707
5708 vassert(size == 16);
5709 vassert(is_valid_fp128_regpair(dst_hi, dst_lo));
5710 vassert(is_valid_fp128_regpair(op2_hi, op2_lo));
5711
5712 insn->tag = S390_INSN_BFP_BINOP;
5713 insn->size = size;
5714 insn->variant.bfp_binop.tag = tag;
5715 insn->variant.bfp_binop.dst_hi = dst_hi;
5716 insn->variant.bfp_binop.dst_lo = dst_lo;
5717 insn->variant.bfp_binop.op2_hi = op2_hi;
5718 insn->variant.bfp_binop.op2_lo = op2_lo;
5719
5720 return insn;
5721 }
5722
5723
5724 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)5725 s390_insn_bfp128_unop(UChar size, s390_bfp_unop_t tag, HReg dst_hi,
5726 HReg dst_lo, HReg op_hi, HReg op_lo)
5727 {
5728 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
5729
5730 vassert(size == 16);
5731 vassert(is_valid_fp128_regpair(dst_hi, dst_lo));
5732 vassert(is_valid_fp128_regpair(op_hi, op_lo));
5733
5734 insn->tag = S390_INSN_BFP_UNOP;
5735 insn->size = size;
5736 insn->variant.bfp_unop.tag = tag;
5737 insn->variant.bfp_unop.dst_hi = dst_hi;
5738 insn->variant.bfp_unop.dst_lo = dst_lo;
5739 insn->variant.bfp_unop.op_hi = op_hi;
5740 insn->variant.bfp_unop.op_lo = op_lo;
5741
5742 return insn;
5743 }
5744
5745
5746 s390_insn *
s390_insn_bfp128_compare(UChar size,HReg dst,HReg op1_hi,HReg op1_lo,HReg op2_hi,HReg op2_lo)5747 s390_insn_bfp128_compare(UChar size, HReg dst, HReg op1_hi, HReg op1_lo,
5748 HReg op2_hi, HReg op2_lo)
5749 {
5750 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
5751
5752 vassert(size == 16);
5753 vassert(is_valid_fp128_regpair(op1_hi, op1_lo));
5754 vassert(is_valid_fp128_regpair(op2_hi, op2_lo));
5755
5756 insn->tag = S390_INSN_BFP_COMPARE;
5757 insn->size = size;
5758 insn->variant.bfp_compare.dst = dst;
5759 insn->variant.bfp_compare.op1_hi = op1_hi;
5760 insn->variant.bfp_compare.op1_lo = op1_lo;
5761 insn->variant.bfp_compare.op2_hi = op2_hi;
5762 insn->variant.bfp_compare.op2_lo = op2_lo;
5763
5764 return insn;
5765 }
5766
5767
5768 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)5769 s390_insn_bfp128_convert(UChar size, s390_bfp_conv_t tag, HReg dst_hi,
5770 HReg dst_lo, HReg op_hi, HReg op_lo,
5771 s390_bfp_round_t rounding_mode)
5772 {
5773 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
5774
5775 if (size == 16) {
5776 /* From smaller or equal size to 16 bytes */
5777 vassert(is_valid_fp128_regpair(dst_hi, dst_lo));
5778 vassert(hregIsInvalid(op_lo)
5779 || is_valid_fp128_regpair(op_hi, op_lo));
5780 } else {
5781 /* From 16 bytes to smaller size */
5782 vassert(is_valid_fp128_regpair(op_hi, op_lo));
5783 }
5784
5785 insn->tag = S390_INSN_BFP_CONVERT;
5786 insn->size = size;
5787 insn->variant.bfp_convert.tag = tag;
5788 insn->variant.bfp_convert.dst_hi = dst_hi;
5789 insn->variant.bfp_convert.dst_lo = dst_lo;
5790 insn->variant.bfp_convert.op_hi = op_hi;
5791 insn->variant.bfp_convert.op_lo = op_lo;
5792 insn->variant.bfp_convert.rounding_mode = rounding_mode;
5793
5794 return insn;
5795 }
5796
5797
5798 s390_insn *
s390_insn_bfp128_convert_to(UChar size,s390_bfp_conv_t tag,HReg dst_hi,HReg dst_lo,HReg op)5799 s390_insn_bfp128_convert_to(UChar size, s390_bfp_conv_t tag, HReg dst_hi,
5800 HReg dst_lo, HReg op)
5801 {
5802 /* Conversion to bfp128 never requires a rounding mode. Provide default
5803 rounding mode. It will not be used when emitting insns. */
5804 s390_bfp_round_t rounding_mode = S390_BFP_ROUND_NEAREST_EVEN;
5805
5806 return s390_insn_bfp128_convert(size, tag, dst_hi, dst_lo, op,
5807 INVALID_HREG, rounding_mode);
5808 }
5809
5810
5811 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)5812 s390_insn_bfp128_convert_from(UChar size, s390_bfp_conv_t tag, HReg dst_hi,
5813 HReg dst_lo, HReg op_hi, HReg op_lo,
5814 s390_bfp_round_t rounding_mode)
5815 {
5816 return s390_insn_bfp128_convert(size, tag, dst_hi, dst_lo, op_hi, op_lo,
5817 rounding_mode);
5818 }
5819
5820
5821 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)5822 s390_insn_dfp_binop(UChar size, s390_dfp_binop_t tag, HReg dst, HReg op2,
5823 HReg op3, s390_dfp_round_t rounding_mode)
5824 {
5825 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
5826 s390_dfp_binop *dfp_binop = LibVEX_Alloc_inline(sizeof(s390_dfp_binop));
5827
5828 vassert(size == 8);
5829
5830 insn->tag = S390_INSN_DFP_BINOP;
5831 insn->size = size;
5832 insn->variant.dfp_binop.details = dfp_binop;
5833
5834 dfp_binop->tag = tag;
5835 dfp_binop->dst_hi = dst;
5836 dfp_binop->op2_hi = op2;
5837 dfp_binop->op3_hi = op3;
5838 dfp_binop->dst_lo = INVALID_HREG;
5839 dfp_binop->op2_lo = INVALID_HREG;
5840 dfp_binop->op3_lo = INVALID_HREG;
5841 dfp_binop->rounding_mode = rounding_mode;
5842
5843 return insn;
5844 }
5845
5846
5847 s390_insn *
s390_insn_dfp_unop(UChar size,s390_dfp_unop_t tag,HReg dst,HReg op)5848 s390_insn_dfp_unop(UChar size, s390_dfp_unop_t tag, HReg dst, HReg op)
5849 {
5850 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
5851
5852 vassert(size == 8);
5853
5854 insn->tag = S390_INSN_DFP_UNOP;
5855 insn->size = size;
5856 insn->variant.dfp_unop.tag = tag;
5857 insn->variant.dfp_unop.dst_hi = dst;
5858 insn->variant.dfp_unop.op_hi = op;
5859 insn->variant.dfp_unop.dst_lo = INVALID_HREG;
5860 insn->variant.dfp_unop.op_lo = INVALID_HREG;
5861
5862 return insn;
5863 }
5864
5865
5866 s390_insn *
s390_insn_dfp_intop(UChar size,s390_dfp_intop_t tag,HReg dst,HReg op2,HReg op3)5867 s390_insn_dfp_intop(UChar size, s390_dfp_intop_t tag, HReg dst, HReg op2,
5868 HReg op3)
5869 {
5870 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
5871
5872 vassert(size == 8);
5873
5874 insn->tag = S390_INSN_DFP_INTOP;
5875 insn->size = size;
5876 insn->variant.dfp_intop.tag = tag;
5877 insn->variant.dfp_intop.dst_hi = dst;
5878 insn->variant.dfp_intop.op2 = op2;
5879 insn->variant.dfp_intop.op3_hi = op3;
5880 insn->variant.dfp_intop.dst_lo = INVALID_HREG;
5881 insn->variant.dfp_intop.op3_lo = INVALID_HREG;
5882
5883 return insn;
5884 }
5885
5886
5887 s390_insn *
s390_insn_dfp_compare(UChar size,s390_dfp_cmp_t tag,HReg dst,HReg op1,HReg op2)5888 s390_insn_dfp_compare(UChar size, s390_dfp_cmp_t tag, HReg dst,
5889 HReg op1, HReg op2)
5890 {
5891 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
5892
5893 vassert(size == 8);
5894
5895 insn->tag = S390_INSN_DFP_COMPARE;
5896 insn->size = size;
5897 insn->variant.dfp_compare.tag = tag;
5898 insn->variant.dfp_compare.dst = dst;
5899 insn->variant.dfp_compare.op1_hi = op1;
5900 insn->variant.dfp_compare.op2_hi = op2;
5901 insn->variant.dfp_compare.op1_lo = INVALID_HREG;
5902 insn->variant.dfp_compare.op2_lo = INVALID_HREG;
5903
5904 return insn;
5905 }
5906
5907
5908 s390_insn *
s390_insn_dfp_convert(UChar size,s390_dfp_conv_t tag,HReg dst,HReg op,s390_dfp_round_t rounding_mode)5909 s390_insn_dfp_convert(UChar size, s390_dfp_conv_t tag, HReg dst, HReg op,
5910 s390_dfp_round_t rounding_mode)
5911 {
5912 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
5913
5914 vassert(size == 4 || size == 8);
5915
5916 insn->tag = S390_INSN_DFP_CONVERT;
5917 insn->size = size;
5918 insn->variant.dfp_convert.tag = tag;
5919 insn->variant.dfp_convert.dst_hi = dst;
5920 insn->variant.dfp_convert.op_hi = op;
5921 insn->variant.dfp_convert.dst_lo = INVALID_HREG;
5922 insn->variant.dfp_convert.op_lo = INVALID_HREG;
5923 insn->variant.dfp_convert.rounding_mode = rounding_mode;
5924
5925 return insn;
5926 }
5927
5928
5929 s390_insn *
s390_insn_dfp_reround(UChar size,HReg dst,HReg op2,HReg op3,s390_dfp_round_t rounding_mode)5930 s390_insn_dfp_reround(UChar size, HReg dst, HReg op2, HReg op3,
5931 s390_dfp_round_t rounding_mode)
5932 {
5933 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
5934
5935 vassert(size == 8);
5936
5937 insn->tag = S390_INSN_DFP_REROUND;
5938 insn->size = size;
5939 insn->variant.dfp_reround.dst_hi = dst;
5940 insn->variant.dfp_reround.op2 = op2;
5941 insn->variant.dfp_reround.op3_hi = op3;
5942 insn->variant.dfp_reround.dst_lo = INVALID_HREG;
5943 insn->variant.dfp_reround.op3_lo = INVALID_HREG;
5944 insn->variant.dfp_reround.rounding_mode = rounding_mode;
5945
5946 return insn;
5947 }
5948
5949
5950 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)5951 s390_insn_fp_convert(UChar size, s390_fp_conv_t tag, HReg dst, HReg op,
5952 HReg r1, s390_dfp_round_t rounding_mode)
5953 {
5954 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
5955 s390_fp_convert *fp_convert = LibVEX_Alloc_inline(sizeof(s390_fp_convert));
5956
5957 vassert(size == 4 || size == 8);
5958
5959 insn->tag = S390_INSN_FP_CONVERT;
5960 insn->size = size;
5961 insn->variant.fp_convert.details = fp_convert;
5962
5963 fp_convert->tag = tag;
5964 fp_convert->dst_hi = dst;
5965 fp_convert->op_hi = op;
5966 fp_convert->r1 = r1;
5967 fp_convert->dst_lo = INVALID_HREG;
5968 fp_convert->op_lo = INVALID_HREG;
5969 fp_convert->rounding_mode = rounding_mode;
5970
5971 return insn;
5972 }
5973
5974
5975 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)5976 s390_insn_fp128_convert(UChar size, s390_fp_conv_t tag, HReg dst_hi,
5977 HReg dst_lo, HReg op_hi, HReg op_lo, HReg r1,
5978 s390_dfp_round_t rounding_mode)
5979 {
5980 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
5981 s390_fp_convert *fp_convert = LibVEX_Alloc_inline(sizeof(s390_fp_convert));
5982
5983 vassert(size == 16);
5984
5985 insn->tag = S390_INSN_FP_CONVERT;
5986 insn->size = size;
5987 insn->variant.fp_convert.details = fp_convert;
5988
5989 fp_convert->tag = tag;
5990 fp_convert->dst_hi = dst_hi;
5991 fp_convert->dst_lo = dst_lo;
5992 fp_convert->op_hi = op_hi;
5993 fp_convert->r1 = r1;
5994 fp_convert->op_lo = op_lo;
5995 fp_convert->rounding_mode = rounding_mode;
5996
5997 return insn;
5998 }
5999
6000
6001 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)6002 s390_insn_dfp128_binop(UChar size, s390_dfp_binop_t tag, HReg dst_hi,
6003 HReg dst_lo, HReg op2_hi, HReg op2_lo, HReg op3_hi,
6004 HReg op3_lo, s390_dfp_round_t rounding_mode)
6005 {
6006 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
6007 s390_dfp_binop *dfp_binop = LibVEX_Alloc_inline(sizeof(s390_dfp_binop));
6008
6009 vassert(size == 16);
6010 vassert(is_valid_fp128_regpair(dst_hi, dst_lo));
6011 vassert(is_valid_fp128_regpair(op2_hi, op2_lo));
6012 vassert(is_valid_fp128_regpair(op3_hi, op3_lo));
6013
6014 insn->tag = S390_INSN_DFP_BINOP;
6015 insn->size = size;
6016 insn->variant.dfp_binop.details = dfp_binop;
6017
6018 dfp_binop->tag = tag;
6019 dfp_binop->dst_hi = dst_hi;
6020 dfp_binop->dst_lo = dst_lo;
6021 dfp_binop->op2_hi = op2_hi;
6022 dfp_binop->op2_lo = op2_lo;
6023 dfp_binop->op3_hi = op3_hi;
6024 dfp_binop->op3_lo = op3_lo;
6025 dfp_binop->rounding_mode = rounding_mode;
6026
6027 return insn;
6028 }
6029
6030
6031 s390_insn *
s390_insn_dfp128_unop(UChar size,s390_dfp_unop_t tag,HReg dst,HReg op_hi,HReg op_lo)6032 s390_insn_dfp128_unop(UChar size, s390_dfp_unop_t tag, HReg dst,
6033 HReg op_hi, HReg op_lo)
6034 {
6035 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
6036
6037 /* destination is an 8 byte integer value */
6038 vassert(size == 8);
6039 vassert(is_valid_fp128_regpair(op_hi, op_lo));
6040
6041 insn->tag = S390_INSN_DFP_UNOP;
6042 insn->size = size;
6043 insn->variant.dfp_unop.tag = tag;
6044 insn->variant.dfp_unop.dst_hi = dst;
6045 insn->variant.dfp_unop.dst_lo = INVALID_HREG;
6046 insn->variant.dfp_unop.op_hi = op_hi;
6047 insn->variant.dfp_unop.op_lo = op_lo;
6048
6049 return insn;
6050 }
6051
6052
6053 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)6054 s390_insn_dfp128_intop(UChar size, s390_dfp_intop_t tag, HReg dst_hi,
6055 HReg dst_lo, HReg op2, HReg op3_hi, HReg op3_lo)
6056 {
6057 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
6058
6059 vassert(size == 16);
6060 vassert(is_valid_fp128_regpair(dst_hi, dst_lo));
6061 vassert(is_valid_fp128_regpair(op3_hi, op3_lo));
6062
6063 insn->tag = S390_INSN_DFP_INTOP;
6064 insn->size = size;
6065 insn->variant.dfp_intop.tag = tag;
6066 insn->variant.dfp_intop.dst_hi = dst_hi;
6067 insn->variant.dfp_intop.dst_lo = dst_lo;
6068 insn->variant.dfp_intop.op2 = op2;
6069 insn->variant.dfp_intop.op3_hi = op3_hi;
6070 insn->variant.dfp_intop.op3_lo = op3_lo;
6071
6072 return insn;
6073 }
6074
6075
6076 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)6077 s390_insn_dfp128_compare(UChar size, s390_dfp_cmp_t tag, HReg dst, HReg op1_hi,
6078 HReg op1_lo, HReg op2_hi, HReg op2_lo)
6079 {
6080 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
6081
6082 vassert(size == 16);
6083 vassert(is_valid_fp128_regpair(op1_hi, op1_lo));
6084 vassert(is_valid_fp128_regpair(op2_hi, op2_lo));
6085
6086 insn->tag = S390_INSN_DFP_COMPARE;
6087 insn->size = size;
6088 insn->variant.dfp_compare.tag = tag;
6089 insn->variant.dfp_compare.dst = dst;
6090 insn->variant.dfp_compare.op1_hi = op1_hi;
6091 insn->variant.dfp_compare.op1_lo = op1_lo;
6092 insn->variant.dfp_compare.op2_hi = op2_hi;
6093 insn->variant.dfp_compare.op2_lo = op2_lo;
6094
6095 return insn;
6096 }
6097
6098
6099 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)6100 s390_insn_dfp128_convert(UChar size, s390_dfp_conv_t tag, HReg dst_hi,
6101 HReg dst_lo, HReg op_hi, HReg op_lo,
6102 s390_dfp_round_t rounding_mode)
6103 {
6104 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
6105
6106 if (size == 16) {
6107 /* From smaller size to 16 bytes */
6108 vassert(is_valid_fp128_regpair(dst_hi, dst_lo));
6109 vassert(hregIsInvalid(op_lo));
6110 } else {
6111 /* From 16 bytes to smaller size */
6112 vassert(is_valid_fp128_regpair(op_hi, op_lo));
6113 }
6114
6115 insn->tag = S390_INSN_DFP_CONVERT;
6116 insn->size = size;
6117 insn->variant.dfp_convert.tag = tag;
6118 insn->variant.dfp_convert.dst_hi = dst_hi;
6119 insn->variant.dfp_convert.dst_lo = dst_lo;
6120 insn->variant.dfp_convert.op_hi = op_hi;
6121 insn->variant.dfp_convert.op_lo = op_lo;
6122 insn->variant.dfp_convert.rounding_mode = rounding_mode;
6123
6124 return insn;
6125 }
6126
6127
6128 s390_insn *
s390_insn_dfp128_convert_to(UChar size,s390_dfp_conv_t tag,HReg dst_hi,HReg dst_lo,HReg op)6129 s390_insn_dfp128_convert_to(UChar size, s390_dfp_conv_t tag, HReg dst_hi,
6130 HReg dst_lo, HReg op)
6131 {
6132 /* Conversion to dfp128 never requires a rounding mode. Provide default
6133 rounding mode. It will not be used when emitting insns. */
6134 s390_dfp_round_t rounding_mode = S390_DFP_ROUND_NEAREST_EVEN_4;
6135
6136 return s390_insn_dfp128_convert(size, tag, dst_hi, dst_lo, op,
6137 INVALID_HREG, rounding_mode);
6138 }
6139
6140
6141 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)6142 s390_insn_dfp128_convert_from(UChar size, s390_dfp_conv_t tag, HReg dst_hi,
6143 HReg dst_lo, HReg op_hi, HReg op_lo,
6144 s390_dfp_round_t rounding_mode)
6145 {
6146 return s390_insn_dfp128_convert(size, tag, dst_hi, dst_lo, op_hi, op_lo,
6147 rounding_mode);
6148 }
6149
6150
6151 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)6152 s390_insn_dfp128_reround(UChar size, HReg dst_hi, HReg dst_lo, HReg op2,
6153 HReg op3_hi, HReg op3_lo,
6154 s390_dfp_round_t rounding_mode)
6155 {
6156 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
6157
6158 vassert(size == 16);
6159 vassert(is_valid_fp128_regpair(dst_hi, dst_lo));
6160 vassert(is_valid_fp128_regpair(op3_hi, op3_lo));
6161
6162 insn->tag = S390_INSN_DFP_REROUND;
6163 insn->size = size;
6164 insn->variant.dfp_reround.dst_hi = dst_hi;
6165 insn->variant.dfp_reround.dst_lo = dst_lo;
6166 insn->variant.dfp_reround.op2 = op2;
6167 insn->variant.dfp_reround.op3_hi = op3_hi;
6168 insn->variant.dfp_reround.op3_lo = op3_lo;
6169 insn->variant.dfp_reround.rounding_mode = rounding_mode;
6170
6171 return insn;
6172 }
6173
6174
6175 s390_insn *
s390_insn_mfence(void)6176 s390_insn_mfence(void)
6177 {
6178 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
6179
6180 insn->tag = S390_INSN_MFENCE;
6181 insn->size = 0; /* not needed */
6182
6183 return insn;
6184 }
6185
6186
6187 s390_insn *
s390_insn_mimm(UChar size,s390_amode * dst,ULong value)6188 s390_insn_mimm(UChar size, s390_amode *dst, ULong value)
6189 {
6190 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
6191
6192 /* This insn will be mapped to insns that require base register
6193 plus 12-bit displacement */
6194 vassert(dst->tag == S390_AMODE_B12);
6195
6196 insn->tag = S390_INSN_MIMM;
6197 insn->size = size;
6198 insn->variant.mimm.dst = dst;
6199 insn->variant.mimm.value = value;
6200
6201 return insn;
6202 }
6203
6204
6205 s390_insn *
s390_insn_madd(UChar size,s390_amode * dst,UChar delta,ULong value)6206 s390_insn_madd(UChar size, s390_amode *dst, UChar delta, ULong value)
6207 {
6208 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
6209
6210 vassert(size == 4 || size == 8);
6211
6212 /* This insn will be mapped to an ASI or AGSI so we can only allow base
6213 register plus 12-bit / 20-bit displacement. */
6214 vassert(dst->tag == S390_AMODE_B12 || dst->tag == S390_AMODE_B20);
6215 /* ASI and AGSI require the GIE facility */
6216 vassert(s390_host_has_gie);
6217
6218 insn->tag = S390_INSN_MADD;
6219 insn->size = size;
6220 insn->variant.madd.dst = dst;
6221 insn->variant.madd.delta = delta;
6222 insn->variant.madd.value = value;
6223
6224 return insn;
6225 }
6226
6227
6228 s390_insn *
s390_insn_set_fpc_bfprm(UChar size,HReg mode)6229 s390_insn_set_fpc_bfprm(UChar size, HReg mode)
6230 {
6231 vassert(size == 4);
6232
6233 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
6234
6235 insn->tag = S390_INSN_SET_FPC_BFPRM;
6236 insn->size = size;
6237 insn->variant.set_fpc_bfprm.mode = mode;
6238
6239 return insn;
6240 }
6241
6242
6243 s390_insn *
s390_insn_set_fpc_dfprm(UChar size,HReg mode)6244 s390_insn_set_fpc_dfprm(UChar size, HReg mode)
6245 {
6246 vassert(size == 4);
6247
6248 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
6249
6250 insn->tag = S390_INSN_SET_FPC_DFPRM;
6251 insn->size = size;
6252 insn->variant.set_fpc_dfprm.mode = mode;
6253
6254 return insn;
6255 }
6256
6257
6258 s390_insn *
s390_insn_xdirect(s390_cc_t cond,Addr64 dst,s390_amode * guest_IA,Bool to_fast_entry)6259 s390_insn_xdirect(s390_cc_t cond, Addr64 dst, s390_amode *guest_IA,
6260 Bool to_fast_entry)
6261 {
6262 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
6263
6264 vassert(guest_IA->tag == S390_AMODE_B12);
6265
6266 insn->tag = S390_INSN_XDIRECT;
6267 insn->size = 0; /* does not matter */
6268
6269 insn->variant.xdirect.cond = cond;
6270 insn->variant.xdirect.dst = dst;
6271 insn->variant.xdirect.guest_IA = guest_IA;
6272 insn->variant.xdirect.to_fast_entry = to_fast_entry;
6273
6274 return insn;
6275 }
6276
6277
6278 s390_insn *
s390_insn_xindir(s390_cc_t cond,HReg dst,s390_amode * guest_IA)6279 s390_insn_xindir(s390_cc_t cond, HReg dst, s390_amode *guest_IA)
6280 {
6281 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
6282
6283 vassert(guest_IA->tag == S390_AMODE_B12);
6284
6285 insn->tag = S390_INSN_XINDIR;
6286 insn->size = 0; /* does not matter */
6287
6288 insn->variant.xindir.cond = cond;
6289 insn->variant.xindir.dst = dst;
6290 insn->variant.xindir.guest_IA = guest_IA;
6291
6292 return insn;
6293 }
6294
6295
6296 s390_insn *
s390_insn_xassisted(s390_cc_t cond,HReg dst,s390_amode * guest_IA,IRJumpKind kind)6297 s390_insn_xassisted(s390_cc_t cond, HReg dst, s390_amode *guest_IA,
6298 IRJumpKind kind)
6299 {
6300 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
6301
6302 vassert(guest_IA->tag == S390_AMODE_B12);
6303
6304 insn->tag = S390_INSN_XASSISTED;
6305 insn->size = 0; /* does not matter */
6306
6307 insn->variant.xassisted.cond = cond;
6308 insn->variant.xassisted.dst = dst;
6309 insn->variant.xassisted.guest_IA = guest_IA;
6310 insn->variant.xassisted.kind = kind;
6311
6312 return insn;
6313 }
6314
6315
6316 s390_insn *
s390_insn_evcheck(s390_amode * counter,s390_amode * fail_addr)6317 s390_insn_evcheck(s390_amode *counter, s390_amode *fail_addr)
6318 {
6319 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
6320
6321 vassert(counter->tag == S390_AMODE_B12);
6322 vassert(fail_addr->tag == S390_AMODE_B12);
6323
6324 insn->tag = S390_INSN_EVCHECK;
6325 insn->size = 0; /* does not matter */
6326
6327 insn->variant.evcheck.counter = counter;
6328 insn->variant.evcheck.fail_addr = fail_addr;
6329
6330 return insn;
6331 }
6332
6333
6334 s390_insn *
s390_insn_profinc(void)6335 s390_insn_profinc(void)
6336 {
6337 s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
6338
6339 insn->tag = S390_INSN_PROFINC;
6340 insn->size = 0; /* does not matter */
6341
6342 return insn;
6343 }
6344
6345
6346 /*---------------------------------------------------------------*/
6347 /*--- Debug print ---*/
6348 /*---------------------------------------------------------------*/
6349
6350 static const HChar *
s390_cc_as_string(s390_cc_t cc)6351 s390_cc_as_string(s390_cc_t cc)
6352 {
6353 switch (cc) {
6354 case S390_CC_NEVER: return "never";
6355 case S390_CC_OVFL: return "overflow";
6356 case S390_CC_H: return "greater than"; /* A > B ; high */
6357 case S390_CC_NLE: return "not low or equal";
6358 case S390_CC_L: return "less than"; /* A < B ; low */
6359 case S390_CC_NHE: return "not high or equal";
6360 case S390_CC_LH: return "low or high";
6361 case S390_CC_NE: return "not equal"; /* A != B ; not zero */
6362 case S390_CC_E: return "equal"; /* A == B ; zero */
6363 case S390_CC_NLH: return "not low or high";
6364 case S390_CC_HE: return "greater or equal"; /* A >= B ; high or equal*/
6365 case S390_CC_NL: return "not low"; /* not low */
6366 case S390_CC_LE: return "less or equal"; /* A <= B ; low or equal */
6367 case S390_CC_NH: return "not high";
6368 case S390_CC_NO: return "not overflow";
6369 case S390_CC_ALWAYS: return "always";
6370 default:
6371 vpanic("s390_cc_as_string");
6372 }
6373 }
6374
6375
6376 static const HChar *
s390_jump_kind_as_string(IRJumpKind kind)6377 s390_jump_kind_as_string(IRJumpKind kind)
6378 {
6379 switch (kind) {
6380 case Ijk_Boring: return "Boring";
6381 case Ijk_Call: return "Call";
6382 case Ijk_Ret: return "Return";
6383 case Ijk_ClientReq: return "ClientReq";
6384 case Ijk_Yield: return "Yield";
6385 case Ijk_EmWarn: return "EmWarn";
6386 case Ijk_EmFail: return "EmFail";
6387 case Ijk_NoDecode: return "NoDecode";
6388 case Ijk_MapFail: return "MapFail";
6389 case Ijk_InvalICache: return "Invalidate";
6390 case Ijk_NoRedir: return "NoRedir";
6391 case Ijk_SigTRAP: return "SigTRAP";
6392 case Ijk_SigSEGV: return "SigSEGV";
6393 case Ijk_SigBUS: return "SigBUS";
6394 case Ijk_Sys_syscall: return "Sys_syscall";
6395 default:
6396 vpanic("s390_jump_kind_as_string");
6397 }
6398 }
6399
6400
6401 /* Helper function for writing out a V insn */
6402 static void
s390_sprintf(HChar * buf,const HChar * fmt,...)6403 s390_sprintf(HChar *buf, const HChar *fmt, ...)
6404 {
6405 HChar *p;
6406 ULong value;
6407 va_list args;
6408 va_start(args, fmt);
6409
6410 p = buf;
6411 for ( ; *fmt; ++fmt) {
6412 Int c = *fmt;
6413
6414 if (c != '%') {
6415 *p++ = c;
6416 continue;
6417 }
6418
6419 c = *++fmt; /* next char */
6420 switch (c) {
6421 case '%':
6422 *p++ = c; /* %% */
6423 continue;
6424
6425 case 's': /* %s */
6426 p += vex_sprintf(p, "%s", va_arg(args, HChar *));
6427 continue;
6428
6429 case 'M': /* %M = mnemonic */
6430 p += vex_sprintf(p, "%-8s", va_arg(args, HChar *));
6431 continue;
6432
6433 case 'R': /* %R = register */
6434 p += vex_sprintf(p, "%s", s390_hreg_as_string(va_arg(args, HReg)));
6435 continue;
6436
6437 case 'A': /* %A = amode */
6438 p += vex_sprintf(p, "%s",
6439 s390_amode_as_string(va_arg(args, s390_amode *)));
6440 continue;
6441
6442 case 'G': /* %G = guest state @ offset */
6443 p += vex_sprintf(p, "guest[%u]", va_arg(args, UInt));
6444 continue;
6445
6446 case 'C': /* %C = condition code */
6447 p += vex_sprintf(p, "%s", s390_cc_as_string(va_arg(args, s390_cc_t)));
6448 continue;
6449
6450 case 'J': /* &J = jump kind */
6451 p += vex_sprintf(p, "%s",
6452 s390_jump_kind_as_string(va_arg(args, IRJumpKind)));
6453 continue;
6454
6455 case 'L': { /* %L = argument list in helper call*/
6456 UInt i, num_args;
6457
6458 num_args = va_arg(args, UInt);
6459
6460 for (i = 0; i < num_args; ++i) {
6461 if (i != 0) p += vex_sprintf(p, ", ");
6462 p += vex_sprintf(p, "r%u", s390_gprno_from_arg_index(i));
6463 }
6464 continue;
6465 }
6466
6467 case 'O': { /* %O = RMI operand */
6468 s390_opnd_RMI *op = va_arg(args, s390_opnd_RMI *);
6469
6470 switch (op->tag) {
6471 case S390_OPND_REG:
6472 p += vex_sprintf(p, "%s", s390_hreg_as_string(op->variant.reg));
6473 continue;
6474
6475 case S390_OPND_AMODE:
6476 p += vex_sprintf(p, "%s", s390_amode_as_string(op->variant.am));
6477 continue;
6478
6479 case S390_OPND_IMMEDIATE:
6480 value = op->variant.imm;
6481 goto print_value;
6482
6483 default:
6484 goto fail;
6485 }
6486 }
6487
6488 case 'I': /* %I = immediate value */
6489 value = va_arg(args, ULong);
6490 goto print_value;
6491
6492 print_value:
6493 if ((Long)value < 0)
6494 p += vex_sprintf(p, "%lld", (Long)value);
6495 else if (value < 100)
6496 p += vex_sprintf(p, "%llu", value);
6497 else
6498 p += vex_sprintf(p, "0x%llx", value);
6499 continue;
6500
6501 default:
6502 goto fail;
6503 }
6504 }
6505 *p = '\0';
6506 va_end(args);
6507
6508 return;
6509
6510 fail: vpanic("s390_printf");
6511 }
6512
6513
6514 /* Decompile the given insn into a static buffer and return it */
6515 const HChar *
s390_insn_as_string(const s390_insn * insn)6516 s390_insn_as_string(const s390_insn *insn)
6517 {
6518 static HChar buf[300]; // large enough
6519 const HChar *op;
6520 HChar *p;
6521
6522 buf[0] = '\0';
6523
6524 switch (insn->tag) {
6525 case S390_INSN_LOAD:
6526 s390_sprintf(buf, "%M %R,%A", "v-load", insn->variant.load.dst,
6527 insn->variant.load.src);
6528 break;
6529
6530 case S390_INSN_STORE:
6531 s390_sprintf(buf, "%M %R,%A", "v-store", insn->variant.store.src,
6532 insn->variant.store.dst);
6533 break;
6534
6535 case S390_INSN_MOVE:
6536 s390_sprintf(buf, "%M %R,%R", "v-move", insn->variant.move.dst,
6537 insn->variant.move.src);
6538 break;
6539
6540 case S390_INSN_MEMCPY:
6541 s390_sprintf(buf, "%M %A,%A", "v-memcpy", insn->variant.memcpy.dst,
6542 insn->variant.memcpy.src);
6543 break;
6544
6545 case S390_INSN_COND_MOVE:
6546 s390_sprintf(buf, "%M if (%C) %R,%O", "v-move",
6547 insn->variant.cond_move.cond, insn->variant.cond_move.dst,
6548 &insn->variant.cond_move.src);
6549 break;
6550
6551 case S390_INSN_LOAD_IMMEDIATE:
6552 s390_sprintf(buf, "%M %R,%I", "v-loadi", insn->variant.load_immediate.dst,
6553 insn->variant.load_immediate.value);
6554 break;
6555
6556 case S390_INSN_ALU:
6557 switch (insn->variant.alu.tag) {
6558 case S390_ALU_ADD: op = "v-add"; break;
6559 case S390_ALU_SUB: op = "v-sub"; break;
6560 case S390_ALU_MUL: op = "v-mul"; break;
6561 case S390_ALU_AND: op = "v-and"; break;
6562 case S390_ALU_OR: op = "v-or"; break;
6563 case S390_ALU_XOR: op = "v-xor"; break;
6564 case S390_ALU_LSH: op = "v-lsh"; break;
6565 case S390_ALU_RSH: op = "v-rsh"; break;
6566 case S390_ALU_RSHA: op = "v-rsha"; break;
6567 default: goto fail;
6568 }
6569 s390_sprintf(buf, "%M %R,%O", op, insn->variant.alu.dst, /* also op1 */
6570 &insn->variant.alu.op2);
6571 break;
6572
6573 case S390_INSN_SMUL:
6574 case S390_INSN_UMUL:
6575 if (insn->tag == S390_INSN_SMUL) {
6576 op = "v-muls";
6577 } else {
6578 op = "v-mulu";
6579 }
6580 s390_sprintf(buf, "%M %R,%O", op, insn->variant.mul.dst_hi,
6581 &insn->variant.mul.op2);
6582 break;
6583
6584 case S390_INSN_SDIV:
6585 case S390_INSN_UDIV:
6586 if (insn->tag == S390_INSN_SDIV) {
6587 op = "v-divs";
6588 } else {
6589 op = "v-divu";
6590 }
6591 s390_sprintf(buf, "%M %R,%O", op, insn->variant.div.op1_hi,
6592 &insn->variant.div.op2);
6593 break;
6594
6595 case S390_INSN_DIVS:
6596 s390_sprintf(buf, "%M %R,%O", "v-divsi", insn->variant.divs.op1,
6597 &insn->variant.divs.op2);
6598 break;
6599
6600 case S390_INSN_CLZ:
6601 s390_sprintf(buf, "%M %R,%O", "v-clz", insn->variant.clz.num_bits,
6602 &insn->variant.clz.src);
6603 break;
6604
6605 case S390_INSN_UNOP:
6606 switch (insn->variant.unop.tag) {
6607 case S390_ZERO_EXTEND_8:
6608 case S390_ZERO_EXTEND_16:
6609 case S390_ZERO_EXTEND_32:
6610 op = "v-zerox";
6611 break;
6612
6613 case S390_SIGN_EXTEND_8:
6614 case S390_SIGN_EXTEND_16:
6615 case S390_SIGN_EXTEND_32:
6616 op = "v-signx";
6617 break;
6618
6619 case S390_NEGATE:
6620 op = "v-neg";
6621 break;
6622
6623 default:
6624 goto fail;
6625 }
6626 s390_sprintf(buf, "%M %R,%O", op, insn->variant.unop.dst,
6627 &insn->variant.unop.src);
6628 break;
6629
6630 case S390_INSN_TEST:
6631 s390_sprintf(buf, "%M %O", "v-test", &insn->variant.test.src);
6632 break;
6633
6634 case S390_INSN_CC2BOOL:
6635 s390_sprintf(buf, "%M %R,%C", "v-cc2b", insn->variant.cc2bool.dst,
6636 insn->variant.cc2bool.cond);
6637 break;
6638
6639 case S390_INSN_CAS:
6640 s390_sprintf(buf, "%M %R,%A,%R,%R", "v-cas", insn->variant.cas.op1,
6641 insn->variant.cas.op2, insn->variant.cas.op3,
6642 insn->variant.cas.old_mem);
6643 break;
6644
6645 case S390_INSN_CDAS: {
6646 s390_cdas *cdas = insn->variant.cdas.details;
6647
6648 s390_sprintf(buf, "%M %R,%R,%A,%R,%R,%R,%R", "v-cdas",
6649 cdas->op1_high, cdas->op1_low, cdas->op2, cdas->op3_high,
6650 cdas->op3_low, cdas->old_mem_high, cdas->old_mem_low);
6651 break;
6652 }
6653
6654 case S390_INSN_COMPARE:
6655 if (insn->variant.compare.signed_comparison) {
6656 op = "v-cmps";
6657 } else {
6658 op = "v-cmpu";
6659 }
6660 s390_sprintf(buf, "%M %R,%O", op, insn->variant.compare.src1,
6661 &insn->variant.compare.src2);
6662 break;
6663
6664 case S390_INSN_HELPER_CALL: {
6665 s390_helper_call *helper_call = insn->variant.helper_call.details;
6666 s390_sprintf(buf, "%M if (%C) %s{%I}(%L)", "v-call",
6667 helper_call->cond,
6668 helper_call->name,
6669 helper_call->target,
6670 helper_call->num_args);
6671 return buf; /* avoid printing "size = ..." which is meaningless */
6672 }
6673
6674 case S390_INSN_BFP_TRIOP:
6675 switch (insn->variant.bfp_triop.tag) {
6676 case S390_BFP_MADD: op = "v-fmadd"; break;
6677 case S390_BFP_MSUB: op = "v-fmsub"; break;
6678 default: goto fail;
6679 }
6680 s390_sprintf(buf, "%M %R,%R,%R", op,
6681 insn->variant.bfp_triop.dst /* op1 same as dst */,
6682 insn->variant.bfp_triop.op2, insn->variant.bfp_triop.op3);
6683 break;
6684
6685 case S390_INSN_BFP_BINOP:
6686 switch (insn->variant.bfp_binop.tag) {
6687 case S390_BFP_ADD: op = "v-fadd"; break;
6688 case S390_BFP_SUB: op = "v-fsub"; break;
6689 case S390_BFP_MUL: op = "v-fmul"; break;
6690 case S390_BFP_DIV: op = "v-fdiv"; break;
6691 default: goto fail;
6692 }
6693 s390_sprintf(buf, "%M %R,%R", op,
6694 insn->variant.bfp_binop.dst_hi /* op1 same as dst */,
6695 insn->variant.bfp_binop.op2_hi);
6696 break;
6697
6698 case S390_INSN_BFP_COMPARE:
6699 s390_sprintf(buf, "%M %R,%R,%R", "v-fcmp", insn->variant.bfp_compare.dst,
6700 insn->variant.bfp_compare.op1_hi,
6701 insn->variant.bfp_compare.op2_hi);
6702 break;
6703
6704 case S390_INSN_BFP_UNOP:
6705 switch (insn->variant.bfp_unop.tag) {
6706 case S390_BFP_ABS: op = "v-fabs"; break;
6707 case S390_BFP_NABS: op = "v-fnabs"; break;
6708 case S390_BFP_NEG: op = "v-fneg"; break;
6709 case S390_BFP_SQRT: op = "v-fsqrt"; break;
6710 default: goto fail;
6711 }
6712 s390_sprintf(buf, "%M %R,%R", op, insn->variant.bfp_unop.dst_hi,
6713 insn->variant.bfp_unop.op_hi);
6714 break;
6715
6716 case S390_INSN_BFP_CONVERT:
6717 switch (insn->variant.bfp_convert.tag) {
6718 case S390_BFP_I32_TO_F32:
6719 case S390_BFP_I32_TO_F64:
6720 case S390_BFP_I32_TO_F128:
6721 case S390_BFP_I64_TO_F32:
6722 case S390_BFP_I64_TO_F64:
6723 case S390_BFP_I64_TO_F128: op = "v-i2f"; break;
6724 case S390_BFP_U32_TO_F32:
6725 case S390_BFP_U32_TO_F64:
6726 case S390_BFP_U32_TO_F128:
6727 case S390_BFP_U64_TO_F32:
6728 case S390_BFP_U64_TO_F64:
6729 case S390_BFP_U64_TO_F128: op = "v-u2f"; break;
6730 case S390_BFP_F32_TO_I32:
6731 case S390_BFP_F32_TO_I64:
6732 case S390_BFP_F64_TO_I32:
6733 case S390_BFP_F64_TO_I64:
6734 case S390_BFP_F128_TO_I32:
6735 case S390_BFP_F128_TO_I64: op = "v-f2i"; break;
6736 case S390_BFP_F32_TO_U32:
6737 case S390_BFP_F32_TO_U64:
6738 case S390_BFP_F64_TO_U32:
6739 case S390_BFP_F64_TO_U64:
6740 case S390_BFP_F128_TO_U32:
6741 case S390_BFP_F128_TO_U64: op = "v-f2u"; break;
6742 case S390_BFP_F32_TO_F64:
6743 case S390_BFP_F32_TO_F128:
6744 case S390_BFP_F64_TO_F32:
6745 case S390_BFP_F64_TO_F128:
6746 case S390_BFP_F128_TO_F32:
6747 case S390_BFP_F128_TO_F64: op = "v-f2f"; break;
6748 case S390_BFP_F32_TO_F32I:
6749 case S390_BFP_F64_TO_F64I:
6750 case S390_BFP_F128_TO_F128I: op = "v-f2fi"; break;
6751 default: goto fail;
6752 }
6753 s390_sprintf(buf, "%M %R,%R", op, insn->variant.bfp_convert.dst_hi,
6754 insn->variant.bfp_convert.op_hi);
6755 break;
6756
6757 case S390_INSN_DFP_BINOP: {
6758 s390_dfp_binop *dfp_binop = insn->variant.dfp_binop.details;
6759
6760 switch (dfp_binop->tag) {
6761 case S390_DFP_ADD: op = "v-dadd"; break;
6762 case S390_DFP_SUB: op = "v-dsub"; break;
6763 case S390_DFP_MUL: op = "v-dmul"; break;
6764 case S390_DFP_DIV: op = "v-ddiv"; break;
6765 case S390_DFP_QUANTIZE: op = "v-dqua"; break;
6766 default: goto fail;
6767 }
6768 s390_sprintf(buf, "%M %R,%R,%R", op, dfp_binop->dst_hi,
6769 dfp_binop->op2_hi, dfp_binop->op3_hi);
6770 break;
6771 }
6772
6773 case S390_INSN_DFP_UNOP:
6774 switch (insn->variant.dfp_unop.tag) {
6775 case S390_DFP_EXTRACT_EXP_D64:
6776 case S390_DFP_EXTRACT_EXP_D128: op = "v-d2exp"; break;
6777 case S390_DFP_EXTRACT_SIG_D64:
6778 case S390_DFP_EXTRACT_SIG_D128: op = "v-d2sig"; break;
6779 default: goto fail;
6780 }
6781 s390_sprintf(buf, "%M %R,%R", op, insn->variant.dfp_unop.dst_hi,
6782 insn->variant.dfp_unop.op_hi);
6783 break;
6784
6785 case S390_INSN_DFP_INTOP:
6786 switch (insn->variant.dfp_intop.tag) {
6787 case S390_DFP_SHIFT_LEFT: op = "v-dshl"; break;
6788 case S390_DFP_SHIFT_RIGHT: op = "v-dshr"; break;
6789 case S390_DFP_INSERT_EXP: op = "v-diexp"; break;
6790 default: goto fail;
6791 }
6792 s390_sprintf(buf, "%M %R,%R,%R", op, insn->variant.dfp_intop.dst_hi,
6793 insn->variant.dfp_intop.op2,
6794 insn->variant.dfp_intop.op3_hi);
6795 break;
6796
6797 case S390_INSN_DFP_COMPARE:
6798 switch (insn->variant.dfp_compare.tag) {
6799 case S390_DFP_COMPARE: op = "v-dcmp"; break;
6800 case S390_DFP_COMPARE_EXP: op = "v-dcmpexp"; break;
6801 default: goto fail;
6802 }
6803 s390_sprintf(buf, "%M %R,%R,%R", op, insn->variant.dfp_compare.dst,
6804 insn->variant.dfp_compare.op1_hi,
6805 insn->variant.dfp_compare.op2_hi);
6806 break;
6807
6808 case S390_INSN_DFP_CONVERT:
6809 switch (insn->variant.dfp_convert.tag) {
6810 case S390_DFP_D32_TO_D64:
6811 case S390_DFP_D64_TO_D32:
6812 case S390_DFP_D64_TO_D128:
6813 case S390_DFP_D128_TO_D64: op = "v-d2d"; break;
6814 case S390_DFP_I32_TO_D64:
6815 case S390_DFP_I32_TO_D128:
6816 case S390_DFP_I64_TO_D64:
6817 case S390_DFP_I64_TO_D128: op = "v-i2d"; break;
6818 case S390_DFP_U32_TO_D64:
6819 case S390_DFP_U32_TO_D128:
6820 case S390_DFP_U64_TO_D64:
6821 case S390_DFP_U64_TO_D128: op = "v-u2d"; break;
6822 case S390_DFP_D64_TO_I32:
6823 case S390_DFP_D128_TO_I32:
6824 case S390_DFP_D64_TO_I64:
6825 case S390_DFP_D128_TO_I64: op = "v-d2i"; break;
6826 case S390_DFP_D64_TO_U32:
6827 case S390_DFP_D64_TO_U64:
6828 case S390_DFP_D128_TO_U32:
6829 case S390_DFP_D128_TO_U64: op = "v-d2u"; break;
6830 default: goto fail;
6831 }
6832 s390_sprintf(buf, "%M %R,%R", op, insn->variant.dfp_convert.dst_hi,
6833 insn->variant.dfp_convert.op_hi);
6834 break;
6835
6836 case S390_INSN_DFP_REROUND:
6837 s390_sprintf(buf, "%M %R,%R,%R", "v-drrnd",
6838 insn->variant.dfp_reround.dst_hi,
6839 insn->variant.dfp_reround.op2,
6840 insn->variant.dfp_reround.op3_hi);
6841 break;
6842
6843 case S390_INSN_FP_CONVERT: {
6844 s390_fp_convert *fp_convert = insn->variant.fp_convert.details;
6845
6846 switch (fp_convert->tag) {
6847 case S390_FP_F32_TO_D32:
6848 case S390_FP_F32_TO_D64:
6849 case S390_FP_F32_TO_D128:
6850 case S390_FP_F64_TO_D32:
6851 case S390_FP_F64_TO_D64:
6852 case S390_FP_F64_TO_D128:
6853 case S390_FP_F128_TO_D32:
6854 case S390_FP_F128_TO_D64:
6855 case S390_FP_F128_TO_D128: op = "v-f2d"; break;
6856 case S390_FP_D32_TO_F32:
6857 case S390_FP_D32_TO_F64:
6858 case S390_FP_D32_TO_F128:
6859 case S390_FP_D64_TO_F32:
6860 case S390_FP_D64_TO_F64:
6861 case S390_FP_D64_TO_F128:
6862 case S390_FP_D128_TO_F32:
6863 case S390_FP_D128_TO_F64:
6864 case S390_FP_D128_TO_F128: op = "v-d2f"; break;
6865 default: goto fail;
6866 }
6867 s390_sprintf(buf, "%M %R,%R", op, fp_convert->dst_hi,
6868 fp_convert->op_hi);
6869 break;
6870 }
6871
6872 case S390_INSN_MFENCE:
6873 s390_sprintf(buf, "%M", "v-mfence");
6874 return buf; /* avoid printing "size = ..." which is meaningless */
6875
6876 case S390_INSN_MIMM:
6877 s390_sprintf(buf, "%M %A,%I", "v-mimm", insn->variant.mimm.dst,
6878 insn->variant.mimm.value);
6879 break;
6880
6881 case S390_INSN_MADD:
6882 s390_sprintf(buf, "%M %A += %I (= %I)", "v-madd",
6883 insn->variant.madd.dst,
6884 (Long)(Char)insn->variant.madd.delta,
6885 insn->variant.madd.value);
6886 break;
6887
6888 case S390_INSN_SET_FPC_BFPRM:
6889 s390_sprintf(buf, "%M %R", "v-set-fpc-bfprm",
6890 insn->variant.set_fpc_bfprm.mode);
6891 break;
6892
6893 case S390_INSN_SET_FPC_DFPRM:
6894 s390_sprintf(buf, "%M %R", "v-set-fpc-dfprm",
6895 insn->variant.set_fpc_dfprm.mode);
6896 break;
6897
6898 case S390_INSN_EVCHECK:
6899 s390_sprintf(buf, "%M counter = %A, fail-addr = %A", "v-evcheck",
6900 insn->variant.evcheck.counter,
6901 insn->variant.evcheck.fail_addr);
6902 return buf; /* avoid printing "size = ..." which is meaningless */
6903
6904 case S390_INSN_PROFINC:
6905 s390_sprintf(buf, "%M", "v-profinc");
6906 return buf; /* avoid printing "size = ..." which is meaningless */
6907
6908 case S390_INSN_XDIRECT:
6909 s390_sprintf(buf, "%M if (%C) %A = %I %s", "v-xdirect",
6910 insn->variant.xdirect.cond,
6911 insn->variant.xdirect.guest_IA,
6912 insn->variant.xdirect.dst,
6913 insn->variant.xdirect.to_fast_entry ? "fast" : "slow");
6914 return buf; /* avoid printing "size = ..." which is meaningless */
6915
6916 case S390_INSN_XINDIR:
6917 s390_sprintf(buf, "%M if (%C) %A = %R", "v-xindir",
6918 insn->variant.xindir.cond,
6919 insn->variant.xindir.guest_IA,
6920 insn->variant.xindir.dst);
6921 return buf; /* avoid printing "size = ..." which is meaningless */
6922
6923 case S390_INSN_XASSISTED:
6924 s390_sprintf(buf, "%M if (%C) %J %A = %R", "v-xassisted",
6925 insn->variant.xassisted.cond,
6926 insn->variant.xassisted.kind,
6927 insn->variant.xassisted.guest_IA,
6928 insn->variant.xassisted.dst);
6929 return buf; /* avoid printing "size = ..." which is meaningless */
6930
6931 default: goto fail;
6932 }
6933
6934 /* Write out how many bytes are involved in the operation */
6935
6936 {
6937 UInt len, i;
6938
6939 for (p = buf; *p; ++p)
6940 continue;
6941
6942 len = p - buf;
6943
6944 if (len < 32) {
6945 for (i = len; i < 32; ++i)
6946 p += vex_sprintf(p, " ");
6947 } else {
6948 p += vex_sprintf(p, "\t");
6949 }
6950 }
6951
6952 /* Special cases first */
6953 switch (insn->tag) {
6954 case S390_INSN_UNOP:
6955 switch (insn->variant.unop.tag) {
6956 case S390_SIGN_EXTEND_8:
6957 case S390_ZERO_EXTEND_8: p += vex_sprintf(p, "1 -> "); goto common;
6958 case S390_SIGN_EXTEND_16:
6959 case S390_ZERO_EXTEND_16: p += vex_sprintf(p, "2 -> "); goto common;
6960 case S390_SIGN_EXTEND_32:
6961 case S390_ZERO_EXTEND_32: p += vex_sprintf(p, "4 -> "); goto common;
6962 default:
6963 goto common;
6964 }
6965
6966 case S390_INSN_BFP_CONVERT:
6967 switch (insn->variant.bfp_convert.tag) {
6968 case S390_BFP_I32_TO_F32:
6969 case S390_BFP_I32_TO_F64:
6970 case S390_BFP_I32_TO_F128:
6971 case S390_BFP_U32_TO_F32:
6972 case S390_BFP_U32_TO_F64:
6973 case S390_BFP_U32_TO_F128:
6974 case S390_BFP_F32_TO_I32:
6975 case S390_BFP_F32_TO_I64:
6976 case S390_BFP_F32_TO_U32:
6977 case S390_BFP_F32_TO_U64:
6978 case S390_BFP_F32_TO_F64:
6979 case S390_BFP_F32_TO_F128: p += vex_sprintf(p, "4 -> "); goto common;
6980 case S390_BFP_I64_TO_F32:
6981 case S390_BFP_I64_TO_F64:
6982 case S390_BFP_I64_TO_F128:
6983 case S390_BFP_U64_TO_F32:
6984 case S390_BFP_U64_TO_F64:
6985 case S390_BFP_U64_TO_F128:
6986 case S390_BFP_F64_TO_I32:
6987 case S390_BFP_F64_TO_I64:
6988 case S390_BFP_F64_TO_U32:
6989 case S390_BFP_F64_TO_U64:
6990 case S390_BFP_F64_TO_F32:
6991 case S390_BFP_F64_TO_F128: p += vex_sprintf(p, "8 -> "); goto common;
6992 case S390_BFP_F128_TO_I32:
6993 case S390_BFP_F128_TO_I64:
6994 case S390_BFP_F128_TO_U32:
6995 case S390_BFP_F128_TO_U64:
6996 case S390_BFP_F128_TO_F32:
6997 case S390_BFP_F128_TO_F64: p += vex_sprintf(p, "16 -> "); goto common;
6998 default:
6999 goto common;
7000 }
7001
7002 case S390_INSN_DFP_CONVERT:
7003 switch (insn->variant.dfp_convert.tag) {
7004 case S390_DFP_D32_TO_D64:
7005 case S390_DFP_I32_TO_D64:
7006 case S390_DFP_I32_TO_D128:
7007 case S390_DFP_U32_TO_D64:
7008 case S390_DFP_U32_TO_D128: p += vex_sprintf(p, "4 -> "); goto common;
7009 case S390_DFP_D64_TO_D32:
7010 case S390_DFP_D64_TO_D128:
7011 case S390_DFP_I64_TO_D64:
7012 case S390_DFP_I64_TO_D128:
7013 case S390_DFP_U64_TO_D64:
7014 case S390_DFP_U64_TO_D128:
7015 case S390_DFP_D64_TO_I32:
7016 case S390_DFP_D64_TO_I64:
7017 case S390_DFP_D64_TO_U32:
7018 case S390_DFP_D64_TO_U64: p += vex_sprintf(p, "8 -> "); goto common;
7019 case S390_DFP_D128_TO_D64:
7020 case S390_DFP_D128_TO_I32:
7021 case S390_DFP_D128_TO_I64:
7022 case S390_DFP_D128_TO_U32:
7023 case S390_DFP_D128_TO_U64: p += vex_sprintf(p, "16 -> "); goto common;
7024 default:
7025 goto common;
7026 }
7027
7028 case S390_INSN_FP_CONVERT: {
7029 s390_fp_convert *fp_convert = insn->variant.fp_convert.details;
7030
7031 switch (fp_convert->tag) {
7032 case S390_FP_F32_TO_D32:
7033 case S390_FP_F32_TO_D64:
7034 case S390_FP_F32_TO_D128:
7035 case S390_FP_D32_TO_F32:
7036 case S390_FP_D32_TO_F64:
7037 case S390_FP_D32_TO_F128: p += vex_sprintf(p, "4 -> "); goto common;
7038 case S390_FP_F64_TO_D32:
7039 case S390_FP_F64_TO_D64:
7040 case S390_FP_F64_TO_D128:
7041 case S390_FP_D64_TO_F32:
7042 case S390_FP_D64_TO_F64:
7043 case S390_FP_D64_TO_F128: p += vex_sprintf(p, "8 -> "); goto common;
7044 case S390_FP_F128_TO_D32:
7045 case S390_FP_F128_TO_D64:
7046 case S390_FP_F128_TO_D128:
7047 case S390_FP_D128_TO_F32:
7048 case S390_FP_D128_TO_F64:
7049 case S390_FP_D128_TO_F128: p += vex_sprintf(p, "16 -> "); goto common;
7050 default:
7051 goto common;
7052 }
7053 }
7054
7055 default:
7056 goto common;
7057 }
7058
7059 /* Common case */
7060 common:
7061 vex_sprintf(p, "%u bytes", (UInt)insn->size);
7062
7063 return buf;
7064
7065 fail: vpanic("s390_insn_as_string");
7066 }
7067
7068
7069
7070 /* Load NUM bytes from memory into register REG using addressing mode AM. */
7071 static UChar *
s390_emit_load_mem(UChar * p,UInt num,UChar reg,const s390_amode * am)7072 s390_emit_load_mem(UChar *p, UInt num, UChar reg, const s390_amode *am)
7073 {
7074 UInt b = hregNumber(am->b);
7075 UInt x = hregNumber(am->x); /* 0 for B12 and B20 */
7076 UInt d = am->d;
7077
7078 switch (am->tag) {
7079 case S390_AMODE_B12:
7080 case S390_AMODE_BX12:
7081 switch (num) {
7082 case 1: return s390_emit_IC(p, reg, x, b, d);
7083 case 2: return s390_emit_LH(p, reg, x, b, d);
7084 case 4: return s390_emit_L(p, reg, x, b, d);
7085 case 8: return s390_emit_LG(p, reg, x, b, DISP20(d));
7086 default: goto fail;
7087 }
7088 break;
7089
7090 case S390_AMODE_B20:
7091 case S390_AMODE_BX20:
7092 switch (num) {
7093 case 1: return s390_emit_ICY(p, reg, x, b, DISP20(d));
7094 case 2: return s390_emit_LHY(p, reg, x, b, DISP20(d));
7095 case 4: return s390_emit_LY(p, reg, x, b, DISP20(d));
7096 case 8: return s390_emit_LG(p, reg, x, b, DISP20(d));
7097 default: goto fail;
7098 }
7099 break;
7100
7101 default: goto fail;
7102 }
7103
7104 fail:
7105 vpanic("s390_emit_load_mem");
7106 }
7107
7108
7109 /* Load condition code into register REG */
7110 static UChar *
s390_emit_load_cc(UChar * p,UChar reg)7111 s390_emit_load_cc(UChar *p, UChar reg)
7112 {
7113 p = s390_emit_LGHI(p, reg, 0); /* Clear out, cc not affected */
7114 p = s390_emit_IPM(p, reg, reg);
7115 /* Shift 28 bits to the right --> [0,1,2,3] */
7116 return s390_emit_SRL(p, reg, 0, 28); /* REG = cc */
7117 }
7118
7119
7120 /*---------------------------------------------------------------*/
7121 /*--- Code generation ---*/
7122 /*---------------------------------------------------------------*/
7123
7124 /* Do not load more bytes than requested. */
7125 static UChar *
s390_insn_load_emit(UChar * buf,const s390_insn * insn)7126 s390_insn_load_emit(UChar *buf, const s390_insn *insn)
7127 {
7128 UInt r, x, b, d;
7129 const s390_amode *src;
7130
7131 src = insn->variant.load.src;
7132
7133 r = hregNumber(insn->variant.load.dst);
7134
7135 if (hregClass(insn->variant.load.dst) == HRcFlt64) {
7136 b = hregNumber(src->b);
7137 x = hregNumber(src->x); /* 0 for B12 and B20 */
7138 d = src->d;
7139
7140 switch (insn->size) {
7141
7142 case 4:
7143 switch (src->tag) {
7144 case S390_AMODE_B12:
7145 case S390_AMODE_BX12:
7146 return s390_emit_LE(buf, r, x, b, d);
7147
7148 case S390_AMODE_B20:
7149 case S390_AMODE_BX20:
7150 return s390_emit_LEY(buf, r, x, b, DISP20(d));
7151 }
7152 break;
7153
7154 case 8:
7155 switch (src->tag) {
7156 case S390_AMODE_B12:
7157 case S390_AMODE_BX12:
7158 return s390_emit_LD(buf, r, x, b, d);
7159
7160 case S390_AMODE_B20:
7161 case S390_AMODE_BX20:
7162 return s390_emit_LDY(buf, r, x, b, DISP20(d));
7163 }
7164 break;
7165 }
7166 vpanic("s390_insn_load_emit");
7167 }
7168
7169 /* Integer stuff */
7170 return s390_emit_load_mem(buf, insn->size, r, src);
7171 }
7172
7173
7174 static UChar *
s390_insn_store_emit(UChar * buf,const s390_insn * insn)7175 s390_insn_store_emit(UChar *buf, const s390_insn *insn)
7176 {
7177 UInt r, x, b, d;
7178 const s390_amode *dst;
7179
7180 dst = insn->variant.store.dst;
7181
7182 r = hregNumber(insn->variant.store.src);
7183 b = hregNumber(dst->b);
7184 x = hregNumber(dst->x); /* 0 for B12 and B20 */
7185 d = dst->d;
7186
7187 if (hregClass(insn->variant.store.src) == HRcFlt64) {
7188 switch (insn->size) {
7189
7190 case 4:
7191 switch (dst->tag) {
7192 case S390_AMODE_B12:
7193 case S390_AMODE_BX12:
7194 return s390_emit_STE(buf, r, x, b, d);
7195
7196 case S390_AMODE_B20:
7197 case S390_AMODE_BX20:
7198 return s390_emit_STEY(buf, r, x, b, DISP20(d));
7199 }
7200 break;
7201
7202 case 8:
7203 switch (dst->tag) {
7204 case S390_AMODE_B12:
7205 case S390_AMODE_BX12:
7206 return s390_emit_STD(buf, r, x, b, d);
7207
7208 case S390_AMODE_B20:
7209 case S390_AMODE_BX20:
7210 return s390_emit_STDY(buf, r, x, b, DISP20(d));
7211 }
7212 break;
7213 }
7214 vpanic("s390_insn_store_emit");
7215 }
7216
7217 /* Integer stuff */
7218 switch (insn->size) {
7219 case 1:
7220 switch (dst->tag) {
7221 case S390_AMODE_B12:
7222 case S390_AMODE_BX12:
7223 return s390_emit_STC(buf, r, x, b, d);
7224
7225 case S390_AMODE_B20:
7226 case S390_AMODE_BX20:
7227 return s390_emit_STCY(buf, r, x, b, DISP20(d));
7228 }
7229 break;
7230
7231 case 2:
7232 switch (dst->tag) {
7233 case S390_AMODE_B12:
7234 case S390_AMODE_BX12:
7235 return s390_emit_STH(buf, r, x, b, d);
7236
7237 case S390_AMODE_B20:
7238 case S390_AMODE_BX20:
7239 return s390_emit_STHY(buf, r, x, b, DISP20(d));
7240 }
7241 break;
7242
7243 case 4:
7244 switch (dst->tag) {
7245 case S390_AMODE_B12:
7246 case S390_AMODE_BX12:
7247 return s390_emit_ST(buf, r, x, b, d);
7248
7249 case S390_AMODE_B20:
7250 case S390_AMODE_BX20:
7251 return s390_emit_STY(buf, r, x, b, DISP20(d));
7252 }
7253 break;
7254
7255 case 8:
7256 return s390_emit_STG(buf, r, x, b, DISP20(d));
7257
7258 default:
7259 break;
7260 }
7261
7262 vpanic("s390_insn_store_emit");
7263 }
7264
7265
7266 static UChar *
s390_insn_move_emit(UChar * buf,const s390_insn * insn)7267 s390_insn_move_emit(UChar *buf, const s390_insn *insn)
7268 {
7269 UInt dst, src;
7270 HRegClass dst_class, src_class;
7271
7272 dst = hregNumber(insn->variant.move.dst);
7273 src = hregNumber(insn->variant.move.src);
7274
7275 dst_class = hregClass(insn->variant.move.dst);
7276 src_class = hregClass(insn->variant.move.src);
7277
7278 if (dst_class == src_class) {
7279 if (dst_class == HRcInt64)
7280 return s390_emit_LGR(buf, dst, src);
7281 if (dst_class == HRcFlt64)
7282 return s390_emit_LDR(buf, dst, src);
7283 } else {
7284 if (dst_class == HRcFlt64 && src_class == HRcInt64) {
7285 if (insn->size == 4) {
7286 buf = s390_emit_SLLG(buf, R0, src, 0, DISP20(32)); /* r0 = src << 32 */
7287 return s390_emit_LDGRw(buf, dst, R0);
7288 } else {
7289 return s390_emit_LDGRw(buf, dst, src);
7290 }
7291 }
7292 if (dst_class == HRcInt64 && src_class == HRcFlt64) {
7293 if (insn->size == 4) {
7294 buf = s390_emit_LGDRw(buf, dst, src);
7295 return s390_emit_SRLG(buf, dst, dst, 0, DISP20(32)); /* dst >>= 32 */
7296 } else {
7297 return s390_emit_LGDRw(buf, dst, src);
7298 }
7299 }
7300 /* A move between floating point registers and general purpose
7301 registers of different size should never occur and indicates
7302 an error elsewhere. */
7303 }
7304
7305 vpanic("s390_insn_move_emit");
7306 }
7307
7308
7309 static UChar *
s390_insn_memcpy_emit(UChar * buf,const s390_insn * insn)7310 s390_insn_memcpy_emit(UChar *buf, const s390_insn *insn)
7311 {
7312 s390_amode *dst = insn->variant.memcpy.dst;
7313 s390_amode *src = insn->variant.memcpy.src;
7314
7315 return s390_emit_MVC(buf, insn->size - 1, hregNumber(dst->b), dst->d,
7316 hregNumber(src->b), src->d);
7317 }
7318
7319
7320 static UChar *
s390_insn_load_immediate_emit(UChar * buf,const s390_insn * insn)7321 s390_insn_load_immediate_emit(UChar *buf, const s390_insn *insn)
7322 {
7323 UInt r;
7324 ULong value = insn->variant.load_immediate.value;
7325
7326 r = hregNumber(insn->variant.load_immediate.dst);
7327
7328 if (hregClass(insn->variant.load_immediate.dst) == HRcFlt64) {
7329 vassert(value == 0);
7330 switch (insn->size) {
7331 case 4: return s390_emit_LZER(buf, r, value);
7332 case 8: return s390_emit_LZDR(buf, r, value);
7333 }
7334 vpanic("s390_insn_load_immediate_emit");
7335 }
7336
7337 switch (insn->size) {
7338 case 1:
7339 case 2:
7340 /* Load the immediate values as a 4 byte value. That does not hurt as
7341 those extra bytes will not be looked at. Fall through .... */
7342 case 4:
7343 return s390_emit_load_32imm(buf, r, value);
7344
7345 case 8:
7346 return s390_emit_load_64imm(buf, r, value);
7347 }
7348
7349 vpanic("s390_insn_load_immediate_emit");
7350 }
7351
7352
7353 /* There is no easy way to do ALU operations on 1-byte or 2-byte operands.
7354 So we simply perform a 4-byte operation. Doing so uses possibly undefined
7355 bits and produces an undefined result in those extra bit positions. But
7356 upstream does not look at those positions, so this is OK. */
7357 static UChar *
s390_insn_alu_emit(UChar * buf,const s390_insn * insn)7358 s390_insn_alu_emit(UChar *buf, const s390_insn *insn)
7359 {
7360 s390_opnd_RMI op2;
7361 UInt dst;
7362
7363 dst = hregNumber(insn->variant.alu.dst);
7364 op2 = insn->variant.alu.op2;
7365
7366 /* Second operand is in a register */
7367 if (op2.tag == S390_OPND_REG) {
7368 UInt r2 = hregNumber(op2.variant.reg);
7369
7370 switch (insn->size) {
7371 case 1:
7372 case 2:
7373 case 4:
7374 switch (insn->variant.alu.tag) {
7375 case S390_ALU_ADD: return s390_emit_AR(buf, dst, r2);
7376 case S390_ALU_SUB: return s390_emit_SR(buf, dst, r2);
7377 case S390_ALU_MUL: return s390_emit_MSR(buf, dst, r2);
7378 case S390_ALU_AND: return s390_emit_NR(buf, dst, r2);
7379 case S390_ALU_OR: return s390_emit_OR(buf, dst, r2);
7380 case S390_ALU_XOR: return s390_emit_XR(buf, dst, r2);
7381 case S390_ALU_LSH: return s390_emit_SLL(buf, dst, r2, 0);
7382 case S390_ALU_RSH: return s390_emit_SRL(buf, dst, r2, 0);
7383 case S390_ALU_RSHA: return s390_emit_SRA(buf, dst, r2, 0);
7384 }
7385 goto fail;
7386
7387 case 8:
7388 switch (insn->variant.alu.tag) {
7389 case S390_ALU_ADD: return s390_emit_AGR(buf, dst, r2);
7390 case S390_ALU_SUB: return s390_emit_SGR(buf, dst, r2);
7391 case S390_ALU_MUL: return s390_emit_MSGR(buf, dst, r2);
7392 case S390_ALU_AND: return s390_emit_NGR(buf, dst, r2);
7393 case S390_ALU_OR: return s390_emit_OGR(buf, dst, r2);
7394 case S390_ALU_XOR: return s390_emit_XGR(buf, dst, r2);
7395 case S390_ALU_LSH: return s390_emit_SLLG(buf, dst, dst, r2, DISP20(0));
7396 case S390_ALU_RSH: return s390_emit_SRLG(buf, dst, dst, r2, DISP20(0));
7397 case S390_ALU_RSHA: return s390_emit_SRAG(buf, dst, dst, r2, DISP20(0));
7398 }
7399 goto fail;
7400 }
7401 goto fail;
7402 }
7403
7404 /* 2nd operand is in memory */
7405 if (op2.tag == S390_OPND_AMODE) {
7406 UInt b, x, d;
7407 const s390_amode *src = op2.variant.am;
7408
7409 b = hregNumber(src->b);
7410 x = hregNumber(src->x); /* 0 for B12 and B20 */
7411 d = src->d;
7412
7413 /* Shift operands are special here as there are no opcodes that
7414 allow a memory operand. So we first load the 2nd operand into
7415 some register. R0 is used to save restore the contents of the
7416 chosen register.. */
7417
7418 if (insn->variant.alu.tag == S390_ALU_LSH ||
7419 insn->variant.alu.tag == S390_ALU_RSH ||
7420 insn->variant.alu.tag == S390_ALU_RSHA) {
7421 UInt b2;
7422
7423 /* Choose a register (other than DST or R0) into which to stick the
7424 shift amount. The following works because r15 is reserved and
7425 thusly dst != 15. */
7426 vassert(dst != 15); /* extra paranoia */
7427 b2 = (dst + 1) % 16;
7428
7429 buf = s390_emit_LGR(buf, R0, b2); /* save */
7430
7431 /* Loading SRC to B2 does not modify R0. */
7432 buf = s390_emit_load_mem(buf, insn->size, b2, src);
7433
7434 if (insn->size == 8) {
7435 switch (insn->variant.alu.tag) {
7436 case S390_ALU_LSH:
7437 buf = s390_emit_SLLG(buf, dst, dst, b2, DISP20(0));
7438 break;
7439 case S390_ALU_RSH:
7440 buf = s390_emit_SRLG(buf, dst, dst, b2, DISP20(0));
7441 break;
7442 case S390_ALU_RSHA:
7443 buf = s390_emit_SRAG(buf, dst, dst, b2, DISP20(0));
7444 break;
7445 default: /* unreachable */
7446 goto fail;
7447 }
7448 } else {
7449 switch (insn->variant.alu.tag) {
7450 case S390_ALU_LSH:
7451 buf = s390_emit_SLL(buf, dst, b2, 0);
7452 break;
7453 case S390_ALU_RSH:
7454 buf = s390_emit_SRL(buf, dst, b2, 0);
7455 break;
7456 case S390_ALU_RSHA:
7457 buf = s390_emit_SRA(buf, dst, b2, 0);
7458 break;
7459 default: /* unreachable */
7460 goto fail;
7461 }
7462 }
7463 return s390_emit_LGR(buf, b2, R0); /* restore */
7464 }
7465
7466 switch (insn->size) {
7467 case 1:
7468 /* Move the byte from memory into scratch register r0 */
7469 buf = s390_emit_load_mem(buf, 1, R0, src);
7470
7471 switch (insn->variant.alu.tag) {
7472 case S390_ALU_ADD: return s390_emit_AR(buf, dst, R0);
7473 case S390_ALU_SUB: return s390_emit_SR(buf, dst, R0);
7474 case S390_ALU_MUL: return s390_emit_MSR(buf, dst, R0);
7475 case S390_ALU_AND: return s390_emit_NR(buf, dst, R0);
7476 case S390_ALU_OR: return s390_emit_OR(buf, dst, R0);
7477 case S390_ALU_XOR: return s390_emit_XR(buf, dst, R0);
7478 case S390_ALU_LSH:
7479 case S390_ALU_RSH:
7480 case S390_ALU_RSHA: ; /* avoid GCC warning */
7481 }
7482 goto fail;
7483
7484 case 2:
7485 switch (src->tag) {
7486 case S390_AMODE_B12:
7487 case S390_AMODE_BX12:
7488 switch (insn->variant.alu.tag) {
7489 case S390_ALU_ADD:
7490 return s390_emit_AH(buf, dst, x, b, d);
7491
7492 case S390_ALU_SUB:
7493 return s390_emit_SH(buf, dst, x, b, d);
7494
7495 case S390_ALU_MUL:
7496 return s390_emit_MH(buf, dst, x, b, d);
7497
7498 /* For bitwise operations: Move two bytes from memory into scratch
7499 register r0; then perform operation */
7500 case S390_ALU_AND:
7501 buf = s390_emit_LH(buf, R0, x, b, d);
7502 return s390_emit_NR(buf, dst, R0);
7503
7504 case S390_ALU_OR:
7505 buf = s390_emit_LH(buf, R0, x, b, d);
7506 return s390_emit_OR(buf, dst, R0);
7507
7508 case S390_ALU_XOR:
7509 buf = s390_emit_LH(buf, R0, x, b, d);
7510 return s390_emit_XR(buf, dst, R0);
7511
7512 case S390_ALU_LSH:
7513 case S390_ALU_RSH:
7514 case S390_ALU_RSHA: ; /* avoid GCC warning */
7515 }
7516 goto fail;
7517
7518 case S390_AMODE_B20:
7519 case S390_AMODE_BX20:
7520 switch (insn->variant.alu.tag) {
7521 case S390_ALU_ADD:
7522 return s390_emit_AHY(buf, dst, x, b, DISP20(d));
7523
7524 case S390_ALU_SUB:
7525 return s390_emit_SHY(buf, dst, x, b, DISP20(d));
7526
7527 case S390_ALU_MUL:
7528 return s390_emit_MHYw(buf, dst, x, b, DISP20(d));
7529
7530 /* For bitwise operations: Move two bytes from memory into scratch
7531 register r0; then perform operation */
7532 case S390_ALU_AND:
7533 buf = s390_emit_LHY(buf, R0, x, b, DISP20(d));
7534 return s390_emit_NR(buf, dst, R0);
7535
7536 case S390_ALU_OR:
7537 buf = s390_emit_LHY(buf, R0, x, b, DISP20(d));
7538 return s390_emit_OR(buf, dst, R0);
7539
7540 case S390_ALU_XOR:
7541 buf = s390_emit_LHY(buf, R0, x, b, DISP20(d));
7542 return s390_emit_XR(buf, dst, R0);
7543
7544 case S390_ALU_LSH:
7545 case S390_ALU_RSH:
7546 case S390_ALU_RSHA: ; /* avoid GCC warning */
7547 }
7548 goto fail;
7549 }
7550 goto fail;
7551
7552 case 4:
7553 switch (src->tag) {
7554 case S390_AMODE_B12:
7555 case S390_AMODE_BX12:
7556 switch (insn->variant.alu.tag) {
7557 case S390_ALU_ADD: return s390_emit_A(buf, dst, x, b, d);
7558 case S390_ALU_SUB: return s390_emit_S(buf, dst, x, b, d);
7559 case S390_ALU_MUL: return s390_emit_MS(buf, dst, x, b, d);
7560 case S390_ALU_AND: return s390_emit_N(buf, dst, x, b, d);
7561 case S390_ALU_OR: return s390_emit_O(buf, dst, x, b, d);
7562 case S390_ALU_XOR: return s390_emit_X(buf, dst, x, b, d);
7563 case S390_ALU_LSH:
7564 case S390_ALU_RSH:
7565 case S390_ALU_RSHA: ; /* avoid GCC warning */
7566 }
7567 goto fail;
7568
7569 case S390_AMODE_B20:
7570 case S390_AMODE_BX20:
7571 switch (insn->variant.alu.tag) {
7572 case S390_ALU_ADD: return s390_emit_AY(buf, dst, x, b, DISP20(d));
7573 case S390_ALU_SUB: return s390_emit_SY(buf, dst, x, b, DISP20(d));
7574 case S390_ALU_MUL: return s390_emit_MSY(buf, dst, x, b, DISP20(d));
7575 case S390_ALU_AND: return s390_emit_NY(buf, dst, x, b, DISP20(d));
7576 case S390_ALU_OR: return s390_emit_OY(buf, dst, x, b, DISP20(d));
7577 case S390_ALU_XOR: return s390_emit_XY(buf, dst, x, b, DISP20(d));
7578 case S390_ALU_LSH:
7579 case S390_ALU_RSH:
7580 case S390_ALU_RSHA: ; /* avoid GCC warning */
7581 }
7582 goto fail;
7583 }
7584 goto fail;
7585
7586 case 8:
7587 switch (insn->variant.alu.tag) {
7588 case S390_ALU_ADD: return s390_emit_AG(buf, dst, x, b, DISP20(d));
7589 case S390_ALU_SUB: return s390_emit_SG(buf, dst, x, b, DISP20(d));
7590 case S390_ALU_MUL: return s390_emit_MSG(buf, dst, x, b, DISP20(d));
7591 case S390_ALU_AND: return s390_emit_NG(buf, dst, x, b, DISP20(d));
7592 case S390_ALU_OR: return s390_emit_OG(buf, dst, x, b, DISP20(d));
7593 case S390_ALU_XOR: return s390_emit_XG(buf, dst, x, b, DISP20(d));
7594 case S390_ALU_LSH:
7595 case S390_ALU_RSH:
7596 case S390_ALU_RSHA: ; /* avoid GCC warning */
7597 }
7598 goto fail;
7599 }
7600 goto fail;
7601 }
7602
7603 /* 2nd operand is an immediate value */
7604 if (op2.tag == S390_OPND_IMMEDIATE) {
7605 ULong value;
7606
7607 /* No masking of the value is required as it is not sign extended */
7608 value = op2.variant.imm;
7609
7610 switch (insn->size) {
7611 case 1:
7612 case 2:
7613 /* There is no 1-byte opcode. Do the computation in
7614 2 bytes. The extra byte will be ignored. */
7615 switch (insn->variant.alu.tag) {
7616 case S390_ALU_ADD:
7617 return s390_emit_AHI(buf, dst, value);
7618
7619 case S390_ALU_SUB:
7620 return s390_emit_SLFIw(buf, dst, value);
7621
7622 case S390_ALU_MUL:
7623 return s390_emit_MHI(buf, dst, value);
7624
7625 case S390_ALU_AND: return s390_emit_NILL(buf, dst, value);
7626 case S390_ALU_OR: return s390_emit_OILL(buf, dst, value);
7627 case S390_ALU_XOR:
7628 /* There is no XILL instruction. Load the immediate value into
7629 R0 and combine with the destination register. */
7630 buf = s390_emit_LHI(buf, R0, value);
7631 return s390_emit_XR(buf, dst, R0);
7632
7633 case S390_ALU_LSH:
7634 return s390_emit_SLL(buf, dst, 0, value);
7635
7636 case S390_ALU_RSH:
7637 return s390_emit_SRL(buf, dst, 0, value);
7638
7639 case S390_ALU_RSHA:
7640 return s390_emit_SRA(buf, dst, 0, value);
7641 }
7642 goto fail;
7643
7644 case 4:
7645 switch (insn->variant.alu.tag) {
7646 case S390_ALU_ADD:
7647 if (uint_fits_signed_16bit(value)) {
7648 return s390_emit_AHI(buf, dst, value);
7649 }
7650 return s390_emit_AFIw(buf, dst, value);
7651
7652 case S390_ALU_SUB: return s390_emit_SLFIw(buf, dst, value);
7653 case S390_ALU_MUL: return s390_emit_MSFIw(buf, dst, value);
7654 case S390_ALU_AND: return s390_emit_NILFw(buf, dst, value);
7655 case S390_ALU_OR: return s390_emit_OILFw(buf, dst, value);
7656 case S390_ALU_XOR: return s390_emit_XILFw(buf, dst, value);
7657 case S390_ALU_LSH: return s390_emit_SLL(buf, dst, 0, value);
7658 case S390_ALU_RSH: return s390_emit_SRL(buf, dst, 0, value);
7659 case S390_ALU_RSHA: return s390_emit_SRA(buf, dst, 0, value);
7660 }
7661 goto fail;
7662
7663 case 8:
7664 switch (insn->variant.alu.tag) {
7665 case S390_ALU_ADD:
7666 if (ulong_fits_signed_16bit(value)) {
7667 return s390_emit_AGHI(buf, dst, value);
7668 }
7669 if (ulong_fits_signed_32bit(value) && s390_host_has_eimm) {
7670 return s390_emit_AGFI(buf, dst, value);
7671 }
7672 /* Load constant into R0 then add */
7673 buf = s390_emit_load_64imm(buf, R0, value);
7674 return s390_emit_AGR(buf, dst, R0);
7675
7676 case S390_ALU_SUB:
7677 if (ulong_fits_unsigned_32bit(value)) {
7678 return s390_emit_SLGFIw(buf, dst, value);
7679 }
7680 /* Load value into R0; then subtract from destination reg */
7681 buf = s390_emit_load_64imm(buf, R0, value);
7682 return s390_emit_SGR(buf, dst, R0);
7683
7684 case S390_ALU_MUL:
7685 if (ulong_fits_signed_32bit(value) && s390_host_has_gie) {
7686 return s390_emit_MSGFI(buf, dst, value);
7687 }
7688 /* Load constant into R0 then add */
7689 buf = s390_emit_load_64imm(buf, R0, value);
7690 return s390_emit_MSGR(buf, dst, R0);
7691
7692 /* Do it in two steps: upper half [0:31] and lower half [32:63] */
7693 case S390_ALU_AND:
7694 if (s390_host_has_eimm) {
7695 buf = s390_emit_NIHF(buf, dst, value >> 32);
7696 return s390_emit_NILF(buf, dst, value & 0xFFFFFFFF);
7697 }
7698 /* Load value into R0; then combine with destination reg */
7699 buf = s390_emit_load_64imm(buf, R0, value);
7700 return s390_emit_NGR(buf, dst, R0);
7701
7702 case S390_ALU_OR:
7703 if (s390_host_has_eimm) {
7704 buf = s390_emit_OIHF(buf, dst, value >> 32);
7705 return s390_emit_OILF(buf, dst, value & 0xFFFFFFFF);
7706 }
7707 /* Load value into R0; then combine with destination reg */
7708 buf = s390_emit_load_64imm(buf, R0, value);
7709 return s390_emit_OGR(buf, dst, R0);
7710
7711 case S390_ALU_XOR:
7712 if (s390_host_has_eimm) {
7713 buf = s390_emit_XIHF(buf, dst, value >> 32);
7714 return s390_emit_XILF(buf, dst, value & 0xFFFFFFFF);
7715 }
7716 /* Load value into R0; then combine with destination reg */
7717 buf = s390_emit_load_64imm(buf, R0, value);
7718 return s390_emit_XGR(buf, dst, R0);
7719
7720 /* No special considerations for long displacement here. Only the six
7721 least significant bits of VALUE will be taken; all other bits are
7722 ignored. So the DH2 bits are irrelevant and do not influence the
7723 shift operation, independent of whether long-displacement is available
7724 or not. */
7725 case S390_ALU_LSH: return s390_emit_SLLG(buf, dst, dst, 0, DISP20(value));
7726 case S390_ALU_RSH: return s390_emit_SRLG(buf, dst, dst, 0, DISP20(value));
7727 case S390_ALU_RSHA: return s390_emit_SRAG(buf, dst, dst, 0, DISP20(value));
7728 }
7729 goto fail;
7730 }
7731 goto fail;
7732 }
7733
7734 fail:
7735 vpanic("s390_insn_alu_emit");
7736 }
7737
7738
7739 static UChar *
s390_widen_emit(UChar * buf,const s390_insn * insn,UInt from_size,Bool sign_extend)7740 s390_widen_emit(UChar *buf, const s390_insn *insn, UInt from_size,
7741 Bool sign_extend)
7742 {
7743 s390_opnd_RMI opnd = insn->variant.unop.src;
7744
7745 switch (opnd.tag) {
7746 case S390_OPND_REG: {
7747 UChar r1 = hregNumber(insn->variant.unop.dst);
7748 UChar r2 = hregNumber(opnd.variant.reg);
7749
7750 switch (from_size) {
7751 case 1:
7752 /* Widening to a half-word is implemented like widening to a word
7753 because the upper half-word will not be looked at. */
7754 if (insn->size == 4 || insn->size == 2) { /* 8 --> 32 8 --> 16 */
7755 if (sign_extend)
7756 return s390_emit_LBRw(buf, r1, r2);
7757 else
7758 return s390_emit_LLCRw(buf, r1, r2);
7759 }
7760 if (insn->size == 8) { /* 8 --> 64 */
7761 if (sign_extend)
7762 return s390_emit_LGBRw(buf, r1, r2);
7763 else
7764 return s390_emit_LLGCRw(buf, r1, r2);
7765 }
7766 goto fail;
7767
7768 case 2:
7769 if (insn->size == 4) { /* 16 --> 32 */
7770 if (sign_extend)
7771 return s390_emit_LHRw(buf, r1, r2);
7772 else
7773 return s390_emit_LLHRw(buf, r1, r2);
7774 }
7775 if (insn->size == 8) { /* 16 --> 64 */
7776 if (sign_extend)
7777 return s390_emit_LGHRw(buf, r1, r2);
7778 else
7779 return s390_emit_LLGHRw(buf, r1, r2);
7780 }
7781 goto fail;
7782
7783 case 4:
7784 if (insn->size == 8) { /* 32 --> 64 */
7785 if (sign_extend)
7786 return s390_emit_LGFR(buf, r1, r2);
7787 else
7788 return s390_emit_LLGFR(buf, r1, r2);
7789 }
7790 goto fail;
7791
7792 default: /* unexpected "from" size */
7793 goto fail;
7794 }
7795 }
7796
7797 case S390_OPND_AMODE: {
7798 UChar r1 = hregNumber(insn->variant.unop.dst);
7799 const s390_amode *src = opnd.variant.am;
7800 UChar b = hregNumber(src->b);
7801 UChar x = hregNumber(src->x);
7802 Int d = src->d;
7803
7804 switch (from_size) {
7805 case 1:
7806 if (insn->size == 4 || insn->size == 2) {
7807 if (sign_extend)
7808 return s390_emit_LB(buf, r1, x, b, DISP20(d));
7809 else
7810 return s390_emit_LLCw(buf, r1, x, b, DISP20(d));
7811 }
7812 if (insn->size == 8) {
7813 if (sign_extend)
7814 return s390_emit_LGB(buf, r1, x, b, DISP20(d));
7815 else
7816 return s390_emit_LLGC(buf, r1, x, b, DISP20(d));
7817 }
7818 goto fail;
7819
7820 case 2:
7821 if (insn->size == 4) { /* 16 --> 32 */
7822 if (sign_extend == 0)
7823 return s390_emit_LLHw(buf, r1, x, b, DISP20(d));
7824
7825 switch (src->tag) {
7826 case S390_AMODE_B12:
7827 case S390_AMODE_BX12:
7828 return s390_emit_LH(buf, r1, x, b, d);
7829
7830 case S390_AMODE_B20:
7831 case S390_AMODE_BX20:
7832 return s390_emit_LHY(buf, r1, x, b, DISP20(d));
7833 }
7834 goto fail;
7835 }
7836 if (insn->size == 8) { /* 16 --> 64 */
7837 if (sign_extend)
7838 return s390_emit_LGH(buf, r1, x, b, DISP20(d));
7839 else
7840 return s390_emit_LLGH(buf, r1, x, b, DISP20(d));
7841 }
7842 goto fail;
7843
7844 case 4:
7845 if (insn->size == 8) { /* 32 --> 64 */
7846 if (sign_extend)
7847 return s390_emit_LGF(buf, r1, x, b, DISP20(d));
7848 else
7849 return s390_emit_LLGF(buf, r1, x, b, DISP20(d));
7850 }
7851 goto fail;
7852
7853 default: /* unexpected "from" size */
7854 goto fail;
7855 }
7856 }
7857
7858 case S390_OPND_IMMEDIATE: {
7859 UChar r1 = hregNumber(insn->variant.unop.dst);
7860 ULong value = opnd.variant.imm;
7861
7862 switch (from_size) {
7863 case 1:
7864 if (insn->size == 4 || insn->size == 2) { /* 8 --> 32 8 --> 16 */
7865 if (sign_extend) {
7866 /* host can do the sign extension to 16-bit; LHI does the rest */
7867 return s390_emit_LHI(buf, r1, (Short)(Char)(UChar)value);
7868 } else {
7869 return s390_emit_LHI(buf, r1, value);
7870 }
7871 }
7872 if (insn->size == 8) { /* 8 --> 64 */
7873 if (sign_extend) {
7874 /* host can do the sign extension to 16-bit; LGHI does the rest */
7875 return s390_emit_LGHI(buf, r1, (Short)(Char)(UChar)value);
7876 } else {
7877 return s390_emit_LGHI(buf, r1, value);
7878 }
7879 }
7880 goto fail;
7881
7882 case 2:
7883 if (insn->size == 4) { /* 16 --> 32 */
7884 return s390_emit_LHI(buf, r1, value);
7885 }
7886 if (insn->size == 8) { /* 16 --> 64 */
7887 if (sign_extend)
7888 return s390_emit_LGHI(buf, r1, value);
7889 else
7890 return s390_emit_LLILL(buf, r1, value);
7891 }
7892 goto fail;
7893
7894 case 4:
7895 if (insn->size == 8) { /* 32 --> 64 */
7896 if (sign_extend)
7897 return s390_emit_LGFIw(buf, r1, value);
7898 else
7899 return s390_emit_LLILFw(buf, r1, value);
7900 }
7901 goto fail;
7902
7903 default: /* unexpected "from" size */
7904 goto fail;
7905 }
7906 }
7907 }
7908
7909 fail:
7910 vpanic("s390_widen_emit");
7911 }
7912
7913
7914 static UChar *
s390_negate_emit(UChar * buf,const s390_insn * insn)7915 s390_negate_emit(UChar *buf, const s390_insn *insn)
7916 {
7917 s390_opnd_RMI opnd;
7918
7919 opnd = insn->variant.unop.src;
7920
7921 switch (opnd.tag) {
7922 case S390_OPND_REG: {
7923 UChar r1 = hregNumber(insn->variant.unop.dst);
7924 UChar r2 = hregNumber(opnd.variant.reg);
7925
7926 switch (insn->size) {
7927 case 1:
7928 case 2:
7929 case 4:
7930 return s390_emit_LCR(buf, r1, r2);
7931
7932 case 8:
7933 return s390_emit_LCGR(buf, r1, r2);
7934
7935 default:
7936 goto fail;
7937 }
7938 }
7939
7940 case S390_OPND_AMODE: {
7941 UChar r1 = hregNumber(insn->variant.unop.dst);
7942
7943 /* Load bytes into scratch register R0, then negate */
7944 buf = s390_emit_load_mem(buf, insn->size, R0, opnd.variant.am);
7945
7946 switch (insn->size) {
7947 case 1:
7948 case 2:
7949 case 4:
7950 return s390_emit_LCR(buf, r1, R0);
7951
7952 case 8:
7953 return s390_emit_LCGR(buf, r1, R0);
7954
7955 default:
7956 goto fail;
7957 }
7958 }
7959
7960 case S390_OPND_IMMEDIATE: {
7961 UChar r1 = hregNumber(insn->variant.unop.dst);
7962 ULong value = opnd.variant.imm;
7963
7964 value = ~value + 1; /* two's complement */
7965
7966 switch (insn->size) {
7967 case 1:
7968 case 2:
7969 /* Load the immediate values as a 4 byte value. That does not hurt as
7970 those extra bytes will not be looked at. Fall through .... */
7971 case 4:
7972 return s390_emit_load_32imm(buf, r1, value);
7973
7974 case 8:
7975 return s390_emit_load_64imm(buf, r1, value);
7976
7977 default:
7978 goto fail;
7979 }
7980 }
7981 }
7982
7983 fail:
7984 vpanic("s390_negate_emit");
7985 }
7986
7987
7988 static UChar *
s390_insn_unop_emit(UChar * buf,const s390_insn * insn)7989 s390_insn_unop_emit(UChar *buf, const s390_insn *insn)
7990 {
7991 switch (insn->variant.unop.tag) {
7992 case S390_ZERO_EXTEND_8: return s390_widen_emit(buf, insn, 1, 0);
7993 case S390_ZERO_EXTEND_16: return s390_widen_emit(buf, insn, 2, 0);
7994 case S390_ZERO_EXTEND_32: return s390_widen_emit(buf, insn, 4, 0);
7995
7996 case S390_SIGN_EXTEND_8: return s390_widen_emit(buf, insn, 1, 1);
7997 case S390_SIGN_EXTEND_16: return s390_widen_emit(buf, insn, 2, 1);
7998 case S390_SIGN_EXTEND_32: return s390_widen_emit(buf, insn, 4, 1);
7999
8000 case S390_NEGATE: return s390_negate_emit(buf, insn);
8001 }
8002
8003 vpanic("s390_insn_unop_emit");
8004 }
8005
8006
8007 /* Only 4-byte and 8-byte operands are handled. 1-byte and 2-byte
8008 comparisons will have been converted to 4-byte comparisons in
8009 s390_isel_cc and should not occur here. */
8010 static UChar *
s390_insn_test_emit(UChar * buf,const s390_insn * insn)8011 s390_insn_test_emit(UChar *buf, const s390_insn *insn)
8012 {
8013 s390_opnd_RMI opnd;
8014
8015 opnd = insn->variant.test.src;
8016
8017 switch (opnd.tag) {
8018 case S390_OPND_REG: {
8019 UInt reg = hregNumber(opnd.variant.reg);
8020
8021 switch (insn->size) {
8022 case 4:
8023 return s390_emit_LTR(buf, reg, reg);
8024
8025 case 8:
8026 return s390_emit_LTGR(buf, reg, reg);
8027
8028 default:
8029 goto fail;
8030 }
8031 }
8032
8033 case S390_OPND_AMODE: {
8034 const s390_amode *am = opnd.variant.am;
8035 UChar b = hregNumber(am->b);
8036 UChar x = hregNumber(am->x);
8037 Int d = am->d;
8038
8039 switch (insn->size) {
8040 case 4:
8041 return s390_emit_LTw(buf, R0, x, b, DISP20(d));
8042
8043 case 8:
8044 return s390_emit_LTGw(buf, R0, x, b, DISP20(d));
8045
8046 default:
8047 goto fail;
8048 }
8049 }
8050
8051 case S390_OPND_IMMEDIATE: {
8052 ULong value = opnd.variant.imm;
8053
8054 switch (insn->size) {
8055 case 4:
8056 buf = s390_emit_load_32imm(buf, R0, value);
8057 return s390_emit_LTR(buf, R0, R0);
8058
8059 case 8:
8060 buf = s390_emit_load_64imm(buf, R0, value);
8061 return s390_emit_LTGR(buf, R0, R0);
8062
8063 default:
8064 goto fail;
8065 }
8066 }
8067
8068 default:
8069 goto fail;
8070 }
8071
8072 fail:
8073 vpanic("s390_insn_test_emit");
8074 }
8075
8076
8077 static UChar *
s390_insn_cc2bool_emit(UChar * buf,const s390_insn * insn)8078 s390_insn_cc2bool_emit(UChar *buf, const s390_insn *insn)
8079 {
8080 UChar r1 = hregNumber(insn->variant.cc2bool.dst);
8081 s390_cc_t cond = insn->variant.cc2bool.cond;
8082
8083 /* Make the destination register be 1 or 0, depending on whether
8084 the relevant condition holds. A 64-bit value is computed. */
8085 if (cond == S390_CC_ALWAYS)
8086 return s390_emit_LGHI(buf, r1, 1); /* r1 = 1 */
8087
8088 buf = s390_emit_load_cc(buf, r1); /* r1 = cc */
8089 buf = s390_emit_LGHI(buf, R0, cond); /* r0 = mask */
8090 buf = s390_emit_SLLG(buf, r1, R0, r1, DISP20(0)); /* r1 = mask << cc */
8091 buf = s390_emit_SRLG(buf, r1, r1, 0, DISP20(3)); /* r1 = r1 >> 3 */
8092 buf = s390_emit_NILL(buf, r1, 1); /* r1 = r1 & 0x1 */
8093
8094 return buf;
8095 }
8096
8097
8098 /* Only 4-byte and 8-byte operands are handled. */
8099 static UChar *
s390_insn_cas_emit(UChar * buf,const s390_insn * insn)8100 s390_insn_cas_emit(UChar *buf, const s390_insn *insn)
8101 {
8102 UChar r1, r3, b, old;
8103 Int d;
8104 s390_amode *am;
8105
8106 r1 = hregNumber(insn->variant.cas.op1); /* expected value */
8107 r3 = hregNumber(insn->variant.cas.op3);
8108 old= hregNumber(insn->variant.cas.old_mem);
8109 am = insn->variant.cas.op2;
8110 b = hregNumber(am->b);
8111 d = am->d;
8112
8113 vassert(am->tag == S390_AMODE_B12 || am->tag == S390_AMODE_B20);
8114
8115 switch (insn->size) {
8116 case 4:
8117 /* r1 must not be overwritten. So copy it to R0 and let CS clobber it */
8118 buf = s390_emit_LR(buf, R0, r1);
8119 if (am->tag == S390_AMODE_B12)
8120 buf = s390_emit_CS(buf, R0, r3, b, d);
8121 else
8122 buf = s390_emit_CSY(buf, R0, r3, b, DISP20(d));
8123 /* Now copy R0 which has the old memory value to OLD */
8124 return s390_emit_LR(buf, old, R0);
8125
8126 case 8:
8127 /* r1 must not be overwritten. So copy it to R0 and let CS clobber it */
8128 buf = s390_emit_LGR(buf, R0, r1);
8129 buf = s390_emit_CSG(buf, R0, r3, b, DISP20(d));
8130 /* Now copy R0 which has the old memory value to OLD */
8131 return s390_emit_LGR(buf, old, R0);
8132
8133 default:
8134 goto fail;
8135 }
8136
8137 fail:
8138 vpanic("s390_insn_cas_emit");
8139 }
8140
8141
8142 /* Only 4-byte and 8-byte operands are handled. */
8143 static UChar *
s390_insn_cdas_emit(UChar * buf,const s390_insn * insn)8144 s390_insn_cdas_emit(UChar *buf, const s390_insn *insn)
8145 {
8146 UChar r1, r1p1, r3, /*r3p1,*/ b, old_high, old_low, scratch;
8147 Int d;
8148 s390_amode *am;
8149 s390_cdas *cdas = insn->variant.cdas.details;
8150
8151 r1 = hregNumber(cdas->op1_high); /* expected value */
8152 r1p1 = hregNumber(cdas->op1_low); /* expected value */
8153 r3 = hregNumber(cdas->op3_high);
8154 /* r3p1 = hregNumber(cdas->op3_low); */ /* unused */
8155 old_high = hregNumber(cdas->old_mem_high);
8156 old_low = hregNumber(cdas->old_mem_low);
8157 scratch = hregNumber(cdas->scratch);
8158 am = cdas->op2;
8159 b = hregNumber(am->b);
8160 d = am->d;
8161
8162 vassert(scratch == 1);
8163 vassert(am->tag == S390_AMODE_B12 || am->tag == S390_AMODE_B20);
8164
8165 switch (insn->size) {
8166 case 4:
8167 /* r1, r1+1 must not be overwritten. So copy them to R0,scratch
8168 and let CDS/CDSY clobber it */
8169 buf = s390_emit_LR(buf, R0, r1);
8170 buf = s390_emit_LR(buf, scratch, r1p1);
8171
8172 if (am->tag == S390_AMODE_B12)
8173 buf = s390_emit_CDS(buf, R0, r3, b, d);
8174 else
8175 buf = s390_emit_CDSY(buf, R0, r3, b, DISP20(d));
8176
8177 /* Now copy R0,scratch which has the old memory value to OLD */
8178 buf = s390_emit_LR(buf, old_high, R0);
8179 buf = s390_emit_LR(buf, old_low, scratch);
8180 return buf;
8181
8182 case 8:
8183 /* r1, r1+1 must not be overwritten. So copy them to R0,scratch
8184 and let CDSG clobber it */
8185 buf = s390_emit_LGR(buf, R0, r1);
8186 buf = s390_emit_LGR(buf, scratch, r1p1);
8187
8188 buf = s390_emit_CDSG(buf, R0, r3, b, DISP20(d));
8189
8190 /* Now copy R0,scratch which has the old memory value to OLD */
8191 buf = s390_emit_LGR(buf, old_high, R0);
8192 buf = s390_emit_LGR(buf, old_low, scratch);
8193 return buf;
8194
8195 default:
8196 goto fail;
8197 }
8198
8199 fail:
8200 vpanic("s390_insn_cdas_emit");
8201 }
8202
8203
8204 /* Only 4-byte and 8-byte comparisons are handled. 1-byte and 2-byte
8205 comparisons will have been converted to 4-byte comparisons in
8206 s390_isel_cc and should not occur here. */
8207 static UChar *
s390_insn_compare_emit(UChar * buf,const s390_insn * insn)8208 s390_insn_compare_emit(UChar *buf, const s390_insn *insn)
8209 {
8210 s390_opnd_RMI op2;
8211 HReg op1;
8212 Bool signed_comparison;
8213
8214 op1 = insn->variant.compare.src1;
8215 op2 = insn->variant.compare.src2;
8216 signed_comparison = insn->variant.compare.signed_comparison;
8217
8218 switch (op2.tag) {
8219 case S390_OPND_REG: {
8220 UInt r1 = hregNumber(op1);
8221 UInt r2 = hregNumber(op2.variant.reg);
8222
8223 switch (insn->size) {
8224 case 4:
8225 if (signed_comparison)
8226 return s390_emit_CR(buf, r1, r2);
8227 else
8228 return s390_emit_CLR(buf, r1, r2);
8229
8230 case 8:
8231 if (signed_comparison)
8232 return s390_emit_CGR(buf, r1, r2);
8233 else
8234 return s390_emit_CLGR(buf, r1, r2);
8235
8236 default:
8237 goto fail;
8238 }
8239 }
8240
8241 case S390_OPND_AMODE: {
8242 UChar r1 = hregNumber(op1);
8243 const s390_amode *am = op2.variant.am;
8244 UChar b = hregNumber(am->b);
8245 UChar x = hregNumber(am->x);
8246 Int d = am->d;
8247
8248 switch (insn->size) {
8249 case 4:
8250 switch (am->tag) {
8251 case S390_AMODE_B12:
8252 case S390_AMODE_BX12:
8253 if (signed_comparison)
8254 return s390_emit_C(buf, r1, x, b, d);
8255 else
8256 return s390_emit_CL(buf, r1, x, b, d);
8257
8258 case S390_AMODE_B20:
8259 case S390_AMODE_BX20:
8260 if (signed_comparison)
8261 return s390_emit_CY(buf, r1, x, b, DISP20(d));
8262 else
8263 return s390_emit_CLY(buf, r1, x, b, DISP20(d));
8264 }
8265 goto fail;
8266
8267 case 8:
8268 if (signed_comparison)
8269 return s390_emit_CG(buf, r1, x, b, DISP20(d));
8270 else
8271 return s390_emit_CLG(buf, r1, x, b, DISP20(d));
8272
8273 default:
8274 goto fail;
8275 }
8276 }
8277
8278 case S390_OPND_IMMEDIATE: {
8279 UChar r1 = hregNumber(op1);
8280 ULong value = op2.variant.imm;
8281
8282 switch (insn->size) {
8283 case 4:
8284 if (signed_comparison)
8285 return s390_emit_CFIw(buf, r1, value);
8286 else
8287 return s390_emit_CLFIw(buf, r1, value);
8288
8289 case 8:
8290 if (s390_host_has_eimm) {
8291 if (signed_comparison) {
8292 if (ulong_fits_signed_32bit(value))
8293 return s390_emit_CGFI(buf, r1, value);
8294 } else {
8295 if (ulong_fits_unsigned_32bit(value))
8296 return s390_emit_CLGFI(buf, r1, value);
8297 }
8298 }
8299 buf = s390_emit_load_64imm(buf, R0, value);
8300 if (signed_comparison)
8301 return s390_emit_CGR(buf, r1, R0);
8302 else
8303 return s390_emit_CLGR(buf, r1, R0);
8304
8305 default:
8306 goto fail;
8307 }
8308 }
8309
8310 default:
8311 goto fail;
8312 }
8313
8314 fail:
8315 vpanic("s390_insn_compare_emit");
8316 }
8317
8318
8319 static UChar *
s390_insn_mul_emit(UChar * buf,const s390_insn * insn)8320 s390_insn_mul_emit(UChar *buf, const s390_insn *insn)
8321 {
8322 s390_opnd_RMI op2;
8323 UChar r1;
8324 Bool signed_multiply;
8325
8326 /* The register number identifying the register pair */
8327 r1 = hregNumber(insn->variant.mul.dst_hi);
8328
8329 op2 = insn->variant.mul.op2;
8330 signed_multiply = insn->tag == S390_INSN_SMUL;
8331
8332 switch (op2.tag) {
8333 case S390_OPND_REG: {
8334 UInt r2 = hregNumber(op2.variant.reg);
8335
8336 switch (insn->size) {
8337 case 1:
8338 case 2:
8339 case 4:
8340 if (signed_multiply)
8341 return s390_emit_MR(buf, r1, r2);
8342 else
8343 return s390_emit_MLR(buf, r1, r2);
8344
8345 case 8:
8346 if (signed_multiply)
8347 vpanic("s390_insn_mul_emit");
8348 else
8349 return s390_emit_MLGR(buf, r1, r2);
8350
8351 default:
8352 goto fail;
8353 }
8354 }
8355
8356 case S390_OPND_AMODE: {
8357 const s390_amode *am = op2.variant.am;
8358 UChar b = hregNumber(am->b);
8359 UChar x = hregNumber(am->x);
8360 Int d = am->d;
8361
8362 switch (insn->size) {
8363 case 1:
8364 case 2:
8365 /* Load bytes into scratch register R0, then multiply */
8366 buf = s390_emit_load_mem(buf, insn->size, R0, am);
8367 if (signed_multiply)
8368 return s390_emit_MR(buf, r1, R0);
8369 else
8370 return s390_emit_MLR(buf, r1, R0);
8371
8372 case 4:
8373 switch (am->tag) {
8374 case S390_AMODE_B12:
8375 case S390_AMODE_BX12:
8376 if (signed_multiply)
8377 return s390_emit_M(buf, r1, x, b, d);
8378 else
8379 return s390_emit_ML(buf, r1, x, b, DISP20(d));
8380
8381 case S390_AMODE_B20:
8382 case S390_AMODE_BX20:
8383 if (signed_multiply)
8384 return s390_emit_MFYw(buf, r1, x, b, DISP20(d));
8385 else
8386 return s390_emit_ML(buf, r1, x, b, DISP20(d));
8387 }
8388 goto fail;
8389
8390 case 8:
8391 if (signed_multiply)
8392 vpanic("s390_insn_mul_emit");
8393 else
8394 return s390_emit_MLG(buf, r1, x, b, DISP20(d));
8395
8396 default:
8397 goto fail;
8398 }
8399 }
8400
8401 case S390_OPND_IMMEDIATE: {
8402 ULong value = op2.variant.imm;
8403
8404 switch (insn->size) {
8405 case 1:
8406 case 2:
8407 case 4:
8408 buf = s390_emit_load_32imm(buf, R0, value);
8409 if (signed_multiply)
8410 return s390_emit_MR(buf, r1, R0);
8411 else
8412 return s390_emit_MLR(buf, r1, R0);
8413
8414 case 8:
8415 buf = s390_emit_load_64imm(buf, R0, value);
8416 if (signed_multiply)
8417 vpanic("s390_insn_mul_emit");
8418 else
8419 return s390_emit_MLGR(buf, r1, R0);
8420
8421 default:
8422 goto fail;
8423 }
8424 }
8425
8426 default:
8427 goto fail;
8428 }
8429
8430 fail:
8431 vpanic("s390_insn_mul_emit");
8432 }
8433
8434
8435 static UChar *
s390_insn_div_emit(UChar * buf,const s390_insn * insn)8436 s390_insn_div_emit(UChar *buf, const s390_insn *insn)
8437 {
8438 s390_opnd_RMI op2;
8439 UChar r1;
8440 Bool signed_divide;
8441
8442 r1 = hregNumber(insn->variant.div.op1_hi);
8443 op2 = insn->variant.div.op2;
8444 signed_divide = insn->tag == S390_INSN_SDIV;
8445
8446 switch (op2.tag) {
8447 case S390_OPND_REG: {
8448 UInt r2 = hregNumber(op2.variant.reg);
8449
8450 switch (insn->size) {
8451 case 4:
8452 if (signed_divide)
8453 return s390_emit_DR(buf, r1, r2);
8454 else
8455 return s390_emit_DLR(buf, r1, r2);
8456
8457 case 8:
8458 if (signed_divide)
8459 vpanic("s390_insn_div_emit");
8460 else
8461 return s390_emit_DLGR(buf, r1, r2);
8462
8463 default:
8464 goto fail;
8465 }
8466 }
8467
8468 case S390_OPND_AMODE: {
8469 const s390_amode *am = op2.variant.am;
8470 UChar b = hregNumber(am->b);
8471 UChar x = hregNumber(am->x);
8472 Int d = am->d;
8473
8474 switch (insn->size) {
8475 case 4:
8476 switch (am->tag) {
8477 case S390_AMODE_B12:
8478 case S390_AMODE_BX12:
8479 if (signed_divide)
8480 return s390_emit_D(buf, r1, x, b, d);
8481 else
8482 return s390_emit_DL(buf, r1, x, b, DISP20(d));
8483
8484 case S390_AMODE_B20:
8485 case S390_AMODE_BX20:
8486 if (signed_divide) {
8487 buf = s390_emit_LY(buf, R0, x, b, DISP20(d));
8488 return s390_emit_DR(buf, r1, R0);
8489 } else
8490 return s390_emit_DL(buf, r1, x, b, DISP20(d));
8491 }
8492 goto fail;
8493
8494 case 8:
8495 if (signed_divide)
8496 vpanic("s390_insn_div_emit");
8497 else
8498 return s390_emit_DLG(buf, r1, x, b, DISP20(d));
8499
8500 default:
8501 goto fail;
8502 }
8503 }
8504
8505 case S390_OPND_IMMEDIATE: {
8506 ULong value = op2.variant.imm;
8507
8508 switch (insn->size) {
8509 case 4:
8510 buf = s390_emit_load_32imm(buf, R0, value);
8511 if (signed_divide)
8512 return s390_emit_DR(buf, r1, R0);
8513 else
8514 return s390_emit_DLR(buf, r1, R0);
8515
8516 case 8:
8517 buf = s390_emit_load_64imm(buf, R0, value);
8518 if (signed_divide)
8519 vpanic("s390_insn_div_emit");
8520 else
8521 return s390_emit_DLGR(buf, r1, R0);
8522
8523 default:
8524 goto fail;
8525 }
8526 }
8527
8528 default:
8529 goto fail;
8530 }
8531
8532 fail:
8533 vpanic("s390_insn_div_emit");
8534 }
8535
8536
8537 static UChar *
s390_insn_divs_emit(UChar * buf,const s390_insn * insn)8538 s390_insn_divs_emit(UChar *buf, const s390_insn *insn)
8539 {
8540 s390_opnd_RMI op2;
8541 UChar r1;
8542
8543 r1 = hregNumber(insn->variant.divs.rem);
8544 op2 = insn->variant.divs.op2;
8545
8546 switch (op2.tag) {
8547 case S390_OPND_REG: {
8548 UInt r2 = hregNumber(op2.variant.reg);
8549
8550 return s390_emit_DSGR(buf, r1, r2);
8551 }
8552
8553 case S390_OPND_AMODE: {
8554 const s390_amode *am = op2.variant.am;
8555 UChar b = hregNumber(am->b);
8556 UChar x = hregNumber(am->x);
8557 Int d = am->d;
8558
8559 return s390_emit_DSG(buf, r1, x, b, DISP20(d));
8560 }
8561
8562 case S390_OPND_IMMEDIATE: {
8563 ULong value = op2.variant.imm;
8564
8565 buf = s390_emit_load_64imm(buf, R0, value);
8566 return s390_emit_DSGR(buf, r1, R0);
8567 }
8568
8569 default:
8570 goto fail;
8571 }
8572
8573 fail:
8574 vpanic("s390_insn_divs_emit");
8575 }
8576
8577
8578 static UChar *
s390_insn_clz_emit(UChar * buf,const s390_insn * insn)8579 s390_insn_clz_emit(UChar *buf, const s390_insn *insn)
8580 {
8581 s390_opnd_RMI src;
8582 UChar r1, r1p1, r2, *p;
8583
8584 r1 = hregNumber(insn->variant.clz.num_bits);
8585 r1p1 = hregNumber(insn->variant.clz.clobber);
8586
8587 vassert((r1 & 0x1) == 0);
8588 vassert(r1p1 == r1 + 1);
8589
8590 p = buf;
8591 src = insn->variant.clz.src;
8592
8593 /* Get operand and move it to r2 */
8594 switch (src.tag) {
8595 case S390_OPND_REG:
8596 r2 = hregNumber(src.variant.reg);
8597 break;
8598
8599 case S390_OPND_AMODE: {
8600 const s390_amode *am = src.variant.am;
8601 UChar b = hregNumber(am->b);
8602 UChar x = hregNumber(am->x);
8603 Int d = am->d;
8604
8605 p = s390_emit_LG(p, R0, x, b, DISP20(d));
8606 r2 = R0;
8607 break;
8608 }
8609
8610 case S390_OPND_IMMEDIATE: {
8611 ULong value = src.variant.imm;
8612
8613 p = s390_emit_load_64imm(p, R0, value);
8614 r2 = R0;
8615 break;
8616 }
8617
8618 default:
8619 goto fail;
8620 }
8621
8622 /* Use FLOGR if you can */
8623 if (s390_host_has_eimm) {
8624 return s390_emit_FLOGR(p, r1, r2);
8625 }
8626
8627 /*
8628 r0 = r2;
8629 r1 = 64;
8630 while (r0 != 0) {
8631 r1 -= 1;
8632 r0 >>= 1;
8633 }
8634 */
8635 p = s390_emit_LTGR(p, R0, r2);
8636 p = s390_emit_LLILL(p, r1, 64);
8637
8638 p = s390_emit_BRC(p, S390_CC_E, (4 + 4 + 6 + 4 + 4)/ 2); /* 4 bytes */
8639 p = s390_emit_AGHI(p, r1, (UShort)-1); /* r1 -= 1; 4 bytes */
8640 p = s390_emit_SRLG(p, R0, R0, R0, DISP20(1)); /* r0 >>= 1; 6 bytes */
8641 p = s390_emit_LTGR(p, R0, R0); /* set cc 4 bytes */
8642 p = s390_emit_BRC(p, S390_CC_NE, /* 4 bytes */
8643 (UShort)(-(4 + 6 + 4) / 2));
8644 return p;
8645
8646 fail:
8647 vpanic("s390_insn_clz_emit");
8648 }
8649
8650
8651 /* Returns a value == BUF to denote failure, != BUF to denote success. */
8652 static UChar *
s390_insn_helper_call_emit(UChar * buf,const s390_insn * insn)8653 s390_insn_helper_call_emit(UChar *buf, const s390_insn *insn)
8654 {
8655 s390_cc_t cond;
8656 ULong target;
8657 UChar *ptmp = buf;
8658 s390_helper_call *helper_call = insn->variant.helper_call.details;
8659
8660 cond = helper_call->cond;
8661 target = helper_call->target;
8662
8663 if (cond != S390_CC_ALWAYS
8664 && helper_call->rloc.pri != RLPri_None) {
8665 /* The call might not happen (it isn't unconditional) and it
8666 returns a result. In this case we will need to generate a
8667 control flow diamond to put 0x555..555 in the return
8668 register(s) in the case where the call doesn't happen. If
8669 this ever becomes necessary, maybe copy code from the ARM
8670 equivalent. Until that day, just give up. */
8671 return buf; /* To denote failure. */
8672 }
8673
8674 if (cond != S390_CC_ALWAYS) {
8675 /* So we have something like this
8676 if (cond) call X;
8677 Y: ...
8678 We convert this into
8679 if (! cond) goto Y; // BRC opcode; 4 bytes
8680 call X;
8681 Y:
8682 */
8683 /* 4 bytes (a BRC insn) to be filled in here */
8684 buf += 4;
8685 }
8686
8687 /* Load the target address into a register, that
8688 (a) is not used for passing parameters to the helper and
8689 (b) can be clobbered by the callee
8690 (c) is not special to the BASR insn
8691 r1 is the only choice.
8692 Also, need to arrange for the return address be put into the
8693 link-register */
8694 buf = s390_emit_load_64imm(buf, 1, target);
8695
8696 /* Stash away the client's FPC register because the helper might change it. */
8697 buf = s390_emit_STFPC(buf, S390_REGNO_STACK_POINTER, S390_OFFSET_SAVED_FPC_C);
8698
8699 buf = s390_emit_BASR(buf, S390_REGNO_LINK_REGISTER, 1); // call helper
8700
8701 buf = s390_emit_LFPC(buf, S390_REGNO_STACK_POINTER, // restore FPC
8702 S390_OFFSET_SAVED_FPC_C);
8703
8704 if (cond != S390_CC_ALWAYS) {
8705 Int delta = buf - ptmp;
8706
8707 delta >>= 1; /* immediate constant is #half-words */
8708 vassert(delta > 0 && delta < (1 << 16));
8709 s390_emit_BRC(ptmp, s390_cc_invert(cond), delta);
8710 }
8711
8712 return buf;
8713 }
8714
8715
8716 static UChar *
s390_insn_cond_move_emit(UChar * buf,const s390_insn * insn)8717 s390_insn_cond_move_emit(UChar *buf, const s390_insn *insn)
8718 {
8719 HReg dst;
8720 s390_opnd_RMI src;
8721 s390_cc_t cond;
8722 UChar *p, *ptmp = 0; /* avoid compiler warnings */
8723
8724 cond = insn->variant.cond_move.cond;
8725 dst = insn->variant.cond_move.dst;
8726 src = insn->variant.cond_move.src;
8727
8728 if (cond == S390_CC_NEVER) return buf;
8729
8730 p = buf;
8731
8732 if (s390_host_has_lsc) {
8733 /* LOCx is not the preferred way to implement an unconditional load. */
8734 if (cond != S390_CC_ALWAYS) goto use_branch_insn;
8735
8736 switch (src.tag) {
8737 case S390_OPND_REG:
8738 return s390_emit_LOCGR(p, cond, hregNumber(dst),
8739 hregNumber(src.variant.reg));
8740
8741 case S390_OPND_AMODE: {
8742 const s390_amode *am = src.variant.am;
8743
8744 /* We cannot use LOCx for loads less than 4 bytes. In that case
8745 load into R0 and then use LOCGR. Do the same if the amode uses
8746 an index register. */
8747 if (insn->size < 4 ||
8748 am->tag == S390_AMODE_BX12 || am->tag == S390_AMODE_BX20) {
8749 p = s390_emit_load_mem(p, insn->size, R0, am);
8750 p = s390_emit_LOCGR(p, cond, hregNumber(dst), R0);
8751 return p;
8752 }
8753
8754 vassert(am->tag == S390_AMODE_B12 || am->tag == S390_AMODE_B20);
8755 vassert(insn->size == 4 || insn->size == 8);
8756
8757 UInt b = hregNumber(am->b);
8758 UInt d = am->d;
8759
8760 if (insn->size == 4) {
8761 return s390_emit_LOC(p, hregNumber(dst), cond, b, DISP20(d));
8762 }
8763 return s390_emit_LOCG(p, hregNumber(dst), cond, b, DISP20(d));
8764 }
8765
8766 case S390_OPND_IMMEDIATE: {
8767 ULong value = src.variant.imm;
8768
8769 /* Load value into R0, then use LOCGR */
8770 if (insn->size <= 4) {
8771 p = s390_emit_load_32imm(p, R0, value);
8772 return s390_emit_LOCGR(p, cond, hregNumber(dst), R0);
8773 }
8774
8775 vassert(insn->size == 8);
8776 p = s390_emit_load_64imm(p, R0, value);
8777 return s390_emit_LOCGR(p, cond, hregNumber(dst), R0);
8778 }
8779 }
8780 }
8781
8782 use_branch_insn:
8783 /* Branch (if cond fails) over move instrs */
8784 if (cond != S390_CC_ALWAYS) {
8785 /* Don't know how many bytes to jump over yet.
8786 Make space for a BRC instruction (4 bytes) and fill in later. */
8787 ptmp = p; /* to be filled in here */
8788 p += 4;
8789 }
8790
8791 // cond true: move src => dst
8792
8793 switch (src.tag) {
8794 case S390_OPND_REG:
8795 p = s390_emit_LGR(p, hregNumber(dst), hregNumber(src.variant.reg));
8796 break;
8797
8798 case S390_OPND_AMODE:
8799 p = s390_emit_load_mem(p, insn->size, hregNumber(dst), src.variant.am);
8800 break;
8801
8802 case S390_OPND_IMMEDIATE: {
8803 ULong value = src.variant.imm;
8804 UInt r = hregNumber(dst);
8805
8806 switch (insn->size) {
8807 case 1:
8808 case 2:
8809 /* Load the immediate values as a 4 byte value. That does not hurt as
8810 those extra bytes will not be looked at. Fall through .... */
8811 case 4:
8812 p = s390_emit_load_32imm(p, r, value);
8813 break;
8814
8815 case 8:
8816 p = s390_emit_load_64imm(p, r, value);
8817 break;
8818 }
8819 break;
8820 }
8821
8822 default:
8823 goto fail;
8824 }
8825
8826 if (cond != S390_CC_ALWAYS) {
8827 Int delta = p - ptmp;
8828
8829 delta >>= 1; /* immediate constant is #half-words */
8830 vassert(delta > 0 && delta < (1 << 16));
8831 s390_emit_BRC(ptmp, s390_cc_invert(cond), delta);
8832 }
8833
8834 return p;
8835
8836 fail:
8837 vpanic("s390_insn_cond_move_emit");
8838 }
8839
8840
8841 static UChar *
s390_insn_bfp_triop_emit(UChar * buf,const s390_insn * insn)8842 s390_insn_bfp_triop_emit(UChar *buf, const s390_insn *insn)
8843 {
8844 UInt r1 = hregNumber(insn->variant.bfp_triop.dst);
8845 UInt r2 = hregNumber(insn->variant.bfp_triop.op2);
8846 UInt r3 = hregNumber(insn->variant.bfp_triop.op3);
8847
8848 switch (insn->size) {
8849 case 4:
8850 switch (insn->variant.bfp_triop.tag) {
8851 case S390_BFP_MADD: return s390_emit_MAEBR(buf, r1, r3, r2);
8852 case S390_BFP_MSUB: return s390_emit_MSEBR(buf, r1, r3, r2);
8853 default: goto fail;
8854 }
8855 break;
8856
8857 case 8:
8858 switch (insn->variant.bfp_triop.tag) {
8859 case S390_BFP_MADD: return s390_emit_MADBR(buf, r1, r3, r2);
8860 case S390_BFP_MSUB: return s390_emit_MSDBR(buf, r1, r3, r2);
8861 default: goto fail;
8862 }
8863 break;
8864
8865 default: goto fail;
8866 }
8867
8868 fail:
8869 vpanic("s390_insn_bfp_triop_emit");
8870 }
8871
8872
8873 static UChar *
s390_insn_bfp_binop_emit(UChar * buf,const s390_insn * insn)8874 s390_insn_bfp_binop_emit(UChar *buf, const s390_insn *insn)
8875 {
8876 UInt r1 = hregNumber(insn->variant.bfp_binop.dst_hi);
8877 UInt r2 = hregNumber(insn->variant.bfp_binop.op2_hi);
8878
8879 switch (insn->size) {
8880 case 4:
8881 switch (insn->variant.bfp_binop.tag) {
8882 case S390_BFP_ADD: return s390_emit_AEBR(buf, r1, r2);
8883 case S390_BFP_SUB: return s390_emit_SEBR(buf, r1, r2);
8884 case S390_BFP_MUL: return s390_emit_MEEBR(buf, r1, r2);
8885 case S390_BFP_DIV: return s390_emit_DEBR(buf, r1, r2);
8886 default: goto fail;
8887 }
8888 break;
8889
8890 case 8:
8891 switch (insn->variant.bfp_binop.tag) {
8892 case S390_BFP_ADD: return s390_emit_ADBR(buf, r1, r2);
8893 case S390_BFP_SUB: return s390_emit_SDBR(buf, r1, r2);
8894 case S390_BFP_MUL: return s390_emit_MDBR(buf, r1, r2);
8895 case S390_BFP_DIV: return s390_emit_DDBR(buf, r1, r2);
8896 default: goto fail;
8897 }
8898 break;
8899
8900 case 16:
8901 switch (insn->variant.bfp_binop.tag) {
8902 case S390_BFP_ADD: return s390_emit_AXBR(buf, r1, r2);
8903 case S390_BFP_SUB: return s390_emit_SXBR(buf, r1, r2);
8904 case S390_BFP_MUL: return s390_emit_MXBR(buf, r1, r2);
8905 case S390_BFP_DIV: return s390_emit_DXBR(buf, r1, r2);
8906 default: goto fail;
8907 }
8908 break;
8909
8910 default: goto fail;
8911 }
8912
8913 fail:
8914 vpanic("s390_insn_bfp_binop_emit");
8915 }
8916
8917
8918 static UChar *
s390_insn_bfp_unop_emit(UChar * buf,const s390_insn * insn)8919 s390_insn_bfp_unop_emit(UChar *buf, const s390_insn *insn)
8920 {
8921 UInt r1 = hregNumber(insn->variant.bfp_unop.dst_hi);
8922 UInt r2 = hregNumber(insn->variant.bfp_unop.op_hi);
8923
8924 switch (insn->variant.bfp_unop.tag) {
8925 case S390_BFP_ABS:
8926 switch (insn->size) {
8927 case 4: return s390_emit_LPEBR(buf, r1, r2);
8928 case 8: return s390_emit_LPDBR(buf, r1, r2);
8929 case 16: return s390_emit_LPXBR(buf, r1, r2);
8930 default: goto fail;
8931 }
8932 break;
8933
8934 case S390_BFP_NABS:
8935 switch (insn->size) {
8936 case 4: return s390_emit_LNEBR(buf, r1, r2);
8937 case 8: return s390_emit_LNDBR(buf, r1, r2);
8938 case 16: return s390_emit_LNXBR(buf, r1, r2);
8939 default: goto fail;
8940 }
8941 break;
8942
8943 case S390_BFP_NEG:
8944 switch (insn->size) {
8945 case 4: return s390_emit_LCEBR(buf, r1, r2);
8946 case 8: return s390_emit_LCDBR(buf, r1, r2);
8947 case 16: return s390_emit_LCXBR(buf, r1, r2);
8948 default: goto fail;
8949 }
8950 break;
8951
8952 case S390_BFP_SQRT:
8953 switch (insn->size) {
8954 case 4: return s390_emit_SQEBR(buf, r1, r2);
8955 case 8: return s390_emit_SQDBR(buf, r1, r2);
8956 case 16: return s390_emit_SQXBR(buf, r1, r2);
8957 default: goto fail;
8958 }
8959 break;
8960
8961 default: goto fail;
8962 }
8963
8964 fail:
8965 vpanic("s390_insn_bfp_unop_emit");
8966 }
8967
8968
8969 static UChar *
s390_insn_bfp_convert_emit(UChar * buf,const s390_insn * insn)8970 s390_insn_bfp_convert_emit(UChar *buf, const s390_insn *insn)
8971 {
8972 UInt r1 = hregNumber(insn->variant.bfp_convert.dst_hi);
8973 UInt r2 = hregNumber(insn->variant.bfp_convert.op_hi);
8974 s390_bfp_round_t m3 = insn->variant.bfp_convert.rounding_mode;
8975 /* The IEEE-inexact-exception control is not modelled. So the
8976 m4 field is 0 (which is what GCC does, too) */
8977 const UInt m4 = 0;
8978
8979 switch (insn->variant.bfp_convert.tag) {
8980 /* Convert to fixed */
8981 case S390_BFP_F32_TO_I32: return s390_emit_CFEBR(buf, m3, r1, r2);
8982 case S390_BFP_F64_TO_I32: return s390_emit_CFDBR(buf, m3, r1, r2);
8983 case S390_BFP_F128_TO_I32: return s390_emit_CFXBR(buf, m3, r1, r2);
8984 case S390_BFP_F32_TO_I64: return s390_emit_CGEBR(buf, m3, r1, r2);
8985 case S390_BFP_F64_TO_I64: return s390_emit_CGDBR(buf, m3, r1, r2);
8986 case S390_BFP_F128_TO_I64: return s390_emit_CGXBR(buf, m3, r1, r2);
8987
8988 /* Convert to logical */
8989 case S390_BFP_F32_TO_U32: return s390_emit_CLFEBR(buf, m3, m4, r1, r2);
8990 case S390_BFP_F64_TO_U32: return s390_emit_CLFDBR(buf, m3, m4, r1, r2);
8991 case S390_BFP_F128_TO_U32: return s390_emit_CLFXBR(buf, m3, m4, r1, r2);
8992 case S390_BFP_F32_TO_U64: return s390_emit_CLGEBR(buf, m3, m4, r1, r2);
8993 case S390_BFP_F64_TO_U64: return s390_emit_CLGDBR(buf, m3, m4, r1, r2);
8994 case S390_BFP_F128_TO_U64: return s390_emit_CLGXBR(buf, m3, m4, r1, r2);
8995
8996 /* Convert from fixed */
8997 case S390_BFP_I32_TO_F32: return s390_emit_CEFBRA(buf, m3, m4, r1, r2);
8998 case S390_BFP_I32_TO_F64: return s390_emit_CDFBRA(buf, 0, m4, r1, r2);
8999 case S390_BFP_I32_TO_F128: return s390_emit_CXFBRA(buf, 0, m4, r1, r2);
9000 case S390_BFP_I64_TO_F32: return s390_emit_CEGBRA(buf, m3, m4, r1, r2);
9001 case S390_BFP_I64_TO_F64: return s390_emit_CDGBRA(buf, m3, m4, r1, r2);
9002 case S390_BFP_I64_TO_F128: return s390_emit_CXGBRA(buf, 0, m4, r1, r2);
9003
9004 /* Convert from logical */
9005 case S390_BFP_U32_TO_F32: return s390_emit_CELFBR(buf, m3, m4, r1, r2);
9006 case S390_BFP_U32_TO_F64: return s390_emit_CDLFBR(buf, m3, m4, r1, r2);
9007 case S390_BFP_U32_TO_F128: return s390_emit_CXLFBR(buf, m3, m4, r1, r2);
9008 case S390_BFP_U64_TO_F32: return s390_emit_CELGBR(buf, m3, m4, r1, r2);
9009 case S390_BFP_U64_TO_F64: return s390_emit_CDLGBR(buf, m3, m4, r1, r2);
9010 case S390_BFP_U64_TO_F128: return s390_emit_CXLGBR(buf, m3, m4, r1, r2);
9011
9012 /* Load lengthened */
9013 case S390_BFP_F32_TO_F64: return s390_emit_LDEBR(buf, r1, r2);
9014 case S390_BFP_F32_TO_F128: return s390_emit_LXEBR(buf, r1, r2);
9015 case S390_BFP_F64_TO_F128: return s390_emit_LXDBR(buf, r1, r2);
9016
9017 /* Load rounded */
9018 case S390_BFP_F64_TO_F32: return s390_emit_LEDBRA(buf, m3, m4, r1, r2);
9019 case S390_BFP_F128_TO_F32: return s390_emit_LEXBRA(buf, m3, m4, r1, r2);
9020 case S390_BFP_F128_TO_F64: return s390_emit_LDXBRA(buf, m3, m4, r1, r2);
9021
9022 /* Load FP integer */
9023 case S390_BFP_F32_TO_F32I: return s390_emit_FIEBRA(buf, m3, m4, r1, r2);
9024 case S390_BFP_F64_TO_F64I: return s390_emit_FIDBRA(buf, m3, m4, r1, r2);
9025 case S390_BFP_F128_TO_F128I: return s390_emit_FIXBRA(buf, m3, m4, r1, r2);
9026
9027 default: goto fail;
9028 }
9029
9030 fail:
9031 vpanic("s390_insn_bfp_convert_emit");
9032 }
9033
9034
9035 static UChar *
s390_insn_bfp_compare_emit(UChar * buf,const s390_insn * insn)9036 s390_insn_bfp_compare_emit(UChar *buf, const s390_insn *insn)
9037 {
9038 UInt dst = hregNumber(insn->variant.bfp_compare.dst);
9039 UInt r1 = hregNumber(insn->variant.bfp_compare.op1_hi);
9040 UInt r2 = hregNumber(insn->variant.bfp_compare.op2_hi);
9041
9042 switch (insn->size) {
9043 case 4: buf = s390_emit_CEBR(buf, r1, r2); break;
9044 case 8: buf = s390_emit_CDBR(buf, r1, r2); break;
9045 case 16: buf = s390_emit_CXBR(buf, r1, r2); break;
9046 default: goto fail;
9047 }
9048
9049 return s390_emit_load_cc(buf, dst); /* Load condition code into DST */
9050
9051 fail:
9052 vpanic("s390_insn_bfp_compare_emit");
9053 }
9054
9055
9056 static UChar *
s390_insn_dfp_binop_emit(UChar * buf,const s390_insn * insn)9057 s390_insn_dfp_binop_emit(UChar *buf, const s390_insn *insn)
9058 {
9059 s390_dfp_binop *dfp_binop = insn->variant.dfp_binop.details;
9060
9061 UInt r1 = hregNumber(dfp_binop->dst_hi);
9062 UInt r2 = hregNumber(dfp_binop->op2_hi);
9063 UInt r3 = hregNumber(dfp_binop->op3_hi);
9064 s390_dfp_round_t m4 = dfp_binop->rounding_mode;
9065
9066 switch (insn->size) {
9067 case 8:
9068 switch (dfp_binop->tag) {
9069 case S390_DFP_ADD: return s390_emit_ADTRA(buf, r3, m4, r1, r2);
9070 case S390_DFP_SUB: return s390_emit_SDTRA(buf, r3, m4, r1, r2);
9071 case S390_DFP_MUL: return s390_emit_MDTRA(buf, r3, m4, r1, r2);
9072 case S390_DFP_DIV: return s390_emit_DDTRA(buf, r3, m4, r1, r2);
9073 case S390_DFP_QUANTIZE: return s390_emit_QADTR(buf, r3, m4, r1, r2);
9074 default: goto fail;
9075 }
9076 break;
9077
9078 case 16:
9079 switch (dfp_binop->tag) {
9080 case S390_DFP_ADD: return s390_emit_AXTRA(buf, r3, m4, r1, r2);
9081 case S390_DFP_SUB: return s390_emit_SXTRA(buf, r3, m4, r1, r2);
9082 case S390_DFP_MUL: return s390_emit_MXTRA(buf, r3, m4, r1, r2);
9083 case S390_DFP_DIV: return s390_emit_DXTRA(buf, r3, m4, r1, r2);
9084 case S390_DFP_QUANTIZE: return s390_emit_QAXTR(buf, r3, m4, r1, r2);
9085 default: goto fail;
9086 }
9087 break;
9088
9089 default: goto fail;
9090 }
9091
9092 fail:
9093 vpanic("s390_insn_dfp_binop_emit");
9094 }
9095
9096
9097 static UChar *
s390_insn_dfp_reround_emit(UChar * buf,const s390_insn * insn)9098 s390_insn_dfp_reround_emit(UChar *buf, const s390_insn *insn)
9099 {
9100 UInt r1 = hregNumber(insn->variant.dfp_reround.dst_hi);
9101 UInt r2 = hregNumber(insn->variant.dfp_reround.op2);
9102 UInt r3 = hregNumber(insn->variant.dfp_reround.op3_hi);
9103 s390_dfp_round_t m4 = insn->variant.dfp_reround.rounding_mode;
9104
9105 switch (insn->size) {
9106 case 8:
9107 return s390_emit_RRDTR(buf, r3, m4, r1, r2);
9108
9109 case 16:
9110 return s390_emit_RRXTR(buf, r3, m4, r1, r2);
9111
9112 default: goto fail;
9113 }
9114 fail:
9115 vpanic("s390_insn_dfp_reround_emit");
9116 }
9117
9118
9119 static UChar *
s390_insn_dfp_unop_emit(UChar * buf,const s390_insn * insn)9120 s390_insn_dfp_unop_emit(UChar *buf, const s390_insn *insn)
9121 {
9122 UInt r1 = hregNumber(insn->variant.dfp_unop.dst_hi);
9123 UInt r2 = hregNumber(insn->variant.dfp_unop.op_hi);
9124
9125 switch (insn->variant.dfp_unop.tag) {
9126 case S390_DFP_EXTRACT_EXP_D64: return s390_emit_EEDTR(buf, r1, r2); break;
9127 case S390_DFP_EXTRACT_EXP_D128: return s390_emit_EEXTR(buf, r1, r2); break;
9128 case S390_DFP_EXTRACT_SIG_D64: return s390_emit_ESDTR(buf, r1, r2); break;
9129 case S390_DFP_EXTRACT_SIG_D128: return s390_emit_ESXTR(buf, r1, r2); break;
9130 default: goto fail;
9131 }
9132 fail:
9133 vpanic("s390_insn_dfp_unop_emit");
9134 }
9135
9136
9137 static UChar *
s390_insn_dfp_intop_emit(UChar * buf,const s390_insn * insn)9138 s390_insn_dfp_intop_emit(UChar *buf, const s390_insn *insn)
9139 {
9140 UInt r1 = hregNumber(insn->variant.dfp_intop.dst_hi);
9141 UInt r2 = hregNumber(insn->variant.dfp_intop.op2);
9142 UInt r3 = hregNumber(insn->variant.dfp_intop.op3_hi);
9143
9144 switch (insn->size) {
9145 case 8:
9146 switch (insn->variant.dfp_intop.tag) {
9147 case S390_DFP_SHIFT_LEFT: return s390_emit_SLDT(buf, r3, r1, r2);
9148 case S390_DFP_SHIFT_RIGHT: return s390_emit_SRDT(buf, r3, r1, r2);
9149 case S390_DFP_INSERT_EXP: return s390_emit_IEDTR(buf, r3, r1, r2);
9150 default: goto fail;
9151 }
9152 break;
9153
9154 case 16:
9155 switch (insn->variant.dfp_intop.tag) {
9156 case S390_DFP_SHIFT_LEFT: return s390_emit_SLXT(buf, r3, r1, r2);
9157 case S390_DFP_SHIFT_RIGHT: return s390_emit_SRXT(buf, r3, r1, r2);
9158 case S390_DFP_INSERT_EXP: return s390_emit_IEXTR(buf, r3, r1, r2);
9159 default: goto fail;
9160 }
9161 break;
9162
9163 default: goto fail;
9164 }
9165
9166 fail:
9167 vpanic("s390_insn_dfp_intop_emit");
9168 }
9169
9170
9171 static UChar *
s390_insn_dfp_compare_emit(UChar * buf,const s390_insn * insn)9172 s390_insn_dfp_compare_emit(UChar *buf, const s390_insn *insn)
9173 {
9174 UInt dst = hregNumber(insn->variant.dfp_compare.dst);
9175 UInt r1 = hregNumber(insn->variant.dfp_compare.op1_hi);
9176 UInt r2 = hregNumber(insn->variant.dfp_compare.op2_hi);
9177
9178 switch (insn->size) {
9179 case 8:
9180 switch(insn->variant.dfp_compare.tag) {
9181 case S390_DFP_COMPARE: buf = s390_emit_CDTR(buf, r1, r2); break;
9182 case S390_DFP_COMPARE_EXP: buf = s390_emit_CEDTR(buf, r1, r2); break;
9183 default: goto fail;
9184 }
9185 break;
9186
9187 case 16:
9188 switch(insn->variant.dfp_compare.tag) {
9189 case S390_DFP_COMPARE: buf = s390_emit_CXTR(buf, r1, r2); break;
9190 case S390_DFP_COMPARE_EXP: buf = s390_emit_CEXTR(buf, r1, r2); break;
9191 default: goto fail;
9192 }
9193 break;
9194
9195 default: goto fail;
9196 }
9197
9198 return s390_emit_load_cc(buf, dst); /* Load condition code into DST */
9199
9200 fail:
9201 vpanic("s390_insn_dfp_compare_emit");
9202 }
9203
9204
9205 static UChar *
s390_insn_dfp_convert_emit(UChar * buf,const s390_insn * insn)9206 s390_insn_dfp_convert_emit(UChar *buf, const s390_insn *insn)
9207 {
9208 UInt r1 = hregNumber(insn->variant.dfp_convert.dst_hi);
9209 UInt r2 = hregNumber(insn->variant.dfp_convert.op_hi);
9210 s390_dfp_round_t m3 = insn->variant.dfp_convert.rounding_mode;
9211 /* The IEEE-inexact-exception control is not modelled. So the
9212 m4 field is 0 (which is what GCC does, too) */
9213 const UInt m4 = 0;
9214
9215 switch (insn->variant.dfp_convert.tag) {
9216
9217 /* Convert to fixed */
9218 case S390_DFP_D64_TO_I32: return s390_emit_CFDTR(buf, m3, m4, r1, r2);
9219 case S390_DFP_D128_TO_I32: return s390_emit_CFXTR(buf, m3, m4, r1, r2);
9220 case S390_DFP_D64_TO_I64: return s390_emit_CGDTR(buf, m3, m4, r1, r2);
9221 case S390_DFP_D128_TO_I64: return s390_emit_CGXTR(buf, m3, m4, r1, r2);
9222
9223 /* Convert to logical */
9224 case S390_DFP_D64_TO_U32: return s390_emit_CLFDTR(buf, m3, m4, r1, r2);
9225 case S390_DFP_D128_TO_U32: return s390_emit_CLFXTR(buf, m3, m4, r1, r2);
9226 case S390_DFP_D64_TO_U64: return s390_emit_CLGDTR(buf, m3, m4, r1, r2);
9227 case S390_DFP_D128_TO_U64: return s390_emit_CLGXTR(buf, m3, m4, r1, r2);
9228
9229 /* Convert from fixed */
9230 case S390_DFP_I32_TO_D64: return s390_emit_CDFTR(buf, 0, m4, r1, r2);
9231 case S390_DFP_I32_TO_D128: return s390_emit_CXFTR(buf, 0, m4, r1, r2);
9232 case S390_DFP_I64_TO_D64: return s390_emit_CDGTRA(buf, m3, m4, r1, r2);
9233 case S390_DFP_I64_TO_D128: return s390_emit_CXGTR(buf, 0, m4, r1, r2);
9234
9235 /* Convert from logical */
9236 case S390_DFP_U32_TO_D64: return s390_emit_CDLFTR(buf, m3, m4, r1, r2);
9237 case S390_DFP_U64_TO_D64: return s390_emit_CDLGTR(buf, m3, m4, r1, r2);
9238 case S390_DFP_U32_TO_D128: return s390_emit_CXLFTR(buf, m3, m4, r1, r2);
9239 case S390_DFP_U64_TO_D128: return s390_emit_CXLGTR(buf, m3, m4, r1, r2);
9240
9241 /* Load lengthened */
9242 case S390_DFP_D32_TO_D64: return s390_emit_LDETR(buf, m4, r1, r2);
9243 case S390_DFP_D64_TO_D128: return s390_emit_LXDTR(buf, m4, r1, r2);
9244
9245 /* Load rounded */
9246 case S390_DFP_D64_TO_D32: return s390_emit_LEDTR(buf, m3, m4, r1, r2);
9247 case S390_DFP_D128_TO_D64: return s390_emit_LDXTR(buf, m3, m4, r1, r2);
9248
9249 default: goto fail;
9250 }
9251
9252 fail:
9253 vpanic("s390_insn_dfp_convert_emit");
9254 }
9255
9256
9257 static UChar *
s390_insn_fp_convert_emit(UChar * buf,const s390_insn * insn)9258 s390_insn_fp_convert_emit(UChar *buf, const s390_insn *insn)
9259 {
9260 UInt pfpo;
9261 s390_fp_convert *fp_convert = insn->variant.fp_convert.details;
9262 s390_dfp_round_t rm = fp_convert->rounding_mode;
9263
9264 vassert(rm < 2 || rm > 7);
9265
9266 switch (fp_convert->tag) {
9267 case S390_FP_F32_TO_D32: pfpo = S390_PFPO_F32_TO_D32 << 8; break;
9268 case S390_FP_F32_TO_D64: pfpo = S390_PFPO_F32_TO_D64 << 8; break;
9269 case S390_FP_F32_TO_D128: pfpo = S390_PFPO_F32_TO_D128 << 8; break;
9270 case S390_FP_F64_TO_D32: pfpo = S390_PFPO_F64_TO_D32 << 8; break;
9271 case S390_FP_F64_TO_D64: pfpo = S390_PFPO_F64_TO_D64 << 8; break;
9272 case S390_FP_F64_TO_D128: pfpo = S390_PFPO_F64_TO_D128 << 8; break;
9273 case S390_FP_F128_TO_D32: pfpo = S390_PFPO_F128_TO_D32 << 8; break;
9274 case S390_FP_F128_TO_D64: pfpo = S390_PFPO_F128_TO_D64 << 8; break;
9275 case S390_FP_F128_TO_D128: pfpo = S390_PFPO_F128_TO_D128 << 8; break;
9276 case S390_FP_D32_TO_F32: pfpo = S390_PFPO_D32_TO_F32 << 8; break;
9277 case S390_FP_D32_TO_F64: pfpo = S390_PFPO_D32_TO_F64 << 8; break;
9278 case S390_FP_D32_TO_F128: pfpo = S390_PFPO_D32_TO_F128 << 8; break;
9279 case S390_FP_D64_TO_F32: pfpo = S390_PFPO_D64_TO_F32 << 8; break;
9280 case S390_FP_D64_TO_F64: pfpo = S390_PFPO_D64_TO_F64 << 8; break;
9281 case S390_FP_D64_TO_F128: pfpo = S390_PFPO_D64_TO_F128 << 8; break;
9282 case S390_FP_D128_TO_F32: pfpo = S390_PFPO_D128_TO_F32 << 8; break;
9283 case S390_FP_D128_TO_F64: pfpo = S390_PFPO_D128_TO_F64 << 8; break;
9284 case S390_FP_D128_TO_F128: pfpo = S390_PFPO_D128_TO_F128 << 8; break;
9285 default: goto fail;
9286 }
9287
9288 pfpo = pfpo | rm;
9289 buf = s390_emit_load_32imm(buf, R0, pfpo);
9290 buf = s390_emit_PFPO(buf);
9291 return buf;
9292
9293 fail:
9294 vpanic("s390_insn_fp_convert_emit");
9295 }
9296
9297
9298 static UChar *
s390_insn_mfence_emit(UChar * buf,const s390_insn * insn)9299 s390_insn_mfence_emit(UChar *buf, const s390_insn *insn)
9300 {
9301 return s390_emit_BCR(buf, 0xF, 0x0);
9302 }
9303
9304
9305 static UChar *
s390_insn_mimm_emit(UChar * buf,const s390_insn * insn)9306 s390_insn_mimm_emit(UChar *buf, const s390_insn *insn)
9307 {
9308 s390_amode *am = insn->variant.mimm.dst;
9309 UChar b = hregNumber(am->b);
9310 Int d = am->d;
9311 ULong value = insn->variant.mimm.value;
9312
9313 if (value == 0) {
9314 return s390_emit_XC(buf, insn->size - 1, b, d, b, d);
9315 }
9316
9317 if (insn->size == 1) {
9318 return s390_emit_MVI(buf, value & 0xFF, b, d);
9319 }
9320
9321 if (s390_host_has_gie && ulong_fits_signed_16bit(value)) {
9322 value &= 0xFFFF;
9323 switch (insn->size) {
9324 case 2: return s390_emit_MVHHI(buf, b, d, value);
9325 case 4: return s390_emit_MVHI(buf, b, d, value);
9326 case 8: return s390_emit_MVGHI(buf, b, d, value);
9327 }
9328 } else {
9329 // Load value to R0, then store.
9330 switch (insn->size) {
9331 case 2:
9332 buf = s390_emit_LHI(buf, R0, value & 0xFFFF);
9333 return s390_emit_STH(buf, R0, 0, b, d);
9334 case 4:
9335 buf = s390_emit_load_32imm(buf, R0, value);
9336 return s390_emit_ST(buf, R0, 0, b, d);
9337 case 8:
9338 buf = s390_emit_load_64imm(buf, R0, value);
9339 return s390_emit_STG(buf, R0, 0, b, DISP20(d));
9340 }
9341 }
9342
9343 vpanic("s390_insn_mimm_emit");
9344 }
9345
9346
9347 static UChar *
s390_insn_madd_emit(UChar * buf,const s390_insn * insn)9348 s390_insn_madd_emit(UChar *buf, const s390_insn *insn)
9349 {
9350 s390_amode *am = insn->variant.madd.dst;
9351 UChar b = hregNumber(am->b);
9352 Int d = am->d;
9353
9354 if (insn->size == 4) {
9355 return s390_emit_ASI(buf, insn->variant.madd.delta, b, DISP20(d));
9356 }
9357
9358 return s390_emit_AGSI(buf, insn->variant.madd.delta, b, DISP20(d));
9359 }
9360
9361
9362 static UChar *
s390_insn_set_fpc_bfprm_emit(UChar * buf,const s390_insn * insn)9363 s390_insn_set_fpc_bfprm_emit(UChar *buf, const s390_insn *insn)
9364 {
9365 UInt mode = hregNumber(insn->variant.set_fpc_bfprm.mode);
9366
9367 /* Copy FPC from guest state to R0 and OR in the new rounding mode */
9368 buf = s390_emit_L(buf, R0, 0, S390_REGNO_GUEST_STATE_POINTER,
9369 S390X_GUEST_OFFSET(guest_fpc)); // r0 = guest_fpc
9370
9371 buf = s390_emit_NILL(buf, R0, 0xFFF8); /* Clear out right-most 3 bits */
9372 buf = s390_emit_OR(buf, R0, mode); /* OR in the new rounding mode */
9373 buf = s390_emit_SFPC(buf, R0); /* Load FPC register from R0 */
9374
9375 return buf;
9376 }
9377
9378
9379 static UChar *
s390_insn_set_fpc_dfprm_emit(UChar * buf,const s390_insn * insn)9380 s390_insn_set_fpc_dfprm_emit(UChar *buf, const s390_insn *insn)
9381 {
9382 UInt mode = hregNumber(insn->variant.set_fpc_dfprm.mode);
9383
9384 /* Copy FPC from guest state to R0 and OR in the new rounding mode */
9385 buf = s390_emit_L(buf, R0, 0, S390_REGNO_GUEST_STATE_POINTER,
9386 S390X_GUEST_OFFSET(guest_fpc)); // r0 = guest_fpc
9387
9388 /* DFP rounding mode is set at bit position 25:27 in FPC register */
9389 buf = s390_emit_NILL(buf, R0, 0xFF8F); /* Clear out 25:27 bits */
9390 buf = s390_emit_SLL(buf, mode, 0, 4); /* bring mode to 25:27 bits */
9391 buf = s390_emit_OR(buf, R0, mode); /* OR in the new rounding mode */
9392 buf = s390_emit_SFPC(buf, R0); /* Load FPC register from R0 */
9393
9394 return buf;
9395 }
9396
9397
9398 /* Define convenience functions needed for translation chaining.
9399 Any changes need to be applied to the functions in concert. */
9400
9401 static __inline__ Bool
s390_insn_is_BRCL(const UChar * p,UChar condition)9402 s390_insn_is_BRCL(const UChar *p, UChar condition)
9403 {
9404 return p[0] == 0xc0 && p[1] == ((condition << 4) | 0x04);
9405 }
9406
9407 static __inline__ Bool
s390_insn_is_BR(const UChar * p,UChar reg)9408 s390_insn_is_BR(const UChar *p, UChar reg)
9409 {
9410 return p[0] == 0x07 && p[1] == (0xF0 | reg); /* BCR 15,reg */
9411 }
9412
9413
9414 /* The length of the BASR insn */
9415 #define S390_BASR_LEN 2
9416
9417
9418 /* Load the 64-bit VALUE into REG. Note that this function must NOT
9419 optimise the generated code by looking at the value. I.e. using
9420 LGHI if value == 0 would be very wrong. */
9421 static UChar *
s390_tchain_load64(UChar * buf,UChar regno,ULong value)9422 s390_tchain_load64(UChar *buf, UChar regno, ULong value)
9423 {
9424 UChar *begin = buf;
9425
9426 if (s390_host_has_eimm) {
9427 /* Do it in two steps: upper half [0:31] and lower half [32:63] */
9428 buf = s390_emit_IIHF(buf, regno, value >> 32);
9429 buf = s390_emit_IILF(buf, regno, value & 0xFFFFFFFF);
9430 } else {
9431 buf = s390_emit_IILL(buf, regno, value & 0xFFFF);
9432 value >>= 16;
9433 buf = s390_emit_IILH(buf, regno, value & 0xFFFF);
9434 value >>= 16;
9435 buf = s390_emit_IIHL(buf, regno, value & 0xFFFF);
9436 value >>= 16;
9437 buf = s390_emit_IIHH(buf, regno, value & 0xFFFF);
9438 }
9439
9440 vassert(buf - begin == s390_tchain_load64_len());
9441
9442 return buf;
9443 }
9444
9445 /* Return number of bytes generated by s390_tchain_load64 */
9446 static UInt
s390_tchain_load64_len(void)9447 s390_tchain_load64_len(void)
9448 {
9449 if (s390_host_has_eimm) {
9450 return 6 + 6; /* IIHF + IILF */
9451 }
9452 return 4 + 4 + 4 + 4; /* IIHH + IIHL + IILH + IILL */
9453 }
9454
9455 /* Verify that CODE is the code sequence generated by s390_tchain_load64
9456 to load VALUE into REGNO. Return pointer to the byte following the
9457 insn sequence. */
9458 static const UChar *
s390_tchain_verify_load64(const UChar * code,UChar regno,ULong value)9459 s390_tchain_verify_load64(const UChar *code, UChar regno, ULong value)
9460 {
9461 UInt regmask = regno << 4;
9462 UInt hw;
9463
9464 if (s390_host_has_eimm) {
9465 /* Check for IIHF */
9466 vassert(code[0] == 0xC0);
9467 vassert(code[1] == (0x08 | regmask));
9468 vassert(*(const UInt *)&code[2] == (value >> 32));
9469 /* Check for IILF */
9470 vassert(code[6] == 0xC0);
9471 vassert(code[7] == (0x09 | regmask));
9472 vassert(*(const UInt *)&code[8] == (value & 0xFFFFFFFF));
9473 } else {
9474 /* Check for IILL */
9475 hw = value & 0xFFFF;
9476 vassert(code[0] == 0xA5);
9477 vassert(code[1] == (0x03 | regmask));
9478 vassert(code[2] == (hw >> 8));
9479 vassert(code[3] == (hw & 0xFF));
9480
9481 /* Check for IILH */
9482 hw = (value >> 16) & 0xFFFF;
9483 vassert(code[4] == 0xA5);
9484 vassert(code[5] == (0x02 | regmask));
9485 vassert(code[6] == (hw >> 8));
9486 vassert(code[7] == (hw & 0xFF));
9487
9488 /* Check for IIHL */
9489 hw = (value >> 32) & 0xFFFF;
9490 vassert(code[8] == 0xA5);
9491 vassert(code[9] == (0x01 | regmask));
9492 vassert(code[10] == (hw >> 8));
9493 vassert(code[11] == (hw & 0xFF));
9494
9495 /* Check for IIHH */
9496 hw = (value >> 48) & 0xFFFF;
9497 vassert(code[12] == 0xA5);
9498 vassert(code[13] == (0x00 | regmask));
9499 vassert(code[14] == (hw >> 8));
9500 vassert(code[15] == (hw & 0xFF));
9501 }
9502
9503 return code + s390_tchain_load64_len();
9504 }
9505
9506 /* CODE points to the code sequence as generated by s390_tchain_load64.
9507 Change the loaded value to IMM64. Return pointer to the byte following
9508 the patched code sequence. */
9509 static UChar *
s390_tchain_patch_load64(UChar * code,ULong imm64)9510 s390_tchain_patch_load64(UChar *code, ULong imm64)
9511 {
9512 if (s390_host_has_eimm) {
9513 /* Patch IIHF */
9514 *(UInt *)&code[2] = imm64 >> 32;
9515 /* Patch IILF */
9516 *(UInt *)&code[8] = imm64 & 0xFFFFFFFF;
9517 } else {
9518 code[3] = imm64 & 0xFF; imm64 >>= 8;
9519 code[2] = imm64 & 0xFF; imm64 >>= 8;
9520 code[7] = imm64 & 0xFF; imm64 >>= 8;
9521 code[6] = imm64 & 0xFF; imm64 >>= 8;
9522 code[11] = imm64 & 0xFF; imm64 >>= 8;
9523 code[10] = imm64 & 0xFF; imm64 >>= 8;
9524 code[15] = imm64 & 0xFF; imm64 >>= 8;
9525 code[14] = imm64 & 0xFF; imm64 >>= 8;
9526 }
9527
9528 return code + s390_tchain_load64_len();
9529 }
9530
9531
9532 /* NB: what goes on here has to be very closely coordinated with the
9533 chainXDirect_S390 and unchainXDirect_S390 below. */
9534 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)9535 s390_insn_xdirect_emit(UChar *buf, const s390_insn *insn,
9536 const void *disp_cp_chain_me_to_slowEP,
9537 const void *disp_cp_chain_me_to_fastEP)
9538 {
9539 /* We're generating chain-me requests here, so we need to be
9540 sure this is actually allowed -- no-redir translations can't
9541 use chain-me's. Hence: */
9542 vassert(disp_cp_chain_me_to_slowEP != NULL);
9543 vassert(disp_cp_chain_me_to_fastEP != NULL);
9544
9545 /* Use ptmp for backpatching conditional jumps. */
9546 UChar *ptmp = buf;
9547
9548 /* First off, if this is conditional, create a conditional
9549 jump over the rest of it. */
9550 s390_cc_t cond = insn->variant.xdirect.cond;
9551
9552 if (cond != S390_CC_ALWAYS) {
9553 /* So we have something like this
9554 if (cond) do_xdirect;
9555 Y: ...
9556 We convert this into
9557 if (! cond) goto Y; // BRC opcode; 4 bytes
9558 do_xdirect;
9559 Y:
9560 */
9561 /* 4 bytes (a BRC insn) to be filled in here */
9562 buf += 4;
9563 }
9564
9565 /* Update the guest IA. */
9566 buf = s390_emit_load_64imm(buf, R0, insn->variant.xdirect.dst);
9567
9568 const s390_amode *amode = insn->variant.xdirect.guest_IA;
9569 vassert(amode->tag == S390_AMODE_B12);
9570 UInt b = hregNumber(amode->b);
9571 UInt d = amode->d;
9572
9573 buf = s390_emit_STG(buf, R0, 0, b, DISP20(d));
9574
9575 /* Load the chosen entry point into the scratch reg */
9576 const void *disp_cp_chain_me;
9577
9578 disp_cp_chain_me =
9579 insn->variant.xdirect.to_fast_entry ? disp_cp_chain_me_to_fastEP
9580 : disp_cp_chain_me_to_slowEP;
9581 /* Get the address of the beginning of the load64 code sequence into %r1.
9582 Do not change the register! This is part of the protocol with the
9583 dispatcher. */
9584 buf = s390_emit_BASR(buf, 1, R0);
9585
9586 /* --- FIRST PATCHABLE BYTE follows (must not modify %r1) --- */
9587 Addr64 addr = (Addr)disp_cp_chain_me;
9588 buf = s390_tchain_load64(buf, S390_REGNO_TCHAIN_SCRATCH, addr);
9589
9590 /* goto *tchain_scratch */
9591 buf = s390_emit_BCR(buf, S390_CC_ALWAYS, S390_REGNO_TCHAIN_SCRATCH);
9592
9593 /* --- END of PATCHABLE BYTES --- */
9594
9595 /* Fix up the conditional jump, if there was one. */
9596 if (cond != S390_CC_ALWAYS) {
9597 Int delta = buf - ptmp;
9598
9599 delta >>= 1; /* immediate constant is #half-words */
9600 vassert(delta > 0 && delta < (1 << 16));
9601 s390_emit_BRC(ptmp, s390_cc_invert(cond), delta);
9602 }
9603
9604 return buf;
9605 }
9606
9607 /* Return the number of patchable bytes from an xdirect insn. */
9608 static UInt
s390_xdirect_patchable_len(void)9609 s390_xdirect_patchable_len(void)
9610 {
9611 return s390_tchain_load64_len() + S390_BASR_LEN;
9612 }
9613
9614
9615 static UChar *
s390_insn_xindir_emit(UChar * buf,const s390_insn * insn,const void * disp_cp_xindir)9616 s390_insn_xindir_emit(UChar *buf, const s390_insn *insn,
9617 const void *disp_cp_xindir)
9618 {
9619 /* We're generating transfers that could lead indirectly to a
9620 chain-me, so we need to be sure this is actually allowed --
9621 no-redir translations are not allowed to reach normal
9622 translations without going through the scheduler. That means
9623 no XDirects or XIndirs out from no-redir translations.
9624 Hence: */
9625 vassert(disp_cp_xindir != NULL);
9626
9627 /* Use ptmp for backpatching conditional jumps. */
9628 UChar *ptmp = buf;
9629
9630 /* First off, if this is conditional, create a conditional
9631 jump over the rest of it. */
9632 s390_cc_t cond = insn->variant.xdirect.cond;
9633
9634 if (cond != S390_CC_ALWAYS) {
9635 /* So we have something like this
9636 if (cond) do_xdirect;
9637 Y: ...
9638 We convert this into
9639 if (! cond) goto Y; // BRC opcode; 4 bytes
9640 do_xdirect;
9641 Y:
9642 */
9643 /* 4 bytes (a BRC insn) to be filled in here */
9644 buf += 4;
9645 }
9646
9647 /* Update the guest IA with the address in xdirect.dst. */
9648 const s390_amode *amode = insn->variant.xindir.guest_IA;
9649
9650 vassert(amode->tag == S390_AMODE_B12);
9651 UInt b = hregNumber(amode->b);
9652 UInt d = amode->d;
9653 UInt regno = hregNumber(insn->variant.xindir.dst);
9654
9655 buf = s390_emit_STG(buf, regno, 0, b, DISP20(d));
9656
9657 /* load tchain_scratch, #disp_indir */
9658 buf = s390_tchain_load64(buf, S390_REGNO_TCHAIN_SCRATCH,
9659 (Addr)disp_cp_xindir);
9660 /* goto *tchain_direct */
9661 buf = s390_emit_BCR(buf, S390_CC_ALWAYS, S390_REGNO_TCHAIN_SCRATCH);
9662
9663 /* Fix up the conditional jump, if there was one. */
9664 if (cond != S390_CC_ALWAYS) {
9665 Int delta = buf - ptmp;
9666
9667 delta >>= 1; /* immediate constant is #half-words */
9668 vassert(delta > 0 && delta < (1 << 16));
9669 s390_emit_BRC(ptmp, s390_cc_invert(cond), delta);
9670 }
9671
9672 return buf;
9673 }
9674
9675 static UChar *
s390_insn_xassisted_emit(UChar * buf,const s390_insn * insn,const void * disp_cp_xassisted)9676 s390_insn_xassisted_emit(UChar *buf, const s390_insn *insn,
9677 const void *disp_cp_xassisted)
9678 {
9679 /* Use ptmp for backpatching conditional jumps. */
9680 UChar *ptmp = buf;
9681
9682 /* First off, if this is conditional, create a conditional
9683 jump over the rest of it. */
9684 s390_cc_t cond = insn->variant.xdirect.cond;
9685
9686 if (cond != S390_CC_ALWAYS) {
9687 /* So we have something like this
9688 if (cond) do_xdirect;
9689 Y: ...
9690 We convert this into
9691 if (! cond) goto Y; // BRC opcode; 4 bytes
9692 do_xdirect;
9693 Y:
9694 */
9695 /* 4 bytes (a BRC insn) to be filled in here */
9696 buf += 4;
9697 }
9698
9699 /* Update the guest IA with the address in xassisted.dst. */
9700 const s390_amode *amode = insn->variant.xassisted.guest_IA;
9701
9702 vassert(amode->tag == S390_AMODE_B12);
9703 UInt b = hregNumber(amode->b);
9704 UInt d = amode->d;
9705 UInt regno = hregNumber(insn->variant.xassisted.dst);
9706
9707 buf = s390_emit_STG(buf, regno, 0, b, DISP20(d));
9708
9709 UInt trcval = 0;
9710
9711 switch (insn->variant.xassisted.kind) {
9712 case Ijk_ClientReq: trcval = VEX_TRC_JMP_CLIENTREQ; break;
9713 case Ijk_Sys_syscall: trcval = VEX_TRC_JMP_SYS_SYSCALL; break;
9714 case Ijk_Yield: trcval = VEX_TRC_JMP_YIELD; break;
9715 case Ijk_EmWarn: trcval = VEX_TRC_JMP_EMWARN; break;
9716 case Ijk_EmFail: trcval = VEX_TRC_JMP_EMFAIL; break;
9717 case Ijk_MapFail: trcval = VEX_TRC_JMP_MAPFAIL; break;
9718 case Ijk_NoDecode: trcval = VEX_TRC_JMP_NODECODE; break;
9719 case Ijk_InvalICache: trcval = VEX_TRC_JMP_INVALICACHE; break;
9720 case Ijk_NoRedir: trcval = VEX_TRC_JMP_NOREDIR; break;
9721 case Ijk_SigTRAP: trcval = VEX_TRC_JMP_SIGTRAP; break;
9722 case Ijk_SigSEGV: trcval = VEX_TRC_JMP_SIGSEGV; break;
9723 case Ijk_Boring: trcval = VEX_TRC_JMP_BORING; break;
9724 /* We don't expect to see the following being assisted. */
9725 case Ijk_Ret:
9726 case Ijk_Call:
9727 /* fallthrough */
9728 default:
9729 ppIRJumpKind(insn->variant.xassisted.kind);
9730 vpanic("s390_insn_xassisted_emit: unexpected jump kind");
9731 }
9732
9733 vassert(trcval != 0);
9734
9735 /* guest_state_pointer = trcval */
9736 buf = s390_emit_LGHI(buf, S390_REGNO_GUEST_STATE_POINTER, trcval);
9737
9738 /* load tchain_scratch, #disp_assisted */
9739 buf = s390_tchain_load64(buf, S390_REGNO_TCHAIN_SCRATCH,
9740 (Addr)disp_cp_xassisted);
9741
9742 /* goto *tchain_direct */
9743 buf = s390_emit_BCR(buf, S390_CC_ALWAYS, S390_REGNO_TCHAIN_SCRATCH);
9744
9745 /* Fix up the conditional jump, if there was one. */
9746 if (cond != S390_CC_ALWAYS) {
9747 Int delta = buf - ptmp;
9748
9749 delta >>= 1; /* immediate constant is #half-words */
9750 vassert(delta > 0 && delta < (1 << 16));
9751 s390_emit_BRC(ptmp, s390_cc_invert(cond), delta);
9752 }
9753
9754 return buf;
9755 }
9756
9757
9758 /* Pseudo code:
9759
9760 guest_state[host_EvC_COUNTER] -= 1;
9761 if (guest_state[host_EvC_COUNTER] >= 0) goto nofail;
9762 goto guest_state[host_EvC_FAILADDR];
9763 nofail: ;
9764
9765 The dispatch counter is a 32-bit value. */
9766 static UChar *
s390_insn_evcheck_emit(UChar * buf,const s390_insn * insn,VexEndness endness_host)9767 s390_insn_evcheck_emit(UChar *buf, const s390_insn *insn,
9768 VexEndness endness_host)
9769 {
9770 s390_amode *amode;
9771 UInt b, d;
9772 UChar *code_begin, *code_end;
9773
9774 code_begin = buf;
9775
9776 amode = insn->variant.evcheck.counter;
9777 vassert(amode->tag == S390_AMODE_B12);
9778 b = hregNumber(amode->b);
9779 d = amode->d;
9780
9781 /* Decrement the dispatch counter in the guest state */
9782 if (s390_host_has_gie) {
9783 buf = s390_emit_ASI(buf, -1, b, DISP20(d)); /* 6 bytes */
9784 } else {
9785 buf = s390_emit_LHI(buf, R0, -1); /* 4 bytes */
9786 buf = s390_emit_A(buf, R0, 0, b, d); /* 4 bytes */
9787 buf = s390_emit_ST(buf, R0, 0, b, d); /* 4 bytes */
9788 }
9789
9790 /* Jump over the next insn if >= 0 */
9791 buf = s390_emit_BRC(buf, S390_CC_HE, (4 + 6 + 2) / 2); /* 4 bytes */
9792
9793 /* Computed goto to fail_address */
9794 amode = insn->variant.evcheck.fail_addr;
9795 b = hregNumber(amode->b);
9796 d = amode->d;
9797 buf = s390_emit_LG(buf, S390_REGNO_TCHAIN_SCRATCH, 0, b, DISP20(d)); /* 6 bytes */
9798 buf = s390_emit_BCR(buf, S390_CC_ALWAYS, S390_REGNO_TCHAIN_SCRATCH); /* 2 bytes */
9799
9800 code_end = buf;
9801
9802 /* Make sure the size of the generated code is identical to the size
9803 returned by evCheckSzB_S390 */
9804 vassert(evCheckSzB_S390() == code_end - code_begin);
9805
9806 return buf;
9807 }
9808
9809
9810 static UChar *
s390_insn_profinc_emit(UChar * buf,const s390_insn * insn)9811 s390_insn_profinc_emit(UChar *buf,
9812 const s390_insn *insn __attribute__((unused)))
9813 {
9814 /* Generate a code template to increment a memory location whose
9815 address will be known later as an immediate value. This code
9816 template will be patched once the memory location is known.
9817 For now we do this with address == 0. */
9818 buf = s390_tchain_load64(buf, S390_REGNO_TCHAIN_SCRATCH, 0);
9819 if (s390_host_has_gie) {
9820 buf = s390_emit_AGSI(buf, 1, S390_REGNO_TCHAIN_SCRATCH, DISP20(0));
9821 } else {
9822 buf = s390_emit_LGHI(buf, R0, 1);
9823 buf = s390_emit_AG( buf, R0, 0, S390_REGNO_TCHAIN_SCRATCH, DISP20(0));
9824 buf = s390_emit_STG(buf, R0, 0, S390_REGNO_TCHAIN_SCRATCH, DISP20(0));
9825 }
9826
9827 return buf;
9828 }
9829
9830
9831 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)9832 emit_S390Instr(Bool *is_profinc, UChar *buf, Int nbuf, const s390_insn *insn,
9833 Bool mode64, VexEndness endness_host,
9834 const void *disp_cp_chain_me_to_slowEP,
9835 const void *disp_cp_chain_me_to_fastEP,
9836 const void *disp_cp_xindir,
9837 const void *disp_cp_xassisted)
9838 {
9839 UChar *end;
9840
9841 /* Used to be 48 bytes. Make sure it stays low */
9842 vassert(sizeof(s390_insn) == 32);
9843
9844 switch (insn->tag) {
9845 case S390_INSN_LOAD:
9846 end = s390_insn_load_emit(buf, insn);
9847 break;
9848
9849 case S390_INSN_STORE:
9850 end = s390_insn_store_emit(buf, insn);
9851 break;
9852
9853 case S390_INSN_MOVE:
9854 end = s390_insn_move_emit(buf, insn);
9855 break;
9856
9857 case S390_INSN_MEMCPY:
9858 end = s390_insn_memcpy_emit(buf, insn);
9859 break;
9860
9861 case S390_INSN_COND_MOVE:
9862 end = s390_insn_cond_move_emit(buf, insn);
9863 break;
9864
9865 case S390_INSN_LOAD_IMMEDIATE:
9866 end = s390_insn_load_immediate_emit(buf, insn);
9867 break;
9868
9869 case S390_INSN_ALU:
9870 end = s390_insn_alu_emit(buf, insn);
9871 break;
9872
9873 case S390_INSN_SMUL:
9874 case S390_INSN_UMUL:
9875 end = s390_insn_mul_emit(buf, insn);
9876 break;
9877
9878 case S390_INSN_SDIV:
9879 case S390_INSN_UDIV:
9880 end = s390_insn_div_emit(buf, insn);
9881 break;
9882
9883 case S390_INSN_DIVS:
9884 end = s390_insn_divs_emit(buf, insn);
9885 break;
9886
9887 case S390_INSN_CLZ:
9888 end = s390_insn_clz_emit(buf, insn);
9889 break;
9890
9891 case S390_INSN_UNOP:
9892 end = s390_insn_unop_emit(buf, insn);
9893 break;
9894
9895 case S390_INSN_TEST:
9896 end = s390_insn_test_emit(buf, insn);
9897 break;
9898
9899 case S390_INSN_CC2BOOL:
9900 end = s390_insn_cc2bool_emit(buf, insn);
9901 break;
9902
9903 case S390_INSN_CAS:
9904 end = s390_insn_cas_emit(buf, insn);
9905 break;
9906
9907 case S390_INSN_CDAS:
9908 end = s390_insn_cdas_emit(buf, insn);
9909 break;
9910
9911 case S390_INSN_COMPARE:
9912 end = s390_insn_compare_emit(buf, insn);
9913 break;
9914
9915 case S390_INSN_HELPER_CALL:
9916 end = s390_insn_helper_call_emit(buf, insn);
9917 if (end == buf) goto fail;
9918 break;
9919
9920 case S390_INSN_BFP_TRIOP:
9921 end = s390_insn_bfp_triop_emit(buf, insn);
9922 break;
9923
9924 case S390_INSN_BFP_BINOP:
9925 end = s390_insn_bfp_binop_emit(buf, insn);
9926 break;
9927
9928 case S390_INSN_BFP_UNOP:
9929 end = s390_insn_bfp_unop_emit(buf, insn);
9930 break;
9931
9932 case S390_INSN_BFP_COMPARE:
9933 end = s390_insn_bfp_compare_emit(buf, insn);
9934 break;
9935
9936 case S390_INSN_BFP_CONVERT:
9937 end = s390_insn_bfp_convert_emit(buf, insn);
9938 break;
9939
9940 case S390_INSN_DFP_BINOP:
9941 end = s390_insn_dfp_binop_emit(buf, insn);
9942 break;
9943
9944 case S390_INSN_DFP_UNOP:
9945 end = s390_insn_dfp_unop_emit(buf, insn);
9946 break;
9947
9948 case S390_INSN_DFP_INTOP:
9949 end = s390_insn_dfp_intop_emit(buf, insn);
9950 break;
9951
9952 case S390_INSN_DFP_COMPARE:
9953 end = s390_insn_dfp_compare_emit(buf, insn);
9954 break;
9955
9956 case S390_INSN_DFP_CONVERT:
9957 end = s390_insn_dfp_convert_emit(buf, insn);
9958 break;
9959
9960 case S390_INSN_DFP_REROUND:
9961 end = s390_insn_dfp_reround_emit(buf, insn);
9962 break;
9963
9964 case S390_INSN_FP_CONVERT:
9965 end = s390_insn_fp_convert_emit(buf, insn);
9966 break;
9967
9968 case S390_INSN_MFENCE:
9969 end = s390_insn_mfence_emit(buf, insn);
9970 break;
9971
9972 case S390_INSN_MIMM:
9973 end = s390_insn_mimm_emit(buf, insn);
9974 break;
9975
9976 case S390_INSN_MADD:
9977 end = s390_insn_madd_emit(buf, insn);
9978 break;
9979
9980 case S390_INSN_SET_FPC_BFPRM:
9981 end = s390_insn_set_fpc_bfprm_emit(buf, insn);
9982 break;
9983
9984 case S390_INSN_SET_FPC_DFPRM:
9985 end = s390_insn_set_fpc_dfprm_emit(buf, insn);
9986 break;
9987
9988 case S390_INSN_PROFINC:
9989 end = s390_insn_profinc_emit(buf, insn);
9990 /* Tell the caller .. */
9991 vassert(*is_profinc == False);
9992 *is_profinc = True;
9993 break;
9994
9995 case S390_INSN_EVCHECK:
9996 end = s390_insn_evcheck_emit(buf, insn, endness_host);
9997 break;
9998
9999 case S390_INSN_XDIRECT:
10000 end = s390_insn_xdirect_emit(buf, insn, disp_cp_chain_me_to_slowEP,
10001 disp_cp_chain_me_to_fastEP);
10002 break;
10003
10004 case S390_INSN_XINDIR:
10005 end = s390_insn_xindir_emit(buf, insn, disp_cp_xindir);
10006 break;
10007
10008 case S390_INSN_XASSISTED:
10009 end = s390_insn_xassisted_emit(buf, insn, disp_cp_xassisted);
10010 break;
10011
10012 fail:
10013 default:
10014 vpanic("emit_S390Instr");
10015 }
10016
10017 vassert(end - buf <= nbuf);
10018
10019 return end - buf;
10020 }
10021
10022
10023 /* Return the number of bytes emitted for an S390_INSN_EVCHECK.
10024 See s390_insn_evcheck_emit */
10025 Int
evCheckSzB_S390(void)10026 evCheckSzB_S390(void)
10027 {
10028 return s390_host_has_gie ? 18 : 24;
10029 }
10030
10031
10032 /* Patch the counter address into CODE_TO_PATCH as previously
10033 generated by s390_insn_profinc_emit. */
10034 VexInvalRange
patchProfInc_S390(VexEndness endness_host,void * code_to_patch,const ULong * location_of_counter)10035 patchProfInc_S390(VexEndness endness_host,
10036 void *code_to_patch, const ULong *location_of_counter)
10037 {
10038 vassert(sizeof(ULong *) == 8);
10039
10040 s390_tchain_verify_load64(code_to_patch, S390_REGNO_TCHAIN_SCRATCH, 0);
10041
10042 UChar *p = s390_tchain_patch_load64(code_to_patch,
10043 (Addr)location_of_counter);
10044
10045 UInt len = p - (UChar *)code_to_patch;
10046 VexInvalRange vir = { (HWord)code_to_patch, len };
10047 return vir;
10048 }
10049
10050
10051 /* NB: what goes on here has to be very closely coordinated with the
10052 s390_insn_xdirect_emit code above. */
10053 VexInvalRange
chainXDirect_S390(VexEndness endness_host,void * place_to_chain,const void * disp_cp_chain_me_EXPECTED,const void * place_to_jump_to)10054 chainXDirect_S390(VexEndness endness_host,
10055 void *place_to_chain,
10056 const void *disp_cp_chain_me_EXPECTED,
10057 const void *place_to_jump_to)
10058 {
10059 vassert(endness_host == VexEndnessBE);
10060
10061 /* What we're expecting to see @ PLACE_TO_CHAIN is:
10062
10063 load tchain_scratch, #disp_cp_chain_me_EXPECTED
10064 goto *tchain_scratch
10065 */
10066 const UChar *next;
10067 next = s390_tchain_verify_load64(place_to_chain, S390_REGNO_TCHAIN_SCRATCH,
10068 (Addr)disp_cp_chain_me_EXPECTED);
10069 vassert(s390_insn_is_BR(next, S390_REGNO_TCHAIN_SCRATCH));
10070
10071 /* And what we want to change it to is either:
10072 (general case):
10073
10074 load tchain_scratch, #place_to_jump_to
10075 goto *tchain_scratch
10076
10077 ---OR---
10078
10079 in the case where the displacement is small enough
10080
10081 BRCL delta where delta is in half-words
10082 invalid opcodes
10083
10084 In both cases the replacement has the same length as the original.
10085 To remain sane & verifiable,
10086 (1) limit the displacement for the short form to
10087 (say) +/- one billion, so as to avoid wraparound
10088 off-by-ones
10089 (2) even if the short form is applicable, once every (say)
10090 1024 times use the long form anyway, so as to maintain
10091 verifiability
10092 */
10093
10094 /* This is the delta we need to put into a BRCL insn. Note, that the
10095 offset in BRCL is in half-words. Hence division by 2. */
10096 Long delta =
10097 (Long)((const UChar *)place_to_jump_to - (const UChar *)place_to_chain) / 2;
10098 Bool shortOK = delta >= -1000*1000*1000 && delta < 1000*1000*1000;
10099
10100 static UInt shortCTR = 0; /* DO NOT MAKE NON-STATIC */
10101 if (shortOK) {
10102 shortCTR++; // thread safety bleh
10103 if (0 == (shortCTR & 0x3FF)) {
10104 shortOK = False;
10105 if (0)
10106 vex_printf("QQQ chainXDirect_S390: shortCTR = %u, "
10107 "using long jmp\n", shortCTR);
10108 }
10109 }
10110
10111 /* And make the modifications. */
10112 UChar *p = (UChar *)place_to_chain;
10113 if (shortOK) {
10114 p = s390_emit_BRCL(p, S390_CC_ALWAYS, delta); /* 6 bytes */
10115
10116 /* Make sure that BRCL fits into the patchable part of an xdirect
10117 code sequence */
10118 vassert(6 <= s390_xdirect_patchable_len());
10119
10120 /* Fill remaining bytes with 0x00 (invalid opcode) */
10121 Int i;
10122 for (i = 0; i < s390_xdirect_patchable_len() - 6; ++i)
10123 p[i] = 0x00;
10124 } else {
10125 /*
10126 load tchain_scratch, #place_to_jump_to
10127 goto *tchain_scratch
10128 */
10129 Addr64 addr = (Addr)place_to_jump_to;
10130 p = s390_tchain_load64(p, S390_REGNO_TCHAIN_SCRATCH, addr);
10131 /* There is not need to emit a BCR here, as it is already there. */
10132 }
10133
10134 UInt len = p - (UChar *)place_to_chain;
10135 VexInvalRange vir = { (HWord)place_to_chain, len };
10136 return vir;
10137 }
10138
10139
10140 /* NB: what goes on here has to be very closely coordinated with the
10141 s390_insn_xdirect_emit code above. */
10142 VexInvalRange
unchainXDirect_S390(VexEndness endness_host,void * place_to_unchain,const void * place_to_jump_to_EXPECTED,const void * disp_cp_chain_me)10143 unchainXDirect_S390(VexEndness endness_host,
10144 void *place_to_unchain,
10145 const void *place_to_jump_to_EXPECTED,
10146 const void *disp_cp_chain_me)
10147 {
10148 vassert(endness_host == VexEndnessBE);
10149
10150 /* What we're expecting to see @ PLACE_TO_UNCHAIN:
10151
10152 load tchain_scratch, #place_to_jump_to_EXPECTED
10153 goto *tchain_scratch
10154
10155 ---OR---
10156 in the case where the displacement falls within 32 bits
10157
10158 BRCL delta
10159 invalid opcodes
10160 */
10161 UChar *p = place_to_unchain;
10162
10163 Bool uses_short_form = False;
10164
10165 if (s390_insn_is_BRCL(p, S390_CC_ALWAYS)) {
10166 /* Looks like the short form */
10167 Int num_hw = *(Int *)&p[2];
10168 Int delta = 2 *num_hw;
10169
10170 vassert(p + delta == place_to_jump_to_EXPECTED);
10171
10172 Int i;
10173 for (i = 0; i < s390_xdirect_patchable_len() - 6; ++i)
10174 vassert(p[6+i] == 0x00);
10175 uses_short_form = True;
10176 } else {
10177 /* Should be the long form */
10178 const UChar *next;
10179
10180 next = s390_tchain_verify_load64(p, S390_REGNO_TCHAIN_SCRATCH,
10181 (Addr)place_to_jump_to_EXPECTED);
10182 /* Check for BR *tchain_scratch */
10183 vassert(s390_insn_is_BR(next, S390_REGNO_TCHAIN_SCRATCH));
10184 }
10185
10186 /* And what we want to change it to is:
10187
10188 load tchain_scratch, #disp_cp_chain_me
10189 goto *tchain_scratch
10190 */
10191
10192 /* Get the address of the beginning of the load64 code sequence into %r1.
10193 Do not change the register! This is part of the protocol with the
10194 dispatcher.
10195 Note: the incoming argument PLACE_TO_CHAIN points to the beginning of the
10196 load64 insn sequence. That sequence is prefixed with a BASR to get its
10197 address (see s390_insn_xdirect_emit). */
10198 p = s390_emit_BASR(p - S390_BASR_LEN, 1, R0);
10199
10200 Addr64 addr = (Addr)disp_cp_chain_me;
10201 p = s390_tchain_load64(p, S390_REGNO_TCHAIN_SCRATCH, addr);
10202
10203 /* Emit the BCR in case the short form was used. In case of the long
10204 form, the BCR is already there. */
10205 if (uses_short_form)
10206 s390_emit_BCR(p, S390_CC_ALWAYS, S390_REGNO_TCHAIN_SCRATCH);
10207
10208 UInt len = p - (UChar *)place_to_unchain;
10209 VexInvalRange vir = { (HWord)place_to_unchain, len };
10210 return vir;
10211 }
10212
10213 /*---------------------------------------------------------------*/
10214 /*--- end host_s390_defs.c ---*/
10215 /*---------------------------------------------------------------*/
10216