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-2011
12
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
26 02110-1301, USA.
27
28 The GNU General Public License is contained in the file COPYING.
29 */
30
31 /* Contributed by Florian Krohm */
32
33 #include "libvex_basictypes.h"
34 #include "libvex.h"
35 #include "libvex_trc_values.h"
36 #include "libvex_guest_offsets.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 "host_s390_disasm.h"
44 #include <stdarg.h>
45
46 /* KLUDGE: We need to know the hwcaps of the host when generating
47 code. But that info is not passed to emit_S390Instr. Only mode64 is
48 being passed. So, ideally, we want this passed as an argument, too.
49 Until then, we use a global variable. This variable is set as a side
50 effect of iselSB_S390. This is safe because instructions are selected
51 before they are emitted. */
52 const VexArchInfo *s390_archinfo_host;
53
54
55 /*------------------------------------------------------------*/
56 /*--- Forward declarations ---*/
57 /*------------------------------------------------------------*/
58
59 static Bool s390_insn_is_reg_reg_move(const s390_insn *, HReg *src, HReg *dst);
60 static void s390_insn_map_regs(HRegRemap *, s390_insn *);
61 static void s390_insn_get_reg_usage(HRegUsage *u, const s390_insn *);
62
63
64 /*------------------------------------------------------------*/
65 /*--- Registers ---*/
66 /*------------------------------------------------------------*/
67
68 /* Decompile the given register into a static buffer and return it */
69 const HChar *
s390_hreg_as_string(HReg reg)70 s390_hreg_as_string(HReg reg)
71 {
72 static HChar buf[10];
73
74 static const HChar ireg_names[16][5] = {
75 "%r0", "%r1", "%r2", "%r3", "%r4", "%r5", "%r6", "%r7",
76 "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15"
77 };
78
79 static const HChar freg_names[16][5] = {
80 "%f0", "%f1", "%f2", "%f3", "%f4", "%f5", "%f6", "%f7",
81 "%f8", "%f9", "%f10", "%f11", "%f12", "%f13", "%f14", "%f15"
82 };
83
84 UInt r; /* hregNumber() returns an UInt */
85
86 r = hregNumber(reg);
87
88 /* Be generic for all virtual regs. */
89 if (hregIsVirtual(reg)) {
90 buf[0] = '\0';
91 switch (hregClass(reg)) {
92 case HRcInt64: vex_sprintf(buf, "%%vR%d", r); break;
93 case HRcFlt64: vex_sprintf(buf, "%%vF%d", r); break;
94 default: goto fail;
95 }
96 return buf;
97 }
98
99 /* But specific for real regs. */
100 vassert(r < 16);
101
102 switch (hregClass(reg)) {
103 case HRcInt64: return ireg_names[r];
104 case HRcFlt64: return freg_names[r];
105 default: goto fail;
106 }
107
108 fail: vpanic("s390_hreg_as_string");
109 }
110
111
112 /* Tell the register allocator which registers can be allocated. */
113 static void
s390_hreg_get_allocable(Int * nregs,HReg ** arr)114 s390_hreg_get_allocable(Int *nregs, HReg **arr)
115 {
116 UInt i;
117
118 /* Total number of allocable registers (all classes) */
119 *nregs = 16 /* GPRs */
120 - 1 /* r0 */
121 - 1 /* r12 register holding VG_(dispatch_ctr) */
122 - 1 /* r13 guest state pointer */
123 - 1 /* r14 link register */
124 - 1 /* r15 stack pointer */
125 + 16 /* FPRs */
126 ;
127
128 *arr = LibVEX_Alloc(*nregs * sizeof(HReg));
129
130 i = 0;
131
132 /* GPR0 is not available because it is interpreted as 0, when used
133 as a base or index register. */
134 (*arr)[i++] = mkHReg(1, HRcInt64, False);
135 (*arr)[i++] = mkHReg(2, HRcInt64, False);
136 (*arr)[i++] = mkHReg(3, HRcInt64, False);
137 (*arr)[i++] = mkHReg(4, HRcInt64, False);
138 (*arr)[i++] = mkHReg(5, HRcInt64, False);
139 (*arr)[i++] = mkHReg(6, HRcInt64, False);
140 (*arr)[i++] = mkHReg(7, HRcInt64, False);
141 (*arr)[i++] = mkHReg(8, HRcInt64, False);
142 (*arr)[i++] = mkHReg(9, HRcInt64, False);
143 /* GPR10 and GPR11 are used for instructions that use register pairs.
144 Otherwise, they are available to the allocator */
145 (*arr)[i++] = mkHReg(10, HRcInt64, False);
146 (*arr)[i++] = mkHReg(11, HRcInt64, False);
147 /* GPR12 is not available because it caches VG_(dispatch_ctr) */
148 /* GPR13 is not available because it is used as guest state pointer */
149 /* GPR14 is not available because it is used as link register */
150 /* GPR15 is not available because it is used as stack pointer */
151
152 /* Add the available real (non-virtual) FPRs */
153 (*arr)[i++] = mkHReg(0, HRcFlt64, False);
154 (*arr)[i++] = mkHReg(1, HRcFlt64, False);
155 (*arr)[i++] = mkHReg(2, HRcFlt64, False);
156 (*arr)[i++] = mkHReg(3, HRcFlt64, False);
157 (*arr)[i++] = mkHReg(4, HRcFlt64, False);
158 (*arr)[i++] = mkHReg(5, HRcFlt64, False);
159 (*arr)[i++] = mkHReg(6, HRcFlt64, False);
160 (*arr)[i++] = mkHReg(7, HRcFlt64, False);
161 (*arr)[i++] = mkHReg(8, HRcFlt64, False);
162 (*arr)[i++] = mkHReg(9, HRcFlt64, False);
163 (*arr)[i++] = mkHReg(10, HRcFlt64, False);
164 (*arr)[i++] = mkHReg(11, HRcFlt64, False);
165 (*arr)[i++] = mkHReg(12, HRcFlt64, False);
166 (*arr)[i++] = mkHReg(13, HRcFlt64, False);
167 (*arr)[i++] = mkHReg(14, HRcFlt64, False);
168 (*arr)[i++] = mkHReg(15, HRcFlt64, False);
169 /* FPR12 - FPR15 are also used as register pairs for 128-bit
170 floating point operations */
171 }
172
173
174 /* Return the real register that holds the guest state pointer */
175 HReg
s390_hreg_guest_state_pointer(void)176 s390_hreg_guest_state_pointer(void)
177 {
178 return mkHReg(S390_REGNO_GUEST_STATE_POINTER, HRcInt64, False);
179 }
180
181 /* Is VALUE within the domain of a 20-bit signed integer. */
182 static __inline__ Bool
fits_signed_20bit(Int value)183 fits_signed_20bit(Int value)
184 {
185 return ((value << 12) >> 12) == value;
186 }
187
188
189 /* Is VALUE within the domain of a 12-bit unsigned integer. */
190 static __inline__ Bool
fits_unsigned_12bit(Int value)191 fits_unsigned_12bit(Int value)
192 {
193 return (value & 0xFFF) == value;
194 }
195
196 /*------------------------------------------------------------*/
197 /*--- Addressing modes (amodes) ---*/
198 /*------------------------------------------------------------*/
199
200 /* Construct a b12 amode. */
201 s390_amode *
s390_amode_b12(Int d,HReg b)202 s390_amode_b12(Int d, HReg b)
203 {
204 s390_amode *am = LibVEX_Alloc(sizeof(s390_amode));
205
206 vassert(fits_unsigned_12bit(d));
207
208 am->tag = S390_AMODE_B12;
209 am->d = d;
210 am->b = b;
211 am->x = 0; /* hregNumber(0) == 0 */
212
213 return am;
214 }
215
216
217 /* Construct a b20 amode. */
218 s390_amode *
s390_amode_b20(Int d,HReg b)219 s390_amode_b20(Int d, HReg b)
220 {
221 s390_amode *am = LibVEX_Alloc(sizeof(s390_amode));
222
223 vassert(fits_signed_20bit(d));
224
225 am->tag = S390_AMODE_B20;
226 am->d = d;
227 am->b = b;
228 am->x = 0; /* hregNumber(0) == 0 */
229
230 return am;
231 }
232
233
234 /* Construct a bx12 amode. */
235 s390_amode *
s390_amode_bx12(Int d,HReg b,HReg x)236 s390_amode_bx12(Int d, HReg b, HReg x)
237 {
238 s390_amode *am = LibVEX_Alloc(sizeof(s390_amode));
239
240 vassert(fits_unsigned_12bit(d));
241 vassert(b != 0);
242 vassert(x != 0);
243
244 am->tag = S390_AMODE_BX12;
245 am->d = d;
246 am->b = b;
247 am->x = x;
248
249 return am;
250 }
251
252
253 /* Construct a bx20 amode. */
254 s390_amode *
s390_amode_bx20(Int d,HReg b,HReg x)255 s390_amode_bx20(Int d, HReg b, HReg x)
256 {
257 s390_amode *am = LibVEX_Alloc(sizeof(s390_amode));
258
259 vassert(fits_signed_20bit(d));
260 vassert(b != 0);
261 vassert(x != 0);
262
263 am->tag = S390_AMODE_BX20;
264 am->d = d;
265 am->b = b;
266 am->x = x;
267
268 return am;
269 }
270
271
272 /* Construct an AMODE for accessing the guest state at OFFSET */
273 s390_amode *
s390_amode_for_guest_state(Int offset)274 s390_amode_for_guest_state(Int offset)
275 {
276 if (fits_unsigned_12bit(offset))
277 return s390_amode_b12(offset, s390_hreg_guest_state_pointer());
278
279 vpanic("invalid guest state offset");
280 }
281
282
283 /* Decompile the given amode into a static buffer and return it. */
284 const HChar *
s390_amode_as_string(const s390_amode * am)285 s390_amode_as_string(const s390_amode *am)
286 {
287 static HChar buf[30];
288 HChar *p;
289
290 buf[0] = '\0';
291 p = buf;
292
293 switch (am->tag) {
294 case S390_AMODE_B12:
295 case S390_AMODE_B20:
296 vex_sprintf(p, "%d(%s)", am->d, s390_hreg_as_string(am->b));
297 break;
298
299 case S390_AMODE_BX12:
300 case S390_AMODE_BX20:
301 /* s390_hreg_as_string returns pointer to local buffer. Need to
302 split this into two printfs */
303 p += vex_sprintf(p, "%d(%s,", am->d, s390_hreg_as_string(am->x));
304 vex_sprintf(p, "%s)", s390_hreg_as_string(am->b));
305 break;
306
307 default:
308 vpanic("s390_amode_as_string");
309 }
310
311 return buf;
312 }
313
314
315 /* Helper function for s390_amode_is_sane */
316 static __inline__ Bool
is_virtual_gpr(HReg reg)317 is_virtual_gpr(HReg reg)
318 {
319 return hregIsVirtual(reg) && hregClass(reg) == HRcInt64;
320 }
321
322
323 /* Sanity check for an amode */
324 Bool
s390_amode_is_sane(const s390_amode * am)325 s390_amode_is_sane(const s390_amode *am)
326 {
327 switch (am->tag) {
328 case S390_AMODE_B12:
329 return is_virtual_gpr(am->b) && fits_unsigned_12bit(am->d);
330
331 case S390_AMODE_B20:
332 return is_virtual_gpr(am->b) && fits_signed_20bit(am->d);
333
334 case S390_AMODE_BX12:
335 return is_virtual_gpr(am->b) && is_virtual_gpr(am->x) &&
336 fits_unsigned_12bit(am->d);
337
338 case S390_AMODE_BX20:
339 return is_virtual_gpr(am->b) && is_virtual_gpr(am->x) &&
340 fits_signed_20bit(am->d);
341
342 default:
343 vpanic("s390_amode_is_sane");
344 }
345 }
346
347
348 /* Record the register use of an amode */
349 static void
s390_amode_get_reg_usage(HRegUsage * u,const s390_amode * am)350 s390_amode_get_reg_usage(HRegUsage *u, const s390_amode *am)
351 {
352 switch (am->tag) {
353 case S390_AMODE_B12:
354 case S390_AMODE_B20:
355 addHRegUse(u, HRmRead, am->b);
356 return;
357
358 case S390_AMODE_BX12:
359 case S390_AMODE_BX20:
360 addHRegUse(u, HRmRead, am->b);
361 addHRegUse(u, HRmRead, am->x);
362 return;
363
364 default:
365 vpanic("s390_amode_get_reg_usage");
366 }
367 }
368
369
370 static void
s390_amode_map_regs(HRegRemap * m,s390_amode * am)371 s390_amode_map_regs(HRegRemap *m, s390_amode *am)
372 {
373 switch (am->tag) {
374 case S390_AMODE_B12:
375 case S390_AMODE_B20:
376 am->b = lookupHRegRemap(m, am->b);
377 return;
378
379 case S390_AMODE_BX12:
380 case S390_AMODE_BX20:
381 am->b = lookupHRegRemap(m, am->b);
382 am->x = lookupHRegRemap(m, am->x);
383 return;
384
385 default:
386 vpanic("s390_amode_map_regs");
387 }
388 }
389
390
391 void
ppS390AMode(s390_amode * am)392 ppS390AMode(s390_amode *am)
393 {
394 vex_printf("%s", s390_amode_as_string(am));
395 }
396
397 void
ppS390Instr(s390_insn * insn,Bool mode64)398 ppS390Instr(s390_insn *insn, Bool mode64)
399 {
400 vex_printf("%s", s390_insn_as_string(insn));
401 }
402
403 void
ppHRegS390(HReg reg)404 ppHRegS390(HReg reg)
405 {
406 vex_printf("%s", s390_hreg_as_string(reg));
407 }
408
409 /*------------------------------------------------------------*/
410 /*--- Helpers for register allocation ---*/
411 /*------------------------------------------------------------*/
412
413 /* Called once per translation. */
414 void
getAllocableRegs_S390(Int * nregs,HReg ** arr,Bool mode64)415 getAllocableRegs_S390(Int *nregs, HReg **arr, Bool mode64)
416 {
417 s390_hreg_get_allocable(nregs, arr);
418 }
419
420
421 /* Tell the register allocator how the given instruction uses the registers
422 it refers to. */
423 void
getRegUsage_S390Instr(HRegUsage * u,s390_insn * insn,Bool mode64)424 getRegUsage_S390Instr(HRegUsage *u, s390_insn *insn, Bool mode64)
425 {
426 s390_insn_get_reg_usage(u, insn);
427 }
428
429
430 /* Map the registers of the given instruction */
431 void
mapRegs_S390Instr(HRegRemap * m,s390_insn * insn,Bool mode64)432 mapRegs_S390Instr(HRegRemap *m, s390_insn *insn, Bool mode64)
433 {
434 s390_insn_map_regs(m, insn);
435 }
436
437
438 /* Figure out if the given insn represents a reg-reg move, and if so
439 assign the source and destination to *src and *dst. If in doubt say No.
440 Used by the register allocator to do move coalescing. */
441 Bool
isMove_S390Instr(s390_insn * insn,HReg * src,HReg * dst)442 isMove_S390Instr(s390_insn *insn, HReg *src, HReg *dst)
443 {
444 return s390_insn_is_reg_reg_move(insn, src, dst);
445 }
446
447
448 /* Generate s390 spill/reload instructions under the direction of the
449 register allocator. Note it's critical these don't write the
450 condition codes. This is like an Ist_Put */
451 void
genSpill_S390(HInstr ** i1,HInstr ** i2,HReg rreg,Int offsetB,Bool mode64)452 genSpill_S390(HInstr **i1, HInstr **i2, HReg rreg, Int offsetB, Bool mode64)
453 {
454 s390_amode *am;
455
456 vassert(offsetB >= 0);
457 vassert(offsetB <= (1 << 12)); /* because we use b12 amode */
458 vassert(!hregIsVirtual(rreg));
459
460 *i1 = *i2 = NULL;
461
462 am = s390_amode_for_guest_state(offsetB);
463
464 switch (hregClass(rreg)) {
465 case HRcInt64:
466 case HRcFlt64:
467 *i1 = s390_insn_store(8, am, rreg);
468 return;
469
470 default:
471 ppHRegClass(hregClass(rreg));
472 vpanic("genSpill_S390: unimplemented regclass");
473 }
474 }
475
476
477 /* This is like an Iex_Get */
478 void
genReload_S390(HInstr ** i1,HInstr ** i2,HReg rreg,Int offsetB,Bool mode64)479 genReload_S390(HInstr **i1, HInstr **i2, HReg rreg, Int offsetB, Bool mode64)
480 {
481 s390_amode *am;
482
483 vassert(offsetB >= 0);
484 vassert(offsetB <= (1 << 12)); /* because we use b12 amode */
485 vassert(!hregIsVirtual(rreg));
486
487 *i1 = *i2 = NULL;
488
489 am = s390_amode_for_guest_state(offsetB);
490
491 switch (hregClass(rreg)) {
492 case HRcInt64:
493 case HRcFlt64:
494 *i1 = s390_insn_load(8, rreg, am);
495 return;
496
497 default:
498 ppHRegClass(hregClass(rreg));
499 vpanic("genReload_S390: unimplemented regclass");
500 }
501 }
502
503 /* Helper function for s390_insn_get_reg_usage */
504 static void
s390_opnd_RMI_get_reg_usage(HRegUsage * u,s390_opnd_RMI op)505 s390_opnd_RMI_get_reg_usage(HRegUsage *u, s390_opnd_RMI op)
506 {
507 switch (op.tag) {
508 case S390_OPND_REG:
509 addHRegUse(u, HRmRead, op.variant.reg);
510 break;
511
512 case S390_OPND_AMODE:
513 s390_amode_get_reg_usage(u, op.variant.am);
514 break;
515
516 case S390_OPND_IMMEDIATE:
517 break;
518
519 default:
520 vpanic("s390_opnd_RMI_get_reg_usage");
521 }
522 }
523
524
525 /* Tell the register allocator how the given insn uses the registers */
526 static void
s390_insn_get_reg_usage(HRegUsage * u,const s390_insn * insn)527 s390_insn_get_reg_usage(HRegUsage *u, const s390_insn *insn)
528 {
529 initHRegUsage(u);
530
531 switch (insn->tag) {
532 case S390_INSN_LOAD:
533 addHRegUse(u, HRmWrite, insn->variant.load.dst);
534 s390_amode_get_reg_usage(u, insn->variant.load.src);
535 break;
536
537 case S390_INSN_LOAD_IMMEDIATE:
538 addHRegUse(u, HRmWrite, insn->variant.load_immediate.dst);
539 break;
540
541 case S390_INSN_STORE:
542 addHRegUse(u, HRmRead, insn->variant.store.src);
543 s390_amode_get_reg_usage(u, insn->variant.store.dst);
544 break;
545
546 case S390_INSN_MOVE:
547 addHRegUse(u, HRmRead, insn->variant.move.src);
548 addHRegUse(u, HRmWrite, insn->variant.move.dst);
549 break;
550
551 case S390_INSN_COND_MOVE:
552 s390_opnd_RMI_get_reg_usage(u, insn->variant.cond_move.src);
553 addHRegUse(u, HRmWrite, insn->variant.cond_move.dst);
554 break;
555
556 case S390_INSN_ALU:
557 addHRegUse(u, HRmWrite, insn->variant.alu.dst);
558 addHRegUse(u, HRmRead, insn->variant.alu.dst); /* op1 */
559 s390_opnd_RMI_get_reg_usage(u, insn->variant.alu.op2);
560 break;
561
562 case S390_INSN_MUL:
563 addHRegUse(u, HRmRead, insn->variant.mul.dst_lo); /* op1 */
564 addHRegUse(u, HRmWrite, insn->variant.mul.dst_lo);
565 addHRegUse(u, HRmWrite, insn->variant.mul.dst_hi);
566 s390_opnd_RMI_get_reg_usage(u, insn->variant.mul.op2);
567 break;
568
569 case S390_INSN_DIV:
570 addHRegUse(u, HRmRead, insn->variant.div.op1_lo);
571 addHRegUse(u, HRmRead, insn->variant.div.op1_hi);
572 addHRegUse(u, HRmWrite, insn->variant.div.op1_lo);
573 addHRegUse(u, HRmWrite, insn->variant.div.op1_hi);
574 s390_opnd_RMI_get_reg_usage(u, insn->variant.div.op2);
575 break;
576
577 case S390_INSN_DIVS:
578 addHRegUse(u, HRmRead, insn->variant.divs.op1);
579 addHRegUse(u, HRmWrite, insn->variant.divs.op1); /* quotient */
580 addHRegUse(u, HRmWrite, insn->variant.divs.rem); /* remainder */
581 s390_opnd_RMI_get_reg_usage(u, insn->variant.divs.op2);
582 break;
583
584 case S390_INSN_CLZ:
585 addHRegUse(u, HRmWrite, insn->variant.clz.num_bits);
586 addHRegUse(u, HRmWrite, insn->variant.clz.clobber);
587 s390_opnd_RMI_get_reg_usage(u, insn->variant.clz.src);
588 break;
589
590 case S390_INSN_UNOP:
591 addHRegUse(u, HRmWrite, insn->variant.unop.dst);
592 s390_opnd_RMI_get_reg_usage(u, insn->variant.unop.src);
593 break;
594
595 case S390_INSN_TEST:
596 s390_opnd_RMI_get_reg_usage(u, insn->variant.test.src);
597 break;
598
599 case S390_INSN_CC2BOOL:
600 addHRegUse(u, HRmWrite, insn->variant.cc2bool.dst);
601 break;
602
603 case S390_INSN_CAS:
604 addHRegUse(u, HRmRead, insn->variant.cas.op1);
605 s390_amode_get_reg_usage(u, insn->variant.cas.op2);
606 addHRegUse(u, HRmRead, insn->variant.cas.op3);
607 addHRegUse(u, HRmWrite, insn->variant.cas.old_mem);
608 break;
609
610 case S390_INSN_COMPARE:
611 addHRegUse(u, HRmRead, insn->variant.compare.src1);
612 s390_opnd_RMI_get_reg_usage(u, insn->variant.compare.src2);
613 break;
614
615 case S390_INSN_BRANCH:
616 s390_opnd_RMI_get_reg_usage(u, insn->variant.branch.dst);
617 /* The destination address is loaded into S390_REGNO_RETURN_VALUE.
618 See s390_insn_branch_emit. */
619 addHRegUse(u, HRmWrite,
620 mkHReg(S390_REGNO_RETURN_VALUE, HRcInt64, False));
621 break;
622
623 case S390_INSN_HELPER_CALL: {
624 UInt i;
625
626 /* Assume that all volatile registers are clobbered. ABI says,
627 volatile registers are: r0 - r5. Valgrind's register allocator
628 does not know about r0, so we can leave that out */
629 for (i = 1; i <= 5; ++i) {
630 addHRegUse(u, HRmWrite, mkHReg(i, HRcInt64, False));
631 }
632
633 /* Ditto for floating point registers. f0 - f7 are volatile */
634 for (i = 0; i <= 7; ++i) {
635 addHRegUse(u, HRmWrite, mkHReg(i, HRcFlt64, False));
636 }
637
638 /* The registers that are used for passing arguments will be read.
639 Not all of them may, but in general we need to assume that. */
640 for (i = 0; i < insn->variant.helper_call.num_args; ++i) {
641 addHRegUse(u, HRmRead, mkHReg(s390_gprno_from_arg_index(i),
642 HRcInt64, False));
643 }
644
645 /* s390_insn_helper_call_emit also reads / writes the link register
646 and stack pointer. But those registers are not visible to the
647 register allocator. So we don't need to do anything for them. */
648 break;
649 }
650
651 case S390_INSN_BFP_TRIOP:
652 addHRegUse(u, HRmWrite, insn->variant.bfp_triop.dst);
653 addHRegUse(u, HRmRead, insn->variant.bfp_triop.dst); /* first */
654 addHRegUse(u, HRmRead, insn->variant.bfp_triop.op2); /* second */
655 addHRegUse(u, HRmRead, insn->variant.bfp_triop.op3); /* third */
656 break;
657
658 case S390_INSN_BFP_BINOP:
659 addHRegUse(u, HRmWrite, insn->variant.bfp_binop.dst);
660 addHRegUse(u, HRmRead, insn->variant.bfp_binop.dst); /* left */
661 addHRegUse(u, HRmRead, insn->variant.bfp_binop.op2); /* right */
662 break;
663
664 case S390_INSN_BFP_UNOP:
665 addHRegUse(u, HRmWrite, insn->variant.bfp_unop.dst);
666 addHRegUse(u, HRmRead, insn->variant.bfp_unop.op); /* operand */
667 break;
668
669 case S390_INSN_BFP_COMPARE:
670 addHRegUse(u, HRmWrite, insn->variant.bfp_compare.dst);
671 addHRegUse(u, HRmRead, insn->variant.bfp_compare.op1); /* left */
672 addHRegUse(u, HRmRead, insn->variant.bfp_compare.op2); /* right */
673 break;
674
675 case S390_INSN_BFP128_BINOP:
676 addHRegUse(u, HRmWrite, insn->variant.bfp128_binop.dst_hi);
677 addHRegUse(u, HRmWrite, insn->variant.bfp128_binop.dst_lo);
678 addHRegUse(u, HRmRead, insn->variant.bfp128_binop.dst_hi); /* left */
679 addHRegUse(u, HRmRead, insn->variant.bfp128_binop.dst_lo); /* left */
680 addHRegUse(u, HRmRead, insn->variant.bfp128_binop.op2_hi); /* right */
681 addHRegUse(u, HRmRead, insn->variant.bfp128_binop.op2_lo); /* right */
682 break;
683
684 case S390_INSN_BFP128_COMPARE:
685 addHRegUse(u, HRmWrite, insn->variant.bfp128_compare.dst);
686 addHRegUse(u, HRmRead, insn->variant.bfp128_compare.op1_hi); /* left */
687 addHRegUse(u, HRmRead, insn->variant.bfp128_compare.op1_lo); /* left */
688 addHRegUse(u, HRmRead, insn->variant.bfp128_compare.op2_hi); /* right */
689 addHRegUse(u, HRmRead, insn->variant.bfp128_compare.op2_lo); /* right */
690 break;
691
692 case S390_INSN_BFP128_UNOP:
693 addHRegUse(u, HRmWrite, insn->variant.bfp128_unop.dst_hi);
694 addHRegUse(u, HRmWrite, insn->variant.bfp128_unop.dst_lo);
695 addHRegUse(u, HRmRead, insn->variant.bfp128_unop.op_hi);
696 addHRegUse(u, HRmRead, insn->variant.bfp128_unop.op_lo);
697 break;
698
699 case S390_INSN_BFP128_CONVERT_TO:
700 addHRegUse(u, HRmWrite, insn->variant.bfp128_unop.dst_hi);
701 addHRegUse(u, HRmWrite, insn->variant.bfp128_unop.dst_lo);
702 addHRegUse(u, HRmRead, insn->variant.bfp128_unop.op_hi);
703 break;
704
705 case S390_INSN_BFP128_CONVERT_FROM:
706 addHRegUse(u, HRmWrite, insn->variant.bfp128_unop.dst_hi);
707 addHRegUse(u, HRmRead, insn->variant.bfp128_unop.op_hi);
708 addHRegUse(u, HRmRead, insn->variant.bfp128_unop.op_lo);
709 break;
710
711 case S390_INSN_MFENCE:
712 break;
713
714 default:
715 vpanic("s390_insn_get_reg_usage");
716 }
717 }
718
719
720 /* Helper function for s390_insn_map_regs */
721 static void
s390_opnd_RMI_map_regs(HRegRemap * m,s390_opnd_RMI * op)722 s390_opnd_RMI_map_regs(HRegRemap *m, s390_opnd_RMI *op)
723 {
724 switch (op->tag) {
725 case S390_OPND_REG:
726 op->variant.reg = lookupHRegRemap(m, op->variant.reg);
727 break;
728
729 case S390_OPND_IMMEDIATE:
730 break;
731
732 case S390_OPND_AMODE:
733 s390_amode_map_regs(m, op->variant.am);
734 break;
735
736 default:
737 vpanic("s390_opnd_RMI_map_regs");
738 }
739 }
740
741
742 static void
s390_insn_map_regs(HRegRemap * m,s390_insn * insn)743 s390_insn_map_regs(HRegRemap *m, s390_insn *insn)
744 {
745 switch (insn->tag) {
746 case S390_INSN_LOAD:
747 insn->variant.load.dst = lookupHRegRemap(m, insn->variant.load.dst);
748 s390_amode_map_regs(m, insn->variant.load.src);
749 break;
750
751 case S390_INSN_STORE:
752 s390_amode_map_regs(m, insn->variant.store.dst);
753 insn->variant.store.src = lookupHRegRemap(m, insn->variant.store.src);
754 break;
755
756 case S390_INSN_MOVE:
757 insn->variant.move.dst = lookupHRegRemap(m, insn->variant.move.dst);
758 insn->variant.move.src = lookupHRegRemap(m, insn->variant.move.src);
759 break;
760
761 case S390_INSN_COND_MOVE:
762 insn->variant.cond_move.dst = lookupHRegRemap(m, insn->variant.cond_move.dst);
763 s390_opnd_RMI_map_regs(m, &insn->variant.cond_move.src);
764 break;
765
766 case S390_INSN_LOAD_IMMEDIATE:
767 insn->variant.load_immediate.dst =
768 lookupHRegRemap(m, insn->variant.load_immediate.dst);
769 break;
770
771 case S390_INSN_ALU:
772 insn->variant.alu.dst = lookupHRegRemap(m, insn->variant.alu.dst);
773 s390_opnd_RMI_map_regs(m, &insn->variant.alu.op2);
774 break;
775
776 case S390_INSN_MUL:
777 insn->variant.mul.dst_hi = lookupHRegRemap(m, insn->variant.mul.dst_hi);
778 insn->variant.mul.dst_lo = lookupHRegRemap(m, insn->variant.mul.dst_lo);
779 s390_opnd_RMI_map_regs(m, &insn->variant.mul.op2);
780 break;
781
782 case S390_INSN_DIV:
783 insn->variant.div.op1_hi = lookupHRegRemap(m, insn->variant.div.op1_hi);
784 insn->variant.div.op1_lo = lookupHRegRemap(m, insn->variant.div.op1_lo);
785 s390_opnd_RMI_map_regs(m, &insn->variant.div.op2);
786 break;
787
788 case S390_INSN_DIVS:
789 insn->variant.divs.op1 = lookupHRegRemap(m, insn->variant.divs.op1);
790 insn->variant.divs.rem = lookupHRegRemap(m, insn->variant.divs.rem);
791 s390_opnd_RMI_map_regs(m, &insn->variant.divs.op2);
792 break;
793
794 case S390_INSN_CLZ:
795 insn->variant.clz.num_bits = lookupHRegRemap(m, insn->variant.clz.num_bits);
796 insn->variant.clz.clobber = lookupHRegRemap(m, insn->variant.clz.clobber);
797 s390_opnd_RMI_map_regs(m, &insn->variant.clz.src);
798 break;
799
800 case S390_INSN_UNOP:
801 insn->variant.unop.dst = lookupHRegRemap(m, insn->variant.unop.dst);
802 s390_opnd_RMI_map_regs(m, &insn->variant.unop.src);
803 break;
804
805 case S390_INSN_TEST:
806 s390_opnd_RMI_map_regs(m, &insn->variant.test.src);
807 break;
808
809 case S390_INSN_CC2BOOL:
810 insn->variant.cc2bool.dst = lookupHRegRemap(m, insn->variant.cc2bool.dst);
811 break;
812
813 case S390_INSN_CAS:
814 insn->variant.cas.op1 = lookupHRegRemap(m, insn->variant.cas.op1);
815 s390_amode_map_regs(m, insn->variant.cas.op2);
816 insn->variant.cas.op3 = lookupHRegRemap(m, insn->variant.cas.op3);
817 insn->variant.cas.old_mem = lookupHRegRemap(m, insn->variant.cas.old_mem);
818 break;
819
820 case S390_INSN_COMPARE:
821 insn->variant.compare.src1 = lookupHRegRemap(m, insn->variant.compare.src1);
822 s390_opnd_RMI_map_regs(m, &insn->variant.compare.src2);
823 break;
824
825 case S390_INSN_BRANCH:
826 s390_opnd_RMI_map_regs(m, &insn->variant.branch.dst);
827 /* No need to map S390_REGNO_RETURN_VALUE. It's not virtual */
828 break;
829
830 case S390_INSN_HELPER_CALL:
831 /* s390_insn_helper_call_emit also reads / writes the link register
832 and stack pointer. But those registers are not visible to the
833 register allocator. So we don't need to do anything for them.
834 As for the arguments of the helper call -- they will be loaded into
835 non-virtual registers. Again, we don't need to do anything for those
836 here. */
837 break;
838
839 case S390_INSN_BFP_TRIOP:
840 insn->variant.bfp_triop.dst = lookupHRegRemap(m, insn->variant.bfp_triop.dst);
841 insn->variant.bfp_triop.op2 = lookupHRegRemap(m, insn->variant.bfp_triop.op2);
842 insn->variant.bfp_triop.op3 = lookupHRegRemap(m, insn->variant.bfp_triop.op3);
843 break;
844
845 case S390_INSN_BFP_BINOP:
846 insn->variant.bfp_binop.dst = lookupHRegRemap(m, insn->variant.bfp_binop.dst);
847 insn->variant.bfp_binop.op2 = lookupHRegRemap(m, insn->variant.bfp_binop.op2);
848 break;
849
850 case S390_INSN_BFP_UNOP:
851 insn->variant.bfp_unop.dst = lookupHRegRemap(m, insn->variant.bfp_unop.dst);
852 insn->variant.bfp_unop.op = lookupHRegRemap(m, insn->variant.bfp_unop.op);
853 break;
854
855 case S390_INSN_BFP_COMPARE:
856 insn->variant.bfp_compare.dst = lookupHRegRemap(m, insn->variant.bfp_compare.dst);
857 insn->variant.bfp_compare.op1 = lookupHRegRemap(m, insn->variant.bfp_compare.op1);
858 insn->variant.bfp_compare.op2 = lookupHRegRemap(m, insn->variant.bfp_compare.op2);
859 break;
860
861 case S390_INSN_BFP128_BINOP:
862 insn->variant.bfp128_binop.dst_hi =
863 lookupHRegRemap(m, insn->variant.bfp128_binop.dst_hi);
864 insn->variant.bfp128_binop.dst_lo =
865 lookupHRegRemap(m, insn->variant.bfp128_binop.dst_lo);
866 insn->variant.bfp128_binop.op2_hi =
867 lookupHRegRemap(m, insn->variant.bfp128_binop.op2_hi);
868 insn->variant.bfp128_binop.op2_lo =
869 lookupHRegRemap(m, insn->variant.bfp128_binop.op2_lo);
870 break;
871
872 case S390_INSN_BFP128_COMPARE:
873 insn->variant.bfp128_compare.dst =
874 lookupHRegRemap(m, insn->variant.bfp128_compare.dst);
875 insn->variant.bfp128_compare.op1_hi =
876 lookupHRegRemap(m, insn->variant.bfp128_compare.op1_hi);
877 insn->variant.bfp128_compare.op1_lo =
878 lookupHRegRemap(m, insn->variant.bfp128_compare.op1_lo);
879 insn->variant.bfp128_compare.op2_hi =
880 lookupHRegRemap(m, insn->variant.bfp128_compare.op2_hi);
881 insn->variant.bfp128_compare.op2_lo =
882 lookupHRegRemap(m, insn->variant.bfp128_compare.op2_lo);
883 break;
884
885 case S390_INSN_BFP128_UNOP:
886 insn->variant.bfp128_unop.dst_hi =
887 lookupHRegRemap(m, insn->variant.bfp128_unop.dst_hi);
888 insn->variant.bfp128_unop.dst_lo =
889 lookupHRegRemap(m, insn->variant.bfp128_unop.dst_lo);
890 insn->variant.bfp128_unop.op_hi =
891 lookupHRegRemap(m, insn->variant.bfp128_unop.op_hi);
892 insn->variant.bfp128_unop.op_lo =
893 lookupHRegRemap(m, insn->variant.bfp128_unop.op_lo);
894 break;
895
896 case S390_INSN_BFP128_CONVERT_TO:
897 insn->variant.bfp128_unop.dst_hi =
898 lookupHRegRemap(m, insn->variant.bfp128_unop.dst_hi);
899 insn->variant.bfp128_unop.dst_lo =
900 lookupHRegRemap(m, insn->variant.bfp128_unop.dst_lo);
901 insn->variant.bfp128_unop.op_hi =
902 lookupHRegRemap(m, insn->variant.bfp128_unop.op_hi);
903 break;
904
905 case S390_INSN_BFP128_CONVERT_FROM:
906 insn->variant.bfp128_unop.dst_hi =
907 lookupHRegRemap(m, insn->variant.bfp128_unop.dst_hi);
908 insn->variant.bfp128_unop.op_hi =
909 lookupHRegRemap(m, insn->variant.bfp128_unop.op_hi);
910 insn->variant.bfp128_unop.op_lo =
911 lookupHRegRemap(m, insn->variant.bfp128_unop.op_lo);
912 break;
913
914 case S390_INSN_MFENCE:
915 break;
916
917 default:
918 vpanic("s390_insn_map_regs");
919 }
920 }
921
922
923 /* Return True, if INSN is a move between two registers of the same class.
924 In that case assign the source and destination registers to SRC and DST,
925 respectively. */
926 static Bool
s390_insn_is_reg_reg_move(const s390_insn * insn,HReg * src,HReg * dst)927 s390_insn_is_reg_reg_move(const s390_insn *insn, HReg *src, HReg *dst)
928 {
929 if (insn->tag == S390_INSN_MOVE &&
930 hregClass(insn->variant.move.src) == hregClass(insn->variant.move.dst)) {
931 *src = insn->variant.move.src;
932 *dst = insn->variant.move.dst;
933 return True;
934 }
935
936 return False;
937 }
938
939
940 /*------------------------------------------------------------*/
941 /*--- Functions to emit a sequence of bytes ---*/
942 /*------------------------------------------------------------*/
943
944 static __inline__ UChar *
emit_2bytes(UChar * p,ULong val)945 emit_2bytes(UChar *p, ULong val)
946 {
947 return (UChar *)__builtin_memcpy(p, ((UChar *)&val) + 6, 2) + 2;
948 }
949
950
951 static __inline__ UChar *
emit_4bytes(UChar * p,ULong val)952 emit_4bytes(UChar *p, ULong val)
953 {
954 return (UChar *)__builtin_memcpy(p, ((UChar *)&val) + 4, 4) + 4;
955 }
956
957
958 static __inline__ UChar *
emit_6bytes(UChar * p,ULong val)959 emit_6bytes(UChar *p, ULong val)
960 {
961 return (UChar *)__builtin_memcpy(p, ((UChar *)&val) + 2, 6) + 6;
962 }
963
964
965 /*------------------------------------------------------------*/
966 /*--- Functions to emit various instruction formats ---*/
967 /*------------------------------------------------------------*/
968
969 static UChar *
emit_RI(UChar * p,UInt op,UChar r1,UShort i2)970 emit_RI(UChar *p, UInt op, UChar r1, UShort i2)
971 {
972 ULong the_insn = op;
973
974 the_insn |= ((ULong)r1) << 20;
975 the_insn |= ((ULong)i2) << 0;
976
977 return emit_4bytes(p, the_insn);
978 }
979
980
981 static UChar *
emit_RIL(UChar * p,ULong op,UChar r1,UInt i2)982 emit_RIL(UChar *p, ULong op, UChar r1, UInt i2)
983 {
984 ULong the_insn = op;
985
986 the_insn |= ((ULong)r1) << 36;
987 the_insn |= ((ULong)i2) << 0;
988
989 return emit_6bytes(p, the_insn);
990 }
991
992
993 static UChar *
emit_RR(UChar * p,UInt op,UChar r1,UChar r2)994 emit_RR(UChar *p, UInt op, UChar r1, UChar r2)
995 {
996 ULong the_insn = op;
997
998 the_insn |= ((ULong)r1) << 4;
999 the_insn |= ((ULong)r2) << 0;
1000
1001 return emit_2bytes(p, the_insn);
1002 }
1003
1004
1005 static UChar *
emit_RRE(UChar * p,UInt op,UChar r1,UChar r2)1006 emit_RRE(UChar *p, UInt op, UChar r1, UChar r2)
1007 {
1008 ULong the_insn = op;
1009
1010 the_insn |= ((ULong)r1) << 4;
1011 the_insn |= ((ULong)r2) << 0;
1012
1013 return emit_4bytes(p, the_insn);
1014 }
1015
1016
1017 static UChar *
emit_RRF(UChar * p,UInt op,UChar r1,UChar r3,UChar r2)1018 emit_RRF(UChar *p, UInt op, UChar r1, UChar r3, UChar r2)
1019 {
1020 ULong the_insn = op;
1021
1022 the_insn |= ((ULong)r1) << 12;
1023 the_insn |= ((ULong)r3) << 4;
1024 the_insn |= ((ULong)r2) << 0;
1025
1026 return emit_4bytes(p, the_insn);
1027 }
1028
1029
1030 static UChar *
emit_RRF3(UChar * p,UInt op,UChar r3,UChar r1,UChar r2)1031 emit_RRF3(UChar *p, UInt op, UChar r3, UChar r1, UChar r2)
1032 {
1033 ULong the_insn = op;
1034
1035 the_insn |= ((ULong)r3) << 12;
1036 the_insn |= ((ULong)r1) << 4;
1037 the_insn |= ((ULong)r2) << 0;
1038
1039 return emit_4bytes(p, the_insn);
1040 }
1041
1042
1043 static UChar *
emit_RS(UChar * p,UInt op,UChar r1,UChar r3,UChar b2,UShort d2)1044 emit_RS(UChar *p, UInt op, UChar r1, UChar r3, UChar b2, UShort d2)
1045 {
1046 ULong the_insn = op;
1047
1048 the_insn |= ((ULong)r1) << 20;
1049 the_insn |= ((ULong)r3) << 16;
1050 the_insn |= ((ULong)b2) << 12;
1051 the_insn |= ((ULong)d2) << 0;
1052
1053 return emit_4bytes(p, the_insn);
1054 }
1055
1056
1057 static UChar *
emit_RSY(UChar * p,ULong op,UChar r1,UChar r3,UChar b2,UShort dl2,UChar dh2)1058 emit_RSY(UChar *p, ULong op, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
1059 {
1060 ULong the_insn = op;
1061
1062 the_insn |= ((ULong)r1) << 36;
1063 the_insn |= ((ULong)r3) << 32;
1064 the_insn |= ((ULong)b2) << 28;
1065 the_insn |= ((ULong)dl2) << 16;
1066 the_insn |= ((ULong)dh2) << 8;
1067
1068 return emit_6bytes(p, the_insn);
1069 }
1070
1071
1072 static UChar *
emit_RX(UChar * p,UInt op,UChar r1,UChar x2,UChar b2,UShort d2)1073 emit_RX(UChar *p, UInt op, UChar r1, UChar x2, UChar b2, UShort d2)
1074 {
1075 ULong the_insn = op;
1076
1077 the_insn |= ((ULong)r1) << 20;
1078 the_insn |= ((ULong)x2) << 16;
1079 the_insn |= ((ULong)b2) << 12;
1080 the_insn |= ((ULong)d2) << 0;
1081
1082 return emit_4bytes(p, the_insn);
1083 }
1084
1085
1086 static UChar *
emit_RXY(UChar * p,ULong op,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)1087 emit_RXY(UChar *p, ULong op, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1088 {
1089 ULong the_insn = op;
1090
1091 the_insn |= ((ULong)r1) << 36;
1092 the_insn |= ((ULong)x2) << 32;
1093 the_insn |= ((ULong)b2) << 28;
1094 the_insn |= ((ULong)dl2) << 16;
1095 the_insn |= ((ULong)dh2) << 8;
1096
1097 return emit_6bytes(p, the_insn);
1098 }
1099
1100
1101 static UChar *
emit_S(UChar * p,UInt op,UChar b2,UShort d2)1102 emit_S(UChar *p, UInt op, UChar b2, UShort d2)
1103 {
1104 ULong the_insn = op;
1105
1106 the_insn |= ((ULong)b2) << 12;
1107 the_insn |= ((ULong)d2) << 0;
1108
1109 return emit_4bytes(p, the_insn);
1110 }
1111
1112
1113 /*------------------------------------------------------------*/
1114 /*--- Functions to emit particular instructions ---*/
1115 /*------------------------------------------------------------*/
1116
1117 static UChar *
s390_emit_AR(UChar * p,UChar r1,UChar r2)1118 s390_emit_AR(UChar *p, UChar r1, UChar r2)
1119 {
1120 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1121 s390_disasm(ENC3(MNM, GPR, GPR), "ar", r1, r2);
1122
1123 return emit_RR(p, 0x1a00, r1, r2);
1124 }
1125
1126
1127 static UChar *
s390_emit_AGR(UChar * p,UChar r1,UChar r2)1128 s390_emit_AGR(UChar *p, UChar r1, UChar r2)
1129 {
1130 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1131 s390_disasm(ENC3(MNM, GPR, GPR), "agr", r1, r2);
1132
1133 return emit_RRE(p, 0xb9080000, r1, r2);
1134 }
1135
1136
1137 static UChar *
s390_emit_A(UChar * p,UChar r1,UChar x2,UChar b2,UShort d2)1138 s390_emit_A(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
1139 {
1140 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1141 s390_disasm(ENC3(MNM, GPR, UDXB), "a", r1, d2, x2, b2);
1142
1143 return emit_RX(p, 0x5a000000, r1, x2, b2, d2);
1144 }
1145
1146
1147 static UChar *
s390_emit_AY(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)1148 s390_emit_AY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1149 {
1150 vassert(s390_host_has_ldisp);
1151
1152 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1153 s390_disasm(ENC3(MNM, GPR, SDXB), "ay", r1, dh2, dl2, x2, b2);
1154
1155 return emit_RXY(p, 0xe3000000005aULL, r1, x2, b2, dl2, dh2);
1156 }
1157
1158
1159 static UChar *
s390_emit_AG(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)1160 s390_emit_AG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1161 {
1162 vassert(s390_host_has_ldisp || dh2 == 0);
1163
1164 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1165 s390_disasm(ENC3(MNM, GPR, SDXB), "ag", r1, dh2, dl2, x2, b2);
1166
1167 return emit_RXY(p, 0xe30000000008ULL, r1, x2, b2, dl2, dh2);
1168 }
1169
1170
1171 static UChar *
s390_emit_AFI(UChar * p,UChar r1,UInt i2)1172 s390_emit_AFI(UChar *p, UChar r1, UInt i2)
1173 {
1174 vassert(s390_host_has_eimm);
1175
1176 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1177 s390_disasm(ENC3(MNM, GPR, INT), "afi", r1, i2);
1178
1179 return emit_RIL(p, 0xc20900000000ULL, r1, i2);
1180 }
1181
1182
1183 static UChar *
s390_emit_AGFI(UChar * p,UChar r1,UInt i2)1184 s390_emit_AGFI(UChar *p, UChar r1, UInt i2)
1185 {
1186 vassert(s390_host_has_eimm);
1187
1188 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1189 s390_disasm(ENC3(MNM, GPR, INT), "agfi", r1, i2);
1190
1191 return emit_RIL(p, 0xc20800000000ULL, r1, i2);
1192 }
1193
1194
1195 static UChar *
s390_emit_AH(UChar * p,UChar r1,UChar x2,UChar b2,UShort d2)1196 s390_emit_AH(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
1197 {
1198 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1199 s390_disasm(ENC3(MNM, GPR, UDXB), "ah", r1, d2, x2, b2);
1200
1201 return emit_RX(p, 0x4a000000, r1, x2, b2, d2);
1202 }
1203
1204
1205 static UChar *
s390_emit_AHY(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)1206 s390_emit_AHY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1207 {
1208 vassert(s390_host_has_ldisp);
1209
1210 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1211 s390_disasm(ENC3(MNM, GPR, SDXB), "ahy", r1, dh2, dl2, x2, b2);
1212
1213 return emit_RXY(p, 0xe3000000007aULL, r1, x2, b2, dl2, dh2);
1214 }
1215
1216
1217 static UChar *
s390_emit_AHI(UChar * p,UChar r1,UShort i2)1218 s390_emit_AHI(UChar *p, UChar r1, UShort i2)
1219 {
1220 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1221 s390_disasm(ENC3(MNM, GPR, INT), "ahi", r1, (Int)(Short)i2);
1222
1223 return emit_RI(p, 0xa70a0000, r1, i2);
1224 }
1225
1226
1227 static UChar *
s390_emit_AGHI(UChar * p,UChar r1,UShort i2)1228 s390_emit_AGHI(UChar *p, UChar r1, UShort i2)
1229 {
1230 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1231 s390_disasm(ENC3(MNM, GPR, INT), "aghi", r1, (Int)(Short)i2);
1232
1233 return emit_RI(p, 0xa70b0000, r1, i2);
1234 }
1235
1236
1237 static UChar *
s390_emit_NR(UChar * p,UChar r1,UChar r2)1238 s390_emit_NR(UChar *p, UChar r1, UChar r2)
1239 {
1240 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1241 s390_disasm(ENC3(MNM, GPR, GPR), "nr", r1, r2);
1242
1243 return emit_RR(p, 0x1400, r1, r2);
1244 }
1245
1246
1247 static UChar *
s390_emit_NGR(UChar * p,UChar r1,UChar r2)1248 s390_emit_NGR(UChar *p, UChar r1, UChar r2)
1249 {
1250 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1251 s390_disasm(ENC3(MNM, GPR, GPR), "ngr", r1, r2);
1252
1253 return emit_RRE(p, 0xb9800000, r1, r2);
1254 }
1255
1256
1257 static UChar *
s390_emit_N(UChar * p,UChar r1,UChar x2,UChar b2,UShort d2)1258 s390_emit_N(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
1259 {
1260 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1261 s390_disasm(ENC3(MNM, GPR, UDXB), "n", r1, d2, x2, b2);
1262
1263 return emit_RX(p, 0x54000000, r1, x2, b2, d2);
1264 }
1265
1266
1267 static UChar *
s390_emit_NY(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)1268 s390_emit_NY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1269 {
1270 vassert(s390_host_has_ldisp);
1271
1272 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1273 s390_disasm(ENC3(MNM, GPR, SDXB), "ny", r1, dh2, dl2, x2, b2);
1274
1275 return emit_RXY(p, 0xe30000000054ULL, r1, x2, b2, dl2, dh2);
1276 }
1277
1278
1279 static UChar *
s390_emit_NG(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)1280 s390_emit_NG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1281 {
1282 vassert(s390_host_has_ldisp || dh2 == 0);
1283
1284 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1285 s390_disasm(ENC3(MNM, GPR, SDXB), "ng", r1, dh2, dl2, x2, b2);
1286
1287 return emit_RXY(p, 0xe30000000080ULL, r1, x2, b2, dl2, dh2);
1288 }
1289
1290
1291 static UChar *
s390_emit_NIHF(UChar * p,UChar r1,UInt i2)1292 s390_emit_NIHF(UChar *p, UChar r1, UInt i2)
1293 {
1294 vassert(s390_host_has_eimm);
1295
1296 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1297 s390_disasm(ENC3(MNM, GPR, UINT), "nihf", r1, i2);
1298
1299 return emit_RIL(p, 0xc00a00000000ULL, r1, i2);
1300 }
1301
1302
1303 static UChar *
s390_emit_NILF(UChar * p,UChar r1,UInt i2)1304 s390_emit_NILF(UChar *p, UChar r1, UInt i2)
1305 {
1306 vassert(s390_host_has_eimm);
1307
1308 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1309 s390_disasm(ENC3(MNM, GPR, UINT), "nilf", r1, i2);
1310
1311 return emit_RIL(p, 0xc00b00000000ULL, r1, i2);
1312 }
1313
1314
1315 static UChar *
s390_emit_NILL(UChar * p,UChar r1,UShort i2)1316 s390_emit_NILL(UChar *p, UChar r1, UShort i2)
1317 {
1318 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1319 s390_disasm(ENC3(MNM, GPR, UINT), "nill", r1, i2);
1320
1321 return emit_RI(p, 0xa5070000, r1, i2);
1322 }
1323
1324
1325 static UChar *
s390_emit_BASR(UChar * p,UChar r1,UChar r2)1326 s390_emit_BASR(UChar *p, UChar r1, UChar r2)
1327 {
1328 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1329 s390_disasm(ENC3(MNM, GPR, GPR), "basr", r1, r2);
1330
1331 return emit_RR(p, 0x0d00, r1, r2);
1332 }
1333
1334
1335 static UChar *
s390_emit_BCR(UChar * p,UChar r1,UChar r2)1336 s390_emit_BCR(UChar *p, UChar r1, UChar r2)
1337 {
1338 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1339 s390_disasm(ENC2(XMNM, GPR), S390_XMNM_BCR, r1, r2);
1340
1341 return emit_RR(p, 0x0700, r1, r2);
1342 }
1343
1344
1345 static UChar *
s390_emit_BRC(UChar * p,UChar r1,UShort i2)1346 s390_emit_BRC(UChar *p, UChar r1, UShort i2)
1347 {
1348 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1349 s390_disasm(ENC2(XMNM, PCREL), S390_XMNM_BRC, r1, (Int)(Short)i2);
1350
1351 return emit_RI(p, 0xa7040000, r1, i2);
1352 }
1353
1354
1355 static UChar *
s390_emit_CR(UChar * p,UChar r1,UChar r2)1356 s390_emit_CR(UChar *p, UChar r1, UChar r2)
1357 {
1358 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1359 s390_disasm(ENC3(MNM, GPR, GPR), "cr", r1, r2);
1360
1361 return emit_RR(p, 0x1900, r1, r2);
1362 }
1363
1364
1365 static UChar *
s390_emit_CGR(UChar * p,UChar r1,UChar r2)1366 s390_emit_CGR(UChar *p, UChar r1, UChar r2)
1367 {
1368 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1369 s390_disasm(ENC3(MNM, GPR, GPR), "cgr", r1, r2);
1370
1371 return emit_RRE(p, 0xb9200000, r1, r2);
1372 }
1373
1374
1375 static UChar *
s390_emit_C(UChar * p,UChar r1,UChar x2,UChar b2,UShort d2)1376 s390_emit_C(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
1377 {
1378 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1379 s390_disasm(ENC3(MNM, GPR, UDXB), "c", r1, d2, x2, b2);
1380
1381 return emit_RX(p, 0x59000000, r1, x2, b2, d2);
1382 }
1383
1384
1385 static UChar *
s390_emit_CY(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)1386 s390_emit_CY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1387 {
1388 vassert(s390_host_has_ldisp);
1389
1390 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1391 s390_disasm(ENC3(MNM, GPR, SDXB), "cy", r1, dh2, dl2, x2, b2);
1392
1393 return emit_RXY(p, 0xe30000000059ULL, r1, x2, b2, dl2, dh2);
1394 }
1395
1396
1397 static UChar *
s390_emit_CG(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)1398 s390_emit_CG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1399 {
1400 vassert(s390_host_has_ldisp || dh2 == 0);
1401
1402 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1403 s390_disasm(ENC3(MNM, GPR, SDXB), "cg", r1, dh2, dl2, x2, b2);
1404
1405 return emit_RXY(p, 0xe30000000020ULL, r1, x2, b2, dl2, dh2);
1406 }
1407
1408
1409 static UChar *
s390_emit_CFI(UChar * p,UChar r1,UInt i2)1410 s390_emit_CFI(UChar *p, UChar r1, UInt i2)
1411 {
1412 vassert(s390_host_has_eimm);
1413
1414 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1415 s390_disasm(ENC3(MNM, GPR, INT), "cfi", r1, i2);
1416
1417 return emit_RIL(p, 0xc20d00000000ULL, r1, i2);
1418 }
1419
1420
1421 static UChar *
s390_emit_CS(UChar * p,UChar r1,UChar r3,UChar b2,UShort d2)1422 s390_emit_CS(UChar *p, UChar r1, UChar r3, UChar b2, UShort d2)
1423 {
1424 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1425 s390_disasm(ENC4(MNM, GPR, GPR, UDXB), "cs", r1, r3, d2, 0, b2);
1426
1427 return emit_RS(p, 0xba000000, r1, r3, b2, d2);
1428 }
1429
1430
1431 static UChar *
s390_emit_CSY(UChar * p,UChar r1,UChar r3,UChar b2,UShort dl2,UChar dh2)1432 s390_emit_CSY(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
1433 {
1434 vassert(s390_host_has_ldisp);
1435
1436 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1437 s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "csy", r1, r3, dh2, dl2, 0, b2);
1438
1439 return emit_RSY(p, 0xeb0000000014ULL, r1, r3, b2, dl2, dh2);
1440 }
1441
1442
1443 static UChar *
s390_emit_CSG(UChar * p,UChar r1,UChar r3,UChar b2,UShort dl2,UChar dh2)1444 s390_emit_CSG(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
1445 {
1446 vassert(s390_host_has_ldisp || dh2 == 0);
1447
1448 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1449 s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "csg", r1, r3, dh2, dl2, 0, b2);
1450
1451 return emit_RSY(p, 0xeb0000000030ULL, r1, r3, b2, dl2, dh2);
1452 }
1453
1454
1455 static UChar *
s390_emit_CLR(UChar * p,UChar r1,UChar r2)1456 s390_emit_CLR(UChar *p, UChar r1, UChar r2)
1457 {
1458 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1459 s390_disasm(ENC3(MNM, GPR, GPR), "clr", r1, r2);
1460
1461 return emit_RR(p, 0x1500, r1, r2);
1462 }
1463
1464
1465 static UChar *
s390_emit_CLGR(UChar * p,UChar r1,UChar r2)1466 s390_emit_CLGR(UChar *p, UChar r1, UChar r2)
1467 {
1468 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1469 s390_disasm(ENC3(MNM, GPR, GPR), "clgr", r1, r2);
1470
1471 return emit_RRE(p, 0xb9210000, r1, r2);
1472 }
1473
1474
1475 static UChar *
s390_emit_CL(UChar * p,UChar r1,UChar x2,UChar b2,UShort d2)1476 s390_emit_CL(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
1477 {
1478 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1479 s390_disasm(ENC3(MNM, GPR, UDXB), "cl", r1, d2, x2, b2);
1480
1481 return emit_RX(p, 0x55000000, r1, x2, b2, d2);
1482 }
1483
1484
1485 static UChar *
s390_emit_CLY(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)1486 s390_emit_CLY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1487 {
1488 vassert(s390_host_has_ldisp);
1489
1490 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1491 s390_disasm(ENC3(MNM, GPR, SDXB), "cly", r1, dh2, dl2, x2, b2);
1492
1493 return emit_RXY(p, 0xe30000000055ULL, r1, x2, b2, dl2, dh2);
1494 }
1495
1496
1497 static UChar *
s390_emit_CLG(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)1498 s390_emit_CLG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1499 {
1500 vassert(s390_host_has_ldisp || dh2 == 0);
1501
1502 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1503 s390_disasm(ENC3(MNM, GPR, SDXB), "clg", r1, dh2, dl2, x2, b2);
1504
1505 return emit_RXY(p, 0xe30000000021ULL, r1, x2, b2, dl2, dh2);
1506 }
1507
1508
1509 static UChar *
s390_emit_CLFI(UChar * p,UChar r1,UInt i2)1510 s390_emit_CLFI(UChar *p, UChar r1, UInt i2)
1511 {
1512 vassert(s390_host_has_eimm);
1513
1514 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1515 s390_disasm(ENC3(MNM, GPR, UINT), "clfi", r1, i2);
1516
1517 return emit_RIL(p, 0xc20f00000000ULL, r1, i2);
1518 }
1519
1520
1521 static UChar *
s390_emit_DR(UChar * p,UChar r1,UChar r2)1522 s390_emit_DR(UChar *p, UChar r1, UChar r2)
1523 {
1524 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1525 s390_disasm(ENC3(MNM, GPR, GPR), "dr", r1, r2);
1526
1527 return emit_RR(p, 0x1d00, r1, r2);
1528 }
1529
1530
1531 static UChar *
s390_emit_D(UChar * p,UChar r1,UChar x2,UChar b2,UShort d2)1532 s390_emit_D(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
1533 {
1534 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1535 s390_disasm(ENC3(MNM, GPR, UDXB), "d", r1, d2, x2, b2);
1536
1537 return emit_RX(p, 0x5d000000, r1, x2, b2, d2);
1538 }
1539
1540
1541 static UChar *
s390_emit_DLR(UChar * p,UChar r1,UChar r2)1542 s390_emit_DLR(UChar *p, UChar r1, UChar r2)
1543 {
1544 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1545 s390_disasm(ENC3(MNM, GPR, GPR), "dlr", r1, r2);
1546
1547 return emit_RRE(p, 0xb9970000, r1, r2);
1548 }
1549
1550
1551 static UChar *
s390_emit_DLGR(UChar * p,UChar r1,UChar r2)1552 s390_emit_DLGR(UChar *p, UChar r1, UChar r2)
1553 {
1554 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1555 s390_disasm(ENC3(MNM, GPR, GPR), "dlgr", r1, r2);
1556
1557 return emit_RRE(p, 0xb9870000, r1, r2);
1558 }
1559
1560
1561 static UChar *
s390_emit_DL(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)1562 s390_emit_DL(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1563 {
1564 vassert(s390_host_has_ldisp || dh2 == 0);
1565
1566 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1567 s390_disasm(ENC3(MNM, GPR, SDXB), "dl", r1, dh2, dl2, x2, b2);
1568
1569 return emit_RXY(p, 0xe30000000097ULL, r1, x2, b2, dl2, dh2);
1570 }
1571
1572
1573 static UChar *
s390_emit_DLG(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)1574 s390_emit_DLG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1575 {
1576 vassert(s390_host_has_ldisp || dh2 == 0);
1577
1578 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1579 s390_disasm(ENC3(MNM, GPR, SDXB), "dlg", r1, dh2, dl2, x2, b2);
1580
1581 return emit_RXY(p, 0xe30000000087ULL, r1, x2, b2, dl2, dh2);
1582 }
1583
1584
1585 static UChar *
s390_emit_DSGR(UChar * p,UChar r1,UChar r2)1586 s390_emit_DSGR(UChar *p, UChar r1, UChar r2)
1587 {
1588 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1589 s390_disasm(ENC3(MNM, GPR, GPR), "dsgr", r1, r2);
1590
1591 return emit_RRE(p, 0xb90d0000, r1, r2);
1592 }
1593
1594
1595 static UChar *
s390_emit_DSG(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)1596 s390_emit_DSG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1597 {
1598 vassert(s390_host_has_ldisp || dh2 == 0);
1599
1600 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1601 s390_disasm(ENC3(MNM, GPR, SDXB), "dsg", r1, dh2, dl2, x2, b2);
1602
1603 return emit_RXY(p, 0xe3000000000dULL, r1, x2, b2, dl2, dh2);
1604 }
1605
1606
1607 static UChar *
s390_emit_XR(UChar * p,UChar r1,UChar r2)1608 s390_emit_XR(UChar *p, UChar r1, UChar r2)
1609 {
1610 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1611 s390_disasm(ENC3(MNM, GPR, GPR), "xr", r1, r2);
1612
1613 return emit_RR(p, 0x1700, r1, r2);
1614 }
1615
1616
1617 static UChar *
s390_emit_XGR(UChar * p,UChar r1,UChar r2)1618 s390_emit_XGR(UChar *p, UChar r1, UChar r2)
1619 {
1620 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1621 s390_disasm(ENC3(MNM, GPR, GPR), "xgr", r1, r2);
1622
1623 return emit_RRE(p, 0xb9820000, r1, r2);
1624 }
1625
1626
1627 static UChar *
s390_emit_X(UChar * p,UChar r1,UChar x2,UChar b2,UShort d2)1628 s390_emit_X(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
1629 {
1630 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1631 s390_disasm(ENC3(MNM, GPR, UDXB), "x", r1, d2, x2, b2);
1632
1633 return emit_RX(p, 0x57000000, r1, x2, b2, d2);
1634 }
1635
1636
1637 static UChar *
s390_emit_XY(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)1638 s390_emit_XY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1639 {
1640 vassert(s390_host_has_ldisp);
1641
1642 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1643 s390_disasm(ENC3(MNM, GPR, SDXB), "xy", r1, dh2, dl2, x2, b2);
1644
1645 return emit_RXY(p, 0xe30000000057ULL, r1, x2, b2, dl2, dh2);
1646 }
1647
1648
1649 static UChar *
s390_emit_XG(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)1650 s390_emit_XG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1651 {
1652 vassert(s390_host_has_ldisp || dh2 == 0);
1653
1654 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1655 s390_disasm(ENC3(MNM, GPR, SDXB), "xg", r1, dh2, dl2, x2, b2);
1656
1657 return emit_RXY(p, 0xe30000000082ULL, r1, x2, b2, dl2, dh2);
1658 }
1659
1660
1661 static UChar *
s390_emit_XIHF(UChar * p,UChar r1,UInt i2)1662 s390_emit_XIHF(UChar *p, UChar r1, UInt i2)
1663 {
1664 vassert(s390_host_has_eimm);
1665
1666 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1667 s390_disasm(ENC3(MNM, GPR, UINT), "xihf", r1, i2);
1668
1669 return emit_RIL(p, 0xc00600000000ULL, r1, i2);
1670 }
1671
1672
1673 static UChar *
s390_emit_XILF(UChar * p,UChar r1,UInt i2)1674 s390_emit_XILF(UChar *p, UChar r1, UInt i2)
1675 {
1676 vassert(s390_host_has_eimm);
1677
1678 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1679 s390_disasm(ENC3(MNM, GPR, UINT), "xilf", r1, i2);
1680
1681 return emit_RIL(p, 0xc00700000000ULL, r1, i2);
1682 }
1683
1684
1685 static UChar *
s390_emit_FLOGR(UChar * p,UChar r1,UChar r2)1686 s390_emit_FLOGR(UChar *p, UChar r1, UChar r2)
1687 {
1688 vassert(s390_host_has_eimm);
1689
1690 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1691 s390_disasm(ENC3(MNM, GPR, GPR), "flogr", r1, r2);
1692
1693 return emit_RRE(p, 0xb9830000, r1, r2);
1694 }
1695
1696
1697 static UChar *
s390_emit_IC(UChar * p,UChar r1,UChar x2,UChar b2,UShort d2)1698 s390_emit_IC(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
1699 {
1700 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1701 s390_disasm(ENC3(MNM, GPR, UDXB), "ic", r1, d2, x2, b2);
1702
1703 return emit_RX(p, 0x43000000, r1, x2, b2, d2);
1704 }
1705
1706
1707 static UChar *
s390_emit_ICY(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)1708 s390_emit_ICY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1709 {
1710 vassert(s390_host_has_ldisp);
1711
1712 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1713 s390_disasm(ENC3(MNM, GPR, SDXB), "icy", r1, dh2, dl2, x2, b2);
1714
1715 return emit_RXY(p, 0xe30000000073ULL, r1, x2, b2, dl2, dh2);
1716 }
1717
1718
1719 static UChar *
s390_emit_IIHF(UChar * p,UChar r1,UInt i2)1720 s390_emit_IIHF(UChar *p, UChar r1, UInt i2)
1721 {
1722 vassert(s390_host_has_eimm);
1723
1724 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1725 s390_disasm(ENC3(MNM, GPR, UINT), "iihf", r1, i2);
1726
1727 return emit_RIL(p, 0xc00800000000ULL, r1, i2);
1728 }
1729
1730
1731 static UChar *
s390_emit_IIHH(UChar * p,UChar r1,UShort i2)1732 s390_emit_IIHH(UChar *p, UChar r1, UShort i2)
1733 {
1734 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1735 s390_disasm(ENC3(MNM, GPR, UINT), "iihh", r1, i2);
1736
1737 return emit_RI(p, 0xa5000000, r1, i2);
1738 }
1739
1740
1741 static UChar *
s390_emit_IIHL(UChar * p,UChar r1,UShort i2)1742 s390_emit_IIHL(UChar *p, UChar r1, UShort i2)
1743 {
1744 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1745 s390_disasm(ENC3(MNM, GPR, UINT), "iihl", r1, i2);
1746
1747 return emit_RI(p, 0xa5010000, r1, i2);
1748 }
1749
1750
1751 static UChar *
s390_emit_IILF(UChar * p,UChar r1,UInt i2)1752 s390_emit_IILF(UChar *p, UChar r1, UInt i2)
1753 {
1754 vassert(s390_host_has_eimm);
1755
1756 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1757 s390_disasm(ENC3(MNM, GPR, UINT), "iilf", r1, i2);
1758
1759 return emit_RIL(p, 0xc00900000000ULL, r1, i2);
1760 }
1761
1762
1763 static UChar *
s390_emit_IILH(UChar * p,UChar r1,UShort i2)1764 s390_emit_IILH(UChar *p, UChar r1, UShort i2)
1765 {
1766 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1767 s390_disasm(ENC3(MNM, GPR, UINT), "iilh", r1, i2);
1768
1769 return emit_RI(p, 0xa5020000, r1, i2);
1770 }
1771
1772
1773 static UChar *
s390_emit_IILL(UChar * p,UChar r1,UShort i2)1774 s390_emit_IILL(UChar *p, UChar r1, UShort i2)
1775 {
1776 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1777 s390_disasm(ENC3(MNM, GPR, UINT), "iill", r1, i2);
1778
1779 return emit_RI(p, 0xa5030000, r1, i2);
1780 }
1781
1782
1783 static UChar *
s390_emit_IPM(UChar * p,UChar r1,UChar r2)1784 s390_emit_IPM(UChar *p, UChar r1, UChar r2)
1785 {
1786 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1787 s390_disasm(ENC2(MNM, GPR), "ipm", r1);
1788
1789 return emit_RRE(p, 0xb2220000, r1, r2);
1790 }
1791
1792
1793 static UChar *
s390_emit_LR(UChar * p,UChar r1,UChar r2)1794 s390_emit_LR(UChar *p, UChar r1, UChar r2)
1795 {
1796 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1797 s390_disasm(ENC3(MNM, GPR, GPR), "lr", r1, r2);
1798
1799 return emit_RR(p, 0x1800, r1, r2);
1800 }
1801
1802
1803 static UChar *
s390_emit_LGR(UChar * p,UChar r1,UChar r2)1804 s390_emit_LGR(UChar *p, UChar r1, UChar r2)
1805 {
1806 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1807 s390_disasm(ENC3(MNM, GPR, GPR), "lgr", r1, r2);
1808
1809 return emit_RRE(p, 0xb9040000, r1, r2);
1810 }
1811
1812
1813 static UChar *
s390_emit_LGFR(UChar * p,UChar r1,UChar r2)1814 s390_emit_LGFR(UChar *p, UChar r1, UChar r2)
1815 {
1816 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1817 s390_disasm(ENC3(MNM, GPR, GPR), "lgfr", r1, r2);
1818
1819 return emit_RRE(p, 0xb9140000, r1, r2);
1820 }
1821
1822
1823 static UChar *
s390_emit_L(UChar * p,UChar r1,UChar x2,UChar b2,UShort d2)1824 s390_emit_L(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
1825 {
1826 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1827 s390_disasm(ENC3(MNM, GPR, UDXB), "l", r1, d2, x2, b2);
1828
1829 return emit_RX(p, 0x58000000, r1, x2, b2, d2);
1830 }
1831
1832
1833 static UChar *
s390_emit_LY(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)1834 s390_emit_LY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1835 {
1836 vassert(s390_host_has_ldisp);
1837
1838 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1839 s390_disasm(ENC3(MNM, GPR, SDXB), "ly", r1, dh2, dl2, x2, b2);
1840
1841 return emit_RXY(p, 0xe30000000058ULL, r1, x2, b2, dl2, dh2);
1842 }
1843
1844
1845 static UChar *
s390_emit_LG(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)1846 s390_emit_LG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1847 {
1848 vassert(s390_host_has_ldisp || dh2 == 0);
1849
1850 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1851 s390_disasm(ENC3(MNM, GPR, SDXB), "lg", r1, dh2, dl2, x2, b2);
1852
1853 return emit_RXY(p, 0xe30000000004ULL, r1, x2, b2, dl2, dh2);
1854 }
1855
1856
1857 static UChar *
s390_emit_LGF(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)1858 s390_emit_LGF(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1859 {
1860 vassert(s390_host_has_ldisp || dh2 == 0);
1861
1862 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1863 s390_disasm(ENC3(MNM, GPR, SDXB), "lgf", r1, dh2, dl2, x2, b2);
1864
1865 return emit_RXY(p, 0xe30000000014ULL, r1, x2, b2, dl2, dh2);
1866 }
1867
1868
1869 static UChar *
s390_emit_LGFI(UChar * p,UChar r1,UInt i2)1870 s390_emit_LGFI(UChar *p, UChar r1, UInt i2)
1871 {
1872 vassert(s390_host_has_eimm);
1873
1874 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1875 s390_disasm(ENC3(MNM, GPR, INT), "lgfi", r1, i2);
1876
1877 return emit_RIL(p, 0xc00100000000ULL, r1, i2);
1878 }
1879
1880
1881 static UChar *
s390_emit_LTR(UChar * p,UChar r1,UChar r2)1882 s390_emit_LTR(UChar *p, UChar r1, UChar r2)
1883 {
1884 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1885 s390_disasm(ENC3(MNM, GPR, GPR), "ltr", r1, r2);
1886
1887 return emit_RR(p, 0x1200, r1, r2);
1888 }
1889
1890
1891 static UChar *
s390_emit_LTGR(UChar * p,UChar r1,UChar r2)1892 s390_emit_LTGR(UChar *p, UChar r1, UChar r2)
1893 {
1894 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1895 s390_disasm(ENC3(MNM, GPR, GPR), "ltgr", r1, r2);
1896
1897 return emit_RRE(p, 0xb9020000, r1, r2);
1898 }
1899
1900
1901 static UChar *
s390_emit_LT(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)1902 s390_emit_LT(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1903 {
1904 vassert(s390_host_has_eimm);
1905
1906 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1907 s390_disasm(ENC3(MNM, GPR, SDXB), "lt", r1, dh2, dl2, x2, b2);
1908
1909 return emit_RXY(p, 0xe30000000012ULL, r1, x2, b2, dl2, dh2);
1910 }
1911
1912
1913 static UChar *
s390_emit_LTG(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)1914 s390_emit_LTG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1915 {
1916 vassert(s390_host_has_eimm);
1917
1918 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1919 s390_disasm(ENC3(MNM, GPR, SDXB), "ltg", r1, dh2, dl2, x2, b2);
1920
1921 return emit_RXY(p, 0xe30000000002ULL, r1, x2, b2, dl2, dh2);
1922 }
1923
1924
1925 static UChar *
s390_emit_LBR(UChar * p,UChar r1,UChar r2)1926 s390_emit_LBR(UChar *p, UChar r1, UChar r2)
1927 {
1928 vassert(s390_host_has_eimm);
1929
1930 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1931 s390_disasm(ENC3(MNM, GPR, GPR), "lbr", r1, r2);
1932
1933 return emit_RRE(p, 0xb9260000, r1, r2);
1934 }
1935
1936
1937 static UChar *
s390_emit_LGBR(UChar * p,UChar r1,UChar r2)1938 s390_emit_LGBR(UChar *p, UChar r1, UChar r2)
1939 {
1940 vassert(s390_host_has_eimm);
1941
1942 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1943 s390_disasm(ENC3(MNM, GPR, GPR), "lgbr", r1, r2);
1944
1945 return emit_RRE(p, 0xb9060000, r1, r2);
1946 }
1947
1948
1949 static UChar *
s390_emit_LB(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)1950 s390_emit_LB(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1951 {
1952 vassert(s390_host_has_ldisp);
1953
1954 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1955 s390_disasm(ENC3(MNM, GPR, SDXB), "lb", r1, dh2, dl2, x2, b2);
1956
1957 return emit_RXY(p, 0xe30000000076ULL, r1, x2, b2, dl2, dh2);
1958 }
1959
1960
1961 static UChar *
s390_emit_LGB(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)1962 s390_emit_LGB(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1963 {
1964 vassert(s390_host_has_ldisp);
1965
1966 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1967 s390_disasm(ENC3(MNM, GPR, SDXB), "lgb", r1, dh2, dl2, x2, b2);
1968
1969 return emit_RXY(p, 0xe30000000077ULL, r1, x2, b2, dl2, dh2);
1970 }
1971
1972
1973 static UChar *
s390_emit_LCR(UChar * p,UChar r1,UChar r2)1974 s390_emit_LCR(UChar *p, UChar r1, UChar r2)
1975 {
1976 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1977 s390_disasm(ENC3(MNM, GPR, GPR), "lcr", r1, r2);
1978
1979 return emit_RR(p, 0x1300, r1, r2);
1980 }
1981
1982
1983 static UChar *
s390_emit_LCGR(UChar * p,UChar r1,UChar r2)1984 s390_emit_LCGR(UChar *p, UChar r1, UChar r2)
1985 {
1986 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1987 s390_disasm(ENC3(MNM, GPR, GPR), "lcgr", r1, r2);
1988
1989 return emit_RRE(p, 0xb9030000, r1, r2);
1990 }
1991
1992
1993 static UChar *
s390_emit_LHR(UChar * p,UChar r1,UChar r2)1994 s390_emit_LHR(UChar *p, UChar r1, UChar r2)
1995 {
1996 vassert(s390_host_has_eimm);
1997
1998 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1999 s390_disasm(ENC3(MNM, GPR, GPR), "lhr", r1, r2);
2000
2001 return emit_RRE(p, 0xb9270000, r1, r2);
2002 }
2003
2004
2005 static UChar *
s390_emit_LGHR(UChar * p,UChar r1,UChar r2)2006 s390_emit_LGHR(UChar *p, UChar r1, UChar r2)
2007 {
2008 vassert(s390_host_has_eimm);
2009
2010 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2011 s390_disasm(ENC3(MNM, GPR, GPR), "lghr", r1, r2);
2012
2013 return emit_RRE(p, 0xb9070000, r1, r2);
2014 }
2015
2016
2017 static UChar *
s390_emit_LH(UChar * p,UChar r1,UChar x2,UChar b2,UShort d2)2018 s390_emit_LH(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2019 {
2020 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2021 s390_disasm(ENC3(MNM, GPR, UDXB), "lh", r1, d2, x2, b2);
2022
2023 return emit_RX(p, 0x48000000, r1, x2, b2, d2);
2024 }
2025
2026
2027 static UChar *
s390_emit_LHY(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)2028 s390_emit_LHY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2029 {
2030 vassert(s390_host_has_ldisp);
2031
2032 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2033 s390_disasm(ENC3(MNM, GPR, SDXB), "lhy", r1, dh2, dl2, x2, b2);
2034
2035 return emit_RXY(p, 0xe30000000078ULL, r1, x2, b2, dl2, dh2);
2036 }
2037
2038
2039 static UChar *
s390_emit_LGH(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)2040 s390_emit_LGH(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2041 {
2042 vassert(s390_host_has_ldisp || dh2 == 0);
2043
2044 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2045 s390_disasm(ENC3(MNM, GPR, SDXB), "lgh", r1, dh2, dl2, x2, b2);
2046
2047 return emit_RXY(p, 0xe30000000015ULL, r1, x2, b2, dl2, dh2);
2048 }
2049
2050
2051 static UChar *
s390_emit_LHI(UChar * p,UChar r1,UShort i2)2052 s390_emit_LHI(UChar *p, UChar r1, UShort i2)
2053 {
2054 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2055 s390_disasm(ENC3(MNM, GPR, INT), "lhi", r1, (Int)(Short)i2);
2056
2057 return emit_RI(p, 0xa7080000, r1, i2);
2058 }
2059
2060
2061 static UChar *
s390_emit_LGHI(UChar * p,UChar r1,UShort i2)2062 s390_emit_LGHI(UChar *p, UChar r1, UShort i2)
2063 {
2064 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2065 s390_disasm(ENC3(MNM, GPR, INT), "lghi", r1, (Int)(Short)i2);
2066
2067 return emit_RI(p, 0xa7090000, r1, i2);
2068 }
2069
2070
2071 static UChar *
s390_emit_LLGFR(UChar * p,UChar r1,UChar r2)2072 s390_emit_LLGFR(UChar *p, UChar r1, UChar r2)
2073 {
2074 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2075 s390_disasm(ENC3(MNM, GPR, GPR), "llgfr", r1, r2);
2076
2077 return emit_RRE(p, 0xb9160000, r1, r2);
2078 }
2079
2080
2081 static UChar *
s390_emit_LLGF(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)2082 s390_emit_LLGF(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2083 {
2084 vassert(s390_host_has_ldisp || dh2 == 0);
2085
2086 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2087 s390_disasm(ENC3(MNM, GPR, SDXB), "llgf", r1, dh2, dl2, x2, b2);
2088
2089 return emit_RXY(p, 0xe30000000016ULL, r1, x2, b2, dl2, dh2);
2090 }
2091
2092
2093 static UChar *
s390_emit_LLCR(UChar * p,UChar r1,UChar r2)2094 s390_emit_LLCR(UChar *p, UChar r1, UChar r2)
2095 {
2096 vassert(s390_host_has_eimm);
2097
2098 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2099 s390_disasm(ENC3(MNM, GPR, GPR), "llcr", r1, r2);
2100
2101 return emit_RRE(p, 0xb9940000, r1, r2);
2102 }
2103
2104
2105 static UChar *
s390_emit_LLGCR(UChar * p,UChar r1,UChar r2)2106 s390_emit_LLGCR(UChar *p, UChar r1, UChar r2)
2107 {
2108 vassert(s390_host_has_eimm);
2109
2110 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2111 s390_disasm(ENC3(MNM, GPR, GPR), "llgcr", r1, r2);
2112
2113 return emit_RRE(p, 0xb9840000, r1, r2);
2114 }
2115
2116
2117 static UChar *
s390_emit_LLC(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)2118 s390_emit_LLC(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2119 {
2120 vassert(s390_host_has_eimm);
2121
2122 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2123 s390_disasm(ENC3(MNM, GPR, SDXB), "llc", r1, dh2, dl2, x2, b2);
2124
2125 return emit_RXY(p, 0xe30000000094ULL, r1, x2, b2, dl2, dh2);
2126 }
2127
2128
2129 static UChar *
s390_emit_LLGC(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)2130 s390_emit_LLGC(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2131 {
2132 vassert(s390_host_has_ldisp || dh2 == 0);
2133
2134 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2135 s390_disasm(ENC3(MNM, GPR, SDXB), "llgc", r1, dh2, dl2, x2, b2);
2136
2137 return emit_RXY(p, 0xe30000000090ULL, r1, x2, b2, dl2, dh2);
2138 }
2139
2140
2141 static UChar *
s390_emit_LLHR(UChar * p,UChar r1,UChar r2)2142 s390_emit_LLHR(UChar *p, UChar r1, UChar r2)
2143 {
2144 vassert(s390_host_has_eimm);
2145
2146 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2147 s390_disasm(ENC3(MNM, GPR, GPR), "llhr", r1, r2);
2148
2149 return emit_RRE(p, 0xb9950000, r1, r2);
2150 }
2151
2152
2153 static UChar *
s390_emit_LLGHR(UChar * p,UChar r1,UChar r2)2154 s390_emit_LLGHR(UChar *p, UChar r1, UChar r2)
2155 {
2156 vassert(s390_host_has_eimm);
2157
2158 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2159 s390_disasm(ENC3(MNM, GPR, GPR), "llghr", r1, r2);
2160
2161 return emit_RRE(p, 0xb9850000, r1, r2);
2162 }
2163
2164
2165 static UChar *
s390_emit_LLH(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)2166 s390_emit_LLH(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2167 {
2168 vassert(s390_host_has_eimm);
2169
2170 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2171 s390_disasm(ENC3(MNM, GPR, SDXB), "llh", r1, dh2, dl2, x2, b2);
2172
2173 return emit_RXY(p, 0xe30000000095ULL, r1, x2, b2, dl2, dh2);
2174 }
2175
2176
2177 static UChar *
s390_emit_LLGH(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)2178 s390_emit_LLGH(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2179 {
2180 vassert(s390_host_has_ldisp || dh2 == 0);
2181
2182 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2183 s390_disasm(ENC3(MNM, GPR, SDXB), "llgh", r1, dh2, dl2, x2, b2);
2184
2185 return emit_RXY(p, 0xe30000000091ULL, r1, x2, b2, dl2, dh2);
2186 }
2187
2188
2189 static UChar *
s390_emit_LLILF(UChar * p,UChar r1,UInt i2)2190 s390_emit_LLILF(UChar *p, UChar r1, UInt i2)
2191 {
2192 vassert(s390_host_has_eimm);
2193
2194 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2195 s390_disasm(ENC3(MNM, GPR, UINT), "llilf", r1, i2);
2196
2197 return emit_RIL(p, 0xc00f00000000ULL, r1, i2);
2198 }
2199
2200
2201 static UChar *
s390_emit_LLILH(UChar * p,UChar r1,UShort i2)2202 s390_emit_LLILH(UChar *p, UChar r1, UShort i2)
2203 {
2204 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2205 s390_disasm(ENC3(MNM, GPR, UINT), "llilh", r1, i2);
2206
2207 return emit_RI(p, 0xa50e0000, r1, i2);
2208 }
2209
2210
2211 static UChar *
s390_emit_LLILL(UChar * p,UChar r1,UShort i2)2212 s390_emit_LLILL(UChar *p, UChar r1, UShort i2)
2213 {
2214 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2215 s390_disasm(ENC3(MNM, GPR, UINT), "llill", r1, i2);
2216
2217 return emit_RI(p, 0xa50f0000, r1, i2);
2218 }
2219
2220
2221 static UChar *
s390_emit_MR(UChar * p,UChar r1,UChar r2)2222 s390_emit_MR(UChar *p, UChar r1, UChar r2)
2223 {
2224 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2225 s390_disasm(ENC3(MNM, GPR, GPR), "mr", r1, r2);
2226
2227 return emit_RR(p, 0x1c00, r1, r2);
2228 }
2229
2230
2231 static UChar *
s390_emit_M(UChar * p,UChar r1,UChar x2,UChar b2,UShort d2)2232 s390_emit_M(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2233 {
2234 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2235 s390_disasm(ENC3(MNM, GPR, UDXB), "m", r1, d2, x2, b2);
2236
2237 return emit_RX(p, 0x5c000000, r1, x2, b2, d2);
2238 }
2239
2240
2241 static UChar *
s390_emit_MFY(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)2242 s390_emit_MFY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2243 {
2244 vassert(s390_host_has_gie);
2245
2246 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2247 s390_disasm(ENC3(MNM, GPR, SDXB), "mfy", r1, dh2, dl2, x2, b2);
2248
2249 return emit_RXY(p, 0xe3000000005cULL, r1, x2, b2, dl2, dh2);
2250 }
2251
2252
2253 static UChar *
s390_emit_MH(UChar * p,UChar r1,UChar x2,UChar b2,UShort d2)2254 s390_emit_MH(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2255 {
2256 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2257 s390_disasm(ENC3(MNM, GPR, UDXB), "mh", r1, d2, x2, b2);
2258
2259 return emit_RX(p, 0x4c000000, r1, x2, b2, d2);
2260 }
2261
2262
2263 static UChar *
s390_emit_MHY(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)2264 s390_emit_MHY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2265 {
2266 vassert(s390_host_has_gie);
2267
2268 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2269 s390_disasm(ENC3(MNM, GPR, SDXB), "mhy", r1, dh2, dl2, x2, b2);
2270
2271 return emit_RXY(p, 0xe3000000007cULL, r1, x2, b2, dl2, dh2);
2272 }
2273
2274
2275 static UChar *
s390_emit_MHI(UChar * p,UChar r1,UShort i2)2276 s390_emit_MHI(UChar *p, UChar r1, UShort i2)
2277 {
2278 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2279 s390_disasm(ENC3(MNM, GPR, INT), "mhi", r1, (Int)(Short)i2);
2280
2281 return emit_RI(p, 0xa70c0000, r1, i2);
2282 }
2283
2284
2285 static UChar *
s390_emit_MLR(UChar * p,UChar r1,UChar r2)2286 s390_emit_MLR(UChar *p, UChar r1, UChar r2)
2287 {
2288 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2289 s390_disasm(ENC3(MNM, GPR, GPR), "mlr", r1, r2);
2290
2291 return emit_RRE(p, 0xb9960000, r1, r2);
2292 }
2293
2294
2295 static UChar *
s390_emit_MLGR(UChar * p,UChar r1,UChar r2)2296 s390_emit_MLGR(UChar *p, UChar r1, UChar r2)
2297 {
2298 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2299 s390_disasm(ENC3(MNM, GPR, GPR), "mlgr", r1, r2);
2300
2301 return emit_RRE(p, 0xb9860000, r1, r2);
2302 }
2303
2304
2305 static UChar *
s390_emit_ML(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)2306 s390_emit_ML(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2307 {
2308 vassert(s390_host_has_ldisp || dh2 == 0);
2309
2310 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2311 s390_disasm(ENC3(MNM, GPR, SDXB), "ml", r1, dh2, dl2, x2, b2);
2312
2313 return emit_RXY(p, 0xe30000000096ULL, r1, x2, b2, dl2, dh2);
2314 }
2315
2316
2317 static UChar *
s390_emit_MLG(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)2318 s390_emit_MLG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2319 {
2320 vassert(s390_host_has_ldisp || dh2 == 0);
2321
2322 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2323 s390_disasm(ENC3(MNM, GPR, SDXB), "mlg", r1, dh2, dl2, x2, b2);
2324
2325 return emit_RXY(p, 0xe30000000086ULL, r1, x2, b2, dl2, dh2);
2326 }
2327
2328
2329 static UChar *
s390_emit_MSR(UChar * p,UChar r1,UChar r2)2330 s390_emit_MSR(UChar *p, UChar r1, UChar r2)
2331 {
2332 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2333 s390_disasm(ENC3(MNM, GPR, GPR), "msr", r1, r2);
2334
2335 return emit_RRE(p, 0xb2520000, r1, r2);
2336 }
2337
2338
2339 static UChar *
s390_emit_MSGR(UChar * p,UChar r1,UChar r2)2340 s390_emit_MSGR(UChar *p, UChar r1, UChar r2)
2341 {
2342 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2343 s390_disasm(ENC3(MNM, GPR, GPR), "msgr", r1, r2);
2344
2345 return emit_RRE(p, 0xb90c0000, r1, r2);
2346 }
2347
2348
2349 static UChar *
s390_emit_MS(UChar * p,UChar r1,UChar x2,UChar b2,UShort d2)2350 s390_emit_MS(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2351 {
2352 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2353 s390_disasm(ENC3(MNM, GPR, UDXB), "ms", r1, d2, x2, b2);
2354
2355 return emit_RX(p, 0x71000000, r1, x2, b2, d2);
2356 }
2357
2358
2359 static UChar *
s390_emit_MSY(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)2360 s390_emit_MSY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2361 {
2362 vassert(s390_host_has_ldisp);
2363
2364 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2365 s390_disasm(ENC3(MNM, GPR, SDXB), "msy", r1, dh2, dl2, x2, b2);
2366
2367 return emit_RXY(p, 0xe30000000051ULL, r1, x2, b2, dl2, dh2);
2368 }
2369
2370
2371 static UChar *
s390_emit_MSG(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)2372 s390_emit_MSG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2373 {
2374 vassert(s390_host_has_ldisp || dh2 == 0);
2375
2376 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2377 s390_disasm(ENC3(MNM, GPR, SDXB), "msg", r1, dh2, dl2, x2, b2);
2378
2379 return emit_RXY(p, 0xe3000000000cULL, r1, x2, b2, dl2, dh2);
2380 }
2381
2382
2383 static UChar *
s390_emit_MSFI(UChar * p,UChar r1,UInt i2)2384 s390_emit_MSFI(UChar *p, UChar r1, UInt i2)
2385 {
2386 vassert(s390_host_has_gie);
2387
2388 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2389 s390_disasm(ENC3(MNM, GPR, INT), "msfi", r1, i2);
2390
2391 return emit_RIL(p, 0xc20100000000ULL, r1, i2);
2392 }
2393
2394
2395 static UChar *
s390_emit_MSGFI(UChar * p,UChar r1,UInt i2)2396 s390_emit_MSGFI(UChar *p, UChar r1, UInt i2)
2397 {
2398 vassert(s390_host_has_gie);
2399
2400 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2401 s390_disasm(ENC3(MNM, GPR, INT), "msgfi", r1, i2);
2402
2403 return emit_RIL(p, 0xc20000000000ULL, r1, i2);
2404 }
2405
2406
2407 static UChar *
s390_emit_OR(UChar * p,UChar r1,UChar r2)2408 s390_emit_OR(UChar *p, UChar r1, UChar r2)
2409 {
2410 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2411 s390_disasm(ENC3(MNM, GPR, GPR), "or", r1, r2);
2412
2413 return emit_RR(p, 0x1600, r1, r2);
2414 }
2415
2416
2417 static UChar *
s390_emit_OGR(UChar * p,UChar r1,UChar r2)2418 s390_emit_OGR(UChar *p, UChar r1, UChar r2)
2419 {
2420 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2421 s390_disasm(ENC3(MNM, GPR, GPR), "ogr", r1, r2);
2422
2423 return emit_RRE(p, 0xb9810000, r1, r2);
2424 }
2425
2426
2427 static UChar *
s390_emit_O(UChar * p,UChar r1,UChar x2,UChar b2,UShort d2)2428 s390_emit_O(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2429 {
2430 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2431 s390_disasm(ENC3(MNM, GPR, UDXB), "o", r1, d2, x2, b2);
2432
2433 return emit_RX(p, 0x56000000, r1, x2, b2, d2);
2434 }
2435
2436
2437 static UChar *
s390_emit_OY(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)2438 s390_emit_OY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2439 {
2440 vassert(s390_host_has_ldisp);
2441
2442 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2443 s390_disasm(ENC3(MNM, GPR, SDXB), "oy", r1, dh2, dl2, x2, b2);
2444
2445 return emit_RXY(p, 0xe30000000056ULL, r1, x2, b2, dl2, dh2);
2446 }
2447
2448
2449 static UChar *
s390_emit_OG(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)2450 s390_emit_OG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2451 {
2452 vassert(s390_host_has_ldisp || dh2 == 0);
2453
2454 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2455 s390_disasm(ENC3(MNM, GPR, SDXB), "og", r1, dh2, dl2, x2, b2);
2456
2457 return emit_RXY(p, 0xe30000000081ULL, r1, x2, b2, dl2, dh2);
2458 }
2459
2460
2461 static UChar *
s390_emit_OIHF(UChar * p,UChar r1,UInt i2)2462 s390_emit_OIHF(UChar *p, UChar r1, UInt i2)
2463 {
2464 vassert(s390_host_has_eimm);
2465
2466 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2467 s390_disasm(ENC3(MNM, GPR, UINT), "oihf", r1, i2);
2468
2469 return emit_RIL(p, 0xc00c00000000ULL, r1, i2);
2470 }
2471
2472
2473 static UChar *
s390_emit_OILF(UChar * p,UChar r1,UInt i2)2474 s390_emit_OILF(UChar *p, UChar r1, UInt i2)
2475 {
2476 vassert(s390_host_has_eimm);
2477
2478 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2479 s390_disasm(ENC3(MNM, GPR, UINT), "oilf", r1, i2);
2480
2481 return emit_RIL(p, 0xc00d00000000ULL, r1, i2);
2482 }
2483
2484
2485 static UChar *
s390_emit_OILL(UChar * p,UChar r1,UShort i2)2486 s390_emit_OILL(UChar *p, UChar r1, UShort i2)
2487 {
2488 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2489 s390_disasm(ENC3(MNM, GPR, UINT), "oill", r1, i2);
2490
2491 return emit_RI(p, 0xa50b0000, r1, i2);
2492 }
2493
2494
2495 static UChar *
s390_emit_SLL(UChar * p,UChar r1,UChar b2,UShort d2)2496 s390_emit_SLL(UChar *p, UChar r1, UChar b2, UShort d2)
2497 {
2498 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2499 s390_disasm(ENC3(MNM, GPR, UDXB), "sll", r1, d2, 0, b2);
2500
2501 return emit_RS(p, 0x89000000, r1, 0, b2, d2);
2502 }
2503
2504
2505 static UChar *
s390_emit_SLLG(UChar * p,UChar r1,UChar r3,UChar b2,UShort dl2,UChar dh2)2506 s390_emit_SLLG(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
2507 {
2508 vassert(s390_host_has_ldisp || dh2 == 0);
2509
2510 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2511 s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "sllg", r1, r3, dh2, dl2, 0, b2);
2512
2513 return emit_RSY(p, 0xeb000000000dULL, r1, r3, b2, dl2, dh2);
2514 }
2515
2516
2517 static UChar *
s390_emit_SRA(UChar * p,UChar r1,UChar b2,UShort d2)2518 s390_emit_SRA(UChar *p, UChar r1, UChar b2, UShort d2)
2519 {
2520 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2521 s390_disasm(ENC3(MNM, GPR, UDXB), "sra", r1, d2, 0, b2);
2522
2523 return emit_RS(p, 0x8a000000, r1, 0, b2, d2);
2524 }
2525
2526
2527 static UChar *
s390_emit_SRAG(UChar * p,UChar r1,UChar r3,UChar b2,UShort dl2,UChar dh2)2528 s390_emit_SRAG(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
2529 {
2530 vassert(s390_host_has_ldisp || dh2 == 0);
2531
2532 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2533 s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "srag", r1, r3, dh2, dl2, 0, b2);
2534
2535 return emit_RSY(p, 0xeb000000000aULL, r1, r3, b2, dl2, dh2);
2536 }
2537
2538
2539 static UChar *
s390_emit_SRL(UChar * p,UChar r1,UChar b2,UShort d2)2540 s390_emit_SRL(UChar *p, UChar r1, UChar b2, UShort d2)
2541 {
2542 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2543 s390_disasm(ENC3(MNM, GPR, UDXB), "srl", r1, d2, 0, b2);
2544
2545 return emit_RS(p, 0x88000000, r1, 0, b2, d2);
2546 }
2547
2548
2549 static UChar *
s390_emit_SRLG(UChar * p,UChar r1,UChar r3,UChar b2,UShort dl2,UChar dh2)2550 s390_emit_SRLG(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
2551 {
2552 vassert(s390_host_has_ldisp || dh2 == 0);
2553
2554 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2555 s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "srlg", r1, r3, dh2, dl2, 0, b2);
2556
2557 return emit_RSY(p, 0xeb000000000cULL, r1, r3, b2, dl2, dh2);
2558 }
2559
2560
2561 static UChar *
s390_emit_ST(UChar * p,UChar r1,UChar x2,UChar b2,UShort d2)2562 s390_emit_ST(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2563 {
2564 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2565 s390_disasm(ENC3(MNM, GPR, UDXB), "st", r1, d2, x2, b2);
2566
2567 return emit_RX(p, 0x50000000, r1, x2, b2, d2);
2568 }
2569
2570
2571 static UChar *
s390_emit_STY(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)2572 s390_emit_STY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2573 {
2574 vassert(s390_host_has_ldisp);
2575
2576 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2577 s390_disasm(ENC3(MNM, GPR, SDXB), "sty", r1, dh2, dl2, x2, b2);
2578
2579 return emit_RXY(p, 0xe30000000050ULL, r1, x2, b2, dl2, dh2);
2580 }
2581
2582
2583 static UChar *
s390_emit_STG(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)2584 s390_emit_STG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2585 {
2586 vassert(s390_host_has_ldisp || dh2 == 0);
2587
2588 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2589 s390_disasm(ENC3(MNM, GPR, SDXB), "stg", r1, dh2, dl2, x2, b2);
2590
2591 return emit_RXY(p, 0xe30000000024ULL, r1, x2, b2, dl2, dh2);
2592 }
2593
2594
2595 static UChar *
s390_emit_STC(UChar * p,UChar r1,UChar x2,UChar b2,UShort d2)2596 s390_emit_STC(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2597 {
2598 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2599 s390_disasm(ENC3(MNM, GPR, UDXB), "stc", r1, d2, x2, b2);
2600
2601 return emit_RX(p, 0x42000000, r1, x2, b2, d2);
2602 }
2603
2604
2605 static UChar *
s390_emit_STCY(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)2606 s390_emit_STCY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2607 {
2608 vassert(s390_host_has_ldisp);
2609
2610 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2611 s390_disasm(ENC3(MNM, GPR, SDXB), "stcy", r1, dh2, dl2, x2, b2);
2612
2613 return emit_RXY(p, 0xe30000000072ULL, r1, x2, b2, dl2, dh2);
2614 }
2615
2616
2617 static UChar *
s390_emit_STH(UChar * p,UChar r1,UChar x2,UChar b2,UShort d2)2618 s390_emit_STH(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2619 {
2620 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2621 s390_disasm(ENC3(MNM, GPR, UDXB), "sth", r1, d2, x2, b2);
2622
2623 return emit_RX(p, 0x40000000, r1, x2, b2, d2);
2624 }
2625
2626
2627 static UChar *
s390_emit_STHY(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)2628 s390_emit_STHY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2629 {
2630 vassert(s390_host_has_ldisp);
2631
2632 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2633 s390_disasm(ENC3(MNM, GPR, SDXB), "sthy", r1, dh2, dl2, x2, b2);
2634
2635 return emit_RXY(p, 0xe30000000070ULL, r1, x2, b2, dl2, dh2);
2636 }
2637
2638
2639 static UChar *
s390_emit_SR(UChar * p,UChar r1,UChar r2)2640 s390_emit_SR(UChar *p, UChar r1, UChar r2)
2641 {
2642 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2643 s390_disasm(ENC3(MNM, GPR, GPR), "sr", r1, r2);
2644
2645 return emit_RR(p, 0x1b00, r1, r2);
2646 }
2647
2648
2649 static UChar *
s390_emit_SGR(UChar * p,UChar r1,UChar r2)2650 s390_emit_SGR(UChar *p, UChar r1, UChar r2)
2651 {
2652 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2653 s390_disasm(ENC3(MNM, GPR, GPR), "sgr", r1, r2);
2654
2655 return emit_RRE(p, 0xb9090000, r1, r2);
2656 }
2657
2658
2659 static UChar *
s390_emit_S(UChar * p,UChar r1,UChar x2,UChar b2,UShort d2)2660 s390_emit_S(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2661 {
2662 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2663 s390_disasm(ENC3(MNM, GPR, UDXB), "s", r1, d2, x2, b2);
2664
2665 return emit_RX(p, 0x5b000000, r1, x2, b2, d2);
2666 }
2667
2668
2669 static UChar *
s390_emit_SY(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)2670 s390_emit_SY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2671 {
2672 vassert(s390_host_has_ldisp);
2673
2674 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2675 s390_disasm(ENC3(MNM, GPR, SDXB), "sy", r1, dh2, dl2, x2, b2);
2676
2677 return emit_RXY(p, 0xe3000000005bULL, r1, x2, b2, dl2, dh2);
2678 }
2679
2680
2681 static UChar *
s390_emit_SG(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)2682 s390_emit_SG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2683 {
2684 vassert(s390_host_has_ldisp || dh2 == 0);
2685
2686 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2687 s390_disasm(ENC3(MNM, GPR, SDXB), "sg", r1, dh2, dl2, x2, b2);
2688
2689 return emit_RXY(p, 0xe30000000009ULL, r1, x2, b2, dl2, dh2);
2690 }
2691
2692
2693 static UChar *
s390_emit_SH(UChar * p,UChar r1,UChar x2,UChar b2,UShort d2)2694 s390_emit_SH(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2695 {
2696 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2697 s390_disasm(ENC3(MNM, GPR, UDXB), "sh", r1, d2, x2, b2);
2698
2699 return emit_RX(p, 0x4b000000, r1, x2, b2, d2);
2700 }
2701
2702
2703 static UChar *
s390_emit_SHY(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)2704 s390_emit_SHY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2705 {
2706 vassert(s390_host_has_ldisp);
2707
2708 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2709 s390_disasm(ENC3(MNM, GPR, SDXB), "shy", r1, dh2, dl2, x2, b2);
2710
2711 return emit_RXY(p, 0xe3000000007bULL, r1, x2, b2, dl2, dh2);
2712 }
2713
2714
2715 static UChar *
s390_emit_SLFI(UChar * p,UChar r1,UInt i2)2716 s390_emit_SLFI(UChar *p, UChar r1, UInt i2)
2717 {
2718 vassert(s390_host_has_eimm);
2719
2720 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2721 s390_disasm(ENC3(MNM, GPR, UINT), "slfi", r1, i2);
2722
2723 return emit_RIL(p, 0xc20500000000ULL, r1, i2);
2724 }
2725
2726
2727 static UChar *
s390_emit_SLGFI(UChar * p,UChar r1,UInt i2)2728 s390_emit_SLGFI(UChar *p, UChar r1, UInt i2)
2729 {
2730 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2731 s390_disasm(ENC3(MNM, GPR, UINT), "slgfi", r1, i2);
2732
2733 return emit_RIL(p, 0xc20400000000ULL, r1, i2);
2734 }
2735
2736
2737 static UChar *
s390_emit_LDR(UChar * p,UChar r1,UChar r2)2738 s390_emit_LDR(UChar *p, UChar r1, UChar r2)
2739 {
2740 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2741 s390_disasm(ENC3(MNM, FPR, FPR), "ldr", r1, r2);
2742
2743 return emit_RR(p, 0x2800, r1, r2);
2744 }
2745
2746
2747 static UChar *
s390_emit_LE(UChar * p,UChar r1,UChar x2,UChar b2,UShort d2)2748 s390_emit_LE(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2749 {
2750 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2751 s390_disasm(ENC3(MNM, FPR, UDXB), "le", r1, d2, x2, b2);
2752
2753 return emit_RX(p, 0x78000000, r1, x2, b2, d2);
2754 }
2755
2756
2757 static UChar *
s390_emit_LD(UChar * p,UChar r1,UChar x2,UChar b2,UShort d2)2758 s390_emit_LD(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2759 {
2760 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2761 s390_disasm(ENC3(MNM, FPR, UDXB), "ld", r1, d2, x2, b2);
2762
2763 return emit_RX(p, 0x68000000, r1, x2, b2, d2);
2764 }
2765
2766
2767 static UChar *
s390_emit_LEY(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)2768 s390_emit_LEY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2769 {
2770 vassert(s390_host_has_ldisp);
2771
2772 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2773 s390_disasm(ENC3(MNM, FPR, SDXB), "ley", r1, dh2, dl2, x2, b2);
2774
2775 return emit_RXY(p, 0xed0000000064ULL, r1, x2, b2, dl2, dh2);
2776 }
2777
2778
2779 static UChar *
s390_emit_LDY(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)2780 s390_emit_LDY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2781 {
2782 vassert(s390_host_has_ldisp);
2783
2784 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2785 s390_disasm(ENC3(MNM, FPR, SDXB), "ldy", r1, dh2, dl2, x2, b2);
2786
2787 return emit_RXY(p, 0xed0000000065ULL, r1, x2, b2, dl2, dh2);
2788 }
2789
2790
2791 static UChar *
s390_emit_LFPC(UChar * p,UChar b2,UShort d2)2792 s390_emit_LFPC(UChar *p, UChar b2, UShort d2)
2793 {
2794 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2795 s390_disasm(ENC2(MNM, UDXB), "lfpc", d2, 0, b2);
2796
2797 return emit_S(p, 0xb29d0000, b2, d2);
2798 }
2799
2800
2801 static UChar *
s390_emit_LDGR(UChar * p,UChar r1,UChar r2)2802 s390_emit_LDGR(UChar *p, UChar r1, UChar r2)
2803 {
2804 vassert(s390_host_has_fgx);
2805
2806 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2807 s390_disasm(ENC3(MNM, FPR, GPR), "ldgr", r1, r2);
2808
2809 return emit_RRE(p, 0xb3c10000, r1, r2);
2810 }
2811
2812
2813 static UChar *
s390_emit_LGDR(UChar * p,UChar r1,UChar r2)2814 s390_emit_LGDR(UChar *p, UChar r1, UChar r2)
2815 {
2816 vassert(s390_host_has_fgx);
2817
2818 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2819 s390_disasm(ENC3(MNM, GPR, FPR), "lgdr", r1, r2);
2820
2821 return emit_RRE(p, 0xb3cd0000, r1, r2);
2822 }
2823
2824
2825 static UChar *
s390_emit_LZER(UChar * p,UChar r1,UChar r2)2826 s390_emit_LZER(UChar *p, UChar r1, UChar r2)
2827 {
2828 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2829 s390_disasm(ENC2(MNM, FPR), "lzer", r1);
2830
2831 return emit_RRE(p, 0xb3740000, r1, r2);
2832 }
2833
2834
2835 static UChar *
s390_emit_LZDR(UChar * p,UChar r1,UChar r2)2836 s390_emit_LZDR(UChar *p, UChar r1, UChar r2)
2837 {
2838 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2839 s390_disasm(ENC2(MNM, FPR), "lzdr", r1);
2840
2841 return emit_RRE(p, 0xb3750000, r1, r2);
2842 }
2843
2844
2845 static UChar *
s390_emit_SFPC(UChar * p,UChar r1,UChar r2)2846 s390_emit_SFPC(UChar *p, UChar r1, UChar r2)
2847 {
2848 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2849 s390_disasm(ENC2(MNM, GPR), "sfpc", r1);
2850
2851 return emit_RRE(p, 0xb3840000, r1, r2);
2852 }
2853
2854
2855 static UChar *
s390_emit_STE(UChar * p,UChar r1,UChar x2,UChar b2,UShort d2)2856 s390_emit_STE(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2857 {
2858 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2859 s390_disasm(ENC3(MNM, FPR, UDXB), "ste", r1, d2, x2, b2);
2860
2861 return emit_RX(p, 0x70000000, r1, x2, b2, d2);
2862 }
2863
2864
2865 static UChar *
s390_emit_STD(UChar * p,UChar r1,UChar x2,UChar b2,UShort d2)2866 s390_emit_STD(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2867 {
2868 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2869 s390_disasm(ENC3(MNM, FPR, UDXB), "std", r1, d2, x2, b2);
2870
2871 return emit_RX(p, 0x60000000, r1, x2, b2, d2);
2872 }
2873
2874
2875 static UChar *
s390_emit_STEY(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)2876 s390_emit_STEY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2877 {
2878 vassert(s390_host_has_ldisp);
2879
2880 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2881 s390_disasm(ENC3(MNM, FPR, SDXB), "stey", r1, dh2, dl2, x2, b2);
2882
2883 return emit_RXY(p, 0xed0000000066ULL, r1, x2, b2, dl2, dh2);
2884 }
2885
2886
2887 static UChar *
s390_emit_STDY(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)2888 s390_emit_STDY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2889 {
2890 vassert(s390_host_has_ldisp);
2891
2892 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2893 s390_disasm(ENC3(MNM, FPR, SDXB), "stdy", r1, dh2, dl2, x2, b2);
2894
2895 return emit_RXY(p, 0xed0000000067ULL, r1, x2, b2, dl2, dh2);
2896 }
2897
2898
2899 static UChar *
s390_emit_STFPC(UChar * p,UChar b2,UShort d2)2900 s390_emit_STFPC(UChar *p, UChar b2, UShort d2)
2901 {
2902 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2903 s390_disasm(ENC2(MNM, UDXB), "stfpc", d2, 0, b2);
2904
2905 return emit_S(p, 0xb29c0000, b2, d2);
2906 }
2907
2908
2909 static UChar *
s390_emit_AEBR(UChar * p,UChar r1,UChar r2)2910 s390_emit_AEBR(UChar *p, UChar r1, UChar r2)
2911 {
2912 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2913 s390_disasm(ENC3(MNM, FPR, FPR), "aebr", r1, r2);
2914
2915 return emit_RRE(p, 0xb30a0000, r1, r2);
2916 }
2917
2918
2919 static UChar *
s390_emit_ADBR(UChar * p,UChar r1,UChar r2)2920 s390_emit_ADBR(UChar *p, UChar r1, UChar r2)
2921 {
2922 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2923 s390_disasm(ENC3(MNM, FPR, FPR), "adbr", r1, r2);
2924
2925 return emit_RRE(p, 0xb31a0000, r1, r2);
2926 }
2927
2928
2929 static UChar *
s390_emit_AXBR(UChar * p,UChar r1,UChar r2)2930 s390_emit_AXBR(UChar *p, UChar r1, UChar r2)
2931 {
2932 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2933 s390_disasm(ENC3(MNM, FPR, FPR), "axbr", r1, r2);
2934
2935 return emit_RRE(p, 0xb34a0000, r1, r2);
2936 }
2937
2938
2939 static UChar *
s390_emit_CEBR(UChar * p,UChar r1,UChar r2)2940 s390_emit_CEBR(UChar *p, UChar r1, UChar r2)
2941 {
2942 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2943 s390_disasm(ENC3(MNM, FPR, FPR), "cebr", r1, r2);
2944
2945 return emit_RRE(p, 0xb3090000, r1, r2);
2946 }
2947
2948
2949 static UChar *
s390_emit_CDBR(UChar * p,UChar r1,UChar r2)2950 s390_emit_CDBR(UChar *p, UChar r1, UChar r2)
2951 {
2952 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2953 s390_disasm(ENC3(MNM, FPR, FPR), "cdbr", r1, r2);
2954
2955 return emit_RRE(p, 0xb3190000, r1, r2);
2956 }
2957
2958
2959 static UChar *
s390_emit_CXBR(UChar * p,UChar r1,UChar r2)2960 s390_emit_CXBR(UChar *p, UChar r1, UChar r2)
2961 {
2962 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2963 s390_disasm(ENC3(MNM, FPR, FPR), "cxbr", r1, r2);
2964
2965 return emit_RRE(p, 0xb3490000, r1, r2);
2966 }
2967
2968
2969 static UChar *
s390_emit_CEFBR(UChar * p,UChar r1,UChar r2)2970 s390_emit_CEFBR(UChar *p, UChar r1, UChar r2)
2971 {
2972 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2973 s390_disasm(ENC3(MNM, FPR, GPR), "cefbr", r1, r2);
2974
2975 return emit_RRE(p, 0xb3940000, r1, r2);
2976 }
2977
2978
2979 static UChar *
s390_emit_CDFBR(UChar * p,UChar r1,UChar r2)2980 s390_emit_CDFBR(UChar *p, UChar r1, UChar r2)
2981 {
2982 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2983 s390_disasm(ENC3(MNM, FPR, GPR), "cdfbr", r1, r2);
2984
2985 return emit_RRE(p, 0xb3950000, r1, r2);
2986 }
2987
2988
2989 static UChar *
s390_emit_CXFBR(UChar * p,UChar r1,UChar r2)2990 s390_emit_CXFBR(UChar *p, UChar r1, UChar r2)
2991 {
2992 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2993 s390_disasm(ENC3(MNM, FPR, GPR), "cxfbr", r1, r2);
2994
2995 return emit_RRE(p, 0xb3960000, r1, r2);
2996 }
2997
2998
2999 static UChar *
s390_emit_CEGBR(UChar * p,UChar r1,UChar r2)3000 s390_emit_CEGBR(UChar *p, UChar r1, UChar r2)
3001 {
3002 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3003 s390_disasm(ENC3(MNM, FPR, GPR), "cegbr", r1, r2);
3004
3005 return emit_RRE(p, 0xb3a40000, r1, r2);
3006 }
3007
3008
3009 static UChar *
s390_emit_CDGBR(UChar * p,UChar r1,UChar r2)3010 s390_emit_CDGBR(UChar *p, UChar r1, UChar r2)
3011 {
3012 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3013 s390_disasm(ENC3(MNM, FPR, GPR), "cdgbr", r1, r2);
3014
3015 return emit_RRE(p, 0xb3a50000, r1, r2);
3016 }
3017
3018
3019 static UChar *
s390_emit_CXGBR(UChar * p,UChar r1,UChar r2)3020 s390_emit_CXGBR(UChar *p, UChar r1, UChar r2)
3021 {
3022 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3023 s390_disasm(ENC3(MNM, FPR, GPR), "cxgbr", r1, r2);
3024
3025 return emit_RRE(p, 0xb3a60000, r1, r2);
3026 }
3027
3028
3029 static UChar *
s390_emit_CFEBR(UChar * p,UChar r3,UChar r1,UChar r2)3030 s390_emit_CFEBR(UChar *p, UChar r3, UChar r1, UChar r2)
3031 {
3032 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3033 s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cfebr", r1, r3, r2);
3034
3035 return emit_RRF3(p, 0xb3980000, r3, r1, r2);
3036 }
3037
3038
3039 static UChar *
s390_emit_CFDBR(UChar * p,UChar r3,UChar r1,UChar r2)3040 s390_emit_CFDBR(UChar *p, UChar r3, UChar r1, UChar r2)
3041 {
3042 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3043 s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cfdbr", r1, r3, r2);
3044
3045 return emit_RRF3(p, 0xb3990000, r3, r1, r2);
3046 }
3047
3048
3049 static UChar *
s390_emit_CFXBR(UChar * p,UChar r3,UChar r1,UChar r2)3050 s390_emit_CFXBR(UChar *p, UChar r3, UChar r1, UChar r2)
3051 {
3052 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3053 s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cfxbr", r1, r3, r2);
3054
3055 return emit_RRF3(p, 0xb39a0000, r3, r1, r2);
3056 }
3057
3058
3059 static UChar *
s390_emit_CGEBR(UChar * p,UChar r3,UChar r1,UChar r2)3060 s390_emit_CGEBR(UChar *p, UChar r3, UChar r1, UChar r2)
3061 {
3062 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3063 s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cgebr", r1, r3, r2);
3064
3065 return emit_RRF3(p, 0xb3a80000, r3, r1, r2);
3066 }
3067
3068
3069 static UChar *
s390_emit_CGDBR(UChar * p,UChar r3,UChar r1,UChar r2)3070 s390_emit_CGDBR(UChar *p, UChar r3, UChar r1, UChar r2)
3071 {
3072 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3073 s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cgdbr", r1, r3, r2);
3074
3075 return emit_RRF3(p, 0xb3a90000, r3, r1, r2);
3076 }
3077
3078
3079 static UChar *
s390_emit_CGXBR(UChar * p,UChar r3,UChar r1,UChar r2)3080 s390_emit_CGXBR(UChar *p, UChar r3, UChar r1, UChar r2)
3081 {
3082 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3083 s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cgxbr", r1, r3, r2);
3084
3085 return emit_RRF3(p, 0xb3aa0000, r3, r1, r2);
3086 }
3087
3088
3089 static UChar *
s390_emit_DEBR(UChar * p,UChar r1,UChar r2)3090 s390_emit_DEBR(UChar *p, UChar r1, UChar r2)
3091 {
3092 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3093 s390_disasm(ENC3(MNM, FPR, FPR), "debr", r1, r2);
3094
3095 return emit_RRE(p, 0xb30d0000, r1, r2);
3096 }
3097
3098
3099 static UChar *
s390_emit_DDBR(UChar * p,UChar r1,UChar r2)3100 s390_emit_DDBR(UChar *p, UChar r1, UChar r2)
3101 {
3102 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3103 s390_disasm(ENC3(MNM, FPR, FPR), "ddbr", r1, r2);
3104
3105 return emit_RRE(p, 0xb31d0000, r1, r2);
3106 }
3107
3108
3109 static UChar *
s390_emit_DXBR(UChar * p,UChar r1,UChar r2)3110 s390_emit_DXBR(UChar *p, UChar r1, UChar r2)
3111 {
3112 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3113 s390_disasm(ENC3(MNM, FPR, FPR), "dxbr", r1, r2);
3114
3115 return emit_RRE(p, 0xb34d0000, r1, r2);
3116 }
3117
3118
3119 static UChar *
s390_emit_LCEBR(UChar * p,UChar r1,UChar r2)3120 s390_emit_LCEBR(UChar *p, UChar r1, UChar r2)
3121 {
3122 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3123 s390_disasm(ENC3(MNM, FPR, FPR), "lcebr", r1, r2);
3124
3125 return emit_RRE(p, 0xb3030000, r1, r2);
3126 }
3127
3128
3129 static UChar *
s390_emit_LCDBR(UChar * p,UChar r1,UChar r2)3130 s390_emit_LCDBR(UChar *p, UChar r1, UChar r2)
3131 {
3132 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3133 s390_disasm(ENC3(MNM, FPR, FPR), "lcdbr", r1, r2);
3134
3135 return emit_RRE(p, 0xb3130000, r1, r2);
3136 }
3137
3138
3139 static UChar *
s390_emit_LCXBR(UChar * p,UChar r1,UChar r2)3140 s390_emit_LCXBR(UChar *p, UChar r1, UChar r2)
3141 {
3142 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3143 s390_disasm(ENC3(MNM, FPR, FPR), "lcxbr", r1, r2);
3144
3145 return emit_RRE(p, 0xb3430000, r1, r2);
3146 }
3147
3148
3149 static UChar *
s390_emit_LDEBR(UChar * p,UChar r1,UChar r2)3150 s390_emit_LDEBR(UChar *p, UChar r1, UChar r2)
3151 {
3152 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3153 s390_disasm(ENC3(MNM, FPR, FPR), "ldebr", r1, r2);
3154
3155 return emit_RRE(p, 0xb3040000, r1, r2);
3156 }
3157
3158
3159 static UChar *
s390_emit_LXDBR(UChar * p,UChar r1,UChar r2)3160 s390_emit_LXDBR(UChar *p, UChar r1, UChar r2)
3161 {
3162 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3163 s390_disasm(ENC3(MNM, FPR, FPR), "lxdbr", r1, r2);
3164
3165 return emit_RRE(p, 0xb3050000, r1, r2);
3166 }
3167
3168
3169 static UChar *
s390_emit_LXEBR(UChar * p,UChar r1,UChar r2)3170 s390_emit_LXEBR(UChar *p, UChar r1, UChar r2)
3171 {
3172 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3173 s390_disasm(ENC3(MNM, FPR, FPR), "lxebr", r1, r2);
3174
3175 return emit_RRE(p, 0xb3060000, r1, r2);
3176 }
3177
3178
3179 static UChar *
s390_emit_LNEBR(UChar * p,UChar r1,UChar r2)3180 s390_emit_LNEBR(UChar *p, UChar r1, UChar r2)
3181 {
3182 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3183 s390_disasm(ENC3(MNM, FPR, FPR), "lnebr", r1, r2);
3184
3185 return emit_RRE(p, 0xb3010000, r1, r2);
3186 }
3187
3188
3189 static UChar *
s390_emit_LNDBR(UChar * p,UChar r1,UChar r2)3190 s390_emit_LNDBR(UChar *p, UChar r1, UChar r2)
3191 {
3192 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3193 s390_disasm(ENC3(MNM, FPR, FPR), "lndbr", r1, r2);
3194
3195 return emit_RRE(p, 0xb3110000, r1, r2);
3196 }
3197
3198
3199 static UChar *
s390_emit_LNXBR(UChar * p,UChar r1,UChar r2)3200 s390_emit_LNXBR(UChar *p, UChar r1, UChar r2)
3201 {
3202 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3203 s390_disasm(ENC3(MNM, FPR, FPR), "lnxbr", r1, r2);
3204
3205 return emit_RRE(p, 0xb3410000, r1, r2);
3206 }
3207
3208
3209 static UChar *
s390_emit_LPEBR(UChar * p,UChar r1,UChar r2)3210 s390_emit_LPEBR(UChar *p, UChar r1, UChar r2)
3211 {
3212 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3213 s390_disasm(ENC3(MNM, FPR, FPR), "lpebr", r1, r2);
3214
3215 return emit_RRE(p, 0xb3000000, r1, r2);
3216 }
3217
3218
3219 static UChar *
s390_emit_LPDBR(UChar * p,UChar r1,UChar r2)3220 s390_emit_LPDBR(UChar *p, UChar r1, UChar r2)
3221 {
3222 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3223 s390_disasm(ENC3(MNM, FPR, FPR), "lpdbr", r1, r2);
3224
3225 return emit_RRE(p, 0xb3100000, r1, r2);
3226 }
3227
3228
3229 static UChar *
s390_emit_LPXBR(UChar * p,UChar r1,UChar r2)3230 s390_emit_LPXBR(UChar *p, UChar r1, UChar r2)
3231 {
3232 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3233 s390_disasm(ENC3(MNM, FPR, FPR), "lpxbr", r1, r2);
3234
3235 return emit_RRE(p, 0xb3400000, r1, r2);
3236 }
3237
3238
3239 static UChar *
s390_emit_LEDBR(UChar * p,UChar r1,UChar r2)3240 s390_emit_LEDBR(UChar *p, UChar r1, UChar r2)
3241 {
3242 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3243 s390_disasm(ENC3(MNM, FPR, FPR), "ledbr", r1, r2);
3244
3245 return emit_RRE(p, 0xb3440000, r1, r2);
3246 }
3247
3248
3249 static UChar *
s390_emit_LDXBR(UChar * p,UChar r1,UChar r2)3250 s390_emit_LDXBR(UChar *p, UChar r1, UChar r2)
3251 {
3252 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3253 s390_disasm(ENC3(MNM, FPR, FPR), "ldxbr", r1, r2);
3254
3255 return emit_RRE(p, 0xb3450000, r1, r2);
3256 }
3257
3258
3259 static UChar *
s390_emit_LEXBR(UChar * p,UChar r1,UChar r2)3260 s390_emit_LEXBR(UChar *p, UChar r1, UChar r2)
3261 {
3262 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3263 s390_disasm(ENC3(MNM, FPR, FPR), "lexbr", r1, r2);
3264
3265 return emit_RRE(p, 0xb3460000, r1, r2);
3266 }
3267
3268
3269 static UChar *
s390_emit_MEEBR(UChar * p,UChar r1,UChar r2)3270 s390_emit_MEEBR(UChar *p, UChar r1, UChar r2)
3271 {
3272 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3273 s390_disasm(ENC3(MNM, FPR, FPR), "meebr", r1, r2);
3274
3275 return emit_RRE(p, 0xb3170000, r1, r2);
3276 }
3277
3278
3279 static UChar *
s390_emit_MDBR(UChar * p,UChar r1,UChar r2)3280 s390_emit_MDBR(UChar *p, UChar r1, UChar r2)
3281 {
3282 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3283 s390_disasm(ENC3(MNM, FPR, FPR), "mdbr", r1, r2);
3284
3285 return emit_RRE(p, 0xb31c0000, r1, r2);
3286 }
3287
3288
3289 static UChar *
s390_emit_MXBR(UChar * p,UChar r1,UChar r2)3290 s390_emit_MXBR(UChar *p, UChar r1, UChar r2)
3291 {
3292 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3293 s390_disasm(ENC3(MNM, FPR, FPR), "mxbr", r1, r2);
3294
3295 return emit_RRE(p, 0xb34c0000, r1, r2);
3296 }
3297
3298
3299 static UChar *
s390_emit_MAEBR(UChar * p,UChar r1,UChar r3,UChar r2)3300 s390_emit_MAEBR(UChar *p, UChar r1, UChar r3, UChar r2)
3301 {
3302 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3303 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "maebr", r1, r3, r2);
3304
3305 return emit_RRF(p, 0xb30e0000, r1, r3, r2);
3306 }
3307
3308
3309 static UChar *
s390_emit_MADBR(UChar * p,UChar r1,UChar r3,UChar r2)3310 s390_emit_MADBR(UChar *p, UChar r1, UChar r3, UChar r2)
3311 {
3312 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3313 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "madbr", r1, r3, r2);
3314
3315 return emit_RRF(p, 0xb31e0000, r1, r3, r2);
3316 }
3317
3318
3319 static UChar *
s390_emit_MSEBR(UChar * p,UChar r1,UChar r3,UChar r2)3320 s390_emit_MSEBR(UChar *p, UChar r1, UChar r3, UChar r2)
3321 {
3322 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3323 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "msebr", r1, r3, r2);
3324
3325 return emit_RRF(p, 0xb30f0000, r1, r3, r2);
3326 }
3327
3328
3329 static UChar *
s390_emit_MSDBR(UChar * p,UChar r1,UChar r3,UChar r2)3330 s390_emit_MSDBR(UChar *p, UChar r1, UChar r3, UChar r2)
3331 {
3332 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3333 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "msdbr", r1, r3, r2);
3334
3335 return emit_RRF(p, 0xb31f0000, r1, r3, r2);
3336 }
3337
3338
3339 static UChar *
s390_emit_SQEBR(UChar * p,UChar r1,UChar r2)3340 s390_emit_SQEBR(UChar *p, UChar r1, UChar r2)
3341 {
3342 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3343 s390_disasm(ENC3(MNM, FPR, FPR), "sqebr", r1, r2);
3344
3345 return emit_RRE(p, 0xb3140000, r1, r2);
3346 }
3347
3348
3349 static UChar *
s390_emit_SQDBR(UChar * p,UChar r1,UChar r2)3350 s390_emit_SQDBR(UChar *p, UChar r1, UChar r2)
3351 {
3352 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3353 s390_disasm(ENC3(MNM, FPR, FPR), "sqdbr", r1, r2);
3354
3355 return emit_RRE(p, 0xb3150000, r1, r2);
3356 }
3357
3358
3359 static UChar *
s390_emit_SQXBR(UChar * p,UChar r1,UChar r2)3360 s390_emit_SQXBR(UChar *p, UChar r1, UChar r2)
3361 {
3362 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3363 s390_disasm(ENC3(MNM, FPR, FPR), "sqxbr", r1, r2);
3364
3365 return emit_RRE(p, 0xb3160000, r1, r2);
3366 }
3367
3368
3369 static UChar *
s390_emit_SEBR(UChar * p,UChar r1,UChar r2)3370 s390_emit_SEBR(UChar *p, UChar r1, UChar r2)
3371 {
3372 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3373 s390_disasm(ENC3(MNM, FPR, FPR), "sebr", r1, r2);
3374
3375 return emit_RRE(p, 0xb30b0000, r1, r2);
3376 }
3377
3378
3379 static UChar *
s390_emit_SDBR(UChar * p,UChar r1,UChar r2)3380 s390_emit_SDBR(UChar *p, UChar r1, UChar r2)
3381 {
3382 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3383 s390_disasm(ENC3(MNM, FPR, FPR), "sdbr", r1, r2);
3384
3385 return emit_RRE(p, 0xb31b0000, r1, r2);
3386 }
3387
3388
3389 static UChar *
s390_emit_SXBR(UChar * p,UChar r1,UChar r2)3390 s390_emit_SXBR(UChar *p, UChar r1, UChar r2)
3391 {
3392 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3393 s390_disasm(ENC3(MNM, FPR, FPR), "sxbr", r1, r2);
3394
3395 return emit_RRE(p, 0xb34b0000, r1, r2);
3396 }
3397
3398
3399 /* Provide a symbolic name for register "R0" */
3400 #define R0 0
3401
3402 /* Split up a 20-bit displacement into its high and low piece
3403 suitable for passing as function arguments */
3404 #define DISP20(d) (((UInt)d) & 0xFFF), ((((UInt)d) >> 12) & 0xFF)
3405
3406 /*---------------------------------------------------------------*/
3407 /*--- Helper functions ---*/
3408 /*---------------------------------------------------------------*/
3409
3410 static __inline__ Bool
uint_fits_signed_16bit(UInt val)3411 uint_fits_signed_16bit(UInt val)
3412 {
3413 int v = val & 0xFFFFu;
3414
3415 /* sign extend */
3416 v = (v << 16) >> 16;
3417
3418 return val == (UInt)v;
3419 }
3420
3421
3422 static __inline__ Bool
ulong_fits_signed_16bit(ULong val)3423 ulong_fits_signed_16bit(ULong val)
3424 {
3425 Long v = val & 0xFFFFu;
3426
3427 /* sign extend */
3428 v = (v << 48) >> 48;
3429
3430 return val == (ULong)v;
3431 }
3432
3433
3434 static __inline__ Bool
ulong_fits_signed_32bit(ULong val)3435 ulong_fits_signed_32bit(ULong val)
3436 {
3437 Long v = val & 0xFFFFFFFFu;
3438
3439 /* sign extend */
3440 v = (v << 32) >> 32;
3441
3442 return val == (ULong)v;
3443 }
3444
3445
3446 static __inline__ Bool
ulong_fits_unsigned_32bit(ULong val)3447 ulong_fits_unsigned_32bit(ULong val)
3448 {
3449 return (val & 0xFFFFFFFFu) == val;
3450 }
3451
3452
3453 /* Load a 64-bit immediate VAL into register REG. */
3454 static UChar *
s390_emit_load_64imm(UChar * p,UChar reg,ULong val)3455 s390_emit_load_64imm(UChar *p, UChar reg, ULong val)
3456 {
3457 if (ulong_fits_signed_16bit(val)) {
3458 return s390_emit_LGHI(p, reg, val);
3459 }
3460
3461 if (s390_host_has_eimm) {
3462 if (ulong_fits_unsigned_32bit(val)) {
3463 return s390_emit_LLILF(p, reg, val);
3464 }
3465 if (ulong_fits_signed_32bit(val)) {
3466 /* LGFI's sign extension will recreate the correct 64-bit value */
3467 return s390_emit_LGFI(p, reg, val);
3468 }
3469 /* Do it in two steps: upper half [0:31] and lower half [32:63] */
3470 p = s390_emit_IIHF(p, reg, val >> 32);
3471 return s390_emit_IILF(p, reg, val & 0xFFFFFFFF);
3472 }
3473
3474 /* Fall back */
3475 if (ulong_fits_unsigned_32bit(val)) {
3476 p = s390_emit_LLILH(p, reg, (val >> 16) & 0xFFFF); /* sets val[32:47]
3477 val[0:31] = 0 */
3478 p = s390_emit_IILL(p, reg, val & 0xFFFF); /* sets val[48:63] */
3479 return p;
3480 }
3481
3482 p = s390_emit_IIHH(p, reg, (val >> 48) & 0xFFFF);
3483 p = s390_emit_IIHL(p, reg, (val >> 32) & 0xFFFF);
3484 p = s390_emit_IILH(p, reg, (val >> 16) & 0xFFFF);
3485 p = s390_emit_IILL(p, reg, val & 0xFFFF);
3486
3487 return p;
3488 }
3489
3490 /* Load a 32-bit immediate VAL into register REG. */
3491 static UChar *
s390_emit_load_32imm(UChar * p,UChar reg,UInt val)3492 s390_emit_load_32imm(UChar *p, UChar reg, UInt val)
3493 {
3494 if (uint_fits_signed_16bit(val)) {
3495 /* LHI's sign extension will recreate the correct 32-bit value */
3496 return s390_emit_LHI(p, reg, val);
3497 }
3498 if (s390_host_has_eimm) {
3499 return s390_emit_IILF(p, reg, val);
3500 }
3501 /* val[0:15] --> (val >> 16) & 0xFFFF
3502 val[16:31] --> val & 0xFFFF */
3503 p = s390_emit_IILH(p, reg, (val >> 16) & 0xFFFF);
3504 return s390_emit_IILL(p, reg, val & 0xFFFF);
3505 }
3506
3507 /*------------------------------------------------------------*/
3508 /*--- Wrapper functions ---*/
3509 /*------------------------------------------------------------*/
3510
3511 /* r1[32:63],r1+1[32:63] = r1+1[32:63] * memory[op2addr][0:31] */
3512 static UChar *
s390_emit_MFYw(UChar * p,UChar r1,UChar x,UChar b,UShort dl,UChar dh)3513 s390_emit_MFYw(UChar *p, UChar r1, UChar x, UChar b, UShort dl, UChar dh)
3514 {
3515 if (s390_host_has_gie) {
3516 return s390_emit_MFY(p, r1, x, b, dl, dh);
3517 }
3518
3519 /* Load from memory into R0, then MULTIPLY with R1 */
3520 p = s390_emit_LY(p, R0, x, b, dl, dh);
3521 return s390_emit_MR(p, r1, R0);
3522 }
3523
3524 /* r1[32:63] = r1[32:63] * memory[op2addr][0:15] */
3525 static UChar *
s390_emit_MHYw(UChar * p,UChar r1,UChar x,UChar b,UShort dl,UChar dh)3526 s390_emit_MHYw(UChar *p, UChar r1, UChar x, UChar b, UShort dl, UChar dh)
3527 {
3528 if (s390_host_has_gie) {
3529 return s390_emit_MHY(p, r1, x, b, dl, dh);
3530 }
3531
3532 /* Load from memory into R0, then MULTIPLY with R1 */
3533 p = s390_emit_LHY(p, R0, x, b, dl, dh);
3534 return s390_emit_MSR(p, r1, R0);
3535 }
3536
3537 /* r1[32:63] = r1[32:63] * i2 */
3538 static UChar *
s390_emit_MSFIw(UChar * p,UChar r1,UInt i2)3539 s390_emit_MSFIw(UChar *p, UChar r1, UInt i2)
3540 {
3541 if (s390_host_has_gie) {
3542 return s390_emit_MSFI(p, r1, i2);
3543 }
3544
3545 /* Load I2 into R0; then MULTIPLY R0 with R1 */
3546 p = s390_emit_load_32imm(p, R0, i2);
3547 return s390_emit_MSR(p, r1, R0);
3548 }
3549
3550
3551 /* r1[32:63] = r1[32:63] & i2 */
3552 static UChar *
s390_emit_NILFw(UChar * p,UChar r1,UInt i2)3553 s390_emit_NILFw(UChar *p, UChar r1, UInt i2)
3554 {
3555 if (s390_host_has_eimm) {
3556 return s390_emit_NILF(p, r1, i2);
3557 }
3558
3559 /* Load I2 into R0; then AND R0 with R1 */
3560 p = s390_emit_load_32imm(p, R0, i2);
3561 return s390_emit_NR(p, r1, R0);
3562 }
3563
3564
3565 /* r1[32:63] = r1[32:63] | i2 */
3566 static UChar *
s390_emit_OILFw(UChar * p,UChar r1,UInt i2)3567 s390_emit_OILFw(UChar *p, UChar r1, UInt i2)
3568 {
3569 if (s390_host_has_eimm) {
3570 return s390_emit_OILF(p, r1, i2);
3571 }
3572
3573 /* Load I2 into R0; then AND R0 with R1 */
3574 p = s390_emit_load_32imm(p, R0, i2);
3575 return s390_emit_OR(p, r1, R0);
3576 }
3577
3578
3579 /* r1[32:63] = r1[32:63] ^ i2 */
3580 static UChar *
s390_emit_XILFw(UChar * p,UChar r1,UInt i2)3581 s390_emit_XILFw(UChar *p, UChar r1, UInt i2)
3582 {
3583 if (s390_host_has_eimm) {
3584 return s390_emit_XILF(p, r1, i2);
3585 }
3586
3587 /* Load I2 into R0; then AND R0 with R1 */
3588 p = s390_emit_load_32imm(p, R0, i2);
3589 return s390_emit_XR(p, r1, R0);
3590 }
3591
3592
3593 /* r1[32:63] = sign_extend(mem[op2addr][0:7]) */
3594 static UChar *
s390_emit_LBw(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)3595 s390_emit_LBw(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3596 {
3597 vassert(s390_host_has_ldisp || dh2 == 0);
3598
3599 if (s390_host_has_ldisp) {
3600 return s390_emit_LB(p, r1, x2, b2, dl2, dh2);
3601 }
3602
3603 p = s390_emit_IC(p, r1, x2, b2, dl2); /* r1[56:63] = mem[op2addr][0:7] */
3604 p = s390_emit_SLL(p, r1, R0, 24); /* r1 = r1 << 24 */
3605 return s390_emit_SRA(p, r1, R0, 24); /* r1 = r1 >>a 24 */
3606 }
3607
3608
3609 /* r1[32:63] = sign_extend(r2[56:63]) */
3610 static UChar *
s390_emit_LBRw(UChar * p,UChar r1,UChar r2)3611 s390_emit_LBRw(UChar *p, UChar r1, UChar r2)
3612 {
3613 if (s390_host_has_eimm) {
3614 return s390_emit_LBR(p, r1, r2);
3615 }
3616
3617 p = s390_emit_LR(p, r1, r2); /* r1 = r2 */
3618 p = s390_emit_SLL(p, r1, R0, 24); /* r1 = r1 << 24 */
3619 return s390_emit_SRA(p, r1, R0, 24); /* r1 = r1 >>a 24 */
3620 }
3621
3622
3623 /* r1[0:63] = sign_extend(mem[op2addr][0:7]) */
3624 static UChar *
s390_emit_LGBw(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl2,UChar dh2)3625 s390_emit_LGBw(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3626 {
3627 vassert(s390_host_has_ldisp || dh2 == 0);
3628
3629 if (s390_host_has_ldisp) {
3630 return s390_emit_LGB(p, r1, x2, b2, dl2, dh2);
3631 }
3632
3633 p = s390_emit_IC(p, r1, x2, b2, dl2); /* r1[56:63] = mem[op2addr][0:7] */
3634 p = s390_emit_SLLG(p, r1, r1, R0, DISP20(56)); /* r1 = r1 << 56 */
3635 return s390_emit_SRAG(p, r1, r1, R0, DISP20(56)); /* r1 = r1 >>a 56 */
3636 }
3637
3638
3639 /* r1[0:63] = sign_extend(r2[56:63]) */
3640 static UChar *
s390_emit_LGBRw(UChar * p,UChar r1,UChar r2)3641 s390_emit_LGBRw(UChar *p, UChar r1, UChar r2)
3642 {
3643 if (s390_host_has_eimm) {
3644 return s390_emit_LGBR(p, r1, r2);
3645 }
3646
3647 p = s390_emit_LR(p, r1, r2); /* r1 = r2 */
3648 p = s390_emit_SLLG(p, r1, r1, R0, DISP20(56)); /* r1 = r1 << 56 */
3649 return s390_emit_SRAG(p, r1, r1, R0, DISP20(56)); /* r1 = r1 >>a 56 */
3650 }
3651
3652
3653 /* r1[32:63] = sign_extend(r2[48:63]) */
3654 static UChar *
s390_emit_LHRw(UChar * p,UChar r1,UChar r2)3655 s390_emit_LHRw(UChar *p, UChar r1, UChar r2)
3656 {
3657 if (s390_host_has_eimm) {
3658 return s390_emit_LHR(p, r1, r2);
3659 }
3660
3661 p = s390_emit_LR(p, r1, r2); /* r1 = r2 */
3662 p = s390_emit_SLL(p, r1, R0, 16); /* r1 = r1 << 16 */
3663 return s390_emit_SRA(p, r1, R0, 16); /* r1 = r1 >>a 16 */
3664 }
3665
3666
3667 /* r1[0:63] = sign_extend(r2[48:63]) */
3668 static UChar *
s390_emit_LGHRw(UChar * p,UChar r1,UChar r2)3669 s390_emit_LGHRw(UChar *p, UChar r1, UChar r2)
3670 {
3671 if (s390_host_has_eimm) {
3672 return s390_emit_LGHR(p, r1, r2);
3673 }
3674
3675 p = s390_emit_LR(p, r1, r2); /* r1 = r2 */
3676 p = s390_emit_SLLG(p, r1, r1, R0, DISP20(48)); /* r1 = r1 << 48 */
3677 return s390_emit_SRAG(p, r1, r1, R0, DISP20(48)); /* r1 = r1 >>a 48 */
3678 }
3679
3680
3681 /* r1[0:63] = sign_extend(i2) */
3682 static UChar *
s390_emit_LGFIw(UChar * p,UChar r1,UInt i2)3683 s390_emit_LGFIw(UChar *p, UChar r1, UInt i2)
3684 {
3685 if (s390_host_has_eimm) {
3686 return s390_emit_LGFI(p, r1, i2);
3687 }
3688
3689 p = s390_emit_load_32imm(p, R0, i2);
3690 return s390_emit_LGFR(p, r1, R0);
3691 }
3692
3693
3694 /* r1[32:63] = zero_extend($r2[56:63]) */
3695 static UChar *
s390_emit_LLCRw(UChar * p,UChar r1,UChar r2)3696 s390_emit_LLCRw(UChar *p, UChar r1, UChar r2)
3697 {
3698 if (s390_host_has_eimm) {
3699 return s390_emit_LLCR(p, r1, r2);
3700 }
3701
3702 p = s390_emit_LR(p, r1, r2);
3703 p = s390_emit_LHI(p, R0, 0xFF);
3704 return s390_emit_NR(p, r1, R0);
3705 }
3706
3707
3708 /* r1[0:63] = zero_extend($r2[56:63]) */
3709 static UChar *
s390_emit_LLGCRw(UChar * p,UChar r1,UChar r2)3710 s390_emit_LLGCRw(UChar *p, UChar r1, UChar r2)
3711 {
3712 if (s390_host_has_eimm) {
3713 return s390_emit_LLGCR(p, r1, r2);
3714 }
3715
3716 p = s390_emit_LR(p, r1, r2);
3717 p = s390_emit_LLILL(p, R0, 0xFF);
3718 return s390_emit_NGR(p, r1, R0);
3719 }
3720
3721
3722 /* r1[32:63] = zero_extend(r2[48:63]) */
3723 static UChar *
s390_emit_LLHRw(UChar * p,UChar r1,UChar r2)3724 s390_emit_LLHRw(UChar *p, UChar r1, UChar r2)
3725 {
3726 if (s390_host_has_eimm) {
3727 return s390_emit_LLHR(p, r1, r2);
3728 }
3729
3730 p = s390_emit_LR(p, r1, r2);
3731 p = s390_emit_LLILL(p, R0, 0xFFFF);
3732 return s390_emit_NR(p, r1, R0);
3733 }
3734
3735
3736 /* r1[0:63] = zero_extend(r2[48:63]) */
3737 static UChar *
s390_emit_LLGHRw(UChar * p,UChar r1,UChar r2)3738 s390_emit_LLGHRw(UChar *p, UChar r1, UChar r2)
3739 {
3740 if (s390_host_has_eimm) {
3741 return s390_emit_LLGHR(p, r1, r2);
3742 }
3743
3744 p = s390_emit_LR(p, r1, r2);
3745 p = s390_emit_LLILL(p, R0, 0xFFFF);
3746 return s390_emit_NGR(p, r1, R0);
3747 }
3748
3749
3750 /* r1[32:63] = zero_extend(mem[op2addr][0:7]) */
3751 static UChar *
s390_emit_LLCw(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl,UChar dh)3752 s390_emit_LLCw(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl, UChar dh)
3753 {
3754 if (s390_host_has_eimm) {
3755 return s390_emit_LLC(p, r1, x2, b2, dl, dh);
3756 }
3757
3758 if (dh == 0) {
3759 p = s390_emit_IC(p, r1, x2, b2, dl);
3760 } else {
3761 p = s390_emit_ICY(p, r1, x2, b2, dl, dh);
3762 }
3763 p = s390_emit_LLILL(p, R0, 0xFF);
3764 return s390_emit_NR(p, r1, R0);
3765 }
3766
3767
3768 /* r1[32:63] = zero_extend(mem[op2addr][0:15]) */
3769 static UChar *
s390_emit_LLHw(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl,UChar dh)3770 s390_emit_LLHw(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl, UChar dh)
3771 {
3772 if (s390_host_has_eimm) {
3773 return s390_emit_LLH(p, r1, x2, b2, dl, dh);
3774 }
3775
3776 p = s390_emit_LLGH(p, r1, x2, b2, dl, dh);
3777 p = s390_emit_LLILL(p, R0, 0xFFFF);
3778 return s390_emit_NR(p, r1, R0);
3779 }
3780
3781
3782 /* r1[0:63] = zero_extend(i2) */
3783 static UChar *
s390_emit_LLILFw(UChar * p,UChar r1,UInt i2)3784 s390_emit_LLILFw(UChar *p, UChar r1, UInt i2)
3785 {
3786 if (s390_host_has_eimm) {
3787 return s390_emit_LLILF(p, r1, i2);
3788 }
3789
3790 p = s390_emit_LLILH(p, r1, (i2 >> 16) & 0xFFFF); /* i2[0:15] */
3791 return s390_emit_OILL(p, r1, i2 & 0xFFFF);
3792 }
3793
3794
3795 /* r1[32:63] = r1[32:63] + i2 */
3796 static UChar *
s390_emit_AFIw(UChar * p,UChar r1,UInt i2)3797 s390_emit_AFIw(UChar *p, UChar r1, UInt i2)
3798 {
3799 if (s390_host_has_eimm) {
3800 return s390_emit_AFI(p, r1, i2);
3801 }
3802 /* Load 32 bit immediate to R0 then add */
3803 p = s390_emit_load_32imm(p, R0, i2);
3804 return s390_emit_AR(p, r1, R0);
3805 }
3806
3807
3808 /* r1[32:63] = r1[32:63] - i2 */
3809 static UChar *
s390_emit_SLFIw(UChar * p,UChar r1,UInt i2)3810 s390_emit_SLFIw(UChar *p, UChar r1, UInt i2)
3811 {
3812 if (s390_host_has_eimm) {
3813 return s390_emit_SLFI(p, r1, i2);
3814 }
3815
3816 /* Load 32 bit immediate to R0 then subtract */
3817 p = s390_emit_load_32imm(p, R0, i2);
3818 return s390_emit_SR(p, r1, R0);
3819 }
3820
3821
3822 /* r1[0:63] = r1[0:63] - zero_extend(i2) */
3823 static UChar *
s390_emit_SLGFIw(UChar * p,UChar r1,UInt i2)3824 s390_emit_SLGFIw(UChar *p, UChar r1, UInt i2)
3825 {
3826 if (s390_host_has_eimm) {
3827 return s390_emit_SLGFI(p, r1, i2);
3828 }
3829
3830 /* Load zero-extended 32 bit immediate to R0 then subtract */
3831 p = s390_emit_load_64imm(p, R0, i2);
3832 return s390_emit_SGR(p, r1, R0);
3833 }
3834
3835
3836 static UChar *
s390_emit_LTw(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl,UChar dh)3837 s390_emit_LTw(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl, UChar dh)
3838 {
3839 if (s390_host_has_eimm) {
3840 return s390_emit_LT(p, r1, x2, b2, dl, dh);
3841 }
3842 /* Load 32 bit from memory to R0 then compare */
3843 if (dh == 0) {
3844 p = s390_emit_L(p, R0, x2, b2, dl);
3845 } else {
3846 p = s390_emit_LY(p, R0, x2, b2, dl, dh);
3847 }
3848 return s390_emit_LTR(p, r1, R0);
3849 }
3850
3851
3852 static UChar *
s390_emit_LTGw(UChar * p,UChar r1,UChar x2,UChar b2,UShort dl,UChar dh)3853 s390_emit_LTGw(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl, UChar dh)
3854 {
3855 if (s390_host_has_eimm) {
3856 return s390_emit_LTG(p, r1, x2, b2, dl, dh);
3857 }
3858 /* Load 64 bit from memory to R0 then compare */
3859 p = s390_emit_LG(p, R0, x2, b2, dl, dh);
3860 return s390_emit_LTGR(p, r1, R0);
3861 }
3862
3863
3864 static UChar *
s390_emit_CFIw(UChar * p,UChar r1,UInt i2)3865 s390_emit_CFIw(UChar *p, UChar r1, UInt i2)
3866 {
3867 if (s390_host_has_eimm) {
3868 return s390_emit_CFI(p, r1, i2);
3869 }
3870 /* Load 32 bit immediate to R0 then compare */
3871 p = s390_emit_load_32imm(p, R0, i2);
3872 return s390_emit_CR(p, r1, R0);
3873 }
3874
3875
3876 static UChar *
s390_emit_CLFIw(UChar * p,UChar r1,UInt i2)3877 s390_emit_CLFIw(UChar *p, UChar r1, UInt i2)
3878 {
3879 if (s390_host_has_eimm) {
3880 return s390_emit_CLFI(p, r1, i2);
3881 }
3882 /* Load 32 bit immediate to R0 then compare */
3883 p = s390_emit_load_32imm(p, R0, i2);
3884 return s390_emit_CLR(p, r1, R0);
3885 }
3886
3887
3888 static UChar *
s390_emit_LGDRw(UChar * p,UChar r1,UChar r2)3889 s390_emit_LGDRw(UChar *p, UChar r1, UChar r2)
3890 {
3891 if (s390_host_has_fgx) {
3892 return s390_emit_LGDR(p, r1, r2);
3893 }
3894
3895 /* Store the FPR at memory[sp - 8]. This is safe because SP grows towards
3896 smaller addresses and is 8-byte aligned. Then load the GPR from that
3897 memory location/ */
3898 if (s390_host_has_ldisp) {
3899 p = s390_emit_STDY(p, r2, R0, S390_REGNO_STACK_POINTER, DISP20(-8));
3900 return s390_emit_LG(p, r1, R0, S390_REGNO_STACK_POINTER, DISP20(-8));
3901 }
3902
3903 /* No long displacement. Need to adjust SP explicitly as to avoid negative
3904 displacements. */
3905 p = s390_emit_AGHI(p, S390_REGNO_STACK_POINTER, -8);
3906 p = s390_emit_STD(p, r2, R0, S390_REGNO_STACK_POINTER, 0);
3907 p = s390_emit_LG(p, r1, R0, S390_REGNO_STACK_POINTER, DISP20(0));
3908 return s390_emit_AGHI(p, S390_REGNO_STACK_POINTER, 8);
3909 }
3910
3911
3912 static UChar *
s390_emit_LDGRw(UChar * p,UChar r1,UChar r2)3913 s390_emit_LDGRw(UChar *p, UChar r1, UChar r2)
3914 {
3915 if (s390_host_has_fgx) {
3916 return s390_emit_LDGR(p, r1, r2);
3917 }
3918
3919 /* Store the GPR at memory[sp - 8]. This is safe because SP grows towards
3920 smaller addresses and is 8-byte aligned. Then load the FPR from that
3921 memory location/ */
3922 if (s390_host_has_ldisp) {
3923 p = s390_emit_STG(p, r2, R0, S390_REGNO_STACK_POINTER, DISP20(-8));
3924 return s390_emit_LDY(p, r1, R0, S390_REGNO_STACK_POINTER, DISP20(-8));
3925 }
3926
3927 /* No long displacement. Need to adjust SP explicitly as to avoid negative
3928 displacements. */
3929 p = s390_emit_AGHI(p, S390_REGNO_STACK_POINTER, -8);
3930 p = s390_emit_STG(p, r2, R0, S390_REGNO_STACK_POINTER, DISP20(0));
3931 p = s390_emit_LD(p, r1, R0, S390_REGNO_STACK_POINTER, 0);
3932 return s390_emit_AGHI(p, S390_REGNO_STACK_POINTER, 8);
3933 }
3934
3935
3936 /*---------------------------------------------------------------*/
3937 /*--- Constructors for the various s390_insn kinds ---*/
3938 /*---------------------------------------------------------------*/
3939
3940 s390_insn *
s390_insn_load(UChar size,HReg dst,s390_amode * src)3941 s390_insn_load(UChar size, HReg dst, s390_amode *src)
3942 {
3943 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
3944
3945 insn->tag = S390_INSN_LOAD;
3946 insn->size = size;
3947 insn->variant.load.src = src;
3948 insn->variant.load.dst = dst;
3949
3950 vassert(size == 1 || size == 2 || size == 4 || size == 8);
3951
3952 return insn;
3953 }
3954
3955
3956 s390_insn *
s390_insn_store(UChar size,s390_amode * dst,HReg src)3957 s390_insn_store(UChar size, s390_amode *dst, HReg src)
3958 {
3959 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
3960
3961 insn->tag = S390_INSN_STORE;
3962 insn->size = size;
3963 insn->variant.store.src = src;
3964 insn->variant.store.dst = dst;
3965
3966 vassert(size == 1 || size == 2 || size == 4 || size == 8);
3967
3968 return insn;
3969 }
3970
3971
3972 s390_insn *
s390_insn_move(UChar size,HReg dst,HReg src)3973 s390_insn_move(UChar size, HReg dst, HReg src)
3974 {
3975 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
3976
3977 insn->tag = S390_INSN_MOVE;
3978 insn->size = size;
3979 insn->variant.move.src = src;
3980 insn->variant.move.dst = dst;
3981
3982 vassert(size == 1 || size == 2 || size == 4 || size == 8);
3983
3984 return insn;
3985 }
3986
3987
3988 s390_insn *
s390_insn_cond_move(UChar size,s390_cc_t cond,HReg dst,s390_opnd_RMI src)3989 s390_insn_cond_move(UChar size, s390_cc_t cond, HReg dst, s390_opnd_RMI src)
3990 {
3991 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
3992
3993 insn->tag = S390_INSN_COND_MOVE;
3994 insn->size = size;
3995 insn->variant.cond_move.cond = cond;
3996 insn->variant.cond_move.src = src;
3997 insn->variant.cond_move.dst = dst;
3998
3999 vassert(size == 1 || size == 2 || size == 4 || size == 8);
4000
4001 return insn;
4002 }
4003
4004
4005 s390_insn *
s390_insn_load_immediate(UChar size,HReg dst,ULong value)4006 s390_insn_load_immediate(UChar size, HReg dst, ULong value)
4007 {
4008 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4009
4010 insn->tag = S390_INSN_LOAD_IMMEDIATE;
4011 insn->size = size;
4012 insn->variant.load_immediate.dst = dst;
4013 insn->variant.load_immediate.value = value;
4014
4015 return insn;
4016 }
4017
4018
4019 s390_insn *
s390_insn_alu(UChar size,s390_alu_t tag,HReg dst,s390_opnd_RMI op2)4020 s390_insn_alu(UChar size, s390_alu_t tag, HReg dst, s390_opnd_RMI op2)
4021 {
4022 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4023
4024 insn->tag = S390_INSN_ALU;
4025 insn->size = size;
4026 insn->variant.alu.tag = tag;
4027 insn->variant.alu.dst = dst;
4028 insn->variant.alu.op2 = op2;
4029
4030 return insn;
4031 }
4032
4033
4034 s390_insn *
s390_insn_mul(UChar size,HReg dst_hi,HReg dst_lo,s390_opnd_RMI op2,Bool signed_multiply)4035 s390_insn_mul(UChar size, HReg dst_hi, HReg dst_lo, s390_opnd_RMI op2,
4036 Bool signed_multiply)
4037 {
4038 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4039
4040 vassert(! hregIsVirtual(dst_hi));
4041 vassert(! hregIsVirtual(dst_lo));
4042
4043 insn->tag = S390_INSN_MUL;
4044 insn->size = size;
4045 insn->variant.mul.dst_hi = dst_hi;
4046 insn->variant.mul.dst_lo = dst_lo;
4047 insn->variant.mul.op2 = op2;
4048 insn->variant.mul.signed_multiply = signed_multiply;
4049
4050 return insn;
4051 }
4052
4053
4054 s390_insn *
s390_insn_div(UChar size,HReg op1_hi,HReg op1_lo,s390_opnd_RMI op2,Bool signed_divide)4055 s390_insn_div(UChar size, HReg op1_hi, HReg op1_lo, s390_opnd_RMI op2,
4056 Bool signed_divide)
4057 {
4058 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4059
4060 vassert(size == 4 || size == 8);
4061 vassert(! hregIsVirtual(op1_hi));
4062 vassert(! hregIsVirtual(op1_lo));
4063
4064 insn->tag = S390_INSN_DIV;
4065 insn->size = size;
4066 insn->variant.div.op1_hi = op1_hi;
4067 insn->variant.div.op1_lo = op1_lo;
4068 insn->variant.div.op2 = op2;
4069 insn->variant.div.signed_divide = signed_divide;
4070
4071 return insn;
4072 }
4073
4074
4075 s390_insn *
s390_insn_divs(UChar size,HReg rem,HReg op1,s390_opnd_RMI op2)4076 s390_insn_divs(UChar size, HReg rem, HReg op1, s390_opnd_RMI op2)
4077 {
4078 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4079
4080 vassert(size == 8);
4081 vassert(! hregIsVirtual(op1));
4082 vassert(! hregIsVirtual(rem));
4083
4084 insn->tag = S390_INSN_DIVS;
4085 insn->size = size;
4086 insn->variant.divs.rem = rem; /* remainder */
4087 insn->variant.divs.op1 = op1; /* also quotient */
4088 insn->variant.divs.op2 = op2;
4089
4090 return insn;
4091 }
4092
4093
4094 s390_insn *
s390_insn_clz(UChar size,HReg num_bits,HReg clobber,s390_opnd_RMI src)4095 s390_insn_clz(UChar size, HReg num_bits, HReg clobber, s390_opnd_RMI src)
4096 {
4097 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4098
4099 vassert(size == 8);
4100 vassert(! hregIsVirtual(num_bits));
4101 vassert(! hregIsVirtual(clobber));
4102
4103 insn->tag = S390_INSN_CLZ;
4104 insn->size = size;
4105 insn->variant.clz.num_bits = num_bits;
4106 insn->variant.clz.clobber = clobber;
4107 insn->variant.clz.src = src;
4108
4109 return insn;
4110 }
4111
4112
4113 s390_insn *
s390_insn_unop(UChar size,s390_unop_t tag,HReg dst,s390_opnd_RMI opnd)4114 s390_insn_unop(UChar size, s390_unop_t tag, HReg dst, s390_opnd_RMI opnd)
4115 {
4116 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4117
4118 insn->tag = S390_INSN_UNOP;
4119 insn->size = size;
4120 insn->variant.unop.tag = tag;
4121 insn->variant.unop.dst = dst;
4122 insn->variant.unop.src = opnd;
4123
4124 return insn;
4125 }
4126
4127
4128 s390_insn *
s390_insn_test(UChar size,s390_opnd_RMI src)4129 s390_insn_test(UChar size, s390_opnd_RMI src)
4130 {
4131 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4132
4133 vassert(size == 4 || size == 8);
4134
4135 insn->tag = S390_INSN_TEST;
4136 insn->size = size;
4137 insn->variant.test.src = src;
4138
4139 return insn;
4140 }
4141
4142
4143 s390_insn *
s390_insn_cc2bool(HReg dst,s390_cc_t cond)4144 s390_insn_cc2bool(HReg dst, s390_cc_t cond)
4145 {
4146 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4147
4148 insn->tag = S390_INSN_CC2BOOL;
4149 insn->size = 0; /* does not matter */
4150 insn->variant.cc2bool.cond = cond;
4151 insn->variant.cc2bool.dst = dst;
4152
4153 return insn;
4154 }
4155
4156
4157 s390_insn *
s390_insn_cas(UChar size,HReg op1,s390_amode * op2,HReg op3,HReg old_mem)4158 s390_insn_cas(UChar size, HReg op1, s390_amode *op2, HReg op3, HReg old_mem)
4159 {
4160 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4161
4162 vassert(size == 4 || size == 8);
4163 vassert(op2->x == 0);
4164
4165 insn->tag = S390_INSN_CAS;
4166 insn->size = size;
4167 insn->variant.cas.op1 = op1;
4168 insn->variant.cas.op2 = op2;
4169 insn->variant.cas.op3 = op3;
4170 insn->variant.cas.old_mem = old_mem;
4171
4172 return insn;
4173 }
4174
4175
4176 s390_insn *
s390_insn_compare(UChar size,HReg src1,s390_opnd_RMI src2,Bool signed_comparison)4177 s390_insn_compare(UChar size, HReg src1, s390_opnd_RMI src2,
4178 Bool signed_comparison)
4179 {
4180 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4181
4182 vassert(size == 4 || size == 8);
4183
4184 insn->tag = S390_INSN_COMPARE;
4185 insn->size = size;
4186 insn->variant.compare.src1 = src1;
4187 insn->variant.compare.src2 = src2;
4188 insn->variant.compare.signed_comparison = signed_comparison;
4189
4190 return insn;
4191 }
4192
4193
4194 s390_insn *
s390_insn_branch(IRJumpKind kind,s390_cc_t cond,s390_opnd_RMI dst)4195 s390_insn_branch(IRJumpKind kind, s390_cc_t cond, s390_opnd_RMI dst)
4196 {
4197 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4198
4199 insn->tag = S390_INSN_BRANCH;
4200 insn->size = 0; /* does not matter */
4201 insn->variant.branch.kind = kind;
4202 insn->variant.branch.dst = dst;
4203 insn->variant.branch.cond = cond;
4204
4205 return insn;
4206 }
4207
4208
4209 s390_insn *
s390_insn_helper_call(s390_cc_t cond,Addr64 target,UInt num_args,HChar * name)4210 s390_insn_helper_call(s390_cc_t cond, Addr64 target, UInt num_args,
4211 HChar *name)
4212 {
4213 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4214
4215 insn->tag = S390_INSN_HELPER_CALL;
4216 insn->size = 0; /* does not matter */
4217 insn->variant.helper_call.cond = cond;
4218 insn->variant.helper_call.target = target;
4219 insn->variant.helper_call.num_args = num_args;
4220 insn->variant.helper_call.name = name;
4221
4222 return insn;
4223 }
4224
4225
4226 s390_insn *
s390_insn_bfp_triop(UChar size,s390_bfp_triop_t tag,HReg dst,HReg op2,HReg op3,s390_round_t rounding_mode)4227 s390_insn_bfp_triop(UChar size, s390_bfp_triop_t tag, HReg dst, HReg op2,
4228 HReg op3, s390_round_t rounding_mode)
4229 {
4230 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4231
4232 insn->tag = S390_INSN_BFP_TRIOP;
4233 insn->size = size;
4234 insn->variant.bfp_triop.tag = tag;
4235 insn->variant.bfp_triop.dst = dst;
4236 insn->variant.bfp_triop.op2 = op2;
4237 insn->variant.bfp_triop.op3 = op3;
4238 insn->variant.bfp_triop.rounding_mode = rounding_mode;
4239
4240 return insn;
4241 }
4242
4243
4244 s390_insn *
s390_insn_bfp_binop(UChar size,s390_bfp_binop_t tag,HReg dst,HReg op2,s390_round_t rounding_mode)4245 s390_insn_bfp_binop(UChar size, s390_bfp_binop_t tag, HReg dst, HReg op2,
4246 s390_round_t rounding_mode)
4247 {
4248 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4249
4250 insn->tag = S390_INSN_BFP_BINOP;
4251 insn->size = size;
4252 insn->variant.bfp_binop.tag = tag;
4253 insn->variant.bfp_binop.dst = dst;
4254 insn->variant.bfp_binop.op2 = op2;
4255 insn->variant.bfp_binop.rounding_mode = rounding_mode;
4256
4257 return insn;
4258 }
4259
4260
4261 s390_insn *
s390_insn_bfp_unop(UChar size,s390_bfp_unop_t tag,HReg dst,HReg op,s390_round_t rounding_mode)4262 s390_insn_bfp_unop(UChar size, s390_bfp_unop_t tag, HReg dst, HReg op,
4263 s390_round_t rounding_mode)
4264 {
4265 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4266
4267 insn->tag = S390_INSN_BFP_UNOP;
4268 insn->size = size;
4269 insn->variant.bfp_unop.tag = tag;
4270 insn->variant.bfp_unop.dst = dst;
4271 insn->variant.bfp_unop.op = op;
4272 insn->variant.bfp_unop.rounding_mode = rounding_mode;
4273
4274 return insn;
4275 }
4276
4277
4278 s390_insn *
s390_insn_bfp_compare(UChar size,HReg dst,HReg op1,HReg op2)4279 s390_insn_bfp_compare(UChar size, HReg dst, HReg op1, HReg op2)
4280 {
4281 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4282
4283 vassert(size == 4 || size == 8);
4284
4285 insn->tag = S390_INSN_BFP_COMPARE;
4286 insn->size = size;
4287 insn->variant.bfp_compare.dst = dst;
4288 insn->variant.bfp_compare.op1 = op1;
4289 insn->variant.bfp_compare.op2 = op2;
4290
4291 return insn;
4292 }
4293
4294
4295 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,s390_round_t rounding_mode)4296 s390_insn_bfp128_binop(UChar size, s390_bfp_binop_t tag, HReg dst_hi,
4297 HReg dst_lo, HReg op2_hi, HReg op2_lo,
4298 s390_round_t rounding_mode)
4299 {
4300 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4301
4302 insn->tag = S390_INSN_BFP128_BINOP;
4303 insn->size = size;
4304 insn->variant.bfp128_binop.tag = tag;
4305 insn->variant.bfp128_binop.dst_hi = dst_hi;
4306 insn->variant.bfp128_binop.dst_lo = dst_lo;
4307 insn->variant.bfp128_binop.op2_hi = op2_hi;
4308 insn->variant.bfp128_binop.op2_lo = op2_lo;
4309 insn->variant.bfp128_binop.rounding_mode = rounding_mode;
4310
4311 return insn;
4312 }
4313
4314
4315 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,s390_round_t rounding_mode)4316 s390_insn_bfp128_unop(UChar size, s390_bfp_unop_t tag, HReg dst_hi,
4317 HReg dst_lo, HReg op_hi, HReg op_lo,
4318 s390_round_t rounding_mode)
4319 {
4320 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4321
4322 insn->tag = S390_INSN_BFP128_UNOP;
4323 insn->size = size;
4324 insn->variant.bfp128_unop.tag = tag;
4325 insn->variant.bfp128_unop.dst_hi = dst_hi;
4326 insn->variant.bfp128_unop.dst_lo = dst_lo;
4327 insn->variant.bfp128_unop.op_hi = op_hi;
4328 insn->variant.bfp128_unop.op_lo = op_lo;
4329 insn->variant.bfp128_unop.rounding_mode = rounding_mode;
4330
4331 return insn;
4332 }
4333
4334
4335 s390_insn *
s390_insn_bfp128_compare(UChar size,HReg dst,HReg op1_hi,HReg op1_lo,HReg op2_hi,HReg op2_lo)4336 s390_insn_bfp128_compare(UChar size, HReg dst, HReg op1_hi, HReg op1_lo,
4337 HReg op2_hi, HReg op2_lo)
4338 {
4339 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4340
4341 insn->tag = S390_INSN_BFP128_COMPARE;
4342 insn->size = size;
4343 insn->variant.bfp128_compare.dst = dst;
4344 insn->variant.bfp128_compare.op1_hi = op1_hi;
4345 insn->variant.bfp128_compare.op1_lo = op1_lo;
4346 insn->variant.bfp128_compare.op2_hi = op2_hi;
4347 insn->variant.bfp128_compare.op2_lo = op2_lo;
4348
4349 return insn;
4350 }
4351
4352
4353 s390_insn *
s390_insn_bfp128_convert_to(UChar size,s390_bfp_unop_t tag,HReg dst_hi,HReg dst_lo,HReg op)4354 s390_insn_bfp128_convert_to(UChar size, s390_bfp_unop_t tag, HReg dst_hi,
4355 HReg dst_lo, HReg op)
4356 {
4357 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4358
4359 insn->tag = S390_INSN_BFP128_CONVERT_TO;
4360 insn->size = size;
4361 insn->variant.bfp128_unop.tag = tag;
4362 insn->variant.bfp128_unop.dst_hi = dst_hi;
4363 insn->variant.bfp128_unop.dst_lo = dst_lo;
4364 insn->variant.bfp128_unop.op_hi = op;
4365 insn->variant.bfp128_unop.op_lo = INVALID_HREG; /* unused */
4366 insn->variant.bfp128_unop.rounding_mode = S390_ROUND_NEAREST_EVEN; /* unused */
4367
4368 return insn;
4369 }
4370
4371
4372 s390_insn *
s390_insn_bfp128_convert_from(UChar size,s390_bfp_unop_t tag,HReg dst,HReg op_hi,HReg op_lo,s390_round_t rounding_mode)4373 s390_insn_bfp128_convert_from(UChar size, s390_bfp_unop_t tag, HReg dst,
4374 HReg op_hi, HReg op_lo,
4375 s390_round_t rounding_mode)
4376 {
4377 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4378
4379 insn->tag = S390_INSN_BFP128_CONVERT_FROM;
4380 insn->size = size;
4381 insn->variant.bfp128_unop.tag = tag;
4382 insn->variant.bfp128_unop.dst_hi = dst;
4383 insn->variant.bfp128_unop.dst_lo = INVALID_HREG; /* unused */
4384 insn->variant.bfp128_unop.op_hi = op_hi;
4385 insn->variant.bfp128_unop.op_lo = op_lo;
4386 insn->variant.bfp128_unop.rounding_mode = rounding_mode;
4387
4388 return insn;
4389 }
4390
4391
4392 s390_insn *
s390_insn_mfence(void)4393 s390_insn_mfence(void)
4394 {
4395 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4396
4397 insn->tag = S390_INSN_MFENCE;
4398 insn->size = 0; /* not needed */
4399
4400 return insn;
4401 }
4402
4403
4404 /*---------------------------------------------------------------*/
4405 /*--- Debug print ---*/
4406 /*---------------------------------------------------------------*/
4407
4408 static const HChar *
s390_cc_as_string(s390_cc_t cc)4409 s390_cc_as_string(s390_cc_t cc)
4410 {
4411 switch (cc) {
4412 case S390_CC_NEVER: return "never";
4413 case S390_CC_OVFL: return "overflow";
4414 case S390_CC_H: return "greater than"; /* A > B ; high */
4415 case S390_CC_NLE: return "not low or equal";
4416 case S390_CC_L: return "less than"; /* A < B ; low */
4417 case S390_CC_NHE: return "not high or equal";
4418 case S390_CC_LH: return "low or high";
4419 case S390_CC_NE: return "not equal"; /* A != B ; not zero */
4420 case S390_CC_E: return "equal"; /* A == B ; zero */
4421 case S390_CC_NLH: return "not low or high";
4422 case S390_CC_HE: return "greater or equal"; /* A >= B ; high or equal*/
4423 case S390_CC_NL: return "not low"; /* not low */
4424 case S390_CC_LE: return "less or equal"; /* A <= B ; low or equal */
4425 case S390_CC_NH: return "not high";
4426 case S390_CC_NO: return "not overflow";
4427 case S390_CC_ALWAYS: return "always";
4428 default:
4429 vpanic("s390_cc_as_string");
4430 }
4431 }
4432
4433
4434 /* Helper function for writing out a V insn */
4435 static void
s390_sprintf(HChar * buf,HChar * fmt,...)4436 s390_sprintf(HChar *buf, HChar *fmt, ...)
4437 {
4438 HChar *p;
4439 ULong value;
4440 va_list args;
4441 va_start(args, fmt);
4442
4443 p = buf;
4444 for ( ; *fmt; ++fmt) {
4445 Int c = *fmt;
4446
4447 if (c != '%') {
4448 *p++ = c;
4449 continue;
4450 }
4451
4452 c = *++fmt; /* next char */
4453 switch (c) {
4454 case '%':
4455 *p++ = c; /* %% */
4456 continue;
4457
4458 case 's': /* %s */
4459 p += vex_sprintf(p, "%s", va_arg(args, HChar *));
4460 continue;
4461
4462 case 'M': /* %M = mnemonic */
4463 p += vex_sprintf(p, "%-8s", va_arg(args, HChar *));
4464 continue;
4465
4466 case 'R': /* %R = register */
4467 p += vex_sprintf(p, "%s", s390_hreg_as_string(va_arg(args, HReg)));
4468 continue;
4469
4470 case 'A': /* %A = amode */
4471 p += vex_sprintf(p, "%s",
4472 s390_amode_as_string(va_arg(args, s390_amode *)));
4473 continue;
4474
4475 case 'C': /* %C = condition code */
4476 p += vex_sprintf(p, "%s", s390_cc_as_string(va_arg(args, s390_cc_t)));
4477 continue;
4478
4479 case 'L': { /* %L = argument list in helper call*/
4480 UInt i, num_args;
4481
4482 num_args = va_arg(args, UInt);
4483
4484 for (i = 0; i < num_args; ++i) {
4485 if (i != 0) p += vex_sprintf(p, ", ");
4486 p += vex_sprintf(p, "r%d", s390_gprno_from_arg_index(i));
4487 }
4488 continue;
4489 }
4490
4491 case 'O': { /* %O = RMI operand */
4492 s390_opnd_RMI *op = va_arg(args, s390_opnd_RMI *);
4493
4494 switch (op->tag) {
4495 case S390_OPND_REG:
4496 p += vex_sprintf(p, "%s", s390_hreg_as_string(op->variant.reg));
4497 continue;
4498
4499 case S390_OPND_AMODE:
4500 p += vex_sprintf(p, "%s", s390_amode_as_string(op->variant.am));
4501 continue;
4502
4503 case S390_OPND_IMMEDIATE:
4504 value = op->variant.imm;
4505 goto print_value;
4506
4507 default:
4508 goto fail;
4509 }
4510 }
4511
4512 case 'I': /* %I = immediate value */
4513 value = va_arg(args, ULong);
4514 goto print_value;
4515
4516 print_value:
4517 if ((Long)value < 0)
4518 p += vex_sprintf(p, "%lld", (Long)value);
4519 else if (value < 100)
4520 p += vex_sprintf(p, "%llu", value);
4521 else
4522 p += vex_sprintf(p, "0x%llx", value);
4523 continue;
4524
4525 default:
4526 goto fail;
4527 }
4528 }
4529 *p = '\0';
4530 va_end(args);
4531
4532 return;
4533
4534 fail: vpanic("s390_printf");
4535 }
4536
4537
4538 /* Decompile the given insn into a static buffer and return it */
4539 const HChar *
s390_insn_as_string(const s390_insn * insn)4540 s390_insn_as_string(const s390_insn *insn)
4541 {
4542 static HChar buf[300];
4543 const HChar *op;
4544 HChar *p;
4545
4546 buf[0] = '\0';
4547
4548 switch (insn->tag) {
4549 case S390_INSN_LOAD:
4550 s390_sprintf(buf, "%M %R,%A", "v-load", insn->variant.load.dst,
4551 insn->variant.load.src);
4552 break;
4553
4554 case S390_INSN_STORE:
4555 s390_sprintf(buf, "%M %R,%A", "v-store", insn->variant.store.src,
4556 insn->variant.store.dst);
4557 break;
4558
4559 case S390_INSN_MOVE:
4560 s390_sprintf(buf, "%M %R,%R", "v-move", insn->variant.move.dst,
4561 insn->variant.move.src);
4562 break;
4563
4564 case S390_INSN_COND_MOVE:
4565 s390_sprintf(buf, "%M if (%C) %R,%O", "v-move",
4566 insn->variant.cond_move.cond, insn->variant.cond_move.dst,
4567 &insn->variant.cond_move.src);
4568 break;
4569
4570 case S390_INSN_LOAD_IMMEDIATE:
4571 s390_sprintf(buf, "%M %R,%I", "v-loadi", insn->variant.load_immediate.dst,
4572 insn->variant.load_immediate.value);
4573 break;
4574
4575 case S390_INSN_ALU:
4576 switch (insn->variant.alu.tag) {
4577 case S390_ALU_ADD: op = "v-add"; break;
4578 case S390_ALU_SUB: op = "v-sub"; break;
4579 case S390_ALU_MUL: op = "v-mul"; break;
4580 case S390_ALU_AND: op = "v-and"; break;
4581 case S390_ALU_OR: op = "v-or"; break;
4582 case S390_ALU_XOR: op = "v-xor"; break;
4583 case S390_ALU_LSH: op = "v-lsh"; break;
4584 case S390_ALU_RSH: op = "v-rsh"; break;
4585 case S390_ALU_RSHA: op = "v-rsha"; break;
4586 default: goto fail;
4587 }
4588 s390_sprintf(buf, "%M %R,%R,%O", op, insn->variant.alu.dst,
4589 insn->variant.alu.dst /* op1 same as dst */,
4590 &insn->variant.alu.op2);
4591 break;
4592
4593 case S390_INSN_MUL:
4594 if (insn->variant.mul.signed_multiply) {
4595 op = "v-muls";
4596 } else {
4597 op = "v-mulu";
4598 }
4599 s390_sprintf(buf, "%M %R,%O", op, insn->variant.mul.dst_hi,
4600 &insn->variant.mul.op2);
4601 break;
4602
4603 case S390_INSN_DIV:
4604 if (insn->variant.div.signed_divide) {
4605 op = "v-divs";
4606 } else {
4607 op = "v-divu";
4608 }
4609 s390_sprintf(buf, "%M %R,%O", op, insn->variant.div.op1_hi,
4610 &insn->variant.div.op2);
4611 break;
4612
4613 case S390_INSN_DIVS:
4614 s390_sprintf(buf, "%M %R,%O", "v-divsi", insn->variant.divs.op1,
4615 &insn->variant.divs.op2);
4616 break;
4617
4618 case S390_INSN_CLZ:
4619 s390_sprintf(buf, "%M %R,%O", "v-clz", insn->variant.clz.num_bits,
4620 &insn->variant.clz.src);
4621 break;
4622
4623 case S390_INSN_UNOP:
4624 switch (insn->variant.unop.tag) {
4625 case S390_ZERO_EXTEND_8:
4626 case S390_ZERO_EXTEND_16:
4627 case S390_ZERO_EXTEND_32:
4628 op = "v-zerox";
4629 break;
4630
4631 case S390_SIGN_EXTEND_8:
4632 case S390_SIGN_EXTEND_16:
4633 case S390_SIGN_EXTEND_32:
4634 op = "v-signx";
4635 break;
4636
4637 case S390_NEGATE:
4638 op = "v-neg";
4639 break;
4640
4641 default:
4642 goto fail;
4643 }
4644 s390_sprintf(buf, "%M %R,%O", op, insn->variant.unop.dst,
4645 &insn->variant.unop.src);
4646 break;
4647
4648 case S390_INSN_TEST:
4649 s390_sprintf(buf, "%M %O", "v-test", &insn->variant.test.src);
4650 break;
4651
4652 case S390_INSN_CC2BOOL:
4653 s390_sprintf(buf, "%M %R,%C", "v-cc2b", insn->variant.cc2bool.dst,
4654 insn->variant.cc2bool.cond);
4655 break;
4656
4657 case S390_INSN_CAS:
4658 s390_sprintf(buf, "%M %R,%A,%R,%R", "v-cas", insn->variant.cas.op1,
4659 insn->variant.cas.op2, insn->variant.cas.op3,
4660 insn->variant.cas.old_mem);
4661 break;
4662
4663 case S390_INSN_COMPARE:
4664 if (insn->variant.compare.signed_comparison) {
4665 op = "v-cmps";
4666 } else {
4667 op = "v-cmpu";
4668 }
4669 s390_sprintf(buf, "%M %R,%O", op, insn->variant.compare.src1,
4670 &insn->variant.compare.src2);
4671 break;
4672
4673 case S390_INSN_BRANCH:
4674 switch (insn->variant.branch.kind) {
4675 case Ijk_ClientReq: op = "clientreq"; break;
4676 case Ijk_Sys_syscall: op = "syscall"; break;
4677 case Ijk_Yield: op = "yield"; break;
4678 case Ijk_EmWarn: op = "emwarn"; break;
4679 case Ijk_EmFail: op = "emfail"; break;
4680 case Ijk_MapFail: op = "mapfail"; break;
4681 case Ijk_NoDecode: op = "nodecode"; break;
4682 case Ijk_TInval: op = "tinval"; break;
4683 case Ijk_NoRedir: op = "noredir"; break;
4684 case Ijk_SigTRAP: op = "sigtrap"; break;
4685 case Ijk_Boring: op = "goto"; break;
4686 case Ijk_Call: op = "call"; break;
4687 case Ijk_Ret: op = "return"; break;
4688 default:
4689 goto fail;
4690 }
4691 s390_sprintf(buf, "if (%C) %s %O", insn->variant.branch.cond, op,
4692 &insn->variant.branch.dst);
4693 break;
4694
4695 case S390_INSN_HELPER_CALL: {
4696
4697 if (insn->variant.helper_call.cond != S390_CC_ALWAYS) {
4698 s390_sprintf(buf, "%M if (%C) %s{%I}(%L)", "v-call",
4699 insn->variant.helper_call.cond,
4700 insn->variant.helper_call.name,
4701 insn->variant.helper_call.target,
4702 insn->variant.helper_call.num_args);
4703 } else {
4704 s390_sprintf(buf, "%M %s{%I}(%L)", "v-call",
4705 insn->variant.helper_call.name,
4706 insn->variant.helper_call.target,
4707 insn->variant.helper_call.num_args);
4708 }
4709 break;
4710 }
4711
4712 case S390_INSN_BFP_TRIOP:
4713 switch (insn->variant.bfp_triop.tag) {
4714 case S390_BFP_MADD: op = "v-fmadd"; break;
4715 case S390_BFP_MSUB: op = "v-fmsub"; break;
4716 default: goto fail;
4717 }
4718 s390_sprintf(buf, "%M %R,%R,%R,%R", op, insn->variant.bfp_triop.dst,
4719 insn->variant.bfp_triop.dst /* op1 same as dst */,
4720 insn->variant.bfp_triop.op2, insn->variant.bfp_triop.op3);
4721 break;
4722
4723 case S390_INSN_BFP_BINOP:
4724 switch (insn->variant.bfp_binop.tag) {
4725 case S390_BFP_ADD: op = "v-fadd"; break;
4726 case S390_BFP_SUB: op = "v-fsub"; break;
4727 case S390_BFP_MUL: op = "v-fmul"; break;
4728 case S390_BFP_DIV: op = "v-fdiv"; break;
4729 default: goto fail;
4730 }
4731 s390_sprintf(buf, "%M %R,%R,%R", op, insn->variant.bfp_binop.dst,
4732 insn->variant.bfp_binop.dst /* op1 same as dst */,
4733 insn->variant.bfp_binop.op2);
4734 break;
4735
4736 case S390_INSN_BFP_COMPARE:
4737 s390_sprintf(buf, "%M %R,%R,%R", "v-fcmp", insn->variant.bfp_compare.dst,
4738 insn->variant.bfp_compare.op1, insn->variant.bfp_compare.op2);
4739 break;
4740
4741 case S390_INSN_BFP_UNOP:
4742 switch (insn->variant.bfp_unop.tag) {
4743 case S390_BFP_ABS: op = "v-fabs"; break;
4744 case S390_BFP_NABS: op = "v-fnabs"; break;
4745 case S390_BFP_NEG: op = "v-fneg"; break;
4746 case S390_BFP_SQRT: op = "v-fsqrt"; break;
4747 case S390_BFP_I32_TO_F32:
4748 case S390_BFP_I32_TO_F64:
4749 case S390_BFP_I32_TO_F128:
4750 case S390_BFP_I64_TO_F32:
4751 case S390_BFP_I64_TO_F64:
4752 case S390_BFP_I64_TO_F128: op = "v-i2f"; break;
4753 case S390_BFP_F32_TO_I32:
4754 case S390_BFP_F32_TO_I64:
4755 case S390_BFP_F64_TO_I32:
4756 case S390_BFP_F64_TO_I64:
4757 case S390_BFP_F128_TO_I32:
4758 case S390_BFP_F128_TO_I64: op = "v-f2i"; break;
4759 case S390_BFP_F32_TO_F64:
4760 case S390_BFP_F32_TO_F128:
4761 case S390_BFP_F64_TO_F32:
4762 case S390_BFP_F64_TO_F128:
4763 case S390_BFP_F128_TO_F32:
4764 case S390_BFP_F128_TO_F64: op = "v-f2f"; break;
4765 default: goto fail;
4766 }
4767 s390_sprintf(buf, "%M %R,%R", op, insn->variant.bfp_unop.dst,
4768 insn->variant.bfp_unop.op);
4769 break;
4770
4771 case S390_INSN_BFP128_BINOP:
4772 switch (insn->variant.bfp128_binop.tag) {
4773 case S390_BFP_ADD: op = "v-fadd"; break;
4774 case S390_BFP_SUB: op = "v-fsub"; break;
4775 case S390_BFP_MUL: op = "v-fmul"; break;
4776 case S390_BFP_DIV: op = "v-fdiv"; break;
4777 default: goto fail;
4778 }
4779 /* Only write the register that identifies the register pair */
4780 s390_sprintf(buf, "%M %R,%R,%R", op, insn->variant.bfp128_binop.dst_hi,
4781 insn->variant.bfp128_binop.dst_hi /* op1 same as dst */,
4782 insn->variant.bfp128_binop.op2_hi);
4783 break;
4784
4785 case S390_INSN_BFP128_COMPARE:
4786 /* Only write the register that identifies the register pair */
4787 s390_sprintf(buf, "%M %R,%R,%R", "v-fcmp", insn->variant.bfp128_compare.dst,
4788 insn->variant.bfp128_compare.op1_hi,
4789 insn->variant.bfp128_compare.op2_hi);
4790 break;
4791
4792 case S390_INSN_BFP128_UNOP:
4793 case S390_INSN_BFP128_CONVERT_TO:
4794 case S390_INSN_BFP128_CONVERT_FROM:
4795 switch (insn->variant.bfp128_unop.tag) {
4796 case S390_BFP_ABS: op = "v-fabs"; break;
4797 case S390_BFP_NABS: op = "v-fnabs"; break;
4798 case S390_BFP_NEG: op = "v-fneg"; break;
4799 case S390_BFP_SQRT: op = "v-fsqrt"; break;
4800 case S390_BFP_I32_TO_F128:
4801 case S390_BFP_I64_TO_F128: op = "v-i2f"; break;
4802 case S390_BFP_F128_TO_I32:
4803 case S390_BFP_F128_TO_I64: op = "v-f2i"; break;
4804 case S390_BFP_F32_TO_F128:
4805 case S390_BFP_F64_TO_F128:
4806 case S390_BFP_F128_TO_F32:
4807 case S390_BFP_F128_TO_F64: op = "v-f2f"; break;
4808 default: goto fail;
4809 }
4810 /* Only write the register that identifies the register pair */
4811 s390_sprintf(buf, "%M %R,%R", op, insn->variant.bfp128_unop.dst_hi,
4812 insn->variant.bfp128_unop.op_hi);
4813 break;
4814
4815 case S390_INSN_MFENCE:
4816 s390_sprintf(buf, "%M", "v-mfence");
4817 return buf; /* avoid printing "size = ..." which is meaningless */
4818
4819 default: goto fail;
4820 }
4821
4822 /* Write out how many bytes are involved in the operation */
4823
4824 {
4825 UInt len, i;
4826
4827 for (p = buf; *p; ++p)
4828 continue;
4829
4830 len = p - buf;
4831
4832 if (len < 32) {
4833 for (i = len; i < 32; ++i)
4834 p += vex_sprintf(p, " ");
4835 } else {
4836 p += vex_sprintf(p, "\t");
4837 }
4838 }
4839
4840 /* Special cases first */
4841 switch (insn->tag) {
4842 case S390_INSN_UNOP:
4843 switch (insn->variant.unop.tag) {
4844 case S390_SIGN_EXTEND_8:
4845 case S390_ZERO_EXTEND_8: p += vex_sprintf(p, "1 -> "); goto common;
4846 case S390_SIGN_EXTEND_16:
4847 case S390_ZERO_EXTEND_16: p += vex_sprintf(p, "2 -> "); goto common;
4848 case S390_SIGN_EXTEND_32:
4849 case S390_ZERO_EXTEND_32: p += vex_sprintf(p, "4 -> "); goto common;
4850 default:
4851 goto common;
4852 }
4853
4854 case S390_INSN_BFP_UNOP:
4855 switch (insn->variant.bfp_unop.tag) {
4856 case S390_BFP_I32_TO_F32:
4857 case S390_BFP_I32_TO_F64:
4858 case S390_BFP_I32_TO_F128:
4859 case S390_BFP_F32_TO_I32:
4860 case S390_BFP_F32_TO_I64:
4861 case S390_BFP_F32_TO_F64:
4862 case S390_BFP_F32_TO_F128: p += vex_sprintf(p, "4 -> "); goto common;
4863 case S390_BFP_I64_TO_F32:
4864 case S390_BFP_I64_TO_F64:
4865 case S390_BFP_I64_TO_F128:
4866 case S390_BFP_F64_TO_I32:
4867 case S390_BFP_F64_TO_I64:
4868 case S390_BFP_F64_TO_F32:
4869 case S390_BFP_F64_TO_F128: p += vex_sprintf(p, "8 -> "); goto common;
4870 case S390_BFP_F128_TO_I32:
4871 case S390_BFP_F128_TO_I64:
4872 case S390_BFP_F128_TO_F32:
4873 case S390_BFP_F128_TO_F64: p += vex_sprintf(p, "16 -> "); goto common;
4874 default:
4875 goto common;
4876 }
4877
4878 case S390_INSN_BFP128_UNOP:
4879 case S390_INSN_BFP128_CONVERT_TO:
4880 case S390_INSN_BFP128_CONVERT_FROM:
4881 switch (insn->variant.bfp128_unop.tag) {
4882 case S390_BFP_I32_TO_F128:
4883 case S390_BFP_F32_TO_F128: p += vex_sprintf(p, "4 -> "); goto common;
4884 case S390_BFP_I64_TO_F128:
4885 case S390_BFP_F64_TO_F128: p += vex_sprintf(p, "8 -> "); goto common;
4886 case S390_BFP_F128_TO_I32:
4887 case S390_BFP_F128_TO_I64:
4888 case S390_BFP_F128_TO_F32:
4889 case S390_BFP_F128_TO_F64: p += vex_sprintf(p, "16 -> "); goto common;
4890 default:
4891 goto common;
4892 }
4893
4894 default:
4895 goto common;
4896 }
4897
4898 /* Common case */
4899 common:
4900 vex_sprintf(p, "%u bytes", (UInt)insn->size);
4901
4902 return buf;
4903
4904 fail: vpanic("s390_insn_as_string");
4905 }
4906
4907
4908
4909 /* Load NUM bytes from memory into register REG using addressing mode AM. */
4910 static UChar *
s390_emit_load_mem(UChar * p,UInt num,UChar reg,const s390_amode * am)4911 s390_emit_load_mem(UChar *p, UInt num, UChar reg, const s390_amode *am)
4912 {
4913 UInt b = hregNumber(am->b);
4914 UInt x = hregNumber(am->x); /* 0 for B12 and B20 */
4915 UInt d = am->d;
4916
4917 switch (am->tag) {
4918 case S390_AMODE_B12:
4919 case S390_AMODE_BX12:
4920 switch (num) {
4921 case 1: return s390_emit_IC(p, reg, x, b, d);
4922 case 2: return s390_emit_LH(p, reg, x, b, d);
4923 case 4: return s390_emit_L(p, reg, x, b, d);
4924 case 8: return s390_emit_LG(p, reg, x, b, DISP20(d));
4925 default: goto fail;
4926 }
4927 break;
4928
4929 case S390_AMODE_B20:
4930 case S390_AMODE_BX20:
4931 switch (num) {
4932 case 1: return s390_emit_ICY(p, reg, x, b, DISP20(d));
4933 case 2: return s390_emit_LHY(p, reg, x, b, DISP20(d));
4934 case 4: return s390_emit_LY(p, reg, x, b, DISP20(d));
4935 case 8: return s390_emit_LG(p, reg, x, b, DISP20(d));
4936 default: goto fail;
4937 }
4938 break;
4939
4940 default: goto fail;
4941 }
4942
4943 fail:
4944 vpanic("s390_emit_load_mem");
4945 }
4946
4947
4948 /* Load condition code into register REG */
4949 static UChar *
s390_emit_load_cc(UChar * p,UChar reg)4950 s390_emit_load_cc(UChar *p, UChar reg)
4951 {
4952 p = s390_emit_LGHI(p, reg, 0); /* Clear out, cc not affected */
4953 p = s390_emit_IPM(p, reg, reg);
4954 /* Shift 28 bits to the right --> [0,1,2,3] */
4955 return s390_emit_SRL(p, reg, 0, 28); /* REG = cc */
4956 }
4957
4958
4959 /*---------------------------------------------------------------*/
4960 /*--- Code generation ---*/
4961 /*---------------------------------------------------------------*/
4962
4963 /* Do not load more bytes than requested. */
4964 static UChar *
s390_insn_load_emit(UChar * buf,const s390_insn * insn)4965 s390_insn_load_emit(UChar *buf, const s390_insn *insn)
4966 {
4967 UInt r, x, b, d;
4968 const s390_amode *src;
4969
4970 src = insn->variant.load.src;
4971
4972 r = hregNumber(insn->variant.load.dst);
4973
4974 if (hregClass(insn->variant.load.dst) == HRcFlt64) {
4975 b = hregNumber(src->b);
4976 x = hregNumber(src->x); /* 0 for B12 and B20 */
4977 d = src->d;
4978
4979 switch (insn->size) {
4980
4981 case 4:
4982 switch (src->tag) {
4983 case S390_AMODE_B12:
4984 case S390_AMODE_BX12:
4985 return s390_emit_LE(buf, r, x, b, d);
4986
4987 case S390_AMODE_B20:
4988 case S390_AMODE_BX20:
4989 return s390_emit_LEY(buf, r, x, b, DISP20(d));
4990 }
4991 break;
4992
4993 case 8:
4994 switch (src->tag) {
4995 case S390_AMODE_B12:
4996 case S390_AMODE_BX12:
4997 return s390_emit_LD(buf, r, x, b, d);
4998
4999 case S390_AMODE_B20:
5000 case S390_AMODE_BX20:
5001 return s390_emit_LDY(buf, r, x, b, DISP20(d));
5002 }
5003 break;
5004 }
5005 vpanic("s390_insn_load_emit");
5006 }
5007
5008 /* Integer stuff */
5009 return s390_emit_load_mem(buf, insn->size, r, src);
5010 }
5011
5012
5013 static UChar *
s390_insn_store_emit(UChar * buf,const s390_insn * insn)5014 s390_insn_store_emit(UChar *buf, const s390_insn *insn)
5015 {
5016 UInt r, x, b, d;
5017 const s390_amode *dst;
5018
5019 dst = insn->variant.store.dst;
5020
5021 r = hregNumber(insn->variant.store.src);
5022 b = hregNumber(dst->b);
5023 x = hregNumber(dst->x); /* 0 for B12 and B20 */
5024 d = dst->d;
5025
5026 if (hregClass(insn->variant.store.src) == HRcFlt64) {
5027 switch (insn->size) {
5028
5029 case 4:
5030 switch (dst->tag) {
5031 case S390_AMODE_B12:
5032 case S390_AMODE_BX12:
5033 return s390_emit_STE(buf, r, x, b, d);
5034
5035 case S390_AMODE_B20:
5036 case S390_AMODE_BX20:
5037 return s390_emit_STEY(buf, r, x, b, DISP20(d));
5038 }
5039 break;
5040
5041 case 8:
5042 switch (dst->tag) {
5043 case S390_AMODE_B12:
5044 case S390_AMODE_BX12:
5045 return s390_emit_STD(buf, r, x, b, d);
5046
5047 case S390_AMODE_B20:
5048 case S390_AMODE_BX20:
5049 return s390_emit_STDY(buf, r, x, b, DISP20(d));
5050 }
5051 break;
5052 }
5053 vpanic("s390_insn_store_emit");
5054 }
5055
5056 /* Integer stuff */
5057 switch (insn->size) {
5058 case 1:
5059 switch (dst->tag) {
5060 case S390_AMODE_B12:
5061 case S390_AMODE_BX12:
5062 return s390_emit_STC(buf, r, x, b, d);
5063
5064 case S390_AMODE_B20:
5065 case S390_AMODE_BX20:
5066 return s390_emit_STCY(buf, r, x, b, DISP20(d));
5067 }
5068 break;
5069
5070 case 2:
5071 switch (dst->tag) {
5072 case S390_AMODE_B12:
5073 case S390_AMODE_BX12:
5074 return s390_emit_STH(buf, r, x, b, d);
5075
5076 case S390_AMODE_B20:
5077 case S390_AMODE_BX20:
5078 return s390_emit_STHY(buf, r, x, b, DISP20(d));
5079 }
5080 break;
5081
5082 case 4:
5083 switch (dst->tag) {
5084 case S390_AMODE_B12:
5085 case S390_AMODE_BX12:
5086 return s390_emit_ST(buf, r, x, b, d);
5087
5088 case S390_AMODE_B20:
5089 case S390_AMODE_BX20:
5090 return s390_emit_STY(buf, r, x, b, DISP20(d));
5091 }
5092 break;
5093
5094 case 8:
5095 return s390_emit_STG(buf, r, x, b, DISP20(d));
5096
5097 default:
5098 break;
5099 }
5100
5101 vpanic("s390_insn_store_emit");
5102 }
5103
5104
5105 static UChar *
s390_insn_move_emit(UChar * buf,const s390_insn * insn)5106 s390_insn_move_emit(UChar *buf, const s390_insn *insn)
5107 {
5108 UInt dst, src;
5109 HRegClass dst_class, src_class;
5110
5111 dst = hregNumber(insn->variant.move.dst);
5112 src = hregNumber(insn->variant.move.src);
5113
5114 dst_class = hregClass(insn->variant.move.dst);
5115 src_class = hregClass(insn->variant.move.src);
5116
5117 if (dst_class == src_class) {
5118 if (dst_class == HRcInt64)
5119 return s390_emit_LGR(buf, dst, src);
5120 if (dst_class == HRcFlt64)
5121 return s390_emit_LDR(buf, dst, src);
5122 } else {
5123 if (dst_class == HRcFlt64 && src_class == HRcInt64)
5124 return s390_emit_LDGRw(buf, dst, src);
5125 if (dst_class == HRcInt64 && src_class == HRcFlt64)
5126 return s390_emit_LGDRw(buf, dst, src);
5127 /* A move between floating point registers and general purpose
5128 registers of different size should never occur and indicates
5129 an error elsewhere. */
5130 }
5131
5132 vpanic("s390_insn_move_emit");
5133 }
5134
5135
5136 static UChar *
s390_insn_load_immediate_emit(UChar * buf,const s390_insn * insn)5137 s390_insn_load_immediate_emit(UChar *buf, const s390_insn *insn)
5138 {
5139 UInt r;
5140 ULong value = insn->variant.load_immediate.value;
5141
5142 r = hregNumber(insn->variant.load_immediate.dst);
5143
5144 if (hregClass(insn->variant.load_immediate.dst) == HRcFlt64) {
5145 vassert(value == 0);
5146 switch (insn->size) {
5147 case 4: return s390_emit_LZER(buf, r, value);
5148 case 8: return s390_emit_LZDR(buf, r, value);
5149 }
5150 vpanic("s390_insn_load_immediate_emit");
5151 }
5152
5153 switch (insn->size) {
5154 case 1:
5155 case 2:
5156 /* Load the immediate values as a 4 byte value. That does not hurt as
5157 those extra bytes will not be looked at. Fall through .... */
5158 case 4:
5159 return s390_emit_load_32imm(buf, r, value);
5160
5161 case 8:
5162 return s390_emit_load_64imm(buf, r, value);
5163 }
5164
5165 vpanic("s390_insn_load_immediate_emit");
5166 }
5167
5168
5169 /* There is no easy way to do ALU operations on 1-byte or 2-byte operands.
5170 So we simply perform a 4-byte operation. Doing so uses possibly undefined
5171 bits and produces an undefined result in those extra bit positions. But
5172 upstream does not look at those positions, so this is OK. */
5173 static UChar *
s390_insn_alu_emit(UChar * buf,const s390_insn * insn)5174 s390_insn_alu_emit(UChar *buf, const s390_insn *insn)
5175 {
5176 s390_opnd_RMI op2;
5177 UInt dst;
5178
5179 dst = hregNumber(insn->variant.alu.dst);
5180 op2 = insn->variant.alu.op2;
5181
5182 /* Second operand is in a register */
5183 if (op2.tag == S390_OPND_REG) {
5184 UInt r2 = hregNumber(op2.variant.reg);
5185
5186 switch (insn->size) {
5187 case 1:
5188 case 2:
5189 case 4:
5190 switch (insn->variant.alu.tag) {
5191 case S390_ALU_ADD: return s390_emit_AR(buf, dst, r2);
5192 case S390_ALU_SUB: return s390_emit_SR(buf, dst, r2);
5193 case S390_ALU_MUL: return s390_emit_MSR(buf, dst, r2);
5194 case S390_ALU_AND: return s390_emit_NR(buf, dst, r2);
5195 case S390_ALU_OR: return s390_emit_OR(buf, dst, r2);
5196 case S390_ALU_XOR: return s390_emit_XR(buf, dst, r2);
5197 case S390_ALU_LSH: return s390_emit_SLL(buf, dst, r2, 0);
5198 case S390_ALU_RSH: return s390_emit_SRL(buf, dst, r2, 0);
5199 case S390_ALU_RSHA: return s390_emit_SRA(buf, dst, r2, 0);
5200 }
5201 goto fail;
5202
5203 case 8:
5204 switch (insn->variant.alu.tag) {
5205 case S390_ALU_ADD: return s390_emit_AGR(buf, dst, r2);
5206 case S390_ALU_SUB: return s390_emit_SGR(buf, dst, r2);
5207 case S390_ALU_MUL: return s390_emit_MSGR(buf, dst, r2);
5208 case S390_ALU_AND: return s390_emit_NGR(buf, dst, r2);
5209 case S390_ALU_OR: return s390_emit_OGR(buf, dst, r2);
5210 case S390_ALU_XOR: return s390_emit_XGR(buf, dst, r2);
5211 case S390_ALU_LSH: return s390_emit_SLLG(buf, dst, dst, r2, DISP20(0));
5212 case S390_ALU_RSH: return s390_emit_SRLG(buf, dst, dst, r2, DISP20(0));
5213 case S390_ALU_RSHA: return s390_emit_SRAG(buf, dst, dst, r2, DISP20(0));
5214 }
5215 goto fail;
5216 }
5217 goto fail;
5218 }
5219
5220 /* 2nd operand is in memory */
5221 if (op2.tag == S390_OPND_AMODE) {
5222 UInt b, x, d;
5223 const s390_amode *src = op2.variant.am;
5224
5225 b = hregNumber(src->b);
5226 x = hregNumber(src->x); /* 0 for B12 and B20 */
5227 d = src->d;
5228
5229 /* Shift operands are special here as there are no opcodes that
5230 allow a memory operand. So we first load the 2nd operand into
5231 some register. R0 is used to save restore the contents of the
5232 chosen register.. */
5233
5234 if (insn->variant.alu.tag == S390_ALU_LSH ||
5235 insn->variant.alu.tag == S390_ALU_RSH ||
5236 insn->variant.alu.tag == S390_ALU_RSHA) {
5237 UInt b2;
5238
5239 /* Choose a register (other than DST or R0) into which to stick the
5240 shift amount. The following works because r15 is reserved and
5241 thusly dst != 15. */
5242 vassert(dst != 15); /* extra paranoia */
5243 b2 = (dst + 1) % 16;
5244
5245 buf = s390_emit_LGR(buf, R0, b2); /* save */
5246
5247 /* Loading SRC to B2 does not modify R0. */
5248 buf = s390_emit_load_mem(buf, insn->size, b2, src);
5249
5250 if (insn->size == 8) {
5251 switch (insn->variant.alu.tag) {
5252 case S390_ALU_LSH:
5253 buf = s390_emit_SLLG(buf, dst, dst, b2, DISP20(0));
5254 break;
5255 case S390_ALU_RSH:
5256 buf = s390_emit_SRLG(buf, dst, dst, b2, DISP20(0));
5257 break;
5258 case S390_ALU_RSHA:
5259 buf = s390_emit_SRAG(buf, dst, dst, b2, DISP20(0));
5260 break;
5261 default: /* unreachable */
5262 goto fail;
5263 }
5264 } else {
5265 switch (insn->variant.alu.tag) {
5266 case S390_ALU_LSH:
5267 buf = s390_emit_SLL(buf, dst, b2, 0);
5268 break;
5269 case S390_ALU_RSH:
5270 buf = s390_emit_SRL(buf, dst, b2, 0);
5271 break;
5272 case S390_ALU_RSHA:
5273 buf = s390_emit_SRA(buf, dst, b2, 0);
5274 break;
5275 default: /* unreachable */
5276 goto fail;
5277 }
5278 }
5279 return s390_emit_LGR(buf, b2, R0); /* restore */
5280 }
5281
5282 switch (insn->size) {
5283 case 1:
5284 /* Move the byte from memory into scratch register r0 */
5285 buf = s390_emit_load_mem(buf, 1, R0, src);
5286
5287 switch (insn->variant.alu.tag) {
5288 case S390_ALU_ADD: return s390_emit_AR(buf, dst, R0);
5289 case S390_ALU_SUB: return s390_emit_SR(buf, dst, R0);
5290 case S390_ALU_MUL: return s390_emit_MSR(buf, dst, R0);
5291 case S390_ALU_AND: return s390_emit_NR(buf, dst, R0);
5292 case S390_ALU_OR: return s390_emit_OR(buf, dst, R0);
5293 case S390_ALU_XOR: return s390_emit_XR(buf, dst, R0);
5294 case S390_ALU_LSH:
5295 case S390_ALU_RSH:
5296 case S390_ALU_RSHA: ; /* avoid GCC warning */
5297 }
5298 goto fail;
5299
5300 case 2:
5301 switch (src->tag) {
5302 case S390_AMODE_B12:
5303 case S390_AMODE_BX12:
5304 switch (insn->variant.alu.tag) {
5305 case S390_ALU_ADD:
5306 return s390_emit_AH(buf, dst, x, b, d);
5307
5308 case S390_ALU_SUB:
5309 return s390_emit_SH(buf, dst, x, b, d);
5310
5311 case S390_ALU_MUL:
5312 return s390_emit_MH(buf, dst, x, b, d);
5313
5314 /* For bitwise operations: Move two bytes from memory into scratch
5315 register r0; then perform operation */
5316 case S390_ALU_AND:
5317 buf = s390_emit_LH(buf, R0, x, b, d);
5318 return s390_emit_NR(buf, dst, R0);
5319
5320 case S390_ALU_OR:
5321 buf = s390_emit_LH(buf, R0, x, b, d);
5322 return s390_emit_OR(buf, dst, R0);
5323
5324 case S390_ALU_XOR:
5325 buf = s390_emit_LH(buf, R0, x, b, d);
5326 return s390_emit_XR(buf, dst, R0);
5327
5328 case S390_ALU_LSH:
5329 case S390_ALU_RSH:
5330 case S390_ALU_RSHA: ; /* avoid GCC warning */
5331 }
5332 goto fail;
5333
5334 case S390_AMODE_B20:
5335 case S390_AMODE_BX20:
5336 switch (insn->variant.alu.tag) {
5337 case S390_ALU_ADD:
5338 return s390_emit_AHY(buf, dst, x, b, DISP20(d));
5339
5340 case S390_ALU_SUB:
5341 return s390_emit_SHY(buf, dst, x, b, DISP20(d));
5342
5343 case S390_ALU_MUL:
5344 return s390_emit_MHYw(buf, dst, x, b, DISP20(d));
5345
5346 /* For bitwise operations: Move two bytes from memory into scratch
5347 register r0; then perform operation */
5348 case S390_ALU_AND:
5349 buf = s390_emit_LHY(buf, R0, x, b, DISP20(d));
5350 return s390_emit_NR(buf, dst, R0);
5351
5352 case S390_ALU_OR:
5353 buf = s390_emit_LHY(buf, R0, x, b, DISP20(d));
5354 return s390_emit_OR(buf, dst, R0);
5355
5356 case S390_ALU_XOR:
5357 buf = s390_emit_LHY(buf, R0, x, b, DISP20(d));
5358 return s390_emit_XR(buf, dst, R0);
5359
5360 case S390_ALU_LSH:
5361 case S390_ALU_RSH:
5362 case S390_ALU_RSHA: ; /* avoid GCC warning */
5363 }
5364 goto fail;
5365 }
5366 goto fail;
5367
5368 case 4:
5369 switch (src->tag) {
5370 case S390_AMODE_B12:
5371 case S390_AMODE_BX12:
5372 switch (insn->variant.alu.tag) {
5373 case S390_ALU_ADD: return s390_emit_A(buf, dst, x, b, d);
5374 case S390_ALU_SUB: return s390_emit_S(buf, dst, x, b, d);
5375 case S390_ALU_MUL: return s390_emit_MS(buf, dst, x, b, d);
5376 case S390_ALU_AND: return s390_emit_N(buf, dst, x, b, d);
5377 case S390_ALU_OR: return s390_emit_O(buf, dst, x, b, d);
5378 case S390_ALU_XOR: return s390_emit_X(buf, dst, x, b, d);
5379 case S390_ALU_LSH:
5380 case S390_ALU_RSH:
5381 case S390_ALU_RSHA: ; /* avoid GCC warning */
5382 }
5383 goto fail;
5384
5385 case S390_AMODE_B20:
5386 case S390_AMODE_BX20:
5387 switch (insn->variant.alu.tag) {
5388 case S390_ALU_ADD: return s390_emit_AY(buf, dst, x, b, DISP20(d));
5389 case S390_ALU_SUB: return s390_emit_SY(buf, dst, x, b, DISP20(d));
5390 case S390_ALU_MUL: return s390_emit_MSY(buf, dst, x, b, DISP20(d));
5391 case S390_ALU_AND: return s390_emit_NY(buf, dst, x, b, DISP20(d));
5392 case S390_ALU_OR: return s390_emit_OY(buf, dst, x, b, DISP20(d));
5393 case S390_ALU_XOR: return s390_emit_XY(buf, dst, x, b, DISP20(d));
5394 case S390_ALU_LSH:
5395 case S390_ALU_RSH:
5396 case S390_ALU_RSHA: ; /* avoid GCC warning */
5397 }
5398 goto fail;
5399 }
5400 goto fail;
5401
5402 case 8:
5403 switch (insn->variant.alu.tag) {
5404 case S390_ALU_ADD: return s390_emit_AG(buf, dst, x, b, DISP20(d));
5405 case S390_ALU_SUB: return s390_emit_SG(buf, dst, x, b, DISP20(d));
5406 case S390_ALU_MUL: return s390_emit_MSG(buf, dst, x, b, DISP20(d));
5407 case S390_ALU_AND: return s390_emit_NG(buf, dst, x, b, DISP20(d));
5408 case S390_ALU_OR: return s390_emit_OG(buf, dst, x, b, DISP20(d));
5409 case S390_ALU_XOR: return s390_emit_XG(buf, dst, x, b, DISP20(d));
5410 case S390_ALU_LSH:
5411 case S390_ALU_RSH:
5412 case S390_ALU_RSHA: ; /* avoid GCC warning */
5413 }
5414 goto fail;
5415 }
5416 goto fail;
5417 }
5418
5419 /* 2nd operand is an immediate value */
5420 if (op2.tag == S390_OPND_IMMEDIATE) {
5421 ULong value;
5422
5423 /* No masking of the value is required as it is not sign extended */
5424 value = op2.variant.imm;
5425
5426 switch (insn->size) {
5427 case 1:
5428 case 2:
5429 /* There is no 1-byte opcode. Do the computation in
5430 2 bytes. The extra byte will be ignored. */
5431 switch (insn->variant.alu.tag) {
5432 case S390_ALU_ADD:
5433 return s390_emit_AHI(buf, dst, value);
5434
5435 case S390_ALU_SUB:
5436 return s390_emit_SLFIw(buf, dst, value);
5437
5438 case S390_ALU_MUL:
5439 return s390_emit_MHI(buf, dst, value);
5440
5441 case S390_ALU_AND: return s390_emit_NILL(buf, dst, value);
5442 case S390_ALU_OR: return s390_emit_OILL(buf, dst, value);
5443 case S390_ALU_XOR:
5444 /* There is no XILL instruction. Load the immediate value into
5445 R0 and combine with the destination register. */
5446 buf = s390_emit_LHI(buf, R0, value);
5447 return s390_emit_XR(buf, dst, R0);
5448
5449 case S390_ALU_LSH:
5450 return s390_emit_SLL(buf, dst, 0, value);
5451
5452 case S390_ALU_RSH:
5453 return s390_emit_SRL(buf, dst, 0, value);
5454
5455 case S390_ALU_RSHA:
5456 return s390_emit_SRA(buf, dst, 0, value);
5457 }
5458 goto fail;
5459
5460 case 4:
5461 switch (insn->variant.alu.tag) {
5462 case S390_ALU_ADD:
5463 if (uint_fits_signed_16bit(value)) {
5464 return s390_emit_AHI(buf, dst, value);
5465 }
5466 return s390_emit_AFIw(buf, dst, value);
5467
5468 case S390_ALU_SUB: return s390_emit_SLFIw(buf, dst, value);
5469 case S390_ALU_MUL: return s390_emit_MSFIw(buf, dst, value);
5470 case S390_ALU_AND: return s390_emit_NILFw(buf, dst, value);
5471 case S390_ALU_OR: return s390_emit_OILFw(buf, dst, value);
5472 case S390_ALU_XOR: return s390_emit_XILFw(buf, dst, value);
5473 case S390_ALU_LSH: return s390_emit_SLL(buf, dst, 0, value);
5474 case S390_ALU_RSH: return s390_emit_SRL(buf, dst, 0, value);
5475 case S390_ALU_RSHA: return s390_emit_SRA(buf, dst, 0, value);
5476 }
5477 goto fail;
5478
5479 case 8:
5480 switch (insn->variant.alu.tag) {
5481 case S390_ALU_ADD:
5482 if (ulong_fits_signed_16bit(value)) {
5483 return s390_emit_AGHI(buf, dst, value);
5484 }
5485 if (ulong_fits_signed_32bit(value) && s390_host_has_eimm) {
5486 return s390_emit_AGFI(buf, dst, value);
5487 }
5488 /* Load constant into R0 then add */
5489 buf = s390_emit_load_64imm(buf, R0, value);
5490 return s390_emit_AGR(buf, dst, R0);
5491
5492 case S390_ALU_SUB:
5493 if (ulong_fits_unsigned_32bit(value)) {
5494 return s390_emit_SLGFIw(buf, dst, value);
5495 }
5496 /* Load value into R0; then subtract from destination reg */
5497 buf = s390_emit_load_64imm(buf, R0, value);
5498 return s390_emit_SGR(buf, dst, R0);
5499
5500 case S390_ALU_MUL:
5501 if (ulong_fits_signed_32bit(value) && s390_host_has_gie) {
5502 return s390_emit_MSGFI(buf, dst, value);
5503 }
5504 /* Load constant into R0 then add */
5505 buf = s390_emit_load_64imm(buf, R0, value);
5506 return s390_emit_MSGR(buf, dst, R0);
5507
5508 /* Do it in two steps: upper half [0:31] and lower half [32:63] */
5509 case S390_ALU_AND:
5510 if (s390_host_has_eimm) {
5511 buf = s390_emit_NIHF(buf, dst, value >> 32);
5512 return s390_emit_NILF(buf, dst, value & 0xFFFFFFFF);
5513 }
5514 /* Load value into R0; then combine with destination reg */
5515 buf = s390_emit_load_64imm(buf, R0, value);
5516 return s390_emit_NGR(buf, dst, R0);
5517
5518 case S390_ALU_OR:
5519 if (s390_host_has_eimm) {
5520 buf = s390_emit_OIHF(buf, dst, value >> 32);
5521 return s390_emit_OILF(buf, dst, value & 0xFFFFFFFF);
5522 }
5523 /* Load value into R0; then combine with destination reg */
5524 buf = s390_emit_load_64imm(buf, R0, value);
5525 return s390_emit_OGR(buf, dst, R0);
5526
5527 case S390_ALU_XOR:
5528 if (s390_host_has_eimm) {
5529 buf = s390_emit_XIHF(buf, dst, value >> 32);
5530 return s390_emit_XILF(buf, dst, value & 0xFFFFFFFF);
5531 }
5532 /* Load value into R0; then combine with destination reg */
5533 buf = s390_emit_load_64imm(buf, R0, value);
5534 return s390_emit_XGR(buf, dst, R0);
5535
5536 /* No special considerations for long displacement here. Only the six
5537 least significant bits of VALUE will be taken; all other bits are
5538 ignored. So the DH2 bits are irrelevant and do not influence the
5539 shift operation, independent of whether long-displacement is available
5540 or not. */
5541 case S390_ALU_LSH: return s390_emit_SLLG(buf, dst, dst, 0, DISP20(value));
5542 case S390_ALU_RSH: return s390_emit_SRLG(buf, dst, dst, 0, DISP20(value));
5543 case S390_ALU_RSHA: return s390_emit_SRAG(buf, dst, dst, 0, DISP20(value));
5544 }
5545 goto fail;
5546 }
5547 goto fail;
5548 }
5549
5550 fail:
5551 vpanic("s390_insn_alu_emit");
5552 }
5553
5554
5555 static UChar *
s390_widen_emit(UChar * buf,const s390_insn * insn,UInt from_size,Bool sign_extend)5556 s390_widen_emit(UChar *buf, const s390_insn *insn, UInt from_size,
5557 Bool sign_extend)
5558 {
5559 s390_opnd_RMI opnd = insn->variant.unop.src;
5560
5561 switch (opnd.tag) {
5562 case S390_OPND_REG: {
5563 UChar r1 = hregNumber(insn->variant.unop.dst);
5564 UChar r2 = hregNumber(opnd.variant.reg);
5565
5566 switch (from_size) {
5567 case 1:
5568 /* Widening to a half-word is implemented like widening to a word
5569 because the upper half-word will not be looked at. */
5570 if (insn->size == 4 || insn->size == 2) { /* 8 --> 32 8 --> 16 */
5571 if (sign_extend)
5572 return s390_emit_LBRw(buf, r1, r2);
5573 else
5574 return s390_emit_LLCRw(buf, r1, r2);
5575 }
5576 if (insn->size == 8) { /* 8 --> 64 */
5577 if (sign_extend)
5578 return s390_emit_LGBRw(buf, r1, r2);
5579 else
5580 return s390_emit_LLGCRw(buf, r1, r2);
5581 }
5582 goto fail;
5583
5584 case 2:
5585 if (insn->size == 4) { /* 16 --> 32 */
5586 if (sign_extend)
5587 return s390_emit_LHRw(buf, r1, r2);
5588 else
5589 return s390_emit_LLHRw(buf, r1, r2);
5590 }
5591 if (insn->size == 8) { /* 16 --> 64 */
5592 if (sign_extend)
5593 return s390_emit_LGHRw(buf, r1, r2);
5594 else
5595 return s390_emit_LLGHRw(buf, r1, r2);
5596 }
5597 goto fail;
5598
5599 case 4:
5600 if (insn->size == 8) { /* 32 --> 64 */
5601 if (sign_extend)
5602 return s390_emit_LGFR(buf, r1, r2);
5603 else
5604 return s390_emit_LLGFR(buf, r1, r2);
5605 }
5606 goto fail;
5607
5608 default: /* unexpected "from" size */
5609 goto fail;
5610 }
5611 }
5612
5613 case S390_OPND_AMODE: {
5614 UChar r1 = hregNumber(insn->variant.unop.dst);
5615 const s390_amode *src = opnd.variant.am;
5616 UChar b = hregNumber(src->b);
5617 UChar x = hregNumber(src->x);
5618 Int d = src->d;
5619
5620 switch (from_size) {
5621 case 1:
5622 if (insn->size == 4 || insn->size == 2) {
5623 if (sign_extend)
5624 return s390_emit_LBw(buf, r1, x, b, DISP20(d));
5625 else
5626 return s390_emit_LLCw(buf, r1, x, b, DISP20(d));
5627 }
5628 if (insn->size == 8) {
5629 if (sign_extend)
5630 return s390_emit_LGBw(buf, r1, x, b, DISP20(d));
5631 else
5632 return s390_emit_LLGC(buf, r1, x, b, DISP20(d));
5633 }
5634 goto fail;
5635
5636 case 2:
5637 if (insn->size == 4) { /* 16 --> 32 */
5638 if (sign_extend == 0)
5639 return s390_emit_LLHw(buf, r1, x, b, DISP20(d));
5640
5641 switch (src->tag) {
5642 case S390_AMODE_B12:
5643 case S390_AMODE_BX12:
5644 return s390_emit_LH(buf, r1, x, b, d);
5645
5646 case S390_AMODE_B20:
5647 case S390_AMODE_BX20:
5648 return s390_emit_LHY(buf, r1, x, b, DISP20(d));
5649 }
5650 goto fail;
5651 }
5652 if (insn->size == 8) { /* 16 --> 64 */
5653 if (sign_extend)
5654 return s390_emit_LGH(buf, r1, x, b, DISP20(d));
5655 else
5656 return s390_emit_LLGH(buf, r1, x, b, DISP20(d));
5657 }
5658 goto fail;
5659
5660 case 4:
5661 if (insn->size == 8) { /* 32 --> 64 */
5662 if (sign_extend)
5663 return s390_emit_LGF(buf, r1, x, b, DISP20(d));
5664 else
5665 return s390_emit_LLGF(buf, r1, x, b, DISP20(d));
5666 }
5667 goto fail;
5668
5669 default: /* unexpected "from" size */
5670 goto fail;
5671 }
5672 }
5673
5674 case S390_OPND_IMMEDIATE: {
5675 UChar r1 = hregNumber(insn->variant.unop.dst);
5676 ULong value = opnd.variant.imm;
5677
5678 switch (from_size) {
5679 case 1:
5680 if (insn->size == 4 || insn->size == 2) { /* 8 --> 32 8 --> 16 */
5681 if (sign_extend) {
5682 /* host can do the sign extension to 16-bit; LHI does the rest */
5683 return s390_emit_LHI(buf, r1, (Short)(Char)(UChar)value);
5684 } else {
5685 return s390_emit_LHI(buf, r1, value);
5686 }
5687 }
5688 if (insn->size == 8) { /* 8 --> 64 */
5689 if (sign_extend) {
5690 /* host can do the sign extension to 16-bit; LGHI does the rest */
5691 return s390_emit_LGHI(buf, r1, (Short)(Char)(UChar)value);
5692 } else {
5693 return s390_emit_LGHI(buf, r1, value);
5694 }
5695 }
5696 goto fail;
5697
5698 case 2:
5699 if (insn->size == 4) { /* 16 --> 32 */
5700 return s390_emit_LHI(buf, r1, value);
5701 }
5702 if (insn->size == 8) { /* 16 --> 64 */
5703 if (sign_extend)
5704 return s390_emit_LGHI(buf, r1, value);
5705 else
5706 return s390_emit_LLILL(buf, r1, value);
5707 }
5708 goto fail;
5709
5710 case 4:
5711 if (insn->size == 8) { /* 32 --> 64 */
5712 if (sign_extend)
5713 return s390_emit_LGFIw(buf, r1, value);
5714 else
5715 return s390_emit_LLILFw(buf, r1, value);
5716 }
5717 goto fail;
5718
5719 default: /* unexpected "from" size */
5720 goto fail;
5721 }
5722 }
5723 }
5724
5725 fail:
5726 vpanic("s390_widen_emit");
5727 }
5728
5729
5730 static UChar *
s390_negate_emit(UChar * buf,const s390_insn * insn)5731 s390_negate_emit(UChar *buf, const s390_insn *insn)
5732 {
5733 s390_opnd_RMI opnd;
5734
5735 opnd = insn->variant.unop.src;
5736
5737 switch (opnd.tag) {
5738 case S390_OPND_REG: {
5739 UChar r1 = hregNumber(insn->variant.unop.dst);
5740 UChar r2 = hregNumber(opnd.variant.reg);
5741
5742 switch (insn->size) {
5743 case 1:
5744 case 2:
5745 case 4:
5746 return s390_emit_LCR(buf, r1, r2);
5747
5748 case 8:
5749 return s390_emit_LCGR(buf, r1, r2);
5750
5751 default:
5752 goto fail;
5753 }
5754 }
5755
5756 case S390_OPND_AMODE: {
5757 UChar r1 = hregNumber(insn->variant.unop.dst);
5758
5759 /* Load bytes into scratch register R0, then negate */
5760 buf = s390_emit_load_mem(buf, insn->size, R0, opnd.variant.am);
5761
5762 switch (insn->size) {
5763 case 1:
5764 case 2:
5765 case 4:
5766 return s390_emit_LCR(buf, r1, R0);
5767
5768 case 8:
5769 return s390_emit_LCGR(buf, r1, R0);
5770
5771 default:
5772 goto fail;
5773 }
5774 }
5775
5776 case S390_OPND_IMMEDIATE: {
5777 UChar r1 = hregNumber(insn->variant.unop.dst);
5778 ULong value = opnd.variant.imm;
5779
5780 value = ~value + 1; /* two's complement */
5781
5782 switch (insn->size) {
5783 case 1:
5784 case 2:
5785 /* Load the immediate values as a 4 byte value. That does not hurt as
5786 those extra bytes will not be looked at. Fall through .... */
5787 case 4:
5788 return s390_emit_load_32imm(buf, r1, value);
5789
5790 case 8:
5791 return s390_emit_load_64imm(buf, r1, value);
5792
5793 default:
5794 goto fail;
5795 }
5796 }
5797 }
5798
5799 fail:
5800 vpanic("s390_negate_emit");
5801 }
5802
5803
5804 static UChar *
s390_insn_unop_emit(UChar * buf,const s390_insn * insn)5805 s390_insn_unop_emit(UChar *buf, const s390_insn *insn)
5806 {
5807 switch (insn->variant.unop.tag) {
5808 case S390_ZERO_EXTEND_8: return s390_widen_emit(buf, insn, 1, 0);
5809 case S390_ZERO_EXTEND_16: return s390_widen_emit(buf, insn, 2, 0);
5810 case S390_ZERO_EXTEND_32: return s390_widen_emit(buf, insn, 4, 0);
5811
5812 case S390_SIGN_EXTEND_8: return s390_widen_emit(buf, insn, 1, 1);
5813 case S390_SIGN_EXTEND_16: return s390_widen_emit(buf, insn, 2, 1);
5814 case S390_SIGN_EXTEND_32: return s390_widen_emit(buf, insn, 4, 1);
5815
5816 case S390_NEGATE: return s390_negate_emit(buf, insn);
5817 }
5818
5819 vpanic("s390_insn_unop_emit");
5820 }
5821
5822
5823 /* Only 4-byte and 8-byte operands are handled. 1-byte and 2-byte
5824 comparisons will have been converted to 4-byte comparisons in
5825 s390_isel_cc and should not occur here. */
5826 static UChar *
s390_insn_test_emit(UChar * buf,const s390_insn * insn)5827 s390_insn_test_emit(UChar *buf, const s390_insn *insn)
5828 {
5829 s390_opnd_RMI opnd;
5830
5831 opnd = insn->variant.test.src;
5832
5833 switch (opnd.tag) {
5834 case S390_OPND_REG: {
5835 UInt reg = hregNumber(opnd.variant.reg);
5836
5837 switch (insn->size) {
5838 case 4:
5839 return s390_emit_LTR(buf, reg, reg);
5840
5841 case 8:
5842 return s390_emit_LTGR(buf, reg, reg);
5843
5844 default:
5845 goto fail;
5846 }
5847 }
5848
5849 case S390_OPND_AMODE: {
5850 const s390_amode *am = opnd.variant.am;
5851 UChar b = hregNumber(am->b);
5852 UChar x = hregNumber(am->x);
5853 Int d = am->d;
5854
5855 switch (insn->size) {
5856 case 4:
5857 return s390_emit_LTw(buf, R0, x, b, DISP20(d));
5858
5859 case 8:
5860 return s390_emit_LTGw(buf, R0, x, b, DISP20(d));
5861
5862 default:
5863 goto fail;
5864 }
5865 }
5866
5867 case S390_OPND_IMMEDIATE: {
5868 ULong value = opnd.variant.imm;
5869
5870 switch (insn->size) {
5871 case 4:
5872 buf = s390_emit_load_32imm(buf, R0, value);
5873 return s390_emit_LTR(buf, R0, R0);
5874
5875 case 8:
5876 buf = s390_emit_load_64imm(buf, R0, value);
5877 return s390_emit_LTGR(buf, R0, R0);
5878
5879 default:
5880 goto fail;
5881 }
5882 }
5883
5884 default:
5885 goto fail;
5886 }
5887
5888 fail:
5889 vpanic("s390_insn_test_emit");
5890 }
5891
5892
5893 static UChar *
s390_insn_cc2bool_emit(UChar * buf,const s390_insn * insn)5894 s390_insn_cc2bool_emit(UChar *buf, const s390_insn *insn)
5895 {
5896 UChar r1 = hregNumber(insn->variant.cc2bool.dst);
5897 s390_cc_t cond = insn->variant.cc2bool.cond;
5898
5899 /* Make the destination register be 1 or 0, depending on whether
5900 the relevant condition holds. A 64-bit value is computed. */
5901 if (cond == S390_CC_ALWAYS)
5902 return s390_emit_LGHI(buf, r1, 1); /* r1 = 1 */
5903
5904 buf = s390_emit_load_cc(buf, r1); /* r1 = cc */
5905 buf = s390_emit_LGHI(buf, R0, cond); /* r0 = mask */
5906 buf = s390_emit_SLLG(buf, r1, R0, r1, DISP20(0)); /* r1 = mask << cc */
5907 buf = s390_emit_SRLG(buf, r1, r1, 0, DISP20(3)); /* r1 = r1 >> 3 */
5908 buf = s390_emit_NILL(buf, r1, 1); /* r1 = r1 & 0x1 */
5909
5910 return buf;
5911 }
5912
5913
5914 /* Only 4-byte and 8-byte operands are handled. */
5915 static UChar *
s390_insn_cas_emit(UChar * buf,const s390_insn * insn)5916 s390_insn_cas_emit(UChar *buf, const s390_insn *insn)
5917 {
5918 UChar r1, r3, b, old;
5919 Int d;
5920 s390_amode *am;
5921
5922 r1 = hregNumber(insn->variant.cas.op1); /* expected value */
5923 r3 = hregNumber(insn->variant.cas.op3);
5924 old= hregNumber(insn->variant.cas.old_mem);
5925 am = insn->variant.cas.op2;
5926 b = hregNumber(am->b);
5927 d = am->d;
5928
5929 switch (insn->size) {
5930 case 4:
5931 /* r1 must no be overwritten. So copy it to R0 and let CS clobber it */
5932 buf = s390_emit_LR(buf, R0, r1);
5933 if (am->tag == S390_AMODE_B12)
5934 buf = s390_emit_CS(buf, R0, r3, b, d);
5935 else
5936 buf = s390_emit_CSY(buf, R0, r3, b, DISP20(d));
5937 /* Now copy R0 which has the old memory value to OLD */
5938 return s390_emit_LR(buf, old, R0);
5939
5940 case 8:
5941 /* r1 must no be overwritten. So copy it to R0 and let CS clobber it */
5942 buf = s390_emit_LGR(buf, R0, r1);
5943 buf = s390_emit_CSG(buf, R0, r3, b, DISP20(d));
5944 /* Now copy R0 which has the old memory value to OLD */
5945 return s390_emit_LGR(buf, old, R0);
5946
5947 default:
5948 goto fail;
5949 }
5950
5951 fail:
5952 vpanic("s390_insn_cas_emit");
5953 }
5954
5955
5956 /* Only 4-byte and 8-byte comparisons are handled. 1-byte and 2-byte
5957 comparisons will have been converted to 4-byte comparisons in
5958 s390_isel_cc and should not occur here. */
5959 static UChar *
s390_insn_compare_emit(UChar * buf,const s390_insn * insn)5960 s390_insn_compare_emit(UChar *buf, const s390_insn *insn)
5961 {
5962 s390_opnd_RMI op2;
5963 HReg op1;
5964 Bool signed_comparison;
5965
5966 op1 = insn->variant.compare.src1;
5967 op2 = insn->variant.compare.src2;
5968 signed_comparison = insn->variant.compare.signed_comparison;
5969
5970 switch (op2.tag) {
5971 case S390_OPND_REG: {
5972 UInt r1 = hregNumber(op1);
5973 UInt r2 = hregNumber(op2.variant.reg);
5974
5975 switch (insn->size) {
5976 case 4:
5977 if (signed_comparison)
5978 return s390_emit_CR(buf, r1, r2);
5979 else
5980 return s390_emit_CLR(buf, r1, r2);
5981
5982 case 8:
5983 if (signed_comparison)
5984 return s390_emit_CGR(buf, r1, r2);
5985 else
5986 return s390_emit_CLGR(buf, r1, r2);
5987
5988 default:
5989 goto fail;
5990 }
5991 }
5992
5993 case S390_OPND_AMODE: {
5994 UChar r1 = hregNumber(op1);
5995 const s390_amode *am = op2.variant.am;
5996 UChar b = hregNumber(am->b);
5997 UChar x = hregNumber(am->x);
5998 Int d = am->d;
5999
6000 switch (insn->size) {
6001 case 4:
6002 switch (am->tag) {
6003 case S390_AMODE_B12:
6004 case S390_AMODE_BX12:
6005 if (signed_comparison)
6006 return s390_emit_C(buf, r1, x, b, d);
6007 else
6008 return s390_emit_CL(buf, r1, x, b, d);
6009
6010 case S390_AMODE_B20:
6011 case S390_AMODE_BX20:
6012 if (signed_comparison)
6013 return s390_emit_CY(buf, r1, x, b, DISP20(d));
6014 else
6015 return s390_emit_CLY(buf, r1, x, b, DISP20(d));
6016 }
6017 goto fail;
6018
6019 case 8:
6020 if (signed_comparison)
6021 return s390_emit_CG(buf, r1, x, b, DISP20(d));
6022 else
6023 return s390_emit_CLG(buf, r1, x, b, DISP20(d));
6024
6025 default:
6026 goto fail;
6027 }
6028 }
6029
6030 case S390_OPND_IMMEDIATE: {
6031 UChar r1 = hregNumber(op1);
6032 ULong value = op2.variant.imm;
6033
6034 switch (insn->size) {
6035 case 4:
6036 if (signed_comparison)
6037 return s390_emit_CFIw(buf, r1, value);
6038 else
6039 return s390_emit_CLFIw(buf, r1, value);
6040
6041 case 8:
6042 buf = s390_emit_load_64imm(buf, R0, value);
6043 if (signed_comparison)
6044 return s390_emit_CGR(buf, r1, R0);
6045 else
6046 return s390_emit_CLGR(buf, r1, R0);
6047
6048 default:
6049 goto fail;
6050 }
6051 }
6052
6053 default:
6054 goto fail;
6055 }
6056
6057 fail:
6058 vpanic("s390_insn_compare_emit");
6059 }
6060
6061
6062 static UChar *
s390_insn_mul_emit(UChar * buf,const s390_insn * insn)6063 s390_insn_mul_emit(UChar *buf, const s390_insn *insn)
6064 {
6065 s390_opnd_RMI op2;
6066 UChar r1;
6067 Bool signed_multiply;
6068
6069 /* The register number identifying the register pair */
6070 r1 = hregNumber(insn->variant.mul.dst_hi);
6071
6072 op2 = insn->variant.mul.op2;
6073 signed_multiply = insn->variant.mul.signed_multiply;
6074
6075 switch (op2.tag) {
6076 case S390_OPND_REG: {
6077 UInt r2 = hregNumber(op2.variant.reg);
6078
6079 switch (insn->size) {
6080 case 1:
6081 case 2:
6082 case 4:
6083 if (signed_multiply)
6084 return s390_emit_MR(buf, r1, r2);
6085 else
6086 return s390_emit_MLR(buf, r1, r2);
6087
6088 case 8:
6089 if (signed_multiply)
6090 vpanic("s390_insn_mul_emit");
6091 else
6092 return s390_emit_MLGR(buf, r1, r2);
6093
6094 default:
6095 goto fail;
6096 }
6097 }
6098
6099 case S390_OPND_AMODE: {
6100 const s390_amode *am = op2.variant.am;
6101 UChar b = hregNumber(am->b);
6102 UChar x = hregNumber(am->x);
6103 Int d = am->d;
6104
6105 switch (insn->size) {
6106 case 1:
6107 case 2:
6108 /* Load bytes into scratch register R0, then multiply */
6109 buf = s390_emit_load_mem(buf, insn->size, R0, am);
6110 if (signed_multiply)
6111 return s390_emit_MR(buf, r1, R0);
6112 else
6113 return s390_emit_MLR(buf, r1, R0);
6114
6115 case 4:
6116 switch (am->tag) {
6117 case S390_AMODE_B12:
6118 case S390_AMODE_BX12:
6119 if (signed_multiply)
6120 return s390_emit_M(buf, r1, x, b, d);
6121 else
6122 return s390_emit_ML(buf, r1, x, b, DISP20(d));
6123
6124 case S390_AMODE_B20:
6125 case S390_AMODE_BX20:
6126 if (signed_multiply)
6127 return s390_emit_MFYw(buf, r1, x, b, DISP20(d));
6128 else
6129 return s390_emit_ML(buf, r1, x, b, DISP20(d));
6130 }
6131 goto fail;
6132
6133 case 8:
6134 if (signed_multiply)
6135 vpanic("s390_insn_mul_emit");
6136 else
6137 return s390_emit_MLG(buf, r1, x, b, DISP20(d));
6138
6139 default:
6140 goto fail;
6141 }
6142 }
6143
6144 case S390_OPND_IMMEDIATE: {
6145 ULong value = op2.variant.imm;
6146
6147 switch (insn->size) {
6148 case 1:
6149 case 2:
6150 case 4:
6151 buf = s390_emit_load_32imm(buf, R0, value);
6152 if (signed_multiply)
6153 return s390_emit_MR(buf, r1, R0);
6154 else
6155 return s390_emit_MLR(buf, r1, R0);
6156
6157 case 8:
6158 buf = s390_emit_load_64imm(buf, R0, value);
6159 if (signed_multiply)
6160 vpanic("s390_insn_mul_emit");
6161 else
6162 return s390_emit_MLGR(buf, r1, R0);
6163
6164 default:
6165 goto fail;
6166 }
6167 }
6168
6169 default:
6170 goto fail;
6171 }
6172
6173 fail:
6174 vpanic("s390_insn_mul_emit");
6175 }
6176
6177
6178 static UChar *
s390_insn_div_emit(UChar * buf,const s390_insn * insn)6179 s390_insn_div_emit(UChar *buf, const s390_insn *insn)
6180 {
6181 s390_opnd_RMI op2;
6182 UChar r1;
6183 Bool signed_divide;
6184
6185 r1 = hregNumber(insn->variant.div.op1_hi);
6186 op2 = insn->variant.div.op2;
6187 signed_divide = insn->variant.div.signed_divide;
6188
6189 switch (op2.tag) {
6190 case S390_OPND_REG: {
6191 UInt r2 = hregNumber(op2.variant.reg);
6192
6193 switch (insn->size) {
6194 case 4:
6195 if (signed_divide)
6196 return s390_emit_DR(buf, r1, r2);
6197 else
6198 return s390_emit_DLR(buf, r1, r2);
6199
6200 case 8:
6201 if (signed_divide)
6202 vpanic("s390_insn_div_emit");
6203 else
6204 return s390_emit_DLGR(buf, r1, r2);
6205
6206 default:
6207 goto fail;
6208 }
6209 }
6210
6211 case S390_OPND_AMODE: {
6212 const s390_amode *am = op2.variant.am;
6213 UChar b = hregNumber(am->b);
6214 UChar x = hregNumber(am->x);
6215 Int d = am->d;
6216
6217 switch (insn->size) {
6218 case 4:
6219 switch (am->tag) {
6220 case S390_AMODE_B12:
6221 case S390_AMODE_BX12:
6222 if (signed_divide)
6223 return s390_emit_D(buf, r1, x, b, d);
6224 else
6225 return s390_emit_DL(buf, r1, x, b, DISP20(d));
6226
6227 case S390_AMODE_B20:
6228 case S390_AMODE_BX20:
6229 if (signed_divide) {
6230 buf = s390_emit_LY(buf, R0, x, b, DISP20(d));
6231 return s390_emit_DR(buf, r1, R0);
6232 } else
6233 return s390_emit_DL(buf, r1, x, b, DISP20(d));
6234 }
6235 goto fail;
6236
6237 case 8:
6238 if (signed_divide)
6239 vpanic("s390_insn_div_emit");
6240 else
6241 return s390_emit_DLG(buf, r1, x, b, DISP20(d));
6242
6243 default:
6244 goto fail;
6245 }
6246 }
6247
6248 case S390_OPND_IMMEDIATE: {
6249 ULong value = op2.variant.imm;
6250
6251 switch (insn->size) {
6252 case 4:
6253 buf = s390_emit_load_32imm(buf, R0, value);
6254 if (signed_divide)
6255 return s390_emit_DR(buf, r1, R0);
6256 else
6257 return s390_emit_DLR(buf, r1, R0);
6258
6259 case 8:
6260 buf = s390_emit_load_64imm(buf, R0, value);
6261 if (signed_divide)
6262 vpanic("s390_insn_div_emit");
6263 else
6264 return s390_emit_DLGR(buf, r1, R0);
6265
6266 default:
6267 goto fail;
6268 }
6269 }
6270
6271 default:
6272 goto fail;
6273 }
6274
6275 fail:
6276 vpanic("s390_insn_div_emit");
6277 }
6278
6279
6280 static UChar *
s390_insn_divs_emit(UChar * buf,const s390_insn * insn)6281 s390_insn_divs_emit(UChar *buf, const s390_insn *insn)
6282 {
6283 s390_opnd_RMI op2;
6284 UChar r1;
6285
6286 r1 = hregNumber(insn->variant.divs.rem);
6287 op2 = insn->variant.divs.op2;
6288
6289 switch (op2.tag) {
6290 case S390_OPND_REG: {
6291 UInt r2 = hregNumber(op2.variant.reg);
6292
6293 return s390_emit_DSGR(buf, r1, r2);
6294 }
6295
6296 case S390_OPND_AMODE: {
6297 const s390_amode *am = op2.variant.am;
6298 UChar b = hregNumber(am->b);
6299 UChar x = hregNumber(am->x);
6300 Int d = am->d;
6301
6302 return s390_emit_DSG(buf, r1, x, b, DISP20(d));
6303 }
6304
6305 case S390_OPND_IMMEDIATE: {
6306 ULong value = op2.variant.imm;
6307
6308 buf = s390_emit_load_64imm(buf, R0, value);
6309 return s390_emit_DSGR(buf, r1, R0);
6310 }
6311
6312 default:
6313 goto fail;
6314 }
6315
6316 fail:
6317 vpanic("s390_insn_divs_emit");
6318 }
6319
6320
6321 static UChar *
s390_insn_clz_emit(UChar * buf,const s390_insn * insn)6322 s390_insn_clz_emit(UChar *buf, const s390_insn *insn)
6323 {
6324 s390_opnd_RMI src;
6325 UChar r1, r1p1, r2, *p;
6326
6327 r1 = hregNumber(insn->variant.clz.num_bits);
6328 r1p1 = hregNumber(insn->variant.clz.clobber);
6329
6330 vassert((r1 & 0x1) == 0);
6331 vassert(r1p1 == r1 + 1);
6332
6333 p = buf;
6334 src = insn->variant.clz.src;
6335
6336 /* Get operand and move it to r2 */
6337 switch (src.tag) {
6338 case S390_OPND_REG:
6339 r2 = hregNumber(src.variant.reg);
6340 break;
6341
6342 case S390_OPND_AMODE: {
6343 const s390_amode *am = src.variant.am;
6344 UChar b = hregNumber(am->b);
6345 UChar x = hregNumber(am->x);
6346 Int d = am->d;
6347
6348 p = s390_emit_LG(p, R0, x, b, DISP20(d));
6349 r2 = R0;
6350 break;
6351 }
6352
6353 case S390_OPND_IMMEDIATE: {
6354 ULong value = src.variant.imm;
6355
6356 p = s390_emit_load_64imm(p, R0, value);
6357 r2 = R0;
6358 break;
6359 }
6360
6361 default:
6362 goto fail;
6363 }
6364
6365 /* Use FLOGR if you can */
6366 if (s390_host_has_eimm) {
6367 return s390_emit_FLOGR(p, r1, r2);
6368 }
6369
6370 /*
6371 r0 = r2;
6372 r1 = 64;
6373 while (r0 != 0) {
6374 r1 -= 1;
6375 r0 >>= 1;
6376 }
6377 */
6378 p = s390_emit_LTGR(p, R0, r2);
6379 p = s390_emit_LLILL(p, r1, 64);
6380
6381 p = s390_emit_BRC(p, S390_CC_E, (4 + 4 + 6 + 4 + 4)/ 2); /* 4 bytes */
6382 p = s390_emit_AGHI(p, r1, (UShort)-1); /* r1 -= 1; 4 bytes */
6383 p = s390_emit_SRLG(p, R0, R0, R0, DISP20(1)); /* r0 >>= 1; 6 bytes */
6384 p = s390_emit_LTGR(p, R0, R0); /* set cc 4 bytes */
6385 p = s390_emit_BRC(p, S390_CC_NE, /* 4 bytes */
6386 (UShort)(-(4 + 6 + 4) / 2));
6387 return p;
6388
6389 fail:
6390 vpanic("s390_insn_clz_emit");
6391 }
6392
6393
6394 static UChar *
s390_insn_branch_emit(UChar * buf,const s390_insn * insn)6395 s390_insn_branch_emit(UChar *buf, const s390_insn *insn)
6396 {
6397 s390_opnd_RMI dst;
6398 s390_cc_t cond;
6399 UInt trc;
6400 UChar *p, *ptmp = 0; /* avoid compiler warnings */
6401
6402 cond = insn->variant.branch.cond;
6403 dst = insn->variant.branch.dst;
6404
6405 p = buf;
6406 trc = 0;
6407
6408 if (cond != S390_CC_ALWAYS) {
6409 /* So we have something like this
6410 if (cond) goto X;
6411 Y: ...
6412 We convert this into
6413 if (! cond) goto Y; // BRC insn; 4 bytes
6414 return_reg = X;
6415 return to dispatcher
6416 Y:
6417 */
6418 ptmp = p; /* 4 bytes (a BRC insn) to be filled in here */
6419 p += 4;
6420 }
6421
6422 /* If a non-boring, set guest-state-pointer appropriately. */
6423
6424 switch (insn->variant.branch.kind) {
6425 case Ijk_ClientReq: trc = VEX_TRC_JMP_CLIENTREQ; break;
6426 case Ijk_Sys_syscall: trc = VEX_TRC_JMP_SYS_SYSCALL; break;
6427 case Ijk_Yield: trc = VEX_TRC_JMP_YIELD; break;
6428 case Ijk_EmWarn: trc = VEX_TRC_JMP_EMWARN; break;
6429 case Ijk_EmFail: trc = VEX_TRC_JMP_EMFAIL; break;
6430 case Ijk_MapFail: trc = VEX_TRC_JMP_MAPFAIL; break;
6431 case Ijk_NoDecode: trc = VEX_TRC_JMP_NODECODE; break;
6432 case Ijk_TInval: trc = VEX_TRC_JMP_TINVAL; break;
6433 case Ijk_NoRedir: trc = VEX_TRC_JMP_NOREDIR; break;
6434 case Ijk_SigTRAP: trc = VEX_TRC_JMP_SIGTRAP; break;
6435 case Ijk_Ret: trc = 0; break;
6436 case Ijk_Call: trc = 0; break;
6437 case Ijk_Boring: trc = 0; break;
6438 break;
6439
6440 default:
6441 vpanic("s390_insn_branch_emit: unknown jump kind");
6442 }
6443
6444 /* Get the destination address into the return register */
6445 switch (dst.tag) {
6446 case S390_OPND_REG:
6447 p = s390_emit_LGR(p, S390_REGNO_RETURN_VALUE, hregNumber(dst.variant.reg));
6448 break;
6449
6450 case S390_OPND_AMODE: {
6451 const s390_amode *am = dst.variant.am;
6452 UChar b = hregNumber(am->b);
6453 UChar x = hregNumber(am->x);
6454 Int d = am->d;
6455
6456 p = s390_emit_LG(p, S390_REGNO_RETURN_VALUE, x, b, DISP20(d));
6457 break;
6458 }
6459
6460 case S390_OPND_IMMEDIATE:
6461 p = s390_emit_load_64imm(p, S390_REGNO_RETURN_VALUE, dst.variant.imm);
6462 break;
6463
6464 default:
6465 goto fail;
6466 }
6467
6468 if (trc != 0) {
6469 /* Something special. Set guest-state pointer appropriately */
6470 p = s390_emit_LGHI(p, S390_REGNO_GUEST_STATE_POINTER, trc);
6471 } else {
6472 /* Nothing special needs to be done for calls and returns. */
6473 }
6474
6475 p = s390_emit_BCR(p, S390_CC_ALWAYS, S390_REGNO_LINK_REGISTER);
6476
6477 if (cond != S390_CC_ALWAYS) {
6478 Int delta = p - ptmp;
6479
6480 delta >>= 1; /* immediate constant is #half-words */
6481 vassert(delta > 0 && delta < (1 << 16));
6482 s390_emit_BRC(ptmp, s390_cc_invert(cond), delta);
6483 }
6484
6485 return p;
6486
6487 fail:
6488 vpanic("s390_insn_branch_emit");
6489 }
6490
6491
6492 static UChar *
s390_insn_helper_call_emit(UChar * buf,const s390_insn * insn)6493 s390_insn_helper_call_emit(UChar *buf, const s390_insn *insn)
6494 {
6495 s390_cc_t cond;
6496 ULong target;
6497 UChar *ptmp = buf;
6498
6499 cond = insn->variant.helper_call.cond;
6500 target = insn->variant.helper_call.target;
6501
6502 if (cond != S390_CC_ALWAYS) {
6503 /* So we have something like this
6504 if (cond) call X;
6505 Y: ...
6506 We convert this into
6507 if (! cond) goto Y; // BRC opcode; 4 bytes
6508 call X;
6509 Y:
6510 */
6511 /* 4 bytes (a BRC insn) to be filled in here */
6512 buf += 4;
6513 }
6514
6515 /* Load the target address into a register, that
6516 (a) is not used for passing parameters to the helper and
6517 (b) can be clobbered by the callee
6518 r1 looks like a good choice.
6519 Also, need to arrange for the return address be put into the
6520 link-register */
6521 buf = s390_emit_load_64imm(buf, 1, target);
6522
6523 /* Stash away the client's FPC register because the helper might change it. */
6524 buf = s390_emit_STFPC(buf, S390_REGNO_STACK_POINTER, S390_OFFSET_SAVED_FPC_C);
6525
6526 /* Before we can call the helper, we need to save the link register,
6527 because the BASR will overwrite it. We cannot use a register for that.
6528 (a) Volatile registers will be modified by the helper.
6529 (b) For saved registers the client code assumes that they have not
6530 changed after the function returns. So we cannot use it to store
6531 the link register.
6532 In the dispatcher, before calling the client code, we have arranged for
6533 a location on the stack for this purpose. See dispatch-s390x-linux.S. */
6534 buf = s390_emit_STG(buf, S390_REGNO_LINK_REGISTER, 0, // save LR
6535 S390_REGNO_STACK_POINTER, S390_OFFSET_SAVED_LR, 0);
6536 buf = s390_emit_BASR(buf, S390_REGNO_LINK_REGISTER, 1); // call helper
6537 buf = s390_emit_LG(buf, S390_REGNO_LINK_REGISTER, 0, // restore LR
6538 S390_REGNO_STACK_POINTER, S390_OFFSET_SAVED_LR, 0);
6539 buf = s390_emit_LFPC(buf, S390_REGNO_STACK_POINTER, // restore FPC
6540 S390_OFFSET_SAVED_FPC_C);
6541
6542 if (cond != S390_CC_ALWAYS) {
6543 Int delta = buf - ptmp;
6544
6545 delta >>= 1; /* immediate constant is #half-words */
6546 vassert(delta > 0 && delta < (1 << 16));
6547 s390_emit_BRC(ptmp, s390_cc_invert(cond), delta);
6548 }
6549
6550 return buf;
6551 }
6552
6553
6554 static UChar *
s390_insn_cond_move_emit(UChar * buf,const s390_insn * insn)6555 s390_insn_cond_move_emit(UChar *buf, const s390_insn *insn)
6556 {
6557 HReg dst;
6558 s390_opnd_RMI src;
6559 s390_cc_t cond;
6560 UChar *p, *ptmp = 0; /* avoid compiler warnings */
6561
6562 cond = insn->variant.cond_move.cond;
6563 dst = insn->variant.cond_move.dst;
6564 src = insn->variant.cond_move.src;
6565
6566 p = buf;
6567
6568 /* Branch (if cond fails) over move instrs */
6569 if (cond != S390_CC_ALWAYS) {
6570 /* Don't know how many bytes to jump over yet.
6571 Make space for a BRC instruction (4 bytes) and fill in later. */
6572 ptmp = p; /* to be filled in here */
6573 p += 4;
6574 }
6575
6576 // cond true: move src => dst
6577
6578 switch (src.tag) {
6579 case S390_OPND_REG:
6580 p = s390_emit_LGR(p, hregNumber(dst), hregNumber(src.variant.reg));
6581 break;
6582
6583 case S390_OPND_AMODE:
6584 p = s390_emit_load_mem(p, insn->size, hregNumber(dst), src.variant.am);
6585 break;
6586
6587 case S390_OPND_IMMEDIATE: {
6588 ULong value = src.variant.imm;
6589 UInt r = hregNumber(dst);
6590
6591 switch (insn->size) {
6592 case 1:
6593 case 2:
6594 /* Load the immediate values as a 4 byte value. That does not hurt as
6595 those extra bytes will not be looked at. Fall through .... */
6596 case 4:
6597 p = s390_emit_load_32imm(p, r, value);
6598 break;
6599
6600 case 8:
6601 p = s390_emit_load_64imm(p, r, value);
6602 break;
6603 }
6604 break;
6605 }
6606
6607 default:
6608 goto fail;
6609 }
6610
6611 if (cond != S390_CC_ALWAYS) {
6612 Int delta = p - ptmp;
6613
6614 delta >>= 1; /* immediate constant is #half-words */
6615 vassert(delta > 0 && delta < (1 << 16));
6616 s390_emit_BRC(ptmp, s390_cc_invert(cond), delta);
6617 }
6618
6619 return p;
6620
6621 fail:
6622 vpanic("s390_insn_cond_move_emit");
6623 }
6624
6625
6626 /* Little helper function to the rounding mode in the real FPC
6627 register */
6628 static UChar *
s390_set_fpc_rounding_mode(UChar * buf,s390_round_t rounding_mode)6629 s390_set_fpc_rounding_mode(UChar *buf, s390_round_t rounding_mode)
6630 {
6631 UChar bits;
6632
6633 /* Determine BFP rounding bits */
6634 switch (rounding_mode) {
6635 case S390_ROUND_NEAREST_EVEN: bits = 0; break;
6636 case S390_ROUND_ZERO: bits = 1; break;
6637 case S390_ROUND_POSINF: bits = 2; break;
6638 case S390_ROUND_NEGINF: bits = 3; break;
6639 default: vpanic("invalid rounding mode\n");
6640 }
6641
6642 /* Copy FPC from guest state to R0 and OR in the new rounding mode */
6643 buf = s390_emit_L(buf, R0, 0, S390_REGNO_GUEST_STATE_POINTER,
6644 OFFSET_s390x_fpc); // r0 = guest_fpc
6645
6646 buf = s390_emit_NILL(buf, R0, 0xFFFC); /* Clear out right-most 2 bits */
6647 buf = s390_emit_OILL(buf, R0, bits); /* OR in the new rounding mode */
6648 buf = s390_emit_SFPC(buf, R0, 0); /* Load FPC register from R0 */
6649
6650 return buf;
6651 }
6652
6653
6654 static UChar *
s390_insn_bfp_triop_emit(UChar * buf,const s390_insn * insn)6655 s390_insn_bfp_triop_emit(UChar *buf, const s390_insn *insn)
6656 {
6657 UInt r1 = hregNumber(insn->variant.bfp_triop.dst);
6658 UInt r2 = hregNumber(insn->variant.bfp_triop.op2);
6659 UInt r3 = hregNumber(insn->variant.bfp_triop.op3);
6660 s390_round_t rounding_mode = insn->variant.bfp_triop.rounding_mode;
6661
6662 if (rounding_mode != S390_ROUND_NEAREST_EVEN) {
6663 buf = s390_set_fpc_rounding_mode(buf, rounding_mode);
6664 }
6665
6666 switch (insn->size) {
6667 case 4:
6668 switch (insn->variant.bfp_triop.tag) {
6669 case S390_BFP_MADD: buf = s390_emit_MAEBR(buf, r1, r3, r2); break;
6670 case S390_BFP_MSUB: buf = s390_emit_MSEBR(buf, r1, r3, r2); break;
6671 default: goto fail;
6672 }
6673 break;
6674
6675 case 8:
6676 switch (insn->variant.bfp_triop.tag) {
6677 case S390_BFP_MADD: buf = s390_emit_MADBR(buf, r1, r3, r2); break;
6678 case S390_BFP_MSUB: buf = s390_emit_MSDBR(buf, r1, r3, r2); break;
6679 default: goto fail;
6680 }
6681 break;
6682
6683 default: goto fail;
6684 }
6685
6686 if (rounding_mode != S390_ROUND_NEAREST_EVEN) {
6687 /* Restore FPC register from guest state */
6688 buf = s390_emit_LFPC(buf, S390_REGNO_GUEST_STATE_POINTER,
6689 OFFSET_s390x_fpc); // fpc = guest_fpc
6690 }
6691 return buf;
6692
6693 fail:
6694 vpanic("s390_insn_bfp_triop_emit");
6695 }
6696
6697
6698 static UChar *
s390_insn_bfp_binop_emit(UChar * buf,const s390_insn * insn)6699 s390_insn_bfp_binop_emit(UChar *buf, const s390_insn *insn)
6700 {
6701 UInt r1 = hregNumber(insn->variant.bfp_binop.dst);
6702 UInt r2 = hregNumber(insn->variant.bfp_binop.op2);
6703 s390_round_t rounding_mode = insn->variant.bfp_binop.rounding_mode;
6704
6705 if (rounding_mode != S390_ROUND_NEAREST_EVEN) {
6706 buf = s390_set_fpc_rounding_mode(buf, rounding_mode);
6707 }
6708
6709 switch (insn->size) {
6710 case 4:
6711 switch (insn->variant.bfp_binop.tag) {
6712 case S390_BFP_ADD: buf = s390_emit_AEBR(buf, r1, r2); break;
6713 case S390_BFP_SUB: buf = s390_emit_SEBR(buf, r1, r2); break;
6714 case S390_BFP_MUL: buf = s390_emit_MEEBR(buf, r1, r2); break;
6715 case S390_BFP_DIV: buf = s390_emit_DEBR(buf, r1, r2); break;
6716 default: goto fail;
6717 }
6718 break;
6719
6720 case 8:
6721 switch (insn->variant.bfp_binop.tag) {
6722 case S390_BFP_ADD: buf = s390_emit_ADBR(buf, r1, r2); break;
6723 case S390_BFP_SUB: buf = s390_emit_SDBR(buf, r1, r2); break;
6724 case S390_BFP_MUL: buf = s390_emit_MDBR(buf, r1, r2); break;
6725 case S390_BFP_DIV: buf = s390_emit_DDBR(buf, r1, r2); break;
6726 default: goto fail;
6727 }
6728 break;
6729
6730 default: goto fail;
6731 }
6732
6733 if (rounding_mode != S390_ROUND_NEAREST_EVEN) {
6734 /* Restore FPC register from guest state */
6735 buf = s390_emit_LFPC(buf, S390_REGNO_GUEST_STATE_POINTER,
6736 OFFSET_s390x_fpc);
6737 }
6738 return buf;
6739
6740 fail:
6741 vpanic("s390_insn_bfp_binop_emit");
6742 }
6743
6744
6745 static UChar *
s390_insn_bfp_unop_emit(UChar * buf,const s390_insn * insn)6746 s390_insn_bfp_unop_emit(UChar *buf, const s390_insn *insn)
6747 {
6748 UInt r1 = hregNumber(insn->variant.bfp_unop.dst);
6749 UInt r2 = hregNumber(insn->variant.bfp_unop.op);
6750 s390_round_t rounding_mode = insn->variant.bfp_unop.rounding_mode;
6751 s390_round_t m3 = rounding_mode;
6752
6753 /* The "convert to fixed" instructions have a field for the rounding
6754 mode and no FPC modification is necessary. So we handle them
6755 upfront. */
6756 switch (insn->variant.bfp_unop.tag) {
6757 case S390_BFP_F32_TO_I32: return s390_emit_CFEBR(buf, m3, r1, r2);
6758 case S390_BFP_F64_TO_I32: return s390_emit_CFDBR(buf, m3, r1, r2);
6759 case S390_BFP_F32_TO_I64: return s390_emit_CGEBR(buf, m3, r1, r2);
6760 case S390_BFP_F64_TO_I64: return s390_emit_CGDBR(buf, m3, r1, r2);
6761 default: break;
6762 }
6763
6764 /* For all other insns if a special rounding mode is requested,
6765 we need to set the FPC first and restore it later. */
6766 if (rounding_mode != S390_ROUND_NEAREST_EVEN) {
6767 buf = s390_set_fpc_rounding_mode(buf, rounding_mode);
6768 }
6769
6770 switch (insn->variant.bfp_unop.tag) {
6771 case S390_BFP_ABS:
6772 switch (insn->size) {
6773 case 4: buf = s390_emit_LPEBR(buf, r1, r2); break;
6774 case 8: buf = s390_emit_LPDBR(buf, r1, r2); break;
6775 case 16: buf = s390_emit_LPXBR(buf, r1, r2); break;
6776 default: goto fail;
6777 }
6778 break;
6779
6780 case S390_BFP_NABS:
6781 switch (insn->size) {
6782 case 4: buf = s390_emit_LNEBR(buf, r1, r2); break;
6783 case 8: buf = s390_emit_LNDBR(buf, r1, r2); break;
6784 case 16: buf = s390_emit_LNXBR(buf, r1, r2); break;
6785 default: goto fail;
6786 }
6787 break;
6788
6789 case S390_BFP_NEG:
6790 switch (insn->size) {
6791 case 4: buf = s390_emit_LCEBR(buf, r1, r2); break;
6792 case 8: buf = s390_emit_LCDBR(buf, r1, r2); break;
6793 case 16: buf = s390_emit_LCXBR(buf, r1, r2); break;
6794 default: goto fail;
6795 }
6796 break;
6797
6798 case S390_BFP_SQRT:
6799 switch (insn->size) {
6800 case 4: buf = s390_emit_SQEBR(buf, r1, r2); break;
6801 case 8: buf = s390_emit_SQDBR(buf, r1, r2); break;
6802 case 16: buf = s390_emit_SQXBR(buf, r1, r2); break;
6803 default: goto fail;
6804 }
6805 break;
6806
6807 case S390_BFP_I32_TO_F32: buf = s390_emit_CEFBR(buf, r1, r2); break;
6808 case S390_BFP_I32_TO_F64: buf = s390_emit_CDFBR(buf, r1, r2); break;
6809 case S390_BFP_I32_TO_F128: buf = s390_emit_CXFBR(buf, r1, r2); break;
6810 case S390_BFP_I64_TO_F32: buf = s390_emit_CEGBR(buf, r1, r2); break;
6811 case S390_BFP_I64_TO_F64: buf = s390_emit_CDGBR(buf, r1, r2); break;
6812 case S390_BFP_I64_TO_F128: buf = s390_emit_CXGBR(buf, r1, r2); break;
6813
6814 case S390_BFP_F32_TO_F64: buf = s390_emit_LDEBR(buf, r1, r2); break;
6815 case S390_BFP_F32_TO_F128: buf = s390_emit_LXEBR(buf, r1, r2); break;
6816 case S390_BFP_F64_TO_F32: buf = s390_emit_LEDBR(buf, r1, r2); break;
6817 case S390_BFP_F64_TO_F128: buf = s390_emit_LXDBR(buf, r1, r2); break;
6818
6819 default: goto fail;
6820 }
6821
6822 if (rounding_mode != S390_ROUND_NEAREST_EVEN) {
6823 /* Restore FPC register from guest state */
6824 buf = s390_emit_LFPC(buf, S390_REGNO_GUEST_STATE_POINTER,
6825 OFFSET_s390x_fpc); // fpc = guest_fpc
6826 }
6827 return buf;
6828
6829 fail:
6830 vpanic("s390_insn_bfp_unop_emit");
6831 }
6832
6833
6834 static UChar *
s390_insn_bfp_compare_emit(UChar * buf,const s390_insn * insn)6835 s390_insn_bfp_compare_emit(UChar *buf, const s390_insn *insn)
6836 {
6837 UInt dst = hregNumber(insn->variant.bfp_compare.dst);
6838 UInt r1 = hregNumber(insn->variant.bfp_compare.op1);
6839 UInt r2 = hregNumber(insn->variant.bfp_compare.op2);
6840
6841 switch (insn->size) {
6842 case 4:
6843 buf = s390_emit_CEBR(buf, r1, r2);
6844 break;
6845
6846 case 8:
6847 buf = s390_emit_CDBR(buf, r1, r2);
6848 break;
6849
6850 default: goto fail;
6851 }
6852
6853 return s390_emit_load_cc(buf, dst); /* Load condition code into DST */
6854
6855 fail:
6856 vpanic("s390_insn_bfp_compare_emit");
6857 }
6858
6859
6860 static UChar *
s390_insn_bfp128_binop_emit(UChar * buf,const s390_insn * insn)6861 s390_insn_bfp128_binop_emit(UChar *buf, const s390_insn *insn)
6862 {
6863 UInt r1_hi = hregNumber(insn->variant.bfp128_binop.dst_hi);
6864 UInt r1_lo = hregNumber(insn->variant.bfp128_binop.dst_lo);
6865 UInt r2_hi = hregNumber(insn->variant.bfp128_binop.op2_hi);
6866 UInt r2_lo = hregNumber(insn->variant.bfp128_binop.op2_lo);
6867 s390_round_t rounding_mode = insn->variant.bfp_binop.rounding_mode;
6868
6869 /* Paranoia */
6870 vassert(insn->size == 16);
6871 vassert(r1_lo == r1_hi + 2);
6872 vassert(r2_lo == r2_hi + 2);
6873 vassert((r1_hi & 0x2) == 0);
6874 vassert((r2_hi & 0x2) == 0);
6875
6876 if (rounding_mode != S390_ROUND_NEAREST_EVEN) {
6877 buf = s390_set_fpc_rounding_mode(buf, rounding_mode);
6878 }
6879
6880 switch (insn->variant.bfp128_binop.tag) {
6881 case S390_BFP_ADD: buf = s390_emit_AXBR(buf, r1_hi, r2_hi); break;
6882 case S390_BFP_SUB: buf = s390_emit_SXBR(buf, r1_hi, r2_hi); break;
6883 case S390_BFP_MUL: buf = s390_emit_MXBR(buf, r1_hi, r2_hi); break;
6884 case S390_BFP_DIV: buf = s390_emit_DXBR(buf, r1_hi, r2_hi); break;
6885 default: goto fail;
6886 }
6887
6888 if (rounding_mode != S390_ROUND_NEAREST_EVEN) {
6889 /* Restore FPC register from guest state */
6890 buf = s390_emit_LFPC(buf, S390_REGNO_GUEST_STATE_POINTER,
6891 OFFSET_s390x_fpc); // fpc = guest_fpc
6892 }
6893 return buf;
6894
6895 fail:
6896 vpanic("s390_insn_bfp128_binop_emit");
6897 }
6898
6899
6900 static UChar *
s390_insn_bfp128_compare_emit(UChar * buf,const s390_insn * insn)6901 s390_insn_bfp128_compare_emit(UChar *buf, const s390_insn *insn)
6902 {
6903 UInt dst = hregNumber(insn->variant.bfp128_compare.dst);
6904 UInt r1_hi = hregNumber(insn->variant.bfp128_compare.op1_hi);
6905 UInt r1_lo = hregNumber(insn->variant.bfp128_compare.op1_lo);
6906 UInt r2_hi = hregNumber(insn->variant.bfp128_compare.op2_hi);
6907 UInt r2_lo = hregNumber(insn->variant.bfp128_compare.op2_lo);
6908
6909 /* Paranoia */
6910 vassert(insn->size == 16);
6911 vassert(r1_lo == r1_hi + 2);
6912 vassert(r2_lo == r2_hi + 2);
6913 vassert((r1_hi & 0x2) == 0);
6914 vassert((r2_hi & 0x2) == 0);
6915
6916 buf = s390_emit_CXBR(buf, r1_hi, r2_hi);
6917
6918 /* Load condition code into DST */
6919 return s390_emit_load_cc(buf, dst);
6920 }
6921
6922
6923 static UChar *
s390_insn_bfp128_unop_emit(UChar * buf,const s390_insn * insn)6924 s390_insn_bfp128_unop_emit(UChar *buf, const s390_insn *insn)
6925 {
6926 UInt r1_hi = hregNumber(insn->variant.bfp128_unop.dst_hi);
6927 UInt r1_lo = hregNumber(insn->variant.bfp128_unop.dst_lo);
6928 UInt r2_hi = hregNumber(insn->variant.bfp128_unop.op_hi);
6929 UInt r2_lo = hregNumber(insn->variant.bfp128_unop.op_lo);
6930 s390_round_t rounding_mode = insn->variant.bfp_binop.rounding_mode;
6931
6932 /* Paranoia */
6933 vassert(insn->size == 16);
6934 vassert(r1_lo == r1_hi + 2);
6935 vassert(r2_lo == r2_hi + 2);
6936 vassert((r1_hi & 0x2) == 0);
6937 vassert((r2_hi & 0x2) == 0);
6938
6939 if (rounding_mode != S390_ROUND_NEAREST_EVEN) {
6940 buf = s390_set_fpc_rounding_mode(buf, rounding_mode);
6941 }
6942
6943 switch (insn->variant.bfp128_unop.tag) {
6944 case S390_BFP_ABS: buf = s390_emit_LPXBR(buf, r1_hi, r2_hi); break;
6945 case S390_BFP_NABS: buf = s390_emit_LNXBR(buf, r1_hi, r2_hi); break;
6946 case S390_BFP_NEG: buf = s390_emit_LCXBR(buf, r1_hi, r2_hi); break;
6947 case S390_BFP_SQRT: buf = s390_emit_SQXBR(buf, r1_hi, r2_hi); break;
6948 case S390_BFP_F128_TO_F32: buf = s390_emit_LEXBR(buf, r1_hi, r2_hi); break;
6949 case S390_BFP_F128_TO_F64: buf = s390_emit_LDXBR(buf, r1_hi, r2_hi); break;
6950 default: goto fail;
6951 }
6952
6953 if (rounding_mode != S390_ROUND_NEAREST_EVEN) {
6954 /* Restore FPC register from guest state */
6955 buf = s390_emit_LFPC(buf, S390_REGNO_GUEST_STATE_POINTER,
6956 OFFSET_s390x_fpc); // fpc = guest_fpc
6957 }
6958 return buf;
6959
6960 fail:
6961 vpanic("s390_insn_bfp128_unop_emit");
6962 }
6963
6964
6965 /* Conversion to 128-bit BFP does not require a rounding mode */
6966 static UChar *
s390_insn_bfp128_convert_to_emit(UChar * buf,const s390_insn * insn)6967 s390_insn_bfp128_convert_to_emit(UChar *buf, const s390_insn *insn)
6968 {
6969 UInt r1_hi = hregNumber(insn->variant.bfp128_unop.dst_hi);
6970 UInt r1_lo = hregNumber(insn->variant.bfp128_unop.dst_lo);
6971 UInt r2 = hregNumber(insn->variant.bfp128_unop.op_hi);
6972
6973 /* Paranoia */
6974 vassert(insn->size == 16);
6975 vassert(r1_lo == r1_hi + 2);
6976 vassert((r1_hi & 0x2) == 0);
6977
6978 switch (insn->variant.bfp128_unop.tag) {
6979 case S390_BFP_I32_TO_F128: buf = s390_emit_CXFBR(buf, r1_hi, r2); break;
6980 case S390_BFP_I64_TO_F128: buf = s390_emit_CXGBR(buf, r1_hi, r2); break;
6981 case S390_BFP_F32_TO_F128: buf = s390_emit_LXEBR(buf, r1_hi, r2); break;
6982 case S390_BFP_F64_TO_F128: buf = s390_emit_LXDBR(buf, r1_hi, r2); break;
6983 default: goto fail;
6984 }
6985
6986 return buf;
6987
6988 fail:
6989 vpanic("s390_insn_bfp128_convert_to_emit");
6990 }
6991
6992
6993 static UChar *
s390_insn_bfp128_convert_from_emit(UChar * buf,const s390_insn * insn)6994 s390_insn_bfp128_convert_from_emit(UChar *buf, const s390_insn *insn)
6995 {
6996 UInt r1 = hregNumber(insn->variant.bfp128_unop.dst_hi);
6997 UInt r2_hi = hregNumber(insn->variant.bfp128_unop.op_hi);
6998 UInt r2_lo = hregNumber(insn->variant.bfp128_unop.op_lo);
6999 s390_round_t rounding_mode = insn->variant.bfp_binop.rounding_mode;
7000
7001 /* Paranoia */
7002 vassert(insn->size != 16);
7003 vassert(r2_lo == r2_hi + 2);
7004 vassert((r2_hi & 0x2) == 0);
7005
7006 /* The "convert to fixed" instructions have a field for the rounding
7007 mode and no FPC modification is necessary. So we handle them
7008 upfront. */
7009 switch (insn->variant.bfp_unop.tag) {
7010 case S390_BFP_F128_TO_I32: return s390_emit_CFXBR(buf, rounding_mode,
7011 r1, r2_hi); break;
7012 case S390_BFP_F128_TO_I64: return s390_emit_CGXBR(buf, rounding_mode,
7013 r1, r2_hi); break;
7014 default: break;
7015 }
7016
7017 vpanic("s390_insn_bfp128_convert_from_emit");
7018 }
7019
7020
7021 static UChar *
s390_insn_mfence_emit(UChar * buf,const s390_insn * insn)7022 s390_insn_mfence_emit(UChar *buf, const s390_insn *insn)
7023 {
7024 return s390_emit_BCR(buf, 0xF, 0x0);
7025 }
7026
7027
7028 Int
emit_S390Instr(UChar * buf,Int nbuf,s390_insn * insn,Bool mode64,void * dispatch_unassisted,void * dispatch_assisted)7029 emit_S390Instr(UChar *buf, Int nbuf, s390_insn *insn, Bool mode64,
7030 void *dispatch_unassisted, void *dispatch_assisted)
7031 {
7032 UChar *end;
7033
7034 switch (insn->tag) {
7035 case S390_INSN_LOAD:
7036 end = s390_insn_load_emit(buf, insn);
7037 break;
7038
7039 case S390_INSN_STORE:
7040 end = s390_insn_store_emit(buf, insn);
7041 break;
7042
7043 case S390_INSN_MOVE:
7044 end = s390_insn_move_emit(buf, insn);
7045 break;
7046
7047 case S390_INSN_COND_MOVE:
7048 end = s390_insn_cond_move_emit(buf, insn);
7049 break;
7050
7051 case S390_INSN_LOAD_IMMEDIATE:
7052 end = s390_insn_load_immediate_emit(buf, insn);
7053 break;
7054
7055 case S390_INSN_ALU:
7056 end = s390_insn_alu_emit(buf, insn);
7057 break;
7058
7059 case S390_INSN_MUL:
7060 end = s390_insn_mul_emit(buf, insn);
7061 break;
7062
7063 case S390_INSN_DIV:
7064 end = s390_insn_div_emit(buf, insn);
7065 break;
7066
7067 case S390_INSN_DIVS:
7068 end = s390_insn_divs_emit(buf, insn);
7069 break;
7070
7071 case S390_INSN_CLZ:
7072 end = s390_insn_clz_emit(buf, insn);
7073 break;
7074
7075 case S390_INSN_UNOP:
7076 end = s390_insn_unop_emit(buf, insn);
7077 break;
7078
7079 case S390_INSN_TEST:
7080 end = s390_insn_test_emit(buf, insn);
7081 break;
7082
7083 case S390_INSN_CC2BOOL:
7084 end = s390_insn_cc2bool_emit(buf, insn);
7085 break;
7086
7087 case S390_INSN_CAS:
7088 end = s390_insn_cas_emit(buf, insn);
7089 break;
7090
7091 case S390_INSN_COMPARE:
7092 end = s390_insn_compare_emit(buf, insn);
7093 break;
7094
7095 case S390_INSN_BRANCH:
7096 vassert(dispatch_unassisted == NULL);
7097 vassert(dispatch_assisted == NULL);
7098 end = s390_insn_branch_emit(buf, insn);
7099 break;
7100
7101 case S390_INSN_HELPER_CALL:
7102 end = s390_insn_helper_call_emit(buf, insn);
7103 break;
7104
7105 case S390_INSN_BFP_TRIOP:
7106 end = s390_insn_bfp_triop_emit(buf, insn);
7107 break;
7108
7109 case S390_INSN_BFP_BINOP:
7110 end = s390_insn_bfp_binop_emit(buf, insn);
7111 break;
7112
7113 case S390_INSN_BFP_UNOP:
7114 end = s390_insn_bfp_unop_emit(buf, insn);
7115 break;
7116
7117 case S390_INSN_BFP_COMPARE:
7118 end = s390_insn_bfp_compare_emit(buf, insn);
7119 break;
7120
7121 case S390_INSN_BFP128_BINOP:
7122 end = s390_insn_bfp128_binop_emit(buf, insn);
7123 break;
7124
7125 case S390_INSN_BFP128_COMPARE:
7126 end = s390_insn_bfp128_compare_emit(buf, insn);
7127 break;
7128
7129 case S390_INSN_BFP128_UNOP:
7130 end = s390_insn_bfp128_unop_emit(buf, insn);
7131 break;
7132
7133 case S390_INSN_BFP128_CONVERT_TO:
7134 end = s390_insn_bfp128_convert_to_emit(buf, insn);
7135 break;
7136
7137 case S390_INSN_BFP128_CONVERT_FROM:
7138 end = s390_insn_bfp128_convert_from_emit(buf, insn);
7139 break;
7140
7141 case S390_INSN_MFENCE:
7142 end = s390_insn_mfence_emit(buf, insn);
7143 break;
7144
7145 default:
7146 vpanic("s390_insn_emit");
7147 }
7148
7149 vassert(end - buf <= nbuf);
7150
7151 return end - buf;
7152 }
7153
7154
7155 /*---------------------------------------------------------------*/
7156 /*--- end host_s390_defs.c ---*/
7157 /*---------------------------------------------------------------*/
7158