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