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