blob: 432b985b584a95359447a53e42258a899f3fb525 [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
sewardj89ae8472013-10-18 14:12:58 +000011 Copyright IBM Corp. 2010-2013
12 Copyright (C) 2012-2013 Florian Krohm (britzel@acm.org)
sewardj2019a972011-03-07 16:04:07 +000013
14 This program is free software; you can redistribute it and/or
15 modify it under the terms of the GNU General Public License as
16 published by the Free Software Foundation; either version 2 of the
17 License, or (at your option) any later version.
18
19 This program is distributed in the hope that it will be useful, but
20 WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 General Public License for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with this program; if not, write to the Free Software
26 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
27 02110-1301, USA.
28
29 The GNU General Public License is contained in the file COPYING.
30*/
31
32/* Contributed by Florian Krohm */
33
34#include "libvex_basictypes.h"
35#include "libvex.h"
36#include "libvex_trc_values.h"
sewardj2019a972011-03-07 16:04:07 +000037#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"
florian79af5752012-09-20 01:22:10 +000043#include "s390_disasm.h"
florian428dfdd2012-03-27 03:09:49 +000044#include "guest_s390_defs.h" /* S390X_GUEST_OFFSET */
sewardj2019a972011-03-07 16:04:07 +000045#include <stdarg.h>
46
47/* KLUDGE: We need to know the hwcaps of the host when generating
48 code. But that info is not passed to emit_S390Instr. Only mode64 is
49 being passed. So, ideally, we want this passed as an argument, too.
50 Until then, we use a global variable. This variable is set as a side
florian3eb7bab2014-12-08 12:42:26 +000051 effect of LibVEX_Translate. */
florianf26994a2012-04-21 03:34:54 +000052UInt s390_host_hwcaps;
sewardj2019a972011-03-07 16:04:07 +000053
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 *);
florian1c857042012-04-15 04:11:07 +000062static UInt s390_tchain_load64_len(void);
florianb4df7682011-07-05 02:09:01 +000063
64
sewardj2019a972011-03-07 16:04:07 +000065/*------------------------------------------------------------*/
66/*--- Registers ---*/
67/*------------------------------------------------------------*/
68
69/* Decompile the given register into a static buffer and return it */
70const HChar *
71s390_hreg_as_string(HReg reg)
72{
73 static HChar buf[10];
74
75 static const HChar ireg_names[16][5] = {
76 "%r0", "%r1", "%r2", "%r3", "%r4", "%r5", "%r6", "%r7",
77 "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15"
78 };
79
80 static const HChar freg_names[16][5] = {
81 "%f0", "%f1", "%f2", "%f3", "%f4", "%f5", "%f6", "%f7",
82 "%f8", "%f9", "%f10", "%f11", "%f12", "%f13", "%f14", "%f15"
83 };
84
85 UInt r; /* hregNumber() returns an UInt */
86
87 r = hregNumber(reg);
88
89 /* Be generic for all virtual regs. */
90 if (hregIsVirtual(reg)) {
91 buf[0] = '\0';
92 switch (hregClass(reg)) {
93 case HRcInt64: vex_sprintf(buf, "%%vR%d", r); break;
94 case HRcFlt64: vex_sprintf(buf, "%%vF%d", r); break;
95 default: goto fail;
96 }
97 return buf;
98 }
99
100 /* But specific for real regs. */
101 vassert(r < 16);
102
103 switch (hregClass(reg)) {
104 case HRcInt64: return ireg_names[r];
105 case HRcFlt64: return freg_names[r];
106 default: goto fail;
107 }
108
109 fail: vpanic("s390_hreg_as_string");
110}
111
112
113/* Tell the register allocator which registers can be allocated. */
florianb4df7682011-07-05 02:09:01 +0000114static void
sewardj2019a972011-03-07 16:04:07 +0000115s390_hreg_get_allocable(Int *nregs, HReg **arr)
116{
117 UInt i;
118
119 /* Total number of allocable registers (all classes) */
120 *nregs = 16 /* GPRs */
121 - 1 /* r0 */
florian8844a632012-04-13 04:04:06 +0000122 - 1 /* r12 scratch register for translation chaining support */
sewardj2019a972011-03-07 16:04:07 +0000123 - 1 /* r13 guest state pointer */
124 - 1 /* r14 link register */
125 - 1 /* r15 stack pointer */
126 + 16 /* FPRs */
127 ;
128
129 *arr = LibVEX_Alloc(*nregs * sizeof(HReg));
130
131 i = 0;
132
133 /* GPR0 is not available because it is interpreted as 0, when used
134 as a base or index register. */
135 (*arr)[i++] = mkHReg(1, HRcInt64, False);
136 (*arr)[i++] = mkHReg(2, HRcInt64, False);
137 (*arr)[i++] = mkHReg(3, HRcInt64, False);
138 (*arr)[i++] = mkHReg(4, HRcInt64, False);
139 (*arr)[i++] = mkHReg(5, HRcInt64, False);
140 (*arr)[i++] = mkHReg(6, HRcInt64, False);
141 (*arr)[i++] = mkHReg(7, HRcInt64, False);
142 (*arr)[i++] = mkHReg(8, HRcInt64, False);
143 (*arr)[i++] = mkHReg(9, HRcInt64, False);
144 /* GPR10 and GPR11 are used for instructions that use register pairs.
145 Otherwise, they are available to the allocator */
146 (*arr)[i++] = mkHReg(10, HRcInt64, False);
147 (*arr)[i++] = mkHReg(11, HRcInt64, False);
florian8844a632012-04-13 04:04:06 +0000148 /* GPR12 is not available because it us used as a scratch register
149 in translation chaining. */
sewardj2019a972011-03-07 16:04:07 +0000150 /* GPR13 is not available because it is used as guest state pointer */
151 /* GPR14 is not available because it is used as link register */
152 /* GPR15 is not available because it is used as stack pointer */
153
154 /* Add the available real (non-virtual) FPRs */
155 (*arr)[i++] = mkHReg(0, HRcFlt64, False);
156 (*arr)[i++] = mkHReg(1, HRcFlt64, False);
157 (*arr)[i++] = mkHReg(2, HRcFlt64, False);
158 (*arr)[i++] = mkHReg(3, HRcFlt64, False);
159 (*arr)[i++] = mkHReg(4, HRcFlt64, False);
160 (*arr)[i++] = mkHReg(5, HRcFlt64, False);
161 (*arr)[i++] = mkHReg(6, HRcFlt64, False);
162 (*arr)[i++] = mkHReg(7, HRcFlt64, False);
163 (*arr)[i++] = mkHReg(8, HRcFlt64, False);
164 (*arr)[i++] = mkHReg(9, HRcFlt64, False);
165 (*arr)[i++] = mkHReg(10, HRcFlt64, False);
166 (*arr)[i++] = mkHReg(11, HRcFlt64, False);
167 (*arr)[i++] = mkHReg(12, HRcFlt64, False);
168 (*arr)[i++] = mkHReg(13, HRcFlt64, False);
169 (*arr)[i++] = mkHReg(14, HRcFlt64, False);
170 (*arr)[i++] = mkHReg(15, HRcFlt64, False);
171 /* FPR12 - FPR15 are also used as register pairs for 128-bit
172 floating point operations */
173}
174
175
176/* Return the real register that holds the guest state pointer */
177HReg
178s390_hreg_guest_state_pointer(void)
179{
180 return mkHReg(S390_REGNO_GUEST_STATE_POINTER, HRcInt64, False);
181}
182
florian8844a632012-04-13 04:04:06 +0000183
sewardj2019a972011-03-07 16:04:07 +0000184/* Is VALUE within the domain of a 20-bit signed integer. */
185static __inline__ Bool
186fits_signed_20bit(Int value)
187{
188 return ((value << 12) >> 12) == value;
189}
190
191
192/* Is VALUE within the domain of a 12-bit unsigned integer. */
193static __inline__ Bool
194fits_unsigned_12bit(Int value)
195{
196 return (value & 0xFFF) == value;
197}
198
199/*------------------------------------------------------------*/
200/*--- Addressing modes (amodes) ---*/
201/*------------------------------------------------------------*/
202
203/* Construct a b12 amode. */
204s390_amode *
205s390_amode_b12(Int d, HReg b)
206{
207 s390_amode *am = LibVEX_Alloc(sizeof(s390_amode));
208
209 vassert(fits_unsigned_12bit(d));
210
211 am->tag = S390_AMODE_B12;
212 am->d = d;
213 am->b = b;
florian3123f722013-01-24 15:55:52 +0000214 am->x = mkHReg(0, HRcInt64, False); /* hregNumber(am->x) == 0 */
sewardj2019a972011-03-07 16:04:07 +0000215
216 return am;
217}
218
219
220/* Construct a b20 amode. */
221s390_amode *
222s390_amode_b20(Int d, HReg b)
223{
224 s390_amode *am = LibVEX_Alloc(sizeof(s390_amode));
225
226 vassert(fits_signed_20bit(d));
227
228 am->tag = S390_AMODE_B20;
229 am->d = d;
230 am->b = b;
florian3123f722013-01-24 15:55:52 +0000231 am->x = mkHReg(0, HRcInt64, False); /* hregNumber(am->x) == 0 */
sewardj2019a972011-03-07 16:04:07 +0000232
233 return am;
234}
235
236
237/* Construct a bx12 amode. */
238s390_amode *
239s390_amode_bx12(Int d, HReg b, HReg x)
240{
241 s390_amode *am = LibVEX_Alloc(sizeof(s390_amode));
242
243 vassert(fits_unsigned_12bit(d));
florian3123f722013-01-24 15:55:52 +0000244 vassert(hregNumber(b) != 0);
245 vassert(hregNumber(x) != 0);
sewardj2019a972011-03-07 16:04:07 +0000246
247 am->tag = S390_AMODE_BX12;
248 am->d = d;
249 am->b = b;
250 am->x = x;
251
252 return am;
253}
254
255
256/* Construct a bx20 amode. */
257s390_amode *
258s390_amode_bx20(Int d, HReg b, HReg x)
259{
260 s390_amode *am = LibVEX_Alloc(sizeof(s390_amode));
261
262 vassert(fits_signed_20bit(d));
florian3123f722013-01-24 15:55:52 +0000263 vassert(hregNumber(b) != 0);
264 vassert(hregNumber(x) != 0);
sewardj2019a972011-03-07 16:04:07 +0000265
266 am->tag = S390_AMODE_BX20;
267 am->d = d;
268 am->b = b;
269 am->x = x;
270
271 return am;
272}
273
274
florian08d02cb2014-02-11 09:23:01 +0000275/* Construct an AMODE for accessing the guest state at OFFSET.
276 OFFSET can be at most 3 * sizeof(VexGuestS390XState) + LibVEX_N_SPILL_BYTES
277 which may be too large for a B12 addressing mode.
278 Use a B20 amode as a fallback which will be safe for any offset.
279*/
sewardj2019a972011-03-07 16:04:07 +0000280s390_amode *
281s390_amode_for_guest_state(Int offset)
282{
283 if (fits_unsigned_12bit(offset))
284 return s390_amode_b12(offset, s390_hreg_guest_state_pointer());
sewardj2019a972011-03-07 16:04:07 +0000285
florian08d02cb2014-02-11 09:23:01 +0000286 if (fits_signed_20bit(offset))
287 return s390_amode_b20(offset, s390_hreg_guest_state_pointer());
288
sewardj2019a972011-03-07 16:04:07 +0000289 vpanic("invalid guest state offset");
290}
291
292
293/* Decompile the given amode into a static buffer and return it. */
294const HChar *
295s390_amode_as_string(const s390_amode *am)
296{
297 static HChar buf[30];
298 HChar *p;
299
300 buf[0] = '\0';
301 p = buf;
302
303 switch (am->tag) {
304 case S390_AMODE_B12:
305 case S390_AMODE_B20:
306 vex_sprintf(p, "%d(%s)", am->d, s390_hreg_as_string(am->b));
307 break;
308
309 case S390_AMODE_BX12:
310 case S390_AMODE_BX20:
311 /* s390_hreg_as_string returns pointer to local buffer. Need to
312 split this into two printfs */
313 p += vex_sprintf(p, "%d(%s,", am->d, s390_hreg_as_string(am->x));
314 vex_sprintf(p, "%s)", s390_hreg_as_string(am->b));
315 break;
316
317 default:
318 vpanic("s390_amode_as_string");
319 }
320
321 return buf;
322}
323
324
325/* Helper function for s390_amode_is_sane */
326static __inline__ Bool
327is_virtual_gpr(HReg reg)
328{
329 return hregIsVirtual(reg) && hregClass(reg) == HRcInt64;
330}
331
332
333/* Sanity check for an amode */
334Bool
335s390_amode_is_sane(const s390_amode *am)
336{
337 switch (am->tag) {
338 case S390_AMODE_B12:
339 return is_virtual_gpr(am->b) && fits_unsigned_12bit(am->d);
340
341 case S390_AMODE_B20:
342 return is_virtual_gpr(am->b) && fits_signed_20bit(am->d);
343
344 case S390_AMODE_BX12:
345 return is_virtual_gpr(am->b) && is_virtual_gpr(am->x) &&
346 fits_unsigned_12bit(am->d);
347
348 case S390_AMODE_BX20:
349 return is_virtual_gpr(am->b) && is_virtual_gpr(am->x) &&
350 fits_signed_20bit(am->d);
351
352 default:
353 vpanic("s390_amode_is_sane");
354 }
355}
356
357
358/* Record the register use of an amode */
florianb4df7682011-07-05 02:09:01 +0000359static void
sewardj2019a972011-03-07 16:04:07 +0000360s390_amode_get_reg_usage(HRegUsage *u, const s390_amode *am)
361{
362 switch (am->tag) {
363 case S390_AMODE_B12:
364 case S390_AMODE_B20:
365 addHRegUse(u, HRmRead, am->b);
366 return;
367
368 case S390_AMODE_BX12:
369 case S390_AMODE_BX20:
370 addHRegUse(u, HRmRead, am->b);
371 addHRegUse(u, HRmRead, am->x);
372 return;
373
374 default:
375 vpanic("s390_amode_get_reg_usage");
376 }
377}
378
379
florianb4df7682011-07-05 02:09:01 +0000380static void
sewardj2019a972011-03-07 16:04:07 +0000381s390_amode_map_regs(HRegRemap *m, s390_amode *am)
382{
383 switch (am->tag) {
384 case S390_AMODE_B12:
385 case S390_AMODE_B20:
386 am->b = lookupHRegRemap(m, am->b);
387 return;
388
389 case S390_AMODE_BX12:
390 case S390_AMODE_BX20:
391 am->b = lookupHRegRemap(m, am->b);
392 am->x = lookupHRegRemap(m, am->x);
393 return;
394
395 default:
396 vpanic("s390_amode_map_regs");
397 }
398}
399
400
sewardj2019a972011-03-07 16:04:07 +0000401void
floriancacba8e2014-12-15 18:58:07 +0000402ppS390AMode(const s390_amode *am)
sewardj2019a972011-03-07 16:04:07 +0000403{
404 vex_printf("%s", s390_amode_as_string(am));
405}
406
407void
floriand8c64e02014-10-08 08:54:44 +0000408ppS390Instr(const s390_insn *insn, Bool mode64)
sewardj2019a972011-03-07 16:04:07 +0000409{
410 vex_printf("%s", s390_insn_as_string(insn));
411}
412
413void
414ppHRegS390(HReg reg)
415{
416 vex_printf("%s", s390_hreg_as_string(reg));
417}
418
419/*------------------------------------------------------------*/
420/*--- Helpers for register allocation ---*/
421/*------------------------------------------------------------*/
422
423/* Called once per translation. */
424void
425getAllocableRegs_S390(Int *nregs, HReg **arr, Bool mode64)
426{
427 s390_hreg_get_allocable(nregs, arr);
428}
429
430
431/* Tell the register allocator how the given instruction uses the registers
432 it refers to. */
433void
floriand8c64e02014-10-08 08:54:44 +0000434getRegUsage_S390Instr(HRegUsage *u, const s390_insn *insn, Bool mode64)
sewardj2019a972011-03-07 16:04:07 +0000435{
436 s390_insn_get_reg_usage(u, insn);
437}
438
439
440/* Map the registers of the given instruction */
441void
florianb4df7682011-07-05 02:09:01 +0000442mapRegs_S390Instr(HRegRemap *m, s390_insn *insn, Bool mode64)
sewardj2019a972011-03-07 16:04:07 +0000443{
444 s390_insn_map_regs(m, insn);
445}
446
447
448/* Figure out if the given insn represents a reg-reg move, and if so
449 assign the source and destination to *src and *dst. If in doubt say No.
450 Used by the register allocator to do move coalescing. */
451Bool
floriand8c64e02014-10-08 08:54:44 +0000452isMove_S390Instr(const s390_insn *insn, HReg *src, HReg *dst)
sewardj2019a972011-03-07 16:04:07 +0000453{
454 return s390_insn_is_reg_reg_move(insn, src, dst);
455}
456
457
458/* Generate s390 spill/reload instructions under the direction of the
459 register allocator. Note it's critical these don't write the
460 condition codes. This is like an Ist_Put */
461void
462genSpill_S390(HInstr **i1, HInstr **i2, HReg rreg, Int offsetB, Bool mode64)
463{
464 s390_amode *am;
465
466 vassert(offsetB >= 0);
sewardj2019a972011-03-07 16:04:07 +0000467 vassert(!hregIsVirtual(rreg));
468
469 *i1 = *i2 = NULL;
470
471 am = s390_amode_for_guest_state(offsetB);
472
473 switch (hregClass(rreg)) {
474 case HRcInt64:
475 case HRcFlt64:
476 *i1 = s390_insn_store(8, am, rreg);
477 return;
478
479 default:
480 ppHRegClass(hregClass(rreg));
481 vpanic("genSpill_S390: unimplemented regclass");
482 }
483}
484
485
486/* This is like an Iex_Get */
487void
488genReload_S390(HInstr **i1, HInstr **i2, HReg rreg, Int offsetB, Bool mode64)
489{
490 s390_amode *am;
491
492 vassert(offsetB >= 0);
sewardj2019a972011-03-07 16:04:07 +0000493 vassert(!hregIsVirtual(rreg));
494
495 *i1 = *i2 = NULL;
496
497 am = s390_amode_for_guest_state(offsetB);
498
499 switch (hregClass(rreg)) {
500 case HRcInt64:
501 case HRcFlt64:
502 *i1 = s390_insn_load(8, rreg, am);
503 return;
504
505 default:
506 ppHRegClass(hregClass(rreg));
507 vpanic("genReload_S390: unimplemented regclass");
508 }
509}
510
511/* Helper function for s390_insn_get_reg_usage */
512static void
513s390_opnd_RMI_get_reg_usage(HRegUsage *u, s390_opnd_RMI op)
514{
515 switch (op.tag) {
516 case S390_OPND_REG:
517 addHRegUse(u, HRmRead, op.variant.reg);
518 break;
519
520 case S390_OPND_AMODE:
521 s390_amode_get_reg_usage(u, op.variant.am);
522 break;
523
524 case S390_OPND_IMMEDIATE:
525 break;
526
527 default:
528 vpanic("s390_opnd_RMI_get_reg_usage");
529 }
530}
531
532
533/* Tell the register allocator how the given insn uses the registers */
florianb4df7682011-07-05 02:09:01 +0000534static void
sewardj2019a972011-03-07 16:04:07 +0000535s390_insn_get_reg_usage(HRegUsage *u, const s390_insn *insn)
536{
537 initHRegUsage(u);
538
539 switch (insn->tag) {
540 case S390_INSN_LOAD:
541 addHRegUse(u, HRmWrite, insn->variant.load.dst);
542 s390_amode_get_reg_usage(u, insn->variant.load.src);
543 break;
544
545 case S390_INSN_LOAD_IMMEDIATE:
546 addHRegUse(u, HRmWrite, insn->variant.load_immediate.dst);
547 break;
548
549 case S390_INSN_STORE:
550 addHRegUse(u, HRmRead, insn->variant.store.src);
551 s390_amode_get_reg_usage(u, insn->variant.store.dst);
552 break;
553
554 case S390_INSN_MOVE:
555 addHRegUse(u, HRmRead, insn->variant.move.src);
556 addHRegUse(u, HRmWrite, insn->variant.move.dst);
557 break;
558
floriancec3a8a2013-02-02 00:16:58 +0000559 case S390_INSN_MEMCPY:
560 s390_amode_get_reg_usage(u, insn->variant.memcpy.src);
561 s390_amode_get_reg_usage(u, insn->variant.memcpy.dst);
562 break;
563
sewardj2019a972011-03-07 16:04:07 +0000564 case S390_INSN_COND_MOVE:
565 s390_opnd_RMI_get_reg_usage(u, insn->variant.cond_move.src);
566 addHRegUse(u, HRmWrite, insn->variant.cond_move.dst);
567 break;
568
569 case S390_INSN_ALU:
570 addHRegUse(u, HRmWrite, insn->variant.alu.dst);
571 addHRegUse(u, HRmRead, insn->variant.alu.dst); /* op1 */
572 s390_opnd_RMI_get_reg_usage(u, insn->variant.alu.op2);
573 break;
574
florianc4aa7ed2012-12-22 15:01:04 +0000575 case S390_INSN_SMUL:
576 case S390_INSN_UMUL:
sewardj2019a972011-03-07 16:04:07 +0000577 addHRegUse(u, HRmRead, insn->variant.mul.dst_lo); /* op1 */
578 addHRegUse(u, HRmWrite, insn->variant.mul.dst_lo);
579 addHRegUse(u, HRmWrite, insn->variant.mul.dst_hi);
580 s390_opnd_RMI_get_reg_usage(u, insn->variant.mul.op2);
581 break;
582
florianc4aa7ed2012-12-22 15:01:04 +0000583 case S390_INSN_SDIV:
584 case S390_INSN_UDIV:
sewardj2019a972011-03-07 16:04:07 +0000585 addHRegUse(u, HRmRead, insn->variant.div.op1_lo);
586 addHRegUse(u, HRmRead, insn->variant.div.op1_hi);
587 addHRegUse(u, HRmWrite, insn->variant.div.op1_lo);
588 addHRegUse(u, HRmWrite, insn->variant.div.op1_hi);
589 s390_opnd_RMI_get_reg_usage(u, insn->variant.div.op2);
590 break;
591
592 case S390_INSN_DIVS:
593 addHRegUse(u, HRmRead, insn->variant.divs.op1);
594 addHRegUse(u, HRmWrite, insn->variant.divs.op1); /* quotient */
595 addHRegUse(u, HRmWrite, insn->variant.divs.rem); /* remainder */
596 s390_opnd_RMI_get_reg_usage(u, insn->variant.divs.op2);
597 break;
598
sewardj611b06e2011-03-24 08:57:29 +0000599 case S390_INSN_CLZ:
600 addHRegUse(u, HRmWrite, insn->variant.clz.num_bits);
601 addHRegUse(u, HRmWrite, insn->variant.clz.clobber);
602 s390_opnd_RMI_get_reg_usage(u, insn->variant.clz.src);
sewardj2019a972011-03-07 16:04:07 +0000603 break;
604
605 case S390_INSN_UNOP:
606 addHRegUse(u, HRmWrite, insn->variant.unop.dst);
607 s390_opnd_RMI_get_reg_usage(u, insn->variant.unop.src);
608 break;
609
610 case S390_INSN_TEST:
611 s390_opnd_RMI_get_reg_usage(u, insn->variant.test.src);
612 break;
613
614 case S390_INSN_CC2BOOL:
615 addHRegUse(u, HRmWrite, insn->variant.cc2bool.dst);
616 break;
617
618 case S390_INSN_CAS:
619 addHRegUse(u, HRmRead, insn->variant.cas.op1);
620 s390_amode_get_reg_usage(u, insn->variant.cas.op2);
621 addHRegUse(u, HRmRead, insn->variant.cas.op3);
622 addHRegUse(u, HRmWrite, insn->variant.cas.old_mem);
623 break;
624
florianc4aa7ed2012-12-22 15:01:04 +0000625 case S390_INSN_CDAS: {
626 s390_cdas *cdas = insn->variant.cdas.details;
627
628 addHRegUse(u, HRmRead, cdas->op1_high);
629 addHRegUse(u, HRmRead, cdas->op1_low);
630 s390_amode_get_reg_usage(u, cdas->op2);
631 addHRegUse(u, HRmRead, cdas->op3_high);
632 addHRegUse(u, HRmRead, cdas->op3_low);
633 addHRegUse(u, HRmWrite, cdas->old_mem_high);
634 addHRegUse(u, HRmWrite, cdas->old_mem_low);
635 addHRegUse(u, HRmWrite, cdas->scratch);
florian448cbba2012-06-06 02:26:01 +0000636 break;
florianc4aa7ed2012-12-22 15:01:04 +0000637 }
florian448cbba2012-06-06 02:26:01 +0000638
sewardj2019a972011-03-07 16:04:07 +0000639 case S390_INSN_COMPARE:
640 addHRegUse(u, HRmRead, insn->variant.compare.src1);
641 s390_opnd_RMI_get_reg_usage(u, insn->variant.compare.src2);
642 break;
643
sewardj2019a972011-03-07 16:04:07 +0000644 case S390_INSN_HELPER_CALL: {
645 UInt i;
646
647 /* Assume that all volatile registers are clobbered. ABI says,
648 volatile registers are: r0 - r5. Valgrind's register allocator
649 does not know about r0, so we can leave that out */
650 for (i = 1; i <= 5; ++i) {
651 addHRegUse(u, HRmWrite, mkHReg(i, HRcInt64, False));
652 }
653
654 /* Ditto for floating point registers. f0 - f7 are volatile */
655 for (i = 0; i <= 7; ++i) {
656 addHRegUse(u, HRmWrite, mkHReg(i, HRcFlt64, False));
657 }
658
659 /* The registers that are used for passing arguments will be read.
660 Not all of them may, but in general we need to assume that. */
sewardj74142b82013-08-08 10:28:59 +0000661 for (i = 0; i < insn->variant.helper_call.details->num_args; ++i) {
sewardj2019a972011-03-07 16:04:07 +0000662 addHRegUse(u, HRmRead, mkHReg(s390_gprno_from_arg_index(i),
663 HRcInt64, False));
664 }
665
666 /* s390_insn_helper_call_emit also reads / writes the link register
667 and stack pointer. But those registers are not visible to the
668 register allocator. So we don't need to do anything for them. */
669 break;
670 }
671
672 case S390_INSN_BFP_TRIOP:
673 addHRegUse(u, HRmWrite, insn->variant.bfp_triop.dst);
674 addHRegUse(u, HRmRead, insn->variant.bfp_triop.dst); /* first */
675 addHRegUse(u, HRmRead, insn->variant.bfp_triop.op2); /* second */
676 addHRegUse(u, HRmRead, insn->variant.bfp_triop.op3); /* third */
677 break;
678
679 case S390_INSN_BFP_BINOP:
floriancc491a62012-09-10 23:44:37 +0000680 addHRegUse(u, HRmWrite, insn->variant.bfp_binop.dst_hi);
681 addHRegUse(u, HRmRead, insn->variant.bfp_binop.dst_hi); /* left */
682 addHRegUse(u, HRmRead, insn->variant.bfp_binop.op2_hi); /* right */
683 if (insn->size == 16) {
684 addHRegUse(u, HRmWrite, insn->variant.bfp_binop.dst_lo);
685 addHRegUse(u, HRmRead, insn->variant.bfp_binop.dst_lo); /* left */
686 addHRegUse(u, HRmRead, insn->variant.bfp_binop.op2_lo); /* right */
687 }
sewardj2019a972011-03-07 16:04:07 +0000688 break;
689
690 case S390_INSN_BFP_UNOP:
floriancc491a62012-09-10 23:44:37 +0000691 addHRegUse(u, HRmWrite, insn->variant.bfp_unop.dst_hi);
692 addHRegUse(u, HRmRead, insn->variant.bfp_unop.op_hi); /* operand */
693 if (insn->size == 16) {
694 addHRegUse(u, HRmWrite, insn->variant.bfp_unop.dst_lo);
695 addHRegUse(u, HRmRead, insn->variant.bfp_unop.op_lo); /* operand */
696 }
sewardj2019a972011-03-07 16:04:07 +0000697 break;
698
699 case S390_INSN_BFP_COMPARE:
700 addHRegUse(u, HRmWrite, insn->variant.bfp_compare.dst);
floriancc491a62012-09-10 23:44:37 +0000701 addHRegUse(u, HRmRead, insn->variant.bfp_compare.op1_hi); /* left */
702 addHRegUse(u, HRmRead, insn->variant.bfp_compare.op2_hi); /* right */
703 if (insn->size == 16) {
704 addHRegUse(u, HRmRead, insn->variant.bfp_compare.op1_lo); /* left */
705 addHRegUse(u, HRmRead, insn->variant.bfp_compare.op2_lo); /* right */
706 }
sewardj2019a972011-03-07 16:04:07 +0000707 break;
708
florian9fcff4c2012-09-10 03:09:04 +0000709 case S390_INSN_BFP_CONVERT:
floriancc491a62012-09-10 23:44:37 +0000710 addHRegUse(u, HRmWrite, insn->variant.bfp_convert.dst_hi);
florian79efdc62013-02-11 00:47:35 +0000711 if (! hregIsInvalid(insn->variant.bfp_convert.dst_lo))
floriancc491a62012-09-10 23:44:37 +0000712 addHRegUse(u, HRmWrite, insn->variant.bfp_convert.dst_lo);
713 addHRegUse(u, HRmRead, insn->variant.bfp_convert.op_hi);
florian79efdc62013-02-11 00:47:35 +0000714 if (! hregIsInvalid(insn->variant.bfp_convert.op_lo))
floriancc491a62012-09-10 23:44:37 +0000715 addHRegUse(u, HRmRead, insn->variant.bfp_convert.op_lo);
sewardj2019a972011-03-07 16:04:07 +0000716 break;
717
florianc4aa7ed2012-12-22 15:01:04 +0000718 case S390_INSN_DFP_BINOP: {
719 s390_dfp_binop *dfp_binop = insn->variant.dfp_binop.details;
720
721 addHRegUse(u, HRmWrite, dfp_binop->dst_hi);
722 addHRegUse(u, HRmRead, dfp_binop->op2_hi); /* left */
723 addHRegUse(u, HRmRead, dfp_binop->op3_hi); /* right */
florian12390202012-11-10 22:34:14 +0000724 if (insn->size == 16) {
florianc4aa7ed2012-12-22 15:01:04 +0000725 addHRegUse(u, HRmWrite, dfp_binop->dst_lo);
726 addHRegUse(u, HRmRead, dfp_binop->op2_lo); /* left */
727 addHRegUse(u, HRmRead, dfp_binop->op3_lo); /* right */
florian12390202012-11-10 22:34:14 +0000728 }
729 break;
florianc4aa7ed2012-12-22 15:01:04 +0000730 }
florian12390202012-11-10 22:34:14 +0000731
floriance9e3db2012-12-27 20:14:03 +0000732 case S390_INSN_DFP_UNOP:
733 addHRegUse(u, HRmWrite, insn->variant.dfp_unop.dst_hi);
734 addHRegUse(u, HRmRead, insn->variant.dfp_unop.op_hi); /* operand */
735 if (insn->size == 16) {
736 addHRegUse(u, HRmWrite, insn->variant.dfp_unop.dst_lo);
737 addHRegUse(u, HRmRead, insn->variant.dfp_unop.op_lo); /* operand */
738 }
739 break;
740
florian1b901d42013-01-01 22:19:24 +0000741 case S390_INSN_DFP_INTOP:
742 addHRegUse(u, HRmWrite, insn->variant.dfp_intop.dst_hi);
743 addHRegUse(u, HRmRead, insn->variant.dfp_intop.op2);
744 addHRegUse(u, HRmRead, insn->variant.dfp_intop.op3_hi);
745 if (insn->size == 16) {
746 addHRegUse(u, HRmWrite, insn->variant.dfp_intop.dst_lo);
747 addHRegUse(u, HRmRead, insn->variant.dfp_intop.op3_lo);
748 }
749 break;
750
floriane38f6412012-12-21 17:32:12 +0000751 case S390_INSN_DFP_COMPARE:
752 addHRegUse(u, HRmWrite, insn->variant.dfp_compare.dst);
753 addHRegUse(u, HRmRead, insn->variant.dfp_compare.op1_hi); /* left */
754 addHRegUse(u, HRmRead, insn->variant.dfp_compare.op2_hi); /* right */
755 if (insn->size == 16) {
756 addHRegUse(u, HRmRead, insn->variant.dfp_compare.op1_lo); /* left */
757 addHRegUse(u, HRmRead, insn->variant.dfp_compare.op2_lo); /* right */
758 }
759 break;
760
761 case S390_INSN_DFP_CONVERT:
762 addHRegUse(u, HRmWrite, insn->variant.dfp_convert.dst_hi);
florian79efdc62013-02-11 00:47:35 +0000763 if (! hregIsInvalid(insn->variant.dfp_convert.dst_lo))
floriane38f6412012-12-21 17:32:12 +0000764 addHRegUse(u, HRmWrite, insn->variant.dfp_convert.dst_lo);
765 addHRegUse(u, HRmRead, insn->variant.dfp_convert.op_hi); /* operand */
florian79efdc62013-02-11 00:47:35 +0000766 if (! hregIsInvalid(insn->variant.dfp_convert.op_lo))
floriane38f6412012-12-21 17:32:12 +0000767 addHRegUse(u, HRmRead, insn->variant.dfp_convert.op_lo); /* operand */
768 break;
769
florian5c539732013-02-14 14:27:12 +0000770 case S390_INSN_DFP_REROUND:
771 addHRegUse(u, HRmWrite, insn->variant.dfp_reround.dst_hi);
772 addHRegUse(u, HRmRead, insn->variant.dfp_reround.op2); /* left */
773 addHRegUse(u, HRmRead, insn->variant.dfp_reround.op3_hi); /* right */
774 if (insn->size == 16) {
775 addHRegUse(u, HRmWrite, insn->variant.dfp_reround.dst_lo);
776 addHRegUse(u, HRmRead, insn->variant.dfp_reround.op3_lo); /* right */
777 }
778 break;
779
florian78d5ef72013-05-11 15:02:58 +0000780 case S390_INSN_FP_CONVERT: {
781 s390_fp_convert *fp_convert = insn->variant.fp_convert.details;
782
783 addHRegUse(u, HRmWrite, fp_convert->dst_hi);
784 if (! hregIsInvalid(fp_convert->dst_lo))
785 addHRegUse(u, HRmWrite, fp_convert->dst_lo);
786 addHRegUse(u, HRmRead, fp_convert->op_hi);
787 if (! hregIsInvalid(fp_convert->op_lo))
788 addHRegUse(u, HRmRead, fp_convert->op_lo);
789 addHRegUse(u, HRmWrite, fp_convert->r1);
790 break;
791 }
792
florianb93348d2012-12-27 00:59:43 +0000793 case S390_INSN_MIMM:
794 s390_amode_get_reg_usage(u, insn->variant.mimm.dst);
florian09bbba82012-12-11 04:09:43 +0000795 break;
796
florianf85fe3e2012-12-22 02:28:25 +0000797 case S390_INSN_MADD:
798 s390_amode_get_reg_usage(u, insn->variant.madd.dst);
799 break;
800
sewardja52e37e2011-04-28 18:48:06 +0000801 case S390_INSN_MFENCE:
802 break;
803
florian125e20d2012-10-07 15:42:37 +0000804 case S390_INSN_SET_FPC_BFPRM:
805 addHRegUse(u, HRmRead, insn->variant.set_fpc_bfprm.mode);
florian2c74d242012-09-12 19:38:42 +0000806 break;
807
florianc8e4f562012-10-27 16:19:31 +0000808 case S390_INSN_SET_FPC_DFPRM:
809 addHRegUse(u, HRmRead, insn->variant.set_fpc_dfprm.mode);
810 break;
811
florian8844a632012-04-13 04:04:06 +0000812 case S390_INSN_EVCHECK:
813 s390_amode_get_reg_usage(u, insn->variant.evcheck.counter);
814 s390_amode_get_reg_usage(u, insn->variant.evcheck.fail_addr);
815 break;
816
817 case S390_INSN_PROFINC:
818 /* Does not use any register visible to the register allocator */
819 break;
820
821 case S390_INSN_XDIRECT:
822 s390_amode_get_reg_usage(u, insn->variant.xdirect.guest_IA);
823 break;
824
825 case S390_INSN_XINDIR:
826 addHRegUse(u, HRmRead, insn->variant.xindir.dst);
827 s390_amode_get_reg_usage(u, insn->variant.xindir.guest_IA);
828 break;
829
830 case S390_INSN_XASSISTED:
831 addHRegUse(u, HRmRead, insn->variant.xassisted.dst);
832 s390_amode_get_reg_usage(u, insn->variant.xassisted.guest_IA);
833 break;
834
sewardj2019a972011-03-07 16:04:07 +0000835 default:
836 vpanic("s390_insn_get_reg_usage");
837 }
838}
839
840
841/* Helper function for s390_insn_map_regs */
842static void
843s390_opnd_RMI_map_regs(HRegRemap *m, s390_opnd_RMI *op)
844{
845 switch (op->tag) {
846 case S390_OPND_REG:
847 op->variant.reg = lookupHRegRemap(m, op->variant.reg);
848 break;
849
850 case S390_OPND_IMMEDIATE:
851 break;
852
853 case S390_OPND_AMODE:
854 s390_amode_map_regs(m, op->variant.am);
855 break;
856
857 default:
858 vpanic("s390_opnd_RMI_map_regs");
859 }
860}
861
862
florianb4df7682011-07-05 02:09:01 +0000863static void
sewardj2019a972011-03-07 16:04:07 +0000864s390_insn_map_regs(HRegRemap *m, s390_insn *insn)
865{
866 switch (insn->tag) {
867 case S390_INSN_LOAD:
868 insn->variant.load.dst = lookupHRegRemap(m, insn->variant.load.dst);
869 s390_amode_map_regs(m, insn->variant.load.src);
870 break;
871
872 case S390_INSN_STORE:
873 s390_amode_map_regs(m, insn->variant.store.dst);
874 insn->variant.store.src = lookupHRegRemap(m, insn->variant.store.src);
875 break;
876
877 case S390_INSN_MOVE:
878 insn->variant.move.dst = lookupHRegRemap(m, insn->variant.move.dst);
879 insn->variant.move.src = lookupHRegRemap(m, insn->variant.move.src);
880 break;
881
floriancec3a8a2013-02-02 00:16:58 +0000882 case S390_INSN_MEMCPY:
883 s390_amode_map_regs(m, insn->variant.memcpy.dst);
884 s390_amode_map_regs(m, insn->variant.memcpy.src);
885 break;
886
sewardj2019a972011-03-07 16:04:07 +0000887 case S390_INSN_COND_MOVE:
888 insn->variant.cond_move.dst = lookupHRegRemap(m, insn->variant.cond_move.dst);
889 s390_opnd_RMI_map_regs(m, &insn->variant.cond_move.src);
890 break;
891
892 case S390_INSN_LOAD_IMMEDIATE:
893 insn->variant.load_immediate.dst =
894 lookupHRegRemap(m, insn->variant.load_immediate.dst);
895 break;
896
897 case S390_INSN_ALU:
898 insn->variant.alu.dst = lookupHRegRemap(m, insn->variant.alu.dst);
899 s390_opnd_RMI_map_regs(m, &insn->variant.alu.op2);
900 break;
901
florianc4aa7ed2012-12-22 15:01:04 +0000902 case S390_INSN_SMUL:
903 case S390_INSN_UMUL:
sewardj2019a972011-03-07 16:04:07 +0000904 insn->variant.mul.dst_hi = lookupHRegRemap(m, insn->variant.mul.dst_hi);
905 insn->variant.mul.dst_lo = lookupHRegRemap(m, insn->variant.mul.dst_lo);
906 s390_opnd_RMI_map_regs(m, &insn->variant.mul.op2);
907 break;
908
florianc4aa7ed2012-12-22 15:01:04 +0000909 case S390_INSN_SDIV:
910 case S390_INSN_UDIV:
sewardj2019a972011-03-07 16:04:07 +0000911 insn->variant.div.op1_hi = lookupHRegRemap(m, insn->variant.div.op1_hi);
912 insn->variant.div.op1_lo = lookupHRegRemap(m, insn->variant.div.op1_lo);
913 s390_opnd_RMI_map_regs(m, &insn->variant.div.op2);
914 break;
915
916 case S390_INSN_DIVS:
917 insn->variant.divs.op1 = lookupHRegRemap(m, insn->variant.divs.op1);
918 insn->variant.divs.rem = lookupHRegRemap(m, insn->variant.divs.rem);
919 s390_opnd_RMI_map_regs(m, &insn->variant.divs.op2);
920 break;
921
sewardj611b06e2011-03-24 08:57:29 +0000922 case S390_INSN_CLZ:
923 insn->variant.clz.num_bits = lookupHRegRemap(m, insn->variant.clz.num_bits);
924 insn->variant.clz.clobber = lookupHRegRemap(m, insn->variant.clz.clobber);
925 s390_opnd_RMI_map_regs(m, &insn->variant.clz.src);
sewardj2019a972011-03-07 16:04:07 +0000926 break;
927
928 case S390_INSN_UNOP:
929 insn->variant.unop.dst = lookupHRegRemap(m, insn->variant.unop.dst);
930 s390_opnd_RMI_map_regs(m, &insn->variant.unop.src);
931 break;
932
933 case S390_INSN_TEST:
934 s390_opnd_RMI_map_regs(m, &insn->variant.test.src);
935 break;
936
937 case S390_INSN_CC2BOOL:
938 insn->variant.cc2bool.dst = lookupHRegRemap(m, insn->variant.cc2bool.dst);
939 break;
940
941 case S390_INSN_CAS:
942 insn->variant.cas.op1 = lookupHRegRemap(m, insn->variant.cas.op1);
943 s390_amode_map_regs(m, insn->variant.cas.op2);
944 insn->variant.cas.op3 = lookupHRegRemap(m, insn->variant.cas.op3);
945 insn->variant.cas.old_mem = lookupHRegRemap(m, insn->variant.cas.old_mem);
946 break;
947
florianc4aa7ed2012-12-22 15:01:04 +0000948 case S390_INSN_CDAS: {
949 s390_cdas *cdas = insn->variant.cdas.details;
950
951 cdas->op1_high = lookupHRegRemap(m, cdas->op1_high);
952 cdas->op1_low = lookupHRegRemap(m, cdas->op1_low);
953 s390_amode_map_regs(m, cdas->op2);
954 cdas->op3_high = lookupHRegRemap(m, cdas->op3_high);
955 cdas->op3_low = lookupHRegRemap(m, cdas->op3_low);
956 cdas->old_mem_high = lookupHRegRemap(m, cdas->old_mem_high);
957 cdas->old_mem_low = lookupHRegRemap(m, cdas->old_mem_low);
958 cdas->scratch = lookupHRegRemap(m, cdas->scratch);
florian448cbba2012-06-06 02:26:01 +0000959 break;
florianc4aa7ed2012-12-22 15:01:04 +0000960 }
florian448cbba2012-06-06 02:26:01 +0000961
sewardj2019a972011-03-07 16:04:07 +0000962 case S390_INSN_COMPARE:
963 insn->variant.compare.src1 = lookupHRegRemap(m, insn->variant.compare.src1);
964 s390_opnd_RMI_map_regs(m, &insn->variant.compare.src2);
965 break;
966
sewardj2019a972011-03-07 16:04:07 +0000967 case S390_INSN_HELPER_CALL:
968 /* s390_insn_helper_call_emit also reads / writes the link register
969 and stack pointer. But those registers are not visible to the
970 register allocator. So we don't need to do anything for them.
971 As for the arguments of the helper call -- they will be loaded into
972 non-virtual registers. Again, we don't need to do anything for those
973 here. */
974 break;
975
976 case S390_INSN_BFP_TRIOP:
floriancc491a62012-09-10 23:44:37 +0000977 insn->variant.bfp_triop.dst =
978 lookupHRegRemap(m, insn->variant.bfp_triop.dst);
979 insn->variant.bfp_triop.op2 =
980 lookupHRegRemap(m, insn->variant.bfp_triop.op2);
981 insn->variant.bfp_triop.op3 =
982 lookupHRegRemap(m, insn->variant.bfp_triop.op3);
sewardj2019a972011-03-07 16:04:07 +0000983 break;
984
985 case S390_INSN_BFP_BINOP:
floriancc491a62012-09-10 23:44:37 +0000986 insn->variant.bfp_binop.dst_hi =
987 lookupHRegRemap(m, insn->variant.bfp_binop.dst_hi);
988 insn->variant.bfp_binop.op2_hi =
989 lookupHRegRemap(m, insn->variant.bfp_binop.op2_hi);
990 if (insn->size == 16) {
floriana1659202012-09-19 16:01:21 +0000991 insn->variant.bfp_binop.dst_lo =
floriancc491a62012-09-10 23:44:37 +0000992 lookupHRegRemap(m, insn->variant.bfp_binop.dst_lo);
floriana1659202012-09-19 16:01:21 +0000993 insn->variant.bfp_binop.op2_lo =
floriancc491a62012-09-10 23:44:37 +0000994 lookupHRegRemap(m, insn->variant.bfp_binop.op2_lo);
995 }
sewardj2019a972011-03-07 16:04:07 +0000996 break;
997
998 case S390_INSN_BFP_UNOP:
floriancc491a62012-09-10 23:44:37 +0000999 insn->variant.bfp_unop.dst_hi =
1000 lookupHRegRemap(m, insn->variant.bfp_unop.dst_hi);
1001 insn->variant.bfp_unop.op_hi =
1002 lookupHRegRemap(m, insn->variant.bfp_unop.op_hi);
1003 if (insn->size == 16) {
1004 insn->variant.bfp_unop.dst_lo =
1005 lookupHRegRemap(m, insn->variant.bfp_unop.dst_lo);
1006 insn->variant.bfp_unop.op_lo =
1007 lookupHRegRemap(m, insn->variant.bfp_unop.op_lo);
1008 }
sewardj2019a972011-03-07 16:04:07 +00001009 break;
1010
1011 case S390_INSN_BFP_COMPARE:
floriancc491a62012-09-10 23:44:37 +00001012 insn->variant.bfp_compare.dst =
1013 lookupHRegRemap(m, insn->variant.bfp_compare.dst);
1014 insn->variant.bfp_compare.op1_hi =
1015 lookupHRegRemap(m, insn->variant.bfp_compare.op1_hi);
1016 insn->variant.bfp_compare.op2_hi =
1017 lookupHRegRemap(m, insn->variant.bfp_compare.op2_hi);
1018 if (insn->size == 16) {
1019 insn->variant.bfp_compare.op1_lo =
1020 lookupHRegRemap(m, insn->variant.bfp_compare.op1_lo);
1021 insn->variant.bfp_compare.op2_lo =
1022 lookupHRegRemap(m, insn->variant.bfp_compare.op2_lo);
1023 }
sewardj2019a972011-03-07 16:04:07 +00001024 break;
1025
florian9fcff4c2012-09-10 03:09:04 +00001026 case S390_INSN_BFP_CONVERT:
floriancc491a62012-09-10 23:44:37 +00001027 insn->variant.bfp_convert.dst_hi =
1028 lookupHRegRemap(m, insn->variant.bfp_convert.dst_hi);
florian79efdc62013-02-11 00:47:35 +00001029 if (! hregIsInvalid(insn->variant.bfp_convert.dst_lo))
floriancc491a62012-09-10 23:44:37 +00001030 insn->variant.bfp_convert.dst_lo =
1031 lookupHRegRemap(m, insn->variant.bfp_convert.dst_lo);
1032 insn->variant.bfp_convert.op_hi =
1033 lookupHRegRemap(m, insn->variant.bfp_convert.op_hi);
florian79efdc62013-02-11 00:47:35 +00001034 if (! hregIsInvalid(insn->variant.bfp_convert.op_lo))
floriancc491a62012-09-10 23:44:37 +00001035 insn->variant.bfp_convert.op_lo =
1036 lookupHRegRemap(m, insn->variant.bfp_convert.op_lo);
sewardj2019a972011-03-07 16:04:07 +00001037 break;
1038
florianc4aa7ed2012-12-22 15:01:04 +00001039 case S390_INSN_DFP_BINOP: {
1040 s390_dfp_binop *dfp_binop = insn->variant.dfp_binop.details;
1041
1042 dfp_binop->dst_hi = lookupHRegRemap(m, dfp_binop->dst_hi);
1043 dfp_binop->op2_hi = lookupHRegRemap(m, dfp_binop->op2_hi);
1044 dfp_binop->op3_hi = lookupHRegRemap(m, dfp_binop->op3_hi);
florian12390202012-11-10 22:34:14 +00001045 if (insn->size == 16) {
florianc4aa7ed2012-12-22 15:01:04 +00001046 dfp_binop->dst_lo = lookupHRegRemap(m, dfp_binop->dst_lo);
1047 dfp_binop->op2_lo = lookupHRegRemap(m, dfp_binop->op2_lo);
1048 dfp_binop->op3_lo = lookupHRegRemap(m, dfp_binop->op3_lo);
florian12390202012-11-10 22:34:14 +00001049 }
1050 break;
florianc4aa7ed2012-12-22 15:01:04 +00001051 }
florian12390202012-11-10 22:34:14 +00001052
floriance9e3db2012-12-27 20:14:03 +00001053 case S390_INSN_DFP_UNOP:
1054 insn->variant.dfp_unop.dst_hi =
1055 lookupHRegRemap(m, insn->variant.dfp_unop.dst_hi);
1056 insn->variant.dfp_unop.op_hi =
1057 lookupHRegRemap(m, insn->variant.dfp_unop.op_hi);
1058 if (insn->size == 16) {
1059 insn->variant.dfp_unop.dst_lo =
1060 lookupHRegRemap(m, insn->variant.dfp_unop.dst_lo);
1061 insn->variant.dfp_unop.op_lo =
1062 lookupHRegRemap(m, insn->variant.dfp_unop.op_lo);
1063 }
1064 break;
1065
florian1b901d42013-01-01 22:19:24 +00001066 case S390_INSN_DFP_INTOP:
1067 insn->variant.dfp_intop.dst_hi =
1068 lookupHRegRemap(m, insn->variant.dfp_intop.dst_hi);
1069 insn->variant.dfp_intop.op2 =
1070 lookupHRegRemap(m, insn->variant.dfp_intop.op2);
1071 insn->variant.dfp_intop.op3_hi =
1072 lookupHRegRemap(m, insn->variant.dfp_intop.op3_hi);
1073 if (insn->size == 16) {
1074 insn->variant.dfp_intop.dst_lo =
1075 lookupHRegRemap(m, insn->variant.dfp_intop.dst_lo);
1076 insn->variant.dfp_intop.op3_lo =
1077 lookupHRegRemap(m, insn->variant.dfp_intop.op3_lo);
1078 }
1079 break;
1080
floriane38f6412012-12-21 17:32:12 +00001081 case S390_INSN_DFP_COMPARE:
1082 insn->variant.dfp_compare.dst =
1083 lookupHRegRemap(m, insn->variant.dfp_compare.dst);
1084 insn->variant.dfp_compare.op1_hi =
1085 lookupHRegRemap(m, insn->variant.dfp_compare.op1_hi);
1086 insn->variant.dfp_compare.op2_hi =
1087 lookupHRegRemap(m, insn->variant.dfp_compare.op2_hi);
1088 if (insn->size == 16) {
1089 insn->variant.dfp_compare.op1_lo =
1090 lookupHRegRemap(m, insn->variant.dfp_compare.op1_lo);
1091 insn->variant.dfp_compare.op2_lo =
1092 lookupHRegRemap(m, insn->variant.dfp_compare.op2_lo);
1093 }
1094 break;
1095
1096 case S390_INSN_DFP_CONVERT:
1097 insn->variant.dfp_convert.dst_hi =
1098 lookupHRegRemap(m, insn->variant.dfp_convert.dst_hi);
florian79efdc62013-02-11 00:47:35 +00001099 if (! hregIsInvalid(insn->variant.dfp_convert.dst_lo))
floriane38f6412012-12-21 17:32:12 +00001100 insn->variant.dfp_convert.dst_lo =
1101 lookupHRegRemap(m, insn->variant.dfp_convert.dst_lo);
1102 insn->variant.dfp_convert.op_hi =
1103 lookupHRegRemap(m, insn->variant.dfp_convert.op_hi);
florian79efdc62013-02-11 00:47:35 +00001104 if (! hregIsInvalid(insn->variant.dfp_convert.op_lo))
floriane38f6412012-12-21 17:32:12 +00001105 insn->variant.dfp_convert.op_lo =
1106 lookupHRegRemap(m, insn->variant.dfp_convert.op_lo);
1107 break;
1108
florian5c539732013-02-14 14:27:12 +00001109 case S390_INSN_DFP_REROUND:
1110 insn->variant.dfp_reround.dst_hi =
1111 lookupHRegRemap(m, insn->variant.dfp_reround.dst_hi);
1112 insn->variant.dfp_reround.op2 =
1113 lookupHRegRemap(m, insn->variant.dfp_reround.op2);
1114 insn->variant.dfp_reround.op3_hi =
1115 lookupHRegRemap(m, insn->variant.dfp_reround.op3_hi);
1116 if (insn->size == 16) {
1117 insn->variant.dfp_reround.dst_lo =
1118 lookupHRegRemap(m, insn->variant.dfp_reround.dst_lo);
1119 insn->variant.dfp_reround.op3_lo =
1120 lookupHRegRemap(m, insn->variant.dfp_reround.op3_lo);
1121 }
1122 break;
1123
florian78d5ef72013-05-11 15:02:58 +00001124 case S390_INSN_FP_CONVERT: {
1125 s390_fp_convert *fp_convert = insn->variant.fp_convert.details;
1126
1127 fp_convert->dst_hi = lookupHRegRemap(m, fp_convert->dst_hi);
1128 if (! hregIsInvalid(fp_convert->dst_lo))
1129 fp_convert->dst_lo = lookupHRegRemap(m, fp_convert->dst_lo);
1130 fp_convert->op_hi = lookupHRegRemap(m, fp_convert->op_hi);
1131 if (! hregIsInvalid(fp_convert->op_lo))
1132 fp_convert->op_lo = lookupHRegRemap(m, fp_convert->op_lo);
1133 fp_convert->r1 = lookupHRegRemap(m, fp_convert->r1);
1134 break;
1135 }
1136
florianb93348d2012-12-27 00:59:43 +00001137 case S390_INSN_MIMM:
1138 s390_amode_map_regs(m, insn->variant.mimm.dst);
florian09bbba82012-12-11 04:09:43 +00001139 break;
1140
florianf85fe3e2012-12-22 02:28:25 +00001141 case S390_INSN_MADD:
1142 s390_amode_map_regs(m, insn->variant.madd.dst);
1143 break;
1144
sewardja52e37e2011-04-28 18:48:06 +00001145 case S390_INSN_MFENCE:
1146 break;
1147
florian125e20d2012-10-07 15:42:37 +00001148 case S390_INSN_SET_FPC_BFPRM:
1149 insn->variant.set_fpc_bfprm.mode =
1150 lookupHRegRemap(m, insn->variant.set_fpc_bfprm.mode);
florian2c74d242012-09-12 19:38:42 +00001151 break;
1152
florianc8e4f562012-10-27 16:19:31 +00001153 case S390_INSN_SET_FPC_DFPRM:
1154 insn->variant.set_fpc_dfprm.mode =
1155 lookupHRegRemap(m, insn->variant.set_fpc_dfprm.mode);
1156 break;
1157
florian8844a632012-04-13 04:04:06 +00001158 case S390_INSN_EVCHECK:
1159 s390_amode_map_regs(m, insn->variant.evcheck.counter);
1160 s390_amode_map_regs(m, insn->variant.evcheck.fail_addr);
1161 break;
1162
1163 case S390_INSN_PROFINC:
1164 /* Does not use any register visible to the register allocator */
1165 break;
1166
1167 case S390_INSN_XDIRECT:
1168 s390_amode_map_regs(m, insn->variant.xdirect.guest_IA);
1169 break;
1170
1171 case S390_INSN_XINDIR:
1172 s390_amode_map_regs(m, insn->variant.xindir.guest_IA);
1173 insn->variant.xindir.dst =
1174 lookupHRegRemap(m, insn->variant.xindir.dst);
1175 break;
1176
1177 case S390_INSN_XASSISTED:
1178 s390_amode_map_regs(m, insn->variant.xassisted.guest_IA);
1179 insn->variant.xassisted.dst =
1180 lookupHRegRemap(m, insn->variant.xassisted.dst);
1181 break;
1182
sewardj2019a972011-03-07 16:04:07 +00001183 default:
1184 vpanic("s390_insn_map_regs");
1185 }
1186}
1187
1188
1189/* Return True, if INSN is a move between two registers of the same class.
1190 In that case assign the source and destination registers to SRC and DST,
1191 respectively. */
florianb4df7682011-07-05 02:09:01 +00001192static Bool
sewardj2019a972011-03-07 16:04:07 +00001193s390_insn_is_reg_reg_move(const s390_insn *insn, HReg *src, HReg *dst)
1194{
1195 if (insn->tag == S390_INSN_MOVE &&
1196 hregClass(insn->variant.move.src) == hregClass(insn->variant.move.dst)) {
1197 *src = insn->variant.move.src;
1198 *dst = insn->variant.move.dst;
1199 return True;
1200 }
1201
1202 return False;
1203}
1204
1205
sewardj2019a972011-03-07 16:04:07 +00001206/*------------------------------------------------------------*/
1207/*--- Functions to emit a sequence of bytes ---*/
1208/*------------------------------------------------------------*/
1209
sewardj2019a972011-03-07 16:04:07 +00001210static __inline__ UChar *
1211emit_2bytes(UChar *p, ULong val)
1212{
1213 return (UChar *)__builtin_memcpy(p, ((UChar *)&val) + 6, 2) + 2;
1214}
1215
1216
1217static __inline__ UChar *
1218emit_4bytes(UChar *p, ULong val)
1219{
1220 return (UChar *)__builtin_memcpy(p, ((UChar *)&val) + 4, 4) + 4;
1221}
1222
1223
1224static __inline__ UChar *
1225emit_6bytes(UChar *p, ULong val)
1226{
1227 return (UChar *)__builtin_memcpy(p, ((UChar *)&val) + 2, 6) + 6;
1228}
1229
1230
1231/*------------------------------------------------------------*/
1232/*--- Functions to emit various instruction formats ---*/
1233/*------------------------------------------------------------*/
1234
sewardj2019a972011-03-07 16:04:07 +00001235static UChar *
1236emit_RI(UChar *p, UInt op, UChar r1, UShort i2)
1237{
1238 ULong the_insn = op;
1239
1240 the_insn |= ((ULong)r1) << 20;
1241 the_insn |= ((ULong)i2) << 0;
1242
1243 return emit_4bytes(p, the_insn);
1244}
1245
1246
1247static UChar *
1248emit_RIL(UChar *p, ULong op, UChar r1, UInt i2)
1249{
1250 ULong the_insn = op;
1251
1252 the_insn |= ((ULong)r1) << 36;
1253 the_insn |= ((ULong)i2) << 0;
1254
1255 return emit_6bytes(p, the_insn);
1256}
1257
1258
1259static UChar *
1260emit_RR(UChar *p, UInt op, UChar r1, UChar r2)
1261{
1262 ULong the_insn = op;
1263
1264 the_insn |= ((ULong)r1) << 4;
1265 the_insn |= ((ULong)r2) << 0;
1266
1267 return emit_2bytes(p, the_insn);
1268}
1269
1270
1271static UChar *
1272emit_RRE(UChar *p, UInt op, UChar r1, UChar r2)
1273{
1274 ULong the_insn = op;
1275
1276 the_insn |= ((ULong)r1) << 4;
1277 the_insn |= ((ULong)r2) << 0;
1278
1279 return emit_4bytes(p, the_insn);
1280}
1281
1282
1283static UChar *
1284emit_RRF(UChar *p, UInt op, UChar r1, UChar r3, UChar r2)
1285{
1286 ULong the_insn = op;
1287
1288 the_insn |= ((ULong)r1) << 12;
1289 the_insn |= ((ULong)r3) << 4;
1290 the_insn |= ((ULong)r2) << 0;
1291
1292 return emit_4bytes(p, the_insn);
1293}
1294
1295
1296static UChar *
florian1c8f7ff2012-09-01 00:12:11 +00001297emit_RRF2(UChar *p, UInt op, UChar m3, UChar m4, UChar r1, UChar r2)
1298{
1299 ULong the_insn = op;
1300
1301 the_insn |= ((ULong)m3) << 12;
1302 the_insn |= ((ULong)m4) << 8;
1303 the_insn |= ((ULong)r1) << 4;
1304 the_insn |= ((ULong)r2) << 0;
1305
1306 return emit_4bytes(p, the_insn);
1307}
1308
1309
1310static UChar *
sewardj2019a972011-03-07 16:04:07 +00001311emit_RRF3(UChar *p, UInt op, UChar r3, UChar r1, UChar r2)
1312{
1313 ULong the_insn = op;
1314
1315 the_insn |= ((ULong)r3) << 12;
1316 the_insn |= ((ULong)r1) << 4;
1317 the_insn |= ((ULong)r2) << 0;
1318
1319 return emit_4bytes(p, the_insn);
1320}
1321
1322
1323static UChar *
florian12390202012-11-10 22:34:14 +00001324emit_RRF4(UChar *p, UInt op, UChar r3, UChar m4, UChar r1, UChar r2)
1325{
1326 ULong the_insn = op;
1327
1328 the_insn |= ((ULong)r3) << 12;
1329 the_insn |= ((ULong)m4) << 8;
1330 the_insn |= ((ULong)r1) << 4;
1331 the_insn |= ((ULong)r2) << 0;
1332
1333 return emit_4bytes(p, the_insn);
1334}
1335
1336
1337static UChar *
floriane38f6412012-12-21 17:32:12 +00001338emit_RRF5(UChar *p, UInt op, UChar m4, UChar r1, UChar r2)
1339{
1340 ULong the_insn = op;
1341
1342 the_insn |= ((ULong)m4) << 8;
1343 the_insn |= ((ULong)r1) << 4;
1344 the_insn |= ((ULong)r2) << 0;
1345
1346 return emit_4bytes(p, the_insn);
1347}
1348
1349
1350static UChar *
sewardj2019a972011-03-07 16:04:07 +00001351emit_RS(UChar *p, UInt op, UChar r1, UChar r3, UChar b2, UShort d2)
1352{
1353 ULong the_insn = op;
1354
1355 the_insn |= ((ULong)r1) << 20;
1356 the_insn |= ((ULong)r3) << 16;
1357 the_insn |= ((ULong)b2) << 12;
1358 the_insn |= ((ULong)d2) << 0;
1359
1360 return emit_4bytes(p, the_insn);
1361}
1362
1363
1364static UChar *
1365emit_RSY(UChar *p, ULong op, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
1366{
1367 ULong the_insn = op;
1368
1369 the_insn |= ((ULong)r1) << 36;
1370 the_insn |= ((ULong)r3) << 32;
1371 the_insn |= ((ULong)b2) << 28;
1372 the_insn |= ((ULong)dl2) << 16;
1373 the_insn |= ((ULong)dh2) << 8;
1374
1375 return emit_6bytes(p, the_insn);
1376}
1377
1378
1379static UChar *
1380emit_RX(UChar *p, UInt op, UChar r1, UChar x2, UChar b2, UShort d2)
1381{
1382 ULong the_insn = op;
1383
1384 the_insn |= ((ULong)r1) << 20;
1385 the_insn |= ((ULong)x2) << 16;
1386 the_insn |= ((ULong)b2) << 12;
1387 the_insn |= ((ULong)d2) << 0;
1388
1389 return emit_4bytes(p, the_insn);
1390}
1391
1392
1393static UChar *
florian1b901d42013-01-01 22:19:24 +00001394emit_RXF(UChar *p, ULong op, UChar r3, UChar x2, UChar b2, UShort d2, UChar r1)
1395{
1396 ULong the_insn = op;
1397
1398 the_insn |= ((ULong)r3) << 36;
1399 the_insn |= ((ULong)x2) << 32;
1400 the_insn |= ((ULong)b2) << 28;
1401 the_insn |= ((ULong)d2) << 16;
1402 the_insn |= ((ULong)r1) << 12;
1403
1404 return emit_6bytes(p, the_insn);
1405}
1406
1407
1408static UChar *
sewardj2019a972011-03-07 16:04:07 +00001409emit_RXY(UChar *p, ULong op, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1410{
1411 ULong the_insn = op;
1412
1413 the_insn |= ((ULong)r1) << 36;
1414 the_insn |= ((ULong)x2) << 32;
1415 the_insn |= ((ULong)b2) << 28;
1416 the_insn |= ((ULong)dl2) << 16;
1417 the_insn |= ((ULong)dh2) << 8;
1418
1419 return emit_6bytes(p, the_insn);
1420}
1421
1422
1423static UChar *
1424emit_S(UChar *p, UInt op, UChar b2, UShort d2)
1425{
1426 ULong the_insn = op;
1427
1428 the_insn |= ((ULong)b2) << 12;
1429 the_insn |= ((ULong)d2) << 0;
1430
1431 return emit_4bytes(p, the_insn);
1432}
1433
1434
florianad43b3a2012-02-20 15:01:14 +00001435static UChar *
florianb93348d2012-12-27 00:59:43 +00001436emit_SI(UChar *p, UInt op, UChar i2, UChar b1, UShort d1)
1437{
1438 ULong the_insn = op;
1439
1440 the_insn |= ((ULong)i2) << 16;
1441 the_insn |= ((ULong)b1) << 12;
1442 the_insn |= ((ULong)d1) << 0;
1443
1444 return emit_4bytes(p, the_insn);
1445}
1446
1447
1448static UChar *
1449emit_SIL(UChar *p, ULong op, UChar b1, UShort d1, UShort i2)
1450{
1451 ULong the_insn = op;
1452
1453 the_insn |= ((ULong)b1) << 28;
1454 the_insn |= ((ULong)d1) << 16;
1455 the_insn |= ((ULong)i2) << 0;
1456
1457 return emit_6bytes(p, the_insn);
1458}
1459
1460
1461static UChar *
florianad43b3a2012-02-20 15:01:14 +00001462emit_SIY(UChar *p, ULong op, UChar i2, UChar b1, UShort dl1, UChar dh1)
1463{
1464 ULong the_insn = op;
1465
1466 the_insn |= ((ULong)i2) << 32;
1467 the_insn |= ((ULong)b1) << 28;
1468 the_insn |= ((ULong)dl1) << 16;
1469 the_insn |= ((ULong)dh1) << 8;
1470
1471 return emit_6bytes(p, the_insn);
1472}
1473
1474
1475static UChar *
1476emit_SSa(UChar *p, ULong op, UChar l, UChar b1, UShort d1, UChar b2, UShort d2)
1477{
1478 ULong the_insn = op;
1479
1480 the_insn |= ((ULong)l) << 32;
1481 the_insn |= ((ULong)b1) << 28;
1482 the_insn |= ((ULong)d1) << 16;
1483 the_insn |= ((ULong)b2) << 12;
1484 the_insn |= ((ULong)d2) << 0;
1485
1486 return emit_6bytes(p, the_insn);
1487}
1488
1489
sewardj2019a972011-03-07 16:04:07 +00001490/*------------------------------------------------------------*/
1491/*--- Functions to emit particular instructions ---*/
1492/*------------------------------------------------------------*/
1493
sewardj9d31dfd2011-03-15 12:36:44 +00001494static UChar *
sewardj2019a972011-03-07 16:04:07 +00001495s390_emit_AR(UChar *p, UChar r1, UChar r2)
1496{
sewardj7ee97522011-05-09 21:45:04 +00001497 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001498 s390_disasm(ENC3(MNM, GPR, GPR), "ar", r1, r2);
1499
1500 return emit_RR(p, 0x1a00, r1, r2);
1501}
1502
1503
sewardj9d31dfd2011-03-15 12:36:44 +00001504static UChar *
sewardj2019a972011-03-07 16:04:07 +00001505s390_emit_AGR(UChar *p, UChar r1, UChar r2)
1506{
sewardj7ee97522011-05-09 21:45:04 +00001507 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001508 s390_disasm(ENC3(MNM, GPR, GPR), "agr", r1, r2);
1509
1510 return emit_RRE(p, 0xb9080000, r1, r2);
1511}
1512
1513
sewardj9d31dfd2011-03-15 12:36:44 +00001514static UChar *
sewardj2019a972011-03-07 16:04:07 +00001515s390_emit_A(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
1516{
sewardj7ee97522011-05-09 21:45:04 +00001517 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001518 s390_disasm(ENC3(MNM, GPR, UDXB), "a", r1, d2, x2, b2);
1519
1520 return emit_RX(p, 0x5a000000, r1, x2, b2, d2);
1521}
1522
1523
sewardj9d31dfd2011-03-15 12:36:44 +00001524static UChar *
sewardj2019a972011-03-07 16:04:07 +00001525s390_emit_AY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1526{
sewardj7ee97522011-05-09 21:45:04 +00001527 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001528 s390_disasm(ENC3(MNM, GPR, SDXB), "ay", r1, dh2, dl2, x2, b2);
1529
1530 return emit_RXY(p, 0xe3000000005aULL, r1, x2, b2, dl2, dh2);
1531}
1532
1533
sewardj9d31dfd2011-03-15 12:36:44 +00001534static UChar *
sewardj2019a972011-03-07 16:04:07 +00001535s390_emit_AG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1536{
sewardj7ee97522011-05-09 21:45:04 +00001537 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001538 s390_disasm(ENC3(MNM, GPR, SDXB), "ag", r1, dh2, dl2, x2, b2);
1539
1540 return emit_RXY(p, 0xe30000000008ULL, r1, x2, b2, dl2, dh2);
1541}
1542
1543
sewardj9d31dfd2011-03-15 12:36:44 +00001544static UChar *
sewardj2019a972011-03-07 16:04:07 +00001545s390_emit_AFI(UChar *p, UChar r1, UInt i2)
1546{
sewardj652b56a2011-04-13 15:38:17 +00001547 vassert(s390_host_has_eimm);
1548
sewardj7ee97522011-05-09 21:45:04 +00001549 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001550 s390_disasm(ENC3(MNM, GPR, INT), "afi", r1, i2);
1551
1552 return emit_RIL(p, 0xc20900000000ULL, r1, i2);
1553}
1554
1555
sewardj9d31dfd2011-03-15 12:36:44 +00001556static UChar *
sewardj2019a972011-03-07 16:04:07 +00001557s390_emit_AGFI(UChar *p, UChar r1, UInt i2)
1558{
sewardj652b56a2011-04-13 15:38:17 +00001559 vassert(s390_host_has_eimm);
1560
sewardj7ee97522011-05-09 21:45:04 +00001561 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001562 s390_disasm(ENC3(MNM, GPR, INT), "agfi", r1, i2);
1563
1564 return emit_RIL(p, 0xc20800000000ULL, r1, i2);
1565}
1566
1567
sewardj9d31dfd2011-03-15 12:36:44 +00001568static UChar *
sewardj2019a972011-03-07 16:04:07 +00001569s390_emit_AH(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
1570{
sewardj7ee97522011-05-09 21:45:04 +00001571 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001572 s390_disasm(ENC3(MNM, GPR, UDXB), "ah", r1, d2, x2, b2);
1573
1574 return emit_RX(p, 0x4a000000, r1, x2, b2, d2);
1575}
1576
1577
sewardj9d31dfd2011-03-15 12:36:44 +00001578static UChar *
sewardj2019a972011-03-07 16:04:07 +00001579s390_emit_AHY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1580{
sewardj7ee97522011-05-09 21:45:04 +00001581 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001582 s390_disasm(ENC3(MNM, GPR, SDXB), "ahy", r1, dh2, dl2, x2, b2);
1583
1584 return emit_RXY(p, 0xe3000000007aULL, r1, x2, b2, dl2, dh2);
1585}
1586
1587
sewardj9d31dfd2011-03-15 12:36:44 +00001588static UChar *
sewardj2019a972011-03-07 16:04:07 +00001589s390_emit_AHI(UChar *p, UChar r1, UShort i2)
1590{
sewardj7ee97522011-05-09 21:45:04 +00001591 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001592 s390_disasm(ENC3(MNM, GPR, INT), "ahi", r1, (Int)(Short)i2);
1593
1594 return emit_RI(p, 0xa70a0000, r1, i2);
1595}
1596
1597
sewardj9d31dfd2011-03-15 12:36:44 +00001598static UChar *
sewardj2019a972011-03-07 16:04:07 +00001599s390_emit_AGHI(UChar *p, UChar r1, UShort i2)
1600{
sewardj7ee97522011-05-09 21:45:04 +00001601 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001602 s390_disasm(ENC3(MNM, GPR, INT), "aghi", r1, (Int)(Short)i2);
1603
1604 return emit_RI(p, 0xa70b0000, r1, i2);
1605}
1606
1607
sewardj9d31dfd2011-03-15 12:36:44 +00001608static UChar *
florianad43b3a2012-02-20 15:01:14 +00001609s390_emit_AGSI(UChar *p, UChar i2, UChar b1, UShort dl1, UChar dh1)
1610{
1611 vassert(s390_host_has_gie);
1612
1613 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
florian061dc422012-05-12 16:14:08 +00001614 s390_disasm(ENC3(MNM, SDXB, INT), "agsi", dh1, dl1, 0, b1, (Int)(Char)i2);
florianad43b3a2012-02-20 15:01:14 +00001615
1616 return emit_SIY(p, 0xeb000000007aULL, i2, b1, dl1, dh1);
1617}
1618
1619
1620static UChar *
florian0e047d62012-04-21 16:06:04 +00001621s390_emit_ASI(UChar *p, UChar i2, UChar b1, UShort dl1, UChar dh1)
1622{
1623 vassert(s390_host_has_gie);
1624
1625 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
florian061dc422012-05-12 16:14:08 +00001626 s390_disasm(ENC3(MNM, SDXB, INT), "asi", dh1, dl1, 0, b1, (Int)(Char)i2);
florian0e047d62012-04-21 16:06:04 +00001627
1628 return emit_SIY(p, 0xeb000000006aULL, i2, b1, dl1, dh1);
1629}
1630
1631
1632static UChar *
sewardj2019a972011-03-07 16:04:07 +00001633s390_emit_NR(UChar *p, UChar r1, UChar r2)
1634{
sewardj7ee97522011-05-09 21:45:04 +00001635 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001636 s390_disasm(ENC3(MNM, GPR, GPR), "nr", r1, r2);
1637
1638 return emit_RR(p, 0x1400, r1, r2);
1639}
1640
1641
sewardj9d31dfd2011-03-15 12:36:44 +00001642static UChar *
sewardj2019a972011-03-07 16:04:07 +00001643s390_emit_NGR(UChar *p, UChar r1, UChar r2)
1644{
sewardj7ee97522011-05-09 21:45:04 +00001645 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001646 s390_disasm(ENC3(MNM, GPR, GPR), "ngr", r1, r2);
1647
1648 return emit_RRE(p, 0xb9800000, r1, r2);
1649}
1650
1651
sewardj9d31dfd2011-03-15 12:36:44 +00001652static UChar *
sewardj2019a972011-03-07 16:04:07 +00001653s390_emit_N(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
1654{
sewardj7ee97522011-05-09 21:45:04 +00001655 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001656 s390_disasm(ENC3(MNM, GPR, UDXB), "n", r1, d2, x2, b2);
1657
1658 return emit_RX(p, 0x54000000, r1, x2, b2, d2);
1659}
1660
1661
sewardj9d31dfd2011-03-15 12:36:44 +00001662static UChar *
sewardj2019a972011-03-07 16:04:07 +00001663s390_emit_NY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1664{
sewardj7ee97522011-05-09 21:45:04 +00001665 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001666 s390_disasm(ENC3(MNM, GPR, SDXB), "ny", r1, dh2, dl2, x2, b2);
1667
1668 return emit_RXY(p, 0xe30000000054ULL, r1, x2, b2, dl2, dh2);
1669}
1670
1671
sewardj9d31dfd2011-03-15 12:36:44 +00001672static UChar *
sewardj2019a972011-03-07 16:04:07 +00001673s390_emit_NG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1674{
sewardj7ee97522011-05-09 21:45:04 +00001675 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001676 s390_disasm(ENC3(MNM, GPR, SDXB), "ng", r1, dh2, dl2, x2, b2);
1677
1678 return emit_RXY(p, 0xe30000000080ULL, r1, x2, b2, dl2, dh2);
1679}
1680
1681
sewardj9d31dfd2011-03-15 12:36:44 +00001682static UChar *
sewardj2019a972011-03-07 16:04:07 +00001683s390_emit_NIHF(UChar *p, UChar r1, UInt i2)
1684{
sewardj652b56a2011-04-13 15:38:17 +00001685 vassert(s390_host_has_eimm);
1686
sewardj7ee97522011-05-09 21:45:04 +00001687 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001688 s390_disasm(ENC3(MNM, GPR, UINT), "nihf", r1, i2);
1689
1690 return emit_RIL(p, 0xc00a00000000ULL, r1, i2);
1691}
1692
1693
sewardj9d31dfd2011-03-15 12:36:44 +00001694static UChar *
sewardj2019a972011-03-07 16:04:07 +00001695s390_emit_NILF(UChar *p, UChar r1, UInt i2)
1696{
sewardj652b56a2011-04-13 15:38:17 +00001697 vassert(s390_host_has_eimm);
1698
sewardj7ee97522011-05-09 21:45:04 +00001699 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001700 s390_disasm(ENC3(MNM, GPR, UINT), "nilf", r1, i2);
1701
1702 return emit_RIL(p, 0xc00b00000000ULL, r1, i2);
1703}
1704
1705
sewardj9d31dfd2011-03-15 12:36:44 +00001706static UChar *
sewardj2019a972011-03-07 16:04:07 +00001707s390_emit_NILL(UChar *p, UChar r1, UShort i2)
1708{
sewardj7ee97522011-05-09 21:45:04 +00001709 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001710 s390_disasm(ENC3(MNM, GPR, UINT), "nill", r1, i2);
1711
1712 return emit_RI(p, 0xa5070000, r1, i2);
1713}
1714
1715
sewardj9d31dfd2011-03-15 12:36:44 +00001716static UChar *
sewardj2019a972011-03-07 16:04:07 +00001717s390_emit_BASR(UChar *p, UChar r1, UChar r2)
1718{
sewardj7ee97522011-05-09 21:45:04 +00001719 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001720 s390_disasm(ENC3(MNM, GPR, GPR), "basr", r1, r2);
1721
1722 return emit_RR(p, 0x0d00, r1, r2);
1723}
1724
1725
sewardj9d31dfd2011-03-15 12:36:44 +00001726static UChar *
sewardj2019a972011-03-07 16:04:07 +00001727s390_emit_BCR(UChar *p, UChar r1, UChar r2)
1728{
sewardj7ee97522011-05-09 21:45:04 +00001729 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001730 s390_disasm(ENC2(XMNM, GPR), S390_XMNM_BCR, r1, r2);
1731
1732 return emit_RR(p, 0x0700, r1, r2);
1733}
1734
1735
sewardj9d31dfd2011-03-15 12:36:44 +00001736static UChar *
sewardj2019a972011-03-07 16:04:07 +00001737s390_emit_BRC(UChar *p, UChar r1, UShort i2)
1738{
sewardj7ee97522011-05-09 21:45:04 +00001739 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001740 s390_disasm(ENC2(XMNM, PCREL), S390_XMNM_BRC, r1, (Int)(Short)i2);
1741
1742 return emit_RI(p, 0xa7040000, r1, i2);
1743}
1744
1745
sewardj9d31dfd2011-03-15 12:36:44 +00001746static UChar *
florian8844a632012-04-13 04:04:06 +00001747s390_emit_BRCL(UChar *p, UChar r1, ULong i2)
1748{
1749 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1750 s390_disasm(ENC2(XMNM, PCREL), S390_XMNM_BRCL, r1, i2);
1751
1752 return emit_RIL(p, 0xc00400000000ULL, r1, i2);
1753}
1754
1755
1756static UChar *
sewardj2019a972011-03-07 16:04:07 +00001757s390_emit_CR(UChar *p, UChar r1, UChar r2)
1758{
sewardj7ee97522011-05-09 21:45:04 +00001759 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001760 s390_disasm(ENC3(MNM, GPR, GPR), "cr", r1, r2);
1761
1762 return emit_RR(p, 0x1900, r1, r2);
1763}
1764
1765
sewardj9d31dfd2011-03-15 12:36:44 +00001766static UChar *
sewardj2019a972011-03-07 16:04:07 +00001767s390_emit_CGR(UChar *p, UChar r1, UChar r2)
1768{
sewardj7ee97522011-05-09 21:45:04 +00001769 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001770 s390_disasm(ENC3(MNM, GPR, GPR), "cgr", r1, r2);
1771
1772 return emit_RRE(p, 0xb9200000, r1, r2);
1773}
1774
1775
sewardj9d31dfd2011-03-15 12:36:44 +00001776static UChar *
sewardj2019a972011-03-07 16:04:07 +00001777s390_emit_C(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
1778{
sewardj7ee97522011-05-09 21:45:04 +00001779 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001780 s390_disasm(ENC3(MNM, GPR, UDXB), "c", r1, d2, x2, b2);
1781
1782 return emit_RX(p, 0x59000000, r1, x2, b2, d2);
1783}
1784
1785
sewardj9d31dfd2011-03-15 12:36:44 +00001786static UChar *
sewardj2019a972011-03-07 16:04:07 +00001787s390_emit_CY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1788{
sewardj7ee97522011-05-09 21:45:04 +00001789 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001790 s390_disasm(ENC3(MNM, GPR, SDXB), "cy", r1, dh2, dl2, x2, b2);
1791
1792 return emit_RXY(p, 0xe30000000059ULL, r1, x2, b2, dl2, dh2);
1793}
1794
1795
sewardj9d31dfd2011-03-15 12:36:44 +00001796static UChar *
sewardj2019a972011-03-07 16:04:07 +00001797s390_emit_CG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1798{
sewardj7ee97522011-05-09 21:45:04 +00001799 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001800 s390_disasm(ENC3(MNM, GPR, SDXB), "cg", r1, dh2, dl2, x2, b2);
1801
1802 return emit_RXY(p, 0xe30000000020ULL, r1, x2, b2, dl2, dh2);
1803}
1804
1805
sewardj9d31dfd2011-03-15 12:36:44 +00001806static UChar *
sewardj2019a972011-03-07 16:04:07 +00001807s390_emit_CFI(UChar *p, UChar r1, UInt i2)
1808{
sewardj652b56a2011-04-13 15:38:17 +00001809 vassert(s390_host_has_eimm);
1810
sewardj7ee97522011-05-09 21:45:04 +00001811 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001812 s390_disasm(ENC3(MNM, GPR, INT), "cfi", r1, i2);
1813
1814 return emit_RIL(p, 0xc20d00000000ULL, r1, i2);
1815}
1816
1817
sewardj9d31dfd2011-03-15 12:36:44 +00001818static UChar *
florian07d34552012-05-26 01:59:21 +00001819s390_emit_CGFI(UChar *p, UChar r1, UInt i2)
1820{
1821 vassert(s390_host_has_eimm);
1822
1823 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1824 s390_disasm(ENC3(MNM, GPR, INT), "cgfi", r1, i2);
1825
1826 return emit_RIL(p, 0xc20c00000000ULL, r1, i2);
1827}
1828
1829
1830static UChar *
sewardj2019a972011-03-07 16:04:07 +00001831s390_emit_CS(UChar *p, UChar r1, UChar r3, UChar b2, UShort d2)
1832{
sewardj7ee97522011-05-09 21:45:04 +00001833 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001834 s390_disasm(ENC4(MNM, GPR, GPR, UDXB), "cs", r1, r3, d2, 0, b2);
1835
1836 return emit_RS(p, 0xba000000, r1, r3, b2, d2);
1837}
1838
1839
sewardj9d31dfd2011-03-15 12:36:44 +00001840static UChar *
sewardj2019a972011-03-07 16:04:07 +00001841s390_emit_CSY(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
1842{
sewardj7ee97522011-05-09 21:45:04 +00001843 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001844 s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "csy", r1, r3, dh2, dl2, 0, b2);
1845
1846 return emit_RSY(p, 0xeb0000000014ULL, r1, r3, b2, dl2, dh2);
1847}
1848
1849
sewardj9d31dfd2011-03-15 12:36:44 +00001850static UChar *
sewardj2019a972011-03-07 16:04:07 +00001851s390_emit_CSG(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
1852{
sewardj7ee97522011-05-09 21:45:04 +00001853 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001854 s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "csg", r1, r3, dh2, dl2, 0, b2);
1855
1856 return emit_RSY(p, 0xeb0000000030ULL, r1, r3, b2, dl2, dh2);
1857}
1858
1859
sewardj9d31dfd2011-03-15 12:36:44 +00001860static UChar *
florian448cbba2012-06-06 02:26:01 +00001861s390_emit_CDS(UChar *p, UChar r1, UChar r3, UChar b2, UShort d2)
1862{
1863 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1864 s390_disasm(ENC4(MNM, GPR, GPR, UDXB), "cds", r1, r3, d2, 0, b2);
1865
1866 return emit_RS(p, 0xbb000000, r1, r3, b2, d2);
1867}
1868
1869
1870static UChar *
1871s390_emit_CDSY(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
1872{
florian448cbba2012-06-06 02:26:01 +00001873 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1874 s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "cdsy", r1, r3, dh2, dl2, 0, b2);
1875
1876 return emit_RSY(p, 0xeb0000000031ULL, r1, r3, b2, dl2, dh2);
1877}
1878
1879
1880static UChar *
1881s390_emit_CDSG(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
1882{
florian448cbba2012-06-06 02:26:01 +00001883 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1884 s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "cdsg", r1, r3, dh2, dl2, 0, b2);
1885
1886 return emit_RSY(p, 0xeb000000003eULL, r1, r3, b2, dl2, dh2);
1887}
1888
1889
1890static UChar *
sewardj2019a972011-03-07 16:04:07 +00001891s390_emit_CLR(UChar *p, UChar r1, UChar r2)
1892{
sewardj7ee97522011-05-09 21:45:04 +00001893 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001894 s390_disasm(ENC3(MNM, GPR, GPR), "clr", r1, r2);
1895
1896 return emit_RR(p, 0x1500, r1, r2);
1897}
1898
1899
sewardj9d31dfd2011-03-15 12:36:44 +00001900static UChar *
sewardj2019a972011-03-07 16:04:07 +00001901s390_emit_CLGR(UChar *p, UChar r1, UChar r2)
1902{
sewardj7ee97522011-05-09 21:45:04 +00001903 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001904 s390_disasm(ENC3(MNM, GPR, GPR), "clgr", r1, r2);
1905
1906 return emit_RRE(p, 0xb9210000, r1, r2);
1907}
1908
1909
sewardj9d31dfd2011-03-15 12:36:44 +00001910static UChar *
sewardj2019a972011-03-07 16:04:07 +00001911s390_emit_CL(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
1912{
sewardj7ee97522011-05-09 21:45:04 +00001913 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001914 s390_disasm(ENC3(MNM, GPR, UDXB), "cl", r1, d2, x2, b2);
1915
1916 return emit_RX(p, 0x55000000, r1, x2, b2, d2);
1917}
1918
1919
sewardj9d31dfd2011-03-15 12:36:44 +00001920static UChar *
sewardj2019a972011-03-07 16:04:07 +00001921s390_emit_CLY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1922{
sewardj7ee97522011-05-09 21:45:04 +00001923 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001924 s390_disasm(ENC3(MNM, GPR, SDXB), "cly", r1, dh2, dl2, x2, b2);
1925
1926 return emit_RXY(p, 0xe30000000055ULL, r1, x2, b2, dl2, dh2);
1927}
1928
1929
sewardj9d31dfd2011-03-15 12:36:44 +00001930static UChar *
sewardj2019a972011-03-07 16:04:07 +00001931s390_emit_CLG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
1932{
sewardj7ee97522011-05-09 21:45:04 +00001933 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001934 s390_disasm(ENC3(MNM, GPR, SDXB), "clg", r1, dh2, dl2, x2, b2);
1935
1936 return emit_RXY(p, 0xe30000000021ULL, r1, x2, b2, dl2, dh2);
1937}
1938
1939
sewardj9d31dfd2011-03-15 12:36:44 +00001940static UChar *
sewardj2019a972011-03-07 16:04:07 +00001941s390_emit_CLFI(UChar *p, UChar r1, UInt i2)
1942{
sewardj652b56a2011-04-13 15:38:17 +00001943 vassert(s390_host_has_eimm);
1944
sewardj7ee97522011-05-09 21:45:04 +00001945 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001946 s390_disasm(ENC3(MNM, GPR, UINT), "clfi", r1, i2);
1947
1948 return emit_RIL(p, 0xc20f00000000ULL, r1, i2);
1949}
1950
1951
sewardj9d31dfd2011-03-15 12:36:44 +00001952static UChar *
florian07d34552012-05-26 01:59:21 +00001953s390_emit_CLGFI(UChar *p, UChar r1, UInt i2)
1954{
1955 vassert(s390_host_has_eimm);
1956
1957 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
1958 s390_disasm(ENC3(MNM, GPR, UINT), "clgfi", r1, i2);
1959
1960 return emit_RIL(p, 0xc20e00000000ULL, r1, i2);
1961}
1962
1963
1964static UChar *
sewardj2019a972011-03-07 16:04:07 +00001965s390_emit_DR(UChar *p, UChar r1, UChar r2)
1966{
sewardj7ee97522011-05-09 21:45:04 +00001967 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001968 s390_disasm(ENC3(MNM, GPR, GPR), "dr", r1, r2);
1969
1970 return emit_RR(p, 0x1d00, r1, r2);
1971}
1972
1973
sewardj9d31dfd2011-03-15 12:36:44 +00001974static UChar *
sewardj2019a972011-03-07 16:04:07 +00001975s390_emit_D(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
1976{
sewardj7ee97522011-05-09 21:45:04 +00001977 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001978 s390_disasm(ENC3(MNM, GPR, UDXB), "d", r1, d2, x2, b2);
1979
1980 return emit_RX(p, 0x5d000000, r1, x2, b2, d2);
1981}
1982
1983
sewardj9d31dfd2011-03-15 12:36:44 +00001984static UChar *
sewardj2019a972011-03-07 16:04:07 +00001985s390_emit_DLR(UChar *p, UChar r1, UChar r2)
1986{
sewardj7ee97522011-05-09 21:45:04 +00001987 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001988 s390_disasm(ENC3(MNM, GPR, GPR), "dlr", r1, r2);
1989
1990 return emit_RRE(p, 0xb9970000, r1, r2);
1991}
1992
1993
sewardj9d31dfd2011-03-15 12:36:44 +00001994static UChar *
sewardj2019a972011-03-07 16:04:07 +00001995s390_emit_DLGR(UChar *p, UChar r1, UChar r2)
1996{
sewardj7ee97522011-05-09 21:45:04 +00001997 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00001998 s390_disasm(ENC3(MNM, GPR, GPR), "dlgr", r1, r2);
1999
2000 return emit_RRE(p, 0xb9870000, r1, r2);
2001}
2002
2003
sewardj9d31dfd2011-03-15 12:36:44 +00002004static UChar *
sewardj2019a972011-03-07 16:04:07 +00002005s390_emit_DL(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2006{
sewardj7ee97522011-05-09 21:45:04 +00002007 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002008 s390_disasm(ENC3(MNM, GPR, SDXB), "dl", r1, dh2, dl2, x2, b2);
2009
2010 return emit_RXY(p, 0xe30000000097ULL, r1, x2, b2, dl2, dh2);
2011}
2012
2013
sewardj9d31dfd2011-03-15 12:36:44 +00002014static UChar *
sewardj2019a972011-03-07 16:04:07 +00002015s390_emit_DLG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2016{
sewardj7ee97522011-05-09 21:45:04 +00002017 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002018 s390_disasm(ENC3(MNM, GPR, SDXB), "dlg", r1, dh2, dl2, x2, b2);
2019
2020 return emit_RXY(p, 0xe30000000087ULL, r1, x2, b2, dl2, dh2);
2021}
2022
2023
sewardj9d31dfd2011-03-15 12:36:44 +00002024static UChar *
sewardj2019a972011-03-07 16:04:07 +00002025s390_emit_DSGR(UChar *p, UChar r1, UChar r2)
2026{
sewardj7ee97522011-05-09 21:45:04 +00002027 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002028 s390_disasm(ENC3(MNM, GPR, GPR), "dsgr", r1, r2);
2029
2030 return emit_RRE(p, 0xb90d0000, r1, r2);
2031}
2032
2033
sewardj9d31dfd2011-03-15 12:36:44 +00002034static UChar *
sewardj2019a972011-03-07 16:04:07 +00002035s390_emit_DSG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2036{
sewardj7ee97522011-05-09 21:45:04 +00002037 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002038 s390_disasm(ENC3(MNM, GPR, SDXB), "dsg", r1, dh2, dl2, x2, b2);
2039
2040 return emit_RXY(p, 0xe3000000000dULL, r1, x2, b2, dl2, dh2);
2041}
2042
2043
sewardj9d31dfd2011-03-15 12:36:44 +00002044static UChar *
sewardj2019a972011-03-07 16:04:07 +00002045s390_emit_XR(UChar *p, UChar r1, UChar r2)
2046{
sewardj7ee97522011-05-09 21:45:04 +00002047 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002048 s390_disasm(ENC3(MNM, GPR, GPR), "xr", r1, r2);
2049
2050 return emit_RR(p, 0x1700, r1, r2);
2051}
2052
2053
sewardj9d31dfd2011-03-15 12:36:44 +00002054static UChar *
sewardj2019a972011-03-07 16:04:07 +00002055s390_emit_XGR(UChar *p, UChar r1, UChar r2)
2056{
sewardj7ee97522011-05-09 21:45:04 +00002057 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002058 s390_disasm(ENC3(MNM, GPR, GPR), "xgr", r1, r2);
2059
2060 return emit_RRE(p, 0xb9820000, r1, r2);
2061}
2062
2063
sewardj9d31dfd2011-03-15 12:36:44 +00002064static UChar *
sewardj2019a972011-03-07 16:04:07 +00002065s390_emit_X(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2066{
sewardj7ee97522011-05-09 21:45:04 +00002067 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002068 s390_disasm(ENC3(MNM, GPR, UDXB), "x", r1, d2, x2, b2);
2069
2070 return emit_RX(p, 0x57000000, r1, x2, b2, d2);
2071}
2072
2073
sewardj9d31dfd2011-03-15 12:36:44 +00002074static UChar *
sewardj2019a972011-03-07 16:04:07 +00002075s390_emit_XY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2076{
sewardj7ee97522011-05-09 21:45:04 +00002077 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002078 s390_disasm(ENC3(MNM, GPR, SDXB), "xy", r1, dh2, dl2, x2, b2);
2079
2080 return emit_RXY(p, 0xe30000000057ULL, r1, x2, b2, dl2, dh2);
2081}
2082
2083
sewardj9d31dfd2011-03-15 12:36:44 +00002084static UChar *
sewardj2019a972011-03-07 16:04:07 +00002085s390_emit_XG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2086{
sewardj7ee97522011-05-09 21:45:04 +00002087 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002088 s390_disasm(ENC3(MNM, GPR, SDXB), "xg", r1, dh2, dl2, x2, b2);
2089
2090 return emit_RXY(p, 0xe30000000082ULL, r1, x2, b2, dl2, dh2);
2091}
2092
2093
sewardj9d31dfd2011-03-15 12:36:44 +00002094static UChar *
sewardj2019a972011-03-07 16:04:07 +00002095s390_emit_XIHF(UChar *p, UChar r1, UInt i2)
2096{
sewardj652b56a2011-04-13 15:38:17 +00002097 vassert(s390_host_has_eimm);
2098
sewardj7ee97522011-05-09 21:45:04 +00002099 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002100 s390_disasm(ENC3(MNM, GPR, UINT), "xihf", r1, i2);
2101
2102 return emit_RIL(p, 0xc00600000000ULL, r1, i2);
2103}
2104
2105
sewardj9d31dfd2011-03-15 12:36:44 +00002106static UChar *
sewardj2019a972011-03-07 16:04:07 +00002107s390_emit_XILF(UChar *p, UChar r1, UInt i2)
2108{
sewardj652b56a2011-04-13 15:38:17 +00002109 vassert(s390_host_has_eimm);
2110
sewardj7ee97522011-05-09 21:45:04 +00002111 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002112 s390_disasm(ENC3(MNM, GPR, UINT), "xilf", r1, i2);
2113
2114 return emit_RIL(p, 0xc00700000000ULL, r1, i2);
2115}
2116
2117
sewardj9d31dfd2011-03-15 12:36:44 +00002118static UChar *
florianad43b3a2012-02-20 15:01:14 +00002119s390_emit_XC(UChar *p, UInt l, UChar b1, UShort d1, UChar b2, UShort d2)
2120{
2121 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2122 s390_disasm(ENC3(MNM, UDLB, UDXB), "xc", d1, l, b1, d2, 0, b2);
2123
2124 return emit_SSa(p, 0xd70000000000ULL, l, b1, d1, b2, d2);
2125}
2126
2127
2128static UChar *
sewardj2019a972011-03-07 16:04:07 +00002129s390_emit_FLOGR(UChar *p, UChar r1, UChar r2)
2130{
sewardj652b56a2011-04-13 15:38:17 +00002131 vassert(s390_host_has_eimm);
2132
sewardj7ee97522011-05-09 21:45:04 +00002133 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002134 s390_disasm(ENC3(MNM, GPR, GPR), "flogr", r1, r2);
2135
2136 return emit_RRE(p, 0xb9830000, r1, r2);
2137}
2138
2139
sewardj9d31dfd2011-03-15 12:36:44 +00002140static UChar *
sewardj2019a972011-03-07 16:04:07 +00002141s390_emit_IC(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2142{
sewardj7ee97522011-05-09 21:45:04 +00002143 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002144 s390_disasm(ENC3(MNM, GPR, UDXB), "ic", r1, d2, x2, b2);
2145
2146 return emit_RX(p, 0x43000000, r1, x2, b2, d2);
2147}
2148
2149
sewardj9d31dfd2011-03-15 12:36:44 +00002150static UChar *
sewardj2019a972011-03-07 16:04:07 +00002151s390_emit_ICY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2152{
sewardj7ee97522011-05-09 21:45:04 +00002153 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002154 s390_disasm(ENC3(MNM, GPR, SDXB), "icy", r1, dh2, dl2, x2, b2);
2155
2156 return emit_RXY(p, 0xe30000000073ULL, r1, x2, b2, dl2, dh2);
2157}
2158
2159
sewardj9d31dfd2011-03-15 12:36:44 +00002160static UChar *
sewardj2019a972011-03-07 16:04:07 +00002161s390_emit_IIHF(UChar *p, UChar r1, UInt i2)
2162{
sewardj652b56a2011-04-13 15:38:17 +00002163 vassert(s390_host_has_eimm);
2164
sewardj7ee97522011-05-09 21:45:04 +00002165 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002166 s390_disasm(ENC3(MNM, GPR, UINT), "iihf", r1, i2);
2167
2168 return emit_RIL(p, 0xc00800000000ULL, r1, i2);
2169}
2170
2171
sewardj9d31dfd2011-03-15 12:36:44 +00002172static UChar *
sewardj2019a972011-03-07 16:04:07 +00002173s390_emit_IIHH(UChar *p, UChar r1, UShort i2)
2174{
sewardj7ee97522011-05-09 21:45:04 +00002175 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002176 s390_disasm(ENC3(MNM, GPR, UINT), "iihh", r1, i2);
2177
2178 return emit_RI(p, 0xa5000000, r1, i2);
2179}
2180
2181
sewardj9d31dfd2011-03-15 12:36:44 +00002182static UChar *
sewardj2019a972011-03-07 16:04:07 +00002183s390_emit_IIHL(UChar *p, UChar r1, UShort i2)
2184{
sewardj7ee97522011-05-09 21:45:04 +00002185 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002186 s390_disasm(ENC3(MNM, GPR, UINT), "iihl", r1, i2);
2187
2188 return emit_RI(p, 0xa5010000, r1, i2);
2189}
2190
2191
sewardj9d31dfd2011-03-15 12:36:44 +00002192static UChar *
sewardj2019a972011-03-07 16:04:07 +00002193s390_emit_IILF(UChar *p, UChar r1, UInt i2)
2194{
sewardj652b56a2011-04-13 15:38:17 +00002195 vassert(s390_host_has_eimm);
2196
sewardj7ee97522011-05-09 21:45:04 +00002197 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002198 s390_disasm(ENC3(MNM, GPR, UINT), "iilf", r1, i2);
2199
2200 return emit_RIL(p, 0xc00900000000ULL, r1, i2);
2201}
2202
2203
sewardj9d31dfd2011-03-15 12:36:44 +00002204static UChar *
sewardj2019a972011-03-07 16:04:07 +00002205s390_emit_IILH(UChar *p, UChar r1, UShort i2)
2206{
sewardj7ee97522011-05-09 21:45:04 +00002207 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002208 s390_disasm(ENC3(MNM, GPR, UINT), "iilh", r1, i2);
2209
2210 return emit_RI(p, 0xa5020000, r1, i2);
2211}
2212
2213
sewardj9d31dfd2011-03-15 12:36:44 +00002214static UChar *
sewardj2019a972011-03-07 16:04:07 +00002215s390_emit_IILL(UChar *p, UChar r1, UShort i2)
2216{
sewardj7ee97522011-05-09 21:45:04 +00002217 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002218 s390_disasm(ENC3(MNM, GPR, UINT), "iill", r1, i2);
2219
2220 return emit_RI(p, 0xa5030000, r1, i2);
2221}
2222
2223
sewardj9d31dfd2011-03-15 12:36:44 +00002224static UChar *
sewardj2019a972011-03-07 16:04:07 +00002225s390_emit_IPM(UChar *p, UChar r1, UChar r2)
2226{
sewardj7ee97522011-05-09 21:45:04 +00002227 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002228 s390_disasm(ENC2(MNM, GPR), "ipm", r1);
2229
2230 return emit_RRE(p, 0xb2220000, r1, r2);
2231}
2232
2233
sewardj9d31dfd2011-03-15 12:36:44 +00002234static UChar *
sewardj2019a972011-03-07 16:04:07 +00002235s390_emit_LR(UChar *p, UChar r1, UChar r2)
2236{
sewardj7ee97522011-05-09 21:45:04 +00002237 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002238 s390_disasm(ENC3(MNM, GPR, GPR), "lr", r1, r2);
2239
2240 return emit_RR(p, 0x1800, r1, r2);
2241}
2242
2243
sewardj9d31dfd2011-03-15 12:36:44 +00002244static UChar *
sewardj2019a972011-03-07 16:04:07 +00002245s390_emit_LGR(UChar *p, UChar r1, UChar r2)
2246{
sewardj7ee97522011-05-09 21:45:04 +00002247 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002248 s390_disasm(ENC3(MNM, GPR, GPR), "lgr", r1, r2);
2249
2250 return emit_RRE(p, 0xb9040000, r1, r2);
2251}
2252
2253
sewardj9d31dfd2011-03-15 12:36:44 +00002254static UChar *
sewardj2019a972011-03-07 16:04:07 +00002255s390_emit_LGFR(UChar *p, UChar r1, UChar r2)
2256{
sewardj7ee97522011-05-09 21:45:04 +00002257 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002258 s390_disasm(ENC3(MNM, GPR, GPR), "lgfr", r1, r2);
2259
2260 return emit_RRE(p, 0xb9140000, r1, r2);
2261}
2262
2263
sewardj9d31dfd2011-03-15 12:36:44 +00002264static UChar *
sewardj2019a972011-03-07 16:04:07 +00002265s390_emit_L(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2266{
sewardj7ee97522011-05-09 21:45:04 +00002267 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002268 s390_disasm(ENC3(MNM, GPR, UDXB), "l", r1, d2, x2, b2);
2269
2270 return emit_RX(p, 0x58000000, r1, x2, b2, d2);
2271}
2272
2273
sewardj9d31dfd2011-03-15 12:36:44 +00002274static UChar *
sewardj2019a972011-03-07 16:04:07 +00002275s390_emit_LY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2276{
sewardj7ee97522011-05-09 21:45:04 +00002277 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002278 s390_disasm(ENC3(MNM, GPR, SDXB), "ly", r1, dh2, dl2, x2, b2);
2279
2280 return emit_RXY(p, 0xe30000000058ULL, r1, x2, b2, dl2, dh2);
2281}
2282
2283
sewardj9d31dfd2011-03-15 12:36:44 +00002284static UChar *
sewardj2019a972011-03-07 16:04:07 +00002285s390_emit_LG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2286{
sewardj7ee97522011-05-09 21:45:04 +00002287 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002288 s390_disasm(ENC3(MNM, GPR, SDXB), "lg", r1, dh2, dl2, x2, b2);
2289
2290 return emit_RXY(p, 0xe30000000004ULL, r1, x2, b2, dl2, dh2);
2291}
2292
2293
sewardj9d31dfd2011-03-15 12:36:44 +00002294static UChar *
sewardj2019a972011-03-07 16:04:07 +00002295s390_emit_LGF(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2296{
sewardj7ee97522011-05-09 21:45:04 +00002297 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002298 s390_disasm(ENC3(MNM, GPR, SDXB), "lgf", r1, dh2, dl2, x2, b2);
2299
2300 return emit_RXY(p, 0xe30000000014ULL, r1, x2, b2, dl2, dh2);
2301}
2302
2303
sewardj9d31dfd2011-03-15 12:36:44 +00002304static UChar *
sewardj2019a972011-03-07 16:04:07 +00002305s390_emit_LGFI(UChar *p, UChar r1, UInt i2)
2306{
sewardj652b56a2011-04-13 15:38:17 +00002307 vassert(s390_host_has_eimm);
2308
sewardj7ee97522011-05-09 21:45:04 +00002309 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002310 s390_disasm(ENC3(MNM, GPR, INT), "lgfi", r1, i2);
2311
2312 return emit_RIL(p, 0xc00100000000ULL, r1, i2);
2313}
2314
2315
sewardj9d31dfd2011-03-15 12:36:44 +00002316static UChar *
sewardj2019a972011-03-07 16:04:07 +00002317s390_emit_LTR(UChar *p, UChar r1, UChar r2)
2318{
sewardj7ee97522011-05-09 21:45:04 +00002319 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002320 s390_disasm(ENC3(MNM, GPR, GPR), "ltr", r1, r2);
2321
2322 return emit_RR(p, 0x1200, r1, r2);
2323}
2324
2325
sewardj9d31dfd2011-03-15 12:36:44 +00002326static UChar *
sewardj2019a972011-03-07 16:04:07 +00002327s390_emit_LTGR(UChar *p, UChar r1, UChar r2)
2328{
sewardj7ee97522011-05-09 21:45:04 +00002329 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002330 s390_disasm(ENC3(MNM, GPR, GPR), "ltgr", r1, r2);
2331
2332 return emit_RRE(p, 0xb9020000, r1, r2);
2333}
2334
2335
sewardj9d31dfd2011-03-15 12:36:44 +00002336static UChar *
sewardj2019a972011-03-07 16:04:07 +00002337s390_emit_LT(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2338{
sewardj652b56a2011-04-13 15:38:17 +00002339 vassert(s390_host_has_eimm);
2340
sewardj7ee97522011-05-09 21:45:04 +00002341 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002342 s390_disasm(ENC3(MNM, GPR, SDXB), "lt", r1, dh2, dl2, x2, b2);
2343
2344 return emit_RXY(p, 0xe30000000012ULL, r1, x2, b2, dl2, dh2);
2345}
2346
2347
sewardj9d31dfd2011-03-15 12:36:44 +00002348static UChar *
sewardj2019a972011-03-07 16:04:07 +00002349s390_emit_LTG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2350{
sewardj652b56a2011-04-13 15:38:17 +00002351 vassert(s390_host_has_eimm);
2352
sewardj7ee97522011-05-09 21:45:04 +00002353 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002354 s390_disasm(ENC3(MNM, GPR, SDXB), "ltg", r1, dh2, dl2, x2, b2);
2355
2356 return emit_RXY(p, 0xe30000000002ULL, r1, x2, b2, dl2, dh2);
2357}
2358
2359
sewardj9d31dfd2011-03-15 12:36:44 +00002360static UChar *
sewardj2019a972011-03-07 16:04:07 +00002361s390_emit_LBR(UChar *p, UChar r1, UChar r2)
2362{
sewardj652b56a2011-04-13 15:38:17 +00002363 vassert(s390_host_has_eimm);
2364
sewardj7ee97522011-05-09 21:45:04 +00002365 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002366 s390_disasm(ENC3(MNM, GPR, GPR), "lbr", r1, r2);
2367
2368 return emit_RRE(p, 0xb9260000, r1, r2);
2369}
2370
2371
sewardj9d31dfd2011-03-15 12:36:44 +00002372static UChar *
sewardj2019a972011-03-07 16:04:07 +00002373s390_emit_LGBR(UChar *p, UChar r1, UChar r2)
2374{
sewardj652b56a2011-04-13 15:38:17 +00002375 vassert(s390_host_has_eimm);
2376
sewardj7ee97522011-05-09 21:45:04 +00002377 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002378 s390_disasm(ENC3(MNM, GPR, GPR), "lgbr", r1, r2);
2379
2380 return emit_RRE(p, 0xb9060000, r1, r2);
2381}
2382
2383
sewardj9d31dfd2011-03-15 12:36:44 +00002384static UChar *
sewardj2019a972011-03-07 16:04:07 +00002385s390_emit_LB(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2386{
sewardj7ee97522011-05-09 21:45:04 +00002387 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002388 s390_disasm(ENC3(MNM, GPR, SDXB), "lb", r1, dh2, dl2, x2, b2);
2389
2390 return emit_RXY(p, 0xe30000000076ULL, r1, x2, b2, dl2, dh2);
2391}
2392
2393
sewardj9d31dfd2011-03-15 12:36:44 +00002394static UChar *
sewardj2019a972011-03-07 16:04:07 +00002395s390_emit_LGB(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2396{
sewardj7ee97522011-05-09 21:45:04 +00002397 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002398 s390_disasm(ENC3(MNM, GPR, SDXB), "lgb", r1, dh2, dl2, x2, b2);
2399
2400 return emit_RXY(p, 0xe30000000077ULL, r1, x2, b2, dl2, dh2);
2401}
2402
2403
sewardj9d31dfd2011-03-15 12:36:44 +00002404static UChar *
sewardj2019a972011-03-07 16:04:07 +00002405s390_emit_LCR(UChar *p, UChar r1, UChar r2)
2406{
sewardj7ee97522011-05-09 21:45:04 +00002407 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002408 s390_disasm(ENC3(MNM, GPR, GPR), "lcr", r1, r2);
2409
2410 return emit_RR(p, 0x1300, r1, r2);
2411}
2412
2413
sewardj9d31dfd2011-03-15 12:36:44 +00002414static UChar *
sewardj2019a972011-03-07 16:04:07 +00002415s390_emit_LCGR(UChar *p, UChar r1, UChar r2)
2416{
sewardj7ee97522011-05-09 21:45:04 +00002417 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002418 s390_disasm(ENC3(MNM, GPR, GPR), "lcgr", r1, r2);
2419
2420 return emit_RRE(p, 0xb9030000, r1, r2);
2421}
2422
2423
sewardj9d31dfd2011-03-15 12:36:44 +00002424static UChar *
sewardj2019a972011-03-07 16:04:07 +00002425s390_emit_LHR(UChar *p, UChar r1, UChar r2)
2426{
sewardj652b56a2011-04-13 15:38:17 +00002427 vassert(s390_host_has_eimm);
2428
sewardj7ee97522011-05-09 21:45:04 +00002429 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002430 s390_disasm(ENC3(MNM, GPR, GPR), "lhr", r1, r2);
2431
2432 return emit_RRE(p, 0xb9270000, r1, r2);
2433}
2434
2435
sewardj9d31dfd2011-03-15 12:36:44 +00002436static UChar *
sewardj2019a972011-03-07 16:04:07 +00002437s390_emit_LGHR(UChar *p, UChar r1, UChar r2)
2438{
sewardj652b56a2011-04-13 15:38:17 +00002439 vassert(s390_host_has_eimm);
2440
sewardj7ee97522011-05-09 21:45:04 +00002441 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002442 s390_disasm(ENC3(MNM, GPR, GPR), "lghr", r1, r2);
2443
2444 return emit_RRE(p, 0xb9070000, r1, r2);
2445}
2446
2447
sewardj9d31dfd2011-03-15 12:36:44 +00002448static UChar *
sewardj2019a972011-03-07 16:04:07 +00002449s390_emit_LH(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2450{
sewardj7ee97522011-05-09 21:45:04 +00002451 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002452 s390_disasm(ENC3(MNM, GPR, UDXB), "lh", r1, d2, x2, b2);
2453
2454 return emit_RX(p, 0x48000000, r1, x2, b2, d2);
2455}
2456
2457
sewardj9d31dfd2011-03-15 12:36:44 +00002458static UChar *
sewardj2019a972011-03-07 16:04:07 +00002459s390_emit_LHY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2460{
sewardj7ee97522011-05-09 21:45:04 +00002461 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002462 s390_disasm(ENC3(MNM, GPR, SDXB), "lhy", r1, dh2, dl2, x2, b2);
2463
2464 return emit_RXY(p, 0xe30000000078ULL, r1, x2, b2, dl2, dh2);
2465}
2466
2467
sewardj9d31dfd2011-03-15 12:36:44 +00002468static UChar *
sewardj2019a972011-03-07 16:04:07 +00002469s390_emit_LGH(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2470{
sewardj7ee97522011-05-09 21:45:04 +00002471 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002472 s390_disasm(ENC3(MNM, GPR, SDXB), "lgh", r1, dh2, dl2, x2, b2);
2473
2474 return emit_RXY(p, 0xe30000000015ULL, r1, x2, b2, dl2, dh2);
2475}
2476
2477
sewardj9d31dfd2011-03-15 12:36:44 +00002478static UChar *
sewardj2019a972011-03-07 16:04:07 +00002479s390_emit_LHI(UChar *p, UChar r1, UShort i2)
2480{
sewardj7ee97522011-05-09 21:45:04 +00002481 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002482 s390_disasm(ENC3(MNM, GPR, INT), "lhi", r1, (Int)(Short)i2);
2483
2484 return emit_RI(p, 0xa7080000, r1, i2);
2485}
2486
2487
sewardj9d31dfd2011-03-15 12:36:44 +00002488static UChar *
sewardj2019a972011-03-07 16:04:07 +00002489s390_emit_LGHI(UChar *p, UChar r1, UShort i2)
2490{
sewardj7ee97522011-05-09 21:45:04 +00002491 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002492 s390_disasm(ENC3(MNM, GPR, INT), "lghi", r1, (Int)(Short)i2);
2493
2494 return emit_RI(p, 0xa7090000, r1, i2);
2495}
2496
2497
sewardj9d31dfd2011-03-15 12:36:44 +00002498static UChar *
sewardj2019a972011-03-07 16:04:07 +00002499s390_emit_LLGFR(UChar *p, UChar r1, UChar r2)
2500{
sewardj7ee97522011-05-09 21:45:04 +00002501 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002502 s390_disasm(ENC3(MNM, GPR, GPR), "llgfr", r1, r2);
2503
2504 return emit_RRE(p, 0xb9160000, r1, r2);
2505}
2506
2507
sewardj9d31dfd2011-03-15 12:36:44 +00002508static UChar *
sewardj2019a972011-03-07 16:04:07 +00002509s390_emit_LLGF(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2510{
sewardj7ee97522011-05-09 21:45:04 +00002511 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002512 s390_disasm(ENC3(MNM, GPR, SDXB), "llgf", r1, dh2, dl2, x2, b2);
2513
2514 return emit_RXY(p, 0xe30000000016ULL, r1, x2, b2, dl2, dh2);
2515}
2516
2517
sewardj9d31dfd2011-03-15 12:36:44 +00002518static UChar *
sewardj2019a972011-03-07 16:04:07 +00002519s390_emit_LLCR(UChar *p, UChar r1, UChar r2)
2520{
sewardj652b56a2011-04-13 15:38:17 +00002521 vassert(s390_host_has_eimm);
2522
sewardj7ee97522011-05-09 21:45:04 +00002523 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002524 s390_disasm(ENC3(MNM, GPR, GPR), "llcr", r1, r2);
2525
2526 return emit_RRE(p, 0xb9940000, r1, r2);
2527}
2528
2529
sewardj9d31dfd2011-03-15 12:36:44 +00002530static UChar *
sewardj2019a972011-03-07 16:04:07 +00002531s390_emit_LLGCR(UChar *p, UChar r1, UChar r2)
2532{
sewardj652b56a2011-04-13 15:38:17 +00002533 vassert(s390_host_has_eimm);
2534
sewardj7ee97522011-05-09 21:45:04 +00002535 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002536 s390_disasm(ENC3(MNM, GPR, GPR), "llgcr", r1, r2);
2537
2538 return emit_RRE(p, 0xb9840000, r1, r2);
2539}
2540
2541
sewardj9d31dfd2011-03-15 12:36:44 +00002542static UChar *
sewardj2019a972011-03-07 16:04:07 +00002543s390_emit_LLC(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2544{
sewardj652b56a2011-04-13 15:38:17 +00002545 vassert(s390_host_has_eimm);
2546
sewardj7ee97522011-05-09 21:45:04 +00002547 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002548 s390_disasm(ENC3(MNM, GPR, SDXB), "llc", r1, dh2, dl2, x2, b2);
2549
2550 return emit_RXY(p, 0xe30000000094ULL, r1, x2, b2, dl2, dh2);
2551}
2552
2553
sewardj9d31dfd2011-03-15 12:36:44 +00002554static UChar *
sewardj2019a972011-03-07 16:04:07 +00002555s390_emit_LLGC(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2556{
sewardj7ee97522011-05-09 21:45:04 +00002557 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002558 s390_disasm(ENC3(MNM, GPR, SDXB), "llgc", r1, dh2, dl2, x2, b2);
2559
2560 return emit_RXY(p, 0xe30000000090ULL, r1, x2, b2, dl2, dh2);
2561}
2562
2563
sewardj9d31dfd2011-03-15 12:36:44 +00002564static UChar *
sewardj2019a972011-03-07 16:04:07 +00002565s390_emit_LLHR(UChar *p, UChar r1, UChar r2)
2566{
sewardj652b56a2011-04-13 15:38:17 +00002567 vassert(s390_host_has_eimm);
2568
sewardj7ee97522011-05-09 21:45:04 +00002569 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002570 s390_disasm(ENC3(MNM, GPR, GPR), "llhr", r1, r2);
2571
2572 return emit_RRE(p, 0xb9950000, r1, r2);
2573}
2574
2575
sewardj9d31dfd2011-03-15 12:36:44 +00002576static UChar *
sewardj2019a972011-03-07 16:04:07 +00002577s390_emit_LLGHR(UChar *p, UChar r1, UChar r2)
2578{
sewardj652b56a2011-04-13 15:38:17 +00002579 vassert(s390_host_has_eimm);
2580
sewardj7ee97522011-05-09 21:45:04 +00002581 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002582 s390_disasm(ENC3(MNM, GPR, GPR), "llghr", r1, r2);
2583
2584 return emit_RRE(p, 0xb9850000, r1, r2);
2585}
2586
2587
sewardj9d31dfd2011-03-15 12:36:44 +00002588static UChar *
sewardj2019a972011-03-07 16:04:07 +00002589s390_emit_LLH(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2590{
sewardj652b56a2011-04-13 15:38:17 +00002591 vassert(s390_host_has_eimm);
2592
sewardj7ee97522011-05-09 21:45:04 +00002593 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002594 s390_disasm(ENC3(MNM, GPR, SDXB), "llh", r1, dh2, dl2, x2, b2);
2595
2596 return emit_RXY(p, 0xe30000000095ULL, r1, x2, b2, dl2, dh2);
2597}
2598
2599
sewardj9d31dfd2011-03-15 12:36:44 +00002600static UChar *
sewardj2019a972011-03-07 16:04:07 +00002601s390_emit_LLGH(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2602{
sewardj7ee97522011-05-09 21:45:04 +00002603 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002604 s390_disasm(ENC3(MNM, GPR, SDXB), "llgh", r1, dh2, dl2, x2, b2);
2605
2606 return emit_RXY(p, 0xe30000000091ULL, r1, x2, b2, dl2, dh2);
2607}
2608
2609
sewardj9d31dfd2011-03-15 12:36:44 +00002610static UChar *
sewardj2019a972011-03-07 16:04:07 +00002611s390_emit_LLILF(UChar *p, UChar r1, UInt i2)
2612{
sewardj652b56a2011-04-13 15:38:17 +00002613 vassert(s390_host_has_eimm);
2614
sewardj7ee97522011-05-09 21:45:04 +00002615 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002616 s390_disasm(ENC3(MNM, GPR, UINT), "llilf", r1, i2);
2617
2618 return emit_RIL(p, 0xc00f00000000ULL, r1, i2);
2619}
2620
2621
sewardj9d31dfd2011-03-15 12:36:44 +00002622static UChar *
sewardj2019a972011-03-07 16:04:07 +00002623s390_emit_LLILH(UChar *p, UChar r1, UShort i2)
2624{
sewardj7ee97522011-05-09 21:45:04 +00002625 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002626 s390_disasm(ENC3(MNM, GPR, UINT), "llilh", r1, i2);
2627
2628 return emit_RI(p, 0xa50e0000, r1, i2);
2629}
2630
2631
sewardj9d31dfd2011-03-15 12:36:44 +00002632static UChar *
sewardj2019a972011-03-07 16:04:07 +00002633s390_emit_LLILL(UChar *p, UChar r1, UShort i2)
2634{
sewardj7ee97522011-05-09 21:45:04 +00002635 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002636 s390_disasm(ENC3(MNM, GPR, UINT), "llill", r1, i2);
2637
2638 return emit_RI(p, 0xa50f0000, r1, i2);
2639}
2640
2641
sewardj9d31dfd2011-03-15 12:36:44 +00002642static UChar *
sewardj2019a972011-03-07 16:04:07 +00002643s390_emit_MR(UChar *p, UChar r1, UChar r2)
2644{
sewardj7ee97522011-05-09 21:45:04 +00002645 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002646 s390_disasm(ENC3(MNM, GPR, GPR), "mr", r1, r2);
2647
2648 return emit_RR(p, 0x1c00, r1, r2);
2649}
2650
2651
sewardj9d31dfd2011-03-15 12:36:44 +00002652static UChar *
sewardj2019a972011-03-07 16:04:07 +00002653s390_emit_M(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2654{
sewardj7ee97522011-05-09 21:45:04 +00002655 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002656 s390_disasm(ENC3(MNM, GPR, UDXB), "m", r1, d2, x2, b2);
2657
2658 return emit_RX(p, 0x5c000000, r1, x2, b2, d2);
2659}
2660
2661
sewardj9d31dfd2011-03-15 12:36:44 +00002662static UChar *
sewardj2019a972011-03-07 16:04:07 +00002663s390_emit_MFY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2664{
sewardj652b56a2011-04-13 15:38:17 +00002665 vassert(s390_host_has_gie);
2666
sewardj7ee97522011-05-09 21:45:04 +00002667 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002668 s390_disasm(ENC3(MNM, GPR, SDXB), "mfy", r1, dh2, dl2, x2, b2);
2669
2670 return emit_RXY(p, 0xe3000000005cULL, r1, x2, b2, dl2, dh2);
2671}
2672
2673
sewardj9d31dfd2011-03-15 12:36:44 +00002674static UChar *
sewardj2019a972011-03-07 16:04:07 +00002675s390_emit_MH(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2676{
sewardj7ee97522011-05-09 21:45:04 +00002677 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002678 s390_disasm(ENC3(MNM, GPR, UDXB), "mh", r1, d2, x2, b2);
2679
2680 return emit_RX(p, 0x4c000000, r1, x2, b2, d2);
2681}
2682
2683
sewardj9d31dfd2011-03-15 12:36:44 +00002684static UChar *
sewardj2019a972011-03-07 16:04:07 +00002685s390_emit_MHY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2686{
sewardj652b56a2011-04-13 15:38:17 +00002687 vassert(s390_host_has_gie);
2688
sewardj7ee97522011-05-09 21:45:04 +00002689 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002690 s390_disasm(ENC3(MNM, GPR, SDXB), "mhy", r1, dh2, dl2, x2, b2);
2691
2692 return emit_RXY(p, 0xe3000000007cULL, r1, x2, b2, dl2, dh2);
2693}
2694
2695
sewardj9d31dfd2011-03-15 12:36:44 +00002696static UChar *
sewardj2019a972011-03-07 16:04:07 +00002697s390_emit_MHI(UChar *p, UChar r1, UShort i2)
2698{
sewardj7ee97522011-05-09 21:45:04 +00002699 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002700 s390_disasm(ENC3(MNM, GPR, INT), "mhi", r1, (Int)(Short)i2);
2701
2702 return emit_RI(p, 0xa70c0000, r1, i2);
2703}
2704
2705
sewardj9d31dfd2011-03-15 12:36:44 +00002706static UChar *
sewardj2019a972011-03-07 16:04:07 +00002707s390_emit_MLR(UChar *p, UChar r1, UChar r2)
2708{
sewardj7ee97522011-05-09 21:45:04 +00002709 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002710 s390_disasm(ENC3(MNM, GPR, GPR), "mlr", r1, r2);
2711
2712 return emit_RRE(p, 0xb9960000, r1, r2);
2713}
2714
2715
sewardj9d31dfd2011-03-15 12:36:44 +00002716static UChar *
sewardj2019a972011-03-07 16:04:07 +00002717s390_emit_MLGR(UChar *p, UChar r1, UChar r2)
2718{
sewardj7ee97522011-05-09 21:45:04 +00002719 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002720 s390_disasm(ENC3(MNM, GPR, GPR), "mlgr", r1, r2);
2721
2722 return emit_RRE(p, 0xb9860000, r1, r2);
2723}
2724
2725
sewardj9d31dfd2011-03-15 12:36:44 +00002726static UChar *
sewardj2019a972011-03-07 16:04:07 +00002727s390_emit_ML(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2728{
sewardj7ee97522011-05-09 21:45:04 +00002729 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002730 s390_disasm(ENC3(MNM, GPR, SDXB), "ml", r1, dh2, dl2, x2, b2);
2731
2732 return emit_RXY(p, 0xe30000000096ULL, r1, x2, b2, dl2, dh2);
2733}
2734
2735
sewardj9d31dfd2011-03-15 12:36:44 +00002736static UChar *
sewardj2019a972011-03-07 16:04:07 +00002737s390_emit_MLG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2738{
sewardj7ee97522011-05-09 21:45:04 +00002739 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002740 s390_disasm(ENC3(MNM, GPR, SDXB), "mlg", r1, dh2, dl2, x2, b2);
2741
2742 return emit_RXY(p, 0xe30000000086ULL, r1, x2, b2, dl2, dh2);
2743}
2744
2745
sewardj9d31dfd2011-03-15 12:36:44 +00002746static UChar *
sewardj2019a972011-03-07 16:04:07 +00002747s390_emit_MSR(UChar *p, UChar r1, UChar r2)
2748{
sewardj7ee97522011-05-09 21:45:04 +00002749 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002750 s390_disasm(ENC3(MNM, GPR, GPR), "msr", r1, r2);
2751
2752 return emit_RRE(p, 0xb2520000, r1, r2);
2753}
2754
2755
sewardj9d31dfd2011-03-15 12:36:44 +00002756static UChar *
sewardj2019a972011-03-07 16:04:07 +00002757s390_emit_MSGR(UChar *p, UChar r1, UChar r2)
2758{
sewardj7ee97522011-05-09 21:45:04 +00002759 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002760 s390_disasm(ENC3(MNM, GPR, GPR), "msgr", r1, r2);
2761
2762 return emit_RRE(p, 0xb90c0000, r1, r2);
2763}
2764
2765
sewardj9d31dfd2011-03-15 12:36:44 +00002766static UChar *
sewardj2019a972011-03-07 16:04:07 +00002767s390_emit_MS(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2768{
sewardj7ee97522011-05-09 21:45:04 +00002769 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002770 s390_disasm(ENC3(MNM, GPR, UDXB), "ms", r1, d2, x2, b2);
2771
2772 return emit_RX(p, 0x71000000, r1, x2, b2, d2);
2773}
2774
2775
sewardj9d31dfd2011-03-15 12:36:44 +00002776static UChar *
sewardj2019a972011-03-07 16:04:07 +00002777s390_emit_MSY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2778{
sewardj7ee97522011-05-09 21:45:04 +00002779 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002780 s390_disasm(ENC3(MNM, GPR, SDXB), "msy", r1, dh2, dl2, x2, b2);
2781
2782 return emit_RXY(p, 0xe30000000051ULL, r1, x2, b2, dl2, dh2);
2783}
2784
2785
sewardj9d31dfd2011-03-15 12:36:44 +00002786static UChar *
sewardj2019a972011-03-07 16:04:07 +00002787s390_emit_MSG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2788{
sewardj7ee97522011-05-09 21:45:04 +00002789 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002790 s390_disasm(ENC3(MNM, GPR, SDXB), "msg", r1, dh2, dl2, x2, b2);
2791
2792 return emit_RXY(p, 0xe3000000000cULL, r1, x2, b2, dl2, dh2);
2793}
2794
2795
sewardj9d31dfd2011-03-15 12:36:44 +00002796static UChar *
sewardj2019a972011-03-07 16:04:07 +00002797s390_emit_MSFI(UChar *p, UChar r1, UInt i2)
2798{
sewardj652b56a2011-04-13 15:38:17 +00002799 vassert(s390_host_has_gie);
2800
sewardj7ee97522011-05-09 21:45:04 +00002801 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002802 s390_disasm(ENC3(MNM, GPR, INT), "msfi", r1, i2);
2803
2804 return emit_RIL(p, 0xc20100000000ULL, r1, i2);
2805}
2806
2807
sewardj9d31dfd2011-03-15 12:36:44 +00002808static UChar *
sewardj2019a972011-03-07 16:04:07 +00002809s390_emit_MSGFI(UChar *p, UChar r1, UInt i2)
2810{
sewardj652b56a2011-04-13 15:38:17 +00002811 vassert(s390_host_has_gie);
2812
sewardj7ee97522011-05-09 21:45:04 +00002813 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002814 s390_disasm(ENC3(MNM, GPR, INT), "msgfi", r1, i2);
2815
2816 return emit_RIL(p, 0xc20000000000ULL, r1, i2);
2817}
2818
2819
sewardj9d31dfd2011-03-15 12:36:44 +00002820static UChar *
floriancec3a8a2013-02-02 00:16:58 +00002821s390_emit_MVC(UChar *p, UInt l, UChar b1, UShort d1, UChar b2, UShort d2)
2822{
2823 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
2824 s390_disasm(ENC3(MNM, UDLB, UDXB), "mvc", d1, l, b1, d2, 0, b2);
2825
2826 return emit_SSa(p, 0xd20000000000ULL, l, b1, d1, b2, d2);
2827}
2828
2829
2830static UChar *
florianb93348d2012-12-27 00:59:43 +00002831s390_emit_MVI(UChar *p, UChar i2, UChar b1, UShort d1)
2832{
2833 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
florian0470c5d2013-03-03 03:21:57 +00002834 s390_disasm(ENC3(MNM, UDXB, INT), "mvi", d1, 0, b1, i2);
florianb93348d2012-12-27 00:59:43 +00002835
2836 return emit_SI(p, 0x92000000, i2, b1, d1);
2837}
2838
2839
2840static UChar *
2841s390_emit_MVHHI(UChar *p, UChar b1, UShort d1, UShort i2)
2842{
florian49adf862014-12-06 20:24:08 +00002843 vassert(s390_host_has_gie);
2844
florianb93348d2012-12-27 00:59:43 +00002845 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
florian0470c5d2013-03-03 03:21:57 +00002846 s390_disasm(ENC3(MNM, UDXB, INT), "mvhhi", d1, 0, b1, i2);
florianb93348d2012-12-27 00:59:43 +00002847
2848 return emit_SIL(p, 0xe54400000000ULL, b1, d1, i2);
2849}
2850
2851
2852static UChar *
2853s390_emit_MVHI(UChar *p, UChar b1, UShort d1, UShort i2)
2854{
florian49adf862014-12-06 20:24:08 +00002855 vassert(s390_host_has_gie);
2856
florianb93348d2012-12-27 00:59:43 +00002857 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
florian0470c5d2013-03-03 03:21:57 +00002858 s390_disasm(ENC3(MNM, UDXB, INT), "mvhi", d1, 0, b1, i2);
florianb93348d2012-12-27 00:59:43 +00002859
2860 return emit_SIL(p, 0xe54c00000000ULL, b1, d1, i2);
2861}
2862
2863
2864static UChar *
2865s390_emit_MVGHI(UChar *p, UChar b1, UShort d1, UShort i2)
2866{
florian49adf862014-12-06 20:24:08 +00002867 vassert(s390_host_has_gie);
2868
florianb93348d2012-12-27 00:59:43 +00002869 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
florian0470c5d2013-03-03 03:21:57 +00002870 s390_disasm(ENC3(MNM, UDXB, INT), "mvghi", d1, 0, b1, i2);
florianb93348d2012-12-27 00:59:43 +00002871
2872 return emit_SIL(p, 0xe54800000000ULL, b1, d1, i2);
2873}
2874
2875
2876static UChar *
sewardj2019a972011-03-07 16:04:07 +00002877s390_emit_OR(UChar *p, UChar r1, UChar r2)
2878{
sewardj7ee97522011-05-09 21:45:04 +00002879 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002880 s390_disasm(ENC3(MNM, GPR, GPR), "or", r1, r2);
2881
2882 return emit_RR(p, 0x1600, r1, r2);
2883}
2884
2885
sewardj9d31dfd2011-03-15 12:36:44 +00002886static UChar *
sewardj2019a972011-03-07 16:04:07 +00002887s390_emit_OGR(UChar *p, UChar r1, UChar r2)
2888{
sewardj7ee97522011-05-09 21:45:04 +00002889 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002890 s390_disasm(ENC3(MNM, GPR, GPR), "ogr", r1, r2);
2891
2892 return emit_RRE(p, 0xb9810000, r1, r2);
2893}
2894
2895
sewardj9d31dfd2011-03-15 12:36:44 +00002896static UChar *
sewardj2019a972011-03-07 16:04:07 +00002897s390_emit_O(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
2898{
sewardj7ee97522011-05-09 21:45:04 +00002899 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002900 s390_disasm(ENC3(MNM, GPR, UDXB), "o", r1, d2, x2, b2);
2901
2902 return emit_RX(p, 0x56000000, r1, x2, b2, d2);
2903}
2904
2905
sewardj9d31dfd2011-03-15 12:36:44 +00002906static UChar *
sewardj2019a972011-03-07 16:04:07 +00002907s390_emit_OY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2908{
sewardj7ee97522011-05-09 21:45:04 +00002909 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002910 s390_disasm(ENC3(MNM, GPR, SDXB), "oy", r1, dh2, dl2, x2, b2);
2911
2912 return emit_RXY(p, 0xe30000000056ULL, r1, x2, b2, dl2, dh2);
2913}
2914
2915
sewardj9d31dfd2011-03-15 12:36:44 +00002916static UChar *
sewardj2019a972011-03-07 16:04:07 +00002917s390_emit_OG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
2918{
sewardj7ee97522011-05-09 21:45:04 +00002919 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002920 s390_disasm(ENC3(MNM, GPR, SDXB), "og", r1, dh2, dl2, x2, b2);
2921
2922 return emit_RXY(p, 0xe30000000081ULL, r1, x2, b2, dl2, dh2);
2923}
2924
2925
sewardj9d31dfd2011-03-15 12:36:44 +00002926static UChar *
sewardj2019a972011-03-07 16:04:07 +00002927s390_emit_OIHF(UChar *p, UChar r1, UInt i2)
2928{
sewardj652b56a2011-04-13 15:38:17 +00002929 vassert(s390_host_has_eimm);
2930
sewardj7ee97522011-05-09 21:45:04 +00002931 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002932 s390_disasm(ENC3(MNM, GPR, UINT), "oihf", r1, i2);
2933
2934 return emit_RIL(p, 0xc00c00000000ULL, r1, i2);
2935}
2936
2937
sewardj9d31dfd2011-03-15 12:36:44 +00002938static UChar *
sewardj2019a972011-03-07 16:04:07 +00002939s390_emit_OILF(UChar *p, UChar r1, UInt i2)
2940{
sewardj652b56a2011-04-13 15:38:17 +00002941 vassert(s390_host_has_eimm);
2942
sewardj7ee97522011-05-09 21:45:04 +00002943 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002944 s390_disasm(ENC3(MNM, GPR, UINT), "oilf", r1, i2);
2945
2946 return emit_RIL(p, 0xc00d00000000ULL, r1, i2);
2947}
2948
2949
sewardj9d31dfd2011-03-15 12:36:44 +00002950static UChar *
sewardj2019a972011-03-07 16:04:07 +00002951s390_emit_OILL(UChar *p, UChar r1, UShort i2)
2952{
sewardj7ee97522011-05-09 21:45:04 +00002953 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002954 s390_disasm(ENC3(MNM, GPR, UINT), "oill", r1, i2);
2955
2956 return emit_RI(p, 0xa50b0000, r1, i2);
2957}
2958
2959
sewardj9d31dfd2011-03-15 12:36:44 +00002960static UChar *
sewardj3c49aaa2011-04-05 14:00:37 +00002961s390_emit_SLL(UChar *p, UChar r1, UChar b2, UShort d2)
sewardj2019a972011-03-07 16:04:07 +00002962{
sewardj7ee97522011-05-09 21:45:04 +00002963 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002964 s390_disasm(ENC3(MNM, GPR, UDXB), "sll", r1, d2, 0, b2);
2965
sewardj3c49aaa2011-04-05 14:00:37 +00002966 return emit_RS(p, 0x89000000, r1, 0, b2, d2);
sewardj2019a972011-03-07 16:04:07 +00002967}
2968
2969
sewardj9d31dfd2011-03-15 12:36:44 +00002970static UChar *
sewardj2019a972011-03-07 16:04:07 +00002971s390_emit_SLLG(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
2972{
sewardj7ee97522011-05-09 21:45:04 +00002973 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002974 s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "sllg", r1, r3, dh2, dl2, 0, b2);
2975
2976 return emit_RSY(p, 0xeb000000000dULL, r1, r3, b2, dl2, dh2);
2977}
2978
2979
sewardj9d31dfd2011-03-15 12:36:44 +00002980static UChar *
sewardj3c49aaa2011-04-05 14:00:37 +00002981s390_emit_SRA(UChar *p, UChar r1, UChar b2, UShort d2)
sewardj2019a972011-03-07 16:04:07 +00002982{
sewardj7ee97522011-05-09 21:45:04 +00002983 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002984 s390_disasm(ENC3(MNM, GPR, UDXB), "sra", r1, d2, 0, b2);
2985
sewardj3c49aaa2011-04-05 14:00:37 +00002986 return emit_RS(p, 0x8a000000, r1, 0, b2, d2);
sewardj2019a972011-03-07 16:04:07 +00002987}
2988
2989
sewardj9d31dfd2011-03-15 12:36:44 +00002990static UChar *
sewardj2019a972011-03-07 16:04:07 +00002991s390_emit_SRAG(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
2992{
sewardj7ee97522011-05-09 21:45:04 +00002993 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00002994 s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "srag", r1, r3, dh2, dl2, 0, b2);
2995
2996 return emit_RSY(p, 0xeb000000000aULL, r1, r3, b2, dl2, dh2);
2997}
2998
2999
sewardj9d31dfd2011-03-15 12:36:44 +00003000static UChar *
sewardj3c49aaa2011-04-05 14:00:37 +00003001s390_emit_SRL(UChar *p, UChar r1, UChar b2, UShort d2)
sewardj2019a972011-03-07 16:04:07 +00003002{
sewardj7ee97522011-05-09 21:45:04 +00003003 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003004 s390_disasm(ENC3(MNM, GPR, UDXB), "srl", r1, d2, 0, b2);
3005
sewardj3c49aaa2011-04-05 14:00:37 +00003006 return emit_RS(p, 0x88000000, r1, 0, b2, d2);
sewardj2019a972011-03-07 16:04:07 +00003007}
3008
3009
sewardj9d31dfd2011-03-15 12:36:44 +00003010static UChar *
sewardj2019a972011-03-07 16:04:07 +00003011s390_emit_SRLG(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
3012{
sewardj7ee97522011-05-09 21:45:04 +00003013 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003014 s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "srlg", r1, r3, dh2, dl2, 0, b2);
3015
3016 return emit_RSY(p, 0xeb000000000cULL, r1, r3, b2, dl2, dh2);
3017}
3018
3019
sewardj9d31dfd2011-03-15 12:36:44 +00003020static UChar *
sewardj2019a972011-03-07 16:04:07 +00003021s390_emit_ST(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
3022{
sewardj7ee97522011-05-09 21:45:04 +00003023 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003024 s390_disasm(ENC3(MNM, GPR, UDXB), "st", r1, d2, x2, b2);
3025
3026 return emit_RX(p, 0x50000000, r1, x2, b2, d2);
3027}
3028
3029
sewardj9d31dfd2011-03-15 12:36:44 +00003030static UChar *
sewardj2019a972011-03-07 16:04:07 +00003031s390_emit_STY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3032{
sewardj7ee97522011-05-09 21:45:04 +00003033 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003034 s390_disasm(ENC3(MNM, GPR, SDXB), "sty", r1, dh2, dl2, x2, b2);
3035
3036 return emit_RXY(p, 0xe30000000050ULL, r1, x2, b2, dl2, dh2);
3037}
3038
3039
sewardj9d31dfd2011-03-15 12:36:44 +00003040static UChar *
sewardj2019a972011-03-07 16:04:07 +00003041s390_emit_STG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3042{
sewardj7ee97522011-05-09 21:45:04 +00003043 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003044 s390_disasm(ENC3(MNM, GPR, SDXB), "stg", r1, dh2, dl2, x2, b2);
3045
3046 return emit_RXY(p, 0xe30000000024ULL, r1, x2, b2, dl2, dh2);
3047}
3048
3049
sewardj9d31dfd2011-03-15 12:36:44 +00003050static UChar *
sewardj2019a972011-03-07 16:04:07 +00003051s390_emit_STC(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
3052{
sewardj7ee97522011-05-09 21:45:04 +00003053 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003054 s390_disasm(ENC3(MNM, GPR, UDXB), "stc", r1, d2, x2, b2);
3055
3056 return emit_RX(p, 0x42000000, r1, x2, b2, d2);
3057}
3058
3059
sewardj9d31dfd2011-03-15 12:36:44 +00003060static UChar *
sewardj2019a972011-03-07 16:04:07 +00003061s390_emit_STCY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3062{
sewardj7ee97522011-05-09 21:45:04 +00003063 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003064 s390_disasm(ENC3(MNM, GPR, SDXB), "stcy", r1, dh2, dl2, x2, b2);
3065
3066 return emit_RXY(p, 0xe30000000072ULL, r1, x2, b2, dl2, dh2);
3067}
3068
3069
sewardj9d31dfd2011-03-15 12:36:44 +00003070static UChar *
sewardj2019a972011-03-07 16:04:07 +00003071s390_emit_STH(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
3072{
sewardj7ee97522011-05-09 21:45:04 +00003073 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003074 s390_disasm(ENC3(MNM, GPR, UDXB), "sth", r1, d2, x2, b2);
3075
3076 return emit_RX(p, 0x40000000, r1, x2, b2, d2);
3077}
3078
3079
sewardj9d31dfd2011-03-15 12:36:44 +00003080static UChar *
sewardj2019a972011-03-07 16:04:07 +00003081s390_emit_STHY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3082{
sewardj7ee97522011-05-09 21:45:04 +00003083 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003084 s390_disasm(ENC3(MNM, GPR, SDXB), "sthy", r1, dh2, dl2, x2, b2);
3085
3086 return emit_RXY(p, 0xe30000000070ULL, r1, x2, b2, dl2, dh2);
3087}
3088
3089
sewardj9d31dfd2011-03-15 12:36:44 +00003090static UChar *
sewardj2019a972011-03-07 16:04:07 +00003091s390_emit_SR(UChar *p, UChar r1, UChar r2)
3092{
sewardj7ee97522011-05-09 21:45:04 +00003093 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003094 s390_disasm(ENC3(MNM, GPR, GPR), "sr", r1, r2);
3095
3096 return emit_RR(p, 0x1b00, r1, r2);
3097}
3098
3099
sewardj9d31dfd2011-03-15 12:36:44 +00003100static UChar *
sewardj2019a972011-03-07 16:04:07 +00003101s390_emit_SGR(UChar *p, UChar r1, UChar r2)
3102{
sewardj7ee97522011-05-09 21:45:04 +00003103 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003104 s390_disasm(ENC3(MNM, GPR, GPR), "sgr", r1, r2);
3105
3106 return emit_RRE(p, 0xb9090000, r1, r2);
3107}
3108
3109
sewardj9d31dfd2011-03-15 12:36:44 +00003110static UChar *
sewardj2019a972011-03-07 16:04:07 +00003111s390_emit_S(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
3112{
sewardj7ee97522011-05-09 21:45:04 +00003113 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003114 s390_disasm(ENC3(MNM, GPR, UDXB), "s", r1, d2, x2, b2);
3115
3116 return emit_RX(p, 0x5b000000, r1, x2, b2, d2);
3117}
3118
3119
sewardj9d31dfd2011-03-15 12:36:44 +00003120static UChar *
sewardj2019a972011-03-07 16:04:07 +00003121s390_emit_SY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3122{
sewardj7ee97522011-05-09 21:45:04 +00003123 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003124 s390_disasm(ENC3(MNM, GPR, SDXB), "sy", r1, dh2, dl2, x2, b2);
3125
3126 return emit_RXY(p, 0xe3000000005bULL, r1, x2, b2, dl2, dh2);
3127}
3128
3129
sewardj9d31dfd2011-03-15 12:36:44 +00003130static UChar *
sewardj2019a972011-03-07 16:04:07 +00003131s390_emit_SG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3132{
sewardj7ee97522011-05-09 21:45:04 +00003133 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003134 s390_disasm(ENC3(MNM, GPR, SDXB), "sg", r1, dh2, dl2, x2, b2);
3135
3136 return emit_RXY(p, 0xe30000000009ULL, r1, x2, b2, dl2, dh2);
3137}
3138
3139
sewardj9d31dfd2011-03-15 12:36:44 +00003140static UChar *
sewardj2019a972011-03-07 16:04:07 +00003141s390_emit_SH(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
3142{
sewardj7ee97522011-05-09 21:45:04 +00003143 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003144 s390_disasm(ENC3(MNM, GPR, UDXB), "sh", r1, d2, x2, b2);
3145
3146 return emit_RX(p, 0x4b000000, r1, x2, b2, d2);
3147}
3148
3149
sewardj9d31dfd2011-03-15 12:36:44 +00003150static UChar *
sewardj2019a972011-03-07 16:04:07 +00003151s390_emit_SHY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3152{
sewardj7ee97522011-05-09 21:45:04 +00003153 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003154 s390_disasm(ENC3(MNM, GPR, SDXB), "shy", r1, dh2, dl2, x2, b2);
3155
3156 return emit_RXY(p, 0xe3000000007bULL, r1, x2, b2, dl2, dh2);
3157}
3158
3159
sewardj9d31dfd2011-03-15 12:36:44 +00003160static UChar *
sewardj2019a972011-03-07 16:04:07 +00003161s390_emit_SLFI(UChar *p, UChar r1, UInt i2)
3162{
sewardj652b56a2011-04-13 15:38:17 +00003163 vassert(s390_host_has_eimm);
3164
sewardj7ee97522011-05-09 21:45:04 +00003165 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003166 s390_disasm(ENC3(MNM, GPR, UINT), "slfi", r1, i2);
3167
3168 return emit_RIL(p, 0xc20500000000ULL, r1, i2);
3169}
3170
3171
sewardj9d31dfd2011-03-15 12:36:44 +00003172static UChar *
sewardjb13a92a2011-04-13 14:44:29 +00003173s390_emit_SLGFI(UChar *p, UChar r1, UInt i2)
3174{
sewardj7ee97522011-05-09 21:45:04 +00003175 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardjb13a92a2011-04-13 14:44:29 +00003176 s390_disasm(ENC3(MNM, GPR, UINT), "slgfi", r1, i2);
3177
3178 return emit_RIL(p, 0xc20400000000ULL, r1, i2);
3179}
3180
3181
3182static UChar *
sewardj2019a972011-03-07 16:04:07 +00003183s390_emit_LDR(UChar *p, UChar r1, UChar r2)
3184{
sewardj7ee97522011-05-09 21:45:04 +00003185 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003186 s390_disasm(ENC3(MNM, FPR, FPR), "ldr", r1, r2);
3187
3188 return emit_RR(p, 0x2800, r1, r2);
3189}
3190
3191
sewardj9d31dfd2011-03-15 12:36:44 +00003192static UChar *
sewardj2019a972011-03-07 16:04:07 +00003193s390_emit_LE(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
3194{
sewardj7ee97522011-05-09 21:45:04 +00003195 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003196 s390_disasm(ENC3(MNM, FPR, UDXB), "le", r1, d2, x2, b2);
3197
3198 return emit_RX(p, 0x78000000, r1, x2, b2, d2);
3199}
3200
3201
sewardj9d31dfd2011-03-15 12:36:44 +00003202static UChar *
sewardj2019a972011-03-07 16:04:07 +00003203s390_emit_LD(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
3204{
sewardj7ee97522011-05-09 21:45:04 +00003205 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003206 s390_disasm(ENC3(MNM, FPR, UDXB), "ld", r1, d2, x2, b2);
3207
3208 return emit_RX(p, 0x68000000, r1, x2, b2, d2);
3209}
3210
3211
sewardj9d31dfd2011-03-15 12:36:44 +00003212static UChar *
sewardj2019a972011-03-07 16:04:07 +00003213s390_emit_LEY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3214{
sewardj7ee97522011-05-09 21:45:04 +00003215 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003216 s390_disasm(ENC3(MNM, FPR, SDXB), "ley", r1, dh2, dl2, x2, b2);
3217
3218 return emit_RXY(p, 0xed0000000064ULL, r1, x2, b2, dl2, dh2);
3219}
3220
3221
sewardj9d31dfd2011-03-15 12:36:44 +00003222static UChar *
sewardj2019a972011-03-07 16:04:07 +00003223s390_emit_LDY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3224{
sewardj7ee97522011-05-09 21:45:04 +00003225 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003226 s390_disasm(ENC3(MNM, FPR, SDXB), "ldy", r1, dh2, dl2, x2, b2);
3227
3228 return emit_RXY(p, 0xed0000000065ULL, r1, x2, b2, dl2, dh2);
3229}
3230
3231
sewardj9d31dfd2011-03-15 12:36:44 +00003232static UChar *
sewardj2019a972011-03-07 16:04:07 +00003233s390_emit_LFPC(UChar *p, UChar b2, UShort d2)
3234{
sewardj7ee97522011-05-09 21:45:04 +00003235 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003236 s390_disasm(ENC2(MNM, UDXB), "lfpc", d2, 0, b2);
3237
3238 return emit_S(p, 0xb29d0000, b2, d2);
3239}
3240
3241
sewardj9d31dfd2011-03-15 12:36:44 +00003242static UChar *
sewardj2019a972011-03-07 16:04:07 +00003243s390_emit_LDGR(UChar *p, UChar r1, UChar r2)
3244{
sewardjd07b8562011-04-27 11:58:22 +00003245 vassert(s390_host_has_fgx);
3246
sewardj7ee97522011-05-09 21:45:04 +00003247 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003248 s390_disasm(ENC3(MNM, FPR, GPR), "ldgr", r1, r2);
3249
3250 return emit_RRE(p, 0xb3c10000, r1, r2);
3251}
3252
3253
sewardj9d31dfd2011-03-15 12:36:44 +00003254static UChar *
sewardj2019a972011-03-07 16:04:07 +00003255s390_emit_LGDR(UChar *p, UChar r1, UChar r2)
3256{
sewardjd07b8562011-04-27 11:58:22 +00003257 vassert(s390_host_has_fgx);
3258
sewardj7ee97522011-05-09 21:45:04 +00003259 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003260 s390_disasm(ENC3(MNM, GPR, FPR), "lgdr", r1, r2);
3261
3262 return emit_RRE(p, 0xb3cd0000, r1, r2);
3263}
3264
3265
sewardj9d31dfd2011-03-15 12:36:44 +00003266static UChar *
sewardj2019a972011-03-07 16:04:07 +00003267s390_emit_LZER(UChar *p, UChar r1, UChar r2)
3268{
sewardj7ee97522011-05-09 21:45:04 +00003269 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003270 s390_disasm(ENC2(MNM, FPR), "lzer", r1);
3271
3272 return emit_RRE(p, 0xb3740000, r1, r2);
3273}
3274
3275
sewardj9d31dfd2011-03-15 12:36:44 +00003276static UChar *
sewardj2019a972011-03-07 16:04:07 +00003277s390_emit_LZDR(UChar *p, UChar r1, UChar r2)
3278{
sewardj7ee97522011-05-09 21:45:04 +00003279 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003280 s390_disasm(ENC2(MNM, FPR), "lzdr", r1);
3281
3282 return emit_RRE(p, 0xb3750000, r1, r2);
3283}
3284
3285
sewardj9d31dfd2011-03-15 12:36:44 +00003286static UChar *
florian6d8e26e2012-09-12 19:52:16 +00003287s390_emit_SFPC(UChar *p, UChar r1)
sewardj2019a972011-03-07 16:04:07 +00003288{
sewardj7ee97522011-05-09 21:45:04 +00003289 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003290 s390_disasm(ENC2(MNM, GPR), "sfpc", r1);
3291
florian6d8e26e2012-09-12 19:52:16 +00003292 return emit_RRE(p, 0xb3840000, r1, 0);
sewardj2019a972011-03-07 16:04:07 +00003293}
3294
3295
sewardj9d31dfd2011-03-15 12:36:44 +00003296static UChar *
sewardj2019a972011-03-07 16:04:07 +00003297s390_emit_STE(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
3298{
sewardj7ee97522011-05-09 21:45:04 +00003299 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003300 s390_disasm(ENC3(MNM, FPR, UDXB), "ste", r1, d2, x2, b2);
3301
3302 return emit_RX(p, 0x70000000, r1, x2, b2, d2);
3303}
3304
3305
sewardj9d31dfd2011-03-15 12:36:44 +00003306static UChar *
sewardj2019a972011-03-07 16:04:07 +00003307s390_emit_STD(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2)
3308{
sewardj7ee97522011-05-09 21:45:04 +00003309 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003310 s390_disasm(ENC3(MNM, FPR, UDXB), "std", r1, d2, x2, b2);
3311
3312 return emit_RX(p, 0x60000000, r1, x2, b2, d2);
3313}
3314
3315
sewardj9d31dfd2011-03-15 12:36:44 +00003316static UChar *
sewardj2019a972011-03-07 16:04:07 +00003317s390_emit_STEY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3318{
sewardj7ee97522011-05-09 21:45:04 +00003319 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003320 s390_disasm(ENC3(MNM, FPR, SDXB), "stey", r1, dh2, dl2, x2, b2);
3321
3322 return emit_RXY(p, 0xed0000000066ULL, r1, x2, b2, dl2, dh2);
3323}
3324
3325
sewardj9d31dfd2011-03-15 12:36:44 +00003326static UChar *
sewardj2019a972011-03-07 16:04:07 +00003327s390_emit_STDY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
3328{
sewardj7ee97522011-05-09 21:45:04 +00003329 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003330 s390_disasm(ENC3(MNM, FPR, SDXB), "stdy", r1, dh2, dl2, x2, b2);
3331
3332 return emit_RXY(p, 0xed0000000067ULL, r1, x2, b2, dl2, dh2);
3333}
3334
3335
sewardj9d31dfd2011-03-15 12:36:44 +00003336static UChar *
sewardj2019a972011-03-07 16:04:07 +00003337s390_emit_STFPC(UChar *p, UChar b2, UShort d2)
3338{
sewardj7ee97522011-05-09 21:45:04 +00003339 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003340 s390_disasm(ENC2(MNM, UDXB), "stfpc", d2, 0, b2);
3341
3342 return emit_S(p, 0xb29c0000, b2, d2);
3343}
3344
3345
sewardj9d31dfd2011-03-15 12:36:44 +00003346static UChar *
sewardj2019a972011-03-07 16:04:07 +00003347s390_emit_AEBR(UChar *p, UChar r1, UChar r2)
3348{
sewardj7ee97522011-05-09 21:45:04 +00003349 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003350 s390_disasm(ENC3(MNM, FPR, FPR), "aebr", r1, r2);
3351
3352 return emit_RRE(p, 0xb30a0000, r1, r2);
3353}
3354
3355
sewardj9d31dfd2011-03-15 12:36:44 +00003356static UChar *
sewardj2019a972011-03-07 16:04:07 +00003357s390_emit_ADBR(UChar *p, UChar r1, UChar r2)
3358{
sewardj7ee97522011-05-09 21:45:04 +00003359 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003360 s390_disasm(ENC3(MNM, FPR, FPR), "adbr", r1, r2);
3361
3362 return emit_RRE(p, 0xb31a0000, r1, r2);
3363}
3364
3365
sewardj9d31dfd2011-03-15 12:36:44 +00003366static UChar *
sewardj2019a972011-03-07 16:04:07 +00003367s390_emit_AXBR(UChar *p, UChar r1, UChar r2)
3368{
sewardj7ee97522011-05-09 21:45:04 +00003369 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003370 s390_disasm(ENC3(MNM, FPR, FPR), "axbr", r1, r2);
3371
3372 return emit_RRE(p, 0xb34a0000, r1, r2);
3373}
3374
3375
sewardj9d31dfd2011-03-15 12:36:44 +00003376static UChar *
sewardj2019a972011-03-07 16:04:07 +00003377s390_emit_CEBR(UChar *p, UChar r1, UChar r2)
3378{
sewardj7ee97522011-05-09 21:45:04 +00003379 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003380 s390_disasm(ENC3(MNM, FPR, FPR), "cebr", r1, r2);
3381
3382 return emit_RRE(p, 0xb3090000, r1, r2);
3383}
3384
3385
sewardj9d31dfd2011-03-15 12:36:44 +00003386static UChar *
sewardj2019a972011-03-07 16:04:07 +00003387s390_emit_CDBR(UChar *p, UChar r1, UChar r2)
3388{
sewardj7ee97522011-05-09 21:45:04 +00003389 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003390 s390_disasm(ENC3(MNM, FPR, FPR), "cdbr", r1, r2);
3391
3392 return emit_RRE(p, 0xb3190000, r1, r2);
3393}
3394
3395
sewardj9d31dfd2011-03-15 12:36:44 +00003396static UChar *
sewardj2019a972011-03-07 16:04:07 +00003397s390_emit_CXBR(UChar *p, UChar r1, UChar r2)
3398{
sewardj7ee97522011-05-09 21:45:04 +00003399 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003400 s390_disasm(ENC3(MNM, FPR, FPR), "cxbr", r1, r2);
3401
3402 return emit_RRE(p, 0xb3490000, r1, r2);
3403}
3404
3405
sewardj9d31dfd2011-03-15 12:36:44 +00003406static UChar *
florian8c3ccaf2012-09-09 18:18:25 +00003407s390_emit_CEFBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
sewardj2019a972011-03-07 16:04:07 +00003408{
florian8c3ccaf2012-09-09 18:18:25 +00003409 vassert(m4 == 0);
3410 vassert(m3 == 0 || s390_host_has_fpext);
sewardj2019a972011-03-07 16:04:07 +00003411
florian8c3ccaf2012-09-09 18:18:25 +00003412 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
3413 if (m3 == 0)
3414 s390_disasm(ENC3(MNM, FPR, GPR), "cefbr", r1, r2);
3415 else
3416 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT),
3417 "cefbra", r1, m3, r2, m4);
3418 }
3419
3420 return emit_RRF2(p, 0xb3940000, m3, m4, r1, r2);
sewardj2019a972011-03-07 16:04:07 +00003421}
3422
3423
sewardj9d31dfd2011-03-15 12:36:44 +00003424static UChar *
florian8c3ccaf2012-09-09 18:18:25 +00003425s390_emit_CDFBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
sewardj2019a972011-03-07 16:04:07 +00003426{
florian8c3ccaf2012-09-09 18:18:25 +00003427 vassert(m4 == 0);
3428 vassert(m3 == 0 || s390_host_has_fpext);
sewardj2019a972011-03-07 16:04:07 +00003429
florian8c3ccaf2012-09-09 18:18:25 +00003430 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
3431 if (m3 == 0)
3432 s390_disasm(ENC3(MNM, FPR, GPR), "cdfbr", r1, r2);
3433 else
3434 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT),
3435 "cdfbra", r1, m3, r2, m4);
3436 }
3437
3438 return emit_RRF2(p, 0xb3950000, m3, m4, r1, r2);
sewardj2019a972011-03-07 16:04:07 +00003439}
3440
3441
sewardj9d31dfd2011-03-15 12:36:44 +00003442static UChar *
florian8c3ccaf2012-09-09 18:18:25 +00003443s390_emit_CXFBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
sewardj2019a972011-03-07 16:04:07 +00003444{
florian8c3ccaf2012-09-09 18:18:25 +00003445 vassert(m4 == 0);
3446 vassert(m3 == 0 || s390_host_has_fpext);
sewardj2019a972011-03-07 16:04:07 +00003447
florian8c3ccaf2012-09-09 18:18:25 +00003448 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
3449 if (m3 == 0)
3450 s390_disasm(ENC3(MNM, FPR, GPR), "cxfbr", r1, r2);
3451 else
3452 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT),
3453 "cxfbra", r1, m3, r2, m4);
3454 }
3455
3456 return emit_RRF2(p, 0xb3960000, m3, m4, r1, r2);
sewardj2019a972011-03-07 16:04:07 +00003457}
3458
3459
sewardj9d31dfd2011-03-15 12:36:44 +00003460static UChar *
florian8c3ccaf2012-09-09 18:18:25 +00003461s390_emit_CEGBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
sewardj2019a972011-03-07 16:04:07 +00003462{
florian8c3ccaf2012-09-09 18:18:25 +00003463 vassert(m4 == 0);
3464 vassert(m3 == 0 || s390_host_has_fpext);
sewardj2019a972011-03-07 16:04:07 +00003465
florian8c3ccaf2012-09-09 18:18:25 +00003466 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
3467 if (m3 == 0)
3468 s390_disasm(ENC3(MNM, FPR, GPR), "cegbr", r1, r2);
3469 else
3470 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT),
3471 "cegbra", r1, m3, r2, m4);
3472 }
3473
3474 return emit_RRF2(p, 0xb3a40000, m3, m4, r1, r2);
sewardj2019a972011-03-07 16:04:07 +00003475}
3476
3477
sewardj9d31dfd2011-03-15 12:36:44 +00003478static UChar *
florian8c3ccaf2012-09-09 18:18:25 +00003479s390_emit_CDGBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
sewardj2019a972011-03-07 16:04:07 +00003480{
florian8c3ccaf2012-09-09 18:18:25 +00003481 vassert(m4 == 0);
3482 vassert(m3 == 0 || s390_host_has_fpext);
sewardj2019a972011-03-07 16:04:07 +00003483
florian8c3ccaf2012-09-09 18:18:25 +00003484 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
3485 if (m3 == 0)
3486 s390_disasm(ENC3(MNM, FPR, GPR), "cdgbr", r1, r2);
3487 else
3488 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT),
3489 "cdgbra", r1, m3, r2, m4);
3490 }
3491
3492 return emit_RRF2(p, 0xb3a50000, m3, m4, r1, r2);
sewardj2019a972011-03-07 16:04:07 +00003493}
3494
3495
sewardj9d31dfd2011-03-15 12:36:44 +00003496static UChar *
florian8c3ccaf2012-09-09 18:18:25 +00003497s390_emit_CXGBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
sewardj2019a972011-03-07 16:04:07 +00003498{
florian8c3ccaf2012-09-09 18:18:25 +00003499 vassert(m4 == 0);
3500 vassert(m3 == 0 || s390_host_has_fpext);
sewardj2019a972011-03-07 16:04:07 +00003501
florian8c3ccaf2012-09-09 18:18:25 +00003502 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
3503 if (m3 == 0)
3504 s390_disasm(ENC3(MNM, FPR, GPR), "cxgbr", r1, r2);
3505 else
3506 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT),
3507 "cxgbra", r1, m3, r2, m4);
3508 }
3509
3510 return emit_RRF2(p, 0xb3a60000, m3, m4, r1, r2);
sewardj2019a972011-03-07 16:04:07 +00003511}
3512
3513
sewardj9d31dfd2011-03-15 12:36:44 +00003514static UChar *
florian1c8f7ff2012-09-01 00:12:11 +00003515s390_emit_CELFBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
3516{
florian606dbeb2012-09-09 18:12:28 +00003517 vassert(m4 == 0);
3518 vassert(s390_host_has_fpext);
3519
florian1c8f7ff2012-09-01 00:12:11 +00003520 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3521 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "celfbr", r1, m3, r2, m4);
3522
3523 return emit_RRF2(p, 0xb3900000, m3, m4, r1, r2);
3524}
3525
3526
3527static UChar *
3528s390_emit_CDLFBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
3529{
florian606dbeb2012-09-09 18:12:28 +00003530 vassert(m4 == 0);
3531 vassert(s390_host_has_fpext);
3532
florian1c8f7ff2012-09-01 00:12:11 +00003533 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3534 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cdlfbr", r1, m3, r2, m4);
3535
3536 return emit_RRF2(p, 0xb3910000, m3, m4, r1, r2);
3537}
3538
3539
3540static UChar *
3541s390_emit_CXLFBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
3542{
florian606dbeb2012-09-09 18:12:28 +00003543 vassert(m4 == 0);
3544 vassert(s390_host_has_fpext);
3545
florian1c8f7ff2012-09-01 00:12:11 +00003546 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3547 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cxlfbr", r1, m3, r2, m4);
3548
3549 return emit_RRF2(p, 0xb3920000, m3, m4, r1, r2);
3550}
3551
3552
3553static UChar *
3554s390_emit_CELGBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
3555{
florian606dbeb2012-09-09 18:12:28 +00003556 vassert(m4 == 0);
3557 vassert(s390_host_has_fpext);
3558
florian1c8f7ff2012-09-01 00:12:11 +00003559 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3560 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "celgbr", r1, m3, r2, m4);
3561
3562 return emit_RRF2(p, 0xb3a00000, m3, m4, r1, r2);
3563}
3564
3565
3566static UChar *
3567s390_emit_CDLGBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
3568{
florian606dbeb2012-09-09 18:12:28 +00003569 vassert(m4 == 0);
3570 vassert(s390_host_has_fpext);
3571
florian1c8f7ff2012-09-01 00:12:11 +00003572 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3573 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cdlgbr", r1, m3, r2, m4);
3574
3575 return emit_RRF2(p, 0xb3a10000, m3, m4, r1, r2);
3576}
3577
3578
3579static UChar *
3580s390_emit_CXLGBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
3581{
florian606dbeb2012-09-09 18:12:28 +00003582 vassert(m4 == 0);
3583 vassert(s390_host_has_fpext);
3584
florian1c8f7ff2012-09-01 00:12:11 +00003585 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3586 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cxlgbr", r1, m3, r2, m4);
3587
3588 return emit_RRF2(p, 0xb3a20000, m3, m4, r1, r2);
3589}
3590
3591
3592static UChar *
3593s390_emit_CLFEBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
3594{
florian606dbeb2012-09-09 18:12:28 +00003595 vassert(m4 == 0);
3596 vassert(s390_host_has_fpext);
3597
florian1c8f7ff2012-09-01 00:12:11 +00003598 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3599 s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clfebr", r1, m3, r2, m4);
3600
3601 return emit_RRF2(p, 0xb39c0000, m3, m4, r1, r2);
3602}
3603
3604
3605static UChar *
3606s390_emit_CLFDBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
3607{
florian606dbeb2012-09-09 18:12:28 +00003608 vassert(m4 == 0);
3609 vassert(s390_host_has_fpext);
3610
florian1c8f7ff2012-09-01 00:12:11 +00003611 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3612 s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clfdbr", r1, m3, r2, m4);
3613
3614 return emit_RRF2(p, 0xb39d0000, m3, m4, r1, r2);
3615}
3616
3617
3618static UChar *
3619s390_emit_CLFXBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
3620{
florian606dbeb2012-09-09 18:12:28 +00003621 vassert(m4 == 0);
3622 vassert(s390_host_has_fpext);
3623
florian1c8f7ff2012-09-01 00:12:11 +00003624 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3625 s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clfxbr", r1, m3, r2, m4);
3626
3627 return emit_RRF2(p, 0xb39e0000, m3, m4, r1, r2);
3628}
3629
3630
3631static UChar *
3632s390_emit_CLGEBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
3633{
florian606dbeb2012-09-09 18:12:28 +00003634 vassert(m4 == 0);
3635 vassert(s390_host_has_fpext);
3636
florian1c8f7ff2012-09-01 00:12:11 +00003637 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3638 s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clgebr", r1, m3, r2, m4);
3639
3640 return emit_RRF2(p, 0xb3ac0000, m3, m4, r1, r2);
3641}
3642
3643
3644static UChar *
3645s390_emit_CLGDBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
3646{
florian606dbeb2012-09-09 18:12:28 +00003647 vassert(m4 == 0);
3648 vassert(s390_host_has_fpext);
3649
florian1c8f7ff2012-09-01 00:12:11 +00003650 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3651 s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clgdbr", r1, m3, r2, m4);
3652
3653 return emit_RRF2(p, 0xb3ad0000, m3, m4, r1, r2);
3654}
3655
3656
3657static UChar *
3658s390_emit_CLGXBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
3659{
florian606dbeb2012-09-09 18:12:28 +00003660 vassert(m4 == 0);
3661 vassert(s390_host_has_fpext);
3662
florian1c8f7ff2012-09-01 00:12:11 +00003663 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
3664 s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clgxbr", r1, m3, r2, m4);
3665
3666 return emit_RRF2(p, 0xb3ae0000, m3, m4, r1, r2);
3667}
3668
3669
3670static UChar *
sewardj2019a972011-03-07 16:04:07 +00003671s390_emit_CFEBR(UChar *p, UChar r3, UChar r1, UChar r2)
3672{
sewardj7ee97522011-05-09 21:45:04 +00003673 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003674 s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cfebr", r1, r3, r2);
3675
3676 return emit_RRF3(p, 0xb3980000, r3, r1, r2);
3677}
3678
3679
sewardj9d31dfd2011-03-15 12:36:44 +00003680static UChar *
sewardj2019a972011-03-07 16:04:07 +00003681s390_emit_CFDBR(UChar *p, UChar r3, UChar r1, UChar r2)
3682{
sewardj7ee97522011-05-09 21:45:04 +00003683 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003684 s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cfdbr", r1, r3, r2);
3685
3686 return emit_RRF3(p, 0xb3990000, r3, r1, r2);
3687}
3688
3689
sewardj9d31dfd2011-03-15 12:36:44 +00003690static UChar *
sewardj2019a972011-03-07 16:04:07 +00003691s390_emit_CFXBR(UChar *p, UChar r3, UChar r1, UChar r2)
3692{
sewardj7ee97522011-05-09 21:45:04 +00003693 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003694 s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cfxbr", r1, r3, r2);
3695
3696 return emit_RRF3(p, 0xb39a0000, r3, r1, r2);
3697}
3698
3699
sewardj9d31dfd2011-03-15 12:36:44 +00003700static UChar *
sewardj2019a972011-03-07 16:04:07 +00003701s390_emit_CGEBR(UChar *p, UChar r3, UChar r1, UChar r2)
3702{
sewardj7ee97522011-05-09 21:45:04 +00003703 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003704 s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cgebr", r1, r3, r2);
3705
3706 return emit_RRF3(p, 0xb3a80000, r3, r1, r2);
3707}
3708
3709
sewardj9d31dfd2011-03-15 12:36:44 +00003710static UChar *
sewardj2019a972011-03-07 16:04:07 +00003711s390_emit_CGDBR(UChar *p, UChar r3, UChar r1, UChar r2)
3712{
sewardj7ee97522011-05-09 21:45:04 +00003713 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003714 s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cgdbr", r1, r3, r2);
3715
3716 return emit_RRF3(p, 0xb3a90000, r3, r1, r2);
3717}
3718
3719
sewardj9d31dfd2011-03-15 12:36:44 +00003720static UChar *
sewardj2019a972011-03-07 16:04:07 +00003721s390_emit_CGXBR(UChar *p, UChar r3, UChar r1, UChar r2)
3722{
sewardj7ee97522011-05-09 21:45:04 +00003723 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003724 s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cgxbr", r1, r3, r2);
3725
3726 return emit_RRF3(p, 0xb3aa0000, r3, r1, r2);
3727}
3728
3729
sewardj9d31dfd2011-03-15 12:36:44 +00003730static UChar *
sewardj2019a972011-03-07 16:04:07 +00003731s390_emit_DEBR(UChar *p, UChar r1, UChar r2)
3732{
sewardj7ee97522011-05-09 21:45:04 +00003733 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003734 s390_disasm(ENC3(MNM, FPR, FPR), "debr", r1, r2);
3735
3736 return emit_RRE(p, 0xb30d0000, r1, r2);
3737}
3738
3739
sewardj9d31dfd2011-03-15 12:36:44 +00003740static UChar *
sewardj2019a972011-03-07 16:04:07 +00003741s390_emit_DDBR(UChar *p, UChar r1, UChar r2)
3742{
sewardj7ee97522011-05-09 21:45:04 +00003743 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003744 s390_disasm(ENC3(MNM, FPR, FPR), "ddbr", r1, r2);
3745
3746 return emit_RRE(p, 0xb31d0000, r1, r2);
3747}
3748
3749
sewardj9d31dfd2011-03-15 12:36:44 +00003750static UChar *
sewardj2019a972011-03-07 16:04:07 +00003751s390_emit_DXBR(UChar *p, UChar r1, UChar r2)
3752{
sewardj7ee97522011-05-09 21:45:04 +00003753 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003754 s390_disasm(ENC3(MNM, FPR, FPR), "dxbr", r1, r2);
3755
3756 return emit_RRE(p, 0xb34d0000, r1, r2);
3757}
3758
3759
sewardj9d31dfd2011-03-15 12:36:44 +00003760static UChar *
sewardj2019a972011-03-07 16:04:07 +00003761s390_emit_LCEBR(UChar *p, UChar r1, UChar r2)
3762{
sewardj7ee97522011-05-09 21:45:04 +00003763 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003764 s390_disasm(ENC3(MNM, FPR, FPR), "lcebr", r1, r2);
3765
3766 return emit_RRE(p, 0xb3030000, r1, r2);
3767}
3768
3769
sewardj9d31dfd2011-03-15 12:36:44 +00003770static UChar *
sewardj2019a972011-03-07 16:04:07 +00003771s390_emit_LCDBR(UChar *p, UChar r1, UChar r2)
3772{
sewardj7ee97522011-05-09 21:45:04 +00003773 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003774 s390_disasm(ENC3(MNM, FPR, FPR), "lcdbr", r1, r2);
3775
3776 return emit_RRE(p, 0xb3130000, r1, r2);
3777}
3778
3779
sewardj9d31dfd2011-03-15 12:36:44 +00003780static UChar *
sewardj2019a972011-03-07 16:04:07 +00003781s390_emit_LCXBR(UChar *p, UChar r1, UChar r2)
3782{
sewardj7ee97522011-05-09 21:45:04 +00003783 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003784 s390_disasm(ENC3(MNM, FPR, FPR), "lcxbr", r1, r2);
3785
3786 return emit_RRE(p, 0xb3430000, r1, r2);
3787}
3788
3789
sewardj9d31dfd2011-03-15 12:36:44 +00003790static UChar *
sewardj2019a972011-03-07 16:04:07 +00003791s390_emit_LDEBR(UChar *p, UChar r1, UChar r2)
3792{
sewardj7ee97522011-05-09 21:45:04 +00003793 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003794 s390_disasm(ENC3(MNM, FPR, FPR), "ldebr", r1, r2);
3795
3796 return emit_RRE(p, 0xb3040000, r1, r2);
3797}
3798
3799
sewardj9d31dfd2011-03-15 12:36:44 +00003800static UChar *
sewardj2019a972011-03-07 16:04:07 +00003801s390_emit_LXDBR(UChar *p, UChar r1, UChar r2)
3802{
sewardj7ee97522011-05-09 21:45:04 +00003803 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003804 s390_disasm(ENC3(MNM, FPR, FPR), "lxdbr", r1, r2);
3805
3806 return emit_RRE(p, 0xb3050000, r1, r2);
3807}
3808
3809
sewardj9d31dfd2011-03-15 12:36:44 +00003810static UChar *
sewardj2019a972011-03-07 16:04:07 +00003811s390_emit_LXEBR(UChar *p, UChar r1, UChar r2)
3812{
sewardj7ee97522011-05-09 21:45:04 +00003813 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003814 s390_disasm(ENC3(MNM, FPR, FPR), "lxebr", r1, r2);
3815
3816 return emit_RRE(p, 0xb3060000, r1, r2);
3817}
3818
3819
sewardj9d31dfd2011-03-15 12:36:44 +00003820static UChar *
sewardj2019a972011-03-07 16:04:07 +00003821s390_emit_LNEBR(UChar *p, UChar r1, UChar r2)
3822{
sewardj7ee97522011-05-09 21:45:04 +00003823 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003824 s390_disasm(ENC3(MNM, FPR, FPR), "lnebr", r1, r2);
3825
3826 return emit_RRE(p, 0xb3010000, r1, r2);
3827}
3828
3829
sewardj9d31dfd2011-03-15 12:36:44 +00003830static UChar *
sewardj2019a972011-03-07 16:04:07 +00003831s390_emit_LNDBR(UChar *p, UChar r1, UChar r2)
3832{
sewardj7ee97522011-05-09 21:45:04 +00003833 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003834 s390_disasm(ENC3(MNM, FPR, FPR), "lndbr", r1, r2);
3835
3836 return emit_RRE(p, 0xb3110000, r1, r2);
3837}
3838
3839
sewardj9d31dfd2011-03-15 12:36:44 +00003840static UChar *
sewardj2019a972011-03-07 16:04:07 +00003841s390_emit_LNXBR(UChar *p, UChar r1, UChar r2)
3842{
sewardj7ee97522011-05-09 21:45:04 +00003843 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003844 s390_disasm(ENC3(MNM, FPR, FPR), "lnxbr", r1, r2);
3845
3846 return emit_RRE(p, 0xb3410000, r1, r2);
3847}
3848
3849
sewardj9d31dfd2011-03-15 12:36:44 +00003850static UChar *
sewardj2019a972011-03-07 16:04:07 +00003851s390_emit_LPEBR(UChar *p, UChar r1, UChar r2)
3852{
sewardj7ee97522011-05-09 21:45:04 +00003853 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003854 s390_disasm(ENC3(MNM, FPR, FPR), "lpebr", r1, r2);
3855
3856 return emit_RRE(p, 0xb3000000, r1, r2);
3857}
3858
3859
sewardj9d31dfd2011-03-15 12:36:44 +00003860static UChar *
sewardj2019a972011-03-07 16:04:07 +00003861s390_emit_LPDBR(UChar *p, UChar r1, UChar r2)
3862{
sewardj7ee97522011-05-09 21:45:04 +00003863 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003864 s390_disasm(ENC3(MNM, FPR, FPR), "lpdbr", r1, r2);
3865
3866 return emit_RRE(p, 0xb3100000, r1, r2);
3867}
3868
3869
sewardj9d31dfd2011-03-15 12:36:44 +00003870static UChar *
sewardj2019a972011-03-07 16:04:07 +00003871s390_emit_LPXBR(UChar *p, UChar r1, UChar r2)
3872{
sewardj7ee97522011-05-09 21:45:04 +00003873 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003874 s390_disasm(ENC3(MNM, FPR, FPR), "lpxbr", r1, r2);
3875
3876 return emit_RRE(p, 0xb3400000, r1, r2);
3877}
3878
3879
sewardj9d31dfd2011-03-15 12:36:44 +00003880static UChar *
florian8c3ccaf2012-09-09 18:18:25 +00003881s390_emit_LEDBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
sewardj2019a972011-03-07 16:04:07 +00003882{
florian8c3ccaf2012-09-09 18:18:25 +00003883 vassert(m4 == 0);
3884 vassert(m3 == 0 || s390_host_has_fpext);
sewardj2019a972011-03-07 16:04:07 +00003885
florian8c3ccaf2012-09-09 18:18:25 +00003886 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
3887 if (m3 == 0)
3888 s390_disasm(ENC3(MNM, FPR, FPR), "ledbr", r1, r2);
3889 else
3890 s390_disasm(ENC5(MNM, FPR, UINT, FPR, UINT),
3891 "ledbra", r1, m3, r2, m4);
3892 }
3893
3894 return emit_RRF2(p, 0xb3440000, m3, m4, r1, r2);
sewardj2019a972011-03-07 16:04:07 +00003895}
3896
3897
sewardj9d31dfd2011-03-15 12:36:44 +00003898static UChar *
florian8c3ccaf2012-09-09 18:18:25 +00003899s390_emit_LDXBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
sewardj2019a972011-03-07 16:04:07 +00003900{
florian8c3ccaf2012-09-09 18:18:25 +00003901 vassert(m4 == 0);
3902 vassert(m3 == 0 || s390_host_has_fpext);
sewardj2019a972011-03-07 16:04:07 +00003903
florian8c3ccaf2012-09-09 18:18:25 +00003904 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
3905 if (m3 == 0)
3906 s390_disasm(ENC3(MNM, FPR, FPR), "ldxbr", r1, r2);
3907 else
3908 s390_disasm(ENC5(MNM, FPR, UINT, FPR, UINT),
3909 "ldxbra", r1, m3, r2, m4);
3910 }
3911
3912 return emit_RRF2(p, 0xb3450000, m3, m4, r1, r2);
sewardj2019a972011-03-07 16:04:07 +00003913}
3914
3915
sewardj9d31dfd2011-03-15 12:36:44 +00003916static UChar *
florian8c3ccaf2012-09-09 18:18:25 +00003917s390_emit_LEXBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
sewardj2019a972011-03-07 16:04:07 +00003918{
florian8c3ccaf2012-09-09 18:18:25 +00003919 vassert(m4 == 0);
3920 vassert(m3 == 0 || s390_host_has_fpext);
sewardj2019a972011-03-07 16:04:07 +00003921
florian8c3ccaf2012-09-09 18:18:25 +00003922 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
3923 if (m3 == 0)
3924 s390_disasm(ENC3(MNM, FPR, FPR), "lexbr", r1, r2);
3925 else
3926 s390_disasm(ENC5(MNM, FPR, UINT, FPR, UINT),
3927 "lexbra", r1, m3, r2, m4);
3928 }
3929
3930 return emit_RRF2(p, 0xb3460000, m3, m4, r1, r2);
sewardj2019a972011-03-07 16:04:07 +00003931}
3932
3933
sewardj9d31dfd2011-03-15 12:36:44 +00003934static UChar *
sewardj2019a972011-03-07 16:04:07 +00003935s390_emit_MEEBR(UChar *p, UChar r1, UChar r2)
3936{
sewardj7ee97522011-05-09 21:45:04 +00003937 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003938 s390_disasm(ENC3(MNM, FPR, FPR), "meebr", r1, r2);
3939
3940 return emit_RRE(p, 0xb3170000, r1, r2);
3941}
3942
3943
sewardj9d31dfd2011-03-15 12:36:44 +00003944static UChar *
sewardj2019a972011-03-07 16:04:07 +00003945s390_emit_MDBR(UChar *p, UChar r1, UChar r2)
3946{
sewardj7ee97522011-05-09 21:45:04 +00003947 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003948 s390_disasm(ENC3(MNM, FPR, FPR), "mdbr", r1, r2);
3949
3950 return emit_RRE(p, 0xb31c0000, r1, r2);
3951}
3952
3953
sewardj9d31dfd2011-03-15 12:36:44 +00003954static UChar *
sewardj2019a972011-03-07 16:04:07 +00003955s390_emit_MXBR(UChar *p, UChar r1, UChar r2)
3956{
sewardj7ee97522011-05-09 21:45:04 +00003957 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003958 s390_disasm(ENC3(MNM, FPR, FPR), "mxbr", r1, r2);
3959
3960 return emit_RRE(p, 0xb34c0000, r1, r2);
3961}
3962
3963
sewardj9d31dfd2011-03-15 12:36:44 +00003964static UChar *
sewardj2019a972011-03-07 16:04:07 +00003965s390_emit_MAEBR(UChar *p, UChar r1, UChar r3, UChar r2)
3966{
sewardj7ee97522011-05-09 21:45:04 +00003967 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003968 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "maebr", r1, r3, r2);
3969
3970 return emit_RRF(p, 0xb30e0000, r1, r3, r2);
3971}
3972
3973
sewardj9d31dfd2011-03-15 12:36:44 +00003974static UChar *
sewardj2019a972011-03-07 16:04:07 +00003975s390_emit_MADBR(UChar *p, UChar r1, UChar r3, UChar r2)
3976{
sewardj7ee97522011-05-09 21:45:04 +00003977 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003978 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "madbr", r1, r3, r2);
3979
3980 return emit_RRF(p, 0xb31e0000, r1, r3, r2);
3981}
3982
3983
sewardj9d31dfd2011-03-15 12:36:44 +00003984static UChar *
sewardj2019a972011-03-07 16:04:07 +00003985s390_emit_MSEBR(UChar *p, UChar r1, UChar r3, UChar r2)
3986{
sewardj7ee97522011-05-09 21:45:04 +00003987 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003988 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "msebr", r1, r3, r2);
3989
3990 return emit_RRF(p, 0xb30f0000, r1, r3, r2);
3991}
3992
3993
sewardj9d31dfd2011-03-15 12:36:44 +00003994static UChar *
sewardj2019a972011-03-07 16:04:07 +00003995s390_emit_MSDBR(UChar *p, UChar r1, UChar r3, UChar r2)
3996{
sewardj7ee97522011-05-09 21:45:04 +00003997 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00003998 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "msdbr", r1, r3, r2);
3999
4000 return emit_RRF(p, 0xb31f0000, r1, r3, r2);
4001}
4002
4003
sewardj9d31dfd2011-03-15 12:36:44 +00004004static UChar *
sewardj2019a972011-03-07 16:04:07 +00004005s390_emit_SQEBR(UChar *p, UChar r1, UChar r2)
4006{
sewardj7ee97522011-05-09 21:45:04 +00004007 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00004008 s390_disasm(ENC3(MNM, FPR, FPR), "sqebr", r1, r2);
4009
4010 return emit_RRE(p, 0xb3140000, r1, r2);
4011}
4012
4013
sewardj9d31dfd2011-03-15 12:36:44 +00004014static UChar *
sewardj2019a972011-03-07 16:04:07 +00004015s390_emit_SQDBR(UChar *p, UChar r1, UChar r2)
4016{
sewardj7ee97522011-05-09 21:45:04 +00004017 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00004018 s390_disasm(ENC3(MNM, FPR, FPR), "sqdbr", r1, r2);
4019
4020 return emit_RRE(p, 0xb3150000, r1, r2);
4021}
4022
4023
sewardj9d31dfd2011-03-15 12:36:44 +00004024static UChar *
sewardj2019a972011-03-07 16:04:07 +00004025s390_emit_SQXBR(UChar *p, UChar r1, UChar r2)
4026{
sewardj7ee97522011-05-09 21:45:04 +00004027 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00004028 s390_disasm(ENC3(MNM, FPR, FPR), "sqxbr", r1, r2);
4029
4030 return emit_RRE(p, 0xb3160000, r1, r2);
4031}
4032
4033
sewardj9d31dfd2011-03-15 12:36:44 +00004034static UChar *
sewardj2019a972011-03-07 16:04:07 +00004035s390_emit_SEBR(UChar *p, UChar r1, UChar r2)
4036{
sewardj7ee97522011-05-09 21:45:04 +00004037 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00004038 s390_disasm(ENC3(MNM, FPR, FPR), "sebr", r1, r2);
4039
4040 return emit_RRE(p, 0xb30b0000, r1, r2);
4041}
4042
4043
sewardj9d31dfd2011-03-15 12:36:44 +00004044static UChar *
sewardj2019a972011-03-07 16:04:07 +00004045s390_emit_SDBR(UChar *p, UChar r1, UChar r2)
4046{
sewardj7ee97522011-05-09 21:45:04 +00004047 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00004048 s390_disasm(ENC3(MNM, FPR, FPR), "sdbr", r1, r2);
4049
4050 return emit_RRE(p, 0xb31b0000, r1, r2);
4051}
4052
4053
sewardj9d31dfd2011-03-15 12:36:44 +00004054static UChar *
sewardj2019a972011-03-07 16:04:07 +00004055s390_emit_SXBR(UChar *p, UChar r1, UChar r2)
4056{
sewardj7ee97522011-05-09 21:45:04 +00004057 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
sewardj2019a972011-03-07 16:04:07 +00004058 s390_disasm(ENC3(MNM, FPR, FPR), "sxbr", r1, r2);
4059
4060 return emit_RRE(p, 0xb34b0000, r1, r2);
4061}
4062
sewardj2019a972011-03-07 16:04:07 +00004063
florian12390202012-11-10 22:34:14 +00004064static UChar *
4065s390_emit_ADTRA(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
4066{
4067 vassert(s390_host_has_dfp);
4068 vassert(m4 == 0 || s390_host_has_fpext);
4069 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
4070 if (m4 == 0)
4071 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "adtr", r1, r2, r3);
4072 else
florianb3764a92012-12-20 14:44:42 +00004073 s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "adtra", r1, r2, r3, m4);
florian12390202012-11-10 22:34:14 +00004074 }
4075
4076 return emit_RRF4(p, 0xb3d20000, r3, m4, r1, r2);
4077}
4078
4079
4080static UChar *
floriane38f6412012-12-21 17:32:12 +00004081s390_emit_AXTRA(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
4082{
4083 vassert(s390_host_has_dfp);
4084 vassert(m4 == 0 || s390_host_has_fpext);
4085 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
4086 if (m4 == 0)
4087 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "axtr", r1, r2, r3);
4088 else
4089 s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "axtra", r1, r2, r3, m4);
4090 }
4091
4092 return emit_RRF4(p, 0xb3da0000, r3, m4, r1, r2);
4093}
4094
4095
4096static UChar *
4097s390_emit_CDTR(UChar *p, UChar r1, UChar r2)
4098{
4099 vassert(s390_host_has_dfp);
4100 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4101 s390_disasm(ENC3(MNM, FPR, FPR), "cdtr", r1, r2);
4102
4103 return emit_RRE(p, 0xb3e40000, r1, r2);
4104}
4105
4106
4107static UChar *
4108s390_emit_CXTR(UChar *p, UChar r1, UChar r2)
4109{
4110 vassert(s390_host_has_dfp);
4111 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4112 s390_disasm(ENC3(MNM, FPR, FPR), "cxtr", r1, r2);
4113
4114 return emit_RRE(p, 0xb3ec0000, r1, r2);
4115}
4116
4117
4118static UChar *
floriana887acd2013-02-08 23:32:54 +00004119s390_emit_CDGTRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4120{
4121 vassert(s390_host_has_dfp);
4122 vassert(m4 == 0);
4123 vassert(m3 == 0 || s390_host_has_fpext);
4124
4125 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
4126 if (m3 == 0)
4127 s390_disasm(ENC3(MNM, FPR, GPR), "cdgtr", r1, r2);
4128 else
4129 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cdgtra", r1, m3, r2, m4);
4130 }
4131
4132 return emit_RRF2(p, 0xb3f10000, m3, m4, r1, r2);
4133}
4134
4135
4136static UChar *
4137s390_emit_CXGTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4138{
4139 vassert(s390_host_has_dfp);
4140 vassert(m4 == 0);
4141 /* rounding mode m3 is not considered, as the corresponding
4142 IRop (Iop_I64StoD128) does not take rounding mode. */
4143 vassert(m3 == 0);
4144
florian08f65d92013-02-22 03:40:22 +00004145 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
floriana887acd2013-02-08 23:32:54 +00004146 s390_disasm(ENC3(MNM, FPR, GPR), "cxgtr", r1, r2);
floriana887acd2013-02-08 23:32:54 +00004147
4148 return emit_RRF2(p, 0xb3f90000, m3, m4, r1, r2);
4149}
4150
4151
4152static UChar *
florian5f034622013-01-13 02:29:05 +00004153s390_emit_CDFTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4154{
4155 vassert(m4 == 0);
4156 vassert(s390_host_has_dfp);
4157 vassert(s390_host_has_fpext);
4158
florian08f65d92013-02-22 03:40:22 +00004159 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
florian5f034622013-01-13 02:29:05 +00004160 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cdftr", r1, m3, r2, m4);
florian5f034622013-01-13 02:29:05 +00004161
4162 return emit_RRF2(p, 0xb9510000, m3, m4, r1, r2);
4163}
4164
4165
4166static UChar *
4167s390_emit_CXFTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4168{
4169 vassert(m4 == 0);
4170 vassert(s390_host_has_dfp);
4171 vassert(s390_host_has_fpext);
4172
florian08f65d92013-02-22 03:40:22 +00004173 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
florian5f034622013-01-13 02:29:05 +00004174 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cxftr", r1, m3, r2, m4);
florian5f034622013-01-13 02:29:05 +00004175
4176 return emit_RRF2(p, 0xb9590000, m3, m4, r1, r2);
4177}
4178
4179
4180static UChar *
4181s390_emit_CDLFTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4182{
4183 vassert(m4 == 0);
4184 vassert(s390_host_has_dfp);
4185 vassert(s390_host_has_fpext);
4186
4187 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4188 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cdlftr", r1, m3, r2, m4);
4189
4190 return emit_RRF2(p, 0xb9530000, m3, m4, r1, r2);
4191}
4192
4193
4194static UChar *
4195s390_emit_CXLFTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4196{
4197 vassert(m4 == 0);
4198 vassert(s390_host_has_dfp);
4199 vassert(s390_host_has_fpext);
4200
4201 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4202 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cxlftr", r1, m3, r2, m4);
4203
4204 return emit_RRF2(p, 0xb95b0000, m3, m4, r1, r2);
4205}
4206
4207
4208static UChar *
4209s390_emit_CDLGTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4210{
4211 vassert(m4 == 0);
4212 vassert(s390_host_has_dfp);
4213 vassert(s390_host_has_fpext);
4214
4215 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4216 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cdlgtr", r1, m3, r2, m4);
4217
4218 return emit_RRF2(p, 0xb9520000, m3, m4, r1, r2);
4219}
4220
4221
4222static UChar *
4223s390_emit_CXLGTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4224{
4225 vassert(m4 == 0);
4226 vassert(s390_host_has_dfp);
4227 vassert(s390_host_has_fpext);
4228
4229 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4230 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cxlgtr", r1, m3, r2, m4);
4231
4232 return emit_RRF2(p, 0xb95a0000, m3, m4, r1, r2);
4233}
4234
4235
4236static UChar *
florian20c6bca2012-12-26 17:47:19 +00004237s390_emit_CEDTR(UChar *p, UChar r1, UChar r2)
4238{
4239 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4240 s390_disasm(ENC3(MNM, FPR, FPR), "cedtr", r1, r2);
4241
4242 return emit_RRE(p, 0xb3f40000, r1, r2);
4243}
4244
4245
4246static UChar *
4247s390_emit_CEXTR(UChar *p, UChar r1, UChar r2)
4248{
4249 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4250 s390_disasm(ENC3(MNM, FPR, FPR), "cextr", r1, r2);
4251
4252 return emit_RRE(p, 0xb3fc0000, r1, r2);
4253}
4254
4255
4256static UChar *
florian5f034622013-01-13 02:29:05 +00004257s390_emit_CFDTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4258{
4259 vassert(m4 == 0);
4260 vassert(s390_host_has_dfp);
4261 vassert(s390_host_has_fpext);
4262
florian08f65d92013-02-22 03:40:22 +00004263 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
florian5f034622013-01-13 02:29:05 +00004264 s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "cfdtr", r1, m3, r2, m4);
florian5f034622013-01-13 02:29:05 +00004265
4266 return emit_RRF2(p, 0xb9410000, m3, m4, r1, r2);
4267}
4268
4269
4270static UChar *
4271s390_emit_CFXTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4272{
4273 vassert(m4 == 0);
4274 vassert(s390_host_has_dfp);
4275 vassert(s390_host_has_fpext);
4276
florian08f65d92013-02-22 03:40:22 +00004277 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
florian5f034622013-01-13 02:29:05 +00004278 s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "cfxtr", r1, m3, r2, m4);
florian5f034622013-01-13 02:29:05 +00004279
4280 return emit_RRF2(p, 0xb9490000, m3, m4, r1, r2);
4281}
4282
4283
4284static UChar *
floriana887acd2013-02-08 23:32:54 +00004285s390_emit_CGDTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4286{
4287 vassert(s390_host_has_dfp);
4288 vassert(m4 == 0);
4289 vassert(s390_host_has_fpext || m3 < 1 || m3 > 7);
4290
florian08f65d92013-02-22 03:40:22 +00004291 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
floriana887acd2013-02-08 23:32:54 +00004292 s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cgdtr", r1, m3, r2);
floriana887acd2013-02-08 23:32:54 +00004293
4294 return emit_RRF2(p, 0xb3e10000, m3, m4, r1, r2);
4295}
4296
4297
4298static UChar *
4299s390_emit_CGXTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4300{
4301 vassert(s390_host_has_dfp);
4302 vassert(m4 == 0);
4303 vassert(s390_host_has_fpext || m3 < 1 || m3 > 7);
4304
florian08f65d92013-02-22 03:40:22 +00004305 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
floriana887acd2013-02-08 23:32:54 +00004306 s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cgxtr", r1, m3, r2);
floriana887acd2013-02-08 23:32:54 +00004307
4308 return emit_RRF2(p, 0xb3e90000, m3, m4, r1, r2);
4309}
4310
4311
4312static UChar *
florian5f034622013-01-13 02:29:05 +00004313s390_emit_CLFDTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4314{
4315 vassert(m4 == 0);
4316 vassert(s390_host_has_dfp);
4317 vassert(s390_host_has_fpext);
4318
4319 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4320 s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clfdtr", r1, m3, r2, m4);
4321
4322 return emit_RRF2(p, 0xb9430000, m3, m4, r1, r2);
4323}
4324
4325
4326static UChar *
4327s390_emit_CLFXTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4328{
4329 vassert(m4 == 0);
4330 vassert(s390_host_has_dfp);
4331 vassert(s390_host_has_fpext);
4332
4333 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4334 s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clfxtr", r1, m3, r2, m4);
4335
4336 return emit_RRF2(p, 0xb94b0000, m3, m4, r1, r2);
4337}
4338
4339
4340static UChar *
4341s390_emit_CLGDTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4342{
4343 vassert(m4 == 0);
4344 vassert(s390_host_has_dfp);
4345 vassert(s390_host_has_fpext);
4346
4347 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4348 s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clgdtr", r1, m3, r2, m4);
4349
4350 return emit_RRF2(p, 0xb9420000, m3, m4, r1, r2);
4351}
4352
4353
4354static UChar *
4355s390_emit_CLGXTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4356{
4357 vassert(m4 == 0);
4358 vassert(s390_host_has_dfp);
4359 vassert(s390_host_has_fpext);
4360
4361 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4362 s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clgxtr", r1, m3, r2, m4);
4363
4364 return emit_RRF2(p, 0xb94a0000, m3, m4, r1, r2);
4365}
4366
4367
4368static UChar *
florian12390202012-11-10 22:34:14 +00004369s390_emit_DDTRA(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
4370{
4371 vassert(s390_host_has_dfp);
4372 vassert(m4 == 0 || s390_host_has_fpext);
4373 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
4374 if (m4 == 0)
4375 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "ddtr", r1, r2, r3);
4376 else
florianb3764a92012-12-20 14:44:42 +00004377 s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "ddtra", r1, r2, r3, m4);
florian12390202012-11-10 22:34:14 +00004378 }
4379
4380 return emit_RRF4(p, 0xb3d10000, r3, m4, r1, r2);
4381}
4382
4383
4384static UChar *
floriane38f6412012-12-21 17:32:12 +00004385s390_emit_DXTRA(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
4386{
4387 vassert(s390_host_has_dfp);
4388 vassert(m4 == 0 || s390_host_has_fpext);
4389 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
4390 if (m4 == 0)
4391 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "dxtr", r1, r2, r3);
4392 else
4393 s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "dxtra", r1, r2, r3, m4);
4394 }
4395
4396 return emit_RRF4(p, 0xb3d90000, r3, m4, r1, r2);
4397}
4398
4399
4400static UChar *
florian5c539732013-02-14 14:27:12 +00004401s390_emit_EEDTR(UChar *p, UChar r1, UChar r2)
4402{
4403 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4404 s390_disasm(ENC3(MNM, GPR, FPR), "eedtr", r1, r2);
4405
4406 return emit_RRE(p, 0xb3e50000, r1, r2);
4407}
4408
4409
4410static UChar *
4411s390_emit_EEXTR(UChar *p, UChar r1, UChar r2)
4412{
4413 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4414 s390_disasm(ENC3(MNM, GPR, FPR), "eextr", r1, r2);
4415
4416 return emit_RRE(p, 0xb3ed0000, r1, r2);
4417}
4418
4419
4420static UChar *
floriance9e3db2012-12-27 20:14:03 +00004421s390_emit_ESDTR(UChar *p, UChar r1, UChar r2)
4422{
4423 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4424 s390_disasm(ENC3(MNM, GPR, FPR), "esdtr", r1, r2);
4425
4426 return emit_RRE(p, 0xb3e70000, r1, r2);
4427}
4428
4429
4430static UChar *
4431s390_emit_ESXTR(UChar *p, UChar r1, UChar r2)
4432{
4433 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4434 s390_disasm(ENC3(MNM, GPR, FPR), "esxtr", r1, r2);
4435
4436 return emit_RRE(p, 0xb3ef0000, r1, r2);
4437}
4438
4439
4440static UChar *
florian5c539732013-02-14 14:27:12 +00004441s390_emit_IEDTR(UChar *p, UChar r3, UChar r1, UChar r2)
4442{
4443 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4444 s390_disasm(ENC4(MNM, FPR, FPR, GPR), "iedtr", r1, r3, r2);
4445
4446 return emit_RRF(p, 0xb3f60000, r3, r1, r2);
4447}
4448
4449
4450static UChar *
4451s390_emit_IEXTR(UChar *p, UChar r3, UChar r1, UChar r2)
4452{
4453 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4454 s390_disasm(ENC4(MNM, FPR, FPR, GPR), "iextr", r1, r3, r2);
4455
4456 return emit_RRF(p, 0xb3fe0000, r3, r1, r2);
4457}
4458
4459
4460static UChar *
floriane38f6412012-12-21 17:32:12 +00004461s390_emit_LDETR(UChar *p, UChar m4, UChar r1, UChar r2)
4462{
4463 vassert(s390_host_has_dfp);
4464 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4465 s390_disasm(ENC4(MNM, FPR, FPR, UINT), "ldetr", r1, r2, m4);
4466
4467 return emit_RRF5(p, 0xb3d40000, m4, r1, r2);
4468}
4469
4470
4471static UChar *
4472s390_emit_LXDTR(UChar *p, UChar m4, UChar r1, UChar r2)
4473{
4474 vassert(s390_host_has_dfp);
4475 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4476 s390_disasm(ENC4(MNM, FPR, FPR, UINT), "lxdtr", r1, r2, m4);
4477
4478 return emit_RRF5(p, 0xb3dc0000, m4, r1, r2);
4479}
4480
4481
4482static UChar *
4483s390_emit_LEDTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4484{
4485 vassert(s390_host_has_dfp);
4486 vassert(m4 == 0);
florian1bb7f6f2013-02-11 00:03:27 +00004487 vassert(s390_host_has_fpext || m3 < 1 || m3 > 7);
floriane38f6412012-12-21 17:32:12 +00004488
florian08f65d92013-02-22 03:40:22 +00004489 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4490 s390_disasm(ENC5(MNM, FPR, UINT, FPR, UINT), "ledtr", r1, m3, r2, m4);
floriane38f6412012-12-21 17:32:12 +00004491
4492 return emit_RRF2(p, 0xb3d50000, m3, m4, r1, r2);
4493}
4494
4495
4496static UChar *
4497s390_emit_LDXTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2)
4498{
4499 vassert(s390_host_has_dfp);
4500 vassert(m4 == 0);
florian1bb7f6f2013-02-11 00:03:27 +00004501 vassert(s390_host_has_fpext || m3 < 1 || m3 > 7);
floriane38f6412012-12-21 17:32:12 +00004502
florian08f65d92013-02-22 03:40:22 +00004503 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4504 s390_disasm(ENC5(MNM, FPR, UINT, FPR, UINT), "ldxtr", r1, m3, r2, m4);
floriane38f6412012-12-21 17:32:12 +00004505
4506 return emit_RRF2(p, 0xb3dd0000, m3, m4, r1, r2);
4507}
4508
4509
4510static UChar *
florian12390202012-11-10 22:34:14 +00004511s390_emit_MDTRA(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
4512{
4513 vassert(s390_host_has_dfp);
4514 vassert(m4 == 0 || s390_host_has_fpext);
4515 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
4516 if (m4 == 0)
4517 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "mdtr", r1, r2, r3);
4518 else
florianb3764a92012-12-20 14:44:42 +00004519 s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "mdtra", r1, r2, r3, m4);
florian12390202012-11-10 22:34:14 +00004520 }
4521
4522 return emit_RRF4(p, 0xb3d00000, r3, m4, r1, r2);
4523}
4524
4525
4526static UChar *
floriane38f6412012-12-21 17:32:12 +00004527s390_emit_MXTRA(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
4528{
4529 vassert(s390_host_has_dfp);
4530 vassert(m4 == 0 || s390_host_has_fpext);
4531 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
4532 if (m4 == 0)
4533 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "mxtr", r1, r2, r3);
4534 else
4535 s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "mxtra", r1, r2, r3, m4);
4536 }
4537
4538 return emit_RRF4(p, 0xb3d80000, r3, m4, r1, r2);
4539}
4540
4541
4542static UChar *
florian78d5ef72013-05-11 15:02:58 +00004543emit_E(UChar *p, UInt op)
4544{
4545 ULong the_insn = op;
4546
4547 return emit_2bytes(p, the_insn);
4548}
4549
4550
4551static UChar *
4552s390_emit_PFPO(UChar *p)
4553{
4554 vassert(s390_host_has_pfpo);
4555 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
4556 s390_disasm(ENC1(MNM), "pfpo");
4557 }
4558
4559 return emit_E(p, 0x010a);
4560}
4561
4562
4563static UChar *
florian5c539732013-02-14 14:27:12 +00004564s390_emit_QADTR(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
4565{
4566 vassert(s390_host_has_dfp);
4567 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4568 s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "qadtr", r1, r3, r2, m4);
4569
4570 return emit_RRF4(p, 0xb3f50000, r3, m4, r1, r2);
4571}
4572
4573
4574static UChar *
4575s390_emit_QAXTR(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
4576{
4577 vassert(s390_host_has_dfp);
4578 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4579 s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "qaxtr", r1, r3, r2, m4);
4580
4581 return emit_RRF4(p, 0xb3fd0000, r3, m4, r1, r2);
4582}
4583
4584
4585static UChar *
4586s390_emit_RRDTR(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
4587{
4588 vassert(s390_host_has_dfp);
4589 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4590 s390_disasm(ENC5(MNM, FPR, FPR, GPR, UINT), "rrdtr", r1, r3, r2, m4);
4591
4592 return emit_RRF4(p, 0xb3f70000, r3, m4, r1, r2);
4593}
4594
4595
4596static UChar *
4597s390_emit_RRXTR(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
4598{
4599 vassert(s390_host_has_dfp);
4600 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4601 s390_disasm(ENC5(MNM, FPR, FPR, GPR, UINT), "rrxtr", r1, r3, r2, m4);
4602
4603 return emit_RRF4(p, 0xb3ff0000, r3, m4, r1, r2);
4604}
4605
4606
4607static UChar *
florian12390202012-11-10 22:34:14 +00004608s390_emit_SDTRA(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
4609{
4610 vassert(s390_host_has_dfp);
4611 vassert(m4 == 0 || s390_host_has_fpext);
4612 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
4613 if (m4 == 0)
4614 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "sdtr", r1, r2, r3);
4615 else
florianb3764a92012-12-20 14:44:42 +00004616 s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "sdtra", r1, r2, r3, m4);
florian12390202012-11-10 22:34:14 +00004617 }
4618
4619 return emit_RRF4(p, 0xb3d30000, r3, m4, r1, r2);
4620}
4621
florian3a3d7f12012-12-03 13:32:05 +00004622
4623static UChar *
floriane38f6412012-12-21 17:32:12 +00004624s390_emit_SXTRA(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2)
4625{
4626 vassert(s390_host_has_dfp);
4627 vassert(m4 == 0 || s390_host_has_fpext);
4628 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
4629 if (m4 == 0)
4630 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "sxtr", r1, r2, r3);
4631 else
4632 s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "sxtra", r1, r2, r3, m4);
4633 }
4634
4635 return emit_RRF4(p, 0xb3db0000, r3, m4, r1, r2);
4636}
4637
4638
4639static UChar *
florian1b901d42013-01-01 22:19:24 +00004640s390_emit_SLDT(UChar *p, UChar r3, UChar r1, UChar r2)
4641{
4642 vassert(s390_host_has_dfp);
florian08f65d92013-02-22 03:40:22 +00004643 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
florian1b901d42013-01-01 22:19:24 +00004644 s390_disasm(ENC4(MNM, FPR, FPR, UDXB), "sldt", r1, r3, 0, 0, r2);
florian1b901d42013-01-01 22:19:24 +00004645
sewardj6938b9d2013-02-11 16:06:03 +00004646 return emit_RXF(p, 0xED0000000040ULL, r3, 0, r2, 0, r1);
florian1b901d42013-01-01 22:19:24 +00004647}
4648
4649
4650static UChar *
4651s390_emit_SLXT(UChar *p, UChar r3, UChar r1, UChar r2)
4652{
4653 vassert(s390_host_has_dfp);
florian08f65d92013-02-22 03:40:22 +00004654 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
florian1b901d42013-01-01 22:19:24 +00004655 s390_disasm(ENC4(MNM, FPR, FPR, UDXB), "slxt", r1, r3, 0, 0, r2);
florian1b901d42013-01-01 22:19:24 +00004656
sewardj6938b9d2013-02-11 16:06:03 +00004657 return emit_RXF(p, 0xED0000000048ULL, r3, 0, r2, 0, r1);
florian1b901d42013-01-01 22:19:24 +00004658}
4659
4660
4661static UChar *
4662s390_emit_SRDT(UChar *p, UChar r3, UChar r1, UChar r2)
4663{
4664 vassert(s390_host_has_dfp);
florian08f65d92013-02-22 03:40:22 +00004665 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
florian1b901d42013-01-01 22:19:24 +00004666 s390_disasm(ENC4(MNM, FPR, FPR, UDXB), "srdt", r1, r3, 0, 0, r2);
florian1b901d42013-01-01 22:19:24 +00004667
sewardj6938b9d2013-02-11 16:06:03 +00004668 return emit_RXF(p, 0xED0000000041ULL, r3, 0, r2, 0, r1);
florian1b901d42013-01-01 22:19:24 +00004669}
4670
4671
4672static UChar *
4673s390_emit_SRXT(UChar *p, UChar r3, UChar r1, UChar r2)
4674{
4675 vassert(s390_host_has_dfp);
florian08f65d92013-02-22 03:40:22 +00004676 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
florian1b901d42013-01-01 22:19:24 +00004677 s390_disasm(ENC4(MNM, FPR, FPR, UDXB), "srxt", r1, r3, 0, 0, r2);
florian1b901d42013-01-01 22:19:24 +00004678
sewardj6938b9d2013-02-11 16:06:03 +00004679 return emit_RXF(p, 0xED0000000049ULL, r3, 0, r2, 0, r1);
florian1b901d42013-01-01 22:19:24 +00004680}
4681
4682
4683static UChar *
florian3a3d7f12012-12-03 13:32:05 +00004684s390_emit_LOCGR(UChar *p, UChar m3, UChar r1, UChar r2)
4685{
florianaec8e052012-12-09 17:26:32 +00004686 vassert(s390_host_has_lsc);
florian08f65d92013-02-22 03:40:22 +00004687 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
florian3a3d7f12012-12-03 13:32:05 +00004688 s390_disasm(ENC4(MNM, GPR, GPR, UINT), "locgr", r1, r2, m3);
florian3a3d7f12012-12-03 13:32:05 +00004689
4690 return emit_RRF3(p, 0xb9e20000, m3, r1, r2);
4691}
4692
4693
4694static UChar *
4695s390_emit_LOC(UChar *p, UChar r1, UChar m3, UChar b2, UShort dl2, UChar dh2)
4696{
florian3a3d7f12012-12-03 13:32:05 +00004697 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4698 s390_disasm(ENC4(MNM, GPR, UINT, SDXB), "loc", r1, m3, dh2, dl2, 0, b2);
4699
4700 return emit_RSY(p, 0xeb00000000f2ULL, r1, m3, b2, dl2, dh2);
4701}
4702
4703
4704static UChar *
4705s390_emit_LOCG(UChar *p, UChar r1, UChar m3, UChar b2, UShort dl2, UChar dh2)
4706{
florian3a3d7f12012-12-03 13:32:05 +00004707 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
4708 s390_disasm(ENC4(MNM, GPR, UINT, SDXB), "locg", r1, m3, dh2, dl2, 0, b2);
4709
4710 return emit_RSY(p, 0xeb00000000e2ULL, r1, m3, b2, dl2, dh2);
4711}
4712
4713
sewardj2019a972011-03-07 16:04:07 +00004714/* Provide a symbolic name for register "R0" */
4715#define R0 0
4716
4717/* Split up a 20-bit displacement into its high and low piece
4718 suitable for passing as function arguments */
sewardjcd2b0252011-05-09 20:35:41 +00004719#define DISP20(d) (((UInt)d) & 0xFFF), ((((UInt)d) >> 12) & 0xFF)
sewardj2019a972011-03-07 16:04:07 +00004720
4721/*---------------------------------------------------------------*/
4722/*--- Helper functions ---*/
4723/*---------------------------------------------------------------*/
4724
4725static __inline__ Bool
4726uint_fits_signed_16bit(UInt val)
4727{
florianffbd84d2012-12-09 02:06:29 +00004728 Int v = val & 0xFFFFu;
sewardj2019a972011-03-07 16:04:07 +00004729
4730 /* sign extend */
4731 v = (v << 16) >> 16;
4732
4733 return val == (UInt)v;
4734}
4735
4736
4737static __inline__ Bool
4738ulong_fits_signed_16bit(ULong val)
4739{
4740 Long v = val & 0xFFFFu;
4741
4742 /* sign extend */
4743 v = (v << 48) >> 48;
4744
4745 return val == (ULong)v;
4746}
4747
4748
4749static __inline__ Bool
4750ulong_fits_signed_32bit(ULong val)
4751{
4752 Long v = val & 0xFFFFFFFFu;
4753
4754 /* sign extend */
4755 v = (v << 32) >> 32;
4756
4757 return val == (ULong)v;
4758}
4759
4760
4761static __inline__ Bool
4762ulong_fits_unsigned_32bit(ULong val)
4763{
4764 return (val & 0xFFFFFFFFu) == val;
4765}
4766
4767
4768/* Load a 64-bit immediate VAL into register REG. */
4769static UChar *
4770s390_emit_load_64imm(UChar *p, UChar reg, ULong val)
4771{
4772 if (ulong_fits_signed_16bit(val)) {
4773 return s390_emit_LGHI(p, reg, val);
4774 }
4775
4776 if (s390_host_has_eimm) {
4777 if (ulong_fits_unsigned_32bit(val)) {
4778 return s390_emit_LLILF(p, reg, val);
4779 }
4780 if (ulong_fits_signed_32bit(val)) {
4781 /* LGFI's sign extension will recreate the correct 64-bit value */
4782 return s390_emit_LGFI(p, reg, val);
4783 }
4784 /* Do it in two steps: upper half [0:31] and lower half [32:63] */
4785 p = s390_emit_IIHF(p, reg, val >> 32);
4786 return s390_emit_IILF(p, reg, val & 0xFFFFFFFF);
4787 }
4788
4789 /* Fall back */
4790 if (ulong_fits_unsigned_32bit(val)) {
4791 p = s390_emit_LLILH(p, reg, (val >> 16) & 0xFFFF); /* sets val[32:47]
4792 val[0:31] = 0 */
4793 p = s390_emit_IILL(p, reg, val & 0xFFFF); /* sets val[48:63] */
4794 return p;
4795 }
4796
4797 p = s390_emit_IIHH(p, reg, (val >> 48) & 0xFFFF);
4798 p = s390_emit_IIHL(p, reg, (val >> 32) & 0xFFFF);
4799 p = s390_emit_IILH(p, reg, (val >> 16) & 0xFFFF);
4800 p = s390_emit_IILL(p, reg, val & 0xFFFF);
4801
4802 return p;
4803}
4804
4805/* Load a 32-bit immediate VAL into register REG. */
4806static UChar *
4807s390_emit_load_32imm(UChar *p, UChar reg, UInt val)
4808{
4809 if (uint_fits_signed_16bit(val)) {
4810 /* LHI's sign extension will recreate the correct 32-bit value */
4811 return s390_emit_LHI(p, reg, val);
4812 }
4813 if (s390_host_has_eimm) {
4814 return s390_emit_IILF(p, reg, val);
4815 }
4816 /* val[0:15] --> (val >> 16) & 0xFFFF
4817 val[16:31] --> val & 0xFFFF */
4818 p = s390_emit_IILH(p, reg, (val >> 16) & 0xFFFF);
4819 return s390_emit_IILL(p, reg, val & 0xFFFF);
4820}
4821
4822/*------------------------------------------------------------*/
4823/*--- Wrapper functions ---*/
4824/*------------------------------------------------------------*/
4825
sewardjeae8db52011-03-24 09:01:50 +00004826/* r1[32:63],r1+1[32:63] = r1+1[32:63] * memory[op2addr][0:31] */
sewardj2019a972011-03-07 16:04:07 +00004827static UChar *
4828s390_emit_MFYw(UChar *p, UChar r1, UChar x, UChar b, UShort dl, UChar dh)
4829{
4830 if (s390_host_has_gie) {
4831 return s390_emit_MFY(p, r1, x, b, dl, dh);
4832 }
4833
4834 /* Load from memory into R0, then MULTIPLY with R1 */
4835 p = s390_emit_LY(p, R0, x, b, dl, dh);
4836 return s390_emit_MR(p, r1, R0);
4837}
4838
sewardjeae8db52011-03-24 09:01:50 +00004839/* r1[32:63] = r1[32:63] * memory[op2addr][0:15] */
4840static UChar *
4841s390_emit_MHYw(UChar *p, UChar r1, UChar x, UChar b, UShort dl, UChar dh)
4842{
4843 if (s390_host_has_gie) {
4844 return s390_emit_MHY(p, r1, x, b, dl, dh);
4845 }
4846
4847 /* Load from memory into R0, then MULTIPLY with R1 */
4848 p = s390_emit_LHY(p, R0, x, b, dl, dh);
4849 return s390_emit_MSR(p, r1, R0);
4850}
4851
sewardj2019a972011-03-07 16:04:07 +00004852/* r1[32:63] = r1[32:63] * i2 */
4853static UChar *
4854s390_emit_MSFIw(UChar *p, UChar r1, UInt i2)
4855{
4856 if (s390_host_has_gie) {
4857 return s390_emit_MSFI(p, r1, i2);
4858 }
4859
4860 /* Load I2 into R0; then MULTIPLY R0 with R1 */
4861 p = s390_emit_load_32imm(p, R0, i2);
4862 return s390_emit_MSR(p, r1, R0);
4863}
4864
4865
4866/* r1[32:63] = r1[32:63] & i2 */
4867static UChar *
4868s390_emit_NILFw(UChar *p, UChar r1, UInt i2)
4869{
4870 if (s390_host_has_eimm) {
4871 return s390_emit_NILF(p, r1, i2);
4872 }
4873
4874 /* Load I2 into R0; then AND R0 with R1 */
4875 p = s390_emit_load_32imm(p, R0, i2);
4876 return s390_emit_NR(p, r1, R0);
4877}
4878
4879
4880/* r1[32:63] = r1[32:63] | i2 */
4881static UChar *
4882s390_emit_OILFw(UChar *p, UChar r1, UInt i2)
4883{
4884 if (s390_host_has_eimm) {
4885 return s390_emit_OILF(p, r1, i2);
4886 }
4887
4888 /* Load I2 into R0; then AND R0 with R1 */
4889 p = s390_emit_load_32imm(p, R0, i2);
4890 return s390_emit_OR(p, r1, R0);
4891}
4892
4893
4894/* r1[32:63] = r1[32:63] ^ i2 */
4895static UChar *
4896s390_emit_XILFw(UChar *p, UChar r1, UInt i2)
4897{
4898 if (s390_host_has_eimm) {
4899 return s390_emit_XILF(p, r1, i2);
4900 }
4901
4902 /* Load I2 into R0; then AND R0 with R1 */
4903 p = s390_emit_load_32imm(p, R0, i2);
4904 return s390_emit_XR(p, r1, R0);
4905}
4906
4907
4908/* r1[32:63] = sign_extend(r2[56:63]) */
4909static UChar *
4910s390_emit_LBRw(UChar *p, UChar r1, UChar r2)
4911{
4912 if (s390_host_has_eimm) {
4913 return s390_emit_LBR(p, r1, r2);
4914 }
4915
4916 p = s390_emit_LR(p, r1, r2); /* r1 = r2 */
sewardj3c49aaa2011-04-05 14:00:37 +00004917 p = s390_emit_SLL(p, r1, R0, 24); /* r1 = r1 << 24 */
4918 return s390_emit_SRA(p, r1, R0, 24); /* r1 = r1 >>a 24 */
sewardj2019a972011-03-07 16:04:07 +00004919}
4920
4921
4922/* r1[0:63] = sign_extend(r2[56:63]) */
4923static UChar *
4924s390_emit_LGBRw(UChar *p, UChar r1, UChar r2)
4925{
4926 if (s390_host_has_eimm) {
4927 return s390_emit_LGBR(p, r1, r2);
4928 }
4929
4930 p = s390_emit_LR(p, r1, r2); /* r1 = r2 */
4931 p = s390_emit_SLLG(p, r1, r1, R0, DISP20(56)); /* r1 = r1 << 56 */
4932 return s390_emit_SRAG(p, r1, r1, R0, DISP20(56)); /* r1 = r1 >>a 56 */
4933}
4934
4935
4936/* r1[32:63] = sign_extend(r2[48:63]) */
4937static UChar *
4938s390_emit_LHRw(UChar *p, UChar r1, UChar r2)
4939{
4940 if (s390_host_has_eimm) {
4941 return s390_emit_LHR(p, r1, r2);
4942 }
4943
4944 p = s390_emit_LR(p, r1, r2); /* r1 = r2 */
sewardj3c49aaa2011-04-05 14:00:37 +00004945 p = s390_emit_SLL(p, r1, R0, 16); /* r1 = r1 << 16 */
4946 return s390_emit_SRA(p, r1, R0, 16); /* r1 = r1 >>a 16 */
sewardj2019a972011-03-07 16:04:07 +00004947}
4948
4949
4950/* r1[0:63] = sign_extend(r2[48:63]) */
4951static UChar *
4952s390_emit_LGHRw(UChar *p, UChar r1, UChar r2)
4953{
4954 if (s390_host_has_eimm) {
4955 return s390_emit_LGHR(p, r1, r2);
4956 }
4957
4958 p = s390_emit_LR(p, r1, r2); /* r1 = r2 */
4959 p = s390_emit_SLLG(p, r1, r1, R0, DISP20(48)); /* r1 = r1 << 48 */
4960 return s390_emit_SRAG(p, r1, r1, R0, DISP20(48)); /* r1 = r1 >>a 48 */
4961}
4962
4963
4964/* r1[0:63] = sign_extend(i2) */
4965static UChar *
4966s390_emit_LGFIw(UChar *p, UChar r1, UInt i2)
4967{
4968 if (s390_host_has_eimm) {
4969 return s390_emit_LGFI(p, r1, i2);
4970 }
4971
4972 p = s390_emit_load_32imm(p, R0, i2);
4973 return s390_emit_LGFR(p, r1, R0);
4974}
4975
4976
4977/* r1[32:63] = zero_extend($r2[56:63]) */
4978static UChar *
4979s390_emit_LLCRw(UChar *p, UChar r1, UChar r2)
4980{
4981 if (s390_host_has_eimm) {
4982 return s390_emit_LLCR(p, r1, r2);
4983 }
4984
4985 p = s390_emit_LR(p, r1, r2);
4986 p = s390_emit_LHI(p, R0, 0xFF);
4987 return s390_emit_NR(p, r1, R0);
4988}
4989
4990
4991/* r1[0:63] = zero_extend($r2[56:63]) */
4992static UChar *
4993s390_emit_LLGCRw(UChar *p, UChar r1, UChar r2)
4994{
4995 if (s390_host_has_eimm) {
4996 return s390_emit_LLGCR(p, r1, r2);
4997 }
4998
4999 p = s390_emit_LR(p, r1, r2);
5000 p = s390_emit_LLILL(p, R0, 0xFF);
5001 return s390_emit_NGR(p, r1, R0);
5002}
5003
5004
5005/* r1[32:63] = zero_extend(r2[48:63]) */
5006static UChar *
5007s390_emit_LLHRw(UChar *p, UChar r1, UChar r2)
5008{
5009 if (s390_host_has_eimm) {
5010 return s390_emit_LLHR(p, r1, r2);
5011 }
5012
5013 p = s390_emit_LR(p, r1, r2);
5014 p = s390_emit_LLILL(p, R0, 0xFFFF);
5015 return s390_emit_NR(p, r1, R0);
5016}
5017
5018
5019/* r1[0:63] = zero_extend(r2[48:63]) */
5020static UChar *
5021s390_emit_LLGHRw(UChar *p, UChar r1, UChar r2)
5022{
5023 if (s390_host_has_eimm) {
5024 return s390_emit_LLGHR(p, r1, r2);
5025 }
5026
5027 p = s390_emit_LR(p, r1, r2);
5028 p = s390_emit_LLILL(p, R0, 0xFFFF);
5029 return s390_emit_NGR(p, r1, R0);
5030}
5031
5032
5033/* r1[32:63] = zero_extend(mem[op2addr][0:7]) */
5034static UChar *
5035s390_emit_LLCw(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl, UChar dh)
5036{
5037 if (s390_host_has_eimm) {
5038 return s390_emit_LLC(p, r1, x2, b2, dl, dh);
5039 }
5040
5041 if (dh == 0) {
5042 p = s390_emit_IC(p, r1, x2, b2, dl);
5043 } else {
5044 p = s390_emit_ICY(p, r1, x2, b2, dl, dh);
5045 }
5046 p = s390_emit_LLILL(p, R0, 0xFF);
5047 return s390_emit_NR(p, r1, R0);
5048}
5049
5050
5051/* r1[32:63] = zero_extend(mem[op2addr][0:15]) */
5052static UChar *
5053s390_emit_LLHw(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl, UChar dh)
5054{
5055 if (s390_host_has_eimm) {
5056 return s390_emit_LLH(p, r1, x2, b2, dl, dh);
5057 }
5058
5059 p = s390_emit_LLGH(p, r1, x2, b2, dl, dh);
5060 p = s390_emit_LLILL(p, R0, 0xFFFF);
5061 return s390_emit_NR(p, r1, R0);
5062}
5063
5064
5065/* r1[0:63] = zero_extend(i2) */
5066static UChar *
5067s390_emit_LLILFw(UChar *p, UChar r1, UInt i2)
5068{
5069 if (s390_host_has_eimm) {
5070 return s390_emit_LLILF(p, r1, i2);
5071 }
5072
5073 p = s390_emit_LLILH(p, r1, (i2 >> 16) & 0xFFFF); /* i2[0:15] */
5074 return s390_emit_OILL(p, r1, i2 & 0xFFFF);
5075}
5076
5077
5078/* r1[32:63] = r1[32:63] + i2 */
5079static UChar *
5080s390_emit_AFIw(UChar *p, UChar r1, UInt i2)
5081{
5082 if (s390_host_has_eimm) {
5083 return s390_emit_AFI(p, r1, i2);
5084 }
5085 /* Load 32 bit immediate to R0 then add */
5086 p = s390_emit_load_32imm(p, R0, i2);
5087 return s390_emit_AR(p, r1, R0);
5088}
5089
5090
5091/* r1[32:63] = r1[32:63] - i2 */
5092static UChar *
5093s390_emit_SLFIw(UChar *p, UChar r1, UInt i2)
5094{
5095 if (s390_host_has_eimm) {
5096 return s390_emit_SLFI(p, r1, i2);
5097 }
5098
5099 /* Load 32 bit immediate to R0 then subtract */
5100 p = s390_emit_load_32imm(p, R0, i2);
5101 return s390_emit_SR(p, r1, R0);
5102}
5103
5104
sewardjb13a92a2011-04-13 14:44:29 +00005105/* r1[0:63] = r1[0:63] - zero_extend(i2) */
5106static UChar *
5107s390_emit_SLGFIw(UChar *p, UChar r1, UInt i2)
5108{
5109 if (s390_host_has_eimm) {
5110 return s390_emit_SLGFI(p, r1, i2);
5111 }
5112
5113 /* Load zero-extended 32 bit immediate to R0 then subtract */
5114 p = s390_emit_load_64imm(p, R0, i2);
5115 return s390_emit_SGR(p, r1, R0);
5116}
5117
5118
sewardj2019a972011-03-07 16:04:07 +00005119static UChar *
5120s390_emit_LTw(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl, UChar dh)
5121{
5122 if (s390_host_has_eimm) {
5123 return s390_emit_LT(p, r1, x2, b2, dl, dh);
5124 }
5125 /* Load 32 bit from memory to R0 then compare */
5126 if (dh == 0) {
5127 p = s390_emit_L(p, R0, x2, b2, dl);
5128 } else {
5129 p = s390_emit_LY(p, R0, x2, b2, dl, dh);
5130 }
5131 return s390_emit_LTR(p, r1, R0);
5132}
5133
5134
5135static UChar *
5136s390_emit_LTGw(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl, UChar dh)
5137{
5138 if (s390_host_has_eimm) {
5139 return s390_emit_LTG(p, r1, x2, b2, dl, dh);
5140 }
5141 /* Load 64 bit from memory to R0 then compare */
5142 p = s390_emit_LG(p, R0, x2, b2, dl, dh);
5143 return s390_emit_LTGR(p, r1, R0);
5144}
5145
5146
5147static UChar *
5148s390_emit_CFIw(UChar *p, UChar r1, UInt i2)
5149{
5150 if (s390_host_has_eimm) {
5151 return s390_emit_CFI(p, r1, i2);
5152 }
5153 /* Load 32 bit immediate to R0 then compare */
5154 p = s390_emit_load_32imm(p, R0, i2);
5155 return s390_emit_CR(p, r1, R0);
5156}
5157
5158
5159static UChar *
5160s390_emit_CLFIw(UChar *p, UChar r1, UInt i2)
5161{
5162 if (s390_host_has_eimm) {
5163 return s390_emit_CLFI(p, r1, i2);
5164 }
5165 /* Load 32 bit immediate to R0 then compare */
5166 p = s390_emit_load_32imm(p, R0, i2);
5167 return s390_emit_CLR(p, r1, R0);
5168}
5169
sewardjd07b8562011-04-27 11:58:22 +00005170
5171static UChar *
5172s390_emit_LGDRw(UChar *p, UChar r1, UChar r2)
5173{
5174 if (s390_host_has_fgx) {
5175 return s390_emit_LGDR(p, r1, r2);
5176 }
5177
5178 /* Store the FPR at memory[sp - 8]. This is safe because SP grows towards
5179 smaller addresses and is 8-byte aligned. Then load the GPR from that
5180 memory location/ */
floriandc6e7472014-12-08 14:01:33 +00005181 p = s390_emit_STDY(p, r2, R0, S390_REGNO_STACK_POINTER, DISP20(-8));
5182 return s390_emit_LG(p, r1, R0, S390_REGNO_STACK_POINTER, DISP20(-8));
sewardjd07b8562011-04-27 11:58:22 +00005183}
5184
5185
5186static UChar *
5187s390_emit_LDGRw(UChar *p, UChar r1, UChar r2)
5188{
5189 if (s390_host_has_fgx) {
5190 return s390_emit_LDGR(p, r1, r2);
5191 }
5192
5193 /* Store the GPR at memory[sp - 8]. This is safe because SP grows towards
5194 smaller addresses and is 8-byte aligned. Then load the FPR from that
5195 memory location/ */
floriandc6e7472014-12-08 14:01:33 +00005196 p = s390_emit_STG(p, r2, R0, S390_REGNO_STACK_POINTER, DISP20(-8));
5197 return s390_emit_LDY(p, r1, R0, S390_REGNO_STACK_POINTER, DISP20(-8));
sewardjd07b8562011-04-27 11:58:22 +00005198}
5199
5200
sewardj2019a972011-03-07 16:04:07 +00005201/*---------------------------------------------------------------*/
5202/*--- Constructors for the various s390_insn kinds ---*/
5203/*---------------------------------------------------------------*/
5204
5205s390_insn *
5206s390_insn_load(UChar size, HReg dst, s390_amode *src)
5207{
5208 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5209
5210 insn->tag = S390_INSN_LOAD;
5211 insn->size = size;
5212 insn->variant.load.src = src;
5213 insn->variant.load.dst = dst;
5214
5215 vassert(size == 1 || size == 2 || size == 4 || size == 8);
5216
5217 return insn;
5218}
5219
5220
5221s390_insn *
5222s390_insn_store(UChar size, s390_amode *dst, HReg src)
5223{
5224 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5225
5226 insn->tag = S390_INSN_STORE;
5227 insn->size = size;
5228 insn->variant.store.src = src;
5229 insn->variant.store.dst = dst;
5230
5231 vassert(size == 1 || size == 2 || size == 4 || size == 8);
5232
5233 return insn;
5234}
5235
5236
5237s390_insn *
5238s390_insn_move(UChar size, HReg dst, HReg src)
5239{
5240 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5241
5242 insn->tag = S390_INSN_MOVE;
5243 insn->size = size;
5244 insn->variant.move.src = src;
5245 insn->variant.move.dst = dst;
5246
5247 vassert(size == 1 || size == 2 || size == 4 || size == 8);
5248
5249 return insn;
5250}
5251
5252
5253s390_insn *
floriancec3a8a2013-02-02 00:16:58 +00005254s390_insn_memcpy(UChar size, s390_amode *dst, s390_amode *src)
5255{
5256 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5257
5258 /* This insn will be mapped to MVC which requires base register
5259 plus 12-bit displacement */
5260 vassert(src->tag == S390_AMODE_B12);
5261 vassert(dst->tag == S390_AMODE_B12);
5262
5263 insn->tag = S390_INSN_MEMCPY;
5264 insn->size = size;
5265 insn->variant.memcpy.src = src;
5266 insn->variant.memcpy.dst = dst;
5267
5268 vassert(size == 1 || size == 2 || size == 4 || size == 8);
5269
5270 return insn;
5271}
5272
5273
5274s390_insn *
sewardj2019a972011-03-07 16:04:07 +00005275s390_insn_cond_move(UChar size, s390_cc_t cond, HReg dst, s390_opnd_RMI src)
5276{
5277 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5278
5279 insn->tag = S390_INSN_COND_MOVE;
5280 insn->size = size;
5281 insn->variant.cond_move.cond = cond;
5282 insn->variant.cond_move.src = src;
5283 insn->variant.cond_move.dst = dst;
5284
5285 vassert(size == 1 || size == 2 || size == 4 || size == 8);
5286
5287 return insn;
5288}
5289
5290
5291s390_insn *
5292s390_insn_load_immediate(UChar size, HReg dst, ULong value)
5293{
5294 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5295
5296 insn->tag = S390_INSN_LOAD_IMMEDIATE;
5297 insn->size = size;
5298 insn->variant.load_immediate.dst = dst;
5299 insn->variant.load_immediate.value = value;
5300
5301 return insn;
5302}
5303
5304
5305s390_insn *
5306s390_insn_alu(UChar size, s390_alu_t tag, HReg dst, s390_opnd_RMI op2)
5307{
5308 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5309
5310 insn->tag = S390_INSN_ALU;
5311 insn->size = size;
5312 insn->variant.alu.tag = tag;
5313 insn->variant.alu.dst = dst;
5314 insn->variant.alu.op2 = op2;
5315
5316 return insn;
5317}
5318
5319
5320s390_insn *
5321s390_insn_mul(UChar size, HReg dst_hi, HReg dst_lo, s390_opnd_RMI op2,
5322 Bool signed_multiply)
5323{
5324 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5325
5326 vassert(! hregIsVirtual(dst_hi));
5327 vassert(! hregIsVirtual(dst_lo));
5328
florianc4aa7ed2012-12-22 15:01:04 +00005329 insn->tag = signed_multiply ? S390_INSN_SMUL : S390_INSN_UMUL;
sewardj2019a972011-03-07 16:04:07 +00005330 insn->size = size;
5331 insn->variant.mul.dst_hi = dst_hi;
5332 insn->variant.mul.dst_lo = dst_lo;
5333 insn->variant.mul.op2 = op2;
sewardj2019a972011-03-07 16:04:07 +00005334
5335 return insn;
5336}
5337
5338
5339s390_insn *
5340s390_insn_div(UChar size, HReg op1_hi, HReg op1_lo, s390_opnd_RMI op2,
5341 Bool signed_divide)
5342{
5343 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5344
5345 vassert(size == 4 || size == 8);
5346 vassert(! hregIsVirtual(op1_hi));
5347 vassert(! hregIsVirtual(op1_lo));
5348
florianc4aa7ed2012-12-22 15:01:04 +00005349 insn->tag = signed_divide ? S390_INSN_SDIV : S390_INSN_UDIV;
sewardj2019a972011-03-07 16:04:07 +00005350 insn->size = size;
5351 insn->variant.div.op1_hi = op1_hi;
5352 insn->variant.div.op1_lo = op1_lo;
5353 insn->variant.div.op2 = op2;
sewardj2019a972011-03-07 16:04:07 +00005354
5355 return insn;
5356}
5357
5358
5359s390_insn *
5360s390_insn_divs(UChar size, HReg rem, HReg op1, s390_opnd_RMI op2)
5361{
5362 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5363
5364 vassert(size == 8);
5365 vassert(! hregIsVirtual(op1));
5366 vassert(! hregIsVirtual(rem));
5367
5368 insn->tag = S390_INSN_DIVS;
5369 insn->size = size;
5370 insn->variant.divs.rem = rem; /* remainder */
5371 insn->variant.divs.op1 = op1; /* also quotient */
5372 insn->variant.divs.op2 = op2;
5373
5374 return insn;
5375}
5376
5377
5378s390_insn *
sewardj611b06e2011-03-24 08:57:29 +00005379s390_insn_clz(UChar size, HReg num_bits, HReg clobber, s390_opnd_RMI src)
sewardj2019a972011-03-07 16:04:07 +00005380{
5381 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5382
5383 vassert(size == 8);
sewardj611b06e2011-03-24 08:57:29 +00005384 vassert(! hregIsVirtual(num_bits));
5385 vassert(! hregIsVirtual(clobber));
sewardj2019a972011-03-07 16:04:07 +00005386
sewardj611b06e2011-03-24 08:57:29 +00005387 insn->tag = S390_INSN_CLZ;
sewardj2019a972011-03-07 16:04:07 +00005388 insn->size = size;
sewardj611b06e2011-03-24 08:57:29 +00005389 insn->variant.clz.num_bits = num_bits;
5390 insn->variant.clz.clobber = clobber;
5391 insn->variant.clz.src = src;
sewardj2019a972011-03-07 16:04:07 +00005392
5393 return insn;
5394}
5395
5396
5397s390_insn *
5398s390_insn_unop(UChar size, s390_unop_t tag, HReg dst, s390_opnd_RMI opnd)
5399{
5400 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5401
5402 insn->tag = S390_INSN_UNOP;
5403 insn->size = size;
5404 insn->variant.unop.tag = tag;
5405 insn->variant.unop.dst = dst;
5406 insn->variant.unop.src = opnd;
5407
5408 return insn;
5409}
5410
5411
5412s390_insn *
5413s390_insn_test(UChar size, s390_opnd_RMI src)
5414{
5415 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5416
5417 vassert(size == 4 || size == 8);
5418
5419 insn->tag = S390_INSN_TEST;
5420 insn->size = size;
5421 insn->variant.test.src = src;
5422
5423 return insn;
5424}
5425
5426
5427s390_insn *
5428s390_insn_cc2bool(HReg dst, s390_cc_t cond)
5429{
5430 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5431
5432 insn->tag = S390_INSN_CC2BOOL;
5433 insn->size = 0; /* does not matter */
5434 insn->variant.cc2bool.cond = cond;
5435 insn->variant.cc2bool.dst = dst;
5436
5437 return insn;
5438}
5439
5440
5441s390_insn *
5442s390_insn_cas(UChar size, HReg op1, s390_amode *op2, HReg op3, HReg old_mem)
5443{
5444 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5445
5446 vassert(size == 4 || size == 8);
florian3123f722013-01-24 15:55:52 +00005447 vassert(hregNumber(op2->x) == 0);
florian406ac942014-11-22 20:10:21 +00005448 vassert(op2->tag == S390_AMODE_B12 || op2->tag == S390_AMODE_B20);
sewardj2019a972011-03-07 16:04:07 +00005449
5450 insn->tag = S390_INSN_CAS;
5451 insn->size = size;
5452 insn->variant.cas.op1 = op1;
5453 insn->variant.cas.op2 = op2;
5454 insn->variant.cas.op3 = op3;
5455 insn->variant.cas.old_mem = old_mem;
5456
5457 return insn;
5458}
5459
5460
5461s390_insn *
florian448cbba2012-06-06 02:26:01 +00005462s390_insn_cdas(UChar size, HReg op1_high, HReg op1_low, s390_amode *op2,
5463 HReg op3_high, HReg op3_low, HReg old_mem_high, HReg old_mem_low,
5464 HReg scratch)
5465{
5466 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
florianc4aa7ed2012-12-22 15:01:04 +00005467 s390_cdas *cdas = LibVEX_Alloc(sizeof(s390_cdas));
florian448cbba2012-06-06 02:26:01 +00005468
5469 vassert(size == 4 || size == 8);
florian3123f722013-01-24 15:55:52 +00005470 vassert(hregNumber(op2->x) == 0);
florian448cbba2012-06-06 02:26:01 +00005471 vassert(hregNumber(scratch) == 1); /* r0,r1 used as scratch reg pair */
florian406ac942014-11-22 20:10:21 +00005472 vassert(op2->tag == S390_AMODE_B12 || op2->tag == S390_AMODE_B20);
florian448cbba2012-06-06 02:26:01 +00005473
5474 insn->tag = S390_INSN_CDAS;
5475 insn->size = size;
florianc4aa7ed2012-12-22 15:01:04 +00005476 insn->variant.cdas.details = cdas;
5477
5478 cdas->op1_high = op1_high;
5479 cdas->op1_low = op1_low;
5480 cdas->op2 = op2;
5481 cdas->op3_high = op3_high;
5482 cdas->op3_low = op3_low;
5483 cdas->old_mem_high = old_mem_high;
5484 cdas->old_mem_low = old_mem_low;
5485 cdas->scratch = scratch;
florian448cbba2012-06-06 02:26:01 +00005486
5487 return insn;
5488}
5489
5490
5491s390_insn *
sewardj2019a972011-03-07 16:04:07 +00005492s390_insn_compare(UChar size, HReg src1, s390_opnd_RMI src2,
5493 Bool signed_comparison)
5494{
5495 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5496
5497 vassert(size == 4 || size == 8);
5498
5499 insn->tag = S390_INSN_COMPARE;
5500 insn->size = size;
5501 insn->variant.compare.src1 = src1;
5502 insn->variant.compare.src2 = src2;
5503 insn->variant.compare.signed_comparison = signed_comparison;
5504
5505 return insn;
5506}
5507
5508
5509s390_insn *
sewardj2019a972011-03-07 16:04:07 +00005510s390_insn_helper_call(s390_cc_t cond, Addr64 target, UInt num_args,
sewardj74142b82013-08-08 10:28:59 +00005511 const HChar *name, RetLoc rloc)
sewardj2019a972011-03-07 16:04:07 +00005512{
5513 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
sewardj74142b82013-08-08 10:28:59 +00005514 s390_helper_call *helper_call = LibVEX_Alloc(sizeof(s390_helper_call));
sewardj2019a972011-03-07 16:04:07 +00005515
5516 insn->tag = S390_INSN_HELPER_CALL;
5517 insn->size = 0; /* does not matter */
sewardj74142b82013-08-08 10:28:59 +00005518 insn->variant.helper_call.details = helper_call;
5519
5520 helper_call->cond = cond;
5521 helper_call->target = target;
5522 helper_call->num_args = num_args;
5523 helper_call->name = name;
5524 helper_call->rloc = rloc;
5525
5526 vassert(is_sane_RetLoc(rloc));
sewardj2019a972011-03-07 16:04:07 +00005527
5528 return insn;
5529}
5530
5531
5532s390_insn *
5533s390_insn_bfp_triop(UChar size, s390_bfp_triop_t tag, HReg dst, HReg op2,
florian2c74d242012-09-12 19:38:42 +00005534 HReg op3)
sewardj2019a972011-03-07 16:04:07 +00005535{
5536 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5537
floriancc491a62012-09-10 23:44:37 +00005538 vassert(size == 4 || size == 8);
5539
sewardj2019a972011-03-07 16:04:07 +00005540 insn->tag = S390_INSN_BFP_TRIOP;
5541 insn->size = size;
5542 insn->variant.bfp_triop.tag = tag;
5543 insn->variant.bfp_triop.dst = dst;
5544 insn->variant.bfp_triop.op2 = op2;
5545 insn->variant.bfp_triop.op3 = op3;
sewardj2019a972011-03-07 16:04:07 +00005546
5547 return insn;
5548}
5549
5550
5551s390_insn *
florian2c74d242012-09-12 19:38:42 +00005552s390_insn_bfp_binop(UChar size, s390_bfp_binop_t tag, HReg dst, HReg op2)
sewardj2019a972011-03-07 16:04:07 +00005553{
5554 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5555
floriancc491a62012-09-10 23:44:37 +00005556 vassert(size == 4 || size == 8);
5557
sewardj2019a972011-03-07 16:04:07 +00005558 insn->tag = S390_INSN_BFP_BINOP;
5559 insn->size = size;
5560 insn->variant.bfp_binop.tag = tag;
floriancc491a62012-09-10 23:44:37 +00005561 insn->variant.bfp_binop.dst_hi = dst;
5562 insn->variant.bfp_binop.op2_hi = op2;
5563 insn->variant.bfp_binop.dst_lo = INVALID_HREG;
5564 insn->variant.bfp_binop.op2_lo = INVALID_HREG;
sewardj2019a972011-03-07 16:04:07 +00005565
5566 return insn;
5567}
5568
5569
5570s390_insn *
florian2c74d242012-09-12 19:38:42 +00005571s390_insn_bfp_unop(UChar size, s390_bfp_unop_t tag, HReg dst, HReg op)
sewardj2019a972011-03-07 16:04:07 +00005572{
5573 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5574
floriancc491a62012-09-10 23:44:37 +00005575 vassert(size == 4 || size == 8);
5576
sewardj2019a972011-03-07 16:04:07 +00005577 insn->tag = S390_INSN_BFP_UNOP;
5578 insn->size = size;
5579 insn->variant.bfp_unop.tag = tag;
floriancc491a62012-09-10 23:44:37 +00005580 insn->variant.bfp_unop.dst_hi = dst;
5581 insn->variant.bfp_unop.op_hi = op;
5582 insn->variant.bfp_unop.dst_lo = INVALID_HREG;
5583 insn->variant.bfp_unop.op_lo = INVALID_HREG;
sewardj2019a972011-03-07 16:04:07 +00005584
5585 return insn;
5586}
5587
5588
5589s390_insn *
5590s390_insn_bfp_compare(UChar size, HReg dst, HReg op1, HReg op2)
5591{
5592 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5593
5594 vassert(size == 4 || size == 8);
5595
5596 insn->tag = S390_INSN_BFP_COMPARE;
5597 insn->size = size;
5598 insn->variant.bfp_compare.dst = dst;
floriancc491a62012-09-10 23:44:37 +00005599 insn->variant.bfp_compare.op1_hi = op1;
5600 insn->variant.bfp_compare.op2_hi = op2;
5601 insn->variant.bfp_compare.op1_lo = INVALID_HREG;
5602 insn->variant.bfp_compare.op2_lo = INVALID_HREG;
sewardj2019a972011-03-07 16:04:07 +00005603
5604 return insn;
5605}
5606
5607
5608s390_insn *
florian6dc90242012-12-21 21:43:00 +00005609s390_insn_bfp_convert(UChar size, s390_bfp_conv_t tag, HReg dst, HReg op,
florian125e20d2012-10-07 15:42:37 +00005610 s390_bfp_round_t rounding_mode)
florian9fcff4c2012-09-10 03:09:04 +00005611{
5612 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5613
floriancc491a62012-09-10 23:44:37 +00005614 vassert(size == 4 || size == 8);
5615
florian9fcff4c2012-09-10 03:09:04 +00005616 insn->tag = S390_INSN_BFP_CONVERT;
5617 insn->size = size;
5618 insn->variant.bfp_convert.tag = tag;
floriancc491a62012-09-10 23:44:37 +00005619 insn->variant.bfp_convert.dst_hi = dst;
5620 insn->variant.bfp_convert.op_hi = op;
5621 insn->variant.bfp_convert.dst_lo = INVALID_HREG;
5622 insn->variant.bfp_convert.op_lo = INVALID_HREG;
florian9fcff4c2012-09-10 03:09:04 +00005623 insn->variant.bfp_convert.rounding_mode = rounding_mode;
5624
5625 return insn;
5626}
5627
5628
floriane38f6412012-12-21 17:32:12 +00005629/* Check validity of a register pair for 128-bit FP. Valid register
floriancc491a62012-09-10 23:44:37 +00005630 pairs are (0,2), (1,3), (4, 6), (5, 7), (8, 10), (9, 11), (12, 14),
5631 and (13, 15). */
5632static Bool
floriane38f6412012-12-21 17:32:12 +00005633is_valid_fp128_regpair(HReg hi, HReg lo)
floriancc491a62012-09-10 23:44:37 +00005634{
5635 UInt hi_regno = hregNumber(hi);
5636 UInt lo_regno = hregNumber(lo);
5637
5638 if (lo_regno != hi_regno + 2) return False;
5639 if ((hi_regno & 0x2) != 0) return False;
5640
5641 return True;
5642}
5643
florian9fcff4c2012-09-10 03:09:04 +00005644s390_insn *
sewardj2019a972011-03-07 16:04:07 +00005645s390_insn_bfp128_binop(UChar size, s390_bfp_binop_t tag, HReg dst_hi,
florian2c74d242012-09-12 19:38:42 +00005646 HReg dst_lo, HReg op2_hi, HReg op2_lo)
sewardj2019a972011-03-07 16:04:07 +00005647{
5648 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5649
floriancc491a62012-09-10 23:44:37 +00005650 vassert(size == 16);
floriane38f6412012-12-21 17:32:12 +00005651 vassert(is_valid_fp128_regpair(dst_hi, dst_lo));
5652 vassert(is_valid_fp128_regpair(op2_hi, op2_lo));
floriancc491a62012-09-10 23:44:37 +00005653
5654 insn->tag = S390_INSN_BFP_BINOP;
sewardj2019a972011-03-07 16:04:07 +00005655 insn->size = size;
floriancc491a62012-09-10 23:44:37 +00005656 insn->variant.bfp_binop.tag = tag;
5657 insn->variant.bfp_binop.dst_hi = dst_hi;
5658 insn->variant.bfp_binop.dst_lo = dst_lo;
5659 insn->variant.bfp_binop.op2_hi = op2_hi;
5660 insn->variant.bfp_binop.op2_lo = op2_lo;
sewardj2019a972011-03-07 16:04:07 +00005661
5662 return insn;
5663}
5664
5665
5666s390_insn *
sewardja970c402011-04-28 18:38:42 +00005667s390_insn_bfp128_unop(UChar size, s390_bfp_unop_t tag, HReg dst_hi,
florian2c74d242012-09-12 19:38:42 +00005668 HReg dst_lo, HReg op_hi, HReg op_lo)
sewardj2019a972011-03-07 16:04:07 +00005669{
5670 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5671
floriancc491a62012-09-10 23:44:37 +00005672 vassert(size == 16);
floriane38f6412012-12-21 17:32:12 +00005673 vassert(is_valid_fp128_regpair(dst_hi, dst_lo));
5674 vassert(is_valid_fp128_regpair(op_hi, op_lo));
floriancc491a62012-09-10 23:44:37 +00005675
5676 insn->tag = S390_INSN_BFP_UNOP;
sewardj2019a972011-03-07 16:04:07 +00005677 insn->size = size;
floriancc491a62012-09-10 23:44:37 +00005678 insn->variant.bfp_unop.tag = tag;
5679 insn->variant.bfp_unop.dst_hi = dst_hi;
5680 insn->variant.bfp_unop.dst_lo = dst_lo;
5681 insn->variant.bfp_unop.op_hi = op_hi;
5682 insn->variant.bfp_unop.op_lo = op_lo;
sewardj2019a972011-03-07 16:04:07 +00005683
5684 return insn;
5685}
5686
5687
5688s390_insn *
5689s390_insn_bfp128_compare(UChar size, HReg dst, HReg op1_hi, HReg op1_lo,
5690 HReg op2_hi, HReg op2_lo)
5691{
5692 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5693
floriancc491a62012-09-10 23:44:37 +00005694 vassert(size == 16);
floriane38f6412012-12-21 17:32:12 +00005695 vassert(is_valid_fp128_regpair(op1_hi, op1_lo));
5696 vassert(is_valid_fp128_regpair(op2_hi, op2_lo));
floriancc491a62012-09-10 23:44:37 +00005697
5698 insn->tag = S390_INSN_BFP_COMPARE;
sewardj2019a972011-03-07 16:04:07 +00005699 insn->size = size;
floriancc491a62012-09-10 23:44:37 +00005700 insn->variant.bfp_compare.dst = dst;
5701 insn->variant.bfp_compare.op1_hi = op1_hi;
5702 insn->variant.bfp_compare.op1_lo = op1_lo;
5703 insn->variant.bfp_compare.op2_hi = op2_hi;
5704 insn->variant.bfp_compare.op2_lo = op2_lo;
sewardj2019a972011-03-07 16:04:07 +00005705
5706 return insn;
5707}
5708
5709
florian9fcff4c2012-09-10 03:09:04 +00005710static s390_insn *
florian6dc90242012-12-21 21:43:00 +00005711s390_insn_bfp128_convert(UChar size, s390_bfp_conv_t tag, HReg dst_hi,
florian9fcff4c2012-09-10 03:09:04 +00005712 HReg dst_lo, HReg op_hi, HReg op_lo,
florian125e20d2012-10-07 15:42:37 +00005713 s390_bfp_round_t rounding_mode)
sewardj2019a972011-03-07 16:04:07 +00005714{
5715 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5716
floriancc491a62012-09-10 23:44:37 +00005717 if (size == 16) {
5718 /* From smaller size to 16 bytes */
floriane38f6412012-12-21 17:32:12 +00005719 vassert(is_valid_fp128_regpair(dst_hi, dst_lo));
florian79efdc62013-02-11 00:47:35 +00005720 vassert(hregIsInvalid(op_lo));
floriancc491a62012-09-10 23:44:37 +00005721 } else {
5722 /* From 16 bytes to smaller size */
floriane38f6412012-12-21 17:32:12 +00005723 vassert(is_valid_fp128_regpair(op_hi, op_lo));
floriancc491a62012-09-10 23:44:37 +00005724 }
5725
5726 insn->tag = S390_INSN_BFP_CONVERT;
sewardj2019a972011-03-07 16:04:07 +00005727 insn->size = size;
floriancc491a62012-09-10 23:44:37 +00005728 insn->variant.bfp_convert.tag = tag;
5729 insn->variant.bfp_convert.dst_hi = dst_hi;
5730 insn->variant.bfp_convert.dst_lo = dst_lo;
5731 insn->variant.bfp_convert.op_hi = op_hi;
5732 insn->variant.bfp_convert.op_lo = op_lo;
5733 insn->variant.bfp_convert.rounding_mode = rounding_mode;
sewardj2019a972011-03-07 16:04:07 +00005734
5735 return insn;
5736}
5737
5738
5739s390_insn *
florian6dc90242012-12-21 21:43:00 +00005740s390_insn_bfp128_convert_to(UChar size, s390_bfp_conv_t tag, HReg dst_hi,
florian9fcff4c2012-09-10 03:09:04 +00005741 HReg dst_lo, HReg op)
5742{
5743 /* Conversion to bfp128 never requires a rounding mode. Provide default
5744 rounding mode. It will not be used when emitting insns. */
florian125e20d2012-10-07 15:42:37 +00005745 s390_bfp_round_t rounding_mode = S390_BFP_ROUND_NEAREST_EVEN;
florian9fcff4c2012-09-10 03:09:04 +00005746
5747 return s390_insn_bfp128_convert(size, tag, dst_hi, dst_lo, op,
5748 INVALID_HREG, rounding_mode);
5749}
5750
5751
5752s390_insn *
floriana2039c52013-12-10 16:51:15 +00005753s390_insn_bfp128_convert_from(UChar size, s390_bfp_conv_t tag, HReg dst_hi,
5754 HReg dst_lo, HReg op_hi, HReg op_lo,
florian125e20d2012-10-07 15:42:37 +00005755 s390_bfp_round_t rounding_mode)
sewardj2019a972011-03-07 16:04:07 +00005756{
floriana2039c52013-12-10 16:51:15 +00005757 return s390_insn_bfp128_convert(size, tag, dst_hi, dst_lo, op_hi, op_lo,
florian9fcff4c2012-09-10 03:09:04 +00005758 rounding_mode);
sewardj2019a972011-03-07 16:04:07 +00005759}
5760
5761
sewardja52e37e2011-04-28 18:48:06 +00005762s390_insn *
florian12390202012-11-10 22:34:14 +00005763s390_insn_dfp_binop(UChar size, s390_dfp_binop_t tag, HReg dst, HReg op2,
5764 HReg op3, s390_dfp_round_t rounding_mode)
5765{
5766 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
florianc4aa7ed2012-12-22 15:01:04 +00005767 s390_dfp_binop *dfp_binop = LibVEX_Alloc(sizeof(s390_dfp_binop));
florian12390202012-11-10 22:34:14 +00005768
5769 vassert(size == 8);
5770
5771 insn->tag = S390_INSN_DFP_BINOP;
5772 insn->size = size;
florianc4aa7ed2012-12-22 15:01:04 +00005773 insn->variant.dfp_binop.details = dfp_binop;
5774
5775 dfp_binop->tag = tag;
5776 dfp_binop->dst_hi = dst;
5777 dfp_binop->op2_hi = op2;
5778 dfp_binop->op3_hi = op3;
5779 dfp_binop->dst_lo = INVALID_HREG;
5780 dfp_binop->op2_lo = INVALID_HREG;
5781 dfp_binop->op3_lo = INVALID_HREG;
5782 dfp_binop->rounding_mode = rounding_mode;
florian12390202012-11-10 22:34:14 +00005783
5784 return insn;
5785}
5786
5787
5788s390_insn *
floriance9e3db2012-12-27 20:14:03 +00005789s390_insn_dfp_unop(UChar size, s390_dfp_unop_t tag, HReg dst, HReg op)
5790{
5791 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5792
5793 vassert(size == 8);
5794
5795 insn->tag = S390_INSN_DFP_UNOP;
5796 insn->size = size;
5797 insn->variant.dfp_unop.tag = tag;
5798 insn->variant.dfp_unop.dst_hi = dst;
5799 insn->variant.dfp_unop.op_hi = op;
5800 insn->variant.dfp_unop.dst_lo = INVALID_HREG;
5801 insn->variant.dfp_unop.op_lo = INVALID_HREG;
5802
5803 return insn;
5804}
5805
5806
5807s390_insn *
florian1b901d42013-01-01 22:19:24 +00005808s390_insn_dfp_intop(UChar size, s390_dfp_intop_t tag, HReg dst, HReg op2,
5809 HReg op3)
5810{
5811 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5812
5813 vassert(size == 8);
5814
5815 insn->tag = S390_INSN_DFP_INTOP;
5816 insn->size = size;
5817 insn->variant.dfp_intop.tag = tag;
5818 insn->variant.dfp_intop.dst_hi = dst;
5819 insn->variant.dfp_intop.op2 = op2;
5820 insn->variant.dfp_intop.op3_hi = op3;
5821 insn->variant.dfp_intop.dst_lo = INVALID_HREG;
5822 insn->variant.dfp_intop.op3_lo = INVALID_HREG;
5823
5824 return insn;
5825}
5826
5827
5828s390_insn *
florian20c6bca2012-12-26 17:47:19 +00005829s390_insn_dfp_compare(UChar size, s390_dfp_cmp_t tag, HReg dst,
5830 HReg op1, HReg op2)
floriane38f6412012-12-21 17:32:12 +00005831{
5832 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5833
5834 vassert(size == 8);
5835
5836 insn->tag = S390_INSN_DFP_COMPARE;
5837 insn->size = size;
florian20c6bca2012-12-26 17:47:19 +00005838 insn->variant.dfp_compare.tag = tag;
floriane38f6412012-12-21 17:32:12 +00005839 insn->variant.dfp_compare.dst = dst;
5840 insn->variant.dfp_compare.op1_hi = op1;
5841 insn->variant.dfp_compare.op2_hi = op2;
5842 insn->variant.dfp_compare.op1_lo = INVALID_HREG;
5843 insn->variant.dfp_compare.op2_lo = INVALID_HREG;
5844
5845 return insn;
5846}
5847
5848
5849s390_insn *
5850s390_insn_dfp_convert(UChar size, s390_dfp_conv_t tag, HReg dst, HReg op,
5851 s390_dfp_round_t rounding_mode)
5852{
5853 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5854
florian06dfe212012-12-22 02:09:40 +00005855 vassert(size == 4 || size == 8);
floriane38f6412012-12-21 17:32:12 +00005856
5857 insn->tag = S390_INSN_DFP_CONVERT;
5858 insn->size = size;
5859 insn->variant.dfp_convert.tag = tag;
5860 insn->variant.dfp_convert.dst_hi = dst;
5861 insn->variant.dfp_convert.op_hi = op;
5862 insn->variant.dfp_convert.dst_lo = INVALID_HREG;
5863 insn->variant.dfp_convert.op_lo = INVALID_HREG;
5864 insn->variant.dfp_convert.rounding_mode = rounding_mode;
5865
5866 return insn;
5867}
5868
5869
5870s390_insn *
florian5c539732013-02-14 14:27:12 +00005871s390_insn_dfp_reround(UChar size, HReg dst, HReg op2, HReg op3,
5872 s390_dfp_round_t rounding_mode)
5873{
5874 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5875
5876 vassert(size == 8);
5877
5878 insn->tag = S390_INSN_DFP_REROUND;
5879 insn->size = size;
5880 insn->variant.dfp_reround.dst_hi = dst;
5881 insn->variant.dfp_reround.op2 = op2;
5882 insn->variant.dfp_reround.op3_hi = op3;
5883 insn->variant.dfp_reround.dst_lo = INVALID_HREG;
5884 insn->variant.dfp_reround.op3_lo = INVALID_HREG;
5885 insn->variant.dfp_reround.rounding_mode = rounding_mode;
5886
5887 return insn;
5888}
5889
5890
5891s390_insn *
florian78d5ef72013-05-11 15:02:58 +00005892s390_insn_fp_convert(UChar size, s390_fp_conv_t tag, HReg dst, HReg op,
5893 HReg r1, s390_dfp_round_t rounding_mode)
5894{
5895 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5896 s390_fp_convert *fp_convert = LibVEX_Alloc(sizeof(s390_fp_convert));
5897
5898 vassert(size == 4 || size == 8);
5899
5900 insn->tag = S390_INSN_FP_CONVERT;
5901 insn->size = size;
5902 insn->variant.fp_convert.details = fp_convert;
5903
5904 fp_convert->tag = tag;
5905 fp_convert->dst_hi = dst;
5906 fp_convert->op_hi = op;
5907 fp_convert->r1 = r1;
5908 fp_convert->dst_lo = INVALID_HREG;
5909 fp_convert->op_lo = INVALID_HREG;
5910 fp_convert->rounding_mode = rounding_mode;
5911
5912 return insn;
5913}
5914
5915
5916s390_insn *
5917s390_insn_fp128_convert(UChar size, s390_fp_conv_t tag, HReg dst_hi,
5918 HReg dst_lo, HReg op_hi, HReg op_lo, HReg r1,
5919 s390_dfp_round_t rounding_mode)
5920{
5921 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5922 s390_fp_convert *fp_convert = LibVEX_Alloc(sizeof(s390_fp_convert));
5923
5924 vassert(size == 16);
5925
5926 insn->tag = S390_INSN_FP_CONVERT;
5927 insn->size = size;
5928 insn->variant.fp_convert.details = fp_convert;
5929
5930 fp_convert->tag = tag;
5931 fp_convert->dst_hi = dst_hi;
5932 fp_convert->dst_lo = dst_lo;
5933 fp_convert->op_hi = op_hi;
5934 fp_convert->r1 = r1;
5935 fp_convert->op_lo = op_lo;
5936 fp_convert->rounding_mode = rounding_mode;
5937
5938 return insn;
5939}
5940
5941
5942s390_insn *
floriane38f6412012-12-21 17:32:12 +00005943s390_insn_dfp128_binop(UChar size, s390_dfp_binop_t tag, HReg dst_hi,
5944 HReg dst_lo, HReg op2_hi, HReg op2_lo, HReg op3_hi,
5945 HReg op3_lo, s390_dfp_round_t rounding_mode)
5946{
5947 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
florianc4aa7ed2012-12-22 15:01:04 +00005948 s390_dfp_binop *dfp_binop = LibVEX_Alloc(sizeof(s390_dfp_binop));
floriane38f6412012-12-21 17:32:12 +00005949
5950 vassert(size == 16);
5951 vassert(is_valid_fp128_regpair(dst_hi, dst_lo));
5952 vassert(is_valid_fp128_regpair(op2_hi, op2_lo));
5953 vassert(is_valid_fp128_regpair(op3_hi, op3_lo));
5954
floriane38f6412012-12-21 17:32:12 +00005955 insn->tag = S390_INSN_DFP_BINOP;
5956 insn->size = size;
florianc4aa7ed2012-12-22 15:01:04 +00005957 insn->variant.dfp_binop.details = dfp_binop;
5958
5959 dfp_binop->tag = tag;
5960 dfp_binop->dst_hi = dst_hi;
5961 dfp_binop->dst_lo = dst_lo;
5962 dfp_binop->op2_hi = op2_hi;
5963 dfp_binop->op2_lo = op2_lo;
5964 dfp_binop->op3_hi = op3_hi;
5965 dfp_binop->op3_lo = op3_lo;
5966 dfp_binop->rounding_mode = rounding_mode;
floriane38f6412012-12-21 17:32:12 +00005967
5968 return insn;
5969}
5970
5971
5972s390_insn *
floriance9e3db2012-12-27 20:14:03 +00005973s390_insn_dfp128_unop(UChar size, s390_dfp_unop_t tag, HReg dst,
5974 HReg op_hi, HReg op_lo)
5975{
5976 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5977
5978 /* destination is an 8 byte integer value */
5979 vassert(size == 8);
5980 vassert(is_valid_fp128_regpair(op_hi, op_lo));
5981
5982 insn->tag = S390_INSN_DFP_UNOP;
5983 insn->size = size;
5984 insn->variant.dfp_unop.tag = tag;
5985 insn->variant.dfp_unop.dst_hi = dst;
5986 insn->variant.dfp_unop.dst_lo = INVALID_HREG;
5987 insn->variant.dfp_unop.op_hi = op_hi;
5988 insn->variant.dfp_unop.op_lo = op_lo;
5989
5990 return insn;
5991}
5992
5993
5994s390_insn *
florian1b901d42013-01-01 22:19:24 +00005995s390_insn_dfp128_intop(UChar size, s390_dfp_intop_t tag, HReg dst_hi,
5996 HReg dst_lo, HReg op2, HReg op3_hi, HReg op3_lo)
5997{
5998 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
5999
6000 vassert(size == 16);
6001 vassert(is_valid_fp128_regpair(dst_hi, dst_lo));
6002 vassert(is_valid_fp128_regpair(op3_hi, op3_lo));
6003
6004 insn->tag = S390_INSN_DFP_INTOP;
6005 insn->size = size;
6006 insn->variant.dfp_intop.tag = tag;
6007 insn->variant.dfp_intop.dst_hi = dst_hi;
6008 insn->variant.dfp_intop.dst_lo = dst_lo;
6009 insn->variant.dfp_intop.op2 = op2;
6010 insn->variant.dfp_intop.op3_hi = op3_hi;
6011 insn->variant.dfp_intop.op3_lo = op3_lo;
6012
6013 return insn;
6014}
6015
6016
6017s390_insn *
florian20c6bca2012-12-26 17:47:19 +00006018s390_insn_dfp128_compare(UChar size, s390_dfp_cmp_t tag, HReg dst, HReg op1_hi,
6019 HReg op1_lo, HReg op2_hi, HReg op2_lo)
floriane38f6412012-12-21 17:32:12 +00006020{
6021 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
6022
6023 vassert(size == 16);
6024 vassert(is_valid_fp128_regpair(op1_hi, op1_lo));
6025 vassert(is_valid_fp128_regpair(op2_hi, op2_lo));
6026
6027 insn->tag = S390_INSN_DFP_COMPARE;
6028 insn->size = size;
florian20c6bca2012-12-26 17:47:19 +00006029 insn->variant.dfp_compare.tag = tag;
floriane38f6412012-12-21 17:32:12 +00006030 insn->variant.dfp_compare.dst = dst;
6031 insn->variant.dfp_compare.op1_hi = op1_hi;
6032 insn->variant.dfp_compare.op1_lo = op1_lo;
6033 insn->variant.dfp_compare.op2_hi = op2_hi;
6034 insn->variant.dfp_compare.op2_lo = op2_lo;
6035
6036 return insn;
6037}
6038
6039
6040static s390_insn *
6041s390_insn_dfp128_convert(UChar size, s390_dfp_conv_t tag, HReg dst_hi,
6042 HReg dst_lo, HReg op_hi, HReg op_lo,
6043 s390_dfp_round_t rounding_mode)
6044{
6045 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
6046
6047 if (size == 16) {
6048 /* From smaller size to 16 bytes */
6049 vassert(is_valid_fp128_regpair(dst_hi, dst_lo));
florian79efdc62013-02-11 00:47:35 +00006050 vassert(hregIsInvalid(op_lo));
floriane38f6412012-12-21 17:32:12 +00006051 } else {
6052 /* From 16 bytes to smaller size */
6053 vassert(is_valid_fp128_regpair(op_hi, op_lo));
floriane38f6412012-12-21 17:32:12 +00006054 }
6055
6056 insn->tag = S390_INSN_DFP_CONVERT;
6057 insn->size = size;
6058 insn->variant.dfp_convert.tag = tag;
6059 insn->variant.dfp_convert.dst_hi = dst_hi;
6060 insn->variant.dfp_convert.dst_lo = dst_lo;
6061 insn->variant.dfp_convert.op_hi = op_hi;
6062 insn->variant.dfp_convert.op_lo = op_lo;
6063 insn->variant.dfp_convert.rounding_mode = rounding_mode;
6064
6065 return insn;
6066}
6067
6068
6069s390_insn *
6070s390_insn_dfp128_convert_to(UChar size, s390_dfp_conv_t tag, HReg dst_hi,
6071 HReg dst_lo, HReg op)
6072{
6073 /* Conversion to dfp128 never requires a rounding mode. Provide default
6074 rounding mode. It will not be used when emitting insns. */
6075 s390_dfp_round_t rounding_mode = S390_DFP_ROUND_NEAREST_EVEN_4;
6076
6077 return s390_insn_dfp128_convert(size, tag, dst_hi, dst_lo, op,
6078 INVALID_HREG, rounding_mode);
6079}
6080
6081
6082s390_insn *
floriana2039c52013-12-10 16:51:15 +00006083s390_insn_dfp128_convert_from(UChar size, s390_dfp_conv_t tag, HReg dst_hi,
6084 HReg dst_lo, HReg op_hi, HReg op_lo,
floriane38f6412012-12-21 17:32:12 +00006085 s390_dfp_round_t rounding_mode)
6086{
floriana2039c52013-12-10 16:51:15 +00006087 return s390_insn_dfp128_convert(size, tag, dst_hi, dst_lo, op_hi, op_lo,
floriane38f6412012-12-21 17:32:12 +00006088 rounding_mode);
6089}
6090
6091
6092s390_insn *
florian5c539732013-02-14 14:27:12 +00006093s390_insn_dfp128_reround(UChar size, HReg dst_hi, HReg dst_lo, HReg op2,
6094 HReg op3_hi, HReg op3_lo,
6095 s390_dfp_round_t rounding_mode)
6096{
6097 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
6098
6099 vassert(size == 16);
6100 vassert(is_valid_fp128_regpair(dst_hi, dst_lo));
6101 vassert(is_valid_fp128_regpair(op3_hi, op3_lo));
6102
6103 insn->tag = S390_INSN_DFP_REROUND;
6104 insn->size = size;
6105 insn->variant.dfp_reround.dst_hi = dst_hi;
6106 insn->variant.dfp_reround.dst_lo = dst_lo;
6107 insn->variant.dfp_reround.op2 = op2;
6108 insn->variant.dfp_reround.op3_hi = op3_hi;
6109 insn->variant.dfp_reround.op3_lo = op3_lo;
6110 insn->variant.dfp_reround.rounding_mode = rounding_mode;
6111
6112 return insn;
6113}
6114
6115
6116s390_insn *
sewardja52e37e2011-04-28 18:48:06 +00006117s390_insn_mfence(void)
6118{
6119 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
6120
6121 insn->tag = S390_INSN_MFENCE;
6122 insn->size = 0; /* not needed */
6123
6124 return insn;
6125}
6126
6127
florianad43b3a2012-02-20 15:01:14 +00006128s390_insn *
florianb93348d2012-12-27 00:59:43 +00006129s390_insn_mimm(UChar size, s390_amode *dst, ULong value)
florianad43b3a2012-02-20 15:01:14 +00006130{
6131 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
6132
florianb93348d2012-12-27 00:59:43 +00006133 /* This insn will be mapped to insns that require base register
florian09bbba82012-12-11 04:09:43 +00006134 plus 12-bit displacement */
6135 vassert(dst->tag == S390_AMODE_B12);
6136
florianb93348d2012-12-27 00:59:43 +00006137 insn->tag = S390_INSN_MIMM;
florianad43b3a2012-02-20 15:01:14 +00006138 insn->size = size;
florianb93348d2012-12-27 00:59:43 +00006139 insn->variant.mimm.dst = dst;
6140 insn->variant.mimm.value = value;
florianad43b3a2012-02-20 15:01:14 +00006141
6142 return insn;
6143}
6144
6145
6146s390_insn *
florianf85fe3e2012-12-22 02:28:25 +00006147s390_insn_madd(UChar size, s390_amode *dst, UChar delta, ULong value)
florianad43b3a2012-02-20 15:01:14 +00006148{
6149 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
6150
florianf85fe3e2012-12-22 02:28:25 +00006151 vassert(size == 4 || size == 8);
6152
6153 /* This insn will be mapped to an ASI or AGSI so we can only allow base
6154 register plus 12-bit / 20-bit displacement. */
6155 vassert(dst->tag == S390_AMODE_B12 || dst->tag == S390_AMODE_B20);
florian49adf862014-12-06 20:24:08 +00006156 /* ASI and AGSI require the GIE facility */
6157 vassert(s390_host_has_gie);
florianf85fe3e2012-12-22 02:28:25 +00006158
6159 insn->tag = S390_INSN_MADD;
florianad43b3a2012-02-20 15:01:14 +00006160 insn->size = size;
florianf85fe3e2012-12-22 02:28:25 +00006161 insn->variant.madd.dst = dst;
6162 insn->variant.madd.delta = delta;
6163 insn->variant.madd.value = value;
florianad43b3a2012-02-20 15:01:14 +00006164
6165 return insn;
6166}
6167
6168
florian8844a632012-04-13 04:04:06 +00006169s390_insn *
florian125e20d2012-10-07 15:42:37 +00006170s390_insn_set_fpc_bfprm(UChar size, HReg mode)
florian2c74d242012-09-12 19:38:42 +00006171{
6172 vassert(size == 4);
6173
6174 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
6175
florian125e20d2012-10-07 15:42:37 +00006176 insn->tag = S390_INSN_SET_FPC_BFPRM;
florian2c74d242012-09-12 19:38:42 +00006177 insn->size = size;
florian125e20d2012-10-07 15:42:37 +00006178 insn->variant.set_fpc_bfprm.mode = mode;
florian2c74d242012-09-12 19:38:42 +00006179
6180 return insn;
6181}
6182
6183
6184s390_insn *
florianc8e4f562012-10-27 16:19:31 +00006185s390_insn_set_fpc_dfprm(UChar size, HReg mode)
6186{
6187 vassert(size == 4);
6188
6189 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
6190
6191 insn->tag = S390_INSN_SET_FPC_DFPRM;
6192 insn->size = size;
6193 insn->variant.set_fpc_dfprm.mode = mode;
6194
6195 return insn;
6196}
6197
6198
6199s390_insn *
florian8844a632012-04-13 04:04:06 +00006200s390_insn_xdirect(s390_cc_t cond, Addr64 dst, s390_amode *guest_IA,
6201 Bool to_fast_entry)
6202{
6203 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
6204
florian406ac942014-11-22 20:10:21 +00006205 vassert(guest_IA->tag == S390_AMODE_B12);
6206
florian8844a632012-04-13 04:04:06 +00006207 insn->tag = S390_INSN_XDIRECT;
6208 insn->size = 0; /* does not matter */
6209
6210 insn->variant.xdirect.cond = cond;
6211 insn->variant.xdirect.dst = dst;
6212 insn->variant.xdirect.guest_IA = guest_IA;
6213 insn->variant.xdirect.to_fast_entry = to_fast_entry;
6214
6215 return insn;
6216}
6217
6218
6219s390_insn *
6220s390_insn_xindir(s390_cc_t cond, HReg dst, s390_amode *guest_IA)
6221{
6222 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
6223
florian406ac942014-11-22 20:10:21 +00006224 vassert(guest_IA->tag == S390_AMODE_B12);
6225
florian7346c7a2012-04-13 21:14:24 +00006226 insn->tag = S390_INSN_XINDIR;
florian8844a632012-04-13 04:04:06 +00006227 insn->size = 0; /* does not matter */
6228
florian7346c7a2012-04-13 21:14:24 +00006229 insn->variant.xindir.cond = cond;
6230 insn->variant.xindir.dst = dst;
6231 insn->variant.xindir.guest_IA = guest_IA;
florian8844a632012-04-13 04:04:06 +00006232
6233 return insn;
6234}
6235
6236
6237s390_insn *
6238s390_insn_xassisted(s390_cc_t cond, HReg dst, s390_amode *guest_IA,
6239 IRJumpKind kind)
6240{
6241 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
6242
florian406ac942014-11-22 20:10:21 +00006243 vassert(guest_IA->tag == S390_AMODE_B12);
6244
florian8844a632012-04-13 04:04:06 +00006245 insn->tag = S390_INSN_XASSISTED;
6246 insn->size = 0; /* does not matter */
6247
6248 insn->variant.xassisted.cond = cond;
6249 insn->variant.xassisted.dst = dst;
6250 insn->variant.xassisted.guest_IA = guest_IA;
6251 insn->variant.xassisted.kind = kind;
6252
6253 return insn;
6254}
6255
6256
6257s390_insn *
6258s390_insn_evcheck(s390_amode *counter, s390_amode *fail_addr)
6259{
6260 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
6261
florianbf516d12012-04-21 15:53:13 +00006262 vassert(counter->tag == S390_AMODE_B12);
6263 vassert(fail_addr->tag == S390_AMODE_B12);
florian8844a632012-04-13 04:04:06 +00006264
6265 insn->tag = S390_INSN_EVCHECK;
6266 insn->size = 0; /* does not matter */
6267
6268 insn->variant.evcheck.counter = counter;
6269 insn->variant.evcheck.fail_addr = fail_addr;
6270
6271 return insn;
6272}
6273
6274
6275s390_insn *
6276s390_insn_profinc(void)
6277{
6278 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
6279
6280 insn->tag = S390_INSN_PROFINC;
6281 insn->size = 0; /* does not matter */
6282
6283 return insn;
6284}
6285
6286
sewardj2019a972011-03-07 16:04:07 +00006287/*---------------------------------------------------------------*/
6288/*--- Debug print ---*/
6289/*---------------------------------------------------------------*/
6290
6291static const HChar *
6292s390_cc_as_string(s390_cc_t cc)
6293{
6294 switch (cc) {
6295 case S390_CC_NEVER: return "never";
6296 case S390_CC_OVFL: return "overflow";
6297 case S390_CC_H: return "greater than"; /* A > B ; high */
6298 case S390_CC_NLE: return "not low or equal";
6299 case S390_CC_L: return "less than"; /* A < B ; low */
6300 case S390_CC_NHE: return "not high or equal";
6301 case S390_CC_LH: return "low or high";
6302 case S390_CC_NE: return "not equal"; /* A != B ; not zero */
6303 case S390_CC_E: return "equal"; /* A == B ; zero */
6304 case S390_CC_NLH: return "not low or high";
6305 case S390_CC_HE: return "greater or equal"; /* A >= B ; high or equal*/
6306 case S390_CC_NL: return "not low"; /* not low */
6307 case S390_CC_LE: return "less or equal"; /* A <= B ; low or equal */
6308 case S390_CC_NH: return "not high";
6309 case S390_CC_NO: return "not overflow";
6310 case S390_CC_ALWAYS: return "always";
6311 default:
6312 vpanic("s390_cc_as_string");
6313 }
6314}
6315
6316
florian8844a632012-04-13 04:04:06 +00006317static const HChar *
6318s390_jump_kind_as_string(IRJumpKind kind)
6319{
6320 switch (kind) {
6321 case Ijk_Boring: return "Boring";
6322 case Ijk_Call: return "Call";
6323 case Ijk_Ret: return "Return";
6324 case Ijk_ClientReq: return "ClientReq";
6325 case Ijk_Yield: return "Yield";
6326 case Ijk_EmWarn: return "EmWarn";
6327 case Ijk_EmFail: return "EmFail";
6328 case Ijk_NoDecode: return "NoDecode";
6329 case Ijk_MapFail: return "MapFail";
sewardj05f5e012014-05-04 10:52:11 +00006330 case Ijk_InvalICache: return "Invalidate";
florian8844a632012-04-13 04:04:06 +00006331 case Ijk_NoRedir: return "NoRedir";
6332 case Ijk_SigTRAP: return "SigTRAP";
6333 case Ijk_SigSEGV: return "SigSEGV";
6334 case Ijk_SigBUS: return "SigBUS";
6335 case Ijk_Sys_syscall: return "Sys_syscall";
6336 default:
6337 vpanic("s390_jump_kind_as_string");
6338 }
6339}
6340
6341
sewardj2019a972011-03-07 16:04:07 +00006342/* Helper function for writing out a V insn */
6343static void
florian55085f82012-11-21 00:36:55 +00006344s390_sprintf(HChar *buf, const HChar *fmt, ...)
sewardj2019a972011-03-07 16:04:07 +00006345{
6346 HChar *p;
6347 ULong value;
6348 va_list args;
6349 va_start(args, fmt);
6350
6351 p = buf;
6352 for ( ; *fmt; ++fmt) {
6353 Int c = *fmt;
6354
6355 if (c != '%') {
6356 *p++ = c;
6357 continue;
6358 }
6359
6360 c = *++fmt; /* next char */
6361 switch (c) {
6362 case '%':
6363 *p++ = c; /* %% */
6364 continue;
6365
6366 case 's': /* %s */
6367 p += vex_sprintf(p, "%s", va_arg(args, HChar *));
6368 continue;
6369
6370 case 'M': /* %M = mnemonic */
6371 p += vex_sprintf(p, "%-8s", va_arg(args, HChar *));
6372 continue;
6373
6374 case 'R': /* %R = register */
6375 p += vex_sprintf(p, "%s", s390_hreg_as_string(va_arg(args, HReg)));
6376 continue;
6377
6378 case 'A': /* %A = amode */
6379 p += vex_sprintf(p, "%s",
6380 s390_amode_as_string(va_arg(args, s390_amode *)));
6381 continue;
6382
florianad43b3a2012-02-20 15:01:14 +00006383 case 'G': /* %G = guest state @ offset */
6384 p += vex_sprintf(p, "guest[%d]", va_arg(args, UInt));
6385 continue;
6386
sewardj2019a972011-03-07 16:04:07 +00006387 case 'C': /* %C = condition code */
6388 p += vex_sprintf(p, "%s", s390_cc_as_string(va_arg(args, s390_cc_t)));
6389 continue;
6390
florian8844a632012-04-13 04:04:06 +00006391 case 'J': /* &J = jump kind */
6392 p += vex_sprintf(p, "%s",
6393 s390_jump_kind_as_string(va_arg(args, IRJumpKind)));
6394 continue;
6395
sewardj2019a972011-03-07 16:04:07 +00006396 case 'L': { /* %L = argument list in helper call*/
6397 UInt i, num_args;
6398
6399 num_args = va_arg(args, UInt);
6400
6401 for (i = 0; i < num_args; ++i) {
6402 if (i != 0) p += vex_sprintf(p, ", ");
6403 p += vex_sprintf(p, "r%d", s390_gprno_from_arg_index(i));
6404 }
6405 continue;
6406 }
6407
6408 case 'O': { /* %O = RMI operand */
6409 s390_opnd_RMI *op = va_arg(args, s390_opnd_RMI *);
6410
6411 switch (op->tag) {
6412 case S390_OPND_REG:
6413 p += vex_sprintf(p, "%s", s390_hreg_as_string(op->variant.reg));
6414 continue;
6415
6416 case S390_OPND_AMODE:
6417 p += vex_sprintf(p, "%s", s390_amode_as_string(op->variant.am));
6418 continue;
6419
6420 case S390_OPND_IMMEDIATE:
6421 value = op->variant.imm;
6422 goto print_value;
6423
6424 default:
6425 goto fail;
6426 }
6427 }
6428
6429 case 'I': /* %I = immediate value */
6430 value = va_arg(args, ULong);
6431 goto print_value;
6432
6433 print_value:
6434 if ((Long)value < 0)
6435 p += vex_sprintf(p, "%lld", (Long)value);
6436 else if (value < 100)
6437 p += vex_sprintf(p, "%llu", value);
6438 else
6439 p += vex_sprintf(p, "0x%llx", value);
6440 continue;
6441
6442 default:
6443 goto fail;
6444 }
6445 }
6446 *p = '\0';
6447 va_end(args);
6448
6449 return;
6450
6451 fail: vpanic("s390_printf");
6452}
6453
6454
6455/* Decompile the given insn into a static buffer and return it */
6456const HChar *
6457s390_insn_as_string(const s390_insn *insn)
6458{
florian8a45a4e2014-12-23 11:05:03 +00006459 static HChar buf[300]; // large enough
sewardj2019a972011-03-07 16:04:07 +00006460 const HChar *op;
6461 HChar *p;
6462
6463 buf[0] = '\0';
6464
6465 switch (insn->tag) {
6466 case S390_INSN_LOAD:
6467 s390_sprintf(buf, "%M %R,%A", "v-load", insn->variant.load.dst,
6468 insn->variant.load.src);
6469 break;
6470
6471 case S390_INSN_STORE:
6472 s390_sprintf(buf, "%M %R,%A", "v-store", insn->variant.store.src,
6473 insn->variant.store.dst);
6474 break;
6475
6476 case S390_INSN_MOVE:
6477 s390_sprintf(buf, "%M %R,%R", "v-move", insn->variant.move.dst,
6478 insn->variant.move.src);
6479 break;
6480
floriancec3a8a2013-02-02 00:16:58 +00006481 case S390_INSN_MEMCPY:
6482 s390_sprintf(buf, "%M %A,%A", "v-memcpy", insn->variant.memcpy.dst,
6483 insn->variant.memcpy.src);
6484 break;
6485
sewardj2019a972011-03-07 16:04:07 +00006486 case S390_INSN_COND_MOVE:
6487 s390_sprintf(buf, "%M if (%C) %R,%O", "v-move",
6488 insn->variant.cond_move.cond, insn->variant.cond_move.dst,
6489 &insn->variant.cond_move.src);
6490 break;
6491
6492 case S390_INSN_LOAD_IMMEDIATE:
6493 s390_sprintf(buf, "%M %R,%I", "v-loadi", insn->variant.load_immediate.dst,
6494 insn->variant.load_immediate.value);
6495 break;
6496
6497 case S390_INSN_ALU:
6498 switch (insn->variant.alu.tag) {
6499 case S390_ALU_ADD: op = "v-add"; break;
6500 case S390_ALU_SUB: op = "v-sub"; break;
6501 case S390_ALU_MUL: op = "v-mul"; break;
6502 case S390_ALU_AND: op = "v-and"; break;
6503 case S390_ALU_OR: op = "v-or"; break;
6504 case S390_ALU_XOR: op = "v-xor"; break;
6505 case S390_ALU_LSH: op = "v-lsh"; break;
6506 case S390_ALU_RSH: op = "v-rsh"; break;
6507 case S390_ALU_RSHA: op = "v-rsha"; break;
6508 default: goto fail;
6509 }
florian043af212012-06-06 02:44:53 +00006510 s390_sprintf(buf, "%M %R,%O", op, insn->variant.alu.dst, /* also op1 */
sewardj2019a972011-03-07 16:04:07 +00006511 &insn->variant.alu.op2);
6512 break;
6513
florianc4aa7ed2012-12-22 15:01:04 +00006514 case S390_INSN_SMUL:
6515 case S390_INSN_UMUL:
6516 if (insn->tag == S390_INSN_SMUL) {
sewardj2019a972011-03-07 16:04:07 +00006517 op = "v-muls";
6518 } else {
6519 op = "v-mulu";
6520 }
6521 s390_sprintf(buf, "%M %R,%O", op, insn->variant.mul.dst_hi,
6522 &insn->variant.mul.op2);
6523 break;
6524
florianc4aa7ed2012-12-22 15:01:04 +00006525 case S390_INSN_SDIV:
6526 case S390_INSN_UDIV:
6527 if (insn->tag == S390_INSN_SDIV) {
sewardj2019a972011-03-07 16:04:07 +00006528 op = "v-divs";
6529 } else {
6530 op = "v-divu";
6531 }
6532 s390_sprintf(buf, "%M %R,%O", op, insn->variant.div.op1_hi,
6533 &insn->variant.div.op2);
6534 break;
6535
6536 case S390_INSN_DIVS:
6537 s390_sprintf(buf, "%M %R,%O", "v-divsi", insn->variant.divs.op1,
6538 &insn->variant.divs.op2);
6539 break;
6540
sewardj611b06e2011-03-24 08:57:29 +00006541 case S390_INSN_CLZ:
6542 s390_sprintf(buf, "%M %R,%O", "v-clz", insn->variant.clz.num_bits,
6543 &insn->variant.clz.src);
sewardj2019a972011-03-07 16:04:07 +00006544 break;
6545
6546 case S390_INSN_UNOP:
6547 switch (insn->variant.unop.tag) {
6548 case S390_ZERO_EXTEND_8:
6549 case S390_ZERO_EXTEND_16:
6550 case S390_ZERO_EXTEND_32:
6551 op = "v-zerox";
6552 break;
6553
6554 case S390_SIGN_EXTEND_8:
6555 case S390_SIGN_EXTEND_16:
6556 case S390_SIGN_EXTEND_32:
6557 op = "v-signx";
6558 break;
6559
6560 case S390_NEGATE:
6561 op = "v-neg";
6562 break;
6563
6564 default:
6565 goto fail;
6566 }
6567 s390_sprintf(buf, "%M %R,%O", op, insn->variant.unop.dst,
6568 &insn->variant.unop.src);
6569 break;
6570
6571 case S390_INSN_TEST:
6572 s390_sprintf(buf, "%M %O", "v-test", &insn->variant.test.src);
6573 break;
6574
6575 case S390_INSN_CC2BOOL:
6576 s390_sprintf(buf, "%M %R,%C", "v-cc2b", insn->variant.cc2bool.dst,
6577 insn->variant.cc2bool.cond);
6578 break;
6579
6580 case S390_INSN_CAS:
6581 s390_sprintf(buf, "%M %R,%A,%R,%R", "v-cas", insn->variant.cas.op1,
6582 insn->variant.cas.op2, insn->variant.cas.op3,
6583 insn->variant.cas.old_mem);
6584 break;
6585
florianc4aa7ed2012-12-22 15:01:04 +00006586 case S390_INSN_CDAS: {
6587 s390_cdas *cdas = insn->variant.cdas.details;
6588
florian448cbba2012-06-06 02:26:01 +00006589 s390_sprintf(buf, "%M %R,%R,%A,%R,%R,%R,%R", "v-cdas",
florianc4aa7ed2012-12-22 15:01:04 +00006590 cdas->op1_high, cdas->op1_low, cdas->op2, cdas->op3_high,
6591 cdas->op3_low, cdas->old_mem_high, cdas->old_mem_low);
florian448cbba2012-06-06 02:26:01 +00006592 break;
florianc4aa7ed2012-12-22 15:01:04 +00006593 }
florian448cbba2012-06-06 02:26:01 +00006594
sewardj2019a972011-03-07 16:04:07 +00006595 case S390_INSN_COMPARE:
6596 if (insn->variant.compare.signed_comparison) {
6597 op = "v-cmps";
6598 } else {
6599 op = "v-cmpu";
6600 }
6601 s390_sprintf(buf, "%M %R,%O", op, insn->variant.compare.src1,
6602 &insn->variant.compare.src2);
6603 break;
6604
sewardj2019a972011-03-07 16:04:07 +00006605 case S390_INSN_HELPER_CALL: {
sewardj74142b82013-08-08 10:28:59 +00006606 s390_helper_call *helper_call = insn->variant.helper_call.details;
6607 s390_sprintf(buf, "%M if (%C) %s{%I}(%L)", "v-call",
6608 helper_call->cond,
6609 helper_call->name,
6610 helper_call->target,
6611 helper_call->num_args);
florian8844a632012-04-13 04:04:06 +00006612 return buf; /* avoid printing "size = ..." which is meaningless */
sewardj2019a972011-03-07 16:04:07 +00006613 }
6614
6615 case S390_INSN_BFP_TRIOP:
6616 switch (insn->variant.bfp_triop.tag) {
6617 case S390_BFP_MADD: op = "v-fmadd"; break;
6618 case S390_BFP_MSUB: op = "v-fmsub"; break;
6619 default: goto fail;
6620 }
florian043af212012-06-06 02:44:53 +00006621 s390_sprintf(buf, "%M %R,%R,%R", op,
sewardj2019a972011-03-07 16:04:07 +00006622 insn->variant.bfp_triop.dst /* op1 same as dst */,
6623 insn->variant.bfp_triop.op2, insn->variant.bfp_triop.op3);
6624 break;
6625
6626 case S390_INSN_BFP_BINOP:
6627 switch (insn->variant.bfp_binop.tag) {
6628 case S390_BFP_ADD: op = "v-fadd"; break;
6629 case S390_BFP_SUB: op = "v-fsub"; break;
6630 case S390_BFP_MUL: op = "v-fmul"; break;
6631 case S390_BFP_DIV: op = "v-fdiv"; break;
6632 default: goto fail;
6633 }
florian043af212012-06-06 02:44:53 +00006634 s390_sprintf(buf, "%M %R,%R", op,
floriancc491a62012-09-10 23:44:37 +00006635 insn->variant.bfp_binop.dst_hi /* op1 same as dst */,
6636 insn->variant.bfp_binop.op2_hi);
sewardj2019a972011-03-07 16:04:07 +00006637 break;
6638
6639 case S390_INSN_BFP_COMPARE:
6640 s390_sprintf(buf, "%M %R,%R,%R", "v-fcmp", insn->variant.bfp_compare.dst,
floriancc491a62012-09-10 23:44:37 +00006641 insn->variant.bfp_compare.op1_hi,
6642 insn->variant.bfp_compare.op2_hi);
sewardj2019a972011-03-07 16:04:07 +00006643 break;
6644
6645 case S390_INSN_BFP_UNOP:
6646 switch (insn->variant.bfp_unop.tag) {
6647 case S390_BFP_ABS: op = "v-fabs"; break;
6648 case S390_BFP_NABS: op = "v-fnabs"; break;
6649 case S390_BFP_NEG: op = "v-fneg"; break;
6650 case S390_BFP_SQRT: op = "v-fsqrt"; break;
florian9fcff4c2012-09-10 03:09:04 +00006651 default: goto fail;
6652 }
floriancc491a62012-09-10 23:44:37 +00006653 s390_sprintf(buf, "%M %R,%R", op, insn->variant.bfp_unop.dst_hi,
6654 insn->variant.bfp_unop.op_hi);
florian9fcff4c2012-09-10 03:09:04 +00006655 break;
6656
6657 case S390_INSN_BFP_CONVERT:
6658 switch (insn->variant.bfp_convert.tag) {
sewardj2019a972011-03-07 16:04:07 +00006659 case S390_BFP_I32_TO_F32:
6660 case S390_BFP_I32_TO_F64:
6661 case S390_BFP_I32_TO_F128:
6662 case S390_BFP_I64_TO_F32:
6663 case S390_BFP_I64_TO_F64:
6664 case S390_BFP_I64_TO_F128: op = "v-i2f"; break;
florian1c8f7ff2012-09-01 00:12:11 +00006665 case S390_BFP_U32_TO_F32:
6666 case S390_BFP_U32_TO_F64:
6667 case S390_BFP_U32_TO_F128:
6668 case S390_BFP_U64_TO_F32:
6669 case S390_BFP_U64_TO_F64:
6670 case S390_BFP_U64_TO_F128: op = "v-u2f"; break;
sewardj2019a972011-03-07 16:04:07 +00006671 case S390_BFP_F32_TO_I32:
6672 case S390_BFP_F32_TO_I64:
6673 case S390_BFP_F64_TO_I32:
6674 case S390_BFP_F64_TO_I64:
6675 case S390_BFP_F128_TO_I32:
6676 case S390_BFP_F128_TO_I64: op = "v-f2i"; break;
florian1c8f7ff2012-09-01 00:12:11 +00006677 case S390_BFP_F32_TO_U32:
6678 case S390_BFP_F32_TO_U64:
6679 case S390_BFP_F64_TO_U32:
6680 case S390_BFP_F64_TO_U64:
6681 case S390_BFP_F128_TO_U32:
6682 case S390_BFP_F128_TO_U64: op = "v-f2u"; break;
sewardj2019a972011-03-07 16:04:07 +00006683 case S390_BFP_F32_TO_F64:
6684 case S390_BFP_F32_TO_F128:
6685 case S390_BFP_F64_TO_F32:
6686 case S390_BFP_F64_TO_F128:
6687 case S390_BFP_F128_TO_F32:
6688 case S390_BFP_F128_TO_F64: op = "v-f2f"; break;
6689 default: goto fail;
6690 }
floriancc491a62012-09-10 23:44:37 +00006691 s390_sprintf(buf, "%M %R,%R", op, insn->variant.bfp_convert.dst_hi,
6692 insn->variant.bfp_convert.op_hi);
sewardj2019a972011-03-07 16:04:07 +00006693 break;
6694
florianc4aa7ed2012-12-22 15:01:04 +00006695 case S390_INSN_DFP_BINOP: {
6696 s390_dfp_binop *dfp_binop = insn->variant.dfp_binop.details;
6697
6698 switch (dfp_binop->tag) {
florian12390202012-11-10 22:34:14 +00006699 case S390_DFP_ADD: op = "v-dadd"; break;
6700 case S390_DFP_SUB: op = "v-dsub"; break;
6701 case S390_DFP_MUL: op = "v-dmul"; break;
6702 case S390_DFP_DIV: op = "v-ddiv"; break;
florian5c539732013-02-14 14:27:12 +00006703 case S390_DFP_QUANTIZE: op = "v-dqua"; break;
florian12390202012-11-10 22:34:14 +00006704 default: goto fail;
6705 }
florianc4aa7ed2012-12-22 15:01:04 +00006706 s390_sprintf(buf, "%M %R,%R,%R", op, dfp_binop->dst_hi,
6707 dfp_binop->op2_hi, dfp_binop->op3_hi);
florian12390202012-11-10 22:34:14 +00006708 break;
florianc4aa7ed2012-12-22 15:01:04 +00006709 }
florian12390202012-11-10 22:34:14 +00006710
floriance9e3db2012-12-27 20:14:03 +00006711 case S390_INSN_DFP_UNOP:
6712 switch (insn->variant.dfp_unop.tag) {
florian5c539732013-02-14 14:27:12 +00006713 case S390_DFP_EXTRACT_EXP_D64:
6714 case S390_DFP_EXTRACT_EXP_D128: op = "v-d2exp"; break;
floriance9e3db2012-12-27 20:14:03 +00006715 case S390_DFP_EXTRACT_SIG_D64:
6716 case S390_DFP_EXTRACT_SIG_D128: op = "v-d2sig"; break;
6717 default: goto fail;
6718 }
6719 s390_sprintf(buf, "%M %R,%R", op, insn->variant.dfp_unop.dst_hi,
6720 insn->variant.dfp_unop.op_hi);
6721 break;
6722
florian1b901d42013-01-01 22:19:24 +00006723 case S390_INSN_DFP_INTOP:
6724 switch (insn->variant.dfp_intop.tag) {
6725 case S390_DFP_SHIFT_LEFT: op = "v-dshl"; break;
6726 case S390_DFP_SHIFT_RIGHT: op = "v-dshr"; break;
florian5c539732013-02-14 14:27:12 +00006727 case S390_DFP_INSERT_EXP: op = "v-diexp"; break;
florian1b901d42013-01-01 22:19:24 +00006728 default: goto fail;
6729 }
6730 s390_sprintf(buf, "%M %R,%R,%R", op, insn->variant.dfp_intop.dst_hi,
6731 insn->variant.dfp_intop.op2,
6732 insn->variant.dfp_intop.op3_hi);
6733 break;
6734
floriane38f6412012-12-21 17:32:12 +00006735 case S390_INSN_DFP_COMPARE:
florian20c6bca2012-12-26 17:47:19 +00006736 switch (insn->variant.dfp_compare.tag) {
6737 case S390_DFP_COMPARE: op = "v-dcmp"; break;
6738 case S390_DFP_COMPARE_EXP: op = "v-dcmpexp"; break;
6739 default: goto fail;
6740 }
6741 s390_sprintf(buf, "%M %R,%R,%R", op, insn->variant.dfp_compare.dst,
floriane38f6412012-12-21 17:32:12 +00006742 insn->variant.dfp_compare.op1_hi,
6743 insn->variant.dfp_compare.op2_hi);
6744 break;
6745
6746 case S390_INSN_DFP_CONVERT:
6747 switch (insn->variant.dfp_convert.tag) {
6748 case S390_DFP_D32_TO_D64:
6749 case S390_DFP_D64_TO_D32:
6750 case S390_DFP_D64_TO_D128:
6751 case S390_DFP_D128_TO_D64: op = "v-d2d"; break;
florian5f034622013-01-13 02:29:05 +00006752 case S390_DFP_I32_TO_D64:
floriana887acd2013-02-08 23:32:54 +00006753 case S390_DFP_I32_TO_D128:
6754 case S390_DFP_I64_TO_D64:
6755 case S390_DFP_I64_TO_D128: op = "v-i2d"; break;
florian5f034622013-01-13 02:29:05 +00006756 case S390_DFP_U32_TO_D64:
6757 case S390_DFP_U32_TO_D128:
6758 case S390_DFP_U64_TO_D64:
6759 case S390_DFP_U64_TO_D128: op = "v-u2d"; break;
6760 case S390_DFP_D64_TO_I32:
floriana887acd2013-02-08 23:32:54 +00006761 case S390_DFP_D128_TO_I32:
6762 case S390_DFP_D64_TO_I64:
6763 case S390_DFP_D128_TO_I64: op = "v-d2i"; break;
florian5f034622013-01-13 02:29:05 +00006764 case S390_DFP_D64_TO_U32:
6765 case S390_DFP_D64_TO_U64:
6766 case S390_DFP_D128_TO_U32:
6767 case S390_DFP_D128_TO_U64: op = "v-d2u"; break;
floriane38f6412012-12-21 17:32:12 +00006768 default: goto fail;
6769 }
6770 s390_sprintf(buf, "%M %R,%R", op, insn->variant.dfp_convert.dst_hi,
6771 insn->variant.dfp_convert.op_hi);
6772 break;
6773
florian5c539732013-02-14 14:27:12 +00006774 case S390_INSN_DFP_REROUND:
6775 s390_sprintf(buf, "%M %R,%R,%R", "v-drrnd",
6776 insn->variant.dfp_reround.dst_hi,
6777 insn->variant.dfp_reround.op2,
6778 insn->variant.dfp_reround.op3_hi);
6779 break;
6780
florian78d5ef72013-05-11 15:02:58 +00006781 case S390_INSN_FP_CONVERT: {
6782 s390_fp_convert *fp_convert = insn->variant.fp_convert.details;
6783
6784 switch (fp_convert->tag) {
florian7ab421d2013-06-17 21:03:56 +00006785 case S390_FP_F32_TO_D32:
6786 case S390_FP_F32_TO_D64:
6787 case S390_FP_F32_TO_D128:
6788 case S390_FP_F64_TO_D32:
6789 case S390_FP_F64_TO_D64:
6790 case S390_FP_F64_TO_D128:
6791 case S390_FP_F128_TO_D32:
6792 case S390_FP_F128_TO_D64:
florian78d5ef72013-05-11 15:02:58 +00006793 case S390_FP_F128_TO_D128: op = "v-f2d"; break;
florian7ab421d2013-06-17 21:03:56 +00006794 case S390_FP_D32_TO_F32:
6795 case S390_FP_D32_TO_F64:
6796 case S390_FP_D32_TO_F128:
6797 case S390_FP_D64_TO_F32:
6798 case S390_FP_D64_TO_F64:
6799 case S390_FP_D64_TO_F128:
6800 case S390_FP_D128_TO_F32:
6801 case S390_FP_D128_TO_F64:
florian78d5ef72013-05-11 15:02:58 +00006802 case S390_FP_D128_TO_F128: op = "v-d2f"; break;
6803 default: goto fail;
6804 }
6805 s390_sprintf(buf, "%M %R,%R", op, fp_convert->dst_hi,
6806 fp_convert->op_hi);
6807 break;
6808 }
6809
sewardja52e37e2011-04-28 18:48:06 +00006810 case S390_INSN_MFENCE:
6811 s390_sprintf(buf, "%M", "v-mfence");
6812 return buf; /* avoid printing "size = ..." which is meaningless */
6813
florianb93348d2012-12-27 00:59:43 +00006814 case S390_INSN_MIMM:
6815 s390_sprintf(buf, "%M %A,%I", "v-mimm", insn->variant.mimm.dst,
6816 insn->variant.mimm.value);
florianad43b3a2012-02-20 15:01:14 +00006817 break;
6818
florianf85fe3e2012-12-22 02:28:25 +00006819 case S390_INSN_MADD:
6820 s390_sprintf(buf, "%M %A += %I (= %I)", "v-madd",
6821 insn->variant.madd.dst,
6822 (Long)(Char)insn->variant.madd.delta,
6823 insn->variant.madd.value);
florianad43b3a2012-02-20 15:01:14 +00006824 break;
6825
florian125e20d2012-10-07 15:42:37 +00006826 case S390_INSN_SET_FPC_BFPRM:
6827 s390_sprintf(buf, "%M %R", "v-set-fpc-bfprm",
6828 insn->variant.set_fpc_bfprm.mode);
florian2c74d242012-09-12 19:38:42 +00006829 break;
6830
florianc8e4f562012-10-27 16:19:31 +00006831 case S390_INSN_SET_FPC_DFPRM:
6832 s390_sprintf(buf, "%M %R", "v-set-fpc-dfprm",
6833 insn->variant.set_fpc_dfprm.mode);
6834 break;
6835
florian8844a632012-04-13 04:04:06 +00006836 case S390_INSN_EVCHECK:
6837 s390_sprintf(buf, "%M counter = %A, fail-addr = %A", "v-evcheck",
6838 insn->variant.evcheck.counter,
6839 insn->variant.evcheck.fail_addr);
6840 return buf; /* avoid printing "size = ..." which is meaningless */
6841
6842 case S390_INSN_PROFINC:
6843 s390_sprintf(buf, "%M", "v-profinc");
6844 return buf; /* avoid printing "size = ..." which is meaningless */
6845
6846 case S390_INSN_XDIRECT:
6847 s390_sprintf(buf, "%M if (%C) %A = %I %s", "v-xdirect",
6848 insn->variant.xdirect.cond,
6849 insn->variant.xdirect.guest_IA,
6850 insn->variant.xdirect.dst,
6851 insn->variant.xdirect.to_fast_entry ? "fast" : "slow");
6852 return buf; /* avoid printing "size = ..." which is meaningless */
6853
6854 case S390_INSN_XINDIR:
6855 s390_sprintf(buf, "%M if (%C) %A = %R", "v-xindir",
6856 insn->variant.xindir.cond,
6857 insn->variant.xindir.guest_IA,
6858 insn->variant.xindir.dst);
6859 return buf; /* avoid printing "size = ..." which is meaningless */
6860
6861 case S390_INSN_XASSISTED:
6862 s390_sprintf(buf, "%M if (%C) %J %A = %R", "v-xassisted",
6863 insn->variant.xassisted.cond,
6864 insn->variant.xassisted.kind,
6865 insn->variant.xassisted.guest_IA,
6866 insn->variant.xassisted.dst);
6867 return buf; /* avoid printing "size = ..." which is meaningless */
6868
sewardj2019a972011-03-07 16:04:07 +00006869 default: goto fail;
6870 }
6871
6872 /* Write out how many bytes are involved in the operation */
6873
6874 {
6875 UInt len, i;
6876
6877 for (p = buf; *p; ++p)
6878 continue;
6879
6880 len = p - buf;
6881
6882 if (len < 32) {
6883 for (i = len; i < 32; ++i)
6884 p += vex_sprintf(p, " ");
6885 } else {
6886 p += vex_sprintf(p, "\t");
6887 }
6888 }
6889
6890 /* Special cases first */
6891 switch (insn->tag) {
6892 case S390_INSN_UNOP:
6893 switch (insn->variant.unop.tag) {
6894 case S390_SIGN_EXTEND_8:
6895 case S390_ZERO_EXTEND_8: p += vex_sprintf(p, "1 -> "); goto common;
6896 case S390_SIGN_EXTEND_16:
6897 case S390_ZERO_EXTEND_16: p += vex_sprintf(p, "2 -> "); goto common;
6898 case S390_SIGN_EXTEND_32:
6899 case S390_ZERO_EXTEND_32: p += vex_sprintf(p, "4 -> "); goto common;
6900 default:
6901 goto common;
6902 }
6903
floriancc491a62012-09-10 23:44:37 +00006904 case S390_INSN_BFP_CONVERT:
6905 switch (insn->variant.bfp_convert.tag) {
sewardj2019a972011-03-07 16:04:07 +00006906 case S390_BFP_I32_TO_F32:
6907 case S390_BFP_I32_TO_F64:
6908 case S390_BFP_I32_TO_F128:
florian1c8f7ff2012-09-01 00:12:11 +00006909 case S390_BFP_U32_TO_F32:
6910 case S390_BFP_U32_TO_F64:
6911 case S390_BFP_U32_TO_F128:
sewardj2019a972011-03-07 16:04:07 +00006912 case S390_BFP_F32_TO_I32:
6913 case S390_BFP_F32_TO_I64:
florian1c8f7ff2012-09-01 00:12:11 +00006914 case S390_BFP_F32_TO_U32:
6915 case S390_BFP_F32_TO_U64:
sewardj2019a972011-03-07 16:04:07 +00006916 case S390_BFP_F32_TO_F64:
6917 case S390_BFP_F32_TO_F128: p += vex_sprintf(p, "4 -> "); goto common;
6918 case S390_BFP_I64_TO_F32:
6919 case S390_BFP_I64_TO_F64:
6920 case S390_BFP_I64_TO_F128:
florian1c8f7ff2012-09-01 00:12:11 +00006921 case S390_BFP_U64_TO_F32:
6922 case S390_BFP_U64_TO_F64:
6923 case S390_BFP_U64_TO_F128:
sewardj2019a972011-03-07 16:04:07 +00006924 case S390_BFP_F64_TO_I32:
6925 case S390_BFP_F64_TO_I64:
florian1c8f7ff2012-09-01 00:12:11 +00006926 case S390_BFP_F64_TO_U32:
6927 case S390_BFP_F64_TO_U64:
sewardj2019a972011-03-07 16:04:07 +00006928 case S390_BFP_F64_TO_F32:
6929 case S390_BFP_F64_TO_F128: p += vex_sprintf(p, "8 -> "); goto common;
6930 case S390_BFP_F128_TO_I32:
6931 case S390_BFP_F128_TO_I64:
florian1c8f7ff2012-09-01 00:12:11 +00006932 case S390_BFP_F128_TO_U32:
6933 case S390_BFP_F128_TO_U64:
sewardj2019a972011-03-07 16:04:07 +00006934 case S390_BFP_F128_TO_F32:
6935 case S390_BFP_F128_TO_F64: p += vex_sprintf(p, "16 -> "); goto common;
6936 default:
6937 goto common;
6938 }
6939
floriane38f6412012-12-21 17:32:12 +00006940 case S390_INSN_DFP_CONVERT:
6941 switch (insn->variant.dfp_convert.tag) {
florian5f034622013-01-13 02:29:05 +00006942 case S390_DFP_D32_TO_D64:
6943 case S390_DFP_I32_TO_D64:
6944 case S390_DFP_I32_TO_D128:
6945 case S390_DFP_U32_TO_D64:
6946 case S390_DFP_U32_TO_D128: p += vex_sprintf(p, "4 -> "); goto common;
floriane38f6412012-12-21 17:32:12 +00006947 case S390_DFP_D64_TO_D32:
florian5f034622013-01-13 02:29:05 +00006948 case S390_DFP_D64_TO_D128:
floriana887acd2013-02-08 23:32:54 +00006949 case S390_DFP_I64_TO_D64:
6950 case S390_DFP_I64_TO_D128:
florian5f034622013-01-13 02:29:05 +00006951 case S390_DFP_U64_TO_D64:
6952 case S390_DFP_U64_TO_D128:
6953 case S390_DFP_D64_TO_I32:
floriana887acd2013-02-08 23:32:54 +00006954 case S390_DFP_D64_TO_I64:
florian5f034622013-01-13 02:29:05 +00006955 case S390_DFP_D64_TO_U32:
6956 case S390_DFP_D64_TO_U64: p += vex_sprintf(p, "8 -> "); goto common;
6957 case S390_DFP_D128_TO_D64:
6958 case S390_DFP_D128_TO_I32:
floriana887acd2013-02-08 23:32:54 +00006959 case S390_DFP_D128_TO_I64:
florian5f034622013-01-13 02:29:05 +00006960 case S390_DFP_D128_TO_U32:
6961 case S390_DFP_D128_TO_U64: p += vex_sprintf(p, "16 -> "); goto common;
floriane38f6412012-12-21 17:32:12 +00006962 default:
6963 goto common;
6964 }
6965
florian78d5ef72013-05-11 15:02:58 +00006966 case S390_INSN_FP_CONVERT: {
6967 s390_fp_convert *fp_convert = insn->variant.fp_convert.details;
6968
6969 switch (fp_convert->tag) {
florian7ab421d2013-06-17 21:03:56 +00006970 case S390_FP_F32_TO_D32:
6971 case S390_FP_F32_TO_D64:
6972 case S390_FP_F32_TO_D128:
6973 case S390_FP_D32_TO_F32:
6974 case S390_FP_D32_TO_F64:
6975 case S390_FP_D32_TO_F128: p += vex_sprintf(p, "4 -> "); goto common;
6976 case S390_FP_F64_TO_D32:
florian78d5ef72013-05-11 15:02:58 +00006977 case S390_FP_F64_TO_D64:
florian7ab421d2013-06-17 21:03:56 +00006978 case S390_FP_F64_TO_D128:
6979 case S390_FP_D64_TO_F32:
florian78d5ef72013-05-11 15:02:58 +00006980 case S390_FP_D64_TO_F64:
florian7ab421d2013-06-17 21:03:56 +00006981 case S390_FP_D64_TO_F128: p += vex_sprintf(p, "8 -> "); goto common;
6982 case S390_FP_F128_TO_D32:
6983 case S390_FP_F128_TO_D64:
florian78d5ef72013-05-11 15:02:58 +00006984 case S390_FP_F128_TO_D128:
florian7ab421d2013-06-17 21:03:56 +00006985 case S390_FP_D128_TO_F32:
6986 case S390_FP_D128_TO_F64:
florian78d5ef72013-05-11 15:02:58 +00006987 case S390_FP_D128_TO_F128: p += vex_sprintf(p, "16 -> "); goto common;
6988 default:
6989 goto common;
6990 }
6991 }
6992
sewardj2019a972011-03-07 16:04:07 +00006993 default:
6994 goto common;
6995 }
6996
6997 /* Common case */
6998 common:
6999 vex_sprintf(p, "%u bytes", (UInt)insn->size);
7000
7001 return buf;
7002
7003 fail: vpanic("s390_insn_as_string");
7004}
7005
7006
7007
7008/* Load NUM bytes from memory into register REG using addressing mode AM. */
7009static UChar *
7010s390_emit_load_mem(UChar *p, UInt num, UChar reg, const s390_amode *am)
7011{
7012 UInt b = hregNumber(am->b);
7013 UInt x = hregNumber(am->x); /* 0 for B12 and B20 */
7014 UInt d = am->d;
7015
7016 switch (am->tag) {
7017 case S390_AMODE_B12:
7018 case S390_AMODE_BX12:
7019 switch (num) {
7020 case 1: return s390_emit_IC(p, reg, x, b, d);
7021 case 2: return s390_emit_LH(p, reg, x, b, d);
7022 case 4: return s390_emit_L(p, reg, x, b, d);
7023 case 8: return s390_emit_LG(p, reg, x, b, DISP20(d));
7024 default: goto fail;
7025 }
7026 break;
7027
7028 case S390_AMODE_B20:
7029 case S390_AMODE_BX20:
7030 switch (num) {
7031 case 1: return s390_emit_ICY(p, reg, x, b, DISP20(d));
7032 case 2: return s390_emit_LHY(p, reg, x, b, DISP20(d));
7033 case 4: return s390_emit_LY(p, reg, x, b, DISP20(d));
7034 case 8: return s390_emit_LG(p, reg, x, b, DISP20(d));
7035 default: goto fail;
7036 }
7037 break;
7038
7039 default: goto fail;
7040 }
7041
7042 fail:
7043 vpanic("s390_emit_load_mem");
7044}
7045
7046
7047/* Load condition code into register REG */
7048static UChar *
7049s390_emit_load_cc(UChar *p, UChar reg)
7050{
7051 p = s390_emit_LGHI(p, reg, 0); /* Clear out, cc not affected */
7052 p = s390_emit_IPM(p, reg, reg);
7053 /* Shift 28 bits to the right --> [0,1,2,3] */
sewardjf74c86f2011-04-05 14:04:53 +00007054 return s390_emit_SRL(p, reg, 0, 28); /* REG = cc */
sewardj2019a972011-03-07 16:04:07 +00007055}
7056
7057
7058/*---------------------------------------------------------------*/
7059/*--- Code generation ---*/
7060/*---------------------------------------------------------------*/
7061
7062/* Do not load more bytes than requested. */
7063static UChar *
7064s390_insn_load_emit(UChar *buf, const s390_insn *insn)
7065{
7066 UInt r, x, b, d;
7067 const s390_amode *src;
7068
7069 src = insn->variant.load.src;
7070
7071 r = hregNumber(insn->variant.load.dst);
7072
7073 if (hregClass(insn->variant.load.dst) == HRcFlt64) {
7074 b = hregNumber(src->b);
7075 x = hregNumber(src->x); /* 0 for B12 and B20 */
7076 d = src->d;
7077
7078 switch (insn->size) {
7079
7080 case 4:
7081 switch (src->tag) {
7082 case S390_AMODE_B12:
7083 case S390_AMODE_BX12:
7084 return s390_emit_LE(buf, r, x, b, d);
7085
7086 case S390_AMODE_B20:
7087 case S390_AMODE_BX20:
7088 return s390_emit_LEY(buf, r, x, b, DISP20(d));
7089 }
7090 break;
7091
7092 case 8:
7093 switch (src->tag) {
7094 case S390_AMODE_B12:
7095 case S390_AMODE_BX12:
7096 return s390_emit_LD(buf, r, x, b, d);
7097
7098 case S390_AMODE_B20:
7099 case S390_AMODE_BX20:
7100 return s390_emit_LDY(buf, r, x, b, DISP20(d));
7101 }
7102 break;
7103 }
7104 vpanic("s390_insn_load_emit");
7105 }
7106
7107 /* Integer stuff */
7108 return s390_emit_load_mem(buf, insn->size, r, src);
7109}
7110
7111
7112static UChar *
7113s390_insn_store_emit(UChar *buf, const s390_insn *insn)
7114{
7115 UInt r, x, b, d;
7116 const s390_amode *dst;
7117
7118 dst = insn->variant.store.dst;
7119
7120 r = hregNumber(insn->variant.store.src);
7121 b = hregNumber(dst->b);
7122 x = hregNumber(dst->x); /* 0 for B12 and B20 */
7123 d = dst->d;
7124
7125 if (hregClass(insn->variant.store.src) == HRcFlt64) {
7126 switch (insn->size) {
7127
7128 case 4:
7129 switch (dst->tag) {
7130 case S390_AMODE_B12:
7131 case S390_AMODE_BX12:
7132 return s390_emit_STE(buf, r, x, b, d);
7133
7134 case S390_AMODE_B20:
7135 case S390_AMODE_BX20:
7136 return s390_emit_STEY(buf, r, x, b, DISP20(d));
7137 }
7138 break;
7139
7140 case 8:
7141 switch (dst->tag) {
7142 case S390_AMODE_B12:
7143 case S390_AMODE_BX12:
7144 return s390_emit_STD(buf, r, x, b, d);
7145
7146 case S390_AMODE_B20:
7147 case S390_AMODE_BX20:
7148 return s390_emit_STDY(buf, r, x, b, DISP20(d));
7149 }
7150 break;
7151 }
7152 vpanic("s390_insn_store_emit");
7153 }
7154
7155 /* Integer stuff */
7156 switch (insn->size) {
7157 case 1:
7158 switch (dst->tag) {
7159 case S390_AMODE_B12:
7160 case S390_AMODE_BX12:
7161 return s390_emit_STC(buf, r, x, b, d);
7162
7163 case S390_AMODE_B20:
7164 case S390_AMODE_BX20:
7165 return s390_emit_STCY(buf, r, x, b, DISP20(d));
7166 }
7167 break;
7168
7169 case 2:
7170 switch (dst->tag) {
7171 case S390_AMODE_B12:
7172 case S390_AMODE_BX12:
7173 return s390_emit_STH(buf, r, x, b, d);
7174
7175 case S390_AMODE_B20:
7176 case S390_AMODE_BX20:
7177 return s390_emit_STHY(buf, r, x, b, DISP20(d));
7178 }
7179 break;
7180
7181 case 4:
7182 switch (dst->tag) {
7183 case S390_AMODE_B12:
7184 case S390_AMODE_BX12:
7185 return s390_emit_ST(buf, r, x, b, d);
7186
7187 case S390_AMODE_B20:
7188 case S390_AMODE_BX20:
7189 return s390_emit_STY(buf, r, x, b, DISP20(d));
7190 }
7191 break;
7192
7193 case 8:
7194 return s390_emit_STG(buf, r, x, b, DISP20(d));
7195
7196 default:
7197 break;
7198 }
7199
7200 vpanic("s390_insn_store_emit");
7201}
7202
7203
7204static UChar *
7205s390_insn_move_emit(UChar *buf, const s390_insn *insn)
7206{
7207 UInt dst, src;
7208 HRegClass dst_class, src_class;
7209
7210 dst = hregNumber(insn->variant.move.dst);
7211 src = hregNumber(insn->variant.move.src);
7212
7213 dst_class = hregClass(insn->variant.move.dst);
7214 src_class = hregClass(insn->variant.move.src);
7215
7216 if (dst_class == src_class) {
7217 if (dst_class == HRcInt64)
7218 return s390_emit_LGR(buf, dst, src);
7219 if (dst_class == HRcFlt64)
7220 return s390_emit_LDR(buf, dst, src);
7221 } else {
floriana782a172011-12-18 15:51:54 +00007222 if (dst_class == HRcFlt64 && src_class == HRcInt64) {
7223 if (insn->size == 4) {
7224 buf = s390_emit_SLLG(buf, R0, src, 0, DISP20(32)); /* r0 = src << 32 */
7225 return s390_emit_LDGRw(buf, dst, R0);
7226 } else {
7227 return s390_emit_LDGRw(buf, dst, src);
7228 }
7229 }
7230 if (dst_class == HRcInt64 && src_class == HRcFlt64) {
7231 if (insn->size == 4) {
7232 buf = s390_emit_LGDRw(buf, dst, src);
7233 return s390_emit_SRLG(buf, dst, dst, 0, DISP20(32)); /* dst >>= 32 */
7234 } else {
7235 return s390_emit_LGDRw(buf, dst, src);
7236 }
7237 }
sewardj2019a972011-03-07 16:04:07 +00007238 /* A move between floating point registers and general purpose
7239 registers of different size should never occur and indicates
7240 an error elsewhere. */
7241 }
7242
7243 vpanic("s390_insn_move_emit");
7244}
7245
7246
7247static UChar *
floriancec3a8a2013-02-02 00:16:58 +00007248s390_insn_memcpy_emit(UChar *buf, const s390_insn *insn)
7249{
7250 s390_amode *dst = insn->variant.memcpy.dst;
7251 s390_amode *src = insn->variant.memcpy.src;
7252
7253 return s390_emit_MVC(buf, insn->size - 1, hregNumber(dst->b), dst->d,
7254 hregNumber(src->b), src->d);
7255}
7256
7257
7258static UChar *
sewardj2019a972011-03-07 16:04:07 +00007259s390_insn_load_immediate_emit(UChar *buf, const s390_insn *insn)
7260{
7261 UInt r;
7262 ULong value = insn->variant.load_immediate.value;
7263
7264 r = hregNumber(insn->variant.load_immediate.dst);
7265
7266 if (hregClass(insn->variant.load_immediate.dst) == HRcFlt64) {
7267 vassert(value == 0);
7268 switch (insn->size) {
7269 case 4: return s390_emit_LZER(buf, r, value);
7270 case 8: return s390_emit_LZDR(buf, r, value);
7271 }
7272 vpanic("s390_insn_load_immediate_emit");
7273 }
7274
7275 switch (insn->size) {
7276 case 1:
7277 case 2:
7278 /* Load the immediate values as a 4 byte value. That does not hurt as
7279 those extra bytes will not be looked at. Fall through .... */
7280 case 4:
7281 return s390_emit_load_32imm(buf, r, value);
7282
7283 case 8:
7284 return s390_emit_load_64imm(buf, r, value);
7285 }
7286
7287 vpanic("s390_insn_load_immediate_emit");
7288}
7289
7290
7291/* There is no easy way to do ALU operations on 1-byte or 2-byte operands.
7292 So we simply perform a 4-byte operation. Doing so uses possibly undefined
7293 bits and produces an undefined result in those extra bit positions. But
7294 upstream does not look at those positions, so this is OK. */
7295static UChar *
7296s390_insn_alu_emit(UChar *buf, const s390_insn *insn)
7297{
7298 s390_opnd_RMI op2;
7299 UInt dst;
7300
7301 dst = hregNumber(insn->variant.alu.dst);
7302 op2 = insn->variant.alu.op2;
7303
7304 /* Second operand is in a register */
7305 if (op2.tag == S390_OPND_REG) {
7306 UInt r2 = hregNumber(op2.variant.reg);
7307
7308 switch (insn->size) {
7309 case 1:
7310 case 2:
7311 case 4:
7312 switch (insn->variant.alu.tag) {
7313 case S390_ALU_ADD: return s390_emit_AR(buf, dst, r2);
7314 case S390_ALU_SUB: return s390_emit_SR(buf, dst, r2);
7315 case S390_ALU_MUL: return s390_emit_MSR(buf, dst, r2);
7316 case S390_ALU_AND: return s390_emit_NR(buf, dst, r2);
7317 case S390_ALU_OR: return s390_emit_OR(buf, dst, r2);
7318 case S390_ALU_XOR: return s390_emit_XR(buf, dst, r2);
sewardj3c49aaa2011-04-05 14:00:37 +00007319 case S390_ALU_LSH: return s390_emit_SLL(buf, dst, r2, 0);
7320 case S390_ALU_RSH: return s390_emit_SRL(buf, dst, r2, 0);
7321 case S390_ALU_RSHA: return s390_emit_SRA(buf, dst, r2, 0);
sewardj2019a972011-03-07 16:04:07 +00007322 }
7323 goto fail;
7324
7325 case 8:
7326 switch (insn->variant.alu.tag) {
7327 case S390_ALU_ADD: return s390_emit_AGR(buf, dst, r2);
7328 case S390_ALU_SUB: return s390_emit_SGR(buf, dst, r2);
7329 case S390_ALU_MUL: return s390_emit_MSGR(buf, dst, r2);
7330 case S390_ALU_AND: return s390_emit_NGR(buf, dst, r2);
7331 case S390_ALU_OR: return s390_emit_OGR(buf, dst, r2);
7332 case S390_ALU_XOR: return s390_emit_XGR(buf, dst, r2);
7333 case S390_ALU_LSH: return s390_emit_SLLG(buf, dst, dst, r2, DISP20(0));
7334 case S390_ALU_RSH: return s390_emit_SRLG(buf, dst, dst, r2, DISP20(0));
7335 case S390_ALU_RSHA: return s390_emit_SRAG(buf, dst, dst, r2, DISP20(0));
7336 }
7337 goto fail;
7338 }
7339 goto fail;
7340 }
7341
7342 /* 2nd operand is in memory */
7343 if (op2.tag == S390_OPND_AMODE) {
7344 UInt b, x, d;
7345 const s390_amode *src = op2.variant.am;
7346
7347 b = hregNumber(src->b);
7348 x = hregNumber(src->x); /* 0 for B12 and B20 */
7349 d = src->d;
7350
7351 /* Shift operands are special here as there are no opcodes that
sewardje0dd77e2011-04-27 12:07:01 +00007352 allow a memory operand. So we first load the 2nd operand into
7353 some register. R0 is used to save restore the contents of the
7354 chosen register.. */
sewardj652b56a2011-04-13 15:38:17 +00007355
sewardj2019a972011-03-07 16:04:07 +00007356 if (insn->variant.alu.tag == S390_ALU_LSH ||
7357 insn->variant.alu.tag == S390_ALU_RSH ||
7358 insn->variant.alu.tag == S390_ALU_RSHA) {
sewardje0dd77e2011-04-27 12:07:01 +00007359 UInt b2;
sewardj2019a972011-03-07 16:04:07 +00007360
sewardje0dd77e2011-04-27 12:07:01 +00007361 /* Choose a register (other than DST or R0) into which to stick the
7362 shift amount. The following works because r15 is reserved and
7363 thusly dst != 15. */
7364 vassert(dst != 15); /* extra paranoia */
7365 b2 = (dst + 1) % 16;
7366
7367 buf = s390_emit_LGR(buf, R0, b2); /* save */
7368
7369 /* Loading SRC to B2 does not modify R0. */
7370 buf = s390_emit_load_mem(buf, insn->size, b2, src);
sewardj2019a972011-03-07 16:04:07 +00007371
7372 if (insn->size == 8) {
sewardje0dd77e2011-04-27 12:07:01 +00007373 switch (insn->variant.alu.tag) {
7374 case S390_ALU_LSH:
7375 buf = s390_emit_SLLG(buf, dst, dst, b2, DISP20(0));
7376 break;
7377 case S390_ALU_RSH:
7378 buf = s390_emit_SRLG(buf, dst, dst, b2, DISP20(0));
7379 break;
7380 case S390_ALU_RSHA:
7381 buf = s390_emit_SRAG(buf, dst, dst, b2, DISP20(0));
7382 break;
7383 default: /* unreachable */
7384 goto fail;
7385 }
sewardj2019a972011-03-07 16:04:07 +00007386 } else {
sewardje0dd77e2011-04-27 12:07:01 +00007387 switch (insn->variant.alu.tag) {
7388 case S390_ALU_LSH:
7389 buf = s390_emit_SLL(buf, dst, b2, 0);
7390 break;
7391 case S390_ALU_RSH:
7392 buf = s390_emit_SRL(buf, dst, b2, 0);
7393 break;
7394 case S390_ALU_RSHA:
7395 buf = s390_emit_SRA(buf, dst, b2, 0);
7396 break;
7397 default: /* unreachable */
7398 goto fail;
7399 }
sewardj2019a972011-03-07 16:04:07 +00007400 }
sewardje0dd77e2011-04-27 12:07:01 +00007401 return s390_emit_LGR(buf, b2, R0); /* restore */
sewardj2019a972011-03-07 16:04:07 +00007402 }
7403
7404 switch (insn->size) {
7405 case 1:
7406 /* Move the byte from memory into scratch register r0 */
7407 buf = s390_emit_load_mem(buf, 1, R0, src);
7408
7409 switch (insn->variant.alu.tag) {
7410 case S390_ALU_ADD: return s390_emit_AR(buf, dst, R0);
7411 case S390_ALU_SUB: return s390_emit_SR(buf, dst, R0);
7412 case S390_ALU_MUL: return s390_emit_MSR(buf, dst, R0);
7413 case S390_ALU_AND: return s390_emit_NR(buf, dst, R0);
7414 case S390_ALU_OR: return s390_emit_OR(buf, dst, R0);
7415 case S390_ALU_XOR: return s390_emit_XR(buf, dst, R0);
7416 case S390_ALU_LSH:
7417 case S390_ALU_RSH:
7418 case S390_ALU_RSHA: ; /* avoid GCC warning */
7419 }
7420 goto fail;
7421
7422 case 2:
7423 switch (src->tag) {
7424 case S390_AMODE_B12:
7425 case S390_AMODE_BX12:
7426 switch (insn->variant.alu.tag) {
7427 case S390_ALU_ADD:
7428 return s390_emit_AH(buf, dst, x, b, d);
7429
7430 case S390_ALU_SUB:
7431 return s390_emit_SH(buf, dst, x, b, d);
7432
7433 case S390_ALU_MUL:
7434 return s390_emit_MH(buf, dst, x, b, d);
7435
7436 /* For bitwise operations: Move two bytes from memory into scratch
7437 register r0; then perform operation */
7438 case S390_ALU_AND:
7439 buf = s390_emit_LH(buf, R0, x, b, d);
7440 return s390_emit_NR(buf, dst, R0);
7441
7442 case S390_ALU_OR:
7443 buf = s390_emit_LH(buf, R0, x, b, d);
7444 return s390_emit_OR(buf, dst, R0);
7445
7446 case S390_ALU_XOR:
7447 buf = s390_emit_LH(buf, R0, x, b, d);
7448 return s390_emit_XR(buf, dst, R0);
7449
7450 case S390_ALU_LSH:
7451 case S390_ALU_RSH:
7452 case S390_ALU_RSHA: ; /* avoid GCC warning */
7453 }
7454 goto fail;
7455
7456 case S390_AMODE_B20:
7457 case S390_AMODE_BX20:
7458 switch (insn->variant.alu.tag) {
7459 case S390_ALU_ADD:
7460 return s390_emit_AHY(buf, dst, x, b, DISP20(d));
7461
7462 case S390_ALU_SUB:
7463 return s390_emit_SHY(buf, dst, x, b, DISP20(d));
7464
7465 case S390_ALU_MUL:
sewardjeae8db52011-03-24 09:01:50 +00007466 return s390_emit_MHYw(buf, dst, x, b, DISP20(d));
sewardj2019a972011-03-07 16:04:07 +00007467
7468 /* For bitwise operations: Move two bytes from memory into scratch
7469 register r0; then perform operation */
7470 case S390_ALU_AND:
7471 buf = s390_emit_LHY(buf, R0, x, b, DISP20(d));
7472 return s390_emit_NR(buf, dst, R0);
7473
7474 case S390_ALU_OR:
7475 buf = s390_emit_LHY(buf, R0, x, b, DISP20(d));
7476 return s390_emit_OR(buf, dst, R0);
7477
7478 case S390_ALU_XOR:
7479 buf = s390_emit_LHY(buf, R0, x, b, DISP20(d));
7480 return s390_emit_XR(buf, dst, R0);
7481
7482 case S390_ALU_LSH:
7483 case S390_ALU_RSH:
7484 case S390_ALU_RSHA: ; /* avoid GCC warning */
7485 }
7486 goto fail;
7487 }
7488 goto fail;
7489
7490 case 4:
7491 switch (src->tag) {
7492 case S390_AMODE_B12:
7493 case S390_AMODE_BX12:
7494 switch (insn->variant.alu.tag) {
7495 case S390_ALU_ADD: return s390_emit_A(buf, dst, x, b, d);
7496 case S390_ALU_SUB: return s390_emit_S(buf, dst, x, b, d);
7497 case S390_ALU_MUL: return s390_emit_MS(buf, dst, x, b, d);
7498 case S390_ALU_AND: return s390_emit_N(buf, dst, x, b, d);
7499 case S390_ALU_OR: return s390_emit_O(buf, dst, x, b, d);
7500 case S390_ALU_XOR: return s390_emit_X(buf, dst, x, b, d);
7501 case S390_ALU_LSH:
7502 case S390_ALU_RSH:
7503 case S390_ALU_RSHA: ; /* avoid GCC warning */
7504 }
7505 goto fail;
7506
7507 case S390_AMODE_B20:
7508 case S390_AMODE_BX20:
7509 switch (insn->variant.alu.tag) {
7510 case S390_ALU_ADD: return s390_emit_AY(buf, dst, x, b, DISP20(d));
7511 case S390_ALU_SUB: return s390_emit_SY(buf, dst, x, b, DISP20(d));
7512 case S390_ALU_MUL: return s390_emit_MSY(buf, dst, x, b, DISP20(d));
7513 case S390_ALU_AND: return s390_emit_NY(buf, dst, x, b, DISP20(d));
7514 case S390_ALU_OR: return s390_emit_OY(buf, dst, x, b, DISP20(d));
7515 case S390_ALU_XOR: return s390_emit_XY(buf, dst, x, b, DISP20(d));
7516 case S390_ALU_LSH:
7517 case S390_ALU_RSH:
7518 case S390_ALU_RSHA: ; /* avoid GCC warning */
7519 }
7520 goto fail;
7521 }
7522 goto fail;
7523
7524 case 8:
7525 switch (insn->variant.alu.tag) {
7526 case S390_ALU_ADD: return s390_emit_AG(buf, dst, x, b, DISP20(d));
7527 case S390_ALU_SUB: return s390_emit_SG(buf, dst, x, b, DISP20(d));
7528 case S390_ALU_MUL: return s390_emit_MSG(buf, dst, x, b, DISP20(d));
7529 case S390_ALU_AND: return s390_emit_NG(buf, dst, x, b, DISP20(d));
7530 case S390_ALU_OR: return s390_emit_OG(buf, dst, x, b, DISP20(d));
7531 case S390_ALU_XOR: return s390_emit_XG(buf, dst, x, b, DISP20(d));
7532 case S390_ALU_LSH:
7533 case S390_ALU_RSH:
7534 case S390_ALU_RSHA: ; /* avoid GCC warning */
7535 }
7536 goto fail;
7537 }
7538 goto fail;
7539 }
7540
7541 /* 2nd operand is an immediate value */
7542 if (op2.tag == S390_OPND_IMMEDIATE) {
7543 ULong value;
7544
7545 /* No masking of the value is required as it is not sign extended */
7546 value = op2.variant.imm;
7547
7548 switch (insn->size) {
7549 case 1:
7550 case 2:
7551 /* There is no 1-byte opcode. Do the computation in
7552 2 bytes. The extra byte will be ignored. */
7553 switch (insn->variant.alu.tag) {
7554 case S390_ALU_ADD:
7555 return s390_emit_AHI(buf, dst, value);
7556
7557 case S390_ALU_SUB:
sewardjb13a92a2011-04-13 14:44:29 +00007558 return s390_emit_SLFIw(buf, dst, value);
sewardj2019a972011-03-07 16:04:07 +00007559
7560 case S390_ALU_MUL:
7561 return s390_emit_MHI(buf, dst, value);
7562
7563 case S390_ALU_AND: return s390_emit_NILL(buf, dst, value);
7564 case S390_ALU_OR: return s390_emit_OILL(buf, dst, value);
7565 case S390_ALU_XOR:
7566 /* There is no XILL instruction. Load the immediate value into
7567 R0 and combine with the destination register. */
7568 buf = s390_emit_LHI(buf, R0, value);
7569 return s390_emit_XR(buf, dst, R0);
7570
7571 case S390_ALU_LSH:
sewardj3c49aaa2011-04-05 14:00:37 +00007572 return s390_emit_SLL(buf, dst, 0, value);
sewardj2019a972011-03-07 16:04:07 +00007573
7574 case S390_ALU_RSH:
sewardj3c49aaa2011-04-05 14:00:37 +00007575 return s390_emit_SRL(buf, dst, 0, value);
sewardj2019a972011-03-07 16:04:07 +00007576
7577 case S390_ALU_RSHA:
sewardj3c49aaa2011-04-05 14:00:37 +00007578 return s390_emit_SRA(buf, dst, 0, value);
sewardj2019a972011-03-07 16:04:07 +00007579 }
7580 goto fail;
7581
7582 case 4:
7583 switch (insn->variant.alu.tag) {
7584 case S390_ALU_ADD:
7585 if (uint_fits_signed_16bit(value)) {
7586 return s390_emit_AHI(buf, dst, value);
7587 }
7588 return s390_emit_AFIw(buf, dst, value);
7589
7590 case S390_ALU_SUB: return s390_emit_SLFIw(buf, dst, value);
7591 case S390_ALU_MUL: return s390_emit_MSFIw(buf, dst, value);
7592 case S390_ALU_AND: return s390_emit_NILFw(buf, dst, value);
7593 case S390_ALU_OR: return s390_emit_OILFw(buf, dst, value);
7594 case S390_ALU_XOR: return s390_emit_XILFw(buf, dst, value);
sewardj3c49aaa2011-04-05 14:00:37 +00007595 case S390_ALU_LSH: return s390_emit_SLL(buf, dst, 0, value);
7596 case S390_ALU_RSH: return s390_emit_SRL(buf, dst, 0, value);
7597 case S390_ALU_RSHA: return s390_emit_SRA(buf, dst, 0, value);
sewardj2019a972011-03-07 16:04:07 +00007598 }
7599 goto fail;
7600
7601 case 8:
7602 switch (insn->variant.alu.tag) {
7603 case S390_ALU_ADD:
7604 if (ulong_fits_signed_16bit(value)) {
7605 return s390_emit_AGHI(buf, dst, value);
7606 }
7607 if (ulong_fits_signed_32bit(value) && s390_host_has_eimm) {
7608 return s390_emit_AGFI(buf, dst, value);
7609 }
7610 /* Load constant into R0 then add */
7611 buf = s390_emit_load_64imm(buf, R0, value);
7612 return s390_emit_AGR(buf, dst, R0);
7613
7614 case S390_ALU_SUB:
sewardjb13a92a2011-04-13 14:44:29 +00007615 if (ulong_fits_unsigned_32bit(value)) {
7616 return s390_emit_SLGFIw(buf, dst, value);
7617 }
sewardj2019a972011-03-07 16:04:07 +00007618 /* Load value into R0; then subtract from destination reg */
7619 buf = s390_emit_load_64imm(buf, R0, value);
7620 return s390_emit_SGR(buf, dst, R0);
7621
7622 case S390_ALU_MUL:
7623 if (ulong_fits_signed_32bit(value) && s390_host_has_gie) {
7624 return s390_emit_MSGFI(buf, dst, value);
7625 }
7626 /* Load constant into R0 then add */
7627 buf = s390_emit_load_64imm(buf, R0, value);
7628 return s390_emit_MSGR(buf, dst, R0);
7629
7630 /* Do it in two steps: upper half [0:31] and lower half [32:63] */
7631 case S390_ALU_AND:
7632 if (s390_host_has_eimm) {
7633 buf = s390_emit_NIHF(buf, dst, value >> 32);
7634 return s390_emit_NILF(buf, dst, value & 0xFFFFFFFF);
7635 }
7636 /* Load value into R0; then combine with destination reg */
7637 buf = s390_emit_load_64imm(buf, R0, value);
7638 return s390_emit_NGR(buf, dst, R0);
7639
7640 case S390_ALU_OR:
7641 if (s390_host_has_eimm) {
7642 buf = s390_emit_OIHF(buf, dst, value >> 32);
7643 return s390_emit_OILF(buf, dst, value & 0xFFFFFFFF);
7644 }
7645 /* Load value into R0; then combine with destination reg */
7646 buf = s390_emit_load_64imm(buf, R0, value);
7647 return s390_emit_OGR(buf, dst, R0);
7648
7649 case S390_ALU_XOR:
7650 if (s390_host_has_eimm) {
7651 buf = s390_emit_XIHF(buf, dst, value >> 32);
7652 return s390_emit_XILF(buf, dst, value & 0xFFFFFFFF);
7653 }
7654 /* Load value into R0; then combine with destination reg */
7655 buf = s390_emit_load_64imm(buf, R0, value);
7656 return s390_emit_XGR(buf, dst, R0);
7657
sewardj652b56a2011-04-13 15:38:17 +00007658 /* No special considerations for long displacement here. Only the six
7659 least significant bits of VALUE will be taken; all other bits are
7660 ignored. So the DH2 bits are irrelevant and do not influence the
7661 shift operation, independent of whether long-displacement is available
7662 or not. */
sewardj2019a972011-03-07 16:04:07 +00007663 case S390_ALU_LSH: return s390_emit_SLLG(buf, dst, dst, 0, DISP20(value));
7664 case S390_ALU_RSH: return s390_emit_SRLG(buf, dst, dst, 0, DISP20(value));
7665 case S390_ALU_RSHA: return s390_emit_SRAG(buf, dst, dst, 0, DISP20(value));
7666 }
7667 goto fail;
7668 }
7669 goto fail;
7670 }
7671
7672 fail:
7673 vpanic("s390_insn_alu_emit");
7674}
7675
7676
7677static UChar *
7678s390_widen_emit(UChar *buf, const s390_insn *insn, UInt from_size,
7679 Bool sign_extend)
7680{
sewardj06122e72011-03-28 12:14:48 +00007681 s390_opnd_RMI opnd = insn->variant.unop.src;
sewardj2019a972011-03-07 16:04:07 +00007682
7683 switch (opnd.tag) {
7684 case S390_OPND_REG: {
7685 UChar r1 = hregNumber(insn->variant.unop.dst);
7686 UChar r2 = hregNumber(opnd.variant.reg);
7687
7688 switch (from_size) {
7689 case 1:
7690 /* Widening to a half-word is implemented like widening to a word
7691 because the upper half-word will not be looked at. */
7692 if (insn->size == 4 || insn->size == 2) { /* 8 --> 32 8 --> 16 */
7693 if (sign_extend)
7694 return s390_emit_LBRw(buf, r1, r2);
7695 else
7696 return s390_emit_LLCRw(buf, r1, r2);
7697 }
7698 if (insn->size == 8) { /* 8 --> 64 */
7699 if (sign_extend)
7700 return s390_emit_LGBRw(buf, r1, r2);
7701 else
7702 return s390_emit_LLGCRw(buf, r1, r2);
7703 }
7704 goto fail;
7705
7706 case 2:
7707 if (insn->size == 4) { /* 16 --> 32 */
7708 if (sign_extend)
7709 return s390_emit_LHRw(buf, r1, r2);
7710 else
7711 return s390_emit_LLHRw(buf, r1, r2);
7712 }
7713 if (insn->size == 8) { /* 16 --> 64 */
7714 if (sign_extend)
7715 return s390_emit_LGHRw(buf, r1, r2);
7716 else
7717 return s390_emit_LLGHRw(buf, r1, r2);
7718 }
7719 goto fail;
7720
7721 case 4:
7722 if (insn->size == 8) { /* 32 --> 64 */
7723 if (sign_extend)
7724 return s390_emit_LGFR(buf, r1, r2);
7725 else
7726 return s390_emit_LLGFR(buf, r1, r2);
7727 }
7728 goto fail;
7729
7730 default: /* unexpected "from" size */
7731 goto fail;
7732 }
7733 }
7734
7735 case S390_OPND_AMODE: {
7736 UChar r1 = hregNumber(insn->variant.unop.dst);
7737 const s390_amode *src = opnd.variant.am;
7738 UChar b = hregNumber(src->b);
7739 UChar x = hregNumber(src->x);
7740 Int d = src->d;
7741
7742 switch (from_size) {
7743 case 1:
7744 if (insn->size == 4 || insn->size == 2) {
7745 if (sign_extend)
floriandc6e7472014-12-08 14:01:33 +00007746 return s390_emit_LB(buf, r1, x, b, DISP20(d));
sewardj2019a972011-03-07 16:04:07 +00007747 else
7748 return s390_emit_LLCw(buf, r1, x, b, DISP20(d));
7749 }
7750 if (insn->size == 8) {
7751 if (sign_extend)
floriandc6e7472014-12-08 14:01:33 +00007752 return s390_emit_LGB(buf, r1, x, b, DISP20(d));
sewardj2019a972011-03-07 16:04:07 +00007753 else
sewardj2019a972011-03-07 16:04:07 +00007754 return s390_emit_LLGC(buf, r1, x, b, DISP20(d));
7755 }
7756 goto fail;
7757
7758 case 2:
7759 if (insn->size == 4) { /* 16 --> 32 */
7760 if (sign_extend == 0)
7761 return s390_emit_LLHw(buf, r1, x, b, DISP20(d));
7762
7763 switch (src->tag) {
7764 case S390_AMODE_B12:
7765 case S390_AMODE_BX12:
7766 return s390_emit_LH(buf, r1, x, b, d);
7767
7768 case S390_AMODE_B20:
7769 case S390_AMODE_BX20:
7770 return s390_emit_LHY(buf, r1, x, b, DISP20(d));
7771 }
7772 goto fail;
7773 }
7774 if (insn->size == 8) { /* 16 --> 64 */
sewardj2019a972011-03-07 16:04:07 +00007775 if (sign_extend)
7776 return s390_emit_LGH(buf, r1, x, b, DISP20(d));
7777 else
7778 return s390_emit_LLGH(buf, r1, x, b, DISP20(d));
7779 }
7780 goto fail;
7781
7782 case 4:
7783 if (insn->size == 8) { /* 32 --> 64 */
sewardj2019a972011-03-07 16:04:07 +00007784 if (sign_extend)
7785 return s390_emit_LGF(buf, r1, x, b, DISP20(d));
7786 else
7787 return s390_emit_LLGF(buf, r1, x, b, DISP20(d));
7788 }
7789 goto fail;
7790
7791 default: /* unexpected "from" size */
7792 goto fail;
7793 }
7794 }
7795
7796 case S390_OPND_IMMEDIATE: {
7797 UChar r1 = hregNumber(insn->variant.unop.dst);
7798 ULong value = opnd.variant.imm;
7799
7800 switch (from_size) {
7801 case 1:
7802 if (insn->size == 4 || insn->size == 2) { /* 8 --> 32 8 --> 16 */
7803 if (sign_extend) {
7804 /* host can do the sign extension to 16-bit; LHI does the rest */
7805 return s390_emit_LHI(buf, r1, (Short)(Char)(UChar)value);
7806 } else {
7807 return s390_emit_LHI(buf, r1, value);
7808 }
7809 }
7810 if (insn->size == 8) { /* 8 --> 64 */
7811 if (sign_extend) {
7812 /* host can do the sign extension to 16-bit; LGHI does the rest */
7813 return s390_emit_LGHI(buf, r1, (Short)(Char)(UChar)value);
7814 } else {
7815 return s390_emit_LGHI(buf, r1, value);
7816 }
7817 }
7818 goto fail;
7819
7820 case 2:
7821 if (insn->size == 4) { /* 16 --> 32 */
7822 return s390_emit_LHI(buf, r1, value);
7823 }
7824 if (insn->size == 8) { /* 16 --> 64 */
7825 if (sign_extend)
7826 return s390_emit_LGHI(buf, r1, value);
7827 else
7828 return s390_emit_LLILL(buf, r1, value);
7829 }
7830 goto fail;
7831
7832 case 4:
7833 if (insn->size == 8) { /* 32 --> 64 */
7834 if (sign_extend)
7835 return s390_emit_LGFIw(buf, r1, value);
7836 else
7837 return s390_emit_LLILFw(buf, r1, value);
7838 }
7839 goto fail;
7840
7841 default: /* unexpected "from" size */
7842 goto fail;
7843 }
7844 }
7845 }
7846
7847 fail:
7848 vpanic("s390_widen_emit");
7849}
7850
7851
7852static UChar *
7853s390_negate_emit(UChar *buf, const s390_insn *insn)
7854{
7855 s390_opnd_RMI opnd;
7856
7857 opnd = insn->variant.unop.src;
7858
7859 switch (opnd.tag) {
7860 case S390_OPND_REG: {
7861 UChar r1 = hregNumber(insn->variant.unop.dst);
7862 UChar r2 = hregNumber(opnd.variant.reg);
7863
7864 switch (insn->size) {
7865 case 1:
7866 case 2:
7867 case 4:
7868 return s390_emit_LCR(buf, r1, r2);
7869
7870 case 8:
7871 return s390_emit_LCGR(buf, r1, r2);
7872
7873 default:
7874 goto fail;
7875 }
7876 }
7877
7878 case S390_OPND_AMODE: {
7879 UChar r1 = hregNumber(insn->variant.unop.dst);
7880
7881 /* Load bytes into scratch register R0, then negate */
7882 buf = s390_emit_load_mem(buf, insn->size, R0, opnd.variant.am);
7883
7884 switch (insn->size) {
7885 case 1:
7886 case 2:
7887 case 4:
7888 return s390_emit_LCR(buf, r1, R0);
7889
7890 case 8:
7891 return s390_emit_LCGR(buf, r1, R0);
7892
7893 default:
7894 goto fail;
7895 }
7896 }
7897
7898 case S390_OPND_IMMEDIATE: {
7899 UChar r1 = hregNumber(insn->variant.unop.dst);
7900 ULong value = opnd.variant.imm;
7901
7902 value = ~value + 1; /* two's complement */
7903
7904 switch (insn->size) {
7905 case 1:
7906 case 2:
7907 /* Load the immediate values as a 4 byte value. That does not hurt as
7908 those extra bytes will not be looked at. Fall through .... */
7909 case 4:
7910 return s390_emit_load_32imm(buf, r1, value);
7911
7912 case 8:
7913 return s390_emit_load_64imm(buf, r1, value);
7914
7915 default:
7916 goto fail;
7917 }
7918 }
7919 }
7920
7921 fail:
7922 vpanic("s390_negate_emit");
7923}
7924
7925
7926static UChar *
7927s390_insn_unop_emit(UChar *buf, const s390_insn *insn)
7928{
7929 switch (insn->variant.unop.tag) {
7930 case S390_ZERO_EXTEND_8: return s390_widen_emit(buf, insn, 1, 0);
7931 case S390_ZERO_EXTEND_16: return s390_widen_emit(buf, insn, 2, 0);
7932 case S390_ZERO_EXTEND_32: return s390_widen_emit(buf, insn, 4, 0);
7933
7934 case S390_SIGN_EXTEND_8: return s390_widen_emit(buf, insn, 1, 1);
7935 case S390_SIGN_EXTEND_16: return s390_widen_emit(buf, insn, 2, 1);
7936 case S390_SIGN_EXTEND_32: return s390_widen_emit(buf, insn, 4, 1);
7937
7938 case S390_NEGATE: return s390_negate_emit(buf, insn);
7939 }
7940
7941 vpanic("s390_insn_unop_emit");
7942}
7943
7944
7945/* Only 4-byte and 8-byte operands are handled. 1-byte and 2-byte
7946 comparisons will have been converted to 4-byte comparisons in
7947 s390_isel_cc and should not occur here. */
7948static UChar *
7949s390_insn_test_emit(UChar *buf, const s390_insn *insn)
7950{
7951 s390_opnd_RMI opnd;
7952
7953 opnd = insn->variant.test.src;
7954
7955 switch (opnd.tag) {
7956 case S390_OPND_REG: {
7957 UInt reg = hregNumber(opnd.variant.reg);
7958
7959 switch (insn->size) {
7960 case 4:
7961 return s390_emit_LTR(buf, reg, reg);
7962
7963 case 8:
7964 return s390_emit_LTGR(buf, reg, reg);
7965
7966 default:
7967 goto fail;
7968 }
7969 }
7970
7971 case S390_OPND_AMODE: {
7972 const s390_amode *am = opnd.variant.am;
7973 UChar b = hregNumber(am->b);
7974 UChar x = hregNumber(am->x);
7975 Int d = am->d;
7976
7977 switch (insn->size) {
7978 case 4:
7979 return s390_emit_LTw(buf, R0, x, b, DISP20(d));
7980
7981 case 8:
7982 return s390_emit_LTGw(buf, R0, x, b, DISP20(d));
7983
7984 default:
7985 goto fail;
7986 }
7987 }
7988
7989 case S390_OPND_IMMEDIATE: {
7990 ULong value = opnd.variant.imm;
7991
7992 switch (insn->size) {
7993 case 4:
7994 buf = s390_emit_load_32imm(buf, R0, value);
7995 return s390_emit_LTR(buf, R0, R0);
7996
7997 case 8:
7998 buf = s390_emit_load_64imm(buf, R0, value);
7999 return s390_emit_LTGR(buf, R0, R0);
8000
8001 default:
8002 goto fail;
8003 }
8004 }
8005
8006 default:
8007 goto fail;
8008 }
8009
8010 fail:
8011 vpanic("s390_insn_test_emit");
8012}
8013
8014
8015static UChar *
8016s390_insn_cc2bool_emit(UChar *buf, const s390_insn *insn)
8017{
8018 UChar r1 = hregNumber(insn->variant.cc2bool.dst);
8019 s390_cc_t cond = insn->variant.cc2bool.cond;
8020
8021 /* Make the destination register be 1 or 0, depending on whether
8022 the relevant condition holds. A 64-bit value is computed. */
8023 if (cond == S390_CC_ALWAYS)
8024 return s390_emit_LGHI(buf, r1, 1); /* r1 = 1 */
8025
8026 buf = s390_emit_load_cc(buf, r1); /* r1 = cc */
8027 buf = s390_emit_LGHI(buf, R0, cond); /* r0 = mask */
8028 buf = s390_emit_SLLG(buf, r1, R0, r1, DISP20(0)); /* r1 = mask << cc */
8029 buf = s390_emit_SRLG(buf, r1, r1, 0, DISP20(3)); /* r1 = r1 >> 3 */
8030 buf = s390_emit_NILL(buf, r1, 1); /* r1 = r1 & 0x1 */
8031
8032 return buf;
8033}
8034
8035
8036/* Only 4-byte and 8-byte operands are handled. */
8037static UChar *
8038s390_insn_cas_emit(UChar *buf, const s390_insn *insn)
8039{
8040 UChar r1, r3, b, old;
8041 Int d;
8042 s390_amode *am;
8043
8044 r1 = hregNumber(insn->variant.cas.op1); /* expected value */
8045 r3 = hregNumber(insn->variant.cas.op3);
8046 old= hregNumber(insn->variant.cas.old_mem);
8047 am = insn->variant.cas.op2;
8048 b = hregNumber(am->b);
8049 d = am->d;
8050
florian406ac942014-11-22 20:10:21 +00008051 vassert(am->tag == S390_AMODE_B12 || am->tag == S390_AMODE_B20);
8052
sewardj2019a972011-03-07 16:04:07 +00008053 switch (insn->size) {
8054 case 4:
florian406ac942014-11-22 20:10:21 +00008055 /* r1 must not be overwritten. So copy it to R0 and let CS clobber it */
sewardj2019a972011-03-07 16:04:07 +00008056 buf = s390_emit_LR(buf, R0, r1);
8057 if (am->tag == S390_AMODE_B12)
8058 buf = s390_emit_CS(buf, R0, r3, b, d);
8059 else
8060 buf = s390_emit_CSY(buf, R0, r3, b, DISP20(d));
8061 /* Now copy R0 which has the old memory value to OLD */
8062 return s390_emit_LR(buf, old, R0);
8063
8064 case 8:
florian406ac942014-11-22 20:10:21 +00008065 /* r1 must not be overwritten. So copy it to R0 and let CS clobber it */
sewardj2019a972011-03-07 16:04:07 +00008066 buf = s390_emit_LGR(buf, R0, r1);
8067 buf = s390_emit_CSG(buf, R0, r3, b, DISP20(d));
8068 /* Now copy R0 which has the old memory value to OLD */
8069 return s390_emit_LGR(buf, old, R0);
8070
8071 default:
8072 goto fail;
8073 }
8074
8075 fail:
8076 vpanic("s390_insn_cas_emit");
8077}
8078
8079
florian448cbba2012-06-06 02:26:01 +00008080/* Only 4-byte and 8-byte operands are handled. */
8081static UChar *
8082s390_insn_cdas_emit(UChar *buf, const s390_insn *insn)
8083{
sewardja90622a2012-06-19 13:29:00 +00008084 UChar r1, r1p1, r3, /*r3p1,*/ b, old_high, old_low, scratch;
florian448cbba2012-06-06 02:26:01 +00008085 Int d;
8086 s390_amode *am;
florianc4aa7ed2012-12-22 15:01:04 +00008087 s390_cdas *cdas = insn->variant.cdas.details;
florian448cbba2012-06-06 02:26:01 +00008088
florianc4aa7ed2012-12-22 15:01:04 +00008089 r1 = hregNumber(cdas->op1_high); /* expected value */
8090 r1p1 = hregNumber(cdas->op1_low); /* expected value */
8091 r3 = hregNumber(cdas->op3_high);
8092 /* r3p1 = hregNumber(cdas->op3_low); */ /* unused */
8093 old_high = hregNumber(cdas->old_mem_high);
8094 old_low = hregNumber(cdas->old_mem_low);
8095 scratch = hregNumber(cdas->scratch);
8096 am = cdas->op2;
florian448cbba2012-06-06 02:26:01 +00008097 b = hregNumber(am->b);
8098 d = am->d;
8099
8100 vassert(scratch == 1);
florian406ac942014-11-22 20:10:21 +00008101 vassert(am->tag == S390_AMODE_B12 || am->tag == S390_AMODE_B20);
florian448cbba2012-06-06 02:26:01 +00008102
8103 switch (insn->size) {
8104 case 4:
8105 /* r1, r1+1 must not be overwritten. So copy them to R0,scratch
8106 and let CDS/CDSY clobber it */
8107 buf = s390_emit_LR(buf, R0, r1);
8108 buf = s390_emit_LR(buf, scratch, r1p1);
8109
8110 if (am->tag == S390_AMODE_B12)
8111 buf = s390_emit_CDS(buf, R0, r3, b, d);
8112 else
8113 buf = s390_emit_CDSY(buf, R0, r3, b, DISP20(d));
8114
8115 /* Now copy R0,scratch which has the old memory value to OLD */
8116 buf = s390_emit_LR(buf, old_high, R0);
8117 buf = s390_emit_LR(buf, old_low, scratch);
8118 return buf;
8119
8120 case 8:
8121 /* r1, r1+1 must not be overwritten. So copy them to R0,scratch
8122 and let CDSG clobber it */
8123 buf = s390_emit_LGR(buf, R0, r1);
8124 buf = s390_emit_LGR(buf, scratch, r1p1);
8125
8126 buf = s390_emit_CDSG(buf, R0, r3, b, DISP20(d));
8127
8128 /* Now copy R0,scratch which has the old memory value to OLD */
8129 buf = s390_emit_LGR(buf, old_high, R0);
8130 buf = s390_emit_LGR(buf, old_low, scratch);
8131 return buf;
8132
8133 default:
8134 goto fail;
8135 }
8136
8137 fail:
florianbb5aa782012-12-01 21:29:07 +00008138 vpanic("s390_insn_cdas_emit");
florian448cbba2012-06-06 02:26:01 +00008139}
8140
8141
sewardj2019a972011-03-07 16:04:07 +00008142/* Only 4-byte and 8-byte comparisons are handled. 1-byte and 2-byte
8143 comparisons will have been converted to 4-byte comparisons in
8144 s390_isel_cc and should not occur here. */
8145static UChar *
8146s390_insn_compare_emit(UChar *buf, const s390_insn *insn)
8147{
8148 s390_opnd_RMI op2;
8149 HReg op1;
8150 Bool signed_comparison;
8151
8152 op1 = insn->variant.compare.src1;
8153 op2 = insn->variant.compare.src2;
8154 signed_comparison = insn->variant.compare.signed_comparison;
8155
8156 switch (op2.tag) {
8157 case S390_OPND_REG: {
8158 UInt r1 = hregNumber(op1);
8159 UInt r2 = hregNumber(op2.variant.reg);
8160
8161 switch (insn->size) {
8162 case 4:
8163 if (signed_comparison)
8164 return s390_emit_CR(buf, r1, r2);
8165 else
8166 return s390_emit_CLR(buf, r1, r2);
8167
8168 case 8:
8169 if (signed_comparison)
8170 return s390_emit_CGR(buf, r1, r2);
8171 else
8172 return s390_emit_CLGR(buf, r1, r2);
8173
8174 default:
8175 goto fail;
8176 }
8177 }
8178
8179 case S390_OPND_AMODE: {
8180 UChar r1 = hregNumber(op1);
8181 const s390_amode *am = op2.variant.am;
8182 UChar b = hregNumber(am->b);
8183 UChar x = hregNumber(am->x);
8184 Int d = am->d;
8185
8186 switch (insn->size) {
8187 case 4:
8188 switch (am->tag) {
8189 case S390_AMODE_B12:
8190 case S390_AMODE_BX12:
8191 if (signed_comparison)
8192 return s390_emit_C(buf, r1, x, b, d);
8193 else
8194 return s390_emit_CL(buf, r1, x, b, d);
8195
8196 case S390_AMODE_B20:
8197 case S390_AMODE_BX20:
8198 if (signed_comparison)
8199 return s390_emit_CY(buf, r1, x, b, DISP20(d));
8200 else
8201 return s390_emit_CLY(buf, r1, x, b, DISP20(d));
8202 }
8203 goto fail;
8204
8205 case 8:
8206 if (signed_comparison)
8207 return s390_emit_CG(buf, r1, x, b, DISP20(d));
8208 else
8209 return s390_emit_CLG(buf, r1, x, b, DISP20(d));
8210
8211 default:
8212 goto fail;
8213 }
8214 }
8215
8216 case S390_OPND_IMMEDIATE: {
8217 UChar r1 = hregNumber(op1);
8218 ULong value = op2.variant.imm;
8219
8220 switch (insn->size) {
8221 case 4:
8222 if (signed_comparison)
8223 return s390_emit_CFIw(buf, r1, value);
8224 else
8225 return s390_emit_CLFIw(buf, r1, value);
8226
8227 case 8:
florian07d34552012-05-26 01:59:21 +00008228 if (s390_host_has_eimm) {
8229 if (signed_comparison) {
8230 if (ulong_fits_signed_32bit(value))
8231 return s390_emit_CGFI(buf, r1, value);
8232 } else {
8233 if (ulong_fits_unsigned_32bit(value))
8234 return s390_emit_CLGFI(buf, r1, value);
8235 }
8236 }
sewardj2019a972011-03-07 16:04:07 +00008237 buf = s390_emit_load_64imm(buf, R0, value);
8238 if (signed_comparison)
8239 return s390_emit_CGR(buf, r1, R0);
8240 else
8241 return s390_emit_CLGR(buf, r1, R0);
8242
8243 default:
8244 goto fail;
8245 }
8246 }
8247
8248 default:
8249 goto fail;
8250 }
8251
8252 fail:
8253 vpanic("s390_insn_compare_emit");
8254}
8255
8256
8257static UChar *
8258s390_insn_mul_emit(UChar *buf, const s390_insn *insn)
8259{
8260 s390_opnd_RMI op2;
8261 UChar r1;
8262 Bool signed_multiply;
8263
8264 /* The register number identifying the register pair */
8265 r1 = hregNumber(insn->variant.mul.dst_hi);
8266
8267 op2 = insn->variant.mul.op2;
florianc4aa7ed2012-12-22 15:01:04 +00008268 signed_multiply = insn->tag == S390_INSN_SMUL;
sewardj2019a972011-03-07 16:04:07 +00008269
8270 switch (op2.tag) {
8271 case S390_OPND_REG: {
8272 UInt r2 = hregNumber(op2.variant.reg);
8273
8274 switch (insn->size) {
8275 case 1:
8276 case 2:
8277 case 4:
8278 if (signed_multiply)
8279 return s390_emit_MR(buf, r1, r2);
8280 else
8281 return s390_emit_MLR(buf, r1, r2);
8282
8283 case 8:
8284 if (signed_multiply)
8285 vpanic("s390_insn_mul_emit");
8286 else
8287 return s390_emit_MLGR(buf, r1, r2);
8288
8289 default:
8290 goto fail;
8291 }
8292 }
8293
8294 case S390_OPND_AMODE: {
8295 const s390_amode *am = op2.variant.am;
8296 UChar b = hregNumber(am->b);
8297 UChar x = hregNumber(am->x);
8298 Int d = am->d;
8299
8300 switch (insn->size) {
8301 case 1:
8302 case 2:
8303 /* Load bytes into scratch register R0, then multiply */
8304 buf = s390_emit_load_mem(buf, insn->size, R0, am);
8305 if (signed_multiply)
8306 return s390_emit_MR(buf, r1, R0);
8307 else
8308 return s390_emit_MLR(buf, r1, R0);
8309
8310 case 4:
8311 switch (am->tag) {
8312 case S390_AMODE_B12:
8313 case S390_AMODE_BX12:
8314 if (signed_multiply)
8315 return s390_emit_M(buf, r1, x, b, d);
8316 else
8317 return s390_emit_ML(buf, r1, x, b, DISP20(d));
8318
8319 case S390_AMODE_B20:
8320 case S390_AMODE_BX20:
8321 if (signed_multiply)
8322 return s390_emit_MFYw(buf, r1, x, b, DISP20(d));
8323 else
sewardjb13a92a2011-04-13 14:44:29 +00008324 return s390_emit_ML(buf, r1, x, b, DISP20(d));
sewardj2019a972011-03-07 16:04:07 +00008325 }
8326 goto fail;
8327
8328 case 8:
8329 if (signed_multiply)
8330 vpanic("s390_insn_mul_emit");
8331 else
8332 return s390_emit_MLG(buf, r1, x, b, DISP20(d));
8333
8334 default:
8335 goto fail;
8336 }
8337 }
8338
8339 case S390_OPND_IMMEDIATE: {
8340 ULong value = op2.variant.imm;
8341
8342 switch (insn->size) {
8343 case 1:
8344 case 2:
8345 case 4:
8346 buf = s390_emit_load_32imm(buf, R0, value);
8347 if (signed_multiply)
8348 return s390_emit_MR(buf, r1, R0);
8349 else
8350 return s390_emit_MLR(buf, r1, R0);
8351
8352 case 8:
8353 buf = s390_emit_load_64imm(buf, R0, value);
8354 if (signed_multiply)
8355 vpanic("s390_insn_mul_emit");
8356 else
8357 return s390_emit_MLGR(buf, r1, R0);
8358
8359 default:
8360 goto fail;
8361 }
8362 }
8363
8364 default:
8365 goto fail;
8366 }
8367
8368 fail:
8369 vpanic("s390_insn_mul_emit");
8370}
8371
8372
8373static UChar *
8374s390_insn_div_emit(UChar *buf, const s390_insn *insn)
8375{
8376 s390_opnd_RMI op2;
8377 UChar r1;
8378 Bool signed_divide;
8379
8380 r1 = hregNumber(insn->variant.div.op1_hi);
8381 op2 = insn->variant.div.op2;
florianc4aa7ed2012-12-22 15:01:04 +00008382 signed_divide = insn->tag == S390_INSN_SDIV;
sewardj2019a972011-03-07 16:04:07 +00008383
8384 switch (op2.tag) {
8385 case S390_OPND_REG: {
8386 UInt r2 = hregNumber(op2.variant.reg);
8387
8388 switch (insn->size) {
8389 case 4:
8390 if (signed_divide)
8391 return s390_emit_DR(buf, r1, r2);
8392 else
8393 return s390_emit_DLR(buf, r1, r2);
8394
8395 case 8:
8396 if (signed_divide)
8397 vpanic("s390_insn_div_emit");
8398 else
8399 return s390_emit_DLGR(buf, r1, r2);
8400
8401 default:
8402 goto fail;
8403 }
8404 }
8405
8406 case S390_OPND_AMODE: {
8407 const s390_amode *am = op2.variant.am;
8408 UChar b = hregNumber(am->b);
8409 UChar x = hregNumber(am->x);
8410 Int d = am->d;
8411
8412 switch (insn->size) {
8413 case 4:
8414 switch (am->tag) {
8415 case S390_AMODE_B12:
8416 case S390_AMODE_BX12:
8417 if (signed_divide)
8418 return s390_emit_D(buf, r1, x, b, d);
8419 else
8420 return s390_emit_DL(buf, r1, x, b, DISP20(d));
8421
8422 case S390_AMODE_B20:
8423 case S390_AMODE_BX20:
sewardjb13a92a2011-04-13 14:44:29 +00008424 if (signed_divide) {
8425 buf = s390_emit_LY(buf, R0, x, b, DISP20(d));
sewardj2019a972011-03-07 16:04:07 +00008426 return s390_emit_DR(buf, r1, R0);
sewardjb13a92a2011-04-13 14:44:29 +00008427 } else
8428 return s390_emit_DL(buf, r1, x, b, DISP20(d));
sewardj2019a972011-03-07 16:04:07 +00008429 }
8430 goto fail;
8431
8432 case 8:
8433 if (signed_divide)
8434 vpanic("s390_insn_div_emit");
8435 else
8436 return s390_emit_DLG(buf, r1, x, b, DISP20(d));
8437
8438 default:
8439 goto fail;
8440 }
8441 }
8442
8443 case S390_OPND_IMMEDIATE: {
8444 ULong value = op2.variant.imm;
8445
8446 switch (insn->size) {
8447 case 4:
8448 buf = s390_emit_load_32imm(buf, R0, value);
8449 if (signed_divide)
8450 return s390_emit_DR(buf, r1, R0);
8451 else
8452 return s390_emit_DLR(buf, r1, R0);
8453
8454 case 8:
8455 buf = s390_emit_load_64imm(buf, R0, value);
8456 if (signed_divide)
8457 vpanic("s390_insn_div_emit");
8458 else
8459 return s390_emit_DLGR(buf, r1, R0);
8460
8461 default:
8462 goto fail;
8463 }
8464 }
8465
8466 default:
8467 goto fail;
8468 }
8469
8470 fail:
8471 vpanic("s390_insn_div_emit");
8472}
8473
8474
8475static UChar *
8476s390_insn_divs_emit(UChar *buf, const s390_insn *insn)
8477{
8478 s390_opnd_RMI op2;
8479 UChar r1;
8480
8481 r1 = hregNumber(insn->variant.divs.rem);
8482 op2 = insn->variant.divs.op2;
8483
8484 switch (op2.tag) {
8485 case S390_OPND_REG: {
8486 UInt r2 = hregNumber(op2.variant.reg);
8487
8488 return s390_emit_DSGR(buf, r1, r2);
8489 }
8490
8491 case S390_OPND_AMODE: {
8492 const s390_amode *am = op2.variant.am;
8493 UChar b = hregNumber(am->b);
8494 UChar x = hregNumber(am->x);
8495 Int d = am->d;
8496
8497 return s390_emit_DSG(buf, r1, x, b, DISP20(d));
8498 }
8499
8500 case S390_OPND_IMMEDIATE: {
8501 ULong value = op2.variant.imm;
8502
8503 buf = s390_emit_load_64imm(buf, R0, value);
8504 return s390_emit_DSGR(buf, r1, R0);
8505 }
8506
8507 default:
8508 goto fail;
8509 }
8510
8511 fail:
8512 vpanic("s390_insn_divs_emit");
8513}
8514
8515
8516static UChar *
sewardj611b06e2011-03-24 08:57:29 +00008517s390_insn_clz_emit(UChar *buf, const s390_insn *insn)
sewardj2019a972011-03-07 16:04:07 +00008518{
8519 s390_opnd_RMI src;
sewardj611b06e2011-03-24 08:57:29 +00008520 UChar r1, r1p1, r2, *p;
sewardj2019a972011-03-07 16:04:07 +00008521
sewardj611b06e2011-03-24 08:57:29 +00008522 r1 = hregNumber(insn->variant.clz.num_bits);
8523 r1p1 = hregNumber(insn->variant.clz.clobber);
sewardj2019a972011-03-07 16:04:07 +00008524
8525 vassert((r1 & 0x1) == 0);
8526 vassert(r1p1 == r1 + 1);
8527
sewardj611b06e2011-03-24 08:57:29 +00008528 p = buf;
8529 src = insn->variant.clz.src;
sewardj2019a972011-03-07 16:04:07 +00008530
sewardj611b06e2011-03-24 08:57:29 +00008531 /* Get operand and move it to r2 */
sewardj2019a972011-03-07 16:04:07 +00008532 switch (src.tag) {
sewardj611b06e2011-03-24 08:57:29 +00008533 case S390_OPND_REG:
8534 r2 = hregNumber(src.variant.reg);
8535 break;
sewardj2019a972011-03-07 16:04:07 +00008536
8537 case S390_OPND_AMODE: {
8538 const s390_amode *am = src.variant.am;
8539 UChar b = hregNumber(am->b);
8540 UChar x = hregNumber(am->x);
8541 Int d = am->d;
8542
sewardj611b06e2011-03-24 08:57:29 +00008543 p = s390_emit_LG(p, R0, x, b, DISP20(d));
8544 r2 = R0;
8545 break;
sewardj2019a972011-03-07 16:04:07 +00008546 }
8547
8548 case S390_OPND_IMMEDIATE: {
8549 ULong value = src.variant.imm;
8550
sewardj611b06e2011-03-24 08:57:29 +00008551 p = s390_emit_load_64imm(p, R0, value);
8552 r2 = R0;
8553 break;
sewardj2019a972011-03-07 16:04:07 +00008554 }
8555
8556 default:
8557 goto fail;
8558 }
8559
sewardj611b06e2011-03-24 08:57:29 +00008560 /* Use FLOGR if you can */
8561 if (s390_host_has_eimm) {
8562 return s390_emit_FLOGR(p, r1, r2);
8563 }
8564
8565 /*
8566 r0 = r2;
8567 r1 = 64;
8568 while (r0 != 0) {
8569 r1 -= 1;
8570 r0 >>= 1;
8571 }
8572 */
8573 p = s390_emit_LTGR(p, R0, r2);
8574 p = s390_emit_LLILL(p, r1, 64);
8575
8576 p = s390_emit_BRC(p, S390_CC_E, (4 + 4 + 6 + 4 + 4)/ 2); /* 4 bytes */
8577 p = s390_emit_AGHI(p, r1, (UShort)-1); /* r1 -= 1; 4 bytes */
8578 p = s390_emit_SRLG(p, R0, R0, R0, DISP20(1)); /* r0 >>= 1; 6 bytes */
8579 p = s390_emit_LTGR(p, R0, R0); /* set cc 4 bytes */
8580 p = s390_emit_BRC(p, S390_CC_NE, /* 4 bytes */
8581 (UShort)(-(4 + 6 + 4) / 2));
8582 return p;
8583
sewardj2019a972011-03-07 16:04:07 +00008584 fail:
sewardj611b06e2011-03-24 08:57:29 +00008585 vpanic("s390_insn_clz_emit");
sewardj2019a972011-03-07 16:04:07 +00008586}
8587
8588
sewardjcfe046e2013-01-17 14:23:53 +00008589/* Returns a value == BUF to denote failure, != BUF to denote success. */
sewardj2019a972011-03-07 16:04:07 +00008590static UChar *
sewardj2019a972011-03-07 16:04:07 +00008591s390_insn_helper_call_emit(UChar *buf, const s390_insn *insn)
8592{
8593 s390_cc_t cond;
8594 ULong target;
8595 UChar *ptmp = buf;
sewardj74142b82013-08-08 10:28:59 +00008596 s390_helper_call *helper_call = insn->variant.helper_call.details;
sewardj2019a972011-03-07 16:04:07 +00008597
sewardj74142b82013-08-08 10:28:59 +00008598 cond = helper_call->cond;
8599 target = helper_call->target;
sewardj2019a972011-03-07 16:04:07 +00008600
sewardjcfe046e2013-01-17 14:23:53 +00008601 if (cond != S390_CC_ALWAYS
sewardj74142b82013-08-08 10:28:59 +00008602 && helper_call->rloc.pri != RLPri_None) {
sewardjcfe046e2013-01-17 14:23:53 +00008603 /* The call might not happen (it isn't unconditional) and it
8604 returns a result. In this case we will need to generate a
8605 control flow diamond to put 0x555..555 in the return
8606 register(s) in the case where the call doesn't happen. If
8607 this ever becomes necessary, maybe copy code from the ARM
8608 equivalent. Until that day, just give up. */
floriandff20412014-09-25 20:33:50 +00008609 return buf; /* To denote failure. */
sewardjcfe046e2013-01-17 14:23:53 +00008610 }
8611
sewardj2019a972011-03-07 16:04:07 +00008612 if (cond != S390_CC_ALWAYS) {
8613 /* So we have something like this
8614 if (cond) call X;
8615 Y: ...
8616 We convert this into
8617 if (! cond) goto Y; // BRC opcode; 4 bytes
8618 call X;
8619 Y:
8620 */
8621 /* 4 bytes (a BRC insn) to be filled in here */
8622 buf += 4;
8623 }
8624
8625 /* Load the target address into a register, that
8626 (a) is not used for passing parameters to the helper and
8627 (b) can be clobbered by the callee
florianc9e90e52012-05-27 17:20:47 +00008628 (c) is not special to the BASR insn
8629 r1 is the only choice.
sewardj2019a972011-03-07 16:04:07 +00008630 Also, need to arrange for the return address be put into the
8631 link-register */
8632 buf = s390_emit_load_64imm(buf, 1, target);
8633
8634 /* Stash away the client's FPC register because the helper might change it. */
8635 buf = s390_emit_STFPC(buf, S390_REGNO_STACK_POINTER, S390_OFFSET_SAVED_FPC_C);
8636
sewardj2019a972011-03-07 16:04:07 +00008637 buf = s390_emit_BASR(buf, S390_REGNO_LINK_REGISTER, 1); // call helper
florian01ed6e72012-05-27 16:52:43 +00008638
sewardj2019a972011-03-07 16:04:07 +00008639 buf = s390_emit_LFPC(buf, S390_REGNO_STACK_POINTER, // restore FPC
8640 S390_OFFSET_SAVED_FPC_C);
8641
8642 if (cond != S390_CC_ALWAYS) {
8643 Int delta = buf - ptmp;
8644
8645 delta >>= 1; /* immediate constant is #half-words */
8646 vassert(delta > 0 && delta < (1 << 16));
8647 s390_emit_BRC(ptmp, s390_cc_invert(cond), delta);
8648 }
8649
8650 return buf;
8651}
8652
8653
8654static UChar *
8655s390_insn_cond_move_emit(UChar *buf, const s390_insn *insn)
8656{
8657 HReg dst;
8658 s390_opnd_RMI src;
8659 s390_cc_t cond;
8660 UChar *p, *ptmp = 0; /* avoid compiler warnings */
8661
8662 cond = insn->variant.cond_move.cond;
8663 dst = insn->variant.cond_move.dst;
8664 src = insn->variant.cond_move.src;
8665
florian3a3d7f12012-12-03 13:32:05 +00008666 if (cond == S390_CC_NEVER) return buf;
8667
sewardj2019a972011-03-07 16:04:07 +00008668 p = buf;
8669
florianaec8e052012-12-09 17:26:32 +00008670 if (s390_host_has_lsc) {
florian3a3d7f12012-12-03 13:32:05 +00008671 /* LOCx is not the preferred way to implement an unconditional load. */
8672 if (cond != S390_CC_ALWAYS) goto use_branch_insn;
8673
8674 switch (src.tag) {
8675 case S390_OPND_REG:
8676 return s390_emit_LOCGR(p, cond, hregNumber(dst),
8677 hregNumber(src.variant.reg));
8678
8679 case S390_OPND_AMODE: {
8680 const s390_amode *am = src.variant.am;
8681
8682 /* We cannot use LOCx for loads less than 4 bytes. In that case
8683 load into R0 and then use LOCGR. Do the same if the amode uses
8684 an index register. */
8685 if (insn->size < 4 ||
8686 am->tag == S390_AMODE_BX12 || am->tag == S390_AMODE_BX20) {
8687 p = s390_emit_load_mem(p, insn->size, R0, am);
8688 p = s390_emit_LOCGR(p, cond, hregNumber(dst), R0);
8689 return p;
8690 }
8691
8692 vassert(am->tag == S390_AMODE_B12 || am->tag == S390_AMODE_B20);
8693 vassert(insn->size == 4 || insn->size == 8);
8694
8695 UInt b = hregNumber(am->b);
8696 UInt d = am->d;
8697
8698 if (insn->size == 4) {
8699 return s390_emit_LOC(p, hregNumber(dst), cond, b, DISP20(d));
8700 }
8701 return s390_emit_LOCG(p, hregNumber(dst), cond, b, DISP20(d));
8702 }
8703
8704 case S390_OPND_IMMEDIATE: {
8705 ULong value = src.variant.imm;
8706
8707 /* Load value into R0, then use LOCGR */
8708 if (insn->size <= 4) {
8709 p = s390_emit_load_32imm(p, R0, value);
8710 return s390_emit_LOCGR(p, cond, hregNumber(dst), R0);
8711 }
8712
8713 vassert(insn->size == 8);
8714 p = s390_emit_load_64imm(p, R0, value);
8715 return s390_emit_LOCGR(p, cond, hregNumber(dst), R0);
8716 }
8717 }
8718 }
8719
8720use_branch_insn:
sewardj2019a972011-03-07 16:04:07 +00008721 /* Branch (if cond fails) over move instrs */
8722 if (cond != S390_CC_ALWAYS) {
8723 /* Don't know how many bytes to jump over yet.
8724 Make space for a BRC instruction (4 bytes) and fill in later. */
8725 ptmp = p; /* to be filled in here */
8726 p += 4;
8727 }
8728
8729 // cond true: move src => dst
8730
8731 switch (src.tag) {
8732 case S390_OPND_REG:
8733 p = s390_emit_LGR(p, hregNumber(dst), hregNumber(src.variant.reg));
8734 break;
8735
8736 case S390_OPND_AMODE:
8737 p = s390_emit_load_mem(p, insn->size, hregNumber(dst), src.variant.am);
8738 break;
8739
8740 case S390_OPND_IMMEDIATE: {
8741 ULong value = src.variant.imm;
8742 UInt r = hregNumber(dst);
8743
8744 switch (insn->size) {
8745 case 1:
8746 case 2:
8747 /* Load the immediate values as a 4 byte value. That does not hurt as
8748 those extra bytes will not be looked at. Fall through .... */
8749 case 4:
8750 p = s390_emit_load_32imm(p, r, value);
8751 break;
8752
8753 case 8:
8754 p = s390_emit_load_64imm(p, r, value);
8755 break;
8756 }
8757 break;
8758 }
8759
8760 default:
8761 goto fail;
8762 }
8763
8764 if (cond != S390_CC_ALWAYS) {
8765 Int delta = p - ptmp;
8766
8767 delta >>= 1; /* immediate constant is #half-words */
8768 vassert(delta > 0 && delta < (1 << 16));
8769 s390_emit_BRC(ptmp, s390_cc_invert(cond), delta);
8770 }
8771
8772 return p;
8773
8774 fail:
8775 vpanic("s390_insn_cond_move_emit");
8776}
8777
8778
sewardj2019a972011-03-07 16:04:07 +00008779static UChar *
8780s390_insn_bfp_triop_emit(UChar *buf, const s390_insn *insn)
8781{
8782 UInt r1 = hregNumber(insn->variant.bfp_triop.dst);
8783 UInt r2 = hregNumber(insn->variant.bfp_triop.op2);
8784 UInt r3 = hregNumber(insn->variant.bfp_triop.op3);
sewardj2019a972011-03-07 16:04:07 +00008785
8786 switch (insn->size) {
8787 case 4:
8788 switch (insn->variant.bfp_triop.tag) {
florian2c74d242012-09-12 19:38:42 +00008789 case S390_BFP_MADD: return s390_emit_MAEBR(buf, r1, r3, r2);
8790 case S390_BFP_MSUB: return s390_emit_MSEBR(buf, r1, r3, r2);
sewardj2019a972011-03-07 16:04:07 +00008791 default: goto fail;
8792 }
8793 break;
8794
8795 case 8:
8796 switch (insn->variant.bfp_triop.tag) {
florian2c74d242012-09-12 19:38:42 +00008797 case S390_BFP_MADD: return s390_emit_MADBR(buf, r1, r3, r2);
8798 case S390_BFP_MSUB: return s390_emit_MSDBR(buf, r1, r3, r2);
sewardj2019a972011-03-07 16:04:07 +00008799 default: goto fail;
8800 }
8801 break;
8802
8803 default: goto fail;
8804 }
8805
sewardj2019a972011-03-07 16:04:07 +00008806 fail:
8807 vpanic("s390_insn_bfp_triop_emit");
8808}
8809
8810
8811static UChar *
8812s390_insn_bfp_binop_emit(UChar *buf, const s390_insn *insn)
8813{
floriancc491a62012-09-10 23:44:37 +00008814 UInt r1 = hregNumber(insn->variant.bfp_binop.dst_hi);
8815 UInt r2 = hregNumber(insn->variant.bfp_binop.op2_hi);
sewardj2019a972011-03-07 16:04:07 +00008816
8817 switch (insn->size) {
8818 case 4:
8819 switch (insn->variant.bfp_binop.tag) {
florian2c74d242012-09-12 19:38:42 +00008820 case S390_BFP_ADD: return s390_emit_AEBR(buf, r1, r2);
8821 case S390_BFP_SUB: return s390_emit_SEBR(buf, r1, r2);
8822 case S390_BFP_MUL: return s390_emit_MEEBR(buf, r1, r2);
8823 case S390_BFP_DIV: return s390_emit_DEBR(buf, r1, r2);
sewardj2019a972011-03-07 16:04:07 +00008824 default: goto fail;
8825 }
8826 break;
8827
8828 case 8:
8829 switch (insn->variant.bfp_binop.tag) {
florian2c74d242012-09-12 19:38:42 +00008830 case S390_BFP_ADD: return s390_emit_ADBR(buf, r1, r2);
8831 case S390_BFP_SUB: return s390_emit_SDBR(buf, r1, r2);
8832 case S390_BFP_MUL: return s390_emit_MDBR(buf, r1, r2);
8833 case S390_BFP_DIV: return s390_emit_DDBR(buf, r1, r2);
sewardj2019a972011-03-07 16:04:07 +00008834 default: goto fail;
8835 }
8836 break;
8837
floriancc491a62012-09-10 23:44:37 +00008838 case 16:
8839 switch (insn->variant.bfp_binop.tag) {
florian2c74d242012-09-12 19:38:42 +00008840 case S390_BFP_ADD: return s390_emit_AXBR(buf, r1, r2);
8841 case S390_BFP_SUB: return s390_emit_SXBR(buf, r1, r2);
8842 case S390_BFP_MUL: return s390_emit_MXBR(buf, r1, r2);
8843 case S390_BFP_DIV: return s390_emit_DXBR(buf, r1, r2);
floriancc491a62012-09-10 23:44:37 +00008844 default: goto fail;
8845 }
8846 break;
8847
sewardj2019a972011-03-07 16:04:07 +00008848 default: goto fail;
8849 }
8850
sewardj2019a972011-03-07 16:04:07 +00008851 fail:
8852 vpanic("s390_insn_bfp_binop_emit");
8853}
8854
8855
8856static UChar *
8857s390_insn_bfp_unop_emit(UChar *buf, const s390_insn *insn)
8858{
floriancc491a62012-09-10 23:44:37 +00008859 UInt r1 = hregNumber(insn->variant.bfp_unop.dst_hi);
8860 UInt r2 = hregNumber(insn->variant.bfp_unop.op_hi);
sewardj2019a972011-03-07 16:04:07 +00008861
8862 switch (insn->variant.bfp_unop.tag) {
8863 case S390_BFP_ABS:
8864 switch (insn->size) {
florian2c74d242012-09-12 19:38:42 +00008865 case 4: return s390_emit_LPEBR(buf, r1, r2);
8866 case 8: return s390_emit_LPDBR(buf, r1, r2);
8867 case 16: return s390_emit_LPXBR(buf, r1, r2);
sewardj2019a972011-03-07 16:04:07 +00008868 default: goto fail;
8869 }
8870 break;
8871
8872 case S390_BFP_NABS:
8873 switch (insn->size) {
florian2c74d242012-09-12 19:38:42 +00008874 case 4: return s390_emit_LNEBR(buf, r1, r2);
8875 case 8: return s390_emit_LNDBR(buf, r1, r2);
8876 case 16: return s390_emit_LNXBR(buf, r1, r2);
sewardj2019a972011-03-07 16:04:07 +00008877 default: goto fail;
8878 }
8879 break;
8880
8881 case S390_BFP_NEG:
8882 switch (insn->size) {
florian2c74d242012-09-12 19:38:42 +00008883 case 4: return s390_emit_LCEBR(buf, r1, r2);
8884 case 8: return s390_emit_LCDBR(buf, r1, r2);
8885 case 16: return s390_emit_LCXBR(buf, r1, r2);
sewardj2019a972011-03-07 16:04:07 +00008886 default: goto fail;
8887 }
8888 break;
8889
8890 case S390_BFP_SQRT:
8891 switch (insn->size) {
florian2c74d242012-09-12 19:38:42 +00008892 case 4: return s390_emit_SQEBR(buf, r1, r2);
8893 case 8: return s390_emit_SQDBR(buf, r1, r2);
8894 case 16: return s390_emit_SQXBR(buf, r1, r2);
sewardj2019a972011-03-07 16:04:07 +00008895 default: goto fail;
8896 }
8897 break;
8898
florian9fcff4c2012-09-10 03:09:04 +00008899 default: goto fail;
8900 }
8901
florian9fcff4c2012-09-10 03:09:04 +00008902 fail:
8903 vpanic("s390_insn_bfp_unop_emit");
8904}
8905
8906
8907static UChar *
8908s390_insn_bfp_convert_emit(UChar *buf, const s390_insn *insn)
8909{
floriancc491a62012-09-10 23:44:37 +00008910 UInt r1 = hregNumber(insn->variant.bfp_convert.dst_hi);
8911 UInt r2 = hregNumber(insn->variant.bfp_convert.op_hi);
florian125e20d2012-10-07 15:42:37 +00008912 s390_bfp_round_t m3 = insn->variant.bfp_convert.rounding_mode;
florian2c74d242012-09-12 19:38:42 +00008913 /* The IEEE-inexact-exception control is not modelled. So the
8914 m4 field is 0 (which is what GCC does, too) */
8915 const UInt m4 = 0;
florian9fcff4c2012-09-10 03:09:04 +00008916
florian9fcff4c2012-09-10 03:09:04 +00008917 switch (insn->variant.bfp_convert.tag) {
floriancc491a62012-09-10 23:44:37 +00008918 /* Convert to fixed */
florian9fcff4c2012-09-10 03:09:04 +00008919 case S390_BFP_F32_TO_I32: return s390_emit_CFEBR(buf, m3, r1, r2);
8920 case S390_BFP_F64_TO_I32: return s390_emit_CFDBR(buf, m3, r1, r2);
floriancc491a62012-09-10 23:44:37 +00008921 case S390_BFP_F128_TO_I32: return s390_emit_CFXBR(buf, m3, r1, r2);
florian9fcff4c2012-09-10 03:09:04 +00008922 case S390_BFP_F32_TO_I64: return s390_emit_CGEBR(buf, m3, r1, r2);
8923 case S390_BFP_F64_TO_I64: return s390_emit_CGDBR(buf, m3, r1, r2);
floriancc491a62012-09-10 23:44:37 +00008924 case S390_BFP_F128_TO_I64: return s390_emit_CGXBR(buf, m3, r1, r2);
florian9fcff4c2012-09-10 03:09:04 +00008925
floriancc491a62012-09-10 23:44:37 +00008926 /* Convert to logical */
florian2c74d242012-09-12 19:38:42 +00008927 case S390_BFP_F32_TO_U32: return s390_emit_CLFEBR(buf, m3, m4, r1, r2);
8928 case S390_BFP_F64_TO_U32: return s390_emit_CLFDBR(buf, m3, m4, r1, r2);
8929 case S390_BFP_F128_TO_U32: return s390_emit_CLFXBR(buf, m3, m4, r1, r2);
8930 case S390_BFP_F32_TO_U64: return s390_emit_CLGEBR(buf, m3, m4, r1, r2);
8931 case S390_BFP_F64_TO_U64: return s390_emit_CLGDBR(buf, m3, m4, r1, r2);
8932 case S390_BFP_F128_TO_U64: return s390_emit_CLGXBR(buf, m3, m4, r1, r2);
florian9fcff4c2012-09-10 03:09:04 +00008933
florian2c74d242012-09-12 19:38:42 +00008934 /* Convert from fixed */
8935 case S390_BFP_I32_TO_F32: return s390_emit_CEFBRA(buf, m3, m4, r1, r2);
8936 case S390_BFP_I32_TO_F64: return s390_emit_CDFBRA(buf, 0, m4, r1, r2);
8937 case S390_BFP_I32_TO_F128: return s390_emit_CXFBRA(buf, 0, m4, r1, r2);
8938 case S390_BFP_I64_TO_F32: return s390_emit_CEGBRA(buf, m3, m4, r1, r2);
8939 case S390_BFP_I64_TO_F64: return s390_emit_CDGBRA(buf, m3, m4, r1, r2);
8940 case S390_BFP_I64_TO_F128: return s390_emit_CXGBRA(buf, 0, m4, r1, r2);
8941
8942 /* Convert from logical */
8943 case S390_BFP_U32_TO_F32: return s390_emit_CELFBR(buf, m3, m4, r1, r2);
8944 case S390_BFP_U32_TO_F64: return s390_emit_CDLFBR(buf, m3, m4, r1, r2);
8945 case S390_BFP_U32_TO_F128: return s390_emit_CXLFBR(buf, m3, m4, r1, r2);
8946 case S390_BFP_U64_TO_F32: return s390_emit_CELGBR(buf, m3, m4, r1, r2);
8947 case S390_BFP_U64_TO_F64: return s390_emit_CDLGBR(buf, m3, m4, r1, r2);
8948 case S390_BFP_U64_TO_F128: return s390_emit_CXLGBR(buf, m3, m4, r1, r2);
8949
8950 /* Load lengthened */
8951 case S390_BFP_F32_TO_F64: return s390_emit_LDEBR(buf, r1, r2);
floriancc491a62012-09-10 23:44:37 +00008952 case S390_BFP_F32_TO_F128: return s390_emit_LXEBR(buf, r1, r2);
8953 case S390_BFP_F64_TO_F128: return s390_emit_LXDBR(buf, r1, r2);
florian9fcff4c2012-09-10 03:09:04 +00008954
florian2c74d242012-09-12 19:38:42 +00008955 /* Load rounded */
8956 case S390_BFP_F64_TO_F32: return s390_emit_LEDBRA(buf, m3, m4, r1, r2);
8957 case S390_BFP_F128_TO_F32: return s390_emit_LEXBRA(buf, m3, m4, r1, r2);
8958 case S390_BFP_F128_TO_F64: return s390_emit_LDXBRA(buf, m3, m4, r1, r2);
floriancc491a62012-09-10 23:44:37 +00008959
sewardj2019a972011-03-07 16:04:07 +00008960 default: goto fail;
8961 }
8962
sewardj2019a972011-03-07 16:04:07 +00008963 fail:
florian9fcff4c2012-09-10 03:09:04 +00008964 vpanic("s390_insn_bfp_convert_emit");
sewardj2019a972011-03-07 16:04:07 +00008965}
8966
8967
8968static UChar *
8969s390_insn_bfp_compare_emit(UChar *buf, const s390_insn *insn)
8970{
8971 UInt dst = hregNumber(insn->variant.bfp_compare.dst);
floriancc491a62012-09-10 23:44:37 +00008972 UInt r1 = hregNumber(insn->variant.bfp_compare.op1_hi);
8973 UInt r2 = hregNumber(insn->variant.bfp_compare.op2_hi);
sewardj2019a972011-03-07 16:04:07 +00008974
8975 switch (insn->size) {
floriancc491a62012-09-10 23:44:37 +00008976 case 4: buf = s390_emit_CEBR(buf, r1, r2); break;
8977 case 8: buf = s390_emit_CDBR(buf, r1, r2); break;
8978 case 16: buf = s390_emit_CXBR(buf, r1, r2); break;
sewardj2019a972011-03-07 16:04:07 +00008979 default: goto fail;
8980 }
8981
8982 return s390_emit_load_cc(buf, dst); /* Load condition code into DST */
8983
8984 fail:
8985 vpanic("s390_insn_bfp_compare_emit");
8986}
8987
8988
8989static UChar *
florian12390202012-11-10 22:34:14 +00008990s390_insn_dfp_binop_emit(UChar *buf, const s390_insn *insn)
8991{
florianc4aa7ed2012-12-22 15:01:04 +00008992 s390_dfp_binop *dfp_binop = insn->variant.dfp_binop.details;
8993
8994 UInt r1 = hregNumber(dfp_binop->dst_hi);
8995 UInt r2 = hregNumber(dfp_binop->op2_hi);
8996 UInt r3 = hregNumber(dfp_binop->op3_hi);
florian89bb1a92013-01-10 15:41:46 +00008997 s390_dfp_round_t m4 = dfp_binop->rounding_mode;
florian12390202012-11-10 22:34:14 +00008998
8999 switch (insn->size) {
9000 case 8:
florianc4aa7ed2012-12-22 15:01:04 +00009001 switch (dfp_binop->tag) {
florian362e2712013-01-22 14:02:05 +00009002 case S390_DFP_ADD: return s390_emit_ADTRA(buf, r3, m4, r1, r2);
9003 case S390_DFP_SUB: return s390_emit_SDTRA(buf, r3, m4, r1, r2);
9004 case S390_DFP_MUL: return s390_emit_MDTRA(buf, r3, m4, r1, r2);
9005 case S390_DFP_DIV: return s390_emit_DDTRA(buf, r3, m4, r1, r2);
florian5c539732013-02-14 14:27:12 +00009006 case S390_DFP_QUANTIZE: return s390_emit_QADTR(buf, r3, m4, r1, r2);
florian12390202012-11-10 22:34:14 +00009007 default: goto fail;
9008 }
9009 break;
floriane38f6412012-12-21 17:32:12 +00009010
9011 case 16:
florianc4aa7ed2012-12-22 15:01:04 +00009012 switch (dfp_binop->tag) {
floriane38f6412012-12-21 17:32:12 +00009013 case S390_DFP_ADD: return s390_emit_AXTRA(buf, r3, m4, r1, r2);
9014 case S390_DFP_SUB: return s390_emit_SXTRA(buf, r3, m4, r1, r2);
9015 case S390_DFP_MUL: return s390_emit_MXTRA(buf, r3, m4, r1, r2);
9016 case S390_DFP_DIV: return s390_emit_DXTRA(buf, r3, m4, r1, r2);
florian5c539732013-02-14 14:27:12 +00009017 case S390_DFP_QUANTIZE: return s390_emit_QAXTR(buf, r3, m4, r1, r2);
floriane38f6412012-12-21 17:32:12 +00009018 default: goto fail;
9019 }
9020 break;
9021
florian12390202012-11-10 22:34:14 +00009022 default: goto fail;
9023 }
9024
9025 fail:
9026 vpanic("s390_insn_dfp_binop_emit");
9027}
9028
9029
9030static UChar *
florian5c539732013-02-14 14:27:12 +00009031s390_insn_dfp_reround_emit(UChar *buf, const s390_insn *insn)
9032{
9033 UInt r1 = hregNumber(insn->variant.dfp_reround.dst_hi);
9034 UInt r2 = hregNumber(insn->variant.dfp_reround.op2);
9035 UInt r3 = hregNumber(insn->variant.dfp_reround.op3_hi);
9036 s390_dfp_round_t m4 = insn->variant.dfp_reround.rounding_mode;
9037
9038 switch (insn->size) {
9039 case 8:
9040 return s390_emit_RRDTR(buf, r3, m4, r1, r2);
9041
9042 case 16:
9043 return s390_emit_RRXTR(buf, r3, m4, r1, r2);
9044
9045 default: goto fail;
9046 }
9047 fail:
9048 vpanic("s390_insn_dfp_reround_emit");
9049}
9050
9051
9052static UChar *
floriance9e3db2012-12-27 20:14:03 +00009053s390_insn_dfp_unop_emit(UChar *buf, const s390_insn *insn)
9054{
9055 UInt r1 = hregNumber(insn->variant.dfp_unop.dst_hi);
9056 UInt r2 = hregNumber(insn->variant.dfp_unop.op_hi);
9057
9058 switch (insn->variant.dfp_unop.tag) {
florian5c539732013-02-14 14:27:12 +00009059 case S390_DFP_EXTRACT_EXP_D64: return s390_emit_EEDTR(buf, r1, r2); break;
9060 case S390_DFP_EXTRACT_EXP_D128: return s390_emit_EEXTR(buf, r1, r2); break;
floriance9e3db2012-12-27 20:14:03 +00009061 case S390_DFP_EXTRACT_SIG_D64: return s390_emit_ESDTR(buf, r1, r2); break;
9062 case S390_DFP_EXTRACT_SIG_D128: return s390_emit_ESXTR(buf, r1, r2); break;
9063 default: goto fail;
9064 }
9065 fail:
9066 vpanic("s390_insn_dfp_unop_emit");
9067}
9068
9069
9070static UChar *
florian1b901d42013-01-01 22:19:24 +00009071s390_insn_dfp_intop_emit(UChar *buf, const s390_insn *insn)
9072{
9073 UInt r1 = hregNumber(insn->variant.dfp_intop.dst_hi);
9074 UInt r2 = hregNumber(insn->variant.dfp_intop.op2);
9075 UInt r3 = hregNumber(insn->variant.dfp_intop.op3_hi);
9076
9077 switch (insn->size) {
9078 case 8:
9079 switch (insn->variant.dfp_intop.tag) {
9080 case S390_DFP_SHIFT_LEFT: return s390_emit_SLDT(buf, r3, r1, r2);
9081 case S390_DFP_SHIFT_RIGHT: return s390_emit_SRDT(buf, r3, r1, r2);
florian5c539732013-02-14 14:27:12 +00009082 case S390_DFP_INSERT_EXP: return s390_emit_IEDTR(buf, r3, r1, r2);
florian1b901d42013-01-01 22:19:24 +00009083 default: goto fail;
9084 }
9085 break;
9086
9087 case 16:
9088 switch (insn->variant.dfp_intop.tag) {
9089 case S390_DFP_SHIFT_LEFT: return s390_emit_SLXT(buf, r3, r1, r2);
9090 case S390_DFP_SHIFT_RIGHT: return s390_emit_SRXT(buf, r3, r1, r2);
florian5c539732013-02-14 14:27:12 +00009091 case S390_DFP_INSERT_EXP: return s390_emit_IEXTR(buf, r3, r1, r2);
florian1b901d42013-01-01 22:19:24 +00009092 default: goto fail;
9093 }
9094 break;
9095
9096 default: goto fail;
9097 }
9098
9099 fail:
9100 vpanic("s390_insn_dfp_intop_emit");
9101}
9102
9103
9104static UChar *
floriane38f6412012-12-21 17:32:12 +00009105s390_insn_dfp_compare_emit(UChar *buf, const s390_insn *insn)
9106{
9107 UInt dst = hregNumber(insn->variant.dfp_compare.dst);
9108 UInt r1 = hregNumber(insn->variant.dfp_compare.op1_hi);
9109 UInt r2 = hregNumber(insn->variant.dfp_compare.op2_hi);
9110
9111 switch (insn->size) {
florian20c6bca2012-12-26 17:47:19 +00009112 case 8:
9113 switch(insn->variant.dfp_compare.tag) {
9114 case S390_DFP_COMPARE: buf = s390_emit_CDTR(buf, r1, r2); break;
9115 case S390_DFP_COMPARE_EXP: buf = s390_emit_CEDTR(buf, r1, r2); break;
9116 default: goto fail;
9117 }
9118 break;
9119
9120 case 16:
9121 switch(insn->variant.dfp_compare.tag) {
9122 case S390_DFP_COMPARE: buf = s390_emit_CXTR(buf, r1, r2); break;
9123 case S390_DFP_COMPARE_EXP: buf = s390_emit_CEXTR(buf, r1, r2); break;
9124 default: goto fail;
9125 }
9126 break;
9127
floriane38f6412012-12-21 17:32:12 +00009128 default: goto fail;
9129 }
9130
9131 return s390_emit_load_cc(buf, dst); /* Load condition code into DST */
9132
9133 fail:
9134 vpanic("s390_insn_dfp_compare_emit");
9135}
9136
9137
9138static UChar *
9139s390_insn_dfp_convert_emit(UChar *buf, const s390_insn *insn)
9140{
9141 UInt r1 = hregNumber(insn->variant.dfp_convert.dst_hi);
9142 UInt r2 = hregNumber(insn->variant.dfp_convert.op_hi);
9143 s390_dfp_round_t m3 = insn->variant.dfp_convert.rounding_mode;
9144 /* The IEEE-inexact-exception control is not modelled. So the
9145 m4 field is 0 (which is what GCC does, too) */
9146 const UInt m4 = 0;
9147
9148 switch (insn->variant.dfp_convert.tag) {
9149
florian5f034622013-01-13 02:29:05 +00009150 /* Convert to fixed */
9151 case S390_DFP_D64_TO_I32: return s390_emit_CFDTR(buf, m3, m4, r1, r2);
9152 case S390_DFP_D128_TO_I32: return s390_emit_CFXTR(buf, m3, m4, r1, r2);
floriana887acd2013-02-08 23:32:54 +00009153 case S390_DFP_D64_TO_I64: return s390_emit_CGDTR(buf, m3, m4, r1, r2);
9154 case S390_DFP_D128_TO_I64: return s390_emit_CGXTR(buf, m3, m4, r1, r2);
florian5f034622013-01-13 02:29:05 +00009155
9156 /* Convert to logical */
9157 case S390_DFP_D64_TO_U32: return s390_emit_CLFDTR(buf, m3, m4, r1, r2);
9158 case S390_DFP_D128_TO_U32: return s390_emit_CLFXTR(buf, m3, m4, r1, r2);
9159 case S390_DFP_D64_TO_U64: return s390_emit_CLGDTR(buf, m3, m4, r1, r2);
9160 case S390_DFP_D128_TO_U64: return s390_emit_CLGXTR(buf, m3, m4, r1, r2);
9161
9162 /* Convert from fixed */
9163 case S390_DFP_I32_TO_D64: return s390_emit_CDFTR(buf, 0, m4, r1, r2);
9164 case S390_DFP_I32_TO_D128: return s390_emit_CXFTR(buf, 0, m4, r1, r2);
floriana887acd2013-02-08 23:32:54 +00009165 case S390_DFP_I64_TO_D64: return s390_emit_CDGTRA(buf, m3, m4, r1, r2);
9166 case S390_DFP_I64_TO_D128: return s390_emit_CXGTR(buf, 0, m4, r1, r2);
florian5f034622013-01-13 02:29:05 +00009167
9168 /* Convert from logical */
9169 case S390_DFP_U32_TO_D64: return s390_emit_CDLFTR(buf, m3, m4, r1, r2);
9170 case S390_DFP_U64_TO_D64: return s390_emit_CDLGTR(buf, m3, m4, r1, r2);
9171 case S390_DFP_U32_TO_D128: return s390_emit_CXLFTR(buf, m3, m4, r1, r2);
9172 case S390_DFP_U64_TO_D128: return s390_emit_CXLGTR(buf, m3, m4, r1, r2);
9173
floriane38f6412012-12-21 17:32:12 +00009174 /* Load lengthened */
9175 case S390_DFP_D32_TO_D64: return s390_emit_LDETR(buf, m4, r1, r2);
9176 case S390_DFP_D64_TO_D128: return s390_emit_LXDTR(buf, m4, r1, r2);
9177
9178 /* Load rounded */
9179 case S390_DFP_D64_TO_D32: return s390_emit_LEDTR(buf, m3, m4, r1, r2);
9180 case S390_DFP_D128_TO_D64: return s390_emit_LDXTR(buf, m3, m4, r1, r2);
9181
9182 default: goto fail;
9183 }
9184
9185 fail:
9186 vpanic("s390_insn_dfp_convert_emit");
9187}
9188
9189
9190static UChar *
florian78d5ef72013-05-11 15:02:58 +00009191s390_insn_fp_convert_emit(UChar *buf, const s390_insn *insn)
9192{
9193 UInt pfpo;
9194 s390_fp_convert *fp_convert = insn->variant.fp_convert.details;
9195 s390_dfp_round_t rm = fp_convert->rounding_mode;
9196
9197 vassert(rm < 2 || rm > 7);
9198
9199 switch (fp_convert->tag) {
florian7ab421d2013-06-17 21:03:56 +00009200 case S390_FP_F32_TO_D32: pfpo = S390_PFPO_F32_TO_D32 << 8; break;
9201 case S390_FP_F32_TO_D64: pfpo = S390_PFPO_F32_TO_D64 << 8; break;
9202 case S390_FP_F32_TO_D128: pfpo = S390_PFPO_F32_TO_D128 << 8; break;
9203 case S390_FP_F64_TO_D32: pfpo = S390_PFPO_F64_TO_D32 << 8; break;
florian78d5ef72013-05-11 15:02:58 +00009204 case S390_FP_F64_TO_D64: pfpo = S390_PFPO_F64_TO_D64 << 8; break;
florian78d5ef72013-05-11 15:02:58 +00009205 case S390_FP_F64_TO_D128: pfpo = S390_PFPO_F64_TO_D128 << 8; break;
florian7ab421d2013-06-17 21:03:56 +00009206 case S390_FP_F128_TO_D32: pfpo = S390_PFPO_F128_TO_D32 << 8; break;
9207 case S390_FP_F128_TO_D64: pfpo = S390_PFPO_F128_TO_D64 << 8; break;
florian78d5ef72013-05-11 15:02:58 +00009208 case S390_FP_F128_TO_D128: pfpo = S390_PFPO_F128_TO_D128 << 8; break;
florian7ab421d2013-06-17 21:03:56 +00009209 case S390_FP_D32_TO_F32: pfpo = S390_PFPO_D32_TO_F32 << 8; break;
9210 case S390_FP_D32_TO_F64: pfpo = S390_PFPO_D32_TO_F64 << 8; break;
9211 case S390_FP_D32_TO_F128: pfpo = S390_PFPO_D32_TO_F128 << 8; break;
9212 case S390_FP_D64_TO_F32: pfpo = S390_PFPO_D64_TO_F32 << 8; break;
9213 case S390_FP_D64_TO_F64: pfpo = S390_PFPO_D64_TO_F64 << 8; break;
9214 case S390_FP_D64_TO_F128: pfpo = S390_PFPO_D64_TO_F128 << 8; break;
9215 case S390_FP_D128_TO_F32: pfpo = S390_PFPO_D128_TO_F32 << 8; break;
9216 case S390_FP_D128_TO_F64: pfpo = S390_PFPO_D128_TO_F64 << 8; break;
florian78d5ef72013-05-11 15:02:58 +00009217 case S390_FP_D128_TO_F128: pfpo = S390_PFPO_D128_TO_F128 << 8; break;
9218 default: goto fail;
9219 }
9220
9221 pfpo = pfpo | rm;
9222 buf = s390_emit_load_32imm(buf, R0, pfpo);
9223 buf = s390_emit_PFPO(buf);
9224 return buf;
9225
9226 fail:
9227 vpanic("s390_insn_fp_convert_emit");
9228}
9229
9230
9231static UChar *
sewardja52e37e2011-04-28 18:48:06 +00009232s390_insn_mfence_emit(UChar *buf, const s390_insn *insn)
9233{
9234 return s390_emit_BCR(buf, 0xF, 0x0);
9235}
9236
9237
florianad43b3a2012-02-20 15:01:14 +00009238static UChar *
florianb93348d2012-12-27 00:59:43 +00009239s390_insn_mimm_emit(UChar *buf, const s390_insn *insn)
florianad43b3a2012-02-20 15:01:14 +00009240{
florianb93348d2012-12-27 00:59:43 +00009241 s390_amode *am = insn->variant.mimm.dst;
florian3123f722013-01-24 15:55:52 +00009242 UChar b = hregNumber(am->b);
florian3123f722013-01-24 15:55:52 +00009243 Int d = am->d;
florianb93348d2012-12-27 00:59:43 +00009244 ULong value = insn->variant.mimm.value;
florian09bbba82012-12-11 04:09:43 +00009245
florianb93348d2012-12-27 00:59:43 +00009246 if (value == 0) {
florian3123f722013-01-24 15:55:52 +00009247 return s390_emit_XC(buf, insn->size - 1, b, d, b, d);
florianb93348d2012-12-27 00:59:43 +00009248 }
9249
9250 if (insn->size == 1) {
florian3123f722013-01-24 15:55:52 +00009251 return s390_emit_MVI(buf, value & 0xFF, b, d);
florianb93348d2012-12-27 00:59:43 +00009252 }
9253
9254 if (s390_host_has_gie && ulong_fits_signed_16bit(value)) {
9255 value &= 0xFFFF;
9256 switch (insn->size) {
florian3123f722013-01-24 15:55:52 +00009257 case 2: return s390_emit_MVHHI(buf, b, d, value);
9258 case 4: return s390_emit_MVHI(buf, b, d, value);
9259 case 8: return s390_emit_MVGHI(buf, b, d, value);
florianb93348d2012-12-27 00:59:43 +00009260 }
9261 } else {
9262 // Load value to R0, then store.
9263 switch (insn->size) {
9264 case 2:
9265 buf = s390_emit_LHI(buf, R0, value & 0xFFFF);
florian3123f722013-01-24 15:55:52 +00009266 return s390_emit_STH(buf, R0, 0, b, d);
florianb93348d2012-12-27 00:59:43 +00009267 case 4:
9268 buf = s390_emit_load_32imm(buf, R0, value);
florian3123f722013-01-24 15:55:52 +00009269 return s390_emit_ST(buf, R0, 0, b, d);
florianb93348d2012-12-27 00:59:43 +00009270 case 8:
9271 buf = s390_emit_load_64imm(buf, R0, value);
florian3123f722013-01-24 15:55:52 +00009272 return s390_emit_STG(buf, R0, 0, b, DISP20(d));
florianb93348d2012-12-27 00:59:43 +00009273 }
9274 }
9275
9276 vpanic("s390_insn_mimm_emit");
florianad43b3a2012-02-20 15:01:14 +00009277}
9278
9279
9280static UChar *
florianf85fe3e2012-12-22 02:28:25 +00009281s390_insn_madd_emit(UChar *buf, const s390_insn *insn)
florianad43b3a2012-02-20 15:01:14 +00009282{
florianf85fe3e2012-12-22 02:28:25 +00009283 s390_amode *am = insn->variant.madd.dst;
florian3123f722013-01-24 15:55:52 +00009284 UChar b = hregNumber(am->b);
florian3123f722013-01-24 15:55:52 +00009285 Int d = am->d;
florianf85fe3e2012-12-22 02:28:25 +00009286
9287 if (insn->size == 4) {
florian3123f722013-01-24 15:55:52 +00009288 return s390_emit_ASI(buf, insn->variant.madd.delta, b, DISP20(d));
florianf85fe3e2012-12-22 02:28:25 +00009289 }
9290
florian3123f722013-01-24 15:55:52 +00009291 return s390_emit_AGSI(buf, insn->variant.madd.delta, b, DISP20(d));
florianad43b3a2012-02-20 15:01:14 +00009292}
9293
9294
florian2c74d242012-09-12 19:38:42 +00009295static UChar *
florian125e20d2012-10-07 15:42:37 +00009296s390_insn_set_fpc_bfprm_emit(UChar *buf, const s390_insn *insn)
florian2c74d242012-09-12 19:38:42 +00009297{
florian125e20d2012-10-07 15:42:37 +00009298 UInt mode = hregNumber(insn->variant.set_fpc_bfprm.mode);
florian2c74d242012-09-12 19:38:42 +00009299
9300 /* Copy FPC from guest state to R0 and OR in the new rounding mode */
9301 buf = s390_emit_L(buf, R0, 0, S390_REGNO_GUEST_STATE_POINTER,
9302 S390X_GUEST_OFFSET(guest_fpc)); // r0 = guest_fpc
9303
9304 buf = s390_emit_NILL(buf, R0, 0xFFF8); /* Clear out right-most 3 bits */
9305 buf = s390_emit_OR(buf, R0, mode); /* OR in the new rounding mode */
florian6d8e26e2012-09-12 19:52:16 +00009306 buf = s390_emit_SFPC(buf, R0); /* Load FPC register from R0 */
florian2c74d242012-09-12 19:38:42 +00009307
9308 return buf;
9309}
9310
9311
florianc8e4f562012-10-27 16:19:31 +00009312static UChar *
9313s390_insn_set_fpc_dfprm_emit(UChar *buf, const s390_insn *insn)
9314{
9315 UInt mode = hregNumber(insn->variant.set_fpc_dfprm.mode);
9316
9317 /* Copy FPC from guest state to R0 and OR in the new rounding mode */
9318 buf = s390_emit_L(buf, R0, 0, S390_REGNO_GUEST_STATE_POINTER,
9319 S390X_GUEST_OFFSET(guest_fpc)); // r0 = guest_fpc
9320
9321 /* DFP rounding mode is set at bit position 25:27 in FPC register */
9322 buf = s390_emit_NILL(buf, R0, 0xFF8F); /* Clear out 25:27 bits */
9323 buf = s390_emit_SLL(buf, mode, 0, 4); /* bring mode to 25:27 bits */
9324 buf = s390_emit_OR(buf, R0, mode); /* OR in the new rounding mode */
9325 buf = s390_emit_SFPC(buf, R0); /* Load FPC register from R0 */
9326
9327 return buf;
9328}
9329
9330
florian8844a632012-04-13 04:04:06 +00009331/* Define convenience functions needed for translation chaining.
9332 Any changes need to be applied to the functions in concert. */
9333
florian1c857042012-04-15 04:11:07 +00009334static __inline__ Bool
9335s390_insn_is_BRCL(const UChar *p, UChar condition)
9336{
9337 return p[0] == 0xc0 && p[1] == ((condition << 4) | 0x04);
9338}
9339
9340static __inline__ Bool
9341s390_insn_is_BR(const UChar *p, UChar reg)
9342{
9343 return p[0] == 0x07 && p[1] == (0xF0 | reg); /* BCR 15,reg */
9344}
9345
florianebaf8d92012-04-22 17:38:46 +00009346
9347/* The length of the BASR insn */
9348#define S390_BASR_LEN 2
9349
florian1c857042012-04-15 04:11:07 +00009350
florian8844a632012-04-13 04:04:06 +00009351/* Load the 64-bit VALUE into REG. Note that this function must NOT
9352 optimise the generated code by looking at the value. I.e. using
floriane09e8bb2012-05-07 03:28:18 +00009353 LGHI if value == 0 would be very wrong. */
florian8844a632012-04-13 04:04:06 +00009354static UChar *
9355s390_tchain_load64(UChar *buf, UChar regno, ULong value)
9356{
florian1c857042012-04-15 04:11:07 +00009357 UChar *begin = buf;
9358
florian1c2b4db2012-04-22 17:46:31 +00009359 if (s390_host_has_eimm) {
9360 /* Do it in two steps: upper half [0:31] and lower half [32:63] */
9361 buf = s390_emit_IIHF(buf, regno, value >> 32);
9362 buf = s390_emit_IILF(buf, regno, value & 0xFFFFFFFF);
9363 } else {
9364 buf = s390_emit_IILL(buf, regno, value & 0xFFFF);
9365 value >>= 16;
9366 buf = s390_emit_IILH(buf, regno, value & 0xFFFF);
9367 value >>= 16;
9368 buf = s390_emit_IIHL(buf, regno, value & 0xFFFF);
9369 value >>= 16;
9370 buf = s390_emit_IIHH(buf, regno, value & 0xFFFF);
9371 }
florian8844a632012-04-13 04:04:06 +00009372
florian1c857042012-04-15 04:11:07 +00009373 vassert(buf - begin == s390_tchain_load64_len());
9374
florian8844a632012-04-13 04:04:06 +00009375 return buf;
9376}
9377
9378/* Return number of bytes generated by s390_tchain_load64 */
9379static UInt
9380s390_tchain_load64_len(void)
9381{
florian1c2b4db2012-04-22 17:46:31 +00009382 if (s390_host_has_eimm) {
9383 return 6 + 6; /* IIHF + IILF */
9384 }
florianebaf8d92012-04-22 17:38:46 +00009385 return 4 + 4 + 4 + 4; /* IIHH + IIHL + IILH + IILL */
florian8844a632012-04-13 04:04:06 +00009386}
9387
9388/* Verify that CODE is the code sequence generated by s390_tchain_load64
9389 to load VALUE into REGNO. Return pointer to the byte following the
9390 insn sequence. */
9391static const UChar *
9392s390_tchain_verify_load64(const UChar *code, UChar regno, ULong value)
9393{
9394 UInt regmask = regno << 4;
9395 UInt hw;
9396
florian1c2b4db2012-04-22 17:46:31 +00009397 if (s390_host_has_eimm) {
9398 /* Check for IIHF */
9399 vassert(code[0] == 0xC0);
9400 vassert(code[1] == (0x08 | regmask));
9401 vassert(*(const UInt *)&code[2] == (value >> 32));
9402 /* Check for IILF */
9403 vassert(code[6] == 0xC0);
9404 vassert(code[7] == (0x09 | regmask));
9405 vassert(*(const UInt *)&code[8] == (value & 0xFFFFFFFF));
9406 } else {
9407 /* Check for IILL */
9408 hw = value & 0xFFFF;
9409 vassert(code[0] == 0xA5);
9410 vassert(code[1] == (0x03 | regmask));
9411 vassert(code[2] == (hw >> 8));
9412 vassert(code[3] == (hw & 0xFF));
florian8844a632012-04-13 04:04:06 +00009413
florian1c2b4db2012-04-22 17:46:31 +00009414 /* Check for IILH */
9415 hw = (value >> 16) & 0xFFFF;
9416 vassert(code[4] == 0xA5);
9417 vassert(code[5] == (0x02 | regmask));
9418 vassert(code[6] == (hw >> 8));
9419 vassert(code[7] == (hw & 0xFF));
florian8844a632012-04-13 04:04:06 +00009420
florian1c2b4db2012-04-22 17:46:31 +00009421 /* Check for IIHL */
9422 hw = (value >> 32) & 0xFFFF;
9423 vassert(code[8] == 0xA5);
9424 vassert(code[9] == (0x01 | regmask));
9425 vassert(code[10] == (hw >> 8));
9426 vassert(code[11] == (hw & 0xFF));
florian8844a632012-04-13 04:04:06 +00009427
florian1c2b4db2012-04-22 17:46:31 +00009428 /* Check for IIHH */
9429 hw = (value >> 48) & 0xFFFF;
9430 vassert(code[12] == 0xA5);
9431 vassert(code[13] == (0x00 | regmask));
9432 vassert(code[14] == (hw >> 8));
9433 vassert(code[15] == (hw & 0xFF));
9434 }
florian8844a632012-04-13 04:04:06 +00009435
florian1c857042012-04-15 04:11:07 +00009436 return code + s390_tchain_load64_len();
florian8844a632012-04-13 04:04:06 +00009437}
9438
9439/* CODE points to the code sequence as generated by s390_tchain_load64.
florian5ea257b2012-09-29 17:05:46 +00009440 Change the loaded value to IMM64. Return pointer to the byte following
florian8844a632012-04-13 04:04:06 +00009441 the patched code sequence. */
9442static UChar *
9443s390_tchain_patch_load64(UChar *code, ULong imm64)
9444{
florian1c2b4db2012-04-22 17:46:31 +00009445 if (s390_host_has_eimm) {
9446 /* Patch IIHF */
9447 *(UInt *)&code[2] = imm64 >> 32;
9448 /* Patch IILF */
9449 *(UInt *)&code[8] = imm64 & 0xFFFFFFFF;
9450 } else {
9451 code[3] = imm64 & 0xFF; imm64 >>= 8;
9452 code[2] = imm64 & 0xFF; imm64 >>= 8;
9453 code[7] = imm64 & 0xFF; imm64 >>= 8;
9454 code[6] = imm64 & 0xFF; imm64 >>= 8;
9455 code[11] = imm64 & 0xFF; imm64 >>= 8;
9456 code[10] = imm64 & 0xFF; imm64 >>= 8;
9457 code[15] = imm64 & 0xFF; imm64 >>= 8;
9458 code[14] = imm64 & 0xFF; imm64 >>= 8;
9459 }
florian8844a632012-04-13 04:04:06 +00009460
florian1c857042012-04-15 04:11:07 +00009461 return code + s390_tchain_load64_len();
florian8844a632012-04-13 04:04:06 +00009462}
9463
9464
9465/* NB: what goes on here has to be very closely coordinated with the
9466 chainXDirect_S390 and unchainXDirect_S390 below. */
9467static UChar *
9468s390_insn_xdirect_emit(UChar *buf, const s390_insn *insn,
florian8462d112014-09-24 15:18:09 +00009469 const void *disp_cp_chain_me_to_slowEP,
9470 const void *disp_cp_chain_me_to_fastEP)
florian8844a632012-04-13 04:04:06 +00009471{
9472 /* We're generating chain-me requests here, so we need to be
9473 sure this is actually allowed -- no-redir translations can't
9474 use chain-me's. Hence: */
9475 vassert(disp_cp_chain_me_to_slowEP != NULL);
9476 vassert(disp_cp_chain_me_to_fastEP != NULL);
9477
9478 /* Use ptmp for backpatching conditional jumps. */
9479 UChar *ptmp = buf;
9480
9481 /* First off, if this is conditional, create a conditional
9482 jump over the rest of it. */
9483 s390_cc_t cond = insn->variant.xdirect.cond;
9484
9485 if (cond != S390_CC_ALWAYS) {
9486 /* So we have something like this
9487 if (cond) do_xdirect;
9488 Y: ...
9489 We convert this into
9490 if (! cond) goto Y; // BRC opcode; 4 bytes
9491 do_xdirect;
9492 Y:
9493 */
9494 /* 4 bytes (a BRC insn) to be filled in here */
9495 buf += 4;
9496 }
9497
9498 /* Update the guest IA. */
9499 buf = s390_emit_load_64imm(buf, R0, insn->variant.xdirect.dst);
9500
9501 const s390_amode *amode = insn->variant.xdirect.guest_IA;
florianbf516d12012-04-21 15:53:13 +00009502 vassert(amode->tag == S390_AMODE_B12);
florian8844a632012-04-13 04:04:06 +00009503 UInt b = hregNumber(amode->b);
florian8844a632012-04-13 04:04:06 +00009504 UInt d = amode->d;
9505
florianbf516d12012-04-21 15:53:13 +00009506 buf = s390_emit_STG(buf, R0, 0, b, DISP20(d));
florian8844a632012-04-13 04:04:06 +00009507
florian8844a632012-04-13 04:04:06 +00009508 /* Load the chosen entry point into the scratch reg */
florian8462d112014-09-24 15:18:09 +00009509 const void *disp_cp_chain_me;
florian8844a632012-04-13 04:04:06 +00009510
9511 disp_cp_chain_me =
9512 insn->variant.xdirect.to_fast_entry ? disp_cp_chain_me_to_fastEP
9513 : disp_cp_chain_me_to_slowEP;
florianebaf8d92012-04-22 17:38:46 +00009514 /* Get the address of the beginning of the load64 code sequence into %r1.
9515 Do not change the register! This is part of the protocol with the
9516 dispatcher. */
9517 buf = s390_emit_BASR(buf, 1, R0);
florian8844a632012-04-13 04:04:06 +00009518
florianebaf8d92012-04-22 17:38:46 +00009519 /* --- FIRST PATCHABLE BYTE follows (must not modify %r1) --- */
florian8844a632012-04-13 04:04:06 +00009520 ULong addr = Ptr_to_ULong(disp_cp_chain_me);
9521 buf = s390_tchain_load64(buf, S390_REGNO_TCHAIN_SCRATCH, addr);
9522
florianebaf8d92012-04-22 17:38:46 +00009523 /* goto *tchain_scratch */
9524 buf = s390_emit_BCR(buf, S390_CC_ALWAYS, S390_REGNO_TCHAIN_SCRATCH);
florian8844a632012-04-13 04:04:06 +00009525
9526 /* --- END of PATCHABLE BYTES --- */
9527
9528 /* Fix up the conditional jump, if there was one. */
9529 if (cond != S390_CC_ALWAYS) {
9530 Int delta = buf - ptmp;
9531
9532 delta >>= 1; /* immediate constant is #half-words */
9533 vassert(delta > 0 && delta < (1 << 16));
9534 s390_emit_BRC(ptmp, s390_cc_invert(cond), delta);
9535 }
9536
9537 return buf;
9538}
9539
9540/* Return the number of patchable bytes from an xdirect insn. */
9541static UInt
9542s390_xdirect_patchable_len(void)
9543{
florianebaf8d92012-04-22 17:38:46 +00009544 return s390_tchain_load64_len() + S390_BASR_LEN;
florian8844a632012-04-13 04:04:06 +00009545}
9546
9547
9548static UChar *
florian8462d112014-09-24 15:18:09 +00009549s390_insn_xindir_emit(UChar *buf, const s390_insn *insn,
9550 const void *disp_cp_xindir)
florian8844a632012-04-13 04:04:06 +00009551{
9552 /* We're generating transfers that could lead indirectly to a
9553 chain-me, so we need to be sure this is actually allowed --
9554 no-redir translations are not allowed to reach normal
9555 translations without going through the scheduler. That means
9556 no XDirects or XIndirs out from no-redir translations.
9557 Hence: */
9558 vassert(disp_cp_xindir != NULL);
9559
9560 /* Use ptmp for backpatching conditional jumps. */
9561 UChar *ptmp = buf;
9562
9563 /* First off, if this is conditional, create a conditional
9564 jump over the rest of it. */
9565 s390_cc_t cond = insn->variant.xdirect.cond;
9566
9567 if (cond != S390_CC_ALWAYS) {
9568 /* So we have something like this
9569 if (cond) do_xdirect;
9570 Y: ...
9571 We convert this into
9572 if (! cond) goto Y; // BRC opcode; 4 bytes
9573 do_xdirect;
9574 Y:
9575 */
9576 /* 4 bytes (a BRC insn) to be filled in here */
9577 buf += 4;
9578 }
9579
9580 /* Update the guest IA with the address in xdirect.dst. */
florian7346c7a2012-04-13 21:14:24 +00009581 const s390_amode *amode = insn->variant.xindir.guest_IA;
florian8844a632012-04-13 04:04:06 +00009582
florianbf516d12012-04-21 15:53:13 +00009583 vassert(amode->tag == S390_AMODE_B12);
florian8844a632012-04-13 04:04:06 +00009584 UInt b = hregNumber(amode->b);
florian8844a632012-04-13 04:04:06 +00009585 UInt d = amode->d;
florian7346c7a2012-04-13 21:14:24 +00009586 UInt regno = hregNumber(insn->variant.xindir.dst);
florian8844a632012-04-13 04:04:06 +00009587
florianbf516d12012-04-21 15:53:13 +00009588 buf = s390_emit_STG(buf, regno, 0, b, DISP20(d));
florian8844a632012-04-13 04:04:06 +00009589
9590 /* load tchain_scratch, #disp_indir */
9591 buf = s390_tchain_load64(buf, S390_REGNO_TCHAIN_SCRATCH,
9592 Ptr_to_ULong(disp_cp_xindir));
florianebaf8d92012-04-22 17:38:46 +00009593 /* goto *tchain_direct */
florian8844a632012-04-13 04:04:06 +00009594 buf = s390_emit_BCR(buf, S390_CC_ALWAYS, S390_REGNO_TCHAIN_SCRATCH);
9595
9596 /* Fix up the conditional jump, if there was one. */
9597 if (cond != S390_CC_ALWAYS) {
9598 Int delta = buf - ptmp;
9599
9600 delta >>= 1; /* immediate constant is #half-words */
9601 vassert(delta > 0 && delta < (1 << 16));
9602 s390_emit_BRC(ptmp, s390_cc_invert(cond), delta);
9603 }
9604
9605 return buf;
9606}
9607
9608static UChar *
9609s390_insn_xassisted_emit(UChar *buf, const s390_insn *insn,
florian8462d112014-09-24 15:18:09 +00009610 const void *disp_cp_xassisted)
florian8844a632012-04-13 04:04:06 +00009611{
9612 /* Use ptmp for backpatching conditional jumps. */
9613 UChar *ptmp = buf;
9614
9615 /* First off, if this is conditional, create a conditional
9616 jump over the rest of it. */
9617 s390_cc_t cond = insn->variant.xdirect.cond;
9618
9619 if (cond != S390_CC_ALWAYS) {
9620 /* So we have something like this
9621 if (cond) do_xdirect;
9622 Y: ...
9623 We convert this into
9624 if (! cond) goto Y; // BRC opcode; 4 bytes
9625 do_xdirect;
9626 Y:
9627 */
9628 /* 4 bytes (a BRC insn) to be filled in here */
9629 buf += 4;
9630 }
9631
9632 /* Update the guest IA with the address in xassisted.dst. */
9633 const s390_amode *amode = insn->variant.xassisted.guest_IA;
9634
florianbf516d12012-04-21 15:53:13 +00009635 vassert(amode->tag == S390_AMODE_B12);
florian8844a632012-04-13 04:04:06 +00009636 UInt b = hregNumber(amode->b);
florian8844a632012-04-13 04:04:06 +00009637 UInt d = amode->d;
9638 UInt regno = hregNumber(insn->variant.xassisted.dst);
9639
florianbf516d12012-04-21 15:53:13 +00009640 buf = s390_emit_STG(buf, regno, 0, b, DISP20(d));
florian8844a632012-04-13 04:04:06 +00009641
9642 UInt trcval = 0;
9643
9644 switch (insn->variant.xassisted.kind) {
9645 case Ijk_ClientReq: trcval = VEX_TRC_JMP_CLIENTREQ; break;
9646 case Ijk_Sys_syscall: trcval = VEX_TRC_JMP_SYS_SYSCALL; break;
florian8844a632012-04-13 04:04:06 +00009647 case Ijk_Yield: trcval = VEX_TRC_JMP_YIELD; break;
9648 case Ijk_EmWarn: trcval = VEX_TRC_JMP_EMWARN; break;
florian4e0083e2012-08-26 03:41:56 +00009649 case Ijk_EmFail: trcval = VEX_TRC_JMP_EMFAIL; break;
florian8844a632012-04-13 04:04:06 +00009650 case Ijk_MapFail: trcval = VEX_TRC_JMP_MAPFAIL; break;
9651 case Ijk_NoDecode: trcval = VEX_TRC_JMP_NODECODE; break;
sewardj05f5e012014-05-04 10:52:11 +00009652 case Ijk_InvalICache: trcval = VEX_TRC_JMP_INVALICACHE; break;
florian8844a632012-04-13 04:04:06 +00009653 case Ijk_NoRedir: trcval = VEX_TRC_JMP_NOREDIR; break;
9654 case Ijk_SigTRAP: trcval = VEX_TRC_JMP_SIGTRAP; break;
9655 case Ijk_SigSEGV: trcval = VEX_TRC_JMP_SIGSEGV; break;
9656 case Ijk_Boring: trcval = VEX_TRC_JMP_BORING; break;
9657 /* We don't expect to see the following being assisted. */
9658 case Ijk_Ret:
9659 case Ijk_Call:
9660 /* fallthrough */
9661 default:
9662 ppIRJumpKind(insn->variant.xassisted.kind);
9663 vpanic("s390_insn_xassisted_emit: unexpected jump kind");
9664 }
9665
9666 vassert(trcval != 0);
9667
9668 /* guest_state_pointer = trcval */
9669 buf = s390_emit_LGHI(buf, S390_REGNO_GUEST_STATE_POINTER, trcval);
9670
9671 /* load tchain_scratch, #disp_assisted */
9672 buf = s390_tchain_load64(buf, S390_REGNO_TCHAIN_SCRATCH,
9673 Ptr_to_ULong(disp_cp_xassisted));
9674
florianebaf8d92012-04-22 17:38:46 +00009675 /* goto *tchain_direct */
florian8844a632012-04-13 04:04:06 +00009676 buf = s390_emit_BCR(buf, S390_CC_ALWAYS, S390_REGNO_TCHAIN_SCRATCH);
9677
9678 /* Fix up the conditional jump, if there was one. */
9679 if (cond != S390_CC_ALWAYS) {
9680 Int delta = buf - ptmp;
9681
9682 delta >>= 1; /* immediate constant is #half-words */
9683 vassert(delta > 0 && delta < (1 << 16));
9684 s390_emit_BRC(ptmp, s390_cc_invert(cond), delta);
9685 }
9686
9687 return buf;
9688}
9689
9690
9691/* Pseudo code:
9692
9693 guest_state[host_EvC_COUNTER] -= 1;
9694 if (guest_state[host_EvC_COUNTER] >= 0) goto nofail;
9695 goto guest_state[host_EvC_FAILADDR];
9696 nofail: ;
9697
9698 The dispatch counter is a 32-bit value. */
9699static UChar *
sewardj9b769162014-07-24 12:42:03 +00009700s390_insn_evcheck_emit(UChar *buf, const s390_insn *insn,
9701 VexEndness endness_host)
florian8844a632012-04-13 04:04:06 +00009702{
9703 s390_amode *amode;
florianbf516d12012-04-21 15:53:13 +00009704 UInt b, d;
florian8844a632012-04-13 04:04:06 +00009705 UChar *code_begin, *code_end;
9706
9707 code_begin = buf;
9708
9709 amode = insn->variant.evcheck.counter;
florianbf516d12012-04-21 15:53:13 +00009710 vassert(amode->tag == S390_AMODE_B12);
florian8844a632012-04-13 04:04:06 +00009711 b = hregNumber(amode->b);
florian8844a632012-04-13 04:04:06 +00009712 d = amode->d;
9713
9714 /* Decrement the dispatch counter in the guest state */
florian0e047d62012-04-21 16:06:04 +00009715 if (s390_host_has_gie) {
9716 buf = s390_emit_ASI(buf, -1, b, DISP20(d)); /* 6 bytes */
9717 } else {
9718 buf = s390_emit_LHI(buf, R0, -1); /* 4 bytes */
9719 buf = s390_emit_A(buf, R0, 0, b, d); /* 4 bytes */
9720 buf = s390_emit_ST(buf, R0, 0, b, d); /* 4 bytes */
9721 }
florian8844a632012-04-13 04:04:06 +00009722
9723 /* Jump over the next insn if >= 0 */
9724 buf = s390_emit_BRC(buf, S390_CC_HE, (4 + 6 + 2) / 2); /* 4 bytes */
9725
9726 /* Computed goto to fail_address */
9727 amode = insn->variant.evcheck.fail_addr;
9728 b = hregNumber(amode->b);
florian8844a632012-04-13 04:04:06 +00009729 d = amode->d;
florianbf516d12012-04-21 15:53:13 +00009730 buf = s390_emit_LG(buf, S390_REGNO_TCHAIN_SCRATCH, 0, b, DISP20(d)); /* 6 bytes */
florian8844a632012-04-13 04:04:06 +00009731 buf = s390_emit_BCR(buf, S390_CC_ALWAYS, S390_REGNO_TCHAIN_SCRATCH); /* 2 bytes */
9732
9733 code_end = buf;
9734
9735 /* Make sure the size of the generated code is identical to the size
9736 returned by evCheckSzB_S390 */
sewardj9b769162014-07-24 12:42:03 +00009737 vassert(evCheckSzB_S390(endness_host) == code_end - code_begin);
florian8844a632012-04-13 04:04:06 +00009738
9739 return buf;
9740}
9741
9742
9743static UChar *
9744s390_insn_profinc_emit(UChar *buf,
9745 const s390_insn *insn __attribute__((unused)))
9746{
9747 /* Generate a code template to increment a memory location whose
9748 address will be known later as an immediate value. This code
9749 template will be patched once the memory location is known.
9750 For now we do this with address == 0. */
9751 buf = s390_tchain_load64(buf, S390_REGNO_TCHAIN_SCRATCH, 0);
florian0e047d62012-04-21 16:06:04 +00009752 if (s390_host_has_gie) {
9753 buf = s390_emit_AGSI(buf, 1, S390_REGNO_TCHAIN_SCRATCH, DISP20(0));
9754 } else {
9755 buf = s390_emit_LGHI(buf, R0, 1);
9756 buf = s390_emit_AG( buf, R0, 0, S390_REGNO_TCHAIN_SCRATCH, DISP20(0));
9757 buf = s390_emit_STG(buf, R0, 0, S390_REGNO_TCHAIN_SCRATCH, DISP20(0));
9758 }
florian8844a632012-04-13 04:04:06 +00009759
9760 return buf;
9761}
9762
9763
sewardj2019a972011-03-07 16:04:07 +00009764Int
floriand8c64e02014-10-08 08:54:44 +00009765emit_S390Instr(Bool *is_profinc, UChar *buf, Int nbuf, const s390_insn *insn,
sewardj9b769162014-07-24 12:42:03 +00009766 Bool mode64, VexEndness endness_host,
florian8462d112014-09-24 15:18:09 +00009767 const void *disp_cp_chain_me_to_slowEP,
9768 const void *disp_cp_chain_me_to_fastEP,
9769 const void *disp_cp_xindir,
9770 const void *disp_cp_xassisted)
sewardj2019a972011-03-07 16:04:07 +00009771{
9772 UChar *end;
9773
florianc4aa7ed2012-12-22 15:01:04 +00009774 /* Used to be 48 bytes. Make sure it stays low */
9775 vassert(sizeof(s390_insn) == 32);
9776
sewardj2019a972011-03-07 16:04:07 +00009777 switch (insn->tag) {
9778 case S390_INSN_LOAD:
9779 end = s390_insn_load_emit(buf, insn);
9780 break;
9781
9782 case S390_INSN_STORE:
9783 end = s390_insn_store_emit(buf, insn);
9784 break;
9785
9786 case S390_INSN_MOVE:
9787 end = s390_insn_move_emit(buf, insn);
9788 break;
9789
floriancec3a8a2013-02-02 00:16:58 +00009790 case S390_INSN_MEMCPY:
9791 end = s390_insn_memcpy_emit(buf, insn);
9792 break;
9793
sewardj2019a972011-03-07 16:04:07 +00009794 case S390_INSN_COND_MOVE:
9795 end = s390_insn_cond_move_emit(buf, insn);
9796 break;
9797
9798 case S390_INSN_LOAD_IMMEDIATE:
9799 end = s390_insn_load_immediate_emit(buf, insn);
9800 break;
9801
9802 case S390_INSN_ALU:
9803 end = s390_insn_alu_emit(buf, insn);
9804 break;
9805
florianc4aa7ed2012-12-22 15:01:04 +00009806 case S390_INSN_SMUL:
9807 case S390_INSN_UMUL:
sewardj2019a972011-03-07 16:04:07 +00009808 end = s390_insn_mul_emit(buf, insn);
9809 break;
9810
florianc4aa7ed2012-12-22 15:01:04 +00009811 case S390_INSN_SDIV:
9812 case S390_INSN_UDIV:
sewardj2019a972011-03-07 16:04:07 +00009813 end = s390_insn_div_emit(buf, insn);
9814 break;
9815
9816 case S390_INSN_DIVS:
9817 end = s390_insn_divs_emit(buf, insn);
9818 break;
9819
sewardj611b06e2011-03-24 08:57:29 +00009820 case S390_INSN_CLZ:
9821 end = s390_insn_clz_emit(buf, insn);
sewardj2019a972011-03-07 16:04:07 +00009822 break;
9823
9824 case S390_INSN_UNOP:
9825 end = s390_insn_unop_emit(buf, insn);
9826 break;
9827
9828 case S390_INSN_TEST:
9829 end = s390_insn_test_emit(buf, insn);
9830 break;
9831
9832 case S390_INSN_CC2BOOL:
9833 end = s390_insn_cc2bool_emit(buf, insn);
9834 break;
9835
9836 case S390_INSN_CAS:
9837 end = s390_insn_cas_emit(buf, insn);
9838 break;
9839
florian448cbba2012-06-06 02:26:01 +00009840 case S390_INSN_CDAS:
9841 end = s390_insn_cdas_emit(buf, insn);
9842 break;
9843
sewardj2019a972011-03-07 16:04:07 +00009844 case S390_INSN_COMPARE:
9845 end = s390_insn_compare_emit(buf, insn);
9846 break;
9847
sewardj2019a972011-03-07 16:04:07 +00009848 case S390_INSN_HELPER_CALL:
9849 end = s390_insn_helper_call_emit(buf, insn);
sewardjcfe046e2013-01-17 14:23:53 +00009850 if (end == buf) goto fail;
sewardj2019a972011-03-07 16:04:07 +00009851 break;
9852
9853 case S390_INSN_BFP_TRIOP:
9854 end = s390_insn_bfp_triop_emit(buf, insn);
9855 break;
9856
9857 case S390_INSN_BFP_BINOP:
9858 end = s390_insn_bfp_binop_emit(buf, insn);
9859 break;
9860
9861 case S390_INSN_BFP_UNOP:
9862 end = s390_insn_bfp_unop_emit(buf, insn);
9863 break;
9864
9865 case S390_INSN_BFP_COMPARE:
9866 end = s390_insn_bfp_compare_emit(buf, insn);
9867 break;
9868
florian9fcff4c2012-09-10 03:09:04 +00009869 case S390_INSN_BFP_CONVERT:
9870 end = s390_insn_bfp_convert_emit(buf, insn);
9871 break;
9872
florian12390202012-11-10 22:34:14 +00009873 case S390_INSN_DFP_BINOP:
9874 end = s390_insn_dfp_binop_emit(buf, insn);
9875 break;
9876
floriance9e3db2012-12-27 20:14:03 +00009877 case S390_INSN_DFP_UNOP:
9878 end = s390_insn_dfp_unop_emit(buf, insn);
9879 break;
9880
florian1b901d42013-01-01 22:19:24 +00009881 case S390_INSN_DFP_INTOP:
9882 end = s390_insn_dfp_intop_emit(buf, insn);
9883 break;
9884
floriane38f6412012-12-21 17:32:12 +00009885 case S390_INSN_DFP_COMPARE:
9886 end = s390_insn_dfp_compare_emit(buf, insn);
9887 break;
9888
9889 case S390_INSN_DFP_CONVERT:
9890 end = s390_insn_dfp_convert_emit(buf, insn);
9891 break;
9892
florian5c539732013-02-14 14:27:12 +00009893 case S390_INSN_DFP_REROUND:
9894 end = s390_insn_dfp_reround_emit(buf, insn);
9895 break;
9896
florian78d5ef72013-05-11 15:02:58 +00009897 case S390_INSN_FP_CONVERT:
9898 end = s390_insn_fp_convert_emit(buf, insn);
9899 break;
9900
sewardja52e37e2011-04-28 18:48:06 +00009901 case S390_INSN_MFENCE:
9902 end = s390_insn_mfence_emit(buf, insn);
9903 break;
9904
florianb93348d2012-12-27 00:59:43 +00009905 case S390_INSN_MIMM:
9906 end = s390_insn_mimm_emit(buf, insn);
florianad43b3a2012-02-20 15:01:14 +00009907 break;
9908
florianf85fe3e2012-12-22 02:28:25 +00009909 case S390_INSN_MADD:
9910 end = s390_insn_madd_emit(buf, insn);
florianad43b3a2012-02-20 15:01:14 +00009911 break;
9912
florian125e20d2012-10-07 15:42:37 +00009913 case S390_INSN_SET_FPC_BFPRM:
9914 end = s390_insn_set_fpc_bfprm_emit(buf, insn);
florian2c74d242012-09-12 19:38:42 +00009915 break;
9916
florianc8e4f562012-10-27 16:19:31 +00009917 case S390_INSN_SET_FPC_DFPRM:
9918 end = s390_insn_set_fpc_dfprm_emit(buf, insn);
9919 break;
9920
florian8844a632012-04-13 04:04:06 +00009921 case S390_INSN_PROFINC:
9922 end = s390_insn_profinc_emit(buf, insn);
9923 /* Tell the caller .. */
9924 vassert(*is_profinc == False);
9925 *is_profinc = True;
9926 break;
9927
9928 case S390_INSN_EVCHECK:
sewardj9b769162014-07-24 12:42:03 +00009929 end = s390_insn_evcheck_emit(buf, insn, endness_host);
florian8844a632012-04-13 04:04:06 +00009930 break;
9931
9932 case S390_INSN_XDIRECT:
9933 end = s390_insn_xdirect_emit(buf, insn, disp_cp_chain_me_to_slowEP,
9934 disp_cp_chain_me_to_fastEP);
9935 break;
9936
9937 case S390_INSN_XINDIR:
9938 end = s390_insn_xindir_emit(buf, insn, disp_cp_xindir);
9939 break;
9940
9941 case S390_INSN_XASSISTED:
9942 end = s390_insn_xassisted_emit(buf, insn, disp_cp_xassisted);
9943 break;
9944
sewardjcfe046e2013-01-17 14:23:53 +00009945 fail:
sewardj2019a972011-03-07 16:04:07 +00009946 default:
florian616458b2012-03-25 16:17:18 +00009947 vpanic("emit_S390Instr");
sewardj2019a972011-03-07 16:04:07 +00009948 }
9949
9950 vassert(end - buf <= nbuf);
9951
9952 return end - buf;
9953}
9954
9955
florian8844a632012-04-13 04:04:06 +00009956/* Return the number of bytes emitted for an S390_INSN_EVCHECK.
9957 See s390_insn_evcheck_emit */
9958Int
sewardj9b769162014-07-24 12:42:03 +00009959evCheckSzB_S390(VexEndness endness_host)
florian8844a632012-04-13 04:04:06 +00009960{
florian0e047d62012-04-21 16:06:04 +00009961 return s390_host_has_gie ? 18 : 24;
florian8844a632012-04-13 04:04:06 +00009962}
9963
9964
9965/* Patch the counter address into CODE_TO_PATCH as previously
9966 generated by s390_insn_profinc_emit. */
9967VexInvalRange
sewardj9b769162014-07-24 12:42:03 +00009968patchProfInc_S390(VexEndness endness_host,
florian7d6f81d2014-09-22 21:43:37 +00009969 void *code_to_patch, const ULong *location_of_counter)
florian8844a632012-04-13 04:04:06 +00009970{
9971 vassert(sizeof(ULong *) == 8);
9972
9973 s390_tchain_verify_load64(code_to_patch, S390_REGNO_TCHAIN_SCRATCH, 0);
9974
florian5ea257b2012-09-29 17:05:46 +00009975 UChar *p = s390_tchain_patch_load64(code_to_patch,
9976 Ptr_to_ULong(location_of_counter));
florian8844a632012-04-13 04:04:06 +00009977
florian5ea257b2012-09-29 17:05:46 +00009978 UInt len = p - (UChar *)code_to_patch;
9979 VexInvalRange vir = { (HWord)code_to_patch, len };
florian8844a632012-04-13 04:04:06 +00009980 return vir;
9981}
9982
9983
9984/* NB: what goes on here has to be very closely coordinated with the
9985 s390_insn_xdirect_emit code above. */
9986VexInvalRange
sewardj9b769162014-07-24 12:42:03 +00009987chainXDirect_S390(VexEndness endness_host,
9988 void *place_to_chain,
florian7d6f81d2014-09-22 21:43:37 +00009989 const void *disp_cp_chain_me_EXPECTED,
9990 const void *place_to_jump_to)
florian8844a632012-04-13 04:04:06 +00009991{
sewardj9b769162014-07-24 12:42:03 +00009992 vassert(endness_host == VexEndnessBE);
9993
florianebaf8d92012-04-22 17:38:46 +00009994 /* What we're expecting to see @ PLACE_TO_CHAIN is:
florian8844a632012-04-13 04:04:06 +00009995
florianebaf8d92012-04-22 17:38:46 +00009996 load tchain_scratch, #disp_cp_chain_me_EXPECTED
9997 goto *tchain_scratch
florian8844a632012-04-13 04:04:06 +00009998 */
9999 const UChar *next;
10000 next = s390_tchain_verify_load64(place_to_chain, S390_REGNO_TCHAIN_SCRATCH,
10001 Ptr_to_ULong(disp_cp_chain_me_EXPECTED));
florianebaf8d92012-04-22 17:38:46 +000010002 vassert(s390_insn_is_BR(next, S390_REGNO_TCHAIN_SCRATCH));
florian8844a632012-04-13 04:04:06 +000010003
10004 /* And what we want to change it to is either:
10005 (general case):
10006
florianebaf8d92012-04-22 17:38:46 +000010007 load tchain_scratch, #place_to_jump_to
10008 goto *tchain_scratch
florian8844a632012-04-13 04:04:06 +000010009
10010 ---OR---
10011
10012 in the case where the displacement is small enough
10013
10014 BRCL delta where delta is in half-words
10015 invalid opcodes
10016
10017 In both cases the replacement has the same length as the original.
10018 To remain sane & verifiable,
10019 (1) limit the displacement for the short form to
10020 (say) +/- one billion, so as to avoid wraparound
10021 off-by-ones
10022 (2) even if the short form is applicable, once every (say)
10023 1024 times use the long form anyway, so as to maintain
10024 verifiability
10025 */
10026
10027 /* This is the delta we need to put into a BRCL insn. Note, that the
10028 offset in BRCL is in half-words. Hence division by 2. */
florian7d6f81d2014-09-22 21:43:37 +000010029 Long delta =
10030 (Long)((const UChar *)place_to_jump_to - (const UChar *)place_to_chain) / 2;
florian8844a632012-04-13 04:04:06 +000010031 Bool shortOK = delta >= -1000*1000*1000 && delta < 1000*1000*1000;
10032
10033 static UInt shortCTR = 0; /* DO NOT MAKE NON-STATIC */
10034 if (shortOK) {
10035 shortCTR++; // thread safety bleh
10036 if (0 == (shortCTR & 0x3FF)) {
10037 shortOK = False;
10038 if (0)
10039 vex_printf("QQQ chainXDirect_S390: shortCTR = %u, "
10040 "using long jmp\n", shortCTR);
10041 }
10042 }
10043
10044 /* And make the modifications. */
10045 UChar *p = (UChar *)place_to_chain;
10046 if (shortOK) {
10047 p = s390_emit_BRCL(p, S390_CC_ALWAYS, delta); /* 6 bytes */
10048
florian48cb9612012-04-20 02:50:28 +000010049 /* Make sure that BRCL fits into the patchable part of an xdirect
florian1c857042012-04-15 04:11:07 +000010050 code sequence */
florian48cb9612012-04-20 02:50:28 +000010051 vassert(6 <= s390_xdirect_patchable_len());
florian1c857042012-04-15 04:11:07 +000010052
florian8844a632012-04-13 04:04:06 +000010053 /* Fill remaining bytes with 0x00 (invalid opcode) */
10054 Int i;
10055 for (i = 0; i < s390_xdirect_patchable_len() - 6; ++i)
10056 p[i] = 0x00;
10057 } else {
florian1c857042012-04-15 04:11:07 +000010058 /*
florianebaf8d92012-04-22 17:38:46 +000010059 load tchain_scratch, #place_to_jump_to
10060 goto *tchain_scratch
florian1c857042012-04-15 04:11:07 +000010061 */
10062 ULong addr = Ptr_to_ULong(place_to_jump_to);
10063 p = s390_tchain_load64(p, S390_REGNO_TCHAIN_SCRATCH, addr);
florianebaf8d92012-04-22 17:38:46 +000010064 /* There is not need to emit a BCR here, as it is already there. */
florian8844a632012-04-13 04:04:06 +000010065 }
10066
florian5ea257b2012-09-29 17:05:46 +000010067 UInt len = p - (UChar *)place_to_chain;
10068 VexInvalRange vir = { (HWord)place_to_chain, len };
florian8844a632012-04-13 04:04:06 +000010069 return vir;
10070}
10071
10072
10073/* NB: what goes on here has to be very closely coordinated with the
10074 s390_insn_xdirect_emit code above. */
10075VexInvalRange
sewardj9b769162014-07-24 12:42:03 +000010076unchainXDirect_S390(VexEndness endness_host,
10077 void *place_to_unchain,
florian7d6f81d2014-09-22 21:43:37 +000010078 const void *place_to_jump_to_EXPECTED,
10079 const void *disp_cp_chain_me)
florian8844a632012-04-13 04:04:06 +000010080{
sewardj9b769162014-07-24 12:42:03 +000010081 vassert(endness_host == VexEndnessBE);
10082
florian8844a632012-04-13 04:04:06 +000010083 /* What we're expecting to see @ PLACE_TO_UNCHAIN:
10084
florianebaf8d92012-04-22 17:38:46 +000010085 load tchain_scratch, #place_to_jump_to_EXPECTED
10086 goto *tchain_scratch
florian8844a632012-04-13 04:04:06 +000010087
10088 ---OR---
10089 in the case where the displacement falls within 32 bits
10090
10091 BRCL delta
10092 invalid opcodes
10093 */
10094 UChar *p = place_to_unchain;
florian1c857042012-04-15 04:11:07 +000010095
florianebaf8d92012-04-22 17:38:46 +000010096 Bool uses_short_form = False;
10097
florian1c857042012-04-15 04:11:07 +000010098 if (s390_insn_is_BRCL(p, S390_CC_ALWAYS)) {
florian8844a632012-04-13 04:04:06 +000010099 /* Looks like the short form */
10100 Int num_hw = *(Int *)&p[2];
10101 Int delta = 2 *num_hw;
10102
10103 vassert(p + delta == place_to_jump_to_EXPECTED);
10104
florian8844a632012-04-13 04:04:06 +000010105 Int i;
10106 for (i = 0; i < s390_xdirect_patchable_len() - 6; ++i)
florian1c857042012-04-15 04:11:07 +000010107 vassert(p[6+i] == 0x00);
florianebaf8d92012-04-22 17:38:46 +000010108 uses_short_form = True;
florian8844a632012-04-13 04:04:06 +000010109 } else {
10110 /* Should be the long form */
10111 const UChar *next;
10112
10113 next = s390_tchain_verify_load64(p, S390_REGNO_TCHAIN_SCRATCH,
10114 Ptr_to_ULong(place_to_jump_to_EXPECTED));
10115 /* Check for BR *tchain_scratch */
florian1c857042012-04-15 04:11:07 +000010116 vassert(s390_insn_is_BR(next, S390_REGNO_TCHAIN_SCRATCH));
florian8844a632012-04-13 04:04:06 +000010117 }
10118
10119 /* And what we want to change it to is:
10120
10121 load tchain_scratch, #disp_cp_chain_me
florianebaf8d92012-04-22 17:38:46 +000010122 goto *tchain_scratch
florian8844a632012-04-13 04:04:06 +000010123 */
florianebaf8d92012-04-22 17:38:46 +000010124
10125 /* Get the address of the beginning of the load64 code sequence into %r1.
10126 Do not change the register! This is part of the protocol with the
10127 dispatcher.
10128 Note: the incoming argument PLACE_TO_CHAIN points to the beginning of the
10129 load64 insn sequence. That sequence is prefixed with a BASR to get its
10130 address (see s390_insn_xdirect_emit). */
10131 p = s390_emit_BASR(p - S390_BASR_LEN, 1, R0);
10132
florian8844a632012-04-13 04:04:06 +000010133 ULong addr = Ptr_to_ULong(disp_cp_chain_me);
10134 p = s390_tchain_load64(p, S390_REGNO_TCHAIN_SCRATCH, addr);
florianebaf8d92012-04-22 17:38:46 +000010135
10136 /* Emit the BCR in case the short form was used. In case of the long
10137 form, the BCR is already there. */
10138 if (uses_short_form)
10139 s390_emit_BCR(p, S390_CC_ALWAYS, S390_REGNO_TCHAIN_SCRATCH);
florian8844a632012-04-13 04:04:06 +000010140
florian5ea257b2012-09-29 17:05:46 +000010141 UInt len = p - (UChar *)place_to_unchain;
10142 VexInvalRange vir = { (HWord)place_to_unchain, len };
florian8844a632012-04-13 04:04:06 +000010143 return vir;
10144}
10145
sewardj2019a972011-03-07 16:04:07 +000010146/*---------------------------------------------------------------*/
10147/*--- end host_s390_defs.c ---*/
10148/*---------------------------------------------------------------*/