blob: ad589e785a1ef68c3461b1806be7f3739516f1fd [file] [log] [blame]
sewardj2019a972011-03-07 16:04:07 +00001/* -*- mode: C; c-basic-offset: 3; -*- */
2
3/*---------------------------------------------------------------*/
4/*--- begin host_s390_defs.c ---*/
5/*---------------------------------------------------------------*/
6
7/*
8 This file is part of Valgrind, a dynamic binary instrumentation
9 framework.
10
11 Copyright IBM Corp. 2010-2011
12
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
26 02110-1301, USA.
27
28 The GNU General Public License is contained in the file COPYING.
29*/
30
31/* Contributed by Florian Krohm */
32
33#include "libvex_basictypes.h"
34#include "libvex.h"
35#include "libvex_trc_values.h"
36#include "libvex_guest_offsets.h"
37#include "libvex_s390x_common.h"
38
39#include "main_util.h"
40#include "main_globals.h"
41#include "host_generic_regs.h"
42#include "host_s390_defs.h"
43#include "host_s390_disasm.h"
44#include <stdarg.h>
45
46/* KLUDGE: We need to know the hwcaps of the host when generating
47 code. But that info is not passed to emit_S390Instr. Only mode64 is
48 being passed. So, ideally, we want this passed as an argument, too.
49 Until then, we use a global variable. This variable is set as a side
50 effect of iselSB_S390. This is safe because instructions are selected
51 before they are emitted. */
52const VexArchInfo *s390_archinfo_host;
53
florianb4df7682011-07-05 02:09:01 +000054
55/*------------------------------------------------------------*/
56/*--- Forward declarations ---*/
57/*------------------------------------------------------------*/
58
59static Bool s390_insn_is_reg_reg_move(const s390_insn *, HReg *src, HReg *dst);
60static void s390_insn_map_regs(HRegRemap *, s390_insn *);
61static void s390_insn_get_reg_usage(HRegUsage *u, const s390_insn *);
62
63
sewardj2019a972011-03-07 16:04:07 +000064/*------------------------------------------------------------*/
65/*--- Registers ---*/
66/*------------------------------------------------------------*/
67
68/* Decompile the given register into a static buffer and return it */
69const HChar *
70s390_hreg_as_string(HReg reg)
71{
72 static HChar buf[10];
73
74 static const HChar ireg_names[16][5] = {
75 "%r0", "%r1", "%r2", "%r3", "%r4", "%r5", "%r6", "%r7",
76 "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15"
77 };
78
79 static const HChar freg_names[16][5] = {
80 "%f0", "%f1", "%f2", "%f3", "%f4", "%f5", "%f6", "%f7",
81 "%f8", "%f9", "%f10", "%f11", "%f12", "%f13", "%f14", "%f15"
82 };
83
84 UInt r; /* hregNumber() returns an UInt */
85
86 r = hregNumber(reg);
87
88 /* Be generic for all virtual regs. */
89 if (hregIsVirtual(reg)) {
90 buf[0] = '\0';
91 switch (hregClass(reg)) {
92 case HRcInt64: vex_sprintf(buf, "%%vR%d", r); break;
93 case HRcFlt64: vex_sprintf(buf, "%%vF%d", r); break;
94 default: goto fail;
95 }
96 return buf;
97 }
98
99 /* But specific for real regs. */
100 vassert(r < 16);
101
102 switch (hregClass(reg)) {
103 case HRcInt64: return ireg_names[r];
104 case HRcFlt64: return freg_names[r];
105 default: goto fail;
106 }
107
108 fail: vpanic("s390_hreg_as_string");
109}
110
111
112/* Tell the register allocator which registers can be allocated. */
florianb4df7682011-07-05 02:09:01 +0000113static void
sewardj2019a972011-03-07 16:04:07 +0000114s390_hreg_get_allocable(Int *nregs, HReg **arr)
115{
116 UInt i;
117
118 /* Total number of allocable registers (all classes) */
119 *nregs = 16 /* GPRs */
120 - 1 /* r0 */
121 - 1 /* r12 register holding VG_(dispatch_ctr) */
122 - 1 /* r13 guest state pointer */
123 - 1 /* r14 link register */
124 - 1 /* r15 stack pointer */
125 + 16 /* FPRs */
126 ;
127
128 *arr = LibVEX_Alloc(*nregs * sizeof(HReg));
129
130 i = 0;
131
132 /* GPR0 is not available because it is interpreted as 0, when used
133 as a base or index register. */
134 (*arr)[i++] = mkHReg(1, HRcInt64, False);
135 (*arr)[i++] = mkHReg(2, HRcInt64, False);
136 (*arr)[i++] = mkHReg(3, HRcInt64, False);
137 (*arr)[i++] = mkHReg(4, HRcInt64, False);
138 (*arr)[i++] = mkHReg(5, HRcInt64, False);
139 (*arr)[i++] = mkHReg(6, HRcInt64, False);
140 (*arr)[i++] = mkHReg(7, HRcInt64, False);
141 (*arr)[i++] = mkHReg(8, HRcInt64, False);
142 (*arr)[i++] = mkHReg(9, HRcInt64, False);
143 /* GPR10 and GPR11 are used for instructions that use register pairs.
144 Otherwise, they are available to the allocator */
145 (*arr)[i++] = mkHReg(10, HRcInt64, False);
146 (*arr)[i++] = mkHReg(11, HRcInt64, False);
147 /* GPR12 is not available because it caches VG_(dispatch_ctr) */
148 /* GPR13 is not available because it is used as guest state pointer */
149 /* GPR14 is not available because it is used as link register */
150 /* GPR15 is not available because it is used as stack pointer */
151
152 /* Add the available real (non-virtual) FPRs */
153 (*arr)[i++] = mkHReg(0, HRcFlt64, False);
154 (*arr)[i++] = mkHReg(1, HRcFlt64, False);
155 (*arr)[i++] = mkHReg(2, HRcFlt64, False);
156 (*arr)[i++] = mkHReg(3, HRcFlt64, False);
157 (*arr)[i++] = mkHReg(4, HRcFlt64, False);
158 (*arr)[i++] = mkHReg(5, HRcFlt64, False);
159 (*arr)[i++] = mkHReg(6, HRcFlt64, False);
160 (*arr)[i++] = mkHReg(7, HRcFlt64, False);
161 (*arr)[i++] = mkHReg(8, HRcFlt64, False);
162 (*arr)[i++] = mkHReg(9, HRcFlt64, False);
163 (*arr)[i++] = mkHReg(10, HRcFlt64, False);
164 (*arr)[i++] = mkHReg(11, HRcFlt64, False);
165 (*arr)[i++] = mkHReg(12, HRcFlt64, False);
166 (*arr)[i++] = mkHReg(13, HRcFlt64, False);
167 (*arr)[i++] = mkHReg(14, HRcFlt64, False);
168 (*arr)[i++] = mkHReg(15, HRcFlt64, False);
169 /* FPR12 - FPR15 are also used as register pairs for 128-bit
170 floating point operations */
171}
172
173
174/* Return the real register that holds the guest state pointer */
175HReg
176s390_hreg_guest_state_pointer(void)
177{
178 return mkHReg(S390_REGNO_GUEST_STATE_POINTER, HRcInt64, False);
179}
180
181/* Is VALUE within the domain of a 20-bit signed integer. */
182static __inline__ Bool
183fits_signed_20bit(Int value)
184{
185 return ((value << 12) >> 12) == value;
186}
187
188
189/* Is VALUE within the domain of a 12-bit unsigned integer. */
190static __inline__ Bool
191fits_unsigned_12bit(Int value)
192{
193 return (value & 0xFFF) == value;
194}
195
196/*------------------------------------------------------------*/
197/*--- Addressing modes (amodes) ---*/
198/*------------------------------------------------------------*/
199
200/* Construct a b12 amode. */
201s390_amode *
202s390_amode_b12(Int d, HReg b)
203{
204 s390_amode *am = LibVEX_Alloc(sizeof(s390_amode));
205
206 vassert(fits_unsigned_12bit(d));
207
208 am->tag = S390_AMODE_B12;
209 am->d = d;
210 am->b = b;
211 am->x = 0; /* hregNumber(0) == 0 */
212
213 return am;
214}
215
216
217/* Construct a b20 amode. */
218s390_amode *
219s390_amode_b20(Int d, HReg b)
220{
221 s390_amode *am = LibVEX_Alloc(sizeof(s390_amode));
222
223 vassert(fits_signed_20bit(d));
224
225 am->tag = S390_AMODE_B20;
226 am->d = d;
227 am->b = b;
228 am->x = 0; /* hregNumber(0) == 0 */
229
230 return am;
231}
232
233
234/* Construct a bx12 amode. */
235s390_amode *
236s390_amode_bx12(Int d, HReg b, HReg x)
237{
238 s390_amode *am = LibVEX_Alloc(sizeof(s390_amode));
239
240 vassert(fits_unsigned_12bit(d));
241 vassert(b != 0);
242 vassert(x != 0);
243
244 am->tag = S390_AMODE_BX12;
245 am->d = d;
246 am->b = b;
247 am->x = x;
248
249 return am;
250}
251
252
253/* Construct a bx20 amode. */
254s390_amode *
255s390_amode_bx20(Int d, HReg b, HReg x)
256{
257 s390_amode *am = LibVEX_Alloc(sizeof(s390_amode));
258
259 vassert(fits_signed_20bit(d));
260 vassert(b != 0);
261 vassert(x != 0);
262
263 am->tag = S390_AMODE_BX20;
264 am->d = d;
265 am->b = b;
266 am->x = x;
267
268 return am;
269}
270
271
272/* Construct an AMODE for accessing the guest state at OFFSET */
273s390_amode *
274s390_amode_for_guest_state(Int offset)
275{
276 if (fits_unsigned_12bit(offset))
277 return s390_amode_b12(offset, s390_hreg_guest_state_pointer());
sewardj2019a972011-03-07 16:04:07 +0000278
279 vpanic("invalid guest state offset");
280}
281
282
283/* Decompile the given amode into a static buffer and return it. */
284const HChar *
285s390_amode_as_string(const s390_amode *am)
286{
287 static HChar buf[30];
288 HChar *p;
289
290 buf[0] = '\0';
291 p = buf;
292
293 switch (am->tag) {
294 case S390_AMODE_B12:
295 case S390_AMODE_B20:
296 vex_sprintf(p, "%d(%s)", am->d, s390_hreg_as_string(am->b));
297 break;
298
299 case S390_AMODE_BX12:
300 case S390_AMODE_BX20:
301 /* s390_hreg_as_string returns pointer to local buffer. Need to
302 split this into two printfs */
303 p += vex_sprintf(p, "%d(%s,", am->d, s390_hreg_as_string(am->x));
304 vex_sprintf(p, "%s)", s390_hreg_as_string(am->b));
305 break;
306
307 default:
308 vpanic("s390_amode_as_string");
309 }
310
311 return buf;
312}
313
314
315/* Helper function for s390_amode_is_sane */
316static __inline__ Bool
317is_virtual_gpr(HReg reg)
318{
319 return hregIsVirtual(reg) && hregClass(reg) == HRcInt64;
320}
321
322
323/* Sanity check for an amode */
324Bool
325s390_amode_is_sane(const s390_amode *am)
326{
327 switch (am->tag) {
328 case S390_AMODE_B12:
329 return is_virtual_gpr(am->b) && fits_unsigned_12bit(am->d);
330
331 case S390_AMODE_B20:
332 return is_virtual_gpr(am->b) && fits_signed_20bit(am->d);
333
334 case S390_AMODE_BX12:
335 return is_virtual_gpr(am->b) && is_virtual_gpr(am->x) &&
336 fits_unsigned_12bit(am->d);
337
338 case S390_AMODE_BX20:
339 return is_virtual_gpr(am->b) && is_virtual_gpr(am->x) &&
340 fits_signed_20bit(am->d);
341
342 default:
343 vpanic("s390_amode_is_sane");
344 }
345}
346
347
348/* Record the register use of an amode */
florianb4df7682011-07-05 02:09:01 +0000349static void
sewardj2019a972011-03-07 16:04:07 +0000350s390_amode_get_reg_usage(HRegUsage *u, const s390_amode *am)
351{
352 switch (am->tag) {
353 case S390_AMODE_B12:
354 case S390_AMODE_B20:
355 addHRegUse(u, HRmRead, am->b);
356 return;
357
358 case S390_AMODE_BX12:
359 case S390_AMODE_BX20:
360 addHRegUse(u, HRmRead, am->b);
361 addHRegUse(u, HRmRead, am->x);
362 return;
363
364 default:
365 vpanic("s390_amode_get_reg_usage");
366 }
367}
368
369
florianb4df7682011-07-05 02:09:01 +0000370static void
sewardj2019a972011-03-07 16:04:07 +0000371s390_amode_map_regs(HRegRemap *m, s390_amode *am)
372{
373 switch (am->tag) {
374 case S390_AMODE_B12:
375 case S390_AMODE_B20:
376 am->b = lookupHRegRemap(m, am->b);
377 return;
378
379 case S390_AMODE_BX12:
380 case S390_AMODE_BX20:
381 am->b = lookupHRegRemap(m, am->b);
382 am->x = lookupHRegRemap(m, am->x);
383 return;
384
385 default:
386 vpanic("s390_amode_map_regs");
387 }
388}
389
390
sewardj2019a972011-03-07 16:04:07 +0000391void
florianb4df7682011-07-05 02:09:01 +0000392ppS390AMode(s390_amode *am)
sewardj2019a972011-03-07 16:04:07 +0000393{
394 vex_printf("%s", s390_amode_as_string(am));
395}
396
397void
florianb4df7682011-07-05 02:09:01 +0000398ppS390Instr(s390_insn *insn, Bool mode64)
sewardj2019a972011-03-07 16:04:07 +0000399{
400 vex_printf("%s", s390_insn_as_string(insn));
401}
402
403void
404ppHRegS390(HReg reg)
405{
406 vex_printf("%s", s390_hreg_as_string(reg));
407}
408
409/*------------------------------------------------------------*/
410/*--- Helpers for register allocation ---*/
411/*------------------------------------------------------------*/
412
413/* Called once per translation. */
414void
415getAllocableRegs_S390(Int *nregs, HReg **arr, Bool mode64)
416{
417 s390_hreg_get_allocable(nregs, arr);
418}
419
420
421/* Tell the register allocator how the given instruction uses the registers
422 it refers to. */
423void
florianb4df7682011-07-05 02:09:01 +0000424getRegUsage_S390Instr(HRegUsage *u, s390_insn *insn, Bool mode64)
sewardj2019a972011-03-07 16:04:07 +0000425{
426 s390_insn_get_reg_usage(u, insn);
427}
428
429
430/* Map the registers of the given instruction */
431void
florianb4df7682011-07-05 02:09:01 +0000432mapRegs_S390Instr(HRegRemap *m, s390_insn *insn, Bool mode64)
sewardj2019a972011-03-07 16:04:07 +0000433{
434 s390_insn_map_regs(m, insn);
435}
436
437
438/* Figure out if the given insn represents a reg-reg move, and if so
439 assign the source and destination to *src and *dst. If in doubt say No.
440 Used by the register allocator to do move coalescing. */
441Bool
florianb4df7682011-07-05 02:09:01 +0000442isMove_S390Instr(s390_insn *insn, HReg *src, HReg *dst)
sewardj2019a972011-03-07 16:04:07 +0000443{
444 return s390_insn_is_reg_reg_move(insn, src, dst);
445}
446
447
448/* Generate s390 spill/reload instructions under the direction of the
449 register allocator. Note it's critical these don't write the
450 condition codes. This is like an Ist_Put */
451void
452genSpill_S390(HInstr **i1, HInstr **i2, HReg rreg, Int offsetB, Bool mode64)
453{
454 s390_amode *am;
455
456 vassert(offsetB >= 0);
457 vassert(offsetB <= (1 << 12)); /* because we use b12 amode */
458 vassert(!hregIsVirtual(rreg));
459
460 *i1 = *i2 = NULL;
461
462 am = s390_amode_for_guest_state(offsetB);
463
464 switch (hregClass(rreg)) {
465 case HRcInt64:
466 case HRcFlt64:
467 *i1 = s390_insn_store(8, am, rreg);
468 return;
469
470 default:
471 ppHRegClass(hregClass(rreg));
472 vpanic("genSpill_S390: unimplemented regclass");
473 }
474}
475
476
477/* This is like an Iex_Get */
478void
479genReload_S390(HInstr **i1, HInstr **i2, HReg rreg, Int offsetB, Bool mode64)
480{
481 s390_amode *am;
482
483 vassert(offsetB >= 0);
484 vassert(offsetB <= (1 << 12)); /* because we use b12 amode */
485 vassert(!hregIsVirtual(rreg));
486
487 *i1 = *i2 = NULL;
488
489 am = s390_amode_for_guest_state(offsetB);
490
491 switch (hregClass(rreg)) {
492 case HRcInt64:
493 case HRcFlt64:
494 *i1 = s390_insn_load(8, rreg, am);
495 return;
496
497 default:
498 ppHRegClass(hregClass(rreg));
499 vpanic("genReload_S390: unimplemented regclass");
500 }
501}
502
503/* Helper function for s390_insn_get_reg_usage */
504static void
505s390_opnd_RMI_get_reg_usage(HRegUsage *u, s390_opnd_RMI op)
506{
507 switch (op.tag) {
508 case S390_OPND_REG:
509 addHRegUse(u, HRmRead, op.variant.reg);
510 break;
511
512 case S390_OPND_AMODE:
513 s390_amode_get_reg_usage(u, op.variant.am);
514 break;
515
516 case S390_OPND_IMMEDIATE:
517 break;
518
519 default:
520 vpanic("s390_opnd_RMI_get_reg_usage");
521 }
522}
523
524
525/* Tell the register allocator how the given insn uses the registers */
florianb4df7682011-07-05 02:09:01 +0000526static void
sewardj2019a972011-03-07 16:04:07 +0000527s390_insn_get_reg_usage(HRegUsage *u, const s390_insn *insn)
528{
529 initHRegUsage(u);
530
531 switch (insn->tag) {
532 case S390_INSN_LOAD:
533 addHRegUse(u, HRmWrite, insn->variant.load.dst);
534 s390_amode_get_reg_usage(u, insn->variant.load.src);
535 break;
536
537 case S390_INSN_LOAD_IMMEDIATE:
538 addHRegUse(u, HRmWrite, insn->variant.load_immediate.dst);
539 break;
540
541 case S390_INSN_STORE:
542 addHRegUse(u, HRmRead, insn->variant.store.src);
543 s390_amode_get_reg_usage(u, insn->variant.store.dst);
544 break;
545
546 case S390_INSN_MOVE:
547 addHRegUse(u, HRmRead, insn->variant.move.src);
548 addHRegUse(u, HRmWrite, insn->variant.move.dst);
549 break;
550
551 case S390_INSN_COND_MOVE:
552 s390_opnd_RMI_get_reg_usage(u, insn->variant.cond_move.src);
553 addHRegUse(u, HRmWrite, insn->variant.cond_move.dst);
554 break;
555
556 case S390_INSN_ALU:
557 addHRegUse(u, HRmWrite, insn->variant.alu.dst);
558 addHRegUse(u, HRmRead, insn->variant.alu.dst); /* op1 */
559 s390_opnd_RMI_get_reg_usage(u, insn->variant.alu.op2);
560 break;
561
562 case S390_INSN_MUL:
563 addHRegUse(u, HRmRead, insn->variant.mul.dst_lo); /* op1 */
564 addHRegUse(u, HRmWrite, insn->variant.mul.dst_lo);
565 addHRegUse(u, HRmWrite, insn->variant.mul.dst_hi);
566 s390_opnd_RMI_get_reg_usage(u, insn->variant.mul.op2);
567 break;
568
569 case S390_INSN_DIV:
570 addHRegUse(u, HRmRead, insn->variant.div.op1_lo);
571 addHRegUse(u, HRmRead, insn->variant.div.op1_hi);
572 addHRegUse(u, HRmWrite, insn->variant.div.op1_lo);
573 addHRegUse(u, HRmWrite, insn->variant.div.op1_hi);
574 s390_opnd_RMI_get_reg_usage(u, insn->variant.div.op2);
575 break;
576
577 case S390_INSN_DIVS:
578 addHRegUse(u, HRmRead, insn->variant.divs.op1);
579 addHRegUse(u, HRmWrite, insn->variant.divs.op1); /* quotient */
580 addHRegUse(u, HRmWrite, insn->variant.divs.rem); /* remainder */
581 s390_opnd_RMI_get_reg_usage(u, insn->variant.divs.op2);
582 break;
583
sewardj611b06e2011-03-24 08:57:29 +0000584 case S390_INSN_CLZ:
585 addHRegUse(u, HRmWrite, insn->variant.clz.num_bits);
586 addHRegUse(u, HRmWrite, insn->variant.clz.clobber);
587 s390_opnd_RMI_get_reg_usage(u, insn->variant.clz.src);
sewardj2019a972011-03-07 16:04:07 +0000588 break;
589
590 case S390_INSN_UNOP:
591 addHRegUse(u, HRmWrite, insn->variant.unop.dst);
592 s390_opnd_RMI_get_reg_usage(u, insn->variant.unop.src);
593 break;
594
595 case S390_INSN_TEST:
596 s390_opnd_RMI_get_reg_usage(u, insn->variant.test.src);
597 break;
598
599 case S390_INSN_CC2BOOL:
600 addHRegUse(u, HRmWrite, insn->variant.cc2bool.dst);
601 break;
602
603 case S390_INSN_CAS:
604 addHRegUse(u, HRmRead, insn->variant.cas.op1);
605 s390_amode_get_reg_usage(u, insn->variant.cas.op2);
606 addHRegUse(u, HRmRead, insn->variant.cas.op3);
607 addHRegUse(u, HRmWrite, insn->variant.cas.old_mem);
608 break;
609
610 case S390_INSN_COMPARE:
611 addHRegUse(u, HRmRead, insn->variant.compare.src1);
612 s390_opnd_RMI_get_reg_usage(u, insn->variant.compare.src2);
613 break;
614
615 case S390_INSN_BRANCH:
616 s390_opnd_RMI_get_reg_usage(u, insn->variant.branch.dst);
617 /* The destination address is loaded into S390_REGNO_RETURN_VALUE.
618 See s390_insn_branch_emit. */
619 addHRegUse(u, HRmWrite,
620 mkHReg(S390_REGNO_RETURN_VALUE, HRcInt64, False));
621 break;
622
623 case S390_INSN_HELPER_CALL: {
624 UInt i;
625
626 /* Assume that all volatile registers are clobbered. ABI says,
627 volatile registers are: r0 - r5. Valgrind's register allocator
628 does not know about r0, so we can leave that out */
629 for (i = 1; i <= 5; ++i) {
630 addHRegUse(u, HRmWrite, mkHReg(i, HRcInt64, False));
631 }
632
633 /* Ditto for floating point registers. f0 - f7 are volatile */
634 for (i = 0; i <= 7; ++i) {
635 addHRegUse(u, HRmWrite, mkHReg(i, HRcFlt64, False));
636 }
637
638 /* The registers that are used for passing arguments will be read.
639 Not all of them may, but in general we need to assume that. */
640 for (i = 0; i < insn->variant.helper_call.num_args; ++i) {
641 addHRegUse(u, HRmRead, mkHReg(s390_gprno_from_arg_index(i),
642 HRcInt64, False));
643 }
644
645 /* s390_insn_helper_call_emit also reads / writes the link register
646 and stack pointer. But those registers are not visible to the
647 register allocator. So we don't need to do anything for them. */
648 break;
649 }
650
651 case S390_INSN_BFP_TRIOP:
652 addHRegUse(u, HRmWrite, insn->variant.bfp_triop.dst);
653 addHRegUse(u, HRmRead, insn->variant.bfp_triop.dst); /* first */
654 addHRegUse(u, HRmRead, insn->variant.bfp_triop.op2); /* second */
655 addHRegUse(u, HRmRead, insn->variant.bfp_triop.op3); /* third */
656 break;
657
658 case S390_INSN_BFP_BINOP:
659 addHRegUse(u, HRmWrite, insn->variant.bfp_binop.dst);
660 addHRegUse(u, HRmRead, insn->variant.bfp_binop.dst); /* left */
661 addHRegUse(u, HRmRead, insn->variant.bfp_binop.op2); /* right */
662 break;
663
664 case S390_INSN_BFP_UNOP:
665 addHRegUse(u, HRmWrite, insn->variant.bfp_unop.dst);
666 addHRegUse(u, HRmRead, insn->variant.bfp_unop.op); /* operand */
667 break;
668
669 case S390_INSN_BFP_COMPARE:
670 addHRegUse(u, HRmWrite, insn->variant.bfp_compare.dst);
671 addHRegUse(u, HRmRead, insn->variant.bfp_compare.op1); /* left */
672 addHRegUse(u, HRmRead, insn->variant.bfp_compare.op2); /* right */
673 break;
674
675 case S390_INSN_BFP128_BINOP:
676 addHRegUse(u, HRmWrite, insn->variant.bfp128_binop.dst_hi);
677 addHRegUse(u, HRmWrite, insn->variant.bfp128_binop.dst_lo);
678 addHRegUse(u, HRmRead, insn->variant.bfp128_binop.dst_hi); /* left */
679 addHRegUse(u, HRmRead, insn->variant.bfp128_binop.dst_lo); /* left */
680 addHRegUse(u, HRmRead, insn->variant.bfp128_binop.op2_hi); /* right */
681 addHRegUse(u, HRmRead, insn->variant.bfp128_binop.op2_lo); /* right */
682 break;
683
684 case S390_INSN_BFP128_COMPARE:
685 addHRegUse(u, HRmWrite, insn->variant.bfp128_compare.dst);
686 addHRegUse(u, HRmRead, insn->variant.bfp128_compare.op1_hi); /* left */
687 addHRegUse(u, HRmRead, insn->variant.bfp128_compare.op1_lo); /* left */
688 addHRegUse(u, HRmRead, insn->variant.bfp128_compare.op2_hi); /* right */
689 addHRegUse(u, HRmRead, insn->variant.bfp128_compare.op2_lo); /* right */
690 break;
691
692 case S390_INSN_BFP128_UNOP:
693 addHRegUse(u, HRmWrite, insn->variant.bfp128_unop.dst_hi);
694 addHRegUse(u, HRmWrite, insn->variant.bfp128_unop.dst_lo);
695 addHRegUse(u, HRmRead, insn->variant.bfp128_unop.op_hi);
696 addHRegUse(u, HRmRead, insn->variant.bfp128_unop.op_lo);
697 break;
698
699 case S390_INSN_BFP128_CONVERT_TO:
700 addHRegUse(u, HRmWrite, insn->variant.bfp128_unop.dst_hi);
701 addHRegUse(u, HRmWrite, insn->variant.bfp128_unop.dst_lo);
702 addHRegUse(u, HRmRead, insn->variant.bfp128_unop.op_hi);
703 break;
704
705 case S390_INSN_BFP128_CONVERT_FROM:
706 addHRegUse(u, HRmWrite, insn->variant.bfp128_unop.dst_hi);
707 addHRegUse(u, HRmRead, insn->variant.bfp128_unop.op_hi);
708 addHRegUse(u, HRmRead, insn->variant.bfp128_unop.op_lo);
709 break;
710
sewardja52e37e2011-04-28 18:48:06 +0000711 case S390_INSN_MFENCE:
712 break;
713
sewardj2019a972011-03-07 16:04:07 +0000714 default:
715 vpanic("s390_insn_get_reg_usage");
716 }
717}
718
719
720/* Helper function for s390_insn_map_regs */
721static void
722s390_opnd_RMI_map_regs(HRegRemap *m, s390_opnd_RMI *op)
723{
724 switch (op->tag) {
725 case S390_OPND_REG:
726 op->variant.reg = lookupHRegRemap(m, op->variant.reg);
727 break;
728
729 case S390_OPND_IMMEDIATE:
730 break;
731
732 case S390_OPND_AMODE:
733 s390_amode_map_regs(m, op->variant.am);
734 break;
735
736 default:
737 vpanic("s390_opnd_RMI_map_regs");
738 }
739}
740
741
florianb4df7682011-07-05 02:09:01 +0000742static void
sewardj2019a972011-03-07 16:04:07 +0000743s390_insn_map_regs(HRegRemap *m, s390_insn *insn)
744{
745 switch (insn->tag) {
746 case S390_INSN_LOAD:
747 insn->variant.load.dst = lookupHRegRemap(m, insn->variant.load.dst);
748 s390_amode_map_regs(m, insn->variant.load.src);
749 break;
750
751 case S390_INSN_STORE:
752 s390_amode_map_regs(m, insn->variant.store.dst);
753 insn->variant.store.src = lookupHRegRemap(m, insn->variant.store.src);
754 break;
755
756 case S390_INSN_MOVE:
757 insn->variant.move.dst = lookupHRegRemap(m, insn->variant.move.dst);
758 insn->variant.move.src = lookupHRegRemap(m, insn->variant.move.src);
759 break;
760
761 case S390_INSN_COND_MOVE:
762 insn->variant.cond_move.dst = lookupHRegRemap(m, insn->variant.cond_move.dst);
763 s390_opnd_RMI_map_regs(m, &insn->variant.cond_move.src);
764 break;
765
766 case S390_INSN_LOAD_IMMEDIATE:
767 insn->variant.load_immediate.dst =
768 lookupHRegRemap(m, insn->variant.load_immediate.dst);
769 break;
770
771 case S390_INSN_ALU:
772 insn->variant.alu.dst = lookupHRegRemap(m, insn->variant.alu.dst);
773 s390_opnd_RMI_map_regs(m, &insn->variant.alu.op2);
774 break;
775
776 case S390_INSN_MUL:
777 insn->variant.mul.dst_hi = lookupHRegRemap(m, insn->variant.mul.dst_hi);
778 insn->variant.mul.dst_lo = lookupHRegRemap(m, insn->variant.mul.dst_lo);
779 s390_opnd_RMI_map_regs(m, &insn->variant.mul.op2);
780 break;
781
782 case S390_INSN_DIV:
783 insn->variant.div.op1_hi = lookupHRegRemap(m, insn->variant.div.op1_hi);
784 insn->variant.div.op1_lo = lookupHRegRemap(m, insn->variant.div.op1_lo);
785 s390_opnd_RMI_map_regs(m, &insn->variant.div.op2);
786 break;
787
788 case S390_INSN_DIVS:
789 insn->variant.divs.op1 = lookupHRegRemap(m, insn->variant.divs.op1);
790 insn->variant.divs.rem = lookupHRegRemap(m, insn->variant.divs.rem);
791 s390_opnd_RMI_map_regs(m, &insn->variant.divs.op2);
792 break;
793
sewardj611b06e2011-03-24 08:57:29 +0000794 case S390_INSN_CLZ:
795 insn->variant.clz.num_bits = lookupHRegRemap(m, insn->variant.clz.num_bits);
796 insn->variant.clz.clobber = lookupHRegRemap(m, insn->variant.clz.clobber);
797 s390_opnd_RMI_map_regs(m, &insn->variant.clz.src);
sewardj2019a972011-03-07 16:04:07 +0000798 break;
799
800 case S390_INSN_UNOP:
801 insn->variant.unop.dst = lookupHRegRemap(m, insn->variant.unop.dst);
802 s390_opnd_RMI_map_regs(m, &insn->variant.unop.src);
803 break;
804
805 case S390_INSN_TEST:
806 s390_opnd_RMI_map_regs(m, &insn->variant.test.src);
807 break;
808
809 case S390_INSN_CC2BOOL:
810 insn->variant.cc2bool.dst = lookupHRegRemap(m, insn->variant.cc2bool.dst);
811 break;
812
813 case S390_INSN_CAS:
814 insn->variant.cas.op1 = lookupHRegRemap(m, insn->variant.cas.op1);
815 s390_amode_map_regs(m, insn->variant.cas.op2);
816 insn->variant.cas.op3 = lookupHRegRemap(m, insn->variant.cas.op3);
817 insn->variant.cas.old_mem = lookupHRegRemap(m, insn->variant.cas.old_mem);
818 break;
819
820 case S390_INSN_COMPARE:
821 insn->variant.compare.src1 = lookupHRegRemap(m, insn->variant.compare.src1);
822 s390_opnd_RMI_map_regs(m, &insn->variant.compare.src2);
823 break;
824
825 case S390_INSN_BRANCH:
826 s390_opnd_RMI_map_regs(m, &insn->variant.branch.dst);
827 /* No need to map S390_REGNO_RETURN_VALUE. It's not virtual */
828 break;
829
830 case S390_INSN_HELPER_CALL:
831 /* s390_insn_helper_call_emit also reads / writes the link register
832 and stack pointer. But those registers are not visible to the
833 register allocator. So we don't need to do anything for them.
834 As for the arguments of the helper call -- they will be loaded into
835 non-virtual registers. Again, we don't need to do anything for those
836 here. */
837 break;
838
839 case S390_INSN_BFP_TRIOP:
840 insn->variant.bfp_triop.dst = lookupHRegRemap(m, insn->variant.bfp_triop.dst);
841 insn->variant.bfp_triop.op2 = lookupHRegRemap(m, insn->variant.bfp_triop.op2);
842 insn->variant.bfp_triop.op3 = lookupHRegRemap(m, insn->variant.bfp_triop.op3);
843 break;
844
845 case S390_INSN_BFP_BINOP:
846 insn->variant.bfp_binop.dst = lookupHRegRemap(m, insn->variant.bfp_binop.dst);
847 insn->variant.bfp_binop.op2 = lookupHRegRemap(m, insn->variant.bfp_binop.op2);
848 break;
849
850 case S390_INSN_BFP_UNOP:
851 insn->variant.bfp_unop.dst = lookupHRegRemap(m, insn->variant.bfp_unop.dst);
852 insn->variant.bfp_unop.op = lookupHRegRemap(m, insn->variant.bfp_unop.op);
853 break;
854
855 case S390_INSN_BFP_COMPARE:
856 insn->variant.bfp_compare.dst = lookupHRegRemap(m, insn->variant.bfp_compare.dst);
857 insn->variant.bfp_compare.op1 = lookupHRegRemap(m, insn->variant.bfp_compare.op1);
858 insn->variant.bfp_compare.op2 = lookupHRegRemap(m, insn->variant.bfp_compare.op2);
859 break;
860
861 case S390_INSN_BFP128_BINOP:
862 insn->variant.bfp128_binop.dst_hi =
863 lookupHRegRemap(m, insn->variant.bfp128_binop.dst_hi);
864 insn->variant.bfp128_binop.dst_lo =
865 lookupHRegRemap(m, insn->variant.bfp128_binop.dst_lo);
866 insn->variant.bfp128_binop.op2_hi =
867 lookupHRegRemap(m, insn->variant.bfp128_binop.op2_hi);
868 insn->variant.bfp128_binop.op2_lo =
869 lookupHRegRemap(m, insn->variant.bfp128_binop.op2_lo);
870 break;
871
872 case S390_INSN_BFP128_COMPARE:
873 insn->variant.bfp128_compare.dst =
874 lookupHRegRemap(m, insn->variant.bfp128_compare.dst);
875 insn->variant.bfp128_compare.op1_hi =
876 lookupHRegRemap(m, insn->variant.bfp128_compare.op1_hi);
877 insn->variant.bfp128_compare.op1_lo =
878 lookupHRegRemap(m, insn->variant.bfp128_compare.op1_lo);
879 insn->variant.bfp128_compare.op2_hi =
880 lookupHRegRemap(m, insn->variant.bfp128_compare.op2_hi);
881 insn->variant.bfp128_compare.op2_lo =
882 lookupHRegRemap(m, insn->variant.bfp128_compare.op2_lo);
883 break;
884
885 case S390_INSN_BFP128_UNOP:
886 insn->variant.bfp128_unop.dst_hi =
887 lookupHRegRemap(m, insn->variant.bfp128_unop.dst_hi);
888 insn->variant.bfp128_unop.dst_lo =
889 lookupHRegRemap(m, insn->variant.bfp128_unop.dst_lo);
890 insn->variant.bfp128_unop.op_hi =
891 lookupHRegRemap(m, insn->variant.bfp128_unop.op_hi);
892 insn->variant.bfp128_unop.op_lo =
893 lookupHRegRemap(m, insn->variant.bfp128_unop.op_lo);
894 break;
895
896 case S390_INSN_BFP128_CONVERT_TO:
897 insn->variant.bfp128_unop.dst_hi =
898 lookupHRegRemap(m, insn->variant.bfp128_unop.dst_hi);
899 insn->variant.bfp128_unop.dst_lo =
900 lookupHRegRemap(m, insn->variant.bfp128_unop.dst_lo);
901 insn->variant.bfp128_unop.op_hi =
902 lookupHRegRemap(m, insn->variant.bfp128_unop.op_hi);
903 break;
904
905 case S390_INSN_BFP128_CONVERT_FROM:
906 insn->variant.bfp128_unop.dst_hi =
907 lookupHRegRemap(m, insn->variant.bfp128_unop.dst_hi);
908 insn->variant.bfp128_unop.op_hi =
909 lookupHRegRemap(m, insn->variant.bfp128_unop.op_hi);
910 insn->variant.bfp128_unop.op_lo =
911 lookupHRegRemap(m, insn->variant.bfp128_unop.op_lo);
912 break;
913
sewardja52e37e2011-04-28 18:48:06 +0000914 case S390_INSN_MFENCE:
915 break;
916
sewardj2019a972011-03-07 16:04:07 +0000917 default:
918 vpanic("s390_insn_map_regs");
919 }
920}
921
922
923/* Return True, if INSN is a move between two registers of the same class.
924 In that case assign the source and destination registers to SRC and DST,
925 respectively. */
florianb4df7682011-07-05 02:09:01 +0000926static Bool
sewardj2019a972011-03-07 16:04:07 +0000927s390_insn_is_reg_reg_move(const s390_insn *insn, HReg *src, HReg *dst)
928{
929 if (insn->tag == S390_INSN_MOVE &&
930 hregClass(insn->variant.move.src) == hregClass(insn->variant.move.dst)) {
931 *src = insn->variant.move.src;
932 *dst = insn->variant.move.dst;
933 return True;
934 }
935
936 return False;
937}
938
939
sewardj2019a972011-03-07 16:04:07 +0000940/*------------------------------------------------------------*/
941/*--- Functions to emit a sequence of bytes ---*/
942/*------------------------------------------------------------*/
943
sewardj2019a972011-03-07 16:04:07 +0000944static __inline__ UChar *
945emit_2bytes(UChar *p, ULong val)
946{
947 return (UChar *)__builtin_memcpy(p, ((UChar *)&val) + 6, 2) + 2;
948}
949
950
951static __inline__ UChar *
952emit_4bytes(UChar *p, ULong val)
953{
954 return (UChar *)__builtin_memcpy(p, ((UChar *)&val) + 4, 4) + 4;
955}
956
957
958static __inline__ UChar *
959emit_6bytes(UChar *p, ULong val)
960{
961 return (UChar *)__builtin_memcpy(p, ((UChar *)&val) + 2, 6) + 6;
962}
963
964
965/*------------------------------------------------------------*/
966/*--- Functions to emit various instruction formats ---*/
967/*------------------------------------------------------------*/
968
sewardj2019a972011-03-07 16:04:07 +0000969static UChar *
970emit_RI(UChar *p, UInt op, UChar r1, UShort i2)
971{
972 ULong the_insn = op;
973
974 the_insn |= ((ULong)r1) << 20;
975 the_insn |= ((ULong)i2) << 0;
976
977 return emit_4bytes(p, the_insn);
978}
979
980
981static UChar *
982emit_RIL(UChar *p, ULong op, UChar r1, UInt i2)
983{
984 ULong the_insn = op;
985
986 the_insn |= ((ULong)r1) << 36;
987 the_insn |= ((ULong)i2) << 0;
988
989 return emit_6bytes(p, the_insn);
990}
991
992
993static UChar *
994emit_RR(UChar *p, UInt op, UChar r1, UChar r2)
995{
996 ULong the_insn = op;
997
998 the_insn |= ((ULong)r1) << 4;
999 the_insn |= ((ULong)r2) << 0;
1000
1001 return emit_2bytes(p, the_insn);
1002}
1003
1004
1005static UChar *
1006emit_RRE(UChar *p, UInt op, UChar r1, UChar r2)
1007{
1008 ULong the_insn = op;
1009
1010 the_insn |= ((ULong)r1) << 4;
1011 the_insn |= ((ULong)r2) << 0;
1012
1013 return emit_4bytes(p, the_insn);
1014}
1015
1016
1017static UChar *
1018emit_RRF(UChar *p, UInt op, UChar r1, UChar r3, UChar r2)
1019{
1020 ULong the_insn = op;
1021
1022 the_insn |= ((ULong)r1) << 12;
1023 the_insn |= ((ULong)r3) << 4;
1024 the_insn |= ((ULong)r2) << 0;
1025
1026 return emit_4bytes(p, the_insn);
1027}
1028
1029
1030static UChar *
1031emit_RRF3(UChar *p, UInt op, UChar r3, UChar r1, UChar r2)
1032{
1033 ULong the_insn = op;
1034
1035 the_insn |= ((ULong)r3) << 12;
1036 the_insn |= ((ULong)r1) << 4;
1037 the_insn |= ((ULong)r2) << 0;
1038
1039 return emit_4bytes(p, the_insn);
1040}
1041
1042
1043static UChar *
1044emit_RS(UChar *p, UInt op, UChar r1, UChar r3, UChar b2, UShort d2)
1045{
1046 ULong the_insn = op;
1047
1048 the_insn |= ((ULong)r1) << 20;
1049 the_insn |= ((ULong)r3) << 16;
1050 the_insn |= ((ULong)b2) << 12;
1051 the_insn |= ((ULong)d2) << 0;
1052
1053 return emit_4bytes(p, the_insn);
1054}
1055
1056
1057static UChar *
1058emit_RSY(UChar *p, ULong op, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
1059{
1060 ULong the_insn = op;
1061
1062 the_insn |= ((ULong)r1) << 36;
1063 the_insn |= ((ULong)r3) << 32;
1064 the_insn |= ((ULong)b2) << 28;
1065 the_insn |= ((ULong)dl2) << 16;
1066 the_insn |= ((ULong)dh2) << 8;
1067
1068 return emit_6bytes(p, the_insn);
1069}
1070
1071
1072static UChar *
1073emit_RX(UChar *p, UInt op, UChar r1, UChar x2, UChar b2, UShort d2)
1074{
1075 ULong the_insn = op;
1076
1077 the_insn |= ((ULong)r1) << 20;
1078 the_insn |= ((ULong)x2) << 16;
1079 the_insn |= ((ULong)b2) << 12;
1080 the_insn |= ((ULong)d2) << 0;
1081
1082 return emit_4bytes(p, the_insn);
1083}
1084
1085
1086static UChar *
1087emit_RXY(UChar *p, ULong op, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1088{
1089 ULong the_insn = op;
1090
1091 the_insn |= ((ULong)r1) << 36;
1092 the_insn |= ((ULong)x2) << 32;
1093 the_insn |= ((ULong)b2) << 28;
1094 the_insn |= ((ULong)dl2) << 16;
1095 the_insn |= ((ULong)dh2) << 8;
1096
1097 return emit_6bytes(p, the_insn);
1098}
1099
1100
1101static UChar *
1102emit_S(UChar *p, UInt op, UChar b2, UShort d2)
1103{
1104 ULong the_insn = op;
1105
1106 the_insn |= ((ULong)b2) << 12;
1107 the_insn |= ((ULong)d2) << 0;
1108
1109 return emit_4bytes(p, the_insn);
1110}
1111
1112
1113/*------------------------------------------------------------*/
1114/*--- Functions to emit particular instructions ---*/
1115/*------------------------------------------------------------*/
1116
sewardj9d31dfd2011-03-15 12:36:44 +00001117static UChar *
sewardj2019a972011-03-07 16:04:07 +00001118s390_emit_AR(UChar *p, UChar r1, UChar r2)
1119{
sewardj7ee97522011-05-09 21:45:04 +00001120 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001121 s390_disasm(ENC3(MNM, GPR, GPR), "ar", r1, r2);
1122
1123 return emit_RR(p, 0x1a00, r1, r2);
1124}
1125
1126
sewardj9d31dfd2011-03-15 12:36:44 +00001127static UChar *
sewardj2019a972011-03-07 16:04:07 +00001128s390_emit_AGR(UChar *p, UChar r1, UChar r2)
1129{
sewardj7ee97522011-05-09 21:45:04 +00001130 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001131 s390_disasm(ENC3(MNM, GPR, GPR), "agr", r1, r2);
1132
1133 return emit_RRE(p, 0xb9080000, r1, r2);
1134}
1135
1136
sewardj9d31dfd2011-03-15 12:36:44 +00001137static UChar *
sewardj2019a972011-03-07 16:04:07 +00001138s390_emit_A(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
1139{
sewardj7ee97522011-05-09 21:45:04 +00001140 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001141 s390_disasm(ENC3(MNM, GPR, UDXB), "a", r1, d2, x2, b2);
1142
1143 return emit_RX(p, 0x5a000000, r1, x2, b2, d2);
1144}
1145
1146
sewardj9d31dfd2011-03-15 12:36:44 +00001147static UChar *
sewardj2019a972011-03-07 16:04:07 +00001148s390_emit_AY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1149{
sewardj652b56a2011-04-13 15:38:17 +00001150 vassert(s390_host_has_ldisp);
1151
sewardj7ee97522011-05-09 21:45:04 +00001152 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001153 s390_disasm(ENC3(MNM, GPR, SDXB), "ay", r1, dh2, dl2, x2, b2);
1154
1155 return emit_RXY(p, 0xe3000000005aULL, r1, x2, b2, dl2, dh2);
1156}
1157
1158
sewardj9d31dfd2011-03-15 12:36:44 +00001159static UChar *
sewardj2019a972011-03-07 16:04:07 +00001160s390_emit_AG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1161{
sewardj652b56a2011-04-13 15:38:17 +00001162 vassert(s390_host_has_ldisp || dh2 == 0);
1163
sewardj7ee97522011-05-09 21:45:04 +00001164 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001165 s390_disasm(ENC3(MNM, GPR, SDXB), "ag", r1, dh2, dl2, x2, b2);
1166
1167 return emit_RXY(p, 0xe30000000008ULL, r1, x2, b2, dl2, dh2);
1168}
1169
1170
sewardj9d31dfd2011-03-15 12:36:44 +00001171static UChar *
sewardj2019a972011-03-07 16:04:07 +00001172s390_emit_AFI(UChar *p, UChar r1, UInt i2)
1173{
sewardj652b56a2011-04-13 15:38:17 +00001174 vassert(s390_host_has_eimm);
1175
sewardj7ee97522011-05-09 21:45:04 +00001176 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001177 s390_disasm(ENC3(MNM, GPR, INT), "afi", r1, i2);
1178
1179 return emit_RIL(p, 0xc20900000000ULL, r1, i2);
1180}
1181
1182
sewardj9d31dfd2011-03-15 12:36:44 +00001183static UChar *
sewardj2019a972011-03-07 16:04:07 +00001184s390_emit_AGFI(UChar *p, UChar r1, UInt i2)
1185{
sewardj652b56a2011-04-13 15:38:17 +00001186 vassert(s390_host_has_eimm);
1187
sewardj7ee97522011-05-09 21:45:04 +00001188 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001189 s390_disasm(ENC3(MNM, GPR, INT), "agfi", r1, i2);
1190
1191 return emit_RIL(p, 0xc20800000000ULL, r1, i2);
1192}
1193
1194
sewardj9d31dfd2011-03-15 12:36:44 +00001195static UChar *
sewardj2019a972011-03-07 16:04:07 +00001196s390_emit_AH(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
1197{
sewardj7ee97522011-05-09 21:45:04 +00001198 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001199 s390_disasm(ENC3(MNM, GPR, UDXB), "ah", r1, d2, x2, b2);
1200
1201 return emit_RX(p, 0x4a000000, r1, x2, b2, d2);
1202}
1203
1204
sewardj9d31dfd2011-03-15 12:36:44 +00001205static UChar *
sewardj2019a972011-03-07 16:04:07 +00001206s390_emit_AHY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1207{
sewardj652b56a2011-04-13 15:38:17 +00001208 vassert(s390_host_has_ldisp);
1209
sewardj7ee97522011-05-09 21:45:04 +00001210 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001211 s390_disasm(ENC3(MNM, GPR, SDXB), "ahy", r1, dh2, dl2, x2, b2);
1212
1213 return emit_RXY(p, 0xe3000000007aULL, r1, x2, b2, dl2, dh2);
1214}
1215
1216
sewardj9d31dfd2011-03-15 12:36:44 +00001217static UChar *
sewardj2019a972011-03-07 16:04:07 +00001218s390_emit_AHI(UChar *p, UChar r1, UShort i2)
1219{
sewardj7ee97522011-05-09 21:45:04 +00001220 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001221 s390_disasm(ENC3(MNM, GPR, INT), "ahi", r1, (Int)(Short)i2);
1222
1223 return emit_RI(p, 0xa70a0000, r1, i2);
1224}
1225
1226
sewardj9d31dfd2011-03-15 12:36:44 +00001227static UChar *
sewardj2019a972011-03-07 16:04:07 +00001228s390_emit_AGHI(UChar *p, UChar r1, UShort i2)
1229{
sewardj7ee97522011-05-09 21:45:04 +00001230 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001231 s390_disasm(ENC3(MNM, GPR, INT), "aghi", r1, (Int)(Short)i2);
1232
1233 return emit_RI(p, 0xa70b0000, r1, i2);
1234}
1235
1236
sewardj9d31dfd2011-03-15 12:36:44 +00001237static UChar *
sewardj2019a972011-03-07 16:04:07 +00001238s390_emit_NR(UChar *p, UChar r1, UChar r2)
1239{
sewardj7ee97522011-05-09 21:45:04 +00001240 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001241 s390_disasm(ENC3(MNM, GPR, GPR), "nr", r1, r2);
1242
1243 return emit_RR(p, 0x1400, r1, r2);
1244}
1245
1246
sewardj9d31dfd2011-03-15 12:36:44 +00001247static UChar *
sewardj2019a972011-03-07 16:04:07 +00001248s390_emit_NGR(UChar *p, UChar r1, UChar r2)
1249{
sewardj7ee97522011-05-09 21:45:04 +00001250 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001251 s390_disasm(ENC3(MNM, GPR, GPR), "ngr", r1, r2);
1252
1253 return emit_RRE(p, 0xb9800000, r1, r2);
1254}
1255
1256
sewardj9d31dfd2011-03-15 12:36:44 +00001257static UChar *
sewardj2019a972011-03-07 16:04:07 +00001258s390_emit_N(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
1259{
sewardj7ee97522011-05-09 21:45:04 +00001260 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001261 s390_disasm(ENC3(MNM, GPR, UDXB), "n", r1, d2, x2, b2);
1262
1263 return emit_RX(p, 0x54000000, r1, x2, b2, d2);
1264}
1265
1266
sewardj9d31dfd2011-03-15 12:36:44 +00001267static UChar *
sewardj2019a972011-03-07 16:04:07 +00001268s390_emit_NY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1269{
sewardj652b56a2011-04-13 15:38:17 +00001270 vassert(s390_host_has_ldisp);
1271
sewardj7ee97522011-05-09 21:45:04 +00001272 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001273 s390_disasm(ENC3(MNM, GPR, SDXB), "ny", r1, dh2, dl2, x2, b2);
1274
1275 return emit_RXY(p, 0xe30000000054ULL, r1, x2, b2, dl2, dh2);
1276}
1277
1278
sewardj9d31dfd2011-03-15 12:36:44 +00001279static UChar *
sewardj2019a972011-03-07 16:04:07 +00001280s390_emit_NG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1281{
sewardj652b56a2011-04-13 15:38:17 +00001282 vassert(s390_host_has_ldisp || dh2 == 0);
1283
sewardj7ee97522011-05-09 21:45:04 +00001284 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001285 s390_disasm(ENC3(MNM, GPR, SDXB), "ng", r1, dh2, dl2, x2, b2);
1286
1287 return emit_RXY(p, 0xe30000000080ULL, r1, x2, b2, dl2, dh2);
1288}
1289
1290
sewardj9d31dfd2011-03-15 12:36:44 +00001291static UChar *
sewardj2019a972011-03-07 16:04:07 +00001292s390_emit_NIHF(UChar *p, UChar r1, UInt i2)
1293{
sewardj652b56a2011-04-13 15:38:17 +00001294 vassert(s390_host_has_eimm);
1295
sewardj7ee97522011-05-09 21:45:04 +00001296 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001297 s390_disasm(ENC3(MNM, GPR, UINT), "nihf", r1, i2);
1298
1299 return emit_RIL(p, 0xc00a00000000ULL, r1, i2);
1300}
1301
1302
sewardj9d31dfd2011-03-15 12:36:44 +00001303static UChar *
sewardj2019a972011-03-07 16:04:07 +00001304s390_emit_NILF(UChar *p, UChar r1, UInt i2)
1305{
sewardj652b56a2011-04-13 15:38:17 +00001306 vassert(s390_host_has_eimm);
1307
sewardj7ee97522011-05-09 21:45:04 +00001308 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001309 s390_disasm(ENC3(MNM, GPR, UINT), "nilf", r1, i2);
1310
1311 return emit_RIL(p, 0xc00b00000000ULL, r1, i2);
1312}
1313
1314
sewardj9d31dfd2011-03-15 12:36:44 +00001315static UChar *
sewardj2019a972011-03-07 16:04:07 +00001316s390_emit_NILL(UChar *p, UChar r1, UShort i2)
1317{
sewardj7ee97522011-05-09 21:45:04 +00001318 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001319 s390_disasm(ENC3(MNM, GPR, UINT), "nill", r1, i2);
1320
1321 return emit_RI(p, 0xa5070000, r1, i2);
1322}
1323
1324
sewardj9d31dfd2011-03-15 12:36:44 +00001325static UChar *
sewardj2019a972011-03-07 16:04:07 +00001326s390_emit_BASR(UChar *p, UChar r1, UChar r2)
1327{
sewardj7ee97522011-05-09 21:45:04 +00001328 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001329 s390_disasm(ENC3(MNM, GPR, GPR), "basr", r1, r2);
1330
1331 return emit_RR(p, 0x0d00, r1, r2);
1332}
1333
1334
sewardj9d31dfd2011-03-15 12:36:44 +00001335static UChar *
sewardj2019a972011-03-07 16:04:07 +00001336s390_emit_BCR(UChar *p, UChar r1, UChar r2)
1337{
sewardj7ee97522011-05-09 21:45:04 +00001338 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001339 s390_disasm(ENC2(XMNM, GPR), S390_XMNM_BCR, r1, r2);
1340
1341 return emit_RR(p, 0x0700, r1, r2);
1342}
1343
1344
sewardj9d31dfd2011-03-15 12:36:44 +00001345static UChar *
sewardj2019a972011-03-07 16:04:07 +00001346s390_emit_BRC(UChar *p, UChar r1, UShort i2)
1347{
sewardj7ee97522011-05-09 21:45:04 +00001348 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001349 s390_disasm(ENC2(XMNM, PCREL), S390_XMNM_BRC, r1, (Int)(Short)i2);
1350
1351 return emit_RI(p, 0xa7040000, r1, i2);
1352}
1353
1354
sewardj9d31dfd2011-03-15 12:36:44 +00001355static UChar *
sewardj2019a972011-03-07 16:04:07 +00001356s390_emit_CR(UChar *p, UChar r1, UChar r2)
1357{
sewardj7ee97522011-05-09 21:45:04 +00001358 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001359 s390_disasm(ENC3(MNM, GPR, GPR), "cr", r1, r2);
1360
1361 return emit_RR(p, 0x1900, r1, r2);
1362}
1363
1364
sewardj9d31dfd2011-03-15 12:36:44 +00001365static UChar *
sewardj2019a972011-03-07 16:04:07 +00001366s390_emit_CGR(UChar *p, UChar r1, UChar r2)
1367{
sewardj7ee97522011-05-09 21:45:04 +00001368 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001369 s390_disasm(ENC3(MNM, GPR, GPR), "cgr", r1, r2);
1370
1371 return emit_RRE(p, 0xb9200000, r1, r2);
1372}
1373
1374
sewardj9d31dfd2011-03-15 12:36:44 +00001375static UChar *
sewardj2019a972011-03-07 16:04:07 +00001376s390_emit_C(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
1377{
sewardj7ee97522011-05-09 21:45:04 +00001378 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001379 s390_disasm(ENC3(MNM, GPR, UDXB), "c", r1, d2, x2, b2);
1380
1381 return emit_RX(p, 0x59000000, r1, x2, b2, d2);
1382}
1383
1384
sewardj9d31dfd2011-03-15 12:36:44 +00001385static UChar *
sewardj2019a972011-03-07 16:04:07 +00001386s390_emit_CY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1387{
sewardj652b56a2011-04-13 15:38:17 +00001388 vassert(s390_host_has_ldisp);
1389
sewardj7ee97522011-05-09 21:45:04 +00001390 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001391 s390_disasm(ENC3(MNM, GPR, SDXB), "cy", r1, dh2, dl2, x2, b2);
1392
1393 return emit_RXY(p, 0xe30000000059ULL, r1, x2, b2, dl2, dh2);
1394}
1395
1396
sewardj9d31dfd2011-03-15 12:36:44 +00001397static UChar *
sewardj2019a972011-03-07 16:04:07 +00001398s390_emit_CG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1399{
sewardj652b56a2011-04-13 15:38:17 +00001400 vassert(s390_host_has_ldisp || dh2 == 0);
1401
sewardj7ee97522011-05-09 21:45:04 +00001402 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001403 s390_disasm(ENC3(MNM, GPR, SDXB), "cg", r1, dh2, dl2, x2, b2);
1404
1405 return emit_RXY(p, 0xe30000000020ULL, r1, x2, b2, dl2, dh2);
1406}
1407
1408
sewardj9d31dfd2011-03-15 12:36:44 +00001409static UChar *
sewardj2019a972011-03-07 16:04:07 +00001410s390_emit_CFI(UChar *p, UChar r1, UInt i2)
1411{
sewardj652b56a2011-04-13 15:38:17 +00001412 vassert(s390_host_has_eimm);
1413
sewardj7ee97522011-05-09 21:45:04 +00001414 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001415 s390_disasm(ENC3(MNM, GPR, INT), "cfi", r1, i2);
1416
1417 return emit_RIL(p, 0xc20d00000000ULL, r1, i2);
1418}
1419
1420
sewardj9d31dfd2011-03-15 12:36:44 +00001421static UChar *
sewardj2019a972011-03-07 16:04:07 +00001422s390_emit_CS(UChar *p, UChar r1, UChar r3, UChar b2, UShort d2)
1423{
sewardj7ee97522011-05-09 21:45:04 +00001424 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001425 s390_disasm(ENC4(MNM, GPR, GPR, UDXB), "cs", r1, r3, d2, 0, b2);
1426
1427 return emit_RS(p, 0xba000000, r1, r3, b2, d2);
1428}
1429
1430
sewardj9d31dfd2011-03-15 12:36:44 +00001431static UChar *
sewardj2019a972011-03-07 16:04:07 +00001432s390_emit_CSY(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
1433{
sewardj652b56a2011-04-13 15:38:17 +00001434 vassert(s390_host_has_ldisp);
1435
sewardj7ee97522011-05-09 21:45:04 +00001436 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001437 s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "csy", r1, r3, dh2, dl2, 0, b2);
1438
1439 return emit_RSY(p, 0xeb0000000014ULL, r1, r3, b2, dl2, dh2);
1440}
1441
1442
sewardj9d31dfd2011-03-15 12:36:44 +00001443static UChar *
sewardj2019a972011-03-07 16:04:07 +00001444s390_emit_CSG(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
1445{
sewardj652b56a2011-04-13 15:38:17 +00001446 vassert(s390_host_has_ldisp || dh2 == 0);
1447
sewardj7ee97522011-05-09 21:45:04 +00001448 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001449 s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "csg", r1, r3, dh2, dl2, 0, b2);
1450
1451 return emit_RSY(p, 0xeb0000000030ULL, r1, r3, b2, dl2, dh2);
1452}
1453
1454
sewardj9d31dfd2011-03-15 12:36:44 +00001455static UChar *
sewardj2019a972011-03-07 16:04:07 +00001456s390_emit_CLR(UChar *p, UChar r1, UChar r2)
1457{
sewardj7ee97522011-05-09 21:45:04 +00001458 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001459 s390_disasm(ENC3(MNM, GPR, GPR), "clr", r1, r2);
1460
1461 return emit_RR(p, 0x1500, r1, r2);
1462}
1463
1464
sewardj9d31dfd2011-03-15 12:36:44 +00001465static UChar *
sewardj2019a972011-03-07 16:04:07 +00001466s390_emit_CLGR(UChar *p, UChar r1, UChar r2)
1467{
sewardj7ee97522011-05-09 21:45:04 +00001468 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001469 s390_disasm(ENC3(MNM, GPR, GPR), "clgr", r1, r2);
1470
1471 return emit_RRE(p, 0xb9210000, r1, r2);
1472}
1473
1474
sewardj9d31dfd2011-03-15 12:36:44 +00001475static UChar *
sewardj2019a972011-03-07 16:04:07 +00001476s390_emit_CL(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
1477{
sewardj7ee97522011-05-09 21:45:04 +00001478 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001479 s390_disasm(ENC3(MNM, GPR, UDXB), "cl", r1, d2, x2, b2);
1480
1481 return emit_RX(p, 0x55000000, r1, x2, b2, d2);
1482}
1483
1484
sewardj9d31dfd2011-03-15 12:36:44 +00001485static UChar *
sewardj2019a972011-03-07 16:04:07 +00001486s390_emit_CLY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1487{
sewardj652b56a2011-04-13 15:38:17 +00001488 vassert(s390_host_has_ldisp);
1489
sewardj7ee97522011-05-09 21:45:04 +00001490 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001491 s390_disasm(ENC3(MNM, GPR, SDXB), "cly", r1, dh2, dl2, x2, b2);
1492
1493 return emit_RXY(p, 0xe30000000055ULL, r1, x2, b2, dl2, dh2);
1494}
1495
1496
sewardj9d31dfd2011-03-15 12:36:44 +00001497static UChar *
sewardj2019a972011-03-07 16:04:07 +00001498s390_emit_CLG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1499{
sewardj652b56a2011-04-13 15:38:17 +00001500 vassert(s390_host_has_ldisp || dh2 == 0);
1501
sewardj7ee97522011-05-09 21:45:04 +00001502 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001503 s390_disasm(ENC3(MNM, GPR, SDXB), "clg", r1, dh2, dl2, x2, b2);
1504
1505 return emit_RXY(p, 0xe30000000021ULL, r1, x2, b2, dl2, dh2);
1506}
1507
1508
sewardj9d31dfd2011-03-15 12:36:44 +00001509static UChar *
sewardj2019a972011-03-07 16:04:07 +00001510s390_emit_CLFI(UChar *p, UChar r1, UInt i2)
1511{
sewardj652b56a2011-04-13 15:38:17 +00001512 vassert(s390_host_has_eimm);
1513
sewardj7ee97522011-05-09 21:45:04 +00001514 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001515 s390_disasm(ENC3(MNM, GPR, UINT), "clfi", r1, i2);
1516
1517 return emit_RIL(p, 0xc20f00000000ULL, r1, i2);
1518}
1519
1520
sewardj9d31dfd2011-03-15 12:36:44 +00001521static UChar *
sewardj2019a972011-03-07 16:04:07 +00001522s390_emit_DR(UChar *p, UChar r1, UChar r2)
1523{
sewardj7ee97522011-05-09 21:45:04 +00001524 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001525 s390_disasm(ENC3(MNM, GPR, GPR), "dr", r1, r2);
1526
1527 return emit_RR(p, 0x1d00, r1, r2);
1528}
1529
1530
sewardj9d31dfd2011-03-15 12:36:44 +00001531static UChar *
sewardj2019a972011-03-07 16:04:07 +00001532s390_emit_D(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
1533{
sewardj7ee97522011-05-09 21:45:04 +00001534 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001535 s390_disasm(ENC3(MNM, GPR, UDXB), "d", r1, d2, x2, b2);
1536
1537 return emit_RX(p, 0x5d000000, r1, x2, b2, d2);
1538}
1539
1540
sewardj9d31dfd2011-03-15 12:36:44 +00001541static UChar *
sewardj2019a972011-03-07 16:04:07 +00001542s390_emit_DLR(UChar *p, UChar r1, UChar r2)
1543{
sewardj7ee97522011-05-09 21:45:04 +00001544 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001545 s390_disasm(ENC3(MNM, GPR, GPR), "dlr", r1, r2);
1546
1547 return emit_RRE(p, 0xb9970000, r1, r2);
1548}
1549
1550
sewardj9d31dfd2011-03-15 12:36:44 +00001551static UChar *
sewardj2019a972011-03-07 16:04:07 +00001552s390_emit_DLGR(UChar *p, UChar r1, UChar r2)
1553{
sewardj7ee97522011-05-09 21:45:04 +00001554 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001555 s390_disasm(ENC3(MNM, GPR, GPR), "dlgr", r1, r2);
1556
1557 return emit_RRE(p, 0xb9870000, r1, r2);
1558}
1559
1560
sewardj9d31dfd2011-03-15 12:36:44 +00001561static UChar *
sewardj2019a972011-03-07 16:04:07 +00001562s390_emit_DL(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1563{
sewardj652b56a2011-04-13 15:38:17 +00001564 vassert(s390_host_has_ldisp || dh2 == 0);
1565
sewardj7ee97522011-05-09 21:45:04 +00001566 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001567 s390_disasm(ENC3(MNM, GPR, SDXB), "dl", r1, dh2, dl2, x2, b2);
1568
1569 return emit_RXY(p, 0xe30000000097ULL, r1, x2, b2, dl2, dh2);
1570}
1571
1572
sewardj9d31dfd2011-03-15 12:36:44 +00001573static UChar *
sewardj2019a972011-03-07 16:04:07 +00001574s390_emit_DLG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1575{
sewardj652b56a2011-04-13 15:38:17 +00001576 vassert(s390_host_has_ldisp || dh2 == 0);
1577
sewardj7ee97522011-05-09 21:45:04 +00001578 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001579 s390_disasm(ENC3(MNM, GPR, SDXB), "dlg", r1, dh2, dl2, x2, b2);
1580
1581 return emit_RXY(p, 0xe30000000087ULL, r1, x2, b2, dl2, dh2);
1582}
1583
1584
sewardj9d31dfd2011-03-15 12:36:44 +00001585static UChar *
sewardj2019a972011-03-07 16:04:07 +00001586s390_emit_DSGR(UChar *p, UChar r1, UChar r2)
1587{
sewardj7ee97522011-05-09 21:45:04 +00001588 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001589 s390_disasm(ENC3(MNM, GPR, GPR), "dsgr", r1, r2);
1590
1591 return emit_RRE(p, 0xb90d0000, r1, r2);
1592}
1593
1594
sewardj9d31dfd2011-03-15 12:36:44 +00001595static UChar *
sewardj2019a972011-03-07 16:04:07 +00001596s390_emit_DSG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1597{
sewardj652b56a2011-04-13 15:38:17 +00001598 vassert(s390_host_has_ldisp || dh2 == 0);
1599
sewardj7ee97522011-05-09 21:45:04 +00001600 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001601 s390_disasm(ENC3(MNM, GPR, SDXB), "dsg", r1, dh2, dl2, x2, b2);
1602
1603 return emit_RXY(p, 0xe3000000000dULL, r1, x2, b2, dl2, dh2);
1604}
1605
1606
sewardj9d31dfd2011-03-15 12:36:44 +00001607static UChar *
sewardj2019a972011-03-07 16:04:07 +00001608s390_emit_XR(UChar *p, UChar r1, UChar r2)
1609{
sewardj7ee97522011-05-09 21:45:04 +00001610 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001611 s390_disasm(ENC3(MNM, GPR, GPR), "xr", r1, r2);
1612
1613 return emit_RR(p, 0x1700, r1, r2);
1614}
1615
1616
sewardj9d31dfd2011-03-15 12:36:44 +00001617static UChar *
sewardj2019a972011-03-07 16:04:07 +00001618s390_emit_XGR(UChar *p, UChar r1, UChar r2)
1619{
sewardj7ee97522011-05-09 21:45:04 +00001620 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001621 s390_disasm(ENC3(MNM, GPR, GPR), "xgr", r1, r2);
1622
1623 return emit_RRE(p, 0xb9820000, r1, r2);
1624}
1625
1626
sewardj9d31dfd2011-03-15 12:36:44 +00001627static UChar *
sewardj2019a972011-03-07 16:04:07 +00001628s390_emit_X(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
1629{
sewardj7ee97522011-05-09 21:45:04 +00001630 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001631 s390_disasm(ENC3(MNM, GPR, UDXB), "x", r1, d2, x2, b2);
1632
1633 return emit_RX(p, 0x57000000, r1, x2, b2, d2);
1634}
1635
1636
sewardj9d31dfd2011-03-15 12:36:44 +00001637static UChar *
sewardj2019a972011-03-07 16:04:07 +00001638s390_emit_XY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1639{
sewardj652b56a2011-04-13 15:38:17 +00001640 vassert(s390_host_has_ldisp);
1641
sewardj7ee97522011-05-09 21:45:04 +00001642 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001643 s390_disasm(ENC3(MNM, GPR, SDXB), "xy", r1, dh2, dl2, x2, b2);
1644
1645 return emit_RXY(p, 0xe30000000057ULL, r1, x2, b2, dl2, dh2);
1646}
1647
1648
sewardj9d31dfd2011-03-15 12:36:44 +00001649static UChar *
sewardj2019a972011-03-07 16:04:07 +00001650s390_emit_XG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1651{
sewardj652b56a2011-04-13 15:38:17 +00001652 vassert(s390_host_has_ldisp || dh2 == 0);
1653
sewardj7ee97522011-05-09 21:45:04 +00001654 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001655 s390_disasm(ENC3(MNM, GPR, SDXB), "xg", r1, dh2, dl2, x2, b2);
1656
1657 return emit_RXY(p, 0xe30000000082ULL, r1, x2, b2, dl2, dh2);
1658}
1659
1660
sewardj9d31dfd2011-03-15 12:36:44 +00001661static UChar *
sewardj2019a972011-03-07 16:04:07 +00001662s390_emit_XIHF(UChar *p, UChar r1, UInt i2)
1663{
sewardj652b56a2011-04-13 15:38:17 +00001664 vassert(s390_host_has_eimm);
1665
sewardj7ee97522011-05-09 21:45:04 +00001666 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001667 s390_disasm(ENC3(MNM, GPR, UINT), "xihf", r1, i2);
1668
1669 return emit_RIL(p, 0xc00600000000ULL, r1, i2);
1670}
1671
1672
sewardj9d31dfd2011-03-15 12:36:44 +00001673static UChar *
sewardj2019a972011-03-07 16:04:07 +00001674s390_emit_XILF(UChar *p, UChar r1, UInt i2)
1675{
sewardj652b56a2011-04-13 15:38:17 +00001676 vassert(s390_host_has_eimm);
1677
sewardj7ee97522011-05-09 21:45:04 +00001678 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001679 s390_disasm(ENC3(MNM, GPR, UINT), "xilf", r1, i2);
1680
1681 return emit_RIL(p, 0xc00700000000ULL, r1, i2);
1682}
1683
1684
sewardj9d31dfd2011-03-15 12:36:44 +00001685static UChar *
sewardj2019a972011-03-07 16:04:07 +00001686s390_emit_FLOGR(UChar *p, UChar r1, UChar r2)
1687{
sewardj652b56a2011-04-13 15:38:17 +00001688 vassert(s390_host_has_eimm);
1689
sewardj7ee97522011-05-09 21:45:04 +00001690 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001691 s390_disasm(ENC3(MNM, GPR, GPR), "flogr", r1, r2);
1692
1693 return emit_RRE(p, 0xb9830000, r1, r2);
1694}
1695
1696
sewardj9d31dfd2011-03-15 12:36:44 +00001697static UChar *
sewardj2019a972011-03-07 16:04:07 +00001698s390_emit_IC(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
1699{
sewardj7ee97522011-05-09 21:45:04 +00001700 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001701 s390_disasm(ENC3(MNM, GPR, UDXB), "ic", r1, d2, x2, b2);
1702
1703 return emit_RX(p, 0x43000000, r1, x2, b2, d2);
1704}
1705
1706
sewardj9d31dfd2011-03-15 12:36:44 +00001707static UChar *
sewardj2019a972011-03-07 16:04:07 +00001708s390_emit_ICY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1709{
sewardj652b56a2011-04-13 15:38:17 +00001710 vassert(s390_host_has_ldisp);
1711
sewardj7ee97522011-05-09 21:45:04 +00001712 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001713 s390_disasm(ENC3(MNM, GPR, SDXB), "icy", r1, dh2, dl2, x2, b2);
1714
1715 return emit_RXY(p, 0xe30000000073ULL, r1, x2, b2, dl2, dh2);
1716}
1717
1718
sewardj9d31dfd2011-03-15 12:36:44 +00001719static UChar *
sewardj2019a972011-03-07 16:04:07 +00001720s390_emit_IIHF(UChar *p, UChar r1, UInt i2)
1721{
sewardj652b56a2011-04-13 15:38:17 +00001722 vassert(s390_host_has_eimm);
1723
sewardj7ee97522011-05-09 21:45:04 +00001724 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001725 s390_disasm(ENC3(MNM, GPR, UINT), "iihf", r1, i2);
1726
1727 return emit_RIL(p, 0xc00800000000ULL, r1, i2);
1728}
1729
1730
sewardj9d31dfd2011-03-15 12:36:44 +00001731static UChar *
sewardj2019a972011-03-07 16:04:07 +00001732s390_emit_IIHH(UChar *p, UChar r1, UShort i2)
1733{
sewardj7ee97522011-05-09 21:45:04 +00001734 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001735 s390_disasm(ENC3(MNM, GPR, UINT), "iihh", r1, i2);
1736
1737 return emit_RI(p, 0xa5000000, r1, i2);
1738}
1739
1740
sewardj9d31dfd2011-03-15 12:36:44 +00001741static UChar *
sewardj2019a972011-03-07 16:04:07 +00001742s390_emit_IIHL(UChar *p, UChar r1, UShort i2)
1743{
sewardj7ee97522011-05-09 21:45:04 +00001744 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001745 s390_disasm(ENC3(MNM, GPR, UINT), "iihl", r1, i2);
1746
1747 return emit_RI(p, 0xa5010000, r1, i2);
1748}
1749
1750
sewardj9d31dfd2011-03-15 12:36:44 +00001751static UChar *
sewardj2019a972011-03-07 16:04:07 +00001752s390_emit_IILF(UChar *p, UChar r1, UInt i2)
1753{
sewardj652b56a2011-04-13 15:38:17 +00001754 vassert(s390_host_has_eimm);
1755
sewardj7ee97522011-05-09 21:45:04 +00001756 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001757 s390_disasm(ENC3(MNM, GPR, UINT), "iilf", r1, i2);
1758
1759 return emit_RIL(p, 0xc00900000000ULL, r1, i2);
1760}
1761
1762
sewardj9d31dfd2011-03-15 12:36:44 +00001763static UChar *
sewardj2019a972011-03-07 16:04:07 +00001764s390_emit_IILH(UChar *p, UChar r1, UShort i2)
1765{
sewardj7ee97522011-05-09 21:45:04 +00001766 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001767 s390_disasm(ENC3(MNM, GPR, UINT), "iilh", r1, i2);
1768
1769 return emit_RI(p, 0xa5020000, r1, i2);
1770}
1771
1772
sewardj9d31dfd2011-03-15 12:36:44 +00001773static UChar *
sewardj2019a972011-03-07 16:04:07 +00001774s390_emit_IILL(UChar *p, UChar r1, UShort i2)
1775{
sewardj7ee97522011-05-09 21:45:04 +00001776 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001777 s390_disasm(ENC3(MNM, GPR, UINT), "iill", r1, i2);
1778
1779 return emit_RI(p, 0xa5030000, r1, i2);
1780}
1781
1782
sewardj9d31dfd2011-03-15 12:36:44 +00001783static UChar *
sewardj2019a972011-03-07 16:04:07 +00001784s390_emit_IPM(UChar *p, UChar r1, UChar r2)
1785{
sewardj7ee97522011-05-09 21:45:04 +00001786 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001787 s390_disasm(ENC2(MNM, GPR), "ipm", r1);
1788
1789 return emit_RRE(p, 0xb2220000, r1, r2);
1790}
1791
1792
sewardj9d31dfd2011-03-15 12:36:44 +00001793static UChar *
sewardj2019a972011-03-07 16:04:07 +00001794s390_emit_LR(UChar *p, UChar r1, UChar r2)
1795{
sewardj7ee97522011-05-09 21:45:04 +00001796 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001797 s390_disasm(ENC3(MNM, GPR, GPR), "lr", r1, r2);
1798
1799 return emit_RR(p, 0x1800, r1, r2);
1800}
1801
1802
sewardj9d31dfd2011-03-15 12:36:44 +00001803static UChar *
sewardj2019a972011-03-07 16:04:07 +00001804s390_emit_LGR(UChar *p, UChar r1, UChar r2)
1805{
sewardj7ee97522011-05-09 21:45:04 +00001806 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001807 s390_disasm(ENC3(MNM, GPR, GPR), "lgr", r1, r2);
1808
1809 return emit_RRE(p, 0xb9040000, r1, r2);
1810}
1811
1812
sewardj9d31dfd2011-03-15 12:36:44 +00001813static UChar *
sewardj2019a972011-03-07 16:04:07 +00001814s390_emit_LGFR(UChar *p, UChar r1, UChar r2)
1815{
sewardj7ee97522011-05-09 21:45:04 +00001816 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001817 s390_disasm(ENC3(MNM, GPR, GPR), "lgfr", r1, r2);
1818
1819 return emit_RRE(p, 0xb9140000, r1, r2);
1820}
1821
1822
sewardj9d31dfd2011-03-15 12:36:44 +00001823static UChar *
sewardj2019a972011-03-07 16:04:07 +00001824s390_emit_L(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
1825{
sewardj7ee97522011-05-09 21:45:04 +00001826 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001827 s390_disasm(ENC3(MNM, GPR, UDXB), "l", r1, d2, x2, b2);
1828
1829 return emit_RX(p, 0x58000000, r1, x2, b2, d2);
1830}
1831
1832
sewardj9d31dfd2011-03-15 12:36:44 +00001833static UChar *
sewardj2019a972011-03-07 16:04:07 +00001834s390_emit_LY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1835{
sewardj652b56a2011-04-13 15:38:17 +00001836 vassert(s390_host_has_ldisp);
1837
sewardj7ee97522011-05-09 21:45:04 +00001838 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001839 s390_disasm(ENC3(MNM, GPR, SDXB), "ly", r1, dh2, dl2, x2, b2);
1840
1841 return emit_RXY(p, 0xe30000000058ULL, r1, x2, b2, dl2, dh2);
1842}
1843
1844
sewardj9d31dfd2011-03-15 12:36:44 +00001845static UChar *
sewardj2019a972011-03-07 16:04:07 +00001846s390_emit_LG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1847{
sewardj652b56a2011-04-13 15:38:17 +00001848 vassert(s390_host_has_ldisp || dh2 == 0);
1849
sewardj7ee97522011-05-09 21:45:04 +00001850 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001851 s390_disasm(ENC3(MNM, GPR, SDXB), "lg", r1, dh2, dl2, x2, b2);
1852
1853 return emit_RXY(p, 0xe30000000004ULL, r1, x2, b2, dl2, dh2);
1854}
1855
1856
sewardj9d31dfd2011-03-15 12:36:44 +00001857static UChar *
sewardj2019a972011-03-07 16:04:07 +00001858s390_emit_LGF(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1859{
sewardj652b56a2011-04-13 15:38:17 +00001860 vassert(s390_host_has_ldisp || dh2 == 0);
1861
sewardj7ee97522011-05-09 21:45:04 +00001862 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001863 s390_disasm(ENC3(MNM, GPR, SDXB), "lgf", r1, dh2, dl2, x2, b2);
1864
1865 return emit_RXY(p, 0xe30000000014ULL, r1, x2, b2, dl2, dh2);
1866}
1867
1868
sewardj9d31dfd2011-03-15 12:36:44 +00001869static UChar *
sewardj2019a972011-03-07 16:04:07 +00001870s390_emit_LGFI(UChar *p, UChar r1, UInt i2)
1871{
sewardj652b56a2011-04-13 15:38:17 +00001872 vassert(s390_host_has_eimm);
1873
sewardj7ee97522011-05-09 21:45:04 +00001874 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001875 s390_disasm(ENC3(MNM, GPR, INT), "lgfi", r1, i2);
1876
1877 return emit_RIL(p, 0xc00100000000ULL, r1, i2);
1878}
1879
1880
sewardj9d31dfd2011-03-15 12:36:44 +00001881static UChar *
sewardj2019a972011-03-07 16:04:07 +00001882s390_emit_LTR(UChar *p, UChar r1, UChar r2)
1883{
sewardj7ee97522011-05-09 21:45:04 +00001884 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001885 s390_disasm(ENC3(MNM, GPR, GPR), "ltr", r1, r2);
1886
1887 return emit_RR(p, 0x1200, r1, r2);
1888}
1889
1890
sewardj9d31dfd2011-03-15 12:36:44 +00001891static UChar *
sewardj2019a972011-03-07 16:04:07 +00001892s390_emit_LTGR(UChar *p, UChar r1, UChar r2)
1893{
sewardj7ee97522011-05-09 21:45:04 +00001894 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001895 s390_disasm(ENC3(MNM, GPR, GPR), "ltgr", r1, r2);
1896
1897 return emit_RRE(p, 0xb9020000, r1, r2);
1898}
1899
1900
sewardj9d31dfd2011-03-15 12:36:44 +00001901static UChar *
sewardj2019a972011-03-07 16:04:07 +00001902s390_emit_LT(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1903{
sewardj652b56a2011-04-13 15:38:17 +00001904 vassert(s390_host_has_eimm);
1905
sewardj7ee97522011-05-09 21:45:04 +00001906 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001907 s390_disasm(ENC3(MNM, GPR, SDXB), "lt", r1, dh2, dl2, x2, b2);
1908
1909 return emit_RXY(p, 0xe30000000012ULL, r1, x2, b2, dl2, dh2);
1910}
1911
1912
sewardj9d31dfd2011-03-15 12:36:44 +00001913static UChar *
sewardj2019a972011-03-07 16:04:07 +00001914s390_emit_LTG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1915{
sewardj652b56a2011-04-13 15:38:17 +00001916 vassert(s390_host_has_eimm);
1917
sewardj7ee97522011-05-09 21:45:04 +00001918 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001919 s390_disasm(ENC3(MNM, GPR, SDXB), "ltg", r1, dh2, dl2, x2, b2);
1920
1921 return emit_RXY(p, 0xe30000000002ULL, r1, x2, b2, dl2, dh2);
1922}
1923
1924
sewardj9d31dfd2011-03-15 12:36:44 +00001925static UChar *
sewardj2019a972011-03-07 16:04:07 +00001926s390_emit_LBR(UChar *p, UChar r1, UChar r2)
1927{
sewardj652b56a2011-04-13 15:38:17 +00001928 vassert(s390_host_has_eimm);
1929
sewardj7ee97522011-05-09 21:45:04 +00001930 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001931 s390_disasm(ENC3(MNM, GPR, GPR), "lbr", r1, r2);
1932
1933 return emit_RRE(p, 0xb9260000, r1, r2);
1934}
1935
1936
sewardj9d31dfd2011-03-15 12:36:44 +00001937static UChar *
sewardj2019a972011-03-07 16:04:07 +00001938s390_emit_LGBR(UChar *p, UChar r1, UChar r2)
1939{
sewardj652b56a2011-04-13 15:38:17 +00001940 vassert(s390_host_has_eimm);
1941
sewardj7ee97522011-05-09 21:45:04 +00001942 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001943 s390_disasm(ENC3(MNM, GPR, GPR), "lgbr", r1, r2);
1944
1945 return emit_RRE(p, 0xb9060000, r1, r2);
1946}
1947
1948
sewardj9d31dfd2011-03-15 12:36:44 +00001949static UChar *
sewardj2019a972011-03-07 16:04:07 +00001950s390_emit_LB(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1951{
sewardj652b56a2011-04-13 15:38:17 +00001952 vassert(s390_host_has_ldisp);
1953
sewardj7ee97522011-05-09 21:45:04 +00001954 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001955 s390_disasm(ENC3(MNM, GPR, SDXB), "lb", r1, dh2, dl2, x2, b2);
1956
1957 return emit_RXY(p, 0xe30000000076ULL, r1, x2, b2, dl2, dh2);
1958}
1959
1960
sewardj9d31dfd2011-03-15 12:36:44 +00001961static UChar *
sewardj2019a972011-03-07 16:04:07 +00001962s390_emit_LGB(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1963{
sewardj652b56a2011-04-13 15:38:17 +00001964 vassert(s390_host_has_ldisp);
1965
sewardj7ee97522011-05-09 21:45:04 +00001966 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001967 s390_disasm(ENC3(MNM, GPR, SDXB), "lgb", r1, dh2, dl2, x2, b2);
1968
1969 return emit_RXY(p, 0xe30000000077ULL, r1, x2, b2, dl2, dh2);
1970}
1971
1972
sewardj9d31dfd2011-03-15 12:36:44 +00001973static UChar *
sewardj2019a972011-03-07 16:04:07 +00001974s390_emit_LCR(UChar *p, UChar r1, UChar r2)
1975{
sewardj7ee97522011-05-09 21:45:04 +00001976 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001977 s390_disasm(ENC3(MNM, GPR, GPR), "lcr", r1, r2);
1978
1979 return emit_RR(p, 0x1300, r1, r2);
1980}
1981
1982
sewardj9d31dfd2011-03-15 12:36:44 +00001983static UChar *
sewardj2019a972011-03-07 16:04:07 +00001984s390_emit_LCGR(UChar *p, UChar r1, UChar r2)
1985{
sewardj7ee97522011-05-09 21:45:04 +00001986 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001987 s390_disasm(ENC3(MNM, GPR, GPR), "lcgr", r1, r2);
1988
1989 return emit_RRE(p, 0xb9030000, r1, r2);
1990}
1991
1992
sewardj9d31dfd2011-03-15 12:36:44 +00001993static UChar *
sewardj2019a972011-03-07 16:04:07 +00001994s390_emit_LHR(UChar *p, UChar r1, UChar r2)
1995{
sewardj652b56a2011-04-13 15:38:17 +00001996 vassert(s390_host_has_eimm);
1997
sewardj7ee97522011-05-09 21:45:04 +00001998 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001999 s390_disasm(ENC3(MNM, GPR, GPR), "lhr", r1, r2);
2000
2001 return emit_RRE(p, 0xb9270000, r1, r2);
2002}
2003
2004
sewardj9d31dfd2011-03-15 12:36:44 +00002005static UChar *
sewardj2019a972011-03-07 16:04:07 +00002006s390_emit_LGHR(UChar *p, UChar r1, UChar r2)
2007{
sewardj652b56a2011-04-13 15:38:17 +00002008 vassert(s390_host_has_eimm);
2009
sewardj7ee97522011-05-09 21:45:04 +00002010 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002011 s390_disasm(ENC3(MNM, GPR, GPR), "lghr", r1, r2);
2012
2013 return emit_RRE(p, 0xb9070000, r1, r2);
2014}
2015
2016
sewardj9d31dfd2011-03-15 12:36:44 +00002017static UChar *
sewardj2019a972011-03-07 16:04:07 +00002018s390_emit_LH(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2019{
sewardj7ee97522011-05-09 21:45:04 +00002020 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002021 s390_disasm(ENC3(MNM, GPR, UDXB), "lh", r1, d2, x2, b2);
2022
2023 return emit_RX(p, 0x48000000, r1, x2, b2, d2);
2024}
2025
2026
sewardj9d31dfd2011-03-15 12:36:44 +00002027static UChar *
sewardj2019a972011-03-07 16:04:07 +00002028s390_emit_LHY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2029{
sewardj652b56a2011-04-13 15:38:17 +00002030 vassert(s390_host_has_ldisp);
2031
sewardj7ee97522011-05-09 21:45:04 +00002032 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002033 s390_disasm(ENC3(MNM, GPR, SDXB), "lhy", r1, dh2, dl2, x2, b2);
2034
2035 return emit_RXY(p, 0xe30000000078ULL, r1, x2, b2, dl2, dh2);
2036}
2037
2038
sewardj9d31dfd2011-03-15 12:36:44 +00002039static UChar *
sewardj2019a972011-03-07 16:04:07 +00002040s390_emit_LGH(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2041{
sewardj652b56a2011-04-13 15:38:17 +00002042 vassert(s390_host_has_ldisp || dh2 == 0);
2043
sewardj7ee97522011-05-09 21:45:04 +00002044 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002045 s390_disasm(ENC3(MNM, GPR, SDXB), "lgh", r1, dh2, dl2, x2, b2);
2046
2047 return emit_RXY(p, 0xe30000000015ULL, r1, x2, b2, dl2, dh2);
2048}
2049
2050
sewardj9d31dfd2011-03-15 12:36:44 +00002051static UChar *
sewardj2019a972011-03-07 16:04:07 +00002052s390_emit_LHI(UChar *p, UChar r1, UShort i2)
2053{
sewardj7ee97522011-05-09 21:45:04 +00002054 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002055 s390_disasm(ENC3(MNM, GPR, INT), "lhi", r1, (Int)(Short)i2);
2056
2057 return emit_RI(p, 0xa7080000, r1, i2);
2058}
2059
2060
sewardj9d31dfd2011-03-15 12:36:44 +00002061static UChar *
sewardj2019a972011-03-07 16:04:07 +00002062s390_emit_LGHI(UChar *p, UChar r1, UShort i2)
2063{
sewardj7ee97522011-05-09 21:45:04 +00002064 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002065 s390_disasm(ENC3(MNM, GPR, INT), "lghi", r1, (Int)(Short)i2);
2066
2067 return emit_RI(p, 0xa7090000, r1, i2);
2068}
2069
2070
sewardj9d31dfd2011-03-15 12:36:44 +00002071static UChar *
sewardj2019a972011-03-07 16:04:07 +00002072s390_emit_LLGFR(UChar *p, UChar r1, UChar r2)
2073{
sewardj7ee97522011-05-09 21:45:04 +00002074 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002075 s390_disasm(ENC3(MNM, GPR, GPR), "llgfr", r1, r2);
2076
2077 return emit_RRE(p, 0xb9160000, r1, r2);
2078}
2079
2080
sewardj9d31dfd2011-03-15 12:36:44 +00002081static UChar *
sewardj2019a972011-03-07 16:04:07 +00002082s390_emit_LLGF(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2083{
sewardj652b56a2011-04-13 15:38:17 +00002084 vassert(s390_host_has_ldisp || dh2 == 0);
2085
sewardj7ee97522011-05-09 21:45:04 +00002086 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002087 s390_disasm(ENC3(MNM, GPR, SDXB), "llgf", r1, dh2, dl2, x2, b2);
2088
2089 return emit_RXY(p, 0xe30000000016ULL, r1, x2, b2, dl2, dh2);
2090}
2091
2092
sewardj9d31dfd2011-03-15 12:36:44 +00002093static UChar *
sewardj2019a972011-03-07 16:04:07 +00002094s390_emit_LLCR(UChar *p, UChar r1, UChar r2)
2095{
sewardj652b56a2011-04-13 15:38:17 +00002096 vassert(s390_host_has_eimm);
2097
sewardj7ee97522011-05-09 21:45:04 +00002098 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002099 s390_disasm(ENC3(MNM, GPR, GPR), "llcr", r1, r2);
2100
2101 return emit_RRE(p, 0xb9940000, r1, r2);
2102}
2103
2104
sewardj9d31dfd2011-03-15 12:36:44 +00002105static UChar *
sewardj2019a972011-03-07 16:04:07 +00002106s390_emit_LLGCR(UChar *p, UChar r1, UChar r2)
2107{
sewardj652b56a2011-04-13 15:38:17 +00002108 vassert(s390_host_has_eimm);
2109
sewardj7ee97522011-05-09 21:45:04 +00002110 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002111 s390_disasm(ENC3(MNM, GPR, GPR), "llgcr", r1, r2);
2112
2113 return emit_RRE(p, 0xb9840000, r1, r2);
2114}
2115
2116
sewardj9d31dfd2011-03-15 12:36:44 +00002117static UChar *
sewardj2019a972011-03-07 16:04:07 +00002118s390_emit_LLC(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2119{
sewardj652b56a2011-04-13 15:38:17 +00002120 vassert(s390_host_has_eimm);
2121
sewardj7ee97522011-05-09 21:45:04 +00002122 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002123 s390_disasm(ENC3(MNM, GPR, SDXB), "llc", r1, dh2, dl2, x2, b2);
2124
2125 return emit_RXY(p, 0xe30000000094ULL, r1, x2, b2, dl2, dh2);
2126}
2127
2128
sewardj9d31dfd2011-03-15 12:36:44 +00002129static UChar *
sewardj2019a972011-03-07 16:04:07 +00002130s390_emit_LLGC(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2131{
sewardj652b56a2011-04-13 15:38:17 +00002132 vassert(s390_host_has_ldisp || dh2 == 0);
2133
sewardj7ee97522011-05-09 21:45:04 +00002134 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002135 s390_disasm(ENC3(MNM, GPR, SDXB), "llgc", r1, dh2, dl2, x2, b2);
2136
2137 return emit_RXY(p, 0xe30000000090ULL, r1, x2, b2, dl2, dh2);
2138}
2139
2140
sewardj9d31dfd2011-03-15 12:36:44 +00002141static UChar *
sewardj2019a972011-03-07 16:04:07 +00002142s390_emit_LLHR(UChar *p, UChar r1, UChar r2)
2143{
sewardj652b56a2011-04-13 15:38:17 +00002144 vassert(s390_host_has_eimm);
2145
sewardj7ee97522011-05-09 21:45:04 +00002146 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002147 s390_disasm(ENC3(MNM, GPR, GPR), "llhr", r1, r2);
2148
2149 return emit_RRE(p, 0xb9950000, r1, r2);
2150}
2151
2152
sewardj9d31dfd2011-03-15 12:36:44 +00002153static UChar *
sewardj2019a972011-03-07 16:04:07 +00002154s390_emit_LLGHR(UChar *p, UChar r1, UChar r2)
2155{
sewardj652b56a2011-04-13 15:38:17 +00002156 vassert(s390_host_has_eimm);
2157
sewardj7ee97522011-05-09 21:45:04 +00002158 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002159 s390_disasm(ENC3(MNM, GPR, GPR), "llghr", r1, r2);
2160
2161 return emit_RRE(p, 0xb9850000, r1, r2);
2162}
2163
2164
sewardj9d31dfd2011-03-15 12:36:44 +00002165static UChar *
sewardj2019a972011-03-07 16:04:07 +00002166s390_emit_LLH(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2167{
sewardj652b56a2011-04-13 15:38:17 +00002168 vassert(s390_host_has_eimm);
2169
sewardj7ee97522011-05-09 21:45:04 +00002170 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002171 s390_disasm(ENC3(MNM, GPR, SDXB), "llh", r1, dh2, dl2, x2, b2);
2172
2173 return emit_RXY(p, 0xe30000000095ULL, r1, x2, b2, dl2, dh2);
2174}
2175
2176
sewardj9d31dfd2011-03-15 12:36:44 +00002177static UChar *
sewardj2019a972011-03-07 16:04:07 +00002178s390_emit_LLGH(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2179{
sewardj652b56a2011-04-13 15:38:17 +00002180 vassert(s390_host_has_ldisp || dh2 == 0);
2181
sewardj7ee97522011-05-09 21:45:04 +00002182 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002183 s390_disasm(ENC3(MNM, GPR, SDXB), "llgh", r1, dh2, dl2, x2, b2);
2184
2185 return emit_RXY(p, 0xe30000000091ULL, r1, x2, b2, dl2, dh2);
2186}
2187
2188
sewardj9d31dfd2011-03-15 12:36:44 +00002189static UChar *
sewardj2019a972011-03-07 16:04:07 +00002190s390_emit_LLILF(UChar *p, UChar r1, UInt i2)
2191{
sewardj652b56a2011-04-13 15:38:17 +00002192 vassert(s390_host_has_eimm);
2193
sewardj7ee97522011-05-09 21:45:04 +00002194 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002195 s390_disasm(ENC3(MNM, GPR, UINT), "llilf", r1, i2);
2196
2197 return emit_RIL(p, 0xc00f00000000ULL, r1, i2);
2198}
2199
2200
sewardj9d31dfd2011-03-15 12:36:44 +00002201static UChar *
sewardj2019a972011-03-07 16:04:07 +00002202s390_emit_LLILH(UChar *p, UChar r1, UShort i2)
2203{
sewardj7ee97522011-05-09 21:45:04 +00002204 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002205 s390_disasm(ENC3(MNM, GPR, UINT), "llilh", r1, i2);
2206
2207 return emit_RI(p, 0xa50e0000, r1, i2);
2208}
2209
2210
sewardj9d31dfd2011-03-15 12:36:44 +00002211static UChar *
sewardj2019a972011-03-07 16:04:07 +00002212s390_emit_LLILL(UChar *p, UChar r1, UShort i2)
2213{
sewardj7ee97522011-05-09 21:45:04 +00002214 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002215 s390_disasm(ENC3(MNM, GPR, UINT), "llill", r1, i2);
2216
2217 return emit_RI(p, 0xa50f0000, r1, i2);
2218}
2219
2220
sewardj9d31dfd2011-03-15 12:36:44 +00002221static UChar *
sewardj2019a972011-03-07 16:04:07 +00002222s390_emit_MR(UChar *p, UChar r1, UChar r2)
2223{
sewardj7ee97522011-05-09 21:45:04 +00002224 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002225 s390_disasm(ENC3(MNM, GPR, GPR), "mr", r1, r2);
2226
2227 return emit_RR(p, 0x1c00, r1, r2);
2228}
2229
2230
sewardj9d31dfd2011-03-15 12:36:44 +00002231static UChar *
sewardj2019a972011-03-07 16:04:07 +00002232s390_emit_M(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2233{
sewardj7ee97522011-05-09 21:45:04 +00002234 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002235 s390_disasm(ENC3(MNM, GPR, UDXB), "m", r1, d2, x2, b2);
2236
2237 return emit_RX(p, 0x5c000000, r1, x2, b2, d2);
2238}
2239
2240
sewardj9d31dfd2011-03-15 12:36:44 +00002241static UChar *
sewardj2019a972011-03-07 16:04:07 +00002242s390_emit_MFY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2243{
sewardj652b56a2011-04-13 15:38:17 +00002244 vassert(s390_host_has_gie);
2245
sewardj7ee97522011-05-09 21:45:04 +00002246 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002247 s390_disasm(ENC3(MNM, GPR, SDXB), "mfy", r1, dh2, dl2, x2, b2);
2248
2249 return emit_RXY(p, 0xe3000000005cULL, r1, x2, b2, dl2, dh2);
2250}
2251
2252
sewardj9d31dfd2011-03-15 12:36:44 +00002253static UChar *
sewardj2019a972011-03-07 16:04:07 +00002254s390_emit_MH(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2255{
sewardj7ee97522011-05-09 21:45:04 +00002256 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002257 s390_disasm(ENC3(MNM, GPR, UDXB), "mh", r1, d2, x2, b2);
2258
2259 return emit_RX(p, 0x4c000000, r1, x2, b2, d2);
2260}
2261
2262
sewardj9d31dfd2011-03-15 12:36:44 +00002263static UChar *
sewardj2019a972011-03-07 16:04:07 +00002264s390_emit_MHY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2265{
sewardj652b56a2011-04-13 15:38:17 +00002266 vassert(s390_host_has_gie);
2267
sewardj7ee97522011-05-09 21:45:04 +00002268 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002269 s390_disasm(ENC3(MNM, GPR, SDXB), "mhy", r1, dh2, dl2, x2, b2);
2270
2271 return emit_RXY(p, 0xe3000000007cULL, r1, x2, b2, dl2, dh2);
2272}
2273
2274
sewardj9d31dfd2011-03-15 12:36:44 +00002275static UChar *
sewardj2019a972011-03-07 16:04:07 +00002276s390_emit_MHI(UChar *p, UChar r1, UShort i2)
2277{
sewardj7ee97522011-05-09 21:45:04 +00002278 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002279 s390_disasm(ENC3(MNM, GPR, INT), "mhi", r1, (Int)(Short)i2);
2280
2281 return emit_RI(p, 0xa70c0000, r1, i2);
2282}
2283
2284
sewardj9d31dfd2011-03-15 12:36:44 +00002285static UChar *
sewardj2019a972011-03-07 16:04:07 +00002286s390_emit_MLR(UChar *p, UChar r1, UChar r2)
2287{
sewardj7ee97522011-05-09 21:45:04 +00002288 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002289 s390_disasm(ENC3(MNM, GPR, GPR), "mlr", r1, r2);
2290
2291 return emit_RRE(p, 0xb9960000, r1, r2);
2292}
2293
2294
sewardj9d31dfd2011-03-15 12:36:44 +00002295static UChar *
sewardj2019a972011-03-07 16:04:07 +00002296s390_emit_MLGR(UChar *p, UChar r1, UChar r2)
2297{
sewardj7ee97522011-05-09 21:45:04 +00002298 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002299 s390_disasm(ENC3(MNM, GPR, GPR), "mlgr", r1, r2);
2300
2301 return emit_RRE(p, 0xb9860000, r1, r2);
2302}
2303
2304
sewardj9d31dfd2011-03-15 12:36:44 +00002305static UChar *
sewardj2019a972011-03-07 16:04:07 +00002306s390_emit_ML(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2307{
sewardj652b56a2011-04-13 15:38:17 +00002308 vassert(s390_host_has_ldisp || dh2 == 0);
2309
sewardj7ee97522011-05-09 21:45:04 +00002310 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002311 s390_disasm(ENC3(MNM, GPR, SDXB), "ml", r1, dh2, dl2, x2, b2);
2312
2313 return emit_RXY(p, 0xe30000000096ULL, r1, x2, b2, dl2, dh2);
2314}
2315
2316
sewardj9d31dfd2011-03-15 12:36:44 +00002317static UChar *
sewardj2019a972011-03-07 16:04:07 +00002318s390_emit_MLG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2319{
sewardj652b56a2011-04-13 15:38:17 +00002320 vassert(s390_host_has_ldisp || dh2 == 0);
2321
sewardj7ee97522011-05-09 21:45:04 +00002322 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002323 s390_disasm(ENC3(MNM, GPR, SDXB), "mlg", r1, dh2, dl2, x2, b2);
2324
2325 return emit_RXY(p, 0xe30000000086ULL, r1, x2, b2, dl2, dh2);
2326}
2327
2328
sewardj9d31dfd2011-03-15 12:36:44 +00002329static UChar *
sewardj2019a972011-03-07 16:04:07 +00002330s390_emit_MSR(UChar *p, UChar r1, UChar r2)
2331{
sewardj7ee97522011-05-09 21:45:04 +00002332 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002333 s390_disasm(ENC3(MNM, GPR, GPR), "msr", r1, r2);
2334
2335 return emit_RRE(p, 0xb2520000, r1, r2);
2336}
2337
2338
sewardj9d31dfd2011-03-15 12:36:44 +00002339static UChar *
sewardj2019a972011-03-07 16:04:07 +00002340s390_emit_MSGR(UChar *p, UChar r1, UChar r2)
2341{
sewardj7ee97522011-05-09 21:45:04 +00002342 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002343 s390_disasm(ENC3(MNM, GPR, GPR), "msgr", r1, r2);
2344
2345 return emit_RRE(p, 0xb90c0000, r1, r2);
2346}
2347
2348
sewardj9d31dfd2011-03-15 12:36:44 +00002349static UChar *
sewardj2019a972011-03-07 16:04:07 +00002350s390_emit_MS(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2351{
sewardj7ee97522011-05-09 21:45:04 +00002352 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002353 s390_disasm(ENC3(MNM, GPR, UDXB), "ms", r1, d2, x2, b2);
2354
2355 return emit_RX(p, 0x71000000, r1, x2, b2, d2);
2356}
2357
2358
sewardj9d31dfd2011-03-15 12:36:44 +00002359static UChar *
sewardj2019a972011-03-07 16:04:07 +00002360s390_emit_MSY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2361{
sewardj652b56a2011-04-13 15:38:17 +00002362 vassert(s390_host_has_ldisp);
2363
sewardj7ee97522011-05-09 21:45:04 +00002364 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002365 s390_disasm(ENC3(MNM, GPR, SDXB), "msy", r1, dh2, dl2, x2, b2);
2366
2367 return emit_RXY(p, 0xe30000000051ULL, r1, x2, b2, dl2, dh2);
2368}
2369
2370
sewardj9d31dfd2011-03-15 12:36:44 +00002371static UChar *
sewardj2019a972011-03-07 16:04:07 +00002372s390_emit_MSG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2373{
sewardj652b56a2011-04-13 15:38:17 +00002374 vassert(s390_host_has_ldisp || dh2 == 0);
2375
sewardj7ee97522011-05-09 21:45:04 +00002376 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002377 s390_disasm(ENC3(MNM, GPR, SDXB), "msg", r1, dh2, dl2, x2, b2);
2378
2379 return emit_RXY(p, 0xe3000000000cULL, r1, x2, b2, dl2, dh2);
2380}
2381
2382
sewardj9d31dfd2011-03-15 12:36:44 +00002383static UChar *
sewardj2019a972011-03-07 16:04:07 +00002384s390_emit_MSFI(UChar *p, UChar r1, UInt i2)
2385{
sewardj652b56a2011-04-13 15:38:17 +00002386 vassert(s390_host_has_gie);
2387
sewardj7ee97522011-05-09 21:45:04 +00002388 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002389 s390_disasm(ENC3(MNM, GPR, INT), "msfi", r1, i2);
2390
2391 return emit_RIL(p, 0xc20100000000ULL, r1, i2);
2392}
2393
2394
sewardj9d31dfd2011-03-15 12:36:44 +00002395static UChar *
sewardj2019a972011-03-07 16:04:07 +00002396s390_emit_MSGFI(UChar *p, UChar r1, UInt i2)
2397{
sewardj652b56a2011-04-13 15:38:17 +00002398 vassert(s390_host_has_gie);
2399
sewardj7ee97522011-05-09 21:45:04 +00002400 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002401 s390_disasm(ENC3(MNM, GPR, INT), "msgfi", r1, i2);
2402
2403 return emit_RIL(p, 0xc20000000000ULL, r1, i2);
2404}
2405
2406
sewardj9d31dfd2011-03-15 12:36:44 +00002407static UChar *
sewardj2019a972011-03-07 16:04:07 +00002408s390_emit_OR(UChar *p, UChar r1, UChar r2)
2409{
sewardj7ee97522011-05-09 21:45:04 +00002410 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002411 s390_disasm(ENC3(MNM, GPR, GPR), "or", r1, r2);
2412
2413 return emit_RR(p, 0x1600, r1, r2);
2414}
2415
2416
sewardj9d31dfd2011-03-15 12:36:44 +00002417static UChar *
sewardj2019a972011-03-07 16:04:07 +00002418s390_emit_OGR(UChar *p, UChar r1, UChar r2)
2419{
sewardj7ee97522011-05-09 21:45:04 +00002420 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002421 s390_disasm(ENC3(MNM, GPR, GPR), "ogr", r1, r2);
2422
2423 return emit_RRE(p, 0xb9810000, r1, r2);
2424}
2425
2426
sewardj9d31dfd2011-03-15 12:36:44 +00002427static UChar *
sewardj2019a972011-03-07 16:04:07 +00002428s390_emit_O(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2429{
sewardj7ee97522011-05-09 21:45:04 +00002430 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002431 s390_disasm(ENC3(MNM, GPR, UDXB), "o", r1, d2, x2, b2);
2432
2433 return emit_RX(p, 0x56000000, r1, x2, b2, d2);
2434}
2435
2436
sewardj9d31dfd2011-03-15 12:36:44 +00002437static UChar *
sewardj2019a972011-03-07 16:04:07 +00002438s390_emit_OY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2439{
sewardj652b56a2011-04-13 15:38:17 +00002440 vassert(s390_host_has_ldisp);
2441
sewardj7ee97522011-05-09 21:45:04 +00002442 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002443 s390_disasm(ENC3(MNM, GPR, SDXB), "oy", r1, dh2, dl2, x2, b2);
2444
2445 return emit_RXY(p, 0xe30000000056ULL, r1, x2, b2, dl2, dh2);
2446}
2447
2448
sewardj9d31dfd2011-03-15 12:36:44 +00002449static UChar *
sewardj2019a972011-03-07 16:04:07 +00002450s390_emit_OG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2451{
sewardj652b56a2011-04-13 15:38:17 +00002452 vassert(s390_host_has_ldisp || dh2 == 0);
2453
sewardj7ee97522011-05-09 21:45:04 +00002454 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002455 s390_disasm(ENC3(MNM, GPR, SDXB), "og", r1, dh2, dl2, x2, b2);
2456
2457 return emit_RXY(p, 0xe30000000081ULL, r1, x2, b2, dl2, dh2);
2458}
2459
2460
sewardj9d31dfd2011-03-15 12:36:44 +00002461static UChar *
sewardj2019a972011-03-07 16:04:07 +00002462s390_emit_OIHF(UChar *p, UChar r1, UInt i2)
2463{
sewardj652b56a2011-04-13 15:38:17 +00002464 vassert(s390_host_has_eimm);
2465
sewardj7ee97522011-05-09 21:45:04 +00002466 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002467 s390_disasm(ENC3(MNM, GPR, UINT), "oihf", r1, i2);
2468
2469 return emit_RIL(p, 0xc00c00000000ULL, r1, i2);
2470}
2471
2472
sewardj9d31dfd2011-03-15 12:36:44 +00002473static UChar *
sewardj2019a972011-03-07 16:04:07 +00002474s390_emit_OILF(UChar *p, UChar r1, UInt i2)
2475{
sewardj652b56a2011-04-13 15:38:17 +00002476 vassert(s390_host_has_eimm);
2477
sewardj7ee97522011-05-09 21:45:04 +00002478 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002479 s390_disasm(ENC3(MNM, GPR, UINT), "oilf", r1, i2);
2480
2481 return emit_RIL(p, 0xc00d00000000ULL, r1, i2);
2482}
2483
2484
sewardj9d31dfd2011-03-15 12:36:44 +00002485static UChar *
sewardj2019a972011-03-07 16:04:07 +00002486s390_emit_OILL(UChar *p, UChar r1, UShort i2)
2487{
sewardj7ee97522011-05-09 21:45:04 +00002488 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002489 s390_disasm(ENC3(MNM, GPR, UINT), "oill", r1, i2);
2490
2491 return emit_RI(p, 0xa50b0000, r1, i2);
2492}
2493
2494
sewardj9d31dfd2011-03-15 12:36:44 +00002495static UChar *
sewardj3c49aaa2011-04-05 14:00:37 +00002496s390_emit_SLL(UChar *p, UChar r1, UChar b2, UShort d2)
sewardj2019a972011-03-07 16:04:07 +00002497{
sewardj7ee97522011-05-09 21:45:04 +00002498 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002499 s390_disasm(ENC3(MNM, GPR, UDXB), "sll", r1, d2, 0, b2);
2500
sewardj3c49aaa2011-04-05 14:00:37 +00002501 return emit_RS(p, 0x89000000, r1, 0, b2, d2);
sewardj2019a972011-03-07 16:04:07 +00002502}
2503
2504
sewardj9d31dfd2011-03-15 12:36:44 +00002505static UChar *
sewardj2019a972011-03-07 16:04:07 +00002506s390_emit_SLLG(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
2507{
sewardj652b56a2011-04-13 15:38:17 +00002508 vassert(s390_host_has_ldisp || dh2 == 0);
2509
sewardj7ee97522011-05-09 21:45:04 +00002510 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002511 s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "sllg", r1, r3, dh2, dl2, 0, b2);
2512
2513 return emit_RSY(p, 0xeb000000000dULL, r1, r3, b2, dl2, dh2);
2514}
2515
2516
sewardj9d31dfd2011-03-15 12:36:44 +00002517static UChar *
sewardj3c49aaa2011-04-05 14:00:37 +00002518s390_emit_SRA(UChar *p, UChar r1, UChar b2, UShort d2)
sewardj2019a972011-03-07 16:04:07 +00002519{
sewardj7ee97522011-05-09 21:45:04 +00002520 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002521 s390_disasm(ENC3(MNM, GPR, UDXB), "sra", r1, d2, 0, b2);
2522
sewardj3c49aaa2011-04-05 14:00:37 +00002523 return emit_RS(p, 0x8a000000, r1, 0, b2, d2);
sewardj2019a972011-03-07 16:04:07 +00002524}
2525
2526
sewardj9d31dfd2011-03-15 12:36:44 +00002527static UChar *
sewardj2019a972011-03-07 16:04:07 +00002528s390_emit_SRAG(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
2529{
sewardj652b56a2011-04-13 15:38:17 +00002530 vassert(s390_host_has_ldisp || dh2 == 0);
2531
sewardj7ee97522011-05-09 21:45:04 +00002532 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002533 s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "srag", r1, r3, dh2, dl2, 0, b2);
2534
2535 return emit_RSY(p, 0xeb000000000aULL, r1, r3, b2, dl2, dh2);
2536}
2537
2538
sewardj9d31dfd2011-03-15 12:36:44 +00002539static UChar *
sewardj3c49aaa2011-04-05 14:00:37 +00002540s390_emit_SRL(UChar *p, UChar r1, UChar b2, UShort d2)
sewardj2019a972011-03-07 16:04:07 +00002541{
sewardj7ee97522011-05-09 21:45:04 +00002542 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002543 s390_disasm(ENC3(MNM, GPR, UDXB), "srl", r1, d2, 0, b2);
2544
sewardj3c49aaa2011-04-05 14:00:37 +00002545 return emit_RS(p, 0x88000000, r1, 0, b2, d2);
sewardj2019a972011-03-07 16:04:07 +00002546}
2547
2548
sewardj9d31dfd2011-03-15 12:36:44 +00002549static UChar *
sewardj2019a972011-03-07 16:04:07 +00002550s390_emit_SRLG(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
2551{
sewardj652b56a2011-04-13 15:38:17 +00002552 vassert(s390_host_has_ldisp || dh2 == 0);
2553
sewardj7ee97522011-05-09 21:45:04 +00002554 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002555 s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "srlg", r1, r3, dh2, dl2, 0, b2);
2556
2557 return emit_RSY(p, 0xeb000000000cULL, r1, r3, b2, dl2, dh2);
2558}
2559
2560
sewardj9d31dfd2011-03-15 12:36:44 +00002561static UChar *
sewardj2019a972011-03-07 16:04:07 +00002562s390_emit_ST(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2563{
sewardj7ee97522011-05-09 21:45:04 +00002564 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002565 s390_disasm(ENC3(MNM, GPR, UDXB), "st", r1, d2, x2, b2);
2566
2567 return emit_RX(p, 0x50000000, r1, x2, b2, d2);
2568}
2569
2570
sewardj9d31dfd2011-03-15 12:36:44 +00002571static UChar *
sewardj2019a972011-03-07 16:04:07 +00002572s390_emit_STY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2573{
sewardj652b56a2011-04-13 15:38:17 +00002574 vassert(s390_host_has_ldisp);
2575
sewardj7ee97522011-05-09 21:45:04 +00002576 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002577 s390_disasm(ENC3(MNM, GPR, SDXB), "sty", r1, dh2, dl2, x2, b2);
2578
2579 return emit_RXY(p, 0xe30000000050ULL, r1, x2, b2, dl2, dh2);
2580}
2581
2582
sewardj9d31dfd2011-03-15 12:36:44 +00002583static UChar *
sewardj2019a972011-03-07 16:04:07 +00002584s390_emit_STG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2585{
sewardj652b56a2011-04-13 15:38:17 +00002586 vassert(s390_host_has_ldisp || dh2 == 0);
2587
sewardj7ee97522011-05-09 21:45:04 +00002588 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002589 s390_disasm(ENC3(MNM, GPR, SDXB), "stg", r1, dh2, dl2, x2, b2);
2590
2591 return emit_RXY(p, 0xe30000000024ULL, r1, x2, b2, dl2, dh2);
2592}
2593
2594
sewardj9d31dfd2011-03-15 12:36:44 +00002595static UChar *
sewardj2019a972011-03-07 16:04:07 +00002596s390_emit_STC(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2597{
sewardj7ee97522011-05-09 21:45:04 +00002598 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002599 s390_disasm(ENC3(MNM, GPR, UDXB), "stc", r1, d2, x2, b2);
2600
2601 return emit_RX(p, 0x42000000, r1, x2, b2, d2);
2602}
2603
2604
sewardj9d31dfd2011-03-15 12:36:44 +00002605static UChar *
sewardj2019a972011-03-07 16:04:07 +00002606s390_emit_STCY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2607{
sewardj652b56a2011-04-13 15:38:17 +00002608 vassert(s390_host_has_ldisp);
2609
sewardj7ee97522011-05-09 21:45:04 +00002610 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002611 s390_disasm(ENC3(MNM, GPR, SDXB), "stcy", r1, dh2, dl2, x2, b2);
2612
2613 return emit_RXY(p, 0xe30000000072ULL, r1, x2, b2, dl2, dh2);
2614}
2615
2616
sewardj9d31dfd2011-03-15 12:36:44 +00002617static UChar *
sewardj2019a972011-03-07 16:04:07 +00002618s390_emit_STH(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2619{
sewardj7ee97522011-05-09 21:45:04 +00002620 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002621 s390_disasm(ENC3(MNM, GPR, UDXB), "sth", r1, d2, x2, b2);
2622
2623 return emit_RX(p, 0x40000000, r1, x2, b2, d2);
2624}
2625
2626
sewardj9d31dfd2011-03-15 12:36:44 +00002627static UChar *
sewardj2019a972011-03-07 16:04:07 +00002628s390_emit_STHY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2629{
sewardj652b56a2011-04-13 15:38:17 +00002630 vassert(s390_host_has_ldisp);
2631
sewardj7ee97522011-05-09 21:45:04 +00002632 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002633 s390_disasm(ENC3(MNM, GPR, SDXB), "sthy", r1, dh2, dl2, x2, b2);
2634
2635 return emit_RXY(p, 0xe30000000070ULL, r1, x2, b2, dl2, dh2);
2636}
2637
2638
sewardj9d31dfd2011-03-15 12:36:44 +00002639static UChar *
sewardj2019a972011-03-07 16:04:07 +00002640s390_emit_SR(UChar *p, UChar r1, UChar r2)
2641{
sewardj7ee97522011-05-09 21:45:04 +00002642 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002643 s390_disasm(ENC3(MNM, GPR, GPR), "sr", r1, r2);
2644
2645 return emit_RR(p, 0x1b00, r1, r2);
2646}
2647
2648
sewardj9d31dfd2011-03-15 12:36:44 +00002649static UChar *
sewardj2019a972011-03-07 16:04:07 +00002650s390_emit_SGR(UChar *p, UChar r1, UChar r2)
2651{
sewardj7ee97522011-05-09 21:45:04 +00002652 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002653 s390_disasm(ENC3(MNM, GPR, GPR), "sgr", r1, r2);
2654
2655 return emit_RRE(p, 0xb9090000, r1, r2);
2656}
2657
2658
sewardj9d31dfd2011-03-15 12:36:44 +00002659static UChar *
sewardj2019a972011-03-07 16:04:07 +00002660s390_emit_S(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2661{
sewardj7ee97522011-05-09 21:45:04 +00002662 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002663 s390_disasm(ENC3(MNM, GPR, UDXB), "s", r1, d2, x2, b2);
2664
2665 return emit_RX(p, 0x5b000000, r1, x2, b2, d2);
2666}
2667
2668
sewardj9d31dfd2011-03-15 12:36:44 +00002669static UChar *
sewardj2019a972011-03-07 16:04:07 +00002670s390_emit_SY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2671{
sewardj652b56a2011-04-13 15:38:17 +00002672 vassert(s390_host_has_ldisp);
2673
sewardj7ee97522011-05-09 21:45:04 +00002674 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002675 s390_disasm(ENC3(MNM, GPR, SDXB), "sy", r1, dh2, dl2, x2, b2);
2676
2677 return emit_RXY(p, 0xe3000000005bULL, r1, x2, b2, dl2, dh2);
2678}
2679
2680
sewardj9d31dfd2011-03-15 12:36:44 +00002681static UChar *
sewardj2019a972011-03-07 16:04:07 +00002682s390_emit_SG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2683{
sewardj652b56a2011-04-13 15:38:17 +00002684 vassert(s390_host_has_ldisp || dh2 == 0);
2685
sewardj7ee97522011-05-09 21:45:04 +00002686 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002687 s390_disasm(ENC3(MNM, GPR, SDXB), "sg", r1, dh2, dl2, x2, b2);
2688
2689 return emit_RXY(p, 0xe30000000009ULL, r1, x2, b2, dl2, dh2);
2690}
2691
2692
sewardj9d31dfd2011-03-15 12:36:44 +00002693static UChar *
sewardj2019a972011-03-07 16:04:07 +00002694s390_emit_SH(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2695{
sewardj7ee97522011-05-09 21:45:04 +00002696 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002697 s390_disasm(ENC3(MNM, GPR, UDXB), "sh", r1, d2, x2, b2);
2698
2699 return emit_RX(p, 0x4b000000, r1, x2, b2, d2);
2700}
2701
2702
sewardj9d31dfd2011-03-15 12:36:44 +00002703static UChar *
sewardj2019a972011-03-07 16:04:07 +00002704s390_emit_SHY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2705{
sewardj652b56a2011-04-13 15:38:17 +00002706 vassert(s390_host_has_ldisp);
2707
sewardj7ee97522011-05-09 21:45:04 +00002708 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002709 s390_disasm(ENC3(MNM, GPR, SDXB), "shy", r1, dh2, dl2, x2, b2);
2710
2711 return emit_RXY(p, 0xe3000000007bULL, r1, x2, b2, dl2, dh2);
2712}
2713
2714
sewardj9d31dfd2011-03-15 12:36:44 +00002715static UChar *
sewardj2019a972011-03-07 16:04:07 +00002716s390_emit_SLFI(UChar *p, UChar r1, UInt i2)
2717{
sewardj652b56a2011-04-13 15:38:17 +00002718 vassert(s390_host_has_eimm);
2719
sewardj7ee97522011-05-09 21:45:04 +00002720 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002721 s390_disasm(ENC3(MNM, GPR, UINT), "slfi", r1, i2);
2722
2723 return emit_RIL(p, 0xc20500000000ULL, r1, i2);
2724}
2725
2726
sewardj9d31dfd2011-03-15 12:36:44 +00002727static UChar *
sewardjb13a92a2011-04-13 14:44:29 +00002728s390_emit_SLGFI(UChar *p, UChar r1, UInt i2)
2729{
sewardj7ee97522011-05-09 21:45:04 +00002730 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardjb13a92a2011-04-13 14:44:29 +00002731 s390_disasm(ENC3(MNM, GPR, UINT), "slgfi", r1, i2);
2732
2733 return emit_RIL(p, 0xc20400000000ULL, r1, i2);
2734}
2735
2736
2737static UChar *
sewardj2019a972011-03-07 16:04:07 +00002738s390_emit_LDR(UChar *p, UChar r1, UChar r2)
2739{
sewardj7ee97522011-05-09 21:45:04 +00002740 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002741 s390_disasm(ENC3(MNM, FPR, FPR), "ldr", r1, r2);
2742
2743 return emit_RR(p, 0x2800, r1, r2);
2744}
2745
2746
sewardj9d31dfd2011-03-15 12:36:44 +00002747static UChar *
sewardj2019a972011-03-07 16:04:07 +00002748s390_emit_LE(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2749{
sewardj7ee97522011-05-09 21:45:04 +00002750 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002751 s390_disasm(ENC3(MNM, FPR, UDXB), "le", r1, d2, x2, b2);
2752
2753 return emit_RX(p, 0x78000000, r1, x2, b2, d2);
2754}
2755
2756
sewardj9d31dfd2011-03-15 12:36:44 +00002757static UChar *
sewardj2019a972011-03-07 16:04:07 +00002758s390_emit_LD(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2759{
sewardj7ee97522011-05-09 21:45:04 +00002760 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002761 s390_disasm(ENC3(MNM, FPR, UDXB), "ld", r1, d2, x2, b2);
2762
2763 return emit_RX(p, 0x68000000, r1, x2, b2, d2);
2764}
2765
2766
sewardj9d31dfd2011-03-15 12:36:44 +00002767static UChar *
sewardj2019a972011-03-07 16:04:07 +00002768s390_emit_LEY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2769{
sewardj652b56a2011-04-13 15:38:17 +00002770 vassert(s390_host_has_ldisp);
2771
sewardj7ee97522011-05-09 21:45:04 +00002772 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002773 s390_disasm(ENC3(MNM, FPR, SDXB), "ley", r1, dh2, dl2, x2, b2);
2774
2775 return emit_RXY(p, 0xed0000000064ULL, r1, x2, b2, dl2, dh2);
2776}
2777
2778
sewardj9d31dfd2011-03-15 12:36:44 +00002779static UChar *
sewardj2019a972011-03-07 16:04:07 +00002780s390_emit_LDY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2781{
sewardj652b56a2011-04-13 15:38:17 +00002782 vassert(s390_host_has_ldisp);
2783
sewardj7ee97522011-05-09 21:45:04 +00002784 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002785 s390_disasm(ENC3(MNM, FPR, SDXB), "ldy", r1, dh2, dl2, x2, b2);
2786
2787 return emit_RXY(p, 0xed0000000065ULL, r1, x2, b2, dl2, dh2);
2788}
2789
2790
sewardj9d31dfd2011-03-15 12:36:44 +00002791static UChar *
sewardj2019a972011-03-07 16:04:07 +00002792s390_emit_LFPC(UChar *p, UChar b2, UShort d2)
2793{
sewardj7ee97522011-05-09 21:45:04 +00002794 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002795 s390_disasm(ENC2(MNM, UDXB), "lfpc", d2, 0, b2);
2796
2797 return emit_S(p, 0xb29d0000, b2, d2);
2798}
2799
2800
sewardj9d31dfd2011-03-15 12:36:44 +00002801static UChar *
sewardj2019a972011-03-07 16:04:07 +00002802s390_emit_LDGR(UChar *p, UChar r1, UChar r2)
2803{
sewardjd07b8562011-04-27 11:58:22 +00002804 vassert(s390_host_has_fgx);
2805
sewardj7ee97522011-05-09 21:45:04 +00002806 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002807 s390_disasm(ENC3(MNM, FPR, GPR), "ldgr", r1, r2);
2808
2809 return emit_RRE(p, 0xb3c10000, r1, r2);
2810}
2811
2812
sewardj9d31dfd2011-03-15 12:36:44 +00002813static UChar *
sewardj2019a972011-03-07 16:04:07 +00002814s390_emit_LGDR(UChar *p, UChar r1, UChar r2)
2815{
sewardjd07b8562011-04-27 11:58:22 +00002816 vassert(s390_host_has_fgx);
2817
sewardj7ee97522011-05-09 21:45:04 +00002818 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002819 s390_disasm(ENC3(MNM, GPR, FPR), "lgdr", r1, r2);
2820
2821 return emit_RRE(p, 0xb3cd0000, r1, r2);
2822}
2823
2824
sewardj9d31dfd2011-03-15 12:36:44 +00002825static UChar *
sewardj2019a972011-03-07 16:04:07 +00002826s390_emit_LZER(UChar *p, UChar r1, UChar r2)
2827{
sewardj7ee97522011-05-09 21:45:04 +00002828 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002829 s390_disasm(ENC2(MNM, FPR), "lzer", r1);
2830
2831 return emit_RRE(p, 0xb3740000, r1, r2);
2832}
2833
2834
sewardj9d31dfd2011-03-15 12:36:44 +00002835static UChar *
sewardj2019a972011-03-07 16:04:07 +00002836s390_emit_LZDR(UChar *p, UChar r1, UChar r2)
2837{
sewardj7ee97522011-05-09 21:45:04 +00002838 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002839 s390_disasm(ENC2(MNM, FPR), "lzdr", r1);
2840
2841 return emit_RRE(p, 0xb3750000, r1, r2);
2842}
2843
2844
sewardj9d31dfd2011-03-15 12:36:44 +00002845static UChar *
sewardj2019a972011-03-07 16:04:07 +00002846s390_emit_SFPC(UChar *p, UChar r1, UChar r2)
2847{
sewardj7ee97522011-05-09 21:45:04 +00002848 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002849 s390_disasm(ENC2(MNM, GPR), "sfpc", r1);
2850
2851 return emit_RRE(p, 0xb3840000, r1, r2);
2852}
2853
2854
sewardj9d31dfd2011-03-15 12:36:44 +00002855static UChar *
sewardj2019a972011-03-07 16:04:07 +00002856s390_emit_STE(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2857{
sewardj7ee97522011-05-09 21:45:04 +00002858 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002859 s390_disasm(ENC3(MNM, FPR, UDXB), "ste", r1, d2, x2, b2);
2860
2861 return emit_RX(p, 0x70000000, r1, x2, b2, d2);
2862}
2863
2864
sewardj9d31dfd2011-03-15 12:36:44 +00002865static UChar *
sewardj2019a972011-03-07 16:04:07 +00002866s390_emit_STD(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2867{
sewardj7ee97522011-05-09 21:45:04 +00002868 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002869 s390_disasm(ENC3(MNM, FPR, UDXB), "std", r1, d2, x2, b2);
2870
2871 return emit_RX(p, 0x60000000, r1, x2, b2, d2);
2872}
2873
2874
sewardj9d31dfd2011-03-15 12:36:44 +00002875static UChar *
sewardj2019a972011-03-07 16:04:07 +00002876s390_emit_STEY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2877{
sewardj652b56a2011-04-13 15:38:17 +00002878 vassert(s390_host_has_ldisp);
2879
sewardj7ee97522011-05-09 21:45:04 +00002880 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002881 s390_disasm(ENC3(MNM, FPR, SDXB), "stey", r1, dh2, dl2, x2, b2);
2882
2883 return emit_RXY(p, 0xed0000000066ULL, r1, x2, b2, dl2, dh2);
2884}
2885
2886
sewardj9d31dfd2011-03-15 12:36:44 +00002887static UChar *
sewardj2019a972011-03-07 16:04:07 +00002888s390_emit_STDY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2889{
sewardj652b56a2011-04-13 15:38:17 +00002890 vassert(s390_host_has_ldisp);
2891
sewardj7ee97522011-05-09 21:45:04 +00002892 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002893 s390_disasm(ENC3(MNM, FPR, SDXB), "stdy", r1, dh2, dl2, x2, b2);
2894
2895 return emit_RXY(p, 0xed0000000067ULL, r1, x2, b2, dl2, dh2);
2896}
2897
2898
sewardj9d31dfd2011-03-15 12:36:44 +00002899static UChar *
sewardj2019a972011-03-07 16:04:07 +00002900s390_emit_STFPC(UChar *p, UChar b2, UShort d2)
2901{
sewardj7ee97522011-05-09 21:45:04 +00002902 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002903 s390_disasm(ENC2(MNM, UDXB), "stfpc", d2, 0, b2);
2904
2905 return emit_S(p, 0xb29c0000, b2, d2);
2906}
2907
2908
sewardj9d31dfd2011-03-15 12:36:44 +00002909static UChar *
sewardj2019a972011-03-07 16:04:07 +00002910s390_emit_AEBR(UChar *p, UChar r1, UChar r2)
2911{
sewardj7ee97522011-05-09 21:45:04 +00002912 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002913 s390_disasm(ENC3(MNM, FPR, FPR), "aebr", r1, r2);
2914
2915 return emit_RRE(p, 0xb30a0000, r1, r2);
2916}
2917
2918
sewardj9d31dfd2011-03-15 12:36:44 +00002919static UChar *
sewardj2019a972011-03-07 16:04:07 +00002920s390_emit_ADBR(UChar *p, UChar r1, UChar r2)
2921{
sewardj7ee97522011-05-09 21:45:04 +00002922 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002923 s390_disasm(ENC3(MNM, FPR, FPR), "adbr", r1, r2);
2924
2925 return emit_RRE(p, 0xb31a0000, r1, r2);
2926}
2927
2928
sewardj9d31dfd2011-03-15 12:36:44 +00002929static UChar *
sewardj2019a972011-03-07 16:04:07 +00002930s390_emit_AXBR(UChar *p, UChar r1, UChar r2)
2931{
sewardj7ee97522011-05-09 21:45:04 +00002932 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002933 s390_disasm(ENC3(MNM, FPR, FPR), "axbr", r1, r2);
2934
2935 return emit_RRE(p, 0xb34a0000, r1, r2);
2936}
2937
2938
sewardj9d31dfd2011-03-15 12:36:44 +00002939static UChar *
sewardj2019a972011-03-07 16:04:07 +00002940s390_emit_CEBR(UChar *p, UChar r1, UChar r2)
2941{
sewardj7ee97522011-05-09 21:45:04 +00002942 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002943 s390_disasm(ENC3(MNM, FPR, FPR), "cebr", r1, r2);
2944
2945 return emit_RRE(p, 0xb3090000, r1, r2);
2946}
2947
2948
sewardj9d31dfd2011-03-15 12:36:44 +00002949static UChar *
sewardj2019a972011-03-07 16:04:07 +00002950s390_emit_CDBR(UChar *p, UChar r1, UChar r2)
2951{
sewardj7ee97522011-05-09 21:45:04 +00002952 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002953 s390_disasm(ENC3(MNM, FPR, FPR), "cdbr", r1, r2);
2954
2955 return emit_RRE(p, 0xb3190000, r1, r2);
2956}
2957
2958
sewardj9d31dfd2011-03-15 12:36:44 +00002959static UChar *
sewardj2019a972011-03-07 16:04:07 +00002960s390_emit_CXBR(UChar *p, UChar r1, UChar r2)
2961{
sewardj7ee97522011-05-09 21:45:04 +00002962 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002963 s390_disasm(ENC3(MNM, FPR, FPR), "cxbr", r1, r2);
2964
2965 return emit_RRE(p, 0xb3490000, r1, r2);
2966}
2967
2968
sewardj9d31dfd2011-03-15 12:36:44 +00002969static UChar *
sewardj2019a972011-03-07 16:04:07 +00002970s390_emit_CEFBR(UChar *p, UChar r1, UChar r2)
2971{
sewardj7ee97522011-05-09 21:45:04 +00002972 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002973 s390_disasm(ENC3(MNM, FPR, GPR), "cefbr", r1, r2);
2974
2975 return emit_RRE(p, 0xb3940000, r1, r2);
2976}
2977
2978
sewardj9d31dfd2011-03-15 12:36:44 +00002979static UChar *
sewardj2019a972011-03-07 16:04:07 +00002980s390_emit_CDFBR(UChar *p, UChar r1, UChar r2)
2981{
sewardj7ee97522011-05-09 21:45:04 +00002982 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002983 s390_disasm(ENC3(MNM, FPR, GPR), "cdfbr", r1, r2);
2984
2985 return emit_RRE(p, 0xb3950000, r1, r2);
2986}
2987
2988
sewardj9d31dfd2011-03-15 12:36:44 +00002989static UChar *
sewardj2019a972011-03-07 16:04:07 +00002990s390_emit_CXFBR(UChar *p, UChar r1, UChar r2)
2991{
sewardj7ee97522011-05-09 21:45:04 +00002992 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002993 s390_disasm(ENC3(MNM, FPR, GPR), "cxfbr", r1, r2);
2994
2995 return emit_RRE(p, 0xb3960000, r1, r2);
2996}
2997
2998
sewardj9d31dfd2011-03-15 12:36:44 +00002999static UChar *
sewardj2019a972011-03-07 16:04:07 +00003000s390_emit_CEGBR(UChar *p, UChar r1, UChar r2)
3001{
sewardj7ee97522011-05-09 21:45:04 +00003002 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003003 s390_disasm(ENC3(MNM, FPR, GPR), "cegbr", r1, r2);
3004
3005 return emit_RRE(p, 0xb3a40000, r1, r2);
3006}
3007
3008
sewardj9d31dfd2011-03-15 12:36:44 +00003009static UChar *
sewardj2019a972011-03-07 16:04:07 +00003010s390_emit_CDGBR(UChar *p, UChar r1, UChar r2)
3011{
sewardj7ee97522011-05-09 21:45:04 +00003012 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003013 s390_disasm(ENC3(MNM, FPR, GPR), "cdgbr", r1, r2);
3014
3015 return emit_RRE(p, 0xb3a50000, r1, r2);
3016}
3017
3018
sewardj9d31dfd2011-03-15 12:36:44 +00003019static UChar *
sewardj2019a972011-03-07 16:04:07 +00003020s390_emit_CXGBR(UChar *p, UChar r1, UChar r2)
3021{
sewardj7ee97522011-05-09 21:45:04 +00003022 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003023 s390_disasm(ENC3(MNM, FPR, GPR), "cxgbr", r1, r2);
3024
3025 return emit_RRE(p, 0xb3a60000, r1, r2);
3026}
3027
3028
sewardj9d31dfd2011-03-15 12:36:44 +00003029static UChar *
sewardj2019a972011-03-07 16:04:07 +00003030s390_emit_CFEBR(UChar *p, UChar r3, UChar r1, UChar r2)
3031{
sewardj7ee97522011-05-09 21:45:04 +00003032 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003033 s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cfebr", r1, r3, r2);
3034
3035 return emit_RRF3(p, 0xb3980000, r3, r1, r2);
3036}
3037
3038
sewardj9d31dfd2011-03-15 12:36:44 +00003039static UChar *
sewardj2019a972011-03-07 16:04:07 +00003040s390_emit_CFDBR(UChar *p, UChar r3, UChar r1, UChar r2)
3041{
sewardj7ee97522011-05-09 21:45:04 +00003042 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003043 s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cfdbr", r1, r3, r2);
3044
3045 return emit_RRF3(p, 0xb3990000, r3, r1, r2);
3046}
3047
3048
sewardj9d31dfd2011-03-15 12:36:44 +00003049static UChar *
sewardj2019a972011-03-07 16:04:07 +00003050s390_emit_CFXBR(UChar *p, UChar r3, UChar r1, UChar r2)
3051{
sewardj7ee97522011-05-09 21:45:04 +00003052 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003053 s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cfxbr", r1, r3, r2);
3054
3055 return emit_RRF3(p, 0xb39a0000, r3, r1, r2);
3056}
3057
3058
sewardj9d31dfd2011-03-15 12:36:44 +00003059static UChar *
sewardj2019a972011-03-07 16:04:07 +00003060s390_emit_CGEBR(UChar *p, UChar r3, UChar r1, UChar r2)
3061{
sewardj7ee97522011-05-09 21:45:04 +00003062 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003063 s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cgebr", r1, r3, r2);
3064
3065 return emit_RRF3(p, 0xb3a80000, r3, r1, r2);
3066}
3067
3068
sewardj9d31dfd2011-03-15 12:36:44 +00003069static UChar *
sewardj2019a972011-03-07 16:04:07 +00003070s390_emit_CGDBR(UChar *p, UChar r3, UChar r1, UChar r2)
3071{
sewardj7ee97522011-05-09 21:45:04 +00003072 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003073 s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cgdbr", r1, r3, r2);
3074
3075 return emit_RRF3(p, 0xb3a90000, r3, r1, r2);
3076}
3077
3078
sewardj9d31dfd2011-03-15 12:36:44 +00003079static UChar *
sewardj2019a972011-03-07 16:04:07 +00003080s390_emit_CGXBR(UChar *p, UChar r3, UChar r1, UChar r2)
3081{
sewardj7ee97522011-05-09 21:45:04 +00003082 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003083 s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cgxbr", r1, r3, r2);
3084
3085 return emit_RRF3(p, 0xb3aa0000, r3, r1, r2);
3086}
3087
3088
sewardj9d31dfd2011-03-15 12:36:44 +00003089static UChar *
sewardj2019a972011-03-07 16:04:07 +00003090s390_emit_DEBR(UChar *p, UChar r1, UChar r2)
3091{
sewardj7ee97522011-05-09 21:45:04 +00003092 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003093 s390_disasm(ENC3(MNM, FPR, FPR), "debr", r1, r2);
3094
3095 return emit_RRE(p, 0xb30d0000, r1, r2);
3096}
3097
3098
sewardj9d31dfd2011-03-15 12:36:44 +00003099static UChar *
sewardj2019a972011-03-07 16:04:07 +00003100s390_emit_DDBR(UChar *p, UChar r1, UChar r2)
3101{
sewardj7ee97522011-05-09 21:45:04 +00003102 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003103 s390_disasm(ENC3(MNM, FPR, FPR), "ddbr", r1, r2);
3104
3105 return emit_RRE(p, 0xb31d0000, r1, r2);
3106}
3107
3108
sewardj9d31dfd2011-03-15 12:36:44 +00003109static UChar *
sewardj2019a972011-03-07 16:04:07 +00003110s390_emit_DXBR(UChar *p, UChar r1, UChar r2)
3111{
sewardj7ee97522011-05-09 21:45:04 +00003112 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003113 s390_disasm(ENC3(MNM, FPR, FPR), "dxbr", r1, r2);
3114
3115 return emit_RRE(p, 0xb34d0000, r1, r2);
3116}
3117
3118
sewardj9d31dfd2011-03-15 12:36:44 +00003119static UChar *
sewardj2019a972011-03-07 16:04:07 +00003120s390_emit_LCEBR(UChar *p, UChar r1, UChar r2)
3121{
sewardj7ee97522011-05-09 21:45:04 +00003122 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003123 s390_disasm(ENC3(MNM, FPR, FPR), "lcebr", r1, r2);
3124
3125 return emit_RRE(p, 0xb3030000, r1, r2);
3126}
3127
3128
sewardj9d31dfd2011-03-15 12:36:44 +00003129static UChar *
sewardj2019a972011-03-07 16:04:07 +00003130s390_emit_LCDBR(UChar *p, UChar r1, UChar r2)
3131{
sewardj7ee97522011-05-09 21:45:04 +00003132 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003133 s390_disasm(ENC3(MNM, FPR, FPR), "lcdbr", r1, r2);
3134
3135 return emit_RRE(p, 0xb3130000, r1, r2);
3136}
3137
3138
sewardj9d31dfd2011-03-15 12:36:44 +00003139static UChar *
sewardj2019a972011-03-07 16:04:07 +00003140s390_emit_LCXBR(UChar *p, UChar r1, UChar r2)
3141{
sewardj7ee97522011-05-09 21:45:04 +00003142 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003143 s390_disasm(ENC3(MNM, FPR, FPR), "lcxbr", r1, r2);
3144
3145 return emit_RRE(p, 0xb3430000, r1, r2);
3146}
3147
3148
sewardj9d31dfd2011-03-15 12:36:44 +00003149static UChar *
sewardj2019a972011-03-07 16:04:07 +00003150s390_emit_LDEBR(UChar *p, UChar r1, UChar r2)
3151{
sewardj7ee97522011-05-09 21:45:04 +00003152 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003153 s390_disasm(ENC3(MNM, FPR, FPR), "ldebr", r1, r2);
3154
3155 return emit_RRE(p, 0xb3040000, r1, r2);
3156}
3157
3158
sewardj9d31dfd2011-03-15 12:36:44 +00003159static UChar *
sewardj2019a972011-03-07 16:04:07 +00003160s390_emit_LXDBR(UChar *p, UChar r1, UChar r2)
3161{
sewardj7ee97522011-05-09 21:45:04 +00003162 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003163 s390_disasm(ENC3(MNM, FPR, FPR), "lxdbr", r1, r2);
3164
3165 return emit_RRE(p, 0xb3050000, r1, r2);
3166}
3167
3168
sewardj9d31dfd2011-03-15 12:36:44 +00003169static UChar *
sewardj2019a972011-03-07 16:04:07 +00003170s390_emit_LXEBR(UChar *p, UChar r1, UChar r2)
3171{
sewardj7ee97522011-05-09 21:45:04 +00003172 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003173 s390_disasm(ENC3(MNM, FPR, FPR), "lxebr", r1, r2);
3174
3175 return emit_RRE(p, 0xb3060000, r1, r2);
3176}
3177
3178
sewardj9d31dfd2011-03-15 12:36:44 +00003179static UChar *
sewardj2019a972011-03-07 16:04:07 +00003180s390_emit_LNEBR(UChar *p, UChar r1, UChar r2)
3181{
sewardj7ee97522011-05-09 21:45:04 +00003182 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003183 s390_disasm(ENC3(MNM, FPR, FPR), "lnebr", r1, r2);
3184
3185 return emit_RRE(p, 0xb3010000, r1, r2);
3186}
3187
3188
sewardj9d31dfd2011-03-15 12:36:44 +00003189static UChar *
sewardj2019a972011-03-07 16:04:07 +00003190s390_emit_LNDBR(UChar *p, UChar r1, UChar r2)
3191{
sewardj7ee97522011-05-09 21:45:04 +00003192 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003193 s390_disasm(ENC3(MNM, FPR, FPR), "lndbr", r1, r2);
3194
3195 return emit_RRE(p, 0xb3110000, r1, r2);
3196}
3197
3198
sewardj9d31dfd2011-03-15 12:36:44 +00003199static UChar *
sewardj2019a972011-03-07 16:04:07 +00003200s390_emit_LNXBR(UChar *p, UChar r1, UChar r2)
3201{
sewardj7ee97522011-05-09 21:45:04 +00003202 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003203 s390_disasm(ENC3(MNM, FPR, FPR), "lnxbr", r1, r2);
3204
3205 return emit_RRE(p, 0xb3410000, r1, r2);
3206}
3207
3208
sewardj9d31dfd2011-03-15 12:36:44 +00003209static UChar *
sewardj2019a972011-03-07 16:04:07 +00003210s390_emit_LPEBR(UChar *p, UChar r1, UChar r2)
3211{
sewardj7ee97522011-05-09 21:45:04 +00003212 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003213 s390_disasm(ENC3(MNM, FPR, FPR), "lpebr", r1, r2);
3214
3215 return emit_RRE(p, 0xb3000000, r1, r2);
3216}
3217
3218
sewardj9d31dfd2011-03-15 12:36:44 +00003219static UChar *
sewardj2019a972011-03-07 16:04:07 +00003220s390_emit_LPDBR(UChar *p, UChar r1, UChar r2)
3221{
sewardj7ee97522011-05-09 21:45:04 +00003222 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003223 s390_disasm(ENC3(MNM, FPR, FPR), "lpdbr", r1, r2);
3224
3225 return emit_RRE(p, 0xb3100000, r1, r2);
3226}
3227
3228
sewardj9d31dfd2011-03-15 12:36:44 +00003229static UChar *
sewardj2019a972011-03-07 16:04:07 +00003230s390_emit_LPXBR(UChar *p, UChar r1, UChar r2)
3231{
sewardj7ee97522011-05-09 21:45:04 +00003232 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003233 s390_disasm(ENC3(MNM, FPR, FPR), "lpxbr", r1, r2);
3234
3235 return emit_RRE(p, 0xb3400000, r1, r2);
3236}
3237
3238
sewardj9d31dfd2011-03-15 12:36:44 +00003239static UChar *
sewardj2019a972011-03-07 16:04:07 +00003240s390_emit_LEDBR(UChar *p, UChar r1, UChar r2)
3241{
sewardj7ee97522011-05-09 21:45:04 +00003242 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003243 s390_disasm(ENC3(MNM, FPR, FPR), "ledbr", r1, r2);
3244
3245 return emit_RRE(p, 0xb3440000, r1, r2);
3246}
3247
3248
sewardj9d31dfd2011-03-15 12:36:44 +00003249static UChar *
sewardj2019a972011-03-07 16:04:07 +00003250s390_emit_LDXBR(UChar *p, UChar r1, UChar r2)
3251{
sewardj7ee97522011-05-09 21:45:04 +00003252 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003253 s390_disasm(ENC3(MNM, FPR, FPR), "ldxbr", r1, r2);
3254
3255 return emit_RRE(p, 0xb3450000, r1, r2);
3256}
3257
3258
sewardj9d31dfd2011-03-15 12:36:44 +00003259static UChar *
sewardj2019a972011-03-07 16:04:07 +00003260s390_emit_LEXBR(UChar *p, UChar r1, UChar r2)
3261{
sewardj7ee97522011-05-09 21:45:04 +00003262 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003263 s390_disasm(ENC3(MNM, FPR, FPR), "lexbr", r1, r2);
3264
3265 return emit_RRE(p, 0xb3460000, r1, r2);
3266}
3267
3268
sewardj9d31dfd2011-03-15 12:36:44 +00003269static UChar *
sewardj2019a972011-03-07 16:04:07 +00003270s390_emit_MEEBR(UChar *p, UChar r1, UChar r2)
3271{
sewardj7ee97522011-05-09 21:45:04 +00003272 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003273 s390_disasm(ENC3(MNM, FPR, FPR), "meebr", r1, r2);
3274
3275 return emit_RRE(p, 0xb3170000, r1, r2);
3276}
3277
3278
sewardj9d31dfd2011-03-15 12:36:44 +00003279static UChar *
sewardj2019a972011-03-07 16:04:07 +00003280s390_emit_MDBR(UChar *p, UChar r1, UChar r2)
3281{
sewardj7ee97522011-05-09 21:45:04 +00003282 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003283 s390_disasm(ENC3(MNM, FPR, FPR), "mdbr", r1, r2);
3284
3285 return emit_RRE(p, 0xb31c0000, r1, r2);
3286}
3287
3288
sewardj9d31dfd2011-03-15 12:36:44 +00003289static UChar *
sewardj2019a972011-03-07 16:04:07 +00003290s390_emit_MXBR(UChar *p, UChar r1, UChar r2)
3291{
sewardj7ee97522011-05-09 21:45:04 +00003292 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003293 s390_disasm(ENC3(MNM, FPR, FPR), "mxbr", r1, r2);
3294
3295 return emit_RRE(p, 0xb34c0000, r1, r2);
3296}
3297
3298
sewardj9d31dfd2011-03-15 12:36:44 +00003299static UChar *
sewardj2019a972011-03-07 16:04:07 +00003300s390_emit_MAEBR(UChar *p, UChar r1, UChar r3, UChar r2)
3301{
sewardj7ee97522011-05-09 21:45:04 +00003302 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003303 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "maebr", r1, r3, r2);
3304
3305 return emit_RRF(p, 0xb30e0000, r1, r3, r2);
3306}
3307
3308
sewardj9d31dfd2011-03-15 12:36:44 +00003309static UChar *
sewardj2019a972011-03-07 16:04:07 +00003310s390_emit_MADBR(UChar *p, UChar r1, UChar r3, UChar r2)
3311{
sewardj7ee97522011-05-09 21:45:04 +00003312 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003313 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "madbr", r1, r3, r2);
3314
3315 return emit_RRF(p, 0xb31e0000, r1, r3, r2);
3316}
3317
3318
sewardj9d31dfd2011-03-15 12:36:44 +00003319static UChar *
sewardj2019a972011-03-07 16:04:07 +00003320s390_emit_MSEBR(UChar *p, UChar r1, UChar r3, UChar r2)
3321{
sewardj7ee97522011-05-09 21:45:04 +00003322 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003323 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "msebr", r1, r3, r2);
3324
3325 return emit_RRF(p, 0xb30f0000, r1, r3, r2);
3326}
3327
3328
sewardj9d31dfd2011-03-15 12:36:44 +00003329static UChar *
sewardj2019a972011-03-07 16:04:07 +00003330s390_emit_MSDBR(UChar *p, UChar r1, UChar r3, UChar r2)
3331{
sewardj7ee97522011-05-09 21:45:04 +00003332 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003333 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "msdbr", r1, r3, r2);
3334
3335 return emit_RRF(p, 0xb31f0000, r1, r3, r2);
3336}
3337
3338
sewardj9d31dfd2011-03-15 12:36:44 +00003339static UChar *
sewardj2019a972011-03-07 16:04:07 +00003340s390_emit_SQEBR(UChar *p, UChar r1, UChar r2)
3341{
sewardj7ee97522011-05-09 21:45:04 +00003342 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003343 s390_disasm(ENC3(MNM, FPR, FPR), "sqebr", r1, r2);
3344
3345 return emit_RRE(p, 0xb3140000, r1, r2);
3346}
3347
3348
sewardj9d31dfd2011-03-15 12:36:44 +00003349static UChar *
sewardj2019a972011-03-07 16:04:07 +00003350s390_emit_SQDBR(UChar *p, UChar r1, UChar r2)
3351{
sewardj7ee97522011-05-09 21:45:04 +00003352 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003353 s390_disasm(ENC3(MNM, FPR, FPR), "sqdbr", r1, r2);
3354
3355 return emit_RRE(p, 0xb3150000, r1, r2);
3356}
3357
3358
sewardj9d31dfd2011-03-15 12:36:44 +00003359static UChar *
sewardj2019a972011-03-07 16:04:07 +00003360s390_emit_SQXBR(UChar *p, UChar r1, UChar r2)
3361{
sewardj7ee97522011-05-09 21:45:04 +00003362 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003363 s390_disasm(ENC3(MNM, FPR, FPR), "sqxbr", r1, r2);
3364
3365 return emit_RRE(p, 0xb3160000, r1, r2);
3366}
3367
3368
sewardj9d31dfd2011-03-15 12:36:44 +00003369static UChar *
sewardj2019a972011-03-07 16:04:07 +00003370s390_emit_SEBR(UChar *p, UChar r1, UChar r2)
3371{
sewardj7ee97522011-05-09 21:45:04 +00003372 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003373 s390_disasm(ENC3(MNM, FPR, FPR), "sebr", r1, r2);
3374
3375 return emit_RRE(p, 0xb30b0000, r1, r2);
3376}
3377
3378
sewardj9d31dfd2011-03-15 12:36:44 +00003379static UChar *
sewardj2019a972011-03-07 16:04:07 +00003380s390_emit_SDBR(UChar *p, UChar r1, UChar r2)
3381{
sewardj7ee97522011-05-09 21:45:04 +00003382 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003383 s390_disasm(ENC3(MNM, FPR, FPR), "sdbr", r1, r2);
3384
3385 return emit_RRE(p, 0xb31b0000, r1, r2);
3386}
3387
3388
sewardj9d31dfd2011-03-15 12:36:44 +00003389static UChar *
sewardj2019a972011-03-07 16:04:07 +00003390s390_emit_SXBR(UChar *p, UChar r1, UChar r2)
3391{
sewardj7ee97522011-05-09 21:45:04 +00003392 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003393 s390_disasm(ENC3(MNM, FPR, FPR), "sxbr", r1, r2);
3394
3395 return emit_RRE(p, 0xb34b0000, r1, r2);
3396}
3397
sewardj2019a972011-03-07 16:04:07 +00003398
3399/* Provide a symbolic name for register "R0" */
3400#define R0 0
3401
3402/* Split up a 20-bit displacement into its high and low piece
3403 suitable for passing as function arguments */
sewardjcd2b0252011-05-09 20:35:41 +00003404#define DISP20(d) (((UInt)d) & 0xFFF), ((((UInt)d) >> 12) & 0xFF)
sewardj2019a972011-03-07 16:04:07 +00003405
3406/*---------------------------------------------------------------*/
3407/*--- Helper functions ---*/
3408/*---------------------------------------------------------------*/
3409
3410static __inline__ Bool
3411uint_fits_signed_16bit(UInt val)
3412{
3413 int v = val & 0xFFFFu;
3414
3415 /* sign extend */
3416 v = (v << 16) >> 16;
3417
3418 return val == (UInt)v;
3419}
3420
3421
3422static __inline__ Bool
3423ulong_fits_signed_16bit(ULong val)
3424{
3425 Long v = val & 0xFFFFu;
3426
3427 /* sign extend */
3428 v = (v << 48) >> 48;
3429
3430 return val == (ULong)v;
3431}
3432
3433
3434static __inline__ Bool
3435ulong_fits_signed_32bit(ULong val)
3436{
3437 Long v = val & 0xFFFFFFFFu;
3438
3439 /* sign extend */
3440 v = (v << 32) >> 32;
3441
3442 return val == (ULong)v;
3443}
3444
3445
3446static __inline__ Bool
3447ulong_fits_unsigned_32bit(ULong val)
3448{
3449 return (val & 0xFFFFFFFFu) == val;
3450}
3451
3452
3453/* Load a 64-bit immediate VAL into register REG. */
3454static UChar *
3455s390_emit_load_64imm(UChar *p, UChar reg, ULong val)
3456{
3457 if (ulong_fits_signed_16bit(val)) {
3458 return s390_emit_LGHI(p, reg, val);
3459 }
3460
3461 if (s390_host_has_eimm) {
3462 if (ulong_fits_unsigned_32bit(val)) {
3463 return s390_emit_LLILF(p, reg, val);
3464 }
3465 if (ulong_fits_signed_32bit(val)) {
3466 /* LGFI's sign extension will recreate the correct 64-bit value */
3467 return s390_emit_LGFI(p, reg, val);
3468 }
3469 /* Do it in two steps: upper half [0:31] and lower half [32:63] */
3470 p = s390_emit_IIHF(p, reg, val >> 32);
3471 return s390_emit_IILF(p, reg, val & 0xFFFFFFFF);
3472 }
3473
3474 /* Fall back */
3475 if (ulong_fits_unsigned_32bit(val)) {
3476 p = s390_emit_LLILH(p, reg, (val >> 16) & 0xFFFF); /* sets val[32:47]
3477 val[0:31] = 0 */
3478 p = s390_emit_IILL(p, reg, val & 0xFFFF); /* sets val[48:63] */
3479 return p;
3480 }
3481
3482 p = s390_emit_IIHH(p, reg, (val >> 48) & 0xFFFF);
3483 p = s390_emit_IIHL(p, reg, (val >> 32) & 0xFFFF);
3484 p = s390_emit_IILH(p, reg, (val >> 16) & 0xFFFF);
3485 p = s390_emit_IILL(p, reg, val & 0xFFFF);
3486
3487 return p;
3488}
3489
3490/* Load a 32-bit immediate VAL into register REG. */
3491static UChar *
3492s390_emit_load_32imm(UChar *p, UChar reg, UInt val)
3493{
3494 if (uint_fits_signed_16bit(val)) {
3495 /* LHI's sign extension will recreate the correct 32-bit value */
3496 return s390_emit_LHI(p, reg, val);
3497 }
3498 if (s390_host_has_eimm) {
3499 return s390_emit_IILF(p, reg, val);
3500 }
3501 /* val[0:15] --> (val >> 16) & 0xFFFF
3502 val[16:31] --> val & 0xFFFF */
3503 p = s390_emit_IILH(p, reg, (val >> 16) & 0xFFFF);
3504 return s390_emit_IILL(p, reg, val & 0xFFFF);
3505}
3506
3507/*------------------------------------------------------------*/
3508/*--- Wrapper functions ---*/
3509/*------------------------------------------------------------*/
3510
sewardjeae8db52011-03-24 09:01:50 +00003511/* r1[32:63],r1+1[32:63] = r1+1[32:63] * memory[op2addr][0:31] */
sewardj2019a972011-03-07 16:04:07 +00003512static UChar *
3513s390_emit_MFYw(UChar *p, UChar r1, UChar x, UChar b, UShort dl, UChar dh)
3514{
3515 if (s390_host_has_gie) {
3516 return s390_emit_MFY(p, r1, x, b, dl, dh);
3517 }
3518
3519 /* Load from memory into R0, then MULTIPLY with R1 */
3520 p = s390_emit_LY(p, R0, x, b, dl, dh);
3521 return s390_emit_MR(p, r1, R0);
3522}
3523
sewardjeae8db52011-03-24 09:01:50 +00003524/* r1[32:63] = r1[32:63] * memory[op2addr][0:15] */
3525static UChar *
3526s390_emit_MHYw(UChar *p, UChar r1, UChar x, UChar b, UShort dl, UChar dh)
3527{
3528 if (s390_host_has_gie) {
3529 return s390_emit_MHY(p, r1, x, b, dl, dh);
3530 }
3531
3532 /* Load from memory into R0, then MULTIPLY with R1 */
3533 p = s390_emit_LHY(p, R0, x, b, dl, dh);
3534 return s390_emit_MSR(p, r1, R0);
3535}
3536
sewardj2019a972011-03-07 16:04:07 +00003537/* r1[32:63] = r1[32:63] * i2 */
3538static UChar *
3539s390_emit_MSFIw(UChar *p, UChar r1, UInt i2)
3540{
3541 if (s390_host_has_gie) {
3542 return s390_emit_MSFI(p, r1, i2);
3543 }
3544
3545 /* Load I2 into R0; then MULTIPLY R0 with R1 */
3546 p = s390_emit_load_32imm(p, R0, i2);
3547 return s390_emit_MSR(p, r1, R0);
3548}
3549
3550
3551/* r1[32:63] = r1[32:63] & i2 */
3552static UChar *
3553s390_emit_NILFw(UChar *p, UChar r1, UInt i2)
3554{
3555 if (s390_host_has_eimm) {
3556 return s390_emit_NILF(p, r1, i2);
3557 }
3558
3559 /* Load I2 into R0; then AND R0 with R1 */
3560 p = s390_emit_load_32imm(p, R0, i2);
3561 return s390_emit_NR(p, r1, R0);
3562}
3563
3564
3565/* r1[32:63] = r1[32:63] | i2 */
3566static UChar *
3567s390_emit_OILFw(UChar *p, UChar r1, UInt i2)
3568{
3569 if (s390_host_has_eimm) {
3570 return s390_emit_OILF(p, r1, i2);
3571 }
3572
3573 /* Load I2 into R0; then AND R0 with R1 */
3574 p = s390_emit_load_32imm(p, R0, i2);
3575 return s390_emit_OR(p, r1, R0);
3576}
3577
3578
3579/* r1[32:63] = r1[32:63] ^ i2 */
3580static UChar *
3581s390_emit_XILFw(UChar *p, UChar r1, UInt i2)
3582{
3583 if (s390_host_has_eimm) {
3584 return s390_emit_XILF(p, r1, i2);
3585 }
3586
3587 /* Load I2 into R0; then AND R0 with R1 */
3588 p = s390_emit_load_32imm(p, R0, i2);
3589 return s390_emit_XR(p, r1, R0);
3590}
3591
3592
sewardj652b56a2011-04-13 15:38:17 +00003593/* r1[32:63] = sign_extend(mem[op2addr][0:7]) */
3594static UChar *
3595s390_emit_LBw(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3596{
3597 vassert(s390_host_has_ldisp || dh2 == 0);
3598
3599 if (s390_host_has_ldisp) {
3600 return s390_emit_LB(p, r1, x2, b2, dl2, dh2);
3601 }
3602
3603 p = s390_emit_IC(p, r1, x2, b2, dl2); /* r1[56:63] = mem[op2addr][0:7] */
3604 p = s390_emit_SLL(p, r1, R0, 24); /* r1 = r1 << 24 */
3605 return s390_emit_SRA(p, r1, R0, 24); /* r1 = r1 >>a 24 */
3606}
3607
3608
sewardj2019a972011-03-07 16:04:07 +00003609/* r1[32:63] = sign_extend(r2[56:63]) */
3610static UChar *
3611s390_emit_LBRw(UChar *p, UChar r1, UChar r2)
3612{
3613 if (s390_host_has_eimm) {
3614 return s390_emit_LBR(p, r1, r2);
3615 }
3616
3617 p = s390_emit_LR(p, r1, r2); /* r1 = r2 */
sewardj3c49aaa2011-04-05 14:00:37 +00003618 p = s390_emit_SLL(p, r1, R0, 24); /* r1 = r1 << 24 */
3619 return s390_emit_SRA(p, r1, R0, 24); /* r1 = r1 >>a 24 */
sewardj2019a972011-03-07 16:04:07 +00003620}
3621
3622
sewardj652b56a2011-04-13 15:38:17 +00003623/* r1[0:63] = sign_extend(mem[op2addr][0:7]) */
3624static UChar *
3625s390_emit_LGBw(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3626{
3627 vassert(s390_host_has_ldisp || dh2 == 0);
3628
3629 if (s390_host_has_ldisp) {
3630 return s390_emit_LGB(p, r1, x2, b2, dl2, dh2);
3631 }
3632
3633 p = s390_emit_IC(p, r1, x2, b2, dl2); /* r1[56:63] = mem[op2addr][0:7] */
3634 p = s390_emit_SLLG(p, r1, r1, R0, DISP20(56)); /* r1 = r1 << 56 */
3635 return s390_emit_SRAG(p, r1, r1, R0, DISP20(56)); /* r1 = r1 >>a 56 */
3636}
3637
3638
sewardj2019a972011-03-07 16:04:07 +00003639/* r1[0:63] = sign_extend(r2[56:63]) */
3640static UChar *
3641s390_emit_LGBRw(UChar *p, UChar r1, UChar r2)
3642{
3643 if (s390_host_has_eimm) {
3644 return s390_emit_LGBR(p, r1, r2);
3645 }
3646
3647 p = s390_emit_LR(p, r1, r2); /* r1 = r2 */
3648 p = s390_emit_SLLG(p, r1, r1, R0, DISP20(56)); /* r1 = r1 << 56 */
3649 return s390_emit_SRAG(p, r1, r1, R0, DISP20(56)); /* r1 = r1 >>a 56 */
3650}
3651
3652
3653/* r1[32:63] = sign_extend(r2[48:63]) */
3654static UChar *
3655s390_emit_LHRw(UChar *p, UChar r1, UChar r2)
3656{
3657 if (s390_host_has_eimm) {
3658 return s390_emit_LHR(p, r1, r2);
3659 }
3660
3661 p = s390_emit_LR(p, r1, r2); /* r1 = r2 */
sewardj3c49aaa2011-04-05 14:00:37 +00003662 p = s390_emit_SLL(p, r1, R0, 16); /* r1 = r1 << 16 */
3663 return s390_emit_SRA(p, r1, R0, 16); /* r1 = r1 >>a 16 */
sewardj2019a972011-03-07 16:04:07 +00003664}
3665
3666
3667/* r1[0:63] = sign_extend(r2[48:63]) */
3668static UChar *
3669s390_emit_LGHRw(UChar *p, UChar r1, UChar r2)
3670{
3671 if (s390_host_has_eimm) {
3672 return s390_emit_LGHR(p, r1, r2);
3673 }
3674
3675 p = s390_emit_LR(p, r1, r2); /* r1 = r2 */
3676 p = s390_emit_SLLG(p, r1, r1, R0, DISP20(48)); /* r1 = r1 << 48 */
3677 return s390_emit_SRAG(p, r1, r1, R0, DISP20(48)); /* r1 = r1 >>a 48 */
3678}
3679
3680
3681/* r1[0:63] = sign_extend(i2) */
3682static UChar *
3683s390_emit_LGFIw(UChar *p, UChar r1, UInt i2)
3684{
3685 if (s390_host_has_eimm) {
3686 return s390_emit_LGFI(p, r1, i2);
3687 }
3688
3689 p = s390_emit_load_32imm(p, R0, i2);
3690 return s390_emit_LGFR(p, r1, R0);
3691}
3692
3693
3694/* r1[32:63] = zero_extend($r2[56:63]) */
3695static UChar *
3696s390_emit_LLCRw(UChar *p, UChar r1, UChar r2)
3697{
3698 if (s390_host_has_eimm) {
3699 return s390_emit_LLCR(p, r1, r2);
3700 }
3701
3702 p = s390_emit_LR(p, r1, r2);
3703 p = s390_emit_LHI(p, R0, 0xFF);
3704 return s390_emit_NR(p, r1, R0);
3705}
3706
3707
3708/* r1[0:63] = zero_extend($r2[56:63]) */
3709static UChar *
3710s390_emit_LLGCRw(UChar *p, UChar r1, UChar r2)
3711{
3712 if (s390_host_has_eimm) {
3713 return s390_emit_LLGCR(p, r1, r2);
3714 }
3715
3716 p = s390_emit_LR(p, r1, r2);
3717 p = s390_emit_LLILL(p, R0, 0xFF);
3718 return s390_emit_NGR(p, r1, R0);
3719}
3720
3721
3722/* r1[32:63] = zero_extend(r2[48:63]) */
3723static UChar *
3724s390_emit_LLHRw(UChar *p, UChar r1, UChar r2)
3725{
3726 if (s390_host_has_eimm) {
3727 return s390_emit_LLHR(p, r1, r2);
3728 }
3729
3730 p = s390_emit_LR(p, r1, r2);
3731 p = s390_emit_LLILL(p, R0, 0xFFFF);
3732 return s390_emit_NR(p, r1, R0);
3733}
3734
3735
3736/* r1[0:63] = zero_extend(r2[48:63]) */
3737static UChar *
3738s390_emit_LLGHRw(UChar *p, UChar r1, UChar r2)
3739{
3740 if (s390_host_has_eimm) {
3741 return s390_emit_LLGHR(p, r1, r2);
3742 }
3743
3744 p = s390_emit_LR(p, r1, r2);
3745 p = s390_emit_LLILL(p, R0, 0xFFFF);
3746 return s390_emit_NGR(p, r1, R0);
3747}
3748
3749
3750/* r1[32:63] = zero_extend(mem[op2addr][0:7]) */
3751static UChar *
3752s390_emit_LLCw(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl, UChar dh)
3753{
3754 if (s390_host_has_eimm) {
3755 return s390_emit_LLC(p, r1, x2, b2, dl, dh);
3756 }
3757
3758 if (dh == 0) {
3759 p = s390_emit_IC(p, r1, x2, b2, dl);
3760 } else {
3761 p = s390_emit_ICY(p, r1, x2, b2, dl, dh);
3762 }
3763 p = s390_emit_LLILL(p, R0, 0xFF);
3764 return s390_emit_NR(p, r1, R0);
3765}
3766
3767
3768/* r1[32:63] = zero_extend(mem[op2addr][0:15]) */
3769static UChar *
3770s390_emit_LLHw(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl, UChar dh)
3771{
3772 if (s390_host_has_eimm) {
3773 return s390_emit_LLH(p, r1, x2, b2, dl, dh);
3774 }
3775
3776 p = s390_emit_LLGH(p, r1, x2, b2, dl, dh);
3777 p = s390_emit_LLILL(p, R0, 0xFFFF);
3778 return s390_emit_NR(p, r1, R0);
3779}
3780
3781
3782/* r1[0:63] = zero_extend(i2) */
3783static UChar *
3784s390_emit_LLILFw(UChar *p, UChar r1, UInt i2)
3785{
3786 if (s390_host_has_eimm) {
3787 return s390_emit_LLILF(p, r1, i2);
3788 }
3789
3790 p = s390_emit_LLILH(p, r1, (i2 >> 16) & 0xFFFF); /* i2[0:15] */
3791 return s390_emit_OILL(p, r1, i2 & 0xFFFF);
3792}
3793
3794
3795/* r1[32:63] = r1[32:63] + i2 */
3796static UChar *
3797s390_emit_AFIw(UChar *p, UChar r1, UInt i2)
3798{
3799 if (s390_host_has_eimm) {
3800 return s390_emit_AFI(p, r1, i2);
3801 }
3802 /* Load 32 bit immediate to R0 then add */
3803 p = s390_emit_load_32imm(p, R0, i2);
3804 return s390_emit_AR(p, r1, R0);
3805}
3806
3807
3808/* r1[32:63] = r1[32:63] - i2 */
3809static UChar *
3810s390_emit_SLFIw(UChar *p, UChar r1, UInt i2)
3811{
3812 if (s390_host_has_eimm) {
3813 return s390_emit_SLFI(p, r1, i2);
3814 }
3815
3816 /* Load 32 bit immediate to R0 then subtract */
3817 p = s390_emit_load_32imm(p, R0, i2);
3818 return s390_emit_SR(p, r1, R0);
3819}
3820
3821
sewardjb13a92a2011-04-13 14:44:29 +00003822/* r1[0:63] = r1[0:63] - zero_extend(i2) */
3823static UChar *
3824s390_emit_SLGFIw(UChar *p, UChar r1, UInt i2)
3825{
3826 if (s390_host_has_eimm) {
3827 return s390_emit_SLGFI(p, r1, i2);
3828 }
3829
3830 /* Load zero-extended 32 bit immediate to R0 then subtract */
3831 p = s390_emit_load_64imm(p, R0, i2);
3832 return s390_emit_SGR(p, r1, R0);
3833}
3834
3835
sewardj2019a972011-03-07 16:04:07 +00003836static UChar *
3837s390_emit_LTw(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl, UChar dh)
3838{
3839 if (s390_host_has_eimm) {
3840 return s390_emit_LT(p, r1, x2, b2, dl, dh);
3841 }
3842 /* Load 32 bit from memory to R0 then compare */
3843 if (dh == 0) {
3844 p = s390_emit_L(p, R0, x2, b2, dl);
3845 } else {
3846 p = s390_emit_LY(p, R0, x2, b2, dl, dh);
3847 }
3848 return s390_emit_LTR(p, r1, R0);
3849}
3850
3851
3852static UChar *
3853s390_emit_LTGw(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl, UChar dh)
3854{
3855 if (s390_host_has_eimm) {
3856 return s390_emit_LTG(p, r1, x2, b2, dl, dh);
3857 }
3858 /* Load 64 bit from memory to R0 then compare */
3859 p = s390_emit_LG(p, R0, x2, b2, dl, dh);
3860 return s390_emit_LTGR(p, r1, R0);
3861}
3862
3863
3864static UChar *
3865s390_emit_CFIw(UChar *p, UChar r1, UInt i2)
3866{
3867 if (s390_host_has_eimm) {
3868 return s390_emit_CFI(p, r1, i2);
3869 }
3870 /* Load 32 bit immediate to R0 then compare */
3871 p = s390_emit_load_32imm(p, R0, i2);
3872 return s390_emit_CR(p, r1, R0);
3873}
3874
3875
3876static UChar *
3877s390_emit_CLFIw(UChar *p, UChar r1, UInt i2)
3878{
3879 if (s390_host_has_eimm) {
3880 return s390_emit_CLFI(p, r1, i2);
3881 }
3882 /* Load 32 bit immediate to R0 then compare */
3883 p = s390_emit_load_32imm(p, R0, i2);
3884 return s390_emit_CLR(p, r1, R0);
3885}
3886
sewardjd07b8562011-04-27 11:58:22 +00003887
3888static UChar *
3889s390_emit_LGDRw(UChar *p, UChar r1, UChar r2)
3890{
3891 if (s390_host_has_fgx) {
3892 return s390_emit_LGDR(p, r1, r2);
3893 }
3894
3895 /* Store the FPR at memory[sp - 8]. This is safe because SP grows towards
3896 smaller addresses and is 8-byte aligned. Then load the GPR from that
3897 memory location/ */
3898 if (s390_host_has_ldisp) {
3899 p = s390_emit_STDY(p, r2, R0, S390_REGNO_STACK_POINTER, DISP20(-8));
3900 return s390_emit_LG(p, r1, R0, S390_REGNO_STACK_POINTER, DISP20(-8));
3901 }
3902
3903 /* No long displacement. Need to adjust SP explicitly as to avoid negative
3904 displacements. */
3905 p = s390_emit_AGHI(p, S390_REGNO_STACK_POINTER, -8);
3906 p = s390_emit_STD(p, r2, R0, S390_REGNO_STACK_POINTER, 0);
3907 p = s390_emit_LG(p, r1, R0, S390_REGNO_STACK_POINTER, DISP20(0));
3908 return s390_emit_AGHI(p, S390_REGNO_STACK_POINTER, 8);
3909}
3910
3911
3912static UChar *
3913s390_emit_LDGRw(UChar *p, UChar r1, UChar r2)
3914{
3915 if (s390_host_has_fgx) {
3916 return s390_emit_LDGR(p, r1, r2);
3917 }
3918
3919 /* Store the GPR at memory[sp - 8]. This is safe because SP grows towards
3920 smaller addresses and is 8-byte aligned. Then load the FPR from that
3921 memory location/ */
3922 if (s390_host_has_ldisp) {
3923 p = s390_emit_STG(p, r2, R0, S390_REGNO_STACK_POINTER, DISP20(-8));
3924 return s390_emit_LDY(p, r1, R0, S390_REGNO_STACK_POINTER, DISP20(-8));
3925 }
3926
3927 /* No long displacement. Need to adjust SP explicitly as to avoid negative
3928 displacements. */
3929 p = s390_emit_AGHI(p, S390_REGNO_STACK_POINTER, -8);
3930 p = s390_emit_STG(p, r2, R0, S390_REGNO_STACK_POINTER, DISP20(0));
3931 p = s390_emit_LD(p, r1, R0, S390_REGNO_STACK_POINTER, 0);
3932 return s390_emit_AGHI(p, S390_REGNO_STACK_POINTER, 8);
3933}
3934
3935
sewardj2019a972011-03-07 16:04:07 +00003936/*---------------------------------------------------------------*/
3937/*--- Constructors for the various s390_insn kinds ---*/
3938/*---------------------------------------------------------------*/
3939
3940s390_insn *
3941s390_insn_load(UChar size, HReg dst, s390_amode *src)
3942{
3943 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
3944
3945 insn->tag = S390_INSN_LOAD;
3946 insn->size = size;
3947 insn->variant.load.src = src;
3948 insn->variant.load.dst = dst;
3949
3950 vassert(size == 1 || size == 2 || size == 4 || size == 8);
3951
3952 return insn;
3953}
3954
3955
3956s390_insn *
3957s390_insn_store(UChar size, s390_amode *dst, HReg src)
3958{
3959 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
3960
3961 insn->tag = S390_INSN_STORE;
3962 insn->size = size;
3963 insn->variant.store.src = src;
3964 insn->variant.store.dst = dst;
3965
3966 vassert(size == 1 || size == 2 || size == 4 || size == 8);
3967
3968 return insn;
3969}
3970
3971
3972s390_insn *
3973s390_insn_move(UChar size, HReg dst, HReg src)
3974{
3975 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
3976
3977 insn->tag = S390_INSN_MOVE;
3978 insn->size = size;
3979 insn->variant.move.src = src;
3980 insn->variant.move.dst = dst;
3981
3982 vassert(size == 1 || size == 2 || size == 4 || size == 8);
3983
3984 return insn;
3985}
3986
3987
3988s390_insn *
3989s390_insn_cond_move(UChar size, s390_cc_t cond, HReg dst, s390_opnd_RMI src)
3990{
3991 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
3992
3993 insn->tag = S390_INSN_COND_MOVE;
3994 insn->size = size;
3995 insn->variant.cond_move.cond = cond;
3996 insn->variant.cond_move.src = src;
3997 insn->variant.cond_move.dst = dst;
3998
3999 vassert(size == 1 || size == 2 || size == 4 || size == 8);
4000
4001 return insn;
4002}
4003
4004
4005s390_insn *
4006s390_insn_load_immediate(UChar size, HReg dst, ULong value)
4007{
4008 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4009
4010 insn->tag = S390_INSN_LOAD_IMMEDIATE;
4011 insn->size = size;
4012 insn->variant.load_immediate.dst = dst;
4013 insn->variant.load_immediate.value = value;
4014
4015 return insn;
4016}
4017
4018
4019s390_insn *
4020s390_insn_alu(UChar size, s390_alu_t tag, HReg dst, s390_opnd_RMI op2)
4021{
4022 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4023
4024 insn->tag = S390_INSN_ALU;
4025 insn->size = size;
4026 insn->variant.alu.tag = tag;
4027 insn->variant.alu.dst = dst;
4028 insn->variant.alu.op2 = op2;
4029
4030 return insn;
4031}
4032
4033
4034s390_insn *
4035s390_insn_mul(UChar size, HReg dst_hi, HReg dst_lo, s390_opnd_RMI op2,
4036 Bool signed_multiply)
4037{
4038 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4039
4040 vassert(! hregIsVirtual(dst_hi));
4041 vassert(! hregIsVirtual(dst_lo));
4042
4043 insn->tag = S390_INSN_MUL;
4044 insn->size = size;
4045 insn->variant.mul.dst_hi = dst_hi;
4046 insn->variant.mul.dst_lo = dst_lo;
4047 insn->variant.mul.op2 = op2;
4048 insn->variant.mul.signed_multiply = signed_multiply;
4049
4050 return insn;
4051}
4052
4053
4054s390_insn *
4055s390_insn_div(UChar size, HReg op1_hi, HReg op1_lo, s390_opnd_RMI op2,
4056 Bool signed_divide)
4057{
4058 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4059
4060 vassert(size == 4 || size == 8);
4061 vassert(! hregIsVirtual(op1_hi));
4062 vassert(! hregIsVirtual(op1_lo));
4063
4064 insn->tag = S390_INSN_DIV;
4065 insn->size = size;
4066 insn->variant.div.op1_hi = op1_hi;
4067 insn->variant.div.op1_lo = op1_lo;
4068 insn->variant.div.op2 = op2;
4069 insn->variant.div.signed_divide = signed_divide;
4070
4071 return insn;
4072}
4073
4074
4075s390_insn *
4076s390_insn_divs(UChar size, HReg rem, HReg op1, s390_opnd_RMI op2)
4077{
4078 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4079
4080 vassert(size == 8);
4081 vassert(! hregIsVirtual(op1));
4082 vassert(! hregIsVirtual(rem));
4083
4084 insn->tag = S390_INSN_DIVS;
4085 insn->size = size;
4086 insn->variant.divs.rem = rem; /* remainder */
4087 insn->variant.divs.op1 = op1; /* also quotient */
4088 insn->variant.divs.op2 = op2;
4089
4090 return insn;
4091}
4092
4093
4094s390_insn *
sewardj611b06e2011-03-24 08:57:29 +00004095s390_insn_clz(UChar size, HReg num_bits, HReg clobber, s390_opnd_RMI src)
sewardj2019a972011-03-07 16:04:07 +00004096{
4097 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4098
4099 vassert(size == 8);
sewardj611b06e2011-03-24 08:57:29 +00004100 vassert(! hregIsVirtual(num_bits));
4101 vassert(! hregIsVirtual(clobber));
sewardj2019a972011-03-07 16:04:07 +00004102
sewardj611b06e2011-03-24 08:57:29 +00004103 insn->tag = S390_INSN_CLZ;
sewardj2019a972011-03-07 16:04:07 +00004104 insn->size = size;
sewardj611b06e2011-03-24 08:57:29 +00004105 insn->variant.clz.num_bits = num_bits;
4106 insn->variant.clz.clobber = clobber;
4107 insn->variant.clz.src = src;
sewardj2019a972011-03-07 16:04:07 +00004108
4109 return insn;
4110}
4111
4112
4113s390_insn *
4114s390_insn_unop(UChar size, s390_unop_t tag, HReg dst, s390_opnd_RMI opnd)
4115{
4116 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4117
4118 insn->tag = S390_INSN_UNOP;
4119 insn->size = size;
4120 insn->variant.unop.tag = tag;
4121 insn->variant.unop.dst = dst;
4122 insn->variant.unop.src = opnd;
4123
4124 return insn;
4125}
4126
4127
4128s390_insn *
4129s390_insn_test(UChar size, s390_opnd_RMI src)
4130{
4131 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4132
4133 vassert(size == 4 || size == 8);
4134
4135 insn->tag = S390_INSN_TEST;
4136 insn->size = size;
4137 insn->variant.test.src = src;
4138
4139 return insn;
4140}
4141
4142
4143s390_insn *
4144s390_insn_cc2bool(HReg dst, s390_cc_t cond)
4145{
4146 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4147
4148 insn->tag = S390_INSN_CC2BOOL;
4149 insn->size = 0; /* does not matter */
4150 insn->variant.cc2bool.cond = cond;
4151 insn->variant.cc2bool.dst = dst;
4152
4153 return insn;
4154}
4155
4156
4157s390_insn *
4158s390_insn_cas(UChar size, HReg op1, s390_amode *op2, HReg op3, HReg old_mem)
4159{
4160 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4161
4162 vassert(size == 4 || size == 8);
4163 vassert(op2->x == 0);
4164
4165 insn->tag = S390_INSN_CAS;
4166 insn->size = size;
4167 insn->variant.cas.op1 = op1;
4168 insn->variant.cas.op2 = op2;
4169 insn->variant.cas.op3 = op3;
4170 insn->variant.cas.old_mem = old_mem;
4171
4172 return insn;
4173}
4174
4175
4176s390_insn *
4177s390_insn_compare(UChar size, HReg src1, s390_opnd_RMI src2,
4178 Bool signed_comparison)
4179{
4180 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4181
4182 vassert(size == 4 || size == 8);
4183
4184 insn->tag = S390_INSN_COMPARE;
4185 insn->size = size;
4186 insn->variant.compare.src1 = src1;
4187 insn->variant.compare.src2 = src2;
4188 insn->variant.compare.signed_comparison = signed_comparison;
4189
4190 return insn;
4191}
4192
4193
4194s390_insn *
4195s390_insn_branch(IRJumpKind kind, s390_cc_t cond, s390_opnd_RMI dst)
4196{
4197 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4198
4199 insn->tag = S390_INSN_BRANCH;
4200 insn->size = 0; /* does not matter */
4201 insn->variant.branch.kind = kind;
4202 insn->variant.branch.dst = dst;
4203 insn->variant.branch.cond = cond;
4204
4205 return insn;
4206}
4207
4208
4209s390_insn *
4210s390_insn_helper_call(s390_cc_t cond, Addr64 target, UInt num_args,
4211 HChar *name)
4212{
4213 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4214
4215 insn->tag = S390_INSN_HELPER_CALL;
4216 insn->size = 0; /* does not matter */
4217 insn->variant.helper_call.cond = cond;
4218 insn->variant.helper_call.target = target;
4219 insn->variant.helper_call.num_args = num_args;
4220 insn->variant.helper_call.name = name;
4221
4222 return insn;
4223}
4224
4225
4226s390_insn *
4227s390_insn_bfp_triop(UChar size, s390_bfp_triop_t tag, HReg dst, HReg op2,
4228 HReg op3, s390_round_t rounding_mode)
4229{
4230 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4231
4232 insn->tag = S390_INSN_BFP_TRIOP;
4233 insn->size = size;
4234 insn->variant.bfp_triop.tag = tag;
4235 insn->variant.bfp_triop.dst = dst;
4236 insn->variant.bfp_triop.op2 = op2;
4237 insn->variant.bfp_triop.op3 = op3;
4238 insn->variant.bfp_triop.rounding_mode = rounding_mode;
4239
4240 return insn;
4241}
4242
4243
4244s390_insn *
4245s390_insn_bfp_binop(UChar size, s390_bfp_binop_t tag, HReg dst, HReg op2,
4246 s390_round_t rounding_mode)
4247{
4248 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4249
4250 insn->tag = S390_INSN_BFP_BINOP;
4251 insn->size = size;
4252 insn->variant.bfp_binop.tag = tag;
4253 insn->variant.bfp_binop.dst = dst;
4254 insn->variant.bfp_binop.op2 = op2;
4255 insn->variant.bfp_binop.rounding_mode = rounding_mode;
4256
4257 return insn;
4258}
4259
4260
4261s390_insn *
4262s390_insn_bfp_unop(UChar size, s390_bfp_unop_t tag, HReg dst, HReg op,
4263 s390_round_t rounding_mode)
4264{
4265 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4266
4267 insn->tag = S390_INSN_BFP_UNOP;
4268 insn->size = size;
4269 insn->variant.bfp_unop.tag = tag;
4270 insn->variant.bfp_unop.dst = dst;
4271 insn->variant.bfp_unop.op = op;
4272 insn->variant.bfp_unop.rounding_mode = rounding_mode;
4273
4274 return insn;
4275}
4276
4277
4278s390_insn *
4279s390_insn_bfp_compare(UChar size, HReg dst, HReg op1, HReg op2)
4280{
4281 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4282
4283 vassert(size == 4 || size == 8);
4284
4285 insn->tag = S390_INSN_BFP_COMPARE;
4286 insn->size = size;
4287 insn->variant.bfp_compare.dst = dst;
4288 insn->variant.bfp_compare.op1 = op1;
4289 insn->variant.bfp_compare.op2 = op2;
4290
4291 return insn;
4292}
4293
4294
4295s390_insn *
4296s390_insn_bfp128_binop(UChar size, s390_bfp_binop_t tag, HReg dst_hi,
4297 HReg dst_lo, HReg op2_hi, HReg op2_lo,
4298 s390_round_t rounding_mode)
4299{
4300 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4301
4302 insn->tag = S390_INSN_BFP128_BINOP;
4303 insn->size = size;
4304 insn->variant.bfp128_binop.tag = tag;
4305 insn->variant.bfp128_binop.dst_hi = dst_hi;
4306 insn->variant.bfp128_binop.dst_lo = dst_lo;
4307 insn->variant.bfp128_binop.op2_hi = op2_hi;
4308 insn->variant.bfp128_binop.op2_lo = op2_lo;
4309 insn->variant.bfp128_binop.rounding_mode = rounding_mode;
4310
4311 return insn;
4312}
4313
4314
4315s390_insn *
sewardja970c402011-04-28 18:38:42 +00004316s390_insn_bfp128_unop(UChar size, s390_bfp_unop_t tag, HReg dst_hi,
sewardj2019a972011-03-07 16:04:07 +00004317 HReg dst_lo, HReg op_hi, HReg op_lo,
4318 s390_round_t rounding_mode)
4319{
4320 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4321
4322 insn->tag = S390_INSN_BFP128_UNOP;
4323 insn->size = size;
4324 insn->variant.bfp128_unop.tag = tag;
4325 insn->variant.bfp128_unop.dst_hi = dst_hi;
4326 insn->variant.bfp128_unop.dst_lo = dst_lo;
4327 insn->variant.bfp128_unop.op_hi = op_hi;
4328 insn->variant.bfp128_unop.op_lo = op_lo;
4329 insn->variant.bfp128_unop.rounding_mode = rounding_mode;
4330
4331 return insn;
4332}
4333
4334
4335s390_insn *
4336s390_insn_bfp128_compare(UChar size, HReg dst, HReg op1_hi, HReg op1_lo,
4337 HReg op2_hi, HReg op2_lo)
4338{
4339 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4340
4341 insn->tag = S390_INSN_BFP128_COMPARE;
4342 insn->size = size;
4343 insn->variant.bfp128_compare.dst = dst;
4344 insn->variant.bfp128_compare.op1_hi = op1_hi;
4345 insn->variant.bfp128_compare.op1_lo = op1_lo;
4346 insn->variant.bfp128_compare.op2_hi = op2_hi;
4347 insn->variant.bfp128_compare.op2_lo = op2_lo;
4348
4349 return insn;
4350}
4351
4352
4353s390_insn *
4354s390_insn_bfp128_convert_to(UChar size, s390_bfp_unop_t tag, HReg dst_hi,
4355 HReg dst_lo, HReg op)
4356{
4357 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4358
4359 insn->tag = S390_INSN_BFP128_CONVERT_TO;
4360 insn->size = size;
4361 insn->variant.bfp128_unop.tag = tag;
4362 insn->variant.bfp128_unop.dst_hi = dst_hi;
4363 insn->variant.bfp128_unop.dst_lo = dst_lo;
4364 insn->variant.bfp128_unop.op_hi = op;
4365 insn->variant.bfp128_unop.op_lo = INVALID_HREG; /* unused */
4366 insn->variant.bfp128_unop.rounding_mode = S390_ROUND_NEAREST_EVEN; /* unused */
4367
4368 return insn;
4369}
4370
4371
4372s390_insn *
4373s390_insn_bfp128_convert_from(UChar size, s390_bfp_unop_t tag, HReg dst,
4374 HReg op_hi, HReg op_lo,
4375 s390_round_t rounding_mode)
4376{
4377 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4378
4379 insn->tag = S390_INSN_BFP128_CONVERT_FROM;
4380 insn->size = size;
4381 insn->variant.bfp128_unop.tag = tag;
4382 insn->variant.bfp128_unop.dst_hi = dst;
4383 insn->variant.bfp128_unop.dst_lo = INVALID_HREG; /* unused */
4384 insn->variant.bfp128_unop.op_hi = op_hi;
4385 insn->variant.bfp128_unop.op_lo = op_lo;
4386 insn->variant.bfp128_unop.rounding_mode = rounding_mode;
4387
4388 return insn;
4389}
4390
4391
sewardja52e37e2011-04-28 18:48:06 +00004392s390_insn *
4393s390_insn_mfence(void)
4394{
4395 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
4396
4397 insn->tag = S390_INSN_MFENCE;
4398 insn->size = 0; /* not needed */
4399
4400 return insn;
4401}
4402
4403
sewardj2019a972011-03-07 16:04:07 +00004404/*---------------------------------------------------------------*/
4405/*--- Debug print ---*/
4406/*---------------------------------------------------------------*/
4407
4408static const HChar *
4409s390_cc_as_string(s390_cc_t cc)
4410{
4411 switch (cc) {
4412 case S390_CC_NEVER: return "never";
4413 case S390_CC_OVFL: return "overflow";
4414 case S390_CC_H: return "greater than"; /* A > B ; high */
4415 case S390_CC_NLE: return "not low or equal";
4416 case S390_CC_L: return "less than"; /* A < B ; low */
4417 case S390_CC_NHE: return "not high or equal";
4418 case S390_CC_LH: return "low or high";
4419 case S390_CC_NE: return "not equal"; /* A != B ; not zero */
4420 case S390_CC_E: return "equal"; /* A == B ; zero */
4421 case S390_CC_NLH: return "not low or high";
4422 case S390_CC_HE: return "greater or equal"; /* A >= B ; high or equal*/
4423 case S390_CC_NL: return "not low"; /* not low */
4424 case S390_CC_LE: return "less or equal"; /* A <= B ; low or equal */
4425 case S390_CC_NH: return "not high";
4426 case S390_CC_NO: return "not overflow";
4427 case S390_CC_ALWAYS: return "always";
4428 default:
4429 vpanic("s390_cc_as_string");
4430 }
4431}
4432
4433
4434/* Helper function for writing out a V insn */
4435static void
4436s390_sprintf(HChar *buf, HChar *fmt, ...)
4437{
4438 HChar *p;
4439 ULong value;
4440 va_list args;
4441 va_start(args, fmt);
4442
4443 p = buf;
4444 for ( ; *fmt; ++fmt) {
4445 Int c = *fmt;
4446
4447 if (c != '%') {
4448 *p++ = c;
4449 continue;
4450 }
4451
4452 c = *++fmt; /* next char */
4453 switch (c) {
4454 case '%':
4455 *p++ = c; /* %% */
4456 continue;
4457
4458 case 's': /* %s */
4459 p += vex_sprintf(p, "%s", va_arg(args, HChar *));
4460 continue;
4461
4462 case 'M': /* %M = mnemonic */
4463 p += vex_sprintf(p, "%-8s", va_arg(args, HChar *));
4464 continue;
4465
4466 case 'R': /* %R = register */
4467 p += vex_sprintf(p, "%s", s390_hreg_as_string(va_arg(args, HReg)));
4468 continue;
4469
4470 case 'A': /* %A = amode */
4471 p += vex_sprintf(p, "%s",
4472 s390_amode_as_string(va_arg(args, s390_amode *)));
4473 continue;
4474
4475 case 'C': /* %C = condition code */
4476 p += vex_sprintf(p, "%s", s390_cc_as_string(va_arg(args, s390_cc_t)));
4477 continue;
4478
4479 case 'L': { /* %L = argument list in helper call*/
4480 UInt i, num_args;
4481
4482 num_args = va_arg(args, UInt);
4483
4484 for (i = 0; i < num_args; ++i) {
4485 if (i != 0) p += vex_sprintf(p, ", ");
4486 p += vex_sprintf(p, "r%d", s390_gprno_from_arg_index(i));
4487 }
4488 continue;
4489 }
4490
4491 case 'O': { /* %O = RMI operand */
4492 s390_opnd_RMI *op = va_arg(args, s390_opnd_RMI *);
4493
4494 switch (op->tag) {
4495 case S390_OPND_REG:
4496 p += vex_sprintf(p, "%s", s390_hreg_as_string(op->variant.reg));
4497 continue;
4498
4499 case S390_OPND_AMODE:
4500 p += vex_sprintf(p, "%s", s390_amode_as_string(op->variant.am));
4501 continue;
4502
4503 case S390_OPND_IMMEDIATE:
4504 value = op->variant.imm;
4505 goto print_value;
4506
4507 default:
4508 goto fail;
4509 }
4510 }
4511
4512 case 'I': /* %I = immediate value */
4513 value = va_arg(args, ULong);
4514 goto print_value;
4515
4516 print_value:
4517 if ((Long)value < 0)
4518 p += vex_sprintf(p, "%lld", (Long)value);
4519 else if (value < 100)
4520 p += vex_sprintf(p, "%llu", value);
4521 else
4522 p += vex_sprintf(p, "0x%llx", value);
4523 continue;
4524
4525 default:
4526 goto fail;
4527 }
4528 }
4529 *p = '\0';
4530 va_end(args);
4531
4532 return;
4533
4534 fail: vpanic("s390_printf");
4535}
4536
4537
4538/* Decompile the given insn into a static buffer and return it */
4539const HChar *
4540s390_insn_as_string(const s390_insn *insn)
4541{
4542 static HChar buf[300];
4543 const HChar *op;
4544 HChar *p;
4545
4546 buf[0] = '\0';
4547
4548 switch (insn->tag) {
4549 case S390_INSN_LOAD:
4550 s390_sprintf(buf, "%M %R,%A", "v-load", insn->variant.load.dst,
4551 insn->variant.load.src);
4552 break;
4553
4554 case S390_INSN_STORE:
4555 s390_sprintf(buf, "%M %R,%A", "v-store", insn->variant.store.src,
4556 insn->variant.store.dst);
4557 break;
4558
4559 case S390_INSN_MOVE:
4560 s390_sprintf(buf, "%M %R,%R", "v-move", insn->variant.move.dst,
4561 insn->variant.move.src);
4562 break;
4563
4564 case S390_INSN_COND_MOVE:
4565 s390_sprintf(buf, "%M if (%C) %R,%O", "v-move",
4566 insn->variant.cond_move.cond, insn->variant.cond_move.dst,
4567 &insn->variant.cond_move.src);
4568 break;
4569
4570 case S390_INSN_LOAD_IMMEDIATE:
4571 s390_sprintf(buf, "%M %R,%I", "v-loadi", insn->variant.load_immediate.dst,
4572 insn->variant.load_immediate.value);
4573 break;
4574
4575 case S390_INSN_ALU:
4576 switch (insn->variant.alu.tag) {
4577 case S390_ALU_ADD: op = "v-add"; break;
4578 case S390_ALU_SUB: op = "v-sub"; break;
4579 case S390_ALU_MUL: op = "v-mul"; break;
4580 case S390_ALU_AND: op = "v-and"; break;
4581 case S390_ALU_OR: op = "v-or"; break;
4582 case S390_ALU_XOR: op = "v-xor"; break;
4583 case S390_ALU_LSH: op = "v-lsh"; break;
4584 case S390_ALU_RSH: op = "v-rsh"; break;
4585 case S390_ALU_RSHA: op = "v-rsha"; break;
4586 default: goto fail;
4587 }
4588 s390_sprintf(buf, "%M %R,%R,%O", op, insn->variant.alu.dst,
4589 insn->variant.alu.dst /* op1 same as dst */,
4590 &insn->variant.alu.op2);
4591 break;
4592
4593 case S390_INSN_MUL:
4594 if (insn->variant.mul.signed_multiply) {
4595 op = "v-muls";
4596 } else {
4597 op = "v-mulu";
4598 }
4599 s390_sprintf(buf, "%M %R,%O", op, insn->variant.mul.dst_hi,
4600 &insn->variant.mul.op2);
4601 break;
4602
4603 case S390_INSN_DIV:
4604 if (insn->variant.div.signed_divide) {
4605 op = "v-divs";
4606 } else {
4607 op = "v-divu";
4608 }
4609 s390_sprintf(buf, "%M %R,%O", op, insn->variant.div.op1_hi,
4610 &insn->variant.div.op2);
4611 break;
4612
4613 case S390_INSN_DIVS:
4614 s390_sprintf(buf, "%M %R,%O", "v-divsi", insn->variant.divs.op1,
4615 &insn->variant.divs.op2);
4616 break;
4617
sewardj611b06e2011-03-24 08:57:29 +00004618 case S390_INSN_CLZ:
4619 s390_sprintf(buf, "%M %R,%O", "v-clz", insn->variant.clz.num_bits,
4620 &insn->variant.clz.src);
sewardj2019a972011-03-07 16:04:07 +00004621 break;
4622
4623 case S390_INSN_UNOP:
4624 switch (insn->variant.unop.tag) {
4625 case S390_ZERO_EXTEND_8:
4626 case S390_ZERO_EXTEND_16:
4627 case S390_ZERO_EXTEND_32:
4628 op = "v-zerox";
4629 break;
4630
4631 case S390_SIGN_EXTEND_8:
4632 case S390_SIGN_EXTEND_16:
4633 case S390_SIGN_EXTEND_32:
4634 op = "v-signx";
4635 break;
4636
4637 case S390_NEGATE:
4638 op = "v-neg";
4639 break;
4640
4641 default:
4642 goto fail;
4643 }
4644 s390_sprintf(buf, "%M %R,%O", op, insn->variant.unop.dst,
4645 &insn->variant.unop.src);
4646 break;
4647
4648 case S390_INSN_TEST:
4649 s390_sprintf(buf, "%M %O", "v-test", &insn->variant.test.src);
4650 break;
4651
4652 case S390_INSN_CC2BOOL:
4653 s390_sprintf(buf, "%M %R,%C", "v-cc2b", insn->variant.cc2bool.dst,
4654 insn->variant.cc2bool.cond);
4655 break;
4656
4657 case S390_INSN_CAS:
4658 s390_sprintf(buf, "%M %R,%A,%R,%R", "v-cas", insn->variant.cas.op1,
4659 insn->variant.cas.op2, insn->variant.cas.op3,
4660 insn->variant.cas.old_mem);
4661 break;
4662
4663 case S390_INSN_COMPARE:
4664 if (insn->variant.compare.signed_comparison) {
4665 op = "v-cmps";
4666 } else {
4667 op = "v-cmpu";
4668 }
4669 s390_sprintf(buf, "%M %R,%O", op, insn->variant.compare.src1,
4670 &insn->variant.compare.src2);
4671 break;
4672
4673 case S390_INSN_BRANCH:
4674 switch (insn->variant.branch.kind) {
4675 case Ijk_ClientReq: op = "clientreq"; break;
4676 case Ijk_Sys_syscall: op = "syscall"; break;
4677 case Ijk_Yield: op = "yield"; break;
4678 case Ijk_EmWarn: op = "emwarn"; break;
4679 case Ijk_EmFail: op = "emfail"; break;
4680 case Ijk_MapFail: op = "mapfail"; break;
4681 case Ijk_NoDecode: op = "nodecode"; break;
4682 case Ijk_TInval: op = "tinval"; break;
4683 case Ijk_NoRedir: op = "noredir"; break;
4684 case Ijk_SigTRAP: op = "sigtrap"; break;
4685 case Ijk_Boring: op = "goto"; break;
4686 case Ijk_Call: op = "call"; break;
4687 case Ijk_Ret: op = "return"; break;
4688 default:
4689 goto fail;
4690 }
4691 s390_sprintf(buf, "if (%C) %s %O", insn->variant.branch.cond, op,
4692 &insn->variant.branch.dst);
4693 break;
4694
4695 case S390_INSN_HELPER_CALL: {
4696
4697 if (insn->variant.helper_call.cond != S390_CC_ALWAYS) {
4698 s390_sprintf(buf, "%M if (%C) %s{%I}(%L)", "v-call",
4699 insn->variant.helper_call.cond,
4700 insn->variant.helper_call.name,
4701 insn->variant.helper_call.target,
4702 insn->variant.helper_call.num_args);
4703 } else {
4704 s390_sprintf(buf, "%M %s{%I}(%L)", "v-call",
4705 insn->variant.helper_call.name,
4706 insn->variant.helper_call.target,
4707 insn->variant.helper_call.num_args);
4708 }
4709 break;
4710 }
4711
4712 case S390_INSN_BFP_TRIOP:
4713 switch (insn->variant.bfp_triop.tag) {
4714 case S390_BFP_MADD: op = "v-fmadd"; break;
4715 case S390_BFP_MSUB: op = "v-fmsub"; break;
4716 default: goto fail;
4717 }
4718 s390_sprintf(buf, "%M %R,%R,%R,%R", op, insn->variant.bfp_triop.dst,
4719 insn->variant.bfp_triop.dst /* op1 same as dst */,
4720 insn->variant.bfp_triop.op2, insn->variant.bfp_triop.op3);
4721 break;
4722
4723 case S390_INSN_BFP_BINOP:
4724 switch (insn->variant.bfp_binop.tag) {
4725 case S390_BFP_ADD: op = "v-fadd"; break;
4726 case S390_BFP_SUB: op = "v-fsub"; break;
4727 case S390_BFP_MUL: op = "v-fmul"; break;
4728 case S390_BFP_DIV: op = "v-fdiv"; break;
4729 default: goto fail;
4730 }
4731 s390_sprintf(buf, "%M %R,%R,%R", op, insn->variant.bfp_binop.dst,
4732 insn->variant.bfp_binop.dst /* op1 same as dst */,
4733 insn->variant.bfp_binop.op2);
4734 break;
4735
4736 case S390_INSN_BFP_COMPARE:
4737 s390_sprintf(buf, "%M %R,%R,%R", "v-fcmp", insn->variant.bfp_compare.dst,
4738 insn->variant.bfp_compare.op1, insn->variant.bfp_compare.op2);
4739 break;
4740
4741 case S390_INSN_BFP_UNOP:
4742 switch (insn->variant.bfp_unop.tag) {
4743 case S390_BFP_ABS: op = "v-fabs"; break;
4744 case S390_BFP_NABS: op = "v-fnabs"; break;
4745 case S390_BFP_NEG: op = "v-fneg"; break;
4746 case S390_BFP_SQRT: op = "v-fsqrt"; break;
4747 case S390_BFP_I32_TO_F32:
4748 case S390_BFP_I32_TO_F64:
4749 case S390_BFP_I32_TO_F128:
4750 case S390_BFP_I64_TO_F32:
4751 case S390_BFP_I64_TO_F64:
4752 case S390_BFP_I64_TO_F128: op = "v-i2f"; break;
4753 case S390_BFP_F32_TO_I32:
4754 case S390_BFP_F32_TO_I64:
4755 case S390_BFP_F64_TO_I32:
4756 case S390_BFP_F64_TO_I64:
4757 case S390_BFP_F128_TO_I32:
4758 case S390_BFP_F128_TO_I64: op = "v-f2i"; break;
4759 case S390_BFP_F32_TO_F64:
4760 case S390_BFP_F32_TO_F128:
4761 case S390_BFP_F64_TO_F32:
4762 case S390_BFP_F64_TO_F128:
4763 case S390_BFP_F128_TO_F32:
4764 case S390_BFP_F128_TO_F64: op = "v-f2f"; break;
4765 default: goto fail;
4766 }
4767 s390_sprintf(buf, "%M %R,%R", op, insn->variant.bfp_unop.dst,
4768 insn->variant.bfp_unop.op);
4769 break;
4770
4771 case S390_INSN_BFP128_BINOP:
4772 switch (insn->variant.bfp128_binop.tag) {
4773 case S390_BFP_ADD: op = "v-fadd"; break;
4774 case S390_BFP_SUB: op = "v-fsub"; break;
4775 case S390_BFP_MUL: op = "v-fmul"; break;
4776 case S390_BFP_DIV: op = "v-fdiv"; break;
4777 default: goto fail;
4778 }
4779 /* Only write the register that identifies the register pair */
4780 s390_sprintf(buf, "%M %R,%R,%R", op, insn->variant.bfp128_binop.dst_hi,
4781 insn->variant.bfp128_binop.dst_hi /* op1 same as dst */,
4782 insn->variant.bfp128_binop.op2_hi);
4783 break;
4784
4785 case S390_INSN_BFP128_COMPARE:
4786 /* Only write the register that identifies the register pair */
4787 s390_sprintf(buf, "%M %R,%R,%R", "v-fcmp", insn->variant.bfp128_compare.dst,
4788 insn->variant.bfp128_compare.op1_hi,
4789 insn->variant.bfp128_compare.op2_hi);
4790 break;
4791
4792 case S390_INSN_BFP128_UNOP:
4793 case S390_INSN_BFP128_CONVERT_TO:
4794 case S390_INSN_BFP128_CONVERT_FROM:
4795 switch (insn->variant.bfp128_unop.tag) {
4796 case S390_BFP_ABS: op = "v-fabs"; break;
4797 case S390_BFP_NABS: op = "v-fnabs"; break;
4798 case S390_BFP_NEG: op = "v-fneg"; break;
4799 case S390_BFP_SQRT: op = "v-fsqrt"; break;
4800 case S390_BFP_I32_TO_F128:
4801 case S390_BFP_I64_TO_F128: op = "v-i2f"; break;
4802 case S390_BFP_F128_TO_I32:
4803 case S390_BFP_F128_TO_I64: op = "v-f2i"; break;
4804 case S390_BFP_F32_TO_F128:
4805 case S390_BFP_F64_TO_F128:
4806 case S390_BFP_F128_TO_F32:
4807 case S390_BFP_F128_TO_F64: op = "v-f2f"; break;
4808 default: goto fail;
4809 }
4810 /* Only write the register that identifies the register pair */
4811 s390_sprintf(buf, "%M %R,%R", op, insn->variant.bfp128_unop.dst_hi,
4812 insn->variant.bfp128_unop.op_hi);
4813 break;
4814
sewardja52e37e2011-04-28 18:48:06 +00004815 case S390_INSN_MFENCE:
4816 s390_sprintf(buf, "%M", "v-mfence");
4817 return buf; /* avoid printing "size = ..." which is meaningless */
4818
sewardj2019a972011-03-07 16:04:07 +00004819 default: goto fail;
4820 }
4821
4822 /* Write out how many bytes are involved in the operation */
4823
4824 {
4825 UInt len, i;
4826
4827 for (p = buf; *p; ++p)
4828 continue;
4829
4830 len = p - buf;
4831
4832 if (len < 32) {
4833 for (i = len; i < 32; ++i)
4834 p += vex_sprintf(p, " ");
4835 } else {
4836 p += vex_sprintf(p, "\t");
4837 }
4838 }
4839
4840 /* Special cases first */
4841 switch (insn->tag) {
4842 case S390_INSN_UNOP:
4843 switch (insn->variant.unop.tag) {
4844 case S390_SIGN_EXTEND_8:
4845 case S390_ZERO_EXTEND_8: p += vex_sprintf(p, "1 -> "); goto common;
4846 case S390_SIGN_EXTEND_16:
4847 case S390_ZERO_EXTEND_16: p += vex_sprintf(p, "2 -> "); goto common;
4848 case S390_SIGN_EXTEND_32:
4849 case S390_ZERO_EXTEND_32: p += vex_sprintf(p, "4 -> "); goto common;
4850 default:
4851 goto common;
4852 }
4853
4854 case S390_INSN_BFP_UNOP:
4855 switch (insn->variant.bfp_unop.tag) {
4856 case S390_BFP_I32_TO_F32:
4857 case S390_BFP_I32_TO_F64:
4858 case S390_BFP_I32_TO_F128:
4859 case S390_BFP_F32_TO_I32:
4860 case S390_BFP_F32_TO_I64:
4861 case S390_BFP_F32_TO_F64:
4862 case S390_BFP_F32_TO_F128: p += vex_sprintf(p, "4 -> "); goto common;
4863 case S390_BFP_I64_TO_F32:
4864 case S390_BFP_I64_TO_F64:
4865 case S390_BFP_I64_TO_F128:
4866 case S390_BFP_F64_TO_I32:
4867 case S390_BFP_F64_TO_I64:
4868 case S390_BFP_F64_TO_F32:
4869 case S390_BFP_F64_TO_F128: p += vex_sprintf(p, "8 -> "); goto common;
4870 case S390_BFP_F128_TO_I32:
4871 case S390_BFP_F128_TO_I64:
4872 case S390_BFP_F128_TO_F32:
4873 case S390_BFP_F128_TO_F64: p += vex_sprintf(p, "16 -> "); goto common;
4874 default:
4875 goto common;
4876 }
4877
4878 case S390_INSN_BFP128_UNOP:
4879 case S390_INSN_BFP128_CONVERT_TO:
4880 case S390_INSN_BFP128_CONVERT_FROM:
4881 switch (insn->variant.bfp128_unop.tag) {
4882 case S390_BFP_I32_TO_F128:
4883 case S390_BFP_F32_TO_F128: p += vex_sprintf(p, "4 -> "); goto common;
4884 case S390_BFP_I64_TO_F128:
4885 case S390_BFP_F64_TO_F128: p += vex_sprintf(p, "8 -> "); goto common;
4886 case S390_BFP_F128_TO_I32:
4887 case S390_BFP_F128_TO_I64:
4888 case S390_BFP_F128_TO_F32:
4889 case S390_BFP_F128_TO_F64: p += vex_sprintf(p, "16 -> "); goto common;
4890 default:
4891 goto common;
4892 }
4893
4894 default:
4895 goto common;
4896 }
4897
4898 /* Common case */
4899 common:
4900 vex_sprintf(p, "%u bytes", (UInt)insn->size);
4901
4902 return buf;
4903
4904 fail: vpanic("s390_insn_as_string");
4905}
4906
4907
4908
4909/* Load NUM bytes from memory into register REG using addressing mode AM. */
4910static UChar *
4911s390_emit_load_mem(UChar *p, UInt num, UChar reg, const s390_amode *am)
4912{
4913 UInt b = hregNumber(am->b);
4914 UInt x = hregNumber(am->x); /* 0 for B12 and B20 */
4915 UInt d = am->d;
4916
4917 switch (am->tag) {
4918 case S390_AMODE_B12:
4919 case S390_AMODE_BX12:
4920 switch (num) {
4921 case 1: return s390_emit_IC(p, reg, x, b, d);
4922 case 2: return s390_emit_LH(p, reg, x, b, d);
4923 case 4: return s390_emit_L(p, reg, x, b, d);
4924 case 8: return s390_emit_LG(p, reg, x, b, DISP20(d));
4925 default: goto fail;
4926 }
4927 break;
4928
4929 case S390_AMODE_B20:
4930 case S390_AMODE_BX20:
4931 switch (num) {
4932 case 1: return s390_emit_ICY(p, reg, x, b, DISP20(d));
4933 case 2: return s390_emit_LHY(p, reg, x, b, DISP20(d));
4934 case 4: return s390_emit_LY(p, reg, x, b, DISP20(d));
4935 case 8: return s390_emit_LG(p, reg, x, b, DISP20(d));
4936 default: goto fail;
4937 }
4938 break;
4939
4940 default: goto fail;
4941 }
4942
4943 fail:
4944 vpanic("s390_emit_load_mem");
4945}
4946
4947
4948/* Load condition code into register REG */
4949static UChar *
4950s390_emit_load_cc(UChar *p, UChar reg)
4951{
4952 p = s390_emit_LGHI(p, reg, 0); /* Clear out, cc not affected */
4953 p = s390_emit_IPM(p, reg, reg);
4954 /* Shift 28 bits to the right --> [0,1,2,3] */
sewardjf74c86f2011-04-05 14:04:53 +00004955 return s390_emit_SRL(p, reg, 0, 28); /* REG = cc */
sewardj2019a972011-03-07 16:04:07 +00004956}
4957
4958
4959/*---------------------------------------------------------------*/
4960/*--- Code generation ---*/
4961/*---------------------------------------------------------------*/
4962
4963/* Do not load more bytes than requested. */
4964static UChar *
4965s390_insn_load_emit(UChar *buf, const s390_insn *insn)
4966{
4967 UInt r, x, b, d;
4968 const s390_amode *src;
4969
4970 src = insn->variant.load.src;
4971
4972 r = hregNumber(insn->variant.load.dst);
4973
4974 if (hregClass(insn->variant.load.dst) == HRcFlt64) {
4975 b = hregNumber(src->b);
4976 x = hregNumber(src->x); /* 0 for B12 and B20 */
4977 d = src->d;
4978
4979 switch (insn->size) {
4980
4981 case 4:
4982 switch (src->tag) {
4983 case S390_AMODE_B12:
4984 case S390_AMODE_BX12:
4985 return s390_emit_LE(buf, r, x, b, d);
4986
4987 case S390_AMODE_B20:
4988 case S390_AMODE_BX20:
4989 return s390_emit_LEY(buf, r, x, b, DISP20(d));
4990 }
4991 break;
4992
4993 case 8:
4994 switch (src->tag) {
4995 case S390_AMODE_B12:
4996 case S390_AMODE_BX12:
4997 return s390_emit_LD(buf, r, x, b, d);
4998
4999 case S390_AMODE_B20:
5000 case S390_AMODE_BX20:
5001 return s390_emit_LDY(buf, r, x, b, DISP20(d));
5002 }
5003 break;
5004 }
5005 vpanic("s390_insn_load_emit");
5006 }
5007
5008 /* Integer stuff */
5009 return s390_emit_load_mem(buf, insn->size, r, src);
5010}
5011
5012
5013static UChar *
5014s390_insn_store_emit(UChar *buf, const s390_insn *insn)
5015{
5016 UInt r, x, b, d;
5017 const s390_amode *dst;
5018
5019 dst = insn->variant.store.dst;
5020
5021 r = hregNumber(insn->variant.store.src);
5022 b = hregNumber(dst->b);
5023 x = hregNumber(dst->x); /* 0 for B12 and B20 */
5024 d = dst->d;
5025
5026 if (hregClass(insn->variant.store.src) == HRcFlt64) {
5027 switch (insn->size) {
5028
5029 case 4:
5030 switch (dst->tag) {
5031 case S390_AMODE_B12:
5032 case S390_AMODE_BX12:
5033 return s390_emit_STE(buf, r, x, b, d);
5034
5035 case S390_AMODE_B20:
5036 case S390_AMODE_BX20:
5037 return s390_emit_STEY(buf, r, x, b, DISP20(d));
5038 }
5039 break;
5040
5041 case 8:
5042 switch (dst->tag) {
5043 case S390_AMODE_B12:
5044 case S390_AMODE_BX12:
5045 return s390_emit_STD(buf, r, x, b, d);
5046
5047 case S390_AMODE_B20:
5048 case S390_AMODE_BX20:
5049 return s390_emit_STDY(buf, r, x, b, DISP20(d));
5050 }
5051 break;
5052 }
5053 vpanic("s390_insn_store_emit");
5054 }
5055
5056 /* Integer stuff */
5057 switch (insn->size) {
5058 case 1:
5059 switch (dst->tag) {
5060 case S390_AMODE_B12:
5061 case S390_AMODE_BX12:
5062 return s390_emit_STC(buf, r, x, b, d);
5063
5064 case S390_AMODE_B20:
5065 case S390_AMODE_BX20:
5066 return s390_emit_STCY(buf, r, x, b, DISP20(d));
5067 }
5068 break;
5069
5070 case 2:
5071 switch (dst->tag) {
5072 case S390_AMODE_B12:
5073 case S390_AMODE_BX12:
5074 return s390_emit_STH(buf, r, x, b, d);
5075
5076 case S390_AMODE_B20:
5077 case S390_AMODE_BX20:
5078 return s390_emit_STHY(buf, r, x, b, DISP20(d));
5079 }
5080 break;
5081
5082 case 4:
5083 switch (dst->tag) {
5084 case S390_AMODE_B12:
5085 case S390_AMODE_BX12:
5086 return s390_emit_ST(buf, r, x, b, d);
5087
5088 case S390_AMODE_B20:
5089 case S390_AMODE_BX20:
5090 return s390_emit_STY(buf, r, x, b, DISP20(d));
5091 }
5092 break;
5093
5094 case 8:
5095 return s390_emit_STG(buf, r, x, b, DISP20(d));
5096
5097 default:
5098 break;
5099 }
5100
5101 vpanic("s390_insn_store_emit");
5102}
5103
5104
5105static UChar *
5106s390_insn_move_emit(UChar *buf, const s390_insn *insn)
5107{
5108 UInt dst, src;
5109 HRegClass dst_class, src_class;
5110
5111 dst = hregNumber(insn->variant.move.dst);
5112 src = hregNumber(insn->variant.move.src);
5113
5114 dst_class = hregClass(insn->variant.move.dst);
5115 src_class = hregClass(insn->variant.move.src);
5116
5117 if (dst_class == src_class) {
5118 if (dst_class == HRcInt64)
5119 return s390_emit_LGR(buf, dst, src);
5120 if (dst_class == HRcFlt64)
5121 return s390_emit_LDR(buf, dst, src);
5122 } else {
floriana782a172011-12-18 15:51:54 +00005123 if (dst_class == HRcFlt64 && src_class == HRcInt64) {
5124 if (insn->size == 4) {
5125 buf = s390_emit_SLLG(buf, R0, src, 0, DISP20(32)); /* r0 = src << 32 */
5126 return s390_emit_LDGRw(buf, dst, R0);
5127 } else {
5128 return s390_emit_LDGRw(buf, dst, src);
5129 }
5130 }
5131 if (dst_class == HRcInt64 && src_class == HRcFlt64) {
5132 if (insn->size == 4) {
5133 buf = s390_emit_LGDRw(buf, dst, src);
5134 return s390_emit_SRLG(buf, dst, dst, 0, DISP20(32)); /* dst >>= 32 */
5135 } else {
5136 return s390_emit_LGDRw(buf, dst, src);
5137 }
5138 }
sewardj2019a972011-03-07 16:04:07 +00005139 /* A move between floating point registers and general purpose
5140 registers of different size should never occur and indicates
5141 an error elsewhere. */
5142 }
5143
5144 vpanic("s390_insn_move_emit");
5145}
5146
5147
5148static UChar *
5149s390_insn_load_immediate_emit(UChar *buf, const s390_insn *insn)
5150{
5151 UInt r;
5152 ULong value = insn->variant.load_immediate.value;
5153
5154 r = hregNumber(insn->variant.load_immediate.dst);
5155
5156 if (hregClass(insn->variant.load_immediate.dst) == HRcFlt64) {
5157 vassert(value == 0);
5158 switch (insn->size) {
5159 case 4: return s390_emit_LZER(buf, r, value);
5160 case 8: return s390_emit_LZDR(buf, r, value);
5161 }
5162 vpanic("s390_insn_load_immediate_emit");
5163 }
5164
5165 switch (insn->size) {
5166 case 1:
5167 case 2:
5168 /* Load the immediate values as a 4 byte value. That does not hurt as
5169 those extra bytes will not be looked at. Fall through .... */
5170 case 4:
5171 return s390_emit_load_32imm(buf, r, value);
5172
5173 case 8:
5174 return s390_emit_load_64imm(buf, r, value);
5175 }
5176
5177 vpanic("s390_insn_load_immediate_emit");
5178}
5179
5180
5181/* There is no easy way to do ALU operations on 1-byte or 2-byte operands.
5182 So we simply perform a 4-byte operation. Doing so uses possibly undefined
5183 bits and produces an undefined result in those extra bit positions. But
5184 upstream does not look at those positions, so this is OK. */
5185static UChar *
5186s390_insn_alu_emit(UChar *buf, const s390_insn *insn)
5187{
5188 s390_opnd_RMI op2;
5189 UInt dst;
5190
5191 dst = hregNumber(insn->variant.alu.dst);
5192 op2 = insn->variant.alu.op2;
5193
5194 /* Second operand is in a register */
5195 if (op2.tag == S390_OPND_REG) {
5196 UInt r2 = hregNumber(op2.variant.reg);
5197
5198 switch (insn->size) {
5199 case 1:
5200 case 2:
5201 case 4:
5202 switch (insn->variant.alu.tag) {
5203 case S390_ALU_ADD: return s390_emit_AR(buf, dst, r2);
5204 case S390_ALU_SUB: return s390_emit_SR(buf, dst, r2);
5205 case S390_ALU_MUL: return s390_emit_MSR(buf, dst, r2);
5206 case S390_ALU_AND: return s390_emit_NR(buf, dst, r2);
5207 case S390_ALU_OR: return s390_emit_OR(buf, dst, r2);
5208 case S390_ALU_XOR: return s390_emit_XR(buf, dst, r2);
sewardj3c49aaa2011-04-05 14:00:37 +00005209 case S390_ALU_LSH: return s390_emit_SLL(buf, dst, r2, 0);
5210 case S390_ALU_RSH: return s390_emit_SRL(buf, dst, r2, 0);
5211 case S390_ALU_RSHA: return s390_emit_SRA(buf, dst, r2, 0);
sewardj2019a972011-03-07 16:04:07 +00005212 }
5213 goto fail;
5214
5215 case 8:
5216 switch (insn->variant.alu.tag) {
5217 case S390_ALU_ADD: return s390_emit_AGR(buf, dst, r2);
5218 case S390_ALU_SUB: return s390_emit_SGR(buf, dst, r2);
5219 case S390_ALU_MUL: return s390_emit_MSGR(buf, dst, r2);
5220 case S390_ALU_AND: return s390_emit_NGR(buf, dst, r2);
5221 case S390_ALU_OR: return s390_emit_OGR(buf, dst, r2);
5222 case S390_ALU_XOR: return s390_emit_XGR(buf, dst, r2);
5223 case S390_ALU_LSH: return s390_emit_SLLG(buf, dst, dst, r2, DISP20(0));
5224 case S390_ALU_RSH: return s390_emit_SRLG(buf, dst, dst, r2, DISP20(0));
5225 case S390_ALU_RSHA: return s390_emit_SRAG(buf, dst, dst, r2, DISP20(0));
5226 }
5227 goto fail;
5228 }
5229 goto fail;
5230 }
5231
5232 /* 2nd operand is in memory */
5233 if (op2.tag == S390_OPND_AMODE) {
5234 UInt b, x, d;
5235 const s390_amode *src = op2.variant.am;
5236
5237 b = hregNumber(src->b);
5238 x = hregNumber(src->x); /* 0 for B12 and B20 */
5239 d = src->d;
5240
5241 /* Shift operands are special here as there are no opcodes that
sewardje0dd77e2011-04-27 12:07:01 +00005242 allow a memory operand. So we first load the 2nd operand into
5243 some register. R0 is used to save restore the contents of the
5244 chosen register.. */
sewardj652b56a2011-04-13 15:38:17 +00005245
sewardj2019a972011-03-07 16:04:07 +00005246 if (insn->variant.alu.tag == S390_ALU_LSH ||
5247 insn->variant.alu.tag == S390_ALU_RSH ||
5248 insn->variant.alu.tag == S390_ALU_RSHA) {
sewardje0dd77e2011-04-27 12:07:01 +00005249 UInt b2;
sewardj2019a972011-03-07 16:04:07 +00005250
sewardje0dd77e2011-04-27 12:07:01 +00005251 /* Choose a register (other than DST or R0) into which to stick the
5252 shift amount. The following works because r15 is reserved and
5253 thusly dst != 15. */
5254 vassert(dst != 15); /* extra paranoia */
5255 b2 = (dst + 1) % 16;
5256
5257 buf = s390_emit_LGR(buf, R0, b2); /* save */
5258
5259 /* Loading SRC to B2 does not modify R0. */
5260 buf = s390_emit_load_mem(buf, insn->size, b2, src);
sewardj2019a972011-03-07 16:04:07 +00005261
5262 if (insn->size == 8) {
sewardje0dd77e2011-04-27 12:07:01 +00005263 switch (insn->variant.alu.tag) {
5264 case S390_ALU_LSH:
5265 buf = s390_emit_SLLG(buf, dst, dst, b2, DISP20(0));
5266 break;
5267 case S390_ALU_RSH:
5268 buf = s390_emit_SRLG(buf, dst, dst, b2, DISP20(0));
5269 break;
5270 case S390_ALU_RSHA:
5271 buf = s390_emit_SRAG(buf, dst, dst, b2, DISP20(0));
5272 break;
5273 default: /* unreachable */
5274 goto fail;
5275 }
sewardj2019a972011-03-07 16:04:07 +00005276 } else {
sewardje0dd77e2011-04-27 12:07:01 +00005277 switch (insn->variant.alu.tag) {
5278 case S390_ALU_LSH:
5279 buf = s390_emit_SLL(buf, dst, b2, 0);
5280 break;
5281 case S390_ALU_RSH:
5282 buf = s390_emit_SRL(buf, dst, b2, 0);
5283 break;
5284 case S390_ALU_RSHA:
5285 buf = s390_emit_SRA(buf, dst, b2, 0);
5286 break;
5287 default: /* unreachable */
5288 goto fail;
5289 }
sewardj2019a972011-03-07 16:04:07 +00005290 }
sewardje0dd77e2011-04-27 12:07:01 +00005291 return s390_emit_LGR(buf, b2, R0); /* restore */
sewardj2019a972011-03-07 16:04:07 +00005292 }
5293
5294 switch (insn->size) {
5295 case 1:
5296 /* Move the byte from memory into scratch register r0 */
5297 buf = s390_emit_load_mem(buf, 1, R0, src);
5298
5299 switch (insn->variant.alu.tag) {
5300 case S390_ALU_ADD: return s390_emit_AR(buf, dst, R0);
5301 case S390_ALU_SUB: return s390_emit_SR(buf, dst, R0);
5302 case S390_ALU_MUL: return s390_emit_MSR(buf, dst, R0);
5303 case S390_ALU_AND: return s390_emit_NR(buf, dst, R0);
5304 case S390_ALU_OR: return s390_emit_OR(buf, dst, R0);
5305 case S390_ALU_XOR: return s390_emit_XR(buf, dst, R0);
5306 case S390_ALU_LSH:
5307 case S390_ALU_RSH:
5308 case S390_ALU_RSHA: ; /* avoid GCC warning */
5309 }
5310 goto fail;
5311
5312 case 2:
5313 switch (src->tag) {
5314 case S390_AMODE_B12:
5315 case S390_AMODE_BX12:
5316 switch (insn->variant.alu.tag) {
5317 case S390_ALU_ADD:
5318 return s390_emit_AH(buf, dst, x, b, d);
5319
5320 case S390_ALU_SUB:
5321 return s390_emit_SH(buf, dst, x, b, d);
5322
5323 case S390_ALU_MUL:
5324 return s390_emit_MH(buf, dst, x, b, d);
5325
5326 /* For bitwise operations: Move two bytes from memory into scratch
5327 register r0; then perform operation */
5328 case S390_ALU_AND:
5329 buf = s390_emit_LH(buf, R0, x, b, d);
5330 return s390_emit_NR(buf, dst, R0);
5331
5332 case S390_ALU_OR:
5333 buf = s390_emit_LH(buf, R0, x, b, d);
5334 return s390_emit_OR(buf, dst, R0);
5335
5336 case S390_ALU_XOR:
5337 buf = s390_emit_LH(buf, R0, x, b, d);
5338 return s390_emit_XR(buf, dst, R0);
5339
5340 case S390_ALU_LSH:
5341 case S390_ALU_RSH:
5342 case S390_ALU_RSHA: ; /* avoid GCC warning */
5343 }
5344 goto fail;
5345
5346 case S390_AMODE_B20:
5347 case S390_AMODE_BX20:
5348 switch (insn->variant.alu.tag) {
5349 case S390_ALU_ADD:
5350 return s390_emit_AHY(buf, dst, x, b, DISP20(d));
5351
5352 case S390_ALU_SUB:
5353 return s390_emit_SHY(buf, dst, x, b, DISP20(d));
5354
5355 case S390_ALU_MUL:
sewardjeae8db52011-03-24 09:01:50 +00005356 return s390_emit_MHYw(buf, dst, x, b, DISP20(d));
sewardj2019a972011-03-07 16:04:07 +00005357
5358 /* For bitwise operations: Move two bytes from memory into scratch
5359 register r0; then perform operation */
5360 case S390_ALU_AND:
5361 buf = s390_emit_LHY(buf, R0, x, b, DISP20(d));
5362 return s390_emit_NR(buf, dst, R0);
5363
5364 case S390_ALU_OR:
5365 buf = s390_emit_LHY(buf, R0, x, b, DISP20(d));
5366 return s390_emit_OR(buf, dst, R0);
5367
5368 case S390_ALU_XOR:
5369 buf = s390_emit_LHY(buf, R0, x, b, DISP20(d));
5370 return s390_emit_XR(buf, dst, R0);
5371
5372 case S390_ALU_LSH:
5373 case S390_ALU_RSH:
5374 case S390_ALU_RSHA: ; /* avoid GCC warning */
5375 }
5376 goto fail;
5377 }
5378 goto fail;
5379
5380 case 4:
5381 switch (src->tag) {
5382 case S390_AMODE_B12:
5383 case S390_AMODE_BX12:
5384 switch (insn->variant.alu.tag) {
5385 case S390_ALU_ADD: return s390_emit_A(buf, dst, x, b, d);
5386 case S390_ALU_SUB: return s390_emit_S(buf, dst, x, b, d);
5387 case S390_ALU_MUL: return s390_emit_MS(buf, dst, x, b, d);
5388 case S390_ALU_AND: return s390_emit_N(buf, dst, x, b, d);
5389 case S390_ALU_OR: return s390_emit_O(buf, dst, x, b, d);
5390 case S390_ALU_XOR: return s390_emit_X(buf, dst, x, b, d);
5391 case S390_ALU_LSH:
5392 case S390_ALU_RSH:
5393 case S390_ALU_RSHA: ; /* avoid GCC warning */
5394 }
5395 goto fail;
5396
5397 case S390_AMODE_B20:
5398 case S390_AMODE_BX20:
5399 switch (insn->variant.alu.tag) {
5400 case S390_ALU_ADD: return s390_emit_AY(buf, dst, x, b, DISP20(d));
5401 case S390_ALU_SUB: return s390_emit_SY(buf, dst, x, b, DISP20(d));
5402 case S390_ALU_MUL: return s390_emit_MSY(buf, dst, x, b, DISP20(d));
5403 case S390_ALU_AND: return s390_emit_NY(buf, dst, x, b, DISP20(d));
5404 case S390_ALU_OR: return s390_emit_OY(buf, dst, x, b, DISP20(d));
5405 case S390_ALU_XOR: return s390_emit_XY(buf, dst, x, b, DISP20(d));
5406 case S390_ALU_LSH:
5407 case S390_ALU_RSH:
5408 case S390_ALU_RSHA: ; /* avoid GCC warning */
5409 }
5410 goto fail;
5411 }
5412 goto fail;
5413
5414 case 8:
5415 switch (insn->variant.alu.tag) {
5416 case S390_ALU_ADD: return s390_emit_AG(buf, dst, x, b, DISP20(d));
5417 case S390_ALU_SUB: return s390_emit_SG(buf, dst, x, b, DISP20(d));
5418 case S390_ALU_MUL: return s390_emit_MSG(buf, dst, x, b, DISP20(d));
5419 case S390_ALU_AND: return s390_emit_NG(buf, dst, x, b, DISP20(d));
5420 case S390_ALU_OR: return s390_emit_OG(buf, dst, x, b, DISP20(d));
5421 case S390_ALU_XOR: return s390_emit_XG(buf, dst, x, b, DISP20(d));
5422 case S390_ALU_LSH:
5423 case S390_ALU_RSH:
5424 case S390_ALU_RSHA: ; /* avoid GCC warning */
5425 }
5426 goto fail;
5427 }
5428 goto fail;
5429 }
5430
5431 /* 2nd operand is an immediate value */
5432 if (op2.tag == S390_OPND_IMMEDIATE) {
5433 ULong value;
5434
5435 /* No masking of the value is required as it is not sign extended */
5436 value = op2.variant.imm;
5437
5438 switch (insn->size) {
5439 case 1:
5440 case 2:
5441 /* There is no 1-byte opcode. Do the computation in
5442 2 bytes. The extra byte will be ignored. */
5443 switch (insn->variant.alu.tag) {
5444 case S390_ALU_ADD:
5445 return s390_emit_AHI(buf, dst, value);
5446
5447 case S390_ALU_SUB:
sewardjb13a92a2011-04-13 14:44:29 +00005448 return s390_emit_SLFIw(buf, dst, value);
sewardj2019a972011-03-07 16:04:07 +00005449
5450 case S390_ALU_MUL:
5451 return s390_emit_MHI(buf, dst, value);
5452
5453 case S390_ALU_AND: return s390_emit_NILL(buf, dst, value);
5454 case S390_ALU_OR: return s390_emit_OILL(buf, dst, value);
5455 case S390_ALU_XOR:
5456 /* There is no XILL instruction. Load the immediate value into
5457 R0 and combine with the destination register. */
5458 buf = s390_emit_LHI(buf, R0, value);
5459 return s390_emit_XR(buf, dst, R0);
5460
5461 case S390_ALU_LSH:
sewardj3c49aaa2011-04-05 14:00:37 +00005462 return s390_emit_SLL(buf, dst, 0, value);
sewardj2019a972011-03-07 16:04:07 +00005463
5464 case S390_ALU_RSH:
sewardj3c49aaa2011-04-05 14:00:37 +00005465 return s390_emit_SRL(buf, dst, 0, value);
sewardj2019a972011-03-07 16:04:07 +00005466
5467 case S390_ALU_RSHA:
sewardj3c49aaa2011-04-05 14:00:37 +00005468 return s390_emit_SRA(buf, dst, 0, value);
sewardj2019a972011-03-07 16:04:07 +00005469 }
5470 goto fail;
5471
5472 case 4:
5473 switch (insn->variant.alu.tag) {
5474 case S390_ALU_ADD:
5475 if (uint_fits_signed_16bit(value)) {
5476 return s390_emit_AHI(buf, dst, value);
5477 }
5478 return s390_emit_AFIw(buf, dst, value);
5479
5480 case S390_ALU_SUB: return s390_emit_SLFIw(buf, dst, value);
5481 case S390_ALU_MUL: return s390_emit_MSFIw(buf, dst, value);
5482 case S390_ALU_AND: return s390_emit_NILFw(buf, dst, value);
5483 case S390_ALU_OR: return s390_emit_OILFw(buf, dst, value);
5484 case S390_ALU_XOR: return s390_emit_XILFw(buf, dst, value);
sewardj3c49aaa2011-04-05 14:00:37 +00005485 case S390_ALU_LSH: return s390_emit_SLL(buf, dst, 0, value);
5486 case S390_ALU_RSH: return s390_emit_SRL(buf, dst, 0, value);
5487 case S390_ALU_RSHA: return s390_emit_SRA(buf, dst, 0, value);
sewardj2019a972011-03-07 16:04:07 +00005488 }
5489 goto fail;
5490
5491 case 8:
5492 switch (insn->variant.alu.tag) {
5493 case S390_ALU_ADD:
5494 if (ulong_fits_signed_16bit(value)) {
5495 return s390_emit_AGHI(buf, dst, value);
5496 }
5497 if (ulong_fits_signed_32bit(value) && s390_host_has_eimm) {
5498 return s390_emit_AGFI(buf, dst, value);
5499 }
5500 /* Load constant into R0 then add */
5501 buf = s390_emit_load_64imm(buf, R0, value);
5502 return s390_emit_AGR(buf, dst, R0);
5503
5504 case S390_ALU_SUB:
sewardjb13a92a2011-04-13 14:44:29 +00005505 if (ulong_fits_unsigned_32bit(value)) {
5506 return s390_emit_SLGFIw(buf, dst, value);
5507 }
sewardj2019a972011-03-07 16:04:07 +00005508 /* Load value into R0; then subtract from destination reg */
5509 buf = s390_emit_load_64imm(buf, R0, value);
5510 return s390_emit_SGR(buf, dst, R0);
5511
5512 case S390_ALU_MUL:
5513 if (ulong_fits_signed_32bit(value) && s390_host_has_gie) {
5514 return s390_emit_MSGFI(buf, dst, value);
5515 }
5516 /* Load constant into R0 then add */
5517 buf = s390_emit_load_64imm(buf, R0, value);
5518 return s390_emit_MSGR(buf, dst, R0);
5519
5520 /* Do it in two steps: upper half [0:31] and lower half [32:63] */
5521 case S390_ALU_AND:
5522 if (s390_host_has_eimm) {
5523 buf = s390_emit_NIHF(buf, dst, value >> 32);
5524 return s390_emit_NILF(buf, dst, value & 0xFFFFFFFF);
5525 }
5526 /* Load value into R0; then combine with destination reg */
5527 buf = s390_emit_load_64imm(buf, R0, value);
5528 return s390_emit_NGR(buf, dst, R0);
5529
5530 case S390_ALU_OR:
5531 if (s390_host_has_eimm) {
5532 buf = s390_emit_OIHF(buf, dst, value >> 32);
5533 return s390_emit_OILF(buf, dst, value & 0xFFFFFFFF);
5534 }
5535 /* Load value into R0; then combine with destination reg */
5536 buf = s390_emit_load_64imm(buf, R0, value);
5537 return s390_emit_OGR(buf, dst, R0);
5538
5539 case S390_ALU_XOR:
5540 if (s390_host_has_eimm) {
5541 buf = s390_emit_XIHF(buf, dst, value >> 32);
5542 return s390_emit_XILF(buf, dst, value & 0xFFFFFFFF);
5543 }
5544 /* Load value into R0; then combine with destination reg */
5545 buf = s390_emit_load_64imm(buf, R0, value);
5546 return s390_emit_XGR(buf, dst, R0);
5547
sewardj652b56a2011-04-13 15:38:17 +00005548 /* No special considerations for long displacement here. Only the six
5549 least significant bits of VALUE will be taken; all other bits are
5550 ignored. So the DH2 bits are irrelevant and do not influence the
5551 shift operation, independent of whether long-displacement is available
5552 or not. */
sewardj2019a972011-03-07 16:04:07 +00005553 case S390_ALU_LSH: return s390_emit_SLLG(buf, dst, dst, 0, DISP20(value));
5554 case S390_ALU_RSH: return s390_emit_SRLG(buf, dst, dst, 0, DISP20(value));
5555 case S390_ALU_RSHA: return s390_emit_SRAG(buf, dst, dst, 0, DISP20(value));
5556 }
5557 goto fail;
5558 }
5559 goto fail;
5560 }
5561
5562 fail:
5563 vpanic("s390_insn_alu_emit");
5564}
5565
5566
5567static UChar *
5568s390_widen_emit(UChar *buf, const s390_insn *insn, UInt from_size,
5569 Bool sign_extend)
5570{
sewardj06122e72011-03-28 12:14:48 +00005571 s390_opnd_RMI opnd = insn->variant.unop.src;
sewardj2019a972011-03-07 16:04:07 +00005572
5573 switch (opnd.tag) {
5574 case S390_OPND_REG: {
5575 UChar r1 = hregNumber(insn->variant.unop.dst);
5576 UChar r2 = hregNumber(opnd.variant.reg);
5577
5578 switch (from_size) {
5579 case 1:
5580 /* Widening to a half-word is implemented like widening to a word
5581 because the upper half-word will not be looked at. */
5582 if (insn->size == 4 || insn->size == 2) { /* 8 --> 32 8 --> 16 */
5583 if (sign_extend)
5584 return s390_emit_LBRw(buf, r1, r2);
5585 else
5586 return s390_emit_LLCRw(buf, r1, r2);
5587 }
5588 if (insn->size == 8) { /* 8 --> 64 */
5589 if (sign_extend)
5590 return s390_emit_LGBRw(buf, r1, r2);
5591 else
5592 return s390_emit_LLGCRw(buf, r1, r2);
5593 }
5594 goto fail;
5595
5596 case 2:
5597 if (insn->size == 4) { /* 16 --> 32 */
5598 if (sign_extend)
5599 return s390_emit_LHRw(buf, r1, r2);
5600 else
5601 return s390_emit_LLHRw(buf, r1, r2);
5602 }
5603 if (insn->size == 8) { /* 16 --> 64 */
5604 if (sign_extend)
5605 return s390_emit_LGHRw(buf, r1, r2);
5606 else
5607 return s390_emit_LLGHRw(buf, r1, r2);
5608 }
5609 goto fail;
5610
5611 case 4:
5612 if (insn->size == 8) { /* 32 --> 64 */
5613 if (sign_extend)
5614 return s390_emit_LGFR(buf, r1, r2);
5615 else
5616 return s390_emit_LLGFR(buf, r1, r2);
5617 }
5618 goto fail;
5619
5620 default: /* unexpected "from" size */
5621 goto fail;
5622 }
5623 }
5624
5625 case S390_OPND_AMODE: {
5626 UChar r1 = hregNumber(insn->variant.unop.dst);
5627 const s390_amode *src = opnd.variant.am;
5628 UChar b = hregNumber(src->b);
5629 UChar x = hregNumber(src->x);
5630 Int d = src->d;
5631
5632 switch (from_size) {
5633 case 1:
5634 if (insn->size == 4 || insn->size == 2) {
5635 if (sign_extend)
sewardj652b56a2011-04-13 15:38:17 +00005636 return s390_emit_LBw(buf, r1, x, b, DISP20(d));
sewardj2019a972011-03-07 16:04:07 +00005637 else
5638 return s390_emit_LLCw(buf, r1, x, b, DISP20(d));
5639 }
5640 if (insn->size == 8) {
5641 if (sign_extend)
sewardj652b56a2011-04-13 15:38:17 +00005642 return s390_emit_LGBw(buf, r1, x, b, DISP20(d));
sewardj2019a972011-03-07 16:04:07 +00005643 else
sewardj2019a972011-03-07 16:04:07 +00005644 return s390_emit_LLGC(buf, r1, x, b, DISP20(d));
5645 }
5646 goto fail;
5647
5648 case 2:
5649 if (insn->size == 4) { /* 16 --> 32 */
5650 if (sign_extend == 0)
5651 return s390_emit_LLHw(buf, r1, x, b, DISP20(d));
5652
5653 switch (src->tag) {
5654 case S390_AMODE_B12:
5655 case S390_AMODE_BX12:
5656 return s390_emit_LH(buf, r1, x, b, d);
5657
5658 case S390_AMODE_B20:
5659 case S390_AMODE_BX20:
5660 return s390_emit_LHY(buf, r1, x, b, DISP20(d));
5661 }
5662 goto fail;
5663 }
5664 if (insn->size == 8) { /* 16 --> 64 */
sewardj2019a972011-03-07 16:04:07 +00005665 if (sign_extend)
5666 return s390_emit_LGH(buf, r1, x, b, DISP20(d));
5667 else
5668 return s390_emit_LLGH(buf, r1, x, b, DISP20(d));
5669 }
5670 goto fail;
5671
5672 case 4:
5673 if (insn->size == 8) { /* 32 --> 64 */
sewardj2019a972011-03-07 16:04:07 +00005674 if (sign_extend)
5675 return s390_emit_LGF(buf, r1, x, b, DISP20(d));
5676 else
5677 return s390_emit_LLGF(buf, r1, x, b, DISP20(d));
5678 }
5679 goto fail;
5680
5681 default: /* unexpected "from" size */
5682 goto fail;
5683 }
5684 }
5685
5686 case S390_OPND_IMMEDIATE: {
5687 UChar r1 = hregNumber(insn->variant.unop.dst);
5688 ULong value = opnd.variant.imm;
5689
5690 switch (from_size) {
5691 case 1:
5692 if (insn->size == 4 || insn->size == 2) { /* 8 --> 32 8 --> 16 */
5693 if (sign_extend) {
5694 /* host can do the sign extension to 16-bit; LHI does the rest */
5695 return s390_emit_LHI(buf, r1, (Short)(Char)(UChar)value);
5696 } else {
5697 return s390_emit_LHI(buf, r1, value);
5698 }
5699 }
5700 if (insn->size == 8) { /* 8 --> 64 */
5701 if (sign_extend) {
5702 /* host can do the sign extension to 16-bit; LGHI does the rest */
5703 return s390_emit_LGHI(buf, r1, (Short)(Char)(UChar)value);
5704 } else {
5705 return s390_emit_LGHI(buf, r1, value);
5706 }
5707 }
5708 goto fail;
5709
5710 case 2:
5711 if (insn->size == 4) { /* 16 --> 32 */
5712 return s390_emit_LHI(buf, r1, value);
5713 }
5714 if (insn->size == 8) { /* 16 --> 64 */
5715 if (sign_extend)
5716 return s390_emit_LGHI(buf, r1, value);
5717 else
5718 return s390_emit_LLILL(buf, r1, value);
5719 }
5720 goto fail;
5721
5722 case 4:
5723 if (insn->size == 8) { /* 32 --> 64 */
5724 if (sign_extend)
5725 return s390_emit_LGFIw(buf, r1, value);
5726 else
5727 return s390_emit_LLILFw(buf, r1, value);
5728 }
5729 goto fail;
5730
5731 default: /* unexpected "from" size */
5732 goto fail;
5733 }
5734 }
5735 }
5736
5737 fail:
5738 vpanic("s390_widen_emit");
5739}
5740
5741
5742static UChar *
5743s390_negate_emit(UChar *buf, const s390_insn *insn)
5744{
5745 s390_opnd_RMI opnd;
5746
5747 opnd = insn->variant.unop.src;
5748
5749 switch (opnd.tag) {
5750 case S390_OPND_REG: {
5751 UChar r1 = hregNumber(insn->variant.unop.dst);
5752 UChar r2 = hregNumber(opnd.variant.reg);
5753
5754 switch (insn->size) {
5755 case 1:
5756 case 2:
5757 case 4:
5758 return s390_emit_LCR(buf, r1, r2);
5759
5760 case 8:
5761 return s390_emit_LCGR(buf, r1, r2);
5762
5763 default:
5764 goto fail;
5765 }
5766 }
5767
5768 case S390_OPND_AMODE: {
5769 UChar r1 = hregNumber(insn->variant.unop.dst);
5770
5771 /* Load bytes into scratch register R0, then negate */
5772 buf = s390_emit_load_mem(buf, insn->size, R0, opnd.variant.am);
5773
5774 switch (insn->size) {
5775 case 1:
5776 case 2:
5777 case 4:
5778 return s390_emit_LCR(buf, r1, R0);
5779
5780 case 8:
5781 return s390_emit_LCGR(buf, r1, R0);
5782
5783 default:
5784 goto fail;
5785 }
5786 }
5787
5788 case S390_OPND_IMMEDIATE: {
5789 UChar r1 = hregNumber(insn->variant.unop.dst);
5790 ULong value = opnd.variant.imm;
5791
5792 value = ~value + 1; /* two's complement */
5793
5794 switch (insn->size) {
5795 case 1:
5796 case 2:
5797 /* Load the immediate values as a 4 byte value. That does not hurt as
5798 those extra bytes will not be looked at. Fall through .... */
5799 case 4:
5800 return s390_emit_load_32imm(buf, r1, value);
5801
5802 case 8:
5803 return s390_emit_load_64imm(buf, r1, value);
5804
5805 default:
5806 goto fail;
5807 }
5808 }
5809 }
5810
5811 fail:
5812 vpanic("s390_negate_emit");
5813}
5814
5815
5816static UChar *
5817s390_insn_unop_emit(UChar *buf, const s390_insn *insn)
5818{
5819 switch (insn->variant.unop.tag) {
5820 case S390_ZERO_EXTEND_8: return s390_widen_emit(buf, insn, 1, 0);
5821 case S390_ZERO_EXTEND_16: return s390_widen_emit(buf, insn, 2, 0);
5822 case S390_ZERO_EXTEND_32: return s390_widen_emit(buf, insn, 4, 0);
5823
5824 case S390_SIGN_EXTEND_8: return s390_widen_emit(buf, insn, 1, 1);
5825 case S390_SIGN_EXTEND_16: return s390_widen_emit(buf, insn, 2, 1);
5826 case S390_SIGN_EXTEND_32: return s390_widen_emit(buf, insn, 4, 1);
5827
5828 case S390_NEGATE: return s390_negate_emit(buf, insn);
5829 }
5830
5831 vpanic("s390_insn_unop_emit");
5832}
5833
5834
5835/* Only 4-byte and 8-byte operands are handled. 1-byte and 2-byte
5836 comparisons will have been converted to 4-byte comparisons in
5837 s390_isel_cc and should not occur here. */
5838static UChar *
5839s390_insn_test_emit(UChar *buf, const s390_insn *insn)
5840{
5841 s390_opnd_RMI opnd;
5842
5843 opnd = insn->variant.test.src;
5844
5845 switch (opnd.tag) {
5846 case S390_OPND_REG: {
5847 UInt reg = hregNumber(opnd.variant.reg);
5848
5849 switch (insn->size) {
5850 case 4:
5851 return s390_emit_LTR(buf, reg, reg);
5852
5853 case 8:
5854 return s390_emit_LTGR(buf, reg, reg);
5855
5856 default:
5857 goto fail;
5858 }
5859 }
5860
5861 case S390_OPND_AMODE: {
5862 const s390_amode *am = opnd.variant.am;
5863 UChar b = hregNumber(am->b);
5864 UChar x = hregNumber(am->x);
5865 Int d = am->d;
5866
5867 switch (insn->size) {
5868 case 4:
5869 return s390_emit_LTw(buf, R0, x, b, DISP20(d));
5870
5871 case 8:
5872 return s390_emit_LTGw(buf, R0, x, b, DISP20(d));
5873
5874 default:
5875 goto fail;
5876 }
5877 }
5878
5879 case S390_OPND_IMMEDIATE: {
5880 ULong value = opnd.variant.imm;
5881
5882 switch (insn->size) {
5883 case 4:
5884 buf = s390_emit_load_32imm(buf, R0, value);
5885 return s390_emit_LTR(buf, R0, R0);
5886
5887 case 8:
5888 buf = s390_emit_load_64imm(buf, R0, value);
5889 return s390_emit_LTGR(buf, R0, R0);
5890
5891 default:
5892 goto fail;
5893 }
5894 }
5895
5896 default:
5897 goto fail;
5898 }
5899
5900 fail:
5901 vpanic("s390_insn_test_emit");
5902}
5903
5904
5905static UChar *
5906s390_insn_cc2bool_emit(UChar *buf, const s390_insn *insn)
5907{
5908 UChar r1 = hregNumber(insn->variant.cc2bool.dst);
5909 s390_cc_t cond = insn->variant.cc2bool.cond;
5910
5911 /* Make the destination register be 1 or 0, depending on whether
5912 the relevant condition holds. A 64-bit value is computed. */
5913 if (cond == S390_CC_ALWAYS)
5914 return s390_emit_LGHI(buf, r1, 1); /* r1 = 1 */
5915
5916 buf = s390_emit_load_cc(buf, r1); /* r1 = cc */
5917 buf = s390_emit_LGHI(buf, R0, cond); /* r0 = mask */
5918 buf = s390_emit_SLLG(buf, r1, R0, r1, DISP20(0)); /* r1 = mask << cc */
5919 buf = s390_emit_SRLG(buf, r1, r1, 0, DISP20(3)); /* r1 = r1 >> 3 */
5920 buf = s390_emit_NILL(buf, r1, 1); /* r1 = r1 & 0x1 */
5921
5922 return buf;
5923}
5924
5925
5926/* Only 4-byte and 8-byte operands are handled. */
5927static UChar *
5928s390_insn_cas_emit(UChar *buf, const s390_insn *insn)
5929{
5930 UChar r1, r3, b, old;
5931 Int d;
5932 s390_amode *am;
5933
5934 r1 = hregNumber(insn->variant.cas.op1); /* expected value */
5935 r3 = hregNumber(insn->variant.cas.op3);
5936 old= hregNumber(insn->variant.cas.old_mem);
5937 am = insn->variant.cas.op2;
5938 b = hregNumber(am->b);
5939 d = am->d;
5940
5941 switch (insn->size) {
5942 case 4:
5943 /* r1 must no be overwritten. So copy it to R0 and let CS clobber it */
5944 buf = s390_emit_LR(buf, R0, r1);
5945 if (am->tag == S390_AMODE_B12)
5946 buf = s390_emit_CS(buf, R0, r3, b, d);
5947 else
5948 buf = s390_emit_CSY(buf, R0, r3, b, DISP20(d));
5949 /* Now copy R0 which has the old memory value to OLD */
5950 return s390_emit_LR(buf, old, R0);
5951
5952 case 8:
5953 /* r1 must no be overwritten. So copy it to R0 and let CS clobber it */
5954 buf = s390_emit_LGR(buf, R0, r1);
5955 buf = s390_emit_CSG(buf, R0, r3, b, DISP20(d));
5956 /* Now copy R0 which has the old memory value to OLD */
5957 return s390_emit_LGR(buf, old, R0);
5958
5959 default:
5960 goto fail;
5961 }
5962
5963 fail:
5964 vpanic("s390_insn_cas_emit");
5965}
5966
5967
5968/* Only 4-byte and 8-byte comparisons are handled. 1-byte and 2-byte
5969 comparisons will have been converted to 4-byte comparisons in
5970 s390_isel_cc and should not occur here. */
5971static UChar *
5972s390_insn_compare_emit(UChar *buf, const s390_insn *insn)
5973{
5974 s390_opnd_RMI op2;
5975 HReg op1;
5976 Bool signed_comparison;
5977
5978 op1 = insn->variant.compare.src1;
5979 op2 = insn->variant.compare.src2;
5980 signed_comparison = insn->variant.compare.signed_comparison;
5981
5982 switch (op2.tag) {
5983 case S390_OPND_REG: {
5984 UInt r1 = hregNumber(op1);
5985 UInt r2 = hregNumber(op2.variant.reg);
5986
5987 switch (insn->size) {
5988 case 4:
5989 if (signed_comparison)
5990 return s390_emit_CR(buf, r1, r2);
5991 else
5992 return s390_emit_CLR(buf, r1, r2);
5993
5994 case 8:
5995 if (signed_comparison)
5996 return s390_emit_CGR(buf, r1, r2);
5997 else
5998 return s390_emit_CLGR(buf, r1, r2);
5999
6000 default:
6001 goto fail;
6002 }
6003 }
6004
6005 case S390_OPND_AMODE: {
6006 UChar r1 = hregNumber(op1);
6007 const s390_amode *am = op2.variant.am;
6008 UChar b = hregNumber(am->b);
6009 UChar x = hregNumber(am->x);
6010 Int d = am->d;
6011
6012 switch (insn->size) {
6013 case 4:
6014 switch (am->tag) {
6015 case S390_AMODE_B12:
6016 case S390_AMODE_BX12:
6017 if (signed_comparison)
6018 return s390_emit_C(buf, r1, x, b, d);
6019 else
6020 return s390_emit_CL(buf, r1, x, b, d);
6021
6022 case S390_AMODE_B20:
6023 case S390_AMODE_BX20:
6024 if (signed_comparison)
6025 return s390_emit_CY(buf, r1, x, b, DISP20(d));
6026 else
6027 return s390_emit_CLY(buf, r1, x, b, DISP20(d));
6028 }
6029 goto fail;
6030
6031 case 8:
6032 if (signed_comparison)
6033 return s390_emit_CG(buf, r1, x, b, DISP20(d));
6034 else
6035 return s390_emit_CLG(buf, r1, x, b, DISP20(d));
6036
6037 default:
6038 goto fail;
6039 }
6040 }
6041
6042 case S390_OPND_IMMEDIATE: {
6043 UChar r1 = hregNumber(op1);
6044 ULong value = op2.variant.imm;
6045
6046 switch (insn->size) {
6047 case 4:
6048 if (signed_comparison)
6049 return s390_emit_CFIw(buf, r1, value);
6050 else
6051 return s390_emit_CLFIw(buf, r1, value);
6052
6053 case 8:
6054 buf = s390_emit_load_64imm(buf, R0, value);
6055 if (signed_comparison)
6056 return s390_emit_CGR(buf, r1, R0);
6057 else
6058 return s390_emit_CLGR(buf, r1, R0);
6059
6060 default:
6061 goto fail;
6062 }
6063 }
6064
6065 default:
6066 goto fail;
6067 }
6068
6069 fail:
6070 vpanic("s390_insn_compare_emit");
6071}
6072
6073
6074static UChar *
6075s390_insn_mul_emit(UChar *buf, const s390_insn *insn)
6076{
6077 s390_opnd_RMI op2;
6078 UChar r1;
6079 Bool signed_multiply;
6080
6081 /* The register number identifying the register pair */
6082 r1 = hregNumber(insn->variant.mul.dst_hi);
6083
6084 op2 = insn->variant.mul.op2;
6085 signed_multiply = insn->variant.mul.signed_multiply;
6086
6087 switch (op2.tag) {
6088 case S390_OPND_REG: {
6089 UInt r2 = hregNumber(op2.variant.reg);
6090
6091 switch (insn->size) {
6092 case 1:
6093 case 2:
6094 case 4:
6095 if (signed_multiply)
6096 return s390_emit_MR(buf, r1, r2);
6097 else
6098 return s390_emit_MLR(buf, r1, r2);
6099
6100 case 8:
6101 if (signed_multiply)
6102 vpanic("s390_insn_mul_emit");
6103 else
6104 return s390_emit_MLGR(buf, r1, r2);
6105
6106 default:
6107 goto fail;
6108 }
6109 }
6110
6111 case S390_OPND_AMODE: {
6112 const s390_amode *am = op2.variant.am;
6113 UChar b = hregNumber(am->b);
6114 UChar x = hregNumber(am->x);
6115 Int d = am->d;
6116
6117 switch (insn->size) {
6118 case 1:
6119 case 2:
6120 /* Load bytes into scratch register R0, then multiply */
6121 buf = s390_emit_load_mem(buf, insn->size, R0, am);
6122 if (signed_multiply)
6123 return s390_emit_MR(buf, r1, R0);
6124 else
6125 return s390_emit_MLR(buf, r1, R0);
6126
6127 case 4:
6128 switch (am->tag) {
6129 case S390_AMODE_B12:
6130 case S390_AMODE_BX12:
6131 if (signed_multiply)
6132 return s390_emit_M(buf, r1, x, b, d);
6133 else
6134 return s390_emit_ML(buf, r1, x, b, DISP20(d));
6135
6136 case S390_AMODE_B20:
6137 case S390_AMODE_BX20:
6138 if (signed_multiply)
6139 return s390_emit_MFYw(buf, r1, x, b, DISP20(d));
6140 else
sewardjb13a92a2011-04-13 14:44:29 +00006141 return s390_emit_ML(buf, r1, x, b, DISP20(d));
sewardj2019a972011-03-07 16:04:07 +00006142 }
6143 goto fail;
6144
6145 case 8:
6146 if (signed_multiply)
6147 vpanic("s390_insn_mul_emit");
6148 else
6149 return s390_emit_MLG(buf, r1, x, b, DISP20(d));
6150
6151 default:
6152 goto fail;
6153 }
6154 }
6155
6156 case S390_OPND_IMMEDIATE: {
6157 ULong value = op2.variant.imm;
6158
6159 switch (insn->size) {
6160 case 1:
6161 case 2:
6162 case 4:
6163 buf = s390_emit_load_32imm(buf, R0, value);
6164 if (signed_multiply)
6165 return s390_emit_MR(buf, r1, R0);
6166 else
6167 return s390_emit_MLR(buf, r1, R0);
6168
6169 case 8:
6170 buf = s390_emit_load_64imm(buf, R0, value);
6171 if (signed_multiply)
6172 vpanic("s390_insn_mul_emit");
6173 else
6174 return s390_emit_MLGR(buf, r1, R0);
6175
6176 default:
6177 goto fail;
6178 }
6179 }
6180
6181 default:
6182 goto fail;
6183 }
6184
6185 fail:
6186 vpanic("s390_insn_mul_emit");
6187}
6188
6189
6190static UChar *
6191s390_insn_div_emit(UChar *buf, const s390_insn *insn)
6192{
6193 s390_opnd_RMI op2;
6194 UChar r1;
6195 Bool signed_divide;
6196
6197 r1 = hregNumber(insn->variant.div.op1_hi);
6198 op2 = insn->variant.div.op2;
6199 signed_divide = insn->variant.div.signed_divide;
6200
6201 switch (op2.tag) {
6202 case S390_OPND_REG: {
6203 UInt r2 = hregNumber(op2.variant.reg);
6204
6205 switch (insn->size) {
6206 case 4:
6207 if (signed_divide)
6208 return s390_emit_DR(buf, r1, r2);
6209 else
6210 return s390_emit_DLR(buf, r1, r2);
6211
6212 case 8:
6213 if (signed_divide)
6214 vpanic("s390_insn_div_emit");
6215 else
6216 return s390_emit_DLGR(buf, r1, r2);
6217
6218 default:
6219 goto fail;
6220 }
6221 }
6222
6223 case S390_OPND_AMODE: {
6224 const s390_amode *am = op2.variant.am;
6225 UChar b = hregNumber(am->b);
6226 UChar x = hregNumber(am->x);
6227 Int d = am->d;
6228
6229 switch (insn->size) {
6230 case 4:
6231 switch (am->tag) {
6232 case S390_AMODE_B12:
6233 case S390_AMODE_BX12:
6234 if (signed_divide)
6235 return s390_emit_D(buf, r1, x, b, d);
6236 else
6237 return s390_emit_DL(buf, r1, x, b, DISP20(d));
6238
6239 case S390_AMODE_B20:
6240 case S390_AMODE_BX20:
sewardjb13a92a2011-04-13 14:44:29 +00006241 if (signed_divide) {
6242 buf = s390_emit_LY(buf, R0, x, b, DISP20(d));
sewardj2019a972011-03-07 16:04:07 +00006243 return s390_emit_DR(buf, r1, R0);
sewardjb13a92a2011-04-13 14:44:29 +00006244 } else
6245 return s390_emit_DL(buf, r1, x, b, DISP20(d));
sewardj2019a972011-03-07 16:04:07 +00006246 }
6247 goto fail;
6248
6249 case 8:
6250 if (signed_divide)
6251 vpanic("s390_insn_div_emit");
6252 else
6253 return s390_emit_DLG(buf, r1, x, b, DISP20(d));
6254
6255 default:
6256 goto fail;
6257 }
6258 }
6259
6260 case S390_OPND_IMMEDIATE: {
6261 ULong value = op2.variant.imm;
6262
6263 switch (insn->size) {
6264 case 4:
6265 buf = s390_emit_load_32imm(buf, R0, value);
6266 if (signed_divide)
6267 return s390_emit_DR(buf, r1, R0);
6268 else
6269 return s390_emit_DLR(buf, r1, R0);
6270
6271 case 8:
6272 buf = s390_emit_load_64imm(buf, R0, value);
6273 if (signed_divide)
6274 vpanic("s390_insn_div_emit");
6275 else
6276 return s390_emit_DLGR(buf, r1, R0);
6277
6278 default:
6279 goto fail;
6280 }
6281 }
6282
6283 default:
6284 goto fail;
6285 }
6286
6287 fail:
6288 vpanic("s390_insn_div_emit");
6289}
6290
6291
6292static UChar *
6293s390_insn_divs_emit(UChar *buf, const s390_insn *insn)
6294{
6295 s390_opnd_RMI op2;
6296 UChar r1;
6297
6298 r1 = hregNumber(insn->variant.divs.rem);
6299 op2 = insn->variant.divs.op2;
6300
6301 switch (op2.tag) {
6302 case S390_OPND_REG: {
6303 UInt r2 = hregNumber(op2.variant.reg);
6304
6305 return s390_emit_DSGR(buf, r1, r2);
6306 }
6307
6308 case S390_OPND_AMODE: {
6309 const s390_amode *am = op2.variant.am;
6310 UChar b = hregNumber(am->b);
6311 UChar x = hregNumber(am->x);
6312 Int d = am->d;
6313
6314 return s390_emit_DSG(buf, r1, x, b, DISP20(d));
6315 }
6316
6317 case S390_OPND_IMMEDIATE: {
6318 ULong value = op2.variant.imm;
6319
6320 buf = s390_emit_load_64imm(buf, R0, value);
6321 return s390_emit_DSGR(buf, r1, R0);
6322 }
6323
6324 default:
6325 goto fail;
6326 }
6327
6328 fail:
6329 vpanic("s390_insn_divs_emit");
6330}
6331
6332
6333static UChar *
sewardj611b06e2011-03-24 08:57:29 +00006334s390_insn_clz_emit(UChar *buf, const s390_insn *insn)
sewardj2019a972011-03-07 16:04:07 +00006335{
6336 s390_opnd_RMI src;
sewardj611b06e2011-03-24 08:57:29 +00006337 UChar r1, r1p1, r2, *p;
sewardj2019a972011-03-07 16:04:07 +00006338
sewardj611b06e2011-03-24 08:57:29 +00006339 r1 = hregNumber(insn->variant.clz.num_bits);
6340 r1p1 = hregNumber(insn->variant.clz.clobber);
sewardj2019a972011-03-07 16:04:07 +00006341
6342 vassert((r1 & 0x1) == 0);
6343 vassert(r1p1 == r1 + 1);
6344
sewardj611b06e2011-03-24 08:57:29 +00006345 p = buf;
6346 src = insn->variant.clz.src;
sewardj2019a972011-03-07 16:04:07 +00006347
sewardj611b06e2011-03-24 08:57:29 +00006348 /* Get operand and move it to r2 */
sewardj2019a972011-03-07 16:04:07 +00006349 switch (src.tag) {
sewardj611b06e2011-03-24 08:57:29 +00006350 case S390_OPND_REG:
6351 r2 = hregNumber(src.variant.reg);
6352 break;
sewardj2019a972011-03-07 16:04:07 +00006353
6354 case S390_OPND_AMODE: {
6355 const s390_amode *am = src.variant.am;
6356 UChar b = hregNumber(am->b);
6357 UChar x = hregNumber(am->x);
6358 Int d = am->d;
6359
sewardj611b06e2011-03-24 08:57:29 +00006360 p = s390_emit_LG(p, R0, x, b, DISP20(d));
6361 r2 = R0;
6362 break;
sewardj2019a972011-03-07 16:04:07 +00006363 }
6364
6365 case S390_OPND_IMMEDIATE: {
6366 ULong value = src.variant.imm;
6367
sewardj611b06e2011-03-24 08:57:29 +00006368 p = s390_emit_load_64imm(p, R0, value);
6369 r2 = R0;
6370 break;
sewardj2019a972011-03-07 16:04:07 +00006371 }
6372
6373 default:
6374 goto fail;
6375 }
6376
sewardj611b06e2011-03-24 08:57:29 +00006377 /* Use FLOGR if you can */
6378 if (s390_host_has_eimm) {
6379 return s390_emit_FLOGR(p, r1, r2);
6380 }
6381
6382 /*
6383 r0 = r2;
6384 r1 = 64;
6385 while (r0 != 0) {
6386 r1 -= 1;
6387 r0 >>= 1;
6388 }
6389 */
6390 p = s390_emit_LTGR(p, R0, r2);
6391 p = s390_emit_LLILL(p, r1, 64);
6392
6393 p = s390_emit_BRC(p, S390_CC_E, (4 + 4 + 6 + 4 + 4)/ 2); /* 4 bytes */
6394 p = s390_emit_AGHI(p, r1, (UShort)-1); /* r1 -= 1; 4 bytes */
6395 p = s390_emit_SRLG(p, R0, R0, R0, DISP20(1)); /* r0 >>= 1; 6 bytes */
6396 p = s390_emit_LTGR(p, R0, R0); /* set cc 4 bytes */
6397 p = s390_emit_BRC(p, S390_CC_NE, /* 4 bytes */
6398 (UShort)(-(4 + 6 + 4) / 2));
6399 return p;
6400
sewardj2019a972011-03-07 16:04:07 +00006401 fail:
sewardj611b06e2011-03-24 08:57:29 +00006402 vpanic("s390_insn_clz_emit");
sewardj2019a972011-03-07 16:04:07 +00006403}
6404
6405
6406static UChar *
6407s390_insn_branch_emit(UChar *buf, const s390_insn *insn)
6408{
6409 s390_opnd_RMI dst;
6410 s390_cc_t cond;
sewardj2019a972011-03-07 16:04:07 +00006411 UInt trc;
6412 UChar *p, *ptmp = 0; /* avoid compiler warnings */
6413
sewardj2019a972011-03-07 16:04:07 +00006414 cond = insn->variant.branch.cond;
6415 dst = insn->variant.branch.dst;
6416
6417 p = buf;
6418 trc = 0;
6419
6420 if (cond != S390_CC_ALWAYS) {
6421 /* So we have something like this
6422 if (cond) goto X;
6423 Y: ...
6424 We convert this into
6425 if (! cond) goto Y; // BRC insn; 4 bytes
6426 return_reg = X;
6427 return to dispatcher
6428 Y:
6429 */
6430 ptmp = p; /* 4 bytes (a BRC insn) to be filled in here */
6431 p += 4;
6432 }
6433
6434 /* If a non-boring, set guest-state-pointer appropriately. */
6435
6436 switch (insn->variant.branch.kind) {
6437 case Ijk_ClientReq: trc = VEX_TRC_JMP_CLIENTREQ; break;
6438 case Ijk_Sys_syscall: trc = VEX_TRC_JMP_SYS_SYSCALL; break;
6439 case Ijk_Yield: trc = VEX_TRC_JMP_YIELD; break;
6440 case Ijk_EmWarn: trc = VEX_TRC_JMP_EMWARN; break;
6441 case Ijk_EmFail: trc = VEX_TRC_JMP_EMFAIL; break;
6442 case Ijk_MapFail: trc = VEX_TRC_JMP_MAPFAIL; break;
6443 case Ijk_NoDecode: trc = VEX_TRC_JMP_NODECODE; break;
6444 case Ijk_TInval: trc = VEX_TRC_JMP_TINVAL; break;
6445 case Ijk_NoRedir: trc = VEX_TRC_JMP_NOREDIR; break;
6446 case Ijk_SigTRAP: trc = VEX_TRC_JMP_SIGTRAP; break;
6447 case Ijk_Ret: trc = 0; break;
6448 case Ijk_Call: trc = 0; break;
6449 case Ijk_Boring: trc = 0; break;
6450 break;
6451
6452 default:
6453 vpanic("s390_insn_branch_emit: unknown jump kind");
6454 }
6455
6456 /* Get the destination address into the return register */
6457 switch (dst.tag) {
6458 case S390_OPND_REG:
6459 p = s390_emit_LGR(p, S390_REGNO_RETURN_VALUE, hregNumber(dst.variant.reg));
6460 break;
6461
6462 case S390_OPND_AMODE: {
6463 const s390_amode *am = dst.variant.am;
6464 UChar b = hregNumber(am->b);
6465 UChar x = hregNumber(am->x);
6466 Int d = am->d;
6467
6468 p = s390_emit_LG(p, S390_REGNO_RETURN_VALUE, x, b, DISP20(d));
6469 break;
6470 }
6471
6472 case S390_OPND_IMMEDIATE:
6473 p = s390_emit_load_64imm(p, S390_REGNO_RETURN_VALUE, dst.variant.imm);
6474 break;
6475
6476 default:
6477 goto fail;
6478 }
6479
6480 if (trc != 0) {
6481 /* Something special. Set guest-state pointer appropriately */
6482 p = s390_emit_LGHI(p, S390_REGNO_GUEST_STATE_POINTER, trc);
6483 } else {
6484 /* Nothing special needs to be done for calls and returns. */
6485 }
6486
6487 p = s390_emit_BCR(p, S390_CC_ALWAYS, S390_REGNO_LINK_REGISTER);
6488
6489 if (cond != S390_CC_ALWAYS) {
6490 Int delta = p - ptmp;
6491
6492 delta >>= 1; /* immediate constant is #half-words */
6493 vassert(delta > 0 && delta < (1 << 16));
6494 s390_emit_BRC(ptmp, s390_cc_invert(cond), delta);
6495 }
6496
6497 return p;
6498
6499 fail:
6500 vpanic("s390_insn_branch_emit");
6501}
6502
6503
6504static UChar *
6505s390_insn_helper_call_emit(UChar *buf, const s390_insn *insn)
6506{
6507 s390_cc_t cond;
6508 ULong target;
6509 UChar *ptmp = buf;
6510
6511 cond = insn->variant.helper_call.cond;
6512 target = insn->variant.helper_call.target;
6513
6514 if (cond != S390_CC_ALWAYS) {
6515 /* So we have something like this
6516 if (cond) call X;
6517 Y: ...
6518 We convert this into
6519 if (! cond) goto Y; // BRC opcode; 4 bytes
6520 call X;
6521 Y:
6522 */
6523 /* 4 bytes (a BRC insn) to be filled in here */
6524 buf += 4;
6525 }
6526
6527 /* Load the target address into a register, that
6528 (a) is not used for passing parameters to the helper and
6529 (b) can be clobbered by the callee
6530 r1 looks like a good choice.
6531 Also, need to arrange for the return address be put into the
6532 link-register */
6533 buf = s390_emit_load_64imm(buf, 1, target);
6534
6535 /* Stash away the client's FPC register because the helper might change it. */
6536 buf = s390_emit_STFPC(buf, S390_REGNO_STACK_POINTER, S390_OFFSET_SAVED_FPC_C);
6537
6538 /* Before we can call the helper, we need to save the link register,
6539 because the BASR will overwrite it. We cannot use a register for that.
6540 (a) Volatile registers will be modified by the helper.
6541 (b) For saved registers the client code assumes that they have not
6542 changed after the function returns. So we cannot use it to store
6543 the link register.
6544 In the dispatcher, before calling the client code, we have arranged for
6545 a location on the stack for this purpose. See dispatch-s390x-linux.S. */
6546 buf = s390_emit_STG(buf, S390_REGNO_LINK_REGISTER, 0, // save LR
6547 S390_REGNO_STACK_POINTER, S390_OFFSET_SAVED_LR, 0);
6548 buf = s390_emit_BASR(buf, S390_REGNO_LINK_REGISTER, 1); // call helper
6549 buf = s390_emit_LG(buf, S390_REGNO_LINK_REGISTER, 0, // restore LR
6550 S390_REGNO_STACK_POINTER, S390_OFFSET_SAVED_LR, 0);
6551 buf = s390_emit_LFPC(buf, S390_REGNO_STACK_POINTER, // restore FPC
6552 S390_OFFSET_SAVED_FPC_C);
6553
6554 if (cond != S390_CC_ALWAYS) {
6555 Int delta = buf - ptmp;
6556
6557 delta >>= 1; /* immediate constant is #half-words */
6558 vassert(delta > 0 && delta < (1 << 16));
6559 s390_emit_BRC(ptmp, s390_cc_invert(cond), delta);
6560 }
6561
6562 return buf;
6563}
6564
6565
6566static UChar *
6567s390_insn_cond_move_emit(UChar *buf, const s390_insn *insn)
6568{
6569 HReg dst;
6570 s390_opnd_RMI src;
6571 s390_cc_t cond;
6572 UChar *p, *ptmp = 0; /* avoid compiler warnings */
6573
6574 cond = insn->variant.cond_move.cond;
6575 dst = insn->variant.cond_move.dst;
6576 src = insn->variant.cond_move.src;
6577
6578 p = buf;
6579
6580 /* Branch (if cond fails) over move instrs */
6581 if (cond != S390_CC_ALWAYS) {
6582 /* Don't know how many bytes to jump over yet.
6583 Make space for a BRC instruction (4 bytes) and fill in later. */
6584 ptmp = p; /* to be filled in here */
6585 p += 4;
6586 }
6587
6588 // cond true: move src => dst
6589
6590 switch (src.tag) {
6591 case S390_OPND_REG:
6592 p = s390_emit_LGR(p, hregNumber(dst), hregNumber(src.variant.reg));
6593 break;
6594
6595 case S390_OPND_AMODE:
6596 p = s390_emit_load_mem(p, insn->size, hregNumber(dst), src.variant.am);
6597 break;
6598
6599 case S390_OPND_IMMEDIATE: {
6600 ULong value = src.variant.imm;
6601 UInt r = hregNumber(dst);
6602
6603 switch (insn->size) {
6604 case 1:
6605 case 2:
6606 /* Load the immediate values as a 4 byte value. That does not hurt as
6607 those extra bytes will not be looked at. Fall through .... */
6608 case 4:
6609 p = s390_emit_load_32imm(p, r, value);
6610 break;
6611
6612 case 8:
6613 p = s390_emit_load_64imm(p, r, value);
6614 break;
6615 }
6616 break;
6617 }
6618
6619 default:
6620 goto fail;
6621 }
6622
6623 if (cond != S390_CC_ALWAYS) {
6624 Int delta = p - ptmp;
6625
6626 delta >>= 1; /* immediate constant is #half-words */
6627 vassert(delta > 0 && delta < (1 << 16));
6628 s390_emit_BRC(ptmp, s390_cc_invert(cond), delta);
6629 }
6630
6631 return p;
6632
6633 fail:
6634 vpanic("s390_insn_cond_move_emit");
6635}
6636
6637
6638/* Little helper function to the rounding mode in the real FPC
6639 register */
6640static UChar *
6641s390_set_fpc_rounding_mode(UChar *buf, s390_round_t rounding_mode)
6642{
6643 UChar bits;
6644
6645 /* Determine BFP rounding bits */
6646 switch (rounding_mode) {
6647 case S390_ROUND_NEAREST_EVEN: bits = 0; break;
6648 case S390_ROUND_ZERO: bits = 1; break;
6649 case S390_ROUND_POSINF: bits = 2; break;
6650 case S390_ROUND_NEGINF: bits = 3; break;
6651 default: vpanic("invalid rounding mode\n");
6652 }
6653
6654 /* Copy FPC from guest state to R0 and OR in the new rounding mode */
6655 buf = s390_emit_L(buf, R0, 0, S390_REGNO_GUEST_STATE_POINTER,
6656 OFFSET_s390x_fpc); // r0 = guest_fpc
6657
6658 buf = s390_emit_NILL(buf, R0, 0xFFFC); /* Clear out right-most 2 bits */
6659 buf = s390_emit_OILL(buf, R0, bits); /* OR in the new rounding mode */
6660 buf = s390_emit_SFPC(buf, R0, 0); /* Load FPC register from R0 */
6661
6662 return buf;
6663}
6664
6665
6666static UChar *
6667s390_insn_bfp_triop_emit(UChar *buf, const s390_insn *insn)
6668{
6669 UInt r1 = hregNumber(insn->variant.bfp_triop.dst);
6670 UInt r2 = hregNumber(insn->variant.bfp_triop.op2);
6671 UInt r3 = hregNumber(insn->variant.bfp_triop.op3);
6672 s390_round_t rounding_mode = insn->variant.bfp_triop.rounding_mode;
6673
6674 if (rounding_mode != S390_ROUND_NEAREST_EVEN) {
6675 buf = s390_set_fpc_rounding_mode(buf, rounding_mode);
6676 }
6677
6678 switch (insn->size) {
6679 case 4:
6680 switch (insn->variant.bfp_triop.tag) {
6681 case S390_BFP_MADD: buf = s390_emit_MAEBR(buf, r1, r3, r2); break;
6682 case S390_BFP_MSUB: buf = s390_emit_MSEBR(buf, r1, r3, r2); break;
6683 default: goto fail;
6684 }
6685 break;
6686
6687 case 8:
6688 switch (insn->variant.bfp_triop.tag) {
6689 case S390_BFP_MADD: buf = s390_emit_MADBR(buf, r1, r3, r2); break;
6690 case S390_BFP_MSUB: buf = s390_emit_MSDBR(buf, r1, r3, r2); break;
6691 default: goto fail;
6692 }
6693 break;
6694
6695 default: goto fail;
6696 }
6697
6698 if (rounding_mode != S390_ROUND_NEAREST_EVEN) {
6699 /* Restore FPC register from guest state */
6700 buf = s390_emit_LFPC(buf, S390_REGNO_GUEST_STATE_POINTER,
6701 OFFSET_s390x_fpc); // fpc = guest_fpc
6702 }
6703 return buf;
6704
6705 fail:
6706 vpanic("s390_insn_bfp_triop_emit");
6707}
6708
6709
6710static UChar *
6711s390_insn_bfp_binop_emit(UChar *buf, const s390_insn *insn)
6712{
6713 UInt r1 = hregNumber(insn->variant.bfp_binop.dst);
6714 UInt r2 = hregNumber(insn->variant.bfp_binop.op2);
6715 s390_round_t rounding_mode = insn->variant.bfp_binop.rounding_mode;
6716
6717 if (rounding_mode != S390_ROUND_NEAREST_EVEN) {
6718 buf = s390_set_fpc_rounding_mode(buf, rounding_mode);
6719 }
6720
6721 switch (insn->size) {
6722 case 4:
6723 switch (insn->variant.bfp_binop.tag) {
6724 case S390_BFP_ADD: buf = s390_emit_AEBR(buf, r1, r2); break;
6725 case S390_BFP_SUB: buf = s390_emit_SEBR(buf, r1, r2); break;
6726 case S390_BFP_MUL: buf = s390_emit_MEEBR(buf, r1, r2); break;
6727 case S390_BFP_DIV: buf = s390_emit_DEBR(buf, r1, r2); break;
6728 default: goto fail;
6729 }
6730 break;
6731
6732 case 8:
6733 switch (insn->variant.bfp_binop.tag) {
6734 case S390_BFP_ADD: buf = s390_emit_ADBR(buf, r1, r2); break;
6735 case S390_BFP_SUB: buf = s390_emit_SDBR(buf, r1, r2); break;
6736 case S390_BFP_MUL: buf = s390_emit_MDBR(buf, r1, r2); break;
6737 case S390_BFP_DIV: buf = s390_emit_DDBR(buf, r1, r2); break;
6738 default: goto fail;
6739 }
6740 break;
6741
6742 default: goto fail;
6743 }
6744
6745 if (rounding_mode != S390_ROUND_NEAREST_EVEN) {
6746 /* Restore FPC register from guest state */
6747 buf = s390_emit_LFPC(buf, S390_REGNO_GUEST_STATE_POINTER,
6748 OFFSET_s390x_fpc);
6749 }
6750 return buf;
6751
6752 fail:
6753 vpanic("s390_insn_bfp_binop_emit");
6754}
6755
6756
6757static UChar *
6758s390_insn_bfp_unop_emit(UChar *buf, const s390_insn *insn)
6759{
6760 UInt r1 = hregNumber(insn->variant.bfp_unop.dst);
6761 UInt r2 = hregNumber(insn->variant.bfp_unop.op);
6762 s390_round_t rounding_mode = insn->variant.bfp_unop.rounding_mode;
6763 s390_round_t m3 = rounding_mode;
6764
6765 /* The "convert to fixed" instructions have a field for the rounding
6766 mode and no FPC modification is necessary. So we handle them
6767 upfront. */
6768 switch (insn->variant.bfp_unop.tag) {
6769 case S390_BFP_F32_TO_I32: return s390_emit_CFEBR(buf, m3, r1, r2);
6770 case S390_BFP_F64_TO_I32: return s390_emit_CFDBR(buf, m3, r1, r2);
6771 case S390_BFP_F32_TO_I64: return s390_emit_CGEBR(buf, m3, r1, r2);
6772 case S390_BFP_F64_TO_I64: return s390_emit_CGDBR(buf, m3, r1, r2);
6773 default: break;
6774 }
6775
6776 /* For all other insns if a special rounding mode is requested,
6777 we need to set the FPC first and restore it later. */
6778 if (rounding_mode != S390_ROUND_NEAREST_EVEN) {
6779 buf = s390_set_fpc_rounding_mode(buf, rounding_mode);
6780 }
6781
6782 switch (insn->variant.bfp_unop.tag) {
6783 case S390_BFP_ABS:
6784 switch (insn->size) {
6785 case 4: buf = s390_emit_LPEBR(buf, r1, r2); break;
6786 case 8: buf = s390_emit_LPDBR(buf, r1, r2); break;
6787 case 16: buf = s390_emit_LPXBR(buf, r1, r2); break;
6788 default: goto fail;
6789 }
6790 break;
6791
6792 case S390_BFP_NABS:
6793 switch (insn->size) {
6794 case 4: buf = s390_emit_LNEBR(buf, r1, r2); break;
6795 case 8: buf = s390_emit_LNDBR(buf, r1, r2); break;
6796 case 16: buf = s390_emit_LNXBR(buf, r1, r2); break;
6797 default: goto fail;
6798 }
6799 break;
6800
6801 case S390_BFP_NEG:
6802 switch (insn->size) {
6803 case 4: buf = s390_emit_LCEBR(buf, r1, r2); break;
6804 case 8: buf = s390_emit_LCDBR(buf, r1, r2); break;
6805 case 16: buf = s390_emit_LCXBR(buf, r1, r2); break;
6806 default: goto fail;
6807 }
6808 break;
6809
6810 case S390_BFP_SQRT:
6811 switch (insn->size) {
6812 case 4: buf = s390_emit_SQEBR(buf, r1, r2); break;
6813 case 8: buf = s390_emit_SQDBR(buf, r1, r2); break;
6814 case 16: buf = s390_emit_SQXBR(buf, r1, r2); break;
6815 default: goto fail;
6816 }
6817 break;
6818
6819 case S390_BFP_I32_TO_F32: buf = s390_emit_CEFBR(buf, r1, r2); break;
6820 case S390_BFP_I32_TO_F64: buf = s390_emit_CDFBR(buf, r1, r2); break;
6821 case S390_BFP_I32_TO_F128: buf = s390_emit_CXFBR(buf, r1, r2); break;
6822 case S390_BFP_I64_TO_F32: buf = s390_emit_CEGBR(buf, r1, r2); break;
6823 case S390_BFP_I64_TO_F64: buf = s390_emit_CDGBR(buf, r1, r2); break;
6824 case S390_BFP_I64_TO_F128: buf = s390_emit_CXGBR(buf, r1, r2); break;
6825
6826 case S390_BFP_F32_TO_F64: buf = s390_emit_LDEBR(buf, r1, r2); break;
6827 case S390_BFP_F32_TO_F128: buf = s390_emit_LXEBR(buf, r1, r2); break;
6828 case S390_BFP_F64_TO_F32: buf = s390_emit_LEDBR(buf, r1, r2); break;
6829 case S390_BFP_F64_TO_F128: buf = s390_emit_LXDBR(buf, r1, r2); break;
6830
6831 default: goto fail;
6832 }
6833
6834 if (rounding_mode != S390_ROUND_NEAREST_EVEN) {
6835 /* Restore FPC register from guest state */
6836 buf = s390_emit_LFPC(buf, S390_REGNO_GUEST_STATE_POINTER,
6837 OFFSET_s390x_fpc); // fpc = guest_fpc
6838 }
6839 return buf;
6840
6841 fail:
6842 vpanic("s390_insn_bfp_unop_emit");
6843}
6844
6845
6846static UChar *
6847s390_insn_bfp_compare_emit(UChar *buf, const s390_insn *insn)
6848{
6849 UInt dst = hregNumber(insn->variant.bfp_compare.dst);
6850 UInt r1 = hregNumber(insn->variant.bfp_compare.op1);
6851 UInt r2 = hregNumber(insn->variant.bfp_compare.op2);
6852
6853 switch (insn->size) {
6854 case 4:
6855 buf = s390_emit_CEBR(buf, r1, r2);
6856 break;
6857
6858 case 8:
6859 buf = s390_emit_CDBR(buf, r1, r2);
6860 break;
6861
6862 default: goto fail;
6863 }
6864
6865 return s390_emit_load_cc(buf, dst); /* Load condition code into DST */
6866
6867 fail:
6868 vpanic("s390_insn_bfp_compare_emit");
6869}
6870
6871
6872static UChar *
6873s390_insn_bfp128_binop_emit(UChar *buf, const s390_insn *insn)
6874{
6875 UInt r1_hi = hregNumber(insn->variant.bfp128_binop.dst_hi);
6876 UInt r1_lo = hregNumber(insn->variant.bfp128_binop.dst_lo);
6877 UInt r2_hi = hregNumber(insn->variant.bfp128_binop.op2_hi);
6878 UInt r2_lo = hregNumber(insn->variant.bfp128_binop.op2_lo);
6879 s390_round_t rounding_mode = insn->variant.bfp_binop.rounding_mode;
6880
6881 /* Paranoia */
6882 vassert(insn->size == 16);
6883 vassert(r1_lo == r1_hi + 2);
6884 vassert(r2_lo == r2_hi + 2);
6885 vassert((r1_hi & 0x2) == 0);
6886 vassert((r2_hi & 0x2) == 0);
6887
6888 if (rounding_mode != S390_ROUND_NEAREST_EVEN) {
6889 buf = s390_set_fpc_rounding_mode(buf, rounding_mode);
6890 }
6891
6892 switch (insn->variant.bfp128_binop.tag) {
6893 case S390_BFP_ADD: buf = s390_emit_AXBR(buf, r1_hi, r2_hi); break;
6894 case S390_BFP_SUB: buf = s390_emit_SXBR(buf, r1_hi, r2_hi); break;
6895 case S390_BFP_MUL: buf = s390_emit_MXBR(buf, r1_hi, r2_hi); break;
6896 case S390_BFP_DIV: buf = s390_emit_DXBR(buf, r1_hi, r2_hi); break;
6897 default: goto fail;
6898 }
6899
6900 if (rounding_mode != S390_ROUND_NEAREST_EVEN) {
6901 /* Restore FPC register from guest state */
6902 buf = s390_emit_LFPC(buf, S390_REGNO_GUEST_STATE_POINTER,
6903 OFFSET_s390x_fpc); // fpc = guest_fpc
6904 }
6905 return buf;
6906
6907 fail:
6908 vpanic("s390_insn_bfp128_binop_emit");
6909}
6910
6911
6912static UChar *
6913s390_insn_bfp128_compare_emit(UChar *buf, const s390_insn *insn)
6914{
6915 UInt dst = hregNumber(insn->variant.bfp128_compare.dst);
6916 UInt r1_hi = hregNumber(insn->variant.bfp128_compare.op1_hi);
6917 UInt r1_lo = hregNumber(insn->variant.bfp128_compare.op1_lo);
6918 UInt r2_hi = hregNumber(insn->variant.bfp128_compare.op2_hi);
6919 UInt r2_lo = hregNumber(insn->variant.bfp128_compare.op2_lo);
6920
6921 /* Paranoia */
6922 vassert(insn->size == 16);
6923 vassert(r1_lo == r1_hi + 2);
6924 vassert(r2_lo == r2_hi + 2);
6925 vassert((r1_hi & 0x2) == 0);
6926 vassert((r2_hi & 0x2) == 0);
6927
6928 buf = s390_emit_CXBR(buf, r1_hi, r2_hi);
6929
6930 /* Load condition code into DST */
6931 return s390_emit_load_cc(buf, dst);
6932}
6933
6934
6935static UChar *
6936s390_insn_bfp128_unop_emit(UChar *buf, const s390_insn *insn)
6937{
6938 UInt r1_hi = hregNumber(insn->variant.bfp128_unop.dst_hi);
6939 UInt r1_lo = hregNumber(insn->variant.bfp128_unop.dst_lo);
6940 UInt r2_hi = hregNumber(insn->variant.bfp128_unop.op_hi);
6941 UInt r2_lo = hregNumber(insn->variant.bfp128_unop.op_lo);
6942 s390_round_t rounding_mode = insn->variant.bfp_binop.rounding_mode;
6943
6944 /* Paranoia */
6945 vassert(insn->size == 16);
6946 vassert(r1_lo == r1_hi + 2);
6947 vassert(r2_lo == r2_hi + 2);
6948 vassert((r1_hi & 0x2) == 0);
6949 vassert((r2_hi & 0x2) == 0);
6950
6951 if (rounding_mode != S390_ROUND_NEAREST_EVEN) {
6952 buf = s390_set_fpc_rounding_mode(buf, rounding_mode);
6953 }
6954
6955 switch (insn->variant.bfp128_unop.tag) {
6956 case S390_BFP_ABS: buf = s390_emit_LPXBR(buf, r1_hi, r2_hi); break;
6957 case S390_BFP_NABS: buf = s390_emit_LNXBR(buf, r1_hi, r2_hi); break;
6958 case S390_BFP_NEG: buf = s390_emit_LCXBR(buf, r1_hi, r2_hi); break;
6959 case S390_BFP_SQRT: buf = s390_emit_SQXBR(buf, r1_hi, r2_hi); break;
6960 case S390_BFP_F128_TO_F32: buf = s390_emit_LEXBR(buf, r1_hi, r2_hi); break;
6961 case S390_BFP_F128_TO_F64: buf = s390_emit_LDXBR(buf, r1_hi, r2_hi); break;
6962 default: goto fail;
6963 }
6964
6965 if (rounding_mode != S390_ROUND_NEAREST_EVEN) {
6966 /* Restore FPC register from guest state */
6967 buf = s390_emit_LFPC(buf, S390_REGNO_GUEST_STATE_POINTER,
6968 OFFSET_s390x_fpc); // fpc = guest_fpc
6969 }
6970 return buf;
6971
6972 fail:
6973 vpanic("s390_insn_bfp128_unop_emit");
6974}
6975
6976
6977/* Conversion to 128-bit BFP does not require a rounding mode */
6978static UChar *
6979s390_insn_bfp128_convert_to_emit(UChar *buf, const s390_insn *insn)
6980{
6981 UInt r1_hi = hregNumber(insn->variant.bfp128_unop.dst_hi);
6982 UInt r1_lo = hregNumber(insn->variant.bfp128_unop.dst_lo);
6983 UInt r2 = hregNumber(insn->variant.bfp128_unop.op_hi);
6984
6985 /* Paranoia */
6986 vassert(insn->size == 16);
6987 vassert(r1_lo == r1_hi + 2);
6988 vassert((r1_hi & 0x2) == 0);
6989
6990 switch (insn->variant.bfp128_unop.tag) {
6991 case S390_BFP_I32_TO_F128: buf = s390_emit_CXFBR(buf, r1_hi, r2); break;
6992 case S390_BFP_I64_TO_F128: buf = s390_emit_CXGBR(buf, r1_hi, r2); break;
6993 case S390_BFP_F32_TO_F128: buf = s390_emit_LXEBR(buf, r1_hi, r2); break;
6994 case S390_BFP_F64_TO_F128: buf = s390_emit_LXDBR(buf, r1_hi, r2); break;
6995 default: goto fail;
6996 }
6997
6998 return buf;
6999
7000 fail:
7001 vpanic("s390_insn_bfp128_convert_to_emit");
7002}
7003
7004
7005static UChar *
7006s390_insn_bfp128_convert_from_emit(UChar *buf, const s390_insn *insn)
7007{
7008 UInt r1 = hregNumber(insn->variant.bfp128_unop.dst_hi);
7009 UInt r2_hi = hregNumber(insn->variant.bfp128_unop.op_hi);
7010 UInt r2_lo = hregNumber(insn->variant.bfp128_unop.op_lo);
7011 s390_round_t rounding_mode = insn->variant.bfp_binop.rounding_mode;
7012
7013 /* Paranoia */
7014 vassert(insn->size != 16);
7015 vassert(r2_lo == r2_hi + 2);
7016 vassert((r2_hi & 0x2) == 0);
7017
7018 /* The "convert to fixed" instructions have a field for the rounding
7019 mode and no FPC modification is necessary. So we handle them
7020 upfront. */
7021 switch (insn->variant.bfp_unop.tag) {
7022 case S390_BFP_F128_TO_I32: return s390_emit_CFXBR(buf, rounding_mode,
7023 r1, r2_hi); break;
7024 case S390_BFP_F128_TO_I64: return s390_emit_CGXBR(buf, rounding_mode,
7025 r1, r2_hi); break;
7026 default: break;
7027 }
7028
7029 vpanic("s390_insn_bfp128_convert_from_emit");
7030}
7031
7032
sewardja52e37e2011-04-28 18:48:06 +00007033static UChar *
7034s390_insn_mfence_emit(UChar *buf, const s390_insn *insn)
7035{
7036 return s390_emit_BCR(buf, 0xF, 0x0);
7037}
7038
7039
sewardj2019a972011-03-07 16:04:07 +00007040Int
florianb4df7682011-07-05 02:09:01 +00007041emit_S390Instr(UChar *buf, Int nbuf, s390_insn *insn, Bool mode64,
sewardj010ac542011-05-29 09:29:18 +00007042 void *dispatch_unassisted, void *dispatch_assisted)
sewardj2019a972011-03-07 16:04:07 +00007043{
7044 UChar *end;
7045
7046 switch (insn->tag) {
7047 case S390_INSN_LOAD:
7048 end = s390_insn_load_emit(buf, insn);
7049 break;
7050
7051 case S390_INSN_STORE:
7052 end = s390_insn_store_emit(buf, insn);
7053 break;
7054
7055 case S390_INSN_MOVE:
7056 end = s390_insn_move_emit(buf, insn);
7057 break;
7058
7059 case S390_INSN_COND_MOVE:
7060 end = s390_insn_cond_move_emit(buf, insn);
7061 break;
7062
7063 case S390_INSN_LOAD_IMMEDIATE:
7064 end = s390_insn_load_immediate_emit(buf, insn);
7065 break;
7066
7067 case S390_INSN_ALU:
7068 end = s390_insn_alu_emit(buf, insn);
7069 break;
7070
7071 case S390_INSN_MUL:
7072 end = s390_insn_mul_emit(buf, insn);
7073 break;
7074
7075 case S390_INSN_DIV:
7076 end = s390_insn_div_emit(buf, insn);
7077 break;
7078
7079 case S390_INSN_DIVS:
7080 end = s390_insn_divs_emit(buf, insn);
7081 break;
7082
sewardj611b06e2011-03-24 08:57:29 +00007083 case S390_INSN_CLZ:
7084 end = s390_insn_clz_emit(buf, insn);
sewardj2019a972011-03-07 16:04:07 +00007085 break;
7086
7087 case S390_INSN_UNOP:
7088 end = s390_insn_unop_emit(buf, insn);
7089 break;
7090
7091 case S390_INSN_TEST:
7092 end = s390_insn_test_emit(buf, insn);
7093 break;
7094
7095 case S390_INSN_CC2BOOL:
7096 end = s390_insn_cc2bool_emit(buf, insn);
7097 break;
7098
7099 case S390_INSN_CAS:
7100 end = s390_insn_cas_emit(buf, insn);
7101 break;
7102
7103 case S390_INSN_COMPARE:
7104 end = s390_insn_compare_emit(buf, insn);
7105 break;
7106
7107 case S390_INSN_BRANCH:
sewardj010ac542011-05-29 09:29:18 +00007108 vassert(dispatch_unassisted == NULL);
7109 vassert(dispatch_assisted == NULL);
sewardj2019a972011-03-07 16:04:07 +00007110 end = s390_insn_branch_emit(buf, insn);
7111 break;
7112
7113 case S390_INSN_HELPER_CALL:
7114 end = s390_insn_helper_call_emit(buf, insn);
7115 break;
7116
7117 case S390_INSN_BFP_TRIOP:
7118 end = s390_insn_bfp_triop_emit(buf, insn);
7119 break;
7120
7121 case S390_INSN_BFP_BINOP:
7122 end = s390_insn_bfp_binop_emit(buf, insn);
7123 break;
7124
7125 case S390_INSN_BFP_UNOP:
7126 end = s390_insn_bfp_unop_emit(buf, insn);
7127 break;
7128
7129 case S390_INSN_BFP_COMPARE:
7130 end = s390_insn_bfp_compare_emit(buf, insn);
7131 break;
7132
7133 case S390_INSN_BFP128_BINOP:
7134 end = s390_insn_bfp128_binop_emit(buf, insn);
7135 break;
7136
7137 case S390_INSN_BFP128_COMPARE:
7138 end = s390_insn_bfp128_compare_emit(buf, insn);
7139 break;
7140
7141 case S390_INSN_BFP128_UNOP:
7142 end = s390_insn_bfp128_unop_emit(buf, insn);
7143 break;
7144
7145 case S390_INSN_BFP128_CONVERT_TO:
7146 end = s390_insn_bfp128_convert_to_emit(buf, insn);
7147 break;
7148
7149 case S390_INSN_BFP128_CONVERT_FROM:
7150 end = s390_insn_bfp128_convert_from_emit(buf, insn);
7151 break;
7152
sewardja52e37e2011-04-28 18:48:06 +00007153 case S390_INSN_MFENCE:
7154 end = s390_insn_mfence_emit(buf, insn);
7155 break;
7156
sewardj2019a972011-03-07 16:04:07 +00007157 default:
7158 vpanic("s390_insn_emit");
7159 }
7160
7161 vassert(end - buf <= nbuf);
7162
7163 return end - buf;
7164}
7165
7166
7167/*---------------------------------------------------------------*/
7168/*--- end host_s390_defs.c ---*/
7169/*---------------------------------------------------------------*/